pax_global_header00006660000000000000000000000064146276601100014515gustar00rootroot0000000000000052 comment=398be02d23a5e0bfc07e841d0b953d8fb22a07f6 mongodb-mongo-python-driver-509e9b7/000077500000000000000000000000001462766011000174355ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/.evergreen/000077500000000000000000000000001462766011000214755ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/.evergreen/build-mac.sh000077500000000000000000000011271462766011000236720ustar00rootroot00000000000000#!/bin/bash -ex # Get access to testinstall. . .evergreen/utils.sh # Create temp directory for validated files. rm -rf validdist mkdir -p validdist mv dist/* validdist || true VERSION=${VERSION:-3.10} PYTHON=/Library/Frameworks/Python.framework/Versions/$VERSION/bin/python3 rm -rf build createvirtualenv $PYTHON releasevenv python -m pip install build python -m build --wheel . deactivate || true rm -rf releasevenv # Test that each wheel is installable. for release in dist/*; do testinstall $PYTHON $release mv $release validdist/ done mv validdist/* dist rm -rf validdist ls dist mongodb-mongo-python-driver-509e9b7/.evergreen/build-manylinux-internal.sh000077500000000000000000000020201462766011000267610ustar00rootroot00000000000000#!/bin/bash -ex cd /src # Get access to testinstall. . .evergreen/utils.sh # Create temp directory for validated files. rm -rf validdist mkdir -p validdist mv dist/* validdist || true # Compile wheels for PYTHON in /opt/python/*/bin/python; do if [[ ! $PYTHON =~ (cp37|cp38|cp39|cp310|cp311|cp312) ]]; then continue fi # https://github.com/pypa/manylinux/issues/49 rm -rf build $PYTHON -m pip install build $PYTHON -m build --wheel . rm -rf build # Audit wheels and write manylinux tag for whl in dist/*.whl; do # Skip already built manylinux wheels. if [[ "$whl" != *"manylinux"* ]]; then auditwheel repair $whl -w dist rm $whl fi done # Test that each wheel is installable. # Test without virtualenv because it's not present on manylinux containers. for release in dist/*; do testinstall $PYTHON $release "without-virtualenv" mv $release validdist/ done done mv validdist/* dist rm -rf validdist ls dist mongodb-mongo-python-driver-509e9b7/.evergreen/build-manylinux.sh000077500000000000000000000037761462766011000251720ustar00rootroot00000000000000#!/bin/bash -ex docker version # Set up qemu support using the method used in docker/setup-qemu-action # https://github.com/docker/setup-qemu-action/blob/2b82ce82d56a2a04d2637cd93a637ae1b359c0a7/README.md?plain=1#L46 docker run --rm --privileged tonistiigi/binfmt:latest --install all # manylinux1 2021-05-05-b64d921 and manylinux2014 2021-05-05-1ac6ef3 were # the last releases to generate pip < 20.3 compatible wheels. After that # auditwheel was upgraded to v4 which produces PEP 600 manylinux_x_y wheels # which requires pip >= 20.3. We use the older docker image to support older # pip versions. BUILD_WITH_TAG="$1" if [ -n "$BUILD_WITH_TAG" ]; then images=(quay.io/pypa/manylinux1_x86_64:2021-05-05-b64d921 \ quay.io/pypa/manylinux1_i686:2021-05-05-b64d921 \ quay.io/pypa/manylinux2014_x86_64:2021-05-05-1ac6ef3 \ quay.io/pypa/manylinux2014_i686:2021-05-05-1ac6ef3 \ quay.io/pypa/manylinux2014_aarch64:2021-05-05-1ac6ef3 \ quay.io/pypa/manylinux2014_ppc64le:2021-05-05-1ac6ef3 \ quay.io/pypa/manylinux2014_s390x:2021-05-05-1ac6ef3) else images=(quay.io/pypa/manylinux1_x86_64 \ quay.io/pypa/manylinux1_i686 \ quay.io/pypa/manylinux2014_x86_64 \ quay.io/pypa/manylinux2014_i686 \ quay.io/pypa/manylinux2014_aarch64 \ quay.io/pypa/manylinux2014_ppc64le \ quay.io/pypa/manylinux2014_s390x) fi for image in "${images[@]}"; do docker pull $image docker run --rm -v "`pwd`:/src" $image /src/.evergreen/build-manylinux-internal.sh done ls dist # Check for any unexpected files. unexpected=$(find dist \! \( -iname dist -or \ -iname '*cp37*' -or \ -iname '*cp38*' -or \ -iname '*cp39*' -or \ -iname '*cp310*' -or \ -iname '*cp311*' -or \ -iname '*cp312*' \)) if [ -n "$unexpected" ]; then echo "Unexpected files:" $unexpected exit 1 fi mongodb-mongo-python-driver-509e9b7/.evergreen/build-windows.sh000077500000000000000000000012701462766011000246230ustar00rootroot00000000000000#!/bin/bash -ex # Get access to testinstall. . .evergreen/utils.sh # Create temp directory for validated files. rm -rf validdist mkdir -p validdist mv dist/* validdist || true for VERSION in 37 38 39 310 311 312; do _pythons=("C:/Python/Python${VERSION}/python.exe" \ "C:/Python/32/Python${VERSION}/python.exe") for PYTHON in "${_pythons[@]}"; do rm -rf build $PYTHON -m pip install build $PYTHON -m build --wheel . # Test that each wheel is installable. for release in dist/*; do testinstall $PYTHON $release mv $release validdist/ done done done mv validdist/* dist rm -rf validdist ls dist mongodb-mongo-python-driver-509e9b7/.evergreen/combine-coverage.sh000066400000000000000000000012431462766011000252360ustar00rootroot00000000000000#!/bin/bash # # Coverage combine merges (and removes) all the coverage files and # generates a new .coverage file in the current directory. set -o xtrace # Write all commands first to stderr set -o errexit # Exit the script with error if any of the commands fail . .evergreen/utils.sh if [ -z "$PYTHON_BINARY" ]; then PYTHON_BINARY=$(find_python3) fi createvirtualenv "$PYTHON_BINARY" covenv # coverage 7.3 dropped support for Python 3.7, keep in sync with run-tests.sh # coverage >=5 is needed for relative_files=true. pip install -q "coverage>=5,<7.3" pip list ls -la coverage/ python -m coverage combine coverage/coverage.* python -m coverage html -d htmlcov mongodb-mongo-python-driver-509e9b7/.evergreen/config.yml000066400000000000000000003046561462766011000235030ustar00rootroot00000000000000######################################## # Evergreen Template for MongoDB Drivers ######################################## # When a task that used to pass starts to fail # Go through all versions that may have been skipped to detect # when the task started failing stepback: true # Mark a failure as a system/bootstrap failure (purple box) rather then a task # failure by default. # Actual testing tasks are marked with `type: test` command_type: system # Protect ourselves against rogue test case, or curl gone wild, that runs forever # Good rule of thumb: the averageish length a task takes, times 5 # That roughly accounts for variable system performance for various buildvariants exec_timeout_secs: 3600 # 60 minutes is the longest we'll ever run (primarily # for macos hosts) # What to do when evergreen hits the timeout (`post:` tasks are run automatically) timeout: - command: shell.exec params: script: | ls -la functions: "fetch source": # Executes clone and applies the submitted patch, if any - command: git.get_project params: directory: "src" # Applies the subitted patch, if any # Deprecated. Should be removed. But still needed for certain agents (ZAP) - command: git.apply_patch # Make an evergreen exapanstion file with dynamic values - command: shell.exec params: working_dir: "src" script: | set +x # Get the current unique version of this checkout if [ "${is_patch}" = "true" ]; then CURRENT_VERSION=$(git describe)-patch-${version_id} else CURRENT_VERSION=latest fi export DRIVERS_TOOLS="$(dirname $(pwd))/drivers-tools" export PROJECT_DIRECTORY="$(pwd)" # Python has cygwin path problems on Windows. Detect prospective mongo-orchestration home directory if [ "Windows_NT" = "$OS" ]; then # Magic variable in cygwin export DRIVERS_TOOLS=$(cygpath -m $DRIVERS_TOOLS) export PROJECT_DIRECTORY=$(cygpath -m $PROJECT_DIRECTORY) fi export MONGO_ORCHESTRATION_HOME="$DRIVERS_TOOLS/.evergreen/orchestration" export MONGODB_BINARIES="$DRIVERS_TOOLS/mongodb/bin" export UPLOAD_BUCKET="${project}" cat < expansion.yml CURRENT_VERSION: "$CURRENT_VERSION" DRIVERS_TOOLS: "$DRIVERS_TOOLS" MONGO_ORCHESTRATION_HOME: "$MONGO_ORCHESTRATION_HOME" MONGODB_BINARIES: "$MONGODB_BINARIES" UPLOAD_BUCKET: "$UPLOAD_BUCKET" PROJECT_DIRECTORY: "$PROJECT_DIRECTORY" PREPARE_SHELL: | set -o errexit export SKIP_LEGACY_SHELL=1 export DRIVERS_TOOLS="$DRIVERS_TOOLS" export MONGO_ORCHESTRATION_HOME="$MONGO_ORCHESTRATION_HOME" export MONGODB_BINARIES="$MONGODB_BINARIES" export UPLOAD_BUCKET="$UPLOAD_BUCKET" export PROJECT_DIRECTORY="$PROJECT_DIRECTORY" export TMPDIR="$MONGO_ORCHESTRATION_HOME/db" export PATH="$MONGODB_BINARIES:$PATH" export PROJECT="${project}" export PIP_QUIET=1 EOT # Load the expansion file to make an evergreen variable with the current unique version - command: expansions.update params: file: src/expansion.yml "prepare resources": - command: shell.exec params: script: | ${PREPARE_SHELL} set -o xtrace rm -rf $DRIVERS_TOOLS if [ "${project}" = "drivers-tools" ]; then # If this was a patch build, doing a fresh clone would not actually test the patch cp -R ${PROJECT_DIRECTORY}/ $DRIVERS_TOOLS else git clone https://github.com/mongodb-labs/drivers-evergreen-tools.git $DRIVERS_TOOLS fi echo "{ \"releases\": { \"default\": \"$MONGODB_BINARIES\" }}" > $MONGO_ORCHESTRATION_HOME/orchestration.config "upload coverage" : - command: s3.put params: aws_key: ${aws_key} aws_secret: ${aws_secret} local_file: src/.coverage optional: true # Upload the coverage report for all tasks in a single build to the same directory. remote_file: ${UPLOAD_BUCKET}/coverage/${revision}/${version_id}/coverage/coverage.${build_variant}.${task_name} bucket: mciuploads permissions: public-read content_type: text/html display_name: "Raw Coverage Report" "download and merge coverage" : - command: shell.exec params: silent: true working_dir: "src" script: | export AWS_ACCESS_KEY_ID=${aws_key} export AWS_SECRET_ACCESS_KEY=${aws_secret} # Download all the task coverage files. aws s3 cp --recursive s3://mciuploads/${UPLOAD_BUCKET}/coverage/${revision}/${version_id}/coverage/ coverage/ - command: shell.exec params: working_dir: "src" script: | ${PREPARE_SHELL} bash .evergreen/combine-coverage.sh # Upload the resulting html coverage report. - command: shell.exec params: silent: true working_dir: "src" script: | export AWS_ACCESS_KEY_ID=${aws_key} export AWS_SECRET_ACCESS_KEY=${aws_secret} aws s3 cp htmlcov/ s3://mciuploads/${UPLOAD_BUCKET}/coverage/${revision}/${version_id}/htmlcov/ --recursive --acl public-read --region us-east-1 # Attach the index.html with s3.put so it shows up in the Evergreen UI. - command: s3.put params: aws_key: ${aws_key} aws_secret: ${aws_secret} local_file: src/htmlcov/index.html remote_file: ${UPLOAD_BUCKET}/coverage/${revision}/${version_id}/htmlcov/index.html bucket: mciuploads permissions: public-read content_type: text/html display_name: "Coverage Report HTML" "upload mo artifacts": - command: shell.exec params: script: | ${PREPARE_SHELL} set -o xtrace mkdir out_dir find $MONGO_ORCHESTRATION_HOME -name \*.log -exec sh -c 'x="{}"; mv $x $PWD/out_dir/$(basename $(dirname $x))_$(basename $x)' \; tar zcvf mongodb-logs.tar.gz -C out_dir/ . rm -rf out_dir - command: archive.targz_pack params: target: "mongo-coredumps.tgz" source_dir: "./" include: - "./**.core" - "./**.mdmp" # Windows: minidumps - command: s3.put params: aws_key: ${aws_key} aws_secret: ${aws_secret} local_file: mongo-coredumps.tgz remote_file: ${UPLOAD_BUCKET}/${build_variant}/${revision}/${version_id}/${build_id}/coredumps/${task_id}-${execution}-mongodb-coredumps.tar.gz bucket: mciuploads permissions: public-read content_type: ${content_type|application/gzip} display_name: Core Dumps - Execution optional: true - command: s3.put params: aws_key: ${aws_key} aws_secret: ${aws_secret} local_file: mongodb-logs.tar.gz remote_file: ${UPLOAD_BUCKET}/${build_variant}/${revision}/${version_id}/${build_id}/logs/${task_id}-${execution}-mongodb-logs.tar.gz bucket: mciuploads permissions: public-read content_type: ${content_type|application/x-gzip} display_name: "mongodb-logs.tar.gz" - command: s3.put params: aws_key: ${aws_key} aws_secret: ${aws_secret} local_file: drivers-tools/.evergreen/orchestration/server.log remote_file: ${UPLOAD_BUCKET}/${build_variant}/${revision}/${version_id}/${build_id}/logs/${task_id}-${execution}-orchestration.log bucket: mciuploads permissions: public-read content_type: ${content_type|text/plain} display_name: "orchestration.log" "upload working dir": - command: archive.targz_pack params: target: "working-dir.tar.gz" source_dir: ${PROJECT_DIRECTORY}/ include: - "./**" - command: s3.put params: aws_key: ${aws_key} aws_secret: ${aws_secret} local_file: working-dir.tar.gz remote_file: ${UPLOAD_BUCKET}/${build_variant}/${revision}/${version_id}/${build_id}/artifacts/${task_id}-${execution}-working-dir.tar.gz bucket: mciuploads permissions: public-read content_type: ${content_type|application/x-gzip} display_name: "working-dir.tar.gz" - command: archive.targz_pack params: target: "drivers-dir.tar.gz" source_dir: ${DRIVERS_TOOLS} include: - "./**" exclude_files: # Windows cannot read the mongod *.lock files because they are locked. - "*.lock" - command: s3.put params: aws_key: ${aws_key} aws_secret: ${aws_secret} local_file: drivers-dir.tar.gz remote_file: ${UPLOAD_BUCKET}/${build_variant}/${revision}/${version_id}/${build_id}/artifacts/${task_id}-${execution}-drivers-dir.tar.gz bucket: mciuploads permissions: public-read content_type: ${content_type|application/x-gzip} display_name: "drivers-dir.tar.gz" "upload test results": - command: attach.results params: file_location: "${DRIVERS_TOOLS}/results.json" - command: attach.xunit_results params: file: "src/xunit-results/TEST-*.xml" "bootstrap mongo-orchestration": - command: shell.exec params: script: | ${PREPARE_SHELL} set -o xtrace # Enable core dumps if enabled on the machine # Copied from https://github.com/mongodb/mongo/blob/master/etc/evergreen.yml if [ -f /proc/self/coredump_filter ]; then # Set the shell process (and its children processes) to dump ELF headers (bit 4), # anonymous shared mappings (bit 1), and anonymous private mappings (bit 0). echo 0x13 > /proc/self/coredump_filter if [ -f /sbin/sysctl ]; then # Check that the core pattern is set explicitly on our distro image instead # of being the OS's default value. This ensures that coredump names are consistent # across distros and can be picked up by Evergreen. core_pattern=$(/sbin/sysctl -n "kernel.core_pattern") if [ "$core_pattern" = "dump_%e.%p.core" ]; then echo "Enabling coredumps" ulimit -c unlimited fi fi fi if [ $(uname -s) = "Darwin" ]; then core_pattern_mac=$(/usr/sbin/sysctl -n "kern.corefile") if [ "$core_pattern_mac" = "dump_%N.%P.core" ]; then echo "Enabling coredumps" ulimit -c unlimited fi fi if [ -n "${skip_crypt_shared}" ]; then export SKIP_CRYPT_SHARED=1 fi MONGODB_VERSION=${VERSION} \ TOPOLOGY=${TOPOLOGY} \ AUTH=${AUTH} \ SSL=${SSL} \ STORAGE_ENGINE=${STORAGE_ENGINE} \ DISABLE_TEST_COMMANDS=${DISABLE_TEST_COMMANDS} \ ORCHESTRATION_FILE=${ORCHESTRATION_FILE} \ REQUIRE_API_VERSION=${REQUIRE_API_VERSION} \ LOAD_BALANCER=${LOAD_BALANCER} \ bash ${DRIVERS_TOOLS}/.evergreen/run-orchestration.sh # run-orchestration generates expansion file with the MONGODB_URI for the cluster - command: expansions.update params: file: mo-expansion.yml - command: expansions.update params: updates: - key: MONGODB_STARTED value: "1" "bootstrap data lake": - command: shell.exec type: setup params: script: | ${PREPARE_SHELL} bash ${DRIVERS_TOOLS}/.evergreen/atlas_data_lake/pull-mongohouse-image.sh - command: shell.exec type: setup params: script: | ${PREPARE_SHELL} bash ${DRIVERS_TOOLS}/.evergreen/atlas_data_lake/run-mongohouse-image.sh sleep 1 docker ps "stop mongo-orchestration": - command: shell.exec params: script: | ${PREPARE_SHELL} set -o xtrace bash ${DRIVERS_TOOLS}/.evergreen/stop-orchestration.sh "run mod_wsgi tests": - command: shell.exec type: test params: working_dir: "src" script: | ${PREPARE_SHELL} set -o xtrace PYTHON_BINARY=${PYTHON_BINARY} MOD_WSGI_VERSION=${MOD_WSGI_VERSION} \ MOD_WSGI_EMBEDDED=${MOD_WSGI_EMBEDDED} PROJECT_DIRECTORY=${PROJECT_DIRECTORY} \ bash ${PROJECT_DIRECTORY}/.evergreen/run-mod-wsgi-tests.sh "run mockupdb tests": - command: shell.exec type: test params: working_dir: "src" script: | ${PREPARE_SHELL} set -o xtrace export PYTHON_BINARY=${PYTHON_BINARY} bash ${PROJECT_DIRECTORY}/.evergreen/tox.sh -m test-mockupdb "run doctests": - command: shell.exec type: test params: working_dir: "src" script: | ${PREPARE_SHELL} set -o xtrace PYTHON_BINARY=${PYTHON_BINARY} bash ${PROJECT_DIRECTORY}/.evergreen/tox.sh -m doc-test "run tests": - command: shell.exec params: working_dir: "src" shell: bash include_expansions_in_env: ["AWS_ACCESS_KEY_ID", "AWS_SECRET_ACCESS_KEY", "AWS_SESSION_TOKEN"] script: | ${PREPARE_SHELL} if [ -n "${test_encryption}" ]; then . .evergreen/tox.sh -m setup-encryption fi - command: shell.exec type: test params: working_dir: "src" shell: bash include_expansions_in_env: ["DRIVERS_ATLAS_LAMBDA_USER", "DRIVERS_ATLAS_LAMBDA_PASSWORD"] script: | # Disable xtrace set +x ${PREPARE_SHELL} if [ -n "${MONGODB_STARTED}" ]; then export PYMONGO_MUST_CONNECT=true fi if [ -n "${DISABLE_TEST_COMMANDS}" ]; then export PYMONGO_DISABLE_TEST_COMMANDS=1 fi if [ -n "${test_encryption}" ]; then # Disable xtrace (just in case it was accidentally set). set +x export TEST_ENCRYPTION=1 if [ -n "${test_encryption_pyopenssl}" ]; then export TEST_ENCRYPTION_PYOPENSSL=1 fi fi if [ -n "${test_crypt_shared}" ]; then export TEST_CRYPT_SHARED=1 export CRYPT_SHARED_LIB_PATH=${CRYPT_SHARED_LIB_PATH} fi if [ -n "${test_pyopenssl}" ]; then export TEST_PYOPENSSL=1 fi if [ -n "${SETDEFAULTENCODING}" ]; then export SETDEFAULTENCODING="${SETDEFAULTENCODING}" fi if [ -n "${test_loadbalancer}" ]; then export TEST_LOADBALANCER=1 export SINGLE_MONGOS_LB_URI="${SINGLE_MONGOS_LB_URI}" export MULTI_MONGOS_LB_URI="${MULTI_MONGOS_LB_URI}" fi if [ -n "${test_serverless}" ]; then export TEST_SERVERLESS=1 fi if [ -n "${IS_SERVERLESS_PROXY}" ]; then export IS_SERVERLESS_PROXY=1 fi if [ -n "${TEST_INDEX_MANAGEMENT}" ]; then export TEST_INDEX_MANAGEMENT=1 fi GREEN_FRAMEWORK=${GREEN_FRAMEWORK} \ PYTHON_BINARY=${PYTHON_BINARY} \ NO_EXT=${NO_EXT} \ COVERAGE=${COVERAGE} \ COMPRESSORS=${COMPRESSORS} \ AUTH=${AUTH} \ SSL=${SSL} \ TEST_DATA_LAKE=${TEST_DATA_LAKE} \ MONGODB_API_VERSION=${MONGODB_API_VERSION} \ bash ${PROJECT_DIRECTORY}/.evergreen/tox.sh -m test-eg "run enterprise auth tests": - command: shell.exec type: test params: working_dir: "src" include_expansions_in_env: ["DRIVERS_TOOLS", "AWS_ACCESS_KEY_ID", "AWS_SECRET_ACCESS_KEY", "AWS_SESSION_TOKEN"] script: | # Disable xtrace for security reasons (just in case it was accidentally set). set +x bash ${DRIVERS_TOOLS}/.evergreen/auth_aws/setup_secrets.sh drivers/enterprise_auth PROJECT_DIRECTORY="${PROJECT_DIRECTORY}" \ PYTHON_BINARY="${PYTHON_BINARY}" \ TEST_ENTERPRISE_AUTH=1 \ AUTH=auth \ bash ${PROJECT_DIRECTORY}/.evergreen/tox.sh -m test-eg "run atlas tests": - command: shell.exec type: test params: include_expansions_in_env: ["DRIVERS_TOOLS", "AWS_ACCESS_KEY_ID", "AWS_SECRET_ACCESS_KEY", "AWS_SESSION_TOKEN"] working_dir: "src" script: | # Disable xtrace for security reasons (just in case it was accidentally set). set +x set -o errexit bash ${DRIVERS_TOOLS}/.evergreen/auth_aws/setup_secrets.sh drivers/atlas_connect PROJECT_DIRECTORY="${PROJECT_DIRECTORY}" \ PYTHON_BINARY="${PYTHON_BINARY}" \ TEST_ATLAS=1 \ bash ${PROJECT_DIRECTORY}/.evergreen/tox.sh -m test-eg "get aws auth secrets": - command: subprocess.exec type: test params: include_expansions_in_env: ["AWS_ACCESS_KEY_ID", "AWS_SECRET_ACCESS_KEY", "AWS_SESSION_TOKEN"] binary: bash args: - ${DRIVERS_TOOLS}/.evergreen/auth_aws/setup-secrets.sh "run aws auth test with regular aws credentials": - command: shell.exec type: test params: shell: "bash" working_dir: "src" script: | ${PREPARE_SHELL} .evergreen/run-mongodb-aws-test.sh regular "run aws auth test with assume role credentials": - command: shell.exec type: test params: shell: "bash" working_dir: "src" script: | ${PREPARE_SHELL} .evergreen/run-mongodb-aws-test.sh assume-role "run aws auth test with aws EC2 credentials": - command: shell.exec type: test params: working_dir: "src" shell: "bash" script: | if [ "${skip_EC2_auth_test}" = "true" ]; then echo "This platform does not support the EC2 auth test, skipping..." exit 0 fi ${PREPARE_SHELL} .evergreen/run-mongodb-aws-test.sh ec2 "run aws auth test with aws web identity credentials": - command: shell.exec type: test params: working_dir: "src" shell: "bash" script: | if [ "${skip_EC2_auth_test}" = "true" ]; then echo "This platform does not support the web identity auth test, skipping..." exit 0 fi ${PREPARE_SHELL} # Test with and without AWS_ROLE_SESSION_NAME set. .evergreen/run-mongodb-aws-test.sh web-identity AWS_ROLE_SESSION_NAME="test" \ .evergreen/run-mongodb-aws-test.sh web-identity "run oidc auth test with test credentials": - command: subprocess.exec type: test params: working_dir: "src" binary: bash include_expansions_in_env: ["DRIVERS_TOOLS", "AWS_ACCESS_KEY_ID", "AWS_SECRET_ACCESS_KEY", "AWS_SESSION_TOKEN"] args: - .evergreen/run-mongodb-oidc-test.sh "run aws auth test with aws credentials as environment variables": - command: shell.exec type: test params: working_dir: "src" shell: bash script: | ${PREPARE_SHELL} .evergreen/run-mongodb-aws-test.sh env-creds "run aws auth test with aws credentials and session token as environment variables": - command: shell.exec type: test params: working_dir: "src" shell: bash script: | ${PREPARE_SHELL} .evergreen/run-mongodb-aws-test.sh session-creds "run aws ECS auth test": - command: shell.exec type: test params: shell: "bash" working_dir: "src" script: | if [ "${skip_ECS_auth_test}" = "true" ]; then echo "This platform does not support the ECS auth test, skipping..." exit 0 fi ${PREPARE_SHELL} set -ex cd ${DRIVERS_TOOLS}/.evergreen/auth_aws . ./activate-authawsvenv.sh . aws_setup.sh ecs export MONGODB_BINARIES="${MONGODB_BINARIES}"; export PROJECT_DIRECTORY="${PROJECT_DIRECTORY}"; python aws_tester.py ecs cd - "cleanup": - command: shell.exec params: working_dir: "src" script: | ${PREPARE_SHELL} . .evergreen/tox.sh -m teardown-encryption rm -rf $DRIVERS_TOOLS || true rm -f ./secrets-export.sh || true "fix absolute paths": - command: shell.exec params: script: | set +x ${PREPARE_SHELL} for filename in $(find ${DRIVERS_TOOLS} -name \*.json); do perl -p -i -e "s|ABSOLUTE_PATH_REPLACEMENT_TOKEN|${DRIVERS_TOOLS}|g" $filename done "windows fix": - command: shell.exec params: script: | set +x ${PREPARE_SHELL} for i in $(find ${DRIVERS_TOOLS}/.evergreen ${PROJECT_DIRECTORY}/.evergreen -name \*.sh); do cat $i | tr -d '\r' > $i.new mv $i.new $i done # Copy client certificate because symlinks do not work on Windows. cp ${DRIVERS_TOOLS}/.evergreen/x509gen/client.pem ${MONGO_ORCHESTRATION_HOME}/lib/client.pem "make files executable": - command: shell.exec params: script: | set +x ${PREPARE_SHELL} for i in $(find ${DRIVERS_TOOLS}/.evergreen ${PROJECT_DIRECTORY}/.evergreen -name \*.sh); do chmod +x $i done "init test-results": - command: shell.exec params: script: | set +x ${PREPARE_SHELL} echo '{"results": [{ "status": "FAIL", "test_file": "Build", "log_raw": "No test-results.json found was created" } ]}' > ${PROJECT_DIRECTORY}/test-results.json "install dependencies": - command: shell.exec params: working_dir: "src" script: | ${PREPARE_SHELL} set -o xtrace file="${PROJECT_DIRECTORY}/.evergreen/install-dependencies.sh" # Don't use ${file} syntax here because evergreen treats it as an empty expansion. [ -f "$file" ] && bash $file || echo "$file not available, skipping" "assume ec2 role": - command: ec2.assume_role params: role_arn: ${aws_test_secrets_role} "setup atlas": - command: subprocess.exec params: binary: bash include_expansions_in_env: ["task_id", "execution"] env: MONGODB_VERSION: "7.0" LAMBDA_STACK_NAME: dbx-python-lambda args: - ${DRIVERS_TOOLS}/.evergreen/atlas/setup-atlas-cluster.sh - command: expansions.update params: file: atlas-expansion.yml "run-ocsp-test": - command: shell.exec type: test params: working_dir: "src" script: | ${PREPARE_SHELL} TEST_OCSP=1 \ PYTHON_BINARY=${PYTHON_BINARY} \ CA_FILE="$DRIVERS_TOOLS/.evergreen/ocsp/${OCSP_ALGORITHM}/ca.pem" \ OCSP_TLS_SHOULD_SUCCEED="${OCSP_TLS_SHOULD_SUCCEED}" \ bash ${PROJECT_DIRECTORY}/.evergreen/tox.sh -m test-eg run-valid-ocsp-server: - command: shell.exec params: background: true script: | ${PREPARE_SHELL} cd ${DRIVERS_TOOLS}/.evergreen/ocsp . ./activate-ocspvenv.sh python ocsp_mock.py \ --ca_file ${OCSP_ALGORITHM}/ca.pem \ --ocsp_responder_cert ${OCSP_ALGORITHM}/ca.crt \ --ocsp_responder_key ${OCSP_ALGORITHM}/ca.key \ -p 8100 -v run-revoked-ocsp-server: - command: shell.exec params: background: true script: | ${PREPARE_SHELL} cd ${DRIVERS_TOOLS}/.evergreen/ocsp . ./activate-ocspvenv.sh python ocsp_mock.py \ --ca_file ${OCSP_ALGORITHM}/ca.pem \ --ocsp_responder_cert ${OCSP_ALGORITHM}/ca.crt \ --ocsp_responder_key ${OCSP_ALGORITHM}/ca.key \ -p 8100 \ -v \ --fault revoked run-valid-delegate-ocsp-server: - command: shell.exec params: background: true script: | ${PREPARE_SHELL} cd ${DRIVERS_TOOLS}/.evergreen/ocsp . ./activate-ocspvenv.sh python ocsp_mock.py \ --ca_file ${OCSP_ALGORITHM}/ca.pem \ --ocsp_responder_cert ${OCSP_ALGORITHM}/ocsp-responder.crt \ --ocsp_responder_key ${OCSP_ALGORITHM}/ocsp-responder.key \ -p 8100 -v run-revoked-delegate-ocsp-server: - command: shell.exec params: background: true script: | ${PREPARE_SHELL} cd ${DRIVERS_TOOLS}/.evergreen/ocsp . ./activate-ocspvenv.sh python ocsp_mock.py \ --ca_file ${OCSP_ALGORITHM}/ca.pem \ --ocsp_responder_cert ${OCSP_ALGORITHM}/ocsp-responder.crt \ --ocsp_responder_key ${OCSP_ALGORITHM}/ocsp-responder.key \ -p 8100 \ -v \ --fault revoked "run load-balancer": - command: shell.exec params: script: | DRIVERS_TOOLS=${DRIVERS_TOOLS} MONGODB_URI=${MONGODB_URI} bash ${DRIVERS_TOOLS}/.evergreen/run-load-balancer.sh start - command: expansions.update params: file: lb-expansion.yml "stop load-balancer": - command: shell.exec params: script: | cd ${DRIVERS_TOOLS}/.evergreen DRIVERS_TOOLS=${DRIVERS_TOOLS} bash ${DRIVERS_TOOLS}/.evergreen/run-load-balancer.sh stop "teardown_docker": - command: shell.exec params: script: | # Remove all Docker images DOCKER=$(command -v docker) || true if [ -n "$DOCKER" ]; then docker rmi -f $(docker images -a -q) &> /dev/null || true fi "teardown_aws": - command: shell.exec params: shell: "bash" script: | ${PREPARE_SHELL} cd "${DRIVERS_TOOLS}/.evergreen/auth_aws" if [ -f "./aws_e2e_setup.json" ]; then . ./activate-authawsvenv.sh python ./lib/aws_assign_instance_profile.py fi "teardown atlas": - command: subprocess.exec params: binary: bash args: - ${DRIVERS_TOOLS}/.evergreen/atlas/teardown-atlas-cluster.sh "build release": - command: shell.exec type: test params: working_dir: "src" script: | ${PREPARE_SHELL} set -o xtrace VERSION=${VERSION} ENSURE_UNIVERSAL2=${ENSURE_UNIVERSAL2} .evergreen/release.sh "upload release": - command: archive.targz_pack params: target: "release-files.tgz" source_dir: "src/dist" include: - "*" - command: s3.put params: aws_key: ${aws_key} aws_secret: ${aws_secret} local_file: release-files.tgz remote_file: ${UPLOAD_BUCKET}/release/${revision}/${task_id}-${execution}-release-files.tar.gz bucket: mciuploads permissions: public-read content_type: ${content_type|application/gzip} display_name: Release files "download and merge releases": - command: shell.exec params: silent: true script: | export AWS_ACCESS_KEY_ID=${aws_key} export AWS_SECRET_ACCESS_KEY=${aws_secret} # Download all the task coverage files. aws s3 cp --recursive s3://mciuploads/${UPLOAD_BUCKET}/release/${revision}/ release/ - command: shell.exec params: shell: "bash" script: | ${PREPARE_SHELL} set -o xtrace # Combine releases into one directory. ls -la release/ mkdir releases # Copy old manylinux release first since we want the newer manylinux # wheels to override them. mkdir old_manylinux if mv release/*old_manylinux* old_manylinux; then for REL in old_manylinux/*; do tar zxvf $REL -C releases/ done fi for REL in release/*; do tar zxvf $REL -C releases/ done # Build source distribution. cd src/ /opt/python/3.7/bin/python3 -m pip install build /opt/python/3.7/bin/python3 -m build --sdist . cp dist/* ../releases - command: archive.targz_pack params: target: "release-files-all.tgz" source_dir: "releases/" include: - "*" - command: s3.put params: aws_key: ${aws_key} aws_secret: ${aws_secret} local_file: release-files-all.tgz remote_file: ${UPLOAD_BUCKET}/release-all/${revision}/${task_id}-${execution}-release-files-all.tar.gz bucket: mciuploads permissions: public-read content_type: ${content_type|application/gzip} display_name: Release files all "run perf tests": - command: shell.exec type: test params: working_dir: "src" script: | ${PREPARE_SHELL} PROJECT_DIRECTORY=${PROJECT_DIRECTORY} bash ${PROJECT_DIRECTORY}/.evergreen/run-perf-tests.sh "attach benchmark test results": - command: attach.results params: file_location: src/report.json "send dashboard data": - command: perf.send params: file: src/results.json pre: - func: "fetch source" - func: "prepare resources" - func: "windows fix" - func: "fix absolute paths" - func: "init test-results" - func: "make files executable" - func: "install dependencies" - func: "assume ec2 role" post: # Disabled, causing timeouts # - func: "upload working dir" - func: "upload coverage" - func: "upload mo artifacts" - func: "upload test results" - func: "stop mongo-orchestration" - func: "teardown_aws" - func: "cleanup" - func: "teardown_docker" task_groups: - name: serverless_task_group setup_group_can_fail_task: true setup_group_timeout_secs: 1800 # 30 minutes setup_group: - func: "fetch source" - func: "prepare resources" - command: subprocess.exec params: binary: bash env: VAULT_NAME: ${VAULT_NAME} args: - ${DRIVERS_TOOLS}/.evergreen/serverless/create-instance.sh teardown_task: - command: subprocess.exec params: binary: bash args: - ${DRIVERS_TOOLS}/.evergreen/serverless/delete-instance.sh - func: "upload test results" tasks: - ".serverless" - name: testgcpkms_task_group setup_group_can_fail_task: true setup_group_timeout_secs: 1800 # 30 minutes setup_group: - func: fetch source - func: prepare resources - func: fix absolute paths - func: make files executable - command: subprocess.exec params: binary: "bash" args: - ${DRIVERS_TOOLS}/.evergreen/csfle/gcpkms/create-and-setup-instance.sh teardown_task: - command: subprocess.exec params: binary: "bash" args: - ${DRIVERS_TOOLS}/.evergreen/csfle/gcpkms/delete-instance.sh - func: "upload test results" tasks: - testgcpkms-task - name: testazurekms_task_group setup_group: - func: fetch source - func: prepare resources - func: fix absolute paths - func: make files executable - command: subprocess.exec params: binary: bash env: AZUREKMS_VMNAME_PREFIX: "PYTHON_DRIVER" args: - ${DRIVERS_TOOLS}/.evergreen/csfle/azurekms/create-and-setup-vm.sh teardown_group: - command: subprocess.exec params: binary: bash args: - ${DRIVERS_TOOLS}/.evergreen/csfle/azurekms/delete-vm.sh - func: "upload test results" setup_group_can_fail_task: true teardown_group_can_fail_task: true setup_group_timeout_secs: 1800 tasks: - testazurekms-task - name: testazureoidc_task_group setup_group: - func: fetch source - func: prepare resources - func: fix absolute paths - func: make files executable - command: subprocess.exec params: binary: bash env: AZUREOIDC_VMNAME_PREFIX: "PYTHON_DRIVER" args: - ${DRIVERS_TOOLS}/.evergreen/auth_oidc/azure/create-and-setup-vm.sh teardown_task: - command: subprocess.exec params: binary: bash args: - ${DRIVERS_TOOLS}/.evergreen/auth_oidc/azure/delete-vm.sh setup_group_can_fail_task: true setup_group_timeout_secs: 1800 tasks: - oidc-auth-test-azure-latest - name: testgcpoidc_task_group setup_group: - func: fetch source - func: prepare resources - func: fix absolute paths - func: make files executable - command: subprocess.exec params: binary: bash env: GCPOIDC_VMNAME_PREFIX: "PYTHON_DRIVER" args: - ${DRIVERS_TOOLS}/.evergreen/auth_oidc/gcp/setup.sh teardown_task: - command: subprocess.exec params: binary: bash args: - ${DRIVERS_TOOLS}/.evergreen/auth_oidc/gcp/teardown.sh setup_group_can_fail_task: true setup_group_timeout_secs: 1800 tasks: - oidc-auth-test-gcp-latest - name: testoidc_task_group setup_group: - func: fetch source - func: prepare resources - func: fix absolute paths - func: make files executable - func: "assume ec2 role" - command: subprocess.exec params: binary: bash include_expansions_in_env: ["AWS_ACCESS_KEY_ID", "AWS_SECRET_ACCESS_KEY", "AWS_SESSION_TOKEN"] args: - ${DRIVERS_TOOLS}/.evergreen/auth_oidc/setup.sh teardown_task: - command: subprocess.exec params: binary: bash args: - ${DRIVERS_TOOLS}/.evergreen/auth_oidc/teardown.sh setup_group_can_fail_task: true setup_group_timeout_secs: 1800 tasks: - oidc-auth-test-latest - name: test_aws_lambda_task_group setup_group: - func: fetch source - func: prepare resources - func: setup atlas teardown_task: - func: teardown atlas setup_group_can_fail_task: true setup_group_timeout_secs: 1800 tasks: - test-aws-lambda-deployed - name: test_atlas_task_group_search_indexes setup_group: - func: fetch source - func: prepare resources - func: fix absolute paths - func: make files executable - func: setup atlas teardown_task: - func: teardown atlas setup_group_can_fail_task: true setup_group_timeout_secs: 1800 tasks: - test-search-index-helpers tasks: # Wildcard task. Do you need to find out what tools are available and where? # Throw it here, and execute this task on all buildvariants - name: getdata commands: - command: shell.exec type: test params: script: | set -o xtrace . ${DRIVERS_TOOLS}/.evergreen/download-mongodb.sh || true get_distro || true echo $DISTRO echo $MARCH echo $OS uname -a || true ls /etc/*release* || true cc --version || true gcc --version || true clang --version || true gcov --version || true lcov --version || true llvm-cov --version || true echo $PATH ls -la /usr/local/Cellar/llvm/*/bin/ || true ls -la /usr/local/Cellar/ || true scan-build --version || true genhtml --version || true valgrind --version || true - name: "release-mac-1100" tags: ["release_tag"] run_on: macos-1100 commands: - func: "build release" vars: VERSION: "3.12" ENSURE_UNIVERSAL2: "1" - func: "build release" vars: VERSION: "3.11" ENSURE_UNIVERSAL2: "1" - func: "build release" vars: VERSION: "3.10" ENSURE_UNIVERSAL2: "1" - func: "build release" vars: VERSION: "3.9" ENSURE_UNIVERSAL2: "1" - func: "upload release" - func: "build release" vars: VERSION: "3.8" - func: "upload release" - name: "release-mac-1014" tags: ["release_tag"] run_on: macos-1014 commands: - func: "build release" vars: VERSION: "3.7" - func: "upload release" - name: "release-windows" tags: ["release_tag"] run_on: windows-64-vsMulti-small commands: - func: "build release" - func: "upload release" - name: "release-manylinux" tags: ["release_tag"] run_on: ubuntu2204-large exec_timeout_secs: 216000 # 60 minutes (manylinux task is slow). commands: - func: "build release" - func: "upload release" - name: "release-old-manylinux" tags: ["release_tag"] run_on: ubuntu2204-large exec_timeout_secs: 216000 # 60 minutes (manylinux task is slow). commands: - command: shell.exec type: test params: working_dir: "src" script: | ${PREPARE_SHELL} set -o xtrace .evergreen/build-manylinux.sh BUILD_WITH_TAG - func: "upload release" - name: "release-combine" tags: ["release_tag"] run_on: rhel84-small depends_on: - name: "*" variant: ".release_tag" patch_optional: true commands: - func: "download and merge releases" # Standard test tasks {{{ - name: "mockupdb" tags: ["mockupdb"] commands: - func: "run mockupdb tests" - name: "doctests" tags: ["doctests"] commands: - func: "bootstrap mongo-orchestration" vars: VERSION: "latest" TOPOLOGY: "server" - func: "run doctests" - name: "test-3.6-standalone" tags: ["3.6", "standalone"] commands: - func: "bootstrap mongo-orchestration" vars: VERSION: "3.6" TOPOLOGY: "server" - func: "run tests" - name: "test-3.6-replica_set" tags: ["3.6", "replica_set"] commands: - func: "bootstrap mongo-orchestration" vars: VERSION: "3.6" TOPOLOGY: "replica_set" - func: "run tests" - name: "test-3.6-sharded_cluster" tags: ["3.6", "sharded_cluster"] commands: - func: "bootstrap mongo-orchestration" vars: VERSION: "3.6" TOPOLOGY: "sharded_cluster" - func: "run tests" - name: "test-4.0-standalone" tags: ["4.0", "standalone"] commands: - func: "bootstrap mongo-orchestration" vars: VERSION: "4.0" TOPOLOGY: "server" - func: "run tests" - name: "test-4.0-replica_set" tags: ["4.0", "replica_set"] commands: - func: "bootstrap mongo-orchestration" vars: VERSION: "4.0" TOPOLOGY: "replica_set" - func: "run tests" - name: "test-4.0-sharded_cluster" tags: ["4.0", "sharded_cluster"] commands: - func: "bootstrap mongo-orchestration" vars: VERSION: "4.0" TOPOLOGY: "sharded_cluster" - func: "run tests" - name: "test-4.2-standalone" tags: ["4.2", "standalone"] commands: - func: "bootstrap mongo-orchestration" vars: VERSION: "4.2" TOPOLOGY: "server" - func: "run tests" - name: "test-4.2-replica_set" tags: ["4.2", "replica_set"] commands: - func: "bootstrap mongo-orchestration" vars: VERSION: "4.2" TOPOLOGY: "replica_set" - func: "run tests" - name: "test-4.2-sharded_cluster" tags: ["4.2", "sharded_cluster"] commands: - func: "bootstrap mongo-orchestration" vars: VERSION: "4.2" TOPOLOGY: "sharded_cluster" - func: "run tests" - name: "test-4.4-standalone" tags: ["4.4", "standalone"] commands: - func: "bootstrap mongo-orchestration" vars: VERSION: "4.4" TOPOLOGY: "server" - func: "run tests" - name: "test-4.4-replica_set" tags: ["4.4", "replica_set"] commands: - func: "bootstrap mongo-orchestration" vars: VERSION: "4.4" TOPOLOGY: "replica_set" - func: "run tests" - name: "test-4.4-sharded_cluster" tags: ["4.4", "sharded_cluster"] commands: - func: "bootstrap mongo-orchestration" vars: VERSION: "4.4" TOPOLOGY: "sharded_cluster" - func: "run tests" - name: "test-5.0-standalone" tags: ["5.0", "standalone"] commands: - func: "bootstrap mongo-orchestration" vars: VERSION: "5.0" TOPOLOGY: "server" - func: "run tests" - name: "test-5.0-replica_set" tags: ["5.0", "replica_set"] commands: - func: "bootstrap mongo-orchestration" vars: VERSION: "5.0" TOPOLOGY: "replica_set" - func: "run tests" - name: "test-5.0-sharded_cluster" tags: ["5.0", "sharded_cluster"] commands: - func: "bootstrap mongo-orchestration" vars: VERSION: "5.0" TOPOLOGY: "sharded_cluster" - func: "run tests" - name: "test-6.0-standalone" tags: ["6.0", "standalone"] commands: - func: "bootstrap mongo-orchestration" vars: VERSION: "6.0" TOPOLOGY: "server" - func: "run tests" - name: "test-6.0-replica_set" tags: ["6.0", "replica_set"] commands: - func: "bootstrap mongo-orchestration" vars: VERSION: "6.0" TOPOLOGY: "replica_set" - func: "run tests" - name: "test-6.0-sharded_cluster" tags: ["6.0", "sharded_cluster"] commands: - func: "bootstrap mongo-orchestration" vars: VERSION: "6.0" TOPOLOGY: "sharded_cluster" - func: "run tests" - name: "test-8.0-standalone" tags: ["8.0", "standalone"] commands: - func: "bootstrap mongo-orchestration" vars: VERSION: "8.0" TOPOLOGY: "server" - func: "run tests" - name: "test-8.0-replica_set" tags: ["8.0", "replica_set"] commands: - func: "bootstrap mongo-orchestration" vars: VERSION: "8.0" TOPOLOGY: "replica_set" - func: "run tests" - name: "test-8.0-sharded_cluster" tags: ["8.0", "sharded_cluster"] commands: - func: "bootstrap mongo-orchestration" vars: VERSION: "8.0" TOPOLOGY: "sharded_cluster" - func: "run tests" - name: "test-7.0-standalone" tags: ["7.0", "standalone"] commands: - func: "bootstrap mongo-orchestration" vars: VERSION: "7.0" TOPOLOGY: "server" - func: "run tests" - name: "test-7.0-replica_set" tags: ["7.0", "replica_set"] commands: - func: "bootstrap mongo-orchestration" vars: VERSION: "7.0" TOPOLOGY: "replica_set" - func: "run tests" - name: "test-7.0-sharded_cluster" tags: ["7.0", "sharded_cluster"] commands: - func: "bootstrap mongo-orchestration" vars: VERSION: "7.0" TOPOLOGY: "sharded_cluster" - func: "run tests" - name: "test-latest-standalone" tags: ["latest", "standalone"] commands: - func: "bootstrap mongo-orchestration" vars: VERSION: "latest" TOPOLOGY: "server" - func: "run tests" - name: "test-latest-replica_set" tags: ["latest", "replica_set"] commands: - func: "bootstrap mongo-orchestration" vars: VERSION: "latest" TOPOLOGY: "replica_set" - func: "run tests" - name: "test-latest-sharded_cluster" tags: ["latest", "sharded_cluster"] commands: - func: "bootstrap mongo-orchestration" vars: VERSION: "latest" TOPOLOGY: "sharded_cluster" - func: "run tests" - name: "test-rapid-standalone" tags: ["rapid", "standalone"] commands: - func: "bootstrap mongo-orchestration" vars: VERSION: "rapid" TOPOLOGY: "server" - func: "run tests" - name: "test-rapid-replica_set" tags: ["rapid", "replica_set"] commands: - func: "bootstrap mongo-orchestration" vars: VERSION: "rapid" TOPOLOGY: "replica_set" - func: "run tests" - name: "test-rapid-sharded_cluster" tags: ["rapid", "sharded_cluster"] commands: - func: "bootstrap mongo-orchestration" vars: VERSION: "rapid" TOPOLOGY: "sharded_cluster" - func: "run tests" - name: "test-serverless" tags: ["serverless"] commands: - func: "run tests" - name: "test-enterprise-auth" tags: ["enterprise-auth"] commands: - func: "bootstrap mongo-orchestration" vars: VERSION: "latest" TOPOLOGY: "server" - func: "assume ec2 role" - func: "run enterprise auth tests" - name: "test-search-index-helpers" commands: - func: "bootstrap mongo-orchestration" vars: VERSION: "6.0" TOPOLOGY: "replica_set" - func: "run tests" vars: TEST_INDEX_MANAGEMENT: "1" - name: "mod-wsgi-standalone" tags: ["mod_wsgi"] commands: - func: "bootstrap mongo-orchestration" vars: VERSION: "latest" TOPOLOGY: "server" - func: "run mod_wsgi tests" - name: "mod-wsgi-replica-set" tags: ["mod_wsgi"] commands: - func: "bootstrap mongo-orchestration" vars: VERSION: "latest" TOPOLOGY: "replica_set" - func: "run mod_wsgi tests" - name: "mod-wsgi-embedded-mode-standalone" tags: ["mod_wsgi"] commands: - func: "bootstrap mongo-orchestration" vars: VERSION: "latest" TOPOLOGY: "server" - func: "run mod_wsgi tests" vars: MOD_WSGI_EMBEDDED: "1" - name: "mod-wsgi-embedded-mode-replica-set" tags: ["mod_wsgi"] commands: - func: "bootstrap mongo-orchestration" vars: VERSION: "latest" TOPOLOGY: "replica_set" - func: "run mod_wsgi tests" vars: MOD_WSGI_EMBEDDED: "1" - name: "no-server" tags: ["no-server"] commands: - func: "run tests" - name: "atlas-connect" tags: ["atlas-connect"] commands: - func: "assume ec2 role" - func: "run atlas tests" - name: atlas-data-lake-tests commands: - func: "bootstrap data lake" - func: "run tests" vars: TEST_DATA_LAKE: "true" - name: "test-aws-lambda-deployed" commands: - func: "install dependencies" - command: ec2.assume_role params: role_arn: ${LAMBDA_AWS_ROLE_ARN} duration_seconds: 3600 - command: subprocess.exec params: working_dir: src binary: bash add_expansions_to_env: true args: - .evergreen/run-deployed-lambda-aws-tests.sh env: TEST_LAMBDA_DIRECTORY: ${PROJECT_DIRECTORY}/test/lambda - name: test-ocsp-rsa-valid-cert-server-staples tags: ["ocsp", "ocsp-rsa", "ocsp-staple"] commands: - func: run-valid-ocsp-server vars: OCSP_ALGORITHM: "rsa" - func: "bootstrap mongo-orchestration" vars: ORCHESTRATION_FILE: "rsa-basic-tls-ocsp-mustStaple.json" - func: run-ocsp-test vars: OCSP_ALGORITHM: "rsa" OCSP_TLS_SHOULD_SUCCEED: "true" - name: test-ocsp-rsa-invalid-cert-server-staples tags: ["ocsp", "ocsp-rsa", "ocsp-staple"] commands: - func: run-revoked-ocsp-server vars: OCSP_ALGORITHM: "rsa" - func: "bootstrap mongo-orchestration" vars: ORCHESTRATION_FILE: "rsa-basic-tls-ocsp-mustStaple.json" - func: run-ocsp-test vars: OCSP_ALGORITHM: "rsa" OCSP_TLS_SHOULD_SUCCEED: "false" - name: test-ocsp-rsa-valid-cert-server-does-not-staple tags: ["ocsp", "ocsp-rsa"] commands: - func: run-valid-ocsp-server vars: OCSP_ALGORITHM: "rsa" - func: "bootstrap mongo-orchestration" vars: ORCHESTRATION_FILE: "rsa-basic-tls-ocsp-disableStapling.json" - func: run-ocsp-test vars: OCSP_ALGORITHM: "rsa" OCSP_TLS_SHOULD_SUCCEED: "true" - name: test-ocsp-rsa-invalid-cert-server-does-not-staple tags: ["ocsp", "ocsp-rsa"] commands: - func: run-revoked-ocsp-server vars: OCSP_ALGORITHM: "rsa" - func: "bootstrap mongo-orchestration" vars: ORCHESTRATION_FILE: "rsa-basic-tls-ocsp-disableStapling.json" - func: run-ocsp-test vars: OCSP_ALGORITHM: "rsa" OCSP_TLS_SHOULD_SUCCEED: "false" - name: test-ocsp-rsa-soft-fail tags: ["ocsp", "ocsp-rsa"] commands: - func: "bootstrap mongo-orchestration" vars: ORCHESTRATION_FILE: "rsa-basic-tls-ocsp-disableStapling.json" - func: run-ocsp-test vars: OCSP_ALGORITHM: "rsa" OCSP_TLS_SHOULD_SUCCEED: "true" - name: test-ocsp-rsa-malicious-invalid-cert-mustStaple-server-does-not-staple tags: ["ocsp", "ocsp-rsa"] commands: - func: run-revoked-ocsp-server vars: OCSP_ALGORITHM: "rsa" - func: "bootstrap mongo-orchestration" vars: ORCHESTRATION_FILE: "rsa-basic-tls-ocsp-mustStaple-disableStapling.json" - func: run-ocsp-test vars: OCSP_ALGORITHM: "rsa" OCSP_TLS_SHOULD_SUCCEED: "false" - name: test-ocsp-rsa-malicious-no-responder-mustStaple-server-does-not-staple tags: ["ocsp", "ocsp-rsa"] commands: - func: "bootstrap mongo-orchestration" vars: ORCHESTRATION_FILE: "rsa-basic-tls-ocsp-mustStaple-disableStapling.json" - func: run-ocsp-test vars: OCSP_ALGORITHM: "rsa" OCSP_TLS_SHOULD_SUCCEED: "false" - name: test-ocsp-rsa-delegate-valid-cert-server-staples tags: ["ocsp", "ocsp-rsa", "ocsp-staple"] commands: - func: run-valid-delegate-ocsp-server vars: OCSP_ALGORITHM: "rsa" - func: "bootstrap mongo-orchestration" vars: ORCHESTRATION_FILE: "rsa-basic-tls-ocsp-mustStaple.json" - func: run-ocsp-test vars: OCSP_ALGORITHM: "rsa" OCSP_TLS_SHOULD_SUCCEED: "true" - name: test-ocsp-rsa-delegate-invalid-cert-server-staples tags: ["ocsp", "ocsp-rsa", "ocsp-staple"] commands: - func: run-revoked-delegate-ocsp-server vars: OCSP_ALGORITHM: "rsa" - func: "bootstrap mongo-orchestration" vars: ORCHESTRATION_FILE: "rsa-basic-tls-ocsp-mustStaple.json" - func: run-ocsp-test vars: OCSP_ALGORITHM: "rsa" OCSP_TLS_SHOULD_SUCCEED: "false" - name: test-ocsp-rsa-delegate-valid-cert-server-does-not-staple tags: ["ocsp", "ocsp-rsa"] commands: - func: run-valid-delegate-ocsp-server vars: OCSP_ALGORITHM: "rsa" - func: "bootstrap mongo-orchestration" vars: ORCHESTRATION_FILE: "rsa-basic-tls-ocsp-disableStapling.json" - func: run-ocsp-test vars: OCSP_ALGORITHM: "rsa" OCSP_TLS_SHOULD_SUCCEED: "true" - name: test-ocsp-rsa-delegate-invalid-cert-server-does-not-staple tags: ["ocsp", "ocsp-rsa"] commands: - func: run-revoked-delegate-ocsp-server vars: OCSP_ALGORITHM: "rsa" - func: "bootstrap mongo-orchestration" vars: ORCHESTRATION_FILE: "rsa-basic-tls-ocsp-disableStapling.json" - func: run-ocsp-test vars: OCSP_ALGORITHM: "rsa" OCSP_TLS_SHOULD_SUCCEED: "false" - name: test-ocsp-rsa-delegate-malicious-invalid-cert-mustStaple-server-does-not-staple tags: ["ocsp", "ocsp-rsa"] commands: - func: run-revoked-delegate-ocsp-server vars: OCSP_ALGORITHM: "rsa" - func: "bootstrap mongo-orchestration" vars: ORCHESTRATION_FILE: "rsa-basic-tls-ocsp-mustStaple-disableStapling.json" - func: run-ocsp-test vars: OCSP_ALGORITHM: "rsa" OCSP_TLS_SHOULD_SUCCEED: "false" - name: test-ocsp-ecdsa-valid-cert-server-staples tags: ["ocsp", "ocsp-ecdsa", "ocsp-staple"] commands: - func: run-valid-ocsp-server vars: OCSP_ALGORITHM: "ecdsa" - func: "bootstrap mongo-orchestration" vars: ORCHESTRATION_FILE: "ecdsa-basic-tls-ocsp-mustStaple.json" - func: run-ocsp-test vars: OCSP_ALGORITHM: "ecdsa" OCSP_TLS_SHOULD_SUCCEED: "true" - name: test-ocsp-ecdsa-invalid-cert-server-staples tags: ["ocsp", "ocsp-ecdsa", "ocsp-staple"] commands: - func: run-revoked-ocsp-server vars: OCSP_ALGORITHM: "ecdsa" - func: "bootstrap mongo-orchestration" vars: ORCHESTRATION_FILE: "ecdsa-basic-tls-ocsp-mustStaple.json" - func: run-ocsp-test vars: OCSP_ALGORITHM: "ecdsa" OCSP_TLS_SHOULD_SUCCEED: "false" - name: test-ocsp-ecdsa-valid-cert-server-does-not-staple tags: ["ocsp", "ocsp-ecdsa"] commands: - func: run-valid-ocsp-server vars: OCSP_ALGORITHM: "ecdsa" - func: "bootstrap mongo-orchestration" vars: ORCHESTRATION_FILE: "ecdsa-basic-tls-ocsp-disableStapling.json" - func: run-ocsp-test vars: OCSP_ALGORITHM: "ecdsa" OCSP_TLS_SHOULD_SUCCEED: "true" - name: test-ocsp-ecdsa-invalid-cert-server-does-not-staple tags: ["ocsp", "ocsp-ecdsa"] commands: - func: run-revoked-ocsp-server vars: OCSP_ALGORITHM: "ecdsa" - func: "bootstrap mongo-orchestration" vars: ORCHESTRATION_FILE: "ecdsa-basic-tls-ocsp-disableStapling.json" - func: run-ocsp-test vars: OCSP_ALGORITHM: "ecdsa" OCSP_TLS_SHOULD_SUCCEED: "false" - name: test-ocsp-ecdsa-soft-fail tags: ["ocsp", "ocsp-ecdsa"] commands: - func: "bootstrap mongo-orchestration" vars: ORCHESTRATION_FILE: "ecdsa-basic-tls-ocsp-disableStapling.json" - func: run-ocsp-test vars: OCSP_ALGORITHM: "ecdsa" OCSP_TLS_SHOULD_SUCCEED: "true" - name: test-ocsp-ecdsa-malicious-invalid-cert-mustStaple-server-does-not-staple tags: ["ocsp", "ocsp-ecdsa"] commands: - func: run-revoked-ocsp-server vars: OCSP_ALGORITHM: "ecdsa" - func: "bootstrap mongo-orchestration" vars: ORCHESTRATION_FILE: "ecdsa-basic-tls-ocsp-mustStaple-disableStapling.json" - func: run-ocsp-test vars: OCSP_ALGORITHM: "ecdsa" OCSP_TLS_SHOULD_SUCCEED: "false" - name: test-ocsp-ecdsa-malicious-no-responder-mustStaple-server-does-not-staple tags: ["ocsp", "ocsp-ecdsa"] commands: - func: "bootstrap mongo-orchestration" vars: ORCHESTRATION_FILE: "ecdsa-basic-tls-ocsp-mustStaple-disableStapling.json" - func: run-ocsp-test vars: OCSP_ALGORITHM: "ecdsa" OCSP_TLS_SHOULD_SUCCEED: "false" - name: test-ocsp-ecdsa-delegate-valid-cert-server-staples tags: ["ocsp", "ocsp-ecdsa", "ocsp-staple"] commands: - func: run-valid-delegate-ocsp-server vars: OCSP_ALGORITHM: "ecdsa" - func: "bootstrap mongo-orchestration" vars: ORCHESTRATION_FILE: "ecdsa-basic-tls-ocsp-mustStaple.json" - func: run-ocsp-test vars: OCSP_ALGORITHM: "ecdsa" OCSP_TLS_SHOULD_SUCCEED: "true" - name: test-ocsp-ecdsa-delegate-invalid-cert-server-staples tags: ["ocsp", "ocsp-ecdsa", "ocsp-staple"] commands: - func: run-revoked-delegate-ocsp-server vars: OCSP_ALGORITHM: "ecdsa" - func: "bootstrap mongo-orchestration" vars: ORCHESTRATION_FILE: "ecdsa-basic-tls-ocsp-mustStaple.json" - func: run-ocsp-test vars: OCSP_ALGORITHM: "ecdsa" OCSP_TLS_SHOULD_SUCCEED: "false" - name: test-ocsp-ecdsa-delegate-valid-cert-server-does-not-staple tags: ["ocsp", "ocsp-ecdsa"] commands: - func: run-valid-delegate-ocsp-server vars: OCSP_ALGORITHM: "ecdsa" - func: "bootstrap mongo-orchestration" vars: ORCHESTRATION_FILE: "ecdsa-basic-tls-ocsp-disableStapling.json" - func: run-ocsp-test vars: OCSP_ALGORITHM: "ecdsa" OCSP_TLS_SHOULD_SUCCEED: "true" - name: test-ocsp-ecdsa-delegate-invalid-cert-server-does-not-staple tags: ["ocsp", "ocsp-ecdsa"] commands: - func: run-revoked-delegate-ocsp-server vars: OCSP_ALGORITHM: "ecdsa" - func: "bootstrap mongo-orchestration" vars: ORCHESTRATION_FILE: "ecdsa-basic-tls-ocsp-disableStapling.json" - func: run-ocsp-test vars: OCSP_ALGORITHM: "ecdsa" OCSP_TLS_SHOULD_SUCCEED: "false" - name: test-ocsp-ecdsa-delegate-malicious-invalid-cert-mustStaple-server-does-not-staple tags: ["ocsp", "ocsp-ecdsa"] commands: - func: run-revoked-delegate-ocsp-server vars: OCSP_ALGORITHM: "ecdsa" - func: "bootstrap mongo-orchestration" vars: ORCHESTRATION_FILE: "ecdsa-basic-tls-ocsp-mustStaple-disableStapling.json" - func: run-ocsp-test vars: OCSP_ALGORITHM: "ecdsa" OCSP_TLS_SHOULD_SUCCEED: "false" - name: "aws-auth-test-4.4" commands: - func: "bootstrap mongo-orchestration" vars: AUTH: "auth" ORCHESTRATION_FILE: "auth-aws.json" TOPOLOGY: "server" VERSION: "4.4" - func: "assume ec2 role" - func: "get aws auth secrets" - func: "run aws auth test with regular aws credentials" - func: "run aws auth test with assume role credentials" - func: "run aws auth test with aws credentials as environment variables" - func: "run aws auth test with aws credentials and session token as environment variables" - func: "run aws auth test with aws EC2 credentials" - func: "run aws auth test with aws web identity credentials" - func: "run aws ECS auth test" - name: "aws-auth-test-5.0" commands: - func: "bootstrap mongo-orchestration" vars: AUTH: "auth" ORCHESTRATION_FILE: "auth-aws.json" TOPOLOGY: "server" VERSION: "5.0" - func: "assume ec2 role" - func: "get aws auth secrets" - func: "run aws auth test with regular aws credentials" - func: "run aws auth test with assume role credentials" - func: "run aws auth test with aws credentials as environment variables" - func: "run aws auth test with aws credentials and session token as environment variables" - func: "run aws auth test with aws EC2 credentials" - func: "run aws auth test with aws web identity credentials" - func: "run aws ECS auth test" - name: "aws-auth-test-6.0" commands: - func: "bootstrap mongo-orchestration" vars: AUTH: "auth" ORCHESTRATION_FILE: "auth-aws.json" TOPOLOGY: "server" VERSION: "6.0" - func: "assume ec2 role" - func: "get aws auth secrets" - func: "run aws auth test with regular aws credentials" - func: "run aws auth test with assume role credentials" - func: "run aws auth test with aws credentials as environment variables" - func: "run aws auth test with aws credentials and session token as environment variables" - func: "run aws auth test with aws EC2 credentials" - func: "run aws auth test with aws web identity credentials" - func: "run aws ECS auth test" - name: "aws-auth-test-7.0" commands: - func: "bootstrap mongo-orchestration" vars: AUTH: "auth" ORCHESTRATION_FILE: "auth-aws.json" TOPOLOGY: "server" VERSION: "7.0" - func: "assume ec2 role" - func: "get aws auth secrets" - func: "run aws auth test with regular aws credentials" - func: "run aws auth test with assume role credentials" - func: "run aws auth test with aws credentials as environment variables" - func: "run aws auth test with aws credentials and session token as environment variables" - func: "run aws auth test with aws EC2 credentials" - func: "run aws auth test with aws web identity credentials" - func: "run aws ECS auth test" - name: "aws-auth-test-8.0" commands: - func: "bootstrap mongo-orchestration" vars: AUTH: "auth" ORCHESTRATION_FILE: "auth-aws.json" TOPOLOGY: "server" VERSION: "8.0" - func: "assume ec2 role" - func: "get aws auth secrets" - func: "run aws auth test with regular aws credentials" - func: "run aws auth test with assume role credentials" - func: "run aws auth test with aws credentials as environment variables" - func: "run aws auth test with aws credentials and session token as environment variables" - func: "run aws auth test with aws EC2 credentials" - func: "run aws auth test with aws web identity credentials" - func: "run aws ECS auth test" - name: "aws-auth-test-rapid" commands: - func: "bootstrap mongo-orchestration" vars: AUTH: "auth" ORCHESTRATION_FILE: "auth-aws.json" TOPOLOGY: "server" VERSION: "rapid" - func: "assume ec2 role" - func: "get aws auth secrets" - func: "run aws auth test with regular aws credentials" - func: "run aws auth test with assume role credentials" - func: "run aws auth test with aws credentials as environment variables" - func: "run aws auth test with aws credentials and session token as environment variables" - func: "run aws auth test with aws EC2 credentials" - func: "run aws auth test with aws web identity credentials" - func: "run aws ECS auth test" - name: "aws-auth-test-latest" commands: - func: "bootstrap mongo-orchestration" vars: AUTH: "auth" ORCHESTRATION_FILE: "auth-aws.json" TOPOLOGY: "server" VERSION: "latest" - func: "assume ec2 role" - func: "get aws auth secrets" - func: "run aws auth test with regular aws credentials" - func: "run aws auth test with assume role credentials" - func: "run aws auth test with aws credentials as environment variables" - func: "run aws auth test with aws credentials and session token as environment variables" - func: "run aws auth test with aws EC2 credentials" - func: "run aws auth test with aws web identity credentials" - func: "run aws ECS auth test" - name: load-balancer-test commands: - func: "bootstrap mongo-orchestration" vars: TOPOLOGY: "sharded_cluster" LOAD_BALANCER: true - func: "run load-balancer" - func: "run tests" - name: "oidc-auth-test-latest" commands: - func: "run oidc auth test with test credentials" - name: "oidc-auth-test-azure-latest" commands: - command: shell.exec params: shell: bash script: |- set -o errexit ${PREPARE_SHELL} cd src git add . git commit -m "add files" export AZUREOIDC_DRIVERS_TAR_FILE=/tmp/mongo-python-driver.tgz git archive -o $AZUREOIDC_DRIVERS_TAR_FILE HEAD export AZUREOIDC_TEST_CMD="OIDC_ENV=azure ./.evergreen/run-mongodb-oidc-test.sh" bash $DRIVERS_TOOLS/.evergreen/auth_oidc/azure/run-driver-test.sh - name: "oidc-auth-test-gcp-latest" commands: - command: shell.exec params: shell: bash script: |- set -o errexit ${PREPARE_SHELL} cd src git add . git commit -m "add files" export GCPOIDC_DRIVERS_TAR_FILE=/tmp/mongo-python-driver.tgz git archive -o $GCPOIDC_DRIVERS_TAR_FILE HEAD # Define the command to run on the VM. # Ensure that we source the environment file created for us, set up any other variables we need, # and then run our test suite on the vm. export GCPOIDC_TEST_CMD="OIDC_ENV=gcp ./.evergreen/run-mongodb-oidc-test.sh" bash $DRIVERS_TOOLS/.evergreen/auth_oidc/gcp/run-driver-test.sh - name: "test-fips-standalone" tags: ["fips"] commands: - func: "bootstrap mongo-orchestration" vars: VERSION: "latest" TOPOLOGY: "server" - func: "run tests" # }}} - name: "coverage-report" tags: ["coverage"] depends_on: # BUILD-3165: We can't use "*" (all tasks) and specify "variant". # Instead list out all coverage tasks using tags. - name: ".standalone" variant: ".coverage_tag" # Run the coverage task even if some tasks fail. status: "*" # Run the coverage task even if some tasks are not scheduled in a patch build. patch_optional: true - name: ".replica_set" variant: ".coverage_tag" status: "*" patch_optional: true - name: ".sharded_cluster" variant: ".coverage_tag" status: "*" patch_optional: true commands: - func: "download and merge coverage" - name: "testgcpkms-task" commands: - command: subprocess.exec type: setup params: working_dir: "src" binary: "bash" include_expansions_in_env: ["DRIVERS_TOOLS"] args: - .evergreen/run-gcpkms-test.sh - name: "testgcpkms-fail-task" # testgcpkms-fail-task runs in a non-GCE environment. # It is expected to fail to obtain GCE credentials. commands: - func: "bootstrap mongo-orchestration" vars: VERSION: "latest" TOPOLOGY: "server" - command: shell.exec type: test params: working_dir: "src" shell: "bash" script: | ${PREPARE_SHELL} export PYTHON_BINARY=/opt/mongodbtoolchain/v4/bin/python3 export LIBMONGOCRYPT_URL=https://s3.amazonaws.com/mciuploads/libmongocrypt/debian10/master/latest/libmongocrypt.tar.gz SUCCESS=false TEST_FLE_GCP_AUTO=1 ./.evergreen/tox.sh -m test-eg - name: testazurekms-task commands: - command: subprocess.exec params: binary: bash working_dir: src include_expansions_in_env: ["DRIVERS_TOOLS"] args: - .evergreen/run-azurekms-test.sh - name: testazurekms-fail-task commands: - func: fetch source - func: make files executable - func: "bootstrap mongo-orchestration" vars: VERSION: "latest" TOPOLOGY: "server" - command: subprocess.exec type: test params: binary: bash working_dir: src include_expansions_in_env: ["DRIVERS_TOOLS"] args: - .evergreen/run-azurekms-fail-test.sh - name: "perf-6.0-standalone" tags: ["perf"] commands: - func: "bootstrap mongo-orchestration" vars: VERSION: "v6.0-perf" TOPOLOGY: "server" - func: "run perf tests" - func: "attach benchmark test results" - func: "send dashboard data" - name: "perf-6.0-standalone-ssl" tags: ["perf"] commands: - func: "bootstrap mongo-orchestration" vars: VERSION: "v6.0-perf" TOPOLOGY: "server" SSL: "ssl" - func: "run perf tests" - func: "attach benchmark test results" - func: "send dashboard data" - name: "assign-pr-reviewer" tags: ["pr"] allowed_requesters: ["patch", "github_pr"] commands: - command: shell.exec type: test params: shell: "bash" working_dir: src script: | ${PREPARE_SHELL} set -x export CONFIG=$PROJECT_DIRECTORY/.github/reviewers.txt export SCRIPT="$DRIVERS_TOOLS/.evergreen/github_app/assign-reviewer.sh" bash $SCRIPT -p $CONFIG -h ${github_commit} -o "mongodb" -n "mongo-python-driver" echo '{"results": [{ "status": "PASS", "test_file": "Build", "log_raw": "Test completed" } ]}' > ${PROJECT_DIRECTORY}/test-results.json - name: "check-import-time" tags: ["pr"] commands: - command: shell.exec type: test params: shell: "bash" working_dir: src script: | ${PREPARE_SHELL} set -x export BASE_SHA=${revision} export HEAD_SHA=${github_commit} bash .evergreen/run-import-time-test.sh axes: # Choice of distro - id: platform display_name: OS values: - id: macos-1014 display_name: "macOS 10.14" run_on: macos-1014 variables: skip_EC2_auth_test: true skip_ECS_auth_test: true skip_web_identity_auth_test: true - id: macos-1100 display_name: "macOS 11.00" run_on: macos-1100 variables: skip_EC2_auth_test: true skip_ECS_auth_test: true skip_web_identity_auth_test: true - id: macos-1100-arm64 display_name: "macOS 11.00 Arm64" run_on: macos-1100-arm64 variables: skip_EC2_auth_test: true skip_ECS_auth_test: true skip_web_identity_auth_test: true - id: rhel7 display_name: "RHEL 7.x" run_on: rhel79-small batchtime: 10080 # 7 days - id: rhel8 display_name: "RHEL 8.x" run_on: rhel87-small batchtime: 10080 # 7 days - id: rhel80-fips display_name: "RHEL 8.0 FIPS" run_on: rhel80-fips batchtime: 10080 # 7 days - id: ubuntu-22.04 display_name: "Ubuntu 22.04" run_on: ubuntu2204-small batchtime: 10080 # 7 days - id: ubuntu-20.04 display_name: "Ubuntu 20.04" run_on: ubuntu2004-small batchtime: 10080 # 7 days - id: rhel83-zseries display_name: "RHEL 8.3 (zSeries)" run_on: rhel83-zseries-small batchtime: 10080 # 7 days - id: rhel81-power8 display_name: "RHEL 8.1 (POWER8)" run_on: rhel81-power8-small batchtime: 10080 # 7 days - id: rhel82-arm64 display_name: "RHEL 8.2 (ARM64)" run_on: rhel82-arm64-small batchtime: 10080 # 7 days variables: - id: windows-64-vsMulti-small display_name: "Windows 64" run_on: windows-64-vsMulti-small batchtime: 10080 # 7 days variables: skip_ECS_auth_test: true skip_EC2_auth_test: true skip_web_identity_auth_test: true venv_bin_dir: "Scripts" # Test with authentication? - id: auth display_name: Authentication values: - id: auth display_name: Auth variables: AUTH: "auth" - id: noauth display_name: NoAuth variables: AUTH: "noauth" # Test with SSL? - id: ssl display_name: SSL values: - id: ssl display_name: SSL variables: SSL: "ssl" - id: nossl display_name: NoSSL variables: SSL: "nossl" # Test with Auth + SSL (combined for convenience)? - id: auth-ssl display_name: Auth SSL values: - id: auth-ssl display_name: Auth SSL variables: AUTH: "auth" SSL: "ssl" - id: noauth-nossl display_name: NoAuth NoSSL variables: AUTH: "noauth" SSL: "nossl" # Choice of wire protocol compression support - id: compression display_name: Compression values: - id: snappy display_name: snappy compression variables: COMPRESSORS: "snappy" - id: zlib display_name: zlib compression variables: COMPRESSORS: "zlib" - id: zstd display_name: zstd compression variables: COMPRESSORS: "zstd" # Choice of MongoDB server version - id: mongodb-version display_name: "MongoDB" values: - id: "3.6" display_name: "MongoDB 3.6" variables: VERSION: "3.6" - id: "4.0" display_name: "MongoDB 4.0" variables: VERSION: "4.0" - id: "4.2" display_name: "MongoDB 4.2" variables: VERSION: "4.2" - id: "4.4" display_name: "MongoDB 4.4" variables: VERSION: "4.4" - id: "5.0" display_name: "MongoDB 5.0" variables: VERSION: "5.0" - id: "6.0" display_name: "MongoDB 6.0" variables: VERSION: "6.0" - id: "7.0" display_name: "MongoDB 7.0" variables: VERSION: "7.0" - id: "8.0" display_name: "MongoDB 8.0" variables: VERSION: "8.0" - id: "latest" display_name: "MongoDB latest" variables: VERSION: "latest" - id: "rapid" display_name: "MongoDB rapid" variables: VERSION: "rapid" # Choice of Python runtime version - id: python-version display_name: "Python" values: # Note: always display platform with python-version to avoid ambiguous display names. # Linux - id: "3.7" display_name: "Python 3.7" variables: PYTHON_BINARY: "/opt/python/3.7/bin/python3" - id: "3.8" display_name: "Python 3.8" variables: PYTHON_BINARY: "/opt/python/3.8/bin/python3" - id: "3.9" display_name: "Python 3.9" variables: PYTHON_BINARY: "/opt/python/3.9/bin/python3" - id: "3.10" display_name: "Python 3.10" variables: PYTHON_BINARY: "/opt/python/3.10/bin/python3" - id: "3.11" display_name: "Python 3.11" variables: PYTHON_BINARY: "/opt/python/3.11/bin/python3" - id: "3.12" display_name: "Python 3.12" variables: PYTHON_BINARY: "/opt/python/3.12/bin/python3" - id: "pypy3.8" display_name: "PyPy 3.8" variables: PYTHON_BINARY: "/opt/python/pypy3.8/bin/pypy3" - id: "pypy3.10" display_name: "PyPy 3.10" variables: PYTHON_BINARY: "/opt/python/pypy3.10/bin/pypy3" - id: python-version-windows display_name: "Python" values: - id: "3.7" display_name: "Python 3.7" variables: PYTHON_BINARY: "C:/python/Python37/python.exe" - id: "3.8" display_name: "Python 3.8" variables: PYTHON_BINARY: "C:/python/Python38/python.exe" - id: "3.9" display_name: "Python 3.9" variables: PYTHON_BINARY: "C:/python/Python39/python.exe" - id: "3.10" display_name: "Python 3.10" variables: PYTHON_BINARY: "C:/python/Python310/python.exe" - id: "3.11" display_name: "Python 3.11" variables: PYTHON_BINARY: "C:/python/Python311/python.exe" - id: "3.12" display_name: "Python 3.12" variables: PYTHON_BINARY: "C:/python/Python312/python.exe" - id: python-version-windows-32 display_name: "Python" values: - id: "3.7" display_name: "32-bit Python 3.7" variables: PYTHON_BINARY: "C:/python/32/Python37/python.exe" - id: "3.8" display_name: "32-bit Python 3.8" variables: PYTHON_BINARY: "C:/python/32/Python38/python.exe" - id: "3.9" display_name: "32-bit Python 3.9" variables: PYTHON_BINARY: "C:/python/32/Python39/python.exe" - id: "3.10" display_name: "32-bit Python 3.10" variables: PYTHON_BINARY: "C:/python/32/Python310/python.exe" - id: "3.11" display_name: "32-bit Python 3.11" variables: PYTHON_BINARY: "C:/python/32/Python311/python.exe" - id: "3.12" display_name: "32-bit Python 3.12" variables: PYTHON_BINARY: "C:/python/32/Python312/python.exe" # Choice of mod_wsgi version - id: mod-wsgi-version display_name: "mod_wsgi version" values: - id: "4" display_name: "mod_wsgi 4.x" variables: MOD_WSGI_VERSION: "4" # Choice of Python async framework - id: green-framework display_name: "Green Framework" values: - id: "eventlet" display_name: "Eventlet" variables: GREEN_FRAMEWORK: "eventlet" - id: "gevent" display_name: "Gevent" variables: GREEN_FRAMEWORK: "gevent" # Install and use the driver's C-extensions? - id: c-extensions display_name: "C Extensions" values: - id: "without-c-extensions" display_name: "Without C Extensions" variables: NO_EXT: "1" - id: "with-c-extensions" display_name: "With C Extensions" variables: NO_EXT: "" # Choice of MongoDB storage engine - id: storage-engine display_name: Storage values: - id: mmapv1 display_name: MMAPv1 variables: STORAGE_ENGINE: "mmapv1" - id: inmemory display_name: InMemory variables: STORAGE_ENGINE: "inmemory" # Run with test commands disabled on server? - id: disableTestCommands display_name: Disable test commands values: - id: disabled display_name: disabled variables: DISABLE_TEST_COMMANDS: "1" # Generate coverage report? - id: coverage display_name: "Coverage" values: - id: "coverage" display_name: "Coverage" tags: ["coverage_tag"] variables: COVERAGE: "coverage" # Run encryption tests? - id: encryption display_name: "Encryption" values: - id: "encryption" display_name: "Encryption" tags: ["encryption_tag"] variables: test_encryption: true batchtime: 10080 # 7 days - id: "encryption_pyopenssl" display_name: "Encryption PyOpenSSL" tags: ["encryption_tag"] variables: test_encryption: true test_encryption_pyopenssl: true batchtime: 10080 # 7 days # The path to crypt_shared is stored in the $CRYPT_SHARED_LIB_PATH expansion. - id: "encryption_crypt_shared" display_name: "Encryption shared lib" tags: ["encryption_tag"] variables: test_encryption: true test_crypt_shared: true batchtime: 10080 # 7 days # Run pyopenssl tests? - id: pyopenssl display_name: "PyOpenSSL" values: - id: "enabled" display_name: "PyOpenSSL" variables: test_pyopenssl: true batchtime: 10080 # 7 days - id: versionedApi display_name: "versionedApi" values: # Test against a cluster with requireApiVersion=1. - id: "requireApiVersion1" display_name: "requireApiVersion1" tags: [ "versionedApi_tag" ] variables: # REQUIRE_API_VERSION is set to make drivers-evergreen-tools # start a cluster with the requireApiVersion parameter. REQUIRE_API_VERSION: "1" # MONGODB_API_VERSION is the apiVersion to use in the test suite. MONGODB_API_VERSION: "1" # Test against a cluster with acceptApiVersion2 but without # requireApiVersion, and don't automatically add apiVersion to # clients created in the test suite. - id: "acceptApiVersion2" display_name: "acceptApiVersion2" tags: [ "versionedApi_tag" ] variables: ORCHESTRATION_FILE: "versioned-api-testing.json" # Run load balancer tests? - id: loadbalancer display_name: "Load Balancer" values: - id: "enabled" display_name: "Load Balancer" variables: test_loadbalancer: true batchtime: 10080 # 7 days - id: serverless display_name: "Serverless" values: - id: "original" display_name: "Serverless" variables: test_serverless: true batchtime: 10080 # 7 days - id: "proxy" display_name: "Serverless Proxy" variables: test_serverless: true VAULT_NAME: "serverless_next" IS_SERVERLESS_PROXY: true batchtime: 10080 # 7 days buildvariants: - matrix_name: "tests-fips" matrix_spec: platform: - rhel80-fips auth: "auth" ssl: "ssl" display_name: "${platform} ${auth} ${ssl}" tasks: - "test-fips-standalone" - matrix_name: "test-macos" matrix_spec: platform: # MacOS introduced SSL support with MongoDB >= 3.2. # Older server versions (2.6, 3.0) are supported without SSL. - macos-1014 auth: "*" ssl: "*" exclude_spec: # No point testing with SSL without auth. - platform: macos-1014 auth: "noauth" ssl: "ssl" display_name: "${platform} ${auth} ${ssl}" tasks: - ".latest" - ".8.0" - ".7.0" - ".6.0" - ".5.0" - ".4.4" - ".4.2" - ".4.0" - ".3.6" - matrix_name: "test-macos-arm64" matrix_spec: platform: - macos-1100-arm64 auth-ssl: "*" display_name: "${platform} ${auth-ssl}" tasks: - ".latest" - ".8.0" - ".7.0" - ".6.0" - ".5.0" - ".4.4" - matrix_name: "test-macos-encryption" matrix_spec: platform: - macos-1100 auth: "auth" ssl: "nossl" encryption: "*" display_name: "${encryption} ${platform} ${auth} ${ssl}" tasks: "test-latest-replica_set" rules: - if: encryption: ["encryption", "encryption_crypt_shared"] platform: macos-1100 auth: "auth" ssl: "nossl" then: add_tasks: &encryption-server-versions - ".rapid" - ".latest" - ".8.0" - ".7.0" - ".6.0" - ".5.0" - ".4.4" - ".4.2" - ".4.0" # Test one server version with zSeries, POWER8, and ARM. - matrix_name: "test-different-cpu-architectures" matrix_spec: platform: - rhel83-zseries # Added in 5.0.8 (SERVER-44074) - rhel81-power8 # Added in 4.2.7 (SERVER-44072) - rhel82-arm64 # Added in 4.4.2 (SERVER-48282) auth-ssl: "*" display_name: "${platform} ${auth-ssl}" tasks: - ".6.0" - matrix_name: "tests-python-version-rhel8-test-ssl" matrix_spec: platform: rhel8 python-version: "*" auth-ssl: "*" coverage: "*" display_name: "${python-version} ${platform} ${auth-ssl} ${coverage}" tasks: &all-server-versions - ".rapid" - ".latest" - ".8.0" - ".7.0" - ".6.0" - ".5.0" - ".4.4" - ".4.2" - ".4.0" - ".3.6" - matrix_name: "tests-pyopenssl" matrix_spec: platform: rhel8 python-version: "*" auth: "*" ssl: "ssl" pyopenssl: "*" # Only test "noauth" with Python 3.7. exclude_spec: platform: rhel8 python-version: ["3.8", "3.9", "3.10", "pypy3.8", "pypy3.10"] auth: "noauth" ssl: "ssl" pyopenssl: "*" display_name: "PyOpenSSL ${platform} ${python-version} ${auth}" tasks: - '.replica_set' # Test standalone and sharded only on 7.0. - '.7.0' - matrix_name: "tests-pyopenssl-macOS" matrix_spec: platform: macos-1014 auth: "auth" ssl: "ssl" pyopenssl: "*" display_name: "PyOpenSSL ${platform} ${auth}" tasks: - '.replica_set' - matrix_name: "tests-pyopenssl-windows" matrix_spec: platform: windows-64-vsMulti-small python-version-windows: "*" auth: "auth" ssl: "ssl" pyopenssl: "*" display_name: "PyOpenSSL ${platform} ${python-version-windows} ${auth}" tasks: - '.replica_set' - matrix_name: "tests-python-version-rhel8-test-encryption" matrix_spec: platform: rhel8 python-version: "*" auth-ssl: noauth-nossl # TODO: dependency error for 'coverage-report' task: # dependency tests-python-version-rhel62-test-encryption_.../test-2.6-standalone is not present in the project config # coverage: "*" encryption: "*" display_name: "${encryption} ${python-version} ${platform} ${auth-ssl}" tasks: "test-latest-replica_set" rules: - if: encryption: ["encryption", "encryption_crypt_shared"] platform: rhel8 auth-ssl: noauth-nossl python-version: "*" then: add_tasks: *encryption-server-versions - matrix_name: "tests-python-version-rhel8-without-c-extensions" matrix_spec: platform: rhel8 python-version: "*" c-extensions: without-c-extensions auth-ssl: noauth-nossl coverage: "*" exclude_spec: # These interpreters are always tested without extensions. - platform: rhel8 python-version: ["pypy3.8", "pypy3.10"] c-extensions: "*" auth-ssl: "*" coverage: "*" display_name: "${c-extensions} ${python-version} ${platform} ${auth} ${ssl} ${coverage}" tasks: *all-server-versions - matrix_name: "tests-python-version-rhel8-compression" matrix_spec: platform: rhel8 python-version: "*" c-extensions: "*" compression: "*" exclude_spec: # These interpreters are always tested without extensions. - platform: rhel8 python-version: ["pypy3.8", "pypy3.10"] c-extensions: "with-c-extensions" compression: "*" display_name: "${compression} ${c-extensions} ${python-version} ${platform}" tasks: - "test-latest-standalone" - "test-5.0-standalone" - "test-4.4-standalone" - "test-4.2-standalone" rules: # Server versions 3.6 and 4.0 support snappy and zlib. - if: python-version: "*" c-extensions: "*" compression: ["snappy", "zlib"] then: add_tasks: - "test-4.0-standalone" - "test-3.6-standalone" - matrix_name: "tests-python-version-green-framework-rhel8" matrix_spec: platform: rhel8 python-version: "*" green-framework: "*" auth-ssl: "*" exclude_spec: # Don't test green frameworks on these Python versions. - platform: rhel8 python-version: ["pypy3.8", "pypy3.10"] green-framework: "*" auth-ssl: "*" display_name: "${green-framework} ${python-version} ${platform} ${auth-ssl}" tasks: *all-server-versions - matrix_name: "tests-windows-python-version" matrix_spec: platform: windows-64-vsMulti-small python-version-windows: "*" auth-ssl: "*" display_name: "${platform} ${python-version-windows} ${auth-ssl}" tasks: *all-server-versions - matrix_name: "tests-windows-python-version-32-bit" matrix_spec: platform: windows-64-vsMulti-small python-version-windows-32: "*" auth-ssl: "*" display_name: "${platform} ${python-version-windows-32} ${auth-ssl}" tasks: *all-server-versions - matrix_name: "tests-python-version-supports-openssl-102-test-ssl" matrix_spec: platform: rhel7 # Python 3.10+ requires OpenSSL 1.1.1+ python-version: ["3.7", "3.8", "3.9", "pypy3.8", "pypy3.10"] auth-ssl: "*" display_name: "OpenSSL 1.0.2 ${python-version} ${platform} ${auth-ssl}" tasks: - ".5.0" - matrix_name: "tests-windows-encryption" matrix_spec: platform: windows-64-vsMulti-small python-version-windows: "*" auth-ssl: "*" encryption: "*" display_name: "${encryption} ${platform} ${python-version-windows} ${auth-ssl}" tasks: "test-latest-replica_set" rules: - if: encryption: ["encryption", "encryption_crypt_shared"] platform: windows-64-vsMulti-small python-version-windows: "*" auth-ssl: "*" then: add_tasks: *encryption-server-versions # Storage engine tests on RHEL 8.4 (x86_64) with Python 3.7. - matrix_name: "tests-storage-engines" matrix_spec: platform: rhel8 storage-engine: "*" python-version: 3.7 display_name: "Storage ${storage-engine} ${python-version} ${platform}" rules: - if: platform: rhel8 storage-engine: ["inmemory"] python-version: "*" then: add_tasks: - "test-latest-standalone" - "test-8.0-standalone" - "test-7.0-standalone" - "test-6.0-standalone" - "test-5.0-standalone" - "test-4.4-standalone" - "test-4.2-standalone" - "test-4.0-standalone" - "test-3.6-standalone" - if: # MongoDB 4.2 drops support for MMAPv1 platform: rhel8 storage-engine: ["mmapv1"] python-version: "*" then: add_tasks: - "test-4.0-standalone" - "test-4.0-replica_set" - "test-3.6-standalone" - "test-3.6-replica_set" # enableTestCommands=0 tests on RHEL 8.4 (x86_64) with Python 3.7. - matrix_name: "test-disableTestCommands" matrix_spec: platform: rhel8 disableTestCommands: "*" python-version: "3.7" display_name: "Disable test commands ${python-version} ${platform}" tasks: - ".latest" - matrix_name: "test-linux-enterprise-auth" matrix_spec: platform: rhel8 python-version: "*" auth: "auth" display_name: "Enterprise ${auth} ${platform} ${python-version}" tasks: - name: "test-enterprise-auth" - matrix_name: "tests-windows-enterprise-auth" matrix_spec: platform: windows-64-vsMulti-small python-version-windows: "*" auth: "auth" display_name: "Enterprise ${auth} ${platform} ${python-version-windows}" tasks: - name: "test-enterprise-auth" - matrix_name: "test-search-index-helpers" matrix_spec: platform: rhel8 python-version: "3.8" display_name: "Search Index Helpers ${platform}" tasks: - name: "test_atlas_task_group_search_indexes" - matrix_name: "tests-mod-wsgi" matrix_spec: platform: ubuntu-22.04 python-version: ["3.7", "3.8", "3.9", "3.10", "3.11", "3.12"] mod-wsgi-version: "*" display_name: "${mod-wsgi-version} ${python-version} ${platform}" tasks: - name: "mod-wsgi-standalone" - name: "mod-wsgi-replica-set" - name: "mod-wsgi-embedded-mode-standalone" - name: "mod-wsgi-embedded-mode-replica-set" - matrix_name: "mockupdb-tests" matrix_spec: platform: rhel8 python-version: 3.7 display_name: "MockupDB Tests" tasks: - name: "mockupdb" - matrix_name: "tests-doctests" matrix_spec: platform: rhel8 python-version: ["3.8"] display_name: "Doctests ${python-version} ${platform}" tasks: - name: "doctests" - name: "no-server" display_name: "No server test" run_on: - rhel84-small tasks: - name: "no-server" - name: "Coverage Report" display_name: "Coverage Report" run_on: - rhel84-small tasks: - name: "coverage-report" - matrix_name: "atlas-connect" matrix_spec: platform: rhel8 python-version: "*" display_name: "Atlas connect ${python-version} ${platform}" tasks: - name: "atlas-connect" - matrix_name: "serverless" matrix_spec: platform: rhel8 python-version: "*" auth-ssl: auth-ssl serverless: "original" display_name: "${serverless} ${python-version} ${platform}" tasks: - "serverless_task_group" - matrix_name: "serverless_proxy" matrix_spec: platform: rhel8 python-version: ["3.7", "3.10"] auth-ssl: auth-ssl serverless: "proxy" display_name: "${serverless} ${python-version} ${platform}" tasks: - "serverless_task_group" - matrix_name: "data-lake-spec-tests" matrix_spec: platform: ubuntu-22.04 python-version: ["3.7", "3.10"] auth: "auth" c-extensions: "*" display_name: "Atlas Data Lake ${python-version} ${c-extensions}" tasks: - name: atlas-data-lake-tests - matrix_name: "stable-api-tests" matrix_spec: platform: rhel8 python-version: ["3.7", "3.10"] auth: "auth" versionedApi: "*" display_name: "Versioned API ${versionedApi} ${python-version}" batchtime: 10080 # 7 days tasks: # Versioned API was introduced in MongoDB 4.7 - "test-latest-standalone" - "test-5.0-standalone" - matrix_name: "ocsp-test" matrix_spec: platform: rhel8 python-version: ["3.7", "3.10", "pypy3.8", "pypy3.10"] mongodb-version: ["4.4", "5.0", "6.0", "7.0", "8.0", "latest"] auth: "noauth" ssl: "ssl" display_name: "OCSP test ${platform} ${python-version} ${mongodb-version}" batchtime: 20160 # 14 days tasks: - name: ".ocsp" - matrix_name: "ocsp-test-windows" matrix_spec: platform: windows-64-vsMulti-small python-version-windows: ["3.7", "3.10"] mongodb-version: ["4.4", "5.0", "6.0", "7.0", "8.0", "latest"] auth: "noauth" ssl: "ssl" display_name: "OCSP test ${platform} ${python-version-windows} ${mongodb-version}" batchtime: 20160 # 14 days tasks: # Windows MongoDB servers do not staple OCSP responses and only support RSA. - name: ".ocsp-rsa !.ocsp-staple" - matrix_name: "ocsp-test-macos" matrix_spec: platform: macos-1014 mongodb-version: ["4.4", "5.0", "6.0", "7.0", "8.0", "latest"] auth: "noauth" ssl: "ssl" display_name: "OCSP test ${platform} ${mongodb-version}" batchtime: 20160 # 14 days tasks: # macOS MongoDB servers do not staple OCSP responses and only support RSA. - name: ".ocsp-rsa !.ocsp-staple" - matrix_name: "oidc-auth-test" matrix_spec: platform: [ rhel8, macos-1100, windows-64-vsMulti-small ] display_name: "OIDC Auth ${platform}" tasks: - name: testoidc_task_group batchtime: 20160 # 14 days - name: testazureoidc-variant display_name: "OIDC Auth Azure" run_on: ubuntu2204-small tasks: - name: testazureoidc_task_group batchtime: 20160 # Use a batchtime of 14 days as suggested by the CSFLE test README - name: testgcpoidc-variant display_name: "OIDC Auth GCP" run_on: ubuntu2204-small tasks: - name: testgcpoidc_task_group batchtime: 20160 # Use a batchtime of 14 days as suggested by the CSFLE test README - matrix_name: "aws-auth-test" matrix_spec: platform: [ubuntu-20.04] python-version: ["3.9"] display_name: "MONGODB-AWS Auth ${platform} ${python-version}" tasks: - name: "aws-auth-test-4.4" - name: "aws-auth-test-5.0" - name: "aws-auth-test-6.0" - name: "aws-auth-test-7.0" - name: "aws-auth-test-8.0" - name: "aws-auth-test-rapid" - name: "aws-auth-test-latest" - matrix_name: "aws-auth-test-mac" matrix_spec: platform: [macos-1014] display_name: "MONGODB-AWS Auth ${platform} ${python-version-mac}" tasks: - name: "aws-auth-test-4.4" - name: "aws-auth-test-5.0" - name: "aws-auth-test-6.0" - name: "aws-auth-test-7.0" - name: "aws-auth-test-8.0" - name: "aws-auth-test-rapid" - name: "aws-auth-test-latest" - matrix_name: "aws-auth-test-windows" matrix_spec: platform: [windows-64-vsMulti-small] python-version-windows: "*" display_name: "MONGODB-AWS Auth ${platform} ${python-version-windows}" tasks: - name: "aws-auth-test-4.4" - name: "aws-auth-test-5.0" - name: "aws-auth-test-6.0" - name: "aws-auth-test-7.0" - name: "aws-auth-test-8.0" - name: "aws-auth-test-rapid" - name: "aws-auth-test-latest" - matrix_name: "load-balancer" matrix_spec: platform: rhel8 mongodb-version: ["6.0", "7.0", "8.0", "rapid", "latest"] auth-ssl: "*" python-version: "*" loadbalancer: "*" display_name: "Load Balancer ${platform} ${python-version} ${mongodb-version} ${auth-ssl}" tasks: - name: "load-balancer-test" - name: testgcpkms-variant display_name: "GCP KMS" run_on: - debian10-small tasks: - name: testgcpkms_task_group batchtime: 20160 # Use a batchtime of 14 days as suggested by the CSFLE test README - testgcpkms-fail-task - name: testazurekms-variant display_name: "Azure KMS" run_on: rhel87-small tasks: - name: testazurekms_task_group batchtime: 20160 # Use a batchtime of 14 days as suggested by the CSFLE test README - testazurekms-fail-task - name: rhel8-test-lambda display_name: AWS Lambda handler tests run_on: rhel87-small tasks: - name: test_aws_lambda_task_group - name: rhel8-pr-assign-reviewer display_name: Assign PR Reviewer run_on: rhel87-small tasks: - name: "assign-pr-reviewer" - name: rhel8-import-time display_name: Import Time Check run_on: rhel87-small tasks: - name: "check-import-time" - name: Release display_name: Release batchtime: 20160 # 14 days tags: ["release_tag"] tasks: - ".release_tag" - name: "perf-tests" display_name: "Performance Benchmark Tests" batchtime: 10080 # 7 days run_on: rhel90-dbx-perf-large tasks: - name: "perf-6.0-standalone" - name: "perf-6.0-standalone-ssl" # Platform notes # i386 builds of OpenSSL or Cyrus SASL are not available # Debian 8.1 only supports MongoDB 3.4+ # SUSE12 s390x is only supported by MongoDB 3.4+ # No enterprise build for Archlinux, SSL not available # RHEL 7.6 and RHEL 8.4 only supports 3.6+. # RHEL 7 only supports 2.6+ # RHEL 7.1 ppc64le is only supported by MongoDB 3.2+ # RHEL 7.2 s390x is only supported by MongoDB 3.4+ # Solaris MongoDB SSL builds are not available # Darwin MongoDB SSL builds are not available for 2.6 # SUSE12 x86_64 is only supported by MongoDB 3.2+ # vim: set et sw=2 ts=2 : mongodb-mongo-python-driver-509e9b7/.evergreen/install-dependencies.sh000066400000000000000000000012301462766011000261170ustar00rootroot00000000000000#!/bin/bash set -o xtrace # Write all commands first to stderr set -o errexit # Exit the script with error if any of the commands fail # Copy PyMongo's test certificates over driver-evergreen-tools' cp ${PROJECT_DIRECTORY}/test/certificates/* ${DRIVERS_TOOLS}/.evergreen/x509gen/ # Replace MongoOrchestration's client certificate. cp ${PROJECT_DIRECTORY}/test/certificates/client.pem ${MONGO_ORCHESTRATION_HOME}/lib/client.pem if [ -w /etc/hosts ]; then SUDO="" else SUDO="sudo" fi # Add 'server' and 'hostname_not_in_cert' as a hostnames echo "127.0.0.1 server" | $SUDO tee -a /etc/hosts echo "127.0.0.1 hostname_not_in_cert" | $SUDO tee -a /etc/hosts mongodb-mongo-python-driver-509e9b7/.evergreen/release.sh000077500000000000000000000003341462766011000234540ustar00rootroot00000000000000#!/bin/bash -ex if [ "$(uname -s)" = "Darwin" ]; then .evergreen/build-mac.sh elif [ "Windows_NT" = "$OS" ]; then # Magic variable in cygwin .evergreen/build-windows.sh else .evergreen/build-manylinux.sh fi mongodb-mongo-python-driver-509e9b7/.evergreen/resync-specs.sh000077500000000000000000000157331462766011000244630ustar00rootroot00000000000000#!/bin/bash # exit when any command fails set -e PYMONGO=$(dirname "$(cd "$(dirname "$0")"; pwd)") SPECS=${MDB_SPECS:-~/Work/specifications} help (){ echo "Usage: resync_specs.sh [-bcsp] spec" echo "Required arguments:" echo " spec determines which folder the spec tests will be copied from." echo "Optional flags:" echo " -b is used to add a string to the blocklist for that next run. Can be used" echo " any number of times on a single command to block multiple patterns." echo " You can use any regex pattern (it is passed to 'grep -Ev')." echo " -c is used to set a branch or commit that will be checked out in the" echo " specifications repo before copying." echo " -s is used to set a unique path to the specs repo for that specific" echo " run." echo "Notes:" echo "You can export the environment variable MDB_SPECS to set the specs" echo " repo similar to -s, but this will persist between runs until you " echo "unset it." } # Parse flag args BRANCH='' BLOCKLIST='.*\.yml' while getopts 'b:c:s:' flag; do case "${flag}" in b) BLOCKLIST+="|$OPTARG" ;; c) BRANCH="${OPTARG}" ;; s) SPECS="${OPTARG}" ;; *) help; exit 0 ;; esac done shift $((OPTIND-1)) if [ -n "$BRANCH" ] then git -C $SPECS checkout $BRANCH fi # Ensure the JSON files are up to date. cd $SPECS/source make cd - # cpjson unified-test-format/tests/invalid unified-test-format/invalid # * param1: Path to spec tests dir in specifications repo # * param2: Path to where the corresponding tests live in Python. cpjson () { find "$PYMONGO"/test/$2 -type f -delete cd "$SPECS"/source/$1 find . -name '*.json' | grep -Ev "${BLOCKLIST}" | cpio -pdm \ $PYMONGO/test/$2 printf "\nIgnored files for ${PWD}:\n" IGNORED_FILES="$(printf "\n%s\n" "$(diff <(find . -name '*.json' | sort) \ <(find . -name '*.json' | grep -Ev "${BLOCKLIST}" | sort))" | \ sed -e '/^[0-9]/d' | sed -e 's|< ./||g' )" printf "%s\n" $IGNORED_FILES cd "$PYMONGO"/test/$2 printf "%s\n" $IGNORED_FILES | xargs git checkout master } for spec in "$@" do # Match the spec dir name, the python test dir name, and/or common abbreviations. case "$spec" in auth) cpjson auth/tests/ auth ;; atlas-data-lake-testing|data_lake) cpjson atlas-data-lake-testing/tests/ data_lake ;; bson-corpus|bson_corpus) cpjson bson-corpus/tests/ bson_corpus ;; max-staleness|max_staleness) cpjson max-staleness/tests/ max_staleness ;; collection-management|collection_management) cpjson collection-management/tests/ collection_management ;; connection-string|connection_string) cpjson connection-string/tests/ connection_string/test ;; change-streams|change_streams) cpjson change-streams/tests/ change_streams/ ;; client-side-encryption|csfle|fle) cpjson client-side-encryption/tests/ client-side-encryption/spec cpjson client-side-encryption/corpus/ client-side-encryption/corpus cpjson client-side-encryption/external/ client-side-encryption/external cpjson client-side-encryption/limits/ client-side-encryption/limits cpjson client-side-encryption/etc/data client-side-encryption/etc/data ;; connection-monitoring|connection_monitoring) cpjson connection-monitoring-and-pooling/tests/cmap-format connection_monitoring ;; connection-logging|connection_logging) cpjson connection-monitoring-and-pooling/tests/logging connection_logging ;; cmap|CMAP|connection-monitoring-and-pooling) cpjson connection-monitoring-and-pooling/tests/logging connection_logging cpjson connection-monitoring-and-pooling/tests/cmap-format connection_monitoring rm $PYMONGO/test/connection_monitoring/wait-queue-fairness.json # PYTHON-1873 ;; apm|APM|command-monitoring|command_monitoring) cpjson command-logging-and-monitoring/tests/monitoring command_monitoring ;; command-logging|command_logging) cpjson command-logging-and-monitoring/tests/logging command_logging ;; clam|CLAM|command-logging-and-monitoring|command_logging_and_monitoring) cpjson command-logging-and-monitoring/tests/logging command_logging cpjson command-logging-and-monitoring/tests/monitoring command_monitoring ;; crud|CRUD) cpjson crud/tests/ crud ;; csot|CSOT|client-side-operations-timeout) cpjson client-side-operations-timeout/tests csot ;; gridfs) cpjson gridfs/tests gridfs ;; index|index-management) cpjson index-management/tests index_management ;; load-balancers|load_balancer) cpjson load-balancers/tests load_balancer ;; srv|SRV|initial-dns-seedlist-discovery|srv_seedlist) cpjson initial-dns-seedlist-discovery/tests/ srv_seedlist ;; retryable-reads|retryable_reads) cpjson retryable-reads/tests/ retryable_reads ;; retryable-writes|retryable_writes) cpjson retryable-writes/tests/ retryable_writes ;; run-command|run_command) cpjson run-command/tests/ run_command ;; sdam|SDAM|server-discovery-and-monitoring|discovery_and_monitoring) cpjson server-discovery-and-monitoring/tests/errors \ discovery_and_monitoring/errors cpjson server-discovery-and-monitoring/tests/rs \ discovery_and_monitoring/rs cpjson server-discovery-and-monitoring/tests/sharded \ discovery_and_monitoring/sharded cpjson server-discovery-and-monitoring/tests/single \ discovery_and_monitoring/single cpjson server-discovery-and-monitoring/tests/unified \ discovery_and_monitoring/unified cpjson server-discovery-and-monitoring/tests/load-balanced \ discovery_and_monitoring/load-balanced ;; sdam-monitoring|sdam_monitoring) cpjson server-discovery-and-monitoring/tests/monitoring sdam_monitoring ;; server-selection|server_selection) cpjson server-selection/tests/ server_selection rm -rf $PYMONGO/test/server_selection/logging cpjson server-selection/tests/logging server_selection_logging ;; server-selection-logging|server_selection_logging) cpjson server-selection/tests/logging server_selection_logging ;; sessions) cpjson sessions/tests/ sessions ;; transactions|transactions-convenient-api) cpjson transactions/tests/ transactions cpjson transactions-convenient-api/tests/ transactions-convenient-api rm $PYMONGO/test/transactions/legacy/errors-client.json # PYTHON-1894 ;; unified|unified-test-format) cpjson unified-test-format/tests/ unified-test-format/ ;; uri|uri-options|uri_options) cpjson uri-options/tests uri_options cp "$SPECS"/source/uri-options/tests/*.pem $PYMONGO/test/uri_options ;; stable-api|versioned-api) cpjson versioned-api/tests versioned-api ;; *) echo "Do not know how to resync spec tests for '${spec}'" help ;; esac done mongodb-mongo-python-driver-509e9b7/.evergreen/run-azurekms-fail-test.sh000066400000000000000000000007471462766011000263720ustar00rootroot00000000000000#!/bin/bash set -o errexit # Exit the script with error if any of the commands fail . $DRIVERS_TOOLS/.evergreen/csfle/azurekms/setup-secrets.sh PYTHON_BINARY=/opt/mongodbtoolchain/v4/bin/python3 \ KEY_NAME="${AZUREKMS_KEYNAME}" \ KEY_VAULT_ENDPOINT="${AZUREKMS_KEYVAULTENDPOINT}" \ LIBMONGOCRYPT_URL=https://s3.amazonaws.com/mciuploads/libmongocrypt/debian10/master/latest/libmongocrypt.tar.gz \ SUCCESS=false TEST_FLE_AZURE_AUTO=1 \ ./.evergreen/tox.sh -m test-eg mongodb-mongo-python-driver-509e9b7/.evergreen/run-azurekms-test.sh000066400000000000000000000021451462766011000254530ustar00rootroot00000000000000#!/bin/bash set -o errexit # Exit the script with error if any of the commands fail source ${DRIVERS_TOOLS}/.evergreen/csfle/azurekms/secrets-export.sh echo "Copying files ... begin" export AZUREKMS_RESOURCEGROUP=${AZUREKMS_RESOURCEGROUP} export AZUREKMS_VMNAME=${AZUREKMS_VMNAME} export AZUREKMS_PRIVATEKEYPATH=/tmp/testazurekms_privatekey tar czf /tmp/mongo-python-driver.tgz . # shellcheck disable=SC2088 AZUREKMS_SRC="/tmp/mongo-python-driver.tgz" AZUREKMS_DST="~/" \ $DRIVERS_TOOLS/.evergreen/csfle/azurekms/copy-file.sh echo "Copying files ... end" echo "Untarring file ... begin" AZUREKMS_CMD="tar xf mongo-python-driver.tgz" \ $DRIVERS_TOOLS/.evergreen/csfle/azurekms/run-command.sh echo "Untarring file ... end" echo "Running test ... begin" AZUREKMS_CMD="KEY_NAME=\"$AZUREKMS_KEYNAME\" KEY_VAULT_ENDPOINT=\"$AZUREKMS_KEYVAULTENDPOINT\" LIBMONGOCRYPT_URL=https://s3.amazonaws.com/mciuploads/libmongocrypt/debian10/master/latest/libmongocrypt.tar.gz SUCCESS=true TEST_FLE_AZURE_AUTO=1 ./.evergreen/tox.sh -m test-eg" \ $DRIVERS_TOOLS/.evergreen/csfle/azurekms/run-command.sh echo "Running test ... end" mongodb-mongo-python-driver-509e9b7/.evergreen/run-deployed-lambda-aws-tests.sh000066400000000000000000000004001462766011000276000ustar00rootroot00000000000000#!/bin/bash set -o errexit # Exit the script with error if any of the commands fail export PATH="/opt/python/3.9/bin:${PATH}" python --version pushd ./test/lambda . build.sh popd . ${DRIVERS_TOOLS}/.evergreen/aws_lambda/run-deployed-lambda-aws-tests.sh mongodb-mongo-python-driver-509e9b7/.evergreen/run-gcpkms-test.sh000066400000000000000000000017471462766011000251050ustar00rootroot00000000000000#!/bin/bash set -o errexit # Exit the script with error if any of the commands fail source ${DRIVERS_TOOLS}/.evergreen/csfle/gcpkms/secrets-export.sh echo "Copying files ... begin" export GCPKMS_GCLOUD=${GCPKMS_GCLOUD} export GCPKMS_PROJECT=${GCPKMS_PROJECT} export GCPKMS_ZONE=${GCPKMS_ZONE} export GCPKMS_INSTANCENAME=${GCPKMS_INSTANCENAME} tar czf /tmp/mongo-python-driver.tgz . GCPKMS_SRC=/tmp/mongo-python-driver.tgz GCPKMS_DST=$GCPKMS_INSTANCENAME: $DRIVERS_TOOLS/.evergreen/csfle/gcpkms/copy-file.sh echo "Copying files ... end" echo "Untarring file ... begin" GCPKMS_CMD="tar xf mongo-python-driver.tgz" $DRIVERS_TOOLS/.evergreen/csfle/gcpkms/run-command.sh echo "Untarring file ... end" echo "Running test ... begin" GCPKMS_CMD="SUCCESS=true TEST_FLE_GCP_AUTO=1 LIBMONGOCRYPT_URL=https://s3.amazonaws.com/mciuploads/libmongocrypt/debian10/master/latest/libmongocrypt.tar.gz ./.evergreen/tox.sh -m test-eg" $DRIVERS_TOOLS/.evergreen/csfle/gcpkms/run-command.sh echo "Running test ... end" mongodb-mongo-python-driver-509e9b7/.evergreen/run-import-time-test.sh000077500000000000000000000014471462766011000260670ustar00rootroot00000000000000#!/bin/bash -ex set -o errexit # Exit the script with error if any of the commands fail set -x . .evergreen/utils.sh if [ -z "$PYTHON_BINARY" ]; then PYTHON_BINARY=$(find_python3) fi # Use the previous commit if this was not a PR run. if [ "$BASE_SHA" == "$HEAD_SHA" ]; then BASE_SHA=$(git rev-parse HEAD~1) fi function get_import_time() { local log_file createvirtualenv "$PYTHON_BINARY" import-venv python -m pip install -q ".[aws,encryption,gssapi,ocsp,snappy,zstd]" # Import once to cache modules python -c "import pymongo" log_file="pymongo-$1.log" python -X importtime -c "import pymongo" 2> $log_file } get_import_time $HEAD_SHA git checkout $BASE_SHA get_import_time $BASE_SHA git checkout $HEAD_SHA python tools/compare_import_time.py $HEAD_SHA $BASE_SHA mongodb-mongo-python-driver-509e9b7/.evergreen/run-mod-wsgi-tests.sh000066400000000000000000000035751462766011000255330ustar00rootroot00000000000000#!/bin/bash set -o xtrace set -o errexit APACHE=$(command -v apache2 || command -v /usr/lib/apache2/mpm-prefork/apache2) || true if [ -n "$APACHE" ]; then APACHE_CONFIG=apache24ubuntu161404.conf else APACHE=$(command -v httpd) || true if [ -z "$APACHE" ]; then echo "Could not find apache2 binary" exit 1 else APACHE_CONFIG=apache22amazon.conf fi fi PYTHON_VERSION=$(${PYTHON_BINARY} -c "import sys; sys.stdout.write('.'.join(str(val) for val in sys.version_info[:2]))") # Ensure the C extensions are installed. ${PYTHON_BINARY} setup.py build_ext -i export MOD_WSGI_SO=/opt/python/mod_wsgi/python_version/$PYTHON_VERSION/mod_wsgi_version/$MOD_WSGI_VERSION/mod_wsgi.so export PYTHONHOME=/opt/python/$PYTHON_VERSION # If MOD_WSGI_EMBEDDED is set use the default embedded mode behavior instead # of daemon mode (WSGIDaemonProcess). if [ -n "$MOD_WSGI_EMBEDDED" ]; then export MOD_WSGI_CONF=mod_wsgi_test_embedded.conf else export MOD_WSGI_CONF=mod_wsgi_test.conf fi cd .. $APACHE -k start -f ${PROJECT_DIRECTORY}/test/mod_wsgi_test/${APACHE_CONFIG} trap '$APACHE -k stop -f ${PROJECT_DIRECTORY}/test/mod_wsgi_test/${APACHE_CONFIG}' EXIT HUP wget -t 1 -T 10 -O - "http://localhost:8080/interpreter1${PROJECT_DIRECTORY}" || (cat error_log && exit 1) wget -t 1 -T 10 -O - "http://localhost:8080/interpreter2${PROJECT_DIRECTORY}" || (cat error_log && exit 1) ${PYTHON_BINARY} ${PROJECT_DIRECTORY}/test/mod_wsgi_test/test_client.py -n 25000 -t 100 parallel \ http://localhost:8080/interpreter1${PROJECT_DIRECTORY} http://localhost:8080/interpreter2${PROJECT_DIRECTORY} || \ (tail -n 100 error_log && exit 1) ${PYTHON_BINARY} ${PROJECT_DIRECTORY}/test/mod_wsgi_test/test_client.py -n 25000 serial \ http://localhost:8080/interpreter1${PROJECT_DIRECTORY} http://localhost:8080/interpreter2${PROJECT_DIRECTORY} || \ (tail -n 100 error_log && exit 1) mongodb-mongo-python-driver-509e9b7/.evergreen/run-mongodb-aws-ecs-test.sh000077500000000000000000000016111462766011000265770ustar00rootroot00000000000000#!/bin/bash # Don't trace since the URI contains a password that shouldn't show up in the logs set -o errexit # Exit the script with error if any of the commands fail ############################################ # Main Program # ############################################ if [[ -z "$1" ]]; then echo "usage: $0 " exit 1 fi export MONGODB_URI="$1" if echo "$MONGODB_URI" | grep -q "@"; then echo "MONGODB_URI unexpectedly contains user credentials in ECS test!"; exit 1 fi # Now we can safely enable xtrace set -o xtrace # Install python with pip. PYTHON_VER="python3.9" apt-get update apt-get install $PYTHON_VER python3-pip build-essential $PYTHON_VER-dev -y export PYTHON_BINARY=$PYTHON_VER export TEST_AUTH_AWS=1 export AUTH="auth" export SET_XTRACE_ON=1 cd src $PYTHON_BINARY -m pip install -q --user tox bash .evergreen/tox.sh -m test-eg mongodb-mongo-python-driver-509e9b7/.evergreen/run-mongodb-aws-test.sh000077500000000000000000000014131462766011000260270ustar00rootroot00000000000000#!/bin/bash set -o xtrace set -o errexit # Exit the script with error if any of the commands fail ############################################ # Main Program # ############################################ # Supported/used environment variables: # MONGODB_URI Set the URI, including an optional username/password to use # to connect to the server via MONGODB-AWS authentication # mechanism. # PYTHON_BINARY The Python version to use. echo "Running MONGODB-AWS authentication tests" # Handle credentials and environment setup. . $DRIVERS_TOOLS/.evergreen/auth_aws/aws_setup.sh $1 # show test output set -x export TEST_AUTH_AWS=1 export AUTH="auth" export SET_XTRACE_ON=1 bash ./.evergreen/tox.sh -m test-eg mongodb-mongo-python-driver-509e9b7/.evergreen/run-mongodb-oidc-test.sh000077500000000000000000000012431462766011000261540ustar00rootroot00000000000000#!/bin/bash set +x # Disable debug trace set -eu echo "Running MONGODB-OIDC authentication tests" OIDC_ENV=${OIDC_ENV:-"test"} if [ $OIDC_ENV == "test" ]; then # Make sure DRIVERS_TOOLS is set. if [ -z "$DRIVERS_TOOLS" ]; then echo "Must specify DRIVERS_TOOLS" exit 1 fi source ${DRIVERS_TOOLS}/.evergreen/auth_oidc/secrets-export.sh elif [ $OIDC_ENV == "azure" ]; then source ./env.sh elif [ $OIDC_ENV == "gcp" ]; then source ./secrets-export.sh else echo "Unrecognized OIDC_ENV $OIDC_ENV" exit 1 fi export TEST_AUTH_OIDC=1 export COVERAGE=1 export AUTH="auth" bash ./.evergreen/tox.sh -m test-eg -- "${@:1}" mongodb-mongo-python-driver-509e9b7/.evergreen/run-perf-tests.sh000066400000000000000000000007551462766011000247360ustar00rootroot00000000000000#!/bin/bash set -o xtrace set -o errexit git clone --depth 1 https://github.com/mongodb/specifications.git pushd specifications/source/benchmarking/data tar xf extended_bson.tgz tar xf parallel.tgz tar xf single_and_multi_document.tgz popd export TEST_PATH="${PROJECT_DIRECTORY}/specifications/source/benchmarking/data" export OUTPUT_FILE="${PROJECT_DIRECTORY}/results.json" export PYTHON_BINARY=/opt/mongodbtoolchain/v4/bin/python3 export PERF_TEST=1 bash ./.evergreen/tox.sh -m test-eg mongodb-mongo-python-driver-509e9b7/.evergreen/run-tests.sh000077500000000000000000000236631462766011000240120ustar00rootroot00000000000000#!/bin/bash set -o errexit # Exit the script with error if any of the commands fail set -o xtrace # Note: It is assumed that you have already set up a virtual environment before running this file. # Supported/used environment variables: # AUTH Set to enable authentication. Defaults to "noauth" # SSL Set to enable SSL. Defaults to "nossl" # GREEN_FRAMEWORK The green framework to test with, if any. # COVERAGE If non-empty, run the test suite with coverage. # COMPRESSORS If non-empty, install appropriate compressor. # LIBMONGOCRYPT_URL The URL to download libmongocrypt. # TEST_DATA_LAKE If non-empty, run data lake tests. # TEST_ENCRYPTION If non-empty, run encryption tests. # TEST_CRYPT_SHARED If non-empty, install crypt_shared lib. # TEST_SERVERLESS If non-empy, test on serverless. # TEST_LOADBALANCER If non-empy, test load balancing. # TEST_FLE_AZURE_AUTO If non-empy, test auto FLE on Azure # TEST_FLE_GCP_AUTO If non-empy, test auto FLE on GCP # TEST_PYOPENSSL If non-empy, test with PyOpenSSL # TEST_ENTERPRISE_AUTH If non-empty, test with Enterprise Auth # TEST_AUTH_AWS If non-empty, test AWS Auth Mechanism # TEST_AUTH_OIDC If non-empty, test OIDC Auth Mechanism # TEST_PERF If non-empty, run performance tests # TEST_OCSP If non-empty, run OCSP tests # TEST_ATLAS If non-empty, test Atlas connections # TEST_INDEX_MANAGEMENT If non-empty, run index management tests # TEST_ENCRYPTION_PYOPENSSL If non-empy, test encryption with PyOpenSSL AUTH=${AUTH:-noauth} SSL=${SSL:-nossl} TEST_ARGS="${*:1}" PYTHON=$(which python) # TODO: Remove when we drop PyPy 3.8 support. OLD_PYPY=$(python -c "import sys; print(sys.implementation.name.lower() == 'pypy' and sys.implementation.version < (7, 3, 12))") export PIP_QUIET=1 # Quiet by default export PIP_PREFER_BINARY=1 # Prefer binary dists by default python -c "import sys; sys.exit(sys.prefix == sys.base_prefix)" || (echo "Not inside a virtual env!"; exit 1) # Try to source local Drivers Secrets if [ -f ./secrets-export.sh ]; then echo "Sourcing secrets" source ./secrets-export.sh else echo "Not sourcing secrets" fi if [ "$AUTH" != "noauth" ]; then set +x if [ ! -z "$TEST_DATA_LAKE" ]; then export DB_USER="mhuser" export DB_PASSWORD="pencil" elif [ ! -z "$TEST_SERVERLESS" ]; then source ${DRIVERS_TOOLS}/.evergreen/serverless/secrets-export.sh export DB_USER=$SERVERLESS_ATLAS_USER export DB_PASSWORD=$SERVERLESS_ATLAS_PASSWORD export MONGODB_URI="$SERVERLESS_URI" echo "MONGODB_URI=$MONGODB_URI" export SINGLE_MONGOS_LB_URI=$MONGODB_URI export MULTI_MONGOS_LB_URI=$MONGODB_URI elif [ ! -z "$TEST_AUTH_OIDC" ]; then export DB_USER=$OIDC_ADMIN_USER export DB_PASSWORD=$OIDC_ADMIN_PWD export DB_IP="$MONGODB_URI" else export DB_USER="bob" export DB_PASSWORD="pwd123" fi echo "Added auth, DB_USER: $DB_USER" set -x fi if [ -n "$TEST_ENTERPRISE_AUTH" ]; then if [ "Windows_NT" = "$OS" ]; then echo "Setting GSSAPI_PASS" export GSSAPI_PASS=${SASL_PASS} export GSSAPI_CANONICALIZE="true" else # BUILD-3830 touch krb5.conf.empty export KRB5_CONFIG=${PROJECT_DIRECTORY}/.evergreen/krb5.conf.empty echo "Writing keytab" echo ${KEYTAB_BASE64} | base64 -d > ${PROJECT_DIRECTORY}/.evergreen/drivers.keytab echo "Running kinit" kinit -k -t ${PROJECT_DIRECTORY}/.evergreen/drivers.keytab -p ${PRINCIPAL} fi echo "Setting GSSAPI variables" export GSSAPI_HOST=${SASL_HOST} export GSSAPI_PORT=${SASL_PORT} export GSSAPI_PRINCIPAL=${PRINCIPAL} fi 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_ARGS="test/test_load_balancer.py" fi if [ "$SSL" != "nossl" ]; then export CLIENT_PEM="$DRIVERS_TOOLS/.evergreen/x509gen/client.pem" export CA_PEM="$DRIVERS_TOOLS/.evergreen/x509gen/ca.pem" if [ -n "$TEST_LOADBALANCER" ]; then export SINGLE_MONGOS_LB_URI="${SINGLE_MONGOS_LB_URI}&tls=true" export MULTI_MONGOS_LB_URI="${MULTI_MONGOS_LB_URI}&tls=true" fi fi if [ "$COMPRESSORS" = "snappy" ]; then python -m pip install '.[snappy]' if [ "$OLD_PYPY" == "True" ]; then pip install "python-snappy<0.7.0" fi PYTHON=python elif [ "$COMPRESSORS" = "zstd" ]; then python -m pip install zstandard fi # PyOpenSSL test setup. if [ -n "$TEST_PYOPENSSL" ]; then python -m pip install '.[ocsp]' fi if [ -n "$TEST_ENCRYPTION" ] || [ -n "$TEST_FLE_AZURE_AUTO" ] || [ -n "$TEST_FLE_GCP_AUTO" ]; then python -m pip install '.[encryption]' # Install libmongocrypt if necessary. if [ ! -d "libmongocrypt" ]; then bash ./.evergreen/setup-libmongocrypt.sh fi # Use the nocrypto build to avoid dependency issues with older windows/python versions. BASE=$(pwd)/libmongocrypt/nocrypto if [ -f "${BASE}/lib/libmongocrypt.so" ]; then PYMONGOCRYPT_LIB=${BASE}/lib/libmongocrypt.so elif [ -f "${BASE}/lib/libmongocrypt.dylib" ]; then PYMONGOCRYPT_LIB=${BASE}/lib/libmongocrypt.dylib elif [ -f "${BASE}/bin/mongocrypt.dll" ]; then PYMONGOCRYPT_LIB=${BASE}/bin/mongocrypt.dll # libmongocrypt's windows dll is not marked executable. chmod +x $PYMONGOCRYPT_LIB PYMONGOCRYPT_LIB=$(cygpath -m $PYMONGOCRYPT_LIB) elif [ -f "${BASE}/lib64/libmongocrypt.so" ]; then PYMONGOCRYPT_LIB=${BASE}/lib64/libmongocrypt.so else echo "Cannot find libmongocrypt shared object file" exit 1 fi export PYMONGOCRYPT_LIB # TODO: Test with 'pip install pymongocrypt' if [ ! -d "libmongocrypt_git" ]; then git clone https://github.com/mongodb/libmongocrypt.git libmongocrypt_git fi python -m pip install ./libmongocrypt_git/bindings/python python -c "import pymongocrypt; print('pymongocrypt version: '+pymongocrypt.__version__)" python -c "import pymongocrypt; print('libmongocrypt version: '+pymongocrypt.libmongocrypt_version())" # PATH is updated by PREPARE_SHELL for access to mongocryptd. fi if [ -n "$TEST_ENCRYPTION" ]; then if [ -n "$TEST_ENCRYPTION_PYOPENSSL" ]; then python -m pip install '.[ocsp]' fi if [ -n "$TEST_CRYPT_SHARED" ]; then CRYPT_SHARED_DIR=`dirname $CRYPT_SHARED_LIB_PATH` echo "using crypt_shared_dir $CRYPT_SHARED_DIR" export DYLD_FALLBACK_LIBRARY_PATH=$CRYPT_SHARED_DIR:$DYLD_FALLBACK_LIBRARY_PATH export LD_LIBRARY_PATH=$CRYPT_SHARED_DIR:$LD_LIBRARY_PATH export PATH=$CRYPT_SHARED_DIR:$PATH fi # Only run the encryption tests. if [ -z "$TEST_ARGS" ]; then TEST_ARGS="test/test_encryption.py" fi fi if [ -n "$TEST_FLE_AZURE_AUTO" ] || [ -n "$TEST_FLE_GCP_AUTO" ]; then if [[ -z "$SUCCESS" ]]; then echo "Must define SUCCESS" exit 1 fi if echo "$MONGODB_URI" | grep -q "@"; then echo "MONGODB_URI unexpectedly contains user credentials in FLE test!"; exit 1 fi if [ -z "$TEST_ARGS" ]; then TEST_ARGS="test/test_on_demand_csfle.py" fi fi if [ -n "$TEST_INDEX_MANAGEMENT" ]; then source $DRIVERS_TOOLS/.evergreen/atlas/secrets-export.sh export DB_USER="${DRIVERS_ATLAS_LAMBDA_USER}" set +x export DB_PASSWORD="${DRIVERS_ATLAS_LAMBDA_PASSWORD}" set -x TEST_ARGS="test/test_index_management.py" fi if [ -n "$TEST_DATA_LAKE" ] && [ -z "$TEST_ARGS" ]; then TEST_ARGS="test/test_data_lake.py" fi if [ -n "$TEST_ATLAS" ]; then TEST_ARGS="test/atlas/test_connection.py" fi if [ -n "$TEST_OCSP" ]; then python -m pip install ".[ocsp]" TEST_ARGS="test/ocsp/test_ocsp.py" fi if [ -n "$TEST_AUTH_AWS" ]; then python -m pip install ".[aws]" TEST_ARGS="test/auth_aws/test_auth_aws.py" fi if [ -n "$TEST_AUTH_OIDC" ]; then python -m pip install ".[aws]" TEST_ARGS="test/auth_oidc/test_auth_oidc.py $TEST_ARGS" fi if [ -n "$PERF_TEST" ]; then python -m pip install simplejson start_time=$(date +%s) TEST_ARGS="test/performance/perf_test.py" fi echo "Running $AUTH tests over $SSL with python $PYTHON" python -c 'import sys; print(sys.version)' # Run the tests, and store the results in Evergreen compatible XUnit XML # files in the xunit-results/ directory. # Run the tests with coverage if requested and coverage is installed. # Only cover CPython. PyPy reports suspiciously low coverage. PYTHON_IMPL=$($PYTHON -c "import platform; print(platform.python_implementation())") if [ -n "$COVERAGE" ] && [ "$PYTHON_IMPL" = "CPython" ]; then # coverage 7.3 dropped support for Python 3.7, keep in sync with combine-coverage.sh. # coverage >=5 is needed for relative_files=true. python -m pip install pytest-cov "coverage>=5,<7.3" TEST_ARGS="$TEST_ARGS --cov" fi if [ -n "$GREEN_FRAMEWORK" ]; then python -m pip install $GREEN_FRAMEWORK fi # Show the installed packages 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_ARGS else python green_framework_test.py $GREEN_FRAMEWORK -v $TEST_ARGS fi # Handle perf test post actions. if [ -n "$PERF_TEST" ]; then end_time=$(date +%s) elapsed_secs=$((end_time-start_time)) cat results.json echo "{\"failures\": 0, \"results\": [{\"status\": \"pass\", \"exit_code\": 0, \"test_file\": \"BenchMarkTests\", \"start\": $start_time, \"end\": $end_time, \"elapsed\": $elapsed_secs}]}" > report.json cat report.json fi # Handle coverage post actions. if [ -n "$COVERAGE" ]; then rm -rf .pytest_cache fi mongodb-mongo-python-driver-509e9b7/.evergreen/setup-libmongocrypt.sh000066400000000000000000000026541462766011000260660ustar00rootroot00000000000000#!/bin/bash set -o errexit # Exit the script with error if any of the commands fail set -o xtrace TARGET="" if [ "Windows_NT" = "${OS:-''}" ]; then # Magic variable in cygwin # PYTHON-2808 Ensure this machine has the CA cert for google KMS. powershell.exe "Invoke-WebRequest -URI https://oauth2.googleapis.com/" > /dev/null || true TARGET="windows-test" fi if [ "$(uname -s)" = "Darwin" ]; then TARGET="macos" fi if [ "$(uname -s)" = "Linux" ]; then rhel_ver=$(awk -F'=' '/VERSION_ID/{ gsub(/"/,""); print $2}' /etc/os-release) arch=$(uname -m) echo "RHEL $rhel_ver $arch" if [[ $rhel_ver =~ 7 ]]; then TARGET="rhel-70-64-bit" elif [[ $rhel_ver =~ 8 ]]; then if [ "$arch" = "x86_64" ]; then TARGET="rhel-80-64-bit" elif [ "$arch" = "arm" ]; then TARGET="rhel-82-arm64" fi fi fi if [ -z "$LIBMONGOCRYPT_URL" ] && [ -n "$TARGET" ]; then LIBMONGOCRYPT_URL="https://s3.amazonaws.com/mciuploads/libmongocrypt/$TARGET/master/latest/libmongocrypt.tar.gz" fi if [ -z "$LIBMONGOCRYPT_URL" ]; then echo "Cannot test client side encryption without LIBMONGOCRYPT_URL!" exit 1 fi rm -rf libmongocrypt libmongocrypt.tar.gz echo "Fetching $LIBMONGOCRYPT_URL..." curl -O "$LIBMONGOCRYPT_URL" echo "Fetching $LIBMONGOCRYPT_URL...done" mkdir libmongocrypt tar xzf libmongocrypt.tar.gz -C ./libmongocrypt ls -la libmongocrypt ls -la libmongocrypt/nocrypto mongodb-mongo-python-driver-509e9b7/.evergreen/tox.sh000066400000000000000000000010401462766011000226360ustar00rootroot00000000000000#!/bin/bash set -o errexit # Exit the script with error if any of the commands fail set -x . .evergreen/utils.sh if [ -z "$PYTHON_BINARY" ]; then PYTHON_BINARY=$(find_python3) fi if $PYTHON_BINARY -m tox --version; then run_tox() { $PYTHON_BINARY -m tox "$@" } else # No toolchain present, set up virtualenv before installing tox createvirtualenv "$PYTHON_BINARY" toxenv trap "deactivate; rm -rf toxenv" EXIT HUP python -m pip install -q tox run_tox() { python -m tox "$@" } fi run_tox "${@:1}" mongodb-mongo-python-driver-509e9b7/.evergreen/utils.sh000077500000000000000000000070321462766011000231760ustar00rootroot00000000000000#!/bin/bash -ex set -o xtrace find_python3() { PYTHON="" # Add a fallback system python3 if it is available and Python 3.7+. if is_python_37 "$(command -v python3)"; then PYTHON="$(command -v python3)" fi # Find a suitable toolchain version, if available. if [ "$(uname -s)" = "Darwin" ]; then # macos 11.00 if [ -d "/Library/Frameworks/Python.Framework/Versions/3.10" ]; then PYTHON="/Library/Frameworks/Python.Framework/Versions/3.10/bin/python3" # macos 10.14 elif [ -d "/Library/Frameworks/Python.Framework/Versions/3.7" ]; then PYTHON="/Library/Frameworks/Python.Framework/Versions/3.7/bin/python3" fi elif [ "Windows_NT" = "$OS" ]; then # Magic variable in cygwin PYTHON="C:/python/Python37/python.exe" else # Prefer our own toolchain, fall back to mongodb toolchain if it has Python 3.7+. if [ -f "/opt/python/3.7/bin/python3" ]; then PYTHON="/opt/python/3.7/bin/python3" elif is_python_37 "$(command -v /opt/mongodbtoolchain/v4/bin/python3)"; then PYTHON="/opt/mongodbtoolchain/v4/bin/python3" elif is_python_37 "$(command -v /opt/mongodbtoolchain/v3/bin/python3)"; then PYTHON="/opt/mongodbtoolchain/v3/bin/python3" fi fi if [ -z "$PYTHON" ]; then echo "Cannot test without python3.7+ installed!" exit 1 fi echo "$PYTHON" } # Usage: # createvirtualenv /path/to/python /output/path/for/venv # * param1: Python binary to use for the virtualenv # * param2: Path to the virtualenv to create createvirtualenv () { PYTHON=$1 VENVPATH=$2 # Prefer venv VENV="$PYTHON -m venv" if [ "$(uname -s)" = "Darwin" ]; then VIRTUALENV="$PYTHON -m virtualenv" else VIRTUALENV=$(command -v virtualenv 2>/dev/null || echo "$PYTHON -m virtualenv") VIRTUALENV="$VIRTUALENV -p $PYTHON" fi if ! $VENV $VENVPATH 2>/dev/null; then # Workaround for bug in older versions of virtualenv. $VIRTUALENV $VENVPATH 2>/dev/null || $VIRTUALENV $VENVPATH fi if [ "Windows_NT" = "$OS" ]; then # Workaround https://bugs.python.org/issue32451: # mongovenv/Scripts/activate: line 3: $'\r': command not found dos2unix $VENVPATH/Scripts/activate || true . $VENVPATH/Scripts/activate else . $VENVPATH/bin/activate fi export PIP_QUIET=1 python -m pip install --upgrade pip python -m pip install --upgrade setuptools tox } # Usage: # testinstall /path/to/python /path/to/.whl ["no-virtualenv"] # * param1: Python binary to test # * param2: Path to the wheel to install # * param3 (optional): If set to a non-empty string, don't create a virtualenv. Used in manylinux containers. testinstall () { PYTHON=$1 RELEASE=$2 NO_VIRTUALENV=$3 if [ -z "$NO_VIRTUALENV" ]; then createvirtualenv $PYTHON venvtestinstall PYTHON=python fi $PYTHON -m pip install --upgrade $RELEASE cd tools $PYTHON fail_if_no_c.py $PYTHON -m pip uninstall -y pymongo cd .. if [ -z "$NO_VIRTUALENV" ]; then deactivate rm -rf venvtestinstall fi } # Function that returns success if the provided Python binary is version 3.7 or later # Usage: # is_python_37 /path/to/python # * param1: Python binary is_python_37() { if [ -z "$1" ]; then return 1 elif $1 -c "import sys; exit(sys.version_info[:2] < (3, 7))"; then # runs when sys.version_info[:2] >= (3, 7) return 0 else return 1 fi } mongodb-mongo-python-driver-509e9b7/.git-blame-ignore-revs000066400000000000000000000002051462766011000235320ustar00rootroot00000000000000# Initial pre-commit reformat 5578999a90e439fbca06fc0ffc98f4d04e96f7b4 # pyupgrade and ruff 0092b0af79378abf35b6db73a082ecb91af1d973 mongodb-mongo-python-driver-509e9b7/.github/000077500000000000000000000000001462766011000207755ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/.github/dependabot.yml000066400000000000000000000004501462766011000236240ustar00rootroot00000000000000version: 2 updates: # GitHub Actions - package-ecosystem: "github-actions" directory: "/" schedule: interval: "weekly" groups: actions: patterns: - "*" # Python - package-ecosystem: "pip" directory: "/" schedule: interval: "weekly" mongodb-mongo-python-driver-509e9b7/.github/reviewers.txt000066400000000000000000000001351462766011000235500ustar00rootroot00000000000000# List of reviewers for auto-assignment of reviews. caseyclements blink1073 Jibola NoahStapp mongodb-mongo-python-driver-509e9b7/.github/workflows/000077500000000000000000000000001462766011000230325ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/.github/workflows/codeql.yml000066400000000000000000000031271462766011000250270ustar00rootroot00000000000000name: "CodeQL" on: push: branches: [ "master", "v*"] tags: ['*'] pull_request: schedule: - cron: '17 10 * * 2' concurrency: group: codeql-${{ github.ref }} cancel-in-progress: true jobs: analyze: name: Analyze (${{ matrix.language }}) runs-on: "ubuntu-latest" timeout-minutes: 360 permissions: # required for all workflows security-events: write # required to fetch internal or private CodeQL packs packages: read strategy: fail-fast: false matrix: include: - language: c-cpp build-mode: manual - language: python build-mode: none steps: - name: Checkout repository uses: actions/checkout@v4 - uses: actions/setup-python@v3 # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL uses: github/codeql-action/init@v3 with: languages: ${{ matrix.language }} build-mode: ${{ matrix.build-mode }} # For more details on CodeQL's query packs, refer to: https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs queries: security-extended config: | paths-ignore: - '.github/**' - 'doc/**' - 'tools/**' - 'test/**' - if: matrix.build-mode == 'manual' run: | pip install -e . - name: Perform CodeQL Analysis uses: github/codeql-action/analyze@v3 with: category: "/language:${{matrix.language}}" mongodb-mongo-python-driver-509e9b7/.github/workflows/pull_request_template.md000066400000000000000000000014771462766011000300040ustar00rootroot00000000000000# [JIRA Ticket ID](Link to Ticket) # Summary # Changes in this PR # Test Plan # Screenshots (Optional) # Callouts or Follow-up items (Optional) mongodb-mongo-python-driver-509e9b7/.github/workflows/release-python.yml000066400000000000000000000113321462766011000265140ustar00rootroot00000000000000name: Python Wheels on: push: tags: - "[0-9]+.[0-9]+.[0-9]+" - "[0-9]+.[0-9]+.[0-9]+.post[0-9]+" - "[0-9]+.[0-9]+.[0-9]+[a-b][0-9]+" - "[0-9]+.[0-9]+.[0-9]+rc[0-9]+" workflow_dispatch: pull_request: concurrency: group: wheels-${{ github.ref }} cancel-in-progress: true defaults: run: shell: bash -eux {0} jobs: build_wheels: name: Build wheels for ${{ matrix.buildplat[1] }} runs-on: ${{ matrix.buildplat[0] }} strategy: # Ensure that a wheel builder finishes even if another fails fail-fast: false matrix: # Github Actions doesn't support pairing matrix values together, let's improvise # https://github.com/github/feedback/discussions/7835#discussioncomment-1769026 buildplat: - [ubuntu-20.04, "manylinux_x86_64", "cp3*-manylinux_x86_64"] - [ubuntu-20.04, "manylinux_aarch64", "cp3*-manylinux_aarch64"] - [ubuntu-20.04, "manylinux_ppc64le", "cp3*-manylinux_ppc64le"] - [ubuntu-20.04, "manylinux_s390x", "cp3*-manylinux_s390x"] - [ubuntu-20.04, "manylinux_i686", "cp3*-manylinux_i686"] - [windows-2019, "win_amd6", "cp3*-win_amd64"] - [windows-2019, "win32", "cp3*-win32"] - [macos-14, "macos", "cp*-macosx_*"] steps: - name: Checkout pymongo uses: actions/checkout@v4 with: fetch-depth: 0 - uses: actions/setup-python@v5 with: cache: 'pip' python-version: 3.8 cache-dependency-path: 'pyproject.toml' allow-prereleases: true - name: Set up QEMU if: runner.os == 'Linux' uses: docker/setup-qemu-action@v3 with: platforms: all - name: Install cibuildwheel # Note: the default manylinux is manylinux2014 run: | python -m pip install -U pip python -m pip install "cibuildwheel>=2.17,<3" - name: Build wheels env: CIBW_BUILD: ${{ matrix.buildplat[2] }} run: python -m cibuildwheel --output-dir wheelhouse - name: Build manylinux1 wheels if: ${{ matrix.buildplat[1] == 'manylinux_x86_64' || matrix.buildplat[1] == 'manylinux_i686' }} env: CIBW_MANYLINUX_X86_64_IMAGE: manylinux1 CIBW_MANYLINUX_I686_IMAGE: manylinux1 CIBW_BUILD: "cp37-${{ matrix.buildplat[1] }} cp38-${{ matrix.buildplat[1] }} cp39-${{ matrix.buildplat[1] }}" run: python -m cibuildwheel --output-dir wheelhouse - name: Assert all versions in wheelhouse if: ${{ ! startsWith(matrix.buildplat[1], 'macos') }} run: | ls wheelhouse/*cp37*.whl ls wheelhouse/*cp38*.whl ls wheelhouse/*cp39*.whl ls wheelhouse/*cp310*.whl ls wheelhouse/*cp311*.whl ls wheelhouse/*cp312*.whl - uses: actions/upload-artifact@v4 with: name: wheel-${{ matrix.buildplat[1] }} path: ./wheelhouse/*.whl if-no-files-found: error make_sdist: name: Make SDist runs-on: macos-13 steps: - uses: actions/checkout@v4 with: fetch-depth: 0 - uses: actions/setup-python@v5 with: # Build sdist on lowest supported Python python-version: '3.7' - name: Build SDist run: | set -ex python -m pip install -U pip build python -m build --sdist . - name: Test SDist run: | python -m pip install dist/*.gz cd .. python -c "from pymongo import has_c; assert has_c()" - uses: actions/upload-artifact@v4 with: name: "sdist" path: ./dist/*.tar.gz collect_dist: runs-on: ubuntu-latest needs: [build_wheels, make_sdist] name: Download Wheels steps: - name: Download all workflow run artifacts uses: actions/download-artifact@v4 - name: Flatten directory working-directory: . run: | find . -mindepth 2 -type f -exec mv {} . \; find . -type d -empty -delete - uses: actions/upload-artifact@v4 with: name: all-dist-${{ github.run_id }} path: "./*" publish: # https://packaging.python.org/en/latest/guides/publishing-package-distribution-releases-using-github-actions-ci-cd-workflows/#publishing-the-distribution-to-pypi needs: [collect_dist] if: startsWith(github.ref, 'refs/tags/') runs-on: ubuntu-latest environment: release permissions: id-token: write steps: - name: Download all the dists uses: actions/download-artifact@v4 with: name: all-dist-${{ github.run_id }} path: dist/ - name: Publish distribution 📦 to PyPI uses: pypa/gh-action-pypi-publish@release/v1 mongodb-mongo-python-driver-509e9b7/.github/workflows/test-python.yml000066400000000000000000000122731462766011000260600ustar00rootroot00000000000000name: Python Tests on: push: branches: ["master", "v**"] pull_request: workflow_dispatch: concurrency: group: tests-${{ github.ref }} cancel-in-progress: true defaults: run: shell: bash -eux {0} jobs: static: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: actions/setup-python@v5 with: python-version: "3.8" cache: 'pip' cache-dependency-path: 'pyproject.toml' - name: Install Python dependencies run: | python -m pip install -U pip tox - name: Run linters run: | tox -m lint-manual - name: Check Manifest run: | tox -m manifest - name: Run compilation run: | pip install -e . python tools/fail_if_no_c.py - name: Run typecheck run: | tox -m typecheck - run: | sudo apt-get install -y cppcheck - run: | cppcheck --force bson cppcheck pymongo build: # supercharge/mongodb-github-action requires containers so we don't test other platforms runs-on: ${{ matrix.os }} strategy: matrix: os: [ubuntu-20.04] python-version: ["3.7", "3.11", "pypy-3.8"] name: CPython ${{ matrix.python-version }}-${{ matrix.os }} steps: - uses: actions/checkout@v4 - name: Setup Python uses: actions/setup-python@v5 with: python-version: ${{ matrix.python-version }} cache: 'pip' cache-dependency-path: 'pyproject.toml' - name: Install dependencies run: | pip install -q tox - name: Start MongoDB uses: supercharge/mongodb-github-action@1.10.0 with: mongodb-version: 4.4 - name: Run tests run: | tox -m test doctest: runs-on: ubuntu-latest name: DocTest steps: - uses: actions/checkout@v4 - name: Setup Python uses: actions/setup-python@v5 with: python-version: "3.8" cache: 'pip' cache-dependency-path: 'pyproject.toml' - name: Install dependencies run: | pip install -q tox - name: Start MongoDB uses: supercharge/mongodb-github-action@1.10.0 with: mongodb-version: 4.4 - name: Run tests run: | tox -m doc-test docs: name: Docs Checks runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: actions/setup-python@v5 with: cache: 'pip' cache-dependency-path: 'pyproject.toml' # Build docs on lowest supported Python for furo python-version: '3.8' - name: Install dependencies run: | pip install -q tox - name: Build docs run: | tox -m doc linkcheck: name: Link Check runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: actions/setup-python@v5 with: cache: 'pip' cache-dependency-path: 'pyproject.toml' # Build docs on lowest supported Python for furo python-version: '3.8' - name: Install dependencies run: | pip install -q tox - name: Build docs run: | tox -m linkcheck typing: name: Typing Tests runs-on: ubuntu-latest strategy: matrix: python: ["3.7", "3.11"] steps: - uses: actions/checkout@v4 - uses: actions/setup-python@v5 with: python-version: "${{matrix.python}}" cache: 'pip' cache-dependency-path: 'pyproject.toml' - name: Install dependencies run: | pip install -q tox - name: Run typecheck run: | tox -m typecheck make_sdist: runs-on: ubuntu-latest name: "Make an sdist" steps: - uses: actions/checkout@v4 - uses: actions/setup-python@v5 with: cache: 'pip' cache-dependency-path: 'pyproject.toml' # Build sdist on lowest supported Python python-version: '3.7' - name: Build SDist shell: bash run: | pip install build python -m build --sdist - uses: actions/upload-artifact@v4 with: name: "sdist" path: dist/*.tar.gz test_sdist: runs-on: ubuntu-latest needs: [make_sdist] name: Install from SDist and Test timeout-minutes: 20 steps: - name: Download sdist uses: actions/download-artifact@v4 - name: Unpack SDist shell: bash run: | cd sdist ls mkdir test tar --strip-components=1 -zxf *.tar.gz -C ./test ls test - uses: actions/setup-python@v5 with: cache: 'pip' cache-dependency-path: 'sdist/test/pyproject.toml' # Test sdist on lowest supported Python python-version: '3.7' - name: Start MongoDB uses: supercharge/mongodb-github-action@1.10.0 - name: Run Test shell: bash run: | cd sdist/test ls which python pip install -e ".[test]" pytest -v mongodb-mongo-python-driver-509e9b7/.gitignore000066400000000000000000000007111462766011000214240ustar00rootroot00000000000000*~ *#* .DS* *.cm *.class *.pyc *.pyd build/ doc/_build/ dist/ tools/settings.py drivers-evergreen-tools pymongo.egg-info/ *.so *.egg* .tox mongocryptd.pid .idea/ .vscode/ .nova/ venv/ secrets-export.sh libmongocrypt.tar.gz libmongocrypt/ libmongocrypt_git/ # Lambda temp files test/lambda/.aws-sam test/lambda/env.json test/lambda/mongodb/pymongo/* test/lambda/mongodb/gridfs/* test/lambda/mongodb/bson/* # test results and logs xunit-results/ server.log mongodb-mongo-python-driver-509e9b7/.pre-commit-config.yaml000066400000000000000000000052161462766011000237220ustar00rootroot00000000000000 repos: - repo: https://github.com/pre-commit/pre-commit-hooks rev: v4.5.0 hooks: - id: check-added-large-files - id: check-case-conflict - id: check-toml - id: check-yaml exclude: template.yaml - id: debug-statements - id: end-of-file-fixer exclude: WHEEL exclude_types: [json] - id: forbid-new-submodules - id: trailing-whitespace exclude: .patch exclude_types: [json] - repo: https://github.com/astral-sh/ruff-pre-commit # Ruff version. rev: v0.1.3 hooks: - id: ruff args: ["--fix", "--show-fixes"] - id: ruff-format - repo: https://github.com/adamchainz/blacken-docs rev: "1.16.0" hooks: - id: blacken-docs additional_dependencies: - black==22.3.0 - repo: https://github.com/pre-commit/pygrep-hooks rev: "v1.10.0" hooks: - id: rst-backticks - id: rst-directive-colons - id: rst-inline-touching-normal - repo: https://github.com/rstcheck/rstcheck rev: v6.2.0 hooks: - id: rstcheck additional_dependencies: [sphinx] args: ["--ignore-directives=doctest,testsetup,todo,automodule","--ignore-substitutions=release", "--report-level=error"] # We use the Python version instead of the original version which seems to require Docker # https://github.com/koalaman/shellcheck-precommit - repo: https://github.com/shellcheck-py/shellcheck-py rev: v0.9.0.6 hooks: - id: shellcheck name: shellcheck args: ["--severity=warning"] stages: [manual] - repo: https://github.com/PyCQA/doc8 rev: v1.1.1 hooks: - id: doc8 args: ["--ignore=D001"] # ignore line length stages: [manual] - repo: https://github.com/sirosen/check-jsonschema rev: 0.27.0 hooks: - id: check-jsonschema name: "Check GitHub Workflows" files: ^\.github/workflows/ types: [yaml] args: ["--schemafile", "https://json.schemastore.org/github-workflow"] stages: [manual] - repo: https://github.com/ariebovenberg/slotscheck rev: v0.17.0 hooks: - id: slotscheck files: \.py$ exclude: "^(test|tools)/" stages: [manual] args: ["--no-strict-imports"] - repo: https://github.com/codespell-project/codespell rev: "v2.2.6" hooks: - id: codespell # Examples of errors or updates to justify the exceptions: # - test/test_on_demand_csfle.py:44: FLE ==> FILE # - test/test_bson.py:1043: fo ==> of, for, to, do, go # - test/bson_corpus/decimal128-4.json:98: Infinit ==> Infinite # - test/test_bson.py:267: isnt ==> isn't # - test/versioned-api/crud-api-version-1-strict.json:514: nin ==> inn, min, bin, nine # - test/test_client.py:188: te ==> the, be, we, to args: ["-L", "fle,fo,infinit,isnt,nin,te,aks"] mongodb-mongo-python-driver-509e9b7/.readthedocs.yaml000066400000000000000000000010271462766011000226640ustar00rootroot00000000000000# .readthedocs.yaml # Read the Docs configuration file # See https://docs.readthedocs.io/en/stable/config-file/v2.html for details # Required version: 2 # Build documentation in the doc/ directory with Sphinx sphinx: configuration: doc/conf.py fail_on_warning: true # Set the version of Python and requirements required to build the docs. python: install: # Install pymongo itself. - method: pip path: . - requirements: requirements/docs.txt build: os: ubuntu-22.04 tools: python: "3.11" mongodb-mongo-python-driver-509e9b7/CONTRIBUTING.md000066400000000000000000000215531462766011000216740ustar00rootroot00000000000000# Contributing to PyMongo PyMongo has a large [community](https://pymongo.readthedocs.io/en/stable/contributors.html) and contributions are always encouraged. Contributions can be as simple as minor tweaks to the documentation. Please read these guidelines before sending a pull request. ## Bugfixes and New Features Before starting to write code, look for existing [tickets](https://jira.mongodb.org/browse/PYTHON) or [create one](https://jira.mongodb.org/browse/PYTHON) for your specific issue or feature request. That way you avoid working on something that might not be of interest or that has already been addressed. ## Supported Interpreters PyMongo supports CPython 3.7+ and PyPy3.8+. Language features not supported by all interpreters can not be used. ## Style Guide PyMongo follows [PEP8](http://www.python.org/dev/peps/pep-0008/) including 4 space indents and 79 character line limits. ## General Guidelines - Avoid backward breaking changes if at all possible. - Write inline documentation for new classes and methods. - Write tests and make sure they pass (make sure you have a mongod running on the default port, then execute `tox -e test` from the cmd line to run the test suite). - Add yourself to doc/contributors.rst `:)` ## Authoring a Pull Request **Our Pull Request Policy is based on this** [Code Review Developer Guide](https://google.github.io/eng-practices/review) The expectation for any code author is to provide all the context needed in the space of a pull request for any engineer to feel equipped to review the code. Depending on the type of change, do your best to highlight important new functions or objects you've introduced in the code; think complex functions or new abstractions. Whilst it may seem like more work for you to adjust your pull request, the reality is your likelihood for getting review sooner shoots up. **Self Review Guidelines to follow** - If the PR is too large, split it if possible. - Use 250 LoC (excluding test data and config changes) as a rule-of-thumb. - Moving and changing code should be in separate PRs or commits. - Moving: Taking large code blobs and transplanting them to another file. There\'s generally no (or very little) actual code changed other than a cut and paste. It can even be extended to large deletions. - Changing: Adding code changes (be that refactors or functionality additions/subtractions). - These two, when mixed, can muddy understanding and sometimes make it harder for reviewers to keep track of things. - Prefer explaining with code comments instead of PR comments. **Provide background** - The PR description and linked tickets should answer the "what" and "why" of the change. The code change explains the "how". **Follow the Template** - Please do not deviate from the template we make; it is there for a lot of reasons. If it is a one line fix, we still need to have context on what and why it is needed. - If making a versioning change, please let that be known. See examples below: - `versionadded:: 3.11` - `versionchanged:: 3.5` **Pull Request Template Breakdown** - **Github PR Title** - The PR Title format should always be `[JIRA-ID] : Jira Title or Blurb Summary`. - **JIRA LINK** - Convenient link to the associated JIRA ticket. - **Summary** - Small blurb on why this is needed. The JIRA task should have the more in-depth description, but this should still, at a high level, give anyone looking an understanding of why the PR has been checked in. - **Changes in this PR** - The explicit code changes that this PR is introducing. This should be more specific than just the task name. (Unless the task name is very clear). - **Test Plan** - Everything needs a test description. Describe what you did to validate your changes actually worked; if you did nothing, then document you did not test it. Aim to make these steps reproducible by other engineers, specifically with your primary reviewer in mind. - **Screenshots** - Any images that provide more context to the PR. Usually, these just coincide with the test plan. - **Callouts or follow-up items** - This is a good place for identifying "to-dos" that you've placed in the code (Must have an accompanying JIRA Ticket). - Potential bugs that you are unsure how to test in the code. - Opinions you want to receive about your code. ## Running Linters PyMongo uses [pre-commit](https://pypi.org/project/pre-commit/) for managing linting of the codebase. `pre-commit` performs various checks on all files in PyMongo and uses tools that help follow a consistent code style within the codebase. To set up `pre-commit` locally, run: ```bash brew install pre-commit pre-commit install ``` To run `pre-commit` manually, run: ```bash pre-commit run --all-files ``` To run a manual hook like `mypy` manually, run: ```bash pre-commit run --all-files --hook-stage manual mypy ``` Typically we use `tox` to run the linters, e.g. ```bash tox -e typecheck-mypy tox -e lint-manual ``` ## Documentation To contribute to the [API documentation](https://pymongo.readthedocs.io/en/stable/) just make your changes to the inline documentation of the appropriate [source code](https://github.com/mongodb/mongo-python-driver) or [rst file](https://github.com/mongodb/mongo-python-driver/tree/master/doc) in a branch and submit a [pull request](https://help.github.com/articles/using-pull-requests). You might also use the GitHub [Edit](https://github.com/blog/844-forking-with-the-edit-button) button. We use [reStructuredText](https://www.sphinx-doc.org/en/master/usage/restructuredtext/basics.html) for all documentation including narrative docs, and the [Sphinx docstring format](https://sphinx-rtd-tutorial.readthedocs.io/en/latest/docstrings.html). You can build the documentation locally by running: ```bash tox -e doc ``` When updating docs, it can be helpful to run the live docs server as: ```bash tox -e doc-serve ``` Browse to the link provided, and then as you make changes to docstrings or narrative docs, the pages will re-render and the browser will automatically refresh. ## Running Tests Locally - Ensure you have started the appropriate Mongo Server(s). - Run `pip install tox` to use `tox` for testing or run `pip install -e ".[test]"` to run `pytest` directly. - Run `tox -m test` or `pytest` to run all of the tests. - Append `test/.py::::` to run specific tests. You can omit the `` to test a full class and the `` to test a full module. For example: `tox -m test -- test/test_change_stream.py::TestUnifiedChangeStreamsErrors::test_change_stream_errors_on_ElectionInProgress`. - Use the `-k` argument to select tests by pattern. ## Running Load Balancer Tests Locally - Install `haproxy` (available as `brew install haproxy` on macOS). - Clone `drivers-evergreen-tools`: `git clone git@github.com:mongodb-labs/drivers-evergreen-tools.git`. - Start the servers using `LOAD_BALANCER=true TOPOLOGY=sharded_cluster AUTH=noauth SSL=nossl MONGODB_VERSION=6.0 DRIVERS_TOOLS=$PWD/drivers-evergreen-tools MONGO_ORCHESTRATION_HOME=$PWD/drivers-evergreen-tools/.evergreen/orchestration $PWD/drivers-evergreen-tools/.evergreen/run-orchestration.sh`. - Start the load balancer using: `MONGODB_URI='mongodb://localhost:27017,localhost:27018/' $PWD/drivers-evergreen-tools/.evergreen/run-load-balancer.sh start`. - Run the tests from the `pymongo` checkout directory using: `TEST_LOADBALANCER=1 tox -m test-eg`. ## Running Encryption Tests Locally - Run `AWS_PROFILE= tox -m setup-encryption` after setting up your AWS profile with `aws configure sso`. - Run the tests with `TEST_ENCRYPTION=1 tox -e test-eg`. - When done, run `tox -m teardown-encryption` to clean up. ## Re-sync Spec Tests If you would like to re-sync the copy of the specification tests in the PyMongo repository with that which is inside the [specifications repo](https://github.com/mongodb/specifications), please use the script provided in `.evergreen/resync-specs.sh`.: ```bash git clone git@github.com:mongodb/specifications.git export MDB_SPECS=~/specifications cd ~/mongo-python-driver/.evergreen ./resync-specs.sh -b "" spec1 spec2 ... ./resync-specs.sh -b "connection-string*" crud bson-corpus # Updates crud and bson-corpus specs while ignoring all files with the regex "connection-string*" cd .. ``` The `-b` flag adds as a regex pattern to block files you do not wish to update in PyMongo. This is primarily helpful if you are implementing a new feature in PyMongo that has spec tests already implemented, or if you are attempting to validate new spec tests in PyMongo. mongodb-mongo-python-driver-509e9b7/LICENSE000066400000000000000000000261351462766011000204510ustar00rootroot00000000000000 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright [yyyy] [name of copyright owner] 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. mongodb-mongo-python-driver-509e9b7/MANIFEST.in000066400000000000000000000015101462766011000211700ustar00rootroot00000000000000include README.md include LICENSE include THIRD-PARTY-NOTICES include *.ini include requirements.txt exclude .coveragerc exclude .git-blame-ignore-revs exclude .pre-commit-config.yaml exclude .readthedocs.yaml exclude CONTRIBUTING.md exclude RELEASE.md recursive-include doc *.rst recursive-include doc *.py recursive-include doc *.conf recursive-include doc *.css recursive-include doc *.js recursive-include doc *.png include doc/Makefile include doc/_templates/layout.html include doc/make.bat include doc/static/periodic-executor-refs.dot recursive-include requirements *.txt recursive-include tools *.py include tools/README.rst include green_framework_test.py recursive-include test *.pem recursive-include test *.py recursive-include test *.json recursive-include bson *.h prune test/mod_wsgi_test prune test/lambda prune .evergreen mongodb-mongo-python-driver-509e9b7/README.md000066400000000000000000000150641462766011000207220ustar00rootroot00000000000000# PyMongo [![PyPI Version](https://img.shields.io/pypi/v/pymongo)](https://pypi.org/project/pymongo) [![Python Versions](https://img.shields.io/pypi/pyversions/pymongo)](https://pypi.org/project/pymongo) [![Monthly Downloads](https://static.pepy.tech/badge/pymongo/month)](https://pepy.tech/project/pymongo) [![Documentation Status](https://readthedocs.org/projects/pymongo/badge/?version=stable)](http://pymongo.readthedocs.io/en/stable/?badge=stable) ## About The PyMongo distribution contains tools for interacting with MongoDB database from Python. The `bson` package is an implementation of the [BSON format](http://bsonspec.org) for Python. The `pymongo` package is a native Python driver for MongoDB. The `gridfs` package is a [gridfs](https://github.com/mongodb/specifications/blob/master/source/gridfs/gridfs-spec.rst/) implementation on top of `pymongo`. PyMongo supports MongoDB 3.6, 4.0, 4.2, 4.4, 5.0, 6.0, and 7.0. ## Support / Feedback For issues with, questions about, or feedback for PyMongo, please look into our [support channels](https://support.mongodb.com/welcome). Please do not email any of the PyMongo developers directly with issues or questions - you're more likely to get an answer on [StackOverflow](https://stackoverflow.com/questions/tagged/mongodb) (using a "mongodb" tag). ## Bugs / Feature Requests Think you've found a bug? Want to see a new feature in PyMongo? Please open a case in our issue management tool, JIRA: - [Create an account and login](https://jira.mongodb.org). - Navigate to [the PYTHON project](https://jira.mongodb.org/browse/PYTHON). - Click **Create Issue** - Please provide as much information as possible about the issue type and how to reproduce it. Bug reports in JIRA for all driver projects (i.e. PYTHON, CSHARP, JAVA) and the Core Server (i.e. SERVER) project are **public**. ### How To Ask For Help Please include all of the following information when opening an issue: - Detailed steps to reproduce the problem, including full traceback, if possible. - The exact python version used, with patch level: ```bash python -c "import sys; print(sys.version)" ``` - The exact version of PyMongo used, with patch level: ```bash python -c "import pymongo; print(pymongo.version); print(pymongo.has_c())" ``` - The operating system and version (e.g. Windows 7, OSX 10.8, ...) - Web framework or asynchronous network library used, if any, with version (e.g. Django 1.7, mod_wsgi 4.3.0, gevent 1.0.1, Tornado 4.0.2, ...) ### Security Vulnerabilities If you've identified a security vulnerability in a driver or any other MongoDB project, please report it according to the [instructions here](https://www.mongodb.com/docs/manual/tutorial/create-a-vulnerability-report/). ## Installation PyMongo can be installed with [pip](http://pypi.python.org/pypi/pip): ```bash python -m pip install pymongo ``` Or `easy_install` from [setuptools](http://pypi.python.org/pypi/setuptools): ```bash python -m easy_install pymongo ``` You can also download the project source and do: ```bash pip install . ``` Do **not** install the "bson" package from pypi. PyMongo comes with its own bson package; running "pip install bson" installs a third-party package that is incompatible with PyMongo. ## Dependencies PyMongo supports CPython 3.7+ and PyPy3.7+. Required dependencies: Support for `mongodb+srv://` URIs requires [dnspython](https://pypi.python.org/pypi/dnspython) Optional dependencies: GSSAPI authentication requires [pykerberos](https://pypi.python.org/pypi/pykerberos) on Unix or [WinKerberos](https://pypi.python.org/pypi/winkerberos) on Windows. The correct dependency can be installed automatically along with PyMongo: ```bash python -m pip install "pymongo[gssapi]" ``` MONGODB-AWS authentication requires [pymongo-auth-aws](https://pypi.org/project/pymongo-auth-aws/): ```bash python -m pip install "pymongo[aws]" ``` OCSP (Online Certificate Status Protocol) requires [PyOpenSSL](https://pypi.org/project/pyOpenSSL/), [requests](https://pypi.org/project/requests/), [service_identity](https://pypi.org/project/service_identity/) and may require [certifi](https://pypi.python.org/pypi/certifi): ```bash python -m pip install "pymongo[ocsp]" ``` Wire protocol compression with snappy requires [python-snappy](https://pypi.org/project/python-snappy): ```bash python -m pip install "pymongo[snappy]" ``` Wire protocol compression with zstandard requires [zstandard](https://pypi.org/project/zstandard): ```bash python -m pip install "pymongo[zstd]" ``` Client-Side Field Level Encryption requires [pymongocrypt](https://pypi.org/project/pymongocrypt/) and [pymongo-auth-aws](https://pypi.org/project/pymongo-auth-aws/): ```bash python -m pip install "pymongo[encryption]" ``` You can install all dependencies automatically with the following command: ```bash python -m pip install "pymongo[gssapi,aws,ocsp,snappy,zstd,encryption]" ``` Additional dependencies are: - (to generate documentation or run tests) [tox](https://tox.wiki/en/latest/index.html) ## Examples Here's a basic example (for more see the *examples* section of the docs): ```pycon >>> import pymongo >>> client = pymongo.MongoClient("localhost", 27017) >>> db = client.test >>> db.name 'test' >>> db.my_collection Collection(Database(MongoClient('localhost', 27017), 'test'), 'my_collection') >>> db.my_collection.insert_one({"x": 10}).inserted_id ObjectId('4aba15ebe23f6b53b0000000') >>> db.my_collection.insert_one({"x": 8}).inserted_id ObjectId('4aba160ee23f6b543e000000') >>> db.my_collection.insert_one({"x": 11}).inserted_id ObjectId('4aba160ee23f6b543e000002') >>> db.my_collection.find_one() {'x': 10, '_id': ObjectId('4aba15ebe23f6b53b0000000')} >>> for item in db.my_collection.find(): ... print(item["x"]) ... 10 8 11 >>> db.my_collection.create_index("x") 'x_1' >>> for item in db.my_collection.find().sort("x", pymongo.ASCENDING): ... print(item["x"]) ... 8 10 11 >>> [item["x"] for item in db.my_collection.find().limit(2).skip(1)] [8, 11] ``` ## Documentation Documentation is available at [pymongo.readthedocs.io](https://pymongo.readthedocs.io/en/stable/). Documentation can be generated by running **tox -m doc**. Generated documentation can be found in the `doc/build/html/` directory. ## Learning Resources - MongoDB Learn - [Python courses](https://learn.mongodb.com/catalog?labels=%5B%22Language%22%5D&values=%5B%22Python%22%5D). - [Python Articles on Developer Center](https://www.mongodb.com/developer/languages/python/). ## Testing The easiest way to run the tests is to run **tox -m test** in the root of the distribution. For example, ```bash tox -e test ``` mongodb-mongo-python-driver-509e9b7/RELEASE.md000066400000000000000000000105071462766011000210420ustar00rootroot00000000000000# Some notes on PyMongo releases ## Versioning We follow [semver](https://semver.org/) and [pep-0440](https://www.python.org/dev/peps/pep-0440) for versioning. We shoot for a release every few months - that will generally just increment the middle / minor version number (e.g. `3.5.0` -> `3.6.0`). Patch releases are reserved for bug fixes (in general no new features or deprecations) - they only happen in cases where there is a critical bug in a recently released version, or when a release has no new features or API changes. In between releases we add `.devN` to the version number to denote the version under development. So if we just released `3.6.0`, then the current dev version might be `3.6.1.dev0` or `3.7.0.dev0`. When we make the next release we replace all instances of `3.x.x.devN` in the docs with the new version number. ## Deprecation Changes should be backwards compatible unless absolutely necessary. When making API changes the approach is generally to add a deprecation warning but keeping the existing API functional. Deprecated features can be removed in a release that changes the major version number. ## Doing a Release 1. PyMongo is tested on Evergreen. Ensure the latest commit are passing [CI](https://spruce.mongodb.com/commits/mongo-python-driver) as expected. 2. Check Jira to ensure all the tickets in this version have been completed. 3. Make a PR that adds the release notes to `doc/changelog.rst`. Generally just summarize/clarify the git log, but you might add some more long form notes for big changes. 4. Merge the PR. 5. Clone the source repository in a temporary directory and check out the release branch. 6. Update the version number in `pymongo/_version.py`. 7. Commit the change, e.g. `git add . && git commit -m "BUMP "` 7. Tag w/ version_number, eg, `git tag -a '4.1.0' -m 'BUMP 4.1.0'`. 8. Bump the version number to `.dev0` in `pymongo/_version.py`, commit, push. 9. Push commit / tag, eg `git push && git push --tags`. 10. Pushing a tag will trigger the release process on GitHub Actions that will require a member of the team to authorize the deployment. Navigate to https://github.com/mongodb/mongo-python-driver/actions/workflows/release-python.yml and wait for the publish to complete. 11. Make sure the new version appears on `https://pymongo.readthedocs.io/en/stable/`. If the new version does not show up automatically, trigger a rebuild of "stable" on https://readthedocs.org/projects/pymongo/builds/. 12. Publish the release version in Jira and add a description of the release, such as a the reason or the main feature. 13. Announce the release on the [community forum](https://www.mongodb.com/community/forums/tags/c/announcements/driver-releases/110/python) 14. File a ticket for DOCSP highlighting changes in server version and Python version compatibility or the lack thereof, for example https://jira.mongodb.org/browse/DOCSP-34040 15. Create a GitHub Release for the tag using https://github.com/mongodb/mongo-python-driver/releases/new. The title should be "PyMongo X.Y.Z", and the description should contain a link to the release notes on the the community forum, e.g. "Release notes: mongodb.com/community/forums/t/pymongo-4-0-2-released/150457" 16. Wait for automated update PR on conda-forge, e.g.: https://github.com/conda-forge/pymongo-feedstock/pull/81 Update dependencies if needed. ## Doing a Bug Fix Release 1. If it is a new branch, first create the release branch and Evergreen project. - Clone the source repository in a temporary location. - Create a branch from the tag, e.g. `git checkout -b v4.1 4.1.0`. - Push the branch, e.g.: `git push origin v4.6`. - Create a new project in Evergreen for the branch by duplicating the "Mongo Python Driver" project. Select the option to create a JIRA ticket for S3 bucket permissions. - Update the "Display Name", "Branch Name", and "Identifier". - Attach the project to the repository. - Wait for the JIRA ticket to be resolved and verify S3 upload capability with a patch release on the new project. 2. Create a PR against the release branch. 3. Create a release using the "Doing a Release" checklist above, ensuring that you check out the appropriate release branch in the source checkout. 4. Cherry-pick the changelog PR onto the `master` branch. mongodb-mongo-python-driver-509e9b7/THIRD-PARTY-NOTICES000066400000000000000000000064661462766011000222450ustar00rootroot00000000000000PyMongo uses third-party libraries or other resources that may be distributed under licenses different than the PyMongo software. In the event that we accidentally failed to list a required notice, please bring it to our attention through any of the ways detailed here: https://jira.mongodb.org/projects/PYTHON The attached notices are provided for information only. For any licenses that require disclosure of source, sources are available at https://github.com/mongodb/mongo-python-driver. 1) License Notice for time64.c ------------------------------ Copyright (c) 2007-2010 Michael G Schwern This software originally derived from Paul Sheer's pivotal_gmtime_r.c. The MIT License: Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 2) License Notice for bson-stdint-win32.h ----------------------------------------- ISO C9x compliant stdint.h for Microsoft Visual Studio Based on ISO/IEC 9899:TC2 Committee draft (May 6, 2005) WG14/N1124 Copyright (c) 2006-2013 Alexander Chemeris Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the product nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. mongodb-mongo-python-driver-509e9b7/bson/000077500000000000000000000000001462766011000203765ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/bson/__init__.py000066400000000000000000001413061462766011000225140ustar00rootroot00000000000000# Copyright 2009-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. """BSON (Binary JSON) encoding and decoding. The mapping from Python types to BSON types is as follows: ======================================= ============= =================== Python Type BSON Type Supported Direction ======================================= ============= =================== None null both bool boolean both int [#int]_ int32 / int64 py -> bson `bson.int64.Int64` int64 both float number (real) both str string both list array both dict / `SON` object both datetime.datetime [#dt]_ [#dt2]_ date both `bson.regex.Regex` regex both compiled re [#re]_ regex py -> bson `bson.binary.Binary` binary both `bson.objectid.ObjectId` oid both `bson.dbref.DBRef` dbref both None undefined bson -> py `bson.code.Code` code both str symbol bson -> py bytes [#bytes]_ binary both ======================================= ============= =================== .. [#int] A Python int will be saved as a BSON int32 or BSON int64 depending on its size. A BSON int32 will always decode to a Python int. A BSON int64 will always decode to a :class:`~bson.int64.Int64`. .. [#dt] datetime.datetime instances will be rounded to the nearest millisecond when saved .. [#dt2] all datetime.datetime instances are treated as *naive*. clients should always use UTC. .. [#re] :class:`~bson.regex.Regex` instances and regular expression objects from ``re.compile()`` are both saved as BSON regular expressions. BSON regular expressions are decoded as :class:`~bson.regex.Regex` instances. .. [#bytes] The bytes type is encoded as BSON binary with subtype 0. It will be decoded back to bytes. """ from __future__ import annotations import datetime import itertools import os import re import struct import sys import uuid from codecs import utf_8_decode as _utf_8_decode from codecs import utf_8_encode as _utf_8_encode from collections import abc as _abc from typing import ( IO, TYPE_CHECKING, Any, BinaryIO, Callable, Generator, Iterator, Mapping, MutableMapping, NoReturn, Optional, Sequence, Tuple, Type, TypeVar, Union, cast, overload, ) from bson.binary import ( ALL_UUID_SUBTYPES, CSHARP_LEGACY, JAVA_LEGACY, OLD_UUID_SUBTYPE, STANDARD, UUID_SUBTYPE, Binary, UuidRepresentation, ) from bson.code import Code from bson.codec_options import ( DEFAULT_CODEC_OPTIONS, CodecOptions, DatetimeConversion, _raw_document_class, ) from bson.datetime_ms import ( EPOCH_AWARE, EPOCH_NAIVE, DatetimeMS, _datetime_to_millis, _millis_to_datetime, ) from bson.dbref import DBRef from bson.decimal128 import Decimal128 from bson.errors import InvalidBSON, InvalidDocument, InvalidStringData from bson.int64 import Int64 from bson.max_key import MaxKey from bson.min_key import MinKey from bson.objectid import ObjectId from bson.regex import Regex from bson.son import RE_TYPE, SON from bson.timestamp import Timestamp from bson.tz_util import utc # Import some modules for type-checking only. if TYPE_CHECKING: from bson.raw_bson import RawBSONDocument from bson.typings import _DocumentType, _ReadableBuffer try: from bson import _cbson # type: ignore[attr-defined] _USE_C = True except ImportError: _USE_C = False __all__ = [ "ALL_UUID_SUBTYPES", "CSHARP_LEGACY", "JAVA_LEGACY", "OLD_UUID_SUBTYPE", "STANDARD", "UUID_SUBTYPE", "Binary", "UuidRepresentation", "Code", "DEFAULT_CODEC_OPTIONS", "CodecOptions", "DBRef", "Decimal128", "InvalidBSON", "InvalidDocument", "InvalidStringData", "Int64", "MaxKey", "MinKey", "ObjectId", "Regex", "RE_TYPE", "SON", "Timestamp", "utc", "EPOCH_AWARE", "EPOCH_NAIVE", "BSONNUM", "BSONSTR", "BSONOBJ", "BSONARR", "BSONBIN", "BSONUND", "BSONOID", "BSONBOO", "BSONDAT", "BSONNUL", "BSONRGX", "BSONREF", "BSONCOD", "BSONSYM", "BSONCWS", "BSONINT", "BSONTIM", "BSONLON", "BSONDEC", "BSONMIN", "BSONMAX", "get_data_and_view", "gen_list_name", "encode", "decode", "decode_all", "decode_iter", "decode_file_iter", "is_valid", "BSON", "has_c", "DatetimeConversion", "DatetimeMS", ] BSONNUM = b"\x01" # Floating point BSONSTR = b"\x02" # UTF-8 string BSONOBJ = b"\x03" # Embedded document BSONARR = b"\x04" # Array BSONBIN = b"\x05" # Binary BSONUND = b"\x06" # Undefined BSONOID = b"\x07" # ObjectId BSONBOO = b"\x08" # Boolean BSONDAT = b"\x09" # UTC Datetime BSONNUL = b"\x0A" # Null BSONRGX = b"\x0B" # Regex BSONREF = b"\x0C" # DBRef BSONCOD = b"\x0D" # Javascript code BSONSYM = b"\x0E" # Symbol BSONCWS = b"\x0F" # Javascript code with scope BSONINT = b"\x10" # 32bit int BSONTIM = b"\x11" # Timestamp BSONLON = b"\x12" # 64bit int BSONDEC = b"\x13" # Decimal128 BSONMIN = b"\xFF" # Min key BSONMAX = b"\x7F" # Max key _UNPACK_FLOAT_FROM = struct.Struct(" Tuple[Any, memoryview]: if isinstance(data, (bytes, bytearray)): return data, memoryview(data) view = memoryview(data) return view.tobytes(), view def _raise_unknown_type(element_type: int, element_name: str) -> NoReturn: """Unknown type helper.""" raise InvalidBSON( "Detected unknown BSON type {!r} for fieldname '{}'. Are " "you using the latest driver version?".format(chr(element_type).encode(), element_name) ) def _get_int( data: Any, _view: Any, position: int, dummy0: Any, dummy1: Any, dummy2: Any ) -> Tuple[int, int]: """Decode a BSON int32 to python int.""" return _UNPACK_INT_FROM(data, position)[0], position + 4 def _get_c_string(data: Any, view: Any, position: int, opts: CodecOptions[Any]) -> Tuple[str, int]: """Decode a BSON 'C' string to python str.""" end = data.index(b"\x00", position) return _utf_8_decode(view[position:end], opts.unicode_decode_error_handler, True)[0], end + 1 def _get_float( data: Any, _view: Any, position: int, dummy0: Any, dummy1: Any, dummy2: Any ) -> Tuple[float, int]: """Decode a BSON double to python float.""" return _UNPACK_FLOAT_FROM(data, position)[0], position + 8 def _get_string( data: Any, view: Any, position: int, obj_end: int, opts: CodecOptions[Any], dummy: Any ) -> Tuple[str, int]: """Decode a BSON string to python str.""" length = _UNPACK_INT_FROM(data, position)[0] position += 4 if length < 1 or obj_end - position < length: raise InvalidBSON("invalid string length") end = position + length - 1 if data[end] != 0: raise InvalidBSON("invalid end of string") return _utf_8_decode(view[position:end], opts.unicode_decode_error_handler, True)[0], end + 1 def _get_object_size(data: Any, position: int, obj_end: int) -> Tuple[int, int]: """Validate and return a BSON document's size.""" try: obj_size = _UNPACK_INT_FROM(data, position)[0] except struct.error as exc: raise InvalidBSON(str(exc)) from None end = position + obj_size - 1 if data[end] != 0: raise InvalidBSON("bad eoo") if end >= obj_end: raise InvalidBSON("invalid object length") # If this is the top-level document, validate the total size too. if position == 0 and obj_size != obj_end: raise InvalidBSON("invalid object length") return obj_size, end def _get_object( data: Any, view: Any, position: int, obj_end: int, opts: CodecOptions[Any], dummy: Any ) -> Tuple[Any, int]: """Decode a BSON subdocument to opts.document_class or bson.dbref.DBRef.""" obj_size, end = _get_object_size(data, position, obj_end) if _raw_document_class(opts.document_class): return (opts.document_class(data[position : end + 1], opts), position + obj_size) obj = _elements_to_dict(data, view, position + 4, end, opts) position += obj_size # If DBRef validation fails, return a normal doc. if ( isinstance(obj.get("$ref"), str) and "$id" in obj and isinstance(obj.get("$db"), (str, type(None))) ): return (DBRef(obj.pop("$ref"), obj.pop("$id", None), obj.pop("$db", None), obj), position) return obj, position def _get_array( data: Any, view: Any, position: int, obj_end: int, opts: CodecOptions[Any], element_name: str ) -> Tuple[Any, int]: """Decode a BSON array to python list.""" size = _UNPACK_INT_FROM(data, position)[0] end = position + size - 1 if data[end] != 0: raise InvalidBSON("bad eoo") position += 4 end -= 1 result: list[Any] = [] # Avoid doing global and attribute lookups in the loop. append = result.append index = data.index getter = _ELEMENT_GETTER decoder_map = opts.type_registry._decoder_map while position < end: element_type = data[position] # Just skip the keys. position = index(b"\x00", position) + 1 try: value, position = getter[element_type]( data, view, position, obj_end, opts, element_name ) except KeyError: _raise_unknown_type(element_type, element_name) if decoder_map: custom_decoder = decoder_map.get(type(value)) if custom_decoder is not None: value = custom_decoder(value) append(value) if position != end + 1: raise InvalidBSON("bad array length") return result, position + 1 def _get_binary( data: Any, _view: Any, position: int, obj_end: int, opts: CodecOptions[Any], dummy1: Any ) -> Tuple[Union[Binary, uuid.UUID], int]: """Decode a BSON binary to bson.binary.Binary or python UUID.""" length, subtype = _UNPACK_LENGTH_SUBTYPE_FROM(data, position) position += 5 if subtype == 2: length2 = _UNPACK_INT_FROM(data, position)[0] position += 4 if length2 != length - 4: raise InvalidBSON("invalid binary (st 2) - lengths don't match!") length = length2 end = position + length if length < 0 or end > obj_end: raise InvalidBSON("bad binary object length") # Convert UUID subtypes to native UUIDs. if subtype in ALL_UUID_SUBTYPES: uuid_rep = opts.uuid_representation binary_value = Binary(data[position:end], subtype) if ( (uuid_rep == UuidRepresentation.UNSPECIFIED) or (subtype == UUID_SUBTYPE and uuid_rep != STANDARD) or (subtype == OLD_UUID_SUBTYPE and uuid_rep == STANDARD) ): return binary_value, end return binary_value.as_uuid(uuid_rep), end # Decode subtype 0 to 'bytes'. if subtype == 0: value = data[position:end] else: value = Binary(data[position:end], subtype) return value, end def _get_oid( data: Any, _view: Any, position: int, dummy0: Any, dummy1: Any, dummy2: Any ) -> Tuple[ObjectId, int]: """Decode a BSON ObjectId to bson.objectid.ObjectId.""" end = position + 12 return ObjectId(data[position:end]), end def _get_boolean( data: Any, _view: Any, position: int, dummy0: Any, dummy1: Any, dummy2: Any ) -> Tuple[bool, int]: """Decode a BSON true/false to python True/False.""" end = position + 1 boolean_byte = data[position:end] if boolean_byte == b"\x00": return False, end elif boolean_byte == b"\x01": return True, end raise InvalidBSON("invalid boolean value: %r" % boolean_byte) def _get_date( data: Any, _view: Any, position: int, dummy0: int, opts: CodecOptions[Any], dummy1: Any ) -> Tuple[Union[datetime.datetime, DatetimeMS], int]: """Decode a BSON datetime to python datetime.datetime.""" return _millis_to_datetime(_UNPACK_LONG_FROM(data, position)[0], opts), position + 8 def _get_code( data: Any, view: Any, position: int, obj_end: int, opts: CodecOptions[Any], element_name: str ) -> Tuple[Code, int]: """Decode a BSON code to bson.code.Code.""" code, position = _get_string(data, view, position, obj_end, opts, element_name) return Code(code), position def _get_code_w_scope( data: Any, view: Any, position: int, _obj_end: int, opts: CodecOptions[Any], element_name: str ) -> Tuple[Code, int]: """Decode a BSON code_w_scope to bson.code.Code.""" code_end = position + _UNPACK_INT_FROM(data, position)[0] code, position = _get_string(data, view, position + 4, code_end, opts, element_name) scope, position = _get_object(data, view, position, code_end, opts, element_name) if position != code_end: raise InvalidBSON("scope outside of javascript code boundaries") return Code(code, scope), position def _get_regex( data: Any, view: Any, position: int, dummy0: Any, opts: CodecOptions[Any], dummy1: Any ) -> Tuple[Regex[Any], int]: """Decode a BSON regex to bson.regex.Regex or a python pattern object.""" pattern, position = _get_c_string(data, view, position, opts) bson_flags, position = _get_c_string(data, view, position, opts) bson_re = Regex(pattern, bson_flags) return bson_re, position def _get_ref( data: Any, view: Any, position: int, obj_end: int, opts: CodecOptions[Any], element_name: str ) -> Tuple[DBRef, int]: """Decode (deprecated) BSON DBPointer to bson.dbref.DBRef.""" collection, position = _get_string(data, view, position, obj_end, opts, element_name) oid, position = _get_oid(data, view, position, obj_end, opts, element_name) return DBRef(collection, oid), position def _get_timestamp( data: Any, _view: Any, position: int, dummy0: Any, dummy1: Any, dummy2: Any ) -> Tuple[Timestamp, int]: """Decode a BSON timestamp to bson.timestamp.Timestamp.""" inc, timestamp = _UNPACK_TIMESTAMP_FROM(data, position) return Timestamp(timestamp, inc), position + 8 def _get_int64( data: Any, _view: Any, position: int, dummy0: Any, dummy1: Any, dummy2: Any ) -> Tuple[Int64, int]: """Decode a BSON int64 to bson.int64.Int64.""" return Int64(_UNPACK_LONG_FROM(data, position)[0]), position + 8 def _get_decimal128( data: Any, _view: Any, position: int, dummy0: Any, dummy1: Any, dummy2: Any ) -> Tuple[Decimal128, int]: """Decode a BSON decimal128 to bson.decimal128.Decimal128.""" end = position + 16 return Decimal128.from_bid(data[position:end]), end # Each decoder function's signature is: # - data: bytes # - view: memoryview that references `data` # - position: int, beginning of object in 'data' to decode # - obj_end: int, end of object to decode in 'data' if variable-length type # - opts: a CodecOptions _ELEMENT_GETTER: dict[int, Callable[..., Tuple[Any, int]]] = { ord(BSONNUM): _get_float, ord(BSONSTR): _get_string, ord(BSONOBJ): _get_object, ord(BSONARR): _get_array, ord(BSONBIN): _get_binary, ord(BSONUND): lambda u, v, w, x, y, z: (None, w), # noqa: ARG005 # Deprecated undefined ord(BSONOID): _get_oid, ord(BSONBOO): _get_boolean, ord(BSONDAT): _get_date, ord(BSONNUL): lambda u, v, w, x, y, z: (None, w), # noqa: ARG005 ord(BSONRGX): _get_regex, ord(BSONREF): _get_ref, # Deprecated DBPointer ord(BSONCOD): _get_code, ord(BSONSYM): _get_string, # Deprecated symbol ord(BSONCWS): _get_code_w_scope, ord(BSONINT): _get_int, ord(BSONTIM): _get_timestamp, ord(BSONLON): _get_int64, ord(BSONDEC): _get_decimal128, ord(BSONMIN): lambda u, v, w, x, y, z: (MinKey(), w), # noqa: ARG005 ord(BSONMAX): lambda u, v, w, x, y, z: (MaxKey(), w), # noqa: ARG005 } if _USE_C: def _element_to_dict( data: Any, view: Any, # noqa: ARG001 position: int, obj_end: int, opts: CodecOptions[Any], raw_array: bool = False, ) -> Tuple[str, Any, int]: return cast( "Tuple[str, Any, int]", _cbson._element_to_dict(data, position, obj_end, opts, raw_array), ) else: def _element_to_dict( data: Any, view: Any, position: int, obj_end: int, opts: CodecOptions[Any], raw_array: bool = False, ) -> Tuple[str, Any, int]: """Decode a single key, value pair.""" element_type = data[position] position += 1 element_name, position = _get_c_string(data, view, position, opts) if raw_array and element_type == ord(BSONARR): _, end = _get_object_size(data, position, len(data)) return element_name, view[position : end + 1], end + 1 try: value, position = _ELEMENT_GETTER[element_type]( data, view, position, obj_end, opts, element_name ) except KeyError: _raise_unknown_type(element_type, element_name) if opts.type_registry._decoder_map: custom_decoder = opts.type_registry._decoder_map.get(type(value)) if custom_decoder is not None: value = custom_decoder(value) return element_name, value, position _T = TypeVar("_T", bound=MutableMapping[str, Any]) def _raw_to_dict( data: Any, position: int, obj_end: int, opts: CodecOptions[RawBSONDocument], result: _T, raw_array: bool = False, ) -> _T: data, view = get_data_and_view(data) return cast( _T, _elements_to_dict(data, view, position, obj_end, opts, result, raw_array=raw_array) ) def _elements_to_dict( data: Any, view: Any, position: int, obj_end: int, opts: CodecOptions[Any], result: Any = None, raw_array: bool = False, ) -> Any: """Decode a BSON document into result.""" if result is None: result = opts.document_class() end = obj_end - 1 while position < end: key, value, position = _element_to_dict( data, view, position, obj_end, opts, raw_array=raw_array ) result[key] = value if position != obj_end: raise InvalidBSON("bad object or element length") return result def _bson_to_dict(data: Any, opts: CodecOptions[_DocumentType]) -> _DocumentType: """Decode a BSON string to document_class.""" data, view = get_data_and_view(data) try: if _raw_document_class(opts.document_class): return opts.document_class(data, opts) # type:ignore[call-arg] _, end = _get_object_size(data, 0, len(data)) return cast("_DocumentType", _elements_to_dict(data, view, 4, end, opts)) except InvalidBSON: raise except Exception: # Change exception type to InvalidBSON but preserve traceback. _, exc_value, exc_tb = sys.exc_info() raise InvalidBSON(str(exc_value)).with_traceback(exc_tb) from None if _USE_C: _bson_to_dict = _cbson._bson_to_dict _PACK_FLOAT = struct.Struct(" Generator[bytes, None, None]: """Generate "keys" for encoded lists in the sequence b"0\x00", b"1\x00", b"2\x00", ... The first 1000 keys are returned from a pre-built cache. All subsequent keys are generated on the fly. """ yield from _LIST_NAMES counter = itertools.count(1000) while True: yield (str(next(counter)) + "\x00").encode("utf8") def _make_c_string_check(string: Union[str, bytes]) -> bytes: """Make a 'C' string, checking for embedded NUL characters.""" if isinstance(string, bytes): if b"\x00" in string: raise InvalidDocument("BSON keys / regex patterns must not contain a NUL character") try: _utf_8_decode(string, None, True) return string + b"\x00" except UnicodeError: raise InvalidStringData( "strings in documents must be valid UTF-8: %r" % string ) from None else: if "\x00" in string: raise InvalidDocument("BSON keys / regex patterns must not contain a NUL character") return _utf_8_encode(string)[0] + b"\x00" def _make_c_string(string: Union[str, bytes]) -> bytes: """Make a 'C' string.""" if isinstance(string, bytes): try: _utf_8_decode(string, None, True) return string + b"\x00" except UnicodeError: raise InvalidStringData( "strings in documents must be valid UTF-8: %r" % string ) from None else: return _utf_8_encode(string)[0] + b"\x00" def _make_name(string: str) -> bytes: """Make a 'C' string suitable for a BSON key.""" if "\x00" in string: raise InvalidDocument("BSON keys must not contain a NUL character") return _utf_8_encode(string)[0] + b"\x00" def _encode_float(name: bytes, value: float, dummy0: Any, dummy1: Any) -> bytes: """Encode a float.""" return b"\x01" + name + _PACK_FLOAT(value) def _encode_bytes(name: bytes, value: bytes, dummy0: Any, dummy1: Any) -> bytes: """Encode a python bytes.""" # Python3 special case. Store 'bytes' as BSON binary subtype 0. return b"\x05" + name + _PACK_INT(len(value)) + b"\x00" + value def _encode_mapping(name: bytes, value: Any, check_keys: bool, opts: CodecOptions[Any]) -> bytes: """Encode a mapping type.""" if _raw_document_class(value): return b"\x03" + name + cast(bytes, value.raw) data = b"".join([_element_to_bson(key, val, check_keys, opts) for key, val in value.items()]) return b"\x03" + name + _PACK_INT(len(data) + 5) + data + b"\x00" def _encode_dbref(name: bytes, value: DBRef, check_keys: bool, opts: CodecOptions[Any]) -> bytes: """Encode bson.dbref.DBRef.""" buf = bytearray(b"\x03" + name + b"\x00\x00\x00\x00") begin = len(buf) - 4 buf += _name_value_to_bson(b"$ref\x00", value.collection, check_keys, opts) buf += _name_value_to_bson(b"$id\x00", value.id, check_keys, opts) if value.database is not None: buf += _name_value_to_bson(b"$db\x00", value.database, check_keys, opts) for key, val in value._DBRef__kwargs.items(): buf += _element_to_bson(key, val, check_keys, opts) buf += b"\x00" buf[begin : begin + 4] = _PACK_INT(len(buf) - begin) return bytes(buf) def _encode_list( name: bytes, value: Sequence[Any], check_keys: bool, opts: CodecOptions[Any] ) -> bytes: """Encode a list/tuple.""" lname = gen_list_name() data = b"".join([_name_value_to_bson(next(lname), item, check_keys, opts) for item in value]) return b"\x04" + name + _PACK_INT(len(data) + 5) + data + b"\x00" def _encode_text(name: bytes, value: str, dummy0: Any, dummy1: Any) -> bytes: """Encode a python str.""" bvalue = _utf_8_encode(value)[0] return b"\x02" + name + _PACK_INT(len(bvalue) + 1) + bvalue + b"\x00" def _encode_binary(name: bytes, value: Binary, dummy0: Any, dummy1: Any) -> bytes: """Encode bson.binary.Binary.""" subtype = value.subtype if subtype == 2: value = _PACK_INT(len(value)) + value # type: ignore return b"\x05" + name + _PACK_LENGTH_SUBTYPE(len(value), subtype) + value def _encode_uuid(name: bytes, value: uuid.UUID, dummy: Any, opts: CodecOptions[Any]) -> bytes: """Encode uuid.UUID.""" uuid_representation = opts.uuid_representation binval = Binary.from_uuid(value, uuid_representation=uuid_representation) return _encode_binary(name, binval, dummy, opts) def _encode_objectid(name: bytes, value: ObjectId, dummy: Any, dummy1: Any) -> bytes: """Encode bson.objectid.ObjectId.""" return b"\x07" + name + value.binary def _encode_bool(name: bytes, value: bool, dummy0: Any, dummy1: Any) -> bytes: """Encode a python boolean (True/False).""" return b"\x08" + name + (value and b"\x01" or b"\x00") def _encode_datetime(name: bytes, value: datetime.datetime, dummy0: Any, dummy1: Any) -> bytes: """Encode datetime.datetime.""" millis = _datetime_to_millis(value) return b"\x09" + name + _PACK_LONG(millis) def _encode_datetime_ms(name: bytes, value: DatetimeMS, dummy0: Any, dummy1: Any) -> bytes: """Encode datetime.datetime.""" millis = int(value) return b"\x09" + name + _PACK_LONG(millis) def _encode_none(name: bytes, dummy0: Any, dummy1: Any, dummy2: Any) -> bytes: """Encode python None.""" return b"\x0A" + name def _encode_regex(name: bytes, value: Regex[Any], dummy0: Any, dummy1: Any) -> bytes: """Encode a python regex or bson.regex.Regex.""" flags = value.flags # Python 3 common case if flags == re.UNICODE: return b"\x0B" + name + _make_c_string_check(value.pattern) + b"u\x00" elif flags == 0: return b"\x0B" + name + _make_c_string_check(value.pattern) + b"\x00" else: sflags = b"" if flags & re.IGNORECASE: sflags += b"i" if flags & re.LOCALE: sflags += b"l" if flags & re.MULTILINE: sflags += b"m" if flags & re.DOTALL: sflags += b"s" if flags & re.UNICODE: sflags += b"u" if flags & re.VERBOSE: sflags += b"x" sflags += b"\x00" return b"\x0B" + name + _make_c_string_check(value.pattern) + sflags def _encode_code(name: bytes, value: Code, dummy: Any, opts: CodecOptions[Any]) -> bytes: """Encode bson.code.Code.""" cstring = _make_c_string(value) cstrlen = len(cstring) if value.scope is None: return b"\x0D" + name + _PACK_INT(cstrlen) + cstring scope = _dict_to_bson(value.scope, False, opts, False) full_length = _PACK_INT(8 + cstrlen + len(scope)) return b"\x0F" + name + full_length + _PACK_INT(cstrlen) + cstring + scope def _encode_int(name: bytes, value: int, dummy0: Any, dummy1: Any) -> bytes: """Encode a python int.""" if -2147483648 <= value <= 2147483647: return b"\x10" + name + _PACK_INT(value) else: try: return b"\x12" + name + _PACK_LONG(value) except struct.error: raise OverflowError("BSON can only handle up to 8-byte ints") from None def _encode_timestamp(name: bytes, value: Any, dummy0: Any, dummy1: Any) -> bytes: """Encode bson.timestamp.Timestamp.""" return b"\x11" + name + _PACK_TIMESTAMP(value.inc, value.time) def _encode_long(name: bytes, value: Any, dummy0: Any, dummy1: Any) -> bytes: """Encode a bson.int64.Int64.""" try: return b"\x12" + name + _PACK_LONG(value) except struct.error: raise OverflowError("BSON can only handle up to 8-byte ints") from None def _encode_decimal128(name: bytes, value: Decimal128, dummy0: Any, dummy1: Any) -> bytes: """Encode bson.decimal128.Decimal128.""" return b"\x13" + name + value.bid def _encode_minkey(name: bytes, dummy0: Any, dummy1: Any, dummy2: Any) -> bytes: """Encode bson.min_key.MinKey.""" return b"\xFF" + name def _encode_maxkey(name: bytes, dummy0: Any, dummy1: Any, dummy2: Any) -> bytes: """Encode bson.max_key.MaxKey.""" return b"\x7F" + name # Each encoder function's signature is: # - name: utf-8 bytes # - value: a Python data type, e.g. a Python int for _encode_int # - check_keys: bool, whether to check for invalid names # - opts: a CodecOptions _ENCODERS = { bool: _encode_bool, bytes: _encode_bytes, datetime.datetime: _encode_datetime, DatetimeMS: _encode_datetime_ms, dict: _encode_mapping, float: _encode_float, int: _encode_int, list: _encode_list, str: _encode_text, tuple: _encode_list, type(None): _encode_none, uuid.UUID: _encode_uuid, Binary: _encode_binary, Int64: _encode_long, Code: _encode_code, DBRef: _encode_dbref, MaxKey: _encode_maxkey, MinKey: _encode_minkey, ObjectId: _encode_objectid, Regex: _encode_regex, RE_TYPE: _encode_regex, SON: _encode_mapping, Timestamp: _encode_timestamp, Decimal128: _encode_decimal128, # Special case. This will never be looked up directly. _abc.Mapping: _encode_mapping, } # Map each _type_marker to its encoder for faster lookup. _MARKERS = {} for _typ in _ENCODERS: if hasattr(_typ, "_type_marker"): _MARKERS[_typ._type_marker] = _ENCODERS[_typ] _BUILT_IN_TYPES = tuple(t for t in _ENCODERS) def _name_value_to_bson( name: bytes, value: Any, check_keys: bool, opts: CodecOptions[Any], in_custom_call: bool = False, in_fallback_call: bool = False, ) -> bytes: """Encode a single name, value pair.""" was_integer_overflow = False # First see if the type is already cached. KeyError will only ever # happen once per subtype. try: return _ENCODERS[type(value)](name, value, check_keys, opts) # type: ignore except KeyError: pass except OverflowError: if not isinstance(value, int): raise # Give the fallback_encoder a chance was_integer_overflow = True # Second, fall back to trying _type_marker. This has to be done # before the loop below since users could subclass one of our # custom types that subclasses a python built-in (e.g. Binary) marker = getattr(value, "_type_marker", None) if isinstance(marker, int) and marker in _MARKERS: func = _MARKERS[marker] # Cache this type for faster subsequent lookup. _ENCODERS[type(value)] = func return func(name, value, check_keys, opts) # type: ignore # Third, check if a type encoder is registered for this type. # Note that subtypes of registered custom types are not auto-encoded. if not in_custom_call and opts.type_registry._encoder_map: custom_encoder = opts.type_registry._encoder_map.get(type(value)) if custom_encoder is not None: return _name_value_to_bson( name, custom_encoder(value), check_keys, opts, in_custom_call=True ) # Fourth, test each base type. This will only happen once for # a subtype of a supported base type. Unlike in the C-extensions, this # is done after trying the custom type encoder because checking for each # subtype is expensive. for base in _BUILT_IN_TYPES: if not was_integer_overflow and isinstance(value, base): func = _ENCODERS[base] # Cache this type for faster subsequent lookup. _ENCODERS[type(value)] = func return func(name, value, check_keys, opts) # type: ignore # As a last resort, try using the fallback encoder, if the user has # provided one. fallback_encoder = opts.type_registry._fallback_encoder if not in_fallback_call and fallback_encoder is not None: return _name_value_to_bson( name, fallback_encoder(value), check_keys, opts, in_fallback_call=True ) if was_integer_overflow: raise OverflowError("BSON can only handle up to 8-byte ints") raise InvalidDocument(f"cannot encode object: {value!r}, of type: {type(value)!r}") def _element_to_bson(key: Any, value: Any, check_keys: bool, opts: CodecOptions[Any]) -> bytes: """Encode a single key, value pair.""" if not isinstance(key, str): raise InvalidDocument(f"documents must have only string keys, key was {key!r}") if check_keys: if key.startswith("$"): raise InvalidDocument(f"key {key!r} must not start with '$'") if "." in key: raise InvalidDocument(f"key {key!r} must not contain '.'") name = _make_name(key) return _name_value_to_bson(name, value, check_keys, opts) def _dict_to_bson( doc: Any, check_keys: bool, opts: CodecOptions[Any], top_level: bool = True ) -> bytes: """Encode a document to BSON.""" if _raw_document_class(doc): return cast(bytes, doc.raw) try: elements = [] if top_level and "_id" in doc: elements.append(_name_value_to_bson(b"_id\x00", doc["_id"], check_keys, opts)) for key, value in doc.items(): if not top_level or key != "_id": elements.append(_element_to_bson(key, value, check_keys, opts)) except AttributeError: raise TypeError(f"encoder expected a mapping type but got: {doc!r}") from None encoded = b"".join(elements) return _PACK_INT(len(encoded) + 5) + encoded + b"\x00" if _USE_C: _dict_to_bson = _cbson._dict_to_bson _CODEC_OPTIONS_TYPE_ERROR = TypeError("codec_options must be an instance of CodecOptions") def encode( document: Mapping[str, Any], check_keys: bool = False, codec_options: CodecOptions[Any] = DEFAULT_CODEC_OPTIONS, ) -> bytes: """Encode a document to BSON. A document can be any mapping type (like :class:`dict`). Raises :class:`TypeError` if `document` is not a mapping type, or contains keys that are not instances of :class:`str`. Raises :class:`~bson.errors.InvalidDocument` if `document` cannot be converted to :class:`BSON`. :param document: mapping type representing a document :param check_keys: check if keys start with '$' or contain '.', raising :class:`~bson.errors.InvalidDocument` in either case :param codec_options: An instance of :class:`~bson.codec_options.CodecOptions`. .. versionadded:: 3.9 """ if not isinstance(codec_options, CodecOptions): raise _CODEC_OPTIONS_TYPE_ERROR return _dict_to_bson(document, check_keys, codec_options) @overload def decode(data: _ReadableBuffer, codec_options: None = None) -> dict[str, Any]: ... @overload def decode(data: _ReadableBuffer, codec_options: CodecOptions[_DocumentType]) -> _DocumentType: ... def decode( data: _ReadableBuffer, codec_options: Optional[CodecOptions[_DocumentType]] = None ) -> Union[dict[str, Any], _DocumentType]: """Decode BSON to a document. By default, returns a BSON document represented as a Python :class:`dict`. To use a different :class:`MutableMapping` class, configure a :class:`~bson.codec_options.CodecOptions`:: >>> import collections # From Python standard library. >>> import bson >>> from bson.codec_options import CodecOptions >>> data = bson.encode({'a': 1}) >>> decoded_doc = bson.decode(data) >>> options = CodecOptions(document_class=collections.OrderedDict) >>> decoded_doc = bson.decode(data, codec_options=options) >>> type(decoded_doc) :param data: the BSON to decode. Any bytes-like object that implements the buffer protocol. :param codec_options: An instance of :class:`~bson.codec_options.CodecOptions`. .. versionadded:: 3.9 """ opts: CodecOptions[Any] = codec_options or DEFAULT_CODEC_OPTIONS if not isinstance(opts, CodecOptions): raise _CODEC_OPTIONS_TYPE_ERROR return cast("Union[dict[str, Any], _DocumentType]", _bson_to_dict(data, opts)) def _decode_all(data: _ReadableBuffer, opts: CodecOptions[_DocumentType]) -> list[_DocumentType]: """Decode a BSON data to multiple documents.""" data, view = get_data_and_view(data) data_len = len(data) docs: list[_DocumentType] = [] position = 0 end = data_len - 1 use_raw = _raw_document_class(opts.document_class) try: while position < end: obj_size = _UNPACK_INT_FROM(data, position)[0] if data_len - position < obj_size: raise InvalidBSON("invalid object size") obj_end = position + obj_size - 1 if data[obj_end] != 0: raise InvalidBSON("bad eoo") if use_raw: docs.append(opts.document_class(data[position : obj_end + 1], opts)) # type: ignore else: docs.append(_elements_to_dict(data, view, position + 4, obj_end, opts)) position += obj_size return docs except InvalidBSON: raise except Exception: # Change exception type to InvalidBSON but preserve traceback. _, exc_value, exc_tb = sys.exc_info() raise InvalidBSON(str(exc_value)).with_traceback(exc_tb) from None if _USE_C: _decode_all = _cbson._decode_all @overload def decode_all(data: _ReadableBuffer, codec_options: None = None) -> list[dict[str, Any]]: ... @overload def decode_all( data: _ReadableBuffer, codec_options: CodecOptions[_DocumentType] ) -> list[_DocumentType]: ... def decode_all( data: _ReadableBuffer, codec_options: Optional[CodecOptions[_DocumentType]] = None ) -> Union[list[dict[str, Any]], list[_DocumentType]]: """Decode BSON data to multiple documents. `data` must be a bytes-like object implementing the buffer protocol that provides concatenated, valid, BSON-encoded documents. :param data: BSON data :param codec_options: An instance of :class:`~bson.codec_options.CodecOptions`. .. versionchanged:: 3.9 Supports bytes-like objects that implement the buffer protocol. .. versionchanged:: 3.0 Removed `compile_re` option: PyMongo now always represents BSON regular expressions as :class:`~bson.regex.Regex` objects. Use :meth:`~bson.regex.Regex.try_compile` to attempt to convert from a BSON regular expression to a Python regular expression object. Replaced `as_class`, `tz_aware`, and `uuid_subtype` options with `codec_options`. """ if codec_options is None: return _decode_all(data, DEFAULT_CODEC_OPTIONS) if not isinstance(codec_options, CodecOptions): raise _CODEC_OPTIONS_TYPE_ERROR return _decode_all(data, codec_options) def _decode_selective( rawdoc: Any, fields: Any, codec_options: CodecOptions[_DocumentType] ) -> _DocumentType: if _raw_document_class(codec_options.document_class): # If document_class is RawBSONDocument, use vanilla dictionary for # decoding command response. doc: _DocumentType = {} # type:ignore[assignment] else: # Else, use the specified document_class. doc = codec_options.document_class() for key, value in rawdoc.items(): if key in fields: if fields[key] == 1: doc[key] = _bson_to_dict(rawdoc.raw, codec_options)[key] # type:ignore[index] else: doc[key] = _decode_selective( # type:ignore[index] value, fields[key], codec_options ) else: doc[key] = value # type:ignore[index] return doc def _array_of_documents_to_buffer(view: memoryview) -> bytes: # Extract the raw bytes of each document. position = 0 _, end = _get_object_size(view, position, len(view)) position += 4 buffers: list[memoryview] = [] append = buffers.append while position < end - 1: # Just skip the keys. while view[position] != 0: position += 1 position += 1 obj_size, _ = _get_object_size(view, position, end) append(view[position : position + obj_size]) position += obj_size if position != end: raise InvalidBSON("bad object or element length") return b"".join(buffers) if _USE_C: _array_of_documents_to_buffer = _cbson._array_of_documents_to_buffer def _convert_raw_document_lists_to_streams(document: Any) -> None: """Convert raw array of documents to a stream of BSON documents.""" cursor = document.get("cursor") if not cursor: return for key in ("firstBatch", "nextBatch"): batch = cursor.get(key) if not batch: continue data = _array_of_documents_to_buffer(batch) if data: cursor[key] = [data] else: cursor[key] = [] def _decode_all_selective( data: Any, codec_options: CodecOptions[_DocumentType], fields: Any ) -> list[_DocumentType]: """Decode BSON data to a single document while using user-provided custom decoding logic. `data` must be a string representing a valid, BSON-encoded document. :param data: BSON data :param codec_options: An instance of :class:`~bson.codec_options.CodecOptions` with user-specified type decoders. If no decoders are found, this method is the same as ``decode_all``. :param fields: Map of document namespaces where data that needs to be custom decoded lives or None. For example, to custom decode a list of objects in 'field1.subfield1', the specified value should be ``{'field1': {'subfield1': 1}}``. If ``fields`` is an empty map or None, this method is the same as ``decode_all``. :return: Single-member list containing the decoded document. .. versionadded:: 3.8 """ if not codec_options.type_registry._decoder_map: return decode_all(data, codec_options) if not fields: return decode_all(data, codec_options.with_options(type_registry=None)) # Decode documents for internal use. from bson.raw_bson import RawBSONDocument internal_codec_options: CodecOptions[RawBSONDocument] = codec_options.with_options( document_class=RawBSONDocument, type_registry=None ) _doc = _bson_to_dict(data, internal_codec_options) return [ _decode_selective( _doc, fields, codec_options, ) ] @overload def decode_iter(data: bytes, codec_options: None = None) -> Iterator[dict[str, Any]]: ... @overload def decode_iter(data: bytes, codec_options: CodecOptions[_DocumentType]) -> Iterator[_DocumentType]: ... def decode_iter( data: bytes, codec_options: Optional[CodecOptions[_DocumentType]] = None ) -> Union[Iterator[dict[str, Any]], Iterator[_DocumentType]]: """Decode BSON data to multiple documents as a generator. Works similarly to the decode_all function, but yields one document at a time. `data` must be a string of concatenated, valid, BSON-encoded documents. :param data: BSON data :param codec_options: An instance of :class:`~bson.codec_options.CodecOptions`. .. versionchanged:: 3.0 Replaced `as_class`, `tz_aware`, and `uuid_subtype` options with `codec_options`. .. versionadded:: 2.8 """ opts = codec_options or DEFAULT_CODEC_OPTIONS if not isinstance(opts, CodecOptions): raise _CODEC_OPTIONS_TYPE_ERROR position = 0 end = len(data) - 1 while position < end: obj_size = _UNPACK_INT_FROM(data, position)[0] elements = data[position : position + obj_size] position += obj_size yield _bson_to_dict(elements, opts) # type:ignore[misc, type-var] @overload def decode_file_iter( file_obj: Union[BinaryIO, IO[bytes]], codec_options: None = None ) -> Iterator[dict[str, Any]]: ... @overload def decode_file_iter( file_obj: Union[BinaryIO, IO[bytes]], codec_options: CodecOptions[_DocumentType] ) -> Iterator[_DocumentType]: ... def decode_file_iter( file_obj: Union[BinaryIO, IO[bytes]], codec_options: Optional[CodecOptions[_DocumentType]] = None, ) -> Union[Iterator[dict[str, Any]], Iterator[_DocumentType]]: """Decode bson data from a file to multiple documents as a generator. Works similarly to the decode_all function, but reads from the file object in chunks and parses bson in chunks, yielding one document at a time. :param file_obj: A file object containing BSON data. :param codec_options: An instance of :class:`~bson.codec_options.CodecOptions`. .. versionchanged:: 3.0 Replaced `as_class`, `tz_aware`, and `uuid_subtype` options with `codec_options`. .. versionadded:: 2.8 """ opts = codec_options or DEFAULT_CODEC_OPTIONS while True: # Read size of next object. size_data: Any = file_obj.read(4) if not size_data: break # Finished with file normally. elif len(size_data) != 4: raise InvalidBSON("cut off in middle of objsize") obj_size = _UNPACK_INT_FROM(size_data, 0)[0] - 4 elements = size_data + file_obj.read(max(0, obj_size)) yield _bson_to_dict(elements, opts) # type:ignore[type-var, arg-type, misc] def is_valid(bson: bytes) -> bool: """Check that the given string represents valid :class:`BSON` data. Raises :class:`TypeError` if `bson` is not an instance of :class:`bytes`. Returns ``True`` if `bson` is valid :class:`BSON`, ``False`` otherwise. :param bson: the data to be validated """ if not isinstance(bson, bytes): raise TypeError("BSON data must be an instance of a subclass of bytes") try: _bson_to_dict(bson, DEFAULT_CODEC_OPTIONS) return True except Exception: return False class BSON(bytes): """BSON (Binary JSON) data. .. warning:: Using this class to encode and decode BSON adds a performance cost. For better performance use the module level functions :func:`encode` and :func:`decode` instead. """ @classmethod def encode( cls: Type[BSON], document: Mapping[str, Any], check_keys: bool = False, codec_options: CodecOptions[Any] = DEFAULT_CODEC_OPTIONS, ) -> BSON: """Encode a document to a new :class:`BSON` instance. A document can be any mapping type (like :class:`dict`). Raises :class:`TypeError` if `document` is not a mapping type, or contains keys that are not instances of :class:`str'. Raises :class:`~bson.errors.InvalidDocument` if `document` cannot be converted to :class:`BSON`. :param document: mapping type representing a document :param check_keys: check if keys start with '$' or contain '.', raising :class:`~bson.errors.InvalidDocument` in either case :param codec_options: An instance of :class:`~bson.codec_options.CodecOptions`. .. versionchanged:: 3.0 Replaced `uuid_subtype` option with `codec_options`. """ return cls(encode(document, check_keys, codec_options)) def decode( # type:ignore[override] self, codec_options: CodecOptions[Any] = DEFAULT_CODEC_OPTIONS ) -> dict[str, Any]: """Decode this BSON data. By default, returns a BSON document represented as a Python :class:`dict`. To use a different :class:`MutableMapping` class, configure a :class:`~bson.codec_options.CodecOptions`:: >>> import collections # From Python standard library. >>> import bson >>> from bson.codec_options import CodecOptions >>> data = bson.BSON.encode({'a': 1}) >>> decoded_doc = bson.BSON(data).decode() >>> options = CodecOptions(document_class=collections.OrderedDict) >>> decoded_doc = bson.BSON(data).decode(codec_options=options) >>> type(decoded_doc) :param codec_options: An instance of :class:`~bson.codec_options.CodecOptions`. .. versionchanged:: 3.0 Removed `compile_re` option: PyMongo now always represents BSON regular expressions as :class:`~bson.regex.Regex` objects. Use :meth:`~bson.regex.Regex.try_compile` to attempt to convert from a BSON regular expression to a Python regular expression object. Replaced `as_class`, `tz_aware`, and `uuid_subtype` options with `codec_options`. """ return decode(self, codec_options) def has_c() -> bool: """Is the C extension installed?""" return _USE_C def _after_fork() -> None: """Releases the ObjectID lock child.""" if ObjectId._inc_lock.locked(): ObjectId._inc_lock.release() if hasattr(os, "register_at_fork"): # This will run in the same thread as the fork was called. # If we fork in a critical region on the same thread, it should break. # This is fine since we would never call fork directly from a critical region. os.register_at_fork(after_in_child=_after_fork) mongodb-mongo-python-driver-509e9b7/bson/_cbsonmodule.c000066400000000000000000003103121462766011000232130ustar00rootroot00000000000000/* * Copyright 2009-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. */ /* * This file contains C implementations of some of the functions * needed by the bson module. If possible, these implementations * should be used to speed up BSON encoding and decoding. */ #define PY_SSIZE_T_CLEAN #include "Python.h" #include "datetime.h" #include "buffer.h" #include "time64.h" #define _CBSON_MODULE #include "_cbsonmodule.h" /* New module state and initialization code. * See the module-initialization-and-state * section in the following doc: * http://docs.python.org/release/3.1.3/howto/cporting.html * which references the following pep: * http://www.python.org/dev/peps/pep-3121/ * */ struct module_state { PyObject* Binary; PyObject* Code; PyObject* ObjectId; PyObject* DBRef; PyObject* Regex; PyObject* UUID; PyObject* Timestamp; PyObject* MinKey; PyObject* MaxKey; PyObject* UTC; PyTypeObject* REType; PyObject* BSONInt64; PyObject* Decimal128; PyObject* Mapping; PyObject* DatetimeMS; PyObject* _min_datetime_ms; PyObject* _max_datetime_ms; PyObject* _type_marker_str; PyObject* _flags_str; PyObject* _pattern_str; PyObject* _encoder_map_str; PyObject* _decoder_map_str; PyObject* _fallback_encoder_str; PyObject* _raw_str; PyObject* _subtype_str; PyObject* _binary_str; PyObject* _scope_str; PyObject* _inc_str; PyObject* _time_str; PyObject* _bid_str; PyObject* _replace_str; PyObject* _astimezone_str; PyObject* _id_str; PyObject* _dollar_ref_str; PyObject* _dollar_id_str; PyObject* _dollar_db_str; PyObject* _tzinfo_str; PyObject* _as_doc_str; PyObject* _utcoffset_str; PyObject* _from_uuid_str; PyObject* _as_uuid_str; PyObject* _from_bid_str; }; #define GETSTATE(m) ((struct module_state*)PyModule_GetState(m)) /* Maximum number of regex flags */ #define FLAGS_SIZE 7 /* Default UUID representation type code. */ #define PYTHON_LEGACY 3 /* Other UUID representations. */ #define STANDARD 4 #define JAVA_LEGACY 5 #define CSHARP_LEGACY 6 #define UNSPECIFIED 0 #define BSON_MAX_SIZE 2147483647 /* The smallest possible BSON document, i.e. "{}" */ #define BSON_MIN_SIZE 5 /* Datetime codec options */ #define DATETIME 1 #define DATETIME_CLAMP 2 #define DATETIME_MS 3 #define DATETIME_AUTO 4 /* Converts integer to its string representation in decimal notation. */ extern int cbson_long_long_to_str(long long num, char* str, size_t size) { // Buffer should fit 64-bit signed integer if (size < 21) { PyErr_Format( PyExc_RuntimeError, "Buffer too small to hold long long: %d < 21", size); return -1; } int index = 0; int sign = 1; // Convert to unsigned to handle -LLONG_MIN overflow unsigned long long absNum; // Handle the case of 0 if (num == 0) { str[index++] = '0'; str[index] = '\0'; return 0; } // Handle negative numbers if (num < 0) { sign = -1; absNum = 0ULL - (unsigned long long)num; } else { absNum = (unsigned long long)num; } // Convert the number to string unsigned long long digit; while (absNum > 0) { digit = absNum % 10ULL; str[index++] = (char)digit + '0'; // Convert digit to character absNum /= 10; } // Add minus sign if negative if (sign == -1) { str[index++] = '-'; } str[index] = '\0'; // Null terminator // Reverse the string int start = 0; int end = index - 1; while (start < end) { char temp = str[start]; str[start++] = str[end]; str[end--] = temp; } return 0; } static PyObject* _test_long_long_to_str(PyObject* self, PyObject* args) { // Test extreme values Py_ssize_t maxNum = PY_SSIZE_T_MAX; Py_ssize_t minNum = PY_SSIZE_T_MIN; Py_ssize_t num; char str_1[BUF_SIZE]; char str_2[BUF_SIZE]; int res = LL2STR(str_1, (long long)minNum); if (res == -1) { return NULL; } INT2STRING(str_2, (long long)minNum); if (strcmp(str_1, str_2) != 0) { PyErr_Format( PyExc_RuntimeError, "LL2STR != INT2STRING: %s != %s", str_1, str_2); return NULL; } LL2STR(str_1, (long long)maxNum); INT2STRING(str_2, (long long)maxNum); if (strcmp(str_1, str_2) != 0) { PyErr_Format( PyExc_RuntimeError, "LL2STR != INT2STRING: %s != %s", str_1, str_2); return NULL; } // Test common values for (num = 0; num < 10000; num++) { char str_1[BUF_SIZE]; char str_2[BUF_SIZE]; LL2STR(str_1, (long long)num); INT2STRING(str_2, (long long)num); if (strcmp(str_1, str_2) != 0) { PyErr_Format( PyExc_RuntimeError, "LL2STR != INT2STRING: %s != %s", str_1, str_2); return NULL; } } return args; } /* Get an error class from the bson.errors module. * * Returns a new ref */ static PyObject* _error(char* name) { PyObject* error; PyObject* errors = PyImport_ImportModule("bson.errors"); if (!errors) { return NULL; } error = PyObject_GetAttrString(errors, name); Py_DECREF(errors); return error; } /* Safely downcast from Py_ssize_t to int, setting an * exception and returning -1 on error. */ static int _downcast_and_check(Py_ssize_t size, uint8_t extra) { if (size > BSON_MAX_SIZE || ((BSON_MAX_SIZE - extra) < size)) { PyObject* InvalidStringData = _error("InvalidStringData"); if (InvalidStringData) { PyErr_SetString(InvalidStringData, "String length must be <= 2147483647"); Py_DECREF(InvalidStringData); } return -1; } return (int)size + extra; } static PyObject* elements_to_dict(PyObject* self, const char* string, unsigned max, const codec_options_t* options); static int _write_element_to_buffer(PyObject* self, buffer_t buffer, int type_byte, PyObject* value, unsigned char check_keys, const codec_options_t* options, unsigned char in_custom_call, unsigned char in_fallback_call); /* Write a RawBSONDocument to the buffer. * Returns the number of bytes written or 0 on failure. */ static int write_raw_doc(buffer_t buffer, PyObject* raw, PyObject* _raw); /* Date stuff */ static PyObject* datetime_from_millis(long long millis) { /* To encode a datetime instance like datetime(9999, 12, 31, 23, 59, 59, 999999) * we follow these steps: * 1. Calculate a timestamp in seconds: 253402300799 * 2. Multiply that by 1000: 253402300799000 * 3. Add in microseconds divided by 1000 253402300799999 * * (Note: BSON doesn't support microsecond accuracy, hence the rounding.) * * To decode we could do: * 1. Get seconds: timestamp / 1000: 253402300799 * 2. Get micros: (timestamp % 1000) * 1000: 999000 * Resulting in datetime(9999, 12, 31, 23, 59, 59, 999000) -- the expected result * * Now what if the we encode (1, 1, 1, 1, 1, 1, 111111)? * 1. and 2. gives: -62135593139000 * 3. Gives us: -62135593138889 * * Now decode: * 1. Gives us: -62135593138 * 2. Gives us: -889000 * Resulting in datetime(1, 1, 1, 1, 1, 2, 15888216) -- an invalid result * * If instead to decode we do: * diff = ((millis % 1000) + 1000) % 1000: 111 * seconds = (millis - diff) / 1000: -62135593139 * micros = diff * 1000 111000 * Resulting in datetime(1, 1, 1, 1, 1, 1, 111000) -- the expected result */ PyObject* datetime; int diff = (int)(((millis % 1000) + 1000) % 1000); int microseconds = diff * 1000; Time64_T seconds = (millis - diff) / 1000; struct TM timeinfo; cbson_gmtime64_r(&seconds, &timeinfo); datetime = PyDateTime_FromDateAndTime(timeinfo.tm_year + 1900, timeinfo.tm_mon + 1, timeinfo.tm_mday, timeinfo.tm_hour, timeinfo.tm_min, timeinfo.tm_sec, microseconds); if(!datetime) { PyObject *etype, *evalue, *etrace; /* * Calling _error clears the error state, so fetch it first. */ PyErr_Fetch(&etype, &evalue, &etrace); /* Only add addition error message on ValueError exceptions. */ if (PyErr_GivenExceptionMatches(etype, PyExc_ValueError)) { if (evalue) { PyObject* err_msg = PyObject_Str(evalue); if (err_msg) { PyObject* appendage = PyUnicode_FromString(" (Consider Using CodecOptions(datetime_conversion=DATETIME_AUTO) or MongoClient(datetime_conversion='DATETIME_AUTO')). See: https://pymongo.readthedocs.io/en/stable/examples/datetimes.html#handling-out-of-range-datetimes"); if (appendage) { PyObject* msg = PyUnicode_Concat(err_msg, appendage); if (msg) { Py_DECREF(evalue); evalue = msg; } } Py_XDECREF(appendage); } Py_XDECREF(err_msg); } PyErr_NormalizeException(&etype, &evalue, &etrace); } /* Steals references to args. */ PyErr_Restore(etype, evalue, etrace); } return datetime; } static long long millis_from_datetime(PyObject* datetime) { struct TM timeinfo; long long millis; timeinfo.tm_year = PyDateTime_GET_YEAR(datetime) - 1900; timeinfo.tm_mon = PyDateTime_GET_MONTH(datetime) - 1; timeinfo.tm_mday = PyDateTime_GET_DAY(datetime); timeinfo.tm_hour = PyDateTime_DATE_GET_HOUR(datetime); timeinfo.tm_min = PyDateTime_DATE_GET_MINUTE(datetime); timeinfo.tm_sec = PyDateTime_DATE_GET_SECOND(datetime); millis = cbson_timegm64(&timeinfo) * 1000; millis += PyDateTime_DATE_GET_MICROSECOND(datetime) / 1000; return millis; } /* Extended-range datetime, returns a DatetimeMS object with millis */ static PyObject* datetime_ms_from_millis(PyObject* self, long long millis){ // Allocate a new DatetimeMS object. struct module_state *state = GETSTATE(self); if (!state) { return NULL; } PyObject* dt; PyObject* ll_millis; if (!(ll_millis = PyLong_FromLongLong(millis))){ return NULL; } dt = PyObject_CallFunctionObjArgs(state->DatetimeMS, ll_millis, NULL); Py_DECREF(ll_millis); return dt; } /* Extended-range datetime, takes a DatetimeMS object and extracts the long long value. */ static int millis_from_datetime_ms(PyObject* dt, long long* out){ PyObject* ll_millis; long long millis; if (!(ll_millis = PyNumber_Long(dt))){ return 0; } millis = PyLong_AsLongLong(ll_millis); Py_DECREF(ll_millis); if (millis == -1 && PyErr_Occurred()) { /* Overflow */ PyErr_SetString(PyExc_OverflowError, "MongoDB datetimes can only handle up to 8-byte ints"); return 0; } *out = millis; return 1; } /* Just make this compatible w/ the old API. */ int buffer_write_bytes(buffer_t buffer, const char* data, int size) { if (pymongo_buffer_write(buffer, data, size)) { return 0; } return 1; } int buffer_write_double(buffer_t buffer, double data) { double data_le = BSON_DOUBLE_TO_LE(data); return buffer_write_bytes(buffer, (const char*)&data_le, 8); } int buffer_write_int32(buffer_t buffer, int32_t data) { uint32_t data_le = BSON_UINT32_TO_LE(data); return buffer_write_bytes(buffer, (const char*)&data_le, 4); } int buffer_write_int64(buffer_t buffer, int64_t data) { uint64_t data_le = BSON_UINT64_TO_LE(data); return buffer_write_bytes(buffer, (const char*)&data_le, 8); } void buffer_write_int32_at_position(buffer_t buffer, int position, int32_t data) { uint32_t data_le = BSON_UINT32_TO_LE(data); memcpy(pymongo_buffer_get_buffer(buffer) + position, &data_le, 4); } static int write_unicode(buffer_t buffer, PyObject* py_string) { int size; const char* data; PyObject* encoded = PyUnicode_AsUTF8String(py_string); if (!encoded) { return 0; } data = PyBytes_AS_STRING(encoded); if (!data) goto unicodefail; if ((size = _downcast_and_check(PyBytes_GET_SIZE(encoded), 1)) == -1) goto unicodefail; if (!buffer_write_int32(buffer, (int32_t)size)) goto unicodefail; if (!buffer_write_bytes(buffer, data, size)) goto unicodefail; Py_DECREF(encoded); return 1; unicodefail: Py_DECREF(encoded); return 0; } /* returns 0 on failure */ static int write_string(buffer_t buffer, PyObject* py_string) { int size; const char* data; if (PyUnicode_Check(py_string)){ return write_unicode(buffer, py_string); } data = PyBytes_AsString(py_string); if (!data) { return 0; } if ((size = _downcast_and_check(PyBytes_Size(py_string), 1)) == -1) return 0; if (!buffer_write_int32(buffer, (int32_t)size)) { return 0; } if (!buffer_write_bytes(buffer, data, size)) { return 0; } return 1; } /* Load a Python object to cache. * * Returns non-zero on failure. */ static int _load_object(PyObject** object, char* module_name, char* object_name) { PyObject* module; module = PyImport_ImportModule(module_name); if (!module) { return 1; } *object = PyObject_GetAttrString(module, object_name); Py_DECREF(module); return (*object) ? 0 : 2; } /* Load all Python objects to cache. * * Returns non-zero on failure. */ static int _load_python_objects(PyObject* module) { PyObject* empty_string = NULL; PyObject* re_compile = NULL; PyObject* compiled = NULL; struct module_state *state = GETSTATE(module); if (!state) { return 1; } /* Cache commonly used attribute names to improve performance. */ if (!((state->_type_marker_str = PyUnicode_FromString("_type_marker")) && (state->_flags_str = PyUnicode_FromString("flags")) && (state->_pattern_str = PyUnicode_FromString("pattern")) && (state->_encoder_map_str = PyUnicode_FromString("_encoder_map")) && (state->_decoder_map_str = PyUnicode_FromString("_decoder_map")) && (state->_fallback_encoder_str = PyUnicode_FromString("_fallback_encoder")) && (state->_raw_str = PyUnicode_FromString("raw")) && (state->_subtype_str = PyUnicode_FromString("subtype")) && (state->_binary_str = PyUnicode_FromString("binary")) && (state->_scope_str = PyUnicode_FromString("scope")) && (state->_inc_str = PyUnicode_FromString("inc")) && (state->_time_str = PyUnicode_FromString("time")) && (state->_bid_str = PyUnicode_FromString("bid")) && (state->_replace_str = PyUnicode_FromString("replace")) && (state->_astimezone_str = PyUnicode_FromString("astimezone")) && (state->_id_str = PyUnicode_FromString("_id")) && (state->_dollar_ref_str = PyUnicode_FromString("$ref")) && (state->_dollar_id_str = PyUnicode_FromString("$id")) && (state->_dollar_db_str = PyUnicode_FromString("$db")) && (state->_tzinfo_str = PyUnicode_FromString("tzinfo")) && (state->_as_doc_str = PyUnicode_FromString("as_doc")) && (state->_utcoffset_str = PyUnicode_FromString("utcoffset")) && (state->_from_uuid_str = PyUnicode_FromString("from_uuid")) && (state->_as_uuid_str = PyUnicode_FromString("as_uuid")) && (state->_from_bid_str = PyUnicode_FromString("from_bid")))) { return 1; } if (_load_object(&state->Binary, "bson.binary", "Binary") || _load_object(&state->Code, "bson.code", "Code") || _load_object(&state->ObjectId, "bson.objectid", "ObjectId") || _load_object(&state->DBRef, "bson.dbref", "DBRef") || _load_object(&state->Timestamp, "bson.timestamp", "Timestamp") || _load_object(&state->MinKey, "bson.min_key", "MinKey") || _load_object(&state->MaxKey, "bson.max_key", "MaxKey") || _load_object(&state->UTC, "bson.tz_util", "utc") || _load_object(&state->Regex, "bson.regex", "Regex") || _load_object(&state->BSONInt64, "bson.int64", "Int64") || _load_object(&state->Decimal128, "bson.decimal128", "Decimal128") || _load_object(&state->UUID, "uuid", "UUID") || _load_object(&state->Mapping, "collections.abc", "Mapping") || _load_object(&state->DatetimeMS, "bson.datetime_ms", "DatetimeMS") || _load_object(&state->_min_datetime_ms, "bson.datetime_ms", "_min_datetime_ms") || _load_object(&state->_max_datetime_ms, "bson.datetime_ms", "_max_datetime_ms")) { return 1; } /* Reload our REType hack too. */ empty_string = PyBytes_FromString(""); if (empty_string == NULL) { state->REType = NULL; return 1; } if (_load_object(&re_compile, "re", "compile")) { state->REType = NULL; Py_DECREF(empty_string); return 1; } compiled = PyObject_CallFunction(re_compile, "O", empty_string); Py_DECREF(re_compile); if (compiled == NULL) { state->REType = NULL; Py_DECREF(empty_string); return 1; } Py_INCREF(Py_TYPE(compiled)); state->REType = Py_TYPE(compiled); Py_DECREF(empty_string); Py_DECREF(compiled); return 0; } /* * Get the _type_marker from an Object. * * Return the type marker, 0 if there is no marker, or -1 on failure. */ static long _type_marker(PyObject* object, PyObject* _type_marker_str) { PyObject* type_marker = NULL; long type = 0; if (PyObject_HasAttr(object, _type_marker_str)) { type_marker = PyObject_GetAttr(object, _type_marker_str); if (type_marker == NULL) { return -1; } } /* * Python objects with broken __getattr__ implementations could return * arbitrary types for a call to PyObject_GetAttrString. For example * pymongo.database.Database returns a new Collection instance for * __getattr__ calls with names that don't match an existing attribute * or method. In some cases "value" could be a subtype of something * we know how to serialize. Make a best effort to encode these types. */ if (type_marker && PyLong_CheckExact(type_marker)) { type = PyLong_AsLong(type_marker); Py_DECREF(type_marker); } else { Py_XDECREF(type_marker); } return type; } /* Fill out a type_registry_t* from a TypeRegistry object. * * Return 1 on success. options->document_class is a new reference. * Return 0 on failure. */ int cbson_convert_type_registry(PyObject* registry_obj, type_registry_t* registry, PyObject* _encoder_map_str, PyObject* _decoder_map_str, PyObject* _fallback_encoder_str) { registry->encoder_map = NULL; registry->decoder_map = NULL; registry->fallback_encoder = NULL; registry->registry_obj = NULL; registry->encoder_map = PyObject_GetAttr(registry_obj, _encoder_map_str); if (registry->encoder_map == NULL) { goto fail; } registry->is_encoder_empty = (PyDict_Size(registry->encoder_map) == 0); registry->decoder_map = PyObject_GetAttr(registry_obj, _decoder_map_str); if (registry->decoder_map == NULL) { goto fail; } registry->is_decoder_empty = (PyDict_Size(registry->decoder_map) == 0); registry->fallback_encoder = PyObject_GetAttr(registry_obj, _fallback_encoder_str); if (registry->fallback_encoder == NULL) { goto fail; } registry->has_fallback_encoder = (registry->fallback_encoder != Py_None); registry->registry_obj = registry_obj; Py_INCREF(registry->registry_obj); return 1; fail: Py_XDECREF(registry->encoder_map); Py_XDECREF(registry->decoder_map); Py_XDECREF(registry->fallback_encoder); return 0; } /* Fill out a codec_options_t* from a CodecOptions object. * * Return 1 on success. options->document_class is a new reference. * Return 0 on failure. */ int convert_codec_options(PyObject* self, PyObject* options_obj, codec_options_t* options) { PyObject* type_registry_obj = NULL; struct module_state *state = GETSTATE(self); long type_marker; if (!state) { return 0; } options->unicode_decode_error_handler = NULL; if (!PyArg_ParseTuple(options_obj, "ObbzOOb", &options->document_class, &options->tz_aware, &options->uuid_rep, &options->unicode_decode_error_handler, &options->tzinfo, &type_registry_obj, &options->datetime_conversion)) { return 0; } type_marker = _type_marker(options->document_class, state->_type_marker_str); if (type_marker < 0) { return 0; } if (!cbson_convert_type_registry(type_registry_obj, &options->type_registry, state->_encoder_map_str, state->_decoder_map_str, state->_fallback_encoder_str)) { return 0; } options->is_raw_bson = (101 == type_marker); options->options_obj = options_obj; Py_INCREF(options->options_obj); Py_INCREF(options->document_class); Py_INCREF(options->tzinfo); return 1; } void destroy_codec_options(codec_options_t* options) { Py_CLEAR(options->document_class); Py_CLEAR(options->tzinfo); Py_CLEAR(options->options_obj); Py_CLEAR(options->type_registry.registry_obj); Py_CLEAR(options->type_registry.encoder_map); Py_CLEAR(options->type_registry.decoder_map); Py_CLEAR(options->type_registry.fallback_encoder); } static int write_element_to_buffer(PyObject* self, buffer_t buffer, int type_byte, PyObject* value, unsigned char check_keys, const codec_options_t* options, unsigned char in_custom_call, unsigned char in_fallback_call) { int result = 0; if(Py_EnterRecursiveCall(" while encoding an object to BSON ")) { return 0; } result = _write_element_to_buffer(self, buffer, type_byte, value, check_keys, options, in_custom_call, in_fallback_call); Py_LeaveRecursiveCall(); return result; } static void _set_cannot_encode(PyObject* value) { if (PyLong_Check(value)) { if ((PyLong_AsLongLong(value) == -1) && PyErr_Occurred()) { return PyErr_SetString(PyExc_OverflowError, "MongoDB can only handle up to 8-byte ints"); } } PyObject* type = NULL; PyObject* InvalidDocument = _error("InvalidDocument"); if (InvalidDocument == NULL) { goto error; } type = PyObject_Type(value); if (type == NULL) { goto error; } PyErr_Format(InvalidDocument, "cannot encode object: %R, of type: %R", value, type); error: Py_XDECREF(type); Py_XDECREF(InvalidDocument); } /* * Encode a builtin Python regular expression or our custom Regex class. * * Sets exception and returns 0 on failure. */ static int _write_regex_to_buffer( buffer_t buffer, int type_byte, PyObject* value, PyObject* _flags_str, PyObject* _pattern_str) { PyObject* py_flags; PyObject* py_pattern; PyObject* encoded_pattern; PyObject* decoded_pattern; long int_flags; char flags[FLAGS_SIZE]; char check_utf8 = 0; const char* pattern_data; int pattern_length, flags_length; /* * Both the builtin re type and our Regex class have attributes * "flags" and "pattern". */ py_flags = PyObject_GetAttr(value, _flags_str); if (!py_flags) { return 0; } int_flags = PyLong_AsLong(py_flags); Py_DECREF(py_flags); if (int_flags == -1 && PyErr_Occurred()) { return 0; } py_pattern = PyObject_GetAttr(value, _pattern_str); if (!py_pattern) { return 0; } if (PyUnicode_Check(py_pattern)) { encoded_pattern = PyUnicode_AsUTF8String(py_pattern); Py_DECREF(py_pattern); if (!encoded_pattern) { return 0; } } else { encoded_pattern = py_pattern; check_utf8 = 1; } if (!(pattern_data = PyBytes_AsString(encoded_pattern))) { Py_DECREF(encoded_pattern); return 0; } if ((pattern_length = _downcast_and_check(PyBytes_Size(encoded_pattern), 0)) == -1) { Py_DECREF(encoded_pattern); return 0; } if (strlen(pattern_data) != (size_t) pattern_length){ PyObject* InvalidDocument = _error("InvalidDocument"); if (InvalidDocument) { PyErr_SetString(InvalidDocument, "regex patterns must not contain the NULL byte"); Py_DECREF(InvalidDocument); } Py_DECREF(encoded_pattern); return 0; } if (check_utf8) { decoded_pattern = PyUnicode_DecodeUTF8(pattern_data, (Py_ssize_t) pattern_length, NULL); if (decoded_pattern == NULL) { PyErr_Clear(); PyObject* InvalidStringData = _error("InvalidStringData"); if (InvalidStringData) { PyErr_SetString(InvalidStringData, "regex patterns must be valid UTF-8"); Py_DECREF(InvalidStringData); } Py_DECREF(encoded_pattern); return 0; } Py_DECREF(decoded_pattern); } if (!buffer_write_bytes(buffer, pattern_data, pattern_length + 1)) { Py_DECREF(encoded_pattern); return 0; } Py_DECREF(encoded_pattern); flags[0] = 0; if (int_flags & 2) { STRCAT(flags, FLAGS_SIZE, "i"); } if (int_flags & 4) { STRCAT(flags, FLAGS_SIZE, "l"); } if (int_flags & 8) { STRCAT(flags, FLAGS_SIZE, "m"); } if (int_flags & 16) { STRCAT(flags, FLAGS_SIZE, "s"); } if (int_flags & 32) { STRCAT(flags, FLAGS_SIZE, "u"); } if (int_flags & 64) { STRCAT(flags, FLAGS_SIZE, "x"); } flags_length = (int)strlen(flags) + 1; if (!buffer_write_bytes(buffer, flags, flags_length)) { return 0; } *(pymongo_buffer_get_buffer(buffer) + type_byte) = 0x0B; return 1; } /* Write a single value to the buffer (also write its type_byte, for which * space has already been reserved. * * returns 0 on failure */ static int _write_element_to_buffer(PyObject* self, buffer_t buffer, int type_byte, PyObject* value, unsigned char check_keys, const codec_options_t* options, unsigned char in_custom_call, unsigned char in_fallback_call) { PyObject* new_value = NULL; int retval; int is_list; long type; struct module_state *state = GETSTATE(self); if (!state) { return 0; } /* * Use _type_marker attribute instead of PyObject_IsInstance for better perf. */ type = _type_marker(value, state->_type_marker_str); if (type < 0) { return 0; } switch (type) { case 5: { /* Binary */ PyObject* subtype_object; char subtype; const char* data; int size; *(pymongo_buffer_get_buffer(buffer) + type_byte) = 0x05; subtype_object = PyObject_GetAttr(value, state->_subtype_str); if (!subtype_object) { return 0; } subtype = (char)PyLong_AsLong(subtype_object); if (subtype == -1) { Py_DECREF(subtype_object); return 0; } size = _downcast_and_check(PyBytes_Size(value), 0); if (size == -1) { Py_DECREF(subtype_object); return 0; } Py_DECREF(subtype_object); if (subtype == 2) { int other_size = _downcast_and_check(PyBytes_Size(value), 4); if (other_size == -1) return 0; if (!buffer_write_int32(buffer, other_size)) { return 0; } if (!buffer_write_bytes(buffer, &subtype, 1)) { return 0; } } if (!buffer_write_int32(buffer, size)) { return 0; } if (subtype != 2) { if (!buffer_write_bytes(buffer, &subtype, 1)) { return 0; } } data = PyBytes_AsString(value); if (!data) { return 0; } if (!buffer_write_bytes(buffer, data, size)) { return 0; } return 1; } case 7: { /* ObjectId */ const char* data; PyObject* pystring = PyObject_GetAttr(value, state->_binary_str); if (!pystring) { return 0; } data = PyBytes_AsString(pystring); if (!data) { Py_DECREF(pystring); return 0; } if (!buffer_write_bytes(buffer, data, 12)) { Py_DECREF(pystring); return 0; } Py_DECREF(pystring); *(pymongo_buffer_get_buffer(buffer) + type_byte) = 0x07; return 1; } case 9: { /* DatetimeMS */ long long millis; if (!millis_from_datetime_ms(value, &millis)) { return 0; } *(pymongo_buffer_get_buffer(buffer) + type_byte) = 0x09; return buffer_write_int64(buffer, (int64_t)millis); } case 11: { /* Regex */ return _write_regex_to_buffer(buffer, type_byte, value, state->_flags_str, state->_pattern_str); } case 13: { /* Code */ int start_position, length_location, length; PyObject* scope = PyObject_GetAttr(value, state->_scope_str); if (!scope) { return 0; } if (scope == Py_None) { Py_DECREF(scope); *(pymongo_buffer_get_buffer(buffer) + type_byte) = 0x0D; return write_string(buffer, value); } *(pymongo_buffer_get_buffer(buffer) + type_byte) = 0x0F; start_position = pymongo_buffer_get_position(buffer); /* save space for length */ length_location = pymongo_buffer_save_space(buffer, 4); if (length_location == -1) { Py_DECREF(scope); return 0; } if (!write_string(buffer, value)) { Py_DECREF(scope); return 0; } if (!write_dict(self, buffer, scope, 0, options, 0)) { Py_DECREF(scope); return 0; } Py_DECREF(scope); length = pymongo_buffer_get_position(buffer) - start_position; buffer_write_int32_at_position( buffer, length_location, (int32_t)length); return 1; } case 17: { /* Timestamp */ PyObject* obj; unsigned long i; obj = PyObject_GetAttr(value, state->_inc_str); if (!obj) { return 0; } i = PyLong_AsUnsignedLong(obj); Py_DECREF(obj); if (i == (unsigned long)-1 && PyErr_Occurred()) { return 0; } if (!buffer_write_int32(buffer, (int32_t)i)) { return 0; } obj = PyObject_GetAttr(value, state->_time_str); if (!obj) { return 0; } i = PyLong_AsUnsignedLong(obj); Py_DECREF(obj); if (i == (unsigned long)-1 && PyErr_Occurred()) { return 0; } if (!buffer_write_int32(buffer, (int32_t)i)) { return 0; } *(pymongo_buffer_get_buffer(buffer) + type_byte) = 0x11; return 1; } case 18: { /* Int64 */ const long long ll = PyLong_AsLongLong(value); if (PyErr_Occurred()) { /* Overflow */ PyErr_SetString(PyExc_OverflowError, "MongoDB can only handle up to 8-byte ints"); return 0; } if (!buffer_write_int64(buffer, (int64_t)ll)) { return 0; } *(pymongo_buffer_get_buffer(buffer) + type_byte) = 0x12; return 1; } case 19: { /* Decimal128 */ const char* data; PyObject* pystring = PyObject_GetAttr(value, state->_bid_str); if (!pystring) { return 0; } data = PyBytes_AsString(pystring); if (!data) { Py_DECREF(pystring); return 0; } if (!buffer_write_bytes(buffer, data, 16)) { Py_DECREF(pystring); return 0; } Py_DECREF(pystring); *(pymongo_buffer_get_buffer(buffer) + type_byte) = 0x13; return 1; } case 100: { /* DBRef */ PyObject* as_doc = PyObject_CallMethodObjArgs(value, state->_as_doc_str, NULL); if (!as_doc) { return 0; } if (!write_dict(self, buffer, as_doc, 0, options, 0)) { Py_DECREF(as_doc); return 0; } Py_DECREF(as_doc); *(pymongo_buffer_get_buffer(buffer) + type_byte) = 0x03; return 1; } case 101: { /* RawBSONDocument */ if (!write_raw_doc(buffer, value, state->_raw_str)) { return 0; } *(pymongo_buffer_get_buffer(buffer) + type_byte) = 0x03; return 1; } case 255: { /* MinKey */ *(pymongo_buffer_get_buffer(buffer) + type_byte) = 0xFF; return 1; } case 127: { /* MaxKey */ *(pymongo_buffer_get_buffer(buffer) + type_byte) = 0x7F; return 1; } } /* No _type_marker attribute or not one of our types. */ if (PyBool_Check(value)) { const char c = (value == Py_True) ? 0x01 : 0x00; *(pymongo_buffer_get_buffer(buffer) + type_byte) = 0x08; return buffer_write_bytes(buffer, &c, 1); } else if (PyLong_Check(value)) { const long long long_long_value = PyLong_AsLongLong(value); if (long_long_value == -1 && PyErr_Occurred()) { /* Ignore error and give the fallback_encoder a chance. */ PyErr_Clear(); } else if (-2147483648LL <= long_long_value && long_long_value <= 2147483647LL) { *(pymongo_buffer_get_buffer(buffer) + type_byte) = 0x10; return buffer_write_int32(buffer, (int32_t)long_long_value); } else { *(pymongo_buffer_get_buffer(buffer) + type_byte) = 0x12; return buffer_write_int64(buffer, (int64_t)long_long_value); } } else if (PyFloat_Check(value)) { const double d = PyFloat_AsDouble(value); *(pymongo_buffer_get_buffer(buffer) + type_byte) = 0x01; return buffer_write_double(buffer, d); } else if (value == Py_None) { *(pymongo_buffer_get_buffer(buffer) + type_byte) = 0x0A; return 1; } else if (PyDict_Check(value)) { *(pymongo_buffer_get_buffer(buffer) + type_byte) = 0x03; return write_dict(self, buffer, value, check_keys, options, 0); } else if ((is_list = PyList_Check(value)) || PyTuple_Check(value)) { Py_ssize_t items, i; int start_position, length_location, length; char zero = 0; *(pymongo_buffer_get_buffer(buffer) + type_byte) = 0x04; start_position = pymongo_buffer_get_position(buffer); /* save space for length */ length_location = pymongo_buffer_save_space(buffer, 4); if (length_location == -1) { return 0; } if (is_list) { items = PyList_Size(value); } else { items = PyTuple_Size(value); } if (items > BSON_MAX_SIZE) { PyObject* BSONError = _error("BSONError"); if (BSONError) { PyErr_SetString(BSONError, "Too many items to serialize."); Py_DECREF(BSONError); } return 0; } for(i = 0; i < items; i++) { int list_type_byte = pymongo_buffer_save_space(buffer, 1); char name[BUF_SIZE]; PyObject* item_value; if (list_type_byte == -1) { return 0; } int res = LL2STR(name, (long long)i); if (res == -1) { return 0; } if (!buffer_write_bytes(buffer, name, (int)strlen(name) + 1)) { return 0; } if (is_list) { item_value = PyList_GET_ITEM(value, i); } else { item_value = PyTuple_GET_ITEM(value, i); } if (!item_value) { return 0; } if (!write_element_to_buffer(self, buffer, list_type_byte, item_value, check_keys, options, 0, 0)) { return 0; } } /* write null byte and fill in length */ if (!buffer_write_bytes(buffer, &zero, 1)) { return 0; } length = pymongo_buffer_get_position(buffer) - start_position; buffer_write_int32_at_position( buffer, length_location, (int32_t)length); return 1; /* Python3 special case. Store bytes as BSON binary subtype 0. */ } else if (PyBytes_Check(value)) { char subtype = 0; int size; const char* data = PyBytes_AS_STRING(value); if (!data) return 0; if ((size = _downcast_and_check(PyBytes_GET_SIZE(value), 0)) == -1) return 0; *(pymongo_buffer_get_buffer(buffer) + type_byte) = 0x05; if (!buffer_write_int32(buffer, (int32_t)size)) { return 0; } if (!buffer_write_bytes(buffer, &subtype, 1)) { return 0; } if (!buffer_write_bytes(buffer, data, size)) { return 0; } return 1; } else if (PyUnicode_Check(value)) { *(pymongo_buffer_get_buffer(buffer) + type_byte) = 0x02; return write_unicode(buffer, value); } else if (PyDateTime_Check(value)) { long long millis; PyObject* utcoffset = PyObject_CallMethodObjArgs(value, state->_utcoffset_str , NULL); if (utcoffset == NULL) return 0; if (utcoffset != Py_None) { PyObject* result = PyNumber_Subtract(value, utcoffset); Py_DECREF(utcoffset); if (!result) { return 0; } millis = millis_from_datetime(result); Py_DECREF(result); } else { millis = millis_from_datetime(value); } *(pymongo_buffer_get_buffer(buffer) + type_byte) = 0x09; return buffer_write_int64(buffer, (int64_t)millis); } else if (PyObject_TypeCheck(value, state->REType)) { return _write_regex_to_buffer(buffer, type_byte, value, state->_flags_str, state->_pattern_str); } else if (PyObject_IsInstance(value, state->Mapping)) { /* PyObject_IsInstance returns -1 on error */ if (PyErr_Occurred()) { return 0; } *(pymongo_buffer_get_buffer(buffer) + type_byte) = 0x03; return write_dict(self, buffer, value, check_keys, options, 0); } else if (PyObject_IsInstance(value, state->UUID)) { PyObject* binary_value = NULL; PyObject *uuid_rep_obj = NULL; int result; /* PyObject_IsInstance returns -1 on error */ if (PyErr_Occurred()) { return 0; } if (!(uuid_rep_obj = PyLong_FromLong(options->uuid_rep))) { return 0; } binary_value = PyObject_CallMethodObjArgs(state->Binary, state->_from_uuid_str, value, uuid_rep_obj, NULL); Py_DECREF(uuid_rep_obj); if (binary_value == NULL) { return 0; } result = _write_element_to_buffer(self, buffer, type_byte, binary_value, check_keys, options, in_custom_call, in_fallback_call); Py_DECREF(binary_value); return result; } /* Try a custom encoder if one is provided and we have not already * attempted to use a type encoder. */ if (!in_custom_call && !options->type_registry.is_encoder_empty) { PyObject* value_type = NULL; PyObject* converter = NULL; value_type = PyObject_Type(value); if (value_type == NULL) { return 0; } converter = PyDict_GetItem(options->type_registry.encoder_map, value_type); Py_XDECREF(value_type); if (converter != NULL) { /* Transform types that have a registered converter. * A new reference is created upon transformation. */ new_value = PyObject_CallFunctionObjArgs(converter, value, NULL); if (new_value == NULL) { return 0; } retval = write_element_to_buffer(self, buffer, type_byte, new_value, check_keys, options, 1, 0); Py_XDECREF(new_value); return retval; } } /* Try the fallback encoder if one is provided and we have not already * attempted to use the fallback encoder. */ if (!in_fallback_call && options->type_registry.has_fallback_encoder) { new_value = PyObject_CallFunctionObjArgs( options->type_registry.fallback_encoder, value, NULL); if (new_value == NULL) { // propagate any exception raised by the callback return 0; } retval = write_element_to_buffer(self, buffer, type_byte, new_value, check_keys, options, 0, 1); Py_XDECREF(new_value); return retval; } /* We can't determine value's type. Fail. */ _set_cannot_encode(value); return 0; } static int check_key_name(const char* name, int name_length) { if (name_length > 0 && name[0] == '$') { PyObject* InvalidDocument = _error("InvalidDocument"); if (InvalidDocument) { PyObject* errmsg = PyUnicode_FromFormat( "key '%s' must not start with '$'", name); if (errmsg) { PyErr_SetObject(InvalidDocument, errmsg); Py_DECREF(errmsg); } Py_DECREF(InvalidDocument); } return 0; } if (strchr(name, '.')) { PyObject* InvalidDocument = _error("InvalidDocument"); if (InvalidDocument) { PyObject* errmsg = PyUnicode_FromFormat( "key '%s' must not contain '.'", name); if (errmsg) { PyErr_SetObject(InvalidDocument, errmsg); Py_DECREF(errmsg); } Py_DECREF(InvalidDocument); } return 0; } return 1; } /* Write a (key, value) pair to the buffer. * * Returns 0 on failure */ int write_pair(PyObject* self, buffer_t buffer, const char* name, int name_length, PyObject* value, unsigned char check_keys, const codec_options_t* options, unsigned char allow_id) { int type_byte; /* Don't write any _id elements unless we're explicitly told to - * _id has to be written first so we do so, but don't bother * deleting it from the dictionary being written. */ if (!allow_id && strcmp(name, "_id") == 0) { return 1; } type_byte = pymongo_buffer_save_space(buffer, 1); if (type_byte == -1) { return 0; } if (check_keys && !check_key_name(name, name_length)) { return 0; } if (!buffer_write_bytes(buffer, name, name_length + 1)) { return 0; } if (!write_element_to_buffer(self, buffer, type_byte, value, check_keys, options, 0, 0)) { return 0; } return 1; } int decode_and_write_pair(PyObject* self, buffer_t buffer, PyObject* key, PyObject* value, unsigned char check_keys, const codec_options_t* options, unsigned char top_level) { PyObject* encoded; const char* data; int size; if (PyUnicode_Check(key)) { encoded = PyUnicode_AsUTF8String(key); if (!encoded) { return 0; } if (!(data = PyBytes_AS_STRING(encoded))) { Py_DECREF(encoded); return 0; } if ((size = _downcast_and_check(PyBytes_GET_SIZE(encoded), 1)) == -1) { Py_DECREF(encoded); return 0; } if (strlen(data) != (size_t)(size - 1)) { PyObject* InvalidDocument = _error("InvalidDocument"); if (InvalidDocument) { PyErr_SetString(InvalidDocument, "Key names must not contain the NULL byte"); Py_DECREF(InvalidDocument); } Py_DECREF(encoded); return 0; } } else { PyObject* InvalidDocument = _error("InvalidDocument"); if (InvalidDocument) { PyObject* repr = PyObject_Repr(key); if (repr) { PyObject* errmsg = PyUnicode_FromString( "documents must have only string keys, key was "); if (errmsg) { PyObject* error = PyUnicode_Concat(errmsg, repr); if (error) { PyErr_SetObject(InvalidDocument, error); Py_DECREF(error); } Py_DECREF(errmsg); Py_DECREF(repr); } else { Py_DECREF(repr); } } Py_DECREF(InvalidDocument); } return 0; } /* If top_level is True, don't allow writing _id here - it was already written. */ if (!write_pair(self, buffer, data, size - 1, value, check_keys, options, !top_level)) { Py_DECREF(encoded); return 0; } Py_DECREF(encoded); return 1; } /* Write a RawBSONDocument to the buffer. * Returns the number of bytes written or 0 on failure. */ static int write_raw_doc(buffer_t buffer, PyObject* raw, PyObject* _raw_str) { char* bytes; Py_ssize_t len; int len_int; int bytes_written = 0; PyObject* bytes_obj = NULL; bytes_obj = PyObject_GetAttr(raw, _raw_str); if (!bytes_obj) { goto fail; } if (-1 == PyBytes_AsStringAndSize(bytes_obj, &bytes, &len)) { goto fail; } len_int = _downcast_and_check(len, 0); if (-1 == len_int) { goto fail; } if (!buffer_write_bytes(buffer, bytes, len_int)) { goto fail; } bytes_written = len_int; fail: Py_XDECREF(bytes_obj); return bytes_written; } /* returns the number of bytes written or 0 on failure */ int write_dict(PyObject* self, buffer_t buffer, PyObject* dict, unsigned char check_keys, const codec_options_t* options, unsigned char top_level) { PyObject* key; PyObject* iter; char zero = 0; int length; int length_location; struct module_state *state = GETSTATE(self); long type_marker; int is_dict = PyDict_Check(dict); if (!state) { return 0; } if (!is_dict) { /* check for RawBSONDocument */ type_marker = _type_marker(dict, state->_type_marker_str); if (type_marker < 0) { return 0; } if (101 == type_marker) { return write_raw_doc(buffer, dict, state->_raw_str); } if (!PyObject_IsInstance(dict, state->Mapping)) { PyObject* repr; if ((repr = PyObject_Repr(dict))) { PyObject* errmsg = PyUnicode_FromString( "encoder expected a mapping type but got: "); if (errmsg) { PyObject* error = PyUnicode_Concat(errmsg, repr); if (error) { PyErr_SetObject(PyExc_TypeError, error); Py_DECREF(error); } Py_DECREF(errmsg); Py_DECREF(repr); } else { Py_DECREF(repr); } } else { PyErr_SetString(PyExc_TypeError, "encoder expected a mapping type"); } return 0; } /* PyObject_IsInstance returns -1 on error */ if (PyErr_Occurred()) { return 0; } } length_location = pymongo_buffer_save_space(buffer, 4); if (length_location == -1) { return 0; } /* Write _id first if this is a top level doc. */ if (top_level) { /* * If "dict" is a defaultdict we don't want to call * PyObject_GetItem on it. That would **create** * an _id where one didn't previously exist (PYTHON-871). */ if (is_dict) { /* PyDict_GetItem returns a borrowed reference. */ PyObject* _id = PyDict_GetItem(dict, state->_id_str); if (_id) { if (!write_pair(self, buffer, "_id", 3, _id, check_keys, options, 1)) { return 0; } } } else if (PyMapping_HasKey(dict, state->_id_str)) { PyObject* _id = PyObject_GetItem(dict, state->_id_str); if (!_id) { return 0; } if (!write_pair(self, buffer, "_id", 3, _id, check_keys, options, 1)) { Py_DECREF(_id); return 0; } /* PyObject_GetItem returns a new reference. */ Py_DECREF(_id); } } if (is_dict) { PyObject* value; Py_ssize_t pos = 0; while (PyDict_Next(dict, &pos, &key, &value)) { if (!decode_and_write_pair(self, buffer, key, value, check_keys, options, top_level)) { return 0; } } } else { iter = PyObject_GetIter(dict); if (iter == NULL) { return 0; } while ((key = PyIter_Next(iter)) != NULL) { PyObject* value = PyObject_GetItem(dict, key); if (!value) { PyErr_SetObject(PyExc_KeyError, key); Py_DECREF(key); Py_DECREF(iter); return 0; } if (!decode_and_write_pair(self, buffer, key, value, check_keys, options, top_level)) { Py_DECREF(key); Py_DECREF(value); Py_DECREF(iter); return 0; } Py_DECREF(key); Py_DECREF(value); } Py_DECREF(iter); if (PyErr_Occurred()) { return 0; } } /* write null byte and fill in length */ if (!buffer_write_bytes(buffer, &zero, 1)) { return 0; } length = pymongo_buffer_get_position(buffer) - length_location; buffer_write_int32_at_position( buffer, length_location, (int32_t)length); return length; } static PyObject* _cbson_dict_to_bson(PyObject* self, PyObject* args) { PyObject* dict; PyObject* result; unsigned char check_keys; unsigned char top_level = 1; PyObject* options_obj; codec_options_t options; buffer_t buffer; PyObject* raw_bson_document_bytes_obj; long type_marker; struct module_state *state = GETSTATE(self); if (!state) { return NULL; } if (!(PyArg_ParseTuple(args, "ObO|b", &dict, &check_keys, &options_obj, &top_level) && convert_codec_options(self, options_obj, &options))) { return NULL; } /* check for RawBSONDocument */ type_marker = _type_marker(dict, state->_type_marker_str); if (type_marker < 0) { destroy_codec_options(&options); return NULL; } else if (101 == type_marker) { destroy_codec_options(&options); raw_bson_document_bytes_obj = PyObject_GetAttr(dict, state->_raw_str); if (NULL == raw_bson_document_bytes_obj) { return NULL; } return raw_bson_document_bytes_obj; } buffer = pymongo_buffer_new(); if (!buffer) { destroy_codec_options(&options); return NULL; } if (!write_dict(self, buffer, dict, check_keys, &options, top_level)) { destroy_codec_options(&options); pymongo_buffer_free(buffer); return NULL; } /* objectify buffer */ result = Py_BuildValue("y#", pymongo_buffer_get_buffer(buffer), (Py_ssize_t)pymongo_buffer_get_position(buffer)); destroy_codec_options(&options); pymongo_buffer_free(buffer); return result; } /* * Hook for optional decoding BSON documents to DBRef. */ static PyObject *_dbref_hook(PyObject* self, PyObject* value) { struct module_state *state = GETSTATE(self); PyObject* ref = NULL; PyObject* id = NULL; PyObject* database = NULL; PyObject* ret = NULL; int db_present = 0; if (!state) { return NULL; } /* Decoding for DBRefs */ if (PyMapping_HasKey(value, state->_dollar_ref_str) && PyMapping_HasKey(value, state->_dollar_id_str)) { /* DBRef */ ref = PyObject_GetItem(value, state->_dollar_ref_str); /* PyObject_GetItem returns NULL to indicate error. */ if (!ref) { goto invalid; } id = PyObject_GetItem(value, state->_dollar_id_str); /* PyObject_GetItem returns NULL to indicate error. */ if (!id) { goto invalid; } if (PyMapping_HasKey(value, state->_dollar_db_str)) { database = PyObject_GetItem(value, state->_dollar_db_str); if (!database) { goto invalid; } db_present = 1; } else { database = Py_None; Py_INCREF(database); } // check types if (!(PyUnicode_Check(ref) && (database == Py_None || PyUnicode_Check(database)))) { ret = value; goto invalid; } PyMapping_DelItem(value, state->_dollar_ref_str); PyMapping_DelItem(value, state->_dollar_id_str); if (db_present) { PyMapping_DelItem(value, state->_dollar_db_str); } ret = PyObject_CallFunctionObjArgs(state->DBRef, ref, id, database, value, NULL); Py_DECREF(value); } else { ret = value; } invalid: Py_XDECREF(ref); Py_XDECREF(id); Py_XDECREF(database); return ret; } static PyObject* get_value(PyObject* self, PyObject* name, const char* buffer, unsigned* position, unsigned char type, unsigned max, const codec_options_t* options, int raw_array) { struct module_state *state = GETSTATE(self); PyObject* value = NULL; if (!state) { return NULL; } switch (type) { case 1: { double d; if (max < 8) { goto invalid; } memcpy(&d, buffer + *position, 8); value = PyFloat_FromDouble(BSON_DOUBLE_FROM_LE(d)); *position += 8; break; } case 2: case 14: { uint32_t value_length; if (max < 4) { goto invalid; } memcpy(&value_length, buffer + *position, 4); value_length = BSON_UINT32_FROM_LE(value_length); /* Encoded string length + string */ if (!value_length || max < value_length || max < 4 + value_length) { goto invalid; } *position += 4; /* Strings must end in \0 */ if (buffer[*position + value_length - 1]) { goto invalid; } value = PyUnicode_DecodeUTF8( buffer + *position, value_length - 1, options->unicode_decode_error_handler); if (!value) { goto invalid; } *position += value_length; break; } case 3: { uint32_t size; if (max < 4) { goto invalid; } memcpy(&size, buffer + *position, 4); size = BSON_UINT32_FROM_LE(size); if (size < BSON_MIN_SIZE || max < size) { goto invalid; } /* Check for bad eoo */ if (buffer[*position + size - 1]) { goto invalid; } value = elements_to_dict(self, buffer + *position, size, options); if (!value) { goto invalid; } if (options->is_raw_bson) { *position += size; break; } /* Hook for DBRefs */ value = _dbref_hook(self, value); if (!value) { goto invalid; } *position += size; break; } case 4: { uint32_t size, end; if (max < 4) { goto invalid; } memcpy(&size, buffer + *position, 4); size = BSON_UINT32_FROM_LE(size); if (size < BSON_MIN_SIZE || max < size) { goto invalid; } end = *position + size - 1; /* Check for bad eoo */ if (buffer[end]) { goto invalid; } if (raw_array != 0) { // Treat it as a binary buffer. value = PyBytes_FromStringAndSize(buffer + *position, size); *position += size; break; } *position += 4; value = PyList_New(0); if (!value) { goto invalid; } while (*position < end) { PyObject* to_append; unsigned char bson_type = (unsigned char)buffer[(*position)++]; size_t key_size = strlen(buffer + *position); if (max < key_size) { Py_DECREF(value); goto invalid; } /* just skip the key, they're in order. */ *position += (unsigned)key_size + 1; if (Py_EnterRecursiveCall(" while decoding a list value")) { Py_DECREF(value); goto invalid; } to_append = get_value(self, name, buffer, position, bson_type, max - (unsigned)key_size, options, raw_array); Py_LeaveRecursiveCall(); if (!to_append) { Py_DECREF(value); goto invalid; } if (PyList_Append(value, to_append) < 0) { Py_DECREF(value); Py_DECREF(to_append); goto invalid; } Py_DECREF(to_append); } if (*position != end) { goto invalid; } (*position)++; break; } case 5: { PyObject* data; PyObject* st; uint32_t length, length2; unsigned char subtype; if (max < 5) { goto invalid; } memcpy(&length, buffer + *position, 4); length = BSON_UINT32_FROM_LE(length); if (max < length) { goto invalid; } subtype = (unsigned char)buffer[*position + 4]; *position += 5; if (subtype == 2) { if (length < 4) { goto invalid; } memcpy(&length2, buffer + *position, 4); length2 = BSON_UINT32_FROM_LE(length2); if (length2 != length - 4) { goto invalid; } } /* Python3 special case. Decode BSON binary subtype 0 to bytes. */ if (subtype == 0) { value = PyBytes_FromStringAndSize(buffer + *position, length); *position += length; break; } if (subtype == 2) { data = PyBytes_FromStringAndSize(buffer + *position + 4, length - 4); } else { data = PyBytes_FromStringAndSize(buffer + *position, length); } if (!data) { goto invalid; } /* Encode as UUID or Binary based on options->uuid_rep */ if (subtype == 3 || subtype == 4) { PyObject* binary_value = NULL; char uuid_rep = options->uuid_rep; /* UUID should always be 16 bytes */ if (length != 16) { goto uuiderror; } binary_value = PyObject_CallFunction(state->Binary, "(Oi)", data, subtype); if (binary_value == NULL) { goto uuiderror; } if ((uuid_rep == UNSPECIFIED) || (subtype == 4 && uuid_rep != STANDARD) || (subtype == 3 && uuid_rep == STANDARD)) { value = binary_value; Py_INCREF(value); } else { PyObject *uuid_rep_obj = PyLong_FromLong(uuid_rep); if (!uuid_rep_obj) { goto uuiderror; } value = PyObject_CallMethodObjArgs(binary_value, state->_as_uuid_str, uuid_rep_obj, NULL); Py_DECREF(uuid_rep_obj); } uuiderror: Py_XDECREF(binary_value); Py_DECREF(data); if (!value) { goto invalid; } *position += length; break; } st = PyLong_FromLong(subtype); if (!st) { Py_DECREF(data); goto invalid; } value = PyObject_CallFunctionObjArgs(state->Binary, data, st, NULL); Py_DECREF(st); Py_DECREF(data); if (!value) { goto invalid; } *position += length; break; } case 6: case 10: { value = Py_None; Py_INCREF(value); break; } case 7: { if (max < 12) { goto invalid; } value = PyObject_CallFunction(state->ObjectId, "y#", buffer + *position, (Py_ssize_t)12); *position += 12; break; } case 8: { char boolean_raw = buffer[(*position)++]; if (0 == boolean_raw) { value = Py_False; } else if (1 == boolean_raw) { value = Py_True; } else { PyObject* InvalidBSON = _error("InvalidBSON"); if (InvalidBSON) { PyErr_Format(InvalidBSON, "invalid boolean value: %x", boolean_raw); Py_DECREF(InvalidBSON); } return NULL; } Py_INCREF(value); break; } case 9: { PyObject* naive; PyObject* replace; PyObject* args; PyObject* kwargs; PyObject* astimezone; int64_t millis; if (max < 8) { goto invalid; } memcpy(&millis, buffer + *position, 8); millis = (int64_t)BSON_UINT64_FROM_LE(millis); *position += 8; if (options->datetime_conversion == DATETIME_MS){ value = datetime_ms_from_millis(self, millis); break; } int dt_clamp = options->datetime_conversion == DATETIME_CLAMP; int dt_auto = options->datetime_conversion == DATETIME_AUTO; if (dt_clamp || dt_auto){ PyObject *min_millis_fn_res; PyObject *max_millis_fn_res; int64_t min_millis; int64_t max_millis; if (options->tz_aware){ PyObject* tzinfo = options->tzinfo; if (tzinfo == Py_None) { // Default to UTC. tzinfo = state->UTC; } min_millis_fn_res = PyObject_CallFunctionObjArgs(state->_min_datetime_ms, tzinfo, NULL); max_millis_fn_res = PyObject_CallFunctionObjArgs(state->_max_datetime_ms, tzinfo, NULL); } else { min_millis_fn_res = PyObject_CallObject(state->_min_datetime_ms, NULL); max_millis_fn_res = PyObject_CallObject(state->_max_datetime_ms, NULL); } if (!min_millis_fn_res || !max_millis_fn_res){ Py_XDECREF(min_millis_fn_res); Py_XDECREF(max_millis_fn_res); goto invalid; } min_millis = PyLong_AsLongLong(min_millis_fn_res); max_millis = PyLong_AsLongLong(max_millis_fn_res); if ((min_millis == -1 || max_millis == -1) && PyErr_Occurred()) { // min/max_millis check goto invalid; } if (dt_clamp) { if (millis < min_millis) { millis = min_millis; } else if (millis > max_millis) { millis = max_millis; } // Continues from here to return a datetime. } else { // dt_auto if (millis < min_millis || millis > max_millis){ value = datetime_ms_from_millis(self, millis); break; // Out-of-range so done. } } } naive = datetime_from_millis(millis); if (!options->tz_aware) { /* In the naive case, we're done here. */ value = naive; break; } if (!naive) { goto invalid; } replace = PyObject_GetAttr(naive, state->_replace_str); Py_DECREF(naive); if (!replace) { goto invalid; } args = PyTuple_New(0); if (!args) { Py_DECREF(replace); goto invalid; } kwargs = PyDict_New(); if (!kwargs) { Py_DECREF(replace); Py_DECREF(args); goto invalid; } if (PyDict_SetItem(kwargs, state->_tzinfo_str, state->UTC) == -1) { Py_DECREF(replace); Py_DECREF(args); Py_DECREF(kwargs); goto invalid; } value = PyObject_Call(replace, args, kwargs); if (!value) { Py_DECREF(replace); Py_DECREF(args); Py_DECREF(kwargs); goto invalid; } /* convert to local time */ if (options->tzinfo != Py_None) { astimezone = PyObject_GetAttr(value, state->_astimezone_str); Py_DECREF(value); if (!astimezone) { Py_DECREF(replace); Py_DECREF(args); Py_DECREF(kwargs); goto invalid; } value = PyObject_CallFunctionObjArgs(astimezone, options->tzinfo, NULL); Py_DECREF(astimezone); } Py_DECREF(replace); Py_DECREF(args); Py_DECREF(kwargs); break; } case 11: { PyObject* pattern; int flags; size_t flags_length, i; size_t pattern_length = strlen(buffer + *position); if (pattern_length > BSON_MAX_SIZE || max < pattern_length) { goto invalid; } pattern = PyUnicode_DecodeUTF8( buffer + *position, pattern_length, options->unicode_decode_error_handler); if (!pattern) { goto invalid; } *position += (unsigned)pattern_length + 1; flags_length = strlen(buffer + *position); if (flags_length > BSON_MAX_SIZE || (BSON_MAX_SIZE - pattern_length) < flags_length) { Py_DECREF(pattern); goto invalid; } if (max < pattern_length + flags_length) { Py_DECREF(pattern); goto invalid; } flags = 0; for (i = 0; i < flags_length; i++) { if (buffer[*position + i] == 'i') { flags |= 2; } else if (buffer[*position + i] == 'l') { flags |= 4; } else if (buffer[*position + i] == 'm') { flags |= 8; } else if (buffer[*position + i] == 's') { flags |= 16; } else if (buffer[*position + i] == 'u') { flags |= 32; } else if (buffer[*position + i] == 'x') { flags |= 64; } } *position += (unsigned)flags_length + 1; value = PyObject_CallFunction(state->Regex, "Oi", pattern, flags); Py_DECREF(pattern); break; } case 12: { uint32_t coll_length; PyObject* collection; PyObject* id = NULL; if (max < 4) { goto invalid; } memcpy(&coll_length, buffer + *position, 4); coll_length = BSON_UINT32_FROM_LE(coll_length); /* Encoded string length + string + 12 byte ObjectId */ if (!coll_length || max < coll_length || max < 4 + coll_length + 12) { goto invalid; } *position += 4; /* Strings must end in \0 */ if (buffer[*position + coll_length - 1]) { goto invalid; } collection = PyUnicode_DecodeUTF8( buffer + *position, coll_length - 1, options->unicode_decode_error_handler); if (!collection) { goto invalid; } *position += coll_length; id = PyObject_CallFunction(state->ObjectId, "y#", buffer + *position, (Py_ssize_t)12); if (!id) { Py_DECREF(collection); goto invalid; } *position += 12; value = PyObject_CallFunctionObjArgs(state->DBRef, collection, id, NULL); Py_DECREF(collection); Py_DECREF(id); break; } case 13: { PyObject* code; uint32_t value_length; if (max < 4) { goto invalid; } memcpy(&value_length, buffer + *position, 4); value_length = BSON_UINT32_FROM_LE(value_length); /* Encoded string length + string */ if (!value_length || max < value_length || max < 4 + value_length) { goto invalid; } *position += 4; /* Strings must end in \0 */ if (buffer[*position + value_length - 1]) { goto invalid; } code = PyUnicode_DecodeUTF8( buffer + *position, value_length - 1, options->unicode_decode_error_handler); if (!code) { goto invalid; } *position += value_length; value = PyObject_CallFunctionObjArgs(state->Code, code, NULL, NULL); Py_DECREF(code); break; } case 15: { uint32_t c_w_s_size; uint32_t code_size; uint32_t scope_size; uint32_t len; PyObject* code; PyObject* scope; if (max < 8) { goto invalid; } memcpy(&c_w_s_size, buffer + *position, 4); c_w_s_size = BSON_UINT32_FROM_LE(c_w_s_size); *position += 4; if (max < c_w_s_size) { goto invalid; } memcpy(&code_size, buffer + *position, 4); code_size = BSON_UINT32_FROM_LE(code_size); /* code_w_scope length + code length + code + scope length */ len = 4 + 4 + code_size + 4; if (!code_size || max < code_size || max < len || len < code_size) { goto invalid; } *position += 4; /* Strings must end in \0 */ if (buffer[*position + code_size - 1]) { goto invalid; } code = PyUnicode_DecodeUTF8( buffer + *position, code_size - 1, options->unicode_decode_error_handler); if (!code) { goto invalid; } *position += code_size; memcpy(&scope_size, buffer + *position, 4); scope_size = BSON_UINT32_FROM_LE(scope_size); /* code length + code + scope length + scope */ len = 4 + 4 + code_size + scope_size; if (scope_size < BSON_MIN_SIZE || len != c_w_s_size || len < scope_size) { Py_DECREF(code); goto invalid; } /* Check for bad eoo */ if (buffer[*position + scope_size - 1]) { goto invalid; } scope = elements_to_dict(self, buffer + *position, scope_size, options); if (!scope) { Py_DECREF(code); goto invalid; } *position += scope_size; value = PyObject_CallFunctionObjArgs(state->Code, code, scope, NULL); Py_DECREF(code); Py_DECREF(scope); break; } case 16: { int32_t i; if (max < 4) { goto invalid; } memcpy(&i, buffer + *position, 4); i = (int32_t)BSON_UINT32_FROM_LE(i); value = PyLong_FromLong(i); if (!value) { goto invalid; } *position += 4; break; } case 17: { uint32_t time, inc; if (max < 8) { goto invalid; } memcpy(&inc, buffer + *position, 4); memcpy(&time, buffer + *position + 4, 4); inc = BSON_UINT32_FROM_LE(inc); time = BSON_UINT32_FROM_LE(time); value = PyObject_CallFunction(state->Timestamp, "II", time, inc); *position += 8; break; } case 18: { int64_t ll; if (max < 8) { goto invalid; } memcpy(&ll, buffer + *position, 8); ll = (int64_t)BSON_UINT64_FROM_LE(ll); value = PyObject_CallFunction(state->BSONInt64, "L", ll); *position += 8; break; } case 19: { if (max < 16) { goto invalid; } PyObject *_bytes_obj = PyBytes_FromStringAndSize(buffer + *position, (Py_ssize_t)16); if (!_bytes_obj) { goto invalid; } value = PyObject_CallMethodObjArgs(state->Decimal128, state->_from_bid_str, _bytes_obj, NULL); Py_DECREF(_bytes_obj); *position += 16; break; } case 255: { value = PyObject_CallFunctionObjArgs(state->MinKey, NULL); break; } case 127: { value = PyObject_CallFunctionObjArgs(state->MaxKey, NULL); break; } default: { PyObject* InvalidBSON = _error("InvalidBSON"); if (InvalidBSON) { PyObject* bobj = PyBytes_FromFormat("%c", type); if (bobj) { PyObject* repr = PyObject_Repr(bobj); Py_DECREF(bobj); /* * See http://bugs.python.org/issue22023 for why we can't * just use PyUnicode_FromFormat with %S or %R to do this * work. */ if (repr) { PyObject* left = PyUnicode_FromString( "Detected unknown BSON type "); if (left) { PyObject* lmsg = PyUnicode_Concat(left, repr); Py_DECREF(left); if (lmsg) { PyObject* errmsg = PyUnicode_FromFormat( "%U for fieldname '%U'. Are you using the " "latest driver version?", lmsg, name); if (errmsg) { PyErr_SetObject(InvalidBSON, errmsg); Py_DECREF(errmsg); } Py_DECREF(lmsg); } } Py_DECREF(repr); } } Py_DECREF(InvalidBSON); } goto invalid; } } if (value) { if (!options->type_registry.is_decoder_empty) { PyObject* value_type = NULL; PyObject* converter = NULL; value_type = PyObject_Type(value); if (value_type == NULL) { goto invalid; } converter = PyDict_GetItem(options->type_registry.decoder_map, value_type); if (converter != NULL) { PyObject* new_value = PyObject_CallFunctionObjArgs(converter, value, NULL); Py_DECREF(value_type); Py_DECREF(value); return new_value; } else { Py_DECREF(value_type); return value; } } return value; } invalid: /* * Wrap any non-InvalidBSON errors in InvalidBSON. */ if (PyErr_Occurred()) { PyObject *etype, *evalue, *etrace; PyObject *InvalidBSON; /* * Calling _error clears the error state, so fetch it first. */ PyErr_Fetch(&etype, &evalue, &etrace); /* Dont reraise anything but PyExc_Exceptions as InvalidBSON. */ if (PyErr_GivenExceptionMatches(etype, PyExc_Exception)) { InvalidBSON = _error("InvalidBSON"); if (InvalidBSON) { if (!PyErr_GivenExceptionMatches(etype, InvalidBSON)) { /* * Raise InvalidBSON(str(e)). */ Py_DECREF(etype); etype = InvalidBSON; if (evalue) { PyObject *msg = PyObject_Str(evalue); Py_DECREF(evalue); evalue = msg; } PyErr_NormalizeException(&etype, &evalue, &etrace); } else { /* * The current exception matches InvalidBSON, so we don't * need this reference after all. */ Py_DECREF(InvalidBSON); } } } /* Steals references to args. */ PyErr_Restore(etype, evalue, etrace); } else { PyObject *InvalidBSON = _error("InvalidBSON"); if (InvalidBSON) { PyErr_SetString(InvalidBSON, "invalid length or type code"); Py_DECREF(InvalidBSON); } } return NULL; } /* * Get the next 'name' and 'value' from a document in a string, whose position * is provided. * * Returns the position of the next element in the document, or -1 on error. */ static int _element_to_dict(PyObject* self, const char* string, unsigned position, unsigned max, const codec_options_t* options, int raw_array, PyObject** name, PyObject** value) { unsigned char type = (unsigned char)string[position++]; size_t name_length = strlen(string + position); if (name_length > BSON_MAX_SIZE || position + name_length >= max) { PyObject* InvalidBSON = _error("InvalidBSON"); if (InvalidBSON) { PyErr_SetString(InvalidBSON, "field name too large"); Py_DECREF(InvalidBSON); } return -1; } *name = PyUnicode_DecodeUTF8( string + position, name_length, options->unicode_decode_error_handler); if (!*name) { /* If NULL is returned then wrap the UnicodeDecodeError in an InvalidBSON error */ PyObject *etype, *evalue, *etrace; PyObject *InvalidBSON; PyErr_Fetch(&etype, &evalue, &etrace); if (PyErr_GivenExceptionMatches(etype, PyExc_Exception)) { InvalidBSON = _error("InvalidBSON"); if (InvalidBSON) { Py_DECREF(etype); etype = InvalidBSON; if (evalue) { PyObject *msg = PyObject_Str(evalue); Py_DECREF(evalue); evalue = msg; } PyErr_NormalizeException(&etype, &evalue, &etrace); } } PyErr_Restore(etype, evalue, etrace); return -1; } position += (unsigned)name_length + 1; *value = get_value(self, *name, string, &position, type, max - position, options, raw_array); if (!*value) { Py_DECREF(*name); return -1; } return position; } static PyObject* _cbson_element_to_dict(PyObject* self, PyObject* args) { /* TODO: Support buffer protocol */ char* string; PyObject* bson; PyObject* options_obj; codec_options_t options; unsigned position; unsigned max; int new_position; int raw_array = 0; PyObject* name; PyObject* value; PyObject* result_tuple; if (!(PyArg_ParseTuple(args, "OIIOp", &bson, &position, &max, &options_obj, &raw_array) && convert_codec_options(self, options_obj, &options))) { return NULL; } if (!PyBytes_Check(bson)) { PyErr_SetString(PyExc_TypeError, "argument to _element_to_dict must be a bytes object"); return NULL; } string = PyBytes_AS_STRING(bson); new_position = _element_to_dict(self, string, position, max, &options, raw_array, &name, &value); if (new_position < 0) { return NULL; } result_tuple = Py_BuildValue("NNi", name, value, new_position); if (!result_tuple) { Py_DECREF(name); Py_DECREF(value); return NULL; } destroy_codec_options(&options); return result_tuple; } static PyObject* _elements_to_dict(PyObject* self, const char* string, unsigned max, const codec_options_t* options) { unsigned position = 0; PyObject* dict = PyObject_CallObject(options->document_class, NULL); if (!dict) { return NULL; } int raw_array = 0; while (position < max) { PyObject* name = NULL; PyObject* value = NULL; int new_position; new_position = _element_to_dict( self, string, position, max, options, raw_array, &name, &value); if (new_position < 0) { Py_DECREF(dict); return NULL; } else { position = (unsigned)new_position; } PyObject_SetItem(dict, name, value); Py_DECREF(name); Py_DECREF(value); } return dict; } static PyObject* elements_to_dict(PyObject* self, const char* string, unsigned max, const codec_options_t* options) { PyObject* result; if (options->is_raw_bson) { return PyObject_CallFunction( options->document_class, "y#O", string, max, options->options_obj); } if (Py_EnterRecursiveCall(" while decoding a BSON document")) return NULL; result = _elements_to_dict(self, string + 4, max - 5, options); Py_LeaveRecursiveCall(); return result; } static int _get_buffer(PyObject *exporter, Py_buffer *view) { if (PyObject_GetBuffer(exporter, view, PyBUF_SIMPLE) == -1) { return 0; } if (!PyBuffer_IsContiguous(view, 'C')) { PyErr_SetString(PyExc_ValueError, "must be a contiguous buffer"); goto fail; } if (!view->buf || view->len < 0) { PyErr_SetString(PyExc_ValueError, "invalid buffer"); goto fail; } if (view->itemsize != 1) { PyErr_SetString(PyExc_ValueError, "buffer data must be ascii or utf8"); goto fail; } return 1; fail: PyBuffer_Release(view); return 0; } static PyObject* _cbson_bson_to_dict(PyObject* self, PyObject* args) { int32_t size; Py_ssize_t total_size; const char* string; PyObject* bson; codec_options_t options; PyObject* result = NULL; PyObject* options_obj; Py_buffer view = {0}; if (! (PyArg_ParseTuple(args, "OO", &bson, &options_obj) && convert_codec_options(self, options_obj, &options))) { return result; } if (!_get_buffer(bson, &view)) { destroy_codec_options(&options); return result; } total_size = view.len; if (total_size < BSON_MIN_SIZE) { PyObject* InvalidBSON = _error("InvalidBSON"); if (InvalidBSON) { PyErr_SetString(InvalidBSON, "not enough data for a BSON document"); Py_DECREF(InvalidBSON); } goto done;; } string = (char*)view.buf; memcpy(&size, string, 4); size = (int32_t)BSON_UINT32_FROM_LE(size); if (size < BSON_MIN_SIZE) { PyObject* InvalidBSON = _error("InvalidBSON"); if (InvalidBSON) { PyErr_SetString(InvalidBSON, "invalid message size"); Py_DECREF(InvalidBSON); } goto done; } if (total_size < size || total_size > BSON_MAX_SIZE) { PyObject* InvalidBSON = _error("InvalidBSON"); if (InvalidBSON) { PyErr_SetString(InvalidBSON, "objsize too large"); Py_DECREF(InvalidBSON); } goto done; } if (size != total_size || string[size - 1]) { PyObject* InvalidBSON = _error("InvalidBSON"); if (InvalidBSON) { PyErr_SetString(InvalidBSON, "bad eoo"); Py_DECREF(InvalidBSON); } goto done; } result = elements_to_dict(self, string, (unsigned)size, &options); done: PyBuffer_Release(&view); destroy_codec_options(&options); return result; } static PyObject* _cbson_decode_all(PyObject* self, PyObject* args) { int32_t size; Py_ssize_t total_size; const char* string; PyObject* bson; PyObject* dict; PyObject* result = NULL; codec_options_t options; PyObject* options_obj = NULL; Py_buffer view = {0}; if (!(PyArg_ParseTuple(args, "OO", &bson, &options_obj) && convert_codec_options(self, options_obj, &options))) { return NULL; } if (!_get_buffer(bson, &view)) { destroy_codec_options(&options); return NULL; } total_size = view.len; string = (char*)view.buf; if (!(result = PyList_New(0))) { goto fail; } while (total_size > 0) { if (total_size < BSON_MIN_SIZE) { PyObject* InvalidBSON = _error("InvalidBSON"); if (InvalidBSON) { PyErr_SetString(InvalidBSON, "not enough data for a BSON document"); Py_DECREF(InvalidBSON); } Py_DECREF(result); goto fail; } memcpy(&size, string, 4); size = (int32_t)BSON_UINT32_FROM_LE(size); if (size < BSON_MIN_SIZE) { PyObject* InvalidBSON = _error("InvalidBSON"); if (InvalidBSON) { PyErr_SetString(InvalidBSON, "invalid message size"); Py_DECREF(InvalidBSON); } Py_DECREF(result); goto fail; } if (total_size < size) { PyObject* InvalidBSON = _error("InvalidBSON"); if (InvalidBSON) { PyErr_SetString(InvalidBSON, "objsize too large"); Py_DECREF(InvalidBSON); } Py_DECREF(result); goto fail; } if (string[size - 1]) { PyObject* InvalidBSON = _error("InvalidBSON"); if (InvalidBSON) { PyErr_SetString(InvalidBSON, "bad eoo"); Py_DECREF(InvalidBSON); } Py_DECREF(result); goto fail; } dict = elements_to_dict(self, string, (unsigned)size, &options); if (!dict) { Py_DECREF(result); goto fail; } if (PyList_Append(result, dict) < 0) { Py_DECREF(dict); Py_DECREF(result); goto fail; } Py_DECREF(dict); string += size; total_size -= size; } goto done; fail: result = NULL; done: PyBuffer_Release(&view); destroy_codec_options(&options); return result; } static PyObject* _cbson_array_of_documents_to_buffer(PyObject* self, PyObject* args) { uint32_t size; uint32_t value_length; uint32_t position = 0; buffer_t buffer; const char* string; PyObject* arr; PyObject* result = NULL; Py_buffer view = {0}; if (!PyArg_ParseTuple(args, "O", &arr)) { return NULL; } if (!_get_buffer(arr, &view)) { return NULL; } buffer = pymongo_buffer_new(); if (!buffer) { PyBuffer_Release(&view); return NULL; } string = (char*)view.buf; if (view.len < BSON_MIN_SIZE) { PyObject* InvalidBSON = _error("InvalidBSON"); if (InvalidBSON) { PyErr_SetString(InvalidBSON, "not enough data for a BSON document"); Py_DECREF(InvalidBSON); } goto done; } memcpy(&size, string, 4); size = BSON_UINT32_FROM_LE(size); /* save space for length */ if (pymongo_buffer_save_space(buffer, size) == -1) { goto fail; } pymongo_buffer_update_position(buffer, 0); position += 4; while (position < size - 1) { // Verify the value is an object. unsigned char type = (unsigned char)string[position]; if (type != 3) { PyObject* InvalidBSON = _error("InvalidBSON"); if (InvalidBSON) { PyErr_SetString(InvalidBSON, "array element was not an object"); Py_DECREF(InvalidBSON); } goto fail; } // Just skip the keys. position = position + strlen(string + position) + 1; if (position >= size || (size - position) < BSON_MIN_SIZE) { PyObject* InvalidBSON = _error("InvalidBSON"); if (InvalidBSON) { PyErr_SetString(InvalidBSON, "invalid array content"); Py_DECREF(InvalidBSON); } goto fail; } memcpy(&value_length, string + position, 4); value_length = BSON_UINT32_FROM_LE(value_length); if (value_length < BSON_MIN_SIZE) { PyObject* InvalidBSON = _error("InvalidBSON"); if (InvalidBSON) { PyErr_SetString(InvalidBSON, "invalid message size"); Py_DECREF(InvalidBSON); } goto fail; } if (view.len < size) { PyObject* InvalidBSON = _error("InvalidBSON"); if (InvalidBSON) { PyErr_SetString(InvalidBSON, "objsize too large"); Py_DECREF(InvalidBSON); } goto fail; } if (string[size - 1]) { PyObject* InvalidBSON = _error("InvalidBSON"); if (InvalidBSON) { PyErr_SetString(InvalidBSON, "bad eoo"); Py_DECREF(InvalidBSON); } goto fail; } if (pymongo_buffer_write(buffer, string + position, value_length) == 1) { goto fail; } position += value_length; } /* objectify buffer */ result = Py_BuildValue("y#", pymongo_buffer_get_buffer(buffer), (Py_ssize_t)pymongo_buffer_get_position(buffer)); goto done; fail: result = NULL; done: PyBuffer_Release(&view); pymongo_buffer_free(buffer); return result; } static PyMethodDef _CBSONMethods[] = { {"_dict_to_bson", _cbson_dict_to_bson, METH_VARARGS, "convert a dictionary to a string containing its BSON representation."}, {"_bson_to_dict", _cbson_bson_to_dict, METH_VARARGS, "convert a BSON string to a SON object."}, {"_decode_all", _cbson_decode_all, METH_VARARGS, "convert binary data to a sequence of documents."}, {"_element_to_dict", _cbson_element_to_dict, METH_VARARGS, "Decode a single key, value pair."}, {"_array_of_documents_to_buffer", _cbson_array_of_documents_to_buffer, METH_VARARGS, "Convert raw array of documents to a stream of BSON documents"}, {"_test_long_long_to_str", _test_long_long_to_str, METH_VARARGS, "Test conversion of extreme and common Py_ssize_t values to str."}, {NULL, NULL, 0, NULL} }; #define INITERROR return -1; static int _cbson_traverse(PyObject *m, visitproc visit, void *arg) { struct module_state *state = GETSTATE(m); if (!state) { return 0; } Py_VISIT(state->Binary); Py_VISIT(state->Code); Py_VISIT(state->ObjectId); Py_VISIT(state->DBRef); Py_VISIT(state->Regex); Py_VISIT(state->UUID); Py_VISIT(state->Timestamp); Py_VISIT(state->MinKey); Py_VISIT(state->MaxKey); Py_VISIT(state->UTC); Py_VISIT(state->REType); Py_VISIT(state->_type_marker_str); Py_VISIT(state->_flags_str); Py_VISIT(state->_pattern_str); Py_VISIT(state->_encoder_map_str); Py_VISIT(state->_decoder_map_str); Py_VISIT(state->_fallback_encoder_str); Py_VISIT(state->_raw_str); Py_VISIT(state->_subtype_str); Py_VISIT(state->_binary_str); Py_VISIT(state->_scope_str); Py_VISIT(state->_inc_str); Py_VISIT(state->_time_str); Py_VISIT(state->_bid_str); Py_VISIT(state->_replace_str); Py_VISIT(state->_astimezone_str); Py_VISIT(state->_id_str); Py_VISIT(state->_dollar_ref_str); Py_VISIT(state->_dollar_id_str); Py_VISIT(state->_dollar_db_str); Py_VISIT(state->_tzinfo_str); Py_VISIT(state->_as_doc_str); Py_VISIT(state->_utcoffset_str); Py_VISIT(state->_from_uuid_str); Py_VISIT(state->_as_uuid_str); Py_VISIT(state->_from_bid_str); return 0; } static int _cbson_clear(PyObject *m) { struct module_state *state = GETSTATE(m); if (!state) { return 0; } Py_CLEAR(state->Binary); Py_CLEAR(state->Code); Py_CLEAR(state->ObjectId); Py_CLEAR(state->DBRef); Py_CLEAR(state->Regex); Py_CLEAR(state->UUID); Py_CLEAR(state->Timestamp); Py_CLEAR(state->MinKey); Py_CLEAR(state->MaxKey); Py_CLEAR(state->UTC); Py_CLEAR(state->REType); Py_CLEAR(state->_type_marker_str); Py_CLEAR(state->_flags_str); Py_CLEAR(state->_pattern_str); Py_CLEAR(state->_encoder_map_str); Py_CLEAR(state->_decoder_map_str); Py_CLEAR(state->_fallback_encoder_str); Py_CLEAR(state->_raw_str); Py_CLEAR(state->_subtype_str); Py_CLEAR(state->_binary_str); Py_CLEAR(state->_scope_str); Py_CLEAR(state->_inc_str); Py_CLEAR(state->_time_str); Py_CLEAR(state->_bid_str); Py_CLEAR(state->_replace_str); Py_CLEAR(state->_astimezone_str); Py_CLEAR(state->_id_str); Py_CLEAR(state->_dollar_ref_str); Py_CLEAR(state->_dollar_id_str); Py_CLEAR(state->_dollar_db_str); Py_CLEAR(state->_tzinfo_str); Py_CLEAR(state->_as_doc_str); Py_CLEAR(state->_utcoffset_str); Py_CLEAR(state->_from_uuid_str); Py_CLEAR(state->_as_uuid_str); Py_CLEAR(state->_from_bid_str); return 0; } /* Multi-phase extension module initialization code. * See https://peps.python.org/pep-0489/. */ static int _cbson_exec(PyObject *m) { PyObject *c_api_object; static void *_cbson_API[_cbson_API_POINTER_COUNT]; PyDateTime_IMPORT; if (PyDateTimeAPI == NULL) { INITERROR; } /* Export C API */ _cbson_API[_cbson_buffer_write_bytes_INDEX] = (void *) buffer_write_bytes; _cbson_API[_cbson_write_dict_INDEX] = (void *) write_dict; _cbson_API[_cbson_write_pair_INDEX] = (void *) write_pair; _cbson_API[_cbson_decode_and_write_pair_INDEX] = (void *) decode_and_write_pair; _cbson_API[_cbson_convert_codec_options_INDEX] = (void *) convert_codec_options; _cbson_API[_cbson_destroy_codec_options_INDEX] = (void *) destroy_codec_options; _cbson_API[_cbson_buffer_write_double_INDEX] = (void *) buffer_write_double; _cbson_API[_cbson_buffer_write_int32_INDEX] = (void *) buffer_write_int32; _cbson_API[_cbson_buffer_write_int64_INDEX] = (void *) buffer_write_int64; _cbson_API[_cbson_buffer_write_int32_at_position_INDEX] = (void *) buffer_write_int32_at_position; _cbson_API[_cbson_downcast_and_check_INDEX] = (void *) _downcast_and_check; c_api_object = PyCapsule_New((void *) _cbson_API, "_cbson._C_API", NULL); if (c_api_object == NULL) INITERROR; /* Import several python objects */ if (_load_python_objects(m)) { Py_DECREF(c_api_object); Py_DECREF(m); INITERROR; } if (PyModule_AddObject(m, "_C_API", c_api_object) < 0) { Py_DECREF(c_api_object); Py_DECREF(m); INITERROR; } return 0; } static PyModuleDef_Slot _cbson_slots[] = { {Py_mod_exec, _cbson_exec}, #if defined(Py_MOD_MULTIPLE_INTERPRETERS_SUPPORTED) {Py_mod_multiple_interpreters, Py_MOD_MULTIPLE_INTERPRETERS_SUPPORTED}, #endif {0, NULL}, }; static struct PyModuleDef moduledef = { PyModuleDef_HEAD_INIT, "_cbson", NULL, sizeof(struct module_state), _CBSONMethods, _cbson_slots, _cbson_traverse, _cbson_clear, NULL }; PyMODINIT_FUNC PyInit__cbson(void) { return PyModuleDef_Init(&moduledef); } mongodb-mongo-python-driver-509e9b7/bson/_cbsonmodule.h000066400000000000000000000176221462766011000232300ustar00rootroot00000000000000/* * Copyright 2009-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. */ #include "bson-endian.h" #ifndef _CBSONMODULE_H #define _CBSONMODULE_H #if defined(WIN32) || defined(_MSC_VER) /* * This macro is basically an implementation of asprintf for win32 * We print to the provided buffer to get the string value as an int. * USE LL2STR. This is kept only to test LL2STR. */ #if defined(_MSC_VER) && (_MSC_VER >= 1400) #define INT2STRING(buffer, i) \ _snprintf_s((buffer), \ _scprintf("%lld", (i)) + 1, \ _scprintf("%lld", (i)) + 1, \ "%lld", \ (i)) #define STRCAT(dest, n, src) strcat_s((dest), (n), (src)) #else #define INT2STRING(buffer, i) \ _snprintf((buffer), \ _scprintf("%lld", (i)) + 1, \ "%lld", \ (i)) #define STRCAT(dest, n, src) strcat((dest), (src)) #endif #else #define INT2STRING(buffer, i) snprintf((buffer), sizeof((buffer)), "%lld", (i)) #define STRCAT(dest, n, src) strcat((dest), (src)) #endif /* Just enough space in char array to hold LLONG_MIN and null terminator */ #define BUF_SIZE 21 /* Converts integer to its string representation in decimal notation. */ extern int cbson_long_long_to_str(long long int num, char* str, size_t size); #define LL2STR(buffer, i) cbson_long_long_to_str((i), (buffer), sizeof(buffer)) typedef struct type_registry_t { PyObject* encoder_map; PyObject* decoder_map; PyObject* fallback_encoder; PyObject* registry_obj; unsigned char is_encoder_empty; unsigned char is_decoder_empty; unsigned char has_fallback_encoder; } type_registry_t; typedef struct codec_options_t { PyObject* document_class; unsigned char tz_aware; unsigned char uuid_rep; char* unicode_decode_error_handler; PyObject* tzinfo; type_registry_t type_registry; unsigned char datetime_conversion; PyObject* options_obj; unsigned char is_raw_bson; } codec_options_t; /* C API functions */ #define _cbson_buffer_write_bytes_INDEX 0 #define _cbson_buffer_write_bytes_RETURN int #define _cbson_buffer_write_bytes_PROTO (buffer_t buffer, const char* data, int size) #define _cbson_write_dict_INDEX 1 #define _cbson_write_dict_RETURN int #define _cbson_write_dict_PROTO (PyObject* self, buffer_t buffer, PyObject* dict, unsigned char check_keys, const codec_options_t* options, unsigned char top_level) #define _cbson_write_pair_INDEX 2 #define _cbson_write_pair_RETURN int #define _cbson_write_pair_PROTO (PyObject* self, buffer_t buffer, const char* name, int name_length, PyObject* value, unsigned char check_keys, const codec_options_t* options, unsigned char allow_id) #define _cbson_decode_and_write_pair_INDEX 3 #define _cbson_decode_and_write_pair_RETURN int #define _cbson_decode_and_write_pair_PROTO (PyObject* self, buffer_t buffer, PyObject* key, PyObject* value, unsigned char check_keys, const codec_options_t* options, unsigned char top_level) #define _cbson_convert_codec_options_INDEX 4 #define _cbson_convert_codec_options_RETURN int #define _cbson_convert_codec_options_PROTO (PyObject* self, PyObject* options_obj, codec_options_t* options) #define _cbson_destroy_codec_options_INDEX 5 #define _cbson_destroy_codec_options_RETURN void #define _cbson_destroy_codec_options_PROTO (codec_options_t* options) #define _cbson_buffer_write_double_INDEX 6 #define _cbson_buffer_write_double_RETURN int #define _cbson_buffer_write_double_PROTO (buffer_t buffer, double data) #define _cbson_buffer_write_int32_INDEX 7 #define _cbson_buffer_write_int32_RETURN int #define _cbson_buffer_write_int32_PROTO (buffer_t buffer, int32_t data) #define _cbson_buffer_write_int64_INDEX 8 #define _cbson_buffer_write_int64_RETURN int #define _cbson_buffer_write_int64_PROTO (buffer_t buffer, int64_t data) #define _cbson_buffer_write_int32_at_position_INDEX 9 #define _cbson_buffer_write_int32_at_position_RETURN void #define _cbson_buffer_write_int32_at_position_PROTO (buffer_t buffer, int position, int32_t data) #define _cbson_downcast_and_check_INDEX 10 #define _cbson_downcast_and_check_RETURN int #define _cbson_downcast_and_check_PROTO (Py_ssize_t size, uint8_t extra) /* Total number of C API pointers */ #define _cbson_API_POINTER_COUNT 11 #ifdef _CBSON_MODULE /* This section is used when compiling _cbsonmodule */ static _cbson_buffer_write_bytes_RETURN buffer_write_bytes _cbson_buffer_write_bytes_PROTO; static _cbson_write_dict_RETURN write_dict _cbson_write_dict_PROTO; static _cbson_write_pair_RETURN write_pair _cbson_write_pair_PROTO; static _cbson_decode_and_write_pair_RETURN decode_and_write_pair _cbson_decode_and_write_pair_PROTO; static _cbson_convert_codec_options_RETURN convert_codec_options _cbson_convert_codec_options_PROTO; static _cbson_destroy_codec_options_RETURN destroy_codec_options _cbson_destroy_codec_options_PROTO; static _cbson_buffer_write_double_RETURN buffer_write_double _cbson_buffer_write_double_PROTO; static _cbson_buffer_write_int32_RETURN buffer_write_int32 _cbson_buffer_write_int32_PROTO; static _cbson_buffer_write_int64_RETURN buffer_write_int64 _cbson_buffer_write_int64_PROTO; static _cbson_buffer_write_int32_at_position_RETURN buffer_write_int32_at_position _cbson_buffer_write_int32_at_position_PROTO; static _cbson_downcast_and_check_RETURN _downcast_and_check _cbson_downcast_and_check_PROTO; #else /* This section is used in modules that use _cbsonmodule's API */ static void **_cbson_API; #define buffer_write_bytes (*(_cbson_buffer_write_bytes_RETURN (*)_cbson_buffer_write_bytes_PROTO) _cbson_API[_cbson_buffer_write_bytes_INDEX]) #define write_dict (*(_cbson_write_dict_RETURN (*)_cbson_write_dict_PROTO) _cbson_API[_cbson_write_dict_INDEX]) #define write_pair (*(_cbson_write_pair_RETURN (*)_cbson_write_pair_PROTO) _cbson_API[_cbson_write_pair_INDEX]) #define decode_and_write_pair (*(_cbson_decode_and_write_pair_RETURN (*)_cbson_decode_and_write_pair_PROTO) _cbson_API[_cbson_decode_and_write_pair_INDEX]) #define convert_codec_options (*(_cbson_convert_codec_options_RETURN (*)_cbson_convert_codec_options_PROTO) _cbson_API[_cbson_convert_codec_options_INDEX]) #define destroy_codec_options (*(_cbson_destroy_codec_options_RETURN (*)_cbson_destroy_codec_options_PROTO) _cbson_API[_cbson_destroy_codec_options_INDEX]) #define buffer_write_double (*(_cbson_buffer_write_double_RETURN (*)_cbson_buffer_write_double_PROTO) _cbson_API[_cbson_buffer_write_double_INDEX]) #define buffer_write_int32 (*(_cbson_buffer_write_int32_RETURN (*)_cbson_buffer_write_int32_PROTO) _cbson_API[_cbson_buffer_write_int32_INDEX]) #define buffer_write_int64 (*(_cbson_buffer_write_int64_RETURN (*)_cbson_buffer_write_int64_PROTO) _cbson_API[_cbson_buffer_write_int64_INDEX]) #define buffer_write_int32_at_position (*(_cbson_buffer_write_int32_at_position_RETURN (*)_cbson_buffer_write_int32_at_position_PROTO) _cbson_API[_cbson_buffer_write_int32_at_position_INDEX]) #define _downcast_and_check (*(_cbson_downcast_and_check_RETURN (*)_cbson_downcast_and_check_PROTO) _cbson_API[_cbson_downcast_and_check_INDEX]) #define _cbson_IMPORT _cbson_API = (void **)PyCapsule_Import("_cbson._C_API", 0) #endif #endif // _CBSONMODULE_H mongodb-mongo-python-driver-509e9b7/bson/_helpers.py000066400000000000000000000025261462766011000225560ustar00rootroot00000000000000# Copyright 2021-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. """Setstate and getstate functions for objects with __slots__, allowing compatibility with default pickling protocol """ from __future__ import annotations from typing import Any, Mapping def _setstate_slots(self: Any, state: Any) -> None: for slot, value in state.items(): setattr(self, slot, value) def _mangle_name(name: str, prefix: str) -> str: if name.startswith("__"): prefix = "_" + prefix else: prefix = "" return prefix + name def _getstate_slots(self: Any) -> Mapping[Any, Any]: prefix = self.__class__.__name__ ret = {} for name in self.__slots__: mangled_name = _mangle_name(name, prefix) if hasattr(self, mangled_name): ret[mangled_name] = getattr(self, mangled_name) return ret mongodb-mongo-python-driver-509e9b7/bson/binary.py000066400000000000000000000300601462766011000222330ustar00rootroot00000000000000# Copyright 2009-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. from __future__ import annotations from typing import TYPE_CHECKING, Any, Tuple, Type, Union from uuid import UUID """Tools for representing BSON binary data. """ BINARY_SUBTYPE = 0 """BSON binary subtype for binary data. This is the default subtype for binary data. """ FUNCTION_SUBTYPE = 1 """BSON binary subtype for functions. """ OLD_BINARY_SUBTYPE = 2 """Old BSON binary subtype for binary data. This is the old default subtype, the current default is :data:`BINARY_SUBTYPE`. """ OLD_UUID_SUBTYPE = 3 """Old BSON binary subtype for a UUID. :class:`uuid.UUID` instances will automatically be encoded by :mod:`bson` using this subtype when using :data:`UuidRepresentation.PYTHON_LEGACY`, :data:`UuidRepresentation.JAVA_LEGACY`, or :data:`UuidRepresentation.CSHARP_LEGACY`. .. versionadded:: 2.1 """ UUID_SUBTYPE = 4 """BSON binary subtype for a UUID. This is the standard BSON binary subtype for UUIDs. :class:`uuid.UUID` instances will automatically be encoded by :mod:`bson` using this subtype when using :data:`UuidRepresentation.STANDARD`. """ if TYPE_CHECKING: from array import array as _array from mmap import mmap as _mmap class UuidRepresentation: UNSPECIFIED = 0 """An unspecified UUID representation. When configured, :class:`uuid.UUID` instances will **not** be automatically encoded to or decoded from :class:`~bson.binary.Binary`. When encoding a :class:`uuid.UUID` instance, an error will be raised. To encode a :class:`uuid.UUID` instance with this configuration, it must be wrapped in the :class:`~bson.binary.Binary` class by the application code. When decoding a BSON binary field with a UUID subtype, a :class:`~bson.binary.Binary` instance will be returned instead of a :class:`uuid.UUID` instance. See :ref:`unspecified-representation-details` for details. .. versionadded:: 3.11 """ STANDARD = UUID_SUBTYPE """The standard UUID representation. :class:`uuid.UUID` instances will automatically be encoded to and decoded from BSON binary, using RFC-4122 byte order with binary subtype :data:`UUID_SUBTYPE`. See :ref:`standard-representation-details` for details. .. versionadded:: 3.11 """ PYTHON_LEGACY = OLD_UUID_SUBTYPE """The Python legacy UUID representation. :class:`uuid.UUID` instances will automatically be encoded to and decoded from BSON binary, using RFC-4122 byte order with binary subtype :data:`OLD_UUID_SUBTYPE`. See :ref:`python-legacy-representation-details` for details. .. versionadded:: 3.11 """ JAVA_LEGACY = 5 """The Java legacy UUID representation. :class:`uuid.UUID` instances will automatically be encoded to and decoded from BSON binary subtype :data:`OLD_UUID_SUBTYPE`, using the Java driver's legacy byte order. See :ref:`java-legacy-representation-details` for details. .. versionadded:: 3.11 """ CSHARP_LEGACY = 6 """The C#/.net legacy UUID representation. :class:`uuid.UUID` instances will automatically be encoded to and decoded from BSON binary subtype :data:`OLD_UUID_SUBTYPE`, using the C# driver's legacy byte order. See :ref:`csharp-legacy-representation-details` for details. .. versionadded:: 3.11 """ STANDARD = UuidRepresentation.STANDARD """An alias for :data:`UuidRepresentation.STANDARD`. .. versionadded:: 3.0 """ PYTHON_LEGACY = UuidRepresentation.PYTHON_LEGACY """An alias for :data:`UuidRepresentation.PYTHON_LEGACY`. .. versionadded:: 3.0 """ JAVA_LEGACY = UuidRepresentation.JAVA_LEGACY """An alias for :data:`UuidRepresentation.JAVA_LEGACY`. .. versionchanged:: 3.6 BSON binary subtype 4 is decoded using RFC-4122 byte order. .. versionadded:: 2.3 """ CSHARP_LEGACY = UuidRepresentation.CSHARP_LEGACY """An alias for :data:`UuidRepresentation.CSHARP_LEGACY`. .. versionchanged:: 3.6 BSON binary subtype 4 is decoded using RFC-4122 byte order. .. versionadded:: 2.3 """ ALL_UUID_SUBTYPES = (OLD_UUID_SUBTYPE, UUID_SUBTYPE) ALL_UUID_REPRESENTATIONS = ( UuidRepresentation.UNSPECIFIED, UuidRepresentation.STANDARD, UuidRepresentation.PYTHON_LEGACY, UuidRepresentation.JAVA_LEGACY, UuidRepresentation.CSHARP_LEGACY, ) UUID_REPRESENTATION_NAMES = { UuidRepresentation.UNSPECIFIED: "UuidRepresentation.UNSPECIFIED", UuidRepresentation.STANDARD: "UuidRepresentation.STANDARD", UuidRepresentation.PYTHON_LEGACY: "UuidRepresentation.PYTHON_LEGACY", UuidRepresentation.JAVA_LEGACY: "UuidRepresentation.JAVA_LEGACY", UuidRepresentation.CSHARP_LEGACY: "UuidRepresentation.CSHARP_LEGACY", } MD5_SUBTYPE = 5 """BSON binary subtype for an MD5 hash. """ COLUMN_SUBTYPE = 7 """BSON binary subtype for columns. .. versionadded:: 4.0 """ SENSITIVE_SUBTYPE = 8 """BSON binary subtype for sensitive data. .. versionadded:: 4.5 """ USER_DEFINED_SUBTYPE = 128 """BSON binary subtype for any user defined structure. """ class Binary(bytes): """Representation of BSON binary data. This is necessary because we want to represent Python strings as the BSON string type. We need to wrap binary data so we can tell the difference between what should be considered binary data and what should be considered a string when we encode to BSON. Raises TypeError if `data` is not an instance of :class:`bytes` or `subtype` is not an instance of :class:`int`. Raises ValueError if `subtype` is not in [0, 256). .. note:: Instances of Binary with subtype 0 will be decoded directly to :class:`bytes`. :param data: the binary data to represent. Can be any bytes-like type that implements the buffer protocol. :param subtype: the `binary subtype `_ to use .. versionchanged:: 3.9 Support any bytes-like type that implements the buffer protocol. """ _type_marker = 5 __subtype: int def __new__( cls: Type[Binary], data: Union[memoryview, bytes, _mmap, _array[Any]], subtype: int = BINARY_SUBTYPE, ) -> Binary: if not isinstance(subtype, int): raise TypeError("subtype must be an instance of int") if subtype >= 256 or subtype < 0: raise ValueError("subtype must be contained in [0, 256)") # Support any type that implements the buffer protocol. self = bytes.__new__(cls, memoryview(data).tobytes()) self.__subtype = subtype return self @classmethod def from_uuid( cls: Type[Binary], uuid: UUID, uuid_representation: int = UuidRepresentation.STANDARD ) -> Binary: """Create a BSON Binary object from a Python UUID. Creates a :class:`~bson.binary.Binary` object from a :class:`uuid.UUID` instance. Assumes that the native :class:`uuid.UUID` instance uses the byte-order implied by the provided ``uuid_representation``. Raises :exc:`TypeError` if `uuid` is not an instance of :class:`~uuid.UUID`. :param uuid: A :class:`uuid.UUID` instance. :param uuid_representation: A member of :class:`~bson.binary.UuidRepresentation`. Default: :const:`~bson.binary.UuidRepresentation.STANDARD`. See :ref:`handling-uuid-data-example` for details. .. versionadded:: 3.11 """ if not isinstance(uuid, UUID): raise TypeError("uuid must be an instance of uuid.UUID") if uuid_representation not in ALL_UUID_REPRESENTATIONS: raise ValueError( "uuid_representation must be a value from bson.binary.UuidRepresentation" ) if uuid_representation == UuidRepresentation.UNSPECIFIED: raise ValueError( "cannot encode native uuid.UUID with " "UuidRepresentation.UNSPECIFIED. UUIDs can be manually " "converted to bson.Binary instances using " "bson.Binary.from_uuid() or a different UuidRepresentation " "can be configured. See the documentation for " "UuidRepresentation for more information." ) subtype = OLD_UUID_SUBTYPE if uuid_representation == UuidRepresentation.PYTHON_LEGACY: payload = uuid.bytes elif uuid_representation == UuidRepresentation.JAVA_LEGACY: from_uuid = uuid.bytes payload = from_uuid[0:8][::-1] + from_uuid[8:16][::-1] elif uuid_representation == UuidRepresentation.CSHARP_LEGACY: payload = uuid.bytes_le else: # uuid_representation == UuidRepresentation.STANDARD subtype = UUID_SUBTYPE payload = uuid.bytes return cls(payload, subtype) def as_uuid(self, uuid_representation: int = UuidRepresentation.STANDARD) -> UUID: """Create a Python UUID from this BSON Binary object. Decodes this binary object as a native :class:`uuid.UUID` instance with the provided ``uuid_representation``. Raises :exc:`ValueError` if this :class:`~bson.binary.Binary` instance does not contain a UUID. :param uuid_representation: A member of :class:`~bson.binary.UuidRepresentation`. Default: :const:`~bson.binary.UuidRepresentation.STANDARD`. See :ref:`handling-uuid-data-example` for details. .. versionadded:: 3.11 """ if self.subtype not in ALL_UUID_SUBTYPES: raise ValueError(f"cannot decode subtype {self.subtype} as a uuid") if uuid_representation not in ALL_UUID_REPRESENTATIONS: raise ValueError( "uuid_representation must be a value from bson.binary.UuidRepresentation" ) if uuid_representation == UuidRepresentation.UNSPECIFIED: raise ValueError("uuid_representation cannot be UNSPECIFIED") elif uuid_representation == UuidRepresentation.PYTHON_LEGACY: if self.subtype == OLD_UUID_SUBTYPE: return UUID(bytes=self) elif uuid_representation == UuidRepresentation.JAVA_LEGACY: if self.subtype == OLD_UUID_SUBTYPE: return UUID(bytes=self[0:8][::-1] + self[8:16][::-1]) elif uuid_representation == UuidRepresentation.CSHARP_LEGACY: if self.subtype == OLD_UUID_SUBTYPE: return UUID(bytes_le=self) else: # uuid_representation == UuidRepresentation.STANDARD if self.subtype == UUID_SUBTYPE: return UUID(bytes=self) raise ValueError( f"cannot decode subtype {self.subtype} to {UUID_REPRESENTATION_NAMES[uuid_representation]}" ) @property def subtype(self) -> int: """Subtype of this binary data.""" return self.__subtype def __getnewargs__(self) -> Tuple[bytes, int]: # type: ignore[override] # Work around http://bugs.python.org/issue7382 data = super().__getnewargs__()[0] if not isinstance(data, bytes): data = data.encode("latin-1") return data, self.__subtype def __eq__(self, other: Any) -> bool: if isinstance(other, Binary): return (self.__subtype, bytes(self)) == (other.subtype, bytes(other)) # We don't return NotImplemented here because if we did then # Binary("foo") == "foo" would return True, since Binary is a # subclass of str... return False def __hash__(self) -> int: return super().__hash__() ^ hash(self.__subtype) def __ne__(self, other: Any) -> bool: return not self == other def __repr__(self) -> str: return f"Binary({bytes.__repr__(self)}, {self.__subtype})" mongodb-mongo-python-driver-509e9b7/bson/bson-endian.h000066400000000000000000000146551462766011000227570ustar00rootroot00000000000000/* * Copyright 2013-2016 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. */ #ifndef BSON_ENDIAN_H #define BSON_ENDIAN_H #if defined(__sun) # include #endif #ifdef _MSC_VER # define BSON_INLINE __inline #else # include # define BSON_INLINE __inline__ #endif #define BSON_BIG_ENDIAN 4321 #define BSON_LITTLE_ENDIAN 1234 /* WORDS_BIGENDIAN from pyconfig.h / Python.h */ #ifdef WORDS_BIGENDIAN # define BSON_BYTE_ORDER BSON_BIG_ENDIAN #else # define BSON_BYTE_ORDER BSON_LITTLE_ENDIAN #endif #if defined(__sun) # define BSON_UINT16_SWAP_LE_BE(v) BSWAP_16((uint16_t)v) # define BSON_UINT32_SWAP_LE_BE(v) BSWAP_32((uint32_t)v) # define BSON_UINT64_SWAP_LE_BE(v) BSWAP_64((uint64_t)v) #elif defined(__clang__) && defined(__clang_major__) && defined(__clang_minor__) && \ (__clang_major__ >= 3) && (__clang_minor__ >= 1) # if __has_builtin(__builtin_bswap16) # define BSON_UINT16_SWAP_LE_BE(v) __builtin_bswap16(v) # endif # if __has_builtin(__builtin_bswap32) # define BSON_UINT32_SWAP_LE_BE(v) __builtin_bswap32(v) # endif # if __has_builtin(__builtin_bswap64) # define BSON_UINT64_SWAP_LE_BE(v) __builtin_bswap64(v) # endif #elif defined(__GNUC__) && (__GNUC__ >= 4) # if __GNUC__ >= 4 && defined (__GNUC_MINOR__) && __GNUC_MINOR__ >= 3 # define BSON_UINT32_SWAP_LE_BE(v) __builtin_bswap32 ((uint32_t)v) # define BSON_UINT64_SWAP_LE_BE(v) __builtin_bswap64 ((uint64_t)v) # endif # if __GNUC__ >= 4 && defined (__GNUC_MINOR__) && __GNUC_MINOR__ >= 8 # define BSON_UINT16_SWAP_LE_BE(v) __builtin_bswap16 ((uint32_t)v) # endif #endif #ifndef BSON_UINT16_SWAP_LE_BE # define BSON_UINT16_SWAP_LE_BE(v) __bson_uint16_swap_slow ((uint16_t)v) #endif #ifndef BSON_UINT32_SWAP_LE_BE # define BSON_UINT32_SWAP_LE_BE(v) __bson_uint32_swap_slow ((uint32_t)v) #endif #ifndef BSON_UINT64_SWAP_LE_BE # define BSON_UINT64_SWAP_LE_BE(v) __bson_uint64_swap_slow ((uint64_t)v) #endif #if BSON_BYTE_ORDER == BSON_LITTLE_ENDIAN # define BSON_UINT16_FROM_LE(v) ((uint16_t)v) # define BSON_UINT16_TO_LE(v) ((uint16_t)v) # define BSON_UINT16_FROM_BE(v) BSON_UINT16_SWAP_LE_BE (v) # define BSON_UINT16_TO_BE(v) BSON_UINT16_SWAP_LE_BE (v) # define BSON_UINT32_FROM_LE(v) ((uint32_t)v) # define BSON_UINT32_TO_LE(v) ((uint32_t)v) # define BSON_UINT32_FROM_BE(v) BSON_UINT32_SWAP_LE_BE (v) # define BSON_UINT32_TO_BE(v) BSON_UINT32_SWAP_LE_BE (v) # define BSON_UINT64_FROM_LE(v) ((uint64_t)v) # define BSON_UINT64_TO_LE(v) ((uint64_t)v) # define BSON_UINT64_FROM_BE(v) BSON_UINT64_SWAP_LE_BE (v) # define BSON_UINT64_TO_BE(v) BSON_UINT64_SWAP_LE_BE (v) # define BSON_DOUBLE_FROM_LE(v) ((double)v) # define BSON_DOUBLE_TO_LE(v) ((double)v) #elif BSON_BYTE_ORDER == BSON_BIG_ENDIAN # define BSON_UINT16_FROM_LE(v) BSON_UINT16_SWAP_LE_BE (v) # define BSON_UINT16_TO_LE(v) BSON_UINT16_SWAP_LE_BE (v) # define BSON_UINT16_FROM_BE(v) ((uint16_t)v) # define BSON_UINT16_TO_BE(v) ((uint16_t)v) # define BSON_UINT32_FROM_LE(v) BSON_UINT32_SWAP_LE_BE (v) # define BSON_UINT32_TO_LE(v) BSON_UINT32_SWAP_LE_BE (v) # define BSON_UINT32_FROM_BE(v) ((uint32_t)v) # define BSON_UINT32_TO_BE(v) ((uint32_t)v) # define BSON_UINT64_FROM_LE(v) BSON_UINT64_SWAP_LE_BE (v) # define BSON_UINT64_TO_LE(v) BSON_UINT64_SWAP_LE_BE (v) # define BSON_UINT64_FROM_BE(v) ((uint64_t)v) # define BSON_UINT64_TO_BE(v) ((uint64_t)v) # define BSON_DOUBLE_FROM_LE(v) (__bson_double_swap_slow (v)) # define BSON_DOUBLE_TO_LE(v) (__bson_double_swap_slow (v)) #else # error "The endianness of target architecture is unknown." #endif /* *-------------------------------------------------------------------------- * * __bson_uint16_swap_slow -- * * Fallback endianness conversion for 16-bit integers. * * Returns: * The endian swapped version. * * Side effects: * None. * *-------------------------------------------------------------------------- */ static BSON_INLINE uint16_t __bson_uint16_swap_slow (uint16_t v) /* IN */ { return ((v & 0x00FF) << 8) | ((v & 0xFF00) >> 8); } /* *-------------------------------------------------------------------------- * * __bson_uint32_swap_slow -- * * Fallback endianness conversion for 32-bit integers. * * Returns: * The endian swapped version. * * Side effects: * None. * *-------------------------------------------------------------------------- */ static BSON_INLINE uint32_t __bson_uint32_swap_slow (uint32_t v) /* IN */ { return ((v & 0x000000FFU) << 24) | ((v & 0x0000FF00U) << 8) | ((v & 0x00FF0000U) >> 8) | ((v & 0xFF000000U) >> 24); } /* *-------------------------------------------------------------------------- * * __bson_uint64_swap_slow -- * * Fallback endianness conversion for 64-bit integers. * * Returns: * The endian swapped version. * * Side effects: * None. * *-------------------------------------------------------------------------- */ static BSON_INLINE uint64_t __bson_uint64_swap_slow (uint64_t v) /* IN */ { return ((v & 0x00000000000000FFULL) << 56) | ((v & 0x000000000000FF00ULL) << 40) | ((v & 0x0000000000FF0000ULL) << 24) | ((v & 0x00000000FF000000ULL) << 8) | ((v & 0x000000FF00000000ULL) >> 8) | ((v & 0x0000FF0000000000ULL) >> 24) | ((v & 0x00FF000000000000ULL) >> 40) | ((v & 0xFF00000000000000ULL) >> 56); } /* *-------------------------------------------------------------------------- * * __bson_double_swap_slow -- * * Fallback endianness conversion for double floating point. * * Returns: * The endian swapped version. * * Side effects: * None. * *-------------------------------------------------------------------------- */ static BSON_INLINE double __bson_double_swap_slow (double v) /* IN */ { uint64_t uv; memcpy(&uv, &v, sizeof(v)); uv = BSON_UINT64_SWAP_LE_BE(uv); memcpy(&v, &uv, sizeof(v)); return v; } #endif /* BSON_ENDIAN_H */ mongodb-mongo-python-driver-509e9b7/bson/buffer.c000066400000000000000000000105421462766011000220150ustar00rootroot00000000000000/* * Copyright 2009-2015 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. */ /* Include Python.h so we can set Python's error indicator. */ #define PY_SSIZE_T_CLEAN #include "Python.h" #include #include #include "buffer.h" #define INITIAL_BUFFER_SIZE 256 struct buffer { char* buffer; int size; int position; }; /* Set Python's error indicator to MemoryError. * Called after allocation failures. */ static void set_memory_error(void) { PyErr_NoMemory(); } /* Allocate and return a new buffer. * Return NULL and sets MemoryError on allocation failure. */ buffer_t pymongo_buffer_new(void) { buffer_t buffer; buffer = (buffer_t)malloc(sizeof(struct buffer)); if (buffer == NULL) { set_memory_error(); return NULL; } buffer->size = INITIAL_BUFFER_SIZE; buffer->position = 0; buffer->buffer = (char*)malloc(sizeof(char) * INITIAL_BUFFER_SIZE); if (buffer->buffer == NULL) { free(buffer); set_memory_error(); return NULL; } return buffer; } /* Free the memory allocated for `buffer`. * Return non-zero on failure. */ int pymongo_buffer_free(buffer_t buffer) { if (buffer == NULL) { return 1; } /* Buffer will be NULL when buffer_grow fails. */ if (buffer->buffer != NULL) { free(buffer->buffer); } free(buffer); return 0; } /* Grow `buffer` to at least `min_length`. * Return non-zero and sets MemoryError on allocation failure. */ static int buffer_grow(buffer_t buffer, int min_length) { int old_size = 0; int size = buffer->size; char* old_buffer = buffer->buffer; if (size >= min_length) { return 0; } while (size < min_length) { old_size = size; size *= 2; if (size <= old_size) { /* Size did not increase. Could be an overflow * or size < 1. Just go with min_length. */ size = min_length; } } buffer->buffer = (char*)realloc(buffer->buffer, sizeof(char) * size); if (buffer->buffer == NULL) { free(old_buffer); set_memory_error(); return 1; } buffer->size = size; return 0; } /* Assure that `buffer` has at least `size` free bytes (and grow if needed). * Return non-zero and sets MemoryError on allocation failure. * Return non-zero and sets ValueError if `size` would exceed 2GiB. */ static int buffer_assure_space(buffer_t buffer, int size) { int new_size = buffer->position + size; /* Check for overflow. */ if (new_size < buffer->position) { PyErr_SetString(PyExc_ValueError, "Document would overflow BSON size limit"); return 1; } if (new_size <= buffer->size) { return 0; } return buffer_grow(buffer, new_size); } /* Save `size` bytes from the current position in `buffer` (and grow if needed). * Return offset for writing, or -1 on failure. * Sets MemoryError or ValueError on failure. */ buffer_position pymongo_buffer_save_space(buffer_t buffer, int size) { int position = buffer->position; if (buffer_assure_space(buffer, size) != 0) { return -1; } buffer->position += size; return position; } /* Write `size` bytes from `data` to `buffer` (and grow if needed). * Return non-zero on failure. * Sets MemoryError or ValueError on failure. */ int pymongo_buffer_write(buffer_t buffer, const char* data, int size) { if (buffer_assure_space(buffer, size) != 0) { return 1; } memcpy(buffer->buffer + buffer->position, data, size); buffer->position += size; return 0; } int pymongo_buffer_get_position(buffer_t buffer) { return buffer->position; } char* pymongo_buffer_get_buffer(buffer_t buffer) { return buffer->buffer; } void pymongo_buffer_update_position(buffer_t buffer, buffer_position new_position) { buffer->position = new_position; } mongodb-mongo-python-driver-509e9b7/bson/buffer.h000066400000000000000000000034441462766011000220250ustar00rootroot00000000000000/* * Copyright 2009-2015 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. */ #ifndef BUFFER_H #define BUFFER_H /* Note: if any of these functions return a failure condition then the buffer * has already been freed. */ /* A buffer */ typedef struct buffer* buffer_t; /* A position in the buffer */ typedef int buffer_position; /* Allocate and return a new buffer. * Return NULL on allocation failure. */ buffer_t pymongo_buffer_new(void); /* Free the memory allocated for `buffer`. * Return non-zero on failure. */ int pymongo_buffer_free(buffer_t buffer); /* Save `size` bytes from the current position in `buffer` (and grow if needed). * Return offset for writing, or -1 on allocation failure. */ buffer_position pymongo_buffer_save_space(buffer_t buffer, int size); /* Write `size` bytes from `data` to `buffer` (and grow if needed). * Return non-zero on allocation failure. */ int pymongo_buffer_write(buffer_t buffer, const char* data, int size); /* Getters for the internals of a buffer_t. * Should try to avoid using these as much as possible * since they break the abstraction. */ buffer_position pymongo_buffer_get_position(buffer_t buffer); char* pymongo_buffer_get_buffer(buffer_t buffer); void pymongo_buffer_update_position(buffer_t buffer, buffer_position new_position); #endif mongodb-mongo-python-driver-509e9b7/bson/code.py000066400000000000000000000065511462766011000216710ustar00rootroot00000000000000# Copyright 2009-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. """Tools for representing JavaScript code in BSON.""" from __future__ import annotations from collections.abc import Mapping as _Mapping from typing import Any, Mapping, Optional, Type, Union class Code(str): """BSON's JavaScript code type. Raises :class:`TypeError` if `code` is not an instance of :class:`str` or `scope` is not ``None`` or an instance of :class:`dict`. Scope variables can be set by passing a dictionary as the `scope` argument or by using keyword arguments. If a variable is set as a keyword argument it will override any setting for that variable in the `scope` dictionary. :param code: A string containing JavaScript code to be evaluated or another instance of Code. In the latter case, the scope of `code` becomes this Code's :attr:`scope`. :param scope: dictionary representing the scope in which `code` should be evaluated - a mapping from identifiers (as strings) to values. Defaults to ``None``. This is applied after any scope associated with a given `code` above. :param kwargs: scope variables can also be passed as keyword arguments. These are applied after `scope` and `code`. .. versionchanged:: 3.4 The default value for :attr:`scope` is ``None`` instead of ``{}``. """ _type_marker = 13 __scope: Union[Mapping[str, Any], None] def __new__( cls: Type[Code], code: Union[str, Code], scope: Optional[Mapping[str, Any]] = None, **kwargs: Any, ) -> Code: if not isinstance(code, str): raise TypeError("code must be an instance of str") self = str.__new__(cls, code) try: self.__scope = code.scope # type: ignore except AttributeError: self.__scope = None if scope is not None: if not isinstance(scope, _Mapping): raise TypeError("scope must be an instance of dict") if self.__scope is not None: self.__scope.update(scope) # type: ignore else: self.__scope = scope if kwargs: if self.__scope is not None: self.__scope.update(kwargs) # type: ignore else: self.__scope = kwargs return self @property def scope(self) -> Optional[Mapping[str, Any]]: """Scope dictionary for this instance or ``None``.""" return self.__scope def __repr__(self) -> str: return f"Code({str.__repr__(self)}, {self.__scope!r})" def __eq__(self, other: Any) -> bool: if isinstance(other, Code): return (self.__scope, str(self)) == (other.__scope, str(other)) return False __hash__: Any = None def __ne__(self, other: Any) -> bool: return not self == other mongodb-mongo-python-driver-509e9b7/bson/codec_options.py000066400000000000000000000463031462766011000236060ustar00rootroot00000000000000# Copyright 2014-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. """Tools for specifying BSON codec options.""" from __future__ import annotations import abc import datetime import enum from collections.abc import MutableMapping as _MutableMapping from typing import ( TYPE_CHECKING, Any, Callable, Generic, Iterable, Mapping, NamedTuple, Optional, Tuple, Type, Union, cast, ) from bson.binary import ( ALL_UUID_REPRESENTATIONS, UUID_REPRESENTATION_NAMES, UuidRepresentation, ) from bson.typings import _DocumentType _RAW_BSON_DOCUMENT_MARKER = 101 def _raw_document_class(document_class: Any) -> bool: """Determine if a document_class is a RawBSONDocument class.""" marker = getattr(document_class, "_type_marker", None) return marker == _RAW_BSON_DOCUMENT_MARKER class TypeEncoder(abc.ABC): """Base class for defining type codec classes which describe how a custom type can be transformed to one of the types BSON understands. Codec classes must implement the ``python_type`` attribute, and the ``transform_python`` method to support encoding. See :ref:`custom-type-type-codec` documentation for an example. """ @abc.abstractproperty def python_type(self) -> Any: """The Python type to be converted into something serializable.""" @abc.abstractmethod def transform_python(self, value: Any) -> Any: """Convert the given Python object into something serializable.""" class TypeDecoder(abc.ABC): """Base class for defining type codec classes which describe how a BSON type can be transformed to a custom type. Codec classes must implement the ``bson_type`` attribute, and the ``transform_bson`` method to support decoding. See :ref:`custom-type-type-codec` documentation for an example. """ @abc.abstractproperty def bson_type(self) -> Any: """The BSON type to be converted into our own type.""" @abc.abstractmethod def transform_bson(self, value: Any) -> Any: """Convert the given BSON value into our own type.""" class TypeCodec(TypeEncoder, TypeDecoder): """Base class for defining type codec classes which describe how a custom type can be transformed to/from one of the types :mod:`bson` can already encode/decode. Codec classes must implement the ``python_type`` attribute, and the ``transform_python`` method to support encoding, as well as the ``bson_type`` attribute, and the ``transform_bson`` method to support decoding. See :ref:`custom-type-type-codec` documentation for an example. """ _Codec = Union[TypeEncoder, TypeDecoder, TypeCodec] _Fallback = Callable[[Any], Any] class TypeRegistry: """Encapsulates type codecs used in encoding and / or decoding BSON, as well as the fallback encoder. Type registries cannot be modified after instantiation. ``TypeRegistry`` can be initialized with an iterable of type codecs, and a callable for the fallback encoder:: >>> from bson.codec_options import TypeRegistry >>> type_registry = TypeRegistry([Codec1, Codec2, Codec3, ...], ... fallback_encoder) See :ref:`custom-type-type-registry` documentation for an example. :param type_codecs: iterable of type codec instances. If ``type_codecs`` contains multiple codecs that transform a single python or BSON type, the transformation specified by the type codec occurring last prevails. A TypeError will be raised if one or more type codecs modify the encoding behavior of a built-in :mod:`bson` type. :param fallback_encoder: callable that accepts a single, unencodable python value and transforms it into a type that :mod:`bson` can encode. See :ref:`fallback-encoder-callable` documentation for an example. """ def __init__( self, type_codecs: Optional[Iterable[_Codec]] = None, fallback_encoder: Optional[_Fallback] = None, ) -> None: self.__type_codecs = list(type_codecs or []) self._fallback_encoder = fallback_encoder self._encoder_map: dict[Any, Any] = {} self._decoder_map: dict[Any, Any] = {} if self._fallback_encoder is not None: if not callable(fallback_encoder): raise TypeError("fallback_encoder %r is not a callable" % (fallback_encoder)) for codec in self.__type_codecs: is_valid_codec = False if isinstance(codec, TypeEncoder): self._validate_type_encoder(codec) is_valid_codec = True self._encoder_map[codec.python_type] = codec.transform_python if isinstance(codec, TypeDecoder): is_valid_codec = True self._decoder_map[codec.bson_type] = codec.transform_bson if not is_valid_codec: raise TypeError( f"Expected an instance of {TypeEncoder.__name__}, {TypeDecoder.__name__}, or {TypeCodec.__name__}, got {codec!r} instead" ) def _validate_type_encoder(self, codec: _Codec) -> None: from bson import _BUILT_IN_TYPES for pytype in _BUILT_IN_TYPES: if issubclass(cast(TypeCodec, codec).python_type, pytype): err_msg = ( "TypeEncoders cannot change how built-in types are " f"encoded (encoder {codec} transforms type {pytype})" ) raise TypeError(err_msg) def __repr__(self) -> str: return "{}(type_codecs={!r}, fallback_encoder={!r})".format( self.__class__.__name__, self.__type_codecs, self._fallback_encoder, ) def __eq__(self, other: Any) -> Any: if not isinstance(other, type(self)): return NotImplemented return ( (self._decoder_map == other._decoder_map) and (self._encoder_map == other._encoder_map) and (self._fallback_encoder == other._fallback_encoder) ) class DatetimeConversion(int, enum.Enum): """Options for decoding BSON datetimes.""" DATETIME = 1 """Decode a BSON UTC datetime as a :class:`datetime.datetime`. BSON UTC datetimes that cannot be represented as a :class:`~datetime.datetime` will raise an :class:`OverflowError` or a :class:`ValueError`. .. versionadded 4.3 """ DATETIME_CLAMP = 2 """Decode a BSON UTC datetime as a :class:`datetime.datetime`, clamping to :attr:`~datetime.datetime.min` and :attr:`~datetime.datetime.max`. .. versionadded 4.3 """ DATETIME_MS = 3 """Decode a BSON UTC datetime as a :class:`~bson.datetime_ms.DatetimeMS` object. .. versionadded 4.3 """ DATETIME_AUTO = 4 """Decode a BSON UTC datetime as a :class:`datetime.datetime` if possible, and a :class:`~bson.datetime_ms.DatetimeMS` if not. .. versionadded 4.3 """ class _BaseCodecOptions(NamedTuple): document_class: Type[Mapping[str, Any]] tz_aware: bool uuid_representation: int unicode_decode_error_handler: str tzinfo: Optional[datetime.tzinfo] type_registry: TypeRegistry datetime_conversion: Optional[DatetimeConversion] if TYPE_CHECKING: class CodecOptions(Tuple[_DocumentType], Generic[_DocumentType]): document_class: Type[_DocumentType] tz_aware: bool uuid_representation: int unicode_decode_error_handler: Optional[str] tzinfo: Optional[datetime.tzinfo] type_registry: TypeRegistry datetime_conversion: Optional[int] def __new__( cls: Type[CodecOptions[_DocumentType]], document_class: Optional[Type[_DocumentType]] = ..., tz_aware: bool = ..., uuid_representation: Optional[int] = ..., unicode_decode_error_handler: Optional[str] = ..., tzinfo: Optional[datetime.tzinfo] = ..., type_registry: Optional[TypeRegistry] = ..., datetime_conversion: Optional[int] = ..., ) -> CodecOptions[_DocumentType]: ... # CodecOptions API def with_options(self, **kwargs: Any) -> CodecOptions[Any]: ... def _arguments_repr(self) -> str: ... def _options_dict(self) -> dict[Any, Any]: ... # NamedTuple API @classmethod def _make(cls, obj: Iterable[Any]) -> CodecOptions[_DocumentType]: ... def _asdict(self) -> dict[str, Any]: ... def _replace(self, **kwargs: Any) -> CodecOptions[_DocumentType]: ... _source: str _fields: Tuple[str] else: class CodecOptions(_BaseCodecOptions): """Encapsulates options used encoding and / or decoding BSON.""" def __init__(self, *args, **kwargs): """Encapsulates options used encoding and / or decoding BSON. The `document_class` option is used to define a custom type for use decoding BSON documents. Access to the underlying raw BSON bytes for a document is available using the :class:`~bson.raw_bson.RawBSONDocument` type:: >>> from bson.raw_bson import RawBSONDocument >>> from bson.codec_options import CodecOptions >>> codec_options = CodecOptions(document_class=RawBSONDocument) >>> coll = db.get_collection('test', codec_options=codec_options) >>> doc = coll.find_one() >>> doc.raw '\\x16\\x00\\x00\\x00\\x07_id\\x00[0\\x165\\x91\\x10\\xea\\x14\\xe8\\xc5\\x8b\\x93\\x00' The document class can be any type that inherits from :class:`~collections.abc.MutableMapping`:: >>> class AttributeDict(dict): ... # A dict that supports attribute access. ... def __getattr__(self, key): ... return self[key] ... def __setattr__(self, key, value): ... self[key] = value ... >>> codec_options = CodecOptions(document_class=AttributeDict) >>> coll = db.get_collection('test', codec_options=codec_options) >>> doc = coll.find_one() >>> doc._id ObjectId('5b3016359110ea14e8c58b93') See :doc:`/examples/datetimes` for examples using the `tz_aware` and `tzinfo` options. See :doc:`/examples/uuid` for examples using the `uuid_representation` option. :param document_class: BSON documents returned in queries will be decoded to an instance of this class. Must be a subclass of :class:`~collections.abc.MutableMapping`. Defaults to :class:`dict`. :param tz_aware: If ``True``, BSON datetimes will be decoded to timezone aware instances of :class:`~datetime.datetime`. Otherwise they will be naive. Defaults to ``False``. :param uuid_representation: The BSON representation to use when encoding and decoding instances of :class:`~uuid.UUID`. Defaults to :data:`~bson.binary.UuidRepresentation.UNSPECIFIED`. New applications should consider setting this to :data:`~bson.binary.UuidRepresentation.STANDARD` for cross language compatibility. See :ref:`handling-uuid-data-example` for details. :param unicode_decode_error_handler: The error handler to apply when a Unicode-related error occurs during BSON decoding that would otherwise raise :exc:`UnicodeDecodeError`. Valid options include 'strict', 'replace', 'backslashreplace', 'surrogateescape', and 'ignore'. Defaults to 'strict'. :param tzinfo: A :class:`~datetime.tzinfo` subclass that specifies the timezone to/from which :class:`~datetime.datetime` objects should be encoded/decoded. :param type_registry: Instance of :class:`TypeRegistry` used to customize encoding and decoding behavior. :param datetime_conversion: Specifies how UTC datetimes should be decoded within BSON. Valid options include 'datetime_ms' to return as a DatetimeMS, 'datetime' to return as a datetime.datetime and raising a ValueError for out-of-range values, 'datetime_auto' to return DatetimeMS objects when the underlying datetime is out-of-range and 'datetime_clamp' to clamp to the minimum and maximum possible datetimes. Defaults to 'datetime'. .. versionchanged:: 4.0 The default for `uuid_representation` was changed from :const:`~bson.binary.UuidRepresentation.PYTHON_LEGACY` to :const:`~bson.binary.UuidRepresentation.UNSPECIFIED`. .. versionadded:: 3.8 `type_registry` attribute. .. warning:: Care must be taken when changing `unicode_decode_error_handler` from its default value ('strict'). The 'replace' and 'ignore' modes should not be used when documents retrieved from the server will be modified in the client application and stored back to the server. """ super().__init__() def __new__( cls: Type[CodecOptions], document_class: Optional[Type[Mapping[str, Any]]] = None, tz_aware: bool = False, uuid_representation: Optional[int] = UuidRepresentation.UNSPECIFIED, unicode_decode_error_handler: str = "strict", tzinfo: Optional[datetime.tzinfo] = None, type_registry: Optional[TypeRegistry] = None, datetime_conversion: Optional[DatetimeConversion] = DatetimeConversion.DATETIME, ) -> CodecOptions: doc_class = document_class or dict # issubclass can raise TypeError for generic aliases like SON[str, Any]. # In that case we can use the base class for the comparison. is_mapping = False try: is_mapping = issubclass(doc_class, _MutableMapping) except TypeError: if hasattr(doc_class, "__origin__"): is_mapping = issubclass(doc_class.__origin__, _MutableMapping) if not (is_mapping or _raw_document_class(doc_class)): raise TypeError( "document_class must be dict, bson.son.SON, " "bson.raw_bson.RawBSONDocument, or a " "subclass of collections.abc.MutableMapping" ) if not isinstance(tz_aware, bool): raise TypeError(f"tz_aware must be True or False, was: tz_aware={tz_aware}") if uuid_representation not in ALL_UUID_REPRESENTATIONS: raise ValueError( "uuid_representation must be a value from bson.binary.UuidRepresentation" ) if not isinstance(unicode_decode_error_handler, str): raise ValueError("unicode_decode_error_handler must be a string") if tzinfo is not None: if not isinstance(tzinfo, datetime.tzinfo): raise TypeError("tzinfo must be an instance of datetime.tzinfo") if not tz_aware: raise ValueError("cannot specify tzinfo without also setting tz_aware=True") type_registry = type_registry or TypeRegistry() if not isinstance(type_registry, TypeRegistry): raise TypeError("type_registry must be an instance of TypeRegistry") return tuple.__new__( cls, ( doc_class, tz_aware, uuid_representation, unicode_decode_error_handler, tzinfo, type_registry, datetime_conversion, ), ) def _arguments_repr(self) -> str: """Representation of the arguments used to create this object.""" document_class_repr = ( "dict" if self.document_class is dict else repr(self.document_class) ) uuid_rep_repr = UUID_REPRESENTATION_NAMES.get( self.uuid_representation, self.uuid_representation ) return ( "document_class={}, tz_aware={!r}, uuid_representation={}, " "unicode_decode_error_handler={!r}, tzinfo={!r}, " "type_registry={!r}, datetime_conversion={!s}".format( document_class_repr, self.tz_aware, uuid_rep_repr, self.unicode_decode_error_handler, self.tzinfo, self.type_registry, self.datetime_conversion, ) ) def _options_dict(self) -> dict[str, Any]: """Dictionary of the arguments used to create this object.""" # TODO: PYTHON-2442 use _asdict() instead return { "document_class": self.document_class, "tz_aware": self.tz_aware, "uuid_representation": self.uuid_representation, "unicode_decode_error_handler": self.unicode_decode_error_handler, "tzinfo": self.tzinfo, "type_registry": self.type_registry, "datetime_conversion": self.datetime_conversion, } def __repr__(self) -> str: return f"{self.__class__.__name__}({self._arguments_repr()})" def with_options(self, **kwargs: Any) -> CodecOptions: """Make a copy of this CodecOptions, overriding some options:: >>> from bson.codec_options import DEFAULT_CODEC_OPTIONS >>> DEFAULT_CODEC_OPTIONS.tz_aware False >>> options = DEFAULT_CODEC_OPTIONS.with_options(tz_aware=True) >>> options.tz_aware True .. versionadded:: 3.5 """ opts = self._options_dict() opts.update(kwargs) return CodecOptions(**opts) DEFAULT_CODEC_OPTIONS: CodecOptions[dict[str, Any]] = CodecOptions() def _parse_codec_options(options: Any) -> CodecOptions[Any]: """Parse BSON codec options.""" kwargs = {} for k in set(options) & { "document_class", "tz_aware", "uuidrepresentation", "unicode_decode_error_handler", "tzinfo", "type_registry", "datetime_conversion", }: if k == "uuidrepresentation": kwargs["uuid_representation"] = options[k] else: kwargs[k] = options[k] return CodecOptions(**kwargs) mongodb-mongo-python-driver-509e9b7/bson/datetime_ms.py000066400000000000000000000146411462766011000232510ustar00rootroot00000000000000# Copyright 2022-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. """Tools for representing the BSON datetime type. .. versionadded:: 4.3 """ from __future__ import annotations import calendar import datetime import functools from typing import Any, Union, cast from bson.codec_options import DEFAULT_CODEC_OPTIONS, CodecOptions, DatetimeConversion from bson.errors import InvalidBSON from bson.tz_util import utc EPOCH_AWARE = datetime.datetime.fromtimestamp(0, utc) EPOCH_NAIVE = EPOCH_AWARE.replace(tzinfo=None) _DATETIME_ERROR_SUGGESTION = ( "(Consider Using CodecOptions(datetime_conversion=DATETIME_AUTO)" " or MongoClient(datetime_conversion='DATETIME_AUTO'))." " See: https://pymongo.readthedocs.io/en/stable/examples/datetimes.html#handling-out-of-range-datetimes" ) class DatetimeMS: """Represents a BSON UTC datetime.""" __slots__ = ("_value",) def __init__(self, value: Union[int, datetime.datetime]): """Represents a BSON UTC datetime. BSON UTC datetimes are defined as an int64 of milliseconds since the Unix epoch. The principal use of DatetimeMS is to represent datetimes outside the range of the Python builtin :class:`~datetime.datetime` class when encoding/decoding BSON. To decode UTC datetimes as a ``DatetimeMS``, `datetime_conversion` in :class:`~bson.codec_options.CodecOptions` must be set to 'datetime_ms' or 'datetime_auto'. See :ref:`handling-out-of-range-datetimes` for details. :param value: An instance of :class:`datetime.datetime` to be represented as milliseconds since the Unix epoch, or int of milliseconds since the Unix epoch. """ if isinstance(value, int): if not (-(2**63) <= value <= 2**63 - 1): raise OverflowError("Must be a 64-bit integer of milliseconds") self._value = value elif isinstance(value, datetime.datetime): self._value = _datetime_to_millis(value) else: raise TypeError(f"{type(value)} is not a valid type for DatetimeMS") def __hash__(self) -> int: return hash(self._value) def __repr__(self) -> str: return type(self).__name__ + "(" + str(self._value) + ")" def __lt__(self, other: Union[DatetimeMS, int]) -> bool: return self._value < other def __le__(self, other: Union[DatetimeMS, int]) -> bool: return self._value <= other def __eq__(self, other: Any) -> bool: if isinstance(other, DatetimeMS): return self._value == other._value return False def __ne__(self, other: Any) -> bool: if isinstance(other, DatetimeMS): return self._value != other._value return True def __gt__(self, other: Union[DatetimeMS, int]) -> bool: return self._value > other def __ge__(self, other: Union[DatetimeMS, int]) -> bool: return self._value >= other _type_marker = 9 def as_datetime( self, codec_options: CodecOptions[Any] = DEFAULT_CODEC_OPTIONS ) -> datetime.datetime: """Create a Python :class:`~datetime.datetime` from this DatetimeMS object. :param codec_options: A CodecOptions instance for specifying how the resulting DatetimeMS object will be formatted using ``tz_aware`` and ``tz_info``. Defaults to :const:`~bson.codec_options.DEFAULT_CODEC_OPTIONS`. """ return cast(datetime.datetime, _millis_to_datetime(self._value, codec_options)) def __int__(self) -> int: return self._value # Inclusive and exclusive min and max for timezones. # Timezones are hashed by their offset, which is a timedelta # and therefore there are more than 24 possible timezones. @functools.lru_cache(maxsize=None) def _min_datetime_ms(tz: datetime.timezone = datetime.timezone.utc) -> int: return _datetime_to_millis(datetime.datetime.min.replace(tzinfo=tz)) @functools.lru_cache(maxsize=None) def _max_datetime_ms(tz: datetime.timezone = datetime.timezone.utc) -> int: return _datetime_to_millis(datetime.datetime.max.replace(tzinfo=tz)) def _millis_to_datetime( millis: int, opts: CodecOptions[Any] ) -> Union[datetime.datetime, DatetimeMS]: """Convert milliseconds since epoch UTC to datetime.""" if ( opts.datetime_conversion == DatetimeConversion.DATETIME or opts.datetime_conversion == DatetimeConversion.DATETIME_CLAMP or opts.datetime_conversion == DatetimeConversion.DATETIME_AUTO ): tz = opts.tzinfo or datetime.timezone.utc if opts.datetime_conversion == DatetimeConversion.DATETIME_CLAMP: millis = max(_min_datetime_ms(tz), min(millis, _max_datetime_ms(tz))) elif opts.datetime_conversion == DatetimeConversion.DATETIME_AUTO: if not (_min_datetime_ms(tz) <= millis <= _max_datetime_ms(tz)): return DatetimeMS(millis) diff = ((millis % 1000) + 1000) % 1000 seconds = (millis - diff) // 1000 micros = diff * 1000 try: if opts.tz_aware: dt = EPOCH_AWARE + datetime.timedelta(seconds=seconds, microseconds=micros) if opts.tzinfo: dt = dt.astimezone(tz) return dt else: return EPOCH_NAIVE + datetime.timedelta(seconds=seconds, microseconds=micros) except ArithmeticError as err: raise InvalidBSON(f"{err} {_DATETIME_ERROR_SUGGESTION}") from err elif opts.datetime_conversion == DatetimeConversion.DATETIME_MS: return DatetimeMS(millis) else: raise ValueError("datetime_conversion must be an element of DatetimeConversion") def _datetime_to_millis(dtm: datetime.datetime) -> int: """Convert datetime to milliseconds since epoch UTC.""" if dtm.utcoffset() is not None: dtm = dtm - dtm.utcoffset() # type: ignore return int(calendar.timegm(dtm.timetuple()) * 1000 + dtm.microsecond // 1000) mongodb-mongo-python-driver-509e9b7/bson/dbref.py000066400000000000000000000111701462766011000220320ustar00rootroot00000000000000# Copyright 2009-2015 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. """Tools for manipulating DBRefs (references to MongoDB documents).""" from __future__ import annotations from copy import deepcopy from typing import Any, Mapping, Optional from bson._helpers import _getstate_slots, _setstate_slots from bson.son import SON class DBRef: """A reference to a document stored in MongoDB.""" __slots__ = "__collection", "__id", "__database", "__kwargs" __getstate__ = _getstate_slots __setstate__ = _setstate_slots # DBRef isn't actually a BSON "type" so this number was arbitrarily chosen. _type_marker = 100 def __init__( self, collection: str, id: Any, database: Optional[str] = None, _extra: Optional[Mapping[str, Any]] = None, **kwargs: Any, ) -> None: """Initialize a new :class:`DBRef`. Raises :class:`TypeError` if `collection` or `database` is not an instance of :class:`str`. `database` is optional and allows references to documents to work across databases. Any additional keyword arguments will create additional fields in the resultant embedded document. :param collection: name of the collection the document is stored in :param id: the value of the document's ``"_id"`` field :param database: name of the database to reference :param kwargs: additional keyword arguments will create additional, custom fields .. seealso:: The MongoDB documentation on `dbrefs `_. """ if not isinstance(collection, str): raise TypeError("collection must be an instance of str") if database is not None and not isinstance(database, str): raise TypeError("database must be an instance of str") self.__collection = collection self.__id = id self.__database = database kwargs.update(_extra or {}) self.__kwargs = kwargs @property def collection(self) -> str: """Get the name of this DBRef's collection.""" return self.__collection @property def id(self) -> Any: """Get this DBRef's _id.""" return self.__id @property def database(self) -> Optional[str]: """Get the name of this DBRef's database. Returns None if this DBRef doesn't specify a database. """ return self.__database def __getattr__(self, key: Any) -> Any: try: return self.__kwargs[key] except KeyError: raise AttributeError(key) from None def as_doc(self) -> SON[str, Any]: """Get the SON document representation of this DBRef. Generally not needed by application developers """ doc = SON([("$ref", self.collection), ("$id", self.id)]) if self.database is not None: doc["$db"] = self.database doc.update(self.__kwargs) return doc def __repr__(self) -> str: extra = "".join([f", {k}={v!r}" for k, v in self.__kwargs.items()]) if self.database is None: return f"DBRef({self.collection!r}, {self.id!r}{extra})" return f"DBRef({self.collection!r}, {self.id!r}, {self.database!r}{extra})" def __eq__(self, other: Any) -> bool: if isinstance(other, DBRef): us = (self.__database, self.__collection, self.__id, self.__kwargs) them = (other.__database, other.__collection, other.__id, other.__kwargs) return us == them return NotImplemented def __ne__(self, other: Any) -> bool: return not self == other def __hash__(self) -> int: """Get a hash value for this :class:`DBRef`.""" return hash( (self.__collection, self.__id, self.__database, tuple(sorted(self.__kwargs.items()))) ) def __deepcopy__(self, memo: Any) -> DBRef: """Support function for `copy.deepcopy()`.""" return DBRef( deepcopy(self.__collection, memo), deepcopy(self.__id, memo), deepcopy(self.__database, memo), deepcopy(self.__kwargs, memo), ) mongodb-mongo-python-driver-509e9b7/bson/decimal128.py000066400000000000000000000237451462766011000226140ustar00rootroot00000000000000# Copyright 2016-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. """Tools for working with the BSON decimal128 type. .. versionadded:: 3.4 """ from __future__ import annotations import decimal import struct from typing import Any, Sequence, Tuple, Type, Union _PACK_64 = struct.Struct(" decimal.Context: """Returns an instance of :class:`decimal.Context` appropriate for working with IEEE-754 128-bit decimal floating point values. """ opts = _CTX_OPTIONS.copy() opts["traps"] = [] return decimal.Context(**opts) # type: ignore def _decimal_to_128(value: _VALUE_OPTIONS) -> Tuple[int, int]: """Converts a decimal.Decimal to BID (high bits, low bits). :param value: An instance of decimal.Decimal """ with decimal.localcontext(_DEC128_CTX) as ctx: value = ctx.create_decimal(value) if value.is_infinite(): return _NINF if value.is_signed() else _PINF sign, digits, exponent = value.as_tuple() if value.is_nan(): if digits: raise ValueError("NaN with debug payload is not supported") if value.is_snan(): return _NSNAN if value.is_signed() else _PSNAN return _NNAN if value.is_signed() else _PNAN significand = int("".join([str(digit) for digit in digits])) bit_length = significand.bit_length() high = 0 low = 0 for i in range(min(64, bit_length)): if significand & (1 << i): low |= 1 << i for i in range(64, bit_length): if significand & (1 << i): high |= 1 << (i - 64) biased_exponent = exponent + _EXPONENT_BIAS # type: ignore[operator] if high >> 49 == 1: high = high & 0x7FFFFFFFFFFF high |= _EXPONENT_MASK high |= (biased_exponent & 0x3FFF) << 47 else: high |= biased_exponent << 49 if sign: high |= _SIGN return high, low class Decimal128: """BSON Decimal128 type:: >>> Decimal128(Decimal("0.0005")) Decimal128('0.0005') >>> Decimal128("0.0005") Decimal128('0.0005') >>> Decimal128((3474527112516337664, 5)) Decimal128('0.0005') :param value: An instance of :class:`decimal.Decimal`, string, or tuple of (high bits, low bits) from Binary Integer Decimal (BID) format. .. note:: :class:`~Decimal128` uses an instance of :class:`decimal.Context` configured for IEEE-754 Decimal128 when validating parameters. Signals like :class:`decimal.InvalidOperation`, :class:`decimal.Inexact`, and :class:`decimal.Overflow` are trapped and raised as exceptions:: >>> Decimal128(".13.1") Traceback (most recent call last): File "", line 1, in ... decimal.InvalidOperation: [] >>> >>> Decimal128("1E-6177") Traceback (most recent call last): File "", line 1, in ... decimal.Inexact: [] >>> >>> Decimal128("1E6145") Traceback (most recent call last): File "", line 1, in ... decimal.Overflow: [, ] To ensure the result of a calculation can always be stored as BSON Decimal128 use the context returned by :func:`create_decimal128_context`:: >>> import decimal >>> decimal128_ctx = create_decimal128_context() >>> with decimal.localcontext(decimal128_ctx) as ctx: ... Decimal128(ctx.create_decimal(".13.3")) ... Decimal128('NaN') >>> >>> with decimal.localcontext(decimal128_ctx) as ctx: ... Decimal128(ctx.create_decimal("1E-6177")) ... Decimal128('0E-6176') >>> >>> with decimal.localcontext(DECIMAL128_CTX) as ctx: ... Decimal128(ctx.create_decimal("1E6145")) ... Decimal128('Infinity') To match the behavior of MongoDB's Decimal128 implementation str(Decimal(value)) may not match str(Decimal128(value)) for NaN values:: >>> Decimal128(Decimal('NaN')) Decimal128('NaN') >>> Decimal128(Decimal('-NaN')) Decimal128('NaN') >>> Decimal128(Decimal('sNaN')) Decimal128('NaN') >>> Decimal128(Decimal('-sNaN')) Decimal128('NaN') However, :meth:`~Decimal128.to_decimal` will return the exact value:: >>> Decimal128(Decimal('NaN')).to_decimal() Decimal('NaN') >>> Decimal128(Decimal('-NaN')).to_decimal() Decimal('-NaN') >>> Decimal128(Decimal('sNaN')).to_decimal() Decimal('sNaN') >>> Decimal128(Decimal('-sNaN')).to_decimal() Decimal('-sNaN') Two instances of :class:`Decimal128` compare equal if their Binary Integer Decimal encodings are equal:: >>> Decimal128('NaN') == Decimal128('NaN') True >>> Decimal128('NaN').bid == Decimal128('NaN').bid True This differs from :class:`decimal.Decimal` comparisons for NaN:: >>> Decimal('NaN') == Decimal('NaN') False """ __slots__ = ("__high", "__low") _type_marker = 19 def __init__(self, value: _VALUE_OPTIONS) -> None: if isinstance(value, (str, decimal.Decimal)): self.__high, self.__low = _decimal_to_128(value) elif isinstance(value, (list, tuple)): if len(value) != 2: raise ValueError( "Invalid size for creation of Decimal128 " "from list or tuple. Must have exactly 2 " "elements." ) self.__high, self.__low = value # type: ignore else: raise TypeError(f"Cannot convert {value!r} to Decimal128") def to_decimal(self) -> decimal.Decimal: """Returns an instance of :class:`decimal.Decimal` for this :class:`Decimal128`. """ high = self.__high low = self.__low sign = 1 if (high & _SIGN) else 0 if (high & _SNAN) == _SNAN: return decimal.Decimal((sign, (), "N")) # type: ignore elif (high & _NAN) == _NAN: return decimal.Decimal((sign, (), "n")) # type: ignore elif (high & _INF) == _INF: return decimal.Decimal((sign, (), "F")) # type: ignore if (high & _EXPONENT_MASK) == _EXPONENT_MASK: exponent = ((high & 0x1FFFE00000000000) >> 47) - _EXPONENT_BIAS return decimal.Decimal((sign, (0,), exponent)) else: exponent = ((high & 0x7FFF800000000000) >> 49) - _EXPONENT_BIAS arr = bytearray(15) mask = 0x00000000000000FF for i in range(14, 6, -1): arr[i] = (low & mask) >> ((14 - i) << 3) mask = mask << 8 mask = 0x00000000000000FF for i in range(6, 0, -1): arr[i] = (high & mask) >> ((6 - i) << 3) mask = mask << 8 mask = 0x0001000000000000 arr[0] = (high & mask) >> 48 # cdecimal only accepts a tuple for digits. digits = tuple(int(digit) for digit in str(int.from_bytes(arr, "big"))) with decimal.localcontext(_DEC128_CTX) as ctx: return ctx.create_decimal((sign, digits, exponent)) @classmethod def from_bid(cls: Type[Decimal128], value: bytes) -> Decimal128: """Create an instance of :class:`Decimal128` from Binary Integer Decimal string. :param value: 16 byte string (128-bit IEEE 754-2008 decimal floating point in Binary Integer Decimal (BID) format). """ if not isinstance(value, bytes): raise TypeError("value must be an instance of bytes") if len(value) != 16: raise ValueError("value must be exactly 16 bytes") return cls((_UNPACK_64(value[8:])[0], _UNPACK_64(value[:8])[0])) # type: ignore @property def bid(self) -> bytes: """The Binary Integer Decimal (BID) encoding of this instance.""" return _PACK_64(self.__low) + _PACK_64(self.__high) def __str__(self) -> str: dec = self.to_decimal() if dec.is_nan(): # Required by the drivers spec to match MongoDB behavior. return "NaN" return str(dec) def __repr__(self) -> str: return f"Decimal128('{self!s}')" def __setstate__(self, value: Tuple[int, int]) -> None: self.__high, self.__low = value def __getstate__(self) -> Tuple[int, int]: return self.__high, self.__low def __eq__(self, other: Any) -> bool: if isinstance(other, Decimal128): return self.bid == other.bid return NotImplemented def __ne__(self, other: Any) -> bool: return not self == other mongodb-mongo-python-driver-509e9b7/bson/errors.py000066400000000000000000000022211462766011000222610ustar00rootroot00000000000000# Copyright 2009-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. """Exceptions raised by the BSON package.""" from __future__ import annotations class BSONError(Exception): """Base class for all BSON exceptions.""" class InvalidBSON(BSONError): """Raised when trying to create a BSON object from invalid data.""" class InvalidStringData(BSONError): """Raised when trying to encode a string containing non-UTF8 data.""" class InvalidDocument(BSONError): """Raised when trying to create a BSON object from an invalid document.""" class InvalidId(BSONError): """Raised when trying to create an ObjectId from invalid data.""" mongodb-mongo-python-driver-509e9b7/bson/int64.py000066400000000000000000000022321462766011000217130ustar00rootroot00000000000000# Copyright 2014-2015 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. """A BSON wrapper for long (int in python3)""" from __future__ import annotations from typing import Any class Int64(int): """Representation of the BSON int64 type. This is necessary because every integral number is an :class:`int` in Python 3. Small integral numbers are encoded to BSON int32 by default, but Int64 numbers will always be encoded to BSON int64. :param value: the numeric value to represent """ __slots__ = () _type_marker = 18 def __getstate__(self) -> Any: return {} def __setstate__(self, state: Any) -> None: pass mongodb-mongo-python-driver-509e9b7/bson/json_util.py000066400000000000000000001232111462766011000227560ustar00rootroot00000000000000# Copyright 2009-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. """Tools for using Python's :mod:`json` module with BSON documents. This module provides two helper methods `dumps` and `loads` that wrap the native :mod:`json` methods and provide explicit BSON conversion to and from JSON. :class:`~bson.json_util.JSONOptions` provides a way to control how JSON is emitted and parsed, with the default being the Relaxed Extended JSON format. :mod:`~bson.json_util` can also generate Canonical or legacy `Extended JSON`_ when :const:`CANONICAL_JSON_OPTIONS` or :const:`LEGACY_JSON_OPTIONS` is provided, respectively. .. _Extended JSON: https://github.com/mongodb/specifications/blob/master/source/extended-json.rst Example usage (deserialization): .. doctest:: >>> from bson.json_util import loads >>> loads( ... '[{"foo": [1, 2]}, {"bar": {"hello": "world"}}, {"code": {"$scope": {}, "$code": "function x() { return 1; }"}}, {"bin": {"$type": "80", "$binary": "AQIDBA=="}}]' ... ) [{'foo': [1, 2]}, {'bar': {'hello': 'world'}}, {'code': Code('function x() { return 1; }', {})}, {'bin': Binary(b'...', 128)}] Example usage with :const:`RELAXED_JSON_OPTIONS` (the default): .. doctest:: >>> from bson import Binary, Code >>> from bson.json_util import dumps >>> dumps( ... [ ... {"foo": [1, 2]}, ... {"bar": {"hello": "world"}}, ... {"code": Code("function x() { return 1; }")}, ... {"bin": Binary(b"\x01\x02\x03\x04")}, ... ] ... ) '[{"foo": [1, 2]}, {"bar": {"hello": "world"}}, {"code": {"$code": "function x() { return 1; }"}}, {"bin": {"$binary": {"base64": "AQIDBA==", "subType": "00"}}}]' Example usage (with :const:`CANONICAL_JSON_OPTIONS`): .. doctest:: >>> from bson import Binary, Code >>> from bson.json_util import dumps, CANONICAL_JSON_OPTIONS >>> dumps( ... [ ... {"foo": [1, 2]}, ... {"bar": {"hello": "world"}}, ... {"code": Code("function x() { return 1; }")}, ... {"bin": Binary(b"\x01\x02\x03\x04")}, ... ], ... json_options=CANONICAL_JSON_OPTIONS, ... ) '[{"foo": [{"$numberInt": "1"}, {"$numberInt": "2"}]}, {"bar": {"hello": "world"}}, {"code": {"$code": "function x() { return 1; }"}}, {"bin": {"$binary": {"base64": "AQIDBA==", "subType": "00"}}}]' Example usage (with :const:`LEGACY_JSON_OPTIONS`): .. doctest:: >>> from bson import Binary, Code >>> from bson.json_util import dumps, LEGACY_JSON_OPTIONS >>> dumps( ... [ ... {"foo": [1, 2]}, ... {"bar": {"hello": "world"}}, ... {"code": Code("function x() { return 1; }", {})}, ... {"bin": Binary(b"\x01\x02\x03\x04")}, ... ], ... json_options=LEGACY_JSON_OPTIONS, ... ) '[{"foo": [1, 2]}, {"bar": {"hello": "world"}}, {"code": {"$code": "function x() { return 1; }", "$scope": {}}}, {"bin": {"$binary": "AQIDBA==", "$type": "00"}}]' Alternatively, you can manually pass the `default` to :func:`json.dumps`. It won't handle :class:`~bson.binary.Binary` and :class:`~bson.code.Code` instances (as they are extended strings you can't provide custom defaults), but it will be faster as there is less recursion. .. note:: If your application does not need the flexibility offered by :class:`JSONOptions` and spends a large amount of time in the `json_util` module, look to `python-bsonjs `_ for a nice performance improvement. `python-bsonjs` is a fast BSON to MongoDB Extended JSON converter for Python built on top of `libbson `_. `python-bsonjs` works best with PyMongo when using :class:`~bson.raw_bson.RawBSONDocument`. """ from __future__ import annotations import base64 import datetime import json import math import re import uuid from typing import ( TYPE_CHECKING, Any, Callable, Mapping, MutableMapping, Optional, Sequence, Tuple, Type, Union, cast, ) from bson.binary import ALL_UUID_SUBTYPES, UUID_SUBTYPE, Binary, UuidRepresentation from bson.code import Code from bson.codec_options import CodecOptions, DatetimeConversion from bson.datetime_ms import ( EPOCH_AWARE, DatetimeMS, _datetime_to_millis, _max_datetime_ms, _millis_to_datetime, ) from bson.dbref import DBRef from bson.decimal128 import Decimal128 from bson.int64 import Int64 from bson.max_key import MaxKey from bson.min_key import MinKey from bson.objectid import ObjectId from bson.regex import Regex from bson.son import RE_TYPE from bson.timestamp import Timestamp from bson.tz_util import utc _RE_OPT_TABLE = { "i": re.I, "l": re.L, "m": re.M, "s": re.S, "u": re.U, "x": re.X, } class DatetimeRepresentation: LEGACY = 0 """Legacy MongoDB Extended JSON datetime representation. :class:`datetime.datetime` instances will be encoded to JSON in the format `{"$date": }`, where `dateAsMilliseconds` is a 64-bit signed integer giving the number of milliseconds since the Unix epoch UTC. This was the default encoding before PyMongo version 3.4. .. versionadded:: 3.4 """ NUMBERLONG = 1 """NumberLong datetime representation. :class:`datetime.datetime` instances will be encoded to JSON in the format `{"$date": {"$numberLong": ""}}`, where `dateAsMilliseconds` is the string representation of a 64-bit signed integer giving the number of milliseconds since the Unix epoch UTC. .. versionadded:: 3.4 """ ISO8601 = 2 """ISO-8601 datetime representation. :class:`datetime.datetime` instances greater than or equal to the Unix epoch UTC will be encoded to JSON in the format `{"$date": ""}`. :class:`datetime.datetime` instances before the Unix epoch UTC will be encoded as if the datetime representation is :const:`~DatetimeRepresentation.NUMBERLONG`. .. versionadded:: 3.4 """ class JSONMode: LEGACY = 0 """Legacy Extended JSON representation. In this mode, :func:`~bson.json_util.dumps` produces PyMongo's legacy non-standard JSON output. Consider using :const:`~bson.json_util.JSONMode.RELAXED` or :const:`~bson.json_util.JSONMode.CANONICAL` instead. .. versionadded:: 3.5 """ RELAXED = 1 """Relaxed Extended JSON representation. In this mode, :func:`~bson.json_util.dumps` produces Relaxed Extended JSON, a mostly JSON-like format. Consider using this for things like a web API, where one is sending a document (or a projection of a document) that only uses ordinary JSON type primitives. In particular, the ``int``, :class:`~bson.int64.Int64`, and ``float`` numeric types are represented in the native JSON number format. This output is also the most human readable and is useful for debugging and documentation. .. seealso:: The specification for Relaxed `Extended JSON`_. .. versionadded:: 3.5 """ CANONICAL = 2 """Canonical Extended JSON representation. In this mode, :func:`~bson.json_util.dumps` produces Canonical Extended JSON, a type preserving format. Consider using this for things like testing, where one has to precisely specify expected types in JSON. In particular, the ``int``, :class:`~bson.int64.Int64`, and ``float`` numeric types are encoded with type wrappers. .. seealso:: The specification for Canonical `Extended JSON`_. .. versionadded:: 3.5 """ if TYPE_CHECKING: _BASE_CLASS = CodecOptions[MutableMapping[str, Any]] else: _BASE_CLASS = CodecOptions _INT32_MAX = 2**31 class JSONOptions(_BASE_CLASS): json_mode: int strict_number_long: bool datetime_representation: int strict_uuid: bool document_class: Type[MutableMapping[str, Any]] def __init__(self, *args: Any, **kwargs: Any): """Encapsulates JSON options for :func:`dumps` and :func:`loads`. :param strict_number_long: If ``True``, :class:`~bson.int64.Int64` objects are encoded to MongoDB Extended JSON's *Strict mode* type `NumberLong`, ie ``'{"$numberLong": "" }'``. Otherwise they will be encoded as an `int`. Defaults to ``False``. :param datetime_representation: The representation to use when encoding instances of :class:`datetime.datetime`. Defaults to :const:`~DatetimeRepresentation.LEGACY`. :param strict_uuid: If ``True``, :class:`uuid.UUID` object are encoded to MongoDB Extended JSON's *Strict mode* type `Binary`. Otherwise it will be encoded as ``'{"$uuid": "" }'``. Defaults to ``False``. :param json_mode: The :class:`JSONMode` to use when encoding BSON types to Extended JSON. Defaults to :const:`~JSONMode.LEGACY`. :param document_class: BSON documents returned by :func:`loads` will be decoded to an instance of this class. Must be a subclass of :class:`collections.MutableMapping`. Defaults to :class:`dict`. :param uuid_representation: The :class:`~bson.binary.UuidRepresentation` to use when encoding and decoding instances of :class:`uuid.UUID`. Defaults to :const:`~bson.binary.UuidRepresentation.UNSPECIFIED`. :param tz_aware: If ``True``, MongoDB Extended JSON's *Strict mode* type `Date` will be decoded to timezone aware instances of :class:`datetime.datetime`. Otherwise they will be naive. Defaults to ``False``. :param tzinfo: A :class:`datetime.tzinfo` subclass that specifies the timezone from which :class:`~datetime.datetime` objects should be decoded. Defaults to :const:`~bson.tz_util.utc`. :param datetime_conversion: Specifies how UTC datetimes should be decoded within BSON. Valid options include 'datetime_ms' to return as a DatetimeMS, 'datetime' to return as a datetime.datetime and raising a ValueError for out-of-range values, 'datetime_auto' to return DatetimeMS objects when the underlying datetime is out-of-range and 'datetime_clamp' to clamp to the minimum and maximum possible datetimes. Defaults to 'datetime'. See :ref:`handling-out-of-range-datetimes` for details. :param args: arguments to :class:`~bson.codec_options.CodecOptions` :param kwargs: arguments to :class:`~bson.codec_options.CodecOptions` .. seealso:: The specification for Relaxed and Canonical `Extended JSON`_. .. versionchanged:: 4.0 The default for `json_mode` was changed from :const:`JSONMode.LEGACY` to :const:`JSONMode.RELAXED`. The default for `uuid_representation` was changed from :const:`~bson.binary.UuidRepresentation.PYTHON_LEGACY` to :const:`~bson.binary.UuidRepresentation.UNSPECIFIED`. .. versionchanged:: 3.5 Accepts the optional parameter `json_mode`. .. versionchanged:: 4.0 Changed default value of `tz_aware` to False. """ super().__init__() def __new__( cls: Type[JSONOptions], strict_number_long: Optional[bool] = None, datetime_representation: Optional[int] = None, strict_uuid: Optional[bool] = None, json_mode: int = JSONMode.RELAXED, *args: Any, **kwargs: Any, ) -> JSONOptions: kwargs["tz_aware"] = kwargs.get("tz_aware", False) if kwargs["tz_aware"]: kwargs["tzinfo"] = kwargs.get("tzinfo", utc) if datetime_representation not in ( DatetimeRepresentation.LEGACY, DatetimeRepresentation.NUMBERLONG, DatetimeRepresentation.ISO8601, None, ): raise ValueError( "JSONOptions.datetime_representation must be one of LEGACY, " "NUMBERLONG, or ISO8601 from DatetimeRepresentation." ) self = cast(JSONOptions, super().__new__(cls, *args, **kwargs)) # type:ignore[arg-type] if json_mode not in (JSONMode.LEGACY, JSONMode.RELAXED, JSONMode.CANONICAL): raise ValueError( "JSONOptions.json_mode must be one of LEGACY, RELAXED, " "or CANONICAL from JSONMode." ) self.json_mode = json_mode if self.json_mode == JSONMode.RELAXED: if strict_number_long: raise ValueError("Cannot specify strict_number_long=True with JSONMode.RELAXED") if datetime_representation not in (None, DatetimeRepresentation.ISO8601): raise ValueError( "datetime_representation must be DatetimeRepresentation." "ISO8601 or omitted with JSONMode.RELAXED" ) if strict_uuid not in (None, True): raise ValueError("Cannot specify strict_uuid=False with JSONMode.RELAXED") self.strict_number_long = False self.datetime_representation = DatetimeRepresentation.ISO8601 self.strict_uuid = True elif self.json_mode == JSONMode.CANONICAL: if strict_number_long not in (None, True): raise ValueError("Cannot specify strict_number_long=False with JSONMode.RELAXED") if datetime_representation not in (None, DatetimeRepresentation.NUMBERLONG): raise ValueError( "datetime_representation must be DatetimeRepresentation." "NUMBERLONG or omitted with JSONMode.RELAXED" ) if strict_uuid not in (None, True): raise ValueError("Cannot specify strict_uuid=False with JSONMode.RELAXED") self.strict_number_long = True self.datetime_representation = DatetimeRepresentation.NUMBERLONG self.strict_uuid = True else: # JSONMode.LEGACY self.strict_number_long = False self.datetime_representation = DatetimeRepresentation.LEGACY self.strict_uuid = False if strict_number_long is not None: self.strict_number_long = strict_number_long if datetime_representation is not None: self.datetime_representation = datetime_representation if strict_uuid is not None: self.strict_uuid = strict_uuid return self def _arguments_repr(self) -> str: return ( "strict_number_long={!r}, " "datetime_representation={!r}, " "strict_uuid={!r}, json_mode={!r}, {}".format( self.strict_number_long, self.datetime_representation, self.strict_uuid, self.json_mode, super()._arguments_repr(), ) ) def _options_dict(self) -> dict[Any, Any]: # TODO: PYTHON-2442 use _asdict() instead options_dict = super()._options_dict() options_dict.update( { "strict_number_long": self.strict_number_long, "datetime_representation": self.datetime_representation, "strict_uuid": self.strict_uuid, "json_mode": self.json_mode, } ) return options_dict def with_options(self, **kwargs: Any) -> JSONOptions: """ Make a copy of this JSONOptions, overriding some options:: >>> from bson.json_util import CANONICAL_JSON_OPTIONS >>> CANONICAL_JSON_OPTIONS.tz_aware True >>> json_options = CANONICAL_JSON_OPTIONS.with_options(tz_aware=False, tzinfo=None) >>> json_options.tz_aware False .. versionadded:: 3.12 """ opts = self._options_dict() for opt in ("strict_number_long", "datetime_representation", "strict_uuid", "json_mode"): opts[opt] = kwargs.get(opt, getattr(self, opt)) opts.update(kwargs) return JSONOptions(**opts) LEGACY_JSON_OPTIONS: JSONOptions = JSONOptions(json_mode=JSONMode.LEGACY) """:class:`JSONOptions` for encoding to PyMongo's legacy JSON format. .. seealso:: The documentation for :const:`bson.json_util.JSONMode.LEGACY`. .. versionadded:: 3.5 """ CANONICAL_JSON_OPTIONS: JSONOptions = JSONOptions(json_mode=JSONMode.CANONICAL) """:class:`JSONOptions` for Canonical Extended JSON. .. seealso:: The documentation for :const:`bson.json_util.JSONMode.CANONICAL`. .. versionadded:: 3.5 """ RELAXED_JSON_OPTIONS: JSONOptions = JSONOptions(json_mode=JSONMode.RELAXED) """:class:`JSONOptions` for Relaxed Extended JSON. .. seealso:: The documentation for :const:`bson.json_util.JSONMode.RELAXED`. .. versionadded:: 3.5 """ DEFAULT_JSON_OPTIONS: JSONOptions = RELAXED_JSON_OPTIONS """The default :class:`JSONOptions` for JSON encoding/decoding. The same as :const:`RELAXED_JSON_OPTIONS`. .. versionchanged:: 4.0 Changed from :const:`LEGACY_JSON_OPTIONS` to :const:`RELAXED_JSON_OPTIONS`. .. versionadded:: 3.4 """ def dumps(obj: Any, *args: Any, **kwargs: Any) -> str: """Helper function that wraps :func:`json.dumps`. Recursive function that handles all BSON types including :class:`~bson.binary.Binary` and :class:`~bson.code.Code`. :param json_options: A :class:`JSONOptions` instance used to modify the encoding of MongoDB Extended JSON types. Defaults to :const:`DEFAULT_JSON_OPTIONS`. .. versionchanged:: 4.0 Now outputs MongoDB Relaxed Extended JSON by default (using :const:`DEFAULT_JSON_OPTIONS`). .. versionchanged:: 3.4 Accepts optional parameter `json_options`. See :class:`JSONOptions`. """ json_options = kwargs.pop("json_options", DEFAULT_JSON_OPTIONS) return json.dumps(_json_convert(obj, json_options), *args, **kwargs) def loads(s: Union[str, bytes, bytearray], *args: Any, **kwargs: Any) -> Any: """Helper function that wraps :func:`json.loads`. Automatically passes the object_hook for BSON type conversion. Raises ``TypeError``, ``ValueError``, ``KeyError``, or :exc:`~bson.errors.InvalidId` on invalid MongoDB Extended JSON. :param json_options: A :class:`JSONOptions` instance used to modify the decoding of MongoDB Extended JSON types. Defaults to :const:`DEFAULT_JSON_OPTIONS`. .. versionchanged:: 4.0 Now loads :class:`datetime.datetime` instances as naive by default. To load timezone aware instances utilize the `json_options` parameter. See :ref:`tz_aware_default_change` for an example. .. versionchanged:: 3.5 Parses Relaxed and Canonical Extended JSON as well as PyMongo's legacy format. Now raises ``TypeError`` or ``ValueError`` when parsing JSON type wrappers with values of the wrong type or any extra keys. .. versionchanged:: 3.4 Accepts optional parameter `json_options`. See :class:`JSONOptions`. """ json_options = kwargs.pop("json_options", DEFAULT_JSON_OPTIONS) # Execution time optimization if json_options.document_class is dict if json_options.document_class is dict: kwargs["object_hook"] = lambda obj: object_hook(obj, json_options) else: kwargs["object_pairs_hook"] = lambda pairs: object_pairs_hook(pairs, json_options) return json.loads(s, *args, **kwargs) def _json_convert(obj: Any, json_options: JSONOptions = DEFAULT_JSON_OPTIONS) -> Any: """Recursive helper method that converts BSON types so they can be converted into json. """ if hasattr(obj, "items"): return {k: _json_convert(v, json_options) for k, v in obj.items()} elif hasattr(obj, "__iter__") and not isinstance(obj, (str, bytes)): return [_json_convert(v, json_options) for v in obj] try: return default(obj, json_options) except TypeError: return obj def object_pairs_hook( pairs: Sequence[Tuple[str, Any]], json_options: JSONOptions = DEFAULT_JSON_OPTIONS ) -> Any: return object_hook(json_options.document_class(pairs), json_options) # type:ignore[call-arg] def object_hook(dct: Mapping[str, Any], json_options: JSONOptions = DEFAULT_JSON_OPTIONS) -> Any: match = None for k in dct: if k in _PARSERS_SET: match = k break if match: return _PARSERS[match](dct, json_options) return dct def _parse_legacy_regex(doc: Any, dummy0: Any) -> Any: pattern = doc["$regex"] # Check if this is the $regex query operator. if not isinstance(pattern, (str, bytes)): return doc flags = 0 # PyMongo always adds $options but some other tools may not. for opt in doc.get("$options", ""): flags |= _RE_OPT_TABLE.get(opt, 0) return Regex(pattern, flags) def _parse_legacy_uuid(doc: Any, json_options: JSONOptions) -> Union[Binary, uuid.UUID]: """Decode a JSON legacy $uuid to Python UUID.""" if len(doc) != 1: raise TypeError(f"Bad $uuid, extra field(s): {doc}") if not isinstance(doc["$uuid"], str): raise TypeError(f"$uuid must be a string: {doc}") if json_options.uuid_representation == UuidRepresentation.UNSPECIFIED: return Binary.from_uuid(uuid.UUID(doc["$uuid"])) else: return uuid.UUID(doc["$uuid"]) def _binary_or_uuid(data: Any, subtype: int, json_options: JSONOptions) -> Union[Binary, uuid.UUID]: # special handling for UUID if subtype in ALL_UUID_SUBTYPES: uuid_representation = json_options.uuid_representation binary_value = Binary(data, subtype) if uuid_representation == UuidRepresentation.UNSPECIFIED: return binary_value if subtype == UUID_SUBTYPE: # Legacy behavior: use STANDARD with binary subtype 4. uuid_representation = UuidRepresentation.STANDARD elif uuid_representation == UuidRepresentation.STANDARD: # subtype == OLD_UUID_SUBTYPE # Legacy behavior: STANDARD is the same as PYTHON_LEGACY. uuid_representation = UuidRepresentation.PYTHON_LEGACY return binary_value.as_uuid(uuid_representation) if subtype == 0: return cast(uuid.UUID, data) return Binary(data, subtype) def _parse_legacy_binary(doc: Any, json_options: JSONOptions) -> Union[Binary, uuid.UUID]: if isinstance(doc["$type"], int): doc["$type"] = "%02x" % doc["$type"] subtype = int(doc["$type"], 16) if subtype >= 0xFFFFFF80: # Handle mongoexport values subtype = int(doc["$type"][6:], 16) data = base64.b64decode(doc["$binary"].encode()) return _binary_or_uuid(data, subtype, json_options) def _parse_canonical_binary(doc: Any, json_options: JSONOptions) -> Union[Binary, uuid.UUID]: binary = doc["$binary"] b64 = binary["base64"] subtype = binary["subType"] if not isinstance(b64, str): raise TypeError(f"$binary base64 must be a string: {doc}") if not isinstance(subtype, str) or len(subtype) > 2: raise TypeError(f"$binary subType must be a string at most 2 characters: {doc}") if len(binary) != 2: raise TypeError(f'$binary must include only "base64" and "subType" components: {doc}') data = base64.b64decode(b64.encode()) return _binary_or_uuid(data, int(subtype, 16), json_options) def _parse_canonical_datetime( doc: Any, json_options: JSONOptions ) -> Union[datetime.datetime, DatetimeMS]: """Decode a JSON datetime to python datetime.datetime.""" dtm = doc["$date"] if len(doc) != 1: raise TypeError(f"Bad $date, extra field(s): {doc}") # mongoexport 2.6 and newer if isinstance(dtm, str): # Parse offset if dtm[-1] == "Z": dt = dtm[:-1] offset = "Z" elif dtm[-6] in ("+", "-") and dtm[-3] == ":": # (+|-)HH:MM dt = dtm[:-6] offset = dtm[-6:] elif dtm[-5] in ("+", "-"): # (+|-)HHMM dt = dtm[:-5] offset = dtm[-5:] elif dtm[-3] in ("+", "-"): # (+|-)HH dt = dtm[:-3] offset = dtm[-3:] else: dt = dtm offset = "" # Parse the optional factional seconds portion. dot_index = dt.rfind(".") microsecond = 0 if dot_index != -1: microsecond = int(float(dt[dot_index:]) * 1000000) dt = dt[:dot_index] aware = datetime.datetime.strptime(dt, "%Y-%m-%dT%H:%M:%S").replace( microsecond=microsecond, tzinfo=utc ) if offset and offset != "Z": if len(offset) == 6: hours, minutes = offset[1:].split(":") secs = int(hours) * 3600 + int(minutes) * 60 elif len(offset) == 5: secs = int(offset[1:3]) * 3600 + int(offset[3:]) * 60 elif len(offset) == 3: secs = int(offset[1:3]) * 3600 if offset[0] == "-": secs *= -1 aware = aware - datetime.timedelta(seconds=secs) if json_options.tz_aware: if json_options.tzinfo: aware = aware.astimezone(json_options.tzinfo) if json_options.datetime_conversion == DatetimeConversion.DATETIME_MS: return DatetimeMS(aware) return aware else: aware_tzinfo_none = aware.replace(tzinfo=None) if json_options.datetime_conversion == DatetimeConversion.DATETIME_MS: return DatetimeMS(aware_tzinfo_none) return aware_tzinfo_none return _millis_to_datetime(int(dtm), cast("CodecOptions[Any]", json_options)) def _parse_canonical_oid(doc: Any, dummy0: Any) -> ObjectId: """Decode a JSON ObjectId to bson.objectid.ObjectId.""" if len(doc) != 1: raise TypeError(f"Bad $oid, extra field(s): {doc}") return ObjectId(doc["$oid"]) def _parse_canonical_symbol(doc: Any, dummy0: Any) -> str: """Decode a JSON symbol to Python string.""" symbol = doc["$symbol"] if len(doc) != 1: raise TypeError(f"Bad $symbol, extra field(s): {doc}") return str(symbol) def _parse_canonical_code(doc: Any, dummy0: Any) -> Code: """Decode a JSON code to bson.code.Code.""" for key in doc: if key not in ("$code", "$scope"): raise TypeError(f"Bad $code, extra field(s): {doc}") return Code(doc["$code"], scope=doc.get("$scope")) def _parse_canonical_regex(doc: Any, dummy0: Any) -> Regex[str]: """Decode a JSON regex to bson.regex.Regex.""" regex = doc["$regularExpression"] if len(doc) != 1: raise TypeError(f"Bad $regularExpression, extra field(s): {doc}") if len(regex) != 2: raise TypeError( f'Bad $regularExpression must include only "pattern and "options" components: {doc}' ) opts = regex["options"] if not isinstance(opts, str): raise TypeError( "Bad $regularExpression options, options must be string, was type %s" % (type(opts)) ) return Regex(regex["pattern"], opts) def _parse_canonical_dbref(doc: Any, dummy0: Any) -> Any: """Decode a JSON DBRef to bson.dbref.DBRef.""" if ( isinstance(doc.get("$ref"), str) and "$id" in doc and isinstance(doc.get("$db"), (str, type(None))) ): return DBRef(doc.pop("$ref"), doc.pop("$id"), database=doc.pop("$db", None), **doc) return doc def _parse_canonical_dbpointer(doc: Any, dummy0: Any) -> Any: """Decode a JSON (deprecated) DBPointer to bson.dbref.DBRef.""" dbref = doc["$dbPointer"] if len(doc) != 1: raise TypeError(f"Bad $dbPointer, extra field(s): {doc}") if isinstance(dbref, DBRef): dbref_doc = dbref.as_doc() # DBPointer must not contain $db in its value. if dbref.database is not None: raise TypeError(f"Bad $dbPointer, extra field $db: {dbref_doc}") if not isinstance(dbref.id, ObjectId): raise TypeError(f"Bad $dbPointer, $id must be an ObjectId: {dbref_doc}") if len(dbref_doc) != 2: raise TypeError(f"Bad $dbPointer, extra field(s) in DBRef: {dbref_doc}") return dbref else: raise TypeError(f"Bad $dbPointer, expected a DBRef: {doc}") def _parse_canonical_int32(doc: Any, dummy0: Any) -> int: """Decode a JSON int32 to python int.""" i_str = doc["$numberInt"] if len(doc) != 1: raise TypeError(f"Bad $numberInt, extra field(s): {doc}") if not isinstance(i_str, str): raise TypeError(f"$numberInt must be string: {doc}") return int(i_str) def _parse_canonical_int64(doc: Any, dummy0: Any) -> Int64: """Decode a JSON int64 to bson.int64.Int64.""" l_str = doc["$numberLong"] if len(doc) != 1: raise TypeError(f"Bad $numberLong, extra field(s): {doc}") return Int64(l_str) def _parse_canonical_double(doc: Any, dummy0: Any) -> float: """Decode a JSON double to python float.""" d_str = doc["$numberDouble"] if len(doc) != 1: raise TypeError(f"Bad $numberDouble, extra field(s): {doc}") if not isinstance(d_str, str): raise TypeError(f"$numberDouble must be string: {doc}") return float(d_str) def _parse_canonical_decimal128(doc: Any, dummy0: Any) -> Decimal128: """Decode a JSON decimal128 to bson.decimal128.Decimal128.""" d_str = doc["$numberDecimal"] if len(doc) != 1: raise TypeError(f"Bad $numberDecimal, extra field(s): {doc}") if not isinstance(d_str, str): raise TypeError(f"$numberDecimal must be string: {doc}") return Decimal128(d_str) def _parse_canonical_minkey(doc: Any, dummy0: Any) -> MinKey: """Decode a JSON MinKey to bson.min_key.MinKey.""" if type(doc["$minKey"]) is not int or doc["$minKey"] != 1: # noqa: E721 raise TypeError(f"$minKey value must be 1: {doc}") if len(doc) != 1: raise TypeError(f"Bad $minKey, extra field(s): {doc}") return MinKey() def _parse_canonical_maxkey(doc: Any, dummy0: Any) -> MaxKey: """Decode a JSON MaxKey to bson.max_key.MaxKey.""" if type(doc["$maxKey"]) is not int or doc["$maxKey"] != 1: # noqa: E721 raise TypeError("$maxKey value must be 1: %s", (doc,)) if len(doc) != 1: raise TypeError(f"Bad $minKey, extra field(s): {doc}") return MaxKey() def _parse_binary(doc: Any, json_options: JSONOptions) -> Union[Binary, uuid.UUID]: if "$type" in doc: return _parse_legacy_binary(doc, json_options) else: return _parse_canonical_binary(doc, json_options) def _parse_timestamp(doc: Any, dummy0: Any) -> Timestamp: tsp = doc["$timestamp"] return Timestamp(tsp["t"], tsp["i"]) _PARSERS: dict[str, Callable[[Any, JSONOptions], Any]] = { "$oid": _parse_canonical_oid, "$ref": _parse_canonical_dbref, "$date": _parse_canonical_datetime, "$regex": _parse_legacy_regex, "$minKey": _parse_canonical_minkey, "$maxKey": _parse_canonical_maxkey, "$binary": _parse_binary, "$code": _parse_canonical_code, "$uuid": _parse_legacy_uuid, "$undefined": lambda _, _1: None, "$numberLong": _parse_canonical_int64, "$timestamp": _parse_timestamp, "$numberDecimal": _parse_canonical_decimal128, "$dbPointer": _parse_canonical_dbpointer, "$regularExpression": _parse_canonical_regex, "$symbol": _parse_canonical_symbol, "$numberInt": _parse_canonical_int32, "$numberDouble": _parse_canonical_double, } _PARSERS_SET = set(_PARSERS) def _encode_binary(data: bytes, subtype: int, json_options: JSONOptions) -> Any: if json_options.json_mode == JSONMode.LEGACY: return {"$binary": base64.b64encode(data).decode(), "$type": "%02x" % subtype} return {"$binary": {"base64": base64.b64encode(data).decode(), "subType": "%02x" % subtype}} def _encode_datetimems(obj: Any, json_options: JSONOptions) -> dict: if ( json_options.datetime_representation == DatetimeRepresentation.ISO8601 and 0 <= int(obj) <= _max_datetime_ms() ): return _encode_datetime(obj.as_datetime(), json_options) elif json_options.datetime_representation == DatetimeRepresentation.LEGACY: return {"$date": str(int(obj))} return {"$date": {"$numberLong": str(int(obj))}} def _encode_code(obj: Code, json_options: JSONOptions) -> dict: if obj.scope is None: return {"$code": str(obj)} else: return {"$code": str(obj), "$scope": _json_convert(obj.scope, json_options)} def _encode_int64(obj: Int64, json_options: JSONOptions) -> Any: if json_options.strict_number_long: return {"$numberLong": str(obj)} else: return int(obj) def _encode_noop(obj: Any, dummy0: Any) -> Any: return obj def _encode_regex(obj: Any, json_options: JSONOptions) -> dict: flags = "" if obj.flags & re.IGNORECASE: flags += "i" if obj.flags & re.LOCALE: flags += "l" if obj.flags & re.MULTILINE: flags += "m" if obj.flags & re.DOTALL: flags += "s" if obj.flags & re.UNICODE: flags += "u" if obj.flags & re.VERBOSE: flags += "x" if isinstance(obj.pattern, str): pattern = obj.pattern else: pattern = obj.pattern.decode("utf-8") if json_options.json_mode == JSONMode.LEGACY: return {"$regex": pattern, "$options": flags} return {"$regularExpression": {"pattern": pattern, "options": flags}} def _encode_int(obj: int, json_options: JSONOptions) -> Any: if json_options.json_mode == JSONMode.CANONICAL: if -_INT32_MAX <= obj < _INT32_MAX: return {"$numberInt": str(obj)} return {"$numberLong": str(obj)} return obj def _encode_float(obj: float, json_options: JSONOptions) -> Any: if json_options.json_mode != JSONMode.LEGACY: if math.isnan(obj): return {"$numberDouble": "NaN"} elif math.isinf(obj): representation = "Infinity" if obj > 0 else "-Infinity" return {"$numberDouble": representation} elif json_options.json_mode == JSONMode.CANONICAL: # repr() will return the shortest string guaranteed to produce the # original value, when float() is called on it. return {"$numberDouble": str(repr(obj))} return obj def _encode_datetime(obj: datetime.datetime, json_options: JSONOptions) -> dict: if json_options.datetime_representation == DatetimeRepresentation.ISO8601: if not obj.tzinfo: obj = obj.replace(tzinfo=utc) assert obj.tzinfo is not None if obj >= EPOCH_AWARE: off = obj.tzinfo.utcoffset(obj) if (off.days, off.seconds, off.microseconds) == (0, 0, 0): # type: ignore tz_string = "Z" else: tz_string = obj.strftime("%z") millis = int(obj.microsecond / 1000) fracsecs = ".%03d" % (millis,) if millis else "" return { "$date": "{}{}{}".format(obj.strftime("%Y-%m-%dT%H:%M:%S"), fracsecs, tz_string) } millis = _datetime_to_millis(obj) if json_options.datetime_representation == DatetimeRepresentation.LEGACY: return {"$date": millis} return {"$date": {"$numberLong": str(millis)}} def _encode_bytes(obj: bytes, json_options: JSONOptions) -> dict: return _encode_binary(obj, 0, json_options) def _encode_binary_obj(obj: Binary, json_options: JSONOptions) -> dict: return _encode_binary(obj, obj.subtype, json_options) def _encode_uuid(obj: uuid.UUID, json_options: JSONOptions) -> dict: if json_options.strict_uuid: binval = Binary.from_uuid(obj, uuid_representation=json_options.uuid_representation) return _encode_binary(binval, binval.subtype, json_options) else: return {"$uuid": obj.hex} def _encode_objectid(obj: ObjectId, dummy0: Any) -> dict: return {"$oid": str(obj)} def _encode_timestamp(obj: Timestamp, dummy0: Any) -> dict: return {"$timestamp": {"t": obj.time, "i": obj.inc}} def _encode_decimal128(obj: Timestamp, dummy0: Any) -> dict: return {"$numberDecimal": str(obj)} def _encode_dbref(obj: DBRef, json_options: JSONOptions) -> dict: return _json_convert(obj.as_doc(), json_options=json_options) def _encode_minkey(dummy0: Any, dummy1: Any) -> dict: return {"$minKey": 1} def _encode_maxkey(dummy0: Any, dummy1: Any) -> dict: return {"$maxKey": 1} # Encoders for BSON types # Each encoder function's signature is: # - obj: a Python data type, e.g. a Python int for _encode_int # - json_options: a JSONOptions _ENCODERS: dict[Type, Callable[[Any, JSONOptions], Any]] = { bool: _encode_noop, bytes: _encode_bytes, datetime.datetime: _encode_datetime, DatetimeMS: _encode_datetimems, float: _encode_float, int: _encode_int, str: _encode_noop, type(None): _encode_noop, uuid.UUID: _encode_uuid, Binary: _encode_binary_obj, Int64: _encode_int64, Code: _encode_code, DBRef: _encode_dbref, MaxKey: _encode_maxkey, MinKey: _encode_minkey, ObjectId: _encode_objectid, Regex: _encode_regex, RE_TYPE: _encode_regex, Timestamp: _encode_timestamp, Decimal128: _encode_decimal128, } # Map each _type_marker to its encoder for faster lookup. _MARKERS: dict[int, Callable[[Any, JSONOptions], Any]] = {} for _typ in _ENCODERS: if hasattr(_typ, "_type_marker"): _MARKERS[_typ._type_marker] = _ENCODERS[_typ] _BUILT_IN_TYPES = tuple(t for t in _ENCODERS) def default(obj: Any, json_options: JSONOptions = DEFAULT_JSON_OPTIONS) -> Any: # First see if the type is already cached. KeyError will only ever # happen once per subtype. try: return _ENCODERS[type(obj)](obj, json_options) except KeyError: pass # Second, fall back to trying _type_marker. This has to be done # before the loop below since users could subclass one of our # custom types that subclasses a python built-in (e.g. Binary) if hasattr(obj, "_type_marker"): marker = obj._type_marker if marker in _MARKERS: func = _MARKERS[marker] # Cache this type for faster subsequent lookup. _ENCODERS[type(obj)] = func return func(obj, json_options) # Third, test each base type. This will only happen once for # a subtype of a supported base type. for base in _BUILT_IN_TYPES: if isinstance(obj, base): func = _ENCODERS[base] # Cache this type for faster subsequent lookup. _ENCODERS[type(obj)] = func return func(obj, json_options) raise TypeError("%r is not JSON serializable" % obj) def _get_str_size(obj: Any) -> int: return len(obj) def _get_datetime_size(obj: datetime.datetime) -> int: return 5 + len(str(obj.time())) def _get_regex_size(obj: Regex) -> int: return 18 + len(obj.pattern) def _get_dbref_size(obj: DBRef) -> int: return 34 + len(obj.collection) _CONSTANT_SIZE_TABLE: dict[Any, int] = { ObjectId: 28, int: 11, Int64: 11, Decimal128: 11, Timestamp: 14, MinKey: 8, MaxKey: 8, } _VARIABLE_SIZE_TABLE: dict[Any, Callable[[Any], int]] = { str: _get_str_size, bytes: _get_str_size, datetime.datetime: _get_datetime_size, Regex: _get_regex_size, DBRef: _get_dbref_size, } def get_size(obj: Any, max_size: int, current_size: int = 0) -> int: """Recursively finds size of objects""" if current_size >= max_size: return current_size obj_type = type(obj) # Check to see if the obj has a constant size estimate try: return _CONSTANT_SIZE_TABLE[obj_type] except KeyError: pass # Check to see if the obj has a variable but simple size estimate try: return _VARIABLE_SIZE_TABLE[obj_type](obj) except KeyError: pass # Special cases that require recursion if obj_type == Code: if obj.scope: current_size += ( 5 + get_size(obj.scope, max_size, current_size) + len(obj) - len(obj.scope) ) else: current_size += 5 + len(obj) elif obj_type == dict: for k, v in obj.items(): current_size += get_size(k, max_size, current_size) current_size += get_size(v, max_size, current_size) if current_size >= max_size: return current_size elif hasattr(obj, "__iter__"): for i in obj: current_size += get_size(i, max_size, current_size) if current_size >= max_size: return current_size return current_size def _truncate_documents(obj: Any, max_length: int) -> Tuple[Any, int]: """Recursively truncate documents as needed to fit inside max_length characters.""" if max_length <= 0: return None, 0 remaining = max_length if hasattr(obj, "items"): truncated: Any = {} for k, v in obj.items(): truncated_v, remaining = _truncate_documents(v, remaining) if truncated_v: truncated[k] = truncated_v if remaining <= 0: break return truncated, remaining elif hasattr(obj, "__iter__") and not isinstance(obj, (str, bytes)): truncated: Any = [] # type:ignore[no-redef] for v in obj: truncated_v, remaining = _truncate_documents(v, remaining) if truncated_v: truncated.append(truncated_v) if remaining <= 0: break return truncated, remaining else: return _truncate(obj, remaining) def _truncate(obj: Any, remaining: int) -> Tuple[Any, int]: size = get_size(obj, remaining) if size <= remaining: return obj, remaining - size else: try: truncated = obj[:remaining] except TypeError: truncated = obj return truncated, remaining - size mongodb-mongo-python-driver-509e9b7/bson/max_key.py000066400000000000000000000027401462766011000224100ustar00rootroot00000000000000# Copyright 2010-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. """Representation for the MongoDB internal MaxKey type.""" from __future__ import annotations from typing import Any class MaxKey: """MongoDB internal MaxKey type.""" __slots__ = () _type_marker = 127 def __getstate__(self) -> Any: return {} def __setstate__(self, state: Any) -> None: pass def __eq__(self, other: Any) -> bool: return isinstance(other, MaxKey) def __hash__(self) -> int: return hash(self._type_marker) def __ne__(self, other: Any) -> bool: return not self == other def __le__(self, other: Any) -> bool: return isinstance(other, MaxKey) def __lt__(self, dummy: Any) -> bool: return False def __ge__(self, dummy: Any) -> bool: return True def __gt__(self, other: Any) -> bool: return not isinstance(other, MaxKey) def __repr__(self) -> str: return "MaxKey()" mongodb-mongo-python-driver-509e9b7/bson/min_key.py000066400000000000000000000027401462766011000224060ustar00rootroot00000000000000# Copyright 2010-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. """Representation for the MongoDB internal MinKey type.""" from __future__ import annotations from typing import Any class MinKey: """MongoDB internal MinKey type.""" __slots__ = () _type_marker = 255 def __getstate__(self) -> Any: return {} def __setstate__(self, state: Any) -> None: pass def __eq__(self, other: Any) -> bool: return isinstance(other, MinKey) def __hash__(self) -> int: return hash(self._type_marker) def __ne__(self, other: Any) -> bool: return not self == other def __le__(self, dummy: Any) -> bool: return True def __lt__(self, other: Any) -> bool: return not isinstance(other, MinKey) def __ge__(self, other: Any) -> bool: return isinstance(other, MinKey) def __gt__(self, dummy: Any) -> bool: return False def __repr__(self) -> str: return "MinKey()" mongodb-mongo-python-driver-509e9b7/bson/objectid.py000066400000000000000000000216651462766011000225450ustar00rootroot00000000000000# Copyright 2009-2015 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. """Tools for working with MongoDB ObjectIds.""" from __future__ import annotations import binascii import calendar import datetime import os import struct import threading import time from random import SystemRandom from typing import Any, NoReturn, Optional, Type, Union from bson.errors import InvalidId from bson.tz_util import utc _MAX_COUNTER_VALUE = 0xFFFFFF def _raise_invalid_id(oid: str) -> NoReturn: raise InvalidId( "%r is not a valid ObjectId, it must be a 12-byte input" " or a 24-character hex string" % oid ) def _random_bytes() -> bytes: """Get the 5-byte random field of an ObjectId.""" return os.urandom(5) class ObjectId: """A MongoDB ObjectId.""" _pid = os.getpid() _inc = SystemRandom().randint(0, _MAX_COUNTER_VALUE) _inc_lock = threading.Lock() __random = _random_bytes() __slots__ = ("__id",) _type_marker = 7 def __init__(self, oid: Optional[Union[str, ObjectId, bytes]] = None) -> None: """Initialize a new ObjectId. An ObjectId is a 12-byte unique identifier consisting of: - a 4-byte value representing the seconds since the Unix epoch, - a 5-byte random value, - a 3-byte counter, starting with a random value. By default, ``ObjectId()`` creates a new unique identifier. The optional parameter `oid` can be an :class:`ObjectId`, or any 12 :class:`bytes`. For example, the 12 bytes b'foo-bar-quux' do not follow the ObjectId specification but they are acceptable input:: >>> ObjectId(b'foo-bar-quux') ObjectId('666f6f2d6261722d71757578') `oid` can also be a :class:`str` of 24 hex digits:: >>> ObjectId('0123456789ab0123456789ab') ObjectId('0123456789ab0123456789ab') Raises :class:`~bson.errors.InvalidId` if `oid` is not 12 bytes nor 24 hex digits, or :class:`TypeError` if `oid` is not an accepted type. :param oid: a valid ObjectId. .. seealso:: The MongoDB documentation on `ObjectIds `_. .. versionchanged:: 3.8 :class:`~bson.objectid.ObjectId` now implements the `ObjectID specification version 0.2 `_. """ if oid is None: self.__generate() elif isinstance(oid, bytes) and len(oid) == 12: self.__id = oid else: self.__validate(oid) @classmethod def from_datetime(cls: Type[ObjectId], generation_time: datetime.datetime) -> ObjectId: """Create a dummy ObjectId instance with a specific generation time. This method is useful for doing range queries on a field containing :class:`ObjectId` instances. .. warning:: It is not safe to insert a document containing an ObjectId generated using this method. This method deliberately eliminates the uniqueness guarantee that ObjectIds generally provide. ObjectIds generated with this method should be used exclusively in queries. `generation_time` will be converted to UTC. Naive datetime instances will be treated as though they already contain UTC. An example using this helper to get documents where ``"_id"`` was generated before January 1, 2010 would be: >>> gen_time = datetime.datetime(2010, 1, 1) >>> dummy_id = ObjectId.from_datetime(gen_time) >>> result = collection.find({"_id": {"$lt": dummy_id}}) :param generation_time: :class:`~datetime.datetime` to be used as the generation time for the resulting ObjectId. """ offset = generation_time.utcoffset() if offset is not None: generation_time = generation_time - offset timestamp = calendar.timegm(generation_time.timetuple()) oid = struct.pack(">I", int(timestamp)) + b"\x00\x00\x00\x00\x00\x00\x00\x00" return cls(oid) @classmethod def is_valid(cls: Type[ObjectId], oid: Any) -> bool: """Checks if a `oid` string is valid or not. :param oid: the object id to validate .. versionadded:: 2.3 """ if not oid: return False try: ObjectId(oid) return True except (InvalidId, TypeError): return False @classmethod def _random(cls) -> bytes: """Generate a 5-byte random number once per process.""" pid = os.getpid() if pid != cls._pid: cls._pid = pid cls.__random = _random_bytes() return cls.__random def __generate(self) -> None: """Generate a new value for this ObjectId.""" # 4 bytes current time oid = struct.pack(">I", int(time.time())) # 5 bytes random oid += ObjectId._random() # 3 bytes inc with ObjectId._inc_lock: oid += struct.pack(">I", ObjectId._inc)[1:4] ObjectId._inc = (ObjectId._inc + 1) % (_MAX_COUNTER_VALUE + 1) self.__id = oid def __validate(self, oid: Any) -> None: """Validate and use the given id for this ObjectId. Raises TypeError if id is not an instance of :class:`str`, :class:`bytes`, or ObjectId. Raises InvalidId if it is not a valid ObjectId. :param oid: a valid ObjectId """ if isinstance(oid, ObjectId): self.__id = oid.binary elif isinstance(oid, str): if len(oid) == 24: try: self.__id = bytes.fromhex(oid) except (TypeError, ValueError): _raise_invalid_id(oid) else: _raise_invalid_id(oid) else: raise TypeError(f"id must be an instance of (bytes, str, ObjectId), not {type(oid)}") @property def binary(self) -> bytes: """12-byte binary representation of this ObjectId.""" return self.__id @property def generation_time(self) -> datetime.datetime: """A :class:`datetime.datetime` instance representing the time of generation for this :class:`ObjectId`. The :class:`datetime.datetime` is timezone aware, and represents the generation time in UTC. It is precise to the second. """ timestamp = struct.unpack(">I", self.__id[0:4])[0] return datetime.datetime.fromtimestamp(timestamp, utc) def __getstate__(self) -> bytes: """Return value of object for pickling. needed explicitly because __slots__() defined. """ return self.__id def __setstate__(self, value: Any) -> None: """Explicit state set from pickling""" # Provide backwards compatibility with OIDs # pickled with pymongo-1.9 or older. if isinstance(value, dict): oid = value["_ObjectId__id"] else: oid = value # ObjectIds pickled in python 2.x used `str` for __id. # In python 3.x this has to be converted to `bytes` # by encoding latin-1. if isinstance(oid, str): self.__id = oid.encode("latin-1") else: self.__id = oid def __str__(self) -> str: return binascii.hexlify(self.__id).decode() def __repr__(self) -> str: return f"ObjectId('{self!s}')" def __eq__(self, other: Any) -> bool: if isinstance(other, ObjectId): return self.__id == other.binary return NotImplemented def __ne__(self, other: Any) -> bool: if isinstance(other, ObjectId): return self.__id != other.binary return NotImplemented def __lt__(self, other: Any) -> bool: if isinstance(other, ObjectId): return self.__id < other.binary return NotImplemented def __le__(self, other: Any) -> bool: if isinstance(other, ObjectId): return self.__id <= other.binary return NotImplemented def __gt__(self, other: Any) -> bool: if isinstance(other, ObjectId): return self.__id > other.binary return NotImplemented def __ge__(self, other: Any) -> bool: if isinstance(other, ObjectId): return self.__id >= other.binary return NotImplemented def __hash__(self) -> int: """Get a hash value for this :class:`ObjectId`.""" return hash(self.__id) mongodb-mongo-python-driver-509e9b7/bson/py.typed000066400000000000000000000002521462766011000220740ustar00rootroot00000000000000# PEP-561 Support File. # "Package maintainers who wish to support type checking of their code MUST add a marker file named py.typed to their package supporting typing". mongodb-mongo-python-driver-509e9b7/bson/raw_bson.py000066400000000000000000000162051462766011000225660ustar00rootroot00000000000000# Copyright 2015-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. """Tools for representing raw BSON documents. Inserting and Retrieving RawBSONDocuments ========================================= Example: Moving a document between different databases/collections .. doctest:: >>> import bson >>> from pymongo import MongoClient >>> from bson.raw_bson import RawBSONDocument >>> client = MongoClient(document_class=RawBSONDocument) >>> client.drop_database("db") >>> client.drop_database("replica_db") >>> db = client.db >>> result = db.test.insert_many( ... [{"_id": 1, "a": 1}, {"_id": 2, "b": 1}, {"_id": 3, "c": 1}, {"_id": 4, "d": 1}] ... ) >>> replica_db = client.replica_db >>> for doc in db.test.find(): ... print(f"raw document: {doc.raw}") ... print(f"decoded document: {bson.decode(doc.raw)}") ... result = replica_db.test.insert_one(doc) ... raw document: b'...' decoded document: {'_id': 1, 'a': 1} raw document: b'...' decoded document: {'_id': 2, 'b': 1} raw document: b'...' decoded document: {'_id': 3, 'c': 1} raw document: b'...' decoded document: {'_id': 4, 'd': 1} For use cases like moving documents across different databases or writing binary blobs to disk, using raw BSON documents provides better speed and avoids the overhead of decoding or encoding BSON. """ from __future__ import annotations from typing import Any, ItemsView, Iterator, Mapping, Optional from bson import _get_object_size, _raw_to_dict from bson.codec_options import _RAW_BSON_DOCUMENT_MARKER, CodecOptions from bson.codec_options import DEFAULT_CODEC_OPTIONS as DEFAULT def _inflate_bson( bson_bytes: bytes, codec_options: CodecOptions[RawBSONDocument], raw_array: bool = False ) -> dict[str, Any]: """Inflates the top level fields of a BSON document. :param bson_bytes: the BSON bytes that compose this document :param codec_options: An instance of :class:`~bson.codec_options.CodecOptions` whose ``document_class`` must be :class:`RawBSONDocument`. """ return _raw_to_dict(bson_bytes, 4, len(bson_bytes) - 1, codec_options, {}, raw_array=raw_array) class RawBSONDocument(Mapping[str, Any]): """Representation for a MongoDB document that provides access to the raw BSON bytes that compose it. Only when a field is accessed or modified within the document does RawBSONDocument decode its bytes. """ __slots__ = ("__raw", "__inflated_doc", "__codec_options") _type_marker = _RAW_BSON_DOCUMENT_MARKER __codec_options: CodecOptions[RawBSONDocument] def __init__( self, bson_bytes: bytes, codec_options: Optional[CodecOptions[RawBSONDocument]] = None ) -> None: """Create a new :class:`RawBSONDocument` :class:`RawBSONDocument` is a representation of a BSON document that provides access to the underlying raw BSON bytes. Only when a field is accessed or modified within the document does RawBSONDocument decode its bytes. :class:`RawBSONDocument` implements the ``Mapping`` abstract base class from the standard library so it can be used like a read-only ``dict``:: >>> from bson import encode >>> raw_doc = RawBSONDocument(encode({'_id': 'my_doc'})) >>> raw_doc.raw b'...' >>> raw_doc['_id'] 'my_doc' :param bson_bytes: the BSON bytes that compose this document :param codec_options: An instance of :class:`~bson.codec_options.CodecOptions` whose ``document_class`` must be :class:`RawBSONDocument`. The default is :attr:`DEFAULT_RAW_BSON_OPTIONS`. .. versionchanged:: 3.8 :class:`RawBSONDocument` now validates that the ``bson_bytes`` passed in represent a single bson document. .. versionchanged:: 3.5 If a :class:`~bson.codec_options.CodecOptions` is passed in, its `document_class` must be :class:`RawBSONDocument`. """ self.__raw = bson_bytes self.__inflated_doc: Optional[Mapping[str, Any]] = None # Can't default codec_options to DEFAULT_RAW_BSON_OPTIONS in signature, # it refers to this class RawBSONDocument. if codec_options is None: codec_options = DEFAULT_RAW_BSON_OPTIONS elif not issubclass(codec_options.document_class, RawBSONDocument): raise TypeError( "RawBSONDocument cannot use CodecOptions with document " f"class {codec_options.document_class}" ) self.__codec_options = codec_options # Validate the bson object size. _get_object_size(bson_bytes, 0, len(bson_bytes)) @property def raw(self) -> bytes: """The raw BSON bytes composing this document.""" return self.__raw def items(self) -> ItemsView[str, Any]: """Lazily decode and iterate elements in this document.""" return self.__inflated.items() @property def __inflated(self) -> Mapping[str, Any]: if self.__inflated_doc is None: # We already validated the object's size when this document was # created, so no need to do that again. self.__inflated_doc = self._inflate_bson(self.__raw, self.__codec_options) return self.__inflated_doc @staticmethod def _inflate_bson( bson_bytes: bytes, codec_options: CodecOptions[RawBSONDocument] ) -> Mapping[str, Any]: return _inflate_bson(bson_bytes, codec_options) def __getitem__(self, item: str) -> Any: return self.__inflated[item] def __iter__(self) -> Iterator[str]: return iter(self.__inflated) def __len__(self) -> int: return len(self.__inflated) def __eq__(self, other: Any) -> bool: if isinstance(other, RawBSONDocument): return self.__raw == other.raw return NotImplemented def __repr__(self) -> str: return f"{self.__class__.__name__}({self.raw!r}, codec_options={self.__codec_options!r})" class _RawArrayBSONDocument(RawBSONDocument): """A RawBSONDocument that only expands sub-documents and arrays when accessed.""" @staticmethod def _inflate_bson( bson_bytes: bytes, codec_options: CodecOptions[RawBSONDocument] ) -> Mapping[str, Any]: return _inflate_bson(bson_bytes, codec_options, raw_array=True) DEFAULT_RAW_BSON_OPTIONS: CodecOptions[RawBSONDocument] = DEFAULT.with_options( document_class=RawBSONDocument ) _RAW_ARRAY_BSON_OPTIONS: CodecOptions[_RawArrayBSONDocument] = DEFAULT.with_options( document_class=_RawArrayBSONDocument ) """The default :class:`~bson.codec_options.CodecOptions` for :class:`RawBSONDocument`. """ mongodb-mongo-python-driver-509e9b7/bson/regex.py000066400000000000000000000107541462766011000220710ustar00rootroot00000000000000# Copyright 2013-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. """Tools for representing MongoDB regular expressions.""" from __future__ import annotations import re from typing import Any, Generic, Pattern, Type, TypeVar, Union from bson._helpers import _getstate_slots, _setstate_slots from bson.son import RE_TYPE def str_flags_to_int(str_flags: str) -> int: flags = 0 if "i" in str_flags: flags |= re.IGNORECASE if "l" in str_flags: flags |= re.LOCALE if "m" in str_flags: flags |= re.MULTILINE if "s" in str_flags: flags |= re.DOTALL if "u" in str_flags: flags |= re.UNICODE if "x" in str_flags: flags |= re.VERBOSE return flags _T = TypeVar("_T", str, bytes) class Regex(Generic[_T]): """BSON regular expression data.""" __slots__ = ("pattern", "flags") __getstate__ = _getstate_slots __setstate__ = _setstate_slots _type_marker = 11 @classmethod def from_native(cls: Type[Regex[Any]], regex: Pattern[_T]) -> Regex[_T]: """Convert a Python regular expression into a ``Regex`` instance. Note that in Python 3, a regular expression compiled from a :class:`str` has the ``re.UNICODE`` flag set. If it is undesirable to store this flag in a BSON regular expression, unset it first:: >>> pattern = re.compile('.*') >>> regex = Regex.from_native(pattern) >>> regex.flags ^= re.UNICODE >>> db.collection.insert_one({'pattern': regex}) :param regex: A regular expression object from ``re.compile()``. .. warning:: Python regular expressions use a different syntax and different set of flags than MongoDB, which uses `PCRE`_. A regular expression retrieved from the server may not compile in Python, or may match a different set of strings in Python than when used in a MongoDB query. .. _PCRE: http://www.pcre.org/ """ if not isinstance(regex, RE_TYPE): raise TypeError("regex must be a compiled regular expression, not %s" % type(regex)) return Regex(regex.pattern, regex.flags) def __init__(self, pattern: _T, flags: Union[str, int] = 0) -> None: """BSON regular expression data. This class is useful to store and retrieve regular expressions that are incompatible with Python's regular expression dialect. :param pattern: string :param flags: an integer bitmask, or a string of flag characters like "im" for IGNORECASE and MULTILINE """ if not isinstance(pattern, (str, bytes)): raise TypeError("pattern must be a string, not %s" % type(pattern)) self.pattern: _T = pattern if isinstance(flags, str): self.flags = str_flags_to_int(flags) elif isinstance(flags, int): self.flags = flags else: raise TypeError("flags must be a string or int, not %s" % type(flags)) def __eq__(self, other: Any) -> bool: if isinstance(other, Regex): return self.pattern == other.pattern and self.flags == other.flags else: return NotImplemented __hash__ = None # type: ignore def __ne__(self, other: Any) -> bool: return not self == other def __repr__(self) -> str: return f"Regex({self.pattern!r}, {self.flags!r})" def try_compile(self) -> Pattern[_T]: """Compile this :class:`Regex` as a Python regular expression. .. warning:: Python regular expressions use a different syntax and different set of flags than MongoDB, which uses `PCRE`_. A regular expression retrieved from the server may not compile in Python, or may match a different set of strings in Python than when used in a MongoDB query. :meth:`try_compile()` may raise :exc:`re.error`. .. _PCRE: http://www.pcre.org/ """ return re.compile(self.pattern, self.flags) mongodb-mongo-python-driver-509e9b7/bson/son.py000066400000000000000000000145571462766011000215630ustar00rootroot00000000000000# Copyright 2009-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. """Tools for creating and manipulating SON, the Serialized Ocument Notation. Regular dictionaries can be used instead of SON objects, but not when the order of keys is important. A SON object can be used just like a normal Python dictionary. """ from __future__ import annotations import copy import re from collections.abc import Mapping as _Mapping from typing import ( Any, Dict, Iterable, Iterator, Mapping, Optional, Pattern, Tuple, Type, TypeVar, Union, cast, ) # This sort of sucks, but seems to be as good as it gets... # This is essentially the same as re._pattern_type RE_TYPE: Type[Pattern[Any]] = type(re.compile("")) _Key = TypeVar("_Key") _Value = TypeVar("_Value") _T = TypeVar("_T") class SON(Dict[_Key, _Value]): """SON data. A subclass of dict that maintains ordering of keys and provides a few extra niceties for dealing with SON. SON provides an API similar to collections.OrderedDict. """ __keys: list[Any] def __init__( self, data: Optional[Union[Mapping[_Key, _Value], Iterable[Tuple[_Key, _Value]]]] = None, **kwargs: Any, ) -> None: self.__keys = [] dict.__init__(self) self.update(data) self.update(kwargs) def __new__(cls: Type[SON[_Key, _Value]], *args: Any, **kwargs: Any) -> SON[_Key, _Value]: instance = super().__new__(cls, *args, **kwargs) # type: ignore[type-var] instance.__keys = [] return instance def __repr__(self) -> str: result = [] for key in self.__keys: result.append(f"({key!r}, {self[key]!r})") return "SON([%s])" % ", ".join(result) def __setitem__(self, key: _Key, value: _Value) -> None: if key not in self.__keys: self.__keys.append(key) dict.__setitem__(self, key, value) def __delitem__(self, key: _Key) -> None: self.__keys.remove(key) dict.__delitem__(self, key) def copy(self) -> SON[_Key, _Value]: other: SON[_Key, _Value] = SON() other.update(self) return other # TODO this is all from UserDict.DictMixin. it could probably be made more # efficient. # second level definitions support higher levels def __iter__(self) -> Iterator[_Key]: yield from self.__keys def has_key(self, key: _Key) -> bool: return key in self.__keys def iterkeys(self) -> Iterator[_Key]: return self.__iter__() # fourth level uses definitions from lower levels def itervalues(self) -> Iterator[_Value]: for _, v in self.items(): yield v def values(self) -> list[_Value]: # type: ignore[override] return [v for _, v in self.items()] def clear(self) -> None: self.__keys = [] super().clear() def setdefault(self, key: _Key, default: _Value) -> _Value: try: return self[key] except KeyError: self[key] = default return default def pop(self, key: _Key, *args: Union[_Value, _T]) -> Union[_Value, _T]: if len(args) > 1: raise TypeError("pop expected at most 2 arguments, got " + repr(1 + len(args))) try: value = self[key] except KeyError: if args: return args[0] raise del self[key] return value def popitem(self) -> Tuple[_Key, _Value]: try: k, v = next(iter(self.items())) except StopIteration: raise KeyError("container is empty") from None del self[k] return (k, v) def update(self, other: Optional[Any] = None, **kwargs: _Value) -> None: # type: ignore[override] # Make progressively weaker assumptions about "other" if other is None: pass elif hasattr(other, "items"): for k, v in other.items(): self[k] = v elif hasattr(other, "keys"): for k in other: self[k] = other[k] else: for k, v in other: self[k] = v if kwargs: self.update(kwargs) def get( # type: ignore[override] self, key: _Key, default: Optional[Union[_Value, _T]] = None ) -> Union[_Value, _T, None]: try: return self[key] except KeyError: return default def __eq__(self, other: Any) -> bool: """Comparison to another SON is order-sensitive while comparison to a regular dictionary is order-insensitive. """ if isinstance(other, SON): return len(self) == len(other) and list(self.items()) == list(other.items()) return cast(bool, self.to_dict() == other) def __ne__(self, other: Any) -> bool: return not self == other def __len__(self) -> int: return len(self.__keys) def to_dict(self) -> dict[_Key, _Value]: """Convert a SON document to a normal Python dictionary instance. This is trickier than just *dict(...)* because it needs to be recursive. """ def transform_value(value: Any) -> Any: if isinstance(value, list): return [transform_value(v) for v in value] elif isinstance(value, _Mapping): return {k: transform_value(v) for k, v in value.items()} else: return value return cast("dict[_Key, _Value]", transform_value(dict(self))) def __deepcopy__(self, memo: dict[int, SON[_Key, _Value]]) -> SON[_Key, _Value]: out: SON[_Key, _Value] = SON() val_id = id(self) if val_id in memo: return memo[val_id] memo[val_id] = out for k, v in self.items(): if not isinstance(v, RE_TYPE): v = copy.deepcopy(v, memo) # noqa: PLW2901 out[k] = v return out mongodb-mongo-python-driver-509e9b7/bson/time64.c000066400000000000000000000520271462766011000216600ustar00rootroot00000000000000/* Copyright (c) 2007-2010 Michael G Schwern This software originally derived from Paul Sheer's pivotal_gmtime_r.c. The MIT License: Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /* Programmers who have available to them 64-bit time values as a 'long long' type can use cbson_localtime64_r() and cbson_gmtime64_r() which correctly converts the time even on 32-bit systems. Whether you have 64-bit time values will depend on the operating system. cbson_localtime64_r() is a 64-bit equivalent of localtime_r(). cbson_gmtime64_r() is a 64-bit equivalent of gmtime_r(). */ #ifdef _MSC_VER #define _CRT_SECURE_NO_WARNINGS #endif /* Including Python.h fixes issues with interpreters built with -std=c99. */ #define PY_SSIZE_T_CLEAN #include "Python.h" #include #include "time64.h" #include "time64_limits.h" /* Spec says except for stftime() and the _r() functions, these all return static memory. Stabbings! */ static struct TM Static_Return_Date; static const int days_in_month[2][12] = { {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}, {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}, }; static const int julian_days_by_month[2][12] = { {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334}, {0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335}, }; static const int length_of_year[2] = { 365, 366 }; /* Some numbers relating to the gregorian cycle */ static const Year years_in_gregorian_cycle = 400; #define days_in_gregorian_cycle ((365 * 400) + 100 - 4 + 1) static const Time64_T seconds_in_gregorian_cycle = days_in_gregorian_cycle * 60LL * 60LL * 24LL; /* Year range we can trust the time functions with */ #define MAX_SAFE_YEAR 2037 #define MIN_SAFE_YEAR 1971 /* 28 year Julian calendar cycle */ #define SOLAR_CYCLE_LENGTH 28 /* Year cycle from MAX_SAFE_YEAR down. */ static const int safe_years_high[SOLAR_CYCLE_LENGTH] = { 2016, 2017, 2018, 2019, 2020, 2021, 2022, 2023, 2024, 2025, 2026, 2027, 2028, 2029, 2030, 2031, 2032, 2033, 2034, 2035, 2036, 2037, 2010, 2011, 2012, 2013, 2014, 2015 }; /* Year cycle from MIN_SAFE_YEAR up */ static const int safe_years_low[SOLAR_CYCLE_LENGTH] = { 1996, 1997, 1998, 1971, 1972, 1973, 1974, 1975, 1976, 1977, 1978, 1979, 1980, 1981, 1982, 1983, 1984, 1985, 1986, 1987, 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, }; /* Let's assume people are going to be looking for dates in the future. Let's provide some cheats so you can skip ahead. This has a 4x speed boost when near 2008. */ /* Number of days since epoch on Jan 1st, 2008 GMT */ #define CHEAT_DAYS (1199145600 / 24 / 60 / 60) #define CHEAT_YEARS 108 #define IS_LEAP(n) ((!(((n) + 1900) % 400) || (!(((n) + 1900) % 4) && (((n) + 1900) % 100))) != 0) #define _TIME64_WRAP(a,b,m) ((a) = ((a) < 0 ) ? ((b)--, (a) + (m)) : (a)) #ifdef USE_SYSTEM_LOCALTIME # define SHOULD_USE_SYSTEM_LOCALTIME(a) ( \ (a) <= SYSTEM_LOCALTIME_MAX && \ (a) >= SYSTEM_LOCALTIME_MIN \ ) #else # define SHOULD_USE_SYSTEM_LOCALTIME(a) (0) #endif #ifdef USE_SYSTEM_GMTIME # define SHOULD_USE_SYSTEM_GMTIME(a) ( \ (a) <= SYSTEM_GMTIME_MAX && \ (a) >= SYSTEM_GMTIME_MIN \ ) #else # define SHOULD_USE_SYSTEM_GMTIME(a) (0) #endif /* Multi varadic macros are a C99 thing, alas */ #ifdef TIME_64_DEBUG # define TIME64_TRACE(format) (fprintf(stderr, format)) # define TIME64_TRACE1(format, var1) (fprintf(stderr, format, var1)) # define TIME64_TRACE2(format, var1, var2) (fprintf(stderr, format, var1, var2)) # define TIME64_TRACE3(format, var1, var2, var3) (fprintf(stderr, format, var1, var2, var3)) #else # define TIME64_TRACE(format) ((void)0) # define TIME64_TRACE1(format, var1) ((void)0) # define TIME64_TRACE2(format, var1, var2) ((void)0) # define TIME64_TRACE3(format, var1, var2, var3) ((void)0) #endif static int is_exception_century(Year year) { int is_exception = ((year % 100 == 0) && !(year % 400 == 0)); TIME64_TRACE1("# is_exception_century: %s\n", is_exception ? "yes" : "no"); return(is_exception); } /* Compare two dates. The result is like cmp. Ignores things like gmtoffset and dst */ int cbson_cmp_date( const struct TM* left, const struct tm* right ) { if( left->tm_year > right->tm_year ) return 1; else if( left->tm_year < right->tm_year ) return -1; if( left->tm_mon > right->tm_mon ) return 1; else if( left->tm_mon < right->tm_mon ) return -1; if( left->tm_mday > right->tm_mday ) return 1; else if( left->tm_mday < right->tm_mday ) return -1; if( left->tm_hour > right->tm_hour ) return 1; else if( left->tm_hour < right->tm_hour ) return -1; if( left->tm_min > right->tm_min ) return 1; else if( left->tm_min < right->tm_min ) return -1; if( left->tm_sec > right->tm_sec ) return 1; else if( left->tm_sec < right->tm_sec ) return -1; return 0; } /* Check if a date is safely inside a range. The intention is to check if its a few days inside. */ int cbson_date_in_safe_range( const struct TM* date, const struct tm* min, const struct tm* max ) { if( cbson_cmp_date(date, min) == -1 ) return 0; if( cbson_cmp_date(date, max) == 1 ) return 0; return 1; } /* timegm() is not in the C or POSIX spec, but it is such a useful extension I would be remiss in leaving it out. Also I need it for cbson_localtime64() */ Time64_T cbson_timegm64(const struct TM *date) { Time64_T days = 0; Time64_T seconds = 0; Year year; Year orig_year = (Year)date->tm_year; int cycles = 0; if( orig_year > 100 ) { cycles = (int)((orig_year - 100) / 400); orig_year -= cycles * 400; days += (Time64_T)cycles * days_in_gregorian_cycle; } else if( orig_year < -300 ) { cycles = (int)((orig_year - 100) / 400); orig_year -= cycles * 400; days += (Time64_T)cycles * days_in_gregorian_cycle; } TIME64_TRACE3("# timegm/ cycles: %d, days: %lld, orig_year: %lld\n", cycles, days, orig_year); if( orig_year > 70 ) { year = 70; while( year < orig_year ) { days += length_of_year[IS_LEAP(year)]; year++; } } else if ( orig_year < 70 ) { year = 69; do { days -= length_of_year[IS_LEAP(year)]; year--; } while( year >= orig_year ); } days += julian_days_by_month[IS_LEAP(orig_year)][date->tm_mon]; days += date->tm_mday - 1; seconds = days * 60 * 60 * 24; seconds += date->tm_hour * 60 * 60; seconds += date->tm_min * 60; seconds += date->tm_sec; return(seconds); } #ifndef NDEBUG static int check_tm(struct TM *tm) { /* Don't forget leap seconds */ assert(tm->tm_sec >= 0); assert(tm->tm_sec <= 61); assert(tm->tm_min >= 0); assert(tm->tm_min <= 59); assert(tm->tm_hour >= 0); assert(tm->tm_hour <= 23); assert(tm->tm_mday >= 1); assert(tm->tm_mday <= days_in_month[IS_LEAP(tm->tm_year)][tm->tm_mon]); assert(tm->tm_mon >= 0); assert(tm->tm_mon <= 11); assert(tm->tm_wday >= 0); assert(tm->tm_wday <= 6); assert(tm->tm_yday >= 0); assert(tm->tm_yday <= length_of_year[IS_LEAP(tm->tm_year)]); #ifdef HAS_TM_TM_GMTOFF assert(tm->tm_gmtoff >= -24 * 60 * 60); assert(tm->tm_gmtoff <= 24 * 60 * 60); #endif return 1; } #endif /* The exceptional centuries without leap years cause the cycle to shift by 16 */ static Year cycle_offset(Year year) { const Year start_year = 2000; Year year_diff = year - start_year; Year exceptions; if( year > start_year ) year_diff--; exceptions = year_diff / 100; exceptions -= year_diff / 400; TIME64_TRACE3("# year: %lld, exceptions: %lld, year_diff: %lld\n", year, exceptions, year_diff); return exceptions * 16; } /* For a given year after 2038, pick the latest possible matching year in the 28 year calendar cycle. A matching year... 1) Starts on the same day of the week. 2) Has the same leap year status. This is so the calendars match up. Also the previous year must match. When doing Jan 1st you might wind up on Dec 31st the previous year when doing a -UTC time zone. Finally, the next year must have the same start day of week. This is for Dec 31st with a +UTC time zone. It doesn't need the same leap year status since we only care about January 1st. */ static int safe_year(const Year year) { int safe_year = 0; Year year_cycle; if( year >= MIN_SAFE_YEAR && year <= MAX_SAFE_YEAR ) { return (int)year; } year_cycle = year + cycle_offset(year); /* safe_years_low is off from safe_years_high by 8 years */ if( year < MIN_SAFE_YEAR ) year_cycle -= 8; /* Change non-leap xx00 years to an equivalent */ if( is_exception_century(year) ) year_cycle += 11; /* Also xx01 years, since the previous year will be wrong */ if( is_exception_century(year - 1) ) year_cycle += 17; year_cycle %= SOLAR_CYCLE_LENGTH; if( year_cycle < 0 ) year_cycle = SOLAR_CYCLE_LENGTH + year_cycle; assert( year_cycle >= 0 ); assert( year_cycle < SOLAR_CYCLE_LENGTH ); if( year < MIN_SAFE_YEAR ) safe_year = safe_years_low[year_cycle]; else if( year > MAX_SAFE_YEAR ) safe_year = safe_years_high[year_cycle]; else assert(0); TIME64_TRACE3("# year: %lld, year_cycle: %lld, safe_year: %d\n", year, year_cycle, safe_year); assert(safe_year <= MAX_SAFE_YEAR && safe_year >= MIN_SAFE_YEAR); return safe_year; } void pymongo_copy_tm_to_TM64(const struct tm *src, struct TM *dest) { if( src == NULL ) { memset(dest, 0, sizeof(*dest)); } else { # ifdef USE_TM64 dest->tm_sec = src->tm_sec; dest->tm_min = src->tm_min; dest->tm_hour = src->tm_hour; dest->tm_mday = src->tm_mday; dest->tm_mon = src->tm_mon; dest->tm_year = (Year)src->tm_year; dest->tm_wday = src->tm_wday; dest->tm_yday = src->tm_yday; dest->tm_isdst = src->tm_isdst; # ifdef HAS_TM_TM_GMTOFF dest->tm_gmtoff = src->tm_gmtoff; # endif # ifdef HAS_TM_TM_ZONE dest->tm_zone = src->tm_zone; # endif # else /* They're the same type */ memcpy(dest, src, sizeof(*dest)); # endif } } void cbson_copy_TM64_to_tm(const struct TM *src, struct tm *dest) { if( src == NULL ) { memset(dest, 0, sizeof(*dest)); } else { # ifdef USE_TM64 dest->tm_sec = src->tm_sec; dest->tm_min = src->tm_min; dest->tm_hour = src->tm_hour; dest->tm_mday = src->tm_mday; dest->tm_mon = src->tm_mon; dest->tm_year = (int)src->tm_year; dest->tm_wday = src->tm_wday; dest->tm_yday = src->tm_yday; dest->tm_isdst = src->tm_isdst; # ifdef HAS_TM_TM_GMTOFF dest->tm_gmtoff = src->tm_gmtoff; # endif # ifdef HAS_TM_TM_ZONE dest->tm_zone = src->tm_zone; # endif # else /* They're the same type */ memcpy(dest, src, sizeof(*dest)); # endif } } /* Simulate localtime_r() to the best of our ability */ struct tm * cbson_fake_localtime_r(const time_t *time, struct tm *result) { const struct tm *static_result = localtime(time); assert(result != NULL); if( static_result == NULL ) { memset(result, 0, sizeof(*result)); return NULL; } else { memcpy(result, static_result, sizeof(*result)); return result; } } /* Simulate gmtime_r() to the best of our ability */ struct tm * cbson_fake_gmtime_r(const time_t *time, struct tm *result) { const struct tm *static_result = gmtime(time); assert(result != NULL); if( static_result == NULL ) { memset(result, 0, sizeof(*result)); return NULL; } else { memcpy(result, static_result, sizeof(*result)); return result; } } static Time64_T seconds_between_years(Year left_year, Year right_year) { int increment = (left_year > right_year) ? 1 : -1; Time64_T seconds = 0; int cycles; if( left_year > 2400 ) { cycles = (int)((left_year - 2400) / 400); left_year -= cycles * 400; seconds += cycles * seconds_in_gregorian_cycle; } else if( left_year < 1600 ) { cycles = (int)((left_year - 1600) / 400); left_year += cycles * 400; seconds += cycles * seconds_in_gregorian_cycle; } while( left_year != right_year ) { seconds += length_of_year[IS_LEAP(right_year - 1900)] * 60 * 60 * 24; right_year += increment; } return seconds * increment; } Time64_T cbson_mktime64(const struct TM *input_date) { struct tm safe_date; struct TM date; Time64_T time; Year year = input_date->tm_year + 1900; if( cbson_date_in_safe_range(input_date, &SYSTEM_MKTIME_MIN, &SYSTEM_MKTIME_MAX) ) { cbson_copy_TM64_to_tm(input_date, &safe_date); return (Time64_T)mktime(&safe_date); } /* Have to make the year safe in date else it won't fit in safe_date */ date = *input_date; date.tm_year = safe_year(year) - 1900; cbson_copy_TM64_to_tm(&date, &safe_date); time = (Time64_T)mktime(&safe_date); time += seconds_between_years(year, (Year)(safe_date.tm_year + 1900)); return time; } /* Because I think mktime() is a crappy name */ Time64_T timelocal64(const struct TM *date) { return cbson_mktime64(date); } struct TM *cbson_gmtime64_r (const Time64_T *in_time, struct TM *p) { int v_tm_sec, v_tm_min, v_tm_hour, v_tm_mon, v_tm_wday; Time64_T v_tm_tday; int leap; Time64_T m; Time64_T time = *in_time; Year year = 70; int cycles = 0; assert(p != NULL); #ifdef USE_SYSTEM_GMTIME /* Use the system gmtime() if time_t is small enough */ if( SHOULD_USE_SYSTEM_GMTIME(*in_time) ) { time_t safe_time = (time_t)*in_time; struct tm safe_date; GMTIME_R(&safe_time, &safe_date); pymongo_copy_tm_to_TM64(&safe_date, p); assert(check_tm(p)); return p; } #endif #ifdef HAS_TM_TM_GMTOFF p->tm_gmtoff = 0; #endif p->tm_isdst = 0; #ifdef HAS_TM_TM_ZONE p->tm_zone = "UTC"; #endif v_tm_sec = (int)(time % 60); time /= 60; v_tm_min = (int)(time % 60); time /= 60; v_tm_hour = (int)(time % 24); time /= 24; v_tm_tday = time; _TIME64_WRAP (v_tm_sec, v_tm_min, 60); _TIME64_WRAP (v_tm_min, v_tm_hour, 60); _TIME64_WRAP (v_tm_hour, v_tm_tday, 24); v_tm_wday = (int)((v_tm_tday + 4) % 7); if (v_tm_wday < 0) v_tm_wday += 7; m = v_tm_tday; if (m >= CHEAT_DAYS) { year = CHEAT_YEARS; m -= CHEAT_DAYS; } if (m >= 0) { /* Gregorian cycles, this is huge optimization for distant times */ cycles = (int)(m / (Time64_T) days_in_gregorian_cycle); if( cycles ) { m -= (cycles * (Time64_T) days_in_gregorian_cycle); year += (cycles * years_in_gregorian_cycle); } /* Years */ leap = IS_LEAP (year); while (m >= (Time64_T) length_of_year[leap]) { m -= (Time64_T) length_of_year[leap]; year++; leap = IS_LEAP (year); } /* Months */ v_tm_mon = 0; while (m >= (Time64_T) days_in_month[leap][v_tm_mon]) { m -= (Time64_T) days_in_month[leap][v_tm_mon]; v_tm_mon++; } } else { year--; /* Gregorian cycles */ cycles = (int)((m / (Time64_T) days_in_gregorian_cycle) + 1); if( cycles ) { m -= (cycles * (Time64_T) days_in_gregorian_cycle); year += (cycles * years_in_gregorian_cycle); } /* Years */ leap = IS_LEAP (year); while (m < (Time64_T) -length_of_year[leap]) { m += (Time64_T) length_of_year[leap]; year--; leap = IS_LEAP (year); } /* Months */ v_tm_mon = 11; while (m < (Time64_T) -days_in_month[leap][v_tm_mon]) { m += (Time64_T) days_in_month[leap][v_tm_mon]; v_tm_mon--; } m += (Time64_T) days_in_month[leap][v_tm_mon]; } p->tm_year = (int)year; if( p->tm_year != year ) { #ifdef EOVERFLOW errno = EOVERFLOW; #endif return NULL; } /* At this point m is less than a year so casting to an int is safe */ p->tm_mday = (int) m + 1; p->tm_yday = julian_days_by_month[leap][v_tm_mon] + (int)m; p->tm_sec = v_tm_sec; p->tm_min = v_tm_min; p->tm_hour = v_tm_hour; p->tm_mon = v_tm_mon; p->tm_wday = v_tm_wday; assert(check_tm(p)); return p; } struct TM *cbson_localtime64_r (const Time64_T *time, struct TM *local_tm) { time_t safe_time; struct tm safe_date; struct TM gm_tm; Year orig_year; int month_diff; assert(local_tm != NULL); #ifdef USE_SYSTEM_LOCALTIME /* Use the system localtime() if time_t is small enough */ if( SHOULD_USE_SYSTEM_LOCALTIME(*time) ) { safe_time = (time_t)*time; TIME64_TRACE1("Using system localtime for %lld\n", *time); LOCALTIME_R(&safe_time, &safe_date); pymongo_copy_tm_to_TM64(&safe_date, local_tm); assert(check_tm(local_tm)); return local_tm; } #endif if( cbson_gmtime64_r(time, &gm_tm) == NULL ) { TIME64_TRACE1("cbson_gmtime64_r returned null for %lld\n", *time); return NULL; } orig_year = gm_tm.tm_year; if (gm_tm.tm_year > (2037 - 1900) || gm_tm.tm_year < (1970 - 1900) ) { TIME64_TRACE1("Mapping tm_year %lld to safe_year\n", (Year)gm_tm.tm_year); gm_tm.tm_year = safe_year((Year)(gm_tm.tm_year + 1900)) - 1900; } safe_time = (time_t)cbson_timegm64(&gm_tm); if( LOCALTIME_R(&safe_time, &safe_date) == NULL ) { TIME64_TRACE1("localtime_r(%d) returned NULL\n", (int)safe_time); return NULL; } pymongo_copy_tm_to_TM64(&safe_date, local_tm); local_tm->tm_year = (int)orig_year; if( local_tm->tm_year != orig_year ) { TIME64_TRACE2("tm_year overflow: tm_year %lld, orig_year %lld\n", (Year)local_tm->tm_year, (Year)orig_year); #ifdef EOVERFLOW errno = EOVERFLOW; #endif return NULL; } month_diff = local_tm->tm_mon - gm_tm.tm_mon; /* When localtime is Dec 31st previous year and gmtime is Jan 1st next year. */ if( month_diff == 11 ) { local_tm->tm_year--; } /* When localtime is Jan 1st, next year and gmtime is Dec 31st, previous year. */ if( month_diff == -11 ) { local_tm->tm_year++; } /* GMT is Jan 1st, xx01 year, but localtime is still Dec 31st in a non-leap xx00. There is one point in the cycle we can't account for which the safe xx00 year is a leap year. So we need to correct for Dec 31st coming out as the 366th day of the year. */ if( !IS_LEAP(local_tm->tm_year) && local_tm->tm_yday == 365 ) local_tm->tm_yday--; assert(check_tm(local_tm)); return local_tm; } int cbson_valid_tm_wday( const struct TM* date ) { if( 0 <= date->tm_wday && date->tm_wday <= 6 ) return 1; else return 0; } int cbson_valid_tm_mon( const struct TM* date ) { if( 0 <= date->tm_mon && date->tm_mon <= 11 ) return 1; else return 0; } /* Non-thread safe versions of the above */ struct TM *cbson_localtime64(const Time64_T *time) { #ifdef _MSC_VER _tzset(); #else tzset(); #endif return cbson_localtime64_r(time, &Static_Return_Date); } struct TM *cbson_gmtime64(const Time64_T *time) { return cbson_gmtime64_r(time, &Static_Return_Date); } mongodb-mongo-python-driver-509e9b7/bson/time64.h000066400000000000000000000030311462766011000216540ustar00rootroot00000000000000#ifndef TIME64_H # define TIME64_H #include #include "time64_config.h" /* Set our custom types */ typedef INT_64_T Int64; typedef Int64 Time64_T; typedef Int64 Year; /* A copy of the tm struct but with a 64 bit year */ struct TM64 { int tm_sec; int tm_min; int tm_hour; int tm_mday; int tm_mon; Year tm_year; int tm_wday; int tm_yday; int tm_isdst; #ifdef HAS_TM_TM_GMTOFF long tm_gmtoff; #endif #ifdef HAS_TM_TM_ZONE char *tm_zone; #endif }; /* Decide which tm struct to use */ #ifdef USE_TM64 #define TM TM64 #else #define TM tm #endif /* Declare public functions */ struct TM *cbson_gmtime64_r (const Time64_T *, struct TM *); struct TM *cbson_localtime64_r (const Time64_T *, struct TM *); struct TM *cbson_gmtime64 (const Time64_T *); struct TM *cbson_localtime64 (const Time64_T *); Time64_T cbson_timegm64 (const struct TM *); Time64_T cbson_mktime64 (const struct TM *); Time64_T timelocal64 (const struct TM *); /* Not everyone has gm/localtime_r(), provide a replacement */ #ifdef HAS_LOCALTIME_R # define LOCALTIME_R(clock, result) localtime_r(clock, result) #else # define LOCALTIME_R(clock, result) cbson_fake_localtime_r(clock, result) #endif #ifdef HAS_GMTIME_R # define GMTIME_R(clock, result) gmtime_r(clock, result) #else # define GMTIME_R(clock, result) cbson_fake_gmtime_r(clock, result) #endif #endif mongodb-mongo-python-driver-509e9b7/bson/time64_config.h000066400000000000000000000032221462766011000232030ustar00rootroot00000000000000/* Configuration ------------- Define as appropriate for your system. Sensible defaults provided. */ #ifndef TIME64_CONFIG_H # define TIME64_CONFIG_H /* Debugging TIME_64_DEBUG Define if you want debugging messages */ /* #define TIME_64_DEBUG */ /* INT_64_T A 64 bit integer type to use to store time and others. Must be defined. */ #define INT_64_T long long /* USE_TM64 Should we use a 64 bit safe replacement for tm? This will let you go past year 2 billion but the struct will be incompatible with tm. Conversion functions will be provided. */ /* #define USE_TM64 */ /* Availability of system functions. HAS_GMTIME_R Define if your system has gmtime_r() HAS_LOCALTIME_R Define if your system has localtime_r() HAS_TIMEGM Define if your system has timegm(), a GNU extension. */ #if !defined(WIN32) && !defined(_MSC_VER) #define HAS_GMTIME_R #define HAS_LOCALTIME_R #endif /* #define HAS_TIMEGM */ /* Details of non-standard tm struct elements. HAS_TM_TM_GMTOFF True if your tm struct has a "tm_gmtoff" element. A BSD extension. HAS_TM_TM_ZONE True if your tm struct has a "tm_zone" element. A BSD extension. */ /* #define HAS_TM_TM_GMTOFF */ /* #define HAS_TM_TM_ZONE */ /* USE_SYSTEM_LOCALTIME USE_SYSTEM_GMTIME USE_SYSTEM_MKTIME USE_SYSTEM_TIMEGM Should we use the system functions if the time is inside their range? Your system localtime() is probably more accurate, but our gmtime() is fast and safe. */ #define USE_SYSTEM_LOCALTIME /* #define USE_SYSTEM_GMTIME */ #define USE_SYSTEM_MKTIME /* #define USE_SYSTEM_TIMEGM */ #endif /* TIME64_CONFIG_H */ mongodb-mongo-python-driver-509e9b7/bson/time64_limits.h000066400000000000000000000027241462766011000232450ustar00rootroot00000000000000/* Maximum and minimum inputs your system's respective time functions can correctly handle. time64.h will use your system functions if the input falls inside these ranges and corresponding USE_SYSTEM_* constant is defined. */ #ifndef TIME64_LIMITS_H #define TIME64_LIMITS_H /* Max/min for localtime() */ #define SYSTEM_LOCALTIME_MAX 2147483647 #define SYSTEM_LOCALTIME_MIN -2147483647-1 /* Max/min for gmtime() */ #define SYSTEM_GMTIME_MAX 2147483647 #define SYSTEM_GMTIME_MIN -2147483647-1 /* Max/min for mktime() */ static const struct tm SYSTEM_MKTIME_MAX = { 7, 14, 19, 18, 0, 138, 1, 17, 0 #ifdef HAS_TM_TM_GMTOFF ,-28800 #endif #ifdef HAS_TM_TM_ZONE ,"PST" #endif }; static const struct tm SYSTEM_MKTIME_MIN = { 52, 45, 12, 13, 11, 1, 5, 346, 0 #ifdef HAS_TM_TM_GMTOFF ,-28800 #endif #ifdef HAS_TM_TM_ZONE ,"PST" #endif }; /* Max/min for timegm() */ #ifdef HAS_TIMEGM static const struct tm SYSTEM_TIMEGM_MAX = { 7, 14, 3, 19, 0, 138, 2, 18, 0 #ifdef HAS_TM_TM_GMTOFF ,0 #endif #ifdef HAS_TM_TM_ZONE ,"UTC" #endif }; static const struct tm SYSTEM_TIMEGM_MIN = { 52, 45, 20, 13, 11, 1, 5, 346, 0 #ifdef HAS_TM_TM_GMTOFF ,0 #endif #ifdef HAS_TM_TM_ZONE ,"UTC" #endif }; #endif /* HAS_TIMEGM */ #endif /* TIME64_LIMITS_H */ mongodb-mongo-python-driver-509e9b7/bson/timestamp.py000066400000000000000000000102111462766011000227460ustar00rootroot00000000000000# Copyright 2010-2015 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. """Tools for representing MongoDB internal Timestamps.""" from __future__ import annotations import calendar import datetime from typing import Any, Union from bson._helpers import _getstate_slots, _setstate_slots from bson.tz_util import utc UPPERBOUND = 4294967296 class Timestamp: """MongoDB internal timestamps used in the opLog.""" __slots__ = ("__time", "__inc") __getstate__ = _getstate_slots __setstate__ = _setstate_slots _type_marker = 17 def __init__(self, time: Union[datetime.datetime, int], inc: int) -> None: """Create a new :class:`Timestamp`. This class is only for use with the MongoDB opLog. If you need to store a regular timestamp, please use a :class:`~datetime.datetime`. Raises :class:`TypeError` if `time` is not an instance of :class: `int` or :class:`~datetime.datetime`, or `inc` is not an instance of :class:`int`. Raises :class:`ValueError` if `time` or `inc` is not in [0, 2**32). :param time: time in seconds since epoch UTC, or a naive UTC :class:`~datetime.datetime`, or an aware :class:`~datetime.datetime` :param inc: the incrementing counter """ if isinstance(time, datetime.datetime): offset = time.utcoffset() if offset is not None: time = time - offset time = int(calendar.timegm(time.timetuple())) if not isinstance(time, int): raise TypeError("time must be an instance of int") if not isinstance(inc, int): raise TypeError("inc must be an instance of int") if not 0 <= time < UPPERBOUND: raise ValueError("time must be contained in [0, 2**32)") if not 0 <= inc < UPPERBOUND: raise ValueError("inc must be contained in [0, 2**32)") self.__time = time self.__inc = inc @property def time(self) -> int: """Get the time portion of this :class:`Timestamp`.""" return self.__time @property def inc(self) -> int: """Get the inc portion of this :class:`Timestamp`.""" return self.__inc def __eq__(self, other: Any) -> bool: if isinstance(other, Timestamp): return self.__time == other.time and self.__inc == other.inc else: return NotImplemented def __hash__(self) -> int: return hash(self.time) ^ hash(self.inc) def __ne__(self, other: Any) -> bool: return not self == other def __lt__(self, other: Any) -> bool: if isinstance(other, Timestamp): return (self.time, self.inc) < (other.time, other.inc) return NotImplemented def __le__(self, other: Any) -> bool: if isinstance(other, Timestamp): return (self.time, self.inc) <= (other.time, other.inc) return NotImplemented def __gt__(self, other: Any) -> bool: if isinstance(other, Timestamp): return (self.time, self.inc) > (other.time, other.inc) return NotImplemented def __ge__(self, other: Any) -> bool: if isinstance(other, Timestamp): return (self.time, self.inc) >= (other.time, other.inc) return NotImplemented def __repr__(self) -> str: return f"Timestamp({self.__time}, {self.__inc})" def as_datetime(self) -> datetime.datetime: """Return a :class:`~datetime.datetime` instance corresponding to the time portion of this :class:`Timestamp`. The returned datetime's timezone is UTC. """ return datetime.datetime.fromtimestamp(self.__time, utc) mongodb-mongo-python-driver-509e9b7/bson/typings.py000066400000000000000000000021621462766011000224460ustar00rootroot00000000000000# Copyright 2023-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. """Type aliases used by bson""" from __future__ import annotations from typing import TYPE_CHECKING, Any, Mapping, MutableMapping, TypeVar, Union if TYPE_CHECKING: from array import array from mmap import mmap from bson.raw_bson import RawBSONDocument # Common Shared Types. _DocumentOut = Union[MutableMapping[str, Any], "RawBSONDocument"] _DocumentType = TypeVar("_DocumentType", bound=Mapping[str, Any]) _DocumentTypeArg = TypeVar("_DocumentTypeArg", bound=Mapping[str, Any]) _ReadableBuffer = Union[bytes, memoryview, "mmap", "array"] mongodb-mongo-python-driver-509e9b7/bson/tz_util.py000066400000000000000000000033411462766011000224430ustar00rootroot00000000000000# Copyright 2010-2015 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. """Timezone related utilities for BSON.""" from __future__ import annotations from datetime import datetime, timedelta, tzinfo from typing import Optional, Tuple, Union ZERO: timedelta = timedelta(0) class FixedOffset(tzinfo): """Fixed offset timezone, in minutes east from UTC. Implementation based from the Python `standard library documentation `_. Defining __getinitargs__ enables pickling / copying. """ def __init__(self, offset: Union[float, timedelta], name: str) -> None: if isinstance(offset, timedelta): self.__offset = offset else: self.__offset = timedelta(minutes=offset) self.__name = name def __getinitargs__(self) -> Tuple[timedelta, str]: return self.__offset, self.__name def utcoffset(self, dt: Optional[datetime]) -> timedelta: return self.__offset def tzname(self, dt: Optional[datetime]) -> str: return self.__name def dst(self, dt: Optional[datetime]) -> timedelta: return ZERO utc: FixedOffset = FixedOffset(0, "UTC") """Fixed offset timezone representing UTC.""" mongodb-mongo-python-driver-509e9b7/doc/000077500000000000000000000000001462766011000202025ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/doc/Makefile000066400000000000000000000011721462766011000216430ustar00rootroot00000000000000# Minimal makefile for Sphinx documentation # # You can set these variables from the command line, and also # from the environment for the first two. SPHINXOPTS ?= SPHINXBUILD ?= sphinx-build SOURCEDIR = . BUILDDIR = _build # Put it first so that "make" without argument is like "make help". help: @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) .PHONY: help Makefile # Catch-all target: route all unknown targets to Sphinx using the new # "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). %: Makefile @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) mongodb-mongo-python-driver-509e9b7/doc/__init__.py000066400000000000000000000000001462766011000223010ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/doc/_templates/000077500000000000000000000000001462766011000223375ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/doc/_templates/layout.html000066400000000000000000000013721462766011000245450ustar00rootroot00000000000000{% extends "!layout.html" %} {%- block extrahead %} {% if theme_googletag %} {% endif %} {%- endblock -%} mongodb-mongo-python-driver-509e9b7/doc/api/000077500000000000000000000000001462766011000207535ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/doc/api/bson/000077500000000000000000000000001462766011000217145ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/doc/api/bson/binary.rst000066400000000000000000000014671462766011000237420ustar00rootroot00000000000000:mod:`binary` -- Tools for representing binary data to be stored in MongoDB =========================================================================== .. automodule:: bson.binary :synopsis: Tools for representing binary data to be stored in MongoDB .. autodata:: BINARY_SUBTYPE .. autodata:: FUNCTION_SUBTYPE .. autodata:: OLD_BINARY_SUBTYPE .. autodata:: OLD_UUID_SUBTYPE .. autodata:: UUID_SUBTYPE .. autodata:: STANDARD .. autodata:: PYTHON_LEGACY .. autodata:: JAVA_LEGACY .. autodata:: CSHARP_LEGACY .. autodata:: MD5_SUBTYPE .. autodata:: COLUMN_SUBTYPE .. autodata:: SENSITIVE_SUBTYPE .. autodata:: USER_DEFINED_SUBTYPE .. autoclass:: UuidRepresentation :members: .. autoclass:: Binary(data, subtype=BINARY_SUBTYPE) :members: :show-inheritance: mongodb-mongo-python-driver-509e9b7/doc/api/bson/code.rst000066400000000000000000000004311462766011000233560ustar00rootroot00000000000000:mod:`code` -- Tools for representing JavaScript code ===================================================== .. automodule:: bson.code :synopsis: Tools for representing JavaScript code .. autoclass:: Code(code, scope=None, **kwargs) :members: :show-inheritance: mongodb-mongo-python-driver-509e9b7/doc/api/bson/codec_options.rst000066400000000000000000000003501462766011000252740ustar00rootroot00000000000000:mod:`codec_options` -- Tools for specifying BSON codec options =============================================================== .. automodule:: bson.codec_options :synopsis: Tools for specifying BSON codec options. :members: mongodb-mongo-python-driver-509e9b7/doc/api/bson/datetime_ms.rst000066400000000000000000000003051462766011000247370ustar00rootroot00000000000000:mod:`datetime_ms` -- Support for BSON UTC Datetime =================================================== .. automodule:: bson.datetime_ms :synopsis: Support for BSON UTC datetimes. :members: mongodb-mongo-python-driver-509e9b7/doc/api/bson/dbref.rst000066400000000000000000000004651462766011000235350ustar00rootroot00000000000000:mod:`dbref` -- Tools for manipulating DBRefs (references to documents stored in MongoDB) ========================================================================================= .. automodule:: bson.dbref :synopsis: Tools for manipulating DBRefs (references to documents stored in MongoDB) :members: mongodb-mongo-python-driver-509e9b7/doc/api/bson/decimal128.rst000066400000000000000000000002171462766011000242770ustar00rootroot00000000000000:mod:`decimal128` -- Support for BSON Decimal128 ================================================ .. automodule:: bson.decimal128 :members: mongodb-mongo-python-driver-509e9b7/doc/api/bson/errors.rst000066400000000000000000000003321462766011000237600ustar00rootroot00000000000000:mod:`errors` -- Exceptions raised by the :mod:`bson` package ============================================================= .. automodule:: bson.errors :synopsis: Exceptions raised by the bson package :members: mongodb-mongo-python-driver-509e9b7/doc/api/bson/index.rst000066400000000000000000000010261462766011000235540ustar00rootroot00000000000000:mod:`bson` -- BSON (Binary JSON) Encoding and Decoding ======================================================= .. automodule:: bson :synopsis: BSON (Binary JSON) Encoding and Decoding :members: BSON, decode, decode_all, decode_file_iter, decode_iter, encode, gen_list_name, has_c, is_valid Sub-modules: .. toctree:: :maxdepth: 2 binary code codec_options datetime_ms dbref decimal128 errors int64 json_util max_key min_key objectid raw_bson regex son timestamp tz_util mongodb-mongo-python-driver-509e9b7/doc/api/bson/int64.rst000066400000000000000000000003231462766011000234100ustar00rootroot00000000000000:mod:`int64` -- Tools for representing BSON int64 ================================================= .. versionadded:: 3.0 .. automodule:: bson.int64 :synopsis: Tools for representing BSON int64 :members: mongodb-mongo-python-driver-509e9b7/doc/api/bson/json_util.rst000066400000000000000000000005111462766011000244510ustar00rootroot00000000000000:mod:`json_util` -- Tools for using Python's :mod:`json` module with BSON documents =================================================================================== .. automodule:: bson.json_util :synopsis: Tools for using Python's json module with BSON documents :members: :undoc-members: :member-order: bysource mongodb-mongo-python-driver-509e9b7/doc/api/bson/max_key.rst000066400000000000000000000003701462766011000241030ustar00rootroot00000000000000:mod:`max_key` -- Representation for the MongoDB internal MaxKey type ===================================================================== .. automodule:: bson.max_key :synopsis: Representation for the MongoDB internal MaxKey type :members: mongodb-mongo-python-driver-509e9b7/doc/api/bson/min_key.rst000066400000000000000000000003701462766011000241010ustar00rootroot00000000000000:mod:`min_key` -- Representation for the MongoDB internal MinKey type ===================================================================== .. automodule:: bson.min_key :synopsis: Representation for the MongoDB internal MinKey type :members: mongodb-mongo-python-driver-509e9b7/doc/api/bson/objectid.rst000066400000000000000000000012751462766011000242360ustar00rootroot00000000000000:mod:`objectid` -- Tools for working with MongoDB ObjectIds =========================================================== .. automodule:: bson.objectid :synopsis: Tools for working with MongoDB ObjectIds .. autoclass:: bson.objectid.ObjectId(oid=None) :members: .. describe:: str(o) Get a hex encoded version of :class:`ObjectId` `o`. The following property always holds: .. testsetup:: from bson.objectid import ObjectId .. doctest:: >>> o = ObjectId() >>> o == ObjectId(str(o)) True This representation is useful for urls or other places where ``o.binary`` is inappropriate. mongodb-mongo-python-driver-509e9b7/doc/api/bson/raw_bson.rst000066400000000000000000000003401462766011000242550ustar00rootroot00000000000000:mod:`raw_bson` -- Tools for representing raw BSON documents. ============================================================= .. automodule:: bson.raw_bson :synopsis: Tools for representing raw BSON documents. :members: mongodb-mongo-python-driver-509e9b7/doc/api/bson/regex.rst000066400000000000000000000004061462766011000235600ustar00rootroot00000000000000:mod:`regex` -- Tools for representing MongoDB regular expressions ================================================================== .. versionadded:: 2.7 .. automodule:: bson.regex :synopsis: Tools for representing MongoDB regular expressions :members: mongodb-mongo-python-driver-509e9b7/doc/api/bson/son.rst000066400000000000000000000003361462766011000232470ustar00rootroot00000000000000:mod:`son` -- Tools for working with SON, an ordered mapping ============================================================ .. automodule:: bson.son :synopsis: Tools for working with SON, an ordered mapping :members: mongodb-mongo-python-driver-509e9b7/doc/api/bson/timestamp.rst000066400000000000000000000003731462766011000244540ustar00rootroot00000000000000:mod:`timestamp` -- Tools for representing MongoDB internal Timestamps ====================================================================== .. automodule:: bson.timestamp :synopsis: Tools for representing MongoDB internal Timestamps :members: mongodb-mongo-python-driver-509e9b7/doc/api/bson/tz_util.rst000066400000000000000000000003521462766011000241400ustar00rootroot00000000000000:mod:`tz_util` -- Utilities for dealing with timezones in Python ================================================================ .. automodule:: bson.tz_util :synopsis: Utilities for dealing with timezones in Python :members: mongodb-mongo-python-driver-509e9b7/doc/api/gridfs/000077500000000000000000000000001462766011000222315ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/doc/api/gridfs/errors.rst000066400000000000000000000003441462766011000243000ustar00rootroot00000000000000:mod:`errors` -- Exceptions raised by the :mod:`gridfs` package ================================================================= .. automodule:: gridfs.errors :synopsis: Exceptions raised by the gridfs package :members: mongodb-mongo-python-driver-509e9b7/doc/api/gridfs/grid_file.rst000066400000000000000000000007031462766011000247070ustar00rootroot00000000000000:mod:`grid_file` -- Tools for representing files stored in GridFS ================================================================= .. automodule:: gridfs.grid_file :synopsis: Tools for representing files stored in GridFS .. autoclass:: GridIn :members: .. autoattribute:: _id .. autoclass:: GridOut :members: .. autoattribute:: _id .. automethod:: __iter__ .. autoclass:: GridOutCursor :members: mongodb-mongo-python-driver-509e9b7/doc/api/gridfs/index.rst000066400000000000000000000004101462766011000240650ustar00rootroot00000000000000:mod:`gridfs` -- Tools for working with GridFS ============================================== .. automodule:: gridfs :synopsis: Tools for working with GridFS :members: GridFS, GridFSBucket Sub-modules: .. toctree:: :maxdepth: 2 errors grid_file mongodb-mongo-python-driver-509e9b7/doc/api/index.rst000066400000000000000000000010011462766011000226040ustar00rootroot00000000000000API Documentation ================= The PyMongo distribution contains three top-level packages for interacting with MongoDB. :mod:`bson` is an implementation of the `BSON format `_, :mod:`pymongo` is a full-featured driver for MongoDB, and :mod:`gridfs` is a set of tools for working with the `GridFS `_ storage specification. .. toctree:: :maxdepth: 2 bson/index pymongo/index gridfs/index mongodb-mongo-python-driver-509e9b7/doc/api/pymongo/000077500000000000000000000000001462766011000224435ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/doc/api/pymongo/auth_oidc.rst000066400000000000000000000002541462766011000251350ustar00rootroot00000000000000:mod:`auth_oidc` -- MONGODB-OIDC Authentication =========================================================================== .. automodule:: pymongo.auth_oidc :members: mongodb-mongo-python-driver-509e9b7/doc/api/pymongo/change_stream.rst000066400000000000000000000003141462766011000257730ustar00rootroot00000000000000:mod:`change_stream` -- Watch changes on a collection, database, or cluster =========================================================================== .. automodule:: pymongo.change_stream :members: mongodb-mongo-python-driver-509e9b7/doc/api/pymongo/client_options.rst000066400000000000000000000004121462766011000262230ustar00rootroot00000000000000:mod:`client_options` -- Read only configuration options for a MongoClient. =========================================================================== .. automodule:: pymongo.client_options .. autoclass:: pymongo.client_options.ClientOptions() :members: mongodb-mongo-python-driver-509e9b7/doc/api/pymongo/client_session.rst000066400000000000000000000002751462766011000262220ustar00rootroot00000000000000:mod:`client_session` -- Logical sessions for sequential operations =================================================================== .. automodule:: pymongo.client_session :members: mongodb-mongo-python-driver-509e9b7/doc/api/pymongo/collation.rst000066400000000000000000000012061462766011000251600ustar00rootroot00000000000000:mod:`collation` -- Tools for working with collations. ====================================================== .. automodule:: pymongo.collation :synopsis: Tools for working with collations. .. autoclass:: pymongo.collation.Collation .. autoclass:: pymongo.collation.CollationStrength :members: :member-order: bysource .. autoclass:: pymongo.collation.CollationAlternate :members: :member-order: bysource .. autoclass:: pymongo.collation.CollationCaseFirst :members: :member-order: bysource .. autoclass:: pymongo.collation.CollationMaxVariable :members: :member-order: bysource mongodb-mongo-python-driver-509e9b7/doc/api/pymongo/collection.rst000066400000000000000000000065651462766011000253440ustar00rootroot00000000000000:mod:`collection` -- Collection level operations ================================================ .. automodule:: pymongo.collection :synopsis: Collection level operations .. autodata:: pymongo.ASCENDING .. autodata:: pymongo.DESCENDING .. autodata:: pymongo.GEO2D .. autodata:: pymongo.GEOSPHERE .. autodata:: pymongo.HASHED .. autodata:: pymongo.TEXT .. autoclass:: pymongo.collection.ReturnDocument .. autoattribute:: BEFORE :annotation: .. autoattribute:: AFTER :annotation: .. autoclass:: pymongo.collection.Collection(database, name, create=False, **kwargs) .. describe:: c[name] || c.name Get the `name` sub-collection of :class:`Collection` `c`. Raises :class:`~pymongo.errors.InvalidName` if an invalid collection name is used. .. autoattribute:: full_name .. autoattribute:: name .. autoattribute:: database .. autoattribute:: codec_options .. autoattribute:: read_preference .. autoattribute:: write_concern .. autoattribute:: read_concern .. automethod:: with_options .. automethod:: bulk_write .. automethod:: insert_one .. automethod:: insert_many .. automethod:: replace_one .. automethod:: update_one .. automethod:: update_many .. automethod:: delete_one .. automethod:: delete_many .. automethod:: aggregate .. automethod:: aggregate_raw_batches .. automethod:: watch .. automethod:: find(filter=None, projection=None, skip=0, limit=0, no_cursor_timeout=False, cursor_type=CursorType.NON_TAILABLE, sort=None, allow_partial_results=False, oplog_replay=False, batch_size=0, collation=None, hint=None, max_scan=None, max_time_ms=None, max=None, min=None, return_key=False, show_record_id=False, snapshot=False, comment=None, session=None, allow_disk_use=None) .. automethod:: find_raw_batches(filter=None, projection=None, skip=0, limit=0, no_cursor_timeout=False, cursor_type=CursorType.NON_TAILABLE, sort=None, allow_partial_results=False, oplog_replay=False, batch_size=0, collation=None, hint=None, max_scan=None, max_time_ms=None, max=None, min=None, return_key=False, show_record_id=False, snapshot=False, comment=None, session=None, allow_disk_use=None) .. automethod:: find_one(filter=None, *args, **kwargs) .. automethod:: find_one_and_delete .. automethod:: find_one_and_replace(filter, replacement, projection=None, sort=None, return_document=ReturnDocument.BEFORE, hint=None, session=None, **kwargs) .. automethod:: find_one_and_update(filter, update, projection=None, sort=None, return_document=ReturnDocument.BEFORE, array_filters=None, hint=None, session=None, **kwargs) .. automethod:: count_documents .. automethod:: estimated_document_count .. automethod:: distinct .. automethod:: create_index .. automethod:: create_indexes .. automethod:: drop_index .. automethod:: drop_indexes .. automethod:: list_indexes .. automethod:: index_information .. automethod:: create_search_index .. automethod:: create_search_indexes .. automethod:: drop_search_index .. automethod:: list_search_indexes .. automethod:: update_search_index .. automethod:: drop .. automethod:: rename .. automethod:: options .. automethod:: __getitem__ .. automethod:: __getattr__ mongodb-mongo-python-driver-509e9b7/doc/api/pymongo/command_cursor.rst000066400000000000000000000004101462766011000262030ustar00rootroot00000000000000:mod:`command_cursor` -- Tools for iterating over MongoDB command results ========================================================================= .. automodule:: pymongo.command_cursor :synopsis: Tools for iterating over MongoDB command results :members: mongodb-mongo-python-driver-509e9b7/doc/api/pymongo/cursor.rst000066400000000000000000000027011462766011000245120ustar00rootroot00000000000000:mod:`cursor` -- Tools for iterating over MongoDB query results =============================================================== .. automodule:: pymongo.cursor :synopsis: Tools for iterating over MongoDB query results .. autoclass:: pymongo.cursor.CursorType .. autoattribute:: NON_TAILABLE :annotation: .. autoattribute:: TAILABLE :annotation: .. autoattribute:: TAILABLE_AWAIT :annotation: .. autoattribute:: EXHAUST :annotation: .. autoclass:: pymongo.cursor.Cursor(collection, filter=None, projection=None, skip=0, limit=0, no_cursor_timeout=False, cursor_type=CursorType.NON_TAILABLE, sort=None, allow_partial_results=False, oplog_replay=False, batch_size=0, collation=None, hint=None, max_scan=None, max_time_ms=None, max=None, min=None, return_key=False, show_record_id=False, snapshot=False, comment=None, session=None, allow_disk_use=None) :members: .. describe:: c[index] See :meth:`__getitem__` and read the warning. .. automethod:: __getitem__ .. autoclass:: pymongo.cursor.RawBatchCursor(collection, filter=None, projection=None, skip=0, limit=0, no_cursor_timeout=False, cursor_type=CursorType.NON_TAILABLE, sort=None, allow_partial_results=False, oplog_replay=False, batch_size=0, collation=None, hint=None, max_scan=None, max_time_ms=None, max=None, min=None, return_key=False, show_record_id=False, snapshot=False, comment=None, allow_disk_use=None) mongodb-mongo-python-driver-509e9b7/doc/api/pymongo/database.rst000066400000000000000000000016361462766011000247470ustar00rootroot00000000000000:mod:`database` -- Database level operations ============================================ .. automodule:: pymongo.database :synopsis: Database level operations .. autodata:: pymongo.auth.MECHANISMS .. autoclass:: pymongo.database.Database :members: .. describe:: db[collection_name] || db.collection_name Get the `collection_name` :class:`~pymongo.collection.Collection` of :class:`Database` `db`. Raises :class:`~pymongo.errors.InvalidName` if an invalid collection name is used. .. note:: Use dictionary style access if `collection_name` is an attribute of the :class:`Database` class eg: db[`collection_name`]. .. automethod:: __getitem__ .. automethod:: __getattr__ .. autoattribute:: codec_options .. autoattribute:: read_preference .. autoattribute:: write_concern .. autoattribute:: read_concern mongodb-mongo-python-driver-509e9b7/doc/api/pymongo/driver_info.rst000066400000000000000000000002451462766011000255040ustar00rootroot00000000000000:mod:`driver_info` ================== .. automodule:: pymongo.driver_info .. autoclass:: pymongo.driver_info.DriverInfo(name=None, version=None, platform=None) mongodb-mongo-python-driver-509e9b7/doc/api/pymongo/encryption.rst000066400000000000000000000002411462766011000253640ustar00rootroot00000000000000:mod:`encryption` -- Client-Side Field Level Encryption ======================================================= .. automodule:: pymongo.encryption :members: mongodb-mongo-python-driver-509e9b7/doc/api/pymongo/encryption_options.rst000066400000000000000000000004241462766011000271420ustar00rootroot00000000000000:mod:`encryption_options` -- Automatic Client-Side Field Level Encryption ========================================================================= .. automodule:: pymongo.encryption_options :synopsis: Support for automatic client-side field level encryption :members: mongodb-mongo-python-driver-509e9b7/doc/api/pymongo/errors.rst000066400000000000000000000003461462766011000245140ustar00rootroot00000000000000:mod:`errors` -- Exceptions raised by the :mod:`pymongo` package ================================================================ .. automodule:: pymongo.errors :synopsis: Exceptions raised by the pymongo package :members: mongodb-mongo-python-driver-509e9b7/doc/api/pymongo/event_loggers.rst000066400000000000000000000003261462766011000260410ustar00rootroot00000000000000:mod:`event_loggers` -- Example loggers =========================================== .. automodule:: pymongo.event_loggers :synopsis: A collection of simple listeners for monitoring driver events. :members: mongodb-mongo-python-driver-509e9b7/doc/api/pymongo/index.rst000066400000000000000000000020471462766011000243070ustar00rootroot00000000000000:mod:`pymongo` -- Python driver for MongoDB =========================================== .. automodule:: pymongo :synopsis: Python driver for MongoDB .. autodata:: version .. data:: MongoClient Alias for :class:`pymongo.mongo_client.MongoClient`. .. data:: ReadPreference Alias for :class:`pymongo.read_preferences.ReadPreference`. .. autofunction:: has_c .. data:: MIN_SUPPORTED_WIRE_VERSION The minimum wire protocol version PyMongo supports. .. data:: MAX_SUPPORTED_WIRE_VERSION The maximum wire protocol version PyMongo supports. .. autofunction:: timeout Sub-modules: .. toctree:: :maxdepth: 2 auth_oidc change_stream client_options client_session collation collection command_cursor cursor database driver_info encryption encryption_options errors mongo_client monitoring operations pool read_concern read_preferences results server_api server_description topology_description uri_parser write_concern event_loggers mongodb-mongo-python-driver-509e9b7/doc/api/pymongo/mongo_client.rst000066400000000000000000000026261462766011000256600ustar00rootroot00000000000000:mod:`mongo_client` -- Tools for connecting to MongoDB ====================================================== .. automodule:: pymongo.mongo_client :synopsis: Tools for connecting to MongoDB .. autoclass:: pymongo.mongo_client.MongoClient(host='localhost', port=27017, document_class=dict, tz_aware=False, connect=True, **kwargs) .. automethod:: close .. describe:: c[db_name] || c.db_name Get the `db_name` :class:`~pymongo.database.Database` on :class:`MongoClient` `c`. Raises :class:`~pymongo.errors.InvalidName` if an invalid database name is used. .. autoattribute:: topology_description .. autoattribute:: address .. autoattribute:: primary .. autoattribute:: secondaries .. autoattribute:: arbiters .. autoattribute:: is_primary .. autoattribute:: is_mongos .. autoattribute:: nodes .. autoattribute:: codec_options .. autoattribute:: read_preference .. autoattribute:: write_concern .. autoattribute:: read_concern .. autoattribute:: options .. automethod:: start_session .. automethod:: list_databases .. automethod:: list_database_names .. automethod:: drop_database .. automethod:: get_default_database .. automethod:: get_database .. automethod:: server_info .. automethod:: watch .. automethod:: __getitem__ .. automethod:: __getattr__ mongodb-mongo-python-driver-509e9b7/doc/api/pymongo/monitoring.rst000066400000000000000000000050461462766011000253670ustar00rootroot00000000000000:mod:`monitoring` -- Tools for monitoring driver events. ======================================================== .. automodule:: pymongo.monitoring :synopsis: Tools for monitoring driver events. .. autofunction:: register(listener) .. autoclass:: CommandListener :members: :inherited-members: .. autoclass:: ServerListener :members: :inherited-members: .. autoclass:: ServerHeartbeatListener :members: :inherited-members: .. autoclass:: TopologyListener :members: :inherited-members: .. autoclass:: ConnectionPoolListener :members: :inherited-members: .. autoclass:: CommandStartedEvent :members: :inherited-members: .. autoclass:: CommandSucceededEvent :members: :inherited-members: .. autoclass:: CommandFailedEvent :members: :inherited-members: .. autoclass:: ServerDescriptionChangedEvent :members: :inherited-members: .. autoclass:: ServerOpeningEvent :members: :inherited-members: .. autoclass:: ServerClosedEvent :members: :inherited-members: .. autoclass:: TopologyDescriptionChangedEvent :members: :inherited-members: .. autoclass:: TopologyOpenedEvent :members: :inherited-members: .. autoclass:: TopologyClosedEvent :members: :inherited-members: .. autoclass:: ServerHeartbeatStartedEvent :members: :inherited-members: .. autoclass:: ServerHeartbeatSucceededEvent :members: :inherited-members: .. autoclass:: ServerHeartbeatFailedEvent :members: :inherited-members: .. autoclass:: PoolCreatedEvent :members: :inherited-members: .. autoclass:: PoolClearedEvent :members: :inherited-members: .. autoclass:: PoolClosedEvent :members: :inherited-members: .. autoclass:: ConnectionCreatedEvent :members: :inherited-members: .. autoclass:: ConnectionReadyEvent :members: :inherited-members: .. autoclass:: ConnectionClosedReason :members: .. autoclass:: ConnectionClosedEvent :members: :inherited-members: .. autoclass:: ConnectionCheckOutStartedEvent :members: :inherited-members: .. autoclass:: ConnectionCheckOutFailedReason :members: .. autoclass:: ConnectionCheckOutFailedEvent :members: :inherited-members: .. autoclass:: ConnectionCheckedOutEvent :members: :inherited-members: .. autoclass:: ConnectionCheckedInEvent :members: :inherited-members: mongodb-mongo-python-driver-509e9b7/doc/api/pymongo/operations.rst000066400000000000000000000002751462766011000253640ustar00rootroot00000000000000:mod:`operations` -- Operation class definitions ================================================ .. automodule:: pymongo.operations :synopsis: Operation class definitions :members: mongodb-mongo-python-driver-509e9b7/doc/api/pymongo/pool.rst000066400000000000000000000003251462766011000241460ustar00rootroot00000000000000:mod:`pool` -- Pool module for use with a MongoDB client. ============================================================== .. automodule:: pymongo.pool .. autoclass:: pymongo.pool.PoolOptions() :members: mongodb-mongo-python-driver-509e9b7/doc/api/pymongo/read_concern.rst000066400000000000000000000003651462766011000256230ustar00rootroot00000000000000:mod:`read_concern` -- Tools for working with read concern. =========================================================== .. automodule:: pymongo.read_concern :synopsis: Tools for working with read concern. :members: :inherited-members: mongodb-mongo-python-driver-509e9b7/doc/api/pymongo/read_preferences.rst000066400000000000000000000021411462766011000264670ustar00rootroot00000000000000:mod:`read_preferences` -- Utilities for choosing which member of a replica set to read from. ============================================================================================= .. automodule:: pymongo.read_preferences :synopsis: Utilities for choosing which member of a replica set to read from. .. autoclass:: pymongo.read_preferences.Primary .. max_staleness, min_wire_version, mongos_mode, and tag_sets don't make sense for Primary. .. autoattribute:: document .. autoattribute:: mode .. autoattribute:: name .. autoclass:: pymongo.read_preferences.PrimaryPreferred :inherited-members: .. autoclass:: pymongo.read_preferences.Secondary :inherited-members: .. autoclass:: pymongo.read_preferences.SecondaryPreferred :inherited-members: .. autoclass:: pymongo.read_preferences.Nearest :inherited-members: .. autoclass:: ReadPreference .. autoattribute:: PRIMARY .. autoattribute:: PRIMARY_PREFERRED .. autoattribute:: SECONDARY .. autoattribute:: SECONDARY_PREFERRED .. autoattribute:: NEAREST mongodb-mongo-python-driver-509e9b7/doc/api/pymongo/results.rst000066400000000000000000000003021462766011000246710ustar00rootroot00000000000000:mod:`results` -- Result class definitions ========================================== .. automodule:: pymongo.results :synopsis: Result class definitions :members: :inherited-members: mongodb-mongo-python-driver-509e9b7/doc/api/pymongo/server_api.rst000066400000000000000000000005031462766011000253320ustar00rootroot00000000000000:mod:`server_api` -- Support for MongoDB Stable API ====================================================== .. automodule:: pymongo.server_api :synopsis: Support for MongoDB Stable API .. autoclass:: pymongo.server_api.ServerApi :members: .. autoclass:: pymongo.server_api.ServerApiVersion :members: mongodb-mongo-python-driver-509e9b7/doc/api/pymongo/server_description.rst000066400000000000000000000005041462766011000271050ustar00rootroot00000000000000:orphan: :mod:`server_description` -- An object representation of a server the driver is connected to. ============================================================================================= .. automodule:: pymongo.server_description .. autoclass:: pymongo.server_description.ServerDescription() :members: mongodb-mongo-python-driver-509e9b7/doc/api/pymongo/topology_description.rst000066400000000000000000000005061462766011000274550ustar00rootroot00000000000000:orphan: :mod:`topology_description` -- An object representation of a deployment of MongoDB servers. =========================================================================================== .. automodule:: pymongo.topology_description .. autoclass:: pymongo.topology_description.TopologyDescription() :members: mongodb-mongo-python-driver-509e9b7/doc/api/pymongo/uri_parser.rst000066400000000000000000000003501462766011000253460ustar00rootroot00000000000000:mod:`uri_parser` -- Tools to parse and validate a MongoDB URI ============================================================== .. automodule:: pymongo.uri_parser :synopsis: Tools to parse and validate a MongoDB URI. :members: mongodb-mongo-python-driver-509e9b7/doc/api/pymongo/write_concern.rst000066400000000000000000000003341462766011000260360ustar00rootroot00000000000000:mod:`write_concern` -- Tools for specifying write concern ========================================================== .. automodule:: pymongo.write_concern :synopsis: Tools for specifying write concern. :members: mongodb-mongo-python-driver-509e9b7/doc/atlas.rst000066400000000000000000000034041462766011000220410ustar00rootroot00000000000000Using PyMongo with MongoDB Atlas ================================ `Atlas `_ is MongoDB, Inc.'s hosted MongoDB as a service offering. To connect to Atlas, pass the connection string provided by Atlas to :class:`~pymongo.mongo_client.MongoClient`:: client = pymongo.MongoClient() Connections to Atlas require TLS/SSL. .. warning:: Industry best practices recommend, and some regulations require, the use of TLS 1.1 or newer. Though no application changes are required for PyMongo to make use of the newest protocols, some operating systems or versions may not provide an OpenSSL version new enough to support them. Users of macOS older than 10.13 (High Sierra) will need to install Python from `python.org`_, `homebrew`_, `macports`_, or another similar source. Users of Linux or other non-macOS Unix can check their OpenSSL version like this:: $ openssl version If the version number is less than 1.0.1 support for TLS 1.1 or newer is not available. Contact your operating system vendor for a solution or upgrade to a newer distribution. You can check your Python interpreter by installing the `requests`_ module and executing the following command:: python -c "import requests; print(requests.get('https://www.howsmyssl.com/a/check', verify=False).json()['tls_version'])" You should see "TLS 1.X" where X is >= 1. You can read more about TLS versions and their security implications here: ``_ .. _python.org: https://www.python.org/downloads/ .. _homebrew: https://brew.sh/ .. _macports: https://www.macports.org/ .. _requests: https://pypi.python.org/pypi/requests mongodb-mongo-python-driver-509e9b7/doc/changelog.rst000066400000000000000000005333051462766011000226740ustar00rootroot00000000000000Changelog ========= Changes in Version 4.7.3 ------------------------- Version 4.7.3 has further fixes for lazily loading modules. - Use deferred imports instead of importlib lazy module loading. - Improve import time on Windows. - Reduce verbosity of "Waiting for suitable server to become available" log message from info to debug. Issues Resolved ............... See the `PyMongo 4.7.3 release notes in JIRA`_ for the list of resolved issues in this release. .. _PyMongo 4.7.3 release notes in JIRA: https://jira.mongodb.org/secure/ReleaseNote.jspa?projectId=10004&version=39865 Changes in Version 4.7.2 ------------------------- Version 4.7.2 fixes a bug introduced in 4.7.0: - Fixed a bug where PyMongo could not be used with the Nuitka compiler. Issues Resolved ............... See the `PyMongo 4.7.2 release notes in JIRA`_ for the list of resolved issues in this release. .. _PyMongo 4.7.2 release notes in JIRA: https://jira.mongodb.org/secure/ReleaseNote.jspa?projectId=10004&version=39710 Changes in Version 4.7.1 ------------------------- Version 4.7.1 fixes a bug introduced in 4.7.0: - Fixed a bug where PyMongo would cause an ``AttributeError`` if ``dns.resolver`` was imported and referenced after PyMongo was imported. - Clarified the behavior of the ``TOKEN_RESOURCE`` auth mechanism property for ``MONGODB-OIDC``. Issues Resolved ............... See the `PyMongo 4.7.1 release notes in JIRA`_ for the list of resolved issues in this release. .. _PyMongo 4.7.1 release notes in JIRA: https://jira.mongodb.org/secure/ReleaseNote.jspa?projectId=10004&version=39680 Changes in Version 4.7 ------------------------ PyMongo 4.7 brings a number of improvements including: - Added support for ``MONGODB-OIDC`` authentication. The MONGODB-OIDC mechanism authenticates using an OpenID Connect (OIDC) access token. The driver supports OIDC for workload identity, defined as an identity you assign to a software workload (such as an application, service, script, or container) to authenticate and access other services and resources. Please see :doc:`examples/authentication` for more information. - Added support for Python's `native logging library `_, enabling developers to customize the verbosity of log messages for their applications. Please see :doc:`examples/logging` for more information. - Significantly improved the performance of encoding BSON documents to JSON. - Added support for named KMS providers for client side field level encryption. Previously supported KMS providers were only: aws, azure, gcp, kmip, and local. The KMS provider is now expanded to support name suffixes (e.g. local:myname). Named KMS providers enables more than one of each KMS provider type to be configured. See the docstring for :class:`~pymongo.encryption_options.AutoEncryptionOpts`. Note that named KMS providers requires pymongocrypt >=1.9 and libmongocrypt >=1.9. - Added the :class:`pymongo.hello.Hello.connection_id`, :attr:`pymongo.monitoring.CommandStartedEvent.server_connection_id`, :attr:`pymongo.monitoring.CommandSucceededEvent.server_connection_id`, and :attr:`pymongo.monitoring.CommandFailedEvent.server_connection_id` properties. - Fixed a bug where inflating a :class:`~bson.raw_bson.RawBSONDocument` containing a :class:`~bson.code.Code` would cause an error. - :meth:`~pymongo.encryption.ClientEncryption.encrypt` and :meth:`~pymongo.encryption.ClientEncryption.encrypt_expression` now allow ``key_id`` to be passed in as a :class:`uuid.UUID`. - Fixed a bug where :class:`~bson.int64.Int64` instances could not always be encoded by `orjson`_. The following now works:: >>> import orjson >>> from bson import json_util >>> orjson.dumps({'a': Int64(1)}, default=json_util.default, option=orjson.OPT_PASSTHROUGH_SUBCLASS) .. _orjson: https://github.com/ijl/orjson - Fixed a bug appearing in Python 3.12 where "RuntimeError: can't create new thread at interpreter shutdown" could be written to stderr when a MongoClient's thread starts as the python interpreter is shutting down. - Added a warning when connecting to DocumentDB and CosmosDB clusters. For more information regarding feature compatibility and support please visit `mongodb.com/supportability/documentdb `_ and `mongodb.com/supportability/cosmosdb `_. - Added the :attr:`pymongo.monitoring.ConnectionCheckedOutEvent.duration`, :attr:`pymongo.monitoring.ConnectionCheckOutFailedEvent.duration`, and :attr:`pymongo.monitoring.ConnectionReadyEvent.duration` properties. - Added the ``type`` and ``kwargs`` arguments to :class:`~pymongo.operations.SearchIndexModel` to enable creating vector search indexes in MongoDB Atlas. - Fixed a bug where ``read_concern`` and ``write_concern`` were improperly added to :meth:`~pymongo.collection.Collection.list_search_indexes` queries. - Deprecated :attr:`pymongo.write_concern.WriteConcern.wtimeout` and :attr:`pymongo.mongo_client.MongoClient.wTimeoutMS`. Use :meth:`~pymongo.timeout` instead. .. warning:: PyMongo depends on ``dnspython``, which released version 2.6.1 with a fix for `CVE-2023-29483 `_. We do not explicitly require that version, but we strongly recommend that you install at least that version in your environment. Unavoidable breaking changes ............................ - Replaced usage of :class:`bson.son.SON` on all internal classes and commands to dict, :attr:`options.pool_options.metadata` is now of type ``dict`` as opposed to :class:`bson.son.SON`. Here's some examples of how this changes expected output as well as how to convert from :class:`dict` to :class:`bson.son.SON`:: # Before >>> from pymongo import MongoClient >>> client = MongoClient() >>> client.options.pool_options.metadata SON([('driver', SON([('name', 'PyMongo'), ('version', '4.7.0.dev0')])), ('os', SON([('type', 'Darwin'), ('name', 'Darwin'), ('architecture', 'arm64'), ('version', '14.3')])), ('platform', 'CPython 3.11.6.final.0')]) # After >>> client.options.pool_options.metadata {'driver': {'name': 'PyMongo', 'version': '4.7.0.dev0'}, 'os': {'type': 'Darwin', 'name': 'Darwin', 'architecture': 'arm64', 'version': '14.3'}, 'platform': 'CPython 3.11.6.final.0'} # To convert from dict to SON # This will only convert the first layer of the dictionary >>> data_as_dict = client.options.pool_options.metadata >>> SON(data_as_dict) SON([('driver', {'name': 'PyMongo', 'version': '4.7.0.dev0'}), ('os', {'type': 'Darwin', 'name': 'Darwin', 'architecture': 'arm64', 'version': '14.3'}), ('platform', 'CPython 3.11.6.final.0')]) # To convert from dict to SON on a nested dictionary >>> def dict_to_SON(data_as_dict: dict[Any, Any]): ... data_as_SON = SON() ... for key, value in data_as_dict.items(): ... data_as_SON[key] = dict_to_SON(value) if isinstance(value, dict) else value ... return data_as_SON >>> >>> dict_to_SON(data_as_dict) SON([('driver', SON([('name', 'PyMongo'), ('version', '4.7.0.dev0')])), ('os', SON([('type', 'Darwin'), ('name', 'Darwin'), ('architecture', 'arm64'), ('version', '14.3')])), ('platform', 'CPython 3.11.6.final.0')]) - PyMongo now uses `lazy imports `_ for external dependencies. If you are relying on any kind of monkey-patching of the standard library, you may need to explicitly import those external libraries in addition to ``pymongo`` before applying the patch. Note that we test with ``gevent`` and ``eventlet`` patching, and those continue to work. - The "aws" extra now requires minimum version of ``1.1.0`` for ``pymongo_auth_aws``. Changes in Version 4.6.3 ------------------------ PyMongo 4.6.3 fixes the following bug: - Fixed a potential memory access violation when decoding invalid bson. Issues Resolved ............... See the `PyMongo 4.6.3 release notes in JIRA`_ for the list of resolved issues in this release. .. _PyMongo 4.6.3 release notes in JIRA: https://jira.mongodb.org/secure/ReleaseNote.jspa?projectId=10004&version=38360 Changes in Version 4.6.2 ------------------------ PyMongo 4.6.2 fixes the following bug: - Fixed a bug appearing in Python 3.12 where "RuntimeError: can't create new thread at interpreter shutdown" could be written to stderr when a MongoClient's thread starts as the python interpreter is shutting down. Issues Resolved ............... See the `PyMongo 4.6.2 release notes in JIRA`_ for the list of resolved issues in this release. .. _PyMongo 4.6.2 release notes in JIRA: https://jira.mongodb.org/secure/ReleaseNote.jspa?projectId=10004&version=37906 Changes in Version 4.6.1 ------------------------ PyMongo 4.6.1 fixes the following bug: - Ensure retryable read ``OperationFailure`` errors re-raise exception when 0 or NoneType error code is provided. Issues Resolved ............... See the `PyMongo 4.6.1 release notes in JIRA`_ for the list of resolved issues in this release. .. _PyMongo 4.6.1 release notes in JIRA: https://jira.mongodb.org/secure/ReleaseNote.jspa?projectId=10004&version=37138 Changes in Version 4.6 ---------------------- PyMongo 4.6 brings a number of improvements including: - Added the ``serverMonitoringMode`` URI and keyword argument to :class:`~pymongo.mongo_client.MongoClient`. - Improved client performance and reduced connection requirements in Function-as-a-service (FaaS) environments like AWS Lambda, Google Cloud Functions, and Microsoft Azure Functions. - Added the :attr:`pymongo.monitoring.CommandSucceededEvent.database_name` property. - Added the :attr:`pymongo.monitoring.CommandFailedEvent.database_name` property. - Allow passing a ``dict`` to sort/create_index/hint. - Added :func:`repr` support to the write result classes: :class:`~pymongo.results.BulkWriteResult`, :class:`~pymongo.results.DeleteResult`, :class:`~pymongo.results.InsertManyResult`, :class:`~pymongo.results.InsertOneResult`, :class:`~pymongo.results.UpdateResult`, and :class:`~pymongo.encryption.RewrapManyDataKeyResult`. For example: >>> client.t.t.insert_one({}) InsertOneResult(ObjectId('65319acdd55bb3a27ab5502b'), acknowledged=True) >>> client.t.t.insert_many([{} for _ in range(3)]) InsertManyResult([ObjectId('6532f85e826f2b6125d6ce39'), ObjectId('6532f85e826f2b6125d6ce3a'), ObjectId('6532f85e826f2b6125d6ce3b')], acknowledged=True) - :meth:`~pymongo.uri_parser.parse_uri` now considers the delimiting slash (``/``) between hosts and connection options optional. For example, "mongodb://example.com?tls=true" is now a valid URI. - Fixed a bug where PyMongo would incorrectly promote all cursors to exhaust cursors when connected to load balanced MongoDB clusters or Serverless clusters. - Added the :ref:`network-compression-example` documentation page. - Added more timeout information to network errors. Issues Resolved ............... See the `PyMongo 4.6 release notes in JIRA`_ for the list of resolved issues in this release. .. _PyMongo 4.6 release notes in JIRA: https://jira.mongodb.org/secure/ReleaseNote.jspa?projectId=10004&version=36542 Changes in Version 4.5 ---------------------- PyMongo 4.5 brings a number of improvements including: - Added new helper methods for Atlas Search Index (requires MongoDB Server 7.0+): :meth:`~pymongo.collection.Collection.list_search_indexes`, :meth:`~pymongo.collection.Collection.create_search_index`, :meth:`~pymongo.collection.Collection.create_search_indexes`, :meth:`~pymongo.collection.Collection.drop_search_index`, :meth:`~pymongo.collection.Collection.update_search_index` - Added :meth:`~pymongo.database.Database.cursor_command` and :meth:`~pymongo.command_cursor.CommandCursor.try_next` to support executing an arbitrary command that returns a cursor. - ``cryptography`` 2.5 or later is now required for :ref:`OCSP` support. - Improved bson encoding and decoding performance by up to 134%(`PYTHON-3729`_, `PYTHON-3797`_, `PYTHON-3816`_, `PYTHON-3817`_, `PYTHON-3820`_, `PYTHON-3824`_, and `PYTHON-3846`_). .. warning:: PyMongo no longer supports PyPy3 versions older than 3.8. Users must upgrade to PyPy3.8+. Issues Resolved ............... See the `PyMongo 4.5 release notes in JIRA`_ for the list of resolved issues in this release. .. _PyMongo 4.5 release notes in JIRA: https://jira.mongodb.org/secure/ReleaseNote.jspa?projectId=10004&version=35492 .. _PYTHON-3729: https://jira.mongodb.org/browse/PYTHON-3729 .. _PYTHON-3797: https://jira.mongodb.org/browse/PYTHON-3797 .. _PYTHON-3816: https://jira.mongodb.org/browse/PYTHON-3816 .. _PYTHON-3817: https://jira.mongodb.org/browse/PYTHON-3817 .. _PYTHON-3820: https://jira.mongodb.org/browse/PYTHON-3820 .. _PYTHON-3824: https://jira.mongodb.org/browse/PYTHON-3824 .. _PYTHON-3846: https://jira.mongodb.org/browse/PYTHON-3846 Changes in Version 4.4.1 ------------------------ Version 4.4.1 fixes the following bugs: - Fixed a bug where pymongo would raise a ``ConfigurationError: Invalid SRV host`` error when connecting to a "mongodb+srv://" URI that included capital letters in the SRV hosts returned from DNS. (`PYTHON-3800`_). - Fixed a minor reference counting bug in the C extension (`PYTHON-3798`_). Issues Resolved ............... See the `PyMongo 4.4.1 release notes in JIRA`_ for the list of resolved issues in this release. .. _PYTHON-3798: https://jira.mongodb.org/browse/PYTHON-3798 .. _PYTHON-3800: https://jira.mongodb.org/browse/PYTHON-3800 .. _PyMongo 4.4.1 release notes in JIRA: https://jira.mongodb.org/secure/ReleaseNote.jspa?projectId=10004&version=36329 Changes in Version 4.4 ----------------------- PyMongo 4.4 brings a number of improvements including: - Added support for MongoDB 7.0. - Added support for Python 3.11. - Added support for passing a list containing (key, direction) pairs or keys to :meth:`~pymongo.collection.Collection.create_index`. - Improved bson encoding performance (`PYTHON-3717`_ and `PYTHON-3718`_). - Improved support for Pyright to improve typing support for IDEs like Visual Studio Code or Visual Studio. - Improved support for type-checking with MyPy "strict" mode (`--strict`). - Added :meth:`~pymongo.encryption.ClientEncryption.create_encrypted_collection`, :class:`~pymongo.errors.EncryptedCollectionError`, :meth:`~pymongo.encryption.ClientEncryption.encrypt_expression`, :class:`~pymongo.encryption_options.RangeOpts`, and :attr:`~pymongo.encryption.Algorithm.RANGEPREVIEW` as part of the experimental Queryable Encryption beta. - pymongocrypt 1.6.0 or later is now required for :ref:`In-Use Encryption` support. MongoDB Server 7.0 introduced a backwards breaking change to the QE protocol. Users taking advantage of the Queryable Encryption beta must now upgrade to MongoDB 7.0+ and PyMongo 4.4+. - Previously, PyMongo's docs recommended using :meth:`datetime.datetime.utcnow` and :meth:`datetime.datetime.utcfromtimestamp`. utcnow and utcfromtimestamp are deprecated in Python 3.12, for reasons explained `in this Github issue`_. Instead, users should use :meth:`datetime.datetime.now(tz=timezone.utc)` and :meth:`datetime.datetime.fromtimestamp(tz=timezone.utc)` instead. .. _in this Github issue: https://github.com/python/cpython/issues/103857 Issues Resolved ............... See the `PyMongo 4.4 release notes in JIRA`_ for the list of resolved issues in this release. .. _PyMongo 4.4 release notes in JIRA: https://jira.mongodb.org/secure/ReleaseNote.jspa?projectId=10004&version=34354 .. _PYTHON-3717: https://jira.mongodb.org/browse/PYTHON-3717 .. _PYTHON-3718: https://jira.mongodb.org/browse/PYTHON-3718 Changes in Version 4.3.3 ------------------------ Version 4.3.3 documents support for the following: - :ref:`CSFLE on-demand credentials` for cloud KMS providers. - Authentication support for :ref:`EKS Clusters`. - Added the :ref:`timeout-example` example page to improve the documentation for :func:`pymongo.timeout`. Bug Fixes ......... - Fixed a performance regression in :meth:`~gridfs.GridFSBucket.download_to_stream` and :meth:`~gridfs.GridFSBucket.download_to_stream_by_name` by reading in chunks instead of line by line (`PYTHON-3502`_). - Improved performance of :meth:`gridfs.grid_file.GridOut.read` and :meth:`gridfs.grid_file.GridOut.readline` (`PYTHON-3508`_). Issues Resolved ............... See the `PyMongo 4.3.3 release notes in JIRA`_ for the list of resolved issues in this release. .. _PYTHON-3502: https://jira.mongodb.org/browse/PYTHON-3502 .. _PYTHON-3508: https://jira.mongodb.org/browse/PYTHON-3508 .. _PyMongo 4.3.3 release notes in JIRA: https://jira.mongodb.org/secure/ReleaseNote.jspa?projectId=10004&version=34709 Changes in Version 4.3 (4.3.2) ------------------------------ Note: We withheld uploading tags 4.3.0 and 4.3.1 to PyPI due to a version handling error and a necessary documentation update. `dnspython `_ is now a required dependency. This change makes PyMongo easier to install for use with "mongodb+srv://" connection strings and `MongoDB Atlas `_. PyMongo 4.3 brings a number of improvements including: - Added support for decoding BSON datetimes outside of the range supported by Python's :class:`~datetime.datetime` builtin. See :ref:`handling-out-of-range-datetimes` for examples, as well as :class:`bson.datetime_ms.DatetimeMS`, :class:`bson.codec_options.DatetimeConversion`, and :class:`bson.codec_options.CodecOptions`'s ``datetime_conversion`` parameter for more details (`PYTHON-1824`_). - PyMongo now resets its locks and other shared state in the child process after a :py:func:`os.fork` to reduce the frequency of deadlocks. Note that deadlocks are still possible because libraries that PyMongo depends like OpenSSL cannot be made fork() safe in multithreaded applications. (`PYTHON-2484`_). For more info see :ref:`pymongo-fork-safe`. - When used with MongoDB 6.0+, :class:`~pymongo.change_stream.ChangeStream` s now allow for new types of events (such as DDL and C2C replication events) to be recorded with the new parameter ``show_expanded_events`` that can be passed to methods such as :meth:`~pymongo.collection.Collection.watch`. - PyMongo now internally caches AWS credentials that it fetches from AWS endpoints, to avoid rate limitations. The cache is cleared when the credentials expire or an error is encountered. - When using the ``MONGODB-AWS`` authentication mechanism with the ``aws`` extra, the behavior of credential fetching has changed with ``pymongo_auth_aws>=1.1.0``. Please see :doc:`examples/authentication` for more information. Bug fixes ......... - Fixed a bug where :class:`~pymongo.change_stream.ChangeStream` would allow an app to retry calling ``next()`` or ``try_next()`` even after non-resumable errors (`PYTHON-3389`_). - Fixed a bug where the client could be unable to discover the new primary after a simultaneous replica set election and reconfig (`PYTHON-2970`_). Issues Resolved ............... See the `PyMongo 4.3 release notes in JIRA`_ for the list of resolved issues in this release. .. _PYTHON-1824: https://jira.mongodb.org/browse/PYTHON-1824 .. _PYTHON-2484: https://jira.mongodb.org/browse/PYTHON-2484 .. _PYTHON-2970: https://jira.mongodb.org/browse/PYTHON-2970 .. _PYTHON-3389: https://jira.mongodb.org/browse/PYTHON-3389 .. _PyMongo 4.3 release notes in JIRA: https://jira.mongodb.org/secure/ReleaseNote.jspa?projectId=10004&version=33425 Changes in Version 4.2 ---------------------- .. warning:: PyMongo 4.2 drops support for Python 3.6: Python 3.7+ is now required. PyMongo 4.2 brings a number of improvements including: - Support for MongoDB 6.0. - Support for the Queryable Encryption beta with MongoDB 6.0. Note that backwards-breaking changes may be made before the final release. See :ref:`automatic-queryable-client-side-encryption` for example usage. - Provisional (beta) support for :func:`pymongo.timeout` to apply a single timeout to an entire block of pymongo operations. See :ref:`timeout-example` for examples. - Added the ``timeoutMS`` URI and keyword argument to :class:`~pymongo.mongo_client.MongoClient`. - Added the :attr:`pymongo.errors.PyMongoError.timeout` property which is ``True`` when the error was caused by a timeout. - Added the ``check_exists`` argument to :meth:`~pymongo.database.Database.create_collection` that when True (the default) runs an additional ``listCollections`` command to verify that the collection does not exist already. - Added the following key management APIs to :class:`~pymongo.encryption.ClientEncryption`: - :meth:`~pymongo.encryption.ClientEncryption.get_key` - :meth:`~pymongo.encryption.ClientEncryption.get_keys` - :meth:`~pymongo.encryption.ClientEncryption.delete_key` - :meth:`~pymongo.encryption.ClientEncryption.add_key_alt_name` - :meth:`~pymongo.encryption.ClientEncryption.get_key_by_alt_name` - :meth:`~pymongo.encryption.ClientEncryption.remove_key_alt_name` - :meth:`~pymongo.encryption.ClientEncryption.rewrap_many_data_key` - :class:`~pymongo.encryption.RewrapManyDataKeyResult` - Support for the ``crypt_shared`` library to replace ``mongocryptd`` using the new ``crypt_shared_lib_path`` and ``crypt_shared_lib_required`` arguments to :class:`~pymongo.encryption_options.AutoEncryptionOpts`. Bug fixes ......... - Fixed a bug where :meth:`~pymongo.collection.Collection.estimated_document_count` would fail with a "CommandNotSupportedOnView" error on views (`PYTHON-2885`_). - Fixed a bug where invalid UTF-8 strings could be passed as patterns for :class:`~bson.regex.Regex` objects. :func:`bson.encode` now correctly raises :class:`bson.errors.InvalidStringData` (`PYTHON-3048`_). - Fixed a bug that caused ``AutoReconnect("connection pool paused")`` errors in the child process after fork (`PYTHON-3257`_). - Fixed a bug where :meth:`~pymongo.collection.Collection.count_documents` and :meth:`~pymongo.collection.Collection.distinct` would fail in a transaction with ``directConnection=True`` (`PYTHON-3333`_). - GridFS no longer uploads an incomplete files collection document after encountering an error in the middle of an upload fork. This results in fewer :class:`~gridfs.errors.CorruptGridFile` errors (`PYTHON-1552`_). - Renamed PyMongo's internal C extension methods to avoid crashing due to name conflicts with mpi4py and other shared libraries (`PYTHON-2110`_). - Fixed tight CPU loop for network I/O when using PyOpenSSL (`PYTHON-3187`_). Unavoidable breaking changes ............................ - pymongocrypt 1.3.0 or later is now required for client side field level encryption support. - :meth:`~pymongo.collection.Collection.estimated_document_count` now always uses the `count`_ command. Due to an oversight in versions 5.0.0-5.0.8 of MongoDB, the count command was not included in V1 of the :ref:`versioned-api-ref`. Users of the Stable API with estimated_document_count are recommended to upgrade their server version to 5.0.9+ or set :attr:`pymongo.server_api.ServerApi.strict` to ``False`` to avoid encountering errors (`PYTHON-3167`_). - Removed generic typing from :class:`~pymongo.client_session.ClientSession` to improve support for Pyright (`PYTHON-3283`_). - Added ``__all__`` to the bson, pymongo, and gridfs packages. This could be a breaking change for apps that relied on ``from bson import *`` to import APIs not present in ``__all__`` (`PYTHON-3311`_). .. _count: https://mongodb.com/docs/manual/reference/command/count/ Issues Resolved ............... See the `PyMongo 4.2 release notes in JIRA`_ for the list of resolved issues in this release. .. _PYTHON-3048: https://jira.mongodb.org/browse/PYTHON-3048 .. _PYTHON-2885: https://jira.mongodb.org/browse/PYTHON-2885 .. _PYTHON-3167: https://jira.mongodb.org/browse/PYTHON-3167 .. _PYTHON-3257: https://jira.mongodb.org/browse/PYTHON-3257 .. _PYTHON-3333: https://jira.mongodb.org/browse/PYTHON-3333 .. _PYTHON-1552: https://jira.mongodb.org/browse/PYTHON-1552 .. _PYTHON-2110: https://jira.mongodb.org/browse/PYTHON-2110 .. _PYTHON-3283: https://jira.mongodb.org/browse/PYTHON-3283 .. _PYTHON-3311: https://jira.mongodb.org/browse/PYTHON-3311 .. _PYTHON-3187: https://jira.mongodb.org/browse/PYTHON-3187 .. _PyMongo 4.2 release notes in JIRA: https://jira.mongodb.org/secure/ReleaseNote.jspa?projectId=10004&version=33196 Changes in Version 4.1.1 ------------------------- Version 4.1.1 fixes a number of bugs: - Fixed a memory leak bug when calling :func:`~bson.decode_all` without a ``codec_options`` argument (`PYTHON-3222`_). - Fixed a bug where :func:`~bson.decode_all` did not accept ``codec_options`` as a keyword argument (`PYTHON-3222`_). - Fixed an oversight where type markers (py.typed files) were not included in our release distributions (`PYTHON-3214`_). - Fixed a bug where pymongo would raise a "NameError: name sys is not defined" exception when attempting to parse a "mongodb+srv://" URI when the dnspython dependency was not installed (`PYTHON-3198`_). Issues Resolved ............... See the `PyMongo 4.1.1 release notes in JIRA`_ for the list of resolved issues in this release. .. _PYTHON-3198: https://jira.mongodb.org/browse/PYTHON-3198 .. _PYTHON-3214: https://jira.mongodb.org/browse/PYTHON-3214 .. _PYTHON-3222: https://jira.mongodb.org/browse/PYTHON-3222 .. _PyMongo 4.1.1 release notes in JIRA: https://jira.mongodb.org/secure/ReleaseNote.jspa?projectId=10004&version=33290 Changes in Version 4.1 ---------------------- .. warning:: PyMongo 4.1 drops support for Python 3.6.0 and 3.6.1, Python 3.6.2+ is now required. PyMongo 4.1 brings a number of improvements including: - Type Hinting support (formerly provided by `pymongo-stubs`_). See :doc:`examples/type_hints` for more information. - Added support for the ``comment`` parameter to all helpers. For example see :meth:`~pymongo.collection.Collection.insert_one`. - Added support for the ``let`` parameter to :meth:`~pymongo.collection.Collection.update_one`, :meth:`~pymongo.collection.Collection.update_many`, :meth:`~pymongo.collection.Collection.delete_one`, :meth:`~pymongo.collection.Collection.delete_many`, :meth:`~pymongo.collection.Collection.replace_one`, :meth:`~pymongo.collection.Collection.aggregate`, :meth:`~pymongo.collection.Collection.find_one_and_delete`, :meth:`~pymongo.collection.Collection.find_one_and_replace`, :meth:`~pymongo.collection.Collection.find_one_and_update`, :meth:`~pymongo.collection.Collection.find`, :meth:`~pymongo.collection.Collection.find_one`, and :meth:`~pymongo.collection.Collection.bulk_write`. ``let`` is a map of parameter names and values. Parameters can then be accessed as variables in an aggregate expression context. - :meth:`~pymongo.collection.Collection.aggregate` now supports $merge and $out executing on secondaries on MongoDB >=5.0. aggregate() now always obeys the collection's :attr:`read_preference` on MongoDB >= 5.0. - :meth:`gridfs.grid_file.GridOut.seek` now returns the new position in the file, to conform to the behavior of :meth:`io.IOBase.seek`. - Improved reuse of implicit sessions (`PYTHON-2956`_). Bug fixes ......... - Fixed bug that would cause SDAM heartbeat timeouts and connection churn on AWS Lambda and other FaaS environments (`PYTHON-3186`_). - Fixed bug where :class:`~pymongo.mongo_client.MongoClient`, :class:`~pymongo.database.Database`, and :class:`~pymongo.collection.Collection` mistakenly implemented :class:`typing.Iterable` (`PYTHON-3084`_). Issues Resolved ............... See the `PyMongo 4.1 release notes in JIRA`_ for the list of resolved issues in this release. .. _PyMongo 4.1 release notes in JIRA: https://jira.mongodb.org/secure/ReleaseNote.jspa?projectId=10004&version=30619 .. _PYTHON-2956: https://jira.mongodb.org/browse/PYTHON-2956 .. _PYTHON-3084: https://jira.mongodb.org/browse/PYTHON-3084 .. _PYTHON-3186: https://jira.mongodb.org/browse/PYTHON-3186 .. _pymongo-stubs: https://github.com/mongodb-labs/pymongo-stubs Changes in Version 4.0 ---------------------- .. warning:: PyMongo 4.0 drops support for Python 2.7, 3.4, and 3.5. .. warning:: PyMongo 4.0 drops support for MongoDB 2.6, 3.0, 3.2, and 3.4. .. warning:: PyMongo 4.0 changes the default value of the ``directConnection`` URI option and keyword argument to :class:`~pymongo.mongo_client.MongoClient` to ``False`` instead of ``None``, allowing for the automatic discovery of replica sets. This means that if you want a direct connection to a single server you must pass ``directConnection=True`` as a URI option or keyword argument. For more details, see the relevant section of the PyMongo 4.x migration guide: :ref:`pymongo4-migration-direct-connection`. PyMongo 4.0 brings a number of improvements as well as some backward breaking changes. For example, all APIs deprecated in PyMongo 3.X have been removed. Be sure to read the changes listed below and the :doc:`migrate-to-pymongo4` before upgrading from PyMongo 3.x. Breaking Changes in 4.0 ....................... - Removed support for Python 2.7, 3.4, and 3.5. Python 3.6.2+ is now required. - The default uuid_representation for :class:`~bson.codec_options.CodecOptions`, :class:`~bson.json_util.JSONOptions`, and :class:`~pymongo.mongo_client.MongoClient` has been changed from :data:`bson.binary.UuidRepresentation.PYTHON_LEGACY` to :data:`bson.binary.UuidRepresentation.UNSPECIFIED`. Attempting to encode a :class:`uuid.UUID` instance to BSON or JSON now produces an error by default. See :ref:`handling-uuid-data-example` for details. - Removed the ``waitQueueMultiple`` keyword argument to :class:`~pymongo.mongo_client.MongoClient` and removed :exc:`pymongo.errors.ExceededMaxWaiters`. - Removed the ``socketKeepAlive`` keyword argument to :class:`~pymongo.mongo_client.MongoClient`. - Removed :meth:`pymongo.mongo_client.MongoClient.fsync`, :meth:`pymongo.mongo_client.MongoClient.unlock`, and :attr:`pymongo.mongo_client.MongoClient.is_locked`. - Removed :meth:`pymongo.mongo_client.MongoClient.database_names`. - Removed :attr:`pymongo.mongo_client.MongoClient.max_bson_size`. - Removed :attr:`pymongo.mongo_client.MongoClient.max_message_size`. - Removed :attr:`pymongo.mongo_client.MongoClient.max_write_batch_size`. - Removed :attr:`pymongo.mongo_client.MongoClient.event_listeners`. - Removed :attr:`pymongo.mongo_client.MongoClient.max_pool_size`. - Removed :attr:`pymongo.mongo_client.MongoClient.max_idle_time_ms`. - Removed :attr:`pymongo.mongo_client.MongoClient.local_threshold_ms`. - Removed :attr:`pymongo.mongo_client.MongoClient.server_selection_timeout`. - Removed :attr:`pymongo.mongo_client.MongoClient.retry_writes`. - Removed :attr:`pymongo.mongo_client.MongoClient.retry_reads`. - Removed :meth:`pymongo.database.Database.eval`, :data:`pymongo.database.Database.system_js` and :class:`pymongo.database.SystemJS`. - Removed :meth:`pymongo.database.Database.collection_names`. - Removed :meth:`pymongo.database.Database.current_op`. - Removed :meth:`pymongo.database.Database.authenticate` and :meth:`pymongo.database.Database.logout`. - Removed :meth:`pymongo.database.Database.error`, :meth:`pymongo.database.Database.last_status`, :meth:`pymongo.database.Database.previous_error`, :meth:`pymongo.database.Database.reset_error_history`. - Removed :meth:`pymongo.database.Database.add_user` and :meth:`pymongo.database.Database.remove_user`. - Removed support for database profiler helpers :meth:`~pymongo.database.Database.profiling_level`, :meth:`~pymongo.database.Database.set_profiling_level`, and :meth:`~pymongo.database.Database.profiling_info`. Instead, users should run the `profile command`_ with the :meth:`~pymongo.database.Database.command` helper directly. - Removed :attr:`pymongo.OFF`, :attr:`pymongo.SLOW_ONLY`, and :attr:`pymongo.ALL`. - Removed :meth:`pymongo.collection.Collection.parallel_scan`. - Removed :meth:`pymongo.collection.Collection.ensure_index`. - Removed :meth:`pymongo.collection.Collection.reindex`. - Removed :meth:`pymongo.collection.Collection.save`. - Removed :meth:`pymongo.collection.Collection.insert`. - Removed :meth:`pymongo.collection.Collection.update`. - Removed :meth:`pymongo.collection.Collection.remove`. - Removed :meth:`pymongo.collection.Collection.find_and_modify`. - Removed :meth:`pymongo.collection.Collection.count`. - Removed :meth:`pymongo.collection.Collection.initialize_ordered_bulk_op`, :meth:`pymongo.collection.Collection.initialize_unordered_bulk_op`, and :class:`pymongo.bulk.BulkOperationBuilder`. Use :meth:`pymongo.collection.Collection.bulk_write` instead. - Removed :meth:`pymongo.collection.Collection.group`. - Removed :meth:`pymongo.collection.Collection.map_reduce` and :meth:`pymongo.collection.Collection.inline_map_reduce`. - Removed the ``useCursor`` option for :meth:`~pymongo.collection.Collection.aggregate`. - Removed :meth:`pymongo.mongo_client.MongoClient.close_cursor`. Use :meth:`pymongo.cursor.Cursor.close` instead. - Removed :meth:`pymongo.mongo_client.MongoClient.kill_cursors`. - Removed :class:`pymongo.cursor_manager.CursorManager` and :mod:`pymongo.cursor_manager`. - Removed :meth:`pymongo.mongo_client.MongoClient.set_cursor_manager`. - Removed :meth:`pymongo.cursor.Cursor.count`. - Removed :mod:`pymongo.thread_util`. - Removed :class:`~pymongo.mongo_replica_set_client.MongoReplicaSetClient`. - Removed :class:`~pymongo.ismaster.IsMaster`. Use :class:`~pymongo.hello.Hello` instead. - Removed :mod:`pymongo.son_manipulator`, :class:`pymongo.son_manipulator.SONManipulator`, :class:`pymongo.son_manipulator.ObjectIdInjector`, :class:`pymongo.son_manipulator.ObjectIdShuffler`, :class:`pymongo.son_manipulator.AutoReference`, :class:`pymongo.son_manipulator.NamespaceInjector`, :meth:`pymongo.database.Database.add_son_manipulator`, :attr:`pymongo.database.Database.outgoing_copying_manipulators`, :attr:`pymongo.database.Database.outgoing_manipulators`, :attr:`pymongo.database.Database.incoming_copying_manipulators`, and :attr:`pymongo.database.Database.incoming_manipulators`. - Removed the ``manipulate`` and ``modifiers`` parameters from :meth:`~pymongo.collection.Collection.find`, :meth:`~pymongo.collection.Collection.find_one`, :meth:`~pymongo.collection.Collection.find_raw_batches`, and :meth:`~pymongo.cursor.Cursor`. - Removed :meth:`pymongo.message.delete`, :meth:`pymongo.message.get_more`, :meth:`pymongo.message.insert`, :meth:`pymongo.message.kill_cursors`, :meth:`pymongo.message.query`, and :meth:`pymongo.message.update`. - Removed :exc:`pymongo.errors.NotMasterError`. Use :exc:`pymongo.errors.NotPrimaryError` instead. - Removed :exc:`pymongo.errors.CertificateError`. - Removed :attr:`pymongo.GEOHAYSTACK`. - Removed :class:`bson.binary.UUIDLegacy`. - Removed :const:`bson.json_util.STRICT_JSON_OPTIONS`. Use :const:`~bson.json_util.RELAXED_JSON_OPTIONS` or :const:`~bson.json_util.CANONICAL_JSON_OPTIONS` instead. - Changed the default JSON encoding representation from legacy to relaxed. The json_mode parameter for :const:`bson.json_util.dumps` now defaults to :const:`~bson.json_util.RELAXED_JSON_OPTIONS`. - Changed the BSON and JSON decoding behavior of :class:`~bson.dbref.DBRef` to match the behavior outlined in the `DBRef specification`_ version 1.0. Specifically, PyMongo now only decodes a subdocument into a :class:`~bson.dbref.DBRef` if and only if, it contains both ``$ref`` and ``$id`` fields and the ``$ref``, ``$id``, and ``$db`` fields are of the correct type. Otherwise the document is returned as normal. Previously, any subdocument containing a ``$ref`` field would be decoded as a :class:`~bson.dbref.DBRef`. - The "tls" install extra is no longer necessary or supported and will be ignored by pip. - The ``tz_aware`` argument to :class:`~bson.json_util.JSONOptions` now defaults to ``False`` instead of ``True``. :meth:`bson.json_util.loads` now decodes datetime as naive by default. See :ref:`tz_aware_default_change` for more info. - ``directConnection`` URI option and keyword argument to :class:`~pymongo.mongo_client.MongoClient` defaults to ``False`` instead of ``None``, allowing for the automatic discovery of replica sets. This means that if you want a direct connection to a single server you must pass ``directConnection=True`` as a URI option or keyword argument. - The ``hint`` option is now required when using ``min`` or ``max`` queries with :meth:`~pymongo.collection.Collection.find`. - ``name`` is now a required argument for the :class:`pymongo.driver_info.DriverInfo` class. - When providing a "mongodb+srv://" URI to :class:`~pymongo.mongo_client.MongoClient` constructor you can now use the ``srvServiceName`` URI option to specify your own SRV service name. - :meth:`~bson.son.SON.items` now returns a ``dict_items`` object rather than a list. - Removed :meth:`bson.son.SON.iteritems`. - :class:`~pymongo.collection.Collection` and :class:`~pymongo.database.Database` now raises an error upon evaluating as a Boolean, please use the syntax ``if collection is not None:`` or ``if database is not None:`` as opposed to the previous syntax which was simply ``if collection:`` or ``if database:``. You must now explicitly compare with None. - :class:`~pymongo.mongo_client.MongoClient` cannot execute any operations after being closed. The previous behavior would simply reconnect. However, now you must create a new instance. - Classes :class:`~bson.int64.Int64`, :class:`~bson.min_key.MinKey`, :class:`~bson.max_key.MaxKey`, :class:`~bson.timestamp.Timestamp`, :class:`~bson.regex.Regex`, and :class:`~bson.dbref.DBRef` all implement ``__slots__`` now. This means that their attributes are fixed, and new attributes cannot be added to them at runtime. - Empty projections (eg {} or []) for :meth:`~pymongo.collection.Collection.find`, and :meth:`~pymongo.collection.Collection.find_one` are passed to the server as-is rather than the previous behavior which substituted in a projection of ``{"_id": 1}``. This means that an empty projection will now return the entire document, not just the ``"_id"`` field. - :class:`~pymongo.mongo_client.MongoClient` now raises a :exc:`~pymongo.errors.ConfigurationError` when more than one URI is passed into the ``hosts`` argument. - :class:`~pymongo.mongo_client.MongoClient`` now raises an :exc:`~pymongo.errors.InvalidURI` exception when it encounters unescaped percent signs in username and password when parsing MongoDB URIs. - Comparing two :class:`~pymongo.mongo_client.MongoClient` instances now uses a set of immutable properties rather than :attr:`~pymongo.mongo_client.MongoClient.address` which can change. - Removed the ``disable_md5`` parameter for :class:`~gridfs.GridFSBucket` and :class:`~gridfs.GridFS`. See :ref:`removed-gridfs-checksum` for details. - pymongocrypt 1.2.0 or later is now required for client side field level encryption support. Notable improvements .................... - Enhanced connection pooling to create connections more efficiently and avoid connection storms. - Added the ``maxConnecting`` URI and :class:`~pymongo.mongo_client.MongoClient` keyword argument. - :class:`~pymongo.mongo_client.MongoClient` now accepts a URI and keyword argument ``srvMaxHosts`` that limits the number of mongos-like hosts a client will connect to. More specifically, when a mongodb+srv:// connection string resolves to more than ``srvMaxHosts`` number of hosts, the client will randomly choose a ``srvMaxHosts`` sized subset of hosts. - Added :attr:`pymongo.mongo_client.MongoClient.options` for read-only access to a client's configuration options. - Support for the "kmip" KMS provider for client side field level encryption. See the docstring for :class:`~pymongo.encryption_options.AutoEncryptionOpts` and :mod:`~pymongo.encryption`. Issues Resolved ............... See the `PyMongo 4.0 release notes in JIRA`_ for the list of resolved issues in this release. .. _PyMongo 4.0 release notes in JIRA: https://jira.mongodb.org/secure/ReleaseNote.jspa?projectId=10004&version=18463 .. _DBRef specification: https://github.com/mongodb/specifications/blob/5a8c8d7/source/dbref.rst Changes in Version 3.13.0 ------------------------- Version 3.13 provides an upgrade path to PyMongo 4.x. Most of the API changes from PyMongo 4.0 have been backported in a backward compatible way, allowing applications to be written against PyMongo >= 3.13, rather then PyMongo 3.x or PyMongo 4.x. See the `PyMongo 4 Migration Guide`_ for detailed examples. Notable improvements .................... - Added :attr:`pymongo.mongo_client.MongoClient.options` for read-only access to a client's configuration options. Issues Resolved ............... PyMongo 3.13 drops support for Python 3.4. Bug fixes ......... - Fixed a memory leak bug when calling :func:`~bson.decode_all` without a ``codec_options`` argument (`PYTHON-3222`_). - Fixed a bug where :func:`~bson.decode_all` did not accept ``codec_options`` as a keyword argument (`PYTHON-3222`_). Deprecations ............ - Deprecated :meth:`~pymongo.collection.Collection.map_reduce` and :meth:`~pymongo.collection.Collection.inline_map_reduce`. Use :meth:`~pymongo.collection.Collection.aggregate` instead. - Deprecated :attr:`pymongo.mongo_client.MongoClient.event_listeners`. Use :attr:`~pymongo.mongo_client.options.event_listeners` instead. - Deprecated :attr:`pymongo.mongo_client.MongoClient.max_pool_size`. Use :attr:`~pymongo.mongo_client.options.pool_options.max_pool_size` instead. - Deprecated :attr:`pymongo.mongo_client.MongoClient.max_idle_time_ms`. Use :attr:`~pymongo.mongo_client.options.pool_options.max_idle_time_seconds` instead. - Deprecated :attr:`pymongo.mongo_client.MongoClient.local_threshold_ms`. Use :attr:`~pymongo.mongo_client.options.local_threshold_ms` instead. - Deprecated :attr:`pymongo.mongo_client.MongoClient.server_selection_timeout`. Use :attr:`~pymongo.mongo_client.options.server_selection_timeout` instead. - Deprecated :attr:`pymongo.mongo_client.MongoClient.retry_writes`. Use :attr:`~pymongo.mongo_client.options.retry_writes` instead. - Deprecated :attr:`pymongo.mongo_client.MongoClient.retry_reads`. Use :attr:`~pymongo.mongo_client.options.retry_reads` instead. - Deprecated :attr:`pymongo.mongo_client.MongoClient.max_bson_size`, :attr:`pymongo.mongo_client.MongoClient.max_message_size`, and :attr:`pymongo.mongo_client.MongoClient.max_write_batch_size`. These helpers were incorrect when in ``loadBalanced=true mode`` and ambiguous in clusters with mixed versions. Use the `hello command`_ to get the authoritative value from the remote server instead. Code like this:: max_bson_size = client.max_bson_size max_message_size = client.max_message_size max_write_batch_size = client.max_write_batch_size can be changed to this:: doc = client.admin.command('hello') max_bson_size = doc['maxBsonObjectSize'] max_message_size = doc['maxMessageSizeBytes'] max_write_batch_size = doc['maxWriteBatchSize'] .. _hello command: https://docs.mongodb.com/manual/reference/command/hello/ See the `PyMongo 3.13.0 release notes in JIRA`_ for the list of resolved issues in this release. .. _PyMongo 4 Migration Guide: https://pymongo.readthedocs.io/en/stable/migrate-to-pymongo4.html .. _PYTHON-3222: https://jira.mongodb.org/browse/PYTHON-3222 .. _PyMongo 3.13.0 release notes in JIRA: https://jira.mongodb.org/secure/ReleaseNote.jspa?projectId=10004&version=31570 Changes in Version 3.12.3 ------------------------- Issues Resolved ............... Version 3.12.3 fixes a bug that prevented :meth:`bson.json_util.loads` from decoding a document with a non-string "$regex" field (`PYTHON-3028`_). See the `PyMongo 3.12.3 release notes in JIRA`_ for the list of resolved issues in this release. .. _PYTHON-3028: https://jira.mongodb.org/browse/PYTHON-3028 .. _PyMongo 3.12.3 release notes in JIRA: https://jira.mongodb.org/secure/ReleaseNote.jspa?projectId=10004&version=32505 Changes in Version 3.12.2 ------------------------- Issues Resolved ............... Version 3.12.2 fixes a number of bugs: - Fixed a bug that prevented PyMongo from retrying bulk writes after a ``writeConcernError`` on MongoDB 4.4+ (`PYTHON-2984`_). - Fixed a bug that could cause the driver to hang during automatic client side field level encryption (`PYTHON-3017`_). See the `PyMongo 3.12.2 release notes in JIRA`_ for the list of resolved issues in this release. .. _PYTHON-2984: https://jira.mongodb.org/browse/PYTHON-2984 .. _PYTHON-3017: https://jira.mongodb.org/browse/PYTHON-3017 .. _PyMongo 3.12.2 release notes in JIRA: https://jira.mongodb.org/secure/ReleaseNote.jspa?projectId=10004&version=32310 Changes in Version 3.12.1 ------------------------- Issues Resolved ............... Version 3.12.1 fixes a number of bugs: - Fixed a bug that caused a multi-document transaction to fail when the first operation was large bulk write (>48MB) that required splitting a batched write command (`PYTHON-2915`_). - Fixed a bug that caused the ``tlsDisableOCSPEndpointCheck`` URI option to be applied incorrectly (`PYTHON-2866`_). See the `PyMongo 3.12.1 release notes in JIRA`_ for the list of resolved issues in this release. .. _PYTHON-2915: https://jira.mongodb.org/browse/PYTHON-2915 .. _PYTHON-2866: https://jira.mongodb.org/browse/PYTHON-2866 .. _PyMongo 3.12.1 release notes in JIRA: https://jira.mongodb.org/secure/ReleaseNote.jspa?projectId=10004&version=31527 Changes in Version 3.12.0 ------------------------- .. warning:: PyMongo 3.12.0 deprecates support for Python 2.7, 3.4 and 3.5. These Python versions will not be supported by PyMongo 4. .. warning:: PyMongo now allows insertion of documents with keys that include dots ('.') or start with dollar signs ('$'). - pymongocrypt 1.1.0 or later is now required for client side field level encryption support. - Iterating over :class:`gridfs.grid_file.GridOut` now moves through the file line by line instead of chunk by chunk, and does not restart at the top for subsequent iterations on the same object. Call ``seek(0)`` to reset the iterator. Notable improvements .................... - Added support for MongoDB 5.0. - Support for MongoDB Stable API, see :class:`~pymongo.server_api.ServerApi`. - Support for snapshot reads on secondaries (see :ref:`snapshot-reads-ref`). - Support for Azure and GCP KMS providers for client side field level encryption. See the docstring for :class:`~pymongo.mongo_client.MongoClient`, :class:`~pymongo.encryption_options.AutoEncryptionOpts`, and :mod:`~pymongo.encryption`. - Support AWS authentication with temporary credentials when connecting to KMS in client side field level encryption. - Support for connecting to load balanced MongoDB clusters via the new ``loadBalanced`` URI option. - Support for creating timeseries collections via the ``timeseries`` and ``expireAfterSeconds`` arguments to :meth:`~pymongo.database.Database.create_collection`. - Added :attr:`pymongo.mongo_client.MongoClient.topology_description`. - Added hash support to :class:`~pymongo.mongo_client.MongoClient`, :class:`~pymongo.database.Database` and :class:`~pymongo.collection.Collection` (`PYTHON-2466`_). - Improved the error message returned by :meth:`~pymongo.collection.Collection.insert_many` when supplied with an argument of incorrect type (`PYTHON-1690`_). - Added session and read concern support to :meth:`~pymongo.collection.Collection.find_raw_batches` and :meth:`~pymongo.collection.Collection.aggregate_raw_batches`. Bug fixes ......... - Fixed a bug that could cause the driver to deadlock during automatic client side field level encryption (`PYTHON-2472`_). - Fixed a potential deadlock when garbage collecting an unclosed exhaust :class:`~pymongo.cursor.Cursor`. - Fixed an bug where using gevent.Timeout to timeout an operation could lead to a deadlock. - Fixed the following bug with Atlas Data Lake. When closing cursors, pymongo now sends killCursors with the namespace returned the cursor's initial command response. - Fixed a bug in :class:`~pymongo.cursor.RawBatchCursor` that caused it to return an empty bytestring when the cursor contained no results. It now raises :exc:`StopIteration` instead. Deprecations ............ - Deprecated support for Python 2.7, 3.4 and 3.5. - Deprecated support for database profiler helpers :meth:`~pymongo.database.Database.profiling_level`, :meth:`~pymongo.database.Database.set_profiling_level`, and :meth:`~pymongo.database.Database.profiling_info`. Instead, users should run the `profile command`_ with the :meth:`~pymongo.database.Database.command` helper directly. - Deprecated :exc:`~pymongo.errors.NotMasterError`. Users should use :exc:`~pymongo.errors.NotPrimaryError` instead. - Deprecated :class:`~pymongo.ismaster.IsMaster` and :mod:`~pymongo.ismaster` which will be removed in PyMongo 4.0 and are replaced by :class:`~pymongo.hello.Hello` and :mod:`~pymongo.hello` which provide the same API. - Deprecated the :mod:`pymongo.messeage` module. - Deprecated the ``ssl_keyfile`` and ``ssl_certfile`` URI options in favor of ``tlsCertificateKeyFile`` (see :doc:`examples/tls`). .. _PYTHON-2466: https://jira.mongodb.org/browse/PYTHON-2466 .. _PYTHON-1690: https://jira.mongodb.org/browse/PYTHON-1690 .. _PYTHON-2472: https://jira.mongodb.org/browse/PYTHON-2472 .. _profile command: https://mongodb.com/docs/manual/reference/command/profile/ Issues Resolved ............... See the `PyMongo 3.12.0 release notes in JIRA`_ for the list of resolved issues in this release. .. _PyMongo 3.12.0 release notes in JIRA: https://jira.mongodb.org/secure/ReleaseNote.jspa?projectId=10004&version=29594 Changes in Version 3.11.3 ------------------------- Issues Resolved ............... Version 3.11.3 fixes a bug that prevented PyMongo from retrying writes after a ``writeConcernError`` on MongoDB 4.4+ (`PYTHON-2452`_) See the `PyMongo 3.11.3 release notes in JIRA`_ for the list of resolved issues in this release. .. _PYTHON-2452: https://jira.mongodb.org/browse/PYTHON-2452 .. _PyMongo 3.11.3 release notes in JIRA: https://jira.mongodb.org/secure/ReleaseNote.jspa?projectId=10004&version=30355 Changes in Version 3.11.2 ------------------------- Issues Resolved ............... Version 3.11.2 includes a number of bugfixes. Highlights include: - Fixed a memory leak caused by failing SDAM monitor checks on Python 3 (`PYTHON-2433`_). - Fixed a regression that changed the string representation of :exc:`~pymongo.errors.BulkWriteError` (`PYTHON-2438`_). - Fixed a bug that made it impossible to use :meth:`bson.codec_options.CodecOptions.with_options` and :meth:`~bson.json_util.JSONOptions.with_options` on some early versions of Python 3.4 and Python 3.5 due to a bug in the standard library implementation of :meth:`collections.namedtuple._asdict` (`PYTHON-2440`_). - Fixed a bug that resulted in a :exc:`TypeError` exception when a PyOpenSSL socket was configured with a timeout of ``None`` (`PYTHON-2443`_). See the `PyMongo 3.11.2 release notes in JIRA`_ for the list of resolved issues in this release. .. _PYTHON-2433: https://jira.mongodb.org/browse/PYTHON-2433 .. _PYTHON-2438: https://jira.mongodb.org/browse/PYTHON-2438 .. _PYTHON-2440: https://jira.mongodb.org/browse/PYTHON-2440 .. _PYTHON-2443: https://jira.mongodb.org/browse/PYTHON-2443 .. _PyMongo 3.11.2 release notes in JIRA: https://jira.mongodb.org/secure/ReleaseNote.jspa?projectId=10004&version=30315 Changes in Version 3.11.1 ------------------------- Version 3.11.1 adds support for Python 3.9 and includes a number of bugfixes. Highlights include: - Support for Python 3.9. - Initial support for Azure and GCP KMS providers for client side field level encryption is in beta. See the docstring for :class:`~pymongo.mongo_client.MongoClient`, :class:`~pymongo.encryption_options.AutoEncryptionOpts`, and :mod:`~pymongo.encryption`. **Note: Backwards-breaking changes may be made before the final release.** - Fixed a bug where the :class:`bson.json_util.JSONOptions` API did not match the :class:`bson.codec_options.CodecOptions` API due to the absence of a :meth:`bson.json_util.JSONOptions.with_options` method. This method has now been added. - Fixed a bug which made it impossible to serialize :class:`~pymongo.errors.BulkWriteError` instances using :mod:`pickle`. - Fixed a bug wherein PyMongo did not always discard an implicit session after encountering a network error. - Fixed a bug where connections created in the background were not authenticated. - Fixed a memory leak in the :mod:`bson` module when using a :class:`~bson.codec_options.TypeRegistry`. Issues Resolved ............... See the `PyMongo 3.11.1 release notes in JIRA`_ for the list of resolved issues in this release. .. _PyMongo 3.11.1 release notes in JIRA: https://jira.mongodb.org/secure/ReleaseNote.jspa?projectId=10004&version=29997 Changes in Version 3.11.0 ------------------------- Version 3.11 adds support for MongoDB 4.4 and includes a number of bug fixes. Highlights include: - Support for :ref:`OCSP` (Online Certificate Status Protocol). - Support for `PyOpenSSL `_ as an alternative TLS implementation. PyOpenSSL is required for :ref:`OCSP` support. It will also be installed when using the "tls" extra if the version of Python in use is older than 2.7.9. - Support for the :ref:`MONGODB-AWS` authentication mechanism. - Support for the ``directConnection`` URI option and kwarg to :class:`~pymongo.mongo_client.MongoClient`. - Support for speculative authentication attempts in connection handshakes which reduces the number of network roundtrips needed to authenticate new connections on MongoDB 4.4+. - Support for creating collections in multi-document transactions with :meth:`~pymongo.database.Database.create_collection` on MongoDB 4.4+. - Added index hinting support to the :meth:`~pymongo.collection.Collection.replace_one`, :meth:`~pymongo.collection.Collection.update_one`, :meth:`~pymongo.collection.Collection.update_many`, :meth:`~pymongo.collection.Collection.find_one_and_replace`, :meth:`~pymongo.collection.Collection.find_one_and_update`, :meth:`~pymongo.collection.Collection.delete_one`, :meth:`~pymongo.collection.Collection.delete_many`, and :meth:`~pymongo.collection.Collection.find_one_and_delete` commands. - Added index hinting support to the :class:`~pymongo.operations.ReplaceOne`, :class:`~pymongo.operations.UpdateOne`, :class:`~pymongo.operations.UpdateMany`, :class:`~pymongo.operations.DeleteOne`, and :class:`~pymongo.operations.DeleteMany` bulk operations. - Added support for :data:`bson.binary.UuidRepresentation.UNSPECIFIED` and ``MongoClient(uuidRepresentation='unspecified')`` which will become the default UUID representation starting in PyMongo 4.0. See :ref:`handling-uuid-data-example` for details. - New methods :meth:`bson.binary.Binary.from_uuid` and :meth:`bson.binary.Binary.as_uuid`. - Added the ``background`` parameter to :meth:`pymongo.database.Database.validate_collection`. For a description of this parameter see the MongoDB documentation for the `validate command`_. - Added the ``allow_disk_use`` parameters to :meth:`pymongo.collection.Collection.find`. - Added the ``hedge`` parameter to :class:`~pymongo.read_preferences.PrimaryPreferred`, :class:`~pymongo.read_preferences.Secondary`, :class:`~pymongo.read_preferences.SecondaryPreferred`, :class:`~pymongo.read_preferences.Nearest` to support disabling (or explicitly enabling) hedged reads in MongoDB 4.4+. - Fixed a bug in change streams that could cause PyMongo to miss some change documents when resuming a stream that was started without a resume token and whose first batch did not contain any change documents. - Fixed an bug where using gevent.Timeout to timeout an operation could lead to a deadlock. Deprecations: - Deprecated the ``oplog_replay`` parameter to :meth:`pymongo.collection.Collection.find`. Starting in MongoDB 4.4, the server optimizes queries against the oplog collection without requiring the user to set this flag. - Deprecated :meth:`pymongo.collection.Collection.reindex`. Use :meth:`~pymongo.database.Database.command` to run the ``reIndex`` command instead. - Deprecated :meth:`pymongo.mongo_client.MongoClient.fsync`. Use :meth:`~pymongo.database.Database.command` to run the ``fsync`` command instead. - Deprecated :meth:`pymongo.mongo_client.MongoClient.unlock`. Use :meth:`~pymongo.database.Database.command` to run the ``fsyncUnlock`` command instead. See the documentation for more information. - Deprecated :attr:`pymongo.mongo_client.MongoClient.is_locked`. Use :meth:`~pymongo.database.Database.command` to run the ``currentOp`` command instead. See the documentation for more information. - Deprecated :class:`bson.binary.UUIDLegacy`. Use :meth:`bson.binary.Binary.from_uuid` instead. Unavoidable breaking changes: - :class:`~gridfs.GridFSBucket` and :class:`~gridfs.GridFS` do not support multi-document transactions. Running a GridFS operation in a transaction now always raises the following error: ``InvalidOperation: GridFS does not support multi-document transactions`` .. _validate command: https://mongodb.com/docs/manual/reference/command/validate/ Issues Resolved ............... See the `PyMongo 3.11.0 release notes in JIRA`_ for the list of resolved issues in this release. .. _PyMongo 3.11.0 release notes in JIRA: https://jira.mongodb.org/secure/ReleaseNote.jspa?projectId=10004&version=24799 Changes in Version 3.10.1 ------------------------- Version 3.10.1 fixes the following issues discovered since the release of 3.10.0: - Fix a TypeError logged to stderr that could be triggered during server maintenance or during :meth:`pymongo.mongo_client.MongoClient.close`. - Avoid creating new connections during :meth:`pymongo.mongo_client.MongoClient.close`. Issues Resolved ............... See the `PyMongo 3.10.1 release notes in JIRA`_ for the list of resolved issues in this release. .. _PyMongo 3.10.1 release notes in JIRA: https://jira.mongodb.org/secure/ReleaseNote.jspa?projectId=10004&version=25039 Changes in Version 3.10.0 ------------------------- Version 3.10 includes a number of improvements and bug fixes. Highlights include: - Support for Client-Side Field Level Encryption with MongoDB 4.2. See :doc:`examples/encryption` for examples. - Support for Python 3.8. - Added :attr:`pymongo.client_session.ClientSession.in_transaction`. - Do not hold the Topology lock while creating connections in a MongoClient's background thread. This change fixes a bug where application operations would block while the background thread ensures that all server pools have minPoolSize connections. - Fix a UnicodeDecodeError bug when coercing a PyMongoError with a non-ascii error message to unicode on Python 2. - Fix an edge case bug where PyMongo could exceed the server's maxMessageSizeBytes when generating a compressed bulk write command. Issues Resolved ............... See the `PyMongo 3.10 release notes in JIRA`_ for the list of resolved issues in this release. .. _PyMongo 3.10 release notes in JIRA: https://jira.mongodb.org/secure/ReleaseNote.jspa?projectId=10004&version=23944 Changes in Version 3.9.0 ------------------------ Version 3.9 adds support for MongoDB 4.2. Highlights include: - Support for MongoDB 4.2 sharded transactions. Sharded transactions have the same API as replica set transactions. See :ref:`transactions-ref`. - New method :meth:`pymongo.client_session.ClientSession.with_transaction` to support conveniently running a transaction in a session with automatic retries and at-most-once semantics. - Initial support for client side field level encryption. See the docstring for :class:`~pymongo.mongo_client.MongoClient`, :class:`~pymongo.encryption_options.AutoEncryptionOpts`, and :mod:`~pymongo.encryption` for details. **Note: Support for client side encryption is in beta. Backwards-breaking changes may be made before the final release.** - Added the ``max_commit_time_ms`` parameter to :meth:`~pymongo.client_session.ClientSession.start_transaction`. - Implement the `URI options specification`_ in the :meth:`~pymongo.mongo_client.MongoClient` constructor. Consequently, there are a number of changes in connection options: - The ``tlsInsecure`` option has been added. - The ``tls`` option has been added. The older ``ssl`` option has been retained as an alias to the new ``tls`` option. - ``wTimeout`` has been deprecated in favor of ``wTimeoutMS``. - ``wTimeoutMS`` now overrides ``wTimeout`` if the user provides both. - ``j`` has been deprecated in favor of ``journal``. - ``journal`` now overrides ``j`` if the user provides both. - ``ssl_cert_reqs`` has been deprecated in favor of ``tlsAllowInvalidCertificates``. Instead of ``ssl.CERT_NONE``, ``ssl.CERT_OPTIONAL`` and ``ssl.CERT_REQUIRED``, the new option expects a boolean value - ``True`` is equivalent to ``ssl.CERT_NONE``, while ``False`` is equivalent to ``ssl.CERT_REQUIRED``. - ``ssl_match_hostname`` has been deprecated in favor of ``tlsAllowInvalidHostnames``. - ``ssl_ca_certs`` has been deprecated in favor of ``tlsCAFile``. - ``ssl_certfile`` has been deprecated in favor of ``tlsCertificateKeyFile``. - ``ssl_pem_passphrase`` has been deprecated in favor of ``tlsCertificateKeyFilePassword``. - ``waitQueueMultiple`` has been deprecated without replacement. This option was a poor solution for putting an upper bound on queuing since it didn't affect queuing in other parts of the driver. - The ``retryWrites`` URI option now defaults to ``True``. Supported write operations that fail with a retryable error will automatically be retried one time, with at-most-once semantics. - Support for retryable reads and the ``retryReads`` URI option which is enabled by default. See the :class:`~pymongo.mongo_client.MongoClient` documentation for details. Now that supported operations are retried automatically and transparently, users should consider adjusting any custom retry logic to prevent an application from inadvertently retrying for too long. - Support zstandard for wire protocol compression. - Support for periodically polling DNS SRV records to update the mongos proxy list without having to change client configuration. - New method :meth:`pymongo.database.Database.aggregate` to support running database level aggregations. - Support for publishing Connection Monitoring and Pooling events via the new :class:`~pymongo.monitoring.ConnectionPoolListener` class. See :mod:`~pymongo.monitoring` for an example. - :meth:`pymongo.collection.Collection.aggregate` and :meth:`pymongo.database.Database.aggregate` now support the ``$merge`` pipeline stage and use read preference :attr:`~pymongo.read_preferences.ReadPreference.PRIMARY` if the ``$out`` or ``$merge`` pipeline stages are used. - Support for specifying a pipeline or document in :meth:`~pymongo.collection.Collection.update_one`, :meth:`~pymongo.collection.Collection.update_many`, :meth:`~pymongo.collection.Collection.find_one_and_update`, :meth:`~pymongo.operations.UpdateOne`, and :meth:`~pymongo.operations.UpdateMany`. - New BSON utility functions :func:`~bson.encode` and :func:`~bson.decode` - :class:`~bson.binary.Binary` now supports any bytes-like type that implements the buffer protocol. - Resume tokens can now be accessed from a ``ChangeStream`` cursor using the :attr:`~pymongo.change_stream.ChangeStream.resume_token` attribute. - Connections now survive primary step-down when using MongoDB 4.2+. Applications should expect less socket connection turnover during replica set elections. Unavoidable breaking changes: - Applications that use MongoDB with the MMAPv1 storage engine must now explicitly disable retryable writes via the connection string (e.g. ``MongoClient("mongodb://my.mongodb.cluster/db?retryWrites=false")``) or the :class:`~pymongo.mongo_client.MongoClient` constructor's keyword argument (e.g. ``MongoClient("mongodb://my.mongodb.cluster/db", retryWrites=False)``) to avoid running into :class:`~pymongo.errors.OperationFailure` exceptions during write operations. The MMAPv1 storage engine is deprecated and does not support retryable writes which are now turned on by default. - In order to ensure that the ``connectTimeoutMS`` URI option is honored when connecting to clusters with a ``mongodb+srv://`` connection string, the minimum required version of the optional ``dnspython`` dependency has been bumped to 1.16.0. This is a breaking change for applications that use PyMongo's SRV support with a version of ``dnspython`` older than 1.16.0. .. _URI options specification: https://github.com/mongodb/specifications/blob/master/source/uri-options/uri-options.rst Issues Resolved ............... See the `PyMongo 3.9 release notes in JIRA`_ for the list of resolved issues in this release. .. _PyMongo 3.9 release notes in JIRA: https://jira.mongodb.org/secure/ReleaseNote.jspa?projectId=10004&version=21787 Changes in Version 3.8.0 ------------------------ .. warning:: PyMongo no longer supports Python 2.6. RHEL 6 users should install Python 2.7 or newer from `Red Hat Software Collections `_. CentOS 6 users should install Python 2.7 or newer from `SCL `_ .. warning:: PyMongo no longer supports PyPy3 versions older than 3.5. Users must upgrade to PyPy3.5+. - :class:`~bson.objectid.ObjectId` now implements the `ObjectID specification version 0.2 `_. - For better performance and to better follow the GridFS spec, :class:`~gridfs.grid_file.GridOut` now uses a single cursor to read all the chunks in the file. Previously, each chunk in the file was queried individually using :meth:`~pymongo.collection.Collection.find_one`. - :meth:`gridfs.grid_file.GridOut.read` now only checks for extra chunks after reading the entire file. Previously, this method would check for extra chunks on every call. - :meth:`~pymongo.database.Database.current_op` now always uses the ``Database``'s :attr:`~pymongo.database.Database.codec_options` when decoding the command response. Previously the codec_options was only used when the MongoDB server version was <= 3.0. - Undeprecated :meth:`~pymongo.mongo_client.MongoClient.get_default_database` and added the ``default`` parameter. - TLS Renegotiation is now disabled when possible. - Custom types can now be directly encoded to, and decoded from MongoDB using the :class:`~bson.codec_options.TypeCodec` and :class:`~bson.codec_options.TypeRegistry` APIs. For more information, see the :doc:`custom type example `. - Attempting a multi-document transaction on a sharded cluster now raises a :exc:`~pymongo.errors.ConfigurationError`. - :meth:`pymongo.cursor.Cursor.distinct` and :meth:`pymongo.cursor.Cursor.count` now send the Cursor's :meth:`~pymongo.cursor.Cursor.comment` as the "comment" top-level command option instead of "$comment". Also, note that "comment" must be a string. - Add the ``filter`` parameter to :meth:`~pymongo.database.Database.list_collection_names`. - Changes can now be requested from a ``ChangeStream`` cursor without blocking indefinitely using the new :meth:`pymongo.change_stream.ChangeStream.try_next` method. - Fixed a reference leak bug when splitting a batched write command based on maxWriteBatchSize or the max message size. - Deprecated running find queries that set :meth:`~pymongo.cursor.Cursor.min` and/or :meth:`~pymongo.cursor.Cursor.max` but do not also set a :meth:`~pymongo.cursor.Cursor.hint` of which index to use. The find command is expected to require a :meth:`~pymongo.cursor.Cursor.hint` when using min/max starting in MongoDB 4.2. - Documented support for the uuidRepresentation URI option, which has been supported since PyMongo 2.7. Valid values are ``pythonLegacy`` (the default), ``javaLegacy``, ``csharpLegacy`` and ``standard``. New applications should consider setting this to ``standard`` for cross language compatibility. - :class:`~bson.raw_bson.RawBSONDocument` now validates that the ``bson_bytes`` passed in represent a single bson document. Earlier versions would mistakenly accept multiple bson documents. - Iterating over a :class:`~bson.raw_bson.RawBSONDocument` now maintains the same field order of the underlying raw BSON document. - Applications can now register a custom server selector. For more information see the :doc:`server selector example `. - The connection pool now implements a LIFO policy. Unavoidable breaking changes: - In order to follow the ObjectID Spec version 0.2, an ObjectId's 3-byte machine identifier and 2-byte process id have been replaced with a single 5-byte random value generated per process. This is a breaking change for any application that attempts to interpret those bytes. Issues Resolved ............... See the `PyMongo 3.8 release notes in JIRA`_ for the list of resolved issues in this release. .. _PyMongo 3.8 release notes in JIRA: https://jira.mongodb.org/secure/ReleaseNote.jspa?projectId=10004&version=19904 Changes in Version 3.7.2 ------------------------ Version 3.7.2 fixes a few issues discovered since the release of 3.7.1. - Fixed a bug in retryable writes where a previous command's "txnNumber" field could be sent leading to incorrect results. - Fixed a memory leak of a few bytes on some insert, update, or delete commands when running against MongoDB 3.6+. - Fixed a bug that caused :meth:`pymongo.collection.Collection.ensure_index` to only cache a single index per database. - Updated the documentation examples to use :meth:`pymongo.collection.Collection.count_documents` instead of :meth:`pymongo.collection.Collection.count` and :meth:`pymongo.cursor.Cursor.count`. Issues Resolved ............... See the `PyMongo 3.7.2 release notes in JIRA`_ for the list of resolved issues in this release. .. _PyMongo 3.7.2 release notes in JIRA: https://jira.mongodb.org/secure/ReleaseNote.jspa?projectId=10004&version=21519 Changes in Version 3.7.1 ------------------------ Version 3.7.1 fixes a few issues discovered since the release of 3.7.0. - Calling :meth:`~pymongo.database.Database.authenticate` more than once with the same credentials results in OperationFailure. - Authentication fails when SCRAM-SHA-1 is used to authenticate users with only MONGODB-CR credentials. - A millisecond rounding problem when decoding datetimes in the pure Python BSON decoder on 32 bit systems and AWS lambda. Issues Resolved ............... See the `PyMongo 3.7.1 release notes in JIRA`_ for the list of resolved issues in this release. .. _PyMongo 3.7.1 release notes in JIRA: https://jira.mongodb.org/secure/ReleaseNote.jspa?projectId=10004&version=21096 Changes in Version 3.7.0 ------------------------ Version 3.7 adds support for MongoDB 4.0. Highlights include: - Support for single replica set multi-document ACID transactions. See :ref:`transactions-ref`. - Support for wire protocol compression via the new ``compressors`` URI and keyword argument to :meth:`~pymongo.mongo_client.MongoClient`. See :ref:`network-compression-example` for details. - Support for Python 3.7. - New count methods, :meth:`~pymongo.collection.Collection.count_documents` and :meth:`~pymongo.collection.Collection.estimated_document_count`. :meth:`~pymongo.collection.Collection.count_documents` is always accurate when used with MongoDB 3.6+, or when used with older standalone or replica set deployments. With older sharded clusters is it always accurate when used with Primary read preference. It can also be used in a transaction, unlike the now deprecated :meth:`pymongo.collection.Collection.count` and :meth:`pymongo.cursor.Cursor.count` methods. - Support for watching changes on all collections in a database using the new :meth:`pymongo.database.Database.watch` method. - Support for watching changes on all collections in all databases using the new :meth:`pymongo.mongo_client.MongoClient.watch` method. - Support for watching changes starting at a user provided timestamp using the new ``start_at_operation_time`` parameter for the ``watch()`` helpers. - Better support for using PyMongo in a FIPS 140-2 environment. Specifically, the following features and changes allow PyMongo to function when MD5 support is disabled in OpenSSL by the FIPS Object Module: - Support for the :ref:`SCRAM-SHA-256 ` authentication mechanism. The :ref:`GSSAPI `, :ref:`PLAIN `, and :ref:`MONGODB-X509 ` mechanisms can also be used to avoid issues with OpenSSL in FIPS environments. - MD5 checksums are now optional in GridFS. See the ``disable_md5`` option of :class:`~gridfs.GridFS` and :class:`~gridfs.GridFSBucket`. - :class:`~bson.objectid.ObjectId` machine bytes are now hashed using `FNV-1a `_ instead of MD5. - The :meth:`~pymongo.database.Database.list_collection_names` and :meth:`~pymongo.database.Database.collection_names` methods use the nameOnly option when supported by MongoDB. - The :meth:`pymongo.collection.Collection.watch` method now returns an instance of the :class:`~pymongo.change_stream.CollectionChangeStream` class which is a subclass of :class:`~pymongo.change_stream.ChangeStream`. - SCRAM client and server keys are cached for improved performance, following `RFC 5802 `_. - If not specified, the authSource for the :ref:`PLAIN ` authentication mechanism defaults to $external. - wtimeoutMS is once again supported as a URI option. - When using unacknowledged write concern and connected to MongoDB server version 3.6 or greater, the ``bypass_document_validation`` option is now supported in the following write helpers: :meth:`~pymongo.collection.Collection.insert_one`, :meth:`~pymongo.collection.Collection.replace_one`, :meth:`~pymongo.collection.Collection.update_one`, :meth:`~pymongo.collection.Collection.update_many`. Deprecations: - Deprecated :meth:`pymongo.collection.Collection.count` and :meth:`pymongo.cursor.Cursor.count`. These two methods use the ``count`` command and `may or may not be accurate `_, depending on the options used and connected MongoDB topology. Use :meth:`~pymongo.collection.Collection.count_documents` instead. - Deprecated the snapshot option of :meth:`~pymongo.collection.Collection.find` and :meth:`~pymongo.collection.Collection.find_one`. The option was deprecated in MongoDB 3.6 and removed in MongoDB 4.0. - Deprecated the max_scan option of :meth:`~pymongo.collection.Collection.find` and :meth:`~pymongo.collection.Collection.find_one`. The option was deprecated in MongoDB 4.0. Use ``maxTimeMS`` instead. - Deprecated :meth:`~pymongo.mongo_client.MongoClient.close_cursor`. Use :meth:`~pymongo.cursor.Cursor.close` instead. - Deprecated :meth:`~pymongo.mongo_client.MongoClient.database_names`. Use :meth:`~pymongo.mongo_client.MongoClient.list_database_names` instead. - Deprecated :meth:`~pymongo.database.Database.collection_names`. Use :meth:`~pymongo.database.Database.list_collection_names` instead. - Deprecated :meth:`~pymongo.collection.Collection.parallel_scan`. MongoDB 4.2 will remove the parallelCollectionScan command. Unavoidable breaking changes: - Commands that fail with server error codes 10107, 13435, 13436, 11600, 11602, 189, 91 (NotMaster, NotMasterNoSlaveOk, NotMasterOrSecondary, InterruptedAtShutdown, InterruptedDueToReplStateChange, PrimarySteppedDown, ShutdownInProgress respectively) now always raise :class:`~pymongo.errors.NotMasterError` instead of :class:`~pymongo.errors.OperationFailure`. - :meth:`~pymongo.collection.Collection.parallel_scan` no longer uses an implicit session. Explicit sessions are still supported. - Unacknowledged writes (``w=0``) with an explicit ``session`` parameter now raise a client side error. Since PyMongo does not wait for a response for an unacknowledged write, two unacknowledged writes run serially by the client may be executed simultaneously on the server. However, the server requires a single session must not be used simultaneously by more than one operation. Therefore explicit sessions cannot support unacknowledged writes. Unacknowledged writes without a ``session`` parameter are still supported. Issues Resolved ............... See the `PyMongo 3.7 release notes in JIRA`_ for the list of resolved issues in this release. .. _PyMongo 3.7 release notes in JIRA: https://jira.mongodb.org/secure/ReleaseNote.jspa?projectId=10004&version=19287 Changes in Version 3.6.1 ------------------------ Version 3.6.1 fixes bugs reported since the release of 3.6.0: - Fix regression in PyMongo 3.5.0 that causes idle sockets to be closed almost instantly when ``maxIdleTimeMS`` is set. Idle sockets are now closed after ``maxIdleTimeMS`` milliseconds. - :attr:`pymongo.mongo_client.MongoClient.max_idle_time_ms` now returns milliseconds instead of seconds. - Properly import and use the `monotonic `_ library for monotonic time when it is installed. - :meth:`~pymongo.collection.Collection.aggregate` now ignores the ``batchSize`` argument when running a pipeline with a ``$out`` stage. - Always send handshake metadata for new connections. Issues Resolved ............... See the `PyMongo 3.6.1 release notes in JIRA`_ for the list of resolved issues in this release. .. _PyMongo 3.6.1 release notes in JIRA: https://jira.mongodb.org/secure/ReleaseNote.jspa?projectId=10004&version=19438 Changes in Version 3.6.0 ------------------------ Version 3.6 adds support for MongoDB 3.6, drops support for CPython 3.3 (PyPy3 is still supported), and drops support for MongoDB versions older than 2.6. If connecting to a MongoDB 2.4 server or older, PyMongo now throws a :exc:`~pymongo.errors.ConfigurationError`. Highlights include: - Support for change streams. See the :meth:`~pymongo.collection.Collection.watch` method for details. - Support for array_filters in :meth:`~pymongo.collection.Collection.update_one`, :meth:`~pymongo.collection.Collection.update_many`, :meth:`~pymongo.collection.Collection.find_one_and_update`, :meth:`~pymongo.operations.UpdateOne`, and :meth:`~pymongo.operations.UpdateMany`. - New Session API, see :meth:`~pymongo.mongo_client.MongoClient.start_session`. - New methods :meth:`~pymongo.collection.Collection.find_raw_batches` and :meth:`~pymongo.collection.Collection.aggregate_raw_batches` for use with external libraries that can parse raw batches of BSON data. - New methods :meth:`~pymongo.mongo_client.MongoClient.list_databases` and :meth:`~pymongo.mongo_client.MongoClient.list_database_names`. - New methods :meth:`~pymongo.database.Database.list_collections` and :meth:`~pymongo.database.Database.list_collection_names`. - Support for mongodb+srv:// URIs. See :class:`~pymongo.mongo_client.MongoClient` for details. - Index management helpers (:meth:`~pymongo.collection.Collection.create_index`, :meth:`~pymongo.collection.Collection.create_indexes`, :meth:`~pymongo.collection.Collection.drop_index`, :meth:`~pymongo.collection.Collection.drop_indexes`, :meth:`~pymongo.collection.Collection.reindex`) now support maxTimeMS. - Support for retryable writes and the ``retryWrites`` URI option. See :class:`~pymongo.mongo_client.MongoClient` for details. Deprecations: - The ``useCursor`` option for :meth:`~pymongo.collection.Collection.aggregate` is deprecated. The option was only necessary when upgrading from MongoDB 2.4 to MongoDB 2.6. MongoDB 2.4 is no longer supported. - The :meth:`~pymongo.database.Database.add_user` and :meth:`~pymongo.database.Database.remove_user` methods are deprecated. See the method docstrings for alternatives. Unavoidable breaking changes: - Starting in MongoDB 3.6, the deprecated methods :meth:`~pymongo.database.Database.authenticate` and :meth:`~pymongo.database.Database.logout` now invalidate all cursors created prior. Instead of using these methods to change credentials, pass credentials for one user to the :class:`~pymongo.mongo_client.MongoClient` at construction time, and either grant access to several databases to one user account, or use a distinct client object for each user. - BSON binary subtype 4 is decoded using RFC-4122 byte order regardless of the UUID representation. This is a change in behavior for applications that use UUID representation :data:`bson.binary.JAVA_LEGACY` or :data:`bson.binary.CSHARP_LEGACY` to decode BSON binary subtype 4. Other UUID representations, :data:`bson.binary.PYTHON_LEGACY` (the default) and :data:`bson.binary.STANDARD`, and the decoding of BSON binary subtype 3 are unchanged. Issues Resolved ............... See the `PyMongo 3.6 release notes in JIRA`_ for the list of resolved issues in this release. .. _PyMongo 3.6 release notes in JIRA: https://jira.mongodb.org/secure/ReleaseNote.jspa?projectId=10004&version=18043 Changes in Version 3.5.1 ------------------------ Version 3.5.1 fixes bugs reported since the release of 3.5.0: - Work around socket.getsockopt issue with NetBSD. - :meth:`pymongo.command_cursor.CommandCursor.close` now closes the cursor synchronously instead of deferring to a background thread. - Fix documentation build warnings with Sphinx 1.6.x. Issues Resolved ............... See the `PyMongo 3.5.1 release notes in JIRA`_ for the list of resolved issues in this release. .. _PyMongo 3.5.1 release notes in JIRA: https://jira.mongodb.org/secure/ReleaseNote.jspa?projectId=10004&version=18721 Changes in Version 3.5 ---------------------- Version 3.5 implements a number of improvements and bug fixes: Highlights include: - Username and password can be passed to :class:`~pymongo.mongo_client.MongoClient` as keyword arguments. Before, the only way to pass them was in the URI. - Increased the performance of using :class:`~bson.raw_bson.RawBSONDocument`. - Increased the performance of :meth:`~pymongo.mongo_client.MongoClient.database_names` by using the ``nameOnly`` option for listDatabases when available. - Increased the performance of :meth:`~pymongo.collection.Collection.bulk_write` by reducing the memory overhead of :class:`~pymongo.operations.InsertOne`, :class:`~pymongo.operations.DeleteOne`, and :class:`~pymongo.operations.DeleteMany`. - Added the ``collation`` option to :class:`~pymongo.operations.DeleteOne`, :class:`~pymongo.operations.DeleteMany`, :class:`~pymongo.operations.ReplaceOne`, :class:`~pymongo.operations.UpdateOne`, and :class:`~pymongo.operations.UpdateMany`. - Implemented the `MongoDB Extended JSON `_ specification. - :class:`~bson.decimal128.Decimal128` now works when cdecimal is installed. - PyMongo is now tested against a wider array of operating systems and CPU architectures (including s390x, ARM64, and POWER8). Changes and Deprecations: - :meth:`~pymongo.collection.Collection.find` has new options ``return_key``, ``show_record_id``, ``snapshot``, ``hint``, ``max_time_ms``, ``max_scan``, ``min``, ``max``, and ``comment``. Deprecated the option ``modifiers``. - Deprecated :meth:`~pymongo.collection.Collection.group`. The group command was deprecated in MongoDB 3.4 and is expected to be removed in MongoDB 3.6. Applications should use :meth:`~pymongo.collection.Collection.aggregate` with the ``$group`` pipeline stage instead. - Deprecated :meth:`~pymongo.database.Database.authenticate`. Authenticating multiple users conflicts with support for logical sessions in MongoDB 3.6. To authenticate as multiple users, create multiple instances of :class:`~pymongo.mongo_client.MongoClient`. - Deprecated :meth:`~pymongo.database.Database.eval`. The eval command was deprecated in MongoDB 3.0 and will be removed in a future server version. - Deprecated :class:`~pymongo.database.SystemJS`. - Deprecated :meth:`~pymongo.mongo_client.MongoClient.get_default_database`. Applications should use :meth:`~pymongo.mongo_client.MongoClient.get_database` without the ```name``` parameter instead. - Deprecated the MongoClient option ``socketKeepAlive```. It now defaults to true and disabling it is not recommended, see `does TCP keepalive time affect MongoDB Deployments? `_ - Deprecated :meth:`~pymongo.collection.Collection.initialize_ordered_bulk_op`, :meth:`~pymongo.collection.Collection.initialize_unordered_bulk_op`, and :class:`~pymongo.bulk.BulkOperationBuilder`. Use :meth:`~pymongo.collection.Collection.bulk_write` instead. - Deprecated :const:`~bson.json_util.STRICT_JSON_OPTIONS`. Use :const:`~bson.json_util.RELAXED_JSON_OPTIONS` or :const:`~bson.json_util.CANONICAL_JSON_OPTIONS` instead. - If a custom :class:`~bson.codec_options.CodecOptions` is passed to :class:`RawBSONDocument`, its ``document_class``` must be :class:`RawBSONDocument`. - :meth:`~pymongo.collection.Collection.list_indexes` no longer raises OperationFailure when the collection (or database) does not exist on MongoDB >= 3.0. Instead, it returns an empty :class:`~pymongo.command_cursor.CommandCursor` to make the behavior consistent across all MongoDB versions. - In Python 3, :meth:`~bson.json_util.loads` now automatically decodes JSON $binary with a subtype of 0 into :class:`bytes` instead of :class:`~bson.binary.Binary`. See the :doc:`/python3` for more details. - :meth:`~bson.json_util.loads` now raises ``TypeError`` or ``ValueError`` when parsing JSON type wrappers with values of the wrong type or any extra keys. - :meth:`pymongo.cursor.Cursor.close` and :meth:`pymongo.mongo_client.MongoClient.close` now kill cursors synchronously instead of deferring to a background thread. - :meth:`~pymongo.uri_parser.parse_uri` now returns the original value of the ``readPreference`` MongoDB URI option instead of the validated read preference mode. Issues Resolved ............... See the `PyMongo 3.5 release notes in JIRA`_ for the list of resolved issues in this release. .. _PyMongo 3.5 release notes in JIRA: https://jira.mongodb.org/secure/ReleaseNote.jspa?projectId=10004&version=17590 Changes in Version 3.4 ---------------------- Version 3.4 implements the new server features introduced in MongoDB 3.4 and a whole lot more: Highlights include: - Complete support for MongoDB 3.4: - Unicode aware string comparison using :doc:`examples/collations`. - Support for the new :class:`~bson.decimal128.Decimal128` BSON type. - A new maxStalenessSeconds read preference option. - A username is no longer required for the MONGODB-X509 authentication mechanism when connected to MongoDB >= 3.4. - :meth:`~pymongo.collection.Collection.parallel_scan` supports maxTimeMS. - :attr:`~pymongo.write_concern.WriteConcern` is automatically applied by all helpers for commands that write to the database when connected to MongoDB 3.4+. This change affects the following helpers: - :meth:`~pymongo.mongo_client.MongoClient.drop_database` - :meth:`~pymongo.database.Database.create_collection` - :meth:`~pymongo.database.Database.drop_collection` - :meth:`~pymongo.collection.Collection.aggregate` (when using $out) - :meth:`~pymongo.collection.Collection.create_indexes` - :meth:`~pymongo.collection.Collection.create_index` - :meth:`~pymongo.collection.Collection.drop_indexes` - :meth:`~pymongo.collection.Collection.drop_indexes` - :meth:`~pymongo.collection.Collection.drop_index` - :meth:`~pymongo.collection.Collection.map_reduce` (when output is not "inline") - :meth:`~pymongo.collection.Collection.reindex` - :meth:`~pymongo.collection.Collection.rename` - Improved support for logging server discovery and monitoring events. See :mod:`~pymongo.monitoring` for examples. - Support for matching iPAddress subjectAltName values for TLS certificate verification. - TLS compression is now explicitly disabled when possible. - The Server Name Indication (SNI) TLS extension is used when possible. - Finer control over JSON encoding/decoding with :class:`~bson.json_util.JSONOptions`. - Allow :class:`~bson.code.Code` objects to have a scope of ``None``, signifying no scope. Also allow encoding Code objects with an empty scope (i.e. ``{}``). .. warning:: Starting in PyMongo 3.4, :attr:`bson.code.Code.scope` may return ``None``, as the default scope is ``None`` instead of ``{}``. .. note:: PyMongo 3.4+ attempts to create sockets non-inheritable when possible (i.e. it sets the close-on-exec flag on socket file descriptors). Support is limited to a subset of POSIX operating systems (not including Windows) and the flag usually cannot be set in a single atomic operation. CPython 3.4+ implements `PEP 446`_, creating all file descriptors non-inheritable by default. Users that require this behavior are encouraged to upgrade to CPython 3.4+. Since 3.4rc0, the max staleness option has been renamed from ``maxStalenessMS`` to ``maxStalenessSeconds``, its smallest value has changed from twice ``heartbeatFrequencyMS`` to 90 seconds, and its default value has changed from ``None`` or 0 to -1. .. _PEP 446: https://www.python.org/dev/peps/pep-0446/ Issues Resolved ............... See the `PyMongo 3.4 release notes in JIRA`_ for the list of resolved issues in this release. .. _PyMongo 3.4 release notes in JIRA: https://jira.mongodb.org/secure/ReleaseNote.jspa?projectId=10004&version=16594 Changes in Version 3.3.1 ------------------------ Version 3.3.1 fixes a memory leak when decoding elements inside of a :class:`~bson.raw_bson.RawBSONDocument`. Issues Resolved ............... See the `PyMongo 3.3.1 release notes in Jira`_ for the list of resolved issues in this release. .. _PyMongo 3.3.1 release notes in Jira: https://jira.mongodb.org/secure/ReleaseNote.jspa?projectId=10004&version=17636 Changes in Version 3.3 ---------------------- Version 3.3 adds the following major new features: - C extensions support on big endian systems. - Kerberos authentication support on Windows using `WinKerberos `_. - A new ``ssl_clrfile`` option to support certificate revocation lists. - A new ``ssl_pem_passphrase`` option to support encrypted key files. - Support for publishing server discovery and monitoring events. See :mod:`~pymongo.monitoring` for details. - New connection pool options ``minPoolSize`` and ``maxIdleTimeMS``. - New ``heartbeatFrequencyMS`` option controls the rate at which background monitoring threads re-check servers. Default is once every 10 seconds. .. warning:: PyMongo 3.3 drops support for MongoDB versions older than 2.4. It also drops support for python 3.2 (pypy3 continues to be supported). Issues Resolved ............... See the `PyMongo 3.3 release notes in JIRA`_ for the list of resolved issues in this release. .. _PyMongo 3.3 release notes in JIRA: https://jira.mongodb.org/secure/ReleaseNote.jspa?projectId=10004&version=16005 Changes in Version 3.2.2 ------------------------ Version 3.2.2 fixes a few issues reported since the release of 3.2.1, including a fix for using the ``connect`` option in the MongoDB URI and support for setting the batch size for a query to 1 when using MongoDB 3.2+. Issues Resolved ............... See the `PyMongo 3.2.2 release notes in JIRA`_ for the list of resolved issues in this release. .. _PyMongo 3.2.2 release notes in JIRA: https://jira.mongodb.org/secure/ReleaseNote.jspa?projectId=10004&version=16538 Changes in Version 3.2.1 ------------------------ Version 3.2.1 fixes a few issues reported since the release of 3.2, including running the mapreduce command twice when calling the :meth:`~pymongo.collection.Collection.inline_map_reduce` method and a :exc:`TypeError` being raised when calling :meth:`~gridfs.GridFSBucket.download_to_stream`. This release also improves error messaging around BSON decoding. Issues Resolved ............... See the `PyMongo 3.2.1 release notes in JIRA`_ for the list of resolved issues in this release. .. _PyMongo 3.2.1 release notes in JIRA: https://jira.mongodb.org/secure/ReleaseNote.jspa?projectId=10004&version=16312 Changes in Version 3.2 ---------------------- Version 3.2 implements the new server features introduced in MongoDB 3.2. Highlights include: - Full support for MongoDB 3.2 including: - Support for :class:`~pymongo.read_concern.ReadConcern` - :class:`~pymongo.write_concern.WriteConcern` is now applied to :meth:`~pymongo.collection.Collection.find_one_and_replace`, :meth:`~pymongo.collection.Collection.find_one_and_update`, and :meth:`~pymongo.collection.Collection.find_one_and_delete`. - Support for the new ``bypassDocumentValidation`` option in write helpers. - Support for reading and writing raw BSON with :class:`~bson.raw_bson.RawBSONDocument` .. note:: Certain :class:`~pymongo.mongo_client.MongoClient` properties now block until a connection is established or raise :exc:`~pymongo.errors.ServerSelectionTimeoutError` if no server is available. See :class:`~pymongo.mongo_client.MongoClient` for details. Issues Resolved ............... See the `PyMongo 3.2 release notes in JIRA`_ for the list of resolved issues in this release. .. _PyMongo 3.2 release notes in JIRA: https://jira.mongodb.org/secure/ReleaseNote.jspa?projectId=10004&version=15612 Changes in Version 3.1.1 ------------------------ Version 3.1.1 fixes a few issues reported since the release of 3.1, including a regression in error handling for oversize command documents and interrupt handling issues in the C extensions. Issues Resolved ............... See the `PyMongo 3.1.1 release notes in JIRA`_ for the list of resolved issues in this release. .. _PyMongo 3.1.1 release notes in JIRA: https://jira.mongodb.org/secure/ReleaseNote.jspa?projectId=10004&version=16211 Changes in Version 3.1 ---------------------- Version 3.1 implements a few new features and fixes bugs reported since the release of 3.0.3. Highlights include: - Command monitoring support. See :mod:`~pymongo.monitoring` for details. - Configurable error handling for :exc:`UnicodeDecodeError`. See the ``unicode_decode_error_handler`` option of :class:`~bson.codec_options.CodecOptions`. - Optional automatic timezone conversion when decoding BSON datetime. See the ``tzinfo`` option of :class:`~bson.codec_options.CodecOptions`. - An implementation of :class:`~gridfs.GridFSBucket` from the new GridFS spec. - Compliance with the new Connection String spec. - Reduced idle CPU usage in Python 2. Changes in internal classes ........................... The private ``PeriodicExecutor`` class no longer takes a ``condition_class`` option, and the private ``thread_util.Event`` class is removed. Issues Resolved ............... See the `PyMongo 3.1 release notes in JIRA`_ for the list of resolved issues in this release. .. _PyMongo 3.1 release notes in JIRA: https://jira.mongodb.org/secure/ReleaseNote.jspa?projectId=10004&version=14796 Changes in Version 3.0.3 ------------------------ Version 3.0.3 fixes issues reported since the release of 3.0.2, including a feature breaking bug in the GSSAPI implementation. Issues Resolved ............... See the `PyMongo 3.0.3 release notes in JIRA`_ for the list of resolved issues in this release. .. _PyMongo 3.0.3 release notes in JIRA: https://jira.mongodb.org/secure/ReleaseNote.jspa?projectId=10004&version=15528 Changes in Version 3.0.2 ------------------------ Version 3.0.2 fixes issues reported since the release of 3.0.1, most importantly a bug that could route operations to replica set members that are not in primary or secondary state when using :class:`~pymongo.read_preferences.PrimaryPreferred` or :class:`~pymongo.read_preferences.Nearest`. It is a recommended upgrade for all users of PyMongo 3.0.x. Issues Resolved ............... See the `PyMongo 3.0.2 release notes in JIRA`_ for the list of resolved issues in this release. .. _PyMongo 3.0.2 release notes in JIRA: https://jira.mongodb.org/secure/ReleaseNote.jspa?projectId=10004&version=15430 Changes in Version 3.0.1 ------------------------ Version 3.0.1 fixes issues reported since the release of 3.0, most importantly a bug in GridFS.delete that could prevent file chunks from actually being deleted. Issues Resolved ............... See the `PyMongo 3.0.1 release notes in JIRA`_ for the list of resolved issues in this release. .. _PyMongo 3.0.1 release notes in JIRA: https://jira.mongodb.org/secure/ReleaseNote.jspa?projectId=10004&version=15322 Changes in Version 3.0 ---------------------- PyMongo 3.0 is a partial rewrite of PyMongo bringing a large number of improvements: - A unified client class. MongoClient is the one and only client class for connecting to a standalone mongod, replica set, or sharded cluster. Migrating from a standalone, to a replica set, to a sharded cluster can be accomplished with only a simple URI change. - MongoClient is much more responsive to configuration changes in your MongoDB deployment. All connected servers are monitored in a non-blocking manner. Slow to respond or down servers no longer block server discovery, reducing application startup time and time to respond to new or reconfigured servers and replica set failovers. - A unified CRUD API. All official MongoDB drivers now implement a standard CRUD API allowing polyglot developers to move from language to language with ease. - Single source support for Python 2.x and 3.x. PyMongo no longer relies on 2to3 to support Python 3. - A rewritten pure Python BSON implementation, improving performance with pypy and cpython deployments without support for C extensions. - Better support for greenlet based async frameworks including eventlet. - Immutable client, database, and collection classes, avoiding a host of thread safety issues in client applications. PyMongo 3.0 brings a large number of API changes. Be sure to read the changes listed below before upgrading from PyMongo 2.x. .. warning:: PyMongo no longer supports Python 2.4, 2.5, or 3.1. If you must use PyMongo with these versions of Python the 2.x branch of PyMongo will be minimally supported for some time. SONManipulator changes ...................... The :class:`~pymongo.son_manipulator.SONManipulator` API has limitations as a technique for transforming your data. Instead, it is more flexible and straightforward to transform outgoing documents in your own code before passing them to PyMongo, and transform incoming documents after receiving them from PyMongo. Thus the :meth:`~pymongo.database.Database.add_son_manipulator` method is deprecated. PyMongo 3's new CRUD API does **not** apply SON manipulators to documents passed to :meth:`~pymongo.collection.Collection.bulk_write`, :meth:`~pymongo.collection.Collection.insert_one`, :meth:`~pymongo.collection.Collection.insert_many`, :meth:`~pymongo.collection.Collection.update_one`, or :meth:`~pymongo.collection.Collection.update_many`. SON manipulators are **not** applied to documents returned by the new methods :meth:`~pymongo.collection.Collection.find_one_and_delete`, :meth:`~pymongo.collection.Collection.find_one_and_replace`, and :meth:`~pymongo.collection.Collection.find_one_and_update`. SSL/TLS changes ............... When ``ssl`` is ``True`` the ``ssl_cert_reqs`` option now defaults to :attr:`ssl.CERT_REQUIRED` if not provided. PyMongo will attempt to load OS provided CA certificates to verify the server, raising :exc:`~pymongo.errors.ConfigurationError` if it cannot. Gevent Support .............. In previous versions, PyMongo supported Gevent in two modes: you could call ``gevent.monkey.patch_socket()`` and pass ``use_greenlets=True`` to :class:`~pymongo.mongo_client.MongoClient`, or you could simply call ``gevent.monkey.patch_all()`` and omit the ``use_greenlets`` argument. In PyMongo 3.0, the ``use_greenlets`` option is gone. To use PyMongo with Gevent simply call ``gevent.monkey.patch_all()``. For more information, see :doc:`PyMongo's Gevent documentation `. :class:`~pymongo.mongo_client.MongoClient` changes .................................................. :class:`~pymongo.mongo_client.MongoClient` is now the one and only client class for a standalone server, mongos, or replica set. It includes the functionality that had been split into ``MongoReplicaSetClient``: it can connect to a replica set, discover all its members, and monitor the set for stepdowns, elections, and reconfigs. :class:`~pymongo.mongo_client.MongoClient` now also supports the full :class:`~pymongo.read_preferences.ReadPreference` API. The obsolete classes ``MasterSlaveConnection``, ``Connection``, and ``ReplicaSetConnection`` are removed. The :class:`~pymongo.mongo_client.MongoClient` constructor no longer blocks while connecting to the server or servers, and it no longer raises :class:`~pymongo.errors.ConnectionFailure` if they are unavailable, nor :class:`~pymongo.errors.ConfigurationError` if the user's credentials are wrong. Instead, the constructor returns immediately and launches the connection process on background threads. The ``connect`` option is added to control whether these threads are started immediately, or when the client is first used. Therefore the ``alive`` method is removed since it no longer provides meaningful information; even if the client is disconnected, it may discover a server in time to fulfill the next operation. In PyMongo 2.x, :class:`~pymongo.mongo_client.MongoClient` accepted a list of standalone MongoDB servers and used the first it could connect to:: MongoClient(['host1.com:27017', 'host2.com:27017']) A list of multiple standalones is no longer supported; if multiple servers are listed they must be members of the same replica set, or mongoses in the same sharded cluster. The behavior for a list of mongoses is changed from "high availability" to "load balancing". Before, the client connected to the lowest-latency mongos in the list, and used it until a network error prompted it to re-evaluate all mongoses' latencies and reconnect to one of them. In PyMongo 3, the client monitors its network latency to all the mongoses continuously, and distributes operations evenly among those with the lowest latency. See :ref:`mongos-load-balancing` for more information. The client methods ``start_request``, ``in_request``, and ``end_request`` are removed, and so is the ``auto_start_request`` option. Requests were designed to make read-your-writes consistency more likely with the ``w=0`` write concern. Additionally, a thread in a request used the same member for all secondary reads in a replica set. To ensure read-your-writes consistency in PyMongo 3.0, do not override the default write concern with ``w=0``, and do not override the default :ref:`read preference ` of PRIMARY. Support for the ``slaveOk`` (or ``slave_okay``), ``safe``, and ``network_timeout`` options has been removed. Use :attr:`~pymongo.read_preferences.ReadPreference.SECONDARY_PREFERRED` instead of slave_okay. Accept the default write concern, acknowledged writes, instead of setting safe=True. Use socketTimeoutMS in place of network_timeout (note that network_timeout was in seconds, where as socketTimeoutMS is milliseconds). The ``max_pool_size`` option has been removed. It is replaced by the ``maxPoolSize`` MongoDB URI option. ``maxPoolSize`` is now a supported URI option in PyMongo and can be passed as a keyword argument. The ``copy_database`` method is removed, see the :doc:`copy_database examples ` for alternatives. The ``disconnect`` method is removed. Use :meth:`~pymongo.mongo_client.MongoClient.close` instead. The ``get_document_class`` method is removed. Use :attr:`~pymongo.mongo_client.MongoClient.codec_options` instead. The ``get_lasterror_options``, ``set_lasterror_options``, and ``unset_lasterror_options`` methods are removed. Write concern options can be passed to :class:`~pymongo.mongo_client.MongoClient` as keyword arguments or MongoDB URI options. The :meth:`~pymongo.mongo_client.MongoClient.get_database` method is added for getting a Database instance with its options configured differently than the MongoClient's. The following read-only attributes have been added: - :attr:`~pymongo.mongo_client.MongoClient.codec_options` The following attributes are now read-only: - :attr:`~pymongo.mongo_client.MongoClient.read_preference` - :attr:`~pymongo.mongo_client.MongoClient.write_concern` The following attributes have been removed: - :attr:`~pymongo.mongo_client.MongoClient.document_class` (use :attr:`~pymongo.mongo_client.MongoClient.codec_options` instead) - :attr:`~pymongo.mongo_client.MongoClient.host` (use :attr:`~pymongo.mongo_client.MongoClient.address` instead) - :attr:`~pymongo.mongo_client.MongoClient.min_wire_version` - :attr:`~pymongo.mongo_client.MongoClient.max_wire_version` - :attr:`~pymongo.mongo_client.MongoClient.port` (use :attr:`~pymongo.mongo_client.MongoClient.address` instead) - :attr:`~pymongo.mongo_client.MongoClient.safe` (use :attr:`~pymongo.mongo_client.MongoClient.write_concern` instead) - :attr:`~pymongo.mongo_client.MongoClient.slave_okay` (use :attr:`~pymongo.mongo_client.MongoClient.read_preference` instead) - :attr:`~pymongo.mongo_client.MongoClient.tag_sets` (use :attr:`~pymongo.mongo_client.MongoClient.read_preference` instead) - :attr:`~pymongo.mongo_client.MongoClient.tz_aware` (use :attr:`~pymongo.mongo_client.MongoClient.codec_options` instead) The following attributes have been renamed: - :attr:`~pymongo.mongo_client.MongoClient.secondary_acceptable_latency_ms` is now :attr:`~pymongo.mongo_client.MongoClient.local_threshold_ms` and is now read-only. :class:`~pymongo.cursor.Cursor` changes ....................................... The ``conn_id`` property is renamed to :attr:`~pymongo.cursor.Cursor.address`. Cursor management changes ......................... :class:`~pymongo.cursor_manager.CursorManager` and :meth:`~pymongo.mongo_client.MongoClient.set_cursor_manager` are no longer deprecated. If you subclass :class:`~pymongo.cursor_manager.CursorManager` your implementation of :meth:`~pymongo.cursor_manager.CursorManager.close` must now take a second parameter, ``address``. The ``BatchCursorManager`` class is removed. The second parameter to :meth:`~pymongo.mongo_client.MongoClient.close_cursor` is renamed from ``_conn_id`` to ``address``. :meth:`~pymongo.mongo_client.MongoClient.kill_cursors` now accepts an ``address`` parameter. :class:`~pymongo.database.Database` changes ........................................... The ``connection`` property is renamed to :attr:`~pymongo.database.Database.client`. The following read-only attributes have been added: - :attr:`~pymongo.database.Database.codec_options` The following attributes are now read-only: - :attr:`~pymongo.database.Database.read_preference` - :attr:`~pymongo.database.Database.write_concern` Use :meth:`~pymongo.mongo_client.MongoClient.get_database` for getting a Database instance with its options configured differently than the MongoClient's. The following attributes have been removed: - :attr:`~pymongo.database.Database.safe` - :attr:`~pymongo.database.Database.secondary_acceptable_latency_ms` - :attr:`~pymongo.database.Database.slave_okay` - :attr:`~pymongo.database.Database.tag_sets` The following methods have been added: - :meth:`~pymongo.database.Database.get_collection` The following methods have been changed: - :meth:`~pymongo.database.Database.command`. Support for ``as_class``, ``uuid_subtype``, ``tag_sets``, and ``secondary_acceptable_latency_ms`` have been removed. You can instead pass an instance of :class:`~bson.codec_options.CodecOptions` as ``codec_options`` and an instance of a read preference class from :mod:`~pymongo.read_preferences` as ``read_preference``. The ``fields`` and ``compile_re`` options are also removed. The ``fields`` options was undocumented and never really worked. Regular expressions are always decoded to :class:`~bson.regex.Regex`. The following methods have been deprecated: - :meth:`~pymongo.database.Database.add_son_manipulator` The following methods have been removed: The ``get_lasterror_options``, ``set_lasterror_options``, and ``unset_lasterror_options`` methods have been removed. Use :class:`~pymongo.write_concern.WriteConcern` with :meth:`~pymongo.mongo_client.MongoClient.get_database` instead. :class:`~pymongo.collection.Collection` changes ............................................... The following read-only attributes have been added: - :attr:`~pymongo.collection.Collection.codec_options` The following attributes are now read-only: - :attr:`~pymongo.collection.Collection.read_preference` - :attr:`~pymongo.collection.Collection.write_concern` Use :meth:`~pymongo.database.Database.get_collection` or :meth:`~pymongo.collection.Collection.with_options` for getting a Collection instance with its options configured differently than the Database's. The following attributes have been removed: - :attr:`~pymongo.collection.Collection.safe` - :attr:`~pymongo.collection.Collection.secondary_acceptable_latency_ms` - :attr:`~pymongo.collection.Collection.slave_okay` - :attr:`~pymongo.collection.Collection.tag_sets` The following methods have been added: - :meth:`~pymongo.collection.Collection.bulk_write` - :meth:`~pymongo.collection.Collection.insert_one` - :meth:`~pymongo.collection.Collection.insert_many` - :meth:`~pymongo.collection.Collection.update_one` - :meth:`~pymongo.collection.Collection.update_many` - :meth:`~pymongo.collection.Collection.replace_one` - :meth:`~pymongo.collection.Collection.delete_one` - :meth:`~pymongo.collection.Collection.delete_many` - :meth:`~pymongo.collection.Collection.find_one_and_delete` - :meth:`~pymongo.collection.Collection.find_one_and_replace` - :meth:`~pymongo.collection.Collection.find_one_and_update` - :meth:`~pymongo.collection.Collection.with_options` - :meth:`~pymongo.collection.Collection.create_indexes` - :meth:`~pymongo.collection.Collection.list_indexes` The following methods have changed: - :meth:`~pymongo.collection.Collection.aggregate` now **always** returns an instance of :class:`~pymongo.command_cursor.CommandCursor`. See the documentation for all options. - :meth:`~pymongo.collection.Collection.count` now optionally takes a filter argument, as well as other options supported by the count command. - :meth:`~pymongo.collection.Collection.distinct` now optionally takes a filter argument. - :meth:`~pymongo.collection.Collection.create_index` no longer caches indexes, therefore the ``cache_for`` parameter has been removed. It also no longer supports the ``bucket_size`` and ``drop_dups`` aliases for ``bucketSize`` and ``dropDups``. The following methods are deprecated: - :meth:`~pymongo.collection.Collection.save` - :meth:`~pymongo.collection.Collection.insert` - :meth:`~pymongo.collection.Collection.update` - :meth:`~pymongo.collection.Collection.remove` - :meth:`~pymongo.collection.Collection.find_and_modify` - :meth:`~pymongo.collection.Collection.ensure_index` The following methods have been removed: The ``get_lasterror_options``, ``set_lasterror_options``, and ``unset_lasterror_options`` methods have been removed. Use :class:`~pymongo.write_concern.WriteConcern` with :meth:`~pymongo.collection.Collection.with_options` instead. Changes to :meth:`~pymongo.collection.Collection.find` and :meth:`~pymongo.collection.Collection.find_one` `````````````````````````````````````````````````````````````````````````````````````````````````````````` The following find/find_one options have been renamed: These renames only affect your code if you passed these as keyword arguments, like find(fields=['fieldname']). If you passed only positional parameters these changes are not significant for your application. - spec -> filter - fields -> projection - partial -> allow_partial_results The following find/find_one options have been added: - cursor_type (see :class:`~pymongo.cursor.CursorType` for values) - oplog_replay - modifiers The following find/find_one options have been removed: - network_timeout (use :meth:`~pymongo.cursor.Cursor.max_time_ms` instead) - slave_okay (use one of the read preference classes from :mod:`~pymongo.read_preferences` and :meth:`~pymongo.collection.Collection.with_options` instead) - read_preference (use :meth:`~pymongo.collection.Collection.with_options` instead) - tag_sets (use one of the read preference classes from :mod:`~pymongo.read_preferences` and :meth:`~pymongo.collection.Collection.with_options` instead) - secondary_acceptable_latency_ms (use the ``localThresholdMS`` URI option instead) - max_scan (use the new ``modifiers`` option instead) - snapshot (use the new ``modifiers`` option instead) - tailable (use the new ``cursor_type`` option instead) - await_data (use the new ``cursor_type`` option instead) - exhaust (use the new ``cursor_type`` option instead) - as_class (use :meth:`~pymongo.collection.Collection.with_options` with :class:`~bson.codec_options.CodecOptions` instead) - compile_re (BSON regular expressions are always decoded to :class:`~bson.regex.Regex`) The following find/find_one options are deprecated: - manipulate The following renames need special handling. - timeout -> no_cursor_timeout - The default for ``timeout`` was True. The default for ``no_cursor_timeout`` is False. If you were previously passing False for ``t`imeout`` you must pass **True** for ``no_cursor_timeout`` to keep the previous behavior. :mod:`~pymongo.errors` changes .............................. The exception classes ``UnsupportedOption`` and ``TimeoutError`` are deleted. :mod:`~gridfs` changes ...................... Since PyMongo 1.6, methods ``open`` and ``close`` of :class:`~gridfs.GridFS` raised an ``UnsupportedAPI`` exception, as did the entire ``GridFile`` class. The unsupported methods, the class, and the exception are all deleted. :mod:`~bson` changes .................... The ``compile_re`` option is removed from all methods that accepted it in :mod:`~bson` and :mod:`~bson.json_util`. Additionally, it is removed from :meth:`~pymongo.collection.Collection.find`, :meth:`~pymongo.collection.Collection.find_one`, :meth:`~pymongo.collection.Collection.aggregate`, :meth:`~pymongo.database.Database.command`, and so on. PyMongo now always represents BSON regular expressions as :class:`~bson.regex.Regex` objects. This prevents errors for incompatible patterns, see `PYTHON-500`_. Use :meth:`~bson.regex.Regex.try_compile` to attempt to convert from a BSON regular expression to a Python regular expression object. PyMongo now decodes the int64 BSON type to :class:`~bson.int64.Int64`, a trivial wrapper around long (in python 2.x) or int (in python 3.x). This allows BSON int64 to be round tripped without losing type information in python 3. Note that if you store a python long (or a python int larger than 4 bytes) it will be returned from PyMongo as :class:`~bson.int64.Int64`. The ``as_class``, ``tz_aware``, and ``uuid_subtype`` options are removed from all BSON encoding and decoding methods. Use :class:`~bson.codec_options.CodecOptions` to configure these options. The APIs affected are: - :func:`~bson.decode_all` - :func:`~bson.decode_iter` - :func:`~bson.decode_file_iter` - :meth:`~bson.BSON.encode` - :meth:`~bson.BSON.decode` This is a breaking change for any application that uses the BSON API directly and changes any of the named parameter defaults. No changes are required for applications that use the default values for these options. The behavior remains the same. .. _PYTHON-500: https://jira.mongodb.org/browse/PYTHON-500 Issues Resolved ............... See the `PyMongo 3.0 release notes in JIRA`_ for the list of resolved issues in this release. .. _PyMongo 3.0 release notes in JIRA: https://jira.mongodb.org/secure/ReleaseNote.jspa?projectId=10004&version=12501 Changes in Version 2.9.5 ------------------------ Version 2.9.5 works around ssl module deprecations in Python 3.6, and expected future ssl module deprecations. It also fixes bugs found since the release of 2.9.4. - Use ssl.SSLContext and ssl.PROTOCOL_TLS_CLIENT when available. - Fixed a C extensions build issue when the interpreter was built with -std=c99 - Fixed various build issues with MinGW32. - Fixed a write concern bug in :meth:`~pymongo.database.Database.add_user` and :meth:`~pymongo.database.Database.remove_user` when connected to MongoDB 3.2+ - Fixed various test failures related to changes in gevent, MongoDB, and our CI test environment. Issues Resolved ............... See the `PyMongo 2.9.5 release notes in JIRA`_ for the list of resolved issues in this release. .. _PyMongo 2.9.5 release notes in JIRA: https://jira.mongodb.org/secure/ReleaseNote.jspa?projectId=10004&version=17605 Changes in Version 2.9.4 ------------------------ Version 2.9.4 fixes issues reported since the release of 2.9.3. - Fixed __repr__ for closed instances of :class:`~pymongo.mongo_client.MongoClient`. - Fixed :class:`~pymongo.mongo_replica_set_client.MongoReplicaSetClient` handling of uuidRepresentation. - Fixed building and testing the documentation with python 3.x. - New documentation for :doc:`examples/tls` and :doc:`atlas`. Issues Resolved ............... See the `PyMongo 2.9.4 release notes in JIRA`_ for the list of resolved issues in this release. .. _PyMongo 2.9.4 release notes in JIRA: https://jira.mongodb.org/secure/ReleaseNote.jspa?projectId=10004&version=16885 Changes in Version 2.9.3 ------------------------ Version 2.9.3 fixes a few issues reported since the release of 2.9.2 including thread safety issues in :meth:`~pymongo.collection.Collection.ensure_index`, :meth:`~pymongo.collection.Collection.drop_index`, and :meth:`~pymongo.collection.Collection.drop_indexes`. Issues Resolved ............... See the `PyMongo 2.9.3 release notes in JIRA`_ for the list of resolved issues in this release. .. _PyMongo 2.9.3 release notes in JIRA: https://jira.mongodb.org/secure/ReleaseNote.jspa?projectId=10004&version=16539 Changes in Version 2.9.2 ------------------------ Version 2.9.2 restores Python 3.1 support, which was broken in PyMongo 2.8. It improves an error message when decoding BSON as well as fixes a couple other issues including :meth:`~pymongo.collection.Collection.aggregate` ignoring :attr:`~pymongo.collection.Collection.codec_options` and :meth:`~pymongo.database.Database.command` raising a superfluous ``DeprecationWarning``. Issues Resolved ............... See the `PyMongo 2.9.2 release notes in JIRA`_ for the list of resolved issues in this release. .. _PyMongo 2.9.2 release notes in JIRA: https://jira.mongodb.org/secure/ReleaseNote.jspa?projectId=10004&version=16303 Changes in Version 2.9.1 ------------------------ Version 2.9.1 fixes two interrupt handling issues in the C extensions and adapts a test case for a behavior change in MongoDB 3.2. Issues Resolved ............... See the `PyMongo 2.9.1 release notes in JIRA`_ for the list of resolved issues in this release. .. _PyMongo 2.9.1 release notes in JIRA: https://jira.mongodb.org/secure/ReleaseNote.jspa?projectId=10004&version=16208 Changes in Version 2.9 ---------------------- Version 2.9 provides an upgrade path to PyMongo 3.x. Most of the API changes from PyMongo 3.0 have been backported in a backward compatible way, allowing applications to be written against PyMongo >= 2.9, rather then PyMongo 2.x or PyMongo 3.x. See the `PyMongo 3 Migration Guide `_ for detailed examples. .. note:: There are a number of new deprecations in this release for features that were removed in PyMongo 3.0. :class:`~pymongo.mongo_client.MongoClient`: - :attr:`~pymongo.mongo_client.MongoClient.host` - :attr:`~pymongo.mongo_client.MongoClient.port` - :attr:`~pymongo.mongo_client.MongoClient.use_greenlets` - :attr:`~pymongo.mongo_client.MongoClient.document_class` - :attr:`~pymongo.mongo_client.MongoClient.tz_aware` - :attr:`~pymongo.mongo_client.MongoClient.secondary_acceptable_latency_ms` - :attr:`~pymongo.mongo_client.MongoClient.tag_sets` - :attr:`~pymongo.mongo_client.MongoClient.uuid_subtype` - :meth:`~pymongo.mongo_client.MongoClient.disconnect` - :meth:`~pymongo.mongo_client.MongoClient.alive` :class:`~pymongo.mongo_replica_set_client.MongoReplicaSetClient`: - :attr:`~pymongo.mongo_replica_set_client.MongoReplicaSetClient.use_greenlets` - :attr:`~pymongo.mongo_replica_set_client.MongoReplicaSetClient.document_class` - :attr:`~pymongo.mongo_replica_set_client.MongoReplicaSetClient.tz_aware` - :attr:`~pymongo.mongo_replica_set_client.MongoReplicaSetClient.secondary_acceptable_latency_ms` - :attr:`~pymongo.mongo_replica_set_client.MongoReplicaSetClient.tag_sets` - :attr:`~pymongo.mongo_replica_set_client.MongoReplicaSetClient.uuid_subtype` - :meth:`~pymongo.mongo_replica_set_client.MongoReplicaSetClient.alive` :class:`~pymongo.database.Database`: - :attr:`~pymongo.database.Database.secondary_acceptable_latency_ms` - :attr:`~pymongo.database.Database.tag_sets` - :attr:`~pymongo.database.Database.uuid_subtype` :class:`~pymongo.collection.Collection`: - :attr:`~pymongo.collection.Collection.secondary_acceptable_latency_ms` - :attr:`~pymongo.collection.Collection.tag_sets` - :attr:`~pymongo.collection.Collection.uuid_subtype` .. warning:: In previous versions of PyMongo, changing the value of :attr:`~pymongo.mongo_client.MongoClient.document_class` changed the behavior of all existing instances of :class:`~pymongo.collection.Collection`:: >>> coll = client.test.test >>> coll.find_one() {u'_id': ObjectId('5579dc7cfba5220cc14d9a18')} >>> from bson.son import SON >>> client.document_class = SON >>> coll.find_one() SON([(u'_id', ObjectId('5579dc7cfba5220cc14d9a18'))]) The document_class setting is now configurable at the client, database, collection, and per-operation level. This required breaking the existing behavior. To change the document class per operation in a forward compatible way use :meth:`~pymongo.collection.Collection.with_options`:: >>> coll.find_one() {u'_id': ObjectId('5579dc7cfba5220cc14d9a18')} >>> from bson.codec_options import CodecOptions >>> coll.with_options(CodecOptions(SON)).find_one() SON([(u'_id', ObjectId('5579dc7cfba5220cc14d9a18'))]) Issues Resolved ............... See the `PyMongo 2.9 release notes in JIRA`_ for the list of resolved issues in this release. .. _PyMongo 2.9 release notes in JIRA: https://jira.mongodb.org/secure/ReleaseNote.jspa?projectId=10004&version=14795 Changes in Version 2.8.1 ------------------------ Version 2.8.1 fixes a number of issues reported since the release of PyMongo 2.8. It is a recommended upgrade for all users of PyMongo 2.x. Issues Resolved ............... See the `PyMongo 2.8.1 release notes in JIRA`_ for the list of resolved issues in this release. .. _PyMongo 2.8.1 release notes in JIRA: https://jira.mongodb.org/secure/ReleaseNote.jspa?projectId=10004&version=15324 Changes in Version 2.8 ---------------------- Version 2.8 is a major release that provides full support for MongoDB 3.0 and fixes a number of bugs. Special thanks to Don Mitchell, Ximing, Can Zhang, Sergey Azovskov, and Heewa Barfchin for their contributions to this release. Highlights include: - Support for the SCRAM-SHA-1 authentication mechanism (new in MongoDB 3.0). - JSON decoder support for the new $numberLong and $undefined types. - JSON decoder support for the $date type as an ISO-8601 string. - Support passing an index name to :meth:`~pymongo.cursor.Cursor.hint`. - The :meth:`~pymongo.cursor.Cursor.count` method will use a hint if one has been provided through :meth:`~pymongo.cursor.Cursor.hint`. - A new socketKeepAlive option for the connection pool. - New generator based BSON decode functions, :func:`~bson.decode_iter` and :func:`~bson.decode_file_iter`. - Internal changes to support alternative storage engines like wiredtiger. .. note:: There are a number of deprecations in this release for features that will be removed in PyMongo 3.0. These include: - :meth:`~pymongo.mongo_client.MongoClient.start_request` - :meth:`~pymongo.mongo_client.MongoClient.in_request` - :meth:`~pymongo.mongo_client.MongoClient.end_request` - :meth:`~pymongo.mongo_client.MongoClient.copy_database` - :meth:`~pymongo.database.Database.error` - :meth:`~pymongo.database.Database.last_status` - :meth:`~pymongo.database.Database.previous_error` - :meth:`~pymongo.database.Database.reset_error_history` - :class:`~pymongo.master_slave_connection.MasterSlaveConnection` The JSON format for :class:`~bson.timestamp.Timestamp` has changed from '{"t": , "i": }' to '{"$timestamp": {"t": , "i": }}'. This new format will be decoded to an instance of :class:`~bson.timestamp.Timestamp`. The old format will continue to be decoded to a python dict as before. Encoding to the old format is no longer supported as it was never correct and loses type information. Issues Resolved ............... See the `PyMongo 2.8 release notes in JIRA`_ for the list of resolved issues in this release. .. _PyMongo 2.8 release notes in JIRA: https://jira.mongodb.org/secure/ReleaseNote.jspa?projectId=10004&version=14223 Changes in Version 2.7.2 ------------------------ Version 2.7.2 includes fixes for upsert reporting in the bulk API for MongoDB versions previous to 2.6, a regression in how son manipulators are applied in :meth:`~pymongo.collection.Collection.insert`, a few obscure connection pool semaphore leaks, and a few other minor issues. See the list of issues resolved for full details. Issues Resolved ............... See the `PyMongo 2.7.2 release notes in JIRA`_ for the list of resolved issues in this release. .. _PyMongo 2.7.2 release notes in JIRA: https://jira.mongodb.org/secure/ReleaseNote.jspa?projectId=10004&version=14005 Changes in Version 2.7.1 ------------------------ Version 2.7.1 fixes a number of issues reported since the release of 2.7, most importantly a fix for creating indexes and manipulating users through mongos versions older than 2.4.0. Issues Resolved ............... See the `PyMongo 2.7.1 release notes in JIRA`_ for the list of resolved issues in this release. .. _PyMongo 2.7.1 release notes in JIRA: https://jira.mongodb.org/secure/ReleaseNote.jspa?projectId=10004&version=13823 Changes in Version 2.7 ---------------------- PyMongo 2.7 is a major release with a large number of new features and bug fixes. Highlights include: - Full support for MongoDB 2.6. - A new :doc:`bulk write operations API `. - Support for server side query timeouts using :meth:`~pymongo.cursor.Cursor.max_time_ms`. - Support for writing :meth:`~pymongo.collection.Collection.aggregate` output to a collection. - A new :meth:`~pymongo.collection.Collection.parallel_scan` helper. - :class:`~pymongo.errors.OperationFailure` and its subclasses now include a :attr:`~pymongo.errors.OperationFailure.details` attribute with complete error details from the server. - A new GridFS :meth:`~gridfs.GridFS.find` method that returns a :class:`~gridfs.grid_file.GridOutCursor`. - Greatly improved :doc:`support for mod_wsgi ` when using PyMongo's C extensions. Read `Jesse's blog post `_ for details. - Improved C extension support for ARM little endian. Breaking changes ................ Version 2.7 drops support for replica sets running MongoDB versions older than 1.6.2. Issues Resolved ............... See the `PyMongo 2.7 release notes in JIRA`_ for the list of resolved issues in this release. .. _PyMongo 2.7 release notes in JIRA: https://jira.mongodb.org/secure/ReleaseNote.jspa?projectId=10004&version=12892 Changes in Version 2.6.3 ------------------------ Version 2.6.3 fixes issues reported since the release of 2.6.2, most importantly a semaphore leak when a connection to the server fails. Issues Resolved ............... See the `PyMongo 2.6.3 release notes in JIRA`_ for the list of resolved issues in this release. .. _PyMongo 2.6.3 release notes in JIRA: https://jira.mongodb.org/secure/ReleaseNote.jspa?projectId=10004&version=13098 Changes in Version 2.6.2 ------------------------ Version 2.6.2 fixes a :exc:`TypeError` problem when max_pool_size=None is used in Python 3. Issues Resolved ............... See the `PyMongo 2.6.2 release notes in JIRA`_ for the list of resolved issues in this release. .. _PyMongo 2.6.2 release notes in JIRA: https://jira.mongodb.org/secure/ReleaseNote.jspa?projectId=10004&version=12910 Changes in Version 2.6.1 ------------------------ Version 2.6.1 fixes a reference leak in the :meth:`~pymongo.collection.Collection.insert` method. Issues Resolved ............... See the `PyMongo 2.6.1 release notes in JIRA`_ for the list of resolved issues in this release. .. _PyMongo 2.6.1 release notes in JIRA: https://jira.mongodb.org/secure/ReleaseNote.jspa?projectId=10004&version=12905 Changes in Version 2.6 ---------------------- Version 2.6 includes some frequently requested improvements and adds support for some early MongoDB 2.6 features. Special thanks go to Justin Patrin for his work on the connection pool in this release. Important new features: - The ``max_pool_size`` option for :class:`~pymongo.mongo_client.MongoClient` and :class:`~pymongo.mongo_replica_set_client.MongoReplicaSetClient` now actually caps the number of sockets the pool will open concurrently. Once the pool has reaches max_pool_size operations will block waiting for a socket to become available. If ``waitQueueTimeoutMS`` is set, an operation that blocks waiting for a socket will raise :exc:`~pymongo.errors.ConnectionFailure` after the timeout. By default ``waitQueueTimeoutMS`` is not set. See :ref:`connection-pooling` for more information. - The :meth:`~pymongo.collection.Collection.insert` method automatically splits large batches of documents into multiple insert messages based on :attr:`~pymongo.mongo_client.MongoClient.max_message_size` - Support for the exhaust cursor flag. See :meth:`~pymongo.collection.Collection.find` for details and caveats. - Support for the PLAIN and MONGODB-X509 authentication mechanisms. See :doc:`the authentication docs ` for more information. - Support aggregation output as a :class:`~pymongo.cursor.Cursor`. See :meth:`~pymongo.collection.Collection.aggregate` for details. .. warning:: SIGNIFICANT BEHAVIOR CHANGE in 2.6. Previously, ``max_pool_size`` would limit only the idle sockets the pool would hold onto, not the number of open sockets. The default has also changed, from 10 to 100. If you pass a value for ``max_pool_size`` make sure it is large enough for the expected load. (Sockets are only opened when needed, so there is no cost to having a ``max_pool_size`` larger than necessary. Err towards a larger value.) If your application accepts the default, continue to do so. See :ref:`connection-pooling` for more information. Issues Resolved ............... See the `PyMongo 2.6 release notes in JIRA`_ for the list of resolved issues in this release. .. _PyMongo 2.6 release notes in JIRA: https://jira.mongodb.org/secure/ReleaseNote.jspa?projectId=10004&version=12380 Changes in Version 2.5.2 ------------------------ Version 2.5.2 fixes a NULL pointer dereference issue when decoding an invalid :class:`~bson.dbref.DBRef`. Issues Resolved ............... See the `PyMongo 2.5.2 release notes in JIRA`_ for the list of resolved issues in this release. .. _PyMongo 2.5.2 release notes in JIRA: https://jira.mongodb.org/secure/ReleaseNote.jspa?projectId=10004&version=12581 Changes in Version 2.5.1 ------------------------ Version 2.5.1 is a minor release that fixes issues discovered after the release of 2.5. Most importantly, this release addresses some race conditions in replica set monitoring. Issues Resolved ............... See the `PyMongo 2.5.1 release notes in JIRA`_ for the list of resolved issues in this release. .. _PyMongo 2.5.1 release notes in JIRA: https://jira.mongodb.org/secure/ReleaseNote.jspa?projectId=10004&version=12484 Changes in Version 2.5 ---------------------- Version 2.5 includes changes to support new features in MongoDB 2.4. Important new features: - Support for :ref:`GSSAPI (Kerberos) authentication `. - Support for SSL certificate validation with hostname matching. - Support for delegated and role based authentication. - New GEOSPHERE (2dsphere) and HASHED index constants. .. note:: :meth:`~pymongo.database.Database.authenticate` now raises a subclass of :class:`~pymongo.errors.PyMongoError` if authentication fails due to invalid credentials or configuration issues. Issues Resolved ............... See the `PyMongo 2.5 release notes in JIRA`_ for the list of resolved issues in this release. .. _PyMongo 2.5 release notes in JIRA: https://jira.mongodb.org/secure/ReleaseNote.jspa?projectId=10004&version=11981 Changes in Version 2.4.2 ------------------------ Version 2.4.2 is a minor release that fixes issues discovered after the release of 2.4.1. Most importantly, PyMongo will no longer select a replica set member for read operations that is not in primary or secondary state. Issues Resolved ............... See the `PyMongo 2.4.2 release notes in JIRA`_ for the list of resolved issues in this release. .. _PyMongo 2.4.2 release notes in JIRA: https://jira.mongodb.org/secure/ReleaseNote.jspa?projectId=10004&version=12299 Changes in Version 2.4.1 ------------------------ Version 2.4.1 is a minor release that fixes issues discovered after the release of 2.4. Most importantly, this release fixes a regression using :meth:`~pymongo.collection.Collection.aggregate`, and possibly other commands, with mongos. Issues Resolved ............... See the `PyMongo 2.4.1 release notes in JIRA`_ for the list of resolved issues in this release. .. _PyMongo 2.4.1 release notes in JIRA: https://jira.mongodb.org/secure/ReleaseNote.jspa?projectId=10004&version=12286 Changes in Version 2.4 ---------------------- Version 2.4 includes a few important new features and a large number of bug fixes. Important new features: - New :class:`~pymongo.mongo_client.MongoClient` and :class:`~pymongo.mongo_replica_set_client.MongoReplicaSetClient` classes - these connection classes do acknowledged write operations (previously referred to as 'safe' writes) by default. :class:`~pymongo.connection.Connection` and :class:`~pymongo.replica_set_connection.ReplicaSetConnection` are deprecated but still support the old default fire-and-forget behavior. - A new write concern API implemented as a :attr:`~pymongo.collection.Collection.write_concern` attribute on the connection, :class:`~pymongo.database.Database`, or :class:`~pymongo.collection.Collection` classes. - :class:`~pymongo.mongo_client.MongoClient` (and :class:`~pymongo.connection.Connection`) now support Unix Domain Sockets. - :class:`~pymongo.cursor.Cursor` can be copied with functions from the :mod:`copy` module. - The :meth:`~pymongo.database.Database.set_profiling_level` method now supports a ``slow_ms`` option. - The replica set monitor task (used by :class:`~pymongo.mongo_replica_set_client.MongoReplicaSetClient` and :class:`~pymongo.replica_set_connection.ReplicaSetConnection`) is a daemon thread once again, meaning you won't have to call :meth:`~pymongo.mongo_replica_set_client.MongoReplicaSetClient.close` before exiting the python interactive shell. .. warning:: The constructors for :class:`~pymongo.mongo_client.MongoClient`, :class:`~pymongo.mongo_replica_set_client.MongoReplicaSetClient`, :class:`~pymongo.connection.Connection`, and :class:`~pymongo.replica_set_connection.ReplicaSetConnection` now raise :exc:`~pymongo.errors.ConnectionFailure` instead of its subclass :exc:`~pymongo.errors.AutoReconnect` if the server is unavailable. Applications that expect to catch :exc:`~pymongo.errors.AutoReconnect` should now catch :exc:`~pymongo.errors.ConnectionFailure` while creating a new connection. Issues Resolved ............... See the `PyMongo 2.4 release notes in JIRA`_ for the list of resolved issues in this release. .. _PyMongo 2.4 release notes in JIRA: https://jira.mongodb.org/secure/ReleaseNote.jspa?projectId=10004&version=11485 Changes in Version 2.3 ---------------------- Version 2.3 adds support for new features and behavior changes in MongoDB 2.2. Important New Features: - Support for expanded read preferences including directing reads to tagged servers - See :ref:`secondary-reads` for more information. - Support for mongos failover. - A new :meth:`~pymongo.collection.Collection.aggregate` method to support MongoDB's new `aggregation framework `_. - Support for legacy Java and C# byte order when encoding and decoding UUIDs. - Support for connecting directly to an arbiter. .. warning:: Starting with MongoDB 2.2 the getLastError command requires authentication when the server's `authentication features `_ are enabled. Changes to PyMongo were required to support this behavior change. Users of authentication must upgrade to PyMongo 2.3 (or newer) for "safe" write operations to function correctly. Issues Resolved ............... See the `PyMongo 2.3 release notes in JIRA`_ for the list of resolved issues in this release. .. _PyMongo 2.3 release notes in JIRA: https://jira.mongodb.org/secure/ReleaseNote.jspa?projectId=10004&version=11146 Changes in Version 2.2.1 ------------------------ Version 2.2.1 is a minor release that fixes issues discovered after the release of 2.2. Most importantly, this release fixes an incompatibility with mod_wsgi 2.x that could cause connections to leak. Users of mod_wsgi 2.x are strongly encouraged to upgrade from PyMongo 2.2. Issues Resolved ............... See the `PyMongo 2.2.1 release notes in JIRA`_ for the list of resolved issues in this release. .. _PyMongo 2.2.1 release notes in JIRA: https://jira.mongodb.org/secure/ReleaseNote.jspa?projectId=10004&version=11185 Changes in Version 2.2 ---------------------- Version 2.2 adds a few more frequently requested features and fixes a number of bugs. Special thanks go to Alex Grönholm for his contributions to Python 3 support and maintaining the original pymongo3 port. Christoph Simon, Wouter Bolsterlee, Mike O'Brien, and Chris Tompkinson also contributed to this release. Important New Features: - Support for Python 3 - See the :doc:`python3` for more information. - Support for Gevent - See :doc:`examples/gevent` for more information. - Improved connection pooling. See `PYTHON-287 `_. .. warning:: A number of methods and method parameters that were deprecated in PyMongo 1.9 or older versions have been removed in this release. The full list of changes can be found in the following JIRA ticket: https://jira.mongodb.org/browse/PYTHON-305 BSON module aliases from the pymongo package that were deprecated in PyMongo 1.9 have also been removed in this release. See the following JIRA ticket for details: https://jira.mongodb.org/browse/PYTHON-304 As a result of this cleanup some minor code changes may be required to use this release. Issues Resolved ............... See the `PyMongo 2.2 release notes in JIRA`_ for the list of resolved issues in this release. .. _PyMongo 2.2 release notes in JIRA: https://jira.mongodb.org/secure/ReleaseNote.jspa?projectId=10004&version=10584 Changes in Version 2.1.1 ------------------------ Version 2.1.1 is a minor release that fixes a few issues discovered after the release of 2.1. You can now use :class:`~pymongo.replica_set_connection.ReplicaSetConnection` to run inline map reduce commands on secondaries. See :meth:`~pymongo.collection.Collection.inline_map_reduce` for details. Special thanks go to Samuel Clay and Ross Lawley for their contributions to this release. Issues Resolved ............... See the `PyMongo 2.1.1 release notes in JIRA`_ for the list of resolved issues in this release. .. _PyMongo 2.1.1 release notes in JIRA: https://jira.mongodb.org/secure/ReleaseNote.jspa?version=11081&styleName=Html&projectId=10004 Changes in Version 2.1 ---------------------- Version 2.1 adds a few frequently requested features and includes the usual round of bug fixes and improvements. Special thanks go to Alexey Borzenkov, Dan Crosta, Kostya Rybnikov, Flavio Percoco Premoli, Jonas Haag, and Jesse Davis for their contributions to this release. Important New Features: - ReplicaSetConnection - :class:`~pymongo.replica_set_connection.ReplicaSetConnection` can be used to distribute reads to secondaries in a replica set. It supports automatic failover handling and periodically checks the state of the replica set to handle issues like primary stepdown or secondaries being removed for backup operations. Read preferences are defined through :class:`~pymongo.read_preferences.ReadPreference`. - PyMongo supports the new BSON binary subtype 4 for UUIDs. The default subtype to use can be set through :attr:`~pymongo.collection.Collection.uuid_subtype` The current default remains :attr:`~bson.binary.OLD_UUID_SUBTYPE` but will be changed to :attr:`~bson.binary.UUID_SUBTYPE` in a future release. - The getLastError option 'w' can be set to a string, allowing for options like "majority" available in newer version of MongoDB. - Added support for the MongoDB URI options socketTimeoutMS and connectTimeoutMS. - Added support for the ContinueOnError insert flag. - Added basic SSL support. - Added basic support for Jython. - Secondaries can be used for :meth:`~pymongo.cursor.Cursor.count`, :meth:`~pymongo.cursor.Cursor.distinct`, :meth:`~pymongo.collection.Collection.group`, and querying :class:`~gridfs.GridFS`. - Added document_class and tz_aware options to :class:`~pymongo.master_slave_connection.MasterSlaveConnection` Issues Resolved ............... See the `PyMongo 2.1 release notes in JIRA`_ for the list of resolved issues in this release. .. _PyMongo 2.1 release notes in JIRA: https://jira.mongodb.org/secure/ReleaseNote.jspa?projectId=10004&version=10583 Changes in Version 2.0.1 ------------------------ Version 2.0.1 fixes a regression in :class:`~gridfs.grid_file.GridIn` when writing pre-chunked strings. Thanks go to Alexey Borzenkov for reporting the issue and submitting a patch. Issues Resolved ............... - `PYTHON-271 `_: Regression in GridFS leads to serious loss of data. Changes in Version 2.0 ---------------------- Version 2.0 adds a large number of features and fixes a number of issues. Special thanks go to James Murty, Abhay Vardhan, David Pisoni, Ryan Smith-Roberts, Andrew Pendleton, Mher Movsisyan, Reed O'Brien, Michael Schurter, Josip Delic and Jonas Haag for their contributions to this release. Important New Features: - PyMongo now performs automatic per-socket database authentication. You no longer have to re-authenticate for each new thread or after a replica set failover. Authentication credentials are cached by the driver until the application calls :meth:`~pymongo.database.Database.logout`. - slave_okay can be set independently at the connection, database, collection or query level. Each level will inherit the slave_okay setting from the previous level and each level can override the previous level's setting. - safe and getLastError options (e.g. w, wtimeout, etc.) can be set independently at the connection, database, collection or query level. Each level will inherit settings from the previous level and each level can override the previous level's setting. - PyMongo now supports the ``await_data`` and ``partial`` cursor flags. If the ``await_data`` flag is set on a ``tailable`` cursor the server will block for some extra time waiting for more data to return. The ``partial`` flag tells a mongos to return partial data for a query if not all shards are available. - :meth:`~pymongo.collection.Collection.map_reduce` will accept a ``dict`` or instance of :class:`~bson.son.SON` as the ``out`` parameter. - The URI parser has been moved into its own module and can be used directly by application code. - AutoReconnect exception now provides information about the error that actually occurred instead of a generic failure message. - A number of new helper methods have been added with options for setting and unsetting cursor flags, re-indexing a collection, fsync and locking a server, and getting the server's current operations. API changes: - If only one host:port pair is specified :class:`~pymongo.connection.Connection` will make a direct connection to only that host. Please note that ``slave_okay`` must be ``True`` in order to query from a secondary. - If more than one host:port pair is specified or the ``replicaset`` option is used PyMongo will treat the specified host:port pair(s) as a seed list and connect using replica set behavior. .. warning:: The default subtype for :class:`~bson.binary.Binary` has changed from :const:`~bson.binary.OLD_BINARY_SUBTYPE` (2) to :const:`~bson.binary.BINARY_SUBTYPE` (0). Issues Resolved ............... See the `PyMongo 2.0 release notes in JIRA`_ for the list of resolved issues in this release. .. _PyMongo 2.0 release notes in JIRA: https://jira.mongodb.org/secure/ReleaseNote.jspa?projectId=10004&version=10274 Changes in Version 1.11 ----------------------- Version 1.11 adds a few new features and fixes a few more bugs. New Features: - Basic IPv6 support: pymongo prefers IPv4 but will try IPv6. You can also specify an IPv6 address literal in the ``host`` parameter or a MongoDB URI provided it is enclosed in '[' and ']'. - max_pool_size option: previously pymongo had a hard coded pool size of 10 connections. With this change you can specify a different pool size as a parameter to :class:`~pymongo.connection.Connection` (max_pool_size=) or in the MongoDB URI (maxPoolSize=). - Find by metadata in GridFS: You can know specify query fields as keyword parameters for :meth:`~gridfs.GridFS.get_version` and :meth:`~gridfs.GridFS.get_last_version`. - Per-query slave_okay option: slave_okay=True is now a valid keyword argument for :meth:`~pymongo.collection.Collection.find` and :meth:`~pymongo.collection.Collection.find_one`. API changes: - :meth:`~pymongo.database.Database.validate_collection` now returns a dict instead of a string. This change was required to deal with an API change on the server. This method also now takes the optional ``scandata`` and ``full`` parameters. See the documentation for more details. .. warning:: The ``pool_size``, ``auto_start_request```, and ``timeout`` parameters for :class:`~pymongo.connection.Connection` have been completely removed in this release. They were deprecated in pymongo-1.4 and have had no effect since then. Please make sure that your code doesn't currently pass these parameters when creating a Connection instance. Issues resolved ............... - `PYTHON-241 `_: Support setting slaveok at the cursor level. - `PYTHON-240 `_: Queries can sometimes permanently fail after a replica set fail over. - `PYTHON-238 `_: error after few million requests - `PYTHON-237 `_: Basic IPv6 support. - `PYTHON-236 `_: Restore option to specify pool size in Connection. - `PYTHON-212 `_: pymongo does not recover after stale config - `PYTHON-138 `_: Find method for GridFS Changes in Version 1.10.1 ------------------------- Version 1.10.1 is primarily a bugfix release. It fixes a regression in version 1.10 that broke pickling of ObjectIds. A number of other bugs have been fixed as well. There are two behavior changes to be aware of: - If a read slave raises :class:`~pymongo.errors.AutoReconnect` :class:`~pymongo.master_slave_connection.MasterSlaveConnection` will now retry the query on each slave until it is successful or all slaves have raised :class:`~pymongo.errors.AutoReconnect`. Any other exception will immediately be raised. The order that the slaves are tried is random. Previously the read would be sent to one randomly chosen slave and :class:`~pymongo.errors.AutoReconnect` was immediately raised in case of a connection failure. - A Python ``long`` is now always BSON encoded as an int64. Previously the encoding was based only on the value of the field and a ``long`` with a value less than ``2147483648`` or greater than ``-2147483649`` would always be BSON encoded as an int32. Issues resolved ............... - `PYTHON-234 `_: Fix setup.py to raise exception if any when building extensions - `PYTHON-233 `_: Add information to build and test with extensions on windows - `PYTHON-232 `_: Traceback when hashing a DBRef instance - `PYTHON-231 `_: Traceback when pickling a DBRef instance - `PYTHON-230 `_: Pickled ObjectIds are not compatible between pymongo 1.9 and 1.10 - `PYTHON-228 `_: Cannot pickle bson.ObjectId - `PYTHON-227 `_: Traceback when calling find() on system.js - `PYTHON-216 `_: MasterSlaveConnection is missing disconnect() method - `PYTHON-186 `_: When storing integers, type is selected according to value instead of type - `PYTHON-173 `_: as_class option is not propagated by Cursor.clone - `PYTHON-113 `_: Redunducy in MasterSlaveConnection Changes in Version 1.10 ----------------------- Version 1.10 includes changes to support new features in MongoDB 1.8.x. Highlights include a modified map/reduce API including an inline map/reduce helper method, a new find_and_modify helper, and the ability to query the server for the maximum BSON document size it supports. - added :meth:`~pymongo.collection.Collection.find_and_modify`. - added :meth:`~pymongo.collection.Collection.inline_map_reduce`. - changed :meth:`~pymongo.collection.Collection.map_reduce`. .. warning:: MongoDB versions greater than 1.7.4 no longer generate temporary collections for map/reduce results. An output collection name must be provided and the output will replace any existing output collection with the same name. :meth:`~pymongo.collection.Collection.map_reduce` now requires the ``out`` parameter. Issues resolved ............... - PYTHON-225: :class:`~pymongo.objectid.ObjectId` class definition should use __slots__. - PYTHON-223: Documentation fix. - PYTHON-220: Documentation fix. - PYTHON-219: KeyError in :meth:`~pymongo.collection.Collection.find_and_modify` - PYTHON-213: Query server for maximum BSON document size. - PYTHON-208: Fix :class:`~pymongo.connection.Connection` __repr__. - PYTHON-207: Changes to Map/Reduce API. - PYTHON-205: Accept slaveOk in the URI to match the URI docs. - PYTHON-203: When slave_okay=True and we only specify one host don't autodetect other set members. - PYTHON-194: Show size when whining about a document being too large. - PYTHON-184: Raise :class:`~pymongo.errors.DuplicateKeyError` for duplicate keys in capped collections. - PYTHON-178: Don't segfault when trying to encode a recursive data structure. - PYTHON-177: Don't segfault when decoding dicts with broken iterators. - PYTHON-172: Fix a typo. - PYTHON-170: Add :meth:`~pymongo.collection.Collection.find_and_modify`. - PYTHON-169: Support deepcopy of DBRef. - PYTHON-167: Duplicate of PYTHON-166. - PYTHON-166: Fixes a concurrency issue. - PYTHON-158: Add code and err string to ``db assertion`` messages. Changes in Version 1.9 ---------------------- Version 1.9 adds a new package to the PyMongo distribution, :mod:`bson`. :mod:`bson` contains all of the `BSON `_ encoding and decoding logic, and the BSON types that were formerly in the :mod:`pymongo` package. The following modules have been renamed: - :mod:`pymongo.bson` -> :mod:`bson` - :mod:`pymongo._cbson` -> :mod:`bson._cbson` and :mod:`pymongo._cmessage` - :mod:`pymongo.binary` -> :mod:`bson.binary` - :mod:`pymongo.code` -> :mod:`bson.code` - :mod:`pymongo.dbref` -> :mod:`bson.dbref` - :mod:`pymongo.json_util` -> :mod:`bson.json_util` - :mod:`pymongo.max_key` -> :mod:`bson.max_key` - :mod:`pymongo.min_key` -> :mod:`bson.min_key` - :mod:`pymongo.objectid` -> :mod:`bson.objectid` - :mod:`pymongo.son` -> :mod:`bson.son` - :mod:`pymongo.timestamp` -> :mod:`bson.timestamp` - :mod:`pymongo.tz_util` -> :mod:`bson.tz_util` In addition, the following exception classes have been renamed: - :class:`pymongo.errors.InvalidBSON` -> :class:`bson.errors.InvalidBSON` - :class:`pymongo.errors.InvalidStringData` -> :class:`bson.errors.InvalidStringData` - :class:`pymongo.errors.InvalidDocument` -> :class:`bson.errors.InvalidDocument` - :class:`pymongo.errors.InvalidId` -> :class:`bson.errors.InvalidId` The above exceptions now inherit from :class:`bson.errors.BSONError` rather than :class:`pymongo.errors.PyMongoError`. .. note:: All of the renamed modules and exceptions above have aliases created with the old names, so these changes should not break existing code. The old names will eventually be deprecated and then removed, so users should begin migrating towards the new names now. .. warning:: The change to the exception hierarchy mentioned above is possibly breaking. If your code is catching :class:`~pymongo.errors.PyMongoError`, then the exceptions raised by :mod:`bson` will not be caught, even though they would have been caught previously. Before upgrading, it is recommended that users check for any cases like this. - the C extension now shares buffer.c/h with the Ruby driver - :mod:`bson` no longer raises :class:`~pymongo.errors.InvalidName`, all occurrences have been replaced with :class:`~bson.errors.InvalidDocument`. - renamed :meth:`bson._to_dicts` to :meth:`~bson.decode_all`. - renamed :meth:`~bson.BSON.from_dict` to :meth:`~bson.BSON.encode` and :meth:`~bson.BSON.to_dict` to :meth:`~bson.BSON.decode`. - added :meth:`~pymongo.cursor.Cursor.batch_size`. - allow updating (some) file metadata after a :class:`~gridfs.grid_file.GridIn` instance has been closed. - performance improvements for reading from GridFS. - special cased slice with the same start and stop to return an empty cursor. - allow writing :class:`unicode` to GridFS if an :attr:`encoding` attribute has been specified for the file. - added :meth:`gridfs.GridFS.get_version`. - scope variables for :class:`~bson.code.Code` can now be specified as keyword arguments. - added :meth:`~gridfs.grid_file.GridOut.readline` to :class:`~gridfs.grid_file.GridOut`. - make a best effort to transparently auto-reconnect if a :class:`~pymongo.connection.Connection` has been idle for a while. - added :meth:`~pymongo.database.SystemJS.list` to :class:`~pymongo.database.SystemJS`. - added ``file_document`` argument to :meth:`~gridfs.grid_file.GridOut` to allow initializing from an existing file document. - raise :class:`~pymongo.errors.TimeoutError` even if the ``getLastError`` command was run manually and not through "safe" mode. - added :class:`uuid` support to :mod:`~bson.json_util`. Changes in Version 1.8.1 ------------------------ - fixed a typo in the C extension that could cause safe-mode operations to report a failure (:class:`SystemError`) even when none occurred. - added a :meth:`__ne__` implementation to any class where we define :meth:`__eq__`. Changes in Version 1.8 ---------------------- Version 1.8 adds support for connecting to replica sets, specifying per-operation values for ``w`` and ``wtimeout``, and decoding to timezone-aware datetimes. - fixed a reference leak in the C extension when decoding a :class:`~bson.dbref.DBRef`. - added support for ``w``, ``wtimeout``, and ``fsync`` (and any other options for ``getLastError``) to "safe mode" operations. - added :attr:`~pymongo.connection.Connection.nodes` property. - added a maximum pool size of 10 sockets. - added support for replica sets. - DEPRECATED :meth:`~pymongo.connection.Connection.from_uri` and :meth:`~pymongo.connection.Connection.paired`, both are supplanted by extended functionality in :meth:`~pymongo.connection.Connection`. - added tz aware support for datetimes in :class:`~bson.objectid.ObjectId`, :class:`~bson.timestamp.Timestamp` and :mod:`~bson.json_util` methods. - added :meth:`~pymongo.collection.Collection.drop` helper. - reuse the socket used for finding the master when a :class:`~pymongo.connection.Connection` is first created. - added support for :class:`~bson.min_key.MinKey`, :class:`~bson.max_key.MaxKey` and :class:`~bson.timestamp.Timestamp` to :mod:`~bson.json_util`. - added support for decoding datetimes as aware (UTC) - it is highly recommended to enable this by setting the ``tz_aware`` parameter to :meth:`~pymongo.connection.Connection` to ``True``. - added ``network_timeout`` option for individual calls to :meth:`~pymongo.collection.Collection.find` and :meth:`~pymongo.collection.Collection.find_one`. - added :meth:`~gridfs.GridFS.exists` to check if a file exists in GridFS. - added support for additional keys in :class:`~bson.dbref.DBRef` instances. - added :attr:`~pymongo.errors.OperationFailure.code` attribute to :class:`~pymongo.errors.OperationFailure` exceptions. - fixed serialization of int and float subclasses in the C extension. Changes in Version 1.7 ---------------------- Version 1.7 is a recommended upgrade for all PyMongo users. The full release notes are below, and some more in depth discussion of the highlights is `here `_. - no longer attempt to build the C extension on big-endian systems. - added :class:`~bson.min_key.MinKey` and :class:`~bson.max_key.MaxKey`. - use unsigned for :class:`~bson.timestamp.Timestamp` in BSON encoder/decoder. - support ``True`` as ``"ok"`` in command responses, in addition to ``1.0`` - necessary for server versions **>= 1.5.X** - BREAKING change to :meth:`~pymongo.collection.Collection.index_information` to add support for querying unique status and other index information. - added :attr:`~pymongo.connection.Connection.document_class`, to specify class for returned documents. - added ``as_class`` argument for :meth:`~pymongo.collection.Collection.find`, and in the BSON decoder. - added support for creating :class:`~bson.timestamp.Timestamp` instances using a :class:`~datetime.datetime`. - allow ``dropTarget`` argument for :class:`~pymongo.collection.Collection.rename`. - handle aware :class:`~datetime.datetime` instances, by converting to UTC. - added support for :class:`~pymongo.cursor.Cursor.max_scan`. - raise :class:`~gridfs.errors.FileExists` exception when creating a duplicate GridFS file. - use `y2038 `_ for time handling in the C extension - eliminates 2038 problems when extension is installed. - added ``sort`` parameter to :meth:`~pymongo.collection.Collection.find` - finalized deprecation of changes from versions **<= 1.4** - take any non-:class:`dict` as an ``"_id"`` query for :meth:`~pymongo.collection.Collection.find_one` or :meth:`~pymongo.collection.Collection.remove` - added ability to pass a :class:`dict` for ``fields`` argument to :meth:`~pymongo.collection.Collection.find` (supports ``"$slice"`` and field negation) - simplified code to find master, since paired setups don't always have a remote - fixed bug in C encoder for certain invalid types (like :class:`~pymongo.collection.Collection` instances). - don't transparently map ``"filename"`` key to :attr:`name` attribute for GridFS. Changes in Version 1.6 ---------------------- The biggest change in version 1.6 is a complete re-implementation of :mod:`gridfs` with a lot of improvements over the old implementation. There are many details and examples of using the new API in `this blog post `_. The old API has been removed in this version, so existing code will need to be modified before upgrading to 1.6. - fixed issue where connection pool was being shared across :class:`~pymongo.connection.Connection` instances. - more improvements to Python code caching in C extension - should improve behavior on mod_wsgi. - added :meth:`~bson.objectid.ObjectId.from_datetime`. - complete rewrite of :mod:`gridfs` support. - improvements to the :meth:`~pymongo.database.Database.command` API. - fixed :meth:`~pymongo.collection.Collection.drop_indexes` behavior on non-existent collections. - disallow empty bulk inserts. Changes in Version 1.5.2 ------------------------ - fixed response handling to ignore unknown response flags in queries. - handle server versions containing '-pre-'. Changes in Version 1.5.1 ------------------------ - added :data:`~gridfs.grid_file.GridFile._id` property for :class:`~gridfs.grid_file.GridFile` instances. - fix for making a :class:`~pymongo.connection.Connection` (with ``slave_okay`` set) directly to a slave in a replica pair. - accept kwargs for :meth:`~pymongo.collection.Collection.create_index` and :meth:`~pymongo.collection.Collection.ensure_index` to support all indexing options. - add :data:`pymongo.GEO2D` and support for geo indexing. - improvements to Python code caching in C extension - should improve behavior on mod_wsgi. Changes in Version 1.5 ---------------------- - added subtype constants to :mod:`~bson.binary` module. - DEPRECATED ``options`` argument to :meth:`~pymongo.collection.Collection` and :meth:`~pymongo.database.Database.create_collection` in favor of kwargs. - added :meth:`~pymongo.has_c` to check for C extension. - added :meth:`~pymongo.connection.Connection.copy_database`. - added :data:`~pymongo.cursor.Cursor.alive` to tell when a cursor might have more data to return (useful for tailable cursors). - added :class:`~bson.timestamp.Timestamp` to better support dealing with internal MongoDB timestamps. - added ``name`` argument for :meth:`~pymongo.collection.Collection.create_index` and :meth:`~pymongo.collection.Collection.ensure_index`. - fixed connection pooling w/ fork - :meth:`~pymongo.connection.Connection.paired` takes all kwargs that are allowed for :meth:`~pymongo.connection.Connection`. - :meth:`~pymongo.collection.Collection.insert` returns list for bulk inserts of size one. - fixed handling of :class:`datetime.datetime` instances in :mod:`~bson.json_util`. - added :meth:`~pymongo.connection.Connection.from_uri` to support MongoDB connection uri scheme. - fixed chunk number calculation when unaligned in :mod:`gridfs`. - :meth:`~pymongo.database.Database.command` takes a string for simple commands. - added :data:`~pymongo.database.Database.system_js` helper for dealing with server-side JS. - don't wrap queries containing ``"$query"`` (support manual use of ``"$min"``, etc.). - added :class:`~gridfs.errors.GridFSError` as base class for :mod:`gridfs` exceptions. Changes in Version 1.4 ---------------------- Perhaps the most important change in version 1.4 is that we have decided to **no longer support Python 2.3**. The most immediate reason for this is to allow some improvements to connection pooling. This will also allow us to use some new (as in Python 2.4 ;) idioms and will help begin the path towards supporting Python 3.0. If you need to use Python 2.3 you should consider using version 1.3 of this driver, although that will no longer be actively supported. Other changes: - move ``"_id"`` to front only for top-level documents (fixes some corner cases). - :meth:`~pymongo.collection.Collection.update` and :meth:`~pymongo.collection.Collection.remove` return the entire response to the *lastError* command when safe is ``True``. - completed removal of things that were deprecated in version 1.2 or earlier. - enforce that collection names do not contain the NULL byte. - fix to allow using UTF-8 collection names with the C extension. - added :class:`~pymongo.errors.PyMongoError` as base exception class for all :mod:`~pymongo.errors`. this changes the exception hierarchy somewhat, and is a BREAKING change if you depend on :class:`~pymongo.errors.ConnectionFailure` being a :class:`IOError` or :class:`~bson.errors.InvalidBSON` being a :class:`ValueError`, for example. - added :class:`~pymongo.errors.DuplicateKeyError` for calls to :meth:`~pymongo.collection.Collection.insert` or :meth:`~pymongo.collection.Collection.update` with ``safe`` set to ``True``. - removed :mod:`~pymongo.thread_util`. - added :meth:`~pymongo.database.Database.add_user` and :meth:`~pymongo.database.Database.remove_user` helpers. - fix for :meth:`~pymongo.database.Database.authenticate` when using non-UTF-8 names or passwords. - minor fixes for :class:`~pymongo.master_slave_connection.MasterSlaveConnection`. - clean up all cases where :class:`~pymongo.errors.ConnectionFailure` is raised. - simplification of connection pooling - makes driver ~2x faster for simple benchmarks. see :ref:`connection-pooling` for more information. - DEPRECATED ``pool_size``, ``auto_start_request`` and ``timeout`` parameters to :class:`~pymongo.connection.Connection`. DEPRECATED :meth:`~pymongo.connection.Connection.start_request`. - use :meth:`socket.sendall`. - removed :meth:`~bson.son.SON.from_xml` as it was only being used for some internal testing - also eliminates dependency on :mod:`elementtree`. - implementation of :meth:`~pymongo.message.update` in C. - deprecate :meth:`~pymongo.database.Database._command` in favor of :meth:`~pymongo.database.Database.command`. - send all commands without wrapping as ``{"query": ...}``. - support string as ``key`` argument to :meth:`~pymongo.collection.Collection.group` (keyf) and run all groups as commands. - support for equality testing for :class:`~bson.code.Code` instances. - allow the NULL byte in strings and disallow it in key names or regex patterns Changes in Version 1.3 ---------------------- - DEPRECATED running :meth:`~pymongo.collection.Collection.group` as :meth:`~pymongo.database.Database.eval`, also changed default for :meth:`~pymongo.collection.Collection.group` to running as a command - remove :meth:`pymongo.cursor.Cursor.__len__`, which was deprecated in 1.1.1 - needed to do this aggressively due to it's presence breaking **Django** template *for* loops - DEPRECATED :meth:`~pymongo.connection.Connection.host`, :meth:`~pymongo.connection.Connection.port`, :meth:`~pymongo.database.Database.connection`, :meth:`~pymongo.database.Database.name`, :meth:`~pymongo.collection.Collection.database`, :meth:`~pymongo.collection.Collection.name` and :meth:`~pymongo.collection.Collection.full_name` in favor of :attr:`~pymongo.connection.Connection.host`, :attr:`~pymongo.connection.Connection.port`, :attr:`~pymongo.database.Database.connection`, :attr:`~pymongo.database.Database.name`, :attr:`~pymongo.collection.Collection.database`, :attr:`~pymongo.collection.Collection.name` and :attr:`~pymongo.collection.Collection.full_name`, respectively. The deprecation schedule for this change will probably be faster than usual, as it carries some performance implications. - added :meth:`~pymongo.connection.Connection.disconnect` Changes in Version 1.2.1 ------------------------ - added :doc:`changelog` to docs - added ``setup.py doc --test`` to run doctests for tutorial, examples - moved most examples to Sphinx docs (and remove from *examples/* directory) - raise :class:`~bson.errors.InvalidId` instead of :class:`TypeError` when passing a 24 character string to :class:`~bson.objectid.ObjectId` that contains non-hexadecimal characters - allow :class:`unicode` instances for :class:`~bson.objectid.ObjectId` init Changes in Version 1.2 ---------------------- - ``spec`` parameter for :meth:`~pymongo.collection.Collection.remove` is now optional to allow for deleting all documents in a :class:`~pymongo.collection.Collection` - always wrap queries with ``{query: ...}`` even when no special options - get around some issues with queries on fields named ``query`` - enforce 4MB document limit on the client side - added :meth:`~pymongo.collection.Collection.map_reduce` helper - see :doc:`example ` - added :meth:`~pymongo.cursor.Cursor.distinct` method on :class:`~pymongo.cursor.Cursor` instances to allow distinct with queries - fix for :meth:`~pymongo.cursor.Cursor.__getitem__` after :meth:`~pymongo.cursor.Cursor.skip` - allow any UTF-8 string in :class:`~bson.BSON` encoder, not just ASCII subset - added :attr:`~bson.objectid.ObjectId.generation_time` - removed support for legacy :class:`~bson.objectid.ObjectId` format - pretty sure this was never used, and is just confusing - DEPRECATED :meth:`~bson.objectid.ObjectId.url_encode` and :meth:`~bson.objectid.ObjectId.url_decode` in favor of :meth:`str` and :meth:`~bson.objectid.ObjectId`, respectively - allow *oplog.$main* as a valid collection name - some minor fixes for installation process - added support for datetime and regex in :mod:`~bson.json_util` Changes in Version 1.1.2 ------------------------ - improvements to :meth:`~pymongo.collection.Collection.insert` speed (using C for insert message creation) - use random number for request_id - fix some race conditions with :class:`~pymongo.errors.AutoReconnect` Changes in Version 1.1.1 ------------------------ - added ``multi`` parameter for :meth:`~pymongo.collection.Collection.update` - fix unicode regex patterns with C extension - added :meth:`~pymongo.collection.Collection.distinct` - added ``database`` support for :class:`~bson.dbref.DBRef` - added :mod:`~bson.json_util` with helpers for encoding / decoding special types to JSON - DEPRECATED :meth:`pymongo.cursor.Cursor.__len__` in favor of :meth:`~pymongo.cursor.Cursor.count` with ``with_limit_and_skip`` set to ``True`` due to performance regression - switch documentation to Sphinx Changes in Version 1.1 ---------------------- - added :meth:`__hash__` for :class:`~bson.dbref.DBRef` and :class:`~bson.objectid.ObjectId` - bulk :meth:`~pymongo.collection.Collection.insert` works with any iterable - fix :class:`~bson.objectid.ObjectId` generation when using :mod:`multiprocessing` - added :attr:`~pymongo.cursor.Cursor.collection` - added ``network_timeout`` parameter for :meth:`~pymongo.connection.Connection` - DEPRECATED ``slave_okay`` parameter for individual queries - fix for ``safe`` mode when multi-threaded - added ``safe`` parameter for :meth:`~pymongo.collection.Collection.remove` - added ``tailable`` parameter for :meth:`~pymongo.collection.Collection.find` Changes in Version 1.0 ---------------------- - fixes for :class:`~pymongo.master_slave_connection.MasterSlaveConnection` - added ``finalize`` parameter for :meth:`~pymongo.collection.Collection.group` - improvements to :meth:`~pymongo.collection.Collection.insert` speed - improvements to :mod:`gridfs` speed - added :meth:`~pymongo.cursor.Cursor.__getitem__` and :meth:`~pymongo.cursor.Cursor.__len__` for :class:`~pymongo.cursor.Cursor` instances Changes in Version 0.16 ----------------------- - support for encoding/decoding :class:`uuid.UUID` instances - fix for :meth:`~pymongo.cursor.Cursor.explain` with limits Changes in Version 0.15.2 ------------------------- - documentation changes only Changes in Version 0.15.1 ------------------------- - various performance improvements - API CHANGE no longer need to specify direction for :meth:`~pymongo.collection.Collection.create_index` and :meth:`~pymongo.collection.Collection.ensure_index` when indexing a single key - support for encoding :class:`tuple` instances as :class:`list` instances Changes in Version 0.15 ----------------------- - fix string representation of :class:`~bson.objectid.ObjectId` instances - added ``timeout`` parameter for :meth:`~pymongo.collection.Collection.find` - allow scope for ``reduce`` function in :meth:`~pymongo.collection.Collection.group` Changes in Version 0.14.2 ------------------------- - minor bugfixes Changes in Version 0.14.1 ------------------------- - :meth:`~gridfs.grid_file.GridFile.seek` and :meth:`~gridfs.grid_file.GridFile.tell` for (read mode) :class:`~gridfs.grid_file.GridFile` instances Changes in Version 0.14 ----------------------- - support for long in :class:`~bson.BSON` - added :meth:`~pymongo.collection.Collection.rename` - added ``snapshot`` parameter for :meth:`~pymongo.collection.Collection.find` Changes in Version 0.13 ----------------------- - better :class:`~pymongo.master_slave_connection.MasterSlaveConnection` support - API CHANGE :meth:`~pymongo.collection.Collection.insert` and :meth:`~pymongo.collection.Collection.save` both return inserted ``_id`` - DEPRECATED passing an index name to :meth:`~pymongo.cursor.Cursor.hint` Changes in Version 0.12 ----------------------- - improved :class:`~bson.objectid.ObjectId` generation - added :class:`~pymongo.errors.AutoReconnect` exception for when reconnection is possible - make :mod:`gridfs` thread-safe - fix for :mod:`gridfs` with non :class:`~bson.objectid.ObjectId` ``_id`` Changes in Version 0.11.3 ------------------------- - don't allow NULL bytes in string encoder - fixes for Python 2.3 Changes in Version 0.11.2 ------------------------- - PEP 8 - updates for :meth:`~pymongo.collection.Collection.group` - VS build Changes in Version 0.11.1 ------------------------- - fix for connection pooling under Python 2.5 Changes in Version 0.11 ----------------------- - better build failure detection - driver support for selecting fields in sub-documents - disallow insertion of invalid key names - added ``timeout`` parameter for :meth:`~pymongo.connection.Connection` Changes in Version 0.10.3 ------------------------- - fix bug with large :meth:`~pymongo.cursor.Cursor.limit` - better exception when modules get reloaded out from underneath the C extension - better exception messages when calling a :class:`~pymongo.collection.Collection` or :class:`~pymongo.database.Database` instance Changes in Version 0.10.2 ------------------------- - support subclasses of :class:`dict` in C encoder Changes in Version 0.10.1 ------------------------- - alias :class:`~pymongo.connection.Connection` as :attr:`pymongo.Connection` - raise an exception rather than silently overflowing in encoder Changes in Version 0.10 ----------------------- - added :meth:`~pymongo.collection.Collection.ensure_index` Changes in Version 0.9.7 ------------------------ - allow sub-collections of *$cmd* as valid :class:`~pymongo.collection.Collection` names - add version as :attr:`pymongo.version` - add ``--no_ext`` command line option to *setup.py* mongodb-mongo-python-driver-509e9b7/doc/common-issues.rst000066400000000000000000000106351462766011000235420ustar00rootroot00000000000000Frequently Encountered Issues ============================= Also see the :ref:`TLSErrors` section. Server reports wire version X, PyMongo requires Y ------------------------------------------------- When one attempts to connect to a <=3.4 version server, PyMongo will throw the following error:: >>> client.admin.command('ping') ... pymongo.errors.ConfigurationError: Server at localhost:27017 reports wire version 5, but this version of PyMongo requires at least 6 (MongoDB 3.6). This is caused by the driver being too new for the server it is being run against. To resolve this issue either upgrade your database to version >= 3.6 or downgrade to PyMongo 3.x which supports MongoDB >= 2.6. 'Cursor' object has no attribute '_Cursor__killed' -------------------------------------------------- On versions of PyMongo <3.9, when supplying invalid arguments the constructor of Cursor, there will be a TypeError raised, and an AttributeError printed to ``stderr``. The AttributeError is not relevant, instead look at the TypeError for debugging information:: >>> coll.find(wrong=1) Exception ignored in: ... AttributeError: 'Cursor' object has no attribute '_Cursor__killed' ... TypeError: __init__() got an unexpected keyword argument 'wrong' To fix this, make sure that you are supplying the correct keyword arguments. In addition, you can also upgrade to PyMongo >=3.9, which will remove the spurious error. MongoClient fails ConfigurationError ------------------------------------ This is a common issue stemming from using incorrect keyword argument names. >>> client = MongoClient(wrong=1) ... pymongo.errors.ConfigurationError: Unknown option wrong To fix this, check your spelling and make sure that the keyword argument you are specifying exists. DeprecationWarning: count is deprecated --------------------------------------- PyMongo no longer supports :meth:`pymongo.cursor.count`. Instead, use :meth:`pymongo.collection.count_documents`:: >>> client = MongoClient() >>> d = datetime.datetime(2009, 11, 12, 12) >>> list(client.db.coll.find({"date": {"$lt": d}}, limit=2)) [{'_id': ObjectId('6247b058cebb8b179b7039f8'), 'date': datetime.datetime(1, 1, 1, 0, 0)}, {'_id': ObjectId('6247b059cebb8b179b7039f9'), 'date': datetime.datetime(1, 1, 1, 0, 0)}] >>> client.db.coll.count_documents({"date": {"$lt": d}}, limit=2) 2 Note that this is NOT the same as ``Cursor.count_documents`` (which does not exist), this is a method of the Collection class, so you must call it on a collection object or you will receive the following error:: >>> Cursor(MongoClient().db.coll).count() Traceback (most recent call last): File "", line 1, in AttributeError: 'Cursor' object has no attribute 'count' >>> Timeout when accessing MongoDB from PyMongo with tunneling ---------------------------------------------------------- When attempting to connect to a replica set MongoDB instance over an SSH tunnel you will receive the following error:: File "/Library/Python/2.7/site-packages/pymongo/collection.py", line 1560, in count return self._count(cmd, collation, session) File "/Library/Python/2.7/site-packages/pymongo/collection.py", line 1504, in _count with self._socket_for_reads() as (connection, slave_ok): File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/contextlib.py", line 17, in __enter__ return self.gen.next() File "/Library/Python/2.7/site-packages/pymongo/mongo_client.py", line 982, in _socket_for_reads server = topology.select_server(read_preference) File "/Library/Python/2.7/site-packages/pymongo/topology.py", line 224, in select_server address)) File "/Library/Python/2.7/site-packages/pymongo/topology.py", line 183, in select_servers selector, server_timeout, address) File "/Library/Python/2.7/site-packages/pymongo/topology.py", line 199, in _select_servers_loop self._error_message(selector)) pymongo.errors.ServerSelectionTimeoutError: localhost:27017: timed out This is due to the fact that PyMongo discovers replica set members using the response from the isMaster command which then contains the address and ports of the other members. However, these addresses and ports will not be accessible through the SSH tunnel. Thus, this behavior is unsupported. You can, however, connect directly to a single MongoDB node using the directConnection=True option with SSH tunneling. mongodb-mongo-python-driver-509e9b7/doc/compatibility-policy.rst000066400000000000000000000043321462766011000251040ustar00rootroot00000000000000Compatibility Policy ==================== Semantic Versioning ------------------- PyMongo's version numbers follow `semantic versioning`_: each version number is structured "major.minor.patch". Patch releases fix bugs, minor releases add features (and may fix bugs), and major releases include API changes that break backwards compatibility (and may add features and fix bugs). Deprecation ----------- Before we remove a feature in a major release, PyMongo's maintainers make an effort to release at least one minor version that *deprecates* it. We add "**DEPRECATED**" to the feature's documentation, and update the code to raise a `DeprecationWarning`_. You can ensure your code is future-proof by running your code with the latest PyMongo release and looking for DeprecationWarnings. The interpreter silences DeprecationWarnings by default. For example, the following code uses the deprecated ``insert`` method but does not raise any warning: .. code-block:: python # "insert.py" (with PyMongo 3.X) from pymongo import MongoClient client = MongoClient() client.test.test.insert({}) To print deprecation warnings to stderr, run python with "-Wd":: $ python3 -Wd insert.py insert.py:4: DeprecationWarning: insert is deprecated. Use insert_one or insert_many instead. client.test.test.insert({}) You can turn warnings into exceptions with "python -We":: $ python3 -We insert.py Traceback (most recent call last): File "insert.py", line 4, in client.test.test.insert({}) File "/home/durin/work/mongo-python-driver/pymongo/collection.py", line 2906, in insert "instead.", DeprecationWarning, stacklevel=2) DeprecationWarning: insert is deprecated. Use insert_one or insert_many instead. If your own code's test suite passes with "python -We" then it uses no deprecated PyMongo features. .. seealso:: The Python documentation on `the warnings module`_, and `the -W command line option`_. .. _semantic versioning: http://semver.org/ .. _DeprecationWarning: https://docs.python.org/3/library/exceptions.html#DeprecationWarning .. _the warnings module: https://docs.python.org/3/library/warnings.html .. _the -W command line option: https://docs.python.org/3/using/cmdline.html#cmdoption-W mongodb-mongo-python-driver-509e9b7/doc/conf.py000066400000000000000000000142441462766011000215060ustar00rootroot00000000000000# # PyMongo documentation build configuration file # # This file is execfile()d with the current directory set to its containing dir. from __future__ import annotations import sys from pathlib import Path sys.path[0:0] = [Path("..").resolve()] import pymongo # noqa: E402 # -- General configuration ----------------------------------------------------- # Add any Sphinx extension module names here, as strings. They can be extensions # coming with Sphinx (named 'sphinx.ext.*') or your custom ones. extensions = [ "sphinx.ext.autodoc", "sphinx.ext.doctest", "sphinx.ext.coverage", "sphinx.ext.todo", "sphinx.ext.intersphinx", ] # Add optional extensions try: import sphinxcontrib.shellcheck # noqa: F401 extensions += ["sphinxcontrib.shellcheck"] except ImportError: pass # Add any paths that contain templates here, relative to this directory. templates_path = ["_templates"] # The suffix of source filenames. source_suffix = ".rst" # The master toctree document. master_doc = "index" # General information about the project. project = "PyMongo" copyright = "MongoDB, Inc. 2008-present. MongoDB, Mongo, and the leaf logo are registered trademarks of MongoDB, Inc" html_show_sphinx = False # The version info for the project you're documenting, acts as replacement for # |version| and |release|, also used in various other places throughout the # built documents. # # The short X.Y version. version = pymongo.version # The full version, including alpha/beta/rc tags. release = pymongo.version # List of documents that shouldn't be included in the build. unused_docs = [] # List of directories, relative to source directory, that shouldn't be searched # for source files. exclude_trees = ["_build"] # The reST default role (used for this markup: `text`) to use for all documents. # default_role = None # If true, sectionauthor and moduleauthor directives will be shown in the # output. They are ignored by default. # show_authors = False # If true, the current module name will be prepended to all description # unit titles (such as .. function::). add_module_names = True # The name of the Pygments (syntax highlighting) style to use. pygments_style = "sphinx" # A list of ignored prefixes for module index sorting. # modindex_common_prefix = [] # Options for link checking # The anchors on the rendered markdown page are created after the fact, # so those link results in a 404. # wiki.centos.org has been flakey. # sourceforge.net is giving a 403 error, but is still accessible from the browser. linkcheck_ignore = [ "https://github.com/mongodb/specifications/blob/master/source/server-discovery-and-monitoring/server-monitoring.rst#requesting-an-immediate-check", "https://github.com/mongodb/libmongocrypt/blob/master/bindings/python/README.rst#installing-from-source", r"https://wiki.centos.org/[\w/]*", r"http://sourceforge.net/", ] # -- Options for extensions ---------------------------------------------------- autoclass_content = "init" autodoc_typehints = "description" doctest_path = [Path("..").resolve()] doctest_test_doctest_blocks = "" doctest_global_setup = """ from pymongo.mongo_client import MongoClient client = MongoClient() client.drop_database("doctest_test") db = client.doctest_test """ # -- Options for HTML output --------------------------------------------------- try: import furo # noqa: F401 html_theme = "furo" except ImportError: # Theme gratefully vendored from CPython source. html_theme = "pydoctheme" html_theme_path = ["."] html_theme_options = {"collapsiblesidebar": True, "googletag": False} # Additional static files. html_static_path = ["static"] # The name for this set of Sphinx documents. If None, it defaults to # " v documentation". # html_title = None # A shorter title for the navigation bar. Default is the same as html_title. # html_short_title = None # The name of an image file (relative to this directory) to place at the top # of the sidebar. # html_logo = None # The name of an image file (within the static path) to use as favicon of the # docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 # pixels large. # html_favicon = None # Add any paths that contain custom static files (such as style sheets) here, # relative to this directory. They are copied after the builtin static files, # so a file named "default.css" will overwrite the builtin "default.css". # html_static_path = ['_static'] # Custom sidebar templates, maps document names to template names. # html_sidebars = {} # Additional templates that should be rendered to pages, maps page names to # template names. # html_additional_pages = {} # If true, links to the reST sources are added to the pages. # html_show_sourcelink = True # If true, an OpenSearch description file will be output, and all pages will # contain a tag referring to it. The value of this option must be the # base URL from which the finished HTML is served. # html_use_opensearch = '' # If nonempty, this is the file name suffix for HTML files (e.g. ".xhtml"). # html_file_suffix = '' # Output file base name for HTML help builder. htmlhelp_basename = "PyMongo" + release.replace(".", "_") # -- Options for LaTeX output -------------------------------------------------- # The paper size ('letter' or 'a4'). # latex_paper_size = 'letter' # The font size ('10pt', '11pt' or '12pt'). # latex_font_size = '10pt' # Grouping the document tree into LaTeX files. List of tuples # (source start file, target name, title, author, documentclass [howto/manual]). latex_documents = [ ("index", "PyMongo.tex", "PyMongo Documentation", "Michael Dirolf", "manual"), ] # The name of an image file (relative to this directory) to place at the top of # the title page. # latex_logo = None # For "manual" documents, if this is true, then toplevel headings are parts, # not chapters. # latex_use_parts = False # Additional stuff for the LaTeX preamble. # latex_preamble = '' # Documents to append as an appendix to all manuals. # latex_appendices = [] # If false, no module index is generated. # latex_use_modindex = True intersphinx_mapping = { "gevent": ("https://www.gevent.org/", None), "py": ("https://docs.python.org/3/", None), } mongodb-mongo-python-driver-509e9b7/doc/contributors.rst000066400000000000000000000054051462766011000234750ustar00rootroot00000000000000Contributors ============ The following is a list of people who have contributed to **PyMongo**. If you belong here and are missing please let us know (or send a pull request after adding yourself to the list): - Mike Dirolf (mdirolf) - Jeff Jenkins (jeffjenkins) - Jim Jones - Eliot Horowitz (erh) - Michael Stephens (mikejs) - Joakim Sernbrant (serbaut) - Alexander Artemenko (svetlyak40wt) - Mathias Stearn (RedBeard0531) - Fajran Iman Rusadi (fajran) - Brad Clements (bkc) - Andrey Fedorov (andreyf) - Joshua Roesslein (joshthecoder) - Gregg Lind (gregglind) - Michael Schurter (schmichael) - Daniel Lundin - Michael Richardson (mtrichardson) - Dan McKinley (mcfunley) - David Wolever (wolever) - Carlos Valiente (carletes) - Jehiah Czebotar (jehiah) - Drew Perttula (drewp) - Carl Baatz (c-w-b) - Johan Bergstrom (jbergstroem) - Jonas Haag (jonashaag) - Kristina Chodorow (kchodorow) - Andrew Sibley (sibsibsib) - Flavio Percoco Premoli (FlaPer87) - Ken Kurzweil (kurzweil) - Christian Wyglendowski (dowski) - James Murty (jmurty) - Brendan W. McAdams (bwmcadams) - Bernie Hackett (behackett) - Reed O'Brien (reedobrien) - Francisco Souza (fsouza) - Alexey I. Froloff (raorn) - Steve Lacy (slacy) - Richard Shea (shearic) - Vladimir Sidorenko (gearheart) - Aaron Westendorf (awestendorf) - Dan Crosta (dcrosta) - Ryan Smith-Roberts (rmsr) - David Pisoni (gefilte) - Abhay Vardhan (abhayv) - Alexey Borzenkov (snaury) - Kostya Rybnikov (k-bx) - A Jesse Jiryu Davis (ajdavis) - Samuel Clay (samuelclay) - Ross Lawley (rozza) - Wouter Bolsterlee (wbolster) - Alex Grönholm (agronholm) - Christoph Simon (kalanzun) - Chris Tompkinson (tompko) - Mike O'Brien (mpobrien) - T Dampier (dampier) - Michael Henson (hensom) - Craig Hobbs (craigahobbs) - Emily Stolfo (estolfo) - Sam Helman (shelman) - Justin Patrin (reversefold) - Xiuming Chen (cxmcc) - Tyler Jones (thomascirca) - Amalia Hawkins (hawka) - Yuchen Ying (yegle) - Kyle Erf (3rf) - Luke Lovett (lovett89) - Jaroslav SemanÄík (girogiro) - Don Mitchell (dmitchell) - Ximing (armnotstrong) - Can Zhang (cannium) - Sergey Azovskov (last-g) - Heewa Barfchin (heewa) - Anna Herlihy (aherlihy) - Len Buckens (buckensl) - ultrabug - Shane Harvey (ShaneHarvey) - Cao Siyang (caosiyang) - Zhecong Kwok (gzcf) - TaoBeier(tao12345666333) - Jagrut Trivedi(Jagrut) - Shrey Batra(shreybatra) - Felipe Rodrigues(fbidu) - Terence Honles (terencehonles) - Paul Fisher (thetorpedodog) - Julius Park (juliusgeo) - Khanh Nguyen (KN99HN) - Henri Froese (henrifroese) - Ishmum Jawad Khan (ishmum123) - Arie Bovenberg (ariebovenberg) - Ben Warner (bcwarner) - Jean-Christophe Fillion-Robin (jcfr) - Sean Cheah (thalassemia) - Dainis Gorbunovs (DainisGorbunovs) - Iris Ho (sleepyStick) - Stephan Hof (stephan-hof) - Casey Clements (caseyclements) - Ivan Lukyanchikov (ilukyanchikov) mongodb-mongo-python-driver-509e9b7/doc/developer/000077500000000000000000000000001462766011000221675ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/doc/developer/index.rst000066400000000000000000000002021462766011000240220ustar00rootroot00000000000000Developer Guide =============== Technical guide for contributors to PyMongo. .. toctree:: :maxdepth: 1 periodic_executor mongodb-mongo-python-driver-509e9b7/doc/developer/periodic_executor.rst000066400000000000000000000122311462766011000264340ustar00rootroot00000000000000Periodic Executors ================== .. currentmodule:: pymongo PyMongo implements a :class:`~periodic_executor.PeriodicExecutor` for two purposes: as the background thread for :class:`~monitor.Monitor`, and to regularly check if there are ``OP_KILL_CURSORS`` messages that must be sent to the server. Killing Cursors --------------- An incompletely iterated :class:`~cursor.Cursor` on the client represents an open cursor object on the server. In code like this, we lose a reference to the cursor before finishing iteration:: for doc in collection.find(): raise Exception() We try to send an ``OP_KILL_CURSORS`` to the server to tell it to clean up the server-side cursor. But we must not take any locks directly from the cursor's destructor (see `PYTHON-799`_), so we cannot safely use the PyMongo data structures required to send a message. The solution is to add the cursor's id to an array on the :class:`~mongo_client.MongoClient` without taking any locks. Each client has a :class:`~periodic_executor.PeriodicExecutor` devoted to checking the array for cursor ids. Any it sees are the result of cursors that were freed while the server-side cursor was still open. The executor can safely take the locks it needs in order to send the ``OP_KILL_CURSORS`` message. .. _PYTHON-799: https://jira.mongodb.org/browse/PYTHON-799 Stopping Executors ------------------ Just as :class:`~cursor.Cursor` must not take any locks from its destructor, neither can :class:`~mongo_client.MongoClient` and :class:`~topology.Topology`. Thus, although the client calls :meth:`close` on its kill-cursors thread, and the topology calls :meth:`close` on all its monitor threads, the :meth:`close` method cannot actually call :meth:`wake` on the executor, since :meth:`wake` takes a lock. Instead, executors wake periodically to check if ``self.close`` is set, and if so they exit. A thread can log spurious errors if it wakes late in the Python interpreter's shutdown sequence, so we try to join threads before then. Each periodic executor (either a monitor or a kill-cursors thread) adds a weakref to itself to a set called ``_EXECUTORS``, in the ``periodic_executor`` module. An `exit handler`_ runs on shutdown and tells all executors to stop, then tries (with a short timeout) to join all executor threads. .. _exit handler: https://docs.python.org/2/library/atexit.html Monitoring ---------- For each server in the topology, :class:`~topology.Topology` uses a periodic executor to launch a monitor thread. This thread must not prevent the topology from being freed, so it weakrefs the topology. Furthermore, it uses a weakref callback to terminate itself soon after the topology is freed. Solid lines represent strong references, dashed lines weak ones: .. generated with graphviz: "dot -Tpng periodic-executor-refs.dot > periodic-executor-refs.png" .. image:: ../static/periodic-executor-refs.png See `Stopping Executors`_ above for an explanation of the ``_EXECUTORS`` set. It is a requirement of the `Server Discovery And Monitoring Spec`_ that a sleeping monitor can be awakened early. Aside from infrequent wakeups to do their appointed chores, and occasional interruptions, periodic executors also wake periodically to check if they should terminate. Our first implementation of this idea was the obvious one: use the Python standard library's threading.Condition.wait with a timeout. Another thread wakes the executor early by signaling the condition variable. A topology cannot signal the condition variable to tell the executor to terminate, because it would risk a deadlock in the garbage collector: no destructor or weakref callback can take a lock to signal the condition variable (see `PYTHON-863`_); thus the only way for a dying object to terminate a periodic executor is to set its "stopped" flag and let the executor see the flag next time it wakes. We erred on the side of prompt cleanup, and set the check interval at 100ms. We assumed that checking a flag and going back to sleep 10 times a second was cheap on modern machines. Starting in Python 3.2, the builtin C implementation of lock.acquire takes a timeout parameter, so Python 3.2+ Condition variables sleep simply by calling lock.acquire; they are implemented as efficiently as expected. But in Python 2, lock.acquire has no timeout. To wait with a timeout, a Python 2 condition variable sleeps a millisecond, tries to acquire the lock, sleeps twice as long, and tries again. This exponential backoff reaches a maximum sleep time of 50ms. If PyMongo calls the condition variable's "wait" method with a short timeout, the exponential backoff is restarted frequently. Overall, the condition variable is not waking a few times a second, but hundreds of times. (See `PYTHON-983`_.) Thus the current design of periodic executors is surprisingly simple: they do a simple ``time.sleep`` for a half-second, check if it is time to wake or terminate, and sleep again. .. _Server Discovery And Monitoring Spec: https://github.com/mongodb/specifications/blob/master/source/server-discovery-and-monitoring/server-monitoring.rst#requesting-an-immediate-check .. _PYTHON-863: https://jira.mongodb.org/browse/PYTHON-863 .. _PYTHON-983: https://jira.mongodb.org/browse/PYTHON-983 mongodb-mongo-python-driver-509e9b7/doc/examples/000077500000000000000000000000001462766011000220205ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/doc/examples/aggregation.rst000066400000000000000000000056761462766011000250570ustar00rootroot00000000000000Aggregation Examples ==================== There are several methods of performing aggregations in MongoDB. These examples cover the new aggregation framework, using map reduce and using the group method. .. testsetup:: from pymongo import MongoClient client = MongoClient() client.drop_database("aggregation_example") Setup ----- To start, we'll insert some example data which we can perform aggregations on: .. doctest:: >>> from pymongo import MongoClient >>> db = MongoClient().aggregation_example >>> result = db.things.insert_many( ... [ ... {"x": 1, "tags": ["dog", "cat"]}, ... {"x": 2, "tags": ["cat"]}, ... {"x": 2, "tags": ["mouse", "cat", "dog"]}, ... {"x": 3, "tags": []}, ... ] ... ) >>> result.inserted_ids [ObjectId('...'), ObjectId('...'), ObjectId('...'), ObjectId('...')] .. _aggregate-examples: Aggregation Framework --------------------- This example shows how to use the :meth:`~pymongo.collection.Collection.aggregate` method to use the aggregation framework. We'll perform a simple aggregation to count the number of occurrences for each tag in the ``tags`` array, across the entire collection. To achieve this we need to pass in three operations to the pipeline. First, we need to unwind the ``tags`` array, then group by the tags and sum them up, finally we sort by count. Python dictionaries prior to 3.7 don't maintain order. You should use :class:`~bson.son.SON` or :class:`collections.OrderedDict` where explicit ordering is required for an older Python version eg "$sort": .. note:: aggregate requires server version **>= 2.1.0**. .. doctest:: >>> from bson.son import SON >>> pipeline = [ ... {"$unwind": "$tags"}, ... {"$group": {"_id": "$tags", "count": {"$sum": 1}}}, ... {"$sort": SON([("count", -1), ("_id", -1)])}, ... ] >>> import pprint >>> pprint.pprint(list(db.things.aggregate(pipeline))) [{'_id': 'cat', 'count': 3}, {'_id': 'dog', 'count': 2}, {'_id': 'mouse', 'count': 1}] To run an explain plan for this aggregation use `PyMongoExplain `_, a companion library for PyMongo. It allows you to explain any CRUD operation by providing a few convenience classes:: >>> from pymongoexplain import ExplainableCollection >>> ExplainableCollection(collection).aggregate(pipeline) {'ok': 1.0, 'queryPlanner': [...]} Or, use the :meth:`~pymongo.database.Database.command` method:: >>> db.command('aggregate', 'things', pipeline=pipeline, explain=True) {'ok': 1.0, 'stages': [...]} As well as simple aggregations the aggregation framework provides projection capabilities to reshape the returned data. Using projections and aggregation, you can add computed fields, create new virtual sub-objects, and extract sub-fields into the top-level of results. .. seealso:: The full documentation for MongoDB's `aggregation framework `_ mongodb-mongo-python-driver-509e9b7/doc/examples/authentication.rst000066400000000000000000000510451462766011000255760ustar00rootroot00000000000000Authentication Examples ======================= MongoDB supports several different authentication mechanisms. These examples cover all authentication methods currently supported by PyMongo, documenting Python module and MongoDB version dependencies. .. _percent escaped: Percent-Escaping Username and Password -------------------------------------- Username and password must be percent-escaped with :py:func:`urllib.parse.quote_plus`, to be used in a MongoDB URI. For example:: >>> from pymongo import MongoClient >>> import urllib.parse >>> username = urllib.parse.quote_plus('user') >>> username 'user' >>> password = urllib.parse.quote_plus('pass/word') >>> password 'pass%2Fword' >>> MongoClient('mongodb://%s:%s@127.0.0.1' % (username, password)) ... .. _scram_sha_256: SCRAM-SHA-256 (RFC 7677) ------------------------ .. versionadded:: 3.7 SCRAM-SHA-256 is the default authentication mechanism supported by a cluster configured for authentication with MongoDB 4.0 or later. Authentication requires a username, a password, and a database name. The default database name is "admin", this can be overridden with the ``authSource`` option. Credentials can be specified as arguments to :class:`~pymongo.mongo_client.MongoClient`:: >>> from pymongo import MongoClient >>> client = MongoClient('example.com', ... username='user', ... password='password', ... authSource='the_database', ... authMechanism='SCRAM-SHA-256') Or through the MongoDB URI:: >>> uri = "mongodb://user:password@example.com/?authSource=the_database&authMechanism=SCRAM-SHA-256" >>> client = MongoClient(uri) SCRAM-SHA-1 (RFC 5802) ---------------------- .. versionadded:: 2.8 SCRAM-SHA-1 is the default authentication mechanism supported by a cluster configured for authentication with MongoDB 3.0 or later. Authentication requires a username, a password, and a database name. The default database name is "admin", this can be overridden with the ``authSource`` option. Credentials can be specified as arguments to :class:`~pymongo.mongo_client.MongoClient`:: >>> from pymongo import MongoClient >>> client = MongoClient('example.com', ... username='user', ... password='password', ... authSource='the_database', ... authMechanism='SCRAM-SHA-1') Or through the MongoDB URI:: >>> uri = "mongodb://user:password@example.com/?authSource=the_database&authMechanism=SCRAM-SHA-1" >>> client = MongoClient(uri) For best performance on Python versions older than 2.7.8 install `backports.pbkdf2`_. .. _backports.pbkdf2: https://pypi.python.org/pypi/backports.pbkdf2/ MONGODB-CR ---------- .. warning:: MONGODB-CR was deprecated with the release of MongoDB 3.6 and is no longer supported by MongoDB 4.0. Before MongoDB 3.0 the default authentication mechanism was MONGODB-CR, the "MongoDB Challenge-Response" protocol:: >>> from pymongo import MongoClient >>> client = MongoClient('example.com', ... username='user', ... password='password', ... authMechanism='MONGODB-CR') >>> >>> uri = "mongodb://user:password@example.com/?authSource=the_database&authMechanism=MONGODB-CR" >>> client = MongoClient(uri) Default Authentication Mechanism -------------------------------- If no mechanism is specified, PyMongo automatically SCRAM-SHA-1 when connected to MongoDB 3.6 and negotiates the mechanism to use (SCRAM-SHA-1 or SCRAM-SHA-256) when connected to MongoDB 4.0+. Default Database and "authSource" --------------------------------- You can specify both a default database and the authentication database in the URI:: >>> uri = "mongodb://user:password@example.com/default_db?authSource=admin" >>> client = MongoClient(uri) PyMongo will authenticate on the "admin" database, but the default database will be "default_db":: >>> # get_database with no "name" argument chooses the DB from the URI >>> db = MongoClient(uri).get_database() >>> print(db.name) 'default_db' .. _mongodb_x509: MONGODB-X509 ------------ .. versionadded:: 2.6 The MONGODB-X509 mechanism authenticates via the X.509 certificate presented by the driver during TLS/SSL negotiation. This authentication method requires the use of TLS/SSL connections with certificate validation:: >>> from pymongo import MongoClient >>> client = MongoClient('example.com', ... authMechanism="MONGODB-X509", ... tls=True, ... tlsCertificateKeyFile='/path/to/client.pem', ... tlsCAFile='/path/to/ca.pem') MONGODB-X509 authenticates against the $external virtual database, so you do not have to specify a database in the URI:: >>> uri = "mongodb://example.com/?authMechanism=MONGODB-X509" >>> client = MongoClient(uri, ... tls=True, ... tlsCertificateKeyFile='/path/to/client.pem', ... tlsCAFile='/path/to/ca.pem') >>> .. _gssapi: GSSAPI (Kerberos) ----------------- .. versionadded:: 2.5 GSSAPI (Kerberos) authentication is available in the Enterprise Edition of MongoDB. Unix ~~~~ To authenticate using GSSAPI you must first install the python `kerberos`_ or `pykerberos`_ module using easy_install or pip. Make sure you run kinit before using the following authentication methods:: $ kinit mongodbuser@EXAMPLE.COM mongodbuser@EXAMPLE.COM's Password: $ klist Credentials cache: FILE:/tmp/krb5cc_1000 Principal: mongodbuser@EXAMPLE.COM Issued Expires Principal Feb 9 13:48:51 2013 Feb 9 23:48:51 2013 krbtgt/EXAMPLE.COM@EXAMPLE.COM Now authenticate using the MongoDB URI. GSSAPI authenticates against the $external virtual database so you do not have to specify a database in the URI:: >>> # Note: the kerberos principal must be url encoded. >>> from pymongo import MongoClient >>> uri = "mongodb://mongodbuser%40EXAMPLE.COM@mongo-server.example.com/?authMechanism=GSSAPI" >>> client = MongoClient(uri) >>> The default service name used by MongoDB and PyMongo is ``mongodb``. You can specify a custom service name with the ``authMechanismProperties`` option:: >>> from pymongo import MongoClient >>> uri = "mongodb://mongodbuser%40EXAMPLE.COM@mongo-server.example.com/?authMechanism=GSSAPI&authMechanismProperties=SERVICE_NAME:myservicename" >>> client = MongoClient(uri) Windows (SSPI) ~~~~~~~~~~~~~~ .. versionadded:: 3.3 First install the `winkerberos`_ module. Unlike authentication on Unix kinit is not used. If the user to authenticate is different from the user that owns the application process provide a password to authenticate:: >>> uri = "mongodb://mongodbuser%40EXAMPLE.COM:mongodbuserpassword@example.com/?authMechanism=GSSAPI" Two extra ``authMechanismProperties`` are supported on Windows platforms: - CANONICALIZE_HOST_NAME - Uses the fully qualified domain name (FQDN) of the MongoDB host for the server principal (GSSAPI libraries on Unix do this by default):: >>> uri = "mongodb://mongodbuser%40EXAMPLE.COM@example.com/?authMechanism=GSSAPI&authMechanismProperties=CANONICALIZE_HOST_NAME:true" - SERVICE_REALM - This is used when the user's realm is different from the service's realm:: >>> uri = "mongodb://mongodbuser%40EXAMPLE.COM@example.com/?authMechanism=GSSAPI&authMechanismProperties=SERVICE_REALM:otherrealm" .. _kerberos: http://pypi.python.org/pypi/kerberos .. _pykerberos: https://pypi.python.org/pypi/pykerberos .. _winkerberos: https://pypi.python.org/pypi/winkerberos/ .. _sasl_plain: SASL PLAIN (RFC 4616) --------------------- .. versionadded:: 2.6 MongoDB Enterprise Edition version 2.6 and newer support the SASL PLAIN authentication mechanism, initially intended for delegating authentication to an LDAP server. Using the PLAIN mechanism is very similar to MONGODB-CR. These examples use the $external virtual database for LDAP support:: >>> from pymongo import MongoClient >>> uri = "mongodb://user:password@example.com/?authMechanism=PLAIN" >>> client = MongoClient(uri) >>> SASL PLAIN is a clear-text authentication mechanism. We **strongly** recommend that you connect to MongoDB using TLS/SSL with certificate validation when using the SASL PLAIN mechanism:: >>> from pymongo import MongoClient >>> uri = "mongodb://user:password@example.com/?authMechanism=PLAIN" >>> client = MongoClient(uri, ... tls=True, ... tlsCertificateKeyFile='/path/to/client.pem', ... tlsCAFile='/path/to/ca.pem') >>> .. _MONGODB-AWS: MONGODB-AWS ----------- .. versionadded:: 3.11 The MONGODB-AWS authentication mechanism is available in MongoDB 4.4+ and requires extra pymongo dependencies. To use it, install pymongo with the ``aws`` extra:: $ python -m pip install 'pymongo[aws]' The MONGODB-AWS mechanism authenticates using AWS IAM credentials (an access key ID and a secret access key), `temporary AWS IAM credentials`_ obtained from an `AWS Security Token Service (STS)`_ `Assume Role`_ request, AWS Lambda `environment variables`_, or temporary AWS IAM credentials assigned to an `EC2 instance`_ or ECS task. The use of temporary credentials, in addition to an access key ID and a secret access key, also requires a security (or session) token. Credentials can be configured through the MongoDB URI, environment variables, or the local EC2 or ECS endpoint. The order in which the client searches for `credentials`_ is the same as the one used by the AWS ``boto3`` library when using ``pymongo_auth_aws>=1.1.0``. Because we are now using ``boto3`` to handle credentials, the order and locations of credentials are slightly different from before. Particularly, if you have a shared AWS credentials or config file, then those credentials will be used by default if AWS auth environment variables are not set. To override this behavior, set ``AWS_SHARED_CREDENTIALS_FILE=""`` in your shell or add ``os.environ["AWS_SHARED_CREDENTIALS_FILE"] = ""`` to your script or application. Alternatively, you can create an AWS profile specifically for your MongoDB credentials and set ``AWS_PROFILE`` to that profile name. MONGODB-AWS authenticates against the "$external" virtual database, so none of the URIs in this section need to include the ``authSource`` URI option. .. _credentials: https://boto3.amazonaws.com/v1/documentation/api/latest/guide/credentials.html AWS IAM credentials ~~~~~~~~~~~~~~~~~~~ Applications can authenticate using AWS IAM credentials by providing a valid access key id and secret access key pair as the username and password, respectively, in the MongoDB URI. A sample URI would be:: >>> from pymongo import MongoClient >>> uri = "mongodb+srv://:@example.mongodb.net/?authMechanism=MONGODB-AWS" >>> client = MongoClient(uri) .. note:: The access_key_id and secret_access_key passed into the URI MUST be `percent escaped`_. AssumeRole ~~~~~~~~~~ Applications can authenticate using temporary credentials returned from an assume role request. These temporary credentials consist of an access key ID, a secret access key, and a security token passed into the URI. A sample URI would be:: >>> from pymongo import MongoClient >>> uri = "mongodb+srv://:@example.mongodb.net/?authMechanism=MONGODB-AWS&authMechanismProperties=AWS_SESSION_TOKEN:" >>> client = MongoClient(uri) .. note:: The access_key_id, secret_access_key, and session_token passed into the URI MUST be `percent escaped`_. AWS Lambda (Environment Variables) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ When the username and password are not provided and the MONGODB-AWS mechanism is set, the client will fallback to using the `environment variables`_ ``AWS_ACCESS_KEY_ID``, ``AWS_SECRET_ACCESS_KEY``, and ``AWS_SESSION_TOKEN`` for the access key ID, secret access key, and session token, respectively:: $ export AWS_ACCESS_KEY_ID= $ export AWS_SECRET_ACCESS_KEY= $ export AWS_SESSION_TOKEN= $ python >>> from pymongo import MongoClient >>> uri = "mongodb+srv://example.mongodb.net/?authMechanism=MONGODB-AWS" >>> client = MongoClient(uri) .. note:: No username, password, or session token is passed into the URI. PyMongo will use credentials set via the environment variables. These environment variables MUST NOT be `percent escaped`_. .. _EKS Clusters: EKS Clusters ~~~~~~~~~~~~ Applications using the `Authenticating users for your cluster from an OpenID Connect identity provider `_ capability on EKS can now use the provided credentials, by giving the associated IAM User `sts:AssumeRoleWithWebIdentity `_ permission. When the username and password are not provided, the MONGODB-AWS mechanism is set, and ``AWS_WEB_IDENTITY_TOKEN_FILE``, ``AWS_ROLE_ARN``, and optional ``AWS_ROLE_SESSION_NAME`` are available, the driver will use an ``AssumeRoleWithWebIdentity`` call to retrieve temporary credentials. The application must be using ``pymongo_auth_aws`` >= 1.1.0 for EKS support. ECS Container ~~~~~~~~~~~~~ Applications can authenticate from an ECS container via temporary credentials assigned to the machine. A sample URI on an ECS container would be:: >>> from pymongo import MongoClient >>> uri = "mongodb+srv://example.mongodb.com/?authMechanism=MONGODB-AWS" >>> client = MongoClient(uri) .. note:: No username, password, or session token is passed into the URI. PyMongo will query the ECS container endpoint to obtain these credentials. EC2 Instance ~~~~~~~~~~~~ Applications can authenticate from an EC2 instance via temporary credentials assigned to the machine. A sample URI on an EC2 machine would be:: >>> from pymongo import MongoClient >>> uri = "mongodb+srv://example.mongodb.com/?authMechanism=MONGODB-AWS" >>> client = MongoClient(uri) .. note:: No username, password, or session token is passed into the URI. PyMongo will query the EC2 instance endpoint to obtain these credentials. .. _temporary AWS IAM credentials: https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_temp.html .. _AWS Security Token Service (STS): https://docs.aws.amazon.com/STS/latest/APIReference/Welcome.html .. _Assume Role: https://docs.aws.amazon.com/STS/latest/APIReference/API_AssumeRole.html .. _EC2 instance: https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_use_switch-role-ec2.html .. _environment variables: https://docs.aws.amazon.com/lambda/latest/dg/configuration-envvars.html#configuration-envvars-runtime MONGODB-OIDC ------------ .. versionadded:: 4.7 The `MONGODB-OIDC authentication mechanism`_ is available in MongoDB 7.0+ on Linux platforms. The MONGODB-OIDC mechanism authenticates using an OpenID Connect (OIDC) access token. The driver supports OIDC for workload identity, defined as an identity you assign to a software workload (such as an application, service, script, or container) to authenticate and access other services and resources. Credentials can be configured through the MongoDB URI or as arguments to :class:`~pymongo.mongo_client.MongoClient`. Built-in Support ~~~~~~~~~~~~~~~~ The driver has built-in support for Azure IMDS and GCP IMDS environments. Other environments are supported with `Custom Callbacks`_. Azure IMDS ^^^^^^^^^^ For an application running on an Azure VM or otherwise using the `Azure Internal Metadata Service`_, you can use the built-in support for Azure. If using an Azure managed identity, the "" is the client ID. If using a service principal to represent an enterprise application, the "" is the application ID of the service principal. The ```` value is the ``audience`` `configured on your MongoDB deployment`_. .. code-block:: python import os uri = os.environ["MONGODB_URI"] props = {"ENVIRONMENT": "azure", "TOKEN_RESOURCE": ""} c = MongoClient( uri, username="", authMechanism="MONGODB-OIDC", authMechanismProperties=props, ) c.test.test.insert_one({}) c.close() If the application is running on an Azure VM and only one managed identity is associated with the VM, ``username`` can be omitted. If providing the ``TOKEN_RESOURCE`` as part of a connection string, it can be given as follows. If the ``TOKEN_RESOURCE`` contains any of the following characters [``,``, ``+``, ``&``], then it MUST be url-encoded. .. code-block:: python import os uri = f'{os.environ["MONGODB_URI"]}?authMechanism=MONGODB-OIDC&authMechanismProperties=ENVIRONMENT:azure,TOKEN_RESOURCE:' c = MongoClient(uri) c.test.test.insert_one({}) c.close() GCP IMDS ^^^^^^^^ For an application running on an GCP VM or otherwise using the `GCP Internal Metadata Service`_, you can use the built-in support for GCP, where ```` below is the ``audience`` `configured on your MongoDB deployment`_. .. code-block:: python import os uri = os.environ["MONGODB_URI"] props = {"ENVIRONMENT": "gcp", "TOKEN_RESOURCE": ""} c = MongoClient(uri, authMechanism="MONGODB-OIDC", authMechanismProperties=props) c.test.test.insert_one({}) c.close() If providing the ``TOKEN_RESOURCE`` as part of a connection string, it can be given as follows. If the ``TOKEN_RESOURCE`` contains any of the following characters [``,``, ``+``, ``&``], then it MUST be url-encoded. .. code-block:: python import os uri = f'{os.environ["MONGODB_URI"]}?authMechanism=MONGODB-OIDC&authMechanismProperties=ENVIRONMENT:gcp,TOKEN_RESOURCE:' c = MongoClient(uri) c.test.test.insert_one({}) c.close() Custom Callbacks ~~~~~~~~~~~~~~~~ For environments that are not directly supported by the driver, you can use :class:`~pymongo.auth_oidc.OIDCCallback`. Some examples are given below. Other Azure Environments ^^^^^^^^^^^^^^^^^^^^^^^^ For applications running on Azure Functions, App Service Environment (ASE), or Azure Kubernetes Service (AKS), you can use the `azure-identity package`_ to fetch the credentials. This example assumes you have set environment variables for the ``audience`` `configured on your MongoDB deployment`_, and for the client id of the Azure managed identity. .. code-block:: python import os from azure.identity import DefaultAzureCredential from pymongo import MongoClient from pymongo.auth_oidc import OIDCCallback, OIDCCallbackContext, OIDCCallbackResult audience = os.environ["AZURE_AUDIENCE"] client_id = os.environ["AZURE_IDENTITY_CLIENT_ID"] uri = os.environ["MONGODB_URI"] class MyCallback(OIDCCallback): def fetch(self, context: OIDCCallbackContext) -> OIDCCallbackResult: credential = DefaultAzureCredential(managed_identity_client_id=client_id) token = credential.get_token(f"{audience}/.default").token return OIDCCallbackResult(access_token=token) props = {"OIDC_CALLBACK": MyCallback()} c = MongoClient(uri, authMechanism="MONGODB-OIDC", authMechanismProperties=props) c.test.test.insert_one({}) c.close() GCP GKE ^^^^^^^ For a Google Kubernetes Engine cluster with a `configured service account`_, the token can be read from the standard service account token file location. .. code-block:: python import os from pymongo.auth_oidc import OIDCCallback, OIDCCallbackContext, OIDCCallbackResult class MyCallback(OIDCCallback): def fetch(self, context: OIDCCallbackContext) -> OIDCCallbackResult: with open("/var/run/secrets/kubernetes.io/serviceaccount/token") as fid: token = fid.read() return OIDCCallbackResult(access_token=token) uri = os.environ["MONGODB_URI"] props = {"OIDC_CALLBACK": MyCallback()} c = MongoClient(uri, authMechanism="MONGODB-OIDC", authMechanismProperties=props) c.test.test.insert_one({}) c.close() .. _MONGODB-OIDC authentication mechanism: https://www.mongodb.com/docs/manual/core/security-oidc/ .. _Azure Internal Metadata Service: https://learn.microsoft.com/en-us/azure/virtual-machines/instance-metadata-service .. _configured on your MongoDB deployment: https://www.mongodb.com/docs/manual/reference/parameters/#mongodb-parameter-param.oidcIdentityProviders .. _GCP Internal Metadata Service: https://cloud.google.com/compute/docs/metadata/querying-metadata .. _azure-identity package: https://pypi.org/project/azure-identity/ .. _configured service account: https://cloud.google.com/kubernetes-engine/docs/how-to/service-accounts mongodb-mongo-python-driver-509e9b7/doc/examples/bulk.rst000066400000000000000000000127321462766011000235140ustar00rootroot00000000000000Bulk Write Operations ===================== .. testsetup:: from pymongo import MongoClient client = MongoClient() client.drop_database("bulk_example") This tutorial explains how to take advantage of PyMongo's bulk write operation features. Executing write operations in batches reduces the number of network round trips, increasing write throughput. Bulk Insert ----------- .. versionadded:: 2.6 A batch of documents can be inserted by passing a list to the :meth:`~pymongo.collection.Collection.insert_many` method. PyMongo will automatically split the batch into smaller sub-batches based on the maximum message size accepted by MongoDB, supporting very large bulk insert operations. .. doctest:: >>> import pymongo >>> db = pymongo.MongoClient().bulk_example >>> db.test.insert_many([{"i": i} for i in range(10000)]).inserted_ids [...] >>> db.test.count_documents({}) 10000 Mixed Bulk Write Operations --------------------------- .. versionadded:: 2.7 PyMongo also supports executing mixed bulk write operations. A batch of insert, update, and remove operations can be executed together using the bulk write operations API. .. _ordered_bulk: Ordered Bulk Write Operations ............................. Ordered bulk write operations are batched and sent to the server in the order provided for serial execution. The return value is an instance of :class:`~pymongo.results.BulkWriteResult` describing the type and count of operations performed. .. doctest:: :options: +NORMALIZE_WHITESPACE >>> from pprint import pprint >>> from pymongo import InsertOne, DeleteMany, ReplaceOne, UpdateOne >>> result = db.test.bulk_write( ... [ ... DeleteMany({}), # Remove all documents from the previous example. ... InsertOne({"_id": 1}), ... InsertOne({"_id": 2}), ... InsertOne({"_id": 3}), ... UpdateOne({"_id": 1}, {"$set": {"foo": "bar"}}), ... UpdateOne({"_id": 4}, {"$inc": {"j": 1}}, upsert=True), ... ReplaceOne({"j": 1}, {"j": 2}), ... ] ... ) >>> pprint(result.bulk_api_result) {'nInserted': 3, 'nMatched': 2, 'nModified': 2, 'nRemoved': 10000, 'nUpserted': 1, 'upserted': [{'_id': 4, 'index': 5}], 'writeConcernErrors': [], 'writeErrors': []} The first write failure that occurs (e.g. duplicate key error) aborts the remaining operations, and PyMongo raises :class:`~pymongo.errors.BulkWriteError`. The :attr:`details` attribute of the exception instance provides the execution results up until the failure occurred and details about the failure - including the operation that caused the failure. .. doctest:: :options: +NORMALIZE_WHITESPACE >>> from pymongo import InsertOne, DeleteOne, ReplaceOne >>> from pymongo.errors import BulkWriteError >>> requests = [ ... ReplaceOne({"j": 2}, {"i": 5}), ... InsertOne({"_id": 4}), # Violates the unique key constraint on _id. ... DeleteOne({"i": 5}), ... ] >>> try: ... db.test.bulk_write(requests) ... except BulkWriteError as bwe: ... pprint(bwe.details) ... {'nInserted': 0, 'nMatched': 1, 'nModified': 1, 'nRemoved': 0, 'nUpserted': 0, 'upserted': [], 'writeConcernErrors': [], 'writeErrors': [{'code': 11000, 'errmsg': '...E11000...duplicate key error...', 'index': 1,... 'op': {'_id': 4}}]} .. _unordered_bulk: Unordered Bulk Write Operations ............................... Unordered bulk write operations are batched and sent to the server in **arbitrary order** where they may be executed in parallel. Any errors that occur are reported after all operations are attempted. In the next example the first and third operations fail due to the unique constraint on _id. Since we are doing unordered execution the second and fourth operations succeed. .. doctest:: :options: +NORMALIZE_WHITESPACE >>> requests = [ ... InsertOne({"_id": 1}), ... DeleteOne({"_id": 2}), ... InsertOne({"_id": 3}), ... ReplaceOne({"_id": 4}, {"i": 1}), ... ] >>> try: ... db.test.bulk_write(requests, ordered=False) ... except BulkWriteError as bwe: ... pprint(bwe.details) ... {'nInserted': 0, 'nMatched': 1, 'nModified': 1, 'nRemoved': 1, 'nUpserted': 0, 'upserted': [], 'writeConcernErrors': [], 'writeErrors': [{'code': 11000, 'errmsg': '...E11000...duplicate key error...', 'index': 0,... 'op': {'_id': 1}}, {'code': 11000, 'errmsg': '...', 'index': 2,... 'op': {'_id': 3}}]} Write Concern ............. Bulk operations are executed with the :attr:`~pymongo.collection.Collection.write_concern` of the collection they are executed against. Write concern errors (e.g. wtimeout) will be reported after all operations are attempted, regardless of execution order. :: >>> from pymongo import WriteConcern >>> coll = db.get_collection( ... 'test', write_concern=WriteConcern(w=3, wtimeout=1)) >>> try: ... coll.bulk_write([InsertOne({'a': i}) for i in range(4)]) ... except BulkWriteError as bwe: ... pprint(bwe.details) ... {'nInserted': 4, 'nMatched': 0, 'nModified': 0, 'nRemoved': 0, 'nUpserted': 0, 'upserted': [], 'writeConcernErrors': [{'code': 64... 'errInfo': {'wtimeout': True}, 'errmsg': 'waiting for replication timed out'}], 'writeErrors': []} mongodb-mongo-python-driver-509e9b7/doc/examples/collations.rst000066400000000000000000000115361462766011000247270ustar00rootroot00000000000000Collations ========== .. seealso:: The API docs for :mod:`~pymongo.collation`. Collations are a new feature in MongoDB version 3.4. They provide a set of rules to use when comparing strings that comply with the conventions of a particular language, such as Spanish or German. If no collation is specified, the server sorts strings based on a binary comparison. Many languages have specific ordering rules, and collations allow users to build applications that adhere to language-specific comparison rules. In French, for example, the last accent in a given word determines the sorting order. The correct sorting order for the following four words in French is:: cote < côte < coté < côté Specifying a French collation allows users to sort string fields using the French sort order. Usage ----- Users can specify a collation for a :ref:`collection`, an :ref:`index`, or a :ref:`CRUD command `. Collation Parameters: ~~~~~~~~~~~~~~~~~~~~~ Collations can be specified with the :class:`~pymongo.collation.Collation` model or with plain Python dictionaries. The structure is the same:: Collation(locale=, caseLevel=, caseFirst=, strength=, numericOrdering=, alternate=, maxVariable=, backwards=) The only required parameter is ``locale``, which the server parses as an `ICU format locale ID `_. For example, set ``locale`` to ``en_US`` to represent US English or ``fr_CA`` to represent Canadian French. For a complete description of the available parameters, see the MongoDB `manual `_. .. COMMENT add link for manual entry. .. _collation-on-collection: Assign a Default Collation to a Collection ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ The following example demonstrates how to create a new collection called ``contacts`` and assign a default collation with the ``fr_CA`` locale. This operation ensures that all queries that are run against the ``contacts`` collection use the ``fr_CA`` collation unless another collation is explicitly specified:: from pymongo import MongoClient from pymongo.collation import Collation db = MongoClient().test collection = db.create_collection('contacts', collation=Collation(locale='fr_CA')) .. _collation-on-index: Assign a Default Collation to an Index ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ When creating a new index, you can specify a default collation. The following example shows how to create an index on the ``name`` field of the ``contacts`` collection, with the ``unique`` parameter enabled and a default collation with ``locale`` set to ``fr_CA``:: from pymongo import MongoClient from pymongo.collation import Collation contacts = MongoClient().test.contacts contacts.create_index('name', unique=True, collation=Collation(locale='fr_CA')) .. _collation-on-operation: Specify a Collation for a Query ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Individual queries can specify a collation to use when sorting results. The following example demonstrates a query that runs on the ``contacts`` collection in database ``test``. It matches on documents that contain ``New York`` in the ``city`` field, and sorts on the ``name`` field with the ``fr_CA`` collation:: from pymongo import MongoClient from pymongo.collation import Collation collection = MongoClient().test.contacts docs = collection.find({'city': 'New York'}).sort('name').collation( Collation(locale='fr_CA')) Other Query Types ~~~~~~~~~~~~~~~~~ You can use collations to control document matching rules for several different types of queries. All the various update and delete methods (:meth:`~pymongo.collection.Collection.update_one`, :meth:`~pymongo.collection.Collection.update_many`, :meth:`~pymongo.collection.Collection.delete_one`, etc.) support collation, and you can create query filters which employ collations to comply with any of the languages and variants available to the ``locale`` parameter. The following example uses a collation with ``strength`` set to :const:`~pymongo.collation.CollationStrength.SECONDARY`, which considers only the base character and character accents in string comparisons, but not case sensitivity, for example. All documents in the ``contacts`` collection with ``jürgen`` (case-insensitive) in the ``first_name`` field are updated:: from pymongo import MongoClient from pymongo.collation import Collation, CollationStrength contacts = MongoClient().test.contacts result = contacts.update_many( {'first_name': 'jürgen'}, {'$set': {'verified': 1}}, collation=Collation(locale='de', strength=CollationStrength.SECONDARY)) mongodb-mongo-python-driver-509e9b7/doc/examples/copydb.rst000066400000000000000000000054011462766011000240320ustar00rootroot00000000000000Copying a Database ================== MongoDB >= 4.2 -------------- Starting in MongoDB version 4.2, the server removes the deprecated ``copydb`` command. As an alternative, users can use ``mongodump`` and ``mongorestore`` (with the ``mongorestore`` options ``--nsFrom`` and ``--nsTo``). For example, to copy the ``test`` database from a local instance running on the default port 27017 to the ``examples`` database on the same instance, you can: #. Use ``mongodump`` to dump the test database to an archive ``mongodump-test-db``:: mongodump --archive="mongodump-test-db" --db=test #. Use ``mongorestore`` with ``--nsFrom`` and ``--nsTo`` to restore (with database name change) from the archive:: mongorestore --archive="mongodump-test-db" --nsFrom='test.*' --nsTo='examples.*' Include additional options as necessary, such as to specify the uri or host, username, password and authentication database. For more info about using ``mongodump`` and ``mongorestore`` see the `Copy a Database`_ example in the official ``mongodump`` documentation. MongoDB <= 4.0 -------------- When using MongoDB <= 4.0, it is possible to use the deprecated ``copydb`` command to copy a database. To copy a database within a single ``mongod`` process, or between ``mongod`` servers, connect to the target ``mongod`` and use the :meth:`~pymongo.database.Database.command` method:: >>> from pymongo import MongoClient >>> client = MongoClient('target.example.com') >>> client.admin.command('copydb', fromdb='source_db_name', todb='target_db_name') To copy from a different mongod server that is not password-protected:: >>> client.admin.command('copydb', fromdb='source_db_name', todb='target_db_name', fromhost='source.example.com') If the target server is password-protected, authenticate to the "admin" database:: >>> client = MongoClient('target.example.com', ... username='administrator', ... password='pwd') >>> client.admin.command('copydb', fromdb='source_db_name', todb='target_db_name', fromhost='source.example.com') See the :doc:`authentication examples `. If the **source** server is password-protected, use the `copyDatabase function in the mongo shell`_. Versions of PyMongo before 3.0 included a ``copy_database`` helper method, but it has been removed. .. _copyDatabase function in the mongo shell: http://mongodb.com/docs/manual/reference/method/db.copyDatabase/ .. _Copy a Database: https://www.mongodb.com/docs/database-tools/mongodump/mongodump-examples/#copy-and-clone-databases mongodb-mongo-python-driver-509e9b7/doc/examples/custom_type.rst000066400000000000000000000356001462766011000251310ustar00rootroot00000000000000Custom Type Example =================== This is an example of using a custom type with PyMongo. The example here shows how to subclass :class:`~bson.codec_options.TypeCodec` to write a type codec, which is used to populate a :class:`~bson.codec_options.TypeRegistry`. The type registry can then be used to create a custom-type-aware :class:`~pymongo.collection.Collection`. Read and write operations issued against the resulting collection object transparently manipulate documents as they are saved to or retrieved from MongoDB. Setting Up ---------- We'll start by getting a clean database to use for the example: .. doctest:: >>> from pymongo import MongoClient >>> client = MongoClient() >>> client.drop_database("custom_type_example") >>> db = client.custom_type_example Since the purpose of the example is to demonstrate working with custom types, we'll need a custom data type to use. For this example, we will be working with the :py:class:`~decimal.Decimal` type from Python's standard library. Since the BSON library's :class:`~bson.decimal128.Decimal128` type (that implements the IEEE 754 decimal128 decimal-based floating-point numbering format) is distinct from Python's built-in :py:class:`~decimal.Decimal` type, attempting to save an instance of ``Decimal`` with PyMongo, results in an :exc:`~bson.errors.InvalidDocument` exception. .. doctest:: >>> from decimal import Decimal >>> num = Decimal("45.321") >>> db.test.insert_one({"num": num}) Traceback (most recent call last): ... bson.errors.InvalidDocument: cannot encode object: Decimal('45.321'), of type: .. _custom-type-type-codec: The :class:`~bson.codec_options.TypeCodec` Class ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ .. versionadded:: 3.8 In order to encode a custom type, we must first define a **type codec** for that type. A type codec describes how an instance of a custom type can be *transformed* to and/or from one of the types :mod:`~bson` already understands. Depending on the desired functionality, users must choose from the following base classes when defining type codecs: * :class:`~bson.codec_options.TypeEncoder`: subclass this to define a codec that encodes a custom Python type to a known BSON type. Users must implement the ``python_type`` property/attribute and the ``transform_python`` method. * :class:`~bson.codec_options.TypeDecoder`: subclass this to define a codec that decodes a specified BSON type into a custom Python type. Users must implement the ``bson_type`` property/attribute and the ``transform_bson`` method. * :class:`~bson.codec_options.TypeCodec`: subclass this to define a codec that can both encode and decode a custom type. Users must implement the ``python_type`` and ``bson_type`` properties/attributes, as well as the ``transform_python`` and ``transform_bson`` methods. The type codec for our custom type simply needs to define how a :py:class:`~decimal.Decimal` instance can be converted into a :class:`~bson.decimal128.Decimal128` instance and vice-versa. Since we are interested in both encoding and decoding our custom type, we use the ``TypeCodec`` base class to define our codec: .. doctest:: >>> from bson.decimal128 import Decimal128 >>> from bson.codec_options import TypeCodec >>> class DecimalCodec(TypeCodec): ... python_type = Decimal # the Python type acted upon by this type codec ... bson_type = Decimal128 # the BSON type acted upon by this type codec ... def transform_python(self, value): ... """Function that transforms a custom type value into a type ... that BSON can encode.""" ... return Decimal128(value) ... def transform_bson(self, value): ... """Function that transforms a vanilla BSON type value into our ... custom type.""" ... return value.to_decimal() ... >>> decimal_codec = DecimalCodec() .. _custom-type-type-registry: The :class:`~bson.codec_options.TypeRegistry` Class ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ .. versionadded:: 3.8 Before we can begin encoding and decoding our custom type objects, we must first inform PyMongo about the corresponding codec. This is done by creating a :class:`~bson.codec_options.TypeRegistry` instance: .. doctest:: >>> from bson.codec_options import TypeRegistry >>> type_registry = TypeRegistry([decimal_codec]) Note that type registries can be instantiated with any number of type codecs. Once instantiated, registries are immutable and the only way to add codecs to a registry is to create a new one. Putting It Together ------------------- Finally, we can define a :class:`~bson.codec_options.CodecOptions` instance with our ``type_registry`` and use it to get a :class:`~pymongo.collection.Collection` object that understands the :py:class:`~decimal.Decimal` data type: .. doctest:: >>> from bson.codec_options import CodecOptions >>> codec_options = CodecOptions(type_registry=type_registry) >>> collection = db.get_collection("test", codec_options=codec_options) Now, we can seamlessly encode and decode instances of :py:class:`~decimal.Decimal`: .. doctest:: >>> collection.insert_one({"num": Decimal("45.321")}) InsertOneResult(ObjectId('...'), acknowledged=True) >>> mydoc = collection.find_one() >>> import pprint >>> pprint.pprint(mydoc) {'_id': ObjectId('...'), 'num': Decimal('45.321')} We can see what's actually being saved to the database by creating a fresh collection object without the customized codec options and using that to query MongoDB: .. doctest:: >>> vanilla_collection = db.get_collection("test") >>> pprint.pprint(vanilla_collection.find_one()) {'_id': ObjectId('...'), 'num': Decimal128('45.321')} Encoding Subtypes ^^^^^^^^^^^^^^^^^ Consider the situation where, in addition to encoding :py:class:`~decimal.Decimal`, we also need to encode a type that subclasses ``Decimal``. PyMongo does this automatically for types that inherit from Python types that are BSON-encodable by default, but the type codec system described above does not offer the same flexibility. Consider this subtype of ``Decimal`` that has a method to return its value as an integer: .. doctest:: >>> class DecimalInt(Decimal): ... def my_method(self): ... """Method implementing some custom logic.""" ... return int(self) ... If we try to save an instance of this type without first registering a type codec for it, we get an error: .. doctest:: >>> collection.insert_one({"num": DecimalInt("45.321")}) Traceback (most recent call last): ... bson.errors.InvalidDocument: cannot encode object: Decimal('45.321'), of type: In order to proceed further, we must define a type codec for ``DecimalInt``. This is trivial to do since the same transformation as the one used for ``Decimal`` is adequate for encoding ``DecimalInt`` as well: .. doctest:: >>> class DecimalIntCodec(DecimalCodec): ... @property ... def python_type(self): ... """The Python type acted upon by this type codec.""" ... return DecimalInt ... >>> decimalint_codec = DecimalIntCodec() .. note:: No attempt is made to modify decoding behavior because without additional information, it is impossible to discern which incoming :class:`~bson.decimal128.Decimal128` value needs to be decoded as ``Decimal`` and which needs to be decoded as ``DecimalInt``. This example only considers the situation where a user wants to *encode* documents containing either of these types. After creating a new codec options object and using it to get a collection object, we can seamlessly encode instances of ``DecimalInt``: .. doctest:: >>> type_registry = TypeRegistry([decimal_codec, decimalint_codec]) >>> codec_options = CodecOptions(type_registry=type_registry) >>> collection = db.get_collection("test", codec_options=codec_options) >>> collection.drop() >>> collection.insert_one({"num": DecimalInt("45.321")}) InsertOneResult(ObjectId('...'), acknowledged=True) >>> mydoc = collection.find_one() >>> pprint.pprint(mydoc) {'_id': ObjectId('...'), 'num': Decimal('45.321')} Note that the ``transform_bson`` method of the base codec class results in these values being decoded as ``Decimal`` (and not ``DecimalInt``). .. _decoding-binary-types: Decoding :class:`~bson.binary.Binary` Types ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ The decoding treatment of :class:`~bson.binary.Binary` types having ``subtype = 0`` by the :mod:`bson` module varies slightly depending on the version of the Python runtime in use. This must be taken into account while writing a ``TypeDecoder`` that modifies how this datatype is decoded. On Python 3.x, :class:`~bson.binary.Binary` data (``subtype = 0``) is decoded as a ``bytes`` instance: .. code-block:: pycon >>> # On Python 3.x. >>> from bson.binary import Binary >>> newcoll = db.get_collection("new") >>> newcoll.insert_one({"_id": 1, "data": Binary(b"123", subtype=0)}) >>> doc = newcoll.find_one() >>> type(doc["data"]) bytes On Python 2.7.x, the same data is decoded as a :class:`~bson.binary.Binary` instance: .. code-block:: pycon >>> # On Python 2.7.x >>> newcoll = db.get_collection("new") >>> doc = newcoll.find_one() >>> type(doc["data"]) bson.binary.Binary As a consequence of this disparity, users must set the ``bson_type`` attribute on their :class:`~bson.codec_options.TypeDecoder` classes differently, depending on the python version in use. .. note:: For codebases requiring compatibility with both Python 2 and 3, type decoders will have to be registered for both possible ``bson_type`` values. .. _fallback-encoder-callable: The ``fallback_encoder`` Callable --------------------------------- .. versionadded:: 3.8 In addition to type codecs, users can also register a callable to encode types that BSON doesn't recognize and for which no type codec has been registered. This callable is the **fallback encoder** and like the ``transform_python`` method, it accepts an unencodable value as a parameter and returns a BSON-encodable value. The following fallback encoder encodes python's :py:class:`~decimal.Decimal` type to a :class:`~bson.decimal128.Decimal128`: .. doctest:: >>> def fallback_encoder(value): ... if isinstance(value, Decimal): ... return Decimal128(value) ... return value ... After declaring the callback, we must create a type registry and codec options with this fallback encoder before it can be used for initializing a collection: .. doctest:: >>> type_registry = TypeRegistry(fallback_encoder=fallback_encoder) >>> codec_options = CodecOptions(type_registry=type_registry) >>> collection = db.get_collection("test", codec_options=codec_options) >>> collection.drop() We can now seamlessly encode instances of :py:class:`~decimal.Decimal`: .. doctest:: >>> collection.insert_one({"num": Decimal("45.321")}) InsertOneResult(ObjectId('...'), acknowledged=True) >>> mydoc = collection.find_one() >>> pprint.pprint(mydoc) {'_id': ObjectId('...'), 'num': Decimal128('45.321')} .. note:: Fallback encoders are invoked *after* attempts to encode the given value with standard BSON encoders and any configured type encoders have failed. Therefore, in a type registry configured with a type encoder and fallback encoder that both target the same custom type, the behavior specified in the type encoder will prevail. Because fallback encoders don't need to declare the types that they encode beforehand, they can be used to support interesting use-cases that cannot be serviced by ``TypeEncoder``. One such use-case is described in the next section. Encoding Unknown Types ^^^^^^^^^^^^^^^^^^^^^^ In this example, we demonstrate how a fallback encoder can be used to save arbitrary objects to the database. We will use the the standard library's :py:mod:`pickle` module to serialize the unknown types and so naturally, this approach only works for types that are picklable. We start by defining some arbitrary custom types: .. code-block:: python class MyStringType(object): def __init__(self, value): self.__value = value def __repr__(self): return "MyStringType('%s')" % (self.__value,) class MyNumberType(object): def __init__(self, value): self.__value = value def __repr__(self): return "MyNumberType(%s)" % (self.__value,) We also define a fallback encoder that pickles whatever objects it receives and returns them as :class:`~bson.binary.Binary` instances with a custom subtype. The custom subtype, in turn, allows us to write a TypeDecoder that identifies pickled artifacts upon retrieval and transparently decodes them back into Python objects: .. code-block:: python import pickle from bson.binary import Binary, USER_DEFINED_SUBTYPE def fallback_pickle_encoder(value): return Binary(pickle.dumps(value), USER_DEFINED_SUBTYPE) class PickledBinaryDecoder(TypeDecoder): bson_type = Binary def transform_bson(self, value): if value.subtype == USER_DEFINED_SUBTYPE: return pickle.loads(value) return value .. note:: The above example is written assuming the use of Python 3. If you are using Python 2, ``bson_type`` must be set to ``Binary``. See the :ref:`decoding-binary-types` section for a detailed explanation. Finally, we create a ``CodecOptions`` instance: .. code-block:: python codec_options = CodecOptions( type_registry=TypeRegistry( [PickledBinaryDecoder()], fallback_encoder=fallback_pickle_encoder ) ) We can now round trip our custom objects to MongoDB: .. code-block:: python collection = db.get_collection("test_fe", codec_options=codec_options) collection.insert_one( {"_id": 1, "str": MyStringType("hello world"), "num": MyNumberType(2)} ) mydoc = collection.find_one() assert isinstance(mydoc["str"], MyStringType) assert isinstance(mydoc["num"], MyNumberType) Limitations ----------- PyMongo's type codec and fallback encoder features have the following limitations: #. Users cannot customize the encoding behavior of Python types that PyMongo already understands like ``int`` and ``str`` (the 'built-in types'). Attempting to instantiate a type registry with one or more codecs that act upon a built-in type results in a ``TypeError``. This limitation extends to all subtypes of the standard types. #. Chaining type encoders is not supported. A custom type value, once transformed by a codec's ``transform_python`` method, *must* result in a type that is either BSON-encodable by default, or can be transformed by the fallback encoder into something BSON-encodable--it *cannot* be transformed a second time by a different type codec. #. The :meth:`~pymongo.database.Database.command` method does not apply the user's TypeDecoders while decoding the command response document. #. :mod:`gridfs` does not apply custom type encoding or decoding to any documents received from or to returned to the user. mongodb-mongo-python-driver-509e9b7/doc/examples/datetimes.rst000066400000000000000000000162301462766011000245330ustar00rootroot00000000000000Datetimes and Timezones ======================= .. testsetup:: import datetime from pymongo import MongoClient from bson.codec_options import CodecOptions client = MongoClient() client.drop_database("dt_example") db = client.dt_example These examples show how to handle Python :class:`datetime.datetime` objects correctly in PyMongo. Basic Usage ----------- PyMongo uses :class:`datetime.datetime` objects for representing dates and times in MongoDB documents. Because MongoDB assumes that dates and times are in UTC, care should be taken to ensure that dates and times written to the database reflect UTC. For example, the following code stores the current UTC date and time into MongoDB: .. doctest:: >>> result = db.objects.insert_one( ... {"last_modified": datetime.datetime.now(tz=datetime.timezone.utc)} ... ) Always use :meth:`datetime.datetime.now(tz=datetime.timezone.utc)`, which explicitly returns the current time in UTC, instead of :meth:`datetime.datetime.now`, with no arguments, which returns the current local time. Avoid doing this: .. doctest:: >>> result = db.objects.insert_one({"last_modified": datetime.datetime.now()}) The value for ``last_modified`` is very different between these two examples, even though both documents were stored at around the same local time. This will be confusing to the application that reads them: .. doctest:: >>> [doc["last_modified"] for doc in db.objects.find()] # doctest: +SKIP [datetime.datetime(2015, 7, 8, 18, 17, 28, 324000), datetime.datetime(2015, 7, 8, 11, 17, 42, 911000)] :class:`bson.codec_options.CodecOptions` has a ``tz_aware`` option that enables "aware" :class:`datetime.datetime` objects, i.e., datetimes that know what timezone they're in. By default, PyMongo retrieves naive datetimes: .. doctest:: >>> result = db.tzdemo.insert_one({"date": datetime.datetime(2002, 10, 27, 6, 0, 0)}) >>> db.tzdemo.find_one()["date"] datetime.datetime(2002, 10, 27, 6, 0) >>> options = CodecOptions(tz_aware=True) >>> db.get_collection("tzdemo", codec_options=options).find_one()["date"] # doctest: +SKIP datetime.datetime(2002, 10, 27, 6, 0, tzinfo=) Saving Datetimes with Timezones ------------------------------- When storing :class:`datetime.datetime` objects that specify a timezone (i.e. they have a ``tzinfo`` property that isn't ``None``), PyMongo will convert those datetimes to UTC automatically: .. doctest:: >>> import pytz >>> pacific = pytz.timezone("US/Pacific") >>> aware_datetime = pacific.localize(datetime.datetime(2002, 10, 27, 6, 0, 0)) >>> result = db.times.insert_one({"date": aware_datetime}) >>> db.times.find_one()["date"] datetime.datetime(2002, 10, 27, 14, 0) Reading Time ------------ As previously mentioned, by default all :class:`datetime.datetime` objects returned by PyMongo will be naive but reflect UTC (i.e. the time as stored in MongoDB). By setting the ``tz_aware`` option on :class:`~bson.codec_options.CodecOptions`, :class:`datetime.datetime` objects will be timezone-aware and have a ``tzinfo`` property that reflects the UTC timezone. PyMongo 3.1 introduced a ``tzinfo`` property that can be set on :class:`~bson.codec_options.CodecOptions` to convert :class:`datetime.datetime` objects to local time automatically. For example, if we wanted to read all times out of MongoDB in US/Pacific time: >>> from bson.codec_options import CodecOptions >>> db.times.find_one()['date'] datetime.datetime(2002, 10, 27, 14, 0) >>> aware_times = db.times.with_options(codec_options=CodecOptions( ... tz_aware=True, ... tzinfo=pytz.timezone('US/Pacific'))) >>> result = aware_times.find_one() datetime.datetime(2002, 10, 27, 6, 0, # doctest: +NORMALIZE_WHITESPACE tzinfo=) .. _handling-out-of-range-datetimes: Handling out of range datetimes ------------------------------- Python's :class:`~datetime.datetime` can only represent datetimes within the range allowed by :attr:`~datetime.datetime.min` and :attr:`~datetime.datetime.max`, whereas the range of datetimes allowed in BSON can represent any 64-bit number of milliseconds from the Unix epoch. To deal with this, we can use the :class:`bson.datetime_ms.DatetimeMS` object, which is a wrapper for the :class:`int` built-in. To decode UTC datetime values as :class:`~bson.datetime_ms.DatetimeMS`, :class:`~bson.codec_options.CodecOptions` should have its ``datetime_conversion`` parameter set to one of the options available in :class:`bson.datetime_ms.DatetimeConversion`. These include :attr:`~bson.datetime_ms.DatetimeConversion.DATETIME`, :attr:`~bson.datetime_ms.DatetimeConversion.DATETIME_MS`, :attr:`~bson.datetime_ms.DatetimeConversion.DATETIME_AUTO`, :attr:`~bson.datetime_ms.DatetimeConversion.DATETIME_CLAMP`. :attr:`~bson.datetime_ms.DatetimeConversion.DATETIME` is the default option and has the behavior of raising an :class:`~builtin.OverflowError` upon attempting to decode an out-of-range date. :attr:`~bson.datetime_ms.DatetimeConversion.DATETIME_MS` will only return :class:`~bson.datetime_ms.DatetimeMS` objects, regardless of whether the represented datetime is in- or out-of-range: .. doctest:: >>> from datetime import datetime >>> from bson import encode, decode >>> from bson.datetime_ms import DatetimeMS >>> from bson.codec_options import CodecOptions, DatetimeConversion >>> x = encode({"x": datetime(1970, 1, 1)}) >>> codec_ms = CodecOptions(datetime_conversion=DatetimeConversion.DATETIME_MS) >>> decode(x, codec_options=codec_ms) {'x': DatetimeMS(0)} :attr:`~bson.datetime_ms.DatetimeConversion.DATETIME_AUTO` will return :class:`~datetime.datetime` if the underlying UTC datetime is within range, or :class:`~bson.datetime_ms.DatetimeMS` if the underlying datetime cannot be represented using the builtin Python :class:`~datetime.datetime`: .. doctest:: >>> x = encode({"x": datetime(1970, 1, 1)}) >>> y = encode({"x": DatetimeMS(-(2**62))}) >>> codec_auto = CodecOptions(datetime_conversion=DatetimeConversion.DATETIME_AUTO) >>> decode(x, codec_options=codec_auto) {'x': datetime.datetime(1970, 1, 1, 0, 0)} >>> decode(y, codec_options=codec_auto) {'x': DatetimeMS(-4611686018427387904)} :attr:`~bson.datetime_ms.DatetimeConversion.DATETIME_CLAMP` will clamp resulting :class:`~datetime.datetime` objects to be within :attr:`~datetime.datetime.min` and :attr:`~datetime.datetime.max` (trimmed to ``999000`` microseconds): .. doctest:: >>> x = encode({"x": DatetimeMS(2**62)}) >>> y = encode({"x": DatetimeMS(-(2**62))}) >>> codec_clamp = CodecOptions(datetime_conversion=DatetimeConversion.DATETIME_CLAMP) >>> decode(x, codec_options=codec_clamp) {'x': datetime.datetime(9999, 12, 31, 23, 59, 59, 999000)} >>> decode(y, codec_options=codec_clamp) {'x': datetime.datetime(1, 1, 1, 0, 0)} :class:`~bson.datetime_ms.DatetimeMS` objects have support for rich comparison methods against other instances of :class:`~bson.datetime_ms.DatetimeMS`. They can also be converted to :class:`~datetime.datetime` objects with :meth:`~bson.datetime_ms.DatetimeMS.to_datetime()`. mongodb-mongo-python-driver-509e9b7/doc/examples/encryption.rst000066400000000000000000000760771462766011000247650ustar00rootroot00000000000000.. _In-Use Encryption: In-Use Encryption ================= .. _Client-Side Field Level Encryption: Client-Side Field Level Encryption ---------------------------------- New in MongoDB 4.2, client-side field level encryption allows an application to encrypt specific data fields in addition to pre-existing MongoDB encryption features such as `Encryption at Rest `_ and `TLS/SSL (Transport Encryption) `_. With field level encryption, applications can encrypt fields in documents *prior* to transmitting data over the wire to the server. Client-side field level encryption supports workloads where applications must guarantee that unauthorized parties, including server administrators, cannot read the encrypted data. .. seealso:: The MongoDB documentation on `Client Side Field Level Encryption `_. Dependencies ~~~~~~~~~~~~ To get started using client-side field level encryption in your project, you will need to install the `pymongocrypt `_ and `pymongo-auth-aws `_ libraries as well as the driver itself. Install both the driver and a compatible version of the dependencies like this:: $ python -m pip install 'pymongo[encryption]' Note that installing on Linux requires pip 19 or later for manylinux2010 wheel support. For more information about installing pymongocrypt see `the installation instructions on the project's PyPI page `_. Additionally, either `crypt_shared`_ or `mongocryptd`_ are required in order to use *automatic* client-side encryption. crypt_shared ```````````` The Automatic Encryption Shared Library (crypt_shared) provides the same functionality as `mongocryptd`_, but does not require you to spawn another process to perform automatic encryption. By default, pymongo attempts to load crypt_shared from the system and if found uses it automatically. To load crypt_shared from another location, use the ``crypt_shared_lib_path`` argument to :class:`~pymongo.encryption_options.AutoEncryptionOpts`. If pymongo cannot load crypt_shared it will attempt to fallback to using `mongocryptd`_ by default. Set ``crypt_shared_lib_required=True`` to make the app always use crypt_shared and fail if it could not be loaded. For detailed installation instructions see `the MongoDB documentation on Automatic Encryption Shared Library `_. mongocryptd ``````````` The ``mongocryptd`` binary is required for automatic client-side encryption and is included as a component in the `MongoDB Enterprise Server package `_. For detailed installation instructions see `the MongoDB documentation on mongocryptd `_. ``mongocryptd`` performs the following: - Parses the automatic encryption rules specified to the database connection. If the JSON schema contains invalid automatic encryption syntax or any document validation syntax, ``mongocryptd`` returns an error. - Uses the specified automatic encryption rules to mark fields in read and write operations for encryption. - Rejects read/write operations that may return unexpected or incorrect results when applied to an encrypted field. For supported and unsupported operations, see `Read/Write Support with Automatic Field Level Encryption `_. A MongoClient configured with auto encryption will automatically spawn the ``mongocryptd`` process from the application's ``PATH``. Applications can control the spawning behavior as part of the automatic encryption options. For example to set the path to the ``mongocryptd`` process:: auto_encryption_opts = AutoEncryptionOpts( ..., mongocryptd_spawn_path='/path/to/mongocryptd') To control the logging output of ``mongocryptd`` pass options using ``mongocryptd_spawn_args``:: auto_encryption_opts = AutoEncryptionOpts( ..., mongocryptd_spawn_args=['--logpath=/path/to/mongocryptd.log', '--logappend']) If your application wishes to manage the ``mongocryptd`` process manually, it is possible to disable spawning ``mongocryptd``:: auto_encryption_opts = AutoEncryptionOpts( ..., mongocryptd_bypass_spawn=True, # URI of the local ``mongocryptd`` process. mongocryptd_uri='mongodb://localhost:27020') ``mongocryptd`` is only responsible for supporting automatic client-side field level encryption and does not itself perform any encryption or decryption. .. _automatic-client-side-encryption: Automatic Client-Side Field Level Encryption ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Automatic client-side field level encryption is enabled by creating a :class:`~pymongo.mongo_client.MongoClient` with the ``auto_encryption_opts`` option set to an instance of :class:`~pymongo.encryption_options.AutoEncryptionOpts`. The following examples show how to setup automatic client-side field level encryption using :class:`~pymongo.encryption.ClientEncryption` to create a new encryption data key. .. note:: Automatic client-side field level encryption requires MongoDB >=4.2 enterprise or a MongoDB >=4.2 Atlas cluster. The community version of the server supports automatic decryption as well as :ref:`explicit-client-side-encryption`. Providing Local Automatic Encryption Rules `````````````````````````````````````````` The following example shows how to specify automatic encryption rules via the ``schema_map`` option. The automatic encryption rules are expressed using a `strict subset of the JSON Schema syntax `_. Supplying a ``schema_map`` provides more security than relying on JSON Schemas obtained from the server. It protects against a malicious server advertising a false JSON Schema, which could trick the client into sending unencrypted data that should be encrypted. JSON Schemas supplied in the ``schema_map`` only apply to configuring automatic client-side field level encryption. Other validation rules in the JSON schema will not be enforced by the driver and will result in an error. .. code-block:: python import os from bson.codec_options import CodecOptions from bson import json_util from pymongo import MongoClient from pymongo.encryption import Algorithm, ClientEncryption from pymongo.encryption_options import AutoEncryptionOpts def create_json_schema_file(kms_providers, key_vault_namespace, key_vault_client): client_encryption = ClientEncryption( kms_providers, key_vault_namespace, key_vault_client, # The CodecOptions class used for encrypting and decrypting. # This should be the same CodecOptions instance you have configured # on MongoClient, Database, or Collection. We will not be calling # encrypt() or decrypt() in this example so we can use any # CodecOptions. CodecOptions(), ) # Create a new data key and json schema for the encryptedField. # https://dochub.mongodb.org/core/client-side-field-level-encryption-automatic-encryption-rules data_key_id = client_encryption.create_data_key( "local", key_alt_names=["pymongo_encryption_example_1"] ) schema = { "properties": { "encryptedField": { "encrypt": { "keyId": [data_key_id], "bsonType": "string", "algorithm": Algorithm.AEAD_AES_256_CBC_HMAC_SHA_512_Deterministic, } } }, "bsonType": "object", } # Use CANONICAL_JSON_OPTIONS so that other drivers and tools will be # able to parse the MongoDB extended JSON file. json_schema_string = json_util.dumps( schema, json_options=json_util.CANONICAL_JSON_OPTIONS ) with open("jsonSchema.json", "w") as file: file.write(json_schema_string) def main(): # The MongoDB namespace (db.collection) used to store the # encrypted documents in this example. encrypted_namespace = "test.coll" # This must be the same master key that was used to create # the encryption key. local_master_key = os.urandom(96) kms_providers = {"local": {"key": local_master_key}} # The MongoDB namespace (db.collection) used to store # the encryption data keys. key_vault_namespace = "encryption.__pymongoTestKeyVault" key_vault_db_name, key_vault_coll_name = key_vault_namespace.split(".", 1) # The MongoClient used to access the key vault (key_vault_namespace). key_vault_client = MongoClient() key_vault = key_vault_client[key_vault_db_name][key_vault_coll_name] # Ensure that two data keys cannot share the same keyAltName. key_vault.drop() key_vault.create_index( "keyAltNames", unique=True, partialFilterExpression={"keyAltNames": {"$exists": True}}, ) create_json_schema_file(kms_providers, key_vault_namespace, key_vault_client) # Load the JSON Schema and construct the local schema_map option. with open("jsonSchema.json", "r") as file: json_schema_string = file.read() json_schema = json_util.loads(json_schema_string) schema_map = {encrypted_namespace: json_schema} auto_encryption_opts = AutoEncryptionOpts( kms_providers, key_vault_namespace, schema_map=schema_map ) client = MongoClient(auto_encryption_opts=auto_encryption_opts) db_name, coll_name = encrypted_namespace.split(".", 1) coll = client[db_name][coll_name] # Clear old data coll.drop() coll.insert_one({"encryptedField": "123456789"}) print("Decrypted document: %s" % (coll.find_one(),)) unencrypted_coll = MongoClient()[db_name][coll_name] print("Encrypted document: %s" % (unencrypted_coll.find_one(),)) if __name__ == "__main__": main() Server-Side Field Level Encryption Enforcement `````````````````````````````````````````````` MongoDB >=4.2 servers supports using schema validation to enforce encryption of specific fields in a collection. This schema validation will prevent an application from inserting unencrypted values for any fields marked with the ``"encrypt"`` JSON schema keyword. The following example shows how to setup automatic client-side field level encryption using :class:`~pymongo.encryption.ClientEncryption` to create a new encryption data key and create a collection with the `Automatic Encryption JSON Schema Syntax `_: .. code-block:: python import os from bson.codec_options import CodecOptions from bson.binary import STANDARD from pymongo import MongoClient from pymongo.encryption import Algorithm, ClientEncryption from pymongo.encryption_options import AutoEncryptionOpts from pymongo.errors import OperationFailure from pymongo.write_concern import WriteConcern def main(): # The MongoDB namespace (db.collection) used to store the # encrypted documents in this example. encrypted_namespace = "test.coll" # This must be the same master key that was used to create # the encryption key. local_master_key = os.urandom(96) kms_providers = {"local": {"key": local_master_key}} # The MongoDB namespace (db.collection) used to store # the encryption data keys. key_vault_namespace = "encryption.__pymongoTestKeyVault" key_vault_db_name, key_vault_coll_name = key_vault_namespace.split(".", 1) # The MongoClient used to access the key vault (key_vault_namespace). key_vault_client = MongoClient() key_vault = key_vault_client[key_vault_db_name][key_vault_coll_name] # Ensure that two data keys cannot share the same keyAltName. key_vault.drop() key_vault.create_index( "keyAltNames", unique=True, partialFilterExpression={"keyAltNames": {"$exists": True}}, ) client_encryption = ClientEncryption( kms_providers, key_vault_namespace, key_vault_client, # The CodecOptions class used for encrypting and decrypting. # This should be the same CodecOptions instance you have configured # on MongoClient, Database, or Collection. We will not be calling # encrypt() or decrypt() in this example so we can use any # CodecOptions. CodecOptions(), ) # Create a new data key and json schema for the encryptedField. data_key_id = client_encryption.create_data_key( "local", key_alt_names=["pymongo_encryption_example_2"] ) json_schema = { "properties": { "encryptedField": { "encrypt": { "keyId": [data_key_id], "bsonType": "string", "algorithm": Algorithm.AEAD_AES_256_CBC_HMAC_SHA_512_Deterministic, } } }, "bsonType": "object", } auto_encryption_opts = AutoEncryptionOpts(kms_providers, key_vault_namespace) client = MongoClient(auto_encryption_opts=auto_encryption_opts) db_name, coll_name = encrypted_namespace.split(".", 1) db = client[db_name] # Clear old data db.drop_collection(coll_name) # Create the collection with the encryption JSON Schema. db.create_collection( coll_name, # uuid_representation=STANDARD is required to ensure that any # UUIDs in the $jsonSchema document are encoded to BSON Binary # with the standard UUID subtype 4. This is only needed when # running the "create" collection command with an encryption # JSON Schema. codec_options=CodecOptions(uuid_representation=STANDARD), write_concern=WriteConcern(w="majority"), validator={"$jsonSchema": json_schema}, ) coll = client[db_name][coll_name] coll.insert_one({"encryptedField": "123456789"}) print("Decrypted document: %s" % (coll.find_one(),)) unencrypted_coll = MongoClient()[db_name][coll_name] print("Encrypted document: %s" % (unencrypted_coll.find_one(),)) try: unencrypted_coll.insert_one({"encryptedField": "123456789"}) except OperationFailure as exc: print("Unencrypted insert failed: %s" % (exc.details,)) if __name__ == "__main__": main() .. _explicit-client-side-encryption: Explicit Encryption ~~~~~~~~~~~~~~~~~~~ Explicit encryption is a MongoDB community feature and does not use the ``mongocryptd`` process. Explicit encryption is provided by the :class:`~pymongo.encryption.ClientEncryption` class, for example: .. code-block:: python import os from pymongo import MongoClient from pymongo.encryption import Algorithm, ClientEncryption def main(): # This must be the same master key that was used to create # the encryption key. local_master_key = os.urandom(96) kms_providers = {"local": {"key": local_master_key}} # The MongoDB namespace (db.collection) used to store # the encryption data keys. key_vault_namespace = "encryption.__pymongoTestKeyVault" key_vault_db_name, key_vault_coll_name = key_vault_namespace.split(".", 1) # The MongoClient used to read/write application data. client = MongoClient() coll = client.test.coll # Clear old data coll.drop() # Set up the key vault (key_vault_namespace) for this example. key_vault = client[key_vault_db_name][key_vault_coll_name] # Ensure that two data keys cannot share the same keyAltName. key_vault.drop() key_vault.create_index( "keyAltNames", unique=True, partialFilterExpression={"keyAltNames": {"$exists": True}}, ) client_encryption = ClientEncryption( kms_providers, key_vault_namespace, # The MongoClient to use for reading/writing to the key vault. # This can be the same MongoClient used by the main application. client, # The CodecOptions class used for encrypting and decrypting. # This should be the same CodecOptions instance you have configured # on MongoClient, Database, or Collection. coll.codec_options, ) # Create a new data key for the encryptedField. data_key_id = client_encryption.create_data_key( "local", key_alt_names=["pymongo_encryption_example_3"] ) # Explicitly encrypt a field: encrypted_field = client_encryption.encrypt( "123456789", Algorithm.AEAD_AES_256_CBC_HMAC_SHA_512_Deterministic, key_id=data_key_id, ) coll.insert_one({"encryptedField": encrypted_field}) doc = coll.find_one() print("Encrypted document: %s" % (doc,)) # Explicitly decrypt the field: doc["encryptedField"] = client_encryption.decrypt(doc["encryptedField"]) print("Decrypted document: %s" % (doc,)) # Cleanup resources. client_encryption.close() client.close() if __name__ == "__main__": main() Explicit Encryption with Automatic Decryption ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Although automatic encryption requires MongoDB >=4.2 enterprise or a MongoDB >=4.2 Atlas cluster, automatic *decryption* is supported for all users. To configure automatic *decryption* without automatic *encryption* set ``bypass_auto_encryption=True`` in :class:`~pymongo.encryption_options.AutoEncryptionOpts`: .. code-block:: python import os from pymongo import MongoClient from pymongo.encryption import Algorithm, ClientEncryption from pymongo.encryption_options import AutoEncryptionOpts def main(): # This must be the same master key that was used to create # the encryption key. local_master_key = os.urandom(96) kms_providers = {"local": {"key": local_master_key}} # The MongoDB namespace (db.collection) used to store # the encryption data keys. key_vault_namespace = "encryption.__pymongoTestKeyVault" key_vault_db_name, key_vault_coll_name = key_vault_namespace.split(".", 1) # bypass_auto_encryption=True disable automatic encryption but keeps # the automatic _decryption_ behavior. bypass_auto_encryption will # also disable spawning mongocryptd. auto_encryption_opts = AutoEncryptionOpts( kms_providers, key_vault_namespace, bypass_auto_encryption=True ) client = MongoClient(auto_encryption_opts=auto_encryption_opts) coll = client.test.coll # Clear old data coll.drop() # Set up the key vault (key_vault_namespace) for this example. key_vault = client[key_vault_db_name][key_vault_coll_name] # Ensure that two data keys cannot share the same keyAltName. key_vault.drop() key_vault.create_index( "keyAltNames", unique=True, partialFilterExpression={"keyAltNames": {"$exists": True}}, ) client_encryption = ClientEncryption( kms_providers, key_vault_namespace, # The MongoClient to use for reading/writing to the key vault. # This can be the same MongoClient used by the main application. client, # The CodecOptions class used for encrypting and decrypting. # This should be the same CodecOptions instance you have configured # on MongoClient, Database, or Collection. coll.codec_options, ) # Create a new data key for the encryptedField. data_key_id = client_encryption.create_data_key( "local", key_alt_names=["pymongo_encryption_example_4"] ) # Explicitly encrypt a field: encrypted_field = client_encryption.encrypt( "123456789", Algorithm.AEAD_AES_256_CBC_HMAC_SHA_512_Deterministic, key_alt_name="pymongo_encryption_example_4", ) coll.insert_one({"encryptedField": encrypted_field}) # Automatically decrypts any encrypted fields. doc = coll.find_one() print("Decrypted document: %s" % (doc,)) unencrypted_coll = MongoClient().test.coll print("Encrypted document: %s" % (unencrypted_coll.find_one(),)) # Cleanup resources. client_encryption.close() client.close() if __name__ == "__main__": main() .. _CSFLE on-demand credentials: CSFLE on-demand credentials ~~~~~~~~~~~~~~~~~~~~~~~~~~~ ``pymongocrypt`` 1.4 adds support for fetching on-demand KMS credentials for AWS, GCP, and Azure cloud environments. To enable the driver's behavior to obtain credentials from the environment, add the appropriate key ("aws", "gcp", or "azure") with an empty map to "kms_providers" in either :class:`~pymongo.encryption_options.AutoEncryptionOpts` or :class:`~pymongo.encryption.ClientEncryption` options. An application using AWS credentials would look like: .. code-block:: python from pymongo import MongoClient from pymongo.encryption import ClientEncryption client = MongoClient() client_encryption = ClientEncryption( # The empty dictionary enables on-demand credentials. kms_providers={"aws": {}}, key_vault_namespace="keyvault.datakeys", key_vault_client=client, codec_options=client.codec_options, ) master_key = { "region": "us-east-1", "key": ("arn:aws:kms:us-east-1:123456789:key/89fcc2c4-08b0-4bd9-9f25-e30687b580d0"), } client_encryption.create_data_key("aws", master_key) The above will enable the same behavior of obtaining AWS credentials from the environment as is used for :ref:`MONGODB-AWS` authentication, including the caching to avoid rate limiting. An application using GCP credentials would look like: .. code-block:: python from pymongo import MongoClient from pymongo.encryption import ClientEncryption client = MongoClient() client_encryption = ClientEncryption( # The empty dictionary enables on-demand credentials. kms_providers={"gcp": {}}, key_vault_namespace="keyvault.datakeys", key_vault_client=client, codec_options=client.codec_options, ) master_key = { "projectId": "my-project", "location": "global", "keyRing": "key-ring-csfle", "keyName": "key-name-csfle", } client_encryption.create_data_key("gcp", master_key) The driver will query the `VM instance metadata `_ to obtain credentials. An application using Azure credentials would look like, this time using :class:`~pymongo.encryption_options.AutoEncryptionOpts`: .. code-block:: python from pymongo import MongoClient from pymongo.encryption_options import AutoEncryptionOpts # The empty dictionary enables on-demand credentials. kms_providers = ({"azure": {}},) key_vault_namespace = "keyvault.datakeys" auto_encryption_opts = AutoEncryptionOpts(kms_providers, key_vault_namespace) client = MongoClient(auto_encryption_opts=auto_encryption_opts) coll = client.test.coll coll.insert_one({"encryptedField": "123456789"}) The driver will `acquire an access token `_ from the Azure VM. .. _Queryable Encryption: Queryable Encryption -------------------- .. _automatic-queryable-client-side-encryption: Automatic Queryable Encryption ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Automatic Queryable Encryption requires MongoDB 7.0+ Enterprise or a MongoDB 7.0+ Atlas cluster. Queryable Encryption is the second version of Client-Side Field Level Encryption. Data is encrypted client-side. Queryable Encryption supports indexed encrypted fields, which are further processed server-side. Automatic encryption in Queryable Encryption is configured with an ``encrypted_fields`` mapping, as demonstrated by the following example: .. code-block:: python import os from bson.codec_options import CodecOptions from pymongo import MongoClient from pymongo.encryption import Algorithm, ClientEncryption, QueryType from pymongo.encryption_options import AutoEncryptionOpts local_master_key = os.urandom(96) kms_providers = {"local": {"key": local_master_key}} key_vault_namespace = "keyvault.datakeys" key_vault_client = MongoClient() client_encryption = ClientEncryption( kms_providers, key_vault_namespace, key_vault_client, CodecOptions() ) key_vault = key_vault_client["keyvault"]["datakeys"] key_vault.drop() # Ensure that two data keys cannot share the same keyAltName. key_vault.create_index( "keyAltNames", unique=True, partialFilterExpression={"keyAltNames": {"$exists": True}}, ) key1_id = client_encryption.create_data_key("local", key_alt_names=["firstName"]) key2_id = client_encryption.create_data_key("local", key_alt_names=["lastName"]) encrypted_fields_map = { "default.encryptedCollection": { "escCollection": "encryptedCollection.esc", "ecocCollection": "encryptedCollection.ecoc", "fields": [ { "path": "firstName", "bsonType": "string", "keyId": key1_id, "queries": [{"queryType": "equality"}], }, { "path": "lastName", "bsonType": "string", "keyId": key2_id, }, ], } } auto_encryption_opts = AutoEncryptionOpts( kms_providers, key_vault_namespace, encrypted_fields_map=encrypted_fields_map, ) client = MongoClient(auto_encryption_opts=auto_encryption_opts) client.default.drop_collection("encryptedCollection") coll = client.default.create_collection("encryptedCollection") coll.insert_one({"_id": 1, "firstName": "Jane", "lastName": "Doe"}) docs = list(coll.find({"firstName": "Jane"})) print(docs) In the above example, the ``firstName`` and ``lastName`` fields are automatically encrypted and decrypted. Explicit Queryable Encryption ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Explicit Queryable Encryption requires MongoDB 7.0+. Queryable Encryption is the second version of Client-Side Field Level Encryption. Data is encrypted client-side. Queryable Encryption supports indexed encrypted fields, which are further processed server-side. Explicit encryption in Queryable Encryption is performed using the ``encrypt`` and ``decrypt`` methods. Automatic encryption (to allow the ``find_one`` to automatically decrypt) is configured using an ``encrypted_fields`` mapping, as demonstrated by the following example: .. code-block:: python import os from pymongo import MongoClient from pymongo.encryption import ( Algorithm, AutoEncryptionOpts, ClientEncryption, QueryType, ) def main(): # This must be the same master key that was used to create # the encryption key. local_master_key = os.urandom(96) kms_providers = {"local": {"key": local_master_key}} # The MongoDB namespace (db.collection) used to store # the encryption data keys. key_vault_namespace = "encryption.__pymongoTestKeyVault" key_vault_db_name, key_vault_coll_name = key_vault_namespace.split(".", 1) # Set up the key vault (key_vault_namespace) for this example. client = MongoClient() key_vault = client[key_vault_db_name][key_vault_coll_name] # Ensure that two data keys cannot share the same keyAltName. key_vault.drop() key_vault.create_index( "keyAltNames", unique=True, partialFilterExpression={"keyAltNames": {"$exists": True}}, ) client_encryption = ClientEncryption( kms_providers, key_vault_namespace, # The MongoClient to use for reading/writing to the key vault. # This can be the same MongoClient used by the main application. client, # The CodecOptions class used for encrypting and decrypting. # This should be the same CodecOptions instance you have configured # on MongoClient, Database, or Collection. client.codec_options, ) # Create a new data key for the encryptedField. indexed_key_id = client_encryption.create_data_key("local") unindexed_key_id = client_encryption.create_data_key("local") encrypted_fields = { "escCollection": "enxcol_.default.esc", "ecocCollection": "enxcol_.default.ecoc", "fields": [ { "keyId": indexed_key_id, "path": "encryptedIndexed", "bsonType": "string", "queries": {"queryType": "equality"}, }, { "keyId": unindexed_key_id, "path": "encryptedUnindexed", "bsonType": "string", }, ], } opts = AutoEncryptionOpts( {"local": {"key": local_master_key}}, key_vault.full_name, bypass_query_analysis=True, key_vault_client=client, ) # The MongoClient used to read/write application data. encrypted_client = MongoClient(auto_encryption_opts=opts) encrypted_client.drop_database("test") db = encrypted_client.test # Create the collection with encrypted fields. coll = db.create_collection("coll", encryptedFields=encrypted_fields) # Create and encrypt an indexed and unindexed value. val = "encrypted indexed value" unindexed_val = "encrypted unindexed value" insert_payload_indexed = client_encryption.encrypt( val, Algorithm.INDEXED, indexed_key_id, contention_factor=1 ) insert_payload_unindexed = client_encryption.encrypt( unindexed_val, Algorithm.UNINDEXED, unindexed_key_id ) # Insert the payloads. coll.insert_one( { "encryptedIndexed": insert_payload_indexed, "encryptedUnindexed": insert_payload_unindexed, } ) # Encrypt our find payload using QueryType.EQUALITY. # The value of "indexed_key_id" must be the same as used to encrypt # the values above. find_payload = client_encryption.encrypt( val, Algorithm.INDEXED, indexed_key_id, query_type=QueryType.EQUALITY, contention_factor=1, ) # Find the document we inserted using the encrypted payload. # The returned document is automatically decrypted. doc = coll.find_one({"encryptedIndexed": find_payload}) print("Returned document: %s" % (doc,)) # Cleanup resources. client_encryption.close() encrypted_client.close() client.close() if __name__ == "__main__": main() mongodb-mongo-python-driver-509e9b7/doc/examples/geo.rst000066400000000000000000000063131462766011000233270ustar00rootroot00000000000000Geospatial Indexing Example =========================== .. testsetup:: from pymongo import MongoClient client = MongoClient() client.drop_database("geo_example") This example shows how to create and use a :data:`~pymongo.GEO2D` index in PyMongo. To create a spherical (earth-like) geospatial index use :data:`~pymongo.GEOSPHERE` instead. .. seealso:: The MongoDB documentation on `Geospatial Indexes `_. Creating a Geospatial Index --------------------------- Creating a geospatial index in pymongo is easy: .. doctest:: >>> from pymongo import MongoClient, GEO2D >>> db = MongoClient().geo_example >>> db.places.create_index([("loc", GEO2D)]) 'loc_2d' Inserting Places ---------------- Locations in MongoDB are represented using either embedded documents or lists where the first two elements are coordinates. Here, we'll insert a couple of example locations: .. doctest:: >>> result = db.places.insert_many( ... [{"loc": [2, 5]}, {"loc": [30, 5]}, {"loc": [1, 2]}, {"loc": [4, 4]}] ... ) >>> result.inserted_ids [ObjectId('...'), ObjectId('...'), ObjectId('...'), ObjectId('...')] .. note:: If specifying latitude and longitude coordinates in :data:`~pymongo.GEOSPHERE`, list the **longitude** first and then **latitude**. Querying -------- Using the geospatial index we can find documents near another point: .. doctest:: >>> import pprint >>> for doc in db.places.find({"loc": {"$near": [3, 6]}}).limit(3): ... pprint.pprint(doc) ... {'_id': ObjectId('...'), 'loc': [2, 5]} {'_id': ObjectId('...'), 'loc': [4, 4]} {'_id': ObjectId('...'), 'loc': [1, 2]} .. note:: If using :data:`pymongo.GEOSPHERE`, using $nearSphere is recommended. The $maxDistance operator requires the use of :class:`~bson.son.SON`: .. doctest:: >>> from bson.son import SON >>> query = {"loc": SON([("$near", [3, 6]), ("$maxDistance", 100)])} >>> for doc in db.places.find(query).limit(3): ... pprint.pprint(doc) ... {'_id': ObjectId('...'), 'loc': [2, 5]} {'_id': ObjectId('...'), 'loc': [4, 4]} {'_id': ObjectId('...'), 'loc': [1, 2]} It's also possible to query for all items within a given rectangle (specified by lower-left and upper-right coordinates): .. doctest:: >>> query = {"loc": {"$within": {"$box": [[2, 2], [5, 6]]}}} >>> for doc in db.places.find(query).sort("_id"): ... pprint.pprint(doc) ... {'_id': ObjectId('...'), 'loc': [2, 5]} {'_id': ObjectId('...'), 'loc': [4, 4]} Or circle (specified by center point and radius): .. doctest:: >>> query = {"loc": {"$within": {"$center": [[0, 0], 6]}}} >>> for doc in db.places.find(query).sort("_id"): ... pprint.pprint(doc) ... {'_id': ObjectId('...'), 'loc': [2, 5]} {'_id': ObjectId('...'), 'loc': [1, 2]} {'_id': ObjectId('...'), 'loc': [4, 4]} geoNear queries are also supported using :class:`~bson.son.SON`:: >>> from bson.son import SON >>> db.command(SON([('geoNear', 'places'), ('near', [1, 2])])) {'ok': 1.0, 'stats': ...} .. warning:: Starting in MongoDB version 4.0, MongoDB deprecates the **geoNear** command. Use one of the following operations instead. * $geoNear - aggregation stage. * $near - query operator. * $nearSphere - query operator. mongodb-mongo-python-driver-509e9b7/doc/examples/gevent.rst000066400000000000000000000036451462766011000240520ustar00rootroot00000000000000Gevent ====== PyMongo supports `Gevent `_. Simply call Gevent's ``monkey.patch_all()`` before loading any other modules: .. code-block:: pycon >>> # You must call patch_all() *before* importing any other modules >>> from gevent import monkey >>> _ = monkey.patch_all() >>> from pymongo import MongoClient >>> client = MongoClient() PyMongo uses thread and socket functions from the Python standard library. Gevent's monkey-patching replaces those standard functions so that PyMongo does asynchronous I/O with non-blocking sockets, and schedules operations on greenlets instead of threads. Avoid blocking in Hub.join -------------------------- By default, PyMongo uses threads to discover and monitor your servers' topology (see :ref:`health-monitoring`). If you execute ``monkey.patch_all()`` when your application first begins, PyMongo automatically uses greenlets instead of threads. When shutting down, if your application calls :meth:`~gevent.hub.Hub.join` on Gevent's :class:`~gevent.hub.Hub` without first terminating these background greenlets, the call to :meth:`~gevent.hub.Hub.join` blocks indefinitely. You therefore **must close or dereference** any active :class:`~pymongo.mongo_client.MongoClient` before exiting. An example solution to this issue in some application frameworks is a signal handler to end background greenlets when your application receives SIGHUP: .. code-block:: python import signal def graceful_reload(signum, traceback): """Explicitly close some global MongoClient object.""" client.close() signal.signal(signal.SIGHUP, graceful_reload) Applications using uWSGI prior to 1.9.16 are affected by this issue, or newer uWSGI versions with the ``-gevent-wait-for-hub`` option. See `the uWSGI changelog for details `_. mongodb-mongo-python-driver-509e9b7/doc/examples/gridfs.rst000066400000000000000000000043741462766011000240400ustar00rootroot00000000000000GridFS Example ============== .. testsetup:: from pymongo import MongoClient client = MongoClient() client.drop_database("gridfs_example") This example shows how to use :mod:`gridfs` to store large binary objects (e.g. files) in MongoDB. .. seealso:: The API docs for :mod:`gridfs`. .. seealso:: `This blog post `_ for some motivation behind this API. Setup ----- We start by creating a :class:`~gridfs.GridFS` instance to use: .. doctest:: >>> from pymongo import MongoClient >>> import gridfs >>> >>> db = MongoClient().gridfs_example >>> fs = gridfs.GridFS(db) Every :class:`~gridfs.GridFS` instance is created with and will operate on a specific :class:`~pymongo.database.Database` instance. Saving and Retrieving Data -------------------------- The simplest way to work with :mod:`gridfs` is to use its key/value interface (the :meth:`~gridfs.GridFS.put` and :meth:`~gridfs.GridFS.get` methods). To write data to GridFS, use :meth:`~gridfs.GridFS.put`: .. doctest:: >>> a = fs.put(b"hello world") :meth:`~gridfs.GridFS.put` creates a new file in GridFS, and returns the value of the file document's ``"_id"`` key. Given that ``"_id"`` we can use :meth:`~gridfs.GridFS.get` to get back the contents of the file: .. doctest:: >>> fs.get(a).read() b'hello world' :meth:`~gridfs.GridFS.get` returns a file-like object, so we get the file's contents by calling :meth:`~gridfs.grid_file.GridOut.read`. In addition to putting a :class:`str` as a GridFS file, we can also put any file-like object (an object with a :meth:`read` method). GridFS will handle reading the file in chunk-sized segments automatically. We can also add additional attributes to the file as keyword arguments: .. doctest:: >>> b = fs.put(fs.get(a), filename="foo", bar="baz") >>> out = fs.get(b) >>> out.read() b'hello world' >>> out.filename 'foo' >>> out.bar 'baz' >>> out.upload_date datetime.datetime(...) The attributes we set in :meth:`~gridfs.GridFS.put` are stored in the file document, and retrievable after calling :meth:`~gridfs.GridFS.get`. Some attributes (like ``"filename"``) are special and are defined in the GridFS specification - see that document for more details. mongodb-mongo-python-driver-509e9b7/doc/examples/high_availability.rst000066400000000000000000000345751462766011000262410ustar00rootroot00000000000000High Availability and PyMongo ============================= PyMongo makes it easy to write highly available applications whether you use a `single replica set `_ or a `large sharded cluster `_. Connecting to a Replica Set --------------------------- PyMongo makes working with `replica sets `_ easy. Here we'll launch a new replica set and show how to handle both initialization and normal connections with PyMongo. .. seealso:: The MongoDB documentation on `replication `_. Starting a Replica Set ~~~~~~~~~~~~~~~~~~~~~~ The main `replica set documentation `_ contains extensive information about setting up a new replica set or migrating an existing MongoDB setup, be sure to check that out. Here, we'll just do the bare minimum to get a three node replica set setup locally. .. warning:: Replica sets should always use multiple nodes in production - putting all set members on the same physical node is only recommended for testing and development. We start three ``mongod`` processes, each on a different port and with a different dbpath, but all using the same replica set name "foo". .. code-block:: bash $ mkdir -p /data/db0 /data/db1 /data/db2 $ mongod --port 27017 --dbpath /data/db0 --replSet foo .. code-block:: bash $ mongod --port 27018 --dbpath /data/db1 --replSet foo .. code-block:: bash $ mongod --port 27019 --dbpath /data/db2 --replSet foo Initializing the Set ~~~~~~~~~~~~~~~~~~~~ At this point all of our nodes are up and running, but the set has yet to be initialized. Until the set is initialized no node will become the primary, and things are essentially "offline". To initialize the set we need to connect directly to a single node and run the initiate command using the ``directConnection`` option:: >>> from pymongo import MongoClient >>> c = MongoClient('localhost', 27017, directConnection=True) .. note:: We could have connected to any of the other nodes instead, but only the node we initiate from is allowed to contain any initial data. After connecting, we run the initiate command to get things started:: >>> config = {'_id': 'foo', 'members': [ ... {'_id': 0, 'host': 'localhost:27017'}, ... {'_id': 1, 'host': 'localhost:27018'}, ... {'_id': 2, 'host': 'localhost:27019'}]} >>> c.admin.command("replSetInitiate", config) {'ok': 1.0, ...} The three ``mongod`` servers we started earlier will now coordinate and come online as a replica set. Connecting to a Replica Set ~~~~~~~~~~~~~~~~~~~~~~~~~~~ The initial connection as made above is a special case for an uninitialized replica set. Normally we'll want to connect differently. A connection to a replica set can be made using the :meth:`~pymongo.mongo_client.MongoClient` constructor, specifying one or more members of the set and optionally the replica set name. Any of the following connects to the replica set we just created:: >>> MongoClient('localhost') MongoClient(host=['localhost:27017'], ...) >>> MongoClient('localhost', replicaset='foo') MongoClient(host=['localhost:27017'], replicaset='foo', ...) >>> MongoClient('localhost:27018', replicaset='foo') MongoClient(['localhost:27018'], replicaset='foo', ...) >>> MongoClient('localhost', 27019, replicaset='foo') MongoClient(['localhost:27019'], replicaset='foo', ...) >>> MongoClient('mongodb://localhost:27017,localhost:27018/') MongoClient(['localhost:27017', 'localhost:27018'], ...) >>> MongoClient('mongodb://localhost:27017,localhost:27018/?replicaSet=foo') MongoClient(['localhost:27017', 'localhost:27018'], replicaset='foo', ...) The addresses passed to :meth:`~pymongo.mongo_client.MongoClient` are called the *seeds*. As long as at least one of the seeds is online, MongoClient discovers all the members in the replica set, and determines which is the current primary and which are secondaries or arbiters. Each seed must be the address of a single mongod. Multihomed and round robin DNS addresses are **not** supported. The :class:`~pymongo.mongo_client.MongoClient` constructor is non-blocking: the constructor returns immediately while the client connects to the replica set using background threads. Note how, if you create a client and immediately print the string representation of its :attr:`~pymongo.mongo_client.MongoClient.nodes` attribute, the list may be empty initially. If you wait a moment, MongoClient discovers the whole replica set:: >>> from time import sleep >>> c = MongoClient(replicaset='foo'); print(c.nodes); sleep(0.1); print(c.nodes) frozenset([]) frozenset([('localhost', 27019), ('localhost', 27017), ('localhost', 27018)]) You need not wait for replica set discovery in your application, however. If you need to do any operation with a MongoClient, such as a :meth:`~pymongo.collection.Collection.find` or an :meth:`~pymongo.collection.Collection.insert_one`, the client waits to discover a suitable member before it attempts the operation. Handling Failover ~~~~~~~~~~~~~~~~~ When a failover occurs, PyMongo will automatically attempt to find the new primary node and perform subsequent operations on that node. This can't happen completely transparently, however. Here we'll perform an example failover to illustrate how everything behaves. First, we'll connect to the replica set and perform a couple of basic operations:: >>> db = MongoClient("localhost", replicaSet='foo').test >>> db.test.insert_one({"x": 1}).inserted_id ObjectId('...') >>> db.test.find_one() {'x': 1, '_id': ObjectId('...')} By checking the host and port, we can see that we're connected to *localhost:27017*, which is the current primary:: >>> db.client.address ('localhost', 27017) Now let's bring down that node and see what happens when we run our query again:: >>> db.test.find_one() Traceback (most recent call last): pymongo.errors.AutoReconnect: ... We get an :class:`~pymongo.errors.AutoReconnect` exception. This means that the driver was not able to connect to the old primary (which makes sense, as we killed the server), but that it will attempt to automatically reconnect on subsequent operations. When this exception is raised our application code needs to decide whether to retry the operation or to simply continue, accepting the fact that the operation might have failed. On subsequent attempts to run the query we might continue to see this exception. Eventually, however, the replica set will failover and elect a new primary (this should take no more than a couple of seconds in general). At that point the driver will connect to the new primary and the operation will succeed:: >>> db.test.find_one() {'x': 1, '_id': ObjectId('...')} >>> db.client.address ('localhost', 27018) Bring the former primary back up. It will rejoin the set as a secondary. Now we can move to the next section: distributing reads to secondaries. .. _secondary-reads: Secondary Reads ~~~~~~~~~~~~~~~ By default an instance of MongoClient sends queries to the primary member of the replica set. To use secondaries for queries we have to change the read preference:: >>> client = MongoClient( ... 'localhost:27017', ... replicaSet='foo', ... readPreference='secondaryPreferred') >>> client.read_preference SecondaryPreferred(tag_sets=None) Now all queries will be sent to the secondary members of the set. If there are no secondary members the primary will be used as a fallback. If you have queries you would prefer to never send to the primary you can specify that using the ``secondary`` read preference. By default the read preference of a :class:`~pymongo.database.Database` is inherited from its MongoClient, and the read preference of a :class:`~pymongo.collection.Collection` is inherited from its Database. To use a different read preference use the :meth:`~pymongo.mongo_client.MongoClient.get_database` method, or the :meth:`~pymongo.database.Database.get_collection` method:: >>> from pymongo import ReadPreference >>> client.read_preference SecondaryPreferred(tag_sets=None) >>> db = client.get_database('test', read_preference=ReadPreference.SECONDARY) >>> db.read_preference Secondary(tag_sets=None) >>> coll = db.get_collection('test', read_preference=ReadPreference.PRIMARY) >>> coll.read_preference Primary() You can also change the read preference of an existing :class:`~pymongo.collection.Collection` with the :meth:`~pymongo.collection.Collection.with_options` method:: >>> coll2 = coll.with_options(read_preference=ReadPreference.NEAREST) >>> coll.read_preference Primary() >>> coll2.read_preference Nearest(tag_sets=None) Note that since most database commands can only be sent to the primary of a replica set, the :meth:`~pymongo.database.Database.command` method does not obey the Database's :attr:`~pymongo.database.Database.read_preference`, but you can pass an explicit read preference to the method:: >>> db.command('dbstats', read_preference=ReadPreference.NEAREST) {...} Reads are configured using three options: **read preference**, **tag sets**, and **local threshold**. **Read preference**: Read preference is configured using one of the classes from :mod:`~pymongo.read_preferences` (:class:`~pymongo.read_preferences.Primary`, :class:`~pymongo.read_preferences.PrimaryPreferred`, :class:`~pymongo.read_preferences.Secondary`, :class:`~pymongo.read_preferences.SecondaryPreferred`, or :class:`~pymongo.read_preferences.Nearest`). For convenience, we also provide :class:`~pymongo.read_preferences.ReadPreference` with the following attributes: - ``PRIMARY``: Read from the primary. This is the default read preference, and provides the strongest consistency. If no primary is available, raise :class:`~pymongo.errors.AutoReconnect`. - ``PRIMARY_PREFERRED``: Read from the primary if available, otherwise read from a secondary. - ``SECONDARY``: Read from a secondary. If no matching secondary is available, raise :class:`~pymongo.errors.AutoReconnect`. - ``SECONDARY_PREFERRED``: Read from a secondary if available, otherwise from the primary. - ``NEAREST``: Read from any available member. **Tag sets**: Replica-set members can be `tagged `_ according to any criteria you choose. By default, PyMongo ignores tags when choosing a member to read from, but your read preference can be configured with a ``tag_sets`` parameter. ``tag_sets`` must be a list of dictionaries, each dict providing tag values that the replica set member must match. PyMongo tries each set of tags in turn until it finds a set of tags with at least one matching member. For example, to prefer reads from the New York data center, but fall back to the San Francisco data center, tag your replica set members according to their location and create a MongoClient like so:: >>> from pymongo.read_preferences import Secondary >>> db = client.get_database( ... 'test', read_preference=Secondary([{'dc': 'ny'}, {'dc': 'sf'}])) >>> db.read_preference Secondary(tag_sets=[{'dc': 'ny'}, {'dc': 'sf'}]) MongoClient tries to find secondaries in New York, then San Francisco, and raises :class:`~pymongo.errors.AutoReconnect` if none are available. As an additional fallback, specify a final, empty tag set, ``{}``, which means "read from any member that matches the mode, ignoring tags." See :mod:`~pymongo.read_preferences` for more information. .. _distributes reads to secondaries: **Local threshold**: If multiple members match the read preference and tag sets, PyMongo reads from among the nearest members, chosen according to ping time. By default, only members whose ping times are within 15 milliseconds of the nearest are used for queries. You can choose to distribute reads among members with higher latencies by setting ``localThresholdMS`` to a larger number:: >>> client = pymongo.MongoClient( ... replicaSet='repl0', ... readPreference='secondaryPreferred', ... localThresholdMS=35) In this case, PyMongo distributes reads among matching members within 35 milliseconds of the closest member's ping time. .. note:: ``localThresholdMS`` is ignored when talking to a replica set *through* a mongos. The equivalent is the localThreshold_ command line option. .. _localThreshold: https://mongodb.com/docs/manual/reference/program/mongos/#std-option-mongos.--localThreshold .. _health-monitoring: Health Monitoring ''''''''''''''''' When MongoClient is initialized it launches background threads to monitor the replica set for changes in: * Health: detect when a member goes down or comes up, or if a different member becomes primary * Configuration: detect when members are added or removed, and detect changes in members' tags * Latency: track a moving average of each member's ping time Replica-set monitoring ensures queries are continually routed to the proper members as the state of the replica set changes. .. _mongos-load-balancing: mongos Load Balancing --------------------- An instance of :class:`~pymongo.mongo_client.MongoClient` can be configured with a list of addresses of mongos servers: >>> client = MongoClient('mongodb://host1,host2,host3') Each member of the list must be a single mongos server. Multihomed and round robin DNS addresses are **not** supported. The client continuously monitors all the mongoses' availability, and its network latency to each. PyMongo distributes operations evenly among the set of mongoses within its ``localThresholdMS`` (similar to how it `distributes reads to secondaries`_ in a replica set). By default the threshold is 15 ms. The lowest-latency server, and all servers with latencies no more than ``localThresholdMS`` beyond the lowest-latency server's, receive operations equally. For example, if we have three mongoses: - host1: 20 ms - host2: 35 ms - host3: 40 ms By default the ``localThresholdMS`` is 15 ms, so PyMongo uses host1 and host2 evenly. It uses host1 because its network latency to the driver is shortest. It uses host2 because its latency is within 15 ms of the lowest-latency server's. But it excuses host3: host3 is 20ms beyond the lowest-latency server. If we set ``localThresholdMS`` to 30 ms all servers are within the threshold: >>> client = MongoClient('mongodb://host1,host2,host3/?localThresholdMS=30') .. warning:: Do **not** connect PyMongo to a pool of mongos instances through a load balancer. A single socket connection must always be routed to the same mongos instance for proper cursor support. mongodb-mongo-python-driver-509e9b7/doc/examples/index.rst000066400000000000000000000013361462766011000236640ustar00rootroot00000000000000Examples ======== The examples in this section are intended to give in depth overviews of how to accomplish specific tasks with MongoDB and PyMongo. Unless otherwise noted, all examples assume that a MongoDB instance is running on the default host and port. Assuming you have `downloaded and installed `_ MongoDB, you can start it like so: .. code-block:: bash $ mongod .. toctree:: :maxdepth: 1 aggregation authentication collations copydb custom_type bulk datetimes geo gevent gridfs high_availability logging mod_wsgi network_compression server_selection tailable timeouts tls type_hints encryption uuid mongodb-mongo-python-driver-509e9b7/doc/examples/logging.rst000066400000000000000000000101031462766011000241730ustar00rootroot00000000000000Logging ======== Starting in 4.8, **PyMongo** supports `Python's native logging library `_, enabling developers to customize the verbosity of log messages for their applications. Components ------------- There are currently three different **PyMongo** components with logging support: ``pymongo.command``, ``pymongo.connection``, and ``pymongo.serverSelection``. These components deal with command operations, connection management, and server selection, respectively. Each can be configured separately or they can all be configured together. Configuration ------------- Currently, the above components each support ``DEBUG`` logging. To enable a single component, do the following:: import logging logging.getLogger('pymongo.').setLevel(logging.DEBUG) For example, to enable command logging:: import logging logging.getLogger('pymongo.command').setLevel(logging.DEBUG) You can also enable all ``DEBUG`` logs at once:: import logging logging.getLogger('pymongo').setLevel(logging.DEBUG) Truncation ------------- When ``pymongo.command`` debug logs are enabled, every command sent to the server and every response sent back will be included as part of the logs. By default, these command and response documents are truncated after 1000 bytes. You can configure a higher truncation limit by setting the ``MONGOB_LOG_MAX_DOCUMENT_LENGTH`` environment variable to your desired length. Note that by default, only sensitive authentication command contents are redacted. All commands containing user data will be logged, including the actual contents of your queries. To prevent this behavior, set ``MONGOB_LOG_MAX_DOCUMENT_LENGTH`` to 0. This will omit the command and response bodies from the logs. Example ------------- Here's a simple example that enables ``pymongo.command`` debug logs and performs two database operations:: import logging import pymongo # Automatically writes all logs to stdout logging.basicConfig() logging.getLogger('pymongo.command').setLevel(logging.DEBUG) client = pymongo.MongoClient() client.db.test.insert_one({"x": 1}) client.db.test.find_one({"x": 1}) --------------------------------- DEBUG:pymongo.command:{"clientId": {"$oid": "65cbe82614be1fc2beb4e4a9"}, "message": "Command started", "command": "{\"insert\": \"test\", \"ordered\": true, \"lsid\": {\"id\": {\"$binary\": {\"base64\": \"GI7ubVhPSsWd7+OwHEFx6Q==\", \"subType\": \"04\"}}}, \"$db\": \"db\", \"documents\": [{\"x\": 1, \"_id\": {\"$oid\": \"65cbe82614be1fc2beb4e4aa\"}}]}", "commandName": "insert", "databaseName": "db", "requestId": 1144108930, "operationId": 1144108930, "driverConnectionId": 1, "serverConnectionId": 3554, "serverHost": "localhost", "serverPort": 27017} DEBUG:pymongo.command:{"clientId": {"$oid": "65cbe82614be1fc2beb4e4a9"}, "message": "Command succeeded", "durationMS": 0.515, "reply": "{\"n\": 1, \"ok\": 1.0}", "commandName": "insert", "databaseName": "db", "requestId": 1144108930, "operationId": 1144108930, "driverConnectionId": 1, "serverConnectionId": 3554, "serverHost": "localhost", "serverPort": 27017} DEBUG:pymongo.command:{"clientId": {"$oid": "65cbe82614be1fc2beb4e4a9"}, "message": "Command started", "command": "{\"find\": \"test\", \"filter\": {\"x\": 1}, \"limit\": 1, \"singleBatch\": true, \"lsid\": {\"id\": {\"$binary\": {\"base64\": \"GI7ubVhPSsWd7+OwHEFx6Q==\", \"subType\": \"04\"}}}, \"$db\": \"db\"}", "commandName": "find", "databaseName": "db", "requestId": 470211272, "operationId": 470211272, "driverConnectionId": 1, "serverConnectionId": 3554, "serverHost": "localhost", "serverPort": 27017} DEBUG:pymongo.command:{"clientId": {"$oid": "65cbe82614be1fc2beb4e4a9"}, "message": "Command succeeded", "durationMS": 0.621, "reply": "{\"cursor\": {\"firstBatch\": [{\"_id\": {\"$oid\": \"65cbdf391a957ed280001417\"}, \"x\": 1}], \"ns\": \"db.test\"}, \"ok\": 1.0}", "commandName": "find", "databaseName": "db", "requestId": 470211272, "operationId": 470211272, "driverConnectionId": 1, "serverConnectionId": 3554, "serverHost": "localhost", "serverPort": 27017} mongodb-mongo-python-driver-509e9b7/doc/examples/mod_wsgi.rst000066400000000000000000000051411462766011000243630ustar00rootroot00000000000000.. _pymongo-and-mod_wsgi: PyMongo and mod_wsgi ==================== To run your application under `mod_wsgi `_, follow these guidelines: * Run ``mod_wsgi`` in daemon mode with the ``WSGIDaemonProcess`` directive. * Assign each application to a separate daemon with ``WSGIProcessGroup``. * Use ``WSGIApplicationGroup %{GLOBAL}`` to ensure your application is running in the daemon's main Python interpreter, not a sub interpreter. For example, this ``mod_wsgi`` configuration ensures an application runs in the main interpreter:: WSGIDaemonProcess my_process WSGIScriptAlias /my_app /path/to/app.wsgi WSGIProcessGroup my_process WSGIApplicationGroup %{GLOBAL} If you have multiple applications that use PyMongo, put each in a separate daemon, still in the global application group:: WSGIDaemonProcess my_process WSGIScriptAlias /my_app /path/to/app.wsgi WSGIProcessGroup my_process WSGIDaemonProcess my_other_process WSGIScriptAlias /my_other_app /path/to/other_app.wsgi WSGIProcessGroup my_other_process WSGIApplicationGroup %{GLOBAL} Background: ``mod_wsgi`` can run in "embedded" mode when only WSGIScriptAlias is set, or "daemon" mode with WSGIDaemonProcess. In daemon mode, ``mod_wsgi`` can run your application in the Python main interpreter, or in sub interpreters. The correct way to run a PyMongo application is in daemon mode, using the main interpreter. Python C extensions in general have issues running in multiple Python sub interpreters. These difficulties are explained in the documentation for `Py_NewInterpreter `_ and in the `Multiple Python Sub Interpreters `_ section of the ``mod_wsgi`` documentation. Beginning with PyMongo 2.7, the C extension for BSON detects when it is running in a sub interpreter and activates a workaround, which adds a small cost to BSON decoding. To avoid this cost, use ``WSGIApplicationGroup %{GLOBAL}`` to ensure your application runs in the main interpreter. Since your program runs in the main interpreter it should not share its process with any other applications, lest they interfere with each other's state. Each application should have its own daemon process, as shown in the example above. mongodb-mongo-python-driver-509e9b7/doc/examples/network_compression.rst000066400000000000000000000031641462766011000266700ustar00rootroot00000000000000 .. _network-compression-example: Network Compression =================== PyMongo supports network compression where network traffic between the client and MongoDB server are compressed which reduces the amount of data passed over the network. By default no compression is used. The driver supports the following algorithms: - `snappy `_ available in MongoDB 3.4 and later. - :mod:`zlib` available in MongoDB 3.6 and later. - `zstandard `_ available in MongoDB 4.2 and later. .. note:: snappy and zstandard compression require additional dependencies. See :ref:`optional-deps`. Applications can enable wire protocol compression via the ``compressors`` URI and keyword argument to :meth:`~pymongo.mongo_client.MongoClient`. For example:: >>> client = MongoClient(compressors='zlib') When multiple compression algorithms are given, the driver selects the first one in the list supported by the MongoDB instance to which it is connected. For example:: >>> client = MongoClient(compressors='snappy,zstandard,zlib') The ``compressors`` option can also be set via the URI:: >>> client = MongoClient('mongodb://example.com/?compressors=snappy,zstandard,zlib') Additionally, zlib compression allows specifying a compression level with supported values from -1 to 9:: >>> client = MongoClient(compressors='zlib', zlibCompressionLevel=-1) The ``zlibCompressionLevel`` is passed as the ``level`` argument to :func:`zlib.compress`. .. seealso:: The MongoDB documentation on `network compression URI options `_. mongodb-mongo-python-driver-509e9b7/doc/examples/server_selection.rst000066400000000000000000000077241462766011000261370ustar00rootroot00000000000000Server Selector Example ======================= Users can exert fine-grained control over the `server selection algorithm`_ by setting the ``server_selector`` option on the :class:`~pymongo.MongoClient` to an appropriate callable. This example shows how to use this functionality to prefer servers running on ``localhost``. .. warning:: Use of custom server selector functions is a power user feature. Misusing custom server selectors can have unintended consequences such as degraded read/write performance. .. testsetup:: from pymongo import MongoClient .. _server selection algorithm: https://mongodb.com/docs/manual/core/read-preference-mechanics/ Example: Selecting Servers Running on ``localhost`` --------------------------------------------------- To start, we need to write the server selector function that will be used. The server selector function should accept a list of :class:`~pymongo.server_description.ServerDescription` objects and return a list of server descriptions that are suitable for the read or write operation. A server selector must not create or modify :class:`~pymongo.server_description.ServerDescription` objects, and must return the selected instances unchanged. In this example, we write a server selector that prioritizes servers running on ``localhost``. This can be desirable when using a sharded cluster with multiple ``mongos``, as locally run queries are likely to see lower latency and higher throughput. Please note, however, that it is highly dependent on the application if preferring ``localhost`` is beneficial or not. In addition to comparing the hostname with ``localhost``, our server selector function accounts for the edge case when no servers are running on ``localhost``. In this case, we allow the default server selection logic to prevail by passing through the received server description list unchanged. Failure to do this would render the client unable to communicate with MongoDB in the event that no servers were running on ``localhost``. The described server selection logic is implemented in the following server selector function: .. doctest:: >>> def server_selector(server_descriptions): ... servers = [ ... server for server in server_descriptions if server.address[0] == "localhost" ... ] ... if not servers: ... return server_descriptions ... return servers ... Finally, we can create a :class:`~pymongo.MongoClient` instance with this server selector. .. doctest:: >>> client = MongoClient(server_selector=server_selector) Server Selection Process ------------------------ This section dives deeper into the server selection process for reads and writes. In the case of a write, the driver performs the following operations (in order) during the selection process: #. Select all writeable servers from the list of known hosts. For a replica set this is the primary, while for a sharded cluster this is all the known mongoses. #. Apply the user-defined server selector function. Note that the custom server selector is **not** called if there are no servers left from the previous filtering stage. #. Apply the ``localThresholdMS`` setting to the list of remaining hosts. This whittles the host list down to only contain servers whose latency is at most ``localThresholdMS`` milliseconds higher than the lowest observed latency. #. Select a server at random from the remaining host list. The desired operation is then performed against the selected server. In the case of **reads** the process is identical except for the first step. Here, instead of selecting all writeable servers, we select all servers matching the user's :class:`~pymongo.read_preferences.ReadPreference` from the list of known hosts. As an example, for a 3-member replica set with a :class:`~pymongo.read_preferences.Secondary` read preference, we would select all available secondaries. .. _server selection algorithm: https://mongodb.com/docs/manual/core/read-preference-mechanics/ mongodb-mongo-python-driver-509e9b7/doc/examples/tailable.rst000066400000000000000000000033121462766011000243260ustar00rootroot00000000000000Tailable Cursors ================ By default, MongoDB will automatically close a cursor when the client has exhausted all results in the cursor. However, for `capped collections `_ you may use a `tailable cursor `_ that remains open after the client exhausts the results in the initial cursor. The following is a basic example of using a tailable cursor to tail the oplog of a replica set member:: import time import pymongo client = pymongo.MongoClient() oplog = client.local.oplog.rs first = oplog.find().sort('$natural', pymongo.ASCENDING).limit(-1).next() print(first) ts = first['ts'] while True: # For a regular capped collection CursorType.TAILABLE_AWAIT is the # only option required to create a tailable cursor. When querying the # oplog, the oplog_replay option enables an optimization to quickly # find the 'ts' value we're looking for. The oplog_replay option # can only be used when querying the oplog. Starting in MongoDB 4.4 # this option is ignored by the server as queries against the oplog # are optimized automatically by the MongoDB query engine. cursor = oplog.find({'ts': {'$gt': ts}}, cursor_type=pymongo.CursorType.TAILABLE_AWAIT, oplog_replay=True) while cursor.alive: for doc in cursor: ts = doc['ts'] print(doc) # We end up here if the find() returned no documents or if the # tailable cursor timed out (no new documents were added to the # collection for more than 1 second). time.sleep(1) mongodb-mongo-python-driver-509e9b7/doc/examples/timeouts.rst000066400000000000000000000156171462766011000244350ustar00rootroot00000000000000 .. _timeout-example: Client Side Operation Timeout ============================= PyMongo 4.2 introduced :meth:`~pymongo.timeout` and the ``timeoutMS`` URI and keyword argument to :class:`~pymongo.mongo_client.MongoClient`. These features allow applications to more easily limit the amount of time that one or more operations can execute before control is returned to the app. This timeout applies to all of the work done to execute the operation, including but not limited to server selection, connection checkout, serialization, and server-side execution. Basic Usage ----------- The following example uses :meth:`~pymongo.timeout` to configure a 10-second timeout for an :meth:`~pymongo.collection.Collection.insert_one` operation:: import pymongo with pymongo.timeout(10): coll.insert_one({"name": "Nunu"}) The :meth:`~pymongo.timeout` applies to all pymongo operations within the block. The following example ensures that both the ``insert`` and the ``find`` complete within 10 seconds total, or raise a timeout error:: with pymongo.timeout(10): coll.insert_one({"name": "Nunu"}) coll.find_one({"name": "Nunu"}) When nesting :func:`~pymongo.timeout`, the nested deadline is capped by the outer deadline. The deadline can only be shortened, not extended. When exiting the block, the previous deadline is restored:: with pymongo.timeout(5): coll.find_one() # Uses the 5 second deadline. with pymongo.timeout(3): coll.find_one() # Uses the 3 second deadline. coll.find_one() # Uses the original 5 second deadline. with pymongo.timeout(10): coll.find_one() # Still uses the original 5 second deadline. coll.find_one() # Uses the original 5 second deadline. Timeout errors -------------- When the :meth:`~pymongo.timeout` with-statement is entered, a deadline is set for the entire block. When that deadline is exceeded, any blocking pymongo operation will raise a timeout exception. For example:: try: with pymongo.timeout(10): coll.insert_one({"name": "Nunu"}) time.sleep(10) # The deadline has now expired, the next operation will raise # a timeout exception. coll.find_one({"name": "Nunu"}) except PyMongoError as exc: if exc.timeout: print(f"block timed out: {exc!r}") else: print(f"failed with non-timeout error: {exc!r}") The :attr:`pymongo.errors.PyMongoError.timeout` property (added in PyMongo 4.2) will be ``True`` when the error was caused by a timeout and ``False`` otherwise. The timeoutMS URI option ------------------------ PyMongo 4.2 also added support for the ``timeoutMS`` URI and keyword argument to :class:`~pymongo.mongo_client.MongoClient`. When this option is configured, the client will automatically apply the timeout to each API call. For example:: client = MongoClient("mongodb://localhost/?timeoutMS=10000") coll = client.test.test coll.insert_one({"name": "Nunu"}) # Uses a 10-second timeout. coll.find_one({"name": "Nunu"}) # Also uses a 10-second timeout. The above is roughly equivalent to:: client = MongoClient() coll = client.test.test with pymongo.timeout(10): coll.insert_one({"name": "Nunu"}) with pymongo.timeout(10): coll.find_one({"name": "Nunu"}) pymongo.timeout overrides timeoutMS ----------------------------------- :meth:`~pymongo.timeout` overrides ``timeoutMS``; within a :meth:`~pymongo.timeout` block a client's ``timeoutMS`` option is ignored:: client = MongoClient("mongodb://localhost/?timeoutMS=10000") coll = client.test.test coll.insert_one({"name": "Nunu"}) # Uses the client's 10-second timeout. # pymongo.timeout overrides the client's timeoutMS. with pymongo.timeout(20): coll.insert_one({"name": "Nunu"}) # Uses the 20-second timeout. with pymongo.timeout(5): coll.find_one({"name": "Nunu"}) # Uses the 5-second timeout. pymongo.timeout is thread safe ------------------------------ :meth:`~pymongo.timeout` is thread safe; the timeout only applies to current thread and multiple threads can configure different timeouts in parallel. pymongo.timeout is asyncio safe ------------------------------- :meth:`~pymongo.timeout` is asyncio safe; the timeout only applies to current Task and multiple Tasks can configure different timeouts concurrently. :meth:`~pymongo.timeout` can be used identically in `Motor `_, for example:: import motor.motor_asyncio client = motor.motor_asyncio.AsyncIOMotorClient() coll = client.test.test with pymongo.timeout(10): await coll.insert_one({"name": "Nunu"}) await coll.find_one({"name": "Nunu"}) Troubleshooting --------------- There are many timeout errors that can be raised depending on when the timeout expires. In code, these can be identified with the :attr:`pymongo.errors.PyMongoError.timeout` property. Some specific timeout errors examples are described below. When the client was unable to find an available server to run the operation within the given timeout:: pymongo.errors.ServerSelectionTimeoutError: No servers found yet, Timeout: -0.00202266700216569s, Topology Description: ]> When either the client was unable to establish a connection within the given timeout or the operation was sent but the server was not able to respond in time:: pymongo.errors.NetworkTimeout: localhost:27017: timed out When the server cancelled the operation because it exceeded the given timeout. Note that the operation may have partially completed on the server (depending on the operation):: pymongo.errors.ExecutionTimeout: operation exceeded time limit, full error: {'ok': 0.0, 'errmsg': 'operation exceeded time limit', 'code': 50, 'codeName': 'MaxTimeMSExpired'} When the client cancelled the operation because it was not possible to complete within the given timeout:: pymongo.errors.ExecutionTimeout: operation would exceed time limit, remaining timeout:0.00196 <= network round trip time:0.00427 When the client attempted a write operation but the server could not replicate that write (according to the configured write concern) within the given timeout:: pymongo.errors.WTimeoutError: operation exceeded time limit, full error: {'code': 50, 'codeName': 'MaxTimeMSExpired', 'errmsg': 'operation exceeded time limit', 'errInfo': {'writeConcern': {'w': 1, 'wtimeout': 0}}} The same error as above but for :meth:`~pymongo.collection.Collection.insert_many` or :meth:`~pymongo.collection.Collection.bulk_write`:: pymongo.errors.BulkWriteError: batch op errors occurred, full error: {'writeErrors': [], 'writeConcernErrors': [{'code': 50, 'codeName': 'MaxTimeMSExpired', 'errmsg': 'operation exceeded time limit', 'errInfo': {'writeConcern': {'w': 1, 'wtimeout': 0}}}], 'nInserted': 2, 'nUpserted': 0, 'nMatched': 0, 'nModified': 0, 'nRemoved': 0, 'upserted': []} mongodb-mongo-python-driver-509e9b7/doc/examples/tls.rst000066400000000000000000000224701462766011000233610ustar00rootroot00000000000000TLS/SSL and PyMongo =================== PyMongo supports connecting to MongoDB over TLS/SSL. This guide covers the configuration options supported by PyMongo. See `the server documentation `_ to configure MongoDB. .. warning:: Industry best practices recommend, and some regulations require, the use of TLS 1.1 or newer. Though no application changes are required for PyMongo to make use of the newest protocols, some operating systems or versions may not provide an OpenSSL version new enough to support them. Users of macOS older than 10.13 (High Sierra) will need to install Python from `python.org`_, `homebrew`_, `macports`_, or another similar source. Users of Linux or other non-macOS Unix can check their OpenSSL version like this:: $ openssl version If the version number is less than 1.0.1 support for TLS 1.1 or newer is not available. Contact your operating system vendor for a solution or upgrade to a newer distribution. You can check your Python interpreter by installing the `requests`_ module and executing the following command:: python -c "import requests; print(requests.get('https://www.howsmyssl.com/a/check', verify=False).json()['tls_version'])" You should see "TLS 1.X" where X is >= 1. You can read more about TLS versions and their security implications here: ``_ .. _python.org: https://www.python.org/downloads/ .. _homebrew: https://brew.sh/ .. _macports: https://www.macports.org/ .. _requests: https://pypi.python.org/pypi/requests Basic configuration ................... In many cases connecting to MongoDB over TLS/SSL requires nothing more than passing ``tls=True`` as a keyword argument to :class:`~pymongo.mongo_client.MongoClient`:: >>> client = pymongo.MongoClient('example.com', tls=True) Or passing ``tls=true`` in the URI:: >>> client = pymongo.MongoClient('mongodb://example.com/?tls=true') This configures PyMongo to connect to the server using TLS, verify the server's certificate and verify that the host you are attempting to connect to is listed by that certificate. Certificate verification policy ............................... By default, PyMongo is configured to require a certificate from the server when TLS is enabled. This is configurable using the ``tlsAllowInvalidCertificates`` option. To disable this requirement pass ``tlsAllowInvalidCertificates=True`` as a keyword parameter:: >>> client = pymongo.MongoClient('example.com', ... tls=True, ... tlsAllowInvalidCertificates=True) Or, in the URI:: >>> uri = 'mongodb://example.com/?tls=true&tlsAllowInvalidCertificates=true' >>> client = pymongo.MongoClient(uri) Specifying a CA file .................... In some cases you may want to configure PyMongo to use a specific set of CA certificates. This is most often the case when you are acting as your own certificate authority rather than using server certificates signed by a well known authority. The ``tlsCAFile`` option takes a path to a CA file. It can be passed as a keyword argument:: >>> client = pymongo.MongoClient('example.com', ... tls=True, ... tlsCAFile='/path/to/ca.pem') Or, in the URI:: >>> uri = 'mongodb://example.com/?tls=true&tlsCAFile=/path/to/ca.pem' >>> client = pymongo.MongoClient(uri) Specifying a certificate revocation list ........................................ The ``tlsCRLFile`` option takes a path to a CRL file. It can be passed as a keyword argument:: >>> client = pymongo.MongoClient('example.com', ... tls=True, ... tlsCRLFile='/path/to/crl.pem') Or, in the URI:: >>> uri = 'mongodb://example.com/?tls=true&tlsCRLFile=/path/to/crl.pem' >>> client = pymongo.MongoClient(uri) .. note:: Certificate revocation lists and :ref:`OCSP` cannot be used together. Client certificates ................... PyMongo can be configured to present a client certificate using the ``tlsCertificateKeyFile`` option:: >>> client = pymongo.MongoClient('example.com', ... tls=True, ... tlsCertificateKeyFile='/path/to/client.pem') If the private key for the client certificate is stored in a separate file, it should be concatenated with the certificate file. For example, to concatenate a PEM-formatted certificate file ``cert.pem`` and a PEM-formatted keyfile ``key.pem`` into a single file ``combined.pem``, on Unix systems, users can run:: $ cat key.pem cert.pem > combined.pem PyMongo can be configured with the concatenated certificate keyfile using the ``tlsCertificateKeyFile`` option:: >>> client = pymongo.MongoClient('example.com', ... tls=True, ... tlsCertificateKeyFile='/path/to/combined.pem') If the private key contained in the certificate keyfile is encrypted, users can provide a password or passphrase to decrypt the encrypted private keys using the ``tlsCertificateKeyFilePassword`` option:: >>> client = pymongo.MongoClient('example.com', ... tls=True, ... tlsCertificateKeyFile='/path/to/combined.pem', ... tlsCertificateKeyFilePassword=) These options can also be passed as part of the MongoDB URI. .. _OCSP: OCSP .... Starting with PyMongo 3.11, if PyMongo was installed with the "ocsp" extra:: python -m pip install pymongo[ocsp] certificate revocation checking is enabled by way of `OCSP (Online Certification Status Protocol) `_. MongoDB 4.4+ `staples OCSP responses `_ to the TLS handshake which PyMongo will verify, failing the TLS handshake if the stapled OCSP response is invalid or indicates that the peer certificate is revoked. When connecting to a server version older than 4.4, or when a 4.4+ version of MongoDB does not staple an OCSP response, PyMongo will attempt to connect directly to an OCSP endpoint if the peer certificate specified one. The TLS handshake will only fail in this case if the response indicates that the certificate is revoked. Invalid or malformed responses will be ignored, favoring availability over maximum security. .. _TLSErrors: Troubleshooting TLS Errors .......................... TLS errors often fall into three categories - certificate verification failure, protocol version mismatch or certificate revocation checking failure. An error message similar to the following means that OpenSSL was not able to verify the server's certificate:: [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed This often occurs because OpenSSL does not have access to the system's root certificates or the certificates are out of date. Linux users should ensure that they have the latest root certificate updates installed from their Linux vendor. macOS users using Python 3.7 or newer downloaded from python.org `may have to run a script included with python `_ to install root certificates:: open "/Applications/Python /Install Certificates.command" Users of older PyPy portable versions may have to `set an environment variable `_ to tell OpenSSL where to find root certificates. This is easily done using the `certifi module `_ from pypi:: $ pypy -m pip install certifi $ export SSL_CERT_FILE=$(pypy -c "import certifi; print(certifi.where())") An error message similar to the following message means that the OpenSSL version used by Python does not support a new enough TLS protocol to connect to the server:: [SSL: TLSV1_ALERT_PROTOCOL_VERSION] tlsv1 alert protocol version Industry best practices recommend, and some regulations require, that older TLS protocols be disabled in some MongoDB deployments. Some deployments may disable TLS 1.0, others may disable TLS 1.0 and TLS 1.1. See the warning earlier in this document for troubleshooting steps and solutions. An error message similar to the following message means that certificate revocation checking failed:: [('SSL routines', 'tls_process_initial_server_flight', 'invalid status response')] See :ref:`OCSP` for more details. Python 3.10+ incompatibilities with TLS/SSL on MongoDB <= 4.0 ............................................................. Note that `changes made to the ssl module in Python 3.10+ `_ may cause incompatibilities with MongoDB <= 4.0. The following are some example errors that may occur with this combination:: SSL handshake failed: localhost:27017: [SSL: SSLV3_ALERT_HANDSHAKE_FAILURE] sslv3 alert handshake failure (_ssl.c:997) SSL handshake failed: localhost:27017: EOF occurred in violation of protocol (_ssl.c:997) The MongoDB server logs may show the following error:: 2021-06-30T21:22:44.917+0100 E NETWORK [conn16] SSL: error:1408A0C1:SSL routines:ssl3_get_client_hello:no shared cipher To resolve this issue, use Python <=3.10, upgrade to MongoDB 4.2+, or install pymongo with the :ref:`OCSP` extra which relies on PyOpenSSL. mongodb-mongo-python-driver-509e9b7/doc/examples/type_hints.rst000066400000000000000000000311471462766011000247460ustar00rootroot00000000000000 .. _type_hints-example: Type Hints ========== As of version 4.1, PyMongo ships with `type hints`_. With type hints, Python type checkers can easily find bugs before they reveal themselves in your code. If your IDE is configured to use type hints, it can suggest more appropriate completions and highlight errors in your code. Some examples include `PyCharm`_, `Sublime Text`_, and `Visual Studio Code`_. You can also use the `mypy`_ tool from your command line or in Continuous Integration tests. All of the public APIs in PyMongo are fully type hinted, and several of them support generic parameters for the type of document object returned when decoding BSON documents. Due to `limitations in mypy`_, the default values for generic document types are not yet provided (they will eventually be ``Dict[str, any]``). For a larger set of examples that use types, see the PyMongo `test_typing module`_. If you would like to opt out of using the provided types, add the following to your `mypy config`_: :: [mypy-pymongo] follow_imports = False Basic Usage ----------- Note that a type for :class:`~pymongo.mongo_client.MongoClient` must be specified. Here we use the default, unspecified document type: .. doctest:: >>> from pymongo import MongoClient >>> client: MongoClient = MongoClient() >>> collection = client.test.test >>> inserted = collection.insert_one({"x": 1, "tags": ["dog", "cat"]}) >>> retrieved = collection.find_one({"x": 1}) >>> assert isinstance(retrieved, dict) For a more accurate typing for document type you can use: .. doctest:: >>> from typing import Any, Dict >>> from pymongo import MongoClient >>> client: MongoClient[Dict[str, Any]] = MongoClient() >>> collection = client.test.test >>> inserted = collection.insert_one({"x": 1, "tags": ["dog", "cat"]}) >>> retrieved = collection.find_one({"x": 1}) >>> assert isinstance(retrieved, dict) Typed Client ------------ :class:`~pymongo.mongo_client.MongoClient` is generic on the document type used to decode BSON documents. You can specify a :class:`~bson.raw_bson.RawBSONDocument` document type: .. doctest:: >>> from pymongo import MongoClient >>> from bson.raw_bson import RawBSONDocument >>> client = MongoClient(document_class=RawBSONDocument) >>> collection = client.test.test >>> inserted = collection.insert_one({"x": 1, "tags": ["dog", "cat"]}) >>> result = collection.find_one({"x": 1}) >>> assert isinstance(result, RawBSONDocument) Subclasses of :py:class:`collections.abc.Mapping` can also be used, such as :class:`~bson.son.SON`: .. doctest:: >>> from bson import SON >>> from pymongo import MongoClient >>> client = MongoClient(document_class=SON[str, int]) >>> collection = client.test.test >>> inserted = collection.insert_one({"x": 1, "y": 2}) >>> result = collection.find_one({"x": 1}) >>> assert result is not None >>> assert result["x"] == 1 Note that when using :class:`~bson.son.SON`, the key and value types must be given, e.g. ``SON[str, Any]``. Typed Collection ---------------- You can use :py:class:`~typing.TypedDict` (Python 3.8+) when using a well-defined schema for the data in a :class:`~pymongo.collection.Collection`. Note that all `schema validation`_ for inserts and updates is done on the server. These methods automatically add an "_id" field. .. doctest:: :pyversion: >= 3.8 >>> from typing import TypedDict >>> from pymongo import MongoClient >>> from pymongo.collection import Collection >>> class Movie(TypedDict): ... name: str ... year: int ... >>> client: MongoClient = MongoClient() >>> collection: Collection[Movie] = client.test.test >>> inserted = collection.insert_one(Movie(name="Jurassic Park", year=1993)) >>> result = collection.find_one({"name": "Jurassic Park"}) >>> assert result is not None >>> assert result["year"] == 1993 >>> # This will raise a type-checking error, despite being present, because it is added by PyMongo. >>> assert result["_id"] # type:ignore[typeddict-item] This same typing scheme works for all of the insert methods (:meth:`~pymongo.collection.Collection.insert_one`, :meth:`~pymongo.collection.Collection.insert_many`, and :meth:`~pymongo.collection.Collection.bulk_write`). For ``bulk_write`` both :class:`~pymongo.operations.InsertOne` and :class:`~pymongo.operations.ReplaceOne` operators are generic. .. doctest:: :pyversion: >= 3.8 >>> from typing import TypedDict >>> from pymongo import MongoClient >>> from pymongo.operations import InsertOne >>> from pymongo.collection import Collection >>> client: MongoClient = MongoClient() >>> collection: Collection[Movie] = client.test.test >>> inserted = collection.bulk_write([InsertOne(Movie(name="Jurassic Park", year=1993))]) >>> result = collection.find_one({"name": "Jurassic Park"}) >>> assert result is not None >>> assert result["year"] == 1993 >>> # This will raise a type-checking error, despite being present, because it is added by PyMongo. >>> assert result["_id"] # type:ignore[typeddict-item] Modeling Document Types with TypedDict -------------------------------------- You can use :py:class:`~typing.TypedDict` (Python 3.8+) to model structured data. As noted above, PyMongo will automatically add an ``_id`` field if it is not present. This also applies to TypedDict. There are three approaches to this: 1. Do not specify ``_id`` at all. It will be inserted automatically, and can be retrieved at run-time, but will yield a type-checking error unless explicitly ignored. 2. Specify ``_id`` explicitly. This will mean that every instance of your custom TypedDict class will have to pass a value for ``_id``. 3. Make use of :py:class:`~typing.NotRequired`. This has the flexibility of option 1, but with the ability to access the ``_id`` field without causing a type-checking error. Note: to use :py:class:`~typing.TypedDict` and :py:class:`~typing.NotRequired` in earlier versions of Python (<3.8, <3.11), use the ``typing_extensions`` package. .. doctest:: typed-dict-example :pyversion: >= 3.11 >>> from typing import TypedDict, NotRequired >>> from pymongo import MongoClient >>> from pymongo.collection import Collection >>> from bson import ObjectId >>> class Movie(TypedDict): ... name: str ... year: int ... >>> class ExplicitMovie(TypedDict): ... _id: ObjectId ... name: str ... year: int ... >>> class NotRequiredMovie(TypedDict): ... _id: NotRequired[ObjectId] ... name: str ... year: int ... >>> client: MongoClient = MongoClient() >>> collection: Collection[Movie] = client.test.test >>> inserted = collection.insert_one(Movie(name="Jurassic Park", year=1993)) >>> result = collection.find_one({"name": "Jurassic Park"}) >>> assert result is not None >>> # This will yield a type-checking error, despite being present, because it is added by PyMongo. >>> assert result["_id"] # type:ignore[typeddict-item] >>> collection: Collection[ExplicitMovie] = client.test.test >>> # Note that the _id keyword argument must be supplied >>> inserted = collection.insert_one( ... ExplicitMovie(_id=ObjectId(), name="Jurassic Park", year=1993) ... ) >>> result = collection.find_one({"name": "Jurassic Park"}) >>> assert result is not None >>> # This will not raise a type-checking error. >>> assert result["_id"] >>> collection: Collection[NotRequiredMovie] = client.test.test >>> # Note the lack of _id, similar to the first example >>> inserted = collection.insert_one(NotRequiredMovie(name="Jurassic Park", year=1993)) >>> result = collection.find_one({"name": "Jurassic Park"}) >>> assert result is not None >>> # This will not raise a type-checking error, despite not being provided explicitly. >>> assert result["_id"] Typed Database -------------- While less common, you could specify that the documents in an entire database match a well-defined schema using :py:class:`~typing.TypedDict` (Python 3.8+). .. doctest:: >>> from typing import TypedDict >>> from pymongo import MongoClient >>> from pymongo.database import Database >>> class Movie(TypedDict): ... name: str ... year: int ... >>> client: MongoClient = MongoClient() >>> db: Database[Movie] = client.test >>> collection = db.test >>> inserted = collection.insert_one({"name": "Jurassic Park", "year": 1993}) >>> result = collection.find_one({"name": "Jurassic Park"}) >>> assert result is not None >>> assert result["year"] == 1993 Typed Command ------------- When using the :meth:`~pymongo.database.Database.command`, you can specify the document type by providing a custom :class:`~bson.codec_options.CodecOptions`: .. doctest:: >>> from pymongo import MongoClient >>> from bson.raw_bson import RawBSONDocument >>> from bson import CodecOptions >>> client: MongoClient = MongoClient() >>> options = CodecOptions(RawBSONDocument) >>> result = client.admin.command("ping", codec_options=options) >>> assert isinstance(result, RawBSONDocument) Custom :py:class:`collections.abc.Mapping` subclasses and :py:class:`~typing.TypedDict` (Python 3.8+) are also supported. For :py:class:`~typing.TypedDict`, use the form: ``options: CodecOptions[MyTypedDict] = CodecOptions(...)``. Typed BSON Decoding ------------------- You can specify the document type returned by :mod:`bson` decoding functions by providing :class:`~bson.codec_options.CodecOptions`: .. doctest:: >>> from typing import Any, Dict >>> from bson import CodecOptions, encode, decode >>> class MyDict(Dict[str, Any]): ... def foo(self): ... return "bar" ... >>> options = CodecOptions(document_class=MyDict) >>> doc = {"x": 1, "y": 2} >>> bsonbytes = encode(doc, codec_options=options) >>> rt_document = decode(bsonbytes, codec_options=options) >>> assert rt_document.foo() == "bar" :class:`~bson.raw_bson.RawBSONDocument` and :py:class:`~typing.TypedDict` (Python 3.8+) are also supported. For :py:class:`~typing.TypedDict`, use the form: ``options: CodecOptions[MyTypedDict] = CodecOptions(...)``. Troubleshooting --------------- Client Type Annotation ~~~~~~~~~~~~~~~~~~~~~~ If you forget to add a type annotation for a :class:`~pymongo.mongo_client.MongoClient` object you may get the following ``mypy`` error:: from pymongo import MongoClient client = MongoClient() # error: Need type annotation for "client" The solution is to annotate the type as ``client: MongoClient`` or ``client: MongoClient[Dict[str, Any]]``. See `Basic Usage`_. Incompatible Types ~~~~~~~~~~~~~~~~~~ If you use the generic form of :class:`~pymongo.mongo_client.MongoClient` you may encounter a ``mypy`` error like:: from pymongo import MongoClient client: MongoClient = MongoClient() client.test.test.insert_many( {"a": 1} ) # error: Dict entry 0 has incompatible type "str": "int"; # expected "Mapping[str, Any]": "int" The solution is to use ``client: MongoClient[Dict[str, Any]]`` as used in `Basic Usage`_ . Actual Type Errors ~~~~~~~~~~~~~~~~~~ Other times ``mypy`` will catch an actual error, like the following code:: from pymongo import MongoClient from typing import Mapping client: MongoClient = MongoClient() client.test.test.insert_one( [{}] ) # error: Argument 1 to "insert_one" of "Collection" has # incompatible type "List[Dict[, ]]"; # expected "Mapping[str, Any]" In this case the solution is to use ``insert_one({})``, passing a document instead of a list. Another example is trying to set a value on a :class:`~bson.raw_bson.RawBSONDocument`, which is read-only.:: from bson.raw_bson import RawBSONDocument from pymongo import MongoClient client = MongoClient(document_class=RawBSONDocument) coll = client.test.test doc = {"my": "doc"} coll.insert_one(doc) retrieved = coll.find_one({"_id": doc["_id"]}) assert retrieved is not None assert len(retrieved.raw) > 0 retrieved[ "foo" ] = "bar" # error: Unsupported target for indexed assignment # ("RawBSONDocument") [index] .. _PyCharm: https://www.jetbrains.com/help/pycharm/type-hinting-in-product.html .. _Visual Studio Code: https://code.visualstudio.com/docs/languages/python .. _Sublime Text: https://github.com/sublimelsp/LSP-pyright .. _type hints: https://docs.python.org/3/library/typing.html .. _mypy: https://mypy.readthedocs.io/en/stable/cheat_sheet_py3.html .. _limitations in mypy: https://github.com/python/mypy/issues/3737 .. _mypy config: https://mypy.readthedocs.io/en/stable/config_file.html .. _test_typing module: https://github.com/mongodb/mongo-python-driver/blob/master/test/test_typing.py .. _schema validation: https://www.mongodb.com/docs/manual/core/schema-validation/#when-to-use-schema-validation mongodb-mongo-python-driver-509e9b7/doc/examples/uuid.rst000066400000000000000000000516111462766011000235240ustar00rootroot00000000000000 .. _handling-uuid-data-example: Handling UUID Data ================== PyMongo ships with built-in support for dealing with UUID types. It is straightforward to store native :class:`uuid.UUID` objects to MongoDB and retrieve them as native :class:`uuid.UUID` objects:: from pymongo import MongoClient from bson.binary import UuidRepresentation from uuid import uuid4 # use the 'standard' representation for cross-language compatibility. client = MongoClient(uuidRepresentation='standard') collection = client.get_database('uuid_db').get_collection('uuid_coll') # remove all documents from collection collection.delete_many({}) # create a native uuid object uuid_obj = uuid4() # save the native uuid object to MongoDB collection.insert_one({'uuid': uuid_obj}) # retrieve the stored uuid object from MongoDB document = collection.find_one({}) # check that the retrieved UUID matches the inserted UUID assert document['uuid'] == uuid_obj Native :class:`uuid.UUID` objects can also be used as part of MongoDB queries:: document = collection.find({'uuid': uuid_obj}) assert document['uuid'] == uuid_obj The above examples illustrate the simplest of use-cases - one where the UUID is generated by, and used in the same application. However, the situation can be significantly more complex when dealing with a MongoDB deployment that contains UUIDs created by other drivers as the Java and CSharp drivers have historically encoded UUIDs using a byte-order that is different from the one used by PyMongo. Applications that require interoperability across these drivers must specify the appropriate :class:`~bson.binary.UuidRepresentation`. In the following sections, we describe how drivers have historically differed in their encoding of UUIDs, and how applications can use the :class:`~bson.binary.UuidRepresentation` configuration option to maintain cross-language compatibility. .. attention:: New applications that do not share a MongoDB deployment with any other application and that have never stored UUIDs in MongoDB should use the ``standard`` UUID representation for cross-language compatibility. See :ref:`configuring-uuid-representation` for details on how to configure the :class:`~bson.binary.UuidRepresentation`. .. _example-legacy-uuid: Legacy Handling of UUID Data ---------------------------- Historically, MongoDB Drivers have used different byte-ordering while serializing UUID types to :class:`~bson.binary.Binary`. Consider, for instance, a UUID with the following canonical textual representation:: 00112233-4455-6677-8899-aabbccddeeff This UUID would historically be serialized by the Python driver as:: 00112233-4455-6677-8899-aabbccddeeff The same UUID would historically be serialized by the C# driver as:: 33221100-5544-7766-8899-aabbccddeeff Finally, the same UUID would historically be serialized by the Java driver as:: 77665544-3322-1100-ffee-ddccbbaa9988 .. note:: For in-depth information about the the byte-order historically used by different drivers, see the `Handling of Native UUID Types Specification `_. This difference in the byte-order of UUIDs encoded by different drivers can result in highly unintuitive behavior in some scenarios. We detail two such scenarios in the next sections. Scenario 1: Applications Share a MongoDB Deployment ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Consider the following situation: * Application ``C`` written in C# generates a UUID and uses it as the ``_id`` of a document that it proceeds to insert into the ``uuid_test`` collection of the ``example_db`` database. Let's assume that the canonical textual representation of the generated UUID is:: 00112233-4455-6677-8899-aabbccddeeff * Application ``P`` written in Python attempts to ``find`` the document written by application ``C`` in the following manner:: from uuid import UUID collection = client.example_db.uuid_test result = collection.find_one({'_id': UUID('00112233-4455-6677-8899-aabbccddeeff')}) In this instance, ``result`` will never be the document that was inserted by application ``C`` in the previous step. This is because of the different byte-order used by the C# driver for representing UUIDs as BSON Binary. The following query, on the other hand, will successfully find this document:: result = collection.find_one({'_id': UUID('33221100-5544-7766-8899-aabbccddeeff')}) This example demonstrates how the differing byte-order used by different drivers can hamper interoperability. To workaround this problem, users should configure their ``MongoClient`` with the appropriate :class:`~bson.binary.UuidRepresentation` (in this case, ``client`` in application ``P`` can be configured to use the :data:`~bson.binary.UuidRepresentation.CSHARP_LEGACY` representation to avoid the unintuitive behavior) as described in :ref:`configuring-uuid-representation`. Scenario 2: Round-Tripping UUIDs ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ In the following examples, we see how using a misconfigured :class:`~bson.binary.UuidRepresentation` can cause an application to inadvertently change the :class:`~bson.binary.Binary` subtype, and in some cases, the bytes of the :class:`~bson.binary.Binary` field itself when round-tripping documents containing UUIDs. Consider the following situation:: from bson.codec_options import CodecOptions, DEFAULT_CODEC_OPTIONS from bson.binary import Binary, UuidRepresentation from uuid import uuid4 # Using UuidRepresentation.PYTHON_LEGACY stores a Binary subtype-3 UUID python_opts = CodecOptions(uuid_representation=UuidRepresentation.PYTHON_LEGACY) input_uuid = uuid4() collection = client.testdb.get_collection('test', codec_options=python_opts) collection.insert_one({'_id': 'foo', 'uuid': input_uuid}) assert collection.find_one({'uuid': Binary(input_uuid.bytes, 3)})['_id'] == 'foo' # Retrieving this document using UuidRepresentation.STANDARD returns a Binary instance std_opts = CodecOptions(uuid_representation=UuidRepresentation.STANDARD) std_collection = client.testdb.get_collection('test', codec_options=std_opts) doc = std_collection.find_one({'_id': 'foo'}) assert isinstance(doc['uuid'], Binary) # Round-tripping the retrieved document yields the exact same document std_collection.replace_one({'_id': 'foo'}, doc) round_tripped_doc = collection.find_one({'uuid': Binary(input_uuid.bytes, 3)}) assert doc == round_tripped_doc In this example, round-tripping the document using the incorrect :class:`~bson.binary.UuidRepresentation` (``STANDARD`` instead of ``PYTHON_LEGACY``) changes the :class:`~bson.binary.Binary` subtype as a side-effect. **Note that this can also happen when the situation is reversed - i.e. when the original document is written using ``STANDARD`` representation and then round-tripped using the ``PYTHON_LEGACY`` representation.** In the next example, we see the consequences of incorrectly using a representation that modifies byte-order (``CSHARP_LEGACY`` or ``JAVA_LEGACY``) when round-tripping documents:: from bson.codec_options import CodecOptions, DEFAULT_CODEC_OPTIONS from bson.binary import Binary, UuidRepresentation from uuid import uuid4 # Using UuidRepresentation.STANDARD stores a Binary subtype-4 UUID std_opts = CodecOptions(uuid_representation=UuidRepresentation.STANDARD) input_uuid = uuid4() collection = client.testdb.get_collection('test', codec_options=std_opts) collection.insert_one({'_id': 'baz', 'uuid': input_uuid}) assert collection.find_one({'uuid': Binary(input_uuid.bytes, 4)})['_id'] == 'baz' # Retrieving this document using UuidRepresentation.JAVA_LEGACY returns a native UUID # without modifying the UUID byte-order java_opts = CodecOptions(uuid_representation=UuidRepresentation.JAVA_LEGACY) java_collection = client.testdb.get_collection('test', codec_options=java_opts) doc = java_collection.find_one({'_id': 'baz'}) assert doc['uuid'] == input_uuid # Round-tripping the retrieved document silently changes the Binary bytes and subtype java_collection.replace_one({'_id': 'baz'}, doc) assert collection.find_one({'uuid': Binary(input_uuid.bytes, 3)}) is None assert collection.find_one({'uuid': Binary(input_uuid.bytes, 4)}) is None round_tripped_doc = collection.find_one({'_id': 'baz'}) assert round_tripped_doc['uuid'] == Binary(input_uuid.bytes, 3).as_uuid(UuidRepresentation.JAVA_LEGACY) In this case, using the incorrect :class:`~bson.binary.UuidRepresentation` (``JAVA_LEGACY`` instead of ``STANDARD``) changes the :class:`~bson.binary.Binary` bytes and subtype as a side-effect. **Note that this happens when any representation that manipulates byte-order (``CSHARP_LEGACY`` or ``JAVA_LEGACY``) is incorrectly used to round-trip UUIDs written with ``STANDARD``. When the situation is reversed - i.e. when the original document is written using ``CSHARP_LEGACY`` or ``JAVA_LEGACY`` and then round-tripped using ``STANDARD`` - only the :class:`~bson.binary.Binary` subtype is changed.** .. note:: Starting in PyMongo 4.0, these issue will be resolved as the ``STANDARD`` representation will decode Binary subtype 3 fields as :class:`~bson.binary.Binary` objects of subtype 3 (instead of :class:`uuid.UUID`), and each of the ``LEGACY_*`` representations will decode Binary subtype 4 fields to :class:`~bson.binary.Binary` objects of subtype 4 (instead of :class:`uuid.UUID`). .. _configuring-uuid-representation: Configuring a UUID Representation --------------------------------- Users can workaround the problems described above by configuring their applications with the appropriate :class:`~bson.binary.UuidRepresentation`. Configuring the representation modifies PyMongo's behavior while encoding :class:`uuid.UUID` objects to BSON and decoding Binary subtype 3 and 4 fields from BSON. Applications can set the UUID representation in one of the following ways: #. At the ``MongoClient`` level using the ``uuidRepresentation`` URI option, e.g.:: client = MongoClient("mongodb://a:27107/?uuidRepresentation=standard") Valid values are: .. list-table:: :header-rows: 1 * - Value - UUID Representation * - ``unspecified`` - :ref:`unspecified-representation-details` * - ``standard`` - :ref:`standard-representation-details` * - ``pythonLegacy`` - :ref:`python-legacy-representation-details` * - ``javaLegacy`` - :ref:`java-legacy-representation-details` * - ``csharpLegacy`` - :ref:`csharp-legacy-representation-details` #. At the ``MongoClient`` level using the ``uuidRepresentation`` kwarg option, e.g.:: from bson.binary import UuidRepresentation client = MongoClient(uuidRepresentation=UuidRepresentation.STANDARD) #. At the ``Database`` or ``Collection`` level by supplying a suitable :class:`~bson.codec_options.CodecOptions` instance, e.g.:: from bson.codec_options import CodecOptions csharp_opts = CodecOptions(uuid_representation=UuidRepresentation.CSHARP_LEGACY) java_opts = CodecOptions(uuid_representation=UuidRepresentation.JAVA_LEGACY) # Get database/collection from client with csharpLegacy UUID representation csharp_database = client.get_database('csharp_db', codec_options=csharp_opts) csharp_collection = client.testdb.get_collection('csharp_coll', codec_options=csharp_opts) # Get database/collection from existing database/collection with javaLegacy UUID representation java_database = csharp_database.with_options(codec_options=java_opts) java_collection = csharp_collection.with_options(codec_options=java_opts) Supported UUID Representations ------------------------------ .. list-table:: :header-rows: 1 * - UUID Representation - Default? - Encode :class:`uuid.UUID` to - Decode :class:`~bson.binary.Binary` subtype 4 to - Decode :class:`~bson.binary.Binary` subtype 3 to * - :ref:`standard-representation-details` - No - :class:`~bson.binary.Binary` subtype 4 - :class:`uuid.UUID` - :class:`~bson.binary.Binary` subtype 3 * - :ref:`unspecified-representation-details` - Yes, in PyMongo>=4 - Raise :exc:`ValueError` - :class:`~bson.binary.Binary` subtype 4 - :class:`~bson.binary.Binary` subtype 3 * - :ref:`python-legacy-representation-details` - No - :class:`~bson.binary.Binary` subtype 3 with standard byte-order - :class:`~bson.binary.Binary` subtype 4 - :class:`uuid.UUID` * - :ref:`java-legacy-representation-details` - No - :class:`~bson.binary.Binary` subtype 3 with Java legacy byte-order - :class:`~bson.binary.Binary` subtype 4 - :class:`uuid.UUID` * - :ref:`csharp-legacy-representation-details` - No - :class:`~bson.binary.Binary` subtype 3 with C# legacy byte-order - :class:`~bson.binary.Binary` subtype 4 - :class:`uuid.UUID` We now detail the behavior and use-case for each supported UUID representation. .. _unspecified-representation-details: ``UNSPECIFIED`` ^^^^^^^^^^^^^^^ .. attention:: Starting in PyMongo 4.0, :data:`~bson.binary.UuidRepresentation.UNSPECIFIED` is the default UUID representation used by PyMongo. The :data:`~bson.binary.UuidRepresentation.UNSPECIFIED` representation prevents the incorrect interpretation of UUID bytes by stopping short of automatically converting UUID fields in BSON to native UUID types. Decoding a UUID when using this representation returns a :class:`~bson.binary.Binary` object instead. If required, users can coerce the decoded :class:`~bson.binary.Binary` objects into native UUIDs using the :meth:`~bson.binary.Binary.as_uuid` method and specifying the appropriate representation format. The following example shows what this might look like for a UUID stored by the C# driver:: from bson.codec_options import CodecOptions, DEFAULT_CODEC_OPTIONS from bson.binary import Binary, UuidRepresentation from uuid import uuid4 # Using UuidRepresentation.CSHARP_LEGACY csharp_opts = CodecOptions(uuid_representation=UuidRepresentation.CSHARP_LEGACY) # Store a legacy C#-formatted UUID input_uuid = uuid4() collection = client.testdb.get_collection('test', codec_options=csharp_opts) collection.insert_one({'_id': 'foo', 'uuid': input_uuid}) # Using UuidRepresentation.UNSPECIFIED unspec_opts = CodecOptions(uuid_representation=UuidRepresentation.UNSPECIFIED) unspec_collection = client.testdb.get_collection('test', codec_options=unspec_opts) # UUID fields are decoded as Binary when UuidRepresentation.UNSPECIFIED is configured document = unspec_collection.find_one({'_id': 'foo'}) decoded_field = document['uuid'] assert isinstance(decoded_field, Binary) # Binary.as_uuid() can be used to coerce the decoded value to a native UUID decoded_uuid = decoded_field.as_uuid(UuidRepresentation.CSHARP_LEGACY) assert decoded_uuid == input_uuid Native :class:`uuid.UUID` objects cannot directly be encoded to :class:`~bson.binary.Binary` when the UUID representation is ``UNSPECIFIED`` and attempting to do so will result in an exception:: unspec_collection.insert_one({'_id': 'bar', 'uuid': uuid4()}) Traceback (most recent call last): ... ValueError: cannot encode native uuid.UUID with UuidRepresentation.UNSPECIFIED. UUIDs can be manually converted to bson.Binary instances using bson.Binary.from_uuid() or a different UuidRepresentation can be configured. See the documentation for UuidRepresentation for more information. Instead, applications using :data:`~bson.binary.UuidRepresentation.UNSPECIFIED` must explicitly coerce a native UUID using the :meth:`~bson.binary.Binary.from_uuid` method:: explicit_binary = Binary.from_uuid(uuid4(), UuidRepresentation.STANDARD) unspec_collection.insert_one({'_id': 'bar', 'uuid': explicit_binary}) .. _standard-representation-details: ``STANDARD`` ^^^^^^^^^^^^ .. attention:: This UUID representation should be used by new applications or applications that are encoding and/or decoding UUIDs in MongoDB for the first time. The :data:`~bson.binary.UuidRepresentation.STANDARD` representation enables cross-language compatibility by ensuring the same byte-ordering when encoding UUIDs from all drivers. UUIDs written by a driver with this representation configured will be handled correctly by every other provided it is also configured with the ``STANDARD`` representation. ``STANDARD`` encodes native :class:`uuid.UUID` objects to :class:`~bson.binary.Binary` subtype 4 objects. .. _python-legacy-representation-details: ``PYTHON_LEGACY`` ^^^^^^^^^^^^^^^^^ .. attention:: This uuid representation should be used when reading UUIDs generated by existing applications that use the Python driver but **don't** explicitly set a UUID representation. .. attention:: :data:`~bson.binary.UuidRepresentation.PYTHON_LEGACY` was the default uuid representation in PyMongo 3. The :data:`~bson.binary.UuidRepresentation.PYTHON_LEGACY` representation corresponds to the legacy representation of UUIDs used by PyMongo. This representation conforms with `RFC 4122 Section 4.1.2 `_. The following example illustrates the use of this representation:: from bson.codec_options import CodecOptions, DEFAULT_CODEC_OPTIONS from bson.binary import Binary, UuidRepresentation # No configured UUID representation collection = client.python_legacy.get_collection('test', codec_options=DEFAULT_CODEC_OPTIONS) # Using UuidRepresentation.PYTHON_LEGACY pylegacy_opts = CodecOptions(uuid_representation=UuidRepresentation.PYTHON_LEGACY) pylegacy_collection = client.python_legacy.get_collection('test', codec_options=pylegacy_opts) # UUIDs written by PyMongo 3 with no UuidRepresentation configured # (or PyMongo 4.0 with PYTHON_LEGACY) can be queried using PYTHON_LEGACY uuid_1 = uuid4() pylegacy_collection.insert_one({'uuid': uuid_1}) document = pylegacy_collection.find_one({'uuid': uuid_1}) ``PYTHON_LEGACY`` encodes native :class:`uuid.UUID` objects to :class:`~bson.binary.Binary` subtype 3 objects, preserving the same byte-order as :attr:`~uuid.UUID.bytes`:: from bson.binary import Binary document = collection.find_one({'uuid': Binary(uuid_2.bytes, subtype=3)}) assert document['uuid'] == uuid_2 .. _java-legacy-representation-details: ``JAVA_LEGACY`` ^^^^^^^^^^^^^^^ .. attention:: This UUID representation should be used when reading UUIDs written to MongoDB by the legacy applications (i.e. applications that don't use the ``STANDARD`` representation) using the Java driver. The :data:`~bson.binary.UuidRepresentation.JAVA_LEGACY` representation corresponds to the legacy representation of UUIDs used by the MongoDB Java Driver. .. note:: The ``JAVA_LEGACY`` representation reverses the order of bytes 0-7, and bytes 8-15. As an example, consider the same UUID described in :ref:`example-legacy-uuid`. Let us assume that an application used the Java driver without an explicitly specified UUID representation to insert the example UUID ``00112233-4455-6677-8899-aabbccddeeff`` into MongoDB. If we try to read this value using ``PYTHON_LEGACY``, we end up with an entirely different UUID:: UUID('77665544-3322-1100-ffee-ddccbbaa9988') However, if we explicitly set the representation to :data:`~bson.binary.UuidRepresentation.JAVA_LEGACY`, we get the correct result:: UUID('00112233-4455-6677-8899-aabbccddeeff') PyMongo uses the specified UUID representation to reorder the BSON bytes and load them correctly. ``JAVA_LEGACY`` encodes native :class:`uuid.UUID` objects to :class:`~bson.binary.Binary` subtype 3 objects, while performing the same byte-reordering as the legacy Java driver's UUID to BSON encoder. .. _csharp-legacy-representation-details: ``CSHARP_LEGACY`` ^^^^^^^^^^^^^^^^^ .. attention:: This UUID representation should be used when reading UUIDs written to MongoDB by the legacy applications (i.e. applications that don't use the ``STANDARD`` representation) using the C# driver. The :data:`~bson.binary.UuidRepresentation.CSHARP_LEGACY` representation corresponds to the legacy representation of UUIDs used by the MongoDB Java Driver. .. note:: The ``CSHARP_LEGACY`` representation reverses the order of bytes 0-3, bytes 4-5, and bytes 6-7. As an example, consider the same UUID described in :ref:`example-legacy-uuid`. Let us assume that an application used the C# driver without an explicitly specified UUID representation to insert the example UUID ``00112233-4455-6677-8899-aabbccddeeff`` into MongoDB. If we try to read this value using PYTHON_LEGACY, we end up with an entirely different UUID:: UUID('33221100-5544-7766-8899-aabbccddeeff') However, if we explicitly set the representation to :data:`~bson.binary.UuidRepresentation.CSHARP_LEGACY`, we get the correct result:: UUID('00112233-4455-6677-8899-aabbccddeeff') PyMongo uses the specified UUID representation to reorder the BSON bytes and load them correctly. ``CSHARP_LEGACY`` encodes native :class:`uuid.UUID` objects to :class:`~bson.binary.Binary` subtype 3 objects, while performing the same byte-reordering as the legacy C# driver's UUID to BSON encoder. mongodb-mongo-python-driver-509e9b7/doc/faq.rst000066400000000000000000000637711462766011000215210ustar00rootroot00000000000000Frequently Asked Questions ========================== Is PyMongo thread-safe? ----------------------- PyMongo is thread-safe and provides built-in connection pooling for threaded applications. .. _pymongo-fork-safe: Is PyMongo fork-safe? --------------------- PyMongo is not fork-safe. Care must be taken when using instances of :class:`~pymongo.mongo_client.MongoClient` with ``fork()``. Specifically, instances of MongoClient must not be copied from a parent process to a child process. Instead, the parent process and each child process must create their own instances of MongoClient. Instances of MongoClient copied from the parent process have a high probability of deadlock in the child process due to the inherent incompatibilities between ``fork()``, threads, and locks described :ref:`below `. PyMongo will attempt to issue a warning if there is a chance of this deadlock occurring. .. _pymongo-fork-safe-details: MongoClient spawns multiple threads to run background tasks such as monitoring connected servers. These threads share state that is protected by instances of :class:`~threading.Lock`, which are themselves `not fork-safe`_. The driver is therefore subject to the same limitations as any other multithreaded code that uses :class:`~threading.Lock` (and mutexes in general). One of these limitations is that the locks become useless after ``fork()``. During the fork, all locks are copied over to the child process in the same state as they were in the parent: if they were locked, the copied locks are also locked. The child created by ``fork()`` only has one thread, so any locks that were taken out by other threads in the parent will never be released in the child. The next time the child process attempts to acquire one of these locks, deadlock occurs. Starting in version 4.3, PyMongo utilizes :py:func:`os.register_at_fork` to reset its locks and other shared state in the child process after a :py:func:`os.fork` to reduce the frequency of deadlocks. However deadlocks are still possible because libraries that PyMongo depends on, like `OpenSSL`_ and `getaddrinfo(3)`_ (on some platforms), are not fork() safe in a multithreaded application. Linux also imposes the restriction that: After a `fork()`_ in a multithreaded program, the child can safely call only async-signal-safe functions (see `signal-safety(7)`_) until such time as it calls `execve(2)`_. PyMongo relies on functions that are *not* `async-signal-safe`_ and hence the child process can experience deadlocks or crashes when attempting to call a non `async-signal-safe`_ function. For examples of deadlocks or crashes that could occur see `PYTHON-3406`_. For a long but interesting read about the problems of Python locks in multithreaded contexts with ``fork()``, see http://bugs.python.org/issue6721. .. _not fork-safe: http://bugs.python.org/issue6721 .. _OpenSSL: https://github.com/openssl/openssl/issues/19066 .. _fork(): https://man7.org/linux/man-pages/man2/fork.2.html .. _signal-safety(7): https://man7.org/linux/man-pages/man7/signal-safety.7.html .. _async-signal-safe: https://man7.org/linux/man-pages/man7/signal-safety.7.html .. _execve(2): https://man7.org/linux/man-pages/man2/execve.2.html .. _getaddrinfo(3): https://man7.org/linux/man-pages/man3/gai_strerror.3.html .. _PYTHON-3406: https://jira.mongodb.org/browse/PYTHON-3406 .. _connection-pooling: Can PyMongo help me load the results of my query as a Pandas ``DataFrame``? --------------------------------------------------------------------------- While PyMongo itself does not provide any APIs for working with numerical or columnar data, `PyMongoArrow `_ is a companion library to PyMongo that makes it easy to load MongoDB query result sets as `Pandas DataFrames `_, `NumPy ndarrays `_, or `Apache Arrow Tables `_. How does connection pooling work in PyMongo? -------------------------------------------- Every :class:`~pymongo.mongo_client.MongoClient` instance has a built-in connection pool per server in your MongoDB topology. These pools open sockets on demand to support the number of concurrent MongoDB operations that your multi-threaded application requires. There is no thread-affinity for sockets. The size of each connection pool is capped at ``maxPoolSize``, which defaults to 100. If there are ``maxPoolSize`` connections to a server and all are in use, the next request to that server will wait until one of the connections becomes available. The client instance opens two additional sockets per server in your MongoDB topology for monitoring the server's state. For example, a client connected to a 3-node replica set opens 6 monitoring sockets. It also opens as many sockets as needed to support a multi-threaded application's concurrent operations on each server, up to ``maxPoolSize``. With a ``maxPoolSize`` of 100, if the application only uses the primary (the default), then only the primary connection pool grows and the total connections is at most 106. If the application uses a :class:`~pymongo.read_preferences.ReadPreference` to query the secondaries, their pools also grow and the total connections can reach 306. Additionally, the pools are rate limited such that each connection pool can only create at most 2 connections in parallel at any time. The connection creation covers covers all the work required to setup a new connection including DNS, TCP, SSL/TLS, MongoDB handshake, and MongoDB authentication. For example, if three threads concurrently attempt to check out a connection from an empty pool, the first two threads will begin creating new connections while the third thread will wait. The third thread stops waiting when either: - one of the first two threads finishes creating a connection, or - an existing connection is checked back into the pool. Rate limiting concurrent connection creation reduces the likelihood of connection storms and improves the driver's ability to reuse existing connections. It is possible to set the minimum number of concurrent connections to each server with ``minPoolSize``, which defaults to 0. The connection pool will be initialized with this number of sockets. If sockets are closed due to any network errors, causing the total number of sockets (both in use and idle) to drop below the minimum, more sockets are opened until the minimum is reached. The maximum number of milliseconds that a connection can remain idle in the pool before being removed and replaced can be set with ``maxIdleTimeMS``, which defaults to ``None`` (no limit). The default configuration for a :class:`~pymongo.mongo_client.MongoClient` works for most applications:: client = MongoClient(host, port) Create this client **once** for each process, and reuse it for all operations. It is a common mistake to create a new client for each request, which is very inefficient. To support extremely high numbers of concurrent MongoDB operations within one process, increase ``maxPoolSize``:: client = MongoClient(host, port, maxPoolSize=200) ... or make it unbounded:: client = MongoClient(host, port, maxPoolSize=None) Once the pool reaches its maximum size, additional threads have to wait for sockets to become available. PyMongo does not limit the number of threads that can wait for sockets to become available and it is the application's responsibility to limit the size of its thread pool to bound queuing during a load spike. Threads are allowed to wait for any length of time unless ``waitQueueTimeoutMS`` is defined:: client = MongoClient(host, port, waitQueueTimeoutMS=100) A thread that waits more than 100ms (in this example) for a socket raises :exc:`~pymongo.errors.ConnectionFailure`. Use this option if it is more important to bound the duration of operations during a load spike than it is to complete every operation. When :meth:`~pymongo.mongo_client.MongoClient.close` is called by any thread, all idle sockets are closed, and all sockets that are in use will be closed as they are returned to the pool. Does PyMongo support Python 3? ------------------------------ PyMongo supports CPython 3.7+ and PyPy3.8+. See the :doc:`python3` for details. Does PyMongo support asynchronous frameworks like Gevent, asyncio, Tornado, or Twisted? --------------------------------------------------------------------------------------- PyMongo fully supports :doc:`Gevent `. To use MongoDB with `asyncio `_ or `Tornado `_, see the `Motor `_ project. For `Twisted `_, see `TxMongo `_. Its stated mission is to keep feature parity with PyMongo. .. _writes-and-ids: Why does PyMongo add an _id field to all of my documents? --------------------------------------------------------- When a document is inserted to MongoDB using :meth:`~pymongo.collection.Collection.insert_one`, :meth:`~pymongo.collection.Collection.insert_many`, or :meth:`~pymongo.collection.Collection.bulk_write`, and that document does not include an ``_id`` field, PyMongo automatically adds one for you, set to an instance of :class:`~bson.objectid.ObjectId`. For example:: >>> my_doc = {'x': 1} >>> collection.insert_one(my_doc) InsertOneResult(ObjectId('560db337fba522189f171720'), acknowledged=True) >>> my_doc {'x': 1, '_id': ObjectId('560db337fba522189f171720')} Users often discover this behavior when calling :meth:`~pymongo.collection.Collection.insert_many` with a list of references to a single document raises :exc:`~pymongo.errors.BulkWriteError`. Several Python idioms lead to this pitfall:: >>> doc = {} >>> collection.insert_many(doc for _ in range(10)) Traceback (most recent call last): ... pymongo.errors.BulkWriteError: batch op errors occurred >>> doc {'_id': ObjectId('560f171cfba52279f0b0da0c')} >>> docs = [{}] >>> collection.insert_many(docs * 10) Traceback (most recent call last): ... pymongo.errors.BulkWriteError: batch op errors occurred >>> docs [{'_id': ObjectId('560f1933fba52279f0b0da0e')}] PyMongo adds an ``_id`` field in this manner for a few reasons: - All MongoDB documents are required to have an ``_id`` field. - If PyMongo were to insert a document without an ``_id`` MongoDB would add one itself, but it would not report the value back to PyMongo. - Copying the document to insert before adding the ``_id`` field would be prohibitively expensive for most high write volume applications. If you don't want PyMongo to add an ``_id`` to your documents, insert only documents that already have an ``_id`` field, added by your application. Key order in subdocuments -- why does my query work in the shell but not PyMongo? --------------------------------------------------------------------------------- .. Note: We should rework this section now that Python 3.6+ has ordered dict. .. testsetup:: key-order from bson.son import SON from pymongo.mongo_client import MongoClient collection = MongoClient().test.collection collection.drop() collection.insert_one({"_id": 1.0, "subdocument": SON([("b", 1.0), ("a", 1.0)])}) The key-value pairs in a BSON document can have any order (except that ``_id`` is always first). The mongo shell preserves key order when reading and writing data. Observe that "b" comes before "a" when we create the document and when it is displayed: .. code-block:: javascript > // mongo shell. > db.collection.insertOne( { "_id" : 1, "subdocument" : { "b" : 1, "a" : 1 } } ) WriteResult({ "nInserted" : 1 }) > db.collection.findOne() { "_id" : 1, "subdocument" : { "b" : 1, "a" : 1 } } PyMongo represents BSON documents as Python dicts by default, and the order of keys in dicts is not defined. That is, a dict declared with the "a" key first is the same, to Python, as one with "b" first: >>> print({'a': 1.0, 'b': 1.0}) {'a': 1.0, 'b': 1.0} >>> print({'b': 1.0, 'a': 1.0}) {'a': 1.0, 'b': 1.0} Therefore, Python dicts are not guaranteed to show keys in the order they are stored in BSON. Here, "a" is shown before "b": >>> print(collection.find_one()) {'_id': 1.0, 'subdocument': {'a': 1.0, 'b': 1.0}} To preserve order when reading BSON, use the :class:`~bson.son.SON` class, which is a dict that remembers its key order. First, get a handle to the collection, configured to use :class:`~bson.son.SON` instead of dict: .. doctest:: key-order :options: +NORMALIZE_WHITESPACE >>> from bson import CodecOptions, SON >>> opts = CodecOptions(document_class=SON) >>> opts CodecOptions(document_class=...SON..., tz_aware=False, uuid_representation=UuidRepresentation.UNSPECIFIED, unicode_decode_error_handler='strict', tzinfo=None, type_registry=TypeRegistry(type_codecs=[], fallback_encoder=None), datetime_conversion=DatetimeConversion.DATETIME) >>> collection_son = collection.with_options(codec_options=opts) Now, documents and subdocuments in query results are represented with :class:`~bson.son.SON` objects: .. doctest:: key-order >>> print(collection_son.find_one()) SON([('_id', 1.0), ('subdocument', SON([('b', 1.0), ('a', 1.0)]))]) The subdocument's actual storage layout is now visible: "b" is before "a". Because a dict's key order is not defined, you cannot predict how it will be serialized **to** BSON. But MongoDB considers subdocuments equal only if their keys have the same order. So if you use a dict to query on a subdocument it may not match: >>> collection.find_one({'subdocument': {'a': 1.0, 'b': 1.0}}) is None True Swapping the key order in your query makes no difference: >>> collection.find_one({'subdocument': {'b': 1.0, 'a': 1.0}}) is None True ... because, as we saw above, Python considers the two dicts the same. There are two solutions. First, you can match the subdocument field-by-field: >>> collection.find_one({'subdocument.a': 1.0, ... 'subdocument.b': 1.0}) {'_id': 1.0, 'subdocument': {'a': 1.0, 'b': 1.0}} The query matches any subdocument with an "a" of 1.0 and a "b" of 1.0, regardless of the order you specify them in Python or the order they are stored in BSON. Additionally, this query now matches subdocuments with additional keys besides "a" and "b", whereas the previous query required an exact match. The second solution is to use a :class:`~bson.son.SON` to specify the key order: >>> query = {'subdocument': SON([('b', 1.0), ('a', 1.0)])} >>> collection.find_one(query) {'_id': 1.0, 'subdocument': {'a': 1.0, 'b': 1.0}} The key order you use when you create a :class:`~bson.son.SON` is preserved when it is serialized to BSON and used as a query. Thus you can create a subdocument that exactly matches the subdocument in the collection. .. seealso:: `MongoDB Manual entry on subdocument matching `_. What does *CursorNotFound* cursor id not valid at server mean? -------------------------------------------------------------- Cursors in MongoDB can timeout on the server if they've been open for a long time without any operations being performed on them. This can lead to an :class:`~pymongo.errors.CursorNotFound` exception being raised when attempting to iterate the cursor. How do I change the timeout value for cursors? ---------------------------------------------- MongoDB doesn't support custom timeouts for cursors, but cursor timeouts can be turned off entirely. Pass ``no_cursor_timeout=True`` to :meth:`~pymongo.collection.Collection.find`. How can I store :mod:`decimal.Decimal` instances? ------------------------------------------------- PyMongo >= 3.4 supports the Decimal128 BSON type introduced in MongoDB 3.4. See :mod:`~bson.decimal128` for more information. MongoDB <= 3.2 only supports IEEE 754 floating points - the same as the Python float type. The only way PyMongo could store Decimal instances to these versions of MongoDB would be to convert them to this standard, so you'd really only be storing floats anyway - we force users to do this conversion explicitly so that they are aware that it is happening. I'm saving ``9.99`` but when I query my document contains ``9.9900000000000002`` - what's going on here? -------------------------------------------------------------------------------------------------------- The database representation is ``9.99`` as an IEEE floating point (which is common to MongoDB and Python as well as most other modern languages). The problem is that ``9.99`` cannot be represented exactly with a double precision floating point - this is true in some versions of Python as well: >>> 9.99 9.9900000000000002 The result that you get when you save ``9.99`` with PyMongo is exactly the same as the result you'd get saving it with the JavaScript shell or any of the other languages (and as the data you're working with when you type ``9.99`` into a Python program). Can you add attribute style access for documents? ------------------------------------------------- This request has come up a number of times but we've decided not to implement anything like this. The relevant `jira case `_ has some information about the decision, but here is a brief summary: 1. This will pollute the attribute namespace for documents, so could lead to subtle bugs / confusing errors when using a key with the same name as a dictionary method. 2. The only reason we even use SON objects instead of regular dictionaries is to maintain key ordering, since the server requires this for certain operations. So we're hesitant to needlessly complicate SON (at some point it's hypothetically possible we might want to revert back to using dictionaries alone, without breaking backwards compatibility for everyone). 3. It's easy (and Pythonic) for new users to deal with documents, since they behave just like dictionaries. If we start changing their behavior it adds a barrier to entry for new users - another class to learn. What is the correct way to handle time zones with PyMongo? ---------------------------------------------------------- See :doc:`examples/datetimes` for examples on how to handle :class:`~datetime.datetime` objects correctly. How can I save a :mod:`datetime.date` instance? ----------------------------------------------- PyMongo doesn't support saving :mod:`datetime.date` instances, since there is no BSON type for dates without times. Rather than having the driver enforce a convention for converting :mod:`datetime.date` instances to :mod:`datetime.datetime` instances for you, any conversion should be performed in your client code. .. _web-application-querying-by-objectid: When I query for a document by ObjectId in my web application I get no result ----------------------------------------------------------------------------- It's common in web applications to encode documents' ObjectIds in URLs, like:: "/posts/50b3bda58a02fb9a84d8991e" Your web framework will pass the ObjectId portion of the URL to your request handler as a string, so it must be converted to :class:`~bson.objectid.ObjectId` before it is passed to :meth:`~pymongo.collection.Collection.find_one`. It is a common mistake to forget to do this conversion. Here's how to do it correctly in Flask_ (other web frameworks are similar):: from pymongo import MongoClient from bson.objectid import ObjectId from flask import Flask, render_template client = MongoClient() app = Flask(__name__) @app.route("/posts/<_id>") def show_post(_id): # NOTE!: converting _id from string to ObjectId before passing to find_one post = client.db.posts.find_one({'_id': ObjectId(_id)}) return render_template('post.html', post=post) if __name__ == "__main__": app.run() .. _Flask: http://flask.pocoo.org/ .. seealso:: :ref:`querying-by-objectid` How can I use PyMongo from Django? ---------------------------------- `Django `_ is a popular Python web framework. Django includes an ORM, :mod:`django.db`. Currently, there's no official MongoDB backend for Django. `django-mongodb-engine `_ is an unofficial MongoDB backend that supports Django aggregations, (atomic) updates, embedded objects, Map/Reduce and GridFS. It allows you to use most of Django's built-in features, including the ORM, admin, authentication, site and session frameworks and caching. However, it's easy to use MongoDB (and PyMongo) from Django without using a Django backend. Certain features of Django that require :mod:`django.db` (admin, authentication and sessions) will not work using just MongoDB, but most of what Django provides can still be used. One project which should make working with MongoDB and Django easier is `mango `_. Mango is a set of MongoDB backends for Django sessions and authentication (bypassing :mod:`django.db` entirely). .. _using-with-mod-wsgi: Does PyMongo work with **mod_wsgi**? ------------------------------------ Yes. See the configuration guide for :ref:`pymongo-and-mod_wsgi`. Does PyMongo work with PythonAnywhere? -------------------------------------- No. PyMongo creates Python threads which `PythonAnywhere `_ does not support. For more information see `PYTHON-1495 `_. How can I use something like Python's ``json`` module to encode my documents to JSON? ------------------------------------------------------------------------------------- :mod:`~bson.json_util` is PyMongo's built in, flexible tool for using Python's :mod:`json` module with BSON documents and `MongoDB Extended JSON `_. The :mod:`json` module won't work out of the box with all documents from PyMongo as PyMongo supports some special types (like :class:`~bson.objectid.ObjectId` and :class:`~bson.dbref.DBRef`) that are not supported in JSON. `python-bsonjs `_ is a fast BSON to MongoDB Extended JSON converter built on top of `libbson `_. ``python-bsonjs`` does not depend on PyMongo and can offer a nice performance improvement over :mod:`~bson.json_util`. ``python-bsonjs`` works best with PyMongo when using :class:`~bson.raw_bson.RawBSONDocument`. Why do I get OverflowError decoding dates stored by another language's driver? ------------------------------------------------------------------------------ PyMongo decodes BSON datetime values to instances of Python's :class:`datetime.datetime`. Instances of :class:`datetime.datetime` are limited to years between :data:`datetime.MINYEAR` (usually 1) and :data:`datetime.MAXYEAR` (usually 9999). Some MongoDB drivers (e.g. the PHP driver) can store BSON datetimes with year values far outside those supported by :class:`datetime.datetime`. There are a few ways to work around this issue. Starting with PyMongo 4.3, :func:`bson.decode` can decode BSON datetimes in one of four ways, and can be specified using the ``datetime_conversion`` parameter of :class:`~bson.codec_options.CodecOptions`. The default option is :attr:`~bson.codec_options.DatetimeConversion.DATETIME`, which will attempt to decode as a :class:`datetime.datetime`, allowing :class:`~builtin.OverflowError` to occur upon out-of-range dates. :attr:`~bson.codec_options.DatetimeConversion.DATETIME_AUTO` alters this behavior to instead return :class:`~bson.datetime_ms.DatetimeMS` when representations are out-of-range, while returning :class:`~datetime.datetime` objects as before: .. doctest:: >>> from datetime import datetime >>> from bson.datetime_ms import DatetimeMS >>> from bson.codec_options import DatetimeConversion >>> from pymongo import MongoClient >>> client = MongoClient(datetime_conversion=DatetimeConversion.DATETIME_AUTO) >>> client.db.collection.insert_one({"x": datetime(1970, 1, 1)}) InsertOneResult(ObjectId('...'), acknowledged=True) >>> client.db.collection.insert_one({"x": DatetimeMS(2**62)}) InsertOneResult(ObjectId('...'), acknowledged=True) >>> for x in client.db.collection.find(): ... print(x) ... {'_id': ObjectId('...'), 'x': datetime.datetime(1970, 1, 1, 0, 0)} {'_id': ObjectId('...'), 'x': DatetimeMS(4611686018427387904)} For other options, please refer to :class:`~bson.codec_options.DatetimeConversion`. Another option that does not involve setting ``datetime_conversion`` is to to filter out documents values outside of the range supported by :class:`~datetime.datetime`: >>> from datetime import datetime >>> coll = client.test.dates >>> cur = coll.find({'dt': {'$gte': datetime.min, '$lte': datetime.max}}) Another option, assuming you don't need the datetime field, is to filter out just that field:: >>> cur = coll.find({}, projection={'dt': False}) .. _multiprocessing: Using PyMongo with Multiprocessing ---------------------------------- On Unix systems the multiprocessing module spawns processes using ``fork()``. Care must be taken when using instances of :class:`~pymongo.mongo_client.MongoClient` with ``fork()``. Specifically, instances of MongoClient must not be copied from a parent process to a child process. Instead, the parent process and each child process must create their own instances of MongoClient. For example:: # Each process creates its own instance of MongoClient. def func(): db = pymongo.MongoClient().mydb # Do something with db. proc = multiprocessing.Process(target=func) proc.start() **Never do this**:: client = pymongo.MongoClient() # Each child process attempts to copy a global MongoClient # created in the parent process. Never do this. def func(): db = client.mydb # Do something with db. proc = multiprocessing.Process(target=func) proc.start() Instances of MongoClient copied from the parent process have a high probability of deadlock in the child process due to :ref:`inherent incompatibilities between fork(), threads, and locks `. PyMongo will attempt to issue a warning if there is a chance of this deadlock occurring. .. seealso:: :ref:`pymongo-fork-safe` mongodb-mongo-python-driver-509e9b7/doc/index.rst000066400000000000000000000067321462766011000220530ustar00rootroot00000000000000PyMongo |release| Documentation =============================== Overview -------- **PyMongo** is a Python distribution containing tools for working with `MongoDB `_, and is the recommended way to work with MongoDB from Python. This documentation attempts to explain everything you need to know to use **PyMongo**. .. todo:: a list of PyMongo's features :doc:`installation` Instructions on how to get the distribution. :doc:`tutorial` Start here for a quick overview. :doc:`examples/index` Examples of how to perform specific tasks. :doc:`atlas` Using PyMongo with MongoDB Atlas. :doc:`examples/tls` Using PyMongo with TLS / SSL. :doc:`examples/encryption` Using PyMongo with In-Use Encryption. :doc:`examples/type_hints` Using PyMongo with type hints. :doc:`examples/logging` Using PyMongo's logging capabilities. :doc:`faq` Some questions that come up often. :doc:`migrate-to-pymongo4` A PyMongo 3.x to 4.x migration guide. :doc:`python3` Frequently asked questions about python 3 support. :doc:`compatibility-policy` Explanation of deprecations, and how to keep pace with changes in PyMongo's API. :doc:`api/index` The complete API documentation, organized by module. :doc:`tools` A listing of Python tools and libraries that have been written for MongoDB. :doc:`developer/index` Developer guide for contributors to PyMongo. :doc:`common-issues` Common issues encountered when using PyMongo. Getting Help ------------ If you're having trouble or have questions about PyMongo, ask your question on our `MongoDB Community Forum `_. You may also want to consider a `commercial support subscription `_. Once you get an answer, it'd be great if you could work it back into this documentation and contribute! Issues ------ All issues should be reported (and can be tracked / voted for / commented on) at the main `MongoDB JIRA bug tracker `_, in the "Python Driver" project. Feature Requests / Feedback --------------------------- Use our `feedback engine `_ to send us feature requests and general feedback about PyMongo. Contributing ------------ **PyMongo** has a large :doc:`community ` and contributions are always encouraged. Contributions can be as simple as minor tweaks to this documentation. To contribute, fork the project on `GitHub `_ and send a pull request. Changes ------- See the :doc:`changelog` for a full list of changes to PyMongo. For older versions of the documentation please see the `archive list `_. About This Documentation ------------------------ This documentation is generated using the `Sphinx `_ documentation generator. The source files for the documentation are located in the *doc/* directory of the **PyMongo** distribution. To generate the docs locally run the following command from the root directory of the **PyMongo** source: .. code-block:: bash $ pip install tox $ tox -m doc Indices and tables ------------------ * :ref:`genindex` * :ref:`modindex` * :ref:`search` .. toctree:: :hidden: atlas installation tutorial examples/index faq compatibility-policy api/index tools contributors changelog python3 migrate-to-pymongo4 developer/index common-issues mongodb-mongo-python-driver-509e9b7/doc/installation.rst000066400000000000000000000151251462766011000234410ustar00rootroot00000000000000Installing / Upgrading ====================== .. highlight:: bash **PyMongo** is in the `Python Package Index `_. .. warning:: **Do not install the "bson" package from pypi.** PyMongo comes with its own bson package; doing "pip install bson" or "easy_install bson" installs a third-party package that is incompatible with PyMongo. Installing with pip ------------------- We recommend using `pip `_ to install pymongo on all platforms:: $ python3 -m pip install pymongo To get a specific version of pymongo:: $ python3 -m pip install pymongo==3.5.1 To upgrade using pip:: $ python3 -m pip install --upgrade pymongo Dependencies ------------ PyMongo supports CPython 3.7+ and PyPy3.7+. Required dependencies ..................... Support for mongodb+srv:// URIs requires `dnspython `_ .. _optional-deps: Optional dependencies ..................... GSSAPI authentication requires `pykerberos `_ on Unix or `WinKerberos `_ on Windows. The correct dependency can be installed automatically along with PyMongo:: $ python3 -m pip install "pymongo[gssapi]" :ref:`MONGODB-AWS` authentication requires `pymongo-auth-aws `_:: $ python3 -m pip install "pymongo[aws]" :ref:`OCSP` requires `PyOpenSSL `_, `requests `_ and `service_identity `_:: $ python3 -m pip install "pymongo[ocsp]" Wire protocol compression with snappy requires `python-snappy `_:: $ python3 -m pip install "pymongo[snappy]" Wire protocol compression with zstandard requires `zstandard `_:: $ python3 -m pip install "pymongo[zstd]" :ref:`Client-Side Field Level Encryption` requires `pymongocrypt `_ and `pymongo-auth-aws `_:: $ python3 -m pip install "pymongo[encryption]" You can install all dependencies automatically with the following command:: $ python3 -m pip install "pymongo[gssapi,aws,ocsp,snappy,zstd,encryption]" Installing from source ---------------------- If you'd rather install directly from the source (i.e. to stay on the bleeding edge), install the C extension dependencies then check out the latest source from GitHub and install the driver from the resulting tree:: $ git clone https://github.com/mongodb/mongo-python-driver.git pymongo $ cd pymongo/ $ pip install . Installing from source on Unix .............................. To build the optional C extensions on Linux or another non-macOS Unix you must have the GNU C compiler (gcc) installed. Depending on your flavor of Unix (or Linux distribution) you may also need a python development package that provides the necessary header files for your version of Python. The package name may vary from distro to distro. Debian and Ubuntu users should issue the following command:: $ sudo apt-get install build-essential python-dev Users of Red Hat based distributions (RHEL, CentOS, Amazon Linux, Oracle Linux, Fedora, etc.) should issue the following command:: $ sudo yum install gcc python-devel Installing from source on macOS / OSX ..................................... If you want to install PyMongo with C extensions from source you will need the command line developer tools. On modern versions of macOS they can be installed by running the following in Terminal (found in /Applications/Utilities/):: xcode-select --install For older versions of OSX you may need Xcode. See the notes below for various OSX and Xcode versions. **Snow Leopard (10.6)** - Xcode 3 with 'UNIX Development Support'. **Snow Leopard Xcode 4**: The Python versions shipped with OSX 10.6.x are universal binaries. They support i386, PPC, and x86_64. Xcode 4 removed support for PPC, causing the distutils version shipped with Apple's builds of Python to fail to build the C extensions if you have Xcode 4 installed. There is a workaround:: # For some Python builds from python.org $ env ARCHFLAGS='-arch i386 -arch x86_64' python -m easy_install pymongo See `http://bugs.python.org/issue11623 `_ for a more detailed explanation. **Lion (10.7) and newer** - PyMongo's C extensions can be built against versions of Python 3.7+ downloaded from python.org. In all cases Xcode must be installed with 'UNIX Development Support'. **Xcode 5.1**: Starting with version 5.1 the version of clang that ships with Xcode throws an error when it encounters compiler flags it doesn't recognize. This may cause C extension builds to fail with an error similar to:: clang: error: unknown argument: '-mno-fused-madd' [-Wunused-command-line-argument-hard-error-in-future] There are workarounds:: # Apple specified workaround for Xcode 5.1 # easy_install $ ARCHFLAGS=-Wno-error=unused-command-line-argument-hard-error-in-future easy_install pymongo # or pip $ ARCHFLAGS=-Wno-error=unused-command-line-argument-hard-error-in-future pip install pymongo # Alternative workaround using CFLAGS # easy_install $ CFLAGS=-Qunused-arguments easy_install pymongo # or pip $ CFLAGS=-Qunused-arguments pip install pymongo Installing from source on Windows ................................. If you want to install PyMongo with C extensions from source the following requirements apply to both CPython and ActiveState's ActivePython: Windows ~~~~~~~ Install Visual Studio 2015+. .. _install-no-c: Installing Without C Extensions ------------------------------- By default, the driver attempts to build and install optional C extensions (used for increasing performance) when it is installed. If any extension fails to build the driver will be installed anyway but a warning will be printed. If you wish to install PyMongo without the C extensions, even if the extensions build properly, it can be done using a command line option to *pip install*:: $ NO_EXT=1 python -m pip install . Installing a beta or release candidate -------------------------------------- MongoDB, Inc. may occasionally tag a beta or release candidate for testing by the community before final release. These releases will not be uploaded to pypi but can be found on the `GitHub tags page `_. They can be installed by passing the full URL for the tag to pip:: $ python3 -m pip install https://github.com/mongodb/mongo-python-driver/archive/4.4.0b0.tar.gz mongodb-mongo-python-driver-509e9b7/doc/make.bat000066400000000000000000000014331462766011000216100ustar00rootroot00000000000000@ECHO OFF pushd %~dp0 REM Command file for Sphinx documentation if "%SPHINXBUILD%" == "" ( set SPHINXBUILD=sphinx-build ) set SOURCEDIR=. set BUILDDIR=_build if "%1" == "" goto help %SPHINXBUILD% >NUL 2>NUL if errorlevel 9009 ( echo. echo.The 'sphinx-build' command was not found. Make sure you have Sphinx echo.installed, then set the SPHINXBUILD environment variable to point echo.to the full path of the 'sphinx-build' executable. Alternatively you echo.may add the Sphinx directory to PATH. echo. echo.If you don't have Sphinx installed, grab it from echo.http://sphinx-doc.org/ exit /b 1 ) %SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% goto end :help %SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% :end popd mongodb-mongo-python-driver-509e9b7/doc/migrate-to-pymongo4.rst000066400000000000000000001123741462766011000245660ustar00rootroot00000000000000.. _pymongo4-migration-guide: PyMongo 4 Migration Guide ========================= .. testsetup:: from pymongo import MongoClient, ReadPreference client = MongoClient() database = client.my_database collection = database.my_collection PyMongo 4.0 brings a number of improvements as well as some backward breaking changes. This guide provides a roadmap for migrating an existing application from PyMongo 3.x to 4.x or writing libraries that will work with both PyMongo 3.x and 4.x. PyMongo 3 --------- The first step in any successful migration involves upgrading to, or requiring, at least that latest version of PyMongo 3.x. If your project has a requirements.txt file, add the line "pymongo >= 3.12, < 4.0" until you have completely migrated to PyMongo 4. Most of the key new methods and options from PyMongo 4.0 are backported in PyMongo 3.12 making migration much easier. .. note:: Users of PyMongo 2.X who wish to upgrade to 4.x must first upgrade to PyMongo 3.x by following the `PyMongo 3 Migration Guide `_. Python 3.6+ ----------- PyMongo 4.0 drops support for Python 2.7, 3.4, and 3.5. Users who wish to upgrade to 4.x must first upgrade to Python 3.6.2+. Users upgrading from Python 2 should consult the :doc:`python3`. Enable Deprecation Warnings --------------------------- :exc:`DeprecationWarning` is raised by most methods removed in PyMongo 4.0. Make sure you enable runtime warnings to see where deprecated functions and methods are being used in your application:: python -Wd Warnings can also be changed to errors:: python -Wd -Werror .. note:: Not all deprecated features raise :exc:`DeprecationWarning` when used. See `Removed features with no migration path`_. MongoReplicaSetClient --------------------- Removed :class:`~pymongo.mongo_replica_set_client.MongoReplicaSetClient`. Since PyMongo 3.0, ``MongoReplicaSetClient`` has been identical to :class:`pymongo.mongo_client.MongoClient`. Applications can simply replace ``MongoReplicaSetClient`` with :class:`pymongo.mongo_client.MongoClient` and get the same behavior. MongoClient ----------- .. _pymongo4-migration-direct-connection: ``directConnection`` defaults to False ...................................... ``directConnection`` URI option and keyword argument to :class:`~pymongo .mongo_client.MongoClient` defaults to ``False`` instead of ``None``, allowing for the automatic discovery of replica sets. This means that if you want a direct connection to a single server you must pass ``directConnection=True`` as a URI option or keyword argument. If you see any :exc:`~pymongo.errors.ServerSelectionTimeoutError`'s after upgrading from PyMongo 3 to 4.x, you likely need to add ``directConnection=True`` when creating the client. Here are some example errors: .. code-block:: pymongo.errors.ServerSelectionTimeoutError: mongo_node2: [Errno 8] nodename nor servname provided, or not known,mongo_node1:27017 .. code-block:: ServerSelectionTimeoutError: No servers match selector "Primary()", Timeout: 30s, Topology Description: ... Additionally, the "isWritablePrimary" attribute of a hello command sent back by the server will always be True if ``directConnection=False``:: >>> client.admin.command('hello')['isWritablePrimary'] True The waitQueueMultiple parameter is removed .......................................... Removed the ``waitQueueMultiple`` keyword argument to :class:`~pymongo.mongo_client.MongoClient` and removed :exc:`pymongo.errors.ExceededMaxWaiters`. Instead of using ``waitQueueMultiple`` to bound queuing, limit the size of the thread pool in your application. The socketKeepAlive parameter is removed .......................................... Removed the ``socketKeepAlive`` keyword argument to :class:`~pymongo.mongo_client.MongoClient`. PyMongo now always enables TCP keepalive. For more information see the `documentation `_. Renamed URI options ................... Several deprecated URI options have been renamed to the standardized option names defined in the `URI options specification `_. The old option names and their renamed equivalents are summarized in the table below. Some renamed options have different semantics from the option being replaced as noted in the 'Migration Notes' column. +--------------------+-------------------------------+--------------------------------------------------------+ | Old URI Option | Renamed URI Option | Migration Notes | +====================+===============================+========================================================+ | ssl_pem_passphrase | tlsCertificateKeyFilePassword | - | +--------------------+-------------------------------+--------------------------------------------------------+ | ssl_ca_certs | tlsCAFile | - | +--------------------+-------------------------------+--------------------------------------------------------+ | ssl_crlfile | tlsCRLFile | - | +--------------------+-------------------------------+--------------------------------------------------------+ | ssl_match_hostname | tlsAllowInvalidHostnames | ``ssl_match_hostname=True`` is equivalent to | | | | ``tlsAllowInvalidHostnames=False`` and vice-versa. | +--------------------+-------------------------------+--------------------------------------------------------+ | ssl_cert_reqs | tlsAllowInvalidCertificates | Instead of ``ssl.CERT_NONE``, ``ssl.CERT_OPTIONAL`` | | | | and ``ssl.CERT_REQUIRED``, the new option expects | | | | a boolean value - ``True`` is equivalent to | | | | ``ssl.CERT_NONE``, while ``False`` is equivalent to | | | | ``ssl.CERT_REQUIRED``. | +--------------------+-------------------------------+--------------------------------------------------------+ | ssl_certfile | tlsCertificateKeyFile | Instead of using ``ssl_certfile`` and ``ssl_keyfile`` | | | | to specify the certificate and private key files | +--------------------+ | respectively, use ``tlsCertificateKeyFile`` to pass | | ssl_keyfile | | a single file containing both the client certificate | | | | and the private key. | +--------------------+-------------------------------+--------------------------------------------------------+ | j | journal | - | +--------------------+-------------------------------+--------------------------------------------------------+ | wtimeout | wTimeoutMS | - | +--------------------+-------------------------------+--------------------------------------------------------+ MongoClient.fsync is removed ............................ Removed :meth:`pymongo.mongo_client.MongoClient.fsync`. Run the `fsync command`_ directly with :meth:`~pymongo.database.Database.command` instead. For example:: client.admin.command('fsync', lock=True) .. _fsync command: https://mongodb.com/docs/manual/reference/command/fsync/ MongoClient.unlock is removed ............................. Removed :meth:`pymongo.mongo_client.MongoClient.unlock`. Run the `fsyncUnlock command`_ directly with :meth:`~pymongo.database.Database.command` instead. For example:: client.admin.command('fsyncUnlock') .. _fsyncUnlock command: https://mongodb.com/docs/manual/reference/command/fsyncUnlock/ MongoClient.is_locked is removed ................................ Removed :attr:`pymongo.mongo_client.MongoClient.is_locked`. Run the `currentOp command`_ directly with :meth:`~pymongo.database.Database.command` instead. For example:: is_locked = client.admin.command('currentOp').get('fsyncLock') .. _currentOp command: https://mongodb.com/docs/manual/reference/command/currentOp/ MongoClient.database_names is removed ..................................... Removed :meth:`pymongo.mongo_client.MongoClient.database_names`. Use :meth:`~pymongo.mongo_client.MongoClient.list_database_names` instead. Code like this:: names = client.database_names() can be changed to this:: names = client.list_database_names() MongoClient.max_bson_size/max_message_size/max_write_batch_size are removed ........................................................................... Removed :attr:`pymongo.mongo_client.MongoClient.max_bson_size`, :attr:`pymongo.mongo_client.MongoClient.max_message_size`, and :attr:`pymongo.mongo_client.MongoClient.max_write_batch_size`. These helpers were incorrect when in ``loadBalanced=true mode`` and ambiguous in clusters with mixed versions. Use the `hello command`_ to get the authoritative value from the remote server instead. Code like this:: max_bson_size = client.max_bson_size max_message_size = client.max_message_size max_write_batch_size = client.max_write_batch_size can be changed to this:: doc = client.admin.command('hello') max_bson_size = doc['maxBsonObjectSize'] max_message_size = doc['maxMessageSizeBytes'] max_write_batch_size = doc['maxWriteBatchSize'] .. _hello command: https://mongodb.com/docs/manual/reference/command/hello/ MongoClient.event_listeners and other configuration option helpers are removed .............................................................................. The following client configuration option helpers are removed: - :attr:`pymongo.mongo_client.MongoClient.event_listeners`. - :attr:`pymongo.mongo_client.MongoClient.max_pool_size`. - :attr:`pymongo.mongo_client.MongoClient.max_idle_time_ms`. - :attr:`pymongo.mongo_client.MongoClient.local_threshold_ms`. - :attr:`pymongo.mongo_client.MongoClient.server_selection_timeout`. - :attr:`pymongo.mongo_client.MongoClient.retry_writes`. - :attr:`pymongo.mongo_client.MongoClient.retry_reads`. These helpers have been replaced by :attr:`pymongo.mongo_client.MongoClient.options`. Code like this:: client.event_listeners client.local_threshold_ms client.server_selection_timeout client.max_pool_size client.min_pool_size client.max_idle_time_ms can be changed to this:: client.options.event_listeners client.options.local_threshold_ms client.options.server_selection_timeout client.options.pool_options.max_pool_size client.options.pool_options.min_pool_size client.options.pool_options.max_idle_time_seconds .. _tz_aware_default_change: ``tz_aware`` defaults to ``False`` .................................. The ``tz_aware`` argument to :class:`~bson.json_util.JSONOptions` now defaults to ``False`` instead of ``True``. :meth:`bson.json_util.loads` now decodes datetime as naive by default:: >>> from bson import json_util >>> s = '{"dt": {"$date": "2022-05-09T17:54:00Z"}}' >>> json_util.loads(s) {'dt': datetime.datetime(2022, 5, 9, 17, 54)} To retain the PyMongo 3 behavior set ``tz_aware=True``, for example:: >>> from bson import json_util >>> opts = json_util.JSONOptions(tz_aware=True) >>> s = '{"dt": {"$date": "2022-05-09T17:54:00Z"}}' >>> json_util.loads(s, json_options=opts) {'dt': datetime.datetime(2022, 5, 9, 17, 54, tzinfo=)} This change was made to match the default behavior of :class:`~bson.codec_options.CodecOptions` and :class:`bson.decode`. MongoClient cannot execute operations after ``close()`` ....................................................... :class:`~pymongo.mongo_client.MongoClient` cannot execute any operations after being closed. The previous behavior would simply reconnect. However, now you must create a new instance. MongoClient raises exception when given more than one URI ......................................................... :class:`~pymongo.mongo_client.MongoClient` now raises a :exc:`~pymongo.errors.ConfigurationError` when more than one URI is passed into the ``hosts`` argument. MongoClient raises exception when given unescaped percent sign in login info ............................................................................ :class:`~pymongo.mongo_client.MongoClient` now raises an :exc:`~pymongo.errors.InvalidURI` exception when it encounters unescaped percent signs in username and password. Database -------- Database.authenticate and Database.logout are removed ..................................................... Removed :meth:`pymongo.database.Database.authenticate` and :meth:`pymongo.database.Database.logout`. Authenticating multiple users on the same client conflicts with support for logical sessions in MongoDB 3.6+. To authenticate as multiple users, create multiple instances of :class:`~pymongo.mongo_client.MongoClient`. Code like this:: client = MongoClient() client.admin.authenticate('user1', 'pass1') client.admin.authenticate('user2', 'pass2') can be changed to this:: client1 = MongoClient(username='user1', password='pass1') client2 = MongoClient(username='user2', password='pass2') Alternatively, create a single user that contains all the authentication privileges required by your application. Database.collection_names is removed .................................... Removed :meth:`pymongo.database.Database.collection_names`. Use :meth:`~pymongo.database.Database.list_collection_names` instead. Code like this:: names = client.db.collection_names() non_system_names = client.db.collection_names(include_system_collections=False) can be changed to this:: names = client.db.list_collection_names() non_system_names = client.db.list_collection_names(filter={"name": {"$regex": "^(?!system\\.)"}}) Database.current_op is removed .............................. Removed :meth:`pymongo.database.Database.current_op`. Use :meth:`~pymongo.database.Database.aggregate` instead with the `$currentOp aggregation pipeline stage`_. Code like this:: ops = client.admin.current_op()['inprog'] can be changed to this:: ops = list(client.admin.aggregate([{'$currentOp': {}}])) .. _$currentOp aggregation pipeline stage: https://mongodb.com/docs/manual/reference/operator/aggregation/currentOp/ Database.add_user is removed ............................ Removed :meth:`pymongo.database.Database.add_user` which was deprecated in PyMongo 3.6. Use the `createUser command`_ or `updateUser command`_ instead. To create a user:: db.command("createUser", "admin", pwd="password", roles=["dbAdmin"]) To create a read-only user:: db.command("createUser", "user", pwd="password", roles=["read"]) To change a password:: db.command("updateUser", "user", pwd="newpassword") Or change roles:: db.command("updateUser", "user", roles=["readWrite"]) .. _createUser command: https://mongodb.com/docs/manual/reference/command/createUser/ .. _updateUser command: https://mongodb.com/docs/manual/reference/command/updateUser/ Database.remove_user is removed ............................... Removed :meth:`pymongo.database.Database.remove_user` which was deprecated in PyMongo 3.6. Use the `dropUser command`_ instead:: db.command("dropUser", "user") .. _dropUser command: https://mongodb.com/docs/manual/reference/command/createUser/ Database.profiling_level is removed ................................... Removed :meth:`pymongo.database.Database.profiling_level` which was deprecated in PyMongo 3.12. Use the `profile command`_ instead. Code like this:: level = db.profiling_level() Can be changed to this:: profile = db.command('profile', -1) level = profile['was'] .. _profile command: https://mongodb.com/docs/manual/reference/command/profile/ Database.set_profiling_level is removed ....................................... Removed :meth:`pymongo.database.Database.set_profiling_level` which was deprecated in PyMongo 3.12. Use the `profile command`_ instead. Code like this:: db.set_profiling_level(pymongo.ALL, filter={'op': 'query'}) Can be changed to this:: res = db.command('profile', 2, filter={'op': 'query'}) Database.profiling_info is removed .................................. Removed :meth:`pymongo.database.Database.profiling_info` which was deprecated in PyMongo 3.12. Query the `'system.profile' collection`_ instead. Code like this:: profiling_info = db.profiling_info() Can be changed to this:: profiling_info = list(db['system.profile'].find()) .. _'system.profile' collection: https://mongodb.com/docs/manual/reference/database-profiler/ Database.__bool__ raises NotImplementedError ............................................ :class:`~pymongo.database.Database` now raises an error upon evaluating as a Boolean. Code like this:: if database: Can be changed to this:: if database is not None: You must now explicitly compare with None. Collection ---------- The useCursor option for Collection.aggregate is removed ........................................................ Removed the ``useCursor`` option for :meth:`~pymongo.collection.Collection.aggregate` which was deprecated in PyMongo 3.6. The option was only necessary when upgrading from MongoDB 2.4 to MongoDB 2.6. Collection.insert is removed ............................ Removed :meth:`pymongo.collection.Collection.insert`. Use :meth:`~pymongo.collection.Collection.insert_one` or :meth:`~pymongo.collection.Collection.insert_many` instead. Code like this:: collection.insert({'doc': 1}) collection.insert([{'doc': 2}, {'doc': 3}]) Can be changed to this:: collection.insert_one({'my': 'document'}) collection.insert_many([{'doc': 2}, {'doc': 3}]) Collection.save is removed .......................... Removed :meth:`pymongo.collection.Collection.save`. Applications will get better performance using :meth:`~pymongo.collection.Collection.insert_one` to insert a new document and :meth:`~pymongo.collection.Collection.update_one` to update an existing document. Code like this:: doc = collection.find_one({"_id": "some id"}) doc["some field"] = db.collection.save(doc) Can be changed to this:: result = collection.update_one({"_id": "some id"}, {"$set": {"some field": }}) If performance is not a concern and refactoring is untenable, ``save`` can be implemented like so:: def save(doc): if '_id' in doc: collection.replace_one({'_id': doc['_id']}, doc, upsert=True) return doc['_id'] else: res = collection.insert_one(doc) return res.inserted_id Collection.update is removed ............................ Removed :meth:`pymongo.collection.Collection.update`. Use :meth:`~pymongo.collection.Collection.update_one` to update a single document or :meth:`~pymongo.collection.Collection.update_many` to update multiple documents. Code like this:: collection.update({}, {'$set': {'a': 1}}) collection.update({}, {'$set': {'b': 1}}, multi=True) Can be changed to this:: collection.update_one({}, {'$set': {'a': 1}}) collection.update_many({}, {'$set': {'b': 1}}) Collection.remove is removed ............................ Removed :meth:`pymongo.collection.Collection.remove`. Use :meth:`~pymongo.collection.Collection.delete_one` to delete a single document or :meth:`~pymongo.collection.Collection.delete_many` to delete multiple documents. Code like this:: collection.remove({'a': 1}, multi=False) collection.remove({'b': 1}) Can be changed to this:: collection.delete_one({'a': 1}) collection.delete_many({'b': 1}) Collection.find_and_modify is removed ..................................... Removed :meth:`pymongo.collection.Collection.find_and_modify`. Use :meth:`~pymongo.collection.Collection.find_one_and_update`, :meth:`~pymongo.collection.Collection.find_one_and_replace`, or :meth:`~pymongo.collection.Collection.find_one_and_delete` instead. Code like this:: updated_doc = collection.find_and_modify({'a': 1}, {'$set': {'b': 1}}) replaced_doc = collection.find_and_modify({'b': 1}, {'c': 1}) deleted_doc = collection.find_and_modify({'c': 1}, remove=True) Can be changed to this:: updated_doc = collection.find_one_and_update({'a': 1}, {'$set': {'b': 1}}) replaced_doc = collection.find_one_and_replace({'b': 1}, {'c': 1}) deleted_doc = collection.find_one_and_delete({'c': 1}) Collection.count and Cursor.count is removed ............................................ Removed :meth:`pymongo.collection.Collection.count` and :meth:`pymongo.cursor.Cursor.count`. Use :meth:`~pymongo.collection.Collection.count_documents` or :meth:`~pymongo.collection.Collection.estimated_document_count` instead. Code like this:: ntotal = collection.count({}) nmatched = collection.count({'price': {'$gte': 10}}) # Or via the Cursor.count api: ntotal = collection.find({}).count() nmatched = collection.find({'price': {'$gte': 10}}).count() Can be changed to this:: ntotal = collection.estimated_document_count() nmatched = collection.count_documents({'price': {'$gte': 10}}) .. note:: When migrating from :meth:`count` to :meth:`count_documents` the following query operators must be replaced: +-------------+--------------------------------------------------------------+ | Operator | Replacement | +=============+==============================================================+ | $where | `$expr`_ | +-------------+--------------------------------------------------------------+ | $near | `$geoWithin`_ with `$center`_; i.e. | | | ``{'$geoWithin': {'$center': [[,], ]}}`` | +-------------+--------------------------------------------------------------+ | $nearSphere | `$geoWithin`_ with `$centerSphere`_; i.e. | | | ``{'$geoWithin': {'$centerSphere': [[,], ]}}`` | +-------------+--------------------------------------------------------------+ .. _$expr: https://mongodb.com/docs/manual/reference/operator/query/expr/ .. _$geoWithin: https://mongodb.com/docs/manual/reference/operator/query/geoWithin/ .. _$center: https://mongodb.com/docs/manual/reference/operator/query/center/ .. _$centerSphere: https://mongodb.com/docs/manual/reference/operator/query/centerSphere/ Collection.initialize_ordered_bulk_op and initialize_unordered_bulk_op is removed ................................................................................. Removed :meth:`pymongo.collection.Collection.initialize_ordered_bulk_op` and :class:`pymongo.bulk.BulkOperationBuilder`. Use :meth:`pymongo.collection.Collection.bulk_write` instead. Code like this:: batch = coll.initialize_ordered_bulk_op() batch.insert({'a': 1}) batch.find({'a': 1}).update_one({'$set': {'b': 1}}) batch.find({'a': 2}).upsert().replace_one({'b': 2}) batch.find({'a': 3}).remove() result = batch.execute() Can be changed to this:: coll.bulk_write([ InsertOne({'a': 1}), UpdateOne({'a': 1}, {'$set': {'b': 1}}), ReplaceOne({'a': 2}, {'b': 2}, upsert=True), DeleteOne({'a': 3}), ]) Collection.initialize_unordered_bulk_op is removed .................................................. Removed :meth:`pymongo.collection.Collection.initialize_unordered_bulk_op`. Use :meth:`pymongo.collection.Collection.bulk_write` instead. Code like this:: batch = coll.initialize_unordered_bulk_op() batch.insert({'a': 1}) batch.find({'a': 1}).update_one({'$set': {'b': 1}}) batch.find({'a': 2}).upsert().replace_one({'b': 2}) batch.find({'a': 3}).remove() result = batch.execute() Can be changed to this:: coll.bulk_write([ InsertOne({'a': 1}), UpdateOne({'a': 1}, {'$set': {'b': 1}}), ReplaceOne({'a': 2}, {'b': 2}, upsert=True), DeleteOne({'a': 3}), ], ordered=False) Collection.group is removed ........................... Removed :meth:`pymongo.collection.Collection.group`. This method was deprecated in PyMongo 3.5. MongoDB 4.2 removed the group command. Use :meth:`~pymongo.collection.Collection.aggregate` with the ``$group`` stage instead. Collection.map_reduce and Collection.inline_map_reduce are removed .................................................................. Removed :meth:`pymongo.collection.Collection.map_reduce` and :meth:`pymongo.collection.Collection.inline_map_reduce`. Migrate to :meth:`~pymongo.collection.Collection.aggregate` or run the `mapReduce command`_ directly with :meth:`~pymongo.database.Database.command` instead. For more guidance on this migration see: - https://mongodb.com/docs/manual/reference/map-reduce-to-aggregation-pipeline/ - https://mongodb.com/docs/manual/reference/aggregation-commands-comparison/ .. _mapReduce command: https://mongodb.com/docs/manual/reference/command/mapReduce/ Collection.ensure_index is removed .................................. Removed :meth:`pymongo.collection.Collection.ensure_index`. Use :meth:`~pymongo.collection.Collection.create_index` or :meth:`~pymongo.collection.Collection.create_indexes` instead. Note that ``ensure_index`` maintained an in memory cache of recently created indexes whereas the newer methods do not. Applications should avoid frequent calls to :meth:`~pymongo.collection.Collection.create_index` or :meth:`~pymongo.collection.Collection.create_indexes`. Code like this:: def persist(self, document): collection.ensure_index('a', unique=True) collection.insert_one(document) Can be changed to this:: def persist(self, document): if not self.created_index: collection.create_index('a', unique=True) self.created_index = True collection.insert_one(document) Collection.reindex is removed ............................. Removed :meth:`pymongo.collection.Collection.reindex`. Run the `reIndex command`_ directly instead. Code like this:: >>> result = database.my_collection.reindex() can be changed to this:: >>> result = database.command('reIndex', 'my_collection') .. _reIndex command: https://mongodb.com/docs/manual/reference/command/reIndex/ The modifiers parameter is removed .................................. Removed the ``modifiers`` parameter from :meth:`~pymongo.collection.Collection.find`, :meth:`~pymongo.collection.Collection.find_one`, :meth:`~pymongo.collection.Collection.find_raw_batches`, and :meth:`~pymongo.cursor.Cursor`. Pass the options directly to the method instead. Code like this:: cursor = coll.find({}, modifiers={ "$comment": "comment", "$hint": {"_id": 1}, "$min": {"_id": 0}, "$max": {"_id": 6}, "$maxTimeMS": 6000, "$returnKey": False, "$showDiskLoc": False, }) can be changed to this:: cursor = coll.find( {}, comment="comment", hint={"_id": 1}, min={"_id": 0}, max={"_id": 6}, max_time_ms=6000, return_key=False, show_record_id=False, ) The hint parameter is required with min/max ........................................... The ``hint`` option is now required when using ``min`` or ``max`` queries with :meth:`~pymongo.collection.Collection.find` to ensure the query utilizes the correct index. For example, code like this:: cursor = coll.find({}, min={'x', min_value}) can be changed to this:: cursor = coll.find({}, min={'x', min_value}, hint=[('x', ASCENDING)]) Collection.__bool__ raises NotImplementedError .............................................. :class:`~pymongo.collection.Collection` now raises an error upon evaluating as a Boolean. Code like this:: if collection: Can be changed to this:: if collection is not None: You must now explicitly compare with None. Collection.find returns entire document with empty projection ............................................................. Empty projections (eg {} or []) for :meth:`~pymongo.collection.Collection.find`, and :meth:`~pymongo.collection.Collection.find_one` are passed to the server as-is rather than the previous behavior which substituted in a projection of ``{"_id": 1}``. This means that an empty projection will now return the entire document, not just the ``"_id"`` field. To ensure that behavior remains consistent, code like this:: coll.find({}, projection={}) Can be changed to this:: coll.find({}, projection={"_id":1}) SONManipulator is removed ------------------------- Removed :mod:`pymongo.son_manipulator`, :class:`pymongo.son_manipulator.SONManipulator`, :class:`pymongo.son_manipulator.ObjectIdInjector`, :class:`pymongo.son_manipulator.ObjectIdShuffler`, :class:`pymongo.son_manipulator.AutoReference`, :class:`pymongo.son_manipulator.NamespaceInjector`, :meth:`pymongo.database.Database.add_son_manipulator`, :attr:`pymongo.database.Database.outgoing_copying_manipulators`, :attr:`pymongo.database.Database.outgoing_manipulators`, :attr:`pymongo.database.Database.incoming_copying_manipulators`, and :attr:`pymongo.database.Database.incoming_manipulators`. Removed the ``manipulate`` parameter from :meth:`~pymongo.collection.Collection.find`, :meth:`~pymongo.collection.Collection.find_one`, and :meth:`~pymongo.cursor.Cursor`. The :class:`pymongo.son_manipulator.SONManipulator` API has limitations as a technique for transforming your data and was deprecated in PyMongo 3.0. Instead, it is more flexible and straightforward to transform outgoing documents in your own code before passing them to PyMongo, and transform incoming documents after receiving them from PyMongo. Alternatively, if your application uses the ``SONManipulator`` API to convert custom types to BSON, the :class:`~bson.codec_options.TypeCodec` and :class:`~bson.codec_options.TypeRegistry` APIs may be a suitable alternative. For more information, see the :doc:`custom type example `. ``SON().items()`` now returns ``dict_items`` object. ---------------------------------------------------- :meth:`~bson.son.SON.items` now returns a ``dict_items`` object rather than a list. ``SON().iteritems()`` removed. ------------------------------ ``SON.iteritems()`` now removed. Code that looks like this:: for k, v in son.iteritems(): Can now be replaced by code that looks like:: for k, v in son.items(): IsMaster is removed ------------------- Removed :class:`pymongo.ismaster.IsMaster`. Use :class:`pymongo.hello.Hello` instead. NotMasterError is removed ------------------------- Removed :exc:`~pymongo.errors.NotMasterError`. Use :exc:`~pymongo.errors.NotPrimaryError` instead. CertificateError is removed --------------------------- Removed :exc:`~pymongo.errors.CertificateError`. Since PyMongo 3.0 this error is handled internally and is never raised to the application. pymongo.GEOHAYSTACK is removed ------------------------------ Removed :attr:`pymongo.GEOHAYSTACK`. Replace with "geoHaystack" or create a 2d index and use $geoNear or $geoWithin instead. See https://dochub.mongodb.org/core/4.4-deprecate-geoHaystack. UUIDLegacy is removed --------------------- Removed :class:`bson.binary.UUIDLegacy`. Use :meth:`bson.binary.Binary.from_uuid` instead. Code like this:: uu = uuid.uuid4() uuid_legacy = UUIDLegacy(uu) can be changed to this:: uu = uuid.uuid4() uuid_legacy = Binary.from_uuid(uu, PYTHON_LEGACY) Default JSONMode changed from LEGACY to RELAXED ----------------------------------------------- Changed the default JSON encoding representation from legacy to relaxed. The json_mode parameter for :const:`bson.json_util.dumps` now defaults to :const:`~bson.json_util.RELAXED_JSON_OPTIONS`. GridFS changes -------------- .. _removed-gridfs-checksum: disable_md5 parameter is removed ................................ Removed the ``disable_md5`` option for :class:`~gridfs.GridFSBucket` and :class:`~gridfs.GridFS`. GridFS no longer generates checksums. Applications that desire a file digest should implement it outside GridFS and store it with other file metadata. For example:: import hashlib my_db = MongoClient().test fs = GridFSBucket(my_db) with fs.open_upload_stream("test_file") as grid_in: file_data = b'...' sha356 = hashlib.sha256(file_data).hexdigest() grid_in.write(file_data) grid_in.sha356 = sha356 # Set the custom 'sha356' field Note that for large files, the checksum may need to be computed in chunks to avoid the excessive memory needed to load the entire file at once. Removed features with no migration path --------------------------------------- cursor_manager support is removed ................................. Removed :class:`pymongo.cursor_manager.CursorManager`, :mod:`pymongo.cursor_manager`, and :meth:`pymongo.mongo_client.MongoClient.set_cursor_manager`. MongoClient.close_cursor is removed ................................... Removed :meth:`pymongo.mongo_client.MongoClient.close_cursor` and :meth:`pymongo.mongo_client.MongoClient.kill_cursors`. Instead, close cursors with :meth:`pymongo.cursor.Cursor.close` or :meth:`pymongo.command_cursor.CommandCursor.close`. .. _killCursors command: https://mongodb.com/docs/manual/reference/command/killCursors/ Database.eval, Database.system_js, and SystemJS are removed ........................................................... Removed :meth:`~pymongo.database.Database.eval`, :data:`~pymongo.database.Database.system_js` and :class:`~pymongo.database.SystemJS`. The eval command was deprecated in MongoDB 3.0 and removed in MongoDB 4.2. There is no replacement for eval with MongoDB 4.2+. However, on MongoDB <= 4.0, code like this:: >>> result = database.eval('function (x) {return x;}', 3) can be changed to this:: >>> from bson.code import Code >>> result = database.command('eval', Code('function (x) {return x;}'), args=[3]).get('retval') Database.error, Database.last_status, Database.previous_error, and Database.reset_error_history are removed ........................................................................................................... Removed :meth:`pymongo.database.Database.error`, :meth:`pymongo.database.Database.last_status`, :meth:`pymongo.database.Database.previous_error`, and :meth:`pymongo.database.Database.reset_error_history`. These methods are obsolete: all MongoDB write operations use an acknowledged write concern and report their errors by default. These methods were deprecated in PyMongo 2.8. Collection.parallel_scan is removed ................................... Removed :meth:`~pymongo.collection.Collection.parallel_scan`. MongoDB 4.2 removed the parallelCollectionScan command. There is no replacement. pymongo.message helpers are removed ................................... Removed :meth:`pymongo.message.delete`, :meth:`pymongo.message.get_more`, :meth:`pymongo.message.insert`, :meth:`pymongo.message.kill_cursors`, :meth:`pymongo.message.query`, and :meth:`pymongo.message.update`. Name is a required argument for pymongo.driver_info.DriverInfo .............................................................. ``name`` is now a required argument for the :class:`pymongo.driver_info.DriverInfo` class. DBRef BSON/JSON decoding behavior ................................. Changed the BSON and JSON decoding behavior of :class:`~bson.dbref.DBRef` to match the behavior outlined in the `DBRef specification`_ version 1.0. Specifically, PyMongo now only decodes a subdocument into a :class:`~bson.dbref.DBRef` if and only if, it contains both ``$ref`` and ``$id`` fields and the ``$ref``, ``$id``, and ``$db`` fields are of the correct type. Otherwise the document is returned as normal. Previously, any subdocument containing a ``$ref`` field would be decoded as a :class:`~bson.dbref.DBRef`. .. _DBRef specification: https://github.com/mongodb/specifications/blob/5a8c8d7/source/dbref.rst Encoding a UUID raises an error by default .......................................... The default ``uuid_representation`` for :class:`~bson.codec_options.CodecOptions`, :class:`~bson.json_util.JSONOptions`, and :class:`~pymongo.mongo_client.MongoClient` has been changed from :data:`bson.binary.UuidRepresentation.PYTHON_LEGACY` to :data:`bson.binary.UuidRepresentation.UNSPECIFIED`. Attempting to encode a :class:`uuid.UUID` instance to BSON or JSON now produces an error by default. If you were using UUIDs previously, you will need to set your ``uuid_representation`` to :data:`bson.binary.UuidRepresentation.PYTHON_LEGACY` to avoid data corruption. If you do not have UUIDs, then you should set :data:`bson.binary.UuidRepresentation.STANDARD`. If you do not explicitly set a value, you will receive an error like this when attempting to encode a :class:`uuid.UUID`:: ValueError: cannot encode native uuid.UUID with UuidRepresentation.UNSPECIFIED. UUIDs can be manually converted... See :ref:`handling-uuid-data-example` for details. Additional BSON classes implement ``__slots__`` ............................................... :class:`~bson.int64.Int64`, :class:`~bson.min_key.MinKey`, :class:`~bson.max_key.MaxKey`, :class:`~bson.timestamp.Timestamp`, :class:`~bson.regex.Regex`, and :class:`~bson.dbref.DBRef` now implement ``__slots__`` to reduce memory usage. This means that their attributes are fixed, and new attributes cannot be added to the object at runtime. mongodb-mongo-python-driver-509e9b7/doc/pydoctheme/000077500000000000000000000000001462766011000223435ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/doc/pydoctheme/static/000077500000000000000000000000001462766011000236325ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/doc/pydoctheme/static/pydoctheme.css000066400000000000000000000052671462766011000265170ustar00rootroot00000000000000@import url("default.css"); body { background-color: white; margin-left: 1em; margin-right: 1em; } div.related { margin-bottom: 1.2em; padding: 0.5em 0; border-top: 1px solid #ccc; margin-top: 0.5em; } div.related a:hover { color: #0095C4; } div.related:first-child { border-top: 0; border-bottom: 1px solid #ccc; } div.sphinxsidebar { background-color: #eeeeee; border-radius: 5px; line-height: 130%; font-size: smaller; } div.sphinxsidebar h3, div.sphinxsidebar h4 { margin-top: 1.5em; } div.sphinxsidebarwrapper > h3:first-child { margin-top: 0.2em; } div.sphinxsidebarwrapper > ul > li > ul > li { margin-bottom: 0.4em; } div.sphinxsidebar a:hover { color: #0095C4; } div.sphinxsidebar input { font-family: 'Lucida Grande',Arial,sans-serif; border: 1px solid #999999; font-size: smaller; border-radius: 3px; } div.sphinxsidebar input[type=text] { max-width: 150px; } div.body { padding: 0 0 0 1.2em; } div.body p { line-height: 140%; } div.body h1, div.body h2, div.body h3, div.body h4, div.body h5, div.body h6 { margin: 0; border: 0; padding: 0.3em 0; } div.body hr { border: 0; background-color: #ccc; height: 1px; } div.body pre { border-radius: 3px; border: 1px solid #ac9; } div.body div.admonition, div.body div.impl-detail { border-radius: 3px; } div.body div.impl-detail > p { margin: 0; } div.body div.seealso { border: 1px solid #dddd66; } div.body a { color: #0072aa; } div.body a:visited { color: #6363bb; } div.body a:hover { color: #00B0E4; } tt, code, pre { font-family: monospace, sans-serif; font-size: 96.5%; } div.body tt, div.body code { border-radius: 3px; } div.body tt.descname, div.body code.descname { font-size: 120%; } div.body tt.xref, div.body a tt, div.body code.xref, div.body a code { font-weight: normal; } .deprecated { border-radius: 3px; } table.docutils { border: 1px solid #ddd; min-width: 20%; border-radius: 3px; margin-top: 10px; margin-bottom: 10px; } table.docutils td, table.docutils th { border: 1px solid #ddd !important; border-radius: 3px; } table p, table li { text-align: left !important; } table.docutils th { background-color: #eee; padding: 0.3em 0.5em; } table.docutils td { background-color: white; padding: 0.3em 0.5em; } table.footnote, table.footnote td { border: 0 !important; } div.footer { line-height: 150%; margin-top: -2em; text-align: right; width: auto; margin-right: 10px; } div.footer a:hover { color: #0095C4; } .refcount { color: #060; } .stableabi { color: #229; } mongodb-mongo-python-driver-509e9b7/doc/pydoctheme/theme.conf000066400000000000000000000010451462766011000243140ustar00rootroot00000000000000[theme] inherit = default stylesheet = pydoctheme.css pygments_style = sphinx [options] bodyfont = 'Lucida Grande', Arial, sans-serif headfont = 'Lucida Grande', Arial, sans-serif footerbgcolor = white footertextcolor = #555555 relbarbgcolor = white relbartextcolor = #666666 relbarlinkcolor = #444444 sidebarbgcolor = white sidebartextcolor = #444444 sidebarlinkcolor = #444444 bgcolor = white textcolor = #222222 linkcolor = #0090c0 visitedlinkcolor = #00608f headtextcolor = #1a1a1a headbgcolor = white headlinkcolor = #aaaaaa googletag = False mongodb-mongo-python-driver-509e9b7/doc/python3.rst000066400000000000000000000107521462766011000223450ustar00rootroot00000000000000Python 3 FAQ ============ What Python 3 versions are supported? ------------------------------------- PyMongo supports CPython 3.7+ and PyPy3.8+. Are there any PyMongo behavior changes with Python 3? ----------------------------------------------------- Only one intentional change. Instances of :class:`bytes` are encoded as BSON type 5 (Binary data) with subtype 0. In Python 3 they are decoded back to :class:`bytes`. In Python 2 they are decoded to :class:`~bson.binary.Binary` with subtype 0. For example, let's insert a :class:`bytes` instance using Python 3 then read it back. Notice the byte string is decoded back to :class:`bytes`:: Python 3.7.9 (v3.7.9:13c94747c7, Aug 15 2020, 01:31:08) [Clang 6.0 (clang-600.0.57)] on darwin Type "help", "copyright", "credits" or "license" for more information. >>> import pymongo >>> c = pymongo.MongoClient() >>> c.test.bintest.insert_one({'binary': b'this is a byte string'}).inserted_id ObjectId('4f9086b1fba5222021000000') >>> c.test.bintest.find_one() {'binary': b'this is a byte string', '_id': ObjectId('4f9086b1fba5222021000000')} Now retrieve the same document in Python 2. Notice the byte string is decoded to :class:`~bson.binary.Binary`:: Python 2.7.6 (default, Feb 26 2014, 10:36:22) [GCC 4.7.3] on linux2 Type "help", "copyright", "credits" or "license" for more information. >>> import pymongo >>> c = pymongo.MongoClient() >>> c.test.bintest.find_one() {u'binary': Binary('this is a byte string', 0), u'_id': ObjectId('4f9086b1fba5222021000000')} There is a similar change in behavior in parsing JSON binary with subtype 0. In Python 3 they are decoded into :class:`bytes`. In Python 2 they are decoded to :class:`~bson.binary.Binary` with subtype 0. For example, let's decode a JSON binary subtype 0 using Python 3. Notice the byte string is decoded to :class:`bytes`:: Python 3.7.9 (v3.7.9:13c94747c7, Aug 15 2020, 01:31:08) [Clang 6.0 (clang-600.0.57)] on darwin Type "help", "copyright", "credits" or "license" for more information. >>> from bson.json_util import loads >>> loads('{"b": {"$binary": "dGhpcyBpcyBhIGJ5dGUgc3RyaW5n", "$type": "00"}}') {'b': b'this is a byte string'} Now decode the same JSON in Python 2 . Notice the byte string is decoded to :class:`~bson.binary.Binary`:: Python 2.7.10 (default, Feb 7 2017, 00:08:15) [GCC 4.2.1 Compatible Apple LLVM 8.0.0 (clang-800.0.34)] on darwin Type "help", "copyright", "credits" or "license" for more information. >>> from bson.json_util import loads >>> loads('{"b": {"$binary": "dGhpcyBpcyBhIGJ5dGUgc3RyaW5n", "$type": "00"}}') {u'b': Binary('this is a byte string', 0)} Why can't I share pickled ObjectIds between some versions of Python 2 and 3? ---------------------------------------------------------------------------- Instances of :class:`~bson.objectid.ObjectId` pickled using Python 2 can always be unpickled using Python 3. If you pickled an ObjectId using Python 2 and want to unpickle it using Python 3 you must pass ``encoding='latin-1'`` to pickle.loads:: Python 2.7.6 (default, Feb 26 2014, 10:36:22) [GCC 4.7.3] on linux2 Type "help", "copyright", "credits" or "license" for more information. >>> import pickle >>> from bson.objectid import ObjectId >>> oid = ObjectId() >>> oid ObjectId('4f919ba2fba5225b84000000') >>> pickle.dumps(oid) 'ccopy_reg\n_reconstructor\np0\n(cbson.objectid\...' Python 3.7.9 (v3.7.9:13c94747c7, Aug 15 2020, 01:31:08) [Clang 6.0 (clang-600.0.57)] on darwin Type "help", "copyright", "credits" or "license" for more information. >>> import pickle >>> pickle.loads(b'ccopy_reg\n_reconstructor\np0\n(cbson.objectid\...', encoding='latin-1') ObjectId('4f919ba2fba5225b84000000') If you need to pickle ObjectIds using Python 3 and unpickle them using Python 2 you must use ``protocol <= 2``:: Python 3.7.9 (v3.7.9:13c94747c7, Aug 15 2020, 01:31:08) [Clang 6.0 (clang-600.0.57)] on darwin Type "help", "copyright", "credits" or "license" for more information. >>> import pickle >>> from bson.objectid import ObjectId >>> oid = ObjectId() >>> oid ObjectId('4f96f20c430ee6bd06000000') >>> pickle.dumps(oid, protocol=2) b'\x80\x02cbson.objectid\nObjectId\nq\x00)\x81q\x01c_codecs\nencode\...' Python 2.7.15 (default, Jun 21 2018, 15:00:48) [GCC 7.3.0] on linux2 Type "help", "copyright", "credits" or "license" for more information. >>> import pickle >>> pickle.loads('\x80\x02cbson.objectid\nObjectId\nq\x00)\x81q\x01c_codecs\nencode\...') ObjectId('4f96f20c430ee6bd06000000') mongodb-mongo-python-driver-509e9b7/doc/static/000077500000000000000000000000001462766011000214715ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/doc/static/periodic-executor-refs.dot000066400000000000000000000005751462766011000265770ustar00rootroot00000000000000digraph "Monitor and PeriodicExecutor" { // Strong references. topology -> server server -> monitor monitor -> executor executor -> "target()" "target()" -> self_ref thread -> "target()" // Weak references edge [style="dashed"]; self_ref -> monitor [curved=true] monitor -> topology executor -> thread _EXECUTORS -> executor } mongodb-mongo-python-driver-509e9b7/doc/static/periodic-executor-refs.png000066400000000000000000001152421462766011000265730ustar00rootroot00000000000000‰PNG  IHDR?{•‡–LsRGB®Îé@IDATxìÜU÷ǯŠÝØ-v'6 "*¶¨ØÝ‰¨¶€…‰ÝÝ-*¢â«‚Šù÷5æ¾Ç÷.»ûlïÌîÌì9ŸÏ<»ÏÄ{wö̹÷žó;“Ap»31 C µxa2Q~AkµÙZk†€>¹`†@+"`ʯ{ÝÚlΔŸ=†€!Ð’´kÉV[£ ”!ð믿º/¿üR·/¾øB?'L˜à~øá‡œí§Ÿ~rþù§ûïÿ«›ÿ>Ùd“¹©¦šÊM9å”9Ÿ3Í4“›e–Yr¶ÙgŸÝÍ?ÿünÐm¾ùæsÓL3MâµÄu™U¸UøçŸÜ'Ÿ|âÞÿ}÷Áè'ß?þøc÷ý÷ßg`iß¾½C!Í9çœnæ™gÎQ\3Î8£*·lEÇwÖ=Qˆ^òùǸ‰'æ(O”é·ß~ë¾úê+=ßß”{-±Än饗Öm©¥–ÒÏ:øSâö9Ü”_ܺÄêcü,¸—^z)³½úê«îçŸÖ£X^^Á,¹ä’n¡…ÊXc³Í6[ä¢,Q‚X›ÔóóÏ?Ï(dó7ß|£u˜uÖYÝj«­æV_}õÌç\sÍyý*¸)¿ @²S † 0~üx÷Øc¹GyD·Ï>ûÌM>ùäjA¡@ØV]uU·Ì2˸駟¾!uªõ&?þø£{çwÜ+¯¼â^~ùeÝF­&õßxã]çÎ݆nè°F› ¦üšºÝÒÈ ðÑG¹aƹ#F¸×^{M•JåЩS'·Æk¸é¦›.s~’¿ Ÿ{î9÷裪’óÍ7µ½k¯½¶Ûn»íÜöÛo¯sˆ j£)¿m·12Œ3Æ]ýõªô°Žæ˜c·õÖ[»­¶ÚÊm°ÁͲ„2õkÔoéÞu×]î¾ûîÓ!=Š¿Gn—]vqMù5ª£í>­ ÷Üs»òÊ+ݨQ£t1¢gÏžjñ¬·ÞznŠ)¦hi€Xla¸Œ%üÛo¿éË`Ÿ}öq]ºtq¬F‡,¦üBÔŠ3r`âòË/w_|±ûî»ïÜ&›lâöÚk/×­[7u+É9ÙþQ~ÿýwwÇw¸k®¹Æ=õÔSn‘EqGy¤Û}÷ÝÝÔSOJ¦üÂBÒÊ1²ÀõdÀ€îÒK/uýõ—Ûo¿ýÜA¤+²ÙçÙ÷Ò0'zÁè4«ØGq„Ûwß}Ý´ÓN[úÂòGMù•ÇÈÎ0*G€áÛ%—\âÎ<óLµì>ø`wÀ¨¿]奨™ù|ýõ×.rƒÖ•î3Î8ÃõéÓGLòÏ­ðS~e§exâ‰'ÔÂÃï …¡ZÜ]RÊ6*f'0upúé§»Aƒ¹•W^Ù]qÅnÅW¬¥–ÆêR jv!sTýúõS×"ˆº8õÔSMñeƒÒwVƱ¬ßxã ÿÃyeø÷ßW}‹ð¨2»À˜„¡eÝ»w×(¬‘vØaÒAû)D™\vÙeîè£VÈ[o½µ÷³ü"í+<Õ0ÌÅ ™XZ,S|ínÜ_°¸_|ñE7nÜ8 ¡{ûí·+®„QZU •hLB§ÜM7ÝT7”à‚ .8é }k(Ë/¿¼*ÀÅ[LÄ §«DLùU‚’cd!ðøã«s2«7ÝtS"éœ²š“Š¯°×ÜÿýnÝu×u]»vuï¾ûnÙvÙœ_YˆìC`PJ­²Ê*n‹-¶p7Þxc‘“nfߪF.,rH!ˆ•†U¦ˆ˜«K`l·!ÐV™ãc®é™gž 3ڠͽlGí@â ûMÇŽqÃEÄ<Šc» 6àbÁpŠ¡nˆaVmîÓŒcÇŽUß9Bï’.D‚\wÝuK}çwmŽ {‹Bc IüòË/®ƒ°ZEôFš„¶Ý{ï½ê˜U Aidçwv¯¿þº¾° #˜å—†N¶6DÀÍ7ßìÈ“qøá‡Gr3"|ðÁHÊ.W(Q(;í´“éË›¤ãǼ:œÃ¢SHlµ·*¶ÏÈC–øöJL ç]Qù¿Ì%öêÕËÁó×Li×®]ªp`ŒfŽ–¾+$–½­*¶ÏÈB€ÄAÏ>û¬2´díå+«“ Ïà²# Ã3”ì<óÌ£å³bùôÓO+¿±¬¸qdá¢ÂØ·o_÷ä“Oº‡zH“í¹çžê|]ÉreeŸ›ýZ.ÜHÛ#cuà3[::Ô1w¸øâ‹«Ã1¡~ð²Á°¡î+¬°‚[i¥•Ô’fA®Ã6ÚHód—Æw¸o¿ýö‚E™åWÛiLB¢âw—[n¹I;Cúöÿ÷êšAqd\##Èa‡æÎ9ç·å–[ê9Gu”Æ£L^P$(ì¿ÿþª|Þzë-z 7JÅK¹²üyùŸPͯ³Î:ÊP; TôXT7ÜpCæT2ºáþ>'œp‚9r¤Ãñx­µÖr‡z¨c‚\$ðñAaâC ççłҎÊIœ:ážT0öWâãL C ¢ù­~øa‰³j?$¡qZ¾wf šû@û¢l2û¸?õèÝ»wfßÅš „?³ïÄOÔó„þI÷UZ–ÐÇ’.SŽX¥dˆ N:é¤Ì>¾È=t—¬|ëþc=6ìqú?’eNï/T™}|ËUÏ¥œÙ/k¾Q‰XÂZ—lÿw¯afùñ 21J àrcýE)ÙÃY˜ŸIMIÒp/äÅ]xá…Õ¹šäãÖsuË.»¬?ÍsÌ1ºd¤Ò²2üï 0¤¡\sÍ5sÁF o!LË– 6ìCð¯£^XÌÙ‚åJŠKhê,S2ºa½F%¾Ï¼5}S~ÙhØwC äÈeØÆå”Sfê€c4.@,º°²*ÃdwÖYgeæ2ýÅ,~p¹|±J9›(…>##\!1åWÛgä!À¢Ãðáà Oœç[í¿^ée+:\4XeÅI7[X±eU ª˜ ¬XH!IRkY\‡øá³þ#H·É• „a7«ÓC† Ñ!,tóÅü!Yô€ô”SNÑ•_C¢g~øá¢Ö¥)¿¨·rS…®#_}õUQ·‰zëÝZPZ SY±=ûì³5„÷/¬ŒrDzS]’ ÉA9%Mþ_¯ü*-kâĉê~BæîvÛm7U~¸°xax‹JZIWæñPˆ w9Å]H˜{;ðÀÌ8Q[}äû§wܱPUdéÈÄ0*B@A W ó[_ÍIo¼±®JÊüY ‹z© Ù‚:‡rHp÷Ýw»îºk0pàÀœb%Ü.x %œ!üбRYÉ9¯TY²(°2+ŠIëÀêî7ß|£×sL\\ö/\}õÕ0Ú¢à2åKül z­h™ÌgçÎI<”9Ï‘!y ?¥íw…þÉ=„æªÍJuÖ†Yloáw‚í5Ú À<Ž»â^ºÃ³ü(•_¿la?鱤ðË'T %&ÃM,.VWY™ì"2ßË••9±À¬BHðÇc1%[Ã*†KŒXü k:³úœ-8t?öØc®ÿþÙ»CýÎB õ…Ù¹HšËáfùe½ ì«!P‰PËFœ|ËÚãX~²øÐ{º‰,^óÎ;oA+NV}ɮֿ2ü ³-Ç6'Ô¹C)&•Sª¤aÞêûÆ K;òÃuâÔë˜d5RÓf Vs~„—廤4¢^ÌO’SW†ÃN†¹¢FŒòK/½¤s—`…¿˜¹ÀÙgŸ]·üð¸°êzå•Wêj3ó}k¯½vébK©F;f…É~rÀl–“t >lj‰Jx[ +à ¯Š,Ââ·H8] Crû§hµøˆñ"É4E¤BûÝ¡~2o)+çPŽURî0öV“cä!À^âVõÇvÆgüßh!d‹¡¥ß¢Xˆ©¦M2ïXòtq¿)y¼ÖƒÜåâ»ð +-Æ•&az0#§M̵ù¤`¬KªJ¥í/xB‚v¥U‚:˪j”B`³Í6SÇeÈê&L˜P°˜víÚiâ bŽë™W,XxãvšŸ_ã°¶;Ñ!†{‹¯ÃÝbŠsþúë/%^HºïŸY~¾ÇíÓH0øô9Ò=ºnk ™EY¤$,†À?áAB­¿áíJ¶Ð†@ìðî-,D„¡ˆò}üPt uqwá;1Ãm´‘ëÒ¥K(÷kÀ¦üš…¼Ý× °Ü[|u`ƒñ“ „ªðòÍ:ë¬îþûïwRËûÛ6äÓV{³ÝĈ0Ý[| 7Ùdu”~çwV% (;ï¼³f¡K‹â£­6çç{Ü> "P/{K¥MF2ÌÅϤK)[íMA'ZZzÙ[*…6f†Àø¦ElÎ/-=iíh9¼{Ë]wÝyÛ‰!ñP *‘W¶ÂØœ_…@Ùi†@܃½¥š6¥IñÑnS~Õô¾kÄïÞR/{KLšÓ”j˜òk ìvSC >Âvo©¯6ɼڔ_2ûÍjÝÂDáÞÒŠpÚ‚G+öºµ9Ñxö–F,t$¨2•7?¿2ÙaC n„ÉÞ·¶5°>æç×@°íV†@Ýx÷–z’ÕS Zž{î¹zŠˆÍµ6ç›®°Šåh´{K~ˆôXo½õRAeoÊ/¿wíC ¦ÄÁ½e¹å–Ó!ï¾ûnLQª¼Z¦ü*ÇÊÎ4šŠ@Ü[]tQ×¾}{éAÒÅ”_Ò{ÐêßÄŽ…(e–Y&ÊÏ\]Zâ§cL:qroaèk–_ÒŸ(«¿!ÅÞR iQ~fùUÒÛvŽ!ÐD¼{K\œšQ~ãÆsßÿ½²;7šºnms~uÁgÑ#Ðl÷–üvìØÑm½õÖÊòœ,Iÿ›òKRoY]Sé";uêä.¾øb7qâDmkÜ[òAŸgžyVèB -”(Qÿ[x[¢ºË*›f^xá·ÖZk)aèTSMåvß}w7Ë,³¸¸/¿üÒA(j–º24(­ C N~øá-áŸþqÿ÷ÿ箾újM¹Øb‹¹gŸ}ÖÓ›6BÑ:!«ëröÖŸ]l„‡ äÅõBž\„$âݺus:tÐ!1tò&õ#`ʯ~ ­C °üHž/ÿý·î"™ø¡‡êöÙgŸüSìÿh‹t …Ø%†€!P?ù–_~‰ yÉ vòÉ'ç²ÿk@À,¿@³K (ðs~…Êf8<å”SºQ£F¹¥—^ºÐ)¶¯JLùU ˜nD…–ß_ýU°x¬¾»ï¾Û­±Æ7cçwÜá^|ñÅfÜ:”{šò F+ĨñãÇ+]T¡’†ê6Ùd“B‡š¶ï¼óÎs·ß~{Óî_ïMùÕ‹ ]o„„ʯ×»ÓN;:ÔÔ}¬>3¦©u¨çæ¦üêAÏ®5BD€lažïÄOtýúõËÞ›ï(?Üp’*¶Ú›Ôž³z§ü1Ó&æøöÚk/wÚi§eöÅí ÊoìØ±q«VÅõ1˯b¨ìDC Z|<ïSL¡Äƒ Šö†u–>ÿüó;¬Õßÿ½Î’šs¹)¿æànw5r@ø•Þu×]×Ýzë­±e[`´ Ä'QlØ›Ä^³:7øì>þøc×ó^ß~ûmfûî»ïÔ">÷?þÐù»©§žZ·i¦™ÆM;í´nŽ9æpsÎ9§›k®¹ôE/¹: 6ˆ»`ù!(¿Å_<îÕmS?S~m ±†@.(¸—^zɽüò˺½õÖ[î×_Õ“¦Ÿ~z·È"‹¸¹çž[J¥†rCÙ¡èø$‡W„(E®÷ ó“O>q_ýµ†¶=ZË›i¦™ÜJ+­äV[m5ÝV_}õØQHÍ>ûìî°ÃÓ¶ç"–ŒÿŒÒ*ýdµl (%")~øaýD1a‰­°Â ªˆV^ye·ä’Kª•·]X‚‚Ċ¢üàƒÜ«¯¾ê^yåGšHâ{^xa×µkWÝàý3Š«ºnʯ.üìâ´ ÀÄý°aÃt®í©§žR+ n½.]º¸Î;«Ö¬¡èo¿ý¦' ÃQÊ(DVƒQ„;.ŽÌ0à iéŠFµÃ”_£¶ûÄ 4ñ÷ÝwŸZwPGí°ÃM‰@…à‘#GºÛn»M­S˜`¶ß~{õdxlR¦ü*‚ÉNJÿýïÝ!C‘ï¿ÿ¾[o½õÜ~ûí§T\^±@c‹[Ìo¼¡Ãrh¯PàX‡&EnèÅÆ¤ \I®¹æ·ÄK¸C9D•Þ›o¾éæöêÕK颒Öfhîá÷{ýõ×Ý3Ï<£‹%½{÷ÖùÉ#FèBKÒÚÔ¨úšòkÒvŸ¦"ðØc9R.öíÛ×mºé¦ŽUÕ+®¸B•DS+âÍ×Yg³d„¶öèÑí¹æšªC¼MjŠ2å—š®´†B²€ÝvÛÍm¼ñƺBûᇺÁƒ;ï£V蚤ï[j©¥T b ˆ»ÌᇞqÏIzûª¿)¿°´rb‡À“O>©–Ýã?®©áÃÃ]¤Uל§Ÿ~Ú]yå•îºë®s«¬²Š{ûí·Cm>Ý0Kc¤ õf!fÊ/d@­¸x pöÙg«µÇ°§d’l·¢Y²Ç{(D“@†zýõׇÎÚ/|úé§¡•Ù¨‚Lù5 i»OC íã¾ûîëN8áwá…:&ýÍعùæ›Ïa|ðÁ®OŸ>îŒ3Î¥?P¨`ÒÄÂÛ’ÖcVߢ°š»Ë.»èwøðá-kí¶˜³Î:KÃä8à…ÖùçŸ_ìôŠöÆ×¾}{S~¡e'!°ÿþû»{î¹Ç=øàƒnƒ 6ˆè.É/ŸF\dpï™uÖYÝqÇWW£ˆñÍ'b­«À]l–_ƒ€¶ÛD‹C\|øæšâ+5NÐÄ03 Æï±{÷îå/*r ”äKIS~Ië1«oˆu=ꨣܹçžkCÝ6èß=>Œ5»ï¾»#,nÁ,~r‰#X‘IT~FlP¢SíPü`žoÕUWÕaŽÌ¬nšTŽôZ+®¸¢[tÑE5¾¹ò+'¹í¶Ûê¼ßÍ7ßɺ¦ÿKv·@ü‰ dAF § *C‰§Í\¿×^{(M¤Þò3…ÖñEØo´þ’9®ŽRsé0ö¦Þ¶Og}&5†“a ~‚¤¤$ô ©VèœÎzè¡j/mæùÃMù5~»wݰڻÌ2Ëh2r2¶™T€Xºî…^Ðí馛®êzö쉿°KX\°ñùUÝÓvA¬ +Ù9çœãdžÍAªIjF“Ê Ñ“Ì]êês-Š;¡<³o*¿{sÏ4˯¹øÛÝC@«Çbâq¡d’…‰JMàµÞzë©¿aþ*vú[ïlØÛÜM„(¢¢4žzê)ËÕ[¦×™£[k­µ4¢…¹ºvíZ.ÞÁÈLË<#v8!Ì8ãŒîÞ{ïuë«ÙÛX°0)ŒÎÚøó3lذVT| Œ99~>loèСƒ¶GR¬@r{˜ä"ÀÂйR"Xȼ֪bʯU{>¥íf¾ {ñµÓ¬n˜ü‹ÀE]ä`l†„aÔ¨Q-?5`ÊÏ~©CÅǼß{ìázõêå„zʆ֪aÁV[måŽ<òHwÚi§¹{î¹ÇÕº²›& Mù¥©7­-ˆ5•( ˽ÿþûub:©V’¿ÿþÛ 0@Ù¨ßÿ}¥¨?æ˜c,ÅçÿS~­ôkhÁ¶âûGôTñä—e.0L2„8BŠëψ#49Q~¦l2¸µ„-pùxâ‰aÛòLù5f»I3˜i¦™Ü AƒœÐÉ+c <}ä¾ ,.M‚¥‡Òƒ†«{÷înÙe—U¥wú駇úW+”$­IS~Iì5«sM¬ºêªš|ˆ"HLD¢¡K/½T ÕTh .º|׿·ð ++Ÿ80C˜*D ‘Ö—"O,é"(Ü”_ Z‘ñFWG}T‰PYýdŒ0 Îø½ »K¼ µÃŸñ†nÐÈ–ùçŸßþùŽ[(õ±þà l„ÀwuÅÂÛ’ØkVçP`%¥‡¥„ï[ûöí]çÎÕ2Ä:ôi%C½i•…1 4.*lÔ“}’Îí´ÓNšo¤SL•·«øt’Æc]&0<ÎÂÛ*îe;±%`'ä¥JÏDRtÂæ ®‚0æh†ÎÌ©1¥1ª{õÕW¤Ït¯¼òв®|óÍ7•Áœ%ùI°4óÌ3GY²e“×w"á=,{nÌN0å³±êĸýˆˆÀÊB ±1ÌCHòƒEÈÃf²µácÈ'~tSO=ufÃJƒ&ßo’ÓÁ£Ç|å‘°õ“O>Ñ„ì܇œ$>Gñbe­´ÒJšüœcq /¼ðB§_ÂÄ”_Â:̪Ûdà$ÑäèUeŧ°3;¬2ÒQÖ"Xo(̱cǺ®]»êP–¡$É”ØWA“ï„\'ÙɘâZß¼z™òËÄþ5jF€˜b¬8†¬°5{+ý°ÍÀ4í­A,C›Ï|ÆP–ìpIqÁ¡,º=âs× ^ã/4å×xÌ펆@a|:KrøÂNm)Fi)¼V¸!P›nº©Î!âwh=æç=ÆvC "CÇOîàV&b¨¬N2åˆV„!»ï¾»®æ^sÍ5aiåAÀ”_`l·!Ð X=íÓ§8p ¦ÐlFZ垦üZ¥§­‰A€¡ï˜1cÜÈ‘#Sç$VÔÂÛ’ØkVçÔ#4·—vˆ­ö&°Ó¬Ê-€ÀA¤ä ï½÷^,[ûùçŸkX[’EÙ°7––UªÕˆ»ÛË;ï¼ãÈ’d:|S~­þ+³öǸ»½‡L<3 4IS~Ií9«wêˆ³Û 1Íq úªç!0åWzv­!!qv{!ñù’K.aë£/Ú”_ôÛ šˆ«Û ÙààòK²˜òKrïYÝSÔV°5_rÉ%±i+úð’ÿ$ÉbÊ/ɽguo âæö‚Õ‡˜òk‰ÇÏi4¸¹½@·),ÓI‹ðHrïYÝ[†½ÇwœûòË/›ž·#% [„GJ:Òš‘r¼ÛË!CRÞÒÆ5Ïæü‡µÝɨïörÙe—ÛKÍ(æ^hÊ/ûψ-qu{‰-`e*fs~e²Ã†@œ0¶—ÐzÃæüBƒÒ 2€@ÜÜ^ÐäÈnaÃÞÈ µ‚ ðˆ›ÛKø-l\‰¦ü‡µÝɨf³½l¸á†nРAu·#˜ò‹C/X *ðn/NrDòõgŸ}ÖÍ2Ë,UÔ6¾§šò‹oßXÍ ‚x·—F'9zûí·Ý_ýåV^yå‚õJÚNS~Ië1«¯! 4ÃíåÕW_u3Î8câyüüdÊÏ#aŸ†@‚hÛ Êo¥•VrÌ;¦ALù¥¡­ -‰@£Ý^^{íµÔ yy`LùµäÏÆéöòßÿþב´h•UVItÚS~©éJkH«!ÐH·—Ñ£GkL±)¿V{ʬ½†@Lðn/…Ø^‚ ­ÖpøýüóωÏÛ‘ ˆY~ÙhØwC ax·Ïöò÷ß»aƹµ×^ÛuèÐ!ÔÖL3Í4©Yì#6õñ°Â Æ#@]2©íºë®î¡‡rß|ó*),¿?ÿüÓµk×®ñ•Šÿ‡*ñï$«¡!P7ß|Ó]|ñŪànºé&‡å‡ø!ï?üàæ˜cŽ¢×·òö¶rï[Û‹Àý÷߯CÛW\Ñ¡ôˆ¼ðŠ/»Qßÿ}ö¿ö= ³ü²À°¯†@RÀÇï“O>Ñê2´-&X~&…0˯0.¶×ˆ5wÝu—c±còÉKÿ„MùïÆÒȿΎ†@Xn¹å܃>¨s}ÅÂÍØư÷¹çžsüñG[Í­MùEƒ«•jDŽî,wÞygQ÷Vyëµü>þøc·Î:ë¸×_=òö4ú¦ü¸ÝÏÍ7ßÜ]ýõK Ãò{æ™gþ}i¡±ÊÊ”_6öÝH ½{÷v]tQÁš×kùA^ºúê«»©¦šª`ùIÞiÊ/ɽgu7þ‡À!‡âŽ=öØœ!0î/õÎù¡üö¦QLù¥±W­M-‰@ÿþýõ€þùÇ?¾f,¸öƒ>0åW3‚v¡!`4 +¯¼ÒuëÖÍM1ÅzÏz”«¼Ì²°’F1Ë/½jmjYPz·ß~»[k­µƒ &ÔŒC^Ø\Ò’°(‹ðÈGDþÿé§Ÿt®„ù’ü ZŸ_ýU·ß~û­à'Ä„ù£BŸ¼QyPqG(öÉ$ótÓMç¦vZýÌþî÷Í4ÓLúpÎ:ë¬.›~úé ´Îv¥"=¾øâ ÷ù矻^½z9¾þúk·óÎ;ç<Ç¿ÿþ»ãeÃOžGž·ìòÚ·oï¶Øb 7Ûl³éóEœðB -”Ùæ›o¾Œ•™4\[†Õ…Ž7nœn<|ÏÿüÏþ£I~Œ$‰[P.3ÏÄ„nÑEu‹-¶XfCá›4ú!(spl¯¼òŠZl¼d¡²òŠgñÅÏXdsÎ9gdf!%ˆ…Éöá‡f”1NÑ<‹k¬±†Î²Z¼æškªáY¥ª/8™Ê«·Ûû￯+R¬JñcGüÛˆñ /œy xCñ6Dáñà´²`=¢y)øògŸ}¦/l+b®¹ær¼ÉÙ˜òox£JŠæ bDðâ‹/:˜[ØÞxã –‚=sy,@ XPv<ëq,B~“/¼ð‚*êçŸÞ¡1¨3NÙl°Ñ0¢j¢Ä[ù14ä­BÖ(¿Á_æ•V?DÞ~þÇéß~q{(šØÉ5Ýš‡Eȼ/ú‡šá•·QŠ<Äxÿ³‘ß—Iõ`M=ùä“JOEÈÏ8Vøf›m¦Ûúë¯ï˜ßM¢`¹>öØc‹L<2V#H=t>'ê&H¼” ˜õ˜ø¼ù^~ùeÓB‘-½ôÒš3”Û +¬ JŸIãÀ*d®‰1ŸX&¼Ýùc ò†g[wÝuõ“Is“ÂðrÁ=åÖ[oU+œ¼¸;í´“Ûj«­R•/÷ƒ†çVš[n¹E_®L±°(³÷Þ{ëÈÌŸñgs•“ôO=õ”{ôÑGÝO<¡ ðb‚óž7 \“ø"ðË/¿8’Z¿ôÒKºñcz‚E,Â6ÚÈm¼ñÆê0Ûê}‰xøá‡Ý€ÔZpÁÝn»í¦JL+ Ï JpèСjín¿ýö®Âø‡îº¡"VB žèXXtŒûºýúõ î¸ãŽ@~0 ­Ý,:dØÜxã¼Ñy»“J,ÅtéÒ%XÔ@†ÒÑÝ<†%Ë‹]Ÿq™»S,äeˆÈ_ kÛØ*‰gCpà 7bì(6²@<òÈ#QVbXäÊŽ}üñÇÑæ¬(jÃd¼ôéÓ'|ûí·Q6ÐÊŽâƒ\{íµÁ;ìÈj»> K,±DpÌ1Ç2Í£š†_•x yQ}ÙÓ~™6ÿ&))QI‚®]»êóÑ©S§@O¢hYtÊO†?ÁÁˆ™6B†®ÁÉ'ŸÈÂE ±2†/E¡K Ž<òȈU(‹%ÁqÇÈ¢JÂZS¼º2?l½õÖÚ¾m¶Ù&xë­·ŠŸlGrxú駃 6Ø@_{î¹g ‹@9Çëü'\å'Ž:œaËÃ,Á™gžˆß]õ´ËÓŽ€L‚«â÷$}vö\uÕUÌ%&²é q/¿üò@œãñ@F•ÈvġҲ¤F†Sc!I8Ê7õ>ûìˆç¸g°øÌ ©‹Z°Y öØc@eq°?üð@|ƒF€„„éœö‰'žH8Ybê׊J$S°ß~ûé‹‘gCüTë­j}ÊOVj‚m·ÝVÍRY¢×ùœ*Uo£ìú” ÀÉ%—¨å$«Æ:O,®!±nÝ{h·B +¸sW&á"pï½÷ª%8è×SxmÊa,“¶¬Ô2!i&}=}`×–C€ùÁaÆ<ðx`HtJ¹Ë~œ‰yrðd°…¼èà—°Õ€s‰Ø êxV§ü0ßY´Ð0]’¯íèZh%1bD ¾p:—†U(q¤Îjü.‰·Õ:m¹å–6ÌmüL-ˆ#} áªÁ§Ÿ~ZË+W~âɯÚV<øƒë®».`B×Ähz\pÁPv4_ëÃZÕ%&:"@BÑ¡ˆ ­\+¨4L‹à>$á­ß«”a‘™2DÔð>'¶oô&%·’¼µ5¢F;ì0'n#ØOÍLºwïî  ƒDÔÓC5£.­vObGŽéˆ.¿áê›_N[üñ:ÏrñÅ—;ÕŽ G€aïÑGkH0xðà†ßÿ´ÓNÓUéV‹Vi8Ð%n(„Áä“O®"%NË?4¬$ŸßI'äÎ;ï‡yiŽóÒ‚”Vâïõ·ÀÿÙ"V^G²¼I`ƒÎWË´‚»âŠ+ô%ãÏ/wOrËÐD,GwÎ9çh®}Ÿpâ —dE"?æ‘Eö0/WaK§sjÙudNЏ¿b‚#*BÀ2SŠ;°Ò{ˆ‹…Ö¥ s[«Ç|mÅS¬º,L=VhØëO†в!–(%~^‘ºxy„k³‡½0‘0eÀœ ÏG¶0çG(×à '[³…yj†âÔ-*‹Yç9Ã._ÛtŽ<™3%fž9dâæ…èS§I„õXçm™†À©:[èKYÐ ˆ‚…¤ÏóÂÌ#÷Üsöå3GJ;ü³‚.–³N»Ð?ç:êó¸ÐÔ‰BÓcåîÉ|<õç·w饗ê1å@f¶àóÇü}ÒvÎð©ó~q¯˜ˆ'&¼Žï¸;”R~´`hs[Ì«“JïÁ|!åå?„ÅÊõû£T~bõhXL)%<àÔî4/^ùñ€ƒ -,ÎàN’¿0ã¯áYÙtÓMµ,ʃ¬4ПۈO¯üÅjŠìv("”L‚8f3˜0ÿξìHÜЈ¶b± ¹þúëuÁ Eå®kØïRþDöe“…2gMø`¶ÈÈ@_z~DÄ\'§ßUñ=QØ\K„"ž™2ÂüBÔG…sÍmçüüœOR#Ž­07 >f·Ä–­+î¸cpÍÀËž_îÞ=ÅIÊØ€|fÏ庭?^hÞ‘,w cå¨n1Ìá1wYHH“ÈP†)†ë­ùV˜l†ø¡ Ç!Š:@ÅO^å(Ä'*"®ÜYY÷»4iÃQÒ â‹«ûüõì®DM*%ŒÚ™!²ŸÇ˦̗­÷*®-6íåç¡9§Ò{zW)æß‘ì{ëŽþðL«wþ-ÚÌù1/ÆÅ¤žKšôe½õÖ+Zm~Àü8ñ³ã8ꨣtQ èäßÃÏ/ò',pyf—(¥4³²Ì…|ñuÊžƒ+ts?~ùÂü /r®2·tÙe—åŸÒæ&œeEÚuîÜÙÉ0«i¾oÌÇñ‚cÞ1*‹ªüür ý ™ßBH..Ö“úqJÈ_þ¥™ß~­Å„ùeʨDüsYÍ=eB‹öŸ•ܧ–sH¿JßW"m”J¼š<ðI€õa.¤ËËŸH›‡%ÇÛPæ7t•“Éñ?ÿü3ûÔ’ßóïÁ"œW«ƒeÉ‹³ú78‰Õ …øBçæïÃñË Gi&š‹ “ÝH±d1ü¸Ù²“aº“yžœ¢XU»ûî»sö‘N”Å~L8‹û…’œ“"ü‡—‰ ÿ‰p¢²¬¡èIÂÕñ §Ð½8ÆÆª>Îìù/Tž¤Ðª¡òÊíóuiä=ËÕ‰ã(wF¬ôM%ÒFùq‘ÌïhV5™­¤ŒØCŽÐlå (2 +hþmÉÊ,V Ù£$D©ê6ø{ˆÃµzøóÀaI–’ìa ©"A Ö‹?§ÐñRoi†âXjD^àúQHþßwß}k¬j^òËe¸ÂÊ#û‰Œ‘y4ªCÑ¡ze o^?L«Ug—WÍwVR¯(Åc†qž”qvÔucJˆYë¯ô²•kÔ÷¬¦¾¤Ãä÷¸êª«Vv™<ÔE\]t²Sö‚Ç›¹“H i]fò4».LvãuÏÊ.‚S&Ôè~¢5ÿ\Êa¡D¬ÂìC Ré=ÄrÔÉoΗЪ6Ž¡`ˆÓ/ ÅÙ"¶F$ˆõ”½[ $Ì.¡tÎþìˆlá~¬Ö’FɼW›¶Á…'­:Aç;@“3rÅâË)V¦ t?+ÐÙQ2¬Š›KN”«Ãåê–SxHÿ°ºÉªb!§õn‘S ‹\ôSØB=øe¯†â ϾìUx²Ïc%^^6š,Ì×I•RÀ³æ…®Ë¦‚‚yšg%{²íñ|#ü–¸Žgœó¨_¥÷”ÐC½Ö¯:ûº„õÉ 5$²d¬PÚ®öú Ù‘¸Ì@æcC)sX«¤2_¦@âZÁÃÇÊ-9ÄâÐý„¿Ñé<>e"žÿ^!ÒF:L:“ 7Žc=VÓ)VsŸ($Ü>PDd°òLrV¹_¾@ÍD¤õeµ %B[ØpU($\ƒ»Ô›¨BàŠK ç²:‰+^ð¸ˆtN¬¸P®{lQrä ðÂÃîW‚9æ6u¥l¨¥xðPò´‡—g”®&¾^þ|Éñ@]²ÀþxŸ¼Ìèƒ0É|ÅG-ã Â󀂒é}>¸JŠ´œÇ3Ï>ž/OêIhŸøjä}´ë®»2w›i>Þ( ®C‰ñ"$‹"¹FØ'Nñúrƒ+‘~dŸŒh2Þô7ûa„Ê )wÏ«¯¾Zy÷¸ŽºF‘©{àJSìw`Ò—âÊs° Ä„TË©ÐwR9ö-pã‡A2¤‹å„+n$X.„ME!XkÜm&†ȃîÄ vDµì²Ë.Žh¿ŠÞ(„X1gµ\ü!õ÷ѨûÚ}þE@”®k؉?£“a¸«Â½ix»r â&ICñ«<`ÐÆ0‰ÕQ˜"ftÙâpS11@@,eÇËP¬YU€2œo 0,îHƒ“D^V)™ ›RV½)/>¼ „­¨Å÷/\U˜‰š9)&F™T‡Âj.·s ºWP`bŸùÞ¸LÇH츲Þcé©»áV@˜£׳’!¢m.š´£ôœß¤ó&}cå‡ðè|H"CÐç&Ý;ÿ"Àœ%܈ª3ÂT\4¼v„б‘KJ4| ÒH"]~ƒ«Î¤¹ðØ è OòJEÞi´/1ÈeÙèG“\ |%d” N˜› %…f,â~nEšðŸ3(ó7ìßpaÂ$Ý·o_åã,DÈAã£üò &?&Þ pîñƒœÁjà-Ék1”ØðÇ™RÌG±þÿQrà.C6Ý @eãá…;Ž7¬:a¥ÑìtXëð©r½È@IDAT5访1(Œyácù6@|Ùô¹&fUr£h:TÏCƒêÖTèå C#Ýá‰ü^Qô’ߣbÒšn^ø¢ø*¿Bõå¡`Ű!¤œü‚ša­åÇÈ&î6Næt#³ÑAï…ÚÇ}<˜(8¬ÏH%ÎÊÆq„—i°Pü#u¡ qlgê$“ýšr’” B)¥yTx®ýT¬Ûˆ²/ÎÂo•T¤‘dã;9Ox^$±–’ЙÿmV3’¥üŠ¡s/Jfÿƒåó3¡Yp ežyæÑ· Ÿl°ûïþ؉“þ–õ8É’CÁ‡9V¿eÿOžò³z!Quö˃— V5Jψ%}ú(a9zɽ‹eÈÆ …á_B~Ä'/z¦)(k~k~4À'ìä>§ ÏJnÝu×u™§ÑY:”_±Îf8ÁÃÃÜ ÖÿáûO `²…!Vyüw>ÉŒ…‚`ÖàœO¿…Bèä‹}r?Äï«à'ÇP^ÔäÕÙŸÙßÉÑÁ&+e™ÍÿÏuÙ‚…敼ÿä ó™Ü(“Æ#À4ó}<£ƒ.JÇs‹%5=ІÏ6Ï:ÏCI’©³Ñ¯y•y~±$y†yneo\OÚƒìç Î?[|ç÷Äý²OâÉ¡ ™‘J˜Q¹mX´Œñó”nåWé#,>Dj‰?VNgÓé^‘ø€s½òA¹ ¼)<àÙJeœ­œýw¯´yà½u‹r6‰ðJˆÎ›2ï‡WüòË/šL‰) ¯˜¼rbŠg ­á…γE.ì—%J–‘–(é<$¦üêí,oy…È'oÏB]ö>îë-Ã|ë2H‘)”=jx‹’OÞÖ&é@KJÒ(_¦D¹¸“O>9²a+óâþή·ðxÆXX$‰‹VÙÖ /Y/P¾§LLùŵC»wï®V¨äoˆk­^u @¿BÌü Å…›°ŽÒj»”!,Ó [!aÅ÷°…dxÓ–ZZäšš*Ék”–ùJ“ô À\®D»hbw‰xQêõf(>%¿±_mÅŦÕÄ”_L{wVW%#\LkhÕªæäpY0`€.jHŒoh‰Ä«­ ç3׈2FXH!F+‰)¿˜ö6ó½zõÒ·sL«hÕª†¶$ßb® §}IñYÅÕáŸJ$Uö¨÷.’~·’˜ò‹qo3ôÅÙ˜Y“d"ÀBs{Bò«‹8û‘Ôl!¤.ÛŸ•Õ`ITßìj5ôþ±‰ímh«t3¬bcIÑh’,ÍÄzÇ… oLeÄA$ ”º¬`…æ Ö î+- ¶à÷N&Uè\÷jZý²`õT’-iT2D<ÄEñQMØdü\_VµÕÍFC³w¥ú»Y~©î^k\£€ša.¡h(ÀC=TC+]R÷#¾–È¢:²…Pd˜l)Ÿ´¼@°&¡ €Õ„Ó2!]ÌíAÁ7K´  Ãçæ´‹-x¤½‡­}‘#@Ä„¤jpÛl³n¬æÆQñ„$UÏYè(ޤ˜(´;uûlØ›º.µ5†0ÜeµG¼}U÷‚5«”ðÉbB¨e·nÝZÁíÅ<Š=¶ß(‡ÔS·B"ƒpœmÁÅÇÜ^1!þ\r&g¨àŠ—†ýíÒÐkƒ!ÐH Ÿ'ÏÄý÷߯ä'œpBd„a¶ Öó}÷ÝW)Ò}úL:hßS~ö $~ÜP] :T™Gݘ*OBîvØA³¨‘TˆldäÎ5i‹~Ž6ìm‹‹íILäñźz™ j‡^Uråâ¤LÞY8Î=÷Ü– Ú¯\³ü*AÉΉ5á“HÇ“0HÈÖV[måú÷ï뺇Q9’îœvÚinƒ 6pË/¿¼&êܹsE§ºŒVW~æê’’Çëÿ5X_˜Ø‡~=Í2vìXÍiòÒK/¹‹.ºÈõë×/ÍÍ µm¼,Óþ|”Ì”_)tplܸqšH‡Mò²²ð‘ý@c¦UKƒ`Þyçu(¿VX!­M¤]øø¥•§°ÀLùU‚R ÏùôÓO•aÂMMÿõ×_ZËlÅÇŽüÿcØ”ª«ÄDýÁ¬ù4öÛo?wá…¶lžªÁ³ 2˜òË@‘¬/ßÿ½.pAQ|…Z6ËC U»óÎ;Ý6ÛlS¨Ù¶Ï(‹€99—…(ž'¬ºêªêÜ\®vIR~Äš’›¸ ä™Ó[sÍ5Ý<óÌ£,˦ø !eû*EÀ”_¥HÅð<†|ø²áëWL’2ì}ùå—ÝŽ;î¨Äß~ûmNs¾ùæ·ùæ›»£Ž:Ê|òÉîÑGuóÍ7_Î9ö!P-Å5Õ–dç7hm"= I”sx8&3Ï*uïÞ½–òàƒêB¡jÏ<óŒ;î¸ãJ*ûBØ>C ¦ü ¡’ }(=æ¾Èé[H&AùA<€“6þz,Ü<òÈ#ŽŒi‡v˜Z|]ºtÑœ%pð™a!0™¼aÿ}ņU¢•Ó>üðC·Ê*«8¬¨ì.]pÁÝçŸÞ”:UrS,»Í6۬ͩ 塟ÄR“U”)¿dõWÙÚâü»Ç{¨ã3'{çç²6øB«î¾ûî’õ£îD¬²h\ÝÔÝΔŸs¦üR÷X;'ó‹qT~cÆŒq}ûö­y†¿„°™„‹€)?ç ûG„‹³•1L^³Zš½-»ì²JÙαuÖYÇýðÃŽ§g6†Ãþ“Uâ)§œRã<‰õdc.h–Yfq³Î:«~ò}¶ÙfSÿ:’þ°±˜R-3ò?ÿü£¥†ãÔ…ã3Ï<³ÛrË-Õÿ/b[®x¯üf˜a†–k»o°)?D>Qnï½÷^f{ÿý÷«¼ãÇÏÔ¥…bb±š+È=W[m5U`<è(¶lEÇw¬C¯½rDiB‡Òdƒ@û|ùå—Z¦¿!eBºÌ2˸¥—^Z?ù¾Øb‹ôÇ;ï¼ó”„%è…,<æù çÚn»í\·nÝ4½d¡Å}ÖŽ€W~­Lfjʯöç'Ò+qö…©äÅ_Ìl>òa®¹æRE‹ ÎÁ:tP…‡ÒÃ:‹ZX)ôV&n4(`”ò•W^é ˜ÂÕ¥ˆÒeøí7„“2Åç­;”q§NÜÖ[o­Ñ´Á$zàòƒþ¬•_.æçýsVѰ¾ˆk…xÔ¨QŽp/,!”Ê+Ž ²N†¢q~TX¤(n¿}ðÁªù±aQ2T&Qø¶Ûnë6ÞxccdiRgòÌrŒoRu}Ûá¦ü yÖýP÷ß¿»ýöÛ5Œ ‹ +b6˜‰çž{î¬+’ù+Šùo¼Q•úèÑ£õGGûzôè¡ÃÜÙgŸ=™³Z'S~î9¬¹ûî»ÏÝtÓMúùûï¿kln÷îÝ5·,seiˆ °n¡Ú'ƒyÆ6ÚHBÆ·òFí3åרÎ`ÁàꫯvW]u•:ïbõðCgrÎ9çlT5bw†É¼  ³ºçž{4¤lt0Ö,·Ür±«¯U(5˜ò‹º+™ÿ:ãŒ3th‹»ùc÷Ùg] úÞI+‚RœŸyAÀâ‚5xâ‰'êgÒÚbõ=ÛU½óÎ;jÙa½¼ñÆŽ$Ú¸‰N±†¶µàŠ{ /¬3,Æý…•àõÖ[Oÿ¯¥L»Æ(†€ExC¦ÆýÌgíµ×^š?öã?V‹EGn&•!À‚¤¥$gu¸k×®º½û`ge0åW j3§‡“.sX×\s{õÕWÕ¥ Ƥ6ÖZk-7räHÍW‚ŸàJ+­¤„¦dª3©l'óÚKIö•¦üBè?O³Î$=L%ÌW1·gJ/pÿWĆn¨„¦dj8p #‡É›o¾Þ Z¬¤Ž;j¢÷kvNsMùåÀQý?ø¯a0ÄåûùçŸ¯Ñ Õ—dW”C€x {ûí·5|dF×]w]¹Ëìxð½Ä鼕Ŕ_½ë­·j„?B†¸žI¥Ž"íÒ €Pª{hîwß}wWp™’…Ê&çV‹í­±÷á™caãðÃ×\âÖd—ažyæ™ã ! ‡M*C€h¢Vft%S~•=+9gA® ÇÜ)§œâN:餜cöOc` †V…û÷ïߨ $ðnDiÔê–Ÿ {«|xßzë-Í;ÁÜ“)¾*Á‹èô­¶ÚJŸÏ:ë,wóÍ7Gt—ôË1Ë/=}yKˆA%±6s{¬:šÄ,À×_Ýí»ï¾JÞºÐB ŧr1« C^Ä,¿˜uLœ«ÃJ.EÇ<Ê<$þ0+¼L¬“T§•…UÂ^½z92°ÅUvÝuWM‹I]M b˜«K1d²öI€ýe—]–µ7ܯðýaMÁüB¶5èÝ~À·Ýv›Zü­=‰‚pò¥^X9l^Š•ã3ßs×]w)s ”ø$:ÇEä믿VrQ²¦uéÒÅ‘ýíñÇÏ„Á;HîwÞYï !Ö/„yæ™G‹g"fjh¼¨'dù99À š6@_EØôüa ¤8@C‚@žC  2ö7)ƒ€$é ¼àùçŸ/sfm‡{ì±@üƒ×^{-Jû`úé§ößÿLa2ßÈXë ðºÝu× $Â$s_Ê•#J)Ø|ó͉‰ DÉ;í´S ‚O>ùDËáÞ´S2åžzꩺ ~üñÇ@¸öôÿ#<2åHf7=Wh»Q¦XÈ$Z dqHÛ! N‹¥¨÷¦|™:$aQ áUäñÈÜ+¬/¢\™Ð„ 5¬"­œô!0ŒÄ2&eß>ýÁK"ž2gVX¬¥`‘E Ä"Ë\,äz¿le+VL0õÔSB„Ü{ï½øfÎçK¹r$YM b Ö2×IH^ 4[Z;…zKï›­ü„]Y÷¡ü” LXkôþüñǰٴ©“ µ|êŽHü³^»òÊ+Ô%)ó‡z,ì?²’™£ÄÃ.ßÊK<ÃlØ+¿är2Í4Óè)xƇ-·Ür‹£Ü£Ž:*S4ÔM‹.º¨#Ñqùpqª>á„ÜgŸ}¦ÃËÌò¥\9,R@ªºÅ[d.%äªÖÂ3˜=aÎp m¾®þ ©q:†Þë‚ .póÎ;¯¢¸ A^•@yåû-ª{X¹ÉFÀ”_ý7ÿüó«_Ô§Ÿ~š3¿VÁ¥eOa^Š9³JâRQp2/È\`vÚÁrå@¥Ob |…S‹â£QÙÊœ½ˆ ×õÓÿañ9b£ö‘æ.ñù3i‹s®µö{ÛÒ’»ÇV{+è»öíÛ«åeUØ‚"€¶k9yâ‰'´XY2—sz¹rX!Y‹aH¶òóy„e˜žS4~‘$''wI#å™gžÑœu&m ](I¢Z]LùUø0TÃÝ%l\~ (¥ÁƒçÔDÜå—_žÙÇÿçœsŽÖ¡oß¾î¼óÎS-B¹rXÙEòc_'L˜àî¼óN=æ-ÉR,É^ée»‘x*¯§žzJËñ ïG©ÃÆÜH!Üúë¯ßòá[Å0‡§ÕCÛ›ÄO[6¨bòÃ×ÕÌ0o)Š&w]äF !qm äí°ÊëEbWQ.ú/ûÅÕDWW%ñ¹î+W Bºª ÿˆ«L ñɸª\‹ˆb$izÀJ2«³¬‹… ×œ}öÙ(<]¤':/=Ÿ•cd·Ýv Xd`eÜ‹ åƒÅ_\DØ7~üx-KH!ü)¡ÊÔD J<§ôÐËNK,|{ì±iiN­í°ÕÞj“<»ºªÉêf˜‚Â[b‰%T1 X$㛺½pÊb¾ùæSeÄ>¡ÍÄPÏ—ˆ]Ee©r8.saøð©G‘‹îã˜VzÅ‘[ÝTp…yòÉ'™ó 9ä€">ˆzoI-™Qv²hpÀøû¬+­b-cÇŽÕk¸Vœõ:÷Å_à’¶ÐG(\”½Ia^xဗY‹‹)¿j¬!Y4Ž;î¸j.«ø\Ê϶œ*¾0ïÄråà›'Ãݼ«&ý‹"óV' ‹/[°Q¤…_@™ „¢ÐáH÷‰ó¶*Wq´Žô>I/ßN™RIz3ê­ÿ0#6(61Rd?«­Ð&‰ÿ[ŽÛH‘ÓmwƒÀ-hµÕVsLæ‹/cƒîšÌÛ°Et aŠ-,FlPmçC]mº ¯Ü‹/¾Xíåv~š‡O!iC/¹ä’îž"eŽØÉ”€†4¦§UµµÄV{kÀmРAŽøQbWŸ~úéJ°KÂB@æÝl ÍXãæØ\Yb»qÝ"ž»ÕÅ”_ O.!¸S`m@Ý•Iãx饗”Uçjüó¸_£øßB ¬?YÑe#®¡)¿fÞ¶Xƒ¡P'§G)ÿ¸oc—AàÒK/uD@XŠ!?jC LùUƒVÞ¹8üâxŒˆõG¬ì /¼w–ý&²®7”UÄ:3ÔÍ« ó~VVz0åBß’6‘¬np×­½öÚ®OŸ>r“ð€üáä“OÖE ò¨jxüñÇçćw7+©0åR/£ø„öÉ :Ô5ʉӲæ¹îКŰ2‰[+¹0àð`§ ›µ5ÑmíV›Ÿ_ýO¬.™Þ$ŠAKïׯŸÎ ŠsiwKg‘E㮽öZVøê«¯ÔšÆò“H—t6ØZÕh†›ò‹rÈ™˜¿è¢‹?fœJ…ŒÔ²Š•À®Bɇ â¾ÿþ{õ©”8T£§*™ª S~5ÁVåE†Þpà ÊÜÓ‰ 8¡­wÌš{†SV›ûî»OIO™2€ßgr^féUù°•9??<„¼Ì™©?lʯÑ]ÌD=ôUÐHáõJAsÏ=w£«Ó´ûñB@á 6LY©¡¾"i¡ƒ[n¹eQkÓ*™Âã–öwß}w [WU“LùUWˆ'ãhJ¦3ÜdFŽ©Töda#r„ 6<ñÓ"ðÿ½òÊ+ºDæ9ˆOÙ'Ì0‹òŸ}öÙÓÒÜØ¶£[·n޹g‘Z\LùÅá@Jæ5÷ðër€©™a +šÙ›píÅ¡ºÕœ!/¿ü²Æ?‰²c”<DŰ!c ¯"8C;‰ÈŽUVYÅ 0 ´2Z)¿8v~l>ú¨* Ș'ÄJ"ŠFfrÞ²‘Ôf—a˜FY“§ƒ|äZ-…–DL0=“ܨS§Nš8Ž˜·J„+Òm¿ýömÒ ´Jû³ÚiÊ/ ŒØ~ÅuFÒLê°Åâ• –B0?I–ð5ô )äÖ †ß„iY×¼†‰o6|é˜s#± ß¹§ðþéŠ+ŸlPÞ£˜³7æ†èK.¹¤*d”2‹:(=sïQxbó‡çäðÃw‡zhlêÔ¤Š ·ìmMB¾šÛ’u…¶l7nœ&?‚ÙÄ+$¾KòsUT¸ŠàbS¯@䀕$ã:''Ãq-Ò[l1'ìÀ™ìlõÞÏ®,uaêŽî *Ù”_‚:+¿ªÌŸù\¸ùÇüÿ„… ]½Z†GydŽ…‡•‡ÕGæ7o z‹E—m1RùwIžÄÜ$™ÙL’…€·èMùýÛoæäœ¬ç·êÚòÀ“© BbŽëÊbhËbÅW\QOQvm`êBò›¸#F´E4¡:;¥197»¢¾?C`ü !\¨W˜”ü%v»ŠI²À’— z¦øþ×mFl¬ç·êÚâTÍâD aˆ¤¨Ô¨‹þýû‡Qœ•a4 S~Mƒ¾17Fù…aõùÚbýÁ¬é€YûL"¦ü’ØkUÔù¹çž Uùqk¬?\&Ìú«¢#ìÔØ!`Ê/v]^…°Ì U Óò£vÞúíF’§†Wa+Éh ¶ÚÛ@°}+HvÜqG +ÃWÐÄ02ØjoŠ~!¶–08S|)ì\kRÝذ·nã[ÊoµÕV‹o­f E€ˆøüLþEÀ”_JŸæâˆ6å—Ò®¡YÃî¹çž5\™ÎKLù¥³_ÝG}äHždÊ/¥\C³°üpt6ùS~)}ò§»Â +¤´…Ö¬j ¼ ¦“0å—Ò'áÍ7ßTz)`#„a6)%Mâ‹ÊÏ,¿IýcÊo©ú†òëØ±cÃÚ?4WõÑ0È«¾Ã^³ü&ÁfÊo©úöÖ[o5tÈ»í¶ÛZÔGŒŸ ¨Ë ž5ËoR'™ò›„Ej¾}óÍ7Ž­‘–Ÿ1¾ÄûñaÈ‹˜å7©ŸLùMÂ"5ßò"T~ÜÏb~A!žB’,r [¨IýcÊo©ùÆ—Äß~ÐÍú‹ï#óö—_~éH`dò/¦üRø$í,oͳþšºÝ³LùÕ‚Z̯!»1½Íoý :T3¾5£vOC LùU‚RÂÎùðÃ5Ÿo³ªõÇÐÛV›ÕvßJ0åW J :ç믿V +’™7K°þHgibÄS~qîêöÁèUÍöÖPe»Äh ¦üš{t7e¾¼¬sÍ5Wt7±’  `Ê/˜Ý„fÏ÷eמÇÜ\`ù1™„€)¿IX¤âÛ'Ÿ|â]tÑT´Å„ž~úéᘂ’Lù¥ ³›ðÙgŸ¹…^8{W,¾ÿóÏ?±¨G«VRƒÙf›­U›_°Ý¦ü Â’Ü(¿EY$V xï½÷Ô5Æ—æuË„ LùåÁoÊ/$ÿKšÊßÿ=v–ßâ‹/î&›l2ËóÛ¤‡ F—‰'šòËÃß”_ Iþ÷ÓO?ÕêÇÍòóQ×^{­ñý5ácȋذ7|S~¹x$ú?†¼(šùçŸ?ví°˜ßæu C^Ä”_n˜òËÅ#Ñÿ;Vßä“ǯ[Íúkޣ啟qùåöAü~%¹õ³ÿª@`ܸqnÞyç­âŠÆžZÈúûã?Üå—_îößÿÆV¦…îö÷ßë"˜Y~¹>™$ž rwÙIE`ûí·wíÚµs·Ýv[l›põÕW«¢ƒvë‘Gq§vš²NSá_ýÕM;í´±­»U,U o—ªæ´xc¾úê+·ÖZkÅ…vÚÉÝ{ï½nÝu×u DzýÿÆŒ£çbÝ«\j°aojºÒ9†½P•ÇQþûßÿêð–è“‘#Gºï¾û.GñQg”Ÿ‰!Ð(ÌòkÒ߇٠üüâ8çw×]w¹ýöÛ¯ Âó°0\gµÚÄh¦ü…tÄ÷?~¼ûóÏ?5wGÄ·ªºøW^y%3¯WìbV¨Íò+†ŽíöFjÊôî q\Ñ# žÕ\¢<Š ÃbHL F!`ʯQHG|Ÿ8+?”ÞÀÝ¡‡Z…>ú¨äq;h„‰€)¿0ÑlbYqV~– .¸ÀwÜqþß6Ÿ8i›„yœþùçð Nx‰¦üÞ¾ú(?|䦙f¿+–Ÿgžy¦;õÔS Ö¨n„¦æ¸­¼òÊîÁ¬¹Œ´^hÊ/%=‹ò‹ã|_!xO:é$wÎ9ç:d+¾Q©}'Ï °Ñ ìk¯qã®4å×8¬#½ÌIŠÝ<ꨣÜÅ_Ü[ñmI];ð@æ˜cŽºÊIãŦüRÒ«¿üò‹›~úéÕšƒ>Ø 4(SgÈÌ×/G(_p&GÌòk §)¿¶˜$rq±ÓM7]âêŽóó!CÔ ?ES~áv¡·ü’2%nëK—fNÎ¥ñIÌÑß~û-‘Ê€wß}w7õÔS»Þ½{»×^{Í :T}þ¾ùæ÷í·ßꆃu Ìÿýßÿé'l%SM5•.òp=‹=³Ì2‹›sÎ93܆$P‡M’WÎo%Aù‘Ê«Ú$S~¹x$ö?,¿™fš)1õ‡ušÈ—_~Y?ßxã GˆÞ3Ï<£ûHÂ4Ï<ó¨[qÅõs†fP%éÝSL¡J…è•"ü(J”æÇ¬ÌÑ„ý!D‘ W]uUÝV[m5] MÚtA5 6ä-Œ˜)¿Â¸$n/Ê/Žq½H~„>ú¨5j”n_|ñ…Òo-³Ì2ªˆzôèá–\rIµÒX`UTþÚz?±‰A¾ýöÛªlÏ;ï< ¹Ã"ZsÍ5]—.]tC!¢TÓ"X}´Ï¤-ÆçדDîá_guŽÄq†\ÇW~Á'Ÿ|R•Êk¬á:wîì6Þxc·Ê*«¸öíÛ7­º$ò~ê©§”WnA2«¢Ý»ww={öt믿~¨J¸i µB`¸)¿B°$pC9J1ÿ¹F5‰¡+µ„³=ôÐC:ǶÅ[¨2ÙtÓMc½"ýÁ¨²¾ýöÛÝ[o½¥Ãî=÷ÜÓí»ï¾±Ì‹Ò¨>Mé}†ÛjoJz–Éÿf×Xp¹è¢‹taaóÍ7wüã7êüÊk*îskK-µ”;þøãá`(Bb®ºê*סCKösÏ=—’§Åš¦üRòàÅߌÄE¬¼¢ôX 8ñÄVÞûï¿ï{ì1·Ã;$––žùGBñ £Ä¿þúkVÀz}饗RòÔ´v3Lù¥¤ÿ›aù‘+ff”ɉðÑ0`€Ã‚J‹° ²ãŽ;ªÕ÷ðÃ+Aó–X²Ìš$S~Éí»œšcù5jØ;zôh·É&›8òq` á¶rî¹ç¦>„ŠágŸ}ÖÝwß}ל¥—^Z­^^<&ÉCÀ”_òú¬`ù6bØ{à 78üîp@F\sÍ5êƒW°R)ÝÉœæ»ï¾ëŽ8âwì±Çº6ÚÈ‘<Ê$Y˜òKV­-Ã3Ââ’ßÿÝí±Ç®OŸ>ºú‰srÜ3ÅE…åâh}òÉ'»_|Qux!°º'ì‚E³L ÷Š)¿Â¸$n/a[PÁG!'Nt]»vu$""ó¾„.õ/Ò;vT§éÍ6ÛL{®½öÚ(º ¦2Ÿ~úi]¤ù믿jº>íY„GJz8*åÇð–ù=–ù1-»ì²)A,¼f@(ÁtÀ‚ .èð Äâ:üðÃûA%â7ãŒ3ª•Zc©¾Ì”_Jº—añ­a !sÌoñùüóÏ;ÂÎLŠ#pÆgèü'T]„•¡›)(?HL #`ʯ0.‰Û¶åÇêq¯^½ÔÏÍ_åÃA¤s€}ûöUçh¢nš%¦üJ#oʯ4>‰9¶åwþùçk˜±¯øò™TŽ©:qÿÁ?ð½÷Þkš )¿Ò}f ¥ñIÌQævX˜C`?9å”S¹6pè5©ª!mÀl–˜ò+¼)¿Òø$æ(sLa)¿úèÄ´?nåeD\ð­·Þª¬1ͨŸ)¿Ò¨›ò+ObŽ¢ü~üñǺëËüa\ðݵkͬ¤÷Þ{oɾu7¤Êàü£Na*|Vɉ€ÁŠn†,¿üòn¹å–kÆ­“qO¡ 2IBeûHÝ-*ù@xöê.§T#FŒZh¡@(æKÖÐcwÜq‡â'î*¡ÞW\Ñ0Å„Z®V7ÃÌòKÆ;ªl-ðüp•¹û¤ ì «8çì¤ÙÛn»­…VQDä§BT°ú꫇nívêÔIýÿ õ2‰¦üâÕ5׆Ä=?ýôS]¡L„¬ýüóÏ©PsEò.$´ —™1cÆäi CÎMËüCltñÑøJBáo/¢™Ô‰W[¢6$ûÁ7ˆŒZsy¼þú뎇$ù C°$wÞygðÇÙv²É&s[mµ•2$ûòeð¢üxÄÅâRƒ¢ä<ä‡~p·Ür‹ÛÿýÝ< ìÊDNø¹H¨ç‰­EñØž‘Xä'žxB³Á¡hwÙe7ß|óùÛê'‘Æ SÅ 6uñ÷Î9±Î°(¯¿þúÈʯ³z-{¹Y~)éz¯ðÆWs‹ÆŽ«¤¤5w!D§Lø#(B³sv`öë×OWEIYIêÊþýûëù( ÒN-qÙe—){Ê1Ç£~sÄ0ï½÷Þr×­[7÷øã+‡ >u‹¤ªä^\Cl+ùMPˆ^>üðC­‹§vš–EìrÊ¢WîÍðß$FÔ=mhÄùqéĺü€k®$„ž©æë ](¼wZ/¡¾Ê9,ì08f¢„2ûYhÉ^l«Q¯e†hýì@Uô;„mYÏ“ÕUÝ'ÌË _IY©ÿû:³þÏñ_ Ž<òÈÌÿb5bñK,±Df_X_$E§ÖO2È…U¤•S?ÃlØ£Q=Uñ »ë±ü‘ËnO!‹ ËL”Mæ4Ü2Xpñâ­Ù­·ÞZwy†è /¼PÓ]pÀþTµ*Æ"¬®¼òÊn®¹æÒçdŽCpÞ&5%û —¡¤òBý8IiØâÙvˆÂ1‰¦üâÓuׄ¡e=ÊyèH9 )¿ü3——Í=çü'çãËH÷Úk/·å–[æ¡ÿs>Š^ (5„9Q„EH¾\%uÔ «ü¦Ô‰´˜Âór1žâˆÛœ_qlwÖ•Ï?ÿ¼æzCËÎõa8KçW",Åâ!ÉÇ‹ ¹DVZi%u]9î¸ãœøæœÊª8‚õ—/aÕ3»\”íb‹-¦i<³÷Gù¼*qÊáe[k-Û”_­ÈÅð:&ùÚÕ*, ðãg!,ñÊ$Û¢«§lÂÆX@ v6{ƒ2ɲƢ °Z³‚x‹Oÿ‘?,r !¸¹¬»îº¸Uæ2ß©Öof‡}iƒ€)¿6$wG½ÊoöÙg×UQÜK†Òas2G­î*ü?aÂ]•Íæ dÎŽÐ7V‰xÎÍY¨ÐÌi8ã΂‹ówÄ6C(Êu¤š¼ÿþûu÷òË/×Ë.cÕânÃüáСC¬5ǘ$# ËÃb?Æ¿ñ…^pÛl³Þ§QP~sÏ=w£n—ÌûÔ¿hb%ĉ¢ÐUEQ5WI\L¡¨Ä‚ª¹Œü …ÓNëÅJ² «Q®Á¬³ÎªûÄo/ahpÓM7â§§û$1P0xðà@æ0õÿž={2DÍËʬ$ dŽPó).-X—zŽä­Ðð9V“%šDÛÂ*²øB3¯çÈÐ8¹@½žU^ñ/ d1 -«2`õ< 9ì°ÃY¸ Ä £¸ŠÊñm „T¡¢ó[ô¤a¼MR‚€pÈéY,š[$+“ª8vß}÷šËÈ¿e%Uþîºÿ+1xçw±ôÚ”…¿Ì~ê VfæÿE˜O2çIt‹ßÊ'.8²èÈêt(åUZˆ8ºës Ó•^ÒŠçYlo2íõµfȇ»ÊG}Tø„ ö’˜ˆ‰rñ„’ż_~tEU){Š_ÍœvÚiۜ˹5¼P°ÉV`ýyÓO?}þáºþÇ›Å"T) yö–FÝæüJ㓨£„q-³Ì2WŽZ+¿ýöÛ»í¶ÛNsP„ÅXk]’z\~Pƒ‘׸Ñþ}„8"¦üJ?=¦üJ㓸£¸x°P¯°HÀ -JÐ;éÖ[f«\Ï „°„Ö­½öÚ o6,‹:0ý˜GÀ”_qly„Ȇ0”NÂ÷ÝwŸƒé…dåùî"‰§•–9H]Ù%*…lnÍ’ÉgGÊ4£I¸§)¿$ôRuÄòƒ ‹ze…VPÖ“áÇk2³K#Š;ÏlàV\qEÍãë}K_eG›…€)¿f!Ñ};v쨡TaXT±k×®º)æ¯`hA±š´EK«sçÎêÌ ýau&ñFÀ”_¼û§êÚ1ßuT¡Ð­ª ûß믿¾: +‰C¹>ûì³µ•ºë°†á„J.¬dS|ÉèfS~É觪j‰²ò‘ U]Xâd†rX“|2´#„,;:£Ä¥©=D|1!W\q…sùôD«©mtŠfÊ/E雂òƒÕƒP±0E¢2t"J)|aEaHÜjÕ¿Dn(m¾ƒ¯¾úªZ}­†CÒÛkÊ/é=X þ(?û™€[˜Ä'·‹:D˜Üb‹-tU8ì{Å­-äm·Ý¦){ôèÑJïOÈ«àX¡8k£t×\sMµDÓ€²ë®»*#GŽLøÓyõMùEqoÀe/Cθ ɼY\€‡Ð+*à¥c¥–™$ “Ui¯Pù$IÍà-L£`½vèÐAÁ§±}!¶É”_ˆ`Ʋ(¡oר xå’( Uǯ֫ÇXyäô¤çîè£Ö,mÞÄ¢ÃK+±ÅÎ|%¿II†·+yØ&]vÙE“û 80‘1§ ×’fK±Y¨`nדIàkÙ ÁI5HÎ7óóKN_ÕTSV,Q÷ÜsOM×Çñ"SŒ¥g’‹À¹çžë6Ùd“Üö_ALù„%=;±˜Xõ%§mZħ¶d¸kbÔŠ€)¿Z‘KÐu }%­¥. $¨ÚE«ê-?S~E!² `ʯ’~ à3Í4“R/%½-Ôß+?ö¦¡7›×S~ÍþawÆB"¾9üÜ’.6ìMzÆ£þ¦üâёעoß¾ê.2lذÈïõ ¼ågÃÞ¨‘Nwù¦üÒÝ¿™Ö-°ÀšUìÒK/ÍìKê¯ül؛ԌG½MùÅ£R‹~ýú)Ái$§ iÀÿnbÃÞÂhC°fî–ÂwIÏ^S~éé˲-㜮ÍÊ'[¶‚ž€å‡ó³P7UxEkœF^•Fp8¦M{zÒÒ“¶ãÄOTâÑ$³~ ülÈ›ÛáÄ?7Nc™sØÅ0åW ™”îßl³Íñ¾I¶þP~¶Ø‘û€BÃÍ|óÍ—{Àþ+Š€)¿¢Ð¤÷À 'œ üzw&Q˜ó3å—Ûs_}õ•î€ÅƤ2LùU†SªÎÚzë­ÝòË/ïÈK‘D±aoÛ^ûòË/u§Y~m±)¶Ç”_1dR¼ŸŒcgu–»óÎ;5ùPÒšjÃÞ¶=†å¬äMi{ÐöDÀ”_AXÒ¿sóÍ7WJ¨#<2qµaoÛ.Ãò3«¯-.¥öŸ_)tR~ì¼óÎÓ|»X€Ûn»mbZk–_Û®ZguLùµ…¥äS~%áI÷ArXôìÙÓ{ì±nË-·Tß¹$´ØæüÚö«ø&Õ!`ÃÞêðJÝÙýû÷wc$±Ïe—]–˜¶Ù°71]늚ò‹u÷D_¹EYÄqÄJu=|ýIè¥ø×Ñ”_üû(òüñºRˆL‚ذ7 ½ÿ:šò‹E^ÃöíÛ;rüÞtÓMî©§žŠü~õÞÀ†½õ"h׃€)?{m¶ÙÆ1i~À8ÒEÆYlØçÞINÝLù%§¯"¯é%—\¢IÃÉg±aoœ{'9u3å—œ¾Š¼¦‹-¶˜;í´Ót{ÿý÷#¿_­7°ao.r#FŒpƒÎÝiÿ•EÀ”_YˆZë„Ã;Ì­°Â n=öpÿüóO,oÃÞÜn¹ë®»Ü½÷Þ›»Óþ+‹€)¿²µÖ SL1…2dˆƒïE8Š {s{eìØ±nÁÌÝiÿ•EÀ”_YˆZï„å–[ÎáþñéèÑ£c€ {s»ä‹/¾0å— IEÿ™ò«¦Ö;‰·%–X‘ðüï¿ÿŽ6ìÔ08Cj@‚*“ê0åW^-sö”SN©~o¼ñ†;ýôÓcÕnöNê¢r`p¶aï$L*ýfʯR¤Zð¼e–YÆÁüå}œ2¾™å7éadÈ‹˜ò›„I¥ßLùUŠT‹žwຮ]»ºÞ½{»Ÿþ9(؜ߤn`±ƒ,vÆå7 “J¿¥U¥Hµðy×^{­ÒÞ“÷÷ºë®k(wß}·{øá‡5gy;¦šj*@5j”›8qbf‡œv­&;vtƒ rLS˜T‡Àd2aTw‰ÝŠŒ9R9ÿHŒ½ë®»6 ,ϪÒó7Í~dñEdAf®¹ærIa¥ñí°Ï¦"0܆½MÅ?97ïÖ­›R_õíÛ×½ûî»m*þÈ#¸ü±ÍþzwsŒ0©ï·?ÿüÓù ŇճÃ;Ô{+»¾Å0å×b^OsIz´ÒJ+¹=z¸_ýU‹BùrÈ!®K—.îì³Ï®§ø‚×n¸á†núé§/xÌïD‘bbTƒ€)¿jÐjñsÛµkçn½õVG‚ì}öÙÇýôÓOÊs饗*2×\sMè>Ü“T›|2Ñá”ÍÜ—‰!P ¦üªAËÎu$žñÆÝ-·Ü¢NÐ?þx&xüøñŽ…ˆ°¥{÷îEi¶XéÜo¿ý¾¥•טòkN»‰Ÿ²M˜0!G)aaý…-›l²‰®ê*˯W¯^…Ù>C $¦üJÂcó€ô S§N_»|ÒSþ‡a$ì…í¦›nê ]È–ÿoï\À¥ªª8¾)LTÄâ $h¨Š& j RøÌ4…Ð|%(˜ø–41)  ’`¤é½`”"!ÊCE‘ Š%Jø@ƒê³Nû·ôŒsçνwfÎcÎc­ï;wfÎc?þ{fݽ÷Zë¿P¶DHÖ­¢‹€*¿bKñý$82dˆìëÕDwÅy–Ä~ KßÜ:Q¶çwžßUŦ<Ü  S) U~¥á–º§˜éáìÌ[m‚Þ}÷ÝWÛ-%]ÃÕ&·n|ûúöí[RyIxhÑ¢EfþüùIèJYúPû7¹,MÒJ£ˆ@ƒ Ì믿.3-öÙj²¾¢üV¬Xaüf‚þêW¿jzõê•Q€øöaqÎUˆQÄ.¨6‘o¹lQ) U~¥á–ʧ7n,téË—/×”`>A1=@Üi§fÜ:ñí4hP¾êSsN•Ÿ·¡Våç ¿T>Ý¥Kóâ‹/ŠecCî,Å„aÄo@üýÜ}¿=z®§YTùy}U~ÞðKíÓÌÀlÞ|óMsþùçËŒ,[ âó!ŸÒ¢E Ó­[7)’:Ó,;vì0ï½÷ž.{=| ”ØÀxúè¬\¹R”à²eËä$n)¸¡TTT|qSλ-[¶˜ 6dŽM›6‰ï Š“?Â;wJL/~ÄöòŠì±ÇFö#™6mÚTŽ&Mš˜æÍ››¶mÛf§»dÎiF,?®]»ÖpÀfÕªU¸ËN”·Ñ•ªüÊ;‰ªcÑ—]v™(.f‚ÌN ¡âGŠ‚ä€š/áqF øè8P\(1^9Pr<ïÒY¡TQš»ï¾»(B"–h%‡«4axùÛßþ&Ô‚ìСƒìU ÇqðÁK\›<ù䓦_¿~‚áž{î·æG¡½ªü¢0 Ik›pÿ‘N‘< o¼ñ†8D7jÔHÒb¢x:wî,{vÌÎZ·nûƒï¼óNff¹fÍšŒÞ¼y³À[õ‘G™9âB Ê?•Å‹›&íëVTù……tÒëAÁA<:kÖ,óÜsωaÅ×»woqQ9ì°Ãd P~m.\hð—{饗d–HÎb + 0]»vMÔR9*ØG¤ªü"2±lKˇzÈL›6Í0«bßíøãÒS(®X¶ÆE0  QÞDN0{exæ™gŠKM§NâÒmga¨ò+ '½ËE€}=–³“'O6O=õ”a¿ "Ñ3Î8Chä³-¾î3q|eoò±ÇåŽ"ìÞ½»„ö‘Ê“ýC•Ø# Ê/öCR°²bÌ7nœyíµ×$©¢,“¬ Ø7$„ŒÐ¾G}ÔiÂ~æE]dpúV‰-ªüb;t!5Ge–o¸á±²² 1b„ÁP6a™që½÷Þ+–f¬Ú#Gެ“i:m8Ť¿•Æ.cT¼Ìž=Û±¾dŽ Ws.¾øbÇúáå½/m'?ùäÇRö;vèXrgÒ¤IŽe˜I qïo…FxÄäßT˜ÍÄŽ=<Œlô“°hüøñGa•Ϭ™ñaá†H•e0i3ÙP‰ªüâ3V¡´ô‰'žÈÜUxϦûöíC©;n•°çwûí·‹› Û$wºóÎ;YMÚ(Ãøç¤â U~ÞðKÔÓ7Þx£¸©ÀšŒëÊ 'œ¨þÕ(-]ºÔ\{íµÂ×þð‡–T}ø$jŽbïèªòóŽaìK <Œ™Ä/ùKIŽes¯½öŠ}¿ÂìawW_}µ™3gŽ™7ožDŒ¼ûî»4åvÚmüV•Ÿ(Ƹ ˆpWáGKâq’’«”ŽùMˆ!¯1aso¿ývé…Õð$L:ûí·_ Wõt¡¨ò+©ÞÇ>K4–QÏ<óŒüXØÍлD¼ò‚ „|áØc!¿AÞœ®UùyGT•Ÿw c[ÂUW]%yv1lÀp¢âÍš5“Ù43k¨ý"v…©¨Ë^ïc¥ÊÏ;†±,eîØ±cÅaÒÿØ{ï½ÍÌ™3…}å–[nñ¥–¼ˆÎü¼Ã©ÊÏ;†±+ÙɈÉ=ûì³c×þ85÷—›o¾ÙÜtÓM’ÊkÛ1vb§¡u^‘´<’Þ‹Ðâ†!Z82ßqÇqkº¯íeùøüóÏK™ÌЂ’aÆ ¯á5×\㹊³Î:+ÓfÏ…¥¼U~)û\G\óY–¥U¶mÛ&Ë~HUr“…è·àClôŒ3$*ÄKù 6”¨/e賟! Ê/eß’ á „K ¼~Q“|m‚Ýj*þ¸ðßýîwÍÉ'Ÿ,ÛAôÆe,ü‡*Ñ@@•_4Æ!´VX²CêÉ6>'»~öÙgÅÉ7´ŽPQMm>|¸Ð¿ç:rÙBbvx ý7¡¹7T¢@ýh4C[/¼ð‚!ç­Ÿ‚’úìh–áÄ´lÙRÂä¨eBè ŒþÏÍ9ÁžIˆ P˜:uªÐÞzè¡Ò<®áH¬,çH[™ËMÊjãÆR~Ÿ>}äÙšÚDÿqí¹ÿþûå¾Ü?—^z©¹òÊ+…¯ÄJ~ ¸—ËÖ‰ÝUÊŒ@Üyi´ýÅ!`•‡3a„âªãî+V8V±9ַͱJÇá3b *ŽÍááXBPǦ¨tìlÓ™8q¢\³ ·; €3tèPÇ*OÇfds¬r”ëwÝu—Ó¿džÞ9–LÔ±ÜK“ïwÜqŽuÊ–{¬btì>óòË/;–hÔ±ûaŽ]ÊʵšÚd—¶Nß¾}åž|¬2•6Ù|$ù.{:g¯”mÝU<•£û‚@…òùù‚c| A‰Ø}'ßlsô:ûì³O•rÛµk'<€îIîAá¹²nÝ:Qv.|x6#™óþûï;ÖáXvhÇÆ»·:'žx¢ðç¡H‘íÛ·;ÖÑ×[Ï•!C†HyK–,‘SùÚdjëÞã>’÷%{ýõ×ç½æå¤¥¼’öÙÔ^ŠÑgýA B—½ežy‡]=ùoÝÄß~×›úwòî"äé%ÎÕÍÕË9–ÇùgÙ#*ùë_ÿ*¹xYʺ‚A‚Ü!VÙ‰‘âá‡æ”+®¸Â½E 98ÿ®_¿Þ¸ŽÛÙmby“ðI'”y&ßöiƒß’dÚ¿1 ²‚/\¸Ð0«bߎٗ«€?øàƒ*mao*(ö ¹gX†¢\!.ÙXÌå—_.‘ÌŠH-IÌ2ÌHn›¨¯gÏžfõêÕn1Õ^q€&ÊŽC?…:™ùA!Vа_Êž¡ÎüJA¯†gü1œh)qB`РAŽA8V úÖl\\lÂr±È⦂ؼ¾r«¯¡9â²b ?eË–‰ÕÕ~-æÍ›;6äαJOž£]–T,£\wkˆpx็?Öˆ"ýp¯[:yq{qoÈ×&»ï'õÙe´{[•W›—XÜvªœôáƒUÖ’ ϵV[äܹs¬á*¾  ®.¾À³Bð3ÃåÅ&ßñµåvÉéØY^•2s?ã·W—pщo -9øóÙ%£(¾Ö­[g”¤[>ƒ–çÎýXå5_›PĤâÌ“u¤v¬suî%OŸí¬W—%O(¹ü#I•©âªü|ƒ2f5ʱ{qŽ].F®å§žzjŠÙrŠÓ´—FÛ½IÇ.?«Ì)ÏFw8Ö(ã¥èjÏ¢ü™ùZwžj׊9AÛl”K1è½µ# y{í’)•B²Ø› 7ƒá$Jb—Ä€BX ö1Ò@ŠÑ#Û‚[J»q±yðÁÍ=÷Ü#ù6(c̘1«r]>€ÅÔ‡ñ¾Dö- kó"ìyê~Ÿó<[»rÔ«IFÀþ œV­ZÉþÚŽ;"ÓUkpì°ÄµŠNÚh çýw¹ ~ KkëTî°ìõC Ù2𣞔”QQŽæÑ‰z*%Ÿ÷¨£Ž2äžµñ¬¦Q£F‘ê9–_»?©6ÕÕf|—\r‰™¾¸ 3¼Å‹Ë,oÖ¬YâûH8Ý9çœ#‡8 ½KðŽ9R-ïþ#_©ÊÏPSW"³,Ä( ârÉBšJKK%üyÐÏ»„¦QòU›å-Ã5ˆQ¥Þ¡C™é1Û;üðÃ=Ç{éó°aÃSâœU|E@•Ÿ¯pja‚Œ“4É‹ /e³žµìr@£Ï+û†7 1ˆLI¢Ä’•½:^±ÐBš@.`HNÉ3Â^”Ø’mªNqaQÅWTùù §V ’öÀâLâ"ö Q:$BpiÛ¶­lèóÊÞVf”‘ûÊò™™$anîÁò” tÄýò Ã1eÂýá‡ʱiÓ&•¾åú“W¨éØ¡ écßã‰Ä÷ßÿ²Îî¤a5üÙwß}e•¥¯Š¯¨òóN-¬  gbå= Ê= ÁG¡ÌJf™(O²¼±Ô†´ÅÊÑÀrëÅÆÏMÓ á„ß´ú¥â› ç*5{[‚F3.]±4Z†£&a‰êÎàvîÜYe–GþK—/³@wFH\–Ð(=rî"ø(^xá…föìÙ±¸°”õ²M€O¡Šÿ¨ÁÃLµÄ À’ÿ8’ATª¢ä  ”V9€èÇ„ ÀþàСCͤI“êÌÓ›.k7ŠD@œ‹LoäýÅRQE U~¹ˆèçÄ €5ù¼óÎ36-¦ä*NLÇ´#¾  Êϵ¨"`³žI2u¿“´Gµ¿Ú®ÂPƒGáXé1E€8\›9TÏPƒ‡~’€M€nlæ·ÔÓq%¤‹ë¡ÎüŠÃKïŽ)³Â<÷^„vñÒ©S§847ŽmÔ™_GMÛ\<?ÿùÏ…z‹xÞ8©/§OŸ‡¦Æ¶jðˆíÐiËAjâyÇWÌce¹—°6hò»víZ–úÓR©*¿´Œ´öÓ°÷GB&˜f¢,@°DïÒ¥K”›û¶©ò‹ýj EàôÓO—}´Ûo¿½ÐGÊrßòåË…Õ¦ä©eép™*UåW&àµÚð€¿?ò@ZUѼ¿áŒŒ*¿ppÖZ"‚Ð^Mœ81"-ªÞ ”ß!‡Rý‚žñU~¾Â©…E† b~ï¾ûn¡ÊŠZ{·nÝjÖ¯_¯Ê/„QåÈZE´€í…eï´iÓ¢Õ0Ûø I~NÞ•`P'ç`ñÕÒ#ŠÀ!C$SÉ—êÕ«ÑVj³D@œW‹Ž0¸½àKGÆ9•t" 3¿tŽ»öÚ"@Ža–¿Ï=÷œâ‘>tæ—¾1×»òF’ò%K–¸§ô5EèÌ/Eƒ­]­Ž†…–-[š3fT¿¨g’Œ€Îü’<ºÚ·º`öGjÈuëÖÕ}³Þ‘(ÔÕ%Qé)JNßÛn»­ØGõþ˜# Ê/æ¨Í÷†À—¾ô%3|øp3uêTóÞ{ïy+ÌÃÓÛ¶m3ýû÷ר ‹}T•_±ˆéý‰C`ðàÁ†ÈñãÇ—­o^žxâ CÒ%•pPåÎZK„Øm·ÝÌÏ~ö3‰÷ݱcGYZºhÑ"Ó±cGÓ¬Y³²ÔŸÆJUù¥qÔµÏÕ¸øâ‹ ŠoÊ”)Õ®…q_Þ={†Q•Öñ9ªüô« Xš6mjXþÂõG¢ó0åßÿþ·É¥GaV›úºTù¥þ+ ¸`ø€å¹²²Ò=Êë /¼ 3:ó îL%ªü2Pè›´#°ß~û™“N:ÉŒ;6T(Øï#S[Û¶mC­7í•©òKû7@û_œž¡‘Ÿ?~•óA~Ðý¾ Ñ­¹l o«½’Rzõê%®/¸ž„!Û·o7øùµjÕ*Œê´ŽÏÐð6ý&(¹0û›={¶ùË_þ’¹Ä瘥K—fÎùõfÏ=÷TÅç˜E”S¿ˆ{õVE ôë×O|în½õVÓ§OsóÍ7 ÷?âˆ#”e9!ßU~ H톰 íÖ­›0½<ôÐC™‚¿ò•¯˜üã™Ïú&Þ¨ò‹÷øië}DàwÞ1¿þõ¯Í„ Äõ$×ßüªü|¼ÌE©ò+óhõÑ@`îܹæøã—|Ÿ~úiÞF9Žc6nܘ÷šžŒêê¿1Ó€À(¾vu½iÓ¦ºnÑë1A@•_LJ›,_ÿú×ÍÂ… …X ~ýšD~Ò^‘9®¦Yf°½ÕÒA@•Ÿ~Ïhݺµ(@h¥jR€CþóŸÿxÆŒ20ªÀ#¨RTù•w­5¢´k×Î,X°@œœ¿üå/çm¥³¿çŸ^Xdp¥Q)ªüʃ»Öaößóì³Ïxþ`zÎ?,¾O?ý´!–¸M›6¹Åëç¨>²!U¬Õ(QFààƒ6óæÍ3»îºk5è‡ò£lõ•÷ Ê¯¼økíFàÐC5sæÌ1»ì²‹¸ÀÐT–›7oöÔjâxáïëÛ·¯§rôao¨òó†Ÿ>pàØûÓŸþ$J¯^½zòêuæcÌÿþ÷?sôÑG'½hwO•_´ÇG[˜¡Íœ9S–¿Xi½ÎüXò²¬nÒ¤Iz—Þ&(¥UzÇ^{^ Ÿ|ò‰yë­·ÌôéÓ͘1cÌ·¾õ-sä‘Gš?ü0s|üñLJr䀚žð8âÙ7ä•# ard‹ûÎw¾c7nlš7onp³ÁøÁ±i>CKÍÕÛ C ²foΠлÄ ðÏþÓ¬^½ZŽU«V޵kך>ø ÓGè§Pl6l™Û ßÀl%‡¢cÐU†î+I’¶lÙ’QšÐ泌~ûí·¥\*bVçÎ;"OÜW¬Ã*þ! 3?ÿ°Ô’b†ËWX”Ýã•W^‘ˆ feßþö·Eéð꺤0;ãZBÜ0¡sÌ0QˆD¸ŠøÍ7ß4\'É”Z$:âèÚµ«(Ê Ú“‚2+Uù¥`”µ‹Ÿ!€!Y XšW¬X!³3fV(K÷îÝeé‰q#*ÂŒ”Y(ŽÑ$7çÀÑšYè±Çkú÷ïoN8áY>G¥Í1h‡*¿ ’6Ñ#(dÈQòQšÅFwU~ mЬY³ÆÜyçæ·¿ý­Ùc=ÌücQz¤A°LϘ1Cžyæ±L_z饿œsÎ1»ï¾{ (´ªü EJï‹6®¾újÙÏ#6wèС¢øÒüƒ'ÌÔü#‡‘#GšK.¹Ä4hÐ ÚƒNë4{[88k-A!ð÷¿ÿ]f58 CCÏ?úóÏ??õ3–÷“'O7šŸþô§fÔ¨Q¦}ûöfÊ”)aԘĥ\ðˆËHi;« @xØwÜa:uê$é$~øaóÒK/ÉW•õƒø#Ž=Ú¼ñÆæûßÿ¾¹à‚ Ä8’š30©òKã¨Ç¼Ï¯¾úª¸¥\y商»,yO;í´ ù@Ì»Xó[´haÆo^~ùeÁªK—.榛nJ-›´*¿À¾jZp°…s/3?üôXÊM¡R88nã38vìXÃŒ‚…4æ&QåWøwFï,#8(_uÕUbÄÀr¹hÑ"ƒaC¥4ˆÆ(„$´ú."\Ò$ªüÒ4Ú1í+³¼sÏ=×ÜvÛmæ7¿ù™8q¢Îö|KÈØ+ŲwïÞ¢ }*:òŨò‹üi/ºè"ó»ßýÎÌš5Ë 4Hñ˜ež|òIYþ’»˜=Á4ˆ*¿4ŒrŒûxë­·šûï¿_BÓ¾÷½ïŸ'Ñn:û¦Dˆ"GtÈ»ï¾íûÐ:%6ðD-"`[éÕ«—,w‰RP x !w€c$N æÔà¿NZC)À™‡U²cÇŽæüc)Eè3%"°råJ1€Œ7N"BJ,&ê)™iÔG(­íÃ¥ñ©QØ—.\(ásÇsL5gjfL¸á@=µ×^{I({iAKõtÐAføðáæ†n0gŸ}¶ô'è~”¥|ëB ¢D KÏäì½÷ÞŽu`ŽL»¬EÔ±!bŽý‘:–-¦Z»N>ùdÇRK9–•YÚ~Ýu×U»'ˆAÕ»uëVÇ*qçW¿úUÍŽB™0Ī(‘BàñÇwì^“c#Õ.»Ì«ü–-[æÔ¯_ß±.9ÒÞ÷ßßù׿þxÛƒ®×ú:6_Iàý(Sjí-Ë|[+­ ˜–Ùtßwß}k»-ôkVÁI¹üxÄÈbpÏC7O> %èz „4•#‰¢ Œ’8ª1ïÓÒ¥K…š=ˆn@r ó ¯äæ ¾õ›ßüf¦*öŸzê)³qãF‰îÓ§OæZî¸óÈè†ÿ!ŽØ“&M’[N<ñDÓ²eËÜÛó~þè£ ¤ ø2Ξ=[ö GŒaP´5µÅzó6&ç$ÿ€PâŒë’&ªü’6¢ èì#AüØì>–* }'…$D§ˆ«üpí@]xá…Bmÿƒü@6ü'L˜U|ãˆ3^°`¤©ä=R(-þÔ©SEéAAòÄŸK+ŽÆ¤Å¬©-^ëÍÛ™<'QÀ`C¥DJ™ÖÛZ­"O?ýTöÕ,qÞë^NÞ}÷ÝŽõÌaÔŽ‘ÏÛ·owìݱ³ªÌuK/mY²d‰œ³ËLùl•TæÞ\vÙe²GYådÎ<óÌ*ýµYÛœBÚâµÞ›çX§gé_¡÷Çè¾ ù%ò_Z|;E®[fÖ`à{'ðd–F’¸Éë.O™eíܹÓ\qÅ™zɧËÒxýúõæ°ÃËœ÷ó[?<{m$÷H9Ú’¯_ŒCû—ùêúœ*¿ Öò‹Fàßø†ä®-úÁ:€ºéòË/—ˆöé xà]wÝe¦M›&¤›£G–øÜtÏ÷.ØHÙ. 29yùç¥KÍï{…1(P•_ I›˜XZ`]fïŠ {öa&å"\|*Fü$û÷ï/†"ZH MZg{Ùß U~ÙhèûX"À^à¨Q£„nÝÆ×š{î¹Ç´nÝZ(è‰I›ÀDC>’¾Ã`;ü…,qër¾NVê䜦ÑNI_a&8‰Ï1ˆ0üÑ~$ Î,—“(øA•A¿yeV ;>{Iåãó8ŽÛë@}<â¬ZµJö ÙÚ´i“éÔ©“éׯŸ$2ÂÍ#ÎtMôDzËÈUT[½{÷ .¬·…&RŠøÕ#ÊË=˜BÎàÎÕ QÖ¯‰*¿²Â¯•+Š@¹P>¿r!¯õ*Š@yÐò⯵+Š@™PåW&àµZE@(/ÿòQ #*6×IEND®B`‚mongodb-mongo-python-driver-509e9b7/doc/static/sidebar.js000066400000000000000000000142141462766011000234420ustar00rootroot00000000000000/* * sidebar.js * ~~~~~~~~~~ * * This script makes the Sphinx sidebar collapsible and implements intelligent * scrolling. * * .sphinxsidebar contains .sphinxsidebarwrapper. This script adds in * .sphixsidebar, after .sphinxsidebarwrapper, the #sidebarbutton used to * collapse and expand the sidebar. * * When the sidebar is collapsed the .sphinxsidebarwrapper is hidden and the * width of the sidebar and the margin-left of the document are decreased. * When the sidebar is expanded the opposite happens. This script saves a * per-browser/per-session cookie used to remember the position of the sidebar * among the pages. Once the browser is closed the cookie is deleted and the * position reset to the default (expanded). * * :copyright: Copyright 2007-2011 by the Sphinx team, see AUTHORS. * :license: BSD, see LICENSE for details. * */ $(function() { // global elements used by the functions. // the 'sidebarbutton' element is defined as global after its // creation, in the add_sidebar_button function var jwindow = $(window); var jdocument = $(document); var bodywrapper = $('.bodywrapper'); var sidebar = $('.sphinxsidebar'); var sidebarwrapper = $('.sphinxsidebarwrapper'); // original margin-left of the bodywrapper and width of the sidebar // with the sidebar expanded var bw_margin_expanded = bodywrapper.css('margin-left'); var ssb_width_expanded = sidebar.width(); // margin-left of the bodywrapper and width of the sidebar // with the sidebar collapsed var bw_margin_collapsed = '.8em'; var ssb_width_collapsed = '.8em'; // colors used by the current theme var dark_color = '#AAAAAA'; var light_color = '#CCCCCC'; function get_viewport_height() { if (window.innerHeight) return window.innerHeight; else return jwindow.height(); } function sidebar_is_collapsed() { return sidebarwrapper.is(':not(:visible)'); } function toggle_sidebar() { if (sidebar_is_collapsed()) expand_sidebar(); else collapse_sidebar(); // adjust the scrolling of the sidebar scroll_sidebar(); } function collapse_sidebar() { sidebarwrapper.hide(); sidebar.css('width', ssb_width_collapsed); bodywrapper.css('margin-left', bw_margin_collapsed); sidebarbutton.css({ 'margin-left': '0', 'height': bodywrapper.height(), 'border-radius': '5px' }); sidebarbutton.find('span').text('»'); sidebarbutton.attr('title', _('Expand sidebar')); document.cookie = 'sidebar=collapsed'; } function expand_sidebar() { bodywrapper.css('margin-left', bw_margin_expanded); sidebar.css('width', ssb_width_expanded); sidebarwrapper.show(); sidebarbutton.css({ 'margin-left': ssb_width_expanded-12, 'height': bodywrapper.height(), 'border-radius': '0 5px 5px 0' }); sidebarbutton.find('span').text('«'); sidebarbutton.attr('title', _('Collapse sidebar')); //sidebarwrapper.css({'padding-top': // Math.max(window.pageYOffset - sidebarwrapper.offset().top, 10)}); document.cookie = 'sidebar=expanded'; } function add_sidebar_button() { sidebarwrapper.css({ 'float': 'left', 'margin-right': '0', 'width': ssb_width_expanded - 28 }); // create the button sidebar.append( '
«
' ); var sidebarbutton = $('#sidebarbutton'); // find the height of the viewport to center the '<<' in the page var viewport_height = get_viewport_height(); var sidebar_offset = sidebar.offset().top; var sidebar_height = Math.max(bodywrapper.height(), sidebar.height()); sidebarbutton.find('span').css({ 'display': 'block', 'position': 'fixed', 'top': Math.min(viewport_height/2, sidebar_height/2 + sidebar_offset) - 10 }); sidebarbutton.click(toggle_sidebar); sidebarbutton.attr('title', _('Collapse sidebar')); sidebarbutton.css({ 'border-radius': '0 5px 5px 0', 'color': '#444444', 'background-color': '#CCCCCC', 'font-size': '1.2em', 'cursor': 'pointer', 'height': sidebar_height, 'padding-top': '1px', 'padding-left': '1px', 'margin-left': ssb_width_expanded - 12 }); sidebarbutton.hover( function () { $(this).css('background-color', dark_color); }, function () { $(this).css('background-color', light_color); } ); } function set_position_from_cookie() { if (!document.cookie) return; var items = document.cookie.split(';'); for(var k=0; k wintop && curbot > winbot) { sidebarwrapper.css('top', $u.max([wintop - offset - 10, 0])); } else if (curtop < wintop && curbot < winbot) { sidebarwrapper.css('top', $u.min([winbot - sidebar_height - offset - 20, jdocument.height() - sidebar_height - 200])); } } } jwindow.scroll(scroll_sidebar); }); mongodb-mongo-python-driver-509e9b7/doc/tools.rst000066400000000000000000000201071462766011000220740ustar00rootroot00000000000000Tools ===== Many tools have been written for working with **PyMongo**. If you know of or have created a tool for working with MongoDB from Python please list it here. .. note:: We try to keep this list current. As such, projects that have not been updated recently or appear to be unmaintained will occasionally be removed from the list or moved to the back (to keep the list from becoming too intimidating). If a project gets removed that is still being developed or is in active use please let us know or add it back. ORM-like Layers --------------- Some people have found that they prefer to work with a layer that has more features than PyMongo provides. Often, things like models and validation are desired. To that end, several different ORM-like layers have been written by various authors. It is our recommendation that new users begin by working directly with PyMongo, as described in the rest of this documentation. Many people have found that the features of PyMongo are enough for their needs. Even if you eventually come to the decision to use one of these layers, the time spent working directly with the driver will have increased your understanding of how MongoDB actually works. MongoEngine `MongoEngine `_ is another ORM-like layer on top of PyMongo. It allows you to define schemas for documents and query collections using syntax inspired by the Django ORM. The code is available on `GitHub `_; for more information, see the `tutorial `_. MincePy `MincePy `_ is an object-document mapper (ODM) designed to make any Python object storable and queryable in a MongoDB database. It is designed with machine learning and big-data computational and experimental science applications in mind but is entirely general and can be useful to anyone looking to organise, share, or process large amounts data with as little change to their current workflow as possible. Ming `Ming `_ is a library that allows you to enforce schemas on a MongoDB database in your Python application. It was developed by `SourceForge `_ in the course of their migration to MongoDB. See the `introductory blog post `_ for more details. MotorEngine `MotorEngine `_ is a port of MongoEngine to Motor, for asynchronous access with Tornado. It implements the same modeling APIs to be data-portable, meaning that a model defined in MongoEngine can be read in MotorEngine. The source is `available on GitHub `_. uMongo `uMongo `_ is a Python MongoDB ODM. Its inception comes from two needs: the lack of async ODM and the difficulty to do document (un)serialization with existing ODMs. Works with multiple drivers: PyMongo, TxMongo, motor_asyncio, and mongomock. The source `is available on GitHub `_ No longer maintained """""""""""""""""""" PyMODM `PyMODM `_ is an ORM-like framework on top of PyMongo. PyMODM is maintained by engineers at MongoDB, Inc. and is quick to adopt new MongoDB features. PyMODM is a "core" ODM, meaning that it provides simple, extensible functionality that can be leveraged by other libraries to target platforms like Django. At the same time, PyMODM is powerful enough to be used for developing applications on its own. Complete documentation is available on `readthedocs `_. MongoKit The `MongoKit `_ framework is an ORM-like layer on top of PyMongo. There is also a MongoKit `google group `_. Minimongo `minimongo `_ is a lightweight, pythonic interface to MongoDB. It retains pymongo's query and update API, and provides a number of additional features, including a simple document-oriented interface, connection pooling, index management, and collection & database naming helpers. The `source is on GitHub `_. Manga `Manga `_ aims to be a simpler ORM-like layer on top of PyMongo. The syntax for defining schema is inspired by the Django ORM, but Pymongo's query language is maintained. The source `is on GitHub `_. Humongolus `Humongolus `_ is a lightweight ORM framework for Python and MongoDB. The name comes from the combination of MongoDB and `Homunculus `_ (the concept of a miniature though fully formed human body). Humongolus allows you to create models/schemas with robust validation. It attempts to be as pythonic as possible and exposes the pymongo cursor objects whenever possible. The code is available for download `at GitHub `_. Tutorials and usage examples are also available at GitHub. Framework Tools --------------- This section lists tools and adapters that have been designed to work with various Python frameworks and libraries. * `Djongo `_ is a connector for using Django with MongoDB as the database backend. Use the Django Admin GUI to add and modify documents in MongoDB. The `Djongo Source Code `_ is hosted on GitHub and the `Djongo package `_ is on pypi. * `Django MongoDB Engine `_ is a MongoDB database backend for Django that completely integrates with its ORM. For more information `see the tutorial `_. * `mango `_ provides MongoDB backends for Django sessions and authentication (bypassing :mod:`django.db` entirely). * `Django MongoEngine `_ is a MongoDB backend for Django, an `example: `_. For more information see ``_ * `mongodb_beaker `_ is a project to enable using MongoDB as a backend for `beakers `_ caching / session system. `The source is on GitHub `_. * `Log4Mongo `_ is a flexible Python logging handler that can store logs in MongoDB using normal and capped collections. * `MongoLog `_ is a Python logging handler that stores logs in MongoDB using a capped collection. * `rod.recipe.mongodb `_ is a ZC Buildout recipe for downloading and installing MongoDB. * `mongobox `_ is a tool to run a sandboxed MongoDB instance from within a python app. * `Flask-MongoAlchemy `_ Add Flask support for MongoDB using MongoAlchemy. * `Flask-MongoKit `_ Flask extension to better integrate MongoKit into Flask. * `Flask-PyMongo `_ Flask-PyMongo bridges Flask and PyMongo. Alternative Drivers ------------------- These are alternatives to PyMongo. * `Motor `_ is a full-featured, non-blocking MongoDB driver for Python Tornado applications. * `TxMongo `_ is an asynchronous Twisted Python driver for MongoDB. * `MongoMock `_ is a small library to help testing Python code that interacts with MongoDB via Pymongo. mongodb-mongo-python-driver-509e9b7/doc/tutorial.rst000066400000000000000000000311061462766011000226000ustar00rootroot00000000000000Tutorial ======== .. testsetup:: from pymongo import MongoClient client = MongoClient() client.drop_database("test-database") This tutorial is intended as an introduction to working with **MongoDB** and **PyMongo**. Prerequisites ------------- Before we start, make sure that you have the **PyMongo** distribution :doc:`installed `. In the Python shell, the following should run without raising an exception: .. doctest:: >>> import pymongo This tutorial also assumes that a MongoDB instance is running on the default host and port. Assuming you have `downloaded and installed `_ MongoDB, you can start it like so: .. code-block:: bash $ mongod Making a Connection with MongoClient ------------------------------------ The first step when working with **PyMongo** is to create a :class:`~pymongo.mongo_client.MongoClient` to the running **mongod** instance. Doing so is easy: .. doctest:: >>> from pymongo import MongoClient >>> client = MongoClient() The above code will connect on the default host and port. We can also specify the host and port explicitly, as follows: .. doctest:: >>> client = MongoClient("localhost", 27017) Or use the MongoDB URI format: .. doctest:: >>> client = MongoClient("mongodb://localhost:27017/") Getting a Database ------------------ A single instance of MongoDB can support multiple independent `databases `_. When working with PyMongo you access databases using attribute style access on :class:`~pymongo.mongo_client.MongoClient` instances: .. doctest:: >>> db = client.test_database If your database name is such that using attribute style access won't work (like ``test-database``), you can use dictionary style access instead: .. doctest:: >>> db = client["test-database"] Getting a Collection -------------------- A `collection `_ is a group of documents stored in MongoDB, and can be thought of as roughly the equivalent of a table in a relational database. Getting a collection in PyMongo works the same as getting a database: .. doctest:: >>> collection = db.test_collection or (using dictionary style access): .. doctest:: >>> collection = db["test-collection"] An important note about collections (and databases) in MongoDB is that they are created lazily - none of the above commands have actually performed any operations on the MongoDB server. Collections and databases are created when the first document is inserted into them. Documents --------- Data in MongoDB is represented (and stored) using JSON-style documents. In PyMongo we use dictionaries to represent documents. As an example, the following dictionary might be used to represent a blog post: .. doctest:: >>> import datetime >>> post = { ... "author": "Mike", ... "text": "My first blog post!", ... "tags": ["mongodb", "python", "pymongo"], ... "date": datetime.datetime.now(tz=datetime.timezone.utc), ... } Note that documents can contain native Python types (like :class:`datetime.datetime` instances) which will be automatically converted to and from the appropriate `BSON `_ types. .. todo:: link to table of Python <-> BSON types Inserting a Document -------------------- To insert a document into a collection we can use the :meth:`~pymongo.collection.Collection.insert_one` method: .. doctest:: >>> posts = db.posts >>> post_id = posts.insert_one(post).inserted_id >>> post_id ObjectId('...') When a document is inserted a special key, ``"_id"``, is automatically added if the document doesn't already contain an ``"_id"`` key. The value of ``"_id"`` must be unique across the collection. :meth:`~pymongo.collection.Collection.insert_one` returns an instance of :class:`~pymongo.results.InsertOneResult`. For more information on ``"_id"``, see the `documentation on _id `_. After inserting the first document, the *posts* collection has actually been created on the server. We can verify this by listing all of the collections in our database: .. doctest:: >>> db.list_collection_names() ['posts'] Getting a Single Document With :meth:`~pymongo.collection.Collection.find_one` ------------------------------------------------------------------------------ The most basic type of query that can be performed in MongoDB is :meth:`~pymongo.collection.Collection.find_one`. This method returns a single document matching a query (or ``None`` if there are no matches). It is useful when you know there is only one matching document, or are only interested in the first match. Here we use :meth:`~pymongo.collection.Collection.find_one` to get the first document from the posts collection: .. doctest:: >>> import pprint >>> pprint.pprint(posts.find_one()) {'_id': ObjectId('...'), 'author': 'Mike', 'date': datetime.datetime(...), 'tags': ['mongodb', 'python', 'pymongo'], 'text': 'My first blog post!'} The result is a dictionary matching the one that we inserted previously. .. note:: The returned document contains an ``"_id"``, which was automatically added on insert. :meth:`~pymongo.collection.Collection.find_one` also supports querying on specific elements that the resulting document must match. To limit our results to a document with author "Mike" we do: .. doctest:: >>> pprint.pprint(posts.find_one({"author": "Mike"})) {'_id': ObjectId('...'), 'author': 'Mike', 'date': datetime.datetime(...), 'tags': ['mongodb', 'python', 'pymongo'], 'text': 'My first blog post!'} If we try with a different author, like "Eliot", we'll get no result: .. doctest:: >>> posts.find_one({"author": "Eliot"}) >>> .. _querying-by-objectid: Querying By ObjectId -------------------- We can also find a post by its ``_id``, which in our example is an ObjectId: .. doctest:: >>> post_id ObjectId(...) >>> pprint.pprint(posts.find_one({"_id": post_id})) {'_id': ObjectId('...'), 'author': 'Mike', 'date': datetime.datetime(...), 'tags': ['mongodb', 'python', 'pymongo'], 'text': 'My first blog post!'} Note that an ObjectId is not the same as its string representation: .. doctest:: >>> post_id_as_str = str(post_id) >>> posts.find_one({"_id": post_id_as_str}) # No result >>> A common task in web applications is to get an ObjectId from the request URL and find the matching document. It's necessary in this case to **convert the ObjectId from a string** before passing it to ``find_one``:: from bson.objectid import ObjectId # The web framework gets post_id from the URL and passes it as a string def get(post_id): # Convert from string to ObjectId: document = client.db.collection.find_one({'_id': ObjectId(post_id)}) .. seealso:: :ref:`web-application-querying-by-objectid` Bulk Inserts ------------ In order to make querying a little more interesting, let's insert a few more documents. In addition to inserting a single document, we can also perform *bulk insert* operations, by passing a list as the first argument to :meth:`~pymongo.collection.Collection.insert_many`. This will insert each document in the list, sending only a single command to the server: .. doctest:: >>> new_posts = [ ... { ... "author": "Mike", ... "text": "Another post!", ... "tags": ["bulk", "insert"], ... "date": datetime.datetime(2009, 11, 12, 11, 14), ... }, ... { ... "author": "Eliot", ... "title": "MongoDB is fun", ... "text": "and pretty easy too!", ... "date": datetime.datetime(2009, 11, 10, 10, 45), ... }, ... ] >>> result = posts.insert_many(new_posts) >>> result.inserted_ids [ObjectId('...'), ObjectId('...')] There are a couple of interesting things to note about this example: - The result from :meth:`~pymongo.collection.Collection.insert_many` now returns two :class:`~bson.objectid.ObjectId` instances, one for each inserted document. - ``new_posts[1]`` has a different "shape" than the other posts - there is no ``"tags"`` field and we've added a new field, ``"title"``. This is what we mean when we say that MongoDB is *schema-free*. Querying for More Than One Document ----------------------------------- To get more than a single document as the result of a query we use the :meth:`~pymongo.collection.Collection.find` method. :meth:`~pymongo.collection.Collection.find` returns a :class:`~pymongo.cursor.Cursor` instance, which allows us to iterate over all matching documents. For example, we can iterate over every document in the ``posts`` collection: .. doctest:: >>> for post in posts.find(): ... pprint.pprint(post) ... {'_id': ObjectId('...'), 'author': 'Mike', 'date': datetime.datetime(...), 'tags': ['mongodb', 'python', 'pymongo'], 'text': 'My first blog post!'} {'_id': ObjectId('...'), 'author': 'Mike', 'date': datetime.datetime(...), 'tags': ['bulk', 'insert'], 'text': 'Another post!'} {'_id': ObjectId('...'), 'author': 'Eliot', 'date': datetime.datetime(...), 'text': 'and pretty easy too!', 'title': 'MongoDB is fun'} Just like we did with :meth:`~pymongo.collection.Collection.find_one`, we can pass a document to :meth:`~pymongo.collection.Collection.find` to limit the returned results. Here, we get only those documents whose author is "Mike": .. doctest:: >>> for post in posts.find({"author": "Mike"}): ... pprint.pprint(post) ... {'_id': ObjectId('...'), 'author': 'Mike', 'date': datetime.datetime(...), 'tags': ['mongodb', 'python', 'pymongo'], 'text': 'My first blog post!'} {'_id': ObjectId('...'), 'author': 'Mike', 'date': datetime.datetime(...), 'tags': ['bulk', 'insert'], 'text': 'Another post!'} Counting -------- If we just want to know how many documents match a query we can perform a :meth:`~pymongo.collection.Collection.count_documents` operation instead of a full query. We can get a count of all of the documents in a collection: .. doctest:: >>> posts.count_documents({}) 3 or just of those documents that match a specific query: .. doctest:: >>> posts.count_documents({"author": "Mike"}) 2 Range Queries ------------- MongoDB supports many different types of `advanced queries `_. As an example, lets perform a query where we limit results to posts older than a certain date, but also sort the results by author: .. doctest:: >>> d = datetime.datetime(2009, 11, 12, 12) >>> for post in posts.find({"date": {"$lt": d}}).sort("author"): ... pprint.pprint(post) ... {'_id': ObjectId('...'), 'author': 'Eliot', 'date': datetime.datetime(...), 'text': 'and pretty easy too!', 'title': 'MongoDB is fun'} {'_id': ObjectId('...'), 'author': 'Mike', 'date': datetime.datetime(...), 'tags': ['bulk', 'insert'], 'text': 'Another post!'} Here we use the special ``"$lt"`` operator to do a range query, and also call :meth:`~pymongo.cursor.Cursor.sort` to sort the results by author. Indexing -------- Adding indexes can help accelerate certain queries and can also add additional functionality to querying and storing documents. In this example, we'll demonstrate how to create a `unique index `_ on a key that rejects documents whose value for that key already exists in the index. First, we'll need to create the index: .. doctest:: >>> result = db.profiles.create_index([("user_id", pymongo.ASCENDING)], unique=True) >>> sorted(list(db.profiles.index_information())) ['_id_', 'user_id_1'] Notice that we have two indexes now: one is the index on ``_id`` that MongoDB creates automatically, and the other is the index on ``user_id`` we just created. Now let's set up some user profiles: .. doctest:: >>> user_profiles = [{"user_id": 211, "name": "Luke"}, {"user_id": 212, "name": "Ziltoid"}] >>> result = db.profiles.insert_many(user_profiles) The index prevents us from inserting a document whose ``user_id`` is already in the collection: .. doctest:: :options: +IGNORE_EXCEPTION_DETAIL >>> new_profile = {"user_id": 213, "name": "Drew"} >>> duplicate_profile = {"user_id": 212, "name": "Tommy"} >>> result = db.profiles.insert_one(new_profile) # This is fine. >>> result = db.profiles.insert_one(duplicate_profile) Traceback (most recent call last): DuplicateKeyError: E11000 duplicate key error index: test_database.profiles.$user_id_1 dup key: { : 212 } .. seealso:: The MongoDB documentation on `indexes `_ mongodb-mongo-python-driver-509e9b7/green_framework_test.py000066400000000000000000000053511462766011000242270ustar00rootroot00000000000000# Copyright 2015-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. """Test PyMongo with a variety of greenlet-based monkey-patching frameworks.""" from __future__ import annotations import getopt import sys import pytest def run_gevent(): """Prepare to run tests with Gevent. Can raise ImportError.""" from gevent import monkey monkey.patch_all() def run_eventlet(): """Prepare to run tests with Eventlet. Can raise ImportError.""" import eventlet # https://github.com/eventlet/eventlet/issues/401 eventlet.sleep() eventlet.monkey_patch() FRAMEWORKS = { "gevent": run_gevent, "eventlet": run_eventlet, } def list_frameworks(): """Tell the user what framework names are valid.""" sys.stdout.write( """Testable frameworks: %s Note that membership in this list means the framework can be tested with PyMongo, not necessarily that it is officially supported. """ % ", ".join(sorted(FRAMEWORKS)) ) def run(framework_name, *args): """Run tests with monkey-patching enabled. Can raise ImportError.""" # Monkey-patch. FRAMEWORKS[framework_name]() # Run the tests. sys.exit(pytest.main(list(args))) def main(): """Parse options and run tests.""" usage = f"""python {sys.argv[0]} FRAMEWORK_NAME Test PyMongo with a variety of greenlet-based monkey-patching frameworks. See python {sys.argv[0]} --help-frameworks.""" try: opts, args = getopt.getopt(sys.argv[1:], "h", ["help", "help-frameworks"]) except getopt.GetoptError as err: print(str(err)) print(usage) sys.exit(2) for option_name, _ in opts: if option_name in ("-h", "--help"): print(usage) sys.exit() elif option_name == "--help-frameworks": list_frameworks() sys.exit() else: raise AssertionError("unhandled option") if not args: print(usage) sys.exit(1) if args[0] not in FRAMEWORKS: print("%r is not a testable framework.\n" % args[0]) list_frameworks() sys.exit(1) run( args[0], *args[1:], # Framework name. ) # Command line args to pytest, like what test to run. if __name__ == "__main__": main() mongodb-mongo-python-driver-509e9b7/gridfs/000077500000000000000000000000001462766011000207135ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/gridfs/__init__.py000066400000000000000000001116161462766011000230320ustar00rootroot00000000000000# Copyright 2009-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. """GridFS is a specification for storing large objects in Mongo. The :mod:`gridfs` package is an implementation of GridFS on top of :mod:`pymongo`, exposing a file-like interface. .. seealso:: The MongoDB documentation on `gridfs `_. """ from __future__ import annotations from collections import abc from typing import Any, Mapping, Optional, cast from bson.objectid import ObjectId from gridfs.errors import NoFile from gridfs.grid_file import ( DEFAULT_CHUNK_SIZE, GridIn, GridOut, GridOutCursor, _clear_entity_type_registry, _disallow_transactions, ) from pymongo import ASCENDING, DESCENDING, _csot from pymongo.client_session import ClientSession from pymongo.collection import Collection from pymongo.common import validate_string from pymongo.database import Database from pymongo.errors import ConfigurationError from pymongo.read_preferences import _ServerMode from pymongo.write_concern import WriteConcern __all__ = [ "GridFS", "GridFSBucket", "NoFile", "DEFAULT_CHUNK_SIZE", "GridIn", "GridOut", "GridOutCursor", ] class GridFS: """An instance of GridFS on top of a single Database.""" def __init__(self, database: Database, collection: str = "fs"): """Create a new instance of :class:`GridFS`. Raises :class:`TypeError` if `database` is not an instance of :class:`~pymongo.database.Database`. :param database: database to use :param collection: root collection to use .. versionchanged:: 4.0 Removed the `disable_md5` parameter. See :ref:`removed-gridfs-checksum` for details. .. versionchanged:: 3.11 Running a GridFS operation in a transaction now always raises an error. GridFS does not support multi-document transactions. .. versionchanged:: 3.7 Added the `disable_md5` parameter. .. versionchanged:: 3.1 Indexes are only ensured on the first write to the DB. .. versionchanged:: 3.0 `database` must use an acknowledged :attr:`~pymongo.database.Database.write_concern` .. seealso:: The MongoDB documentation on `gridfs `_. """ if not isinstance(database, Database): raise TypeError("database must be an instance of Database") database = _clear_entity_type_registry(database) if not database.write_concern.acknowledged: raise ConfigurationError("database must use acknowledged write_concern") self.__collection = database[collection] self.__files = self.__collection.files self.__chunks = self.__collection.chunks def new_file(self, **kwargs: Any) -> GridIn: """Create a new file in GridFS. Returns a new :class:`~gridfs.grid_file.GridIn` instance to which data can be written. Any keyword arguments will be passed through to :meth:`~gridfs.grid_file.GridIn`. If the ``"_id"`` of the file is manually specified, it must not already exist in GridFS. Otherwise :class:`~gridfs.errors.FileExists` is raised. :param kwargs: keyword arguments for file creation """ return GridIn(self.__collection, **kwargs) def put(self, data: Any, **kwargs: Any) -> Any: """Put data in GridFS as a new file. Equivalent to doing:: with fs.new_file(**kwargs) as f: f.write(data) `data` can be either an instance of :class:`bytes` or a file-like object providing a :meth:`read` method. If an `encoding` keyword argument is passed, `data` can also be a :class:`str` instance, which will be encoded as `encoding` before being written. Any keyword arguments will be passed through to the created file - see :meth:`~gridfs.grid_file.GridIn` for possible arguments. Returns the ``"_id"`` of the created file. If the ``"_id"`` of the file is manually specified, it must not already exist in GridFS. Otherwise :class:`~gridfs.errors.FileExists` is raised. :param data: data to be written as a file. :param kwargs: keyword arguments for file creation .. versionchanged:: 3.0 w=0 writes to GridFS are now prohibited. """ with GridIn(self.__collection, **kwargs) as grid_file: grid_file.write(data) return grid_file._id def get(self, file_id: Any, session: Optional[ClientSession] = None) -> GridOut: """Get a file from GridFS by ``"_id"``. Returns an instance of :class:`~gridfs.grid_file.GridOut`, which provides a file-like interface for reading. :param file_id: ``"_id"`` of the file to get :param session: a :class:`~pymongo.client_session.ClientSession` .. versionchanged:: 3.6 Added ``session`` parameter. """ gout = GridOut(self.__collection, file_id, session=session) # Raise NoFile now, instead of on first attribute access. gout._ensure_file() return gout def get_version( self, filename: Optional[str] = None, version: Optional[int] = -1, session: Optional[ClientSession] = None, **kwargs: Any, ) -> GridOut: """Get a file from GridFS by ``"filename"`` or metadata fields. Returns a version of the file in GridFS whose filename matches `filename` and whose metadata fields match the supplied keyword arguments, as an instance of :class:`~gridfs.grid_file.GridOut`. Version numbering is a convenience atop the GridFS API provided by MongoDB. If more than one file matches the query (either by `filename` alone, by metadata fields, or by a combination of both), then version ``-1`` will be the most recently uploaded matching file, ``-2`` the second most recently uploaded, etc. Version ``0`` will be the first version uploaded, ``1`` the second version, etc. So if three versions have been uploaded, then version ``0`` is the same as version ``-3``, version ``1`` is the same as version ``-2``, and version ``2`` is the same as version ``-1``. Raises :class:`~gridfs.errors.NoFile` if no such version of that file exists. :param filename: ``"filename"`` of the file to get, or `None` :param version: version of the file to get (defaults to -1, the most recent version uploaded) :param session: a :class:`~pymongo.client_session.ClientSession` :param kwargs: find files by custom metadata. .. versionchanged:: 3.6 Added ``session`` parameter. .. versionchanged:: 3.1 ``get_version`` no longer ensures indexes. """ query = kwargs if filename is not None: query["filename"] = filename _disallow_transactions(session) cursor = self.__files.find(query, session=session) if version is None: version = -1 if version < 0: skip = abs(version) - 1 cursor.limit(-1).skip(skip).sort("uploadDate", DESCENDING) else: cursor.limit(-1).skip(version).sort("uploadDate", ASCENDING) try: doc = next(cursor) return GridOut(self.__collection, file_document=doc, session=session) except StopIteration: raise NoFile("no version %d for filename %r" % (version, filename)) from None def get_last_version( self, filename: Optional[str] = None, session: Optional[ClientSession] = None, **kwargs: Any ) -> GridOut: """Get the most recent version of a file in GridFS by ``"filename"`` or metadata fields. Equivalent to calling :meth:`get_version` with the default `version` (``-1``). :param filename: ``"filename"`` of the file to get, or `None` :param session: a :class:`~pymongo.client_session.ClientSession` :param kwargs: find files by custom metadata. .. versionchanged:: 3.6 Added ``session`` parameter. """ return self.get_version(filename=filename, session=session, **kwargs) # TODO add optional safe mode for chunk removal? def delete(self, file_id: Any, session: Optional[ClientSession] = None) -> None: """Delete a file from GridFS by ``"_id"``. Deletes all data belonging to the file with ``"_id"``: `file_id`. .. warning:: Any processes/threads reading from the file while this method is executing will likely see an invalid/corrupt file. Care should be taken to avoid concurrent reads to a file while it is being deleted. .. note:: Deletes of non-existent files are considered successful since the end result is the same: no file with that _id remains. :param file_id: ``"_id"`` of the file to delete :param session: a :class:`~pymongo.client_session.ClientSession` .. versionchanged:: 3.6 Added ``session`` parameter. .. versionchanged:: 3.1 ``delete`` no longer ensures indexes. """ _disallow_transactions(session) self.__files.delete_one({"_id": file_id}, session=session) self.__chunks.delete_many({"files_id": file_id}, session=session) def list(self, session: Optional[ClientSession] = None) -> list[str]: """List the names of all files stored in this instance of :class:`GridFS`. :param session: a :class:`~pymongo.client_session.ClientSession` .. versionchanged:: 3.6 Added ``session`` parameter. .. versionchanged:: 3.1 ``list`` no longer ensures indexes. """ _disallow_transactions(session) # With an index, distinct includes documents with no filename # as None. return [ name for name in self.__files.distinct("filename", session=session) if name is not None ] def find_one( self, filter: Optional[Any] = None, session: Optional[ClientSession] = None, *args: Any, **kwargs: Any, ) -> Optional[GridOut]: """Get a single file from gridfs. All arguments to :meth:`find` are also valid arguments for :meth:`find_one`, although any `limit` argument will be ignored. Returns a single :class:`~gridfs.grid_file.GridOut`, or ``None`` if no matching file is found. For example: .. code-block: python file = fs.find_one({"filename": "lisa.txt"}) :param filter: a dictionary specifying the query to be performing OR any other type to be used as the value for a query for ``"_id"`` in the file collection. :param args: any additional positional arguments are the same as the arguments to :meth:`find`. :param session: a :class:`~pymongo.client_session.ClientSession` :param kwargs: any additional keyword arguments are the same as the arguments to :meth:`find`. .. versionchanged:: 3.6 Added ``session`` parameter. """ if filter is not None and not isinstance(filter, abc.Mapping): filter = {"_id": filter} _disallow_transactions(session) for f in self.find(filter, *args, session=session, **kwargs): return f return None def find(self, *args: Any, **kwargs: Any) -> GridOutCursor: """Query GridFS for files. Returns a cursor that iterates across files matching arbitrary queries on the files collection. Can be combined with other modifiers for additional control. For example:: for grid_out in fs.find({"filename": "lisa.txt"}, no_cursor_timeout=True): data = grid_out.read() would iterate through all versions of "lisa.txt" stored in GridFS. Note that setting no_cursor_timeout to True may be important to prevent the cursor from timing out during long multi-file processing work. As another example, the call:: most_recent_three = fs.find().sort("uploadDate", -1).limit(3) would return a cursor to the three most recently uploaded files in GridFS. Follows a similar interface to :meth:`~pymongo.collection.Collection.find` in :class:`~pymongo.collection.Collection`. If a :class:`~pymongo.client_session.ClientSession` is passed to :meth:`find`, all returned :class:`~gridfs.grid_file.GridOut` instances are associated with that session. :param filter: A query document that selects which files to include in the result set. Can be an empty document to include all files. :param skip: the number of files to omit (from the start of the result set) when returning the results :param limit: the maximum number of results to return :param no_cursor_timeout: if False (the default), any returned cursor is closed by the server after 10 minutes of inactivity. If set to True, the returned cursor will never time out on the server. Care should be taken to ensure that cursors with no_cursor_timeout turned on are properly closed. :param sort: a list of (key, direction) pairs specifying the sort order for this query. See :meth:`~pymongo.cursor.Cursor.sort` for details. Raises :class:`TypeError` if any of the arguments are of improper type. Returns an instance of :class:`~gridfs.grid_file.GridOutCursor` corresponding to this query. .. versionchanged:: 3.0 Removed the read_preference, tag_sets, and secondary_acceptable_latency_ms options. .. versionadded:: 2.7 .. seealso:: The MongoDB documentation on `find `_. """ return GridOutCursor(self.__collection, *args, **kwargs) def exists( self, document_or_id: Optional[Any] = None, session: Optional[ClientSession] = None, **kwargs: Any, ) -> bool: """Check if a file exists in this instance of :class:`GridFS`. The file to check for can be specified by the value of its ``_id`` key, or by passing in a query document. A query document can be passed in as dictionary, or by using keyword arguments. Thus, the following three calls are equivalent: >>> fs.exists(file_id) >>> fs.exists({"_id": file_id}) >>> fs.exists(_id=file_id) As are the following two calls: >>> fs.exists({"filename": "mike.txt"}) >>> fs.exists(filename="mike.txt") And the following two: >>> fs.exists({"foo": {"$gt": 12}}) >>> fs.exists(foo={"$gt": 12}) Returns ``True`` if a matching file exists, ``False`` otherwise. Calls to :meth:`exists` will not automatically create appropriate indexes; application developers should be sure to create indexes if needed and as appropriate. :param document_or_id: query document, or _id of the document to check for :param session: a :class:`~pymongo.client_session.ClientSession` :param kwargs: keyword arguments are used as a query document, if they're present. .. versionchanged:: 3.6 Added ``session`` parameter. """ _disallow_transactions(session) if kwargs: f = self.__files.find_one(kwargs, ["_id"], session=session) else: f = self.__files.find_one(document_or_id, ["_id"], session=session) return f is not None class GridFSBucket: """An instance of GridFS on top of a single Database.""" def __init__( self, db: Database, bucket_name: str = "fs", chunk_size_bytes: int = DEFAULT_CHUNK_SIZE, write_concern: Optional[WriteConcern] = None, read_preference: Optional[_ServerMode] = None, ) -> None: """Create a new instance of :class:`GridFSBucket`. Raises :exc:`TypeError` if `database` is not an instance of :class:`~pymongo.database.Database`. Raises :exc:`~pymongo.errors.ConfigurationError` if `write_concern` is not acknowledged. :param database: database to use. :param bucket_name: The name of the bucket. Defaults to 'fs'. :param chunk_size_bytes: The chunk size in bytes. Defaults to 255KB. :param write_concern: The :class:`~pymongo.write_concern.WriteConcern` to use. If ``None`` (the default) db.write_concern is used. :param read_preference: The read preference to use. If ``None`` (the default) db.read_preference is used. .. versionchanged:: 4.0 Removed the `disable_md5` parameter. See :ref:`removed-gridfs-checksum` for details. .. versionchanged:: 3.11 Running a GridFSBucket operation in a transaction now always raises an error. GridFSBucket does not support multi-document transactions. .. versionchanged:: 3.7 Added the `disable_md5` parameter. .. versionadded:: 3.1 .. seealso:: The MongoDB documentation on `gridfs `_. """ if not isinstance(db, Database): raise TypeError("database must be an instance of Database") db = _clear_entity_type_registry(db) wtc = write_concern if write_concern is not None else db.write_concern if not wtc.acknowledged: raise ConfigurationError("write concern must be acknowledged") self._bucket_name = bucket_name self._collection = db[bucket_name] self._chunks: Collection = self._collection.chunks.with_options( write_concern=write_concern, read_preference=read_preference ) self._files: Collection = self._collection.files.with_options( write_concern=write_concern, read_preference=read_preference ) self._chunk_size_bytes = chunk_size_bytes self._timeout = db.client.options.timeout def open_upload_stream( self, filename: str, chunk_size_bytes: Optional[int] = None, metadata: Optional[Mapping[str, Any]] = None, session: Optional[ClientSession] = None, ) -> GridIn: """Opens a Stream that the application can write the contents of the file to. The user must specify the filename, and can choose to add any additional information in the metadata field of the file document or modify the chunk size. For example:: my_db = MongoClient().test fs = GridFSBucket(my_db) with fs.open_upload_stream( "test_file", chunk_size_bytes=4, metadata={"contentType": "text/plain"}) as grid_in: grid_in.write("data I want to store!") # uploaded on close Returns an instance of :class:`~gridfs.grid_file.GridIn`. Raises :exc:`~gridfs.errors.NoFile` if no such version of that file exists. Raises :exc:`~ValueError` if `filename` is not a string. :param filename: The name of the file to upload. :param chunk_size_bytes` (options): The number of bytes per chunk of this file. Defaults to the chunk_size_bytes in :class:`GridFSBucket`. :param metadata: User data for the 'metadata' field of the files collection document. If not provided the metadata field will be omitted from the files collection document. :param session: a :class:`~pymongo.client_session.ClientSession` .. versionchanged:: 3.6 Added ``session`` parameter. """ validate_string("filename", filename) opts = { "filename": filename, "chunk_size": ( chunk_size_bytes if chunk_size_bytes is not None else self._chunk_size_bytes ), } if metadata is not None: opts["metadata"] = metadata return GridIn(self._collection, session=session, **opts) def open_upload_stream_with_id( self, file_id: Any, filename: str, chunk_size_bytes: Optional[int] = None, metadata: Optional[Mapping[str, Any]] = None, session: Optional[ClientSession] = None, ) -> GridIn: """Opens a Stream that the application can write the contents of the file to. The user must specify the file id and filename, and can choose to add any additional information in the metadata field of the file document or modify the chunk size. For example:: my_db = MongoClient().test fs = GridFSBucket(my_db) with fs.open_upload_stream_with_id( ObjectId(), "test_file", chunk_size_bytes=4, metadata={"contentType": "text/plain"}) as grid_in: grid_in.write("data I want to store!") # uploaded on close Returns an instance of :class:`~gridfs.grid_file.GridIn`. Raises :exc:`~gridfs.errors.NoFile` if no such version of that file exists. Raises :exc:`~ValueError` if `filename` is not a string. :param file_id: The id to use for this file. The id must not have already been used for another file. :param filename: The name of the file to upload. :param chunk_size_bytes` (options): The number of bytes per chunk of this file. Defaults to the chunk_size_bytes in :class:`GridFSBucket`. :param metadata: User data for the 'metadata' field of the files collection document. If not provided the metadata field will be omitted from the files collection document. :param session: a :class:`~pymongo.client_session.ClientSession` .. versionchanged:: 3.6 Added ``session`` parameter. """ validate_string("filename", filename) opts = { "_id": file_id, "filename": filename, "chunk_size": ( chunk_size_bytes if chunk_size_bytes is not None else self._chunk_size_bytes ), } if metadata is not None: opts["metadata"] = metadata return GridIn(self._collection, session=session, **opts) @_csot.apply def upload_from_stream( self, filename: str, source: Any, chunk_size_bytes: Optional[int] = None, metadata: Optional[Mapping[str, Any]] = None, session: Optional[ClientSession] = None, ) -> ObjectId: """Uploads a user file to a GridFS bucket. Reads the contents of the user file from `source` and uploads it to the file `filename`. Source can be a string or file-like object. For example:: my_db = MongoClient().test fs = GridFSBucket(my_db) file_id = fs.upload_from_stream( "test_file", "data I want to store!", chunk_size_bytes=4, metadata={"contentType": "text/plain"}) Returns the _id of the uploaded file. Raises :exc:`~gridfs.errors.NoFile` if no such version of that file exists. Raises :exc:`~ValueError` if `filename` is not a string. :param filename: The name of the file to upload. :param source: The source stream of the content to be uploaded. Must be a file-like object that implements :meth:`read` or a string. :param chunk_size_bytes` (options): The number of bytes per chunk of this file. Defaults to the chunk_size_bytes of :class:`GridFSBucket`. :param metadata: User data for the 'metadata' field of the files collection document. If not provided the metadata field will be omitted from the files collection document. :param session: a :class:`~pymongo.client_session.ClientSession` .. versionchanged:: 3.6 Added ``session`` parameter. """ with self.open_upload_stream(filename, chunk_size_bytes, metadata, session=session) as gin: gin.write(source) return cast(ObjectId, gin._id) @_csot.apply def upload_from_stream_with_id( self, file_id: Any, filename: str, source: Any, chunk_size_bytes: Optional[int] = None, metadata: Optional[Mapping[str, Any]] = None, session: Optional[ClientSession] = None, ) -> None: """Uploads a user file to a GridFS bucket with a custom file id. Reads the contents of the user file from `source` and uploads it to the file `filename`. Source can be a string or file-like object. For example:: my_db = MongoClient().test fs = GridFSBucket(my_db) file_id = fs.upload_from_stream( ObjectId(), "test_file", "data I want to store!", chunk_size_bytes=4, metadata={"contentType": "text/plain"}) Raises :exc:`~gridfs.errors.NoFile` if no such version of that file exists. Raises :exc:`~ValueError` if `filename` is not a string. :param file_id: The id to use for this file. The id must not have already been used for another file. :param filename: The name of the file to upload. :param source: The source stream of the content to be uploaded. Must be a file-like object that implements :meth:`read` or a string. :param chunk_size_bytes` (options): The number of bytes per chunk of this file. Defaults to the chunk_size_bytes of :class:`GridFSBucket`. :param metadata: User data for the 'metadata' field of the files collection document. If not provided the metadata field will be omitted from the files collection document. :param session: a :class:`~pymongo.client_session.ClientSession` .. versionchanged:: 3.6 Added ``session`` parameter. """ with self.open_upload_stream_with_id( file_id, filename, chunk_size_bytes, metadata, session=session ) as gin: gin.write(source) def open_download_stream( self, file_id: Any, session: Optional[ClientSession] = None ) -> GridOut: """Opens a Stream from which the application can read the contents of the stored file specified by file_id. For example:: my_db = MongoClient().test fs = GridFSBucket(my_db) # get _id of file to read. file_id = fs.upload_from_stream("test_file", "data I want to store!") grid_out = fs.open_download_stream(file_id) contents = grid_out.read() Returns an instance of :class:`~gridfs.grid_file.GridOut`. Raises :exc:`~gridfs.errors.NoFile` if no file with file_id exists. :param file_id: The _id of the file to be downloaded. :param session: a :class:`~pymongo.client_session.ClientSession` .. versionchanged:: 3.6 Added ``session`` parameter. """ gout = GridOut(self._collection, file_id, session=session) # Raise NoFile now, instead of on first attribute access. gout._ensure_file() return gout @_csot.apply def download_to_stream( self, file_id: Any, destination: Any, session: Optional[ClientSession] = None ) -> None: """Downloads the contents of the stored file specified by file_id and writes the contents to `destination`. For example:: my_db = MongoClient().test fs = GridFSBucket(my_db) # Get _id of file to read file_id = fs.upload_from_stream("test_file", "data I want to store!") # Get file to write to file = open('myfile','wb+') fs.download_to_stream(file_id, file) file.seek(0) contents = file.read() Raises :exc:`~gridfs.errors.NoFile` if no file with file_id exists. :param file_id: The _id of the file to be downloaded. :param destination: a file-like object implementing :meth:`write`. :param session: a :class:`~pymongo.client_session.ClientSession` .. versionchanged:: 3.6 Added ``session`` parameter. """ with self.open_download_stream(file_id, session=session) as gout: while True: chunk = gout.readchunk() if not len(chunk): break destination.write(chunk) @_csot.apply def delete(self, file_id: Any, session: Optional[ClientSession] = None) -> None: """Given an file_id, delete this stored file's files collection document and associated chunks from a GridFS bucket. For example:: my_db = MongoClient().test fs = GridFSBucket(my_db) # Get _id of file to delete file_id = fs.upload_from_stream("test_file", "data I want to store!") fs.delete(file_id) Raises :exc:`~gridfs.errors.NoFile` if no file with file_id exists. :param file_id: The _id of the file to be deleted. :param session: a :class:`~pymongo.client_session.ClientSession` .. versionchanged:: 3.6 Added ``session`` parameter. """ _disallow_transactions(session) res = self._files.delete_one({"_id": file_id}, session=session) self._chunks.delete_many({"files_id": file_id}, session=session) if not res.deleted_count: raise NoFile("no file could be deleted because none matched %s" % file_id) def find(self, *args: Any, **kwargs: Any) -> GridOutCursor: """Find and return the files collection documents that match ``filter`` Returns a cursor that iterates across files matching arbitrary queries on the files collection. Can be combined with other modifiers for additional control. For example:: for grid_data in fs.find({"filename": "lisa.txt"}, no_cursor_timeout=True): data = grid_data.read() would iterate through all versions of "lisa.txt" stored in GridFS. Note that setting no_cursor_timeout to True may be important to prevent the cursor from timing out during long multi-file processing work. As another example, the call:: most_recent_three = fs.find().sort("uploadDate", -1).limit(3) would return a cursor to the three most recently uploaded files in GridFS. Follows a similar interface to :meth:`~pymongo.collection.Collection.find` in :class:`~pymongo.collection.Collection`. If a :class:`~pymongo.client_session.ClientSession` is passed to :meth:`find`, all returned :class:`~gridfs.grid_file.GridOut` instances are associated with that session. :param filter: Search query. :param batch_size: The number of documents to return per batch. :param limit: The maximum number of documents to return. :param no_cursor_timeout: The server normally times out idle cursors after an inactivity period (10 minutes) to prevent excess memory use. Set this option to True prevent that. :param skip: The number of documents to skip before returning. :param sort: The order by which to sort results. Defaults to None. """ return GridOutCursor(self._collection, *args, **kwargs) def open_download_stream_by_name( self, filename: str, revision: int = -1, session: Optional[ClientSession] = None ) -> GridOut: """Opens a Stream from which the application can read the contents of `filename` and optional `revision`. For example:: my_db = MongoClient().test fs = GridFSBucket(my_db) grid_out = fs.open_download_stream_by_name("test_file") contents = grid_out.read() Returns an instance of :class:`~gridfs.grid_file.GridOut`. Raises :exc:`~gridfs.errors.NoFile` if no such version of that file exists. Raises :exc:`~ValueError` filename is not a string. :param filename: The name of the file to read from. :param revision: Which revision (documents with the same filename and different uploadDate) of the file to retrieve. Defaults to -1 (the most recent revision). :param session: a :class:`~pymongo.client_session.ClientSession` :Note: Revision numbers are defined as follows: - 0 = the original stored file - 1 = the first revision - 2 = the second revision - etc... - -2 = the second most recent revision - -1 = the most recent revision .. versionchanged:: 3.6 Added ``session`` parameter. """ validate_string("filename", filename) query = {"filename": filename} _disallow_transactions(session) cursor = self._files.find(query, session=session) if revision < 0: skip = abs(revision) - 1 cursor.limit(-1).skip(skip).sort("uploadDate", DESCENDING) else: cursor.limit(-1).skip(revision).sort("uploadDate", ASCENDING) try: grid_file = next(cursor) return GridOut(self._collection, file_document=grid_file, session=session) except StopIteration: raise NoFile("no version %d for filename %r" % (revision, filename)) from None @_csot.apply def download_to_stream_by_name( self, filename: str, destination: Any, revision: int = -1, session: Optional[ClientSession] = None, ) -> None: """Write the contents of `filename` (with optional `revision`) to `destination`. For example:: my_db = MongoClient().test fs = GridFSBucket(my_db) # Get file to write to file = open('myfile','wb') fs.download_to_stream_by_name("test_file", file) Raises :exc:`~gridfs.errors.NoFile` if no such version of that file exists. Raises :exc:`~ValueError` if `filename` is not a string. :param filename: The name of the file to read from. :param destination: A file-like object that implements :meth:`write`. :param revision: Which revision (documents with the same filename and different uploadDate) of the file to retrieve. Defaults to -1 (the most recent revision). :param session: a :class:`~pymongo.client_session.ClientSession` :Note: Revision numbers are defined as follows: - 0 = the original stored file - 1 = the first revision - 2 = the second revision - etc... - -2 = the second most recent revision - -1 = the most recent revision .. versionchanged:: 3.6 Added ``session`` parameter. """ with self.open_download_stream_by_name(filename, revision, session=session) as gout: while True: chunk = gout.readchunk() if not len(chunk): break destination.write(chunk) def rename( self, file_id: Any, new_filename: str, session: Optional[ClientSession] = None ) -> None: """Renames the stored file with the specified file_id. For example:: my_db = MongoClient().test fs = GridFSBucket(my_db) # Get _id of file to rename file_id = fs.upload_from_stream("test_file", "data I want to store!") fs.rename(file_id, "new_test_name") Raises :exc:`~gridfs.errors.NoFile` if no file with file_id exists. :param file_id: The _id of the file to be renamed. :param new_filename: The new name of the file. :param session: a :class:`~pymongo.client_session.ClientSession` .. versionchanged:: 3.6 Added ``session`` parameter. """ _disallow_transactions(session) result = self._files.update_one( {"_id": file_id}, {"$set": {"filename": new_filename}}, session=session ) if not result.matched_count: raise NoFile( "no files could be renamed %r because none " "matched file_id %i" % (new_filename, file_id) ) mongodb-mongo-python-driver-509e9b7/gridfs/errors.py000066400000000000000000000021031462766011000225750ustar00rootroot00000000000000# Copyright 2009-2015 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. """Exceptions raised by the :mod:`gridfs` package""" from __future__ import annotations from pymongo.errors import PyMongoError class GridFSError(PyMongoError): """Base class for all GridFS exceptions.""" class CorruptGridFile(GridFSError): """Raised when a file in :class:`~gridfs.GridFS` is malformed.""" class NoFile(GridFSError): """Raised when trying to read from a non-existent file.""" class FileExists(GridFSError): """Raised when trying to create a file that already exists.""" mongodb-mongo-python-driver-509e9b7/gridfs/grid_file.py000066400000000000000000001061651462766011000232220ustar00rootroot00000000000000# Copyright 2009-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. """Tools for representing files stored in GridFS.""" from __future__ import annotations import datetime import io import math import os import warnings from typing import Any, Iterable, Mapping, NoReturn, Optional from bson.int64 import Int64 from bson.objectid import ObjectId from gridfs.errors import CorruptGridFile, FileExists, NoFile from pymongo import ASCENDING from pymongo.client_session import ClientSession from pymongo.collection import Collection from pymongo.common import MAX_MESSAGE_SIZE from pymongo.cursor import Cursor from pymongo.errors import ( BulkWriteError, ConfigurationError, CursorNotFound, DuplicateKeyError, InvalidOperation, OperationFailure, ) from pymongo.helpers import _check_write_command_response from pymongo.read_preferences import ReadPreference _SEEK_SET = os.SEEK_SET _SEEK_CUR = os.SEEK_CUR _SEEK_END = os.SEEK_END EMPTY = b"" NEWLN = b"\n" """Default chunk size, in bytes.""" # Slightly under a power of 2, to work well with server's record allocations. DEFAULT_CHUNK_SIZE = 255 * 1024 # The number of chunked bytes to buffer before calling insert_many. _UPLOAD_BUFFER_SIZE = MAX_MESSAGE_SIZE # The number of chunk documents to buffer before calling insert_many. _UPLOAD_BUFFER_CHUNKS = 100000 # Rough BSON overhead of a chunk document not including the chunk data itself. # Essentially len(encode({"_id": ObjectId(), "files_id": ObjectId(), "n": 1, "data": ""})) _CHUNK_OVERHEAD = 60 _C_INDEX: dict[str, Any] = {"files_id": ASCENDING, "n": ASCENDING} _F_INDEX: dict[str, Any] = {"filename": ASCENDING, "uploadDate": ASCENDING} def _grid_in_property( field_name: str, docstring: str, read_only: Optional[bool] = False, closed_only: Optional[bool] = False, ) -> Any: """Create a GridIn property.""" warn_str = "" if docstring.startswith("DEPRECATED,"): warn_str = ( f"GridIn property '{field_name}' is deprecated and will be removed in PyMongo 5.0" ) def getter(self: Any) -> Any: if warn_str: warnings.warn(warn_str, stacklevel=2, category=DeprecationWarning) if closed_only and not self._closed: raise AttributeError("can only get %r on a closed file" % field_name) # Protect against PHP-237 if field_name == "length": return self._file.get(field_name, 0) return self._file.get(field_name, None) def setter(self: Any, value: Any) -> Any: if warn_str: warnings.warn(warn_str, stacklevel=2, category=DeprecationWarning) if self._closed: self._coll.files.update_one({"_id": self._file["_id"]}, {"$set": {field_name: value}}) self._file[field_name] = value if read_only: docstring += "\n\nThis attribute is read-only." elif closed_only: docstring = "{}\n\n{}".format( docstring, "This attribute is read-only and " "can only be read after :meth:`close` " "has been called.", ) if not read_only and not closed_only: return property(getter, setter, doc=docstring) return property(getter, doc=docstring) def _grid_out_property(field_name: str, docstring: str) -> Any: """Create a GridOut property.""" warn_str = "" if docstring.startswith("DEPRECATED,"): warn_str = ( f"GridOut property '{field_name}' is deprecated and will be removed in PyMongo 5.0" ) def getter(self: Any) -> Any: if warn_str: warnings.warn(warn_str, stacklevel=2, category=DeprecationWarning) self._ensure_file() # Protect against PHP-237 if field_name == "length": return self._file.get(field_name, 0) return self._file.get(field_name, None) docstring += "\n\nThis attribute is read-only." return property(getter, doc=docstring) def _clear_entity_type_registry(entity: Any, **kwargs: Any) -> Any: """Clear the given database/collection object's type registry.""" codecopts = entity.codec_options.with_options(type_registry=None) return entity.with_options(codec_options=codecopts, **kwargs) def _disallow_transactions(session: Optional[ClientSession]) -> None: if session and session.in_transaction: raise InvalidOperation("GridFS does not support multi-document transactions") class GridIn: """Class to write data to GridFS.""" def __init__( self, root_collection: Collection, session: Optional[ClientSession] = None, **kwargs: Any ) -> None: """Write a file to GridFS Application developers should generally not need to instantiate this class directly - instead see the methods provided by :class:`~gridfs.GridFS`. Raises :class:`TypeError` if `root_collection` is not an instance of :class:`~pymongo.collection.Collection`. Any of the file level options specified in the `GridFS Spec `_ may be passed as keyword arguments. Any additional keyword arguments will be set as additional fields on the file document. Valid keyword arguments include: - ``"_id"``: unique ID for this file (default: :class:`~bson.objectid.ObjectId`) - this ``"_id"`` must not have already been used for another file - ``"filename"``: human name for the file - ``"contentType"`` or ``"content_type"``: valid mime-type for the file - ``"chunkSize"`` or ``"chunk_size"``: size of each of the chunks, in bytes (default: 255 kb) - ``"encoding"``: encoding used for this file. Any :class:`str` that is written to the file will be converted to :class:`bytes`. :param root_collection: root collection to write to :param session: a :class:`~pymongo.client_session.ClientSession` to use for all commands :param kwargs: Any: file level options (see above) .. versionchanged:: 4.0 Removed the `disable_md5` parameter. See :ref:`removed-gridfs-checksum` for details. .. versionchanged:: 3.7 Added the `disable_md5` parameter. .. versionchanged:: 3.6 Added ``session`` parameter. .. versionchanged:: 3.0 `root_collection` must use an acknowledged :attr:`~pymongo.collection.Collection.write_concern` """ if not isinstance(root_collection, Collection): raise TypeError("root_collection must be an instance of Collection") if not root_collection.write_concern.acknowledged: raise ConfigurationError("root_collection must use acknowledged write_concern") _disallow_transactions(session) # Handle alternative naming if "content_type" in kwargs: kwargs["contentType"] = kwargs.pop("content_type") if "chunk_size" in kwargs: kwargs["chunkSize"] = kwargs.pop("chunk_size") coll = _clear_entity_type_registry(root_collection, read_preference=ReadPreference.PRIMARY) # Defaults kwargs["_id"] = kwargs.get("_id", ObjectId()) kwargs["chunkSize"] = kwargs.get("chunkSize", DEFAULT_CHUNK_SIZE) object.__setattr__(self, "_session", session) object.__setattr__(self, "_coll", coll) object.__setattr__(self, "_chunks", coll.chunks) object.__setattr__(self, "_file", kwargs) object.__setattr__(self, "_buffer", io.BytesIO()) object.__setattr__(self, "_position", 0) object.__setattr__(self, "_chunk_number", 0) object.__setattr__(self, "_closed", False) object.__setattr__(self, "_ensured_index", False) object.__setattr__(self, "_buffered_docs", []) object.__setattr__(self, "_buffered_docs_size", 0) def __create_index(self, collection: Collection, index_key: Any, unique: bool) -> None: doc = collection.find_one(projection={"_id": 1}, session=self._session) if doc is None: try: index_keys = [ index_spec["key"] for index_spec in collection.list_indexes(session=self._session) ] except OperationFailure: index_keys = [] if index_key not in index_keys: collection.create_index(index_key.items(), unique=unique, session=self._session) def __ensure_indexes(self) -> None: if not object.__getattribute__(self, "_ensured_index"): _disallow_transactions(self._session) self.__create_index(self._coll.files, _F_INDEX, False) self.__create_index(self._coll.chunks, _C_INDEX, True) object.__setattr__(self, "_ensured_index", True) def abort(self) -> None: """Remove all chunks/files that may have been uploaded and close.""" self._coll.chunks.delete_many({"files_id": self._file["_id"]}, session=self._session) self._coll.files.delete_one({"_id": self._file["_id"]}, session=self._session) object.__setattr__(self, "_closed", True) @property def closed(self) -> bool: """Is this file closed?""" return self._closed _id: Any = _grid_in_property("_id", "The ``'_id'`` value for this file.", read_only=True) filename: Optional[str] = _grid_in_property("filename", "Name of this file.") name: Optional[str] = _grid_in_property("filename", "Alias for `filename`.") content_type: Optional[str] = _grid_in_property( "contentType", "DEPRECATED, will be removed in PyMongo 5.0. Mime-type for this file." ) length: int = _grid_in_property("length", "Length (in bytes) of this file.", closed_only=True) chunk_size: int = _grid_in_property("chunkSize", "Chunk size for this file.", read_only=True) upload_date: datetime.datetime = _grid_in_property( "uploadDate", "Date that this file was uploaded.", closed_only=True ) md5: Optional[str] = _grid_in_property( "md5", "DEPRECATED, will be removed in PyMongo 5.0. MD5 of the contents of this file if an md5 sum was created.", closed_only=True, ) _buffer: io.BytesIO _closed: bool _buffered_docs: list[dict[str, Any]] _buffered_docs_size: int def __getattr__(self, name: str) -> Any: if name in self._file: return self._file[name] raise AttributeError("GridIn object has no attribute '%s'" % name) def __setattr__(self, name: str, value: Any) -> None: # For properties of this instance like _buffer, or descriptors set on # the class like filename, use regular __setattr__ if name in self.__dict__ or name in self.__class__.__dict__: object.__setattr__(self, name, value) else: # All other attributes are part of the document in db.fs.files. # Store them to be sent to server on close() or if closed, send # them now. self._file[name] = value if self._closed: self._coll.files.update_one({"_id": self._file["_id"]}, {"$set": {name: value}}) def __flush_data(self, data: Any, force: bool = False) -> None: """Flush `data` to a chunk.""" self.__ensure_indexes() assert len(data) <= self.chunk_size if data: self._buffered_docs.append( {"files_id": self._file["_id"], "n": self._chunk_number, "data": data} ) self._buffered_docs_size += len(data) + _CHUNK_OVERHEAD if not self._buffered_docs: return # Limit to 100,000 chunks or 32MB (+1 chunk) of data. if ( force or self._buffered_docs_size >= _UPLOAD_BUFFER_SIZE or len(self._buffered_docs) >= _UPLOAD_BUFFER_CHUNKS ): try: self._chunks.insert_many(self._buffered_docs, session=self._session) except BulkWriteError as exc: # For backwards compatibility, raise an insert_one style exception. write_errors = exc.details["writeErrors"] for err in write_errors: if err.get("code") in (11000, 11001, 12582): # Duplicate key errors self._raise_file_exists(self._file["_id"]) result = {"writeErrors": write_errors} wces = exc.details["writeConcernErrors"] if wces: result["writeConcernError"] = wces[-1] _check_write_command_response(result) raise self._buffered_docs = [] self._buffered_docs_size = 0 self._chunk_number += 1 self._position += len(data) def __flush_buffer(self, force: bool = False) -> None: """Flush the buffer contents out to a chunk.""" self.__flush_data(self._buffer.getvalue(), force=force) self._buffer.close() self._buffer = io.BytesIO() def __flush(self) -> Any: """Flush the file to the database.""" try: self.__flush_buffer(force=True) # The GridFS spec says length SHOULD be an Int64. self._file["length"] = Int64(self._position) self._file["uploadDate"] = datetime.datetime.now(tz=datetime.timezone.utc) return self._coll.files.insert_one(self._file, session=self._session) except DuplicateKeyError: self._raise_file_exists(self._id) def _raise_file_exists(self, file_id: Any) -> NoReturn: """Raise a FileExists exception for the given file_id.""" raise FileExists("file with _id %r already exists" % file_id) def close(self) -> None: """Flush the file and close it. A closed file cannot be written any more. Calling :meth:`close` more than once is allowed. """ if not self._closed: self.__flush() object.__setattr__(self, "_closed", True) def read(self, size: int = -1) -> NoReturn: raise io.UnsupportedOperation("read") def readable(self) -> bool: return False def seekable(self) -> bool: return False def write(self, data: Any) -> None: """Write data to the file. There is no return value. `data` can be either a string of bytes or a file-like object (implementing :meth:`read`). If the file has an :attr:`encoding` attribute, `data` can also be a :class:`str` instance, which will be encoded as :attr:`encoding` before being written. Due to buffering, the data may not actually be written to the database until the :meth:`close` method is called. Raises :class:`ValueError` if this file is already closed. Raises :class:`TypeError` if `data` is not an instance of :class:`bytes`, a file-like object, or an instance of :class:`str`. Unicode data is only allowed if the file has an :attr:`encoding` attribute. :param data: string of bytes or file-like object to be written to the file """ if self._closed: raise ValueError("cannot write to a closed file") try: # file-like read = data.read except AttributeError: # string if not isinstance(data, (str, bytes)): raise TypeError("can only write strings or file-like objects") from None if isinstance(data, str): try: data = data.encode(self.encoding) except AttributeError: raise TypeError( "must specify an encoding for file in order to write str" ) from None read = io.BytesIO(data).read if self._buffer.tell() > 0: # Make sure to flush only when _buffer is complete space = self.chunk_size - self._buffer.tell() if space: try: to_write = read(space) except BaseException: self.abort() raise self._buffer.write(to_write) if len(to_write) < space: return # EOF or incomplete self.__flush_buffer() to_write = read(self.chunk_size) while to_write and len(to_write) == self.chunk_size: self.__flush_data(to_write) to_write = read(self.chunk_size) self._buffer.write(to_write) def writelines(self, sequence: Iterable[Any]) -> None: """Write a sequence of strings to the file. Does not add separators. """ for line in sequence: self.write(line) def writeable(self) -> bool: return True def __enter__(self) -> GridIn: """Support for the context manager protocol.""" return self def __exit__(self, exc_type: Any, exc_val: Any, exc_tb: Any) -> Any: """Support for the context manager protocol. Close the file if no exceptions occur and allow exceptions to propagate. """ if exc_type is None: # No exceptions happened. self.close() else: # Something happened, at minimum mark as closed. object.__setattr__(self, "_closed", True) # propagate exceptions return False class GridOut(io.IOBase): """Class to read data out of GridFS.""" def __init__( self, root_collection: Collection, file_id: Optional[int] = None, file_document: Optional[Any] = None, session: Optional[ClientSession] = None, ) -> None: """Read a file from GridFS Application developers should generally not need to instantiate this class directly - instead see the methods provided by :class:`~gridfs.GridFS`. Either `file_id` or `file_document` must be specified, `file_document` will be given priority if present. Raises :class:`TypeError` if `root_collection` is not an instance of :class:`~pymongo.collection.Collection`. :param root_collection: root collection to read from :param file_id: value of ``"_id"`` for the file to read :param file_document: file document from `root_collection.files` :param session: a :class:`~pymongo.client_session.ClientSession` to use for all commands .. versionchanged:: 3.8 For better performance and to better follow the GridFS spec, :class:`GridOut` now uses a single cursor to read all the chunks in the file. .. versionchanged:: 3.6 Added ``session`` parameter. .. versionchanged:: 3.0 Creating a GridOut does not immediately retrieve the file metadata from the server. Metadata is fetched when first needed. """ if not isinstance(root_collection, Collection): raise TypeError("root_collection must be an instance of Collection") _disallow_transactions(session) root_collection = _clear_entity_type_registry(root_collection) super().__init__() self.__chunks = root_collection.chunks self.__files = root_collection.files self.__file_id = file_id self.__buffer = EMPTY # Start position within the current buffered chunk. self.__buffer_pos = 0 self.__chunk_iter = None # Position within the total file. self.__position = 0 self._file = file_document self._session = session _id: Any = _grid_out_property("_id", "The ``'_id'`` value for this file.") filename: str = _grid_out_property("filename", "Name of this file.") name: str = _grid_out_property("filename", "Alias for `filename`.") content_type: Optional[str] = _grid_out_property( "contentType", "DEPRECATED, will be removed in PyMongo 5.0. Mime-type for this file." ) length: int = _grid_out_property("length", "Length (in bytes) of this file.") chunk_size: int = _grid_out_property("chunkSize", "Chunk size for this file.") upload_date: datetime.datetime = _grid_out_property( "uploadDate", "Date that this file was first uploaded." ) aliases: Optional[list[str]] = _grid_out_property( "aliases", "DEPRECATED, will be removed in PyMongo 5.0. List of aliases for this file." ) metadata: Optional[Mapping[str, Any]] = _grid_out_property( "metadata", "Metadata attached to this file." ) md5: Optional[str] = _grid_out_property( "md5", "DEPRECATED, will be removed in PyMongo 5.0. MD5 of the contents of this file if an md5 sum was created.", ) _file: Any __chunk_iter: Any def _ensure_file(self) -> None: if not self._file: _disallow_transactions(self._session) self._file = self.__files.find_one({"_id": self.__file_id}, session=self._session) if not self._file: raise NoFile( f"no file in gridfs collection {self.__files!r} with _id {self.__file_id!r}" ) def __getattr__(self, name: str) -> Any: self._ensure_file() if name in self._file: return self._file[name] raise AttributeError("GridOut object has no attribute '%s'" % name) def readable(self) -> bool: return True def readchunk(self) -> bytes: """Reads a chunk at a time. If the current position is within a chunk the remainder of the chunk is returned. """ received = len(self.__buffer) - self.__buffer_pos chunk_data = EMPTY chunk_size = int(self.chunk_size) if received > 0: chunk_data = self.__buffer[self.__buffer_pos :] elif self.__position < int(self.length): chunk_number = int((received + self.__position) / chunk_size) if self.__chunk_iter is None: self.__chunk_iter = _GridOutChunkIterator( self, self.__chunks, self._session, chunk_number ) chunk = self.__chunk_iter.next() chunk_data = chunk["data"][self.__position % chunk_size :] if not chunk_data: raise CorruptGridFile("truncated chunk") self.__position += len(chunk_data) self.__buffer = EMPTY self.__buffer_pos = 0 return chunk_data def _read_size_or_line(self, size: int = -1, line: bool = False) -> bytes: """Internal read() and readline() helper.""" self._ensure_file() remainder = int(self.length) - self.__position if size < 0 or size > remainder: size = remainder if size == 0: return EMPTY received = 0 data = [] while received < size: needed = size - received if self.__buffer: # Optimization: Read the buffer with zero byte copies. buf = self.__buffer chunk_start = self.__buffer_pos chunk_data = memoryview(buf)[self.__buffer_pos :] self.__buffer = EMPTY self.__buffer_pos = 0 self.__position += len(chunk_data) else: buf = self.readchunk() chunk_start = 0 chunk_data = memoryview(buf) if line: pos = buf.find(NEWLN, chunk_start, chunk_start + needed) - chunk_start if pos >= 0: # Decrease size to exit the loop. size = received + pos + 1 needed = pos + 1 if len(chunk_data) > needed: data.append(chunk_data[:needed]) # Optimization: Save the buffer with zero byte copies. self.__buffer = buf self.__buffer_pos = chunk_start + needed self.__position -= len(self.__buffer) - self.__buffer_pos else: data.append(chunk_data) received += len(chunk_data) # Detect extra chunks after reading the entire file. if size == remainder and self.__chunk_iter: try: self.__chunk_iter.next() except StopIteration: pass return b"".join(data) def read(self, size: int = -1) -> bytes: """Read at most `size` bytes from the file (less if there isn't enough data). The bytes are returned as an instance of :class:`bytes` If `size` is negative or omitted all data is read. :param size: the number of bytes to read .. versionchanged:: 3.8 This method now only checks for extra chunks after reading the entire file. Previously, this method would check for extra chunks on every call. """ return self._read_size_or_line(size=size) def readline(self, size: int = -1) -> bytes: # type: ignore[override] """Read one line or up to `size` bytes from the file. :param size: the maximum number of bytes to read """ return self._read_size_or_line(size=size, line=True) def tell(self) -> int: """Return the current position of this file.""" return self.__position def seek(self, pos: int, whence: int = _SEEK_SET) -> int: """Set the current position of this file. :param pos: the position (or offset if using relative positioning) to seek to :param whence: where to seek from. :attr:`os.SEEK_SET` (``0``) for absolute file positioning, :attr:`os.SEEK_CUR` (``1``) to seek relative to the current position, :attr:`os.SEEK_END` (``2``) to seek relative to the file's end. .. versionchanged:: 4.1 The method now returns the new position in the file, to conform to the behavior of :meth:`io.IOBase.seek`. """ if whence == _SEEK_SET: new_pos = pos elif whence == _SEEK_CUR: new_pos = self.__position + pos elif whence == _SEEK_END: new_pos = int(self.length) + pos else: raise OSError(22, "Invalid value for `whence`") if new_pos < 0: raise OSError(22, "Invalid value for `pos` - must be positive") # Optimization, continue using the same buffer and chunk iterator. if new_pos == self.__position: return new_pos self.__position = new_pos self.__buffer = EMPTY self.__buffer_pos = 0 if self.__chunk_iter: self.__chunk_iter.close() self.__chunk_iter = None return new_pos def seekable(self) -> bool: return True def __iter__(self) -> GridOut: """Return an iterator over all of this file's data. The iterator will return lines (delimited by ``b'\\n'``) of :class:`bytes`. This can be useful when serving files using a webserver that handles such an iterator efficiently. .. versionchanged:: 3.8 The iterator now raises :class:`CorruptGridFile` when encountering any truncated, missing, or extra chunk in a file. The previous behavior was to only raise :class:`CorruptGridFile` on a missing chunk. .. versionchanged:: 4.0 The iterator now iterates over *lines* in the file, instead of chunks, to conform to the base class :py:class:`io.IOBase`. Use :meth:`GridOut.readchunk` to read chunk by chunk instead of line by line. """ return self def close(self) -> None: """Make GridOut more generically file-like.""" if self.__chunk_iter: self.__chunk_iter.close() self.__chunk_iter = None super().close() def write(self, value: Any) -> NoReturn: raise io.UnsupportedOperation("write") def writelines(self, lines: Any) -> NoReturn: raise io.UnsupportedOperation("writelines") def writable(self) -> bool: return False def __enter__(self) -> GridOut: """Makes it possible to use :class:`GridOut` files with the context manager protocol. """ return self def __exit__(self, exc_type: Any, exc_val: Any, exc_tb: Any) -> Any: """Makes it possible to use :class:`GridOut` files with the context manager protocol. """ self.close() return False def fileno(self) -> NoReturn: raise io.UnsupportedOperation("fileno") def flush(self) -> None: # GridOut is read-only, so flush does nothing. pass def isatty(self) -> bool: return False def truncate(self, size: Optional[int] = None) -> NoReturn: # See https://docs.python.org/3/library/io.html#io.IOBase.writable # for why truncate has to raise. raise io.UnsupportedOperation("truncate") # Override IOBase.__del__ otherwise it will lead to __getattr__ on # __IOBase_closed which calls _ensure_file and potentially performs I/O. # We cannot do I/O in __del__ since it can lead to a deadlock. def __del__(self) -> None: pass class _GridOutChunkIterator: """Iterates over a file's chunks using a single cursor. Raises CorruptGridFile when encountering any truncated, missing, or extra chunk in a file. """ def __init__( self, grid_out: GridOut, chunks: Collection, session: Optional[ClientSession], next_chunk: Any, ) -> None: self._id = grid_out._id self._chunk_size = int(grid_out.chunk_size) self._length = int(grid_out.length) self._chunks = chunks self._session = session self._next_chunk = next_chunk self._num_chunks = math.ceil(float(self._length) / self._chunk_size) self._cursor = None _cursor: Optional[Cursor] def expected_chunk_length(self, chunk_n: int) -> int: if chunk_n < self._num_chunks - 1: return self._chunk_size return self._length - (self._chunk_size * (self._num_chunks - 1)) def __iter__(self) -> _GridOutChunkIterator: return self def _create_cursor(self) -> None: filter = {"files_id": self._id} if self._next_chunk > 0: filter["n"] = {"$gte": self._next_chunk} _disallow_transactions(self._session) self._cursor = self._chunks.find(filter, sort=[("n", 1)], session=self._session) def _next_with_retry(self) -> Mapping[str, Any]: """Return the next chunk and retry once on CursorNotFound. We retry on CursorNotFound to maintain backwards compatibility in cases where two calls to read occur more than 10 minutes apart (the server's default cursor timeout). """ if self._cursor is None: self._create_cursor() assert self._cursor is not None try: return self._cursor.next() except CursorNotFound: self._cursor.close() self._create_cursor() return self._cursor.next() def next(self) -> Mapping[str, Any]: try: chunk = self._next_with_retry() except StopIteration: if self._next_chunk >= self._num_chunks: raise raise CorruptGridFile("no chunk #%d" % self._next_chunk) from None if chunk["n"] != self._next_chunk: self.close() raise CorruptGridFile( "Missing chunk: expected chunk #%d but found " "chunk with n=%d" % (self._next_chunk, chunk["n"]) ) if chunk["n"] >= self._num_chunks: # According to spec, ignore extra chunks if they are empty. if len(chunk["data"]): self.close() raise CorruptGridFile( "Extra chunk found: expected %d chunks but found " "chunk with n=%d" % (self._num_chunks, chunk["n"]) ) expected_length = self.expected_chunk_length(chunk["n"]) if len(chunk["data"]) != expected_length: self.close() raise CorruptGridFile( "truncated chunk #%d: expected chunk length to be %d but " "found chunk with length %d" % (chunk["n"], expected_length, len(chunk["data"])) ) self._next_chunk += 1 return chunk __next__ = next def close(self) -> None: if self._cursor: self._cursor.close() self._cursor = None class GridOutIterator: def __init__(self, grid_out: GridOut, chunks: Collection, session: ClientSession): self.__chunk_iter = _GridOutChunkIterator(grid_out, chunks, session, 0) def __iter__(self) -> GridOutIterator: return self def next(self) -> bytes: chunk = self.__chunk_iter.next() return bytes(chunk["data"]) __next__ = next class GridOutCursor(Cursor): """A cursor / iterator for returning GridOut objects as the result of an arbitrary query against the GridFS files collection. """ def __init__( self, collection: Collection, filter: Optional[Mapping[str, Any]] = None, skip: int = 0, limit: int = 0, no_cursor_timeout: bool = False, sort: Optional[Any] = None, batch_size: int = 0, session: Optional[ClientSession] = None, ) -> None: """Create a new cursor, similar to the normal :class:`~pymongo.cursor.Cursor`. Should not be called directly by application developers - see the :class:`~gridfs.GridFS` method :meth:`~gridfs.GridFS.find` instead. .. versionadded 2.7 .. seealso:: The MongoDB documentation on `cursors `_. """ _disallow_transactions(session) collection = _clear_entity_type_registry(collection) # Hold on to the base "fs" collection to create GridOut objects later. self.__root_collection = collection super().__init__( collection.files, filter, skip=skip, limit=limit, no_cursor_timeout=no_cursor_timeout, sort=sort, batch_size=batch_size, session=session, ) def next(self) -> GridOut: """Get next GridOut object from cursor.""" _disallow_transactions(self.session) next_file = super().next() return GridOut(self.__root_collection, file_document=next_file, session=self.session) __next__ = next def add_option(self, *args: Any, **kwargs: Any) -> NoReturn: raise NotImplementedError("Method does not exist for GridOutCursor") def remove_option(self, *args: Any, **kwargs: Any) -> NoReturn: raise NotImplementedError("Method does not exist for GridOutCursor") def _clone_base(self, session: Optional[ClientSession]) -> GridOutCursor: """Creates an empty GridOutCursor for information to be copied into.""" return GridOutCursor(self.__root_collection, session=session) mongodb-mongo-python-driver-509e9b7/gridfs/py.typed000066400000000000000000000002521462766011000224110ustar00rootroot00000000000000# PEP-561 Support File. # "Package maintainers who wish to support type checking of their code MUST add a marker file named py.typed to their package supporting typing". mongodb-mongo-python-driver-509e9b7/mypy_test.ini000066400000000000000000000004261462766011000221750ustar00rootroot00000000000000[mypy] strict = true show_error_codes = true disable_error_code = attr-defined, union-attr, var-annotated, assignment, no-redef, type-arg, import, no-untyped-call, no-untyped-def, index, no-any-return, misc exclude = (?x)( ^test/mypy_fails/*.*$ | ^test/conftest.py$ ) mongodb-mongo-python-driver-509e9b7/pymongo/000077500000000000000000000000001462766011000211255ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/pymongo/__init__.py000066400000000000000000000121521462766011000232370ustar00rootroot00000000000000# Copyright 2009-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. """Python driver for MongoDB.""" from __future__ import annotations from typing import ContextManager, Optional __all__ = [ "ASCENDING", "DESCENDING", "GEO2D", "GEOSPHERE", "HASHED", "TEXT", "version_tuple", "get_version_string", "__version__", "version", "ReturnDocument", "MAX_SUPPORTED_WIRE_VERSION", "MIN_SUPPORTED_WIRE_VERSION", "CursorType", "MongoClient", "DeleteMany", "DeleteOne", "IndexModel", "InsertOne", "ReplaceOne", "UpdateMany", "UpdateOne", "ReadPreference", "WriteConcern", "has_c", "timeout", ] ASCENDING = 1 """Ascending sort order.""" DESCENDING = -1 """Descending sort order.""" GEO2D = "2d" """Index specifier for a 2-dimensional `geospatial index`_. .. _geospatial index: http://mongodb.com/docs/manual/core/2d/ """ GEOSPHERE = "2dsphere" """Index specifier for a `spherical geospatial index`_. .. versionadded:: 2.5 .. _spherical geospatial index: http://mongodb.com/docs/manual/core/2dsphere/ """ HASHED = "hashed" """Index specifier for a `hashed index`_. .. versionadded:: 2.5 .. _hashed index: http://mongodb.com/docs/manual/core/index-hashed/ """ TEXT = "text" """Index specifier for a `text index`_. .. seealso:: MongoDB's `Atlas Search `_ which offers more advanced text search functionality. .. versionadded:: 2.7.1 .. _text index: http://mongodb.com/docs/manual/core/index-text/ """ from pymongo import _csot from pymongo._version import __version__, get_version_string, version_tuple from pymongo.collection import ReturnDocument from pymongo.common import MAX_SUPPORTED_WIRE_VERSION, MIN_SUPPORTED_WIRE_VERSION from pymongo.cursor import CursorType from pymongo.mongo_client import MongoClient from pymongo.operations import ( DeleteMany, DeleteOne, IndexModel, InsertOne, ReplaceOne, UpdateMany, UpdateOne, ) from pymongo.read_preferences import ReadPreference from pymongo.write_concern import WriteConcern version = __version__ """Current version of PyMongo.""" def has_c() -> bool: """Is the C extension installed?""" try: from pymongo import _cmessage # type: ignore[attr-defined] # noqa: F401 return True except ImportError: return False def timeout(seconds: Optional[float]) -> ContextManager[None]: """**(Provisional)** Apply the given timeout for a block of operations. .. note:: :func:`~pymongo.timeout` is currently provisional. Backwards incompatible changes may occur before becoming officially supported. Use :func:`~pymongo.timeout` in a with-statement:: with pymongo.timeout(5): client.db.coll.insert_one({}) client.db.coll2.insert_one({}) When the with-statement is entered, a deadline is set for the entire block. When that deadline is exceeded, any blocking pymongo operation will raise a timeout exception. For example:: try: with pymongo.timeout(5): client.db.coll.insert_one({}) time.sleep(5) # The deadline has now expired, the next operation will raise # a timeout exception. client.db.coll2.insert_one({}) except PyMongoError as exc: if exc.timeout: print(f"block timed out: {exc!r}") else: print(f"failed with non-timeout error: {exc!r}") When nesting :func:`~pymongo.timeout`, the nested deadline is capped by the outer deadline. The deadline can only be shortened, not extended. When exiting the block, the previous deadline is restored:: with pymongo.timeout(5): coll.find_one() # Uses the 5 second deadline. with pymongo.timeout(3): coll.find_one() # Uses the 3 second deadline. coll.find_one() # Uses the original 5 second deadline. with pymongo.timeout(10): coll.find_one() # Still uses the original 5 second deadline. coll.find_one() # Uses the original 5 second deadline. :param seconds: A non-negative floating point number expressing seconds, or None. :raises: :py:class:`ValueError`: When `seconds` is negative. See :ref:`timeout-example` for more examples. .. versionadded:: 4.2 """ if not isinstance(seconds, (int, float, type(None))): raise TypeError("timeout must be None, an int, or a float") if seconds and seconds < 0: raise ValueError("timeout cannot be negative") if seconds is not None: seconds = float(seconds) return _csot._TimeoutContext(seconds) mongodb-mongo-python-driver-509e9b7/pymongo/_azure_helpers.py000066400000000000000000000037251462766011000245150ustar00rootroot00000000000000# Copyright 2023-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. """Azure helpers.""" from __future__ import annotations import json from typing import Any, Optional def _get_azure_response( resource: str, client_id: Optional[str] = None, timeout: float = 5 ) -> dict[str, Any]: # Deferred import to save overall import time. from urllib.request import Request, urlopen url = "http://169.254.169.254/metadata/identity/oauth2/token" url += "?api-version=2018-02-01" url += f"&resource={resource}" if client_id: url += f"&client_id={client_id}" headers = {"Metadata": "true", "Accept": "application/json"} request = Request(url, headers=headers) # noqa: S310 try: with urlopen(request, timeout=timeout) as response: # noqa: S310 status = response.status body = response.read().decode("utf8") except Exception as e: msg = "Failed to acquire IMDS access token: %s" % e raise ValueError(msg) from None if status != 200: msg = "Failed to acquire IMDS access token." raise ValueError(msg) try: data = json.loads(body) except Exception: raise ValueError("Azure IMDS response must be in JSON format.") from None for key in ["access_token", "expires_in"]: if not data.get(key): msg = "Azure IMDS response must contain %s, but was %s." msg = msg % (key, body) raise ValueError(msg) return data mongodb-mongo-python-driver-509e9b7/pymongo/_cmessagemodule.c000066400000000000000000000773411462766011000244410ustar00rootroot00000000000000/* * Copyright 2009-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. */ /* * This file contains C implementations of some of the functions * needed by the message module. If possible, these implementations * should be used to speed up message creation. */ #define PY_SSIZE_T_CLEAN #include "Python.h" #include "_cbsonmodule.h" #include "buffer.h" struct module_state { PyObject* _cbson; PyObject* _max_bson_size_str; PyObject* _max_message_size_str; PyObject* _max_write_batch_size_str; PyObject* _max_split_size_str; }; /* See comments about module initialization in _cbsonmodule.c */ #define GETSTATE(m) ((struct module_state*)PyModule_GetState(m)) #define DOC_TOO_LARGE_FMT "BSON document too large (%d bytes)" \ " - the connected server supports" \ " BSON document sizes up to %ld bytes." /* Get an error class from the pymongo.errors module. * * Returns a new ref */ static PyObject* _error(char* name) { PyObject* error; PyObject* errors = PyImport_ImportModule("pymongo.errors"); if (!errors) { return NULL; } error = PyObject_GetAttrString(errors, name); Py_DECREF(errors); return error; } /* The same as buffer_write_bytes except that it also validates * "size" will fit in an int. * Returns 0 on failure */ static int buffer_write_bytes_ssize_t(buffer_t buffer, const char* data, Py_ssize_t size) { int downsize = _downcast_and_check(size, 0); if (size == -1) { return 0; } return buffer_write_bytes(buffer, data, downsize); } static PyObject* _cbson_query_message(PyObject* self, PyObject* args) { /* NOTE just using a random number as the request_id */ int request_id = rand(); unsigned int flags; char* collection_name = NULL; Py_ssize_t collection_name_length; int begin, cur_size, max_size = 0; int num_to_skip; int num_to_return; PyObject* query; PyObject* field_selector; PyObject* options_obj; codec_options_t options; buffer_t buffer = NULL; int length_location, message_length; PyObject* result = NULL; struct module_state *state = GETSTATE(self); if (!state) { return NULL; } if (!(PyArg_ParseTuple(args, "Iet#iiOOO", &flags, "utf-8", &collection_name, &collection_name_length, &num_to_skip, &num_to_return, &query, &field_selector, &options_obj) && convert_codec_options(state->_cbson, options_obj, &options))) { return NULL; } buffer = pymongo_buffer_new(); if (!buffer) { goto fail; } // save space for message length length_location = pymongo_buffer_save_space(buffer, 4); if (length_location == -1) { goto fail; } if (!buffer_write_int32(buffer, (int32_t)request_id) || !buffer_write_bytes(buffer, "\x00\x00\x00\x00\xd4\x07\x00\x00", 8) || !buffer_write_int32(buffer, (int32_t)flags) || !buffer_write_bytes_ssize_t(buffer, collection_name, collection_name_length + 1) || !buffer_write_int32(buffer, (int32_t)num_to_skip) || !buffer_write_int32(buffer, (int32_t)num_to_return)) { goto fail; } begin = pymongo_buffer_get_position(buffer); if (!write_dict(state->_cbson, buffer, query, 0, &options, 1)) { goto fail; } max_size = pymongo_buffer_get_position(buffer) - begin; if (field_selector != Py_None) { begin = pymongo_buffer_get_position(buffer); if (!write_dict(state->_cbson, buffer, field_selector, 0, &options, 1)) { goto fail; } cur_size = pymongo_buffer_get_position(buffer) - begin; max_size = (cur_size > max_size) ? cur_size : max_size; } message_length = pymongo_buffer_get_position(buffer) - length_location; buffer_write_int32_at_position( buffer, length_location, (int32_t)message_length); /* objectify buffer */ result = Py_BuildValue("iy#i", request_id, pymongo_buffer_get_buffer(buffer), (Py_ssize_t)pymongo_buffer_get_position(buffer), max_size); fail: PyMem_Free(collection_name); destroy_codec_options(&options); if (buffer) { pymongo_buffer_free(buffer); } return result; } static PyObject* _cbson_get_more_message(PyObject* self, PyObject* args) { /* NOTE just using a random number as the request_id */ int request_id = rand(); char* collection_name = NULL; Py_ssize_t collection_name_length; int num_to_return; long long cursor_id; buffer_t buffer = NULL; int length_location, message_length; PyObject* result = NULL; if (!PyArg_ParseTuple(args, "et#iL", "utf-8", &collection_name, &collection_name_length, &num_to_return, &cursor_id)) { return NULL; } buffer = pymongo_buffer_new(); if (!buffer) { goto fail; } // save space for message length length_location = pymongo_buffer_save_space(buffer, 4); if (length_location == -1) { goto fail; } if (!buffer_write_int32(buffer, (int32_t)request_id) || !buffer_write_bytes(buffer, "\x00\x00\x00\x00" "\xd5\x07\x00\x00" "\x00\x00\x00\x00", 12) || !buffer_write_bytes_ssize_t(buffer, collection_name, collection_name_length + 1) || !buffer_write_int32(buffer, (int32_t)num_to_return) || !buffer_write_int64(buffer, (int64_t)cursor_id)) { goto fail; } message_length = pymongo_buffer_get_position(buffer) - length_location; buffer_write_int32_at_position( buffer, length_location, (int32_t)message_length); /* objectify buffer */ result = Py_BuildValue("iy#", request_id, pymongo_buffer_get_buffer(buffer), (Py_ssize_t)pymongo_buffer_get_position(buffer)); fail: PyMem_Free(collection_name); if (buffer) { pymongo_buffer_free(buffer); } return result; } /* * NOTE this method handles multiple documents in a type one payload but * it does not perform batch splitting and the total message size is * only checked *after* generating the entire message. */ static PyObject* _cbson_op_msg(PyObject* self, PyObject* args) { /* NOTE just using a random number as the request_id */ int request_id = rand(); unsigned int flags; PyObject* command; char* identifier = NULL; Py_ssize_t identifier_length = 0; PyObject* docs; PyObject* doc; PyObject* options_obj; codec_options_t options; buffer_t buffer = NULL; int length_location, message_length; int total_size = 0; int max_doc_size = 0; PyObject* result = NULL; PyObject* iterator = NULL; struct module_state *state = GETSTATE(self); if (!state) { return NULL; } /*flags, command, identifier, docs, opts*/ if (!(PyArg_ParseTuple(args, "IOet#OO", &flags, &command, "utf-8", &identifier, &identifier_length, &docs, &options_obj) && convert_codec_options(state->_cbson, options_obj, &options))) { return NULL; } buffer = pymongo_buffer_new(); if (!buffer) { goto fail; } // save space for message length length_location = pymongo_buffer_save_space(buffer, 4); if (length_location == -1) { goto fail; } if (!buffer_write_int32(buffer, (int32_t)request_id) || !buffer_write_bytes(buffer, "\x00\x00\x00\x00" /* responseTo */ "\xdd\x07\x00\x00" /* 2013 */, 8)) { goto fail; } if (!buffer_write_int32(buffer, (int32_t)flags) || !buffer_write_bytes(buffer, "\x00", 1) /* Payload type 0 */) { goto fail; } total_size = write_dict(state->_cbson, buffer, command, 0, &options, 1); if (!total_size) { goto fail; } if (identifier_length) { int payload_one_length_location, payload_length; /* Payload type 1 */ if (!buffer_write_bytes(buffer, "\x01", 1)) { goto fail; } /* save space for payload 0 length */ payload_one_length_location = pymongo_buffer_save_space(buffer, 4); /* C string identifier */ if (!buffer_write_bytes_ssize_t(buffer, identifier, identifier_length + 1)) { goto fail; } iterator = PyObject_GetIter(docs); if (iterator == NULL) { goto fail; } while ((doc = PyIter_Next(iterator)) != NULL) { int encoded_doc_size = write_dict( state->_cbson, buffer, doc, 0, &options, 1); if (!encoded_doc_size) { Py_CLEAR(doc); goto fail; } if (encoded_doc_size > max_doc_size) { max_doc_size = encoded_doc_size; } Py_CLEAR(doc); } payload_length = pymongo_buffer_get_position(buffer) - payload_one_length_location; buffer_write_int32_at_position( buffer, payload_one_length_location, (int32_t)payload_length); total_size += payload_length; } message_length = pymongo_buffer_get_position(buffer) - length_location; buffer_write_int32_at_position( buffer, length_location, (int32_t)message_length); /* objectify buffer */ result = Py_BuildValue("iy#ii", request_id, pymongo_buffer_get_buffer(buffer), (Py_ssize_t)pymongo_buffer_get_position(buffer), total_size, max_doc_size); fail: Py_XDECREF(iterator); if (buffer) { pymongo_buffer_free(buffer); } PyMem_Free(identifier); destroy_codec_options(&options); return result; } static void _set_document_too_large(int size, long max) { PyObject* DocumentTooLarge = _error("DocumentTooLarge"); if (DocumentTooLarge) { PyObject* error = PyUnicode_FromFormat(DOC_TOO_LARGE_FMT, size, max); if (error) { PyErr_SetObject(DocumentTooLarge, error); Py_DECREF(error); } Py_DECREF(DocumentTooLarge); } } #define _INSERT 0 #define _UPDATE 1 #define _DELETE 2 /* OP_MSG ----------------------------------------------- */ static int _batched_op_msg( unsigned char op, unsigned char ack, PyObject* command, PyObject* docs, PyObject* ctx, PyObject* to_publish, codec_options_t options, buffer_t buffer, struct module_state *state) { long max_bson_size; long max_write_batch_size; long max_message_size; int idx = 0; int size_location; int position; int length; PyObject* max_bson_size_obj = NULL; PyObject* max_write_batch_size_obj = NULL; PyObject* max_message_size_obj = NULL; PyObject* doc = NULL; PyObject* iterator = NULL; char* flags = ack ? "\x00\x00\x00\x00" : "\x02\x00\x00\x00"; max_bson_size_obj = PyObject_GetAttr(ctx, state->_max_bson_size_str); max_bson_size = PyLong_AsLong(max_bson_size_obj); Py_XDECREF(max_bson_size_obj); if (max_bson_size == -1) { return 0; } max_write_batch_size_obj = PyObject_GetAttr(ctx, state->_max_write_batch_size_str); max_write_batch_size = PyLong_AsLong(max_write_batch_size_obj); Py_XDECREF(max_write_batch_size_obj); if (max_write_batch_size == -1) { return 0; } max_message_size_obj = PyObject_GetAttr(ctx, state->_max_message_size_str); max_message_size = PyLong_AsLong(max_message_size_obj); Py_XDECREF(max_message_size_obj); if (max_message_size == -1) { return 0; } if (!buffer_write_bytes(buffer, flags, 4)) { return 0; } /* Type 0 Section */ if (!buffer_write_bytes(buffer, "\x00", 1)) { return 0; } if (!write_dict(state->_cbson, buffer, command, 0, &options, 0)) { return 0; } /* Type 1 Section */ if (!buffer_write_bytes(buffer, "\x01", 1)) { return 0; } /* Save space for size */ size_location = pymongo_buffer_save_space(buffer, 4); if (size_location == -1) { return 0; } switch (op) { case _INSERT: { if (!buffer_write_bytes(buffer, "documents\x00", 10)) goto fail; break; } case _UPDATE: { if (!buffer_write_bytes(buffer, "updates\x00", 8)) goto fail; break; } case _DELETE: { if (!buffer_write_bytes(buffer, "deletes\x00", 8)) goto fail; break; } default: { PyObject* InvalidOperation = _error("InvalidOperation"); if (InvalidOperation) { PyErr_SetString(InvalidOperation, "Unknown command"); Py_DECREF(InvalidOperation); } return 0; } } iterator = PyObject_GetIter(docs); if (iterator == NULL) { PyObject* InvalidOperation = _error("InvalidOperation"); if (InvalidOperation) { PyErr_SetString(InvalidOperation, "input is not iterable"); Py_DECREF(InvalidOperation); } return 0; } while ((doc = PyIter_Next(iterator)) != NULL) { int cur_doc_begin = pymongo_buffer_get_position(buffer); int cur_size; int doc_too_large = 0; int unacked_doc_too_large = 0; if (!write_dict(state->_cbson, buffer, doc, 0, &options, 1)) { goto fail; } cur_size = pymongo_buffer_get_position(buffer) - cur_doc_begin; /* Does the first document exceed max_message_size? */ doc_too_large = (idx == 0 && (pymongo_buffer_get_position(buffer) > max_message_size)); /* When OP_MSG is used unacknowledged we have to check * document size client side or applications won't be notified. * Otherwise we let the server deal with documents that are too large * since ordered=False causes those documents to be skipped instead of * halting the bulk write operation. * */ unacked_doc_too_large = (!ack && cur_size > max_bson_size); if (doc_too_large || unacked_doc_too_large) { if (op == _INSERT) { _set_document_too_large(cur_size, max_bson_size); } else { PyObject* DocumentTooLarge = _error("DocumentTooLarge"); if (DocumentTooLarge) { /* * There's nothing intelligent we can say * about size for update and delete. */ PyErr_Format( DocumentTooLarge, "%s command document too large", (op == _UPDATE) ? "update": "delete"); Py_DECREF(DocumentTooLarge); } } goto fail; } /* We have enough data, return this batch. */ if (pymongo_buffer_get_position(buffer) > max_message_size) { /* * Roll the existing buffer back to the beginning * of the last document encoded. */ pymongo_buffer_update_position(buffer, cur_doc_begin); Py_CLEAR(doc); break; } if (PyList_Append(to_publish, doc) < 0) { goto fail; } Py_CLEAR(doc); idx += 1; /* We have enough documents, return this batch. */ if (idx == max_write_batch_size) { break; } } Py_CLEAR(iterator); if (PyErr_Occurred()) { goto fail; } position = pymongo_buffer_get_position(buffer); length = position - size_location; buffer_write_int32_at_position(buffer, size_location, (int32_t)length); return 1; fail: Py_XDECREF(doc); Py_XDECREF(iterator); return 0; } static PyObject* _cbson_encode_batched_op_msg(PyObject* self, PyObject* args) { unsigned char op; unsigned char ack; PyObject* command; PyObject* docs; PyObject* ctx = NULL; PyObject* to_publish = NULL; PyObject* result = NULL; PyObject* options_obj; codec_options_t options; buffer_t buffer; struct module_state *state = GETSTATE(self); if (!state) { return NULL; } if (!(PyArg_ParseTuple(args, "bOObOO", &op, &command, &docs, &ack, &options_obj, &ctx) && convert_codec_options(state->_cbson, options_obj, &options))) { return NULL; } if (!(buffer = pymongo_buffer_new())) { destroy_codec_options(&options); return NULL; } if (!(to_publish = PyList_New(0))) { goto fail; } if (!_batched_op_msg( op, ack, command, docs, ctx, to_publish, options, buffer, state)) { goto fail; } result = Py_BuildValue("y#O", pymongo_buffer_get_buffer(buffer), (Py_ssize_t)pymongo_buffer_get_position(buffer), to_publish); fail: destroy_codec_options(&options); pymongo_buffer_free(buffer); Py_XDECREF(to_publish); return result; } static PyObject* _cbson_batched_op_msg(PyObject* self, PyObject* args) { unsigned char op; unsigned char ack; int request_id; int position; PyObject* command; PyObject* docs; PyObject* ctx = NULL; PyObject* to_publish = NULL; PyObject* result = NULL; PyObject* options_obj; codec_options_t options; buffer_t buffer; struct module_state *state = GETSTATE(self); if (!state) { return NULL; } if (!(PyArg_ParseTuple(args, "bOObOO", &op, &command, &docs, &ack, &options_obj, &ctx) && convert_codec_options(state->_cbson, options_obj, &options))) { return NULL; } if (!(buffer = pymongo_buffer_new())) { destroy_codec_options(&options); return NULL; } /* Save space for message length and request id */ if ((pymongo_buffer_save_space(buffer, 8)) == -1) { goto fail; } if (!buffer_write_bytes(buffer, "\x00\x00\x00\x00" /* responseTo */ "\xdd\x07\x00\x00", /* opcode */ 8)) { goto fail; } if (!(to_publish = PyList_New(0))) { goto fail; } if (!_batched_op_msg( op, ack, command, docs, ctx, to_publish, options, buffer, state)) { goto fail; } request_id = rand(); position = pymongo_buffer_get_position(buffer); buffer_write_int32_at_position(buffer, 0, (int32_t)position); buffer_write_int32_at_position(buffer, 4, (int32_t)request_id); result = Py_BuildValue("iy#O", request_id, pymongo_buffer_get_buffer(buffer), (Py_ssize_t)pymongo_buffer_get_position(buffer), to_publish); fail: destroy_codec_options(&options); pymongo_buffer_free(buffer); Py_XDECREF(to_publish); return result; } /* End OP_MSG -------------------------------------------- */ static int _batched_write_command( char* ns, Py_ssize_t ns_len, unsigned char op, PyObject* command, PyObject* docs, PyObject* ctx, PyObject* to_publish, codec_options_t options, buffer_t buffer, struct module_state *state) { long max_bson_size; long max_cmd_size; long max_write_batch_size; long max_split_size; int idx = 0; int cmd_len_loc; int lst_len_loc; int position; int length; PyObject* max_bson_size_obj = NULL; PyObject* max_write_batch_size_obj = NULL; PyObject* max_split_size_obj = NULL; PyObject* doc = NULL; PyObject* iterator = NULL; max_bson_size_obj = PyObject_GetAttr(ctx, state->_max_bson_size_str); max_bson_size = PyLong_AsLong(max_bson_size_obj); Py_XDECREF(max_bson_size_obj); if (max_bson_size == -1) { return 0; } /* * Max BSON object size + 16k - 2 bytes for ending NUL bytes * XXX: This should come from the server - SERVER-10643 */ max_cmd_size = max_bson_size + 16382; max_write_batch_size_obj = PyObject_GetAttr(ctx, state->_max_write_batch_size_str); max_write_batch_size = PyLong_AsLong(max_write_batch_size_obj); Py_XDECREF(max_write_batch_size_obj); if (max_write_batch_size == -1) { return 0; } // max_split_size is the size at which to perform a batch split. // Normally this this value is equal to max_bson_size (16MiB). However, // when auto encryption is enabled max_split_size is reduced to 2MiB. max_split_size_obj = PyObject_GetAttr(ctx, state->_max_split_size_str); max_split_size = PyLong_AsLong(max_split_size_obj); Py_XDECREF(max_split_size_obj); if (max_split_size == -1) { return 0; } if (!buffer_write_bytes(buffer, "\x00\x00\x00\x00", /* flags */ 4) || !buffer_write_bytes_ssize_t(buffer, ns, ns_len + 1) || /* namespace */ !buffer_write_bytes(buffer, "\x00\x00\x00\x00" /* skip */ "\xFF\xFF\xFF\xFF", /* limit (-1) */ 8)) { return 0; } /* Position of command document length */ cmd_len_loc = pymongo_buffer_get_position(buffer); if (!write_dict(state->_cbson, buffer, command, 0, &options, 0)) { return 0; } /* Write type byte for array */ *(pymongo_buffer_get_buffer(buffer) + (pymongo_buffer_get_position(buffer) - 1)) = 0x4; switch (op) { case _INSERT: { if (!buffer_write_bytes(buffer, "documents\x00", 10)) goto fail; break; } case _UPDATE: { if (!buffer_write_bytes(buffer, "updates\x00", 8)) goto fail; break; } case _DELETE: { if (!buffer_write_bytes(buffer, "deletes\x00", 8)) goto fail; break; } default: { PyObject* InvalidOperation = _error("InvalidOperation"); if (InvalidOperation) { PyErr_SetString(InvalidOperation, "Unknown command"); Py_DECREF(InvalidOperation); } return 0; } } /* Save space for list document */ lst_len_loc = pymongo_buffer_save_space(buffer, 4); if (lst_len_loc == -1) { return 0; } iterator = PyObject_GetIter(docs); if (iterator == NULL) { PyObject* InvalidOperation = _error("InvalidOperation"); if (InvalidOperation) { PyErr_SetString(InvalidOperation, "input is not iterable"); Py_DECREF(InvalidOperation); } return 0; } while ((doc = PyIter_Next(iterator)) != NULL) { int sub_doc_begin = pymongo_buffer_get_position(buffer); int cur_doc_begin; int cur_size; int enough_data = 0; char key[BUF_SIZE]; int res = LL2STR(key, (long long)idx); if (res == -1) { return 0; } if (!buffer_write_bytes(buffer, "\x03", 1) || !buffer_write_bytes(buffer, key, (int)strlen(key) + 1)) { goto fail; } cur_doc_begin = pymongo_buffer_get_position(buffer); if (!write_dict(state->_cbson, buffer, doc, 0, &options, 1)) { goto fail; } /* We have enough data, return this batch. * max_cmd_size accounts for the two trailing null bytes. */ cur_size = pymongo_buffer_get_position(buffer) - cur_doc_begin; /* This single document is too large for the command. */ if (cur_size > max_cmd_size) { if (op == _INSERT) { _set_document_too_large(cur_size, max_bson_size); } else { PyObject* DocumentTooLarge = _error("DocumentTooLarge"); if (DocumentTooLarge) { /* * There's nothing intelligent we can say * about size for update and delete. */ PyErr_Format( DocumentTooLarge, "%s command document too large", (op == _UPDATE) ? "update": "delete"); Py_DECREF(DocumentTooLarge); } } goto fail; } enough_data = (idx >= 1 && (pymongo_buffer_get_position(buffer) > max_split_size)); if (enough_data) { /* * Roll the existing buffer back to the beginning * of the last document encoded. */ pymongo_buffer_update_position(buffer, sub_doc_begin); Py_CLEAR(doc); break; } if (PyList_Append(to_publish, doc) < 0) { goto fail; } Py_CLEAR(doc); idx += 1; /* We have enough documents, return this batch. */ if (idx == max_write_batch_size) { break; } } Py_CLEAR(iterator); if (PyErr_Occurred()) { goto fail; } if (!buffer_write_bytes(buffer, "\x00\x00", 2)) { goto fail; } position = pymongo_buffer_get_position(buffer); length = position - lst_len_loc - 1; buffer_write_int32_at_position(buffer, lst_len_loc, (int32_t)length); length = position - cmd_len_loc; buffer_write_int32_at_position(buffer, cmd_len_loc, (int32_t)length); return 1; fail: Py_XDECREF(doc); Py_XDECREF(iterator); return 0; } static PyObject* _cbson_encode_batched_write_command(PyObject* self, PyObject* args) { char *ns = NULL; unsigned char op; Py_ssize_t ns_len; PyObject* command; PyObject* docs; PyObject* ctx = NULL; PyObject* to_publish = NULL; PyObject* result = NULL; PyObject* options_obj; codec_options_t options; buffer_t buffer; struct module_state *state = GETSTATE(self); if (!state) { return NULL; } if (!(PyArg_ParseTuple(args, "et#bOOOO", "utf-8", &ns, &ns_len, &op, &command, &docs, &options_obj, &ctx) && convert_codec_options(state->_cbson, options_obj, &options))) { return NULL; } if (!(buffer = pymongo_buffer_new())) { PyMem_Free(ns); destroy_codec_options(&options); return NULL; } if (!(to_publish = PyList_New(0))) { goto fail; } if (!_batched_write_command( ns, ns_len, op, command, docs, ctx, to_publish, options, buffer, state)) { goto fail; } result = Py_BuildValue("y#O", pymongo_buffer_get_buffer(buffer), (Py_ssize_t)pymongo_buffer_get_position(buffer), to_publish); fail: PyMem_Free(ns); destroy_codec_options(&options); pymongo_buffer_free(buffer); Py_XDECREF(to_publish); return result; } static PyMethodDef _CMessageMethods[] = { {"_query_message", _cbson_query_message, METH_VARARGS, "create a query message to be sent to MongoDB"}, {"_get_more_message", _cbson_get_more_message, METH_VARARGS, "create a get more message to be sent to MongoDB"}, {"_op_msg", _cbson_op_msg, METH_VARARGS, "create an OP_MSG message to be sent to MongoDB"}, {"_encode_batched_write_command", _cbson_encode_batched_write_command, METH_VARARGS, "Encode the next batched insert, update, or delete command"}, {"_batched_op_msg", _cbson_batched_op_msg, METH_VARARGS, "Create the next batched insert, update, or delete using OP_MSG"}, {"_encode_batched_op_msg", _cbson_encode_batched_op_msg, METH_VARARGS, "Encode the next batched insert, update, or delete using OP_MSG"}, {NULL, NULL, 0, NULL} }; #define INITERROR return -1; static int _cmessage_traverse(PyObject *m, visitproc visit, void *arg) { struct module_state *state = GETSTATE(m); if (!state) { return 0; } Py_VISIT(state->_cbson); Py_VISIT(state->_max_bson_size_str); Py_VISIT(state->_max_message_size_str); Py_VISIT(state->_max_split_size_str); Py_VISIT(state->_max_write_batch_size_str); return 0; } static int _cmessage_clear(PyObject *m) { struct module_state *state = GETSTATE(m); if (!state) { return 0; } Py_CLEAR(state->_cbson); Py_CLEAR(state->_max_bson_size_str); Py_CLEAR(state->_max_message_size_str); Py_CLEAR(state->_max_split_size_str); Py_CLEAR(state->_max_write_batch_size_str); return 0; } /* Multi-phase extension module initialization code. * See https://peps.python.org/pep-0489/. */ static int _cmessage_exec(PyObject *m) { PyObject *_cbson = NULL; PyObject *c_api_object = NULL; struct module_state* state = NULL; /* Store a reference to the _cbson module since it's needed to call some * of its functions */ _cbson = PyImport_ImportModule("bson._cbson"); if (_cbson == NULL) { goto fail; } /* Import C API of _cbson * The header file accesses _cbson_API to call the functions */ c_api_object = PyObject_GetAttrString(_cbson, "_C_API"); if (c_api_object == NULL) { goto fail; } _cbson_API = (void **)PyCapsule_GetPointer(c_api_object, "_cbson._C_API"); if (_cbson_API == NULL) { goto fail; } state = GETSTATE(m); if (state == NULL) { goto fail; } state->_cbson = _cbson; if (!((state->_max_bson_size_str = PyUnicode_FromString("max_bson_size")) && (state->_max_message_size_str = PyUnicode_FromString("max_message_size")) && (state->_max_write_batch_size_str = PyUnicode_FromString("max_write_batch_size")) && (state->_max_split_size_str = PyUnicode_FromString("max_split_size")))) { goto fail; } Py_DECREF(c_api_object); return 0; fail: Py_XDECREF(m); Py_XDECREF(c_api_object); Py_XDECREF(_cbson); INITERROR; } static PyModuleDef_Slot _cmessage_slots[] = { {Py_mod_exec, _cmessage_exec}, #ifdef Py_MOD_MULTIPLE_INTERPRETERS_SUPPORTED {Py_mod_multiple_interpreters, Py_MOD_MULTIPLE_INTERPRETERS_SUPPORTED}, #endif {0, NULL}, }; static struct PyModuleDef moduledef = { PyModuleDef_HEAD_INIT, "_cmessage", NULL, sizeof(struct module_state), _CMessageMethods, _cmessage_slots, _cmessage_traverse, _cmessage_clear, NULL }; PyMODINIT_FUNC PyInit__cmessage(void) { return PyModuleDef_Init(&moduledef); } mongodb-mongo-python-driver-509e9b7/pymongo/_csot.py000066400000000000000000000110611462766011000226050ustar00rootroot00000000000000# Copyright 2022-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. """Internal helpers for CSOT.""" from __future__ import annotations import functools import time from collections import deque from contextlib import AbstractContextManager from contextvars import ContextVar, Token from typing import TYPE_CHECKING, Any, Callable, Deque, MutableMapping, Optional, TypeVar, cast if TYPE_CHECKING: from pymongo.write_concern import WriteConcern TIMEOUT: ContextVar[Optional[float]] = ContextVar("TIMEOUT", default=None) RTT: ContextVar[float] = ContextVar("RTT", default=0.0) DEADLINE: ContextVar[float] = ContextVar("DEADLINE", default=float("inf")) def get_timeout() -> Optional[float]: return TIMEOUT.get(None) def get_rtt() -> float: return RTT.get() def get_deadline() -> float: return DEADLINE.get() def set_rtt(rtt: float) -> None: RTT.set(rtt) def remaining() -> Optional[float]: if not get_timeout(): return None return DEADLINE.get() - time.monotonic() def clamp_remaining(max_timeout: float) -> float: """Return the remaining timeout clamped to a max value.""" timeout = remaining() if timeout is None: return max_timeout return min(timeout, max_timeout) class _TimeoutContext(AbstractContextManager): """Internal timeout context manager. Use :func:`pymongo.timeout` instead:: with pymongo.timeout(0.5): client.test.test.insert_one({}) """ def __init__(self, timeout: Optional[float]): self._timeout = timeout self._tokens: Optional[tuple[Token[Optional[float]], Token[float], Token[float]]] = None def __enter__(self) -> _TimeoutContext: timeout_token = TIMEOUT.set(self._timeout) prev_deadline = DEADLINE.get() next_deadline = time.monotonic() + self._timeout if self._timeout else float("inf") deadline_token = DEADLINE.set(min(prev_deadline, next_deadline)) rtt_token = RTT.set(0.0) self._tokens = (timeout_token, deadline_token, rtt_token) return self def __exit__(self, exc_type: Any, exc_val: Any, exc_tb: Any) -> None: if self._tokens: timeout_token, deadline_token, rtt_token = self._tokens TIMEOUT.reset(timeout_token) DEADLINE.reset(deadline_token) RTT.reset(rtt_token) # See https://mypy.readthedocs.io/en/stable/generics.html?#decorator-factories F = TypeVar("F", bound=Callable[..., Any]) def apply(func: F) -> F: """Apply the client's timeoutMS to this operation.""" @functools.wraps(func) def csot_wrapper(self: Any, *args: Any, **kwargs: Any) -> Any: if get_timeout() is None: timeout = self._timeout if timeout is not None: with _TimeoutContext(timeout): return func(self, *args, **kwargs) return func(self, *args, **kwargs) return cast(F, csot_wrapper) def apply_write_concern( cmd: MutableMapping[str, Any], write_concern: Optional[WriteConcern] ) -> None: """Apply the given write concern to a command.""" if not write_concern or write_concern.is_server_default: return wc = write_concern.document if get_timeout() is not None: wc.pop("wtimeout", None) if wc: cmd["writeConcern"] = wc _MAX_RTT_SAMPLES: int = 10 _MIN_RTT_SAMPLES: int = 2 class MovingMinimum: """Tracks a minimum RTT within the last 10 RTT samples.""" samples: Deque[float] def __init__(self) -> None: self.samples = deque(maxlen=_MAX_RTT_SAMPLES) def add_sample(self, sample: float) -> None: if sample < 0: # Likely system time change while waiting for hello response # and not using time.monotonic. Ignore it, the next one will # probably be valid. return self.samples.append(sample) def get(self) -> float: """Get the min, or 0.0 if there aren't enough samples yet.""" if len(self.samples) >= _MIN_RTT_SAMPLES: return min(self.samples) return 0.0 def reset(self) -> None: self.samples.clear() mongodb-mongo-python-driver-509e9b7/pymongo/_gcp_helpers.py000066400000000000000000000026551462766011000241410ustar00rootroot00000000000000# Copyright 2024-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. """GCP helpers.""" from __future__ import annotations from typing import Any def _get_gcp_response(resource: str, timeout: float = 5) -> dict[str, Any]: from urllib.request import Request, urlopen url = "http://metadata/computeMetadata/v1/instance/service-accounts/default/identity" url += f"?audience={resource}" headers = {"Metadata-Flavor": "Google"} request = Request(url, headers=headers) # noqa: S310 try: with urlopen(request, timeout=timeout) as response: # noqa: S310 status = response.status body = response.read().decode("utf8") except Exception as e: msg = "Failed to acquire IMDS access token: %s" % e raise ValueError(msg) from None if status != 200: msg = "Failed to acquire IMDS access token." raise ValueError(msg) return dict(access_token=body) mongodb-mongo-python-driver-509e9b7/pymongo/_version.py000066400000000000000000000017511462766011000233270ustar00rootroot00000000000000# Copyright 2022-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. """Current version of PyMongo.""" from __future__ import annotations from typing import Tuple, Union version_tuple: Tuple[Union[int, str], ...] = (4, 7, 3) def get_version_string() -> str: if isinstance(version_tuple[-1], str): return ".".join(map(str, version_tuple[:-1])) + version_tuple[-1] return ".".join(map(str, version_tuple)) __version__: str = get_version_string() version = __version__ mongodb-mongo-python-driver-509e9b7/pymongo/aggregation.py000066400000000000000000000221651462766011000237740ustar00rootroot00000000000000# Copyright 2019-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. """Perform aggregation operations on a collection or database.""" from __future__ import annotations from collections.abc import Callable, Mapping, MutableMapping from typing import TYPE_CHECKING, Any, Optional, Union from pymongo import common from pymongo.collation import validate_collation_or_none from pymongo.errors import ConfigurationError from pymongo.read_preferences import ReadPreference, _AggWritePref if TYPE_CHECKING: from pymongo.client_session import ClientSession from pymongo.collection import Collection from pymongo.command_cursor import CommandCursor from pymongo.database import Database from pymongo.pool import Connection from pymongo.read_preferences import _ServerMode from pymongo.server import Server from pymongo.typings import _DocumentType, _Pipeline class _AggregationCommand: """The internal abstract base class for aggregation cursors. Should not be called directly by application developers. Use :meth:`pymongo.collection.Collection.aggregate`, or :meth:`pymongo.database.Database.aggregate` instead. """ def __init__( self, target: Union[Database, Collection], cursor_class: type[CommandCursor], pipeline: _Pipeline, options: MutableMapping[str, Any], explicit_session: bool, let: Optional[Mapping[str, Any]] = None, user_fields: Optional[MutableMapping[str, Any]] = None, result_processor: Optional[Callable[[Mapping[str, Any], Connection], None]] = None, comment: Any = None, ) -> None: if "explain" in options: raise ConfigurationError( "The explain option is not supported. Use Database.command instead." ) self._target = target pipeline = common.validate_list("pipeline", pipeline) self._pipeline = pipeline self._performs_write = False if pipeline and ("$out" in pipeline[-1] or "$merge" in pipeline[-1]): self._performs_write = True common.validate_is_mapping("options", options) if let is not None: common.validate_is_mapping("let", let) options["let"] = let if comment is not None: options["comment"] = comment self._options = options # This is the batchSize that will be used for setting the initial # batchSize for the cursor, as well as the subsequent getMores. self._batch_size = common.validate_non_negative_integer_or_none( "batchSize", self._options.pop("batchSize", None) ) # If the cursor option is already specified, avoid overriding it. self._options.setdefault("cursor", {}) # If the pipeline performs a write, we ignore the initial batchSize # since the server doesn't return results in this case. if self._batch_size is not None and not self._performs_write: self._options["cursor"]["batchSize"] = self._batch_size self._cursor_class = cursor_class self._explicit_session = explicit_session self._user_fields = user_fields self._result_processor = result_processor self._collation = validate_collation_or_none(options.pop("collation", None)) self._max_await_time_ms = options.pop("maxAwaitTimeMS", None) self._write_preference: Optional[_AggWritePref] = None @property def _aggregation_target(self) -> Union[str, int]: """The argument to pass to the aggregate command.""" raise NotImplementedError @property def _cursor_namespace(self) -> str: """The namespace in which the aggregate command is run.""" raise NotImplementedError def _cursor_collection(self, cursor_doc: Mapping[str, Any]) -> Collection: """The Collection used for the aggregate command cursor.""" raise NotImplementedError @property def _database(self) -> Database: """The database against which the aggregation command is run.""" raise NotImplementedError def get_read_preference( self, session: Optional[ClientSession] ) -> Union[_AggWritePref, _ServerMode]: if self._write_preference: return self._write_preference pref = self._target._read_preference_for(session) if self._performs_write and pref != ReadPreference.PRIMARY: self._write_preference = pref = _AggWritePref(pref) # type: ignore[assignment] return pref def get_cursor( self, session: Optional[ClientSession], server: Server, conn: Connection, read_preference: _ServerMode, ) -> CommandCursor[_DocumentType]: # Serialize command. cmd = {"aggregate": self._aggregation_target, "pipeline": self._pipeline} cmd.update(self._options) # Apply this target's read concern if: # readConcern has not been specified as a kwarg and either # - server version is >= 4.2 or # - server version is >= 3.2 and pipeline doesn't use $out if ("readConcern" not in cmd) and ( not self._performs_write or (conn.max_wire_version >= 8) ): read_concern = self._target.read_concern else: read_concern = None # Apply this target's write concern if: # writeConcern has not been specified as a kwarg and pipeline doesn't # perform a write operation if "writeConcern" not in cmd and self._performs_write: write_concern = self._target._write_concern_for(session) else: write_concern = None # Run command. result = conn.command( self._database.name, cmd, read_preference, self._target.codec_options, parse_write_concern_error=True, read_concern=read_concern, write_concern=write_concern, collation=self._collation, session=session, client=self._database.client, user_fields=self._user_fields, ) if self._result_processor: self._result_processor(result, conn) # Extract cursor from result or mock/fake one if necessary. if "cursor" in result: cursor = result["cursor"] else: # Unacknowledged $out/$merge write. Fake a cursor. cursor = { "id": 0, "firstBatch": result.get("result", []), "ns": self._cursor_namespace, } # Create and return cursor instance. cmd_cursor = self._cursor_class( self._cursor_collection(cursor), cursor, conn.address, batch_size=self._batch_size or 0, max_await_time_ms=self._max_await_time_ms, session=session, explicit_session=self._explicit_session, comment=self._options.get("comment"), ) cmd_cursor._maybe_pin_connection(conn) return cmd_cursor class _CollectionAggregationCommand(_AggregationCommand): _target: Collection @property def _aggregation_target(self) -> str: return self._target.name @property def _cursor_namespace(self) -> str: return self._target.full_name def _cursor_collection(self, cursor: Mapping[str, Any]) -> Collection: """The Collection used for the aggregate command cursor.""" return self._target @property def _database(self) -> Database: return self._target.database class _CollectionRawAggregationCommand(_CollectionAggregationCommand): def __init__(self, *args: Any, **kwargs: Any) -> None: super().__init__(*args, **kwargs) # For raw-batches, we set the initial batchSize for the cursor to 0. if not self._performs_write: self._options["cursor"]["batchSize"] = 0 class _DatabaseAggregationCommand(_AggregationCommand): _target: Database @property def _aggregation_target(self) -> int: return 1 @property def _cursor_namespace(self) -> str: return f"{self._target.name}.$cmd.aggregate" @property def _database(self) -> Database: return self._target def _cursor_collection(self, cursor: Mapping[str, Any]) -> Collection: """The Collection used for the aggregate command cursor.""" # Collection level aggregate may not always return the "ns" field # according to our MockupDB tests. Let's handle that case for db level # aggregate too by defaulting to the .$cmd.aggregate namespace. _, collname = cursor.get("ns", self._cursor_namespace).split(".", 1) return self._database[collname] mongodb-mongo-python-driver-509e9b7/pymongo/auth.py000066400000000000000000000573751462766011000224610ustar00rootroot00000000000000# Copyright 2013-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. """Authentication helpers.""" from __future__ import annotations import functools import hashlib import hmac import os import socket import typing from base64 import standard_b64decode, standard_b64encode from collections import namedtuple from typing import ( TYPE_CHECKING, Any, Callable, Dict, Mapping, MutableMapping, Optional, cast, ) from urllib.parse import quote from bson.binary import Binary from pymongo.auth_aws import _authenticate_aws from pymongo.auth_oidc import ( _authenticate_oidc, _get_authenticator, _OIDCAzureCallback, _OIDCGCPCallback, _OIDCProperties, _OIDCTestCallback, ) from pymongo.errors import ConfigurationError, OperationFailure from pymongo.saslprep import saslprep if TYPE_CHECKING: from pymongo.hello import Hello from pymongo.pool import Connection HAVE_KERBEROS = True _USE_PRINCIPAL = False try: import winkerberos as kerberos # type:ignore[import] if tuple(map(int, kerberos.__version__.split(".")[:2])) >= (0, 5): _USE_PRINCIPAL = True except ImportError: try: import kerberos # type:ignore[import] except ImportError: HAVE_KERBEROS = False MECHANISMS = frozenset( [ "GSSAPI", "MONGODB-CR", "MONGODB-OIDC", "MONGODB-X509", "MONGODB-AWS", "PLAIN", "SCRAM-SHA-1", "SCRAM-SHA-256", "DEFAULT", ] ) """The authentication mechanisms supported by PyMongo.""" class _Cache: __slots__ = ("data",) _hash_val = hash("_Cache") def __init__(self) -> None: self.data = None def __eq__(self, other: object) -> bool: # Two instances must always compare equal. if isinstance(other, _Cache): return True return NotImplemented def __ne__(self, other: object) -> bool: if isinstance(other, _Cache): return False return NotImplemented def __hash__(self) -> int: return self._hash_val MongoCredential = namedtuple( "MongoCredential", ["mechanism", "source", "username", "password", "mechanism_properties", "cache"], ) """A hashable namedtuple of values used for authentication.""" GSSAPIProperties = namedtuple( "GSSAPIProperties", ["service_name", "canonicalize_host_name", "service_realm"] ) """Mechanism properties for GSSAPI authentication.""" _AWSProperties = namedtuple("_AWSProperties", ["aws_session_token"]) """Mechanism properties for MONGODB-AWS authentication.""" def _build_credentials_tuple( mech: str, source: Optional[str], user: str, passwd: str, extra: Mapping[str, Any], database: Optional[str], ) -> MongoCredential: """Build and return a mechanism specific credentials tuple.""" if mech not in ("MONGODB-X509", "MONGODB-AWS", "MONGODB-OIDC") and user is None: raise ConfigurationError(f"{mech} requires a username.") if mech == "GSSAPI": if source is not None and source != "$external": raise ValueError("authentication source must be $external or None for GSSAPI") properties = extra.get("authmechanismproperties", {}) service_name = properties.get("SERVICE_NAME", "mongodb") canonicalize = bool(properties.get("CANONICALIZE_HOST_NAME", False)) service_realm = properties.get("SERVICE_REALM") props = GSSAPIProperties( service_name=service_name, canonicalize_host_name=canonicalize, service_realm=service_realm, ) # Source is always $external. return MongoCredential(mech, "$external", user, passwd, props, None) elif mech == "MONGODB-X509": if passwd is not None: raise ConfigurationError("Passwords are not supported by MONGODB-X509") if source is not None and source != "$external": raise ValueError("authentication source must be $external or None for MONGODB-X509") # Source is always $external, user can be None. return MongoCredential(mech, "$external", user, None, None, None) elif mech == "MONGODB-AWS": if user is not None and passwd is None: raise ConfigurationError("username without a password is not supported by MONGODB-AWS") if source is not None and source != "$external": raise ConfigurationError( "authentication source must be $external or None for MONGODB-AWS" ) properties = extra.get("authmechanismproperties", {}) aws_session_token = properties.get("AWS_SESSION_TOKEN") aws_props = _AWSProperties(aws_session_token=aws_session_token) # user can be None for temporary link-local EC2 credentials. return MongoCredential(mech, "$external", user, passwd, aws_props, None) elif mech == "MONGODB-OIDC": properties = extra.get("authmechanismproperties", {}) callback = properties.get("OIDC_CALLBACK") human_callback = properties.get("OIDC_HUMAN_CALLBACK") environ = properties.get("ENVIRONMENT") token_resource = properties.get("TOKEN_RESOURCE", "") default_allowed = [ "*.mongodb.net", "*.mongodb-dev.net", "*.mongodb-qa.net", "*.mongodbgov.net", "localhost", "127.0.0.1", "::1", ] allowed_hosts = properties.get("ALLOWED_HOSTS", default_allowed) msg = ( "authentication with MONGODB-OIDC requires providing either a callback or a environment" ) if passwd is not None: msg = "password is not supported by MONGODB-OIDC" raise ConfigurationError(msg) if callback or human_callback: if environ is not None: raise ConfigurationError(msg) if callback and human_callback: msg = "cannot set both OIDC_CALLBACK and OIDC_HUMAN_CALLBACK" raise ConfigurationError(msg) elif environ is not None: if environ == "test": if user is not None: msg = "test environment for MONGODB-OIDC does not support username" raise ConfigurationError(msg) callback = _OIDCTestCallback() elif environ == "azure": passwd = None if not token_resource: raise ConfigurationError( "Azure environment for MONGODB-OIDC requires a TOKEN_RESOURCE auth mechanism property" ) callback = _OIDCAzureCallback(token_resource) elif environ == "gcp": passwd = None if not token_resource: raise ConfigurationError( "GCP provider for MONGODB-OIDC requires a TOKEN_RESOURCE auth mechanism property" ) callback = _OIDCGCPCallback(token_resource) else: raise ConfigurationError(f"unrecognized ENVIRONMENT for MONGODB-OIDC: {environ}") else: raise ConfigurationError(msg) oidc_props = _OIDCProperties( callback=callback, human_callback=human_callback, environment=environ, allowed_hosts=allowed_hosts, token_resource=token_resource, username=user, ) return MongoCredential(mech, "$external", user, passwd, oidc_props, _Cache()) elif mech == "PLAIN": source_database = source or database or "$external" return MongoCredential(mech, source_database, user, passwd, None, None) else: source_database = source or database or "admin" if passwd is None: raise ConfigurationError("A password is required.") return MongoCredential(mech, source_database, user, passwd, None, _Cache()) def _xor(fir: bytes, sec: bytes) -> bytes: """XOR two byte strings together.""" return b"".join([bytes([x ^ y]) for x, y in zip(fir, sec)]) def _parse_scram_response(response: bytes) -> Dict[bytes, bytes]: """Split a scram response into key, value pairs.""" return dict( typing.cast(typing.Tuple[bytes, bytes], item.split(b"=", 1)) for item in response.split(b",") ) def _authenticate_scram_start( credentials: MongoCredential, mechanism: str ) -> tuple[bytes, bytes, MutableMapping[str, Any]]: username = credentials.username user = username.encode("utf-8").replace(b"=", b"=3D").replace(b",", b"=2C") nonce = standard_b64encode(os.urandom(32)) first_bare = b"n=" + user + b",r=" + nonce cmd = { "saslStart": 1, "mechanism": mechanism, "payload": Binary(b"n,," + first_bare), "autoAuthorize": 1, "options": {"skipEmptyExchange": True}, } return nonce, first_bare, cmd def _authenticate_scram(credentials: MongoCredential, conn: Connection, mechanism: str) -> None: """Authenticate using SCRAM.""" username = credentials.username if mechanism == "SCRAM-SHA-256": digest = "sha256" digestmod = hashlib.sha256 data = saslprep(credentials.password).encode("utf-8") else: digest = "sha1" digestmod = hashlib.sha1 data = _password_digest(username, credentials.password).encode("utf-8") source = credentials.source cache = credentials.cache # Make local _hmac = hmac.HMAC ctx = conn.auth_ctx if ctx and ctx.speculate_succeeded(): assert isinstance(ctx, _ScramContext) assert ctx.scram_data is not None nonce, first_bare = ctx.scram_data res = ctx.speculative_authenticate else: nonce, first_bare, cmd = _authenticate_scram_start(credentials, mechanism) res = conn.command(source, cmd) assert res is not None server_first = res["payload"] parsed = _parse_scram_response(server_first) iterations = int(parsed[b"i"]) if iterations < 4096: raise OperationFailure("Server returned an invalid iteration count.") salt = parsed[b"s"] rnonce = parsed[b"r"] if not rnonce.startswith(nonce): raise OperationFailure("Server returned an invalid nonce.") without_proof = b"c=biws,r=" + rnonce if cache.data: client_key, server_key, csalt, citerations = cache.data else: client_key, server_key, csalt, citerations = None, None, None, None # Salt and / or iterations could change for a number of different # reasons. Either changing invalidates the cache. if not client_key or salt != csalt or iterations != citerations: salted_pass = hashlib.pbkdf2_hmac(digest, data, standard_b64decode(salt), iterations) client_key = _hmac(salted_pass, b"Client Key", digestmod).digest() server_key = _hmac(salted_pass, b"Server Key", digestmod).digest() cache.data = (client_key, server_key, salt, iterations) stored_key = digestmod(client_key).digest() auth_msg = b",".join((first_bare, server_first, without_proof)) client_sig = _hmac(stored_key, auth_msg, digestmod).digest() client_proof = b"p=" + standard_b64encode(_xor(client_key, client_sig)) client_final = b",".join((without_proof, client_proof)) server_sig = standard_b64encode(_hmac(server_key, auth_msg, digestmod).digest()) cmd = { "saslContinue": 1, "conversationId": res["conversationId"], "payload": Binary(client_final), } res = conn.command(source, cmd) parsed = _parse_scram_response(res["payload"]) if not hmac.compare_digest(parsed[b"v"], server_sig): raise OperationFailure("Server returned an invalid signature.") # A third empty challenge may be required if the server does not support # skipEmptyExchange: SERVER-44857. if not res["done"]: cmd = { "saslContinue": 1, "conversationId": res["conversationId"], "payload": Binary(b""), } res = conn.command(source, cmd) if not res["done"]: raise OperationFailure("SASL conversation failed to complete.") def _password_digest(username: str, password: str) -> str: """Get a password digest to use for authentication.""" if not isinstance(password, str): raise TypeError("password must be an instance of str") if len(password) == 0: raise ValueError("password can't be empty") if not isinstance(username, str): raise TypeError("username must be an instance of str") md5hash = hashlib.md5() # noqa: S324 data = f"{username}:mongo:{password}" md5hash.update(data.encode("utf-8")) return md5hash.hexdigest() def _auth_key(nonce: str, username: str, password: str) -> str: """Get an auth key to use for authentication.""" digest = _password_digest(username, password) md5hash = hashlib.md5() # noqa: S324 data = f"{nonce}{username}{digest}" md5hash.update(data.encode("utf-8")) return md5hash.hexdigest() def _canonicalize_hostname(hostname: str) -> str: """Canonicalize hostname following MIT-krb5 behavior.""" # https://github.com/krb5/krb5/blob/d406afa363554097ac48646a29249c04f498c88e/src/util/k5test.py#L505-L520 af, socktype, proto, canonname, sockaddr = socket.getaddrinfo( hostname, None, 0, 0, socket.IPPROTO_TCP, socket.AI_CANONNAME )[0] try: name = socket.getnameinfo(sockaddr, socket.NI_NAMEREQD) except socket.gaierror: return canonname.lower() return name[0].lower() def _authenticate_gssapi(credentials: MongoCredential, conn: Connection) -> None: """Authenticate using GSSAPI.""" if not HAVE_KERBEROS: raise ConfigurationError( 'The "kerberos" module must be installed to use GSSAPI authentication.' ) try: username = credentials.username password = credentials.password props = credentials.mechanism_properties # Starting here and continuing through the while loop below - establish # the security context. See RFC 4752, Section 3.1, first paragraph. host = conn.address[0] if props.canonicalize_host_name: host = _canonicalize_hostname(host) service = props.service_name + "@" + host if props.service_realm is not None: service = service + "@" + props.service_realm if password is not None: if _USE_PRINCIPAL: # Note that, though we use unquote_plus for unquoting URI # options, we use quote here. Microsoft's UrlUnescape (used # by WinKerberos) doesn't support +. principal = ":".join((quote(username), quote(password))) result, ctx = kerberos.authGSSClientInit( service, principal, gssflags=kerberos.GSS_C_MUTUAL_FLAG ) else: if "@" in username: user, domain = username.split("@", 1) else: user, domain = username, None result, ctx = kerberos.authGSSClientInit( service, gssflags=kerberos.GSS_C_MUTUAL_FLAG, user=user, domain=domain, password=password, ) else: result, ctx = kerberos.authGSSClientInit(service, gssflags=kerberos.GSS_C_MUTUAL_FLAG) if result != kerberos.AUTH_GSS_COMPLETE: raise OperationFailure("Kerberos context failed to initialize.") try: # pykerberos uses a weird mix of exceptions and return values # to indicate errors. # 0 == continue, 1 == complete, -1 == error # Only authGSSClientStep can return 0. if kerberos.authGSSClientStep(ctx, "") != 0: raise OperationFailure("Unknown kerberos failure in step function.") # Start a SASL conversation with mongod/s # Note: pykerberos deals with base64 encoded byte strings. # Since mongo accepts base64 strings as the payload we don't # have to use bson.binary.Binary. payload = kerberos.authGSSClientResponse(ctx) cmd = { "saslStart": 1, "mechanism": "GSSAPI", "payload": payload, "autoAuthorize": 1, } response = conn.command("$external", cmd) # Limit how many times we loop to catch protocol / library issues for _ in range(10): result = kerberos.authGSSClientStep(ctx, str(response["payload"])) if result == -1: raise OperationFailure("Unknown kerberos failure in step function.") payload = kerberos.authGSSClientResponse(ctx) or "" cmd = { "saslContinue": 1, "conversationId": response["conversationId"], "payload": payload, } response = conn.command("$external", cmd) if result == kerberos.AUTH_GSS_COMPLETE: break else: raise OperationFailure("Kerberos authentication failed to complete.") # Once the security context is established actually authenticate. # See RFC 4752, Section 3.1, last two paragraphs. if kerberos.authGSSClientUnwrap(ctx, str(response["payload"])) != 1: raise OperationFailure("Unknown kerberos failure during GSS_Unwrap step.") if kerberos.authGSSClientWrap(ctx, kerberos.authGSSClientResponse(ctx), username) != 1: raise OperationFailure("Unknown kerberos failure during GSS_Wrap step.") payload = kerberos.authGSSClientResponse(ctx) cmd = { "saslContinue": 1, "conversationId": response["conversationId"], "payload": payload, } conn.command("$external", cmd) finally: kerberos.authGSSClientClean(ctx) except kerberos.KrbError as exc: raise OperationFailure(str(exc)) from None def _authenticate_plain(credentials: MongoCredential, conn: Connection) -> None: """Authenticate using SASL PLAIN (RFC 4616)""" source = credentials.source username = credentials.username password = credentials.password payload = (f"\x00{username}\x00{password}").encode() cmd = { "saslStart": 1, "mechanism": "PLAIN", "payload": Binary(payload), "autoAuthorize": 1, } conn.command(source, cmd) def _authenticate_x509(credentials: MongoCredential, conn: Connection) -> None: """Authenticate using MONGODB-X509.""" ctx = conn.auth_ctx if ctx and ctx.speculate_succeeded(): # MONGODB-X509 is done after the speculative auth step. return cmd = _X509Context(credentials, conn.address).speculate_command() conn.command("$external", cmd) def _authenticate_mongo_cr(credentials: MongoCredential, conn: Connection) -> None: """Authenticate using MONGODB-CR.""" source = credentials.source username = credentials.username password = credentials.password # Get a nonce response = conn.command(source, {"getnonce": 1}) nonce = response["nonce"] key = _auth_key(nonce, username, password) # Actually authenticate query = {"authenticate": 1, "user": username, "nonce": nonce, "key": key} conn.command(source, query) def _authenticate_default(credentials: MongoCredential, conn: Connection) -> None: if conn.max_wire_version >= 7: if conn.negotiated_mechs: mechs = conn.negotiated_mechs else: source = credentials.source cmd = conn.hello_cmd() cmd["saslSupportedMechs"] = source + "." + credentials.username mechs = conn.command(source, cmd, publish_events=False).get("saslSupportedMechs", []) if "SCRAM-SHA-256" in mechs: return _authenticate_scram(credentials, conn, "SCRAM-SHA-256") else: return _authenticate_scram(credentials, conn, "SCRAM-SHA-1") else: return _authenticate_scram(credentials, conn, "SCRAM-SHA-1") _AUTH_MAP: Mapping[str, Callable[..., None]] = { "GSSAPI": _authenticate_gssapi, "MONGODB-CR": _authenticate_mongo_cr, "MONGODB-X509": _authenticate_x509, "MONGODB-AWS": _authenticate_aws, "MONGODB-OIDC": _authenticate_oidc, # type:ignore[dict-item] "PLAIN": _authenticate_plain, "SCRAM-SHA-1": functools.partial(_authenticate_scram, mechanism="SCRAM-SHA-1"), "SCRAM-SHA-256": functools.partial(_authenticate_scram, mechanism="SCRAM-SHA-256"), "DEFAULT": _authenticate_default, } class _AuthContext: def __init__(self, credentials: MongoCredential, address: tuple[str, int]) -> None: self.credentials = credentials self.speculative_authenticate: Optional[Mapping[str, Any]] = None self.address = address @staticmethod def from_credentials( creds: MongoCredential, address: tuple[str, int] ) -> Optional[_AuthContext]: spec_cls = _SPECULATIVE_AUTH_MAP.get(creds.mechanism) if spec_cls: return cast(_AuthContext, spec_cls(creds, address)) return None def speculate_command(self) -> Optional[MutableMapping[str, Any]]: raise NotImplementedError def parse_response(self, hello: Hello[Mapping[str, Any]]) -> None: self.speculative_authenticate = hello.speculative_authenticate def speculate_succeeded(self) -> bool: return bool(self.speculative_authenticate) class _ScramContext(_AuthContext): def __init__( self, credentials: MongoCredential, address: tuple[str, int], mechanism: str ) -> None: super().__init__(credentials, address) self.scram_data: Optional[tuple[bytes, bytes]] = None self.mechanism = mechanism def speculate_command(self) -> Optional[MutableMapping[str, Any]]: nonce, first_bare, cmd = _authenticate_scram_start(self.credentials, self.mechanism) # The 'db' field is included only on the speculative command. cmd["db"] = self.credentials.source # Save for later use. self.scram_data = (nonce, first_bare) return cmd class _X509Context(_AuthContext): def speculate_command(self) -> MutableMapping[str, Any]: cmd = {"authenticate": 1, "mechanism": "MONGODB-X509"} if self.credentials.username is not None: cmd["user"] = self.credentials.username return cmd class _OIDCContext(_AuthContext): def speculate_command(self) -> Optional[MutableMapping[str, Any]]: authenticator = _get_authenticator(self.credentials, self.address) cmd = authenticator.get_spec_auth_cmd() if cmd is None: return None cmd["db"] = self.credentials.source return cmd _SPECULATIVE_AUTH_MAP: Mapping[str, Any] = { "MONGODB-X509": _X509Context, "SCRAM-SHA-1": functools.partial(_ScramContext, mechanism="SCRAM-SHA-1"), "SCRAM-SHA-256": functools.partial(_ScramContext, mechanism="SCRAM-SHA-256"), "MONGODB-OIDC": _OIDCContext, "DEFAULT": functools.partial(_ScramContext, mechanism="SCRAM-SHA-256"), } def authenticate( credentials: MongoCredential, conn: Connection, reauthenticate: bool = False ) -> None: """Authenticate connection.""" mechanism = credentials.mechanism auth_func = _AUTH_MAP[mechanism] if mechanism == "MONGODB-OIDC": _authenticate_oidc(credentials, conn, reauthenticate) else: auth_func(credentials, conn) mongodb-mongo-python-driver-509e9b7/pymongo/auth_aws.py000066400000000000000000000071641462766011000233220ustar00rootroot00000000000000# Copyright 2020-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. """MONGODB-AWS Authentication helpers.""" from __future__ import annotations from typing import TYPE_CHECKING, Any, Mapping, Type import bson from bson.binary import Binary from pymongo.errors import ConfigurationError, OperationFailure if TYPE_CHECKING: from bson.typings import _ReadableBuffer from pymongo.auth import MongoCredential from pymongo.pool import Connection def _authenticate_aws(credentials: MongoCredential, conn: Connection) -> None: """Authenticate using MONGODB-AWS.""" try: import pymongo_auth_aws # type:ignore[import] except ImportError as e: raise ConfigurationError( "MONGODB-AWS authentication requires pymongo-auth-aws: " "install with: python -m pip install 'pymongo[aws]'" ) from e # Delayed import. from pymongo_auth_aws.auth import ( # type:ignore[import] set_cached_credentials, set_use_cached_credentials, ) set_use_cached_credentials(True) if conn.max_wire_version < 9: raise ConfigurationError("MONGODB-AWS authentication requires MongoDB version 4.4 or later") class AwsSaslContext(pymongo_auth_aws.AwsSaslContext): # type: ignore # Dependency injection: def binary_type(self) -> Type[Binary]: """Return the bson.binary.Binary type.""" return Binary def bson_encode(self, doc: Mapping[str, Any]) -> bytes: """Encode a dictionary to BSON.""" return bson.encode(doc) def bson_decode(self, data: _ReadableBuffer) -> Mapping[str, Any]: """Decode BSON to a dictionary.""" return bson.decode(data) try: ctx = AwsSaslContext( pymongo_auth_aws.AwsCredential( credentials.username, credentials.password, credentials.mechanism_properties.aws_session_token, ) ) client_payload = ctx.step(None) client_first = {"saslStart": 1, "mechanism": "MONGODB-AWS", "payload": client_payload} server_first = conn.command("$external", client_first) res = server_first # Limit how many times we loop to catch protocol / library issues for _ in range(10): client_payload = ctx.step(res["payload"]) cmd = { "saslContinue": 1, "conversationId": server_first["conversationId"], "payload": client_payload, } res = conn.command("$external", cmd) if res["done"]: # SASL complete. break except pymongo_auth_aws.PyMongoAuthAwsError as exc: # Clear the cached credentials if we hit a failure in auth. set_cached_credentials(None) # Convert to OperationFailure and include pymongo-auth-aws version. raise OperationFailure( f"{exc} (pymongo-auth-aws version {pymongo_auth_aws.__version__})" ) from None except Exception: # Clear the cached credentials if we hit a failure in auth. set_cached_credentials(None) raise mongodb-mongo-python-driver-509e9b7/pymongo/auth_oidc.py000066400000000000000000000333561462766011000234500ustar00rootroot00000000000000# Copyright 2023-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. """MONGODB-OIDC Authentication helpers.""" from __future__ import annotations import abc import os import threading import time from dataclasses import dataclass, field from typing import TYPE_CHECKING, Any, Mapping, MutableMapping, Optional, Union from urllib.parse import quote import bson from bson.binary import Binary from pymongo._azure_helpers import _get_azure_response from pymongo._csot import remaining from pymongo._gcp_helpers import _get_gcp_response from pymongo.errors import ConfigurationError, OperationFailure from pymongo.helpers import _AUTHENTICATION_FAILURE_CODE if TYPE_CHECKING: from pymongo.auth import MongoCredential from pymongo.pool import Connection @dataclass class OIDCIdPInfo: issuer: str clientId: Optional[str] = field(default=None) requestScopes: Optional[list[str]] = field(default=None) @dataclass class OIDCCallbackContext: timeout_seconds: float username: str version: int refresh_token: Optional[str] = field(default=None) idp_info: Optional[OIDCIdPInfo] = field(default=None) @dataclass class OIDCCallbackResult: access_token: str expires_in_seconds: Optional[float] = field(default=None) refresh_token: Optional[str] = field(default=None) class OIDCCallback(abc.ABC): """A base class for defining OIDC callbacks.""" @abc.abstractmethod def fetch(self, context: OIDCCallbackContext) -> OIDCCallbackResult: """Convert the given BSON value into our own type.""" @dataclass class _OIDCProperties: callback: Optional[OIDCCallback] = field(default=None) human_callback: Optional[OIDCCallback] = field(default=None) environment: Optional[str] = field(default=None) allowed_hosts: list[str] = field(default_factory=list) token_resource: Optional[str] = field(default=None) username: str = "" """Mechanism properties for MONGODB-OIDC authentication.""" TOKEN_BUFFER_MINUTES = 5 HUMAN_CALLBACK_TIMEOUT_SECONDS = 5 * 60 CALLBACK_VERSION = 1 MACHINE_CALLBACK_TIMEOUT_SECONDS = 60 TIME_BETWEEN_CALLS_SECONDS = 0.1 def _get_authenticator( credentials: MongoCredential, address: tuple[str, int] ) -> _OIDCAuthenticator: if credentials.cache.data: return credentials.cache.data # Extract values. principal_name = credentials.username properties = credentials.mechanism_properties # Validate that the address is allowed. if not properties.environment: found = False allowed_hosts = properties.allowed_hosts for patt in allowed_hosts: if patt == address[0]: found = True elif patt.startswith("*.") and address[0].endswith(patt[1:]): found = True if not found: raise ConfigurationError( f"Refusing to connect to {address[0]}, which is not in authOIDCAllowedHosts: {allowed_hosts}" ) # Get or create the cache data. credentials.cache.data = _OIDCAuthenticator(username=principal_name, properties=properties) return credentials.cache.data class _OIDCTestCallback(OIDCCallback): def fetch(self, context: OIDCCallbackContext) -> OIDCCallbackResult: token_file = os.environ.get("OIDC_TOKEN_FILE") if not token_file: raise RuntimeError( 'MONGODB-OIDC with an "test" provider requires "OIDC_TOKEN_FILE" to be set' ) with open(token_file) as fid: return OIDCCallbackResult(access_token=fid.read().strip()) class _OIDCAzureCallback(OIDCCallback): def __init__(self, token_resource: str) -> None: self.token_resource = quote(token_resource) def fetch(self, context: OIDCCallbackContext) -> OIDCCallbackResult: resp = _get_azure_response(self.token_resource, context.username, context.timeout_seconds) return OIDCCallbackResult( access_token=resp["access_token"], expires_in_seconds=resp["expires_in"] ) class _OIDCGCPCallback(OIDCCallback): def __init__(self, token_resource: str) -> None: self.token_resource = quote(token_resource) def fetch(self, context: OIDCCallbackContext) -> OIDCCallbackResult: resp = _get_gcp_response(self.token_resource, context.timeout_seconds) return OIDCCallbackResult(access_token=resp["access_token"]) @dataclass class _OIDCAuthenticator: username: str properties: _OIDCProperties refresh_token: Optional[str] = field(default=None) access_token: Optional[str] = field(default=None) idp_info: Optional[OIDCIdPInfo] = field(default=None) token_gen_id: int = field(default=0) lock: threading.Lock = field(default_factory=threading.Lock) last_call_time: float = field(default=0) def reauthenticate(self, conn: Connection) -> Optional[Mapping[str, Any]]: """Handle a reauthenticate from the server.""" # Invalidate the token for the connection. self._invalidate(conn) # Call the appropriate auth logic for the callback type. if self.properties.callback: return self._authenticate_machine(conn) return self._authenticate_human(conn) def authenticate(self, conn: Connection) -> Optional[Mapping[str, Any]]: """Handle an initial authenticate request.""" # First handle speculative auth. # If it succeeded, we are done. ctx = conn.auth_ctx if ctx and ctx.speculate_succeeded(): resp = ctx.speculative_authenticate if resp and resp["done"]: conn.oidc_token_gen_id = self.token_gen_id return resp # If spec auth failed, call the appropriate auth logic for the callback type. # We cannot assume that the token is invalid, because a proxy may have been # involved that stripped the speculative auth information. if self.properties.callback: return self._authenticate_machine(conn) return self._authenticate_human(conn) def get_spec_auth_cmd(self) -> Optional[MutableMapping[str, Any]]: """Get the appropriate speculative auth command.""" if not self.access_token: return None return self._get_start_command({"jwt": self.access_token}) def _authenticate_machine(self, conn: Connection) -> Mapping[str, Any]: # If there is a cached access token, try to authenticate with it. If # authentication fails with error code 18, invalidate the access token, # fetch a new access token, and try to authenticate again. If authentication # fails for any other reason, raise the error to the user. if self.access_token: try: return self._sasl_start_jwt(conn) except OperationFailure as e: if self._is_auth_error(e): return self._authenticate_machine(conn) raise return self._sasl_start_jwt(conn) def _authenticate_human(self, conn: Connection) -> Optional[Mapping[str, Any]]: # If we have a cached access token, try a JwtStepRequest. # authentication fails with error code 18, invalidate the access token, # and try to authenticate again. If authentication fails for any other # reason, raise the error to the user. if self.access_token: try: return self._sasl_start_jwt(conn) except OperationFailure as e: if self._is_auth_error(e): return self._authenticate_human(conn) raise # If we have a cached refresh token, try a JwtStepRequest with that. # If authentication fails with error code 18, invalidate the access and # refresh tokens, and try to authenticate again. If authentication fails for # any other reason, raise the error to the user. if self.refresh_token: try: return self._sasl_start_jwt(conn) except OperationFailure as e: if self._is_auth_error(e): self.refresh_token = None return self._authenticate_human(conn) raise # Start a new Two-Step SASL conversation. # Run a PrincipalStepRequest to get the IdpInfo. cmd = self._get_start_command(None) start_resp = self._run_command(conn, cmd) # Attempt to authenticate with a JwtStepRequest. return self._sasl_continue_jwt(conn, start_resp) def _get_access_token(self) -> Optional[str]: properties = self.properties cb: Union[None, OIDCCallback] resp: OIDCCallbackResult is_human = properties.human_callback is not None if is_human and self.idp_info is None: return None if properties.callback: cb = properties.callback if properties.human_callback: cb = properties.human_callback prev_token = self.access_token if prev_token: return prev_token if cb is None and not prev_token: return None if not prev_token and cb is not None: with self.lock: # See if the token was changed while we were waiting for the # lock. new_token = self.access_token if new_token != prev_token: return new_token # Ensure that we are waiting a min time between callback invocations. delta = time.time() - self.last_call_time if delta < TIME_BETWEEN_CALLS_SECONDS: time.sleep(TIME_BETWEEN_CALLS_SECONDS - delta) self.last_call_time = time.time() if is_human: timeout = HUMAN_CALLBACK_TIMEOUT_SECONDS assert self.idp_info is not None else: timeout = int(remaining() or MACHINE_CALLBACK_TIMEOUT_SECONDS) context = OIDCCallbackContext( timeout_seconds=timeout, version=CALLBACK_VERSION, refresh_token=self.refresh_token, idp_info=self.idp_info, username=self.properties.username, ) resp = cb.fetch(context) if not isinstance(resp, OIDCCallbackResult): raise ValueError("Callback result must be of type OIDCCallbackResult") self.refresh_token = resp.refresh_token self.access_token = resp.access_token self.token_gen_id += 1 return self.access_token def _run_command(self, conn: Connection, cmd: MutableMapping[str, Any]) -> Mapping[str, Any]: try: return conn.command("$external", cmd, no_reauth=True) # type: ignore[call-arg] except OperationFailure as e: if self._is_auth_error(e): self._invalidate(conn) raise def _is_auth_error(self, err: Exception) -> bool: if not isinstance(err, OperationFailure): return False return err.code == _AUTHENTICATION_FAILURE_CODE def _invalidate(self, conn: Connection) -> None: # Ignore the invalidation if a token gen id is given and is less than our # current token gen id. token_gen_id = conn.oidc_token_gen_id or 0 if token_gen_id is not None and token_gen_id < self.token_gen_id: return self.access_token = None def _sasl_continue_jwt( self, conn: Connection, start_resp: Mapping[str, Any] ) -> Mapping[str, Any]: self.access_token = None self.refresh_token = None start_payload: dict = bson.decode(start_resp["payload"]) if "issuer" in start_payload: self.idp_info = OIDCIdPInfo(**start_payload) access_token = self._get_access_token() conn.oidc_token_gen_id = self.token_gen_id cmd = self._get_continue_command({"jwt": access_token}, start_resp) return self._run_command(conn, cmd) def _sasl_start_jwt(self, conn: Connection) -> Mapping[str, Any]: access_token = self._get_access_token() conn.oidc_token_gen_id = self.token_gen_id cmd = self._get_start_command({"jwt": access_token}) return self._run_command(conn, cmd) def _get_start_command(self, payload: Optional[Mapping[str, Any]]) -> MutableMapping[str, Any]: if payload is None: principal_name = self.username if principal_name: payload = {"n": principal_name} else: payload = {} bin_payload = Binary(bson.encode(payload)) return {"saslStart": 1, "mechanism": "MONGODB-OIDC", "payload": bin_payload} def _get_continue_command( self, payload: Mapping[str, Any], start_resp: Mapping[str, Any] ) -> MutableMapping[str, Any]: bin_payload = Binary(bson.encode(payload)) return { "saslContinue": 1, "payload": bin_payload, "conversationId": start_resp["conversationId"], } def _authenticate_oidc( credentials: MongoCredential, conn: Connection, reauthenticate: bool ) -> Optional[Mapping[str, Any]]: """Authenticate using MONGODB-OIDC.""" authenticator = _get_authenticator(credentials, conn.address) if reauthenticate: return authenticator.reauthenticate(conn) else: return authenticator.authenticate(conn) mongodb-mongo-python-driver-509e9b7/pymongo/bulk.py000066400000000000000000000513751462766011000224470ustar00rootroot00000000000000# Copyright 2014-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. """The bulk write operations interface. .. versionadded:: 2.7 """ from __future__ import annotations import copy from collections.abc import MutableMapping from itertools import islice from typing import ( TYPE_CHECKING, Any, Iterator, Mapping, NoReturn, Optional, Type, Union, ) from bson.objectid import ObjectId from bson.raw_bson import RawBSONDocument from pymongo import _csot, common from pymongo.client_session import ClientSession, _validate_session_write_concern from pymongo.common import ( validate_is_document_type, validate_ok_for_replace, validate_ok_for_update, ) from pymongo.errors import ( BulkWriteError, ConfigurationError, InvalidOperation, OperationFailure, ) from pymongo.helpers import _RETRYABLE_ERROR_CODES, _get_wce_doc from pymongo.message import ( _DELETE, _INSERT, _UPDATE, _BulkWriteContext, _EncryptedBulkWriteContext, _randint, ) from pymongo.read_preferences import ReadPreference from pymongo.write_concern import WriteConcern if TYPE_CHECKING: from pymongo.collection import Collection from pymongo.pool import Connection from pymongo.typings import _DocumentOut, _DocumentType, _Pipeline _DELETE_ALL: int = 0 _DELETE_ONE: int = 1 # For backwards compatibility. See MongoDB src/mongo/base/error_codes.err _BAD_VALUE: int = 2 _UNKNOWN_ERROR: int = 8 _WRITE_CONCERN_ERROR: int = 64 _COMMANDS: tuple[str, str, str] = ("insert", "update", "delete") class _Run: """Represents a batch of write operations.""" def __init__(self, op_type: int) -> None: """Initialize a new Run object.""" self.op_type: int = op_type self.index_map: list[int] = [] self.ops: list[Any] = [] self.idx_offset: int = 0 def index(self, idx: int) -> int: """Get the original index of an operation in this run. :param idx: The Run index that maps to the original index. """ return self.index_map[idx] def add(self, original_index: int, operation: Any) -> None: """Add an operation to this Run instance. :param original_index: The original index of this operation within a larger bulk operation. :param operation: The operation document. """ self.index_map.append(original_index) self.ops.append(operation) def _merge_command( run: _Run, full_result: MutableMapping[str, Any], offset: int, result: Mapping[str, Any], ) -> None: """Merge a write command result into the full bulk result.""" affected = result.get("n", 0) if run.op_type == _INSERT: full_result["nInserted"] += affected elif run.op_type == _DELETE: full_result["nRemoved"] += affected elif run.op_type == _UPDATE: upserted = result.get("upserted") if upserted: n_upserted = len(upserted) for doc in upserted: doc["index"] = run.index(doc["index"] + offset) full_result["upserted"].extend(upserted) full_result["nUpserted"] += n_upserted full_result["nMatched"] += affected - n_upserted else: full_result["nMatched"] += affected full_result["nModified"] += result["nModified"] write_errors = result.get("writeErrors") if write_errors: for doc in write_errors: # Leave the server response intact for APM. replacement = doc.copy() idx = doc["index"] + offset replacement["index"] = run.index(idx) # Add the failed operation to the error document. replacement["op"] = run.ops[idx] full_result["writeErrors"].append(replacement) wce = _get_wce_doc(result) if wce: full_result["writeConcernErrors"].append(wce) def _raise_bulk_write_error(full_result: _DocumentOut) -> NoReturn: """Raise a BulkWriteError from the full bulk api result.""" # retryWrites on MMAPv1 should raise an actionable error. if full_result["writeErrors"]: full_result["writeErrors"].sort(key=lambda error: error["index"]) err = full_result["writeErrors"][0] code = err["code"] msg = err["errmsg"] if code == 20 and msg.startswith("Transaction numbers"): errmsg = ( "This MongoDB deployment does not support " "retryable writes. Please add retryWrites=false " "to your connection string." ) raise OperationFailure(errmsg, code, full_result) raise BulkWriteError(full_result) class _Bulk: """The private guts of the bulk write API.""" def __init__( self, collection: Collection[_DocumentType], ordered: bool, bypass_document_validation: bool, comment: Optional[str] = None, let: Optional[Any] = None, ) -> None: """Initialize a _Bulk instance.""" self.collection = collection.with_options( codec_options=collection.codec_options._replace( unicode_decode_error_handler="replace", document_class=dict ) ) self.let = let if self.let is not None: common.validate_is_document_type("let", self.let) self.comment: Optional[str] = comment self.ordered = ordered self.ops: list[tuple[int, Mapping[str, Any]]] = [] self.executed = False self.bypass_doc_val = bypass_document_validation self.uses_collation = False self.uses_array_filters = False self.uses_hint_update = False self.uses_hint_delete = False self.is_retryable = True self.retrying = False self.started_retryable_write = False # Extra state so that we know where to pick up on a retry attempt. self.current_run = None self.next_run = None @property def bulk_ctx_class(self) -> Type[_BulkWriteContext]: encrypter = self.collection.database.client._encrypter if encrypter and not encrypter._bypass_auto_encryption: return _EncryptedBulkWriteContext else: return _BulkWriteContext def add_insert(self, document: _DocumentOut) -> None: """Add an insert document to the list of ops.""" validate_is_document_type("document", document) # Generate ObjectId client side. if not (isinstance(document, RawBSONDocument) or "_id" in document): document["_id"] = ObjectId() self.ops.append((_INSERT, document)) def add_update( self, selector: Mapping[str, Any], update: Union[Mapping[str, Any], _Pipeline], multi: bool = False, upsert: bool = False, collation: Optional[Mapping[str, Any]] = None, array_filters: Optional[list[Mapping[str, Any]]] = None, hint: Union[str, dict[str, Any], None] = None, ) -> None: """Create an update document and add it to the list of ops.""" validate_ok_for_update(update) cmd: dict[str, Any] = dict( # noqa: C406 [("q", selector), ("u", update), ("multi", multi), ("upsert", upsert)] ) if collation is not None: self.uses_collation = True cmd["collation"] = collation if array_filters is not None: self.uses_array_filters = True cmd["arrayFilters"] = array_filters if hint is not None: self.uses_hint_update = True cmd["hint"] = hint if multi: # A bulk_write containing an update_many is not retryable. self.is_retryable = False self.ops.append((_UPDATE, cmd)) def add_replace( self, selector: Mapping[str, Any], replacement: Mapping[str, Any], upsert: bool = False, collation: Optional[Mapping[str, Any]] = None, hint: Union[str, dict[str, Any], None] = None, ) -> None: """Create a replace document and add it to the list of ops.""" validate_ok_for_replace(replacement) cmd = {"q": selector, "u": replacement, "multi": False, "upsert": upsert} if collation is not None: self.uses_collation = True cmd["collation"] = collation if hint is not None: self.uses_hint_update = True cmd["hint"] = hint self.ops.append((_UPDATE, cmd)) def add_delete( self, selector: Mapping[str, Any], limit: int, collation: Optional[Mapping[str, Any]] = None, hint: Union[str, dict[str, Any], None] = None, ) -> None: """Create a delete document and add it to the list of ops.""" cmd = {"q": selector, "limit": limit} if collation is not None: self.uses_collation = True cmd["collation"] = collation if hint is not None: self.uses_hint_delete = True cmd["hint"] = hint if limit == _DELETE_ALL: # A bulk_write containing a delete_many is not retryable. self.is_retryable = False self.ops.append((_DELETE, cmd)) def gen_ordered(self) -> Iterator[Optional[_Run]]: """Generate batches of operations, batched by type of operation, in the order **provided**. """ run = None for idx, (op_type, operation) in enumerate(self.ops): if run is None: run = _Run(op_type) elif run.op_type != op_type: yield run run = _Run(op_type) run.add(idx, operation) yield run def gen_unordered(self) -> Iterator[_Run]: """Generate batches of operations, batched by type of operation, in arbitrary order. """ operations = [_Run(_INSERT), _Run(_UPDATE), _Run(_DELETE)] for idx, (op_type, operation) in enumerate(self.ops): operations[op_type].add(idx, operation) for run in operations: if run.ops: yield run def _execute_command( self, generator: Iterator[Any], write_concern: WriteConcern, session: Optional[ClientSession], conn: Connection, op_id: int, retryable: bool, full_result: MutableMapping[str, Any], final_write_concern: Optional[WriteConcern] = None, ) -> None: db_name = self.collection.database.name client = self.collection.database.client listeners = client._event_listeners if not self.current_run: self.current_run = next(generator) self.next_run = None run = self.current_run # Connection.command validates the session, but we use # Connection.write_command conn.validate_session(client, session) last_run = False while run: if not self.retrying: self.next_run = next(generator, None) if self.next_run is None: last_run = True cmd_name = _COMMANDS[run.op_type] bwc = self.bulk_ctx_class( db_name, cmd_name, conn, op_id, listeners, session, run.op_type, self.collection.codec_options, ) while run.idx_offset < len(run.ops): # If this is the last possible operation, use the # final write concern. if last_run and (len(run.ops) - run.idx_offset) == 1: write_concern = final_write_concern or write_concern cmd = {cmd_name: self.collection.name, "ordered": self.ordered} if self.comment: cmd["comment"] = self.comment _csot.apply_write_concern(cmd, write_concern) if self.bypass_doc_val: cmd["bypassDocumentValidation"] = True if self.let is not None and run.op_type in (_DELETE, _UPDATE): cmd["let"] = self.let if session: # Start a new retryable write unless one was already # started for this command. if retryable and not self.started_retryable_write: session._start_retryable_write() self.started_retryable_write = True session._apply_to(cmd, retryable, ReadPreference.PRIMARY, conn) conn.send_cluster_time(cmd, session, client) conn.add_server_api(cmd) # CSOT: apply timeout before encoding the command. conn.apply_timeout(client, cmd) ops = islice(run.ops, run.idx_offset, None) # Run as many ops as possible in one command. if write_concern.acknowledged: result, to_send = bwc.execute(cmd, ops, client) # Retryable writeConcernErrors halt the execution of this run. wce = result.get("writeConcernError", {}) if wce.get("code", 0) in _RETRYABLE_ERROR_CODES: # Synthesize the full bulk result without modifying the # current one because this write operation may be retried. full = copy.deepcopy(full_result) _merge_command(run, full, run.idx_offset, result) _raise_bulk_write_error(full) _merge_command(run, full_result, run.idx_offset, result) # We're no longer in a retry once a command succeeds. self.retrying = False self.started_retryable_write = False if self.ordered and "writeErrors" in result: break else: to_send = bwc.execute_unack(cmd, ops, client) run.idx_offset += len(to_send) # We're supposed to continue if errors are # at the write concern level (e.g. wtimeout) if self.ordered and full_result["writeErrors"]: break # Reset our state self.current_run = run = self.next_run def execute_command( self, generator: Iterator[Any], write_concern: WriteConcern, session: Optional[ClientSession], operation: str, ) -> dict[str, Any]: """Execute using write commands.""" # nModified is only reported for write commands, not legacy ops. full_result = { "writeErrors": [], "writeConcernErrors": [], "nInserted": 0, "nUpserted": 0, "nMatched": 0, "nModified": 0, "nRemoved": 0, "upserted": [], } op_id = _randint() def retryable_bulk( session: Optional[ClientSession], conn: Connection, retryable: bool ) -> None: self._execute_command( generator, write_concern, session, conn, op_id, retryable, full_result, ) client = self.collection.database.client client._retryable_write( self.is_retryable, retryable_bulk, session, operation, bulk=self, operation_id=op_id, ) if full_result["writeErrors"] or full_result["writeConcernErrors"]: _raise_bulk_write_error(full_result) return full_result def execute_op_msg_no_results(self, conn: Connection, generator: Iterator[Any]) -> None: """Execute write commands with OP_MSG and w=0 writeConcern, unordered.""" db_name = self.collection.database.name client = self.collection.database.client listeners = client._event_listeners op_id = _randint() if not self.current_run: self.current_run = next(generator) run = self.current_run while run: cmd_name = _COMMANDS[run.op_type] bwc = self.bulk_ctx_class( db_name, cmd_name, conn, op_id, listeners, None, run.op_type, self.collection.codec_options, ) while run.idx_offset < len(run.ops): cmd = { cmd_name: self.collection.name, "ordered": False, "writeConcern": {"w": 0}, } conn.add_server_api(cmd) ops = islice(run.ops, run.idx_offset, None) # Run as many ops as possible. to_send = bwc.execute_unack(cmd, ops, client) run.idx_offset += len(to_send) self.current_run = run = next(generator, None) def execute_command_no_results( self, conn: Connection, generator: Iterator[Any], write_concern: WriteConcern, ) -> None: """Execute write commands with OP_MSG and w=0 WriteConcern, ordered.""" full_result = { "writeErrors": [], "writeConcernErrors": [], "nInserted": 0, "nUpserted": 0, "nMatched": 0, "nModified": 0, "nRemoved": 0, "upserted": [], } # Ordered bulk writes have to be acknowledged so that we stop # processing at the first error, even when the application # specified unacknowledged writeConcern. initial_write_concern = WriteConcern() op_id = _randint() try: self._execute_command( generator, initial_write_concern, None, conn, op_id, False, full_result, write_concern, ) except OperationFailure: pass def execute_no_results( self, conn: Connection, generator: Iterator[Any], write_concern: WriteConcern, ) -> None: """Execute all operations, returning no results (w=0).""" if self.uses_collation: raise ConfigurationError("Collation is unsupported for unacknowledged writes.") if self.uses_array_filters: raise ConfigurationError("arrayFilters is unsupported for unacknowledged writes.") # Guard against unsupported unacknowledged writes. unack = write_concern and not write_concern.acknowledged if unack and self.uses_hint_delete and conn.max_wire_version < 9: raise ConfigurationError( "Must be connected to MongoDB 4.4+ to use hint on unacknowledged delete commands." ) if unack and self.uses_hint_update and conn.max_wire_version < 8: raise ConfigurationError( "Must be connected to MongoDB 4.2+ to use hint on unacknowledged update commands." ) # Cannot have both unacknowledged writes and bypass document validation. if self.bypass_doc_val: raise OperationFailure( "Cannot set bypass_document_validation with unacknowledged write concern" ) if self.ordered: return self.execute_command_no_results(conn, generator, write_concern) return self.execute_op_msg_no_results(conn, generator) def execute( self, write_concern: WriteConcern, session: Optional[ClientSession], operation: str, ) -> Any: """Execute operations.""" if not self.ops: raise InvalidOperation("No operations to execute") if self.executed: raise InvalidOperation("Bulk operations can only be executed once.") self.executed = True write_concern = write_concern or self.collection.write_concern session = _validate_session_write_concern(session, write_concern) if self.ordered: generator = self.gen_ordered() else: generator = self.gen_unordered() client = self.collection.database.client if not write_concern.acknowledged: with client._conn_for_writes(session, operation) as connection: self.execute_no_results(connection, generator, write_concern) return None else: return self.execute_command(generator, write_concern, session, operation) mongodb-mongo-python-driver-509e9b7/pymongo/change_stream.py000066400000000000000000000444101462766011000243020ustar00rootroot00000000000000# Copyright 2017 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. """Watch changes on a collection, a database, or the entire cluster.""" from __future__ import annotations import copy from typing import TYPE_CHECKING, Any, Generic, Mapping, Optional, Type, Union from bson import CodecOptions, _bson_to_dict from bson.raw_bson import RawBSONDocument from bson.timestamp import Timestamp from pymongo import _csot, common from pymongo.aggregation import ( _AggregationCommand, _CollectionAggregationCommand, _DatabaseAggregationCommand, ) from pymongo.collation import validate_collation_or_none from pymongo.command_cursor import CommandCursor from pymongo.errors import ( ConnectionFailure, CursorNotFound, InvalidOperation, OperationFailure, PyMongoError, ) from pymongo.operations import _Op from pymongo.typings import _CollationIn, _DocumentType, _Pipeline # The change streams spec considers the following server errors from the # getMore command non-resumable. All other getMore errors are resumable. _RESUMABLE_GETMORE_ERRORS = frozenset( [ 6, # HostUnreachable 7, # HostNotFound 89, # NetworkTimeout 91, # ShutdownInProgress 189, # PrimarySteppedDown 262, # ExceededTimeLimit 9001, # SocketException 10107, # NotWritablePrimary 11600, # InterruptedAtShutdown 11602, # InterruptedDueToReplStateChange 13435, # NotPrimaryNoSecondaryOk 13436, # NotPrimaryOrSecondary 63, # StaleShardVersion 150, # StaleEpoch 13388, # StaleConfig 234, # RetryChangeStream 133, # FailedToSatisfyReadPreference ] ) if TYPE_CHECKING: from pymongo.client_session import ClientSession from pymongo.collection import Collection from pymongo.database import Database from pymongo.mongo_client import MongoClient from pymongo.pool import Connection def _resumable(exc: PyMongoError) -> bool: """Return True if given a resumable change stream error.""" if isinstance(exc, (ConnectionFailure, CursorNotFound)): return True if isinstance(exc, OperationFailure): if exc._max_wire_version is None: return False return ( exc._max_wire_version >= 9 and exc.has_error_label("ResumableChangeStreamError") ) or (exc._max_wire_version < 9 and exc.code in _RESUMABLE_GETMORE_ERRORS) return False class ChangeStream(Generic[_DocumentType]): """The internal abstract base class for change stream cursors. Should not be called directly by application developers. Use :meth:`pymongo.collection.Collection.watch`, :meth:`pymongo.database.Database.watch`, or :meth:`pymongo.mongo_client.MongoClient.watch` instead. .. versionadded:: 3.6 .. seealso:: The MongoDB documentation on `changeStreams `_. """ def __init__( self, target: Union[ MongoClient[_DocumentType], Database[_DocumentType], Collection[_DocumentType] ], pipeline: Optional[_Pipeline], full_document: Optional[str], resume_after: Optional[Mapping[str, Any]], max_await_time_ms: Optional[int], batch_size: Optional[int], collation: Optional[_CollationIn], start_at_operation_time: Optional[Timestamp], session: Optional[ClientSession], start_after: Optional[Mapping[str, Any]], comment: Optional[Any] = None, full_document_before_change: Optional[str] = None, show_expanded_events: Optional[bool] = None, ) -> None: if pipeline is None: pipeline = [] pipeline = common.validate_list("pipeline", pipeline) common.validate_string_or_none("full_document", full_document) validate_collation_or_none(collation) common.validate_non_negative_integer_or_none("batchSize", batch_size) self._decode_custom = False self._orig_codec_options: CodecOptions[_DocumentType] = target.codec_options if target.codec_options.type_registry._decoder_map: self._decode_custom = True # Keep the type registry so that we support encoding custom types # in the pipeline. self._target = target.with_options( # type: ignore codec_options=target.codec_options.with_options(document_class=RawBSONDocument) ) else: self._target = target self._pipeline = copy.deepcopy(pipeline) self._full_document = full_document self._full_document_before_change = full_document_before_change self._uses_start_after = start_after is not None self._uses_resume_after = resume_after is not None self._resume_token = copy.deepcopy(start_after or resume_after) self._max_await_time_ms = max_await_time_ms self._batch_size = batch_size self._collation = collation self._start_at_operation_time = start_at_operation_time self._session = session self._comment = comment self._closed = False self._timeout = self._target._timeout self._show_expanded_events = show_expanded_events # Initialize cursor. self._cursor = self._create_cursor() @property def _aggregation_command_class(self) -> Type[_AggregationCommand]: """The aggregation command class to be used.""" raise NotImplementedError @property def _client(self) -> MongoClient: """The client against which the aggregation commands for this ChangeStream will be run. """ raise NotImplementedError def _change_stream_options(self) -> dict[str, Any]: """Return the options dict for the $changeStream pipeline stage.""" options: dict[str, Any] = {} if self._full_document is not None: options["fullDocument"] = self._full_document if self._full_document_before_change is not None: options["fullDocumentBeforeChange"] = self._full_document_before_change resume_token = self.resume_token if resume_token is not None: if self._uses_start_after: options["startAfter"] = resume_token else: options["resumeAfter"] = resume_token if self._start_at_operation_time is not None: options["startAtOperationTime"] = self._start_at_operation_time if self._show_expanded_events: options["showExpandedEvents"] = self._show_expanded_events return options def _command_options(self) -> dict[str, Any]: """Return the options dict for the aggregation command.""" options = {} if self._max_await_time_ms is not None: options["maxAwaitTimeMS"] = self._max_await_time_ms if self._batch_size is not None: options["batchSize"] = self._batch_size return options def _aggregation_pipeline(self) -> list[dict[str, Any]]: """Return the full aggregation pipeline for this ChangeStream.""" options = self._change_stream_options() full_pipeline: list = [{"$changeStream": options}] full_pipeline.extend(self._pipeline) return full_pipeline def _process_result(self, result: Mapping[str, Any], conn: Connection) -> None: """Callback that caches the postBatchResumeToken or startAtOperationTime from a changeStream aggregate command response containing an empty batch of change documents. This is implemented as a callback because we need access to the wire version in order to determine whether to cache this value. """ if not result["cursor"]["firstBatch"]: if "postBatchResumeToken" in result["cursor"]: self._resume_token = result["cursor"]["postBatchResumeToken"] elif ( self._start_at_operation_time is None and self._uses_resume_after is False and self._uses_start_after is False and conn.max_wire_version >= 7 ): self._start_at_operation_time = result.get("operationTime") # PYTHON-2181: informative error on missing operationTime. if self._start_at_operation_time is None: raise OperationFailure( "Expected field 'operationTime' missing from command " f"response : {result!r}" ) def _run_aggregation_cmd( self, session: Optional[ClientSession], explicit_session: bool ) -> CommandCursor: """Run the full aggregation pipeline for this ChangeStream and return the corresponding CommandCursor. """ cmd = self._aggregation_command_class( self._target, CommandCursor, self._aggregation_pipeline(), self._command_options(), explicit_session, result_processor=self._process_result, comment=self._comment, ) return self._client._retryable_read( cmd.get_cursor, self._target._read_preference_for(session), session, operation=_Op.AGGREGATE, ) def _create_cursor(self) -> CommandCursor: with self._client._tmp_session(self._session, close=False) as s: return self._run_aggregation_cmd(session=s, explicit_session=self._session is not None) def _resume(self) -> None: """Reestablish this change stream after a resumable error.""" try: self._cursor.close() except PyMongoError: pass self._cursor = self._create_cursor() def close(self) -> None: """Close this ChangeStream.""" self._closed = True self._cursor.close() def __iter__(self) -> ChangeStream[_DocumentType]: return self @property def resume_token(self) -> Optional[Mapping[str, Any]]: """The cached resume token that will be used to resume after the most recently returned change. .. versionadded:: 3.9 """ return copy.deepcopy(self._resume_token) @_csot.apply def next(self) -> _DocumentType: """Advance the cursor. This method blocks until the next change document is returned or an unrecoverable error is raised. This method is used when iterating over all changes in the cursor. For example:: try: resume_token = None pipeline = [{'$match': {'operationType': 'insert'}}] with db.collection.watch(pipeline) as stream: for insert_change in stream: print(insert_change) resume_token = stream.resume_token except pymongo.errors.PyMongoError: # The ChangeStream encountered an unrecoverable error or the # resume attempt failed to recreate the cursor. if resume_token is None: # There is no usable resume token because there was a # failure during ChangeStream initialization. logging.error('...') else: # Use the interrupted ChangeStream's resume token to create # a new ChangeStream. The new stream will continue from the # last seen insert change without missing any events. with db.collection.watch( pipeline, resume_after=resume_token) as stream: for insert_change in stream: print(insert_change) Raises :exc:`StopIteration` if this ChangeStream is closed. """ while self.alive: doc = self.try_next() if doc is not None: return doc raise StopIteration __next__ = next @property def alive(self) -> bool: """Does this cursor have the potential to return more data? .. note:: Even if :attr:`alive` is ``True``, :meth:`next` can raise :exc:`StopIteration` and :meth:`try_next` can return ``None``. .. versionadded:: 3.8 """ return not self._closed @_csot.apply def try_next(self) -> Optional[_DocumentType]: """Advance the cursor without blocking indefinitely. This method returns the next change document without waiting indefinitely for the next change. For example:: with db.collection.watch() as stream: while stream.alive: change = stream.try_next() # Note that the ChangeStream's resume token may be updated # even when no changes are returned. print("Current resume token: %r" % (stream.resume_token,)) if change is not None: print("Change document: %r" % (change,)) continue # We end up here when there are no recent changes. # Sleep for a while before trying again to avoid flooding # the server with getMore requests when no changes are # available. time.sleep(10) If no change document is cached locally then this method runs a single getMore command. If the getMore yields any documents, the next document is returned, otherwise, if the getMore returns no documents (because there have been no changes) then ``None`` is returned. :return: The next change document or ``None`` when no document is available after running a single getMore or when the cursor is closed. .. versionadded:: 3.8 """ if not self._closed and not self._cursor.alive: self._resume() # Attempt to get the next change with at most one getMore and at most # one resume attempt. try: try: change = self._cursor._try_next(True) except PyMongoError as exc: if not _resumable(exc): raise self._resume() change = self._cursor._try_next(False) except PyMongoError as exc: # Close the stream after a fatal error. if not _resumable(exc) and not exc.timeout: self.close() raise except Exception: self.close() raise # Check if the cursor was invalidated. if not self._cursor.alive: self._closed = True # If no changes are available. if change is None: # We have either iterated over all documents in the cursor, # OR the most-recently returned batch is empty. In either case, # update the cached resume token with the postBatchResumeToken if # one was returned. We also clear the startAtOperationTime. if self._cursor._post_batch_resume_token is not None: self._resume_token = self._cursor._post_batch_resume_token self._start_at_operation_time = None return change # Else, changes are available. try: resume_token = change["_id"] except KeyError: self.close() raise InvalidOperation( "Cannot provide resume functionality when the resume token is missing." ) from None # If this is the last change document from the current batch, cache the # postBatchResumeToken. if not self._cursor._has_next() and self._cursor._post_batch_resume_token: resume_token = self._cursor._post_batch_resume_token # Hereafter, don't use startAfter; instead use resumeAfter. self._uses_start_after = False self._uses_resume_after = True # Cache the resume token and clear startAtOperationTime. self._resume_token = resume_token self._start_at_operation_time = None if self._decode_custom: return _bson_to_dict(change.raw, self._orig_codec_options) return change def __enter__(self) -> ChangeStream[_DocumentType]: return self def __exit__(self, exc_type: Any, exc_val: Any, exc_tb: Any) -> None: self.close() class CollectionChangeStream(ChangeStream[_DocumentType]): """A change stream that watches changes on a single collection. Should not be called directly by application developers. Use helper method :meth:`pymongo.collection.Collection.watch` instead. .. versionadded:: 3.7 """ _target: Collection[_DocumentType] @property def _aggregation_command_class(self) -> Type[_CollectionAggregationCommand]: return _CollectionAggregationCommand @property def _client(self) -> MongoClient[_DocumentType]: return self._target.database.client class DatabaseChangeStream(ChangeStream[_DocumentType]): """A change stream that watches changes on all collections in a database. Should not be called directly by application developers. Use helper method :meth:`pymongo.database.Database.watch` instead. .. versionadded:: 3.7 """ _target: Database[_DocumentType] @property def _aggregation_command_class(self) -> Type[_DatabaseAggregationCommand]: return _DatabaseAggregationCommand @property def _client(self) -> MongoClient[_DocumentType]: return self._target.client class ClusterChangeStream(DatabaseChangeStream[_DocumentType]): """A change stream that watches changes on all collections in the cluster. Should not be called directly by application developers. Use helper method :meth:`pymongo.mongo_client.MongoClient.watch` instead. .. versionadded:: 3.7 """ def _change_stream_options(self) -> dict[str, Any]: options = super()._change_stream_options() options["allChangesForCluster"] = True return options mongodb-mongo-python-driver-509e9b7/pymongo/client_options.py000066400000000000000000000303171462766011000245340ustar00rootroot00000000000000# Copyright 2014-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. """Tools to parse mongo client options.""" from __future__ import annotations from typing import TYPE_CHECKING, Any, Mapping, Optional, Sequence, cast from bson.codec_options import _parse_codec_options from pymongo import common from pymongo.compression_support import CompressionSettings from pymongo.errors import ConfigurationError from pymongo.monitoring import _EventListener, _EventListeners from pymongo.pool import PoolOptions from pymongo.read_concern import ReadConcern from pymongo.read_preferences import ( _ServerMode, make_read_preference, read_pref_mode_from_name, ) from pymongo.server_selectors import any_server_selector from pymongo.ssl_support import get_ssl_context from pymongo.write_concern import WriteConcern, validate_boolean if TYPE_CHECKING: from bson.codec_options import CodecOptions from pymongo.auth import MongoCredential from pymongo.encryption_options import AutoEncryptionOpts from pymongo.pyopenssl_context import SSLContext from pymongo.topology_description import _ServerSelector def _parse_credentials( username: str, password: str, database: Optional[str], options: Mapping[str, Any] ) -> Optional[MongoCredential]: """Parse authentication credentials.""" mechanism = options.get("authmechanism", "DEFAULT" if username else None) source = options.get("authsource") if username or mechanism: from pymongo.auth import _build_credentials_tuple return _build_credentials_tuple(mechanism, source, username, password, options, database) return None def _parse_read_preference(options: Mapping[str, Any]) -> _ServerMode: """Parse read preference options.""" if "read_preference" in options: return options["read_preference"] name = options.get("readpreference", "primary") mode = read_pref_mode_from_name(name) tags = options.get("readpreferencetags") max_staleness = options.get("maxstalenessseconds", -1) return make_read_preference(mode, tags, max_staleness) def _parse_write_concern(options: Mapping[str, Any]) -> WriteConcern: """Parse write concern options.""" concern = options.get("w") wtimeout = options.get("wtimeoutms") j = options.get("journal") fsync = options.get("fsync") return WriteConcern(concern, wtimeout, j, fsync) def _parse_read_concern(options: Mapping[str, Any]) -> ReadConcern: """Parse read concern options.""" concern = options.get("readconcernlevel") return ReadConcern(concern) def _parse_ssl_options(options: Mapping[str, Any]) -> tuple[Optional[SSLContext], bool]: """Parse ssl options.""" use_tls = options.get("tls") if use_tls is not None: validate_boolean("tls", use_tls) certfile = options.get("tlscertificatekeyfile") passphrase = options.get("tlscertificatekeyfilepassword") ca_certs = options.get("tlscafile") crlfile = options.get("tlscrlfile") allow_invalid_certificates = options.get("tlsallowinvalidcertificates", False) allow_invalid_hostnames = options.get("tlsallowinvalidhostnames", False) disable_ocsp_endpoint_check = options.get("tlsdisableocspendpointcheck", False) enabled_tls_opts = [] for opt in ( "tlscertificatekeyfile", "tlscertificatekeyfilepassword", "tlscafile", "tlscrlfile", ): # Any non-null value of these options implies tls=True. if opt in options and options[opt]: enabled_tls_opts.append(opt) for opt in ( "tlsallowinvalidcertificates", "tlsallowinvalidhostnames", "tlsdisableocspendpointcheck", ): # A value of False for these options implies tls=True. if opt in options and not options[opt]: enabled_tls_opts.append(opt) if enabled_tls_opts: if use_tls is None: # Implicitly enable TLS when one of the tls* options is set. use_tls = True elif not use_tls: # Error since tls is explicitly disabled but a tls option is set. raise ConfigurationError( "TLS has not been enabled but the " "following tls parameters have been set: " "%s. Please set `tls=True` or remove." % ", ".join(enabled_tls_opts) ) if use_tls: ctx = get_ssl_context( certfile, passphrase, ca_certs, crlfile, allow_invalid_certificates, allow_invalid_hostnames, disable_ocsp_endpoint_check, ) return ctx, allow_invalid_hostnames return None, allow_invalid_hostnames def _parse_pool_options( username: str, password: str, database: Optional[str], options: Mapping[str, Any] ) -> PoolOptions: """Parse connection pool options.""" credentials = _parse_credentials(username, password, database, options) max_pool_size = options.get("maxpoolsize", common.MAX_POOL_SIZE) min_pool_size = options.get("minpoolsize", common.MIN_POOL_SIZE) max_idle_time_seconds = options.get("maxidletimems", common.MAX_IDLE_TIME_SEC) if max_pool_size is not None and min_pool_size > max_pool_size: raise ValueError("minPoolSize must be smaller or equal to maxPoolSize") connect_timeout = options.get("connecttimeoutms", common.CONNECT_TIMEOUT) socket_timeout = options.get("sockettimeoutms") wait_queue_timeout = options.get("waitqueuetimeoutms", common.WAIT_QUEUE_TIMEOUT) event_listeners = cast(Optional[Sequence[_EventListener]], options.get("event_listeners")) appname = options.get("appname") driver = options.get("driver") server_api = options.get("server_api") compression_settings = CompressionSettings( options.get("compressors", []), options.get("zlibcompressionlevel", -1) ) ssl_context, tls_allow_invalid_hostnames = _parse_ssl_options(options) load_balanced = options.get("loadbalanced") max_connecting = options.get("maxconnecting", common.MAX_CONNECTING) return PoolOptions( max_pool_size, min_pool_size, max_idle_time_seconds, connect_timeout, socket_timeout, wait_queue_timeout, ssl_context, tls_allow_invalid_hostnames, _EventListeners(event_listeners), appname, driver, compression_settings, max_connecting=max_connecting, server_api=server_api, load_balanced=load_balanced, credentials=credentials, ) class ClientOptions: """Read only configuration options for a MongoClient. Should not be instantiated directly by application developers. Access a client's options via :attr:`pymongo.mongo_client.MongoClient.options` instead. """ def __init__( self, username: str, password: str, database: Optional[str], options: Mapping[str, Any] ): self.__options = options self.__codec_options = _parse_codec_options(options) self.__direct_connection = options.get("directconnection") self.__local_threshold_ms = options.get("localthresholdms", common.LOCAL_THRESHOLD_MS) # self.__server_selection_timeout is in seconds. Must use full name for # common.SERVER_SELECTION_TIMEOUT because it is set directly by tests. self.__server_selection_timeout = options.get( "serverselectiontimeoutms", common.SERVER_SELECTION_TIMEOUT ) self.__pool_options = _parse_pool_options(username, password, database, options) self.__read_preference = _parse_read_preference(options) self.__replica_set_name = options.get("replicaset") self.__write_concern = _parse_write_concern(options) self.__read_concern = _parse_read_concern(options) self.__connect = options.get("connect") self.__heartbeat_frequency = options.get("heartbeatfrequencyms", common.HEARTBEAT_FREQUENCY) self.__retry_writes = options.get("retrywrites", common.RETRY_WRITES) self.__retry_reads = options.get("retryreads", common.RETRY_READS) self.__server_selector = options.get("server_selector", any_server_selector) self.__auto_encryption_opts = options.get("auto_encryption_opts") self.__load_balanced = options.get("loadbalanced") self.__timeout = options.get("timeoutms") self.__server_monitoring_mode = options.get( "servermonitoringmode", common.SERVER_MONITORING_MODE ) @property def _options(self) -> Mapping[str, Any]: """The original options used to create this ClientOptions.""" return self.__options @property def connect(self) -> Optional[bool]: """Whether to begin discovering a MongoDB topology automatically.""" return self.__connect @property def codec_options(self) -> CodecOptions: """A :class:`~bson.codec_options.CodecOptions` instance.""" return self.__codec_options @property def direct_connection(self) -> Optional[bool]: """Whether to connect to the deployment in 'Single' topology.""" return self.__direct_connection @property def local_threshold_ms(self) -> int: """The local threshold for this instance.""" return self.__local_threshold_ms @property def server_selection_timeout(self) -> int: """The server selection timeout for this instance in seconds.""" return self.__server_selection_timeout @property def server_selector(self) -> _ServerSelector: return self.__server_selector @property def heartbeat_frequency(self) -> int: """The monitoring frequency in seconds.""" return self.__heartbeat_frequency @property def pool_options(self) -> PoolOptions: """A :class:`~pymongo.pool.PoolOptions` instance.""" return self.__pool_options @property def read_preference(self) -> _ServerMode: """A read preference instance.""" return self.__read_preference @property def replica_set_name(self) -> Optional[str]: """Replica set name or None.""" return self.__replica_set_name @property def write_concern(self) -> WriteConcern: """A :class:`~pymongo.write_concern.WriteConcern` instance.""" return self.__write_concern @property def read_concern(self) -> ReadConcern: """A :class:`~pymongo.read_concern.ReadConcern` instance.""" return self.__read_concern @property def timeout(self) -> Optional[float]: """The configured timeoutMS converted to seconds, or None. .. versionadded:: 4.2 """ return self.__timeout @property def retry_writes(self) -> bool: """If this instance should retry supported write operations.""" return self.__retry_writes @property def retry_reads(self) -> bool: """If this instance should retry supported read operations.""" return self.__retry_reads @property def auto_encryption_opts(self) -> Optional[AutoEncryptionOpts]: """A :class:`~pymongo.encryption.AutoEncryptionOpts` or None.""" return self.__auto_encryption_opts @property def load_balanced(self) -> Optional[bool]: """True if the client was configured to connect to a load balancer.""" return self.__load_balanced @property def event_listeners(self) -> list[_EventListeners]: """The event listeners registered for this client. See :mod:`~pymongo.monitoring` for details. .. versionadded:: 4.0 """ assert self.__pool_options._event_listeners is not None return self.__pool_options._event_listeners.event_listeners() @property def server_monitoring_mode(self) -> str: """The configured serverMonitoringMode option. .. versionadded:: 4.5 """ return self.__server_monitoring_mode mongodb-mongo-python-driver-509e9b7/pymongo/client_session.py000066400000000000000000001267211462766011000245310ustar00rootroot00000000000000# Copyright 2017 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. """Logical sessions for ordering sequential operations. .. versionadded:: 3.6 Causally Consistent Reads ========================= .. code-block:: python with client.start_session(causal_consistency=True) as session: collection = client.db.collection collection.update_one({"_id": 1}, {"$set": {"x": 10}}, session=session) secondary_c = collection.with_options(read_preference=ReadPreference.SECONDARY) # A secondary read waits for replication of the write. secondary_c.find_one({"_id": 1}, session=session) If `causal_consistency` is True (the default), read operations that use the session are causally after previous read and write operations. Using a causally consistent session, an application can read its own writes and is guaranteed monotonic reads, even when reading from replica set secondaries. .. seealso:: The MongoDB documentation on `causal-consistency `_. .. _transactions-ref: Transactions ============ .. versionadded:: 3.7 MongoDB 4.0 adds support for transactions on replica set primaries. A transaction is associated with a :class:`ClientSession`. To start a transaction on a session, use :meth:`ClientSession.start_transaction` in a with-statement. Then, execute an operation within the transaction by passing the session to the operation: .. code-block:: python orders = client.db.orders inventory = client.db.inventory with client.start_session() as session: with session.start_transaction(): orders.insert_one({"sku": "abc123", "qty": 100}, session=session) inventory.update_one( {"sku": "abc123", "qty": {"$gte": 100}}, {"$inc": {"qty": -100}}, session=session, ) Upon normal completion of ``with session.start_transaction()`` block, the transaction automatically calls :meth:`ClientSession.commit_transaction`. If the block exits with an exception, the transaction automatically calls :meth:`ClientSession.abort_transaction`. In general, multi-document transactions only support read/write (CRUD) operations on existing collections. However, MongoDB 4.4 adds support for creating collections and indexes with some limitations, including an insert operation that would result in the creation of a new collection. For a complete description of all the supported and unsupported operations see the `MongoDB server's documentation for transactions `_. A session may only have a single active transaction at a time, multiple transactions on the same session can be executed in sequence. Sharded Transactions ^^^^^^^^^^^^^^^^^^^^ .. versionadded:: 3.9 PyMongo 3.9 adds support for transactions on sharded clusters running MongoDB >=4.2. Sharded transactions have the same API as replica set transactions. When running a transaction against a sharded cluster, the session is pinned to the mongos server selected for the first operation in the transaction. All subsequent operations that are part of the same transaction are routed to the same mongos server. When the transaction is completed, by running either commitTransaction or abortTransaction, the session is unpinned. .. seealso:: The MongoDB documentation on `transactions `_. .. _snapshot-reads-ref: Snapshot Reads ============== .. versionadded:: 3.12 MongoDB 5.0 adds support for snapshot reads. Snapshot reads are requested by passing the ``snapshot`` option to :meth:`~pymongo.mongo_client.MongoClient.start_session`. If ``snapshot`` is True, all read operations that use this session read data from the same snapshot timestamp. The server chooses the latest majority-committed snapshot timestamp when executing the first read operation using the session. Subsequent reads on this session read from the same snapshot timestamp. Snapshot reads are also supported when reading from replica set secondaries. .. code-block:: python # Each read using this session reads data from the same point in time. with client.start_session(snapshot=True) as session: order = orders.find_one({"sku": "abc123"}, session=session) inventory = inventory.find_one({"sku": "abc123"}, session=session) Snapshot Reads Limitations ^^^^^^^^^^^^^^^^^^^^^^^^^^ Snapshot reads sessions are incompatible with ``causal_consistency=True``. Only the following read operations are supported in a snapshot reads session: - :meth:`~pymongo.collection.Collection.find` - :meth:`~pymongo.collection.Collection.find_one` - :meth:`~pymongo.collection.Collection.aggregate` - :meth:`~pymongo.collection.Collection.count_documents` - :meth:`~pymongo.collection.Collection.distinct` (on unsharded collections) Classes ======= """ from __future__ import annotations import collections import time import uuid from collections.abc import Mapping as _Mapping from typing import ( TYPE_CHECKING, Any, Callable, ContextManager, Mapping, MutableMapping, NoReturn, Optional, Type, TypeVar, ) from bson.binary import Binary from bson.int64 import Int64 from bson.timestamp import Timestamp from pymongo import _csot from pymongo.cursor import _ConnectionManager from pymongo.errors import ( ConfigurationError, ConnectionFailure, InvalidOperation, OperationFailure, PyMongoError, WTimeoutError, ) from pymongo.helpers import _RETRYABLE_ERROR_CODES from pymongo.operations import _Op from pymongo.read_concern import ReadConcern from pymongo.read_preferences import ReadPreference, _ServerMode from pymongo.server_type import SERVER_TYPE from pymongo.write_concern import WriteConcern if TYPE_CHECKING: from types import TracebackType from pymongo.pool import Connection from pymongo.server import Server from pymongo.typings import ClusterTime, _Address class SessionOptions: """Options for a new :class:`ClientSession`. :param causal_consistency: If True, read operations are causally ordered within the session. Defaults to True when the ``snapshot`` option is ``False``. :param default_transaction_options: The default TransactionOptions to use for transactions started on this session. :param snapshot: If True, then all reads performed using this session will read from the same snapshot. This option is incompatible with ``causal_consistency=True``. Defaults to ``False``. .. versionchanged:: 3.12 Added the ``snapshot`` parameter. """ def __init__( self, causal_consistency: Optional[bool] = None, default_transaction_options: Optional[TransactionOptions] = None, snapshot: Optional[bool] = False, ) -> None: if snapshot: if causal_consistency: raise ConfigurationError("snapshot reads do not support causal_consistency=True") causal_consistency = False elif causal_consistency is None: causal_consistency = True self._causal_consistency = causal_consistency if default_transaction_options is not None: if not isinstance(default_transaction_options, TransactionOptions): raise TypeError( "default_transaction_options must be an instance of " "pymongo.client_session.TransactionOptions, not: {!r}".format( default_transaction_options ) ) self._default_transaction_options = default_transaction_options self._snapshot = snapshot @property def causal_consistency(self) -> bool: """Whether causal consistency is configured.""" return self._causal_consistency @property def default_transaction_options(self) -> Optional[TransactionOptions]: """The default TransactionOptions to use for transactions started on this session. .. versionadded:: 3.7 """ return self._default_transaction_options @property def snapshot(self) -> Optional[bool]: """Whether snapshot reads are configured. .. versionadded:: 3.12 """ return self._snapshot class TransactionOptions: """Options for :meth:`ClientSession.start_transaction`. :param read_concern: The :class:`~pymongo.read_concern.ReadConcern` to use for this transaction. If ``None`` (the default) the :attr:`read_preference` of the :class:`MongoClient` is used. :param write_concern: The :class:`~pymongo.write_concern.WriteConcern` to use for this transaction. If ``None`` (the default) the :attr:`read_preference` of the :class:`MongoClient` is used. :param read_preference: The read preference to use. If ``None`` (the default) the :attr:`read_preference` of this :class:`MongoClient` is used. See :mod:`~pymongo.read_preferences` for options. Transactions which read must use :attr:`~pymongo.read_preferences.ReadPreference.PRIMARY`. :param max_commit_time_ms: The maximum amount of time to allow a single commitTransaction command to run. This option is an alias for maxTimeMS option on the commitTransaction command. If ``None`` (the default) maxTimeMS is not used. .. versionchanged:: 3.9 Added the ``max_commit_time_ms`` option. .. versionadded:: 3.7 """ def __init__( self, read_concern: Optional[ReadConcern] = None, write_concern: Optional[WriteConcern] = None, read_preference: Optional[_ServerMode] = None, max_commit_time_ms: Optional[int] = None, ) -> None: self._read_concern = read_concern self._write_concern = write_concern self._read_preference = read_preference self._max_commit_time_ms = max_commit_time_ms if read_concern is not None: if not isinstance(read_concern, ReadConcern): raise TypeError( "read_concern must be an instance of " f"pymongo.read_concern.ReadConcern, not: {read_concern!r}" ) if write_concern is not None: if not isinstance(write_concern, WriteConcern): raise TypeError( "write_concern must be an instance of " f"pymongo.write_concern.WriteConcern, not: {write_concern!r}" ) if not write_concern.acknowledged: raise ConfigurationError( "transactions do not support unacknowledged write concern" f": {write_concern!r}" ) if read_preference is not None: if not isinstance(read_preference, _ServerMode): raise TypeError( f"{read_preference!r} is not valid for read_preference. See " "pymongo.read_preferences for valid " "options." ) if max_commit_time_ms is not None: if not isinstance(max_commit_time_ms, int): raise TypeError("max_commit_time_ms must be an integer or None") @property def read_concern(self) -> Optional[ReadConcern]: """This transaction's :class:`~pymongo.read_concern.ReadConcern`.""" return self._read_concern @property def write_concern(self) -> Optional[WriteConcern]: """This transaction's :class:`~pymongo.write_concern.WriteConcern`.""" return self._write_concern @property def read_preference(self) -> Optional[_ServerMode]: """This transaction's :class:`~pymongo.read_preferences.ReadPreference`.""" return self._read_preference @property def max_commit_time_ms(self) -> Optional[int]: """The maxTimeMS to use when running a commitTransaction command. .. versionadded:: 3.9 """ return self._max_commit_time_ms def _validate_session_write_concern( session: Optional[ClientSession], write_concern: Optional[WriteConcern] ) -> Optional[ClientSession]: """Validate that an explicit session is not used with an unack'ed write. Returns the session to use for the next operation. """ if session: if write_concern is not None and not write_concern.acknowledged: # For unacknowledged writes without an explicit session, # drivers SHOULD NOT use an implicit session. If a driver # creates an implicit session for unacknowledged writes # without an explicit session, the driver MUST NOT send the # session ID. if session._implicit: return None else: raise ConfigurationError( "Explicit sessions are incompatible with " f"unacknowledged write concern: {write_concern!r}" ) return session class _TransactionContext: """Internal transaction context manager for start_transaction.""" def __init__(self, session: ClientSession): self.__session = session def __enter__(self) -> _TransactionContext: return self def __exit__( self, exc_type: Optional[Type[BaseException]], exc_val: Optional[BaseException], exc_tb: Optional[TracebackType], ) -> None: if self.__session.in_transaction: if exc_val is None: self.__session.commit_transaction() else: self.__session.abort_transaction() class _TxnState: NONE = 1 STARTING = 2 IN_PROGRESS = 3 COMMITTED = 4 COMMITTED_EMPTY = 5 ABORTED = 6 class _Transaction: """Internal class to hold transaction information in a ClientSession.""" def __init__(self, opts: Optional[TransactionOptions], client: MongoClient): self.opts = opts self.state = _TxnState.NONE self.sharded = False self.pinned_address: Optional[_Address] = None self.conn_mgr: Optional[_ConnectionManager] = None self.recovery_token = None self.attempt = 0 self.client = client def active(self) -> bool: return self.state in (_TxnState.STARTING, _TxnState.IN_PROGRESS) def starting(self) -> bool: return self.state == _TxnState.STARTING @property def pinned_conn(self) -> Optional[Connection]: if self.active() and self.conn_mgr: return self.conn_mgr.conn return None def pin(self, server: Server, conn: Connection) -> None: self.sharded = True self.pinned_address = server.description.address if server.description.server_type == SERVER_TYPE.LoadBalancer: conn.pin_txn() self.conn_mgr = _ConnectionManager(conn, False) def unpin(self) -> None: self.pinned_address = None if self.conn_mgr: self.conn_mgr.close() self.conn_mgr = None def reset(self) -> None: self.unpin() self.state = _TxnState.NONE self.sharded = False self.recovery_token = None self.attempt = 0 def __del__(self) -> None: if self.conn_mgr: # Reuse the cursor closing machinery to return the socket to the # pool soon. self.client._close_cursor_soon(0, None, self.conn_mgr) self.conn_mgr = None def _reraise_with_unknown_commit(exc: Any) -> NoReturn: """Re-raise an exception with the UnknownTransactionCommitResult label.""" exc._add_error_label("UnknownTransactionCommitResult") raise def _max_time_expired_error(exc: PyMongoError) -> bool: """Return true if exc is a MaxTimeMSExpired error.""" return isinstance(exc, OperationFailure) and exc.code == 50 # From the transactions spec, all the retryable writes errors plus # WriteConcernFailed. _UNKNOWN_COMMIT_ERROR_CODES: frozenset = _RETRYABLE_ERROR_CODES | frozenset( [ 64, # WriteConcernFailed 50, # MaxTimeMSExpired ] ) # From the Convenient API for Transactions spec, with_transaction must # halt retries after 120 seconds. # This limit is non-configurable and was chosen to be twice the 60 second # default value of MongoDB's `transactionLifetimeLimitSeconds` parameter. _WITH_TRANSACTION_RETRY_TIME_LIMIT = 120 def _within_time_limit(start_time: float) -> bool: """Are we within the with_transaction retry limit?""" return time.monotonic() - start_time < _WITH_TRANSACTION_RETRY_TIME_LIMIT _T = TypeVar("_T") if TYPE_CHECKING: from pymongo.mongo_client import MongoClient class ClientSession: """A session for ordering sequential operations. :class:`ClientSession` instances are **not thread-safe or fork-safe**. They can only be used by one thread or process at a time. A single :class:`ClientSession` cannot be used to run multiple operations concurrently. Should not be initialized directly by application developers - to create a :class:`ClientSession`, call :meth:`~pymongo.mongo_client.MongoClient.start_session`. """ def __init__( self, client: MongoClient, server_session: Any, options: SessionOptions, implicit: bool, ) -> None: # A MongoClient, a _ServerSession, a SessionOptions, and a set. self._client: MongoClient = client self._server_session = server_session self._options = options self._cluster_time: Optional[Mapping[str, Any]] = None self._operation_time: Optional[Timestamp] = None self._snapshot_time = None # Is this an implicitly created session? self._implicit = implicit self._transaction = _Transaction(None, client) def end_session(self) -> None: """Finish this session. If a transaction has started, abort it. It is an error to use the session after the session has ended. """ self._end_session(lock=True) def _end_session(self, lock: bool) -> None: if self._server_session is not None: try: if self.in_transaction: self.abort_transaction() # It's possible we're still pinned here when the transaction # is in the committed state when the session is discarded. self._unpin() finally: self._client._return_server_session(self._server_session, lock) self._server_session = None def _check_ended(self) -> None: if self._server_session is None: raise InvalidOperation("Cannot use ended session") def __enter__(self) -> ClientSession: return self def __exit__(self, exc_type: Any, exc_val: Any, exc_tb: Any) -> None: self._end_session(lock=True) @property def client(self) -> MongoClient: """The :class:`~pymongo.mongo_client.MongoClient` this session was created from. """ return self._client @property def options(self) -> SessionOptions: """The :class:`SessionOptions` this session was created with.""" return self._options @property def session_id(self) -> Mapping[str, Any]: """A BSON document, the opaque server session identifier.""" self._check_ended() self._materialize(self._client.topology_description.logical_session_timeout_minutes) return self._server_session.session_id @property def _transaction_id(self) -> Int64: """The current transaction id for the underlying server session.""" self._materialize(self._client.topology_description.logical_session_timeout_minutes) return self._server_session.transaction_id @property def cluster_time(self) -> Optional[ClusterTime]: """The cluster time returned by the last operation executed in this session. """ return self._cluster_time @property def operation_time(self) -> Optional[Timestamp]: """The operation time returned by the last operation executed in this session. """ return self._operation_time def _inherit_option(self, name: str, val: _T) -> _T: """Return the inherited TransactionOption value.""" if val: return val txn_opts = self.options.default_transaction_options parent_val = txn_opts and getattr(txn_opts, name) if parent_val: return parent_val return getattr(self.client, name) def with_transaction( self, callback: Callable[[ClientSession], _T], read_concern: Optional[ReadConcern] = None, write_concern: Optional[WriteConcern] = None, read_preference: Optional[_ServerMode] = None, max_commit_time_ms: Optional[int] = None, ) -> _T: """Execute a callback in a transaction. This method starts a transaction on this session, executes ``callback`` once, and then commits the transaction. For example:: def callback(session): orders = session.client.db.orders inventory = session.client.db.inventory orders.insert_one({"sku": "abc123", "qty": 100}, session=session) inventory.update_one({"sku": "abc123", "qty": {"$gte": 100}}, {"$inc": {"qty": -100}}, session=session) with client.start_session() as session: session.with_transaction(callback) To pass arbitrary arguments to the ``callback``, wrap your callable with a ``lambda`` like this:: def callback(session, custom_arg, custom_kwarg=None): # Transaction operations... with client.start_session() as session: session.with_transaction( lambda s: callback(s, "custom_arg", custom_kwarg=1)) In the event of an exception, ``with_transaction`` may retry the commit or the entire transaction, therefore ``callback`` may be invoked multiple times by a single call to ``with_transaction``. Developers should be mindful of this possibility when writing a ``callback`` that modifies application state or has any other side-effects. Note that even when the ``callback`` is invoked multiple times, ``with_transaction`` ensures that the transaction will be committed at-most-once on the server. The ``callback`` should not attempt to start new transactions, but should simply run operations meant to be contained within a transaction. The ``callback`` should also not commit the transaction; this is handled automatically by ``with_transaction``. If the ``callback`` does commit or abort the transaction without error, however, ``with_transaction`` will return without taking further action. :class:`ClientSession` instances are **not thread-safe or fork-safe**. Consequently, the ``callback`` must not attempt to execute multiple operations concurrently. When ``callback`` raises an exception, ``with_transaction`` automatically aborts the current transaction. When ``callback`` or :meth:`~ClientSession.commit_transaction` raises an exception that includes the ``"TransientTransactionError"`` error label, ``with_transaction`` starts a new transaction and re-executes the ``callback``. When :meth:`~ClientSession.commit_transaction` raises an exception with the ``"UnknownTransactionCommitResult"`` error label, ``with_transaction`` retries the commit until the result of the transaction is known. This method will cease retrying after 120 seconds has elapsed. This timeout is not configurable and any exception raised by the ``callback`` or by :meth:`ClientSession.commit_transaction` after the timeout is reached will be re-raised. Applications that desire a different timeout duration should not use this method. :param callback: The callable ``callback`` to run inside a transaction. The callable must accept a single argument, this session. Note, under certain error conditions the callback may be run multiple times. :param read_concern: The :class:`~pymongo.read_concern.ReadConcern` to use for this transaction. :param write_concern: The :class:`~pymongo.write_concern.WriteConcern` to use for this transaction. :param read_preference: The read preference to use for this transaction. If ``None`` (the default) the :attr:`read_preference` of this :class:`Database` is used. See :mod:`~pymongo.read_preferences` for options. :return: The return value of the ``callback``. .. versionadded:: 3.9 """ start_time = time.monotonic() while True: self.start_transaction(read_concern, write_concern, read_preference, max_commit_time_ms) try: ret = callback(self) except Exception as exc: if self.in_transaction: self.abort_transaction() if ( isinstance(exc, PyMongoError) and exc.has_error_label("TransientTransactionError") and _within_time_limit(start_time) ): # Retry the entire transaction. continue raise if not self.in_transaction: # Assume callback intentionally ended the transaction. return ret while True: try: self.commit_transaction() except PyMongoError as exc: if ( exc.has_error_label("UnknownTransactionCommitResult") and _within_time_limit(start_time) and not _max_time_expired_error(exc) ): # Retry the commit. continue if exc.has_error_label("TransientTransactionError") and _within_time_limit( start_time ): # Retry the entire transaction. break raise # Commit succeeded. return ret def start_transaction( self, read_concern: Optional[ReadConcern] = None, write_concern: Optional[WriteConcern] = None, read_preference: Optional[_ServerMode] = None, max_commit_time_ms: Optional[int] = None, ) -> ContextManager: """Start a multi-statement transaction. Takes the same arguments as :class:`TransactionOptions`. .. versionchanged:: 3.9 Added the ``max_commit_time_ms`` option. .. versionadded:: 3.7 """ self._check_ended() if self.options.snapshot: raise InvalidOperation("Transactions are not supported in snapshot sessions") if self.in_transaction: raise InvalidOperation("Transaction already in progress") read_concern = self._inherit_option("read_concern", read_concern) write_concern = self._inherit_option("write_concern", write_concern) read_preference = self._inherit_option("read_preference", read_preference) if max_commit_time_ms is None: opts = self.options.default_transaction_options if opts: max_commit_time_ms = opts.max_commit_time_ms self._transaction.opts = TransactionOptions( read_concern, write_concern, read_preference, max_commit_time_ms ) self._transaction.reset() self._transaction.state = _TxnState.STARTING self._start_retryable_write() return _TransactionContext(self) def commit_transaction(self) -> None: """Commit a multi-statement transaction. .. versionadded:: 3.7 """ self._check_ended() state = self._transaction.state if state is _TxnState.NONE: raise InvalidOperation("No transaction started") elif state in (_TxnState.STARTING, _TxnState.COMMITTED_EMPTY): # Server transaction was never started, no need to send a command. self._transaction.state = _TxnState.COMMITTED_EMPTY return elif state is _TxnState.ABORTED: raise InvalidOperation("Cannot call commitTransaction after calling abortTransaction") elif state is _TxnState.COMMITTED: # We're explicitly retrying the commit, move the state back to # "in progress" so that in_transaction returns true. self._transaction.state = _TxnState.IN_PROGRESS try: self._finish_transaction_with_retry("commitTransaction") except ConnectionFailure as exc: # We do not know if the commit was successfully applied on the # server or if it satisfied the provided write concern, set the # unknown commit error label. exc._remove_error_label("TransientTransactionError") _reraise_with_unknown_commit(exc) except WTimeoutError as exc: # We do not know if the commit has satisfied the provided write # concern, add the unknown commit error label. _reraise_with_unknown_commit(exc) except OperationFailure as exc: if exc.code not in _UNKNOWN_COMMIT_ERROR_CODES: # The server reports errorLabels in the case. raise # We do not know if the commit was successfully applied on the # server or if it satisfied the provided write concern, set the # unknown commit error label. _reraise_with_unknown_commit(exc) finally: self._transaction.state = _TxnState.COMMITTED def abort_transaction(self) -> None: """Abort a multi-statement transaction. .. versionadded:: 3.7 """ self._check_ended() state = self._transaction.state if state is _TxnState.NONE: raise InvalidOperation("No transaction started") elif state is _TxnState.STARTING: # Server transaction was never started, no need to send a command. self._transaction.state = _TxnState.ABORTED return elif state is _TxnState.ABORTED: raise InvalidOperation("Cannot call abortTransaction twice") elif state in (_TxnState.COMMITTED, _TxnState.COMMITTED_EMPTY): raise InvalidOperation("Cannot call abortTransaction after calling commitTransaction") try: self._finish_transaction_with_retry("abortTransaction") except (OperationFailure, ConnectionFailure): # The transactions spec says to ignore abortTransaction errors. pass finally: self._transaction.state = _TxnState.ABORTED self._unpin() def _finish_transaction_with_retry(self, command_name: str) -> dict[str, Any]: """Run commit or abort with one retry after any retryable error. :param command_name: Either "commitTransaction" or "abortTransaction". """ def func( _session: Optional[ClientSession], conn: Connection, _retryable: bool ) -> dict[str, Any]: return self._finish_transaction(conn, command_name) return self._client._retry_internal(func, self, None, retryable=True, operation=_Op.ABORT) def _finish_transaction(self, conn: Connection, command_name: str) -> dict[str, Any]: self._transaction.attempt += 1 opts = self._transaction.opts assert opts wc = opts.write_concern cmd = {command_name: 1} if command_name == "commitTransaction": if opts.max_commit_time_ms and _csot.get_timeout() is None: cmd["maxTimeMS"] = opts.max_commit_time_ms # Transaction spec says that after the initial commit attempt, # subsequent commitTransaction commands should be upgraded to use # w:"majority" and set a default value of 10 seconds for wtimeout. if self._transaction.attempt > 1: assert wc wc_doc = wc.document wc_doc["w"] = "majority" wc_doc.setdefault("wtimeout", 10000) wc = WriteConcern(**wc_doc) if self._transaction.recovery_token: cmd["recoveryToken"] = self._transaction.recovery_token return self._client.admin._command( conn, cmd, session=self, write_concern=wc, parse_write_concern_error=True ) def _advance_cluster_time(self, cluster_time: Optional[Mapping[str, Any]]) -> None: """Internal cluster time helper.""" if self._cluster_time is None: self._cluster_time = cluster_time elif cluster_time is not None: if cluster_time["clusterTime"] > self._cluster_time["clusterTime"]: self._cluster_time = cluster_time def advance_cluster_time(self, cluster_time: Mapping[str, Any]) -> None: """Update the cluster time for this session. :param cluster_time: The :data:`~pymongo.client_session.ClientSession.cluster_time` from another `ClientSession` instance. """ if not isinstance(cluster_time, _Mapping): raise TypeError("cluster_time must be a subclass of collections.Mapping") if not isinstance(cluster_time.get("clusterTime"), Timestamp): raise ValueError("Invalid cluster_time") self._advance_cluster_time(cluster_time) def _advance_operation_time(self, operation_time: Optional[Timestamp]) -> None: """Internal operation time helper.""" if self._operation_time is None: self._operation_time = operation_time elif operation_time is not None: if operation_time > self._operation_time: self._operation_time = operation_time def advance_operation_time(self, operation_time: Timestamp) -> None: """Update the operation time for this session. :param operation_time: The :data:`~pymongo.client_session.ClientSession.operation_time` from another `ClientSession` instance. """ if not isinstance(operation_time, Timestamp): raise TypeError("operation_time must be an instance of bson.timestamp.Timestamp") self._advance_operation_time(operation_time) def _process_response(self, reply: Mapping[str, Any]) -> None: """Process a response to a command that was run with this session.""" self._advance_cluster_time(reply.get("$clusterTime")) self._advance_operation_time(reply.get("operationTime")) if self._options.snapshot and self._snapshot_time is None: if "cursor" in reply: ct = reply["cursor"].get("atClusterTime") else: ct = reply.get("atClusterTime") self._snapshot_time = ct if self.in_transaction and self._transaction.sharded: recovery_token = reply.get("recoveryToken") if recovery_token: self._transaction.recovery_token = recovery_token @property def has_ended(self) -> bool: """True if this session is finished.""" return self._server_session is None @property def in_transaction(self) -> bool: """True if this session has an active multi-statement transaction. .. versionadded:: 3.10 """ return self._transaction.active() @property def _starting_transaction(self) -> bool: """True if this session is starting a multi-statement transaction.""" return self._transaction.starting() @property def _pinned_address(self) -> Optional[_Address]: """The mongos address this transaction was created on.""" if self._transaction.active(): return self._transaction.pinned_address return None @property def _pinned_connection(self) -> Optional[Connection]: """The connection this transaction was started on.""" return self._transaction.pinned_conn def _pin(self, server: Server, conn: Connection) -> None: """Pin this session to the given Server or to the given connection.""" self._transaction.pin(server, conn) def _unpin(self) -> None: """Unpin this session from any pinned Server.""" self._transaction.unpin() def _txn_read_preference(self) -> Optional[_ServerMode]: """Return read preference of this transaction or None.""" if self.in_transaction: assert self._transaction.opts return self._transaction.opts.read_preference return None def _materialize(self, logical_session_timeout_minutes: Optional[int] = None) -> None: if isinstance(self._server_session, _EmptyServerSession): old = self._server_session self._server_session = self._client._topology.get_server_session( logical_session_timeout_minutes ) if old.started_retryable_write: self._server_session.inc_transaction_id() def _apply_to( self, command: MutableMapping[str, Any], is_retryable: bool, read_preference: _ServerMode, conn: Connection, ) -> None: if not conn.supports_sessions: if not self._implicit: raise ConfigurationError("Sessions are not supported by this MongoDB deployment") return self._check_ended() self._materialize(conn.logical_session_timeout_minutes) if self.options.snapshot: self._update_read_concern(command, conn) self._server_session.last_use = time.monotonic() command["lsid"] = self._server_session.session_id if is_retryable: command["txnNumber"] = self._server_session.transaction_id return if self.in_transaction: if read_preference != ReadPreference.PRIMARY: raise InvalidOperation( f"read preference in a transaction must be primary, not: {read_preference!r}" ) if self._transaction.state == _TxnState.STARTING: # First command begins a new transaction. self._transaction.state = _TxnState.IN_PROGRESS command["startTransaction"] = True assert self._transaction.opts if self._transaction.opts.read_concern: rc = self._transaction.opts.read_concern.document if rc: command["readConcern"] = rc self._update_read_concern(command, conn) command["txnNumber"] = self._server_session.transaction_id command["autocommit"] = False def _start_retryable_write(self) -> None: self._check_ended() self._server_session.inc_transaction_id() def _update_read_concern(self, cmd: MutableMapping[str, Any], conn: Connection) -> None: if self.options.causal_consistency and self.operation_time is not None: cmd.setdefault("readConcern", {})["afterClusterTime"] = self.operation_time if self.options.snapshot: if conn.max_wire_version < 13: raise ConfigurationError("Snapshot reads require MongoDB 5.0 or later") rc = cmd.setdefault("readConcern", {}) rc["level"] = "snapshot" if self._snapshot_time is not None: rc["atClusterTime"] = self._snapshot_time def __copy__(self) -> NoReturn: raise TypeError("A ClientSession cannot be copied, create a new session instead") class _EmptyServerSession: __slots__ = "dirty", "started_retryable_write" def __init__(self) -> None: self.dirty = False self.started_retryable_write = False def mark_dirty(self) -> None: self.dirty = True def inc_transaction_id(self) -> None: self.started_retryable_write = True class _ServerSession: def __init__(self, generation: int): # Ensure id is type 4, regardless of CodecOptions.uuid_representation. self.session_id = {"id": Binary(uuid.uuid4().bytes, 4)} self.last_use = time.monotonic() self._transaction_id = 0 self.dirty = False self.generation = generation def mark_dirty(self) -> None: """Mark this session as dirty. A server session is marked dirty when a command fails with a network error. Dirty sessions are later discarded from the server session pool. """ self.dirty = True def timed_out(self, session_timeout_minutes: Optional[int]) -> bool: if session_timeout_minutes is None: return False idle_seconds = time.monotonic() - self.last_use # Timed out if we have less than a minute to live. return idle_seconds > (session_timeout_minutes - 1) * 60 @property def transaction_id(self) -> Int64: """Positive 64-bit integer.""" return Int64(self._transaction_id) def inc_transaction_id(self) -> None: self._transaction_id += 1 class _ServerSessionPool(collections.deque): """Pool of _ServerSession objects. This class is not thread-safe, access it while holding the Topology lock. """ def __init__(self, *args: Any, **kwargs: Any): super().__init__(*args, **kwargs) self.generation = 0 def reset(self) -> None: self.generation += 1 self.clear() def pop_all(self) -> list[_ServerSession]: ids = [] while self: ids.append(self.pop().session_id) return ids def get_server_session(self, session_timeout_minutes: Optional[int]) -> _ServerSession: # Although the Driver Sessions Spec says we only clear stale sessions # in return_server_session, PyMongo can't take a lock when returning # sessions from a __del__ method (like in Cursor.__die), so it can't # clear stale sessions there. In case many sessions were returned via # __del__, check for stale sessions here too. self._clear_stale(session_timeout_minutes) # The most recently used sessions are on the left. while self: s = self.popleft() if not s.timed_out(session_timeout_minutes): return s return _ServerSession(self.generation) def return_server_session( self, server_session: _ServerSession, session_timeout_minutes: Optional[int] ) -> None: if session_timeout_minutes is not None: self._clear_stale(session_timeout_minutes) if server_session.timed_out(session_timeout_minutes): return self.return_server_session_no_lock(server_session) def return_server_session_no_lock(self, server_session: _ServerSession) -> None: # Discard sessions from an old pool to avoid duplicate sessions in the # child process after a fork. if server_session.generation == self.generation and not server_session.dirty: self.appendleft(server_session) def _clear_stale(self, session_timeout_minutes: Optional[int]) -> None: # Clear stale sessions. The least recently used are on the right. while self: if self[-1].timed_out(session_timeout_minutes): self.pop() else: # The remaining sessions also haven't timed out. break mongodb-mongo-python-driver-509e9b7/pymongo/collation.py000066400000000000000000000173411462766011000234710ustar00rootroot00000000000000# Copyright 2016 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. """Tools for working with `collations`_. .. _collations: https://www.mongodb.com/docs/manual/reference/collation/ """ from __future__ import annotations from typing import Any, Mapping, Optional, Union from pymongo import common from pymongo.write_concern import validate_boolean class CollationStrength: """ An enum that defines values for `strength` on a :class:`~pymongo.collation.Collation`. """ PRIMARY = 1 """Differentiate base (unadorned) characters.""" SECONDARY = 2 """Differentiate character accents.""" TERTIARY = 3 """Differentiate character case.""" QUATERNARY = 4 """Differentiate words with and without punctuation.""" IDENTICAL = 5 """Differentiate unicode code point (characters are exactly identical).""" class CollationAlternate: """ An enum that defines values for `alternate` on a :class:`~pymongo.collation.Collation`. """ NON_IGNORABLE = "non-ignorable" """Spaces and punctuation are treated as base characters.""" SHIFTED = "shifted" """Spaces and punctuation are *not* considered base characters. Spaces and punctuation are distinguished regardless when the :class:`~pymongo.collation.Collation` strength is at least :data:`~pymongo.collation.CollationStrength.QUATERNARY`. """ class CollationMaxVariable: """ An enum that defines values for `max_variable` on a :class:`~pymongo.collation.Collation`. """ PUNCT = "punct" """Both punctuation and spaces are ignored.""" SPACE = "space" """Spaces alone are ignored.""" class CollationCaseFirst: """ An enum that defines values for `case_first` on a :class:`~pymongo.collation.Collation`. """ UPPER = "upper" """Sort uppercase characters first.""" LOWER = "lower" """Sort lowercase characters first.""" OFF = "off" """Default for locale or collation strength.""" class Collation: """Collation :param locale: (string) The locale of the collation. This should be a string that identifies an `ICU locale ID` exactly. For example, ``en_US`` is valid, but ``en_us`` and ``en-US`` are not. Consult the MongoDB documentation for a list of supported locales. :param caseLevel: (optional) If ``True``, turn on case sensitivity if `strength` is 1 or 2 (case sensitivity is implied if `strength` is greater than 2). Defaults to ``False``. :param caseFirst: (optional) Specify that either uppercase or lowercase characters take precedence. Must be one of the following values: * :data:`~CollationCaseFirst.UPPER` * :data:`~CollationCaseFirst.LOWER` * :data:`~CollationCaseFirst.OFF` (the default) :param strength: Specify the comparison strength. This is also known as the ICU comparison level. This must be one of the following values: * :data:`~CollationStrength.PRIMARY` * :data:`~CollationStrength.SECONDARY` * :data:`~CollationStrength.TERTIARY` (the default) * :data:`~CollationStrength.QUATERNARY` * :data:`~CollationStrength.IDENTICAL` Each successive level builds upon the previous. For example, a `strength` of :data:`~CollationStrength.SECONDARY` differentiates characters based both on the unadorned base character and its accents. :param numericOrdering: If ``True``, order numbers numerically instead of in collation order (defaults to ``False``). :param alternate: Specify whether spaces and punctuation are considered base characters. This must be one of the following values: * :data:`~CollationAlternate.NON_IGNORABLE` (the default) * :data:`~CollationAlternate.SHIFTED` :param maxVariable: When `alternate` is :data:`~CollationAlternate.SHIFTED`, this option specifies what characters may be ignored. This must be one of the following values: * :data:`~CollationMaxVariable.PUNCT` (the default) * :data:`~CollationMaxVariable.SPACE` :param normalization: If ``True``, normalizes text into Unicode NFD. Defaults to ``False``. :param backwards: If ``True``, accents on characters are considered from the back of the word to the front, as it is done in some French dictionary ordering traditions. Defaults to ``False``. :param kwargs: Keyword arguments supplying any additional options to be sent with this Collation object. .. versionadded: 3.4 """ __slots__ = ("__document",) def __init__( self, locale: str, caseLevel: Optional[bool] = None, caseFirst: Optional[str] = None, strength: Optional[int] = None, numericOrdering: Optional[bool] = None, alternate: Optional[str] = None, maxVariable: Optional[str] = None, normalization: Optional[bool] = None, backwards: Optional[bool] = None, **kwargs: Any, ) -> None: locale = common.validate_string("locale", locale) self.__document: dict[str, Any] = {"locale": locale} if caseLevel is not None: self.__document["caseLevel"] = validate_boolean("caseLevel", caseLevel) if caseFirst is not None: self.__document["caseFirst"] = common.validate_string("caseFirst", caseFirst) if strength is not None: self.__document["strength"] = common.validate_integer("strength", strength) if numericOrdering is not None: self.__document["numericOrdering"] = validate_boolean( "numericOrdering", numericOrdering ) if alternate is not None: self.__document["alternate"] = common.validate_string("alternate", alternate) if maxVariable is not None: self.__document["maxVariable"] = common.validate_string("maxVariable", maxVariable) if normalization is not None: self.__document["normalization"] = validate_boolean("normalization", normalization) if backwards is not None: self.__document["backwards"] = validate_boolean("backwards", backwards) self.__document.update(kwargs) @property def document(self) -> dict[str, Any]: """The document representation of this collation. .. note:: :class:`Collation` is immutable. Mutating the value of :attr:`document` does not mutate this :class:`Collation`. """ return self.__document.copy() def __repr__(self) -> str: document = self.document return "Collation({})".format(", ".join(f"{key}={document[key]!r}" for key in document)) def __eq__(self, other: Any) -> bool: if isinstance(other, Collation): return self.document == other.document return NotImplemented def __ne__(self, other: Any) -> bool: return not self == other def validate_collation_or_none( value: Optional[Union[Mapping[str, Any], Collation]] ) -> Optional[dict[str, Any]]: if value is None: return None if isinstance(value, Collation): return value.document if isinstance(value, dict): return value raise TypeError("collation must be a dict, an instance of collation.Collation, or None.") mongodb-mongo-python-driver-509e9b7/pymongo/collection.py000066400000000000000000004222161462766011000236410ustar00rootroot00000000000000# Copyright 2009-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. """Collection level utilities for Mongo.""" from __future__ import annotations from collections import abc from typing import ( TYPE_CHECKING, Any, Callable, ContextManager, Generic, Iterable, Iterator, Mapping, MutableMapping, NoReturn, Optional, Sequence, Type, TypeVar, Union, cast, ) from bson.codec_options import DEFAULT_CODEC_OPTIONS, CodecOptions from bson.objectid import ObjectId from bson.raw_bson import RawBSONDocument from bson.son import SON from bson.timestamp import Timestamp from pymongo import ASCENDING, _csot, common, helpers, message from pymongo.aggregation import ( _CollectionAggregationCommand, _CollectionRawAggregationCommand, ) from pymongo.bulk import _Bulk from pymongo.change_stream import CollectionChangeStream from pymongo.collation import validate_collation_or_none from pymongo.command_cursor import CommandCursor, RawBatchCommandCursor from pymongo.common import _ecoc_coll_name, _esc_coll_name from pymongo.cursor import Cursor, RawBatchCursor from pymongo.errors import ( ConfigurationError, InvalidName, InvalidOperation, OperationFailure, ) from pymongo.helpers import _check_write_command_response from pymongo.message import _UNICODE_REPLACE_CODEC_OPTIONS from pymongo.operations import ( DeleteMany, DeleteOne, IndexModel, InsertOne, ReplaceOne, SearchIndexModel, UpdateMany, UpdateOne, _IndexKeyHint, _IndexList, _Op, ) from pymongo.read_concern import DEFAULT_READ_CONCERN, ReadConcern from pymongo.read_preferences import ReadPreference, _ServerMode from pymongo.results import ( BulkWriteResult, DeleteResult, InsertManyResult, InsertOneResult, UpdateResult, ) from pymongo.typings import _CollationIn, _DocumentType, _DocumentTypeArg, _Pipeline from pymongo.write_concern import DEFAULT_WRITE_CONCERN, WriteConcern, validate_boolean T = TypeVar("T") _FIND_AND_MODIFY_DOC_FIELDS = {"value": 1} _WriteOp = Union[ InsertOne[_DocumentType], DeleteOne, DeleteMany, ReplaceOne[_DocumentType], UpdateOne, UpdateMany, ] class ReturnDocument: """An enum used with :meth:`~pymongo.collection.Collection.find_one_and_replace` and :meth:`~pymongo.collection.Collection.find_one_and_update`. """ BEFORE = False """Return the original document before it was updated/replaced, or ``None`` if no document matches the query. """ AFTER = True """Return the updated/replaced or inserted document.""" if TYPE_CHECKING: from pymongo.aggregation import _AggregationCommand from pymongo.client_session import ClientSession from pymongo.collation import Collation from pymongo.database import Database from pymongo.pool import Connection from pymongo.server import Server class Collection(common.BaseObject, Generic[_DocumentType]): """A Mongo collection.""" def __init__( self, database: Database[_DocumentType], name: str, create: Optional[bool] = False, codec_options: Optional[CodecOptions[_DocumentTypeArg]] = None, read_preference: Optional[_ServerMode] = None, write_concern: Optional[WriteConcern] = None, read_concern: Optional[ReadConcern] = None, session: Optional[ClientSession] = None, **kwargs: Any, ) -> None: """Get / create a Mongo collection. Raises :class:`TypeError` if `name` is not an instance of :class:`str`. Raises :class:`~pymongo.errors.InvalidName` if `name` is not a valid collection name. Any additional keyword arguments will be used as options passed to the create command. See :meth:`~pymongo.database.Database.create_collection` for valid options. If `create` is ``True``, `collation` is specified, or any additional keyword arguments are present, a ``create`` command will be sent, using ``session`` if specified. Otherwise, a ``create`` command will not be sent and the collection will be created implicitly on first use. The optional ``session`` argument is *only* used for the ``create`` command, it is not associated with the collection afterward. :param database: the database to get a collection from :param name: the name of the collection to get :param create: if ``True``, force collection creation even without options being set :param codec_options: An instance of :class:`~bson.codec_options.CodecOptions`. If ``None`` (the default) database.codec_options is used. :param read_preference: The read preference to use. If ``None`` (the default) database.read_preference is used. :param write_concern: An instance of :class:`~pymongo.write_concern.WriteConcern`. If ``None`` (the default) database.write_concern is used. :param read_concern: An instance of :class:`~pymongo.read_concern.ReadConcern`. If ``None`` (the default) database.read_concern is used. :param collation: An instance of :class:`~pymongo.collation.Collation`. If a collation is provided, it will be passed to the create collection command. :param session: a :class:`~pymongo.client_session.ClientSession` that is used with the create collection command :param kwargs: additional keyword arguments will be passed as options for the create collection command .. versionchanged:: 4.2 Added the ``clusteredIndex`` and ``encryptedFields`` parameters. .. versionchanged:: 4.0 Removed the reindex, map_reduce, inline_map_reduce, parallel_scan, initialize_unordered_bulk_op, initialize_ordered_bulk_op, group, count, insert, save, update, remove, find_and_modify, and ensure_index methods. See the :ref:`pymongo4-migration-guide`. .. versionchanged:: 3.6 Added ``session`` parameter. .. versionchanged:: 3.4 Support the `collation` option. .. versionchanged:: 3.2 Added the read_concern option. .. versionchanged:: 3.0 Added the codec_options, read_preference, and write_concern options. Removed the uuid_subtype attribute. :class:`~pymongo.collection.Collection` no longer returns an instance of :class:`~pymongo.collection.Collection` for attribute names with leading underscores. You must use dict-style lookups instead:: collection['__my_collection__'] Not: collection.__my_collection__ .. seealso:: The MongoDB documentation on `collections `_. """ super().__init__( codec_options or database.codec_options, read_preference or database.read_preference, write_concern or database.write_concern, read_concern or database.read_concern, ) if not isinstance(name, str): raise TypeError("name must be an instance of str") if not name or ".." in name: raise InvalidName("collection names cannot be empty") if "$" in name and not (name.startswith(("oplog.$main", "$cmd"))): raise InvalidName("collection names must not contain '$': %r" % name) if name[0] == "." or name[-1] == ".": raise InvalidName("collection names must not start or end with '.': %r" % name) if "\x00" in name: raise InvalidName("collection names must not contain the null character") collation = validate_collation_or_none(kwargs.pop("collation", None)) self.__database: Database[_DocumentType] = database self.__name = name self.__full_name = f"{self.__database.name}.{self.__name}" self.__write_response_codec_options = self.codec_options._replace( unicode_decode_error_handler="replace", document_class=dict ) self._timeout = database.client.options.timeout encrypted_fields = kwargs.pop("encryptedFields", None) if create or kwargs or collation: if encrypted_fields: common.validate_is_mapping("encrypted_fields", encrypted_fields) opts = {"clusteredIndex": {"key": {"_id": 1}, "unique": True}} self.__create( _esc_coll_name(encrypted_fields, name), opts, None, session, qev2_required=True ) self.__create(_ecoc_coll_name(encrypted_fields, name), opts, None, session) self.__create(name, kwargs, collation, session, encrypted_fields=encrypted_fields) self.create_index([("__safeContent__", ASCENDING)], session) else: self.__create(name, kwargs, collation, session) def _conn_for_writes( self, session: Optional[ClientSession], operation: str ) -> ContextManager[Connection]: return self.__database.client._conn_for_writes(session, operation) def _command( self, conn: Connection, command: MutableMapping[str, Any], read_preference: Optional[_ServerMode] = None, codec_options: Optional[CodecOptions] = None, check: bool = True, allowable_errors: Optional[Sequence[Union[str, int]]] = None, read_concern: Optional[ReadConcern] = None, write_concern: Optional[WriteConcern] = None, collation: Optional[_CollationIn] = None, session: Optional[ClientSession] = None, retryable_write: bool = False, user_fields: Optional[Any] = None, ) -> Mapping[str, Any]: """Internal command helper. :param conn` - A Connection instance. :param command` - The command itself, as a :class:`~bson.son.SON` instance. :param read_preference` (optional) - The read preference to use. :param codec_options` (optional) - An instance of :class:`~bson.codec_options.CodecOptions`. :param check: raise OperationFailure if there are errors :param allowable_errors: errors to ignore if `check` is True :param read_concern` (optional) - An instance of :class:`~pymongo.read_concern.ReadConcern`. :param write_concern: An instance of :class:`~pymongo.write_concern.WriteConcern`. :param collation` (optional) - An instance of :class:`~pymongo.collation.Collation`. :param session: a :class:`~pymongo.client_session.ClientSession`. :param retryable_write: True if this command is a retryable write. :param user_fields: Response fields that should be decoded using the TypeDecoders from codec_options, passed to bson._decode_all_selective. :return: The result document. """ with self.__database.client._tmp_session(session) as s: return conn.command( self.__database.name, command, read_preference or self._read_preference_for(session), codec_options or self.codec_options, check, allowable_errors, read_concern=read_concern, write_concern=write_concern, parse_write_concern_error=True, collation=collation, session=s, client=self.__database.client, retryable_write=retryable_write, user_fields=user_fields, ) def __create( self, name: str, options: MutableMapping[str, Any], collation: Optional[_CollationIn], session: Optional[ClientSession], encrypted_fields: Optional[Mapping[str, Any]] = None, qev2_required: bool = False, ) -> None: """Sends a create command with the given options.""" cmd: dict[str, Any] = {"create": name} if encrypted_fields: cmd["encryptedFields"] = encrypted_fields if options: if "size" in options: options["size"] = float(options["size"]) cmd.update(options) with self._conn_for_writes(session, operation=_Op.CREATE) as conn: if qev2_required and conn.max_wire_version < 21: raise ConfigurationError( "Driver support of Queryable Encryption is incompatible with server. " "Upgrade server to use Queryable Encryption. " f"Got maxWireVersion {conn.max_wire_version} but need maxWireVersion >= 21 (MongoDB >=7.0)" ) self._command( conn, cmd, read_preference=ReadPreference.PRIMARY, write_concern=self._write_concern_for(session), collation=collation, session=session, ) def __getattr__(self, name: str) -> Collection[_DocumentType]: """Get a sub-collection of this collection by name. Raises InvalidName if an invalid collection name is used. :param name: the name of the collection to get """ if name.startswith("_"): full_name = f"{self.__name}.{name}" raise AttributeError( f"Collection has no attribute {name!r}. To access the {full_name}" f" collection, use database['{full_name}']." ) return self.__getitem__(name) def __getitem__(self, name: str) -> Collection[_DocumentType]: return Collection( self.__database, f"{self.__name}.{name}", False, self.codec_options, self.read_preference, self.write_concern, self.read_concern, ) def __repr__(self) -> str: return f"Collection({self.__database!r}, {self.__name!r})" def __eq__(self, other: Any) -> bool: if isinstance(other, Collection): return self.__database == other.database and self.__name == other.name return NotImplemented def __ne__(self, other: Any) -> bool: return not self == other def __hash__(self) -> int: return hash((self.__database, self.__name)) def __bool__(self) -> NoReturn: raise NotImplementedError( "Collection objects do not implement truth " "value testing or bool(). Please compare " "with None instead: collection is not None" ) @property def full_name(self) -> str: """The full name of this :class:`Collection`. The full name is of the form `database_name.collection_name`. """ return self.__full_name @property def name(self) -> str: """The name of this :class:`Collection`.""" return self.__name @property def database(self) -> Database[_DocumentType]: """The :class:`~pymongo.database.Database` that this :class:`Collection` is a part of. """ return self.__database def with_options( self, codec_options: Optional[CodecOptions[_DocumentTypeArg]] = None, read_preference: Optional[_ServerMode] = None, write_concern: Optional[WriteConcern] = None, read_concern: Optional[ReadConcern] = None, ) -> Collection[_DocumentType]: """Get a clone of this collection changing the specified settings. >>> coll1.read_preference Primary() >>> from pymongo import ReadPreference >>> coll2 = coll1.with_options(read_preference=ReadPreference.SECONDARY) >>> coll1.read_preference Primary() >>> coll2.read_preference Secondary(tag_sets=None) :param codec_options: An instance of :class:`~bson.codec_options.CodecOptions`. If ``None`` (the default) the :attr:`codec_options` of this :class:`Collection` is used. :param read_preference: The read preference to use. If ``None`` (the default) the :attr:`read_preference` of this :class:`Collection` is used. See :mod:`~pymongo.read_preferences` for options. :param write_concern: An instance of :class:`~pymongo.write_concern.WriteConcern`. If ``None`` (the default) the :attr:`write_concern` of this :class:`Collection` is used. :param read_concern: An instance of :class:`~pymongo.read_concern.ReadConcern`. If ``None`` (the default) the :attr:`read_concern` of this :class:`Collection` is used. """ return Collection( self.__database, self.__name, False, codec_options or self.codec_options, read_preference or self.read_preference, write_concern or self.write_concern, read_concern or self.read_concern, ) @_csot.apply def bulk_write( self, requests: Sequence[_WriteOp[_DocumentType]], ordered: bool = True, bypass_document_validation: bool = False, session: Optional[ClientSession] = None, comment: Optional[Any] = None, let: Optional[Mapping] = None, ) -> BulkWriteResult: """Send a batch of write operations to the server. Requests are passed as a list of write operation instances ( :class:`~pymongo.operations.InsertOne`, :class:`~pymongo.operations.UpdateOne`, :class:`~pymongo.operations.UpdateMany`, :class:`~pymongo.operations.ReplaceOne`, :class:`~pymongo.operations.DeleteOne`, or :class:`~pymongo.operations.DeleteMany`). >>> for doc in db.test.find({}): ... print(doc) ... {'x': 1, '_id': ObjectId('54f62e60fba5226811f634ef')} {'x': 1, '_id': ObjectId('54f62e60fba5226811f634f0')} >>> # DeleteMany, UpdateOne, and UpdateMany are also available. ... >>> from pymongo import InsertOne, DeleteOne, ReplaceOne >>> requests = [InsertOne({'y': 1}), DeleteOne({'x': 1}), ... ReplaceOne({'w': 1}, {'z': 1}, upsert=True)] >>> result = db.test.bulk_write(requests) >>> result.inserted_count 1 >>> result.deleted_count 1 >>> result.modified_count 0 >>> result.upserted_ids {2: ObjectId('54f62ee28891e756a6e1abd5')} >>> for doc in db.test.find({}): ... print(doc) ... {'x': 1, '_id': ObjectId('54f62e60fba5226811f634f0')} {'y': 1, '_id': ObjectId('54f62ee2fba5226811f634f1')} {'z': 1, '_id': ObjectId('54f62ee28891e756a6e1abd5')} :param requests: A list of write operations (see examples above). :param ordered: If ``True`` (the default) requests will be performed on the server serially, in the order provided. If an error occurs all remaining operations are aborted. If ``False`` requests will be performed on the server in arbitrary order, possibly in parallel, and all operations will be attempted. :param bypass_document_validation: (optional) If ``True``, allows the write to opt-out of document level validation. Default is ``False``. :param session: a :class:`~pymongo.client_session.ClientSession`. :param comment: A user-provided comment to attach to this command. :param let: Map of parameter names and values. Values must be constant or closed expressions that do not reference document fields. Parameters can then be accessed as variables in an aggregate expression context (e.g. "$$var"). :return: An instance of :class:`~pymongo.results.BulkWriteResult`. .. seealso:: :ref:`writes-and-ids` .. note:: `bypass_document_validation` requires server version **>= 3.2** .. versionchanged:: 4.1 Added ``comment`` parameter. Added ``let`` parameter. .. versionchanged:: 3.6 Added ``session`` parameter. .. versionchanged:: 3.2 Added bypass_document_validation support .. versionadded:: 3.0 """ common.validate_list("requests", requests) blk = _Bulk(self, ordered, bypass_document_validation, comment=comment, let=let) for request in requests: try: request._add_to_bulk(blk) except AttributeError: raise TypeError(f"{request!r} is not a valid request") from None write_concern = self._write_concern_for(session) bulk_api_result = blk.execute(write_concern, session, _Op.INSERT) if bulk_api_result is not None: return BulkWriteResult(bulk_api_result, True) return BulkWriteResult({}, False) def _insert_one( self, doc: Mapping[str, Any], ordered: bool, write_concern: WriteConcern, op_id: Optional[int], bypass_doc_val: bool, session: Optional[ClientSession], comment: Optional[Any] = None, ) -> Any: """Internal helper for inserting a single document.""" write_concern = write_concern or self.write_concern acknowledged = write_concern.acknowledged command = {"insert": self.name, "ordered": ordered, "documents": [doc]} if comment is not None: command["comment"] = comment def _insert_command( session: Optional[ClientSession], conn: Connection, retryable_write: bool ) -> None: if bypass_doc_val: command["bypassDocumentValidation"] = True result = conn.command( self.__database.name, command, write_concern=write_concern, codec_options=self.__write_response_codec_options, session=session, client=self.__database.client, retryable_write=retryable_write, ) _check_write_command_response(result) self.__database.client._retryable_write( acknowledged, _insert_command, session, operation=_Op.INSERT ) if not isinstance(doc, RawBSONDocument): return doc.get("_id") return None def insert_one( self, document: Union[_DocumentType, RawBSONDocument], bypass_document_validation: bool = False, session: Optional[ClientSession] = None, comment: Optional[Any] = None, ) -> InsertOneResult: """Insert a single document. >>> db.test.count_documents({'x': 1}) 0 >>> result = db.test.insert_one({'x': 1}) >>> result.inserted_id ObjectId('54f112defba522406c9cc208') >>> db.test.find_one({'x': 1}) {'x': 1, '_id': ObjectId('54f112defba522406c9cc208')} :param document: The document to insert. Must be a mutable mapping type. If the document does not have an _id field one will be added automatically. :param bypass_document_validation: (optional) If ``True``, allows the write to opt-out of document level validation. Default is ``False``. :param session: a :class:`~pymongo.client_session.ClientSession`. :param comment: A user-provided comment to attach to this command. :return: - An instance of :class:`~pymongo.results.InsertOneResult`. .. seealso:: :ref:`writes-and-ids` .. note:: `bypass_document_validation` requires server version **>= 3.2** .. versionchanged:: 4.1 Added ``comment`` parameter. .. versionchanged:: 3.6 Added ``session`` parameter. .. versionchanged:: 3.2 Added bypass_document_validation support .. versionadded:: 3.0 """ common.validate_is_document_type("document", document) if not (isinstance(document, RawBSONDocument) or "_id" in document): document["_id"] = ObjectId() # type: ignore[index] write_concern = self._write_concern_for(session) return InsertOneResult( self._insert_one( document, ordered=True, write_concern=write_concern, op_id=None, bypass_doc_val=bypass_document_validation, session=session, comment=comment, ), write_concern.acknowledged, ) @_csot.apply def insert_many( self, documents: Iterable[Union[_DocumentType, RawBSONDocument]], ordered: bool = True, bypass_document_validation: bool = False, session: Optional[ClientSession] = None, comment: Optional[Any] = None, ) -> InsertManyResult: """Insert an iterable of documents. >>> db.test.count_documents({}) 0 >>> result = db.test.insert_many([{'x': i} for i in range(2)]) >>> result.inserted_ids [ObjectId('54f113fffba522406c9cc20e'), ObjectId('54f113fffba522406c9cc20f')] >>> db.test.count_documents({}) 2 :param documents: A iterable of documents to insert. :param ordered: If ``True`` (the default) documents will be inserted on the server serially, in the order provided. If an error occurs all remaining inserts are aborted. If ``False``, documents will be inserted on the server in arbitrary order, possibly in parallel, and all document inserts will be attempted. :param bypass_document_validation: (optional) If ``True``, allows the write to opt-out of document level validation. Default is ``False``. :param session: a :class:`~pymongo.client_session.ClientSession`. :param comment: A user-provided comment to attach to this command. :return: An instance of :class:`~pymongo.results.InsertManyResult`. .. seealso:: :ref:`writes-and-ids` .. note:: `bypass_document_validation` requires server version **>= 3.2** .. versionchanged:: 4.1 Added ``comment`` parameter. .. versionchanged:: 3.6 Added ``session`` parameter. .. versionchanged:: 3.2 Added bypass_document_validation support .. versionadded:: 3.0 """ if ( not isinstance(documents, abc.Iterable) or isinstance(documents, abc.Mapping) or not documents ): raise TypeError("documents must be a non-empty list") inserted_ids: list[ObjectId] = [] def gen() -> Iterator[tuple[int, Mapping[str, Any]]]: """A generator that validates documents and handles _ids.""" for document in documents: common.validate_is_document_type("document", document) if not isinstance(document, RawBSONDocument): if "_id" not in document: document["_id"] = ObjectId() # type: ignore[index] inserted_ids.append(document["_id"]) yield (message._INSERT, document) write_concern = self._write_concern_for(session) blk = _Bulk(self, ordered, bypass_document_validation, comment=comment) blk.ops = list(gen()) blk.execute(write_concern, session, _Op.INSERT) return InsertManyResult(inserted_ids, write_concern.acknowledged) def _update( self, conn: Connection, criteria: Mapping[str, Any], document: Union[Mapping[str, Any], _Pipeline], upsert: bool = False, multi: bool = False, write_concern: Optional[WriteConcern] = None, op_id: Optional[int] = None, ordered: bool = True, bypass_doc_val: Optional[bool] = False, collation: Optional[_CollationIn] = None, array_filters: Optional[Sequence[Mapping[str, Any]]] = None, hint: Optional[_IndexKeyHint] = None, session: Optional[ClientSession] = None, retryable_write: bool = False, let: Optional[Mapping[str, Any]] = None, comment: Optional[Any] = None, ) -> Optional[Mapping[str, Any]]: """Internal update / replace helper.""" validate_boolean("upsert", upsert) collation = validate_collation_or_none(collation) write_concern = write_concern or self.write_concern acknowledged = write_concern.acknowledged update_doc: dict[str, Any] = { "q": criteria, "u": document, "multi": multi, "upsert": upsert, } if collation is not None: if not acknowledged: raise ConfigurationError("Collation is unsupported for unacknowledged writes.") else: update_doc["collation"] = collation if array_filters is not None: if not acknowledged: raise ConfigurationError("arrayFilters is unsupported for unacknowledged writes.") else: update_doc["arrayFilters"] = array_filters if hint is not None: if not acknowledged and conn.max_wire_version < 8: raise ConfigurationError( "Must be connected to MongoDB 4.2+ to use hint on unacknowledged update commands." ) if not isinstance(hint, str): hint = helpers._index_document(hint) update_doc["hint"] = hint command = {"update": self.name, "ordered": ordered, "updates": [update_doc]} if let is not None: common.validate_is_mapping("let", let) command["let"] = let if comment is not None: command["comment"] = comment # Update command. if bypass_doc_val: command["bypassDocumentValidation"] = True # The command result has to be published for APM unmodified # so we make a shallow copy here before adding updatedExisting. result = conn.command( self.__database.name, command, write_concern=write_concern, codec_options=self.__write_response_codec_options, session=session, client=self.__database.client, retryable_write=retryable_write, ).copy() _check_write_command_response(result) # Add the updatedExisting field for compatibility. if result.get("n") and "upserted" not in result: result["updatedExisting"] = True else: result["updatedExisting"] = False # MongoDB >= 2.6.0 returns the upsert _id in an array # element. Break it out for backward compatibility. if "upserted" in result: result["upserted"] = result["upserted"][0]["_id"] if not acknowledged: return None return result def _update_retryable( self, criteria: Mapping[str, Any], document: Union[Mapping[str, Any], _Pipeline], operation: str, upsert: bool = False, multi: bool = False, write_concern: Optional[WriteConcern] = None, op_id: Optional[int] = None, ordered: bool = True, bypass_doc_val: Optional[bool] = False, collation: Optional[_CollationIn] = None, array_filters: Optional[Sequence[Mapping[str, Any]]] = None, hint: Optional[_IndexKeyHint] = None, session: Optional[ClientSession] = None, let: Optional[Mapping[str, Any]] = None, comment: Optional[Any] = None, ) -> Optional[Mapping[str, Any]]: """Internal update / replace helper.""" def _update( session: Optional[ClientSession], conn: Connection, retryable_write: bool ) -> Optional[Mapping[str, Any]]: return self._update( conn, criteria, document, upsert=upsert, multi=multi, write_concern=write_concern, op_id=op_id, ordered=ordered, bypass_doc_val=bypass_doc_val, collation=collation, array_filters=array_filters, hint=hint, session=session, retryable_write=retryable_write, let=let, comment=comment, ) return self.__database.client._retryable_write( (write_concern or self.write_concern).acknowledged and not multi, _update, session, operation, ) def replace_one( self, filter: Mapping[str, Any], replacement: Mapping[str, Any], upsert: bool = False, bypass_document_validation: bool = False, collation: Optional[_CollationIn] = None, hint: Optional[_IndexKeyHint] = None, session: Optional[ClientSession] = None, let: Optional[Mapping[str, Any]] = None, comment: Optional[Any] = None, ) -> UpdateResult: """Replace a single document matching the filter. >>> for doc in db.test.find({}): ... print(doc) ... {'x': 1, '_id': ObjectId('54f4c5befba5220aa4d6dee7')} >>> result = db.test.replace_one({'x': 1}, {'y': 1}) >>> result.matched_count 1 >>> result.modified_count 1 >>> for doc in db.test.find({}): ... print(doc) ... {'y': 1, '_id': ObjectId('54f4c5befba5220aa4d6dee7')} The *upsert* option can be used to insert a new document if a matching document does not exist. >>> result = db.test.replace_one({'x': 1}, {'x': 1}, True) >>> result.matched_count 0 >>> result.modified_count 0 >>> result.upserted_id ObjectId('54f11e5c8891e756a6e1abd4') >>> db.test.find_one({'x': 1}) {'x': 1, '_id': ObjectId('54f11e5c8891e756a6e1abd4')} :param filter: A query that matches the document to replace. :param replacement: The new document. :param upsert: If ``True``, perform an insert if no documents match the filter. :param bypass_document_validation: (optional) If ``True``, allows the write to opt-out of document level validation. Default is ``False``. :param collation: An instance of :class:`~pymongo.collation.Collation`. :param hint: An index to use to support the query predicate specified either by its string name, or in the same format as passed to :meth:`~pymongo.collection.Collection.create_index` (e.g. ``[('field', ASCENDING)]``). This option is only supported on MongoDB 4.2 and above. :param session: a :class:`~pymongo.client_session.ClientSession`. :param let: Map of parameter names and values. Values must be constant or closed expressions that do not reference document fields. Parameters can then be accessed as variables in an aggregate expression context (e.g. "$$var"). :param comment: A user-provided comment to attach to this command. :return: - An instance of :class:`~pymongo.results.UpdateResult`. .. versionchanged:: 4.1 Added ``let`` parameter. Added ``comment`` parameter. .. versionchanged:: 3.11 Added ``hint`` parameter. .. versionchanged:: 3.6 Added ``session`` parameter. .. versionchanged:: 3.4 Added the `collation` option. .. versionchanged:: 3.2 Added bypass_document_validation support. .. versionadded:: 3.0 """ common.validate_is_mapping("filter", filter) common.validate_ok_for_replace(replacement) if let is not None: common.validate_is_mapping("let", let) write_concern = self._write_concern_for(session) return UpdateResult( self._update_retryable( filter, replacement, _Op.UPDATE, upsert, write_concern=write_concern, bypass_doc_val=bypass_document_validation, collation=collation, hint=hint, session=session, let=let, comment=comment, ), write_concern.acknowledged, ) def update_one( self, filter: Mapping[str, Any], update: Union[Mapping[str, Any], _Pipeline], upsert: bool = False, bypass_document_validation: bool = False, collation: Optional[_CollationIn] = None, array_filters: Optional[Sequence[Mapping[str, Any]]] = None, hint: Optional[_IndexKeyHint] = None, session: Optional[ClientSession] = None, let: Optional[Mapping[str, Any]] = None, comment: Optional[Any] = None, ) -> UpdateResult: """Update a single document matching the filter. >>> for doc in db.test.find(): ... print(doc) ... {'x': 1, '_id': 0} {'x': 1, '_id': 1} {'x': 1, '_id': 2} >>> result = db.test.update_one({'x': 1}, {'$inc': {'x': 3}}) >>> result.matched_count 1 >>> result.modified_count 1 >>> for doc in db.test.find(): ... print(doc) ... {'x': 4, '_id': 0} {'x': 1, '_id': 1} {'x': 1, '_id': 2} If ``upsert=True`` and no documents match the filter, create a new document based on the filter criteria and update modifications. >>> result = db.test.update_one({'x': -10}, {'$inc': {'x': 3}}, upsert=True) >>> result.matched_count 0 >>> result.modified_count 0 >>> result.upserted_id ObjectId('626a678eeaa80587d4bb3fb7') >>> db.test.find_one(result.upserted_id) {'_id': ObjectId('626a678eeaa80587d4bb3fb7'), 'x': -7} :param filter: A query that matches the document to update. :param update: The modifications to apply. :param upsert: If ``True``, perform an insert if no documents match the filter. :param bypass_document_validation: (optional) If ``True``, allows the write to opt-out of document level validation. Default is ``False``. :param collation: An instance of :class:`~pymongo.collation.Collation`. :param array_filters: A list of filters specifying which array elements an update should apply. :param hint: An index to use to support the query predicate specified either by its string name, or in the same format as passed to :meth:`~pymongo.collection.Collection.create_index` (e.g. ``[('field', ASCENDING)]``). This option is only supported on MongoDB 4.2 and above. :param session: a :class:`~pymongo.client_session.ClientSession`. :param let: Map of parameter names and values. Values must be constant or closed expressions that do not reference document fields. Parameters can then be accessed as variables in an aggregate expression context (e.g. "$$var"). :param comment: A user-provided comment to attach to this command. :return: - An instance of :class:`~pymongo.results.UpdateResult`. .. versionchanged:: 4.1 Added ``let`` parameter. Added ``comment`` parameter. .. versionchanged:: 3.11 Added ``hint`` parameter. .. versionchanged:: 3.9 Added the ability to accept a pipeline as the ``update``. .. versionchanged:: 3.6 Added the ``array_filters`` and ``session`` parameters. .. versionchanged:: 3.4 Added the ``collation`` option. .. versionchanged:: 3.2 Added ``bypass_document_validation`` support. .. versionadded:: 3.0 """ common.validate_is_mapping("filter", filter) common.validate_ok_for_update(update) common.validate_list_or_none("array_filters", array_filters) write_concern = self._write_concern_for(session) return UpdateResult( self._update_retryable( filter, update, _Op.UPDATE, upsert, write_concern=write_concern, bypass_doc_val=bypass_document_validation, collation=collation, array_filters=array_filters, hint=hint, session=session, let=let, comment=comment, ), write_concern.acknowledged, ) def update_many( self, filter: Mapping[str, Any], update: Union[Mapping[str, Any], _Pipeline], upsert: bool = False, array_filters: Optional[Sequence[Mapping[str, Any]]] = None, bypass_document_validation: Optional[bool] = None, collation: Optional[_CollationIn] = None, hint: Optional[_IndexKeyHint] = None, session: Optional[ClientSession] = None, let: Optional[Mapping[str, Any]] = None, comment: Optional[Any] = None, ) -> UpdateResult: """Update one or more documents that match the filter. >>> for doc in db.test.find(): ... print(doc) ... {'x': 1, '_id': 0} {'x': 1, '_id': 1} {'x': 1, '_id': 2} >>> result = db.test.update_many({'x': 1}, {'$inc': {'x': 3}}) >>> result.matched_count 3 >>> result.modified_count 3 >>> for doc in db.test.find(): ... print(doc) ... {'x': 4, '_id': 0} {'x': 4, '_id': 1} {'x': 4, '_id': 2} :param filter: A query that matches the documents to update. :param update: The modifications to apply. :param upsert: If ``True``, perform an insert if no documents match the filter. :param bypass_document_validation: If ``True``, allows the write to opt-out of document level validation. Default is ``False``. :param collation: An instance of :class:`~pymongo.collation.Collation`. :param array_filters: A list of filters specifying which array elements an update should apply. :param hint: An index to use to support the query predicate specified either by its string name, or in the same format as passed to :meth:`~pymongo.collection.Collection.create_index` (e.g. ``[('field', ASCENDING)]``). This option is only supported on MongoDB 4.2 and above. :param session: a :class:`~pymongo.client_session.ClientSession`. :param let: Map of parameter names and values. Values must be constant or closed expressions that do not reference document fields. Parameters can then be accessed as variables in an aggregate expression context (e.g. "$$var"). :param comment: A user-provided comment to attach to this command. :return: - An instance of :class:`~pymongo.results.UpdateResult`. .. versionchanged:: 4.1 Added ``let`` parameter. Added ``comment`` parameter. .. versionchanged:: 3.11 Added ``hint`` parameter. .. versionchanged:: 3.9 Added the ability to accept a pipeline as the `update`. .. versionchanged:: 3.6 Added ``array_filters`` and ``session`` parameters. .. versionchanged:: 3.4 Added the `collation` option. .. versionchanged:: 3.2 Added bypass_document_validation support. .. versionadded:: 3.0 """ common.validate_is_mapping("filter", filter) common.validate_ok_for_update(update) common.validate_list_or_none("array_filters", array_filters) write_concern = self._write_concern_for(session) return UpdateResult( self._update_retryable( filter, update, _Op.UPDATE, upsert, multi=True, write_concern=write_concern, bypass_doc_val=bypass_document_validation, collation=collation, array_filters=array_filters, hint=hint, session=session, let=let, comment=comment, ), write_concern.acknowledged, ) def drop( self, session: Optional[ClientSession] = None, comment: Optional[Any] = None, encrypted_fields: Optional[Mapping[str, Any]] = None, ) -> None: """Alias for :meth:`~pymongo.database.Database.drop_collection`. :param session: a :class:`~pymongo.client_session.ClientSession`. :param comment: A user-provided comment to attach to this command. :param encrypted_fields: **(BETA)** Document that describes the encrypted fields for Queryable Encryption. The following two calls are equivalent: >>> db.foo.drop() >>> db.drop_collection("foo") .. versionchanged:: 4.2 Added ``encrypted_fields`` parameter. .. versionchanged:: 4.1 Added ``comment`` parameter. .. versionchanged:: 3.7 :meth:`drop` now respects this :class:`Collection`'s :attr:`write_concern`. .. versionchanged:: 3.6 Added ``session`` parameter. """ dbo = self.__database.client.get_database( self.__database.name, self.codec_options, self.read_preference, self.write_concern, self.read_concern, ) dbo.drop_collection( self.__name, session=session, comment=comment, encrypted_fields=encrypted_fields ) def _delete( self, conn: Connection, criteria: Mapping[str, Any], multi: bool, write_concern: Optional[WriteConcern] = None, op_id: Optional[int] = None, ordered: bool = True, collation: Optional[_CollationIn] = None, hint: Optional[_IndexKeyHint] = None, session: Optional[ClientSession] = None, retryable_write: bool = False, let: Optional[Mapping[str, Any]] = None, comment: Optional[Any] = None, ) -> Mapping[str, Any]: """Internal delete helper.""" common.validate_is_mapping("filter", criteria) write_concern = write_concern or self.write_concern acknowledged = write_concern.acknowledged delete_doc = {"q": criteria, "limit": int(not multi)} collation = validate_collation_or_none(collation) if collation is not None: if not acknowledged: raise ConfigurationError("Collation is unsupported for unacknowledged writes.") else: delete_doc["collation"] = collation if hint is not None: if not acknowledged and conn.max_wire_version < 9: raise ConfigurationError( "Must be connected to MongoDB 4.4+ to use hint on unacknowledged delete commands." ) if not isinstance(hint, str): hint = helpers._index_document(hint) delete_doc["hint"] = hint command = {"delete": self.name, "ordered": ordered, "deletes": [delete_doc]} if let is not None: common.validate_is_document_type("let", let) command["let"] = let if comment is not None: command["comment"] = comment # Delete command. result = conn.command( self.__database.name, command, write_concern=write_concern, codec_options=self.__write_response_codec_options, session=session, client=self.__database.client, retryable_write=retryable_write, ) _check_write_command_response(result) return result def _delete_retryable( self, criteria: Mapping[str, Any], multi: bool, write_concern: Optional[WriteConcern] = None, op_id: Optional[int] = None, ordered: bool = True, collation: Optional[_CollationIn] = None, hint: Optional[_IndexKeyHint] = None, session: Optional[ClientSession] = None, let: Optional[Mapping[str, Any]] = None, comment: Optional[Any] = None, ) -> Mapping[str, Any]: """Internal delete helper.""" def _delete( session: Optional[ClientSession], conn: Connection, retryable_write: bool ) -> Mapping[str, Any]: return self._delete( conn, criteria, multi, write_concern=write_concern, op_id=op_id, ordered=ordered, collation=collation, hint=hint, session=session, retryable_write=retryable_write, let=let, comment=comment, ) return self.__database.client._retryable_write( (write_concern or self.write_concern).acknowledged and not multi, _delete, session, operation=_Op.DELETE, ) def delete_one( self, filter: Mapping[str, Any], collation: Optional[_CollationIn] = None, hint: Optional[_IndexKeyHint] = None, session: Optional[ClientSession] = None, let: Optional[Mapping[str, Any]] = None, comment: Optional[Any] = None, ) -> DeleteResult: """Delete a single document matching the filter. >>> db.test.count_documents({'x': 1}) 3 >>> result = db.test.delete_one({'x': 1}) >>> result.deleted_count 1 >>> db.test.count_documents({'x': 1}) 2 :param filter: A query that matches the document to delete. :param collation: An instance of :class:`~pymongo.collation.Collation`. :param hint: An index to use to support the query predicate specified either by its string name, or in the same format as passed to :meth:`~pymongo.collection.Collection.create_index` (e.g. ``[('field', ASCENDING)]``). This option is only supported on MongoDB 4.4 and above. :param session: a :class:`~pymongo.client_session.ClientSession`. :param let: Map of parameter names and values. Values must be constant or closed expressions that do not reference document fields. Parameters can then be accessed as variables in an aggregate expression context (e.g. "$$var"). :param comment: A user-provided comment to attach to this command. :return: - An instance of :class:`~pymongo.results.DeleteResult`. .. versionchanged:: 4.1 Added ``let`` parameter. Added ``comment`` parameter. .. versionchanged:: 3.11 Added ``hint`` parameter. .. versionchanged:: 3.6 Added ``session`` parameter. .. versionchanged:: 3.4 Added the `collation` option. .. versionadded:: 3.0 """ write_concern = self._write_concern_for(session) return DeleteResult( self._delete_retryable( filter, False, write_concern=write_concern, collation=collation, hint=hint, session=session, let=let, comment=comment, ), write_concern.acknowledged, ) def delete_many( self, filter: Mapping[str, Any], collation: Optional[_CollationIn] = None, hint: Optional[_IndexKeyHint] = None, session: Optional[ClientSession] = None, let: Optional[Mapping[str, Any]] = None, comment: Optional[Any] = None, ) -> DeleteResult: """Delete one or more documents matching the filter. >>> db.test.count_documents({'x': 1}) 3 >>> result = db.test.delete_many({'x': 1}) >>> result.deleted_count 3 >>> db.test.count_documents({'x': 1}) 0 :param filter: A query that matches the documents to delete. :param collation: An instance of :class:`~pymongo.collation.Collation`. :param hint: An index to use to support the query predicate specified either by its string name, or in the same format as passed to :meth:`~pymongo.collection.Collection.create_index` (e.g. ``[('field', ASCENDING)]``). This option is only supported on MongoDB 4.4 and above. :param session: a :class:`~pymongo.client_session.ClientSession`. :param let: Map of parameter names and values. Values must be constant or closed expressions that do not reference document fields. Parameters can then be accessed as variables in an aggregate expression context (e.g. "$$var"). :param comment: A user-provided comment to attach to this command. :return: - An instance of :class:`~pymongo.results.DeleteResult`. .. versionchanged:: 4.1 Added ``let`` parameter. Added ``comment`` parameter. .. versionchanged:: 3.11 Added ``hint`` parameter. .. versionchanged:: 3.6 Added ``session`` parameter. .. versionchanged:: 3.4 Added the `collation` option. .. versionadded:: 3.0 """ write_concern = self._write_concern_for(session) return DeleteResult( self._delete_retryable( filter, True, write_concern=write_concern, collation=collation, hint=hint, session=session, let=let, comment=comment, ), write_concern.acknowledged, ) def find_one( self, filter: Optional[Any] = None, *args: Any, **kwargs: Any ) -> Optional[_DocumentType]: """Get a single document from the database. All arguments to :meth:`find` are also valid arguments for :meth:`find_one`, although any `limit` argument will be ignored. Returns a single document, or ``None`` if no matching document is found. The :meth:`find_one` method obeys the :attr:`read_preference` of this :class:`Collection`. :param filter: a dictionary specifying the query to be performed OR any other type to be used as the value for a query for ``"_id"``. :param args: any additional positional arguments are the same as the arguments to :meth:`find`. :param kwargs: any additional keyword arguments are the same as the arguments to :meth:`find`. :: code-block: python >>> collection.find_one(max_time_ms=100) """ if filter is not None and not isinstance(filter, abc.Mapping): filter = {"_id": filter} cursor = self.find(filter, *args, **kwargs) for result in cursor.limit(-1): return result return None def find(self, *args: Any, **kwargs: Any) -> Cursor[_DocumentType]: """Query the database. The `filter` argument is a query document that all results must match. For example: >>> db.test.find({"hello": "world"}) only matches documents that have a key "hello" with value "world". Matches can have other keys *in addition* to "hello". The `projection` argument is used to specify a subset of fields that should be included in the result documents. By limiting results to a certain subset of fields you can cut down on network traffic and decoding time. Raises :class:`TypeError` if any of the arguments are of improper type. Returns an instance of :class:`~pymongo.cursor.Cursor` corresponding to this query. The :meth:`find` method obeys the :attr:`read_preference` of this :class:`Collection`. :param filter: A query document that selects which documents to include in the result set. Can be an empty document to include all documents. :param projection: a list of field names that should be returned in the result set or a dict specifying the fields to include or exclude. If `projection` is a list "_id" will always be returned. Use a dict to exclude fields from the result (e.g. projection={'_id': False}). :param session: a :class:`~pymongo.client_session.ClientSession`. :param skip: the number of documents to omit (from the start of the result set) when returning the results :param limit: the maximum number of results to return. A limit of 0 (the default) is equivalent to setting no limit. :param no_cursor_timeout: if False (the default), any returned cursor is closed by the server after 10 minutes of inactivity. If set to True, the returned cursor will never time out on the server. Care should be taken to ensure that cursors with no_cursor_timeout turned on are properly closed. :param cursor_type: the type of cursor to return. The valid options are defined by :class:`~pymongo.cursor.CursorType`: - :attr:`~pymongo.cursor.CursorType.NON_TAILABLE` - the result of this find call will return a standard cursor over the result set. - :attr:`~pymongo.cursor.CursorType.TAILABLE` - the result of this find call will be a tailable cursor - tailable cursors are only for use with capped collections. They are not closed when the last data is retrieved but are kept open and the cursor location marks the final document position. If more data is received iteration of the cursor will continue from the last document received. For details, see the `tailable cursor documentation `_. - :attr:`~pymongo.cursor.CursorType.TAILABLE_AWAIT` - the result of this find call will be a tailable cursor with the await flag set. The server will wait for a few seconds after returning the full result set so that it can capture and return additional data added during the query. - :attr:`~pymongo.cursor.CursorType.EXHAUST` - the result of this find call will be an exhaust cursor. MongoDB will stream batched results to the client without waiting for the client to request each batch, reducing latency. See notes on compatibility below. :param sort: a list of (key, direction) pairs specifying the sort order for this query. See :meth:`~pymongo.cursor.Cursor.sort` for details. :param allow_partial_results: if True, mongos will return partial results if some shards are down instead of returning an error. :param oplog_replay: **DEPRECATED** - if True, set the oplogReplay query flag. Default: False. :param batch_size: Limits the number of documents returned in a single batch. :param collation: An instance of :class:`~pymongo.collation.Collation`. :param return_key: If True, return only the index keys in each document. :param show_record_id: If True, adds a field ``$recordId`` in each document with the storage engine's internal record identifier. :param snapshot: **DEPRECATED** - If True, prevents the cursor from returning a document more than once because of an intervening write operation. :param hint: An index, in the same format as passed to :meth:`~pymongo.collection.Collection.create_index` (e.g. ``[('field', ASCENDING)]``). Pass this as an alternative to calling :meth:`~pymongo.cursor.Cursor.hint` on the cursor to tell Mongo the proper index to use for the query. :param max_time_ms: Specifies a time limit for a query operation. If the specified time is exceeded, the operation will be aborted and :exc:`~pymongo.errors.ExecutionTimeout` is raised. Pass this as an alternative to calling :meth:`~pymongo.cursor.Cursor.max_time_ms` on the cursor. :param max_scan: **DEPRECATED** - The maximum number of documents to scan. Pass this as an alternative to calling :meth:`~pymongo.cursor.Cursor.max_scan` on the cursor. :param min: A list of field, limit pairs specifying the inclusive lower bound for all keys of a specific index in order. Pass this as an alternative to calling :meth:`~pymongo.cursor.Cursor.min` on the cursor. ``hint`` must also be passed to ensure the query utilizes the correct index. :param max: A list of field, limit pairs specifying the exclusive upper bound for all keys of a specific index in order. Pass this as an alternative to calling :meth:`~pymongo.cursor.Cursor.max` on the cursor. ``hint`` must also be passed to ensure the query utilizes the correct index. :param comment: A string to attach to the query to help interpret and trace the operation in the server logs and in profile data. Pass this as an alternative to calling :meth:`~pymongo.cursor.Cursor.comment` on the cursor. :param allow_disk_use: if True, MongoDB may use temporary disk files to store data exceeding the system memory limit while processing a blocking sort operation. The option has no effect if MongoDB can satisfy the specified sort using an index, or if the blocking sort requires less memory than the 100 MiB limit. This option is only supported on MongoDB 4.4 and above. .. note:: There are a number of caveats to using :attr:`~pymongo.cursor.CursorType.EXHAUST` as cursor_type: - The `limit` option can not be used with an exhaust cursor. - Exhaust cursors are not supported by mongos and can not be used with a sharded cluster. - A :class:`~pymongo.cursor.Cursor` instance created with the :attr:`~pymongo.cursor.CursorType.EXHAUST` cursor_type requires an exclusive :class:`~socket.socket` connection to MongoDB. If the :class:`~pymongo.cursor.Cursor` is discarded without being completely iterated the underlying :class:`~socket.socket` connection will be closed and discarded without being returned to the connection pool. .. versionchanged:: 4.0 Removed the ``modifiers`` option. Empty projections (eg {} or []) are passed to the server as-is, rather than the previous behavior which substituted in a projection of ``{"_id": 1}``. This means that an empty projection will now return the entire document, not just the ``"_id"`` field. .. versionchanged:: 3.11 Added the ``allow_disk_use`` option. Deprecated the ``oplog_replay`` option. Support for this option is deprecated in MongoDB 4.4. The query engine now automatically optimizes queries against the oplog without requiring this option to be set. .. versionchanged:: 3.7 Deprecated the ``snapshot`` option, which is deprecated in MongoDB 3.6 and removed in MongoDB 4.0. Deprecated the ``max_scan`` option. Support for this option is deprecated in MongoDB 4.0. Use ``max_time_ms`` instead to limit server-side execution time. .. versionchanged:: 3.6 Added ``session`` parameter. .. versionchanged:: 3.5 Added the options ``return_key``, ``show_record_id``, ``snapshot``, ``hint``, ``max_time_ms``, ``max_scan``, ``min``, ``max``, and ``comment``. Deprecated the ``modifiers`` option. .. versionchanged:: 3.4 Added support for the ``collation`` option. .. versionchanged:: 3.0 Changed the parameter names ``spec``, ``fields``, ``timeout``, and ``partial`` to ``filter``, ``projection``, ``no_cursor_timeout``, and ``allow_partial_results`` respectively. Added the ``cursor_type``, ``oplog_replay``, and ``modifiers`` options. Removed the ``network_timeout``, ``read_preference``, ``tag_sets``, ``secondary_acceptable_latency_ms``, ``max_scan``, ``snapshot``, ``tailable``, ``await_data``, ``exhaust``, ``as_class``, and slave_okay parameters. Removed ``compile_re`` option: PyMongo now always represents BSON regular expressions as :class:`~bson.regex.Regex` objects. Use :meth:`~bson.regex.Regex.try_compile` to attempt to convert from a BSON regular expression to a Python regular expression object. Soft deprecated the ``manipulate`` option. .. seealso:: The MongoDB documentation on `find `_. """ return Cursor(self, *args, **kwargs) def find_raw_batches(self, *args: Any, **kwargs: Any) -> RawBatchCursor[_DocumentType]: """Query the database and retrieve batches of raw BSON. Similar to the :meth:`find` method but returns a :class:`~pymongo.cursor.RawBatchCursor`. This example demonstrates how to work with raw batches, but in practice raw batches should be passed to an external library that can decode BSON into another data type, rather than used with PyMongo's :mod:`bson` module. >>> import bson >>> cursor = db.test.find_raw_batches() >>> for batch in cursor: ... print(bson.decode_all(batch)) .. note:: find_raw_batches does not support auto encryption. .. versionchanged:: 3.12 Instead of ignoring the user-specified read concern, this method now sends it to the server when connected to MongoDB 3.6+. Added session support. .. versionadded:: 3.6 """ # OP_MSG is required to support encryption. if self.__database.client._encrypter: raise InvalidOperation("find_raw_batches does not support auto encryption") return RawBatchCursor(self, *args, **kwargs) def _count_cmd( self, session: Optional[ClientSession], conn: Connection, read_preference: Optional[_ServerMode], cmd: dict[str, Any], collation: Optional[Collation], ) -> int: """Internal count command helper.""" # XXX: "ns missing" checks can be removed when we drop support for # MongoDB 3.0, see SERVER-17051. res = self._command( conn, cmd, read_preference=read_preference, allowable_errors=["ns missing"], codec_options=self.__write_response_codec_options, read_concern=self.read_concern, collation=collation, session=session, ) if res.get("errmsg", "") == "ns missing": return 0 return int(res["n"]) def _aggregate_one_result( self, conn: Connection, read_preference: Optional[_ServerMode], cmd: dict[str, Any], collation: Optional[_CollationIn], session: Optional[ClientSession], ) -> Optional[Mapping[str, Any]]: """Internal helper to run an aggregate that returns a single result.""" result = self._command( conn, cmd, read_preference, allowable_errors=[26], # Ignore NamespaceNotFound. codec_options=self.__write_response_codec_options, read_concern=self.read_concern, collation=collation, session=session, ) # cursor will not be present for NamespaceNotFound errors. if "cursor" not in result: return None batch = result["cursor"]["firstBatch"] return batch[0] if batch else None def estimated_document_count(self, comment: Optional[Any] = None, **kwargs: Any) -> int: """Get an estimate of the number of documents in this collection using collection metadata. The :meth:`estimated_document_count` method is **not** supported in a transaction. All optional parameters should be passed as keyword arguments to this method. Valid options include: - `maxTimeMS` (int): The maximum amount of time to allow this operation to run, in milliseconds. :param comment: A user-provided comment to attach to this command. :param kwargs: See list of options above. .. versionchanged:: 4.2 This method now always uses the `count`_ command. Due to an oversight in versions 5.0.0-5.0.8 of MongoDB, the count command was not included in V1 of the :ref:`versioned-api-ref`. Users of the Stable API with estimated_document_count are recommended to upgrade their server version to 5.0.9+ or set :attr:`pymongo.server_api.ServerApi.strict` to ``False`` to avoid encountering errors. .. versionadded:: 3.7 .. _count: https://mongodb.com/docs/manual/reference/command/count/ """ if "session" in kwargs: raise ConfigurationError("estimated_document_count does not support sessions") if comment is not None: kwargs["comment"] = comment def _cmd( session: Optional[ClientSession], _server: Server, conn: Connection, read_preference: Optional[_ServerMode], ) -> int: cmd: dict[str, Any] = {"count": self.__name} cmd.update(kwargs) return self._count_cmd(session, conn, read_preference, cmd, collation=None) return self._retryable_non_cursor_read(_cmd, None, operation=_Op.COUNT) def count_documents( self, filter: Mapping[str, Any], session: Optional[ClientSession] = None, comment: Optional[Any] = None, **kwargs: Any, ) -> int: """Count the number of documents in this collection. .. note:: For a fast count of the total documents in a collection see :meth:`estimated_document_count`. The :meth:`count_documents` method is supported in a transaction. All optional parameters should be passed as keyword arguments to this method. Valid options include: - `skip` (int): The number of matching documents to skip before returning results. - `limit` (int): The maximum number of documents to count. Must be a positive integer. If not provided, no limit is imposed. - `maxTimeMS` (int): The maximum amount of time to allow this operation to run, in milliseconds. - `collation` (optional): An instance of :class:`~pymongo.collation.Collation`. - `hint` (string or list of tuples): The index to use. Specify either the index name as a string or the index specification as a list of tuples (e.g. [('a', pymongo.ASCENDING), ('b', pymongo.ASCENDING)]). The :meth:`count_documents` method obeys the :attr:`read_preference` of this :class:`Collection`. .. note:: When migrating from :meth:`count` to :meth:`count_documents` the following query operators must be replaced: +-------------+-------------------------------------+ | Operator | Replacement | +=============+=====================================+ | $where | `$expr`_ | +-------------+-------------------------------------+ | $near | `$geoWithin`_ with `$center`_ | +-------------+-------------------------------------+ | $nearSphere | `$geoWithin`_ with `$centerSphere`_ | +-------------+-------------------------------------+ :param filter: A query document that selects which documents to count in the collection. Can be an empty document to count all documents. :param session: a :class:`~pymongo.client_session.ClientSession`. :param comment: A user-provided comment to attach to this command. :param kwargs: See list of options above. .. versionadded:: 3.7 .. _$expr: https://mongodb.com/docs/manual/reference/operator/query/expr/ .. _$geoWithin: https://mongodb.com/docs/manual/reference/operator/query/geoWithin/ .. _$center: https://mongodb.com/docs/manual/reference/operator/query/center/ .. _$centerSphere: https://mongodb.com/docs/manual/reference/operator/query/centerSphere/ """ pipeline = [{"$match": filter}] if "skip" in kwargs: pipeline.append({"$skip": kwargs.pop("skip")}) if "limit" in kwargs: pipeline.append({"$limit": kwargs.pop("limit")}) if comment is not None: kwargs["comment"] = comment pipeline.append({"$group": {"_id": 1, "n": {"$sum": 1}}}) cmd = {"aggregate": self.__name, "pipeline": pipeline, "cursor": {}} if "hint" in kwargs and not isinstance(kwargs["hint"], str): kwargs["hint"] = helpers._index_document(kwargs["hint"]) collation = validate_collation_or_none(kwargs.pop("collation", None)) cmd.update(kwargs) def _cmd( session: Optional[ClientSession], _server: Server, conn: Connection, read_preference: Optional[_ServerMode], ) -> int: result = self._aggregate_one_result(conn, read_preference, cmd, collation, session) if not result: return 0 return result["n"] return self._retryable_non_cursor_read(_cmd, session, _Op.COUNT) def _retryable_non_cursor_read( self, func: Callable[[Optional[ClientSession], Server, Connection, Optional[_ServerMode]], T], session: Optional[ClientSession], operation: str, ) -> T: """Non-cursor read helper to handle implicit session creation.""" client = self.__database.client with client._tmp_session(session) as s: return client._retryable_read(func, self._read_preference_for(s), s, operation) def create_indexes( self, indexes: Sequence[IndexModel], session: Optional[ClientSession] = None, comment: Optional[Any] = None, **kwargs: Any, ) -> list[str]: """Create one or more indexes on this collection. >>> from pymongo import IndexModel, ASCENDING, DESCENDING >>> index1 = IndexModel([("hello", DESCENDING), ... ("world", ASCENDING)], name="hello_world") >>> index2 = IndexModel([("goodbye", DESCENDING)]) >>> db.test.create_indexes([index1, index2]) ["hello_world", "goodbye_-1"] :param indexes: A list of :class:`~pymongo.operations.IndexModel` instances. :param session: a :class:`~pymongo.client_session.ClientSession`. :param comment: A user-provided comment to attach to this command. :param kwargs: optional arguments to the createIndexes command (like maxTimeMS) can be passed as keyword arguments. .. note:: The :attr:`~pymongo.collection.Collection.write_concern` of this collection is automatically applied to this operation. .. versionchanged:: 3.6 Added ``session`` parameter. Added support for arbitrary keyword arguments. .. versionchanged:: 3.4 Apply this collection's write concern automatically to this operation when connected to MongoDB >= 3.4. .. versionadded:: 3.0 .. _createIndexes: https://mongodb.com/docs/manual/reference/command/createIndexes/ """ common.validate_list("indexes", indexes) if comment is not None: kwargs["comment"] = comment return self.__create_indexes(indexes, session, **kwargs) @_csot.apply def __create_indexes( self, indexes: Sequence[IndexModel], session: Optional[ClientSession], **kwargs: Any ) -> list[str]: """Internal createIndexes helper. :param indexes: A list of :class:`~pymongo.operations.IndexModel` instances. :param session: a :class:`~pymongo.client_session.ClientSession`. :param kwargs: optional arguments to the createIndexes command (like maxTimeMS) can be passed as keyword arguments. """ names = [] with self._conn_for_writes(session, operation=_Op.CREATE_INDEXES) as conn: supports_quorum = conn.max_wire_version >= 9 def gen_indexes() -> Iterator[Mapping[str, Any]]: for index in indexes: if not isinstance(index, IndexModel): raise TypeError( f"{index!r} is not an instance of pymongo.operations.IndexModel" ) document = index.document names.append(document["name"]) yield document cmd = {"createIndexes": self.name, "indexes": list(gen_indexes())} cmd.update(kwargs) if "commitQuorum" in kwargs and not supports_quorum: raise ConfigurationError( "Must be connected to MongoDB 4.4+ to use the " "commitQuorum option for createIndexes" ) self._command( conn, cmd, read_preference=ReadPreference.PRIMARY, codec_options=_UNICODE_REPLACE_CODEC_OPTIONS, write_concern=self._write_concern_for(session), session=session, ) return names def create_index( self, keys: _IndexKeyHint, session: Optional[ClientSession] = None, comment: Optional[Any] = None, **kwargs: Any, ) -> str: """Creates an index on this collection. Takes either a single key or a list containing (key, direction) pairs or keys. If no direction is given, :data:`~pymongo.ASCENDING` will be assumed. The key(s) must be an instance of :class:`str` and the direction(s) must be one of (:data:`~pymongo.ASCENDING`, :data:`~pymongo.DESCENDING`, :data:`~pymongo.GEO2D`, :data:`~pymongo.GEOSPHERE`, :data:`~pymongo.HASHED`, :data:`~pymongo.TEXT`). To create a single key ascending index on the key ``'mike'`` we just use a string argument:: >>> my_collection.create_index("mike") For a compound index on ``'mike'`` descending and ``'eliot'`` ascending we need to use a list of tuples:: >>> my_collection.create_index([("mike", pymongo.DESCENDING), ... "eliot"]) All optional index creation parameters should be passed as keyword arguments to this method. For example:: >>> my_collection.create_index([("mike", pymongo.DESCENDING)], ... background=True) Valid options include, but are not limited to: - `name`: custom name to use for this index - if none is given, a name will be generated. - `unique`: if ``True``, creates a uniqueness constraint on the index. - `background`: if ``True``, this index should be created in the background. - `sparse`: if ``True``, omit from the index any documents that lack the indexed field. - `bucketSize`: for use with geoHaystack indexes. Number of documents to group together within a certain proximity to a given longitude and latitude. - `min`: minimum value for keys in a :data:`~pymongo.GEO2D` index. - `max`: maximum value for keys in a :data:`~pymongo.GEO2D` index. - `expireAfterSeconds`: Used to create an expiring (TTL) collection. MongoDB will automatically delete documents from this collection after seconds. The indexed field must be a UTC datetime or the data will not expire. - `partialFilterExpression`: A document that specifies a filter for a partial index. - `collation` (optional): An instance of :class:`~pymongo.collation.Collation`. - `wildcardProjection`: Allows users to include or exclude specific field paths from a `wildcard index`_ using the {"$**" : 1} key pattern. Requires MongoDB >= 4.2. - `hidden`: if ``True``, this index will be hidden from the query planner and will not be evaluated as part of query plan selection. Requires MongoDB >= 4.4. See the MongoDB documentation for a full list of supported options by server version. .. warning:: `dropDups` is not supported by MongoDB 3.0 or newer. The option is silently ignored by the server and unique index builds using the option will fail if a duplicate value is detected. .. note:: The :attr:`~pymongo.collection.Collection.write_concern` of this collection is automatically applied to this operation. :param keys: a single key or a list of (key, direction) pairs specifying the index to create :param session: a :class:`~pymongo.client_session.ClientSession`. :param comment: A user-provided comment to attach to this command. :param kwargs: any additional index creation options (see the above list) should be passed as keyword arguments. .. versionchanged:: 4.4 Allow passing a list containing (key, direction) pairs or keys for the ``keys`` parameter. .. versionchanged:: 4.1 Added ``comment`` parameter. .. versionchanged:: 3.11 Added the ``hidden`` option. .. versionchanged:: 3.6 Added ``session`` parameter. Added support for passing maxTimeMS in kwargs. .. versionchanged:: 3.4 Apply this collection's write concern automatically to this operation when connected to MongoDB >= 3.4. Support the `collation` option. .. versionchanged:: 3.2 Added partialFilterExpression to support partial indexes. .. versionchanged:: 3.0 Renamed `key_or_list` to `keys`. Removed the `cache_for` option. :meth:`create_index` no longer caches index names. Removed support for the drop_dups and bucket_size aliases. .. seealso:: The MongoDB documentation on `indexes `_. .. _wildcard index: https://dochub.mongodb.org/core/index-wildcard/ """ cmd_options = {} if "maxTimeMS" in kwargs: cmd_options["maxTimeMS"] = kwargs.pop("maxTimeMS") if comment is not None: cmd_options["comment"] = comment index = IndexModel(keys, **kwargs) return self.__create_indexes([index], session, **cmd_options)[0] def drop_indexes( self, session: Optional[ClientSession] = None, comment: Optional[Any] = None, **kwargs: Any, ) -> None: """Drops all indexes on this collection. Can be used on non-existent collections or collections with no indexes. Raises OperationFailure on an error. :param session: a :class:`~pymongo.client_session.ClientSession`. :param comment: A user-provided comment to attach to this command. :param kwargs: optional arguments to the createIndexes command (like maxTimeMS) can be passed as keyword arguments. .. note:: The :attr:`~pymongo.collection.Collection.write_concern` of this collection is automatically applied to this operation. .. versionchanged:: 3.6 Added ``session`` parameter. Added support for arbitrary keyword arguments. .. versionchanged:: 3.4 Apply this collection's write concern automatically to this operation when connected to MongoDB >= 3.4. """ if comment is not None: kwargs["comment"] = comment self.drop_index("*", session=session, **kwargs) @_csot.apply def drop_index( self, index_or_name: _IndexKeyHint, session: Optional[ClientSession] = None, comment: Optional[Any] = None, **kwargs: Any, ) -> None: """Drops the specified index on this collection. Can be used on non-existent collections or collections with no indexes. Raises OperationFailure on an error (e.g. trying to drop an index that does not exist). `index_or_name` can be either an index name (as returned by `create_index`), or an index specifier (as passed to `create_index`). An index specifier should be a list of (key, direction) pairs. Raises TypeError if index is not an instance of (str, unicode, list). .. warning:: if a custom name was used on index creation (by passing the `name` parameter to :meth:`create_index`) the index **must** be dropped by name. :param index_or_name: index (or name of index) to drop :param session: a :class:`~pymongo.client_session.ClientSession`. :param comment: A user-provided comment to attach to this command. :param kwargs: optional arguments to the createIndexes command (like maxTimeMS) can be passed as keyword arguments. .. note:: The :attr:`~pymongo.collection.Collection.write_concern` of this collection is automatically applied to this operation. .. versionchanged:: 3.6 Added ``session`` parameter. Added support for arbitrary keyword arguments. .. versionchanged:: 3.4 Apply this collection's write concern automatically to this operation when connected to MongoDB >= 3.4. """ name = index_or_name if isinstance(index_or_name, list): name = helpers._gen_index_name(index_or_name) if not isinstance(name, str): raise TypeError("index_or_name must be an instance of str or list") cmd = {"dropIndexes": self.__name, "index": name} cmd.update(kwargs) if comment is not None: cmd["comment"] = comment with self._conn_for_writes(session, operation=_Op.DROP_INDEXES) as conn: self._command( conn, cmd, read_preference=ReadPreference.PRIMARY, allowable_errors=["ns not found", 26], write_concern=self._write_concern_for(session), session=session, ) def list_indexes( self, session: Optional[ClientSession] = None, comment: Optional[Any] = None, ) -> CommandCursor[MutableMapping[str, Any]]: """Get a cursor over the index documents for this collection. >>> for index in db.test.list_indexes(): ... print(index) ... SON([('v', 2), ('key', SON([('_id', 1)])), ('name', '_id_')]) :param session: a :class:`~pymongo.client_session.ClientSession`. :param comment: A user-provided comment to attach to this command. :return: An instance of :class:`~pymongo.command_cursor.CommandCursor`. .. versionchanged:: 4.1 Added ``comment`` parameter. .. versionchanged:: 3.6 Added ``session`` parameter. .. versionadded:: 3.0 """ codec_options: CodecOptions = CodecOptions(SON) coll = cast( Collection[MutableMapping[str, Any]], self.with_options(codec_options=codec_options, read_preference=ReadPreference.PRIMARY), ) read_pref = (session and session._txn_read_preference()) or ReadPreference.PRIMARY explicit_session = session is not None def _cmd( session: Optional[ClientSession], _server: Server, conn: Connection, read_preference: _ServerMode, ) -> CommandCursor[MutableMapping[str, Any]]: cmd = {"listIndexes": self.__name, "cursor": {}} if comment is not None: cmd["comment"] = comment try: cursor = self._command(conn, cmd, read_preference, codec_options, session=session)[ "cursor" ] except OperationFailure as exc: # Ignore NamespaceNotFound errors to match the behavior # of reading from *.system.indexes. if exc.code != 26: raise cursor = {"id": 0, "firstBatch": []} cmd_cursor = CommandCursor( coll, cursor, conn.address, session=session, explicit_session=explicit_session, comment=cmd.get("comment"), ) cmd_cursor._maybe_pin_connection(conn) return cmd_cursor with self.__database.client._tmp_session(session, False) as s: return self.__database.client._retryable_read( _cmd, read_pref, s, operation=_Op.LIST_INDEXES ) def index_information( self, session: Optional[ClientSession] = None, comment: Optional[Any] = None, ) -> MutableMapping[str, Any]: """Get information on this collection's indexes. Returns a dictionary where the keys are index names (as returned by create_index()) and the values are dictionaries containing information about each index. The dictionary is guaranteed to contain at least a single key, ``"key"`` which is a list of (key, direction) pairs specifying the index (as passed to create_index()). It will also contain any other metadata about the indexes, except for the ``"ns"`` and ``"name"`` keys, which are cleaned. Example output might look like this: >>> db.test.create_index("x", unique=True) 'x_1' >>> db.test.index_information() {'_id_': {'key': [('_id', 1)]}, 'x_1': {'unique': True, 'key': [('x', 1)]}} :param session: a :class:`~pymongo.client_session.ClientSession`. :param comment: A user-provided comment to attach to this command. .. versionchanged:: 4.1 Added ``comment`` parameter. .. versionchanged:: 3.6 Added ``session`` parameter. """ cursor = self.list_indexes(session=session, comment=comment) info = {} for index in cursor: index["key"] = list(index["key"].items()) index = dict(index) # noqa: PLW2901 info[index.pop("name")] = index return info def list_search_indexes( self, name: Optional[str] = None, session: Optional[ClientSession] = None, comment: Optional[Any] = None, **kwargs: Any, ) -> CommandCursor[Mapping[str, Any]]: """Return a cursor over search indexes for the current collection. :param name: If given, the name of the index to search for. Only indexes with matching index names will be returned. If not given, all search indexes for the current collection will be returned. :param session: a :class:`~pymongo.client_session.ClientSession`. :param comment: A user-provided comment to attach to this command. :return: A :class:`~pymongo.command_cursor.CommandCursor` over the result set. .. note:: requires a MongoDB server version 7.0+ Atlas cluster. .. versionadded:: 4.5 """ if name is None: pipeline: _Pipeline = [{"$listSearchIndexes": {}}] else: pipeline = [{"$listSearchIndexes": {"name": name}}] coll = self.with_options( codec_options=DEFAULT_CODEC_OPTIONS, read_preference=ReadPreference.PRIMARY, write_concern=DEFAULT_WRITE_CONCERN, read_concern=DEFAULT_READ_CONCERN, ) cmd = _CollectionAggregationCommand( coll, CommandCursor, pipeline, kwargs, explicit_session=session is not None, comment=comment, user_fields={"cursor": {"firstBatch": 1}}, ) return self.__database.client._retryable_read( cmd.get_cursor, cmd.get_read_preference(session), # type: ignore[arg-type] session, retryable=not cmd._performs_write, operation=_Op.LIST_SEARCH_INDEX, ) def create_search_index( self, model: Union[Mapping[str, Any], SearchIndexModel], session: Optional[ClientSession] = None, comment: Any = None, **kwargs: Any, ) -> str: """Create a single search index for the current collection. :param model: The model for the new search index. It can be given as a :class:`~pymongo.operations.SearchIndexModel` instance or a dictionary with a model "definition" and optional "name". :param session: a :class:`~pymongo.client_session.ClientSession`. :param comment: A user-provided comment to attach to this command. :param kwargs: optional arguments to the createSearchIndexes command (like maxTimeMS) can be passed as keyword arguments. :return: The name of the new search index. .. note:: requires a MongoDB server version 7.0+ Atlas cluster. .. versionadded:: 4.5 """ if not isinstance(model, SearchIndexModel): model = SearchIndexModel(**model) return self.create_search_indexes([model], session, comment, **kwargs)[0] def create_search_indexes( self, models: list[SearchIndexModel], session: Optional[ClientSession] = None, comment: Optional[Any] = None, **kwargs: Any, ) -> list[str]: """Create multiple search indexes for the current collection. :param models: A list of :class:`~pymongo.operations.SearchIndexModel` instances. :param session: a :class:`~pymongo.client_session.ClientSession`. :param comment: A user-provided comment to attach to this command. :param kwargs: optional arguments to the createSearchIndexes command (like maxTimeMS) can be passed as keyword arguments. :return: A list of the newly created search index names. .. note:: requires a MongoDB server version 7.0+ Atlas cluster. .. versionadded:: 4.5 """ if comment is not None: kwargs["comment"] = comment def gen_indexes() -> Iterator[Mapping[str, Any]]: for index in models: if not isinstance(index, SearchIndexModel): raise TypeError( f"{index!r} is not an instance of pymongo.operations.SearchIndexModel" ) yield index.document cmd = {"createSearchIndexes": self.name, "indexes": list(gen_indexes())} cmd.update(kwargs) with self._conn_for_writes(session, operation=_Op.CREATE_SEARCH_INDEXES) as conn: resp = self._command( conn, cmd, read_preference=ReadPreference.PRIMARY, codec_options=_UNICODE_REPLACE_CODEC_OPTIONS, ) return [index["name"] for index in resp["indexesCreated"]] def drop_search_index( self, name: str, session: Optional[ClientSession] = None, comment: Optional[Any] = None, **kwargs: Any, ) -> None: """Delete a search index by index name. :param name: The name of the search index to be deleted. :param session: a :class:`~pymongo.client_session.ClientSession`. :param comment: A user-provided comment to attach to this command. :param kwargs: optional arguments to the dropSearchIndexes command (like maxTimeMS) can be passed as keyword arguments. .. note:: requires a MongoDB server version 7.0+ Atlas cluster. .. versionadded:: 4.5 """ cmd = {"dropSearchIndex": self.__name, "name": name} cmd.update(kwargs) if comment is not None: cmd["comment"] = comment with self._conn_for_writes(session, operation=_Op.DROP_SEARCH_INDEXES) as conn: self._command( conn, cmd, read_preference=ReadPreference.PRIMARY, allowable_errors=["ns not found", 26], codec_options=_UNICODE_REPLACE_CODEC_OPTIONS, ) def update_search_index( self, name: str, definition: Mapping[str, Any], session: Optional[ClientSession] = None, comment: Optional[Any] = None, **kwargs: Any, ) -> None: """Update a search index by replacing the existing index definition with the provided definition. :param name: The name of the search index to be updated. :param definition: The new search index definition. :param session: a :class:`~pymongo.client_session.ClientSession`. :param comment: A user-provided comment to attach to this command. :param kwargs: optional arguments to the updateSearchIndexes command (like maxTimeMS) can be passed as keyword arguments. .. note:: requires a MongoDB server version 7.0+ Atlas cluster. .. versionadded:: 4.5 """ cmd = {"updateSearchIndex": self.__name, "name": name, "definition": definition} cmd.update(kwargs) if comment is not None: cmd["comment"] = comment with self._conn_for_writes(session, operation=_Op.UPDATE_SEARCH_INDEX) as conn: self._command( conn, cmd, read_preference=ReadPreference.PRIMARY, allowable_errors=["ns not found", 26], codec_options=_UNICODE_REPLACE_CODEC_OPTIONS, ) def options( self, session: Optional[ClientSession] = None, comment: Optional[Any] = None, ) -> MutableMapping[str, Any]: """Get the options set on this collection. Returns a dictionary of options and their values - see :meth:`~pymongo.database.Database.create_collection` for more information on the possible options. Returns an empty dictionary if the collection has not been created yet. :param session: a :class:`~pymongo.client_session.ClientSession`. :param comment: A user-provided comment to attach to this command. .. versionchanged:: 3.6 Added ``session`` parameter. """ dbo = self.__database.client.get_database( self.__database.name, self.codec_options, self.read_preference, self.write_concern, self.read_concern, ) cursor = dbo.list_collections( session=session, filter={"name": self.__name}, comment=comment ) result = None for doc in cursor: result = doc break if not result: return {} options = result.get("options", {}) assert options is not None if "create" in options: del options["create"] return options @_csot.apply def _aggregate( self, aggregation_command: Type[_AggregationCommand], pipeline: _Pipeline, cursor_class: Type[CommandCursor], session: Optional[ClientSession], explicit_session: bool, let: Optional[Mapping[str, Any]] = None, comment: Optional[Any] = None, **kwargs: Any, ) -> CommandCursor[_DocumentType]: if comment is not None: kwargs["comment"] = comment cmd = aggregation_command( self, cursor_class, pipeline, kwargs, explicit_session, let, user_fields={"cursor": {"firstBatch": 1}}, ) return self.__database.client._retryable_read( cmd.get_cursor, cmd.get_read_preference(session), # type: ignore[arg-type] session, retryable=not cmd._performs_write, operation=_Op.AGGREGATE, ) def aggregate( self, pipeline: _Pipeline, session: Optional[ClientSession] = None, let: Optional[Mapping[str, Any]] = None, comment: Optional[Any] = None, **kwargs: Any, ) -> CommandCursor[_DocumentType]: """Perform an aggregation using the aggregation framework on this collection. The :meth:`aggregate` method obeys the :attr:`read_preference` of this :class:`Collection`, except when ``$out`` or ``$merge`` are used on MongoDB <5.0, in which case :attr:`~pymongo.read_preferences.ReadPreference.PRIMARY` is used. .. note:: This method does not support the 'explain' option. Please use `PyMongoExplain `_ instead. An example is included in the :ref:`aggregate-examples` documentation. .. note:: The :attr:`~pymongo.collection.Collection.write_concern` of this collection is automatically applied to this operation. :param pipeline: a list of aggregation pipeline stages :param session: a :class:`~pymongo.client_session.ClientSession`. :param let: A dict of parameter names and values. Values must be constant or closed expressions that do not reference document fields. Parameters can then be accessed as variables in an aggregate expression context (e.g. ``"$$var"``). This option is only supported on MongoDB >= 5.0. :param comment: A user-provided comment to attach to this command. :param kwargs: extra `aggregate command`_ parameters. All optional `aggregate command`_ parameters should be passed as keyword arguments to this method. Valid options include, but are not limited to: - `allowDiskUse` (bool): Enables writing to temporary files. When set to True, aggregation stages can write data to the _tmp subdirectory of the --dbpath directory. The default is False. - `maxTimeMS` (int): The maximum amount of time to allow the operation to run in milliseconds. - `batchSize` (int): The maximum number of documents to return per batch. Ignored if the connected mongod or mongos does not support returning aggregate results using a cursor. - `collation` (optional): An instance of :class:`~pymongo.collation.Collation`. :return: A :class:`~pymongo.command_cursor.CommandCursor` over the result set. .. versionchanged:: 4.1 Added ``comment`` parameter. Added ``let`` parameter. Support $merge and $out executing on secondaries according to the collection's :attr:`read_preference`. .. versionchanged:: 4.0 Removed the ``useCursor`` option. .. versionchanged:: 3.9 Apply this collection's read concern to pipelines containing the `$out` stage when connected to MongoDB >= 4.2. Added support for the ``$merge`` pipeline stage. Aggregations that write always use read preference :attr:`~pymongo.read_preferences.ReadPreference.PRIMARY`. .. versionchanged:: 3.6 Added the `session` parameter. Added the `maxAwaitTimeMS` option. Deprecated the `useCursor` option. .. versionchanged:: 3.4 Apply this collection's write concern automatically to this operation when connected to MongoDB >= 3.4. Support the `collation` option. .. versionchanged:: 3.0 The :meth:`aggregate` method always returns a CommandCursor. The pipeline argument must be a list. .. seealso:: :doc:`/examples/aggregation` .. _aggregate command: https://mongodb.com/docs/manual/reference/command/aggregate """ with self.__database.client._tmp_session(session, close=False) as s: return self._aggregate( _CollectionAggregationCommand, pipeline, CommandCursor, session=s, explicit_session=session is not None, let=let, comment=comment, **kwargs, ) def aggregate_raw_batches( self, pipeline: _Pipeline, session: Optional[ClientSession] = None, comment: Optional[Any] = None, **kwargs: Any, ) -> RawBatchCursor[_DocumentType]: """Perform an aggregation and retrieve batches of raw BSON. Similar to the :meth:`aggregate` method but returns a :class:`~pymongo.cursor.RawBatchCursor`. This example demonstrates how to work with raw batches, but in practice raw batches should be passed to an external library that can decode BSON into another data type, rather than used with PyMongo's :mod:`bson` module. >>> import bson >>> cursor = db.test.aggregate_raw_batches([ ... {'$project': {'x': {'$multiply': [2, '$x']}}}]) >>> for batch in cursor: ... print(bson.decode_all(batch)) .. note:: aggregate_raw_batches does not support auto encryption. .. versionchanged:: 3.12 Added session support. .. versionadded:: 3.6 """ # OP_MSG is required to support encryption. if self.__database.client._encrypter: raise InvalidOperation("aggregate_raw_batches does not support auto encryption") if comment is not None: kwargs["comment"] = comment with self.__database.client._tmp_session(session, close=False) as s: return cast( RawBatchCursor[_DocumentType], self._aggregate( _CollectionRawAggregationCommand, pipeline, RawBatchCommandCursor, session=s, explicit_session=session is not None, **kwargs, ), ) def watch( self, pipeline: Optional[_Pipeline] = None, full_document: Optional[str] = None, resume_after: Optional[Mapping[str, Any]] = None, max_await_time_ms: Optional[int] = None, batch_size: Optional[int] = None, collation: Optional[_CollationIn] = None, start_at_operation_time: Optional[Timestamp] = None, session: Optional[ClientSession] = None, start_after: Optional[Mapping[str, Any]] = None, comment: Optional[Any] = None, full_document_before_change: Optional[str] = None, show_expanded_events: Optional[bool] = None, ) -> CollectionChangeStream[_DocumentType]: """Watch changes on this collection. Performs an aggregation with an implicit initial ``$changeStream`` stage and returns a :class:`~pymongo.change_stream.CollectionChangeStream` cursor which iterates over changes on this collection. .. code-block:: python with db.collection.watch() as stream: for change in stream: print(change) The :class:`~pymongo.change_stream.CollectionChangeStream` iterable blocks until the next change document is returned or an error is raised. If the :meth:`~pymongo.change_stream.CollectionChangeStream.next` method encounters a network error when retrieving a batch from the server, it will automatically attempt to recreate the cursor such that no change events are missed. Any error encountered during the resume attempt indicates there may be an outage and will be raised. .. code-block:: python try: with db.collection.watch([{"$match": {"operationType": "insert"}}]) as stream: for insert_change in stream: print(insert_change) except pymongo.errors.PyMongoError: # The ChangeStream encountered an unrecoverable error or the # resume attempt failed to recreate the cursor. logging.error("...") For a precise description of the resume process see the `change streams specification`_. .. note:: Using this helper method is preferred to directly calling :meth:`~pymongo.collection.Collection.aggregate` with a ``$changeStream`` stage, for the purpose of supporting resumability. .. warning:: This Collection's :attr:`read_concern` must be ``ReadConcern("majority")`` in order to use the ``$changeStream`` stage. :param pipeline: A list of aggregation pipeline stages to append to an initial ``$changeStream`` stage. Not all pipeline stages are valid after a ``$changeStream`` stage, see the MongoDB documentation on change streams for the supported stages. :param full_document: The fullDocument to pass as an option to the ``$changeStream`` stage. Allowed values: 'updateLookup', 'whenAvailable', 'required'. When set to 'updateLookup', the change notification for partial updates will include both a delta describing the changes to the document, as well as a copy of the entire document that was changed from some time after the change occurred. :param full_document_before_change: Allowed values: 'whenAvailable' and 'required'. Change events may now result in a 'fullDocumentBeforeChange' response field. :param resume_after: A resume token. If provided, the change stream will start returning changes that occur directly after the operation specified in the resume token. A resume token is the _id value of a change document. :param max_await_time_ms: The maximum time in milliseconds for the server to wait for changes before responding to a getMore operation. :param batch_size: The maximum number of documents to return per batch. :param collation: The :class:`~pymongo.collation.Collation` to use for the aggregation. :param start_at_operation_time: If provided, the resulting change stream will only return changes that occurred at or after the specified :class:`~bson.timestamp.Timestamp`. Requires MongoDB >= 4.0. :param session: a :class:`~pymongo.client_session.ClientSession`. :param start_after: The same as `resume_after` except that `start_after` can resume notifications after an invalidate event. This option and `resume_after` are mutually exclusive. :param comment: A user-provided comment to attach to this command. :param show_expanded_events: Include expanded events such as DDL events like `dropIndexes`. :return: A :class:`~pymongo.change_stream.CollectionChangeStream` cursor. .. versionchanged:: 4.3 Added `show_expanded_events` parameter. .. versionchanged:: 4.2 Added ``full_document_before_change`` parameter. .. versionchanged:: 4.1 Added ``comment`` parameter. .. versionchanged:: 3.9 Added the ``start_after`` parameter. .. versionchanged:: 3.7 Added the ``start_at_operation_time`` parameter. .. versionadded:: 3.6 .. seealso:: The MongoDB documentation on `changeStreams `_. .. _change streams specification: https://github.com/mongodb/specifications/blob/master/source/change-streams/change-streams.md """ return CollectionChangeStream( self, pipeline, full_document, resume_after, max_await_time_ms, batch_size, collation, start_at_operation_time, session, start_after, comment, full_document_before_change, show_expanded_events, ) @_csot.apply def rename( self, new_name: str, session: Optional[ClientSession] = None, comment: Optional[Any] = None, **kwargs: Any, ) -> MutableMapping[str, Any]: """Rename this collection. If operating in auth mode, client must be authorized as an admin to perform this operation. Raises :class:`TypeError` if `new_name` is not an instance of :class:`str`. Raises :class:`~pymongo.errors.InvalidName` if `new_name` is not a valid collection name. :param new_name: new name for this collection :param session: a :class:`~pymongo.client_session.ClientSession`. :param comment: A user-provided comment to attach to this command. :param kwargs: additional arguments to the rename command may be passed as keyword arguments to this helper method (i.e. ``dropTarget=True``) .. note:: The :attr:`~pymongo.collection.Collection.write_concern` of this collection is automatically applied to this operation. .. versionchanged:: 3.6 Added ``session`` parameter. .. versionchanged:: 3.4 Apply this collection's write concern automatically to this operation when connected to MongoDB >= 3.4. """ if not isinstance(new_name, str): raise TypeError("new_name must be an instance of str") if not new_name or ".." in new_name: raise InvalidName("collection names cannot be empty") if new_name[0] == "." or new_name[-1] == ".": raise InvalidName("collection names must not start or end with '.'") if "$" in new_name and not new_name.startswith("oplog.$main"): raise InvalidName("collection names must not contain '$'") new_name = f"{self.__database.name}.{new_name}" cmd = {"renameCollection": self.__full_name, "to": new_name} cmd.update(kwargs) if comment is not None: cmd["comment"] = comment write_concern = self._write_concern_for_cmd(cmd, session) with self._conn_for_writes(session, operation=_Op.RENAME) as conn: with self.__database.client._tmp_session(session) as s: return conn.command( "admin", cmd, write_concern=write_concern, parse_write_concern_error=True, session=s, client=self.__database.client, ) def distinct( self, key: str, filter: Optional[Mapping[str, Any]] = None, session: Optional[ClientSession] = None, comment: Optional[Any] = None, **kwargs: Any, ) -> list: """Get a list of distinct values for `key` among all documents in this collection. Raises :class:`TypeError` if `key` is not an instance of :class:`str`. All optional distinct parameters should be passed as keyword arguments to this method. Valid options include: - `maxTimeMS` (int): The maximum amount of time to allow the count command to run, in milliseconds. - `collation` (optional): An instance of :class:`~pymongo.collation.Collation`. The :meth:`distinct` method obeys the :attr:`read_preference` of this :class:`Collection`. :param key: name of the field for which we want to get the distinct values :param filter: A query document that specifies the documents from which to retrieve the distinct values. :param session: a :class:`~pymongo.client_session.ClientSession`. :param comment: A user-provided comment to attach to this command. :param kwargs: See list of options above. .. versionchanged:: 3.6 Added ``session`` parameter. .. versionchanged:: 3.4 Support the `collation` option. """ if not isinstance(key, str): raise TypeError("key must be an instance of str") cmd = {"distinct": self.__name, "key": key} if filter is not None: if "query" in kwargs: raise ConfigurationError("can't pass both filter and query") kwargs["query"] = filter collation = validate_collation_or_none(kwargs.pop("collation", None)) cmd.update(kwargs) if comment is not None: cmd["comment"] = comment def _cmd( session: Optional[ClientSession], _server: Server, conn: Connection, read_preference: Optional[_ServerMode], ) -> list: return self._command( conn, cmd, read_preference=read_preference, read_concern=self.read_concern, collation=collation, session=session, user_fields={"values": 1}, )["values"] return self._retryable_non_cursor_read(_cmd, session, operation=_Op.DISTINCT) def _write_concern_for_cmd( self, cmd: Mapping[str, Any], session: Optional[ClientSession] ) -> WriteConcern: raw_wc = cmd.get("writeConcern") if raw_wc is not None: return WriteConcern(**raw_wc) else: return self._write_concern_for(session) def __find_and_modify( self, filter: Mapping[str, Any], projection: Optional[Union[Mapping[str, Any], Iterable[str]]], sort: Optional[_IndexList], upsert: Optional[bool] = None, return_document: bool = ReturnDocument.BEFORE, array_filters: Optional[Sequence[Mapping[str, Any]]] = None, hint: Optional[_IndexKeyHint] = None, session: Optional[ClientSession] = None, let: Optional[Mapping] = None, **kwargs: Any, ) -> Any: """Internal findAndModify helper.""" common.validate_is_mapping("filter", filter) if not isinstance(return_document, bool): raise ValueError( "return_document must be ReturnDocument.BEFORE or ReturnDocument.AFTER" ) collation = validate_collation_or_none(kwargs.pop("collation", None)) cmd = {"findAndModify": self.__name, "query": filter, "new": return_document} if let is not None: common.validate_is_mapping("let", let) cmd["let"] = let cmd.update(kwargs) if projection is not None: cmd["fields"] = helpers._fields_list_to_dict(projection, "projection") if sort is not None: cmd["sort"] = helpers._index_document(sort) if upsert is not None: validate_boolean("upsert", upsert) cmd["upsert"] = upsert if hint is not None: if not isinstance(hint, str): hint = helpers._index_document(hint) write_concern = self._write_concern_for_cmd(cmd, session) def _find_and_modify( session: Optional[ClientSession], conn: Connection, retryable_write: bool ) -> Any: acknowledged = write_concern.acknowledged if array_filters is not None: if not acknowledged: raise ConfigurationError( "arrayFilters is unsupported for unacknowledged writes." ) cmd["arrayFilters"] = list(array_filters) if hint is not None: if conn.max_wire_version < 8: raise ConfigurationError( "Must be connected to MongoDB 4.2+ to use hint on find and modify commands." ) elif not acknowledged and conn.max_wire_version < 9: raise ConfigurationError( "Must be connected to MongoDB 4.4+ to use hint on unacknowledged find and modify commands." ) cmd["hint"] = hint out = self._command( conn, cmd, read_preference=ReadPreference.PRIMARY, write_concern=write_concern, collation=collation, session=session, retryable_write=retryable_write, user_fields=_FIND_AND_MODIFY_DOC_FIELDS, ) _check_write_command_response(out) return out.get("value") return self.__database.client._retryable_write( write_concern.acknowledged, _find_and_modify, session, operation=_Op.FIND_AND_MODIFY, ) def find_one_and_delete( self, filter: Mapping[str, Any], projection: Optional[Union[Mapping[str, Any], Iterable[str]]] = None, sort: Optional[_IndexList] = None, hint: Optional[_IndexKeyHint] = None, session: Optional[ClientSession] = None, let: Optional[Mapping[str, Any]] = None, comment: Optional[Any] = None, **kwargs: Any, ) -> _DocumentType: """Finds a single document and deletes it, returning the document. >>> db.test.count_documents({'x': 1}) 2 >>> db.test.find_one_and_delete({'x': 1}) {'x': 1, '_id': ObjectId('54f4e12bfba5220aa4d6dee8')} >>> db.test.count_documents({'x': 1}) 1 If multiple documents match *filter*, a *sort* can be applied. >>> for doc in db.test.find({'x': 1}): ... print(doc) ... {'x': 1, '_id': 0} {'x': 1, '_id': 1} {'x': 1, '_id': 2} >>> db.test.find_one_and_delete( ... {'x': 1}, sort=[('_id', pymongo.DESCENDING)]) {'x': 1, '_id': 2} The *projection* option can be used to limit the fields returned. >>> db.test.find_one_and_delete({'x': 1}, projection={'_id': False}) {'x': 1} :param filter: A query that matches the document to delete. :param projection: a list of field names that should be returned in the result document or a mapping specifying the fields to include or exclude. If `projection` is a list "_id" will always be returned. Use a mapping to exclude fields from the result (e.g. projection={'_id': False}). :param sort: a list of (key, direction) pairs specifying the sort order for the query. If multiple documents match the query, they are sorted and the first is deleted. :param hint: An index to use to support the query predicate specified either by its string name, or in the same format as passed to :meth:`~pymongo.collection.Collection.create_index` (e.g. ``[('field', ASCENDING)]``). This option is only supported on MongoDB 4.4 and above. :param session: a :class:`~pymongo.client_session.ClientSession`. :param let: Map of parameter names and values. Values must be constant or closed expressions that do not reference document fields. Parameters can then be accessed as variables in an aggregate expression context (e.g. "$$var"). :param comment: A user-provided comment to attach to this command. :param kwargs: additional command arguments can be passed as keyword arguments (for example maxTimeMS can be used with recent server versions). .. versionchanged:: 4.1 Added ``let`` parameter. .. versionchanged:: 3.11 Added ``hint`` parameter. .. versionchanged:: 3.6 Added ``session`` parameter. .. versionchanged:: 3.2 Respects write concern. .. warning:: Starting in PyMongo 3.2, this command uses the :class:`~pymongo.write_concern.WriteConcern` of this :class:`~pymongo.collection.Collection` when connected to MongoDB >= 3.2. Note that using an elevated write concern with this command may be slower compared to using the default write concern. .. versionchanged:: 3.4 Added the `collation` option. .. versionadded:: 3.0 """ kwargs["remove"] = True if comment is not None: kwargs["comment"] = comment return self.__find_and_modify( filter, projection, sort, let=let, hint=hint, session=session, **kwargs ) def find_one_and_replace( self, filter: Mapping[str, Any], replacement: Mapping[str, Any], projection: Optional[Union[Mapping[str, Any], Iterable[str]]] = None, sort: Optional[_IndexList] = None, upsert: bool = False, return_document: bool = ReturnDocument.BEFORE, hint: Optional[_IndexKeyHint] = None, session: Optional[ClientSession] = None, let: Optional[Mapping[str, Any]] = None, comment: Optional[Any] = None, **kwargs: Any, ) -> _DocumentType: """Finds a single document and replaces it, returning either the original or the replaced document. The :meth:`find_one_and_replace` method differs from :meth:`find_one_and_update` by replacing the document matched by *filter*, rather than modifying the existing document. >>> for doc in db.test.find({}): ... print(doc) ... {'x': 1, '_id': 0} {'x': 1, '_id': 1} {'x': 1, '_id': 2} >>> db.test.find_one_and_replace({'x': 1}, {'y': 1}) {'x': 1, '_id': 0} >>> for doc in db.test.find({}): ... print(doc) ... {'y': 1, '_id': 0} {'x': 1, '_id': 1} {'x': 1, '_id': 2} :param filter: A query that matches the document to replace. :param replacement: The replacement document. :param projection: A list of field names that should be returned in the result document or a mapping specifying the fields to include or exclude. If `projection` is a list "_id" will always be returned. Use a mapping to exclude fields from the result (e.g. projection={'_id': False}). :param sort: a list of (key, direction) pairs specifying the sort order for the query. If multiple documents match the query, they are sorted and the first is replaced. :param upsert: When ``True``, inserts a new document if no document matches the query. Defaults to ``False``. :param return_document: If :attr:`ReturnDocument.BEFORE` (the default), returns the original document before it was replaced, or ``None`` if no document matches. If :attr:`ReturnDocument.AFTER`, returns the replaced or inserted document. :param hint: An index to use to support the query predicate specified either by its string name, or in the same format as passed to :meth:`~pymongo.collection.Collection.create_index` (e.g. ``[('field', ASCENDING)]``). This option is only supported on MongoDB 4.4 and above. :param session: a :class:`~pymongo.client_session.ClientSession`. :param let: Map of parameter names and values. Values must be constant or closed expressions that do not reference document fields. Parameters can then be accessed as variables in an aggregate expression context (e.g. "$$var"). :param comment: A user-provided comment to attach to this command. :param kwargs: additional command arguments can be passed as keyword arguments (for example maxTimeMS can be used with recent server versions). .. versionchanged:: 4.1 Added ``let`` parameter. .. versionchanged:: 3.11 Added the ``hint`` option. .. versionchanged:: 3.6 Added ``session`` parameter. .. versionchanged:: 3.4 Added the ``collation`` option. .. versionchanged:: 3.2 Respects write concern. .. warning:: Starting in PyMongo 3.2, this command uses the :class:`~pymongo.write_concern.WriteConcern` of this :class:`~pymongo.collection.Collection` when connected to MongoDB >= 3.2. Note that using an elevated write concern with this command may be slower compared to using the default write concern. .. versionadded:: 3.0 """ common.validate_ok_for_replace(replacement) kwargs["update"] = replacement if comment is not None: kwargs["comment"] = comment return self.__find_and_modify( filter, projection, sort, upsert, return_document, let=let, hint=hint, session=session, **kwargs, ) def find_one_and_update( self, filter: Mapping[str, Any], update: Union[Mapping[str, Any], _Pipeline], projection: Optional[Union[Mapping[str, Any], Iterable[str]]] = None, sort: Optional[_IndexList] = None, upsert: bool = False, return_document: bool = ReturnDocument.BEFORE, array_filters: Optional[Sequence[Mapping[str, Any]]] = None, hint: Optional[_IndexKeyHint] = None, session: Optional[ClientSession] = None, let: Optional[Mapping[str, Any]] = None, comment: Optional[Any] = None, **kwargs: Any, ) -> _DocumentType: """Finds a single document and updates it, returning either the original or the updated document. >>> db.test.find_one_and_update( ... {'_id': 665}, {'$inc': {'count': 1}, '$set': {'done': True}}) {'_id': 665, 'done': False, 'count': 25}} Returns ``None`` if no document matches the filter. >>> db.test.find_one_and_update( ... {'_exists': False}, {'$inc': {'count': 1}}) When the filter matches, by default :meth:`find_one_and_update` returns the original version of the document before the update was applied. To return the updated (or inserted in the case of *upsert*) version of the document instead, use the *return_document* option. >>> from pymongo import ReturnDocument >>> db.example.find_one_and_update( ... {'_id': 'userid'}, ... {'$inc': {'seq': 1}}, ... return_document=ReturnDocument.AFTER) {'_id': 'userid', 'seq': 1} You can limit the fields returned with the *projection* option. >>> db.example.find_one_and_update( ... {'_id': 'userid'}, ... {'$inc': {'seq': 1}}, ... projection={'seq': True, '_id': False}, ... return_document=ReturnDocument.AFTER) {'seq': 2} The *upsert* option can be used to create the document if it doesn't already exist. >>> db.example.delete_many({}).deleted_count 1 >>> db.example.find_one_and_update( ... {'_id': 'userid'}, ... {'$inc': {'seq': 1}}, ... projection={'seq': True, '_id': False}, ... upsert=True, ... return_document=ReturnDocument.AFTER) {'seq': 1} If multiple documents match *filter*, a *sort* can be applied. >>> for doc in db.test.find({'done': True}): ... print(doc) ... {'_id': 665, 'done': True, 'result': {'count': 26}} {'_id': 701, 'done': True, 'result': {'count': 17}} >>> db.test.find_one_and_update( ... {'done': True}, ... {'$set': {'final': True}}, ... sort=[('_id', pymongo.DESCENDING)]) {'_id': 701, 'done': True, 'result': {'count': 17}} :param filter: A query that matches the document to update. :param update: The update operations to apply. :param projection: A list of field names that should be returned in the result document or a mapping specifying the fields to include or exclude. If `projection` is a list "_id" will always be returned. Use a dict to exclude fields from the result (e.g. projection={'_id': False}). :param sort: a list of (key, direction) pairs specifying the sort order for the query. If multiple documents match the query, they are sorted and the first is updated. :param upsert: When ``True``, inserts a new document if no document matches the query. Defaults to ``False``. :param return_document: If :attr:`ReturnDocument.BEFORE` (the default), returns the original document before it was updated. If :attr:`ReturnDocument.AFTER`, returns the updated or inserted document. :param array_filters: A list of filters specifying which array elements an update should apply. :param hint: An index to use to support the query predicate specified either by its string name, or in the same format as passed to :meth:`~pymongo.collection.Collection.create_index` (e.g. ``[('field', ASCENDING)]``). This option is only supported on MongoDB 4.4 and above. :param session: a :class:`~pymongo.client_session.ClientSession`. :param let: Map of parameter names and values. Values must be constant or closed expressions that do not reference document fields. Parameters can then be accessed as variables in an aggregate expression context (e.g. "$$var"). :param comment: A user-provided comment to attach to this command. :param kwargs: additional command arguments can be passed as keyword arguments (for example maxTimeMS can be used with recent server versions). .. versionchanged:: 3.11 Added the ``hint`` option. .. versionchanged:: 3.9 Added the ability to accept a pipeline as the ``update``. .. versionchanged:: 3.6 Added the ``array_filters`` and ``session`` options. .. versionchanged:: 3.4 Added the ``collation`` option. .. versionchanged:: 3.2 Respects write concern. .. warning:: Starting in PyMongo 3.2, this command uses the :class:`~pymongo.write_concern.WriteConcern` of this :class:`~pymongo.collection.Collection` when connected to MongoDB >= 3.2. Note that using an elevated write concern with this command may be slower compared to using the default write concern. .. versionadded:: 3.0 """ common.validate_ok_for_update(update) common.validate_list_or_none("array_filters", array_filters) kwargs["update"] = update if comment is not None: kwargs["comment"] = comment return self.__find_and_modify( filter, projection, sort, upsert, return_document, array_filters, hint=hint, let=let, session=session, **kwargs, ) # See PYTHON-3084. __iter__ = None def __next__(self) -> NoReturn: raise TypeError("'Collection' object is not iterable") next = __next__ def __call__(self, *args: Any, **kwargs: Any) -> NoReturn: """This is only here so that some API misusages are easier to debug.""" if "." not in self.__name: raise TypeError( "'Collection' object is not callable. If you " "meant to call the '%s' method on a 'Database' " "object it is failing because no such method " "exists." % self.__name ) raise TypeError( "'Collection' object is not callable. If you meant to " "call the '%s' method on a 'Collection' object it is " "failing because no such method exists." % self.__name.split(".")[-1] ) mongodb-mongo-python-driver-509e9b7/pymongo/command_cursor.py000066400000000000000000000340001462766011000245070ustar00rootroot00000000000000# Copyright 2014-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. """CommandCursor class to iterate over command results.""" from __future__ import annotations from collections import deque from typing import ( TYPE_CHECKING, Any, Generic, Iterator, Mapping, NoReturn, Optional, Sequence, Union, ) from bson import CodecOptions, _convert_raw_document_lists_to_streams from pymongo.cursor import _CURSOR_CLOSED_ERRORS, _ConnectionManager from pymongo.errors import ConnectionFailure, InvalidOperation, OperationFailure from pymongo.message import _CursorAddress, _GetMore, _OpMsg, _OpReply, _RawBatchGetMore from pymongo.response import PinnedResponse from pymongo.typings import _Address, _DocumentOut, _DocumentType if TYPE_CHECKING: from pymongo.client_session import ClientSession from pymongo.collection import Collection from pymongo.pool import Connection class CommandCursor(Generic[_DocumentType]): """A cursor / iterator over command cursors.""" _getmore_class = _GetMore def __init__( self, collection: Collection[_DocumentType], cursor_info: Mapping[str, Any], address: Optional[_Address], batch_size: int = 0, max_await_time_ms: Optional[int] = None, session: Optional[ClientSession] = None, explicit_session: bool = False, comment: Any = None, ) -> None: """Create a new command cursor.""" self.__sock_mgr: Any = None self.__collection: Collection[_DocumentType] = collection self.__id = cursor_info["id"] self.__data = deque(cursor_info["firstBatch"]) self.__postbatchresumetoken: Optional[Mapping[str, Any]] = cursor_info.get( "postBatchResumeToken" ) self.__address = address self.__batch_size = batch_size self.__max_await_time_ms = max_await_time_ms self.__session = session self.__explicit_session = explicit_session self.__killed = self.__id == 0 self.__comment = comment if self.__killed: self.__end_session(True) if "ns" in cursor_info: # noqa: SIM401 self.__ns = cursor_info["ns"] else: self.__ns = collection.full_name self.batch_size(batch_size) if not isinstance(max_await_time_ms, int) and max_await_time_ms is not None: raise TypeError("max_await_time_ms must be an integer or None") def __del__(self) -> None: self.__die() def __die(self, synchronous: bool = False) -> None: """Closes this cursor.""" already_killed = self.__killed self.__killed = True if self.__id and not already_killed: cursor_id = self.__id assert self.__address is not None address = _CursorAddress(self.__address, self.__ns) else: # Skip killCursors. cursor_id = 0 address = None self.__collection.database.client._cleanup_cursor( synchronous, cursor_id, address, self.__sock_mgr, self.__session, self.__explicit_session, ) if not self.__explicit_session: self.__session = None self.__sock_mgr = None def __end_session(self, synchronous: bool) -> None: if self.__session and not self.__explicit_session: self.__session._end_session(lock=synchronous) self.__session = None def close(self) -> None: """Explicitly close / kill this cursor.""" self.__die(True) def batch_size(self, batch_size: int) -> CommandCursor[_DocumentType]: """Limits the number of documents returned in one batch. Each batch requires a round trip to the server. It can be adjusted to optimize performance and limit data transfer. .. note:: batch_size can not override MongoDB's internal limits on the amount of data it will return to the client in a single batch (i.e if you set batch size to 1,000,000,000, MongoDB will currently only return 4-16MB of results per batch). Raises :exc:`TypeError` if `batch_size` is not an integer. Raises :exc:`ValueError` if `batch_size` is less than ``0``. :param batch_size: The size of each batch of results requested. """ if not isinstance(batch_size, int): raise TypeError("batch_size must be an integer") if batch_size < 0: raise ValueError("batch_size must be >= 0") self.__batch_size = batch_size == 1 and 2 or batch_size return self def _has_next(self) -> bool: """Returns `True` if the cursor has documents remaining from the previous batch. """ return len(self.__data) > 0 @property def _post_batch_resume_token(self) -> Optional[Mapping[str, Any]]: """Retrieve the postBatchResumeToken from the response to a changeStream aggregate or getMore. """ return self.__postbatchresumetoken def _maybe_pin_connection(self, conn: Connection) -> None: client = self.__collection.database.client if not client._should_pin_cursor(self.__session): return if not self.__sock_mgr: conn.pin_cursor() conn_mgr = _ConnectionManager(conn, False) # Ensure the connection gets returned when the entire result is # returned in the first batch. if self.__id == 0: conn_mgr.close() else: self.__sock_mgr = conn_mgr def __send_message(self, operation: _GetMore) -> None: """Send a getmore message and handle the response.""" client = self.__collection.database.client try: response = client._run_operation( operation, self._unpack_response, address=self.__address ) except OperationFailure as exc: if exc.code in _CURSOR_CLOSED_ERRORS: # Don't send killCursors because the cursor is already closed. self.__killed = True if exc.timeout: self.__die(False) else: # Return the session and pinned connection, if necessary. self.close() raise except ConnectionFailure: # Don't send killCursors because the cursor is already closed. self.__killed = True # Return the session and pinned connection, if necessary. self.close() raise except Exception: self.close() raise if isinstance(response, PinnedResponse): if not self.__sock_mgr: self.__sock_mgr = _ConnectionManager(response.conn, response.more_to_come) if response.from_command: cursor = response.docs[0]["cursor"] documents = cursor["nextBatch"] self.__postbatchresumetoken = cursor.get("postBatchResumeToken") self.__id = cursor["id"] else: documents = response.docs assert isinstance(response.data, _OpReply) self.__id = response.data.cursor_id if self.__id == 0: self.close() self.__data = deque(documents) def _unpack_response( self, response: Union[_OpReply, _OpMsg], cursor_id: Optional[int], codec_options: CodecOptions[Mapping[str, Any]], user_fields: Optional[Mapping[str, Any]] = None, legacy_response: bool = False, ) -> Sequence[_DocumentOut]: return response.unpack_response(cursor_id, codec_options, user_fields, legacy_response) def _refresh(self) -> int: """Refreshes the cursor with more data from the server. Returns the length of self.__data after refresh. Will exit early if self.__data is already non-empty. Raises OperationFailure when the cursor cannot be refreshed due to an error on the query. """ if len(self.__data) or self.__killed: return len(self.__data) if self.__id: # Get More dbname, collname = self.__ns.split(".", 1) read_pref = self.__collection._read_preference_for(self.session) self.__send_message( self._getmore_class( dbname, collname, self.__batch_size, self.__id, self.__collection.codec_options, read_pref, self.__session, self.__collection.database.client, self.__max_await_time_ms, self.__sock_mgr, False, self.__comment, ) ) else: # Cursor id is zero nothing else to return self.__die(True) return len(self.__data) @property def alive(self) -> bool: """Does this cursor have the potential to return more data? Even if :attr:`alive` is ``True``, :meth:`next` can raise :exc:`StopIteration`. Best to use a for loop:: for doc in collection.aggregate(pipeline): print(doc) .. note:: :attr:`alive` can be True while iterating a cursor from a failed server. In this case :attr:`alive` will return False after :meth:`next` fails to retrieve the next batch of results from the server. """ return bool(len(self.__data) or (not self.__killed)) @property def cursor_id(self) -> int: """Returns the id of the cursor.""" return self.__id @property def address(self) -> Optional[_Address]: """The (host, port) of the server used, or None. .. versionadded:: 3.0 """ return self.__address @property def session(self) -> Optional[ClientSession]: """The cursor's :class:`~pymongo.client_session.ClientSession`, or None. .. versionadded:: 3.6 """ if self.__explicit_session: return self.__session return None def __iter__(self) -> Iterator[_DocumentType]: return self def next(self) -> _DocumentType: """Advance the cursor.""" # Block until a document is returnable. while self.alive: doc = self._try_next(True) if doc is not None: return doc raise StopIteration __next__ = next def _try_next(self, get_more_allowed: bool) -> Optional[_DocumentType]: """Advance the cursor blocking for at most one getMore command.""" if not len(self.__data) and not self.__killed and get_more_allowed: self._refresh() if len(self.__data): return self.__data.popleft() else: return None def try_next(self) -> Optional[_DocumentType]: """Advance the cursor without blocking indefinitely. This method returns the next document without waiting indefinitely for data. If no document is cached locally then this method runs a single getMore command. If the getMore yields any documents, the next document is returned, otherwise, if the getMore returns no documents (because there is no additional data) then ``None`` is returned. :return: The next document or ``None`` when no document is available after running a single getMore or when the cursor is closed. .. versionadded:: 4.5 """ return self._try_next(get_more_allowed=True) def __enter__(self) -> CommandCursor[_DocumentType]: return self def __exit__(self, exc_type: Any, exc_val: Any, exc_tb: Any) -> None: self.close() class RawBatchCommandCursor(CommandCursor, Generic[_DocumentType]): _getmore_class = _RawBatchGetMore def __init__( self, collection: Collection[_DocumentType], cursor_info: Mapping[str, Any], address: Optional[_Address], batch_size: int = 0, max_await_time_ms: Optional[int] = None, session: Optional[ClientSession] = None, explicit_session: bool = False, comment: Any = None, ) -> None: """Create a new cursor / iterator over raw batches of BSON data. Should not be called directly by application developers - see :meth:`~pymongo.collection.Collection.aggregate_raw_batches` instead. .. seealso:: The MongoDB documentation on `cursors `_. """ assert not cursor_info.get("firstBatch") super().__init__( collection, cursor_info, address, batch_size, max_await_time_ms, session, explicit_session, comment, ) def _unpack_response( # type: ignore[override] self, response: Union[_OpReply, _OpMsg], cursor_id: Optional[int], codec_options: CodecOptions, user_fields: Optional[Mapping[str, Any]] = None, legacy_response: bool = False, ) -> list[Mapping[str, Any]]: raw_response = response.raw_response(cursor_id, user_fields=user_fields) if not legacy_response: # OP_MSG returns firstBatch/nextBatch documents as a BSON array # Re-assemble the array of documents into a document stream _convert_raw_document_lists_to_streams(raw_response[0]) return raw_response # type: ignore[return-value] def __getitem__(self, index: int) -> NoReturn: raise InvalidOperation("Cannot call __getitem__ on RawBatchCursor") mongodb-mongo-python-driver-509e9b7/pymongo/common.py000066400000000000000000001107241462766011000227740ustar00rootroot00000000000000# Copyright 2011-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. """Functions and classes common to multiple pymongo modules.""" from __future__ import annotations import datetime import warnings from collections import OrderedDict, abc from difflib import get_close_matches from typing import ( TYPE_CHECKING, Any, Callable, Iterator, Mapping, MutableMapping, NoReturn, Optional, Sequence, Type, Union, overload, ) from urllib.parse import unquote_plus from bson import SON from bson.binary import UuidRepresentation from bson.codec_options import CodecOptions, DatetimeConversion, TypeRegistry from bson.raw_bson import RawBSONDocument from pymongo.compression_support import ( validate_compressors, validate_zlib_compression_level, ) from pymongo.driver_info import DriverInfo from pymongo.errors import ConfigurationError from pymongo.monitoring import _validate_event_listeners from pymongo.read_concern import ReadConcern from pymongo.read_preferences import _MONGOS_MODES, _ServerMode from pymongo.server_api import ServerApi from pymongo.write_concern import DEFAULT_WRITE_CONCERN, WriteConcern, validate_boolean if TYPE_CHECKING: from pymongo.client_session import ClientSession ORDERED_TYPES: Sequence[Type] = (SON, OrderedDict) # Defaults until we connect to a server and get updated limits. MAX_BSON_SIZE = 16 * (1024**2) MAX_MESSAGE_SIZE: int = 2 * MAX_BSON_SIZE MIN_WIRE_VERSION = 0 MAX_WIRE_VERSION = 0 MAX_WRITE_BATCH_SIZE = 1000 # What this version of PyMongo supports. MIN_SUPPORTED_SERVER_VERSION = "3.6" MIN_SUPPORTED_WIRE_VERSION = 6 MAX_SUPPORTED_WIRE_VERSION = 21 # Frequency to call hello on servers, in seconds. HEARTBEAT_FREQUENCY = 10 # Frequency to clean up unclosed cursors, in seconds. # See MongoClient._process_kill_cursors. KILL_CURSOR_FREQUENCY = 1 # Frequency to process events queue, in seconds. EVENTS_QUEUE_FREQUENCY = 1 # How long to wait, in seconds, for a suitable server to be found before # aborting an operation. For example, if the client attempts an insert # during a replica set election, SERVER_SELECTION_TIMEOUT governs the # longest it is willing to wait for a new primary to be found. SERVER_SELECTION_TIMEOUT = 30 # Spec requires at least 500ms between hello calls. MIN_HEARTBEAT_INTERVAL = 0.5 # Spec requires at least 60s between SRV rescans. MIN_SRV_RESCAN_INTERVAL = 60 # Default connectTimeout in seconds. CONNECT_TIMEOUT = 20.0 # Default value for maxPoolSize. MAX_POOL_SIZE = 100 # Default value for minPoolSize. MIN_POOL_SIZE = 0 # The maximum number of concurrent connection creation attempts per pool. MAX_CONNECTING = 2 # Default value for maxIdleTimeMS. MAX_IDLE_TIME_MS: Optional[int] = None # Default value for maxIdleTimeMS in seconds. MAX_IDLE_TIME_SEC: Optional[int] = None # Default value for waitQueueTimeoutMS in seconds. WAIT_QUEUE_TIMEOUT: Optional[int] = None # Default value for localThresholdMS. LOCAL_THRESHOLD_MS = 15 # Default value for retryWrites. RETRY_WRITES = True # Default value for retryReads. RETRY_READS = True # The error code returned when a command doesn't exist. COMMAND_NOT_FOUND_CODES: Sequence[int] = (59,) # Error codes to ignore if GridFS calls createIndex on a secondary UNAUTHORIZED_CODES: Sequence[int] = (13, 16547, 16548) # Maximum number of sessions to send in a single endSessions command. # From the driver sessions spec. _MAX_END_SESSIONS = 10000 # Default value for srvServiceName SRV_SERVICE_NAME = "mongodb" # Default value for serverMonitoringMode SERVER_MONITORING_MODE = "auto" # poll/stream/auto def partition_node(node: str) -> tuple[str, int]: """Split a host:port string into (host, int(port)) pair.""" host = node port = 27017 idx = node.rfind(":") if idx != -1: host, port = node[:idx], int(node[idx + 1 :]) if host.startswith("["): host = host[1:-1] return host, port def clean_node(node: str) -> tuple[str, int]: """Split and normalize a node name from a hello response.""" host, port = partition_node(node) # Normalize hostname to lowercase, since DNS is case-insensitive: # http://tools.ietf.org/html/rfc4343 # This prevents useless rediscovery if "foo.com" is in the seed list but # "FOO.com" is in the hello response. return host.lower(), port def raise_config_error(key: str, suggestions: Optional[list] = None) -> NoReturn: """Raise ConfigurationError with the given key name.""" msg = f"Unknown option: {key}." if suggestions: msg += f" Did you mean one of ({', '.join(suggestions)}) or maybe a camelCase version of one? Refer to docstring." raise ConfigurationError(msg) # Mapping of URI uuid representation options to valid subtypes. _UUID_REPRESENTATIONS = { "unspecified": UuidRepresentation.UNSPECIFIED, "standard": UuidRepresentation.STANDARD, "pythonLegacy": UuidRepresentation.PYTHON_LEGACY, "javaLegacy": UuidRepresentation.JAVA_LEGACY, "csharpLegacy": UuidRepresentation.CSHARP_LEGACY, } def validate_boolean_or_string(option: str, value: Any) -> bool: """Validates that value is True, False, 'true', or 'false'.""" if isinstance(value, str): if value not in ("true", "false"): raise ValueError(f"The value of {option} must be 'true' or 'false'") return value == "true" return validate_boolean(option, value) def validate_integer(option: str, value: Any) -> int: """Validates that 'value' is an integer (or basestring representation).""" if isinstance(value, int): return value elif isinstance(value, str): try: return int(value) except ValueError: raise ValueError(f"The value of {option} must be an integer") from None raise TypeError(f"Wrong type for {option}, value must be an integer") def validate_positive_integer(option: str, value: Any) -> int: """Validate that 'value' is a positive integer, which does not include 0.""" val = validate_integer(option, value) if val <= 0: raise ValueError(f"The value of {option} must be a positive integer") return val def validate_non_negative_integer(option: str, value: Any) -> int: """Validate that 'value' is a positive integer or 0.""" val = validate_integer(option, value) if val < 0: raise ValueError(f"The value of {option} must be a non negative integer") return val def validate_readable(option: str, value: Any) -> Optional[str]: """Validates that 'value' is file-like and readable.""" if value is None: return value # First make sure its a string py3.3 open(True, 'r') succeeds # Used in ssl cert checking due to poor ssl module error reporting value = validate_string(option, value) open(value).close() return value def validate_positive_integer_or_none(option: str, value: Any) -> Optional[int]: """Validate that 'value' is a positive integer or None.""" if value is None: return value return validate_positive_integer(option, value) def validate_non_negative_integer_or_none(option: str, value: Any) -> Optional[int]: """Validate that 'value' is a positive integer or 0 or None.""" if value is None: return value return validate_non_negative_integer(option, value) def validate_string(option: str, value: Any) -> str: """Validates that 'value' is an instance of `str`.""" if isinstance(value, str): return value raise TypeError(f"Wrong type for {option}, value must be an instance of str") def validate_string_or_none(option: str, value: Any) -> Optional[str]: """Validates that 'value' is an instance of `basestring` or `None`.""" if value is None: return value return validate_string(option, value) def validate_int_or_basestring(option: str, value: Any) -> Union[int, str]: """Validates that 'value' is an integer or string.""" if isinstance(value, int): return value elif isinstance(value, str): try: return int(value) except ValueError: return value raise TypeError(f"Wrong type for {option}, value must be an integer or a string") def validate_non_negative_int_or_basestring(option: Any, value: Any) -> Union[int, str]: """Validates that 'value' is an integer or string.""" if isinstance(value, int): return value elif isinstance(value, str): try: val = int(value) except ValueError: return value return validate_non_negative_integer(option, val) raise TypeError(f"Wrong type for {option}, value must be an non negative integer or a string") def validate_positive_float(option: str, value: Any) -> float: """Validates that 'value' is a float, or can be converted to one, and is positive. """ errmsg = f"{option} must be an integer or float" try: value = float(value) except ValueError: raise ValueError(errmsg) from None except TypeError: raise TypeError(errmsg) from None # float('inf') doesn't work in 2.4 or 2.5 on Windows, so just cap floats at # one billion - this is a reasonable approximation for infinity if not 0 < value < 1e9: raise ValueError(f"{option} must be greater than 0 and less than one billion") return value def validate_positive_float_or_zero(option: str, value: Any) -> float: """Validates that 'value' is 0 or a positive float, or can be converted to 0 or a positive float. """ if value == 0 or value == "0": return 0 return validate_positive_float(option, value) def validate_timeout_or_none(option: str, value: Any) -> Optional[float]: """Validates a timeout specified in milliseconds returning a value in floating point seconds. """ if value is None: return value return validate_positive_float(option, value) / 1000.0 def validate_timeout_or_zero(option: str, value: Any) -> float: """Validates a timeout specified in milliseconds returning a value in floating point seconds for the case where None is an error and 0 is valid. Setting the timeout to nothing in the URI string is a config error. """ if value is None: raise ConfigurationError(f"{option} cannot be None") if value == 0 or value == "0": return 0 return validate_positive_float(option, value) / 1000.0 def validate_timeout_or_none_or_zero(option: Any, value: Any) -> Optional[float]: """Validates a timeout specified in milliseconds returning a value in floating point seconds. value=0 and value="0" are treated the same as value=None which means unlimited timeout. """ if value is None or value == 0 or value == "0": return None return validate_positive_float(option, value) / 1000.0 def validate_timeoutms(option: Any, value: Any) -> Optional[float]: """Validates a timeout specified in milliseconds returning a value in floating point seconds. """ if value is None: return None return validate_positive_float_or_zero(option, value) / 1000.0 def validate_max_staleness(option: str, value: Any) -> int: """Validates maxStalenessSeconds according to the Max Staleness Spec.""" if value == -1 or value == "-1": # Default: No maximum staleness. return -1 return validate_positive_integer(option, value) def validate_read_preference(dummy: Any, value: Any) -> _ServerMode: """Validate a read preference.""" if not isinstance(value, _ServerMode): raise TypeError(f"{value!r} is not a read preference.") return value def validate_read_preference_mode(dummy: Any, value: Any) -> _ServerMode: """Validate read preference mode for a MongoClient. .. versionchanged:: 3.5 Returns the original ``value`` instead of the validated read preference mode. """ if value not in _MONGOS_MODES: raise ValueError(f"{value} is not a valid read preference") return value def validate_auth_mechanism(option: str, value: Any) -> str: """Validate the authMechanism URI option.""" from pymongo.auth import MECHANISMS if value not in MECHANISMS: raise ValueError(f"{option} must be in {tuple(MECHANISMS)}") return value def validate_uuid_representation(dummy: Any, value: Any) -> int: """Validate the uuid representation option selected in the URI.""" try: return _UUID_REPRESENTATIONS[value] except KeyError: raise ValueError( f"{value} is an invalid UUID representation. " "Must be one of " f"{tuple(_UUID_REPRESENTATIONS)}" ) from None def validate_read_preference_tags(name: str, value: Any) -> list[dict[str, str]]: """Parse readPreferenceTags if passed as a client kwarg.""" if not isinstance(value, list): value = [value] tag_sets: list = [] for tag_set in value: if tag_set == "": tag_sets.append({}) continue try: tags = {} for tag in tag_set.split(","): key, val = tag.split(":") tags[unquote_plus(key)] = unquote_plus(val) tag_sets.append(tags) except Exception: raise ValueError(f"{tag_set!r} not a valid value for {name}") from None return tag_sets _MECHANISM_PROPS = frozenset( [ "SERVICE_NAME", "CANONICALIZE_HOST_NAME", "SERVICE_REALM", "AWS_SESSION_TOKEN", "ENVIRONMENT", "TOKEN_RESOURCE", ] ) def validate_auth_mechanism_properties(option: str, value: Any) -> dict[str, Union[bool, str]]: """Validate authMechanismProperties.""" props: dict[str, Any] = {} if not isinstance(value, str): if not isinstance(value, dict): raise ValueError("Auth mechanism properties must be given as a string or a dictionary") for key, value in value.items(): # noqa: B020 if isinstance(value, str): props[key] = value elif isinstance(value, bool): props[key] = str(value).lower() elif key in ["ALLOWED_HOSTS"] and isinstance(value, list): props[key] = value elif key in ["OIDC_CALLBACK", "OIDC_HUMAN_CALLBACK"]: from pymongo.auth_oidc import OIDCCallback if not isinstance(value, OIDCCallback): raise ValueError("callback must be an OIDCCallback object") props[key] = value else: raise ValueError(f"Invalid type for auth mechanism property {key}, {type(value)}") return props value = validate_string(option, value) for opt in value.split(","): key, _, val = opt.partition(":") if key not in _MECHANISM_PROPS: # Try not to leak the token. if "AWS_SESSION_TOKEN" in key: raise ValueError( "auth mechanism properties must be " "key:value pairs like AWS_SESSION_TOKEN:" ) raise ValueError( f"{key} is not a supported auth " "mechanism property. Must be one of " f"{tuple(_MECHANISM_PROPS)}." ) if key == "CANONICALIZE_HOST_NAME": props[key] = validate_boolean_or_string(key, val) else: props[key] = unquote_plus(val) return props def validate_document_class( option: str, value: Any ) -> Union[Type[MutableMapping], Type[RawBSONDocument]]: """Validate the document_class option.""" # issubclass can raise TypeError for generic aliases like SON[str, Any]. # In that case we can use the base class for the comparison. is_mapping = False try: is_mapping = issubclass(value, abc.MutableMapping) except TypeError: if hasattr(value, "__origin__"): is_mapping = issubclass(value.__origin__, abc.MutableMapping) if not is_mapping and not issubclass(value, RawBSONDocument): raise TypeError( f"{option} must be dict, bson.son.SON, " "bson.raw_bson.RawBSONDocument, or a " "subclass of collections.MutableMapping" ) return value def validate_type_registry(option: Any, value: Any) -> Optional[TypeRegistry]: """Validate the type_registry option.""" if value is not None and not isinstance(value, TypeRegistry): raise TypeError(f"{option} must be an instance of {TypeRegistry}") return value def validate_list(option: str, value: Any) -> list: """Validates that 'value' is a list.""" if not isinstance(value, list): raise TypeError(f"{option} must be a list") return value def validate_list_or_none(option: Any, value: Any) -> Optional[list]: """Validates that 'value' is a list or None.""" if value is None: return value return validate_list(option, value) def validate_list_or_mapping(option: Any, value: Any) -> None: """Validates that 'value' is a list or a document.""" if not isinstance(value, (abc.Mapping, list)): raise TypeError( f"{option} must either be a list or an instance of dict, " "bson.son.SON, or any other type that inherits from " "collections.Mapping" ) def validate_is_mapping(option: str, value: Any) -> None: """Validate the type of method arguments that expect a document.""" if not isinstance(value, abc.Mapping): raise TypeError( f"{option} must be an instance of dict, bson.son.SON, or " "any other type that inherits from " "collections.Mapping" ) def validate_is_document_type(option: str, value: Any) -> None: """Validate the type of method arguments that expect a MongoDB document.""" if not isinstance(value, (abc.MutableMapping, RawBSONDocument)): raise TypeError( f"{option} must be an instance of dict, bson.son.SON, " "bson.raw_bson.RawBSONDocument, or " "a type that inherits from " "collections.MutableMapping" ) def validate_appname_or_none(option: str, value: Any) -> Optional[str]: """Validate the appname option.""" if value is None: return value validate_string(option, value) # We need length in bytes, so encode utf8 first. if len(value.encode("utf-8")) > 128: raise ValueError(f"{option} must be <= 128 bytes") return value def validate_driver_or_none(option: Any, value: Any) -> Optional[DriverInfo]: """Validate the driver keyword arg.""" if value is None: return value if not isinstance(value, DriverInfo): raise TypeError(f"{option} must be an instance of DriverInfo") return value def validate_server_api_or_none(option: Any, value: Any) -> Optional[ServerApi]: """Validate the server_api keyword arg.""" if value is None: return value if not isinstance(value, ServerApi): raise TypeError(f"{option} must be an instance of ServerApi") return value def validate_is_callable_or_none(option: Any, value: Any) -> Optional[Callable]: """Validates that 'value' is a callable.""" if value is None: return value if not callable(value): raise ValueError(f"{option} must be a callable") return value def validate_ok_for_replace(replacement: Mapping[str, Any]) -> None: """Validate a replacement document.""" validate_is_mapping("replacement", replacement) # Replacement can be {} if replacement and not isinstance(replacement, RawBSONDocument): first = next(iter(replacement)) if first.startswith("$"): raise ValueError("replacement can not include $ operators") def validate_ok_for_update(update: Any) -> None: """Validate an update document.""" validate_list_or_mapping("update", update) # Update cannot be {}. if not update: raise ValueError("update cannot be empty") is_document = not isinstance(update, list) first = next(iter(update)) if is_document and not first.startswith("$"): raise ValueError("update only works with $ operators") _UNICODE_DECODE_ERROR_HANDLERS = frozenset(["strict", "replace", "ignore"]) def validate_unicode_decode_error_handler(dummy: Any, value: str) -> str: """Validate the Unicode decode error handler option of CodecOptions.""" if value not in _UNICODE_DECODE_ERROR_HANDLERS: raise ValueError( f"{value} is an invalid Unicode decode error handler. " "Must be one of " f"{tuple(_UNICODE_DECODE_ERROR_HANDLERS)}" ) return value def validate_tzinfo(dummy: Any, value: Any) -> Optional[datetime.tzinfo]: """Validate the tzinfo option""" if value is not None and not isinstance(value, datetime.tzinfo): raise TypeError("%s must be an instance of datetime.tzinfo" % value) return value def validate_auto_encryption_opts_or_none(option: Any, value: Any) -> Optional[Any]: """Validate the driver keyword arg.""" if value is None: return value from pymongo.encryption_options import AutoEncryptionOpts if not isinstance(value, AutoEncryptionOpts): raise TypeError(f"{option} must be an instance of AutoEncryptionOpts") return value def validate_datetime_conversion(option: Any, value: Any) -> Optional[DatetimeConversion]: """Validate a DatetimeConversion string.""" if value is None: return DatetimeConversion.DATETIME if isinstance(value, str): if value.isdigit(): return DatetimeConversion(int(value)) return DatetimeConversion[value] elif isinstance(value, int): return DatetimeConversion(value) raise TypeError(f"{option} must be a str or int representing DatetimeConversion") def validate_server_monitoring_mode(option: str, value: str) -> str: """Validate the serverMonitoringMode option.""" if value not in {"auto", "stream", "poll"}: raise ValueError( f'{option}={value!r} is invalid. Must be one of "auto", "stream", or "poll"' ) return value # Dictionary where keys are the names of public URI options, and values # are lists of aliases for that option. URI_OPTIONS_ALIAS_MAP: dict[str, list[str]] = { "tls": ["ssl"], } # Dictionary where keys are the names of URI options, and values # are functions that validate user-input values for that option. If an option # alias uses a different validator than its public counterpart, it should be # included here as a key, value pair. URI_OPTIONS_VALIDATOR_MAP: dict[str, Callable[[Any, Any], Any]] = { "appname": validate_appname_or_none, "authmechanism": validate_auth_mechanism, "authmechanismproperties": validate_auth_mechanism_properties, "authsource": validate_string, "compressors": validate_compressors, "connecttimeoutms": validate_timeout_or_none_or_zero, "directconnection": validate_boolean_or_string, "heartbeatfrequencyms": validate_timeout_or_none, "journal": validate_boolean_or_string, "localthresholdms": validate_positive_float_or_zero, "maxidletimems": validate_timeout_or_none, "maxconnecting": validate_positive_integer, "maxpoolsize": validate_non_negative_integer_or_none, "maxstalenessseconds": validate_max_staleness, "readconcernlevel": validate_string_or_none, "readpreference": validate_read_preference_mode, "readpreferencetags": validate_read_preference_tags, "replicaset": validate_string_or_none, "retryreads": validate_boolean_or_string, "retrywrites": validate_boolean_or_string, "loadbalanced": validate_boolean_or_string, "serverselectiontimeoutms": validate_timeout_or_zero, "sockettimeoutms": validate_timeout_or_none_or_zero, "tls": validate_boolean_or_string, "tlsallowinvalidcertificates": validate_boolean_or_string, "tlsallowinvalidhostnames": validate_boolean_or_string, "tlscafile": validate_readable, "tlscertificatekeyfile": validate_readable, "tlscertificatekeyfilepassword": validate_string_or_none, "tlsdisableocspendpointcheck": validate_boolean_or_string, "tlsinsecure": validate_boolean_or_string, "w": validate_non_negative_int_or_basestring, "wtimeoutms": validate_non_negative_integer, "zlibcompressionlevel": validate_zlib_compression_level, "srvservicename": validate_string, "srvmaxhosts": validate_non_negative_integer, "timeoutms": validate_timeoutms, "servermonitoringmode": validate_server_monitoring_mode, } # Dictionary where keys are the names of URI options specific to pymongo, # and values are functions that validate user-input values for those options. NONSPEC_OPTIONS_VALIDATOR_MAP: dict[str, Callable[[Any, Any], Any]] = { "connect": validate_boolean_or_string, "driver": validate_driver_or_none, "server_api": validate_server_api_or_none, "fsync": validate_boolean_or_string, "minpoolsize": validate_non_negative_integer, "tlscrlfile": validate_readable, "tz_aware": validate_boolean_or_string, "unicode_decode_error_handler": validate_unicode_decode_error_handler, "uuidrepresentation": validate_uuid_representation, "waitqueuemultiple": validate_non_negative_integer_or_none, "waitqueuetimeoutms": validate_timeout_or_none, "datetime_conversion": validate_datetime_conversion, } # Dictionary where keys are the names of keyword-only options for the # MongoClient constructor, and values are functions that validate user-input # values for those options. KW_VALIDATORS: dict[str, Callable[[Any, Any], Any]] = { "document_class": validate_document_class, "type_registry": validate_type_registry, "read_preference": validate_read_preference, "event_listeners": _validate_event_listeners, "tzinfo": validate_tzinfo, "username": validate_string_or_none, "password": validate_string_or_none, "server_selector": validate_is_callable_or_none, "auto_encryption_opts": validate_auto_encryption_opts_or_none, "authoidcallowedhosts": validate_list, } # Dictionary where keys are any URI option name, and values are the # internally-used names of that URI option. Options with only one name # variant need not be included here. Options whose public and internal # names are the same need not be included here. INTERNAL_URI_OPTION_NAME_MAP: dict[str, str] = { "ssl": "tls", } # Map from deprecated URI option names to a tuple indicating the method of # their deprecation and any additional information that may be needed to # construct the warning message. URI_OPTIONS_DEPRECATION_MAP: dict[str, tuple[str, str]] = { # format: : (, ), # Supported values: # - 'renamed': should be the new option name. Note that case is # preserved for renamed options as they are part of user warnings. # - 'removed': may suggest the rationale for deprecating the # option and/or recommend remedial action. # For example: # 'wtimeout': ('renamed', 'wTimeoutMS'), } # Augment the option validator map with pymongo-specific option information. URI_OPTIONS_VALIDATOR_MAP.update(NONSPEC_OPTIONS_VALIDATOR_MAP) for optname, aliases in URI_OPTIONS_ALIAS_MAP.items(): for alias in aliases: if alias not in URI_OPTIONS_VALIDATOR_MAP: URI_OPTIONS_VALIDATOR_MAP[alias] = URI_OPTIONS_VALIDATOR_MAP[optname] # Map containing all URI option and keyword argument validators. VALIDATORS: dict[str, Callable[[Any, Any], Any]] = URI_OPTIONS_VALIDATOR_MAP.copy() VALIDATORS.update(KW_VALIDATORS) # List of timeout-related options. TIMEOUT_OPTIONS: list[str] = [ "connecttimeoutms", "heartbeatfrequencyms", "maxidletimems", "maxstalenessseconds", "serverselectiontimeoutms", "sockettimeoutms", "waitqueuetimeoutms", ] _AUTH_OPTIONS = frozenset(["authmechanismproperties"]) def validate_auth_option(option: str, value: Any) -> tuple[str, Any]: """Validate optional authentication parameters.""" lower, value = validate(option, value) if lower not in _AUTH_OPTIONS: raise ConfigurationError(f"Unknown option: {option}. Must be in {_AUTH_OPTIONS}") return option, value def _get_validator( key: str, validators: dict[str, Callable[[Any, Any], Any]], normed_key: Optional[str] = None ) -> Callable: normed_key = normed_key or key try: return validators[normed_key] except KeyError: suggestions = get_close_matches(normed_key, validators, cutoff=0.2) raise_config_error(key, suggestions) def validate(option: str, value: Any) -> tuple[str, Any]: """Generic validation function.""" validator = _get_validator(option, VALIDATORS, normed_key=option.lower()) value = validator(option, value) return option, value def get_validated_options( options: Mapping[str, Any], warn: bool = True ) -> MutableMapping[str, Any]: """Validate each entry in options and raise a warning if it is not valid. Returns a copy of options with invalid entries removed. :param opts: A dict containing MongoDB URI options. :param warn: If ``True`` then warnings will be logged and invalid options will be ignored. Otherwise, invalid options will cause errors. """ validated_options: MutableMapping[str, Any] if isinstance(options, _CaseInsensitiveDictionary): validated_options = _CaseInsensitiveDictionary() def get_normed_key(x: str) -> str: return x def get_setter_key(x: str) -> str: return options.cased_key(x) # type: ignore[attr-defined] else: validated_options = {} def get_normed_key(x: str) -> str: return x.lower() def get_setter_key(x: str) -> str: return x for opt, value in options.items(): normed_key = get_normed_key(opt) try: validator = _get_validator(opt, URI_OPTIONS_VALIDATOR_MAP, normed_key=normed_key) validated = validator(opt, value) except (ValueError, TypeError, ConfigurationError) as exc: if warn: warnings.warn(str(exc), stacklevel=2) else: raise else: validated_options[get_setter_key(normed_key)] = validated return validated_options def _esc_coll_name(encrypted_fields: Mapping[str, Any], name: str) -> Any: return encrypted_fields.get("escCollection", f"enxcol_.{name}.esc") def _ecoc_coll_name(encrypted_fields: Mapping[str, Any], name: str) -> Any: return encrypted_fields.get("ecocCollection", f"enxcol_.{name}.ecoc") # List of write-concern-related options. WRITE_CONCERN_OPTIONS = frozenset(["w", "wtimeout", "wtimeoutms", "fsync", "j", "journal"]) class BaseObject: """A base class that provides attributes and methods common to multiple pymongo classes. SHOULD NOT BE USED BY DEVELOPERS EXTERNAL TO MONGODB. """ def __init__( self, codec_options: CodecOptions, read_preference: _ServerMode, write_concern: WriteConcern, read_concern: ReadConcern, ) -> None: if not isinstance(codec_options, CodecOptions): raise TypeError("codec_options must be an instance of bson.codec_options.CodecOptions") self.__codec_options = codec_options if not isinstance(read_preference, _ServerMode): raise TypeError( f"{read_preference!r} is not valid for read_preference. See " "pymongo.read_preferences for valid " "options." ) self.__read_preference = read_preference if not isinstance(write_concern, WriteConcern): raise TypeError( "write_concern must be an instance of pymongo.write_concern.WriteConcern" ) self.__write_concern = write_concern if not isinstance(read_concern, ReadConcern): raise TypeError("read_concern must be an instance of pymongo.read_concern.ReadConcern") self.__read_concern = read_concern @property def codec_options(self) -> CodecOptions: """Read only access to the :class:`~bson.codec_options.CodecOptions` of this instance. """ return self.__codec_options @property def write_concern(self) -> WriteConcern: """Read only access to the :class:`~pymongo.write_concern.WriteConcern` of this instance. .. versionchanged:: 3.0 The :attr:`write_concern` attribute is now read only. """ return self.__write_concern def _write_concern_for(self, session: Optional[ClientSession]) -> WriteConcern: """Read only access to the write concern of this instance or session.""" # Override this operation's write concern with the transaction's. if session and session.in_transaction: return DEFAULT_WRITE_CONCERN return self.write_concern @property def read_preference(self) -> _ServerMode: """Read only access to the read preference of this instance. .. versionchanged:: 3.0 The :attr:`read_preference` attribute is now read only. """ return self.__read_preference def _read_preference_for(self, session: Optional[ClientSession]) -> _ServerMode: """Read only access to the read preference of this instance or session.""" # Override this operation's read preference with the transaction's. if session: return session._txn_read_preference() or self.__read_preference return self.__read_preference @property def read_concern(self) -> ReadConcern: """Read only access to the :class:`~pymongo.read_concern.ReadConcern` of this instance. .. versionadded:: 3.2 """ return self.__read_concern class _CaseInsensitiveDictionary(MutableMapping[str, Any]): def __init__(self, *args: Any, **kwargs: Any): self.__casedkeys: dict[str, Any] = {} self.__data: dict[str, Any] = {} self.update(dict(*args, **kwargs)) def __contains__(self, key: str) -> bool: # type: ignore[override] return key.lower() in self.__data def __len__(self) -> int: return len(self.__data) def __iter__(self) -> Iterator[str]: return (key for key in self.__casedkeys) def __repr__(self) -> str: return str({self.__casedkeys[k]: self.__data[k] for k in self}) def __setitem__(self, key: str, value: Any) -> None: lc_key = key.lower() self.__casedkeys[lc_key] = key self.__data[lc_key] = value def __getitem__(self, key: str) -> Any: return self.__data[key.lower()] def __delitem__(self, key: str) -> None: lc_key = key.lower() del self.__casedkeys[lc_key] del self.__data[lc_key] def __eq__(self, other: Any) -> bool: if not isinstance(other, abc.Mapping): return NotImplemented if len(self) != len(other): return False for key in other: # noqa: SIM110 if self[key] != other[key]: return False return True def get(self, key: str, default: Optional[Any] = None) -> Any: return self.__data.get(key.lower(), default) def pop(self, key: str, *args: Any, **kwargs: Any) -> Any: lc_key = key.lower() self.__casedkeys.pop(lc_key, None) return self.__data.pop(lc_key, *args, **kwargs) def popitem(self) -> tuple[str, Any]: lc_key, cased_key = self.__casedkeys.popitem() value = self.__data.pop(lc_key) return cased_key, value def clear(self) -> None: self.__casedkeys.clear() self.__data.clear() @overload def setdefault(self, key: str, default: None = None) -> Optional[Any]: ... @overload def setdefault(self, key: str, default: Any) -> Any: ... def setdefault(self, key: str, default: Optional[Any] = None) -> Optional[Any]: lc_key = key.lower() if key in self: return self.__data[lc_key] else: self.__casedkeys[lc_key] = key self.__data[lc_key] = default return default def update(self, other: Mapping[str, Any]) -> None: # type: ignore[override] if isinstance(other, _CaseInsensitiveDictionary): for key in other: self[other.cased_key(key)] = other[key] else: for key in other: self[key] = other[key] def cased_key(self, key: str) -> Any: return self.__casedkeys[key.lower()] mongodb-mongo-python-driver-509e9b7/pymongo/compression_support.py000066400000000000000000000123571462766011000256440ustar00rootroot00000000000000# Copyright 2018 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. from __future__ import annotations import warnings from typing import Any, Iterable, Optional, Union from pymongo.hello import HelloCompat from pymongo.helpers import _SENSITIVE_COMMANDS _SUPPORTED_COMPRESSORS = {"snappy", "zlib", "zstd"} _NO_COMPRESSION = {HelloCompat.CMD, HelloCompat.LEGACY_CMD} _NO_COMPRESSION.update(_SENSITIVE_COMMANDS) def _have_snappy() -> bool: try: import snappy # type:ignore[import] # noqa: F401 return True except ImportError: return False def _have_zlib() -> bool: try: import zlib # noqa: F401 return True except ImportError: return False def _have_zstd() -> bool: try: import zstandard # noqa: F401 return True except ImportError: return False def validate_compressors(dummy: Any, value: Union[str, Iterable[str]]) -> list[str]: try: # `value` is string. compressors = value.split(",") # type: ignore[union-attr] except AttributeError: # `value` is an iterable. compressors = list(value) for compressor in compressors[:]: if compressor not in _SUPPORTED_COMPRESSORS: compressors.remove(compressor) warnings.warn(f"Unsupported compressor: {compressor}", stacklevel=2) elif compressor == "snappy" and not _have_snappy(): compressors.remove(compressor) warnings.warn( "Wire protocol compression with snappy is not available. " "You must install the python-snappy module for snappy support.", stacklevel=2, ) elif compressor == "zlib" and not _have_zlib(): compressors.remove(compressor) warnings.warn( "Wire protocol compression with zlib is not available. " "The zlib module is not available.", stacklevel=2, ) elif compressor == "zstd" and not _have_zstd(): compressors.remove(compressor) warnings.warn( "Wire protocol compression with zstandard is not available. " "You must install the zstandard module for zstandard support.", stacklevel=2, ) return compressors def validate_zlib_compression_level(option: str, value: Any) -> int: try: level = int(value) except Exception: raise TypeError(f"{option} must be an integer, not {value!r}.") from None if level < -1 or level > 9: raise ValueError("%s must be between -1 and 9, not %d." % (option, level)) return level class CompressionSettings: def __init__(self, compressors: list[str], zlib_compression_level: int): self.compressors = compressors self.zlib_compression_level = zlib_compression_level def get_compression_context( self, compressors: Optional[list[str]] ) -> Union[SnappyContext, ZlibContext, ZstdContext, None]: if compressors: chosen = compressors[0] if chosen == "snappy": return SnappyContext() elif chosen == "zlib": return ZlibContext(self.zlib_compression_level) elif chosen == "zstd": return ZstdContext() return None return None class SnappyContext: compressor_id = 1 @staticmethod def compress(data: bytes) -> bytes: import snappy return snappy.compress(data) class ZlibContext: compressor_id = 2 def __init__(self, level: int): self.level = level def compress(self, data: bytes) -> bytes: import zlib return zlib.compress(data, self.level) class ZstdContext: compressor_id = 3 @staticmethod def compress(data: bytes) -> bytes: # ZstdCompressor is not thread safe. # TODO: Use a pool? import zstandard return zstandard.ZstdCompressor().compress(data) def decompress(data: bytes, compressor_id: int) -> bytes: if compressor_id == SnappyContext.compressor_id: # python-snappy doesn't support the buffer interface. # https://github.com/andrix/python-snappy/issues/65 # This only matters when data is a memoryview since # id(bytes(data)) == id(data) when data is a bytes. import snappy return snappy.uncompress(bytes(data)) elif compressor_id == ZlibContext.compressor_id: import zlib return zlib.decompress(data) elif compressor_id == ZstdContext.compressor_id: # ZstdDecompressor is not thread safe. # TODO: Use a pool? import zstandard return zstandard.ZstdDecompressor().decompress(data) else: raise ValueError("Unknown compressorId %d" % (compressor_id,)) mongodb-mongo-python-driver-509e9b7/pymongo/cursor.py000066400000000000000000001423451462766011000230250ustar00rootroot00000000000000# Copyright 2009-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. """Cursor class to iterate over Mongo query results.""" from __future__ import annotations import copy import warnings from collections import deque from typing import ( TYPE_CHECKING, Any, Generic, Iterable, List, Mapping, NoReturn, Optional, Sequence, Tuple, Union, cast, overload, ) from bson import RE_TYPE, _convert_raw_document_lists_to_streams from bson.code import Code from bson.son import SON from pymongo import helpers from pymongo.collation import validate_collation_or_none from pymongo.common import ( validate_is_document_type, validate_is_mapping, ) from pymongo.errors import ConnectionFailure, InvalidOperation, OperationFailure from pymongo.lock import _create_lock from pymongo.message import ( _CursorAddress, _GetMore, _OpMsg, _OpReply, _Query, _RawBatchGetMore, _RawBatchQuery, ) from pymongo.response import PinnedResponse from pymongo.typings import _Address, _CollationIn, _DocumentOut, _DocumentType from pymongo.write_concern import validate_boolean if TYPE_CHECKING: from _typeshed import SupportsItems from bson.codec_options import CodecOptions from pymongo.client_session import ClientSession from pymongo.collection import Collection from pymongo.pool import Connection from pymongo.read_preferences import _ServerMode # These errors mean that the server has already killed the cursor so there is # no need to send killCursors. _CURSOR_CLOSED_ERRORS = frozenset( [ 43, # CursorNotFound 175, # QueryPlanKilled 237, # CursorKilled # On a tailable cursor, the following errors mean the capped collection # rolled over. # MongoDB 2.6: # {'$err': 'Runner killed during getMore', 'code': 28617, 'ok': 0} 28617, # MongoDB 3.0: # {'$err': 'getMore executor error: UnknownError no details available', # 'code': 17406, 'ok': 0} 17406, # MongoDB 3.2 + 3.4: # {'ok': 0.0, 'errmsg': 'GetMore command executor error: # CappedPositionLost: CollectionScan died due to failure to restore # tailable cursor position. Last seen record id: RecordId(3)', # 'code': 96} 96, # MongoDB 3.6+: # {'ok': 0.0, 'errmsg': 'errmsg: "CollectionScan died due to failure to # restore tailable cursor position. Last seen record id: RecordId(3)"', # 'code': 136, 'codeName': 'CappedPositionLost'} 136, ] ) _QUERY_OPTIONS = { "tailable_cursor": 2, "secondary_okay": 4, "oplog_replay": 8, "no_timeout": 16, "await_data": 32, "exhaust": 64, "partial": 128, } class CursorType: NON_TAILABLE = 0 """The standard cursor type.""" TAILABLE = _QUERY_OPTIONS["tailable_cursor"] """The tailable cursor type. Tailable cursors are only for use with capped collections. They are not closed when the last data is retrieved but are kept open and the cursor location marks the final document position. If more data is received iteration of the cursor will continue from the last document received. """ TAILABLE_AWAIT = TAILABLE | _QUERY_OPTIONS["await_data"] """A tailable cursor with the await option set. Creates a tailable cursor that will wait for a few seconds after returning the full result set so that it can capture and return additional data added during the query. """ EXHAUST = _QUERY_OPTIONS["exhaust"] """An exhaust cursor. MongoDB will stream batched results to the client without waiting for the client to request each batch, reducing latency. """ class _ConnectionManager: """Used with exhaust cursors to ensure the connection is returned.""" def __init__(self, conn: Connection, more_to_come: bool): self.conn: Optional[Connection] = conn self.more_to_come = more_to_come self.lock = _create_lock() def update_exhaust(self, more_to_come: bool) -> None: self.more_to_come = more_to_come def close(self) -> None: """Return this instance's connection to the connection pool.""" if self.conn: self.conn.unpin() self.conn = None _Sort = Union[ Sequence[Union[str, Tuple[str, Union[int, str, Mapping[str, Any]]]]], Mapping[str, Any] ] _Hint = Union[str, _Sort] class Cursor(Generic[_DocumentType]): """A cursor / iterator over Mongo query results.""" _query_class = _Query _getmore_class = _GetMore def __init__( self, collection: Collection[_DocumentType], filter: Optional[Mapping[str, Any]] = None, projection: Optional[Union[Mapping[str, Any], Iterable[str]]] = None, skip: int = 0, limit: int = 0, no_cursor_timeout: bool = False, cursor_type: int = CursorType.NON_TAILABLE, sort: Optional[_Sort] = None, allow_partial_results: bool = False, oplog_replay: bool = False, batch_size: int = 0, collation: Optional[_CollationIn] = None, hint: Optional[_Hint] = None, max_scan: Optional[int] = None, max_time_ms: Optional[int] = None, max: Optional[_Sort] = None, min: Optional[_Sort] = None, return_key: Optional[bool] = None, show_record_id: Optional[bool] = None, snapshot: Optional[bool] = None, comment: Optional[Any] = None, session: Optional[ClientSession] = None, allow_disk_use: Optional[bool] = None, let: Optional[bool] = None, ) -> None: """Create a new cursor. Should not be called directly by application developers - see :meth:`~pymongo.collection.Collection.find` instead. .. seealso:: The MongoDB documentation on `cursors `_. """ # Initialize all attributes used in __del__ before possibly raising # an error to avoid attribute errors during garbage collection. self.__collection: Collection[_DocumentType] = collection self.__id: Any = None self.__exhaust = False self.__sock_mgr: Any = None self.__killed = False self.__session: Optional[ClientSession] if session: self.__session = session self.__explicit_session = True else: self.__session = None self.__explicit_session = False spec: Mapping[str, Any] = filter or {} validate_is_mapping("filter", spec) if not isinstance(skip, int): raise TypeError("skip must be an instance of int") if not isinstance(limit, int): raise TypeError("limit must be an instance of int") validate_boolean("no_cursor_timeout", no_cursor_timeout) if no_cursor_timeout and not self.__explicit_session: warnings.warn( "use an explicit session with no_cursor_timeout=True " "otherwise the cursor may still timeout after " "30 minutes, for more info see " "https://mongodb.com/docs/v4.4/reference/method/" "cursor.noCursorTimeout/" "#session-idle-timeout-overrides-nocursortimeout", UserWarning, stacklevel=2, ) if cursor_type not in ( CursorType.NON_TAILABLE, CursorType.TAILABLE, CursorType.TAILABLE_AWAIT, CursorType.EXHAUST, ): raise ValueError("not a valid value for cursor_type") validate_boolean("allow_partial_results", allow_partial_results) validate_boolean("oplog_replay", oplog_replay) if not isinstance(batch_size, int): raise TypeError("batch_size must be an integer") if batch_size < 0: raise ValueError("batch_size must be >= 0") # Only set if allow_disk_use is provided by the user, else None. if allow_disk_use is not None: allow_disk_use = validate_boolean("allow_disk_use", allow_disk_use) if projection is not None: projection = helpers._fields_list_to_dict(projection, "projection") if let is not None: validate_is_document_type("let", let) self.__let = let self.__spec = spec self.__has_filter = filter is not None self.__projection = projection self.__skip = skip self.__limit = limit self.__batch_size = batch_size self.__ordering = sort and helpers._index_document(sort) or None self.__max_scan = max_scan self.__explain = False self.__comment = comment self.__max_time_ms = max_time_ms self.__max_await_time_ms: Optional[int] = None self.__max: Optional[Union[dict[Any, Any], _Sort]] = max self.__min: Optional[Union[dict[Any, Any], _Sort]] = min self.__collation = validate_collation_or_none(collation) self.__return_key = return_key self.__show_record_id = show_record_id self.__allow_disk_use = allow_disk_use self.__snapshot = snapshot self.__hint: Union[str, dict[str, Any], None] self.__set_hint(hint) # Exhaust cursor support if cursor_type == CursorType.EXHAUST: if self.__collection.database.client.is_mongos: raise InvalidOperation("Exhaust cursors are not supported by mongos") if limit: raise InvalidOperation("Can't use limit and exhaust together.") self.__exhaust = True # This is ugly. People want to be able to do cursor[5:5] and # get an empty result set (old behavior was an # exception). It's hard to do that right, though, because the # server uses limit(0) to mean 'no limit'. So we set __empty # in that case and check for it when iterating. We also unset # it anytime we change __limit. self.__empty = False self.__data: deque = deque() self.__address: Optional[_Address] = None self.__retrieved = 0 self.__codec_options = collection.codec_options # Read preference is set when the initial find is sent. self.__read_preference: Optional[_ServerMode] = None self.__read_concern = collection.read_concern self.__query_flags = cursor_type if no_cursor_timeout: self.__query_flags |= _QUERY_OPTIONS["no_timeout"] if allow_partial_results: self.__query_flags |= _QUERY_OPTIONS["partial"] if oplog_replay: self.__query_flags |= _QUERY_OPTIONS["oplog_replay"] # The namespace to use for find/getMore commands. self.__dbname = collection.database.name self.__collname = collection.name @property def collection(self) -> Collection[_DocumentType]: """The :class:`~pymongo.collection.Collection` that this :class:`Cursor` is iterating. """ return self.__collection @property def retrieved(self) -> int: """The number of documents retrieved so far.""" return self.__retrieved def __del__(self) -> None: self.__die() def rewind(self) -> Cursor[_DocumentType]: """Rewind this cursor to its unevaluated state. Reset this cursor if it has been partially or completely evaluated. Any options that are present on the cursor will remain in effect. Future iterating performed on this cursor will cause new queries to be sent to the server, even if the resultant data has already been retrieved by this cursor. """ self.close() self.__data = deque() self.__id = None self.__address = None self.__retrieved = 0 self.__killed = False return self def clone(self) -> Cursor[_DocumentType]: """Get a clone of this cursor. Returns a new Cursor instance with options matching those that have been set on the current instance. The clone will be completely unevaluated, even if the current instance has been partially or completely evaluated. """ return self._clone(True) def _clone(self, deepcopy: bool = True, base: Optional[Cursor] = None) -> Cursor: """Internal clone helper.""" if not base: if self.__explicit_session: base = self._clone_base(self.__session) else: base = self._clone_base(None) values_to_clone = ( "spec", "projection", "skip", "limit", "max_time_ms", "max_await_time_ms", "comment", "max", "min", "ordering", "explain", "hint", "batch_size", "max_scan", "query_flags", "collation", "empty", "show_record_id", "return_key", "allow_disk_use", "snapshot", "exhaust", "has_filter", ) data = { k: v for k, v in self.__dict__.items() if k.startswith("_Cursor__") and k[9:] in values_to_clone } if deepcopy: data = self._deepcopy(data) base.__dict__.update(data) return base def _clone_base(self, session: Optional[ClientSession]) -> Cursor: """Creates an empty Cursor object for information to be copied into.""" return self.__class__(self.__collection, session=session) def __die(self, synchronous: bool = False) -> None: """Closes this cursor.""" try: already_killed = self.__killed except AttributeError: # __init__ did not run to completion (or at all). return self.__killed = True if self.__id and not already_killed: cursor_id = self.__id assert self.__address is not None address = _CursorAddress(self.__address, f"{self.__dbname}.{self.__collname}") else: # Skip killCursors. cursor_id = 0 address = None self.__collection.database.client._cleanup_cursor( synchronous, cursor_id, address, self.__sock_mgr, self.__session, self.__explicit_session, ) if not self.__explicit_session: self.__session = None self.__sock_mgr = None def close(self) -> None: """Explicitly close / kill this cursor.""" self.__die(True) def __query_spec(self) -> Mapping[str, Any]: """Get the spec to use for a query.""" operators: dict[str, Any] = {} if self.__ordering: operators["$orderby"] = self.__ordering if self.__explain: operators["$explain"] = True if self.__hint: operators["$hint"] = self.__hint if self.__let: operators["let"] = self.__let if self.__comment: operators["$comment"] = self.__comment if self.__max_scan: operators["$maxScan"] = self.__max_scan if self.__max_time_ms is not None: operators["$maxTimeMS"] = self.__max_time_ms if self.__max: operators["$max"] = self.__max if self.__min: operators["$min"] = self.__min if self.__return_key is not None: operators["$returnKey"] = self.__return_key if self.__show_record_id is not None: # This is upgraded to showRecordId for MongoDB 3.2+ "find" command. operators["$showDiskLoc"] = self.__show_record_id if self.__snapshot is not None: operators["$snapshot"] = self.__snapshot if operators: # Make a shallow copy so we can cleanly rewind or clone. spec = dict(self.__spec) # Allow-listed commands must be wrapped in $query. if "$query" not in spec: # $query has to come first spec = {"$query": spec} spec.update(operators) return spec # Have to wrap with $query if "query" is the first key. # We can't just use $query anytime "query" is a key as # that breaks commands like count and find_and_modify. # Checking spec.keys()[0] covers the case that the spec # was passed as an instance of SON or OrderedDict. elif "query" in self.__spec and ( len(self.__spec) == 1 or next(iter(self.__spec)) == "query" ): return {"$query": self.__spec} return self.__spec def __check_okay_to_chain(self) -> None: """Check if it is okay to chain more options onto this cursor.""" if self.__retrieved or self.__id is not None: raise InvalidOperation("cannot set options after executing query") def add_option(self, mask: int) -> Cursor[_DocumentType]: """Set arbitrary query flags using a bitmask. To set the tailable flag: cursor.add_option(2) """ if not isinstance(mask, int): raise TypeError("mask must be an int") self.__check_okay_to_chain() if mask & _QUERY_OPTIONS["exhaust"]: if self.__limit: raise InvalidOperation("Can't use limit and exhaust together.") if self.__collection.database.client.is_mongos: raise InvalidOperation("Exhaust cursors are not supported by mongos") self.__exhaust = True self.__query_flags |= mask return self def remove_option(self, mask: int) -> Cursor[_DocumentType]: """Unset arbitrary query flags using a bitmask. To unset the tailable flag: cursor.remove_option(2) """ if not isinstance(mask, int): raise TypeError("mask must be an int") self.__check_okay_to_chain() if mask & _QUERY_OPTIONS["exhaust"]: self.__exhaust = False self.__query_flags &= ~mask return self def allow_disk_use(self, allow_disk_use: bool) -> Cursor[_DocumentType]: """Specifies whether MongoDB can use temporary disk files while processing a blocking sort operation. Raises :exc:`TypeError` if `allow_disk_use` is not a boolean. .. note:: `allow_disk_use` requires server version **>= 4.4** :param allow_disk_use: if True, MongoDB may use temporary disk files to store data exceeding the system memory limit while processing a blocking sort operation. .. versionadded:: 3.11 """ if not isinstance(allow_disk_use, bool): raise TypeError("allow_disk_use must be a bool") self.__check_okay_to_chain() self.__allow_disk_use = allow_disk_use return self def limit(self, limit: int) -> Cursor[_DocumentType]: """Limits the number of results to be returned by this cursor. Raises :exc:`TypeError` if `limit` is not an integer. Raises :exc:`~pymongo.errors.InvalidOperation` if this :class:`Cursor` has already been used. The last `limit` applied to this cursor takes precedence. A limit of ``0`` is equivalent to no limit. :param limit: the number of results to return .. seealso:: The MongoDB documentation on `limit `_. """ if not isinstance(limit, int): raise TypeError("limit must be an integer") if self.__exhaust: raise InvalidOperation("Can't use limit and exhaust together.") self.__check_okay_to_chain() self.__empty = False self.__limit = limit return self def batch_size(self, batch_size: int) -> Cursor[_DocumentType]: """Limits the number of documents returned in one batch. Each batch requires a round trip to the server. It can be adjusted to optimize performance and limit data transfer. .. note:: batch_size can not override MongoDB's internal limits on the amount of data it will return to the client in a single batch (i.e if you set batch size to 1,000,000,000, MongoDB will currently only return 4-16MB of results per batch). Raises :exc:`TypeError` if `batch_size` is not an integer. Raises :exc:`ValueError` if `batch_size` is less than ``0``. Raises :exc:`~pymongo.errors.InvalidOperation` if this :class:`Cursor` has already been used. The last `batch_size` applied to this cursor takes precedence. :param batch_size: The size of each batch of results requested. """ if not isinstance(batch_size, int): raise TypeError("batch_size must be an integer") if batch_size < 0: raise ValueError("batch_size must be >= 0") self.__check_okay_to_chain() self.__batch_size = batch_size return self def skip(self, skip: int) -> Cursor[_DocumentType]: """Skips the first `skip` results of this cursor. Raises :exc:`TypeError` if `skip` is not an integer. Raises :exc:`ValueError` if `skip` is less than ``0``. Raises :exc:`~pymongo.errors.InvalidOperation` if this :class:`Cursor` has already been used. The last `skip` applied to this cursor takes precedence. :param skip: the number of results to skip """ if not isinstance(skip, int): raise TypeError("skip must be an integer") if skip < 0: raise ValueError("skip must be >= 0") self.__check_okay_to_chain() self.__skip = skip return self def max_time_ms(self, max_time_ms: Optional[int]) -> Cursor[_DocumentType]: """Specifies a time limit for a query operation. If the specified time is exceeded, the operation will be aborted and :exc:`~pymongo.errors.ExecutionTimeout` is raised. If `max_time_ms` is ``None`` no limit is applied. Raises :exc:`TypeError` if `max_time_ms` is not an integer or ``None``. Raises :exc:`~pymongo.errors.InvalidOperation` if this :class:`Cursor` has already been used. :param max_time_ms: the time limit after which the operation is aborted """ if not isinstance(max_time_ms, int) and max_time_ms is not None: raise TypeError("max_time_ms must be an integer or None") self.__check_okay_to_chain() self.__max_time_ms = max_time_ms return self def max_await_time_ms(self, max_await_time_ms: Optional[int]) -> Cursor[_DocumentType]: """Specifies a time limit for a getMore operation on a :attr:`~pymongo.cursor.CursorType.TAILABLE_AWAIT` cursor. For all other types of cursor max_await_time_ms is ignored. Raises :exc:`TypeError` if `max_await_time_ms` is not an integer or ``None``. Raises :exc:`~pymongo.errors.InvalidOperation` if this :class:`Cursor` has already been used. .. note:: `max_await_time_ms` requires server version **>= 3.2** :param max_await_time_ms: the time limit after which the operation is aborted .. versionadded:: 3.2 """ if not isinstance(max_await_time_ms, int) and max_await_time_ms is not None: raise TypeError("max_await_time_ms must be an integer or None") self.__check_okay_to_chain() # Ignore max_await_time_ms if not tailable or await_data is False. if self.__query_flags & CursorType.TAILABLE_AWAIT: self.__max_await_time_ms = max_await_time_ms return self @overload def __getitem__(self, index: int) -> _DocumentType: ... @overload def __getitem__(self, index: slice) -> Cursor[_DocumentType]: ... def __getitem__(self, index: Union[int, slice]) -> Union[_DocumentType, Cursor[_DocumentType]]: """Get a single document or a slice of documents from this cursor. .. warning:: A :class:`~Cursor` is not a Python :class:`list`. Each index access or slice requires that a new query be run using skip and limit. Do not iterate the cursor using index accesses. The following example is **extremely inefficient** and may return surprising results:: cursor = db.collection.find() # Warning: This runs a new query for each document. # Don't do this! for idx in range(10): print(cursor[idx]) Raises :class:`~pymongo.errors.InvalidOperation` if this cursor has already been used. To get a single document use an integral index, e.g.:: >>> db.test.find()[50] An :class:`IndexError` will be raised if the index is negative or greater than the amount of documents in this cursor. Any limit previously applied to this cursor will be ignored. To get a slice of documents use a slice index, e.g.:: >>> db.test.find()[20:25] This will return this cursor with a limit of ``5`` and skip of ``20`` applied. Using a slice index will override any prior limits or skips applied to this cursor (including those applied through previous calls to this method). Raises :class:`IndexError` when the slice has a step, a negative start value, or a stop value less than or equal to the start value. :param index: An integer or slice index to be applied to this cursor """ self.__check_okay_to_chain() self.__empty = False if isinstance(index, slice): if index.step is not None: raise IndexError("Cursor instances do not support slice steps") skip = 0 if index.start is not None: if index.start < 0: raise IndexError("Cursor instances do not support negative indices") skip = index.start if index.stop is not None: limit = index.stop - skip if limit < 0: raise IndexError( "stop index must be greater than start index for slice %r" % index ) if limit == 0: self.__empty = True else: limit = 0 self.__skip = skip self.__limit = limit return self if isinstance(index, int): if index < 0: raise IndexError("Cursor instances do not support negative indices") clone = self.clone() clone.skip(index + self.__skip) clone.limit(-1) # use a hard limit clone.__query_flags &= ~CursorType.TAILABLE_AWAIT # PYTHON-1371 for doc in clone: return doc raise IndexError("no such item for Cursor instance") raise TypeError("index %r cannot be applied to Cursor instances" % index) def max_scan(self, max_scan: Optional[int]) -> Cursor[_DocumentType]: """**DEPRECATED** - Limit the number of documents to scan when performing the query. Raises :class:`~pymongo.errors.InvalidOperation` if this cursor has already been used. Only the last :meth:`max_scan` applied to this cursor has any effect. :param max_scan: the maximum number of documents to scan .. versionchanged:: 3.7 Deprecated :meth:`max_scan`. Support for this option is deprecated in MongoDB 4.0. Use :meth:`max_time_ms` instead to limit server side execution time. """ self.__check_okay_to_chain() self.__max_scan = max_scan return self def max(self, spec: _Sort) -> Cursor[_DocumentType]: """Adds ``max`` operator that specifies upper bound for specific index. When using ``max``, :meth:`~hint` should also be configured to ensure the query uses the expected index and starting in MongoDB 4.2 :meth:`~hint` will be required. :param spec: a list of field, limit pairs specifying the exclusive upper bound for all keys of a specific index in order. .. versionchanged:: 3.8 Deprecated cursors that use ``max`` without a :meth:`~hint`. .. versionadded:: 2.7 """ if not isinstance(spec, (list, tuple)): raise TypeError("spec must be an instance of list or tuple") self.__check_okay_to_chain() self.__max = dict(spec) return self def min(self, spec: _Sort) -> Cursor[_DocumentType]: """Adds ``min`` operator that specifies lower bound for specific index. When using ``min``, :meth:`~hint` should also be configured to ensure the query uses the expected index and starting in MongoDB 4.2 :meth:`~hint` will be required. :param spec: a list of field, limit pairs specifying the inclusive lower bound for all keys of a specific index in order. .. versionchanged:: 3.8 Deprecated cursors that use ``min`` without a :meth:`~hint`. .. versionadded:: 2.7 """ if not isinstance(spec, (list, tuple)): raise TypeError("spec must be an instance of list or tuple") self.__check_okay_to_chain() self.__min = dict(spec) return self def sort( self, key_or_list: _Hint, direction: Optional[Union[int, str]] = None ) -> Cursor[_DocumentType]: """Sorts this cursor's results. Pass a field name and a direction, either :data:`~pymongo.ASCENDING` or :data:`~pymongo.DESCENDING`.:: for doc in collection.find().sort('field', pymongo.ASCENDING): print(doc) To sort by multiple fields, pass a list of (key, direction) pairs. If just a name is given, :data:`~pymongo.ASCENDING` will be inferred:: for doc in collection.find().sort([ 'field1', ('field2', pymongo.DESCENDING)]): print(doc) Text search results can be sorted by relevance:: cursor = db.test.find( {'$text': {'$search': 'some words'}}, {'score': {'$meta': 'textScore'}}) # Sort by 'score' field. cursor.sort([('score', {'$meta': 'textScore'})]) for doc in cursor: print(doc) For more advanced text search functionality, see MongoDB's `Atlas Search `_. Raises :class:`~pymongo.errors.InvalidOperation` if this cursor has already been used. Only the last :meth:`sort` applied to this cursor has any effect. :param key_or_list: a single key or a list of (key, direction) pairs specifying the keys to sort on :param direction: only used if `key_or_list` is a single key, if not given :data:`~pymongo.ASCENDING` is assumed """ self.__check_okay_to_chain() keys = helpers._index_list(key_or_list, direction) self.__ordering = helpers._index_document(keys) return self def distinct(self, key: str) -> list: """Get a list of distinct values for `key` among all documents in the result set of this query. Raises :class:`TypeError` if `key` is not an instance of :class:`str`. The :meth:`distinct` method obeys the :attr:`~pymongo.collection.Collection.read_preference` of the :class:`~pymongo.collection.Collection` instance on which :meth:`~pymongo.collection.Collection.find` was called. :param key: name of key for which we want to get the distinct values .. seealso:: :meth:`pymongo.collection.Collection.distinct` """ options: dict[str, Any] = {} if self.__spec: options["query"] = self.__spec if self.__max_time_ms is not None: options["maxTimeMS"] = self.__max_time_ms if self.__comment: options["comment"] = self.__comment if self.__collation is not None: options["collation"] = self.__collation return self.__collection.distinct(key, session=self.__session, **options) def explain(self) -> _DocumentType: """Returns an explain plan record for this cursor. .. note:: This method uses the default verbosity mode of the `explain command `_, ``allPlansExecution``. To use a different verbosity use :meth:`~pymongo.database.Database.command` to run the explain command directly. .. seealso:: The MongoDB documentation on `explain `_. """ c = self.clone() c.__explain = True # always use a hard limit for explains if c.__limit: c.__limit = -abs(c.__limit) return next(c) def __set_hint(self, index: Optional[_Hint]) -> None: if index is None: self.__hint = None return if isinstance(index, str): self.__hint = index else: self.__hint = helpers._index_document(index) def hint(self, index: Optional[_Hint]) -> Cursor[_DocumentType]: """Adds a 'hint', telling Mongo the proper index to use for the query. Judicious use of hints can greatly improve query performance. When doing a query on multiple fields (at least one of which is indexed) pass the indexed field as a hint to the query. Raises :class:`~pymongo.errors.OperationFailure` if the provided hint requires an index that does not exist on this collection, and raises :class:`~pymongo.errors.InvalidOperation` if this cursor has already been used. `index` should be an index as passed to :meth:`~pymongo.collection.Collection.create_index` (e.g. ``[('field', ASCENDING)]``) or the name of the index. If `index` is ``None`` any existing hint for this query is cleared. The last hint applied to this cursor takes precedence over all others. :param index: index to hint on (as an index specifier) """ self.__check_okay_to_chain() self.__set_hint(index) return self def comment(self, comment: Any) -> Cursor[_DocumentType]: """Adds a 'comment' to the cursor. http://mongodb.com/docs/manual/reference/operator/comment/ :param comment: A string to attach to the query to help interpret and trace the operation in the server logs and in profile data. .. versionadded:: 2.7 """ self.__check_okay_to_chain() self.__comment = comment return self def where(self, code: Union[str, Code]) -> Cursor[_DocumentType]: """Adds a `$where`_ clause to this query. The `code` argument must be an instance of :class:`str` or :class:`~bson.code.Code` containing a JavaScript expression. This expression will be evaluated for each document scanned. Only those documents for which the expression evaluates to *true* will be returned as results. The keyword *this* refers to the object currently being scanned. For example:: # Find all documents where field "a" is less than "b" plus "c". for doc in db.test.find().where('this.a < (this.b + this.c)'): print(doc) Raises :class:`TypeError` if `code` is not an instance of :class:`str`. Raises :class:`~pymongo.errors.InvalidOperation` if this :class:`Cursor` has already been used. Only the last call to :meth:`where` applied to a :class:`Cursor` has any effect. .. note:: MongoDB 4.4 drops support for :class:`~bson.code.Code` with scope variables. Consider using `$expr`_ instead. :param code: JavaScript expression to use as a filter .. _$expr: https://mongodb.com/docs/manual/reference/operator/query/expr/ .. _$where: https://mongodb.com/docs/manual/reference/operator/query/where/ """ self.__check_okay_to_chain() if not isinstance(code, Code): code = Code(code) # Avoid overwriting a filter argument that was given by the user # when updating the spec. spec: dict[str, Any] if self.__has_filter: spec = dict(self.__spec) else: spec = cast(dict, self.__spec) spec["$where"] = code self.__spec = spec return self def collation(self, collation: Optional[_CollationIn]) -> Cursor[_DocumentType]: """Adds a :class:`~pymongo.collation.Collation` to this query. Raises :exc:`TypeError` if `collation` is not an instance of :class:`~pymongo.collation.Collation` or a ``dict``. Raises :exc:`~pymongo.errors.InvalidOperation` if this :class:`Cursor` has already been used. Only the last collation applied to this cursor has any effect. :param collation: An instance of :class:`~pymongo.collation.Collation`. """ self.__check_okay_to_chain() self.__collation = validate_collation_or_none(collation) return self def __send_message(self, operation: Union[_Query, _GetMore]) -> None: """Send a query or getmore operation and handles the response. If operation is ``None`` this is an exhaust cursor, which reads the next result batch off the exhaust socket instead of sending getMore messages to the server. Can raise ConnectionFailure. """ client = self.__collection.database.client # OP_MSG is required to support exhaust cursors with encryption. if client._encrypter and self.__exhaust: raise InvalidOperation("exhaust cursors do not support auto encryption") try: response = client._run_operation( operation, self._unpack_response, address=self.__address ) except OperationFailure as exc: if exc.code in _CURSOR_CLOSED_ERRORS or self.__exhaust: # Don't send killCursors because the cursor is already closed. self.__killed = True if exc.timeout: self.__die(False) else: self.close() # If this is a tailable cursor the error is likely # due to capped collection roll over. Setting # self.__killed to True ensures Cursor.alive will be # False. No need to re-raise. if ( exc.code in _CURSOR_CLOSED_ERRORS and self.__query_flags & _QUERY_OPTIONS["tailable_cursor"] ): return raise except ConnectionFailure: self.__killed = True self.close() raise except Exception: self.close() raise self.__address = response.address if isinstance(response, PinnedResponse): if not self.__sock_mgr: self.__sock_mgr = _ConnectionManager(response.conn, response.more_to_come) cmd_name = operation.name docs = response.docs if response.from_command: if cmd_name != "explain": cursor = docs[0]["cursor"] self.__id = cursor["id"] if cmd_name == "find": documents = cursor["firstBatch"] # Update the namespace used for future getMore commands. ns = cursor.get("ns") if ns: self.__dbname, self.__collname = ns.split(".", 1) else: documents = cursor["nextBatch"] self.__data = deque(documents) self.__retrieved += len(documents) else: self.__id = 0 self.__data = deque(docs) self.__retrieved += len(docs) else: assert isinstance(response.data, _OpReply) self.__id = response.data.cursor_id self.__data = deque(docs) self.__retrieved += response.data.number_returned if self.__id == 0: # Don't wait for garbage collection to call __del__, return the # socket and the session to the pool now. self.close() if self.__limit and self.__id and self.__limit <= self.__retrieved: self.close() def _unpack_response( self, response: Union[_OpReply, _OpMsg], cursor_id: Optional[int], codec_options: CodecOptions, user_fields: Optional[Mapping[str, Any]] = None, legacy_response: bool = False, ) -> Sequence[_DocumentOut]: return response.unpack_response(cursor_id, codec_options, user_fields, legacy_response) def _read_preference(self) -> _ServerMode: if self.__read_preference is None: # Save the read preference for getMore commands. self.__read_preference = self.__collection._read_preference_for(self.session) return self.__read_preference def _refresh(self) -> int: """Refreshes the cursor with more data from Mongo. Returns the length of self.__data after refresh. Will exit early if self.__data is already non-empty. Raises OperationFailure when the cursor cannot be refreshed due to an error on the query. """ if len(self.__data) or self.__killed: return len(self.__data) if not self.__session: self.__session = self.__collection.database.client._ensure_session() if self.__id is None: # Query if (self.__min or self.__max) and not self.__hint: raise InvalidOperation( "Passing a 'hint' is required when using the min/max query" " option to ensure the query utilizes the correct index" ) q = self._query_class( self.__query_flags, self.__collection.database.name, self.__collection.name, self.__skip, self.__query_spec(), self.__projection, self.__codec_options, self._read_preference(), self.__limit, self.__batch_size, self.__read_concern, self.__collation, self.__session, self.__collection.database.client, self.__allow_disk_use, self.__exhaust, ) self.__send_message(q) elif self.__id: # Get More if self.__limit: limit = self.__limit - self.__retrieved if self.__batch_size: limit = min(limit, self.__batch_size) else: limit = self.__batch_size # Exhaust cursors don't send getMore messages. g = self._getmore_class( self.__dbname, self.__collname, limit, self.__id, self.__codec_options, self._read_preference(), self.__session, self.__collection.database.client, self.__max_await_time_ms, self.__sock_mgr, self.__exhaust, self.__comment, ) self.__send_message(g) return len(self.__data) @property def alive(self) -> bool: """Does this cursor have the potential to return more data? This is mostly useful with `tailable cursors `_ since they will stop iterating even though they *may* return more results in the future. With regular cursors, simply use a for loop instead of :attr:`alive`:: for doc in collection.find(): print(doc) .. note:: Even if :attr:`alive` is True, :meth:`next` can raise :exc:`StopIteration`. :attr:`alive` can also be True while iterating a cursor from a failed server. In this case :attr:`alive` will return False after :meth:`next` fails to retrieve the next batch of results from the server. """ return bool(len(self.__data) or (not self.__killed)) @property def cursor_id(self) -> Optional[int]: """Returns the id of the cursor .. versionadded:: 2.2 """ return self.__id @property def address(self) -> Optional[tuple[str, Any]]: """The (host, port) of the server used, or None. .. versionchanged:: 3.0 Renamed from "conn_id". """ return self.__address @property def session(self) -> Optional[ClientSession]: """The cursor's :class:`~pymongo.client_session.ClientSession`, or None. .. versionadded:: 3.6 """ if self.__explicit_session: return self.__session return None def __iter__(self) -> Cursor[_DocumentType]: return self def next(self) -> _DocumentType: """Advance the cursor.""" if self.__empty: raise StopIteration if len(self.__data) or self._refresh(): return self.__data.popleft() else: raise StopIteration __next__ = next def __enter__(self) -> Cursor[_DocumentType]: return self def __exit__(self, exc_type: Any, exc_val: Any, exc_tb: Any) -> None: self.close() def __copy__(self) -> Cursor[_DocumentType]: """Support function for `copy.copy()`. .. versionadded:: 2.4 """ return self._clone(deepcopy=False) def __deepcopy__(self, memo: Any) -> Any: """Support function for `copy.deepcopy()`. .. versionadded:: 2.4 """ return self._clone(deepcopy=True) @overload def _deepcopy(self, x: Iterable, memo: Optional[dict[int, Union[list, dict]]] = None) -> list: ... @overload def _deepcopy( self, x: SupportsItems, memo: Optional[dict[int, Union[list, dict]]] = None ) -> dict: ... def _deepcopy( self, x: Union[Iterable, SupportsItems], memo: Optional[dict[int, Union[list, dict]]] = None ) -> Union[list, dict]: """Deepcopy helper for the data dictionary or list. Regular expressions cannot be deep copied but as they are immutable we don't have to copy them when cloning. """ y: Union[list, dict] iterator: Iterable[tuple[Any, Any]] if not hasattr(x, "items"): y, is_list, iterator = [], True, enumerate(x) else: y, is_list, iterator = {}, False, cast("SupportsItems", x).items() if memo is None: memo = {} val_id = id(x) if val_id in memo: return memo[val_id] memo[val_id] = y for key, value in iterator: if isinstance(value, (dict, list)) and not isinstance(value, SON): value = self._deepcopy(value, memo) # noqa: PLW2901 elif not isinstance(value, RE_TYPE): value = copy.deepcopy(value, memo) # noqa: PLW2901 if is_list: y.append(value) # type: ignore[union-attr] else: if not isinstance(key, RE_TYPE): key = copy.deepcopy(key, memo) # noqa: PLW2901 y[key] = value return y class RawBatchCursor(Cursor, Generic[_DocumentType]): """A cursor / iterator over raw batches of BSON data from a query result.""" _query_class = _RawBatchQuery _getmore_class = _RawBatchGetMore def __init__(self, collection: Collection[_DocumentType], *args: Any, **kwargs: Any) -> None: """Create a new cursor / iterator over raw batches of BSON data. Should not be called directly by application developers - see :meth:`~pymongo.collection.Collection.find_raw_batches` instead. .. seealso:: The MongoDB documentation on `cursors `_. """ super().__init__(collection, *args, **kwargs) def _unpack_response( self, response: Union[_OpReply, _OpMsg], cursor_id: Optional[int], codec_options: CodecOptions[Mapping[str, Any]], user_fields: Optional[Mapping[str, Any]] = None, legacy_response: bool = False, ) -> list[_DocumentOut]: raw_response = response.raw_response(cursor_id, user_fields=user_fields) if not legacy_response: # OP_MSG returns firstBatch/nextBatch documents as a BSON array # Re-assemble the array of documents into a document stream _convert_raw_document_lists_to_streams(raw_response[0]) return cast(List["_DocumentOut"], raw_response) def explain(self) -> _DocumentType: """Returns an explain plan record for this cursor. .. seealso:: The MongoDB documentation on `explain `_. """ clone = self._clone(deepcopy=True, base=Cursor(self.collection)) return clone.explain() def __getitem__(self, index: Any) -> NoReturn: raise InvalidOperation("Cannot call __getitem__ on RawBatchCursor") mongodb-mongo-python-driver-509e9b7/pymongo/daemon.py000066400000000000000000000134031462766011000227430ustar00rootroot00000000000000# Copyright 2019-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. """Support for spawning a daemon process. PyMongo only attempts to spawn the mongocryptd daemon process when automatic client-side field level encryption is enabled. See :ref:`automatic-client-side-encryption` for more info. """ from __future__ import annotations import os import subprocess import sys import warnings from typing import Any, Optional, Sequence # The maximum amount of time to wait for the intermediate subprocess. _WAIT_TIMEOUT = 10 _THIS_FILE = os.path.realpath(__file__) def _popen_wait(popen: subprocess.Popen[Any], timeout: Optional[float]) -> Optional[int]: """Implement wait timeout support for Python 3.""" try: return popen.wait(timeout=timeout) except subprocess.TimeoutExpired: # Silence TimeoutExpired errors. return None def _silence_resource_warning(popen: Optional[subprocess.Popen[Any]]) -> None: """Silence Popen's ResourceWarning. Note this should only be used if the process was created as a daemon. """ # Set the returncode to avoid this warning when popen is garbage collected: # "ResourceWarning: subprocess XXX is still running". # See https://bugs.python.org/issue38890 and # https://bugs.python.org/issue26741. # popen is None when mongocryptd spawning fails if popen is not None: popen.returncode = 0 if sys.platform == "win32": # On Windows we spawn the daemon process simply by using DETACHED_PROCESS. _DETACHED_PROCESS = getattr(subprocess, "DETACHED_PROCESS", 0x00000008) def _spawn_daemon(args: Sequence[str]) -> None: """Spawn a daemon process (Windows).""" try: with open(os.devnull, "r+b") as devnull: popen = subprocess.Popen( args, # noqa: S603 creationflags=_DETACHED_PROCESS, stdin=devnull, stderr=devnull, stdout=devnull, ) _silence_resource_warning(popen) except FileNotFoundError as exc: warnings.warn( f"Failed to start {args[0]}: is it on your $PATH?\nOriginal exception: {exc}", RuntimeWarning, stacklevel=2, ) else: # On Unix we spawn the daemon process with a double Popen. # 1) The first Popen runs this file as a Python script using the current # interpreter. # 2) The script then decouples itself and performs the second Popen to # spawn the daemon process. # 3) The original process waits up to 10 seconds for the script to exit. # # Note that we do not call fork() directly because we want this procedure # to be safe to call from any thread. Using Popen instead of fork also # avoids triggering the application's os.register_at_fork() callbacks when # we spawn the mongocryptd daemon process. def _spawn(args: Sequence[str]) -> Optional[subprocess.Popen[Any]]: """Spawn the process and silence stdout/stderr.""" try: with open(os.devnull, "r+b") as devnull: return subprocess.Popen( args, # noqa: S603 close_fds=True, stdin=devnull, stderr=devnull, stdout=devnull, ) except FileNotFoundError as exc: warnings.warn( f"Failed to start {args[0]}: is it on your $PATH?\nOriginal exception: {exc}", RuntimeWarning, stacklevel=2, ) return None def _spawn_daemon_double_popen(args: Sequence[str]) -> None: """Spawn a daemon process using a double subprocess.Popen.""" spawner_args = [sys.executable, _THIS_FILE] spawner_args.extend(args) temp_proc = subprocess.Popen(spawner_args, close_fds=True) # noqa: S603 # Reap the intermediate child process to avoid creating zombie # processes. _popen_wait(temp_proc, _WAIT_TIMEOUT) def _spawn_daemon(args: Sequence[str]) -> None: """Spawn a daemon process (Unix).""" # "If Python is unable to retrieve the real path to its executable, # sys.executable will be an empty string or None". if sys.executable: _spawn_daemon_double_popen(args) else: # Fallback to spawn a non-daemon process without silencing the # resource warning. We do not use fork here because it is not # safe to call from a thread on all systems. # Unfortunately, this means that: # 1) If the parent application is killed via Ctrl-C, the # non-daemon process will also be killed. # 2) Each non-daemon process will hang around as a zombie process # until the main application exits. _spawn(args) if __name__ == "__main__": # Attempt to start a new session to decouple from the parent. if hasattr(os, "setsid"): try: os.setsid() except OSError: pass # We are performing a double fork (Popen) to spawn the process as a # daemon so it is safe to ignore the resource warning. _silence_resource_warning(_spawn(sys.argv[1:])) os._exit(0) mongodb-mongo-python-driver-509e9b7/pymongo/database.py000066400000000000000000001551061462766011000232530ustar00rootroot00000000000000# Copyright 2009-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. """Database level operations.""" from __future__ import annotations from copy import deepcopy from typing import ( TYPE_CHECKING, Any, Generic, Mapping, MutableMapping, NoReturn, Optional, Sequence, TypeVar, Union, cast, overload, ) from bson.codec_options import DEFAULT_CODEC_OPTIONS, CodecOptions from bson.dbref import DBRef from bson.timestamp import Timestamp from pymongo import _csot, common from pymongo.aggregation import _DatabaseAggregationCommand from pymongo.change_stream import DatabaseChangeStream from pymongo.collection import Collection from pymongo.command_cursor import CommandCursor from pymongo.common import _ecoc_coll_name, _esc_coll_name from pymongo.errors import CollectionInvalid, InvalidName, InvalidOperation from pymongo.operations import _Op from pymongo.read_preferences import ReadPreference, _ServerMode from pymongo.typings import _CollationIn, _DocumentType, _DocumentTypeArg, _Pipeline if TYPE_CHECKING: import bson import bson.codec_options from pymongo.client_session import ClientSession from pymongo.mongo_client import MongoClient from pymongo.pool import Connection from pymongo.read_concern import ReadConcern from pymongo.server import Server from pymongo.write_concern import WriteConcern def _check_name(name: str) -> None: """Check if a database name is valid.""" if not name: raise InvalidName("database name cannot be the empty string") for invalid_char in [" ", ".", "$", "/", "\\", "\x00", '"']: if invalid_char in name: raise InvalidName("database names cannot contain the character %r" % invalid_char) _CodecDocumentType = TypeVar("_CodecDocumentType", bound=Mapping[str, Any]) class Database(common.BaseObject, Generic[_DocumentType]): """A Mongo database.""" def __init__( self, client: MongoClient[_DocumentType], name: str, codec_options: Optional[CodecOptions[_DocumentTypeArg]] = None, read_preference: Optional[_ServerMode] = None, write_concern: Optional[WriteConcern] = None, read_concern: Optional[ReadConcern] = None, ) -> None: """Get a database by client and name. Raises :class:`TypeError` if `name` is not an instance of :class:`str`. Raises :class:`~pymongo.errors.InvalidName` if `name` is not a valid database name. :param client: A :class:`~pymongo.mongo_client.MongoClient` instance. :param name: The database name. :param codec_options: An instance of :class:`~bson.codec_options.CodecOptions`. If ``None`` (the default) client.codec_options is used. :param read_preference: The read preference to use. If ``None`` (the default) client.read_preference is used. :param write_concern: An instance of :class:`~pymongo.write_concern.WriteConcern`. If ``None`` (the default) client.write_concern is used. :param read_concern: An instance of :class:`~pymongo.read_concern.ReadConcern`. If ``None`` (the default) client.read_concern is used. .. seealso:: The MongoDB documentation on `databases `_. .. versionchanged:: 4.0 Removed the eval, system_js, error, last_status, previous_error, reset_error_history, authenticate, logout, collection_names, current_op, add_user, remove_user, profiling_level, set_profiling_level, and profiling_info methods. See the :ref:`pymongo4-migration-guide`. .. versionchanged:: 3.2 Added the read_concern option. .. versionchanged:: 3.0 Added the codec_options, read_preference, and write_concern options. :class:`~pymongo.database.Database` no longer returns an instance of :class:`~pymongo.collection.Collection` for attribute names with leading underscores. You must use dict-style lookups instead:: db['__my_collection__'] Not: db.__my_collection__ """ super().__init__( codec_options or client.codec_options, read_preference or client.read_preference, write_concern or client.write_concern, read_concern or client.read_concern, ) if not isinstance(name, str): raise TypeError("name must be an instance of str") if name != "$external": _check_name(name) self.__name = name self.__client: MongoClient[_DocumentType] = client self._timeout = client.options.timeout @property def client(self) -> MongoClient[_DocumentType]: """The client instance for this :class:`Database`.""" return self.__client @property def name(self) -> str: """The name of this :class:`Database`.""" return self.__name def with_options( self, codec_options: Optional[CodecOptions[_DocumentTypeArg]] = None, read_preference: Optional[_ServerMode] = None, write_concern: Optional[WriteConcern] = None, read_concern: Optional[ReadConcern] = None, ) -> Database[_DocumentType]: """Get a clone of this database changing the specified settings. >>> db1.read_preference Primary() >>> from pymongo.read_preferences import Secondary >>> db2 = db1.with_options(read_preference=Secondary([{'node': 'analytics'}])) >>> db1.read_preference Primary() >>> db2.read_preference Secondary(tag_sets=[{'node': 'analytics'}], max_staleness=-1, hedge=None) :param codec_options: An instance of :class:`~bson.codec_options.CodecOptions`. If ``None`` (the default) the :attr:`codec_options` of this :class:`Collection` is used. :param read_preference: The read preference to use. If ``None`` (the default) the :attr:`read_preference` of this :class:`Collection` is used. See :mod:`~pymongo.read_preferences` for options. :param write_concern: An instance of :class:`~pymongo.write_concern.WriteConcern`. If ``None`` (the default) the :attr:`write_concern` of this :class:`Collection` is used. :param read_concern: An instance of :class:`~pymongo.read_concern.ReadConcern`. If ``None`` (the default) the :attr:`read_concern` of this :class:`Collection` is used. .. versionadded:: 3.8 """ return Database( self.client, self.__name, codec_options or self.codec_options, read_preference or self.read_preference, write_concern or self.write_concern, read_concern or self.read_concern, ) def __eq__(self, other: Any) -> bool: if isinstance(other, Database): return self.__client == other.client and self.__name == other.name return NotImplemented def __ne__(self, other: Any) -> bool: return not self == other def __hash__(self) -> int: return hash((self.__client, self.__name)) def __repr__(self) -> str: return f"Database({self.__client!r}, {self.__name!r})" def __getattr__(self, name: str) -> Collection[_DocumentType]: """Get a collection of this database by name. Raises InvalidName if an invalid collection name is used. :param name: the name of the collection to get """ if name.startswith("_"): raise AttributeError( f"Database has no attribute {name!r}. To access the {name}" f" collection, use database[{name!r}]." ) return self.__getitem__(name) def __getitem__(self, name: str) -> Collection[_DocumentType]: """Get a collection of this database by name. Raises InvalidName if an invalid collection name is used. :param name: the name of the collection to get """ return Collection(self, name) def get_collection( self, name: str, codec_options: Optional[CodecOptions[_DocumentTypeArg]] = None, read_preference: Optional[_ServerMode] = None, write_concern: Optional[WriteConcern] = None, read_concern: Optional[ReadConcern] = None, ) -> Collection[_DocumentType]: """Get a :class:`~pymongo.collection.Collection` with the given name and options. Useful for creating a :class:`~pymongo.collection.Collection` with different codec options, read preference, and/or write concern from this :class:`Database`. >>> db.read_preference Primary() >>> coll1 = db.test >>> coll1.read_preference Primary() >>> from pymongo import ReadPreference >>> coll2 = db.get_collection( ... 'test', read_preference=ReadPreference.SECONDARY) >>> coll2.read_preference Secondary(tag_sets=None) :param name: The name of the collection - a string. :param codec_options: An instance of :class:`~bson.codec_options.CodecOptions`. If ``None`` (the default) the :attr:`codec_options` of this :class:`Database` is used. :param read_preference: The read preference to use. If ``None`` (the default) the :attr:`read_preference` of this :class:`Database` is used. See :mod:`~pymongo.read_preferences` for options. :param write_concern: An instance of :class:`~pymongo.write_concern.WriteConcern`. If ``None`` (the default) the :attr:`write_concern` of this :class:`Database` is used. :param read_concern: An instance of :class:`~pymongo.read_concern.ReadConcern`. If ``None`` (the default) the :attr:`read_concern` of this :class:`Database` is used. """ return Collection( self, name, False, codec_options, read_preference, write_concern, read_concern, ) def _get_encrypted_fields( self, kwargs: Mapping[str, Any], coll_name: str, ask_db: bool ) -> Optional[Mapping[str, Any]]: encrypted_fields = kwargs.get("encryptedFields") if encrypted_fields: return cast(Mapping[str, Any], deepcopy(encrypted_fields)) if ( self.client.options.auto_encryption_opts and self.client.options.auto_encryption_opts._encrypted_fields_map and self.client.options.auto_encryption_opts._encrypted_fields_map.get( f"{self.name}.{coll_name}" ) ): return cast( Mapping[str, Any], deepcopy( self.client.options.auto_encryption_opts._encrypted_fields_map[ f"{self.name}.{coll_name}" ] ), ) if ask_db and self.client.options.auto_encryption_opts: options = self[coll_name].options() if options.get("encryptedFields"): return cast(Mapping[str, Any], deepcopy(options["encryptedFields"])) return None @_csot.apply def create_collection( self, name: str, codec_options: Optional[CodecOptions[_DocumentTypeArg]] = None, read_preference: Optional[_ServerMode] = None, write_concern: Optional[WriteConcern] = None, read_concern: Optional[ReadConcern] = None, session: Optional[ClientSession] = None, check_exists: Optional[bool] = True, **kwargs: Any, ) -> Collection[_DocumentType]: """Create a new :class:`~pymongo.collection.Collection` in this database. Normally collection creation is automatic. This method should only be used to specify options on creation. :class:`~pymongo.errors.CollectionInvalid` will be raised if the collection already exists. :param name: the name of the collection to create :param codec_options: An instance of :class:`~bson.codec_options.CodecOptions`. If ``None`` (the default) the :attr:`codec_options` of this :class:`Database` is used. :param read_preference: The read preference to use. If ``None`` (the default) the :attr:`read_preference` of this :class:`Database` is used. :param write_concern: An instance of :class:`~pymongo.write_concern.WriteConcern`. If ``None`` (the default) the :attr:`write_concern` of this :class:`Database` is used. :param read_concern: An instance of :class:`~pymongo.read_concern.ReadConcern`. If ``None`` (the default) the :attr:`read_concern` of this :class:`Database` is used. :param collation: An instance of :class:`~pymongo.collation.Collation`. :param session: a :class:`~pymongo.client_session.ClientSession`. :param `check_exists`: if True (the default), send a listCollections command to check if the collection already exists before creation. :param kwargs: additional keyword arguments will be passed as options for the `create collection command`_ All optional `create collection command`_ parameters should be passed as keyword arguments to this method. Valid options include, but are not limited to: - ``size`` (int): desired initial size for the collection (in bytes). For capped collections this size is the max size of the collection. - ``capped`` (bool): if True, this is a capped collection - ``max`` (int): maximum number of objects if capped (optional) - ``timeseries`` (dict): a document specifying configuration options for timeseries collections - ``expireAfterSeconds`` (int): the number of seconds after which a document in a timeseries collection expires - ``validator`` (dict): a document specifying validation rules or expressions for the collection - ``validationLevel`` (str): how strictly to apply the validation rules to existing documents during an update. The default level is "strict" - ``validationAction`` (str): whether to "error" on invalid documents (the default) or just "warn" about the violations but allow invalid documents to be inserted - ``indexOptionDefaults`` (dict): a document specifying a default configuration for indexes when creating a collection - ``viewOn`` (str): the name of the source collection or view from which to create the view - ``pipeline`` (list): a list of aggregation pipeline stages - ``comment`` (str): a user-provided comment to attach to this command. This option is only supported on MongoDB >= 4.4. - ``encryptedFields`` (dict): **(BETA)** Document that describes the encrypted fields for Queryable Encryption. For example:: { "escCollection": "enxcol_.encryptedCollection.esc", "ecocCollection": "enxcol_.encryptedCollection.ecoc", "fields": [ { "path": "firstName", "keyId": Binary.from_uuid(UUID('00000000-0000-0000-0000-000000000000')), "bsonType": "string", "queries": {"queryType": "equality"} }, { "path": "ssn", "keyId": Binary.from_uuid(UUID('04104104-1041-0410-4104-104104104104')), "bsonType": "string" } ] } - ``clusteredIndex`` (dict): Document that specifies the clustered index configuration. It must have the following form:: { // key pattern must be {_id: 1} key: , // required unique: , // required, must be `true` name: , // optional, otherwise automatically generated v: , // optional, must be `2` if provided } - ``changeStreamPreAndPostImages`` (dict): a document with a boolean field ``enabled`` for enabling pre- and post-images. .. versionchanged:: 4.2 Added the ``check_exists``, ``clusteredIndex``, and ``encryptedFields`` parameters. .. versionchanged:: 3.11 This method is now supported inside multi-document transactions with MongoDB 4.4+. .. versionchanged:: 3.6 Added ``session`` parameter. .. versionchanged:: 3.4 Added the collation option. .. versionchanged:: 3.0 Added the codec_options, read_preference, and write_concern options. .. _create collection command: https://mongodb.com/docs/manual/reference/command/create """ encrypted_fields = self._get_encrypted_fields(kwargs, name, False) if encrypted_fields: common.validate_is_mapping("encryptedFields", encrypted_fields) kwargs["encryptedFields"] = encrypted_fields clustered_index = kwargs.get("clusteredIndex") if clustered_index: common.validate_is_mapping("clusteredIndex", clustered_index) with self.__client._tmp_session(session) as s: # Skip this check in a transaction where listCollections is not # supported. if ( check_exists and (not s or not s.in_transaction) and name in self.list_collection_names(filter={"name": name}, session=s) ): raise CollectionInvalid("collection %s already exists" % name) return Collection( self, name, True, codec_options, read_preference, write_concern, read_concern, session=s, **kwargs, ) def aggregate( self, pipeline: _Pipeline, session: Optional[ClientSession] = None, **kwargs: Any ) -> CommandCursor[_DocumentType]: """Perform a database-level aggregation. See the `aggregation pipeline`_ documentation for a list of stages that are supported. .. code-block:: python # Lists all operations currently running on the server. with client.admin.aggregate([{"$currentOp": {}}]) as cursor: for operation in cursor: print(operation) The :meth:`aggregate` method obeys the :attr:`read_preference` of this :class:`Database`, except when ``$out`` or ``$merge`` are used, in which case :attr:`~pymongo.read_preferences.ReadPreference.PRIMARY` is used. .. note:: This method does not support the 'explain' option. Please use :meth:`~pymongo.database.Database.command` instead. .. note:: The :attr:`~pymongo.database.Database.write_concern` of this collection is automatically applied to this operation. :param pipeline: a list of aggregation pipeline stages :param session: a :class:`~pymongo.client_session.ClientSession`. :param kwargs: extra `aggregate command`_ parameters. All optional `aggregate command`_ parameters should be passed as keyword arguments to this method. Valid options include, but are not limited to: - `allowDiskUse` (bool): Enables writing to temporary files. When set to True, aggregation stages can write data to the _tmp subdirectory of the --dbpath directory. The default is False. - `maxTimeMS` (int): The maximum amount of time to allow the operation to run in milliseconds. - `batchSize` (int): The maximum number of documents to return per batch. Ignored if the connected mongod or mongos does not support returning aggregate results using a cursor. - `collation` (optional): An instance of :class:`~pymongo.collation.Collation`. - `let` (dict): A dict of parameter names and values. Values must be constant or closed expressions that do not reference document fields. Parameters can then be accessed as variables in an aggregate expression context (e.g. ``"$$var"``). This option is only supported on MongoDB >= 5.0. :return: A :class:`~pymongo.command_cursor.CommandCursor` over the result set. .. versionadded:: 3.9 .. _aggregation pipeline: https://mongodb.com/docs/manual/reference/operator/aggregation-pipeline .. _aggregate command: https://mongodb.com/docs/manual/reference/command/aggregate """ with self.client._tmp_session(session, close=False) as s: cmd = _DatabaseAggregationCommand( self, CommandCursor, pipeline, kwargs, session is not None, user_fields={"cursor": {"firstBatch": 1}}, ) return self.client._retryable_read( cmd.get_cursor, cmd.get_read_preference(s), # type: ignore[arg-type] s, retryable=not cmd._performs_write, operation=_Op.AGGREGATE, ) def watch( self, pipeline: Optional[_Pipeline] = None, full_document: Optional[str] = None, resume_after: Optional[Mapping[str, Any]] = None, max_await_time_ms: Optional[int] = None, batch_size: Optional[int] = None, collation: Optional[_CollationIn] = None, start_at_operation_time: Optional[Timestamp] = None, session: Optional[ClientSession] = None, start_after: Optional[Mapping[str, Any]] = None, comment: Optional[Any] = None, full_document_before_change: Optional[str] = None, show_expanded_events: Optional[bool] = None, ) -> DatabaseChangeStream[_DocumentType]: """Watch changes on this database. Performs an aggregation with an implicit initial ``$changeStream`` stage and returns a :class:`~pymongo.change_stream.DatabaseChangeStream` cursor which iterates over changes on all collections in this database. Introduced in MongoDB 4.0. .. code-block:: python with db.watch() as stream: for change in stream: print(change) The :class:`~pymongo.change_stream.DatabaseChangeStream` iterable blocks until the next change document is returned or an error is raised. If the :meth:`~pymongo.change_stream.DatabaseChangeStream.next` method encounters a network error when retrieving a batch from the server, it will automatically attempt to recreate the cursor such that no change events are missed. Any error encountered during the resume attempt indicates there may be an outage and will be raised. .. code-block:: python try: with db.watch([{"$match": {"operationType": "insert"}}]) as stream: for insert_change in stream: print(insert_change) except pymongo.errors.PyMongoError: # The ChangeStream encountered an unrecoverable error or the # resume attempt failed to recreate the cursor. logging.error("...") For a precise description of the resume process see the `change streams specification`_. :param pipeline: A list of aggregation pipeline stages to append to an initial ``$changeStream`` stage. Not all pipeline stages are valid after a ``$changeStream`` stage, see the MongoDB documentation on change streams for the supported stages. :param full_document: The fullDocument to pass as an option to the ``$changeStream`` stage. Allowed values: 'updateLookup', 'whenAvailable', 'required'. When set to 'updateLookup', the change notification for partial updates will include both a delta describing the changes to the document, as well as a copy of the entire document that was changed from some time after the change occurred. :param full_document_before_change: Allowed values: 'whenAvailable' and 'required'. Change events may now result in a 'fullDocumentBeforeChange' response field. :param resume_after: A resume token. If provided, the change stream will start returning changes that occur directly after the operation specified in the resume token. A resume token is the _id value of a change document. :param max_await_time_ms: The maximum time in milliseconds for the server to wait for changes before responding to a getMore operation. :param batch_size: The maximum number of documents to return per batch. :param collation: The :class:`~pymongo.collation.Collation` to use for the aggregation. :param start_at_operation_time: If provided, the resulting change stream will only return changes that occurred at or after the specified :class:`~bson.timestamp.Timestamp`. Requires MongoDB >= 4.0. :param session: a :class:`~pymongo.client_session.ClientSession`. :param start_after: The same as `resume_after` except that `start_after` can resume notifications after an invalidate event. This option and `resume_after` are mutually exclusive. :param comment: A user-provided comment to attach to this command. :param show_expanded_events: Include expanded events such as DDL events like `dropIndexes`. :return: A :class:`~pymongo.change_stream.DatabaseChangeStream` cursor. .. versionchanged:: 4.3 Added `show_expanded_events` parameter. .. versionchanged:: 4.2 Added ``full_document_before_change`` parameter. .. versionchanged:: 4.1 Added ``comment`` parameter. .. versionchanged:: 3.9 Added the ``start_after`` parameter. .. versionadded:: 3.7 .. seealso:: The MongoDB documentation on `changeStreams `_. .. _change streams specification: https://github.com/mongodb/specifications/blob/master/source/change-streams/change-streams.md """ return DatabaseChangeStream( self, pipeline, full_document, resume_after, max_await_time_ms, batch_size, collation, start_at_operation_time, session, start_after, comment, full_document_before_change, show_expanded_events=show_expanded_events, ) @overload def _command( self, conn: Connection, command: Union[str, MutableMapping[str, Any]], value: int = 1, check: bool = True, allowable_errors: Optional[Sequence[Union[str, int]]] = None, read_preference: _ServerMode = ReadPreference.PRIMARY, codec_options: CodecOptions[dict[str, Any]] = DEFAULT_CODEC_OPTIONS, write_concern: Optional[WriteConcern] = None, parse_write_concern_error: bool = False, session: Optional[ClientSession] = None, **kwargs: Any, ) -> dict[str, Any]: ... @overload def _command( self, conn: Connection, command: Union[str, MutableMapping[str, Any]], value: int = 1, check: bool = True, allowable_errors: Optional[Sequence[Union[str, int]]] = None, read_preference: _ServerMode = ReadPreference.PRIMARY, codec_options: CodecOptions[_CodecDocumentType] = ..., write_concern: Optional[WriteConcern] = None, parse_write_concern_error: bool = False, session: Optional[ClientSession] = None, **kwargs: Any, ) -> _CodecDocumentType: ... def _command( self, conn: Connection, command: Union[str, MutableMapping[str, Any]], value: int = 1, check: bool = True, allowable_errors: Optional[Sequence[Union[str, int]]] = None, read_preference: _ServerMode = ReadPreference.PRIMARY, codec_options: Union[ CodecOptions[dict[str, Any]], CodecOptions[_CodecDocumentType] ] = DEFAULT_CODEC_OPTIONS, write_concern: Optional[WriteConcern] = None, parse_write_concern_error: bool = False, session: Optional[ClientSession] = None, **kwargs: Any, ) -> Union[dict[str, Any], _CodecDocumentType]: """Internal command helper.""" if isinstance(command, str): command = {command: value} command.update(kwargs) with self.__client._tmp_session(session) as s: return conn.command( self.__name, command, read_preference, codec_options, check, allowable_errors, write_concern=write_concern, parse_write_concern_error=parse_write_concern_error, session=s, client=self.__client, ) @overload def command( self, command: Union[str, MutableMapping[str, Any]], value: Any = 1, check: bool = True, allowable_errors: Optional[Sequence[Union[str, int]]] = None, read_preference: Optional[_ServerMode] = None, codec_options: None = None, session: Optional[ClientSession] = None, comment: Optional[Any] = None, **kwargs: Any, ) -> dict[str, Any]: ... @overload def command( self, command: Union[str, MutableMapping[str, Any]], value: Any = 1, check: bool = True, allowable_errors: Optional[Sequence[Union[str, int]]] = None, read_preference: Optional[_ServerMode] = None, codec_options: CodecOptions[_CodecDocumentType] = ..., session: Optional[ClientSession] = None, comment: Optional[Any] = None, **kwargs: Any, ) -> _CodecDocumentType: ... @_csot.apply def command( self, command: Union[str, MutableMapping[str, Any]], value: Any = 1, check: bool = True, allowable_errors: Optional[Sequence[Union[str, int]]] = None, read_preference: Optional[_ServerMode] = None, codec_options: Optional[bson.codec_options.CodecOptions[_CodecDocumentType]] = None, session: Optional[ClientSession] = None, comment: Optional[Any] = None, **kwargs: Any, ) -> Union[dict[str, Any], _CodecDocumentType]: """Issue a MongoDB command. Send command `command` to the database and return the response. If `command` is an instance of :class:`str` then the command {`command`: `value`} will be sent. Otherwise, `command` must be an instance of :class:`dict` and will be sent as is. Any additional keyword arguments will be added to the final command document before it is sent. For example, a command like ``{buildinfo: 1}`` can be sent using: >>> db.command("buildinfo") OR >>> db.command({"buildinfo": 1}) For a command where the value matters, like ``{count: collection_name}`` we can do: >>> db.command("count", collection_name) OR >>> db.command({"count": collection_name}) For commands that take additional arguments we can use kwargs. So ``{count: collection_name, query: query}`` becomes: >>> db.command("count", collection_name, query=query) OR >>> db.command({"count": collection_name, "query": query}) :param command: document representing the command to be issued, or the name of the command (for simple commands only). .. note:: the order of keys in the `command` document is significant (the "verb" must come first), so commands which require multiple keys (e.g. `findandmodify`) should be done with this in mind. :param value: value to use for the command verb when `command` is passed as a string :param check: check the response for errors, raising :class:`~pymongo.errors.OperationFailure` if there are any :param allowable_errors: if `check` is ``True``, error messages in this list will be ignored by error-checking :param read_preference: The read preference for this operation. See :mod:`~pymongo.read_preferences` for options. If the provided `session` is in a transaction, defaults to the read preference configured for the transaction. Otherwise, defaults to :attr:`~pymongo.read_preferences.ReadPreference.PRIMARY`. :param codec_options: A :class:`~bson.codec_options.CodecOptions` instance. :param session: A :class:`~pymongo.client_session.ClientSession`. :param comment: A user-provided comment to attach to this command. :param kwargs: additional keyword arguments will be added to the command document before it is sent .. note:: :meth:`command` does **not** obey this Database's :attr:`read_preference` or :attr:`codec_options`. You must use the ``read_preference`` and ``codec_options`` parameters instead. .. note:: :meth:`command` does **not** apply any custom TypeDecoders when decoding the command response. .. note:: If this client has been configured to use MongoDB Stable API (see :ref:`versioned-api-ref`), then :meth:`command` will automatically add API versioning options to the given command. Explicitly adding API versioning options in the command and declaring an API version on the client is not supported. .. versionchanged:: 3.6 Added ``session`` parameter. .. versionchanged:: 3.0 Removed the `as_class`, `fields`, `uuid_subtype`, `tag_sets`, and `secondary_acceptable_latency_ms` option. Removed `compile_re` option: PyMongo now always represents BSON regular expressions as :class:`~bson.regex.Regex` objects. Use :meth:`~bson.regex.Regex.try_compile` to attempt to convert from a BSON regular expression to a Python regular expression object. Added the ``codec_options`` parameter. .. seealso:: The MongoDB documentation on `commands `_. """ opts = codec_options or DEFAULT_CODEC_OPTIONS if comment is not None: kwargs["comment"] = comment if isinstance(command, str): command_name = command else: command_name = next(iter(command)) if read_preference is None: read_preference = (session and session._txn_read_preference()) or ReadPreference.PRIMARY with self.__client._conn_for_reads(read_preference, session, operation=command_name) as ( connection, read_preference, ): return self._command( connection, command, value, check, allowable_errors, read_preference, opts, session=session, **kwargs, ) @_csot.apply def cursor_command( self, command: Union[str, MutableMapping[str, Any]], value: Any = 1, read_preference: Optional[_ServerMode] = None, codec_options: Optional[bson.codec_options.CodecOptions[_CodecDocumentType]] = None, session: Optional[ClientSession] = None, comment: Optional[Any] = None, max_await_time_ms: Optional[int] = None, **kwargs: Any, ) -> CommandCursor[_DocumentType]: """Issue a MongoDB command and parse the response as a cursor. If the response from the server does not include a cursor field, an error will be thrown. Otherwise, behaves identically to issuing a normal MongoDB command. :param command: document representing the command to be issued, or the name of the command (for simple commands only). .. note:: the order of keys in the `command` document is significant (the "verb" must come first), so commands which require multiple keys (e.g. `findandmodify`) should use an instance of :class:`~bson.son.SON` or a string and kwargs instead of a Python `dict`. :param value: value to use for the command verb when `command` is passed as a string :param read_preference: The read preference for this operation. See :mod:`~pymongo.read_preferences` for options. If the provided `session` is in a transaction, defaults to the read preference configured for the transaction. Otherwise, defaults to :attr:`~pymongo.read_preferences.ReadPreference.PRIMARY`. :param codec_options`: A :class:`~bson.codec_options.CodecOptions` instance. :param session: A :class:`~pymongo.client_session.ClientSession`. :param comment: A user-provided comment to attach to future getMores for this command. :param max_await_time_ms: The number of ms to wait for more data on future getMores for this command. :param kwargs: additional keyword arguments will be added to the command document before it is sent .. note:: :meth:`command` does **not** obey this Database's :attr:`read_preference` or :attr:`codec_options`. You must use the ``read_preference`` and ``codec_options`` parameters instead. .. note:: :meth:`command` does **not** apply any custom TypeDecoders when decoding the command response. .. note:: If this client has been configured to use MongoDB Stable API (see :ref:`versioned-api-ref`), then :meth:`command` will automatically add API versioning options to the given command. Explicitly adding API versioning options in the command and declaring an API version on the client is not supported. .. seealso:: The MongoDB documentation on `commands `_. """ if isinstance(command, str): command_name = command else: command_name = next(iter(command)) with self.__client._tmp_session(session, close=False) as tmp_session: opts = codec_options or DEFAULT_CODEC_OPTIONS if read_preference is None: read_preference = ( tmp_session and tmp_session._txn_read_preference() ) or ReadPreference.PRIMARY with self.__client._conn_for_reads(read_preference, tmp_session, command_name) as ( conn, read_preference, ): response = self._command( conn, command, value, True, None, read_preference, opts, session=tmp_session, **kwargs, ) coll = self.get_collection("$cmd", read_preference=read_preference) if response.get("cursor"): cmd_cursor = CommandCursor( coll, response["cursor"], conn.address, max_await_time_ms=max_await_time_ms, session=tmp_session, explicit_session=session is not None, comment=comment, ) cmd_cursor._maybe_pin_connection(conn) return cmd_cursor else: raise InvalidOperation("Command does not return a cursor.") def _retryable_read_command( self, command: Union[str, MutableMapping[str, Any]], operation: str, session: Optional[ClientSession] = None, ) -> dict[str, Any]: """Same as command but used for retryable read commands.""" read_preference = (session and session._txn_read_preference()) or ReadPreference.PRIMARY def _cmd( session: Optional[ClientSession], _server: Server, conn: Connection, read_preference: _ServerMode, ) -> dict[str, Any]: return self._command( conn, command, read_preference=read_preference, session=session, ) return self.__client._retryable_read(_cmd, read_preference, session, operation) def _list_collections( self, conn: Connection, session: Optional[ClientSession], read_preference: _ServerMode, **kwargs: Any, ) -> CommandCursor[MutableMapping[str, Any]]: """Internal listCollections helper.""" coll = cast( Collection[MutableMapping[str, Any]], self.get_collection("$cmd", read_preference=read_preference), ) cmd = {"listCollections": 1, "cursor": {}} cmd.update(kwargs) with self.__client._tmp_session(session, close=False) as tmp_session: cursor = self._command(conn, cmd, read_preference=read_preference, session=tmp_session)[ "cursor" ] cmd_cursor = CommandCursor( coll, cursor, conn.address, session=tmp_session, explicit_session=session is not None, comment=cmd.get("comment"), ) cmd_cursor._maybe_pin_connection(conn) return cmd_cursor def list_collections( self, session: Optional[ClientSession] = None, filter: Optional[Mapping[str, Any]] = None, comment: Optional[Any] = None, **kwargs: Any, ) -> CommandCursor[MutableMapping[str, Any]]: """Get a cursor over the collections of this database. :param session: a :class:`~pymongo.client_session.ClientSession`. :param filter: A query document to filter the list of collections returned from the listCollections command. :param comment: A user-provided comment to attach to this command. :param kwargs: Optional parameters of the `listCollections command `_ can be passed as keyword arguments to this method. The supported options differ by server version. :return: An instance of :class:`~pymongo.command_cursor.CommandCursor`. .. versionadded:: 3.6 """ if filter is not None: kwargs["filter"] = filter read_pref = (session and session._txn_read_preference()) or ReadPreference.PRIMARY if comment is not None: kwargs["comment"] = comment def _cmd( session: Optional[ClientSession], _server: Server, conn: Connection, read_preference: _ServerMode, ) -> CommandCursor[MutableMapping[str, Any]]: return self._list_collections(conn, session, read_preference=read_preference, **kwargs) return self.__client._retryable_read( _cmd, read_pref, session, operation=_Op.LIST_COLLECTIONS ) def list_collection_names( self, session: Optional[ClientSession] = None, filter: Optional[Mapping[str, Any]] = None, comment: Optional[Any] = None, **kwargs: Any, ) -> list[str]: """Get a list of all the collection names in this database. For example, to list all non-system collections:: filter = {"name": {"$regex": r"^(?!system\\.)"}} db.list_collection_names(filter=filter) :param session: a :class:`~pymongo.client_session.ClientSession`. :param filter: A query document to filter the list of collections returned from the listCollections command. :param comment: A user-provided comment to attach to this command. :param kwargs: Optional parameters of the `listCollections command `_ can be passed as keyword arguments to this method. The supported options differ by server version. .. versionchanged:: 3.8 Added the ``filter`` and ``**kwargs`` parameters. .. versionadded:: 3.6 """ if comment is not None: kwargs["comment"] = comment if filter is None: kwargs["nameOnly"] = True else: # The enumerate collections spec states that "drivers MUST NOT set # nameOnly if a filter specifies any keys other than name." common.validate_is_mapping("filter", filter) kwargs["filter"] = filter if not filter or (len(filter) == 1 and "name" in filter): kwargs["nameOnly"] = True return [result["name"] for result in self.list_collections(session=session, **kwargs)] def _drop_helper( self, name: str, session: Optional[ClientSession] = None, comment: Optional[Any] = None ) -> dict[str, Any]: command = {"drop": name} if comment is not None: command["comment"] = comment with self.__client._conn_for_writes(session, operation=_Op.DROP) as connection: return self._command( connection, command, allowable_errors=["ns not found", 26], write_concern=self._write_concern_for(session), parse_write_concern_error=True, session=session, ) @_csot.apply def drop_collection( self, name_or_collection: Union[str, Collection[_DocumentTypeArg]], session: Optional[ClientSession] = None, comment: Optional[Any] = None, encrypted_fields: Optional[Mapping[str, Any]] = None, ) -> dict[str, Any]: """Drop a collection. :param name_or_collection: the name of a collection to drop or the collection object itself :param session: a :class:`~pymongo.client_session.ClientSession`. :param comment: A user-provided comment to attach to this command. :param encrypted_fields: **(BETA)** Document that describes the encrypted fields for Queryable Encryption. For example:: { "escCollection": "enxcol_.encryptedCollection.esc", "ecocCollection": "enxcol_.encryptedCollection.ecoc", "fields": [ { "path": "firstName", "keyId": Binary.from_uuid(UUID('00000000-0000-0000-0000-000000000000')), "bsonType": "string", "queries": {"queryType": "equality"} }, { "path": "ssn", "keyId": Binary.from_uuid(UUID('04104104-1041-0410-4104-104104104104')), "bsonType": "string" } ] } .. note:: The :attr:`~pymongo.database.Database.write_concern` of this database is automatically applied to this operation. .. versionchanged:: 4.2 Added ``encrypted_fields`` parameter. .. versionchanged:: 4.1 Added ``comment`` parameter. .. versionchanged:: 3.6 Added ``session`` parameter. .. versionchanged:: 3.4 Apply this database's write concern automatically to this operation when connected to MongoDB >= 3.4. """ name = name_or_collection if isinstance(name, Collection): name = name.name if not isinstance(name, str): raise TypeError("name_or_collection must be an instance of str") encrypted_fields = self._get_encrypted_fields( {"encryptedFields": encrypted_fields}, name, True, ) if encrypted_fields: common.validate_is_mapping("encrypted_fields", encrypted_fields) self._drop_helper( _esc_coll_name(encrypted_fields, name), session=session, comment=comment ) self._drop_helper( _ecoc_coll_name(encrypted_fields, name), session=session, comment=comment ) return self._drop_helper(name, session, comment) def validate_collection( self, name_or_collection: Union[str, Collection[_DocumentTypeArg]], scandata: bool = False, full: bool = False, session: Optional[ClientSession] = None, background: Optional[bool] = None, comment: Optional[Any] = None, ) -> dict[str, Any]: """Validate a collection. Returns a dict of validation info. Raises CollectionInvalid if validation fails. See also the MongoDB documentation on the `validate command`_. :param name_or_collection: A Collection object or the name of a collection to validate. :param scandata: Do extra checks beyond checking the overall structure of the collection. :param full: Have the server do a more thorough scan of the collection. Use with `scandata` for a thorough scan of the structure of the collection and the individual documents. :param session: a :class:`~pymongo.client_session.ClientSession`. :param background: A boolean flag that determines whether the command runs in the background. Requires MongoDB 4.4+. :param comment: A user-provided comment to attach to this command. .. versionchanged:: 4.1 Added ``comment`` parameter. .. versionchanged:: 3.11 Added ``background`` parameter. .. versionchanged:: 3.6 Added ``session`` parameter. .. _validate command: https://mongodb.com/docs/manual/reference/command/validate/ """ name = name_or_collection if isinstance(name, Collection): name = name.name if not isinstance(name, str): raise TypeError("name_or_collection must be an instance of str or Collection") cmd = {"validate": name, "scandata": scandata, "full": full} if comment is not None: cmd["comment"] = comment if background is not None: cmd["background"] = background result = self.command(cmd, session=session) valid = True # Pre 1.9 results if "result" in result: info = result["result"] if info.find("exception") != -1 or info.find("corrupt") != -1: raise CollectionInvalid(f"{name} invalid: {info}") # Sharded results elif "raw" in result: for _, res in result["raw"].items(): if "result" in res: info = res["result"] if info.find("exception") != -1 or info.find("corrupt") != -1: raise CollectionInvalid(f"{name} invalid: {info}") elif not res.get("valid", False): valid = False break # Post 1.9 non-sharded results. elif not result.get("valid", False): valid = False if not valid: raise CollectionInvalid(f"{name} invalid: {result!r}") return result # See PYTHON-3084. __iter__ = None def __next__(self) -> NoReturn: raise TypeError("'Database' object is not iterable") next = __next__ def __bool__(self) -> NoReturn: raise NotImplementedError( "Database objects do not implement truth " "value testing or bool(). Please compare " "with None instead: database is not None" ) def dereference( self, dbref: DBRef, session: Optional[ClientSession] = None, comment: Optional[Any] = None, **kwargs: Any, ) -> Optional[_DocumentType]: """Dereference a :class:`~bson.dbref.DBRef`, getting the document it points to. Raises :class:`TypeError` if `dbref` is not an instance of :class:`~bson.dbref.DBRef`. Returns a document, or ``None`` if the reference does not point to a valid document. Raises :class:`ValueError` if `dbref` has a database specified that is different from the current database. :param dbref: the reference :param session: a :class:`~pymongo.client_session.ClientSession`. :param comment: A user-provided comment to attach to this command. :param kwargs: any additional keyword arguments are the same as the arguments to :meth:`~pymongo.collection.Collection.find`. .. versionchanged:: 4.1 Added ``comment`` parameter. .. versionchanged:: 3.6 Added ``session`` parameter. """ if not isinstance(dbref, DBRef): raise TypeError("cannot dereference a %s" % type(dbref)) if dbref.database is not None and dbref.database != self.__name: raise ValueError( "trying to dereference a DBRef that points to " f"another database ({dbref.database!r} not {self.__name!r})" ) return self[dbref.collection].find_one( {"_id": dbref.id}, session=session, comment=comment, **kwargs ) mongodb-mongo-python-driver-509e9b7/pymongo/driver_info.py000066400000000000000000000032511462766011000240060ustar00rootroot00000000000000# Copyright 2018-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. """Advanced options for MongoDB drivers implemented on top of PyMongo.""" from __future__ import annotations from collections import namedtuple from typing import Optional class DriverInfo(namedtuple("DriverInfo", ["name", "version", "platform"])): """Info about a driver wrapping PyMongo. The MongoDB server logs PyMongo's name, version, and platform whenever PyMongo establishes a connection. A driver implemented on top of PyMongo can add its own info to this log message. Initialize with three strings like 'MyDriver', '1.2.3', 'some platform info'. Any of these strings may be None to accept PyMongo's default. """ def __new__( cls, name: str, version: Optional[str] = None, platform: Optional[str] = None ) -> DriverInfo: self = super().__new__(cls, name, version, platform) for key, value in self._asdict().items(): if value is not None and not isinstance(value, str): raise TypeError( f"Wrong type for DriverInfo {key} option, value must be an instance of str" ) return self mongodb-mongo-python-driver-509e9b7/pymongo/encryption.py000066400000000000000000001270471462766011000237040ustar00rootroot00000000000000# Copyright 2019-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. """Support for explicit client-side field level encryption.""" from __future__ import annotations import contextlib import enum import socket import uuid import weakref from copy import deepcopy from typing import ( TYPE_CHECKING, Any, Dict, Generic, Iterator, Mapping, MutableMapping, Optional, Sequence, Union, cast, ) try: from pymongocrypt.auto_encrypter import AutoEncrypter # type:ignore[import] from pymongocrypt.errors import MongoCryptError # type:ignore[import] from pymongocrypt.explicit_encrypter import ExplicitEncrypter # type:ignore[import] from pymongocrypt.mongocrypt import MongoCryptOptions # type:ignore[import] from pymongocrypt.state_machine import MongoCryptCallback # type:ignore[import] _HAVE_PYMONGOCRYPT = True except ImportError: _HAVE_PYMONGOCRYPT = False MongoCryptCallback = object from bson import _dict_to_bson, decode, encode from bson.binary import STANDARD, UUID_SUBTYPE, Binary from bson.codec_options import CodecOptions from bson.errors import BSONError from bson.raw_bson import DEFAULT_RAW_BSON_OPTIONS, RawBSONDocument, _inflate_bson from pymongo import _csot from pymongo.collection import Collection from pymongo.common import CONNECT_TIMEOUT from pymongo.cursor import Cursor from pymongo.daemon import _spawn_daemon from pymongo.database import Database from pymongo.encryption_options import AutoEncryptionOpts, RangeOpts from pymongo.errors import ( ConfigurationError, EncryptedCollectionError, EncryptionError, InvalidOperation, PyMongoError, ServerSelectionTimeoutError, ) from pymongo.mongo_client import MongoClient from pymongo.network import BLOCKING_IO_ERRORS from pymongo.operations import UpdateOne from pymongo.pool import PoolOptions, _configured_socket, _raise_connection_failure from pymongo.read_concern import ReadConcern from pymongo.results import BulkWriteResult, DeleteResult from pymongo.ssl_support import get_ssl_context from pymongo.typings import _DocumentType, _DocumentTypeArg from pymongo.uri_parser import parse_host from pymongo.write_concern import WriteConcern if TYPE_CHECKING: from pymongocrypt.mongocrypt import MongoCryptKmsContext _HTTPS_PORT = 443 _KMS_CONNECT_TIMEOUT = CONNECT_TIMEOUT # CDRIVER-3262 redefined this value to CONNECT_TIMEOUT _MONGOCRYPTD_TIMEOUT_MS = 10000 _DATA_KEY_OPTS: CodecOptions[dict[str, Any]] = CodecOptions( document_class=Dict[str, Any], uuid_representation=STANDARD ) # Use RawBSONDocument codec options to avoid needlessly decoding # documents from the key vault. _KEY_VAULT_OPTS = CodecOptions(document_class=RawBSONDocument) @contextlib.contextmanager def _wrap_encryption_errors() -> Iterator[None]: """Context manager to wrap encryption related errors.""" try: yield except BSONError: # BSON encoding/decoding errors are unrelated to encryption so # we should propagate them unchanged. raise except Exception as exc: raise EncryptionError(exc) from exc class _EncryptionIO(MongoCryptCallback): # type: ignore[misc] def __init__( self, client: Optional[MongoClient[_DocumentTypeArg]], key_vault_coll: Collection[_DocumentTypeArg], mongocryptd_client: Optional[MongoClient[_DocumentTypeArg]], opts: AutoEncryptionOpts, ): """Internal class to perform I/O on behalf of pymongocrypt.""" self.client_ref: Any # Use a weak ref to break reference cycle. if client is not None: self.client_ref = weakref.ref(client) else: self.client_ref = None self.key_vault_coll: Optional[Collection[RawBSONDocument]] = cast( Collection[RawBSONDocument], key_vault_coll.with_options( codec_options=_KEY_VAULT_OPTS, read_concern=ReadConcern(level="majority"), write_concern=WriteConcern(w="majority"), ), ) self.mongocryptd_client = mongocryptd_client self.opts = opts self._spawned = False def kms_request(self, kms_context: MongoCryptKmsContext) -> None: """Complete a KMS request. :param kms_context: A :class:`MongoCryptKmsContext`. :return: None """ endpoint = kms_context.endpoint message = kms_context.message provider = kms_context.kms_provider ctx = self.opts._kms_ssl_contexts.get(provider) if ctx is None: # Enable strict certificate verification, OCSP, match hostname, and # SNI using the system default CA certificates. ctx = get_ssl_context( None, # certfile None, # passphrase None, # ca_certs None, # crlfile False, # allow_invalid_certificates False, # allow_invalid_hostnames False, ) # disable_ocsp_endpoint_check # CSOT: set timeout for socket creation. connect_timeout = max(_csot.clamp_remaining(_KMS_CONNECT_TIMEOUT), 0.001) opts = PoolOptions( connect_timeout=connect_timeout, socket_timeout=connect_timeout, ssl_context=ctx, ) host, port = parse_host(endpoint, _HTTPS_PORT) try: conn = _configured_socket((host, port), opts) try: conn.sendall(message) while kms_context.bytes_needed > 0: # CSOT: update timeout. conn.settimeout(max(_csot.clamp_remaining(_KMS_CONNECT_TIMEOUT), 0)) data = conn.recv(kms_context.bytes_needed) if not data: raise OSError("KMS connection closed") kms_context.feed(data) except BLOCKING_IO_ERRORS: raise socket.timeout("timed out") from None finally: conn.close() except (PyMongoError, MongoCryptError): raise # Propagate pymongo errors directly. except Exception as error: # Wrap I/O errors in PyMongo exceptions. _raise_connection_failure((host, port), error) def collection_info( self, database: Database[Mapping[str, Any]], filter: bytes ) -> Optional[bytes]: """Get the collection info for a namespace. The returned collection info is passed to libmongocrypt which reads the JSON schema. :param database: The database on which to run listCollections. :param filter: The filter to pass to listCollections. :return: The first document from the listCollections command response as BSON. """ with self.client_ref()[database].list_collections(filter=RawBSONDocument(filter)) as cursor: for doc in cursor: return _dict_to_bson(doc, False, _DATA_KEY_OPTS) return None def spawn(self) -> None: """Spawn mongocryptd. Note this method is thread safe; at most one mongocryptd will start successfully. """ self._spawned = True args = [self.opts._mongocryptd_spawn_path or "mongocryptd"] args.extend(self.opts._mongocryptd_spawn_args) _spawn_daemon(args) def mark_command(self, database: str, cmd: bytes) -> bytes: """Mark a command for encryption. :param database: The database on which to run this command. :param cmd: The BSON command to run. :return: The marked command response from mongocryptd. """ if not self._spawned and not self.opts._mongocryptd_bypass_spawn: self.spawn() # Database.command only supports mutable mappings so we need to decode # the raw BSON command first. inflated_cmd = _inflate_bson(cmd, DEFAULT_RAW_BSON_OPTIONS) assert self.mongocryptd_client is not None try: res = self.mongocryptd_client[database].command( inflated_cmd, codec_options=DEFAULT_RAW_BSON_OPTIONS ) except ServerSelectionTimeoutError: if self.opts._mongocryptd_bypass_spawn: raise self.spawn() res = self.mongocryptd_client[database].command( inflated_cmd, codec_options=DEFAULT_RAW_BSON_OPTIONS ) return res.raw def fetch_keys(self, filter: bytes) -> Iterator[bytes]: """Yields one or more keys from the key vault. :param filter: The filter to pass to find. :return: A generator which yields the requested keys from the key vault. """ assert self.key_vault_coll is not None with self.key_vault_coll.find(RawBSONDocument(filter)) as cursor: for key in cursor: yield key.raw def insert_data_key(self, data_key: bytes) -> Binary: """Insert a data key into the key vault. :param data_key: The data key document to insert. :return: The _id of the inserted data key document. """ raw_doc = RawBSONDocument(data_key, _KEY_VAULT_OPTS) data_key_id = raw_doc.get("_id") if not isinstance(data_key_id, Binary) or data_key_id.subtype != UUID_SUBTYPE: raise TypeError("data_key _id must be Binary with a UUID subtype") assert self.key_vault_coll is not None self.key_vault_coll.insert_one(raw_doc) return data_key_id def bson_encode(self, doc: MutableMapping[str, Any]) -> bytes: """Encode a document to BSON. A document can be any mapping type (like :class:`dict`). :param doc: mapping type representing a document :return: The encoded BSON bytes. """ return encode(doc) def close(self) -> None: """Release resources. Note it is not safe to call this method from __del__ or any GC hooks. """ self.client_ref = None self.key_vault_coll = None if self.mongocryptd_client: self.mongocryptd_client.close() self.mongocryptd_client = None class RewrapManyDataKeyResult: """Result object returned by a :meth:`~ClientEncryption.rewrap_many_data_key` operation. .. versionadded:: 4.2 """ def __init__(self, bulk_write_result: Optional[BulkWriteResult] = None) -> None: self._bulk_write_result = bulk_write_result @property def bulk_write_result(self) -> Optional[BulkWriteResult]: """The result of the bulk write operation used to update the key vault collection with one or more rewrapped data keys. If :meth:`~ClientEncryption.rewrap_many_data_key` does not find any matching keys to rewrap, no bulk write operation will be executed and this field will be ``None``. """ return self._bulk_write_result def __repr__(self) -> str: return f"{self.__class__.__name__}({self._bulk_write_result!r})" class _Encrypter: """Encrypts and decrypts MongoDB commands. This class is used to support automatic encryption and decryption of MongoDB commands. """ def __init__(self, client: MongoClient[_DocumentTypeArg], opts: AutoEncryptionOpts): """Create a _Encrypter for a client. :param client: The encrypted MongoClient. :param opts: The encrypted client's :class:`AutoEncryptionOpts`. """ if opts._schema_map is None: schema_map = None else: schema_map = _dict_to_bson(opts._schema_map, False, _DATA_KEY_OPTS) if opts._encrypted_fields_map is None: encrypted_fields_map = None else: encrypted_fields_map = _dict_to_bson(opts._encrypted_fields_map, False, _DATA_KEY_OPTS) self._bypass_auto_encryption = opts._bypass_auto_encryption self._internal_client = None def _get_internal_client( encrypter: _Encrypter, mongo_client: MongoClient[_DocumentTypeArg] ) -> MongoClient[_DocumentTypeArg]: if mongo_client.options.pool_options.max_pool_size is None: # Unlimited pool size, use the same client. return mongo_client # Else - limited pool size, use an internal client. if encrypter._internal_client is not None: return encrypter._internal_client internal_client = mongo_client._duplicate(minPoolSize=0, auto_encryption_opts=None) encrypter._internal_client = internal_client return internal_client if opts._key_vault_client is not None: key_vault_client = opts._key_vault_client else: key_vault_client = _get_internal_client(self, client) if opts._bypass_auto_encryption: metadata_client = None else: metadata_client = _get_internal_client(self, client) db, coll = opts._key_vault_namespace.split(".", 1) key_vault_coll = key_vault_client[db][coll] mongocryptd_client: MongoClient[Mapping[str, Any]] = MongoClient( opts._mongocryptd_uri, connect=False, serverSelectionTimeoutMS=_MONGOCRYPTD_TIMEOUT_MS ) io_callbacks = _EncryptionIO( # type:ignore[misc] metadata_client, key_vault_coll, mongocryptd_client, opts ) self._auto_encrypter = AutoEncrypter( io_callbacks, MongoCryptOptions( opts._kms_providers, schema_map, crypt_shared_lib_path=opts._crypt_shared_lib_path, crypt_shared_lib_required=opts._crypt_shared_lib_required, bypass_encryption=opts._bypass_auto_encryption, encrypted_fields_map=encrypted_fields_map, bypass_query_analysis=opts._bypass_query_analysis, ), ) self._closed = False def encrypt( self, database: str, cmd: Mapping[str, Any], codec_options: CodecOptions[_DocumentTypeArg] ) -> dict[str, Any]: """Encrypt a MongoDB command. :param database: The database for this command. :param cmd: A command document. :param codec_options: The CodecOptions to use while encoding `cmd`. :return: The encrypted command to execute. """ self._check_closed() encoded_cmd = _dict_to_bson(cmd, False, codec_options) with _wrap_encryption_errors(): encrypted_cmd = self._auto_encrypter.encrypt(database, encoded_cmd) # TODO: PYTHON-1922 avoid decoding the encrypted_cmd. return _inflate_bson(encrypted_cmd, DEFAULT_RAW_BSON_OPTIONS) def decrypt(self, response: bytes) -> Optional[bytes]: """Decrypt a MongoDB command response. :param response: A MongoDB command response as BSON. :return: The decrypted command response. """ self._check_closed() with _wrap_encryption_errors(): return cast(bytes, self._auto_encrypter.decrypt(response)) def _check_closed(self) -> None: if self._closed: raise InvalidOperation("Cannot use MongoClient after close") def close(self) -> None: """Cleanup resources.""" self._closed = True self._auto_encrypter.close() if self._internal_client: self._internal_client.close() self._internal_client = None class Algorithm(str, enum.Enum): """An enum that defines the supported encryption algorithms.""" AEAD_AES_256_CBC_HMAC_SHA_512_Deterministic = "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" """AEAD_AES_256_CBC_HMAC_SHA_512_Deterministic.""" AEAD_AES_256_CBC_HMAC_SHA_512_Random = "AEAD_AES_256_CBC_HMAC_SHA_512-Random" """AEAD_AES_256_CBC_HMAC_SHA_512_Random.""" INDEXED = "Indexed" """Indexed. .. versionadded:: 4.2 """ UNINDEXED = "Unindexed" """Unindexed. .. versionadded:: 4.2 """ RANGEPREVIEW = "RangePreview" """RangePreview. .. note:: Support for Range queries is in beta. Backwards-breaking changes may be made before the final release. .. versionadded:: 4.4 """ class QueryType(str, enum.Enum): """An enum that defines the supported values for explicit encryption query_type. .. versionadded:: 4.2 """ EQUALITY = "equality" """Used to encrypt a value for an equality query.""" RANGEPREVIEW = "rangePreview" """Used to encrypt a value for a range query. .. note:: Support for Range queries is in beta. Backwards-breaking changes may be made before the final release. """ class ClientEncryption(Generic[_DocumentType]): """Explicit client-side field level encryption.""" def __init__( self, kms_providers: Mapping[str, Any], key_vault_namespace: str, key_vault_client: MongoClient[_DocumentTypeArg], codec_options: CodecOptions[_DocumentTypeArg], kms_tls_options: Optional[Mapping[str, Any]] = None, ) -> None: """Explicit client-side field level encryption. The ClientEncryption class encapsulates explicit operations on a key vault collection that cannot be done directly on a MongoClient. Similar to configuring auto encryption on a MongoClient, it is constructed with a MongoClient (to a MongoDB cluster containing the key vault collection), KMS provider configuration, and keyVaultNamespace. It provides an API for explicitly encrypting and decrypting values, and creating data keys. It does not provide an API to query keys from the key vault collection, as this can be done directly on the MongoClient. See :ref:`explicit-client-side-encryption` for an example. :param kms_providers: Map of KMS provider options. The `kms_providers` map values differ by provider: - `aws`: Map with "accessKeyId" and "secretAccessKey" as strings. These are the AWS access key ID and AWS secret access key used to generate KMS messages. An optional "sessionToken" may be included to support temporary AWS credentials. - `azure`: Map with "tenantId", "clientId", and "clientSecret" as strings. Additionally, "identityPlatformEndpoint" may also be specified as a string (defaults to 'login.microsoftonline.com'). These are the Azure Active Directory credentials used to generate Azure Key Vault messages. - `gcp`: Map with "email" as a string and "privateKey" as `bytes` or a base64 encoded string. Additionally, "endpoint" may also be specified as a string (defaults to 'oauth2.googleapis.com'). These are the credentials used to generate Google Cloud KMS messages. - `kmip`: Map with "endpoint" as a host with required port. For example: ``{"endpoint": "example.com:443"}``. - `local`: Map with "key" as `bytes` (96 bytes in length) or a base64 encoded string which decodes to 96 bytes. "key" is the master key used to encrypt/decrypt data keys. This key should be generated and stored as securely as possible. KMS providers may be specified with an optional name suffix separated by a colon, for example "kmip:name" or "aws:name". Named KMS providers do not support :ref:`CSFLE on-demand credentials`. :param key_vault_namespace: The namespace for the key vault collection. The key vault collection contains all data keys used for encryption and decryption. Data keys are stored as documents in this MongoDB collection. Data keys are protected with encryption by a KMS provider. :param key_vault_client: A MongoClient connected to a MongoDB cluster containing the `key_vault_namespace` collection. :param codec_options: An instance of :class:`~bson.codec_options.CodecOptions` to use when encoding a value for encryption and decoding the decrypted BSON value. This should be the same CodecOptions instance configured on the MongoClient, Database, or Collection used to access application data. :param kms_tls_options: A map of KMS provider names to TLS options to use when creating secure connections to KMS providers. Accepts the same TLS options as :class:`pymongo.mongo_client.MongoClient`. For example, to override the system default CA file:: kms_tls_options={'kmip': {'tlsCAFile': certifi.where()}} Or to supply a client certificate:: kms_tls_options={'kmip': {'tlsCertificateKeyFile': 'client.pem'}} .. versionchanged:: 4.0 Added the `kms_tls_options` parameter and the "kmip" KMS provider. .. versionadded:: 3.9 """ if not _HAVE_PYMONGOCRYPT: raise ConfigurationError( "client-side field level encryption requires the pymongocrypt " "library: install a compatible version with: " "python -m pip install 'pymongo[encryption]'" ) if not isinstance(codec_options, CodecOptions): raise TypeError("codec_options must be an instance of bson.codec_options.CodecOptions") self._kms_providers = kms_providers self._key_vault_namespace = key_vault_namespace self._key_vault_client = key_vault_client self._codec_options = codec_options db, coll = key_vault_namespace.split(".", 1) key_vault_coll = key_vault_client[db][coll] opts = AutoEncryptionOpts( kms_providers, key_vault_namespace, kms_tls_options=kms_tls_options ) self._io_callbacks: Optional[_EncryptionIO] = _EncryptionIO( None, key_vault_coll, None, opts ) self._encryption = ExplicitEncrypter( self._io_callbacks, MongoCryptOptions(kms_providers, None) ) # Use the same key vault collection as the callback. assert self._io_callbacks.key_vault_coll is not None self._key_vault_coll = self._io_callbacks.key_vault_coll def create_encrypted_collection( self, database: Database[_DocumentTypeArg], name: str, encrypted_fields: Mapping[str, Any], kms_provider: Optional[str] = None, master_key: Optional[Mapping[str, Any]] = None, **kwargs: Any, ) -> tuple[Collection[_DocumentTypeArg], Mapping[str, Any]]: """Create a collection with encryptedFields. .. warning:: This function does not update the encryptedFieldsMap in the client's AutoEncryptionOpts, thus the user must create a new client after calling this function with the encryptedFields returned. Normally collection creation is automatic. This method should only be used to specify options on creation. :class:`~pymongo.errors.EncryptionError` will be raised if the collection already exists. :param name: the name of the collection to create :param encrypted_fields: Document that describes the encrypted fields for Queryable Encryption. The "keyId" may be set to ``None`` to auto-generate the data keys. For example: .. code-block: python { "escCollection": "enxcol_.encryptedCollection.esc", "ecocCollection": "enxcol_.encryptedCollection.ecoc", "fields": [ { "path": "firstName", "keyId": Binary.from_uuid(UUID('00000000-0000-0000-0000-000000000000')), "bsonType": "string", "queries": {"queryType": "equality"} }, { "path": "ssn", "keyId": Binary.from_uuid(UUID('04104104-1041-0410-4104-104104104104')), "bsonType": "string" } ] } :param kms_provider: the KMS provider to be used :param master_key: Identifies a KMS-specific key used to encrypt the new data key. If the kmsProvider is "local" the `master_key` is not applicable and may be omitted. :param kwargs: additional keyword arguments are the same as "create_collection". All optional `create collection command`_ parameters should be passed as keyword arguments to this method. See the documentation for :meth:`~pymongo.database.Database.create_collection` for all valid options. :raises: - :class:`~pymongo.errors.EncryptedCollectionError`: When either data-key creation or creating the collection fails. .. versionadded:: 4.4 .. _create collection command: https://mongodb.com/docs/manual/reference/command/create """ encrypted_fields = deepcopy(encrypted_fields) for i, field in enumerate(encrypted_fields["fields"]): if isinstance(field, dict) and field.get("keyId") is None: try: encrypted_fields["fields"][i]["keyId"] = self.create_data_key( kms_provider=kms_provider, # type:ignore[arg-type] master_key=master_key, ) except EncryptionError as exc: raise EncryptedCollectionError(exc, encrypted_fields) from exc kwargs["encryptedFields"] = encrypted_fields kwargs["check_exists"] = False try: return ( database.create_collection(name=name, **kwargs), encrypted_fields, ) except Exception as exc: raise EncryptedCollectionError(exc, encrypted_fields) from exc def create_data_key( self, kms_provider: str, master_key: Optional[Mapping[str, Any]] = None, key_alt_names: Optional[Sequence[str]] = None, key_material: Optional[bytes] = None, ) -> Binary: """Create and insert a new data key into the key vault collection. :param kms_provider: The KMS provider to use. Supported values are "aws", "azure", "gcp", "kmip", "local", or a named provider like "kmip:name". :param master_key: Identifies a KMS-specific key used to encrypt the new data key. If the kmsProvider is "local" the `master_key` is not applicable and may be omitted. If the `kms_provider` type is "aws" it is required and has the following fields:: - `region` (string): Required. The AWS region, e.g. "us-east-1". - `key` (string): Required. The Amazon Resource Name (ARN) to the AWS customer. - `endpoint` (string): Optional. An alternate host to send KMS requests to. May include port number, e.g. "kms.us-east-1.amazonaws.com:443". If the `kms_provider` type is "azure" it is required and has the following fields:: - `keyVaultEndpoint` (string): Required. Host with optional port, e.g. "example.vault.azure.net". - `keyName` (string): Required. Key name in the key vault. - `keyVersion` (string): Optional. Version of the key to use. If the `kms_provider` type is "gcp" it is required and has the following fields:: - `projectId` (string): Required. The Google cloud project ID. - `location` (string): Required. The GCP location, e.g. "us-east1". - `keyRing` (string): Required. Name of the key ring that contains the key to use. - `keyName` (string): Required. Name of the key to use. - `keyVersion` (string): Optional. Version of the key to use. - `endpoint` (string): Optional. Host with optional port. Defaults to "cloudkms.googleapis.com". If the `kms_provider` type is "kmip" it is optional and has the following fields:: - `keyId` (string): Optional. `keyId` is the KMIP Unique Identifier to a 96 byte KMIP Secret Data managed object. If keyId is omitted, the driver creates a random 96 byte KMIP Secret Data managed object. - `endpoint` (string): Optional. Host with optional port, e.g. "example.vault.azure.net:". :param key_alt_names: An optional list of string alternate names used to reference a key. If a key is created with alternate names, then encryption may refer to the key by the unique alternate name instead of by ``key_id``. The following example shows creating and referring to a data key by alternate name:: client_encryption.create_data_key("local", key_alt_names=["name1"]) # reference the key with the alternate name client_encryption.encrypt("457-55-5462", key_alt_name="name1", algorithm=Algorithm.AEAD_AES_256_CBC_HMAC_SHA_512_Random) :param key_material: Sets the custom key material to be used by the data key for encryption and decryption. :return: The ``_id`` of the created data key document as a :class:`~bson.binary.Binary` with subtype :data:`~bson.binary.UUID_SUBTYPE`. .. versionchanged:: 4.2 Added the `key_material` parameter. """ self._check_closed() with _wrap_encryption_errors(): return cast( Binary, self._encryption.create_data_key( kms_provider, master_key=master_key, key_alt_names=key_alt_names, key_material=key_material, ), ) def _encrypt_helper( self, value: Any, algorithm: str, key_id: Optional[Union[Binary, uuid.UUID]] = None, key_alt_name: Optional[str] = None, query_type: Optional[str] = None, contention_factor: Optional[int] = None, range_opts: Optional[RangeOpts] = None, is_expression: bool = False, ) -> Any: self._check_closed() if isinstance(key_id, uuid.UUID): key_id = Binary.from_uuid(key_id) if key_id is not None and not ( isinstance(key_id, Binary) and key_id.subtype == UUID_SUBTYPE ): raise TypeError("key_id must be a bson.binary.Binary with subtype 4") doc = encode( {"v": value}, codec_options=self._codec_options, ) range_opts_bytes = None if range_opts: range_opts_bytes = encode( range_opts.document, codec_options=self._codec_options, ) with _wrap_encryption_errors(): encrypted_doc = self._encryption.encrypt( value=doc, algorithm=algorithm, key_id=key_id, key_alt_name=key_alt_name, query_type=query_type, contention_factor=contention_factor, range_opts=range_opts_bytes, is_expression=is_expression, ) return decode(encrypted_doc)["v"] def encrypt( self, value: Any, algorithm: str, key_id: Optional[Union[Binary, uuid.UUID]] = None, key_alt_name: Optional[str] = None, query_type: Optional[str] = None, contention_factor: Optional[int] = None, range_opts: Optional[RangeOpts] = None, ) -> Binary: """Encrypt a BSON value with a given key and algorithm. Note that exactly one of ``key_id`` or ``key_alt_name`` must be provided. :param value: The BSON value to encrypt. :param algorithm` (string): The encryption algorithm to use. See :class:`Algorithm` for some valid options. :param key_id: Identifies a data key by ``_id`` which must be a :class:`~bson.binary.Binary` with subtype 4 ( :attr:`~bson.binary.UUID_SUBTYPE`). :param key_alt_name: Identifies a key vault document by 'keyAltName'. :param query_type` (str): The query type to execute. See :class:`QueryType` for valid options. :param contention_factor` (int): The contention factor to use when the algorithm is :attr:`Algorithm.INDEXED`. An integer value *must* be given when the :attr:`Algorithm.INDEXED` algorithm is used. :param range_opts: Experimental only, not intended for public use. :return: The encrypted value, a :class:`~bson.binary.Binary` with subtype 6. .. versionchanged:: 4.7 ``key_id`` can now be passed in as a :class:`uuid.UUID`. .. versionchanged:: 4.2 Added the `query_type` and `contention_factor` parameters. """ return cast( Binary, self._encrypt_helper( value=value, algorithm=algorithm, key_id=key_id, key_alt_name=key_alt_name, query_type=query_type, contention_factor=contention_factor, range_opts=range_opts, is_expression=False, ), ) def encrypt_expression( self, expression: Mapping[str, Any], algorithm: str, key_id: Optional[Union[Binary, uuid.UUID]] = None, key_alt_name: Optional[str] = None, query_type: Optional[str] = None, contention_factor: Optional[int] = None, range_opts: Optional[RangeOpts] = None, ) -> RawBSONDocument: """Encrypt a BSON expression with a given key and algorithm. Note that exactly one of ``key_id`` or ``key_alt_name`` must be provided. :param expression: The BSON aggregate or match expression to encrypt. :param algorithm` (string): The encryption algorithm to use. See :class:`Algorithm` for some valid options. :param key_id: Identifies a data key by ``_id`` which must be a :class:`~bson.binary.Binary` with subtype 4 ( :attr:`~bson.binary.UUID_SUBTYPE`). :param key_alt_name: Identifies a key vault document by 'keyAltName'. :param query_type` (str): The query type to execute. See :class:`QueryType` for valid options. :param contention_factor` (int): The contention factor to use when the algorithm is :attr:`Algorithm.INDEXED`. An integer value *must* be given when the :attr:`Algorithm.INDEXED` algorithm is used. :param range_opts: Experimental only, not intended for public use. :return: The encrypted expression, a :class:`~bson.RawBSONDocument`. .. versionchanged:: 4.7 ``key_id`` can now be passed in as a :class:`uuid.UUID`. .. versionadded:: 4.4 """ return cast( RawBSONDocument, self._encrypt_helper( value=expression, algorithm=algorithm, key_id=key_id, key_alt_name=key_alt_name, query_type=query_type, contention_factor=contention_factor, range_opts=range_opts, is_expression=True, ), ) def decrypt(self, value: Binary) -> Any: """Decrypt an encrypted value. :param value` (Binary): The encrypted value, a :class:`~bson.binary.Binary` with subtype 6. :return: The decrypted BSON value. """ self._check_closed() if not (isinstance(value, Binary) and value.subtype == 6): raise TypeError("value to decrypt must be a bson.binary.Binary with subtype 6") with _wrap_encryption_errors(): doc = encode({"v": value}) decrypted_doc = self._encryption.decrypt(doc) return decode(decrypted_doc, codec_options=self._codec_options)["v"] def get_key(self, id: Binary) -> Optional[RawBSONDocument]: """Get a data key by id. :param id` (Binary): The UUID of a key a which must be a :class:`~bson.binary.Binary` with subtype 4 ( :attr:`~bson.binary.UUID_SUBTYPE`). :return: The key document. .. versionadded:: 4.2 """ self._check_closed() assert self._key_vault_coll is not None return self._key_vault_coll.find_one({"_id": id}) def get_keys(self) -> Cursor[RawBSONDocument]: """Get all of the data keys. :return: An instance of :class:`~pymongo.cursor.Cursor` over the data key documents. .. versionadded:: 4.2 """ self._check_closed() assert self._key_vault_coll is not None return self._key_vault_coll.find({}) def delete_key(self, id: Binary) -> DeleteResult: """Delete a key document in the key vault collection that has the given ``key_id``. :param id` (Binary): The UUID of a key a which must be a :class:`~bson.binary.Binary` with subtype 4 ( :attr:`~bson.binary.UUID_SUBTYPE`). :return: The delete result. .. versionadded:: 4.2 """ self._check_closed() assert self._key_vault_coll is not None return self._key_vault_coll.delete_one({"_id": id}) def add_key_alt_name(self, id: Binary, key_alt_name: str) -> Any: """Add ``key_alt_name`` to the set of alternate names in the key document with UUID ``key_id``. :param `id`: The UUID of a key a which must be a :class:`~bson.binary.Binary` with subtype 4 ( :attr:`~bson.binary.UUID_SUBTYPE`). :param `key_alt_name`: The key alternate name to add. :return: The previous version of the key document. .. versionadded:: 4.2 """ self._check_closed() update = {"$addToSet": {"keyAltNames": key_alt_name}} assert self._key_vault_coll is not None return self._key_vault_coll.find_one_and_update({"_id": id}, update) def get_key_by_alt_name(self, key_alt_name: str) -> Optional[RawBSONDocument]: """Get a key document in the key vault collection that has the given ``key_alt_name``. :param key_alt_name: (str): The key alternate name of the key to get. :return: The key document. .. versionadded:: 4.2 """ self._check_closed() assert self._key_vault_coll is not None return self._key_vault_coll.find_one({"keyAltNames": key_alt_name}) def remove_key_alt_name(self, id: Binary, key_alt_name: str) -> Optional[RawBSONDocument]: """Remove ``key_alt_name`` from the set of keyAltNames in the key document with UUID ``id``. Also removes the ``keyAltNames`` field from the key document if it would otherwise be empty. :param `id`: The UUID of a key a which must be a :class:`~bson.binary.Binary` with subtype 4 ( :attr:`~bson.binary.UUID_SUBTYPE`). :param `key_alt_name`: The key alternate name to remove. :return: Returns the previous version of the key document. .. versionadded:: 4.2 """ self._check_closed() pipeline = [ { "$set": { "keyAltNames": { "$cond": [ {"$eq": ["$keyAltNames", [key_alt_name]]}, "$$REMOVE", { "$filter": { "input": "$keyAltNames", "cond": {"$ne": ["$$this", key_alt_name]}, } }, ] } } } ] assert self._key_vault_coll is not None return self._key_vault_coll.find_one_and_update({"_id": id}, pipeline) def rewrap_many_data_key( self, filter: Mapping[str, Any], provider: Optional[str] = None, master_key: Optional[Mapping[str, Any]] = None, ) -> RewrapManyDataKeyResult: """Decrypts and encrypts all matching data keys in the key vault with a possibly new `master_key` value. :param filter: A document used to filter the data keys. :param provider: The new KMS provider to use to encrypt the data keys, or ``None`` to use the current KMS provider(s). :param `master_key`: The master key fields corresponding to the new KMS provider when ``provider`` is not ``None``. :return: A :class:`RewrapManyDataKeyResult`. This method allows you to re-encrypt all of your data-keys with a new CMK, or master key. Note that this does *not* require re-encrypting any of the data in your encrypted collections, but rather refreshes the key that protects the keys that encrypt the data: .. code-block:: python client_encryption.rewrap_many_data_key( filter={"keyAltNames": "optional filter for which keys you want to update"}, master_key={ "provider": "azure", # replace with your cloud provider "master_key": { # put the rest of your master_key options here "key": "" }, }, ) .. versionadded:: 4.2 """ if master_key is not None and provider is None: raise ConfigurationError("A provider must be given if a master_key is given") self._check_closed() with _wrap_encryption_errors(): raw_result = self._encryption.rewrap_many_data_key(filter, provider, master_key) if raw_result is None: return RewrapManyDataKeyResult() raw_doc = RawBSONDocument(raw_result, DEFAULT_RAW_BSON_OPTIONS) replacements = [] for key in raw_doc["v"]: update_model = { "$set": {"keyMaterial": key["keyMaterial"], "masterKey": key["masterKey"]}, "$currentDate": {"updateDate": True}, } op = UpdateOne({"_id": key["_id"]}, update_model) replacements.append(op) if not replacements: return RewrapManyDataKeyResult() assert self._key_vault_coll is not None result = self._key_vault_coll.bulk_write(replacements) return RewrapManyDataKeyResult(result) def __enter__(self) -> ClientEncryption[_DocumentType]: return self def __exit__(self, exc_type: Any, exc_val: Any, exc_tb: Any) -> None: self.close() def _check_closed(self) -> None: if self._encryption is None: raise InvalidOperation("Cannot use closed ClientEncryption") def close(self) -> None: """Release resources. Note that using this class in a with-statement will automatically call :meth:`close`:: with ClientEncryption(...) as client_encryption: encrypted = client_encryption.encrypt(value, ...) decrypted = client_encryption.decrypt(encrypted) """ if self._io_callbacks: self._io_callbacks.close() self._encryption.close() self._io_callbacks = None self._encryption = None mongodb-mongo-python-driver-509e9b7/pymongo/encryption_options.py000066400000000000000000000313211462766011000254440ustar00rootroot00000000000000# Copyright 2019-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. """Support for automatic client-side field level encryption.""" from __future__ import annotations from typing import TYPE_CHECKING, Any, Mapping, Optional try: import pymongocrypt # type:ignore[import] # noqa: F401 _HAVE_PYMONGOCRYPT = True except ImportError: _HAVE_PYMONGOCRYPT = False from bson import int64 from pymongo.common import validate_is_mapping from pymongo.errors import ConfigurationError from pymongo.uri_parser import _parse_kms_tls_options if TYPE_CHECKING: from pymongo.mongo_client import MongoClient from pymongo.typings import _DocumentTypeArg class AutoEncryptionOpts: """Options to configure automatic client-side field level encryption.""" def __init__( self, kms_providers: Mapping[str, Any], key_vault_namespace: str, key_vault_client: Optional[MongoClient[_DocumentTypeArg]] = None, schema_map: Optional[Mapping[str, Any]] = None, bypass_auto_encryption: bool = False, mongocryptd_uri: str = "mongodb://localhost:27020", mongocryptd_bypass_spawn: bool = False, mongocryptd_spawn_path: str = "mongocryptd", mongocryptd_spawn_args: Optional[list[str]] = None, kms_tls_options: Optional[Mapping[str, Any]] = None, crypt_shared_lib_path: Optional[str] = None, crypt_shared_lib_required: bool = False, bypass_query_analysis: bool = False, encrypted_fields_map: Optional[Mapping[str, Any]] = None, ) -> None: """Options to configure automatic client-side field level encryption. Automatic client-side field level encryption requires MongoDB >=4.2 enterprise or a MongoDB >=4.2 Atlas cluster. Automatic encryption is not supported for operations on a database or view and will result in error. Although automatic encryption requires MongoDB >=4.2 enterprise or a MongoDB >=4.2 Atlas cluster, automatic *decryption* is supported for all users. To configure automatic *decryption* without automatic *encryption* set ``bypass_auto_encryption=True``. Explicit encryption and explicit decryption is also supported for all users with the :class:`~pymongo.encryption.ClientEncryption` class. See :ref:`automatic-client-side-encryption` for an example. :param kms_providers: Map of KMS provider options. The `kms_providers` map values differ by provider: - `aws`: Map with "accessKeyId" and "secretAccessKey" as strings. These are the AWS access key ID and AWS secret access key used to generate KMS messages. An optional "sessionToken" may be included to support temporary AWS credentials. - `azure`: Map with "tenantId", "clientId", and "clientSecret" as strings. Additionally, "identityPlatformEndpoint" may also be specified as a string (defaults to 'login.microsoftonline.com'). These are the Azure Active Directory credentials used to generate Azure Key Vault messages. - `gcp`: Map with "email" as a string and "privateKey" as `bytes` or a base64 encoded string. Additionally, "endpoint" may also be specified as a string (defaults to 'oauth2.googleapis.com'). These are the credentials used to generate Google Cloud KMS messages. - `kmip`: Map with "endpoint" as a host with required port. For example: ``{"endpoint": "example.com:443"}``. - `local`: Map with "key" as `bytes` (96 bytes in length) or a base64 encoded string which decodes to 96 bytes. "key" is the master key used to encrypt/decrypt data keys. This key should be generated and stored as securely as possible. KMS providers may be specified with an optional name suffix separated by a colon, for example "kmip:name" or "aws:name". Named KMS providers do not support :ref:`CSFLE on-demand credentials`. Named KMS providers enables more than one of each KMS provider type to be configured. For example, to configure multiple local KMS providers:: kms_providers = { "local": {"key": local_kek1}, # Unnamed KMS provider. "local:myname": {"key": local_kek2}, # Named KMS provider with name "myname". } :param key_vault_namespace: The namespace for the key vault collection. The key vault collection contains all data keys used for encryption and decryption. Data keys are stored as documents in this MongoDB collection. Data keys are protected with encryption by a KMS provider. :param key_vault_client: By default, the key vault collection is assumed to reside in the same MongoDB cluster as the encrypted MongoClient. Use this option to route data key queries to a separate MongoDB cluster. :param schema_map: Map of collection namespace ("db.coll") to JSON Schema. By default, a collection's JSONSchema is periodically polled with the listCollections command. But a JSONSchema may be specified locally with the schemaMap option. **Supplying a `schema_map` provides more security than relying on JSON Schemas obtained from the server. It protects against a malicious server advertising a false JSON Schema, which could trick the client into sending unencrypted data that should be encrypted.** Schemas supplied in the schemaMap only apply to configuring automatic encryption for client side encryption. Other validation rules in the JSON schema will not be enforced by the driver and will result in an error. :param bypass_auto_encryption: If ``True``, automatic encryption will be disabled but automatic decryption will still be enabled. Defaults to ``False``. :param mongocryptd_uri: The MongoDB URI used to connect to the *local* mongocryptd process. Defaults to ``'mongodb://localhost:27020'``. :param mongocryptd_bypass_spawn: If ``True``, the encrypted MongoClient will not attempt to spawn the mongocryptd process. Defaults to ``False``. :param mongocryptd_spawn_path: Used for spawning the mongocryptd process. Defaults to ``'mongocryptd'`` and spawns mongocryptd from the system path. :param mongocryptd_spawn_args: A list of string arguments to use when spawning the mongocryptd process. Defaults to ``['--idleShutdownTimeoutSecs=60']``. If the list does not include the ``idleShutdownTimeoutSecs`` option then ``'--idleShutdownTimeoutSecs=60'`` will be added. :param kms_tls_options: A map of KMS provider names to TLS options to use when creating secure connections to KMS providers. Accepts the same TLS options as :class:`pymongo.mongo_client.MongoClient`. For example, to override the system default CA file:: kms_tls_options={'kmip': {'tlsCAFile': certifi.where()}} Or to supply a client certificate:: kms_tls_options={'kmip': {'tlsCertificateKeyFile': 'client.pem'}} :param crypt_shared_lib_path: Override the path to load the crypt_shared library. :param crypt_shared_lib_required: If True, raise an error if libmongocrypt is unable to load the crypt_shared library. :param bypass_query_analysis: If ``True``, disable automatic analysis of outgoing commands. Set `bypass_query_analysis` to use explicit encryption on indexed fields without the MongoDB Enterprise Advanced licensed crypt_shared library. :param encrypted_fields_map: Map of collection namespace ("db.coll") to documents that described the encrypted fields for Queryable Encryption. For example:: { "db.encryptedCollection": { "escCollection": "enxcol_.encryptedCollection.esc", "ecocCollection": "enxcol_.encryptedCollection.ecoc", "fields": [ { "path": "firstName", "keyId": Binary.from_uuid(UUID('00000000-0000-0000-0000-000000000000')), "bsonType": "string", "queries": {"queryType": "equality"} }, { "path": "ssn", "keyId": Binary.from_uuid(UUID('04104104-1041-0410-4104-104104104104')), "bsonType": "string" } ] } } .. versionchanged:: 4.2 Added `encrypted_fields_map` `crypt_shared_lib_path`, `crypt_shared_lib_required`, and `bypass_query_analysis` parameters. .. versionchanged:: 4.0 Added the `kms_tls_options` parameter and the "kmip" KMS provider. .. versionadded:: 3.9 """ if not _HAVE_PYMONGOCRYPT: raise ConfigurationError( "client side encryption requires the pymongocrypt library: " "install a compatible version with: " "python -m pip install 'pymongo[encryption]'" ) if encrypted_fields_map: validate_is_mapping("encrypted_fields_map", encrypted_fields_map) self._encrypted_fields_map = encrypted_fields_map self._bypass_query_analysis = bypass_query_analysis self._crypt_shared_lib_path = crypt_shared_lib_path self._crypt_shared_lib_required = crypt_shared_lib_required self._kms_providers = kms_providers self._key_vault_namespace = key_vault_namespace self._key_vault_client = key_vault_client self._schema_map = schema_map self._bypass_auto_encryption = bypass_auto_encryption self._mongocryptd_uri = mongocryptd_uri self._mongocryptd_bypass_spawn = mongocryptd_bypass_spawn self._mongocryptd_spawn_path = mongocryptd_spawn_path if mongocryptd_spawn_args is None: mongocryptd_spawn_args = ["--idleShutdownTimeoutSecs=60"] self._mongocryptd_spawn_args = mongocryptd_spawn_args if not isinstance(self._mongocryptd_spawn_args, list): raise TypeError("mongocryptd_spawn_args must be a list") if not any("idleShutdownTimeoutSecs" in s for s in self._mongocryptd_spawn_args): self._mongocryptd_spawn_args.append("--idleShutdownTimeoutSecs=60") # Maps KMS provider name to a SSLContext. self._kms_ssl_contexts = _parse_kms_tls_options(kms_tls_options) self._bypass_query_analysis = bypass_query_analysis class RangeOpts: """Options to configure encrypted queries using the rangePreview algorithm.""" def __init__( self, sparsity: int, min: Optional[Any] = None, max: Optional[Any] = None, precision: Optional[int] = None, ) -> None: """Options to configure encrypted queries using the rangePreview algorithm. .. note:: This feature is experimental only, and not intended for public use. :param sparsity: An integer. :param min: A BSON scalar value corresponding to the type being queried. :param max: A BSON scalar value corresponding to the type being queried. :param precision: An integer, may only be set for double or decimal128 types. .. versionadded:: 4.4 """ self.min = min self.max = max self.sparsity = sparsity self.precision = precision @property def document(self) -> dict[str, Any]: doc = {} for k, v in [ ("sparsity", int64.Int64(self.sparsity)), ("precision", self.precision), ("min", self.min), ("max", self.max), ]: if v is not None: doc[k] = v return doc mongodb-mongo-python-driver-509e9b7/pymongo/errors.py000066400000000000000000000266121462766011000230220ustar00rootroot00000000000000# Copyright 2009-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. """Exceptions raised by PyMongo.""" from __future__ import annotations from ssl import SSLCertVerificationError as _CertificateError # noqa: F401 from typing import TYPE_CHECKING, Any, Iterable, Mapping, Optional, Sequence, Union from bson.errors import InvalidDocument if TYPE_CHECKING: from pymongo.typings import _DocumentOut class PyMongoError(Exception): """Base class for all PyMongo exceptions.""" def __init__(self, message: str = "", error_labels: Optional[Iterable[str]] = None) -> None: super().__init__(message) self._message = message self._error_labels = set(error_labels or []) def has_error_label(self, label: str) -> bool: """Return True if this error contains the given label. .. versionadded:: 3.7 """ return label in self._error_labels def _add_error_label(self, label: str) -> None: """Add the given label to this error.""" self._error_labels.add(label) def _remove_error_label(self, label: str) -> None: """Remove the given label from this error.""" self._error_labels.discard(label) @property def timeout(self) -> bool: """True if this error was caused by a timeout. .. versionadded:: 4.2 """ return False class ProtocolError(PyMongoError): """Raised for failures related to the wire protocol.""" class ConnectionFailure(PyMongoError): """Raised when a connection to the database cannot be made or is lost.""" class WaitQueueTimeoutError(ConnectionFailure): """Raised when an operation times out waiting to checkout a connection from the pool. Subclass of :exc:`~pymongo.errors.ConnectionFailure`. .. versionadded:: 4.2 """ @property def timeout(self) -> bool: return True class AutoReconnect(ConnectionFailure): """Raised when a connection to the database is lost and an attempt to auto-reconnect will be made. In order to auto-reconnect you must handle this exception, recognizing that the operation which caused it has not necessarily succeeded. Future operations will attempt to open a new connection to the database (and will continue to raise this exception until the first successful connection is made). Subclass of :exc:`~pymongo.errors.ConnectionFailure`. """ errors: Union[Mapping[str, Any], Sequence[Any]] details: Union[Mapping[str, Any], Sequence[Any]] def __init__( self, message: str = "", errors: Optional[Union[Mapping[str, Any], Sequence[Any]]] = None ) -> None: error_labels = None if errors is not None: if isinstance(errors, dict): error_labels = errors.get("errorLabels") super().__init__(message, error_labels) self.errors = self.details = errors or [] class NetworkTimeout(AutoReconnect): """An operation on an open connection exceeded socketTimeoutMS. The remaining connections in the pool stay open. In the case of a write operation, you cannot know whether it succeeded or failed. Subclass of :exc:`~pymongo.errors.AutoReconnect`. """ @property def timeout(self) -> bool: return True def _format_detailed_error( message: str, details: Optional[Union[Mapping[str, Any], list[Any]]] ) -> str: if details is not None: message = f"{message}, full error: {details}" return message class NotPrimaryError(AutoReconnect): """The server responded "not primary" or "node is recovering". These errors result from a query, write, or command. The operation failed because the client thought it was using the primary but the primary has stepped down, or the client thought it was using a healthy secondary but the secondary is stale and trying to recover. The client launches a refresh operation on a background thread, to update its view of the server as soon as possible after throwing this exception. Subclass of :exc:`~pymongo.errors.AutoReconnect`. .. versionadded:: 3.12 """ def __init__( self, message: str = "", errors: Optional[Union[Mapping[str, Any], list[Any]]] = None ) -> None: super().__init__(_format_detailed_error(message, errors), errors=errors) class ServerSelectionTimeoutError(AutoReconnect): """Thrown when no MongoDB server is available for an operation If there is no suitable server for an operation PyMongo tries for ``serverSelectionTimeoutMS`` (default 30 seconds) to find one, then throws this exception. For example, it is thrown after attempting an operation when PyMongo cannot connect to any server, or if you attempt an insert into a replica set that has no primary and does not elect one within the timeout window, or if you attempt to query with a Read Preference that the replica set cannot satisfy. """ @property def timeout(self) -> bool: return True class ConfigurationError(PyMongoError): """Raised when something is incorrectly configured.""" class OperationFailure(PyMongoError): """Raised when a database operation fails. .. versionadded:: 2.7 The :attr:`details` attribute. """ def __init__( self, error: str, code: Optional[int] = None, details: Optional[Mapping[str, Any]] = None, max_wire_version: Optional[int] = None, ) -> None: error_labels = None if details is not None: error_labels = details.get("errorLabels") super().__init__(_format_detailed_error(error, details), error_labels=error_labels) self.__code = code self.__details = details self.__max_wire_version = max_wire_version @property def _max_wire_version(self) -> Optional[int]: return self.__max_wire_version @property def code(self) -> Optional[int]: """The error code returned by the server, if any.""" return self.__code @property def details(self) -> Optional[Mapping[str, Any]]: """The complete error document returned by the server. Depending on the error that occurred, the error document may include useful information beyond just the error message. When connected to a mongos the error document may contain one or more subdocuments if errors occurred on multiple shards. """ return self.__details @property def timeout(self) -> bool: return self.__code in (50,) class CursorNotFound(OperationFailure): """Raised while iterating query results if the cursor is invalidated on the server. .. versionadded:: 2.7 """ class ExecutionTimeout(OperationFailure): """Raised when a database operation times out, exceeding the $maxTimeMS set in the query or command option. .. note:: Requires server version **>= 2.6.0** .. versionadded:: 2.7 """ @property def timeout(self) -> bool: return True class WriteConcernError(OperationFailure): """Base exception type for errors raised due to write concern. .. versionadded:: 3.0 """ class WriteError(OperationFailure): """Base exception type for errors raised during write operations. .. versionadded:: 3.0 """ class WTimeoutError(WriteConcernError): """Raised when a database operation times out (i.e. wtimeout expires) before replication completes. With newer versions of MongoDB the `details` attribute may include write concern fields like 'n', 'updatedExisting', or 'writtenTo'. .. versionadded:: 2.7 """ @property def timeout(self) -> bool: return True class DuplicateKeyError(WriteError): """Raised when an insert or update fails due to a duplicate key error.""" def _wtimeout_error(error: Any) -> bool: """Return True if this writeConcernError doc is a caused by a timeout.""" return error.get("code") == 50 or ("errInfo" in error and error["errInfo"].get("wtimeout")) class BulkWriteError(OperationFailure): """Exception class for bulk write errors. .. versionadded:: 2.7 """ details: _DocumentOut def __init__(self, results: _DocumentOut) -> None: super().__init__("batch op errors occurred", 65, results) def __reduce__(self) -> tuple[Any, Any]: return self.__class__, (self.details,) @property def timeout(self) -> bool: # Check the last writeConcernError and last writeError to determine if this # BulkWriteError was caused by a timeout. wces = self.details.get("writeConcernErrors", []) if wces and _wtimeout_error(wces[-1]): return True werrs = self.details.get("writeErrors", []) if werrs and werrs[-1].get("code") == 50: return True return False class InvalidOperation(PyMongoError): """Raised when a client attempts to perform an invalid operation.""" class InvalidName(PyMongoError): """Raised when an invalid name is used.""" class CollectionInvalid(PyMongoError): """Raised when collection validation fails.""" class InvalidURI(ConfigurationError): """Raised when trying to parse an invalid mongodb URI.""" class DocumentTooLarge(InvalidDocument): """Raised when an encoded document is too large for the connected server.""" class EncryptionError(PyMongoError): """Raised when encryption or decryption fails. This error always wraps another exception which can be retrieved via the :attr:`cause` property. .. versionadded:: 3.9 """ def __init__(self, cause: Exception) -> None: super().__init__(str(cause)) self.__cause = cause @property def cause(self) -> Exception: """The exception that caused this encryption or decryption error.""" return self.__cause @property def timeout(self) -> bool: if isinstance(self.__cause, PyMongoError): return self.__cause.timeout return False class EncryptedCollectionError(EncryptionError): """Raised when creating a collection with encrypted_fields fails. .. versionadded:: 4.4 """ def __init__(self, cause: Exception, encrypted_fields: Mapping[str, Any]) -> None: super().__init__(cause) self.__encrypted_fields = encrypted_fields @property def encrypted_fields(self) -> Mapping[str, Any]: """The encrypted_fields document that allows inferring which data keys are *known* to be created. Note that the returned document is not guaranteed to contain information about *all* of the data keys that were created, for example in the case of an indefinite error like a timeout. Use the `cause` property to determine whether a definite or indefinite error caused this error, and only rely on the accuracy of the encrypted_fields if the error is definite. """ return self.__encrypted_fields class _OperationCancelled(AutoReconnect): """Internal error raised when a socket operation is cancelled.""" mongodb-mongo-python-driver-509e9b7/pymongo/event_loggers.py000066400000000000000000000216551462766011000243530ustar00rootroot00000000000000# Copyright 2020-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. """Example event logger classes. .. versionadded:: 3.11 These loggers can be registered using :func:`register` or :class:`~pymongo.mongo_client.MongoClient`. ``monitoring.register(CommandLogger())`` or ``MongoClient(event_listeners=[CommandLogger()])`` """ from __future__ import annotations import logging from pymongo import monitoring class CommandLogger(monitoring.CommandListener): """A simple listener that logs command events. Listens for :class:`~pymongo.monitoring.CommandStartedEvent`, :class:`~pymongo.monitoring.CommandSucceededEvent` and :class:`~pymongo.monitoring.CommandFailedEvent` events and logs them at the `INFO` severity level using :mod:`logging`. .. versionadded:: 3.11 """ def started(self, event: monitoring.CommandStartedEvent) -> None: logging.info( f"Command {event.command_name} with request id " f"{event.request_id} started on server " f"{event.connection_id}" ) def succeeded(self, event: monitoring.CommandSucceededEvent) -> None: logging.info( f"Command {event.command_name} with request id " f"{event.request_id} on server {event.connection_id} " f"succeeded in {event.duration_micros} " "microseconds" ) def failed(self, event: monitoring.CommandFailedEvent) -> None: logging.info( f"Command {event.command_name} with request id " f"{event.request_id} on server {event.connection_id} " f"failed in {event.duration_micros} " "microseconds" ) class ServerLogger(monitoring.ServerListener): """A simple listener that logs server discovery events. Listens for :class:`~pymongo.monitoring.ServerOpeningEvent`, :class:`~pymongo.monitoring.ServerDescriptionChangedEvent`, and :class:`~pymongo.monitoring.ServerClosedEvent` events and logs them at the `INFO` severity level using :mod:`logging`. .. versionadded:: 3.11 """ def opened(self, event: monitoring.ServerOpeningEvent) -> None: logging.info(f"Server {event.server_address} added to topology {event.topology_id}") def description_changed(self, event: monitoring.ServerDescriptionChangedEvent) -> None: previous_server_type = event.previous_description.server_type new_server_type = event.new_description.server_type if new_server_type != previous_server_type: # server_type_name was added in PyMongo 3.4 logging.info( f"Server {event.server_address} changed type from " f"{event.previous_description.server_type_name} to " f"{event.new_description.server_type_name}" ) def closed(self, event: monitoring.ServerClosedEvent) -> None: logging.warning(f"Server {event.server_address} removed from topology {event.topology_id}") class HeartbeatLogger(monitoring.ServerHeartbeatListener): """A simple listener that logs server heartbeat events. Listens for :class:`~pymongo.monitoring.ServerHeartbeatStartedEvent`, :class:`~pymongo.monitoring.ServerHeartbeatSucceededEvent`, and :class:`~pymongo.monitoring.ServerHeartbeatFailedEvent` events and logs them at the `INFO` severity level using :mod:`logging`. .. versionadded:: 3.11 """ def started(self, event: monitoring.ServerHeartbeatStartedEvent) -> None: logging.info(f"Heartbeat sent to server {event.connection_id}") def succeeded(self, event: monitoring.ServerHeartbeatSucceededEvent) -> None: # The reply.document attribute was added in PyMongo 3.4. logging.info( f"Heartbeat to server {event.connection_id} " "succeeded with reply " f"{event.reply.document}" ) def failed(self, event: monitoring.ServerHeartbeatFailedEvent) -> None: logging.warning( f"Heartbeat to server {event.connection_id} failed with error {event.reply}" ) class TopologyLogger(monitoring.TopologyListener): """A simple listener that logs server topology events. Listens for :class:`~pymongo.monitoring.TopologyOpenedEvent`, :class:`~pymongo.monitoring.TopologyDescriptionChangedEvent`, and :class:`~pymongo.monitoring.TopologyClosedEvent` events and logs them at the `INFO` severity level using :mod:`logging`. .. versionadded:: 3.11 """ def opened(self, event: monitoring.TopologyOpenedEvent) -> None: logging.info(f"Topology with id {event.topology_id} opened") def description_changed(self, event: monitoring.TopologyDescriptionChangedEvent) -> None: logging.info(f"Topology description updated for topology id {event.topology_id}") previous_topology_type = event.previous_description.topology_type new_topology_type = event.new_description.topology_type if new_topology_type != previous_topology_type: # topology_type_name was added in PyMongo 3.4 logging.info( f"Topology {event.topology_id} changed type from " f"{event.previous_description.topology_type_name} to " f"{event.new_description.topology_type_name}" ) # The has_writable_server and has_readable_server methods # were added in PyMongo 3.4. if not event.new_description.has_writable_server(): logging.warning("No writable servers available.") if not event.new_description.has_readable_server(): logging.warning("No readable servers available.") def closed(self, event: monitoring.TopologyClosedEvent) -> None: logging.info(f"Topology with id {event.topology_id} closed") class ConnectionPoolLogger(monitoring.ConnectionPoolListener): """A simple listener that logs server connection pool events. Listens for :class:`~pymongo.monitoring.PoolCreatedEvent`, :class:`~pymongo.monitoring.PoolClearedEvent`, :class:`~pymongo.monitoring.PoolClosedEvent`, :~pymongo.monitoring.class:`ConnectionCreatedEvent`, :class:`~pymongo.monitoring.ConnectionReadyEvent`, :class:`~pymongo.monitoring.ConnectionClosedEvent`, :class:`~pymongo.monitoring.ConnectionCheckOutStartedEvent`, :class:`~pymongo.monitoring.ConnectionCheckOutFailedEvent`, :class:`~pymongo.monitoring.ConnectionCheckedOutEvent`, and :class:`~pymongo.monitoring.ConnectionCheckedInEvent` events and logs them at the `INFO` severity level using :mod:`logging`. .. versionadded:: 3.11 """ def pool_created(self, event: monitoring.PoolCreatedEvent) -> None: logging.info(f"[pool {event.address}] pool created") def pool_ready(self, event: monitoring.PoolReadyEvent) -> None: logging.info(f"[pool {event.address}] pool ready") def pool_cleared(self, event: monitoring.PoolClearedEvent) -> None: logging.info(f"[pool {event.address}] pool cleared") def pool_closed(self, event: monitoring.PoolClosedEvent) -> None: logging.info(f"[pool {event.address}] pool closed") def connection_created(self, event: monitoring.ConnectionCreatedEvent) -> None: logging.info(f"[pool {event.address}][conn #{event.connection_id}] connection created") def connection_ready(self, event: monitoring.ConnectionReadyEvent) -> None: logging.info( f"[pool {event.address}][conn #{event.connection_id}] connection setup succeeded" ) def connection_closed(self, event: monitoring.ConnectionClosedEvent) -> None: logging.info( f"[pool {event.address}][conn #{event.connection_id}] " f'connection closed, reason: "{event.reason}"' ) def connection_check_out_started( self, event: monitoring.ConnectionCheckOutStartedEvent ) -> None: logging.info(f"[pool {event.address}] connection check out started") def connection_check_out_failed(self, event: monitoring.ConnectionCheckOutFailedEvent) -> None: logging.info(f"[pool {event.address}] connection check out failed, reason: {event.reason}") def connection_checked_out(self, event: monitoring.ConnectionCheckedOutEvent) -> None: logging.info( f"[pool {event.address}][conn #{event.connection_id}] connection checked out of pool" ) def connection_checked_in(self, event: monitoring.ConnectionCheckedInEvent) -> None: logging.info( f"[pool {event.address}][conn #{event.connection_id}] connection checked into pool" ) mongodb-mongo-python-driver-509e9b7/pymongo/hello.py000066400000000000000000000150701462766011000226050ustar00rootroot00000000000000# Copyright 2021-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. """Helpers for the 'hello' and legacy hello commands.""" from __future__ import annotations import copy import datetime import itertools from typing import Any, Generic, Mapping, Optional from bson.objectid import ObjectId from pymongo import common from pymongo.server_type import SERVER_TYPE from pymongo.typings import ClusterTime, _DocumentType class HelloCompat: CMD = "hello" LEGACY_CMD = "ismaster" PRIMARY = "isWritablePrimary" LEGACY_PRIMARY = "ismaster" LEGACY_ERROR = "not master" def _get_server_type(doc: Mapping[str, Any]) -> int: """Determine the server type from a hello response.""" if not doc.get("ok"): return SERVER_TYPE.Unknown if doc.get("serviceId"): return SERVER_TYPE.LoadBalancer elif doc.get("isreplicaset"): return SERVER_TYPE.RSGhost elif doc.get("setName"): if doc.get("hidden"): return SERVER_TYPE.RSOther elif doc.get(HelloCompat.PRIMARY): return SERVER_TYPE.RSPrimary elif doc.get(HelloCompat.LEGACY_PRIMARY): return SERVER_TYPE.RSPrimary elif doc.get("secondary"): return SERVER_TYPE.RSSecondary elif doc.get("arbiterOnly"): return SERVER_TYPE.RSArbiter else: return SERVER_TYPE.RSOther elif doc.get("msg") == "isdbgrid": return SERVER_TYPE.Mongos else: return SERVER_TYPE.Standalone class Hello(Generic[_DocumentType]): """Parse a hello response from the server. .. versionadded:: 3.12 """ __slots__ = ("_doc", "_server_type", "_is_writable", "_is_readable", "_awaitable") def __init__(self, doc: _DocumentType, awaitable: bool = False) -> None: self._server_type = _get_server_type(doc) self._doc: _DocumentType = doc self._is_writable = self._server_type in ( SERVER_TYPE.RSPrimary, SERVER_TYPE.Standalone, SERVER_TYPE.Mongos, SERVER_TYPE.LoadBalancer, ) self._is_readable = self.server_type == SERVER_TYPE.RSSecondary or self._is_writable self._awaitable = awaitable @property def document(self) -> _DocumentType: """The complete hello command response document. .. versionadded:: 3.4 """ return copy.copy(self._doc) @property def server_type(self) -> int: return self._server_type @property def all_hosts(self) -> set[tuple[str, int]]: """List of hosts, passives, and arbiters known to this server.""" return set( map( common.clean_node, itertools.chain( self._doc.get("hosts", []), self._doc.get("passives", []), self._doc.get("arbiters", []), ), ) ) @property def tags(self) -> Mapping[str, Any]: """Replica set member tags or empty dict.""" return self._doc.get("tags", {}) @property def primary(self) -> Optional[tuple[str, int]]: """This server's opinion about who the primary is, or None.""" if self._doc.get("primary"): return common.partition_node(self._doc["primary"]) else: return None @property def replica_set_name(self) -> Optional[str]: """Replica set name or None.""" return self._doc.get("setName") @property def max_bson_size(self) -> int: return self._doc.get("maxBsonObjectSize", common.MAX_BSON_SIZE) @property def max_message_size(self) -> int: return self._doc.get("maxMessageSizeBytes", 2 * self.max_bson_size) @property def max_write_batch_size(self) -> int: return self._doc.get("maxWriteBatchSize", common.MAX_WRITE_BATCH_SIZE) @property def min_wire_version(self) -> int: return self._doc.get("minWireVersion", common.MIN_WIRE_VERSION) @property def max_wire_version(self) -> int: return self._doc.get("maxWireVersion", common.MAX_WIRE_VERSION) @property def set_version(self) -> Optional[int]: return self._doc.get("setVersion") @property def election_id(self) -> Optional[ObjectId]: return self._doc.get("electionId") @property def cluster_time(self) -> Optional[ClusterTime]: return self._doc.get("$clusterTime") @property def logical_session_timeout_minutes(self) -> Optional[int]: return self._doc.get("logicalSessionTimeoutMinutes") @property def is_writable(self) -> bool: return self._is_writable @property def is_readable(self) -> bool: return self._is_readable @property def me(self) -> Optional[tuple[str, int]]: me = self._doc.get("me") if me: return common.clean_node(me) return None @property def last_write_date(self) -> Optional[datetime.datetime]: return self._doc.get("lastWrite", {}).get("lastWriteDate") @property def compressors(self) -> Optional[list[str]]: return self._doc.get("compression") @property def sasl_supported_mechs(self) -> list[str]: """Supported authentication mechanisms for the current user. For example:: >>> hello.sasl_supported_mechs ["SCRAM-SHA-1", "SCRAM-SHA-256"] """ return self._doc.get("saslSupportedMechs", []) @property def speculative_authenticate(self) -> Optional[Mapping[str, Any]]: """The speculativeAuthenticate field.""" return self._doc.get("speculativeAuthenticate") @property def topology_version(self) -> Optional[Mapping[str, Any]]: return self._doc.get("topologyVersion") @property def awaitable(self) -> bool: return self._awaitable @property def service_id(self) -> Optional[ObjectId]: return self._doc.get("serviceId") @property def hello_ok(self) -> bool: return self._doc.get("helloOk", False) @property def connection_id(self) -> Optional[int]: return self._doc.get("connectionId") mongodb-mongo-python-driver-509e9b7/pymongo/helpers.py000066400000000000000000000274361462766011000231550ustar00rootroot00000000000000# Copyright 2009-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. """Bits and pieces used by the driver that don't really fit elsewhere.""" from __future__ import annotations import sys import traceback from collections import abc from typing import ( TYPE_CHECKING, Any, Callable, Container, Iterable, Mapping, NoReturn, Optional, Sequence, TypeVar, Union, cast, ) from pymongo import ASCENDING from pymongo.errors import ( CursorNotFound, DuplicateKeyError, ExecutionTimeout, NotPrimaryError, OperationFailure, WriteConcernError, WriteError, WTimeoutError, _wtimeout_error, ) from pymongo.hello import HelloCompat if TYPE_CHECKING: from pymongo.cursor import _Hint from pymongo.operations import _IndexList from pymongo.typings import _DocumentOut # From the SDAM spec, the "node is shutting down" codes. _SHUTDOWN_CODES: frozenset = frozenset( [ 11600, # InterruptedAtShutdown 91, # ShutdownInProgress ] ) # From the SDAM spec, the "not primary" error codes are combined with the # "node is recovering" error codes (of which the "node is shutting down" # errors are a subset). _NOT_PRIMARY_CODES: frozenset = ( frozenset( [ 10058, # LegacyNotPrimary <=3.2 "not primary" error code 10107, # NotWritablePrimary 13435, # NotPrimaryNoSecondaryOk 11602, # InterruptedDueToReplStateChange 13436, # NotPrimaryOrSecondary 189, # PrimarySteppedDown ] ) | _SHUTDOWN_CODES ) # From the retryable writes spec. _RETRYABLE_ERROR_CODES: frozenset = _NOT_PRIMARY_CODES | frozenset( [ 7, # HostNotFound 6, # HostUnreachable 89, # NetworkTimeout 9001, # SocketException 262, # ExceededTimeLimit 134, # ReadConcernMajorityNotAvailableYet ] ) # Server code raised when re-authentication is required _REAUTHENTICATION_REQUIRED_CODE: int = 391 # Server code raised when authentication fails. _AUTHENTICATION_FAILURE_CODE: int = 18 # Note - to avoid bugs from forgetting which if these is all lowercase and # which are camelCase, and at the same time avoid having to add a test for # every command, use all lowercase here and test against command_name.lower(). _SENSITIVE_COMMANDS: set = { "authenticate", "saslstart", "saslcontinue", "getnonce", "createuser", "updateuser", "copydbgetnonce", "copydbsaslstart", "copydb", } def _gen_index_name(keys: _IndexList) -> str: """Generate an index name from the set of fields it is over.""" return "_".join(["{}_{}".format(*item) for item in keys]) def _index_list( key_or_list: _Hint, direction: Optional[Union[int, str]] = None ) -> Sequence[tuple[str, Union[int, str, Mapping[str, Any]]]]: """Helper to generate a list of (key, direction) pairs. Takes such a list, or a single key, or a single key and direction. """ if direction is not None: if not isinstance(key_or_list, str): raise TypeError("Expected a string and a direction") return [(key_or_list, direction)] else: if isinstance(key_or_list, str): return [(key_or_list, ASCENDING)] elif isinstance(key_or_list, abc.ItemsView): return list(key_or_list) # type: ignore[arg-type] elif isinstance(key_or_list, abc.Mapping): return list(key_or_list.items()) elif not isinstance(key_or_list, (list, tuple)): raise TypeError("if no direction is specified, key_or_list must be an instance of list") values: list[tuple[str, int]] = [] for item in key_or_list: if isinstance(item, str): item = (item, ASCENDING) # noqa: PLW2901 values.append(item) return values def _index_document(index_list: _IndexList) -> dict[str, Any]: """Helper to generate an index specifying document. Takes a list of (key, direction) pairs. """ if not isinstance(index_list, (list, tuple, abc.Mapping)): raise TypeError( "must use a dictionary or a list of (key, direction) pairs, not: " + repr(index_list) ) if not len(index_list): raise ValueError("key_or_list must not be empty") index: dict[str, Any] = {} if isinstance(index_list, abc.Mapping): for key in index_list: value = index_list[key] _validate_index_key_pair(key, value) index[key] = value else: for item in index_list: if isinstance(item, str): item = (item, ASCENDING) # noqa: PLW2901 key, value = item _validate_index_key_pair(key, value) index[key] = value return index def _validate_index_key_pair(key: Any, value: Any) -> None: if not isinstance(key, str): raise TypeError("first item in each key pair must be an instance of str") if not isinstance(value, (str, int, abc.Mapping)): raise TypeError( "second item in each key pair must be 1, -1, " "'2d', or another valid MongoDB index specifier." ) def _check_command_response( response: _DocumentOut, max_wire_version: Optional[int], allowable_errors: Optional[Container[Union[int, str]]] = None, parse_write_concern_error: bool = False, ) -> None: """Check the response to a command for errors.""" if "ok" not in response: # Server didn't recognize our message as a command. raise OperationFailure( response.get("$err"), # type: ignore[arg-type] response.get("code"), response, max_wire_version, ) if parse_write_concern_error and "writeConcernError" in response: _error = response["writeConcernError"] _labels = response.get("errorLabels") if _labels: _error.update({"errorLabels": _labels}) _raise_write_concern_error(_error) if response["ok"]: return details = response # Mongos returns the error details in a 'raw' object # for some errors. if "raw" in response: for shard in response["raw"].values(): # Grab the first non-empty raw error from a shard. if shard.get("errmsg") and not shard.get("ok"): details = shard break errmsg = details["errmsg"] code = details.get("code") # For allowable errors, only check for error messages when the code is not # included. if allowable_errors: if code is not None: if code in allowable_errors: return elif errmsg in allowable_errors: return # Server is "not primary" or "recovering" if code is not None: if code in _NOT_PRIMARY_CODES: raise NotPrimaryError(errmsg, response) elif HelloCompat.LEGACY_ERROR in errmsg or "node is recovering" in errmsg: raise NotPrimaryError(errmsg, response) # Other errors # findAndModify with upsert can raise duplicate key error if code in (11000, 11001, 12582): raise DuplicateKeyError(errmsg, code, response, max_wire_version) elif code == 50: raise ExecutionTimeout(errmsg, code, response, max_wire_version) elif code == 43: raise CursorNotFound(errmsg, code, response, max_wire_version) raise OperationFailure(errmsg, code, response, max_wire_version) def _raise_last_write_error(write_errors: list[Any]) -> NoReturn: # If the last batch had multiple errors only report # the last error to emulate continue_on_error. error = write_errors[-1] if error.get("code") == 11000: raise DuplicateKeyError(error.get("errmsg"), 11000, error) raise WriteError(error.get("errmsg"), error.get("code"), error) def _raise_write_concern_error(error: Any) -> NoReturn: if _wtimeout_error(error): # Make sure we raise WTimeoutError raise WTimeoutError(error.get("errmsg"), error.get("code"), error) raise WriteConcernError(error.get("errmsg"), error.get("code"), error) def _get_wce_doc(result: Mapping[str, Any]) -> Optional[Mapping[str, Any]]: """Return the writeConcernError or None.""" wce = result.get("writeConcernError") if wce: # The server reports errorLabels at the top level but it's more # convenient to attach it to the writeConcernError doc itself. error_labels = result.get("errorLabels") if error_labels: # Copy to avoid changing the original document. wce = wce.copy() wce["errorLabels"] = error_labels return wce def _check_write_command_response(result: Mapping[str, Any]) -> None: """Backward compatibility helper for write command error handling.""" # Prefer write errors over write concern errors write_errors = result.get("writeErrors") if write_errors: _raise_last_write_error(write_errors) wce = _get_wce_doc(result) if wce: _raise_write_concern_error(wce) def _fields_list_to_dict( fields: Union[Mapping[str, Any], Iterable[str]], option_name: str ) -> Mapping[str, Any]: """Takes a sequence of field names and returns a matching dictionary. ["a", "b"] becomes {"a": 1, "b": 1} and ["a.b.c", "d", "a.c"] becomes {"a.b.c": 1, "d": 1, "a.c": 1} """ if isinstance(fields, abc.Mapping): return fields if isinstance(fields, (abc.Sequence, abc.Set)): if not all(isinstance(field, str) for field in fields): raise TypeError(f"{option_name} must be a list of key names, each an instance of str") return dict.fromkeys(fields, 1) raise TypeError(f"{option_name} must be a mapping or list of key names") def _handle_exception() -> None: """Print exceptions raised by subscribers to stderr.""" # Heavily influenced by logging.Handler.handleError. # See note here: # https://docs.python.org/3.4/library/sys.html#sys.__stderr__ if sys.stderr: einfo = sys.exc_info() try: traceback.print_exception(einfo[0], einfo[1], einfo[2], None, sys.stderr) except OSError: pass finally: del einfo # See https://mypy.readthedocs.io/en/stable/generics.html?#decorator-factories F = TypeVar("F", bound=Callable[..., Any]) def _handle_reauth(func: F) -> F: def inner(*args: Any, **kwargs: Any) -> Any: no_reauth = kwargs.pop("no_reauth", False) from pymongo.message import _BulkWriteContext from pymongo.pool import Connection try: return func(*args, **kwargs) except OperationFailure as exc: if no_reauth: raise if exc.code == _REAUTHENTICATION_REQUIRED_CODE: # Look for an argument that either is a Connection # or has a connection attribute, so we can trigger # a reauth. conn = None for arg in args: if isinstance(arg, Connection): conn = arg break if isinstance(arg, _BulkWriteContext): conn = arg.conn break if conn: conn.authenticate(reauthenticate=True) else: raise return func(*args, **kwargs) raise return cast(F, inner) mongodb-mongo-python-driver-509e9b7/pymongo/lock.py000066400000000000000000000023751462766011000224360ustar00rootroot00000000000000# Copyright 2022-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. from __future__ import annotations import os import threading import weakref _HAS_REGISTER_AT_FORK = hasattr(os, "register_at_fork") # References to instances of _create_lock _forkable_locks: weakref.WeakSet[threading.Lock] = weakref.WeakSet() def _create_lock() -> threading.Lock: """Represents a lock that is tracked upon instantiation using a WeakSet and reset by pymongo upon forking. """ lock = threading.Lock() if _HAS_REGISTER_AT_FORK: _forkable_locks.add(lock) return lock def _release_locks() -> None: # Completed the fork, reset all the locks in the child. for lock in _forkable_locks: if lock.locked(): lock.release() mongodb-mongo-python-driver-509e9b7/pymongo/logger.py000066400000000000000000000143371462766011000227660ustar00rootroot00000000000000# Copyright 2023-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. from __future__ import annotations import enum import logging import os import warnings from typing import Any from bson import UuidRepresentation, json_util from bson.json_util import JSONOptions, _truncate_documents from pymongo.monitoring import ConnectionCheckOutFailedReason, ConnectionClosedReason class _CommandStatusMessage(str, enum.Enum): STARTED = "Command started" SUCCEEDED = "Command succeeded" FAILED = "Command failed" class _ServerSelectionStatusMessage(str, enum.Enum): STARTED = "Server selection started" SUCCEEDED = "Server selection succeeded" FAILED = "Server selection failed" WAITING = "Waiting for suitable server to become available" class _ConnectionStatusMessage(str, enum.Enum): POOL_CREATED = "Connection pool created" POOL_READY = "Connection pool ready" POOL_CLOSED = "Connection pool closed" POOL_CLEARED = "Connection pool cleared" CONN_CREATED = "Connection created" CONN_READY = "Connection ready" CONN_CLOSED = "Connection closed" CHECKOUT_STARTED = "Connection checkout started" CHECKOUT_SUCCEEDED = "Connection checked out" CHECKOUT_FAILED = "Connection checkout failed" CHECKEDIN = "Connection checked in" _DEFAULT_DOCUMENT_LENGTH = 1000 _SENSITIVE_COMMANDS = [ "authenticate", "saslStart", "saslContinue", "getnonce", "createUser", "updateUser", "copydbgetnonce", "copydbsaslstart", "copydb", ] _HELLO_COMMANDS = ["hello", "ismaster", "isMaster"] _REDACTED_FAILURE_FIELDS = ["code", "codeName", "errorLabels"] _DOCUMENT_NAMES = ["command", "reply", "failure"] _JSON_OPTIONS = JSONOptions(uuid_representation=UuidRepresentation.STANDARD) _COMMAND_LOGGER = logging.getLogger("pymongo.command") _CONNECTION_LOGGER = logging.getLogger("pymongo.connection") _SERVER_SELECTION_LOGGER = logging.getLogger("pymongo.serverSelection") _CLIENT_LOGGER = logging.getLogger("pymongo.client") _VERBOSE_CONNECTION_ERROR_REASONS = { ConnectionClosedReason.POOL_CLOSED: "Connection pool was closed", ConnectionCheckOutFailedReason.POOL_CLOSED: "Connection pool was closed", ConnectionClosedReason.STALE: "Connection pool was stale", ConnectionClosedReason.ERROR: "An error occurred while using the connection", ConnectionCheckOutFailedReason.CONN_ERROR: "An error occurred while trying to establish a new connection", ConnectionClosedReason.IDLE: "Connection was idle too long", ConnectionCheckOutFailedReason.TIMEOUT: "Connection exceeded the specified timeout", } def _debug_log(logger: logging.Logger, **fields: Any) -> None: logger.debug(LogMessage(**fields)) def _verbose_connection_error_reason(reason: str) -> str: return _VERBOSE_CONNECTION_ERROR_REASONS.get(reason, reason) def _info_log(logger: logging.Logger, **fields: Any) -> None: logger.info(LogMessage(**fields)) def _log_or_warn(logger: logging.Logger, message: str) -> None: if logger.isEnabledFor(logging.INFO): logger.info(message) else: # stacklevel=4 ensures that the warning is for the user's code. warnings.warn(message, UserWarning, stacklevel=4) class LogMessage: __slots__ = ("_kwargs", "_redacted") def __init__(self, **kwargs: Any): self._kwargs = kwargs self._redacted = False def __str__(self) -> str: self._redact() return "%s" % ( json_util.dumps( self._kwargs, json_options=_JSON_OPTIONS, default=lambda o: o.__repr__() ) ) def _is_sensitive(self, doc_name: str) -> bool: is_speculative_authenticate = ( self._kwargs.pop("speculative_authenticate", False) or "speculativeAuthenticate" in self._kwargs[doc_name] ) is_sensitive_command = ( "commandName" in self._kwargs and self._kwargs["commandName"] in _SENSITIVE_COMMANDS ) is_sensitive_hello = ( self._kwargs["commandName"] in _HELLO_COMMANDS and is_speculative_authenticate ) return is_sensitive_command or is_sensitive_hello def _redact(self) -> None: if self._redacted: return self._kwargs = {k: v for k, v in self._kwargs.items() if v is not None} if "durationMS" in self._kwargs and hasattr(self._kwargs["durationMS"], "total_seconds"): self._kwargs["durationMS"] = self._kwargs["durationMS"].total_seconds() * 1000 if "serviceId" in self._kwargs: self._kwargs["serviceId"] = str(self._kwargs["serviceId"]) document_length = int(os.getenv("MONGOB_LOG_MAX_DOCUMENT_LENGTH", _DEFAULT_DOCUMENT_LENGTH)) if document_length < 0: document_length = _DEFAULT_DOCUMENT_LENGTH is_server_side_error = self._kwargs.pop("isServerSideError", False) for doc_name in _DOCUMENT_NAMES: doc = self._kwargs.get(doc_name) if doc: if doc_name == "failure" and is_server_side_error: doc = {k: v for k, v in doc.items() if k in _REDACTED_FAILURE_FIELDS} if doc_name != "failure" and self._is_sensitive(doc_name): doc = json_util.dumps({}) else: truncated_doc = _truncate_documents(doc, document_length)[0] doc = json_util.dumps( truncated_doc, json_options=_JSON_OPTIONS, default=lambda o: o.__repr__(), ) if len(doc) > document_length: doc = ( doc.encode()[:document_length].decode("unicode-escape", "ignore") ) + "..." self._kwargs[doc_name] = doc self._redacted = True mongodb-mongo-python-driver-509e9b7/pymongo/max_staleness_selectors.py000066400000000000000000000111011462766011000264220ustar00rootroot00000000000000# Copyright 2016 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. """Criteria to select ServerDescriptions based on maxStalenessSeconds. The Max Staleness Spec says: When there is a known primary P, a secondary S's staleness is estimated with this formula: (S.lastUpdateTime - S.lastWriteDate) - (P.lastUpdateTime - P.lastWriteDate) + heartbeatFrequencyMS When there is no known primary, a secondary S's staleness is estimated with: SMax.lastWriteDate - S.lastWriteDate + heartbeatFrequencyMS where "SMax" is the secondary with the greatest lastWriteDate. """ from __future__ import annotations from typing import TYPE_CHECKING from pymongo.errors import ConfigurationError from pymongo.server_type import SERVER_TYPE if TYPE_CHECKING: from pymongo.server_selectors import Selection # Constant defined in Max Staleness Spec: An idle primary writes a no-op every # 10 seconds to refresh secondaries' lastWriteDate values. IDLE_WRITE_PERIOD = 10 SMALLEST_MAX_STALENESS = 90 def _validate_max_staleness(max_staleness: int, heartbeat_frequency: int) -> None: # We checked for max staleness -1 before this, it must be positive here. if max_staleness < heartbeat_frequency + IDLE_WRITE_PERIOD: raise ConfigurationError( "maxStalenessSeconds must be at least heartbeatFrequencyMS +" " %d seconds. maxStalenessSeconds is set to %d," " heartbeatFrequencyMS is set to %d." % (IDLE_WRITE_PERIOD, max_staleness, heartbeat_frequency * 1000) ) if max_staleness < SMALLEST_MAX_STALENESS: raise ConfigurationError( "maxStalenessSeconds must be at least %d. " "maxStalenessSeconds is set to %d." % (SMALLEST_MAX_STALENESS, max_staleness) ) def _with_primary(max_staleness: int, selection: Selection) -> Selection: """Apply max_staleness, in seconds, to a Selection with a known primary.""" primary = selection.primary assert primary sds = [] for s in selection.server_descriptions: if s.server_type == SERVER_TYPE.RSSecondary: # See max-staleness.rst for explanation of this formula. assert s.last_write_date and primary.last_write_date # noqa: PT018 staleness = ( (s.last_update_time - s.last_write_date) - (primary.last_update_time - primary.last_write_date) + selection.heartbeat_frequency ) if staleness <= max_staleness: sds.append(s) else: sds.append(s) return selection.with_server_descriptions(sds) def _no_primary(max_staleness: int, selection: Selection) -> Selection: """Apply max_staleness, in seconds, to a Selection with no known primary.""" # Secondary that's replicated the most recent writes. smax = selection.secondary_with_max_last_write_date() if not smax: # No secondaries and no primary, short-circuit out of here. return selection.with_server_descriptions([]) sds = [] for s in selection.server_descriptions: if s.server_type == SERVER_TYPE.RSSecondary: # See max-staleness.rst for explanation of this formula. assert smax.last_write_date and s.last_write_date # noqa: PT018 staleness = smax.last_write_date - s.last_write_date + selection.heartbeat_frequency if staleness <= max_staleness: sds.append(s) else: sds.append(s) return selection.with_server_descriptions(sds) def select(max_staleness: int, selection: Selection) -> Selection: """Apply max_staleness, in seconds, to a Selection.""" if max_staleness == -1: return selection # Server Selection Spec: If the TopologyType is ReplicaSetWithPrimary or # ReplicaSetNoPrimary, a client MUST raise an error if maxStaleness < # heartbeatFrequency + IDLE_WRITE_PERIOD, or if maxStaleness < 90. _validate_max_staleness(max_staleness, selection.heartbeat_frequency) if selection.primary: return _with_primary(max_staleness, selection) else: return _no_primary(max_staleness, selection) mongodb-mongo-python-driver-509e9b7/pymongo/message.py000066400000000000000000001630711462766011000231330ustar00rootroot00000000000000# Copyright 2009-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. """Tools for creating `messages `_ to be sent to MongoDB. .. note:: This module is for internal use and is generally not needed by application developers. """ from __future__ import annotations import datetime import logging import random import struct from io import BytesIO as _BytesIO from typing import ( TYPE_CHECKING, Any, Callable, Iterable, Mapping, MutableMapping, NoReturn, Optional, Union, ) import bson from bson import CodecOptions, _decode_selective, _dict_to_bson, _make_c_string, encode from bson.int64 import Int64 from bson.raw_bson import ( _RAW_ARRAY_BSON_OPTIONS, DEFAULT_RAW_BSON_OPTIONS, RawBSONDocument, _inflate_bson, ) try: from pymongo import _cmessage # type: ignore[attr-defined] _use_c = True except ImportError: _use_c = False from pymongo.errors import ( ConfigurationError, CursorNotFound, DocumentTooLarge, ExecutionTimeout, InvalidOperation, NotPrimaryError, OperationFailure, ProtocolError, ) from pymongo.hello import HelloCompat from pymongo.helpers import _handle_reauth from pymongo.logger import _COMMAND_LOGGER, _CommandStatusMessage, _debug_log from pymongo.read_preferences import ReadPreference from pymongo.write_concern import WriteConcern if TYPE_CHECKING: from datetime import timedelta from pymongo.client_session import ClientSession from pymongo.compression_support import SnappyContext, ZlibContext, ZstdContext from pymongo.mongo_client import MongoClient from pymongo.monitoring import _EventListeners from pymongo.pool import Connection from pymongo.read_concern import ReadConcern from pymongo.read_preferences import _ServerMode from pymongo.typings import _Address, _DocumentOut MAX_INT32 = 2147483647 MIN_INT32 = -2147483648 # Overhead allowed for encoded command documents. _COMMAND_OVERHEAD = 16382 _INSERT = 0 _UPDATE = 1 _DELETE = 2 _EMPTY = b"" _BSONOBJ = b"\x03" _ZERO_8 = b"\x00" _ZERO_16 = b"\x00\x00" _ZERO_32 = b"\x00\x00\x00\x00" _ZERO_64 = b"\x00\x00\x00\x00\x00\x00\x00\x00" _SKIPLIM = b"\x00\x00\x00\x00\xff\xff\xff\xff" _OP_MAP = { _INSERT: b"\x04documents\x00\x00\x00\x00\x00", _UPDATE: b"\x04updates\x00\x00\x00\x00\x00", _DELETE: b"\x04deletes\x00\x00\x00\x00\x00", } _FIELD_MAP = {"insert": "documents", "update": "updates", "delete": "deletes"} _UNICODE_REPLACE_CODEC_OPTIONS: CodecOptions[Mapping[str, Any]] = CodecOptions( unicode_decode_error_handler="replace" ) def _randint() -> int: """Generate a pseudo random 32 bit integer.""" return random.randint(MIN_INT32, MAX_INT32) # noqa: S311 def _maybe_add_read_preference( spec: MutableMapping[str, Any], read_preference: _ServerMode ) -> MutableMapping[str, Any]: """Add $readPreference to spec when appropriate.""" mode = read_preference.mode document = read_preference.document # Only add $readPreference if it's something other than primary to avoid # problems with mongos versions that don't support read preferences. Also, # for maximum backwards compatibility, don't add $readPreference for # secondaryPreferred unless tags or maxStalenessSeconds are in use (setting # the secondaryOkay bit has the same effect). if mode and (mode != ReadPreference.SECONDARY_PREFERRED.mode or len(document) > 1): if "$query" not in spec: spec = {"$query": spec} spec["$readPreference"] = document return spec def _convert_exception(exception: Exception) -> dict[str, Any]: """Convert an Exception into a failure document for publishing.""" return {"errmsg": str(exception), "errtype": exception.__class__.__name__} def _convert_write_result( operation: str, command: Mapping[str, Any], result: Mapping[str, Any] ) -> dict[str, Any]: """Convert a legacy write result to write command format.""" # Based on _merge_legacy from bulk.py affected = result.get("n", 0) res = {"ok": 1, "n": affected} errmsg = result.get("errmsg", result.get("err", "")) if errmsg: # The write was successful on at least the primary so don't return. if result.get("wtimeout"): res["writeConcernError"] = {"errmsg": errmsg, "code": 64, "errInfo": {"wtimeout": True}} else: # The write failed. error = {"index": 0, "code": result.get("code", 8), "errmsg": errmsg} if "errInfo" in result: error["errInfo"] = result["errInfo"] res["writeErrors"] = [error] return res if operation == "insert": # GLE result for insert is always 0 in most MongoDB versions. res["n"] = len(command["documents"]) elif operation == "update": if "upserted" in result: res["upserted"] = [{"index": 0, "_id": result["upserted"]}] # Versions of MongoDB before 2.6 don't return the _id for an # upsert if _id is not an ObjectId. elif result.get("updatedExisting") is False and affected == 1: # If _id is in both the update document *and* the query spec # the update document _id takes precedence. update = command["updates"][0] _id = update["u"].get("_id", update["q"].get("_id")) res["upserted"] = [{"index": 0, "_id": _id}] return res _OPTIONS = { "tailable": 2, "oplogReplay": 8, "noCursorTimeout": 16, "awaitData": 32, "allowPartialResults": 128, } _MODIFIERS = { "$query": "filter", "$orderby": "sort", "$hint": "hint", "$comment": "comment", "$maxScan": "maxScan", "$maxTimeMS": "maxTimeMS", "$max": "max", "$min": "min", "$returnKey": "returnKey", "$showRecordId": "showRecordId", "$showDiskLoc": "showRecordId", # <= MongoDb 3.0 "$snapshot": "snapshot", } def _gen_find_command( coll: str, spec: Mapping[str, Any], projection: Optional[Union[Mapping[str, Any], Iterable[str]]], skip: int, limit: int, batch_size: Optional[int], options: Optional[int], read_concern: ReadConcern, collation: Optional[Mapping[str, Any]] = None, session: Optional[ClientSession] = None, allow_disk_use: Optional[bool] = None, ) -> dict[str, Any]: """Generate a find command document.""" cmd: dict[str, Any] = {"find": coll} if "$query" in spec: cmd.update( [ (_MODIFIERS[key], val) if key in _MODIFIERS else (key, val) for key, val in spec.items() ] ) if "$explain" in cmd: cmd.pop("$explain") if "$readPreference" in cmd: cmd.pop("$readPreference") else: cmd["filter"] = spec if projection: cmd["projection"] = projection if skip: cmd["skip"] = skip if limit: cmd["limit"] = abs(limit) if limit < 0: cmd["singleBatch"] = True if batch_size: cmd["batchSize"] = batch_size if read_concern.level and not (session and session.in_transaction): cmd["readConcern"] = read_concern.document if collation: cmd["collation"] = collation if allow_disk_use is not None: cmd["allowDiskUse"] = allow_disk_use if options: cmd.update([(opt, True) for opt, val in _OPTIONS.items() if options & val]) return cmd def _gen_get_more_command( cursor_id: Optional[int], coll: str, batch_size: Optional[int], max_await_time_ms: Optional[int], comment: Optional[Any], conn: Connection, ) -> dict[str, Any]: """Generate a getMore command document.""" cmd: dict[str, Any] = {"getMore": cursor_id, "collection": coll} if batch_size: cmd["batchSize"] = batch_size if max_await_time_ms is not None: cmd["maxTimeMS"] = max_await_time_ms if comment is not None and conn.max_wire_version >= 9: cmd["comment"] = comment return cmd class _Query: """A query operation.""" __slots__ = ( "flags", "db", "coll", "ntoskip", "spec", "fields", "codec_options", "read_preference", "limit", "batch_size", "name", "read_concern", "collation", "session", "client", "allow_disk_use", "_as_command", "exhaust", ) # For compatibility with the _GetMore class. conn_mgr = None cursor_id = None def __init__( self, flags: int, db: str, coll: str, ntoskip: int, spec: Mapping[str, Any], fields: Optional[Mapping[str, Any]], codec_options: CodecOptions, read_preference: _ServerMode, limit: int, batch_size: int, read_concern: ReadConcern, collation: Optional[Mapping[str, Any]], session: Optional[ClientSession], client: MongoClient, allow_disk_use: Optional[bool], exhaust: bool, ): self.flags = flags self.db = db self.coll = coll self.ntoskip = ntoskip self.spec = spec self.fields = fields self.codec_options = codec_options self.read_preference = read_preference self.read_concern = read_concern self.limit = limit self.batch_size = batch_size self.collation = collation self.session = session self.client = client self.allow_disk_use = allow_disk_use self.name = "find" self._as_command: Optional[tuple[dict[str, Any], str]] = None self.exhaust = exhaust def reset(self) -> None: self._as_command = None def namespace(self) -> str: return f"{self.db}.{self.coll}" def use_command(self, conn: Connection) -> bool: use_find_cmd = False if not self.exhaust: use_find_cmd = True elif conn.max_wire_version >= 8: # OP_MSG supports exhaust on MongoDB 4.2+ use_find_cmd = True elif not self.read_concern.ok_for_legacy: raise ConfigurationError( "read concern level of %s is not valid " "with a max wire version of %d." % (self.read_concern.level, conn.max_wire_version) ) conn.validate_session(self.client, self.session) return use_find_cmd def as_command( self, conn: Connection, apply_timeout: bool = False ) -> tuple[dict[str, Any], str]: """Return a find command document for this query.""" # We use the command twice: on the wire and for command monitoring. # Generate it once, for speed and to avoid repeating side-effects. if self._as_command is not None: return self._as_command explain = "$explain" in self.spec cmd: dict[str, Any] = _gen_find_command( self.coll, self.spec, self.fields, self.ntoskip, self.limit, self.batch_size, self.flags, self.read_concern, self.collation, self.session, self.allow_disk_use, ) if explain: self.name = "explain" cmd = {"explain": cmd} session = self.session conn.add_server_api(cmd) if session: session._apply_to(cmd, False, self.read_preference, conn) # Explain does not support readConcern. if not explain and not session.in_transaction: session._update_read_concern(cmd, conn) conn.send_cluster_time(cmd, session, self.client) # Support auto encryption client = self.client if client._encrypter and not client._encrypter._bypass_auto_encryption: cmd = client._encrypter.encrypt(self.db, cmd, self.codec_options) # Support CSOT if apply_timeout: conn.apply_timeout(client, cmd) self._as_command = cmd, self.db return self._as_command def get_message( self, read_preference: _ServerMode, conn: Connection, use_cmd: bool = False ) -> tuple[int, bytes, int]: """Get a query message, possibly setting the secondaryOk bit.""" # Use the read_preference decided by _socket_from_server. self.read_preference = read_preference if read_preference.mode: # Set the secondaryOk bit. flags = self.flags | 4 else: flags = self.flags ns = self.namespace() spec = self.spec if use_cmd: spec = self.as_command(conn, apply_timeout=True)[0] request_id, msg, size, _ = _op_msg( 0, spec, self.db, read_preference, self.codec_options, ctx=conn.compression_context, ) return request_id, msg, size # OP_QUERY treats ntoreturn of -1 and 1 the same, return # one document and close the cursor. We have to use 2 for # batch size if 1 is specified. ntoreturn = self.batch_size == 1 and 2 or self.batch_size if self.limit: if ntoreturn: ntoreturn = min(self.limit, ntoreturn) else: ntoreturn = self.limit if conn.is_mongos: assert isinstance(spec, MutableMapping) spec = _maybe_add_read_preference(spec, read_preference) return _query( flags, ns, self.ntoskip, ntoreturn, spec, None if use_cmd else self.fields, self.codec_options, ctx=conn.compression_context, ) class _GetMore: """A getmore operation.""" __slots__ = ( "db", "coll", "ntoreturn", "cursor_id", "max_await_time_ms", "codec_options", "read_preference", "session", "client", "conn_mgr", "_as_command", "exhaust", "comment", ) name = "getMore" def __init__( self, db: str, coll: str, ntoreturn: int, cursor_id: int, codec_options: CodecOptions, read_preference: _ServerMode, session: Optional[ClientSession], client: MongoClient, max_await_time_ms: Optional[int], conn_mgr: Any, exhaust: bool, comment: Any, ): self.db = db self.coll = coll self.ntoreturn = ntoreturn self.cursor_id = cursor_id self.codec_options = codec_options self.read_preference = read_preference self.session = session self.client = client self.max_await_time_ms = max_await_time_ms self.conn_mgr = conn_mgr self._as_command: Optional[tuple[dict[str, Any], str]] = None self.exhaust = exhaust self.comment = comment def reset(self) -> None: self._as_command = None def namespace(self) -> str: return f"{self.db}.{self.coll}" def use_command(self, conn: Connection) -> bool: use_cmd = False if not self.exhaust: use_cmd = True elif conn.max_wire_version >= 8: # OP_MSG supports exhaust on MongoDB 4.2+ use_cmd = True conn.validate_session(self.client, self.session) return use_cmd def as_command( self, conn: Connection, apply_timeout: bool = False ) -> tuple[dict[str, Any], str]: """Return a getMore command document for this query.""" # See _Query.as_command for an explanation of this caching. if self._as_command is not None: return self._as_command cmd: dict[str, Any] = _gen_get_more_command( self.cursor_id, self.coll, self.ntoreturn, self.max_await_time_ms, self.comment, conn, ) if self.session: self.session._apply_to(cmd, False, self.read_preference, conn) conn.add_server_api(cmd) conn.send_cluster_time(cmd, self.session, self.client) # Support auto encryption client = self.client if client._encrypter and not client._encrypter._bypass_auto_encryption: cmd = client._encrypter.encrypt(self.db, cmd, self.codec_options) # Support CSOT if apply_timeout: conn.apply_timeout(client, cmd=None) self._as_command = cmd, self.db return self._as_command def get_message( self, dummy0: Any, conn: Connection, use_cmd: bool = False ) -> Union[tuple[int, bytes, int], tuple[int, bytes]]: """Get a getmore message.""" ns = self.namespace() ctx = conn.compression_context if use_cmd: spec = self.as_command(conn, apply_timeout=True)[0] if self.conn_mgr and self.exhaust: flags = _OpMsg.EXHAUST_ALLOWED else: flags = 0 request_id, msg, size, _ = _op_msg( flags, spec, self.db, None, self.codec_options, ctx=conn.compression_context ) return request_id, msg, size return _get_more(ns, self.ntoreturn, self.cursor_id, ctx) class _RawBatchQuery(_Query): def use_command(self, conn: Connection) -> bool: # Compatibility checks. super().use_command(conn) if conn.max_wire_version >= 8: # MongoDB 4.2+ supports exhaust over OP_MSG return True elif not self.exhaust: return True return False class _RawBatchGetMore(_GetMore): def use_command(self, conn: Connection) -> bool: # Compatibility checks. super().use_command(conn) if conn.max_wire_version >= 8: # MongoDB 4.2+ supports exhaust over OP_MSG return True elif not self.exhaust: return True return False class _CursorAddress(tuple): """The server address (host, port) of a cursor, with namespace property.""" __namespace: Any def __new__(cls, address: _Address, namespace: str) -> _CursorAddress: self = tuple.__new__(cls, address) self.__namespace = namespace return self @property def namespace(self) -> str: """The namespace this cursor.""" return self.__namespace def __hash__(self) -> int: # Two _CursorAddress instances with different namespaces # must not hash the same. return ((*self, self.__namespace)).__hash__() def __eq__(self, other: object) -> bool: if isinstance(other, _CursorAddress): return tuple(self) == tuple(other) and self.namespace == other.namespace return NotImplemented def __ne__(self, other: object) -> bool: return not self == other _pack_compression_header = struct.Struct(" tuple[int, bytes]: """Takes message data, compresses it, and adds an OP_COMPRESSED header.""" compressed = ctx.compress(data) request_id = _randint() header = _pack_compression_header( _COMPRESSION_HEADER_SIZE + len(compressed), # Total message length request_id, # Request id 0, # responseTo 2012, # operation id operation, # original operation id len(data), # uncompressed message length ctx.compressor_id, ) # compressor id return request_id, header + compressed _pack_header = struct.Struct(" tuple[int, bytes]: """Takes message data and adds a message header based on the operation. Returns the resultant message string. """ rid = _randint() message = _pack_header(16 + len(data), rid, 0, operation) return rid, message + data _pack_int = struct.Struct(" tuple[bytes, int, int]: """Get a OP_MSG message. Note: this method handles multiple documents in a type one payload but it does not perform batch splitting and the total message size is only checked *after* generating the entire message. """ # Encode the command document in payload 0 without checking keys. encoded = _dict_to_bson(command, False, opts) flags_type = _pack_op_msg_flags_type(flags, 0) total_size = len(encoded) max_doc_size = 0 if identifier and docs is not None: type_one = _pack_byte(1) cstring = _make_c_string(identifier) encoded_docs = [_dict_to_bson(doc, False, opts) for doc in docs] size = len(cstring) + sum(len(doc) for doc in encoded_docs) + 4 encoded_size = _pack_int(size) total_size += size max_doc_size = max(len(doc) for doc in encoded_docs) data = [flags_type, encoded, type_one, encoded_size, cstring, *encoded_docs] else: data = [flags_type, encoded] return b"".join(data), total_size, max_doc_size def _op_msg_compressed( flags: int, command: Mapping[str, Any], identifier: str, docs: Optional[list[Mapping[str, Any]]], opts: CodecOptions, ctx: Union[SnappyContext, ZlibContext, ZstdContext], ) -> tuple[int, bytes, int, int]: """Internal OP_MSG message helper.""" msg, total_size, max_bson_size = _op_msg_no_header(flags, command, identifier, docs, opts) rid, msg = _compress(2013, msg, ctx) return rid, msg, total_size, max_bson_size def _op_msg_uncompressed( flags: int, command: Mapping[str, Any], identifier: str, docs: Optional[list[Mapping[str, Any]]], opts: CodecOptions, ) -> tuple[int, bytes, int, int]: """Internal compressed OP_MSG message helper.""" data, total_size, max_bson_size = _op_msg_no_header(flags, command, identifier, docs, opts) request_id, op_message = __pack_message(2013, data) return request_id, op_message, total_size, max_bson_size if _use_c: _op_msg_uncompressed = _cmessage._op_msg def _op_msg( flags: int, command: MutableMapping[str, Any], dbname: str, read_preference: Optional[_ServerMode], opts: CodecOptions, ctx: Union[SnappyContext, ZlibContext, ZstdContext, None] = None, ) -> tuple[int, bytes, int, int]: """Get a OP_MSG message.""" command["$db"] = dbname # getMore commands do not send $readPreference. if read_preference is not None and "$readPreference" not in command: # Only send $readPreference if it's not primary (the default). if read_preference.mode: command["$readPreference"] = read_preference.document name = next(iter(command)) try: identifier = _FIELD_MAP[name] docs = command.pop(identifier) except KeyError: identifier = "" docs = None try: if ctx: return _op_msg_compressed(flags, command, identifier, docs, opts, ctx) return _op_msg_uncompressed(flags, command, identifier, docs, opts) finally: # Add the field back to the command. if identifier: command[identifier] = docs def _query_impl( options: int, collection_name: str, num_to_skip: int, num_to_return: int, query: Mapping[str, Any], field_selector: Optional[Mapping[str, Any]], opts: CodecOptions, ) -> tuple[bytes, int]: """Get an OP_QUERY message.""" encoded = _dict_to_bson(query, False, opts) if field_selector: efs = _dict_to_bson(field_selector, False, opts) else: efs = b"" max_bson_size = max(len(encoded), len(efs)) return ( b"".join( [ _pack_int(options), _make_c_string(collection_name), _pack_int(num_to_skip), _pack_int(num_to_return), encoded, efs, ] ), max_bson_size, ) def _query_compressed( options: int, collection_name: str, num_to_skip: int, num_to_return: int, query: Mapping[str, Any], field_selector: Optional[Mapping[str, Any]], opts: CodecOptions, ctx: Union[SnappyContext, ZlibContext, ZstdContext], ) -> tuple[int, bytes, int]: """Internal compressed query message helper.""" op_query, max_bson_size = _query_impl( options, collection_name, num_to_skip, num_to_return, query, field_selector, opts ) rid, msg = _compress(2004, op_query, ctx) return rid, msg, max_bson_size def _query_uncompressed( options: int, collection_name: str, num_to_skip: int, num_to_return: int, query: Mapping[str, Any], field_selector: Optional[Mapping[str, Any]], opts: CodecOptions, ) -> tuple[int, bytes, int]: """Internal query message helper.""" op_query, max_bson_size = _query_impl( options, collection_name, num_to_skip, num_to_return, query, field_selector, opts ) rid, msg = __pack_message(2004, op_query) return rid, msg, max_bson_size if _use_c: _query_uncompressed = _cmessage._query_message def _query( options: int, collection_name: str, num_to_skip: int, num_to_return: int, query: Mapping[str, Any], field_selector: Optional[Mapping[str, Any]], opts: CodecOptions, ctx: Union[SnappyContext, ZlibContext, ZstdContext, None] = None, ) -> tuple[int, bytes, int]: """Get a **query** message.""" if ctx: return _query_compressed( options, collection_name, num_to_skip, num_to_return, query, field_selector, opts, ctx ) return _query_uncompressed( options, collection_name, num_to_skip, num_to_return, query, field_selector, opts ) _pack_long_long = struct.Struct(" bytes: """Get an OP_GET_MORE message.""" return b"".join( [ _ZERO_32, _make_c_string(collection_name), _pack_int(num_to_return), _pack_long_long(cursor_id), ] ) def _get_more_compressed( collection_name: str, num_to_return: int, cursor_id: int, ctx: Union[SnappyContext, ZlibContext, ZstdContext], ) -> tuple[int, bytes]: """Internal compressed getMore message helper.""" return _compress(2005, _get_more_impl(collection_name, num_to_return, cursor_id), ctx) def _get_more_uncompressed( collection_name: str, num_to_return: int, cursor_id: int ) -> tuple[int, bytes]: """Internal getMore message helper.""" return __pack_message(2005, _get_more_impl(collection_name, num_to_return, cursor_id)) if _use_c: _get_more_uncompressed = _cmessage._get_more_message def _get_more( collection_name: str, num_to_return: int, cursor_id: int, ctx: Union[SnappyContext, ZlibContext, ZstdContext, None] = None, ) -> tuple[int, bytes]: """Get a **getMore** message.""" if ctx: return _get_more_compressed(collection_name, num_to_return, cursor_id, ctx) return _get_more_uncompressed(collection_name, num_to_return, cursor_id) class _BulkWriteContext: """A wrapper around Connection for use with write splitting functions.""" __slots__ = ( "db_name", "conn", "op_id", "name", "field", "publish", "start_time", "listeners", "session", "compress", "op_type", "codec", ) def __init__( self, database_name: str, cmd_name: str, conn: Connection, operation_id: int, listeners: _EventListeners, session: ClientSession, op_type: int, codec: CodecOptions, ): self.db_name = database_name self.conn = conn self.op_id = operation_id self.listeners = listeners self.publish = listeners.enabled_for_commands self.name = cmd_name self.field = _FIELD_MAP[self.name] self.start_time = datetime.datetime.now() self.session = session self.compress = bool(conn.compression_context) self.op_type = op_type self.codec = codec def __batch_command( self, cmd: MutableMapping[str, Any], docs: list[Mapping[str, Any]] ) -> tuple[int, bytes, list[Mapping[str, Any]]]: namespace = self.db_name + ".$cmd" request_id, msg, to_send = _do_batched_op_msg( namespace, self.op_type, cmd, docs, self.codec, self ) if not to_send: raise InvalidOperation("cannot do an empty bulk write") return request_id, msg, to_send def execute( self, cmd: MutableMapping[str, Any], docs: list[Mapping[str, Any]], client: MongoClient ) -> tuple[Mapping[str, Any], list[Mapping[str, Any]]]: request_id, msg, to_send = self.__batch_command(cmd, docs) result = self.write_command(cmd, request_id, msg, to_send, client) client._process_response(result, self.session) return result, to_send def execute_unack( self, cmd: MutableMapping[str, Any], docs: list[Mapping[str, Any]], client: MongoClient ) -> list[Mapping[str, Any]]: request_id, msg, to_send = self.__batch_command(cmd, docs) # Though this isn't strictly a "legacy" write, the helper # handles publishing commands and sending our message # without receiving a result. Send 0 for max_doc_size # to disable size checking. Size checking is handled while # the documents are encoded to BSON. self.unack_write(cmd, request_id, msg, 0, to_send, client) return to_send @property def max_bson_size(self) -> int: """A proxy for SockInfo.max_bson_size.""" return self.conn.max_bson_size @property def max_message_size(self) -> int: """A proxy for SockInfo.max_message_size.""" if self.compress: # Subtract 16 bytes for the message header. return self.conn.max_message_size - 16 return self.conn.max_message_size @property def max_write_batch_size(self) -> int: """A proxy for SockInfo.max_write_batch_size.""" return self.conn.max_write_batch_size @property def max_split_size(self) -> int: """The maximum size of a BSON command before batch splitting.""" return self.max_bson_size def unack_write( self, cmd: MutableMapping[str, Any], request_id: int, msg: bytes, max_doc_size: int, docs: list[Mapping[str, Any]], client: MongoClient, ) -> Optional[Mapping[str, Any]]: """A proxy for Connection.unack_write that handles event publishing.""" if _COMMAND_LOGGER.isEnabledFor(logging.DEBUG): _debug_log( _COMMAND_LOGGER, clientId=client._topology_settings._topology_id, message=_CommandStatusMessage.STARTED, command=cmd, commandName=next(iter(cmd)), databaseName=self.db_name, requestId=request_id, operationId=request_id, driverConnectionId=self.conn.id, serverConnectionId=self.conn.server_connection_id, serverHost=self.conn.address[0], serverPort=self.conn.address[1], serviceId=self.conn.service_id, ) if self.publish: cmd = self._start(cmd, request_id, docs) try: result = self.conn.unack_write(msg, max_doc_size) # type: ignore[func-returns-value] duration = datetime.datetime.now() - self.start_time if result is not None: reply = _convert_write_result(self.name, cmd, result) else: # Comply with APM spec. reply = {"ok": 1} if _COMMAND_LOGGER.isEnabledFor(logging.DEBUG): _debug_log( _COMMAND_LOGGER, clientId=client._topology_settings._topology_id, message=_CommandStatusMessage.SUCCEEDED, durationMS=duration, reply=reply, commandName=next(iter(cmd)), databaseName=self.db_name, requestId=request_id, operationId=request_id, driverConnectionId=self.conn.id, serverConnectionId=self.conn.server_connection_id, serverHost=self.conn.address[0], serverPort=self.conn.address[1], serviceId=self.conn.service_id, ) if self.publish: self._succeed(request_id, reply, duration) except Exception as exc: duration = datetime.datetime.now() - self.start_time if isinstance(exc, OperationFailure): failure: _DocumentOut = _convert_write_result(self.name, cmd, exc.details) # type: ignore[arg-type] elif isinstance(exc, NotPrimaryError): failure = exc.details # type: ignore[assignment] else: failure = _convert_exception(exc) if _COMMAND_LOGGER.isEnabledFor(logging.DEBUG): _debug_log( _COMMAND_LOGGER, clientId=client._topology_settings._topology_id, message=_CommandStatusMessage.FAILED, durationMS=duration, failure=failure, commandName=next(iter(cmd)), databaseName=self.db_name, requestId=request_id, operationId=request_id, driverConnectionId=self.conn.id, serverConnectionId=self.conn.server_connection_id, serverHost=self.conn.address[0], serverPort=self.conn.address[1], serviceId=self.conn.service_id, isServerSideError=isinstance(exc, OperationFailure), ) if self.publish: assert self.start_time is not None self._fail(request_id, failure, duration) raise finally: self.start_time = datetime.datetime.now() return result @_handle_reauth def write_command( self, cmd: MutableMapping[str, Any], request_id: int, msg: bytes, docs: list[Mapping[str, Any]], client: MongoClient, ) -> dict[str, Any]: """A proxy for SocketInfo.write_command that handles event publishing.""" cmd[self.field] = docs if _COMMAND_LOGGER.isEnabledFor(logging.DEBUG): _debug_log( _COMMAND_LOGGER, clientId=client._topology_settings._topology_id, message=_CommandStatusMessage.STARTED, command=cmd, commandName=next(iter(cmd)), databaseName=self.db_name, requestId=request_id, operationId=request_id, driverConnectionId=self.conn.id, serverConnectionId=self.conn.server_connection_id, serverHost=self.conn.address[0], serverPort=self.conn.address[1], serviceId=self.conn.service_id, ) if self.publish: self._start(cmd, request_id, docs) try: reply = self.conn.write_command(request_id, msg, self.codec) duration = datetime.datetime.now() - self.start_time if _COMMAND_LOGGER.isEnabledFor(logging.DEBUG): _debug_log( _COMMAND_LOGGER, clientId=client._topology_settings._topology_id, message=_CommandStatusMessage.SUCCEEDED, durationMS=duration, reply=reply, commandName=next(iter(cmd)), databaseName=self.db_name, requestId=request_id, operationId=request_id, driverConnectionId=self.conn.id, serverConnectionId=self.conn.server_connection_id, serverHost=self.conn.address[0], serverPort=self.conn.address[1], serviceId=self.conn.service_id, ) if self.publish: self._succeed(request_id, reply, duration) except Exception as exc: duration = datetime.datetime.now() - self.start_time if isinstance(exc, (NotPrimaryError, OperationFailure)): failure: _DocumentOut = exc.details # type: ignore[assignment] else: failure = _convert_exception(exc) if _COMMAND_LOGGER.isEnabledFor(logging.DEBUG): _debug_log( _COMMAND_LOGGER, clientId=client._topology_settings._topology_id, message=_CommandStatusMessage.FAILED, durationMS=duration, failure=failure, commandName=next(iter(cmd)), databaseName=self.db_name, requestId=request_id, operationId=request_id, driverConnectionId=self.conn.id, serverConnectionId=self.conn.server_connection_id, serverHost=self.conn.address[0], serverPort=self.conn.address[1], serviceId=self.conn.service_id, isServerSideError=isinstance(exc, OperationFailure), ) if self.publish: self._fail(request_id, failure, duration) raise finally: self.start_time = datetime.datetime.now() return reply def _start( self, cmd: MutableMapping[str, Any], request_id: int, docs: list[Mapping[str, Any]] ) -> MutableMapping[str, Any]: """Publish a CommandStartedEvent.""" cmd[self.field] = docs self.listeners.publish_command_start( cmd, self.db_name, request_id, self.conn.address, self.conn.server_connection_id, self.op_id, self.conn.service_id, ) return cmd def _succeed(self, request_id: int, reply: _DocumentOut, duration: timedelta) -> None: """Publish a CommandSucceededEvent.""" self.listeners.publish_command_success( duration, reply, self.name, request_id, self.conn.address, self.conn.server_connection_id, self.op_id, self.conn.service_id, database_name=self.db_name, ) def _fail(self, request_id: int, failure: _DocumentOut, duration: timedelta) -> None: """Publish a CommandFailedEvent.""" self.listeners.publish_command_failure( duration, failure, self.name, request_id, self.conn.address, self.conn.server_connection_id, self.op_id, self.conn.service_id, database_name=self.db_name, ) # From the Client Side Encryption spec: # Because automatic encryption increases the size of commands, the driver # MUST split bulk writes at a reduced size limit before undergoing automatic # encryption. The write payload MUST be split at 2MiB (2097152). _MAX_SPLIT_SIZE_ENC = 2097152 class _EncryptedBulkWriteContext(_BulkWriteContext): __slots__ = () def __batch_command( self, cmd: MutableMapping[str, Any], docs: list[Mapping[str, Any]] ) -> tuple[dict[str, Any], list[Mapping[str, Any]]]: namespace = self.db_name + ".$cmd" msg, to_send = _encode_batched_write_command( namespace, self.op_type, cmd, docs, self.codec, self ) if not to_send: raise InvalidOperation("cannot do an empty bulk write") # Chop off the OP_QUERY header to get a properly batched write command. cmd_start = msg.index(b"\x00", 4) + 9 outgoing = _inflate_bson(memoryview(msg)[cmd_start:], DEFAULT_RAW_BSON_OPTIONS) return outgoing, to_send def execute( self, cmd: MutableMapping[str, Any], docs: list[Mapping[str, Any]], client: MongoClient ) -> tuple[Mapping[str, Any], list[Mapping[str, Any]]]: batched_cmd, to_send = self.__batch_command(cmd, docs) result: Mapping[str, Any] = self.conn.command( self.db_name, batched_cmd, codec_options=self.codec, session=self.session, client=client ) return result, to_send def execute_unack( self, cmd: MutableMapping[str, Any], docs: list[Mapping[str, Any]], client: MongoClient ) -> list[Mapping[str, Any]]: batched_cmd, to_send = self.__batch_command(cmd, docs) self.conn.command( self.db_name, batched_cmd, write_concern=WriteConcern(w=0), session=self.session, client=client, ) return to_send @property def max_split_size(self) -> int: """Reduce the batch splitting size.""" return _MAX_SPLIT_SIZE_ENC def _raise_document_too_large(operation: str, doc_size: int, max_size: int) -> NoReturn: """Internal helper for raising DocumentTooLarge.""" if operation == "insert": raise DocumentTooLarge( "BSON document too large (%d bytes)" " - the connected server supports" " BSON document sizes up to %d" " bytes." % (doc_size, max_size) ) else: # There's nothing intelligent we can say # about size for update and delete raise DocumentTooLarge(f"{operation!r} command document too large") # OP_MSG ------------------------------------------------------------- _OP_MSG_MAP = { _INSERT: b"documents\x00", _UPDATE: b"updates\x00", _DELETE: b"deletes\x00", } def _batched_op_msg_impl( operation: int, command: Mapping[str, Any], docs: list[Mapping[str, Any]], ack: bool, opts: CodecOptions, ctx: _BulkWriteContext, buf: _BytesIO, ) -> tuple[list[Mapping[str, Any]], int]: """Create a batched OP_MSG write.""" max_bson_size = ctx.max_bson_size max_write_batch_size = ctx.max_write_batch_size max_message_size = ctx.max_message_size flags = b"\x00\x00\x00\x00" if ack else b"\x02\x00\x00\x00" # Flags buf.write(flags) # Type 0 Section buf.write(b"\x00") buf.write(_dict_to_bson(command, False, opts)) # Type 1 Section buf.write(b"\x01") size_location = buf.tell() # Save space for size buf.write(b"\x00\x00\x00\x00") try: buf.write(_OP_MSG_MAP[operation]) except KeyError: raise InvalidOperation("Unknown command") from None to_send = [] idx = 0 for doc in docs: # Encode the current operation value = _dict_to_bson(doc, False, opts) doc_length = len(value) new_message_size = buf.tell() + doc_length # Does first document exceed max_message_size? doc_too_large = idx == 0 and (new_message_size > max_message_size) # When OP_MSG is used unacknowledged we have to check # document size client side or applications won't be notified. # Otherwise we let the server deal with documents that are too large # since ordered=False causes those documents to be skipped instead of # halting the bulk write operation. unacked_doc_too_large = not ack and (doc_length > max_bson_size) if doc_too_large or unacked_doc_too_large: write_op = list(_FIELD_MAP.keys())[operation] _raise_document_too_large(write_op, len(value), max_bson_size) # We have enough data, return this batch. if new_message_size > max_message_size: break buf.write(value) to_send.append(doc) idx += 1 # We have enough documents, return this batch. if idx == max_write_batch_size: break # Write type 1 section size length = buf.tell() buf.seek(size_location) buf.write(_pack_int(length - size_location)) return to_send, length def _encode_batched_op_msg( operation: int, command: Mapping[str, Any], docs: list[Mapping[str, Any]], ack: bool, opts: CodecOptions, ctx: _BulkWriteContext, ) -> tuple[bytes, list[Mapping[str, Any]]]: """Encode the next batched insert, update, or delete operation as OP_MSG. """ buf = _BytesIO() to_send, _ = _batched_op_msg_impl(operation, command, docs, ack, opts, ctx, buf) return buf.getvalue(), to_send if _use_c: _encode_batched_op_msg = _cmessage._encode_batched_op_msg def _batched_op_msg_compressed( operation: int, command: Mapping[str, Any], docs: list[Mapping[str, Any]], ack: bool, opts: CodecOptions, ctx: _BulkWriteContext, ) -> tuple[int, bytes, list[Mapping[str, Any]]]: """Create the next batched insert, update, or delete operation with OP_MSG, compressed. """ data, to_send = _encode_batched_op_msg(operation, command, docs, ack, opts, ctx) assert ctx.conn.compression_context is not None request_id, msg = _compress(2013, data, ctx.conn.compression_context) return request_id, msg, to_send def _batched_op_msg( operation: int, command: Mapping[str, Any], docs: list[Mapping[str, Any]], ack: bool, opts: CodecOptions, ctx: _BulkWriteContext, ) -> tuple[int, bytes, list[Mapping[str, Any]]]: """OP_MSG implementation entry point.""" buf = _BytesIO() # Save space for message length and request id buf.write(_ZERO_64) # responseTo, opCode buf.write(b"\x00\x00\x00\x00\xdd\x07\x00\x00") to_send, length = _batched_op_msg_impl(operation, command, docs, ack, opts, ctx, buf) # Header - request id and message length buf.seek(4) request_id = _randint() buf.write(_pack_int(request_id)) buf.seek(0) buf.write(_pack_int(length)) return request_id, buf.getvalue(), to_send if _use_c: _batched_op_msg = _cmessage._batched_op_msg def _do_batched_op_msg( namespace: str, operation: int, command: MutableMapping[str, Any], docs: list[Mapping[str, Any]], opts: CodecOptions, ctx: _BulkWriteContext, ) -> tuple[int, bytes, list[Mapping[str, Any]]]: """Create the next batched insert, update, or delete operation using OP_MSG. """ command["$db"] = namespace.split(".", 1)[0] if "writeConcern" in command: ack = bool(command["writeConcern"].get("w", 1)) else: ack = True if ctx.conn.compression_context: return _batched_op_msg_compressed(operation, command, docs, ack, opts, ctx) return _batched_op_msg(operation, command, docs, ack, opts, ctx) # End OP_MSG ----------------------------------------------------- def _encode_batched_write_command( namespace: str, operation: int, command: MutableMapping[str, Any], docs: list[Mapping[str, Any]], opts: CodecOptions, ctx: _BulkWriteContext, ) -> tuple[bytes, list[Mapping[str, Any]]]: """Encode the next batched insert, update, or delete command.""" buf = _BytesIO() to_send, _ = _batched_write_command_impl(namespace, operation, command, docs, opts, ctx, buf) return buf.getvalue(), to_send if _use_c: _encode_batched_write_command = _cmessage._encode_batched_write_command def _batched_write_command_impl( namespace: str, operation: int, command: MutableMapping[str, Any], docs: list[Mapping[str, Any]], opts: CodecOptions, ctx: _BulkWriteContext, buf: _BytesIO, ) -> tuple[list[Mapping[str, Any]], int]: """Create a batched OP_QUERY write command.""" max_bson_size = ctx.max_bson_size max_write_batch_size = ctx.max_write_batch_size # Max BSON object size + 16k - 2 bytes for ending NUL bytes. # Server guarantees there is enough room: SERVER-10643. max_cmd_size = max_bson_size + _COMMAND_OVERHEAD max_split_size = ctx.max_split_size # No options buf.write(_ZERO_32) # Namespace as C string buf.write(namespace.encode("utf8")) buf.write(_ZERO_8) # Skip: 0, Limit: -1 buf.write(_SKIPLIM) # Where to write command document length command_start = buf.tell() buf.write(encode(command)) # Start of payload buf.seek(-1, 2) # Work around some Jython weirdness. buf.truncate() try: buf.write(_OP_MAP[operation]) except KeyError: raise InvalidOperation("Unknown command") from None # Where to write list document length list_start = buf.tell() - 4 to_send = [] idx = 0 for doc in docs: # Encode the current operation key = str(idx).encode("utf8") value = _dict_to_bson(doc, False, opts) # Is there enough room to add this document? max_cmd_size accounts for # the two trailing null bytes. doc_too_large = len(value) > max_cmd_size if doc_too_large: write_op = list(_FIELD_MAP.keys())[operation] _raise_document_too_large(write_op, len(value), max_bson_size) enough_data = idx >= 1 and (buf.tell() + len(key) + len(value)) >= max_split_size enough_documents = idx >= max_write_batch_size if enough_data or enough_documents: break buf.write(_BSONOBJ) buf.write(key) buf.write(_ZERO_8) buf.write(value) to_send.append(doc) idx += 1 # Finalize the current OP_QUERY message. # Close list and command documents buf.write(_ZERO_16) # Write document lengths and request id length = buf.tell() buf.seek(list_start) buf.write(_pack_int(length - list_start - 1)) buf.seek(command_start) buf.write(_pack_int(length - command_start)) return to_send, length class _OpReply: """A MongoDB OP_REPLY response message.""" __slots__ = ("flags", "cursor_id", "number_returned", "documents") UNPACK_FROM = struct.Struct(" list[bytes]: """Check the response header from the database, without decoding BSON. Check the response for errors and unpack. Can raise CursorNotFound, NotPrimaryError, ExecutionTimeout, or OperationFailure. :param cursor_id: cursor_id we sent to get this response - used for raising an informative exception when we get cursor id not valid at server response. """ if self.flags & 1: # Shouldn't get this response if we aren't doing a getMore if cursor_id is None: raise ProtocolError("No cursor id for getMore operation") # Fake a getMore command response. OP_GET_MORE provides no # document. msg = "Cursor not found, cursor id: %d" % (cursor_id,) errobj = {"ok": 0, "errmsg": msg, "code": 43} raise CursorNotFound(msg, 43, errobj) elif self.flags & 2: error_object: dict = bson.BSON(self.documents).decode() # Fake the ok field if it doesn't exist. error_object.setdefault("ok", 0) if error_object["$err"].startswith(HelloCompat.LEGACY_ERROR): raise NotPrimaryError(error_object["$err"], error_object) elif error_object.get("code") == 50: default_msg = "operation exceeded time limit" raise ExecutionTimeout( error_object.get("$err", default_msg), error_object.get("code"), error_object ) raise OperationFailure( "database error: %s" % error_object.get("$err"), error_object.get("code"), error_object, ) if self.documents: return [self.documents] return [] def unpack_response( self, cursor_id: Optional[int] = None, codec_options: CodecOptions = _UNICODE_REPLACE_CODEC_OPTIONS, user_fields: Optional[Mapping[str, Any]] = None, legacy_response: bool = False, ) -> list[dict[str, Any]]: """Unpack a response from the database and decode the BSON document(s). Check the response for errors and unpack, returning a dictionary containing the response data. Can raise CursorNotFound, NotPrimaryError, ExecutionTimeout, or OperationFailure. :param cursor_id: cursor_id we sent to get this response - used for raising an informative exception when we get cursor id not valid at server response :param codec_options: an instance of :class:`~bson.codec_options.CodecOptions` :param user_fields: Response fields that should be decoded using the TypeDecoders from codec_options, passed to bson._decode_all_selective. """ self.raw_response(cursor_id) if legacy_response: return bson.decode_all(self.documents, codec_options) return bson._decode_all_selective(self.documents, codec_options, user_fields) def command_response(self, codec_options: CodecOptions) -> dict[str, Any]: """Unpack a command response.""" docs = self.unpack_response(codec_options=codec_options) assert self.number_returned == 1 return docs[0] def raw_command_response(self) -> NoReturn: """Return the bytes of the command response.""" # This should never be called on _OpReply. raise NotImplementedError @property def more_to_come(self) -> bool: """Is the moreToCome bit set on this response?""" return False @classmethod def unpack(cls, msg: bytes) -> _OpReply: """Construct an _OpReply from raw bytes.""" # PYTHON-945: ignore starting_from field. flags, cursor_id, _, number_returned = cls.UNPACK_FROM(msg) documents = msg[20:] return cls(flags, cursor_id, number_returned, documents) class _OpMsg: """A MongoDB OP_MSG response message.""" __slots__ = ("flags", "cursor_id", "number_returned", "payload_document") UNPACK_FROM = struct.Struct(" list[Mapping[str, Any]]: """ cursor_id is ignored user_fields is used to determine which fields must not be decoded """ inflated_response = _decode_selective( RawBSONDocument(self.payload_document), user_fields, _RAW_ARRAY_BSON_OPTIONS ) return [inflated_response] def unpack_response( self, cursor_id: Optional[int] = None, codec_options: CodecOptions = _UNICODE_REPLACE_CODEC_OPTIONS, user_fields: Optional[Mapping[str, Any]] = None, legacy_response: bool = False, ) -> list[dict[str, Any]]: """Unpack a OP_MSG command response. :param cursor_id: Ignored, for compatibility with _OpReply. :param codec_options: an instance of :class:`~bson.codec_options.CodecOptions` :param user_fields: Response fields that should be decoded using the TypeDecoders from codec_options, passed to bson._decode_all_selective. """ # If _OpMsg is in-use, this cannot be a legacy response. assert not legacy_response return bson._decode_all_selective(self.payload_document, codec_options, user_fields) def command_response(self, codec_options: CodecOptions) -> dict[str, Any]: """Unpack a command response.""" return self.unpack_response(codec_options=codec_options)[0] def raw_command_response(self) -> bytes: """Return the bytes of the command response.""" return self.payload_document @property def more_to_come(self) -> bool: """Is the moreToCome bit set on this response?""" return bool(self.flags & self.MORE_TO_COME) @classmethod def unpack(cls, msg: bytes) -> _OpMsg: """Construct an _OpMsg from raw bytes.""" flags, first_payload_type, first_payload_size = cls.UNPACK_FROM(msg) if flags != 0: if flags & cls.CHECKSUM_PRESENT: raise ProtocolError(f"Unsupported OP_MSG flag checksumPresent: 0x{flags:x}") if flags ^ cls.MORE_TO_COME: raise ProtocolError(f"Unsupported OP_MSG flags: 0x{flags:x}") if first_payload_type != 0: raise ProtocolError(f"Unsupported OP_MSG payload type: 0x{first_payload_type:x}") if len(msg) != first_payload_size + 5: raise ProtocolError("Unsupported OP_MSG reply: >1 section") payload_document = msg[5:] return cls(flags, payload_document) _UNPACK_REPLY: dict[int, Callable[[bytes], Union[_OpReply, _OpMsg]]] = { _OpReply.OP_CODE: _OpReply.unpack, _OpMsg.OP_CODE: _OpMsg.unpack, } mongodb-mongo-python-driver-509e9b7/pymongo/mongo_client.py000066400000000000000000003256111462766011000241640ustar00rootroot00000000000000# Copyright 2009-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. """Tools for connecting to MongoDB. .. seealso:: :doc:`/examples/high_availability` for examples of connecting to replica sets or sets of mongos servers. To get a :class:`~pymongo.database.Database` instance from a :class:`MongoClient` use either dictionary-style or attribute-style access: .. doctest:: >>> from pymongo import MongoClient >>> c = MongoClient() >>> c.test_database Database(MongoClient(host=['localhost:27017'], document_class=dict, tz_aware=False, connect=True), 'test_database') >>> c["test-database"] Database(MongoClient(host=['localhost:27017'], document_class=dict, tz_aware=False, connect=True), 'test-database') """ from __future__ import annotations import contextlib import os import weakref from collections import defaultdict from typing import ( TYPE_CHECKING, Any, Callable, ContextManager, FrozenSet, Generic, Iterator, Mapping, MutableMapping, NoReturn, Optional, Sequence, Type, TypeVar, Union, cast, ) from bson.codec_options import DEFAULT_CODEC_OPTIONS, CodecOptions, TypeRegistry from bson.timestamp import Timestamp from pymongo import ( _csot, client_session, common, database, helpers, message, periodic_executor, uri_parser, ) from pymongo.change_stream import ChangeStream, ClusterChangeStream from pymongo.client_options import ClientOptions from pymongo.client_session import _EmptyServerSession from pymongo.command_cursor import CommandCursor from pymongo.errors import ( AutoReconnect, BulkWriteError, ConfigurationError, ConnectionFailure, InvalidOperation, NotPrimaryError, OperationFailure, PyMongoError, ServerSelectionTimeoutError, WaitQueueTimeoutError, WriteConcernError, ) from pymongo.lock import _HAS_REGISTER_AT_FORK, _create_lock, _release_locks from pymongo.logger import _CLIENT_LOGGER, _log_or_warn from pymongo.monitoring import ConnectionClosedReason from pymongo.operations import _Op from pymongo.read_preferences import ReadPreference, _ServerMode from pymongo.server_selectors import writable_server_selector from pymongo.server_type import SERVER_TYPE from pymongo.settings import TopologySettings from pymongo.topology import Topology, _ErrorContext from pymongo.topology_description import TOPOLOGY_TYPE, TopologyDescription from pymongo.typings import ( ClusterTime, _Address, _CollationIn, _DocumentType, _DocumentTypeArg, _Pipeline, ) from pymongo.uri_parser import ( _check_options, _handle_option_deprecations, _handle_security_options, _normalize_options, ) from pymongo.write_concern import DEFAULT_WRITE_CONCERN, WriteConcern if TYPE_CHECKING: import sys from types import TracebackType from bson.objectid import ObjectId from pymongo.bulk import _Bulk from pymongo.client_session import ClientSession, _ServerSession from pymongo.cursor import _ConnectionManager from pymongo.database import Database from pymongo.message import _CursorAddress, _GetMore, _Query from pymongo.pool import Connection from pymongo.read_concern import ReadConcern from pymongo.response import Response from pymongo.server import Server from pymongo.server_selectors import Selection if sys.version_info[:2] >= (3, 9): from collections.abc import Generator else: # Deprecated since version 3.9: collections.abc.Generator now supports []. from typing import Generator T = TypeVar("T") _WriteCall = Callable[[Optional["ClientSession"], "Connection", bool], T] _ReadCall = Callable[[Optional["ClientSession"], "Server", "Connection", _ServerMode], T] class MongoClient(common.BaseObject, Generic[_DocumentType]): """ A client-side representation of a MongoDB cluster. Instances can represent either a standalone MongoDB server, a replica set, or a sharded cluster. Instances of this class are responsible for maintaining up-to-date state of the cluster, and possibly cache resources related to this, including background threads for monitoring, and connection pools. """ HOST = "localhost" PORT = 27017 # Define order to retrieve options from ClientOptions for __repr__. # No host/port; these are retrieved from TopologySettings. _constructor_args = ("document_class", "tz_aware", "connect") _clients: weakref.WeakValueDictionary = weakref.WeakValueDictionary() def __init__( self, host: Optional[Union[str, Sequence[str]]] = None, port: Optional[int] = None, document_class: Optional[Type[_DocumentType]] = None, tz_aware: Optional[bool] = None, connect: Optional[bool] = None, type_registry: Optional[TypeRegistry] = None, **kwargs: Any, ) -> None: """Client for a MongoDB instance, a replica set, or a set of mongoses. .. warning:: Starting in PyMongo 4.0, ``directConnection`` now has a default value of False instead of None. For more details, see the relevant section of the PyMongo 4.x migration guide: :ref:`pymongo4-migration-direct-connection`. The client object is thread-safe and has connection-pooling built in. If an operation fails because of a network error, :class:`~pymongo.errors.ConnectionFailure` is raised and the client reconnects in the background. Application code should handle this exception (recognizing that the operation failed) and then continue to execute. The `host` parameter can be a full `mongodb URI `_, in addition to a simple hostname. It can also be a list of hostnames but no more than one URI. Any port specified in the host string(s) will override the `port` parameter. For username and passwords reserved characters like ':', '/', '+' and '@' must be percent encoded following RFC 2396:: from urllib.parse import quote_plus uri = "mongodb://%s:%s@%s" % ( quote_plus(user), quote_plus(password), host) client = MongoClient(uri) Unix domain sockets are also supported. The socket path must be percent encoded in the URI:: uri = "mongodb://%s:%s@%s" % ( quote_plus(user), quote_plus(password), quote_plus(socket_path)) client = MongoClient(uri) But not when passed as a simple hostname:: client = MongoClient('/tmp/mongodb-27017.sock') Starting with version 3.6, PyMongo supports mongodb+srv:// URIs. The URI must include one, and only one, hostname. The hostname will be resolved to one or more DNS `SRV records `_ which will be used as the seed list for connecting to the MongoDB deployment. When using SRV URIs, the `authSource` and `replicaSet` configuration options can be specified using `TXT records `_. See the `Initial DNS Seedlist Discovery spec `_ for more details. Note that the use of SRV URIs implicitly enables TLS support. Pass tls=false in the URI to override. .. note:: MongoClient creation will block waiting for answers from DNS when mongodb+srv:// URIs are used. .. note:: Starting with version 3.0 the :class:`MongoClient` constructor no longer blocks while connecting to the server or servers, and it no longer raises :class:`~pymongo.errors.ConnectionFailure` if they are unavailable, nor :class:`~pymongo.errors.ConfigurationError` if the user's credentials are wrong. Instead, the constructor returns immediately and launches the connection process on background threads. You can check if the server is available like this:: from pymongo.errors import ConnectionFailure client = MongoClient() try: # The ping command is cheap and does not require auth. client.admin.command('ping') except ConnectionFailure: print("Server not available") .. warning:: When using PyMongo in a multiprocessing context, please read :ref:`multiprocessing` first. .. note:: Many of the following options can be passed using a MongoDB URI or keyword parameters. If the same option is passed in a URI and as a keyword parameter the keyword parameter takes precedence. :param host: hostname or IP address or Unix domain socket path of a single mongod or mongos instance to connect to, or a mongodb URI, or a list of hostnames (but no more than one mongodb URI). If `host` is an IPv6 literal it must be enclosed in '[' and ']' characters following the RFC2732 URL syntax (e.g. '[::1]' for localhost). Multihomed and round robin DNS addresses are **not** supported. :param port: port number on which to connect :param document_class: default class to use for documents returned from queries on this client :param tz_aware: if ``True``, :class:`~datetime.datetime` instances returned as values in a document by this :class:`MongoClient` will be timezone aware (otherwise they will be naive) :param connect: if ``True`` (the default), immediately begin connecting to MongoDB in the background. Otherwise connect on the first operation. :param type_registry: instance of :class:`~bson.codec_options.TypeRegistry` to enable encoding and decoding of custom types. :param datetime_conversion: Specifies how UTC datetimes should be decoded within BSON. Valid options include 'datetime_ms' to return as a DatetimeMS, 'datetime' to return as a datetime.datetime and raising a ValueError for out-of-range values, 'datetime_auto' to return DatetimeMS objects when the underlying datetime is out-of-range and 'datetime_clamp' to clamp to the minimum and maximum possible datetimes. Defaults to 'datetime'. See :ref:`handling-out-of-range-datetimes` for details. | **Other optional parameters can be passed as keyword arguments:** - `directConnection` (optional): if ``True``, forces this client to connect directly to the specified MongoDB host as a standalone. If ``false``, the client connects to the entire replica set of which the given MongoDB host(s) is a part. If this is ``True`` and a mongodb+srv:// URI or a URI containing multiple seeds is provided, an exception will be raised. - `maxPoolSize` (optional): The maximum allowable number of concurrent connections to each connected server. Requests to a server will block if there are `maxPoolSize` outstanding connections to the requested server. Defaults to 100. Can be either 0 or None, in which case there is no limit on the number of concurrent connections. - `minPoolSize` (optional): The minimum required number of concurrent connections that the pool will maintain to each connected server. Default is 0. - `maxIdleTimeMS` (optional): The maximum number of milliseconds that a connection can remain idle in the pool before being removed and replaced. Defaults to `None` (no limit). - `maxConnecting` (optional): The maximum number of connections that each pool can establish concurrently. Defaults to `2`. - `timeoutMS`: (integer or None) Controls how long (in milliseconds) the driver will wait when executing an operation (including retry attempts) before raising a timeout error. ``0`` or ``None`` means no timeout. - `socketTimeoutMS`: (integer or None) Controls how long (in milliseconds) the driver will wait for a response after sending an ordinary (non-monitoring) database operation before concluding that a network error has occurred. ``0`` or ``None`` means no timeout. Defaults to ``None`` (no timeout). - `connectTimeoutMS`: (integer or None) Controls how long (in milliseconds) the driver will wait during server monitoring when connecting a new socket to a server before concluding the server is unavailable. ``0`` or ``None`` means no timeout. Defaults to ``20000`` (20 seconds). - `server_selector`: (callable or None) Optional, user-provided function that augments server selection rules. The function should accept as an argument a list of :class:`~pymongo.server_description.ServerDescription` objects and return a list of server descriptions that should be considered suitable for the desired operation. - `serverSelectionTimeoutMS`: (integer) Controls how long (in milliseconds) the driver will wait to find an available, appropriate server to carry out a database operation; while it is waiting, multiple server monitoring operations may be carried out, each controlled by `connectTimeoutMS`. Defaults to ``30000`` (30 seconds). - `waitQueueTimeoutMS`: (integer or None) How long (in milliseconds) a thread will wait for a socket from the pool if the pool has no free sockets. Defaults to ``None`` (no timeout). - `heartbeatFrequencyMS`: (optional) The number of milliseconds between periodic server checks, or None to accept the default frequency of 10 seconds. - `serverMonitoringMode`: (optional) The server monitoring mode to use. Valid values are the strings: "auto", "stream", "poll". Defaults to "auto". - `appname`: (string or None) The name of the application that created this MongoClient instance. The server will log this value upon establishing each connection. It is also recorded in the slow query log and profile collections. - `driver`: (pair or None) A driver implemented on top of PyMongo can pass a :class:`~pymongo.driver_info.DriverInfo` to add its name, version, and platform to the message printed in the server log when establishing a connection. - `event_listeners`: a list or tuple of event listeners. See :mod:`~pymongo.monitoring` for details. - `retryWrites`: (boolean) Whether supported write operations executed within this MongoClient will be retried once after a network error. Defaults to ``True``. The supported write operations are: - :meth:`~pymongo.collection.Collection.bulk_write`, as long as :class:`~pymongo.operations.UpdateMany` or :class:`~pymongo.operations.DeleteMany` are not included. - :meth:`~pymongo.collection.Collection.delete_one` - :meth:`~pymongo.collection.Collection.insert_one` - :meth:`~pymongo.collection.Collection.insert_many` - :meth:`~pymongo.collection.Collection.replace_one` - :meth:`~pymongo.collection.Collection.update_one` - :meth:`~pymongo.collection.Collection.find_one_and_delete` - :meth:`~pymongo.collection.Collection.find_one_and_replace` - :meth:`~pymongo.collection.Collection.find_one_and_update` Unsupported write operations include, but are not limited to, :meth:`~pymongo.collection.Collection.aggregate` using the ``$out`` pipeline operator and any operation with an unacknowledged write concern (e.g. {w: 0})). See https://github.com/mongodb/specifications/blob/master/source/retryable-writes/retryable-writes.rst - `retryReads`: (boolean) Whether supported read operations executed within this MongoClient will be retried once after a network error. Defaults to ``True``. The supported read operations are: :meth:`~pymongo.collection.Collection.find`, :meth:`~pymongo.collection.Collection.find_one`, :meth:`~pymongo.collection.Collection.aggregate` without ``$out``, :meth:`~pymongo.collection.Collection.distinct`, :meth:`~pymongo.collection.Collection.count`, :meth:`~pymongo.collection.Collection.estimated_document_count`, :meth:`~pymongo.collection.Collection.count_documents`, :meth:`pymongo.collection.Collection.watch`, :meth:`~pymongo.collection.Collection.list_indexes`, :meth:`pymongo.database.Database.watch`, :meth:`~pymongo.database.Database.list_collections`, :meth:`pymongo.mongo_client.MongoClient.watch`, and :meth:`~pymongo.mongo_client.MongoClient.list_databases`. Unsupported read operations include, but are not limited to :meth:`~pymongo.database.Database.command` and any getMore operation on a cursor. Enabling retryable reads makes applications more resilient to transient errors such as network failures, database upgrades, and replica set failovers. For an exact definition of which errors trigger a retry, see the `retryable reads specification `_. - `compressors`: Comma separated list of compressors for wire protocol compression. The list is used to negotiate a compressor with the server. Currently supported options are "snappy", "zlib" and "zstd". Support for snappy requires the `python-snappy `_ package. zlib support requires the Python standard library zlib module. zstd requires the `zstandard `_ package. By default no compression is used. Compression support must also be enabled on the server. MongoDB 3.6+ supports snappy and zlib compression. MongoDB 4.2+ adds support for zstd. See :ref:`network-compression-example` for details. - `zlibCompressionLevel`: (int) The zlib compression level to use when zlib is used as the wire protocol compressor. Supported values are -1 through 9. -1 tells the zlib library to use its default compression level (usually 6). 0 means no compression. 1 is best speed. 9 is best compression. Defaults to -1. - `uuidRepresentation`: The BSON representation to use when encoding from and decoding to instances of :class:`~uuid.UUID`. Valid values are the strings: "standard", "pythonLegacy", "javaLegacy", "csharpLegacy", and "unspecified" (the default). New applications should consider setting this to "standard" for cross language compatibility. See :ref:`handling-uuid-data-example` for details. - `unicode_decode_error_handler`: The error handler to apply when a Unicode-related error occurs during BSON decoding that would otherwise raise :exc:`UnicodeDecodeError`. Valid options include 'strict', 'replace', 'backslashreplace', 'surrogateescape', and 'ignore'. Defaults to 'strict'. - `srvServiceName`: (string) The SRV service name to use for "mongodb+srv://" URIs. Defaults to "mongodb". Use it like so:: MongoClient("mongodb+srv://example.com/?srvServiceName=customname") - `srvMaxHosts`: (int) limits the number of mongos-like hosts a client will connect to. More specifically, when a "mongodb+srv://" connection string resolves to more than srvMaxHosts number of hosts, the client will randomly choose an srvMaxHosts sized subset of hosts. | **Write Concern options:** | (Only set if passed. No default values.) - `w`: (integer or string) If this is a replica set, write operations will block until they have been replicated to the specified number or tagged set of servers. `w=` always includes the replica set primary (e.g. w=3 means write to the primary and wait until replicated to **two** secondaries). Passing w=0 **disables write acknowledgement** and all other write concern options. - `wTimeoutMS`: **DEPRECATED** (integer) Used in conjunction with `w`. Specify a value in milliseconds to control how long to wait for write propagation to complete. If replication does not complete in the given timeframe, a timeout exception is raised. Passing wTimeoutMS=0 will cause **write operations to wait indefinitely**. - `journal`: If ``True`` block until write operations have been committed to the journal. Cannot be used in combination with `fsync`. Write operations will fail with an exception if this option is used when the server is running without journaling. - `fsync`: If ``True`` and the server is running without journaling, blocks until the server has synced all data files to disk. If the server is running with journaling, this acts the same as the `j` option, blocking until write operations have been committed to the journal. Cannot be used in combination with `j`. | **Replica set keyword arguments for connecting with a replica set - either directly or via a mongos:** - `replicaSet`: (string or None) The name of the replica set to connect to. The driver will verify that all servers it connects to match this name. Implies that the hosts specified are a seed list and the driver should attempt to find all members of the set. Defaults to ``None``. | **Read Preference:** - `readPreference`: The replica set read preference for this client. One of ``primary``, ``primaryPreferred``, ``secondary``, ``secondaryPreferred``, or ``nearest``. Defaults to ``primary``. - `readPreferenceTags`: Specifies a tag set as a comma-separated list of colon-separated key-value pairs. For example ``dc:ny,rack:1``. Defaults to ``None``. - `maxStalenessSeconds`: (integer) The maximum estimated length of time a replica set secondary can fall behind the primary in replication before it will no longer be selected for operations. Defaults to ``-1``, meaning no maximum. If maxStalenessSeconds is set, it must be a positive integer greater than or equal to 90 seconds. .. seealso:: :doc:`/examples/server_selection` | **Authentication:** - `username`: A string. - `password`: A string. Although username and password must be percent-escaped in a MongoDB URI, they must not be percent-escaped when passed as parameters. In this example, both the space and slash special characters are passed as-is:: MongoClient(username="user name", password="pass/word") - `authSource`: The database to authenticate on. Defaults to the database specified in the URI, if provided, or to "admin". - `authMechanism`: See :data:`~pymongo.auth.MECHANISMS` for options. If no mechanism is specified, PyMongo automatically SCRAM-SHA-1 when connected to MongoDB 3.6 and negotiates the mechanism to use (SCRAM-SHA-1 or SCRAM-SHA-256) when connected to MongoDB 4.0+. - `authMechanismProperties`: Used to specify authentication mechanism specific options. To specify the service name for GSSAPI authentication pass authMechanismProperties='SERVICE_NAME:'. To specify the session token for MONGODB-AWS authentication pass ``authMechanismProperties='AWS_SESSION_TOKEN:'``. .. seealso:: :doc:`/examples/authentication` | **TLS/SSL configuration:** - `tls`: (boolean) If ``True``, create the connection to the server using transport layer security. Defaults to ``False``. - `tlsInsecure`: (boolean) Specify whether TLS constraints should be relaxed as much as possible. Setting ``tlsInsecure=True`` implies ``tlsAllowInvalidCertificates=True`` and ``tlsAllowInvalidHostnames=True``. Defaults to ``False``. Think very carefully before setting this to ``True`` as it dramatically reduces the security of TLS. - `tlsAllowInvalidCertificates`: (boolean) If ``True``, continues the TLS handshake regardless of the outcome of the certificate verification process. If this is ``False``, and a value is not provided for ``tlsCAFile``, PyMongo will attempt to load system provided CA certificates. If the python version in use does not support loading system CA certificates then the ``tlsCAFile`` parameter must point to a file of CA certificates. ``tlsAllowInvalidCertificates=False`` implies ``tls=True``. Defaults to ``False``. Think very carefully before setting this to ``True`` as that could make your application vulnerable to on-path attackers. - `tlsAllowInvalidHostnames`: (boolean) If ``True``, disables TLS hostname verification. ``tlsAllowInvalidHostnames=False`` implies ``tls=True``. Defaults to ``False``. Think very carefully before setting this to ``True`` as that could make your application vulnerable to on-path attackers. - `tlsCAFile`: A file containing a single or a bundle of "certification authority" certificates, which are used to validate certificates passed from the other end of the connection. Implies ``tls=True``. Defaults to ``None``. - `tlsCertificateKeyFile`: A file containing the client certificate and private key. Implies ``tls=True``. Defaults to ``None``. - `tlsCRLFile`: A file containing a PEM or DER formatted certificate revocation list. Implies ``tls=True``. Defaults to ``None``. - `tlsCertificateKeyFilePassword`: The password or passphrase for decrypting the private key in ``tlsCertificateKeyFile``. Only necessary if the private key is encrypted. Defaults to ``None``. - `tlsDisableOCSPEndpointCheck`: (boolean) If ``True``, disables certificate revocation status checking via the OCSP responder specified on the server certificate. ``tlsDisableOCSPEndpointCheck=False`` implies ``tls=True``. Defaults to ``False``. - `ssl`: (boolean) Alias for ``tls``. | **Read Concern options:** | (If not set explicitly, this will use the server default) - `readConcernLevel`: (string) The read concern level specifies the level of isolation for read operations. For example, a read operation using a read concern level of ``majority`` will only return data that has been written to a majority of nodes. If the level is left unspecified, the server default will be used. | **Client side encryption options:** | (If not set explicitly, client side encryption will not be enabled.) - `auto_encryption_opts`: A :class:`~pymongo.encryption_options.AutoEncryptionOpts` which configures this client to automatically encrypt collection commands and automatically decrypt results. See :ref:`automatic-client-side-encryption` for an example. If a :class:`MongoClient` is configured with ``auto_encryption_opts`` and a non-None ``maxPoolSize``, a separate internal ``MongoClient`` is created if any of the following are true: - A ``key_vault_client`` is not passed to :class:`~pymongo.encryption_options.AutoEncryptionOpts` - ``bypass_auto_encrpytion=False`` is passed to :class:`~pymongo.encryption_options.AutoEncryptionOpts` | **Stable API options:** | (If not set explicitly, Stable API will not be enabled.) - `server_api`: A :class:`~pymongo.server_api.ServerApi` which configures this client to use Stable API. See :ref:`versioned-api-ref` for details. .. seealso:: The MongoDB documentation on `connections `_. .. versionchanged:: 4.5 Added the ``serverMonitoringMode`` keyword argument. .. versionchanged:: 4.2 Added the ``timeoutMS`` keyword argument. .. versionchanged:: 4.0 - Removed the fsync, unlock, is_locked, database_names, and close_cursor methods. See the :ref:`pymongo4-migration-guide`. - Removed the ``waitQueueMultiple`` and ``socketKeepAlive`` keyword arguments. - The default for `uuidRepresentation` was changed from ``pythonLegacy`` to ``unspecified``. - Added the ``srvServiceName``, ``maxConnecting``, and ``srvMaxHosts`` URI and keyword arguments. .. versionchanged:: 3.12 Added the ``server_api`` keyword argument. The following keyword arguments were deprecated: - ``ssl_certfile`` and ``ssl_keyfile`` were deprecated in favor of ``tlsCertificateKeyFile``. .. versionchanged:: 3.11 Added the following keyword arguments and URI options: - ``tlsDisableOCSPEndpointCheck`` - ``directConnection`` .. versionchanged:: 3.9 Added the ``retryReads`` keyword argument and URI option. Added the ``tlsInsecure`` keyword argument and URI option. The following keyword arguments and URI options were deprecated: - ``wTimeout`` was deprecated in favor of ``wTimeoutMS``. - ``j`` was deprecated in favor of ``journal``. - ``ssl_cert_reqs`` was deprecated in favor of ``tlsAllowInvalidCertificates``. - ``ssl_match_hostname`` was deprecated in favor of ``tlsAllowInvalidHostnames``. - ``ssl_ca_certs`` was deprecated in favor of ``tlsCAFile``. - ``ssl_certfile`` was deprecated in favor of ``tlsCertificateKeyFile``. - ``ssl_crlfile`` was deprecated in favor of ``tlsCRLFile``. - ``ssl_pem_passphrase`` was deprecated in favor of ``tlsCertificateKeyFilePassword``. .. versionchanged:: 3.9 ``retryWrites`` now defaults to ``True``. .. versionchanged:: 3.8 Added the ``server_selector`` keyword argument. Added the ``type_registry`` keyword argument. .. versionchanged:: 3.7 Added the ``driver`` keyword argument. .. versionchanged:: 3.6 Added support for mongodb+srv:// URIs. Added the ``retryWrites`` keyword argument and URI option. .. versionchanged:: 3.5 Add ``username`` and ``password`` options. Document the ``authSource``, ``authMechanism``, and ``authMechanismProperties`` options. Deprecated the ``socketKeepAlive`` keyword argument and URI option. ``socketKeepAlive`` now defaults to ``True``. .. versionchanged:: 3.0 :class:`~pymongo.mongo_client.MongoClient` is now the one and only client class for a standalone server, mongos, or replica set. It includes the functionality that had been split into :class:`~pymongo.mongo_client.MongoReplicaSetClient`: it can connect to a replica set, discover all its members, and monitor the set for stepdowns, elections, and reconfigs. The :class:`~pymongo.mongo_client.MongoClient` constructor no longer blocks while connecting to the server or servers, and it no longer raises :class:`~pymongo.errors.ConnectionFailure` if they are unavailable, nor :class:`~pymongo.errors.ConfigurationError` if the user's credentials are wrong. Instead, the constructor returns immediately and launches the connection process on background threads. Therefore the ``alive`` method is removed since it no longer provides meaningful information; even if the client is disconnected, it may discover a server in time to fulfill the next operation. In PyMongo 2.x, :class:`~pymongo.MongoClient` accepted a list of standalone MongoDB servers and used the first it could connect to:: MongoClient(['host1.com:27017', 'host2.com:27017']) A list of multiple standalones is no longer supported; if multiple servers are listed they must be members of the same replica set, or mongoses in the same sharded cluster. The behavior for a list of mongoses is changed from "high availability" to "load balancing". Before, the client connected to the lowest-latency mongos in the list, and used it until a network error prompted it to re-evaluate all mongoses' latencies and reconnect to one of them. In PyMongo 3, the client monitors its network latency to all the mongoses continuously, and distributes operations evenly among those with the lowest latency. See :ref:`mongos-load-balancing` for more information. The ``connect`` option is added. The ``start_request``, ``in_request``, and ``end_request`` methods are removed, as well as the ``auto_start_request`` option. The ``copy_database`` method is removed, see the :doc:`copy_database examples
` for alternatives. The :meth:`MongoClient.disconnect` method is removed; it was a synonym for :meth:`~pymongo.MongoClient.close`. :class:`~pymongo.mongo_client.MongoClient` no longer returns an instance of :class:`~pymongo.database.Database` for attribute names with leading underscores. You must use dict-style lookups instead:: client['__my_database__'] Not:: client.__my_database__ .. versionchanged:: 4.7 Deprecated parameter ``wTimeoutMS``, use :meth:`~pymongo.timeout`. """ doc_class = document_class or dict self.__init_kwargs: dict[str, Any] = { "host": host, "port": port, "document_class": doc_class, "tz_aware": tz_aware, "connect": connect, "type_registry": type_registry, **kwargs, } if host is None: host = self.HOST if isinstance(host, str): host = [host] if port is None: port = self.PORT if not isinstance(port, int): raise TypeError("port must be an instance of int") # _pool_class, _monitor_class, and _condition_class are for deep # customization of PyMongo, e.g. Motor. pool_class = kwargs.pop("_pool_class", None) monitor_class = kwargs.pop("_monitor_class", None) condition_class = kwargs.pop("_condition_class", None) # Parse options passed as kwargs. keyword_opts = common._CaseInsensitiveDictionary(kwargs) keyword_opts["document_class"] = doc_class seeds = set() username = None password = None dbase = None opts = common._CaseInsensitiveDictionary() fqdn = None srv_service_name = keyword_opts.get("srvservicename") srv_max_hosts = keyword_opts.get("srvmaxhosts") if len([h for h in host if "/" in h]) > 1: raise ConfigurationError("host must not contain multiple MongoDB URIs") for entity in host: # A hostname can only include a-z, 0-9, '-' and '.'. If we find a '/' # it must be a URI, # https://en.wikipedia.org/wiki/Hostname#Restrictions_on_valid_host_names if "/" in entity: # Determine connection timeout from kwargs. timeout = keyword_opts.get("connecttimeoutms") if timeout is not None: timeout = common.validate_timeout_or_none_or_zero( keyword_opts.cased_key("connecttimeoutms"), timeout ) res = uri_parser.parse_uri( entity, port, validate=True, warn=True, normalize=False, connect_timeout=timeout, srv_service_name=srv_service_name, srv_max_hosts=srv_max_hosts, ) seeds.update(res["nodelist"]) username = res["username"] or username password = res["password"] or password dbase = res["database"] or dbase opts = res["options"] fqdn = res["fqdn"] else: seeds.update(uri_parser.split_hosts(entity, port)) if not seeds: raise ConfigurationError("need to specify at least one host") for hostname in [node[0] for node in seeds]: if _detect_external_db(hostname): break # Add options with named keyword arguments to the parsed kwarg options. if type_registry is not None: keyword_opts["type_registry"] = type_registry if tz_aware is None: tz_aware = opts.get("tz_aware", False) if connect is None: connect = opts.get("connect", True) keyword_opts["tz_aware"] = tz_aware keyword_opts["connect"] = connect # Handle deprecated options in kwarg options. keyword_opts = _handle_option_deprecations(keyword_opts) # Validate kwarg options. keyword_opts = common._CaseInsensitiveDictionary( dict(common.validate(keyword_opts.cased_key(k), v) for k, v in keyword_opts.items()) ) # Override connection string options with kwarg options. opts.update(keyword_opts) if srv_service_name is None: srv_service_name = opts.get("srvServiceName", common.SRV_SERVICE_NAME) srv_max_hosts = srv_max_hosts or opts.get("srvmaxhosts") # Handle security-option conflicts in combined options. opts = _handle_security_options(opts) # Normalize combined options. opts = _normalize_options(opts) _check_options(seeds, opts) # Username and password passed as kwargs override user info in URI. username = opts.get("username", username) password = opts.get("password", password) self.__options = options = ClientOptions(username, password, dbase, opts) self.__default_database_name = dbase self.__lock = _create_lock() self.__kill_cursors_queue: list = [] self._event_listeners = options.pool_options._event_listeners super().__init__( options.codec_options, options.read_preference, options.write_concern, options.read_concern, ) self._topology_settings = TopologySettings( seeds=seeds, replica_set_name=options.replica_set_name, pool_class=pool_class, pool_options=options.pool_options, monitor_class=monitor_class, condition_class=condition_class, local_threshold_ms=options.local_threshold_ms, server_selection_timeout=options.server_selection_timeout, server_selector=options.server_selector, heartbeat_frequency=options.heartbeat_frequency, fqdn=fqdn, direct_connection=options.direct_connection, load_balanced=options.load_balanced, srv_service_name=srv_service_name, srv_max_hosts=srv_max_hosts, server_monitoring_mode=options.server_monitoring_mode, ) self._init_background() if connect: self._get_topology() self._encrypter = None if self.__options.auto_encryption_opts: from pymongo.encryption import _Encrypter self._encrypter = _Encrypter(self, self.__options.auto_encryption_opts) self._timeout = self.__options.timeout if _HAS_REGISTER_AT_FORK: # Add this client to the list of weakly referenced items. # This will be used later if we fork. MongoClient._clients[self._topology._topology_id] = self def _init_background(self, old_pid: Optional[int] = None) -> None: self._topology = Topology(self._topology_settings) # Seed the topology with the old one's pid so we can detect clients # that are opened before a fork and used after. self._topology._pid = old_pid def target() -> bool: client = self_ref() if client is None: return False # Stop the executor. MongoClient._process_periodic_tasks(client) return True executor = periodic_executor.PeriodicExecutor( interval=common.KILL_CURSOR_FREQUENCY, min_interval=common.MIN_HEARTBEAT_INTERVAL, target=target, name="pymongo_kill_cursors_thread", ) # We strongly reference the executor and it weakly references us via # this closure. When the client is freed, stop the executor soon. self_ref: Any = weakref.ref(self, executor.close) self._kill_cursors_executor = executor def _after_fork(self) -> None: """Resets topology in a child after successfully forking.""" self._init_background(self._topology._pid) def _duplicate(self, **kwargs: Any) -> MongoClient: args = self.__init_kwargs.copy() args.update(kwargs) return MongoClient(**args) def _server_property(self, attr_name: str) -> Any: """An attribute of the current server's description. If the client is not connected, this will block until a connection is established or raise ServerSelectionTimeoutError if no server is available. Not threadsafe if used multiple times in a single method, since the server may change. In such cases, store a local reference to a ServerDescription first, then use its properties. """ server = self._get_topology().select_server(writable_server_selector, _Op.TEST) return getattr(server.description, attr_name) def watch( self, pipeline: Optional[_Pipeline] = None, full_document: Optional[str] = None, resume_after: Optional[Mapping[str, Any]] = None, max_await_time_ms: Optional[int] = None, batch_size: Optional[int] = None, collation: Optional[_CollationIn] = None, start_at_operation_time: Optional[Timestamp] = None, session: Optional[client_session.ClientSession] = None, start_after: Optional[Mapping[str, Any]] = None, comment: Optional[Any] = None, full_document_before_change: Optional[str] = None, show_expanded_events: Optional[bool] = None, ) -> ChangeStream[_DocumentType]: """Watch changes on this cluster. Performs an aggregation with an implicit initial ``$changeStream`` stage and returns a :class:`~pymongo.change_stream.ClusterChangeStream` cursor which iterates over changes on all databases on this cluster. Introduced in MongoDB 4.0. .. code-block:: python with client.watch() as stream: for change in stream: print(change) The :class:`~pymongo.change_stream.ClusterChangeStream` iterable blocks until the next change document is returned or an error is raised. If the :meth:`~pymongo.change_stream.ClusterChangeStream.next` method encounters a network error when retrieving a batch from the server, it will automatically attempt to recreate the cursor such that no change events are missed. Any error encountered during the resume attempt indicates there may be an outage and will be raised. .. code-block:: python try: with client.watch([{"$match": {"operationType": "insert"}}]) as stream: for insert_change in stream: print(insert_change) except pymongo.errors.PyMongoError: # The ChangeStream encountered an unrecoverable error or the # resume attempt failed to recreate the cursor. logging.error("...") For a precise description of the resume process see the `change streams specification`_. :param pipeline: A list of aggregation pipeline stages to append to an initial ``$changeStream`` stage. Not all pipeline stages are valid after a ``$changeStream`` stage, see the MongoDB documentation on change streams for the supported stages. :param full_document: The fullDocument to pass as an option to the ``$changeStream`` stage. Allowed values: 'updateLookup', 'whenAvailable', 'required'. When set to 'updateLookup', the change notification for partial updates will include both a delta describing the changes to the document, as well as a copy of the entire document that was changed from some time after the change occurred. :param full_document_before_change: Allowed values: 'whenAvailable' and 'required'. Change events may now result in a 'fullDocumentBeforeChange' response field. :param resume_after: A resume token. If provided, the change stream will start returning changes that occur directly after the operation specified in the resume token. A resume token is the _id value of a change document. :param max_await_time_ms: The maximum time in milliseconds for the server to wait for changes before responding to a getMore operation. :param batch_size: The maximum number of documents to return per batch. :param collation: The :class:`~pymongo.collation.Collation` to use for the aggregation. :param start_at_operation_time: If provided, the resulting change stream will only return changes that occurred at or after the specified :class:`~bson.timestamp.Timestamp`. Requires MongoDB >= 4.0. :param session: a :class:`~pymongo.client_session.ClientSession`. :param start_after: The same as `resume_after` except that `start_after` can resume notifications after an invalidate event. This option and `resume_after` are mutually exclusive. :param comment: A user-provided comment to attach to this command. :param show_expanded_events: Include expanded events such as DDL events like `dropIndexes`. :return: A :class:`~pymongo.change_stream.ClusterChangeStream` cursor. .. versionchanged:: 4.3 Added `show_expanded_events` parameter. .. versionchanged:: 4.2 Added ``full_document_before_change`` parameter. .. versionchanged:: 4.1 Added ``comment`` parameter. .. versionchanged:: 3.9 Added the ``start_after`` parameter. .. versionadded:: 3.7 .. seealso:: The MongoDB documentation on `changeStreams `_. .. _change streams specification: https://github.com/mongodb/specifications/blob/master/source/change-streams/change-streams.md """ return ClusterChangeStream( self.admin, pipeline, full_document, resume_after, max_await_time_ms, batch_size, collation, start_at_operation_time, session, start_after, comment, full_document_before_change, show_expanded_events=show_expanded_events, ) @property def topology_description(self) -> TopologyDescription: """The description of the connected MongoDB deployment. >>> client.topology_description , , ]> >>> client.topology_description.topology_type_name 'ReplicaSetWithPrimary' Note that the description is periodically updated in the background but the returned object itself is immutable. Access this property again to get a more recent :class:`~pymongo.topology_description.TopologyDescription`. :return: An instance of :class:`~pymongo.topology_description.TopologyDescription`. .. versionadded:: 4.0 """ return self._topology.description @property def address(self) -> Optional[tuple[str, int]]: """(host, port) of the current standalone, primary, or mongos, or None. Accessing :attr:`address` raises :exc:`~.errors.InvalidOperation` if the client is load-balancing among mongoses, since there is no single address. Use :attr:`nodes` instead. If the client is not connected, this will block until a connection is established or raise ServerSelectionTimeoutError if no server is available. .. versionadded:: 3.0 """ topology_type = self._topology._description.topology_type if ( topology_type == TOPOLOGY_TYPE.Sharded and len(self.topology_description.server_descriptions()) > 1 ): raise InvalidOperation( 'Cannot use "address" property when load balancing among' ' mongoses, use "nodes" instead.' ) if topology_type not in ( TOPOLOGY_TYPE.ReplicaSetWithPrimary, TOPOLOGY_TYPE.Single, TOPOLOGY_TYPE.LoadBalanced, TOPOLOGY_TYPE.Sharded, ): return None return self._server_property("address") @property def primary(self) -> Optional[tuple[str, int]]: """The (host, port) of the current primary of the replica set. Returns ``None`` if this client is not connected to a replica set, there is no primary, or this client was created without the `replicaSet` option. .. versionadded:: 3.0 MongoClient gained this property in version 3.0. """ return self._topology.get_primary() # type: ignore[return-value] @property def secondaries(self) -> set[_Address]: """The secondary members known to this client. A sequence of (host, port) pairs. Empty if this client is not connected to a replica set, there are no visible secondaries, or this client was created without the `replicaSet` option. .. versionadded:: 3.0 MongoClient gained this property in version 3.0. """ return self._topology.get_secondaries() @property def arbiters(self) -> set[_Address]: """Arbiters in the replica set. A sequence of (host, port) pairs. Empty if this client is not connected to a replica set, there are no arbiters, or this client was created without the `replicaSet` option. """ return self._topology.get_arbiters() @property def is_primary(self) -> bool: """If this client is connected to a server that can accept writes. True if the current server is a standalone, mongos, or the primary of a replica set. If the client is not connected, this will block until a connection is established or raise ServerSelectionTimeoutError if no server is available. """ return self._server_property("is_writable") @property def is_mongos(self) -> bool: """If this client is connected to mongos. If the client is not connected, this will block until a connection is established or raise ServerSelectionTimeoutError if no server is available. """ return self._server_property("server_type") == SERVER_TYPE.Mongos @property def nodes(self) -> FrozenSet[_Address]: """Set of all currently connected servers. .. warning:: When connected to a replica set the value of :attr:`nodes` can change over time as :class:`MongoClient`'s view of the replica set changes. :attr:`nodes` can also be an empty set when :class:`MongoClient` is first instantiated and hasn't yet connected to any servers, or a network partition causes it to lose connection to all servers. """ description = self._topology.description return frozenset(s.address for s in description.known_servers) @property def options(self) -> ClientOptions: """The configuration options for this client. :return: An instance of :class:`~pymongo.client_options.ClientOptions`. .. versionadded:: 4.0 """ return self.__options def _end_sessions(self, session_ids: list[_ServerSession]) -> None: """Send endSessions command(s) with the given session ids.""" try: # Use Connection.command directly to avoid implicitly creating # another session. with self._conn_for_reads( ReadPreference.PRIMARY_PREFERRED, None, operation=_Op.END_SESSIONS ) as ( conn, read_pref, ): if not conn.supports_sessions: return for i in range(0, len(session_ids), common._MAX_END_SESSIONS): spec = {"endSessions": session_ids[i : i + common._MAX_END_SESSIONS]} conn.command("admin", spec, read_preference=read_pref, client=self) except PyMongoError: # Drivers MUST ignore any errors returned by the endSessions # command. pass def close(self) -> None: """Cleanup client resources and disconnect from MongoDB. End all server sessions created by this client by sending one or more endSessions commands. Close all sockets in the connection pools and stop the monitor threads. .. versionchanged:: 4.0 Once closed, the client cannot be used again and any attempt will raise :exc:`~pymongo.errors.InvalidOperation`. .. versionchanged:: 3.6 End all server sessions created by this client. """ session_ids = self._topology.pop_all_sessions() if session_ids: self._end_sessions(session_ids) # Stop the periodic task thread and then send pending killCursor # requests before closing the topology. self._kill_cursors_executor.close() self._process_kill_cursors() self._topology.close() if self._encrypter: # TODO: PYTHON-1921 Encrypted MongoClients cannot be re-opened. self._encrypter.close() def _get_topology(self) -> Topology: """Get the internal :class:`~pymongo.topology.Topology` object. If this client was created with "connect=False", calling _get_topology launches the connection process in the background. """ self._topology.open() with self.__lock: self._kill_cursors_executor.open() return self._topology @contextlib.contextmanager def _checkout(self, server: Server, session: Optional[ClientSession]) -> Iterator[Connection]: in_txn = session and session.in_transaction with _MongoClientErrorHandler(self, server, session) as err_handler: # Reuse the pinned connection, if it exists. if in_txn and session and session._pinned_connection: err_handler.contribute_socket(session._pinned_connection) yield session._pinned_connection return with server.checkout(handler=err_handler) as conn: # Pin this session to the selected server or connection. if ( in_txn and session and server.description.server_type in ( SERVER_TYPE.Mongos, SERVER_TYPE.LoadBalancer, ) ): session._pin(server, conn) err_handler.contribute_socket(conn) if ( self._encrypter and not self._encrypter._bypass_auto_encryption and conn.max_wire_version < 8 ): raise ConfigurationError( "Auto-encryption requires a minimum MongoDB version of 4.2" ) yield conn def _select_server( self, server_selector: Callable[[Selection], Selection], session: Optional[ClientSession], operation: str, address: Optional[_Address] = None, deprioritized_servers: Optional[list[Server]] = None, operation_id: Optional[int] = None, ) -> Server: """Select a server to run an operation on this client. :param server_selector: The server selector to use if the session is not pinned and no address is given. :param session: The ClientSession for the next operation, or None. May be pinned to a mongos server address. :param operation: The name of the operation that the server is being selected for. :param address: Address when sending a message to a specific server, used for getMore. """ try: topology = self._get_topology() if session and not session.in_transaction: session._transaction.reset() if not address and session: address = session._pinned_address if address: # We're running a getMore or this session is pinned to a mongos. server = topology.select_server_by_address( address, operation, operation_id=operation_id ) if not server: raise AutoReconnect("server %s:%s no longer available" % address) # noqa: UP031 else: server = topology.select_server( server_selector, operation, deprioritized_servers=deprioritized_servers, operation_id=operation_id, ) return server except PyMongoError as exc: # Server selection errors in a transaction are transient. if session and session.in_transaction: exc._add_error_label("TransientTransactionError") session._unpin() raise def _conn_for_writes( self, session: Optional[ClientSession], operation: str ) -> ContextManager[Connection]: server = self._select_server(writable_server_selector, session, operation) return self._checkout(server, session) @contextlib.contextmanager def _conn_from_server( self, read_preference: _ServerMode, server: Server, session: Optional[ClientSession] ) -> Iterator[tuple[Connection, _ServerMode]]: assert read_preference is not None, "read_preference must not be None" # Get a connection for a server matching the read preference, and yield # conn with the effective read preference. The Server Selection # Spec says not to send any $readPreference to standalones and to # always send primaryPreferred when directly connected to a repl set # member. # Thread safe: if the type is single it cannot change. # NOTE: We already opened the Topology when selecting a server so there's no need # to call _get_topology() again. single = self._topology.description.topology_type == TOPOLOGY_TYPE.Single with self._checkout(server, session) as conn: if single: if conn.is_repl and not (session and session.in_transaction): # Use primary preferred to ensure any repl set member # can handle the request. read_preference = ReadPreference.PRIMARY_PREFERRED elif conn.is_standalone: # Don't send read preference to standalones. read_preference = ReadPreference.PRIMARY yield conn, read_preference def _conn_for_reads( self, read_preference: _ServerMode, session: Optional[ClientSession], operation: str, ) -> ContextManager[tuple[Connection, _ServerMode]]: assert read_preference is not None, "read_preference must not be None" server = self._select_server(read_preference, session, operation) return self._conn_from_server(read_preference, server, session) def _should_pin_cursor(self, session: Optional[ClientSession]) -> Optional[bool]: return self.__options.load_balanced and not (session and session.in_transaction) @_csot.apply def _run_operation( self, operation: Union[_Query, _GetMore], unpack_res: Callable, address: Optional[_Address] = None, ) -> Response: """Run a _Query/_GetMore operation and return a Response. :param operation: a _Query or _GetMore object. :param unpack_res: A callable that decodes the wire protocol response. :param address: Optional address when sending a message to a specific server, used for getMore. """ if operation.conn_mgr: server = self._select_server( operation.read_preference, operation.session, operation.name, address=address, ) with operation.conn_mgr.lock: with _MongoClientErrorHandler(self, server, operation.session) as err_handler: err_handler.contribute_socket(operation.conn_mgr.conn) return server.run_operation( operation.conn_mgr.conn, operation, operation.read_preference, self._event_listeners, unpack_res, self, ) def _cmd( _session: Optional[ClientSession], server: Server, conn: Connection, read_preference: _ServerMode, ) -> Response: operation.reset() # Reset op in case of retry. return server.run_operation( conn, operation, read_preference, self._event_listeners, unpack_res, self, ) return self._retryable_read( _cmd, operation.read_preference, operation.session, address=address, retryable=isinstance(operation, message._Query), operation=operation.name, ) def _retry_with_session( self, retryable: bool, func: _WriteCall[T], session: Optional[ClientSession], bulk: Optional[_Bulk], operation: str, operation_id: Optional[int] = None, ) -> T: """Execute an operation with at most one consecutive retries Returns func()'s return value on success. On error retries the same command. Re-raises any exception thrown by func(). """ # Ensure that the options supports retry_writes and there is a valid session not in # transaction, otherwise, we will not support retry behavior for this txn. retryable = bool( retryable and self.options.retry_writes and session and not session.in_transaction ) return self._retry_internal( func=func, session=session, bulk=bulk, operation=operation, retryable=retryable, operation_id=operation_id, ) @_csot.apply def _retry_internal( self, func: _WriteCall[T] | _ReadCall[T], session: Optional[ClientSession], bulk: Optional[_Bulk], operation: str, is_read: bool = False, address: Optional[_Address] = None, read_pref: Optional[_ServerMode] = None, retryable: bool = False, operation_id: Optional[int] = None, ) -> T: """Internal retryable helper for all client transactions. :param func: Callback function we want to retry :param session: Client Session on which the transaction should occur :param bulk: Abstraction to handle bulk write operations :param operation: The name of the operation that the server is being selected for :param is_read: If this is an exclusive read transaction, defaults to False :param address: Server Address, defaults to None :param read_pref: Topology of read operation, defaults to None :param retryable: If the operation should be retried once, defaults to None :return: Output of the calling func() """ return _ClientConnectionRetryable( mongo_client=self, func=func, bulk=bulk, operation=operation, is_read=is_read, session=session, read_pref=read_pref, address=address, retryable=retryable, operation_id=operation_id, ).run() def _retryable_read( self, func: _ReadCall[T], read_pref: _ServerMode, session: Optional[ClientSession], operation: str, address: Optional[_Address] = None, retryable: bool = True, operation_id: Optional[int] = None, ) -> T: """Execute an operation with consecutive retries if possible Returns func()'s return value on success. On error retries the same command. Re-raises any exception thrown by func(). :param func: Read call we want to execute :param read_pref: Desired topology of read operation :param session: Client session we should use to execute operation :param operation: The name of the operation that the server is being selected for :param address: Optional address when sending a message, defaults to None :param retryable: if we should attempt retries (may not always be supported even if supplied), defaults to False """ # Ensure that the client supports retrying on reads and there is no session in # transaction, otherwise, we will not support retry behavior for this call. retryable = bool( retryable and self.options.retry_reads and not (session and session.in_transaction) ) return self._retry_internal( func, session, None, operation, is_read=True, address=address, read_pref=read_pref, retryable=retryable, operation_id=operation_id, ) def _retryable_write( self, retryable: bool, func: _WriteCall[T], session: Optional[ClientSession], operation: str, bulk: Optional[_Bulk] = None, operation_id: Optional[int] = None, ) -> T: """Execute an operation with consecutive retries if possible Returns func()'s return value on success. On error retries the same command. Re-raises any exception thrown by func(). :param retryable: if we should attempt retries (may not always be supported) :param func: write call we want to execute during a session :param session: Client session we will use to execute write operation :param operation: The name of the operation that the server is being selected for :param bulk: bulk abstraction to execute operations in bulk, defaults to None """ with self._tmp_session(session) as s: return self._retry_with_session(retryable, func, s, bulk, operation, operation_id) def __eq__(self, other: Any) -> bool: if isinstance(other, self.__class__): return self._topology == other._topology return NotImplemented def __ne__(self, other: Any) -> bool: return not self == other def __hash__(self) -> int: return hash(self._topology) def _repr_helper(self) -> str: def option_repr(option: str, value: Any) -> str: """Fix options whose __repr__ isn't usable in a constructor.""" if option == "document_class": if value is dict: return "document_class=dict" else: return f"document_class={value.__module__}.{value.__name__}" if option in common.TIMEOUT_OPTIONS and value is not None: return f"{option}={int(value * 1000)}" return f"{option}={value!r}" # Host first... options = [ "host=%r" % [ "%s:%d" % (host, port) if port is not None else host for host, port in self._topology_settings.seeds ] ] # ... then everything in self._constructor_args... options.extend( option_repr(key, self.__options._options[key]) for key in self._constructor_args ) # ... then everything else. options.extend( option_repr(key, self.__options._options[key]) for key in self.__options._options if key not in set(self._constructor_args) and key != "username" and key != "password" ) return ", ".join(options) def __repr__(self) -> str: return f"MongoClient({self._repr_helper()})" def __getattr__(self, name: str) -> database.Database[_DocumentType]: """Get a database by name. Raises :class:`~pymongo.errors.InvalidName` if an invalid database name is used. :param name: the name of the database to get """ if name.startswith("_"): raise AttributeError( f"MongoClient has no attribute {name!r}. To access the {name}" f" database, use client[{name!r}]." ) return self.__getitem__(name) def __getitem__(self, name: str) -> database.Database[_DocumentType]: """Get a database by name. Raises :class:`~pymongo.errors.InvalidName` if an invalid database name is used. :param name: the name of the database to get """ return database.Database(self, name) def _cleanup_cursor( self, locks_allowed: bool, cursor_id: int, address: Optional[_CursorAddress], conn_mgr: _ConnectionManager, session: Optional[ClientSession], explicit_session: bool, ) -> None: """Cleanup a cursor from cursor.close() or __del__. This method handles cleanup for Cursors/CommandCursors including any pinned connection or implicit session attached at the time the cursor was closed or garbage collected. :param locks_allowed: True if we are allowed to acquire locks. :param cursor_id: The cursor id which may be 0. :param address: The _CursorAddress. :param conn_mgr: The _ConnectionManager for the pinned connection or None. :param session: The cursor's session. :param explicit_session: True if the session was passed explicitly. """ if locks_allowed: if cursor_id: if conn_mgr and conn_mgr.more_to_come: # If this is an exhaust cursor and we haven't completely # exhausted the result set we *must* close the socket # to stop the server from sending more data. assert conn_mgr.conn is not None conn_mgr.conn.close_conn(ConnectionClosedReason.ERROR) else: self._close_cursor_now(cursor_id, address, session=session, conn_mgr=conn_mgr) if conn_mgr: conn_mgr.close() else: # The cursor will be closed later in a different session. if cursor_id or conn_mgr: self._close_cursor_soon(cursor_id, address, conn_mgr) if session and not explicit_session: session._end_session(lock=locks_allowed) def _close_cursor_soon( self, cursor_id: int, address: Optional[_CursorAddress], conn_mgr: Optional[_ConnectionManager] = None, ) -> None: """Request that a cursor and/or connection be cleaned up soon.""" self.__kill_cursors_queue.append((address, cursor_id, conn_mgr)) def _close_cursor_now( self, cursor_id: int, address: Optional[_CursorAddress], session: Optional[ClientSession] = None, conn_mgr: Optional[_ConnectionManager] = None, ) -> None: """Send a kill cursors message with the given id. The cursor is closed synchronously on the current thread. """ if not isinstance(cursor_id, int): raise TypeError("cursor_id must be an instance of int") try: if conn_mgr: with conn_mgr.lock: # Cursor is pinned to LB outside of a transaction. assert address is not None assert conn_mgr.conn is not None self._kill_cursor_impl([cursor_id], address, session, conn_mgr.conn) else: self._kill_cursors([cursor_id], address, self._get_topology(), session) except PyMongoError: # Make another attempt to kill the cursor later. self._close_cursor_soon(cursor_id, address) def _kill_cursors( self, cursor_ids: Sequence[int], address: Optional[_CursorAddress], topology: Topology, session: Optional[ClientSession], ) -> None: """Send a kill cursors message with the given ids.""" if address: # address could be a tuple or _CursorAddress, but # select_server_by_address needs (host, port). server = topology.select_server_by_address(tuple(address), _Op.KILL_CURSORS) # type: ignore[arg-type] else: # Application called close_cursor() with no address. server = topology.select_server(writable_server_selector, _Op.KILL_CURSORS) with self._checkout(server, session) as conn: assert address is not None self._kill_cursor_impl(cursor_ids, address, session, conn) def _kill_cursor_impl( self, cursor_ids: Sequence[int], address: _CursorAddress, session: Optional[ClientSession], conn: Connection, ) -> None: namespace = address.namespace db, coll = namespace.split(".", 1) spec = {"killCursors": coll, "cursors": cursor_ids} conn.command(db, spec, session=session, client=self) def _process_kill_cursors(self) -> None: """Process any pending kill cursors requests.""" address_to_cursor_ids = defaultdict(list) pinned_cursors = [] # Other threads or the GC may append to the queue concurrently. while True: try: address, cursor_id, conn_mgr = self.__kill_cursors_queue.pop() except IndexError: break if conn_mgr: pinned_cursors.append((address, cursor_id, conn_mgr)) else: address_to_cursor_ids[address].append(cursor_id) for address, cursor_id, conn_mgr in pinned_cursors: try: self._cleanup_cursor(True, cursor_id, address, conn_mgr, None, False) except Exception as exc: if isinstance(exc, InvalidOperation) and self._topology._closed: # Raise the exception when client is closed so that it # can be caught in _process_periodic_tasks raise else: helpers._handle_exception() # Don't re-open topology if it's closed and there's no pending cursors. if address_to_cursor_ids: topology = self._get_topology() for address, cursor_ids in address_to_cursor_ids.items(): try: self._kill_cursors(cursor_ids, address, topology, session=None) except Exception as exc: if isinstance(exc, InvalidOperation) and self._topology._closed: raise else: helpers._handle_exception() # This method is run periodically by a background thread. def _process_periodic_tasks(self) -> None: """Process any pending kill cursors requests and maintain connection pool parameters. """ try: self._process_kill_cursors() self._topology.update_pool() except Exception as exc: if isinstance(exc, InvalidOperation) and self._topology._closed: return else: helpers._handle_exception() def __start_session(self, implicit: bool, **kwargs: Any) -> ClientSession: server_session = _EmptyServerSession() opts = client_session.SessionOptions(**kwargs) return client_session.ClientSession(self, server_session, opts, implicit) def start_session( self, causal_consistency: Optional[bool] = None, default_transaction_options: Optional[client_session.TransactionOptions] = None, snapshot: Optional[bool] = False, ) -> client_session.ClientSession: """Start a logical session. This method takes the same parameters as :class:`~pymongo.client_session.SessionOptions`. See the :mod:`~pymongo.client_session` module for details and examples. A :class:`~pymongo.client_session.ClientSession` may only be used with the MongoClient that started it. :class:`ClientSession` instances are **not thread-safe or fork-safe**. They can only be used by one thread or process at a time. A single :class:`ClientSession` cannot be used to run multiple operations concurrently. :return: An instance of :class:`~pymongo.client_session.ClientSession`. .. versionadded:: 3.6 """ return self.__start_session( False, causal_consistency=causal_consistency, default_transaction_options=default_transaction_options, snapshot=snapshot, ) def _return_server_session( self, server_session: Union[_ServerSession, _EmptyServerSession], lock: bool ) -> None: """Internal: return a _ServerSession to the pool.""" if isinstance(server_session, _EmptyServerSession): return None return self._topology.return_server_session(server_session, lock) def _ensure_session(self, session: Optional[ClientSession] = None) -> Optional[ClientSession]: """If provided session is None, lend a temporary session.""" if session: return session try: # Don't make implicit sessions causally consistent. Applications # should always opt-in. return self.__start_session(True, causal_consistency=False) except (ConfigurationError, InvalidOperation): # Sessions not supported. return None @contextlib.contextmanager def _tmp_session( self, session: Optional[client_session.ClientSession], close: bool = True ) -> Generator[Optional[client_session.ClientSession], None, None]: """If provided session is None, lend a temporary session.""" if session is not None: if not isinstance(session, client_session.ClientSession): raise ValueError("'session' argument must be a ClientSession or None.") # Don't call end_session. yield session return s = self._ensure_session(session) if s: try: yield s except Exception as exc: if isinstance(exc, ConnectionFailure): s._server_session.mark_dirty() # Always call end_session on error. s.end_session() raise finally: # Call end_session when we exit this scope. if close: s.end_session() else: yield None def _send_cluster_time( self, command: MutableMapping[str, Any], session: Optional[ClientSession] ) -> None: topology_time = self._topology.max_cluster_time() session_time = session.cluster_time if session else None if topology_time and session_time: if topology_time["clusterTime"] > session_time["clusterTime"]: cluster_time: Optional[ClusterTime] = topology_time else: cluster_time = session_time else: cluster_time = topology_time or session_time if cluster_time: command["$clusterTime"] = cluster_time def _process_response(self, reply: Mapping[str, Any], session: Optional[ClientSession]) -> None: self._topology.receive_cluster_time(reply.get("$clusterTime")) if session is not None: session._process_response(reply) def server_info(self, session: Optional[client_session.ClientSession] = None) -> dict[str, Any]: """Get information about the MongoDB server we're connected to. :param session: a :class:`~pymongo.client_session.ClientSession`. .. versionchanged:: 3.6 Added ``session`` parameter. """ return cast( dict, self.admin.command( "buildinfo", read_preference=ReadPreference.PRIMARY, session=session ), ) def list_databases( self, session: Optional[client_session.ClientSession] = None, comment: Optional[Any] = None, **kwargs: Any, ) -> CommandCursor[dict[str, Any]]: """Get a cursor over the databases of the connected server. :param session: a :class:`~pymongo.client_session.ClientSession`. :param comment: A user-provided comment to attach to this command. :param kwargs: Optional parameters of the `listDatabases command `_ can be passed as keyword arguments to this method. The supported options differ by server version. :return: An instance of :class:`~pymongo.command_cursor.CommandCursor`. .. versionadded:: 3.6 """ cmd = {"listDatabases": 1} cmd.update(kwargs) if comment is not None: cmd["comment"] = comment admin = self._database_default_options("admin") res = admin._retryable_read_command(cmd, session=session, operation=_Op.LIST_DATABASES) # listDatabases doesn't return a cursor (yet). Fake one. cursor = { "id": 0, "firstBatch": res["databases"], "ns": "admin.$cmd", } return CommandCursor(admin["$cmd"], cursor, None, comment=comment) def list_database_names( self, session: Optional[client_session.ClientSession] = None, comment: Optional[Any] = None, ) -> list[str]: """Get a list of the names of all databases on the connected server. :param session: a :class:`~pymongo.client_session.ClientSession`. :param comment: A user-provided comment to attach to this command. .. versionchanged:: 4.1 Added ``comment`` parameter. .. versionadded:: 3.6 """ return [doc["name"] for doc in self.list_databases(session, nameOnly=True, comment=comment)] @_csot.apply def drop_database( self, name_or_database: Union[str, database.Database[_DocumentTypeArg]], session: Optional[client_session.ClientSession] = None, comment: Optional[Any] = None, ) -> None: """Drop a database. Raises :class:`TypeError` if `name_or_database` is not an instance of :class:`str` or :class:`~pymongo.database.Database`. :param name_or_database: the name of a database to drop, or a :class:`~pymongo.database.Database` instance representing the database to drop :param session: a :class:`~pymongo.client_session.ClientSession`. :param comment: A user-provided comment to attach to this command. .. versionchanged:: 4.1 Added ``comment`` parameter. .. versionchanged:: 3.6 Added ``session`` parameter. .. note:: The :attr:`~pymongo.mongo_client.MongoClient.write_concern` of this client is automatically applied to this operation. .. versionchanged:: 3.4 Apply this client's write concern automatically to this operation when connected to MongoDB >= 3.4. """ name = name_or_database if isinstance(name, database.Database): name = name.name if not isinstance(name, str): raise TypeError("name_or_database must be an instance of str or a Database") with self._conn_for_writes(session, operation=_Op.DROP_DATABASE) as conn: self[name]._command( conn, {"dropDatabase": 1, "comment": comment}, read_preference=ReadPreference.PRIMARY, write_concern=self._write_concern_for(session), parse_write_concern_error=True, session=session, ) def get_default_database( self, default: Optional[str] = None, codec_options: Optional[CodecOptions[_DocumentTypeArg]] = None, read_preference: Optional[_ServerMode] = None, write_concern: Optional[WriteConcern] = None, read_concern: Optional[ReadConcern] = None, ) -> database.Database[_DocumentType]: """Get the database named in the MongoDB connection URI. >>> uri = 'mongodb://host/my_database' >>> client = MongoClient(uri) >>> db = client.get_default_database() >>> assert db.name == 'my_database' >>> db = client.get_database() >>> assert db.name == 'my_database' Useful in scripts where you want to choose which database to use based only on the URI in a configuration file. :param default: the database name to use if no database name was provided in the URI. :param codec_options: An instance of :class:`~bson.codec_options.CodecOptions`. If ``None`` (the default) the :attr:`codec_options` of this :class:`MongoClient` is used. :param read_preference: The read preference to use. If ``None`` (the default) the :attr:`read_preference` of this :class:`MongoClient` is used. See :mod:`~pymongo.read_preferences` for options. :param write_concern: An instance of :class:`~pymongo.write_concern.WriteConcern`. If ``None`` (the default) the :attr:`write_concern` of this :class:`MongoClient` is used. :param read_concern: An instance of :class:`~pymongo.read_concern.ReadConcern`. If ``None`` (the default) the :attr:`read_concern` of this :class:`MongoClient` is used. :param comment: A user-provided comment to attach to this command. .. versionchanged:: 4.1 Added ``comment`` parameter. .. versionchanged:: 3.8 Undeprecated. Added the ``default``, ``codec_options``, ``read_preference``, ``write_concern`` and ``read_concern`` parameters. .. versionchanged:: 3.5 Deprecated, use :meth:`get_database` instead. """ if self.__default_database_name is None and default is None: raise ConfigurationError("No default database name defined or provided.") name = cast(str, self.__default_database_name or default) return database.Database( self, name, codec_options, read_preference, write_concern, read_concern ) def get_database( self, name: Optional[str] = None, codec_options: Optional[CodecOptions[_DocumentTypeArg]] = None, read_preference: Optional[_ServerMode] = None, write_concern: Optional[WriteConcern] = None, read_concern: Optional[ReadConcern] = None, ) -> database.Database[_DocumentType]: """Get a :class:`~pymongo.database.Database` with the given name and options. Useful for creating a :class:`~pymongo.database.Database` with different codec options, read preference, and/or write concern from this :class:`MongoClient`. >>> client.read_preference Primary() >>> db1 = client.test >>> db1.read_preference Primary() >>> from pymongo import ReadPreference >>> db2 = client.get_database( ... 'test', read_preference=ReadPreference.SECONDARY) >>> db2.read_preference Secondary(tag_sets=None) :param name: The name of the database - a string. If ``None`` (the default) the database named in the MongoDB connection URI is returned. :param codec_options: An instance of :class:`~bson.codec_options.CodecOptions`. If ``None`` (the default) the :attr:`codec_options` of this :class:`MongoClient` is used. :param read_preference: The read preference to use. If ``None`` (the default) the :attr:`read_preference` of this :class:`MongoClient` is used. See :mod:`~pymongo.read_preferences` for options. :param write_concern: An instance of :class:`~pymongo.write_concern.WriteConcern`. If ``None`` (the default) the :attr:`write_concern` of this :class:`MongoClient` is used. :param read_concern: An instance of :class:`~pymongo.read_concern.ReadConcern`. If ``None`` (the default) the :attr:`read_concern` of this :class:`MongoClient` is used. .. versionchanged:: 3.5 The `name` parameter is now optional, defaulting to the database named in the MongoDB connection URI. """ if name is None: if self.__default_database_name is None: raise ConfigurationError("No default database defined") name = self.__default_database_name return database.Database( self, name, codec_options, read_preference, write_concern, read_concern ) def _database_default_options(self, name: str) -> Database: """Get a Database instance with the default settings.""" return self.get_database( name, codec_options=DEFAULT_CODEC_OPTIONS, read_preference=ReadPreference.PRIMARY, write_concern=DEFAULT_WRITE_CONCERN, ) def __enter__(self) -> MongoClient[_DocumentType]: return self def __exit__(self, exc_type: Any, exc_val: Any, exc_tb: Any) -> None: self.close() # See PYTHON-3084. __iter__ = None def __next__(self) -> NoReturn: raise TypeError("'MongoClient' object is not iterable") next = __next__ def _retryable_error_doc(exc: PyMongoError) -> Optional[Mapping[str, Any]]: """Return the server response from PyMongo exception or None.""" if isinstance(exc, BulkWriteError): # Check the last writeConcernError to determine if this # BulkWriteError is retryable. wces = exc.details["writeConcernErrors"] return wces[-1] if wces else None if isinstance(exc, (NotPrimaryError, OperationFailure)): return cast(Mapping[str, Any], exc.details) return None def _add_retryable_write_error(exc: PyMongoError, max_wire_version: int, is_mongos: bool) -> None: doc = _retryable_error_doc(exc) if doc: code = doc.get("code", 0) # retryWrites on MMAPv1 should raise an actionable error. if code == 20 and str(exc).startswith("Transaction numbers"): errmsg = ( "This MongoDB deployment does not support " "retryable writes. Please add retryWrites=false " "to your connection string." ) raise OperationFailure(errmsg, code, exc.details) # type: ignore[attr-defined] if max_wire_version >= 9: # In MongoDB 4.4+, the server reports the error labels. for label in doc.get("errorLabels", []): exc._add_error_label(label) else: # Do not consult writeConcernError for pre-4.4 mongos. if isinstance(exc, WriteConcernError) and is_mongos: pass elif code in helpers._RETRYABLE_ERROR_CODES: exc._add_error_label("RetryableWriteError") # Connection errors are always retryable except NotPrimaryError and WaitQueueTimeoutError which is # handled above. if isinstance(exc, ConnectionFailure) and not isinstance( exc, (NotPrimaryError, WaitQueueTimeoutError) ): exc._add_error_label("RetryableWriteError") class _MongoClientErrorHandler: """Handle errors raised when executing an operation.""" __slots__ = ( "client", "server_address", "session", "max_wire_version", "sock_generation", "completed_handshake", "service_id", "handled", ) def __init__(self, client: MongoClient, server: Server, session: Optional[ClientSession]): self.client = client self.server_address = server.description.address self.session = session self.max_wire_version = common.MIN_WIRE_VERSION # XXX: When get_socket fails, this generation could be out of date: # "Note that when a network error occurs before the handshake # completes then the error's generation number is the generation # of the pool at the time the connection attempt was started." self.sock_generation = server.pool.gen.get_overall() self.completed_handshake = False self.service_id: Optional[ObjectId] = None self.handled = False def contribute_socket(self, conn: Connection, completed_handshake: bool = True) -> None: """Provide socket information to the error handler.""" self.max_wire_version = conn.max_wire_version self.sock_generation = conn.generation self.service_id = conn.service_id self.completed_handshake = completed_handshake def handle( self, exc_type: Optional[Type[BaseException]], exc_val: Optional[BaseException] ) -> None: if self.handled or exc_val is None: return self.handled = True if self.session: if isinstance(exc_val, ConnectionFailure): if self.session.in_transaction: exc_val._add_error_label("TransientTransactionError") self.session._server_session.mark_dirty() if isinstance(exc_val, PyMongoError): if exc_val.has_error_label("TransientTransactionError") or exc_val.has_error_label( "RetryableWriteError" ): self.session._unpin() err_ctx = _ErrorContext( exc_val, self.max_wire_version, self.sock_generation, self.completed_handshake, self.service_id, ) self.client._topology.handle_error(self.server_address, err_ctx) def __enter__(self) -> _MongoClientErrorHandler: return self def __exit__( self, exc_type: Optional[Type[Exception]], exc_val: Optional[Exception], exc_tb: Optional[TracebackType], ) -> None: return self.handle(exc_type, exc_val) class _ClientConnectionRetryable(Generic[T]): """Responsible for executing retryable connections on read or write operations""" def __init__( self, mongo_client: MongoClient, func: _WriteCall[T] | _ReadCall[T], bulk: Optional[_Bulk], operation: str, is_read: bool = False, session: Optional[ClientSession] = None, read_pref: Optional[_ServerMode] = None, address: Optional[_Address] = None, retryable: bool = False, operation_id: Optional[int] = None, ): self._last_error: Optional[Exception] = None self._retrying = False self._multiple_retries = _csot.get_timeout() is not None self._client = mongo_client self._func = func self._bulk = bulk self._session = session self._is_read = is_read self._retryable = retryable self._read_pref = read_pref self._server_selector: Callable[[Selection], Selection] = ( read_pref if is_read else writable_server_selector # type: ignore ) self._address = address self._server: Server = None # type: ignore self._deprioritized_servers: list[Server] = [] self._operation = operation self._operation_id = operation_id def run(self) -> T: """Runs the supplied func() and attempts a retry :raises: self._last_error: Last exception raised :return: Result of the func() call """ # Increment the transaction id up front to ensure any retry attempt # will use the proper txnNumber, even if server or socket selection # fails before the command can be sent. if self._is_session_state_retryable() and self._retryable and not self._is_read: self._session._start_retryable_write() # type: ignore if self._bulk: self._bulk.started_retryable_write = True while True: self._check_last_error(check_csot=True) try: return self._read() if self._is_read else self._write() except ServerSelectionTimeoutError: # The application may think the write was never attempted # if we raise ServerSelectionTimeoutError on the retry # attempt. Raise the original exception instead. self._check_last_error() # A ServerSelectionTimeoutError error indicates that there may # be a persistent outage. Attempting to retry in this case will # most likely be a waste of time. raise except PyMongoError as exc: # Execute specialized catch on read if self._is_read: if isinstance(exc, (ConnectionFailure, OperationFailure)): # ConnectionFailures do not supply a code property exc_code = getattr(exc, "code", None) if self._is_not_eligible_for_retry() or ( isinstance(exc, OperationFailure) and exc_code not in helpers._RETRYABLE_ERROR_CODES ): raise self._retrying = True self._last_error = exc else: raise # Specialized catch on write operation if not self._is_read: if not self._retryable: raise retryable_write_error_exc = exc.has_error_label("RetryableWriteError") if retryable_write_error_exc: assert self._session self._session._unpin() if not retryable_write_error_exc or self._is_not_eligible_for_retry(): if exc.has_error_label("NoWritesPerformed") and self._last_error: raise self._last_error from exc else: raise if self._bulk: self._bulk.retrying = True else: self._retrying = True if not exc.has_error_label("NoWritesPerformed"): self._last_error = exc if self._last_error is None: self._last_error = exc if self._client.topology_description.topology_type == TOPOLOGY_TYPE.Sharded: self._deprioritized_servers.append(self._server) def _is_not_eligible_for_retry(self) -> bool: """Checks if the exchange is not eligible for retry""" return not self._retryable or (self._is_retrying() and not self._multiple_retries) def _is_retrying(self) -> bool: """Checks if the exchange is currently undergoing a retry""" return self._bulk.retrying if self._bulk else self._retrying def _is_session_state_retryable(self) -> bool: """Checks if provided session is eligible for retry reads: Make sure there is no ongoing transaction (if provided a session) writes: Make sure there is a session without an active transaction """ if self._is_read: return not (self._session and self._session.in_transaction) return bool(self._session and not self._session.in_transaction) def _check_last_error(self, check_csot: bool = False) -> None: """Checks if the ongoing client exchange experienced a exception previously. If so, raise last error :param check_csot: Checks CSOT to ensure we are retrying with time remaining defaults to False """ if self._is_retrying(): remaining = _csot.remaining() if not check_csot or (remaining is not None and remaining <= 0): assert self._last_error is not None raise self._last_error def _get_server(self) -> Server: """Retrieves a server object based on provided object context :return: Abstraction to connect to server """ return self._client._select_server( self._server_selector, self._session, self._operation, address=self._address, deprioritized_servers=self._deprioritized_servers, operation_id=self._operation_id, ) def _write(self) -> T: """Wrapper method for write-type retryable client executions :return: Output for func()'s call """ try: max_wire_version = 0 is_mongos = False self._server = self._get_server() with self._client._checkout(self._server, self._session) as conn: max_wire_version = conn.max_wire_version sessions_supported = ( self._session and self._server.description.retryable_writes_supported and conn.supports_sessions ) is_mongos = conn.is_mongos if not sessions_supported: # A retry is not possible because this server does # not support sessions raise the last error. self._check_last_error() self._retryable = False return self._func(self._session, conn, self._retryable) # type: ignore except PyMongoError as exc: if not self._retryable: raise # Add the RetryableWriteError label, if applicable. _add_retryable_write_error(exc, max_wire_version, is_mongos) raise def _read(self) -> T: """Wrapper method for read-type retryable client executions :return: Output for func()'s call """ self._server = self._get_server() assert self._read_pref is not None, "Read Preference required on read calls" with self._client._conn_from_server(self._read_pref, self._server, self._session) as ( conn, read_pref, ): if self._retrying and not self._retryable: self._check_last_error() return self._func(self._session, self._server, conn, read_pref) # type: ignore def _after_fork_child() -> None: """Releases the locks in child process and resets the topologies in all MongoClients. """ # Reinitialize locks _release_locks() # Perform cleanup in clients (i.e. get rid of topology) for _, client in MongoClient._clients.items(): client._after_fork() def _detect_external_db(entity: str) -> bool: """Detects external database hosts and logs an informational message at the INFO level.""" entity = entity.lower() cosmos_db_hosts = [".cosmos.azure.com"] document_db_hosts = [".docdb.amazonaws.com", ".docdb-elastic.amazonaws.com"] for host in cosmos_db_hosts: if entity.endswith(host): _log_or_warn( _CLIENT_LOGGER, "You appear to be connected to a CosmosDB cluster. For more information regarding feature " "compatibility and support please visit https://www.mongodb.com/supportability/cosmosdb", ) return True for host in document_db_hosts: if entity.endswith(host): _log_or_warn( _CLIENT_LOGGER, "You appear to be connected to a DocumentDB cluster. For more information regarding feature " "compatibility and support please visit https://www.mongodb.com/supportability/documentdb", ) return True return False if _HAS_REGISTER_AT_FORK: # This will run in the same thread as the fork was called. # If we fork in a critical region on the same thread, it should break. # This is fine since we would never call fork directly from a critical region. os.register_at_fork(after_in_child=_after_fork_child) mongodb-mongo-python-driver-509e9b7/pymongo/monitor.py000066400000000000000000000423501462766011000231720ustar00rootroot00000000000000# Copyright 2014-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. """Class to monitor a MongoDB server on a background thread.""" from __future__ import annotations import atexit import time import weakref from typing import TYPE_CHECKING, Any, Mapping, Optional, cast from pymongo import common, periodic_executor from pymongo._csot import MovingMinimum from pymongo.errors import NetworkTimeout, NotPrimaryError, OperationFailure, _OperationCancelled from pymongo.hello import Hello from pymongo.lock import _create_lock from pymongo.periodic_executor import _shutdown_executors from pymongo.pool import _is_faas from pymongo.read_preferences import MovingAverage from pymongo.server_description import ServerDescription from pymongo.srv_resolver import _SrvResolver if TYPE_CHECKING: from pymongo.pool import Connection, Pool, _CancellationContext from pymongo.settings import TopologySettings from pymongo.topology import Topology def _sanitize(error: Exception) -> None: """PYTHON-2433 Clear error traceback info.""" error.__traceback__ = None error.__context__ = None error.__cause__ = None class MonitorBase: def __init__(self, topology: Topology, name: str, interval: int, min_interval: float): """Base class to do periodic work on a background thread. The background thread is signaled to stop when the Topology or this instance is freed. """ # We strongly reference the executor and it weakly references us via # this closure. When the monitor is freed, stop the executor soon. def target() -> bool: monitor = self_ref() if monitor is None: return False # Stop the executor. monitor._run() # type:ignore[attr-defined] return True executor = periodic_executor.PeriodicExecutor( interval=interval, min_interval=min_interval, target=target, name=name ) self._executor = executor def _on_topology_gc(dummy: Optional[Topology] = None) -> None: # This prevents GC from waiting 10 seconds for hello to complete # See test_cleanup_executors_on_client_del. monitor = self_ref() if monitor: monitor.gc_safe_close() # Avoid cycles. When self or topology is freed, stop executor soon. self_ref = weakref.ref(self, executor.close) self._topology = weakref.proxy(topology, _on_topology_gc) _register(self) def open(self) -> None: """Start monitoring, or restart after a fork. Multiple calls have no effect. """ self._executor.open() def gc_safe_close(self) -> None: """GC safe close.""" self._executor.close() def close(self) -> None: """Close and stop monitoring. open() restarts the monitor after closing. """ self.gc_safe_close() def join(self, timeout: Optional[int] = None) -> None: """Wait for the monitor to stop.""" self._executor.join(timeout) def request_check(self) -> None: """If the monitor is sleeping, wake it soon.""" self._executor.wake() class Monitor(MonitorBase): def __init__( self, server_description: ServerDescription, topology: Topology, pool: Pool, topology_settings: TopologySettings, ): """Class to monitor a MongoDB server on a background thread. Pass an initial ServerDescription, a Topology, a Pool, and TopologySettings. The Topology is weakly referenced. The Pool must be exclusive to this Monitor. """ super().__init__( topology, "pymongo_server_monitor_thread", topology_settings.heartbeat_frequency, common.MIN_HEARTBEAT_INTERVAL, ) self._server_description = server_description self._pool = pool self._settings = topology_settings self._listeners = self._settings._pool_options._event_listeners self._publish = self._listeners is not None and self._listeners.enabled_for_server_heartbeat self._cancel_context: Optional[_CancellationContext] = None self._rtt_monitor = _RttMonitor( topology, topology_settings, topology._create_pool_for_monitor(server_description.address), ) if topology_settings.server_monitoring_mode == "stream": self._stream = True elif topology_settings.server_monitoring_mode == "poll": self._stream = False else: self._stream = not _is_faas() def cancel_check(self) -> None: """Cancel any concurrent hello check. Note: this is called from a weakref.proxy callback and MUST NOT take any locks. """ context = self._cancel_context if context: # Note: we cannot close the socket because doing so may cause # concurrent reads/writes to hang until a timeout occurs # (depending on the platform). context.cancel() def _start_rtt_monitor(self) -> None: """Start an _RttMonitor that periodically runs ping.""" # If this monitor is closed directly before (or during) this open() # call, the _RttMonitor will not be closed. Checking if this monitor # was closed directly after resolves the race. self._rtt_monitor.open() if self._executor._stopped: self._rtt_monitor.close() def gc_safe_close(self) -> None: self._executor.close() self._rtt_monitor.gc_safe_close() self.cancel_check() def close(self) -> None: self.gc_safe_close() self._rtt_monitor.close() # Increment the generation and maybe close the socket. If the executor # thread has the socket checked out, it will be closed when checked in. self._reset_connection() def _reset_connection(self) -> None: # Clear our pooled connection. self._pool.reset() def _run(self) -> None: try: prev_sd = self._server_description try: self._server_description = self._check_server() except _OperationCancelled as exc: _sanitize(exc) # Already closed the connection, wait for the next check. self._server_description = ServerDescription( self._server_description.address, error=exc ) if prev_sd.is_server_type_known: # Immediately retry since we've already waited 500ms to # discover that we've been cancelled. self._executor.skip_sleep() return # Update the Topology and clear the server pool on error. self._topology.on_change( self._server_description, reset_pool=self._server_description.error, interrupt_connections=isinstance(self._server_description.error, NetworkTimeout), ) if self._stream and ( self._server_description.is_server_type_known and self._server_description.topology_version ): self._start_rtt_monitor() # Immediately check for the next streaming response. self._executor.skip_sleep() if self._server_description.error and prev_sd.is_server_type_known: # Immediately retry on network errors. self._executor.skip_sleep() except ReferenceError: # Topology was garbage-collected. self.close() def _check_server(self) -> ServerDescription: """Call hello or read the next streaming response. Returns a ServerDescription. """ start = time.monotonic() try: try: return self._check_once() except (OperationFailure, NotPrimaryError) as exc: # Update max cluster time even when hello fails. details = cast(Mapping[str, Any], exc.details) self._topology.receive_cluster_time(details.get("$clusterTime")) raise except ReferenceError: raise except Exception as error: _sanitize(error) sd = self._server_description address = sd.address duration = time.monotonic() - start if self._publish: awaited = bool(self._stream and sd.is_server_type_known and sd.topology_version) assert self._listeners is not None self._listeners.publish_server_heartbeat_failed(address, duration, error, awaited) self._reset_connection() if isinstance(error, _OperationCancelled): raise self._rtt_monitor.reset() # Server type defaults to Unknown. return ServerDescription(address, error=error) def _check_once(self) -> ServerDescription: """A single attempt to call hello. Returns a ServerDescription, or raises an exception. """ address = self._server_description.address if self._publish: assert self._listeners is not None sd = self._server_description # XXX: "awaited" could be incorrectly set to True in the rare case # the pool checkout closes and recreates a connection. awaited = bool( self._pool.conns and self._stream and sd.is_server_type_known and sd.topology_version ) self._listeners.publish_server_heartbeat_started(address, awaited) if self._cancel_context and self._cancel_context.cancelled: self._reset_connection() with self._pool.checkout() as conn: self._cancel_context = conn.cancel_context response, round_trip_time = self._check_with_socket(conn) if not response.awaitable: self._rtt_monitor.add_sample(round_trip_time) avg_rtt, min_rtt = self._rtt_monitor.get() sd = ServerDescription(address, response, avg_rtt, min_round_trip_time=min_rtt) if self._publish: assert self._listeners is not None self._listeners.publish_server_heartbeat_succeeded( address, round_trip_time, response, response.awaitable ) return sd def _check_with_socket(self, conn: Connection) -> tuple[Hello, float]: """Return (Hello, round_trip_time). Can raise ConnectionFailure or OperationFailure. """ cluster_time = self._topology.max_cluster_time() start = time.monotonic() if conn.more_to_come: # Read the next streaming hello (MongoDB 4.4+). response = Hello(conn._next_reply(), awaitable=True) elif ( self._stream and conn.performed_handshake and self._server_description.topology_version ): # Initiate streaming hello (MongoDB 4.4+). response = conn._hello( cluster_time, self._server_description.topology_version, self._settings.heartbeat_frequency, ) else: # New connection handshake or polling hello (MongoDB <4.4). response = conn._hello(cluster_time, None, None) return response, time.monotonic() - start class SrvMonitor(MonitorBase): def __init__(self, topology: Topology, topology_settings: TopologySettings): """Class to poll SRV records on a background thread. Pass a Topology and a TopologySettings. The Topology is weakly referenced. """ super().__init__( topology, "pymongo_srv_polling_thread", common.MIN_SRV_RESCAN_INTERVAL, topology_settings.heartbeat_frequency, ) self._settings = topology_settings self._seedlist = self._settings._seeds assert isinstance(self._settings.fqdn, str) self._fqdn: str = self._settings.fqdn self._startup_time = time.monotonic() def _run(self) -> None: # Don't poll right after creation, wait 60 seconds first if time.monotonic() < self._startup_time + common.MIN_SRV_RESCAN_INTERVAL: return seedlist = self._get_seedlist() if seedlist: self._seedlist = seedlist try: self._topology.on_srv_update(self._seedlist) except ReferenceError: # Topology was garbage-collected. self.close() def _get_seedlist(self) -> Optional[list[tuple[str, Any]]]: """Poll SRV records for a seedlist. Returns a list of ServerDescriptions. """ try: resolver = _SrvResolver( self._fqdn, self._settings.pool_options.connect_timeout, self._settings.srv_service_name, ) seedlist, ttl = resolver.get_hosts_and_min_ttl() if len(seedlist) == 0: # As per the spec: this should be treated as a failure. raise Exception except Exception: # As per the spec, upon encountering an error: # - An error must not be raised # - SRV records must be rescanned every heartbeatFrequencyMS # - Topology must be left unchanged self.request_check() return None else: self._executor.update_interval(max(ttl, common.MIN_SRV_RESCAN_INTERVAL)) return seedlist class _RttMonitor(MonitorBase): def __init__(self, topology: Topology, topology_settings: TopologySettings, pool: Pool): """Maintain round trip times for a server. The Topology is weakly referenced. """ super().__init__( topology, "pymongo_server_rtt_thread", topology_settings.heartbeat_frequency, common.MIN_HEARTBEAT_INTERVAL, ) self._pool = pool self._moving_average = MovingAverage() self._moving_min = MovingMinimum() self._lock = _create_lock() def close(self) -> None: self.gc_safe_close() # Increment the generation and maybe close the socket. If the executor # thread has the socket checked out, it will be closed when checked in. self._pool.reset() def add_sample(self, sample: float) -> None: """Add a RTT sample.""" with self._lock: self._moving_average.add_sample(sample) self._moving_min.add_sample(sample) def get(self) -> tuple[Optional[float], float]: """Get the calculated average, or None if no samples yet and the min.""" with self._lock: return self._moving_average.get(), self._moving_min.get() def reset(self) -> None: """Reset the average RTT.""" with self._lock: self._moving_average.reset() self._moving_min.reset() def _run(self) -> None: try: # NOTE: This thread is only run when using the streaming # heartbeat protocol (MongoDB 4.4+). # XXX: Skip check if the server is unknown? rtt = self._ping() self.add_sample(rtt) except ReferenceError: # Topology was garbage-collected. self.close() except Exception: self._pool.reset() def _ping(self) -> float: """Run a "hello" command and return the RTT.""" with self._pool.checkout() as conn: if self._executor._stopped: raise Exception("_RttMonitor closed") start = time.monotonic() conn.hello() return time.monotonic() - start # Close monitors to cancel any in progress streaming checks before joining # executor threads. For an explanation of how this works see the comment # about _EXECUTORS in periodic_executor.py. _MONITORS = set() def _register(monitor: MonitorBase) -> None: ref = weakref.ref(monitor, _unregister) _MONITORS.add(ref) def _unregister(monitor_ref: weakref.ReferenceType[MonitorBase]) -> None: _MONITORS.remove(monitor_ref) def _shutdown_monitors() -> None: if _MONITORS is None: return # Copy the set. Closing monitors removes them. monitors = list(_MONITORS) # Close all monitors. for ref in monitors: monitor = ref() if monitor: monitor.gc_safe_close() monitor = None def _shutdown_resources() -> None: # _shutdown_monitors/_shutdown_executors may already be GC'd at shutdown. shutdown = _shutdown_monitors if shutdown: # type:ignore[truthy-function] shutdown() shutdown = _shutdown_executors if shutdown: # type:ignore[truthy-function] shutdown() atexit.register(_shutdown_resources) mongodb-mongo-python-driver-509e9b7/pymongo/monitoring.py000066400000000000000000001752561462766011000237040ustar00rootroot00000000000000# Copyright 2015-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. """Tools to monitor driver events. .. versionadded:: 3.1 .. attention:: Starting in PyMongo 3.11, the monitoring classes outlined below are included in the PyMongo distribution under the :mod:`~pymongo.event_loggers` submodule. Use :func:`register` to register global listeners for specific events. Listeners must inherit from one of the abstract classes below and implement the correct functions for that class. For example, a simple command logger might be implemented like this:: import logging from pymongo import monitoring class CommandLogger(monitoring.CommandListener): def started(self, event): logging.info("Command {0.command_name} with request id " "{0.request_id} started on server " "{0.connection_id}".format(event)) def succeeded(self, event): logging.info("Command {0.command_name} with request id " "{0.request_id} on server {0.connection_id} " "succeeded in {0.duration_micros} " "microseconds".format(event)) def failed(self, event): logging.info("Command {0.command_name} with request id " "{0.request_id} on server {0.connection_id} " "failed in {0.duration_micros} " "microseconds".format(event)) monitoring.register(CommandLogger()) Server discovery and monitoring events are also available. For example:: class ServerLogger(monitoring.ServerListener): def opened(self, event): logging.info("Server {0.server_address} added to topology " "{0.topology_id}".format(event)) def description_changed(self, event): previous_server_type = event.previous_description.server_type new_server_type = event.new_description.server_type if new_server_type != previous_server_type: # server_type_name was added in PyMongo 3.4 logging.info( "Server {0.server_address} changed type from " "{0.previous_description.server_type_name} to " "{0.new_description.server_type_name}".format(event)) def closed(self, event): logging.warning("Server {0.server_address} removed from topology " "{0.topology_id}".format(event)) class HeartbeatLogger(monitoring.ServerHeartbeatListener): def started(self, event): logging.info("Heartbeat sent to server " "{0.connection_id}".format(event)) def succeeded(self, event): # The reply.document attribute was added in PyMongo 3.4. logging.info("Heartbeat to server {0.connection_id} " "succeeded with reply " "{0.reply.document}".format(event)) def failed(self, event): logging.warning("Heartbeat to server {0.connection_id} " "failed with error {0.reply}".format(event)) class TopologyLogger(monitoring.TopologyListener): def opened(self, event): logging.info("Topology with id {0.topology_id} " "opened".format(event)) def description_changed(self, event): logging.info("Topology description updated for " "topology id {0.topology_id}".format(event)) previous_topology_type = event.previous_description.topology_type new_topology_type = event.new_description.topology_type if new_topology_type != previous_topology_type: # topology_type_name was added in PyMongo 3.4 logging.info( "Topology {0.topology_id} changed type from " "{0.previous_description.topology_type_name} to " "{0.new_description.topology_type_name}".format(event)) # The has_writable_server and has_readable_server methods # were added in PyMongo 3.4. if not event.new_description.has_writable_server(): logging.warning("No writable servers available.") if not event.new_description.has_readable_server(): logging.warning("No readable servers available.") def closed(self, event): logging.info("Topology with id {0.topology_id} " "closed".format(event)) Connection monitoring and pooling events are also available. For example:: class ConnectionPoolLogger(ConnectionPoolListener): def pool_created(self, event): logging.info("[pool {0.address}] pool created".format(event)) def pool_ready(self, event): logging.info("[pool {0.address}] pool is ready".format(event)) def pool_cleared(self, event): logging.info("[pool {0.address}] pool cleared".format(event)) def pool_closed(self, event): logging.info("[pool {0.address}] pool closed".format(event)) def connection_created(self, event): logging.info("[pool {0.address}][connection #{0.connection_id}] " "connection created".format(event)) def connection_ready(self, event): logging.info("[pool {0.address}][connection #{0.connection_id}] " "connection setup succeeded".format(event)) def connection_closed(self, event): logging.info("[pool {0.address}][connection #{0.connection_id}] " "connection closed, reason: " "{0.reason}".format(event)) def connection_check_out_started(self, event): logging.info("[pool {0.address}] connection check out " "started".format(event)) def connection_check_out_failed(self, event): logging.info("[pool {0.address}] connection check out " "failed, reason: {0.reason}".format(event)) def connection_checked_out(self, event): logging.info("[pool {0.address}][connection #{0.connection_id}] " "connection checked out of pool".format(event)) def connection_checked_in(self, event): logging.info("[pool {0.address}][connection #{0.connection_id}] " "connection checked into pool".format(event)) Event listeners can also be registered per instance of :class:`~pymongo.mongo_client.MongoClient`:: client = MongoClient(event_listeners=[CommandLogger()]) Note that previously registered global listeners are automatically included when configuring per client event listeners. Registering a new global listener will not add that listener to existing client instances. .. note:: Events are delivered **synchronously**. Application threads block waiting for event handlers (e.g. :meth:`~CommandListener.started`) to return. Care must be taken to ensure that your event handlers are efficient enough to not adversely affect overall application performance. .. warning:: The command documents published through this API are *not* copies. If you intend to modify them in any way you must copy them in your event handler first. """ from __future__ import annotations import datetime from collections import abc, namedtuple from typing import TYPE_CHECKING, Any, Mapping, Optional, Sequence from bson.objectid import ObjectId from pymongo.hello import Hello, HelloCompat from pymongo.helpers import _SENSITIVE_COMMANDS, _handle_exception from pymongo.typings import _Address, _DocumentOut if TYPE_CHECKING: from datetime import timedelta from pymongo.server_description import ServerDescription from pymongo.topology_description import TopologyDescription _Listeners = namedtuple( "_Listeners", ( "command_listeners", "server_listeners", "server_heartbeat_listeners", "topology_listeners", "cmap_listeners", ), ) _LISTENERS = _Listeners([], [], [], [], []) class _EventListener: """Abstract base class for all event listeners.""" class CommandListener(_EventListener): """Abstract base class for command listeners. Handles `CommandStartedEvent`, `CommandSucceededEvent`, and `CommandFailedEvent`. """ def started(self, event: CommandStartedEvent) -> None: """Abstract method to handle a `CommandStartedEvent`. :param event: An instance of :class:`CommandStartedEvent`. """ raise NotImplementedError def succeeded(self, event: CommandSucceededEvent) -> None: """Abstract method to handle a `CommandSucceededEvent`. :param event: An instance of :class:`CommandSucceededEvent`. """ raise NotImplementedError def failed(self, event: CommandFailedEvent) -> None: """Abstract method to handle a `CommandFailedEvent`. :param event: An instance of :class:`CommandFailedEvent`. """ raise NotImplementedError class ConnectionPoolListener(_EventListener): """Abstract base class for connection pool listeners. Handles all of the connection pool events defined in the Connection Monitoring and Pooling Specification: :class:`PoolCreatedEvent`, :class:`PoolClearedEvent`, :class:`PoolClosedEvent`, :class:`ConnectionCreatedEvent`, :class:`ConnectionReadyEvent`, :class:`ConnectionClosedEvent`, :class:`ConnectionCheckOutStartedEvent`, :class:`ConnectionCheckOutFailedEvent`, :class:`ConnectionCheckedOutEvent`, and :class:`ConnectionCheckedInEvent`. .. versionadded:: 3.9 """ def pool_created(self, event: PoolCreatedEvent) -> None: """Abstract method to handle a :class:`PoolCreatedEvent`. Emitted when a connection Pool is created. :param event: An instance of :class:`PoolCreatedEvent`. """ raise NotImplementedError def pool_ready(self, event: PoolReadyEvent) -> None: """Abstract method to handle a :class:`PoolReadyEvent`. Emitted when a connection Pool is marked ready. :param event: An instance of :class:`PoolReadyEvent`. .. versionadded:: 4.0 """ raise NotImplementedError def pool_cleared(self, event: PoolClearedEvent) -> None: """Abstract method to handle a `PoolClearedEvent`. Emitted when a connection Pool is cleared. :param event: An instance of :class:`PoolClearedEvent`. """ raise NotImplementedError def pool_closed(self, event: PoolClosedEvent) -> None: """Abstract method to handle a `PoolClosedEvent`. Emitted when a connection Pool is closed. :param event: An instance of :class:`PoolClosedEvent`. """ raise NotImplementedError def connection_created(self, event: ConnectionCreatedEvent) -> None: """Abstract method to handle a :class:`ConnectionCreatedEvent`. Emitted when a connection Pool creates a Connection object. :param event: An instance of :class:`ConnectionCreatedEvent`. """ raise NotImplementedError def connection_ready(self, event: ConnectionReadyEvent) -> None: """Abstract method to handle a :class:`ConnectionReadyEvent`. Emitted when a connection has finished its setup, and is now ready to use. :param event: An instance of :class:`ConnectionReadyEvent`. """ raise NotImplementedError def connection_closed(self, event: ConnectionClosedEvent) -> None: """Abstract method to handle a :class:`ConnectionClosedEvent`. Emitted when a connection Pool closes a connection. :param event: An instance of :class:`ConnectionClosedEvent`. """ raise NotImplementedError def connection_check_out_started(self, event: ConnectionCheckOutStartedEvent) -> None: """Abstract method to handle a :class:`ConnectionCheckOutStartedEvent`. Emitted when the driver starts attempting to check out a connection. :param event: An instance of :class:`ConnectionCheckOutStartedEvent`. """ raise NotImplementedError def connection_check_out_failed(self, event: ConnectionCheckOutFailedEvent) -> None: """Abstract method to handle a :class:`ConnectionCheckOutFailedEvent`. Emitted when the driver's attempt to check out a connection fails. :param event: An instance of :class:`ConnectionCheckOutFailedEvent`. """ raise NotImplementedError def connection_checked_out(self, event: ConnectionCheckedOutEvent) -> None: """Abstract method to handle a :class:`ConnectionCheckedOutEvent`. Emitted when the driver successfully checks out a connection. :param event: An instance of :class:`ConnectionCheckedOutEvent`. """ raise NotImplementedError def connection_checked_in(self, event: ConnectionCheckedInEvent) -> None: """Abstract method to handle a :class:`ConnectionCheckedInEvent`. Emitted when the driver checks in a connection back to the connection Pool. :param event: An instance of :class:`ConnectionCheckedInEvent`. """ raise NotImplementedError class ServerHeartbeatListener(_EventListener): """Abstract base class for server heartbeat listeners. Handles `ServerHeartbeatStartedEvent`, `ServerHeartbeatSucceededEvent`, and `ServerHeartbeatFailedEvent`. .. versionadded:: 3.3 """ def started(self, event: ServerHeartbeatStartedEvent) -> None: """Abstract method to handle a `ServerHeartbeatStartedEvent`. :param event: An instance of :class:`ServerHeartbeatStartedEvent`. """ raise NotImplementedError def succeeded(self, event: ServerHeartbeatSucceededEvent) -> None: """Abstract method to handle a `ServerHeartbeatSucceededEvent`. :param event: An instance of :class:`ServerHeartbeatSucceededEvent`. """ raise NotImplementedError def failed(self, event: ServerHeartbeatFailedEvent) -> None: """Abstract method to handle a `ServerHeartbeatFailedEvent`. :param event: An instance of :class:`ServerHeartbeatFailedEvent`. """ raise NotImplementedError class TopologyListener(_EventListener): """Abstract base class for topology monitoring listeners. Handles `TopologyOpenedEvent`, `TopologyDescriptionChangedEvent`, and `TopologyClosedEvent`. .. versionadded:: 3.3 """ def opened(self, event: TopologyOpenedEvent) -> None: """Abstract method to handle a `TopologyOpenedEvent`. :param event: An instance of :class:`TopologyOpenedEvent`. """ raise NotImplementedError def description_changed(self, event: TopologyDescriptionChangedEvent) -> None: """Abstract method to handle a `TopologyDescriptionChangedEvent`. :param event: An instance of :class:`TopologyDescriptionChangedEvent`. """ raise NotImplementedError def closed(self, event: TopologyClosedEvent) -> None: """Abstract method to handle a `TopologyClosedEvent`. :param event: An instance of :class:`TopologyClosedEvent`. """ raise NotImplementedError class ServerListener(_EventListener): """Abstract base class for server listeners. Handles `ServerOpeningEvent`, `ServerDescriptionChangedEvent`, and `ServerClosedEvent`. .. versionadded:: 3.3 """ def opened(self, event: ServerOpeningEvent) -> None: """Abstract method to handle a `ServerOpeningEvent`. :param event: An instance of :class:`ServerOpeningEvent`. """ raise NotImplementedError def description_changed(self, event: ServerDescriptionChangedEvent) -> None: """Abstract method to handle a `ServerDescriptionChangedEvent`. :param event: An instance of :class:`ServerDescriptionChangedEvent`. """ raise NotImplementedError def closed(self, event: ServerClosedEvent) -> None: """Abstract method to handle a `ServerClosedEvent`. :param event: An instance of :class:`ServerClosedEvent`. """ raise NotImplementedError def _to_micros(dur: timedelta) -> int: """Convert duration 'dur' to microseconds.""" return int(dur.total_seconds() * 10e5) def _validate_event_listeners( option: str, listeners: Sequence[_EventListeners] ) -> Sequence[_EventListeners]: """Validate event listeners""" if not isinstance(listeners, abc.Sequence): raise TypeError(f"{option} must be a list or tuple") for listener in listeners: if not isinstance(listener, _EventListener): raise TypeError( f"Listeners for {option} must be either a " "CommandListener, ServerHeartbeatListener, " "ServerListener, TopologyListener, or " "ConnectionPoolListener." ) return listeners def register(listener: _EventListener) -> None: """Register a global event listener. :param listener: A subclasses of :class:`CommandListener`, :class:`ServerHeartbeatListener`, :class:`ServerListener`, :class:`TopologyListener`, or :class:`ConnectionPoolListener`. """ if not isinstance(listener, _EventListener): raise TypeError( f"Listeners for {listener} must be either a " "CommandListener, ServerHeartbeatListener, " "ServerListener, TopologyListener, or " "ConnectionPoolListener." ) if isinstance(listener, CommandListener): _LISTENERS.command_listeners.append(listener) if isinstance(listener, ServerHeartbeatListener): _LISTENERS.server_heartbeat_listeners.append(listener) if isinstance(listener, ServerListener): _LISTENERS.server_listeners.append(listener) if isinstance(listener, TopologyListener): _LISTENERS.topology_listeners.append(listener) if isinstance(listener, ConnectionPoolListener): _LISTENERS.cmap_listeners.append(listener) # The "hello" command is also deemed sensitive when attempting speculative # authentication. def _is_speculative_authenticate(command_name: str, doc: Mapping[str, Any]) -> bool: if ( command_name.lower() in ("hello", HelloCompat.LEGACY_CMD) and "speculativeAuthenticate" in doc ): return True return False class _CommandEvent: """Base class for command events.""" __slots__ = ( "__cmd_name", "__rqst_id", "__conn_id", "__op_id", "__service_id", "__db", "__server_conn_id", ) def __init__( self, command_name: str, request_id: int, connection_id: _Address, operation_id: Optional[int], service_id: Optional[ObjectId] = None, database_name: str = "", server_connection_id: Optional[int] = None, ) -> None: self.__cmd_name = command_name self.__rqst_id = request_id self.__conn_id = connection_id self.__op_id = operation_id self.__service_id = service_id self.__db = database_name self.__server_conn_id = server_connection_id @property def command_name(self) -> str: """The command name.""" return self.__cmd_name @property def request_id(self) -> int: """The request id for this operation.""" return self.__rqst_id @property def connection_id(self) -> _Address: """The address (host, port) of the server this command was sent to.""" return self.__conn_id @property def service_id(self) -> Optional[ObjectId]: """The service_id this command was sent to, or ``None``. .. versionadded:: 3.12 """ return self.__service_id @property def operation_id(self) -> Optional[int]: """An id for this series of events or None.""" return self.__op_id @property def database_name(self) -> str: """The database_name this command was sent to, or ``""``. .. versionadded:: 4.6 """ return self.__db @property def server_connection_id(self) -> Optional[int]: """The server-side connection id for the connection this command was sent on, or ``None``. .. versionadded:: 4.7 """ return self.__server_conn_id class CommandStartedEvent(_CommandEvent): """Event published when a command starts. :param command: The command document. :param database_name: The name of the database this command was run against. :param request_id: The request id for this operation. :param connection_id: The address (host, port) of the server this command was sent to. :param operation_id: An optional identifier for a series of related events. :param service_id: The service_id this command was sent to, or ``None``. """ __slots__ = ("__cmd",) def __init__( self, command: _DocumentOut, database_name: str, request_id: int, connection_id: _Address, operation_id: Optional[int], service_id: Optional[ObjectId] = None, server_connection_id: Optional[int] = None, ) -> None: if not command: raise ValueError(f"{command!r} is not a valid command") # Command name must be first key. command_name = next(iter(command)) super().__init__( command_name, request_id, connection_id, operation_id, service_id=service_id, database_name=database_name, server_connection_id=server_connection_id, ) cmd_name = command_name.lower() if cmd_name in _SENSITIVE_COMMANDS or _is_speculative_authenticate(cmd_name, command): self.__cmd: _DocumentOut = {} else: self.__cmd = command @property def command(self) -> _DocumentOut: """The command document.""" return self.__cmd @property def database_name(self) -> str: """The name of the database this command was run against.""" return super().database_name def __repr__(self) -> str: return ( "<{} {} db: {!r}, command: {!r}, operation_id: {}, service_id: {}, server_connection_id: {}>" ).format( self.__class__.__name__, self.connection_id, self.database_name, self.command_name, self.operation_id, self.service_id, self.server_connection_id, ) class CommandSucceededEvent(_CommandEvent): """Event published when a command succeeds. :param duration: The command duration as a datetime.timedelta. :param reply: The server reply document. :param command_name: The command name. :param request_id: The request id for this operation. :param connection_id: The address (host, port) of the server this command was sent to. :param operation_id: An optional identifier for a series of related events. :param service_id: The service_id this command was sent to, or ``None``. :param database_name: The database this command was sent to, or ``""``. """ __slots__ = ("__duration_micros", "__reply") def __init__( self, duration: datetime.timedelta, reply: _DocumentOut, command_name: str, request_id: int, connection_id: _Address, operation_id: Optional[int], service_id: Optional[ObjectId] = None, database_name: str = "", server_connection_id: Optional[int] = None, ) -> None: super().__init__( command_name, request_id, connection_id, operation_id, service_id=service_id, database_name=database_name, server_connection_id=server_connection_id, ) self.__duration_micros = _to_micros(duration) cmd_name = command_name.lower() if cmd_name in _SENSITIVE_COMMANDS or _is_speculative_authenticate(cmd_name, reply): self.__reply: _DocumentOut = {} else: self.__reply = reply @property def duration_micros(self) -> int: """The duration of this operation in microseconds.""" return self.__duration_micros @property def reply(self) -> _DocumentOut: """The server failure document for this operation.""" return self.__reply def __repr__(self) -> str: return ( "<{} {} db: {!r}, command: {!r}, operation_id: {}, duration_micros: {}, service_id: {}, server_connection_id: {}>" ).format( self.__class__.__name__, self.connection_id, self.database_name, self.command_name, self.operation_id, self.duration_micros, self.service_id, self.server_connection_id, ) class CommandFailedEvent(_CommandEvent): """Event published when a command fails. :param duration: The command duration as a datetime.timedelta. :param failure: The server reply document. :param command_name: The command name. :param request_id: The request id for this operation. :param connection_id: The address (host, port) of the server this command was sent to. :param operation_id: An optional identifier for a series of related events. :param service_id: The service_id this command was sent to, or ``None``. :param database_name: The database this command was sent to, or ``""``. """ __slots__ = ("__duration_micros", "__failure") def __init__( self, duration: datetime.timedelta, failure: _DocumentOut, command_name: str, request_id: int, connection_id: _Address, operation_id: Optional[int], service_id: Optional[ObjectId] = None, database_name: str = "", server_connection_id: Optional[int] = None, ) -> None: super().__init__( command_name, request_id, connection_id, operation_id, service_id=service_id, database_name=database_name, server_connection_id=server_connection_id, ) self.__duration_micros = _to_micros(duration) self.__failure = failure @property def duration_micros(self) -> int: """The duration of this operation in microseconds.""" return self.__duration_micros @property def failure(self) -> _DocumentOut: """The server failure document for this operation.""" return self.__failure def __repr__(self) -> str: return ( "<{} {} db: {!r}, command: {!r}, operation_id: {}, duration_micros: {}, " "failure: {!r}, service_id: {}, server_connection_id: {}>" ).format( self.__class__.__name__, self.connection_id, self.database_name, self.command_name, self.operation_id, self.duration_micros, self.failure, self.service_id, self.server_connection_id, ) class _PoolEvent: """Base class for pool events.""" __slots__ = ("__address",) def __init__(self, address: _Address) -> None: self.__address = address @property def address(self) -> _Address: """The address (host, port) pair of the server the pool is attempting to connect to. """ return self.__address def __repr__(self) -> str: return f"{self.__class__.__name__}({self.__address!r})" class PoolCreatedEvent(_PoolEvent): """Published when a Connection Pool is created. :param address: The address (host, port) pair of the server this Pool is attempting to connect to. .. versionadded:: 3.9 """ __slots__ = ("__options",) def __init__(self, address: _Address, options: dict[str, Any]) -> None: super().__init__(address) self.__options = options @property def options(self) -> dict[str, Any]: """Any non-default pool options that were set on this Connection Pool.""" return self.__options def __repr__(self) -> str: return f"{self.__class__.__name__}({self.address!r}, {self.__options!r})" class PoolReadyEvent(_PoolEvent): """Published when a Connection Pool is marked ready. :param address: The address (host, port) pair of the server this Pool is attempting to connect to. .. versionadded:: 4.0 """ __slots__ = () class PoolClearedEvent(_PoolEvent): """Published when a Connection Pool is cleared. :param address: The address (host, port) pair of the server this Pool is attempting to connect to. :param service_id: The service_id this command was sent to, or ``None``. :param interrupt_connections: True if all active connections were interrupted by the Pool during clearing. .. versionadded:: 3.9 """ __slots__ = ("__service_id", "__interrupt_connections") def __init__( self, address: _Address, service_id: Optional[ObjectId] = None, interrupt_connections: bool = False, ) -> None: super().__init__(address) self.__service_id = service_id self.__interrupt_connections = interrupt_connections @property def service_id(self) -> Optional[ObjectId]: """Connections with this service_id are cleared. When service_id is ``None``, all connections in the pool are cleared. .. versionadded:: 3.12 """ return self.__service_id @property def interrupt_connections(self) -> bool: """If True, active connections are interrupted during clearing. .. versionadded:: 4.7 """ return self.__interrupt_connections def __repr__(self) -> str: return f"{self.__class__.__name__}({self.address!r}, {self.__service_id!r}, {self.__interrupt_connections!r})" class PoolClosedEvent(_PoolEvent): """Published when a Connection Pool is closed. :param address: The address (host, port) pair of the server this Pool is attempting to connect to. .. versionadded:: 3.9 """ __slots__ = () class ConnectionClosedReason: """An enum that defines values for `reason` on a :class:`ConnectionClosedEvent`. .. versionadded:: 3.9 """ STALE = "stale" """The pool was cleared, making the connection no longer valid.""" IDLE = "idle" """The connection became stale by being idle for too long (maxIdleTimeMS). """ ERROR = "error" """The connection experienced an error, making it no longer valid.""" POOL_CLOSED = "poolClosed" """The pool was closed, making the connection no longer valid.""" class ConnectionCheckOutFailedReason: """An enum that defines values for `reason` on a :class:`ConnectionCheckOutFailedEvent`. .. versionadded:: 3.9 """ TIMEOUT = "timeout" """The connection check out attempt exceeded the specified timeout.""" POOL_CLOSED = "poolClosed" """The pool was previously closed, and cannot provide new connections.""" CONN_ERROR = "connectionError" """The connection check out attempt experienced an error while setting up a new connection. """ class _ConnectionEvent: """Private base class for connection events.""" __slots__ = ("__address",) def __init__(self, address: _Address) -> None: self.__address = address @property def address(self) -> _Address: """The address (host, port) pair of the server this connection is attempting to connect to. """ return self.__address def __repr__(self) -> str: return f"{self.__class__.__name__}({self.__address!r})" class _ConnectionIdEvent(_ConnectionEvent): """Private base class for connection events with an id.""" __slots__ = ("__connection_id",) def __init__(self, address: _Address, connection_id: int) -> None: super().__init__(address) self.__connection_id = connection_id @property def connection_id(self) -> int: """The ID of the connection.""" return self.__connection_id def __repr__(self) -> str: return f"{self.__class__.__name__}({self.address!r}, {self.__connection_id!r})" class _ConnectionDurationEvent(_ConnectionIdEvent): """Private base class for connection events with a duration.""" __slots__ = ("__duration",) def __init__(self, address: _Address, connection_id: int, duration: Optional[float]) -> None: super().__init__(address, connection_id) self.__duration = duration @property def duration(self) -> Optional[float]: """The duration of the connection event. .. versionadded:: 4.7 """ return self.__duration def __repr__(self) -> str: return f"{self.__class__.__name__}({self.address!r}, {self.connection_id!r}, {self.__duration!r})" class ConnectionCreatedEvent(_ConnectionIdEvent): """Published when a Connection Pool creates a Connection object. NOTE: This connection is not ready for use until the :class:`ConnectionReadyEvent` is published. :param address: The address (host, port) pair of the server this Connection is attempting to connect to. :param connection_id: The integer ID of the Connection in this Pool. .. versionadded:: 3.9 """ __slots__ = () class ConnectionReadyEvent(_ConnectionDurationEvent): """Published when a Connection has finished its setup, and is ready to use. :param address: The address (host, port) pair of the server this Connection is attempting to connect to. :param connection_id: The integer ID of the Connection in this Pool. .. versionadded:: 3.9 """ __slots__ = () class ConnectionClosedEvent(_ConnectionIdEvent): """Published when a Connection is closed. :param address: The address (host, port) pair of the server this Connection is attempting to connect to. :param connection_id: The integer ID of the Connection in this Pool. :param reason: A reason explaining why this connection was closed. .. versionadded:: 3.9 """ __slots__ = ("__reason",) def __init__(self, address: _Address, connection_id: int, reason: str): super().__init__(address, connection_id) self.__reason = reason @property def reason(self) -> str: """A reason explaining why this connection was closed. The reason must be one of the strings from the :class:`ConnectionClosedReason` enum. """ return self.__reason def __repr__(self) -> str: return "{}({!r}, {!r}, {!r})".format( self.__class__.__name__, self.address, self.connection_id, self.__reason, ) class ConnectionCheckOutStartedEvent(_ConnectionEvent): """Published when the driver starts attempting to check out a connection. :param address: The address (host, port) pair of the server this Connection is attempting to connect to. .. versionadded:: 3.9 """ __slots__ = () class ConnectionCheckOutFailedEvent(_ConnectionDurationEvent): """Published when the driver's attempt to check out a connection fails. :param address: The address (host, port) pair of the server this Connection is attempting to connect to. :param reason: A reason explaining why connection check out failed. .. versionadded:: 3.9 """ __slots__ = ("__reason",) def __init__(self, address: _Address, reason: str, duration: Optional[float]) -> None: super().__init__(address=address, connection_id=0, duration=duration) self.__reason = reason @property def reason(self) -> str: """A reason explaining why connection check out failed. The reason must be one of the strings from the :class:`ConnectionCheckOutFailedReason` enum. """ return self.__reason def __repr__(self) -> str: return f"{self.__class__.__name__}({self.address!r}, {self.__reason!r}, {self.duration!r})" class ConnectionCheckedOutEvent(_ConnectionDurationEvent): """Published when the driver successfully checks out a connection. :param address: The address (host, port) pair of the server this Connection is attempting to connect to. :param connection_id: The integer ID of the Connection in this Pool. .. versionadded:: 3.9 """ __slots__ = () class ConnectionCheckedInEvent(_ConnectionIdEvent): """Published when the driver checks in a Connection into the Pool. :param address: The address (host, port) pair of the server this Connection is attempting to connect to. :param connection_id: The integer ID of the Connection in this Pool. .. versionadded:: 3.9 """ __slots__ = () class _ServerEvent: """Base class for server events.""" __slots__ = ("__server_address", "__topology_id") def __init__(self, server_address: _Address, topology_id: ObjectId) -> None: self.__server_address = server_address self.__topology_id = topology_id @property def server_address(self) -> _Address: """The address (host, port) pair of the server""" return self.__server_address @property def topology_id(self) -> ObjectId: """A unique identifier for the topology this server is a part of.""" return self.__topology_id def __repr__(self) -> str: return f"<{self.__class__.__name__} {self.server_address} topology_id: {self.topology_id}>" class ServerDescriptionChangedEvent(_ServerEvent): """Published when server description changes. .. versionadded:: 3.3 """ __slots__ = ("__previous_description", "__new_description") def __init__( self, previous_description: ServerDescription, new_description: ServerDescription, *args: Any, ) -> None: super().__init__(*args) self.__previous_description = previous_description self.__new_description = new_description @property def previous_description(self) -> ServerDescription: """The previous :class:`~pymongo.server_description.ServerDescription`. """ return self.__previous_description @property def new_description(self) -> ServerDescription: """The new :class:`~pymongo.server_description.ServerDescription`. """ return self.__new_description def __repr__(self) -> str: return "<{} {} changed from: {}, to: {}>".format( self.__class__.__name__, self.server_address, self.previous_description, self.new_description, ) class ServerOpeningEvent(_ServerEvent): """Published when server is initialized. .. versionadded:: 3.3 """ __slots__ = () class ServerClosedEvent(_ServerEvent): """Published when server is closed. .. versionadded:: 3.3 """ __slots__ = () class TopologyEvent: """Base class for topology description events.""" __slots__ = ("__topology_id",) def __init__(self, topology_id: ObjectId) -> None: self.__topology_id = topology_id @property def topology_id(self) -> ObjectId: """A unique identifier for the topology this server is a part of.""" return self.__topology_id def __repr__(self) -> str: return f"<{self.__class__.__name__} topology_id: {self.topology_id}>" class TopologyDescriptionChangedEvent(TopologyEvent): """Published when the topology description changes. .. versionadded:: 3.3 """ __slots__ = ("__previous_description", "__new_description") def __init__( self, previous_description: TopologyDescription, new_description: TopologyDescription, *args: Any, ) -> None: super().__init__(*args) self.__previous_description = previous_description self.__new_description = new_description @property def previous_description(self) -> TopologyDescription: """The previous :class:`~pymongo.topology_description.TopologyDescription`. """ return self.__previous_description @property def new_description(self) -> TopologyDescription: """The new :class:`~pymongo.topology_description.TopologyDescription`. """ return self.__new_description def __repr__(self) -> str: return "<{} topology_id: {} changed from: {}, to: {}>".format( self.__class__.__name__, self.topology_id, self.previous_description, self.new_description, ) class TopologyOpenedEvent(TopologyEvent): """Published when the topology is initialized. .. versionadded:: 3.3 """ __slots__ = () class TopologyClosedEvent(TopologyEvent): """Published when the topology is closed. .. versionadded:: 3.3 """ __slots__ = () class _ServerHeartbeatEvent: """Base class for server heartbeat events.""" __slots__ = ("__connection_id", "__awaited") def __init__(self, connection_id: _Address, awaited: bool = False) -> None: self.__connection_id = connection_id self.__awaited = awaited @property def connection_id(self) -> _Address: """The address (host, port) of the server this heartbeat was sent to. """ return self.__connection_id @property def awaited(self) -> bool: """Whether the heartbeat was issued as an awaitable hello command. .. versionadded:: 4.6 """ return self.__awaited def __repr__(self) -> str: return f"<{self.__class__.__name__} {self.connection_id} awaited: {self.awaited}>" class ServerHeartbeatStartedEvent(_ServerHeartbeatEvent): """Published when a heartbeat is started. .. versionadded:: 3.3 """ __slots__ = () class ServerHeartbeatSucceededEvent(_ServerHeartbeatEvent): """Fired when the server heartbeat succeeds. .. versionadded:: 3.3 """ __slots__ = ("__duration", "__reply") def __init__( self, duration: float, reply: Hello, connection_id: _Address, awaited: bool = False ) -> None: super().__init__(connection_id, awaited) self.__duration = duration self.__reply = reply @property def duration(self) -> float: """The duration of this heartbeat in microseconds.""" return self.__duration @property def reply(self) -> Hello: """An instance of :class:`~pymongo.hello.Hello`.""" return self.__reply @property def awaited(self) -> bool: """Whether the heartbeat was awaited. If true, then :meth:`duration` reflects the sum of the round trip time to the server and the time that the server waited before sending a response. .. versionadded:: 3.11 """ return super().awaited def __repr__(self) -> str: return "<{} {} duration: {}, awaited: {}, reply: {}>".format( self.__class__.__name__, self.connection_id, self.duration, self.awaited, self.reply, ) class ServerHeartbeatFailedEvent(_ServerHeartbeatEvent): """Fired when the server heartbeat fails, either with an "ok: 0" or a socket exception. .. versionadded:: 3.3 """ __slots__ = ("__duration", "__reply") def __init__( self, duration: float, reply: Exception, connection_id: _Address, awaited: bool = False ) -> None: super().__init__(connection_id, awaited) self.__duration = duration self.__reply = reply @property def duration(self) -> float: """The duration of this heartbeat in microseconds.""" return self.__duration @property def reply(self) -> Exception: """A subclass of :exc:`Exception`.""" return self.__reply @property def awaited(self) -> bool: """Whether the heartbeat was awaited. If true, then :meth:`duration` reflects the sum of the round trip time to the server and the time that the server waited before sending a response. .. versionadded:: 3.11 """ return super().awaited def __repr__(self) -> str: return "<{} {} duration: {}, awaited: {}, reply: {!r}>".format( self.__class__.__name__, self.connection_id, self.duration, self.awaited, self.reply, ) class _EventListeners: """Configure event listeners for a client instance. Any event listeners registered globally are included by default. :param listeners: A list of event listeners. """ def __init__(self, listeners: Optional[Sequence[_EventListener]]): self.__command_listeners = _LISTENERS.command_listeners[:] self.__server_listeners = _LISTENERS.server_listeners[:] lst = _LISTENERS.server_heartbeat_listeners self.__server_heartbeat_listeners = lst[:] self.__topology_listeners = _LISTENERS.topology_listeners[:] self.__cmap_listeners = _LISTENERS.cmap_listeners[:] if listeners is not None: for lst in listeners: if isinstance(lst, CommandListener): self.__command_listeners.append(lst) if isinstance(lst, ServerListener): self.__server_listeners.append(lst) if isinstance(lst, ServerHeartbeatListener): self.__server_heartbeat_listeners.append(lst) if isinstance(lst, TopologyListener): self.__topology_listeners.append(lst) if isinstance(lst, ConnectionPoolListener): self.__cmap_listeners.append(lst) self.__enabled_for_commands = bool(self.__command_listeners) self.__enabled_for_server = bool(self.__server_listeners) self.__enabled_for_server_heartbeat = bool(self.__server_heartbeat_listeners) self.__enabled_for_topology = bool(self.__topology_listeners) self.__enabled_for_cmap = bool(self.__cmap_listeners) @property def enabled_for_commands(self) -> bool: """Are any CommandListener instances registered?""" return self.__enabled_for_commands @property def enabled_for_server(self) -> bool: """Are any ServerListener instances registered?""" return self.__enabled_for_server @property def enabled_for_server_heartbeat(self) -> bool: """Are any ServerHeartbeatListener instances registered?""" return self.__enabled_for_server_heartbeat @property def enabled_for_topology(self) -> bool: """Are any TopologyListener instances registered?""" return self.__enabled_for_topology @property def enabled_for_cmap(self) -> bool: """Are any ConnectionPoolListener instances registered?""" return self.__enabled_for_cmap def event_listeners(self) -> list[_EventListeners]: """List of registered event listeners.""" return ( self.__command_listeners + self.__server_heartbeat_listeners + self.__server_listeners + self.__topology_listeners + self.__cmap_listeners ) def publish_command_start( self, command: _DocumentOut, database_name: str, request_id: int, connection_id: _Address, server_connection_id: Optional[int], op_id: Optional[int] = None, service_id: Optional[ObjectId] = None, ) -> None: """Publish a CommandStartedEvent to all command listeners. :param command: The command document. :param database_name: The name of the database this command was run against. :param request_id: The request id for this operation. :param connection_id: The address (host, port) of the server this command was sent to. :param op_id: The (optional) operation id for this operation. :param service_id: The service_id this command was sent to, or ``None``. """ if op_id is None: op_id = request_id event = CommandStartedEvent( command, database_name, request_id, connection_id, op_id, service_id=service_id, server_connection_id=server_connection_id, ) for subscriber in self.__command_listeners: try: subscriber.started(event) except Exception: _handle_exception() def publish_command_success( self, duration: timedelta, reply: _DocumentOut, command_name: str, request_id: int, connection_id: _Address, server_connection_id: Optional[int], op_id: Optional[int] = None, service_id: Optional[ObjectId] = None, speculative_hello: bool = False, database_name: str = "", ) -> None: """Publish a CommandSucceededEvent to all command listeners. :param duration: The command duration as a datetime.timedelta. :param reply: The server reply document. :param command_name: The command name. :param request_id: The request id for this operation. :param connection_id: The address (host, port) of the server this command was sent to. :param op_id: The (optional) operation id for this operation. :param service_id: The service_id this command was sent to, or ``None``. :param speculative_hello: Was the command sent with speculative auth? :param database_name: The database this command was sent to, or ``""``. """ if op_id is None: op_id = request_id if speculative_hello: # Redact entire response when the command started contained # speculativeAuthenticate. reply = {} event = CommandSucceededEvent( duration, reply, command_name, request_id, connection_id, op_id, service_id, database_name=database_name, server_connection_id=server_connection_id, ) for subscriber in self.__command_listeners: try: subscriber.succeeded(event) except Exception: _handle_exception() def publish_command_failure( self, duration: timedelta, failure: _DocumentOut, command_name: str, request_id: int, connection_id: _Address, server_connection_id: Optional[int], op_id: Optional[int] = None, service_id: Optional[ObjectId] = None, database_name: str = "", ) -> None: """Publish a CommandFailedEvent to all command listeners. :param duration: The command duration as a datetime.timedelta. :param failure: The server reply document or failure description document. :param command_name: The command name. :param request_id: The request id for this operation. :param connection_id: The address (host, port) of the server this command was sent to. :param op_id: The (optional) operation id for this operation. :param service_id: The service_id this command was sent to, or ``None``. :param database_name: The database this command was sent to, or ``""``. """ if op_id is None: op_id = request_id event = CommandFailedEvent( duration, failure, command_name, request_id, connection_id, op_id, service_id=service_id, database_name=database_name, server_connection_id=server_connection_id, ) for subscriber in self.__command_listeners: try: subscriber.failed(event) except Exception: _handle_exception() def publish_server_heartbeat_started(self, connection_id: _Address, awaited: bool) -> None: """Publish a ServerHeartbeatStartedEvent to all server heartbeat listeners. :param connection_id: The address (host, port) pair of the connection. :param awaited: True if this heartbeat is part of an awaitable hello command. """ event = ServerHeartbeatStartedEvent(connection_id, awaited) for subscriber in self.__server_heartbeat_listeners: try: subscriber.started(event) except Exception: _handle_exception() def publish_server_heartbeat_succeeded( self, connection_id: _Address, duration: float, reply: Hello, awaited: bool ) -> None: """Publish a ServerHeartbeatSucceededEvent to all server heartbeat listeners. :param connection_id: The address (host, port) pair of the connection. :param duration: The execution time of the event in the highest possible resolution for the platform. :param reply: The command reply. :param awaited: True if the response was awaited. """ event = ServerHeartbeatSucceededEvent(duration, reply, connection_id, awaited) for subscriber in self.__server_heartbeat_listeners: try: subscriber.succeeded(event) except Exception: _handle_exception() def publish_server_heartbeat_failed( self, connection_id: _Address, duration: float, reply: Exception, awaited: bool ) -> None: """Publish a ServerHeartbeatFailedEvent to all server heartbeat listeners. :param connection_id: The address (host, port) pair of the connection. :param duration: The execution time of the event in the highest possible resolution for the platform. :param reply: The command reply. :param awaited: True if the response was awaited. """ event = ServerHeartbeatFailedEvent(duration, reply, connection_id, awaited) for subscriber in self.__server_heartbeat_listeners: try: subscriber.failed(event) except Exception: _handle_exception() def publish_server_opened(self, server_address: _Address, topology_id: ObjectId) -> None: """Publish a ServerOpeningEvent to all server listeners. :param server_address: The address (host, port) pair of the server. :param topology_id: A unique identifier for the topology this server is a part of. """ event = ServerOpeningEvent(server_address, topology_id) for subscriber in self.__server_listeners: try: subscriber.opened(event) except Exception: _handle_exception() def publish_server_closed(self, server_address: _Address, topology_id: ObjectId) -> None: """Publish a ServerClosedEvent to all server listeners. :param server_address: The address (host, port) pair of the server. :param topology_id: A unique identifier for the topology this server is a part of. """ event = ServerClosedEvent(server_address, topology_id) for subscriber in self.__server_listeners: try: subscriber.closed(event) except Exception: _handle_exception() def publish_server_description_changed( self, previous_description: ServerDescription, new_description: ServerDescription, server_address: _Address, topology_id: ObjectId, ) -> None: """Publish a ServerDescriptionChangedEvent to all server listeners. :param previous_description: The previous server description. :param server_address: The address (host, port) pair of the server. :param new_description: The new server description. :param topology_id: A unique identifier for the topology this server is a part of. """ event = ServerDescriptionChangedEvent( previous_description, new_description, server_address, topology_id ) for subscriber in self.__server_listeners: try: subscriber.description_changed(event) except Exception: _handle_exception() def publish_topology_opened(self, topology_id: ObjectId) -> None: """Publish a TopologyOpenedEvent to all topology listeners. :param topology_id: A unique identifier for the topology this server is a part of. """ event = TopologyOpenedEvent(topology_id) for subscriber in self.__topology_listeners: try: subscriber.opened(event) except Exception: _handle_exception() def publish_topology_closed(self, topology_id: ObjectId) -> None: """Publish a TopologyClosedEvent to all topology listeners. :param topology_id: A unique identifier for the topology this server is a part of. """ event = TopologyClosedEvent(topology_id) for subscriber in self.__topology_listeners: try: subscriber.closed(event) except Exception: _handle_exception() def publish_topology_description_changed( self, previous_description: TopologyDescription, new_description: TopologyDescription, topology_id: ObjectId, ) -> None: """Publish a TopologyDescriptionChangedEvent to all topology listeners. :param previous_description: The previous topology description. :param new_description: The new topology description. :param topology_id: A unique identifier for the topology this server is a part of. """ event = TopologyDescriptionChangedEvent(previous_description, new_description, topology_id) for subscriber in self.__topology_listeners: try: subscriber.description_changed(event) except Exception: _handle_exception() def publish_pool_created(self, address: _Address, options: dict[str, Any]) -> None: """Publish a :class:`PoolCreatedEvent` to all pool listeners.""" event = PoolCreatedEvent(address, options) for subscriber in self.__cmap_listeners: try: subscriber.pool_created(event) except Exception: _handle_exception() def publish_pool_ready(self, address: _Address) -> None: """Publish a :class:`PoolReadyEvent` to all pool listeners.""" event = PoolReadyEvent(address) for subscriber in self.__cmap_listeners: try: subscriber.pool_ready(event) except Exception: _handle_exception() def publish_pool_cleared( self, address: _Address, service_id: Optional[ObjectId], interrupt_connections: bool = False, ) -> None: """Publish a :class:`PoolClearedEvent` to all pool listeners.""" event = PoolClearedEvent(address, service_id, interrupt_connections) for subscriber in self.__cmap_listeners: try: subscriber.pool_cleared(event) except Exception: _handle_exception() def publish_pool_closed(self, address: _Address) -> None: """Publish a :class:`PoolClosedEvent` to all pool listeners.""" event = PoolClosedEvent(address) for subscriber in self.__cmap_listeners: try: subscriber.pool_closed(event) except Exception: _handle_exception() def publish_connection_created(self, address: _Address, connection_id: int) -> None: """Publish a :class:`ConnectionCreatedEvent` to all connection listeners. """ event = ConnectionCreatedEvent(address, connection_id) for subscriber in self.__cmap_listeners: try: subscriber.connection_created(event) except Exception: _handle_exception() def publish_connection_ready( self, address: _Address, connection_id: int, duration: float ) -> None: """Publish a :class:`ConnectionReadyEvent` to all connection listeners.""" event = ConnectionReadyEvent(address, connection_id, duration) for subscriber in self.__cmap_listeners: try: subscriber.connection_ready(event) except Exception: _handle_exception() def publish_connection_closed(self, address: _Address, connection_id: int, reason: str) -> None: """Publish a :class:`ConnectionClosedEvent` to all connection listeners. """ event = ConnectionClosedEvent(address, connection_id, reason) for subscriber in self.__cmap_listeners: try: subscriber.connection_closed(event) except Exception: _handle_exception() def publish_connection_check_out_started(self, address: _Address) -> None: """Publish a :class:`ConnectionCheckOutStartedEvent` to all connection listeners. """ event = ConnectionCheckOutStartedEvent(address) for subscriber in self.__cmap_listeners: try: subscriber.connection_check_out_started(event) except Exception: _handle_exception() def publish_connection_check_out_failed( self, address: _Address, reason: str, duration: float ) -> None: """Publish a :class:`ConnectionCheckOutFailedEvent` to all connection listeners. """ event = ConnectionCheckOutFailedEvent(address, reason, duration) for subscriber in self.__cmap_listeners: try: subscriber.connection_check_out_failed(event) except Exception: _handle_exception() def publish_connection_checked_out( self, address: _Address, connection_id: int, duration: float ) -> None: """Publish a :class:`ConnectionCheckedOutEvent` to all connection listeners. """ event = ConnectionCheckedOutEvent(address, connection_id, duration) for subscriber in self.__cmap_listeners: try: subscriber.connection_checked_out(event) except Exception: _handle_exception() def publish_connection_checked_in(self, address: _Address, connection_id: int) -> None: """Publish a :class:`ConnectionCheckedInEvent` to all connection listeners. """ event = ConnectionCheckedInEvent(address, connection_id) for subscriber in self.__cmap_listeners: try: subscriber.connection_checked_in(event) except Exception: _handle_exception() mongodb-mongo-python-driver-509e9b7/pymongo/network.py000066400000000000000000000373571462766011000232070ustar00rootroot00000000000000# Copyright 2015-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. """Internal network layer helper methods.""" from __future__ import annotations import datetime import errno import logging import socket import struct import time from typing import ( TYPE_CHECKING, Any, Mapping, MutableMapping, Optional, Sequence, Union, cast, ) from bson import _decode_all_selective from pymongo import _csot, helpers, message, ssl_support from pymongo.common import MAX_MESSAGE_SIZE from pymongo.compression_support import _NO_COMPRESSION, decompress from pymongo.errors import ( NotPrimaryError, OperationFailure, ProtocolError, _OperationCancelled, ) from pymongo.logger import _COMMAND_LOGGER, _CommandStatusMessage, _debug_log from pymongo.message import _UNPACK_REPLY, _OpMsg, _OpReply from pymongo.monitoring import _is_speculative_authenticate from pymongo.socket_checker import _errno_from_exception if TYPE_CHECKING: from bson import CodecOptions from pymongo.client_session import ClientSession from pymongo.compression_support import SnappyContext, ZlibContext, ZstdContext from pymongo.mongo_client import MongoClient from pymongo.monitoring import _EventListeners from pymongo.pool import Connection from pymongo.read_concern import ReadConcern from pymongo.read_preferences import _ServerMode from pymongo.typings import _Address, _CollationIn, _DocumentOut, _DocumentType from pymongo.write_concern import WriteConcern _UNPACK_HEADER = struct.Struct(" _DocumentType: """Execute a command over the socket, or raise socket.error. :param conn: a Connection instance :param dbname: name of the database on which to run the command :param spec: a command document as an ordered dict type, eg SON. :param is_mongos: are we connected to a mongos? :param read_preference: a read preference :param codec_options: a CodecOptions instance :param session: optional ClientSession instance. :param client: optional MongoClient instance for updating $clusterTime. :param check: raise OperationFailure if there are errors :param allowable_errors: errors to ignore if `check` is True :param address: the (host, port) of `conn` :param listeners: An instance of :class:`~pymongo.monitoring.EventListeners` :param max_bson_size: The maximum encoded bson size for this server :param read_concern: The read concern for this command. :param parse_write_concern_error: Whether to parse the ``writeConcernError`` field in the command response. :param collation: The collation for this command. :param compression_ctx: optional compression Context. :param use_op_msg: True if we should use OP_MSG. :param unacknowledged: True if this is an unacknowledged command. :param user_fields: Response fields that should be decoded using the TypeDecoders from codec_options, passed to bson._decode_all_selective. :param exhaust_allowed: True if we should enable OP_MSG exhaustAllowed. """ name = next(iter(spec)) ns = dbname + ".$cmd" speculative_hello = False # Publish the original command document, perhaps with lsid and $clusterTime. orig = spec if is_mongos and not use_op_msg: assert read_preference is not None spec = message._maybe_add_read_preference(spec, read_preference) if read_concern and not (session and session.in_transaction): if read_concern.level: spec["readConcern"] = read_concern.document if session: session._update_read_concern(spec, conn) if collation is not None: spec["collation"] = collation publish = listeners is not None and listeners.enabled_for_commands start = datetime.datetime.now() if publish: speculative_hello = _is_speculative_authenticate(name, spec) if compression_ctx and name.lower() in _NO_COMPRESSION: compression_ctx = None if client and client._encrypter and not client._encrypter._bypass_auto_encryption: spec = orig = client._encrypter.encrypt(dbname, spec, codec_options) # Support CSOT if client: conn.apply_timeout(client, spec) _csot.apply_write_concern(spec, write_concern) if use_op_msg: flags = _OpMsg.MORE_TO_COME if unacknowledged else 0 flags |= _OpMsg.EXHAUST_ALLOWED if exhaust_allowed else 0 request_id, msg, size, max_doc_size = message._op_msg( flags, spec, dbname, read_preference, codec_options, ctx=compression_ctx ) # If this is an unacknowledged write then make sure the encoded doc(s) # are small enough, otherwise rely on the server to return an error. if unacknowledged and max_bson_size is not None and max_doc_size > max_bson_size: message._raise_document_too_large(name, size, max_bson_size) else: request_id, msg, size = message._query( 0, ns, 0, -1, spec, None, codec_options, compression_ctx ) if max_bson_size is not None and size > max_bson_size + message._COMMAND_OVERHEAD: message._raise_document_too_large(name, size, max_bson_size + message._COMMAND_OVERHEAD) if client is not None: if _COMMAND_LOGGER.isEnabledFor(logging.DEBUG): _debug_log( _COMMAND_LOGGER, clientId=client._topology_settings._topology_id, message=_CommandStatusMessage.STARTED, command=spec, commandName=next(iter(spec)), databaseName=dbname, requestId=request_id, operationId=request_id, driverConnectionId=conn.id, serverConnectionId=conn.server_connection_id, serverHost=conn.address[0], serverPort=conn.address[1], serviceId=conn.service_id, ) if publish: assert listeners is not None assert address is not None listeners.publish_command_start( orig, dbname, request_id, address, conn.server_connection_id, service_id=conn.service_id, ) try: conn.conn.sendall(msg) if use_op_msg and unacknowledged: # Unacknowledged, fake a successful command response. reply = None response_doc: _DocumentOut = {"ok": 1} else: reply = receive_message(conn, request_id) conn.more_to_come = reply.more_to_come unpacked_docs = reply.unpack_response( codec_options=codec_options, user_fields=user_fields ) response_doc = unpacked_docs[0] if client: client._process_response(response_doc, session) if check: helpers._check_command_response( response_doc, conn.max_wire_version, allowable_errors, parse_write_concern_error=parse_write_concern_error, ) except Exception as exc: duration = datetime.datetime.now() - start if isinstance(exc, (NotPrimaryError, OperationFailure)): failure: _DocumentOut = exc.details # type: ignore[assignment] else: failure = message._convert_exception(exc) if client is not None: if _COMMAND_LOGGER.isEnabledFor(logging.DEBUG): _debug_log( _COMMAND_LOGGER, clientId=client._topology_settings._topology_id, message=_CommandStatusMessage.FAILED, durationMS=duration, failure=failure, commandName=next(iter(spec)), databaseName=dbname, requestId=request_id, operationId=request_id, driverConnectionId=conn.id, serverConnectionId=conn.server_connection_id, serverHost=conn.address[0], serverPort=conn.address[1], serviceId=conn.service_id, isServerSideError=isinstance(exc, OperationFailure), ) if publish: assert listeners is not None assert address is not None listeners.publish_command_failure( duration, failure, name, request_id, address, conn.server_connection_id, service_id=conn.service_id, database_name=dbname, ) raise duration = datetime.datetime.now() - start if client is not None: if _COMMAND_LOGGER.isEnabledFor(logging.DEBUG): _debug_log( _COMMAND_LOGGER, clientId=client._topology_settings._topology_id, message=_CommandStatusMessage.SUCCEEDED, durationMS=duration, reply=response_doc, commandName=next(iter(spec)), databaseName=dbname, requestId=request_id, operationId=request_id, driverConnectionId=conn.id, serverConnectionId=conn.server_connection_id, serverHost=conn.address[0], serverPort=conn.address[1], serviceId=conn.service_id, speculative_authenticate="speculativeAuthenticate" in orig, ) if publish: assert listeners is not None assert address is not None listeners.publish_command_success( duration, response_doc, name, request_id, address, conn.server_connection_id, service_id=conn.service_id, speculative_hello=speculative_hello, database_name=dbname, ) if client and client._encrypter and reply: decrypted = client._encrypter.decrypt(reply.raw_command_response()) response_doc = cast( "_DocumentOut", _decode_all_selective(decrypted, codec_options, user_fields)[0] ) return response_doc # type: ignore[return-value] _UNPACK_COMPRESSION_HEADER = struct.Struct(" Union[_OpReply, _OpMsg]: """Receive a raw BSON message or raise socket.error.""" if _csot.get_timeout(): deadline = _csot.get_deadline() else: timeout = conn.conn.gettimeout() if timeout: deadline = time.monotonic() + timeout else: deadline = None # Ignore the response's request id. length, _, response_to, op_code = _UNPACK_HEADER(_receive_data_on_socket(conn, 16, deadline)) # No request_id for exhaust cursor "getMore". if request_id is not None: if request_id != response_to: raise ProtocolError(f"Got response id {response_to!r} but expected {request_id!r}") if length <= 16: raise ProtocolError( f"Message length ({length!r}) not longer than standard message header size (16)" ) if length > max_message_size: raise ProtocolError( f"Message length ({length!r}) is larger than server max " f"message size ({max_message_size!r})" ) if op_code == 2012: op_code, _, compressor_id = _UNPACK_COMPRESSION_HEADER( _receive_data_on_socket(conn, 9, deadline) ) data = decompress(_receive_data_on_socket(conn, length - 25, deadline), compressor_id) else: data = _receive_data_on_socket(conn, length - 16, deadline) try: unpack_reply = _UNPACK_REPLY[op_code] except KeyError: raise ProtocolError( f"Got opcode {op_code!r} but expected {_UNPACK_REPLY.keys()!r}" ) from None return unpack_reply(data) _POLL_TIMEOUT = 0.5 def wait_for_read(conn: Connection, deadline: Optional[float]) -> None: """Block until at least one byte is read, or a timeout, or a cancel.""" sock = conn.conn timed_out = False # Check if the connection's socket has been manually closed if sock.fileno() == -1: return while True: # SSLSocket can have buffered data which won't be caught by select. if hasattr(sock, "pending") and sock.pending() > 0: readable = True else: # Wait up to 500ms for the socket to become readable and then # check for cancellation. if deadline: remaining = deadline - time.monotonic() # When the timeout has expired perform one final check to # see if the socket is readable. This helps avoid spurious # timeouts on AWS Lambda and other FaaS environments. if remaining <= 0: timed_out = True timeout = max(min(remaining, _POLL_TIMEOUT), 0) else: timeout = _POLL_TIMEOUT readable = conn.socket_checker.select(sock, read=True, timeout=timeout) if conn.cancel_context.cancelled: raise _OperationCancelled("operation cancelled") if readable: return if timed_out: raise socket.timeout("timed out") # Errors raised by sockets (and TLS sockets) when in non-blocking mode. BLOCKING_IO_ERRORS = (BlockingIOError, *ssl_support.BLOCKING_IO_ERRORS) def _receive_data_on_socket(conn: Connection, length: int, deadline: Optional[float]) -> memoryview: buf = bytearray(length) mv = memoryview(buf) bytes_read = 0 while bytes_read < length: try: wait_for_read(conn, deadline) # CSOT: Update timeout. When the timeout has expired perform one # final non-blocking recv. This helps avoid spurious timeouts when # the response is actually already buffered on the client. if _csot.get_timeout() and deadline is not None: conn.set_conn_timeout(max(deadline - time.monotonic(), 0)) chunk_length = conn.conn.recv_into(mv[bytes_read:]) except BLOCKING_IO_ERRORS: raise socket.timeout("timed out") from None except OSError as exc: if _errno_from_exception(exc) == errno.EINTR: continue raise if chunk_length == 0: raise OSError("connection closed") bytes_read += chunk_length return mv mongodb-mongo-python-driver-509e9b7/pymongo/ocsp_cache.py000066400000000000000000000073761462766011000236030ustar00rootroot00000000000000# Copyright 2020-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. """Utilities for caching OCSP responses.""" from __future__ import annotations from collections import namedtuple from datetime import datetime as _datetime from datetime import timezone from typing import TYPE_CHECKING, Any from pymongo.lock import _create_lock if TYPE_CHECKING: from cryptography.x509.ocsp import OCSPRequest, OCSPResponse class _OCSPCache: """A cache for OCSP responses.""" CACHE_KEY_TYPE = namedtuple( # type: ignore "OcspResponseCacheKey", ["hash_algorithm", "issuer_name_hash", "issuer_key_hash", "serial_number"], ) def __init__(self) -> None: self._data: dict[Any, OCSPResponse] = {} # Hold this lock when accessing _data. self._lock = _create_lock() def _get_cache_key(self, ocsp_request: OCSPRequest) -> CACHE_KEY_TYPE: return self.CACHE_KEY_TYPE( hash_algorithm=ocsp_request.hash_algorithm.name.lower(), issuer_name_hash=ocsp_request.issuer_name_hash, issuer_key_hash=ocsp_request.issuer_key_hash, serial_number=ocsp_request.serial_number, ) def __setitem__(self, key: OCSPRequest, value: OCSPResponse) -> None: """Add/update a cache entry. 'key' is of type cryptography.x509.ocsp.OCSPRequest 'value' is of type cryptography.x509.ocsp.OCSPResponse Validity of the OCSP response must be checked by caller. """ with self._lock: cache_key = self._get_cache_key(key) # As per the OCSP protocol, if the response's nextUpdate field is # not set, the responder is indicating that newer revocation # information is available all the time. if value.next_update is None: self._data.pop(cache_key, None) return # Do nothing if the response is invalid. if not ( value.this_update <= _datetime.now(tz=timezone.utc).replace(tzinfo=None) < value.next_update ): return # Cache new response OR update cached response if new response # has longer validity. cached_value = self._data.get(cache_key, None) if cached_value is None or ( cached_value.next_update is not None and cached_value.next_update < value.next_update ): self._data[cache_key] = value def __getitem__(self, item: OCSPRequest) -> OCSPResponse: """Get a cache entry if it exists. 'item' is of type cryptography.x509.ocsp.OCSPRequest Raises KeyError if the item is not in the cache. """ with self._lock: cache_key = self._get_cache_key(item) value = self._data[cache_key] # Return cached response if it is still valid. assert value.this_update is not None assert value.next_update is not None if ( value.this_update <= _datetime.now(tz=timezone.utc).replace(tzinfo=None) < value.next_update ): return value self._data.pop(cache_key, None) raise KeyError(cache_key) mongodb-mongo-python-driver-509e9b7/pymongo/ocsp_support.py000066400000000000000000000426111462766011000242430ustar00rootroot00000000000000# Copyright 2020-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. """Support for requesting and verifying OCSP responses.""" from __future__ import annotations import logging as _logging import re as _re from datetime import datetime as _datetime from datetime import timezone from typing import TYPE_CHECKING, Iterable, Optional, Type, Union from cryptography.exceptions import InvalidSignature as _InvalidSignature from cryptography.hazmat.backends import default_backend as _default_backend from cryptography.hazmat.primitives.asymmetric.dsa import DSAPublicKey as _DSAPublicKey from cryptography.hazmat.primitives.asymmetric.ec import ECDSA as _ECDSA from cryptography.hazmat.primitives.asymmetric.ec import ( EllipticCurvePublicKey as _EllipticCurvePublicKey, ) from cryptography.hazmat.primitives.asymmetric.padding import PKCS1v15 as _PKCS1v15 from cryptography.hazmat.primitives.asymmetric.rsa import RSAPublicKey as _RSAPublicKey from cryptography.hazmat.primitives.asymmetric.x448 import ( X448PublicKey as _X448PublicKey, ) from cryptography.hazmat.primitives.asymmetric.x25519 import ( X25519PublicKey as _X25519PublicKey, ) from cryptography.hazmat.primitives.hashes import SHA1 as _SHA1 from cryptography.hazmat.primitives.hashes import Hash as _Hash from cryptography.hazmat.primitives.serialization import Encoding as _Encoding from cryptography.hazmat.primitives.serialization import PublicFormat as _PublicFormat from cryptography.x509 import AuthorityInformationAccess as _AuthorityInformationAccess from cryptography.x509 import ExtendedKeyUsage as _ExtendedKeyUsage from cryptography.x509 import ExtensionNotFound as _ExtensionNotFound from cryptography.x509 import TLSFeature as _TLSFeature from cryptography.x509 import TLSFeatureType as _TLSFeatureType from cryptography.x509 import load_pem_x509_certificate as _load_pem_x509_certificate from cryptography.x509.ocsp import OCSPCertStatus as _OCSPCertStatus from cryptography.x509.ocsp import OCSPRequestBuilder as _OCSPRequestBuilder from cryptography.x509.ocsp import OCSPResponseStatus as _OCSPResponseStatus from cryptography.x509.ocsp import load_der_ocsp_response as _load_der_ocsp_response from cryptography.x509.oid import ( AuthorityInformationAccessOID as _AuthorityInformationAccessOID, ) from cryptography.x509.oid import ExtendedKeyUsageOID as _ExtendedKeyUsageOID from requests import post as _post from requests.exceptions import RequestException as _RequestException from pymongo import _csot if TYPE_CHECKING: from cryptography.hazmat.primitives.asymmetric import ( dsa, ec, ed448, ed25519, rsa, x448, x25519, ) from cryptography.hazmat.primitives.asymmetric.utils import Prehashed from cryptography.hazmat.primitives.hashes import HashAlgorithm from cryptography.x509 import Certificate, Name from cryptography.x509.extensions import Extension, ExtensionTypeVar from cryptography.x509.ocsp import OCSPRequest, OCSPResponse from OpenSSL.SSL import Connection from pymongo.ocsp_cache import _OCSPCache from pymongo.pyopenssl_context import _CallbackData CertificateIssuerPublicKeyTypes = Union[ dsa.DSAPublicKey, rsa.RSAPublicKey, ec.EllipticCurvePublicKey, ed25519.Ed25519PublicKey, ed448.Ed448PublicKey, x25519.X25519PublicKey, x448.X448PublicKey, ] # Note: the functions in this module generally return 1 or 0. The reason # is simple. The entry point, ocsp_callback, is registered as a callback # with OpenSSL through PyOpenSSL. The callback must return 1 (success) or # 0 (failure). _LOGGER = _logging.getLogger(__name__) _CERT_REGEX = _re.compile( b"-----BEGIN CERTIFICATE[^\r\n]+.+?-----END CERTIFICATE[^\r\n]+", _re.DOTALL ) def _load_trusted_ca_certs(cafile: str) -> list[Certificate]: """Parse the tlsCAFile into a list of certificates.""" with open(cafile, "rb") as f: data = f.read() # Load all the certs in the file. trusted_ca_certs = [] backend = _default_backend() for cert_data in _re.findall(_CERT_REGEX, data): trusted_ca_certs.append(_load_pem_x509_certificate(cert_data, backend)) return trusted_ca_certs def _get_issuer_cert( cert: Certificate, chain: Iterable[Certificate], trusted_ca_certs: Optional[list[Certificate]] ) -> Optional[Certificate]: issuer_name = cert.issuer for candidate in chain: if candidate.subject == issuer_name: return candidate # Depending on the server's TLS library, the peer's cert chain may not # include the self signed root CA. In this case we check the user # provided tlsCAFile for the issuer. # Remove once we use the verified peer cert chain in PYTHON-2147. if trusted_ca_certs: for candidate in trusted_ca_certs: if candidate.subject == issuer_name: return candidate return None def _verify_signature( key: CertificateIssuerPublicKeyTypes, signature: bytes, algorithm: Union[Prehashed, HashAlgorithm, None], data: bytes, ) -> int: # See cryptography.x509.Certificate.public_key # for the public key types. try: if isinstance(key, _RSAPublicKey): key.verify(signature, data, _PKCS1v15(), algorithm) # type: ignore[arg-type] elif isinstance(key, _DSAPublicKey): key.verify(signature, data, algorithm) # type: ignore[arg-type] elif isinstance(key, _EllipticCurvePublicKey): key.verify(signature, data, _ECDSA(algorithm)) # type: ignore[arg-type] elif isinstance( key, (_X25519PublicKey, _X448PublicKey) ): # Curve25519 and Curve448 keys do not require verification return 1 else: key.verify(signature, data) except _InvalidSignature: return 0 return 1 def _get_extension( cert: Certificate, klass: Type[ExtensionTypeVar] ) -> Optional[Extension[ExtensionTypeVar]]: try: return cert.extensions.get_extension_for_class(klass) except _ExtensionNotFound: return None def _public_key_hash(cert: Certificate) -> bytes: public_key = cert.public_key() # https://tools.ietf.org/html/rfc2560#section-4.2.1 # "KeyHash ::= OCTET STRING -- SHA-1 hash of responder's public key # (excluding the tag and length fields)" # https://stackoverflow.com/a/46309453/600498 if isinstance(public_key, _RSAPublicKey): pbytes = public_key.public_bytes(_Encoding.DER, _PublicFormat.PKCS1) elif isinstance(public_key, _EllipticCurvePublicKey): pbytes = public_key.public_bytes(_Encoding.X962, _PublicFormat.UncompressedPoint) else: pbytes = public_key.public_bytes(_Encoding.DER, _PublicFormat.SubjectPublicKeyInfo) digest = _Hash(_SHA1(), backend=_default_backend()) # noqa: S303 digest.update(pbytes) return digest.finalize() def _get_certs_by_key_hash( certificates: Iterable[Certificate], issuer: Certificate, responder_key_hash: Optional[bytes] ) -> list[Certificate]: return [ cert for cert in certificates if _public_key_hash(cert) == responder_key_hash and cert.issuer == issuer.subject ] def _get_certs_by_name( certificates: Iterable[Certificate], issuer: Certificate, responder_name: Optional[Name] ) -> list[Certificate]: return [ cert for cert in certificates if cert.subject == responder_name and cert.issuer == issuer.subject ] def _verify_response_signature(issuer: Certificate, response: OCSPResponse) -> int: # Response object will have a responder_name or responder_key_hash # not both. name = response.responder_name rkey_hash = response.responder_key_hash ikey_hash = response.issuer_key_hash if name is not None and name == issuer.subject or rkey_hash == ikey_hash: _LOGGER.debug("Responder is issuer") # Responder is the issuer responder_cert = issuer else: _LOGGER.debug("Responder is a delegate") # Responder is a delegate # https://tools.ietf.org/html/rfc6960#section-2.6 # RFC6960, Section 3.2, Number 3 certs = response.certificates if response.responder_name is not None: responder_certs = _get_certs_by_name(certs, issuer, name) _LOGGER.debug("Using responder name") else: responder_certs = _get_certs_by_key_hash(certs, issuer, rkey_hash) _LOGGER.debug("Using key hash") if not responder_certs: _LOGGER.debug("No matching or valid responder certs.") return 0 # XXX: Can there be more than one? If so, should we try each one # until we find one that passes signature verification? responder_cert = responder_certs[0] # RFC6960, Section 3.2, Number 4 ext = _get_extension(responder_cert, _ExtendedKeyUsage) if not ext or _ExtendedKeyUsageOID.OCSP_SIGNING not in ext.value: _LOGGER.debug("Delegate not authorized for OCSP signing") return 0 if not _verify_signature( issuer.public_key(), responder_cert.signature, responder_cert.signature_hash_algorithm, responder_cert.tbs_certificate_bytes, ): _LOGGER.debug("Delegate signature verification failed") return 0 # RFC6960, Section 3.2, Number 2 ret = _verify_signature( responder_cert.public_key(), response.signature, response.signature_hash_algorithm, response.tbs_response_bytes, ) if not ret: _LOGGER.debug("Response signature verification failed") return ret def _build_ocsp_request(cert: Certificate, issuer: Certificate) -> OCSPRequest: # https://cryptography.io/en/latest/x509/ocsp/#creating-requests builder = _OCSPRequestBuilder() builder = builder.add_certificate(cert, issuer, _SHA1()) # noqa: S303 return builder.build() def _verify_response(issuer: Certificate, response: OCSPResponse) -> int: _LOGGER.debug("Verifying response") # RFC6960, Section 3.2, Number 2, 3 and 4 happen here. res = _verify_response_signature(issuer, response) if not res: return 0 # Note that we are not using a "tolerance period" as discussed in # https://tools.ietf.org/rfc/rfc5019.txt? now = _datetime.now(tz=timezone.utc).replace(tzinfo=None) # RFC6960, Section 3.2, Number 5 if response.this_update > now: _LOGGER.debug("thisUpdate is in the future") return 0 # RFC6960, Section 3.2, Number 6 if response.next_update and response.next_update < now: _LOGGER.debug("nextUpdate is in the past") return 0 return 1 def _get_ocsp_response( cert: Certificate, issuer: Certificate, uri: Union[str, bytes], ocsp_response_cache: _OCSPCache ) -> Optional[OCSPResponse]: ocsp_request = _build_ocsp_request(cert, issuer) try: ocsp_response = ocsp_response_cache[ocsp_request] _LOGGER.debug("Using cached OCSP response.") except KeyError: # CSOT: use the configured timeout or 5 seconds, whichever is smaller. # Note that request's timeout works differently and does not imply an absolute # deadline: https://requests.readthedocs.io/en/stable/user/quickstart/#timeouts timeout = max(_csot.clamp_remaining(5), 0.001) try: response = _post( uri, data=ocsp_request.public_bytes(_Encoding.DER), headers={"Content-Type": "application/ocsp-request"}, timeout=timeout, ) except _RequestException as exc: _LOGGER.debug("HTTP request failed: %s", exc) return None if response.status_code != 200: _LOGGER.debug("HTTP request returned %d", response.status_code) return None ocsp_response = _load_der_ocsp_response(response.content) _LOGGER.debug("OCSP response status: %r", ocsp_response.response_status) if ocsp_response.response_status != _OCSPResponseStatus.SUCCESSFUL: return None # RFC6960, Section 3.2, Number 1. Only relevant if we need to # talk to the responder directly. # Accessing response.serial_number raises if response status is not # SUCCESSFUL. if ocsp_response.serial_number != ocsp_request.serial_number: _LOGGER.debug("Response serial number does not match request") return None if not _verify_response(issuer, ocsp_response): # The response failed verification. return None _LOGGER.debug("Caching OCSP response.") ocsp_response_cache[ocsp_request] = ocsp_response return ocsp_response def _ocsp_callback(conn: Connection, ocsp_bytes: bytes, user_data: Optional[_CallbackData]) -> bool: """Callback for use with OpenSSL.SSL.Context.set_ocsp_client_callback.""" # always pass in user_data but OpenSSL requires it be optional assert user_data pycert = conn.get_peer_certificate() if pycert is None: _LOGGER.debug("No peer cert?") return False cert = pycert.to_cryptography() # Use the verified chain when available (pyopenssl>=20.0). if hasattr(conn, "get_verified_chain"): pychain = conn.get_verified_chain() trusted_ca_certs = None else: pychain = conn.get_peer_cert_chain() trusted_ca_certs = user_data.trusted_ca_certs if not pychain: _LOGGER.debug("No peer cert chain?") return False chain = [cer.to_cryptography() for cer in pychain] issuer = _get_issuer_cert(cert, chain, trusted_ca_certs) must_staple = False # https://tools.ietf.org/html/rfc7633#section-4.2.3.1 ext_tls = _get_extension(cert, _TLSFeature) if ext_tls is not None: for feature in ext_tls.value: if feature == _TLSFeatureType.status_request: _LOGGER.debug("Peer presented a must-staple cert") must_staple = True break ocsp_response_cache = user_data.ocsp_response_cache # No stapled OCSP response if ocsp_bytes == b"": _LOGGER.debug("Peer did not staple an OCSP response") if must_staple: _LOGGER.debug("Must-staple cert with no stapled response, hard fail.") return False if not user_data.check_ocsp_endpoint: _LOGGER.debug("OCSP endpoint checking is disabled, soft fail.") # No stapled OCSP response, checking responder URI disabled, soft fail. return True # https://tools.ietf.org/html/rfc6960#section-3.1 ext_aia = _get_extension(cert, _AuthorityInformationAccess) if ext_aia is None: _LOGGER.debug("No authority access information, soft fail") # No stapled OCSP response, no responder URI, soft fail. return True uris = [ desc.access_location.value for desc in ext_aia.value if desc.access_method == _AuthorityInformationAccessOID.OCSP ] if not uris: _LOGGER.debug("No OCSP URI, soft fail") # No responder URI, soft fail. return True if issuer is None: _LOGGER.debug("No issuer cert?") return False _LOGGER.debug("Requesting OCSP data") # When requesting data from an OCSP endpoint we only fail on # successful, valid responses with a certificate status of REVOKED. for uri in uris: _LOGGER.debug("Trying %s", uri) response = _get_ocsp_response(cert, issuer, uri, ocsp_response_cache) if response is None: # The endpoint didn't respond in time, or the response was # unsuccessful or didn't match the request, or the response # failed verification. continue _LOGGER.debug("OCSP cert status: %r", response.certificate_status) if response.certificate_status == _OCSPCertStatus.GOOD: return True if response.certificate_status == _OCSPCertStatus.REVOKED: return False # Soft fail if we couldn't get a definitive status. _LOGGER.debug("No definitive OCSP cert status, soft fail") return True _LOGGER.debug("Peer stapled an OCSP response") if issuer is None: _LOGGER.debug("No issuer cert?") return False response = _load_der_ocsp_response(ocsp_bytes) _LOGGER.debug("OCSP response status: %r", response.response_status) # This happens in _request_ocsp when there is no stapled response so # we know if we can compare serial numbers for the request and response. if response.response_status != _OCSPResponseStatus.SUCCESSFUL: return False if not _verify_response(issuer, response): return False # Cache the verified, stapled response. ocsp_response_cache[_build_ocsp_request(cert, issuer)] = response _LOGGER.debug("OCSP cert status: %r", response.certificate_status) if response.certificate_status == _OCSPCertStatus.REVOKED: return False return True mongodb-mongo-python-driver-509e9b7/pymongo/operations.py000066400000000000000000000526401462766011000236710ustar00rootroot00000000000000# Copyright 2015-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. """Operation class definitions.""" from __future__ import annotations import enum from typing import ( TYPE_CHECKING, Any, Generic, Mapping, Optional, Sequence, Tuple, Union, ) from bson.raw_bson import RawBSONDocument from pymongo import helpers from pymongo.collation import validate_collation_or_none from pymongo.common import validate_is_mapping, validate_list from pymongo.helpers import _gen_index_name, _index_document, _index_list from pymongo.typings import _CollationIn, _DocumentType, _Pipeline from pymongo.write_concern import validate_boolean if TYPE_CHECKING: from pymongo.bulk import _Bulk # Hint supports index name, "myIndex", a list of either strings or index pairs: [('x', 1), ('y', -1), 'z''], or a dictionary _IndexList = Union[ Sequence[Union[str, Tuple[str, Union[int, str, Mapping[str, Any]]]]], Mapping[str, Any] ] _IndexKeyHint = Union[str, _IndexList] class _Op(str, enum.Enum): ABORT = "abortTransaction" AGGREGATE = "aggregate" COMMIT = "commitTransaction" COUNT = "count" CREATE = "create" CREATE_INDEXES = "createIndexes" CREATE_SEARCH_INDEXES = "createSearchIndexes" DELETE = "delete" DISTINCT = "distinct" DROP = "drop" DROP_DATABASE = "dropDatabase" DROP_INDEXES = "dropIndexes" DROP_SEARCH_INDEXES = "dropSearchIndexes" END_SESSIONS = "endSessions" FIND_AND_MODIFY = "findAndModify" FIND = "find" INSERT = "insert" LIST_COLLECTIONS = "listCollections" LIST_INDEXES = "listIndexes" LIST_SEARCH_INDEX = "listSearchIndexes" LIST_DATABASES = "listDatabases" UPDATE = "update" UPDATE_INDEX = "updateIndex" UPDATE_SEARCH_INDEX = "updateSearchIndex" RENAME = "rename" GETMORE = "getMore" KILL_CURSORS = "killCursors" TEST = "testOperation" class InsertOne(Generic[_DocumentType]): """Represents an insert_one operation.""" __slots__ = ("_doc",) def __init__(self, document: _DocumentType) -> None: """Create an InsertOne instance. For use with :meth:`~pymongo.collection.Collection.bulk_write`. :param document: The document to insert. If the document is missing an _id field one will be added. """ self._doc = document def _add_to_bulk(self, bulkobj: _Bulk) -> None: """Add this operation to the _Bulk instance `bulkobj`.""" bulkobj.add_insert(self._doc) # type: ignore[arg-type] def __repr__(self) -> str: return f"InsertOne({self._doc!r})" def __eq__(self, other: Any) -> bool: if type(other) == type(self): return other._doc == self._doc return NotImplemented def __ne__(self, other: Any) -> bool: return not self == other class DeleteOne: """Represents a delete_one operation.""" __slots__ = ("_filter", "_collation", "_hint") def __init__( self, filter: Mapping[str, Any], collation: Optional[_CollationIn] = None, hint: Optional[_IndexKeyHint] = None, ) -> None: """Create a DeleteOne instance. For use with :meth:`~pymongo.collection.Collection.bulk_write`. :param filter: A query that matches the document to delete. :param collation: An instance of :class:`~pymongo.collation.Collation`. :param hint: An index to use to support the query predicate specified either by its string name, or in the same format as passed to :meth:`~pymongo.collection.Collection.create_index` (e.g. ``[('field', ASCENDING)]``). This option is only supported on MongoDB 4.4 and above. .. versionchanged:: 3.11 Added the ``hint`` option. .. versionchanged:: 3.5 Added the `collation` option. """ if filter is not None: validate_is_mapping("filter", filter) if hint is not None and not isinstance(hint, str): self._hint: Union[str, dict[str, Any], None] = helpers._index_document(hint) else: self._hint = hint self._filter = filter self._collation = collation def _add_to_bulk(self, bulkobj: _Bulk) -> None: """Add this operation to the _Bulk instance `bulkobj`.""" bulkobj.add_delete( self._filter, 1, collation=validate_collation_or_none(self._collation), hint=self._hint, ) def __repr__(self) -> str: return f"DeleteOne({self._filter!r}, {self._collation!r}, {self._hint!r})" def __eq__(self, other: Any) -> bool: if type(other) == type(self): return (other._filter, other._collation, other._hint) == ( self._filter, self._collation, self._hint, ) return NotImplemented def __ne__(self, other: Any) -> bool: return not self == other class DeleteMany: """Represents a delete_many operation.""" __slots__ = ("_filter", "_collation", "_hint") def __init__( self, filter: Mapping[str, Any], collation: Optional[_CollationIn] = None, hint: Optional[_IndexKeyHint] = None, ) -> None: """Create a DeleteMany instance. For use with :meth:`~pymongo.collection.Collection.bulk_write`. :param filter: A query that matches the documents to delete. :param collation: An instance of :class:`~pymongo.collation.Collation`. :param hint: An index to use to support the query predicate specified either by its string name, or in the same format as passed to :meth:`~pymongo.collection.Collection.create_index` (e.g. ``[('field', ASCENDING)]``). This option is only supported on MongoDB 4.4 and above. .. versionchanged:: 3.11 Added the ``hint`` option. .. versionchanged:: 3.5 Added the `collation` option. """ if filter is not None: validate_is_mapping("filter", filter) if hint is not None and not isinstance(hint, str): self._hint: Union[str, dict[str, Any], None] = helpers._index_document(hint) else: self._hint = hint self._filter = filter self._collation = collation def _add_to_bulk(self, bulkobj: _Bulk) -> None: """Add this operation to the _Bulk instance `bulkobj`.""" bulkobj.add_delete( self._filter, 0, collation=validate_collation_or_none(self._collation), hint=self._hint, ) def __repr__(self) -> str: return f"DeleteMany({self._filter!r}, {self._collation!r}, {self._hint!r})" def __eq__(self, other: Any) -> bool: if type(other) == type(self): return (other._filter, other._collation, other._hint) == ( self._filter, self._collation, self._hint, ) return NotImplemented def __ne__(self, other: Any) -> bool: return not self == other class ReplaceOne(Generic[_DocumentType]): """Represents a replace_one operation.""" __slots__ = ("_filter", "_doc", "_upsert", "_collation", "_hint") def __init__( self, filter: Mapping[str, Any], replacement: Union[_DocumentType, RawBSONDocument], upsert: bool = False, collation: Optional[_CollationIn] = None, hint: Optional[_IndexKeyHint] = None, ) -> None: """Create a ReplaceOne instance. For use with :meth:`~pymongo.collection.Collection.bulk_write`. :param filter: A query that matches the document to replace. :param replacement: The new document. :param upsert: If ``True``, perform an insert if no documents match the filter. :param collation: An instance of :class:`~pymongo.collation.Collation`. :param hint: An index to use to support the query predicate specified either by its string name, or in the same format as passed to :meth:`~pymongo.collection.Collection.create_index` (e.g. ``[('field', ASCENDING)]``). This option is only supported on MongoDB 4.2 and above. .. versionchanged:: 3.11 Added the ``hint`` option. .. versionchanged:: 3.5 Added the ``collation`` option. """ if filter is not None: validate_is_mapping("filter", filter) if upsert is not None: validate_boolean("upsert", upsert) if hint is not None and not isinstance(hint, str): self._hint: Union[str, dict[str, Any], None] = helpers._index_document(hint) else: self._hint = hint self._filter = filter self._doc = replacement self._upsert = upsert self._collation = collation def _add_to_bulk(self, bulkobj: _Bulk) -> None: """Add this operation to the _Bulk instance `bulkobj`.""" bulkobj.add_replace( self._filter, self._doc, self._upsert, collation=validate_collation_or_none(self._collation), hint=self._hint, ) def __eq__(self, other: Any) -> bool: if type(other) == type(self): return ( other._filter, other._doc, other._upsert, other._collation, other._hint, ) == ( self._filter, self._doc, self._upsert, self._collation, other._hint, ) return NotImplemented def __ne__(self, other: Any) -> bool: return not self == other def __repr__(self) -> str: return "{}({!r}, {!r}, {!r}, {!r}, {!r})".format( self.__class__.__name__, self._filter, self._doc, self._upsert, self._collation, self._hint, ) class _UpdateOp: """Private base class for update operations.""" __slots__ = ("_filter", "_doc", "_upsert", "_collation", "_array_filters", "_hint") def __init__( self, filter: Mapping[str, Any], doc: Union[Mapping[str, Any], _Pipeline], upsert: bool, collation: Optional[_CollationIn], array_filters: Optional[list[Mapping[str, Any]]], hint: Optional[_IndexKeyHint], ): if filter is not None: validate_is_mapping("filter", filter) if upsert is not None: validate_boolean("upsert", upsert) if array_filters is not None: validate_list("array_filters", array_filters) if hint is not None and not isinstance(hint, str): self._hint: Union[str, dict[str, Any], None] = helpers._index_document(hint) else: self._hint = hint self._filter = filter self._doc = doc self._upsert = upsert self._collation = collation self._array_filters = array_filters def __eq__(self, other: object) -> bool: if isinstance(other, type(self)): return ( other._filter, other._doc, other._upsert, other._collation, other._array_filters, other._hint, ) == ( self._filter, self._doc, self._upsert, self._collation, self._array_filters, self._hint, ) return NotImplemented def __repr__(self) -> str: return "{}({!r}, {!r}, {!r}, {!r}, {!r}, {!r})".format( self.__class__.__name__, self._filter, self._doc, self._upsert, self._collation, self._array_filters, self._hint, ) class UpdateOne(_UpdateOp): """Represents an update_one operation.""" __slots__ = () def __init__( self, filter: Mapping[str, Any], update: Union[Mapping[str, Any], _Pipeline], upsert: bool = False, collation: Optional[_CollationIn] = None, array_filters: Optional[list[Mapping[str, Any]]] = None, hint: Optional[_IndexKeyHint] = None, ) -> None: """Represents an update_one operation. For use with :meth:`~pymongo.collection.Collection.bulk_write`. :param filter: A query that matches the document to update. :param update: The modifications to apply. :param upsert: If ``True``, perform an insert if no documents match the filter. :param collation: An instance of :class:`~pymongo.collation.Collation`. :param array_filters: A list of filters specifying which array elements an update should apply. :param hint: An index to use to support the query predicate specified either by its string name, or in the same format as passed to :meth:`~pymongo.collection.Collection.create_index` (e.g. ``[('field', ASCENDING)]``). This option is only supported on MongoDB 4.2 and above. .. versionchanged:: 3.11 Added the `hint` option. .. versionchanged:: 3.9 Added the ability to accept a pipeline as the `update`. .. versionchanged:: 3.6 Added the `array_filters` option. .. versionchanged:: 3.5 Added the `collation` option. """ super().__init__(filter, update, upsert, collation, array_filters, hint) def _add_to_bulk(self, bulkobj: _Bulk) -> None: """Add this operation to the _Bulk instance `bulkobj`.""" bulkobj.add_update( self._filter, self._doc, False, self._upsert, collation=validate_collation_or_none(self._collation), array_filters=self._array_filters, hint=self._hint, ) class UpdateMany(_UpdateOp): """Represents an update_many operation.""" __slots__ = () def __init__( self, filter: Mapping[str, Any], update: Union[Mapping[str, Any], _Pipeline], upsert: bool = False, collation: Optional[_CollationIn] = None, array_filters: Optional[list[Mapping[str, Any]]] = None, hint: Optional[_IndexKeyHint] = None, ) -> None: """Create an UpdateMany instance. For use with :meth:`~pymongo.collection.Collection.bulk_write`. :param filter: A query that matches the documents to update. :param update: The modifications to apply. :param upsert: If ``True``, perform an insert if no documents match the filter. :param collation: An instance of :class:`~pymongo.collation.Collation`. :param array_filters: A list of filters specifying which array elements an update should apply. :param hint: An index to use to support the query predicate specified either by its string name, or in the same format as passed to :meth:`~pymongo.collection.Collection.create_index` (e.g. ``[('field', ASCENDING)]``). This option is only supported on MongoDB 4.2 and above. .. versionchanged:: 3.11 Added the `hint` option. .. versionchanged:: 3.9 Added the ability to accept a pipeline as the `update`. .. versionchanged:: 3.6 Added the `array_filters` option. .. versionchanged:: 3.5 Added the `collation` option. """ super().__init__(filter, update, upsert, collation, array_filters, hint) def _add_to_bulk(self, bulkobj: _Bulk) -> None: """Add this operation to the _Bulk instance `bulkobj`.""" bulkobj.add_update( self._filter, self._doc, True, self._upsert, collation=validate_collation_or_none(self._collation), array_filters=self._array_filters, hint=self._hint, ) class IndexModel: """Represents an index to create.""" __slots__ = ("__document",) def __init__(self, keys: _IndexKeyHint, **kwargs: Any) -> None: """Create an Index instance. For use with :meth:`~pymongo.collection.Collection.create_indexes`. Takes either a single key or a list containing (key, direction) pairs or keys. If no direction is given, :data:`~pymongo.ASCENDING` will be assumed. The key(s) must be an instance of :class:`str`, and the direction(s) must be one of (:data:`~pymongo.ASCENDING`, :data:`~pymongo.DESCENDING`, :data:`~pymongo.GEO2D`, :data:`~pymongo.GEOSPHERE`, :data:`~pymongo.HASHED`, :data:`~pymongo.TEXT`). Valid options include, but are not limited to: - `name`: custom name to use for this index - if none is given, a name will be generated. - `unique`: if ``True``, creates a uniqueness constraint on the index. - `background`: if ``True``, this index should be created in the background. - `sparse`: if ``True``, omit from the index any documents that lack the indexed field. - `bucketSize`: for use with geoHaystack indexes. Number of documents to group together within a certain proximity to a given longitude and latitude. - `min`: minimum value for keys in a :data:`~pymongo.GEO2D` index. - `max`: maximum value for keys in a :data:`~pymongo.GEO2D` index. - `expireAfterSeconds`: Used to create an expiring (TTL) collection. MongoDB will automatically delete documents from this collection after seconds. The indexed field must be a UTC datetime or the data will not expire. - `partialFilterExpression`: A document that specifies a filter for a partial index. - `collation`: An instance of :class:`~pymongo.collation.Collation` that specifies the collation to use. - `wildcardProjection`: Allows users to include or exclude specific field paths from a `wildcard index`_ using the { "$**" : 1} key pattern. Requires MongoDB >= 4.2. - `hidden`: if ``True``, this index will be hidden from the query planner and will not be evaluated as part of query plan selection. Requires MongoDB >= 4.4. See the MongoDB documentation for a full list of supported options by server version. :param keys: a single key or a list containing (key, direction) pairs or keys specifying the index to create. :param kwargs: any additional index creation options (see the above list) should be passed as keyword arguments. .. versionchanged:: 3.11 Added the ``hidden`` option. .. versionchanged:: 3.2 Added the ``partialFilterExpression`` option to support partial indexes. .. _wildcard index: https://mongodb.com/docs/master/core/index-wildcard/ """ keys = _index_list(keys) if kwargs.get("name") is None: kwargs["name"] = _gen_index_name(keys) kwargs["key"] = _index_document(keys) collation = validate_collation_or_none(kwargs.pop("collation", None)) self.__document = kwargs if collation is not None: self.__document["collation"] = collation @property def document(self) -> dict[str, Any]: """An index document suitable for passing to the createIndexes command. """ return self.__document class SearchIndexModel: """Represents a search index to create.""" __slots__ = ("__document",) def __init__( self, definition: Mapping[str, Any], name: Optional[str] = None, type: Optional[str] = None, **kwargs: Any, ) -> None: """Create a Search Index instance. For use with :meth:`~pymongo.collection.Collection.create_search_index` and :meth:`~pymongo.collection.Collection.create_search_indexes`. :param definition: The definition for this index. :param name: The name for this index, if present. :param type: The type for this index which defaults to "search". Alternative values include "vectorSearch". :param kwargs: Keyword arguments supplying any additional options. .. note:: Search indexes require a MongoDB server version 7.0+ Atlas cluster. .. versionadded:: 4.5 .. versionchanged:: 4.7 Added the type and kwargs arguments. """ self.__document: dict[str, Any] = {} if name is not None: self.__document["name"] = name self.__document["definition"] = definition if type is not None: self.__document["type"] = type self.__document.update(kwargs) @property def document(self) -> Mapping[str, Any]: """The document for this index.""" return self.__document mongodb-mongo-python-driver-509e9b7/pymongo/periodic_executor.py000066400000000000000000000150611462766011000252160ustar00rootroot00000000000000# Copyright 2014-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. """Run a target function on a background thread.""" from __future__ import annotations import sys import threading import time import weakref from typing import Any, Callable, Optional from pymongo.lock import _create_lock class PeriodicExecutor: def __init__( self, interval: float, min_interval: float, target: Callable[[], bool], name: Optional[str] = None, ): """ "Run a target function periodically on a background thread. If the target's return value is false, the executor stops. :param interval: Seconds between calls to `target`. :param min_interval: Minimum seconds between calls if `wake` is called very often. :param target: A function. :param name: A name to give the underlying thread. """ # threading.Event and its internal condition variable are expensive # in Python 2, see PYTHON-983. Use a boolean to know when to wake. # The executor's design is constrained by several Python issues, see # "periodic_executor.rst" in this repository. self._event = False self._interval = interval self._min_interval = min_interval self._target = target self._stopped = False self._thread: Optional[threading.Thread] = None self._name = name self._skip_sleep = False self._thread_will_exit = False self._lock = _create_lock() def __repr__(self) -> str: return f"<{self.__class__.__name__}(name={self._name}) object at 0x{id(self):x}>" def open(self) -> None: """Start. Multiple calls have no effect. Not safe to call from multiple threads at once. """ with self._lock: if self._thread_will_exit: # If the background thread has read self._stopped as True # there is a chance that it has not yet exited. The call to # join should not block indefinitely because there is no # other work done outside the while loop in self._run. try: assert self._thread is not None self._thread.join() except ReferenceError: # Thread terminated. pass self._thread_will_exit = False self._stopped = False started: Any = False try: started = self._thread and self._thread.is_alive() except ReferenceError: # Thread terminated. pass if not started: thread = threading.Thread(target=self._run, name=self._name) thread.daemon = True self._thread = weakref.proxy(thread) _register_executor(self) # Mitigation to RuntimeError firing when thread starts on shutdown # https://github.com/python/cpython/issues/114570 try: thread.start() except RuntimeError as e: if "interpreter shutdown" in str(e) or sys.is_finalizing(): self._thread = None return raise def close(self, dummy: Any = None) -> None: """Stop. To restart, call open(). The dummy parameter allows an executor's close method to be a weakref callback; see monitor.py. """ self._stopped = True def join(self, timeout: Optional[int] = None) -> None: if self._thread is not None: try: self._thread.join(timeout) except (ReferenceError, RuntimeError): # Thread already terminated, or not yet started. pass def wake(self) -> None: """Execute the target function soon.""" self._event = True def update_interval(self, new_interval: int) -> None: self._interval = new_interval def skip_sleep(self) -> None: self._skip_sleep = True def __should_stop(self) -> bool: with self._lock: if self._stopped: self._thread_will_exit = True return True return False def _run(self) -> None: while not self.__should_stop(): try: if not self._target(): self._stopped = True break except BaseException: with self._lock: self._stopped = True self._thread_will_exit = True raise if self._skip_sleep: self._skip_sleep = False else: deadline = time.monotonic() + self._interval while not self._stopped and time.monotonic() < deadline: time.sleep(self._min_interval) if self._event: break # Early wake. self._event = False # _EXECUTORS has a weakref to each running PeriodicExecutor. Once started, # an executor is kept alive by a strong reference from its thread and perhaps # from other objects. When the thread dies and all other referrers are freed, # the executor is freed and removed from _EXECUTORS. If any threads are # running when the interpreter begins to shut down, we try to halt and join # them to avoid spurious errors. _EXECUTORS = set() def _register_executor(executor: PeriodicExecutor) -> None: ref = weakref.ref(executor, _on_executor_deleted) _EXECUTORS.add(ref) def _on_executor_deleted(ref: weakref.ReferenceType[PeriodicExecutor]) -> None: _EXECUTORS.remove(ref) def _shutdown_executors() -> None: if _EXECUTORS is None: return # Copy the set. Stopping threads has the side effect of removing executors. executors = list(_EXECUTORS) # First signal all executors to close... for ref in executors: executor = ref() if executor: executor.close() # ...then try to join them. for ref in executors: executor = ref() if executor: executor.join(1) executor = None mongodb-mongo-python-driver-509e9b7/pymongo/pool.py000066400000000000000000002416621462766011000224630ustar00rootroot00000000000000# Copyright 2011-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. from __future__ import annotations import collections import contextlib import copy import logging import os import platform import socket import ssl import sys import threading import time import weakref from pathlib import Path from typing import ( TYPE_CHECKING, Any, Iterator, Mapping, MutableMapping, NoReturn, Optional, Sequence, Union, ) import bson from bson import DEFAULT_CODEC_OPTIONS from pymongo import __version__, _csot, helpers from pymongo.client_session import _validate_session_write_concern from pymongo.common import ( MAX_BSON_SIZE, MAX_CONNECTING, MAX_IDLE_TIME_SEC, MAX_MESSAGE_SIZE, MAX_POOL_SIZE, MAX_WIRE_VERSION, MAX_WRITE_BATCH_SIZE, MIN_POOL_SIZE, ORDERED_TYPES, WAIT_QUEUE_TIMEOUT, ) from pymongo.errors import ( # type:ignore[attr-defined] AutoReconnect, ConfigurationError, ConnectionFailure, DocumentTooLarge, ExecutionTimeout, InvalidOperation, NetworkTimeout, NotPrimaryError, OperationFailure, PyMongoError, WaitQueueTimeoutError, _CertificateError, ) from pymongo.hello import Hello, HelloCompat from pymongo.helpers import _handle_reauth from pymongo.lock import _create_lock from pymongo.logger import ( _CONNECTION_LOGGER, _ConnectionStatusMessage, _debug_log, _verbose_connection_error_reason, ) from pymongo.monitoring import ( ConnectionCheckOutFailedReason, ConnectionClosedReason, _EventListeners, ) from pymongo.network import command, receive_message from pymongo.read_preferences import ReadPreference from pymongo.server_api import _add_to_command from pymongo.server_type import SERVER_TYPE from pymongo.socket_checker import SocketChecker from pymongo.ssl_support import HAS_SNI, SSLError if TYPE_CHECKING: from bson import CodecOptions from bson.objectid import ObjectId from pymongo.auth import MongoCredential, _AuthContext from pymongo.client_session import ClientSession from pymongo.compression_support import ( CompressionSettings, SnappyContext, ZlibContext, ZstdContext, ) from pymongo.driver_info import DriverInfo from pymongo.message import _OpMsg, _OpReply from pymongo.mongo_client import MongoClient, _MongoClientErrorHandler from pymongo.pyopenssl_context import SSLContext, _sslConn from pymongo.read_concern import ReadConcern from pymongo.read_preferences import _ServerMode from pymongo.server_api import ServerApi from pymongo.typings import ClusterTime, _Address, _CollationIn from pymongo.write_concern import WriteConcern try: from fcntl import F_GETFD, F_SETFD, FD_CLOEXEC, fcntl def _set_non_inheritable_non_atomic(fd: int) -> None: """Set the close-on-exec flag on the given file descriptor.""" flags = fcntl(fd, F_GETFD) fcntl(fd, F_SETFD, flags | FD_CLOEXEC) except ImportError: # Windows, various platforms we don't claim to support # (Jython, IronPython, ..), systems that don't provide # everything we need from fcntl, etc. def _set_non_inheritable_non_atomic(fd: int) -> None: # noqa: ARG001 """Dummy function for platforms that don't provide fcntl.""" _MAX_TCP_KEEPIDLE = 120 _MAX_TCP_KEEPINTVL = 10 _MAX_TCP_KEEPCNT = 9 if sys.platform == "win32": try: import _winreg as winreg except ImportError: import winreg def _query(key, name, default): try: value, _ = winreg.QueryValueEx(key, name) # Ensure the value is a number or raise ValueError. return int(value) except (OSError, ValueError): # QueryValueEx raises OSError when the key does not exist (i.e. # the system is using the Windows default value). return default try: with winreg.OpenKey( winreg.HKEY_LOCAL_MACHINE, r"SYSTEM\CurrentControlSet\Services\Tcpip\Parameters" ) as key: _WINDOWS_TCP_IDLE_MS = _query(key, "KeepAliveTime", 7200000) _WINDOWS_TCP_INTERVAL_MS = _query(key, "KeepAliveInterval", 1000) except OSError: # We could not check the default values because winreg.OpenKey failed. # Assume the system is using the default values. _WINDOWS_TCP_IDLE_MS = 7200000 _WINDOWS_TCP_INTERVAL_MS = 1000 def _set_keepalive_times(sock): idle_ms = min(_WINDOWS_TCP_IDLE_MS, _MAX_TCP_KEEPIDLE * 1000) interval_ms = min(_WINDOWS_TCP_INTERVAL_MS, _MAX_TCP_KEEPINTVL * 1000) if idle_ms < _WINDOWS_TCP_IDLE_MS or interval_ms < _WINDOWS_TCP_INTERVAL_MS: sock.ioctl(socket.SIO_KEEPALIVE_VALS, (1, idle_ms, interval_ms)) else: def _set_tcp_option(sock: socket.socket, tcp_option: str, max_value: int) -> None: if hasattr(socket, tcp_option): sockopt = getattr(socket, tcp_option) try: # PYTHON-1350 - NetBSD doesn't implement getsockopt for # TCP_KEEPIDLE and friends. Don't attempt to set the # values there. default = sock.getsockopt(socket.IPPROTO_TCP, sockopt) if default > max_value: sock.setsockopt(socket.IPPROTO_TCP, sockopt, max_value) except OSError: pass def _set_keepalive_times(sock: socket.socket) -> None: _set_tcp_option(sock, "TCP_KEEPIDLE", _MAX_TCP_KEEPIDLE) _set_tcp_option(sock, "TCP_KEEPINTVL", _MAX_TCP_KEEPINTVL) _set_tcp_option(sock, "TCP_KEEPCNT", _MAX_TCP_KEEPCNT) _METADATA: dict[str, Any] = {"driver": {"name": "PyMongo", "version": __version__}} if sys.platform.startswith("linux"): # platform.linux_distribution was deprecated in Python 3.5 # and removed in Python 3.8. Starting in Python 3.5 it # raises DeprecationWarning # DeprecationWarning: dist() and linux_distribution() functions are deprecated in Python 3.5 _name = platform.system() _METADATA["os"] = { "type": _name, "name": _name, "architecture": platform.machine(), # Kernel version (e.g. 4.4.0-17-generic). "version": platform.release(), } elif sys.platform == "darwin": _METADATA["os"] = { "type": platform.system(), "name": platform.system(), "architecture": platform.machine(), # (mac|i|tv)OS(X) version (e.g. 10.11.6) instead of darwin # kernel version. "version": platform.mac_ver()[0], } elif sys.platform == "win32": _ver = sys.getwindowsversion() _METADATA["os"] = { "type": "Windows", "name": "Windows", # Avoid using platform calls, see PYTHON-4455. "architecture": os.environ.get("PROCESSOR_ARCHITECTURE") or platform.machine(), # Windows patch level (e.g. 10.0.17763-SP0). "version": ".".join(map(str, _ver[:3])) + f"-SP{_ver[-1] or '0'}", } elif sys.platform.startswith("java"): _name, _ver, _arch = platform.java_ver()[-1] _METADATA["os"] = { # Linux, Windows 7, Mac OS X, etc. "type": _name, "name": _name, # x86, x86_64, AMD64, etc. "architecture": _arch, # Linux kernel version, OSX version, etc. "version": _ver, } else: # Get potential alias (e.g. SunOS 5.11 becomes Solaris 2.11) _aliased = platform.system_alias(platform.system(), platform.release(), platform.version()) _METADATA["os"] = { "type": platform.system(), "name": " ".join([part for part in _aliased[:2] if part]), "architecture": platform.machine(), "version": _aliased[2], } if platform.python_implementation().startswith("PyPy"): _METADATA["platform"] = " ".join( ( platform.python_implementation(), ".".join(map(str, sys.pypy_version_info)), # type: ignore "(Python %s)" % ".".join(map(str, sys.version_info)), ) ) elif sys.platform.startswith("java"): _METADATA["platform"] = " ".join( ( platform.python_implementation(), ".".join(map(str, sys.version_info)), "(%s)" % " ".join((platform.system(), platform.release())), ) ) else: _METADATA["platform"] = " ".join( (platform.python_implementation(), ".".join(map(str, sys.version_info))) ) DOCKER_ENV_PATH = "/.dockerenv" ENV_VAR_K8S = "KUBERNETES_SERVICE_HOST" RUNTIME_NAME_DOCKER = "docker" ORCHESTRATOR_NAME_K8S = "kubernetes" def get_container_env_info() -> dict[str, str]: """Returns the runtime and orchestrator of a container. If neither value is present, the metadata client.env.container field will be omitted.""" container = {} if Path(DOCKER_ENV_PATH).exists(): container["runtime"] = RUNTIME_NAME_DOCKER if os.getenv(ENV_VAR_K8S): container["orchestrator"] = ORCHESTRATOR_NAME_K8S return container def _is_lambda() -> bool: if os.getenv("AWS_LAMBDA_RUNTIME_API"): return True env = os.getenv("AWS_EXECUTION_ENV") if env: return env.startswith("AWS_Lambda_") return False def _is_azure_func() -> bool: return bool(os.getenv("FUNCTIONS_WORKER_RUNTIME")) def _is_gcp_func() -> bool: return bool(os.getenv("K_SERVICE") or os.getenv("FUNCTION_NAME")) def _is_vercel() -> bool: return bool(os.getenv("VERCEL")) def _is_faas() -> bool: return _is_lambda() or _is_azure_func() or _is_gcp_func() or _is_vercel() def _getenv_int(key: str) -> Optional[int]: """Like os.getenv but returns an int, or None if the value is missing/malformed.""" val = os.getenv(key) if not val: return None try: return int(val) except ValueError: return None def _metadata_env() -> dict[str, Any]: env: dict[str, Any] = {} container = get_container_env_info() if container: env["container"] = container # Skip if multiple (or no) envs are matched. if (_is_lambda(), _is_azure_func(), _is_gcp_func(), _is_vercel()).count(True) != 1: return env if _is_lambda(): env["name"] = "aws.lambda" region = os.getenv("AWS_REGION") if region: env["region"] = region memory_mb = _getenv_int("AWS_LAMBDA_FUNCTION_MEMORY_SIZE") if memory_mb is not None: env["memory_mb"] = memory_mb elif _is_azure_func(): env["name"] = "azure.func" elif _is_gcp_func(): env["name"] = "gcp.func" region = os.getenv("FUNCTION_REGION") if region: env["region"] = region memory_mb = _getenv_int("FUNCTION_MEMORY_MB") if memory_mb is not None: env["memory_mb"] = memory_mb timeout_sec = _getenv_int("FUNCTION_TIMEOUT_SEC") if timeout_sec is not None: env["timeout_sec"] = timeout_sec elif _is_vercel(): env["name"] = "vercel" region = os.getenv("VERCEL_REGION") if region: env["region"] = region return env _MAX_METADATA_SIZE = 512 # See: https://github.com/mongodb/specifications/blob/5112bcc/source/mongodb-handshake/handshake.rst#limitations def _truncate_metadata(metadata: MutableMapping[str, Any]) -> None: """Perform metadata truncation.""" if len(bson.encode(metadata)) <= _MAX_METADATA_SIZE: return # 1. Omit fields from env except env.name. env_name = metadata.get("env", {}).get("name") if env_name: metadata["env"] = {"name": env_name} if len(bson.encode(metadata)) <= _MAX_METADATA_SIZE: return # 2. Omit fields from os except os.type. os_type = metadata.get("os", {}).get("type") if os_type: metadata["os"] = {"type": os_type} if len(bson.encode(metadata)) <= _MAX_METADATA_SIZE: return # 3. Omit the env document entirely. metadata.pop("env", None) encoded_size = len(bson.encode(metadata)) if encoded_size <= _MAX_METADATA_SIZE: return # 4. Truncate platform. overflow = encoded_size - _MAX_METADATA_SIZE plat = metadata.get("platform", "") if plat: plat = plat[:-overflow] if plat: metadata["platform"] = plat else: metadata.pop("platform", None) # If the first getaddrinfo call of this interpreter's life is on a thread, # while the main thread holds the import lock, getaddrinfo deadlocks trying # to import the IDNA codec. Import it here, where presumably we're on the # main thread, to avoid the deadlock. See PYTHON-607. "foo".encode("idna") def _raise_connection_failure( address: Any, error: Exception, msg_prefix: Optional[str] = None, timeout_details: Optional[dict[str, float]] = None, ) -> NoReturn: """Convert a socket.error to ConnectionFailure and raise it.""" host, port = address # If connecting to a Unix socket, port will be None. if port is not None: msg = "%s:%d: %s" % (host, port, error) else: msg = f"{host}: {error}" if msg_prefix: msg = msg_prefix + msg if "configured timeouts" not in msg: msg += format_timeout_details(timeout_details) if isinstance(error, socket.timeout): raise NetworkTimeout(msg) from error elif isinstance(error, SSLError) and "timed out" in str(error): # Eventlet does not distinguish TLS network timeouts from other # SSLErrors (https://github.com/eventlet/eventlet/issues/692). # Luckily, we can work around this limitation because the phrase # 'timed out' appears in all the timeout related SSLErrors raised. raise NetworkTimeout(msg) from error else: raise AutoReconnect(msg) from error def _cond_wait(condition: threading.Condition, deadline: Optional[float]) -> bool: timeout = deadline - time.monotonic() if deadline else None return condition.wait(timeout) def _get_timeout_details(options: PoolOptions) -> dict[str, float]: details = {} timeout = _csot.get_timeout() socket_timeout = options.socket_timeout connect_timeout = options.connect_timeout if timeout: details["timeoutMS"] = timeout * 1000 if socket_timeout and not timeout: details["socketTimeoutMS"] = socket_timeout * 1000 if connect_timeout: details["connectTimeoutMS"] = connect_timeout * 1000 return details def format_timeout_details(details: Optional[dict[str, float]]) -> str: result = "" if details: result += " (configured timeouts:" for timeout in ["socketTimeoutMS", "timeoutMS", "connectTimeoutMS"]: if timeout in details: result += f" {timeout}: {details[timeout]}ms," result = result[:-1] result += ")" return result class PoolOptions: """Read only connection pool options for a MongoClient. Should not be instantiated directly by application developers. Access a client's pool options via :attr:`~pymongo.client_options.ClientOptions.pool_options` instead:: pool_opts = client.options.pool_options pool_opts.max_pool_size pool_opts.min_pool_size """ __slots__ = ( "__max_pool_size", "__min_pool_size", "__max_idle_time_seconds", "__connect_timeout", "__socket_timeout", "__wait_queue_timeout", "__ssl_context", "__tls_allow_invalid_hostnames", "__event_listeners", "__appname", "__driver", "__metadata", "__compression_settings", "__max_connecting", "__pause_enabled", "__server_api", "__load_balanced", "__credentials", ) def __init__( self, max_pool_size: int = MAX_POOL_SIZE, min_pool_size: int = MIN_POOL_SIZE, max_idle_time_seconds: Optional[int] = MAX_IDLE_TIME_SEC, connect_timeout: Optional[float] = None, socket_timeout: Optional[float] = None, wait_queue_timeout: Optional[int] = WAIT_QUEUE_TIMEOUT, ssl_context: Optional[SSLContext] = None, tls_allow_invalid_hostnames: bool = False, event_listeners: Optional[_EventListeners] = None, appname: Optional[str] = None, driver: Optional[DriverInfo] = None, compression_settings: Optional[CompressionSettings] = None, max_connecting: int = MAX_CONNECTING, pause_enabled: bool = True, server_api: Optional[ServerApi] = None, load_balanced: Optional[bool] = None, credentials: Optional[MongoCredential] = None, ): self.__max_pool_size = max_pool_size self.__min_pool_size = min_pool_size self.__max_idle_time_seconds = max_idle_time_seconds self.__connect_timeout = connect_timeout self.__socket_timeout = socket_timeout self.__wait_queue_timeout = wait_queue_timeout self.__ssl_context = ssl_context self.__tls_allow_invalid_hostnames = tls_allow_invalid_hostnames self.__event_listeners = event_listeners self.__appname = appname self.__driver = driver self.__compression_settings = compression_settings self.__max_connecting = max_connecting self.__pause_enabled = pause_enabled self.__server_api = server_api self.__load_balanced = load_balanced self.__credentials = credentials self.__metadata = copy.deepcopy(_METADATA) if appname: self.__metadata["application"] = {"name": appname} # Combine the "driver" MongoClient option with PyMongo's info, like: # { # 'driver': { # 'name': 'PyMongo|MyDriver', # 'version': '4.2.0|1.2.3', # }, # 'platform': 'CPython 3.7.0|MyPlatform' # } if driver: if driver.name: self.__metadata["driver"]["name"] = "{}|{}".format( _METADATA["driver"]["name"], driver.name, ) if driver.version: self.__metadata["driver"]["version"] = "{}|{}".format( _METADATA["driver"]["version"], driver.version, ) if driver.platform: self.__metadata["platform"] = "{}|{}".format(_METADATA["platform"], driver.platform) env = _metadata_env() if env: self.__metadata["env"] = env _truncate_metadata(self.__metadata) @property def _credentials(self) -> Optional[MongoCredential]: """A :class:`~pymongo.auth.MongoCredentials` instance or None.""" return self.__credentials @property def non_default_options(self) -> dict[str, Any]: """The non-default options this pool was created with. Added for CMAP's :class:`PoolCreatedEvent`. """ opts = {} if self.__max_pool_size != MAX_POOL_SIZE: opts["maxPoolSize"] = self.__max_pool_size if self.__min_pool_size != MIN_POOL_SIZE: opts["minPoolSize"] = self.__min_pool_size if self.__max_idle_time_seconds != MAX_IDLE_TIME_SEC: assert self.__max_idle_time_seconds is not None opts["maxIdleTimeMS"] = self.__max_idle_time_seconds * 1000 if self.__wait_queue_timeout != WAIT_QUEUE_TIMEOUT: assert self.__wait_queue_timeout is not None opts["waitQueueTimeoutMS"] = self.__wait_queue_timeout * 1000 if self.__max_connecting != MAX_CONNECTING: opts["maxConnecting"] = self.__max_connecting return opts @property def max_pool_size(self) -> float: """The maximum allowable number of concurrent connections to each connected server. Requests to a server will block if there are `maxPoolSize` outstanding connections to the requested server. Defaults to 100. Cannot be 0. When a server's pool has reached `max_pool_size`, operations for that server block waiting for a socket to be returned to the pool. If ``waitQueueTimeoutMS`` is set, a blocked operation will raise :exc:`~pymongo.errors.ConnectionFailure` after a timeout. By default ``waitQueueTimeoutMS`` is not set. """ return self.__max_pool_size @property def min_pool_size(self) -> int: """The minimum required number of concurrent connections that the pool will maintain to each connected server. Default is 0. """ return self.__min_pool_size @property def max_connecting(self) -> int: """The maximum number of concurrent connection creation attempts per pool. Defaults to 2. """ return self.__max_connecting @property def pause_enabled(self) -> bool: return self.__pause_enabled @property def max_idle_time_seconds(self) -> Optional[int]: """The maximum number of seconds that a connection can remain idle in the pool before being removed and replaced. Defaults to `None` (no limit). """ return self.__max_idle_time_seconds @property def connect_timeout(self) -> Optional[float]: """How long a connection can take to be opened before timing out.""" return self.__connect_timeout @property def socket_timeout(self) -> Optional[float]: """How long a send or receive on a socket can take before timing out.""" return self.__socket_timeout @property def wait_queue_timeout(self) -> Optional[int]: """How long a thread will wait for a socket from the pool if the pool has no free sockets. """ return self.__wait_queue_timeout @property def _ssl_context(self) -> Optional[SSLContext]: """An SSLContext instance or None.""" return self.__ssl_context @property def tls_allow_invalid_hostnames(self) -> bool: """If True skip ssl.match_hostname.""" return self.__tls_allow_invalid_hostnames @property def _event_listeners(self) -> Optional[_EventListeners]: """An instance of pymongo.monitoring._EventListeners.""" return self.__event_listeners @property def appname(self) -> Optional[str]: """The application name, for sending with hello in server handshake.""" return self.__appname @property def driver(self) -> Optional[DriverInfo]: """Driver name and version, for sending with hello in handshake.""" return self.__driver @property def _compression_settings(self) -> Optional[CompressionSettings]: return self.__compression_settings @property def metadata(self) -> dict[str, Any]: """A dict of metadata about the application, driver, os, and platform.""" return self.__metadata.copy() @property def server_api(self) -> Optional[ServerApi]: """A pymongo.server_api.ServerApi or None.""" return self.__server_api @property def load_balanced(self) -> Optional[bool]: """True if this Pool is configured in load balanced mode.""" return self.__load_balanced class _CancellationContext: def __init__(self) -> None: self._cancelled = False def cancel(self) -> None: """Cancel this context.""" self._cancelled = True @property def cancelled(self) -> bool: """Was cancel called?""" return self._cancelled class Connection: """Store a connection with some metadata. :param conn: a raw connection object :param pool: a Pool instance :param address: the server's (host, port) :param id: the id of this socket in it's pool """ def __init__( self, conn: Union[socket.socket, _sslConn], pool: Pool, address: tuple[str, int], id: int ): self.pool_ref = weakref.ref(pool) self.conn = conn self.address = address self.id = id self.closed = False self.last_checkin_time = time.monotonic() self.performed_handshake = False self.is_writable: bool = False self.max_wire_version = MAX_WIRE_VERSION self.max_bson_size = MAX_BSON_SIZE self.max_message_size = MAX_MESSAGE_SIZE self.max_write_batch_size = MAX_WRITE_BATCH_SIZE self.supports_sessions = False self.hello_ok: bool = False self.is_mongos = False self.op_msg_enabled = False self.listeners = pool.opts._event_listeners self.enabled_for_cmap = pool.enabled_for_cmap self.compression_settings = pool.opts._compression_settings self.compression_context: Union[SnappyContext, ZlibContext, ZstdContext, None] = None self.socket_checker: SocketChecker = SocketChecker() self.oidc_token_gen_id: Optional[int] = None # Support for mechanism negotiation on the initial handshake. self.negotiated_mechs: Optional[list[str]] = None self.auth_ctx: Optional[_AuthContext] = None # The pool's generation changes with each reset() so we can close # sockets created before the last reset. self.pool_gen = pool.gen self.generation = self.pool_gen.get_overall() self.ready = False self.cancel_context: _CancellationContext = _CancellationContext() self.opts = pool.opts self.more_to_come: bool = False # For load balancer support. self.service_id: Optional[ObjectId] = None self.server_connection_id: Optional[int] = None # When executing a transaction in load balancing mode, this flag is # set to true to indicate that the session now owns the connection. self.pinned_txn = False self.pinned_cursor = False self.active = False self.last_timeout = self.opts.socket_timeout self.connect_rtt = 0.0 self._client_id = pool._client_id self.creation_time = time.monotonic() def set_conn_timeout(self, timeout: Optional[float]) -> None: """Cache last timeout to avoid duplicate calls to conn.settimeout.""" if timeout == self.last_timeout: return self.last_timeout = timeout self.conn.settimeout(timeout) def apply_timeout( self, client: MongoClient, cmd: Optional[MutableMapping[str, Any]] ) -> Optional[float]: # CSOT: use remaining timeout when set. timeout = _csot.remaining() if timeout is None: # Reset the socket timeout unless we're performing a streaming monitor check. if not self.more_to_come: self.set_conn_timeout(self.opts.socket_timeout) return None # RTT validation. rtt = _csot.get_rtt() if rtt is None: rtt = self.connect_rtt max_time_ms = timeout - rtt if max_time_ms < 0: timeout_details = _get_timeout_details(self.opts) formatted = format_timeout_details(timeout_details) # CSOT: raise an error without running the command since we know it will time out. errmsg = f"operation would exceed time limit, remaining timeout:{timeout:.5f} <= network round trip time:{rtt:.5f} {formatted}" raise ExecutionTimeout( errmsg, 50, {"ok": 0, "errmsg": errmsg, "code": 50}, self.max_wire_version, ) if cmd is not None: cmd["maxTimeMS"] = int(max_time_ms * 1000) self.set_conn_timeout(timeout) return timeout def pin_txn(self) -> None: self.pinned_txn = True assert not self.pinned_cursor def pin_cursor(self) -> None: self.pinned_cursor = True assert not self.pinned_txn def unpin(self) -> None: pool = self.pool_ref() if pool: pool.checkin(self) else: self.close_conn(ConnectionClosedReason.STALE) def hello_cmd(self) -> dict[str, Any]: # Handshake spec requires us to use OP_MSG+hello command for the # initial handshake in load balanced or stable API mode. if self.opts.server_api or self.hello_ok or self.opts.load_balanced: self.op_msg_enabled = True return {HelloCompat.CMD: 1} else: return {HelloCompat.LEGACY_CMD: 1, "helloOk": True} def hello(self) -> Hello[dict[str, Any]]: return self._hello(None, None, None) def _hello( self, cluster_time: Optional[ClusterTime], topology_version: Optional[Any], heartbeat_frequency: Optional[int], ) -> Hello[dict[str, Any]]: cmd = self.hello_cmd() performing_handshake = not self.performed_handshake awaitable = False if performing_handshake: self.performed_handshake = True cmd["client"] = self.opts.metadata if self.compression_settings: cmd["compression"] = self.compression_settings.compressors if self.opts.load_balanced: cmd["loadBalanced"] = True elif topology_version is not None: cmd["topologyVersion"] = topology_version assert heartbeat_frequency is not None cmd["maxAwaitTimeMS"] = int(heartbeat_frequency * 1000) awaitable = True # If connect_timeout is None there is no timeout. if self.opts.connect_timeout: self.set_conn_timeout(self.opts.connect_timeout + heartbeat_frequency) if not performing_handshake and cluster_time is not None: cmd["$clusterTime"] = cluster_time creds = self.opts._credentials if creds: if creds.mechanism == "DEFAULT" and creds.username: cmd["saslSupportedMechs"] = creds.source + "." + creds.username from pymongo import auth auth_ctx = auth._AuthContext.from_credentials(creds, self.address) if auth_ctx: speculative_authenticate = auth_ctx.speculate_command() if speculative_authenticate is not None: cmd["speculativeAuthenticate"] = speculative_authenticate else: auth_ctx = None if performing_handshake: start = time.monotonic() doc = self.command("admin", cmd, publish_events=False, exhaust_allowed=awaitable) if performing_handshake: self.connect_rtt = time.monotonic() - start hello = Hello(doc, awaitable=awaitable) self.is_writable = hello.is_writable self.max_wire_version = hello.max_wire_version self.max_bson_size = hello.max_bson_size self.max_message_size = hello.max_message_size self.max_write_batch_size = hello.max_write_batch_size self.supports_sessions = ( hello.logical_session_timeout_minutes is not None and hello.is_readable ) self.logical_session_timeout_minutes: Optional[int] = hello.logical_session_timeout_minutes self.hello_ok = hello.hello_ok self.is_repl = hello.server_type in ( SERVER_TYPE.RSPrimary, SERVER_TYPE.RSSecondary, SERVER_TYPE.RSArbiter, SERVER_TYPE.RSOther, SERVER_TYPE.RSGhost, ) self.is_standalone = hello.server_type == SERVER_TYPE.Standalone self.is_mongos = hello.server_type == SERVER_TYPE.Mongos if performing_handshake and self.compression_settings: ctx = self.compression_settings.get_compression_context(hello.compressors) self.compression_context = ctx self.op_msg_enabled = True self.server_connection_id = hello.connection_id if creds: self.negotiated_mechs = hello.sasl_supported_mechs if auth_ctx: auth_ctx.parse_response(hello) # type:ignore[arg-type] if auth_ctx.speculate_succeeded(): self.auth_ctx = auth_ctx if self.opts.load_balanced: if not hello.service_id: raise ConfigurationError( "Driver attempted to initialize in load balancing mode," " but the server does not support this mode" ) self.service_id = hello.service_id self.generation = self.pool_gen.get(self.service_id) return hello def _next_reply(self) -> dict[str, Any]: reply = self.receive_message(None) self.more_to_come = reply.more_to_come unpacked_docs = reply.unpack_response() response_doc = unpacked_docs[0] helpers._check_command_response(response_doc, self.max_wire_version) return response_doc @_handle_reauth def command( self, dbname: str, spec: MutableMapping[str, Any], read_preference: _ServerMode = ReadPreference.PRIMARY, codec_options: CodecOptions = DEFAULT_CODEC_OPTIONS, check: bool = True, allowable_errors: Optional[Sequence[Union[str, int]]] = None, read_concern: Optional[ReadConcern] = None, write_concern: Optional[WriteConcern] = None, parse_write_concern_error: bool = False, collation: Optional[_CollationIn] = None, session: Optional[ClientSession] = None, client: Optional[MongoClient] = None, retryable_write: bool = False, publish_events: bool = True, user_fields: Optional[Mapping[str, Any]] = None, exhaust_allowed: bool = False, ) -> dict[str, Any]: """Execute a command or raise an error. :param dbname: name of the database on which to run the command :param spec: a command document as a dict, SON, or mapping object :param read_preference: a read preference :param codec_options: a CodecOptions instance :param check: raise OperationFailure if there are errors :param allowable_errors: errors to ignore if `check` is True :param read_concern: The read concern for this command. :param write_concern: The write concern for this command. :param parse_write_concern_error: Whether to parse the ``writeConcernError`` field in the command response. :param collation: The collation for this command. :param session: optional ClientSession instance. :param client: optional MongoClient for gossipping $clusterTime. :param retryable_write: True if this command is a retryable write. :param publish_events: Should we publish events for this command? :param user_fields: Response fields that should be decoded using the TypeDecoders from codec_options, passed to bson._decode_all_selective. """ self.validate_session(client, session) session = _validate_session_write_concern(session, write_concern) # Ensure command name remains in first place. if not isinstance(spec, ORDERED_TYPES): # type:ignore[arg-type] spec = dict(spec) if not (write_concern is None or write_concern.acknowledged or collation is None): raise ConfigurationError("Collation is unsupported for unacknowledged writes.") self.add_server_api(spec) if session: session._apply_to(spec, retryable_write, read_preference, self) self.send_cluster_time(spec, session, client) listeners = self.listeners if publish_events else None unacknowledged = bool(write_concern and not write_concern.acknowledged) if self.op_msg_enabled: self._raise_if_not_writable(unacknowledged) try: return command( self, dbname, spec, self.is_mongos, read_preference, codec_options, session, client, check, allowable_errors, self.address, listeners, self.max_bson_size, read_concern, parse_write_concern_error=parse_write_concern_error, collation=collation, compression_ctx=self.compression_context, use_op_msg=self.op_msg_enabled, unacknowledged=unacknowledged, user_fields=user_fields, exhaust_allowed=exhaust_allowed, write_concern=write_concern, ) except (OperationFailure, NotPrimaryError): raise # Catch socket.error, KeyboardInterrupt, etc. and close ourselves. except BaseException as error: self._raise_connection_failure(error) def send_message(self, message: bytes, max_doc_size: int) -> None: """Send a raw BSON message or raise ConnectionFailure. If a network exception is raised, the socket is closed. """ if self.max_bson_size is not None and max_doc_size > self.max_bson_size: raise DocumentTooLarge( "BSON document too large (%d bytes) - the connected server " "supports BSON document sizes up to %d bytes." % (max_doc_size, self.max_bson_size) ) try: self.conn.sendall(message) except BaseException as error: self._raise_connection_failure(error) def receive_message(self, request_id: Optional[int]) -> Union[_OpReply, _OpMsg]: """Receive a raw BSON message or raise ConnectionFailure. If any exception is raised, the socket is closed. """ try: return receive_message(self, request_id, self.max_message_size) except BaseException as error: self._raise_connection_failure(error) def _raise_if_not_writable(self, unacknowledged: bool) -> None: """Raise NotPrimaryError on unacknowledged write if this socket is not writable. """ if unacknowledged and not self.is_writable: # Write won't succeed, bail as if we'd received a not primary error. raise NotPrimaryError("not primary", {"ok": 0, "errmsg": "not primary", "code": 10107}) def unack_write(self, msg: bytes, max_doc_size: int) -> None: """Send unack OP_MSG. Can raise ConnectionFailure or InvalidDocument. :param msg: bytes, an OP_MSG message. :param max_doc_size: size in bytes of the largest document in `msg`. """ self._raise_if_not_writable(True) self.send_message(msg, max_doc_size) def write_command( self, request_id: int, msg: bytes, codec_options: CodecOptions ) -> dict[str, Any]: """Send "insert" etc. command, returning response as a dict. Can raise ConnectionFailure or OperationFailure. :param request_id: an int. :param msg: bytes, the command message. """ self.send_message(msg, 0) reply = self.receive_message(request_id) result = reply.command_response(codec_options) # Raises NotPrimaryError or OperationFailure. helpers._check_command_response(result, self.max_wire_version) return result def authenticate(self, reauthenticate: bool = False) -> None: """Authenticate to the server if needed. Can raise ConnectionFailure or OperationFailure. """ # CMAP spec says to publish the ready event only after authenticating # the connection. if reauthenticate: if self.performed_handshake: # Existing auth_ctx is stale, remove it. self.auth_ctx = None self.ready = False if not self.ready: creds = self.opts._credentials if creds: from pymongo import auth auth.authenticate(creds, self, reauthenticate=reauthenticate) self.ready = True if self.enabled_for_cmap: assert self.listeners is not None duration = time.monotonic() - self.creation_time self.listeners.publish_connection_ready(self.address, self.id, duration) if _CONNECTION_LOGGER.isEnabledFor(logging.DEBUG): _debug_log( _CONNECTION_LOGGER, clientId=self._client_id, message=_ConnectionStatusMessage.CONN_READY, serverHost=self.address[0], serverPort=self.address[1], driverConnectionId=self.id, durationMS=duration, ) def validate_session( self, client: Optional[MongoClient], session: Optional[ClientSession] ) -> None: """Validate this session before use with client. Raises error if the client is not the one that created the session. """ if session: if session._client is not client: raise InvalidOperation("Can only use session with the MongoClient that started it") def close_conn(self, reason: Optional[str]) -> None: """Close this connection with a reason.""" if self.closed: return self._close_conn() if reason and self.enabled_for_cmap: assert self.listeners is not None self.listeners.publish_connection_closed(self.address, self.id, reason) if _CONNECTION_LOGGER.isEnabledFor(logging.DEBUG): _debug_log( _CONNECTION_LOGGER, clientId=self._client_id, message=_ConnectionStatusMessage.CONN_CLOSED, serverHost=self.address[0], serverPort=self.address[1], driverConnectionId=self.id, reason=_verbose_connection_error_reason(reason), error=reason, ) def _close_conn(self) -> None: """Close this connection.""" if self.closed: return self.closed = True self.cancel_context.cancel() # Note: We catch exceptions to avoid spurious errors on interpreter # shutdown. try: self.conn.close() except Exception: # noqa: S110 pass def conn_closed(self) -> bool: """Return True if we know socket has been closed, False otherwise.""" return self.socket_checker.socket_closed(self.conn) def send_cluster_time( self, command: MutableMapping[str, Any], session: Optional[ClientSession], client: Optional[MongoClient], ) -> None: """Add $clusterTime.""" if client: client._send_cluster_time(command, session) def add_server_api(self, command: MutableMapping[str, Any]) -> None: """Add server_api parameters.""" if self.opts.server_api: _add_to_command(command, self.opts.server_api) def update_last_checkin_time(self) -> None: self.last_checkin_time = time.monotonic() def update_is_writable(self, is_writable: bool) -> None: self.is_writable = is_writable def idle_time_seconds(self) -> float: """Seconds since this socket was last checked into its pool.""" return time.monotonic() - self.last_checkin_time def _raise_connection_failure(self, error: BaseException) -> NoReturn: # Catch *all* exceptions from socket methods and close the socket. In # regular Python, socket operations only raise socket.error, even if # the underlying cause was a Ctrl-C: a signal raised during socket.recv # is expressed as an EINTR error from poll. See internal_select_ex() in # socketmodule.c. All error codes from poll become socket.error at # first. Eventually in PyEval_EvalFrameEx the interpreter checks for # signals and throws KeyboardInterrupt into the current frame on the # main thread. # # But in Gevent and Eventlet, the polling mechanism (epoll, kqueue, # ..) is called in Python code, which experiences the signal as a # KeyboardInterrupt from the start, rather than as an initial # socket.error, so we catch that, close the socket, and reraise it. # # The connection closed event will be emitted later in checkin. if self.ready: reason = None else: reason = ConnectionClosedReason.ERROR self.close_conn(reason) # SSLError from PyOpenSSL inherits directly from Exception. if isinstance(error, (IOError, OSError, SSLError)): details = _get_timeout_details(self.opts) _raise_connection_failure(self.address, error, timeout_details=details) else: raise def __eq__(self, other: Any) -> bool: return self.conn == other.conn def __ne__(self, other: Any) -> bool: return not self == other def __hash__(self) -> int: return hash(self.conn) def __repr__(self) -> str: return "Connection({}){} at {}".format( repr(self.conn), self.closed and " CLOSED" or "", id(self), ) def _create_connection(address: _Address, options: PoolOptions) -> socket.socket: """Given (host, port) and PoolOptions, connect and return a socket object. Can raise socket.error. This is a modified version of create_connection from CPython >= 2.7. """ host, port = address # Check if dealing with a unix domain socket if host.endswith(".sock"): if not hasattr(socket, "AF_UNIX"): raise ConnectionFailure("UNIX-sockets are not supported on this system") sock = socket.socket(socket.AF_UNIX) # SOCK_CLOEXEC not supported for Unix sockets. _set_non_inheritable_non_atomic(sock.fileno()) try: sock.connect(host) return sock except OSError: sock.close() raise # Don't try IPv6 if we don't support it. Also skip it if host # is 'localhost' (::1 is fine). Avoids slow connect issues # like PYTHON-356. family = socket.AF_INET if socket.has_ipv6 and host != "localhost": family = socket.AF_UNSPEC err = None for res in socket.getaddrinfo(host, port, family, socket.SOCK_STREAM): af, socktype, proto, dummy, sa = res # SOCK_CLOEXEC was new in CPython 3.2, and only available on a limited # number of platforms (newer Linux and *BSD). Starting with CPython 3.4 # all file descriptors are created non-inheritable. See PEP 446. try: sock = socket.socket(af, socktype | getattr(socket, "SOCK_CLOEXEC", 0), proto) except OSError: # Can SOCK_CLOEXEC be defined even if the kernel doesn't support # it? sock = socket.socket(af, socktype, proto) # Fallback when SOCK_CLOEXEC isn't available. _set_non_inheritable_non_atomic(sock.fileno()) try: sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1) # CSOT: apply timeout to socket connect. timeout = _csot.remaining() if timeout is None: timeout = options.connect_timeout elif timeout <= 0: raise socket.timeout("timed out") sock.settimeout(timeout) sock.setsockopt(socket.SOL_SOCKET, socket.SO_KEEPALIVE, True) _set_keepalive_times(sock) sock.connect(sa) return sock except OSError as e: err = e sock.close() if err is not None: raise err else: # This likely means we tried to connect to an IPv6 only # host with an OS/kernel or Python interpreter that doesn't # support IPv6. The test case is Jython2.5.1 which doesn't # support IPv6 at all. raise OSError("getaddrinfo failed") def _configured_socket(address: _Address, options: PoolOptions) -> Union[socket.socket, _sslConn]: """Given (host, port) and PoolOptions, return a configured socket. Can raise socket.error, ConnectionFailure, or _CertificateError. Sets socket's SSL and timeout options. """ sock = _create_connection(address, options) ssl_context = options._ssl_context if ssl_context is None: sock.settimeout(options.socket_timeout) return sock host = address[0] try: # We have to pass hostname / ip address to wrap_socket # to use SSLContext.check_hostname. if HAS_SNI: ssl_sock = ssl_context.wrap_socket(sock, server_hostname=host) else: ssl_sock = ssl_context.wrap_socket(sock) except _CertificateError: sock.close() # Raise _CertificateError directly like we do after match_hostname # below. raise except (OSError, SSLError) as exc: sock.close() # We raise AutoReconnect for transient and permanent SSL handshake # failures alike. Permanent handshake failures, like protocol # mismatch, will be turned into ServerSelectionTimeoutErrors later. details = _get_timeout_details(options) _raise_connection_failure(address, exc, "SSL handshake failed: ", timeout_details=details) if ( ssl_context.verify_mode and not ssl_context.check_hostname and not options.tls_allow_invalid_hostnames ): try: ssl.match_hostname(ssl_sock.getpeercert(), hostname=host) except _CertificateError: ssl_sock.close() raise ssl_sock.settimeout(options.socket_timeout) return ssl_sock class _PoolClosedError(PyMongoError): """Internal error raised when a thread tries to get a connection from a closed pool. """ class _PoolGeneration: def __init__(self) -> None: # Maps service_id to generation. self._generations: dict[ObjectId, int] = collections.defaultdict(int) # Overall pool generation. self._generation = 0 def get(self, service_id: Optional[ObjectId]) -> int: """Get the generation for the given service_id.""" if service_id is None: return self._generation return self._generations[service_id] def get_overall(self) -> int: """Get the Pool's overall generation.""" return self._generation def inc(self, service_id: Optional[ObjectId]) -> None: """Increment the generation for the given service_id.""" self._generation += 1 if service_id is None: for service_id in self._generations: self._generations[service_id] += 1 else: self._generations[service_id] += 1 def stale(self, gen: int, service_id: Optional[ObjectId]) -> bool: """Return if the given generation for a given service_id is stale.""" return gen != self.get(service_id) class PoolState: PAUSED = 1 READY = 2 CLOSED = 3 # Do *not* explicitly inherit from object or Jython won't call __del__ # http://bugs.jython.org/issue1057 class Pool: def __init__( self, address: _Address, options: PoolOptions, handshake: bool = True, client_id: Optional[ObjectId] = None, ): """ :param address: a (hostname, port) tuple :param options: a PoolOptions instance :param handshake: whether to call hello for each new Connection """ if options.pause_enabled: self.state = PoolState.PAUSED else: self.state = PoolState.READY # Check a socket's health with socket_closed() every once in a while. # Can override for testing: 0 to always check, None to never check. self._check_interval_seconds = 1 # LIFO pool. Sockets are ordered on idle time. Sockets claimed # and returned to pool from the left side. Stale sockets removed # from the right side. self.conns: collections.deque = collections.deque() self.active_contexts: set[_CancellationContext] = set() self.lock = _create_lock() self.active_sockets = 0 # Monotonically increasing connection ID required for CMAP Events. self.next_connection_id = 1 # Track whether the sockets in this pool are writeable or not. self.is_writable: Optional[bool] = None # Keep track of resets, so we notice sockets created before the most # recent reset and close them. # self.generation = 0 self.gen = _PoolGeneration() self.pid = os.getpid() self.address = address self.opts = options self.handshake = handshake # Don't publish events in Monitor pools. self.enabled_for_cmap = ( self.handshake and self.opts._event_listeners is not None and self.opts._event_listeners.enabled_for_cmap ) # The first portion of the wait queue. # Enforces: maxPoolSize # Also used for: clearing the wait queue self.size_cond = threading.Condition(self.lock) self.requests = 0 self.max_pool_size = self.opts.max_pool_size if not self.max_pool_size: self.max_pool_size = float("inf") # The second portion of the wait queue. # Enforces: maxConnecting # Also used for: clearing the wait queue self._max_connecting_cond = threading.Condition(self.lock) self._max_connecting = self.opts.max_connecting self._pending = 0 self._client_id = client_id if self.enabled_for_cmap: assert self.opts._event_listeners is not None self.opts._event_listeners.publish_pool_created( self.address, self.opts.non_default_options ) if _CONNECTION_LOGGER.isEnabledFor(logging.DEBUG): _debug_log( _CONNECTION_LOGGER, clientId=self._client_id, message=_ConnectionStatusMessage.POOL_CREATED, serverHost=self.address[0], serverPort=self.address[1], **self.opts.non_default_options, ) # Similar to active_sockets but includes threads in the wait queue. self.operation_count: int = 0 # Retain references to pinned connections to prevent the CPython GC # from thinking that a cursor's pinned connection can be GC'd when the # cursor is GC'd (see PYTHON-2751). self.__pinned_sockets: set[Connection] = set() self.ncursors = 0 self.ntxns = 0 def ready(self) -> None: # Take the lock to avoid the race condition described in PYTHON-2699. with self.lock: if self.state != PoolState.READY: self.state = PoolState.READY if self.enabled_for_cmap: assert self.opts._event_listeners is not None self.opts._event_listeners.publish_pool_ready(self.address) if _CONNECTION_LOGGER.isEnabledFor(logging.DEBUG): _debug_log( _CONNECTION_LOGGER, clientId=self._client_id, message=_ConnectionStatusMessage.POOL_READY, serverHost=self.address[0], serverPort=self.address[1], ) @property def closed(self) -> bool: return self.state == PoolState.CLOSED def _reset( self, close: bool, pause: bool = True, service_id: Optional[ObjectId] = None, interrupt_connections: bool = False, ) -> None: old_state = self.state with self.size_cond: if self.closed: return if self.opts.pause_enabled and pause and not self.opts.load_balanced: old_state, self.state = self.state, PoolState.PAUSED self.gen.inc(service_id) newpid = os.getpid() if self.pid != newpid: self.pid = newpid self.active_sockets = 0 self.operation_count = 0 if service_id is None: sockets, self.conns = self.conns, collections.deque() else: discard: collections.deque = collections.deque() keep: collections.deque = collections.deque() for conn in self.conns: if conn.service_id == service_id: discard.append(conn) else: keep.append(conn) sockets = discard self.conns = keep if close: self.state = PoolState.CLOSED # Clear the wait queue self._max_connecting_cond.notify_all() self.size_cond.notify_all() if interrupt_connections: for context in self.active_contexts: context.cancel() listeners = self.opts._event_listeners # CMAP spec says that close() MUST close sockets before publishing the # PoolClosedEvent but that reset() SHOULD close sockets *after* # publishing the PoolClearedEvent. if close: for conn in sockets: conn.close_conn(ConnectionClosedReason.POOL_CLOSED) if self.enabled_for_cmap: assert listeners is not None listeners.publish_pool_closed(self.address) if _CONNECTION_LOGGER.isEnabledFor(logging.DEBUG): _debug_log( _CONNECTION_LOGGER, clientId=self._client_id, message=_ConnectionStatusMessage.POOL_CLOSED, serverHost=self.address[0], serverPort=self.address[1], ) else: if old_state != PoolState.PAUSED and self.enabled_for_cmap: assert listeners is not None listeners.publish_pool_cleared( self.address, service_id=service_id, interrupt_connections=interrupt_connections, ) if _CONNECTION_LOGGER.isEnabledFor(logging.DEBUG): _debug_log( _CONNECTION_LOGGER, clientId=self._client_id, message=_ConnectionStatusMessage.POOL_CLEARED, serverHost=self.address[0], serverPort=self.address[1], serviceId=service_id, ) for conn in sockets: conn.close_conn(ConnectionClosedReason.STALE) def update_is_writable(self, is_writable: Optional[bool]) -> None: """Updates the is_writable attribute on all sockets currently in the Pool. """ self.is_writable = is_writable with self.lock: for _socket in self.conns: _socket.update_is_writable(self.is_writable) def reset( self, service_id: Optional[ObjectId] = None, interrupt_connections: bool = False ) -> None: self._reset(close=False, service_id=service_id, interrupt_connections=interrupt_connections) def reset_without_pause(self) -> None: self._reset(close=False, pause=False) def close(self) -> None: self._reset(close=True) def stale_generation(self, gen: int, service_id: Optional[ObjectId]) -> bool: return self.gen.stale(gen, service_id) def remove_stale_sockets(self, reference_generation: int) -> None: """Removes stale sockets then adds new ones if pool is too small and has not been reset. The `reference_generation` argument specifies the `generation` at the point in time this operation was requested on the pool. """ # Take the lock to avoid the race condition described in PYTHON-2699. with self.lock: if self.state != PoolState.READY: return if self.opts.max_idle_time_seconds is not None: with self.lock: while ( self.conns and self.conns[-1].idle_time_seconds() > self.opts.max_idle_time_seconds ): conn = self.conns.pop() conn.close_conn(ConnectionClosedReason.IDLE) while True: with self.size_cond: # There are enough sockets in the pool. if len(self.conns) + self.active_sockets >= self.opts.min_pool_size: return if self.requests >= self.opts.min_pool_size: return self.requests += 1 incremented = False try: with self._max_connecting_cond: # If maxConnecting connections are already being created # by this pool then try again later instead of waiting. if self._pending >= self._max_connecting: return self._pending += 1 incremented = True conn = self.connect() with self.lock: # Close connection and return if the pool was reset during # socket creation or while acquiring the pool lock. if self.gen.get_overall() != reference_generation: conn.close_conn(ConnectionClosedReason.STALE) return self.conns.appendleft(conn) self.active_contexts.discard(conn.cancel_context) finally: if incremented: # Notify after adding the socket to the pool. with self._max_connecting_cond: self._pending -= 1 self._max_connecting_cond.notify() with self.size_cond: self.requests -= 1 self.size_cond.notify() def connect(self, handler: Optional[_MongoClientErrorHandler] = None) -> Connection: """Connect to Mongo and return a new Connection. Can raise ConnectionFailure. Note that the pool does not keep a reference to the socket -- you must call checkin() when you're done with it. """ with self.lock: conn_id = self.next_connection_id self.next_connection_id += 1 listeners = self.opts._event_listeners if self.enabled_for_cmap: assert listeners is not None listeners.publish_connection_created(self.address, conn_id) if _CONNECTION_LOGGER.isEnabledFor(logging.DEBUG): _debug_log( _CONNECTION_LOGGER, clientId=self._client_id, message=_ConnectionStatusMessage.CONN_CREATED, serverHost=self.address[0], serverPort=self.address[1], driverConnectionId=conn_id, ) try: sock = _configured_socket(self.address, self.opts) except BaseException as error: if self.enabled_for_cmap: assert listeners is not None listeners.publish_connection_closed( self.address, conn_id, ConnectionClosedReason.ERROR ) if _CONNECTION_LOGGER.isEnabledFor(logging.DEBUG): _debug_log( _CONNECTION_LOGGER, clientId=self._client_id, message=_ConnectionStatusMessage.CONN_CLOSED, serverHost=self.address[0], serverPort=self.address[1], driverConnectionId=conn_id, reason=_verbose_connection_error_reason(ConnectionClosedReason.ERROR), error=ConnectionClosedReason.ERROR, ) if isinstance(error, (IOError, OSError, SSLError)): details = _get_timeout_details(self.opts) _raise_connection_failure(self.address, error, timeout_details=details) raise conn = Connection(sock, self, self.address, conn_id) # type: ignore[arg-type] with self.lock: self.active_contexts.add(conn.cancel_context) try: if self.handshake: conn.hello() self.is_writable = conn.is_writable if handler: handler.contribute_socket(conn, completed_handshake=False) conn.authenticate() except BaseException: conn.close_conn(ConnectionClosedReason.ERROR) raise return conn @contextlib.contextmanager def checkout(self, handler: Optional[_MongoClientErrorHandler] = None) -> Iterator[Connection]: """Get a connection from the pool. Use with a "with" statement. Returns a :class:`Connection` object wrapping a connected :class:`socket.socket`. This method should always be used in a with-statement:: with pool.get_conn() as connection: connection.send_message(msg) data = connection.receive_message(op_code, request_id) Can raise ConnectionFailure or OperationFailure. :param handler: A _MongoClientErrorHandler. """ listeners = self.opts._event_listeners checkout_started_time = time.monotonic() if self.enabled_for_cmap: assert listeners is not None listeners.publish_connection_check_out_started(self.address) if _CONNECTION_LOGGER.isEnabledFor(logging.DEBUG): _debug_log( _CONNECTION_LOGGER, clientId=self._client_id, message=_ConnectionStatusMessage.CHECKOUT_STARTED, serverHost=self.address[0], serverPort=self.address[1], ) conn = self._get_conn(checkout_started_time, handler=handler) if self.enabled_for_cmap: assert listeners is not None duration = time.monotonic() - checkout_started_time listeners.publish_connection_checked_out(self.address, conn.id, duration) if _CONNECTION_LOGGER.isEnabledFor(logging.DEBUG): _debug_log( _CONNECTION_LOGGER, clientId=self._client_id, message=_ConnectionStatusMessage.CHECKOUT_SUCCEEDED, serverHost=self.address[0], serverPort=self.address[1], driverConnectionId=conn.id, durationMS=duration, ) try: with self.lock: self.active_contexts.add(conn.cancel_context) yield conn except BaseException: # Exception in caller. Ensure the connection gets returned. # Note that when pinned is True, the session owns the # connection and it is responsible for checking the connection # back into the pool. pinned = conn.pinned_txn or conn.pinned_cursor if handler: # Perform SDAM error handling rules while the connection is # still checked out. exc_type, exc_val, _ = sys.exc_info() handler.handle(exc_type, exc_val) if not pinned and conn.active: self.checkin(conn) raise if conn.pinned_txn: with self.lock: self.__pinned_sockets.add(conn) self.ntxns += 1 elif conn.pinned_cursor: with self.lock: self.__pinned_sockets.add(conn) self.ncursors += 1 elif conn.active: self.checkin(conn) def _raise_if_not_ready(self, checkout_started_time: float, emit_event: bool) -> None: if self.state != PoolState.READY: if self.enabled_for_cmap and emit_event: assert self.opts._event_listeners is not None duration = time.monotonic() - checkout_started_time self.opts._event_listeners.publish_connection_check_out_failed( self.address, ConnectionCheckOutFailedReason.CONN_ERROR, duration ) if _CONNECTION_LOGGER.isEnabledFor(logging.DEBUG): _debug_log( _CONNECTION_LOGGER, clientId=self._client_id, message=_ConnectionStatusMessage.CHECKOUT_FAILED, serverHost=self.address[0], serverPort=self.address[1], reason="An error occurred while trying to establish a new connection", error=ConnectionCheckOutFailedReason.CONN_ERROR, durationMS=duration, ) details = _get_timeout_details(self.opts) _raise_connection_failure( self.address, AutoReconnect("connection pool paused"), timeout_details=details ) def _get_conn( self, checkout_started_time: float, handler: Optional[_MongoClientErrorHandler] = None ) -> Connection: """Get or create a Connection. Can raise ConnectionFailure.""" # We use the pid here to avoid issues with fork / multiprocessing. # See test.test_client:TestClient.test_fork for an example of # what could go wrong otherwise if self.pid != os.getpid(): self.reset_without_pause() if self.closed: if self.enabled_for_cmap: assert self.opts._event_listeners is not None duration = time.monotonic() - checkout_started_time self.opts._event_listeners.publish_connection_check_out_failed( self.address, ConnectionCheckOutFailedReason.POOL_CLOSED, duration ) if _CONNECTION_LOGGER.isEnabledFor(logging.DEBUG): _debug_log( _CONNECTION_LOGGER, clientId=self._client_id, message=_ConnectionStatusMessage.CHECKOUT_FAILED, serverHost=self.address[0], serverPort=self.address[1], reason="Connection pool was closed", error=ConnectionCheckOutFailedReason.POOL_CLOSED, durationMS=duration, ) raise _PoolClosedError( "Attempted to check out a connection from closed connection pool" ) with self.lock: self.operation_count += 1 # Get a free socket or create one. if _csot.get_timeout(): deadline = _csot.get_deadline() elif self.opts.wait_queue_timeout: deadline = time.monotonic() + self.opts.wait_queue_timeout else: deadline = None with self.size_cond: self._raise_if_not_ready(checkout_started_time, emit_event=True) while not (self.requests < self.max_pool_size): if not _cond_wait(self.size_cond, deadline): # Timed out, notify the next thread to ensure a # timeout doesn't consume the condition. if self.requests < self.max_pool_size: self.size_cond.notify() self._raise_wait_queue_timeout(checkout_started_time) self._raise_if_not_ready(checkout_started_time, emit_event=True) self.requests += 1 # We've now acquired the semaphore and must release it on error. conn = None incremented = False emitted_event = False try: with self.lock: self.active_sockets += 1 incremented = True while conn is None: # CMAP: we MUST wait for either maxConnecting OR for a socket # to be checked back into the pool. with self._max_connecting_cond: self._raise_if_not_ready(checkout_started_time, emit_event=False) while not (self.conns or self._pending < self._max_connecting): if not _cond_wait(self._max_connecting_cond, deadline): # Timed out, notify the next thread to ensure a # timeout doesn't consume the condition. if self.conns or self._pending < self._max_connecting: self._max_connecting_cond.notify() emitted_event = True self._raise_wait_queue_timeout(checkout_started_time) self._raise_if_not_ready(checkout_started_time, emit_event=False) try: conn = self.conns.popleft() except IndexError: self._pending += 1 if conn: # We got a socket from the pool if self._perished(conn): conn = None continue else: # We need to create a new connection try: conn = self.connect(handler=handler) finally: with self._max_connecting_cond: self._pending -= 1 self._max_connecting_cond.notify() except BaseException: if conn: # We checked out a socket but authentication failed. conn.close_conn(ConnectionClosedReason.ERROR) with self.size_cond: self.requests -= 1 if incremented: self.active_sockets -= 1 self.size_cond.notify() if self.enabled_for_cmap and not emitted_event: assert self.opts._event_listeners is not None duration = time.monotonic() - checkout_started_time self.opts._event_listeners.publish_connection_check_out_failed( self.address, ConnectionCheckOutFailedReason.CONN_ERROR, duration ) if _CONNECTION_LOGGER.isEnabledFor(logging.DEBUG): _debug_log( _CONNECTION_LOGGER, clientId=self._client_id, message=_ConnectionStatusMessage.CHECKOUT_FAILED, serverHost=self.address[0], serverPort=self.address[1], reason="An error occurred while trying to establish a new connection", error=ConnectionCheckOutFailedReason.CONN_ERROR, durationMS=duration, ) raise conn.active = True return conn def checkin(self, conn: Connection) -> None: """Return the connection to the pool, or if it's closed discard it. :param conn: The connection to check into the pool. """ txn = conn.pinned_txn cursor = conn.pinned_cursor conn.active = False conn.pinned_txn = False conn.pinned_cursor = False self.__pinned_sockets.discard(conn) listeners = self.opts._event_listeners with self.lock: self.active_contexts.discard(conn.cancel_context) if self.enabled_for_cmap: assert listeners is not None listeners.publish_connection_checked_in(self.address, conn.id) if _CONNECTION_LOGGER.isEnabledFor(logging.DEBUG): _debug_log( _CONNECTION_LOGGER, clientId=self._client_id, message=_ConnectionStatusMessage.CHECKEDIN, serverHost=self.address[0], serverPort=self.address[1], driverConnectionId=conn.id, ) if self.pid != os.getpid(): self.reset_without_pause() else: if self.closed: conn.close_conn(ConnectionClosedReason.POOL_CLOSED) elif conn.closed: # CMAP requires the closed event be emitted after the check in. if self.enabled_for_cmap: assert listeners is not None listeners.publish_connection_closed( self.address, conn.id, ConnectionClosedReason.ERROR ) if _CONNECTION_LOGGER.isEnabledFor(logging.DEBUG): _debug_log( _CONNECTION_LOGGER, clientId=self._client_id, message=_ConnectionStatusMessage.CONN_CLOSED, serverHost=self.address[0], serverPort=self.address[1], driverConnectionId=conn.id, reason=_verbose_connection_error_reason(ConnectionClosedReason.ERROR), error=ConnectionClosedReason.ERROR, ) else: with self.lock: # Hold the lock to ensure this section does not race with # Pool.reset(). if self.stale_generation(conn.generation, conn.service_id): conn.close_conn(ConnectionClosedReason.STALE) else: conn.update_last_checkin_time() conn.update_is_writable(bool(self.is_writable)) self.conns.appendleft(conn) # Notify any threads waiting to create a connection. self._max_connecting_cond.notify() with self.size_cond: if txn: self.ntxns -= 1 elif cursor: self.ncursors -= 1 self.requests -= 1 self.active_sockets -= 1 self.operation_count -= 1 self.size_cond.notify() def _perished(self, conn: Connection) -> bool: """Return True and close the connection if it is "perished". This side-effecty function checks if this socket has been idle for for longer than the max idle time, or if the socket has been closed by some external network error, or if the socket's generation is outdated. Checking sockets lets us avoid seeing *some* :class:`~pymongo.errors.AutoReconnect` exceptions on server hiccups, etc. We only check if the socket was closed by an external error if it has been > 1 second since the socket was checked into the pool, to keep performance reasonable - we can't avoid AutoReconnects completely anyway. """ idle_time_seconds = conn.idle_time_seconds() # If socket is idle, open a new one. if ( self.opts.max_idle_time_seconds is not None and idle_time_seconds > self.opts.max_idle_time_seconds ): conn.close_conn(ConnectionClosedReason.IDLE) return True if self._check_interval_seconds is not None and ( self._check_interval_seconds == 0 or idle_time_seconds > self._check_interval_seconds ): if conn.conn_closed(): conn.close_conn(ConnectionClosedReason.ERROR) return True if self.stale_generation(conn.generation, conn.service_id): conn.close_conn(ConnectionClosedReason.STALE) return True return False def _raise_wait_queue_timeout(self, checkout_started_time: float) -> NoReturn: listeners = self.opts._event_listeners if self.enabled_for_cmap: assert listeners is not None duration = time.monotonic() - checkout_started_time listeners.publish_connection_check_out_failed( self.address, ConnectionCheckOutFailedReason.TIMEOUT, duration ) if _CONNECTION_LOGGER.isEnabledFor(logging.DEBUG): _debug_log( _CONNECTION_LOGGER, clientId=self._client_id, message=_ConnectionStatusMessage.CHECKOUT_FAILED, serverHost=self.address[0], serverPort=self.address[1], reason="Wait queue timeout elapsed without a connection becoming available", error=ConnectionCheckOutFailedReason.TIMEOUT, durationMS=duration, ) timeout = _csot.get_timeout() or self.opts.wait_queue_timeout if self.opts.load_balanced: other_ops = self.active_sockets - self.ncursors - self.ntxns raise WaitQueueTimeoutError( "Timeout waiting for connection from the connection pool. " "maxPoolSize: {}, connections in use by cursors: {}, " "connections in use by transactions: {}, connections in use " "by other operations: {}, timeout: {}".format( self.opts.max_pool_size, self.ncursors, self.ntxns, other_ops, timeout, ) ) raise WaitQueueTimeoutError( "Timed out while checking out a connection from connection pool. " f"maxPoolSize: {self.opts.max_pool_size}, timeout: {timeout}" ) def __del__(self) -> None: # Avoid ResourceWarnings in Python 3 # Close all sockets without calling reset() or close() because it is # not safe to acquire a lock in __del__. for conn in self.conns: conn.close_conn(None) mongodb-mongo-python-driver-509e9b7/pymongo/py.typed000066400000000000000000000002521462766011000226230ustar00rootroot00000000000000# PEP-561 Support File. # "Package maintainers who wish to support type checking of their code MUST add a marker file named py.typed to their package supporting typing". mongodb-mongo-python-driver-509e9b7/pymongo/pyopenssl_context.py000066400000000000000000000401351462766011000253020ustar00rootroot00000000000000# Copyright 2019-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. """A CPython compatible SSLContext implementation wrapping PyOpenSSL's context. """ from __future__ import annotations import socket as _socket import ssl as _stdlibssl import sys as _sys import time as _time from errno import EINTR as _EINTR from ipaddress import ip_address as _ip_address from typing import TYPE_CHECKING, Any, Callable, Optional, TypeVar, Union import cryptography.x509 as x509 import service_identity from OpenSSL import SSL as _SSL from OpenSSL import crypto as _crypto from pymongo.errors import ConfigurationError as _ConfigurationError from pymongo.errors import _CertificateError # type:ignore[attr-defined] from pymongo.ocsp_cache import _OCSPCache from pymongo.ocsp_support import _load_trusted_ca_certs, _ocsp_callback from pymongo.socket_checker import SocketChecker as _SocketChecker from pymongo.socket_checker import _errno_from_exception from pymongo.write_concern import validate_boolean if TYPE_CHECKING: from ssl import VerifyMode _T = TypeVar("_T") try: import certifi _HAVE_CERTIFI = True except ImportError: _HAVE_CERTIFI = False PROTOCOL_SSLv23 = _SSL.SSLv23_METHOD # Always available OP_NO_SSLv2 = _SSL.OP_NO_SSLv2 OP_NO_SSLv3 = _SSL.OP_NO_SSLv3 OP_NO_COMPRESSION = _SSL.OP_NO_COMPRESSION # This isn't currently documented for PyOpenSSL OP_NO_RENEGOTIATION = getattr(_SSL, "OP_NO_RENEGOTIATION", 0) # Always available HAS_SNI = True IS_PYOPENSSL = True # Base Exception class SSLError = _SSL.Error # https://github.com/python/cpython/blob/v3.8.0/Modules/_ssl.c#L2995-L3002 _VERIFY_MAP = { _stdlibssl.CERT_NONE: _SSL.VERIFY_NONE, _stdlibssl.CERT_OPTIONAL: _SSL.VERIFY_PEER, _stdlibssl.CERT_REQUIRED: _SSL.VERIFY_PEER | _SSL.VERIFY_FAIL_IF_NO_PEER_CERT, } _REVERSE_VERIFY_MAP = {value: key for key, value in _VERIFY_MAP.items()} # For SNI support. According to RFC6066, section 3, IPv4 and IPv6 literals are # not permitted for SNI hostname. def _is_ip_address(address: Any) -> bool: try: _ip_address(address) return True except (ValueError, UnicodeError): return False # According to the docs for socket.send it can raise # WantX509LookupError and should be retried. BLOCKING_IO_ERRORS = (_SSL.WantReadError, _SSL.WantWriteError, _SSL.WantX509LookupError) def _ragged_eof(exc: BaseException) -> bool: """Return True if the OpenSSL.SSL.SysCallError is a ragged EOF.""" return exc.args == (-1, "Unexpected EOF") # https://github.com/pyca/pyopenssl/issues/168 # https://github.com/pyca/pyopenssl/issues/176 # https://docs.python.org/3/library/ssl.html#notes-on-non-blocking-sockets class _sslConn(_SSL.Connection): def __init__( self, ctx: _SSL.Context, sock: Optional[_socket.socket], suppress_ragged_eofs: bool ): self.socket_checker = _SocketChecker() self.suppress_ragged_eofs = suppress_ragged_eofs super().__init__(ctx, sock) def _call(self, call: Callable[..., _T], *args: Any, **kwargs: Any) -> _T: timeout = self.gettimeout() if timeout: start = _time.monotonic() while True: try: return call(*args, **kwargs) except BLOCKING_IO_ERRORS as exc: # Check for closed socket. if self.fileno() == -1: if timeout and _time.monotonic() - start > timeout: raise _socket.timeout("timed out") from None raise SSLError("Underlying socket has been closed") from None if isinstance(exc, _SSL.WantReadError): want_read = True want_write = False elif isinstance(exc, _SSL.WantWriteError): want_read = False want_write = True else: want_read = True want_write = True self.socket_checker.select(self, want_read, want_write, timeout) if timeout and _time.monotonic() - start > timeout: raise _socket.timeout("timed out") from None continue def do_handshake(self, *args: Any, **kwargs: Any) -> None: return self._call(super().do_handshake, *args, **kwargs) def recv(self, *args: Any, **kwargs: Any) -> bytes: try: return self._call(super().recv, *args, **kwargs) except _SSL.SysCallError as exc: # Suppress ragged EOFs to match the stdlib. if self.suppress_ragged_eofs and _ragged_eof(exc): return b"" raise def recv_into(self, *args: Any, **kwargs: Any) -> int: try: return self._call(super().recv_into, *args, **kwargs) except _SSL.SysCallError as exc: # Suppress ragged EOFs to match the stdlib. if self.suppress_ragged_eofs and _ragged_eof(exc): return 0 raise def sendall(self, buf: bytes, flags: int = 0) -> None: # type: ignore[override] view = memoryview(buf) total_length = len(buf) total_sent = 0 while total_sent < total_length: try: sent = self._call(super().send, view[total_sent:], flags) # XXX: It's not clear if this can actually happen. PyOpenSSL # doesn't appear to have any interrupt handling, nor any interrupt # errors for OpenSSL connections. except OSError as exc: if _errno_from_exception(exc) == _EINTR: continue raise # https://github.com/pyca/pyopenssl/blob/19.1.0/src/OpenSSL/SSL.py#L1756 # https://www.openssl.org/docs/man1.0.2/man3/SSL_write.html if sent <= 0: raise OSError("connection closed") total_sent += sent class _CallbackData: """Data class which is passed to the OCSP callback.""" def __init__(self) -> None: self.trusted_ca_certs: Optional[list[x509.Certificate]] = None self.check_ocsp_endpoint: Optional[bool] = None self.ocsp_response_cache = _OCSPCache() class SSLContext: """A CPython compatible SSLContext implementation wrapping PyOpenSSL's context. """ __slots__ = ("_protocol", "_ctx", "_callback_data", "_check_hostname") def __init__(self, protocol: int): self._protocol = protocol self._ctx = _SSL.Context(self._protocol) self._callback_data = _CallbackData() self._check_hostname = True # OCSP # XXX: Find a better place to do this someday, since this is client # side configuration and wrap_socket tries to support both client and # server side sockets. self._callback_data.check_ocsp_endpoint = True self._ctx.set_ocsp_client_callback(callback=_ocsp_callback, data=self._callback_data) @property def protocol(self) -> int: """The protocol version chosen when constructing the context. This attribute is read-only. """ return self._protocol def __get_verify_mode(self) -> VerifyMode: """Whether to try to verify other peers' certificates and how to behave if verification fails. This attribute must be one of ssl.CERT_NONE, ssl.CERT_OPTIONAL or ssl.CERT_REQUIRED. """ return _REVERSE_VERIFY_MAP[self._ctx.get_verify_mode()] def __set_verify_mode(self, value: VerifyMode) -> None: """Setter for verify_mode.""" def _cb( _connobj: _SSL.Connection, _x509obj: _crypto.X509, _errnum: int, _errdepth: int, retcode: int, ) -> bool: # It seems we don't need to do anything here. Twisted doesn't, # and OpenSSL's SSL_CTX_set_verify let's you pass NULL # for the callback option. It's weird that PyOpenSSL requires # this. # This is optional in pyopenssl >= 20 and can be removed once minimum # supported version is bumped # See: pyopenssl.org/en/latest/changelog.html#id47 return bool(retcode) self._ctx.set_verify(_VERIFY_MAP[value], _cb) verify_mode = property(__get_verify_mode, __set_verify_mode) def __get_check_hostname(self) -> bool: return self._check_hostname def __set_check_hostname(self, value: Any) -> None: validate_boolean("check_hostname", value) self._check_hostname = value check_hostname = property(__get_check_hostname, __set_check_hostname) def __get_check_ocsp_endpoint(self) -> Optional[bool]: return self._callback_data.check_ocsp_endpoint def __set_check_ocsp_endpoint(self, value: bool) -> None: validate_boolean("check_ocsp", value) self._callback_data.check_ocsp_endpoint = value check_ocsp_endpoint = property(__get_check_ocsp_endpoint, __set_check_ocsp_endpoint) def __get_options(self) -> None: # Calling set_options adds the option to the existing bitmask and # returns the new bitmask. # https://www.pyopenssl.org/en/stable/api/ssl.html#OpenSSL.SSL.Context.set_options return self._ctx.set_options(0) def __set_options(self, value: int) -> None: # Explicitly convert to int, since newer CPython versions # use enum.IntFlag for options. The values are the same # regardless of implementation. self._ctx.set_options(int(value)) options = property(__get_options, __set_options) def load_cert_chain( self, certfile: Union[str, bytes], keyfile: Union[str, bytes, None] = None, password: Optional[str] = None, ) -> None: """Load a private key and the corresponding certificate. The certfile string must be the path to a single file in PEM format containing the certificate as well as any number of CA certificates needed to establish the certificate's authenticity. The keyfile string, if present, must point to a file containing the private key. Otherwise the private key will be taken from certfile as well. """ # Match CPython behavior # https://github.com/python/cpython/blob/v3.8.0/Modules/_ssl.c#L3930-L3971 # Password callback MUST be set first or it will be ignored. if password: def _pwcb(_max_length: int, _prompt_twice: bool, _user_data: bytes) -> bytes: # XXX:We could check the password length against what OpenSSL # tells us is the max, but we can't raise an exception, so... # warn? assert password is not None return password.encode("utf-8") self._ctx.set_passwd_cb(_pwcb) self._ctx.use_certificate_chain_file(certfile) self._ctx.use_privatekey_file(keyfile or certfile) self._ctx.check_privatekey() def load_verify_locations( self, cafile: Optional[str] = None, capath: Optional[str] = None ) -> None: """Load a set of "certification authority"(CA) certificates used to validate other peers' certificates when `~verify_mode` is other than ssl.CERT_NONE. """ self._ctx.load_verify_locations(cafile, capath) # Manually load the CA certs when get_verified_chain is not available (pyopenssl<20). if not hasattr(_SSL.Connection, "get_verified_chain"): assert cafile is not None self._callback_data.trusted_ca_certs = _load_trusted_ca_certs(cafile) def _load_certifi(self) -> None: """Attempt to load CA certs from certifi.""" if _HAVE_CERTIFI: self.load_verify_locations(certifi.where()) else: raise _ConfigurationError( "tlsAllowInvalidCertificates is False but no system " "CA certificates could be loaded. Please install the " "certifi package, or provide a path to a CA file using " "the tlsCAFile option" ) def _load_wincerts(self, store: str) -> None: """Attempt to load CA certs from Windows trust store.""" cert_store = self._ctx.get_cert_store() oid = _stdlibssl.Purpose.SERVER_AUTH.oid for cert, encoding, trust in _stdlibssl.enum_certificates(store): # type: ignore if encoding == "x509_asn": if trust is True or oid in trust: cert_store.add_cert( _crypto.X509.from_cryptography(x509.load_der_x509_certificate(cert)) ) def load_default_certs(self) -> None: """A PyOpenSSL version of load_default_certs from CPython.""" # PyOpenSSL is incapable of loading CA certs from Windows, and mostly # incapable on macOS. # https://www.pyopenssl.org/en/stable/api/ssl.html#OpenSSL.SSL.Context.set_default_verify_paths if _sys.platform == "win32": try: for storename in ("CA", "ROOT"): self._load_wincerts(storename) except PermissionError: # Fall back to certifi self._load_certifi() elif _sys.platform == "darwin": self._load_certifi() self._ctx.set_default_verify_paths() def set_default_verify_paths(self) -> None: """Specify that the platform provided CA certificates are to be used for verification purposes. """ # Note: See PyOpenSSL's docs for limitations, which are similar # but not that same as CPython's. self._ctx.set_default_verify_paths() def wrap_socket( self, sock: _socket.socket, server_side: bool = False, do_handshake_on_connect: bool = True, suppress_ragged_eofs: bool = True, server_hostname: Optional[str] = None, session: Optional[_SSL.Session] = None, ) -> _sslConn: """Wrap an existing Python socket connection and return a TLS socket object. """ ssl_conn = _sslConn(self._ctx, sock, suppress_ragged_eofs) if session: ssl_conn.set_session(session) if server_side is True: ssl_conn.set_accept_state() else: # SNI if server_hostname and not _is_ip_address(server_hostname): # XXX: Do this in a callback registered with # SSLContext.set_info_callback? See Twisted for an example. ssl_conn.set_tlsext_host_name(server_hostname.encode("idna")) if self.verify_mode != _stdlibssl.CERT_NONE: # Request a stapled OCSP response. ssl_conn.request_ocsp() ssl_conn.set_connect_state() # If this wasn't true the caller of wrap_socket would call # do_handshake() if do_handshake_on_connect: # XXX: If we do hostname checking in a callback we can get rid # of this call to do_handshake() since the handshake # will happen automatically later. ssl_conn.do_handshake() # XXX: Do this in a callback registered with # SSLContext.set_info_callback? See Twisted for an example. if self.check_hostname and server_hostname is not None: from service_identity import pyopenssl try: if _is_ip_address(server_hostname): pyopenssl.verify_ip_address(ssl_conn, server_hostname) else: pyopenssl.verify_hostname(ssl_conn, server_hostname) except ( # type:ignore[misc] service_identity.SICertificateError, service_identity.SIVerificationError, ) as exc: raise _CertificateError(str(exc)) from None return ssl_conn mongodb-mongo-python-driver-509e9b7/pymongo/read_concern.py000066400000000000000000000045541462766011000241310ustar00rootroot00000000000000# Copyright 2015 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. """Tools for working with read concerns.""" from __future__ import annotations from typing import Any, Optional class ReadConcern: """ReadConcern :param level: (string) The read concern level specifies the level of isolation for read operations. For example, a read operation using a read concern level of ``majority`` will only return data that has been written to a majority of nodes. If the level is left unspecified, the server default will be used. .. versionadded:: 3.2 """ def __init__(self, level: Optional[str] = None) -> None: if level is None or isinstance(level, str): self.__level = level else: raise TypeError("level must be a string or None.") @property def level(self) -> Optional[str]: """The read concern level.""" return self.__level @property def ok_for_legacy(self) -> bool: """Return ``True`` if this read concern is compatible with old wire protocol versions. """ return self.level is None or self.level == "local" @property def document(self) -> dict[str, Any]: """The document representation of this read concern. .. note:: :class:`ReadConcern` is immutable. Mutating the value of :attr:`document` does not mutate this :class:`ReadConcern`. """ doc = {} if self.__level: doc["level"] = self.level return doc def __eq__(self, other: Any) -> bool: if isinstance(other, ReadConcern): return self.document == other.document return NotImplemented def __repr__(self) -> str: if self.level: return "ReadConcern(%s)" % self.level return "ReadConcern()" DEFAULT_READ_CONCERN = ReadConcern() mongodb-mongo-python-driver-509e9b7/pymongo/read_preferences.py000066400000000000000000000515751462766011000250100ustar00rootroot00000000000000# Copyright 2012-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. """Utilities for choosing which member of a replica set to read from.""" from __future__ import annotations from collections import abc from typing import TYPE_CHECKING, Any, Mapping, Optional, Sequence from pymongo import max_staleness_selectors from pymongo.errors import ConfigurationError from pymongo.server_selectors import ( member_with_tags_server_selector, secondary_with_tags_server_selector, ) if TYPE_CHECKING: from pymongo.server_selectors import Selection from pymongo.topology_description import TopologyDescription _PRIMARY = 0 _PRIMARY_PREFERRED = 1 _SECONDARY = 2 _SECONDARY_PREFERRED = 3 _NEAREST = 4 _MONGOS_MODES = ( "primary", "primaryPreferred", "secondary", "secondaryPreferred", "nearest", ) _Hedge = Mapping[str, Any] _TagSets = Sequence[Mapping[str, Any]] def _validate_tag_sets(tag_sets: Optional[_TagSets]) -> Optional[_TagSets]: """Validate tag sets for a MongoClient.""" if tag_sets is None: return tag_sets if not isinstance(tag_sets, (list, tuple)): raise TypeError(f"Tag sets {tag_sets!r} invalid, must be a sequence") if len(tag_sets) == 0: raise ValueError( f"Tag sets {tag_sets!r} invalid, must be None or contain at least one set of tags" ) for tags in tag_sets: if not isinstance(tags, abc.Mapping): raise TypeError( f"Tag set {tags!r} invalid, must be an instance of dict, " "bson.son.SON or other type that inherits from " "collection.Mapping" ) return list(tag_sets) def _invalid_max_staleness_msg(max_staleness: Any) -> str: return "maxStalenessSeconds must be a positive integer, not %s" % max_staleness # Some duplication with common.py to avoid import cycle. def _validate_max_staleness(max_staleness: Any) -> int: """Validate max_staleness.""" if max_staleness == -1: return -1 if not isinstance(max_staleness, int): raise TypeError(_invalid_max_staleness_msg(max_staleness)) if max_staleness <= 0: raise ValueError(_invalid_max_staleness_msg(max_staleness)) return max_staleness def _validate_hedge(hedge: Optional[_Hedge]) -> Optional[_Hedge]: """Validate hedge.""" if hedge is None: return None if not isinstance(hedge, dict): raise TypeError(f"hedge must be a dictionary, not {hedge!r}") return hedge class _ServerMode: """Base class for all read preferences.""" __slots__ = ("__mongos_mode", "__mode", "__tag_sets", "__max_staleness", "__hedge") def __init__( self, mode: int, tag_sets: Optional[_TagSets] = None, max_staleness: int = -1, hedge: Optional[_Hedge] = None, ) -> None: self.__mongos_mode = _MONGOS_MODES[mode] self.__mode = mode self.__tag_sets = _validate_tag_sets(tag_sets) self.__max_staleness = _validate_max_staleness(max_staleness) self.__hedge = _validate_hedge(hedge) @property def name(self) -> str: """The name of this read preference.""" return self.__class__.__name__ @property def mongos_mode(self) -> str: """The mongos mode of this read preference.""" return self.__mongos_mode @property def document(self) -> dict[str, Any]: """Read preference as a document.""" doc: dict[str, Any] = {"mode": self.__mongos_mode} if self.__tag_sets not in (None, [{}]): doc["tags"] = self.__tag_sets if self.__max_staleness != -1: doc["maxStalenessSeconds"] = self.__max_staleness if self.__hedge not in (None, {}): doc["hedge"] = self.__hedge return doc @property def mode(self) -> int: """The mode of this read preference instance.""" return self.__mode @property def tag_sets(self) -> _TagSets: """Set ``tag_sets`` to a list of dictionaries like [{'dc': 'ny'}] to read only from members whose ``dc`` tag has the value ``"ny"``. To specify a priority-order for tag sets, provide a list of tag sets: ``[{'dc': 'ny'}, {'dc': 'la'}, {}]``. A final, empty tag set, ``{}``, means "read from any member that matches the mode, ignoring tags." MongoClient tries each set of tags in turn until it finds a set of tags with at least one matching member. For example, to only send a query to an analytic node:: Nearest(tag_sets=[{"node":"analytics"}]) Or using :class:`SecondaryPreferred`:: SecondaryPreferred(tag_sets=[{"node":"analytics"}]) .. seealso:: `Data-Center Awareness `_ """ return list(self.__tag_sets) if self.__tag_sets else [{}] @property def max_staleness(self) -> int: """The maximum estimated length of time (in seconds) a replica set secondary can fall behind the primary in replication before it will no longer be selected for operations, or -1 for no maximum. """ return self.__max_staleness @property def hedge(self) -> Optional[_Hedge]: """The read preference ``hedge`` parameter. A dictionary that configures how the server will perform hedged reads. It consists of the following keys: - ``enabled``: Enables or disables hedged reads in sharded clusters. Hedged reads are automatically enabled in MongoDB 4.4+ when using a ``nearest`` read preference. To explicitly enable hedged reads, set the ``enabled`` key to ``true``:: >>> Nearest(hedge={'enabled': True}) To explicitly disable hedged reads, set the ``enabled`` key to ``False``:: >>> Nearest(hedge={'enabled': False}) .. versionadded:: 3.11 """ return self.__hedge @property def min_wire_version(self) -> int: """The wire protocol version the server must support. Some read preferences impose version requirements on all servers (e.g. maxStalenessSeconds requires MongoDB 3.4 / maxWireVersion 5). All servers' maxWireVersion must be at least this read preference's `min_wire_version`, or the driver raises :exc:`~pymongo.errors.ConfigurationError`. """ return 0 if self.__max_staleness == -1 else 5 def __repr__(self) -> str: return "{}(tag_sets={!r}, max_staleness={!r}, hedge={!r})".format( self.name, self.__tag_sets, self.__max_staleness, self.__hedge, ) def __eq__(self, other: Any) -> bool: if isinstance(other, _ServerMode): return ( self.mode == other.mode and self.tag_sets == other.tag_sets and self.max_staleness == other.max_staleness and self.hedge == other.hedge ) return NotImplemented def __ne__(self, other: Any) -> bool: return not self == other def __getstate__(self) -> dict[str, Any]: """Return value of object for pickling. Needed explicitly because __slots__() defined. """ return { "mode": self.__mode, "tag_sets": self.__tag_sets, "max_staleness": self.__max_staleness, "hedge": self.__hedge, } def __setstate__(self, value: Mapping[str, Any]) -> None: """Restore from pickling.""" self.__mode = value["mode"] self.__mongos_mode = _MONGOS_MODES[self.__mode] self.__tag_sets = _validate_tag_sets(value["tag_sets"]) self.__max_staleness = _validate_max_staleness(value["max_staleness"]) self.__hedge = _validate_hedge(value["hedge"]) def __call__(self, selection: Selection) -> Selection: return selection class Primary(_ServerMode): """Primary read preference. * When directly connected to one mongod queries are allowed if the server is standalone or a replica set primary. * When connected to a mongos queries are sent to the primary of a shard. * When connected to a replica set queries are sent to the primary of the replica set. """ __slots__ = () def __init__(self) -> None: super().__init__(_PRIMARY) def __call__(self, selection: Selection) -> Selection: """Apply this read preference to a Selection.""" return selection.primary_selection def __repr__(self) -> str: return "Primary()" def __eq__(self, other: Any) -> bool: if isinstance(other, _ServerMode): return other.mode == _PRIMARY return NotImplemented class PrimaryPreferred(_ServerMode): """PrimaryPreferred read preference. * When directly connected to one mongod queries are allowed to standalone servers, to a replica set primary, or to replica set secondaries. * When connected to a mongos queries are sent to the primary of a shard if available, otherwise a shard secondary. * When connected to a replica set queries are sent to the primary if available, otherwise a secondary. .. note:: When a :class:`~pymongo.mongo_client.MongoClient` is first created reads will be routed to an available secondary until the primary of the replica set is discovered. :param tag_sets: The :attr:`~tag_sets` to use if the primary is not available. :param max_staleness: (integer, in seconds) The maximum estimated length of time a replica set secondary can fall behind the primary in replication before it will no longer be selected for operations. Default -1, meaning no maximum. If it is set, it must be at least 90 seconds. :param hedge: The :attr:`~hedge` to use if the primary is not available. .. versionchanged:: 3.11 Added ``hedge`` parameter. """ __slots__ = () def __init__( self, tag_sets: Optional[_TagSets] = None, max_staleness: int = -1, hedge: Optional[_Hedge] = None, ) -> None: super().__init__(_PRIMARY_PREFERRED, tag_sets, max_staleness, hedge) def __call__(self, selection: Selection) -> Selection: """Apply this read preference to Selection.""" if selection.primary: return selection.primary_selection else: return secondary_with_tags_server_selector( self.tag_sets, max_staleness_selectors.select(self.max_staleness, selection) ) class Secondary(_ServerMode): """Secondary read preference. * When directly connected to one mongod queries are allowed to standalone servers, to a replica set primary, or to replica set secondaries. * When connected to a mongos queries are distributed among shard secondaries. An error is raised if no secondaries are available. * When connected to a replica set queries are distributed among secondaries. An error is raised if no secondaries are available. :param tag_sets: The :attr:`~tag_sets` for this read preference. :param max_staleness: (integer, in seconds) The maximum estimated length of time a replica set secondary can fall behind the primary in replication before it will no longer be selected for operations. Default -1, meaning no maximum. If it is set, it must be at least 90 seconds. :param hedge: The :attr:`~hedge` for this read preference. .. versionchanged:: 3.11 Added ``hedge`` parameter. """ __slots__ = () def __init__( self, tag_sets: Optional[_TagSets] = None, max_staleness: int = -1, hedge: Optional[_Hedge] = None, ) -> None: super().__init__(_SECONDARY, tag_sets, max_staleness, hedge) def __call__(self, selection: Selection) -> Selection: """Apply this read preference to Selection.""" return secondary_with_tags_server_selector( self.tag_sets, max_staleness_selectors.select(self.max_staleness, selection) ) class SecondaryPreferred(_ServerMode): """SecondaryPreferred read preference. * When directly connected to one mongod queries are allowed to standalone servers, to a replica set primary, or to replica set secondaries. * When connected to a mongos queries are distributed among shard secondaries, or the shard primary if no secondary is available. * When connected to a replica set queries are distributed among secondaries, or the primary if no secondary is available. .. note:: When a :class:`~pymongo.mongo_client.MongoClient` is first created reads will be routed to the primary of the replica set until an available secondary is discovered. :param tag_sets: The :attr:`~tag_sets` for this read preference. :param max_staleness: (integer, in seconds) The maximum estimated length of time a replica set secondary can fall behind the primary in replication before it will no longer be selected for operations. Default -1, meaning no maximum. If it is set, it must be at least 90 seconds. :param hedge: The :attr:`~hedge` for this read preference. .. versionchanged:: 3.11 Added ``hedge`` parameter. """ __slots__ = () def __init__( self, tag_sets: Optional[_TagSets] = None, max_staleness: int = -1, hedge: Optional[_Hedge] = None, ) -> None: super().__init__(_SECONDARY_PREFERRED, tag_sets, max_staleness, hedge) def __call__(self, selection: Selection) -> Selection: """Apply this read preference to Selection.""" secondaries = secondary_with_tags_server_selector( self.tag_sets, max_staleness_selectors.select(self.max_staleness, selection) ) if secondaries: return secondaries else: return selection.primary_selection class Nearest(_ServerMode): """Nearest read preference. * When directly connected to one mongod queries are allowed to standalone servers, to a replica set primary, or to replica set secondaries. * When connected to a mongos queries are distributed among all members of a shard. * When connected to a replica set queries are distributed among all members. :param tag_sets: The :attr:`~tag_sets` for this read preference. :param max_staleness: (integer, in seconds) The maximum estimated length of time a replica set secondary can fall behind the primary in replication before it will no longer be selected for operations. Default -1, meaning no maximum. If it is set, it must be at least 90 seconds. :param hedge: The :attr:`~hedge` for this read preference. .. versionchanged:: 3.11 Added ``hedge`` parameter. """ __slots__ = () def __init__( self, tag_sets: Optional[_TagSets] = None, max_staleness: int = -1, hedge: Optional[_Hedge] = None, ) -> None: super().__init__(_NEAREST, tag_sets, max_staleness, hedge) def __call__(self, selection: Selection) -> Selection: """Apply this read preference to Selection.""" return member_with_tags_server_selector( self.tag_sets, max_staleness_selectors.select(self.max_staleness, selection) ) class _AggWritePref: """Agg $out/$merge write preference. * If there are readable servers and there is any pre-5.0 server, use primary read preference. * Otherwise use `pref` read preference. :param pref: The read preference to use on MongoDB 5.0+. """ __slots__ = ("pref", "effective_pref") def __init__(self, pref: _ServerMode): self.pref = pref self.effective_pref: _ServerMode = ReadPreference.PRIMARY def selection_hook(self, topology_description: TopologyDescription) -> None: common_wv = topology_description.common_wire_version if ( topology_description.has_readable_server(ReadPreference.PRIMARY_PREFERRED) and common_wv and common_wv < 13 ): self.effective_pref = ReadPreference.PRIMARY else: self.effective_pref = self.pref def __call__(self, selection: Selection) -> Selection: """Apply this read preference to a Selection.""" return self.effective_pref(selection) def __repr__(self) -> str: return f"_AggWritePref(pref={self.pref!r})" # Proxy other calls to the effective_pref so that _AggWritePref can be # used in place of an actual read preference. def __getattr__(self, name: str) -> Any: return getattr(self.effective_pref, name) _ALL_READ_PREFERENCES = (Primary, PrimaryPreferred, Secondary, SecondaryPreferred, Nearest) def make_read_preference( mode: int, tag_sets: Optional[_TagSets], max_staleness: int = -1 ) -> _ServerMode: if mode == _PRIMARY: if tag_sets not in (None, [{}]): raise ConfigurationError("Read preference primary cannot be combined with tags") if max_staleness != -1: raise ConfigurationError( "Read preference primary cannot be combined with maxStalenessSeconds" ) return Primary() return _ALL_READ_PREFERENCES[mode](tag_sets, max_staleness) # type: ignore _MODES = ( "PRIMARY", "PRIMARY_PREFERRED", "SECONDARY", "SECONDARY_PREFERRED", "NEAREST", ) class ReadPreference: """An enum that defines some commonly used read preference modes. Apps can also create a custom read preference, for example:: Nearest(tag_sets=[{"node":"analytics"}]) See :doc:`/examples/high_availability` for code examples. A read preference is used in three cases: :class:`~pymongo.mongo_client.MongoClient` connected to a single mongod: - ``PRIMARY``: Queries are allowed if the server is standalone or a replica set primary. - All other modes allow queries to standalone servers, to a replica set primary, or to replica set secondaries. :class:`~pymongo.mongo_client.MongoClient` initialized with the ``replicaSet`` option: - ``PRIMARY``: Read from the primary. This is the default, and provides the strongest consistency. If no primary is available, raise :class:`~pymongo.errors.AutoReconnect`. - ``PRIMARY_PREFERRED``: Read from the primary if available, or if there is none, read from a secondary. - ``SECONDARY``: Read from a secondary. If no secondary is available, raise :class:`~pymongo.errors.AutoReconnect`. - ``SECONDARY_PREFERRED``: Read from a secondary if available, otherwise from the primary. - ``NEAREST``: Read from any member. :class:`~pymongo.mongo_client.MongoClient` connected to a mongos, with a sharded cluster of replica sets: - ``PRIMARY``: Read from the primary of the shard, or raise :class:`~pymongo.errors.OperationFailure` if there is none. This is the default. - ``PRIMARY_PREFERRED``: Read from the primary of the shard, or if there is none, read from a secondary of the shard. - ``SECONDARY``: Read from a secondary of the shard, or raise :class:`~pymongo.errors.OperationFailure` if there is none. - ``SECONDARY_PREFERRED``: Read from a secondary of the shard if available, otherwise from the shard primary. - ``NEAREST``: Read from any shard member. """ PRIMARY = Primary() PRIMARY_PREFERRED = PrimaryPreferred() SECONDARY = Secondary() SECONDARY_PREFERRED = SecondaryPreferred() NEAREST = Nearest() def read_pref_mode_from_name(name: str) -> int: """Get the read preference mode from mongos/uri name.""" return _MONGOS_MODES.index(name) class MovingAverage: """Tracks an exponentially-weighted moving average.""" average: Optional[float] def __init__(self) -> None: self.average = None def add_sample(self, sample: float) -> None: if sample < 0: # Likely system time change while waiting for hello response # and not using time.monotonic. Ignore it, the next one will # probably be valid. return if self.average is None: self.average = sample else: # The Server Selection Spec requires an exponentially weighted # average with alpha = 0.2. self.average = 0.8 * self.average + 0.2 * sample def get(self) -> Optional[float]: """Get the calculated average, or None if no samples yet.""" return self.average def reset(self) -> None: self.average = None mongodb-mongo-python-driver-509e9b7/pymongo/response.py000066400000000000000000000103051462766011000233340ustar00rootroot00000000000000# Copyright 2014-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. """Represent a response from the server.""" from __future__ import annotations from typing import TYPE_CHECKING, Any, Mapping, Optional, Sequence, Union if TYPE_CHECKING: from datetime import timedelta from pymongo.message import _OpMsg, _OpReply from pymongo.pool import Connection from pymongo.typings import _Address, _DocumentOut class Response: __slots__ = ("_data", "_address", "_request_id", "_duration", "_from_command", "_docs") def __init__( self, data: Union[_OpMsg, _OpReply], address: _Address, request_id: int, duration: Optional[timedelta], from_command: bool, docs: Sequence[Mapping[str, Any]], ): """Represent a response from the server. :param data: A network response message. :param address: (host, port) of the source server. :param request_id: The request id of this operation. :param duration: The duration of the operation. :param from_command: if the response is the result of a db command. """ self._data = data self._address = address self._request_id = request_id self._duration = duration self._from_command = from_command self._docs = docs @property def data(self) -> Union[_OpMsg, _OpReply]: """Server response's raw BSON bytes.""" return self._data @property def address(self) -> _Address: """(host, port) of the source server.""" return self._address @property def request_id(self) -> int: """The request id of this operation.""" return self._request_id @property def duration(self) -> Optional[timedelta]: """The duration of the operation.""" return self._duration @property def from_command(self) -> bool: """If the response is a result from a db command.""" return self._from_command @property def docs(self) -> Sequence[Mapping[str, Any]]: """The decoded document(s).""" return self._docs class PinnedResponse(Response): __slots__ = ("_conn", "_more_to_come") def __init__( self, data: Union[_OpMsg, _OpReply], address: _Address, conn: Connection, request_id: int, duration: Optional[timedelta], from_command: bool, docs: list[_DocumentOut], more_to_come: bool, ): """Represent a response to an exhaust cursor's initial query. :param data: A network response message. :param address: (host, port) of the source server. :param conn: The Connection used for the initial query. :param request_id: The request id of this operation. :param duration: The duration of the operation. :param from_command: If the response is the result of a db command. :param docs: List of documents. :param more_to_come: Bool indicating whether cursor is ready to be exhausted. """ super().__init__(data, address, request_id, duration, from_command, docs) self._conn = conn self._more_to_come = more_to_come @property def conn(self) -> Connection: """The Connection used for the initial query. The server will send batches on this socket, without waiting for getMores from the client, until the result set is exhausted or there is an error. """ return self._conn @property def more_to_come(self) -> bool: """If true, server is ready to send batches on the socket until the result set is exhausted or there is an error. """ return self._more_to_come mongodb-mongo-python-driver-509e9b7/pymongo/results.py000066400000000000000000000205031462766011000232000ustar00rootroot00000000000000# Copyright 2015-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. """Result class definitions.""" from __future__ import annotations from typing import Any, Mapping, Optional, cast from pymongo.errors import InvalidOperation class _WriteResult: """Base class for write result classes.""" __slots__ = ("__acknowledged",) def __init__(self, acknowledged: bool) -> None: self.__acknowledged = acknowledged def __repr__(self) -> str: return f"{self.__class__.__name__}({self.__acknowledged})" def _raise_if_unacknowledged(self, property_name: str) -> None: """Raise an exception on property access if unacknowledged.""" if not self.__acknowledged: raise InvalidOperation( f"A value for {property_name} is not available when " "the write is unacknowledged. Check the " "acknowledged attribute to avoid this " "error." ) @property def acknowledged(self) -> bool: """Is this the result of an acknowledged write operation? The :attr:`acknowledged` attribute will be ``False`` when using ``WriteConcern(w=0)``, otherwise ``True``. .. note:: If the :attr:`acknowledged` attribute is ``False`` all other attributes of this class will raise :class:`~pymongo.errors.InvalidOperation` when accessed. Values for other attributes cannot be determined if the write operation was unacknowledged. .. seealso:: :class:`~pymongo.write_concern.WriteConcern` """ return self.__acknowledged class InsertOneResult(_WriteResult): """The return type for :meth:`~pymongo.collection.Collection.insert_one`.""" __slots__ = ("__inserted_id",) def __init__(self, inserted_id: Any, acknowledged: bool) -> None: self.__inserted_id = inserted_id super().__init__(acknowledged) def __repr__(self) -> str: return ( f"{self.__class__.__name__}({self.__inserted_id!r}, acknowledged={self.acknowledged})" ) @property def inserted_id(self) -> Any: """The inserted document's _id.""" return self.__inserted_id class InsertManyResult(_WriteResult): """The return type for :meth:`~pymongo.collection.Collection.insert_many`.""" __slots__ = ("__inserted_ids",) def __init__(self, inserted_ids: list[Any], acknowledged: bool) -> None: self.__inserted_ids = inserted_ids super().__init__(acknowledged) def __repr__(self) -> str: return ( f"{self.__class__.__name__}({self.__inserted_ids!r}, acknowledged={self.acknowledged})" ) @property def inserted_ids(self) -> list[Any]: """A list of _ids of the inserted documents, in the order provided. .. note:: If ``False`` is passed for the `ordered` parameter to :meth:`~pymongo.collection.Collection.insert_many` the server may have inserted the documents in a different order than what is presented here. """ return self.__inserted_ids class UpdateResult(_WriteResult): """The return type for :meth:`~pymongo.collection.Collection.update_one`, :meth:`~pymongo.collection.Collection.update_many`, and :meth:`~pymongo.collection.Collection.replace_one`. """ __slots__ = ("__raw_result",) def __init__(self, raw_result: Optional[Mapping[str, Any]], acknowledged: bool): self.__raw_result = raw_result super().__init__(acknowledged) def __repr__(self) -> str: return f"{self.__class__.__name__}({self.__raw_result!r}, acknowledged={self.acknowledged})" @property def raw_result(self) -> Optional[Mapping[str, Any]]: """The raw result document returned by the server.""" return self.__raw_result @property def matched_count(self) -> int: """The number of documents matched for this update.""" self._raise_if_unacknowledged("matched_count") if self.upserted_id is not None: return 0 assert self.__raw_result is not None return self.__raw_result.get("n", 0) @property def modified_count(self) -> int: """The number of documents modified.""" self._raise_if_unacknowledged("modified_count") assert self.__raw_result is not None return cast(int, self.__raw_result.get("nModified")) @property def upserted_id(self) -> Any: """The _id of the inserted document if an upsert took place. Otherwise ``None``. """ self._raise_if_unacknowledged("upserted_id") assert self.__raw_result is not None return self.__raw_result.get("upserted") class DeleteResult(_WriteResult): """The return type for :meth:`~pymongo.collection.Collection.delete_one` and :meth:`~pymongo.collection.Collection.delete_many` """ __slots__ = ("__raw_result",) def __init__(self, raw_result: Mapping[str, Any], acknowledged: bool) -> None: self.__raw_result = raw_result super().__init__(acknowledged) def __repr__(self) -> str: return f"{self.__class__.__name__}({self.__raw_result!r}, acknowledged={self.acknowledged})" @property def raw_result(self) -> Mapping[str, Any]: """The raw result document returned by the server.""" return self.__raw_result @property def deleted_count(self) -> int: """The number of documents deleted.""" self._raise_if_unacknowledged("deleted_count") return self.__raw_result.get("n", 0) class BulkWriteResult(_WriteResult): """An object wrapper for bulk API write results.""" __slots__ = ("__bulk_api_result",) def __init__(self, bulk_api_result: dict[str, Any], acknowledged: bool) -> None: """Create a BulkWriteResult instance. :param bulk_api_result: A result dict from the bulk API :param acknowledged: Was this write result acknowledged? If ``False`` then all properties of this object will raise :exc:`~pymongo.errors.InvalidOperation`. """ self.__bulk_api_result = bulk_api_result super().__init__(acknowledged) def __repr__(self) -> str: return f"{self.__class__.__name__}({self.__bulk_api_result!r}, acknowledged={self.acknowledged})" @property def bulk_api_result(self) -> dict[str, Any]: """The raw bulk API result.""" return self.__bulk_api_result @property def inserted_count(self) -> int: """The number of documents inserted.""" self._raise_if_unacknowledged("inserted_count") return cast(int, self.__bulk_api_result.get("nInserted")) @property def matched_count(self) -> int: """The number of documents matched for an update.""" self._raise_if_unacknowledged("matched_count") return cast(int, self.__bulk_api_result.get("nMatched")) @property def modified_count(self) -> int: """The number of documents modified.""" self._raise_if_unacknowledged("modified_count") return cast(int, self.__bulk_api_result.get("nModified")) @property def deleted_count(self) -> int: """The number of documents deleted.""" self._raise_if_unacknowledged("deleted_count") return cast(int, self.__bulk_api_result.get("nRemoved")) @property def upserted_count(self) -> int: """The number of documents upserted.""" self._raise_if_unacknowledged("upserted_count") return cast(int, self.__bulk_api_result.get("nUpserted")) @property def upserted_ids(self) -> Optional[dict[int, Any]]: """A map of operation index to the _id of the upserted document.""" self._raise_if_unacknowledged("upserted_ids") if self.__bulk_api_result: return {upsert["index"]: upsert["_id"] for upsert in self.bulk_api_result["upserted"]} return None mongodb-mongo-python-driver-509e9b7/pymongo/saslprep.py000066400000000000000000000104371462766011000233350ustar00rootroot00000000000000# Copyright 2016-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. """An implementation of RFC4013 SASLprep.""" from __future__ import annotations from typing import Any, Optional try: import stringprep except ImportError: HAVE_STRINGPREP = False def saslprep( data: Any, prohibit_unassigned_code_points: Optional[bool] = True, # noqa: ARG001 ) -> Any: """SASLprep dummy""" if isinstance(data, str): raise TypeError( "The stringprep module is not available. Usernames and " "passwords must be instances of bytes." ) return data else: HAVE_STRINGPREP = True import unicodedata # RFC4013 section 2.3 prohibited output. _PROHIBITED = ( # A strict reading of RFC 4013 requires table c12 here, but # characters from it are mapped to SPACE in the Map step. Can # normalization reintroduce them somehow? stringprep.in_table_c12, stringprep.in_table_c21_c22, stringprep.in_table_c3, stringprep.in_table_c4, stringprep.in_table_c5, stringprep.in_table_c6, stringprep.in_table_c7, stringprep.in_table_c8, stringprep.in_table_c9, ) def saslprep(data: Any, prohibit_unassigned_code_points: Optional[bool] = True) -> Any: """An implementation of RFC4013 SASLprep. :param data: The string to SASLprep. Unicode strings (:class:`str`) are supported. Byte strings (:class:`bytes`) are ignored. :param prohibit_unassigned_code_points: True / False. RFC 3454 and RFCs for various SASL mechanisms distinguish between `queries` (unassigned code points allowed) and `stored strings` (unassigned code points prohibited). Defaults to ``True`` (unassigned code points are prohibited). :return: The SASLprep'ed version of `data`. """ prohibited: Any if not isinstance(data, str): return data if prohibit_unassigned_code_points: prohibited = (*_PROHIBITED, stringprep.in_table_a1) else: prohibited = _PROHIBITED # RFC3454 section 2, step 1 - Map # RFC4013 section 2.1 mappings # Map Non-ASCII space characters to SPACE (U+0020). Map # commonly mapped to nothing characters to, well, nothing. in_table_c12 = stringprep.in_table_c12 in_table_b1 = stringprep.in_table_b1 data = "".join( ["\u0020" if in_table_c12(elt) else elt for elt in data if not in_table_b1(elt)] ) # RFC3454 section 2, step 2 - Normalize # RFC4013 section 2.2 normalization data = unicodedata.ucd_3_2_0.normalize("NFKC", data) in_table_d1 = stringprep.in_table_d1 if in_table_d1(data[0]): if not in_table_d1(data[-1]): # RFC3454, Section 6, #3. If a string contains any # RandALCat character, the first and last characters # MUST be RandALCat characters. raise ValueError("SASLprep: failed bidirectional check") # RFC3454, Section 6, #2. If a string contains any RandALCat # character, it MUST NOT contain any LCat character. prohibited = (*prohibited, stringprep.in_table_d2) else: # RFC3454, Section 6, #3. Following the logic of #3, if # the first character is not a RandALCat, no other character # can be either. prohibited = (*prohibited, in_table_d1) # RFC3454 section 2, step 3 and 4 - Prohibit and check bidi for char in data: if any(in_table(char) for in_table in prohibited): raise ValueError("SASLprep: failed prohibited character check") return data mongodb-mongo-python-driver-509e9b7/pymongo/server.py000066400000000000000000000310601462766011000230050ustar00rootroot00000000000000# Copyright 2014-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. """Communicate with one MongoDB server in a topology.""" from __future__ import annotations import logging from datetime import datetime from typing import TYPE_CHECKING, Any, Callable, ContextManager, Optional, Union from bson import _decode_all_selective from pymongo.errors import NotPrimaryError, OperationFailure from pymongo.helpers import _check_command_response, _handle_reauth from pymongo.logger import _COMMAND_LOGGER, _CommandStatusMessage, _debug_log from pymongo.message import _convert_exception, _GetMore, _OpMsg, _Query from pymongo.response import PinnedResponse, Response if TYPE_CHECKING: from queue import Queue from weakref import ReferenceType from bson.objectid import ObjectId from pymongo.mongo_client import MongoClient, _MongoClientErrorHandler from pymongo.monitor import Monitor from pymongo.monitoring import _EventListeners from pymongo.pool import Connection, Pool from pymongo.read_preferences import _ServerMode from pymongo.server_description import ServerDescription from pymongo.typings import _DocumentOut _CURSOR_DOC_FIELDS = {"cursor": {"firstBatch": 1, "nextBatch": 1}} class Server: def __init__( self, server_description: ServerDescription, pool: Pool, monitor: Monitor, topology_id: Optional[ObjectId] = None, listeners: Optional[_EventListeners] = None, events: Optional[ReferenceType[Queue]] = None, ) -> None: """Represent one MongoDB server.""" self._description = server_description self._pool = pool self._monitor = monitor self._topology_id = topology_id self._publish = listeners is not None and listeners.enabled_for_server self._listener = listeners self._events = None if self._publish: self._events = events() # type: ignore[misc] def open(self) -> None: """Start monitoring, or restart after a fork. Multiple calls have no effect. """ if not self._pool.opts.load_balanced: self._monitor.open() def reset(self, service_id: Optional[ObjectId] = None) -> None: """Clear the connection pool.""" self.pool.reset(service_id) def close(self) -> None: """Clear the connection pool and stop the monitor. Reconnect with open(). """ if self._publish: assert self._listener is not None assert self._events is not None self._events.put( ( self._listener.publish_server_closed, (self._description.address, self._topology_id), ) ) self._monitor.close() self._pool.close() def request_check(self) -> None: """Check the server's state soon.""" self._monitor.request_check() @_handle_reauth def run_operation( self, conn: Connection, operation: Union[_Query, _GetMore], read_preference: _ServerMode, listeners: Optional[_EventListeners], unpack_res: Callable[..., list[_DocumentOut]], client: MongoClient, ) -> Response: """Run a _Query or _GetMore operation and return a Response object. This method is used only to run _Query/_GetMore operations from cursors. Can raise ConnectionFailure, OperationFailure, etc. :param conn: A Connection instance. :param operation: A _Query or _GetMore object. :param read_preference: The read preference to use. :param listeners: Instance of _EventListeners or None. :param unpack_res: A callable that decodes the wire protocol response. """ duration = None assert listeners is not None publish = listeners.enabled_for_commands start = datetime.now() use_cmd = operation.use_command(conn) more_to_come = operation.conn_mgr and operation.conn_mgr.more_to_come if more_to_come: request_id = 0 else: message = operation.get_message(read_preference, conn, use_cmd) request_id, data, max_doc_size = self._split_message(message) cmd, dbn = operation.as_command(conn) if _COMMAND_LOGGER.isEnabledFor(logging.DEBUG): _debug_log( _COMMAND_LOGGER, clientId=client._topology_settings._topology_id, message=_CommandStatusMessage.STARTED, command=cmd, commandName=next(iter(cmd)), databaseName=dbn, requestId=request_id, operationId=request_id, driverConnectionId=conn.id, serverConnectionId=conn.server_connection_id, serverHost=conn.address[0], serverPort=conn.address[1], serviceId=conn.service_id, ) if publish: cmd, dbn = operation.as_command(conn) if "$db" not in cmd: cmd["$db"] = dbn assert listeners is not None listeners.publish_command_start( cmd, dbn, request_id, conn.address, conn.server_connection_id, service_id=conn.service_id, ) try: if more_to_come: reply = conn.receive_message(None) else: conn.send_message(data, max_doc_size) reply = conn.receive_message(request_id) # Unpack and check for command errors. if use_cmd: user_fields = _CURSOR_DOC_FIELDS legacy_response = False else: user_fields = None legacy_response = True docs = unpack_res( reply, operation.cursor_id, operation.codec_options, legacy_response=legacy_response, user_fields=user_fields, ) if use_cmd: first = docs[0] operation.client._process_response(first, operation.session) _check_command_response(first, conn.max_wire_version) except Exception as exc: duration = datetime.now() - start if isinstance(exc, (NotPrimaryError, OperationFailure)): failure: _DocumentOut = exc.details # type: ignore[assignment] else: failure = _convert_exception(exc) if _COMMAND_LOGGER.isEnabledFor(logging.DEBUG): _debug_log( _COMMAND_LOGGER, clientId=client._topology_settings._topology_id, message=_CommandStatusMessage.FAILED, durationMS=duration, failure=failure, commandName=next(iter(cmd)), databaseName=dbn, requestId=request_id, operationId=request_id, driverConnectionId=conn.id, serverConnectionId=conn.server_connection_id, serverHost=conn.address[0], serverPort=conn.address[1], serviceId=conn.service_id, isServerSideError=isinstance(exc, OperationFailure), ) if publish: assert listeners is not None listeners.publish_command_failure( duration, failure, operation.name, request_id, conn.address, conn.server_connection_id, service_id=conn.service_id, database_name=dbn, ) raise duration = datetime.now() - start # Must publish in find / getMore / explain command response # format. if use_cmd: res = docs[0] elif operation.name == "explain": res = docs[0] if docs else {} else: res = {"cursor": {"id": reply.cursor_id, "ns": operation.namespace()}, "ok": 1} # type: ignore[union-attr] if operation.name == "find": res["cursor"]["firstBatch"] = docs else: res["cursor"]["nextBatch"] = docs if _COMMAND_LOGGER.isEnabledFor(logging.DEBUG): _debug_log( _COMMAND_LOGGER, clientId=client._topology_settings._topology_id, message=_CommandStatusMessage.SUCCEEDED, durationMS=duration, reply=res, commandName=next(iter(cmd)), databaseName=dbn, requestId=request_id, operationId=request_id, driverConnectionId=conn.id, serverConnectionId=conn.server_connection_id, serverHost=conn.address[0], serverPort=conn.address[1], serviceId=conn.service_id, ) if publish: assert listeners is not None listeners.publish_command_success( duration, res, operation.name, request_id, conn.address, conn.server_connection_id, service_id=conn.service_id, database_name=dbn, ) # Decrypt response. client = operation.client if client and client._encrypter: if use_cmd: decrypted = client._encrypter.decrypt(reply.raw_command_response()) docs = _decode_all_selective(decrypted, operation.codec_options, user_fields) response: Response if client._should_pin_cursor(operation.session) or operation.exhaust: conn.pin_cursor() if isinstance(reply, _OpMsg): # In OP_MSG, the server keeps sending only if the # more_to_come flag is set. more_to_come = reply.more_to_come else: # In OP_REPLY, the server keeps sending until cursor_id is 0. more_to_come = bool(operation.exhaust and reply.cursor_id) if operation.conn_mgr: operation.conn_mgr.update_exhaust(more_to_come) response = PinnedResponse( data=reply, address=self._description.address, conn=conn, duration=duration, request_id=request_id, from_command=use_cmd, docs=docs, more_to_come=more_to_come, ) else: response = Response( data=reply, address=self._description.address, duration=duration, request_id=request_id, from_command=use_cmd, docs=docs, ) return response def checkout( self, handler: Optional[_MongoClientErrorHandler] = None ) -> ContextManager[Connection]: return self.pool.checkout(handler) @property def description(self) -> ServerDescription: return self._description @description.setter def description(self, server_description: ServerDescription) -> None: assert server_description.address == self._description.address self._description = server_description @property def pool(self) -> Pool: return self._pool def _split_message( self, message: Union[tuple[int, Any], tuple[int, Any, int]] ) -> tuple[int, Any, int]: """Return request_id, data, max_doc_size. :param message: (request_id, data, max_doc_size) or (request_id, data) """ if len(message) == 3: return message # type: ignore[return-value] else: # get_more and kill_cursors messages don't include BSON documents. request_id, data = message # type: ignore[misc] return request_id, data, 0 def __repr__(self) -> str: return f"<{self.__class__.__name__} {self._description!r}>" mongodb-mongo-python-driver-509e9b7/pymongo/server_api.py000066400000000000000000000136731462766011000236500ustar00rootroot00000000000000# Copyright 2020-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. """Support for MongoDB Stable API. .. _versioned-api-ref: MongoDB Stable API ===================== Starting in MongoDB 5.0, applications can specify the server API version to use when creating a :class:`~pymongo.mongo_client.MongoClient`. Doing so ensures that the driver behaves in a manner compatible with that server API version, regardless of the server's actual release version. Declaring an API Version ```````````````````````` .. attention:: Stable API requires MongoDB >=5.0. To configure MongoDB Stable API, pass the ``server_api`` keyword option to :class:`~pymongo.mongo_client.MongoClient`:: >>> from pymongo.mongo_client import MongoClient >>> from pymongo.server_api import ServerApi >>> >>> # Declare API version "1" for MongoClient "client" >>> server_api = ServerApi('1') >>> client = MongoClient(server_api=server_api) The declared API version is applied to all commands run through ``client``, including those sent through the generic :meth:`~pymongo.database.Database.command` helper. .. note:: Declaring an API version on the :class:`~pymongo.mongo_client.MongoClient` **and** specifying stable API options in :meth:`~pymongo.database.Database.command` command document is not supported and will lead to undefined behaviour. To run any command without declaring a server API version or using a different API version, create a separate :class:`~pymongo.mongo_client.MongoClient` instance. Strict Mode ``````````` Configuring ``strict`` mode will cause the MongoDB server to reject all commands that are not part of the declared :attr:`ServerApi.version`. This includes command options and aggregation pipeline stages. For example:: >>> server_api = ServerApi('1', strict=True) >>> client = MongoClient(server_api=server_api) >>> client.test.command('count', 'test') Traceback (most recent call last): ... pymongo.errors.OperationFailure: Provided apiStrict:true, but the command count is not in API Version 1, full error: {'ok': 0.0, 'errmsg': 'Provided apiStrict:true, but the command count is not in API Version 1', 'code': 323, 'codeName': 'APIStrictError' Detecting API Deprecations `````````````````````````` The ``deprecationErrors`` option can be used to enable command failures when using functionality that is deprecated from the configured :attr:`ServerApi.version`. For example:: >>> server_api = ServerApi('1', deprecation_errors=True) >>> client = MongoClient(server_api=server_api) Note that at the time of this writing, no deprecated APIs exist. Classes ======= """ from __future__ import annotations from typing import Any, MutableMapping, Optional class ServerApiVersion: """An enum that defines values for :attr:`ServerApi.version`. .. versionadded:: 3.12 """ V1 = "1" """Server API version "1".""" class ServerApi: """MongoDB Stable API.""" def __init__( self, version: str, strict: Optional[bool] = None, deprecation_errors: Optional[bool] = None ): """Options to configure MongoDB Stable API. :param version: The API version string. Must be one of the values in :class:`ServerApiVersion`. :param strict: Set to ``True`` to enable API strict mode. Defaults to ``None`` which means "use the server's default". :param deprecation_errors: Set to ``True`` to enable deprecation errors. Defaults to ``None`` which means "use the server's default". .. versionadded:: 3.12 """ if version != ServerApiVersion.V1: raise ValueError(f"Unknown ServerApi version: {version}") if strict is not None and not isinstance(strict, bool): raise TypeError( "Wrong type for ServerApi strict, value must be an instance " f"of bool, not {type(strict)}" ) if deprecation_errors is not None and not isinstance(deprecation_errors, bool): raise TypeError( "Wrong type for ServerApi deprecation_errors, value must be " f"an instance of bool, not {type(deprecation_errors)}" ) self._version = version self._strict = strict self._deprecation_errors = deprecation_errors @property def version(self) -> str: """The API version setting. This value is sent to the server in the "apiVersion" field. """ return self._version @property def strict(self) -> Optional[bool]: """The API strict mode setting. When set, this value is sent to the server in the "apiStrict" field. """ return self._strict @property def deprecation_errors(self) -> Optional[bool]: """The API deprecation errors setting. When set, this value is sent to the server in the "apiDeprecationErrors" field. """ return self._deprecation_errors def _add_to_command(cmd: MutableMapping[str, Any], server_api: Optional[ServerApi]) -> None: """Internal helper which adds API versioning options to a command. :param cmd: The command. :param server_api: A :class:`ServerApi` or ``None``. """ if not server_api: return cmd["apiVersion"] = server_api.version if server_api.strict is not None: cmd["apiStrict"] = server_api.strict if server_api.deprecation_errors is not None: cmd["apiDeprecationErrors"] = server_api.deprecation_errors mongodb-mongo-python-driver-509e9b7/pymongo/server_description.py000066400000000000000000000226061462766011000254160ustar00rootroot00000000000000# Copyright 2014-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. """Represent one server the driver is connected to.""" from __future__ import annotations import time import warnings from typing import Any, Mapping, Optional from bson import EPOCH_NAIVE from bson.objectid import ObjectId from pymongo.hello import Hello from pymongo.server_type import SERVER_TYPE from pymongo.typings import ClusterTime, _Address class ServerDescription: """Immutable representation of one server. :param address: A (host, port) pair :param hello: Optional Hello instance :param round_trip_time: Optional float :param error: Optional, the last error attempting to connect to the server :param round_trip_time: Optional float, the min latency from the most recent samples """ __slots__ = ( "_address", "_server_type", "_all_hosts", "_tags", "_replica_set_name", "_primary", "_max_bson_size", "_max_message_size", "_max_write_batch_size", "_min_wire_version", "_max_wire_version", "_round_trip_time", "_min_round_trip_time", "_me", "_is_writable", "_is_readable", "_ls_timeout_minutes", "_error", "_set_version", "_election_id", "_cluster_time", "_last_write_date", "_last_update_time", "_topology_version", ) def __init__( self, address: _Address, hello: Optional[Hello] = None, round_trip_time: Optional[float] = None, error: Optional[Exception] = None, min_round_trip_time: float = 0.0, ) -> None: self._address = address if not hello: hello = Hello({}) self._server_type = hello.server_type self._all_hosts = hello.all_hosts self._tags = hello.tags self._replica_set_name = hello.replica_set_name self._primary = hello.primary self._max_bson_size = hello.max_bson_size self._max_message_size = hello.max_message_size self._max_write_batch_size = hello.max_write_batch_size self._min_wire_version = hello.min_wire_version self._max_wire_version = hello.max_wire_version self._set_version = hello.set_version self._election_id = hello.election_id self._cluster_time = hello.cluster_time self._is_writable = hello.is_writable self._is_readable = hello.is_readable self._ls_timeout_minutes = hello.logical_session_timeout_minutes self._round_trip_time = round_trip_time self._min_round_trip_time = min_round_trip_time self._me = hello.me self._last_update_time = time.monotonic() self._error = error self._topology_version = hello.topology_version if error: details = getattr(error, "details", None) if isinstance(details, dict): self._topology_version = details.get("topologyVersion") self._last_write_date: Optional[float] if hello.last_write_date: # Convert from datetime to seconds. delta = hello.last_write_date - EPOCH_NAIVE self._last_write_date = delta.total_seconds() else: self._last_write_date = None @property def address(self) -> _Address: """The address (host, port) of this server.""" return self._address @property def server_type(self) -> int: """The type of this server.""" return self._server_type @property def server_type_name(self) -> str: """The server type as a human readable string. .. versionadded:: 3.4 """ return SERVER_TYPE._fields[self._server_type] @property def all_hosts(self) -> set[tuple[str, int]]: """List of hosts, passives, and arbiters known to this server.""" return self._all_hosts @property def tags(self) -> Mapping[str, Any]: return self._tags @property def replica_set_name(self) -> Optional[str]: """Replica set name or None.""" return self._replica_set_name @property def primary(self) -> Optional[tuple[str, int]]: """This server's opinion about who the primary is, or None.""" return self._primary @property def max_bson_size(self) -> int: return self._max_bson_size @property def max_message_size(self) -> int: return self._max_message_size @property def max_write_batch_size(self) -> int: return self._max_write_batch_size @property def min_wire_version(self) -> int: return self._min_wire_version @property def max_wire_version(self) -> int: return self._max_wire_version @property def set_version(self) -> Optional[int]: return self._set_version @property def election_id(self) -> Optional[ObjectId]: return self._election_id @property def cluster_time(self) -> Optional[ClusterTime]: return self._cluster_time @property def election_tuple(self) -> tuple[Optional[int], Optional[ObjectId]]: warnings.warn( "'election_tuple' is deprecated, use 'set_version' and 'election_id' instead", DeprecationWarning, stacklevel=2, ) return self._set_version, self._election_id @property def me(self) -> Optional[tuple[str, int]]: return self._me @property def logical_session_timeout_minutes(self) -> Optional[int]: return self._ls_timeout_minutes @property def last_write_date(self) -> Optional[float]: return self._last_write_date @property def last_update_time(self) -> float: return self._last_update_time @property def round_trip_time(self) -> Optional[float]: """The current average latency or None.""" # This override is for unittesting only! if self._address in self._host_to_round_trip_time: return self._host_to_round_trip_time[self._address] return self._round_trip_time @property def min_round_trip_time(self) -> float: """The min latency from the most recent samples.""" return self._min_round_trip_time @property def error(self) -> Optional[Exception]: """The last error attempting to connect to the server, or None.""" return self._error @property def is_writable(self) -> bool: return self._is_writable @property def is_readable(self) -> bool: return self._is_readable @property def mongos(self) -> bool: return self._server_type == SERVER_TYPE.Mongos @property def is_server_type_known(self) -> bool: return self.server_type != SERVER_TYPE.Unknown @property def retryable_writes_supported(self) -> bool: """Checks if this server supports retryable writes.""" return ( self._server_type in (SERVER_TYPE.Mongos, SERVER_TYPE.RSPrimary) ) or self._server_type == SERVER_TYPE.LoadBalancer @property def retryable_reads_supported(self) -> bool: """Checks if this server supports retryable writes.""" return self._max_wire_version >= 6 @property def topology_version(self) -> Optional[Mapping[str, Any]]: return self._topology_version def to_unknown(self, error: Optional[Exception] = None) -> ServerDescription: unknown = ServerDescription(self.address, error=error) unknown._topology_version = self.topology_version return unknown def __eq__(self, other: Any) -> bool: if isinstance(other, ServerDescription): return ( (self._address == other.address) and (self._server_type == other.server_type) and (self._min_wire_version == other.min_wire_version) and (self._max_wire_version == other.max_wire_version) and (self._me == other.me) and (self._all_hosts == other.all_hosts) and (self._tags == other.tags) and (self._replica_set_name == other.replica_set_name) and (self._set_version == other.set_version) and (self._election_id == other.election_id) and (self._primary == other.primary) and (self._ls_timeout_minutes == other.logical_session_timeout_minutes) and (self._error == other.error) ) return NotImplemented def __ne__(self, other: Any) -> bool: return not self == other def __repr__(self) -> str: errmsg = "" if self.error: errmsg = f", error={self.error!r}" return "<{} {} server_type: {}, rtt: {}{}>".format( self.__class__.__name__, self.address, self.server_type_name, self.round_trip_time, errmsg, ) # For unittesting only. Use under no circumstances! _host_to_round_trip_time: dict = {} mongodb-mongo-python-driver-509e9b7/pymongo/server_selectors.py000066400000000000000000000136761462766011000251050ustar00rootroot00000000000000# Copyright 2014-2016 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. """Criteria to select some ServerDescriptions from a TopologyDescription.""" from __future__ import annotations from typing import TYPE_CHECKING, Any, Mapping, Optional, Sequence, TypeVar, cast from pymongo.server_type import SERVER_TYPE if TYPE_CHECKING: from pymongo.server_description import ServerDescription from pymongo.topology_description import TopologyDescription T = TypeVar("T") TagSet = Mapping[str, Any] TagSets = Sequence[TagSet] class Selection: """Input or output of a server selector function.""" @classmethod def from_topology_description(cls, topology_description: TopologyDescription) -> Selection: known_servers = topology_description.known_servers primary = None for sd in known_servers: if sd.server_type == SERVER_TYPE.RSPrimary: primary = sd break return Selection( topology_description, topology_description.known_servers, topology_description.common_wire_version, primary, ) def __init__( self, topology_description: TopologyDescription, server_descriptions: list[ServerDescription], common_wire_version: Optional[int], primary: Optional[ServerDescription], ): self.topology_description = topology_description self.server_descriptions = server_descriptions self.primary = primary self.common_wire_version = common_wire_version def with_server_descriptions(self, server_descriptions: list[ServerDescription]) -> Selection: return Selection( self.topology_description, server_descriptions, self.common_wire_version, self.primary ) def secondary_with_max_last_write_date(self) -> Optional[ServerDescription]: secondaries = secondary_server_selector(self) if secondaries.server_descriptions: return max( secondaries.server_descriptions, key=lambda sd: cast(float, sd.last_write_date) ) return None @property def primary_selection(self) -> Selection: primaries = [self.primary] if self.primary else [] return self.with_server_descriptions(primaries) @property def heartbeat_frequency(self) -> int: return self.topology_description.heartbeat_frequency @property def topology_type(self) -> int: return self.topology_description.topology_type def __bool__(self) -> bool: return bool(self.server_descriptions) def __getitem__(self, item: int) -> ServerDescription: return self.server_descriptions[item] def any_server_selector(selection: T) -> T: return selection def readable_server_selector(selection: Selection) -> Selection: return selection.with_server_descriptions( [s for s in selection.server_descriptions if s.is_readable] ) def writable_server_selector(selection: Selection) -> Selection: return selection.with_server_descriptions( [s for s in selection.server_descriptions if s.is_writable] ) def secondary_server_selector(selection: Selection) -> Selection: return selection.with_server_descriptions( [s for s in selection.server_descriptions if s.server_type == SERVER_TYPE.RSSecondary] ) def arbiter_server_selector(selection: Selection) -> Selection: return selection.with_server_descriptions( [s for s in selection.server_descriptions if s.server_type == SERVER_TYPE.RSArbiter] ) def writable_preferred_server_selector(selection: Selection) -> Selection: """Like PrimaryPreferred but doesn't use tags or latency.""" return writable_server_selector(selection) or secondary_server_selector(selection) def apply_single_tag_set(tag_set: TagSet, selection: Selection) -> Selection: """All servers matching one tag set. A tag set is a dict. A server matches if its tags are a superset: A server tagged {'a': '1', 'b': '2'} matches the tag set {'a': '1'}. The empty tag set {} matches any server. """ def tags_match(server_tags: Mapping[str, Any]) -> bool: for key, value in tag_set.items(): if key not in server_tags or server_tags[key] != value: return False return True return selection.with_server_descriptions( [s for s in selection.server_descriptions if tags_match(s.tags)] ) def apply_tag_sets(tag_sets: TagSets, selection: Selection) -> Selection: """All servers match a list of tag sets. tag_sets is a list of dicts. The empty tag set {} matches any server, and may be provided at the end of the list as a fallback. So [{'a': 'value'}, {}] expresses a preference for servers tagged {'a': 'value'}, but accepts any server if none matches the first preference. """ for tag_set in tag_sets: with_tag_set = apply_single_tag_set(tag_set, selection) if with_tag_set: return with_tag_set return selection.with_server_descriptions([]) def secondary_with_tags_server_selector(tag_sets: TagSets, selection: Selection) -> Selection: """All near-enough secondaries matching the tag sets.""" return apply_tag_sets(tag_sets, secondary_server_selector(selection)) def member_with_tags_server_selector(tag_sets: TagSets, selection: Selection) -> Selection: """All near-enough members matching the tag sets.""" return apply_tag_sets(tag_sets, readable_server_selector(selection)) mongodb-mongo-python-driver-509e9b7/pymongo/server_type.py000066400000000000000000000016331462766011000240510ustar00rootroot00000000000000# Copyright 2014-2015 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. """Type codes for MongoDB servers.""" from __future__ import annotations from typing import NamedTuple class _ServerType(NamedTuple): Unknown: int Mongos: int RSPrimary: int RSSecondary: int RSArbiter: int RSOther: int RSGhost: int Standalone: int LoadBalancer: int SERVER_TYPE = _ServerType(*range(9)) mongodb-mongo-python-driver-509e9b7/pymongo/settings.py000066400000000000000000000137011462766011000233410ustar00rootroot00000000000000# Copyright 2014-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. """Represent MongoClient's configuration.""" from __future__ import annotations import threading import traceback from typing import Any, Collection, Optional, Type, Union from bson.objectid import ObjectId from pymongo import common, monitor, pool from pymongo.common import LOCAL_THRESHOLD_MS, SERVER_SELECTION_TIMEOUT from pymongo.errors import ConfigurationError from pymongo.pool import Pool, PoolOptions from pymongo.server_description import ServerDescription from pymongo.topology_description import TOPOLOGY_TYPE, _ServerSelector class TopologySettings: def __init__( self, seeds: Optional[Collection[tuple[str, int]]] = None, replica_set_name: Optional[str] = None, pool_class: Optional[Type[Pool]] = None, pool_options: Optional[PoolOptions] = None, monitor_class: Optional[Type[monitor.Monitor]] = None, condition_class: Optional[Type[threading.Condition]] = None, local_threshold_ms: int = LOCAL_THRESHOLD_MS, server_selection_timeout: int = SERVER_SELECTION_TIMEOUT, heartbeat_frequency: int = common.HEARTBEAT_FREQUENCY, server_selector: Optional[_ServerSelector] = None, fqdn: Optional[str] = None, direct_connection: Optional[bool] = False, load_balanced: Optional[bool] = None, srv_service_name: str = common.SRV_SERVICE_NAME, srv_max_hosts: int = 0, server_monitoring_mode: str = common.SERVER_MONITORING_MODE, ): """Represent MongoClient's configuration. Take a list of (host, port) pairs and optional replica set name. """ if heartbeat_frequency < common.MIN_HEARTBEAT_INTERVAL: raise ConfigurationError( "heartbeatFrequencyMS cannot be less than %d" % (common.MIN_HEARTBEAT_INTERVAL * 1000,) ) self._seeds: Collection[tuple[str, int]] = seeds or [("localhost", 27017)] self._replica_set_name = replica_set_name self._pool_class: Type[Pool] = pool_class or pool.Pool self._pool_options: PoolOptions = pool_options or PoolOptions() self._monitor_class: Type[monitor.Monitor] = monitor_class or monitor.Monitor self._condition_class: Type[threading.Condition] = condition_class or threading.Condition self._local_threshold_ms = local_threshold_ms self._server_selection_timeout = server_selection_timeout self._server_selector = server_selector self._fqdn = fqdn self._heartbeat_frequency = heartbeat_frequency self._direct = direct_connection self._load_balanced = load_balanced self._srv_service_name = srv_service_name self._srv_max_hosts = srv_max_hosts or 0 self._server_monitoring_mode = server_monitoring_mode self._topology_id = ObjectId() # Store the allocation traceback to catch unclosed clients in the # test suite. self._stack = "".join(traceback.format_stack()) @property def seeds(self) -> Collection[tuple[str, int]]: """List of server addresses.""" return self._seeds @property def replica_set_name(self) -> Optional[str]: return self._replica_set_name @property def pool_class(self) -> Type[Pool]: return self._pool_class @property def pool_options(self) -> PoolOptions: return self._pool_options @property def monitor_class(self) -> Type[monitor.Monitor]: return self._monitor_class @property def condition_class(self) -> Type[threading.Condition]: return self._condition_class @property def local_threshold_ms(self) -> int: return self._local_threshold_ms @property def server_selection_timeout(self) -> int: return self._server_selection_timeout @property def server_selector(self) -> Optional[_ServerSelector]: return self._server_selector @property def heartbeat_frequency(self) -> int: return self._heartbeat_frequency @property def fqdn(self) -> Optional[str]: return self._fqdn @property def direct(self) -> Optional[bool]: """Connect directly to a single server, or use a set of servers? True if there is one seed and no replica_set_name. """ return self._direct @property def load_balanced(self) -> Optional[bool]: """True if the client was configured to connect to a load balancer.""" return self._load_balanced @property def srv_service_name(self) -> str: """The srvServiceName.""" return self._srv_service_name @property def srv_max_hosts(self) -> int: """The srvMaxHosts.""" return self._srv_max_hosts @property def server_monitoring_mode(self) -> str: """The serverMonitoringMode.""" return self._server_monitoring_mode def get_topology_type(self) -> int: if self.load_balanced: return TOPOLOGY_TYPE.LoadBalanced elif self.direct: return TOPOLOGY_TYPE.Single elif self.replica_set_name is not None: return TOPOLOGY_TYPE.ReplicaSetNoPrimary else: return TOPOLOGY_TYPE.Unknown def get_server_descriptions(self) -> dict[Union[tuple[str, int], Any], ServerDescription]: """Initial dict of (address, ServerDescription) for all seeds.""" return {address: ServerDescription(address) for address in self.seeds} mongodb-mongo-python-driver-509e9b7/pymongo/socket_checker.py000066400000000000000000000102001462766011000244440ustar00rootroot00000000000000# Copyright 2020-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. """Select / poll helper""" from __future__ import annotations import errno import select import sys from typing import Any, Optional, cast # PYTHON-2320: Jython does not fully support poll on SSL sockets, # https://bugs.jython.org/issue2900 _HAVE_POLL = hasattr(select, "poll") and not sys.platform.startswith("java") _SelectError = getattr(select, "error", OSError) def _errno_from_exception(exc: BaseException) -> Optional[int]: if hasattr(exc, "errno"): return cast(int, exc.errno) if exc.args: return cast(int, exc.args[0]) return None class SocketChecker: def __init__(self) -> None: self._poller: Optional[select.poll] if _HAVE_POLL: self._poller = select.poll() else: self._poller = None def select( self, sock: Any, read: bool = False, write: bool = False, timeout: Optional[float] = 0 ) -> bool: """Select for reads or writes with a timeout in seconds (or None). Returns True if the socket is readable/writable, False on timeout. """ res: Any while True: try: if self._poller: mask = select.POLLERR | select.POLLHUP if read: mask = mask | select.POLLIN | select.POLLPRI if write: mask = mask | select.POLLOUT self._poller.register(sock, mask) try: # poll() timeout is in milliseconds. select() # timeout is in seconds. timeout_ = None if timeout is None else timeout * 1000 res = self._poller.poll(timeout_) # poll returns a possibly-empty list containing # (fd, event) 2-tuples for the descriptors that have # events or errors to report. Return True if the list # is not empty. return bool(res) finally: self._poller.unregister(sock) else: rlist = [sock] if read else [] wlist = [sock] if write else [] res = select.select(rlist, wlist, [sock], timeout) # select returns a 3-tuple of lists of objects that are # ready: subsets of the first three arguments. Return # True if any of the lists are not empty. return any(res) except (_SelectError, OSError) as exc: # type: ignore if _errno_from_exception(exc) in (errno.EINTR, errno.EAGAIN): continue raise def socket_closed(self, sock: Any) -> bool: """Return True if we know socket has been closed, False otherwise.""" try: return self.select(sock, read=True) except (RuntimeError, KeyError): # RuntimeError is raised during a concurrent poll. KeyError # is raised by unregister if the socket is not in the poller. # These errors should not be possible since we protect the # poller with a mutex. raise except ValueError: # ValueError is raised by register/unregister/select if the # socket file descriptor is negative or outside the range for # select (> 1023). return True except Exception: # Any other exceptions should be attributed to a closed # or invalid socket. return True mongodb-mongo-python-driver-509e9b7/pymongo/srv_resolver.py000066400000000000000000000115571462766011000242430ustar00rootroot00000000000000# Copyright 2019-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. """Support for resolving hosts and options from mongodb+srv:// URIs.""" from __future__ import annotations import ipaddress import random from typing import TYPE_CHECKING, Any, Optional, Union from pymongo.common import CONNECT_TIMEOUT from pymongo.errors import ConfigurationError if TYPE_CHECKING: from dns import resolver def _have_dnspython() -> bool: try: import dns # noqa: F401 return True except ImportError: return False # dnspython can return bytes or str from various parts # of its API depending on version. We always want str. def maybe_decode(text: Union[str, bytes]) -> str: if isinstance(text, bytes): return text.decode() return text # PYTHON-2667 Lazily call dns.resolver methods for compatibility with eventlet. def _resolve(*args: Any, **kwargs: Any) -> resolver.Answer: from dns import resolver if hasattr(resolver, "resolve"): # dnspython >= 2 return resolver.resolve(*args, **kwargs) # dnspython 1.X return resolver.query(*args, **kwargs) _INVALID_HOST_MSG = ( "Invalid URI host: %s is not a valid hostname for 'mongodb+srv://'. " "Did you mean to use 'mongodb://'?" ) class _SrvResolver: def __init__( self, fqdn: str, connect_timeout: Optional[float], srv_service_name: str, srv_max_hosts: int = 0, ): self.__fqdn = fqdn self.__srv = srv_service_name self.__connect_timeout = connect_timeout or CONNECT_TIMEOUT self.__srv_max_hosts = srv_max_hosts or 0 # Validate the fully qualified domain name. try: ipaddress.ip_address(fqdn) raise ConfigurationError(_INVALID_HOST_MSG % ("an IP address",)) except ValueError: pass try: self.__plist = self.__fqdn.split(".")[1:] except Exception: raise ConfigurationError(_INVALID_HOST_MSG % (fqdn,)) from None self.__slen = len(self.__plist) if self.__slen < 2: raise ConfigurationError(_INVALID_HOST_MSG % (fqdn,)) def get_options(self) -> Optional[str]: from dns import resolver try: results = _resolve(self.__fqdn, "TXT", lifetime=self.__connect_timeout) except (resolver.NoAnswer, resolver.NXDOMAIN): # No TXT records return None except Exception as exc: raise ConfigurationError(str(exc)) from None if len(results) > 1: raise ConfigurationError("Only one TXT record is supported") return (b"&".join([b"".join(res.strings) for res in results])).decode("utf-8") def _resolve_uri(self, encapsulate_errors: bool) -> resolver.Answer: try: results = _resolve( "_" + self.__srv + "._tcp." + self.__fqdn, "SRV", lifetime=self.__connect_timeout ) except Exception as exc: if not encapsulate_errors: # Raise the original error. raise # Else, raise all errors as ConfigurationError. raise ConfigurationError(str(exc)) from None return results def _get_srv_response_and_hosts( self, encapsulate_errors: bool ) -> tuple[resolver.Answer, list[tuple[str, Any]]]: results = self._resolve_uri(encapsulate_errors) # Construct address tuples nodes = [ (maybe_decode(res.target.to_text(omit_final_dot=True)), res.port) for res in results ] # Validate hosts for node in nodes: try: nlist = node[0].lower().split(".")[1:][-self.__slen :] except Exception: raise ConfigurationError(f"Invalid SRV host: {node[0]}") from None if self.__plist != nlist: raise ConfigurationError(f"Invalid SRV host: {node[0]}") if self.__srv_max_hosts: nodes = random.sample(nodes, min(self.__srv_max_hosts, len(nodes))) return results, nodes def get_hosts(self) -> list[tuple[str, Any]]: _, nodes = self._get_srv_response_and_hosts(True) return nodes def get_hosts_and_min_ttl(self) -> tuple[list[tuple[str, Any]], int]: results, nodes = self._get_srv_response_and_hosts(False) rrset = results.rrset ttl = rrset.ttl if rrset else 0 return nodes, ttl mongodb-mongo-python-driver-509e9b7/pymongo/ssl_context.py000066400000000000000000000026211462766011000240450ustar00rootroot00000000000000# Copyright 2014-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. """A fake SSLContext implementation.""" from __future__ import annotations import ssl as _ssl # PROTOCOL_TLS_CLIENT is Python 3.6+ PROTOCOL_SSLv23 = getattr(_ssl, "PROTOCOL_TLS_CLIENT", _ssl.PROTOCOL_SSLv23) OP_NO_SSLv2 = getattr(_ssl, "OP_NO_SSLv2", 0) OP_NO_SSLv3 = getattr(_ssl, "OP_NO_SSLv3", 0) OP_NO_COMPRESSION = getattr(_ssl, "OP_NO_COMPRESSION", 0) # Python 3.7+, OpenSSL 1.1.0h+ OP_NO_RENEGOTIATION = getattr(_ssl, "OP_NO_RENEGOTIATION", 0) HAS_SNI = getattr(_ssl, "HAS_SNI", False) IS_PYOPENSSL = False # Errors raised by SSL sockets when in non-blocking mode. BLOCKING_IO_ERRORS = (_ssl.SSLWantReadError, _ssl.SSLWantWriteError) # Base Exception class SSLError = _ssl.SSLError from ssl import SSLContext # noqa: F401,E402 if hasattr(_ssl, "VERIFY_CRL_CHECK_LEAF"): from ssl import VERIFY_CRL_CHECK_LEAF # noqa: F401 mongodb-mongo-python-driver-509e9b7/pymongo/ssl_support.py000066400000000000000000000075051462766011000241030ustar00rootroot00000000000000# Copyright 2014-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. """Support for SSL in PyMongo.""" from __future__ import annotations from typing import Optional from pymongo.errors import ConfigurationError HAVE_SSL = True try: import pymongo.pyopenssl_context as _ssl except ImportError: try: import pymongo.ssl_context as _ssl # type: ignore[no-redef] except ImportError: HAVE_SSL = False if HAVE_SSL: # Note: The validate* functions below deal with users passing # CPython ssl module constants to configure certificate verification # at a high level. This is legacy behavior, but requires us to # import the ssl module even if we're only using it for this purpose. import ssl as _stdlibssl # noqa: F401 from ssl import CERT_NONE, CERT_REQUIRED HAS_SNI = _ssl.HAS_SNI IPADDR_SAFE = True SSLError = _ssl.SSLError BLOCKING_IO_ERRORS = _ssl.BLOCKING_IO_ERRORS def get_ssl_context( certfile: Optional[str], passphrase: Optional[str], ca_certs: Optional[str], crlfile: Optional[str], allow_invalid_certificates: bool, allow_invalid_hostnames: bool, disable_ocsp_endpoint_check: bool, ) -> _ssl.SSLContext: """Create and return an SSLContext object.""" verify_mode = CERT_NONE if allow_invalid_certificates else CERT_REQUIRED ctx = _ssl.SSLContext(_ssl.PROTOCOL_SSLv23) if verify_mode != CERT_NONE: ctx.check_hostname = not allow_invalid_hostnames else: ctx.check_hostname = False if hasattr(ctx, "check_ocsp_endpoint"): ctx.check_ocsp_endpoint = not disable_ocsp_endpoint_check if hasattr(ctx, "options"): # Explicitly disable SSLv2, SSLv3 and TLS compression. Note that # up to date versions of MongoDB 2.4 and above already disable # SSLv2 and SSLv3, python disables SSLv2 by default in >= 2.7.7 # and >= 3.3.4 and SSLv3 in >= 3.4.3. ctx.options |= _ssl.OP_NO_SSLv2 ctx.options |= _ssl.OP_NO_SSLv3 ctx.options |= _ssl.OP_NO_COMPRESSION ctx.options |= _ssl.OP_NO_RENEGOTIATION if certfile is not None: try: ctx.load_cert_chain(certfile, None, passphrase) except _ssl.SSLError as exc: raise ConfigurationError(f"Private key doesn't match certificate: {exc}") from None if crlfile is not None: if _ssl.IS_PYOPENSSL: raise ConfigurationError("tlsCRLFile cannot be used with PyOpenSSL") # Match the server's behavior. ctx.verify_flags = getattr( # type:ignore[attr-defined] _ssl, "VERIFY_CRL_CHECK_LEAF", 0 ) ctx.load_verify_locations(crlfile) if ca_certs is not None: ctx.load_verify_locations(ca_certs) elif verify_mode != CERT_NONE: ctx.load_default_certs() ctx.verify_mode = verify_mode return ctx else: class SSLError(Exception): # type: ignore pass HAS_SNI = False IPADDR_SAFE = False BLOCKING_IO_ERRORS = () # type:ignore[assignment] def get_ssl_context(*dummy): # type: ignore """No ssl module, raise ConfigurationError.""" raise ConfigurationError("The ssl module is not available.") mongodb-mongo-python-driver-509e9b7/pymongo/topology.py000066400000000000000000001206461462766011000233640ustar00rootroot00000000000000# Copyright 2014-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. """Internal class to monitor a topology of one or more servers.""" from __future__ import annotations import logging import os import queue import random import sys import time import warnings import weakref from pathlib import Path from typing import TYPE_CHECKING, Any, Callable, Mapping, Optional, cast from pymongo import _csot, common, helpers, periodic_executor from pymongo.client_session import _ServerSession, _ServerSessionPool from pymongo.errors import ( ConnectionFailure, InvalidOperation, NetworkTimeout, NotPrimaryError, OperationFailure, PyMongoError, ServerSelectionTimeoutError, WriteError, ) from pymongo.hello import Hello from pymongo.lock import _create_lock from pymongo.logger import ( _SERVER_SELECTION_LOGGER, _debug_log, _ServerSelectionStatusMessage, ) from pymongo.monitor import SrvMonitor from pymongo.pool import Pool, PoolOptions from pymongo.server import Server from pymongo.server_description import ServerDescription from pymongo.server_selectors import ( Selection, any_server_selector, arbiter_server_selector, secondary_server_selector, writable_server_selector, ) from pymongo.topology_description import ( SRV_POLLING_TOPOLOGIES, TOPOLOGY_TYPE, TopologyDescription, _updated_topology_description_srv_polling, updated_topology_description, ) if TYPE_CHECKING: from bson import ObjectId from pymongo.settings import TopologySettings from pymongo.typings import ClusterTime, _Address _pymongo_dir = str(Path(__file__).parent) def process_events_queue(queue_ref: weakref.ReferenceType[queue.Queue]) -> bool: q = queue_ref() if not q: return False # Cancel PeriodicExecutor. while True: try: event = q.get_nowait() except queue.Empty: break else: fn, args = event fn(*args) return True # Continue PeriodicExecutor. class Topology: """Monitor a topology of one or more servers.""" def __init__(self, topology_settings: TopologySettings): self._topology_id = topology_settings._topology_id self._listeners = topology_settings._pool_options._event_listeners self._publish_server = self._listeners is not None and self._listeners.enabled_for_server self._publish_tp = self._listeners is not None and self._listeners.enabled_for_topology # Create events queue if there are publishers. self._events = None self.__events_executor: Any = None if self._publish_server or self._publish_tp: self._events = queue.Queue(maxsize=100) if self._publish_tp: assert self._events is not None self._events.put((self._listeners.publish_topology_opened, (self._topology_id,))) self._settings = topology_settings topology_description = TopologyDescription( topology_settings.get_topology_type(), topology_settings.get_server_descriptions(), topology_settings.replica_set_name, None, None, topology_settings, ) self._description = topology_description if self._publish_tp: assert self._events is not None initial_td = TopologyDescription( TOPOLOGY_TYPE.Unknown, {}, None, None, None, self._settings ) self._events.put( ( self._listeners.publish_topology_description_changed, (initial_td, self._description, self._topology_id), ) ) for seed in topology_settings.seeds: if self._publish_server: assert self._events is not None self._events.put((self._listeners.publish_server_opened, (seed, self._topology_id))) # Store the seed list to help diagnose errors in _error_message(). self._seed_addresses = list(topology_description.server_descriptions()) self._opened = False self._closed = False self._lock = _create_lock() self._condition = self._settings.condition_class(self._lock) self._servers: dict[_Address, Server] = {} self._pid: Optional[int] = None self._max_cluster_time: Optional[ClusterTime] = None self._session_pool = _ServerSessionPool() if self._publish_server or self._publish_tp: assert self._events is not None weak: weakref.ReferenceType[queue.Queue] def target() -> bool: return process_events_queue(weak) executor = periodic_executor.PeriodicExecutor( interval=common.EVENTS_QUEUE_FREQUENCY, min_interval=common.MIN_HEARTBEAT_INTERVAL, target=target, name="pymongo_events_thread", ) # We strongly reference the executor and it weakly references # the queue via this closure. When the topology is freed, stop # the executor soon. weak = weakref.ref(self._events, executor.close) self.__events_executor = executor executor.open() self._srv_monitor = None if self._settings.fqdn is not None and not self._settings.load_balanced: self._srv_monitor = SrvMonitor(self, self._settings) def open(self) -> None: """Start monitoring, or restart after a fork. No effect if called multiple times. .. warning:: Topology is shared among multiple threads and is protected by mutual exclusion. Using Topology from a process other than the one that initialized it will emit a warning and may result in deadlock. To prevent this from happening, MongoClient must be created after any forking. """ pid = os.getpid() if self._pid is None: self._pid = pid elif pid != self._pid: self._pid = pid if sys.version_info[:2] >= (3, 12): kwargs = {"skip_file_prefixes": (_pymongo_dir,)} else: kwargs = {"stacklevel": 6} # Ignore B028 warning for missing stacklevel. warnings.warn( # type: ignore[call-overload] # noqa: B028 "MongoClient opened before fork. May not be entirely fork-safe, " "proceed with caution. See PyMongo's documentation for details: " "https://pymongo.readthedocs.io/en/stable/faq.html#" "is-pymongo-fork-safe", **kwargs, ) with self._lock: # Close servers and clear the pools. for server in self._servers.values(): server.close() # Reset the session pool to avoid duplicate sessions in # the child process. self._session_pool.reset() with self._lock: self._ensure_opened() def get_server_selection_timeout(self) -> float: # CSOT: use remaining timeout when set. timeout = _csot.remaining() if timeout is None: return self._settings.server_selection_timeout return timeout def select_servers( self, selector: Callable[[Selection], Selection], operation: str, server_selection_timeout: Optional[float] = None, address: Optional[_Address] = None, operation_id: Optional[int] = None, ) -> list[Server]: """Return a list of Servers matching selector, or time out. :param selector: function that takes a list of Servers and returns a subset of them. :param operation: The name of the operation that the server is being selected for. :param server_selection_timeout: maximum seconds to wait. If not provided, the default value common.SERVER_SELECTION_TIMEOUT is used. :param address: optional server address to select. Calls self.open() if needed. Raises exc:`ServerSelectionTimeoutError` after `server_selection_timeout` if no matching servers are found. """ if server_selection_timeout is None: server_timeout = self.get_server_selection_timeout() else: server_timeout = server_selection_timeout with self._lock: server_descriptions = self._select_servers_loop( selector, server_timeout, operation, operation_id, address ) return [ cast(Server, self.get_server_by_address(sd.address)) for sd in server_descriptions ] def _select_servers_loop( self, selector: Callable[[Selection], Selection], timeout: float, operation: str, operation_id: Optional[int], address: Optional[_Address], ) -> list[ServerDescription]: """select_servers() guts. Hold the lock when calling this.""" now = time.monotonic() end_time = now + timeout logged_waiting = False if _SERVER_SELECTION_LOGGER.isEnabledFor(logging.DEBUG): _debug_log( _SERVER_SELECTION_LOGGER, message=_ServerSelectionStatusMessage.STARTED, selector=selector, operation=operation, operationId=operation_id, topologyDescription=self.description, clientId=self.description._topology_settings._topology_id, ) server_descriptions = self._description.apply_selector( selector, address, custom_selector=self._settings.server_selector ) while not server_descriptions: # No suitable servers. if timeout == 0 or now > end_time: if _SERVER_SELECTION_LOGGER.isEnabledFor(logging.DEBUG): _debug_log( _SERVER_SELECTION_LOGGER, message=_ServerSelectionStatusMessage.FAILED, selector=selector, operation=operation, operationId=operation_id, topologyDescription=self.description, clientId=self.description._topology_settings._topology_id, failure=self._error_message(selector), ) raise ServerSelectionTimeoutError( f"{self._error_message(selector)}, Timeout: {timeout}s, Topology Description: {self.description!r}" ) if not logged_waiting: _debug_log( _SERVER_SELECTION_LOGGER, message=_ServerSelectionStatusMessage.WAITING, selector=selector, operation=operation, operationId=operation_id, topologyDescription=self.description, clientId=self.description._topology_settings._topology_id, remainingTimeMS=int(end_time - time.monotonic()), ) logged_waiting = True self._ensure_opened() self._request_check_all() # Release the lock and wait for the topology description to # change, or for a timeout. We won't miss any changes that # came after our most recent apply_selector call, since we've # held the lock until now. self._condition.wait(common.MIN_HEARTBEAT_INTERVAL) self._description.check_compatible() now = time.monotonic() server_descriptions = self._description.apply_selector( selector, address, custom_selector=self._settings.server_selector ) self._description.check_compatible() return server_descriptions def _select_server( self, selector: Callable[[Selection], Selection], operation: str, server_selection_timeout: Optional[float] = None, address: Optional[_Address] = None, deprioritized_servers: Optional[list[Server]] = None, operation_id: Optional[int] = None, ) -> Server: servers = self.select_servers( selector, operation, server_selection_timeout, address, operation_id ) servers = _filter_servers(servers, deprioritized_servers) if len(servers) == 1: return servers[0] server1, server2 = random.sample(servers, 2) if server1.pool.operation_count <= server2.pool.operation_count: return server1 else: return server2 def select_server( self, selector: Callable[[Selection], Selection], operation: str, server_selection_timeout: Optional[float] = None, address: Optional[_Address] = None, deprioritized_servers: Optional[list[Server]] = None, operation_id: Optional[int] = None, ) -> Server: """Like select_servers, but choose a random server if several match.""" server = self._select_server( selector, operation, server_selection_timeout, address, deprioritized_servers, operation_id=operation_id, ) if _csot.get_timeout(): _csot.set_rtt(server.description.min_round_trip_time) if _SERVER_SELECTION_LOGGER.isEnabledFor(logging.DEBUG): _debug_log( _SERVER_SELECTION_LOGGER, message=_ServerSelectionStatusMessage.SUCCEEDED, selector=selector, operation=operation, operationId=operation_id, topologyDescription=self.description, clientId=self.description._topology_settings._topology_id, serverHost=server.description.address[0], serverPort=server.description.address[1], ) return server def select_server_by_address( self, address: _Address, operation: str, server_selection_timeout: Optional[int] = None, operation_id: Optional[int] = None, ) -> Server: """Return a Server for "address", reconnecting if necessary. If the server's type is not known, request an immediate check of all servers. Time out after "server_selection_timeout" if the server cannot be reached. :param address: A (host, port) pair. :param operation: The name of the operation that the server is being selected for. :param server_selection_timeout: maximum seconds to wait. If not provided, the default value common.SERVER_SELECTION_TIMEOUT is used. :param operation_id: The unique id of the current operation being performed. Defaults to None if not provided. Calls self.open() if needed. Raises exc:`ServerSelectionTimeoutError` after `server_selection_timeout` if no matching servers are found. """ return self.select_server( any_server_selector, operation, server_selection_timeout, address, operation_id=operation_id, ) def _process_change( self, server_description: ServerDescription, reset_pool: bool = False, interrupt_connections: bool = False, ) -> None: """Process a new ServerDescription on an opened topology. Hold the lock when calling this. """ td_old = self._description sd_old = td_old._server_descriptions[server_description.address] if _is_stale_server_description(sd_old, server_description): # This is a stale hello response. Ignore it. return new_td = updated_topology_description(self._description, server_description) # CMAP: Ensure the pool is "ready" when the server is selectable. if server_description.is_readable or ( server_description.is_server_type_known and new_td.topology_type == TOPOLOGY_TYPE.Single ): server = self._servers.get(server_description.address) if server: server.pool.ready() suppress_event = (self._publish_server or self._publish_tp) and sd_old == server_description if self._publish_server and not suppress_event: assert self._events is not None self._events.put( ( self._listeners.publish_server_description_changed, (sd_old, server_description, server_description.address, self._topology_id), ) ) self._description = new_td self._update_servers() self._receive_cluster_time_no_lock(server_description.cluster_time) if self._publish_tp and not suppress_event: assert self._events is not None self._events.put( ( self._listeners.publish_topology_description_changed, (td_old, self._description, self._topology_id), ) ) # Shutdown SRV polling for unsupported cluster types. # This is only applicable if the old topology was Unknown, and the # new one is something other than Unknown or Sharded. if self._srv_monitor and ( td_old.topology_type == TOPOLOGY_TYPE.Unknown and self._description.topology_type not in SRV_POLLING_TOPOLOGIES ): self._srv_monitor.close() # Clear the pool from a failed heartbeat. if reset_pool: server = self._servers.get(server_description.address) if server: server.pool.reset(interrupt_connections=interrupt_connections) # Wake waiters in select_servers(). self._condition.notify_all() def on_change( self, server_description: ServerDescription, reset_pool: bool = False, interrupt_connections: bool = False, ) -> None: """Process a new ServerDescription after an hello call completes.""" # We do no I/O holding the lock. with self._lock: # Monitors may continue working on hello calls for some time # after a call to Topology.close, so this method may be called at # any time. Ensure the topology is open before processing the # change. # Any monitored server was definitely in the topology description # once. Check if it's still in the description or if some state- # change removed it. E.g., we got a host list from the primary # that didn't include this server. if self._opened and self._description.has_server(server_description.address): self._process_change(server_description, reset_pool, interrupt_connections) def _process_srv_update(self, seedlist: list[tuple[str, Any]]) -> None: """Process a new seedlist on an opened topology. Hold the lock when calling this. """ td_old = self._description if td_old.topology_type not in SRV_POLLING_TOPOLOGIES: return self._description = _updated_topology_description_srv_polling(self._description, seedlist) self._update_servers() if self._publish_tp: assert self._events is not None self._events.put( ( self._listeners.publish_topology_description_changed, (td_old, self._description, self._topology_id), ) ) def on_srv_update(self, seedlist: list[tuple[str, Any]]) -> None: """Process a new list of nodes obtained from scanning SRV records.""" # We do no I/O holding the lock. with self._lock: if self._opened: self._process_srv_update(seedlist) def get_server_by_address(self, address: _Address) -> Optional[Server]: """Get a Server or None. Returns the current version of the server immediately, even if it's Unknown or absent from the topology. Only use this in unittests. In driver code, use select_server_by_address, since then you're assured a recent view of the server's type and wire protocol version. """ return self._servers.get(address) def has_server(self, address: _Address) -> bool: return address in self._servers def get_primary(self) -> Optional[_Address]: """Return primary's address or None.""" # Implemented here in Topology instead of MongoClient, so it can lock. with self._lock: topology_type = self._description.topology_type if topology_type != TOPOLOGY_TYPE.ReplicaSetWithPrimary: return None return writable_server_selector(self._new_selection())[0].address def _get_replica_set_members(self, selector: Callable[[Selection], Selection]) -> set[_Address]: """Return set of replica set member addresses.""" # Implemented here in Topology instead of MongoClient, so it can lock. with self._lock: topology_type = self._description.topology_type if topology_type not in ( TOPOLOGY_TYPE.ReplicaSetWithPrimary, TOPOLOGY_TYPE.ReplicaSetNoPrimary, ): return set() return {sd.address for sd in iter(selector(self._new_selection()))} def get_secondaries(self) -> set[_Address]: """Return set of secondary addresses.""" return self._get_replica_set_members(secondary_server_selector) def get_arbiters(self) -> set[_Address]: """Return set of arbiter addresses.""" return self._get_replica_set_members(arbiter_server_selector) def max_cluster_time(self) -> Optional[ClusterTime]: """Return a document, the highest seen $clusterTime.""" return self._max_cluster_time def _receive_cluster_time_no_lock(self, cluster_time: Optional[Mapping[str, Any]]) -> None: # Driver Sessions Spec: "Whenever a driver receives a cluster time from # a server it MUST compare it to the current highest seen cluster time # for the deployment. If the new cluster time is higher than the # highest seen cluster time it MUST become the new highest seen cluster # time. Two cluster times are compared using only the BsonTimestamp # value of the clusterTime embedded field." if cluster_time: # ">" uses bson.timestamp.Timestamp's comparison operator. if ( not self._max_cluster_time or cluster_time["clusterTime"] > self._max_cluster_time["clusterTime"] ): self._max_cluster_time = cluster_time def receive_cluster_time(self, cluster_time: Optional[Mapping[str, Any]]) -> None: with self._lock: self._receive_cluster_time_no_lock(cluster_time) def request_check_all(self, wait_time: int = 5) -> None: """Wake all monitors, wait for at least one to check its server.""" with self._lock: self._request_check_all() self._condition.wait(wait_time) def data_bearing_servers(self) -> list[ServerDescription]: """Return a list of all data-bearing servers. This includes any server that might be selected for an operation. """ if self._description.topology_type == TOPOLOGY_TYPE.Single: return self._description.known_servers return self._description.readable_servers def update_pool(self) -> None: # Remove any stale sockets and add new sockets if pool is too small. servers = [] with self._lock: # Only update pools for data-bearing servers. for sd in self.data_bearing_servers(): server = self._servers[sd.address] servers.append((server, server.pool.gen.get_overall())) for server, generation in servers: try: server.pool.remove_stale_sockets(generation) except PyMongoError as exc: ctx = _ErrorContext(exc, 0, generation, False, None) self.handle_error(server.description.address, ctx) raise def close(self) -> None: """Clear pools and terminate monitors. Topology does not reopen on demand. Any further operations will raise :exc:`~.errors.InvalidOperation`. """ with self._lock: for server in self._servers.values(): server.close() # Mark all servers Unknown. self._description = self._description.reset() for address, sd in self._description.server_descriptions().items(): if address in self._servers: self._servers[address].description = sd # Stop SRV polling thread. if self._srv_monitor: self._srv_monitor.close() self._opened = False self._closed = True # Publish only after releasing the lock. if self._publish_tp: assert self._events is not None self._events.put((self._listeners.publish_topology_closed, (self._topology_id,))) if self._publish_server or self._publish_tp: self.__events_executor.close() @property def description(self) -> TopologyDescription: return self._description def pop_all_sessions(self) -> list[_ServerSession]: """Pop all session ids from the pool.""" with self._lock: return self._session_pool.pop_all() def get_server_session(self, session_timeout_minutes: Optional[int]) -> _ServerSession: """Start or resume a server session, or raise ConfigurationError.""" with self._lock: return self._session_pool.get_server_session(session_timeout_minutes) def return_server_session(self, server_session: _ServerSession, lock: bool) -> None: if lock: with self._lock: self._session_pool.return_server_session( server_session, self._description.logical_session_timeout_minutes ) else: # Called from a __del__ method, can't use a lock. self._session_pool.return_server_session_no_lock(server_session) def _new_selection(self) -> Selection: """A Selection object, initially including all known servers. Hold the lock when calling this. """ return Selection.from_topology_description(self._description) def _ensure_opened(self) -> None: """Start monitors, or restart after a fork. Hold the lock when calling this. """ if self._closed: raise InvalidOperation("Cannot use MongoClient after close") if not self._opened: self._opened = True self._update_servers() # Start or restart the events publishing thread. if self._publish_tp or self._publish_server: self.__events_executor.open() # Start the SRV polling thread. if self._srv_monitor and (self.description.topology_type in SRV_POLLING_TOPOLOGIES): self._srv_monitor.open() if self._settings.load_balanced: # Emit initial SDAM events for load balancer mode. self._process_change( ServerDescription( self._seed_addresses[0], Hello({"ok": 1, "serviceId": self._topology_id, "maxWireVersion": 13}), ) ) # Ensure that the monitors are open. for server in self._servers.values(): server.open() def _is_stale_error(self, address: _Address, err_ctx: _ErrorContext) -> bool: server = self._servers.get(address) if server is None: # Another thread removed this server from the topology. return True if server._pool.stale_generation(err_ctx.sock_generation, err_ctx.service_id): # This is an outdated error from a previous pool version. return True # topologyVersion check, ignore error when cur_tv >= error_tv: cur_tv = server.description.topology_version error = err_ctx.error error_tv = None if error and hasattr(error, "details"): if isinstance(error.details, dict): error_tv = error.details.get("topologyVersion") return _is_stale_error_topology_version(cur_tv, error_tv) def _handle_error(self, address: _Address, err_ctx: _ErrorContext) -> None: if self._is_stale_error(address, err_ctx): return server = self._servers[address] error = err_ctx.error service_id = err_ctx.service_id # Ignore a handshake error if the server is behind a load balancer but # the service ID is unknown. This indicates that the error happened # when dialing the connection or during the MongoDB handshake, so we # don't know the service ID to use for clearing the pool. if self._settings.load_balanced and not service_id and not err_ctx.completed_handshake: return if isinstance(error, NetworkTimeout) and err_ctx.completed_handshake: # The socket has been closed. Don't reset the server. # Server Discovery And Monitoring Spec: "When an application # operation fails because of any network error besides a socket # timeout...." return elif isinstance(error, WriteError): # Ignore writeErrors. return elif isinstance(error, (NotPrimaryError, OperationFailure)): # As per the SDAM spec if: # - the server sees a "not primary" error, and # - the server is not shutting down, and # - the server version is >= 4.2, then # we keep the existing connection pool, but mark the server type # as Unknown and request an immediate check of the server. # Otherwise, we clear the connection pool, mark the server as # Unknown and request an immediate check of the server. if hasattr(error, "code"): err_code = error.code else: # Default error code if one does not exist. default = 10107 if isinstance(error, NotPrimaryError) else None err_code = error.details.get("code", default) # type: ignore[union-attr] if err_code in helpers._NOT_PRIMARY_CODES: is_shutting_down = err_code in helpers._SHUTDOWN_CODES # Mark server Unknown, clear the pool, and request check. if not self._settings.load_balanced: self._process_change(ServerDescription(address, error=error)) if is_shutting_down or (err_ctx.max_wire_version <= 7): # Clear the pool. server.reset(service_id) server.request_check() elif not err_ctx.completed_handshake: # Unknown command error during the connection handshake. if not self._settings.load_balanced: self._process_change(ServerDescription(address, error=error)) # Clear the pool. server.reset(service_id) elif isinstance(error, ConnectionFailure): # "Client MUST replace the server's description with type Unknown # ... MUST NOT request an immediate check of the server." if not self._settings.load_balanced: self._process_change(ServerDescription(address, error=error)) # Clear the pool. server.reset(service_id) # "When a client marks a server Unknown from `Network error when # reading or writing`_, clients MUST cancel the hello check on # that server and close the current monitoring connection." server._monitor.cancel_check() def handle_error(self, address: _Address, err_ctx: _ErrorContext) -> None: """Handle an application error. May reset the server to Unknown, clear the pool, and request an immediate check depending on the error and the context. """ with self._lock: self._handle_error(address, err_ctx) def _request_check_all(self) -> None: """Wake all monitors. Hold the lock when calling this.""" for server in self._servers.values(): server.request_check() def _update_servers(self) -> None: """Sync our Servers from TopologyDescription.server_descriptions. Hold the lock while calling this. """ for address, sd in self._description.server_descriptions().items(): if address not in self._servers: monitor = self._settings.monitor_class( server_description=sd, topology=self, pool=self._create_pool_for_monitor(address), topology_settings=self._settings, ) weak = None if self._publish_server and self._events is not None: weak = weakref.ref(self._events) server = Server( server_description=sd, pool=self._create_pool_for_server(address), monitor=monitor, topology_id=self._topology_id, listeners=self._listeners, events=weak, ) self._servers[address] = server server.open() else: # Cache old is_writable value. was_writable = self._servers[address].description.is_writable # Update server description. self._servers[address].description = sd # Update is_writable value of the pool, if it changed. if was_writable != sd.is_writable: self._servers[address].pool.update_is_writable(sd.is_writable) for address, server in list(self._servers.items()): if not self._description.has_server(address): server.close() self._servers.pop(address) def _create_pool_for_server(self, address: _Address) -> Pool: return self._settings.pool_class( address, self._settings.pool_options, client_id=self._topology_id ) def _create_pool_for_monitor(self, address: _Address) -> Pool: options = self._settings.pool_options # According to the Server Discovery And Monitoring Spec, monitors use # connect_timeout for both connect_timeout and socket_timeout. The # pool only has one socket so maxPoolSize and so on aren't needed. monitor_pool_options = PoolOptions( connect_timeout=options.connect_timeout, socket_timeout=options.connect_timeout, ssl_context=options._ssl_context, tls_allow_invalid_hostnames=options.tls_allow_invalid_hostnames, event_listeners=options._event_listeners, appname=options.appname, driver=options.driver, pause_enabled=False, server_api=options.server_api, ) return self._settings.pool_class( address, monitor_pool_options, handshake=False, client_id=self._topology_id ) def _error_message(self, selector: Callable[[Selection], Selection]) -> str: """Format an error message if server selection fails. Hold the lock when calling this. """ is_replica_set = self._description.topology_type in ( TOPOLOGY_TYPE.ReplicaSetWithPrimary, TOPOLOGY_TYPE.ReplicaSetNoPrimary, ) if is_replica_set: server_plural = "replica set members" elif self._description.topology_type == TOPOLOGY_TYPE.Sharded: server_plural = "mongoses" else: server_plural = "servers" if self._description.known_servers: # We've connected, but no servers match the selector. if selector is writable_server_selector: if is_replica_set: return "No primary available for writes" else: return "No %s available for writes" % server_plural else: return f'No {server_plural} match selector "{selector}"' else: addresses = list(self._description.server_descriptions()) servers = list(self._description.server_descriptions().values()) if not servers: if is_replica_set: # We removed all servers because of the wrong setName? return 'No {} available for replica set name "{}"'.format( server_plural, self._settings.replica_set_name, ) else: return "No %s available" % server_plural # 1 or more servers, all Unknown. Are they unknown for one reason? error = servers[0].error same = all(server.error == error for server in servers[1:]) if same: if error is None: # We're still discovering. return "No %s found yet" % server_plural if is_replica_set and not set(addresses).intersection(self._seed_addresses): # We replaced our seeds with new hosts but can't reach any. return ( "Could not reach any servers in %s. Replica set is" " configured with internal hostnames or IPs?" % addresses ) return str(error) else: return ",".join(str(server.error) for server in servers if server.error) def __repr__(self) -> str: msg = "" if not self._opened: msg = "CLOSED " return f"<{self.__class__.__name__} {msg}{self._description!r}>" def eq_props(self) -> tuple[tuple[_Address, ...], Optional[str], Optional[str], str]: """The properties to use for MongoClient/Topology equality checks.""" ts = self._settings return (tuple(sorted(ts.seeds)), ts.replica_set_name, ts.fqdn, ts.srv_service_name) def __eq__(self, other: object) -> bool: if isinstance(other, self.__class__): return self.eq_props() == other.eq_props() return NotImplemented def __hash__(self) -> int: return hash(self.eq_props()) class _ErrorContext: """An error with context for SDAM error handling.""" def __init__( self, error: BaseException, max_wire_version: int, sock_generation: int, completed_handshake: bool, service_id: Optional[ObjectId], ): self.error = error self.max_wire_version = max_wire_version self.sock_generation = sock_generation self.completed_handshake = completed_handshake self.service_id = service_id def _is_stale_error_topology_version( current_tv: Optional[Mapping[str, Any]], error_tv: Optional[Mapping[str, Any]] ) -> bool: """Return True if the error's topologyVersion is <= current.""" if current_tv is None or error_tv is None: return False if current_tv["processId"] != error_tv["processId"]: return False return current_tv["counter"] >= error_tv["counter"] def _is_stale_server_description(current_sd: ServerDescription, new_sd: ServerDescription) -> bool: """Return True if the new topologyVersion is < current.""" current_tv, new_tv = current_sd.topology_version, new_sd.topology_version if current_tv is None or new_tv is None: return False if current_tv["processId"] != new_tv["processId"]: return False return current_tv["counter"] > new_tv["counter"] def _filter_servers( candidates: list[Server], deprioritized_servers: Optional[list[Server]] = None ) -> list[Server]: """Filter out deprioritized servers from a list of server candidates.""" if not deprioritized_servers: return candidates filtered = [server for server in candidates if server not in deprioritized_servers] # If not possible to pick a prioritized server, return the original list return filtered or candidates mongodb-mongo-python-driver-509e9b7/pymongo/topology_description.py000066400000000000000000000643621462766011000257710ustar00rootroot00000000000000# Copyright 2014-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. """Represent a deployment of MongoDB servers.""" from __future__ import annotations from random import sample from typing import ( Any, Callable, List, Mapping, MutableMapping, NamedTuple, Optional, cast, ) from bson.min_key import MinKey from bson.objectid import ObjectId from pymongo import common from pymongo.errors import ConfigurationError from pymongo.read_preferences import ReadPreference, _AggWritePref, _ServerMode from pymongo.server_description import ServerDescription from pymongo.server_selectors import Selection from pymongo.server_type import SERVER_TYPE from pymongo.typings import _Address # Enumeration for various kinds of MongoDB cluster topologies. class _TopologyType(NamedTuple): Single: int ReplicaSetNoPrimary: int ReplicaSetWithPrimary: int Sharded: int Unknown: int LoadBalanced: int TOPOLOGY_TYPE = _TopologyType(*range(6)) # Topologies compatible with SRV record polling. SRV_POLLING_TOPOLOGIES: tuple[int, int] = (TOPOLOGY_TYPE.Unknown, TOPOLOGY_TYPE.Sharded) _ServerSelector = Callable[[List[ServerDescription]], List[ServerDescription]] class TopologyDescription: def __init__( self, topology_type: int, server_descriptions: dict[_Address, ServerDescription], replica_set_name: Optional[str], max_set_version: Optional[int], max_election_id: Optional[ObjectId], topology_settings: Any, ) -> None: """Representation of a deployment of MongoDB servers. :param topology_type: initial type :param server_descriptions: dict of (address, ServerDescription) for all seeds :param replica_set_name: replica set name or None :param max_set_version: greatest setVersion seen from a primary, or None :param max_election_id: greatest electionId seen from a primary, or None :param topology_settings: a TopologySettings """ self._topology_type = topology_type self._replica_set_name = replica_set_name self._server_descriptions = server_descriptions self._max_set_version = max_set_version self._max_election_id = max_election_id # The heartbeat_frequency is used in staleness estimates. self._topology_settings = topology_settings # Is PyMongo compatible with all servers' wire protocols? self._incompatible_err = None if self._topology_type != TOPOLOGY_TYPE.LoadBalanced: self._init_incompatible_err() # Server Discovery And Monitoring Spec: Whenever a client updates the # TopologyDescription from an hello response, it MUST set # TopologyDescription.logicalSessionTimeoutMinutes to the smallest # logicalSessionTimeoutMinutes value among ServerDescriptions of all # data-bearing server types. If any have a null # logicalSessionTimeoutMinutes, then # TopologyDescription.logicalSessionTimeoutMinutes MUST be set to null. readable_servers = self.readable_servers if not readable_servers: self._ls_timeout_minutes = None elif any(s.logical_session_timeout_minutes is None for s in readable_servers): self._ls_timeout_minutes = None else: self._ls_timeout_minutes = min( # type: ignore[type-var] s.logical_session_timeout_minutes for s in readable_servers ) def _init_incompatible_err(self) -> None: """Internal compatibility check for non-load balanced topologies.""" for s in self._server_descriptions.values(): if not s.is_server_type_known: continue # s.min/max_wire_version is the server's wire protocol. # MIN/MAX_SUPPORTED_WIRE_VERSION is what PyMongo supports. server_too_new = ( # Server too new. s.min_wire_version is not None and s.min_wire_version > common.MAX_SUPPORTED_WIRE_VERSION ) server_too_old = ( # Server too old. s.max_wire_version is not None and s.max_wire_version < common.MIN_SUPPORTED_WIRE_VERSION ) if server_too_new: self._incompatible_err = ( "Server at %s:%d requires wire version %d, but this " # type: ignore "version of PyMongo only supports up to %d." % ( s.address[0], s.address[1] or 0, s.min_wire_version, common.MAX_SUPPORTED_WIRE_VERSION, ) ) elif server_too_old: self._incompatible_err = ( "Server at %s:%d reports wire version %d, but this " # type: ignore "version of PyMongo requires at least %d (MongoDB %s)." % ( s.address[0], s.address[1] or 0, s.max_wire_version, common.MIN_SUPPORTED_WIRE_VERSION, common.MIN_SUPPORTED_SERVER_VERSION, ) ) break def check_compatible(self) -> None: """Raise ConfigurationError if any server is incompatible. A server is incompatible if its wire protocol version range does not overlap with PyMongo's. """ if self._incompatible_err: raise ConfigurationError(self._incompatible_err) def has_server(self, address: _Address) -> bool: return address in self._server_descriptions def reset_server(self, address: _Address) -> TopologyDescription: """A copy of this description, with one server marked Unknown.""" unknown_sd = self._server_descriptions[address].to_unknown() return updated_topology_description(self, unknown_sd) def reset(self) -> TopologyDescription: """A copy of this description, with all servers marked Unknown.""" if self._topology_type == TOPOLOGY_TYPE.ReplicaSetWithPrimary: topology_type = TOPOLOGY_TYPE.ReplicaSetNoPrimary else: topology_type = self._topology_type # The default ServerDescription's type is Unknown. sds = {address: ServerDescription(address) for address in self._server_descriptions} return TopologyDescription( topology_type, sds, self._replica_set_name, self._max_set_version, self._max_election_id, self._topology_settings, ) def server_descriptions(self) -> dict[_Address, ServerDescription]: """dict of (address, :class:`~pymongo.server_description.ServerDescription`). """ return self._server_descriptions.copy() @property def topology_type(self) -> int: """The type of this topology.""" return self._topology_type @property def topology_type_name(self) -> str: """The topology type as a human readable string. .. versionadded:: 3.4 """ return TOPOLOGY_TYPE._fields[self._topology_type] @property def replica_set_name(self) -> Optional[str]: """The replica set name.""" return self._replica_set_name @property def max_set_version(self) -> Optional[int]: """Greatest setVersion seen from a primary, or None.""" return self._max_set_version @property def max_election_id(self) -> Optional[ObjectId]: """Greatest electionId seen from a primary, or None.""" return self._max_election_id @property def logical_session_timeout_minutes(self) -> Optional[int]: """Minimum logical session timeout, or None.""" return self._ls_timeout_minutes @property def known_servers(self) -> list[ServerDescription]: """List of Servers of types besides Unknown.""" return [s for s in self._server_descriptions.values() if s.is_server_type_known] @property def has_known_servers(self) -> bool: """Whether there are any Servers of types besides Unknown.""" return any(s for s in self._server_descriptions.values() if s.is_server_type_known) @property def readable_servers(self) -> list[ServerDescription]: """List of readable Servers.""" return [s for s in self._server_descriptions.values() if s.is_readable] @property def common_wire_version(self) -> Optional[int]: """Minimum of all servers' max wire versions, or None.""" servers = self.known_servers if servers: return min(s.max_wire_version for s in self.known_servers) return None @property def heartbeat_frequency(self) -> int: return self._topology_settings.heartbeat_frequency @property def srv_max_hosts(self) -> int: return self._topology_settings._srv_max_hosts def _apply_local_threshold(self, selection: Optional[Selection]) -> list[ServerDescription]: if not selection: return [] round_trip_times: list[float] = [] for server in selection.server_descriptions: if server.round_trip_time is None: config_err_msg = f"round_trip_time for server {server.address} is unexpectedly None: {self}, servers: {selection.server_descriptions}" raise ConfigurationError(config_err_msg) round_trip_times.append(server.round_trip_time) # Round trip time in seconds. fastest = min(round_trip_times) threshold = self._topology_settings.local_threshold_ms / 1000.0 return [ s for s in selection.server_descriptions if (cast(float, s.round_trip_time) - fastest) <= threshold ] def apply_selector( self, selector: Any, address: Optional[_Address] = None, custom_selector: Optional[_ServerSelector] = None, ) -> list[ServerDescription]: """List of servers matching the provided selector(s). :param selector: a callable that takes a Selection as input and returns a Selection as output. For example, an instance of a read preference from :mod:`~pymongo.read_preferences`. :param address: A server address to select. :param custom_selector: A callable that augments server selection rules. Accepts a list of :class:`~pymongo.server_description.ServerDescription` objects and return a list of server descriptions that should be considered suitable for the desired operation. .. versionadded:: 3.4 """ if getattr(selector, "min_wire_version", 0): common_wv = self.common_wire_version if common_wv and common_wv < selector.min_wire_version: raise ConfigurationError( "%s requires min wire version %d, but topology's min" " wire version is %d" % (selector, selector.min_wire_version, common_wv) ) if isinstance(selector, _AggWritePref): selector.selection_hook(self) if self.topology_type == TOPOLOGY_TYPE.Unknown: return [] elif self.topology_type in (TOPOLOGY_TYPE.Single, TOPOLOGY_TYPE.LoadBalanced): # Ignore selectors for standalone and load balancer mode. return self.known_servers if address: # Ignore selectors when explicit address is requested. description = self.server_descriptions().get(address) return [description] if description else [] selection = Selection.from_topology_description(self) # Ignore read preference for sharded clusters. if self.topology_type != TOPOLOGY_TYPE.Sharded: selection = selector(selection) # Apply custom selector followed by localThresholdMS. if custom_selector is not None and selection: selection = selection.with_server_descriptions( custom_selector(selection.server_descriptions) ) return self._apply_local_threshold(selection) def has_readable_server(self, read_preference: _ServerMode = ReadPreference.PRIMARY) -> bool: """Does this topology have any readable servers available matching the given read preference? :param read_preference: an instance of a read preference from :mod:`~pymongo.read_preferences`. Defaults to :attr:`~pymongo.read_preferences.ReadPreference.PRIMARY`. .. note:: When connected directly to a single server this method always returns ``True``. .. versionadded:: 3.4 """ common.validate_read_preference("read_preference", read_preference) return any(self.apply_selector(read_preference)) def has_writable_server(self) -> bool: """Does this topology have a writable server available? .. note:: When connected directly to a single server this method always returns ``True``. .. versionadded:: 3.4 """ return self.has_readable_server(ReadPreference.PRIMARY) def __repr__(self) -> str: # Sort the servers by address. servers = sorted(self._server_descriptions.values(), key=lambda sd: sd.address) return "<{} id: {}, topology_type: {}, servers: {!r}>".format( self.__class__.__name__, self._topology_settings._topology_id, self.topology_type_name, servers, ) # If topology type is Unknown and we receive a hello response, what should # the new topology type be? _SERVER_TYPE_TO_TOPOLOGY_TYPE = { SERVER_TYPE.Mongos: TOPOLOGY_TYPE.Sharded, SERVER_TYPE.RSPrimary: TOPOLOGY_TYPE.ReplicaSetWithPrimary, SERVER_TYPE.RSSecondary: TOPOLOGY_TYPE.ReplicaSetNoPrimary, SERVER_TYPE.RSArbiter: TOPOLOGY_TYPE.ReplicaSetNoPrimary, SERVER_TYPE.RSOther: TOPOLOGY_TYPE.ReplicaSetNoPrimary, # Note: SERVER_TYPE.LoadBalancer and Unknown are intentionally left out. } def updated_topology_description( topology_description: TopologyDescription, server_description: ServerDescription ) -> TopologyDescription: """Return an updated copy of a TopologyDescription. :param topology_description: the current TopologyDescription :param server_description: a new ServerDescription that resulted from a hello call Called after attempting (successfully or not) to call hello on the server at server_description.address. Does not modify topology_description. """ address = server_description.address # These values will be updated, if necessary, to form the new # TopologyDescription. topology_type = topology_description.topology_type set_name = topology_description.replica_set_name max_set_version = topology_description.max_set_version max_election_id = topology_description.max_election_id server_type = server_description.server_type # Don't mutate the original dict of server descriptions; copy it. sds = topology_description.server_descriptions() # Replace this server's description with the new one. sds[address] = server_description if topology_type == TOPOLOGY_TYPE.Single: # Set server type to Unknown if replica set name does not match. if set_name is not None and set_name != server_description.replica_set_name: error = ConfigurationError( "client is configured to connect to a replica set named " "'{}' but this node belongs to a set named '{}'".format( set_name, server_description.replica_set_name ) ) sds[address] = server_description.to_unknown(error=error) # Single type never changes. return TopologyDescription( TOPOLOGY_TYPE.Single, sds, set_name, max_set_version, max_election_id, topology_description._topology_settings, ) if topology_type == TOPOLOGY_TYPE.Unknown: if server_type in (SERVER_TYPE.Standalone, SERVER_TYPE.LoadBalancer): if len(topology_description._topology_settings.seeds) == 1: topology_type = TOPOLOGY_TYPE.Single else: # Remove standalone from Topology when given multiple seeds. sds.pop(address) elif server_type not in (SERVER_TYPE.Unknown, SERVER_TYPE.RSGhost): topology_type = _SERVER_TYPE_TO_TOPOLOGY_TYPE[server_type] if topology_type == TOPOLOGY_TYPE.Sharded: if server_type not in (SERVER_TYPE.Mongos, SERVER_TYPE.Unknown): sds.pop(address) elif topology_type == TOPOLOGY_TYPE.ReplicaSetNoPrimary: if server_type in (SERVER_TYPE.Standalone, SERVER_TYPE.Mongos): sds.pop(address) elif server_type == SERVER_TYPE.RSPrimary: (topology_type, set_name, max_set_version, max_election_id) = _update_rs_from_primary( sds, set_name, server_description, max_set_version, max_election_id ) elif server_type in (SERVER_TYPE.RSSecondary, SERVER_TYPE.RSArbiter, SERVER_TYPE.RSOther): topology_type, set_name = _update_rs_no_primary_from_member( sds, set_name, server_description ) elif topology_type == TOPOLOGY_TYPE.ReplicaSetWithPrimary: if server_type in (SERVER_TYPE.Standalone, SERVER_TYPE.Mongos): sds.pop(address) topology_type = _check_has_primary(sds) elif server_type == SERVER_TYPE.RSPrimary: (topology_type, set_name, max_set_version, max_election_id) = _update_rs_from_primary( sds, set_name, server_description, max_set_version, max_election_id ) elif server_type in (SERVER_TYPE.RSSecondary, SERVER_TYPE.RSArbiter, SERVER_TYPE.RSOther): topology_type = _update_rs_with_primary_from_member(sds, set_name, server_description) else: # Server type is Unknown or RSGhost: did we just lose the primary? topology_type = _check_has_primary(sds) # Return updated copy. return TopologyDescription( topology_type, sds, set_name, max_set_version, max_election_id, topology_description._topology_settings, ) def _updated_topology_description_srv_polling( topology_description: TopologyDescription, seedlist: list[tuple[str, Any]] ) -> TopologyDescription: """Return an updated copy of a TopologyDescription. :param topology_description: the current TopologyDescription :param seedlist: a list of new seeds new ServerDescription that resulted from a hello call """ assert topology_description.topology_type in SRV_POLLING_TOPOLOGIES # Create a copy of the server descriptions. sds = topology_description.server_descriptions() # If seeds haven't changed, don't do anything. if set(sds.keys()) == set(seedlist): return topology_description # Remove SDs corresponding to servers no longer part of the SRV record. for address in list(sds.keys()): if address not in seedlist: sds.pop(address) if topology_description.srv_max_hosts != 0: new_hosts = set(seedlist) - set(sds.keys()) n_to_add = topology_description.srv_max_hosts - len(sds) if n_to_add > 0: seedlist = sample(sorted(new_hosts), min(n_to_add, len(new_hosts))) else: seedlist = [] # Add SDs corresponding to servers recently added to the SRV record. for address in seedlist: if address not in sds: sds[address] = ServerDescription(address) return TopologyDescription( topology_description.topology_type, sds, topology_description.replica_set_name, topology_description.max_set_version, topology_description.max_election_id, topology_description._topology_settings, ) def _update_rs_from_primary( sds: MutableMapping[_Address, ServerDescription], replica_set_name: Optional[str], server_description: ServerDescription, max_set_version: Optional[int], max_election_id: Optional[ObjectId], ) -> tuple[int, Optional[str], Optional[int], Optional[ObjectId]]: """Update topology description from a primary's hello response. Pass in a dict of ServerDescriptions, current replica set name, the ServerDescription we are processing, and the TopologyDescription's max_set_version and max_election_id if any. Returns (new topology type, new replica_set_name, new max_set_version, new max_election_id). """ if replica_set_name is None: replica_set_name = server_description.replica_set_name elif replica_set_name != server_description.replica_set_name: # We found a primary but it doesn't have the replica_set_name # provided by the user. sds.pop(server_description.address) return _check_has_primary(sds), replica_set_name, max_set_version, max_election_id if server_description.max_wire_version is None or server_description.max_wire_version < 17: new_election_tuple: tuple = (server_description.set_version, server_description.election_id) max_election_tuple: tuple = (max_set_version, max_election_id) if None not in new_election_tuple: if None not in max_election_tuple and new_election_tuple < max_election_tuple: # Stale primary, set to type Unknown. sds[server_description.address] = server_description.to_unknown() return _check_has_primary(sds), replica_set_name, max_set_version, max_election_id max_election_id = server_description.election_id if server_description.set_version is not None and ( max_set_version is None or server_description.set_version > max_set_version ): max_set_version = server_description.set_version else: new_election_tuple = server_description.election_id, server_description.set_version max_election_tuple = max_election_id, max_set_version new_election_safe = tuple(MinKey() if i is None else i for i in new_election_tuple) max_election_safe = tuple(MinKey() if i is None else i for i in max_election_tuple) if new_election_safe < max_election_safe: # Stale primary, set to type Unknown. sds[server_description.address] = server_description.to_unknown() return _check_has_primary(sds), replica_set_name, max_set_version, max_election_id else: max_election_id = server_description.election_id max_set_version = server_description.set_version # We've heard from the primary. Is it the same primary as before? for server in sds.values(): if ( server.server_type is SERVER_TYPE.RSPrimary and server.address != server_description.address ): # Reset old primary's type to Unknown. sds[server.address] = server.to_unknown() # There can be only one prior primary. break # Discover new hosts from this primary's response. for new_address in server_description.all_hosts: if new_address not in sds: sds[new_address] = ServerDescription(new_address) # Remove hosts not in the response. for addr in set(sds) - server_description.all_hosts: sds.pop(addr) # If the host list differs from the seed list, we may not have a primary # after all. return (_check_has_primary(sds), replica_set_name, max_set_version, max_election_id) def _update_rs_with_primary_from_member( sds: MutableMapping[_Address, ServerDescription], replica_set_name: Optional[str], server_description: ServerDescription, ) -> int: """RS with known primary. Process a response from a non-primary. Pass in a dict of ServerDescriptions, current replica set name, and the ServerDescription we are processing. Returns new topology type. """ assert replica_set_name is not None if replica_set_name != server_description.replica_set_name: sds.pop(server_description.address) elif server_description.me and server_description.address != server_description.me: sds.pop(server_description.address) # Had this member been the primary? return _check_has_primary(sds) def _update_rs_no_primary_from_member( sds: MutableMapping[_Address, ServerDescription], replica_set_name: Optional[str], server_description: ServerDescription, ) -> tuple[int, Optional[str]]: """RS without known primary. Update from a non-primary's response. Pass in a dict of ServerDescriptions, current replica set name, and the ServerDescription we are processing. Returns (new topology type, new replica_set_name). """ topology_type = TOPOLOGY_TYPE.ReplicaSetNoPrimary if replica_set_name is None: replica_set_name = server_description.replica_set_name elif replica_set_name != server_description.replica_set_name: sds.pop(server_description.address) return topology_type, replica_set_name # This isn't the primary's response, so don't remove any servers # it doesn't report. Only add new servers. for address in server_description.all_hosts: if address not in sds: sds[address] = ServerDescription(address) if server_description.me and server_description.address != server_description.me: sds.pop(server_description.address) return topology_type, replica_set_name def _check_has_primary(sds: Mapping[_Address, ServerDescription]) -> int: """Current topology type is ReplicaSetWithPrimary. Is primary still known? Pass in a dict of ServerDescriptions. Returns new topology type. """ for s in sds.values(): if s.server_type == SERVER_TYPE.RSPrimary: return TOPOLOGY_TYPE.ReplicaSetWithPrimary else: # noqa: PLW0120 return TOPOLOGY_TYPE.ReplicaSetNoPrimary mongodb-mongo-python-driver-509e9b7/pymongo/typings.py000066400000000000000000000027601462766011000232010ustar00rootroot00000000000000# Copyright 2022-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. """Type aliases used by PyMongo""" from __future__ import annotations from typing import ( TYPE_CHECKING, Any, Mapping, Optional, Sequence, Tuple, TypeVar, Union, ) from bson.typings import _DocumentOut, _DocumentType, _DocumentTypeArg if TYPE_CHECKING: from pymongo.collation import Collation # Common Shared Types. _Address = Tuple[str, Optional[int]] _CollationIn = Union[Mapping[str, Any], "Collation"] _Pipeline = Sequence[Mapping[str, Any]] ClusterTime = Mapping[str, Any] _T = TypeVar("_T") def strip_optional(elem: Optional[_T]) -> _T: """This function is to allow us to cast all of the elements of an iterator from Optional[_T] to _T while inside a list comprehension. """ assert elem is not None return elem __all__ = [ "_DocumentOut", "_DocumentType", "_DocumentTypeArg", "_Address", "_CollationIn", "_Pipeline", "strip_optional", ] mongodb-mongo-python-driver-509e9b7/pymongo/uri_parser.py000066400000000000000000000561721462766011000236650ustar00rootroot00000000000000# Copyright 2011-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. """Tools to parse and validate a MongoDB URI.""" from __future__ import annotations import re import sys import warnings from typing import ( TYPE_CHECKING, Any, Mapping, MutableMapping, Optional, Sized, Union, cast, ) from urllib.parse import unquote_plus from pymongo.client_options import _parse_ssl_options from pymongo.common import ( INTERNAL_URI_OPTION_NAME_MAP, SRV_SERVICE_NAME, URI_OPTIONS_DEPRECATION_MAP, _CaseInsensitiveDictionary, get_validated_options, ) from pymongo.errors import ConfigurationError, InvalidURI from pymongo.srv_resolver import _have_dnspython, _SrvResolver from pymongo.typings import _Address if TYPE_CHECKING: from pymongo.pyopenssl_context import SSLContext SCHEME = "mongodb://" SCHEME_LEN = len(SCHEME) SRV_SCHEME = "mongodb+srv://" SRV_SCHEME_LEN = len(SRV_SCHEME) DEFAULT_PORT = 27017 def _unquoted_percent(s: str) -> bool: """Check for unescaped percent signs. :param s: A string. `s` can have things like '%25', '%2525', and '%E2%85%A8' but cannot have unquoted percent like '%foo'. """ for i in range(len(s)): if s[i] == "%": sub = s[i : i + 3] # If unquoting yields the same string this means there was an # unquoted %. if unquote_plus(sub) == sub: return True return False def parse_userinfo(userinfo: str) -> tuple[str, str]: """Validates the format of user information in a MongoDB URI. Reserved characters that are gen-delimiters (":", "/", "?", "#", "[", "]", "@") as per RFC 3986 must be escaped. Returns a 2-tuple containing the unescaped username followed by the unescaped password. :param userinfo: A string of the form : """ if "@" in userinfo or userinfo.count(":") > 1 or _unquoted_percent(userinfo): raise InvalidURI( "Username and password must be escaped according to " "RFC 3986, use urllib.parse.quote_plus" ) user, _, passwd = userinfo.partition(":") # No password is expected with GSSAPI authentication. if not user: raise InvalidURI("The empty string is not valid username.") return unquote_plus(user), unquote_plus(passwd) def parse_ipv6_literal_host( entity: str, default_port: Optional[int] ) -> tuple[str, Optional[Union[str, int]]]: """Validates an IPv6 literal host:port string. Returns a 2-tuple of IPv6 literal followed by port where port is default_port if it wasn't specified in entity. :param entity: A string that represents an IPv6 literal enclosed in braces (e.g. '[::1]' or '[::1]:27017'). :param default_port: The port number to use when one wasn't specified in entity. """ if entity.find("]") == -1: raise ValueError( "an IPv6 address literal must be enclosed in '[' and ']' according to RFC 2732." ) i = entity.find("]:") if i == -1: return entity[1:-1], default_port return entity[1:i], entity[i + 2 :] def parse_host(entity: str, default_port: Optional[int] = DEFAULT_PORT) -> _Address: """Validates a host string Returns a 2-tuple of host followed by port where port is default_port if it wasn't specified in the string. :param entity: A host or host:port string where host could be a hostname or IP address. :param default_port: The port number to use when one wasn't specified in entity. """ host = entity port: Optional[Union[str, int]] = default_port if entity[0] == "[": host, port = parse_ipv6_literal_host(entity, default_port) elif entity.endswith(".sock"): return entity, default_port elif entity.find(":") != -1: if entity.count(":") > 1: raise ValueError( "Reserved characters such as ':' must be " "escaped according RFC 2396. An IPv6 " "address literal must be enclosed in '[' " "and ']' according to RFC 2732." ) host, port = host.split(":", 1) if isinstance(port, str): if not port.isdigit() or int(port) > 65535 or int(port) <= 0: raise ValueError(f"Port must be an integer between 0 and 65535: {port!r}") port = int(port) # Normalize hostname to lowercase, since DNS is case-insensitive: # http://tools.ietf.org/html/rfc4343 # This prevents useless rediscovery if "foo.com" is in the seed list but # "FOO.com" is in the hello response. return host.lower(), port # Options whose values are implicitly determined by tlsInsecure. _IMPLICIT_TLSINSECURE_OPTS = { "tlsallowinvalidcertificates", "tlsallowinvalidhostnames", "tlsdisableocspendpointcheck", } def _parse_options(opts: str, delim: Optional[str]) -> _CaseInsensitiveDictionary: """Helper method for split_options which creates the options dict. Also handles the creation of a list for the URI tag_sets/ readpreferencetags portion, and the use of a unicode options string. """ options = _CaseInsensitiveDictionary() for uriopt in opts.split(delim): key, value = uriopt.split("=") if key.lower() == "readpreferencetags": options.setdefault(key, []).append(value) else: if key in options: warnings.warn(f"Duplicate URI option '{key}'.", stacklevel=2) if key.lower() == "authmechanismproperties": val = value else: val = unquote_plus(value) options[key] = val return options def _handle_security_options(options: _CaseInsensitiveDictionary) -> _CaseInsensitiveDictionary: """Raise appropriate errors when conflicting TLS options are present in the options dictionary. :param options: Instance of _CaseInsensitiveDictionary containing MongoDB URI options. """ # Implicitly defined options must not be explicitly specified. tlsinsecure = options.get("tlsinsecure") if tlsinsecure is not None: for opt in _IMPLICIT_TLSINSECURE_OPTS: if opt in options: err_msg = "URI options %s and %s cannot be specified simultaneously." raise InvalidURI( err_msg % (options.cased_key("tlsinsecure"), options.cased_key(opt)) ) # Handle co-occurence of OCSP & tlsAllowInvalidCertificates options. tlsallowinvalidcerts = options.get("tlsallowinvalidcertificates") if tlsallowinvalidcerts is not None: if "tlsdisableocspendpointcheck" in options: err_msg = "URI options %s and %s cannot be specified simultaneously." raise InvalidURI( err_msg % ("tlsallowinvalidcertificates", options.cased_key("tlsdisableocspendpointcheck")) ) if tlsallowinvalidcerts is True: options["tlsdisableocspendpointcheck"] = True # Handle co-occurence of CRL and OCSP-related options. tlscrlfile = options.get("tlscrlfile") if tlscrlfile is not None: for opt in ("tlsinsecure", "tlsallowinvalidcertificates", "tlsdisableocspendpointcheck"): if options.get(opt) is True: err_msg = "URI option %s=True cannot be specified when CRL checking is enabled." raise InvalidURI(err_msg % (opt,)) if "ssl" in options and "tls" in options: def truth_value(val: Any) -> Any: if val in ("true", "false"): return val == "true" if isinstance(val, bool): return val return val if truth_value(options.get("ssl")) != truth_value(options.get("tls")): err_msg = "Can not specify conflicting values for URI options %s and %s." raise InvalidURI(err_msg % (options.cased_key("ssl"), options.cased_key("tls"))) return options def _handle_option_deprecations(options: _CaseInsensitiveDictionary) -> _CaseInsensitiveDictionary: """Issue appropriate warnings when deprecated options are present in the options dictionary. Removes deprecated option key, value pairs if the options dictionary is found to also have the renamed option. :param options: Instance of _CaseInsensitiveDictionary containing MongoDB URI options. """ for optname in list(options): if optname in URI_OPTIONS_DEPRECATION_MAP: mode, message = URI_OPTIONS_DEPRECATION_MAP[optname] if mode == "renamed": newoptname = message if newoptname in options: warn_msg = "Deprecated option '%s' ignored in favor of '%s'." warnings.warn( warn_msg % (options.cased_key(optname), options.cased_key(newoptname)), DeprecationWarning, stacklevel=2, ) options.pop(optname) continue warn_msg = "Option '%s' is deprecated, use '%s' instead." warnings.warn( warn_msg % (options.cased_key(optname), newoptname), DeprecationWarning, stacklevel=2, ) elif mode == "removed": warn_msg = "Option '%s' is deprecated. %s." warnings.warn( warn_msg % (options.cased_key(optname), message), DeprecationWarning, stacklevel=2, ) return options def _normalize_options(options: _CaseInsensitiveDictionary) -> _CaseInsensitiveDictionary: """Normalizes option names in the options dictionary by converting them to their internally-used names. :param options: Instance of _CaseInsensitiveDictionary containing MongoDB URI options. """ # Expand the tlsInsecure option. tlsinsecure = options.get("tlsinsecure") if tlsinsecure is not None: for opt in _IMPLICIT_TLSINSECURE_OPTS: # Implicit options are logically the same as tlsInsecure. options[opt] = tlsinsecure for optname in list(options): intname = INTERNAL_URI_OPTION_NAME_MAP.get(optname, None) if intname is not None: options[intname] = options.pop(optname) return options def validate_options(opts: Mapping[str, Any], warn: bool = False) -> MutableMapping[str, Any]: """Validates and normalizes options passed in a MongoDB URI. Returns a new dictionary of validated and normalized options. If warn is False then errors will be thrown for invalid options, otherwise they will be ignored and a warning will be issued. :param opts: A dict of MongoDB URI options. :param warn: If ``True`` then warnings will be logged and invalid options will be ignored. Otherwise invalid options will cause errors. """ return get_validated_options(opts, warn) def split_options( opts: str, validate: bool = True, warn: bool = False, normalize: bool = True ) -> MutableMapping[str, Any]: """Takes the options portion of a MongoDB URI, validates each option and returns the options in a dictionary. :param opt: A string representing MongoDB URI options. :param validate: If ``True`` (the default), validate and normalize all options. :param warn: If ``False`` (the default), suppress all warnings raised during validation of options. :param normalize: If ``True`` (the default), renames all options to their internally-used names. """ and_idx = opts.find("&") semi_idx = opts.find(";") try: if and_idx >= 0 and semi_idx >= 0: raise InvalidURI("Can not mix '&' and ';' for option separators.") elif and_idx >= 0: options = _parse_options(opts, "&") elif semi_idx >= 0: options = _parse_options(opts, ";") elif opts.find("=") != -1: options = _parse_options(opts, None) else: raise ValueError except ValueError: raise InvalidURI("MongoDB URI options are key=value pairs.") from None options = _handle_security_options(options) options = _handle_option_deprecations(options) if normalize: options = _normalize_options(options) if validate: options = cast(_CaseInsensitiveDictionary, validate_options(options, warn)) if options.get("authsource") == "": raise InvalidURI("the authSource database cannot be an empty string") return options def split_hosts(hosts: str, default_port: Optional[int] = DEFAULT_PORT) -> list[_Address]: """Takes a string of the form host1[:port],host2[:port]... and splits it into (host, port) tuples. If [:port] isn't present the default_port is used. Returns a set of 2-tuples containing the host name (or IP) followed by port number. :param hosts: A string of the form host1[:port],host2[:port],... :param default_port: The port number to use when one wasn't specified for a host. """ nodes = [] for entity in hosts.split(","): if not entity: raise ConfigurationError("Empty host (or extra comma in host list).") port = default_port # Unix socket entities don't have ports if entity.endswith(".sock"): port = None nodes.append(parse_host(entity, port)) return nodes # Prohibited characters in database name. DB names also can't have ".", but for # backward-compat we allow "db.collection" in URI. _BAD_DB_CHARS = re.compile("[" + re.escape(r'/ "$') + "]") _ALLOWED_TXT_OPTS = frozenset( ["authsource", "authSource", "replicaset", "replicaSet", "loadbalanced", "loadBalanced"] ) def _check_options(nodes: Sized, options: Mapping[str, Any]) -> None: # Ensure directConnection was not True if there are multiple seeds. if len(nodes) > 1 and options.get("directconnection"): raise ConfigurationError("Cannot specify multiple hosts with directConnection=true") if options.get("loadbalanced"): if len(nodes) > 1: raise ConfigurationError("Cannot specify multiple hosts with loadBalanced=true") if options.get("directconnection"): raise ConfigurationError("Cannot specify directConnection=true with loadBalanced=true") if options.get("replicaset"): raise ConfigurationError("Cannot specify replicaSet with loadBalanced=true") def parse_uri( uri: str, default_port: Optional[int] = DEFAULT_PORT, validate: bool = True, warn: bool = False, normalize: bool = True, connect_timeout: Optional[float] = None, srv_service_name: Optional[str] = None, srv_max_hosts: Optional[int] = None, ) -> dict[str, Any]: """Parse and validate a MongoDB URI. Returns a dict of the form:: { 'nodelist': , 'username': or None, 'password': or None, 'database': or None, 'collection': or None, 'options': , 'fqdn': or None } If the URI scheme is "mongodb+srv://" DNS SRV and TXT lookups will be done to build nodelist and options. :param uri: The MongoDB URI to parse. :param default_port: The port number to use when one wasn't specified for a host in the URI. :param validate: If ``True`` (the default), validate and normalize all options. Default: ``True``. :param warn: When validating, if ``True`` then will warn the user then ignore any invalid options or values. If ``False``, validation will error when options are unsupported or values are invalid. Default: ``False``. :param normalize: If ``True``, convert names of URI options to their internally-used names. Default: ``True``. :param connect_timeout: The maximum time in milliseconds to wait for a response from the DNS server. :param srv_service_name: A custom SRV service name .. versionchanged:: 4.6 The delimiting slash (``/``) between hosts and connection options is now optional. For example, "mongodb://example.com?tls=true" is now a valid URI. .. versionchanged:: 4.0 To better follow RFC 3986, unquoted percent signs ("%") are no longer supported. .. versionchanged:: 3.9 Added the ``normalize`` parameter. .. versionchanged:: 3.6 Added support for mongodb+srv:// URIs. .. versionchanged:: 3.5 Return the original value of the ``readPreference`` MongoDB URI option instead of the validated read preference mode. .. versionchanged:: 3.1 ``warn`` added so invalid options can be ignored. """ if uri.startswith(SCHEME): is_srv = False scheme_free = uri[SCHEME_LEN:] elif uri.startswith(SRV_SCHEME): if not _have_dnspython(): python_path = sys.executable or "python" raise ConfigurationError( 'The "dnspython" module must be ' "installed to use mongodb+srv:// URIs. " "To fix this error install pymongo again:\n " "%s -m pip install pymongo>=4.3" % (python_path) ) is_srv = True scheme_free = uri[SRV_SCHEME_LEN:] else: raise InvalidURI(f"Invalid URI scheme: URI must begin with '{SCHEME}' or '{SRV_SCHEME}'") if not scheme_free: raise InvalidURI("Must provide at least one hostname or IP.") user = None passwd = None dbase = None collection = None options = _CaseInsensitiveDictionary() host_part, _, path_part = scheme_free.partition("/") if not host_part: host_part = path_part path_part = "" if path_part: dbase, _, opts = path_part.partition("?") else: # There was no slash in scheme_free, check for a sole "?". host_part, _, opts = host_part.partition("?") if dbase: dbase = unquote_plus(dbase) if "." in dbase: dbase, collection = dbase.split(".", 1) if _BAD_DB_CHARS.search(dbase): raise InvalidURI('Bad database name "%s"' % dbase) else: dbase = None if opts: options.update(split_options(opts, validate, warn, normalize)) if srv_service_name is None: srv_service_name = options.get("srvServiceName", SRV_SERVICE_NAME) if "@" in host_part: userinfo, _, hosts = host_part.rpartition("@") user, passwd = parse_userinfo(userinfo) else: hosts = host_part if "/" in hosts: raise InvalidURI("Any '/' in a unix domain socket must be percent-encoded: %s" % host_part) hosts = unquote_plus(hosts) fqdn = None srv_max_hosts = srv_max_hosts or options.get("srvMaxHosts") if is_srv: if options.get("directConnection"): raise ConfigurationError(f"Cannot specify directConnection=true with {SRV_SCHEME} URIs") nodes = split_hosts(hosts, default_port=None) if len(nodes) != 1: raise InvalidURI(f"{SRV_SCHEME} URIs must include one, and only one, hostname") fqdn, port = nodes[0] if port is not None: raise InvalidURI(f"{SRV_SCHEME} URIs must not include a port number") # Use the connection timeout. connectTimeoutMS passed as a keyword # argument overrides the same option passed in the connection string. connect_timeout = connect_timeout or options.get("connectTimeoutMS") dns_resolver = _SrvResolver(fqdn, connect_timeout, srv_service_name, srv_max_hosts) nodes = dns_resolver.get_hosts() dns_options = dns_resolver.get_options() if dns_options: parsed_dns_options = split_options(dns_options, validate, warn, normalize) if set(parsed_dns_options) - _ALLOWED_TXT_OPTS: raise ConfigurationError( "Only authSource, replicaSet, and loadBalanced are supported from DNS" ) for opt, val in parsed_dns_options.items(): if opt not in options: options[opt] = val if options.get("loadBalanced") and srv_max_hosts: raise InvalidURI("You cannot specify loadBalanced with srvMaxHosts") if options.get("replicaSet") and srv_max_hosts: raise InvalidURI("You cannot specify replicaSet with srvMaxHosts") if "tls" not in options and "ssl" not in options: options["tls"] = True if validate else "true" elif not is_srv and options.get("srvServiceName") is not None: raise ConfigurationError( "The srvServiceName option is only allowed with 'mongodb+srv://' URIs" ) elif not is_srv and srv_max_hosts: raise ConfigurationError( "The srvMaxHosts option is only allowed with 'mongodb+srv://' URIs" ) else: nodes = split_hosts(hosts, default_port=default_port) _check_options(nodes, options) return { "nodelist": nodes, "username": user, "password": passwd, "database": dbase, "collection": collection, "options": options, "fqdn": fqdn, } def _parse_kms_tls_options(kms_tls_options: Optional[Mapping[str, Any]]) -> dict[str, SSLContext]: """Parse KMS TLS connection options.""" if not kms_tls_options: return {} if not isinstance(kms_tls_options, dict): raise TypeError("kms_tls_options must be a dict") contexts = {} for provider, options in kms_tls_options.items(): if not isinstance(options, dict): raise TypeError(f'kms_tls_options["{provider}"] must be a dict') options.setdefault("tls", True) opts = _CaseInsensitiveDictionary(options) opts = _handle_security_options(opts) opts = _normalize_options(opts) opts = cast(_CaseInsensitiveDictionary, validate_options(opts)) ssl_context, allow_invalid_hostnames = _parse_ssl_options(opts) if ssl_context is None: raise ConfigurationError("TLS is required for KMS providers") if allow_invalid_hostnames: raise ConfigurationError("Insecure TLS options prohibited") for n in [ "tlsInsecure", "tlsAllowInvalidCertificates", "tlsAllowInvalidHostnames", "tlsDisableCertificateRevocationCheck", ]: if n in opts: raise ConfigurationError(f"Insecure TLS options prohibited: {n}") contexts[provider] = ssl_context return contexts if __name__ == "__main__": import pprint try: pprint.pprint(parse_uri(sys.argv[1])) # noqa: T203 except InvalidURI as exc: print(exc) # noqa: T201 sys.exit(0) mongodb-mongo-python-driver-509e9b7/pymongo/write_concern.py000066400000000000000000000122641462766011000243450ustar00rootroot00000000000000# Copyright 2014-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. """Tools for working with write concerns.""" from __future__ import annotations from typing import Any, Optional, Union from pymongo.errors import ConfigurationError # Duplicated here to avoid a circular import. def validate_boolean(option: str, value: Any) -> bool: """Validates that 'value' is True or False.""" if isinstance(value, bool): return value raise TypeError(f"{option} must be True or False, was: {option}={value}") class WriteConcern: """WriteConcern :param w: (integer or string) Used with replication, write operations will block until they have been replicated to the specified number or tagged set of servers. `w=` always includes the replica set primary (e.g. w=3 means write to the primary and wait until replicated to **two** secondaries). **w=0 disables acknowledgement of write operations and can not be used with other write concern options.** :param wtimeout: (integer) **DEPRECATED** Used in conjunction with `w`. Specify a value in milliseconds to control how long to wait for write propagation to complete. If replication does not complete in the given timeframe, a timeout exception is raised. :param j: If ``True`` block until write operations have been committed to the journal. Cannot be used in combination with `fsync`. Write operations will fail with an exception if this option is used when the server is running without journaling. :param fsync: If ``True`` and the server is running without journaling, blocks until the server has synced all data files to disk. If the server is running with journaling, this acts the same as the `j` option, blocking until write operations have been committed to the journal. Cannot be used in combination with `j`. .. versionchanged:: 4.7 Deprecated parameter ``wtimeout``, use :meth:`~pymongo.timeout`. """ __slots__ = ("__document", "__acknowledged", "__server_default") def __init__( self, w: Optional[Union[int, str]] = None, wtimeout: Optional[int] = None, j: Optional[bool] = None, fsync: Optional[bool] = None, ) -> None: self.__document: dict[str, Any] = {} self.__acknowledged = True if wtimeout is not None: if not isinstance(wtimeout, int): raise TypeError("wtimeout must be an integer") if wtimeout < 0: raise ValueError("wtimeout cannot be less than 0") self.__document["wtimeout"] = wtimeout if j is not None: validate_boolean("j", j) self.__document["j"] = j if fsync is not None: validate_boolean("fsync", fsync) if j and fsync: raise ConfigurationError("Can't set both j and fsync at the same time") self.__document["fsync"] = fsync if w == 0 and j is True: raise ConfigurationError("Cannot set w to 0 and j to True") if w is not None: if isinstance(w, int): if w < 0: raise ValueError("w cannot be less than 0") self.__acknowledged = w > 0 elif not isinstance(w, str): raise TypeError("w must be an integer or string") self.__document["w"] = w self.__server_default = not self.__document @property def is_server_default(self) -> bool: """Does this WriteConcern match the server default.""" return self.__server_default @property def document(self) -> dict[str, Any]: """The document representation of this write concern. .. note:: :class:`WriteConcern` is immutable. Mutating the value of :attr:`document` does not mutate this :class:`WriteConcern`. """ return self.__document.copy() @property def acknowledged(self) -> bool: """If ``True`` write operations will wait for acknowledgement before returning. """ return self.__acknowledged def __repr__(self) -> str: return "WriteConcern({})".format( ", ".join("{}={}".format(*kvt) for kvt in self.__document.items()) ) def __eq__(self, other: Any) -> bool: if isinstance(other, WriteConcern): return self.__document == other.document return NotImplemented def __ne__(self, other: Any) -> bool: if isinstance(other, WriteConcern): return self.__document != other.document return NotImplemented DEFAULT_WRITE_CONCERN = WriteConcern() mongodb-mongo-python-driver-509e9b7/pyproject.toml000066400000000000000000000155131462766011000223560ustar00rootroot00000000000000[build-system] requires = ["setuptools>=63.0"] build-backend = "setuptools.build_meta" [project] name = "pymongo" dynamic = ["version", "dependencies", "optional-dependencies"] description = "Python driver for MongoDB " readme = "README.md" license = {file="LICENSE"} requires-python = ">=3.7" authors = [ { name = "The MongoDB Python Team" }, ] keywords = [ "bson", "gridfs", "mongo", "mongodb", "pymongo", ] classifiers = [ "Development Status :: 5 - Production/Stable", "Intended Audience :: Developers", "License :: OSI Approved :: Apache Software License", "Operating System :: MacOS :: MacOS X", "Operating System :: Microsoft :: Windows", "Operating System :: POSIX", "Programming Language :: Python :: Implementation :: CPython", "Programming Language :: Python :: Implementation :: PyPy", "Programming Language :: Python :: 3", "Programming Language :: Python :: 3 :: Only", "Programming Language :: Python :: 3.7", "Programming Language :: Python :: 3.8", "Programming Language :: Python :: 3.9", "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", "Programming Language :: Python :: 3.12", "Topic :: Database", "Typing :: Typed", ] [project.urls] Homepage = "https://www.mongodb.org" Documentation = "https://pymongo.readthedocs.io" Source = "https://github.com/mongodb/mongo-python-driver" Tracker = "https://jira.mongodb.org/projects/PYTHON/issues" [tool.setuptools.dynamic] version = {attr = "pymongo._version.__version__"} [tool.setuptools.packages.find] include = ["bson","gridfs", "pymongo"] [tool.setuptools.package-data] bson=["py.typed", "*.pyi"] pymongo=["py.typed", "*.pyi"] gridfs=["py.typed", "*.pyi"] [tool.pytest.ini_options] minversion = "7" addopts = ["-ra", "--strict-config", "--strict-markers", "--junitxml=xunit-results/TEST-results.xml"] testpaths = ["test"] log_cli_level = "INFO" norecursedirs = ["test/*"] faulthandler_timeout = 1500 xfail_strict = true filterwarnings = [ "error", # Internal warnings raised during tests. "module:use an explicit session with no_cursor_timeout=True:UserWarning", "module:serverselectiontimeoutms must be:UserWarning", "module:Unsupported compressor:UserWarning", "module:zlibcompressionlevel must be:UserWarning", "module:Wire protocol compression with:UserWarning", "module:GridIn property:DeprecationWarning", "module:GridOut property:DeprecationWarning", # TODO: Remove as part of PYTHON-3923. "module:unclosed =1.16.0,<3.0.0 mongodb-mongo-python-driver-509e9b7/requirements/000077500000000000000000000000001462766011000221605ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/requirements/aws.txt000066400000000000000000000000371462766011000235130ustar00rootroot00000000000000pymongo-auth-aws>=1.1.0,<2.0.0 mongodb-mongo-python-driver-509e9b7/requirements/docs.txt000066400000000000000000000001641462766011000236520ustar00rootroot00000000000000sphinx>=5.3,<8 sphinx_rtd_theme>=2,<3 readthedocs-sphinx-search~=0.3 sphinxcontrib-shellcheck>=1,<2 furo==2023.9.10 mongodb-mongo-python-driver-509e9b7/requirements/encryption.txt000066400000000000000000000001521462766011000251110ustar00rootroot00000000000000pymongo-auth-aws>=1.1.0,<2.0.0 pymongocrypt>=1.6.0,<2.0.0 certifi;os.name=='nt' or sys_platform=='darwin' mongodb-mongo-python-driver-509e9b7/requirements/gssapi.txt000066400000000000000000000000721462766011000242060ustar00rootroot00000000000000pykerberos;os.name!='nt' winkerberos>=0.5.0;os.name=='nt' mongodb-mongo-python-driver-509e9b7/requirements/ocsp.txt000066400000000000000000000010711462766011000236640ustar00rootroot00000000000000# PyOpenSSL 17.0.0 introduced support for OCSP. 17.1.0 introduced # a related feature we need. 17.2.0 fixes a bug # in set_default_verify_paths we should really avoid. # service_identity 18.1.0 introduced support for IP addr matching. # Fallback to certifi on Windows if we can't load CA certs from the system # store and just use certifi on macOS. # https://www.pyopenssl.org/en/stable/api/ssl.html#OpenSSL.SSL.Context.set_default_verify_paths certifi;os.name=='nt' or sys_platform=='darwin' pyopenssl>=17.2.0 requests<3.0.0 cryptography>=2.5 service_identity>=18.1.0 mongodb-mongo-python-driver-509e9b7/requirements/snappy.txt000066400000000000000000000000161462766011000242300ustar00rootroot00000000000000python-snappy mongodb-mongo-python-driver-509e9b7/requirements/test.txt000066400000000000000000000000121462766011000236710ustar00rootroot00000000000000pytest>=7 mongodb-mongo-python-driver-509e9b7/requirements/zstd.txt000066400000000000000000000000121462766011000236760ustar00rootroot00000000000000zstandard mongodb-mongo-python-driver-509e9b7/setup.py000066400000000000000000000120021462766011000211420ustar00rootroot00000000000000from __future__ import annotations import os import sys import warnings # Hack to silence atexit traceback in some Python versions try: import multiprocessing # noqa: F401 except ImportError: pass from setuptools import setup from setuptools.command.build_ext import build_ext from setuptools.extension import Extension class custom_build_ext(build_ext): """Allow C extension building to fail. The C extension speeds up BSON encoding, but is not essential. """ warning_message = """ ******************************************************************** WARNING: %s could not be compiled. No C extensions are essential for PyMongo to run, although they do result in significant speed improvements. %s Please see the installation docs for solutions to build issues: https://pymongo.readthedocs.io/en/stable/installation.html Here are some hints for popular operating systems: If you are seeing this message on Linux you probably need to install GCC and/or the Python development package for your version of Python. Debian and Ubuntu users should issue the following command: $ sudo apt-get install build-essential python-dev Users of Red Hat based distributions (RHEL, CentOS, Amazon Linux, Oracle Linux, Fedora, etc.) should issue the following command: $ sudo yum install gcc python-devel If you are seeing this message on Microsoft Windows please install PyMongo using pip. Modern versions of pip will install PyMongo from binary wheels available on pypi. If you must install from source read the documentation here: https://pymongo.readthedocs.io/en/stable/installation.html#installing-from-source-on-windows If you are seeing this message on macOS / OSX please install PyMongo using pip. Modern versions of pip will install PyMongo from binary wheels available on pypi. If wheels are not available for your version of macOS / OSX, or you must install from source read the documentation here: https://pymongo.readthedocs.io/en/stable/installation.html#osx ******************************************************************** """ def run(self): try: build_ext.run(self) except Exception: if os.environ.get("PYMONGO_C_EXT_MUST_BUILD"): raise e = sys.exc_info()[1] sys.stdout.write("%s\n" % str(e)) warnings.warn( self.warning_message % ( "Extension modules", "There was an issue with your platform configuration - see above.", ), stacklevel=2, ) def build_extension(self, ext): name = ext.name try: build_ext.build_extension(self, ext) except Exception: if os.environ.get("PYMONGO_C_EXT_MUST_BUILD"): raise e = sys.exc_info()[1] sys.stdout.write("%s\n" % str(e)) warnings.warn( self.warning_message % ( "The %s extension module" % (name,), # noqa: UP031 "The output above this warning shows how the compilation failed.", ), stacklevel=2, ) ext_modules = [ Extension( "bson._cbson", include_dirs=["bson"], sources=["bson/_cbsonmodule.c", "bson/time64.c", "bson/buffer.c"], ), Extension( "pymongo._cmessage", include_dirs=["bson"], sources=[ "pymongo/_cmessagemodule.c", "bson/_cbsonmodule.c", "bson/time64.c", "bson/buffer.c", ], ), ] if "--no_ext" in sys.argv or os.environ.get("NO_EXT"): try: sys.argv.remove("--no_ext") except ValueError: pass ext_modules = [] elif sys.platform.startswith("java") or sys.platform == "cli" or "PyPy" in sys.version: sys.stdout.write( """ *****************************************************\n The optional C extensions are currently not supported\n by this python implementation.\n *****************************************************\n """ ) ext_modules = [] def parse_reqs_file(fname): with open(fname) as fid: lines = [li.strip() for li in fid.readlines()] return [li for li in lines if li and not li.startswith("#")] dependencies = parse_reqs_file("requirements.txt") extras_require = dict( aws=parse_reqs_file("requirements/aws.txt"), encryption=parse_reqs_file("requirements/encryption.txt"), gssapi=parse_reqs_file("requirements/gssapi.txt"), ocsp=parse_reqs_file("requirements/ocsp.txt"), snappy=parse_reqs_file("requirements/snappy.txt"), # PYTHON-3423 Removed in 4.3 but kept here to avoid pip warnings. srv=[], tls=[], # PYTHON-2133 Removed in 4.0 but kept here to avoid pip warnings. zstd=parse_reqs_file("requirements/zstd.txt"), test=parse_reqs_file("requirements/test.txt"), ) setup( cmdclass={"build_ext": custom_build_ext}, install_requires=dependencies, extras_require=extras_require, ext_modules=ext_modules, ) # type:ignore mongodb-mongo-python-driver-509e9b7/test/000077500000000000000000000000001462766011000204145ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/__init__.py000066400000000000000000001324121462766011000225300ustar00rootroot00000000000000# Copyright 2010-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. """Test suite for pymongo, bson, and gridfs.""" from __future__ import annotations import base64 import gc import multiprocessing import os import signal import socket import subprocess import sys import threading import time import traceback import unittest import warnings try: import ipaddress HAVE_IPADDRESS = True except ImportError: HAVE_IPADDRESS = False from contextlib import contextmanager from functools import wraps from test.version import Version from typing import Any, Callable, Dict, Generator, no_type_check from unittest import SkipTest from urllib.parse import quote_plus import pymongo import pymongo.errors from bson.son import SON from pymongo import common, message from pymongo.common import partition_node from pymongo.database import Database from pymongo.hello import HelloCompat from pymongo.mongo_client import MongoClient from pymongo.server_api import ServerApi from pymongo.ssl_support import HAVE_SSL, _ssl # type:ignore[attr-defined] from pymongo.uri_parser import parse_uri if HAVE_SSL: import ssl # Enable debug output for uncollectable objects. PyPy does not have set_debug. if hasattr(gc, "set_debug"): gc.set_debug( gc.DEBUG_UNCOLLECTABLE | getattr(gc, "DEBUG_OBJECTS", 0) | getattr(gc, "DEBUG_INSTANCES", 0) ) # The host and port of a single mongod or mongos, or the seed host # for a replica set. host = os.environ.get("DB_IP", "localhost") port = int(os.environ.get("DB_PORT", 27017)) IS_SRV = "mongodb+srv" in host db_user = os.environ.get("DB_USER", "user") db_pwd = os.environ.get("DB_PASSWORD", "password") CERT_PATH = os.path.join(os.path.dirname(os.path.realpath(__file__)), "certificates") CLIENT_PEM = os.environ.get("CLIENT_PEM", os.path.join(CERT_PATH, "client.pem")) CA_PEM = os.environ.get("CA_PEM", os.path.join(CERT_PATH, "ca.pem")) TLS_OPTIONS: Dict = {"tls": True} if CLIENT_PEM: TLS_OPTIONS["tlsCertificateKeyFile"] = CLIENT_PEM if CA_PEM: TLS_OPTIONS["tlsCAFile"] = CA_PEM COMPRESSORS = os.environ.get("COMPRESSORS") MONGODB_API_VERSION = os.environ.get("MONGODB_API_VERSION") TEST_LOADBALANCER = bool(os.environ.get("TEST_LOADBALANCER")) TEST_SERVERLESS = bool(os.environ.get("TEST_SERVERLESS")) SINGLE_MONGOS_LB_URI = os.environ.get("SINGLE_MONGOS_LB_URI") MULTI_MONGOS_LB_URI = os.environ.get("MULTI_MONGOS_LB_URI") if TEST_LOADBALANCER: res = parse_uri(SINGLE_MONGOS_LB_URI or "") host, port = res["nodelist"][0] db_user = res["username"] or db_user db_pwd = res["password"] or db_pwd elif TEST_SERVERLESS: TEST_LOADBALANCER = True res = parse_uri(SINGLE_MONGOS_LB_URI or "") host, port = res["nodelist"][0] db_user = res["username"] or db_user db_pwd = res["password"] or db_pwd TLS_OPTIONS = {"tls": True} # Spec says serverless tests must be run with compression. COMPRESSORS = COMPRESSORS or "zlib" # Shared KMS data. LOCAL_MASTER_KEY = base64.b64decode( b"Mng0NCt4ZHVUYUJCa1kxNkVyNUR1QURhZ2h2UzR2d2RrZzh0cFBwM3R6NmdWMDFBMUN3YkQ" b"5aXRRMkhGRGdQV09wOGVNYUMxT2k3NjZKelhaQmRCZGJkTXVyZG9uSjFk" ) AWS_CREDS = { "accessKeyId": os.environ.get("FLE_AWS_KEY", ""), "secretAccessKey": os.environ.get("FLE_AWS_SECRET", ""), } AWS_CREDS_2 = { "accessKeyId": os.environ.get("FLE_AWS_KEY2", ""), "secretAccessKey": os.environ.get("FLE_AWS_SECRET2", ""), } AZURE_CREDS = { "tenantId": os.environ.get("FLE_AZURE_TENANTID", ""), "clientId": os.environ.get("FLE_AZURE_CLIENTID", ""), "clientSecret": os.environ.get("FLE_AZURE_CLIENTSECRET", ""), } GCP_CREDS = { "email": os.environ.get("FLE_GCP_EMAIL", ""), "privateKey": os.environ.get("FLE_GCP_PRIVATEKEY", ""), } KMIP_CREDS = {"endpoint": os.environ.get("FLE_KMIP_ENDPOINT", "localhost:5698")} # Ensure Evergreen metadata doesn't result in truncation os.environ.setdefault("MONGOB_LOG_MAX_DOCUMENT_LENGTH", "2000") def is_server_resolvable(): """Returns True if 'server' is resolvable.""" socket_timeout = socket.getdefaulttimeout() socket.setdefaulttimeout(1) try: try: socket.gethostbyname("server") return True except OSError: return False finally: socket.setdefaulttimeout(socket_timeout) def _create_user(authdb, user, pwd=None, roles=None, **kwargs): cmd = SON([("createUser", user)]) # X509 doesn't use a password if pwd: cmd["pwd"] = pwd cmd["roles"] = roles or ["root"] cmd.update(**kwargs) return authdb.command(cmd) class client_knobs: def __init__( self, heartbeat_frequency=None, min_heartbeat_interval=None, kill_cursor_frequency=None, events_queue_frequency=None, ): self.heartbeat_frequency = heartbeat_frequency self.min_heartbeat_interval = min_heartbeat_interval self.kill_cursor_frequency = kill_cursor_frequency self.events_queue_frequency = events_queue_frequency self.old_heartbeat_frequency = None self.old_min_heartbeat_interval = None self.old_kill_cursor_frequency = None self.old_events_queue_frequency = None self._enabled = False self._stack = None def enable(self): self.old_heartbeat_frequency = common.HEARTBEAT_FREQUENCY self.old_min_heartbeat_interval = common.MIN_HEARTBEAT_INTERVAL self.old_kill_cursor_frequency = common.KILL_CURSOR_FREQUENCY self.old_events_queue_frequency = common.EVENTS_QUEUE_FREQUENCY if self.heartbeat_frequency is not None: common.HEARTBEAT_FREQUENCY = self.heartbeat_frequency if self.min_heartbeat_interval is not None: common.MIN_HEARTBEAT_INTERVAL = self.min_heartbeat_interval if self.kill_cursor_frequency is not None: common.KILL_CURSOR_FREQUENCY = self.kill_cursor_frequency if self.events_queue_frequency is not None: common.EVENTS_QUEUE_FREQUENCY = self.events_queue_frequency self._enabled = True # Store the allocation traceback to catch non-disabled client_knobs. self._stack = "".join(traceback.format_stack()) def __enter__(self): self.enable() @no_type_check def disable(self): common.HEARTBEAT_FREQUENCY = self.old_heartbeat_frequency common.MIN_HEARTBEAT_INTERVAL = self.old_min_heartbeat_interval common.KILL_CURSOR_FREQUENCY = self.old_kill_cursor_frequency common.EVENTS_QUEUE_FREQUENCY = self.old_events_queue_frequency self._enabled = False def __exit__(self, exc_type, exc_val, exc_tb): self.disable() def __call__(self, func): def make_wrapper(f): @wraps(f) def wrap(*args, **kwargs): with self: return f(*args, **kwargs) return wrap return make_wrapper(func) def __del__(self): if self._enabled: msg = ( "ERROR: client_knobs still enabled! HEARTBEAT_FREQUENCY={}, " "MIN_HEARTBEAT_INTERVAL={}, KILL_CURSOR_FREQUENCY={}, " "EVENTS_QUEUE_FREQUENCY={}, stack:\n{}".format( common.HEARTBEAT_FREQUENCY, common.MIN_HEARTBEAT_INTERVAL, common.KILL_CURSOR_FREQUENCY, common.EVENTS_QUEUE_FREQUENCY, self._stack, ) ) self.disable() raise Exception(msg) def _all_users(db): return {u["user"] for u in db.command("usersInfo").get("users", [])} class ClientContext: client: MongoClient MULTI_MONGOS_LB_URI = MULTI_MONGOS_LB_URI def __init__(self): """Create a client and grab essential information from the server.""" self.connection_attempts = [] self.connected = False self.w = None self.nodes = set() self.replica_set_name = None self.cmd_line = None self.server_status = None self.version = Version(-1) # Needs to be comparable with Version self.auth_enabled = False self.test_commands_enabled = False self.server_parameters = {} self._hello = None self.is_mongos = False self.mongoses = [] self.is_rs = False self.has_ipv6 = False self.tls = False self.tlsCertificateKeyFile = False self.server_is_resolvable = is_server_resolvable() self.default_client_options: Dict = {} self.sessions_enabled = False self.client = None # type: ignore self.conn_lock = threading.Lock() self.is_data_lake = False self.load_balancer = TEST_LOADBALANCER self.serverless = TEST_SERVERLESS if self.load_balancer or self.serverless: self.default_client_options["loadBalanced"] = True if COMPRESSORS: self.default_client_options["compressors"] = COMPRESSORS if MONGODB_API_VERSION: server_api = ServerApi(MONGODB_API_VERSION) self.default_client_options["server_api"] = server_api @property def client_options(self): """Return the MongoClient options for creating a duplicate client.""" opts = client_context.default_client_options.copy() opts["host"] = host opts["port"] = port if client_context.auth_enabled: opts["username"] = db_user opts["password"] = db_pwd if self.replica_set_name: opts["replicaSet"] = self.replica_set_name return opts @property def uri(self): """Return the MongoClient URI for creating a duplicate client.""" opts = client_context.default_client_options.copy() opts.pop("server_api", None) # Cannot be set from the URI opts_parts = [] for opt, val in opts.items(): strval = str(val) if isinstance(val, bool): strval = strval.lower() opts_parts.append(f"{opt}={quote_plus(strval)}") opts_part = "&".join(opts_parts) auth_part = "" if client_context.auth_enabled: auth_part = f"{quote_plus(db_user)}:{quote_plus(db_pwd)}@" return f"mongodb://{auth_part}{self.pair}/?{opts_part}" @property def hello(self): if not self._hello: if self.serverless or self.load_balancer: self._hello = self.client.admin.command(HelloCompat.CMD) else: self._hello = self.client.admin.command(HelloCompat.LEGACY_CMD) return self._hello def _connect(self, host, port, **kwargs): kwargs.update(self.default_client_options) client: MongoClient = pymongo.MongoClient( host, port, serverSelectionTimeoutMS=5000, **kwargs ) try: try: client.admin.command("ping") # Can we connect? except pymongo.errors.OperationFailure as exc: # SERVER-32063 self.connection_attempts.append( f"connected client {client!r}, but legacy hello failed: {exc}" ) else: self.connection_attempts.append(f"successfully connected client {client!r}") # If connected, then return client with default timeout return pymongo.MongoClient(host, port, **kwargs) except pymongo.errors.ConnectionFailure as exc: self.connection_attempts.append(f"failed to connect client {client!r}: {exc}") return None finally: client.close() def _init_client(self): self.client = self._connect(host, port) if self.client is not None: # Return early when connected to dataLake as mongohoused does not # support the getCmdLineOpts command and is tested without TLS. build_info: Any = self.client.admin.command("buildInfo") if "dataLake" in build_info: self.is_data_lake = True self.auth_enabled = True self.client = self._connect(host, port, username=db_user, password=db_pwd) self.connected = True return if HAVE_SSL and not self.client: # Is MongoDB configured for SSL? self.client = self._connect(host, port, **TLS_OPTIONS) if self.client: self.tls = True self.default_client_options.update(TLS_OPTIONS) self.tlsCertificateKeyFile = True if self.client: self.connected = True if self.serverless: self.auth_enabled = True else: try: self.cmd_line = self.client.admin.command("getCmdLineOpts") except pymongo.errors.OperationFailure as e: assert e.details is not None msg = e.details.get("errmsg", "") if e.code == 13 or "unauthorized" in msg or "login" in msg: # Unauthorized. self.auth_enabled = True else: raise else: self.auth_enabled = self._server_started_with_auth() if self.auth_enabled: if not self.serverless and not IS_SRV: # See if db_user already exists. if not self._check_user_provided(): _create_user(self.client.admin, db_user, db_pwd) self.client = self._connect( host, port, username=db_user, password=db_pwd, replicaSet=self.replica_set_name, **self.default_client_options, ) # May not have this if OperationFailure was raised earlier. self.cmd_line = self.client.admin.command("getCmdLineOpts") if self.serverless: self.server_status = {} else: self.server_status = self.client.admin.command("serverStatus") if self.storage_engine == "mmapv1": # MMAPv1 does not support retryWrites=True. self.default_client_options["retryWrites"] = False hello = self.hello self.sessions_enabled = "logicalSessionTimeoutMinutes" in hello if "setName" in hello: self.replica_set_name = str(hello["setName"]) self.is_rs = True if self.auth_enabled: # It doesn't matter which member we use as the seed here. self.client = pymongo.MongoClient( host, port, username=db_user, password=db_pwd, replicaSet=self.replica_set_name, **self.default_client_options, ) else: self.client = pymongo.MongoClient( host, port, replicaSet=self.replica_set_name, **self.default_client_options ) # Get the authoritative hello result from the primary. self._hello = None hello = self.hello nodes = [partition_node(node.lower()) for node in hello.get("hosts", [])] nodes.extend([partition_node(node.lower()) for node in hello.get("passives", [])]) nodes.extend([partition_node(node.lower()) for node in hello.get("arbiters", [])]) self.nodes = set(nodes) else: self.nodes = {(host, port)} self.w = len(hello.get("hosts", [])) or 1 self.version = Version.from_client(self.client) if self.serverless: self.server_parameters = { "requireApiVersion": False, "enableTestCommands": True, } self.test_commands_enabled = True self.has_ipv6 = False else: self.server_parameters = self.client.admin.command("getParameter", "*") assert self.cmd_line is not None if self.server_parameters["enableTestCommands"]: self.test_commands_enabled = True elif "parsed" in self.cmd_line: params = self.cmd_line["parsed"].get("setParameter", []) if "enableTestCommands=1" in params: self.test_commands_enabled = True else: params = self.cmd_line["parsed"].get("setParameter", {}) if params.get("enableTestCommands") == "1": self.test_commands_enabled = True self.has_ipv6 = self._server_started_with_ipv6() self.is_mongos = self.hello.get("msg") == "isdbgrid" if self.is_mongos: address = self.client.address self.mongoses.append(address) if not self.serverless: # Check for another mongos on the next port. assert address is not None next_address = address[0], address[1] + 1 mongos_client = self._connect(*next_address, **self.default_client_options) if mongos_client: hello = mongos_client.admin.command(HelloCompat.LEGACY_CMD) if hello.get("msg") == "isdbgrid": self.mongoses.append(next_address) def init(self): with self.conn_lock: if not self.client and not self.connection_attempts: self._init_client() def connection_attempt_info(self): return "\n".join(self.connection_attempts) @property def host(self): if self.is_rs and not IS_SRV: primary = self.client.primary return str(primary[0]) if primary is not None else host return host @property def port(self): if self.is_rs and not IS_SRV: primary = self.client.primary return primary[1] if primary is not None else port return port @property def pair(self): return "%s:%d" % (self.host, self.port) @property def has_secondaries(self): if not self.client: return False return bool(len(self.client.secondaries)) @property def storage_engine(self): try: return self.server_status.get("storageEngine", {}).get( # type:ignore[union-attr] "name" ) except AttributeError: # Raised if self.server_status is None. return None def check_auth_type(self, auth_type): auth_mechs = self.server_parameters.get("authenticationMechanisms", []) return auth_type in auth_mechs def _check_user_provided(self): """Return True if db_user/db_password is already an admin user.""" client: MongoClient = pymongo.MongoClient( host, port, username=db_user, password=db_pwd, **self.default_client_options, ) try: return db_user in _all_users(client.admin) except pymongo.errors.OperationFailure as e: assert e.details is not None msg = e.details.get("errmsg", "") if e.code == 18 or "auth fails" in msg: # Auth failed. return False else: raise finally: client.close() def _server_started_with_auth(self): # MongoDB >= 2.0 assert self.cmd_line is not None if "parsed" in self.cmd_line: parsed = self.cmd_line["parsed"] # MongoDB >= 2.6 if "security" in parsed: security = parsed["security"] # >= rc3 if "authorization" in security: return security["authorization"] == "enabled" # < rc3 return security.get("auth", False) or bool(security.get("keyFile")) return parsed.get("auth", False) or bool(parsed.get("keyFile")) # Legacy argv = self.cmd_line["argv"] return "--auth" in argv or "--keyFile" in argv def _server_started_with_ipv6(self): if not socket.has_ipv6: return False assert self.cmd_line is not None if "parsed" in self.cmd_line: if not self.cmd_line["parsed"].get("net", {}).get("ipv6"): return False else: if "--ipv6" not in self.cmd_line["argv"]: return False # The server was started with --ipv6. Is there an IPv6 route to it? try: for info in socket.getaddrinfo(self.host, self.port): if info[0] == socket.AF_INET6: return True except OSError: pass return False def _require(self, condition, msg, func=None): def make_wrapper(f): @wraps(f) def wrap(*args, **kwargs): self.init() # Always raise SkipTest if we can't connect to MongoDB if not self.connected: raise SkipTest(f"Cannot connect to MongoDB on {self.pair}") if condition(): return f(*args, **kwargs) raise SkipTest(msg) return wrap if func is None: def decorate(f): return make_wrapper(f) return decorate return make_wrapper(func) def create_user(self, dbname, user, pwd=None, roles=None, **kwargs): kwargs["writeConcern"] = {"w": self.w} return _create_user(self.client[dbname], user, pwd, roles, **kwargs) def drop_user(self, dbname, user): self.client[dbname].command("dropUser", user, writeConcern={"w": self.w}) def require_connection(self, func): """Run a test only if we can connect to MongoDB.""" return self._require( lambda: True, # _require checks if we're connected f"Cannot connect to MongoDB on {self.pair}", func=func, ) def require_data_lake(self, func): """Run a test only if we are connected to Atlas Data Lake.""" return self._require( lambda: self.is_data_lake, f"Not connected to Atlas Data Lake on {self.pair}", func=func, ) def require_no_mmap(self, func): """Run a test only if the server is not using the MMAPv1 storage engine. Only works for standalone and replica sets; tests are run regardless of storage engine on sharded clusters. """ def is_not_mmap(): if self.is_mongos: return True return self.storage_engine != "mmapv1" return self._require(is_not_mmap, "Storage engine must not be MMAPv1", func=func) def require_version_min(self, *ver): """Run a test only if the server version is at least ``version``.""" other_version = Version(*ver) return self._require( lambda: self.version >= other_version, "Server version must be at least %s" % str(other_version), ) def require_version_max(self, *ver): """Run a test only if the server version is at most ``version``.""" other_version = Version(*ver) return self._require( lambda: self.version <= other_version, "Server version must be at most %s" % str(other_version), ) def require_auth(self, func): """Run a test only if the server is running with auth enabled.""" return self._require( lambda: self.auth_enabled, "Authentication is not enabled on the server", func=func ) def require_no_auth(self, func): """Run a test only if the server is running without auth enabled.""" return self._require( lambda: not self.auth_enabled, "Authentication must not be enabled on the server", func=func, ) def require_replica_set(self, func): """Run a test only if the client is connected to a replica set.""" return self._require(lambda: self.is_rs, "Not connected to a replica set", func=func) def require_secondaries_count(self, count): """Run a test only if the client is connected to a replica set that has `count` secondaries. """ def sec_count(): return 0 if not self.client else len(self.client.secondaries) return self._require(lambda: sec_count() >= count, "Not enough secondaries available") @property def supports_secondary_read_pref(self): if self.has_secondaries: return True if self.is_mongos: shard = self.client.config.shards.find_one()["host"] # type:ignore[index] num_members = shard.count(",") + 1 return num_members > 1 return False def require_secondary_read_pref(self): """Run a test only if the client is connected to a cluster that supports secondary read preference """ return self._require( lambda: self.supports_secondary_read_pref, "This cluster does not support secondary read preference", ) def require_no_replica_set(self, func): """Run a test if the client is *not* connected to a replica set.""" return self._require( lambda: not self.is_rs, "Connected to a replica set, not a standalone mongod", func=func ) def require_ipv6(self, func): """Run a test only if the client can connect to a server via IPv6.""" return self._require(lambda: self.has_ipv6, "No IPv6", func=func) def require_no_mongos(self, func): """Run a test only if the client is not connected to a mongos.""" return self._require( lambda: not self.is_mongos, "Must be connected to a mongod, not a mongos", func=func ) def require_mongos(self, func): """Run a test only if the client is connected to a mongos.""" return self._require(lambda: self.is_mongos, "Must be connected to a mongos", func=func) def require_multiple_mongoses(self, func): """Run a test only if the client is connected to a sharded cluster that has 2 mongos nodes. """ return self._require( lambda: len(self.mongoses) > 1, "Must have multiple mongoses available", func=func ) def require_standalone(self, func): """Run a test only if the client is connected to a standalone.""" return self._require( lambda: not (self.is_mongos or self.is_rs), "Must be connected to a standalone", func=func, ) def require_no_standalone(self, func): """Run a test only if the client is not connected to a standalone.""" return self._require( lambda: self.is_mongos or self.is_rs, "Must be connected to a replica set or mongos", func=func, ) def require_load_balancer(self, func): """Run a test only if the client is connected to a load balancer.""" return self._require( lambda: self.load_balancer, "Must be connected to a load balancer", func=func ) def require_no_load_balancer(self, func): """Run a test only if the client is not connected to a load balancer.""" return self._require( lambda: not self.load_balancer, "Must not be connected to a load balancer", func=func ) def require_no_serverless(self, func): """Run a test only if the client is not connected to serverless.""" return self._require( lambda: not self.serverless, "Must not be connected to serverless", func=func ) def require_change_streams(self, func): """Run a test only if the server supports change streams.""" return self.require_no_mmap(self.require_no_standalone(self.require_no_serverless(func))) def is_topology_type(self, topologies): unknown = set(topologies) - { "single", "replicaset", "sharded", "sharded-replicaset", "load-balanced", } if unknown: raise AssertionError(f"Unknown topologies: {unknown!r}") if self.load_balancer: if "load-balanced" in topologies: return True return False if "single" in topologies and not (self.is_mongos or self.is_rs): return True if "replicaset" in topologies and self.is_rs: return True if "sharded" in topologies and self.is_mongos: return True if "sharded-replicaset" in topologies and self.is_mongos: shards = list(client_context.client.config.shards.find()) for shard in shards: # For a 3-member RS-backed sharded cluster, shard['host'] # will be 'replicaName/ip1:port1,ip2:port2,ip3:port3' # Otherwise it will be 'ip1:port1' host_spec = shard["host"] if not len(host_spec.split("/")) > 1: return False return True return False def require_cluster_type(self, topologies=None): """Run a test only if the client is connected to a cluster that conforms to one of the specified topologies. Acceptable topologies are 'single', 'replicaset', and 'sharded'. """ topologies = topologies or [] def _is_valid_topology(): return self.is_topology_type(topologies) return self._require(_is_valid_topology, "Cluster type not in %s" % (topologies)) def require_test_commands(self, func): """Run a test only if the server has test commands enabled.""" return self._require( lambda: self.test_commands_enabled, "Test commands must be enabled", func=func ) def require_failCommand_fail_point(self, func): """Run a test only if the server supports the failCommand fail point. """ return self._require( lambda: self.supports_failCommand_fail_point, "failCommand fail point must be supported", func=func, ) def require_failCommand_appName(self, func): """Run a test only if the server supports the failCommand appName.""" # SERVER-47195 return self._require( lambda: (self.test_commands_enabled and self.version >= (4, 4, -1)), "failCommand appName must be supported", func=func, ) def require_failCommand_blockConnection(self, func): """Run a test only if the server supports failCommand blockConnection.""" return self._require( lambda: ( self.test_commands_enabled and ( (not self.is_mongos and self.version >= (4, 2, 9)) or (self.is_mongos and self.version >= (4, 4)) ) ), "failCommand blockConnection is not supported", func=func, ) def require_tls(self, func): """Run a test only if the client can connect over TLS.""" return self._require(lambda: self.tls, "Must be able to connect via TLS", func=func) def require_no_tls(self, func): """Run a test only if the client can connect over TLS.""" return self._require(lambda: not self.tls, "Must be able to connect without TLS", func=func) def require_tlsCertificateKeyFile(self, func): """Run a test only if the client can connect with tlsCertificateKeyFile.""" return self._require( lambda: self.tlsCertificateKeyFile, "Must be able to connect with tlsCertificateKeyFile", func=func, ) def require_server_resolvable(self, func): """Run a test only if the hostname 'server' is resolvable.""" return self._require( lambda: self.server_is_resolvable, "No hosts entry for 'server'. Cannot validate hostname in the certificate", func=func, ) def require_sessions(self, func): """Run a test only if the deployment supports sessions.""" return self._require(lambda: self.sessions_enabled, "Sessions not supported", func=func) def supports_retryable_writes(self): if self.storage_engine == "mmapv1": return False if not self.sessions_enabled: return False return self.is_mongos or self.is_rs def require_retryable_writes(self, func): """Run a test only if the deployment supports retryable writes.""" return self._require( self.supports_retryable_writes, "This server does not support retryable writes", func=func, ) def supports_transactions(self): if self.storage_engine == "mmapv1": return False if self.version.at_least(4, 1, 8): return self.is_mongos or self.is_rs if self.version.at_least(4, 0): return self.is_rs return False def require_transactions(self, func): """Run a test only if the deployment might support transactions. *Might* because this does not test the storage engine or FCV. """ return self._require( self.supports_transactions, "Transactions are not supported", func=func ) def require_no_api_version(self, func): """Skip this test when testing with requireApiVersion.""" return self._require( lambda: not MONGODB_API_VERSION, "This test does not work with requireApiVersion", func=func, ) def mongos_seeds(self): return ",".join("{}:{}".format(*address) for address in self.mongoses) @property def supports_failCommand_fail_point(self): """Does the server support the failCommand fail point?""" if self.is_mongos: return self.version.at_least(4, 1, 5) and self.test_commands_enabled else: return self.version.at_least(4, 0) and self.test_commands_enabled @property def requires_hint_with_min_max_queries(self): """Does the server require a hint with min/max queries.""" # Changed in SERVER-39567. return self.version.at_least(4, 1, 10) @property def max_bson_size(self): return self.hello["maxBsonObjectSize"] @property def max_write_batch_size(self): return self.hello["maxWriteBatchSize"] # Reusable client context client_context = ClientContext() def sanitize_cmd(cmd): cp = cmd.copy() cp.pop("$clusterTime", None) cp.pop("$db", None) cp.pop("$readPreference", None) cp.pop("lsid", None) if MONGODB_API_VERSION: # Stable API parameters cp.pop("apiVersion", None) # OP_MSG encoding may move the payload type one field to the # end of the command. Do the same here. name = next(iter(cp)) try: identifier = message._FIELD_MAP[name] docs = cp.pop(identifier) cp[identifier] = docs except KeyError: pass return cp def sanitize_reply(reply): cp = reply.copy() cp.pop("$clusterTime", None) cp.pop("operationTime", None) return cp class PyMongoTestCase(unittest.TestCase): def assertEqualCommand(self, expected, actual, msg=None): self.assertEqual(sanitize_cmd(expected), sanitize_cmd(actual), msg) def assertEqualReply(self, expected, actual, msg=None): self.assertEqual(sanitize_reply(expected), sanitize_reply(actual), msg) @contextmanager def fail_point(self, command_args): cmd_on = SON([("configureFailPoint", "failCommand")]) cmd_on.update(command_args) client_context.client.admin.command(cmd_on) try: yield finally: client_context.client.admin.command( "configureFailPoint", cmd_on["configureFailPoint"], mode="off" ) @contextmanager def fork( self, target: Callable, timeout: float = 60 ) -> Generator[multiprocessing.Process, None, None]: """Helper for tests that use os.fork() Use in a with statement: with self.fork(target=lambda: print('in child')) as proc: self.assertTrue(proc.pid) # Child process was started """ def _print_threads(*args: object) -> None: if _print_threads.called: # type:ignore[attr-defined] return _print_threads.called = True # type:ignore[attr-defined] print_thread_tracebacks() _print_threads.called = False # type:ignore[attr-defined] def _target() -> None: signal.signal(signal.SIGUSR1, _print_threads) try: target() except Exception as exc: sys.stderr.write(f"Child process failed with: {exc}\n") _print_threads() # Sleep for a while to let the parent attach via GDB. time.sleep(2 * timeout) raise ctx = multiprocessing.get_context("fork") proc = ctx.Process(target=_target) proc.start() try: yield proc # type: ignore finally: proc.join(timeout) pid = proc.pid assert pid if proc.exitcode is None: # gdb to get C-level tracebacks print_thread_stacks(pid) # If it failed, SIGUSR1 to get thread tracebacks. os.kill(pid, signal.SIGUSR1) proc.join(5) if proc.exitcode is None: # SIGINT to get main thread traceback in case SIGUSR1 didn't work. os.kill(pid, signal.SIGINT) proc.join(5) if proc.exitcode is None: # SIGKILL in case SIGINT didn't work. proc.kill() proc.join(1) self.fail(f"child timed out after {timeout}s (see traceback in logs): deadlock?") self.assertEqual(proc.exitcode, 0) def print_thread_tracebacks() -> None: """Print all Python thread tracebacks.""" for thread_id, frame in sys._current_frames().items(): sys.stderr.write(f"\n--- Traceback for thread {thread_id} ---\n") traceback.print_stack(frame, file=sys.stderr) def print_thread_stacks(pid: int) -> None: """Print all C-level thread stacks for a given process id.""" if sys.platform == "darwin": cmd = ["lldb", "--attach-pid", f"{pid}", "--batch", "--one-line", '"thread backtrace all"'] else: cmd = ["gdb", f"--pid={pid}", "--batch", '--eval-command="thread apply all bt"'] try: res = subprocess.run( cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, encoding="utf-8" ) except Exception as exc: sys.stderr.write(f"Could not print C-level thread stacks because {cmd[0]} failed: {exc}") else: sys.stderr.write(res.stdout) class IntegrationTest(PyMongoTestCase): """Base class for TestCases that need a connection to MongoDB to pass.""" client: MongoClient[dict] db: Database credentials: Dict[str, str] @classmethod @client_context.require_connection def setUpClass(cls): if client_context.load_balancer and not getattr(cls, "RUN_ON_LOAD_BALANCER", False): raise SkipTest("this test does not support load balancers") if client_context.serverless and not getattr(cls, "RUN_ON_SERVERLESS", False): raise SkipTest("this test does not support serverless") cls.client = client_context.client cls.db = cls.client.pymongo_test if client_context.auth_enabled: cls.credentials = {"username": db_user, "password": db_pwd} else: cls.credentials = {} def cleanup_colls(self, *collections): """Cleanup collections faster than drop_collection.""" for c in collections: c = self.client[c.database.name][c.name] c.delete_many({}) c.drop_indexes() def patch_system_certs(self, ca_certs): patcher = SystemCertsPatcher(ca_certs) self.addCleanup(patcher.disable) class MockClientTest(unittest.TestCase): """Base class for TestCases that use MockClient. This class is *not* an IntegrationTest: if properly written, MockClient tests do not require a running server. The class temporarily overrides HEARTBEAT_FREQUENCY to speed up tests. """ # MockClients tests that use replicaSet, directConnection=True, pass # multiple seed addresses, or wait for heartbeat events are incompatible # with loadBalanced=True. @classmethod @client_context.require_no_load_balancer def setUpClass(cls): pass def setUp(self): super().setUp() self.client_knobs = client_knobs(heartbeat_frequency=0.001, min_heartbeat_interval=0.001) self.client_knobs.enable() def tearDown(self): self.client_knobs.disable() super().tearDown() # Global knobs to speed up the test suite. global_knobs = client_knobs(events_queue_frequency=0.05) def setup(): client_context.init() warnings.resetwarnings() warnings.simplefilter("always") global_knobs.enable() def _get_executors(topology): executors = [] for server in topology._servers.values(): # Some MockMonitor do not have an _executor. if hasattr(server._monitor, "_executor"): executors.append(server._monitor._executor) if hasattr(server._monitor, "_rtt_monitor"): executors.append(server._monitor._rtt_monitor._executor) executors.append(topology._Topology__events_executor) if topology._srv_monitor: executors.append(topology._srv_monitor._executor) return [e for e in executors if e is not None] def print_running_topology(topology): running = [e for e in _get_executors(topology) if not e._stopped] if running: print( "WARNING: found Topology with running threads:\n" f" Threads: {running}\n" f" Topology: {topology}\n" f" Creation traceback:\n{topology._settings._stack}" ) def print_running_clients(): from pymongo.topology import Topology processed = set() # Avoid false positives on the main test client. # XXX: Can be removed after PYTHON-1634 or PYTHON-1896. c = client_context.client if c: processed.add(c._topology._topology_id) # Call collect to manually cleanup any would-be gc'd clients to avoid # false positives. gc.collect() for obj in gc.get_objects(): try: if isinstance(obj, Topology): # Avoid printing the same Topology multiple times. if obj._topology_id in processed: continue print_running_topology(obj) processed.add(obj._topology_id) except ReferenceError: pass def teardown(): global_knobs.disable() garbage = [] for g in gc.garbage: garbage.append(f"GARBAGE: {g!r}") garbage.append(f" gc.get_referents: {gc.get_referents(g)!r}") garbage.append(f" gc.get_referrers: {gc.get_referrers(g)!r}") if garbage: raise AssertionError("\n".join(garbage)) c = client_context.client if c: if not client_context.is_data_lake: c.drop_database("pymongo-pooling-tests") c.drop_database("pymongo_test") c.drop_database("pymongo_test1") c.drop_database("pymongo_test2") c.drop_database("pymongo_test_mike") c.drop_database("pymongo_test_bernie") c.close() print_running_clients() def test_cases(suite): """Iterator over all TestCases within a TestSuite.""" for suite_or_case in suite._tests: if isinstance(suite_or_case, unittest.TestCase): # unittest.TestCase yield suite_or_case else: # unittest.TestSuite yield from test_cases(suite_or_case) # Helper method to workaround https://bugs.python.org/issue21724 def clear_warning_registry(): """Clear the __warningregistry__ for all modules.""" for _, module in list(sys.modules.items()): if hasattr(module, "__warningregistry__"): module.__warningregistry__ = {} # type:ignore[attr-defined] class SystemCertsPatcher: def __init__(self, ca_certs): if ( ssl.OPENSSL_VERSION.lower().startswith("libressl") and sys.platform == "darwin" and not _ssl.IS_PYOPENSSL ): raise SkipTest( "LibreSSL on OSX doesn't support setting CA certificates " "using SSL_CERT_FILE environment variable." ) self.original_certs = os.environ.get("SSL_CERT_FILE") # Tell OpenSSL where CA certificates live. os.environ["SSL_CERT_FILE"] = ca_certs def disable(self): if self.original_certs is None: os.environ.pop("SSL_CERT_FILE") else: os.environ["SSL_CERT_FILE"] = self.original_certs mongodb-mongo-python-driver-509e9b7/test/atlas/000077500000000000000000000000001462766011000215205ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/atlas/test_connection.py000066400000000000000000000066221462766011000252760ustar00rootroot00000000000000# Copyright 2018-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. """Test connections to various Atlas cluster types.""" from __future__ import annotations import os import sys import unittest from collections import defaultdict sys.path[0:0] = [""] import pymongo from pymongo.ssl_support import HAS_SNI URIS = { "ATLAS_REPL": os.environ.get("ATLAS_REPL"), "ATLAS_SHRD": os.environ.get("ATLAS_SHRD"), "ATLAS_FREE": os.environ.get("ATLAS_FREE"), "ATLAS_TLS11": os.environ.get("ATLAS_TLS11"), "ATLAS_TLS12": os.environ.get("ATLAS_TLS12"), "ATLAS_SERVERLESS": os.environ.get("ATLAS_SERVERLESS"), "ATLAS_SRV_REPL": os.environ.get("ATLAS_SRV_REPL"), "ATLAS_SRV_SHRD": os.environ.get("ATLAS_SRV_SHRD"), "ATLAS_SRV_FREE": os.environ.get("ATLAS_SRV_FREE"), "ATLAS_SRV_TLS11": os.environ.get("ATLAS_SRV_TLS11"), "ATLAS_SRV_TLS12": os.environ.get("ATLAS_SRV_TLS12"), "ATLAS_SRV_SERVERLESS": os.environ.get("ATLAS_SRV_SERVERLESS"), } def connect(uri): if not uri: raise Exception("Must set env variable to test.") client = pymongo.MongoClient(uri) # No TLS error client.admin.command("ping") # No auth error client.test.test.count_documents({}) class TestAtlasConnect(unittest.TestCase): @unittest.skipUnless(HAS_SNI, "Free tier requires SNI support") def test_free_tier(self): connect(URIS["ATLAS_FREE"]) def test_replica_set(self): connect(URIS["ATLAS_REPL"]) def test_sharded_cluster(self): connect(URIS["ATLAS_SHRD"]) def test_tls_11(self): connect(URIS["ATLAS_TLS11"]) def test_tls_12(self): connect(URIS["ATLAS_TLS12"]) def test_serverless(self): connect(URIS["ATLAS_SERVERLESS"]) def connect_srv(self, uri): connect(uri) self.assertIn("mongodb+srv://", uri) @unittest.skipUnless(HAS_SNI, "Free tier requires SNI support") def test_srv_free_tier(self): self.connect_srv(URIS["ATLAS_SRV_FREE"]) def test_srv_replica_set(self): self.connect_srv(URIS["ATLAS_SRV_REPL"]) def test_srv_sharded_cluster(self): self.connect_srv(URIS["ATLAS_SRV_SHRD"]) def test_srv_tls_11(self): self.connect_srv(URIS["ATLAS_SRV_TLS11"]) def test_srv_tls_12(self): self.connect_srv(URIS["ATLAS_SRV_TLS12"]) def test_srv_serverless(self): self.connect_srv(URIS["ATLAS_SRV_SERVERLESS"]) def test_uniqueness(self): """Ensure that we don't accidentally duplicate the test URIs.""" uri_to_names = defaultdict(list) for name, uri in URIS.items(): if uri: uri_to_names[uri].append(name) duplicates = [names for names in uri_to_names.values() if len(names) > 1] self.assertFalse( duplicates, f"Error: the following env variables have duplicate values: {duplicates}", ) if __name__ == "__main__": unittest.main() mongodb-mongo-python-driver-509e9b7/test/auth/000077500000000000000000000000001462766011000213555ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/auth/legacy/000077500000000000000000000000001462766011000226215ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/auth/legacy/connection-string.json000066400000000000000000000527471462766011000271760ustar00rootroot00000000000000{ "tests": [ { "description": "should use the default source and mechanism", "uri": "mongodb://user:password@localhost", "valid": true, "credential": { "username": "user", "password": "password", "source": "admin", "mechanism": null, "mechanism_properties": null } }, { "description": "should use the database when no authSource is specified", "uri": "mongodb://user:password@localhost/foo", "valid": true, "credential": { "username": "user", "password": "password", "source": "foo", "mechanism": null, "mechanism_properties": null } }, { "description": "should use the authSource when specified", "uri": "mongodb://user:password@localhost/foo?authSource=bar", "valid": true, "credential": { "username": "user", "password": "password", "source": "bar", "mechanism": null, "mechanism_properties": null } }, { "description": "should recognise the mechanism (GSSAPI)", "uri": "mongodb://user%40DOMAIN.COM@localhost/?authMechanism=GSSAPI", "valid": true, "credential": { "username": "user@DOMAIN.COM", "password": null, "source": "$external", "mechanism": "GSSAPI", "mechanism_properties": { "SERVICE_NAME": "mongodb" } } }, { "description": "should ignore the database (GSSAPI)", "uri": "mongodb://user%40DOMAIN.COM@localhost/foo?authMechanism=GSSAPI", "valid": true, "credential": { "username": "user@DOMAIN.COM", "password": null, "source": "$external", "mechanism": "GSSAPI", "mechanism_properties": { "SERVICE_NAME": "mongodb" } } }, { "description": "should accept valid authSource (GSSAPI)", "uri": "mongodb://user%40DOMAIN.COM@localhost/?authMechanism=GSSAPI&authSource=$external", "valid": true, "credential": { "username": "user@DOMAIN.COM", "password": null, "source": "$external", "mechanism": "GSSAPI", "mechanism_properties": { "SERVICE_NAME": "mongodb" } } }, { "description": "should accept generic mechanism property (GSSAPI)", "uri": "mongodb://user%40DOMAIN.COM@localhost/?authMechanism=GSSAPI&authMechanismProperties=SERVICE_NAME:other,CANONICALIZE_HOST_NAME:true", "valid": true, "credential": { "username": "user@DOMAIN.COM", "password": null, "source": "$external", "mechanism": "GSSAPI", "mechanism_properties": { "SERVICE_NAME": "other", "CANONICALIZE_HOST_NAME": true } } }, { "description": "should accept the password (GSSAPI)", "uri": "mongodb://user%40DOMAIN.COM:password@localhost/?authMechanism=GSSAPI&authSource=$external", "valid": true, "credential": { "username": "user@DOMAIN.COM", "password": "password", "source": "$external", "mechanism": "GSSAPI", "mechanism_properties": { "SERVICE_NAME": "mongodb" } } }, { "description": "must raise an error when the authSource is empty", "uri": "mongodb://user:password@localhost/foo?authSource=", "valid": false }, { "description": "must raise an error when the authSource is empty without credentials", "uri": "mongodb://localhost/admin?authSource=", "valid": false }, { "description": "should throw an exception if authSource is invalid (GSSAPI)", "uri": "mongodb://user%40DOMAIN.COM@localhost/?authMechanism=GSSAPI&authSource=foo", "valid": false }, { "description": "should throw an exception if no username (GSSAPI)", "uri": "mongodb://localhost/?authMechanism=GSSAPI", "valid": false }, { "description": "should recognize the mechanism (MONGODB-CR)", "uri": "mongodb://user:password@localhost/?authMechanism=MONGODB-CR", "valid": true, "credential": { "username": "user", "password": "password", "source": "admin", "mechanism": "MONGODB-CR", "mechanism_properties": null } }, { "description": "should use the database when no authSource is specified (MONGODB-CR)", "uri": "mongodb://user:password@localhost/foo?authMechanism=MONGODB-CR", "valid": true, "credential": { "username": "user", "password": "password", "source": "foo", "mechanism": "MONGODB-CR", "mechanism_properties": null } }, { "description": "should use the authSource when specified (MONGODB-CR)", "uri": "mongodb://user:password@localhost/foo?authMechanism=MONGODB-CR&authSource=bar", "valid": true, "credential": { "username": "user", "password": "password", "source": "bar", "mechanism": "MONGODB-CR", "mechanism_properties": null } }, { "description": "should throw an exception if no username is supplied (MONGODB-CR)", "uri": "mongodb://localhost/?authMechanism=MONGODB-CR", "valid": false }, { "description": "should recognize the mechanism (MONGODB-X509)", "uri": "mongodb://CN%3DmyName%2COU%3DmyOrgUnit%2CO%3DmyOrg%2CL%3DmyLocality%2CST%3DmyState%2CC%3DmyCountry@localhost/?authMechanism=MONGODB-X509", "valid": true, "credential": { "username": "CN=myName,OU=myOrgUnit,O=myOrg,L=myLocality,ST=myState,C=myCountry", "password": null, "source": "$external", "mechanism": "MONGODB-X509", "mechanism_properties": null } }, { "description": "should ignore the database (MONGODB-X509)", "uri": "mongodb://CN%3DmyName%2COU%3DmyOrgUnit%2CO%3DmyOrg%2CL%3DmyLocality%2CST%3DmyState%2CC%3DmyCountry@localhost/foo?authMechanism=MONGODB-X509", "valid": true, "credential": { "username": "CN=myName,OU=myOrgUnit,O=myOrg,L=myLocality,ST=myState,C=myCountry", "password": null, "source": "$external", "mechanism": "MONGODB-X509", "mechanism_properties": null } }, { "description": "should accept valid authSource (MONGODB-X509)", "uri": "mongodb://CN%3DmyName%2COU%3DmyOrgUnit%2CO%3DmyOrg%2CL%3DmyLocality%2CST%3DmyState%2CC%3DmyCountry@localhost/?authMechanism=MONGODB-X509&authSource=$external", "valid": true, "credential": { "username": "CN=myName,OU=myOrgUnit,O=myOrg,L=myLocality,ST=myState,C=myCountry", "password": null, "source": "$external", "mechanism": "MONGODB-X509", "mechanism_properties": null } }, { "description": "should recognize the mechanism with no username (MONGODB-X509)", "uri": "mongodb://localhost/?authMechanism=MONGODB-X509", "valid": true, "credential": { "username": null, "password": null, "source": "$external", "mechanism": "MONGODB-X509", "mechanism_properties": null } }, { "description": "should recognize the mechanism with no username when auth source is explicitly specified (MONGODB-X509)", "uri": "mongodb://localhost/?authMechanism=MONGODB-X509&authSource=$external", "valid": true, "credential": { "username": null, "password": null, "source": "$external", "mechanism": "MONGODB-X509", "mechanism_properties": null } }, { "description": "should throw an exception if supplied a password (MONGODB-X509)", "uri": "mongodb://user:password@localhost/?authMechanism=MONGODB-X509", "valid": false }, { "description": "should throw an exception if authSource is invalid (MONGODB-X509)", "uri": "mongodb://CN%3DmyName%2COU%3DmyOrgUnit%2CO%3DmyOrg%2CL%3DmyLocality%2CST%3DmyState%2CC%3DmyCountry@localhost/foo?authMechanism=MONGODB-X509&authSource=bar", "valid": false }, { "description": "should recognize the mechanism (PLAIN)", "uri": "mongodb://user:password@localhost/?authMechanism=PLAIN", "valid": true, "credential": { "username": "user", "password": "password", "source": "$external", "mechanism": "PLAIN", "mechanism_properties": null } }, { "description": "should use the database when no authSource is specified (PLAIN)", "uri": "mongodb://user:password@localhost/foo?authMechanism=PLAIN", "valid": true, "credential": { "username": "user", "password": "password", "source": "foo", "mechanism": "PLAIN", "mechanism_properties": null } }, { "description": "should use the authSource when specified (PLAIN)", "uri": "mongodb://user:password@localhost/foo?authMechanism=PLAIN&authSource=bar", "valid": true, "credential": { "username": "user", "password": "password", "source": "bar", "mechanism": "PLAIN", "mechanism_properties": null } }, { "description": "should throw an exception if no username (PLAIN)", "uri": "mongodb://localhost/?authMechanism=PLAIN", "valid": false }, { "description": "should recognize the mechanism (SCRAM-SHA-1)", "uri": "mongodb://user:password@localhost/?authMechanism=SCRAM-SHA-1", "valid": true, "credential": { "username": "user", "password": "password", "source": "admin", "mechanism": "SCRAM-SHA-1", "mechanism_properties": null } }, { "description": "should use the database when no authSource is specified (SCRAM-SHA-1)", "uri": "mongodb://user:password@localhost/foo?authMechanism=SCRAM-SHA-1", "valid": true, "credential": { "username": "user", "password": "password", "source": "foo", "mechanism": "SCRAM-SHA-1", "mechanism_properties": null } }, { "description": "should accept valid authSource (SCRAM-SHA-1)", "uri": "mongodb://user:password@localhost/foo?authMechanism=SCRAM-SHA-1&authSource=bar", "valid": true, "credential": { "username": "user", "password": "password", "source": "bar", "mechanism": "SCRAM-SHA-1", "mechanism_properties": null } }, { "description": "should throw an exception if no username (SCRAM-SHA-1)", "uri": "mongodb://localhost/?authMechanism=SCRAM-SHA-1", "valid": false }, { "description": "should recognize the mechanism (SCRAM-SHA-256)", "uri": "mongodb://user:password@localhost/?authMechanism=SCRAM-SHA-256", "valid": true, "credential": { "username": "user", "password": "password", "source": "admin", "mechanism": "SCRAM-SHA-256", "mechanism_properties": null } }, { "description": "should use the database when no authSource is specified (SCRAM-SHA-256)", "uri": "mongodb://user:password@localhost/foo?authMechanism=SCRAM-SHA-256", "valid": true, "credential": { "username": "user", "password": "password", "source": "foo", "mechanism": "SCRAM-SHA-256", "mechanism_properties": null } }, { "description": "should accept valid authSource (SCRAM-SHA-256)", "uri": "mongodb://user:password@localhost/foo?authMechanism=SCRAM-SHA-256&authSource=bar", "valid": true, "credential": { "username": "user", "password": "password", "source": "bar", "mechanism": "SCRAM-SHA-256", "mechanism_properties": null } }, { "description": "should throw an exception if no username (SCRAM-SHA-256)", "uri": "mongodb://localhost/?authMechanism=SCRAM-SHA-256", "valid": false }, { "description": "URI with no auth-related info doesn't create credential", "uri": "mongodb://localhost/", "valid": true, "credential": null }, { "description": "database in URI path doesn't create credentials", "uri": "mongodb://localhost/foo", "valid": true, "credential": null }, { "description": "authSource without username doesn't create credential (default mechanism)", "uri": "mongodb://localhost/?authSource=foo", "valid": true, "credential": null }, { "description": "should throw an exception if no username provided (userinfo implies default mechanism)", "uri": "mongodb://@localhost.com/", "valid": false }, { "description": "should throw an exception if no username/password provided (userinfo implies default mechanism)", "uri": "mongodb://:@localhost.com/", "valid": false }, { "description": "should recognise the mechanism (MONGODB-AWS)", "uri": "mongodb://localhost/?authMechanism=MONGODB-AWS", "valid": true, "credential": { "username": null, "password": null, "source": "$external", "mechanism": "MONGODB-AWS", "mechanism_properties": null } }, { "description": "should recognise the mechanism when auth source is explicitly specified (MONGODB-AWS)", "uri": "mongodb://localhost/?authMechanism=MONGODB-AWS&authSource=$external", "valid": true, "credential": { "username": null, "password": null, "source": "$external", "mechanism": "MONGODB-AWS", "mechanism_properties": null } }, { "description": "should throw an exception if username and no password (MONGODB-AWS)", "uri": "mongodb://user@localhost/?authMechanism=MONGODB-AWS", "valid": false, "credential": null }, { "description": "should use username and password if specified (MONGODB-AWS)", "uri": "mongodb://user%21%40%23%24%25%5E%26%2A%28%29_%2B:pass%21%40%23%24%25%5E%26%2A%28%29_%2B@localhost/?authMechanism=MONGODB-AWS", "valid": true, "credential": { "username": "user!@#$%^&*()_+", "password": "pass!@#$%^&*()_+", "source": "$external", "mechanism": "MONGODB-AWS", "mechanism_properties": null } }, { "description": "should use username, password and session token if specified (MONGODB-AWS)", "uri": "mongodb://user:password@localhost/?authMechanism=MONGODB-AWS&authMechanismProperties=AWS_SESSION_TOKEN:token%21%40%23%24%25%5E%26%2A%28%29_%2B", "valid": true, "credential": { "username": "user", "password": "password", "source": "$external", "mechanism": "MONGODB-AWS", "mechanism_properties": { "AWS_SESSION_TOKEN": "token!@#$%^&*()_+" } } }, { "description": "should recognise the mechanism with test environment (MONGODB-OIDC)", "uri": "mongodb://localhost/?authMechanism=MONGODB-OIDC&authMechanismProperties=ENVIRONMENT:test", "valid": true, "credential": { "username": null, "password": null, "source": "$external", "mechanism": "MONGODB-OIDC", "mechanism_properties": { "ENVIRONMENT": "test" } } }, { "description": "should recognise the mechanism when auth source is explicitly specified and with environment (MONGODB-OIDC)", "uri": "mongodb://localhost/?authMechanism=MONGODB-OIDC&authSource=$external&authMechanismProperties=ENVIRONMENT:test", "valid": true, "credential": { "username": null, "password": null, "source": "$external", "mechanism": "MONGODB-OIDC", "mechanism_properties": { "ENVIRONMENT": "test" } } }, { "description": "should throw an exception if username and password is specified for test environment (MONGODB-OIDC)", "uri": "mongodb://user:pass@localhost/?authMechanism=MONGODB-OIDC&authMechanismProperties=ENVIRONMENT:test", "valid": false, "credential": null }, { "description": "should throw an exception if username is specified for test environment (MONGODB-OIDC)", "uri": "mongodb://principalName@localhost/?authMechanism=MONGODB-OIDC&ENVIRONMENT:test", "valid": false, "credential": null }, { "description": "should throw an exception if specified environment is not supported (MONGODB-OIDC)", "uri": "mongodb://localhost/?authMechanism=MONGODB-OIDC&authMechanismProperties=ENVIRONMENT:invalid", "valid": false, "credential": null }, { "description": "should throw an exception if neither provider nor callbacks specified (MONGODB-OIDC)", "uri": "mongodb://localhost/?authMechanism=MONGODB-OIDC", "valid": false, "credential": null }, { "description": "should recognise the mechanism with azure provider (MONGODB-OIDC)", "uri": "mongodb://localhost/?authMechanism=MONGODB-OIDC&authMechanismProperties=ENVIRONMENT:azure,TOKEN_RESOURCE:foo", "valid": true, "credential": { "username": null, "password": null, "source": "$external", "mechanism": "MONGODB-OIDC", "mechanism_properties": { "ENVIRONMENT": "azure", "TOKEN_RESOURCE": "foo" } } }, { "description": "should accept a username with azure provider (MONGODB-OIDC)", "uri": "mongodb://user@localhost/?authMechanism=MONGODB-OIDC&authMechanismProperties=ENVIRONMENT:azure,TOKEN_RESOURCE:foo", "valid": true, "credential": { "username": "user", "password": null, "source": "$external", "mechanism": "MONGODB-OIDC", "mechanism_properties": { "ENVIRONMENT": "azure", "TOKEN_RESOURCE": "foo" } } }, { "description": "should accept a url-encoded TOKEN_RESOURCE (MONGODB-OIDC)", "uri": "mongodb://user@localhost/?authMechanism=MONGODB-OIDC&authMechanismProperties=ENVIRONMENT:azure,TOKEN_RESOURCE:mongodb%3A%2F%2Ftest-cluster", "valid": true, "credential": { "username": "user", "password": null, "source": "$external", "mechanism": "MONGODB-OIDC", "mechanism_properties": { "ENVIRONMENT": "azure", "TOKEN_RESOURCE": "mongodb://test-cluster" } } }, { "description": "should accept an un-encoded TOKEN_RESOURCE (MONGODB-OIDC)", "uri": "mongodb://user@localhost/?authMechanism=MONGODB-OIDC&authMechanismProperties=ENVIRONMENT:azure,TOKEN_RESOURCE:mongodb://test-cluster", "valid": true, "credential": { "username": "user", "password": null, "source": "$external", "mechanism": "MONGODB-OIDC", "mechanism_properties": { "ENVIRONMENT": "azure", "TOKEN_RESOURCE": "mongodb://test-cluster" } } }, { "description": "should handle a complicated url-encoded TOKEN_RESOURCE (MONGODB-OIDC)", "uri": "mongodb://user@localhost/?authMechanism=MONGODB-OIDC&authMechanismProperties=ENVIRONMENT:azure,TOKEN_RESOURCE:abc%2Cd%25ef%3Ag%26hi", "valid": true, "credential": { "username": "user", "password": null, "source": "$external", "mechanism": "MONGODB-OIDC", "mechanism_properties": { "ENVIRONMENT": "azure", "TOKEN_RESOURCE": "abc,d%ef:g&hi" } } }, { "description": "should url-encode a TOKEN_RESOURCE (MONGODB-OIDC)", "uri": "mongodb://user@localhost/?authMechanism=MONGODB-OIDC&authMechanismProperties=ENVIRONMENT:azure,TOKEN_RESOURCE:a$b", "valid": true, "credential": { "username": "user", "password": null, "source": "$external", "mechanism": "MONGODB-OIDC", "mechanism_properties": { "ENVIRONMENT": "azure", "TOKEN_RESOURCE": "a$b" } } }, { "description": "should accept a username and throw an error for a password with azure provider (MONGODB-OIDC)", "uri": "mongodb://user:pass@localhost/?authMechanism=MONGODB-OIDC&authMechanismProperties=ENVIRONMENT:azure,TOKEN_RESOURCE:foo", "valid": false, "credential": null }, { "description": "should throw an exception if no token audience is given for azure provider (MONGODB-OIDC)", "uri": "mongodb://username@localhost/?authMechanism=MONGODB-OIDC&authMechanismProperties=ENVIRONMENT:azure", "valid": false, "credential": null }, { "description": "should recognise the mechanism with gcp provider (MONGODB-OIDC)", "uri": "mongodb://localhost/?authMechanism=MONGODB-OIDC&authMechanismProperties=ENVIRONMENT:gcp,TOKEN_RESOURCE:foo", "valid": true, "credential": { "username": null, "password": null, "source": "$external", "mechanism": "MONGODB-OIDC", "mechanism_properties": { "ENVIRONMENT": "gcp", "TOKEN_RESOURCE": "foo" } } }, { "description": "should throw an error for a username and password with gcp provider (MONGODB-OIDC)", "uri": "mongodb://user:pass@localhost/?authMechanism=MONGODB-OIDC&authMechanismProperties=ENVIRONMENT:gcp,TOKEN_RESOURCE:foo", "valid": false, "credential": null }, { "description": "should throw an error if not TOKEN_RESOURCE with gcp provider (MONGODB-OIDC)", "uri": "mongodb://user:pass@localhost/?authMechanism=MONGODB-OIDC&authMechanismProperties=ENVIRONMENT:gcp", "valid": false, "credential": null } ] }mongodb-mongo-python-driver-509e9b7/test/auth/unified/000077500000000000000000000000001462766011000230005ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/auth/unified/mongodb-oidc-no-retry.json000066400000000000000000000230111462766011000300060ustar00rootroot00000000000000{ "description": "MONGODB-OIDC authentication with retry disabled", "schemaVersion": "1.19", "runOnRequirements": [ { "minServerVersion": "7.0", "auth": true, "authMechanism": "MONGODB-OIDC" } ], "createEntities": [ { "client": { "id": "failPointClient", "useMultipleMongoses": false } }, { "client": { "id": "client0", "uriOptions": { "authMechanism": "MONGODB-OIDC", "authMechanismProperties": { "$$placeholder": 1 }, "retryReads": false, "retryWrites": false }, "observeEvents": [ "commandStartedEvent", "commandSucceededEvent", "commandFailedEvent" ] } }, { "database": { "id": "database0", "client": "client0", "databaseName": "test" } }, { "collection": { "id": "collection0", "database": "database0", "collectionName": "collName" } } ], "initialData": [ { "collectionName": "collName", "databaseName": "test", "documents": [] } ], "tests": [ { "description": "A read operation should succeed", "operations": [ { "name": "find", "object": "collection0", "arguments": { "filter": {} }, "expectResult": [] } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "find": "collName", "filter": {} } } }, { "commandSucceededEvent": { "commandName": "find" } } ] } ] }, { "description": "A write operation should succeed", "operations": [ { "name": "insertOne", "object": "collection0", "arguments": { "document": { "_id": 1, "x": 1 } } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "insert": "collName", "documents": [ { "_id": 1, "x": 1 } ] } } }, { "commandSucceededEvent": { "commandName": "insert" } } ] } ] }, { "description": "Read commands should reauthenticate and retry when a ReauthenticationRequired error happens", "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "find" ], "errorCode": 391 } } } }, { "name": "find", "object": "collection0", "arguments": { "filter": {} }, "expectResult": [] } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "find": "collName", "filter": {} } } }, { "commandFailedEvent": { "commandName": "find" } }, { "commandStartedEvent": { "command": { "find": "collName", "filter": {} } } }, { "commandSucceededEvent": { "commandName": "find" } } ] } ] }, { "description": "Write commands should reauthenticate and retry when a ReauthenticationRequired error happens", "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "insert" ], "errorCode": 391 } } } }, { "name": "insertOne", "object": "collection0", "arguments": { "document": { "_id": 1, "x": 1 } } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "insert": "collName", "documents": [ { "_id": 1, "x": 1 } ] } } }, { "commandFailedEvent": { "commandName": "insert" } }, { "commandStartedEvent": { "command": { "insert": "collName", "documents": [ { "_id": 1, "x": 1 } ] } } }, { "commandSucceededEvent": { "commandName": "insert" } } ] } ] }, { "description": "Handshake with cached token should use speculative authentication", "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "insert" ], "closeConnection": true } } } }, { "name": "insertOne", "object": "collection0", "arguments": { "document": { "_id": 1, "x": 1 } }, "expectError": { "isClientError": true } }, { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "saslStart" ], "errorCode": 18 } } } }, { "name": "insertOne", "object": "collection0", "arguments": { "document": { "_id": 1, "x": 1 } } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "insert": "collName", "documents": [ { "_id": 1, "x": 1 } ] } } }, { "commandFailedEvent": { "commandName": "insert" } }, { "commandStartedEvent": { "command": { "insert": "collName", "documents": [ { "_id": 1, "x": 1 } ] } } }, { "commandSucceededEvent": { "commandName": "insert" } } ] } ] }, { "description": "Handshake without cached token should not use speculative authentication", "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "saslStart" ], "errorCode": 18 } } } }, { "name": "insertOne", "object": "collection0", "arguments": { "document": { "_id": 1, "x": 1 } }, "expectError": { "errorCode": 18 } } ] } ] } mongodb-mongo-python-driver-509e9b7/test/auth_aws/000077500000000000000000000000001462766011000222275ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/auth_aws/test_auth_aws.py000066400000000000000000000152131462766011000254550ustar00rootroot00000000000000# Copyright 2020-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. """Test MONGODB-AWS Authentication.""" from __future__ import annotations import os import sys import unittest from unittest.mock import patch sys.path[0:0] = [""] from pymongo_auth_aws import AwsCredential, auth from pymongo import MongoClient from pymongo.errors import OperationFailure from pymongo.uri_parser import parse_uri class TestAuthAWS(unittest.TestCase): uri: str @classmethod def setUpClass(cls): cls.uri = os.environ["MONGODB_URI"] def test_should_fail_without_credentials(self): if "@" not in self.uri: self.skipTest("MONGODB_URI already has no credentials") hosts = ["{}:{}".format(*addr) for addr in parse_uri(self.uri)["nodelist"]] self.assertTrue(hosts) with MongoClient(hosts) as client: with self.assertRaises(OperationFailure): client.aws.test.find_one() def test_should_fail_incorrect_credentials(self): with MongoClient( self.uri, username="fake", password="fake", authMechanism="MONGODB-AWS" ) as client: with self.assertRaises(OperationFailure): client.get_database().test.find_one() def test_connect_uri(self): with MongoClient(self.uri) as client: client.get_database().test.find_one() def setup_cache(self): if os.environ.get("AWS_ACCESS_KEY_ID", None) or "@" in self.uri: self.skipTest("Not testing cached credentials") # Make a connection to ensure that we enable caching. client = MongoClient(self.uri) client.get_database().test.find_one() client.close() self.assertTrue(auth.get_use_cached_credentials()) # Ensure cleared credentials. auth.set_cached_credentials(None) self.assertEqual(auth.get_cached_credentials(), None) client = MongoClient(self.uri) client.get_database().test.find_one() client.close() return auth.get_cached_credentials() def test_cache_credentials(self): creds = self.setup_cache() self.assertIsNotNone(creds) def test_cache_about_to_expire(self): creds = self.setup_cache() client = MongoClient(self.uri) self.addCleanup(client.close) # Make the creds about to expire. creds = auth.get_cached_credentials() assert creds is not None creds = AwsCredential(creds.username, creds.password, creds.token, lambda x: True) auth.set_cached_credentials(creds) client.get_database().test.find_one() new_creds = auth.get_cached_credentials() self.assertNotEqual(creds, new_creds) def test_poisoned_cache(self): creds = self.setup_cache() client = MongoClient(self.uri) self.addCleanup(client.close) # Poison the creds with invalid password. assert creds is not None creds = AwsCredential("a" * 24, "b" * 24, "c" * 24) auth.set_cached_credentials(creds) with self.assertRaises(OperationFailure): client.get_database().test.find_one() # Make sure the cache was cleared. self.assertEqual(auth.get_cached_credentials(), None) # The next attempt should generate a new cred and succeed. client.get_database().test.find_one() self.assertNotEqual(auth.get_cached_credentials(), None) def test_environment_variables_ignored(self): creds = self.setup_cache() self.assertIsNotNone(creds) os.environ.copy() client = MongoClient(self.uri) self.addCleanup(client.close) client.get_database().test.find_one() self.assertIsNotNone(auth.get_cached_credentials()) mock_env = { "AWS_ACCESS_KEY_ID": "foo", "AWS_SECRET_ACCESS_KEY": "bar", "AWS_SESSION_TOKEN": "baz", } with patch.dict("os.environ", mock_env): self.assertEqual(os.environ["AWS_ACCESS_KEY_ID"], "foo") client.get_database().test.find_one() auth.set_cached_credentials(None) client2 = MongoClient(self.uri) self.addCleanup(client2.close) with patch.dict("os.environ", mock_env): self.assertEqual(os.environ["AWS_ACCESS_KEY_ID"], "foo") with self.assertRaises(OperationFailure): client2.get_database().test.find_one() def test_no_cache_environment_variables(self): creds = self.setup_cache() self.assertIsNotNone(creds) auth.set_cached_credentials(None) mock_env = {"AWS_ACCESS_KEY_ID": creds.username, "AWS_SECRET_ACCESS_KEY": creds.password} if creds.token: mock_env["AWS_SESSION_TOKEN"] = creds.token client = MongoClient(self.uri) self.addCleanup(client.close) with patch.dict(os.environ, mock_env): self.assertEqual(os.environ["AWS_ACCESS_KEY_ID"], creds.username) client.get_database().test.find_one() self.assertIsNone(auth.get_cached_credentials()) mock_env["AWS_ACCESS_KEY_ID"] = "foo" client2 = MongoClient(self.uri) self.addCleanup(client2.close) with patch.dict("os.environ", mock_env), self.assertRaises(OperationFailure): self.assertEqual(os.environ["AWS_ACCESS_KEY_ID"], "foo") client2.get_database().test.find_one() class TestAWSLambdaExamples(unittest.TestCase): def test_shared_client(self): # Start AWS Lambda Example 1 import os from pymongo import MongoClient client = MongoClient(host=os.environ["MONGODB_URI"]) def lambda_handler(event, context): return client.db.command("ping") # End AWS Lambda Example 1 def test_IAM_auth(self): # Start AWS Lambda Example 2 import os from pymongo import MongoClient client = MongoClient( host=os.environ["MONGODB_URI"], authSource="$external", authMechanism="MONGODB-AWS", ) def lambda_handler(event, context): return client.db.command("ping") # End AWS Lambda Example 2 if __name__ == "__main__": unittest.main() mongodb-mongo-python-driver-509e9b7/test/auth_oidc/000077500000000000000000000000001462766011000223535ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/auth_oidc/test_auth_oidc.py000066400000000000000000001214301462766011000257240ustar00rootroot00000000000000# Copyright 2023-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. """Test MONGODB-OIDC Authentication.""" from __future__ import annotations import os import sys import threading import time import unittest import warnings from contextlib import contextmanager from pathlib import Path from typing import Dict sys.path[0:0] = [""] import pprint from test.unified_format import generate_test_classes from test.utils import EventListener from bson import SON from pymongo import MongoClient from pymongo._azure_helpers import _get_azure_response from pymongo._gcp_helpers import _get_gcp_response from pymongo.auth_oidc import OIDCCallback, OIDCCallbackContext, OIDCCallbackResult from pymongo.cursor import CursorType from pymongo.errors import AutoReconnect, ConfigurationError, OperationFailure from pymongo.hello import HelloCompat from pymongo.operations import InsertOne from pymongo.uri_parser import parse_uri ROOT = Path(__file__).parent.parent.resolve() TEST_PATH = ROOT / "auth" / "unified" ENVIRON = os.environ.get("OIDC_ENV", "test") DOMAIN = os.environ.get("OIDC_DOMAIN", "") TOKEN_DIR = os.environ.get("OIDC_TOKEN_DIR", "") TOKEN_FILE = os.environ.get("OIDC_TOKEN_FILE", "") # Generate unified tests. globals().update(generate_test_classes(str(TEST_PATH), module=__name__)) class OIDCTestBase(unittest.TestCase): @classmethod def setUpClass(cls): cls.uri_single = os.environ["MONGODB_URI_SINGLE"] cls.uri_multiple = os.environ.get("MONGODB_URI_MULTI") cls.uri_admin = os.environ["MONGODB_URI"] def setUp(self): self.request_called = 0 def get_token(self, username=None): """Get a token for the current provider.""" if ENVIRON == "test": if username is None: token_file = TOKEN_FILE else: token_file = os.path.join(TOKEN_DIR, username) with open(token_file) as fid: return fid.read() elif ENVIRON == "azure": opts = parse_uri(self.uri_single)["options"] token_aud = opts["authmechanismproperties"]["TOKEN_RESOURCE"] return _get_azure_response(token_aud, username)["access_token"] elif ENVIRON == "gcp": opts = parse_uri(self.uri_single)["options"] token_aud = opts["authmechanismproperties"]["TOKEN_RESOURCE"] return _get_gcp_response(token_aud, username)["access_token"] @contextmanager def fail_point(self, command_args): cmd_on = SON([("configureFailPoint", "failCommand")]) cmd_on.update(command_args) client = MongoClient(self.uri_admin) client.admin.command(cmd_on) try: yield finally: client.admin.command("configureFailPoint", cmd_on["configureFailPoint"], mode="off") class TestAuthOIDCHuman(OIDCTestBase): uri: str @classmethod def setUpClass(cls): if ENVIRON != "test": raise unittest.SkipTest("Human workflows are only tested with the test environment") if DOMAIN is None: raise ValueError("Missing OIDC_DOMAIN") super().setUpClass() def setUp(self): self.refresh_present = 0 super().setUp() def create_request_cb(self, username="test_user1", sleep=0): def request_token(context: OIDCCallbackContext): # Validate the info. self.assertIsInstance(context.idp_info.issuer, str) if context.idp_info.clientId is not None: self.assertIsInstance(context.idp_info.clientId, str) # Validate the timeout. timeout_seconds = context.timeout_seconds self.assertEqual(timeout_seconds, 60 * 5) if context.refresh_token: self.refresh_present += 1 token = self.get_token(username) resp = OIDCCallbackResult(access_token=token, refresh_token=token) time.sleep(sleep) self.request_called += 1 return resp class Inner(OIDCCallback): def fetch(self, context): return request_token(context) return Inner() def create_client(self, *args, **kwargs): username = kwargs.get("username", "test_user1") if kwargs.get("username") in ["test_user1", "test_user2"]: kwargs["username"] = f"{username}@{DOMAIN}" request_cb = kwargs.pop("request_cb", self.create_request_cb(username=username)) props = kwargs.pop("authmechanismproperties", {"OIDC_HUMAN_CALLBACK": request_cb}) kwargs["retryReads"] = False if not len(args): args = [self.uri_single] return MongoClient(*args, authmechanismproperties=props, **kwargs) def test_1_1_single_principal_implicit_username(self): # Create default OIDC client with authMechanism=MONGODB-OIDC. client = self.create_client() # Perform a find operation that succeeds. client.test.test.find_one() # Close the client. client.close() def test_1_2_single_principal_explicit_username(self): # Create a client with MONGODB_URI_SINGLE, a username of test_user1, authMechanism=MONGODB-OIDC, and the OIDC human callback. client = self.create_client(username="test_user1") # Perform a find operation that succeeds. client.test.test.find_one() # Close the client.. client.close() def test_1_3_multiple_principal_user_1(self): if not self.uri_multiple: raise unittest.SkipTest("Test Requires Server with Multiple Workflow IdPs") # Create a client with MONGODB_URI_MULTI, a username of test_user1, authMechanism=MONGODB-OIDC, and the OIDC human callback. client = self.create_client(self.uri_multiple, username="test_user1") # Perform a find operation that succeeds. client.test.test.find_one() # Close the client. client.close() def test_1_4_multiple_principal_user_2(self): if not self.uri_multiple: raise unittest.SkipTest("Test Requires Server with Multiple Workflow IdPs") # Create a human callback that reads in the generated test_user2 token file. # Create a client with MONGODB_URI_MULTI, a username of test_user2, authMechanism=MONGODB-OIDC, and the OIDC human callback. client = self.create_client(self.uri_multiple, username="test_user2") # Perform a find operation that succeeds. client.test.test.find_one() # Close the client. client.close() def test_1_5_multiple_principal_no_user(self): if not self.uri_multiple: raise unittest.SkipTest("Test Requires Server with Multiple Workflow IdPs") # Create a client with MONGODB_URI_MULTI, no username, authMechanism=MONGODB-OIDC, and the OIDC human callback. client = self.create_client(self.uri_multiple) # Assert that a find operation fails. with self.assertRaises(OperationFailure): client.test.test.find_one() # Close the client. client.close() def test_1_6_allowed_hosts_blocked(self): # Create a default OIDC client, with an ALLOWED_HOSTS that is an empty list. request_token = self.create_request_cb() props: Dict = {"OIDC_HUMAN_CALLBACK": request_token, "ALLOWED_HOSTS": []} client = self.create_client(authmechanismproperties=props) # Assert that a find operation fails with a client-side error. with self.assertRaises(ConfigurationError): client.test.test.find_one() # Close the client. client.close() # Create a client that uses the URL mongodb://localhost/?authMechanism=MONGODB-OIDC&ignored=example.com, # a human callback, and an ALLOWED_HOSTS that contains ["example.com"]. props: Dict = { "OIDC_HUMAN_CALLBACK": request_token, "ALLOWED_HOSTS": ["example.com"], } with warnings.catch_warnings(): warnings.simplefilter("default") client = self.create_client( self.uri_single + "&ignored=example.com", authmechanismproperties=props, connect=False, ) # Assert that a find operation fails with a client-side error. with self.assertRaises(ConfigurationError): client.test.test.find_one() # Close the client. client.close() def test_1_7_allowed_hosts_in_connection_string_ignored(self): # Create an OIDC configured client with the connection string: `mongodb+srv://example.com/?authMechanism=MONGODB-OIDC&authMechanismProperties=ALLOWED_HOSTS:%5B%22example.com%22%5D` and a Human Callback. # Assert that the creation of the client raises a configuration error. uri = "mongodb+srv://example.com?authMechanism=MONGODB-OIDC&authMechanismProperties=ALLOWED_HOSTS:%5B%22example.com%22%5D" with self.assertRaises(ConfigurationError), warnings.catch_warnings(): warnings.simplefilter("ignore") _ = MongoClient( uri, authmechanismproperties=dict(OIDC_HUMAN_CALLBACK=self.create_request_cb()) ) def test_1_8_machine_idp_human_callback(self): if not os.environ.get("OIDC_IS_LOCAL"): raise unittest.SkipTest("Test Requires Local OIDC server") # Create a client with MONGODB_URI_SINGLE, a username of test_machine, authMechanism=MONGODB-OIDC, and the OIDC human callback. client = self.create_client(username="test_machine") # Perform a find operation that succeeds. client.test.test.find_one() # Close the client. client.close() def test_2_1_valid_callback_inputs(self): # Create a MongoClient with a human callback that validates its inputs and returns a valid access token. client = self.create_client() # Perform a find operation that succeeds. Verify that the human callback was called with the appropriate inputs, including the timeout parameter if possible. # Ensure that there are no unexpected fields. client.test.test.find_one() # Close the client. client.close() def test_2_2_callback_returns_missing_data(self): # Create a MongoClient with a human callback that returns data not conforming to the OIDCCredential with missing fields. class CustomCB(OIDCCallback): def fetch(self, ctx): return dict() client = self.create_client(request_cb=CustomCB()) # Perform a find operation that fails. with self.assertRaises(ValueError): client.test.test.find_one() # Close the client. client.close() def test_2_3_refresh_token_is_passed_to_the_callback(self): # Create a MongoClient with a human callback that checks for the presence of a refresh token. client = self.create_client() # Perform a find operation that succeeds. client.test.test.find_one() # Set a fail point for ``find`` commands. with self.fail_point( { "mode": {"times": 1}, "data": {"failCommands": ["find"], "errorCode": 391}, } ): # Perform a ``find`` operation that succeeds. client.test.test.find_one() # Assert that the callback has been called twice. self.assertEqual(self.request_called, 2) # Assert that the refresh token was used once. self.assertEqual(self.refresh_present, 1) def test_3_1_uses_speculative_authentication_if_there_is_a_cached_token(self): # Create a client with a human callback that returns a valid token. client = self.create_client() # Set a fail point for ``find`` commands. with self.fail_point( { "mode": {"times": 1}, "data": {"failCommands": ["find"], "errorCode": 391, "closeConnection": True}, } ): # Perform a ``find`` operation that fails. with self.assertRaises(AutoReconnect): client.test.test.find_one() # Set a fail point for ``saslStart`` commands. with self.fail_point( { "mode": {"times": 1}, "data": {"failCommands": ["saslStart"], "errorCode": 18}, } ): # Perform a ``find`` operation that succeeds client.test.test.find_one() # Close the client. client.close() def test_3_2_does_not_use_speculative_authentication_if_there_is_no_cached_token(self): # Create a ``MongoClient`` with a human callback that returns a valid token client = self.create_client() # Set a fail point for ``saslStart`` commands. with self.fail_point( { "mode": {"times": 1}, "data": {"failCommands": ["saslStart"], "errorCode": 18}, } ): # Perform a ``find`` operation that fails. with self.assertRaises(OperationFailure): client.test.test.find_one() # Close the client. client.close() def test_4_1_reauthenticate_succeeds(self): # Create a default OIDC client and add an event listener. # The following assumes that the driver does not emit saslStart or saslContinue events. # If the driver does emit those events, ignore/filter them for the purposes of this test. listener = EventListener() client = self.create_client(event_listeners=[listener]) # Perform a find operation that succeeds. client.test.test.find_one() # Assert that the human callback has been called once. self.assertEqual(self.request_called, 1) # Clear the listener state if possible. listener.reset() # Force a reauthenication using a fail point. with self.fail_point( { "mode": {"times": 1}, "data": {"failCommands": ["find"], "errorCode": 391}, } ): # Perform another find operation that succeeds. client.test.test.find_one() # Assert that the human callback has been called twice. self.assertEqual(self.request_called, 2) # Assert that the ordering of list started events is [find, find]. # Note that if the listener stat could not be cleared then there will be an extra find command. started_events = [ i.command_name for i in listener.started_events if not i.command_name.startswith("sasl") ] succeeded_events = [ i.command_name for i in listener.succeeded_events if not i.command_name.startswith("sasl") ] failed_events = [ i.command_name for i in listener.failed_events if not i.command_name.startswith("sasl") ] self.assertEqual( started_events, [ "find", "find", ], ) # Assert that the list of command succeeded events is [find]. self.assertEqual(succeeded_events, ["find"]) # Assert that a find operation failed once during the command execution. self.assertEqual(failed_events, ["find"]) # Close the client. client.close() def test_4_2_reauthenticate_succeeds_no_refresh(self): # Create a default OIDC client with a human callback that does not return a refresh token. cb = self.create_request_cb() class CustomRequest(OIDCCallback): def fetch(self, *args, **kwargs): result = cb.fetch(*args, **kwargs) result.refresh_token = None return result client = self.create_client(request_cb=CustomRequest()) # Perform a find operation that succeeds. client.test.test.find_one() # Assert that the human callback has been called once. self.assertEqual(self.request_called, 1) # Force a reauthenication using a fail point. with self.fail_point( { "mode": {"times": 1}, "data": {"failCommands": ["find"], "errorCode": 391}, } ): # Perform a find operation that succeeds. client.test.test.find_one() # Assert that the human callback has been called twice. self.assertEqual(self.request_called, 2) # Close the client. client.close() def test_4_3_reauthenticate_succeeds_after_refresh_fails(self): # Create a default OIDC client with a human callback that returns an invalid refresh token cb = self.create_request_cb() class CustomRequest(OIDCCallback): def fetch(self, *args, **kwargs): result = cb.fetch(*args, **kwargs) result.refresh_token = "bad" return result client = self.create_client(request_cb=CustomRequest()) # Perform a find operation that succeeds. client.test.test.find_one() # Assert that the human callback has been called once. self.assertEqual(self.request_called, 1) # Force a reauthenication using a fail point. with self.fail_point( { "mode": {"times": 1}, "data": {"failCommands": ["find"], "errorCode": 391}, } ): # Perform a find operation that succeeds. client.test.test.find_one() # Assert that the human callback has been called 2 times. self.assertEqual(self.request_called, 2) # Close the client. client.close() def test_4_4_reauthenticate_fails(self): # Create a default OIDC client with a human callback that returns invalid refresh tokens and # Returns invalid access tokens after the first access. cb = self.create_request_cb() class CustomRequest(OIDCCallback): fetch_called = 0 def fetch(self, *args, **kwargs): self.fetch_called += 1 result = cb.fetch(*args, **kwargs) result.refresh_token = "bad" if self.fetch_called > 1: result.access_token = "bad" return result client = self.create_client(request_cb=CustomRequest()) # Perform a find operation that succeeds (to force a speculative auth). client.test.test.find_one() # Assert that the human callback has been called once. self.assertEqual(self.request_called, 1) # Force a reauthentication using a failCommand. with self.fail_point( { "mode": {"times": 1}, "data": {"failCommands": ["find"], "errorCode": 391}, } ): # Perform a find operation that fails. with self.assertRaises(OperationFailure): client.test.test.find_one() # Assert that the human callback has been called three times. self.assertEqual(self.request_called, 3) # Close the client. client.close() def test_request_callback_returns_null(self): class RequestTokenNull(OIDCCallback): def fetch(self, a): return None client = self.create_client(request_cb=RequestTokenNull()) with self.assertRaises(ValueError): client.test.test.find_one() client.close() def test_request_callback_invalid_result(self): class CallbackInvalidToken(OIDCCallback): def fetch(self, a): return {} client = self.create_client(request_cb=CallbackInvalidToken()) with self.assertRaises(ValueError): client.test.test.find_one() client.close() def test_reauthentication_succeeds_multiple_connections(self): request_cb = self.create_request_cb() # Create a client with the callback. client1 = self.create_client(request_cb=request_cb) client2 = self.create_client(request_cb=request_cb) # Perform an insert operation. client1.test.test.insert_many([{"a": 1}, {"a": 1}]) client2.test.test.find_one() self.assertEqual(self.request_called, 2) # Use the same authenticator for both clients # to simulate a race condition with separate connections. # We should only see one extra callback despite both connections # needing to reauthenticate. client2.options.pool_options._credentials.cache.data = ( client1.options.pool_options._credentials.cache.data ) client1.test.test.find_one() client2.test.test.find_one() with self.fail_point( { "mode": {"times": 1}, "data": {"failCommands": ["find"], "errorCode": 391}, } ): client1.test.test.find_one() self.assertEqual(self.request_called, 3) with self.fail_point( { "mode": {"times": 1}, "data": {"failCommands": ["find"], "errorCode": 391}, } ): client2.test.test.find_one() self.assertEqual(self.request_called, 3) client1.close() client2.close() # PyMongo specific tests, since we have multiple code paths for reauth handling. def test_reauthenticate_succeeds_bulk_write(self): # Create a client. client = self.create_client() # Perform a find operation. client.test.test.find_one() # Assert that the request callback has been called once. self.assertEqual(self.request_called, 1) with self.fail_point( { "mode": {"times": 1}, "data": {"failCommands": ["insert"], "errorCode": 391}, } ): # Perform a bulk write operation. client.test.test.bulk_write([InsertOne({})]) # type:ignore[type-var] # Assert that the request callback has been called twice. self.assertEqual(self.request_called, 2) client.close() def test_reauthenticate_succeeds_bulk_read(self): # Create a client. client = self.create_client() # Perform a find operation. client.test.test.find_one() # Perform a bulk write operation. client.test.test.bulk_write([InsertOne({})]) # type:ignore[type-var] # Assert that the request callback has been called once. self.assertEqual(self.request_called, 1) with self.fail_point( { "mode": {"times": 1}, "data": {"failCommands": ["find"], "errorCode": 391}, } ): # Perform a bulk read operation. cursor = client.test.test.find_raw_batches({}) list(cursor) # Assert that the request callback has been called twice. self.assertEqual(self.request_called, 2) client.close() def test_reauthenticate_succeeds_cursor(self): # Create a client. client = self.create_client() # Perform an insert operation. client.test.test.insert_one({"a": 1}) # Assert that the request callback has been called once. self.assertEqual(self.request_called, 1) with self.fail_point( { "mode": {"times": 1}, "data": {"failCommands": ["find"], "errorCode": 391}, } ): # Perform a find operation. cursor = client.test.test.find({"a": 1}) self.assertGreaterEqual(len(list(cursor)), 1) # Assert that the request callback has been called twice. self.assertEqual(self.request_called, 2) client.close() def test_reauthenticate_succeeds_get_more(self): # Create a client. client = self.create_client() # Perform an insert operation. client.test.test.insert_many([{"a": 1}, {"a": 1}]) # Assert that the request callback has been called once. self.assertEqual(self.request_called, 1) with self.fail_point( { "mode": {"times": 1}, "data": {"failCommands": ["getMore"], "errorCode": 391}, } ): # Perform a find operation. cursor = client.test.test.find({"a": 1}, batch_size=1) self.assertGreaterEqual(len(list(cursor)), 1) # Assert that the request callback has been called twice. self.assertEqual(self.request_called, 2) client.close() def test_reauthenticate_succeeds_get_more_exhaust(self): # Ensure no mongos client = self.create_client() hello = client.admin.command(HelloCompat.LEGACY_CMD) if hello.get("msg") != "isdbgrid": raise unittest.SkipTest("Must not be a mongos") # Create a client with the callback. client = self.create_client() # Perform an insert operation. client.test.test.insert_many([{"a": 1}, {"a": 1}]) # Assert that the request callback has been called once. self.assertEqual(self.request_called, 1) with self.fail_point( { "mode": {"times": 1}, "data": {"failCommands": ["getMore"], "errorCode": 391}, } ): # Perform a find operation. cursor = client.test.test.find({"a": 1}, batch_size=1, cursor_type=CursorType.EXHAUST) self.assertGreaterEqual(len(list(cursor)), 1) # Assert that the request callback has been called twice. self.assertEqual(self.request_called, 2) client.close() def test_reauthenticate_succeeds_command(self): # Create a client. client = self.create_client() # Perform an insert operation. client.test.test.insert_one({"a": 1}) # Assert that the request callback has been called once. self.assertEqual(self.request_called, 1) with self.fail_point( { "mode": {"times": 1}, "data": {"failCommands": ["count"], "errorCode": 391}, } ): # Perform a count operation. cursor = client.test.command({"count": "test"}) self.assertGreaterEqual(len(list(cursor)), 1) # Assert that the request callback has been called twice. self.assertEqual(self.request_called, 2) client.close() class TestAuthOIDCMachine(OIDCTestBase): uri: str def setUp(self): self.request_called = 0 def create_request_cb(self, username=None, sleep=0): def request_token(context): assert isinstance(context.timeout_seconds, int) assert context.version == 1 assert context.refresh_token is None assert context.idp_info is None token = self.get_token(username) time.sleep(sleep) self.request_called += 1 return OIDCCallbackResult(access_token=token) class Inner(OIDCCallback): def fetch(self, context): return request_token(context) return Inner() def create_client(self, *args, **kwargs): request_cb = kwargs.pop("request_cb", self.create_request_cb()) props = kwargs.pop("authmechanismproperties", {"OIDC_CALLBACK": request_cb}) kwargs["retryReads"] = False if not len(args): args = [self.uri_single] return MongoClient(*args, authmechanismproperties=props, **kwargs) def test_1_1_callback_is_called_during_reauthentication(self): # Create a ``MongoClient`` configured with a custom OIDC callback that # implements the provider logic. client = self.create_client() # Perform a ``find`` operation that succeeds. client.test.test.find_one() # Assert that the callback was called 1 time. self.assertEqual(self.request_called, 1) # Close the client. client.close() def test_1_2_callback_is_called_once_for_multiple_connections(self): # Create a ``MongoClient`` configured with a custom OIDC callback that # implements the provider logic. client = self.create_client() # Start 10 threads and run 100 find operations in each thread that all succeed. def target(): for _ in range(100): client.test.test.find_one() threads = [] for _ in range(10): thread = threading.Thread(target=target) thread.start() threads.append(thread) for thread in threads: thread.join() # Assert that the callback was called 1 time. self.assertEqual(self.request_called, 1) # Close the client. client.close() def test_2_1_valid_callback_inputs(self): # Create a MongoClient configured with an OIDC callback that validates its inputs and returns a valid access token. client = self.create_client() # Perform a find operation that succeeds. client.test.test.find_one() # Assert that the OIDC callback was called with the appropriate inputs, including the timeout parameter if possible. Ensure that there are no unexpected fields. self.assertEqual(self.request_called, 1) # Close the client. client.close() def test_2_2_oidc_callback_returns_null(self): # Create a MongoClient configured with an OIDC callback that returns null. class CallbackNullToken(OIDCCallback): def fetch(self, a): return None client = self.create_client(request_cb=CallbackNullToken()) # Perform a find operation that fails. with self.assertRaises(ValueError): client.test.test.find_one() # Close the client. client.close() def test_2_3_oidc_callback_returns_missing_data(self): # Create a MongoClient configured with an OIDC callback that returns data not conforming to the OIDCCredential with missing fields. class CustomCallback(OIDCCallback): count = 0 def fetch(self, a): self.count += 1 return object() client = self.create_client(request_cb=CustomCallback()) # Perform a find operation that fails. with self.assertRaises(ValueError): client.test.test.find_one() # Close the client. client.close() def test_2_4_oidc_callback_returns_invalid_data(self): # Create a MongoClient configured with an OIDC callback that returns data not conforming to the OIDCCredential with extra fields. class CustomCallback(OIDCCallback): count = 0 def fetch(self, a): self.count += 1 return OIDCCallbackResult(access_token="bad value") client = self.create_client(request_cb=CustomCallback()) # Perform a ``find`` operation that fails. with self.assertRaises(OperationFailure): client.test.test.find_one() # Close the client. client.close() def test_2_5_invalid_client_configuration_with_callback(self): # Create a MongoClient configured with an OIDC callback and auth mechanism property ENVIRONMENT:test. request_cb = self.create_request_cb() props: Dict = {"OIDC_CALLBACK": request_cb, "ENVIRONMENT": "test"} # Assert it returns a client configuration error. with self.assertRaises(ConfigurationError): self.create_client(authmechanismproperties=props) def test_3_1_authentication_failure_with_cached_tokens_fetch_a_new_token_and_retry(self): # Create a MongoClient and an OIDC callback that implements the provider logic. client = self.create_client() # Poison the cache with an invalid access token. # Set a fail point for ``find`` command. with self.fail_point( { "mode": {"times": 1}, "data": {"failCommands": ["find"], "errorCode": 391, "closeConnection": True}, } ): # Perform a ``find`` operation that fails. This is to force the ``MongoClient`` # to cache an access token. with self.assertRaises(AutoReconnect): client.test.test.find_one() # Poison the cache of the client. client.options.pool_options._credentials.cache.data.access_token = "bad" # Reset the request count. self.request_called = 0 # Verify that a find succeeds. client.test.test.find_one() # Verify that the callback was called 1 time. self.assertEqual(self.request_called, 1) # Close the client. client.close() def test_3_2_authentication_failures_without_cached_tokens_returns_an_error(self): # Create a MongoClient configured with retryReads=false and an OIDC callback that always returns invalid access tokens. class CustomCallback(OIDCCallback): count = 0 def fetch(self, a): self.count += 1 return OIDCCallbackResult(access_token="bad value") callback = CustomCallback() client = self.create_client(request_cb=callback) # Perform a ``find`` operation that fails. with self.assertRaises(OperationFailure): client.test.test.find_one() # Verify that the callback was called 1 time. self.assertEqual(callback.count, 1) # Close the client. client.close() def test_3_3_unexpected_error_code_does_not_clear_cache(self): # Create a ``MongoClient`` with a human callback that returns a valid token client = self.create_client() # Set a fail point for ``saslStart`` commands. with self.fail_point( { "mode": {"times": 1}, "data": {"failCommands": ["saslStart"], "errorCode": 20}, } ): # Perform a ``find`` operation that fails. with self.assertRaises(OperationFailure): client.test.test.find_one() # Assert that the callback has been called once. self.assertEqual(self.request_called, 1) # Perform a ``find`` operation that succeeds. client.test.test.find_one() # Assert that the callback has been called once. self.assertEqual(self.request_called, 1) # Close the client. client.close() def test_4_1_reauthentication_succeds(self): # Create a ``MongoClient`` configured with a custom OIDC callback that # implements the provider logic. client = self.create_client() # Set a fail point for the find command. with self.fail_point( { "mode": {"times": 1}, "data": {"failCommands": ["find"], "errorCode": 391}, } ): # Perform a ``find`` operation that succeeds. client.test.test.find_one() # Verify that the callback was called 2 times (once during the connection # handshake, and again during reauthentication). self.assertEqual(self.request_called, 2) # Close the client. client.close() def test_4_2_read_commands_fail_if_reauthentication_fails(self): # Create a ``MongoClient`` whose OIDC callback returns one good token and then # bad tokens after the first call. get_token = self.get_token class CustomCallback(OIDCCallback): count = 0 def fetch(self, _): self.count += 1 if self.count == 1: access_token = get_token() else: access_token = "bad value" return OIDCCallbackResult(access_token=access_token) callback = CustomCallback() client = self.create_client(request_cb=callback) # Perform a read operation that succeeds. client.test.test.find_one() # Set a fail point for the find command. with self.fail_point( { "mode": {"times": 1}, "data": {"failCommands": ["find"], "errorCode": 391}, } ): # Perform a ``find`` operation that fails. with self.assertRaises(OperationFailure): client.test.test.find_one() # Verify that the callback was called 2 times. self.assertEqual(callback.count, 2) # Close the client. client.close() def test_4_3_write_commands_fail_if_reauthentication_fails(self): # Create a ``MongoClient`` whose OIDC callback returns one good token and then # bad token after the first call. get_token = self.get_token class CustomCallback(OIDCCallback): count = 0 def fetch(self, _): self.count += 1 if self.count == 1: access_token = get_token() else: access_token = "bad value" return OIDCCallbackResult(access_token=access_token) callback = CustomCallback() client = self.create_client(request_cb=callback) # Perform an insert operation that succeeds. client.test.test.insert_one({}) # Set a fail point for the find command. with self.fail_point( { "mode": {"times": 1}, "data": {"failCommands": ["insert"], "errorCode": 391}, } ): # Perform a ``insert`` operation that fails. with self.assertRaises(OperationFailure): client.test.test.insert_one({}) # Verify that the callback was called 2 times. self.assertEqual(callback.count, 2) # Close the client. client.close() def test_5_1_azure_with_no_username(self): if ENVIRON != "azure": raise unittest.SkipTest("Test is only supported on Azure") opts = parse_uri(self.uri_single)["options"] resource = opts["authmechanismproperties"]["TOKEN_RESOURCE"] props = dict(TOKEN_RESOURCE=resource, ENVIRONMENT="azure") client = self.create_client(authMechanismProperties=props) client.test.test.find_one() client.close() def test_5_2_azure_with_bad_username(self): if ENVIRON != "azure": raise unittest.SkipTest("Test is only supported on Azure") opts = parse_uri(self.uri_single)["options"] token_aud = opts["authmechanismproperties"]["TOKEN_RESOURCE"] props = dict(TOKEN_RESOURCE=token_aud, ENVIRONMENT="azure") client = self.create_client(username="bad", authmechanismproperties=props) with self.assertRaises(ValueError): client.test.test.find_one() client.close() def test_speculative_auth_success(self): client1 = self.create_client() client1.test.test.find_one() client2 = self.create_client() # Prime the cache of the second client. client2.options.pool_options._credentials.cache.data = ( client1.options.pool_options._credentials.cache.data ) # Set a fail point for saslStart commands. with self.fail_point( { "mode": {"times": 2}, "data": {"failCommands": ["saslStart"], "errorCode": 18}, } ): # Perform a find operation. client2.test.test.find_one() # Close the clients. client2.close() client1.close() def test_reauthentication_succeeds_multiple_connections(self): client1 = self.create_client() client2 = self.create_client() # Perform an insert operation. client1.test.test.insert_many([{"a": 1}, {"a": 1}]) client2.test.test.find_one() self.assertEqual(self.request_called, 2) # Use the same authenticator for both clients # to simulate a race condition with separate connections. # We should only see one extra callback despite both connections # needing to reauthenticate. client2.options.pool_options._credentials.cache.data = ( client1.options.pool_options._credentials.cache.data ) client1.test.test.find_one() client2.test.test.find_one() with self.fail_point( { "mode": {"times": 1}, "data": {"failCommands": ["find"], "errorCode": 391}, } ): client1.test.test.find_one() self.assertEqual(self.request_called, 3) with self.fail_point( { "mode": {"times": 1}, "data": {"failCommands": ["find"], "errorCode": 391}, } ): client2.test.test.find_one() self.assertEqual(self.request_called, 3) client1.close() client2.close() if __name__ == "__main__": unittest.main() mongodb-mongo-python-driver-509e9b7/test/bson_corpus/000077500000000000000000000000001462766011000227505ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/bson_corpus/array.json000066400000000000000000000037461462766011000247730ustar00rootroot00000000000000{ "description": "Array", "bson_type": "0x04", "test_key": "a", "valid": [ { "description": "Empty", "canonical_bson": "0D000000046100050000000000", "canonical_extjson": "{\"a\" : []}" }, { "description": "Single Element Array", "canonical_bson": "140000000461000C0000001030000A0000000000", "canonical_extjson": "{\"a\" : [{\"$numberInt\": \"10\"}]}" }, { "description": "Single Element Array with index set incorrectly to empty string", "degenerate_bson": "130000000461000B00000010000A0000000000", "canonical_bson": "140000000461000C0000001030000A0000000000", "canonical_extjson": "{\"a\" : [{\"$numberInt\": \"10\"}]}" }, { "description": "Single Element Array with index set incorrectly to ab", "degenerate_bson": "150000000461000D000000106162000A0000000000", "canonical_bson": "140000000461000C0000001030000A0000000000", "canonical_extjson": "{\"a\" : [{\"$numberInt\": \"10\"}]}" }, { "description": "Multi Element Array with duplicate indexes", "degenerate_bson": "1b000000046100130000001030000a000000103000140000000000", "canonical_bson": "1b000000046100130000001030000a000000103100140000000000", "canonical_extjson": "{\"a\" : [{\"$numberInt\": \"10\"}, {\"$numberInt\": \"20\"}]}" } ], "decodeErrors": [ { "description": "Array length too long: eats outer terminator", "bson": "140000000461000D0000001030000A0000000000" }, { "description": "Array length too short: leaks terminator", "bson": "140000000461000B0000001030000A0000000000" }, { "description": "Invalid Array: bad string length in field", "bson": "1A00000004666F6F00100000000230000500000062617A000000" } ] } mongodb-mongo-python-driver-509e9b7/test/bson_corpus/binary.json000066400000000000000000000130751462766011000251350ustar00rootroot00000000000000{ "description": "Binary type", "bson_type": "0x05", "test_key": "x", "valid": [ { "description": "subtype 0x00 (Zero-length)", "canonical_bson": "0D000000057800000000000000", "canonical_extjson": "{\"x\" : { \"$binary\" : {\"base64\" : \"\", \"subType\" : \"00\"}}}" }, { "description": "subtype 0x00 (Zero-length, keys reversed)", "canonical_bson": "0D000000057800000000000000", "canonical_extjson": "{\"x\" : { \"$binary\" : {\"base64\" : \"\", \"subType\" : \"00\"}}}", "degenerate_extjson": "{\"x\" : { \"$binary\" : {\"subType\" : \"00\", \"base64\" : \"\"}}}" }, { "description": "subtype 0x00", "canonical_bson": "0F0000000578000200000000FFFF00", "canonical_extjson": "{\"x\" : { \"$binary\" : {\"base64\" : \"//8=\", \"subType\" : \"00\"}}}" }, { "description": "subtype 0x01", "canonical_bson": "0F0000000578000200000001FFFF00", "canonical_extjson": "{\"x\" : { \"$binary\" : {\"base64\" : \"//8=\", \"subType\" : \"01\"}}}" }, { "description": "subtype 0x02", "canonical_bson": "13000000057800060000000202000000FFFF00", "canonical_extjson": "{\"x\" : { \"$binary\" : {\"base64\" : \"//8=\", \"subType\" : \"02\"}}}" }, { "description": "subtype 0x03", "canonical_bson": "1D000000057800100000000373FFD26444B34C6990E8E7D1DFC035D400", "canonical_extjson": "{\"x\" : { \"$binary\" : {\"base64\" : \"c//SZESzTGmQ6OfR38A11A==\", \"subType\" : \"03\"}}}" }, { "description": "subtype 0x04", "canonical_bson": "1D000000057800100000000473FFD26444B34C6990E8E7D1DFC035D400", "canonical_extjson": "{\"x\" : { \"$binary\" : {\"base64\" : \"c//SZESzTGmQ6OfR38A11A==\", \"subType\" : \"04\"}}}" }, { "description": "subtype 0x04 UUID", "canonical_bson": "1D000000057800100000000473FFD26444B34C6990E8E7D1DFC035D400", "canonical_extjson": "{\"x\" : { \"$binary\" : {\"base64\" : \"c//SZESzTGmQ6OfR38A11A==\", \"subType\" : \"04\"}}}", "degenerate_extjson": "{\"x\" : { \"$uuid\" : \"73ffd264-44b3-4c69-90e8-e7d1dfc035d4\"}}" }, { "description": "subtype 0x05", "canonical_bson": "1D000000057800100000000573FFD26444B34C6990E8E7D1DFC035D400", "canonical_extjson": "{\"x\" : { \"$binary\" : {\"base64\" : \"c//SZESzTGmQ6OfR38A11A==\", \"subType\" : \"05\"}}}" }, { "description": "subtype 0x07", "canonical_bson": "1D000000057800100000000773FFD26444B34C6990E8E7D1DFC035D400", "canonical_extjson": "{\"x\" : { \"$binary\" : {\"base64\" : \"c//SZESzTGmQ6OfR38A11A==\", \"subType\" : \"07\"}}}" }, { "description": "subtype 0x08", "canonical_bson": "1D000000057800100000000873FFD26444B34C6990E8E7D1DFC035D400", "canonical_extjson": "{\"x\" : { \"$binary\" : {\"base64\" : \"c//SZESzTGmQ6OfR38A11A==\", \"subType\" : \"08\"}}}" }, { "description": "subtype 0x80", "canonical_bson": "0F0000000578000200000080FFFF00", "canonical_extjson": "{\"x\" : { \"$binary\" : {\"base64\" : \"//8=\", \"subType\" : \"80\"}}}" }, { "description": "$type query operator (conflicts with legacy $binary form with $type field)", "canonical_bson": "1F000000037800170000000224747970650007000000737472696E67000000", "canonical_extjson": "{\"x\" : { \"$type\" : \"string\"}}" }, { "description": "$type query operator (conflicts with legacy $binary form with $type field)", "canonical_bson": "180000000378001000000010247479706500020000000000", "canonical_extjson": "{\"x\" : { \"$type\" : {\"$numberInt\": \"2\"}}}" } ], "decodeErrors": [ { "description": "Length longer than document", "bson": "1D000000057800FF0000000573FFD26444B34C6990E8E7D1DFC035D400" }, { "description": "Negative length", "bson": "0D000000057800FFFFFFFF0000" }, { "description": "subtype 0x02 length too long ", "bson": "13000000057800060000000203000000FFFF00" }, { "description": "subtype 0x02 length too short", "bson": "13000000057800060000000201000000FFFF00" }, { "description": "subtype 0x02 length negative one", "bson": "130000000578000600000002FFFFFFFFFFFF00" } ], "parseErrors": [ { "description": "$uuid wrong type", "string": "{\"x\" : { \"$uuid\" : { \"data\" : \"73ffd264-44b3-4c69-90e8-e7d1dfc035d4\"}}}" }, { "description": "$uuid invalid value--too short", "string": "{\"x\" : { \"$uuid\" : \"73ffd264-44b3-90e8-e7d1dfc035d4\"}}" }, { "description": "$uuid invalid value--too long", "string": "{\"x\" : { \"$uuid\" : \"73ffd264-44b3-4c69-90e8-e7d1dfc035d4-789e4\"}}" }, { "description": "$uuid invalid value--misplaced hyphens", "string": "{\"x\" : { \"$uuid\" : \"73ff-d26444b-34c6-990e8e-7d1dfc035d4\"}}" }, { "description": "$uuid invalid value--too many hyphens", "string": "{\"x\" : { \"$uuid\" : \"----d264-44b3-4--9-90e8-e7d1dfc0----\"}}" } ] } mongodb-mongo-python-driver-509e9b7/test/bson_corpus/boolean.json000066400000000000000000000012551462766011000252650ustar00rootroot00000000000000{ "description": "Boolean", "bson_type": "0x08", "test_key": "b", "valid": [ { "description": "True", "canonical_bson": "090000000862000100", "canonical_extjson": "{\"b\" : true}" }, { "description": "False", "canonical_bson": "090000000862000000", "canonical_extjson": "{\"b\" : false}" } ], "decodeErrors": [ { "description": "Invalid boolean value of 2", "bson": "090000000862000200" }, { "description": "Invalid boolean value of -1", "bson": "09000000086200FF00" } ] } mongodb-mongo-python-driver-509e9b7/test/bson_corpus/code.json000066400000000000000000000046521462766011000245640ustar00rootroot00000000000000{ "description": "Javascript Code", "bson_type": "0x0D", "test_key": "a", "valid": [ { "description": "Empty string", "canonical_bson": "0D0000000D6100010000000000", "canonical_extjson": "{\"a\" : {\"$code\" : \"\"}}" }, { "description": "Single character", "canonical_bson": "0E0000000D610002000000620000", "canonical_extjson": "{\"a\" : {\"$code\" : \"b\"}}" }, { "description": "Multi-character", "canonical_bson": "190000000D61000D0000006162616261626162616261620000", "canonical_extjson": "{\"a\" : {\"$code\" : \"abababababab\"}}" }, { "description": "two-byte UTF-8 (\u00e9)", "canonical_bson": "190000000D61000D000000C3A9C3A9C3A9C3A9C3A9C3A90000", "canonical_extjson": "{\"a\" : {\"$code\" : \"\\u00e9\\u00e9\\u00e9\\u00e9\\u00e9\\u00e9\"}}" }, { "description": "three-byte UTF-8 (\u2606)", "canonical_bson": "190000000D61000D000000E29886E29886E29886E298860000", "canonical_extjson": "{\"a\" : {\"$code\" : \"\\u2606\\u2606\\u2606\\u2606\"}}" }, { "description": "Embedded nulls", "canonical_bson": "190000000D61000D0000006162006261620062616261620000", "canonical_extjson": "{\"a\" : {\"$code\" : \"ab\\u0000bab\\u0000babab\"}}" } ], "decodeErrors": [ { "description": "bad code string length: 0 (but no 0x00 either)", "bson": "0C0000000D61000000000000" }, { "description": "bad code string length: -1", "bson": "0C0000000D6100FFFFFFFF00" }, { "description": "bad code string length: eats terminator", "bson": "100000000D6100050000006200620000" }, { "description": "bad code string length: longer than rest of document", "bson": "120000000D00FFFFFF00666F6F6261720000" }, { "description": "code string is not null-terminated", "bson": "100000000D610004000000616263FF00" }, { "description": "empty code string, but extra null", "bson": "0E0000000D610001000000000000" }, { "description": "invalid UTF-8", "bson": "0E0000000D610002000000E90000" } ] } mongodb-mongo-python-driver-509e9b7/test/bson_corpus/code_w_scope.json000066400000000000000000000067741462766011000263120ustar00rootroot00000000000000{ "description": "Javascript Code with Scope", "bson_type": "0x0F", "test_key": "a", "valid": [ { "description": "Empty code string, empty scope", "canonical_bson": "160000000F61000E0000000100000000050000000000", "canonical_extjson": "{\"a\" : {\"$code\" : \"\", \"$scope\" : {}}}" }, { "description": "Non-empty code string, empty scope", "canonical_bson": "1A0000000F610012000000050000006162636400050000000000", "canonical_extjson": "{\"a\" : {\"$code\" : \"abcd\", \"$scope\" : {}}}" }, { "description": "Empty code string, non-empty scope", "canonical_bson": "1D0000000F61001500000001000000000C000000107800010000000000", "canonical_extjson": "{\"a\" : {\"$code\" : \"\", \"$scope\" : {\"x\" : {\"$numberInt\": \"1\"}}}}" }, { "description": "Non-empty code string and non-empty scope", "canonical_bson": "210000000F6100190000000500000061626364000C000000107800010000000000", "canonical_extjson": "{\"a\" : {\"$code\" : \"abcd\", \"$scope\" : {\"x\" : {\"$numberInt\": \"1\"}}}}" }, { "description": "Unicode and embedded null in code string, empty scope", "canonical_bson": "1A0000000F61001200000005000000C3A9006400050000000000", "canonical_extjson": "{\"a\" : {\"$code\" : \"\\u00e9\\u0000d\", \"$scope\" : {}}}" } ], "decodeErrors": [ { "description": "field length zero", "bson": "280000000F6100000000000500000061626364001300000010780001000000107900010000000000" }, { "description": "field length negative", "bson": "280000000F6100FFFFFFFF0500000061626364001300000010780001000000107900010000000000" }, { "description": "field length too short (less than minimum size)", "bson": "160000000F61000D0000000100000000050000000000" }, { "description": "field length too short (truncates scope)", "bson": "280000000F61001F0000000500000061626364001300000010780001000000107900010000000000" }, { "description": "field length too long (clips outer doc)", "bson": "280000000F6100210000000500000061626364001300000010780001000000107900010000000000" }, { "description": "field length too long (longer than outer doc)", "bson": "280000000F6100FF0000000500000061626364001300000010780001000000107900010000000000" }, { "description": "bad code string: length too short", "bson": "280000000F6100200000000400000061626364001300000010780001000000107900010000000000" }, { "description": "bad code string: length too long (clips scope)", "bson": "280000000F6100200000000600000061626364001300000010780001000000107900010000000000" }, { "description": "bad code string: negative length", "bson": "280000000F610020000000FFFFFFFF61626364001300000010780001000000107900010000000000" }, { "description": "bad code string: length longer than field", "bson": "280000000F610020000000FF00000061626364001300000010780001000000107900010000000000" }, { "description": "bad scope doc (field has bad string length)", "bson": "1C0000000F001500000001000000000C000000020000000000000000" } ] } mongodb-mongo-python-driver-509e9b7/test/bson_corpus/datetime.json000066400000000000000000000032561462766011000254450ustar00rootroot00000000000000{ "description": "DateTime", "bson_type": "0x09", "test_key": "a", "valid": [ { "description": "epoch", "canonical_bson": "10000000096100000000000000000000", "relaxed_extjson": "{\"a\" : {\"$date\" : \"1970-01-01T00:00:00Z\"}}", "canonical_extjson": "{\"a\" : {\"$date\" : {\"$numberLong\" : \"0\"}}}" }, { "description": "positive ms", "canonical_bson": "10000000096100C5D8D6CC3B01000000", "relaxed_extjson": "{\"a\" : {\"$date\" : \"2012-12-24T12:15:30.501Z\"}}", "canonical_extjson": "{\"a\" : {\"$date\" : {\"$numberLong\" : \"1356351330501\"}}}" }, { "description": "negative", "canonical_bson": "10000000096100C33CE7B9BDFFFFFF00", "relaxed_extjson": "{\"a\" : {\"$date\" : {\"$numberLong\" : \"-284643869501\"}}}", "canonical_extjson": "{\"a\" : {\"$date\" : {\"$numberLong\" : \"-284643869501\"}}}" }, { "description" : "Y10K", "canonical_bson" : "1000000009610000DC1FD277E6000000", "canonical_extjson" : "{\"a\":{\"$date\":{\"$numberLong\":\"253402300800000\"}}}" }, { "description": "leading zero ms", "canonical_bson": "10000000096100D1D6D6CC3B01000000", "relaxed_extjson": "{\"a\" : {\"$date\" : \"2012-12-24T12:15:30.001Z\"}}", "canonical_extjson": "{\"a\" : {\"$date\" : {\"$numberLong\" : \"1356351330001\"}}}" } ], "decodeErrors": [ { "description": "datetime field truncated", "bson": "0C0000000961001234567800" } ] } mongodb-mongo-python-driver-509e9b7/test/bson_corpus/dbpointer.json000066400000000000000000000054031462766011000256330ustar00rootroot00000000000000{ "description": "DBPointer type (deprecated)", "bson_type": "0x0C", "deprecated": true, "test_key": "a", "valid": [ { "description": "DBpointer", "canonical_bson": "1A0000000C610002000000620056E1FC72E0C917E9C471416100", "canonical_extjson": "{\"a\": {\"$dbPointer\": {\"$ref\": \"b\", \"$id\": {\"$oid\": \"56e1fc72e0c917e9c4714161\"}}}}", "converted_bson": "2a00000003610022000000022472656600020000006200072469640056e1fc72e0c917e9c47141610000", "converted_extjson": "{\"a\": {\"$ref\": \"b\", \"$id\": {\"$oid\": \"56e1fc72e0c917e9c4714161\"}}}" }, { "description": "DBpointer with opposite key order", "canonical_bson": "1A0000000C610002000000620056E1FC72E0C917E9C471416100", "canonical_extjson": "{\"a\": {\"$dbPointer\": {\"$ref\": \"b\", \"$id\": {\"$oid\": \"56e1fc72e0c917e9c4714161\"}}}}", "degenerate_extjson": "{\"a\": {\"$dbPointer\": {\"$id\": {\"$oid\": \"56e1fc72e0c917e9c4714161\"}, \"$ref\": \"b\"}}}", "converted_bson": "2a00000003610022000000022472656600020000006200072469640056e1fc72e0c917e9c47141610000", "converted_extjson": "{\"a\": {\"$ref\": \"b\", \"$id\": {\"$oid\": \"56e1fc72e0c917e9c4714161\"}}}" }, { "description": "With two-byte UTF-8", "canonical_bson": "1B0000000C610003000000C3A90056E1FC72E0C917E9C471416100", "canonical_extjson": "{\"a\": {\"$dbPointer\": {\"$ref\": \"é\", \"$id\": {\"$oid\": \"56e1fc72e0c917e9c4714161\"}}}}", "converted_bson": "2B0000000361002300000002247265660003000000C3A900072469640056E1FC72E0C917E9C47141610000", "converted_extjson": "{\"a\": {\"$ref\": \"é\", \"$id\": {\"$oid\": \"56e1fc72e0c917e9c4714161\"}}}" } ], "decodeErrors": [ { "description": "String with negative length", "bson": "1A0000000C6100FFFFFFFF620056E1FC72E0C917E9C471416100" }, { "description": "String with zero length", "bson": "1A0000000C610000000000620056E1FC72E0C917E9C471416100" }, { "description": "String not null terminated", "bson": "1A0000000C610002000000626256E1FC72E0C917E9C471416100" }, { "description": "short OID (less than minimum length for field)", "bson": "160000000C61000300000061620056E1FC72E0C91700" }, { "description": "short OID (greater than minimum, but truncated)", "bson": "1A0000000C61000300000061620056E1FC72E0C917E9C4716100" }, { "description": "String with bad UTF-8", "bson": "1A0000000C610002000000E90056E1FC72E0C917E9C471416100" } ] } mongodb-mongo-python-driver-509e9b7/test/bson_corpus/dbref.json000066400000000000000000000067661462766011000247440ustar00rootroot00000000000000{ "description": "Document type (DBRef sub-documents)", "bson_type": "0x03", "valid": [ { "description": "DBRef", "canonical_bson": "37000000036462726566002b0000000224726566000b000000636f6c6c656374696f6e00072469640058921b3e6e32ab156a22b59e0000", "canonical_extjson": "{\"dbref\": {\"$ref\": \"collection\", \"$id\": {\"$oid\": \"58921b3e6e32ab156a22b59e\"}}}" }, { "description": "DBRef with database", "canonical_bson": "4300000003646272656600370000000224726566000b000000636f6c6c656374696f6e00072469640058921b3e6e32ab156a22b59e0224646200030000006462000000", "canonical_extjson": "{\"dbref\": {\"$ref\": \"collection\", \"$id\": {\"$oid\": \"58921b3e6e32ab156a22b59e\"}, \"$db\": \"db\"}}" }, { "description": "DBRef with database and additional fields", "canonical_bson": "48000000036462726566003c0000000224726566000b000000636f6c6c656374696f6e0010246964002a00000002246462000300000064620002666f6f0004000000626172000000", "canonical_extjson": "{\"dbref\": {\"$ref\": \"collection\", \"$id\": {\"$numberInt\": \"42\"}, \"$db\": \"db\", \"foo\": \"bar\"}}" }, { "description": "DBRef with additional fields", "canonical_bson": "4400000003646272656600380000000224726566000b000000636f6c6c656374696f6e00072469640058921b3e6e32ab156a22b59e02666f6f0004000000626172000000", "canonical_extjson": "{\"dbref\": {\"$ref\": \"collection\", \"$id\": {\"$oid\": \"58921b3e6e32ab156a22b59e\"}, \"foo\": \"bar\"}}" }, { "description": "Document with key names similar to those of a DBRef", "canonical_bson": "3e0000000224726566000c0000006e6f742d612d646272656600072469640058921b3e6e32ab156a22b59e022462616e616e6100050000007065656c0000", "canonical_extjson": "{\"$ref\": \"not-a-dbref\", \"$id\": {\"$oid\": \"58921b3e6e32ab156a22b59e\"}, \"$banana\": \"peel\"}" }, { "description": "DBRef with additional dollar-prefixed and dotted fields", "canonical_bson": "48000000036462726566003c0000000224726566000b000000636f6c6c656374696f6e00072469640058921b3e6e32ab156a22b59e10612e62000100000010246300010000000000", "canonical_extjson": "{\"dbref\": {\"$ref\": \"collection\", \"$id\": {\"$oid\": \"58921b3e6e32ab156a22b59e\"}, \"a.b\": {\"$numberInt\": \"1\"}, \"$c\": {\"$numberInt\": \"1\"}}}" }, { "description": "Sub-document resembles DBRef but $id is missing", "canonical_bson": "26000000036462726566001a0000000224726566000b000000636f6c6c656374696f6e000000", "canonical_extjson": "{\"dbref\": {\"$ref\": \"collection\"}}" }, { "description": "Sub-document resembles DBRef but $ref is not a string", "canonical_bson": "2c000000036462726566002000000010247265660001000000072469640058921b3e6e32ab156a22b59e0000", "canonical_extjson": "{\"dbref\": {\"$ref\": {\"$numberInt\": \"1\"}, \"$id\": {\"$oid\": \"58921b3e6e32ab156a22b59e\"}}}" }, { "description": "Sub-document resembles DBRef but $db is not a string", "canonical_bson": "4000000003646272656600340000000224726566000b000000636f6c6c656374696f6e00072469640058921b3e6e32ab156a22b59e1024646200010000000000", "canonical_extjson": "{\"dbref\": {\"$ref\": \"collection\", \"$id\": {\"$oid\": \"58921b3e6e32ab156a22b59e\"}, \"$db\": {\"$numberInt\": \"1\"}}}" } ] } mongodb-mongo-python-driver-509e9b7/test/bson_corpus/decimal128-1.json000066400000000000000000000431051462766011000256350ustar00rootroot00000000000000{ "description": "Decimal128", "bson_type": "0x13", "test_key": "d", "valid": [ { "description": "Special - Canonical NaN", "canonical_bson": "180000001364000000000000000000000000000000007C00", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"NaN\"}}" }, { "description": "Special - Negative NaN", "canonical_bson": "18000000136400000000000000000000000000000000FC00", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"NaN\"}}", "lossy": true }, { "description": "Special - Negative NaN", "canonical_bson": "18000000136400000000000000000000000000000000FC00", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"NaN\"}}", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"-NaN\"}}", "lossy": true }, { "description": "Special - Canonical SNaN", "canonical_bson": "180000001364000000000000000000000000000000007E00", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"NaN\"}}", "lossy": true }, { "description": "Special - Negative SNaN", "canonical_bson": "18000000136400000000000000000000000000000000FE00", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"NaN\"}}", "lossy": true }, { "description": "Special - NaN with a payload", "canonical_bson": "180000001364001200000000000000000000000000007E00", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"NaN\"}}", "lossy": true }, { "description": "Special - Canonical Positive Infinity", "canonical_bson": "180000001364000000000000000000000000000000007800", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"Infinity\"}}" }, { "description": "Special - Canonical Negative Infinity", "canonical_bson": "18000000136400000000000000000000000000000000F800", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"-Infinity\"}}" }, { "description": "Special - Invalid representation treated as 0", "canonical_bson": "180000001364000000000000000000000000000000106C00", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"0\"}}", "lossy": true }, { "description": "Special - Invalid representation treated as -0", "canonical_bson": "18000000136400DCBA9876543210DEADBEEF00000010EC00", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"-0\"}}", "lossy": true }, { "description": "Special - Invalid representation treated as 0E3", "canonical_bson": "18000000136400FFFFFFFFFFFFFFFFFFFFFFFFFFFF116C00", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"0E+3\"}}", "lossy": true }, { "description": "Regular - Adjusted Exponent Limit", "canonical_bson": "18000000136400F2AF967ED05C82DE3297FF6FDE3CF22F00", "canonical_extjson": "{\"d\": { \"$numberDecimal\": \"0.000001234567890123456789012345678901234\" }}" }, { "description": "Regular - Smallest", "canonical_bson": "18000000136400D204000000000000000000000000343000", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"0.001234\"}}" }, { "description": "Regular - Smallest with Trailing Zeros", "canonical_bson": "1800000013640040EF5A07000000000000000000002A3000", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"0.00123400000\"}}" }, { "description": "Regular - 0.1", "canonical_bson": "1800000013640001000000000000000000000000003E3000", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"0.1\"}}" }, { "description": "Regular - 0.1234567890123456789012345678901234", "canonical_bson": "18000000136400F2AF967ED05C82DE3297FF6FDE3CFC2F00", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"0.1234567890123456789012345678901234\"}}" }, { "description": "Regular - 0", "canonical_bson": "180000001364000000000000000000000000000000403000", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"0\"}}" }, { "description": "Regular - -0", "canonical_bson": "18000000136400000000000000000000000000000040B000", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"-0\"}}" }, { "description": "Regular - -0.0", "canonical_bson": "1800000013640000000000000000000000000000003EB000", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"-0.0\"}}" }, { "description": "Regular - 2", "canonical_bson": "180000001364000200000000000000000000000000403000", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"2\"}}" }, { "description": "Regular - 2.000", "canonical_bson": "18000000136400D0070000000000000000000000003A3000", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"2.000\"}}" }, { "description": "Regular - Largest", "canonical_bson": "18000000136400F2AF967ED05C82DE3297FF6FDE3C403000", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1234567890123456789012345678901234\"}}" }, { "description": "Scientific - Tiniest", "canonical_bson": "18000000136400FFFFFFFF638E8D37C087ADBE09ED010000", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"9.999999999999999999999999999999999E-6143\"}}" }, { "description": "Scientific - Tiny", "canonical_bson": "180000001364000100000000000000000000000000000000", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1E-6176\"}}" }, { "description": "Scientific - Negative Tiny", "canonical_bson": "180000001364000100000000000000000000000000008000", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"-1E-6176\"}}" }, { "description": "Scientific - Adjusted Exponent Limit", "canonical_bson": "18000000136400F2AF967ED05C82DE3297FF6FDE3CF02F00", "canonical_extjson": "{\"d\": { \"$numberDecimal\": \"1.234567890123456789012345678901234E-7\" }}" }, { "description": "Scientific - Fractional", "canonical_bson": "1800000013640064000000000000000000000000002CB000", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"-1.00E-8\"}}" }, { "description": "Scientific - 0 with Exponent", "canonical_bson": "180000001364000000000000000000000000000000205F00", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"0E+6000\"}}" }, { "description": "Scientific - 0 with Negative Exponent", "canonical_bson": "1800000013640000000000000000000000000000007A2B00", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"0E-611\"}}" }, { "description": "Scientific - No Decimal with Signed Exponent", "canonical_bson": "180000001364000100000000000000000000000000463000", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1E+3\"}}" }, { "description": "Scientific - Trailing Zero", "canonical_bson": "180000001364001A04000000000000000000000000423000", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1.050E+4\"}}" }, { "description": "Scientific - With Decimal", "canonical_bson": "180000001364006900000000000000000000000000423000", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1.05E+3\"}}" }, { "description": "Scientific - Full", "canonical_bson": "18000000136400FFFFFFFFFFFFFFFFFFFFFFFFFFFF403000", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"5192296858534827628530496329220095\"}}" }, { "description": "Scientific - Large", "canonical_bson": "18000000136400000000000A5BC138938D44C64D31FE5F00", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1.000000000000000000000000000000000E+6144\"}}" }, { "description": "Scientific - Largest", "canonical_bson": "18000000136400FFFFFFFF638E8D37C087ADBE09EDFF5F00", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"9.999999999999999999999999999999999E+6144\"}}" }, { "description": "Non-Canonical Parsing - Exponent Normalization", "canonical_bson": "1800000013640064000000000000000000000000002CB000", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"-100E-10\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"-1.00E-8\"}}" }, { "description": "Non-Canonical Parsing - Unsigned Positive Exponent", "canonical_bson": "180000001364000100000000000000000000000000463000", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"1E3\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1E+3\"}}" }, { "description": "Non-Canonical Parsing - Lowercase Exponent Identifier", "canonical_bson": "180000001364000100000000000000000000000000463000", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"1e+3\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1E+3\"}}" }, { "description": "Non-Canonical Parsing - Long Significand with Exponent", "canonical_bson": "1800000013640079D9E0F9763ADA429D0200000000583000", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"12345689012345789012345E+12\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1.2345689012345789012345E+34\"}}" }, { "description": "Non-Canonical Parsing - Positive Sign", "canonical_bson": "18000000136400F2AF967ED05C82DE3297FF6FDE3C403000", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"+1234567890123456789012345678901234\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1234567890123456789012345678901234\"}}" }, { "description": "Non-Canonical Parsing - Long Decimal String", "canonical_bson": "180000001364000100000000000000000000000000722800", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \".000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1E-999\"}}" }, { "description": "Non-Canonical Parsing - nan", "canonical_bson": "180000001364000000000000000000000000000000007C00", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"nan\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"NaN\"}}" }, { "description": "Non-Canonical Parsing - nAn", "canonical_bson": "180000001364000000000000000000000000000000007C00", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"nAn\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"NaN\"}}" }, { "description": "Non-Canonical Parsing - +infinity", "canonical_bson": "180000001364000000000000000000000000000000007800", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"+infinity\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"Infinity\"}}" }, { "description": "Non-Canonical Parsing - infinity", "canonical_bson": "180000001364000000000000000000000000000000007800", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"infinity\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"Infinity\"}}" }, { "description": "Non-Canonical Parsing - infiniTY", "canonical_bson": "180000001364000000000000000000000000000000007800", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"infiniTY\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"Infinity\"}}" }, { "description": "Non-Canonical Parsing - inf", "canonical_bson": "180000001364000000000000000000000000000000007800", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"inf\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"Infinity\"}}" }, { "description": "Non-Canonical Parsing - inF", "canonical_bson": "180000001364000000000000000000000000000000007800", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"inF\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"Infinity\"}}" }, { "description": "Non-Canonical Parsing - -infinity", "canonical_bson": "18000000136400000000000000000000000000000000F800", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"-infinity\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"-Infinity\"}}" }, { "description": "Non-Canonical Parsing - -infiniTy", "canonical_bson": "18000000136400000000000000000000000000000000F800", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"-infiniTy\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"-Infinity\"}}" }, { "description": "Non-Canonical Parsing - -Inf", "canonical_bson": "18000000136400000000000000000000000000000000F800", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"-Infinity\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"-Infinity\"}}" }, { "description": "Non-Canonical Parsing - -inf", "canonical_bson": "18000000136400000000000000000000000000000000F800", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"-inf\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"-Infinity\"}}" }, { "description": "Non-Canonical Parsing - -inF", "canonical_bson": "18000000136400000000000000000000000000000000F800", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"-inF\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"-Infinity\"}}" }, { "description": "Rounded Subnormal number", "canonical_bson": "180000001364000100000000000000000000000000000000", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"10E-6177\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1E-6176\"}}" }, { "description": "Clamped", "canonical_bson": "180000001364000a00000000000000000000000000fe5f00", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"1E6112\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1.0E+6112\"}}" }, { "description": "Exact rounding", "canonical_bson": "18000000136400000000000a5bc138938d44c64d31cc3700", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"1000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1.000000000000000000000000000000000E+999\"}}" } ] } mongodb-mongo-python-driver-509e9b7/test/bson_corpus/decimal128-2.json000066400000000000000000001136001462766011000256340ustar00rootroot00000000000000{ "description": "Decimal128", "bson_type": "0x13", "test_key": "d", "valid": [ { "description": "[decq021] Normality", "canonical_bson": "18000000136400F2AF967ED05C82DE3297FF6FDE3C40B000", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"-1234567890123456789012345678901234\"}}" }, { "description": "[decq823] values around [u]int32 edges (zeros done earlier)", "canonical_bson": "18000000136400010000800000000000000000000040B000", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"-2147483649\"}}" }, { "description": "[decq822] values around [u]int32 edges (zeros done earlier)", "canonical_bson": "18000000136400000000800000000000000000000040B000", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"-2147483648\"}}" }, { "description": "[decq821] values around [u]int32 edges (zeros done earlier)", "canonical_bson": "18000000136400FFFFFF7F0000000000000000000040B000", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"-2147483647\"}}" }, { "description": "[decq820] values around [u]int32 edges (zeros done earlier)", "canonical_bson": "18000000136400FEFFFF7F0000000000000000000040B000", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"-2147483646\"}}" }, { "description": "[decq152] fold-downs (more below)", "canonical_bson": "18000000136400393000000000000000000000000040B000", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"-12345\"}}" }, { "description": "[decq154] fold-downs (more below)", "canonical_bson": "18000000136400D20400000000000000000000000040B000", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"-1234\"}}" }, { "description": "[decq006] derivative canonical plain strings", "canonical_bson": "18000000136400EE0200000000000000000000000040B000", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"-750\"}}" }, { "description": "[decq164] fold-downs (more below)", "canonical_bson": "1800000013640039300000000000000000000000003CB000", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"-123.45\"}}" }, { "description": "[decq156] fold-downs (more below)", "canonical_bson": "180000001364007B0000000000000000000000000040B000", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"-123\"}}" }, { "description": "[decq008] derivative canonical plain strings", "canonical_bson": "18000000136400EE020000000000000000000000003EB000", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"-75.0\"}}" }, { "description": "[decq158] fold-downs (more below)", "canonical_bson": "180000001364000C0000000000000000000000000040B000", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"-12\"}}" }, { "description": "[decq122] Nmax and similar", "canonical_bson": "18000000136400FFFFFFFF638E8D37C087ADBE09EDFFDF00", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"-9.999999999999999999999999999999999E+6144\"}}" }, { "description": "[decq002] (mostly derived from the Strawman 4 document and examples)", "canonical_bson": "18000000136400EE020000000000000000000000003CB000", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"-7.50\"}}" }, { "description": "[decq004] derivative canonical plain strings", "canonical_bson": "18000000136400EE0200000000000000000000000042B000", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"-7.50E+3\"}}" }, { "description": "[decq018] derivative canonical plain strings", "canonical_bson": "18000000136400EE020000000000000000000000002EB000", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"-7.50E-7\"}}" }, { "description": "[decq125] Nmax and similar", "canonical_bson": "18000000136400F2AF967ED05C82DE3297FF6FDE3CFEDF00", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"-1.234567890123456789012345678901234E+6144\"}}" }, { "description": "[decq131] fold-downs (more below)", "canonical_bson": "18000000136400000000807F1BCF85B27059C8A43CFEDF00", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"-1.230000000000000000000000000000000E+6144\"}}" }, { "description": "[decq162] fold-downs (more below)", "canonical_bson": "180000001364007B000000000000000000000000003CB000", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"-1.23\"}}" }, { "description": "[decq176] Nmin and below", "canonical_bson": "18000000136400010000000A5BC138938D44C64D31008000", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"-1.000000000000000000000000000000001E-6143\"}}" }, { "description": "[decq174] Nmin and below", "canonical_bson": "18000000136400000000000A5BC138938D44C64D31008000", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"-1.000000000000000000000000000000000E-6143\"}}" }, { "description": "[decq133] fold-downs (more below)", "canonical_bson": "18000000136400000000000A5BC138938D44C64D31FEDF00", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"-1.000000000000000000000000000000000E+6144\"}}" }, { "description": "[decq160] fold-downs (more below)", "canonical_bson": "18000000136400010000000000000000000000000040B000", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"-1\"}}" }, { "description": "[decq172] Nmin and below", "canonical_bson": "180000001364000100000000000000000000000000428000", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"-1E-6143\"}}" }, { "description": "[decq010] derivative canonical plain strings", "canonical_bson": "18000000136400EE020000000000000000000000003AB000", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"-0.750\"}}" }, { "description": "[decq012] derivative canonical plain strings", "canonical_bson": "18000000136400EE0200000000000000000000000038B000", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"-0.0750\"}}" }, { "description": "[decq014] derivative canonical plain strings", "canonical_bson": "18000000136400EE0200000000000000000000000034B000", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"-0.000750\"}}" }, { "description": "[decq016] derivative canonical plain strings", "canonical_bson": "18000000136400EE0200000000000000000000000030B000", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"-0.00000750\"}}" }, { "description": "[decq404] zeros", "canonical_bson": "180000001364000000000000000000000000000000000000", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"0E-6176\"}}" }, { "description": "[decq424] negative zeros", "canonical_bson": "180000001364000000000000000000000000000000008000", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"-0E-6176\"}}" }, { "description": "[decq407] zeros", "canonical_bson": "1800000013640000000000000000000000000000003C3000", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"0.00\"}}" }, { "description": "[decq427] negative zeros", "canonical_bson": "1800000013640000000000000000000000000000003CB000", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"-0.00\"}}" }, { "description": "[decq409] zeros", "canonical_bson": "180000001364000000000000000000000000000000403000", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"0\"}}" }, { "description": "[decq428] negative zeros", "canonical_bson": "18000000136400000000000000000000000000000040B000", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"-0\"}}" }, { "description": "[decq700] Selected DPD codes", "canonical_bson": "180000001364000000000000000000000000000000403000", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"0\"}}" }, { "description": "[decq406] zeros", "canonical_bson": "1800000013640000000000000000000000000000003C3000", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"0.00\"}}" }, { "description": "[decq426] negative zeros", "canonical_bson": "1800000013640000000000000000000000000000003CB000", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"-0.00\"}}" }, { "description": "[decq410] zeros", "canonical_bson": "180000001364000000000000000000000000000000463000", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"0E+3\"}}" }, { "description": "[decq431] negative zeros", "canonical_bson": "18000000136400000000000000000000000000000046B000", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"-0E+3\"}}" }, { "description": "[decq419] clamped zeros...", "canonical_bson": "180000001364000000000000000000000000000000FE5F00", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"0E+6111\"}}" }, { "description": "[decq432] negative zeros", "canonical_bson": "180000001364000000000000000000000000000000FEDF00", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"-0E+6111\"}}" }, { "description": "[decq405] zeros", "canonical_bson": "180000001364000000000000000000000000000000000000", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"0E-6176\"}}" }, { "description": "[decq425] negative zeros", "canonical_bson": "180000001364000000000000000000000000000000008000", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"-0E-6176\"}}" }, { "description": "[decq508] Specials", "canonical_bson": "180000001364000000000000000000000000000000007800", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"Infinity\"}}" }, { "description": "[decq528] Specials", "canonical_bson": "18000000136400000000000000000000000000000000F800", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"-Infinity\"}}" }, { "description": "[decq541] Specials", "canonical_bson": "180000001364000000000000000000000000000000007C00", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"NaN\"}}" }, { "description": "[decq074] Nmin and below", "canonical_bson": "18000000136400000000000A5BC138938D44C64D31000000", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1.000000000000000000000000000000000E-6143\"}}" }, { "description": "[decq602] fold-down full sequence", "canonical_bson": "18000000136400000000000A5BC138938D44C64D31FE5F00", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1.000000000000000000000000000000000E+6144\"}}" }, { "description": "[decq604] fold-down full sequence", "canonical_bson": "180000001364000000000081EFAC855B416D2DEE04FE5F00", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1.00000000000000000000000000000000E+6143\"}}" }, { "description": "[decq606] fold-down full sequence", "canonical_bson": "1800000013640000000080264B91C02220BE377E00FE5F00", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1.0000000000000000000000000000000E+6142\"}}" }, { "description": "[decq608] fold-down full sequence", "canonical_bson": "1800000013640000000040EAED7446D09C2C9F0C00FE5F00", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1.000000000000000000000000000000E+6141\"}}" }, { "description": "[decq610] fold-down full sequence", "canonical_bson": "18000000136400000000A0CA17726DAE0F1E430100FE5F00", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1.00000000000000000000000000000E+6140\"}}" }, { "description": "[decq612] fold-down full sequence", "canonical_bson": "18000000136400000000106102253E5ECE4F200000FE5F00", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1.0000000000000000000000000000E+6139\"}}" }, { "description": "[decq614] fold-down full sequence", "canonical_bson": "18000000136400000000E83C80D09F3C2E3B030000FE5F00", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1.000000000000000000000000000E+6138\"}}" }, { "description": "[decq616] fold-down full sequence", "canonical_bson": "18000000136400000000E4D20CC8DCD2B752000000FE5F00", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1.00000000000000000000000000E+6137\"}}" }, { "description": "[decq618] fold-down full sequence", "canonical_bson": "180000001364000000004A48011416954508000000FE5F00", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1.0000000000000000000000000E+6136\"}}" }, { "description": "[decq620] fold-down full sequence", "canonical_bson": "18000000136400000000A1EDCCCE1BC2D300000000FE5F00", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1.000000000000000000000000E+6135\"}}" }, { "description": "[decq622] fold-down full sequence", "canonical_bson": "18000000136400000080F64AE1C7022D1500000000FE5F00", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1.00000000000000000000000E+6134\"}}" }, { "description": "[decq624] fold-down full sequence", "canonical_bson": "18000000136400000040B2BAC9E0191E0200000000FE5F00", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1.0000000000000000000000E+6133\"}}" }, { "description": "[decq626] fold-down full sequence", "canonical_bson": "180000001364000000A0DEC5ADC935360000000000FE5F00", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1.000000000000000000000E+6132\"}}" }, { "description": "[decq628] fold-down full sequence", "canonical_bson": "18000000136400000010632D5EC76B050000000000FE5F00", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1.00000000000000000000E+6131\"}}" }, { "description": "[decq630] fold-down full sequence", "canonical_bson": "180000001364000000E8890423C78A000000000000FE5F00", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1.0000000000000000000E+6130\"}}" }, { "description": "[decq632] fold-down full sequence", "canonical_bson": "18000000136400000064A7B3B6E00D000000000000FE5F00", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1.000000000000000000E+6129\"}}" }, { "description": "[decq634] fold-down full sequence", "canonical_bson": "1800000013640000008A5D78456301000000000000FE5F00", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1.00000000000000000E+6128\"}}" }, { "description": "[decq636] fold-down full sequence", "canonical_bson": "180000001364000000C16FF2862300000000000000FE5F00", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1.0000000000000000E+6127\"}}" }, { "description": "[decq638] fold-down full sequence", "canonical_bson": "180000001364000080C6A47E8D0300000000000000FE5F00", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1.000000000000000E+6126\"}}" }, { "description": "[decq640] fold-down full sequence", "canonical_bson": "1800000013640000407A10F35A0000000000000000FE5F00", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1.00000000000000E+6125\"}}" }, { "description": "[decq642] fold-down full sequence", "canonical_bson": "1800000013640000A0724E18090000000000000000FE5F00", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1.0000000000000E+6124\"}}" }, { "description": "[decq644] fold-down full sequence", "canonical_bson": "180000001364000010A5D4E8000000000000000000FE5F00", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1.000000000000E+6123\"}}" }, { "description": "[decq646] fold-down full sequence", "canonical_bson": "1800000013640000E8764817000000000000000000FE5F00", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1.00000000000E+6122\"}}" }, { "description": "[decq648] fold-down full sequence", "canonical_bson": "1800000013640000E40B5402000000000000000000FE5F00", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1.0000000000E+6121\"}}" }, { "description": "[decq650] fold-down full sequence", "canonical_bson": "1800000013640000CA9A3B00000000000000000000FE5F00", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1.000000000E+6120\"}}" }, { "description": "[decq652] fold-down full sequence", "canonical_bson": "1800000013640000E1F50500000000000000000000FE5F00", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1.00000000E+6119\"}}" }, { "description": "[decq654] fold-down full sequence", "canonical_bson": "180000001364008096980000000000000000000000FE5F00", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1.0000000E+6118\"}}" }, { "description": "[decq656] fold-down full sequence", "canonical_bson": "1800000013640040420F0000000000000000000000FE5F00", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1.000000E+6117\"}}" }, { "description": "[decq658] fold-down full sequence", "canonical_bson": "18000000136400A086010000000000000000000000FE5F00", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1.00000E+6116\"}}" }, { "description": "[decq660] fold-down full sequence", "canonical_bson": "180000001364001027000000000000000000000000FE5F00", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1.0000E+6115\"}}" }, { "description": "[decq662] fold-down full sequence", "canonical_bson": "18000000136400E803000000000000000000000000FE5F00", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1.000E+6114\"}}" }, { "description": "[decq664] fold-down full sequence", "canonical_bson": "180000001364006400000000000000000000000000FE5F00", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1.00E+6113\"}}" }, { "description": "[decq666] fold-down full sequence", "canonical_bson": "180000001364000A00000000000000000000000000FE5F00", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1.0E+6112\"}}" }, { "description": "[decq060] fold-downs (more below)", "canonical_bson": "180000001364000100000000000000000000000000403000", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1\"}}" }, { "description": "[decq670] fold-down full sequence", "canonical_bson": "180000001364000100000000000000000000000000FC5F00", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1E+6110\"}}" }, { "description": "[decq668] fold-down full sequence", "canonical_bson": "180000001364000100000000000000000000000000FE5F00", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1E+6111\"}}" }, { "description": "[decq072] Nmin and below", "canonical_bson": "180000001364000100000000000000000000000000420000", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1E-6143\"}}" }, { "description": "[decq076] Nmin and below", "canonical_bson": "18000000136400010000000A5BC138938D44C64D31000000", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1.000000000000000000000000000000001E-6143\"}}" }, { "description": "[decq036] fold-downs (more below)", "canonical_bson": "18000000136400000000807F1BCF85B27059C8A43CFE5F00", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1.230000000000000000000000000000000E+6144\"}}" }, { "description": "[decq062] fold-downs (more below)", "canonical_bson": "180000001364007B000000000000000000000000003C3000", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1.23\"}}" }, { "description": "[decq034] Nmax and similar", "canonical_bson": "18000000136400F2AF967ED05C82DE3297FF6FDE3CFE5F00", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1.234567890123456789012345678901234E+6144\"}}" }, { "description": "[decq441] exponent lengths", "canonical_bson": "180000001364000700000000000000000000000000403000", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"7\"}}" }, { "description": "[decq449] exponent lengths", "canonical_bson": "1800000013640007000000000000000000000000001E5F00", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"7E+5999\"}}" }, { "description": "[decq447] exponent lengths", "canonical_bson": "1800000013640007000000000000000000000000000E3800", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"7E+999\"}}" }, { "description": "[decq445] exponent lengths", "canonical_bson": "180000001364000700000000000000000000000000063100", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"7E+99\"}}" }, { "description": "[decq443] exponent lengths", "canonical_bson": "180000001364000700000000000000000000000000523000", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"7E+9\"}}" }, { "description": "[decq842] VG testcase", "canonical_bson": "180000001364000000FED83F4E7C9FE4E269E38A5BCD1700", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"7.049000000000010795488000000000000E-3097\"}}" }, { "description": "[decq841] VG testcase", "canonical_bson": "180000001364000000203B9DB5056F000000000000002400", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"8.000000000000000000E-1550\"}}" }, { "description": "[decq840] VG testcase", "canonical_bson": "180000001364003C17258419D710C42F0000000000002400", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"8.81125000000001349436E-1548\"}}" }, { "description": "[decq701] Selected DPD codes", "canonical_bson": "180000001364000900000000000000000000000000403000", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"9\"}}" }, { "description": "[decq032] Nmax and similar", "canonical_bson": "18000000136400FFFFFFFF638E8D37C087ADBE09EDFF5F00", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"9.999999999999999999999999999999999E+6144\"}}" }, { "description": "[decq702] Selected DPD codes", "canonical_bson": "180000001364000A00000000000000000000000000403000", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"10\"}}" }, { "description": "[decq057] fold-downs (more below)", "canonical_bson": "180000001364000C00000000000000000000000000403000", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"12\"}}" }, { "description": "[decq703] Selected DPD codes", "canonical_bson": "180000001364001300000000000000000000000000403000", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"19\"}}" }, { "description": "[decq704] Selected DPD codes", "canonical_bson": "180000001364001400000000000000000000000000403000", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"20\"}}" }, { "description": "[decq705] Selected DPD codes", "canonical_bson": "180000001364001D00000000000000000000000000403000", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"29\"}}" }, { "description": "[decq706] Selected DPD codes", "canonical_bson": "180000001364001E00000000000000000000000000403000", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"30\"}}" }, { "description": "[decq707] Selected DPD codes", "canonical_bson": "180000001364002700000000000000000000000000403000", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"39\"}}" }, { "description": "[decq708] Selected DPD codes", "canonical_bson": "180000001364002800000000000000000000000000403000", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"40\"}}" }, { "description": "[decq709] Selected DPD codes", "canonical_bson": "180000001364003100000000000000000000000000403000", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"49\"}}" }, { "description": "[decq710] Selected DPD codes", "canonical_bson": "180000001364003200000000000000000000000000403000", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"50\"}}" }, { "description": "[decq711] Selected DPD codes", "canonical_bson": "180000001364003B00000000000000000000000000403000", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"59\"}}" }, { "description": "[decq712] Selected DPD codes", "canonical_bson": "180000001364003C00000000000000000000000000403000", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"60\"}}" }, { "description": "[decq713] Selected DPD codes", "canonical_bson": "180000001364004500000000000000000000000000403000", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"69\"}}" }, { "description": "[decq714] Selected DPD codes", "canonical_bson": "180000001364004600000000000000000000000000403000", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"70\"}}" }, { "description": "[decq715] Selected DPD codes", "canonical_bson": "180000001364004700000000000000000000000000403000", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"71\"}}" }, { "description": "[decq716] Selected DPD codes", "canonical_bson": "180000001364004800000000000000000000000000403000", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"72\"}}" }, { "description": "[decq717] Selected DPD codes", "canonical_bson": "180000001364004900000000000000000000000000403000", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"73\"}}" }, { "description": "[decq718] Selected DPD codes", "canonical_bson": "180000001364004A00000000000000000000000000403000", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"74\"}}" }, { "description": "[decq719] Selected DPD codes", "canonical_bson": "180000001364004B00000000000000000000000000403000", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"75\"}}" }, { "description": "[decq720] Selected DPD codes", "canonical_bson": "180000001364004C00000000000000000000000000403000", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"76\"}}" }, { "description": "[decq721] Selected DPD codes", "canonical_bson": "180000001364004D00000000000000000000000000403000", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"77\"}}" }, { "description": "[decq722] Selected DPD codes", "canonical_bson": "180000001364004E00000000000000000000000000403000", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"78\"}}" }, { "description": "[decq723] Selected DPD codes", "canonical_bson": "180000001364004F00000000000000000000000000403000", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"79\"}}" }, { "description": "[decq056] fold-downs (more below)", "canonical_bson": "180000001364007B00000000000000000000000000403000", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"123\"}}" }, { "description": "[decq064] fold-downs (more below)", "canonical_bson": "1800000013640039300000000000000000000000003C3000", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"123.45\"}}" }, { "description": "[decq732] Selected DPD codes", "canonical_bson": "180000001364000802000000000000000000000000403000", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"520\"}}" }, { "description": "[decq733] Selected DPD codes", "canonical_bson": "180000001364000902000000000000000000000000403000", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"521\"}}" }, { "description": "[decq740] DPD: one of each of the huffman groups", "canonical_bson": "180000001364000903000000000000000000000000403000", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"777\"}}" }, { "description": "[decq741] DPD: one of each of the huffman groups", "canonical_bson": "180000001364000A03000000000000000000000000403000", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"778\"}}" }, { "description": "[decq742] DPD: one of each of the huffman groups", "canonical_bson": "180000001364001303000000000000000000000000403000", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"787\"}}" }, { "description": "[decq746] DPD: one of each of the huffman groups", "canonical_bson": "180000001364001F03000000000000000000000000403000", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"799\"}}" }, { "description": "[decq743] DPD: one of each of the huffman groups", "canonical_bson": "180000001364006D03000000000000000000000000403000", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"877\"}}" }, { "description": "[decq753] DPD all-highs cases (includes the 24 redundant codes)", "canonical_bson": "180000001364007803000000000000000000000000403000", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"888\"}}" }, { "description": "[decq754] DPD all-highs cases (includes the 24 redundant codes)", "canonical_bson": "180000001364007903000000000000000000000000403000", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"889\"}}" }, { "description": "[decq760] DPD all-highs cases (includes the 24 redundant codes)", "canonical_bson": "180000001364008203000000000000000000000000403000", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"898\"}}" }, { "description": "[decq764] DPD all-highs cases (includes the 24 redundant codes)", "canonical_bson": "180000001364008303000000000000000000000000403000", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"899\"}}" }, { "description": "[decq745] DPD: one of each of the huffman groups", "canonical_bson": "18000000136400D303000000000000000000000000403000", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"979\"}}" }, { "description": "[decq770] DPD all-highs cases (includes the 24 redundant codes)", "canonical_bson": "18000000136400DC03000000000000000000000000403000", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"988\"}}" }, { "description": "[decq774] DPD all-highs cases (includes the 24 redundant codes)", "canonical_bson": "18000000136400DD03000000000000000000000000403000", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"989\"}}" }, { "description": "[decq730] Selected DPD codes", "canonical_bson": "18000000136400E203000000000000000000000000403000", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"994\"}}" }, { "description": "[decq731] Selected DPD codes", "canonical_bson": "18000000136400E303000000000000000000000000403000", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"995\"}}" }, { "description": "[decq744] DPD: one of each of the huffman groups", "canonical_bson": "18000000136400E503000000000000000000000000403000", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"997\"}}" }, { "description": "[decq780] DPD all-highs cases (includes the 24 redundant codes)", "canonical_bson": "18000000136400E603000000000000000000000000403000", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"998\"}}" }, { "description": "[decq787] DPD all-highs cases (includes the 24 redundant codes)", "canonical_bson": "18000000136400E703000000000000000000000000403000", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"999\"}}" }, { "description": "[decq053] fold-downs (more below)", "canonical_bson": "18000000136400D204000000000000000000000000403000", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1234\"}}" }, { "description": "[decq052] fold-downs (more below)", "canonical_bson": "180000001364003930000000000000000000000000403000", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"12345\"}}" }, { "description": "[decq792] Miscellaneous (testers' queries, etc.)", "canonical_bson": "180000001364003075000000000000000000000000403000", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"30000\"}}" }, { "description": "[decq793] Miscellaneous (testers' queries, etc.)", "canonical_bson": "1800000013640090940D0000000000000000000000403000", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"890000\"}}" }, { "description": "[decq824] values around [u]int32 edges (zeros done earlier)", "canonical_bson": "18000000136400FEFFFF7F00000000000000000000403000", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"2147483646\"}}" }, { "description": "[decq825] values around [u]int32 edges (zeros done earlier)", "canonical_bson": "18000000136400FFFFFF7F00000000000000000000403000", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"2147483647\"}}" }, { "description": "[decq826] values around [u]int32 edges (zeros done earlier)", "canonical_bson": "180000001364000000008000000000000000000000403000", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"2147483648\"}}" }, { "description": "[decq827] values around [u]int32 edges (zeros done earlier)", "canonical_bson": "180000001364000100008000000000000000000000403000", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"2147483649\"}}" }, { "description": "[decq828] values around [u]int32 edges (zeros done earlier)", "canonical_bson": "18000000136400FEFFFFFF00000000000000000000403000", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"4294967294\"}}" }, { "description": "[decq829] values around [u]int32 edges (zeros done earlier)", "canonical_bson": "18000000136400FFFFFFFF00000000000000000000403000", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"4294967295\"}}" }, { "description": "[decq830] values around [u]int32 edges (zeros done earlier)", "canonical_bson": "180000001364000000000001000000000000000000403000", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"4294967296\"}}" }, { "description": "[decq831] values around [u]int32 edges (zeros done earlier)", "canonical_bson": "180000001364000100000001000000000000000000403000", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"4294967297\"}}" }, { "description": "[decq022] Normality", "canonical_bson": "18000000136400C7711CC7B548F377DC80A131C836403000", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1111111111111111111111111111111111\"}}" }, { "description": "[decq020] Normality", "canonical_bson": "18000000136400F2AF967ED05C82DE3297FF6FDE3C403000", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1234567890123456789012345678901234\"}}" }, { "description": "[decq550] Specials", "canonical_bson": "18000000136400FFFFFFFF638E8D37C087ADBE09ED413000", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"9999999999999999999999999999999999\"}}" } ] } mongodb-mongo-python-driver-509e9b7/test/bson_corpus/decimal128-3.json000066400000000000000000002613321462766011000256430ustar00rootroot00000000000000{ "description": "Decimal128", "bson_type": "0x13", "test_key": "d", "valid": [ { "description": "[basx066] strings without E cannot generate E in result", "canonical_bson": "18000000136400185C0ACE0000000000000000000038B000", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"-00345678.5432\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"-345678.5432\"}}" }, { "description": "[basx065] strings without E cannot generate E in result", "canonical_bson": "18000000136400185C0ACE0000000000000000000038B000", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"-0345678.5432\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"-345678.5432\"}}" }, { "description": "[basx064] strings without E cannot generate E in result", "canonical_bson": "18000000136400185C0ACE0000000000000000000038B000", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"-345678.5432\"}}" }, { "description": "[basx041] strings without E cannot generate E in result", "canonical_bson": "180000001364004C0000000000000000000000000040B000", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"-76\"}}" }, { "description": "[basx027] conform to rules and exponent will be in permitted range).", "canonical_bson": "180000001364000F270000000000000000000000003AB000", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"-9.999\"}}" }, { "description": "[basx026] conform to rules and exponent will be in permitted range).", "canonical_bson": "180000001364009F230000000000000000000000003AB000", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"-9.119\"}}" }, { "description": "[basx025] conform to rules and exponent will be in permitted range).", "canonical_bson": "180000001364008F030000000000000000000000003CB000", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"-9.11\"}}" }, { "description": "[basx024] conform to rules and exponent will be in permitted range).", "canonical_bson": "180000001364005B000000000000000000000000003EB000", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"-9.1\"}}" }, { "description": "[dqbsr531] negatives (Rounded)", "canonical_bson": "1800000013640099761CC7B548F377DC80A131C836FEAF00", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"-1.1111111111111111111111111111123450\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"-1.111111111111111111111111111112345\"}}" }, { "description": "[basx022] conform to rules and exponent will be in permitted range).", "canonical_bson": "180000001364000A000000000000000000000000003EB000", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"-1.0\"}}" }, { "description": "[basx021] conform to rules and exponent will be in permitted range).", "canonical_bson": "18000000136400010000000000000000000000000040B000", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"-1\"}}" }, { "description": "[basx601] Zeros", "canonical_bson": "1800000013640000000000000000000000000000002E3000", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"0.000000000\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"0E-9\"}}" }, { "description": "[basx622] Zeros", "canonical_bson": "1800000013640000000000000000000000000000002EB000", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"-0.000000000\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"-0E-9\"}}" }, { "description": "[basx602] Zeros", "canonical_bson": "180000001364000000000000000000000000000000303000", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"0.00000000\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"0E-8\"}}" }, { "description": "[basx621] Zeros", "canonical_bson": "18000000136400000000000000000000000000000030B000", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"-0.00000000\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"-0E-8\"}}" }, { "description": "[basx603] Zeros", "canonical_bson": "180000001364000000000000000000000000000000323000", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"0.0000000\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"0E-7\"}}" }, { "description": "[basx620] Zeros", "canonical_bson": "18000000136400000000000000000000000000000032B000", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"-0.0000000\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"-0E-7\"}}" }, { "description": "[basx604] Zeros", "canonical_bson": "180000001364000000000000000000000000000000343000", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"0.000000\"}}" }, { "description": "[basx619] Zeros", "canonical_bson": "18000000136400000000000000000000000000000034B000", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"-0.000000\"}}" }, { "description": "[basx605] Zeros", "canonical_bson": "180000001364000000000000000000000000000000363000", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"0.00000\"}}" }, { "description": "[basx618] Zeros", "canonical_bson": "18000000136400000000000000000000000000000036B000", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"-0.00000\"}}" }, { "description": "[basx680] Zeros", "canonical_bson": "180000001364000000000000000000000000000000403000", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"000000.\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"0\"}}" }, { "description": "[basx606] Zeros", "canonical_bson": "180000001364000000000000000000000000000000383000", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"0.0000\"}}" }, { "description": "[basx617] Zeros", "canonical_bson": "18000000136400000000000000000000000000000038B000", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"-0.0000\"}}" }, { "description": "[basx681] Zeros", "canonical_bson": "180000001364000000000000000000000000000000403000", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"00000.\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"0\"}}" }, { "description": "[basx686] Zeros", "canonical_bson": "180000001364000000000000000000000000000000403000", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"+00000.\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"0\"}}" }, { "description": "[basx687] Zeros", "canonical_bson": "18000000136400000000000000000000000000000040B000", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"-00000.\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"-0\"}}" }, { "description": "[basx019] conform to rules and exponent will be in permitted range).", "canonical_bson": "1800000013640000000000000000000000000000003CB000", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"-00.00\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"-0.00\"}}" }, { "description": "[basx607] Zeros", "canonical_bson": "1800000013640000000000000000000000000000003A3000", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"0.000\"}}" }, { "description": "[basx616] Zeros", "canonical_bson": "1800000013640000000000000000000000000000003AB000", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"-0.000\"}}" }, { "description": "[basx682] Zeros", "canonical_bson": "180000001364000000000000000000000000000000403000", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"0000.\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"0\"}}" }, { "description": "[basx155] Numbers with E", "canonical_bson": "1800000013640000000000000000000000000000003A3000", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"0.000e+0\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"0.000\"}}" }, { "description": "[basx130] Numbers with E", "canonical_bson": "180000001364000000000000000000000000000000383000", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"0.000E-1\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"0.0000\"}}" }, { "description": "[basx290] some more negative zeros [systematic tests below]", "canonical_bson": "18000000136400000000000000000000000000000038B000", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"-0.000E-1\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"-0.0000\"}}" }, { "description": "[basx131] Numbers with E", "canonical_bson": "180000001364000000000000000000000000000000363000", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"0.000E-2\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"0.00000\"}}" }, { "description": "[basx291] some more negative zeros [systematic tests below]", "canonical_bson": "18000000136400000000000000000000000000000036B000", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"-0.000E-2\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"-0.00000\"}}" }, { "description": "[basx132] Numbers with E", "canonical_bson": "180000001364000000000000000000000000000000343000", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"0.000E-3\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"0.000000\"}}" }, { "description": "[basx292] some more negative zeros [systematic tests below]", "canonical_bson": "18000000136400000000000000000000000000000034B000", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"-0.000E-3\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"-0.000000\"}}" }, { "description": "[basx133] Numbers with E", "canonical_bson": "180000001364000000000000000000000000000000323000", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"0.000E-4\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"0E-7\"}}" }, { "description": "[basx293] some more negative zeros [systematic tests below]", "canonical_bson": "18000000136400000000000000000000000000000032B000", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"-0.000E-4\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"-0E-7\"}}" }, { "description": "[basx608] Zeros", "canonical_bson": "1800000013640000000000000000000000000000003C3000", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"0.00\"}}" }, { "description": "[basx615] Zeros", "canonical_bson": "1800000013640000000000000000000000000000003CB000", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"-0.00\"}}" }, { "description": "[basx683] Zeros", "canonical_bson": "180000001364000000000000000000000000000000403000", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"000.\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"0\"}}" }, { "description": "[basx630] Zeros", "canonical_bson": "1800000013640000000000000000000000000000003C3000", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"0.00E+0\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"0.00\"}}" }, { "description": "[basx670] Zeros", "canonical_bson": "1800000013640000000000000000000000000000003C3000", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"0.00E-0\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"0.00\"}}" }, { "description": "[basx631] Zeros", "canonical_bson": "1800000013640000000000000000000000000000003E3000", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"0.00E+1\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"0.0\"}}" }, { "description": "[basx671] Zeros", "canonical_bson": "1800000013640000000000000000000000000000003A3000", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"0.00E-1\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"0.000\"}}" }, { "description": "[basx134] Numbers with E", "canonical_bson": "180000001364000000000000000000000000000000383000", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"0.00E-2\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"0.0000\"}}" }, { "description": "[basx294] some more negative zeros [systematic tests below]", "canonical_bson": "18000000136400000000000000000000000000000038B000", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"-0.00E-2\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"-0.0000\"}}" }, { "description": "[basx632] Zeros", "canonical_bson": "180000001364000000000000000000000000000000403000", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"0.00E+2\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"0\"}}" }, { "description": "[basx672] Zeros", "canonical_bson": "180000001364000000000000000000000000000000383000", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"0.00E-2\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"0.0000\"}}" }, { "description": "[basx135] Numbers with E", "canonical_bson": "180000001364000000000000000000000000000000363000", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"0.00E-3\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"0.00000\"}}" }, { "description": "[basx295] some more negative zeros [systematic tests below]", "canonical_bson": "18000000136400000000000000000000000000000036B000", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"-0.00E-3\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"-0.00000\"}}" }, { "description": "[basx633] Zeros", "canonical_bson": "180000001364000000000000000000000000000000423000", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"0.00E+3\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"0E+1\"}}" }, { "description": "[basx673] Zeros", "canonical_bson": "180000001364000000000000000000000000000000363000", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"0.00E-3\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"0.00000\"}}" }, { "description": "[basx136] Numbers with E", "canonical_bson": "180000001364000000000000000000000000000000343000", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"0.00E-4\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"0.000000\"}}" }, { "description": "[basx674] Zeros", "canonical_bson": "180000001364000000000000000000000000000000343000", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"0.00E-4\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"0.000000\"}}" }, { "description": "[basx634] Zeros", "canonical_bson": "180000001364000000000000000000000000000000443000", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"0.00E+4\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"0E+2\"}}" }, { "description": "[basx137] Numbers with E", "canonical_bson": "180000001364000000000000000000000000000000323000", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"0.00E-5\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"0E-7\"}}" }, { "description": "[basx635] Zeros", "canonical_bson": "180000001364000000000000000000000000000000463000", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"0.00E+5\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"0E+3\"}}" }, { "description": "[basx675] Zeros", "canonical_bson": "180000001364000000000000000000000000000000323000", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"0.00E-5\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"0E-7\"}}" }, { "description": "[basx636] Zeros", "canonical_bson": "180000001364000000000000000000000000000000483000", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"0.00E+6\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"0E+4\"}}" }, { "description": "[basx676] Zeros", "canonical_bson": "180000001364000000000000000000000000000000303000", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"0.00E-6\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"0E-8\"}}" }, { "description": "[basx637] Zeros", "canonical_bson": "1800000013640000000000000000000000000000004A3000", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"0.00E+7\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"0E+5\"}}" }, { "description": "[basx677] Zeros", "canonical_bson": "1800000013640000000000000000000000000000002E3000", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"0.00E-7\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"0E-9\"}}" }, { "description": "[basx638] Zeros", "canonical_bson": "1800000013640000000000000000000000000000004C3000", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"0.00E+8\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"0E+6\"}}" }, { "description": "[basx678] Zeros", "canonical_bson": "1800000013640000000000000000000000000000002C3000", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"0.00E-8\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"0E-10\"}}" }, { "description": "[basx149] Numbers with E", "canonical_bson": "180000001364000000000000000000000000000000523000", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"000E+9\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"0E+9\"}}" }, { "description": "[basx639] Zeros", "canonical_bson": "1800000013640000000000000000000000000000004E3000", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"0.00E+9\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"0E+7\"}}" }, { "description": "[basx679] Zeros", "canonical_bson": "1800000013640000000000000000000000000000002A3000", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"0.00E-9\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"0E-11\"}}" }, { "description": "[basx063] strings without E cannot generate E in result", "canonical_bson": "18000000136400185C0ACE00000000000000000000383000", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"+00345678.5432\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"345678.5432\"}}" }, { "description": "[basx018] conform to rules and exponent will be in permitted range).", "canonical_bson": "1800000013640000000000000000000000000000003EB000", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"-0.0\"}}" }, { "description": "[basx609] Zeros", "canonical_bson": "1800000013640000000000000000000000000000003E3000", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"0.0\"}}" }, { "description": "[basx614] Zeros", "canonical_bson": "1800000013640000000000000000000000000000003EB000", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"-0.0\"}}" }, { "description": "[basx684] Zeros", "canonical_bson": "180000001364000000000000000000000000000000403000", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"00.\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"0\"}}" }, { "description": "[basx640] Zeros", "canonical_bson": "1800000013640000000000000000000000000000003E3000", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"0.0E+0\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"0.0\"}}" }, { "description": "[basx660] Zeros", "canonical_bson": "1800000013640000000000000000000000000000003E3000", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"0.0E-0\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"0.0\"}}" }, { "description": "[basx641] Zeros", "canonical_bson": "180000001364000000000000000000000000000000403000", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"0.0E+1\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"0\"}}" }, { "description": "[basx661] Zeros", "canonical_bson": "1800000013640000000000000000000000000000003C3000", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"0.0E-1\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"0.00\"}}" }, { "description": "[basx296] some more negative zeros [systematic tests below]", "canonical_bson": "1800000013640000000000000000000000000000003AB000", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"-0.0E-2\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"-0.000\"}}" }, { "description": "[basx642] Zeros", "canonical_bson": "180000001364000000000000000000000000000000423000", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"0.0E+2\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"0E+1\"}}" }, { "description": "[basx662] Zeros", "canonical_bson": "1800000013640000000000000000000000000000003A3000", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"0.0E-2\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"0.000\"}}" }, { "description": "[basx297] some more negative zeros [systematic tests below]", "canonical_bson": "18000000136400000000000000000000000000000038B000", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"-0.0E-3\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"-0.0000\"}}" }, { "description": "[basx643] Zeros", "canonical_bson": "180000001364000000000000000000000000000000443000", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"0.0E+3\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"0E+2\"}}" }, { "description": "[basx663] Zeros", "canonical_bson": "180000001364000000000000000000000000000000383000", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"0.0E-3\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"0.0000\"}}" }, { "description": "[basx644] Zeros", "canonical_bson": "180000001364000000000000000000000000000000463000", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"0.0E+4\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"0E+3\"}}" }, { "description": "[basx664] Zeros", "canonical_bson": "180000001364000000000000000000000000000000363000", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"0.0E-4\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"0.00000\"}}" }, { "description": "[basx645] Zeros", "canonical_bson": "180000001364000000000000000000000000000000483000", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"0.0E+5\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"0E+4\"}}" }, { "description": "[basx665] Zeros", "canonical_bson": "180000001364000000000000000000000000000000343000", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"0.0E-5\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"0.000000\"}}" }, { "description": "[basx646] Zeros", "canonical_bson": "1800000013640000000000000000000000000000004A3000", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"0.0E+6\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"0E+5\"}}" }, { "description": "[basx666] Zeros", "canonical_bson": "180000001364000000000000000000000000000000323000", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"0.0E-6\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"0E-7\"}}" }, { "description": "[basx647] Zeros", "canonical_bson": "1800000013640000000000000000000000000000004C3000", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"0.0E+7\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"0E+6\"}}" }, { "description": "[basx667] Zeros", "canonical_bson": "180000001364000000000000000000000000000000303000", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"0.0E-7\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"0E-8\"}}" }, { "description": "[basx648] Zeros", "canonical_bson": "1800000013640000000000000000000000000000004E3000", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"0.0E+8\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"0E+7\"}}" }, { "description": "[basx668] Zeros", "canonical_bson": "1800000013640000000000000000000000000000002E3000", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"0.0E-8\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"0E-9\"}}" }, { "description": "[basx160] Numbers with E", "canonical_bson": "180000001364000000000000000000000000000000523000", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"00E+9\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"0E+9\"}}" }, { "description": "[basx161] Numbers with E", "canonical_bson": "1800000013640000000000000000000000000000002E3000", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"00E-9\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"0E-9\"}}" }, { "description": "[basx649] Zeros", "canonical_bson": "180000001364000000000000000000000000000000503000", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"0.0E+9\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"0E+8\"}}" }, { "description": "[basx669] Zeros", "canonical_bson": "1800000013640000000000000000000000000000002C3000", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"0.0E-9\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"0E-10\"}}" }, { "description": "[basx062] strings without E cannot generate E in result", "canonical_bson": "18000000136400185C0ACE00000000000000000000383000", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"+0345678.5432\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"345678.5432\"}}" }, { "description": "[basx001] conform to rules and exponent will be in permitted range).", "canonical_bson": "180000001364000000000000000000000000000000403000", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"0\"}}" }, { "description": "[basx017] conform to rules and exponent will be in permitted range).", "canonical_bson": "18000000136400000000000000000000000000000040B000", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"-0\"}}" }, { "description": "[basx611] Zeros", "canonical_bson": "180000001364000000000000000000000000000000403000", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"0.\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"0\"}}" }, { "description": "[basx613] Zeros", "canonical_bson": "18000000136400000000000000000000000000000040B000", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"-0.\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"-0\"}}" }, { "description": "[basx685] Zeros", "canonical_bson": "180000001364000000000000000000000000000000403000", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"0.\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"0\"}}" }, { "description": "[basx688] Zeros", "canonical_bson": "180000001364000000000000000000000000000000403000", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"+0.\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"0\"}}" }, { "description": "[basx689] Zeros", "canonical_bson": "18000000136400000000000000000000000000000040B000", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"-0.\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"-0\"}}" }, { "description": "[basx650] Zeros", "canonical_bson": "180000001364000000000000000000000000000000403000", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"0E+0\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"0\"}}" }, { "description": "[basx651] Zeros", "canonical_bson": "180000001364000000000000000000000000000000423000", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"0E+1\"}}" }, { "description": "[basx298] some more negative zeros [systematic tests below]", "canonical_bson": "1800000013640000000000000000000000000000003CB000", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"-0E-2\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"-0.00\"}}" }, { "description": "[basx652] Zeros", "canonical_bson": "180000001364000000000000000000000000000000443000", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"0E+2\"}}" }, { "description": "[basx299] some more negative zeros [systematic tests below]", "canonical_bson": "1800000013640000000000000000000000000000003AB000", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"-0E-3\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"-0.000\"}}" }, { "description": "[basx653] Zeros", "canonical_bson": "180000001364000000000000000000000000000000463000", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"0E+3\"}}" }, { "description": "[basx654] Zeros", "canonical_bson": "180000001364000000000000000000000000000000483000", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"0E+4\"}}" }, { "description": "[basx655] Zeros", "canonical_bson": "1800000013640000000000000000000000000000004A3000", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"0E+5\"}}" }, { "description": "[basx656] Zeros", "canonical_bson": "1800000013640000000000000000000000000000004C3000", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"0E+6\"}}" }, { "description": "[basx657] Zeros", "canonical_bson": "1800000013640000000000000000000000000000004E3000", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"0E+7\"}}" }, { "description": "[basx658] Zeros", "canonical_bson": "180000001364000000000000000000000000000000503000", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"0E+8\"}}" }, { "description": "[basx138] Numbers with E", "canonical_bson": "180000001364000000000000000000000000000000523000", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"+0E+9\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"0E+9\"}}" }, { "description": "[basx139] Numbers with E", "canonical_bson": "18000000136400000000000000000000000000000052B000", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"-0E+9\"}}" }, { "description": "[basx144] Numbers with E", "canonical_bson": "180000001364000000000000000000000000000000523000", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"0E+9\"}}" }, { "description": "[basx154] Numbers with E", "canonical_bson": "180000001364000000000000000000000000000000523000", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"0E9\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"0E+9\"}}" }, { "description": "[basx659] Zeros", "canonical_bson": "180000001364000000000000000000000000000000523000", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"0E+9\"}}" }, { "description": "[basx042] strings without E cannot generate E in result", "canonical_bson": "18000000136400FC040000000000000000000000003C3000", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"+12.76\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"12.76\"}}" }, { "description": "[basx143] Numbers with E", "canonical_bson": "180000001364000100000000000000000000000000523000", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"+1E+009\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1E+9\"}}" }, { "description": "[basx061] strings without E cannot generate E in result", "canonical_bson": "18000000136400185C0ACE00000000000000000000383000", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"+345678.5432\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"345678.5432\"}}" }, { "description": "[basx036] conform to rules and exponent will be in permitted range).", "canonical_bson": "1800000013640015CD5B0700000000000000000000203000", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"0.0000000123456789\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1.23456789E-8\"}}" }, { "description": "[basx035] conform to rules and exponent will be in permitted range).", "canonical_bson": "1800000013640015CD5B0700000000000000000000223000", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"0.000000123456789\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1.23456789E-7\"}}" }, { "description": "[basx034] conform to rules and exponent will be in permitted range).", "canonical_bson": "1800000013640015CD5B0700000000000000000000243000", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"0.00000123456789\"}}" }, { "description": "[basx053] strings without E cannot generate E in result", "canonical_bson": "180000001364003200000000000000000000000000323000", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"0.0000050\"}}" }, { "description": "[basx033] conform to rules and exponent will be in permitted range).", "canonical_bson": "1800000013640015CD5B0700000000000000000000263000", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"0.0000123456789\"}}" }, { "description": "[basx016] conform to rules and exponent will be in permitted range).", "canonical_bson": "180000001364000C000000000000000000000000003A3000", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"0.012\"}}" }, { "description": "[basx015] conform to rules and exponent will be in permitted range).", "canonical_bson": "180000001364007B000000000000000000000000003A3000", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"0.123\"}}" }, { "description": "[basx037] conform to rules and exponent will be in permitted range).", "canonical_bson": "1800000013640078DF0D8648700000000000000000223000", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"0.123456789012344\"}}" }, { "description": "[basx038] conform to rules and exponent will be in permitted range).", "canonical_bson": "1800000013640079DF0D8648700000000000000000223000", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"0.123456789012345\"}}" }, { "description": "[basx250] Numbers with E", "canonical_bson": "18000000136400F104000000000000000000000000383000", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"0.1265\"}}" }, { "description": "[basx257] Numbers with E", "canonical_bson": "18000000136400F104000000000000000000000000383000", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"0.1265E-0\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"0.1265\"}}" }, { "description": "[basx256] Numbers with E", "canonical_bson": "18000000136400F104000000000000000000000000363000", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"0.1265E-1\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"0.01265\"}}" }, { "description": "[basx258] Numbers with E", "canonical_bson": "18000000136400F1040000000000000000000000003A3000", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"0.1265E+1\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1.265\"}}" }, { "description": "[basx251] Numbers with E", "canonical_bson": "18000000136400F104000000000000000000000000103000", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"0.1265E-20\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1.265E-21\"}}" }, { "description": "[basx263] Numbers with E", "canonical_bson": "18000000136400F104000000000000000000000000603000", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"0.1265E+20\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1.265E+19\"}}" }, { "description": "[basx255] Numbers with E", "canonical_bson": "18000000136400F104000000000000000000000000343000", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"0.1265E-2\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"0.001265\"}}" }, { "description": "[basx259] Numbers with E", "canonical_bson": "18000000136400F1040000000000000000000000003C3000", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"0.1265E+2\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"12.65\"}}" }, { "description": "[basx254] Numbers with E", "canonical_bson": "18000000136400F104000000000000000000000000323000", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"0.1265E-3\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"0.0001265\"}}" }, { "description": "[basx260] Numbers with E", "canonical_bson": "18000000136400F1040000000000000000000000003E3000", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"0.1265E+3\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"126.5\"}}" }, { "description": "[basx253] Numbers with E", "canonical_bson": "18000000136400F104000000000000000000000000303000", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"0.1265E-4\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"0.00001265\"}}" }, { "description": "[basx261] Numbers with E", "canonical_bson": "18000000136400F104000000000000000000000000403000", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"0.1265E+4\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1265\"}}" }, { "description": "[basx252] Numbers with E", "canonical_bson": "18000000136400F104000000000000000000000000283000", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"0.1265E-8\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1.265E-9\"}}" }, { "description": "[basx262] Numbers with E", "canonical_bson": "18000000136400F104000000000000000000000000483000", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"0.1265E+8\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1.265E+7\"}}" }, { "description": "[basx159] Numbers with E", "canonical_bson": "1800000013640049000000000000000000000000002E3000", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"0.73e-7\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"7.3E-8\"}}" }, { "description": "[basx004] conform to rules and exponent will be in permitted range).", "canonical_bson": "1800000013640064000000000000000000000000003C3000", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1.00\"}}" }, { "description": "[basx003] conform to rules and exponent will be in permitted range).", "canonical_bson": "180000001364000A000000000000000000000000003E3000", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1.0\"}}" }, { "description": "[basx002] conform to rules and exponent will be in permitted range).", "canonical_bson": "180000001364000100000000000000000000000000403000", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1\"}}" }, { "description": "[basx148] Numbers with E", "canonical_bson": "180000001364000100000000000000000000000000523000", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"1E+009\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1E+9\"}}" }, { "description": "[basx153] Numbers with E", "canonical_bson": "180000001364000100000000000000000000000000523000", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"1E009\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1E+9\"}}" }, { "description": "[basx141] Numbers with E", "canonical_bson": "180000001364000100000000000000000000000000523000", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"1e+09\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1E+9\"}}" }, { "description": "[basx146] Numbers with E", "canonical_bson": "180000001364000100000000000000000000000000523000", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"1E+09\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1E+9\"}}" }, { "description": "[basx151] Numbers with E", "canonical_bson": "180000001364000100000000000000000000000000523000", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"1e09\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1E+9\"}}" }, { "description": "[basx142] Numbers with E", "canonical_bson": "180000001364000100000000000000000000000000F43000", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1E+90\"}}" }, { "description": "[basx147] Numbers with E", "canonical_bson": "180000001364000100000000000000000000000000F43000", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"1e+90\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1E+90\"}}" }, { "description": "[basx152] Numbers with E", "canonical_bson": "180000001364000100000000000000000000000000F43000", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"1E90\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1E+90\"}}" }, { "description": "[basx140] Numbers with E", "canonical_bson": "180000001364000100000000000000000000000000523000", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1E+9\"}}" }, { "description": "[basx150] Numbers with E", "canonical_bson": "180000001364000100000000000000000000000000523000", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"1E9\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1E+9\"}}" }, { "description": "[basx014] conform to rules and exponent will be in permitted range).", "canonical_bson": "18000000136400D2040000000000000000000000003A3000", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1.234\"}}" }, { "description": "[basx170] Numbers with E", "canonical_bson": "18000000136400F1040000000000000000000000003A3000", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1.265\"}}" }, { "description": "[basx177] Numbers with E", "canonical_bson": "18000000136400F1040000000000000000000000003A3000", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"1.265E-0\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1.265\"}}" }, { "description": "[basx176] Numbers with E", "canonical_bson": "18000000136400F104000000000000000000000000383000", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"1.265E-1\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"0.1265\"}}" }, { "description": "[basx178] Numbers with E", "canonical_bson": "18000000136400F1040000000000000000000000003C3000", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"1.265E+1\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"12.65\"}}" }, { "description": "[basx171] Numbers with E", "canonical_bson": "18000000136400F104000000000000000000000000123000", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1.265E-20\"}}" }, { "description": "[basx183] Numbers with E", "canonical_bson": "18000000136400F104000000000000000000000000623000", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1.265E+20\"}}" }, { "description": "[basx175] Numbers with E", "canonical_bson": "18000000136400F104000000000000000000000000363000", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"1.265E-2\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"0.01265\"}}" }, { "description": "[basx179] Numbers with E", "canonical_bson": "18000000136400F1040000000000000000000000003E3000", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"1.265E+2\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"126.5\"}}" }, { "description": "[basx174] Numbers with E", "canonical_bson": "18000000136400F104000000000000000000000000343000", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"1.265E-3\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"0.001265\"}}" }, { "description": "[basx180] Numbers with E", "canonical_bson": "18000000136400F104000000000000000000000000403000", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"1.265E+3\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1265\"}}" }, { "description": "[basx173] Numbers with E", "canonical_bson": "18000000136400F104000000000000000000000000323000", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"1.265E-4\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"0.0001265\"}}" }, { "description": "[basx181] Numbers with E", "canonical_bson": "18000000136400F104000000000000000000000000423000", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1.265E+4\"}}" }, { "description": "[basx172] Numbers with E", "canonical_bson": "18000000136400F1040000000000000000000000002A3000", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1.265E-8\"}}" }, { "description": "[basx182] Numbers with E", "canonical_bson": "18000000136400F1040000000000000000000000004A3000", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1.265E+8\"}}" }, { "description": "[basx157] Numbers with E", "canonical_bson": "180000001364000400000000000000000000000000523000", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"4E+9\"}}" }, { "description": "[basx067] examples", "canonical_bson": "180000001364000500000000000000000000000000343000", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"5E-6\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"0.000005\"}}" }, { "description": "[basx069] examples", "canonical_bson": "180000001364000500000000000000000000000000323000", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"5E-7\"}}" }, { "description": "[basx385] Engineering notation tests", "canonical_bson": "180000001364000700000000000000000000000000403000", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"7E0\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"7\"}}" }, { "description": "[basx365] Engineering notation tests", "canonical_bson": "180000001364000700000000000000000000000000543000", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"7E10\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"7E+10\"}}" }, { "description": "[basx405] Engineering notation tests", "canonical_bson": "1800000013640007000000000000000000000000002C3000", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"7E-10\"}}" }, { "description": "[basx363] Engineering notation tests", "canonical_bson": "180000001364000700000000000000000000000000563000", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"7E11\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"7E+11\"}}" }, { "description": "[basx407] Engineering notation tests", "canonical_bson": "1800000013640007000000000000000000000000002A3000", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"7E-11\"}}" }, { "description": "[basx361] Engineering notation tests", "canonical_bson": "180000001364000700000000000000000000000000583000", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"7E12\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"7E+12\"}}" }, { "description": "[basx409] Engineering notation tests", "canonical_bson": "180000001364000700000000000000000000000000283000", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"7E-12\"}}" }, { "description": "[basx411] Engineering notation tests", "canonical_bson": "180000001364000700000000000000000000000000263000", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"7E-13\"}}" }, { "description": "[basx383] Engineering notation tests", "canonical_bson": "180000001364000700000000000000000000000000423000", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"7E1\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"7E+1\"}}" }, { "description": "[basx387] Engineering notation tests", "canonical_bson": "1800000013640007000000000000000000000000003E3000", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"7E-1\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"0.7\"}}" }, { "description": "[basx381] Engineering notation tests", "canonical_bson": "180000001364000700000000000000000000000000443000", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"7E2\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"7E+2\"}}" }, { "description": "[basx389] Engineering notation tests", "canonical_bson": "1800000013640007000000000000000000000000003C3000", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"7E-2\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"0.07\"}}" }, { "description": "[basx379] Engineering notation tests", "canonical_bson": "180000001364000700000000000000000000000000463000", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"7E3\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"7E+3\"}}" }, { "description": "[basx391] Engineering notation tests", "canonical_bson": "1800000013640007000000000000000000000000003A3000", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"7E-3\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"0.007\"}}" }, { "description": "[basx377] Engineering notation tests", "canonical_bson": "180000001364000700000000000000000000000000483000", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"7E4\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"7E+4\"}}" }, { "description": "[basx393] Engineering notation tests", "canonical_bson": "180000001364000700000000000000000000000000383000", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"7E-4\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"0.0007\"}}" }, { "description": "[basx375] Engineering notation tests", "canonical_bson": "1800000013640007000000000000000000000000004A3000", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"7E5\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"7E+5\"}}" }, { "description": "[basx395] Engineering notation tests", "canonical_bson": "180000001364000700000000000000000000000000363000", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"7E-5\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"0.00007\"}}" }, { "description": "[basx373] Engineering notation tests", "canonical_bson": "1800000013640007000000000000000000000000004C3000", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"7E6\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"7E+6\"}}" }, { "description": "[basx397] Engineering notation tests", "canonical_bson": "180000001364000700000000000000000000000000343000", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"7E-6\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"0.000007\"}}" }, { "description": "[basx371] Engineering notation tests", "canonical_bson": "1800000013640007000000000000000000000000004E3000", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"7E7\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"7E+7\"}}" }, { "description": "[basx399] Engineering notation tests", "canonical_bson": "180000001364000700000000000000000000000000323000", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"7E-7\"}}" }, { "description": "[basx369] Engineering notation tests", "canonical_bson": "180000001364000700000000000000000000000000503000", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"7E8\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"7E+8\"}}" }, { "description": "[basx401] Engineering notation tests", "canonical_bson": "180000001364000700000000000000000000000000303000", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"7E-8\"}}" }, { "description": "[basx367] Engineering notation tests", "canonical_bson": "180000001364000700000000000000000000000000523000", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"7E9\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"7E+9\"}}" }, { "description": "[basx403] Engineering notation tests", "canonical_bson": "1800000013640007000000000000000000000000002E3000", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"7E-9\"}}" }, { "description": "[basx007] conform to rules and exponent will be in permitted range).", "canonical_bson": "1800000013640064000000000000000000000000003E3000", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"10.0\"}}" }, { "description": "[basx005] conform to rules and exponent will be in permitted range).", "canonical_bson": "180000001364000A00000000000000000000000000403000", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"10\"}}" }, { "description": "[basx165] Numbers with E", "canonical_bson": "180000001364000A00000000000000000000000000523000", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"10E+009\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1.0E+10\"}}" }, { "description": "[basx163] Numbers with E", "canonical_bson": "180000001364000A00000000000000000000000000523000", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"10E+09\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1.0E+10\"}}" }, { "description": "[basx325] Engineering notation tests", "canonical_bson": "180000001364000A00000000000000000000000000403000", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"10e0\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"10\"}}" }, { "description": "[basx305] Engineering notation tests", "canonical_bson": "180000001364000A00000000000000000000000000543000", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"10e10\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1.0E+11\"}}" }, { "description": "[basx345] Engineering notation tests", "canonical_bson": "180000001364000A000000000000000000000000002C3000", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"10e-10\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1.0E-9\"}}" }, { "description": "[basx303] Engineering notation tests", "canonical_bson": "180000001364000A00000000000000000000000000563000", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"10e11\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1.0E+12\"}}" }, { "description": "[basx347] Engineering notation tests", "canonical_bson": "180000001364000A000000000000000000000000002A3000", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"10e-11\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1.0E-10\"}}" }, { "description": "[basx301] Engineering notation tests", "canonical_bson": "180000001364000A00000000000000000000000000583000", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"10e12\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1.0E+13\"}}" }, { "description": "[basx349] Engineering notation tests", "canonical_bson": "180000001364000A00000000000000000000000000283000", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"10e-12\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1.0E-11\"}}" }, { "description": "[basx351] Engineering notation tests", "canonical_bson": "180000001364000A00000000000000000000000000263000", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"10e-13\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1.0E-12\"}}" }, { "description": "[basx323] Engineering notation tests", "canonical_bson": "180000001364000A00000000000000000000000000423000", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"10e1\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1.0E+2\"}}" }, { "description": "[basx327] Engineering notation tests", "canonical_bson": "180000001364000A000000000000000000000000003E3000", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"10e-1\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1.0\"}}" }, { "description": "[basx321] Engineering notation tests", "canonical_bson": "180000001364000A00000000000000000000000000443000", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"10e2\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1.0E+3\"}}" }, { "description": "[basx329] Engineering notation tests", "canonical_bson": "180000001364000A000000000000000000000000003C3000", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"10e-2\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"0.10\"}}" }, { "description": "[basx319] Engineering notation tests", "canonical_bson": "180000001364000A00000000000000000000000000463000", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"10e3\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1.0E+4\"}}" }, { "description": "[basx331] Engineering notation tests", "canonical_bson": "180000001364000A000000000000000000000000003A3000", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"10e-3\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"0.010\"}}" }, { "description": "[basx317] Engineering notation tests", "canonical_bson": "180000001364000A00000000000000000000000000483000", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"10e4\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1.0E+5\"}}" }, { "description": "[basx333] Engineering notation tests", "canonical_bson": "180000001364000A00000000000000000000000000383000", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"10e-4\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"0.0010\"}}" }, { "description": "[basx315] Engineering notation tests", "canonical_bson": "180000001364000A000000000000000000000000004A3000", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"10e5\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1.0E+6\"}}" }, { "description": "[basx335] Engineering notation tests", "canonical_bson": "180000001364000A00000000000000000000000000363000", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"10e-5\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"0.00010\"}}" }, { "description": "[basx313] Engineering notation tests", "canonical_bson": "180000001364000A000000000000000000000000004C3000", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"10e6\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1.0E+7\"}}" }, { "description": "[basx337] Engineering notation tests", "canonical_bson": "180000001364000A00000000000000000000000000343000", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"10e-6\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"0.000010\"}}" }, { "description": "[basx311] Engineering notation tests", "canonical_bson": "180000001364000A000000000000000000000000004E3000", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"10e7\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1.0E+8\"}}" }, { "description": "[basx339] Engineering notation tests", "canonical_bson": "180000001364000A00000000000000000000000000323000", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"10e-7\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"0.0000010\"}}" }, { "description": "[basx309] Engineering notation tests", "canonical_bson": "180000001364000A00000000000000000000000000503000", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"10e8\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1.0E+9\"}}" }, { "description": "[basx341] Engineering notation tests", "canonical_bson": "180000001364000A00000000000000000000000000303000", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"10e-8\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1.0E-7\"}}" }, { "description": "[basx164] Numbers with E", "canonical_bson": "180000001364000A00000000000000000000000000F43000", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"10e+90\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1.0E+91\"}}" }, { "description": "[basx162] Numbers with E", "canonical_bson": "180000001364000A00000000000000000000000000523000", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"10E+9\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1.0E+10\"}}" }, { "description": "[basx307] Engineering notation tests", "canonical_bson": "180000001364000A00000000000000000000000000523000", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"10e9\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1.0E+10\"}}" }, { "description": "[basx343] Engineering notation tests", "canonical_bson": "180000001364000A000000000000000000000000002E3000", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"10e-9\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1.0E-8\"}}" }, { "description": "[basx008] conform to rules and exponent will be in permitted range).", "canonical_bson": "1800000013640065000000000000000000000000003E3000", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"10.1\"}}" }, { "description": "[basx009] conform to rules and exponent will be in permitted range).", "canonical_bson": "1800000013640068000000000000000000000000003E3000", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"10.4\"}}" }, { "description": "[basx010] conform to rules and exponent will be in permitted range).", "canonical_bson": "1800000013640069000000000000000000000000003E3000", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"10.5\"}}" }, { "description": "[basx011] conform to rules and exponent will be in permitted range).", "canonical_bson": "180000001364006A000000000000000000000000003E3000", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"10.6\"}}" }, { "description": "[basx012] conform to rules and exponent will be in permitted range).", "canonical_bson": "180000001364006D000000000000000000000000003E3000", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"10.9\"}}" }, { "description": "[basx013] conform to rules and exponent will be in permitted range).", "canonical_bson": "180000001364006E000000000000000000000000003E3000", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"11.0\"}}" }, { "description": "[basx040] strings without E cannot generate E in result", "canonical_bson": "180000001364000C00000000000000000000000000403000", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"12\"}}" }, { "description": "[basx190] Numbers with E", "canonical_bson": "18000000136400F1040000000000000000000000003C3000", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"12.65\"}}" }, { "description": "[basx197] Numbers with E", "canonical_bson": "18000000136400F1040000000000000000000000003C3000", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"12.65E-0\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"12.65\"}}" }, { "description": "[basx196] Numbers with E", "canonical_bson": "18000000136400F1040000000000000000000000003A3000", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"12.65E-1\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1.265\"}}" }, { "description": "[basx198] Numbers with E", "canonical_bson": "18000000136400F1040000000000000000000000003E3000", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"12.65E+1\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"126.5\"}}" }, { "description": "[basx191] Numbers with E", "canonical_bson": "18000000136400F104000000000000000000000000143000", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"12.65E-20\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1.265E-19\"}}" }, { "description": "[basx203] Numbers with E", "canonical_bson": "18000000136400F104000000000000000000000000643000", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"12.65E+20\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1.265E+21\"}}" }, { "description": "[basx195] Numbers with E", "canonical_bson": "18000000136400F104000000000000000000000000383000", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"12.65E-2\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"0.1265\"}}" }, { "description": "[basx199] Numbers with E", "canonical_bson": "18000000136400F104000000000000000000000000403000", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"12.65E+2\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1265\"}}" }, { "description": "[basx194] Numbers with E", "canonical_bson": "18000000136400F104000000000000000000000000363000", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"12.65E-3\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"0.01265\"}}" }, { "description": "[basx200] Numbers with E", "canonical_bson": "18000000136400F104000000000000000000000000423000", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"12.65E+3\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1.265E+4\"}}" }, { "description": "[basx193] Numbers with E", "canonical_bson": "18000000136400F104000000000000000000000000343000", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"12.65E-4\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"0.001265\"}}" }, { "description": "[basx201] Numbers with E", "canonical_bson": "18000000136400F104000000000000000000000000443000", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"12.65E+4\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1.265E+5\"}}" }, { "description": "[basx192] Numbers with E", "canonical_bson": "18000000136400F1040000000000000000000000002C3000", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"12.65E-8\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1.265E-7\"}}" }, { "description": "[basx202] Numbers with E", "canonical_bson": "18000000136400F1040000000000000000000000004C3000", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"12.65E+8\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1.265E+9\"}}" }, { "description": "[basx044] strings without E cannot generate E in result", "canonical_bson": "18000000136400FC040000000000000000000000003C3000", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"012.76\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"12.76\"}}" }, { "description": "[basx042] strings without E cannot generate E in result", "canonical_bson": "18000000136400FC040000000000000000000000003C3000", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"12.76\"}}" }, { "description": "[basx046] strings without E cannot generate E in result", "canonical_bson": "180000001364001100000000000000000000000000403000", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"17.\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"17\"}}" }, { "description": "[basx049] strings without E cannot generate E in result", "canonical_bson": "180000001364002C00000000000000000000000000403000", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"0044\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"44\"}}" }, { "description": "[basx048] strings without E cannot generate E in result", "canonical_bson": "180000001364002C00000000000000000000000000403000", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"044\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"44\"}}" }, { "description": "[basx158] Numbers with E", "canonical_bson": "180000001364002C00000000000000000000000000523000", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"44E+9\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"4.4E+10\"}}" }, { "description": "[basx068] examples", "canonical_bson": "180000001364003200000000000000000000000000323000", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"50E-7\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"0.0000050\"}}" }, { "description": "[basx169] Numbers with E", "canonical_bson": "180000001364006400000000000000000000000000523000", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"100e+009\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1.00E+11\"}}" }, { "description": "[basx167] Numbers with E", "canonical_bson": "180000001364006400000000000000000000000000523000", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"100e+09\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1.00E+11\"}}" }, { "description": "[basx168] Numbers with E", "canonical_bson": "180000001364006400000000000000000000000000F43000", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"100E+90\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1.00E+92\"}}" }, { "description": "[basx166] Numbers with E", "canonical_bson": "180000001364006400000000000000000000000000523000", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"100e+9\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1.00E+11\"}}" }, { "description": "[basx210] Numbers with E", "canonical_bson": "18000000136400F1040000000000000000000000003E3000", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"126.5\"}}" }, { "description": "[basx217] Numbers with E", "canonical_bson": "18000000136400F1040000000000000000000000003E3000", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"126.5E-0\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"126.5\"}}" }, { "description": "[basx216] Numbers with E", "canonical_bson": "18000000136400F1040000000000000000000000003C3000", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"126.5E-1\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"12.65\"}}" }, { "description": "[basx218] Numbers with E", "canonical_bson": "18000000136400F104000000000000000000000000403000", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"126.5E+1\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1265\"}}" }, { "description": "[basx211] Numbers with E", "canonical_bson": "18000000136400F104000000000000000000000000163000", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"126.5E-20\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1.265E-18\"}}" }, { "description": "[basx223] Numbers with E", "canonical_bson": "18000000136400F104000000000000000000000000663000", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"126.5E+20\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1.265E+22\"}}" }, { "description": "[basx215] Numbers with E", "canonical_bson": "18000000136400F1040000000000000000000000003A3000", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"126.5E-2\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1.265\"}}" }, { "description": "[basx219] Numbers with E", "canonical_bson": "18000000136400F104000000000000000000000000423000", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"126.5E+2\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1.265E+4\"}}" }, { "description": "[basx214] Numbers with E", "canonical_bson": "18000000136400F104000000000000000000000000383000", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"126.5E-3\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"0.1265\"}}" }, { "description": "[basx220] Numbers with E", "canonical_bson": "18000000136400F104000000000000000000000000443000", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"126.5E+3\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1.265E+5\"}}" }, { "description": "[basx213] Numbers with E", "canonical_bson": "18000000136400F104000000000000000000000000363000", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"126.5E-4\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"0.01265\"}}" }, { "description": "[basx221] Numbers with E", "canonical_bson": "18000000136400F104000000000000000000000000463000", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"126.5E+4\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1.265E+6\"}}" }, { "description": "[basx212] Numbers with E", "canonical_bson": "18000000136400F1040000000000000000000000002E3000", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"126.5E-8\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"0.000001265\"}}" }, { "description": "[basx222] Numbers with E", "canonical_bson": "18000000136400F1040000000000000000000000004E3000", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"126.5E+8\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1.265E+10\"}}" }, { "description": "[basx006] conform to rules and exponent will be in permitted range).", "canonical_bson": "18000000136400E803000000000000000000000000403000", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1000\"}}" }, { "description": "[basx230] Numbers with E", "canonical_bson": "18000000136400F104000000000000000000000000403000", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1265\"}}" }, { "description": "[basx237] Numbers with E", "canonical_bson": "18000000136400F104000000000000000000000000403000", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"1265E-0\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1265\"}}" }, { "description": "[basx236] Numbers with E", "canonical_bson": "18000000136400F1040000000000000000000000003E3000", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"1265E-1\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"126.5\"}}" }, { "description": "[basx238] Numbers with E", "canonical_bson": "18000000136400F104000000000000000000000000423000", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"1265E+1\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1.265E+4\"}}" }, { "description": "[basx231] Numbers with E", "canonical_bson": "18000000136400F104000000000000000000000000183000", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"1265E-20\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1.265E-17\"}}" }, { "description": "[basx243] Numbers with E", "canonical_bson": "18000000136400F104000000000000000000000000683000", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"1265E+20\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1.265E+23\"}}" }, { "description": "[basx235] Numbers with E", "canonical_bson": "18000000136400F1040000000000000000000000003C3000", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"1265E-2\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"12.65\"}}" }, { "description": "[basx239] Numbers with E", "canonical_bson": "18000000136400F104000000000000000000000000443000", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"1265E+2\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1.265E+5\"}}" }, { "description": "[basx234] Numbers with E", "canonical_bson": "18000000136400F1040000000000000000000000003A3000", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"1265E-3\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1.265\"}}" }, { "description": "[basx240] Numbers with E", "canonical_bson": "18000000136400F104000000000000000000000000463000", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"1265E+3\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1.265E+6\"}}" }, { "description": "[basx233] Numbers with E", "canonical_bson": "18000000136400F104000000000000000000000000383000", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"1265E-4\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"0.1265\"}}" }, { "description": "[basx241] Numbers with E", "canonical_bson": "18000000136400F104000000000000000000000000483000", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"1265E+4\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1.265E+7\"}}" }, { "description": "[basx232] Numbers with E", "canonical_bson": "18000000136400F104000000000000000000000000303000", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"1265E-8\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"0.00001265\"}}" }, { "description": "[basx242] Numbers with E", "canonical_bson": "18000000136400F104000000000000000000000000503000", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"1265E+8\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1.265E+11\"}}" }, { "description": "[basx060] strings without E cannot generate E in result", "canonical_bson": "18000000136400185C0ACE00000000000000000000383000", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"345678.5432\"}}" }, { "description": "[basx059] strings without E cannot generate E in result", "canonical_bson": "18000000136400F198670C08000000000000000000363000", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"0345678.54321\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"345678.54321\"}}" }, { "description": "[basx058] strings without E cannot generate E in result", "canonical_bson": "180000001364006AF90B7C50000000000000000000343000", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"345678.543210\"}}" }, { "description": "[basx057] strings without E cannot generate E in result", "canonical_bson": "180000001364006A19562522020000000000000000343000", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"2345678.543210\"}}" }, { "description": "[basx056] strings without E cannot generate E in result", "canonical_bson": "180000001364006AB9C8733A0B0000000000000000343000", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"12345678.543210\"}}" }, { "description": "[basx031] conform to rules and exponent will be in permitted range).", "canonical_bson": "1800000013640040AF0D8648700000000000000000343000", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"123456789.000000\"}}" }, { "description": "[basx030] conform to rules and exponent will be in permitted range).", "canonical_bson": "1800000013640080910F8648700000000000000000343000", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"123456789.123456\"}}" }, { "description": "[basx032] conform to rules and exponent will be in permitted range).", "canonical_bson": "1800000013640080910F8648700000000000000000403000", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"123456789123456\"}}" } ] } mongodb-mongo-python-driver-509e9b7/test/bson_corpus/decimal128-4.json000066400000000000000000000157371462766011000256520ustar00rootroot00000000000000{ "description": "Decimal128", "bson_type": "0x13", "test_key": "d", "valid": [ { "description": "[basx023] conform to rules and exponent will be in permitted range).", "canonical_bson": "1800000013640001000000000000000000000000003EB000", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"-0.1\"}}" }, { "description": "[basx045] strings without E cannot generate E in result", "canonical_bson": "1800000013640003000000000000000000000000003A3000", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"+0.003\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"0.003\"}}" }, { "description": "[basx610] Zeros", "canonical_bson": "1800000013640000000000000000000000000000003E3000", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \".0\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"0.0\"}}" }, { "description": "[basx612] Zeros", "canonical_bson": "1800000013640000000000000000000000000000003EB000", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"-.0\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"-0.0\"}}" }, { "description": "[basx043] strings without E cannot generate E in result", "canonical_bson": "18000000136400FC040000000000000000000000003C3000", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"+12.76\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"12.76\"}}" }, { "description": "[basx055] strings without E cannot generate E in result", "canonical_bson": "180000001364000500000000000000000000000000303000", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"0.00000005\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"5E-8\"}}" }, { "description": "[basx054] strings without E cannot generate E in result", "canonical_bson": "180000001364000500000000000000000000000000323000", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"0.0000005\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"5E-7\"}}" }, { "description": "[basx052] strings without E cannot generate E in result", "canonical_bson": "180000001364000500000000000000000000000000343000", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"0.000005\"}}" }, { "description": "[basx051] strings without E cannot generate E in result", "canonical_bson": "180000001364000500000000000000000000000000363000", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"00.00005\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"0.00005\"}}" }, { "description": "[basx050] strings without E cannot generate E in result", "canonical_bson": "180000001364000500000000000000000000000000383000", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"0.0005\"}}" }, { "description": "[basx047] strings without E cannot generate E in result", "canonical_bson": "1800000013640005000000000000000000000000003E3000", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \".5\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"0.5\"}}" }, { "description": "[dqbsr431] check rounding modes heeded (Rounded)", "canonical_bson": "1800000013640099761CC7B548F377DC80A131C836FE2F00", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"1.1111111111111111111111111111123450\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1.111111111111111111111111111112345\"}}" }, { "description": "OK2", "canonical_bson": "18000000136400000000000A5BC138938D44C64D31FC2F00", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \".100000000000000000000000000000000000000000000000000000000000\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"0.1000000000000000000000000000000000\"}}" } ], "parseErrors": [ { "description": "[basx564] Near-specials (Conversion_syntax)", "string": "Infi" }, { "description": "[basx565] Near-specials (Conversion_syntax)", "string": "Infin" }, { "description": "[basx566] Near-specials (Conversion_syntax)", "string": "Infini" }, { "description": "[basx567] Near-specials (Conversion_syntax)", "string": "Infinit" }, { "description": "[basx568] Near-specials (Conversion_syntax)", "string": "-Infinit" }, { "description": "[basx590] some baddies with dots and Es and dots and specials (Conversion_syntax)", "string": ".Infinity" }, { "description": "[basx562] Near-specials (Conversion_syntax)", "string": "NaNq" }, { "description": "[basx563] Near-specials (Conversion_syntax)", "string": "NaNs" }, { "description": "[dqbas939] overflow results at different rounding modes (Overflow & Inexact & Rounded)", "string": "-7e10000" }, { "description": "[dqbsr534] negatives (Rounded & Inexact)", "string": "-1.11111111111111111111111111111234650" }, { "description": "[dqbsr535] negatives (Rounded & Inexact)", "string": "-1.11111111111111111111111111111234551" }, { "description": "[dqbsr533] negatives (Rounded & Inexact)", "string": "-1.11111111111111111111111111111234550" }, { "description": "[dqbsr532] negatives (Rounded & Inexact)", "string": "-1.11111111111111111111111111111234549" }, { "description": "[dqbsr432] check rounding modes heeded (Rounded & Inexact)", "string": "1.11111111111111111111111111111234549" }, { "description": "[dqbsr433] check rounding modes heeded (Rounded & Inexact)", "string": "1.11111111111111111111111111111234550" }, { "description": "[dqbsr435] check rounding modes heeded (Rounded & Inexact)", "string": "1.11111111111111111111111111111234551" }, { "description": "[dqbsr434] check rounding modes heeded (Rounded & Inexact)", "string": "1.11111111111111111111111111111234650" }, { "description": "[dqbas938] overflow results at different rounding modes (Overflow & Inexact & Rounded)", "string": "7e10000" }, { "description": "Inexact rounding#1", "string": "100000000000000000000000000000000000000000000000000000000001" }, { "description": "Inexact rounding#2", "string": "1E-6177" } ] } mongodb-mongo-python-driver-509e9b7/test/bson_corpus/decimal128-5.json000066400000000000000000000554551462766011000256540ustar00rootroot00000000000000{ "description": "Decimal128", "bson_type": "0x13", "test_key": "d", "valid": [ { "description": "[decq035] fold-downs (more below) (Clamped)", "canonical_bson": "18000000136400000000807F1BCF85B27059C8A43CFE5F00", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"1.23E+6144\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1.230000000000000000000000000000000E+6144\"}}" }, { "description": "[decq037] fold-downs (more below) (Clamped)", "canonical_bson": "18000000136400000000000A5BC138938D44C64D31FE5F00", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"1E+6144\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1.000000000000000000000000000000000E+6144\"}}" }, { "description": "[decq077] Nmin and below (Subnormal)", "canonical_bson": "180000001364000000000081EFAC855B416D2DEE04000000", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"0.100000000000000000000000000000000E-6143\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1.00000000000000000000000000000000E-6144\"}}" }, { "description": "[decq078] Nmin and below (Subnormal)", "canonical_bson": "180000001364000000000081EFAC855B416D2DEE04000000", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1.00000000000000000000000000000000E-6144\"}}" }, { "description": "[decq079] Nmin and below (Subnormal)", "canonical_bson": "180000001364000A00000000000000000000000000000000", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"0.000000000000000000000000000000010E-6143\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1.0E-6175\"}}" }, { "description": "[decq080] Nmin and below (Subnormal)", "canonical_bson": "180000001364000A00000000000000000000000000000000", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1.0E-6175\"}}" }, { "description": "[decq081] Nmin and below (Subnormal)", "canonical_bson": "180000001364000100000000000000000000000000020000", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"0.00000000000000000000000000000001E-6143\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1E-6175\"}}" }, { "description": "[decq082] Nmin and below (Subnormal)", "canonical_bson": "180000001364000100000000000000000000000000020000", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1E-6175\"}}" }, { "description": "[decq083] Nmin and below (Subnormal)", "canonical_bson": "180000001364000100000000000000000000000000000000", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"0.000000000000000000000000000000001E-6143\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1E-6176\"}}" }, { "description": "[decq084] Nmin and below (Subnormal)", "canonical_bson": "180000001364000100000000000000000000000000000000", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1E-6176\"}}" }, { "description": "[decq090] underflows cannot be tested for simple copies, check edge cases (Subnormal)", "canonical_bson": "180000001364000100000000000000000000000000000000", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"1e-6176\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1E-6176\"}}" }, { "description": "[decq100] underflows cannot be tested for simple copies, check edge cases (Subnormal)", "canonical_bson": "18000000136400FFFFFFFF095BC138938D44C64D31000000", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"999999999999999999999999999999999e-6176\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"9.99999999999999999999999999999999E-6144\"}}" }, { "description": "[decq130] fold-downs (more below) (Clamped)", "canonical_bson": "18000000136400000000807F1BCF85B27059C8A43CFEDF00", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"-1.23E+6144\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"-1.230000000000000000000000000000000E+6144\"}}" }, { "description": "[decq132] fold-downs (more below) (Clamped)", "canonical_bson": "18000000136400000000000A5BC138938D44C64D31FEDF00", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"-1E+6144\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"-1.000000000000000000000000000000000E+6144\"}}" }, { "description": "[decq177] Nmin and below (Subnormal)", "canonical_bson": "180000001364000000000081EFAC855B416D2DEE04008000", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"-0.100000000000000000000000000000000E-6143\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"-1.00000000000000000000000000000000E-6144\"}}" }, { "description": "[decq178] Nmin and below (Subnormal)", "canonical_bson": "180000001364000000000081EFAC855B416D2DEE04008000", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"-1.00000000000000000000000000000000E-6144\"}}" }, { "description": "[decq179] Nmin and below (Subnormal)", "canonical_bson": "180000001364000A00000000000000000000000000008000", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"-0.000000000000000000000000000000010E-6143\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"-1.0E-6175\"}}" }, { "description": "[decq180] Nmin and below (Subnormal)", "canonical_bson": "180000001364000A00000000000000000000000000008000", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"-1.0E-6175\"}}" }, { "description": "[decq181] Nmin and below (Subnormal)", "canonical_bson": "180000001364000100000000000000000000000000028000", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"-0.00000000000000000000000000000001E-6143\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"-1E-6175\"}}" }, { "description": "[decq182] Nmin and below (Subnormal)", "canonical_bson": "180000001364000100000000000000000000000000028000", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"-1E-6175\"}}" }, { "description": "[decq183] Nmin and below (Subnormal)", "canonical_bson": "180000001364000100000000000000000000000000008000", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"-0.000000000000000000000000000000001E-6143\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"-1E-6176\"}}" }, { "description": "[decq184] Nmin and below (Subnormal)", "canonical_bson": "180000001364000100000000000000000000000000008000", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"-1E-6176\"}}" }, { "description": "[decq190] underflow edge cases (Subnormal)", "canonical_bson": "180000001364000100000000000000000000000000008000", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"-1e-6176\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"-1E-6176\"}}" }, { "description": "[decq200] underflow edge cases (Subnormal)", "canonical_bson": "18000000136400FFFFFFFF095BC138938D44C64D31008000", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"-999999999999999999999999999999999e-6176\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"-9.99999999999999999999999999999999E-6144\"}}" }, { "description": "[decq400] zeros (Clamped)", "canonical_bson": "180000001364000000000000000000000000000000000000", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"0E-8000\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"0E-6176\"}}" }, { "description": "[decq401] zeros (Clamped)", "canonical_bson": "180000001364000000000000000000000000000000000000", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"0E-6177\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"0E-6176\"}}" }, { "description": "[decq414] clamped zeros... (Clamped)", "canonical_bson": "180000001364000000000000000000000000000000FE5F00", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"0E+6112\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"0E+6111\"}}" }, { "description": "[decq416] clamped zeros... (Clamped)", "canonical_bson": "180000001364000000000000000000000000000000FE5F00", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"0E+6144\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"0E+6111\"}}" }, { "description": "[decq418] clamped zeros... (Clamped)", "canonical_bson": "180000001364000000000000000000000000000000FE5F00", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"0E+8000\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"0E+6111\"}}" }, { "description": "[decq420] negative zeros (Clamped)", "canonical_bson": "180000001364000000000000000000000000000000008000", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"-0E-8000\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"-0E-6176\"}}" }, { "description": "[decq421] negative zeros (Clamped)", "canonical_bson": "180000001364000000000000000000000000000000008000", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"-0E-6177\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"-0E-6176\"}}" }, { "description": "[decq434] clamped zeros... (Clamped)", "canonical_bson": "180000001364000000000000000000000000000000FEDF00", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"-0E+6112\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"-0E+6111\"}}" }, { "description": "[decq436] clamped zeros... (Clamped)", "canonical_bson": "180000001364000000000000000000000000000000FEDF00", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"-0E+6144\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"-0E+6111\"}}" }, { "description": "[decq438] clamped zeros... (Clamped)", "canonical_bson": "180000001364000000000000000000000000000000FEDF00", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"-0E+8000\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"-0E+6111\"}}" }, { "description": "[decq601] fold-down full sequence (Clamped)", "canonical_bson": "18000000136400000000000A5BC138938D44C64D31FE5F00", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"1E+6144\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1.000000000000000000000000000000000E+6144\"}}" }, { "description": "[decq603] fold-down full sequence (Clamped)", "canonical_bson": "180000001364000000000081EFAC855B416D2DEE04FE5F00", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"1E+6143\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1.00000000000000000000000000000000E+6143\"}}" }, { "description": "[decq605] fold-down full sequence (Clamped)", "canonical_bson": "1800000013640000000080264B91C02220BE377E00FE5F00", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"1E+6142\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1.0000000000000000000000000000000E+6142\"}}" }, { "description": "[decq607] fold-down full sequence (Clamped)", "canonical_bson": "1800000013640000000040EAED7446D09C2C9F0C00FE5F00", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"1E+6141\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1.000000000000000000000000000000E+6141\"}}" }, { "description": "[decq609] fold-down full sequence (Clamped)", "canonical_bson": "18000000136400000000A0CA17726DAE0F1E430100FE5F00", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"1E+6140\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1.00000000000000000000000000000E+6140\"}}" }, { "description": "[decq611] fold-down full sequence (Clamped)", "canonical_bson": "18000000136400000000106102253E5ECE4F200000FE5F00", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"1E+6139\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1.0000000000000000000000000000E+6139\"}}" }, { "description": "[decq613] fold-down full sequence (Clamped)", "canonical_bson": "18000000136400000000E83C80D09F3C2E3B030000FE5F00", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"1E+6138\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1.000000000000000000000000000E+6138\"}}" }, { "description": "[decq615] fold-down full sequence (Clamped)", "canonical_bson": "18000000136400000000E4D20CC8DCD2B752000000FE5F00", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"1E+6137\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1.00000000000000000000000000E+6137\"}}" }, { "description": "[decq617] fold-down full sequence (Clamped)", "canonical_bson": "180000001364000000004A48011416954508000000FE5F00", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"1E+6136\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1.0000000000000000000000000E+6136\"}}" }, { "description": "[decq619] fold-down full sequence (Clamped)", "canonical_bson": "18000000136400000000A1EDCCCE1BC2D300000000FE5F00", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"1E+6135\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1.000000000000000000000000E+6135\"}}" }, { "description": "[decq621] fold-down full sequence (Clamped)", "canonical_bson": "18000000136400000080F64AE1C7022D1500000000FE5F00", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"1E+6134\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1.00000000000000000000000E+6134\"}}" }, { "description": "[decq623] fold-down full sequence (Clamped)", "canonical_bson": "18000000136400000040B2BAC9E0191E0200000000FE5F00", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"1E+6133\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1.0000000000000000000000E+6133\"}}" }, { "description": "[decq625] fold-down full sequence (Clamped)", "canonical_bson": "180000001364000000A0DEC5ADC935360000000000FE5F00", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"1E+6132\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1.000000000000000000000E+6132\"}}" }, { "description": "[decq627] fold-down full sequence (Clamped)", "canonical_bson": "18000000136400000010632D5EC76B050000000000FE5F00", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"1E+6131\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1.00000000000000000000E+6131\"}}" }, { "description": "[decq629] fold-down full sequence (Clamped)", "canonical_bson": "180000001364000000E8890423C78A000000000000FE5F00", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"1E+6130\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1.0000000000000000000E+6130\"}}" }, { "description": "[decq631] fold-down full sequence (Clamped)", "canonical_bson": "18000000136400000064A7B3B6E00D000000000000FE5F00", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"1E+6129\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1.000000000000000000E+6129\"}}" }, { "description": "[decq633] fold-down full sequence (Clamped)", "canonical_bson": "1800000013640000008A5D78456301000000000000FE5F00", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"1E+6128\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1.00000000000000000E+6128\"}}" }, { "description": "[decq635] fold-down full sequence (Clamped)", "canonical_bson": "180000001364000000C16FF2862300000000000000FE5F00", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"1E+6127\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1.0000000000000000E+6127\"}}" }, { "description": "[decq637] fold-down full sequence (Clamped)", "canonical_bson": "180000001364000080C6A47E8D0300000000000000FE5F00", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"1E+6126\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1.000000000000000E+6126\"}}" }, { "description": "[decq639] fold-down full sequence (Clamped)", "canonical_bson": "1800000013640000407A10F35A0000000000000000FE5F00", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"1E+6125\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1.00000000000000E+6125\"}}" }, { "description": "[decq641] fold-down full sequence (Clamped)", "canonical_bson": "1800000013640000A0724E18090000000000000000FE5F00", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"1E+6124\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1.0000000000000E+6124\"}}" }, { "description": "[decq643] fold-down full sequence (Clamped)", "canonical_bson": "180000001364000010A5D4E8000000000000000000FE5F00", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"1E+6123\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1.000000000000E+6123\"}}" }, { "description": "[decq645] fold-down full sequence (Clamped)", "canonical_bson": "1800000013640000E8764817000000000000000000FE5F00", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"1E+6122\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1.00000000000E+6122\"}}" }, { "description": "[decq647] fold-down full sequence (Clamped)", "canonical_bson": "1800000013640000E40B5402000000000000000000FE5F00", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"1E+6121\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1.0000000000E+6121\"}}" }, { "description": "[decq649] fold-down full sequence (Clamped)", "canonical_bson": "1800000013640000CA9A3B00000000000000000000FE5F00", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"1E+6120\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1.000000000E+6120\"}}" }, { "description": "[decq651] fold-down full sequence (Clamped)", "canonical_bson": "1800000013640000E1F50500000000000000000000FE5F00", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"1E+6119\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1.00000000E+6119\"}}" }, { "description": "[decq653] fold-down full sequence (Clamped)", "canonical_bson": "180000001364008096980000000000000000000000FE5F00", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"1E+6118\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1.0000000E+6118\"}}" }, { "description": "[decq655] fold-down full sequence (Clamped)", "canonical_bson": "1800000013640040420F0000000000000000000000FE5F00", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"1E+6117\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1.000000E+6117\"}}" }, { "description": "[decq657] fold-down full sequence (Clamped)", "canonical_bson": "18000000136400A086010000000000000000000000FE5F00", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"1E+6116\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1.00000E+6116\"}}" }, { "description": "[decq659] fold-down full sequence (Clamped)", "canonical_bson": "180000001364001027000000000000000000000000FE5F00", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"1E+6115\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1.0000E+6115\"}}" }, { "description": "[decq661] fold-down full sequence (Clamped)", "canonical_bson": "18000000136400E803000000000000000000000000FE5F00", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"1E+6114\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1.000E+6114\"}}" }, { "description": "[decq663] fold-down full sequence (Clamped)", "canonical_bson": "180000001364006400000000000000000000000000FE5F00", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"1E+6113\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1.00E+6113\"}}" }, { "description": "[decq665] fold-down full sequence (Clamped)", "canonical_bson": "180000001364000A00000000000000000000000000FE5F00", "degenerate_extjson": "{\"d\" : {\"$numberDecimal\" : \"1E+6112\"}}", "canonical_extjson": "{\"d\" : {\"$numberDecimal\" : \"1.0E+6112\"}}" } ] } mongodb-mongo-python-driver-509e9b7/test/bson_corpus/decimal128-6.json000066400000000000000000000060111462766011000256350ustar00rootroot00000000000000{ "description": "Decimal128", "bson_type": "0x13", "test_key": "d", "parseErrors": [ { "description": "Incomplete Exponent", "string": "1e" }, { "description": "Exponent at the beginning", "string": "E01" }, { "description": "Just a decimal place", "string": "." }, { "description": "2 decimal places", "string": "..3" }, { "description": "2 decimal places", "string": ".13.3" }, { "description": "2 decimal places", "string": "1..3" }, { "description": "2 decimal places", "string": "1.3.4" }, { "description": "2 decimal places", "string": "1.34." }, { "description": "Decimal with no digits", "string": ".e" }, { "description": "2 signs", "string": "+-32.4" }, { "description": "2 signs", "string": "-+32.4" }, { "description": "2 negative signs", "string": "--32.4" }, { "description": "2 negative signs", "string": "-32.-4" }, { "description": "End in negative sign", "string": "32.0-" }, { "description": "2 negative signs", "string": "32.4E--21" }, { "description": "2 negative signs", "string": "32.4E-2-1" }, { "description": "2 signs", "string": "32.4E+-21" }, { "description": "Empty string", "string": "" }, { "description": "leading white space positive number", "string": " 1" }, { "description": "leading white space negative number", "string": " -1" }, { "description": "trailing white space", "string": "1 " }, { "description": "Invalid", "string": "E" }, { "description": "Invalid", "string": "invalid" }, { "description": "Invalid", "string": "i" }, { "description": "Invalid", "string": "in" }, { "description": "Invalid", "string": "-in" }, { "description": "Invalid", "string": "Na" }, { "description": "Invalid", "string": "-Na" }, { "description": "Invalid", "string": "1.23abc" }, { "description": "Invalid", "string": "1.23abcE+02" }, { "description": "Invalid", "string": "1.23E+0aabs2" } ] } mongodb-mongo-python-driver-509e9b7/test/bson_corpus/decimal128-7.json000066400000000000000000000310171462766011000256420ustar00rootroot00000000000000{ "description": "Decimal128", "bson_type": "0x13", "test_key": "d", "parseErrors": [ { "description": "[basx572] Near-specials (Conversion_syntax)", "string": "-9Inf" }, { "description": "[basx516] The 'baddies' tests from DiagBigDecimal, plus some new ones (Conversion_syntax)", "string": "-1-" }, { "description": "[basx533] The 'baddies' tests from DiagBigDecimal, plus some new ones (Conversion_syntax)", "string": "0000.." }, { "description": "[basx534] The 'baddies' tests from DiagBigDecimal, plus some new ones (Conversion_syntax)", "string": ".0000." }, { "description": "[basx535] The 'baddies' tests from DiagBigDecimal, plus some new ones (Conversion_syntax)", "string": "00..00" }, { "description": "[basx569] Near-specials (Conversion_syntax)", "string": "0Inf" }, { "description": "[basx571] Near-specials (Conversion_syntax)", "string": "-0Inf" }, { "description": "[basx575] Near-specials (Conversion_syntax)", "string": "0sNaN" }, { "description": "[basx503] The 'baddies' tests from DiagBigDecimal, plus some new ones (Conversion_syntax)", "string": "++1" }, { "description": "[basx504] The 'baddies' tests from DiagBigDecimal, plus some new ones (Conversion_syntax)", "string": "--1" }, { "description": "[basx505] The 'baddies' tests from DiagBigDecimal, plus some new ones (Conversion_syntax)", "string": "-+1" }, { "description": "[basx506] The 'baddies' tests from DiagBigDecimal, plus some new ones (Conversion_syntax)", "string": "+-1" }, { "description": "[basx510] The 'baddies' tests from DiagBigDecimal, plus some new ones (Conversion_syntax)", "string": " +1" }, { "description": "[basx513] The 'baddies' tests from DiagBigDecimal, plus some new ones (Conversion_syntax)", "string": " + 1" }, { "description": "[basx514] The 'baddies' tests from DiagBigDecimal, plus some new ones (Conversion_syntax)", "string": " - 1" }, { "description": "[basx501] The 'baddies' tests from DiagBigDecimal, plus some new ones (Conversion_syntax)", "string": "." }, { "description": "[basx502] The 'baddies' tests from DiagBigDecimal, plus some new ones (Conversion_syntax)", "string": ".." }, { "description": "[basx519] The 'baddies' tests from DiagBigDecimal, plus some new ones (Conversion_syntax)", "string": "" }, { "description": "[basx525] The 'baddies' tests from DiagBigDecimal, plus some new ones (Conversion_syntax)", "string": "e100" }, { "description": "[basx549] The 'baddies' tests from DiagBigDecimal, plus some new ones (Conversion_syntax)", "string": "e+1" }, { "description": "[basx577] some baddies with dots and Es and dots and specials (Conversion_syntax)", "string": ".e+1" }, { "description": "[basx578] some baddies with dots and Es and dots and specials (Conversion_syntax)", "string": "+.e+1" }, { "description": "[basx581] some baddies with dots and Es and dots and specials (Conversion_syntax)", "string": "E+1" }, { "description": "[basx582] some baddies with dots and Es and dots and specials (Conversion_syntax)", "string": ".E+1" }, { "description": "[basx583] some baddies with dots and Es and dots and specials (Conversion_syntax)", "string": "+.E+1" }, { "description": "[basx579] some baddies with dots and Es and dots and specials (Conversion_syntax)", "string": "-.e+" }, { "description": "[basx580] some baddies with dots and Es and dots and specials (Conversion_syntax)", "string": "-.e" }, { "description": "[basx584] some baddies with dots and Es and dots and specials (Conversion_syntax)", "string": "-.E+" }, { "description": "[basx585] some baddies with dots and Es and dots and specials (Conversion_syntax)", "string": "-.E" }, { "description": "[basx589] some baddies with dots and Es and dots and specials (Conversion_syntax)", "string": "+.Inf" }, { "description": "[basx586] some baddies with dots and Es and dots and specials (Conversion_syntax)", "string": ".NaN" }, { "description": "[basx587] some baddies with dots and Es and dots and specials (Conversion_syntax)", "string": "-.NaN" }, { "description": "[basx545] The 'baddies' tests from DiagBigDecimal, plus some new ones (Conversion_syntax)", "string": "ONE" }, { "description": "[basx561] Near-specials (Conversion_syntax)", "string": "qNaN" }, { "description": "[basx573] Near-specials (Conversion_syntax)", "string": "-sNa" }, { "description": "[basx588] some baddies with dots and Es and dots and specials (Conversion_syntax)", "string": "+.sNaN" }, { "description": "[basx544] The 'baddies' tests from DiagBigDecimal, plus some new ones (Conversion_syntax)", "string": "ten" }, { "description": "[basx527] The 'baddies' tests from DiagBigDecimal, plus some new ones (Conversion_syntax)", "string": "u0b65" }, { "description": "[basx526] The 'baddies' tests from DiagBigDecimal, plus some new ones (Conversion_syntax)", "string": "u0e5a" }, { "description": "[basx515] The 'baddies' tests from DiagBigDecimal, plus some new ones (Conversion_syntax)", "string": "x" }, { "description": "[basx574] Near-specials (Conversion_syntax)", "string": "xNaN" }, { "description": "[basx530] The 'baddies' tests from DiagBigDecimal, plus some new ones (Conversion_syntax)", "string": ".123.5" }, { "description": "[basx500] The 'baddies' tests from DiagBigDecimal, plus some new ones (Conversion_syntax)", "string": "1..2" }, { "description": "[basx542] The 'baddies' tests from DiagBigDecimal, plus some new ones (Conversion_syntax)", "string": "1e1.0" }, { "description": "[basx553] The 'baddies' tests from DiagBigDecimal, plus some new ones (Conversion_syntax)", "string": "1E+1.2.3" }, { "description": "[basx543] The 'baddies' tests from DiagBigDecimal, plus some new ones (Conversion_syntax)", "string": "1e123e" }, { "description": "[basx552] The 'baddies' tests from DiagBigDecimal, plus some new ones (Conversion_syntax)", "string": "1E+1.2" }, { "description": "[basx546] The 'baddies' tests from DiagBigDecimal, plus some new ones (Conversion_syntax)", "string": "1e.1" }, { "description": "[basx547] The 'baddies' tests from DiagBigDecimal, plus some new ones (Conversion_syntax)", "string": "1e1." }, { "description": "[basx554] The 'baddies' tests from DiagBigDecimal, plus some new ones (Conversion_syntax)", "string": "1E++1" }, { "description": "[basx555] The 'baddies' tests from DiagBigDecimal, plus some new ones (Conversion_syntax)", "string": "1E--1" }, { "description": "[basx556] The 'baddies' tests from DiagBigDecimal, plus some new ones (Conversion_syntax)", "string": "1E+-1" }, { "description": "[basx557] The 'baddies' tests from DiagBigDecimal, plus some new ones (Conversion_syntax)", "string": "1E-+1" }, { "description": "[basx558] The 'baddies' tests from DiagBigDecimal, plus some new ones (Conversion_syntax)", "string": "1E'1" }, { "description": "[basx559] The 'baddies' tests from DiagBigDecimal, plus some new ones (Conversion_syntax)", "string": "1E\"1" }, { "description": "[basx520] The 'baddies' tests from DiagBigDecimal, plus some new ones (Conversion_syntax)", "string": "1e-" }, { "description": "[basx560] The 'baddies' tests from DiagBigDecimal, plus some new ones (Conversion_syntax)", "string": "1E" }, { "description": "[basx548] The 'baddies' tests from DiagBigDecimal, plus some new ones (Conversion_syntax)", "string": "1ee" }, { "description": "[basx551] The 'baddies' tests from DiagBigDecimal, plus some new ones (Conversion_syntax)", "string": "1.2.1" }, { "description": "[basx550] The 'baddies' tests from DiagBigDecimal, plus some new ones (Conversion_syntax)", "string": "1.23.4" }, { "description": "[basx529] The 'baddies' tests from DiagBigDecimal, plus some new ones (Conversion_syntax)", "string": "1.34.5" }, { "description": "[basx531] The 'baddies' tests from DiagBigDecimal, plus some new ones (Conversion_syntax)", "string": "01.35." }, { "description": "[basx532] The 'baddies' tests from DiagBigDecimal, plus some new ones (Conversion_syntax)", "string": "01.35-" }, { "description": "[basx518] The 'baddies' tests from DiagBigDecimal, plus some new ones (Conversion_syntax)", "string": "3+" }, { "description": "[basx521] The 'baddies' tests from DiagBigDecimal, plus some new ones (Conversion_syntax)", "string": "7e99999a" }, { "description": "[basx570] Near-specials (Conversion_syntax)", "string": "9Inf" }, { "description": "[basx512] The 'baddies' tests from DiagBigDecimal, plus some new ones (Conversion_syntax)", "string": "12 " }, { "description": "[basx517] The 'baddies' tests from DiagBigDecimal, plus some new ones (Conversion_syntax)", "string": "12-" }, { "description": "[basx507] The 'baddies' tests from DiagBigDecimal, plus some new ones (Conversion_syntax)", "string": "12e" }, { "description": "[basx508] The 'baddies' tests from DiagBigDecimal, plus some new ones (Conversion_syntax)", "string": "12e++" }, { "description": "[basx509] The 'baddies' tests from DiagBigDecimal, plus some new ones (Conversion_syntax)", "string": "12f4" }, { "description": "[basx536] The 'baddies' tests from DiagBigDecimal, plus some new ones (Conversion_syntax)", "string": "111e*123" }, { "description": "[basx537] The 'baddies' tests from DiagBigDecimal, plus some new ones (Conversion_syntax)", "string": "111e123-" }, { "description": "[basx540] The 'baddies' tests from DiagBigDecimal, plus some new ones (Conversion_syntax)", "string": "111e1*23" }, { "description": "[basx538] The 'baddies' tests from DiagBigDecimal, plus some new ones (Conversion_syntax)", "string": "111e+12+" }, { "description": "[basx539] The 'baddies' tests from DiagBigDecimal, plus some new ones (Conversion_syntax)", "string": "111e1-3-" }, { "description": "[basx541] The 'baddies' tests from DiagBigDecimal, plus some new ones (Conversion_syntax)", "string": "111E1e+3" }, { "description": "[basx528] The 'baddies' tests from DiagBigDecimal, plus some new ones (Conversion_syntax)", "string": "123,65" }, { "description": "[basx523] The 'baddies' tests from DiagBigDecimal, plus some new ones (Conversion_syntax)", "string": "7e12356789012x" }, { "description": "[basx522] The 'baddies' tests from DiagBigDecimal, plus some new ones (Conversion_syntax)", "string": "7e123567890x" } ] } mongodb-mongo-python-driver-509e9b7/test/bson_corpus/document.json000066400000000000000000000043741462766011000254710ustar00rootroot00000000000000{ "description": "Document type (sub-documents)", "bson_type": "0x03", "test_key": "x", "valid": [ { "description": "Empty subdoc", "canonical_bson": "0D000000037800050000000000", "canonical_extjson": "{\"x\" : {}}" }, { "description": "Empty-string key subdoc", "canonical_bson": "150000000378000D00000002000200000062000000", "canonical_extjson": "{\"x\" : {\"\" : \"b\"}}" }, { "description": "Single-character key subdoc", "canonical_bson": "160000000378000E0000000261000200000062000000", "canonical_extjson": "{\"x\" : {\"a\" : \"b\"}}" }, { "description": "Dollar-prefixed key in sub-document", "canonical_bson": "170000000378000F000000022461000200000062000000", "canonical_extjson": "{\"x\" : {\"$a\" : \"b\"}}" }, { "description": "Dollar as key in sub-document", "canonical_bson": "160000000378000E0000000224000200000061000000", "canonical_extjson": "{\"x\" : {\"$\" : \"a\"}}" }, { "description": "Dotted key in sub-document", "canonical_bson": "180000000378001000000002612E62000200000063000000", "canonical_extjson": "{\"x\" : {\"a.b\" : \"c\"}}" }, { "description": "Dot as key in sub-document", "canonical_bson": "160000000378000E000000022E000200000061000000", "canonical_extjson": "{\"x\" : {\".\" : \"a\"}}" } ], "decodeErrors": [ { "description": "Subdocument length too long: eats outer terminator", "bson": "1800000003666F6F000F0000001062617200FFFFFF7F0000" }, { "description": "Subdocument length too short: leaks terminator", "bson": "1500000003666F6F000A0000000862617200010000" }, { "description": "Invalid subdocument: bad string length in field", "bson": "1C00000003666F6F001200000002626172000500000062617A000000" }, { "description": "Null byte in sub-document key", "bson": "150000000378000D00000010610000010000000000" } ] } mongodb-mongo-python-driver-509e9b7/test/bson_corpus/double.json000066400000000000000000000067071462766011000251270ustar00rootroot00000000000000{ "description": "Double type", "bson_type": "0x01", "test_key": "d", "valid": [ { "description": "+1.0", "canonical_bson": "10000000016400000000000000F03F00", "canonical_extjson": "{\"d\" : {\"$numberDouble\": \"1.0\"}}", "relaxed_extjson": "{\"d\" : 1.0}" }, { "description": "-1.0", "canonical_bson": "10000000016400000000000000F0BF00", "canonical_extjson": "{\"d\" : {\"$numberDouble\": \"-1.0\"}}", "relaxed_extjson": "{\"d\" : -1.0}" }, { "description": "+1.0001220703125", "canonical_bson": "10000000016400000000008000F03F00", "canonical_extjson": "{\"d\" : {\"$numberDouble\": \"1.0001220703125\"}}", "relaxed_extjson": "{\"d\" : 1.0001220703125}" }, { "description": "-1.0001220703125", "canonical_bson": "10000000016400000000008000F0BF00", "canonical_extjson": "{\"d\" : {\"$numberDouble\": \"-1.0001220703125\"}}", "relaxed_extjson": "{\"d\" : -1.0001220703125}" }, { "description": "1.2345678921232E+18", "canonical_bson": "100000000164002a1bf5f41022b14300", "canonical_extjson": "{\"d\" : {\"$numberDouble\": \"1.2345678921232E+18\"}}", "relaxed_extjson": "{\"d\" : 1.2345678921232E+18}" }, { "description": "-1.2345678921232E+18", "canonical_bson": "100000000164002a1bf5f41022b1c300", "canonical_extjson": "{\"d\" : {\"$numberDouble\": \"-1.2345678921232E+18\"}}", "relaxed_extjson": "{\"d\" : -1.2345678921232E+18}" }, { "description": "0.0", "canonical_bson": "10000000016400000000000000000000", "canonical_extjson": "{\"d\" : {\"$numberDouble\": \"0.0\"}}", "relaxed_extjson": "{\"d\" : 0.0}" }, { "description": "-0.0", "canonical_bson": "10000000016400000000000000008000", "canonical_extjson": "{\"d\" : {\"$numberDouble\": \"-0.0\"}}", "relaxed_extjson": "{\"d\" : -0.0}" }, { "description": "NaN", "canonical_bson": "10000000016400000000000000F87F00", "canonical_extjson": "{\"d\": {\"$numberDouble\": \"NaN\"}}", "relaxed_extjson": "{\"d\": {\"$numberDouble\": \"NaN\"}}", "lossy": true }, { "description": "NaN with payload", "canonical_bson": "10000000016400120000000000F87F00", "canonical_extjson": "{\"d\": {\"$numberDouble\": \"NaN\"}}", "relaxed_extjson": "{\"d\": {\"$numberDouble\": \"NaN\"}}", "lossy": true }, { "description": "Inf", "canonical_bson": "10000000016400000000000000F07F00", "canonical_extjson": "{\"d\": {\"$numberDouble\": \"Infinity\"}}", "relaxed_extjson": "{\"d\": {\"$numberDouble\": \"Infinity\"}}" }, { "description": "-Inf", "canonical_bson": "10000000016400000000000000F0FF00", "canonical_extjson": "{\"d\": {\"$numberDouble\": \"-Infinity\"}}", "relaxed_extjson": "{\"d\": {\"$numberDouble\": \"-Infinity\"}}" } ], "decodeErrors": [ { "description": "double truncated", "bson": "0B0000000164000000F03F00" } ] } mongodb-mongo-python-driver-509e9b7/test/bson_corpus/int32.json000066400000000000000000000026271462766011000246110ustar00rootroot00000000000000{ "description": "Int32 type", "bson_type": "0x10", "test_key": "i", "valid": [ { "description": "MinValue", "canonical_bson": "0C0000001069000000008000", "canonical_extjson": "{\"i\" : {\"$numberInt\": \"-2147483648\"}}", "relaxed_extjson": "{\"i\" : -2147483648}" }, { "description": "MaxValue", "canonical_bson": "0C000000106900FFFFFF7F00", "canonical_extjson": "{\"i\" : {\"$numberInt\": \"2147483647\"}}", "relaxed_extjson": "{\"i\" : 2147483647}" }, { "description": "-1", "canonical_bson": "0C000000106900FFFFFFFF00", "canonical_extjson": "{\"i\" : {\"$numberInt\": \"-1\"}}", "relaxed_extjson": "{\"i\" : -1}" }, { "description": "0", "canonical_bson": "0C0000001069000000000000", "canonical_extjson": "{\"i\" : {\"$numberInt\": \"0\"}}", "relaxed_extjson": "{\"i\" : 0}" }, { "description": "1", "canonical_bson": "0C0000001069000100000000", "canonical_extjson": "{\"i\" : {\"$numberInt\": \"1\"}}", "relaxed_extjson": "{\"i\" : 1}" } ], "decodeErrors": [ { "description": "Bad int32 field length", "bson": "090000001061000500" } ] } mongodb-mongo-python-driver-509e9b7/test/bson_corpus/int64.json000066400000000000000000000027621462766011000246160ustar00rootroot00000000000000{ "description": "Int64 type", "bson_type": "0x12", "test_key": "a", "valid": [ { "description": "MinValue", "canonical_bson": "10000000126100000000000000008000", "canonical_extjson": "{\"a\" : {\"$numberLong\" : \"-9223372036854775808\"}}", "relaxed_extjson": "{\"a\" : -9223372036854775808}" }, { "description": "MaxValue", "canonical_bson": "10000000126100FFFFFFFFFFFFFF7F00", "canonical_extjson": "{\"a\" : {\"$numberLong\" : \"9223372036854775807\"}}", "relaxed_extjson": "{\"a\" : 9223372036854775807}" }, { "description": "-1", "canonical_bson": "10000000126100FFFFFFFFFFFFFFFF00", "canonical_extjson": "{\"a\" : {\"$numberLong\" : \"-1\"}}", "relaxed_extjson": "{\"a\" : -1}" }, { "description": "0", "canonical_bson": "10000000126100000000000000000000", "canonical_extjson": "{\"a\" : {\"$numberLong\" : \"0\"}}", "relaxed_extjson": "{\"a\" : 0}" }, { "description": "1", "canonical_bson": "10000000126100010000000000000000", "canonical_extjson": "{\"a\" : {\"$numberLong\" : \"1\"}}", "relaxed_extjson": "{\"a\" : 1}" } ], "decodeErrors": [ { "description": "int64 field truncated", "bson": "0C0000001261001234567800" } ] } mongodb-mongo-python-driver-509e9b7/test/bson_corpus/maxkey.json000066400000000000000000000004231462766011000251400ustar00rootroot00000000000000{ "description": "Maxkey type", "bson_type": "0x7F", "test_key": "a", "valid": [ { "description": "Maxkey", "canonical_bson": "080000007F610000", "canonical_extjson": "{\"a\" : {\"$maxKey\" : 1}}" } ] } mongodb-mongo-python-driver-509e9b7/test/bson_corpus/minkey.json000066400000000000000000000004231462766011000251360ustar00rootroot00000000000000{ "description": "Minkey type", "bson_type": "0xFF", "test_key": "a", "valid": [ { "description": "Minkey", "canonical_bson": "08000000FF610000", "canonical_extjson": "{\"a\" : {\"$minKey\" : 1}}" } ] } mongodb-mongo-python-driver-509e9b7/test/bson_corpus/multi-type-deprecated.json000066400000000000000000000124541462766011000300600ustar00rootroot00000000000000{ "description": "Multiple types within the same document", "bson_type": "0x00", "deprecated": true, "valid": [ { "description": "All BSON types", "canonical_bson": "38020000075F69640057E193D7A9CC81B4027498B50E53796D626F6C000700000073796D626F6C0002537472696E670007000000737472696E670010496E743332002A00000012496E743634002A0000000000000001446F75626C6500000000000000F0BF0542696E617279001000000003A34C38F7C3ABEDC8A37814A992AB8DB60542696E61727955736572446566696E656400050000008001020304050D436F6465000E00000066756E6374696F6E2829207B7D000F436F64655769746853636F7065001B0000000E00000066756E6374696F6E2829207B7D00050000000003537562646F63756D656E74001200000002666F6F0004000000626172000004417272617900280000001030000100000010310002000000103200030000001033000400000010340005000000001154696D657374616D7000010000002A0000000B5265676578007061747465726E0000094461746574696D6545706F6368000000000000000000094461746574696D65506F73697469766500FFFFFF7F00000000094461746574696D654E656761746976650000000080FFFFFFFF085472756500010846616C736500000C4442506F696E746572000B000000636F6C6C656374696F6E0057E193D7A9CC81B4027498B1034442526566003D0000000224726566000B000000636F6C6C656374696F6E00072469640057FD71E96E32AB4225B723FB02246462000900000064617461626173650000FF4D696E6B6579007F4D61786B6579000A4E756C6C0006556E646566696E65640000", "converted_bson": "48020000075f69640057e193d7a9cc81b4027498b50253796d626f6c000700000073796d626f6c0002537472696e670007000000737472696e670010496e743332002a00000012496e743634002a0000000000000001446f75626c6500000000000000f0bf0542696e617279001000000003a34c38f7c3abedc8a37814a992ab8db60542696e61727955736572446566696e656400050000008001020304050d436f6465000e00000066756e6374696f6e2829207b7d000f436f64655769746853636f7065001b0000000e00000066756e6374696f6e2829207b7d00050000000003537562646f63756d656e74001200000002666f6f0004000000626172000004417272617900280000001030000100000010310002000000103200030000001033000400000010340005000000001154696d657374616d7000010000002a0000000b5265676578007061747465726e0000094461746574696d6545706f6368000000000000000000094461746574696d65506f73697469766500ffffff7f00000000094461746574696d654e656761746976650000000080ffffffff085472756500010846616c73650000034442506f696e746572002b0000000224726566000b000000636f6c6c656374696f6e00072469640057e193d7a9cc81b4027498b100034442526566003d0000000224726566000b000000636f6c6c656374696f6e00072469640057fd71e96e32ab4225b723fb02246462000900000064617461626173650000ff4d696e6b6579007f4d61786b6579000a4e756c6c000a556e646566696e65640000", "canonical_extjson": "{\"_id\": {\"$oid\": \"57e193d7a9cc81b4027498b5\"}, \"Symbol\": {\"$symbol\": \"symbol\"}, \"String\": \"string\", \"Int32\": {\"$numberInt\": \"42\"}, \"Int64\": {\"$numberLong\": \"42\"}, \"Double\": {\"$numberDouble\": \"-1.0\"}, \"Binary\": { \"$binary\" : {\"base64\": \"o0w498Or7cijeBSpkquNtg==\", \"subType\": \"03\"}}, \"BinaryUserDefined\": { \"$binary\" : {\"base64\": \"AQIDBAU=\", \"subType\": \"80\"}}, \"Code\": {\"$code\": \"function() {}\"}, \"CodeWithScope\": {\"$code\": \"function() {}\", \"$scope\": {}}, \"Subdocument\": {\"foo\": \"bar\"}, \"Array\": [{\"$numberInt\": \"1\"}, {\"$numberInt\": \"2\"}, {\"$numberInt\": \"3\"}, {\"$numberInt\": \"4\"}, {\"$numberInt\": \"5\"}], \"Timestamp\": {\"$timestamp\": {\"t\": 42, \"i\": 1}}, \"Regex\": {\"$regularExpression\": {\"pattern\": \"pattern\", \"options\": \"\"}}, \"DatetimeEpoch\": {\"$date\": {\"$numberLong\": \"0\"}}, \"DatetimePositive\": {\"$date\": {\"$numberLong\": \"2147483647\"}}, \"DatetimeNegative\": {\"$date\": {\"$numberLong\": \"-2147483648\"}}, \"True\": true, \"False\": false, \"DBPointer\": {\"$dbPointer\": {\"$ref\": \"collection\", \"$id\": {\"$oid\": \"57e193d7a9cc81b4027498b1\"}}}, \"DBRef\": {\"$ref\": \"collection\", \"$id\": {\"$oid\": \"57fd71e96e32ab4225b723fb\"}, \"$db\": \"database\"}, \"Minkey\": {\"$minKey\": 1}, \"Maxkey\": {\"$maxKey\": 1}, \"Null\": null, \"Undefined\": {\"$undefined\": true}}", "converted_extjson": "{\"_id\": {\"$oid\": \"57e193d7a9cc81b4027498b5\"}, \"Symbol\": \"symbol\", \"String\": \"string\", \"Int32\": {\"$numberInt\": \"42\"}, \"Int64\": {\"$numberLong\": \"42\"}, \"Double\": {\"$numberDouble\": \"-1.0\"}, \"Binary\": { \"$binary\" : {\"base64\": \"o0w498Or7cijeBSpkquNtg==\", \"subType\": \"03\"}}, \"BinaryUserDefined\": { \"$binary\" : {\"base64\": \"AQIDBAU=\", \"subType\": \"80\"}}, \"Code\": {\"$code\": \"function() {}\"}, \"CodeWithScope\": {\"$code\": \"function() {}\", \"$scope\": {}}, \"Subdocument\": {\"foo\": \"bar\"}, \"Array\": [{\"$numberInt\": \"1\"}, {\"$numberInt\": \"2\"}, {\"$numberInt\": \"3\"}, {\"$numberInt\": \"4\"}, {\"$numberInt\": \"5\"}], \"Timestamp\": {\"$timestamp\": {\"t\": 42, \"i\": 1}}, \"Regex\": {\"$regularExpression\": {\"pattern\": \"pattern\", \"options\": \"\"}}, \"DatetimeEpoch\": {\"$date\": {\"$numberLong\": \"0\"}}, \"DatetimePositive\": {\"$date\": {\"$numberLong\": \"2147483647\"}}, \"DatetimeNegative\": {\"$date\": {\"$numberLong\": \"-2147483648\"}}, \"True\": true, \"False\": false, \"DBPointer\": {\"$ref\": \"collection\", \"$id\": {\"$oid\": \"57e193d7a9cc81b4027498b1\"}}, \"DBRef\": {\"$ref\": \"collection\", \"$id\": {\"$oid\": \"57fd71e96e32ab4225b723fb\"}, \"$db\": \"database\"}, \"Minkey\": {\"$minKey\": 1}, \"Maxkey\": {\"$maxKey\": 1}, \"Null\": null, \"Undefined\": null}" } ] } mongodb-mongo-python-driver-509e9b7/test/bson_corpus/multi-type.json000066400000000000000000000046451462766011000257650ustar00rootroot00000000000000{ "description": "Multiple types within the same document", "bson_type": "0x00", "valid": [ { "description": "All BSON types", "canonical_bson": "F4010000075F69640057E193D7A9CC81B4027498B502537472696E670007000000737472696E670010496E743332002A00000012496E743634002A0000000000000001446F75626C6500000000000000F0BF0542696E617279001000000003A34C38F7C3ABEDC8A37814A992AB8DB60542696E61727955736572446566696E656400050000008001020304050D436F6465000E00000066756E6374696F6E2829207B7D000F436F64655769746853636F7065001B0000000E00000066756E6374696F6E2829207B7D00050000000003537562646F63756D656E74001200000002666F6F0004000000626172000004417272617900280000001030000100000010310002000000103200030000001033000400000010340005000000001154696D657374616D7000010000002A0000000B5265676578007061747465726E0000094461746574696D6545706F6368000000000000000000094461746574696D65506F73697469766500FFFFFF7F00000000094461746574696D654E656761746976650000000080FFFFFFFF085472756500010846616C73650000034442526566003D0000000224726566000B000000636F6C6C656374696F6E00072469640057FD71E96E32AB4225B723FB02246462000900000064617461626173650000FF4D696E6B6579007F4D61786B6579000A4E756C6C0000", "canonical_extjson": "{\"_id\": {\"$oid\": \"57e193d7a9cc81b4027498b5\"}, \"String\": \"string\", \"Int32\": {\"$numberInt\": \"42\"}, \"Int64\": {\"$numberLong\": \"42\"}, \"Double\": {\"$numberDouble\": \"-1.0\"}, \"Binary\": { \"$binary\" : {\"base64\": \"o0w498Or7cijeBSpkquNtg==\", \"subType\": \"03\"}}, \"BinaryUserDefined\": { \"$binary\" : {\"base64\": \"AQIDBAU=\", \"subType\": \"80\"}}, \"Code\": {\"$code\": \"function() {}\"}, \"CodeWithScope\": {\"$code\": \"function() {}\", \"$scope\": {}}, \"Subdocument\": {\"foo\": \"bar\"}, \"Array\": [{\"$numberInt\": \"1\"}, {\"$numberInt\": \"2\"}, {\"$numberInt\": \"3\"}, {\"$numberInt\": \"4\"}, {\"$numberInt\": \"5\"}], \"Timestamp\": {\"$timestamp\": {\"t\": 42, \"i\": 1}}, \"Regex\": {\"$regularExpression\": {\"pattern\": \"pattern\", \"options\": \"\"}}, \"DatetimeEpoch\": {\"$date\": {\"$numberLong\": \"0\"}}, \"DatetimePositive\": {\"$date\": {\"$numberLong\": \"2147483647\"}}, \"DatetimeNegative\": {\"$date\": {\"$numberLong\": \"-2147483648\"}}, \"True\": true, \"False\": false, \"DBRef\": {\"$ref\": \"collection\", \"$id\": {\"$oid\": \"57fd71e96e32ab4225b723fb\"}, \"$db\": \"database\"}, \"Minkey\": {\"$minKey\": 1}, \"Maxkey\": {\"$maxKey\": 1}, \"Null\": null}" } ] } mongodb-mongo-python-driver-509e9b7/test/bson_corpus/null.json000066400000000000000000000004021462766011000246110ustar00rootroot00000000000000{ "description": "Null type", "bson_type": "0x0A", "test_key": "a", "valid": [ { "description": "Null", "canonical_bson": "080000000A610000", "canonical_extjson": "{\"a\" : null}" } ] } mongodb-mongo-python-driver-509e9b7/test/bson_corpus/oid.json000066400000000000000000000016221462766011000244170ustar00rootroot00000000000000{ "description": "ObjectId", "bson_type": "0x07", "test_key": "a", "valid": [ { "description": "All zeroes", "canonical_bson": "1400000007610000000000000000000000000000", "canonical_extjson": "{\"a\" : {\"$oid\" : \"000000000000000000000000\"}}" }, { "description": "All ones", "canonical_bson": "14000000076100FFFFFFFFFFFFFFFFFFFFFFFF00", "canonical_extjson": "{\"a\" : {\"$oid\" : \"ffffffffffffffffffffffff\"}}" }, { "description": "Random", "canonical_bson": "1400000007610056E1FC72E0C917E9C471416100", "canonical_extjson": "{\"a\" : {\"$oid\" : \"56e1fc72e0c917e9c4714161\"}}" } ], "decodeErrors": [ { "description": "OID truncated", "bson": "1200000007610056E1FC72E0C917E9C471" } ] } mongodb-mongo-python-driver-509e9b7/test/bson_corpus/regex.json000066400000000000000000000062011462766011000247540ustar00rootroot00000000000000{ "description": "Regular Expression type", "bson_type": "0x0B", "test_key": "a", "valid": [ { "description": "empty regex with no options", "canonical_bson": "0A0000000B6100000000", "canonical_extjson": "{\"a\" : {\"$regularExpression\" : { \"pattern\": \"\", \"options\" : \"\"}}}" }, { "description": "regex without options", "canonical_bson": "0D0000000B6100616263000000", "canonical_extjson": "{\"a\" : {\"$regularExpression\" : { \"pattern\": \"abc\", \"options\" : \"\"}}}" }, { "description": "regex with options", "canonical_bson": "0F0000000B610061626300696D0000", "canonical_extjson": "{\"a\" : {\"$regularExpression\" : { \"pattern\": \"abc\", \"options\" : \"im\"}}}" }, { "description": "regex with options (keys reversed)", "canonical_bson": "0F0000000B610061626300696D0000", "canonical_extjson": "{\"a\" : {\"$regularExpression\" : { \"pattern\": \"abc\", \"options\" : \"im\"}}}", "degenerate_extjson": "{\"a\" : {\"$regularExpression\" : {\"options\" : \"im\", \"pattern\": \"abc\"}}}" }, { "description": "regex with slash", "canonical_bson": "110000000B610061622F636400696D0000", "canonical_extjson": "{\"a\" : {\"$regularExpression\" : { \"pattern\": \"ab/cd\", \"options\" : \"im\"}}}" }, { "description": "flags not alphabetized", "degenerate_bson": "100000000B6100616263006D69780000", "canonical_bson": "100000000B610061626300696D780000", "canonical_extjson": "{\"a\" : {\"$regularExpression\" : { \"pattern\": \"abc\", \"options\" : \"imx\"}}}", "degenerate_extjson": "{\"a\" : {\"$regularExpression\" : { \"pattern\": \"abc\", \"options\" : \"mix\"}}}" }, { "description" : "Required escapes", "canonical_bson" : "100000000B610061625C226162000000", "canonical_extjson": "{\"a\" : {\"$regularExpression\" : { \"pattern\": \"ab\\\\\\\"ab\", \"options\" : \"\"}}}" }, { "description" : "Regular expression as value of $regex query operator", "canonical_bson" : "180000000B247265676578007061747465726E0069780000", "canonical_extjson": "{\"$regex\" : {\"$regularExpression\" : { \"pattern\": \"pattern\", \"options\" : \"ix\"}}}" }, { "description" : "Regular expression as value of $regex query operator with $options", "canonical_bson" : "270000000B247265676578007061747465726E000002246F7074696F6E73000300000069780000", "canonical_extjson": "{\"$regex\" : {\"$regularExpression\" : { \"pattern\": \"pattern\", \"options\" : \"\"}}, \"$options\" : \"ix\"}" } ], "decodeErrors": [ { "description": "Null byte in pattern string", "bson": "0F0000000B610061006300696D0000" }, { "description": "Null byte in flags string", "bson": "100000000B61006162630069006D0000" } ] } mongodb-mongo-python-driver-509e9b7/test/bson_corpus/string.json000066400000000000000000000053741462766011000251620ustar00rootroot00000000000000{ "description": "String", "bson_type": "0x02", "test_key": "a", "valid": [ { "description": "Empty string", "canonical_bson": "0D000000026100010000000000", "canonical_extjson": "{\"a\" : \"\"}" }, { "description": "Single character", "canonical_bson": "0E00000002610002000000620000", "canonical_extjson": "{\"a\" : \"b\"}" }, { "description": "Multi-character", "canonical_bson": "190000000261000D0000006162616261626162616261620000", "canonical_extjson": "{\"a\" : \"abababababab\"}" }, { "description": "two-byte UTF-8 (\u00e9)", "canonical_bson": "190000000261000D000000C3A9C3A9C3A9C3A9C3A9C3A90000", "canonical_extjson": "{\"a\" : \"\\u00e9\\u00e9\\u00e9\\u00e9\\u00e9\\u00e9\"}" }, { "description": "three-byte UTF-8 (\u2606)", "canonical_bson": "190000000261000D000000E29886E29886E29886E298860000", "canonical_extjson": "{\"a\" : \"\\u2606\\u2606\\u2606\\u2606\"}" }, { "description": "Embedded nulls", "canonical_bson": "190000000261000D0000006162006261620062616261620000", "canonical_extjson": "{\"a\" : \"ab\\u0000bab\\u0000babab\"}" }, { "description": "Required escapes", "canonical_bson" : "320000000261002600000061625C220102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F61620000", "canonical_extjson" : "{\"a\":\"ab\\\\\\\"\\u0001\\u0002\\u0003\\u0004\\u0005\\u0006\\u0007\\b\\t\\n\\u000b\\f\\r\\u000e\\u000f\\u0010\\u0011\\u0012\\u0013\\u0014\\u0015\\u0016\\u0017\\u0018\\u0019\\u001a\\u001b\\u001c\\u001d\\u001e\\u001fab\"}" } ], "decodeErrors": [ { "description": "bad string length: 0 (but no 0x00 either)", "bson": "0C0000000261000000000000" }, { "description": "bad string length: -1", "bson": "0C000000026100FFFFFFFF00" }, { "description": "bad string length: eats terminator", "bson": "10000000026100050000006200620000" }, { "description": "bad string length: longer than rest of document", "bson": "120000000200FFFFFF00666F6F6261720000" }, { "description": "string is not null-terminated", "bson": "1000000002610004000000616263FF00" }, { "description": "empty string, but extra null", "bson": "0E00000002610001000000000000" }, { "description": "invalid UTF-8", "bson": "0E00000002610002000000E90000" } ] } mongodb-mongo-python-driver-509e9b7/test/bson_corpus/symbol.json000066400000000000000000000062401462766011000251520ustar00rootroot00000000000000{ "description": "Symbol", "bson_type": "0x0E", "deprecated": true, "test_key": "a", "valid": [ { "description": "Empty string", "canonical_bson": "0D0000000E6100010000000000", "canonical_extjson": "{\"a\": {\"$symbol\": \"\"}}", "converted_bson": "0D000000026100010000000000", "converted_extjson": "{\"a\": \"\"}" }, { "description": "Single character", "canonical_bson": "0E0000000E610002000000620000", "canonical_extjson": "{\"a\": {\"$symbol\": \"b\"}}", "converted_bson": "0E00000002610002000000620000", "converted_extjson": "{\"a\": \"b\"}" }, { "description": "Multi-character", "canonical_bson": "190000000E61000D0000006162616261626162616261620000", "canonical_extjson": "{\"a\": {\"$symbol\": \"abababababab\"}}", "converted_bson": "190000000261000D0000006162616261626162616261620000", "converted_extjson": "{\"a\": \"abababababab\"}" }, { "description": "two-byte UTF-8 (\u00e9)", "canonical_bson": "190000000E61000D000000C3A9C3A9C3A9C3A9C3A9C3A90000", "canonical_extjson": "{\"a\": {\"$symbol\": \"éééééé\"}}", "converted_bson": "190000000261000D000000C3A9C3A9C3A9C3A9C3A9C3A90000", "converted_extjson": "{\"a\": \"éééééé\"}" }, { "description": "three-byte UTF-8 (\u2606)", "canonical_bson": "190000000E61000D000000E29886E29886E29886E298860000", "canonical_extjson": "{\"a\": {\"$symbol\": \"☆☆☆☆\"}}", "converted_bson": "190000000261000D000000E29886E29886E29886E298860000", "converted_extjson": "{\"a\": \"☆☆☆☆\"}" }, { "description": "Embedded nulls", "canonical_bson": "190000000E61000D0000006162006261620062616261620000", "canonical_extjson": "{\"a\": {\"$symbol\": \"ab\\u0000bab\\u0000babab\"}}", "converted_bson": "190000000261000D0000006162006261620062616261620000", "converted_extjson": "{\"a\": \"ab\\u0000bab\\u0000babab\"}" } ], "decodeErrors": [ { "description": "bad symbol length: 0 (but no 0x00 either)", "bson": "0C0000000E61000000000000" }, { "description": "bad symbol length: -1", "bson": "0C0000000E6100FFFFFFFF00" }, { "description": "bad symbol length: eats terminator", "bson": "100000000E6100050000006200620000" }, { "description": "bad symbol length: longer than rest of document", "bson": "120000000E00FFFFFF00666F6F6261720000" }, { "description": "symbol is not null-terminated", "bson": "100000000E610004000000616263FF00" }, { "description": "empty symbol, but extra null", "bson": "0E0000000E610001000000000000" }, { "description": "invalid UTF-8", "bson": "0E0000000E610002000000E90000" } ] } mongodb-mongo-python-driver-509e9b7/test/bson_corpus/timestamp.json000066400000000000000000000026651462766011000256570ustar00rootroot00000000000000{ "description": "Timestamp type", "bson_type": "0x11", "test_key": "a", "valid": [ { "description": "Timestamp: (123456789, 42)", "canonical_bson": "100000001161002A00000015CD5B0700", "canonical_extjson": "{\"a\" : {\"$timestamp\" : {\"t\" : 123456789, \"i\" : 42} } }" }, { "description": "Timestamp: (123456789, 42) (keys reversed)", "canonical_bson": "100000001161002A00000015CD5B0700", "canonical_extjson": "{\"a\" : {\"$timestamp\" : {\"t\" : 123456789, \"i\" : 42} } }", "degenerate_extjson": "{\"a\" : {\"$timestamp\" : {\"i\" : 42, \"t\" : 123456789} } }" }, { "description": "Timestamp with high-order bit set on both seconds and increment", "canonical_bson": "10000000116100FFFFFFFFFFFFFFFF00", "canonical_extjson": "{\"a\" : {\"$timestamp\" : {\"t\" : 4294967295, \"i\" : 4294967295} } }" }, { "description": "Timestamp with high-order bit set on both seconds and increment (not UINT32_MAX)", "canonical_bson": "1000000011610000286BEE00286BEE00", "canonical_extjson": "{\"a\" : {\"$timestamp\" : {\"t\" : 4000000000, \"i\" : 4000000000} } }" } ], "decodeErrors": [ { "description": "Truncated timestamp field", "bson": "0f0000001161002A00000015CD5B00" } ] } mongodb-mongo-python-driver-509e9b7/test/bson_corpus/top.json000066400000000000000000000246401462766011000244530ustar00rootroot00000000000000{ "description": "Top-level document validity", "bson_type": "0x00", "valid": [ { "description": "Dollar-prefixed key in top-level document", "canonical_bson": "0F00000010246B6579002A00000000", "canonical_extjson": "{\"$key\": {\"$numberInt\": \"42\"}}" }, { "description": "Dollar as key in top-level document", "canonical_bson": "0E00000002240002000000610000", "canonical_extjson": "{\"$\": \"a\"}" }, { "description": "Dotted key in top-level document", "canonical_bson": "1000000002612E620002000000630000", "canonical_extjson": "{\"a.b\": \"c\"}" }, { "description": "Dot as key in top-level document", "canonical_bson": "0E000000022E0002000000610000", "canonical_extjson": "{\".\": \"a\"}" } ], "decodeErrors": [ { "description": "An object size that's too small to even include the object size, but is a well-formed, empty object", "bson": "0100000000" }, { "description": "An object size that's only enough for the object size, but is a well-formed, empty object", "bson": "0400000000" }, { "description": "One object, with length shorter than size (missing EOO)", "bson": "05000000" }, { "description": "One object, sized correctly, with a spot for an EOO, but the EOO is 0x01", "bson": "0500000001" }, { "description": "One object, sized correctly, with a spot for an EOO, but the EOO is 0xff", "bson": "05000000FF" }, { "description": "One object, sized correctly, with a spot for an EOO, but the EOO is 0x70", "bson": "0500000070" }, { "description": "Byte count is zero (with non-zero input length)", "bson": "00000000000000000000" }, { "description": "Stated length exceeds byte count, with truncated document", "bson": "1200000002666F6F0004000000626172" }, { "description": "Stated length less than byte count, with garbage after envelope", "bson": "1200000002666F6F00040000006261720000DEADBEEF" }, { "description": "Stated length exceeds byte count, with valid envelope", "bson": "1300000002666F6F00040000006261720000" }, { "description": "Stated length less than byte count, with valid envelope", "bson": "1100000002666F6F00040000006261720000" }, { "description": "Invalid BSON type low range", "bson": "07000000000000" }, { "description": "Invalid BSON type high range", "bson": "07000000800000" }, { "description": "Document truncated mid-key", "bson": "1200000002666F" }, { "description": "Null byte in document key", "bson": "0D000000107800000100000000" } ], "parseErrors": [ { "description" : "Bad $regularExpression (extra field)", "string" : "{\"a\" : {\"$regularExpression\": {\"pattern\": \"abc\", \"options\": \"\", \"unrelated\": true}}}" }, { "description" : "Bad $regularExpression (missing options field)", "string" : "{\"a\" : {\"$regularExpression\": {\"pattern\": \"abc\"}}}" }, { "description": "Bad $regularExpression (pattern is number, not string)", "string": "{\"x\" : {\"$regularExpression\" : { \"pattern\": 42, \"options\" : \"\"}}}" }, { "description": "Bad $regularExpression (options are number, not string)", "string": "{\"x\" : {\"$regularExpression\" : { \"pattern\": \"a\", \"options\" : 0}}}" }, { "description" : "Bad $regularExpression (missing pattern field)", "string" : "{\"a\" : {\"$regularExpression\": {\"options\":\"ix\"}}}" }, { "description": "Bad $oid (number, not string)", "string": "{\"a\" : {\"$oid\" : 42}}" }, { "description": "Bad $oid (extra field)", "string": "{\"a\" : {\"$oid\" : \"56e1fc72e0c917e9c4714161\", \"unrelated\": true}}" }, { "description": "Bad $numberInt (number, not string)", "string": "{\"a\" : {\"$numberInt\" : 42}}" }, { "description": "Bad $numberInt (extra field)", "string": "{\"a\" : {\"$numberInt\" : \"42\", \"unrelated\": true}}" }, { "description": "Bad $numberLong (number, not string)", "string": "{\"a\" : {\"$numberLong\" : 42}}" }, { "description": "Bad $numberLong (extra field)", "string": "{\"a\" : {\"$numberLong\" : \"42\", \"unrelated\": true}}" }, { "description": "Bad $numberDouble (number, not string)", "string": "{\"a\" : {\"$numberDouble\" : 42}}" }, { "description": "Bad $numberDouble (extra field)", "string": "{\"a\" : {\"$numberDouble\" : \".1\", \"unrelated\": true}}" }, { "description": "Bad $numberDecimal (number, not string)", "string": "{\"a\" : {\"$numberDecimal\" : 42}}" }, { "description": "Bad $numberDecimal (extra field)", "string": "{\"a\" : {\"$numberDecimal\" : \".1\", \"unrelated\": true}}" }, { "description": "Bad $binary (binary is number, not string)", "string": "{\"x\" : {\"$binary\" : {\"base64\" : 0, \"subType\" : \"00\"}}}" }, { "description": "Bad $binary (type is number, not string)", "string": "{\"x\" : {\"$binary\" : {\"base64\" : \"\", \"subType\" : 0}}}" }, { "description": "Bad $binary (missing $type)", "string": "{\"x\" : {\"$binary\" : {\"base64\" : \"//8=\"}}}" }, { "description": "Bad $binary (missing $binary)", "string": "{\"x\" : {\"$binary\" : {\"subType\" : \"00\"}}}" }, { "description": "Bad $binary (extra field)", "string": "{\"x\" : {\"$binary\" : {\"base64\" : \"//8=\", \"subType\" : 0, \"unrelated\": true}}}" }, { "description": "Bad $code (type is number, not string)", "string": "{\"a\" : {\"$code\" : 42}}" }, { "description": "Bad $code (type is number, not string) when $scope is also present", "string": "{\"a\" : {\"$code\" : 42, \"$scope\" : {}}}" }, { "description": "Bad $code (extra field)", "string": "{\"a\" : {\"$code\" : \"\", \"unrelated\": true}}" }, { "description": "Bad $code with $scope (scope is number, not doc)", "string": "{\"x\" : {\"$code\" : \"\", \"$scope\" : 42}}" }, { "description": "Bad $timestamp (type is number, not doc)", "string": "{\"a\" : {\"$timestamp\" : 42} }" }, { "description": "Bad $timestamp ('t' type is string, not number)", "string": "{\"a\" : {\"$timestamp\" : {\"t\" : \"123456789\", \"i\" : 42} } }" }, { "description": "Bad $timestamp ('i' type is string, not number)", "string": "{\"a\" : {\"$timestamp\" : {\"t\" : 123456789, \"i\" : \"42\"} } }" }, { "description": "Bad $timestamp (extra field at same level as $timestamp)", "string": "{\"a\" : {\"$timestamp\" : {\"t\" : \"123456789\", \"i\" : \"42\"}, \"unrelated\": true } }" }, { "description": "Bad $timestamp (extra field at same level as t and i)", "string": "{\"a\" : {\"$timestamp\" : {\"t\" : \"123456789\", \"i\" : \"42\", \"unrelated\": true} } }" }, { "description": "Bad $timestamp (missing t)", "string": "{\"a\" : {\"$timestamp\" : {\"i\" : \"42\"} } }" }, { "description": "Bad $timestamp (missing i)", "string": "{\"a\" : {\"$timestamp\" : {\"t\" : \"123456789\"} } }" }, { "description": "Bad $date (number, not string or hash)", "string": "{\"a\" : {\"$date\" : 42}}" }, { "description": "Bad $date (extra field)", "string": "{\"a\" : {\"$date\" : {\"$numberLong\" : \"1356351330501\"}, \"unrelated\": true}}" }, { "description": "Bad $minKey (boolean, not integer)", "string": "{\"a\" : {\"$minKey\" : true}}" }, { "description": "Bad $minKey (wrong integer)", "string": "{\"a\" : {\"$minKey\" : 0}}" }, { "description": "Bad $minKey (extra field)", "string": "{\"a\" : {\"$minKey\" : 1, \"unrelated\": true}}" }, { "description": "Bad $maxKey (boolean, not integer)", "string": "{\"a\" : {\"$maxKey\" : true}}" }, { "description": "Bad $maxKey (wrong integer)", "string": "{\"a\" : {\"$maxKey\" : 0}}" }, { "description": "Bad $maxKey (extra field)", "string": "{\"a\" : {\"$maxKey\" : 1, \"unrelated\": true}}" }, { "description": "Bad DBpointer (extra field)", "string": "{\"a\": {\"$dbPointer\": {\"a\": {\"$numberInt\": \"1\"}, \"$id\": {\"$oid\": \"56e1fc72e0c917e9c4714161\"}, \"c\": {\"$numberInt\": \"2\"}, \"$ref\": \"b\"}}}" }, { "description" : "Null byte in document key", "string" : "{\"a\\u0000\": 1 }" }, { "description" : "Null byte in sub-document key", "string" : "{\"a\" : {\"b\\u0000\": 1 }}" }, { "description": "Null byte in $regularExpression pattern", "string": "{\"a\" : {\"$regularExpression\" : { \"pattern\": \"b\\u0000\", \"options\" : \"i\"}}}" }, { "description": "Null byte in $regularExpression options", "string": "{\"a\" : {\"$regularExpression\" : { \"pattern\": \"b\", \"options\" : \"i\\u0000\"}}}" } ] } mongodb-mongo-python-driver-509e9b7/test/bson_corpus/undefined.json000066400000000000000000000006511462766011000256060ustar00rootroot00000000000000{ "description": "Undefined type (deprecated)", "bson_type": "0x06", "deprecated": true, "test_key": "a", "valid": [ { "description": "Undefined", "canonical_bson": "0800000006610000", "canonical_extjson": "{\"a\" : {\"$undefined\" : true}}", "converted_bson": "080000000A610000", "converted_extjson": "{\"a\" : null}" } ] } mongodb-mongo-python-driver-509e9b7/test/certificates/000077500000000000000000000000001462766011000230615ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/certificates/ca.pem000066400000000000000000000023711462766011000241520ustar00rootroot00000000000000-----BEGIN CERTIFICATE----- MIIDfzCCAmegAwIBAgIDB1MGMA0GCSqGSIb3DQEBCwUAMHkxGzAZBgNVBAMTEkRy aXZlcnMgVGVzdGluZyBDQTEQMA4GA1UECxMHRHJpdmVyczEQMA4GA1UEChMHTW9u Z29EQjEWMBQGA1UEBxMNTmV3IFlvcmsgQ2l0eTERMA8GA1UECBMITmV3IFlvcmsx CzAJBgNVBAYTAlVTMB4XDTE5MDUyMjIwMjMxMVoXDTM5MDUyMjIwMjMxMVoweTEb MBkGA1UEAxMSRHJpdmVycyBUZXN0aW5nIENBMRAwDgYDVQQLEwdEcml2ZXJzMRAw DgYDVQQKEwdNb25nb0RCMRYwFAYDVQQHEw1OZXcgWW9yayBDaXR5MREwDwYDVQQI EwhOZXcgWW9yazELMAkGA1UEBhMCVVMwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw ggEKAoIBAQCl7VN+WsQfHlwapcOpTLZVoeMAl1LTbWTFuXSAavIyy0W1Ytky1UP/ bxCSW0mSWwCgqoJ5aXbAvrNRp6ArWu3LsTQIEcD3pEdrFIVQhYzWUs9fXqPyI9k+ QNNQ+MRFKeGteTPYwF2eVEtPzUHU5ws3+OKp1m6MCLkwAG3RBFUAfddUnLvGoZiT pd8/eNabhgHvdrCw+tYFCWvSjz7SluEVievpQehrSEPKe8DxJq/IM3tSl3tdylzT zeiKNO7c7LuQrgjAfrZl7n2SriHIlNmqiDR/kdd8+TxBuxjFlcf2WyHCO3lIcIgH KXTlhUCg50KfHaxHu05Qw0x8869yIzqbAgMBAAGjEDAOMAwGA1UdEwQFMAMBAf8w DQYJKoZIhvcNAQELBQADggEBAEHuhTL8KQZcKCTSJbYA9MgZj7U32arMGBbc1hiq VBREwvdVz4+9tIyWMzN9R/YCKmUTnCq8z3wTlC8kBtxYn/l4Tj8nJYcgLJjQ0Fwe gT564CmvkUat8uXPz6olOCdwkMpJ9Sj62i0mpgXJdBfxKQ6TZ9yGz6m3jannjZpN LchB7xSAEWtqUgvNusq0dApJsf4n7jZ+oBZVaQw2+tzaMfaLqHgMwcu1FzA8UKCD sxCgIsZUs8DdxaD418Ot6nPfheOTqe24n+TTa+Z6O0W0QtnofJBx7tmAo1aEc57i 77s89pfwIJetpIlhzNSMKurCAocFCJMJLAASJFuu6dyDvPo= -----END CERTIFICATE----- mongodb-mongo-python-driver-509e9b7/test/certificates/client.pem000066400000000000000000000056141462766011000250500ustar00rootroot00000000000000-----BEGIN RSA PRIVATE KEY----- MIIEpAIBAAKCAQEAsNS8UEuin7/K29jXfIOLpIoh1jEyWVqxiie2Onx7uJJKcoKo khA3XeUnVN0k6X5MwYWcN52xcns7LYtyt06nRpTG2/emoV44w9uKTuHsvUbiOwSV m/ToKQQ4FUFZoqorXH+ZmJuIpJNfoW+3CkE1vEDCIecIq6BNg5ySsPtvSuSJHGjp mc7/5ZUDvFE2aJ8QbJU3Ws0HXiEb6ymi048LlzEL2VKX3w6mqqh+7dcZGAy7qYk2 5FZ9ktKvCeQau7mTyU1hsPrKFiKtMN8Q2ZAItX13asw5/IeSTq2LgLFHlbj5Kpq4 GmLdNCshzH5X7Ew3IYM8EHmsX8dmD6mhv7vpVwIDAQABAoIBABOdpb4qhcG+3twA c/cGCKmaASLnljQ/UU6IFTjrsjXJVKTbRaPeVKX/05sgZQXZ0t3s2mV5AsQ2U1w8 Cd+3w+qaemzQThW8hAOGCROzEDX29QWi/o2sX0ydgTMqaq0Wv3SlWv6I0mGfT45y /BURIsrdTCvCmz2erLqa1dL4MWJXRFjT9UTs5twlecIOM2IHKoGGagFhymRK4kDe wTRC9fpfoAgyfus3pCO/wi/F8yKGPDEwY+zgkhrJQ+kSeki7oKdGD1H540vB8gRt EIqssE0Y6rEYf97WssQlxJgvoJBDSftOijS6mwvoasDUwfFqyyPiirawXWWhHXkc DjIi/XECgYEA5xfjilw9YyM2UGQNESbNNunPcj7gDZbN347xJwmYmi9AUdPLt9xN 3XaMqqR22k1DUOxC/5hH0uiXir7mDfqmC+XS/ic/VOsa3CDWejkEnyGLiwSHY502 wD/xWgHwUiGVAG9HY64vnDGm6L3KGXA2oqxanL4V0+0+Ht49pZ16i8sCgYEAw+Ox CHGtpkzjCP/z8xr+1VTSdpc/4CP2HONnYopcn48KfQnf7Nale69/1kZpypJlvQSG eeA3jMGigNJEkb8/kaVoRLCisXcwLc0XIfCTeiK6FS0Ka30D/84Qm8UsHxRdpGkM kYITAa2r64tgRL8as4/ukeXBKE+oOhX43LeEfyUCgYBkf7IX2Ndlhsm3GlvIarxy NipeP9PGdR/hKlPbq0OvQf9R1q7QrcE7H7Q6/b0mYNV2mtjkOQB7S2WkFDMOP0P5 BqDEoKLdNkV/F9TOYH+PCNKbyYNrodJOt0Ap6Y/u1+Xpw3sjcXwJDFrO+sKqX2+T PStG4S+y84jBedsLbDoAEwKBgQCTz7/KC11o2yOFqv09N+WKvBKDgeWlD/2qFr3w UU9K5viXGVhqshz0k5z25vL09Drowf1nAZVpFMO2SPOMtq8VC6b+Dfr1xmYIaXVH Gu1tf77CM9Zk/VSDNc66e7GrUgbHBK2DLo+A+Ld9aRIfTcSsMbNnS+LQtCrQibvb cG7+MQKBgQCY11oMT2dUekoZEyW4no7W5D74lR8ztMjp/fWWTDo/AZGPBY6cZoZF IICrzYtDT/5BzB0Jh1f4O9ZQkm5+OvlFbmoZoSbMzHL3oJCBOY5K0/kdGXL46WWh IRJSYakNU6VIS7SjDpKgm9D8befQqZeoSggSjIIULIiAtYgS80vmGA== -----END RSA PRIVATE KEY----- -----BEGIN CERTIFICATE----- MIIDgzCCAmugAwIBAgIDAxOUMA0GCSqGSIb3DQEBCwUAMHkxGzAZBgNVBAMTEkRy aXZlcnMgVGVzdGluZyBDQTEQMA4GA1UECxMHRHJpdmVyczEQMA4GA1UEChMHTW9u Z29EQjEWMBQGA1UEBxMNTmV3IFlvcmsgQ2l0eTERMA8GA1UECBMITmV3IFlvcmsx CzAJBgNVBAYTAlVTMB4XDTE5MDUyMjIzNTU1NFoXDTM5MDUyMjIzNTU1NFowaTEP MA0GA1UEAxMGY2xpZW50MRAwDgYDVQQLEwdEcml2ZXJzMQwwCgYDVQQKEwNNREIx FjAUBgNVBAcTDU5ldyBZb3JrIENpdHkxETAPBgNVBAgTCE5ldyBZb3JrMQswCQYD VQQGEwJVUzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALDUvFBLop+/ ytvY13yDi6SKIdYxMllasYontjp8e7iSSnKCqJIQN13lJ1TdJOl+TMGFnDedsXJ7 Oy2LcrdOp0aUxtv3pqFeOMPbik7h7L1G4jsElZv06CkEOBVBWaKqK1x/mZibiKST X6FvtwpBNbxAwiHnCKugTYOckrD7b0rkiRxo6ZnO/+WVA7xRNmifEGyVN1rNB14h G+spotOPC5cxC9lSl98Opqqofu3XGRgMu6mJNuRWfZLSrwnkGru5k8lNYbD6yhYi rTDfENmQCLV9d2rMOfyHkk6ti4CxR5W4+SqauBpi3TQrIcx+V+xMNyGDPBB5rF/H Zg+pob+76VcCAwEAAaMkMCIwCwYDVR0PBAQDAgeAMBMGA1UdJQQMMAoGCCsGAQUF BwMCMA0GCSqGSIb3DQEBCwUAA4IBAQAqRcLAGvYMaGYOV4HJTzNotT2qE0I9THNQ wOV1fBg69x6SrUQTQLjJEptpOA288Wue6Jt3H+p5qAGV5GbXjzN/yjCoItggSKxG Xg7279nz6/C5faoIKRjpS9R+MsJGlttP9nUzdSxrHvvqm62OuSVFjjETxD39DupE YPFQoHOxdFTtBQlc/zIKxVdd20rs1xJeeU2/L7jtRBSPuR/Sk8zot7G2/dQHX49y kHrq8qz12kj1T6XDXf8KZawFywXaz0/Ur+fUYKmkVk1T0JZaNtF4sKqDeNE4zcns p3xLVDSl1Q5Gwj7bgph9o4Hxs9izPwiqjmNaSjPimGYZ399zcurY -----END CERTIFICATE----- mongodb-mongo-python-driver-509e9b7/test/certificates/crl.pem000066400000000000000000000013171462766011000243460ustar00rootroot00000000000000-----BEGIN X509 CRL----- MIIB6jCB0wIBATANBgkqhkiG9w0BAQsFADB5MRswGQYDVQQDExJEcml2ZXJzIFRl c3RpbmcgQ0ExEDAOBgNVBAsTB0RyaXZlcnMxEDAOBgNVBAoTB01vbmdvREIxFjAU BgNVBAcTDU5ldyBZb3JrIENpdHkxETAPBgNVBAgTCE5ldyBZb3JrMQswCQYDVQQG EwJVUxcNMTkwNTIyMjI0NTUzWhcNMTkwNjIxMjI0NTUzWjAVMBMCAncVFw0xOTA1 MjIyMjQ1MzJaoA8wDTALBgNVHRQEBAICEAAwDQYJKoZIhvcNAQELBQADggEBACwQ W9OF6ExJSzzYbpCRroznkfdLG7ghNSxIpBQUGtcnYbkP4em6TdtAj5K3yBjcKn4a hnUoa5EJGr2Xgg0QascV/1GuWEJC9rsYYB9boVi95l1CrkS0pseaunM086iItZ4a hRVza8qEMBc3rdsracA7hElYMKdFTRLpIGciJehXzv40yT5XFBHGy/HIT0CD50O7 BDOHzA+rCFCvxX8UY9myDfb1r1zUW7Gzjn241VT7bcIJmhFE9oV0popzDyqr6GvP qB2t5VmFpbnSwkuc4ie8Jizip1P8Hg73lut3oVAHACFGPpfaNIAp4GcSH61zJmff 9UBe3CJ1INwqyiuqGeA= -----END X509 CRL----- mongodb-mongo-python-driver-509e9b7/test/certificates/password_protected.pem000066400000000000000000000060771462766011000275110ustar00rootroot00000000000000-----BEGIN ENCRYPTED PRIVATE KEY----- MIIFHzBJBgkqhkiG9w0BBQ0wPDAbBgkqhkiG9w0BBQwwDgQIC8as6PDVhwECAggA MB0GCWCGSAFlAwQBAgQQTYOgCJcRqUI7dsgqNojv/ASCBNCG9fiu642V4AuFK34c Q42lvy/cR0CIXLq/rDXN1L685kdeKex7AfDuRtnjY2+7CLJiJimgQNJXDJPHab/k MBHbwbBs38fg6eSYX8V08/IyyTege5EJMhYxmieHDC3DXKt0gyHk6hA/r5+Mr49h HeVGwqBLJEQ3gVIeHaOleZYspsXXWqOPHnFiqnk/biaJS0+LkDDEiQgTLEYSnOjP lexxUc4BV/TN0Z920tZCMfwx7IXD/C+0AkV/Iqq4LALmT702EccB3indaIJ8biGR radqDLR32Q+vT9uZHgT8EFiUsISMqhob2mnyTfFV/s9ghWwogjSz0HrRcq6fxdg7 oeyT9K0ET53AGTGmV0206byPu6qCj1eNvtn+t1Ob+d5hecaTugRMVheWPlc5frsz AcewDNa0pv4pZItjAGMqOPJHfzEDnzTJXpLqGYhg044H1+OCY8+1YK7U0u8dO+/3 f5AoDMq18ipDVTFTooJURej4/Wjbrfad3ZFjp86nxfHPeWM1YjC9+IlLtK1wr0/U V8TjGqCkw8yHayz01A86iA8X53YQBg+tyMGjxmivo6LgFGKa9mXGvDkN+B+0+OcA PqldAuH/TJhnkqzja767e4n9kcr+TmV19Hn1hcJPTDrRU8+sSqQFsWN4pvHazAYB UdWie+EXI0eU2Av9JFgrVcpRipXjB48BaPwuBw8hm+VStCH7ynF4lJy6/3esjYwk Mx+NUf8+pp1DRzpzuJa2vAutzqia5r58+zloQMxkgTZtJkQU6OCRoUhHGVk7WNb1 nxsibOSzyVSP9ZNbHIHAn43vICFGrPubRs200Kc4CdXsOSEWoP0XYebhiNJgGtQs KoISsV4dFRLwhaJhIlayTBQz6w6Ph87WbtuiAqoLiuqdXhUGz/79j/6JZqCH8t/H eZs4Dhu+HdD/wZKJDYAS+JBsiwYWnI3y/EowZYgLdOMI4u6xYDejhxwEw20LW445 qjJ7pV/iX2uavazHgC91Bfd4zodfXIQ1IDyTmb51UFwx0ARzG6enntduO6xtcYU9 MXwfrEpuZ/MkWTLkR0PHPbIPcR1MiVwPKdvrLk42Bzj/urtXYrAFUckMFMzEh+uv 0lix2hbq/Xwj4dXcY4w9hnC6QQDCJTf9S6MU6OisrZHKk0qZ2Vb4aU/eBcBsHBwo X/QGcDHneHxlrrs2eLX26Vh8Odc5h8haeIxnfaa1t+Yv56OKHuAztPMnJOUL7KtQ A556LxT0b5IGx0RcfUcbG8XbxEHseACptoDOoguh9923IBI0uXmpi8q0P815LPUu 0AsE47ATDMGPnXbopejRDicfgMGjykJn8vKO8r/Ia3Fpnomx4iJNCXGqomL+GMpZ IhQbKNrRG6XZMlx5kVCT0Qr1nOWMiOTSDCQ5vrG3c1Viu+0bctvidEvs+LCm98tb 7ty8F0uOno0rYGNQz18OEE1Tj+E19Vauz1U35Z5SsgJJ/GfzhSJ79Srmdg2PsAzk AUNTKXux1GLf1cMjTiiU5g+tCEtUL9Me7lsv3L6aFdrCyRbhXUQfJh4NAG8+3Pvh EaprThBzKsVvbOfU81mOaH9YMmUgmxG86vxDiNtaWd4v6c1k+HGspJr/q49pcXZP ltBMuS9AihstZ1sHJsyQCmNXkA== -----END ENCRYPTED PRIVATE KEY----- -----BEGIN CERTIFICATE----- MIIDgzCCAmugAwIBAgIDBXUHMA0GCSqGSIb3DQEBCwUAMHkxGzAZBgNVBAMTEkRy aXZlcnMgVGVzdGluZyBDQTEQMA4GA1UECxMHRHJpdmVyczEQMA4GA1UEChMHTW9u Z29EQjEWMBQGA1UEBxMNTmV3IFlvcmsgQ2l0eTERMA8GA1UECBMITmV3IFlvcmsx CzAJBgNVBAYTAlVTMB4XDTE5MDUyMzAwMDEyOVoXDTM5MDUyMzAwMDEyOVowaTEP MA0GA1UEAxMGY2xpZW50MRAwDgYDVQQLEwdEcml2ZXJzMQwwCgYDVQQKEwNNREIx FjAUBgNVBAcTDU5ldyBZb3JrIENpdHkxETAPBgNVBAgTCE5ldyBZb3JrMQswCQYD VQQGEwJVUzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAOqCb0Lo4XsV W327Wlnqc5rwWa5Elw0rFuehSfViRIcYfuFWAPXoOj3fIDsYz6d41G8hp6tkF88p swlbzDF8Fc7mXDhauwwl2F/NrWYUXwCT8fKju4DtGd2JlDMi1TRDeofkYCGVPp70 vNqd0H8iDWWs8OmiNrdBLJwNiGaf9y15ena4ImQGitXLFn+qNSXYJ1Rs8p7Y2PTr L+dff5gJCVbANwGII1rjMAsrMACPVmr8c1Lxoq4fSdJiLweosrv2Lk0WWGsO0Seg ZY71dNHEyNjItE+VtFEtslJ5L261i3BfF/FqNnH2UmKXzShwfwxyHT8o84gSAltQ 5/lVJ4QQKosCAwEAAaMkMCIwCwYDVR0PBAQDAgeAMBMGA1UdJQQMMAoGCCsGAQUF BwMCMA0GCSqGSIb3DQEBCwUAA4IBAQBOAlKxIMFcTZ+4k8NJv97RSf+zOb5Wu2ct uxSZxzgKTxLFUuEM8XQiEz1iHQ3XG+uV1fzA74YLQiKjjLrU0mx54eM1vaRtOXvF sJlzZU8Z2+523FVPx4HBPyObQrfXmIoAiHoQ4VUeepkPRpXxpifgWd/OCWhLDr2/ 0Kgcb0ybaGVDpA0UD9uVIwgFjRu6id7wG+lVcdRxJYskTOOaN2o1hMdAKkrpFQbd zNRfEoBPUYR3QAmAKP2HBjpgp4ktOHoOKMlfeAuuMCUocSnmPKc3xJaH/6O7rHcf /Rm0X411RH8JfoXYsSiPsd601kZefhuWvJH0sJLibRDvT7zs8C1v -----END CERTIFICATE----- mongodb-mongo-python-driver-509e9b7/test/certificates/server.pem000066400000000000000000000057221462766011000251000ustar00rootroot00000000000000-----BEGIN RSA PRIVATE KEY----- MIIEogIBAAKCAQEAhNrB0E6GY/kFSd8/vNpu/t952tbnOsD5drV0XPvmuy7SgKDY a/S+xb/jPnlZKKehdBnH7qP/gYbv34ZykzcDFZscjPLiGc2cRGP+NQCSFK0d2/7d y15zSD3zhj14G8+MkpAejTU+0/qFNZMc5neDvGanTe0+8aWa0DXssM0MuTxIv7j6 CtsMWeqLLofN7a1Kw2UvmieCHfHMuA/08pJwRnV/+5T9WONBPJja2ZQRrG1BjpI4 81zSPUZesIqi8yDlExdvgNaRZIEHi/njREqwVgJOZomUY57zmKypiMzbz48dDTsV gUStxrEqbaP+BEjQYPX5+QQk4GdMjkLf52LR6QIDAQABAoIBAHSs+hHLJNOf2zkp S3y8CUblVMsQeTpsR6otaehPgi9Zy50TpX4KD5D0GMrBH8BIl86y5Zd7h+VlcDzK gs0vPxI2izhuBovKuzaE6rf5rFFkSBjxGDCG3o/PeJOoYFdsS3RcBbjVzju0hFCs xnDQ/Wz0anJRrTnjyraY5SnQqx/xuhLXkj/lwWoWjP2bUqDprnuLOj16soNu60Um JziWbmWx9ty0wohkI/8DPBl9FjSniEEUi9pnZXPElFN6kwPkgdfT5rY/TkMH4lsu ozOUc5xgwlkT6kVjXHcs3fleuT/mOfVXLPgNms85JKLucfd6KiV7jYZkT/bXIjQ+ 7CZEn0ECgYEA5QiKZgsfJjWvZpt21V/i7dPje2xdwHtZ8F9NjX7ZUFA7mUPxUlwe GiXxmy6RGzNdnLOto4SF0/7ebuF3koO77oLup5a2etL+y/AnNAufbu4S5D72sbiz wdLzr3d5JQ12xeaEH6kQNk2SD5/ShctdS6GmTgQPiJIgH0MIdi9F3v0CgYEAlH84 hMWcC+5b4hHUEexeNkT8kCXwHVcUjGRaYFdSHgovvWllApZDHSWZ+vRcMBdlhNPu 09Btxo99cjOZwGYJyt20QQLGc/ZyiOF4ximQzabTeFgLkTH3Ox6Mh2Rx9yIruYoX nE3UfMDkYELanEJUv0zenKpZHw7tTt5yXXSlEF0CgYBSsEOvVcKYO/eoluZPYQAA F2jgzZ4HeUFebDoGpM52lZD+463Dq2hezmYtPaG77U6V3bUJ/TWH9VN/Or290vvN v83ECcC2FWlSXdD5lFyqYx/E8gqE3YdgqfW62uqM+xBvoKsA9zvYLydVpsEN9v8m 6CSvs/2btA4O21e5u5WBTQKBgGtAb6vFpe0gHRDs24SOeYUs0lWycPhf+qFjobrP lqnHpa9iPeheat7UV6BfeW3qmBIVl/s4IPE2ld4z0qqZiB0Tf6ssu/TpXNPsNXS6 dLFz+myC+ufFdNEoQUtQitd5wKbjTCZCOGRaVRgJcSdG6Tq55Fa22mOKPm+mTmed ZdKpAoGAFsTYBAHPxs8nzkCJCl7KLa4/zgbgywO6EcQgA7tfelB8bc8vcAMG5o+8 YqAfwxrzhVSVbJx0fibTARXROmbh2pn010l2wj3+qUajM8NiskCPFbSjGy7HSUze P8Kt1uMDJdj55gATzn44au31QBioZY2zXleorxF21cr+BZCJgfA= -----END RSA PRIVATE KEY----- -----BEGIN CERTIFICATE----- MIIDlTCCAn2gAwIBAgICdxUwDQYJKoZIhvcNAQELBQAweTEbMBkGA1UEAxMSRHJp dmVycyBUZXN0aW5nIENBMRAwDgYDVQQLEwdEcml2ZXJzMRAwDgYDVQQKEwdNb25n b0RCMRYwFAYDVQQHEw1OZXcgWW9yayBDaXR5MREwDwYDVQQIEwhOZXcgWW9yazEL MAkGA1UEBhMCVVMwHhcNMTkwNTIyMjIzMjU2WhcNMzkwNTIyMjIzMjU2WjBwMRIw EAYDVQQDEwlsb2NhbGhvc3QxEDAOBgNVBAsTB0RyaXZlcnMxEDAOBgNVBAoTB01v bmdvREIxFjAUBgNVBAcTDU5ldyBZb3JrIENpdHkxETAPBgNVBAgTCE5ldyBZb3Jr MQswCQYDVQQGEwJVUzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAITa wdBOhmP5BUnfP7zabv7fedrW5zrA+Xa1dFz75rsu0oCg2Gv0vsW/4z55WSinoXQZ x+6j/4GG79+GcpM3AxWbHIzy4hnNnERj/jUAkhStHdv+3ctec0g984Y9eBvPjJKQ Ho01PtP6hTWTHOZ3g7xmp03tPvGlmtA17LDNDLk8SL+4+grbDFnqiy6Hze2tSsNl L5ongh3xzLgP9PKScEZ1f/uU/VjjQTyY2tmUEaxtQY6SOPNc0j1GXrCKovMg5RMX b4DWkWSBB4v540RKsFYCTmaJlGOe85isqYjM28+PHQ07FYFErcaxKm2j/gRI0GD1 +fkEJOBnTI5C3+di0ekCAwEAAaMwMC4wLAYDVR0RBCUwI4IJbG9jYWxob3N0hwR/ AAABhxAAAAAAAAAAAAAAAAAAAAABMA0GCSqGSIb3DQEBCwUAA4IBAQBol8+YH7MA HwnIh7KcJ8h87GkCWsjOJCDJWiYBJArQ0MmgDO0qdx+QEtvLMn3XNtP05ZfK0WyX or4cWllAkMFYaFbyB2hYazlD1UAAG+22Rku0UP6pJMLbWe6pnqzx+RL68FYdbZhN fCW2xiiKsdPoo2VEY7eeZKrNr/0RFE5EKXgzmobpTBQT1Dl3Ve4aWLoTy9INlQ/g z40qS7oq1PjjPLgxINhf4ncJqfmRXugYTOnyFiVXLZTys5Pb9SMKdToGl3NTYWLL 2AZdjr6bKtT+WtXyHqO0cQ8CkAW0M6VOlMluACllcJxfrtdlQS2S4lUIj76QKBdZ khBHXq/b8MFX -----END CERTIFICATE----- mongodb-mongo-python-driver-509e9b7/test/certificates/trusted-ca.pem000066400000000000000000000112331462766011000256370ustar00rootroot00000000000000# CA bundle file used to test tlsCAFile loading for OCSP. # Copied from the server: # https://github.com/mongodb/mongo/blob/r4.3.4/jstests/libs/trusted-ca.pem # Autogenerated file, do not edit. # Generate using jstests/ssl/x509/mkcert.py --config jstests/ssl/x509/certs.yml trusted-ca.pem # # CA for alternate client/server certificate chain. -----BEGIN CERTIFICATE----- MIIDojCCAooCBG585gswDQYJKoZIhvcNAQELBQAwfDELMAkGA1UEBhMCVVMxETAP BgNVBAgMCE5ldyBZb3JrMRYwFAYDVQQHDA1OZXcgWW9yayBDaXR5MRAwDgYDVQQK DAdNb25nb0RCMQ8wDQYDVQQLDAZLZXJuZWwxHzAdBgNVBAMMFlRydXN0ZWQgS2Vy bmVsIFRlc3QgQ0EwHhcNMTkwOTI1MjMyNzQxWhcNMzkwOTI3MjMyNzQxWjB8MQsw CQYDVQQGEwJVUzERMA8GA1UECAwITmV3IFlvcmsxFjAUBgNVBAcMDU5ldyBZb3Jr IENpdHkxEDAOBgNVBAoMB01vbmdvREIxDzANBgNVBAsMBktlcm5lbDEfMB0GA1UE AwwWVHJ1c3RlZCBLZXJuZWwgVGVzdCBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEP ADCCAQoCggEBANlRxtpMeCGhkotkjHQqgqvO6O6hoRoAGGJlDaTVtqrjmC8nwySz 1nAFndqUHttxS3A5j4enOabvffdOcV7+Z6vDQmREF6QZmQAk81pmazSc3wOnRiRs AhXjld7i+rhB50CW01oYzQB50rlBFu+ONKYj32nBjD+1YN4AZ2tuRlbxfx2uf8Bo Zowfr4n9nHVcWXBLFmaQLn+88WFO/wuwYUOn6Di1Bvtkvqum0or5QeAF0qkJxfhg 3a4vBnomPdwEXCgAGLvHlB41CWG09EuAjrnE3HPPi5vII8pjY2dKKMomOEYmA+KJ AC1NlTWdN0TtsoaKnyhMMhLWs3eTyXL7kbkCAwEAAaMxMC8wDAYDVR0TBAUwAwEB /zAfBgNVHREEGDAWgglsb2NhbGhvc3SCCTEyNy4wLjAuMTANBgkqhkiG9w0BAQsF AAOCAQEAQk56MO9xAhtO077COCqIYe6pYv3uzOplqjXpJ7Cph7GXwQqdFWfKls7B cLfF/fhIUZIu5itStEkY+AIwht4mBr1F5+hZUp9KZOed30/ewoBXAUgobLipJV66 FKg8NRtmJbiZrrC00BSO+pKfQThU8k0zZjBmNmpjxnbKZZSFWUKtbhHV1vujver6 SXZC7R6692vLwRBMoZxhgy/FkYRdiN0U9wpluKd63eo/O02Nt6OEMyeiyl+Z3JWi 8g5iHNrBYGBbGSnDOnqV6tjEY3eq600JDWiodpA1OQheLi78pkc/VQZwof9dyBCm 6BoCskTjip/UB+vIhdPFT9sgUdgDTg== -----END CERTIFICATE----- -----BEGIN PRIVATE KEY----- MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDZUcbaTHghoZKL ZIx0KoKrzujuoaEaABhiZQ2k1baq45gvJ8Mks9ZwBZ3alB7bcUtwOY+Hpzmm7333 TnFe/merw0JkRBekGZkAJPNaZms0nN8Dp0YkbAIV45Xe4vq4QedAltNaGM0AedK5 QRbvjjSmI99pwYw/tWDeAGdrbkZW8X8drn/AaGaMH6+J/Zx1XFlwSxZmkC5/vPFh Tv8LsGFDp+g4tQb7ZL6rptKK+UHgBdKpCcX4YN2uLwZ6Jj3cBFwoABi7x5QeNQlh tPRLgI65xNxzz4ubyCPKY2NnSijKJjhGJgPiiQAtTZU1nTdE7bKGip8oTDIS1rN3 k8ly+5G5AgMBAAECggEAS7GjLKgT88reSzUTgubHquYf1fZwMak01RjTnsVdoboy aMJVwzPsjgo2yEptUQvuNcGmz54cg5vJaVlmPaspGveg6WGaRmswEo/MP4GK98Fo IFKkKM2CEHO74O14XLN/w8yFA02+IdtM3X/haEFE71VxXNmwawRXIBxN6Wp4j5Fb mPLKIspnWQ/Y/Fn799sCFAzX5mKkbCt1IEgKssgQQEm1UkvmCkcZE+mdO/ErYP8A COO0LpM+TK6WQY2LKiteeCCiosTZFb1GO7MkXrRP5uOBZKaW5kq1R0b6PcopJPCM OcYF0Zli6KB7oiQLdXgU2jCaxYOnuRb6RYh2l7NvAQKBgQD6CZ9TKOn/EUQtukyw pvYTyt1hoLXqYGcbRtLc1gcC+Z2BD28hd3eD/mEUv+g/8bq/OP4wYV9X+VRvR8xN MmfAG/sJeOCOClz1A1TyNeA+G0GZ25qWHyHQ2W4WlSG1CXQgxGzU6wo/t6wiVW5R O4jplFVEOXznf4vmVfBJK50R2QKBgQDegGxm23jF2N5sIYDZ14oxms8bbjPz8zH6 tiIRYNGbSzI7J4KFGY2HiBwtf1yxS22HBL69Y1WrEzGm1vm4aZG/GUwBzI79QZAO +YFIGaIrdlv12Zm6lpJMmAWlOs9XFirC17oQEwOQFweOdQSt7F/+HMZOigdikRBV pK+8Kfay4QKBgQDarDevHwUmkg8yftA7Xomv3aenjkoK5KzH6jTX9kbDj1L0YG8s sbLQuVRmNUAFTH+qZUnJPh+IbQIvIHfIu+CI3u+55QFeuCl8DqHoAr5PEr9Ys/qK eEe2w7HIBj0oe1AYqDEWNUkNWLEuhdCpMowW3CeGN1DJlX7gvyAang4MYQKBgHwM aWNnFQxo/oiWnTnWm2tQfgszA7AMdF7s0E2UBwhnghfMzU3bkzZuwhbznQATp3rR QG5iRU7dop7717ni0akTN3cBTu8PcHuIy3UhJXLJyDdnG/gVHnepgew+v340E58R muB/WUsqK8JWp0c4M8R+0mjTN47ShaLZ8EgdtTbBAoGBAKOcpuDfFEMI+YJgn8zX h0nFT60LX6Lx+zcSDY9+6J6a4n5NhC+weYCDFOGlsLka1SwHcg1xanfrLVjpH7Ok HDJGLrSh1FP2Rq/oFxZ/OKCjonHLa8IulqD/AA+sqYRbysKNsT3Pi0554F2xFEqQ z/C84nlT1R2uTCWIxvrnpU2h -----END PRIVATE KEY----- # Pre Oct 2019 trusted-ca.pem # Transitional pending BUILD update. -----BEGIN CERTIFICATE----- MIIDpjCCAo6gAwIBAgIDAghHMA0GCSqGSIb3DQEBBQUAMHwxHzAdBgNVBAMTFlRy dXN0ZWQgS2VybmVsIFRlc3QgQ0ExDzANBgNVBAsTBktlcm5lbDEQMA4GA1UEChMH TW9uZ29EQjEWMBQGA1UEBxMNTmV3IFlvcmsgQ2l0eTERMA8GA1UECBMITmV3IFlv cmsxCzAJBgNVBAYTAlVTMB4XDTE2MDMzMTE0NTY1NVoXDTM2MDMzMTE0NTY1NVow fDEfMB0GA1UEAxMWVHJ1c3RlZCBLZXJuZWwgVGVzdCBDQTEPMA0GA1UECxMGS2Vy bmVsMRAwDgYDVQQKEwdNb25nb0RCMRYwFAYDVQQHEw1OZXcgWW9yayBDaXR5MREw DwYDVQQIEwhOZXcgWW9yazELMAkGA1UEBhMCVVMwggEiMA0GCSqGSIb3DQEBAQUA A4IBDwAwggEKAoIBAQCePFHZTydC96SlSHSyu73vw//ddaE33kPllBB9DP2L7yRF 6D/blFmno9fSM+Dfg64VfGV+0pCXPIZbpH29nzJu0DkvHzKiWK7P1zUj8rAHaX++ d6k0yeTLFM9v+7YE9rHoANVn22aOyDvTgAyMmA0CLn+SmUy6WObwMIf9cZn97Znd lww7IeFNyK8sWtfsVN4yRBnjr7kKN2Qo0QmWeFa7jxVQptMJQrY8k1PcyVUOgOjQ ocJLbWLlm9k0/OMEQSwQHJ+d9weUbKjlZ9ExOrm4QuuA2tJhb38baTdAYw3Jui4f yD6iBAGD0Jkpc+3YaWv6CBmK8NEFkYJD/gn+lJ75AgMBAAGjMTAvMAwGA1UdEwQF MAMBAf8wHwYDVR0RBBgwFoIJbG9jYWxob3N0ggkxMjcuMC4wLjEwDQYJKoZIhvcN AQEFBQADggEBADYikjB6iwAUs6sglwkE4rOkeMkJdRCNwK/5LpFJTWrDjBvBQCdA Y5hlAVq8PfIYeh+wEuSvsEHXmx7W29X2+p4VuJ95/xBA6NLapwtzuiijRj2RBAOG 1EGuyFQUPTL27DR3+tfayNykDclsVDNN8+l7nt56j8HojP74P5OMHtn+6HX5+mtF FfZMTy0mWguCsMOkZvjAskm6s4U5gEC8pYEoC0ZRbfUdyYsxZe/nrXIFguVlVPCB XnfB/0iG9t+VH5cUVj1LP9skXTW4kXfhQmljUuo+EVBNR6n2nfTnpoC65WeAgHV4 V+s9mJsUv2x72KtKYypqEVT0gaJ1WIN9N1s= -----END CERTIFICATE----- mongodb-mongo-python-driver-509e9b7/test/change_streams/000077500000000000000000000000001462766011000233775ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/change_streams/unified/000077500000000000000000000000001462766011000250225ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/change_streams/unified/change-streams-clusterTime.json000066400000000000000000000032101462766011000331100ustar00rootroot00000000000000{ "description": "change-streams-clusterTime", "schemaVersion": "1.4", "createEntities": [ { "client": { "id": "client0", "useMultipleMongoses": false } }, { "database": { "id": "database0", "client": "client0", "databaseName": "database0" } }, { "collection": { "id": "collection0", "database": "database0", "collectionName": "collection0" } } ], "runOnRequirements": [ { "minServerVersion": "4.0.0", "topologies": [ "replicaset", "sharded-replicaset", "load-balanced", "sharded" ], "serverless": "forbid" } ], "initialData": [ { "collectionName": "collection0", "databaseName": "database0", "documents": [] } ], "tests": [ { "description": "clusterTime is present", "operations": [ { "name": "createChangeStream", "object": "collection0", "arguments": { "pipeline": [] }, "saveResultAsEntity": "changeStream0" }, { "name": "insertOne", "object": "collection0", "arguments": { "document": { "_id": 1 } } }, { "name": "iterateUntilDocumentOrError", "object": "changeStream0", "expectResult": { "ns": { "db": "database0", "coll": "collection0" }, "clusterTime": { "$$exists": true } } } ] } ] } change-streams-disambiguatedPaths.json000066400000000000000000000133221462766011000343400ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/change_streams/unified{ "description": "disambiguatedPaths", "schemaVersion": "1.4", "createEntities": [ { "client": { "id": "client0", "useMultipleMongoses": false } }, { "database": { "id": "database0", "client": "client0", "databaseName": "database0" } }, { "collection": { "id": "collection0", "database": "database0", "collectionName": "collection0" } } ], "runOnRequirements": [ { "minServerVersion": "6.1.0", "topologies": [ "replicaset", "sharded-replicaset", "load-balanced", "sharded" ], "serverless": "forbid" } ], "initialData": [ { "collectionName": "collection0", "databaseName": "database0", "documents": [] } ], "tests": [ { "description": "disambiguatedPaths is not present when showExpandedEvents is false/unset", "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", "operations": [ { "name": "insertOne", "object": "collection0", "arguments": { "document": { "_id": 1, "a": { "1": 1 } } } }, { "name": "createChangeStream", "object": "collection0", "arguments": { "pipeline": [], "showExpandedEvents": true }, "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": { "a.1": [ "a", "1" ] } } } } ] }, { "description": "disambiguatedPaths returns array indices as integers", "operations": [ { "name": "insertOne", "object": "collection0", "arguments": { "document": { "_id": 1, "a": [ { "1": 1 } ] } } }, { "name": "createChangeStream", "object": "collection0", "arguments": { "pipeline": [], "showExpandedEvents": true }, "saveResultAsEntity": "changeStream0" }, { "name": "updateOne", "object": "collection0", "arguments": { "filter": { "_id": 1 }, "update": { "$set": { "a.0.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": { "a.0.1": [ "a", { "$$type": "int" }, "1" ] } } } } ] } ] } mongodb-mongo-python-driver-509e9b7/test/change_streams/unified/change-streams-errors.json000066400000000000000000000127311462766011000321340ustar00rootroot00000000000000{ "description": "change-streams-errors", "schemaVersion": "1.7", "runOnRequirements": [ { "serverless": "forbid" } ], "createEntities": [ { "client": { "id": "client0", "observeEvents": [ "commandStartedEvent" ], "ignoreCommandMonitoringEvents": [ "killCursors" ], "useMultipleMongoses": false } }, { "client": { "id": "globalClient", "useMultipleMongoses": false } }, { "database": { "id": "database0", "client": "client0", "databaseName": "database0" } }, { "collection": { "id": "collection0", "database": "database0", "collectionName": "collection0" } }, { "database": { "id": "globalDatabase0", "client": "globalClient", "databaseName": "database0" } }, { "collection": { "id": "globalCollection0", "database": "globalDatabase0", "collectionName": "collection0" } } ], "initialData": [ { "collectionName": "collection0", "databaseName": "database0", "documents": [] } ], "tests": [ { "description": "The watch helper must not throw a custom exception when executed against a single server topology, but instead depend on a server error", "runOnRequirements": [ { "minServerVersion": "3.6.0", "topologies": [ "single" ] } ], "operations": [ { "name": "createChangeStream", "object": "collection0", "arguments": { "pipeline": [] }, "expectError": { "errorCode": 40573 } } ] }, { "description": "Change Stream should error when an invalid aggregation stage is passed in", "runOnRequirements": [ { "minServerVersion": "3.6.0", "topologies": [ "replicaset" ] } ], "operations": [ { "name": "createChangeStream", "object": "collection0", "arguments": { "pipeline": [ { "$unsupported": "foo" } ] }, "expectError": { "errorCode": 40324 } } ], "expectEvents": [ { "client": "client0", "ignoreExtraEvents": true, "events": [ { "commandStartedEvent": { "command": { "aggregate": "collection0", "cursor": {}, "pipeline": [ { "$changeStream": {} }, { "$unsupported": "foo" } ] }, "commandName": "aggregate", "databaseName": "database0" } } ] } ] }, { "description": "Change Stream should error when _id is projected out", "runOnRequirements": [ { "minServerVersion": "4.1.11", "topologies": [ "replicaset", "sharded-replicaset", "load-balanced" ] } ], "operations": [ { "name": "createChangeStream", "object": "collection0", "arguments": { "pipeline": [ { "$project": { "_id": 0 } } ] }, "saveResultAsEntity": "changeStream0" }, { "name": "insertOne", "object": "globalCollection0", "arguments": { "document": { "z": 3 } } }, { "name": "iterateUntilDocumentOrError", "object": "changeStream0", "expectError": { "errorCode": 280 } } ] }, { "description": "change stream errors on ElectionInProgress", "runOnRequirements": [ { "minServerVersion": "4.2", "topologies": [ "replicaset", "sharded-replicaset", "load-balanced" ] } ], "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "globalClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "getMore" ], "errorCode": 216, "closeConnection": false } } } }, { "name": "createChangeStream", "object": "collection0", "arguments": { "pipeline": [] }, "saveResultAsEntity": "changeStream0" }, { "name": "insertOne", "object": "globalCollection0", "arguments": { "document": { "z": 3 } } }, { "name": "iterateUntilDocumentOrError", "object": "changeStream0", "expectError": { "errorCode": 216 } } ] } ] } change-streams-pre_and_post_images.json000066400000000000000000000474331462766011000345520ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/change_streams/unified{ "description": "change-streams-pre_and_post_images", "schemaVersion": "1.4", "runOnRequirements": [ { "minServerVersion": "6.0.0", "topologies": [ "replicaset", "sharded-replicaset", "load-balanced" ], "serverless": "forbid" } ], "createEntities": [ { "client": { "id": "client0", "observeEvents": [ "commandStartedEvent" ], "ignoreCommandMonitoringEvents": [ "collMod", "insert", "update", "getMore", "killCursors" ] } }, { "database": { "id": "database0", "client": "client0", "databaseName": "change-stream-tests" } }, { "collection": { "id": "collection0", "database": "database0", "collectionName": "test" } } ], "initialData": [ { "collectionName": "test", "databaseName": "change-stream-tests", "documents": [ { "_id": 1 } ] } ], "tests": [ { "description": "fullDocument:whenAvailable with changeStreamPreAndPostImages enabled", "operations": [ { "name": "runCommand", "object": "database0", "arguments": { "commandName": "collMod", "command": { "collMod": "test", "changeStreamPreAndPostImages": { "enabled": true } } } }, { "name": "createChangeStream", "object": "collection0", "arguments": { "pipeline": [], "fullDocument": "whenAvailable" }, "saveResultAsEntity": "changeStream0" }, { "name": "updateOne", "object": "collection0", "arguments": { "filter": { "_id": 1 }, "update": { "$set": { "x": 1 } } } }, { "name": "iterateUntilDocumentOrError", "object": "changeStream0", "expectResult": { "operationType": "update", "ns": { "db": "change-stream-tests", "coll": "test" }, "updateDescription": { "$$type": "object" }, "fullDocument": { "_id": 1, "x": 1 } } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "aggregate": "test", "pipeline": [ { "$changeStream": { "fullDocument": "whenAvailable" } } ] } } } ] } ] }, { "description": "fullDocument:whenAvailable with changeStreamPreAndPostImages disabled", "operations": [ { "name": "runCommand", "object": "database0", "arguments": { "commandName": "collMod", "command": { "collMod": "test", "changeStreamPreAndPostImages": { "enabled": false } } } }, { "name": "createChangeStream", "object": "collection0", "arguments": { "pipeline": [], "fullDocument": "whenAvailable" }, "saveResultAsEntity": "changeStream0" }, { "name": "updateOne", "object": "collection0", "arguments": { "filter": { "_id": 1 }, "update": { "$set": { "x": 1 } } } }, { "name": "iterateUntilDocumentOrError", "object": "changeStream0", "expectResult": { "operationType": "update", "ns": { "db": "change-stream-tests", "coll": "test" }, "updateDescription": { "$$type": "object" }, "fullDocument": null } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "aggregate": "test", "pipeline": [ { "$changeStream": { "fullDocument": "whenAvailable" } } ] } } } ] } ] }, { "description": "fullDocument:required with changeStreamPreAndPostImages enabled", "operations": [ { "name": "runCommand", "object": "database0", "arguments": { "commandName": "collMod", "command": { "collMod": "test", "changeStreamPreAndPostImages": { "enabled": true } } } }, { "name": "createChangeStream", "object": "collection0", "arguments": { "pipeline": [], "fullDocument": "required" }, "saveResultAsEntity": "changeStream0" }, { "name": "updateOne", "object": "collection0", "arguments": { "filter": { "_id": 1 }, "update": { "$set": { "x": 1 } } } }, { "name": "iterateUntilDocumentOrError", "object": "changeStream0", "expectResult": { "operationType": "update", "ns": { "db": "change-stream-tests", "coll": "test" }, "updateDescription": { "$$type": "object" }, "fullDocument": { "_id": 1, "x": 1 } } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "aggregate": "test", "pipeline": [ { "$changeStream": { "fullDocument": "required" } } ] } } } ] } ] }, { "description": "fullDocument:required with changeStreamPreAndPostImages disabled", "operations": [ { "name": "runCommand", "object": "database0", "arguments": { "commandName": "collMod", "command": { "collMod": "test", "changeStreamPreAndPostImages": { "enabled": false } } } }, { "name": "createChangeStream", "object": "collection0", "arguments": { "pipeline": [], "fullDocument": "required" }, "saveResultAsEntity": "changeStream0" }, { "name": "updateOne", "object": "collection0", "arguments": { "filter": { "_id": 1 }, "update": { "$set": { "x": 1 } } } }, { "name": "iterateUntilDocumentOrError", "object": "changeStream0", "expectError": { "isClientError": false } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "aggregate": "test", "pipeline": [ { "$changeStream": { "fullDocument": "required" } } ] } } } ] } ] }, { "description": "fullDocumentBeforeChange:whenAvailable with changeStreamPreAndPostImages enabled", "operations": [ { "name": "runCommand", "object": "database0", "arguments": { "commandName": "collMod", "command": { "collMod": "test", "changeStreamPreAndPostImages": { "enabled": true } } } }, { "name": "createChangeStream", "object": "collection0", "arguments": { "pipeline": [], "fullDocumentBeforeChange": "whenAvailable" }, "saveResultAsEntity": "changeStream0" }, { "name": "updateOne", "object": "collection0", "arguments": { "filter": { "_id": 1 }, "update": { "$set": { "x": 1 } } } }, { "name": "iterateUntilDocumentOrError", "object": "changeStream0", "expectResult": { "operationType": "update", "ns": { "db": "change-stream-tests", "coll": "test" }, "updateDescription": { "$$type": "object" }, "fullDocumentBeforeChange": { "_id": 1 } } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "aggregate": "test", "pipeline": [ { "$changeStream": { "fullDocumentBeforeChange": "whenAvailable" } } ] } } } ] } ] }, { "description": "fullDocumentBeforeChange:whenAvailable with changeStreamPreAndPostImages disabled", "operations": [ { "name": "runCommand", "object": "database0", "arguments": { "commandName": "collMod", "command": { "collMod": "test", "changeStreamPreAndPostImages": { "enabled": false } } } }, { "name": "createChangeStream", "object": "collection0", "arguments": { "pipeline": [], "fullDocumentBeforeChange": "whenAvailable" }, "saveResultAsEntity": "changeStream0" }, { "name": "updateOne", "object": "collection0", "arguments": { "filter": { "_id": 1 }, "update": { "$set": { "x": 1 } } } }, { "name": "iterateUntilDocumentOrError", "object": "changeStream0", "expectResult": { "operationType": "update", "ns": { "db": "change-stream-tests", "coll": "test" }, "updateDescription": { "$$type": "object" }, "fullDocumentBeforeChange": null } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "aggregate": "test", "pipeline": [ { "$changeStream": { "fullDocumentBeforeChange": "whenAvailable" } } ] } } } ] } ] }, { "description": "fullDocumentBeforeChange:required with changeStreamPreAndPostImages enabled", "operations": [ { "name": "runCommand", "object": "database0", "arguments": { "commandName": "collMod", "command": { "collMod": "test", "changeStreamPreAndPostImages": { "enabled": true } } } }, { "name": "createChangeStream", "object": "collection0", "arguments": { "pipeline": [], "fullDocumentBeforeChange": "required" }, "saveResultAsEntity": "changeStream0" }, { "name": "updateOne", "object": "collection0", "arguments": { "filter": { "_id": 1 }, "update": { "$set": { "x": 1 } } } }, { "name": "iterateUntilDocumentOrError", "object": "changeStream0", "expectResult": { "operationType": "update", "ns": { "db": "change-stream-tests", "coll": "test" }, "updateDescription": { "$$type": "object" }, "fullDocumentBeforeChange": { "_id": 1 } } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "aggregate": "test", "pipeline": [ { "$changeStream": { "fullDocumentBeforeChange": "required" } } ] } } } ] } ] }, { "description": "fullDocumentBeforeChange:required with changeStreamPreAndPostImages disabled", "operations": [ { "name": "runCommand", "object": "database0", "arguments": { "commandName": "collMod", "command": { "collMod": "test", "changeStreamPreAndPostImages": { "enabled": false } } } }, { "name": "createChangeStream", "object": "collection0", "arguments": { "pipeline": [], "fullDocumentBeforeChange": "required" }, "saveResultAsEntity": "changeStream0" }, { "name": "updateOne", "object": "collection0", "arguments": { "filter": { "_id": 1 }, "update": { "$set": { "x": 1 } } } }, { "name": "iterateUntilDocumentOrError", "object": "changeStream0", "expectError": { "isClientError": false } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "aggregate": "test", "pipeline": [ { "$changeStream": { "fullDocumentBeforeChange": "required" } } ] } } } ] } ] }, { "description": "fullDocumentBeforeChange:off with changeStreamPreAndPostImages enabled", "operations": [ { "name": "runCommand", "object": "database0", "arguments": { "commandName": "collMod", "command": { "collMod": "test", "changeStreamPreAndPostImages": { "enabled": true } } } }, { "name": "createChangeStream", "object": "collection0", "arguments": { "pipeline": [], "fullDocumentBeforeChange": "off" }, "saveResultAsEntity": "changeStream0" }, { "name": "updateOne", "object": "collection0", "arguments": { "filter": { "_id": 1 }, "update": { "$set": { "x": 1 } } } }, { "name": "iterateUntilDocumentOrError", "object": "changeStream0", "expectResult": { "operationType": "update", "ns": { "db": "change-stream-tests", "coll": "test" }, "updateDescription": { "$$type": "object" }, "fullDocumentBeforeChange": { "$$exists": false } } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "aggregate": "test", "pipeline": [ { "$changeStream": { "fullDocumentBeforeChange": "off" } } ] } } } ] } ] }, { "description": "fullDocumentBeforeChange:off with changeStreamPreAndPostImages disabled", "operations": [ { "name": "runCommand", "object": "database0", "arguments": { "commandName": "collMod", "command": { "collMod": "test", "changeStreamPreAndPostImages": { "enabled": false } } } }, { "name": "createChangeStream", "object": "collection0", "arguments": { "pipeline": [], "fullDocumentBeforeChange": "off" }, "saveResultAsEntity": "changeStream0" }, { "name": "updateOne", "object": "collection0", "arguments": { "filter": { "_id": 1 }, "update": { "$set": { "x": 1 } } } }, { "name": "iterateUntilDocumentOrError", "object": "changeStream0", "expectResult": { "operationType": "update", "ns": { "db": "change-stream-tests", "coll": "test" }, "updateDescription": { "$$type": "object" }, "fullDocumentBeforeChange": { "$$exists": false } } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "aggregate": "test", "pipeline": [ { "$changeStream": { "fullDocumentBeforeChange": "off" } } ] } } } ] } ] } ] } mongodb-mongo-python-driver-509e9b7/test/change_streams/unified/change-streams-resume-allowlist.json000066400000000000000000001670761462766011000341450ustar00rootroot00000000000000{ "description": "change-streams-resume-allowlist", "schemaVersion": "1.7", "runOnRequirements": [ { "minServerVersion": "3.6", "topologies": [ "replicaset", "sharded-replicaset", "load-balanced" ], "serverless": "forbid" } ], "createEntities": [ { "client": { "id": "client0", "observeEvents": [ "commandStartedEvent" ], "ignoreCommandMonitoringEvents": [ "killCursors" ], "useMultipleMongoses": false } }, { "client": { "id": "globalClient", "useMultipleMongoses": false } }, { "database": { "id": "database0", "client": "client0", "databaseName": "database0" } }, { "collection": { "id": "collection0", "database": "database0", "collectionName": "collection0" } }, { "database": { "id": "globalDatabase0", "client": "globalClient", "databaseName": "database0" } }, { "collection": { "id": "globalCollection0", "database": "globalDatabase0", "collectionName": "collection0" } } ], "tests": [ { "description": "change stream resumes after a network error", "runOnRequirements": [ { "minServerVersion": "4.2" } ], "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "globalClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "getMore" ], "closeConnection": true } } } }, { "name": "createChangeStream", "object": "collection0", "arguments": { "pipeline": [] }, "saveResultAsEntity": "changeStream0" }, { "name": "insertOne", "object": "globalCollection0", "arguments": { "document": { "x": 1 } } }, { "name": "iterateUntilDocumentOrError", "object": "changeStream0", "expectResult": { "_id": { "$$exists": true }, "documentKey": { "$$exists": true }, "operationType": "insert", "ns": { "db": "database0", "coll": "collection0" }, "fullDocument": { "x": 1, "_id": { "$$exists": true } } } } ], "expectEvents": [ { "client": "client0", "ignoreExtraEvents": true, "events": [ { "commandStartedEvent": { "command": { "aggregate": "collection0", "cursor": {}, "pipeline": [ { "$changeStream": {} } ] }, "commandName": "aggregate", "databaseName": "database0" } }, { "commandStartedEvent": { "command": { "getMore": { "$$exists": true }, "collection": "collection0" }, "commandName": "getMore", "databaseName": "database0" } }, { "commandStartedEvent": { "command": { "aggregate": "collection0", "cursor": {}, "pipeline": [ { "$changeStream": { "resumeAfter": { "$$unsetOrMatches": { "$$exists": true } } } } ] }, "commandName": "aggregate", "databaseName": "database0" } } ] } ] }, { "description": "change stream resumes after HostUnreachable", "runOnRequirements": [ { "minServerVersion": "4.2", "maxServerVersion": "4.2.99" } ], "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "globalClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "getMore" ], "errorCode": 6, "closeConnection": false } } } }, { "name": "createChangeStream", "object": "collection0", "arguments": { "pipeline": [] }, "saveResultAsEntity": "changeStream0" }, { "name": "insertOne", "object": "globalCollection0", "arguments": { "document": { "x": 1 } } }, { "name": "iterateUntilDocumentOrError", "object": "changeStream0", "expectResult": { "_id": { "$$exists": true }, "documentKey": { "$$exists": true }, "operationType": "insert", "ns": { "db": "database0", "coll": "collection0" }, "fullDocument": { "x": 1, "_id": { "$$exists": true } } } } ], "expectEvents": [ { "client": "client0", "ignoreExtraEvents": true, "events": [ { "commandStartedEvent": { "command": { "aggregate": "collection0", "cursor": {}, "pipeline": [ { "$changeStream": {} } ] }, "commandName": "aggregate", "databaseName": "database0" } }, { "commandStartedEvent": { "command": { "getMore": { "$$exists": true }, "collection": "collection0" }, "commandName": "getMore", "databaseName": "database0" } }, { "commandStartedEvent": { "command": { "aggregate": "collection0", "cursor": {}, "pipeline": [ { "$changeStream": { "resumeAfter": { "$$unsetOrMatches": { "$$exists": true } } } } ] }, "commandName": "aggregate", "databaseName": "database0" } } ] } ] }, { "description": "change stream resumes after HostNotFound", "runOnRequirements": [ { "minServerVersion": "4.2", "maxServerVersion": "4.2.99" } ], "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "globalClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "getMore" ], "errorCode": 7, "closeConnection": false } } } }, { "name": "createChangeStream", "object": "collection0", "arguments": { "pipeline": [] }, "saveResultAsEntity": "changeStream0" }, { "name": "insertOne", "object": "globalCollection0", "arguments": { "document": { "x": 1 } } }, { "name": "iterateUntilDocumentOrError", "object": "changeStream0", "expectResult": { "_id": { "$$exists": true }, "documentKey": { "$$exists": true }, "operationType": "insert", "ns": { "db": "database0", "coll": "collection0" }, "fullDocument": { "x": 1, "_id": { "$$exists": true } } } } ], "expectEvents": [ { "client": "client0", "ignoreExtraEvents": true, "events": [ { "commandStartedEvent": { "command": { "aggregate": "collection0", "cursor": {}, "pipeline": [ { "$changeStream": {} } ] }, "commandName": "aggregate", "databaseName": "database0" } }, { "commandStartedEvent": { "command": { "getMore": { "$$exists": true }, "collection": "collection0" }, "commandName": "getMore", "databaseName": "database0" } }, { "commandStartedEvent": { "command": { "aggregate": "collection0", "cursor": {}, "pipeline": [ { "$changeStream": { "resumeAfter": { "$$unsetOrMatches": { "$$exists": true } } } } ] }, "commandName": "aggregate", "databaseName": "database0" } } ] } ] }, { "description": "change stream resumes after NetworkTimeout", "runOnRequirements": [ { "minServerVersion": "4.2", "maxServerVersion": "4.2.99" } ], "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "globalClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "getMore" ], "errorCode": 89, "closeConnection": false } } } }, { "name": "createChangeStream", "object": "collection0", "arguments": { "pipeline": [] }, "saveResultAsEntity": "changeStream0" }, { "name": "insertOne", "object": "globalCollection0", "arguments": { "document": { "x": 1 } } }, { "name": "iterateUntilDocumentOrError", "object": "changeStream0", "expectResult": { "_id": { "$$exists": true }, "documentKey": { "$$exists": true }, "operationType": "insert", "ns": { "db": "database0", "coll": "collection0" }, "fullDocument": { "x": 1, "_id": { "$$exists": true } } } } ], "expectEvents": [ { "client": "client0", "ignoreExtraEvents": true, "events": [ { "commandStartedEvent": { "command": { "aggregate": "collection0", "cursor": {}, "pipeline": [ { "$changeStream": {} } ] }, "commandName": "aggregate", "databaseName": "database0" } }, { "commandStartedEvent": { "command": { "getMore": { "$$exists": true }, "collection": "collection0" }, "commandName": "getMore", "databaseName": "database0" } }, { "commandStartedEvent": { "command": { "aggregate": "collection0", "cursor": {}, "pipeline": [ { "$changeStream": { "resumeAfter": { "$$unsetOrMatches": { "$$exists": true } } } } ] }, "commandName": "aggregate", "databaseName": "database0" } } ] } ] }, { "description": "change stream resumes after ShutdownInProgress", "runOnRequirements": [ { "minServerVersion": "4.2", "maxServerVersion": "4.2.99" } ], "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "globalClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "getMore" ], "errorCode": 91, "closeConnection": false } } } }, { "name": "createChangeStream", "object": "collection0", "arguments": { "pipeline": [] }, "saveResultAsEntity": "changeStream0" }, { "name": "insertOne", "object": "globalCollection0", "arguments": { "document": { "x": 1 } } }, { "name": "iterateUntilDocumentOrError", "object": "changeStream0", "expectResult": { "_id": { "$$exists": true }, "documentKey": { "$$exists": true }, "operationType": "insert", "ns": { "db": "database0", "coll": "collection0" }, "fullDocument": { "x": 1, "_id": { "$$exists": true } } } } ], "expectEvents": [ { "client": "client0", "ignoreExtraEvents": true, "events": [ { "commandStartedEvent": { "command": { "aggregate": "collection0", "cursor": {}, "pipeline": [ { "$changeStream": {} } ] }, "commandName": "aggregate", "databaseName": "database0" } }, { "commandStartedEvent": { "command": { "getMore": { "$$exists": true }, "collection": "collection0" }, "commandName": "getMore", "databaseName": "database0" } }, { "commandStartedEvent": { "command": { "aggregate": "collection0", "cursor": {}, "pipeline": [ { "$changeStream": { "resumeAfter": { "$$unsetOrMatches": { "$$exists": true } } } } ] }, "commandName": "aggregate", "databaseName": "database0" } } ] } ] }, { "description": "change stream resumes after PrimarySteppedDown", "runOnRequirements": [ { "minServerVersion": "4.2", "maxServerVersion": "4.2.99" } ], "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "globalClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "getMore" ], "errorCode": 189, "closeConnection": false } } } }, { "name": "createChangeStream", "object": "collection0", "arguments": { "pipeline": [] }, "saveResultAsEntity": "changeStream0" }, { "name": "insertOne", "object": "globalCollection0", "arguments": { "document": { "x": 1 } } }, { "name": "iterateUntilDocumentOrError", "object": "changeStream0", "expectResult": { "_id": { "$$exists": true }, "documentKey": { "$$exists": true }, "operationType": "insert", "ns": { "db": "database0", "coll": "collection0" }, "fullDocument": { "x": 1, "_id": { "$$exists": true } } } } ], "expectEvents": [ { "client": "client0", "ignoreExtraEvents": true, "events": [ { "commandStartedEvent": { "command": { "aggregate": "collection0", "cursor": {}, "pipeline": [ { "$changeStream": {} } ] }, "commandName": "aggregate", "databaseName": "database0" } }, { "commandStartedEvent": { "command": { "getMore": { "$$exists": true }, "collection": "collection0" }, "commandName": "getMore", "databaseName": "database0" } }, { "commandStartedEvent": { "command": { "aggregate": "collection0", "cursor": {}, "pipeline": [ { "$changeStream": { "resumeAfter": { "$$unsetOrMatches": { "$$exists": true } } } } ] }, "commandName": "aggregate", "databaseName": "database0" } } ] } ] }, { "description": "change stream resumes after ExceededTimeLimit", "runOnRequirements": [ { "minServerVersion": "4.2", "maxServerVersion": "4.2.99" } ], "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "globalClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "getMore" ], "errorCode": 262, "closeConnection": false } } } }, { "name": "createChangeStream", "object": "collection0", "arguments": { "pipeline": [] }, "saveResultAsEntity": "changeStream0" }, { "name": "insertOne", "object": "globalCollection0", "arguments": { "document": { "x": 1 } } }, { "name": "iterateUntilDocumentOrError", "object": "changeStream0", "expectResult": { "_id": { "$$exists": true }, "documentKey": { "$$exists": true }, "operationType": "insert", "ns": { "db": "database0", "coll": "collection0" }, "fullDocument": { "x": 1, "_id": { "$$exists": true } } } } ], "expectEvents": [ { "client": "client0", "ignoreExtraEvents": true, "events": [ { "commandStartedEvent": { "command": { "aggregate": "collection0", "cursor": {}, "pipeline": [ { "$changeStream": {} } ] }, "commandName": "aggregate", "databaseName": "database0" } }, { "commandStartedEvent": { "command": { "getMore": { "$$exists": true }, "collection": "collection0" }, "commandName": "getMore", "databaseName": "database0" } }, { "commandStartedEvent": { "command": { "aggregate": "collection0", "cursor": {}, "pipeline": [ { "$changeStream": { "resumeAfter": { "$$unsetOrMatches": { "$$exists": true } } } } ] }, "commandName": "aggregate", "databaseName": "database0" } } ] } ] }, { "description": "change stream resumes after SocketException", "runOnRequirements": [ { "minServerVersion": "4.2", "maxServerVersion": "4.2.99" } ], "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "globalClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "getMore" ], "errorCode": 9001, "closeConnection": false } } } }, { "name": "createChangeStream", "object": "collection0", "arguments": { "pipeline": [] }, "saveResultAsEntity": "changeStream0" }, { "name": "insertOne", "object": "globalCollection0", "arguments": { "document": { "x": 1 } } }, { "name": "iterateUntilDocumentOrError", "object": "changeStream0", "expectResult": { "_id": { "$$exists": true }, "documentKey": { "$$exists": true }, "operationType": "insert", "ns": { "db": "database0", "coll": "collection0" }, "fullDocument": { "x": 1, "_id": { "$$exists": true } } } } ], "expectEvents": [ { "client": "client0", "ignoreExtraEvents": true, "events": [ { "commandStartedEvent": { "command": { "aggregate": "collection0", "cursor": {}, "pipeline": [ { "$changeStream": {} } ] }, "commandName": "aggregate", "databaseName": "database0" } }, { "commandStartedEvent": { "command": { "getMore": { "$$exists": true }, "collection": "collection0" }, "commandName": "getMore", "databaseName": "database0" } }, { "commandStartedEvent": { "command": { "aggregate": "collection0", "cursor": {}, "pipeline": [ { "$changeStream": { "resumeAfter": { "$$unsetOrMatches": { "$$exists": true } } } } ] }, "commandName": "aggregate", "databaseName": "database0" } } ] } ] }, { "description": "change stream resumes after NotWritablePrimary", "runOnRequirements": [ { "minServerVersion": "4.2", "maxServerVersion": "4.2.99" } ], "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "globalClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "getMore" ], "errorCode": 10107, "closeConnection": false } } } }, { "name": "createChangeStream", "object": "collection0", "arguments": { "pipeline": [] }, "saveResultAsEntity": "changeStream0" }, { "name": "insertOne", "object": "globalCollection0", "arguments": { "document": { "x": 1 } } }, { "name": "iterateUntilDocumentOrError", "object": "changeStream0", "expectResult": { "_id": { "$$exists": true }, "documentKey": { "$$exists": true }, "operationType": "insert", "ns": { "db": "database0", "coll": "collection0" }, "fullDocument": { "x": 1, "_id": { "$$exists": true } } } } ], "expectEvents": [ { "client": "client0", "ignoreExtraEvents": true, "events": [ { "commandStartedEvent": { "command": { "aggregate": "collection0", "cursor": {}, "pipeline": [ { "$changeStream": {} } ] }, "commandName": "aggregate", "databaseName": "database0" } }, { "commandStartedEvent": { "command": { "getMore": { "$$exists": true }, "collection": "collection0" }, "commandName": "getMore", "databaseName": "database0" } }, { "commandStartedEvent": { "command": { "aggregate": "collection0", "cursor": {}, "pipeline": [ { "$changeStream": { "resumeAfter": { "$$unsetOrMatches": { "$$exists": true } } } } ] }, "commandName": "aggregate", "databaseName": "database0" } } ] } ] }, { "description": "change stream resumes after InterruptedAtShutdown", "runOnRequirements": [ { "minServerVersion": "4.2", "maxServerVersion": "4.2.99" } ], "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "globalClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "getMore" ], "errorCode": 11600, "closeConnection": false } } } }, { "name": "createChangeStream", "object": "collection0", "arguments": { "pipeline": [] }, "saveResultAsEntity": "changeStream0" }, { "name": "insertOne", "object": "globalCollection0", "arguments": { "document": { "x": 1 } } }, { "name": "iterateUntilDocumentOrError", "object": "changeStream0", "expectResult": { "_id": { "$$exists": true }, "documentKey": { "$$exists": true }, "operationType": "insert", "ns": { "db": "database0", "coll": "collection0" }, "fullDocument": { "x": 1, "_id": { "$$exists": true } } } } ], "expectEvents": [ { "client": "client0", "ignoreExtraEvents": true, "events": [ { "commandStartedEvent": { "command": { "aggregate": "collection0", "cursor": {}, "pipeline": [ { "$changeStream": {} } ] }, "commandName": "aggregate", "databaseName": "database0" } }, { "commandStartedEvent": { "command": { "getMore": { "$$exists": true }, "collection": "collection0" }, "commandName": "getMore", "databaseName": "database0" } }, { "commandStartedEvent": { "command": { "aggregate": "collection0", "cursor": {}, "pipeline": [ { "$changeStream": { "resumeAfter": { "$$unsetOrMatches": { "$$exists": true } } } } ] }, "commandName": "aggregate", "databaseName": "database0" } } ] } ] }, { "description": "change stream resumes after InterruptedDueToReplStateChange", "runOnRequirements": [ { "minServerVersion": "4.2", "maxServerVersion": "4.2.99" } ], "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "globalClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "getMore" ], "errorCode": 11602, "closeConnection": false } } } }, { "name": "createChangeStream", "object": "collection0", "arguments": { "pipeline": [] }, "saveResultAsEntity": "changeStream0" }, { "name": "insertOne", "object": "globalCollection0", "arguments": { "document": { "x": 1 } } }, { "name": "iterateUntilDocumentOrError", "object": "changeStream0", "expectResult": { "_id": { "$$exists": true }, "documentKey": { "$$exists": true }, "operationType": "insert", "ns": { "db": "database0", "coll": "collection0" }, "fullDocument": { "x": 1, "_id": { "$$exists": true } } } } ], "expectEvents": [ { "client": "client0", "ignoreExtraEvents": true, "events": [ { "commandStartedEvent": { "command": { "aggregate": "collection0", "cursor": {}, "pipeline": [ { "$changeStream": {} } ] }, "commandName": "aggregate", "databaseName": "database0" } }, { "commandStartedEvent": { "command": { "getMore": { "$$exists": true }, "collection": "collection0" }, "commandName": "getMore", "databaseName": "database0" } }, { "commandStartedEvent": { "command": { "aggregate": "collection0", "cursor": {}, "pipeline": [ { "$changeStream": { "resumeAfter": { "$$unsetOrMatches": { "$$exists": true } } } } ] }, "commandName": "aggregate", "databaseName": "database0" } } ] } ] }, { "description": "change stream resumes after NotPrimaryNoSecondaryOk", "runOnRequirements": [ { "minServerVersion": "4.2", "maxServerVersion": "4.2.99" } ], "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "globalClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "getMore" ], "errorCode": 13435, "closeConnection": false } } } }, { "name": "createChangeStream", "object": "collection0", "arguments": { "pipeline": [] }, "saveResultAsEntity": "changeStream0" }, { "name": "insertOne", "object": "globalCollection0", "arguments": { "document": { "x": 1 } } }, { "name": "iterateUntilDocumentOrError", "object": "changeStream0", "expectResult": { "_id": { "$$exists": true }, "documentKey": { "$$exists": true }, "operationType": "insert", "ns": { "db": "database0", "coll": "collection0" }, "fullDocument": { "x": 1, "_id": { "$$exists": true } } } } ], "expectEvents": [ { "client": "client0", "ignoreExtraEvents": true, "events": [ { "commandStartedEvent": { "command": { "aggregate": "collection0", "cursor": {}, "pipeline": [ { "$changeStream": {} } ] }, "commandName": "aggregate", "databaseName": "database0" } }, { "commandStartedEvent": { "command": { "getMore": { "$$exists": true }, "collection": "collection0" }, "commandName": "getMore", "databaseName": "database0" } }, { "commandStartedEvent": { "command": { "aggregate": "collection0", "cursor": {}, "pipeline": [ { "$changeStream": { "resumeAfter": { "$$unsetOrMatches": { "$$exists": true } } } } ] }, "commandName": "aggregate", "databaseName": "database0" } } ] } ] }, { "description": "change stream resumes after NotPrimaryOrSecondary", "runOnRequirements": [ { "minServerVersion": "4.2", "maxServerVersion": "4.2.99" } ], "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "globalClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "getMore" ], "errorCode": 13436, "closeConnection": false } } } }, { "name": "createChangeStream", "object": "collection0", "arguments": { "pipeline": [] }, "saveResultAsEntity": "changeStream0" }, { "name": "insertOne", "object": "globalCollection0", "arguments": { "document": { "x": 1 } } }, { "name": "iterateUntilDocumentOrError", "object": "changeStream0", "expectResult": { "_id": { "$$exists": true }, "documentKey": { "$$exists": true }, "operationType": "insert", "ns": { "db": "database0", "coll": "collection0" }, "fullDocument": { "x": 1, "_id": { "$$exists": true } } } } ], "expectEvents": [ { "client": "client0", "ignoreExtraEvents": true, "events": [ { "commandStartedEvent": { "command": { "aggregate": "collection0", "cursor": {}, "pipeline": [ { "$changeStream": {} } ] }, "commandName": "aggregate", "databaseName": "database0" } }, { "commandStartedEvent": { "command": { "getMore": { "$$exists": true }, "collection": "collection0" }, "commandName": "getMore", "databaseName": "database0" } }, { "commandStartedEvent": { "command": { "aggregate": "collection0", "cursor": {}, "pipeline": [ { "$changeStream": { "resumeAfter": { "$$unsetOrMatches": { "$$exists": true } } } } ] }, "commandName": "aggregate", "databaseName": "database0" } } ] } ] }, { "description": "change stream resumes after StaleShardVersion", "runOnRequirements": [ { "minServerVersion": "4.2", "maxServerVersion": "4.2.99" } ], "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "globalClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "getMore" ], "errorCode": 63, "closeConnection": false } } } }, { "name": "createChangeStream", "object": "collection0", "arguments": { "pipeline": [] }, "saveResultAsEntity": "changeStream0" }, { "name": "insertOne", "object": "globalCollection0", "arguments": { "document": { "x": 1 } } }, { "name": "iterateUntilDocumentOrError", "object": "changeStream0", "expectResult": { "_id": { "$$exists": true }, "documentKey": { "$$exists": true }, "operationType": "insert", "ns": { "db": "database0", "coll": "collection0" }, "fullDocument": { "x": 1, "_id": { "$$exists": true } } } } ], "expectEvents": [ { "client": "client0", "ignoreExtraEvents": true, "events": [ { "commandStartedEvent": { "command": { "aggregate": "collection0", "cursor": {}, "pipeline": [ { "$changeStream": {} } ] }, "commandName": "aggregate", "databaseName": "database0" } }, { "commandStartedEvent": { "command": { "getMore": { "$$exists": true }, "collection": "collection0" }, "commandName": "getMore", "databaseName": "database0" } }, { "commandStartedEvent": { "command": { "aggregate": "collection0", "cursor": {}, "pipeline": [ { "$changeStream": { "resumeAfter": { "$$unsetOrMatches": { "$$exists": true } } } } ] }, "commandName": "aggregate", "databaseName": "database0" } } ] } ] }, { "description": "change stream resumes after StaleEpoch", "runOnRequirements": [ { "minServerVersion": "4.2", "maxServerVersion": "4.2.99" } ], "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "globalClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "getMore" ], "errorCode": 150, "closeConnection": false } } } }, { "name": "createChangeStream", "object": "collection0", "arguments": { "pipeline": [] }, "saveResultAsEntity": "changeStream0" }, { "name": "insertOne", "object": "globalCollection0", "arguments": { "document": { "x": 1 } } }, { "name": "iterateUntilDocumentOrError", "object": "changeStream0", "expectResult": { "_id": { "$$exists": true }, "documentKey": { "$$exists": true }, "operationType": "insert", "ns": { "db": "database0", "coll": "collection0" }, "fullDocument": { "x": 1, "_id": { "$$exists": true } } } } ], "expectEvents": [ { "client": "client0", "ignoreExtraEvents": true, "events": [ { "commandStartedEvent": { "command": { "aggregate": "collection0", "cursor": {}, "pipeline": [ { "$changeStream": {} } ] }, "commandName": "aggregate", "databaseName": "database0" } }, { "commandStartedEvent": { "command": { "getMore": { "$$exists": true }, "collection": "collection0" }, "commandName": "getMore", "databaseName": "database0" } }, { "commandStartedEvent": { "command": { "aggregate": "collection0", "cursor": {}, "pipeline": [ { "$changeStream": { "resumeAfter": { "$$unsetOrMatches": { "$$exists": true } } } } ] }, "commandName": "aggregate", "databaseName": "database0" } } ] } ] }, { "description": "change stream resumes after RetryChangeStream", "runOnRequirements": [ { "minServerVersion": "4.2", "maxServerVersion": "4.2.99" } ], "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "globalClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "getMore" ], "errorCode": 234, "closeConnection": false } } } }, { "name": "createChangeStream", "object": "collection0", "arguments": { "pipeline": [] }, "saveResultAsEntity": "changeStream0" }, { "name": "insertOne", "object": "globalCollection0", "arguments": { "document": { "x": 1 } } }, { "name": "iterateUntilDocumentOrError", "object": "changeStream0", "expectResult": { "_id": { "$$exists": true }, "documentKey": { "$$exists": true }, "operationType": "insert", "ns": { "db": "database0", "coll": "collection0" }, "fullDocument": { "x": 1, "_id": { "$$exists": true } } } } ], "expectEvents": [ { "client": "client0", "ignoreExtraEvents": true, "events": [ { "commandStartedEvent": { "command": { "aggregate": "collection0", "cursor": {}, "pipeline": [ { "$changeStream": {} } ] }, "commandName": "aggregate", "databaseName": "database0" } }, { "commandStartedEvent": { "command": { "getMore": { "$$exists": true }, "collection": "collection0" }, "commandName": "getMore", "databaseName": "database0" } }, { "commandStartedEvent": { "command": { "aggregate": "collection0", "cursor": {}, "pipeline": [ { "$changeStream": { "resumeAfter": { "$$unsetOrMatches": { "$$exists": true } } } } ] }, "commandName": "aggregate", "databaseName": "database0" } } ] } ] }, { "description": "change stream resumes after FailedToSatisfyReadPreference", "runOnRequirements": [ { "minServerVersion": "4.2", "maxServerVersion": "4.2.99" } ], "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "globalClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "getMore" ], "errorCode": 133, "closeConnection": false } } } }, { "name": "createChangeStream", "object": "collection0", "arguments": { "pipeline": [] }, "saveResultAsEntity": "changeStream0" }, { "name": "insertOne", "object": "globalCollection0", "arguments": { "document": { "x": 1 } } }, { "name": "iterateUntilDocumentOrError", "object": "changeStream0", "expectResult": { "_id": { "$$exists": true }, "documentKey": { "$$exists": true }, "operationType": "insert", "ns": { "db": "database0", "coll": "collection0" }, "fullDocument": { "x": 1, "_id": { "$$exists": true } } } } ], "expectEvents": [ { "client": "client0", "ignoreExtraEvents": true, "events": [ { "commandStartedEvent": { "command": { "aggregate": "collection0", "cursor": {}, "pipeline": [ { "$changeStream": {} } ] }, "commandName": "aggregate", "databaseName": "database0" } }, { "commandStartedEvent": { "command": { "getMore": { "$$exists": true }, "collection": "collection0" }, "commandName": "getMore", "databaseName": "database0" } }, { "commandStartedEvent": { "command": { "aggregate": "collection0", "cursor": {}, "pipeline": [ { "$changeStream": { "resumeAfter": { "$$unsetOrMatches": { "$$exists": true } } } } ] }, "commandName": "aggregate", "databaseName": "database0" } } ] } ] }, { "description": "change stream resumes after CursorNotFound", "runOnRequirements": [ { "minServerVersion": "4.2" } ], "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "globalClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "getMore" ], "errorCode": 43, "closeConnection": false } } } }, { "name": "createChangeStream", "object": "collection0", "arguments": { "pipeline": [] }, "saveResultAsEntity": "changeStream0" }, { "name": "insertOne", "object": "globalCollection0", "arguments": { "document": { "x": 1 } } }, { "name": "iterateUntilDocumentOrError", "object": "changeStream0", "expectResult": { "_id": { "$$exists": true }, "documentKey": { "$$exists": true }, "operationType": "insert", "ns": { "db": "database0", "coll": "collection0" }, "fullDocument": { "x": 1, "_id": { "$$exists": true } } } } ], "expectEvents": [ { "client": "client0", "ignoreExtraEvents": true, "events": [ { "commandStartedEvent": { "command": { "aggregate": "collection0", "cursor": {}, "pipeline": [ { "$changeStream": {} } ] }, "commandName": "aggregate", "databaseName": "database0" } }, { "commandStartedEvent": { "command": { "getMore": { "$$exists": true }, "collection": "collection0" }, "commandName": "getMore", "databaseName": "database0" } }, { "commandStartedEvent": { "command": { "aggregate": "collection0", "cursor": {}, "pipeline": [ { "$changeStream": { "resumeAfter": { "$$unsetOrMatches": { "$$exists": true } } } } ] }, "commandName": "aggregate", "databaseName": "database0" } } ] } ] } ] } change-streams-resume-errorLabels.json000066400000000000000000001551721462766011000343220ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/change_streams/unified{ "description": "change-streams-resume-errorlabels", "schemaVersion": "1.7", "runOnRequirements": [ { "minServerVersion": "4.3.1", "topologies": [ "replicaset", "sharded-replicaset", "load-balanced" ], "serverless": "forbid" } ], "createEntities": [ { "client": { "id": "client0", "observeEvents": [ "commandStartedEvent" ], "ignoreCommandMonitoringEvents": [ "killCursors" ], "useMultipleMongoses": false } }, { "client": { "id": "globalClient", "useMultipleMongoses": false } }, { "database": { "id": "database0", "client": "client0", "databaseName": "database0" } }, { "collection": { "id": "collection0", "database": "database0", "collectionName": "collection0" } }, { "database": { "id": "globalDatabase0", "client": "globalClient", "databaseName": "database0" } }, { "collection": { "id": "globalCollection0", "database": "globalDatabase0", "collectionName": "collection0" } } ], "tests": [ { "description": "change stream resumes after HostUnreachable", "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "globalClient", "failPoint": { "configureFailPoint": "failGetMoreAfterCursorCheckout", "mode": { "times": 1 }, "data": { "errorCode": 6, "closeConnection": false } } } }, { "name": "createChangeStream", "object": "collection0", "arguments": { "pipeline": [] }, "saveResultAsEntity": "changeStream0" }, { "name": "insertOne", "object": "globalCollection0", "arguments": { "document": { "x": 1 } } }, { "name": "iterateUntilDocumentOrError", "object": "changeStream0", "expectResult": { "_id": { "$$exists": true }, "documentKey": { "$$exists": true }, "operationType": "insert", "ns": { "db": "database0", "coll": "collection0" }, "fullDocument": { "x": 1, "_id": { "$$exists": true } } } } ], "expectEvents": [ { "client": "client0", "ignoreExtraEvents": true, "events": [ { "commandStartedEvent": { "command": { "aggregate": "collection0", "cursor": {}, "pipeline": [ { "$changeStream": {} } ] }, "commandName": "aggregate", "databaseName": "database0" } }, { "commandStartedEvent": { "command": { "getMore": { "$$exists": true }, "collection": "collection0" }, "commandName": "getMore", "databaseName": "database0" } }, { "commandStartedEvent": { "command": { "aggregate": "collection0", "cursor": {}, "pipeline": [ { "$changeStream": { "resumeAfter": { "$$unsetOrMatches": { "$$exists": true } } } } ] }, "commandName": "aggregate", "databaseName": "database0" } } ] } ] }, { "description": "change stream resumes after HostNotFound", "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "globalClient", "failPoint": { "configureFailPoint": "failGetMoreAfterCursorCheckout", "mode": { "times": 1 }, "data": { "errorCode": 7, "closeConnection": false } } } }, { "name": "createChangeStream", "object": "collection0", "arguments": { "pipeline": [] }, "saveResultAsEntity": "changeStream0" }, { "name": "insertOne", "object": "globalCollection0", "arguments": { "document": { "x": 1 } } }, { "name": "iterateUntilDocumentOrError", "object": "changeStream0", "expectResult": { "_id": { "$$exists": true }, "documentKey": { "$$exists": true }, "operationType": "insert", "ns": { "db": "database0", "coll": "collection0" }, "fullDocument": { "x": 1, "_id": { "$$exists": true } } } } ], "expectEvents": [ { "client": "client0", "ignoreExtraEvents": true, "events": [ { "commandStartedEvent": { "command": { "aggregate": "collection0", "cursor": {}, "pipeline": [ { "$changeStream": {} } ] }, "commandName": "aggregate", "databaseName": "database0" } }, { "commandStartedEvent": { "command": { "getMore": { "$$exists": true }, "collection": "collection0" }, "commandName": "getMore", "databaseName": "database0" } }, { "commandStartedEvent": { "command": { "aggregate": "collection0", "cursor": {}, "pipeline": [ { "$changeStream": { "resumeAfter": { "$$unsetOrMatches": { "$$exists": true } } } } ] }, "commandName": "aggregate", "databaseName": "database0" } } ] } ] }, { "description": "change stream resumes after NetworkTimeout", "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "globalClient", "failPoint": { "configureFailPoint": "failGetMoreAfterCursorCheckout", "mode": { "times": 1 }, "data": { "errorCode": 89, "closeConnection": false } } } }, { "name": "createChangeStream", "object": "collection0", "arguments": { "pipeline": [] }, "saveResultAsEntity": "changeStream0" }, { "name": "insertOne", "object": "globalCollection0", "arguments": { "document": { "x": 1 } } }, { "name": "iterateUntilDocumentOrError", "object": "changeStream0", "expectResult": { "_id": { "$$exists": true }, "documentKey": { "$$exists": true }, "operationType": "insert", "ns": { "db": "database0", "coll": "collection0" }, "fullDocument": { "x": 1, "_id": { "$$exists": true } } } } ], "expectEvents": [ { "client": "client0", "ignoreExtraEvents": true, "events": [ { "commandStartedEvent": { "command": { "aggregate": "collection0", "cursor": {}, "pipeline": [ { "$changeStream": {} } ] }, "commandName": "aggregate", "databaseName": "database0" } }, { "commandStartedEvent": { "command": { "getMore": { "$$exists": true }, "collection": "collection0" }, "commandName": "getMore", "databaseName": "database0" } }, { "commandStartedEvent": { "command": { "aggregate": "collection0", "cursor": {}, "pipeline": [ { "$changeStream": { "resumeAfter": { "$$unsetOrMatches": { "$$exists": true } } } } ] }, "commandName": "aggregate" } } ] } ] }, { "description": "change stream resumes after ShutdownInProgress", "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "globalClient", "failPoint": { "configureFailPoint": "failGetMoreAfterCursorCheckout", "mode": { "times": 1 }, "data": { "errorCode": 91, "closeConnection": false } } } }, { "name": "createChangeStream", "object": "collection0", "arguments": { "pipeline": [] }, "saveResultAsEntity": "changeStream0" }, { "name": "insertOne", "object": "globalCollection0", "arguments": { "document": { "x": 1 } } }, { "name": "iterateUntilDocumentOrError", "object": "changeStream0", "expectResult": { "_id": { "$$exists": true }, "documentKey": { "$$exists": true }, "operationType": "insert", "ns": { "db": "database0", "coll": "collection0" }, "fullDocument": { "x": 1, "_id": { "$$exists": true } } } } ], "expectEvents": [ { "client": "client0", "ignoreExtraEvents": true, "events": [ { "commandStartedEvent": { "command": { "aggregate": "collection0", "cursor": {}, "pipeline": [ { "$changeStream": {} } ] }, "commandName": "aggregate", "databaseName": "database0" } }, { "commandStartedEvent": { "command": { "getMore": { "$$exists": true }, "collection": "collection0" }, "commandName": "getMore", "databaseName": "database0" } }, { "commandStartedEvent": { "command": { "aggregate": "collection0", "cursor": {}, "pipeline": [ { "$changeStream": { "resumeAfter": { "$$unsetOrMatches": { "$$exists": true } } } } ] }, "commandName": "aggregate", "databaseName": "database0" } } ] } ] }, { "description": "change stream resumes after PrimarySteppedDown", "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "globalClient", "failPoint": { "configureFailPoint": "failGetMoreAfterCursorCheckout", "mode": { "times": 1 }, "data": { "errorCode": 189, "closeConnection": false } } } }, { "name": "createChangeStream", "object": "collection0", "arguments": { "pipeline": [] }, "saveResultAsEntity": "changeStream0" }, { "name": "insertOne", "object": "globalCollection0", "arguments": { "document": { "x": 1 } } }, { "name": "iterateUntilDocumentOrError", "object": "changeStream0", "expectResult": { "_id": { "$$exists": true }, "documentKey": { "$$exists": true }, "operationType": "insert", "ns": { "db": "database0", "coll": "collection0" }, "fullDocument": { "x": 1, "_id": { "$$exists": true } } } } ], "expectEvents": [ { "client": "client0", "ignoreExtraEvents": true, "events": [ { "commandStartedEvent": { "command": { "aggregate": "collection0", "cursor": {}, "pipeline": [ { "$changeStream": {} } ] }, "commandName": "aggregate", "databaseName": "database0" } }, { "commandStartedEvent": { "command": { "getMore": { "$$exists": true }, "collection": "collection0" }, "commandName": "getMore", "databaseName": "database0" } }, { "commandStartedEvent": { "command": { "aggregate": "collection0", "cursor": {}, "pipeline": [ { "$changeStream": { "resumeAfter": { "$$unsetOrMatches": { "$$exists": true } } } } ] }, "commandName": "aggregate", "databaseName": "database0" } } ] } ] }, { "description": "change stream resumes after ExceededTimeLimit", "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "globalClient", "failPoint": { "configureFailPoint": "failGetMoreAfterCursorCheckout", "mode": { "times": 1 }, "data": { "errorCode": 262, "closeConnection": false } } } }, { "name": "createChangeStream", "object": "collection0", "arguments": { "pipeline": [] }, "saveResultAsEntity": "changeStream0" }, { "name": "insertOne", "object": "globalCollection0", "arguments": { "document": { "x": 1 } } }, { "name": "iterateUntilDocumentOrError", "object": "changeStream0", "expectResult": { "_id": { "$$exists": true }, "documentKey": { "$$exists": true }, "operationType": "insert", "ns": { "db": "database0", "coll": "collection0" }, "fullDocument": { "x": 1, "_id": { "$$exists": true } } } } ], "expectEvents": [ { "client": "client0", "ignoreExtraEvents": true, "events": [ { "commandStartedEvent": { "command": { "aggregate": "collection0", "cursor": {}, "pipeline": [ { "$changeStream": {} } ] }, "commandName": "aggregate", "databaseName": "database0" } }, { "commandStartedEvent": { "command": { "getMore": { "$$exists": true }, "collection": "collection0" }, "commandName": "getMore", "databaseName": "database0" } }, { "commandStartedEvent": { "command": { "aggregate": "collection0", "cursor": {}, "pipeline": [ { "$changeStream": { "resumeAfter": { "$$unsetOrMatches": { "$$exists": true } } } } ] }, "commandName": "aggregate", "databaseName": "database0" } } ] } ] }, { "description": "change stream resumes after SocketException", "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "globalClient", "failPoint": { "configureFailPoint": "failGetMoreAfterCursorCheckout", "mode": { "times": 1 }, "data": { "errorCode": 9001, "closeConnection": false } } } }, { "name": "createChangeStream", "object": "collection0", "arguments": { "pipeline": [] }, "saveResultAsEntity": "changeStream0" }, { "name": "insertOne", "object": "globalCollection0", "arguments": { "document": { "x": 1 } } }, { "name": "iterateUntilDocumentOrError", "object": "changeStream0", "expectResult": { "_id": { "$$exists": true }, "documentKey": { "$$exists": true }, "operationType": "insert", "ns": { "db": "database0", "coll": "collection0" }, "fullDocument": { "x": 1, "_id": { "$$exists": true } } } } ], "expectEvents": [ { "client": "client0", "ignoreExtraEvents": true, "events": [ { "commandStartedEvent": { "command": { "aggregate": "collection0", "cursor": {}, "pipeline": [ { "$changeStream": {} } ] }, "commandName": "aggregate", "databaseName": "database0" } }, { "commandStartedEvent": { "command": { "getMore": { "$$exists": true }, "collection": "collection0" }, "commandName": "getMore", "databaseName": "database0" } }, { "commandStartedEvent": { "command": { "aggregate": "collection0", "cursor": {}, "pipeline": [ { "$changeStream": { "resumeAfter": { "$$unsetOrMatches": { "$$exists": true } } } } ] }, "commandName": "aggregate", "databaseName": "database0" } } ] } ] }, { "description": "change stream resumes after NotWritablePrimary", "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "globalClient", "failPoint": { "configureFailPoint": "failGetMoreAfterCursorCheckout", "mode": { "times": 1 }, "data": { "errorCode": 10107, "closeConnection": false } } } }, { "name": "createChangeStream", "object": "collection0", "arguments": { "pipeline": [] }, "saveResultAsEntity": "changeStream0" }, { "name": "insertOne", "object": "globalCollection0", "arguments": { "document": { "x": 1 } } }, { "name": "iterateUntilDocumentOrError", "object": "changeStream0", "expectResult": { "_id": { "$$exists": true }, "documentKey": { "$$exists": true }, "operationType": "insert", "ns": { "db": "database0", "coll": "collection0" }, "fullDocument": { "x": 1, "_id": { "$$exists": true } } } } ], "expectEvents": [ { "client": "client0", "ignoreExtraEvents": true, "events": [ { "commandStartedEvent": { "command": { "aggregate": "collection0", "cursor": {}, "pipeline": [ { "$changeStream": {} } ] }, "commandName": "aggregate", "databaseName": "database0" } }, { "commandStartedEvent": { "command": { "getMore": { "$$exists": true }, "collection": "collection0" }, "commandName": "getMore", "databaseName": "database0" } }, { "commandStartedEvent": { "command": { "aggregate": "collection0", "cursor": {}, "pipeline": [ { "$changeStream": { "resumeAfter": { "$$unsetOrMatches": { "$$exists": true } } } } ] }, "commandName": "aggregate", "databaseName": "database0" } } ] } ] }, { "description": "change stream resumes after InterruptedAtShutdown", "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "globalClient", "failPoint": { "configureFailPoint": "failGetMoreAfterCursorCheckout", "mode": { "times": 1 }, "data": { "errorCode": 11600, "closeConnection": false } } } }, { "name": "createChangeStream", "object": "collection0", "arguments": { "pipeline": [] }, "saveResultAsEntity": "changeStream0" }, { "name": "insertOne", "object": "globalCollection0", "arguments": { "document": { "x": 1 } } }, { "name": "iterateUntilDocumentOrError", "object": "changeStream0", "expectResult": { "_id": { "$$exists": true }, "documentKey": { "$$exists": true }, "operationType": "insert", "ns": { "db": "database0", "coll": "collection0" }, "fullDocument": { "x": 1, "_id": { "$$exists": true } } } } ], "expectEvents": [ { "client": "client0", "ignoreExtraEvents": true, "events": [ { "commandStartedEvent": { "command": { "aggregate": "collection0", "cursor": {}, "pipeline": [ { "$changeStream": {} } ] }, "commandName": "aggregate", "databaseName": "database0" } }, { "commandStartedEvent": { "command": { "getMore": { "$$exists": true }, "collection": "collection0" }, "commandName": "getMore", "databaseName": "database0" } }, { "commandStartedEvent": { "command": { "aggregate": "collection0", "cursor": {}, "pipeline": [ { "$changeStream": { "resumeAfter": { "$$unsetOrMatches": { "$$exists": true } } } } ] }, "commandName": "aggregate", "databaseName": "database0" } } ] } ] }, { "description": "change stream resumes after InterruptedDueToReplStateChange", "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "globalClient", "failPoint": { "configureFailPoint": "failGetMoreAfterCursorCheckout", "mode": { "times": 1 }, "data": { "errorCode": 11602, "closeConnection": false } } } }, { "name": "createChangeStream", "object": "collection0", "arguments": { "pipeline": [] }, "saveResultAsEntity": "changeStream0" }, { "name": "insertOne", "object": "globalCollection0", "arguments": { "document": { "x": 1 } } }, { "name": "iterateUntilDocumentOrError", "object": "changeStream0", "expectResult": { "_id": { "$$exists": true }, "documentKey": { "$$exists": true }, "operationType": "insert", "ns": { "db": "database0", "coll": "collection0" }, "fullDocument": { "x": 1, "_id": { "$$exists": true } } } } ], "expectEvents": [ { "client": "client0", "ignoreExtraEvents": true, "events": [ { "commandStartedEvent": { "command": { "aggregate": "collection0", "cursor": {}, "pipeline": [ { "$changeStream": {} } ] }, "commandName": "aggregate", "databaseName": "database0" } }, { "commandStartedEvent": { "command": { "getMore": { "$$exists": true }, "collection": "collection0" }, "commandName": "getMore", "databaseName": "database0" } }, { "commandStartedEvent": { "command": { "aggregate": "collection0", "cursor": {}, "pipeline": [ { "$changeStream": { "resumeAfter": { "$$unsetOrMatches": { "$$exists": true } } } } ] }, "commandName": "aggregate", "databaseName": "database0" } } ] } ] }, { "description": "change stream resumes after NotPrimaryNoSecondaryOk", "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "globalClient", "failPoint": { "configureFailPoint": "failGetMoreAfterCursorCheckout", "mode": { "times": 1 }, "data": { "errorCode": 13435, "closeConnection": false } } } }, { "name": "createChangeStream", "object": "collection0", "arguments": { "pipeline": [] }, "saveResultAsEntity": "changeStream0" }, { "name": "insertOne", "object": "globalCollection0", "arguments": { "document": { "x": 1 } } }, { "name": "iterateUntilDocumentOrError", "object": "changeStream0", "expectResult": { "_id": { "$$exists": true }, "documentKey": { "$$exists": true }, "operationType": "insert", "ns": { "db": "database0", "coll": "collection0" }, "fullDocument": { "x": 1, "_id": { "$$exists": true } } } } ], "expectEvents": [ { "client": "client0", "ignoreExtraEvents": true, "events": [ { "commandStartedEvent": { "command": { "aggregate": "collection0", "cursor": {}, "pipeline": [ { "$changeStream": {} } ] }, "commandName": "aggregate", "databaseName": "database0" } }, { "commandStartedEvent": { "command": { "getMore": { "$$exists": true }, "collection": "collection0" }, "commandName": "getMore", "databaseName": "database0" } }, { "commandStartedEvent": { "command": { "aggregate": "collection0", "cursor": {}, "pipeline": [ { "$changeStream": { "resumeAfter": { "$$unsetOrMatches": { "$$exists": true } } } } ] }, "commandName": "aggregate", "databaseName": "database0" } } ] } ] }, { "description": "change stream resumes after NotPrimaryOrSecondary", "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "globalClient", "failPoint": { "configureFailPoint": "failGetMoreAfterCursorCheckout", "mode": { "times": 1 }, "data": { "errorCode": 13436, "closeConnection": false } } } }, { "name": "createChangeStream", "object": "collection0", "arguments": { "pipeline": [] }, "saveResultAsEntity": "changeStream0" }, { "name": "insertOne", "object": "globalCollection0", "arguments": { "document": { "x": 1 } } }, { "name": "iterateUntilDocumentOrError", "object": "changeStream0", "expectResult": { "_id": { "$$exists": true }, "documentKey": { "$$exists": true }, "operationType": "insert", "ns": { "db": "database0", "coll": "collection0" }, "fullDocument": { "x": 1, "_id": { "$$exists": true } } } } ], "expectEvents": [ { "client": "client0", "ignoreExtraEvents": true, "events": [ { "commandStartedEvent": { "command": { "aggregate": "collection0", "cursor": {}, "pipeline": [ { "$changeStream": {} } ] }, "commandName": "aggregate", "databaseName": "database0" } }, { "commandStartedEvent": { "command": { "getMore": { "$$exists": true }, "collection": "collection0" }, "commandName": "getMore", "databaseName": "database0" } }, { "commandStartedEvent": { "command": { "aggregate": "collection0", "cursor": {}, "pipeline": [ { "$changeStream": { "resumeAfter": { "$$unsetOrMatches": { "$$exists": true } } } } ] }, "commandName": "aggregate", "databaseName": "database0" } } ] } ] }, { "description": "change stream resumes after StaleShardVersion", "runOnRequirements": [ { "maxServerVersion": "6.0.99" } ], "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "globalClient", "failPoint": { "configureFailPoint": "failGetMoreAfterCursorCheckout", "mode": { "times": 1 }, "data": { "errorCode": 63, "closeConnection": false } } } }, { "name": "createChangeStream", "object": "collection0", "arguments": { "pipeline": [] }, "saveResultAsEntity": "changeStream0" }, { "name": "insertOne", "object": "globalCollection0", "arguments": { "document": { "x": 1 } } }, { "name": "iterateUntilDocumentOrError", "object": "changeStream0", "expectResult": { "_id": { "$$exists": true }, "documentKey": { "$$exists": true }, "operationType": "insert", "ns": { "db": "database0", "coll": "collection0" }, "fullDocument": { "x": 1, "_id": { "$$exists": true } } } } ], "expectEvents": [ { "client": "client0", "ignoreExtraEvents": true, "events": [ { "commandStartedEvent": { "command": { "aggregate": "collection0", "cursor": {}, "pipeline": [ { "$changeStream": {} } ] }, "commandName": "aggregate", "databaseName": "database0" } }, { "commandStartedEvent": { "command": { "getMore": { "$$exists": true }, "collection": "collection0" }, "commandName": "getMore", "databaseName": "database0" } }, { "commandStartedEvent": { "command": { "aggregate": "collection0", "cursor": {}, "pipeline": [ { "$changeStream": { "resumeAfter": { "$$unsetOrMatches": { "$$exists": true } } } } ] }, "commandName": "aggregate", "databaseName": "database0" } } ] } ] }, { "description": "change stream resumes after StaleEpoch", "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "globalClient", "failPoint": { "configureFailPoint": "failGetMoreAfterCursorCheckout", "mode": { "times": 1 }, "data": { "errorCode": 150, "closeConnection": false } } } }, { "name": "createChangeStream", "object": "collection0", "arguments": { "pipeline": [] }, "saveResultAsEntity": "changeStream0" }, { "name": "insertOne", "object": "globalCollection0", "arguments": { "document": { "x": 1 } } }, { "name": "iterateUntilDocumentOrError", "object": "changeStream0", "expectResult": { "_id": { "$$exists": true }, "documentKey": { "$$exists": true }, "operationType": "insert", "ns": { "db": "database0", "coll": "collection0" }, "fullDocument": { "x": 1, "_id": { "$$exists": true } } } } ], "expectEvents": [ { "client": "client0", "ignoreExtraEvents": true, "events": [ { "commandStartedEvent": { "command": { "aggregate": "collection0", "cursor": {}, "pipeline": [ { "$changeStream": {} } ] }, "commandName": "aggregate", "databaseName": "database0" } }, { "commandStartedEvent": { "command": { "getMore": { "$$exists": true }, "collection": "collection0" }, "commandName": "getMore", "databaseName": "database0" } }, { "commandStartedEvent": { "command": { "aggregate": "collection0", "cursor": {}, "pipeline": [ { "$changeStream": { "resumeAfter": { "$$unsetOrMatches": { "$$exists": true } } } } ] }, "commandName": "aggregate", "databaseName": "database0" } } ] } ] }, { "description": "change stream resumes after RetryChangeStream", "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "globalClient", "failPoint": { "configureFailPoint": "failGetMoreAfterCursorCheckout", "mode": { "times": 1 }, "data": { "errorCode": 234, "closeConnection": false } } } }, { "name": "createChangeStream", "object": "collection0", "arguments": { "pipeline": [] }, "saveResultAsEntity": "changeStream0" }, { "name": "insertOne", "object": "globalCollection0", "arguments": { "document": { "x": 1 } } }, { "name": "iterateUntilDocumentOrError", "object": "changeStream0", "expectResult": { "_id": { "$$exists": true }, "documentKey": { "$$exists": true }, "operationType": "insert", "ns": { "db": "database0", "coll": "collection0" }, "fullDocument": { "x": 1, "_id": { "$$exists": true } } } } ], "expectEvents": [ { "client": "client0", "ignoreExtraEvents": true, "events": [ { "commandStartedEvent": { "command": { "aggregate": "collection0", "cursor": {}, "pipeline": [ { "$changeStream": {} } ] }, "commandName": "aggregate", "databaseName": "database0" } }, { "commandStartedEvent": { "command": { "getMore": { "$$exists": true }, "collection": "collection0" }, "commandName": "getMore", "databaseName": "database0" } }, { "commandStartedEvent": { "command": { "aggregate": "collection0", "cursor": {}, "pipeline": [ { "$changeStream": { "resumeAfter": { "$$unsetOrMatches": { "$$exists": true } } } } ] }, "commandName": "aggregate", "databaseName": "database0" } } ] } ] }, { "description": "change stream resumes after FailedToSatisfyReadPreference", "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "globalClient", "failPoint": { "configureFailPoint": "failGetMoreAfterCursorCheckout", "mode": { "times": 1 }, "data": { "errorCode": 133, "closeConnection": false } } } }, { "name": "createChangeStream", "object": "collection0", "arguments": { "pipeline": [] }, "saveResultAsEntity": "changeStream0" }, { "name": "insertOne", "object": "globalCollection0", "arguments": { "document": { "x": 1 } } }, { "name": "iterateUntilDocumentOrError", "object": "changeStream0", "expectResult": { "_id": { "$$exists": true }, "documentKey": { "$$exists": true }, "operationType": "insert", "ns": { "db": "database0", "coll": "collection0" }, "fullDocument": { "x": 1, "_id": { "$$exists": true } } } } ], "expectEvents": [ { "client": "client0", "ignoreExtraEvents": true, "events": [ { "commandStartedEvent": { "command": { "aggregate": "collection0", "cursor": {}, "pipeline": [ { "$changeStream": {} } ] }, "commandName": "aggregate", "databaseName": "database0" } }, { "commandStartedEvent": { "command": { "getMore": { "$$exists": true }, "collection": "collection0" }, "commandName": "getMore", "databaseName": "database0" } }, { "commandStartedEvent": { "command": { "aggregate": "collection0", "cursor": {}, "pipeline": [ { "$changeStream": { "resumeAfter": { "$$unsetOrMatches": { "$$exists": true } } } } ] }, "commandName": "aggregate", "databaseName": "database0" } } ] } ] }, { "description": "change stream resumes if error contains ResumableChangeStreamError", "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "globalClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "getMore" ], "errorCode": 50, "closeConnection": false, "errorLabels": [ "ResumableChangeStreamError" ] } } } }, { "name": "createChangeStream", "object": "collection0", "arguments": { "pipeline": [] }, "saveResultAsEntity": "changeStream0" }, { "name": "insertOne", "object": "globalCollection0", "arguments": { "document": { "x": 1 } } }, { "name": "iterateUntilDocumentOrError", "object": "changeStream0", "expectResult": { "_id": { "$$exists": true }, "documentKey": { "$$exists": true }, "operationType": "insert", "ns": { "db": "database0", "coll": "collection0" }, "fullDocument": { "x": 1, "_id": { "$$exists": true } } } } ], "expectEvents": [ { "client": "client0", "ignoreExtraEvents": true, "events": [ { "commandStartedEvent": { "command": { "aggregate": "collection0", "cursor": {}, "pipeline": [ { "$changeStream": {} } ] }, "commandName": "aggregate", "databaseName": "database0" } }, { "commandStartedEvent": { "command": { "getMore": { "$$exists": true }, "collection": "collection0" }, "commandName": "getMore", "databaseName": "database0" } }, { "commandStartedEvent": { "command": { "aggregate": "collection0", "cursor": {}, "pipeline": [ { "$changeStream": { "resumeAfter": { "$$unsetOrMatches": { "$$exists": true } } } } ] }, "commandName": "aggregate", "databaseName": "database0" } } ] } ] }, { "description": "change stream does not resume if error does not contain ResumableChangeStreamError", "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "globalClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "getMore" ], "errorCode": 6, "closeConnection": false } } } }, { "name": "createChangeStream", "object": "collection0", "arguments": { "pipeline": [] }, "saveResultAsEntity": "changeStream0" }, { "name": "insertOne", "object": "globalCollection0", "arguments": { "document": { "x": 1 } } }, { "name": "iterateUntilDocumentOrError", "object": "changeStream0", "expectError": { "errorCode": 6 } } ] } ] } change-streams-showExpandedEvents.json000066400000000000000000000304561462766011000343630ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/change_streams/unified{ "description": "change-streams-showExpandedEvents", "schemaVersion": "1.7", "runOnRequirements": [ { "minServerVersion": "6.0.0", "topologies": [ "replicaset", "sharded-replicaset", "sharded" ] } ], "createEntities": [ { "client": { "id": "client0", "observeEvents": [ "commandStartedEvent" ], "ignoreCommandMonitoringEvents": [ "killCursors" ], "useMultipleMongoses": false } }, { "database": { "id": "database0", "client": "client0", "databaseName": "database0" } }, { "collection": { "id": "collection0", "database": "database0", "collectionName": "collection0" } }, { "database": { "id": "database1", "client": "client0", "databaseName": "database1" } }, { "collection": { "id": "collection1", "database": "database1", "collectionName": "collection1" } }, { "database": { "id": "shardedDb", "client": "client0", "databaseName": "shardedDb" } }, { "database": { "id": "adminDb", "client": "client0", "databaseName": "admin" } }, { "collection": { "id": "shardedCollection", "database": "shardedDb", "collectionName": "shardedCollection" } } ], "initialData": [ { "collectionName": "collection0", "databaseName": "database0", "documents": [] } ], "tests": [ { "description": "when provided, showExpandedEvents is sent as a part of the aggregate command", "operations": [ { "name": "createChangeStream", "object": "collection0", "arguments": { "pipeline": [], "showExpandedEvents": true }, "saveResultAsEntity": "changeStream0" } ], "expectEvents": [ { "client": "client0", "ignoreExtraEvents": true, "events": [ { "commandStartedEvent": { "command": { "aggregate": "collection0", "cursor": {}, "pipeline": [ { "$changeStream": { "showExpandedEvents": true } } ] }, "commandName": "aggregate", "databaseName": "database0" } } ] } ] }, { "description": "when omitted, showExpandedEvents is not sent as a part of the aggregate command", "operations": [ { "name": "createChangeStream", "object": "collection0", "arguments": { "pipeline": [] }, "saveResultAsEntity": "changeStream0" } ], "expectEvents": [ { "client": "client0", "ignoreExtraEvents": true, "events": [ { "commandStartedEvent": { "command": { "aggregate": "collection0", "cursor": {}, "pipeline": [ { "$changeStream": { "showExpandedEvents": { "$$exists": false } } } ] }, "commandName": "aggregate", "databaseName": "database0" } } ] } ] }, { "description": "when showExpandedEvents is true, new fields on change stream events are handled appropriately", "operations": [ { "name": "dropCollection", "object": "database0", "arguments": { "collection": "foo" } }, { "name": "createCollection", "object": "database0", "arguments": { "collection": "foo" } }, { "name": "createChangeStream", "object": "collection0", "arguments": { "pipeline": [], "showExpandedEvents": true }, "saveResultAsEntity": "changeStream0" }, { "name": "insertOne", "object": "collection0", "arguments": { "document": { "a": 1 } } }, { "name": "createIndex", "object": "collection0", "arguments": { "keys": { "x": 1 }, "name": "x_1" } }, { "name": "rename", "object": "collection0", "arguments": { "to": "foo", "dropTarget": true } }, { "name": "iterateUntilDocumentOrError", "object": "changeStream0", "expectResult": { "operationType": "insert", "ns": { "db": "database0", "coll": "collection0" }, "collectionUUID": { "$$exists": true } } }, { "name": "iterateUntilDocumentOrError", "object": "changeStream0", "expectResult": { "operationType": "createIndexes", "ns": { "db": "database0", "coll": "collection0" }, "operationDescription": { "$$exists": true } } }, { "name": "iterateUntilDocumentOrError", "object": "changeStream0", "expectResult": { "operationType": "rename", "ns": { "db": "database0", "coll": "collection0" }, "to": { "db": "database0", "coll": "foo" }, "operationDescription": { "dropTarget": { "$$exists": true }, "to": { "db": "database0", "coll": "foo" } } } } ] }, { "description": "when showExpandedEvents is true, createIndex events are reported", "operations": [ { "name": "createChangeStream", "object": "collection0", "arguments": { "pipeline": [ { "$match": { "operationType": { "$ne": "create" } } } ], "showExpandedEvents": true }, "saveResultAsEntity": "changeStream0" }, { "name": "createIndex", "object": "collection0", "arguments": { "keys": { "x": 1 }, "name": "x_1" } }, { "name": "iterateUntilDocumentOrError", "object": "changeStream0", "expectResult": { "operationType": "createIndexes" } } ] }, { "description": "when showExpandedEvents is true, dropIndexes events are reported", "operations": [ { "name": "createIndex", "object": "collection0", "arguments": { "keys": { "x": 1 }, "name": "x_1" } }, { "name": "createChangeStream", "object": "collection0", "arguments": { "pipeline": [], "showExpandedEvents": true }, "saveResultAsEntity": "changeStream0" }, { "name": "dropIndex", "object": "collection0", "arguments": { "name": "x_1" } }, { "name": "iterateUntilDocumentOrError", "object": "changeStream0", "expectResult": { "operationType": "dropIndexes" } } ] }, { "description": "when showExpandedEvents is true, create events are reported", "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" } }, { "name": "iterateUntilDocumentOrError", "object": "changeStream0", "expectResult": { "operationType": "create" } } ] }, { "description": "when showExpandedEvents is true, create events on views are reported", "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", "viewOn": "testName" } }, { "name": "iterateUntilDocumentOrError", "object": "changeStream0", "expectResult": { "operationType": "create" } } ] }, { "description": "when showExpandedEvents is true, modify events are reported", "operations": [ { "name": "createIndex", "object": "collection0", "arguments": { "keys": { "x": 1 }, "name": "x_2" } }, { "name": "createChangeStream", "object": "collection0", "arguments": { "pipeline": [], "showExpandedEvents": true }, "saveResultAsEntity": "changeStream0" }, { "name": "runCommand", "object": "database0", "arguments": { "command": { "collMod": "collection0" }, "commandName": "collMod" } }, { "name": "iterateUntilDocumentOrError", "object": "changeStream0", "expectResult": { "operationType": "modify" } } ] }, { "description": "when showExpandedEvents is true, shardCollection events are reported", "runOnRequirements": [ { "topologies": [ "sharded-replicaset", "sharded" ] } ], "operations": [ { "name": "dropCollection", "object": "shardedDb", "arguments": { "collection": "shardedCollection" } }, { "name": "createCollection", "object": "shardedDb", "arguments": { "collection": "shardedCollection" } }, { "name": "createChangeStream", "object": "shardedCollection", "arguments": { "pipeline": [], "showExpandedEvents": true }, "saveResultAsEntity": "changeStream0" }, { "name": "runCommand", "object": "adminDb", "arguments": { "command": { "shardCollection": "shardedDb.shardedCollection", "key": { "_id": 1 } }, "commandName": "shardCollection" } }, { "name": "iterateUntilDocumentOrError", "object": "changeStream0", "expectResult": { "operationType": "shardCollection" } } ] } ] } mongodb-mongo-python-driver-509e9b7/test/change_streams/unified/change-streams.json000066400000000000000000001241061462766011000306220ustar00rootroot00000000000000{ "description": "change-streams", "schemaVersion": "1.7", "runOnRequirements": [ { "minServerVersion": "3.6", "topologies": [ "replicaset" ], "serverless": "forbid" } ], "createEntities": [ { "client": { "id": "client0", "observeEvents": [ "commandStartedEvent" ], "ignoreCommandMonitoringEvents": [ "killCursors" ], "useMultipleMongoses": false } }, { "client": { "id": "globalClient", "useMultipleMongoses": false } }, { "database": { "id": "database0", "client": "client0", "databaseName": "database0" } }, { "collection": { "id": "collection0", "database": "database0", "collectionName": "collection0" } }, { "database": { "id": "database1", "client": "client0", "databaseName": "database1" } }, { "collection": { "id": "collection1", "database": "database1", "collectionName": "collection1" } }, { "database": { "id": "globalDatabase0", "client": "globalClient", "databaseName": "database0" } }, { "collection": { "id": "globalCollection0", "database": "globalDatabase0", "collectionName": "collection0" } }, { "database": { "id": "globalDatabase1", "client": "globalClient", "databaseName": "database1" } }, { "collection": { "id": "globalCollection1", "database": "globalDatabase1", "collectionName": "collection1" } }, { "collection": { "id": "globalDb1Collection0", "database": "globalDatabase1", "collectionName": "collection0" } }, { "collection": { "id": "globalDb0Collection1", "database": "globalDatabase0", "collectionName": "collection1" } } ], "initialData": [ { "collectionName": "collection0", "databaseName": "database0", "documents": [] } ], "tests": [ { "description": "Test array truncation", "runOnRequirements": [ { "minServerVersion": "4.7" } ], "operations": [ { "name": "insertOne", "object": "collection0", "arguments": { "document": { "_id": 1, "a": 1, "array": [ "foo", { "a": "bar" }, 1, 2, 3 ] } } }, { "name": "createChangeStream", "object": "collection0", "arguments": { "pipeline": [] }, "saveResultAsEntity": "changeStream0" }, { "name": "updateOne", "object": "collection0", "arguments": { "filter": { "_id": 1 }, "update": [ { "$set": { "array": [ "foo", { "a": "bar" } ] } } ] } }, { "name": "iterateUntilDocumentOrError", "object": "changeStream0", "expectResult": { "operationType": "update", "ns": { "db": "database0", "coll": "collection0" }, "updateDescription": { "updatedFields": {}, "removedFields": [], "truncatedArrays": [ { "field": "array", "newSize": 2 } ] } } } ] }, { "description": "Test with document comment", "runOnRequirements": [ { "minServerVersion": "4.4" } ], "operations": [ { "name": "createChangeStream", "object": "collection0", "arguments": { "pipeline": [], "comment": { "name": "test1" } }, "saveResultAsEntity": "changeStream0" } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "aggregate": "collection0", "pipeline": [ { "$changeStream": {} } ], "comment": { "name": "test1" } } } } ] } ] }, { "description": "Test with document comment - pre 4.4", "runOnRequirements": [ { "maxServerVersion": "4.2.99" } ], "operations": [ { "name": "createChangeStream", "object": "collection0", "arguments": { "pipeline": [], "comment": { "name": "test1" } }, "expectError": { "isClientError": false } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "aggregate": "collection0", "pipeline": [ { "$changeStream": {} } ], "comment": { "name": "test1" } } } } ] } ] }, { "description": "Test with string comment", "operations": [ { "name": "createChangeStream", "object": "collection0", "arguments": { "pipeline": [], "comment": "comment" }, "saveResultAsEntity": "changeStream0" } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "aggregate": "collection0", "pipeline": [ { "$changeStream": {} } ], "comment": "comment" } } } ] } ] }, { "description": "Test that comment is set on getMore", "runOnRequirements": [ { "minServerVersion": "4.4.0" } ], "operations": [ { "name": "createChangeStream", "object": "collection0", "arguments": { "pipeline": [], "comment": { "key": "value" } }, "saveResultAsEntity": "changeStream0" }, { "name": "insertOne", "object": "collection0", "arguments": { "document": { "_id": 1, "a": 1 } } }, { "name": "iterateUntilDocumentOrError", "object": "changeStream0" } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "aggregate": "collection0", "pipeline": [ { "$changeStream": {} } ], "comment": { "key": "value" } } } }, { "commandStartedEvent": { "command": { "insert": "collection0", "documents": [ { "_id": 1, "a": 1 } ] } } }, { "commandStartedEvent": { "command": { "getMore": { "$$type": [ "int", "long" ] }, "collection": "collection0", "comment": { "key": "value" } }, "commandName": "getMore", "databaseName": "database0" } } ] } ] }, { "description": "Test that comment is not set on getMore - pre 4.4", "runOnRequirements": [ { "maxServerVersion": "4.3.99" } ], "operations": [ { "name": "createChangeStream", "object": "collection0", "arguments": { "pipeline": [], "comment": "comment" }, "saveResultAsEntity": "changeStream0" }, { "name": "insertOne", "object": "collection0", "arguments": { "document": { "_id": 1, "a": 1 } } }, { "name": "iterateUntilDocumentOrError", "object": "changeStream0" } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "aggregate": "collection0", "pipeline": [ { "$changeStream": {} } ], "comment": "comment" } } }, { "commandStartedEvent": { "command": { "insert": "collection0", "documents": [ { "_id": 1, "a": 1 } ] } } }, { "commandStartedEvent": { "command": { "getMore": { "$$type": [ "int", "long" ] }, "collection": "collection0", "comment": { "$$exists": false } }, "commandName": "getMore", "databaseName": "database0" } } ] } ] }, { "description": "to field is set in a rename change event", "runOnRequirements": [ { "minServerVersion": "4.0.1" } ], "operations": [ { "name": "createChangeStream", "object": "collection0", "arguments": { "pipeline": [] }, "saveResultAsEntity": "changeStream0" }, { "name": "dropCollection", "object": "database0", "arguments": { "collection": "collection1" } }, { "name": "rename", "object": "collection0", "arguments": { "to": "collection1" } }, { "name": "iterateUntilDocumentOrError", "object": "changeStream0", "expectResult": { "operationType": "rename", "ns": { "db": "database0", "coll": "collection0" }, "to": { "db": "database0", "coll": "collection1" } } } ] }, { "description": "Test unknown operationType MUST NOT err", "operations": [ { "name": "createChangeStream", "object": "collection0", "arguments": { "pipeline": [ { "$project": { "operationType": "addedInFutureMongoDBVersion", "ns": 1 } } ] }, "saveResultAsEntity": "changeStream0" }, { "name": "insertOne", "object": "collection0", "arguments": { "document": { "_id": 1, "a": 1 } } }, { "name": "iterateUntilDocumentOrError", "object": "changeStream0", "expectResult": { "operationType": "addedInFutureMongoDBVersion", "ns": { "db": "database0", "coll": "collection0" } } } ] }, { "description": "Test newField added in response MUST NOT err", "operations": [ { "name": "createChangeStream", "object": "collection0", "arguments": { "pipeline": [ { "$project": { "operationType": 1, "ns": 1, "newField": "newFieldValue" } } ] }, "saveResultAsEntity": "changeStream0" }, { "name": "insertOne", "object": "collection0", "arguments": { "document": { "_id": 1, "a": 1 } } }, { "name": "iterateUntilDocumentOrError", "object": "changeStream0", "expectResult": { "operationType": "insert", "ns": { "db": "database0", "coll": "collection0" }, "newField": "newFieldValue" } } ] }, { "description": "Test new structure in ns document MUST NOT err", "runOnRequirements": [ { "minServerVersion": "3.6", "maxServerVersion": "5.2.99" }, { "minServerVersion": "6.0" } ], "operations": [ { "name": "createChangeStream", "object": "collection0", "arguments": { "pipeline": [ { "$project": { "operationType": "insert", "ns.viewOn": "db.coll" } } ] }, "saveResultAsEntity": "changeStream0" }, { "name": "insertOne", "object": "collection0", "arguments": { "document": { "_id": 1, "a": 1 } } }, { "name": "iterateUntilDocumentOrError", "object": "changeStream0", "expectResult": { "operationType": "insert", "ns": { "viewOn": "db.coll" } } } ] }, { "description": "Test modified structure in ns document MUST NOT err", "operations": [ { "name": "createChangeStream", "object": "collection0", "arguments": { "pipeline": [ { "$project": { "operationType": "insert", "ns": { "db": "$ns.db", "coll": "$ns.coll", "viewOn": "db.coll" } } } ] }, "saveResultAsEntity": "changeStream0" }, { "name": "insertOne", "object": "collection0", "arguments": { "document": { "_id": 1, "a": 1 } } }, { "name": "iterateUntilDocumentOrError", "object": "changeStream0", "expectResult": { "operationType": "insert", "ns": { "db": "database0", "coll": "collection0", "viewOn": "db.coll" } } } ] }, { "description": "Test server error on projecting out _id", "runOnRequirements": [ { "minServerVersion": "4.2" } ], "operations": [ { "name": "createChangeStream", "object": "collection0", "arguments": { "pipeline": [ { "$project": { "_id": 0 } } ] }, "saveResultAsEntity": "changeStream0" }, { "name": "insertOne", "object": "collection0", "arguments": { "document": { "_id": 1, "a": 1 } } }, { "name": "iterateUntilDocumentOrError", "object": "changeStream0", "expectError": { "errorCode": 280, "errorCodeName": "ChangeStreamFatalError", "errorLabelsContain": [ "NonResumableChangeStreamError" ] } } ] }, { "description": "Test projection in change stream returns expected fields", "operations": [ { "name": "createChangeStream", "object": "collection0", "arguments": { "pipeline": [ { "$project": { "optype": "$operationType", "ns": 1, "newField": "value" } } ] }, "saveResultAsEntity": "changeStream0" }, { "name": "insertOne", "object": "collection0", "arguments": { "document": { "_id": 1, "a": 1 } } }, { "name": "iterateUntilDocumentOrError", "object": "changeStream0", "expectResult": { "optype": "insert", "ns": { "db": "database0", "coll": "collection0" }, "newField": "value" } } ] }, { "description": "$changeStream must be the first stage in a change stream pipeline sent to the server", "runOnRequirements": [ { "minServerVersion": "3.6.0" } ], "operations": [ { "name": "createChangeStream", "object": "collection0", "arguments": { "pipeline": [] }, "saveResultAsEntity": "changeStream0" }, { "name": "insertOne", "object": "globalCollection0", "arguments": { "document": { "x": 1 } } }, { "name": "iterateUntilDocumentOrError", "object": "changeStream0", "expectResult": { "_id": { "$$exists": true }, "documentKey": { "$$exists": true }, "operationType": "insert", "ns": { "db": "database0", "coll": "collection0" }, "fullDocument": { "x": 1, "_id": { "$$exists": true } } } } ], "expectEvents": [ { "client": "client0", "ignoreExtraEvents": true, "events": [ { "commandStartedEvent": { "command": { "aggregate": "collection0", "cursor": {}, "pipeline": [ { "$changeStream": {} } ] }, "commandName": "aggregate", "databaseName": "database0" } } ] } ] }, { "description": "The server returns change stream responses in the specified server response format", "runOnRequirements": [ { "minServerVersion": "3.6.0" } ], "operations": [ { "name": "createChangeStream", "object": "collection0", "arguments": { "pipeline": [] }, "saveResultAsEntity": "changeStream0" }, { "name": "insertOne", "object": "globalCollection0", "arguments": { "document": { "x": 1 } } }, { "name": "iterateUntilDocumentOrError", "object": "changeStream0", "expectResult": { "_id": { "$$exists": true }, "documentKey": { "$$exists": true }, "operationType": "insert", "ns": { "db": "database0", "coll": "collection0" }, "fullDocument": { "x": 1, "_id": { "$$exists": true } } } } ] }, { "description": "Executing a watch helper on a Collection results in notifications for changes to the specified collection", "runOnRequirements": [ { "minServerVersion": "3.6.0" } ], "operations": [ { "name": "createChangeStream", "object": "collection0", "arguments": { "pipeline": [] }, "saveResultAsEntity": "changeStream0" }, { "name": "insertOne", "object": "globalDb0Collection1", "arguments": { "document": { "x": 1 } } }, { "name": "insertOne", "object": "globalDb1Collection0", "arguments": { "document": { "y": 2 } } }, { "name": "insertOne", "object": "globalCollection0", "arguments": { "document": { "z": 3 } } }, { "name": "iterateUntilDocumentOrError", "object": "changeStream0", "expectResult": { "operationType": "insert", "ns": { "db": "database0", "coll": "collection0" }, "fullDocument": { "z": 3, "_id": { "$$exists": true } } } } ], "expectEvents": [ { "client": "client0", "ignoreExtraEvents": true, "events": [ { "commandStartedEvent": { "command": { "aggregate": "collection0", "cursor": {}, "pipeline": [ { "$changeStream": {} } ] }, "commandName": "aggregate", "databaseName": "database0" } } ] } ] }, { "description": "Change Stream should allow valid aggregate pipeline stages", "runOnRequirements": [ { "minServerVersion": "3.6.0" } ], "operations": [ { "name": "createChangeStream", "object": "collection0", "arguments": { "pipeline": [ { "$match": { "fullDocument.z": 3 } } ] }, "saveResultAsEntity": "changeStream0" }, { "name": "insertOne", "object": "globalCollection0", "arguments": { "document": { "y": 2 } } }, { "name": "insertOne", "object": "globalCollection0", "arguments": { "document": { "z": 3 } } }, { "name": "iterateUntilDocumentOrError", "object": "changeStream0", "expectResult": { "operationType": "insert", "ns": { "db": "database0", "coll": "collection0" }, "fullDocument": { "z": 3, "_id": { "$$exists": true } } } } ], "expectEvents": [ { "client": "client0", "ignoreExtraEvents": true, "events": [ { "commandStartedEvent": { "command": { "aggregate": "collection0", "cursor": {}, "pipeline": [ { "$changeStream": {} }, { "$match": { "fullDocument.z": 3 } } ] }, "commandName": "aggregate", "databaseName": "database0" } } ] } ] }, { "description": "Executing a watch helper on a Database results in notifications for changes to all collections in the specified database.", "runOnRequirements": [ { "minServerVersion": "3.8.0" } ], "operations": [ { "name": "createChangeStream", "object": "database0", "arguments": { "pipeline": [] }, "saveResultAsEntity": "changeStream0" }, { "name": "insertOne", "object": "globalDb0Collection1", "arguments": { "document": { "x": 1 } } }, { "name": "insertOne", "object": "globalDb1Collection0", "arguments": { "document": { "y": 2 } } }, { "name": "insertOne", "object": "globalCollection0", "arguments": { "document": { "z": 3 } } }, { "name": "iterateUntilDocumentOrError", "object": "changeStream0", "expectResult": { "operationType": "insert", "ns": { "db": "database0", "coll": "collection1" }, "fullDocument": { "x": 1, "_id": { "$$exists": true } } } }, { "name": "iterateUntilDocumentOrError", "object": "changeStream0", "expectResult": { "operationType": "insert", "ns": { "db": "database0", "coll": "collection0" }, "fullDocument": { "z": 3, "_id": { "$$exists": true } } } } ], "expectEvents": [ { "client": "client0", "ignoreExtraEvents": true, "events": [ { "commandStartedEvent": { "command": { "aggregate": 1, "cursor": {}, "pipeline": [ { "$changeStream": {} } ] }, "commandName": "aggregate", "databaseName": "database0" } } ] } ] }, { "description": "Executing a watch helper on a MongoClient results in notifications for changes to all collections in all databases in the cluster.", "runOnRequirements": [ { "minServerVersion": "3.8.0" } ], "operations": [ { "name": "createChangeStream", "object": "client0", "arguments": { "pipeline": [] }, "saveResultAsEntity": "changeStream0" }, { "name": "insertOne", "object": "globalDb0Collection1", "arguments": { "document": { "x": 1 } } }, { "name": "insertOne", "object": "globalDb1Collection0", "arguments": { "document": { "y": 2 } } }, { "name": "insertOne", "object": "globalCollection0", "arguments": { "document": { "z": 3 } } }, { "name": "iterateUntilDocumentOrError", "object": "changeStream0", "expectResult": { "operationType": "insert", "ns": { "db": "database0", "coll": "collection1" }, "fullDocument": { "x": 1, "_id": { "$$exists": true } } } }, { "name": "iterateUntilDocumentOrError", "object": "changeStream0", "expectResult": { "operationType": "insert", "ns": { "db": "database1", "coll": "collection0" }, "fullDocument": { "y": 2, "_id": { "$$exists": true } } } }, { "name": "iterateUntilDocumentOrError", "object": "changeStream0", "expectResult": { "operationType": "insert", "ns": { "db": "database0", "coll": "collection0" }, "fullDocument": { "z": 3, "_id": { "$$exists": true } } } } ], "expectEvents": [ { "client": "client0", "ignoreExtraEvents": true, "events": [ { "commandStartedEvent": { "command": { "aggregate": 1, "cursor": {}, "pipeline": [ { "$changeStream": { "allChangesForCluster": true } } ] }, "commandName": "aggregate", "databaseName": "admin" } } ] } ] }, { "description": "Test insert, update, replace, and delete event types", "runOnRequirements": [ { "minServerVersion": "3.6.0" } ], "operations": [ { "name": "createChangeStream", "object": "collection0", "arguments": { "pipeline": [] }, "saveResultAsEntity": "changeStream0" }, { "name": "insertOne", "object": "globalCollection0", "arguments": { "document": { "x": 1 } } }, { "name": "updateOne", "object": "globalCollection0", "arguments": { "filter": { "x": 1 }, "update": { "$set": { "x": 2 } } } }, { "name": "replaceOne", "object": "globalCollection0", "arguments": { "filter": { "x": 2 }, "replacement": { "x": 3 } } }, { "name": "deleteOne", "object": "globalCollection0", "arguments": { "filter": { "x": 3 } } }, { "name": "iterateUntilDocumentOrError", "object": "changeStream0", "expectResult": { "operationType": "insert", "ns": { "db": "database0", "coll": "collection0" }, "fullDocument": { "x": 1, "_id": { "$$exists": true } } } }, { "name": "iterateUntilDocumentOrError", "object": "changeStream0", "expectResult": { "operationType": "update", "ns": { "db": "database0", "coll": "collection0" }, "updateDescription": { "updatedFields": { "x": 2 }, "removedFields": [], "truncatedArrays": { "$$unsetOrMatches": { "$$exists": true } } } } }, { "name": "iterateUntilDocumentOrError", "object": "changeStream0", "expectResult": { "operationType": "replace", "ns": { "db": "database0", "coll": "collection0" }, "fullDocument": { "x": 3, "_id": { "$$exists": true } } } }, { "name": "iterateUntilDocumentOrError", "object": "changeStream0", "expectResult": { "operationType": "delete", "ns": { "db": "database0", "coll": "collection0" } } } ], "expectEvents": [ { "client": "client0", "ignoreExtraEvents": true, "events": [ { "commandStartedEvent": { "command": { "aggregate": "collection0", "cursor": {}, "pipeline": [ { "$changeStream": {} } ] }, "commandName": "aggregate", "databaseName": "database0" } } ] } ] }, { "description": "Test rename and invalidate event types", "runOnRequirements": [ { "minServerVersion": "4.0.1" } ], "operations": [ { "name": "createChangeStream", "object": "collection0", "arguments": { "pipeline": [] }, "saveResultAsEntity": "changeStream0" }, { "name": "dropCollection", "object": "database0", "arguments": { "collection": "collection1" } }, { "name": "rename", "object": "globalCollection0", "arguments": { "to": "collection1" } }, { "name": "iterateUntilDocumentOrError", "object": "changeStream0", "expectResult": { "operationType": "rename", "ns": { "db": "database0", "coll": "collection0" }, "to": { "db": "database0", "coll": "collection1" } } }, { "name": "iterateUntilDocumentOrError", "object": "changeStream0", "expectResult": { "operationType": "invalidate" } } ], "expectEvents": [ { "client": "client0", "ignoreExtraEvents": true, "events": [ { "commandStartedEvent": { "command": { "aggregate": "collection0", "cursor": {}, "pipeline": [ { "$changeStream": {} } ] }, "commandName": "aggregate", "databaseName": "database0" } } ] } ] }, { "description": "Test drop and invalidate event types", "runOnRequirements": [ { "minServerVersion": "4.0.1" } ], "operations": [ { "name": "createChangeStream", "object": "collection0", "arguments": { "pipeline": [] }, "saveResultAsEntity": "changeStream0" }, { "name": "dropCollection", "object": "database0", "arguments": { "collection": "collection0" } }, { "name": "iterateUntilDocumentOrError", "object": "changeStream0", "expectResult": { "operationType": "drop", "ns": { "db": "database0", "coll": "collection0" } } }, { "name": "iterateUntilDocumentOrError", "object": "changeStream0", "expectResult": { "operationType": "invalidate" } } ], "expectEvents": [ { "client": "client0", "ignoreExtraEvents": true, "events": [ { "commandStartedEvent": { "command": { "aggregate": "collection0", "cursor": {}, "pipeline": [ { "$changeStream": {} } ] }, "commandName": "aggregate", "databaseName": "database0" } } ] } ] }, { "description": "Test consecutive resume", "runOnRequirements": [ { "minServerVersion": "4.1.7" } ], "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "globalClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 2 }, "data": { "failCommands": [ "getMore" ], "closeConnection": true } } } }, { "name": "createChangeStream", "object": "collection0", "arguments": { "pipeline": [], "batchSize": 1 }, "saveResultAsEntity": "changeStream0" }, { "name": "insertOne", "object": "globalCollection0", "arguments": { "document": { "x": 1 } } }, { "name": "insertOne", "object": "globalCollection0", "arguments": { "document": { "x": 2 } } }, { "name": "insertOne", "object": "globalCollection0", "arguments": { "document": { "x": 3 } } }, { "name": "iterateUntilDocumentOrError", "object": "changeStream0", "expectResult": { "operationType": "insert", "ns": { "db": "database0", "coll": "collection0" }, "fullDocument": { "x": 1, "_id": { "$$exists": true } } } }, { "name": "iterateUntilDocumentOrError", "object": "changeStream0", "expectResult": { "operationType": "insert", "ns": { "db": "database0", "coll": "collection0" }, "fullDocument": { "x": 2, "_id": { "$$exists": true } } } }, { "name": "iterateUntilDocumentOrError", "object": "changeStream0", "expectResult": { "operationType": "insert", "ns": { "db": "database0", "coll": "collection0" }, "fullDocument": { "x": 3, "_id": { "$$exists": true } } } } ], "expectEvents": [ { "client": "client0", "ignoreExtraEvents": true, "events": [ { "commandStartedEvent": { "command": { "aggregate": "collection0", "cursor": { "batchSize": 1 }, "pipeline": [ { "$changeStream": {} } ] }, "commandName": "aggregate", "databaseName": "database0" } } ] } ] }, { "description": "Test wallTime field is set in a change event", "runOnRequirements": [ { "minServerVersion": "6.0.0" } ], "operations": [ { "name": "createChangeStream", "object": "collection0", "arguments": { "pipeline": [] }, "saveResultAsEntity": "changeStream0" }, { "name": "insertOne", "object": "collection0", "arguments": { "document": { "_id": 1, "a": 1 } } }, { "name": "iterateUntilDocumentOrError", "object": "changeStream0", "expectResult": { "operationType": "insert", "ns": { "db": "database0", "coll": "collection0" }, "wallTime": { "$$exists": true } } } ] } ] } mongodb-mongo-python-driver-509e9b7/test/client-side-encryption/000077500000000000000000000000001462766011000250045ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/client-side-encryption/corpus/000077500000000000000000000000001462766011000263175ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/client-side-encryption/corpus/corpus-encrypted.json000066400000000000000000007574761462766011000325520ustar00rootroot00000000000000{ "_id": "client_side_encryption_corpus", "altname_aws": "aws", "altname_local": "local", "aws_double_rand_auto_id": { "kms": "aws", "type": "double", "algo": "rand", "method": "auto", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "AgFkgAAAAAAAAAAAAAAAAAABchrWPF5OPeuFpk4tUV325TmoNpGW+L5iPSXcLQIr319WJFIp3EDy5QiAHBfz2rThI7imU4eLXndIUrsjM0S/vg==", "subType": "06" } } }, "aws_double_rand_auto_altname": { "kms": "aws", "type": "double", "algo": "rand", "method": "auto", "identifier": "altname", "allowed": true, "value": { "$binary": { "base64": "AgFkgAAAAAAAAAAAAAAAAAABga5hXFiFvH/wOr0wOHSHFWRZ4pEs/UCC1XJWf46Dod3GY9Ry5j1ZyzeHueJxc4Ym5M8UHKSmJuXmNo9m9ZnkiA==", "subType": "06" } } }, "aws_double_rand_explicit_id": { "kms": "aws", "type": "double", "algo": "rand", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "AgFkgAAAAAAAAAAAAAAAAAABjTYZbsro/YxLWBb88qPXEIDQdzY7UZyK4UaZZ8h62OTxp43Zp9j6WvOEzKhXt4oJPMxlAxyTdqO6MllX5bsDrw==", "subType": "06" } } }, "aws_double_rand_explicit_altname": { "kms": "aws", "type": "double", "algo": "rand", "method": "explicit", "identifier": "altname", "allowed": true, "value": { "$binary": { "base64": "AgFkgAAAAAAAAAAAAAAAAAABqkyXdeS3aWH2tRFoKxsIIL3ZH05gkiAEbutrjrdfw0b110iPhuCCOb0gP/nX/NRNCg1kCFZ543Vu0xZ0BRXlvQ==", "subType": "06" } } }, "aws_double_det_explicit_id": { "kms": "aws", "type": "double", "algo": "det", "method": "explicit", "identifier": "id", "allowed": false, "value": { "$numberDouble": "1.234" } }, "aws_double_det_explicit_altname": { "kms": "aws", "type": "double", "algo": "det", "method": "explicit", "identifier": "altname", "allowed": false, "value": { "$numberDouble": "1.234" } }, "aws_string_rand_auto_id": { "kms": "aws", "type": "string", "algo": "rand", "method": "auto", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "AgFkgAAAAAAAAAAAAAAAAAACAsI5E0rVT8TpIONY3TnbRvIxUjKsiy9ynVd/fE7U1lndE7KR6dTzs8QWK13kdKxO+njKPeC2ObBX904QmJ65Sw==", "subType": "06" } } }, "aws_string_rand_auto_altname": { "kms": "aws", "type": "string", "algo": "rand", "method": "auto", "identifier": "altname", "allowed": true, "value": { "$binary": { "base64": "AgFkgAAAAAAAAAAAAAAAAAACgBE6J6MRxPSDe+gfJPL8nBvuEIRBYxNS/73LqBTDJYyN/lsHQ6UlFDT5B4EkIPmHPTe+UBMOhZQ1bsP+DK8Aog==", "subType": "06" } } }, "aws_string_rand_explicit_id": { "kms": "aws", "type": "string", "algo": "rand", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "AgFkgAAAAAAAAAAAAAAAAAACbdTVDBWn35M5caKZgLFoiSVeFGKRj5K/QtupKNc8/dPIyCE+/a4PU51G/YIzFpYmp91nLpyq7lD/eJ/V0q66Zw==", "subType": "06" } } }, "aws_string_rand_explicit_altname": { "kms": "aws", "type": "string", "algo": "rand", "method": "explicit", "identifier": "altname", "allowed": true, "value": { "$binary": { "base64": "AgFkgAAAAAAAAAAAAAAAAAACa4O+kE2BaqM0E+yiBrbCuE0YEGTrZ7L/+SuWm9gN3UupxwAQpRfxXAuUCTc9u1CXnvL+ga+VJMcWD2bawnn/Rg==", "subType": "06" } } }, "aws_string_det_auto_id": { "kms": "aws", "type": "string", "algo": "det", "method": "auto", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "AQFkgAAAAAAAAAAAAAAAAAACyvOW8NcqRkZYzujivwVmYptJkic27PWr3Nq3Yv5Njz8cJdoyesVaQan6mn+U3wdfGEH8zbUUISdCx5qgvXEpvw==", "subType": "06" } } }, "aws_string_det_explicit_id": { "kms": "aws", "type": "string", "algo": "det", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "AQFkgAAAAAAAAAAAAAAAAAACyvOW8NcqRkZYzujivwVmYptJkic27PWr3Nq3Yv5Njz8cJdoyesVaQan6mn+U3wdfGEH8zbUUISdCx5qgvXEpvw==", "subType": "06" } } }, "aws_string_det_explicit_altname": { "kms": "aws", "type": "string", "algo": "det", "method": "explicit", "identifier": "altname", "allowed": true, "value": { "$binary": { "base64": "AQFkgAAAAAAAAAAAAAAAAAACyvOW8NcqRkZYzujivwVmYptJkic27PWr3Nq3Yv5Njz8cJdoyesVaQan6mn+U3wdfGEH8zbUUISdCx5qgvXEpvw==", "subType": "06" } } }, "aws_object_rand_auto_id": { "kms": "aws", "type": "object", "algo": "rand", "method": "auto", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "AgFkgAAAAAAAAAAAAAAAAAADI+/afY6Eka8j1VNThWIeGkDZ7vo4/l66a01Z+lVUFFnVLeUV/nz9kM6uTTplNRUa+RXmNmwkoR/BHRnGc7wRNA==", "subType": "06" } } }, "aws_object_rand_auto_altname": { "kms": "aws", "type": "object", "algo": "rand", "method": "auto", "identifier": "altname", "allowed": true, "value": { "$binary": { "base64": "AgFkgAAAAAAAAAAAAAAAAAADzN4hVXWXKerhggRRtwWnDu2W2wQ5KIWb/X1WCZJKTjQSQ5LNHVasabBCa4U1q46PQ5pDDM1PkVjW6o+zzl/4xw==", "subType": "06" } } }, "aws_object_rand_explicit_id": { "kms": "aws", "type": "object", "algo": "rand", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "AgFkgAAAAAAAAAAAAAAAAAADhSs5zKFMuuux3fqFFuPito3N+bp5TgmkUtJtFXjmA/EnLuexGARvEeGUsMJ/n0VzKbbsiE8+AsUNY3o9YXutqQ==", "subType": "06" } } }, "aws_object_rand_explicit_altname": { "kms": "aws", "type": "object", "algo": "rand", "method": "explicit", "identifier": "altname", "allowed": true, "value": { "$binary": { "base64": "AgFkgAAAAAAAAAAAAAAAAAADpj8MSov16h26bFDrHepsNkW+tOLOjRP7oj1Tnj75qZ+uqxxVkQ5B/t/Ihk5fikHTJGAcRBR5Vv6kJ/ulMaDnvQ==", "subType": "06" } } }, "aws_object_det_explicit_id": { "kms": "aws", "type": "object", "algo": "det", "method": "explicit", "identifier": "id", "allowed": false, "value": { "x": { "$numberInt": "1" } } }, "aws_object_det_explicit_altname": { "kms": "aws", "type": "object", "algo": "det", "method": "explicit", "identifier": "altname", "allowed": false, "value": { "x": { "$numberInt": "1" } } }, "aws_array_rand_auto_id": { "kms": "aws", "type": "array", "algo": "rand", "method": "auto", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "AgFkgAAAAAAAAAAAAAAAAAAETWDOZ6zV39H2+W+BkwZIoxI3BNF6phKoiBZ9+i4T9uEoyU3TmoTPjuI0YNwR1v/p5/9rlVCG0KLZd16eeMb3zxZXjqh6IAJqfhsBQ7bzBYI=", "subType": "06" } } }, "aws_array_rand_auto_altname": { "kms": "aws", "type": "array", "algo": "rand", "method": "auto", "identifier": "altname", "allowed": true, "value": { "$binary": { "base64": "AgFkgAAAAAAAAAAAAAAAAAAE1xeHbld2JjUiPB1k+xMZuIzNSai7mv1iusCswxKEfYCZ7YtR0GDQTxN4676CwhcodSDiysjgOxSFIGlptKCvl0k46LNq0EGypP9yWBLvdjQ=", "subType": "06" } } }, "aws_array_rand_explicit_id": { "kms": "aws", "type": "array", "algo": "rand", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "AgFkgAAAAAAAAAAAAAAAAAAEFVa4U2uW65MGihhdOmpZFgnwGTs3VeN5TXXbXJ5cfm0CwXF3EPlzAVjy5WO/+lbvFufpQnIiLH59/kVygmwn+2P9zPNJnSGIJW9gaV8Vye8=", "subType": "06" } } }, "aws_array_rand_explicit_altname": { "kms": "aws", "type": "array", "algo": "rand", "method": "explicit", "identifier": "altname", "allowed": true, "value": { "$binary": { "base64": "AgFkgAAAAAAAAAAAAAAAAAAE11VXbfg7DJQ5/CB9XdBO0hCrxOkK3RrEjPGJ0FXlUo76IMna1uo+NVmDnM63CRlGE3/TEbZPpp0w0jn4vZLKvBmGr7o7WQusRY4jnRf5oH4=", "subType": "06" } } }, "aws_array_det_explicit_id": { "kms": "aws", "type": "array", "algo": "det", "method": "explicit", "identifier": "id", "allowed": false, "value": [ { "$numberInt": "1" }, { "$numberInt": "2" }, { "$numberInt": "3" } ] }, "aws_array_det_explicit_altname": { "kms": "aws", "type": "array", "algo": "det", "method": "explicit", "identifier": "altname", "allowed": false, "value": [ { "$numberInt": "1" }, { "$numberInt": "2" }, { "$numberInt": "3" } ] }, "aws_binData=00_rand_auto_id": { "kms": "aws", "type": "binData=00", "algo": "rand", "method": "auto", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "AgFkgAAAAAAAAAAAAAAAAAAFpZYSktIHzGLZ6mcBFxywICqxdurqLVJcQR34ngix5YIOOulCYEhBSDzzSEyixEPCuU6cEzeuafpZRHX4qgcr9Q==", "subType": "06" } } }, "aws_binData=00_rand_auto_altname": { "kms": "aws", "type": "binData=00", "algo": "rand", "method": "auto", "identifier": "altname", "allowed": true, "value": { "$binary": { "base64": "AgFkgAAAAAAAAAAAAAAAAAAFshzESR9SyR++9r2yeaEjJYScMDez414s8pZkB3C8ihDa+rsyaxNy4yrF7qNEWjFrdFaH7zD2LdlPx+TKZgROlg==", "subType": "06" } } }, "aws_binData=00_rand_explicit_id": { "kms": "aws", "type": "binData=00", "algo": "rand", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "AgFkgAAAAAAAAAAAAAAAAAAFpYwZRPDom7qyAe5WW/QNSq97/OYgRT8xUEaaR5pkbQEFd/Cwtl8Aib/3Bs1CT3MVaHVWna2u5Gcc4s/v18zLhg==", "subType": "06" } } }, "aws_binData=00_rand_explicit_altname": { "kms": "aws", "type": "binData=00", "algo": "rand", "method": "explicit", "identifier": "altname", "allowed": true, "value": { "$binary": { "base64": "AgFkgAAAAAAAAAAAAAAAAAAFBq1RIU1YGHKAS1SAtS42fKtQBHQ/BCQzRutirNdvWlrXxF81LSaS7QgQyycZ2ePiOLsSm2vZS4xaQETeCgRC4g==", "subType": "06" } } }, "aws_binData=00_det_auto_id": { "kms": "aws", "type": "binData=00", "algo": "det", "method": "auto", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "AQFkgAAAAAAAAAAAAAAAAAAF6SJGmfD3hLVc4tLPm4v2zFuHoRxUDLumBR8Q0AlKK2nQPyvuHEPVBD3vQdDi+Q7PwFxmovJsHccr59VnzvpJeg==", "subType": "06" } } }, "aws_binData=00_det_explicit_id": { "kms": "aws", "type": "binData=00", "algo": "det", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "AQFkgAAAAAAAAAAAAAAAAAAF6SJGmfD3hLVc4tLPm4v2zFuHoRxUDLumBR8Q0AlKK2nQPyvuHEPVBD3vQdDi+Q7PwFxmovJsHccr59VnzvpJeg==", "subType": "06" } } }, "aws_binData=00_det_explicit_altname": { "kms": "aws", "type": "binData=00", "algo": "det", "method": "explicit", "identifier": "altname", "allowed": true, "value": { "$binary": { "base64": "AQFkgAAAAAAAAAAAAAAAAAAF6SJGmfD3hLVc4tLPm4v2zFuHoRxUDLumBR8Q0AlKK2nQPyvuHEPVBD3vQdDi+Q7PwFxmovJsHccr59VnzvpJeg==", "subType": "06" } } }, "aws_binData=04_rand_auto_id": { "kms": "aws", "type": "binData=04", "algo": "rand", "method": "auto", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "AgFkgAAAAAAAAAAAAAAAAAAFM5685zqlM8pc3xubtCFuf724g/bWXsebpNzw5E5HrxUqSBBVOvjs3IJH74+Supe169qejY358nOG41mLZvO2wJByvT14qmgUGpgBaLaxPR0=", "subType": "06" } } }, "aws_binData=04_rand_auto_altname": { "kms": "aws", "type": "binData=04", "algo": "rand", "method": "auto", "identifier": "altname", "allowed": true, "value": { "$binary": { "base64": "AgFkgAAAAAAAAAAAAAAAAAAFfLqOzpfjz/XYHDLnliUAA5ehi6s+OIjvrLa59ubqEf8DuoCEWlO13Dl8X42IBB4hoSsO2RUeWtc9MeH4SdIUh/xJN3qS7qzjh/H+GvZRdAM=", "subType": "06" } } }, "aws_binData=04_rand_explicit_id": { "kms": "aws", "type": "binData=04", "algo": "rand", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "AgFkgAAAAAAAAAAAAAAAAAAFkmKfKAbz9tqVaiM9MRhYttiY3vgDwXpdYLQ4uUgWX89KRayLADWortYL+Oq+roFhO3oiwB9vjeWGIdgbj5wSh/50JT/2Gs85TXFe1GFjfWs=", "subType": "06" } } }, "aws_binData=04_rand_explicit_altname": { "kms": "aws", "type": "binData=04", "algo": "rand", "method": "explicit", "identifier": "altname", "allowed": true, "value": { "$binary": { "base64": "AgFkgAAAAAAAAAAAAAAAAAAFKbufv83ddN+07Q5Ocq0VxUEV+BesSrVM7Bol3cMlWjHi7P+MrdwhNEa94xlxlDwU3b+RD6kW+AuNEQ2byA3CX2JjZE1gHwN7l0ukXuqpD0A=", "subType": "06" } } }, "aws_binData=04_det_auto_id": { "kms": "aws", "type": "binData=04", "algo": "det", "method": "auto", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "AQFkgAAAAAAAAAAAAAAAAAAFlg7ceq9w/JMhHcNzQks6UrKYAffpUyeWuBIpcuLoB7YbFO61Dphseh77pzZbk3OvmveUq6EtCP2pmsq7hA+QV4hkv6BTn4m6wnXw6ss/qfE=", "subType": "06" } } }, "aws_binData=04_det_explicit_id": { "kms": "aws", "type": "binData=04", "algo": "det", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "AQFkgAAAAAAAAAAAAAAAAAAFlg7ceq9w/JMhHcNzQks6UrKYAffpUyeWuBIpcuLoB7YbFO61Dphseh77pzZbk3OvmveUq6EtCP2pmsq7hA+QV4hkv6BTn4m6wnXw6ss/qfE=", "subType": "06" } } }, "aws_binData=04_det_explicit_altname": { "kms": "aws", "type": "binData=04", "algo": "det", "method": "explicit", "identifier": "altname", "allowed": true, "value": { "$binary": { "base64": "AQFkgAAAAAAAAAAAAAAAAAAFlg7ceq9w/JMhHcNzQks6UrKYAffpUyeWuBIpcuLoB7YbFO61Dphseh77pzZbk3OvmveUq6EtCP2pmsq7hA+QV4hkv6BTn4m6wnXw6ss/qfE=", "subType": "06" } } }, "aws_undefined_rand_explicit_id": { "kms": "aws", "type": "undefined", "algo": "rand", "method": "explicit", "identifier": "id", "allowed": false, "value": { "$undefined": true } }, "aws_undefined_rand_explicit_altname": { "kms": "aws", "type": "undefined", "algo": "rand", "method": "explicit", "identifier": "altname", "allowed": false, "value": { "$undefined": true } }, "aws_undefined_det_explicit_id": { "kms": "aws", "type": "undefined", "algo": "det", "method": "explicit", "identifier": "id", "allowed": false, "value": { "$undefined": true } }, "aws_undefined_det_explicit_altname": { "kms": "aws", "type": "undefined", "algo": "det", "method": "explicit", "identifier": "altname", "allowed": false, "value": { "$undefined": true } }, "aws_objectId_rand_auto_id": { "kms": "aws", "type": "objectId", "algo": "rand", "method": "auto", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "AgFkgAAAAAAAAAAAAAAAAAAHASE+V+LlkmwgF9QNjBK8QBvC973NaTMk6wbd57VB2EpQzrgxMtR5gYzVeqq4xaaHqrncyZCOIxDJkFlaim2NqA==", "subType": "06" } } }, "aws_objectId_rand_auto_altname": { "kms": "aws", "type": "objectId", "algo": "rand", "method": "auto", "identifier": "altname", "allowed": true, "value": { "$binary": { "base64": "AgFkgAAAAAAAAAAAAAAAAAAHf/+9Qj/ozcDoUb8RNBnajU1d9hJ/6fE17IEZnw+ma6v5yH8LqZk9w3dtm6Sfw1unMhcMKrmIgs6kxqRWhNREJg==", "subType": "06" } } }, "aws_objectId_rand_explicit_id": { "kms": "aws", "type": "objectId", "algo": "rand", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "AgFkgAAAAAAAAAAAAAAAAAAHzX8ejVLhoarQ5xgWsJitU/9eBm/Hlt2IIbZtS0SBc80qzkkWTaP9Zl9wrILH/Hwwx8RFnts855eKII3NJFa3BA==", "subType": "06" } } }, "aws_objectId_rand_explicit_altname": { "kms": "aws", "type": "objectId", "algo": "rand", "method": "explicit", "identifier": "altname", "allowed": true, "value": { "$binary": { "base64": "AgFkgAAAAAAAAAAAAAAAAAAHG5l6nUCY8f/6xO6TsPDrZHcdPRyMe3muMlY2DxHwv9GJNDR5Ne5VEAzUjnbgoy+B29SX4oY8cXJ6XhVz8mt3Eg==", "subType": "06" } } }, "aws_objectId_det_auto_id": { "kms": "aws", "type": "objectId", "algo": "det", "method": "auto", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "AQFkgAAAAAAAAAAAAAAAAAAHTMY2l+gY8glm4HeSsGfCSfOsTVTzYU8qnQV8iqEFHrO5SBJac59gv3N/jukMwAnt0j6vIIQrROkVetU24YY7sQ==", "subType": "06" } } }, "aws_objectId_det_explicit_id": { "kms": "aws", "type": "objectId", "algo": "det", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "AQFkgAAAAAAAAAAAAAAAAAAHTMY2l+gY8glm4HeSsGfCSfOsTVTzYU8qnQV8iqEFHrO5SBJac59gv3N/jukMwAnt0j6vIIQrROkVetU24YY7sQ==", "subType": "06" } } }, "aws_objectId_det_explicit_altname": { "kms": "aws", "type": "objectId", "algo": "det", "method": "explicit", "identifier": "altname", "allowed": true, "value": { "$binary": { "base64": "AQFkgAAAAAAAAAAAAAAAAAAHTMY2l+gY8glm4HeSsGfCSfOsTVTzYU8qnQV8iqEFHrO5SBJac59gv3N/jukMwAnt0j6vIIQrROkVetU24YY7sQ==", "subType": "06" } } }, "aws_bool_rand_auto_id": { "kms": "aws", "type": "bool", "algo": "rand", "method": "auto", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "AgFkgAAAAAAAAAAAAAAAAAAISm4UFt1HC2j0ObpTBg7SvF2Dq31i9To2ED4F3JcTihhq0fVzaSCsUz9VTJ0ziHmeNPNdfPPZO6qA/CDEZBO4jg==", "subType": "06" } } }, "aws_bool_rand_auto_altname": { "kms": "aws", "type": "bool", "algo": "rand", "method": "auto", "identifier": "altname", "allowed": true, "value": { "$binary": { "base64": "AgFkgAAAAAAAAAAAAAAAAAAIj93KeAa96DmZXdB8boFvW19jhJSMmtSs5ag5FDSkH8MdKG2d2VoBOdUlBrL+LHYELqeDHCszY7qCirvb5mIgZg==", "subType": "06" } } }, "aws_bool_rand_explicit_id": { "kms": "aws", "type": "bool", "algo": "rand", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "AgFkgAAAAAAAAAAAAAAAAAAIMbDFEuHIl5MNEsWnYLIand1vpK6EMv7Mso6qxrN4wHSVVwmxK+GCPgrKoUQsNuTssFWNCu0IhwrXOagDEfmlxw==", "subType": "06" } } }, "aws_bool_rand_explicit_altname": { "kms": "aws", "type": "bool", "algo": "rand", "method": "explicit", "identifier": "altname", "allowed": true, "value": { "$binary": { "base64": "AgFkgAAAAAAAAAAAAAAAAAAIkIaWfmPdxgAV5Rtb6on6T0NGt9GPFDScQD5I/Ch0ngiTCCKceJOjU0ljd3YTgfWRA1p/MlMIV0I5YAWZXKTHlg==", "subType": "06" } } }, "aws_bool_det_explicit_id": { "kms": "aws", "type": "bool", "algo": "det", "method": "explicit", "identifier": "id", "allowed": false, "value": true }, "aws_bool_det_explicit_altname": { "kms": "aws", "type": "bool", "algo": "det", "method": "explicit", "identifier": "altname", "allowed": false, "value": true }, "aws_date_rand_auto_id": { "kms": "aws", "type": "date", "algo": "rand", "method": "auto", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "AgFkgAAAAAAAAAAAAAAAAAAJz1VG4+QnQXEE+TGu/pzfPugGMVTiC1xnenG1ByRdPvsERVw9WComWl1tb9tt9oblD7H/q0y1+y8HevkDqohB2Q==", "subType": "06" } } }, "aws_date_rand_auto_altname": { "kms": "aws", "type": "date", "algo": "rand", "method": "auto", "identifier": "altname", "allowed": true, "value": { "$binary": { "base64": "AgFkgAAAAAAAAAAAAAAAAAAJa1kI2mIIYWjf7zjf5dD9+psvAQpjZ3nnsoXA5upcIwEtZaC8bxKKHVpOLOP3rTbvT5EV6vLhXkferGoyaqd/8w==", "subType": "06" } } }, "aws_date_rand_explicit_id": { "kms": "aws", "type": "date", "algo": "rand", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "AgFkgAAAAAAAAAAAAAAAAAAJ9Q5Xe4UuOLQTUwosk47A6xx40XJcNoICCNtKrHqsUYy0QLCFRc5v4nA0160BVghURizbUtX8iuIp11pnsDyRtA==", "subType": "06" } } }, "aws_date_rand_explicit_altname": { "kms": "aws", "type": "date", "algo": "rand", "method": "explicit", "identifier": "altname", "allowed": true, "value": { "$binary": { "base64": "AgFkgAAAAAAAAAAAAAAAAAAJkHOdUc/4U82wxWJZ0SYABkJjQqNApkH2Iy/5S+PoatPgynoeSFTU9FmAbuWV/gbtIfBiaCOIjlsdonl/gf9+5w==", "subType": "06" } } }, "aws_date_det_auto_id": { "kms": "aws", "type": "date", "algo": "det", "method": "auto", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "AQFkgAAAAAAAAAAAAAAAAAAJEEpQNsiqMWPqD4lhMkiOJHGE8FxOeYrKPiiAp/bZTrLKyCSS0ZL1WT9H3cGzxWPm5veihCjKqWhjatC/pjtzbQ==", "subType": "06" } } }, "aws_date_det_explicit_id": { "kms": "aws", "type": "date", "algo": "det", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "AQFkgAAAAAAAAAAAAAAAAAAJEEpQNsiqMWPqD4lhMkiOJHGE8FxOeYrKPiiAp/bZTrLKyCSS0ZL1WT9H3cGzxWPm5veihCjKqWhjatC/pjtzbQ==", "subType": "06" } } }, "aws_date_det_explicit_altname": { "kms": "aws", "type": "date", "algo": "det", "method": "explicit", "identifier": "altname", "allowed": true, "value": { "$binary": { "base64": "AQFkgAAAAAAAAAAAAAAAAAAJEEpQNsiqMWPqD4lhMkiOJHGE8FxOeYrKPiiAp/bZTrLKyCSS0ZL1WT9H3cGzxWPm5veihCjKqWhjatC/pjtzbQ==", "subType": "06" } } }, "aws_null_rand_explicit_id": { "kms": "aws", "type": "null", "algo": "rand", "method": "explicit", "identifier": "id", "allowed": false, "value": null }, "aws_null_rand_explicit_altname": { "kms": "aws", "type": "null", "algo": "rand", "method": "explicit", "identifier": "altname", "allowed": false, "value": null }, "aws_null_det_explicit_id": { "kms": "aws", "type": "null", "algo": "det", "method": "explicit", "identifier": "id", "allowed": false, "value": null }, "aws_null_det_explicit_altname": { "kms": "aws", "type": "null", "algo": "det", "method": "explicit", "identifier": "altname", "allowed": false, "value": null }, "aws_regex_rand_auto_id": { "kms": "aws", "type": "regex", "algo": "rand", "method": "auto", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "AgFkgAAAAAAAAAAAAAAAAAALnhViSt3HqTDzyLN4mWO9srBU8TjRvPWsAJYfj/5sgI/yFuWdrggMs3Aq6G+K3tRrX3Yb+osy5CLiFCxq9WIvAA==", "subType": "06" } } }, "aws_regex_rand_auto_altname": { "kms": "aws", "type": "regex", "algo": "rand", "method": "auto", "identifier": "altname", "allowed": true, "value": { "$binary": { "base64": "AgFkgAAAAAAAAAAAAAAAAAALbL2RS2tGQLBZ+6LtXLKAWFKcoKui+u4+gMIlFemLgpdO2eLqrMJB53ccqZImX8ons9UgAwDkiD68hWy8e7KHfg==", "subType": "06" } } }, "aws_regex_rand_explicit_id": { "kms": "aws", "type": "regex", "algo": "rand", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "AgFkgAAAAAAAAAAAAAAAAAALa0+ftF6W/0Ul4J9VT/3chXFktE1o+OK4S14h2kyOqDVNA8yMKuyCK5nWl1yZvjJ76TuhEABte23oxcBP5QwalQ==", "subType": "06" } } }, "aws_regex_rand_explicit_altname": { "kms": "aws", "type": "regex", "algo": "rand", "method": "explicit", "identifier": "altname", "allowed": true, "value": { "$binary": { "base64": "AgFkgAAAAAAAAAAAAAAAAAALS4Yo9Fwk6OTx2CWdnObFT2L4rHngeIbdCyT4/YMJYd+jLU3mph14M1ptZZg+TBIgSPHq+BkvpRDifbMmOVr/Hg==", "subType": "06" } } }, "aws_regex_det_auto_id": { "kms": "aws", "type": "regex", "algo": "det", "method": "auto", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "AQFkgAAAAAAAAAAAAAAAAAALpwNlokiTCUtTa2Kx9NVGvXR/aKPGhR5iaCT7nHEk4BOiZ9Kr4cRHdPCeZ7A+gjG4cKoT62sm3Fj1FwSOl8J8aQ==", "subType": "06" } } }, "aws_regex_det_explicit_id": { "kms": "aws", "type": "regex", "algo": "det", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "AQFkgAAAAAAAAAAAAAAAAAALpwNlokiTCUtTa2Kx9NVGvXR/aKPGhR5iaCT7nHEk4BOiZ9Kr4cRHdPCeZ7A+gjG4cKoT62sm3Fj1FwSOl8J8aQ==", "subType": "06" } } }, "aws_regex_det_explicit_altname": { "kms": "aws", "type": "regex", "algo": "det", "method": "explicit", "identifier": "altname", "allowed": true, "value": { "$binary": { "base64": "AQFkgAAAAAAAAAAAAAAAAAALpwNlokiTCUtTa2Kx9NVGvXR/aKPGhR5iaCT7nHEk4BOiZ9Kr4cRHdPCeZ7A+gjG4cKoT62sm3Fj1FwSOl8J8aQ==", "subType": "06" } } }, "aws_dbPointer_rand_auto_id": { "kms": "aws", "type": "dbPointer", "algo": "rand", "method": "auto", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "AgFkgAAAAAAAAAAAAAAAAAAMfCVAnMNbRGsThnoVGb2KDsCIU2ehcPtebk/TFG4GZvEmculscLLih813lEz5NHS2sAXBn721EzUS7d0TKAPbmEYFwUBnijIQIPvUoUO8AQM=", "subType": "06" } } }, "aws_dbPointer_rand_auto_altname": { "kms": "aws", "type": "dbPointer", "algo": "rand", "method": "auto", "identifier": "altname", "allowed": true, "value": { "$binary": { "base64": "AgFkgAAAAAAAAAAAAAAAAAAMvYJ5BtaMLVXV+qj85q5WqKRlzlHOBIIxZfUE/BBXUwqSTpJLdQQD++DDh6F2dtorBeYa3oUv2ef3ImASk5j23joU35Pm3Zt9Ci1pMNGodWs=", "subType": "06" } } }, "aws_dbPointer_rand_explicit_id": { "kms": "aws", "type": "dbPointer", "algo": "rand", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "AgFkgAAAAAAAAAAAAAAAAAAMdsmYtPDw8kKjfB2kWfx5W1oNEkWWct1lRpesN303pUWsawDJpfBx40lg18So2X/g4yGIwpY3qfEKQZA4vCJeT+MTjhRXFjXA7eS/mxv8f3E=", "subType": "06" } } }, "aws_dbPointer_rand_explicit_altname": { "kms": "aws", "type": "dbPointer", "algo": "rand", "method": "explicit", "identifier": "altname", "allowed": true, "value": { "$binary": { "base64": "AgFkgAAAAAAAAAAAAAAAAAAM0hcvS5zmY3mlTp0SfME/rINlflF/sx2KvP0eJTdH+Uk0WHuTkFIJAza+bXvV/gB7iNC350qyzUX3M6NHx/9s/5yBpY8MawTZTZ7WCQIA+ZI=", "subType": "06" } } }, "aws_dbPointer_det_auto_id": { "kms": "aws", "type": "dbPointer", "algo": "det", "method": "auto", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "AQFkgAAAAAAAAAAAAAAAAAAMp4QxbaEOij66L+RtaMekrDSm6QbfJBTQ8lQFhxfq9n7SVuQ9Zwdy14Ja8tyI3cGgQzQ/73rHUJ3CKA4+OYr63skYUkkkdlHxUrIMd5j5woc=", "subType": "06" } } }, "aws_dbPointer_det_explicit_id": { "kms": "aws", "type": "dbPointer", "algo": "det", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "AQFkgAAAAAAAAAAAAAAAAAAMp4QxbaEOij66L+RtaMekrDSm6QbfJBTQ8lQFhxfq9n7SVuQ9Zwdy14Ja8tyI3cGgQzQ/73rHUJ3CKA4+OYr63skYUkkkdlHxUrIMd5j5woc=", "subType": "06" } } }, "aws_dbPointer_det_explicit_altname": { "kms": "aws", "type": "dbPointer", "algo": "det", "method": "explicit", "identifier": "altname", "allowed": true, "value": { "$binary": { "base64": "AQFkgAAAAAAAAAAAAAAAAAAMp4QxbaEOij66L+RtaMekrDSm6QbfJBTQ8lQFhxfq9n7SVuQ9Zwdy14Ja8tyI3cGgQzQ/73rHUJ3CKA4+OYr63skYUkkkdlHxUrIMd5j5woc=", "subType": "06" } } }, "aws_javascript_rand_auto_id": { "kms": "aws", "type": "javascript", "algo": "rand", "method": "auto", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "AgFkgAAAAAAAAAAAAAAAAAAN3HzAC9BTD7Jgi0PR4RS/Z6L6QtAQ7VhbKRbX+1smmnYniH6jVBM6zyxMDM8h9YjMPNs8EJrGDnisuf33w5KI/A==", "subType": "06" } } }, "aws_javascript_rand_auto_altname": { "kms": "aws", "type": "javascript", "algo": "rand", "method": "auto", "identifier": "altname", "allowed": true, "value": { "$binary": { "base64": "AgFkgAAAAAAAAAAAAAAAAAANJpw+znlu3ecSiNyZ0EerVsow4aDRF2auI3Wy69EVexJkQlHO753PjRn8hG/x2kY8ROy5IUU43jaugP5AN1bwNQ==", "subType": "06" } } }, "aws_javascript_rand_explicit_id": { "kms": "aws", "type": "javascript", "algo": "rand", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "AgFkgAAAAAAAAAAAAAAAAAANzoDiq8uI0+l8COY8YdM9S3rpLvPOHOWmJqJNtOyS0ZXUx1SB5paRJ4W3Eg8KuXEeoFwvBDe9cW9YT66CzkjlBw==", "subType": "06" } } }, "aws_javascript_rand_explicit_altname": { "kms": "aws", "type": "javascript", "algo": "rand", "method": "explicit", "identifier": "altname", "allowed": true, "value": { "$binary": { "base64": "AgFkgAAAAAAAAAAAAAAAAAAN/JhtRongJweLC5SdrXHhsFz3p82q3cwXf8Sru21DK6S39S997y3uhVLn0xlX5d94PxK1XVYSjz1oVuMxZouZ7Q==", "subType": "06" } } }, "aws_javascript_det_auto_id": { "kms": "aws", "type": "javascript", "algo": "det", "method": "auto", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "AQFkgAAAAAAAAAAAAAAAAAANE39aEGiuUZ1WyakVEBgkGzLp5whkIjJ4uiaFLXniRszJL70FRkcf+aFXlA5Y4So9/ODKF76qbSsH4Jk6L+3mog==", "subType": "06" } } }, "aws_javascript_det_explicit_id": { "kms": "aws", "type": "javascript", "algo": "det", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "AQFkgAAAAAAAAAAAAAAAAAANE39aEGiuUZ1WyakVEBgkGzLp5whkIjJ4uiaFLXniRszJL70FRkcf+aFXlA5Y4So9/ODKF76qbSsH4Jk6L+3mog==", "subType": "06" } } }, "aws_javascript_det_explicit_altname": { "kms": "aws", "type": "javascript", "algo": "det", "method": "explicit", "identifier": "altname", "allowed": true, "value": { "$binary": { "base64": "AQFkgAAAAAAAAAAAAAAAAAANE39aEGiuUZ1WyakVEBgkGzLp5whkIjJ4uiaFLXniRszJL70FRkcf+aFXlA5Y4So9/ODKF76qbSsH4Jk6L+3mog==", "subType": "06" } } }, "aws_symbol_rand_auto_id": { "kms": "aws", "type": "symbol", "algo": "rand", "method": "auto", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "AgFkgAAAAAAAAAAAAAAAAAAOBv1T9tleM0xwNe7efg/MlShyzvXe3Pmg1GzPl3gjFRHZGWXR578KqX+8oiz65eXGzNuyOFvcpnR2gYCs3NeKeQfctO5plEiIva6nzCI5SK8=", "subType": "06" } } }, "aws_symbol_rand_auto_altname": { "kms": "aws", "type": "symbol", "algo": "rand", "method": "auto", "identifier": "altname", "allowed": true, "value": { "$binary": { "base64": "AgFkgAAAAAAAAAAAAAAAAAAOwLgGws8CMh+GgkEJFAx8tDIflyjsgG+/1FmZZobKAg8NOKqfXjtbnNCbvR28OCk6g/8SqBm8m53G6JciwvthJ0DirdfEexiUqu7IPtaeeyw=", "subType": "06" } } }, "aws_symbol_rand_explicit_id": { "kms": "aws", "type": "symbol", "algo": "rand", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "AgFkgAAAAAAAAAAAAAAAAAAORQi3dNkXzZeruWu19kEhDu6fFD/h47ILzk+OVKQMoriAQC5YFyVRp1yAkIaWsrsPcyCHlfZ99FySSQeqSYbZZNj5FqyonWvDuPTduHDy3CI=", "subType": "06" } } }, "aws_symbol_rand_explicit_altname": { "kms": "aws", "type": "symbol", "algo": "rand", "method": "explicit", "identifier": "altname", "allowed": true, "value": { "$binary": { "base64": "AgFkgAAAAAAAAAAAAAAAAAAOj+Yl1pQPiJ6mESOISOyUYsKN/VIvC8f0derhxIPakXkwn57U0sxv+geUkrl3JZDxY3+cX5M1JZmY+PfjaYQhbTorf9RZaVC2Wwo2lMftWi0=", "subType": "06" } } }, "aws_symbol_det_auto_id": { "kms": "aws", "type": "symbol", "algo": "det", "method": "auto", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "AQFkgAAAAAAAAAAAAAAAAAAO5IHripygBGEsVK8RFWZ1rIIVUap8KVDuqOspZpERaj+5ZEfqIcyrP/WK9KdvwOfdOWXfP/mOwuImYgNdbaQe+ejkYe4W0Y0uneCuw88k95Q=", "subType": "06" } } }, "aws_symbol_det_explicit_id": { "kms": "aws", "type": "symbol", "algo": "det", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "AQFkgAAAAAAAAAAAAAAAAAAO5IHripygBGEsVK8RFWZ1rIIVUap8KVDuqOspZpERaj+5ZEfqIcyrP/WK9KdvwOfdOWXfP/mOwuImYgNdbaQe+ejkYe4W0Y0uneCuw88k95Q=", "subType": "06" } } }, "aws_symbol_det_explicit_altname": { "kms": "aws", "type": "symbol", "algo": "det", "method": "explicit", "identifier": "altname", "allowed": true, "value": { "$binary": { "base64": "AQFkgAAAAAAAAAAAAAAAAAAO5IHripygBGEsVK8RFWZ1rIIVUap8KVDuqOspZpERaj+5ZEfqIcyrP/WK9KdvwOfdOWXfP/mOwuImYgNdbaQe+ejkYe4W0Y0uneCuw88k95Q=", "subType": "06" } } }, "aws_javascriptWithScope_rand_auto_id": { "kms": "aws", "type": "javascriptWithScope", "algo": "rand", "method": "auto", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "AgFkgAAAAAAAAAAAAAAAAAAPT31GSNkY1RM43miv1XPYtDX1vU/xORiM3U0pumjqA+JLU/HMhH++75OcMhcAQqMjm2nZtZScxdGJsJJPEEzqjbFNMJgYc9sqR5uLnzk+2dg=", "subType": "06" } } }, "aws_javascriptWithScope_rand_auto_altname": { "kms": "aws", "type": "javascriptWithScope", "algo": "rand", "method": "auto", "identifier": "altname", "allowed": true, "value": { "$binary": { "base64": "AgFkgAAAAAAAAAAAAAAAAAAPUxgaKAxSQ1uzOZtzsbtrxtDT2P/zWY6lYsbChXuRUooqvyjXSkNDqKBBA7Gp5BdGiVB/JLR47Tihpbcw1s1yGhwQRvnqeDvPrf91nvElXRY=", "subType": "06" } } }, "aws_javascriptWithScope_rand_explicit_id": { "kms": "aws", "type": "javascriptWithScope", "algo": "rand", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "AgFkgAAAAAAAAAAAAAAAAAAPv8W0ZtquFCLTG0TqvRjdzKa/4mvqT2FuEGQ0mXG2k2BZh2LY5APr/kgW0tP4eLjHzVld6OLiM9ZKAvENCZ6/fKOvqSwpIfkdLWUIeB4REQg=", "subType": "06" } } }, "aws_javascriptWithScope_rand_explicit_altname": { "kms": "aws", "type": "javascriptWithScope", "algo": "rand", "method": "explicit", "identifier": "altname", "allowed": true, "value": { "$binary": { "base64": "AgFkgAAAAAAAAAAAAAAAAAAPMVhWjaxLffdAOkVgIJpjgNIldMS451NQs3C1jb+pzopHp3DlfZ+AHQpK9reMVVKjaqanhWBpL25q+feA60XVgZPCUDroiRYqMFqU//y0amw=", "subType": "06" } } }, "aws_javascriptWithScope_det_explicit_id": { "kms": "aws", "type": "javascriptWithScope", "algo": "det", "method": "explicit", "identifier": "id", "allowed": false, "value": { "$code": "x=1", "$scope": {} } }, "aws_javascriptWithScope_det_explicit_altname": { "kms": "aws", "type": "javascriptWithScope", "algo": "det", "method": "explicit", "identifier": "altname", "allowed": false, "value": { "$code": "x=1", "$scope": {} } }, "aws_int_rand_auto_id": { "kms": "aws", "type": "int", "algo": "rand", "method": "auto", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "AgFkgAAAAAAAAAAAAAAAAAAQFV5b3vsoZe+MT4z8soetpmrWJpm7be41FNu/rdEqHWTG32jCym6762PCNYH5+vA7ldCWQkdt+ncneHsxzPrm9w==", "subType": "06" } } }, "aws_int_rand_auto_altname": { "kms": "aws", "type": "int", "algo": "rand", "method": "auto", "identifier": "altname", "allowed": true, "value": { "$binary": { "base64": "AgFkgAAAAAAAAAAAAAAAAAAQY9+QenvU1Tk/dEGZP11uOZJLHAJ9hWHbEhxbtxItt1LsdU/8gOZfypilIO5BUkLT/15PUuXV28GISNh6yIuWhw==", "subType": "06" } } }, "aws_int_rand_explicit_id": { "kms": "aws", "type": "int", "algo": "rand", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "AgFkgAAAAAAAAAAAAAAAAAAQruCugbneumhcinuXm89WW1PXVuSOewttp9cpsPPsCRVqe/uAkZOdJnZ2KaEZ9zki2GeqaJTs1qDmaJofc6GMEA==", "subType": "06" } } }, "aws_int_rand_explicit_altname": { "kms": "aws", "type": "int", "algo": "rand", "method": "explicit", "identifier": "altname", "allowed": true, "value": { "$binary": { "base64": "AgFkgAAAAAAAAAAAAAAAAAAQb15qXl/tejk4pmgkc4pUxzt4eJrv/cetgzgcPVaROAQSzd8ptbgCjaV8vP46uqozRoaDFZbQ06t65c3f0x/Ucw==", "subType": "06" } } }, "aws_int_det_auto_id": { "kms": "aws", "type": "int", "algo": "det", "method": "auto", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "AQFkgAAAAAAAAAAAAAAAAAAQCXo6ieWvfoqkG+rP7J2BV013AVf/oNMmmGWe44VEHahF+qZHzW5I/F2qIA+xgKkk172pFq0iTSOpe+K2WHMKFw==", "subType": "06" } } }, "aws_int_det_explicit_id": { "kms": "aws", "type": "int", "algo": "det", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "AQFkgAAAAAAAAAAAAAAAAAAQCXo6ieWvfoqkG+rP7J2BV013AVf/oNMmmGWe44VEHahF+qZHzW5I/F2qIA+xgKkk172pFq0iTSOpe+K2WHMKFw==", "subType": "06" } } }, "aws_int_det_explicit_altname": { "kms": "aws", "type": "int", "algo": "det", "method": "explicit", "identifier": "altname", "allowed": true, "value": { "$binary": { "base64": "AQFkgAAAAAAAAAAAAAAAAAAQCXo6ieWvfoqkG+rP7J2BV013AVf/oNMmmGWe44VEHahF+qZHzW5I/F2qIA+xgKkk172pFq0iTSOpe+K2WHMKFw==", "subType": "06" } } }, "aws_timestamp_rand_auto_id": { "kms": "aws", "type": "timestamp", "algo": "rand", "method": "auto", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "AgFkgAAAAAAAAAAAAAAAAAAR63xXG8mrlixkQzD5VBIPE6NHicaWcS5CBhiIJDcZ0x8D9c5TgRJUfCeWhKvWFD4o0DoxcBQ2opPormFDpvmq/g==", "subType": "06" } } }, "aws_timestamp_rand_auto_altname": { "kms": "aws", "type": "timestamp", "algo": "rand", "method": "auto", "identifier": "altname", "allowed": true, "value": { "$binary": { "base64": "AgFkgAAAAAAAAAAAAAAAAAARAgY9LsUxP6gP4gYRvvzZ4iaHVQRNbycATiVag1YNSiDmEr4LYserYuBscdrIy4v3zgGaulFM9KV86bx0ItycZA==", "subType": "06" } } }, "aws_timestamp_rand_explicit_id": { "kms": "aws", "type": "timestamp", "algo": "rand", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "AgFkgAAAAAAAAAAAAAAAAAARLneAZqPcHdzGGnXz2Ne5E7HP9cDC1+yoIwcA8OSF/IlzEjrrMAi3z6Izol6gWDlD7VOh7QYL3sASJOXyzF1hPQ==", "subType": "06" } } }, "aws_timestamp_rand_explicit_altname": { "kms": "aws", "type": "timestamp", "algo": "rand", "method": "explicit", "identifier": "altname", "allowed": true, "value": { "$binary": { "base64": "AgFkgAAAAAAAAAAAAAAAAAARH2bU7KNo5SHxiO8JFEcT9wryuHNXyM7ADop1oPcESyay1Nc0WHPD3nr0yMAK481NxOkE3qXyaslu7bcP/744WA==", "subType": "06" } } }, "aws_timestamp_det_auto_id": { "kms": "aws", "type": "timestamp", "algo": "det", "method": "auto", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "AQFkgAAAAAAAAAAAAAAAAAARG7kGfx0ky+d4Hl/fRBu8oUR1Mph26Dkv3J7fxGYanpzOFMiHIfVO0uwYMvsfzG54y0DDNlS3FmmS13DzepbzGQ==", "subType": "06" } } }, "aws_timestamp_det_explicit_id": { "kms": "aws", "type": "timestamp", "algo": "det", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "AQFkgAAAAAAAAAAAAAAAAAARG7kGfx0ky+d4Hl/fRBu8oUR1Mph26Dkv3J7fxGYanpzOFMiHIfVO0uwYMvsfzG54y0DDNlS3FmmS13DzepbzGQ==", "subType": "06" } } }, "aws_timestamp_det_explicit_altname": { "kms": "aws", "type": "timestamp", "algo": "det", "method": "explicit", "identifier": "altname", "allowed": true, "value": { "$binary": { "base64": "AQFkgAAAAAAAAAAAAAAAAAARG7kGfx0ky+d4Hl/fRBu8oUR1Mph26Dkv3J7fxGYanpzOFMiHIfVO0uwYMvsfzG54y0DDNlS3FmmS13DzepbzGQ==", "subType": "06" } } }, "aws_long_rand_auto_id": { "kms": "aws", "type": "long", "algo": "rand", "method": "auto", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "AgFkgAAAAAAAAAAAAAAAAAASZbes2EdR78crt2pXVElW2YwAQh8HEBapYYeav2VQeg2syXaV/qZuD8ofnAVn4v/DydTTMVMmK+sVU/TlnAu2eA==", "subType": "06" } } }, "aws_long_rand_auto_altname": { "kms": "aws", "type": "long", "algo": "rand", "method": "auto", "identifier": "altname", "allowed": true, "value": { "$binary": { "base64": "AgFkgAAAAAAAAAAAAAAAAAASt+7fmMYH+fLHgybc+sng8/UmKP3YPUEPCz1SXVQljQp6orsCILSgtgGPsdeGnN5NSxh3XzerHs6zlR92fWpZCw==", "subType": "06" } } }, "aws_long_rand_explicit_id": { "kms": "aws", "type": "long", "algo": "rand", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "AgFkgAAAAAAAAAAAAAAAAAAS01fF1uo6zYDToJnOT/EbDipzk7YZ6I+IspZF+avjU3XYfpRxT9NdAgKr0euWJwyAsdpWqqCwFummfrPeZOy04A==", "subType": "06" } } }, "aws_long_rand_explicit_altname": { "kms": "aws", "type": "long", "algo": "rand", "method": "explicit", "identifier": "altname", "allowed": true, "value": { "$binary": { "base64": "AgFkgAAAAAAAAAAAAAAAAAAS6tpH796bqy58mXf38rJvVtA1uBcxBE5yIGQ4RN44oypc/pvw0ouhFI1dkoneKMtAFU/5RygZV+RvQhRtgKn76A==", "subType": "06" } } }, "aws_long_det_auto_id": { "kms": "aws", "type": "long", "algo": "det", "method": "auto", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "AQFkgAAAAAAAAAAAAAAAAAASC7O/8JeB4WTqQFPuMpFRsAuonPS3yu7IAPZeRPIr03CmM6HNndYIKMoFM13eELNZTdJSgg9u9ItGqRw+/XMHzQ==", "subType": "06" } } }, "aws_long_det_explicit_id": { "kms": "aws", "type": "long", "algo": "det", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "AQFkgAAAAAAAAAAAAAAAAAASC7O/8JeB4WTqQFPuMpFRsAuonPS3yu7IAPZeRPIr03CmM6HNndYIKMoFM13eELNZTdJSgg9u9ItGqRw+/XMHzQ==", "subType": "06" } } }, "aws_long_det_explicit_altname": { "kms": "aws", "type": "long", "algo": "det", "method": "explicit", "identifier": "altname", "allowed": true, "value": { "$binary": { "base64": "AQFkgAAAAAAAAAAAAAAAAAASC7O/8JeB4WTqQFPuMpFRsAuonPS3yu7IAPZeRPIr03CmM6HNndYIKMoFM13eELNZTdJSgg9u9ItGqRw+/XMHzQ==", "subType": "06" } } }, "aws_decimal_rand_auto_id": { "kms": "aws", "type": "decimal", "algo": "rand", "method": "auto", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "AgFkgAAAAAAAAAAAAAAAAAATgf5zW9EgnWHPxj4HAGt472eN9UXP41TaF8V2J7S2zqSpiBZGKDuOIjw2FBSqaNp53vvfl9HpwAuQBJZhrwkBCKRkKV/AAR3/pTpuoqhSKaM=", "subType": "06" } } }, "aws_decimal_rand_auto_altname": { "kms": "aws", "type": "decimal", "algo": "rand", "method": "auto", "identifier": "altname", "allowed": true, "value": { "$binary": { "base64": "AgFkgAAAAAAAAAAAAAAAAAATPRfvZWdupE2N0W1DXUx7X8Zz7g43jawJL7PbQtTYetI78xRETkMdygwSEHgs+cvnUBBtYIeKRVkOGZQkwf568OclhDiPxUeD38cR5blBq/U=", "subType": "06" } } }, "aws_decimal_rand_explicit_id": { "kms": "aws", "type": "decimal", "algo": "rand", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "AgFkgAAAAAAAAAAAAAAAAAAT+ZnCg2lSMIohZ9RJ4CNs3LZ0g+nV04cYAmrxTSrTSBPGlZ7Ywh5A2rCss7AUijYZiKiYyZbuAzukbOuVRhdCtm+xo9+DyLAwTezF18okk6Y=", "subType": "06" } } }, "aws_decimal_rand_explicit_altname": { "kms": "aws", "type": "decimal", "algo": "rand", "method": "explicit", "identifier": "altname", "allowed": true, "value": { "$binary": { "base64": "AgFkgAAAAAAAAAAAAAAAAAATlnQYASsTZRRHzFjcbCClXartcXBVRrYv7JImMkDmAj6EAjf/ZqpjeykkS/wohMhXaNwyZBdREr+n+GDV7imYoL4WRBOLnqB6hrYidlWqNzE=", "subType": "06" } } }, "aws_decimal_det_explicit_id": { "kms": "aws", "type": "decimal", "algo": "det", "method": "explicit", "identifier": "id", "allowed": false, "value": { "$numberDecimal": "1.234" } }, "aws_decimal_det_explicit_altname": { "kms": "aws", "type": "decimal", "algo": "det", "method": "explicit", "identifier": "altname", "allowed": false, "value": { "$numberDecimal": "1.234" } }, "aws_minKey_rand_explicit_id": { "kms": "aws", "type": "minKey", "algo": "rand", "method": "explicit", "identifier": "id", "allowed": false, "value": { "$minKey": 1 } }, "aws_minKey_rand_explicit_altname": { "kms": "aws", "type": "minKey", "algo": "rand", "method": "explicit", "identifier": "altname", "allowed": false, "value": { "$minKey": 1 } }, "aws_minKey_det_explicit_id": { "kms": "aws", "type": "minKey", "algo": "det", "method": "explicit", "identifier": "id", "allowed": false, "value": { "$minKey": 1 } }, "aws_minKey_det_explicit_altname": { "kms": "aws", "type": "minKey", "algo": "det", "method": "explicit", "identifier": "altname", "allowed": false, "value": { "$minKey": 1 } }, "aws_maxKey_rand_explicit_id": { "kms": "aws", "type": "maxKey", "algo": "rand", "method": "explicit", "identifier": "id", "allowed": false, "value": { "$maxKey": 1 } }, "aws_maxKey_rand_explicit_altname": { "kms": "aws", "type": "maxKey", "algo": "rand", "method": "explicit", "identifier": "altname", "allowed": false, "value": { "$maxKey": 1 } }, "aws_maxKey_det_explicit_id": { "kms": "aws", "type": "maxKey", "algo": "det", "method": "explicit", "identifier": "id", "allowed": false, "value": { "$maxKey": 1 } }, "aws_maxKey_det_explicit_altname": { "kms": "aws", "type": "maxKey", "algo": "det", "method": "explicit", "identifier": "altname", "allowed": false, "value": { "$maxKey": 1 } }, "local_double_rand_auto_id": { "kms": "local", "type": "double", "algo": "rand", "method": "auto", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "AizggCwAAAAAAAAAAAAAAAABGF195CB8nRmK9+KxYO7T96MeXucC/ILQtEEQAS4zrwj3Qz7YEQrf/apvbKTCkn3siN2XSDLQ/7dmddZa9xa9yQ==", "subType": "06" } } }, "local_double_rand_auto_altname": { "kms": "local", "type": "double", "algo": "rand", "method": "auto", "identifier": "altname", "allowed": true, "value": { "$binary": { "base64": "AizggCwAAAAAAAAAAAAAAAABY8g18z6ZOjGtfNxaAmU95tXMdoM6qbtDMpB72paqiHZTW1UGB22HPXiEnVz05JTBzzX4fc6tOldX6aJel812Zg==", "subType": "06" } } }, "local_double_rand_explicit_id": { "kms": "local", "type": "double", "algo": "rand", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "AizggCwAAAAAAAAAAAAAAAABDlHwN8hYyScEhhx64TdJ2Qp2rmKRg8983zdqIL1914tyPwRQq7ySCOhmFif2S7v4KT+r0uOfimYvKD1n9rKHlg==", "subType": "06" } } }, "local_double_rand_explicit_altname": { "kms": "local", "type": "double", "algo": "rand", "method": "explicit", "identifier": "altname", "allowed": true, "value": { "$binary": { "base64": "AizggCwAAAAAAAAAAAAAAAAB2VnTFlaCRzAZZTQiMWQORFNgXIuAJlHJXIHiYow2eO6JbVghWTpH+MsdafBNPVnc0zKuZBL0Qs2Nuk1xiQaqhA==", "subType": "06" } } }, "local_double_det_explicit_id": { "kms": "local", "type": "double", "algo": "det", "method": "explicit", "identifier": "id", "allowed": false, "value": { "$numberDouble": "1.234" } }, "local_double_det_explicit_altname": { "kms": "local", "type": "double", "algo": "det", "method": "explicit", "identifier": "altname", "allowed": false, "value": { "$numberDouble": "1.234" } }, "local_string_rand_auto_id": { "kms": "local", "type": "string", "algo": "rand", "method": "auto", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "AizggCwAAAAAAAAAAAAAAAAC5NBAPM8q2n9fnkwQfE9so/XcO51plPBNs5VlBRbDw68k9T6/uZ2TWsAvTYtVooY59zHHr2QS3usKbGQB6J61rA==", "subType": "06" } } }, "local_string_rand_auto_altname": { "kms": "local", "type": "string", "algo": "rand", "method": "auto", "identifier": "altname", "allowed": true, "value": { "$binary": { "base64": "AizggCwAAAAAAAAAAAAAAAACM/EjGMrkYHvSZra26m74upuvLkfKXTs+tTWquGzrgWYLnLt8I6XBIwx1VymS9EybrCU/ewmtgjLUNUFQacIeXA==", "subType": "06" } } }, "local_string_rand_explicit_id": { "kms": "local", "type": "string", "algo": "rand", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "AizggCwAAAAAAAAAAAAAAAACn4tD26UG8lO9gTZaxen6yXzHo/a2lokeY1ClxHMtJODoJr2JZzIDHP3A9aZ8L4+Vu+nyqphaWyGaGONKu8gpcQ==", "subType": "06" } } }, "local_string_rand_explicit_altname": { "kms": "local", "type": "string", "algo": "rand", "method": "explicit", "identifier": "altname", "allowed": true, "value": { "$binary": { "base64": "AizggCwAAAAAAAAAAAAAAAACZfoO2LjY+IB31FZ1Tq7pHr0DCFKGJqWcXcOrnZ7bV9Euc9f101motJc31sp8nF5CTCfd83VQE0319eQrxDDaSw==", "subType": "06" } } }, "local_string_det_auto_id": { "kms": "local", "type": "string", "algo": "det", "method": "auto", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "ASzggCwAAAAAAAAAAAAAAAACW0cZMYWOY3eoqQQkSdBtS9iHC4CSQA27dy6XJGcmTV8EDuhGNnPmbx0EKFTDb0PCSyCjMyuE4nsgmNYgjTaSuw==", "subType": "06" } } }, "local_string_det_explicit_id": { "kms": "local", "type": "string", "algo": "det", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "ASzggCwAAAAAAAAAAAAAAAACW0cZMYWOY3eoqQQkSdBtS9iHC4CSQA27dy6XJGcmTV8EDuhGNnPmbx0EKFTDb0PCSyCjMyuE4nsgmNYgjTaSuw==", "subType": "06" } } }, "local_string_det_explicit_altname": { "kms": "local", "type": "string", "algo": "det", "method": "explicit", "identifier": "altname", "allowed": true, "value": { "$binary": { "base64": "ASzggCwAAAAAAAAAAAAAAAACW0cZMYWOY3eoqQQkSdBtS9iHC4CSQA27dy6XJGcmTV8EDuhGNnPmbx0EKFTDb0PCSyCjMyuE4nsgmNYgjTaSuw==", "subType": "06" } } }, "local_object_rand_auto_id": { "kms": "local", "type": "object", "algo": "rand", "method": "auto", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "AizggCwAAAAAAAAAAAAAAAADlekcUsETAkkKTjCVx5EISJN+sftrQax/VhaWXLyRgRz97adXXmwZkMyt+035SHZsF91i2LaXziMA4RHoP+nKFw==", "subType": "06" } } }, "local_object_rand_auto_altname": { "kms": "local", "type": "object", "algo": "rand", "method": "auto", "identifier": "altname", "allowed": true, "value": { "$binary": { "base64": "AizggCwAAAAAAAAAAAAAAAADpaQmy5r6q9gLqEm+FIi/OyQgcuUnrICCP9rC4S3wR6qUHd82IW/3dFQUzwTkaXxgStjopamQMuZ4ESRj0xx0bA==", "subType": "06" } } }, "local_object_rand_explicit_id": { "kms": "local", "type": "object", "algo": "rand", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "AizggCwAAAAAAAAAAAAAAAADCHRJCINzWY0u4gZPWEmHg/JoQ8IW4yMfUyzYJCQrEMp4rUeupIuxqSuq2QyLBYZBBv0r7t3lNH49I5qDeav2vA==", "subType": "06" } } }, "local_object_rand_explicit_altname": { "kms": "local", "type": "object", "algo": "rand", "method": "explicit", "identifier": "altname", "allowed": true, "value": { "$binary": { "base64": "AizggCwAAAAAAAAAAAAAAAADrHQQUnLF1jdNmFY/V266cS28XAB4nOKetHAcSbwkeUxNzgZT1g+XMQaYfcNMMv/ywypKU1KpgLMsEOpm4qcPkQ==", "subType": "06" } } }, "local_object_det_explicit_id": { "kms": "local", "type": "object", "algo": "det", "method": "explicit", "identifier": "id", "allowed": false, "value": { "x": { "$numberInt": "1" } } }, "local_object_det_explicit_altname": { "kms": "local", "type": "object", "algo": "det", "method": "explicit", "identifier": "altname", "allowed": false, "value": { "x": { "$numberInt": "1" } } }, "local_array_rand_auto_id": { "kms": "local", "type": "array", "algo": "rand", "method": "auto", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "AizggCwAAAAAAAAAAAAAAAAEXa7bQ5vGPNsLdklM/H+sop8aCL4vlDiVUoVjTAGjTngn2WLcdKLWxaNSyMdJpsI/NsxQJ58YrcwP+yHzi9rZVtRdbg7m8p+CYcq1vUm6UoQ=", "subType": "06" } } }, "local_array_rand_auto_altname": { "kms": "local", "type": "array", "algo": "rand", "method": "auto", "identifier": "altname", "allowed": true, "value": { "$binary": { "base64": "AizggCwAAAAAAAAAAAAAAAAEVlZlOvtRmGIhcYi/qPl3HKi/qf0yRQrkbVo9rScYkxDCBN9wA55pAWHDQ/5Sjy4d0DwL57k+M1G9e7xSIrv8xXKwoIuuabhSWaIX2eJHroY=", "subType": "06" } } }, "local_array_rand_explicit_id": { "kms": "local", "type": "array", "algo": "rand", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "AizggCwAAAAAAAAAAAAAAAAEYBLSYHHt2rohezMF4lMjNdqy9CY33EHf+pgRbJwVXZScLDgn9CcqeRsdU8bW5h2qgNpQvoSMBB7pW+Dgp1RauTHZSOd4PcZpAGjwoFDWSSM=", "subType": "06" } } }, "local_array_rand_explicit_altname": { "kms": "local", "type": "array", "algo": "rand", "method": "explicit", "identifier": "altname", "allowed": true, "value": { "$binary": { "base64": "AizggCwAAAAAAAAAAAAAAAAES1IJ8S2NxWekolQockxLJvzFSGfKQ9Xbi55vO8LyWo0sIG9ZgPQXtVQkZ301CsdFduvx9A0vDqQ0MGYc4plxNnpUTizJPRUDyez5dOgZ9tI=", "subType": "06" } } }, "local_array_det_explicit_id": { "kms": "local", "type": "array", "algo": "det", "method": "explicit", "identifier": "id", "allowed": false, "value": [ { "$numberInt": "1" }, { "$numberInt": "2" }, { "$numberInt": "3" } ] }, "local_array_det_explicit_altname": { "kms": "local", "type": "array", "algo": "det", "method": "explicit", "identifier": "altname", "allowed": false, "value": [ { "$numberInt": "1" }, { "$numberInt": "2" }, { "$numberInt": "3" } ] }, "local_binData=00_rand_auto_id": { "kms": "local", "type": "binData=00", "algo": "rand", "method": "auto", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "AizggCwAAAAAAAAAAAAAAAAF+hgWs4ZCo9GnmhSM9SDSWzWX4E7Tlp4TwlEy3zfO/rrMREECGB4u8LD8Ju9b8YP+xcZhMI1tcz/vrQS87NffUg==", "subType": "06" } } }, "local_binData=00_rand_auto_altname": { "kms": "local", "type": "binData=00", "algo": "rand", "method": "auto", "identifier": "altname", "allowed": true, "value": { "$binary": { "base64": "AizggCwAAAAAAAAAAAAAAAAFtEvaXWpGfXC1GlKu0AeRDaeBKHryGoS0tAUr48vfYk7umCr+fJKyXCY9vSv7wCiQxWLe8V/EZWkHsu0zqhJw9w==", "subType": "06" } } }, "local_binData=00_rand_explicit_id": { "kms": "local", "type": "binData=00", "algo": "rand", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "AizggCwAAAAAAAAAAAAAAAAF/1L5bvmMX3Bk2nAw8KvvRd/7nZ82XHVasT0jrlPhSiJU7ehJMeUCOb7HCHU6KgCzZB9C2W3NoVhLKIhE9ZnYdg==", "subType": "06" } } }, "local_binData=00_rand_explicit_altname": { "kms": "local", "type": "binData=00", "algo": "rand", "method": "explicit", "identifier": "altname", "allowed": true, "value": { "$binary": { "base64": "AizggCwAAAAAAAAAAAAAAAAFK0W5IWKzggR4UU+fhwA2p8YCHLfmx5y1OEtHc/9be9eEYTORACDmWY6207Vd4LhBJCedd+Q5qMm7NRZjjhyLEQ==", "subType": "06" } } }, "local_binData=00_det_auto_id": { "kms": "local", "type": "binData=00", "algo": "det", "method": "auto", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "ASzggCwAAAAAAAAAAAAAAAAF1ofBnK9+ERP29P/i14GQ/y3muic6tNKY532zCkzQkJSktYCOeXS8DdY1DdaOP/asZWzPTdgwby6/iZcAxJU+xQ==", "subType": "06" } } }, "local_binData=00_det_explicit_id": { "kms": "local", "type": "binData=00", "algo": "det", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "ASzggCwAAAAAAAAAAAAAAAAF1ofBnK9+ERP29P/i14GQ/y3muic6tNKY532zCkzQkJSktYCOeXS8DdY1DdaOP/asZWzPTdgwby6/iZcAxJU+xQ==", "subType": "06" } } }, "local_binData=00_det_explicit_altname": { "kms": "local", "type": "binData=00", "algo": "det", "method": "explicit", "identifier": "altname", "allowed": true, "value": { "$binary": { "base64": "ASzggCwAAAAAAAAAAAAAAAAF1ofBnK9+ERP29P/i14GQ/y3muic6tNKY532zCkzQkJSktYCOeXS8DdY1DdaOP/asZWzPTdgwby6/iZcAxJU+xQ==", "subType": "06" } } }, "local_binData=04_rand_auto_id": { "kms": "local", "type": "binData=04", "algo": "rand", "method": "auto", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "AizggCwAAAAAAAAAAAAAAAAFxq38aA4k/tYHPwJFRK0pahlo/3zjCe3VHJRqURRA+04lbJCvdkQTawxWlf8o+3Pcetl1UcPTQigdYp5KbIkstuPstLbT+TZXHVD1os9LTRw=", "subType": "06" } } }, "local_binData=04_rand_auto_altname": { "kms": "local", "type": "binData=04", "algo": "rand", "method": "auto", "identifier": "altname", "allowed": true, "value": { "$binary": { "base64": "AizggCwAAAAAAAAAAAAAAAAFTXNWchCPmCSY0+AL22/kCBmAoDJDX5T18jpJHLdvZtHs0zwD64b9hLvfRK268BlNu4P37KDFE6LT0QzjG7brqzFJf3ZaadDCKeIw1q7DWQs=", "subType": "06" } } }, "local_binData=04_rand_explicit_id": { "kms": "local", "type": "binData=04", "algo": "rand", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "AizggCwAAAAAAAAAAAAAAAAF7XgMgKjQmWYWmobrYWKiGYCKsy5kTgVweFBuzvFISaZjFsq2hrZB2DwUaOeT6XUPH/Onrdjc3fNElf3FdQDHif4rt+1lh9jEX+nMbRw9i3s=", "subType": "06" } } }, "local_binData=04_rand_explicit_altname": { "kms": "local", "type": "binData=04", "algo": "rand", "method": "explicit", "identifier": "altname", "allowed": true, "value": { "$binary": { "base64": "AizggCwAAAAAAAAAAAAAAAAFGoA/1H0waFLor6LbkUCLC2Wm9j/ZT7yifPbf0G7WvO0+gBLlffr3aJIQ9ik5vxPbmDDMCoYlbEYgb8i9I5tKC17WPhjVH2N2+4l9y7aEmS4=", "subType": "06" } } }, "local_binData=04_det_auto_id": { "kms": "local", "type": "binData=04", "algo": "det", "method": "auto", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "ASzggCwAAAAAAAAAAAAAAAAFwO3hsD8ee/uwgUiHWem8fGe54LsTJWqgbRCacIe6sxrsyLT6EsVIqg4Sn7Ou+FC3WJbFld5kx8euLe/MHa8FGYjxD97z5j+rUx5tt3T6YbA=", "subType": "06" } } }, "local_binData=04_det_explicit_id": { "kms": "local", "type": "binData=04", "algo": "det", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "ASzggCwAAAAAAAAAAAAAAAAFwO3hsD8ee/uwgUiHWem8fGe54LsTJWqgbRCacIe6sxrsyLT6EsVIqg4Sn7Ou+FC3WJbFld5kx8euLe/MHa8FGYjxD97z5j+rUx5tt3T6YbA=", "subType": "06" } } }, "local_binData=04_det_explicit_altname": { "kms": "local", "type": "binData=04", "algo": "det", "method": "explicit", "identifier": "altname", "allowed": true, "value": { "$binary": { "base64": "ASzggCwAAAAAAAAAAAAAAAAFwO3hsD8ee/uwgUiHWem8fGe54LsTJWqgbRCacIe6sxrsyLT6EsVIqg4Sn7Ou+FC3WJbFld5kx8euLe/MHa8FGYjxD97z5j+rUx5tt3T6YbA=", "subType": "06" } } }, "local_undefined_rand_explicit_id": { "kms": "local", "type": "undefined", "algo": "rand", "method": "explicit", "identifier": "id", "allowed": false, "value": { "$undefined": true } }, "local_undefined_rand_explicit_altname": { "kms": "local", "type": "undefined", "algo": "rand", "method": "explicit", "identifier": "altname", "allowed": false, "value": { "$undefined": true } }, "local_undefined_det_explicit_id": { "kms": "local", "type": "undefined", "algo": "det", "method": "explicit", "identifier": "id", "allowed": false, "value": { "$undefined": true } }, "local_undefined_det_explicit_altname": { "kms": "local", "type": "undefined", "algo": "det", "method": "explicit", "identifier": "altname", "allowed": false, "value": { "$undefined": true } }, "local_objectId_rand_auto_id": { "kms": "local", "type": "objectId", "algo": "rand", "method": "auto", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "AizggCwAAAAAAAAAAAAAAAAHfvxWRZOzfao3faE3RglL0IcDpBcNwqiGL5KgSokmRxWjjWeiel88Mbo5Plo0SswwNQ2H7C5GVG21L+UbvcW63g==", "subType": "06" } } }, "local_objectId_rand_auto_altname": { "kms": "local", "type": "objectId", "algo": "rand", "method": "auto", "identifier": "altname", "allowed": true, "value": { "$binary": { "base64": "AizggCwAAAAAAAAAAAAAAAAHhd9lSOO7bHE7PM+Uxa2v3X1FF66IwyEr0wqnyTaOM+cHQLmec/RlEaRIQ1x2AiW7LwmmVgZ0xBMK9CMh0Lhbyw==", "subType": "06" } } }, "local_objectId_rand_explicit_id": { "kms": "local", "type": "objectId", "algo": "rand", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "AizggCwAAAAAAAAAAAAAAAAHETwT9bo+JtboBVW/8GzzMQCpn22iiNJnlxYfyO45jvYJQRs29RRIouCsnFkmC7cfAO3GlVxv113euYjIO7AlAg==", "subType": "06" } } }, "local_objectId_rand_explicit_altname": { "kms": "local", "type": "objectId", "algo": "rand", "method": "explicit", "identifier": "altname", "allowed": true, "value": { "$binary": { "base64": "AizggCwAAAAAAAAAAAAAAAAHhsguAMBzQUFBAitpJDzKEaMDGUGfvCzmUUhf4rnp8xeall/p91TUudaSMcU11XEgJ0Mym4IbYRd8+TfUai0nvw==", "subType": "06" } } }, "local_objectId_det_auto_id": { "kms": "local", "type": "objectId", "algo": "det", "method": "auto", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "ASzggCwAAAAAAAAAAAAAAAAH4ElF4AvQ+kkGfhadgKNy3GcYrDZPN6RpzaMYIhcCGDvC9W+cIS9dH1aJbPU7vTPmEZnnynPTDWjw3rAj2+9mOA==", "subType": "06" } } }, "local_objectId_det_explicit_id": { "kms": "local", "type": "objectId", "algo": "det", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "ASzggCwAAAAAAAAAAAAAAAAH4ElF4AvQ+kkGfhadgKNy3GcYrDZPN6RpzaMYIhcCGDvC9W+cIS9dH1aJbPU7vTPmEZnnynPTDWjw3rAj2+9mOA==", "subType": "06" } } }, "local_objectId_det_explicit_altname": { "kms": "local", "type": "objectId", "algo": "det", "method": "explicit", "identifier": "altname", "allowed": true, "value": { "$binary": { "base64": "ASzggCwAAAAAAAAAAAAAAAAH4ElF4AvQ+kkGfhadgKNy3GcYrDZPN6RpzaMYIhcCGDvC9W+cIS9dH1aJbPU7vTPmEZnnynPTDWjw3rAj2+9mOA==", "subType": "06" } } }, "local_bool_rand_auto_id": { "kms": "local", "type": "bool", "algo": "rand", "method": "auto", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "AizggCwAAAAAAAAAAAAAAAAIxGld4J/2vSWg5tjQulpkm9C6WeUcLbv2yfKRXPAbmLpv3u4Yrmr5qisJtqmDPTcb993WosvCYAh0UGW+zpsdEg==", "subType": "06" } } }, "local_bool_rand_auto_altname": { "kms": "local", "type": "bool", "algo": "rand", "method": "auto", "identifier": "altname", "allowed": true, "value": { "$binary": { "base64": "AizggCwAAAAAAAAAAAAAAAAIpUFPiS2uoW1Aqs0WQkBa201OBmsuJ8WUKcv5aBPASkcwfaw9qSWs3QrbEDR2GyoU4SeYOByCAQMzXCPoIYAFdQ==", "subType": "06" } } }, "local_bool_rand_explicit_id": { "kms": "local", "type": "bool", "algo": "rand", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "AizggCwAAAAAAAAAAAAAAAAIJuzu1a60meYlU3LMjw/7G4Vh/lqKopxdpGWoLXEmY/NoHgX6Fkv9iTwxv/Nv8rZwtawpFV+mQUG/6A1IHMBASQ==", "subType": "06" } } }, "local_bool_rand_explicit_altname": { "kms": "local", "type": "bool", "algo": "rand", "method": "explicit", "identifier": "altname", "allowed": true, "value": { "$binary": { "base64": "AizggCwAAAAAAAAAAAAAAAAIn9VjxL5TdGgJLckNHRrIaL32L31q5OERRZG2M5OYKk66TnrlfEs+ykcDvGwMGKpr/PYjY5kBHDc/oELGJJbWRQ==", "subType": "06" } } }, "local_bool_det_explicit_id": { "kms": "local", "type": "bool", "algo": "det", "method": "explicit", "identifier": "id", "allowed": false, "value": true }, "local_bool_det_explicit_altname": { "kms": "local", "type": "bool", "algo": "det", "method": "explicit", "identifier": "altname", "allowed": false, "value": true }, "local_date_rand_auto_id": { "kms": "local", "type": "date", "algo": "rand", "method": "auto", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "AizggCwAAAAAAAAAAAAAAAAJPPv4MC5xzt2uxPGBHH9g2z03o9SQjjmuxt97Ub1UcKCCHsGED3bx6YSrocuEMiFFI4d5Fqgl8HNeS4j0PR0tYA==", "subType": "06" } } }, "local_date_rand_auto_altname": { "kms": "local", "type": "date", "algo": "rand", "method": "auto", "identifier": "altname", "allowed": true, "value": { "$binary": { "base64": "AizggCwAAAAAAAAAAAAAAAAJ6i2A9Hi4xWlOMjFMGpwaRctR1VFnb4El166n18RvjKic46V+WoadvLHS32RhPOvkLVYwIeU4C+vrO5isBNoUdw==", "subType": "06" } } }, "local_date_rand_explicit_id": { "kms": "local", "type": "date", "algo": "rand", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "AizggCwAAAAAAAAAAAAAAAAJHcniV7Q0C8ZTWrE0hp5i5bUPlrrRdNLZckfODw8XNVtVPDjbznglccQmI7w1t8kOVp65eKzVzUOXN0YkqA+1QA==", "subType": "06" } } }, "local_date_rand_explicit_altname": { "kms": "local", "type": "date", "algo": "rand", "method": "explicit", "identifier": "altname", "allowed": true, "value": { "$binary": { "base64": "AizggCwAAAAAAAAAAAAAAAAJKCUCjC3hsmEKKYwGP3ceh3zR+ArE8LYFOQfN87aEsTr60VrzHXmsE8PvizRhhMnrp07ljzQkuat39L+0QSR2qQ==", "subType": "06" } } }, "local_date_det_auto_id": { "kms": "local", "type": "date", "algo": "det", "method": "auto", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "ASzggCwAAAAAAAAAAAAAAAAJ1GMYQTruoKr6fv9XCbcVkx/3yivymPSMEkPCRDYxQv45w4TqBKMDfpRd1TOLOv1qvcb+gjH+z5IfVBMp2IpG/Q==", "subType": "06" } } }, "local_date_det_explicit_id": { "kms": "local", "type": "date", "algo": "det", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "ASzggCwAAAAAAAAAAAAAAAAJ1GMYQTruoKr6fv9XCbcVkx/3yivymPSMEkPCRDYxQv45w4TqBKMDfpRd1TOLOv1qvcb+gjH+z5IfVBMp2IpG/Q==", "subType": "06" } } }, "local_date_det_explicit_altname": { "kms": "local", "type": "date", "algo": "det", "method": "explicit", "identifier": "altname", "allowed": true, "value": { "$binary": { "base64": "ASzggCwAAAAAAAAAAAAAAAAJ1GMYQTruoKr6fv9XCbcVkx/3yivymPSMEkPCRDYxQv45w4TqBKMDfpRd1TOLOv1qvcb+gjH+z5IfVBMp2IpG/Q==", "subType": "06" } } }, "local_null_rand_explicit_id": { "kms": "local", "type": "null", "algo": "rand", "method": "explicit", "identifier": "id", "allowed": false, "value": null }, "local_null_rand_explicit_altname": { "kms": "local", "type": "null", "algo": "rand", "method": "explicit", "identifier": "altname", "allowed": false, "value": null }, "local_null_det_explicit_id": { "kms": "local", "type": "null", "algo": "det", "method": "explicit", "identifier": "id", "allowed": false, "value": null }, "local_null_det_explicit_altname": { "kms": "local", "type": "null", "algo": "det", "method": "explicit", "identifier": "altname", "allowed": false, "value": null }, "local_regex_rand_auto_id": { "kms": "local", "type": "regex", "algo": "rand", "method": "auto", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "AizggCwAAAAAAAAAAAAAAAALXKw7zSgqQj1AKoWO0MoMxsBuu0cMB6KdJQCRKdupoLV/Y22owwsVpDDMv5sgUpkG5YIV+Fz7taHodXE07qHopw==", "subType": "06" } } }, "local_regex_rand_auto_altname": { "kms": "local", "type": "regex", "algo": "rand", "method": "auto", "identifier": "altname", "allowed": true, "value": { "$binary": { "base64": "AizggCwAAAAAAAAAAAAAAAALntOLXq7VW1+jwba/dSbidMo2bewNo7AtK9A1CPwk9XrjUQaEOQxfRpho3BYQEo2U67fQdsY/tyhaj4jduHn9JQ==", "subType": "06" } } }, "local_regex_rand_explicit_id": { "kms": "local", "type": "regex", "algo": "rand", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "AizggCwAAAAAAAAAAAAAAAALlMMG2iS/gEOEsVKR7sxBJP2IUzZ+aRbozDSkqADncresBvaPBSE17lng5NG7H1JRCAcP1rH/Te+0CrMd7JpRAQ==", "subType": "06" } } }, "local_regex_rand_explicit_altname": { "kms": "local", "type": "regex", "algo": "rand", "method": "explicit", "identifier": "altname", "allowed": true, "value": { "$binary": { "base64": "AizggCwAAAAAAAAAAAAAAAAL1YNnlVu5+njDLxh1LMhIPOH19RykAXhxrUbCy6TI5MLQsAOSgAJbXOTXeKr0D8/Ff0phToWOKl193gOOIp8yZQ==", "subType": "06" } } }, "local_regex_det_auto_id": { "kms": "local", "type": "regex", "algo": "det", "method": "auto", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "ASzggCwAAAAAAAAAAAAAAAALiZbL5nFIZl7cSLH5E3wK3jJeAeFc7hLHNITtLAu+o10raEs5i/UCihMHmkf8KHZxghs056pfm5BjPzlL9x7IHQ==", "subType": "06" } } }, "local_regex_det_explicit_id": { "kms": "local", "type": "regex", "algo": "det", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "ASzggCwAAAAAAAAAAAAAAAALiZbL5nFIZl7cSLH5E3wK3jJeAeFc7hLHNITtLAu+o10raEs5i/UCihMHmkf8KHZxghs056pfm5BjPzlL9x7IHQ==", "subType": "06" } } }, "local_regex_det_explicit_altname": { "kms": "local", "type": "regex", "algo": "det", "method": "explicit", "identifier": "altname", "allowed": true, "value": { "$binary": { "base64": "ASzggCwAAAAAAAAAAAAAAAALiZbL5nFIZl7cSLH5E3wK3jJeAeFc7hLHNITtLAu+o10raEs5i/UCihMHmkf8KHZxghs056pfm5BjPzlL9x7IHQ==", "subType": "06" } } }, "local_dbPointer_rand_auto_id": { "kms": "local", "type": "dbPointer", "algo": "rand", "method": "auto", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "AizggCwAAAAAAAAAAAAAAAAMUdAA9uOSk1tXJVe/CG3Ps6avYTEF1eHj1wSlCHkFxqlMtTO+rIQpikpjH0MrcXvEEdAO8g5hFZ01I7DWyK5AAxTxDqVF+kOaQ2VfKs6hyuo=", "subType": "06" } } }, "local_dbPointer_rand_auto_altname": { "kms": "local", "type": "dbPointer", "algo": "rand", "method": "auto", "identifier": "altname", "allowed": true, "value": { "$binary": { "base64": "AizggCwAAAAAAAAAAAAAAAAMiNqvqLwZrPnsF235z+Obl1K9iEXdJ5GucMGpJdRG4lRvRE0Oy1vh6ztNTpYPY/tXyUFTBWlzl/lITalSEm/dT1Bnlh0iPAFrAiNySf662og=", "subType": "06" } } }, "local_dbPointer_rand_explicit_id": { "kms": "local", "type": "dbPointer", "algo": "rand", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "AizggCwAAAAAAAAAAAAAAAAM+Tn31YcKiowBTJWRYCYAEO7UARDE2/jTVGEKXCpiwEqqP3JSAS0b80zYt8dxo5mVhUo2a02ClKrB8vs+B6sU1kXrahSaVSEHZlRSGN9fWgo=", "subType": "06" } } }, "local_dbPointer_rand_explicit_altname": { "kms": "local", "type": "dbPointer", "algo": "rand", "method": "explicit", "identifier": "altname", "allowed": true, "value": { "$binary": { "base64": "AizggCwAAAAAAAAAAAAAAAAMdOZZUvpJIqG9qiOLy5x4BdftyHipPDZn/eeLEc7ir3v4jJsY3dsv6fQERo5U9lMynNGA9PJePVzq5tWsIMX0EcCQcMfGmosfkYDzN1OX99A=", "subType": "06" } } }, "local_dbPointer_det_auto_id": { "kms": "local", "type": "dbPointer", "algo": "det", "method": "auto", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "ASzggCwAAAAAAAAAAAAAAAAMQWace2C1w3yqtmo/rgz3YtIDnx1Ia/oDsoHnnMZlEy5RoK3uosi1hvNAZCSg3Sen0H7MH3XVhGGMCL4cS69uJ0ENSvh+K6fiZzAXCKUPfvM=", "subType": "06" } } }, "local_dbPointer_det_explicit_id": { "kms": "local", "type": "dbPointer", "algo": "det", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "ASzggCwAAAAAAAAAAAAAAAAMQWace2C1w3yqtmo/rgz3YtIDnx1Ia/oDsoHnnMZlEy5RoK3uosi1hvNAZCSg3Sen0H7MH3XVhGGMCL4cS69uJ0ENSvh+K6fiZzAXCKUPfvM=", "subType": "06" } } }, "local_dbPointer_det_explicit_altname": { "kms": "local", "type": "dbPointer", "algo": "det", "method": "explicit", "identifier": "altname", "allowed": true, "value": { "$binary": { "base64": "ASzggCwAAAAAAAAAAAAAAAAMQWace2C1w3yqtmo/rgz3YtIDnx1Ia/oDsoHnnMZlEy5RoK3uosi1hvNAZCSg3Sen0H7MH3XVhGGMCL4cS69uJ0ENSvh+K6fiZzAXCKUPfvM=", "subType": "06" } } }, "local_javascript_rand_auto_id": { "kms": "local", "type": "javascript", "algo": "rand", "method": "auto", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "AizggCwAAAAAAAAAAAAAAAANNL2AMKwTDyMIvxLKhBxZKx50C0tBdkLwuXmuMcrUqZeH8bsvjtttoM9LWkkileMyeTWgxblJ1b+uQ+V+4VT6fA==", "subType": "06" } } }, "local_javascript_rand_auto_altname": { "kms": "local", "type": "javascript", "algo": "rand", "method": "auto", "identifier": "altname", "allowed": true, "value": { "$binary": { "base64": "AizggCwAAAAAAAAAAAAAAAANBjBlHGw3K3TWQHpvfa1z0bKhNnVFC/lZArIexo3wjdGq3MdkGA5cuBIp87HHmOIv6o/pvQ9K74v48RQl+JH44A==", "subType": "06" } } }, "local_javascript_rand_explicit_id": { "kms": "local", "type": "javascript", "algo": "rand", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "AizggCwAAAAAAAAAAAAAAAANjvM7u3vNVyKpyI7g5kbzBpHPzXzOQToDSng5/c9yjMG+qi4TPtOyassobJOnMmDYBLyqRXCl/GsDLprbg5jxuA==", "subType": "06" } } }, "local_javascript_rand_explicit_altname": { "kms": "local", "type": "javascript", "algo": "rand", "method": "explicit", "identifier": "altname", "allowed": true, "value": { "$binary": { "base64": "AizggCwAAAAAAAAAAAAAAAANMtO7KneuVx4gSOjX4MQjKL80zJhnt+efDBylkpNsqKyxBXB60nkiredGzwaK3/4QhIfGJrC1fQpwUwu/v1L17g==", "subType": "06" } } }, "local_javascript_det_auto_id": { "kms": "local", "type": "javascript", "algo": "det", "method": "auto", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "ASzggCwAAAAAAAAAAAAAAAANmQsg9E/BzGJVNVhSNyunS/TH0332oVFdPS6gjX0Cp/JC0YhB97DLz3N4e/q8ECaz7tTdQt9JacNUgxo+YCULUA==", "subType": "06" } } }, "local_javascript_det_explicit_id": { "kms": "local", "type": "javascript", "algo": "det", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "ASzggCwAAAAAAAAAAAAAAAANmQsg9E/BzGJVNVhSNyunS/TH0332oVFdPS6gjX0Cp/JC0YhB97DLz3N4e/q8ECaz7tTdQt9JacNUgxo+YCULUA==", "subType": "06" } } }, "local_javascript_det_explicit_altname": { "kms": "local", "type": "javascript", "algo": "det", "method": "explicit", "identifier": "altname", "allowed": true, "value": { "$binary": { "base64": "ASzggCwAAAAAAAAAAAAAAAANmQsg9E/BzGJVNVhSNyunS/TH0332oVFdPS6gjX0Cp/JC0YhB97DLz3N4e/q8ECaz7tTdQt9JacNUgxo+YCULUA==", "subType": "06" } } }, "local_symbol_rand_auto_id": { "kms": "local", "type": "symbol", "algo": "rand", "method": "auto", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "AizggCwAAAAAAAAAAAAAAAAOOuO2b23mekwI8b6gWeEgRy1lLOCsNyBKvdmizK7/oOVKCvd+3kwUn9a6TxygooiVAN/Aohr1cjb8jRlMPWpkP0iO0+Tt6+vkizgFsQW4iio=", "subType": "06" } } }, "local_symbol_rand_auto_altname": { "kms": "local", "type": "symbol", "algo": "rand", "method": "auto", "identifier": "altname", "allowed": true, "value": { "$binary": { "base64": "AizggCwAAAAAAAAAAAAAAAAOhN4QPOcmGnFKGvTfhz6TQleDA02X6oWULLHTnOUJYfE3OUSyf2ULEQh1yhdKdwXMuYVgGl28pMosiwkBShrXYe5ZlMjiZCIMZWSdUMV0tXk=", "subType": "06" } } }, "local_symbol_rand_explicit_id": { "kms": "local", "type": "symbol", "algo": "rand", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "AizggCwAAAAAAAAAAAAAAAAO9aWi9RliwQHdXHoJME9VyN6XgyGd95Eclx+ZFYfLxBGAuUnPNjSfVuNZwYdyKC8JX79+mYhk7IXmcGV4z+4486sxyLk3idi4Kmpz2ESqV5g=", "subType": "06" } } }, "local_symbol_rand_explicit_altname": { "kms": "local", "type": "symbol", "algo": "rand", "method": "explicit", "identifier": "altname", "allowed": true, "value": { "$binary": { "base64": "AizggCwAAAAAAAAAAAAAAAAO/qev3DPfpkQoSW9aHOyalwfI/VYDQVN5VMINx4kw2vEqHiI1HRdZRPOz3q74TlQEy3TMNMTYdCvh5bpN/PptRZCTQbzP6ugz9dTp79w5/Ok=", "subType": "06" } } }, "local_symbol_det_auto_id": { "kms": "local", "type": "symbol", "algo": "det", "method": "auto", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "ASzggCwAAAAAAAAAAAAAAAAOsg5cs6VpZWoTOFg4ztZmpj8kSTeCArVcI1Zz2pOnmMqNv/vcKQGhKSBbfniMripr7iuiYtlgkHGsdO2FqUp6Jb8NEWm5uWqdNU21zR9SRkE=", "subType": "06" } } }, "local_symbol_det_explicit_id": { "kms": "local", "type": "symbol", "algo": "det", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "ASzggCwAAAAAAAAAAAAAAAAOsg5cs6VpZWoTOFg4ztZmpj8kSTeCArVcI1Zz2pOnmMqNv/vcKQGhKSBbfniMripr7iuiYtlgkHGsdO2FqUp6Jb8NEWm5uWqdNU21zR9SRkE=", "subType": "06" } } }, "local_symbol_det_explicit_altname": { "kms": "local", "type": "symbol", "algo": "det", "method": "explicit", "identifier": "altname", "allowed": true, "value": { "$binary": { "base64": "ASzggCwAAAAAAAAAAAAAAAAOsg5cs6VpZWoTOFg4ztZmpj8kSTeCArVcI1Zz2pOnmMqNv/vcKQGhKSBbfniMripr7iuiYtlgkHGsdO2FqUp6Jb8NEWm5uWqdNU21zR9SRkE=", "subType": "06" } } }, "local_javascriptWithScope_rand_auto_id": { "kms": "local", "type": "javascriptWithScope", "algo": "rand", "method": "auto", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "AizggCwAAAAAAAAAAAAAAAAP5gLMvLOAc6vGAvC7bGmEC4eweptAiX3A7L0iCoHps/wm0FBLkfpF6F4pCjVYiY1lTID38wliRLPyhntCj+cfvlMfKSjouNgXMIWyQ8GKZ2c=", "subType": "06" } } }, "local_javascriptWithScope_rand_auto_altname": { "kms": "local", "type": "javascriptWithScope", "algo": "rand", "method": "auto", "identifier": "altname", "allowed": true, "value": { "$binary": { "base64": "AizggCwAAAAAAAAAAAAAAAAPVsw9Opn/P5SAdJhX4MTxIcsmaG8isIN4NKPi9k1u/Vj7AVkcxYqwurAghaJpmfoAgMruvzi1hcKvd05yHd9Nk0vkvODwDgnjJB6QO+qUce8=", "subType": "06" } } }, "local_javascriptWithScope_rand_explicit_id": { "kms": "local", "type": "javascriptWithScope", "algo": "rand", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "AizggCwAAAAAAAAAAAAAAAAPLUa+nsrqiHkVdE5K1xl/ZsiZqQznG2yVXyA3b3loBylbcL2NEBp1JUeGnPZ0y5ZK4AmoL6NMH2Io313rW3V8FTArs/OOQWPRJSe6h0M3wXk=", "subType": "06" } } }, "local_javascriptWithScope_rand_explicit_altname": { "kms": "local", "type": "javascriptWithScope", "algo": "rand", "method": "explicit", "identifier": "altname", "allowed": true, "value": { "$binary": { "base64": "AizggCwAAAAAAAAAAAAAAAAPzUKaXCH0JImSlY73HVop9g9c0YssNEiA7Dy7Vji61avxvnuJJfghDchdwwaY7Vc8+0bymoanUWcErRctLzjm+1uKeMnFQokR8wFtnS3PgpQ=", "subType": "06" } } }, "local_javascriptWithScope_det_explicit_id": { "kms": "local", "type": "javascriptWithScope", "algo": "det", "method": "explicit", "identifier": "id", "allowed": false, "value": { "$code": "x=1", "$scope": {} } }, "local_javascriptWithScope_det_explicit_altname": { "kms": "local", "type": "javascriptWithScope", "algo": "det", "method": "explicit", "identifier": "altname", "allowed": false, "value": { "$code": "x=1", "$scope": {} } }, "local_int_rand_auto_id": { "kms": "local", "type": "int", "algo": "rand", "method": "auto", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "AizggCwAAAAAAAAAAAAAAAAQHXpXb3KlHA2KFTBgl0VoLCu0CUf1ae4DckkwDorbredVSqxvA5e+NvVudY5yuea6bC9F57JlbjI8NWYAUw4q0Q==", "subType": "06" } } }, "local_int_rand_auto_altname": { "kms": "local", "type": "int", "algo": "rand", "method": "auto", "identifier": "altname", "allowed": true, "value": { "$binary": { "base64": "AizggCwAAAAAAAAAAAAAAAAQSxXMF4+TKV+a3lcxXky8VepEqdg5wI/jg+C4CAUgNurq2XhgrxyqiMjkU8z07tfyoLYyX6P+dTrwj6nzvvchCw==", "subType": "06" } } }, "local_int_rand_explicit_id": { "kms": "local", "type": "int", "algo": "rand", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "AizggCwAAAAAAAAAAAAAAAAQmzteYnshCI8HBGd7UYUKvcg4xl6M8PRyi1xX/WHbjyQkAJXxczS8hO91wuqStE3tBNSmulUejz9S691ufTd6ZA==", "subType": "06" } } }, "local_int_rand_explicit_altname": { "kms": "local", "type": "int", "algo": "rand", "method": "explicit", "identifier": "altname", "allowed": true, "value": { "$binary": { "base64": "AizggCwAAAAAAAAAAAAAAAAQLCHLru//++QSoWVEyw2v6TUfCnlrPJXrpLLezWf16vK85jTfm8vJbb2X2UzX04wGzVL9tCFFsWX6Z5gHXhgSBg==", "subType": "06" } } }, "local_int_det_auto_id": { "kms": "local", "type": "int", "algo": "det", "method": "auto", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "ASzggCwAAAAAAAAAAAAAAAAQIxWjLBromNUgiOoeoZ4RUJUYIfhfOmab0sa4qYlS9bgYI41FU6BtzaOevR16O9i+uACbiHL0X6FMXKjOmiRAug==", "subType": "06" } } }, "local_int_det_explicit_id": { "kms": "local", "type": "int", "algo": "det", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "ASzggCwAAAAAAAAAAAAAAAAQIxWjLBromNUgiOoeoZ4RUJUYIfhfOmab0sa4qYlS9bgYI41FU6BtzaOevR16O9i+uACbiHL0X6FMXKjOmiRAug==", "subType": "06" } } }, "local_int_det_explicit_altname": { "kms": "local", "type": "int", "algo": "det", "method": "explicit", "identifier": "altname", "allowed": true, "value": { "$binary": { "base64": "ASzggCwAAAAAAAAAAAAAAAAQIxWjLBromNUgiOoeoZ4RUJUYIfhfOmab0sa4qYlS9bgYI41FU6BtzaOevR16O9i+uACbiHL0X6FMXKjOmiRAug==", "subType": "06" } } }, "local_timestamp_rand_auto_id": { "kms": "local", "type": "timestamp", "algo": "rand", "method": "auto", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "AizggCwAAAAAAAAAAAAAAAARntIycg0Xkd16GEa//VSJI4Rkl7dT6MpRa+D3MiTEeio5Yy8zGK0u2BtEP/9MCRQw2hJDYj5znVqwhdduM0OTiA==", "subType": "06" } } }, "local_timestamp_rand_auto_altname": { "kms": "local", "type": "timestamp", "algo": "rand", "method": "auto", "identifier": "altname", "allowed": true, "value": { "$binary": { "base64": "AizggCwAAAAAAAAAAAAAAAARWA9Ox5ejDPeWxfjbRgcGCtF/G5yrPMbBJD9ESDFc0NaVe0sdNNTisEVxsSkn7M/S4FCibKh+C8femr7xhu1iTw==", "subType": "06" } } }, "local_timestamp_rand_explicit_id": { "kms": "local", "type": "timestamp", "algo": "rand", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "AizggCwAAAAAAAAAAAAAAAARrEfOL4+4Qh7IkhHnHcBEANGfMF8n2wUDnsZ0lXEb0fACKzaN5OKaxMIQBs/3pFBw721qRfCHY+ByKeaQuABbzg==", "subType": "06" } } }, "local_timestamp_rand_explicit_altname": { "kms": "local", "type": "timestamp", "algo": "rand", "method": "explicit", "identifier": "altname", "allowed": true, "value": { "$binary": { "base64": "AizggCwAAAAAAAAAAAAAAAARW8nwmnBt+LFIAcFWvOzX8llrGcveQKFhyYUIth9d7wtpTyc9myFp8GBQCnjDpKzA6lPmbqVYeLU0L9q0h6SHGQ==", "subType": "06" } } }, "local_timestamp_det_auto_id": { "kms": "local", "type": "timestamp", "algo": "det", "method": "auto", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "ASzggCwAAAAAAAAAAAAAAAAR6uMylGytMq8QDr5Yz3w9HlW2MkGt6yIgUKcXYSaXru8eer+EkLv66/vy5rHqTfV0+8ryoi+d+PWO5U6b3Ng5Gg==", "subType": "06" } } }, "local_timestamp_det_explicit_id": { "kms": "local", "type": "timestamp", "algo": "det", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "ASzggCwAAAAAAAAAAAAAAAAR6uMylGytMq8QDr5Yz3w9HlW2MkGt6yIgUKcXYSaXru8eer+EkLv66/vy5rHqTfV0+8ryoi+d+PWO5U6b3Ng5Gg==", "subType": "06" } } }, "local_timestamp_det_explicit_altname": { "kms": "local", "type": "timestamp", "algo": "det", "method": "explicit", "identifier": "altname", "allowed": true, "value": { "$binary": { "base64": "ASzggCwAAAAAAAAAAAAAAAAR6uMylGytMq8QDr5Yz3w9HlW2MkGt6yIgUKcXYSaXru8eer+EkLv66/vy5rHqTfV0+8ryoi+d+PWO5U6b3Ng5Gg==", "subType": "06" } } }, "local_long_rand_auto_id": { "kms": "local", "type": "long", "algo": "rand", "method": "auto", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "AizggCwAAAAAAAAAAAAAAAASrinKUOpHIB7MNRmCAPWcP4CjZwfr5JaRT3G/GqY9B/6csj3+N9jmo1fYvM8uHcnmf5hzDDOamaE2FF1jDKkrHw==", "subType": "06" } } }, "local_long_rand_auto_altname": { "kms": "local", "type": "long", "algo": "rand", "method": "auto", "identifier": "altname", "allowed": true, "value": { "$binary": { "base64": "AizggCwAAAAAAAAAAAAAAAAShWMPYDkCpTC2XLYyykPJMihASLKn6HHcB2Eh7jFwQb/8D1HCQoPmOHMyXaN4AtIKm1oqEfma6FSnEPENQoledQ==", "subType": "06" } } }, "local_long_rand_explicit_id": { "kms": "local", "type": "long", "algo": "rand", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "AizggCwAAAAAAAAAAAAAAAASd2h34ZLib+GiYayrm/FIZ/weg8wF41T0PfF8NCLTJCoT7gIkdpNRz2zkkQgZMR31efNKtsM8Bs4wgZbkrXsXWg==", "subType": "06" } } }, "local_long_rand_explicit_altname": { "kms": "local", "type": "long", "algo": "rand", "method": "explicit", "identifier": "altname", "allowed": true, "value": { "$binary": { "base64": "AizggCwAAAAAAAAAAAAAAAASPAvdjz+a3FvXqDSjazaGqwZxrfXlfFB5/VjQFXQB0gpodCEaz1qaLSKfCWBg83ftrYKa/1sa44gU5NBthDfDwQ==", "subType": "06" } } }, "local_long_det_auto_id": { "kms": "local", "type": "long", "algo": "det", "method": "auto", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "ASzggCwAAAAAAAAAAAAAAAASQk372m/hW3WX82/GH+ikPv3QUwK7Hh/RBpAguiNxMdNhkgA/y2gznVNm17t6djyub7+d5zN4P5PLS/EOm2kjtw==", "subType": "06" } } }, "local_long_det_explicit_id": { "kms": "local", "type": "long", "algo": "det", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "ASzggCwAAAAAAAAAAAAAAAASQk372m/hW3WX82/GH+ikPv3QUwK7Hh/RBpAguiNxMdNhkgA/y2gznVNm17t6djyub7+d5zN4P5PLS/EOm2kjtw==", "subType": "06" } } }, "local_long_det_explicit_altname": { "kms": "local", "type": "long", "algo": "det", "method": "explicit", "identifier": "altname", "allowed": true, "value": { "$binary": { "base64": "ASzggCwAAAAAAAAAAAAAAAASQk372m/hW3WX82/GH+ikPv3QUwK7Hh/RBpAguiNxMdNhkgA/y2gznVNm17t6djyub7+d5zN4P5PLS/EOm2kjtw==", "subType": "06" } } }, "local_decimal_rand_auto_id": { "kms": "local", "type": "decimal", "algo": "rand", "method": "auto", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "AizggCwAAAAAAAAAAAAAAAATLnMMDZhnGSn5F5xHhsJXxiTGXd61Eq6fgppOlxUNVlsZNYyr5tZ3owfTTqRuD9yRg97x65WiHewBBnJJSeirCTAy9zZxWPVlJSiC0gO7rbM=", "subType": "06" } } }, "local_decimal_rand_auto_altname": { "kms": "local", "type": "decimal", "algo": "rand", "method": "auto", "identifier": "altname", "allowed": true, "value": { "$binary": { "base64": "AizggCwAAAAAAAAAAAAAAAATenMh7NKQioGjpuEojIrYKFaJhbuGxUgu2yTTbe3TndhgHryhW9GXiUqo8WTpnXqpC5E/z03ZYLWfCbe7qGdL6T7bbrTpaTaWZnnAm3XaCqY=", "subType": "06" } } }, "local_decimal_rand_explicit_id": { "kms": "local", "type": "decimal", "algo": "rand", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "AizggCwAAAAAAAAAAAAAAAAT9vqXuKRh+2HxeCMr+pQYdhYNw7xrTdU4dySWz0X6tCK7LZO5AV72utmRJxID7Bqv1ZlXAk00V92oDLyKG9kHeG5+S34QE/aLCPsAWcppfxY=", "subType": "06" } } }, "local_decimal_rand_explicit_altname": { "kms": "local", "type": "decimal", "algo": "rand", "method": "explicit", "identifier": "altname", "allowed": true, "value": { "$binary": { "base64": "AizggCwAAAAAAAAAAAAAAAATtqOCFMbOkls3LikQNXlnlkRr5gJns1+5Kvbt7P7texMa/QlXkYSHhtwESyfOcCQ2sw1T0eZ9DDuNaznpdK2KIqZBkVEC9iMoxqIqXF7Nab0=", "subType": "06" } } }, "local_decimal_det_explicit_id": { "kms": "local", "type": "decimal", "algo": "det", "method": "explicit", "identifier": "id", "allowed": false, "value": { "$numberDecimal": "1.234" } }, "local_decimal_det_explicit_altname": { "kms": "local", "type": "decimal", "algo": "det", "method": "explicit", "identifier": "altname", "allowed": false, "value": { "$numberDecimal": "1.234" } }, "local_minKey_rand_explicit_id": { "kms": "local", "type": "minKey", "algo": "rand", "method": "explicit", "identifier": "id", "allowed": false, "value": { "$minKey": 1 } }, "local_minKey_rand_explicit_altname": { "kms": "local", "type": "minKey", "algo": "rand", "method": "explicit", "identifier": "altname", "allowed": false, "value": { "$minKey": 1 } }, "local_minKey_det_explicit_id": { "kms": "local", "type": "minKey", "algo": "det", "method": "explicit", "identifier": "id", "allowed": false, "value": { "$minKey": 1 } }, "local_minKey_det_explicit_altname": { "kms": "local", "type": "minKey", "algo": "det", "method": "explicit", "identifier": "altname", "allowed": false, "value": { "$minKey": 1 } }, "local_maxKey_rand_explicit_id": { "kms": "local", "type": "maxKey", "algo": "rand", "method": "explicit", "identifier": "id", "allowed": false, "value": { "$maxKey": 1 } }, "local_maxKey_rand_explicit_altname": { "kms": "local", "type": "maxKey", "algo": "rand", "method": "explicit", "identifier": "altname", "allowed": false, "value": { "$maxKey": 1 } }, "local_maxKey_det_explicit_id": { "kms": "local", "type": "maxKey", "algo": "det", "method": "explicit", "identifier": "id", "allowed": false, "value": { "$maxKey": 1 } }, "local_maxKey_det_explicit_altname": { "kms": "local", "type": "maxKey", "algo": "det", "method": "explicit", "identifier": "altname", "allowed": false, "value": { "$maxKey": 1 } }, "payload=0,algo=rand": { "kms": "local", "type": "string", "algo": "rand", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "AizggCwAAAAAAAAAAAAAAAACcsBdT93ivCyvtkfQz9qb1A9Ll+I6hnGE0kFy3rmVG6xAvipmRJSoVq3iv7iUEDvaqmPXfjeH8h8cPYT86v3XSg==", "subType": "06" } } }, "payload=1,algo=rand": { "kms": "local", "type": "string", "algo": "rand", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "AizggCwAAAAAAAAAAAAAAAACQOzpNBEGSrANr3Wl8uYpqeIc7pjc8e2LS2FaSrb8tM9F3mR1FqGgfJtn3eD+HZf3Y3WEDGK8975a/1BufkMqIQ==", "subType": "06" } } }, "payload=2,algo=rand": { "kms": "local", "type": "string", "algo": "rand", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "AizggCwAAAAAAAAAAAAAAAACyGJEcuN1pG5oSEyxuKFwqddGHVU5Untbib7LkmtoJe9HngTofkOpeHZH/hV6Z3CFxLu6WFliJoySsFFbnFy9ag==", "subType": "06" } } }, "payload=3,algo=rand": { "kms": "local", "type": "string", "algo": "rand", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "AizggCwAAAAAAAAAAAAAAAACLbp4w6mx45lR1vvgmeRja/y8U+WnR2oH4IpfrDi4lKM+JPVnJweiN3/1wAy+sXSy0S1Yh9yxmhh9ISoTkAuVxw==", "subType": "06" } } }, "payload=4,algo=rand": { "kms": "local", "type": "string", "algo": "rand", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "AizggCwAAAAAAAAAAAAAAAACG0qMY/GPZ/2CR61cxbuizywefyMZVdeTCn5KFjqwejgxeBwX0JmGNHKKWbQIDQykRFv0q0WHUgsRmRhaotNCyQ==", "subType": "06" } } }, "payload=5,algo=rand": { "kms": "local", "type": "string", "algo": "rand", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "AizggCwAAAAAAAAAAAAAAAACJI1onNpQfZhaYWrPEzHvNaJRqUDZK2xoyonB5E473BPgp3zvn0Jmz1deL8GzS+HlkjCrx39OvHyVt3+3S0kYYw==", "subType": "06" } } }, "payload=6,algo=rand": { "kms": "local", "type": "string", "algo": "rand", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "AizggCwAAAAAAAAAAAAAAAAClyKY9tZBjl7SewSXr3MdoWRDUNgLaXDUjENpjyYvi/54EQ9a+J/LAAh1892i+mLpYxEUAmcftPyfX3VhbCgUQw==", "subType": "06" } } }, "payload=7,algo=rand": { "kms": "local", "type": "string", "algo": "rand", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "AizggCwAAAAAAAAAAAAAAAACAMbEA+kNvnVV7B//ds2/QoVot061kbazoMwB/psB5eFdLVB5qApAXEWgQEMwkNnsTUYbtSduQz6uGwdagtNBRw==", "subType": "06" } } }, "payload=8,algo=rand": { "kms": "local", "type": "string", "algo": "rand", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "AizggCwAAAAAAAAAAAAAAAACzdSK/d7Ni6D8qUgNopnEU5ia1K5llhBGk3O1Tf71t4ThnQjYW9eI/rIohWmev5CGWLHhwuvvKUtFcTAe+NMQww==", "subType": "06" } } }, "payload=9,algo=rand": { "kms": "local", "type": "string", "algo": "rand", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "AizggCwAAAAAAAAAAAAAAAACzQcEa+ktF2EZf35TtyatnSGGaIVvFhZNuo5P3VwQvoONJrK2cSad7PBDAv3xDAB+VPZAigXAGQvd051sHooOHg==", "subType": "06" } } }, "payload=10,algo=rand": { "kms": "local", "type": "string", "algo": "rand", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "AizggCwAAAAAAAAAAAAAAAACpfoDmApsR5xOD3TDhcHeD7Jco3kPFuuWjDpHtMepMOJ3S0c+ngGGhzPGZtEz2xuD/E7AQn1ryp/WAQ+WwkaJkQ==", "subType": "06" } } }, "payload=11,algo=rand": { "kms": "local", "type": "string", "algo": "rand", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "AizggCwAAAAAAAAAAAAAAAACICMRXmx3oKqYv0IpmzkSMBIGT4Li3MPBF4Lw1s5F69WvZApD58glIKB6b7koIrF5qc2Wrb1/Nw+stRv0zvQ8Y9CcFV4OHm6WoEw+XDlWXJ4=", "subType": "06" } } }, "payload=12,algo=rand": { "kms": "local", "type": "string", "algo": "rand", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "AizggCwAAAAAAAAAAAAAAAACTArUn0WUTojQC4fSvq3TwJVTsZNhWAK2WB057u2EnkUzMC0xsbU6611W6Okx6idZ7pMudXpBC34fRDrJPXOu3BxK+ZLCOWS2FqsvWq3HeTY=", "subType": "06" } } }, "payload=13,algo=rand": { "kms": "local", "type": "string", "algo": "rand", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "AizggCwAAAAAAAAAAAAAAAACU1Ojn7EM2i+5KK2Beh1gPLhryK3Y7PtaZ/v4JvstxuAV4OHOR9yROP7pwenHXxczkWXvcyMY9OCdmHO8pkQkXO21798IPkDDN/ejJUFI0Uw=", "subType": "06" } } }, "payload=14,algo=rand": { "kms": "local", "type": "string", "algo": "rand", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "AizggCwAAAAAAAAAAAAAAAAC0ZLwSliCbcr/e1uiYWk6gRuD/5qiyulQ7IUNWjhpBR6SLUfX2+yExLzps9hoOp53j9zRSKIzyleZ8yGLTLeN+Lz9BUe2ZT+sV8NiqZz3pkA=", "subType": "06" } } }, "payload=15,algo=rand": { "kms": "local", "type": "string", "algo": "rand", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "AizggCwAAAAAAAAAAAAAAAACQ9pmlQeFDr+jEhFwjL/eGVxdv70JdnkLaKdJ3/jkvCX1VPU5HmQIi+JWY3Rrw844E/6sBR6zIODn5aM0WfyP8a2zKRAWaVQZ7n+QE9hDN/8=", "subType": "06" } } }, "payload=16,algo=rand": { "kms": "local", "type": "string", "algo": "rand", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "AizggCwAAAAAAAAAAAAAAAACiOcItInDGHqvkH0I3udp5nnX32XzDeqya/3KDjgZPT5GHek1vFTZ4924JVxFqFQz+No9rOVmyxm8O2fxjTK2vsjtADzKGnMTtFYZqghYCuc=", "subType": "06" } } }, "payload=0,algo=det": { "kms": "local", "type": "string", "algo": "det", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "ASzggCwAAAAAAAAAAAAAAAACijFptWQy7a1Y0rpXEvamXWI9v9dnx0Qj84/mKUsVpc3agkQ0B04uPYeROdt2MeEeiZoEKVWV0NjBocAQCEz7dw==", "subType": "06" } } }, "payload=1,algo=det": { "kms": "local", "type": "string", "algo": "det", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "ASzggCwAAAAAAAAAAAAAAAAChR90taVWsZk+++sgibX6CnFeQQHNoB8V+n2gmDe3CIT/t+WvhMf9D+mQipbAlrUyHgGihKMHcvAZ5RZ/spaH4Q==", "subType": "06" } } }, "payload=2,algo=det": { "kms": "local", "type": "string", "algo": "det", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "ASzggCwAAAAAAAAAAAAAAAAC67wemDv1Xdu7+EMR9LMBTOxfyAqsGaxQibwamZItzplslL/Dp3t9g9vPuNzq0dWwhnfxQ9GBe8OA3dtRaifYCA==", "subType": "06" } } }, "payload=3,algo=det": { "kms": "local", "type": "string", "algo": "det", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "ASzggCwAAAAAAAAAAAAAAAACVLxch+uC7weXrbtylCo1m4HYZmh0sd9JCrlTECO2M56JK1X9a30i2BDUdhPuoTvvODv74CGXkZKdist3o0mGAQ==", "subType": "06" } } }, "payload=4,algo=det": { "kms": "local", "type": "string", "algo": "det", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "ASzggCwAAAAAAAAAAAAAAAACexfIZGkOYaCGktOUc6cgAYg7Bd/C5ZYmdb7b8+rd5BKWbthW6N6CxhDIyh/DHvkPAeIzfTYA2/9w6tsjfD/TPQ==", "subType": "06" } } }, "payload=5,algo=det": { "kms": "local", "type": "string", "algo": "det", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "ASzggCwAAAAAAAAAAAAAAAACjUH/dPW4egOvFMJJnpWK8v27MeLkbXC4GFl1j+wPqTsIEeIWkzEmcXjHLTQGE2GplHHc/zxwRwD2dXdbzvsCDw==", "subType": "06" } } }, "payload=6,algo=det": { "kms": "local", "type": "string", "algo": "det", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "ASzggCwAAAAAAAAAAAAAAAACzvS+QkGlvb05pNn+vBMml09yKmE8yM6lwccNIST5uZSsUxXf2hrxPtO7Ylc4lmBAJt/9bcM59JIeT9fpYMc75w==", "subType": "06" } } }, "payload=7,algo=det": { "kms": "local", "type": "string", "algo": "det", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "ASzggCwAAAAAAAAAAAAAAAACSf2RxHJpRuh4j8nS1dfonUtsJEwgqfWrwOsfuT/tAGXgDN0ObUpzL2K7G2vmePjP4dwycCSIL3+2j34bqBJK1Q==", "subType": "06" } } }, "payload=8,algo=det": { "kms": "local", "type": "string", "algo": "det", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "ASzggCwAAAAAAAAAAAAAAAACu96YYeLXXoYdEZYNU9UAZjSd6G4fOE1edrA6/RjZKVGWKxftmvj5g1VAOiom0XuTZUe1ihbnwhvKexeoa3Vc8Q==", "subType": "06" } } }, "payload=9,algo=det": { "kms": "local", "type": "string", "algo": "det", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "ASzggCwAAAAAAAAAAAAAAAACX+UjBKo9+N0Z+mbyqZqkQv2ETMSn6aPTONWgJtw5nWklcxKjUSSLI+8LW/6M6Xf9a7177GsqmV2f/yCRF58Xtw==", "subType": "06" } } }, "payload=10,algo=det": { "kms": "local", "type": "string", "algo": "det", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "ASzggCwAAAAAAAAAAAAAAAACL6TVscFzIJ9+Zj6LsCZ9xhaZuTZdvz1nJe4l69nKyj9hCjnyuiV6Ve4AXwQ5W1wiPfkJ0fCZS33NwiHw7QQ/vg==", "subType": "06" } } }, "payload=11,algo=det": { "kms": "local", "type": "string", "algo": "det", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "ASzggCwAAAAAAAAAAAAAAAACPLq7IcWhTVwkKmy0flN7opoQzx7tTe1eD9JIc25FC9B6KGQkdcRDglDDR7/m6+kBtTnq88y63vBgomTxA8ZxQE+3pB7zCiBhX0QznuXvP44=", "subType": "06" } } }, "payload=12,algo=det": { "kms": "local", "type": "string", "algo": "det", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "ASzggCwAAAAAAAAAAAAAAAACxv7v4pKtom5z1g9FUuyjEWAbdzJ3ytPNZlOfVr6KZnUPhIH7PfCz3/lTdYYWBTj01+SUZiC/7ruof9QDhsSiNWP7nUyHpQ/C3joI/BBjtDA=", "subType": "06" } } }, "payload=13,algo=det": { "kms": "local", "type": "string", "algo": "det", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "ASzggCwAAAAAAAAAAAAAAAACZhiElQ/MvyVMwMkZPu8pT54Ap6TlpVSEbE4nIQzzeU3XKVuspMdI5IXvvgfULXKXc+AOu6oQXZ+wAJ1tErVOsb48HF1g0wbXbBA31C5qLEM=", "subType": "06" } } }, "payload=14,algo=det": { "kms": "local", "type": "string", "algo": "det", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "ASzggCwAAAAAAAAAAAAAAAACdp8mDOeDuDLhE0LzTOT2p0CMaUsAQrGCzmiK6Ab9xvaIcPPcejUcpdO3XXAS/pPab4+TUwO5GbI5pDJ29zwaOiOz2H3OJ2m2p5BHQp9mCys=", "subType": "06" } } }, "payload=15,algo=det": { "kms": "local", "type": "string", "algo": "det", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "ASzggCwAAAAAAAAAAAAAAAACmtLohoP/gotuon2IvnGeLEfCWHRMhG9Wp4tPu/vbJJkJkbQTP35HRG9VrMV7KKrEQbOsJ2Y6UDBra4tyjn0fIkwwc/0X9i+xaP+TrwpNabE=", "subType": "06" } } }, "payload=16,algo=det": { "kms": "local", "type": "string", "algo": "det", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "ASzggCwAAAAAAAAAAAAAAAAC6s9eUtSneKWj3/A7S+bPZLj3t1WtUh7ltW80b8jCRzA+kOI26j1MEb1tt68HgcnH1IJ3YQ/+UHlV95OgwSnIxlib/HJn3U0s8mpuCWe1Auo=", "subType": "06" } } }, "azure_double_rand_auto_id": { "kms": "azure", "type": "double", "algo": "rand", "method": "auto", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "AgGVERAAAAAAAAAAAAAAAAAB0S2kOZe54q6iZqeTLndkX+kehTKtb30jTP7FS+Zx+cxhFs626OrGY+jrH41cLfroCccacyNHUZFRinfqZPNOyw==", "subType": "06" } } }, "azure_double_rand_auto_altname": { "kms": "azure", "type": "double", "algo": "rand", "method": "auto", "identifier": "altname", "allowed": true, "value": { "$binary": { "base64": "AgGVERAAAAAAAAAAAAAAAAABYViH7PLjCIdmTibW9dGCJADwXx2dRSMYxEmulPu89clAoeLDa8pwJ7YxLFQCcTGmZRfmp58dDDAzV8tyyE8QMg==", "subType": "06" } } }, "azure_double_rand_explicit_id": { "kms": "azure", "type": "double", "algo": "rand", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "AgGVERAAAAAAAAAAAAAAAAABeRahSj4pniBp0rLIEZE8MdeyiIKcYuTZiuGzGiXbFbntEPow88DFHIBSxbMGR7p/8jCpPL+GqBwFkPkafXbMzg==", "subType": "06" } } }, "azure_double_rand_explicit_altname": { "kms": "azure", "type": "double", "algo": "rand", "method": "explicit", "identifier": "altname", "allowed": true, "value": { "$binary": { "base64": "AgGVERAAAAAAAAAAAAAAAAABdaa3vKtO4cAEUjYJfOPl1KbbgeWtphfUuJd6MxR9VReNSf1jc+kONwmkPVQs2WyZ1n+TSQMGRoBp1nHRttDdTg==", "subType": "06" } } }, "azure_double_det_explicit_id": { "kms": "azure", "type": "double", "algo": "det", "method": "explicit", "identifier": "id", "allowed": false, "value": { "$numberDouble": "1.2339999999999999858" } }, "azure_double_det_explicit_altname": { "kms": "azure", "type": "double", "algo": "det", "method": "explicit", "identifier": "altname", "allowed": false, "value": { "$numberDouble": "1.2339999999999999858" } }, "azure_string_rand_auto_id": { "kms": "azure", "type": "string", "algo": "rand", "method": "auto", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "AgGVERAAAAAAAAAAAAAAAAACeoztcDg9oZ7ixHinReWQTrAumpsfyb0E1s3BGOFHgBCi1tW79CEXfqN8riFRc1YeRTlN4k5ShgHaBWBlax+XoQ==", "subType": "06" } } }, "azure_string_rand_auto_altname": { "kms": "azure", "type": "string", "algo": "rand", "method": "auto", "identifier": "altname", "allowed": true, "value": { "$binary": { "base64": "AgGVERAAAAAAAAAAAAAAAAACov9cXQvDHeKOS5Gxcxa8vdAcTsTXDYgUucGzsCyh4TnTWKGQEVk3DHndUXX569TKCjq5QsC//oWEwweCn1nZ4g==", "subType": "06" } } }, "azure_string_rand_explicit_id": { "kms": "azure", "type": "string", "algo": "rand", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "AgGVERAAAAAAAAAAAAAAAAACKU5qTdMdO0buQ/37ZRANUAAafcsoNMOTxJsDOfkqUb+/kRgM1ePlwVvk4EJiAGhJ/4SEmEOpwv05TT3PxGur2Q==", "subType": "06" } } }, "azure_string_rand_explicit_altname": { "kms": "azure", "type": "string", "algo": "rand", "method": "explicit", "identifier": "altname", "allowed": true, "value": { "$binary": { "base64": "AgGVERAAAAAAAAAAAAAAAAACX/ODKGHUyAKxoJ/c/3lEDBTc+eP/VS8OHrLhYoP96McpnFSgYi5jfUwvrFYa715fkass4N0nAHE6TzoGTYyk6Q==", "subType": "06" } } }, "azure_string_det_auto_id": { "kms": "azure", "type": "string", "algo": "det", "method": "auto", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "AQGVERAAAAAAAAAAAAAAAAACmVI7YK4JLOzutEdQ79he817Vk5EDP/3hXwOlGmERZCtp8J8HcqClhV+pyvRLGbwmlh12fbSs9nEp7mrobQm9wA==", "subType": "06" } } }, "azure_string_det_explicit_id": { "kms": "azure", "type": "string", "algo": "det", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "AQGVERAAAAAAAAAAAAAAAAACmVI7YK4JLOzutEdQ79he817Vk5EDP/3hXwOlGmERZCtp8J8HcqClhV+pyvRLGbwmlh12fbSs9nEp7mrobQm9wA==", "subType": "06" } } }, "azure_string_det_explicit_altname": { "kms": "azure", "type": "string", "algo": "det", "method": "explicit", "identifier": "altname", "allowed": true, "value": { "$binary": { "base64": "AQGVERAAAAAAAAAAAAAAAAACmVI7YK4JLOzutEdQ79he817Vk5EDP/3hXwOlGmERZCtp8J8HcqClhV+pyvRLGbwmlh12fbSs9nEp7mrobQm9wA==", "subType": "06" } } }, "azure_object_rand_auto_id": { "kms": "azure", "type": "object", "algo": "rand", "method": "auto", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "AgGVERAAAAAAAAAAAAAAAAADWkZMsfCo4dOPMH1RXC7GkZFt1RCjJf0vaLDA09ih1Jl47SOetZELQ7B1TQjRQitktzrfD43jk8Fn4J5ZYZu1qQ==", "subType": "06" } } }, "azure_object_rand_auto_altname": { "kms": "azure", "type": "object", "algo": "rand", "method": "auto", "identifier": "altname", "allowed": true, "value": { "$binary": { "base64": "AgGVERAAAAAAAAAAAAAAAAADJFMymfstltZP1oAqj4bgbCk8uLGtCd12eLqvSq0ZO+JDvls7PAovwmoWwigHunP8BBXT8sLydK+jn1sHfnhrlw==", "subType": "06" } } }, "azure_object_rand_explicit_id": { "kms": "azure", "type": "object", "algo": "rand", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "AgGVERAAAAAAAAAAAAAAAAADCen+XrLYKg7gIVubVfdbQwuJ0mFHxhSUUyyBWj4RCeLeLUYXckboPGixXWB9XdwcOnInfF9u6qvktY67GtYASQ==", "subType": "06" } } }, "azure_object_rand_explicit_altname": { "kms": "azure", "type": "object", "algo": "rand", "method": "explicit", "identifier": "altname", "allowed": true, "value": { "$binary": { "base64": "AgGVERAAAAAAAAAAAAAAAAADnUyp/7eLmxxxOdsP+mNuJABK4PQoKFWDAY7lDrH6MYa03ryASOihPZWYZWXZLrbAf7cQQhElEkKqKwY8+NXgqg==", "subType": "06" } } }, "azure_object_det_explicit_id": { "kms": "azure", "type": "object", "algo": "det", "method": "explicit", "identifier": "id", "allowed": false, "value": { "x": { "$numberInt": "1" } } }, "azure_object_det_explicit_altname": { "kms": "azure", "type": "object", "algo": "det", "method": "explicit", "identifier": "altname", "allowed": false, "value": { "x": { "$numberInt": "1" } } }, "azure_array_rand_auto_id": { "kms": "azure", "type": "array", "algo": "rand", "method": "auto", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "AgGVERAAAAAAAAAAAAAAAAAEtk14WyoatZcNPlg3y/XJNsBt6neFJeQwR06B9rMGV58oIsmeE5zMtUOBYTgzlnwyKpqI/XVAg8s1VxvsrvGCyLVPwGVyDztwtMgVSW6QM3s=", "subType": "06" } } }, "azure_array_rand_auto_altname": { "kms": "azure", "type": "array", "algo": "rand", "method": "auto", "identifier": "altname", "allowed": true, "value": { "$binary": { "base64": "AgGVERAAAAAAAAAAAAAAAAAERTO63J4Nj1BpFlqVduA2IrAiGoV4jEOH3FnFgx7ZP7da/YBmLX/bc1EqdpC8v4faHxp74iU0xAB0yW4WgySDX7rriL5cw9sMpqgLRaBxGug=", "subType": "06" } } }, "azure_array_rand_explicit_id": { "kms": "azure", "type": "array", "algo": "rand", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "AgGVERAAAAAAAAAAAAAAAAAEs09qQdNVwh+KFqKPREQkw0XFdRNHAvjYJzs5MDE9+QxvtKlmVKSK3wkxDdCrcH4r7ePV2nCy2h1IHYqaDnnt4s5dSawI2l88iTT+bBcCSrU=", "subType": "06" } } }, "azure_array_rand_explicit_altname": { "kms": "azure", "type": "array", "algo": "rand", "method": "explicit", "identifier": "altname", "allowed": true, "value": { "$binary": { "base64": "AgGVERAAAAAAAAAAAAAAAAAEaQ/YL50up4YIMJuVJSiAP06IQ+YjdKLIfkN/prbOZMiXErcD1Vq1hwGhfGdpEsLVu8E7IhJb4wakVC/2dLZoRP95az6HqRRauNNZAIQMKfY=", "subType": "06" } } }, "azure_array_det_explicit_id": { "kms": "azure", "type": "array", "algo": "det", "method": "explicit", "identifier": "id", "allowed": false, "value": [ { "$numberInt": "1" }, { "$numberInt": "2" }, { "$numberInt": "3" } ] }, "azure_array_det_explicit_altname": { "kms": "azure", "type": "array", "algo": "det", "method": "explicit", "identifier": "altname", "allowed": false, "value": [ { "$numberInt": "1" }, { "$numberInt": "2" }, { "$numberInt": "3" } ] }, "azure_binData=00_rand_auto_id": { "kms": "azure", "type": "binData=00", "algo": "rand", "method": "auto", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "AgGVERAAAAAAAAAAAAAAAAAFl/leuLAHf1p6aRKHdFyN9FM6MW2XzBemql2xQgqkwJ6YOQXW6Pu/aI1scXVOrvrSu3+wBvByjHu++1AqFgzZRQ==", "subType": "06" } } }, "azure_binData=00_rand_auto_altname": { "kms": "azure", "type": "binData=00", "algo": "rand", "method": "auto", "identifier": "altname", "allowed": true, "value": { "$binary": { "base64": "AgGVERAAAAAAAAAAAAAAAAAF4Nq/LwyufT/mx0LtFSkupNHTuyjbr4yUy1N5/37XhkpqZ1e4sWCHGNaTDEm5+cvdnbqZ/MMkBv855dc8N7vnGA==", "subType": "06" } } }, "azure_binData=00_rand_explicit_id": { "kms": "azure", "type": "binData=00", "algo": "rand", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "AgGVERAAAAAAAAAAAAAAAAAFv1Kbv54uXJ76Ih63vtmszQtzkXqDlv8LDCFO3sjzu70+tgRXOhLm3J8uZpwoiNkgM6oNLn0en7tnEekYB9++CA==", "subType": "06" } } }, "azure_binData=00_rand_explicit_altname": { "kms": "azure", "type": "binData=00", "algo": "rand", "method": "explicit", "identifier": "altname", "allowed": true, "value": { "$binary": { "base64": "AgGVERAAAAAAAAAAAAAAAAAFgcYC1n7cGGXpv0qf1Kb8t9y/6kbhscGt2QJkQpAiqadFPPYDU/wwaKdDz94NpAHMZizUbhf9tvZ3UXl1bozhDA==", "subType": "06" } } }, "azure_binData=00_det_auto_id": { "kms": "azure", "type": "binData=00", "algo": "det", "method": "auto", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "AQGVERAAAAAAAAAAAAAAAAAFvswfP3+jgia6rAyrypvbso3Xm4d7MEgJRUCWFYzA+9ov++vmeirgoTp/rFavTNOPb+61fvl1WKbVwrgODusaMg==", "subType": "06" } } }, "azure_binData=00_det_explicit_id": { "kms": "azure", "type": "binData=00", "algo": "det", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "AQGVERAAAAAAAAAAAAAAAAAFvswfP3+jgia6rAyrypvbso3Xm4d7MEgJRUCWFYzA+9ov++vmeirgoTp/rFavTNOPb+61fvl1WKbVwrgODusaMg==", "subType": "06" } } }, "azure_binData=00_det_explicit_altname": { "kms": "azure", "type": "binData=00", "algo": "det", "method": "explicit", "identifier": "altname", "allowed": true, "value": { "$binary": { "base64": "AQGVERAAAAAAAAAAAAAAAAAFvswfP3+jgia6rAyrypvbso3Xm4d7MEgJRUCWFYzA+9ov++vmeirgoTp/rFavTNOPb+61fvl1WKbVwrgODusaMg==", "subType": "06" } } }, "azure_binData=04_rand_auto_id": { "kms": "azure", "type": "binData=04", "algo": "rand", "method": "auto", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "AgGVERAAAAAAAAAAAAAAAAAFMzMC3BLn/zWE9dxpcD8G0h4aifSY0zSHS9xTVJXgq21s2WU++Ov2UvHatVozmtZltsUN9JvSWqOBQRkFsrXvI7bc4lYfOoOmfpTHFcRDA/c=", "subType": "06" } } }, "azure_binData=04_rand_auto_altname": { "kms": "azure", "type": "binData=04", "algo": "rand", "method": "auto", "identifier": "altname", "allowed": true, "value": { "$binary": { "base64": "AgGVERAAAAAAAAAAAAAAAAAFDlBN5hUTcjamOg/sgyeG0S52kphsjUgvlpuqHYz6VVdLtZ69cGHOVqqyml3x2rVqWUZJjd4ZodOhlwWq9p+i5IYNot2QaBvi8NZSaiThTc0=", "subType": "06" } } }, "azure_binData=04_rand_explicit_id": { "kms": "azure", "type": "binData=04", "algo": "rand", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "AgGVERAAAAAAAAAAAAAAAAAFjvS2ozJuAL3rCvyBpraVtgL91OMdiskmgYnyfKlzd8EhYLd1cL4yxnTUjRXx+W+p8uN0/QZo+mynhcWnwcq83raY+I1HftSTx+S6rZ0qyDM=", "subType": "06" } } }, "azure_binData=04_rand_explicit_altname": { "kms": "azure", "type": "binData=04", "algo": "rand", "method": "explicit", "identifier": "altname", "allowed": true, "value": { "$binary": { "base64": "AgGVERAAAAAAAAAAAAAAAAAFqUMd/I0yOdy5W4THvFc6yrgSzB6arkRs/06b0M9Ii+QtAY6vbz+/aJ0Iy3Jm8TahC1wOZVmTj5luQpr+PHZMCEAFadv+0K/Nsx6xVhAh9gg=", "subType": "06" } } }, "azure_binData=04_det_auto_id": { "kms": "azure", "type": "binData=04", "algo": "det", "method": "auto", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "AQGVERAAAAAAAAAAAAAAAAAFmN+KMrERGmfmue8/hG4D+ZcGzxC2HntdYBLjEolzvS9FV5JH/adxyUAnMpyL8FNznARL51rbv/G1nXPn9mPabsQ4BtWEAQbHx9TiXd+xbB0=", "subType": "06" } } }, "azure_binData=04_det_explicit_id": { "kms": "azure", "type": "binData=04", "algo": "det", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "AQGVERAAAAAAAAAAAAAAAAAFmN+KMrERGmfmue8/hG4D+ZcGzxC2HntdYBLjEolzvS9FV5JH/adxyUAnMpyL8FNznARL51rbv/G1nXPn9mPabsQ4BtWEAQbHx9TiXd+xbB0=", "subType": "06" } } }, "azure_binData=04_det_explicit_altname": { "kms": "azure", "type": "binData=04", "algo": "det", "method": "explicit", "identifier": "altname", "allowed": true, "value": { "$binary": { "base64": "AQGVERAAAAAAAAAAAAAAAAAFmN+KMrERGmfmue8/hG4D+ZcGzxC2HntdYBLjEolzvS9FV5JH/adxyUAnMpyL8FNznARL51rbv/G1nXPn9mPabsQ4BtWEAQbHx9TiXd+xbB0=", "subType": "06" } } }, "azure_undefined_rand_explicit_id": { "kms": "azure", "type": "undefined", "algo": "rand", "method": "explicit", "identifier": "id", "allowed": false, "value": { "$undefined": true } }, "azure_undefined_rand_explicit_altname": { "kms": "azure", "type": "undefined", "algo": "rand", "method": "explicit", "identifier": "altname", "allowed": false, "value": { "$undefined": true } }, "azure_undefined_det_explicit_id": { "kms": "azure", "type": "undefined", "algo": "det", "method": "explicit", "identifier": "id", "allowed": false, "value": { "$undefined": true } }, "azure_undefined_det_explicit_altname": { "kms": "azure", "type": "undefined", "algo": "det", "method": "explicit", "identifier": "altname", "allowed": false, "value": { "$undefined": true } }, "azure_objectId_rand_auto_id": { "kms": "azure", "type": "objectId", "algo": "rand", "method": "auto", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "AgGVERAAAAAAAAAAAAAAAAAH3sYVJpCKi310YxndMwm5ltEbbiRO1RwZxxeEkzI8tptbNXC8t7RkrT8VSJZ43wbGYCiqH5RZy9v8pYwtUm4STw==", "subType": "06" } } }, "azure_objectId_rand_auto_altname": { "kms": "azure", "type": "objectId", "algo": "rand", "method": "auto", "identifier": "altname", "allowed": true, "value": { "$binary": { "base64": "AgGVERAAAAAAAAAAAAAAAAAHD7agzVEc0JwesHHhkpGYIDAHQ+3Hc691kqic6YmVvK2N45fD5aRKftaZNs5OxSj3tNHSo7lQ+DVtPj8uSSpsVg==", "subType": "06" } } }, "azure_objectId_rand_explicit_id": { "kms": "azure", "type": "objectId", "algo": "rand", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "AgGVERAAAAAAAAAAAAAAAAAHEgKgy2mpMLpfeEWqbvQOaRZAy+cEGXGon3e53/JoH6dZneEyyt4ZrcrK6uRqyUPWX0q104JbCYxfbtHtdzWgPQ==", "subType": "06" } } }, "azure_objectId_rand_explicit_altname": { "kms": "azure", "type": "objectId", "algo": "rand", "method": "explicit", "identifier": "altname", "allowed": true, "value": { "$binary": { "base64": "AgGVERAAAAAAAAAAAAAAAAAHqSv6Nruw3TIi7y0FPRjSfnJmWSdv5XMhAtnHNkT8MVuHeM32ayo0yc8dTA1wlkRtAI5JrGxTfERCXYuCojvvXg==", "subType": "06" } } }, "azure_objectId_det_auto_id": { "kms": "azure", "type": "objectId", "algo": "det", "method": "auto", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "AQGVERAAAAAAAAAAAAAAAAAHcPRjIOyLDUJCDcdWkUySKCFS2AFkIa1OQyQAfC3Zh5HwJ1O7j2o+iYKRerhbni8lBiZH7EUMm1JcxM99lLC5jQ==", "subType": "06" } } }, "azure_objectId_det_explicit_id": { "kms": "azure", "type": "objectId", "algo": "det", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "AQGVERAAAAAAAAAAAAAAAAAHcPRjIOyLDUJCDcdWkUySKCFS2AFkIa1OQyQAfC3Zh5HwJ1O7j2o+iYKRerhbni8lBiZH7EUMm1JcxM99lLC5jQ==", "subType": "06" } } }, "azure_objectId_det_explicit_altname": { "kms": "azure", "type": "objectId", "algo": "det", "method": "explicit", "identifier": "altname", "allowed": true, "value": { "$binary": { "base64": "AQGVERAAAAAAAAAAAAAAAAAHcPRjIOyLDUJCDcdWkUySKCFS2AFkIa1OQyQAfC3Zh5HwJ1O7j2o+iYKRerhbni8lBiZH7EUMm1JcxM99lLC5jQ==", "subType": "06" } } }, "azure_bool_rand_auto_id": { "kms": "azure", "type": "bool", "algo": "rand", "method": "auto", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "AgGVERAAAAAAAAAAAAAAAAAIYVWPvzSmiCs9LwRlv/AoQWhaS5mzoKX4W26M5eg/gPjOZbEVYOV80pWMxCcZWRAyV/NDWDUmKtRQDMU9b8lCJw==", "subType": "06" } } }, "azure_bool_rand_auto_altname": { "kms": "azure", "type": "bool", "algo": "rand", "method": "auto", "identifier": "altname", "allowed": true, "value": { "$binary": { "base64": "AgGVERAAAAAAAAAAAAAAAAAIsAB01Ugqtw4T9SkuJBQN1y/ewpRAyz0vjFPdKI+jmPMmaXpMlXDJU8ZbTKm/nh6sjJCFcY5oZJ83ylbp2gHc6w==", "subType": "06" } } }, "azure_bool_rand_explicit_id": { "kms": "azure", "type": "bool", "algo": "rand", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "AgGVERAAAAAAAAAAAAAAAAAIr8/qFd564X1mqHEhB0y7bzGFdrHuw+Gk45nXla3VvGHzeIJy6j2Wdl0uziWslMmBvNp8WweW+jQ6E2Fu7SiojQ==", "subType": "06" } } }, "azure_bool_rand_explicit_altname": { "kms": "azure", "type": "bool", "algo": "rand", "method": "explicit", "identifier": "altname", "allowed": true, "value": { "$binary": { "base64": "AgGVERAAAAAAAAAAAAAAAAAIWsca5FAnS2zhHnmKmexvvXMTgsZZ7uAFHnjQassUcay6mvIWH4hOnGiRxt5Zm0wO4S6cZq+PZrmEH5/n9rJcJQ==", "subType": "06" } } }, "azure_bool_det_explicit_id": { "kms": "azure", "type": "bool", "algo": "det", "method": "explicit", "identifier": "id", "allowed": false, "value": true }, "azure_bool_det_explicit_altname": { "kms": "azure", "type": "bool", "algo": "det", "method": "explicit", "identifier": "altname", "allowed": false, "value": true }, "azure_date_rand_auto_id": { "kms": "azure", "type": "date", "algo": "rand", "method": "auto", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "AgGVERAAAAAAAAAAAAAAAAAJwKo7XW5daIFlwY1mDAnJdHlcUgF+74oViL28hQGhde63pkPyyS6lPkYrc1gcCK5DL7PwsSX4Vb9SsNAG9860xw==", "subType": "06" } } }, "azure_date_rand_auto_altname": { "kms": "azure", "type": "date", "algo": "rand", "method": "auto", "identifier": "altname", "allowed": true, "value": { "$binary": { "base64": "AgGVERAAAAAAAAAAAAAAAAAJYZdWIqvqTztGKJkSASMEOjyrUFKnYql8fMIEzfEZWx2BYsIkxxOUUUCASg/Jsn09fTLVQ7yLD+LwycuI2uaXsw==", "subType": "06" } } }, "azure_date_rand_explicit_id": { "kms": "azure", "type": "date", "algo": "rand", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "AgGVERAAAAAAAAAAAAAAAAAJuWzKqi3KV8GbGGnT7i9N4BACUuNjt5AgKsjWIfrWRXK1+jRQFq0bYlVWaliT9CNIygL2aTF0H4eHl55PAI84MQ==", "subType": "06" } } }, "azure_date_rand_explicit_altname": { "kms": "azure", "type": "date", "algo": "rand", "method": "explicit", "identifier": "altname", "allowed": true, "value": { "$binary": { "base64": "AgGVERAAAAAAAAAAAAAAAAAJ5JTtTuP4zTnEbaVlS/W59SrZ08LOC4ZIl+h+H4RnfHUfBXDwUou+APolVaYko+VZMKecrikdPeewgzWaqazJ1g==", "subType": "06" } } }, "azure_date_det_auto_id": { "kms": "azure", "type": "date", "algo": "det", "method": "auto", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "AQGVERAAAAAAAAAAAAAAAAAJCREIp/SPolAZcVU1iOmaJaN2tFId5HhrjNmhp6xhA1AIPLnN+U7TAqesxFN7iebR9fXI5fZxYNgyWqQC1rqUJw==", "subType": "06" } } }, "azure_date_det_explicit_id": { "kms": "azure", "type": "date", "algo": "det", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "AQGVERAAAAAAAAAAAAAAAAAJCREIp/SPolAZcVU1iOmaJaN2tFId5HhrjNmhp6xhA1AIPLnN+U7TAqesxFN7iebR9fXI5fZxYNgyWqQC1rqUJw==", "subType": "06" } } }, "azure_date_det_explicit_altname": { "kms": "azure", "type": "date", "algo": "det", "method": "explicit", "identifier": "altname", "allowed": true, "value": { "$binary": { "base64": "AQGVERAAAAAAAAAAAAAAAAAJCREIp/SPolAZcVU1iOmaJaN2tFId5HhrjNmhp6xhA1AIPLnN+U7TAqesxFN7iebR9fXI5fZxYNgyWqQC1rqUJw==", "subType": "06" } } }, "azure_null_rand_explicit_id": { "kms": "azure", "type": "null", "algo": "rand", "method": "explicit", "identifier": "id", "allowed": false, "value": null }, "azure_null_rand_explicit_altname": { "kms": "azure", "type": "null", "algo": "rand", "method": "explicit", "identifier": "altname", "allowed": false, "value": null }, "azure_null_det_explicit_id": { "kms": "azure", "type": "null", "algo": "det", "method": "explicit", "identifier": "id", "allowed": false, "value": null }, "azure_null_det_explicit_altname": { "kms": "azure", "type": "null", "algo": "det", "method": "explicit", "identifier": "altname", "allowed": false, "value": null }, "azure_regex_rand_auto_id": { "kms": "azure", "type": "regex", "algo": "rand", "method": "auto", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "AgGVERAAAAAAAAAAAAAAAAALsMm3W2ogEiI6m0l8dS5Xhqnw+vMBvN1EesOTqAZOk4tQleX6fWARwUUnjFxbuejU7ISb50fc/Ul+ntL9z/2nHQ==", "subType": "06" } } }, "azure_regex_rand_auto_altname": { "kms": "azure", "type": "regex", "algo": "rand", "method": "auto", "identifier": "altname", "allowed": true, "value": { "$binary": { "base64": "AgGVERAAAAAAAAAAAAAAAAALITQNQI0hfCeMTxH0Hce1Cf5tinQG+Bq8EolUACvxUUQcDqIXfFXn19tV/Qyj4lIdnnwh/18hiswgEpJRK7uLGw==", "subType": "06" } } }, "azure_regex_rand_explicit_id": { "kms": "azure", "type": "regex", "algo": "rand", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "AgGVERAAAAAAAAAAAAAAAAALw/1QI/bKeiGUrrtC+yXOTvxZ2mJjSelPPGOm1mge0ws8DsX0DPHmo6MjhnRO4u0c/LWiE3hwHG2rYjAFlFXZ5A==", "subType": "06" } } }, "azure_regex_rand_explicit_altname": { "kms": "azure", "type": "regex", "algo": "rand", "method": "explicit", "identifier": "altname", "allowed": true, "value": { "$binary": { "base64": "AgGVERAAAAAAAAAAAAAAAAAL6Sl58UfFCHCZzWIB4r19/ZjeSRAoWeTFCFedKiwyR8/xnL+8jzXK/9+vTIspP6j35lFapr+f4iBNB9WjdpYNKA==", "subType": "06" } } }, "azure_regex_det_auto_id": { "kms": "azure", "type": "regex", "algo": "det", "method": "auto", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "AQGVERAAAAAAAAAAAAAAAAALxshM91Tsql/8kPe3dC16oP36XSUIN6godiRVIJLJ+NAwYtEkThthQsln7CrkIxIx6npN6A/hw1CBJERS/cqWhw==", "subType": "06" } } }, "azure_regex_det_explicit_id": { "kms": "azure", "type": "regex", "algo": "det", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "AQGVERAAAAAAAAAAAAAAAAALxshM91Tsql/8kPe3dC16oP36XSUIN6godiRVIJLJ+NAwYtEkThthQsln7CrkIxIx6npN6A/hw1CBJERS/cqWhw==", "subType": "06" } } }, "azure_regex_det_explicit_altname": { "kms": "azure", "type": "regex", "algo": "det", "method": "explicit", "identifier": "altname", "allowed": true, "value": { "$binary": { "base64": "AQGVERAAAAAAAAAAAAAAAAALxshM91Tsql/8kPe3dC16oP36XSUIN6godiRVIJLJ+NAwYtEkThthQsln7CrkIxIx6npN6A/hw1CBJERS/cqWhw==", "subType": "06" } } }, "azure_dbPointer_rand_auto_id": { "kms": "azure", "type": "dbPointer", "algo": "rand", "method": "auto", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "AgGVERAAAAAAAAAAAAAAAAAMaAd1v/XCYM2Kzi/f4utR6aHOFORmzZ17EepEjkn5IeKshktUpPWjI/dBwSunn5Qxx2zI3nm06c3SDvp6tw8qb7u4qXjLQYhlsQ0bHvvm+vE=", "subType": "06" } } }, "azure_dbPointer_rand_auto_altname": { "kms": "azure", "type": "dbPointer", "algo": "rand", "method": "auto", "identifier": "altname", "allowed": true, "value": { "$binary": { "base64": "AgGVERAAAAAAAAAAAAAAAAAM6VNjkN9bMIzfC7AX0ZhOEXPpyPE0nzYq3c5TNHrgeGWdZDR9GVdbO9t55zQrQJJ2Mmevh8c0WaAUV+YODv7ty6TDBsPbaKWWqMzu/v9RXHo=", "subType": "06" } } }, "azure_dbPointer_rand_explicit_id": { "kms": "azure", "type": "dbPointer", "algo": "rand", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "AgGVERAAAAAAAAAAAAAAAAAM66tywuMhwdyUjxfl7EOdKHNCLeIPnct3PgKrAKlOQFjiNQUIA2ShVy0qYpJcvvFsuQ5e8Bjr0IqeBc8mC7n4euRSM1UXpLqI5XHgXMMaYpI=", "subType": "06" } } }, "azure_dbPointer_rand_explicit_altname": { "kms": "azure", "type": "dbPointer", "algo": "rand", "method": "explicit", "identifier": "altname", "allowed": true, "value": { "$binary": { "base64": "AgGVERAAAAAAAAAAAAAAAAAMtPQEbZ4gWoSYjVZLd5X6j0XxutWY1Ecrys2ErKRgZaxP0uGe8uw0cnr2Z5PYylaYmsSicLwD1PwWY42PKmaGBDraHmdfqDOPvrNxhBrfU/E=", "subType": "06" } } }, "azure_dbPointer_det_auto_id": { "kms": "azure", "type": "dbPointer", "algo": "det", "method": "auto", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "AQGVERAAAAAAAAAAAAAAAAAMxUcVqq6RpAUCv08qGkmjuwVAIgLeYyh7xZnMeCYVGmhJKIP1Zdt1SvRGRV0jzwCQmXgxNd04adRwJnG/PRQIsL9aH3ilJgEnUbOo1nqR7yw=", "subType": "06" } } }, "azure_dbPointer_det_explicit_id": { "kms": "azure", "type": "dbPointer", "algo": "det", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "AQGVERAAAAAAAAAAAAAAAAAMxUcVqq6RpAUCv08qGkmjuwVAIgLeYyh7xZnMeCYVGmhJKIP1Zdt1SvRGRV0jzwCQmXgxNd04adRwJnG/PRQIsL9aH3ilJgEnUbOo1nqR7yw=", "subType": "06" } } }, "azure_dbPointer_det_explicit_altname": { "kms": "azure", "type": "dbPointer", "algo": "det", "method": "explicit", "identifier": "altname", "allowed": true, "value": { "$binary": { "base64": "AQGVERAAAAAAAAAAAAAAAAAMxUcVqq6RpAUCv08qGkmjuwVAIgLeYyh7xZnMeCYVGmhJKIP1Zdt1SvRGRV0jzwCQmXgxNd04adRwJnG/PRQIsL9aH3ilJgEnUbOo1nqR7yw=", "subType": "06" } } }, "azure_javascript_rand_auto_id": { "kms": "azure", "type": "javascript", "algo": "rand", "method": "auto", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "AgGVERAAAAAAAAAAAAAAAAANWXPb5z3a0S7F26vkmBF3fV+oXYUj15OEtnSlXlUrc+gbhbPDxSvCPnTBEy5sNu4ndkvEZZxYgZInkF2q4rhlfQ==", "subType": "06" } } }, "azure_javascript_rand_auto_altname": { "kms": "azure", "type": "javascript", "algo": "rand", "method": "auto", "identifier": "altname", "allowed": true, "value": { "$binary": { "base64": "AgGVERAAAAAAAAAAAAAAAAANN4mcwLz/J4eOUknhVsy6kdF1ThDP8cx6dNpOwJWAiyPHEsn+i6JmMTlfQMBrUp9HB/u3R+jLO5yz4XgLUKE8Tw==", "subType": "06" } } }, "azure_javascript_rand_explicit_id": { "kms": "azure", "type": "javascript", "algo": "rand", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "AgGVERAAAAAAAAAAAAAAAAANJ+t5Z8hSQaoNzszzkWndAo4A0avDf9bKFa7euznz8ZYInnl9RUVqWMyxjSuIotAvTyYSJzxh+w2hKCgVf+MjEA==", "subType": "06" } } }, "azure_javascript_rand_explicit_altname": { "kms": "azure", "type": "javascript", "algo": "rand", "method": "explicit", "identifier": "altname", "allowed": true, "value": { "$binary": { "base64": "AgGVERAAAAAAAAAAAAAAAAANRLOQFpmkEg/KdWMmaurkNtUhy45rgtoipc9kQz6olgDWiMim81XC0AW5cOvjbHXL3w7Du28Kwdsp4j0PTTXHUQ==", "subType": "06" } } }, "azure_javascript_det_auto_id": { "kms": "azure", "type": "javascript", "algo": "det", "method": "auto", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "AQGVERAAAAAAAAAAAAAAAAANUrNUS/7/dmKVWBd+2JKGEn1hxbFSyu3p5sDNatukG2m16t4WwxzmYAg8PuQbAxekprs7iaLA+7D2Kn3ZuMSQOw==", "subType": "06" } } }, "azure_javascript_det_explicit_id": { "kms": "azure", "type": "javascript", "algo": "det", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "AQGVERAAAAAAAAAAAAAAAAANUrNUS/7/dmKVWBd+2JKGEn1hxbFSyu3p5sDNatukG2m16t4WwxzmYAg8PuQbAxekprs7iaLA+7D2Kn3ZuMSQOw==", "subType": "06" } } }, "azure_javascript_det_explicit_altname": { "kms": "azure", "type": "javascript", "algo": "det", "method": "explicit", "identifier": "altname", "allowed": true, "value": { "$binary": { "base64": "AQGVERAAAAAAAAAAAAAAAAANUrNUS/7/dmKVWBd+2JKGEn1hxbFSyu3p5sDNatukG2m16t4WwxzmYAg8PuQbAxekprs7iaLA+7D2Kn3ZuMSQOw==", "subType": "06" } } }, "azure_symbol_rand_auto_id": { "kms": "azure", "type": "symbol", "algo": "rand", "method": "auto", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "AgGVERAAAAAAAAAAAAAAAAAORMcgtQSU+/2Qlq57neRrVuAFSeSwkqdo+z1fh6IKjyEzhCy+u5bTzSzTopyKJQTCUZA2mSpRezWkM87oiGfhMFkBRVreMcE62eH+BLlgUaM=", "subType": "06" } } }, "azure_symbol_rand_auto_altname": { "kms": "azure", "type": "symbol", "algo": "rand", "method": "auto", "identifier": "altname", "allowed": true, "value": { "$binary": { "base64": "AgGVERAAAAAAAAAAAAAAAAAOIKlAw/A3nwHn0tO2cYtJx0azB8MGmXtt+bRptzn8yHlUSpMpYaiU0ssBBiLkmMLAITYebLqDk3NHESyP7PvbSfX1E2XVn2Nf694ZqPWMec8=", "subType": "06" } } }, "azure_symbol_rand_explicit_id": { "kms": "azure", "type": "symbol", "algo": "rand", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "AgGVERAAAAAAAAAAAAAAAAAO8SXW76AEr/6D6zyP1RYwmwdVM2AINaXZn3Ipy+fynWTUV6XIPIRR7xMTttNo2zlh7fgXDZ28PmjooGlQzn0q0JVQmXPCIPM3aqAmMcgyuqg=", "subType": "06" } } }, "azure_symbol_rand_explicit_altname": { "kms": "azure", "type": "symbol", "algo": "rand", "method": "explicit", "identifier": "altname", "allowed": true, "value": { "$binary": { "base64": "AgGVERAAAAAAAAAAAAAAAAAOtoJWm2Ucre0foHIiOutsX1WIyub7t3Lby3/F8zRXn+l6ixlTjAPgWFwpRnYg96Lt2ACDDQ9CO51ejr9qk0b8LDBwG3qU5Cuibsp7vo1VsdI=", "subType": "06" } } }, "azure_symbol_det_auto_id": { "kms": "azure", "type": "symbol", "algo": "det", "method": "auto", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "AQGVERAAAAAAAAAAAAAAAAAOvp/FMMmWVMkiuN51uFMFBiRQAcc9jftlNsHsLoNtohZaGni26kgX94b+/EI8pdWF5xA/73JlGlij0Rt+vC9s/zTDItRpn0bJL54WPphDcmA=", "subType": "06" } } }, "azure_symbol_det_explicit_id": { "kms": "azure", "type": "symbol", "algo": "det", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "AQGVERAAAAAAAAAAAAAAAAAOvp/FMMmWVMkiuN51uFMFBiRQAcc9jftlNsHsLoNtohZaGni26kgX94b+/EI8pdWF5xA/73JlGlij0Rt+vC9s/zTDItRpn0bJL54WPphDcmA=", "subType": "06" } } }, "azure_symbol_det_explicit_altname": { "kms": "azure", "type": "symbol", "algo": "det", "method": "explicit", "identifier": "altname", "allowed": true, "value": { "$binary": { "base64": "AQGVERAAAAAAAAAAAAAAAAAOvp/FMMmWVMkiuN51uFMFBiRQAcc9jftlNsHsLoNtohZaGni26kgX94b+/EI8pdWF5xA/73JlGlij0Rt+vC9s/zTDItRpn0bJL54WPphDcmA=", "subType": "06" } } }, "azure_javascriptWithScope_rand_auto_id": { "kms": "azure", "type": "javascriptWithScope", "algo": "rand", "method": "auto", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "AgGVERAAAAAAAAAAAAAAAAAPCw9NnvJyuTYIgZxr1w1UiG85PGZ4rO62DWWDF98HwVM/Y6u7hNdNjkaWjYFsPMl38ioHw/pS8GFR62QmH2RAw/BV0wI7pNy2evANr3i3gKg=", "subType": "06" } } }, "azure_javascriptWithScope_rand_auto_altname": { "kms": "azure", "type": "javascriptWithScope", "algo": "rand", "method": "auto", "identifier": "altname", "allowed": true, "value": { "$binary": { "base64": "AgGVERAAAAAAAAAAAAAAAAAPXQzqnQ2UWkIYof8/OfadNMa7iVKAbOaiu7YGm8iVrx+W6uxKLPFugVqHtQ29hYXXf33xr8rqGNxDlAe7/x1OeYEif71f7LUkmKF9WxJV9Ko=", "subType": "06" } } }, "azure_javascriptWithScope_rand_explicit_id": { "kms": "azure", "type": "javascriptWithScope", "algo": "rand", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "AgGVERAAAAAAAAAAAAAAAAAP0nxlppgPyjLx0eBempbOlL21G6KbABSrE6+YuNDcsjJjxCQuLR9+aoAwa+yCDEC7GZ1E3oP489edKUuNpE4Ts26jy4aRegu4DmyECUeBwAg=", "subType": "06" } } }, "azure_javascriptWithScope_rand_explicit_altname": { "kms": "azure", "type": "javascriptWithScope", "algo": "rand", "method": "explicit", "identifier": "altname", "allowed": true, "value": { "$binary": { "base64": "AgGVERAAAAAAAAAAAAAAAAAPO89afu9Sb+cK9wwM1cO1DPjvu5UNyObjjTScy1hy9PzllJGfj7b84f0Ah74jPYsMPwI0Eslu/IYF3+5jmquq5Qp/VUQESlxqRqRK0xIeMfs=", "subType": "06" } } }, "azure_javascriptWithScope_det_explicit_id": { "kms": "azure", "type": "javascriptWithScope", "algo": "det", "method": "explicit", "identifier": "id", "allowed": false, "value": { "$code": "x=1", "$scope": {} } }, "azure_javascriptWithScope_det_explicit_altname": { "kms": "azure", "type": "javascriptWithScope", "algo": "det", "method": "explicit", "identifier": "altname", "allowed": false, "value": { "$code": "x=1", "$scope": {} } }, "azure_int_rand_auto_id": { "kms": "azure", "type": "int", "algo": "rand", "method": "auto", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "AgGVERAAAAAAAAAAAAAAAAAQUyy4uWmWdzypsK81q9egREg4s80X3L2hzxJzC+fL08Xzy1z9grpPPCfJrluUVKMMGmmZR8gJPJ70igN3unJbzg==", "subType": "06" } } }, "azure_int_rand_auto_altname": { "kms": "azure", "type": "int", "algo": "rand", "method": "auto", "identifier": "altname", "allowed": true, "value": { "$binary": { "base64": "AgGVERAAAAAAAAAAAAAAAAAQr4gyoHKpGsSJo8CMsYSJk/KilFMJhsDCmxrha7yfNW1uR5sjyZj4B4s6uTXGw76x7aR/AvecDlY3QFJb8L1mjg==", "subType": "06" } } }, "azure_int_rand_explicit_id": { "kms": "azure", "type": "int", "algo": "rand", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "AgGVERAAAAAAAAAAAAAAAAAQ0zgXYPV1MuEFksmDpVDoWkoZQelm3+rYrMiT64KYywO//75799W8TbR3a7O6Q/ErjKQOin2OCp8EWwZqTDdz5w==", "subType": "06" } } }, "azure_int_rand_explicit_altname": { "kms": "azure", "type": "int", "algo": "rand", "method": "explicit", "identifier": "altname", "allowed": true, "value": { "$binary": { "base64": "AgGVERAAAAAAAAAAAAAAAAAQG+qz00yizREbP3tla1elMiwf8TKLbUU2XWUP+E0vey/wvbjTTIzqwUlz/b9St77CHJhavypP3hMrngXR9GapbQ==", "subType": "06" } } }, "azure_int_det_auto_id": { "kms": "azure", "type": "int", "algo": "det", "method": "auto", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "AQGVERAAAAAAAAAAAAAAAAAQCkJH+CataLqp/xBjO77QBprC2xPV+rE+goSZ3C6aqwXIeTYHTOqEbeaFb5iZcqYH5nWvNvnfbZSIMyvSfrPjhw==", "subType": "06" } } }, "azure_int_det_explicit_id": { "kms": "azure", "type": "int", "algo": "det", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "AQGVERAAAAAAAAAAAAAAAAAQCkJH+CataLqp/xBjO77QBprC2xPV+rE+goSZ3C6aqwXIeTYHTOqEbeaFb5iZcqYH5nWvNvnfbZSIMyvSfrPjhw==", "subType": "06" } } }, "azure_int_det_explicit_altname": { "kms": "azure", "type": "int", "algo": "det", "method": "explicit", "identifier": "altname", "allowed": true, "value": { "$binary": { "base64": "AQGVERAAAAAAAAAAAAAAAAAQCkJH+CataLqp/xBjO77QBprC2xPV+rE+goSZ3C6aqwXIeTYHTOqEbeaFb5iZcqYH5nWvNvnfbZSIMyvSfrPjhw==", "subType": "06" } } }, "azure_timestamp_rand_auto_id": { "kms": "azure", "type": "timestamp", "algo": "rand", "method": "auto", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "AgGVERAAAAAAAAAAAAAAAAARwcXYtx+A7g/zGkjGdkyVxZGCO9Nzj3D70NIpl2TeH2j9qYGP4DenwL1xSgrL2Ez+X58d2BvNhKrjA9y2w1Z8kA==", "subType": "06" } } }, "azure_timestamp_rand_auto_altname": { "kms": "azure", "type": "timestamp", "algo": "rand", "method": "auto", "identifier": "altname", "allowed": true, "value": { "$binary": { "base64": "AgGVERAAAAAAAAAAAAAAAAARQ0Pjx3l92Aqhn2e1hot2M9rQ6aLPE2Iw8AVhm5AD8FWywWih12Fn2p9+kiE33yKPOCyrTWQHKPtB4yYhqnJgGg==", "subType": "06" } } }, "azure_timestamp_rand_explicit_id": { "kms": "azure", "type": "timestamp", "algo": "rand", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "AgGVERAAAAAAAAAAAAAAAAARvFMlIzh2IjpHkTJ8buqTOqBA0+CxVDsZacUhSHVMgJLN+0DJsJy8OfkmKMu9Lk5hULY00Udoja87x+79mYfmeQ==", "subType": "06" } } }, "azure_timestamp_rand_explicit_altname": { "kms": "azure", "type": "timestamp", "algo": "rand", "method": "explicit", "identifier": "altname", "allowed": true, "value": { "$binary": { "base64": "AgGVERAAAAAAAAAAAAAAAAAR+2SCd7V5ukAkh7CYpNPIatzTL8osNoA4Mb5jjjbos8eMamImw0fbH8YA+Rdm4CgGdQQ9VDX7MtMWlArkj0Jpew==", "subType": "06" } } }, "azure_timestamp_det_auto_id": { "kms": "azure", "type": "timestamp", "algo": "det", "method": "auto", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "AQGVERAAAAAAAAAAAAAAAAARe72T/oC09QGE1vuljb6ZEHa6llEwMLT+C4s9u1fREkOKndpmrOlGE8zOey4teizY1ypOMkIZ8GDQJJ4kLSpNkQ==", "subType": "06" } } }, "azure_timestamp_det_explicit_id": { "kms": "azure", "type": "timestamp", "algo": "det", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "AQGVERAAAAAAAAAAAAAAAAARe72T/oC09QGE1vuljb6ZEHa6llEwMLT+C4s9u1fREkOKndpmrOlGE8zOey4teizY1ypOMkIZ8GDQJJ4kLSpNkQ==", "subType": "06" } } }, "azure_timestamp_det_explicit_altname": { "kms": "azure", "type": "timestamp", "algo": "det", "method": "explicit", "identifier": "altname", "allowed": true, "value": { "$binary": { "base64": "AQGVERAAAAAAAAAAAAAAAAARe72T/oC09QGE1vuljb6ZEHa6llEwMLT+C4s9u1fREkOKndpmrOlGE8zOey4teizY1ypOMkIZ8GDQJJ4kLSpNkQ==", "subType": "06" } } }, "azure_long_rand_auto_id": { "kms": "azure", "type": "long", "algo": "rand", "method": "auto", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "AgGVERAAAAAAAAAAAAAAAAASSSgX7k8iw0xFe0AiIzOu0e0P7Ujyfsk/Cdl0fR5X8V3QLVER+1Qa47Qpb8iWL2VLBSh+55HvIEtvhWn8SwXaog==", "subType": "06" } } }, "azure_long_rand_auto_altname": { "kms": "azure", "type": "long", "algo": "rand", "method": "auto", "identifier": "altname", "allowed": true, "value": { "$binary": { "base64": "AgGVERAAAAAAAAAAAAAAAAASUhKr5K7ulGTeFbhIvJ2DDE10gRAFn5+2zqnsIFSY8lYV2PBYcENdeNBXZs6kyIAYhJdQyuOChVCerTI5jmQWDw==", "subType": "06" } } }, "azure_long_rand_explicit_id": { "kms": "azure", "type": "long", "algo": "rand", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "AgGVERAAAAAAAAAAAAAAAAASHxawpjTHdXYRWQSZ7Qi7gFC+o4dW2mPH8s5nQkPFY/EubcJbdAZ5HFp66NfPaDJ/NSH6Vy+TkpX3683RC+bjSQ==", "subType": "06" } } }, "azure_long_rand_explicit_altname": { "kms": "azure", "type": "long", "algo": "rand", "method": "explicit", "identifier": "altname", "allowed": true, "value": { "$binary": { "base64": "AgGVERAAAAAAAAAAAAAAAAASVaMAv6UjuBOUZMJ9qz+58TQWmgaMpS9xrJziJY80ml9aRlDTtRubP7U40CgbDvrtY1QgHbkF/di1XDCB6iXMMg==", "subType": "06" } } }, "azure_long_det_auto_id": { "kms": "azure", "type": "long", "algo": "det", "method": "auto", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "AQGVERAAAAAAAAAAAAAAAAAS06L8oEPeMvVlA32VlobdOWG24OoyMbv9PyYsHLsbT0bHFwU7lYUSQG9EkYVRNPEDzvXpciE1jT7KT8CRY8XT/g==", "subType": "06" } } }, "azure_long_det_explicit_id": { "kms": "azure", "type": "long", "algo": "det", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "AQGVERAAAAAAAAAAAAAAAAAS06L8oEPeMvVlA32VlobdOWG24OoyMbv9PyYsHLsbT0bHFwU7lYUSQG9EkYVRNPEDzvXpciE1jT7KT8CRY8XT/g==", "subType": "06" } } }, "azure_long_det_explicit_altname": { "kms": "azure", "type": "long", "algo": "det", "method": "explicit", "identifier": "altname", "allowed": true, "value": { "$binary": { "base64": "AQGVERAAAAAAAAAAAAAAAAAS06L8oEPeMvVlA32VlobdOWG24OoyMbv9PyYsHLsbT0bHFwU7lYUSQG9EkYVRNPEDzvXpciE1jT7KT8CRY8XT/g==", "subType": "06" } } }, "azure_decimal_rand_auto_id": { "kms": "azure", "type": "decimal", "algo": "rand", "method": "auto", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "AgGVERAAAAAAAAAAAAAAAAATJ6LZgPu9F+rPtYsMuvwOx62+g1dAk858BUtE9FjC/300DnbDiolhkHNcyoFs07NYUNgLthW2rISb/ejmsDCt/oqnf8zWYf9vrJEfHaS/Ocw=", "subType": "06" } } }, "azure_decimal_rand_auto_altname": { "kms": "azure", "type": "decimal", "algo": "rand", "method": "auto", "identifier": "altname", "allowed": true, "value": { "$binary": { "base64": "AgGVERAAAAAAAAAAAAAAAAATX8eD6qFYWKwIGvXtQG79fXKuPW9hkIV0OwrmNNIqRltw6gPHl+/1X8Q6rgmjCxqvhB05AxTj7xz64gP+ILkPQY8e8VGuCOvOdwDo2IPwy18=", "subType": "06" } } }, "azure_decimal_rand_explicit_id": { "kms": "azure", "type": "decimal", "algo": "rand", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "AgGVERAAAAAAAAAAAAAAAAATBjQ9E5wDdTS/iI1XDqGmDBC5aLbPB4nSyrjRLfv1zEoPRjmcHlQmMRJA0mori2VQv6EBFNHeczFCenJaSAkuh77czeXM2vH3T6qwEIDs4dw=", "subType": "06" } } }, "azure_decimal_rand_explicit_altname": { "kms": "azure", "type": "decimal", "algo": "rand", "method": "explicit", "identifier": "altname", "allowed": true, "value": { "$binary": { "base64": "AgGVERAAAAAAAAAAAAAAAAATtkjbhdve7MNuLaTm6qvaewuVUxeC1DMz1fd4RC4jeiBFMd5uZUVJTiOIerwQ6P5G5lkMlezKDWgKl2FUvZH6c7V3JknhsaWcV5iLWGUL6Zc=", "subType": "06" } } }, "azure_decimal_det_explicit_id": { "kms": "azure", "type": "decimal", "algo": "det", "method": "explicit", "identifier": "id", "allowed": false, "value": { "$numberDecimal": "1.234" } }, "azure_decimal_det_explicit_altname": { "kms": "azure", "type": "decimal", "algo": "det", "method": "explicit", "identifier": "altname", "allowed": false, "value": { "$numberDecimal": "1.234" } }, "azure_minKey_rand_explicit_id": { "kms": "azure", "type": "minKey", "algo": "rand", "method": "explicit", "identifier": "id", "allowed": false, "value": { "$minKey": 1 } }, "azure_minKey_rand_explicit_altname": { "kms": "azure", "type": "minKey", "algo": "rand", "method": "explicit", "identifier": "altname", "allowed": false, "value": { "$minKey": 1 } }, "azure_minKey_det_explicit_id": { "kms": "azure", "type": "minKey", "algo": "det", "method": "explicit", "identifier": "id", "allowed": false, "value": { "$minKey": 1 } }, "azure_minKey_det_explicit_altname": { "kms": "azure", "type": "minKey", "algo": "det", "method": "explicit", "identifier": "altname", "allowed": false, "value": { "$minKey": 1 } }, "azure_maxKey_rand_explicit_id": { "kms": "azure", "type": "maxKey", "algo": "rand", "method": "explicit", "identifier": "id", "allowed": false, "value": { "$maxKey": 1 } }, "azure_maxKey_rand_explicit_altname": { "kms": "azure", "type": "maxKey", "algo": "rand", "method": "explicit", "identifier": "altname", "allowed": false, "value": { "$maxKey": 1 } }, "azure_maxKey_det_explicit_id": { "kms": "azure", "type": "maxKey", "algo": "det", "method": "explicit", "identifier": "id", "allowed": false, "value": { "$maxKey": 1 } }, "azure_maxKey_det_explicit_altname": { "kms": "azure", "type": "maxKey", "algo": "det", "method": "explicit", "identifier": "altname", "allowed": false, "value": { "$maxKey": 1 } }, "gcp_double_rand_auto_id": { "kms": "gcp", "type": "double", "algo": "rand", "method": "auto", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "AhgjwAAAAAAAAAAAAAAAAAABFoHQxnh1XSC0k1B01uFFg7rE9sZVBn4PXo26JX8gx9tuxu+4l9Avb23H9BfOzuWiEc43iw87K/W2y0VfKp5CCg==", "subType": "06" } } }, "gcp_double_rand_auto_altname": { "kms": "gcp", "type": "double", "algo": "rand", "method": "auto", "identifier": "altname", "allowed": true, "value": { "$binary": { "base64": "AhgjwAAAAAAAAAAAAAAAAAABRkZkEtQEFB/r268cNfYRQbN4u5Cxjl9Uh+8wq9TFWLQH2E/9wj2vTLlxQ2cQsM7Qd+XxR5idjfBf9CKAfvUa/A==", "subType": "06" } } }, "gcp_double_rand_explicit_id": { "kms": "gcp", "type": "double", "algo": "rand", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "AhgjwAAAAAAAAAAAAAAAAAABDSUZ+0BbDDEZxCXA+J2T6Js8Uor2dfXSf7s/hpLrg6dxcW2chpht9XLiLOXG5w83TzCAI5pF8cQgBpBpYjR8RQ==", "subType": "06" } } }, "gcp_double_rand_explicit_altname": { "kms": "gcp", "type": "double", "algo": "rand", "method": "explicit", "identifier": "altname", "allowed": true, "value": { "$binary": { "base64": "AhgjwAAAAAAAAAAAAAAAAAABCYxugs7L+4S+1rr0VILSbtBm79JPTLuzluQAv0+8hbu5Z6zReOL6Ta1vQH1oA+pSPGYA4euye3zNl1X6ZewbPw==", "subType": "06" } } }, "gcp_double_det_explicit_id": { "kms": "gcp", "type": "double", "algo": "det", "method": "explicit", "identifier": "id", "allowed": false, "value": { "$numberDouble": "1.2339999999999999858" } }, "gcp_double_det_explicit_altname": { "kms": "gcp", "type": "double", "algo": "det", "method": "explicit", "identifier": "altname", "allowed": false, "value": { "$numberDouble": "1.2339999999999999858" } }, "gcp_string_rand_auto_id": { "kms": "gcp", "type": "string", "algo": "rand", "method": "auto", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "AhgjwAAAAAAAAAAAAAAAAAACx3wSslJEiD80YLTH0n4Bbs4yWVPQl15AU8pZMLLQePqEtI+BJy3t2bqNP1098jS0CGSf+LQmQvXhJn1aNFeMTw==", "subType": "06" } } }, "gcp_string_rand_auto_altname": { "kms": "gcp", "type": "string", "algo": "rand", "method": "auto", "identifier": "altname", "allowed": true, "value": { "$binary": { "base64": "AhgjwAAAAAAAAAAAAAAAAAAC5BTe5KP5UxSIk6dJlkz8aaZ/9fg44XPWHafiiL/48lcv3AWbu2gcBo1EDuc1sJQu6XMrtDCRQ7PCHsL7sEQMGQ==", "subType": "06" } } }, "gcp_string_rand_explicit_id": { "kms": "gcp", "type": "string", "algo": "rand", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "AhgjwAAAAAAAAAAAAAAAAAACyJN55OcyXXJ71x8VphTaIuIg6kQtGgVKPhWx0LSdYc6JOjB6LTdA7SEWiSlSWWFZE26UmKcPbkbLDAYf4IVrzQ==", "subType": "06" } } }, "gcp_string_rand_explicit_altname": { "kms": "gcp", "type": "string", "algo": "rand", "method": "explicit", "identifier": "altname", "allowed": true, "value": { "$binary": { "base64": "AhgjwAAAAAAAAAAAAAAAAAACoa0d9gqfPP5s3+GoruwzxoQFgli8SmjpTVRLAOcFxqGdfrwSbpYffSw/OR45sZPxXCL6T2MtUvZsl7ukv0jBnw==", "subType": "06" } } }, "gcp_string_det_auto_id": { "kms": "gcp", "type": "string", "algo": "det", "method": "auto", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "ARgjwAAAAAAAAAAAAAAAAAACTCkyETcWayIZ9YEoQEBVIF3i7iXEe6M3KjYYaSVCYdqSbSHBzlwKWYbP+Xj/MMYBYTLZ1aiRQWCMK4gWPYppZw==", "subType": "06" } } }, "gcp_string_det_explicit_id": { "kms": "gcp", "type": "string", "algo": "det", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "ARgjwAAAAAAAAAAAAAAAAAACTCkyETcWayIZ9YEoQEBVIF3i7iXEe6M3KjYYaSVCYdqSbSHBzlwKWYbP+Xj/MMYBYTLZ1aiRQWCMK4gWPYppZw==", "subType": "06" } } }, "gcp_string_det_explicit_altname": { "kms": "gcp", "type": "string", "algo": "det", "method": "explicit", "identifier": "altname", "allowed": true, "value": { "$binary": { "base64": "ARgjwAAAAAAAAAAAAAAAAAACTCkyETcWayIZ9YEoQEBVIF3i7iXEe6M3KjYYaSVCYdqSbSHBzlwKWYbP+Xj/MMYBYTLZ1aiRQWCMK4gWPYppZw==", "subType": "06" } } }, "gcp_object_rand_auto_id": { "kms": "gcp", "type": "object", "algo": "rand", "method": "auto", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "AhgjwAAAAAAAAAAAAAAAAAADy+8fkyeNYdIK001YogXfKc25zRXS1VGIFVWR6jRfrexy9C8LBBfX3iDwGNPbP2pkC3Tq16OoziQB6iNGf7s7yg==", "subType": "06" } } }, "gcp_object_rand_auto_altname": { "kms": "gcp", "type": "object", "algo": "rand", "method": "auto", "identifier": "altname", "allowed": true, "value": { "$binary": { "base64": "AhgjwAAAAAAAAAAAAAAAAAADixoDdvm57gH8ooOaKI57WyZD5uaPmuYgmrgAFuV8I+oaalqYctnNSYlzQKCMQX/mIcTxvW3oOWY7+IzAz7npvw==", "subType": "06" } } }, "gcp_object_rand_explicit_id": { "kms": "gcp", "type": "object", "algo": "rand", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "AhgjwAAAAAAAAAAAAAAAAAADvq0OAoijgHaVMhsoNMdfWFLyISDo6Y13sYM0CoBXS/oXJNIJJvhgKPbFSV/h4IgiDLy4qNYOTJQvpqt094RPgQ==", "subType": "06" } } }, "gcp_object_rand_explicit_altname": { "kms": "gcp", "type": "object", "algo": "rand", "method": "explicit", "identifier": "altname", "allowed": true, "value": { "$binary": { "base64": "AhgjwAAAAAAAAAAAAAAAAAADuTZF7/uqGjFbjzBYspPkxGWvvVAEN/ib8bfPOQrEobtTWuU+ju9H3TlT9DMuFy7RdUZnPB0D3HkM8+zky5xeBw==", "subType": "06" } } }, "gcp_object_det_explicit_id": { "kms": "gcp", "type": "object", "algo": "det", "method": "explicit", "identifier": "id", "allowed": false, "value": { "x": { "$numberInt": "1" } } }, "gcp_object_det_explicit_altname": { "kms": "gcp", "type": "object", "algo": "det", "method": "explicit", "identifier": "altname", "allowed": false, "value": { "x": { "$numberInt": "1" } } }, "gcp_array_rand_auto_id": { "kms": "gcp", "type": "array", "algo": "rand", "method": "auto", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "AhgjwAAAAAAAAAAAAAAAAAAE085kJIBX6S93D94bcRjkOegEKsksi2R1cxoVDoOpSdHh3S6bZAOh50W405wvnOKf3KTP9SICDUehQKQZSC026Y5dwVQ2GiM7PtpSedthKJs=", "subType": "06" } } }, "gcp_array_rand_auto_altname": { "kms": "gcp", "type": "array", "algo": "rand", "method": "auto", "identifier": "altname", "allowed": true, "value": { "$binary": { "base64": "AhgjwAAAAAAAAAAAAAAAAAAEk/FAXsaqyVr6I+MY5L0axeLhskcEfLZeB8whLMKbjLDLa8Iep+IdrFVSfKo03Zr/7Ah8Js01aT6+Vt4EDMJK0mGKZJOjsrAf3b6RS+Mzebg=", "subType": "06" } } }, "gcp_array_rand_explicit_id": { "kms": "gcp", "type": "array", "algo": "rand", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "AhgjwAAAAAAAAAAAAAAAAAAEDY7J9JGiurctYr7ytakNjcryVm42fkubcVpQpUYEkpK/G9NLGjrJuFgNW5ZVjYiPKEBbDB7vEtJqGux0BU++hrvVHNJ3wUT2mbDE18NE4KE=", "subType": "06" } } }, "gcp_array_rand_explicit_altname": { "kms": "gcp", "type": "array", "algo": "rand", "method": "explicit", "identifier": "altname", "allowed": true, "value": { "$binary": { "base64": "AhgjwAAAAAAAAAAAAAAAAAAErFFlw8W9J2y+751RnYLw0TSK9ThD6sP3i4zPbZtiuhc90RFoJhScvqM9i4sDKuYePZZRLBxdX4EZhZClOmswCGDLCIWsQlSvCwgDcIsRR/w=", "subType": "06" } } }, "gcp_array_det_explicit_id": { "kms": "gcp", "type": "array", "algo": "det", "method": "explicit", "identifier": "id", "allowed": false, "value": [ { "$numberInt": "1" }, { "$numberInt": "2" }, { "$numberInt": "3" } ] }, "gcp_array_det_explicit_altname": { "kms": "gcp", "type": "array", "algo": "det", "method": "explicit", "identifier": "altname", "allowed": false, "value": [ { "$numberInt": "1" }, { "$numberInt": "2" }, { "$numberInt": "3" } ] }, "gcp_binData=00_rand_auto_id": { "kms": "gcp", "type": "binData=00", "algo": "rand", "method": "auto", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "AhgjwAAAAAAAAAAAAAAAAAAF0R5BNkQKfm6wx/tob8nVGDEYV/pvy9UeCqc9gFNuB5d9KxCkgyxryV65rbB90OriqvWFO2jcxzchRYgRI3fQ+A==", "subType": "06" } } }, "gcp_binData=00_rand_auto_altname": { "kms": "gcp", "type": "binData=00", "algo": "rand", "method": "auto", "identifier": "altname", "allowed": true, "value": { "$binary": { "base64": "AhgjwAAAAAAAAAAAAAAAAAAF4wcT8XGc3xNdKYDX5/cbUwPDdnkIXlWWCCYeSXSk2oWPxMZnPsVQ44nXKJJsKitoE3r/hL1sSG5239WzCWyx9g==", "subType": "06" } } }, "gcp_binData=00_rand_explicit_id": { "kms": "gcp", "type": "binData=00", "algo": "rand", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "AhgjwAAAAAAAAAAAAAAAAAAF07OFs5mlx0AB6QBanaybLuhuFbG+19KxSqHlSgELcz6TQKI6equX97OZdaWSWf2SSeiYm5E6+Y3lgA5l4KxC2A==", "subType": "06" } } }, "gcp_binData=00_rand_explicit_altname": { "kms": "gcp", "type": "binData=00", "algo": "rand", "method": "explicit", "identifier": "altname", "allowed": true, "value": { "$binary": { "base64": "AhgjwAAAAAAAAAAAAAAAAAAFZ74Q7JMm7y2i3wRmjIRKefhmdnrhP1NXJgploi+44eQ2eRraZsW7peGPYyIfsXEbhgV5+aLmiYgvemBywfdogQ==", "subType": "06" } } }, "gcp_binData=00_det_auto_id": { "kms": "gcp", "type": "binData=00", "algo": "det", "method": "auto", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "ARgjwAAAAAAAAAAAAAAAAAAFhwJkocj36WXoY3mg2GWUrJ5IQTo9MvkwEwRFKdkcxm9pX2PZPK7bN5ZWw3IFcQ/0GfaW6V4LYr8WarZdLF0p5g==", "subType": "06" } } }, "gcp_binData=00_det_explicit_id": { "kms": "gcp", "type": "binData=00", "algo": "det", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "ARgjwAAAAAAAAAAAAAAAAAAFhwJkocj36WXoY3mg2GWUrJ5IQTo9MvkwEwRFKdkcxm9pX2PZPK7bN5ZWw3IFcQ/0GfaW6V4LYr8WarZdLF0p5g==", "subType": "06" } } }, "gcp_binData=00_det_explicit_altname": { "kms": "gcp", "type": "binData=00", "algo": "det", "method": "explicit", "identifier": "altname", "allowed": true, "value": { "$binary": { "base64": "ARgjwAAAAAAAAAAAAAAAAAAFhwJkocj36WXoY3mg2GWUrJ5IQTo9MvkwEwRFKdkcxm9pX2PZPK7bN5ZWw3IFcQ/0GfaW6V4LYr8WarZdLF0p5g==", "subType": "06" } } }, "gcp_binData=04_rand_auto_id": { "kms": "gcp", "type": "binData=04", "algo": "rand", "method": "auto", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "AhgjwAAAAAAAAAAAAAAAAAAFmDO47RTVXzm8D4hfhLICILrQJg3yOwG3HYfCdz7yaanPow2Y6bMxvXxk+kDS29aS8pJKDqJQQoMGc1ZFD3yYKsLQHRi/8rW6TNDQd4sCQ00=", "subType": "06" } } }, "gcp_binData=04_rand_auto_altname": { "kms": "gcp", "type": "binData=04", "algo": "rand", "method": "auto", "identifier": "altname", "allowed": true, "value": { "$binary": { "base64": "AhgjwAAAAAAAAAAAAAAAAAAFpiu9Q3LTuPmgdWBqo5Kw0vGF9xU1rMyE4xwR8GccZ7ZMrUcR4AnZnAP7ah5Oz8e7qonNYX4d09obesYSLlIjyK7J7qg+GWiEURgbvmOngaA=", "subType": "06" } } }, "gcp_binData=04_rand_explicit_id": { "kms": "gcp", "type": "binData=04", "algo": "rand", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "AhgjwAAAAAAAAAAAAAAAAAAFHRy8dveGuMng9WMmadIp39jD7iEfl3bEjKmzyNoAc0wIcSJZo9kdGbNEwZ4p+A1gz273fmAt/AJwAxwvqdlanLWBr4wiSKz1Mu9VaBcTlyY=", "subType": "06" } } }, "gcp_binData=04_rand_explicit_altname": { "kms": "gcp", "type": "binData=04", "algo": "rand", "method": "explicit", "identifier": "altname", "allowed": true, "value": { "$binary": { "base64": "AhgjwAAAAAAAAAAAAAAAAAAFiqO+sKodqXuVox0zTbKuY4Ng0QE1If2hDLWXljAEZdYABPk20UJyL/CHR49WP2Cwvi4evJCf8sEfKpR+ugPiyxWzP3iVe6qqTzP93BBjqoc=", "subType": "06" } } }, "gcp_binData=04_det_auto_id": { "kms": "gcp", "type": "binData=04", "algo": "det", "method": "auto", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "ARgjwAAAAAAAAAAAAAAAAAAFEp5Gut6iENHUqDMVdBm4cxQy35gnslTf7vSWW9InFh323BvaTTiubxbxTiMKIa/u47MfMprL9HNQSwgpAQc4lped+YnlRW8RYvTcG4frFtA=", "subType": "06" } } }, "gcp_binData=04_det_explicit_id": { "kms": "gcp", "type": "binData=04", "algo": "det", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "ARgjwAAAAAAAAAAAAAAAAAAFEp5Gut6iENHUqDMVdBm4cxQy35gnslTf7vSWW9InFh323BvaTTiubxbxTiMKIa/u47MfMprL9HNQSwgpAQc4lped+YnlRW8RYvTcG4frFtA=", "subType": "06" } } }, "gcp_binData=04_det_explicit_altname": { "kms": "gcp", "type": "binData=04", "algo": "det", "method": "explicit", "identifier": "altname", "allowed": true, "value": { "$binary": { "base64": "ARgjwAAAAAAAAAAAAAAAAAAFEp5Gut6iENHUqDMVdBm4cxQy35gnslTf7vSWW9InFh323BvaTTiubxbxTiMKIa/u47MfMprL9HNQSwgpAQc4lped+YnlRW8RYvTcG4frFtA=", "subType": "06" } } }, "gcp_undefined_rand_explicit_id": { "kms": "gcp", "type": "undefined", "algo": "rand", "method": "explicit", "identifier": "id", "allowed": false, "value": { "$undefined": true } }, "gcp_undefined_rand_explicit_altname": { "kms": "gcp", "type": "undefined", "algo": "rand", "method": "explicit", "identifier": "altname", "allowed": false, "value": { "$undefined": true } }, "gcp_undefined_det_explicit_id": { "kms": "gcp", "type": "undefined", "algo": "det", "method": "explicit", "identifier": "id", "allowed": false, "value": { "$undefined": true } }, "gcp_undefined_det_explicit_altname": { "kms": "gcp", "type": "undefined", "algo": "det", "method": "explicit", "identifier": "altname", "allowed": false, "value": { "$undefined": true } }, "gcp_objectId_rand_auto_id": { "kms": "gcp", "type": "objectId", "algo": "rand", "method": "auto", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "AhgjwAAAAAAAAAAAAAAAAAAH8Kt6coc8bPI4QIwS1tIdk6pPA05xlZvrOyAQgvoqaozMtWzG15OunQLDdS3yJ5WRiV7kO6CIKqRrvL2RykB5sw==", "subType": "06" } } }, "gcp_objectId_rand_auto_altname": { "kms": "gcp", "type": "objectId", "algo": "rand", "method": "auto", "identifier": "altname", "allowed": true, "value": { "$binary": { "base64": "AhgjwAAAAAAAAAAAAAAAAAAHU5Yzmz2mbgNQrGSvglgVuv14nQWzipBkZUVSO4eYZ7wLrj/9t0fnizsu7Isgg5oA9fV0Snh/A9pDnHZWoccXUw==", "subType": "06" } } }, "gcp_objectId_rand_explicit_id": { "kms": "gcp", "type": "objectId", "algo": "rand", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "AhgjwAAAAAAAAAAAAAAAAAAHsdq5/FLqbjMDiNzf+6k9yxUtFVjS/xSqErqaboOl21934pAzgkOzBGodpKKFuK0Ta4f3h21XS+84wlIYPMlTtw==", "subType": "06" } } }, "gcp_objectId_rand_explicit_altname": { "kms": "gcp", "type": "objectId", "algo": "rand", "method": "explicit", "identifier": "altname", "allowed": true, "value": { "$binary": { "base64": "AhgjwAAAAAAAAAAAAAAAAAAHokIdXxNQ/NBMdMAVNxyVuz/J5pMMdtfxxJxr7PbsRJ3FoD2QNjTgE1Wsz0G4o09Wv9UWD+/mIqPVlLgx1sRtPw==", "subType": "06" } } }, "gcp_objectId_det_auto_id": { "kms": "gcp", "type": "objectId", "algo": "det", "method": "auto", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "ARgjwAAAAAAAAAAAAAAAAAAHkcbaj3Hy3b4HkjRkMgiw5h6jBW7Sc56QSJmAPmVSc2T4B8d79A49dW0RyEiInZJcnVRjrYzUTRtgRaG4/FRd8g==", "subType": "06" } } }, "gcp_objectId_det_explicit_id": { "kms": "gcp", "type": "objectId", "algo": "det", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "ARgjwAAAAAAAAAAAAAAAAAAHkcbaj3Hy3b4HkjRkMgiw5h6jBW7Sc56QSJmAPmVSc2T4B8d79A49dW0RyEiInZJcnVRjrYzUTRtgRaG4/FRd8g==", "subType": "06" } } }, "gcp_objectId_det_explicit_altname": { "kms": "gcp", "type": "objectId", "algo": "det", "method": "explicit", "identifier": "altname", "allowed": true, "value": { "$binary": { "base64": "ARgjwAAAAAAAAAAAAAAAAAAHkcbaj3Hy3b4HkjRkMgiw5h6jBW7Sc56QSJmAPmVSc2T4B8d79A49dW0RyEiInZJcnVRjrYzUTRtgRaG4/FRd8g==", "subType": "06" } } }, "gcp_bool_rand_auto_id": { "kms": "gcp", "type": "bool", "algo": "rand", "method": "auto", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "AhgjwAAAAAAAAAAAAAAAAAAIf7vUYS5XFrEU4g03lzj9dk8a2MkaQdlH8nE/507D2Gm5XKQLi2jCENZ9UaQm3MQtVr4Uqrgz2GZiQHt9mXcG3w==", "subType": "06" } } }, "gcp_bool_rand_auto_altname": { "kms": "gcp", "type": "bool", "algo": "rand", "method": "auto", "identifier": "altname", "allowed": true, "value": { "$binary": { "base64": "AhgjwAAAAAAAAAAAAAAAAAAIdOC4Tx/TaVLRtOL/Qh8RUFIzHFB6nSegZoITwZeDethd8V3+R+aIAgzfN3pvmZzagHyVCm2nbNYJNdjOJhuDrg==", "subType": "06" } } }, "gcp_bool_rand_explicit_id": { "kms": "gcp", "type": "bool", "algo": "rand", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "AhgjwAAAAAAAAAAAAAAAAAAIzB14mX2vaZdiW9kGc+wYEgTCXA0FB5AVEyuERD00+K7U5Otlc6ZUwMtb9nGUu+M7PnnfxiDFHCrUWrTkAZzSUw==", "subType": "06" } } }, "gcp_bool_rand_explicit_altname": { "kms": "gcp", "type": "bool", "algo": "rand", "method": "explicit", "identifier": "altname", "allowed": true, "value": { "$binary": { "base64": "AhgjwAAAAAAAAAAAAAAAAAAIhRLg79ACCMfeERBgG1wirirrZXZzbK11RxHkAbf14Fji2L3sdMBdLBU5I028+rmtDdC7khcNMt11V6XGKpAjnA==", "subType": "06" } } }, "gcp_bool_det_explicit_id": { "kms": "gcp", "type": "bool", "algo": "det", "method": "explicit", "identifier": "id", "allowed": false, "value": true }, "gcp_bool_det_explicit_altname": { "kms": "gcp", "type": "bool", "algo": "det", "method": "explicit", "identifier": "altname", "allowed": false, "value": true }, "gcp_date_rand_auto_id": { "kms": "gcp", "type": "date", "algo": "rand", "method": "auto", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "AhgjwAAAAAAAAAAAAAAAAAAJL+mjI8xBmSahOOi3XkGRGxjhGNdJb445KZtRAaUdCV0vMKbrefuiDHJDPCYo7mLYNhRSIhQfs63IFYMrlKP26A==", "subType": "06" } } }, "gcp_date_rand_auto_altname": { "kms": "gcp", "type": "date", "algo": "rand", "method": "auto", "identifier": "altname", "allowed": true, "value": { "$binary": { "base64": "AhgjwAAAAAAAAAAAAAAAAAAJbeyqO5FRmqvPYyOb0tdKtK6JOg8QKbCl37/iFeEm7N0T0Pjb8Io4U0ndB3O6fjokc3kDQrZcQkV+OFWIMuKFjw==", "subType": "06" } } }, "gcp_date_rand_explicit_id": { "kms": "gcp", "type": "date", "algo": "rand", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "AhgjwAAAAAAAAAAAAAAAAAAJVz3rSYIcoYtM0tZ8pB2Ytgh8RvYPeZvW7aUVJfZkZlIhfUHOHEf5kHqxzt8E1l2n3lmK/7ZVCFUuCCmr8cZyWw==", "subType": "06" } } }, "gcp_date_rand_explicit_altname": { "kms": "gcp", "type": "date", "algo": "rand", "method": "explicit", "identifier": "altname", "allowed": true, "value": { "$binary": { "base64": "AhgjwAAAAAAAAAAAAAAAAAAJAiQqNyUcpuDEpFt7skp2NSHFCux2XObrIIFgXReYgtWoapL/n4zksJXl89PGavzNPBZbzgEa8uwwAe+S+Y6TLg==", "subType": "06" } } }, "gcp_date_det_auto_id": { "kms": "gcp", "type": "date", "algo": "det", "method": "auto", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "ARgjwAAAAAAAAAAAAAAAAAAJmATV2A1P5DmrS8uES6AMD9y+EU3x7u4K4J0p296iSkCEgIdZZORhPIEnuJK3FHw1II6IEShW2nd7sOJRZSGKcg==", "subType": "06" } } }, "gcp_date_det_explicit_id": { "kms": "gcp", "type": "date", "algo": "det", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "ARgjwAAAAAAAAAAAAAAAAAAJmATV2A1P5DmrS8uES6AMD9y+EU3x7u4K4J0p296iSkCEgIdZZORhPIEnuJK3FHw1II6IEShW2nd7sOJRZSGKcg==", "subType": "06" } } }, "gcp_date_det_explicit_altname": { "kms": "gcp", "type": "date", "algo": "det", "method": "explicit", "identifier": "altname", "allowed": true, "value": { "$binary": { "base64": "ARgjwAAAAAAAAAAAAAAAAAAJmATV2A1P5DmrS8uES6AMD9y+EU3x7u4K4J0p296iSkCEgIdZZORhPIEnuJK3FHw1II6IEShW2nd7sOJRZSGKcg==", "subType": "06" } } }, "gcp_null_rand_explicit_id": { "kms": "gcp", "type": "null", "algo": "rand", "method": "explicit", "identifier": "id", "allowed": false, "value": null }, "gcp_null_rand_explicit_altname": { "kms": "gcp", "type": "null", "algo": "rand", "method": "explicit", "identifier": "altname", "allowed": false, "value": null }, "gcp_null_det_explicit_id": { "kms": "gcp", "type": "null", "algo": "det", "method": "explicit", "identifier": "id", "allowed": false, "value": null }, "gcp_null_det_explicit_altname": { "kms": "gcp", "type": "null", "algo": "det", "method": "explicit", "identifier": "altname", "allowed": false, "value": null }, "gcp_regex_rand_auto_id": { "kms": "gcp", "type": "regex", "algo": "rand", "method": "auto", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "AhgjwAAAAAAAAAAAAAAAAAALiebb3hWwJRqlgVEhLYKKvo6cnlU7BFnZnvlZ8GuIr11fUvcnS9Tg2m7vPmfL7WVyuNrXlR48x28Es49YuaxuIg==", "subType": "06" } } }, "gcp_regex_rand_auto_altname": { "kms": "gcp", "type": "regex", "algo": "rand", "method": "auto", "identifier": "altname", "allowed": true, "value": { "$binary": { "base64": "AhgjwAAAAAAAAAAAAAAAAAALouDFNLVgBXqhJvBRj9DKacuD1AQ2NAVDW93P9NpZDFFwGOFxmKUcklbPj8KkHqvma8ovVUBTLLUDR+tKFRvC2Q==", "subType": "06" } } }, "gcp_regex_rand_explicit_id": { "kms": "gcp", "type": "regex", "algo": "rand", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "AhgjwAAAAAAAAAAAAAAAAAALtdcT9+3R1he4eniT+1opqs/YtujFlqzBXssv+hCKhJQVY/IXde32nNpQ1WTgUc7jfIJl/v9HvuA9cDHPtDWWTg==", "subType": "06" } } }, "gcp_regex_rand_explicit_altname": { "kms": "gcp", "type": "regex", "algo": "rand", "method": "explicit", "identifier": "altname", "allowed": true, "value": { "$binary": { "base64": "AhgjwAAAAAAAAAAAAAAAAAALAwlRAlj4Zpn+wu9eOcs5CsNgrkVwrgmu1tc4wyQp0Lt+3UcplYsXQMrMPcTx3yB0JcI4Kh65n/DrAaA+G/a6iw==", "subType": "06" } } }, "gcp_regex_det_auto_id": { "kms": "gcp", "type": "regex", "algo": "det", "method": "auto", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "ARgjwAAAAAAAAAAAAAAAAAALbCutQ7D94gk0djewcQiEdMFVVa21+Dn5enQf/mqPi3o7vPy7OejDBk9fiZRffsioRMhlx2cxqa8T3+AkeN96yg==", "subType": "06" } } }, "gcp_regex_det_explicit_id": { "kms": "gcp", "type": "regex", "algo": "det", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "ARgjwAAAAAAAAAAAAAAAAAALbCutQ7D94gk0djewcQiEdMFVVa21+Dn5enQf/mqPi3o7vPy7OejDBk9fiZRffsioRMhlx2cxqa8T3+AkeN96yg==", "subType": "06" } } }, "gcp_regex_det_explicit_altname": { "kms": "gcp", "type": "regex", "algo": "det", "method": "explicit", "identifier": "altname", "allowed": true, "value": { "$binary": { "base64": "ARgjwAAAAAAAAAAAAAAAAAALbCutQ7D94gk0djewcQiEdMFVVa21+Dn5enQf/mqPi3o7vPy7OejDBk9fiZRffsioRMhlx2cxqa8T3+AkeN96yg==", "subType": "06" } } }, "gcp_dbPointer_rand_auto_id": { "kms": "gcp", "type": "dbPointer", "algo": "rand", "method": "auto", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "AhgjwAAAAAAAAAAAAAAAAAAMG8P+Y2YNIgknxE0/yPDCHASBvCU1IJwsEyaJPuOjn03enxEN7z/wbjVMN0lGUptDP3SVL+OIZtQ35VRP84MtnbdhcfZWqMhLjzrCjmtHUEg=", "subType": "06" } } }, "gcp_dbPointer_rand_auto_altname": { "kms": "gcp", "type": "dbPointer", "algo": "rand", "method": "auto", "identifier": "altname", "allowed": true, "value": { "$binary": { "base64": "AhgjwAAAAAAAAAAAAAAAAAAMKCLFUN6ApB5fSVEWazRddhKTEwgqI/mxfe0BBxht69pZQYhTjhOJP0YcIrtr+RCeHOa4FIJgQod1CFOellIzO5YH5CuV4wPxCAlOdbJcBK8=", "subType": "06" } } }, "gcp_dbPointer_rand_explicit_id": { "kms": "gcp", "type": "dbPointer", "algo": "rand", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "AhgjwAAAAAAAAAAAAAAAAAAM7ULEA6uKKv4Pu4Sa3aAt7dXtEwfQC98aJoLBapHT+xXtn5GWPynOZQNtV3lGaYExQjiGdYbzOcav3SVy/sYTe3ktgkQnuZfe0tk0zyvKIMM=", "subType": "06" } } }, "gcp_dbPointer_rand_explicit_altname": { "kms": "gcp", "type": "dbPointer", "algo": "rand", "method": "explicit", "identifier": "altname", "allowed": true, "value": { "$binary": { "base64": "AhgjwAAAAAAAAAAAAAAAAAAMoMveHO1MadAKuT498xiKWWBUKRbH7k7P2YETDg/BufVw0swos07rk6WJa1vqyF61QEmACjy4pmlK/5P0VfKJBAIvif51YqHPQkobJVS3nVA=", "subType": "06" } } }, "gcp_dbPointer_det_auto_id": { "kms": "gcp", "type": "dbPointer", "algo": "det", "method": "auto", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "ARgjwAAAAAAAAAAAAAAAAAAMz+9m1bE+Th9YeyPmJdtJPO0F5QYsGYtU/Eom/LSoYjDmTmV2ehkKx/cevIxJfZUc+Mvv/uGoeuubGl8tiX4l+f6yLrSIS6QBtIHYKXk+JNE=", "subType": "06" } } }, "gcp_dbPointer_det_explicit_id": { "kms": "gcp", "type": "dbPointer", "algo": "det", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "ARgjwAAAAAAAAAAAAAAAAAAMz+9m1bE+Th9YeyPmJdtJPO0F5QYsGYtU/Eom/LSoYjDmTmV2ehkKx/cevIxJfZUc+Mvv/uGoeuubGl8tiX4l+f6yLrSIS6QBtIHYKXk+JNE=", "subType": "06" } } }, "gcp_dbPointer_det_explicit_altname": { "kms": "gcp", "type": "dbPointer", "algo": "det", "method": "explicit", "identifier": "altname", "allowed": true, "value": { "$binary": { "base64": "ARgjwAAAAAAAAAAAAAAAAAAMz+9m1bE+Th9YeyPmJdtJPO0F5QYsGYtU/Eom/LSoYjDmTmV2ehkKx/cevIxJfZUc+Mvv/uGoeuubGl8tiX4l+f6yLrSIS6QBtIHYKXk+JNE=", "subType": "06" } } }, "gcp_javascript_rand_auto_id": { "kms": "gcp", "type": "javascript", "algo": "rand", "method": "auto", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "AhgjwAAAAAAAAAAAAAAAAAANqBD0ITMn4BaFnDp7BX7vXbRBkFwmjQRVUeBbwsQtv5WVlJMAd/2+w7tyH8Wc44x0/9U/DA5GVhpTrtdDyPBI3w==", "subType": "06" } } }, "gcp_javascript_rand_auto_altname": { "kms": "gcp", "type": "javascript", "algo": "rand", "method": "auto", "identifier": "altname", "allowed": true, "value": { "$binary": { "base64": "AhgjwAAAAAAAAAAAAAAAAAANtA0q4mbkAaKX4x1xk0/094Mln0wnh2bYnI6s6dh+l2WLDH7A9JMZxCl6kc4uOsEfbOvjP/PLIYtdMGs14EjM5A==", "subType": "06" } } }, "gcp_javascript_rand_explicit_id": { "kms": "gcp", "type": "javascript", "algo": "rand", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "AhgjwAAAAAAAAAAAAAAAAAANfrW3pmeiFdBFt5tJS6Auq9Wo/J4r/vMRiueLWxig5S1zYuf9kFPJMK/nN9HqQPIcBIJIC2i/uEPgeepaNXACCw==", "subType": "06" } } }, "gcp_javascript_rand_explicit_altname": { "kms": "gcp", "type": "javascript", "algo": "rand", "method": "explicit", "identifier": "altname", "allowed": true, "value": { "$binary": { "base64": "AhgjwAAAAAAAAAAAAAAAAAANL7UZNzpwfwhRn/HflWIE9CSxGYNwLSo9d86HsOJ42rrZKq6HQqm/hiEAg0lyqCxVIVFxYEc2BUWSaq4/+SSyZw==", "subType": "06" } } }, "gcp_javascript_det_auto_id": { "kms": "gcp", "type": "javascript", "algo": "det", "method": "auto", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "ARgjwAAAAAAAAAAAAAAAAAANB2d97R8nUJqnG0JPsWzyFe5pct5jvUljdkPnlZvLN1ZH+wSu4WmLfjri6IzzYP//f8tywn4Il+R4lZ0Kr/RAeA==", "subType": "06" } } }, "gcp_javascript_det_explicit_id": { "kms": "gcp", "type": "javascript", "algo": "det", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "ARgjwAAAAAAAAAAAAAAAAAANB2d97R8nUJqnG0JPsWzyFe5pct5jvUljdkPnlZvLN1ZH+wSu4WmLfjri6IzzYP//f8tywn4Il+R4lZ0Kr/RAeA==", "subType": "06" } } }, "gcp_javascript_det_explicit_altname": { "kms": "gcp", "type": "javascript", "algo": "det", "method": "explicit", "identifier": "altname", "allowed": true, "value": { "$binary": { "base64": "ARgjwAAAAAAAAAAAAAAAAAANB2d97R8nUJqnG0JPsWzyFe5pct5jvUljdkPnlZvLN1ZH+wSu4WmLfjri6IzzYP//f8tywn4Il+R4lZ0Kr/RAeA==", "subType": "06" } } }, "gcp_symbol_rand_auto_id": { "kms": "gcp", "type": "symbol", "algo": "rand", "method": "auto", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "AhgjwAAAAAAAAAAAAAAAAAAOsGdnr6EKcBdOAvYrP0o1pWbhhJbYsqfVwwwS1zq6ZkBayOss2J3TuYwBGXhJFlq3iIiWLdxGQ883XIvuAECnqUNuvpK2rOLwtDg8xJLiH24=", "subType": "06" } } }, "gcp_symbol_rand_auto_altname": { "kms": "gcp", "type": "symbol", "algo": "rand", "method": "auto", "identifier": "altname", "allowed": true, "value": { "$binary": { "base64": "AhgjwAAAAAAAAAAAAAAAAAAOpfa6CUSnJBvnWdd7pSZ2pXAbYm68Yka6xa/fuyhVx/Tc926/JpqmOmQtXqbOj8dZra0rQ3/yxHySwgD7s9Qr+xvyL7LvAguGkGmEV5H4Xz4=", "subType": "06" } } }, "gcp_symbol_rand_explicit_id": { "kms": "gcp", "type": "symbol", "algo": "rand", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "AhgjwAAAAAAAAAAAAAAAAAAO085iqYGFdtjiFWHcNqE0HuKMNHmk49DVh+pX8Pb4p3ehB57JL1nRqaXqHPqhFenxSEInT/te9HQRr+ADcHADvUGsScfm/n85v85nq6X+5y4=", "subType": "06" } } }, "gcp_symbol_rand_explicit_altname": { "kms": "gcp", "type": "symbol", "algo": "rand", "method": "explicit", "identifier": "altname", "allowed": true, "value": { "$binary": { "base64": "AhgjwAAAAAAAAAAAAAAAAAAOiidb+2TsbAb2wc7MtDzb/UYsjgVNSw410Sz9pm+Uy7aZROE5SURKXdLjrCH2ZM2a+XCAl3o9yAoNgmAjEvYVxjmyzLK00EVjT42MBOrdA+k=", "subType": "06" } } }, "gcp_symbol_det_auto_id": { "kms": "gcp", "type": "symbol", "algo": "det", "method": "auto", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "ARgjwAAAAAAAAAAAAAAAAAAOFBGo77joqvZl7QQMB9ebMsAI3uro8ILQTJsTUgAqNzSh1mNzqihGHZYe84xtgMrVxNuwcjkidkRbNnLXWLuarOx4tgmOLx5A5G1eYEe3s7Q=", "subType": "06" } } }, "gcp_symbol_det_explicit_id": { "kms": "gcp", "type": "symbol", "algo": "det", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "ARgjwAAAAAAAAAAAAAAAAAAOFBGo77joqvZl7QQMB9ebMsAI3uro8ILQTJsTUgAqNzSh1mNzqihGHZYe84xtgMrVxNuwcjkidkRbNnLXWLuarOx4tgmOLx5A5G1eYEe3s7Q=", "subType": "06" } } }, "gcp_symbol_det_explicit_altname": { "kms": "gcp", "type": "symbol", "algo": "det", "method": "explicit", "identifier": "altname", "allowed": true, "value": { "$binary": { "base64": "ARgjwAAAAAAAAAAAAAAAAAAOFBGo77joqvZl7QQMB9ebMsAI3uro8ILQTJsTUgAqNzSh1mNzqihGHZYe84xtgMrVxNuwcjkidkRbNnLXWLuarOx4tgmOLx5A5G1eYEe3s7Q=", "subType": "06" } } }, "gcp_javascriptWithScope_rand_auto_id": { "kms": "gcp", "type": "javascriptWithScope", "algo": "rand", "method": "auto", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "AhgjwAAAAAAAAAAAAAAAAAAPUsQHeXWhdmyfQ2Sq1ev1HMuMhBTc/FZFKO9tMMcI9qzjr+z4IdCOFCcx24/T/6NCsDpMiOGNnCdaBCCNRwNM0CTIkpHNLO+RSZORDgAsm9Q=", "subType": "06" } } }, "gcp_javascriptWithScope_rand_auto_altname": { "kms": "gcp", "type": "javascriptWithScope", "algo": "rand", "method": "auto", "identifier": "altname", "allowed": true, "value": { "$binary": { "base64": "AhgjwAAAAAAAAAAAAAAAAAAPRZawtuu0gErebyFqiQw0LxniWhdeujGzaqfAXriGo/2fU7PalzTlWQa8wsv0y7Q/i1K4JbQwCEFpJWLppmtZshCGbVWjpPljB2BH4NNrLPE=", "subType": "06" } } }, "gcp_javascriptWithScope_rand_explicit_id": { "kms": "gcp", "type": "javascriptWithScope", "algo": "rand", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "AhgjwAAAAAAAAAAAAAAAAAAP0qkQjuKmKIqdrsrR9djxt+1jFlEL7K9bP1oz7QWuY38dZJOoGwa6G1bP4wDzjsucJLCEgU2IY+t7BHraBFXvR/Aar8ID5eXcvJ7iOPIyqUw=", "subType": "06" } } }, "gcp_javascriptWithScope_rand_explicit_altname": { "kms": "gcp", "type": "javascriptWithScope", "algo": "rand", "method": "explicit", "identifier": "altname", "allowed": true, "value": { "$binary": { "base64": "AhgjwAAAAAAAAAAAAAAAAAAP6L41iuBWGLg3hQZuhXp4MupTQvIT07+/+CRY292sC02mehk5BkuSOEVrehlvyvBJFKia4Bqd/UWvY8PnUPLqFKTLnokONWbAuh36y3gjStw=", "subType": "06" } } }, "gcp_javascriptWithScope_det_explicit_id": { "kms": "gcp", "type": "javascriptWithScope", "algo": "det", "method": "explicit", "identifier": "id", "allowed": false, "value": { "$code": "x=1", "$scope": {} } }, "gcp_javascriptWithScope_det_explicit_altname": { "kms": "gcp", "type": "javascriptWithScope", "algo": "det", "method": "explicit", "identifier": "altname", "allowed": false, "value": { "$code": "x=1", "$scope": {} } }, "gcp_int_rand_auto_id": { "kms": "gcp", "type": "int", "algo": "rand", "method": "auto", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "AhgjwAAAAAAAAAAAAAAAAAAQ+6oRKWMSvC+3UGrHSyGeVlR9bFnZtFTmYlUoGn04k6ndtCl8rsmBVUV6dMMYd7znnZtTSIGPI8q6jwf/NJjdIw==", "subType": "06" } } }, "gcp_int_rand_auto_altname": { "kms": "gcp", "type": "int", "algo": "rand", "method": "auto", "identifier": "altname", "allowed": true, "value": { "$binary": { "base64": "AhgjwAAAAAAAAAAAAAAAAAAQnz5jAbrrdutTPFA4m3MvlVJr3bpurTKY5xjwO5k8DZpeWTJzr+kVEJjG6M8/RgC/0UFNgBBrDbDhYa8PZHRijw==", "subType": "06" } } }, "gcp_int_rand_explicit_id": { "kms": "gcp", "type": "int", "algo": "rand", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "AhgjwAAAAAAAAAAAAAAAAAAQfRFoxUgjrv8up/eZ/fLlr/z++d/jFm30nYvKqsnQT7vkmmujJWc8yAtthR9OI6W5biBgAkounqRHhvatLZC6gA==", "subType": "06" } } }, "gcp_int_rand_explicit_altname": { "kms": "gcp", "type": "int", "algo": "rand", "method": "explicit", "identifier": "altname", "allowed": true, "value": { "$binary": { "base64": "AhgjwAAAAAAAAAAAAAAAAAAQY/ePk59RY6vLejx9a5ITwkT9000KAubVSqMoQwv7lNXO+GKZfZoLHG6k1MA/IxTvl1Zbz1Tw1bTctmj0HPEGNA==", "subType": "06" } } }, "gcp_int_det_auto_id": { "kms": "gcp", "type": "int", "algo": "det", "method": "auto", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "ARgjwAAAAAAAAAAAAAAAAAAQE9RVV9pOuysUUEGKq0u6ztFM0gTpoOHcHsTFQstA7+L9XTvxWEgL3RgNeq5KtKdODlxl62niV8dnQwlSoDSSWw==", "subType": "06" } } }, "gcp_int_det_explicit_id": { "kms": "gcp", "type": "int", "algo": "det", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "ARgjwAAAAAAAAAAAAAAAAAAQE9RVV9pOuysUUEGKq0u6ztFM0gTpoOHcHsTFQstA7+L9XTvxWEgL3RgNeq5KtKdODlxl62niV8dnQwlSoDSSWw==", "subType": "06" } } }, "gcp_int_det_explicit_altname": { "kms": "gcp", "type": "int", "algo": "det", "method": "explicit", "identifier": "altname", "allowed": true, "value": { "$binary": { "base64": "ARgjwAAAAAAAAAAAAAAAAAAQE9RVV9pOuysUUEGKq0u6ztFM0gTpoOHcHsTFQstA7+L9XTvxWEgL3RgNeq5KtKdODlxl62niV8dnQwlSoDSSWw==", "subType": "06" } } }, "gcp_timestamp_rand_auto_id": { "kms": "gcp", "type": "timestamp", "algo": "rand", "method": "auto", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "AhgjwAAAAAAAAAAAAAAAAAARLnk1LpJIriKr6iiY1yBDGnfkRaHNwWcQyL+mORtYC4+AQ6oMv0qpGrJxS2QCbYY1tGmAISqZHCIExCG+TIv4bw==", "subType": "06" } } }, "gcp_timestamp_rand_auto_altname": { "kms": "gcp", "type": "timestamp", "algo": "rand", "method": "auto", "identifier": "altname", "allowed": true, "value": { "$binary": { "base64": "AhgjwAAAAAAAAAAAAAAAAAARaqYXh9AVZI6gvRZrBwbprE5P3K5Qf4PIK1ca+mLRNOof0EExyAhtku7mYXusLeq0ww/tV6Zt1cA36KsT8a0Nog==", "subType": "06" } } }, "gcp_timestamp_rand_explicit_id": { "kms": "gcp", "type": "timestamp", "algo": "rand", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "AhgjwAAAAAAAAAAAAAAAAAARLXzBjkCN8BpfXDIrb94kuZCD07Uo/DMBfMIWQtAb1++tTheUoY2ClQz33Luh4g8NXwuMJ7h8ufE70N2+b1yrUg==", "subType": "06" } } }, "gcp_timestamp_rand_explicit_altname": { "kms": "gcp", "type": "timestamp", "algo": "rand", "method": "explicit", "identifier": "altname", "allowed": true, "value": { "$binary": { "base64": "AhgjwAAAAAAAAAAAAAAAAAARe44QH9ZvTAuHsWhEMoue8eHod+cJpBm+Kl/Xtw7NI/6UTOOHC5Kkg20EvX3+GwXdAGk0bUSCFiTZb/yPox1OlA==", "subType": "06" } } }, "gcp_timestamp_det_auto_id": { "kms": "gcp", "type": "timestamp", "algo": "det", "method": "auto", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "ARgjwAAAAAAAAAAAAAAAAAARzXjP6d6j/iQxiz1/TC/m+IfAGLFH9wY2ksS//i9x15QttlhcRrT3XmPvxaP5OjTHac4Gq3m2aXiJH56lETyl8A==", "subType": "06" } } }, "gcp_timestamp_det_explicit_id": { "kms": "gcp", "type": "timestamp", "algo": "det", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "ARgjwAAAAAAAAAAAAAAAAAARzXjP6d6j/iQxiz1/TC/m+IfAGLFH9wY2ksS//i9x15QttlhcRrT3XmPvxaP5OjTHac4Gq3m2aXiJH56lETyl8A==", "subType": "06" } } }, "gcp_timestamp_det_explicit_altname": { "kms": "gcp", "type": "timestamp", "algo": "det", "method": "explicit", "identifier": "altname", "allowed": true, "value": { "$binary": { "base64": "ARgjwAAAAAAAAAAAAAAAAAARzXjP6d6j/iQxiz1/TC/m+IfAGLFH9wY2ksS//i9x15QttlhcRrT3XmPvxaP5OjTHac4Gq3m2aXiJH56lETyl8A==", "subType": "06" } } }, "gcp_long_rand_auto_id": { "kms": "gcp", "type": "long", "algo": "rand", "method": "auto", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "AhgjwAAAAAAAAAAAAAAAAAASuGZs48eEyVBJ9vvM6cvRySfuR0WM4kL7lx52rSGXBKtkZywyP5rJwNtRn9WTBMDqc1O/4jUgYXpqHx39SLhUPA==", "subType": "06" } } }, "gcp_long_rand_auto_altname": { "kms": "gcp", "type": "long", "algo": "rand", "method": "auto", "identifier": "altname", "allowed": true, "value": { "$binary": { "base64": "AhgjwAAAAAAAAAAAAAAAAAAS/62F71oKTX1GlvOP89uNhXpIyLZ5OdnuLeM/hvL5HWyOudSb06cG3+xnPg3QgppAYFK5X2PGgrEcrA87AykLPg==", "subType": "06" } } }, "gcp_long_rand_explicit_id": { "kms": "gcp", "type": "long", "algo": "rand", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "AhgjwAAAAAAAAAAAAAAAAAASSgx+p4YzTvjZ+GCZCFHEKHNXJUSloPnLRHE4iJ515Epb8Tox7h8/aIAkB3ulnDS9BiT5UKdye2TWf8OBEwkXzg==", "subType": "06" } } }, "gcp_long_rand_explicit_altname": { "kms": "gcp", "type": "long", "algo": "rand", "method": "explicit", "identifier": "altname", "allowed": true, "value": { "$binary": { "base64": "AhgjwAAAAAAAAAAAAAAAAAAStqszyEfltpgd3aYeoyqaJX27OX861o06VhNX/N2fdSfKx0NQq/hWlWTkX6hK3hjCijiTtHmhFQR6QLkHD/6THw==", "subType": "06" } } }, "gcp_long_det_auto_id": { "kms": "gcp", "type": "long", "algo": "det", "method": "auto", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "ARgjwAAAAAAAAAAAAAAAAAAS0wJHtZKnxJlWnlSu0xuq7bZR25UdwcbdCRSaXBC0EXEFuqlzrZSn1lcwKPKGZQO8EQ6SdQDqK95alMLmM8eQrQ==", "subType": "06" } } }, "gcp_long_det_explicit_id": { "kms": "gcp", "type": "long", "algo": "det", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "ARgjwAAAAAAAAAAAAAAAAAAS0wJHtZKnxJlWnlSu0xuq7bZR25UdwcbdCRSaXBC0EXEFuqlzrZSn1lcwKPKGZQO8EQ6SdQDqK95alMLmM8eQrQ==", "subType": "06" } } }, "gcp_long_det_explicit_altname": { "kms": "gcp", "type": "long", "algo": "det", "method": "explicit", "identifier": "altname", "allowed": true, "value": { "$binary": { "base64": "ARgjwAAAAAAAAAAAAAAAAAAS0wJHtZKnxJlWnlSu0xuq7bZR25UdwcbdCRSaXBC0EXEFuqlzrZSn1lcwKPKGZQO8EQ6SdQDqK95alMLmM8eQrQ==", "subType": "06" } } }, "gcp_decimal_rand_auto_id": { "kms": "gcp", "type": "decimal", "algo": "rand", "method": "auto", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "AhgjwAAAAAAAAAAAAAAAAAATg4U3nbHBX/Az3ie2yurEIJO6cFryQWKiCpBbx1z0NF7RXd7kFC1XzaY6zcBjfl2AfRO8FFmgjTmFXb6gTRSSF0iAZJZTslfe3n6YFtwSKDI=", "subType": "06" } } }, "gcp_decimal_rand_auto_altname": { "kms": "gcp", "type": "decimal", "algo": "rand", "method": "auto", "identifier": "altname", "allowed": true, "value": { "$binary": { "base64": "AhgjwAAAAAAAAAAAAAAAAAATdSSyp0ewboV5zI3T3TV/FOrdx0UQbFHhqcH+yqpotoWPSw5dxE+BEoihYLeaPKuVU/rUIY4TUv05Egj7Ovg62Kpk3cPscxsGtE/T2Ppbt6o=", "subType": "06" } } }, "gcp_decimal_rand_explicit_id": { "kms": "gcp", "type": "decimal", "algo": "rand", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "AhgjwAAAAAAAAAAAAAAAAAATl7k20T22pf5Y9knVwIDyOIlbHyZBJqyi3Mai8APEZIYjpSKDKs8QNAH69CIjupyge8Izw4Cuch0bRrvMbp6YFfrUgk1JIQ4iLKkqqzHpBTY=", "subType": "06" } } }, "gcp_decimal_rand_explicit_altname": { "kms": "gcp", "type": "decimal", "algo": "rand", "method": "explicit", "identifier": "altname", "allowed": true, "value": { "$binary": { "base64": "AhgjwAAAAAAAAAAAAAAAAAATF7YLkhkuLhXdxrQk2fJTs128tRNYHeodkqw7ha/TxW3Czr5gE272gnkdzfNoS7uu9XwOr1yjrC6y/8gHALAWn77WvGrAlBktLQbIIinsuds=", "subType": "06" } } }, "gcp_decimal_det_explicit_id": { "kms": "gcp", "type": "decimal", "algo": "det", "method": "explicit", "identifier": "id", "allowed": false, "value": { "$numberDecimal": "1.234" } }, "gcp_decimal_det_explicit_altname": { "kms": "gcp", "type": "decimal", "algo": "det", "method": "explicit", "identifier": "altname", "allowed": false, "value": { "$numberDecimal": "1.234" } }, "gcp_minKey_rand_explicit_id": { "kms": "gcp", "type": "minKey", "algo": "rand", "method": "explicit", "identifier": "id", "allowed": false, "value": { "$minKey": 1 } }, "gcp_minKey_rand_explicit_altname": { "kms": "gcp", "type": "minKey", "algo": "rand", "method": "explicit", "identifier": "altname", "allowed": false, "value": { "$minKey": 1 } }, "gcp_minKey_det_explicit_id": { "kms": "gcp", "type": "minKey", "algo": "det", "method": "explicit", "identifier": "id", "allowed": false, "value": { "$minKey": 1 } }, "gcp_minKey_det_explicit_altname": { "kms": "gcp", "type": "minKey", "algo": "det", "method": "explicit", "identifier": "altname", "allowed": false, "value": { "$minKey": 1 } }, "gcp_maxKey_rand_explicit_id": { "kms": "gcp", "type": "maxKey", "algo": "rand", "method": "explicit", "identifier": "id", "allowed": false, "value": { "$maxKey": 1 } }, "gcp_maxKey_rand_explicit_altname": { "kms": "gcp", "type": "maxKey", "algo": "rand", "method": "explicit", "identifier": "altname", "allowed": false, "value": { "$maxKey": 1 } }, "gcp_maxKey_det_explicit_id": { "kms": "gcp", "type": "maxKey", "algo": "det", "method": "explicit", "identifier": "id", "allowed": false, "value": { "$maxKey": 1 } }, "gcp_maxKey_det_explicit_altname": { "kms": "gcp", "type": "maxKey", "algo": "det", "method": "explicit", "identifier": "altname", "allowed": false, "value": { "$maxKey": 1 } }, "kmip_double_rand_auto_id": { "kms": "kmip", "type": "double", "algo": "rand", "method": "auto", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "AijCDwAAAAAAAAAAAAAAAAAB1hL/nPkpQtqxQUANbIJr30PQ98vPvaoy4JWUoElOL+cCnrSra3o7W+12dydy0rCS2EKrVm7Fw0C8L9nf1hpWjw==", "subType": "06" } } }, "kmip_double_rand_auto_altname": { "kms": "kmip", "type": "double", "algo": "rand", "method": "auto", "identifier": "altname", "allowed": true, "value": { "$binary": { "base64": "AijCDwAAAAAAAAAAAAAAAAABxlcphy2SxXlkRBvO1Z3nNUqchmeOhIhkdYBbbW7CwYeLVRDciXFsZN73Nb9Bm+W4IpUNpo6mqFEtfjevIjtFyg==", "subType": "06" } } }, "kmip_double_rand_explicit_id": { "kms": "kmip", "type": "double", "algo": "rand", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "AijCDwAAAAAAAAAAAAAAAAABx5AfRSiblFc1DGwxRIaUSP2kaM76ryzPUKL9KnEgnX1kjIlFz5B15uMht2cxdrntHFe1qZZk8V9PxTBpWZhJ8Q==", "subType": "06" } } }, "kmip_double_rand_explicit_altname": { "kms": "kmip", "type": "double", "algo": "rand", "method": "explicit", "identifier": "altname", "allowed": true, "value": { "$binary": { "base64": "AijCDwAAAAAAAAAAAAAAAAABXUC9v9HPrmU9tINzFmr2sQM9f7GHDus+y5T4pWX28PRtfnTysN/ANCfB9RosoR/wuKsbznwwD2JfSzOvlKo3PQ==", "subType": "06" } } }, "kmip_double_det_explicit_id": { "kms": "kmip", "type": "double", "algo": "det", "method": "explicit", "identifier": "id", "allowed": false, "value": { "$numberDouble": "1.2339999999999999858" } }, "kmip_double_det_explicit_altname": { "kms": "kmip", "type": "double", "algo": "det", "method": "explicit", "identifier": "altname", "allowed": false, "value": { "$numberDouble": "1.2339999999999999858" } }, "kmip_string_rand_auto_id": { "kms": "kmip", "type": "string", "algo": "rand", "method": "auto", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "AijCDwAAAAAAAAAAAAAAAAACGHmqW1qbfqVlfB0x0CkXCk9smhs3yXsxJ/8eypSgbDQqVLSW2nf5bbHpnoCHHNtQ7I7ZBXzPzDLH2GgMJpopeQ==", "subType": "06" } } }, "kmip_string_rand_auto_altname": { "kms": "kmip", "type": "string", "algo": "rand", "method": "auto", "identifier": "altname", "allowed": true, "value": { "$binary": { "base64": "AijCDwAAAAAAAAAAAAAAAAAC9BJTD1pEMbslAjbJYt7yx/jzKkcZF3axu96+NYwp8afUCjXG5TOUZzODOwkbJuWgr7DBxa2GkZTvaAEk86h+Ow==", "subType": "06" } } }, "kmip_string_rand_explicit_id": { "kms": "kmip", "type": "string", "algo": "rand", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "AijCDwAAAAAAAAAAAAAAAAACQlG28ECy8KHXC7GEPdC8+raBo2RMJwl5pofcPaTGkPUEbkreguMd1mYctNb90vXxby1nNeJY4o5zJJCMiNhNXg==", "subType": "06" } } }, "kmip_string_rand_explicit_altname": { "kms": "kmip", "type": "string", "algo": "rand", "method": "explicit", "identifier": "altname", "allowed": true, "value": { "$binary": { "base64": "AijCDwAAAAAAAAAAAAAAAAACbWuK+3nzeKSNVjmgHb0Ii7rA+CsAd+gYubPiMiHXZwE/o6i9FYWN+t/VK3p4K0CwIi6q3cycrMb2IgcvM27Q7Q==", "subType": "06" } } }, "kmip_string_det_auto_id": { "kms": "kmip", "type": "string", "algo": "det", "method": "auto", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "ASjCDwAAAAAAAAAAAAAAAAAC5OZgr9keCXOIj5Fi06i4win1xt7gpsyPA4Os+HdFn1MIP9tnktvWNRb8Rqhuj2O9KO83brx74Hu3EQ4nT6uCMw==", "subType": "06" } } }, "kmip_string_det_explicit_id": { "kms": "kmip", "type": "string", "algo": "det", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "ASjCDwAAAAAAAAAAAAAAAAAC5OZgr9keCXOIj5Fi06i4win1xt7gpsyPA4Os+HdFn1MIP9tnktvWNRb8Rqhuj2O9KO83brx74Hu3EQ4nT6uCMw==", "subType": "06" } } }, "kmip_string_det_explicit_altname": { "kms": "kmip", "type": "string", "algo": "det", "method": "explicit", "identifier": "altname", "allowed": true, "value": { "$binary": { "base64": "ASjCDwAAAAAAAAAAAAAAAAAC5OZgr9keCXOIj5Fi06i4win1xt7gpsyPA4Os+HdFn1MIP9tnktvWNRb8Rqhuj2O9KO83brx74Hu3EQ4nT6uCMw==", "subType": "06" } } }, "kmip_object_rand_auto_id": { "kms": "kmip", "type": "object", "algo": "rand", "method": "auto", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "AijCDwAAAAAAAAAAAAAAAAADh2nGqaAUwHDRVjqYpj8JAPH7scmiHp1Z9SGBZQ6Fapxm+zWDdTBHyitM9U69BctJ5DaaafyqFOj5yr6sJ+ebJQ==", "subType": "06" } } }, "kmip_object_rand_auto_altname": { "kms": "kmip", "type": "object", "algo": "rand", "method": "auto", "identifier": "altname", "allowed": true, "value": { "$binary": { "base64": "AijCDwAAAAAAAAAAAAAAAAAD1YhOKyNle4y0Qbeio1HlCULLeTCALCLgKSITd50bilD+oDyqQawixJAwphcdjhLdFzbFwst5RWqpsiWMPHx4hQ==", "subType": "06" } } }, "kmip_object_rand_explicit_id": { "kms": "kmip", "type": "object", "algo": "rand", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "AijCDwAAAAAAAAAAAAAAAAADveILoWFgX7AhUWCv8UL52TUa75qHuoNadnTQydJlqd6PVmtRKj+8vS7VwxNWPaH4wB1Tk7emMyFEbZpvvzjxqQ==", "subType": "06" } } }, "kmip_object_rand_explicit_altname": { "kms": "kmip", "type": "object", "algo": "rand", "method": "explicit", "identifier": "altname", "allowed": true, "value": { "$binary": { "base64": "AijCDwAAAAAAAAAAAAAAAAADB/LN9V/4SROJn+ESHRLM7wwcUltQUx3+LbbYXjPDXiiV14HK76Iyy6ZxJ+M5qC9bRj3afhTKuWLBblB8WwksOg==", "subType": "06" } } }, "kmip_object_det_explicit_id": { "kms": "kmip", "type": "object", "algo": "det", "method": "explicit", "identifier": "id", "allowed": false, "value": { "x": { "$numberInt": "1" } } }, "kmip_object_det_explicit_altname": { "kms": "kmip", "type": "object", "algo": "det", "method": "explicit", "identifier": "altname", "allowed": false, "value": { "x": { "$numberInt": "1" } } }, "kmip_array_rand_auto_id": { "kms": "kmip", "type": "array", "algo": "rand", "method": "auto", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "AijCDwAAAAAAAAAAAAAAAAAEasWXQam8XtOkSO0nEttMCQ0iZ4V8DDmhMKyQDFDsiNHyF2h98Ya/xFv4ZSlbpGWXPBvBATEGgov/PDg2vhVi53y4Pk33RHfY60hABuksp3o=", "subType": "06" } } }, "kmip_array_rand_auto_altname": { "kms": "kmip", "type": "array", "algo": "rand", "method": "auto", "identifier": "altname", "allowed": true, "value": { "$binary": { "base64": "AijCDwAAAAAAAAAAAAAAAAAEj3A1DYSEHm/3SlEmusA+pewxRPUoZ2NAjs60ioEBlCw9n6yiiB+X8d/w40TKsjZcOSfh05NC0z3gnpqQvrNolkxkvi9dmFiZeiiv5vBZUPI=", "subType": "06" } } }, "kmip_array_rand_explicit_id": { "kms": "kmip", "type": "array", "algo": "rand", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "AijCDwAAAAAAAAAAAAAAAAAEqeJW+L6lP0bn5QcD0FMI0C8vv2n5kV7SKgqKi1o5mxaxmp3Cjlspf7yumfSiQ5js6G9yJVAvHuxlqv14UFyR9RgXS0PIA8WzsAqkL0sJSw0=", "subType": "06" } } }, "kmip_array_rand_explicit_altname": { "kms": "kmip", "type": "array", "algo": "rand", "method": "explicit", "identifier": "altname", "allowed": true, "value": { "$binary": { "base64": "AijCDwAAAAAAAAAAAAAAAAAEnPlPwy0B1VKuNum1GzkZwQjZia5jNYL5bf/k+PbfhnToTRWGxx8+E3R7XXp6YT/rFkjPlzU8ww9+iZNo2oqNpYuHdrIC8ybhO6HZAlvcERo=", "subType": "06" } } }, "kmip_array_det_explicit_id": { "kms": "kmip", "type": "array", "algo": "det", "method": "explicit", "identifier": "id", "allowed": false, "value": [ { "$numberInt": "1" }, { "$numberInt": "2" }, { "$numberInt": "3" } ] }, "kmip_array_det_explicit_altname": { "kms": "kmip", "type": "array", "algo": "det", "method": "explicit", "identifier": "altname", "allowed": false, "value": [ { "$numberInt": "1" }, { "$numberInt": "2" }, { "$numberInt": "3" } ] }, "kmip_binData=00_rand_auto_id": { "kms": "kmip", "type": "binData=00", "algo": "rand", "method": "auto", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "AijCDwAAAAAAAAAAAAAAAAAFliNDZ6DmjoVcYQBCKDI9njpBsDELg+TD6XLF7xbZnMaJCCHLHr7w3x2/xFfrFSN44CtGAKOniYPCMAspaxHqOA==", "subType": "06" } } }, "kmip_binData=00_rand_auto_altname": { "kms": "kmip", "type": "binData=00", "algo": "rand", "method": "auto", "identifier": "altname", "allowed": true, "value": { "$binary": { "base64": "AijCDwAAAAAAAAAAAAAAAAAF/P8LPmHKGgG0l5/Xi7jdkwfxpGPxoY0417suCvN6zjM3JNdufytzkektrm9CbBb1SnZCGYF9c0FCMzFG+tN/dg==", "subType": "06" } } }, "kmip_binData=00_rand_explicit_id": { "kms": "kmip", "type": "binData=00", "algo": "rand", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "AijCDwAAAAAAAAAAAAAAAAAFWI0N4RbnYdEiFrzNpbRN9p+bSLm8Lthiu4K3/CvBg6GQpLMVQFhjW01Bud0lxpT2ohRnOK+ASUhiFcUU/t/lWQ==", "subType": "06" } } }, "kmip_binData=00_rand_explicit_altname": { "kms": "kmip", "type": "binData=00", "algo": "rand", "method": "explicit", "identifier": "altname", "allowed": true, "value": { "$binary": { "base64": "AijCDwAAAAAAAAAAAAAAAAAFQZvAtpY4cjEr1rJWVoUGaZKmzocSJ0muHose7Tk5kRDczjFa4Jcu4hN7JLM9qz2z4g+WJC3KQTdW4ZBXStke/Q==", "subType": "06" } } }, "kmip_binData=00_det_auto_id": { "kms": "kmip", "type": "binData=00", "algo": "det", "method": "auto", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "ASjCDwAAAAAAAAAAAAAAAAAFohIHrvzu8xLxVHsnYEDhZmv8BpEoEtFSjMUQzvBLUInvvTuU/rOzlVL88CkAEII7M3hcvrz8FKY7b7lC1veoYg==", "subType": "06" } } }, "kmip_binData=00_det_explicit_id": { "kms": "kmip", "type": "binData=00", "algo": "det", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "ASjCDwAAAAAAAAAAAAAAAAAFohIHrvzu8xLxVHsnYEDhZmv8BpEoEtFSjMUQzvBLUInvvTuU/rOzlVL88CkAEII7M3hcvrz8FKY7b7lC1veoYg==", "subType": "06" } } }, "kmip_binData=00_det_explicit_altname": { "kms": "kmip", "type": "binData=00", "algo": "det", "method": "explicit", "identifier": "altname", "allowed": true, "value": { "$binary": { "base64": "ASjCDwAAAAAAAAAAAAAAAAAFohIHrvzu8xLxVHsnYEDhZmv8BpEoEtFSjMUQzvBLUInvvTuU/rOzlVL88CkAEII7M3hcvrz8FKY7b7lC1veoYg==", "subType": "06" } } }, "kmip_binData=04_rand_auto_id": { "kms": "kmip", "type": "binData=04", "algo": "rand", "method": "auto", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "AijCDwAAAAAAAAAAAAAAAAAFn7rhdO8tYq77uVxcqd9Qjz84Yg7JnJMYf0ULTMTh1vJHacckkhXw+8fIMMiAKwuOVwGkMAtu5RBvrFqdfxryCg8RLTxu1YYVthufiClEIS0=", "subType": "06" } } }, "kmip_binData=04_rand_auto_altname": { "kms": "kmip", "type": "binData=04", "algo": "rand", "method": "auto", "identifier": "altname", "allowed": true, "value": { "$binary": { "base64": "AijCDwAAAAAAAAAAAAAAAAAFwwXQx9dKyoyHq7GBMmHzYe9ysoJK/f/ZWzA6nErau9MtX1gqi7VRsYqkamb47/zVbsLZwPMmdgNyPxEh3kqbV2D61t5RG2A3VeqhO1pTF8c=", "subType": "06" } } }, "kmip_binData=04_rand_explicit_id": { "kms": "kmip", "type": "binData=04", "algo": "rand", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "AijCDwAAAAAAAAAAAAAAAAAFALeGeinJ8DE+WZniLdCIW2gfJUj445Ukp9PvRLgBXLGedl8mIXlLF2eu3BA9vP6s5y9w6peQjhn+oEofrsUVYD2duyzeIRMKgNiNchjf6TU=", "subType": "06" } } }, "kmip_binData=04_rand_explicit_altname": { "kms": "kmip", "type": "binData=04", "algo": "rand", "method": "explicit", "identifier": "altname", "allowed": true, "value": { "$binary": { "base64": "AijCDwAAAAAAAAAAAAAAAAAF06Fx8CO3OSKE3fGri0VwK0e22YiG9LH2QkDTsRdFbT2lBm+bDD9FrEY8vKWS5RljMuysaxjBOzZ98d2LEs6k8LMOm83Nz/RESe4ZbbcfdQ0=", "subType": "06" } } }, "kmip_binData=04_det_auto_id": { "kms": "kmip", "type": "binData=04", "algo": "det", "method": "auto", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "ASjCDwAAAAAAAAAAAAAAAAAFzmZI909fJgxOykJtvOlv5LsX8z6BxUX2Xg5TsIwOxJMPSC8usm/zR7sZawoVBOuJxtNVLY/8oNP/4pFtAmQo02bUOtTo1yxNz/IZa9x+Q5E=", "subType": "06" } } }, "kmip_binData=04_det_explicit_id": { "kms": "kmip", "type": "binData=04", "algo": "det", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "ASjCDwAAAAAAAAAAAAAAAAAFzmZI909fJgxOykJtvOlv5LsX8z6BxUX2Xg5TsIwOxJMPSC8usm/zR7sZawoVBOuJxtNVLY/8oNP/4pFtAmQo02bUOtTo1yxNz/IZa9x+Q5E=", "subType": "06" } } }, "kmip_binData=04_det_explicit_altname": { "kms": "kmip", "type": "binData=04", "algo": "det", "method": "explicit", "identifier": "altname", "allowed": true, "value": { "$binary": { "base64": "ASjCDwAAAAAAAAAAAAAAAAAFzmZI909fJgxOykJtvOlv5LsX8z6BxUX2Xg5TsIwOxJMPSC8usm/zR7sZawoVBOuJxtNVLY/8oNP/4pFtAmQo02bUOtTo1yxNz/IZa9x+Q5E=", "subType": "06" } } }, "kmip_undefined_rand_explicit_id": { "kms": "kmip", "type": "undefined", "algo": "rand", "method": "explicit", "identifier": "id", "allowed": false, "value": { "$undefined": true } }, "kmip_undefined_rand_explicit_altname": { "kms": "kmip", "type": "undefined", "algo": "rand", "method": "explicit", "identifier": "altname", "allowed": false, "value": { "$undefined": true } }, "kmip_undefined_det_explicit_id": { "kms": "kmip", "type": "undefined", "algo": "det", "method": "explicit", "identifier": "id", "allowed": false, "value": { "$undefined": true } }, "kmip_undefined_det_explicit_altname": { "kms": "kmip", "type": "undefined", "algo": "det", "method": "explicit", "identifier": "altname", "allowed": false, "value": { "$undefined": true } }, "kmip_objectId_rand_auto_id": { "kms": "kmip", "type": "objectId", "algo": "rand", "method": "auto", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "AijCDwAAAAAAAAAAAAAAAAAHZFzE908RuO5deEt3t2QQdT12ybwqbm8D+sMJrdKt2Wp4kVPsw4ocAGGsRYN6VXe46P5fmyG5HqVWn0hkflZnQg==", "subType": "06" } } }, "kmip_objectId_rand_auto_altname": { "kms": "kmip", "type": "objectId", "algo": "rand", "method": "auto", "identifier": "altname", "allowed": true, "value": { "$binary": { "base64": "AijCDwAAAAAAAAAAAAAAAAAH3dPKyCCStvOtVGzlgIS33fsl8OAwQblt9i21pOVuLiliY1Tup9EtkSic88+nNEtXnq9gRknRzLthXv/k1ql+7Q==", "subType": "06" } } }, "kmip_objectId_rand_explicit_id": { "kms": "kmip", "type": "objectId", "algo": "rand", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "AijCDwAAAAAAAAAAAAAAAAAHcEjxVfHDSfLzFxAuK/rs/Pn/XV7jLkgKXZYeY0PNlRi1MHojN2AvQqI3J2rOvAjuYfikGcpvGPp/goqUbV9HYw==", "subType": "06" } } }, "kmip_objectId_rand_explicit_altname": { "kms": "kmip", "type": "objectId", "algo": "rand", "method": "explicit", "identifier": "altname", "allowed": true, "value": { "$binary": { "base64": "AijCDwAAAAAAAAAAAAAAAAAHX65sNHnRYpx3VbWPCdQyFe7u0Y5ItabLEduqDeVsPk/iK4X3GjCSHQfw1yPi+CA+/veVpgdonwws6RiYV4ZZ5Q==", "subType": "06" } } }, "kmip_objectId_det_auto_id": { "kms": "kmip", "type": "objectId", "algo": "det", "method": "auto", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "ASjCDwAAAAAAAAAAAAAAAAAHKU7mcdGEq2WGrDB6TicipLQstAk6G3PkiNt5F3bMavpKLjz04UBrd8aWGVG2gJTTON1UKRztiYFgRvb8f+LK/Q==", "subType": "06" } } }, "kmip_objectId_det_explicit_id": { "kms": "kmip", "type": "objectId", "algo": "det", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "ASjCDwAAAAAAAAAAAAAAAAAHKU7mcdGEq2WGrDB6TicipLQstAk6G3PkiNt5F3bMavpKLjz04UBrd8aWGVG2gJTTON1UKRztiYFgRvb8f+LK/Q==", "subType": "06" } } }, "kmip_objectId_det_explicit_altname": { "kms": "kmip", "type": "objectId", "algo": "det", "method": "explicit", "identifier": "altname", "allowed": true, "value": { "$binary": { "base64": "ASjCDwAAAAAAAAAAAAAAAAAHKU7mcdGEq2WGrDB6TicipLQstAk6G3PkiNt5F3bMavpKLjz04UBrd8aWGVG2gJTTON1UKRztiYFgRvb8f+LK/Q==", "subType": "06" } } }, "kmip_bool_rand_auto_id": { "kms": "kmip", "type": "bool", "algo": "rand", "method": "auto", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "AijCDwAAAAAAAAAAAAAAAAAIw/xgJlKEvErmVtue3X3RFsOI2sttAbxnzh1INc9GUQ2vok1VwYt9k88RxMPiOwMAZG7P1MlAdx7zt865onPKOw==", "subType": "06" } } }, "kmip_bool_rand_auto_altname": { "kms": "kmip", "type": "bool", "algo": "rand", "method": "auto", "identifier": "altname", "allowed": true, "value": { "$binary": { "base64": "AijCDwAAAAAAAAAAAAAAAAAIn8IuzlNHbpTgXOd1wEp364zJOBxj2Zf7a9B5osUV1sDY0G1OVpEnuDvZeUsdiUSyRjTTxzyuD/KZlKZ3+qrnrA==", "subType": "06" } } }, "kmip_bool_rand_explicit_id": { "kms": "kmip", "type": "bool", "algo": "rand", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "AijCDwAAAAAAAAAAAAAAAAAI3Nz9PdjUYQRGfTtvYSR8EQuUKFL0wdlEdfSCTBmMBhBPuuF9KxqCgy+ldVu1DRRgg3346DOKEEtE9BJPPInJ6Q==", "subType": "06" } } }, "kmip_bool_rand_explicit_altname": { "kms": "kmip", "type": "bool", "algo": "rand", "method": "explicit", "identifier": "altname", "allowed": true, "value": { "$binary": { "base64": "AijCDwAAAAAAAAAAAAAAAAAIEGjqoerIZBk8Rw+YTO7jFKWzagDS8mEpD+9Wm1Q0r0ZHUmV0dQZcIqRV4oUk8U8uHUn0N3t2qGLr+rhUs4GH/g==", "subType": "06" } } }, "kmip_bool_det_explicit_id": { "kms": "kmip", "type": "bool", "algo": "det", "method": "explicit", "identifier": "id", "allowed": false, "value": true }, "kmip_bool_det_explicit_altname": { "kms": "kmip", "type": "bool", "algo": "det", "method": "explicit", "identifier": "altname", "allowed": false, "value": true }, "kmip_date_rand_auto_id": { "kms": "kmip", "type": "date", "algo": "rand", "method": "auto", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "AijCDwAAAAAAAAAAAAAAAAAJgr0v4xetUXjlLcPcyKv/rzjtWOKp9CZJcm23Noglu5RR/rXJS0qKI+W9MmJ64TMf27KvaJ0UXwfTRrvOC1plCg==", "subType": "06" } } }, "kmip_date_rand_auto_altname": { "kms": "kmip", "type": "date", "algo": "rand", "method": "auto", "identifier": "altname", "allowed": true, "value": { "$binary": { "base64": "AijCDwAAAAAAAAAAAAAAAAAJoeysAaiPsVK+JL1P1vD/9xF92m5kKidUdn6yklPlSKN4VVEBTymDetTLujULs1u1TlrS71jVLxo3xEwpG/KQvg==", "subType": "06" } } }, "kmip_date_rand_explicit_id": { "kms": "kmip", "type": "date", "algo": "rand", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "AijCDwAAAAAAAAAAAAAAAAAJVwu4+Su0DktpnZvzTBHYpWbWTq5gho/SLijrcIrFJcvq4YrjjPCXv+odCl95tkH+J1RlJdQ5Cr0umEIazLa6GA==", "subType": "06" } } }, "kmip_date_rand_explicit_altname": { "kms": "kmip", "type": "date", "algo": "rand", "method": "explicit", "identifier": "altname", "allowed": true, "value": { "$binary": { "base64": "AijCDwAAAAAAAAAAAAAAAAAJWTYpjbDkIf82QXHMGrvd0SqhP8cBIakfYJf5aNcNrs86vxRhiG3KwETWPeOOlPZ6n1WjE2bOLB+DJTAxmJvahA==", "subType": "06" } } }, "kmip_date_det_auto_id": { "kms": "kmip", "type": "date", "algo": "det", "method": "auto", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "ASjCDwAAAAAAAAAAAAAAAAAJ/+sQrUqQh+JADSVIKM0d68gDUhDy37M1z1uvROzQw6hUAbQeD0DWdztADKg560UTPM4uOgH4NAyhLyBLMrWWHg==", "subType": "06" } } }, "kmip_date_det_explicit_id": { "kms": "kmip", "type": "date", "algo": "det", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "ASjCDwAAAAAAAAAAAAAAAAAJ/+sQrUqQh+JADSVIKM0d68gDUhDy37M1z1uvROzQw6hUAbQeD0DWdztADKg560UTPM4uOgH4NAyhLyBLMrWWHg==", "subType": "06" } } }, "kmip_date_det_explicit_altname": { "kms": "kmip", "type": "date", "algo": "det", "method": "explicit", "identifier": "altname", "allowed": true, "value": { "$binary": { "base64": "ASjCDwAAAAAAAAAAAAAAAAAJ/+sQrUqQh+JADSVIKM0d68gDUhDy37M1z1uvROzQw6hUAbQeD0DWdztADKg560UTPM4uOgH4NAyhLyBLMrWWHg==", "subType": "06" } } }, "kmip_null_rand_explicit_id": { "kms": "kmip", "type": "null", "algo": "rand", "method": "explicit", "identifier": "id", "allowed": false, "value": null }, "kmip_null_rand_explicit_altname": { "kms": "kmip", "type": "null", "algo": "rand", "method": "explicit", "identifier": "altname", "allowed": false, "value": null }, "kmip_null_det_explicit_id": { "kms": "kmip", "type": "null", "algo": "det", "method": "explicit", "identifier": "id", "allowed": false, "value": null }, "kmip_null_det_explicit_altname": { "kms": "kmip", "type": "null", "algo": "det", "method": "explicit", "identifier": "altname", "allowed": false, "value": null }, "kmip_regex_rand_auto_id": { "kms": "kmip", "type": "regex", "algo": "rand", "method": "auto", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "AijCDwAAAAAAAAAAAAAAAAALi8avMfpxSlDsSTqdxO8O2B1M79gOElyUIdXySQo7mvgHlf4oHQ7r94lL9dnsA2t/jmUmBKoGypaUQUSQE+9x+A==", "subType": "06" } } }, "kmip_regex_rand_auto_altname": { "kms": "kmip", "type": "regex", "algo": "rand", "method": "auto", "identifier": "altname", "allowed": true, "value": { "$binary": { "base64": "AijCDwAAAAAAAAAAAAAAAAALfHerZ/KolaBrb5qi3SpeNVW+i/nh5mkcdtQg5f1pHePr68KryHucM/XDAzbMqrPlag2/41STGYdJqzYO7Mbppg==", "subType": "06" } } }, "kmip_regex_rand_explicit_id": { "kms": "kmip", "type": "regex", "algo": "rand", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "AijCDwAAAAAAAAAAAAAAAAALOhKDVAN5cuDyB1EuRFWgKKt0wGJ63E5pPY8Tq2TXMNgCxUUc5O+TE+Ux4ls/uMyOBA3gPzND0CZKiru0i7ACUQ==", "subType": "06" } } }, "kmip_regex_rand_explicit_altname": { "kms": "kmip", "type": "regex", "algo": "rand", "method": "explicit", "identifier": "altname", "allowed": true, "value": { "$binary": { "base64": "AijCDwAAAAAAAAAAAAAAAAALK3Hg8xX9gX+d3vKh7aosRP9CS2CIFeG9sapZv3OAPv1eWjY62Cp/G16kJ0BQt33RYD+DzD3gWupfUSyNZR0gng==", "subType": "06" } } }, "kmip_regex_det_auto_id": { "kms": "kmip", "type": "regex", "algo": "det", "method": "auto", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "ASjCDwAAAAAAAAAAAAAAAAALaQXA8rItT7ELVxO8XtAWdHuiXFFPmnMhS5PMrUy/6mRtbq4fvU9dascW7ozonKOh8ad6+MIT7B/STv9dVBF4Kw==", "subType": "06" } } }, "kmip_regex_det_explicit_id": { "kms": "kmip", "type": "regex", "algo": "det", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "ASjCDwAAAAAAAAAAAAAAAAALaQXA8rItT7ELVxO8XtAWdHuiXFFPmnMhS5PMrUy/6mRtbq4fvU9dascW7ozonKOh8ad6+MIT7B/STv9dVBF4Kw==", "subType": "06" } } }, "kmip_regex_det_explicit_altname": { "kms": "kmip", "type": "regex", "algo": "det", "method": "explicit", "identifier": "altname", "allowed": true, "value": { "$binary": { "base64": "ASjCDwAAAAAAAAAAAAAAAAALaQXA8rItT7ELVxO8XtAWdHuiXFFPmnMhS5PMrUy/6mRtbq4fvU9dascW7ozonKOh8ad6+MIT7B/STv9dVBF4Kw==", "subType": "06" } } }, "kmip_dbPointer_rand_auto_id": { "kms": "kmip", "type": "dbPointer", "algo": "rand", "method": "auto", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "AijCDwAAAAAAAAAAAAAAAAAMoGkfmmUWTI+0aW7jVyCJ5Dgru1SCXBUmJSRzDL0D57pNruQ+79tVVcI6Uz5j87DhZFxShHbPjj583vLOOBNM3WGzZCpqH3serhHTWvXK+NM=", "subType": "06" } } }, "kmip_dbPointer_rand_auto_altname": { "kms": "kmip", "type": "dbPointer", "algo": "rand", "method": "auto", "identifier": "altname", "allowed": true, "value": { "$binary": { "base64": "AijCDwAAAAAAAAAAAAAAAAAMwu1WaRhhv43xgxLNxuenbND9M6mxGtCs9o4J5+yfL95XNB9Daie3RcLlyngz0pncBie6IqjhTycXsxTLQ94Jdg6m5GD5cU541LYKvhbv5f4=", "subType": "06" } } }, "kmip_dbPointer_rand_explicit_id": { "kms": "kmip", "type": "dbPointer", "algo": "rand", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "AijCDwAAAAAAAAAAAAAAAAAM+CIoCAisUwhhJtWQLolxQGQWafniwYyvaJQHmJC94Uwbf1gPfhMR42v2VtrmIVP0J0BaP/xf0cco2/qWRdKGZpgkK2CK6M972NtnZ/2x03A=", "subType": "06" } } }, "kmip_dbPointer_rand_explicit_altname": { "kms": "kmip", "type": "dbPointer", "algo": "rand", "method": "explicit", "identifier": "altname", "allowed": true, "value": { "$binary": { "base64": "AijCDwAAAAAAAAAAAAAAAAAMjbeE9+EaJYjGfeAuxsV8teOdsW8bfnlkvji/tE11Zq89UMGx+oUsZzeLjUgVZ5nxsZKCZjEAq+DPnwFVC+MgqNeqWL7fRChODFlPGH2ZC+8=", "subType": "06" } } }, "kmip_dbPointer_det_auto_id": { "kms": "kmip", "type": "dbPointer", "algo": "det", "method": "auto", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "ASjCDwAAAAAAAAAAAAAAAAAM5B+fjbjYCZzCYUu4N/pJI3srCCXN+OCCHweeweqmpIEmB7yw87bQRIMGtCm6HuekcZ5J5q+nY5AQb0du/wh1YIoOrC3u4w7ZcLHkDmuAJPg=", "subType": "06" } } }, "kmip_dbPointer_det_explicit_id": { "kms": "kmip", "type": "dbPointer", "algo": "det", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "ASjCDwAAAAAAAAAAAAAAAAAM5B+fjbjYCZzCYUu4N/pJI3srCCXN+OCCHweeweqmpIEmB7yw87bQRIMGtCm6HuekcZ5J5q+nY5AQb0du/wh1YIoOrC3u4w7ZcLHkDmuAJPg=", "subType": "06" } } }, "kmip_dbPointer_det_explicit_altname": { "kms": "kmip", "type": "dbPointer", "algo": "det", "method": "explicit", "identifier": "altname", "allowed": true, "value": { "$binary": { "base64": "ASjCDwAAAAAAAAAAAAAAAAAM5B+fjbjYCZzCYUu4N/pJI3srCCXN+OCCHweeweqmpIEmB7yw87bQRIMGtCm6HuekcZ5J5q+nY5AQb0du/wh1YIoOrC3u4w7ZcLHkDmuAJPg=", "subType": "06" } } }, "kmip_javascript_rand_auto_id": { "kms": "kmip", "type": "javascript", "algo": "rand", "method": "auto", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "AijCDwAAAAAAAAAAAAAAAAANuzlkWs/c8xArrAxPgYuCeShjj1zCfIMHOTPohspcyNofo9iY3P5MlhEOprZDiS8dBFg6EB7fZDzDdczx6VCN2A==", "subType": "06" } } }, "kmip_javascript_rand_auto_altname": { "kms": "kmip", "type": "javascript", "algo": "rand", "method": "auto", "identifier": "altname", "allowed": true, "value": { "$binary": { "base64": "AijCDwAAAAAAAAAAAAAAAAANwJ72y7UqCBJh1NwVRiE3vU1ex7FMv/X5YWCMuO9MHPMo4g1V5eaO4KfOr+K8+9NtkflgMpeDkvwP92rfR5ud5Q==", "subType": "06" } } }, "kmip_javascript_rand_explicit_id": { "kms": "kmip", "type": "javascript", "algo": "rand", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "AijCDwAAAAAAAAAAAAAAAAANj5q+888itRnLsw9PNGsBLhgqpvem5IJBOE2292r6zwjVueoEK/2I2PesRnn0esnkwdia1ADoMkcLUegwcFRkWQ==", "subType": "06" } } }, "kmip_javascript_rand_explicit_altname": { "kms": "kmip", "type": "javascript", "algo": "rand", "method": "explicit", "identifier": "altname", "allowed": true, "value": { "$binary": { "base64": "AijCDwAAAAAAAAAAAAAAAAANnvbnmApys7OIe8LGTsZKDG1F1G1SI/rfZVmF6q1fq5U7feYPp1ejb2t2S2+v7LfcOHytsQWGcYuWCDcl+vosvQ==", "subType": "06" } } }, "kmip_javascript_det_auto_id": { "kms": "kmip", "type": "javascript", "algo": "det", "method": "auto", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "ASjCDwAAAAAAAAAAAAAAAAANOR9R/Da8j5iVxllLiGFlv4U/bVn/PyN9/5WeGJkGJeE/j/osKrKx6IL1igI0YVI+pKKzsINqJGIv+bJX0s7MNw==", "subType": "06" } } }, "kmip_javascript_det_explicit_id": { "kms": "kmip", "type": "javascript", "algo": "det", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "ASjCDwAAAAAAAAAAAAAAAAANOR9R/Da8j5iVxllLiGFlv4U/bVn/PyN9/5WeGJkGJeE/j/osKrKx6IL1igI0YVI+pKKzsINqJGIv+bJX0s7MNw==", "subType": "06" } } }, "kmip_javascript_det_explicit_altname": { "kms": "kmip", "type": "javascript", "algo": "det", "method": "explicit", "identifier": "altname", "allowed": true, "value": { "$binary": { "base64": "ASjCDwAAAAAAAAAAAAAAAAANOR9R/Da8j5iVxllLiGFlv4U/bVn/PyN9/5WeGJkGJeE/j/osKrKx6IL1igI0YVI+pKKzsINqJGIv+bJX0s7MNw==", "subType": "06" } } }, "kmip_symbol_rand_auto_id": { "kms": "kmip", "type": "symbol", "algo": "rand", "method": "auto", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "AijCDwAAAAAAAAAAAAAAAAAOe+vXpJSkmBM3WkxZrn4ea9/C6iNyMXWUzkQIzIYlnbkyu8od8nfOdhobUhoFxcKnvdaxN1s5NhJ1FA97RN/upGYN+AI/7cTCElmFSpdSvkI=", "subType": "06" } } }, "kmip_symbol_rand_auto_altname": { "kms": "kmip", "type": "symbol", "algo": "rand", "method": "auto", "identifier": "altname", "allowed": true, "value": { "$binary": { "base64": "AijCDwAAAAAAAAAAAAAAAAAOPpCgK6Hc/M2elOJkwIU9J7PZa+h1chody2yvfDu/UlB6T5sxnEZ6aEY/ISNLhJlhsRzuApSgFOmnrcG6Eg9VnSKin2yK0ll+VFxQEDHAcSA=", "subType": "06" } } }, "kmip_symbol_rand_explicit_id": { "kms": "kmip", "type": "symbol", "algo": "rand", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "AijCDwAAAAAAAAAAAAAAAAAOVoHX9GaOn71L5D9TpZmmxkx/asr0FHCLG5ZgLLA04yIhZHsDjt2DiVGGO/Mf4KwvoBn7Cf08qMhW7rQh2LgvvSLBO3zbw5l+MZ/bSn+Jylo=", "subType": "06" } } }, "kmip_symbol_rand_explicit_altname": { "kms": "kmip", "type": "symbol", "algo": "rand", "method": "explicit", "identifier": "altname", "allowed": true, "value": { "$binary": { "base64": "AijCDwAAAAAAAAAAAAAAAAAOPobmcO/I4QObtCUEmGWpSCJ6tlYyhbO59q78LZBucSNl7DSkf/13tOJ9t+WKXACcMKVMmfPoFsgHbVj1nKWULBT07n1OWWDTZkuMD6C2+Fc=", "subType": "06" } } }, "kmip_symbol_det_auto_id": { "kms": "kmip", "type": "symbol", "algo": "det", "method": "auto", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "ASjCDwAAAAAAAAAAAAAAAAAOPpwX4mafoQJYHuzYfbKW1JunpjpB7Nd2slTC3n8Hsas9wQYf9VkModQhe5M4wZHOIXpehaODRcjKKfKRmpnNBOURSLm/ORJvy+UxtSLsnqo=", "subType": "06" } } }, "kmip_symbol_det_explicit_id": { "kms": "kmip", "type": "symbol", "algo": "det", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "ASjCDwAAAAAAAAAAAAAAAAAOPpwX4mafoQJYHuzYfbKW1JunpjpB7Nd2slTC3n8Hsas9wQYf9VkModQhe5M4wZHOIXpehaODRcjKKfKRmpnNBOURSLm/ORJvy+UxtSLsnqo=", "subType": "06" } } }, "kmip_symbol_det_explicit_altname": { "kms": "kmip", "type": "symbol", "algo": "det", "method": "explicit", "identifier": "altname", "allowed": true, "value": { "$binary": { "base64": "ASjCDwAAAAAAAAAAAAAAAAAOPpwX4mafoQJYHuzYfbKW1JunpjpB7Nd2slTC3n8Hsas9wQYf9VkModQhe5M4wZHOIXpehaODRcjKKfKRmpnNBOURSLm/ORJvy+UxtSLsnqo=", "subType": "06" } } }, "kmip_javascriptWithScope_rand_auto_id": { "kms": "kmip", "type": "javascriptWithScope", "algo": "rand", "method": "auto", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "AijCDwAAAAAAAAAAAAAAAAAPW2VMMm+EvsYpVtJQhsxgxgvV35kr9nxqKxP2qqIOAOQ58R/1oyYScFkNwB/tw0A1/zdvhoo+ERa7c0tjLIojFrosXhX2N/8Z4VnbZruz0Nk=", "subType": "06" } } }, "kmip_javascriptWithScope_rand_auto_altname": { "kms": "kmip", "type": "javascriptWithScope", "algo": "rand", "method": "auto", "identifier": "altname", "allowed": true, "value": { "$binary": { "base64": "AijCDwAAAAAAAAAAAAAAAAAPjPq9BQR4EwG/CD+RthOJY04m99LCl/shY6HnaU/QL627kN1dbBAG5vs+MXfa+glg8waVTNgB94vm3j72FMV1ZOKvbl4faWF1Rl2EOpOlR9U=", "subType": "06" } } }, "kmip_javascriptWithScope_rand_explicit_id": { "kms": "kmip", "type": "javascriptWithScope", "algo": "rand", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "AijCDwAAAAAAAAAAAAAAAAAPtqebrCAidKzBMvp3B5/vBeetqeCoMKS+vo+hLAYooXrnBunWxwRHpr45XYUvroG3aqOMkLtVZSgw8sO6Y/3z1viO2G0sGQW1ZMoW0/PX5Uw=", "subType": "06" } } }, "kmip_javascriptWithScope_rand_explicit_altname": { "kms": "kmip", "type": "javascriptWithScope", "algo": "rand", "method": "explicit", "identifier": "altname", "allowed": true, "value": { "$binary": { "base64": "AijCDwAAAAAAAAAAAAAAAAAPtkJwXKlq8Fx1f1+9HFofM4uKi6lHQRFRyiOyUFJYxxZY1LR/2WXXTqWz3MWtrcJFCB+QSVOb1N/ieC7AZUboPgIuPJISM3Hu5VU2x/Isbdc=", "subType": "06" } } }, "kmip_javascriptWithScope_det_explicit_id": { "kms": "kmip", "type": "javascriptWithScope", "algo": "det", "method": "explicit", "identifier": "id", "allowed": false, "value": { "$code": "x=1", "$scope": {} } }, "kmip_javascriptWithScope_det_explicit_altname": { "kms": "kmip", "type": "javascriptWithScope", "algo": "det", "method": "explicit", "identifier": "altname", "allowed": false, "value": { "$code": "x=1", "$scope": {} } }, "kmip_int_rand_auto_id": { "kms": "kmip", "type": "int", "algo": "rand", "method": "auto", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "AijCDwAAAAAAAAAAAAAAAAAQ50kE7Tby9od2OsmIGZhp9k/mj4vy/YdnmF6YsSPxihbjV1vXGMraI/nGCr+0H1riwzq3m4sCT7aPw2VgiuwKMA==", "subType": "06" } } }, "kmip_int_rand_auto_altname": { "kms": "kmip", "type": "int", "algo": "rand", "method": "auto", "identifier": "altname", "allowed": true, "value": { "$binary": { "base64": "AijCDwAAAAAAAAAAAAAAAAAQkNL14OSMX/bJbsLtB/UumRoat6QOY7fvwZxRrkXTS3VJVHigthI1cUX7Is/uUsY8oHOfk/ZuHklQkifmfdcklQ==", "subType": "06" } } }, "kmip_int_rand_explicit_id": { "kms": "kmip", "type": "int", "algo": "rand", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "AijCDwAAAAAAAAAAAAAAAAAQtN2gNVU9Itoj+vgcK/4jEB5baSUH+Qz2WqTY7m0XaA3bPWGFCiWY4Sdw+qovednrSSSbC+azWi1QYclFRraldQ==", "subType": "06" } } }, "kmip_int_rand_explicit_altname": { "kms": "kmip", "type": "int", "algo": "rand", "method": "explicit", "identifier": "altname", "allowed": true, "value": { "$binary": { "base64": "AijCDwAAAAAAAAAAAAAAAAAQk6uBqwXXFF9zEM4bc124goI3pBy2Jdi8Cd0ycKkjXrPG7GVCUm2UMbO+zEzYODeVo35N11g2yMXcv9RVgjWtNA==", "subType": "06" } } }, "kmip_int_det_auto_id": { "kms": "kmip", "type": "int", "algo": "det", "method": "auto", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "ASjCDwAAAAAAAAAAAAAAAAAQgrkPEf+RBZMn/J7HZObqEfus8icYls6ecaUrlabI6v1ALgxLuv23WSIfTr6mqpQCounqdA14DWS/Wl3kSkVC0w==", "subType": "06" } } }, "kmip_int_det_explicit_id": { "kms": "kmip", "type": "int", "algo": "det", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "ASjCDwAAAAAAAAAAAAAAAAAQgrkPEf+RBZMn/J7HZObqEfus8icYls6ecaUrlabI6v1ALgxLuv23WSIfTr6mqpQCounqdA14DWS/Wl3kSkVC0w==", "subType": "06" } } }, "kmip_int_det_explicit_altname": { "kms": "kmip", "type": "int", "algo": "det", "method": "explicit", "identifier": "altname", "allowed": true, "value": { "$binary": { "base64": "ASjCDwAAAAAAAAAAAAAAAAAQgrkPEf+RBZMn/J7HZObqEfus8icYls6ecaUrlabI6v1ALgxLuv23WSIfTr6mqpQCounqdA14DWS/Wl3kSkVC0w==", "subType": "06" } } }, "kmip_timestamp_rand_auto_id": { "kms": "kmip", "type": "timestamp", "algo": "rand", "method": "auto", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "AijCDwAAAAAAAAAAAAAAAAAR2Cu3o2e/u5o69MndeZPJU5ngVA1G2MNYn00t+up/GlmaUC1ni1CVl0ZR0EVZ0gCDUrfxwPISPib8y23tNjbsog==", "subType": "06" } } }, "kmip_timestamp_rand_auto_altname": { "kms": "kmip", "type": "timestamp", "algo": "rand", "method": "auto", "identifier": "altname", "allowed": true, "value": { "$binary": { "base64": "AijCDwAAAAAAAAAAAAAAAAARgi8stgSQwqnN4Ws2ZBILOREsjreZcS1MBerL7dbGLVfzW99tqECglhGokkrE0aY69L0xMgcAUIaFRN4GanQAPg==", "subType": "06" } } }, "kmip_timestamp_rand_explicit_id": { "kms": "kmip", "type": "timestamp", "algo": "rand", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "AijCDwAAAAAAAAAAAAAAAAARPxEEI8L5Q3Jybu88BLdf31T3uYEUbijgSlKlkTt141RYrlE8nxtiYU5/5H9GXBis0Qq1s2C+MauD2h/cNijTCA==", "subType": "06" } } }, "kmip_timestamp_rand_explicit_altname": { "kms": "kmip", "type": "timestamp", "algo": "rand", "method": "explicit", "identifier": "altname", "allowed": true, "value": { "$binary": { "base64": "AijCDwAAAAAAAAAAAAAAAAARh/QaU1dnGbii4LtXCpT5o6vencc8E2fzarjJFbSEd0ixW/UV1ppZdvD729d0umkaIwIEVA4q+XVvHfl/ckKPFg==", "subType": "06" } } }, "kmip_timestamp_det_auto_id": { "kms": "kmip", "type": "timestamp", "algo": "det", "method": "auto", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "ASjCDwAAAAAAAAAAAAAAAAARqdpLb72mmzb75QBrE+ATMfS5LLqzAD/1g5ScT8zfgh0IHsZZBWCJlSVRNC12Sgr3zdXHMtYp8C3OZT6/tPkQGg==", "subType": "06" } } }, "kmip_timestamp_det_explicit_id": { "kms": "kmip", "type": "timestamp", "algo": "det", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "ASjCDwAAAAAAAAAAAAAAAAARqdpLb72mmzb75QBrE+ATMfS5LLqzAD/1g5ScT8zfgh0IHsZZBWCJlSVRNC12Sgr3zdXHMtYp8C3OZT6/tPkQGg==", "subType": "06" } } }, "kmip_timestamp_det_explicit_altname": { "kms": "kmip", "type": "timestamp", "algo": "det", "method": "explicit", "identifier": "altname", "allowed": true, "value": { "$binary": { "base64": "ASjCDwAAAAAAAAAAAAAAAAARqdpLb72mmzb75QBrE+ATMfS5LLqzAD/1g5ScT8zfgh0IHsZZBWCJlSVRNC12Sgr3zdXHMtYp8C3OZT6/tPkQGg==", "subType": "06" } } }, "kmip_long_rand_auto_id": { "kms": "kmip", "type": "long", "algo": "rand", "method": "auto", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "AijCDwAAAAAAAAAAAAAAAAASVv+ClXkh9spIaXWJYRV/o8UZjG+WWWrNpIjZ9LQn2bXakrKJ3REvdkrzGuxASmBhBYTplEyvxVCJwXuWRAGGYw==", "subType": "06" } } }, "kmip_long_rand_auto_altname": { "kms": "kmip", "type": "long", "algo": "rand", "method": "auto", "identifier": "altname", "allowed": true, "value": { "$binary": { "base64": "AijCDwAAAAAAAAAAAAAAAAASeAz/dK+Gc4/jx3W07B2rNFvQ0LoyCllFRvRVGu1Xf1NByc4cRZLOMzlr99syz/fifF6WY30bOi5Pani9QtFuGg==", "subType": "06" } } }, "kmip_long_rand_explicit_id": { "kms": "kmip", "type": "long", "algo": "rand", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "AijCDwAAAAAAAAAAAAAAAAASP1HD9uoDlwTldaznKxW71JUQcLsa4/cUWzeTnelQwdpohCbZsM8fBZBqgwwTWnjpYY/LBUipC6yhwLKfUXBoBQ==", "subType": "06" } } }, "kmip_long_rand_explicit_altname": { "kms": "kmip", "type": "long", "algo": "rand", "method": "explicit", "identifier": "altname", "allowed": true, "value": { "$binary": { "base64": "AijCDwAAAAAAAAAAAAAAAAASnGPH77bS/ETB1hn+VTvsBrxEvIHA6EAb8Z2SEz6BHt7SVeI+I7DLERvRVpV5kNJFcKgXDrvRmD+Et0rhSmk9sw==", "subType": "06" } } }, "kmip_long_det_auto_id": { "kms": "kmip", "type": "long", "algo": "det", "method": "auto", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "ASjCDwAAAAAAAAAAAAAAAAAS+zKmtijSTPOEVlpwmaeMIOuzVNuZpV4Jw9zP8Yqa1xYtlItXDozqdibacRaA74KU49KNySdR1T7fxwxa2OOTrQ==", "subType": "06" } } }, "kmip_long_det_explicit_id": { "kms": "kmip", "type": "long", "algo": "det", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "ASjCDwAAAAAAAAAAAAAAAAAS+zKmtijSTPOEVlpwmaeMIOuzVNuZpV4Jw9zP8Yqa1xYtlItXDozqdibacRaA74KU49KNySdR1T7fxwxa2OOTrQ==", "subType": "06" } } }, "kmip_long_det_explicit_altname": { "kms": "kmip", "type": "long", "algo": "det", "method": "explicit", "identifier": "altname", "allowed": true, "value": { "$binary": { "base64": "ASjCDwAAAAAAAAAAAAAAAAAS+zKmtijSTPOEVlpwmaeMIOuzVNuZpV4Jw9zP8Yqa1xYtlItXDozqdibacRaA74KU49KNySdR1T7fxwxa2OOTrQ==", "subType": "06" } } }, "kmip_decimal_rand_auto_id": { "kms": "kmip", "type": "decimal", "algo": "rand", "method": "auto", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "AijCDwAAAAAAAAAAAAAAAAATu/BbCc5Ti9SBlMR2B8zj3Q1yQ16Uob+10LWaT5QKS192IcnBGy4wmmNkIsTys060xUby9KKQF80dVPnjYfqJwEXCe/pVaPQZftE0DolKv78=", "subType": "06" } } }, "kmip_decimal_rand_auto_altname": { "kms": "kmip", "type": "decimal", "algo": "rand", "method": "auto", "identifier": "altname", "allowed": true, "value": { "$binary": { "base64": "AijCDwAAAAAAAAAAAAAAAAATpq6/dtxq2ZUZHrK10aB0YjjPalEaXYcyAyRZjfXWAYCLZdT9sIybjX3Axjxisim+VSHx0QU7oXkKUfcbLgHyjUXj8g9059FHxKFkUsNv4Z8=", "subType": "06" } } }, "kmip_decimal_rand_explicit_id": { "kms": "kmip", "type": "decimal", "algo": "rand", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "AijCDwAAAAAAAAAAAAAAAAATS++9KcfM7uiShZYxRpFPrBJquKv7dyvFRTjnxs6aaaPo0fiqpv6bco/cMLsldEVpWDEA/Tc2HtSXYPp4UJsMfASyBjoxCloL5SaRWyD9Ye8=", "subType": "06" } } }, "kmip_decimal_rand_explicit_altname": { "kms": "kmip", "type": "decimal", "algo": "rand", "method": "explicit", "identifier": "altname", "allowed": true, "value": { "$binary": { "base64": "AijCDwAAAAAAAAAAAAAAAAATREcETS5KoAGyj/P45owPrdFfy5ng8Z1ND+F+780lLddOyPeDnIsa7yg6uvhTZ65mHfGLvKcFocclYenq/AX1dY4xdjLRg/AfT088A27ORUA=", "subType": "06" } } }, "kmip_decimal_det_explicit_id": { "kms": "kmip", "type": "decimal", "algo": "det", "method": "explicit", "identifier": "id", "allowed": false, "value": { "$numberDecimal": "1.234" } }, "kmip_decimal_det_explicit_altname": { "kms": "kmip", "type": "decimal", "algo": "det", "method": "explicit", "identifier": "altname", "allowed": false, "value": { "$numberDecimal": "1.234" } }, "kmip_minKey_rand_explicit_id": { "kms": "kmip", "type": "minKey", "algo": "rand", "method": "explicit", "identifier": "id", "allowed": false, "value": { "$minKey": 1 } }, "kmip_minKey_rand_explicit_altname": { "kms": "kmip", "type": "minKey", "algo": "rand", "method": "explicit", "identifier": "altname", "allowed": false, "value": { "$minKey": 1 } }, "kmip_minKey_det_explicit_id": { "kms": "kmip", "type": "minKey", "algo": "det", "method": "explicit", "identifier": "id", "allowed": false, "value": { "$minKey": 1 } }, "kmip_minKey_det_explicit_altname": { "kms": "kmip", "type": "minKey", "algo": "det", "method": "explicit", "identifier": "altname", "allowed": false, "value": { "$minKey": 1 } }, "kmip_maxKey_rand_explicit_id": { "kms": "kmip", "type": "maxKey", "algo": "rand", "method": "explicit", "identifier": "id", "allowed": false, "value": { "$maxKey": 1 } }, "kmip_maxKey_rand_explicit_altname": { "kms": "kmip", "type": "maxKey", "algo": "rand", "method": "explicit", "identifier": "altname", "allowed": false, "value": { "$maxKey": 1 } }, "kmip_maxKey_det_explicit_id": { "kms": "kmip", "type": "maxKey", "algo": "det", "method": "explicit", "identifier": "id", "allowed": false, "value": { "$maxKey": 1 } }, "kmip_maxKey_det_explicit_altname": { "kms": "kmip", "type": "maxKey", "algo": "det", "method": "explicit", "identifier": "altname", "allowed": false, "value": { "$maxKey": 1 } } }mongodb-mongo-python-driver-509e9b7/test/client-side-encryption/corpus/corpus-key-aws.json000066400000000000000000000020231462766011000321000ustar00rootroot00000000000000{ "status": { "$numberInt": "1" }, "_id": { "$binary": { "base64": "AWSAAAAAAAAAAAAAAAAAAA==", "subType": "04" } }, "masterKey": { "region": "us-east-1", "key": "arn:aws:kms:us-east-1:579766882180:key/89fcc2c4-08b0-4bd9-9f25-e30687b580d0", "provider": "aws" }, "updateDate": { "$date": { "$numberLong": "1557827033449" } }, "keyMaterial": { "$binary": { "base64": "AQICAHhQNmWG2CzOm1dq3kWLM+iDUZhEqnhJwH9wZVpuZ94A8gEqnsxXlR51T5EbEVezUqqKAAAAwjCBvwYJKoZIhvcNAQcGoIGxMIGuAgEAMIGoBgkqhkiG9w0BBwEwHgYJYIZIAWUDBAEuMBEEDHa4jo6yp0Z18KgbUgIBEIB74sKxWtV8/YHje5lv5THTl0HIbhSwM6EqRlmBiFFatmEWaeMk4tO4xBX65eq670I5TWPSLMzpp8ncGHMmvHqRajNBnmFtbYxN3E3/WjxmdbOOe+OXpnGJPcGsftc7cB2shRfA4lICPnE26+oVNXT6p0Lo20nY5XC7jyCO", "subType": "00" } }, "creationDate": { "$date": { "$numberLong": "1557827033449" } }, "keyAltNames": ["aws"] }mongodb-mongo-python-driver-509e9b7/test/client-side-encryption/corpus/corpus-key-azure.json000066400000000000000000000017751462766011000324510ustar00rootroot00000000000000{ "_id": { "$binary": { "base64": "AZUREAAAAAAAAAAAAAAAAA==", "subType": "04" } }, "keyMaterial": { "$binary": { "base64": "n+HWZ0ZSVOYA3cvQgP7inN4JSXfOH85IngmeQxRpQHjCCcqT3IFqEWNlrsVHiz3AELimHhX4HKqOLWMUeSIT6emUDDoQX9BAv8DR1+E1w4nGs/NyEneac78EYFkK3JysrFDOgl2ypCCTKAypkn9CkAx1if4cfgQE93LW4kczcyHdGiH36CIxrCDGv1UzAvERN5Qa47DVwsM6a+hWsF2AAAJVnF0wYLLJU07TuRHdMrrphPWXZsFgyV+lRqJ7DDpReKNO8nMPLV/mHqHBHGPGQiRdb9NoJo8CvokGz4+KE8oLwzKf6V24dtwZmRkrsDV4iOhvROAzz+Euo1ypSkL3mw==", "subType": "00" } }, "creationDate": { "$date": { "$numberLong": "1601573901680" } }, "updateDate": { "$date": { "$numberLong": "1601573901680" } }, "status": { "$numberInt": "0" }, "masterKey": { "provider": "azure", "keyVaultEndpoint": "key-vault-csfle.vault.azure.net", "keyName": "key-name-csfle" }, "keyAltNames": ["azure"] }mongodb-mongo-python-driver-509e9b7/test/client-side-encryption/corpus/corpus-key-gcp.json000066400000000000000000000016751462766011000320730ustar00rootroot00000000000000{ "_id": { "$binary": { "base64": "GCPAAAAAAAAAAAAAAAAAAA==", "subType": "04" } }, "keyMaterial": { "$binary": { "base64": "CiQAIgLj0WyktnB4dfYHo5SLZ41K4ASQrjJUaSzl5vvVH0G12G0SiQEAjlV8XPlbnHDEDFbdTO4QIe8ER2/172U1ouLazG0ysDtFFIlSvWX5ZnZUrRMmp/R2aJkzLXEt/zf8Mn4Lfm+itnjgo5R9K4pmPNvvPKNZX5C16lrPT+aA+rd+zXFSmlMg3i5jnxvTdLHhg3G7Q/Uv1ZIJskKt95bzLoe0tUVzRWMYXLIEcohnQg==", "subType": "00" } }, "creationDate": { "$date": { "$numberLong": "1601574333107" } }, "updateDate": { "$date": { "$numberLong": "1601574333107" } }, "status": { "$numberInt": "0" }, "masterKey": { "provider": "gcp", "projectId": "devprod-drivers", "location": "global", "keyRing": "key-ring-csfle", "keyName": "key-name-csfle" }, "keyAltNames": ["gcp"] }mongodb-mongo-python-driver-509e9b7/test/client-side-encryption/corpus/corpus-key-kmip.json000066400000000000000000000014551462766011000322560ustar00rootroot00000000000000{ "_id": { "$binary": { "base64": "KMIPAAAAAAAAAAAAAAAAAA==", "subType": "04" } }, "keyMaterial": { "$binary": { "base64": "eUYDyB0HuWb+lQgUwO+6qJQyTTDTY2gp9FbemL7ZFo0pvr0x6rm6Ff9OVUTGH6HyMKipaeHdiIJU1dzsLwvqKvi7Beh+U4iaIWX/K0oEg1GOsJc0+Z/in8gNHbGUYLmycHViM3LES3kdt7FdFSUl5rEBHrM71yoNEXImz17QJWMGOuT4x6yoi2pvnaRJwfrI4DjpmnnTrDMac92jgZehbg==", "subType": "00" } }, "creationDate": { "$date": { "$numberLong": "1634220190041" } }, "updateDate": { "$date": { "$numberLong": "1634220190041" } }, "status": { "$numberInt": "0" }, "masterKey": { "provider": "kmip", "keyId": "1" }, "keyAltNames": ["kmip"] }mongodb-mongo-python-driver-509e9b7/test/client-side-encryption/corpus/corpus-key-local.json000066400000000000000000000014421462766011000324040ustar00rootroot00000000000000{ "status": { "$numberInt": "1" }, "_id": { "$binary": { "base64": "LOCALAAAAAAAAAAAAAAAAA==", "subType": "04" } }, "masterKey": { "provider": "local" }, "updateDate": { "$date": { "$numberLong": "1557827033449" } }, "keyMaterial": { "$binary": { "base64": "Ce9HSz/HKKGkIt4uyy+jDuKGA+rLC2cycykMo6vc8jXxqa1UVDYHWq1r+vZKbnnSRBfB981akzRKZCFpC05CTyFqDhXv6OnMjpG97OZEREGIsHEYiJkBW0jJJvfLLgeLsEpBzsro9FztGGXASxyxFRZFhXvHxyiLOKrdWfs7X1O/iK3pEoHMx6uSNSfUOgbebLfIqW7TO++iQS5g1xovXA==", "subType": "00" } }, "creationDate": { "$date": { "$numberLong": "1557827033449" } }, "keyAltNames": [ "local" ] }mongodb-mongo-python-driver-509e9b7/test/client-side-encryption/corpus/corpus-schema.json000066400000000000000000004422361462766011000317760ustar00rootroot00000000000000{ "bsonType": "object", "properties": { "aws_double_rand_auto_id": { "bsonType": "object", "properties": { "value": { "encrypt": { "keyId": [ { "$binary": { "base64": "AWSAAAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Random", "bsonType": "double" } } } }, "aws_double_rand_auto_altname": { "bsonType": "object", "properties": { "value": { "encrypt": { "keyId": "/altname_aws", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Random", "bsonType": "double" } } } }, "aws_double_rand_explicit_id": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } }, "aws_double_rand_explicit_altname": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } }, "aws_string_rand_auto_id": { "bsonType": "object", "properties": { "value": { "encrypt": { "keyId": [ { "$binary": { "base64": "AWSAAAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Random", "bsonType": "string" } } } }, "aws_string_rand_auto_altname": { "bsonType": "object", "properties": { "value": { "encrypt": { "keyId": "/altname_aws", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Random", "bsonType": "string" } } } }, "aws_string_rand_explicit_id": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } }, "aws_string_rand_explicit_altname": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } }, "aws_string_det_auto_id": { "bsonType": "object", "properties": { "value": { "encrypt": { "keyId": [ { "$binary": { "base64": "AWSAAAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic", "bsonType": "string" } } } }, "aws_string_det_explicit_id": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } }, "aws_string_det_explicit_altname": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } }, "aws_object_rand_auto_id": { "bsonType": "object", "properties": { "value": { "encrypt": { "keyId": [ { "$binary": { "base64": "AWSAAAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Random", "bsonType": "object" } } } }, "aws_object_rand_auto_altname": { "bsonType": "object", "properties": { "value": { "encrypt": { "keyId": "/altname_aws", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Random", "bsonType": "object" } } } }, "aws_object_rand_explicit_id": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } }, "aws_object_rand_explicit_altname": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } }, "aws_array_rand_auto_id": { "bsonType": "object", "properties": { "value": { "encrypt": { "keyId": [ { "$binary": { "base64": "AWSAAAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Random", "bsonType": "array" } } } }, "aws_array_rand_auto_altname": { "bsonType": "object", "properties": { "value": { "encrypt": { "keyId": "/altname_aws", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Random", "bsonType": "array" } } } }, "aws_array_rand_explicit_id": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } }, "aws_array_rand_explicit_altname": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } }, "aws_binData=00_rand_auto_id": { "bsonType": "object", "properties": { "value": { "encrypt": { "keyId": [ { "$binary": { "base64": "AWSAAAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Random", "bsonType": "binData" } } } }, "aws_binData=00_rand_auto_altname": { "bsonType": "object", "properties": { "value": { "encrypt": { "keyId": "/altname_aws", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Random", "bsonType": "binData" } } } }, "aws_binData=00_rand_explicit_id": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } }, "aws_binData=00_rand_explicit_altname": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } }, "aws_binData=00_det_auto_id": { "bsonType": "object", "properties": { "value": { "encrypt": { "keyId": [ { "$binary": { "base64": "AWSAAAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic", "bsonType": "binData" } } } }, "aws_binData=00_det_explicit_id": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } }, "aws_binData=00_det_explicit_altname": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } }, "aws_binData=04_rand_auto_id": { "bsonType": "object", "properties": { "value": { "encrypt": { "keyId": [ { "$binary": { "base64": "AWSAAAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Random", "bsonType": "binData" } } } }, "aws_binData=04_rand_auto_altname": { "bsonType": "object", "properties": { "value": { "encrypt": { "keyId": "/altname_aws", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Random", "bsonType": "binData" } } } }, "aws_binData=04_rand_explicit_id": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } }, "aws_binData=04_rand_explicit_altname": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } }, "aws_binData=04_det_auto_id": { "bsonType": "object", "properties": { "value": { "encrypt": { "keyId": [ { "$binary": { "base64": "AWSAAAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic", "bsonType": "binData" } } } }, "aws_binData=04_det_explicit_id": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } }, "aws_binData=04_det_explicit_altname": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } }, "aws_objectId_rand_auto_id": { "bsonType": "object", "properties": { "value": { "encrypt": { "keyId": [ { "$binary": { "base64": "AWSAAAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Random", "bsonType": "objectId" } } } }, "aws_objectId_rand_auto_altname": { "bsonType": "object", "properties": { "value": { "encrypt": { "keyId": "/altname_aws", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Random", "bsonType": "objectId" } } } }, "aws_objectId_rand_explicit_id": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } }, "aws_objectId_rand_explicit_altname": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } }, "aws_objectId_det_auto_id": { "bsonType": "object", "properties": { "value": { "encrypt": { "keyId": [ { "$binary": { "base64": "AWSAAAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic", "bsonType": "objectId" } } } }, "aws_objectId_det_explicit_id": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } }, "aws_objectId_det_explicit_altname": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } }, "aws_bool_rand_auto_id": { "bsonType": "object", "properties": { "value": { "encrypt": { "keyId": [ { "$binary": { "base64": "AWSAAAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Random", "bsonType": "bool" } } } }, "aws_bool_rand_auto_altname": { "bsonType": "object", "properties": { "value": { "encrypt": { "keyId": "/altname_aws", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Random", "bsonType": "bool" } } } }, "aws_bool_rand_explicit_id": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } }, "aws_bool_rand_explicit_altname": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } }, "aws_date_rand_auto_id": { "bsonType": "object", "properties": { "value": { "encrypt": { "keyId": [ { "$binary": { "base64": "AWSAAAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Random", "bsonType": "date" } } } }, "aws_date_rand_auto_altname": { "bsonType": "object", "properties": { "value": { "encrypt": { "keyId": "/altname_aws", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Random", "bsonType": "date" } } } }, "aws_date_rand_explicit_id": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } }, "aws_date_rand_explicit_altname": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } }, "aws_date_det_auto_id": { "bsonType": "object", "properties": { "value": { "encrypt": { "keyId": [ { "$binary": { "base64": "AWSAAAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic", "bsonType": "date" } } } }, "aws_date_det_explicit_id": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } }, "aws_date_det_explicit_altname": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } }, "aws_regex_rand_auto_id": { "bsonType": "object", "properties": { "value": { "encrypt": { "keyId": [ { "$binary": { "base64": "AWSAAAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Random", "bsonType": "regex" } } } }, "aws_regex_rand_auto_altname": { "bsonType": "object", "properties": { "value": { "encrypt": { "keyId": "/altname_aws", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Random", "bsonType": "regex" } } } }, "aws_regex_rand_explicit_id": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } }, "aws_regex_rand_explicit_altname": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } }, "aws_regex_det_auto_id": { "bsonType": "object", "properties": { "value": { "encrypt": { "keyId": [ { "$binary": { "base64": "AWSAAAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic", "bsonType": "regex" } } } }, "aws_regex_det_explicit_id": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } }, "aws_regex_det_explicit_altname": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } }, "aws_dbPointer_rand_auto_id": { "bsonType": "object", "properties": { "value": { "encrypt": { "keyId": [ { "$binary": { "base64": "AWSAAAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Random", "bsonType": "dbPointer" } } } }, "aws_dbPointer_rand_auto_altname": { "bsonType": "object", "properties": { "value": { "encrypt": { "keyId": "/altname_aws", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Random", "bsonType": "dbPointer" } } } }, "aws_dbPointer_rand_explicit_id": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } }, "aws_dbPointer_rand_explicit_altname": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } }, "aws_dbPointer_det_auto_id": { "bsonType": "object", "properties": { "value": { "encrypt": { "keyId": [ { "$binary": { "base64": "AWSAAAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic", "bsonType": "dbPointer" } } } }, "aws_dbPointer_det_explicit_id": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } }, "aws_dbPointer_det_explicit_altname": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } }, "aws_javascript_rand_auto_id": { "bsonType": "object", "properties": { "value": { "encrypt": { "keyId": [ { "$binary": { "base64": "AWSAAAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Random", "bsonType": "javascript" } } } }, "aws_javascript_rand_auto_altname": { "bsonType": "object", "properties": { "value": { "encrypt": { "keyId": "/altname_aws", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Random", "bsonType": "javascript" } } } }, "aws_javascript_rand_explicit_id": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } }, "aws_javascript_rand_explicit_altname": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } }, "aws_javascript_det_auto_id": { "bsonType": "object", "properties": { "value": { "encrypt": { "keyId": [ { "$binary": { "base64": "AWSAAAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic", "bsonType": "javascript" } } } }, "aws_javascript_det_explicit_id": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } }, "aws_javascript_det_explicit_altname": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } }, "aws_symbol_rand_auto_id": { "bsonType": "object", "properties": { "value": { "encrypt": { "keyId": [ { "$binary": { "base64": "AWSAAAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Random", "bsonType": "symbol" } } } }, "aws_symbol_rand_auto_altname": { "bsonType": "object", "properties": { "value": { "encrypt": { "keyId": "/altname_aws", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Random", "bsonType": "symbol" } } } }, "aws_symbol_rand_explicit_id": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } }, "aws_symbol_rand_explicit_altname": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } }, "aws_symbol_det_auto_id": { "bsonType": "object", "properties": { "value": { "encrypt": { "keyId": [ { "$binary": { "base64": "AWSAAAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic", "bsonType": "symbol" } } } }, "aws_symbol_det_explicit_id": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } }, "aws_symbol_det_explicit_altname": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } }, "aws_javascriptWithScope_rand_auto_id": { "bsonType": "object", "properties": { "value": { "encrypt": { "keyId": [ { "$binary": { "base64": "AWSAAAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Random", "bsonType": "javascriptWithScope" } } } }, "aws_javascriptWithScope_rand_auto_altname": { "bsonType": "object", "properties": { "value": { "encrypt": { "keyId": "/altname_aws", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Random", "bsonType": "javascriptWithScope" } } } }, "aws_javascriptWithScope_rand_explicit_id": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } }, "aws_javascriptWithScope_rand_explicit_altname": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } }, "aws_int_rand_auto_id": { "bsonType": "object", "properties": { "value": { "encrypt": { "keyId": [ { "$binary": { "base64": "AWSAAAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Random", "bsonType": "int" } } } }, "aws_int_rand_auto_altname": { "bsonType": "object", "properties": { "value": { "encrypt": { "keyId": "/altname_aws", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Random", "bsonType": "int" } } } }, "aws_int_rand_explicit_id": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } }, "aws_int_rand_explicit_altname": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } }, "aws_int_det_auto_id": { "bsonType": "object", "properties": { "value": { "encrypt": { "keyId": [ { "$binary": { "base64": "AWSAAAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic", "bsonType": "int" } } } }, "aws_int_det_explicit_id": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } }, "aws_int_det_explicit_altname": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } }, "aws_timestamp_rand_auto_id": { "bsonType": "object", "properties": { "value": { "encrypt": { "keyId": [ { "$binary": { "base64": "AWSAAAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Random", "bsonType": "timestamp" } } } }, "aws_timestamp_rand_auto_altname": { "bsonType": "object", "properties": { "value": { "encrypt": { "keyId": "/altname_aws", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Random", "bsonType": "timestamp" } } } }, "aws_timestamp_rand_explicit_id": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } }, "aws_timestamp_rand_explicit_altname": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } }, "aws_timestamp_det_auto_id": { "bsonType": "object", "properties": { "value": { "encrypt": { "keyId": [ { "$binary": { "base64": "AWSAAAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic", "bsonType": "timestamp" } } } }, "aws_timestamp_det_explicit_id": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } }, "aws_timestamp_det_explicit_altname": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } }, "aws_long_rand_auto_id": { "bsonType": "object", "properties": { "value": { "encrypt": { "keyId": [ { "$binary": { "base64": "AWSAAAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Random", "bsonType": "long" } } } }, "aws_long_rand_auto_altname": { "bsonType": "object", "properties": { "value": { "encrypt": { "keyId": "/altname_aws", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Random", "bsonType": "long" } } } }, "aws_long_rand_explicit_id": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } }, "aws_long_rand_explicit_altname": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } }, "aws_long_det_auto_id": { "bsonType": "object", "properties": { "value": { "encrypt": { "keyId": [ { "$binary": { "base64": "AWSAAAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic", "bsonType": "long" } } } }, "aws_long_det_explicit_id": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } }, "aws_long_det_explicit_altname": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } }, "aws_decimal_rand_auto_id": { "bsonType": "object", "properties": { "value": { "encrypt": { "keyId": [ { "$binary": { "base64": "AWSAAAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Random", "bsonType": "decimal" } } } }, "aws_decimal_rand_auto_altname": { "bsonType": "object", "properties": { "value": { "encrypt": { "keyId": "/altname_aws", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Random", "bsonType": "decimal" } } } }, "aws_decimal_rand_explicit_id": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } }, "aws_decimal_rand_explicit_altname": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } }, "local_double_rand_auto_id": { "bsonType": "object", "properties": { "value": { "encrypt": { "keyId": [ { "$binary": { "base64": "LOCALAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Random", "bsonType": "double" } } } }, "local_double_rand_auto_altname": { "bsonType": "object", "properties": { "value": { "encrypt": { "keyId": "/altname_local", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Random", "bsonType": "double" } } } }, "local_double_rand_explicit_id": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } }, "local_double_rand_explicit_altname": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } }, "local_string_rand_auto_id": { "bsonType": "object", "properties": { "value": { "encrypt": { "keyId": [ { "$binary": { "base64": "LOCALAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Random", "bsonType": "string" } } } }, "local_string_rand_auto_altname": { "bsonType": "object", "properties": { "value": { "encrypt": { "keyId": "/altname_local", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Random", "bsonType": "string" } } } }, "local_string_rand_explicit_id": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } }, "local_string_rand_explicit_altname": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } }, "local_string_det_auto_id": { "bsonType": "object", "properties": { "value": { "encrypt": { "keyId": [ { "$binary": { "base64": "LOCALAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic", "bsonType": "string" } } } }, "local_string_det_explicit_id": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } }, "local_string_det_explicit_altname": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } }, "local_object_rand_auto_id": { "bsonType": "object", "properties": { "value": { "encrypt": { "keyId": [ { "$binary": { "base64": "LOCALAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Random", "bsonType": "object" } } } }, "local_object_rand_auto_altname": { "bsonType": "object", "properties": { "value": { "encrypt": { "keyId": "/altname_local", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Random", "bsonType": "object" } } } }, "local_object_rand_explicit_id": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } }, "local_object_rand_explicit_altname": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } }, "local_array_rand_auto_id": { "bsonType": "object", "properties": { "value": { "encrypt": { "keyId": [ { "$binary": { "base64": "LOCALAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Random", "bsonType": "array" } } } }, "local_array_rand_auto_altname": { "bsonType": "object", "properties": { "value": { "encrypt": { "keyId": "/altname_local", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Random", "bsonType": "array" } } } }, "local_array_rand_explicit_id": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } }, "local_array_rand_explicit_altname": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } }, "local_binData=00_rand_auto_id": { "bsonType": "object", "properties": { "value": { "encrypt": { "keyId": [ { "$binary": { "base64": "LOCALAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Random", "bsonType": "binData" } } } }, "local_binData=00_rand_auto_altname": { "bsonType": "object", "properties": { "value": { "encrypt": { "keyId": "/altname_local", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Random", "bsonType": "binData" } } } }, "local_binData=00_rand_explicit_id": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } }, "local_binData=00_rand_explicit_altname": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } }, "local_binData=00_det_auto_id": { "bsonType": "object", "properties": { "value": { "encrypt": { "keyId": [ { "$binary": { "base64": "LOCALAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic", "bsonType": "binData" } } } }, "local_binData=00_det_explicit_id": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } }, "local_binData=00_det_explicit_altname": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } }, "local_binData=04_rand_auto_id": { "bsonType": "object", "properties": { "value": { "encrypt": { "keyId": [ { "$binary": { "base64": "LOCALAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Random", "bsonType": "binData" } } } }, "local_binData=04_rand_auto_altname": { "bsonType": "object", "properties": { "value": { "encrypt": { "keyId": "/altname_local", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Random", "bsonType": "binData" } } } }, "local_binData=04_rand_explicit_id": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } }, "local_binData=04_rand_explicit_altname": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } }, "local_binData=04_det_auto_id": { "bsonType": "object", "properties": { "value": { "encrypt": { "keyId": [ { "$binary": { "base64": "LOCALAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic", "bsonType": "binData" } } } }, "local_binData=04_det_explicit_id": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } }, "local_binData=04_det_explicit_altname": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } }, "local_objectId_rand_auto_id": { "bsonType": "object", "properties": { "value": { "encrypt": { "keyId": [ { "$binary": { "base64": "LOCALAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Random", "bsonType": "objectId" } } } }, "local_objectId_rand_auto_altname": { "bsonType": "object", "properties": { "value": { "encrypt": { "keyId": "/altname_local", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Random", "bsonType": "objectId" } } } }, "local_objectId_rand_explicit_id": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } }, "local_objectId_rand_explicit_altname": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } }, "local_objectId_det_auto_id": { "bsonType": "object", "properties": { "value": { "encrypt": { "keyId": [ { "$binary": { "base64": "LOCALAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic", "bsonType": "objectId" } } } }, "local_objectId_det_explicit_id": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } }, "local_objectId_det_explicit_altname": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } }, "local_bool_rand_auto_id": { "bsonType": "object", "properties": { "value": { "encrypt": { "keyId": [ { "$binary": { "base64": "LOCALAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Random", "bsonType": "bool" } } } }, "local_bool_rand_auto_altname": { "bsonType": "object", "properties": { "value": { "encrypt": { "keyId": "/altname_local", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Random", "bsonType": "bool" } } } }, "local_bool_rand_explicit_id": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } }, "local_bool_rand_explicit_altname": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } }, "local_date_rand_auto_id": { "bsonType": "object", "properties": { "value": { "encrypt": { "keyId": [ { "$binary": { "base64": "LOCALAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Random", "bsonType": "date" } } } }, "local_date_rand_auto_altname": { "bsonType": "object", "properties": { "value": { "encrypt": { "keyId": "/altname_local", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Random", "bsonType": "date" } } } }, "local_date_rand_explicit_id": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } }, "local_date_rand_explicit_altname": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } }, "local_date_det_auto_id": { "bsonType": "object", "properties": { "value": { "encrypt": { "keyId": [ { "$binary": { "base64": "LOCALAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic", "bsonType": "date" } } } }, "local_date_det_explicit_id": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } }, "local_date_det_explicit_altname": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } }, "local_regex_rand_auto_id": { "bsonType": "object", "properties": { "value": { "encrypt": { "keyId": [ { "$binary": { "base64": "LOCALAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Random", "bsonType": "regex" } } } }, "local_regex_rand_auto_altname": { "bsonType": "object", "properties": { "value": { "encrypt": { "keyId": "/altname_local", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Random", "bsonType": "regex" } } } }, "local_regex_rand_explicit_id": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } }, "local_regex_rand_explicit_altname": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } }, "local_regex_det_auto_id": { "bsonType": "object", "properties": { "value": { "encrypt": { "keyId": [ { "$binary": { "base64": "LOCALAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic", "bsonType": "regex" } } } }, "local_regex_det_explicit_id": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } }, "local_regex_det_explicit_altname": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } }, "local_dbPointer_rand_auto_id": { "bsonType": "object", "properties": { "value": { "encrypt": { "keyId": [ { "$binary": { "base64": "LOCALAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Random", "bsonType": "dbPointer" } } } }, "local_dbPointer_rand_auto_altname": { "bsonType": "object", "properties": { "value": { "encrypt": { "keyId": "/altname_local", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Random", "bsonType": "dbPointer" } } } }, "local_dbPointer_rand_explicit_id": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } }, "local_dbPointer_rand_explicit_altname": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } }, "local_dbPointer_det_auto_id": { "bsonType": "object", "properties": { "value": { "encrypt": { "keyId": [ { "$binary": { "base64": "LOCALAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic", "bsonType": "dbPointer" } } } }, "local_dbPointer_det_explicit_id": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } }, "local_dbPointer_det_explicit_altname": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } }, "local_javascript_rand_auto_id": { "bsonType": "object", "properties": { "value": { "encrypt": { "keyId": [ { "$binary": { "base64": "LOCALAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Random", "bsonType": "javascript" } } } }, "local_javascript_rand_auto_altname": { "bsonType": "object", "properties": { "value": { "encrypt": { "keyId": "/altname_local", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Random", "bsonType": "javascript" } } } }, "local_javascript_rand_explicit_id": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } }, "local_javascript_rand_explicit_altname": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } }, "local_javascript_det_auto_id": { "bsonType": "object", "properties": { "value": { "encrypt": { "keyId": [ { "$binary": { "base64": "LOCALAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic", "bsonType": "javascript" } } } }, "local_javascript_det_explicit_id": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } }, "local_javascript_det_explicit_altname": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } }, "local_symbol_rand_auto_id": { "bsonType": "object", "properties": { "value": { "encrypt": { "keyId": [ { "$binary": { "base64": "LOCALAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Random", "bsonType": "symbol" } } } }, "local_symbol_rand_auto_altname": { "bsonType": "object", "properties": { "value": { "encrypt": { "keyId": "/altname_local", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Random", "bsonType": "symbol" } } } }, "local_symbol_rand_explicit_id": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } }, "local_symbol_rand_explicit_altname": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } }, "local_symbol_det_auto_id": { "bsonType": "object", "properties": { "value": { "encrypt": { "keyId": [ { "$binary": { "base64": "LOCALAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic", "bsonType": "symbol" } } } }, "local_symbol_det_explicit_id": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } }, "local_symbol_det_explicit_altname": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } }, "local_javascriptWithScope_rand_auto_id": { "bsonType": "object", "properties": { "value": { "encrypt": { "keyId": [ { "$binary": { "base64": "LOCALAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Random", "bsonType": "javascriptWithScope" } } } }, "local_javascriptWithScope_rand_auto_altname": { "bsonType": "object", "properties": { "value": { "encrypt": { "keyId": "/altname_local", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Random", "bsonType": "javascriptWithScope" } } } }, "local_javascriptWithScope_rand_explicit_id": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } }, "local_javascriptWithScope_rand_explicit_altname": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } }, "local_int_rand_auto_id": { "bsonType": "object", "properties": { "value": { "encrypt": { "keyId": [ { "$binary": { "base64": "LOCALAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Random", "bsonType": "int" } } } }, "local_int_rand_auto_altname": { "bsonType": "object", "properties": { "value": { "encrypt": { "keyId": "/altname_local", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Random", "bsonType": "int" } } } }, "local_int_rand_explicit_id": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } }, "local_int_rand_explicit_altname": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } }, "local_int_det_auto_id": { "bsonType": "object", "properties": { "value": { "encrypt": { "keyId": [ { "$binary": { "base64": "LOCALAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic", "bsonType": "int" } } } }, "local_int_det_explicit_id": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } }, "local_int_det_explicit_altname": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } }, "local_timestamp_rand_auto_id": { "bsonType": "object", "properties": { "value": { "encrypt": { "keyId": [ { "$binary": { "base64": "LOCALAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Random", "bsonType": "timestamp" } } } }, "local_timestamp_rand_auto_altname": { "bsonType": "object", "properties": { "value": { "encrypt": { "keyId": "/altname_local", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Random", "bsonType": "timestamp" } } } }, "local_timestamp_rand_explicit_id": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } }, "local_timestamp_rand_explicit_altname": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } }, "local_timestamp_det_auto_id": { "bsonType": "object", "properties": { "value": { "encrypt": { "keyId": [ { "$binary": { "base64": "LOCALAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic", "bsonType": "timestamp" } } } }, "local_timestamp_det_explicit_id": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } }, "local_timestamp_det_explicit_altname": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } }, "local_long_rand_auto_id": { "bsonType": "object", "properties": { "value": { "encrypt": { "keyId": [ { "$binary": { "base64": "LOCALAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Random", "bsonType": "long" } } } }, "local_long_rand_auto_altname": { "bsonType": "object", "properties": { "value": { "encrypt": { "keyId": "/altname_local", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Random", "bsonType": "long" } } } }, "local_long_rand_explicit_id": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } }, "local_long_rand_explicit_altname": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } }, "local_long_det_auto_id": { "bsonType": "object", "properties": { "value": { "encrypt": { "keyId": [ { "$binary": { "base64": "LOCALAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic", "bsonType": "long" } } } }, "local_long_det_explicit_id": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } }, "local_long_det_explicit_altname": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } }, "local_decimal_rand_auto_id": { "bsonType": "object", "properties": { "value": { "encrypt": { "keyId": [ { "$binary": { "base64": "LOCALAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Random", "bsonType": "decimal" } } } }, "local_decimal_rand_auto_altname": { "bsonType": "object", "properties": { "value": { "encrypt": { "keyId": "/altname_local", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Random", "bsonType": "decimal" } } } }, "local_decimal_rand_explicit_id": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } }, "local_decimal_rand_explicit_altname": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } }, "azure_double_rand_auto_id": { "bsonType": "object", "properties": { "value": { "encrypt": { "keyId": [ { "$binary": { "base64": "AZUREAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Random", "bsonType": "double" } } } }, "azure_double_rand_auto_altname": { "bsonType": "object", "properties": { "value": { "encrypt": { "keyId": "/altname_azure", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Random", "bsonType": "double" } } } }, "azure_double_rand_explicit_id": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } }, "azure_double_rand_explicit_altname": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } }, "azure_string_rand_auto_id": { "bsonType": "object", "properties": { "value": { "encrypt": { "keyId": [ { "$binary": { "base64": "AZUREAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Random", "bsonType": "string" } } } }, "azure_string_rand_auto_altname": { "bsonType": "object", "properties": { "value": { "encrypt": { "keyId": "/altname_azure", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Random", "bsonType": "string" } } } }, "azure_string_rand_explicit_id": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } }, "azure_string_rand_explicit_altname": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } }, "azure_string_det_auto_id": { "bsonType": "object", "properties": { "value": { "encrypt": { "keyId": [ { "$binary": { "base64": "AZUREAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic", "bsonType": "string" } } } }, "azure_string_det_explicit_id": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } }, "azure_string_det_explicit_altname": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } }, "azure_object_rand_auto_id": { "bsonType": "object", "properties": { "value": { "encrypt": { "keyId": [ { "$binary": { "base64": "AZUREAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Random", "bsonType": "object" } } } }, "azure_object_rand_auto_altname": { "bsonType": "object", "properties": { "value": { "encrypt": { "keyId": "/altname_azure", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Random", "bsonType": "object" } } } }, "azure_object_rand_explicit_id": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } }, "azure_object_rand_explicit_altname": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } }, "azure_array_rand_auto_id": { "bsonType": "object", "properties": { "value": { "encrypt": { "keyId": [ { "$binary": { "base64": "AZUREAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Random", "bsonType": "array" } } } }, "azure_array_rand_auto_altname": { "bsonType": "object", "properties": { "value": { "encrypt": { "keyId": "/altname_azure", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Random", "bsonType": "array" } } } }, "azure_array_rand_explicit_id": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } }, "azure_array_rand_explicit_altname": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } }, "azure_binData=00_rand_auto_id": { "bsonType": "object", "properties": { "value": { "encrypt": { "keyId": [ { "$binary": { "base64": "AZUREAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Random", "bsonType": "binData" } } } }, "azure_binData=00_rand_auto_altname": { "bsonType": "object", "properties": { "value": { "encrypt": { "keyId": "/altname_azure", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Random", "bsonType": "binData" } } } }, "azure_binData=00_rand_explicit_id": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } }, "azure_binData=00_rand_explicit_altname": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } }, "azure_binData=00_det_auto_id": { "bsonType": "object", "properties": { "value": { "encrypt": { "keyId": [ { "$binary": { "base64": "AZUREAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic", "bsonType": "binData" } } } }, "azure_binData=00_det_explicit_id": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } }, "azure_binData=00_det_explicit_altname": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } }, "azure_binData=04_rand_auto_id": { "bsonType": "object", "properties": { "value": { "encrypt": { "keyId": [ { "$binary": { "base64": "AZUREAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Random", "bsonType": "binData" } } } }, "azure_binData=04_rand_auto_altname": { "bsonType": "object", "properties": { "value": { "encrypt": { "keyId": "/altname_azure", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Random", "bsonType": "binData" } } } }, "azure_binData=04_rand_explicit_id": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } }, "azure_binData=04_rand_explicit_altname": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } }, "azure_binData=04_det_auto_id": { "bsonType": "object", "properties": { "value": { "encrypt": { "keyId": [ { "$binary": { "base64": "AZUREAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic", "bsonType": "binData" } } } }, "azure_binData=04_det_explicit_id": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } }, "azure_binData=04_det_explicit_altname": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } }, "azure_objectId_rand_auto_id": { "bsonType": "object", "properties": { "value": { "encrypt": { "keyId": [ { "$binary": { "base64": "AZUREAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Random", "bsonType": "objectId" } } } }, "azure_objectId_rand_auto_altname": { "bsonType": "object", "properties": { "value": { "encrypt": { "keyId": "/altname_azure", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Random", "bsonType": "objectId" } } } }, "azure_objectId_rand_explicit_id": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } }, "azure_objectId_rand_explicit_altname": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } }, "azure_objectId_det_auto_id": { "bsonType": "object", "properties": { "value": { "encrypt": { "keyId": [ { "$binary": { "base64": "AZUREAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic", "bsonType": "objectId" } } } }, "azure_objectId_det_explicit_id": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } }, "azure_objectId_det_explicit_altname": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } }, "azure_bool_rand_auto_id": { "bsonType": "object", "properties": { "value": { "encrypt": { "keyId": [ { "$binary": { "base64": "AZUREAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Random", "bsonType": "bool" } } } }, "azure_bool_rand_auto_altname": { "bsonType": "object", "properties": { "value": { "encrypt": { "keyId": "/altname_azure", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Random", "bsonType": "bool" } } } }, "azure_bool_rand_explicit_id": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } }, "azure_bool_rand_explicit_altname": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } }, "azure_date_rand_auto_id": { "bsonType": "object", "properties": { "value": { "encrypt": { "keyId": [ { "$binary": { "base64": "AZUREAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Random", "bsonType": "date" } } } }, "azure_date_rand_auto_altname": { "bsonType": "object", "properties": { "value": { "encrypt": { "keyId": "/altname_azure", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Random", "bsonType": "date" } } } }, "azure_date_rand_explicit_id": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } }, "azure_date_rand_explicit_altname": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } }, "azure_date_det_auto_id": { "bsonType": "object", "properties": { "value": { "encrypt": { "keyId": [ { "$binary": { "base64": "AZUREAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic", "bsonType": "date" } } } }, "azure_date_det_explicit_id": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } }, "azure_date_det_explicit_altname": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } }, "azure_regex_rand_auto_id": { "bsonType": "object", "properties": { "value": { "encrypt": { "keyId": [ { "$binary": { "base64": "AZUREAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Random", "bsonType": "regex" } } } }, "azure_regex_rand_auto_altname": { "bsonType": "object", "properties": { "value": { "encrypt": { "keyId": "/altname_azure", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Random", "bsonType": "regex" } } } }, "azure_regex_rand_explicit_id": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } }, "azure_regex_rand_explicit_altname": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } }, "azure_regex_det_auto_id": { "bsonType": "object", "properties": { "value": { "encrypt": { "keyId": [ { "$binary": { "base64": "AZUREAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic", "bsonType": "regex" } } } }, "azure_regex_det_explicit_id": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } }, "azure_regex_det_explicit_altname": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } }, "azure_dbPointer_rand_auto_id": { "bsonType": "object", "properties": { "value": { "encrypt": { "keyId": [ { "$binary": { "base64": "AZUREAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Random", "bsonType": "dbPointer" } } } }, "azure_dbPointer_rand_auto_altname": { "bsonType": "object", "properties": { "value": { "encrypt": { "keyId": "/altname_azure", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Random", "bsonType": "dbPointer" } } } }, "azure_dbPointer_rand_explicit_id": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } }, "azure_dbPointer_rand_explicit_altname": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } }, "azure_dbPointer_det_auto_id": { "bsonType": "object", "properties": { "value": { "encrypt": { "keyId": [ { "$binary": { "base64": "AZUREAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic", "bsonType": "dbPointer" } } } }, "azure_dbPointer_det_explicit_id": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } }, "azure_dbPointer_det_explicit_altname": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } }, "azure_javascript_rand_auto_id": { "bsonType": "object", "properties": { "value": { "encrypt": { "keyId": [ { "$binary": { "base64": "AZUREAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Random", "bsonType": "javascript" } } } }, "azure_javascript_rand_auto_altname": { "bsonType": "object", "properties": { "value": { "encrypt": { "keyId": "/altname_azure", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Random", "bsonType": "javascript" } } } }, "azure_javascript_rand_explicit_id": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } }, "azure_javascript_rand_explicit_altname": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } }, "azure_javascript_det_auto_id": { "bsonType": "object", "properties": { "value": { "encrypt": { "keyId": [ { "$binary": { "base64": "AZUREAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic", "bsonType": "javascript" } } } }, "azure_javascript_det_explicit_id": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } }, "azure_javascript_det_explicit_altname": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } }, "azure_symbol_rand_auto_id": { "bsonType": "object", "properties": { "value": { "encrypt": { "keyId": [ { "$binary": { "base64": "AZUREAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Random", "bsonType": "symbol" } } } }, "azure_symbol_rand_auto_altname": { "bsonType": "object", "properties": { "value": { "encrypt": { "keyId": "/altname_azure", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Random", "bsonType": "symbol" } } } }, "azure_symbol_rand_explicit_id": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } }, "azure_symbol_rand_explicit_altname": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } }, "azure_symbol_det_auto_id": { "bsonType": "object", "properties": { "value": { "encrypt": { "keyId": [ { "$binary": { "base64": "AZUREAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic", "bsonType": "symbol" } } } }, "azure_symbol_det_explicit_id": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } }, "azure_symbol_det_explicit_altname": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } }, "azure_javascriptWithScope_rand_auto_id": { "bsonType": "object", "properties": { "value": { "encrypt": { "keyId": [ { "$binary": { "base64": "AZUREAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Random", "bsonType": "javascriptWithScope" } } } }, "azure_javascriptWithScope_rand_auto_altname": { "bsonType": "object", "properties": { "value": { "encrypt": { "keyId": "/altname_azure", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Random", "bsonType": "javascriptWithScope" } } } }, "azure_javascriptWithScope_rand_explicit_id": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } }, "azure_javascriptWithScope_rand_explicit_altname": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } }, "azure_int_rand_auto_id": { "bsonType": "object", "properties": { "value": { "encrypt": { "keyId": [ { "$binary": { "base64": "AZUREAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Random", "bsonType": "int" } } } }, "azure_int_rand_auto_altname": { "bsonType": "object", "properties": { "value": { "encrypt": { "keyId": "/altname_azure", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Random", "bsonType": "int" } } } }, "azure_int_rand_explicit_id": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } }, "azure_int_rand_explicit_altname": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } }, "azure_int_det_auto_id": { "bsonType": "object", "properties": { "value": { "encrypt": { "keyId": [ { "$binary": { "base64": "AZUREAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic", "bsonType": "int" } } } }, "azure_int_det_explicit_id": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } }, "azure_int_det_explicit_altname": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } }, "azure_timestamp_rand_auto_id": { "bsonType": "object", "properties": { "value": { "encrypt": { "keyId": [ { "$binary": { "base64": "AZUREAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Random", "bsonType": "timestamp" } } } }, "azure_timestamp_rand_auto_altname": { "bsonType": "object", "properties": { "value": { "encrypt": { "keyId": "/altname_azure", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Random", "bsonType": "timestamp" } } } }, "azure_timestamp_rand_explicit_id": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } }, "azure_timestamp_rand_explicit_altname": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } }, "azure_timestamp_det_auto_id": { "bsonType": "object", "properties": { "value": { "encrypt": { "keyId": [ { "$binary": { "base64": "AZUREAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic", "bsonType": "timestamp" } } } }, "azure_timestamp_det_explicit_id": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } }, "azure_timestamp_det_explicit_altname": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } }, "azure_long_rand_auto_id": { "bsonType": "object", "properties": { "value": { "encrypt": { "keyId": [ { "$binary": { "base64": "AZUREAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Random", "bsonType": "long" } } } }, "azure_long_rand_auto_altname": { "bsonType": "object", "properties": { "value": { "encrypt": { "keyId": "/altname_azure", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Random", "bsonType": "long" } } } }, "azure_long_rand_explicit_id": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } }, "azure_long_rand_explicit_altname": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } }, "azure_long_det_auto_id": { "bsonType": "object", "properties": { "value": { "encrypt": { "keyId": [ { "$binary": { "base64": "AZUREAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic", "bsonType": "long" } } } }, "azure_long_det_explicit_id": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } }, "azure_long_det_explicit_altname": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } }, "azure_decimal_rand_auto_id": { "bsonType": "object", "properties": { "value": { "encrypt": { "keyId": [ { "$binary": { "base64": "AZUREAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Random", "bsonType": "decimal" } } } }, "azure_decimal_rand_auto_altname": { "bsonType": "object", "properties": { "value": { "encrypt": { "keyId": "/altname_azure", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Random", "bsonType": "decimal" } } } }, "azure_decimal_rand_explicit_id": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } }, "azure_decimal_rand_explicit_altname": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } }, "gcp_double_rand_auto_id": { "bsonType": "object", "properties": { "value": { "encrypt": { "keyId": [ { "$binary": { "base64": "GCPAAAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Random", "bsonType": "double" } } } }, "gcp_double_rand_auto_altname": { "bsonType": "object", "properties": { "value": { "encrypt": { "keyId": "/altname_gcp", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Random", "bsonType": "double" } } } }, "gcp_double_rand_explicit_id": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } }, "gcp_double_rand_explicit_altname": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } }, "gcp_string_rand_auto_id": { "bsonType": "object", "properties": { "value": { "encrypt": { "keyId": [ { "$binary": { "base64": "GCPAAAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Random", "bsonType": "string" } } } }, "gcp_string_rand_auto_altname": { "bsonType": "object", "properties": { "value": { "encrypt": { "keyId": "/altname_gcp", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Random", "bsonType": "string" } } } }, "gcp_string_rand_explicit_id": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } }, "gcp_string_rand_explicit_altname": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } }, "gcp_string_det_auto_id": { "bsonType": "object", "properties": { "value": { "encrypt": { "keyId": [ { "$binary": { "base64": "GCPAAAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic", "bsonType": "string" } } } }, "gcp_string_det_explicit_id": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } }, "gcp_string_det_explicit_altname": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } }, "gcp_object_rand_auto_id": { "bsonType": "object", "properties": { "value": { "encrypt": { "keyId": [ { "$binary": { "base64": "GCPAAAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Random", "bsonType": "object" } } } }, "gcp_object_rand_auto_altname": { "bsonType": "object", "properties": { "value": { "encrypt": { "keyId": "/altname_gcp", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Random", "bsonType": "object" } } } }, "gcp_object_rand_explicit_id": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } }, "gcp_object_rand_explicit_altname": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } }, "gcp_array_rand_auto_id": { "bsonType": "object", "properties": { "value": { "encrypt": { "keyId": [ { "$binary": { "base64": "GCPAAAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Random", "bsonType": "array" } } } }, "gcp_array_rand_auto_altname": { "bsonType": "object", "properties": { "value": { "encrypt": { "keyId": "/altname_gcp", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Random", "bsonType": "array" } } } }, "gcp_array_rand_explicit_id": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } }, "gcp_array_rand_explicit_altname": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } }, "gcp_binData=00_rand_auto_id": { "bsonType": "object", "properties": { "value": { "encrypt": { "keyId": [ { "$binary": { "base64": "GCPAAAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Random", "bsonType": "binData" } } } }, "gcp_binData=00_rand_auto_altname": { "bsonType": "object", "properties": { "value": { "encrypt": { "keyId": "/altname_gcp", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Random", "bsonType": "binData" } } } }, "gcp_binData=00_rand_explicit_id": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } }, "gcp_binData=00_rand_explicit_altname": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } }, "gcp_binData=00_det_auto_id": { "bsonType": "object", "properties": { "value": { "encrypt": { "keyId": [ { "$binary": { "base64": "GCPAAAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic", "bsonType": "binData" } } } }, "gcp_binData=00_det_explicit_id": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } }, "gcp_binData=00_det_explicit_altname": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } }, "gcp_binData=04_rand_auto_id": { "bsonType": "object", "properties": { "value": { "encrypt": { "keyId": [ { "$binary": { "base64": "GCPAAAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Random", "bsonType": "binData" } } } }, "gcp_binData=04_rand_auto_altname": { "bsonType": "object", "properties": { "value": { "encrypt": { "keyId": "/altname_gcp", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Random", "bsonType": "binData" } } } }, "gcp_binData=04_rand_explicit_id": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } }, "gcp_binData=04_rand_explicit_altname": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } }, "gcp_binData=04_det_auto_id": { "bsonType": "object", "properties": { "value": { "encrypt": { "keyId": [ { "$binary": { "base64": "GCPAAAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic", "bsonType": "binData" } } } }, "gcp_binData=04_det_explicit_id": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } }, "gcp_binData=04_det_explicit_altname": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } }, "gcp_objectId_rand_auto_id": { "bsonType": "object", "properties": { "value": { "encrypt": { "keyId": [ { "$binary": { "base64": "GCPAAAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Random", "bsonType": "objectId" } } } }, "gcp_objectId_rand_auto_altname": { "bsonType": "object", "properties": { "value": { "encrypt": { "keyId": "/altname_gcp", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Random", "bsonType": "objectId" } } } }, "gcp_objectId_rand_explicit_id": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } }, "gcp_objectId_rand_explicit_altname": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } }, "gcp_objectId_det_auto_id": { "bsonType": "object", "properties": { "value": { "encrypt": { "keyId": [ { "$binary": { "base64": "GCPAAAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic", "bsonType": "objectId" } } } }, "gcp_objectId_det_explicit_id": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } }, "gcp_objectId_det_explicit_altname": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } }, "gcp_bool_rand_auto_id": { "bsonType": "object", "properties": { "value": { "encrypt": { "keyId": [ { "$binary": { "base64": "GCPAAAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Random", "bsonType": "bool" } } } }, "gcp_bool_rand_auto_altname": { "bsonType": "object", "properties": { "value": { "encrypt": { "keyId": "/altname_gcp", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Random", "bsonType": "bool" } } } }, "gcp_bool_rand_explicit_id": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } }, "gcp_bool_rand_explicit_altname": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } }, "gcp_date_rand_auto_id": { "bsonType": "object", "properties": { "value": { "encrypt": { "keyId": [ { "$binary": { "base64": "GCPAAAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Random", "bsonType": "date" } } } }, "gcp_date_rand_auto_altname": { "bsonType": "object", "properties": { "value": { "encrypt": { "keyId": "/altname_gcp", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Random", "bsonType": "date" } } } }, "gcp_date_rand_explicit_id": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } }, "gcp_date_rand_explicit_altname": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } }, "gcp_date_det_auto_id": { "bsonType": "object", "properties": { "value": { "encrypt": { "keyId": [ { "$binary": { "base64": "GCPAAAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic", "bsonType": "date" } } } }, "gcp_date_det_explicit_id": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } }, "gcp_date_det_explicit_altname": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } }, "gcp_regex_rand_auto_id": { "bsonType": "object", "properties": { "value": { "encrypt": { "keyId": [ { "$binary": { "base64": "GCPAAAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Random", "bsonType": "regex" } } } }, "gcp_regex_rand_auto_altname": { "bsonType": "object", "properties": { "value": { "encrypt": { "keyId": "/altname_gcp", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Random", "bsonType": "regex" } } } }, "gcp_regex_rand_explicit_id": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } }, "gcp_regex_rand_explicit_altname": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } }, "gcp_regex_det_auto_id": { "bsonType": "object", "properties": { "value": { "encrypt": { "keyId": [ { "$binary": { "base64": "GCPAAAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic", "bsonType": "regex" } } } }, "gcp_regex_det_explicit_id": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } }, "gcp_regex_det_explicit_altname": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } }, "gcp_dbPointer_rand_auto_id": { "bsonType": "object", "properties": { "value": { "encrypt": { "keyId": [ { "$binary": { "base64": "GCPAAAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Random", "bsonType": "dbPointer" } } } }, "gcp_dbPointer_rand_auto_altname": { "bsonType": "object", "properties": { "value": { "encrypt": { "keyId": "/altname_gcp", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Random", "bsonType": "dbPointer" } } } }, "gcp_dbPointer_rand_explicit_id": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } }, "gcp_dbPointer_rand_explicit_altname": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } }, "gcp_dbPointer_det_auto_id": { "bsonType": "object", "properties": { "value": { "encrypt": { "keyId": [ { "$binary": { "base64": "GCPAAAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic", "bsonType": "dbPointer" } } } }, "gcp_dbPointer_det_explicit_id": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } }, "gcp_dbPointer_det_explicit_altname": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } }, "gcp_javascript_rand_auto_id": { "bsonType": "object", "properties": { "value": { "encrypt": { "keyId": [ { "$binary": { "base64": "GCPAAAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Random", "bsonType": "javascript" } } } }, "gcp_javascript_rand_auto_altname": { "bsonType": "object", "properties": { "value": { "encrypt": { "keyId": "/altname_gcp", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Random", "bsonType": "javascript" } } } }, "gcp_javascript_rand_explicit_id": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } }, "gcp_javascript_rand_explicit_altname": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } }, "gcp_javascript_det_auto_id": { "bsonType": "object", "properties": { "value": { "encrypt": { "keyId": [ { "$binary": { "base64": "GCPAAAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic", "bsonType": "javascript" } } } }, "gcp_javascript_det_explicit_id": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } }, "gcp_javascript_det_explicit_altname": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } }, "gcp_symbol_rand_auto_id": { "bsonType": "object", "properties": { "value": { "encrypt": { "keyId": [ { "$binary": { "base64": "GCPAAAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Random", "bsonType": "symbol" } } } }, "gcp_symbol_rand_auto_altname": { "bsonType": "object", "properties": { "value": { "encrypt": { "keyId": "/altname_gcp", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Random", "bsonType": "symbol" } } } }, "gcp_symbol_rand_explicit_id": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } }, "gcp_symbol_rand_explicit_altname": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } }, "gcp_symbol_det_auto_id": { "bsonType": "object", "properties": { "value": { "encrypt": { "keyId": [ { "$binary": { "base64": "GCPAAAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic", "bsonType": "symbol" } } } }, "gcp_symbol_det_explicit_id": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } }, "gcp_symbol_det_explicit_altname": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } }, "gcp_javascriptWithScope_rand_auto_id": { "bsonType": "object", "properties": { "value": { "encrypt": { "keyId": [ { "$binary": { "base64": "GCPAAAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Random", "bsonType": "javascriptWithScope" } } } }, "gcp_javascriptWithScope_rand_auto_altname": { "bsonType": "object", "properties": { "value": { "encrypt": { "keyId": "/altname_gcp", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Random", "bsonType": "javascriptWithScope" } } } }, "gcp_javascriptWithScope_rand_explicit_id": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } }, "gcp_javascriptWithScope_rand_explicit_altname": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } }, "gcp_int_rand_auto_id": { "bsonType": "object", "properties": { "value": { "encrypt": { "keyId": [ { "$binary": { "base64": "GCPAAAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Random", "bsonType": "int" } } } }, "gcp_int_rand_auto_altname": { "bsonType": "object", "properties": { "value": { "encrypt": { "keyId": "/altname_gcp", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Random", "bsonType": "int" } } } }, "gcp_int_rand_explicit_id": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } }, "gcp_int_rand_explicit_altname": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } }, "gcp_int_det_auto_id": { "bsonType": "object", "properties": { "value": { "encrypt": { "keyId": [ { "$binary": { "base64": "GCPAAAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic", "bsonType": "int" } } } }, "gcp_int_det_explicit_id": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } }, "gcp_int_det_explicit_altname": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } }, "gcp_timestamp_rand_auto_id": { "bsonType": "object", "properties": { "value": { "encrypt": { "keyId": [ { "$binary": { "base64": "GCPAAAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Random", "bsonType": "timestamp" } } } }, "gcp_timestamp_rand_auto_altname": { "bsonType": "object", "properties": { "value": { "encrypt": { "keyId": "/altname_gcp", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Random", "bsonType": "timestamp" } } } }, "gcp_timestamp_rand_explicit_id": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } }, "gcp_timestamp_rand_explicit_altname": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } }, "gcp_timestamp_det_auto_id": { "bsonType": "object", "properties": { "value": { "encrypt": { "keyId": [ { "$binary": { "base64": "GCPAAAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic", "bsonType": "timestamp" } } } }, "gcp_timestamp_det_explicit_id": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } }, "gcp_timestamp_det_explicit_altname": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } }, "gcp_long_rand_auto_id": { "bsonType": "object", "properties": { "value": { "encrypt": { "keyId": [ { "$binary": { "base64": "GCPAAAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Random", "bsonType": "long" } } } }, "gcp_long_rand_auto_altname": { "bsonType": "object", "properties": { "value": { "encrypt": { "keyId": "/altname_gcp", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Random", "bsonType": "long" } } } }, "gcp_long_rand_explicit_id": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } }, "gcp_long_rand_explicit_altname": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } }, "gcp_long_det_auto_id": { "bsonType": "object", "properties": { "value": { "encrypt": { "keyId": [ { "$binary": { "base64": "GCPAAAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic", "bsonType": "long" } } } }, "gcp_long_det_explicit_id": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } }, "gcp_long_det_explicit_altname": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } }, "gcp_decimal_rand_auto_id": { "bsonType": "object", "properties": { "value": { "encrypt": { "keyId": [ { "$binary": { "base64": "GCPAAAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Random", "bsonType": "decimal" } } } }, "gcp_decimal_rand_auto_altname": { "bsonType": "object", "properties": { "value": { "encrypt": { "keyId": "/altname_gcp", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Random", "bsonType": "decimal" } } } }, "gcp_decimal_rand_explicit_id": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } }, "gcp_decimal_rand_explicit_altname": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } }, "kmip_double_rand_auto_id": { "bsonType": "object", "properties": { "value": { "encrypt": { "keyId": [ { "$binary": { "base64": "KMIPAAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Random", "bsonType": "double" } } } }, "kmip_double_rand_auto_altname": { "bsonType": "object", "properties": { "value": { "encrypt": { "keyId": "/altname_kmip", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Random", "bsonType": "double" } } } }, "kmip_double_rand_explicit_id": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } }, "kmip_double_rand_explicit_altname": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } }, "kmip_string_rand_auto_id": { "bsonType": "object", "properties": { "value": { "encrypt": { "keyId": [ { "$binary": { "base64": "KMIPAAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Random", "bsonType": "string" } } } }, "kmip_string_rand_auto_altname": { "bsonType": "object", "properties": { "value": { "encrypt": { "keyId": "/altname_kmip", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Random", "bsonType": "string" } } } }, "kmip_string_rand_explicit_id": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } }, "kmip_string_rand_explicit_altname": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } }, "kmip_string_det_auto_id": { "bsonType": "object", "properties": { "value": { "encrypt": { "keyId": [ { "$binary": { "base64": "KMIPAAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic", "bsonType": "string" } } } }, "kmip_string_det_explicit_id": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } }, "kmip_string_det_explicit_altname": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } }, "kmip_object_rand_auto_id": { "bsonType": "object", "properties": { "value": { "encrypt": { "keyId": [ { "$binary": { "base64": "KMIPAAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Random", "bsonType": "object" } } } }, "kmip_object_rand_auto_altname": { "bsonType": "object", "properties": { "value": { "encrypt": { "keyId": "/altname_kmip", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Random", "bsonType": "object" } } } }, "kmip_object_rand_explicit_id": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } }, "kmip_object_rand_explicit_altname": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } }, "kmip_array_rand_auto_id": { "bsonType": "object", "properties": { "value": { "encrypt": { "keyId": [ { "$binary": { "base64": "KMIPAAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Random", "bsonType": "array" } } } }, "kmip_array_rand_auto_altname": { "bsonType": "object", "properties": { "value": { "encrypt": { "keyId": "/altname_kmip", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Random", "bsonType": "array" } } } }, "kmip_array_rand_explicit_id": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } }, "kmip_array_rand_explicit_altname": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } }, "kmip_binData=00_rand_auto_id": { "bsonType": "object", "properties": { "value": { "encrypt": { "keyId": [ { "$binary": { "base64": "KMIPAAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Random", "bsonType": "binData" } } } }, "kmip_binData=00_rand_auto_altname": { "bsonType": "object", "properties": { "value": { "encrypt": { "keyId": "/altname_kmip", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Random", "bsonType": "binData" } } } }, "kmip_binData=00_rand_explicit_id": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } }, "kmip_binData=00_rand_explicit_altname": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } }, "kmip_binData=00_det_auto_id": { "bsonType": "object", "properties": { "value": { "encrypt": { "keyId": [ { "$binary": { "base64": "KMIPAAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic", "bsonType": "binData" } } } }, "kmip_binData=00_det_explicit_id": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } }, "kmip_binData=00_det_explicit_altname": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } }, "kmip_binData=04_rand_auto_id": { "bsonType": "object", "properties": { "value": { "encrypt": { "keyId": [ { "$binary": { "base64": "KMIPAAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Random", "bsonType": "binData" } } } }, "kmip_binData=04_rand_auto_altname": { "bsonType": "object", "properties": { "value": { "encrypt": { "keyId": "/altname_kmip", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Random", "bsonType": "binData" } } } }, "kmip_binData=04_rand_explicit_id": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } }, "kmip_binData=04_rand_explicit_altname": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } }, "kmip_binData=04_det_auto_id": { "bsonType": "object", "properties": { "value": { "encrypt": { "keyId": [ { "$binary": { "base64": "KMIPAAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic", "bsonType": "binData" } } } }, "kmip_binData=04_det_explicit_id": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } }, "kmip_binData=04_det_explicit_altname": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } }, "kmip_objectId_rand_auto_id": { "bsonType": "object", "properties": { "value": { "encrypt": { "keyId": [ { "$binary": { "base64": "KMIPAAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Random", "bsonType": "objectId" } } } }, "kmip_objectId_rand_auto_altname": { "bsonType": "object", "properties": { "value": { "encrypt": { "keyId": "/altname_kmip", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Random", "bsonType": "objectId" } } } }, "kmip_objectId_rand_explicit_id": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } }, "kmip_objectId_rand_explicit_altname": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } }, "kmip_objectId_det_auto_id": { "bsonType": "object", "properties": { "value": { "encrypt": { "keyId": [ { "$binary": { "base64": "KMIPAAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic", "bsonType": "objectId" } } } }, "kmip_objectId_det_explicit_id": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } }, "kmip_objectId_det_explicit_altname": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } }, "kmip_bool_rand_auto_id": { "bsonType": "object", "properties": { "value": { "encrypt": { "keyId": [ { "$binary": { "base64": "KMIPAAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Random", "bsonType": "bool" } } } }, "kmip_bool_rand_auto_altname": { "bsonType": "object", "properties": { "value": { "encrypt": { "keyId": "/altname_kmip", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Random", "bsonType": "bool" } } } }, "kmip_bool_rand_explicit_id": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } }, "kmip_bool_rand_explicit_altname": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } }, "kmip_date_rand_auto_id": { "bsonType": "object", "properties": { "value": { "encrypt": { "keyId": [ { "$binary": { "base64": "KMIPAAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Random", "bsonType": "date" } } } }, "kmip_date_rand_auto_altname": { "bsonType": "object", "properties": { "value": { "encrypt": { "keyId": "/altname_kmip", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Random", "bsonType": "date" } } } }, "kmip_date_rand_explicit_id": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } }, "kmip_date_rand_explicit_altname": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } }, "kmip_date_det_auto_id": { "bsonType": "object", "properties": { "value": { "encrypt": { "keyId": [ { "$binary": { "base64": "KMIPAAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic", "bsonType": "date" } } } }, "kmip_date_det_explicit_id": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } }, "kmip_date_det_explicit_altname": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } }, "kmip_regex_rand_auto_id": { "bsonType": "object", "properties": { "value": { "encrypt": { "keyId": [ { "$binary": { "base64": "KMIPAAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Random", "bsonType": "regex" } } } }, "kmip_regex_rand_auto_altname": { "bsonType": "object", "properties": { "value": { "encrypt": { "keyId": "/altname_kmip", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Random", "bsonType": "regex" } } } }, "kmip_regex_rand_explicit_id": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } }, "kmip_regex_rand_explicit_altname": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } }, "kmip_regex_det_auto_id": { "bsonType": "object", "properties": { "value": { "encrypt": { "keyId": [ { "$binary": { "base64": "KMIPAAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic", "bsonType": "regex" } } } }, "kmip_regex_det_explicit_id": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } }, "kmip_regex_det_explicit_altname": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } }, "kmip_dbPointer_rand_auto_id": { "bsonType": "object", "properties": { "value": { "encrypt": { "keyId": [ { "$binary": { "base64": "KMIPAAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Random", "bsonType": "dbPointer" } } } }, "kmip_dbPointer_rand_auto_altname": { "bsonType": "object", "properties": { "value": { "encrypt": { "keyId": "/altname_kmip", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Random", "bsonType": "dbPointer" } } } }, "kmip_dbPointer_rand_explicit_id": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } }, "kmip_dbPointer_rand_explicit_altname": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } }, "kmip_dbPointer_det_auto_id": { "bsonType": "object", "properties": { "value": { "encrypt": { "keyId": [ { "$binary": { "base64": "KMIPAAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic", "bsonType": "dbPointer" } } } }, "kmip_dbPointer_det_explicit_id": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } }, "kmip_dbPointer_det_explicit_altname": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } }, "kmip_javascript_rand_auto_id": { "bsonType": "object", "properties": { "value": { "encrypt": { "keyId": [ { "$binary": { "base64": "KMIPAAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Random", "bsonType": "javascript" } } } }, "kmip_javascript_rand_auto_altname": { "bsonType": "object", "properties": { "value": { "encrypt": { "keyId": "/altname_kmip", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Random", "bsonType": "javascript" } } } }, "kmip_javascript_rand_explicit_id": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } }, "kmip_javascript_rand_explicit_altname": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } }, "kmip_javascript_det_auto_id": { "bsonType": "object", "properties": { "value": { "encrypt": { "keyId": [ { "$binary": { "base64": "KMIPAAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic", "bsonType": "javascript" } } } }, "kmip_javascript_det_explicit_id": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } }, "kmip_javascript_det_explicit_altname": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } }, "kmip_symbol_rand_auto_id": { "bsonType": "object", "properties": { "value": { "encrypt": { "keyId": [ { "$binary": { "base64": "KMIPAAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Random", "bsonType": "symbol" } } } }, "kmip_symbol_rand_auto_altname": { "bsonType": "object", "properties": { "value": { "encrypt": { "keyId": "/altname_kmip", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Random", "bsonType": "symbol" } } } }, "kmip_symbol_rand_explicit_id": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } }, "kmip_symbol_rand_explicit_altname": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } }, "kmip_symbol_det_auto_id": { "bsonType": "object", "properties": { "value": { "encrypt": { "keyId": [ { "$binary": { "base64": "KMIPAAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic", "bsonType": "symbol" } } } }, "kmip_symbol_det_explicit_id": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } }, "kmip_symbol_det_explicit_altname": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } }, "kmip_javascriptWithScope_rand_auto_id": { "bsonType": "object", "properties": { "value": { "encrypt": { "keyId": [ { "$binary": { "base64": "KMIPAAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Random", "bsonType": "javascriptWithScope" } } } }, "kmip_javascriptWithScope_rand_auto_altname": { "bsonType": "object", "properties": { "value": { "encrypt": { "keyId": "/altname_kmip", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Random", "bsonType": "javascriptWithScope" } } } }, "kmip_javascriptWithScope_rand_explicit_id": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } }, "kmip_javascriptWithScope_rand_explicit_altname": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } }, "kmip_int_rand_auto_id": { "bsonType": "object", "properties": { "value": { "encrypt": { "keyId": [ { "$binary": { "base64": "KMIPAAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Random", "bsonType": "int" } } } }, "kmip_int_rand_auto_altname": { "bsonType": "object", "properties": { "value": { "encrypt": { "keyId": "/altname_kmip", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Random", "bsonType": "int" } } } }, "kmip_int_rand_explicit_id": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } }, "kmip_int_rand_explicit_altname": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } }, "kmip_int_det_auto_id": { "bsonType": "object", "properties": { "value": { "encrypt": { "keyId": [ { "$binary": { "base64": "KMIPAAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic", "bsonType": "int" } } } }, "kmip_int_det_explicit_id": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } }, "kmip_int_det_explicit_altname": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } }, "kmip_timestamp_rand_auto_id": { "bsonType": "object", "properties": { "value": { "encrypt": { "keyId": [ { "$binary": { "base64": "KMIPAAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Random", "bsonType": "timestamp" } } } }, "kmip_timestamp_rand_auto_altname": { "bsonType": "object", "properties": { "value": { "encrypt": { "keyId": "/altname_kmip", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Random", "bsonType": "timestamp" } } } }, "kmip_timestamp_rand_explicit_id": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } }, "kmip_timestamp_rand_explicit_altname": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } }, "kmip_timestamp_det_auto_id": { "bsonType": "object", "properties": { "value": { "encrypt": { "keyId": [ { "$binary": { "base64": "KMIPAAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic", "bsonType": "timestamp" } } } }, "kmip_timestamp_det_explicit_id": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } }, "kmip_timestamp_det_explicit_altname": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } }, "kmip_long_rand_auto_id": { "bsonType": "object", "properties": { "value": { "encrypt": { "keyId": [ { "$binary": { "base64": "KMIPAAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Random", "bsonType": "long" } } } }, "kmip_long_rand_auto_altname": { "bsonType": "object", "properties": { "value": { "encrypt": { "keyId": "/altname_kmip", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Random", "bsonType": "long" } } } }, "kmip_long_rand_explicit_id": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } }, "kmip_long_rand_explicit_altname": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } }, "kmip_long_det_auto_id": { "bsonType": "object", "properties": { "value": { "encrypt": { "keyId": [ { "$binary": { "base64": "KMIPAAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic", "bsonType": "long" } } } }, "kmip_long_det_explicit_id": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } }, "kmip_long_det_explicit_altname": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } }, "kmip_decimal_rand_auto_id": { "bsonType": "object", "properties": { "value": { "encrypt": { "keyId": [ { "$binary": { "base64": "KMIPAAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Random", "bsonType": "decimal" } } } }, "kmip_decimal_rand_auto_altname": { "bsonType": "object", "properties": { "value": { "encrypt": { "keyId": "/altname_kmip", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Random", "bsonType": "decimal" } } } }, "kmip_decimal_rand_explicit_id": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } }, "kmip_decimal_rand_explicit_altname": { "bsonType": "object", "properties": { "value": { "bsonType": "binData" } } } } }mongodb-mongo-python-driver-509e9b7/test/client-side-encryption/corpus/corpus.json000066400000000000000000005230711462766011000305350ustar00rootroot00000000000000{ "_id": "client_side_encryption_corpus", "altname_aws": "aws", "altname_local": "local", "altname_azure": "azure", "altname_gcp": "gcp", "altname_kmip": "kmip", "aws_double_rand_auto_id": { "kms": "aws", "type": "double", "algo": "rand", "method": "auto", "identifier": "id", "allowed": true, "value": { "$numberDouble": "1.234" } }, "aws_double_rand_auto_altname": { "kms": "aws", "type": "double", "algo": "rand", "method": "auto", "identifier": "altname", "allowed": true, "value": { "$numberDouble": "1.234" } }, "aws_double_rand_explicit_id": { "kms": "aws", "type": "double", "algo": "rand", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$numberDouble": "1.234" } }, "aws_double_rand_explicit_altname": { "kms": "aws", "type": "double", "algo": "rand", "method": "explicit", "identifier": "altname", "allowed": true, "value": { "$numberDouble": "1.234" } }, "aws_double_det_explicit_id": { "kms": "aws", "type": "double", "algo": "det", "method": "explicit", "identifier": "id", "allowed": false, "value": { "$numberDouble": "1.234" } }, "aws_double_det_explicit_altname": { "kms": "aws", "type": "double", "algo": "det", "method": "explicit", "identifier": "altname", "allowed": false, "value": { "$numberDouble": "1.234" } }, "aws_string_rand_auto_id": { "kms": "aws", "type": "string", "algo": "rand", "method": "auto", "identifier": "id", "allowed": true, "value": "mongodb" }, "aws_string_rand_auto_altname": { "kms": "aws", "type": "string", "algo": "rand", "method": "auto", "identifier": "altname", "allowed": true, "value": "mongodb" }, "aws_string_rand_explicit_id": { "kms": "aws", "type": "string", "algo": "rand", "method": "explicit", "identifier": "id", "allowed": true, "value": "mongodb" }, "aws_string_rand_explicit_altname": { "kms": "aws", "type": "string", "algo": "rand", "method": "explicit", "identifier": "altname", "allowed": true, "value": "mongodb" }, "aws_string_det_auto_id": { "kms": "aws", "type": "string", "algo": "det", "method": "auto", "identifier": "id", "allowed": true, "value": "mongodb" }, "aws_string_det_explicit_id": { "kms": "aws", "type": "string", "algo": "det", "method": "explicit", "identifier": "id", "allowed": true, "value": "mongodb" }, "aws_string_det_explicit_altname": { "kms": "aws", "type": "string", "algo": "det", "method": "explicit", "identifier": "altname", "allowed": true, "value": "mongodb" }, "aws_object_rand_auto_id": { "kms": "aws", "type": "object", "algo": "rand", "method": "auto", "identifier": "id", "allowed": true, "value": { "x": { "$numberInt": "1" } } }, "aws_object_rand_auto_altname": { "kms": "aws", "type": "object", "algo": "rand", "method": "auto", "identifier": "altname", "allowed": true, "value": { "x": { "$numberInt": "1" } } }, "aws_object_rand_explicit_id": { "kms": "aws", "type": "object", "algo": "rand", "method": "explicit", "identifier": "id", "allowed": true, "value": { "x": { "$numberInt": "1" } } }, "aws_object_rand_explicit_altname": { "kms": "aws", "type": "object", "algo": "rand", "method": "explicit", "identifier": "altname", "allowed": true, "value": { "x": { "$numberInt": "1" } } }, "aws_object_det_explicit_id": { "kms": "aws", "type": "object", "algo": "det", "method": "explicit", "identifier": "id", "allowed": false, "value": { "x": { "$numberInt": "1" } } }, "aws_object_det_explicit_altname": { "kms": "aws", "type": "object", "algo": "det", "method": "explicit", "identifier": "altname", "allowed": false, "value": { "x": { "$numberInt": "1" } } }, "aws_array_rand_auto_id": { "kms": "aws", "type": "array", "algo": "rand", "method": "auto", "identifier": "id", "allowed": true, "value": [ { "$numberInt": "1" }, { "$numberInt": "2" }, { "$numberInt": "3" } ] }, "aws_array_rand_auto_altname": { "kms": "aws", "type": "array", "algo": "rand", "method": "auto", "identifier": "altname", "allowed": true, "value": [ { "$numberInt": "1" }, { "$numberInt": "2" }, { "$numberInt": "3" } ] }, "aws_array_rand_explicit_id": { "kms": "aws", "type": "array", "algo": "rand", "method": "explicit", "identifier": "id", "allowed": true, "value": [ { "$numberInt": "1" }, { "$numberInt": "2" }, { "$numberInt": "3" } ] }, "aws_array_rand_explicit_altname": { "kms": "aws", "type": "array", "algo": "rand", "method": "explicit", "identifier": "altname", "allowed": true, "value": [ { "$numberInt": "1" }, { "$numberInt": "2" }, { "$numberInt": "3" } ] }, "aws_array_det_explicit_id": { "kms": "aws", "type": "array", "algo": "det", "method": "explicit", "identifier": "id", "allowed": false, "value": [ { "$numberInt": "1" }, { "$numberInt": "2" }, { "$numberInt": "3" } ] }, "aws_array_det_explicit_altname": { "kms": "aws", "type": "array", "algo": "det", "method": "explicit", "identifier": "altname", "allowed": false, "value": [ { "$numberInt": "1" }, { "$numberInt": "2" }, { "$numberInt": "3" } ] }, "aws_binData=00_rand_auto_id": { "kms": "aws", "type": "binData=00", "algo": "rand", "method": "auto", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "AQIDBA==", "subType": "00" } } }, "aws_binData=00_rand_auto_altname": { "kms": "aws", "type": "binData=00", "algo": "rand", "method": "auto", "identifier": "altname", "allowed": true, "value": { "$binary": { "base64": "AQIDBA==", "subType": "00" } } }, "aws_binData=00_rand_explicit_id": { "kms": "aws", "type": "binData=00", "algo": "rand", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "AQIDBA==", "subType": "00" } } }, "aws_binData=00_rand_explicit_altname": { "kms": "aws", "type": "binData=00", "algo": "rand", "method": "explicit", "identifier": "altname", "allowed": true, "value": { "$binary": { "base64": "AQIDBA==", "subType": "00" } } }, "aws_binData=00_det_auto_id": { "kms": "aws", "type": "binData=00", "algo": "det", "method": "auto", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "AQIDBA==", "subType": "00" } } }, "aws_binData=00_det_explicit_id": { "kms": "aws", "type": "binData=00", "algo": "det", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "AQIDBA==", "subType": "00" } } }, "aws_binData=00_det_explicit_altname": { "kms": "aws", "type": "binData=00", "algo": "det", "method": "explicit", "identifier": "altname", "allowed": true, "value": { "$binary": { "base64": "AQIDBA==", "subType": "00" } } }, "aws_binData=04_rand_auto_id": { "kms": "aws", "type": "binData=04", "algo": "rand", "method": "auto", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "AAECAwQFBgcICQoLDA0ODw==", "subType": "04" } } }, "aws_binData=04_rand_auto_altname": { "kms": "aws", "type": "binData=04", "algo": "rand", "method": "auto", "identifier": "altname", "allowed": true, "value": { "$binary": { "base64": "AAECAwQFBgcICQoLDA0ODw==", "subType": "04" } } }, "aws_binData=04_rand_explicit_id": { "kms": "aws", "type": "binData=04", "algo": "rand", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "AAECAwQFBgcICQoLDA0ODw==", "subType": "04" } } }, "aws_binData=04_rand_explicit_altname": { "kms": "aws", "type": "binData=04", "algo": "rand", "method": "explicit", "identifier": "altname", "allowed": true, "value": { "$binary": { "base64": "AAECAwQFBgcICQoLDA0ODw==", "subType": "04" } } }, "aws_binData=04_det_auto_id": { "kms": "aws", "type": "binData=04", "algo": "det", "method": "auto", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "AAECAwQFBgcICQoLDA0ODw==", "subType": "04" } } }, "aws_binData=04_det_explicit_id": { "kms": "aws", "type": "binData=04", "algo": "det", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "AAECAwQFBgcICQoLDA0ODw==", "subType": "04" } } }, "aws_binData=04_det_explicit_altname": { "kms": "aws", "type": "binData=04", "algo": "det", "method": "explicit", "identifier": "altname", "allowed": true, "value": { "$binary": { "base64": "AAECAwQFBgcICQoLDA0ODw==", "subType": "04" } } }, "aws_undefined_rand_explicit_id": { "kms": "aws", "type": "undefined", "algo": "rand", "method": "explicit", "identifier": "id", "allowed": false, "value": { "$undefined": true } }, "aws_undefined_rand_explicit_altname": { "kms": "aws", "type": "undefined", "algo": "rand", "method": "explicit", "identifier": "altname", "allowed": false, "value": { "$undefined": true } }, "aws_undefined_det_explicit_id": { "kms": "aws", "type": "undefined", "algo": "det", "method": "explicit", "identifier": "id", "allowed": false, "value": { "$undefined": true } }, "aws_undefined_det_explicit_altname": { "kms": "aws", "type": "undefined", "algo": "det", "method": "explicit", "identifier": "altname", "allowed": false, "value": { "$undefined": true } }, "aws_objectId_rand_auto_id": { "kms": "aws", "type": "objectId", "algo": "rand", "method": "auto", "identifier": "id", "allowed": true, "value": { "$oid": "01234567890abcdef0123456" } }, "aws_objectId_rand_auto_altname": { "kms": "aws", "type": "objectId", "algo": "rand", "method": "auto", "identifier": "altname", "allowed": true, "value": { "$oid": "01234567890abcdef0123456" } }, "aws_objectId_rand_explicit_id": { "kms": "aws", "type": "objectId", "algo": "rand", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$oid": "01234567890abcdef0123456" } }, "aws_objectId_rand_explicit_altname": { "kms": "aws", "type": "objectId", "algo": "rand", "method": "explicit", "identifier": "altname", "allowed": true, "value": { "$oid": "01234567890abcdef0123456" } }, "aws_objectId_det_auto_id": { "kms": "aws", "type": "objectId", "algo": "det", "method": "auto", "identifier": "id", "allowed": true, "value": { "$oid": "01234567890abcdef0123456" } }, "aws_objectId_det_explicit_id": { "kms": "aws", "type": "objectId", "algo": "det", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$oid": "01234567890abcdef0123456" } }, "aws_objectId_det_explicit_altname": { "kms": "aws", "type": "objectId", "algo": "det", "method": "explicit", "identifier": "altname", "allowed": true, "value": { "$oid": "01234567890abcdef0123456" } }, "aws_bool_rand_auto_id": { "kms": "aws", "type": "bool", "algo": "rand", "method": "auto", "identifier": "id", "allowed": true, "value": true }, "aws_bool_rand_auto_altname": { "kms": "aws", "type": "bool", "algo": "rand", "method": "auto", "identifier": "altname", "allowed": true, "value": true }, "aws_bool_rand_explicit_id": { "kms": "aws", "type": "bool", "algo": "rand", "method": "explicit", "identifier": "id", "allowed": true, "value": true }, "aws_bool_rand_explicit_altname": { "kms": "aws", "type": "bool", "algo": "rand", "method": "explicit", "identifier": "altname", "allowed": true, "value": true }, "aws_bool_det_explicit_id": { "kms": "aws", "type": "bool", "algo": "det", "method": "explicit", "identifier": "id", "allowed": false, "value": true }, "aws_bool_det_explicit_altname": { "kms": "aws", "type": "bool", "algo": "det", "method": "explicit", "identifier": "altname", "allowed": false, "value": true }, "aws_date_rand_auto_id": { "kms": "aws", "type": "date", "algo": "rand", "method": "auto", "identifier": "id", "allowed": true, "value": { "$date": { "$numberLong": "12345" } } }, "aws_date_rand_auto_altname": { "kms": "aws", "type": "date", "algo": "rand", "method": "auto", "identifier": "altname", "allowed": true, "value": { "$date": { "$numberLong": "12345" } } }, "aws_date_rand_explicit_id": { "kms": "aws", "type": "date", "algo": "rand", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$date": { "$numberLong": "12345" } } }, "aws_date_rand_explicit_altname": { "kms": "aws", "type": "date", "algo": "rand", "method": "explicit", "identifier": "altname", "allowed": true, "value": { "$date": { "$numberLong": "12345" } } }, "aws_date_det_auto_id": { "kms": "aws", "type": "date", "algo": "det", "method": "auto", "identifier": "id", "allowed": true, "value": { "$date": { "$numberLong": "12345" } } }, "aws_date_det_explicit_id": { "kms": "aws", "type": "date", "algo": "det", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$date": { "$numberLong": "12345" } } }, "aws_date_det_explicit_altname": { "kms": "aws", "type": "date", "algo": "det", "method": "explicit", "identifier": "altname", "allowed": true, "value": { "$date": { "$numberLong": "12345" } } }, "aws_null_rand_explicit_id": { "kms": "aws", "type": "null", "algo": "rand", "method": "explicit", "identifier": "id", "allowed": false, "value": null }, "aws_null_rand_explicit_altname": { "kms": "aws", "type": "null", "algo": "rand", "method": "explicit", "identifier": "altname", "allowed": false, "value": null }, "aws_null_det_explicit_id": { "kms": "aws", "type": "null", "algo": "det", "method": "explicit", "identifier": "id", "allowed": false, "value": null }, "aws_null_det_explicit_altname": { "kms": "aws", "type": "null", "algo": "det", "method": "explicit", "identifier": "altname", "allowed": false, "value": null }, "aws_regex_rand_auto_id": { "kms": "aws", "type": "regex", "algo": "rand", "method": "auto", "identifier": "id", "allowed": true, "value": { "$regularExpression": { "pattern": ".*", "options": "" } } }, "aws_regex_rand_auto_altname": { "kms": "aws", "type": "regex", "algo": "rand", "method": "auto", "identifier": "altname", "allowed": true, "value": { "$regularExpression": { "pattern": ".*", "options": "" } } }, "aws_regex_rand_explicit_id": { "kms": "aws", "type": "regex", "algo": "rand", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$regularExpression": { "pattern": ".*", "options": "" } } }, "aws_regex_rand_explicit_altname": { "kms": "aws", "type": "regex", "algo": "rand", "method": "explicit", "identifier": "altname", "allowed": true, "value": { "$regularExpression": { "pattern": ".*", "options": "" } } }, "aws_regex_det_auto_id": { "kms": "aws", "type": "regex", "algo": "det", "method": "auto", "identifier": "id", "allowed": true, "value": { "$regularExpression": { "pattern": ".*", "options": "" } } }, "aws_regex_det_explicit_id": { "kms": "aws", "type": "regex", "algo": "det", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$regularExpression": { "pattern": ".*", "options": "" } } }, "aws_regex_det_explicit_altname": { "kms": "aws", "type": "regex", "algo": "det", "method": "explicit", "identifier": "altname", "allowed": true, "value": { "$regularExpression": { "pattern": ".*", "options": "" } } }, "aws_dbPointer_rand_auto_id": { "kms": "aws", "type": "dbPointer", "algo": "rand", "method": "auto", "identifier": "id", "allowed": true, "value": { "$dbPointer": { "$ref": "db.example", "$id": { "$oid": "01234567890abcdef0123456" } } } }, "aws_dbPointer_rand_auto_altname": { "kms": "aws", "type": "dbPointer", "algo": "rand", "method": "auto", "identifier": "altname", "allowed": true, "value": { "$dbPointer": { "$ref": "db.example", "$id": { "$oid": "01234567890abcdef0123456" } } } }, "aws_dbPointer_rand_explicit_id": { "kms": "aws", "type": "dbPointer", "algo": "rand", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$dbPointer": { "$ref": "db.example", "$id": { "$oid": "01234567890abcdef0123456" } } } }, "aws_dbPointer_rand_explicit_altname": { "kms": "aws", "type": "dbPointer", "algo": "rand", "method": "explicit", "identifier": "altname", "allowed": true, "value": { "$dbPointer": { "$ref": "db.example", "$id": { "$oid": "01234567890abcdef0123456" } } } }, "aws_dbPointer_det_auto_id": { "kms": "aws", "type": "dbPointer", "algo": "det", "method": "auto", "identifier": "id", "allowed": true, "value": { "$dbPointer": { "$ref": "db.example", "$id": { "$oid": "01234567890abcdef0123456" } } } }, "aws_dbPointer_det_explicit_id": { "kms": "aws", "type": "dbPointer", "algo": "det", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$dbPointer": { "$ref": "db.example", "$id": { "$oid": "01234567890abcdef0123456" } } } }, "aws_dbPointer_det_explicit_altname": { "kms": "aws", "type": "dbPointer", "algo": "det", "method": "explicit", "identifier": "altname", "allowed": true, "value": { "$dbPointer": { "$ref": "db.example", "$id": { "$oid": "01234567890abcdef0123456" } } } }, "aws_javascript_rand_auto_id": { "kms": "aws", "type": "javascript", "algo": "rand", "method": "auto", "identifier": "id", "allowed": true, "value": { "$code": "x=1" } }, "aws_javascript_rand_auto_altname": { "kms": "aws", "type": "javascript", "algo": "rand", "method": "auto", "identifier": "altname", "allowed": true, "value": { "$code": "x=1" } }, "aws_javascript_rand_explicit_id": { "kms": "aws", "type": "javascript", "algo": "rand", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$code": "x=1" } }, "aws_javascript_rand_explicit_altname": { "kms": "aws", "type": "javascript", "algo": "rand", "method": "explicit", "identifier": "altname", "allowed": true, "value": { "$code": "x=1" } }, "aws_javascript_det_auto_id": { "kms": "aws", "type": "javascript", "algo": "det", "method": "auto", "identifier": "id", "allowed": true, "value": { "$code": "x=1" } }, "aws_javascript_det_explicit_id": { "kms": "aws", "type": "javascript", "algo": "det", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$code": "x=1" } }, "aws_javascript_det_explicit_altname": { "kms": "aws", "type": "javascript", "algo": "det", "method": "explicit", "identifier": "altname", "allowed": true, "value": { "$code": "x=1" } }, "aws_symbol_rand_auto_id": { "kms": "aws", "type": "symbol", "algo": "rand", "method": "auto", "identifier": "id", "allowed": true, "value": { "$symbol": "mongodb-symbol" } }, "aws_symbol_rand_auto_altname": { "kms": "aws", "type": "symbol", "algo": "rand", "method": "auto", "identifier": "altname", "allowed": true, "value": { "$symbol": "mongodb-symbol" } }, "aws_symbol_rand_explicit_id": { "kms": "aws", "type": "symbol", "algo": "rand", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$symbol": "mongodb-symbol" } }, "aws_symbol_rand_explicit_altname": { "kms": "aws", "type": "symbol", "algo": "rand", "method": "explicit", "identifier": "altname", "allowed": true, "value": { "$symbol": "mongodb-symbol" } }, "aws_symbol_det_auto_id": { "kms": "aws", "type": "symbol", "algo": "det", "method": "auto", "identifier": "id", "allowed": true, "value": { "$symbol": "mongodb-symbol" } }, "aws_symbol_det_explicit_id": { "kms": "aws", "type": "symbol", "algo": "det", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$symbol": "mongodb-symbol" } }, "aws_symbol_det_explicit_altname": { "kms": "aws", "type": "symbol", "algo": "det", "method": "explicit", "identifier": "altname", "allowed": true, "value": { "$symbol": "mongodb-symbol" } }, "aws_javascriptWithScope_rand_auto_id": { "kms": "aws", "type": "javascriptWithScope", "algo": "rand", "method": "auto", "identifier": "id", "allowed": true, "value": { "$code": "x=1", "$scope": {} } }, "aws_javascriptWithScope_rand_auto_altname": { "kms": "aws", "type": "javascriptWithScope", "algo": "rand", "method": "auto", "identifier": "altname", "allowed": true, "value": { "$code": "x=1", "$scope": {} } }, "aws_javascriptWithScope_rand_explicit_id": { "kms": "aws", "type": "javascriptWithScope", "algo": "rand", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$code": "x=1", "$scope": {} } }, "aws_javascriptWithScope_rand_explicit_altname": { "kms": "aws", "type": "javascriptWithScope", "algo": "rand", "method": "explicit", "identifier": "altname", "allowed": true, "value": { "$code": "x=1", "$scope": {} } }, "aws_javascriptWithScope_det_explicit_id": { "kms": "aws", "type": "javascriptWithScope", "algo": "det", "method": "explicit", "identifier": "id", "allowed": false, "value": { "$code": "x=1", "$scope": {} } }, "aws_javascriptWithScope_det_explicit_altname": { "kms": "aws", "type": "javascriptWithScope", "algo": "det", "method": "explicit", "identifier": "altname", "allowed": false, "value": { "$code": "x=1", "$scope": {} } }, "aws_int_rand_auto_id": { "kms": "aws", "type": "int", "algo": "rand", "method": "auto", "identifier": "id", "allowed": true, "value": { "$numberInt": "123" } }, "aws_int_rand_auto_altname": { "kms": "aws", "type": "int", "algo": "rand", "method": "auto", "identifier": "altname", "allowed": true, "value": { "$numberInt": "123" } }, "aws_int_rand_explicit_id": { "kms": "aws", "type": "int", "algo": "rand", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$numberInt": "123" } }, "aws_int_rand_explicit_altname": { "kms": "aws", "type": "int", "algo": "rand", "method": "explicit", "identifier": "altname", "allowed": true, "value": { "$numberInt": "123" } }, "aws_int_det_auto_id": { "kms": "aws", "type": "int", "algo": "det", "method": "auto", "identifier": "id", "allowed": true, "value": { "$numberInt": "123" } }, "aws_int_det_explicit_id": { "kms": "aws", "type": "int", "algo": "det", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$numberInt": "123" } }, "aws_int_det_explicit_altname": { "kms": "aws", "type": "int", "algo": "det", "method": "explicit", "identifier": "altname", "allowed": true, "value": { "$numberInt": "123" } }, "aws_timestamp_rand_auto_id": { "kms": "aws", "type": "timestamp", "algo": "rand", "method": "auto", "identifier": "id", "allowed": true, "value": { "$timestamp": { "t": 0, "i": 12345 } } }, "aws_timestamp_rand_auto_altname": { "kms": "aws", "type": "timestamp", "algo": "rand", "method": "auto", "identifier": "altname", "allowed": true, "value": { "$timestamp": { "t": 0, "i": 12345 } } }, "aws_timestamp_rand_explicit_id": { "kms": "aws", "type": "timestamp", "algo": "rand", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$timestamp": { "t": 0, "i": 12345 } } }, "aws_timestamp_rand_explicit_altname": { "kms": "aws", "type": "timestamp", "algo": "rand", "method": "explicit", "identifier": "altname", "allowed": true, "value": { "$timestamp": { "t": 0, "i": 12345 } } }, "aws_timestamp_det_auto_id": { "kms": "aws", "type": "timestamp", "algo": "det", "method": "auto", "identifier": "id", "allowed": true, "value": { "$timestamp": { "t": 0, "i": 12345 } } }, "aws_timestamp_det_explicit_id": { "kms": "aws", "type": "timestamp", "algo": "det", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$timestamp": { "t": 0, "i": 12345 } } }, "aws_timestamp_det_explicit_altname": { "kms": "aws", "type": "timestamp", "algo": "det", "method": "explicit", "identifier": "altname", "allowed": true, "value": { "$timestamp": { "t": 0, "i": 12345 } } }, "aws_long_rand_auto_id": { "kms": "aws", "type": "long", "algo": "rand", "method": "auto", "identifier": "id", "allowed": true, "value": { "$numberLong": "456" } }, "aws_long_rand_auto_altname": { "kms": "aws", "type": "long", "algo": "rand", "method": "auto", "identifier": "altname", "allowed": true, "value": { "$numberLong": "456" } }, "aws_long_rand_explicit_id": { "kms": "aws", "type": "long", "algo": "rand", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$numberLong": "456" } }, "aws_long_rand_explicit_altname": { "kms": "aws", "type": "long", "algo": "rand", "method": "explicit", "identifier": "altname", "allowed": true, "value": { "$numberLong": "456" } }, "aws_long_det_auto_id": { "kms": "aws", "type": "long", "algo": "det", "method": "auto", "identifier": "id", "allowed": true, "value": { "$numberLong": "456" } }, "aws_long_det_explicit_id": { "kms": "aws", "type": "long", "algo": "det", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$numberLong": "456" } }, "aws_long_det_explicit_altname": { "kms": "aws", "type": "long", "algo": "det", "method": "explicit", "identifier": "altname", "allowed": true, "value": { "$numberLong": "456" } }, "aws_decimal_rand_auto_id": { "kms": "aws", "type": "decimal", "algo": "rand", "method": "auto", "identifier": "id", "allowed": true, "value": { "$numberDecimal": "1.234" } }, "aws_decimal_rand_auto_altname": { "kms": "aws", "type": "decimal", "algo": "rand", "method": "auto", "identifier": "altname", "allowed": true, "value": { "$numberDecimal": "1.234" } }, "aws_decimal_rand_explicit_id": { "kms": "aws", "type": "decimal", "algo": "rand", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$numberDecimal": "1.234" } }, "aws_decimal_rand_explicit_altname": { "kms": "aws", "type": "decimal", "algo": "rand", "method": "explicit", "identifier": "altname", "allowed": true, "value": { "$numberDecimal": "1.234" } }, "aws_decimal_det_explicit_id": { "kms": "aws", "type": "decimal", "algo": "det", "method": "explicit", "identifier": "id", "allowed": false, "value": { "$numberDecimal": "1.234" } }, "aws_decimal_det_explicit_altname": { "kms": "aws", "type": "decimal", "algo": "det", "method": "explicit", "identifier": "altname", "allowed": false, "value": { "$numberDecimal": "1.234" } }, "aws_minKey_rand_explicit_id": { "kms": "aws", "type": "minKey", "algo": "rand", "method": "explicit", "identifier": "id", "allowed": false, "value": { "$minKey": 1 } }, "aws_minKey_rand_explicit_altname": { "kms": "aws", "type": "minKey", "algo": "rand", "method": "explicit", "identifier": "altname", "allowed": false, "value": { "$minKey": 1 } }, "aws_minKey_det_explicit_id": { "kms": "aws", "type": "minKey", "algo": "det", "method": "explicit", "identifier": "id", "allowed": false, "value": { "$minKey": 1 } }, "aws_minKey_det_explicit_altname": { "kms": "aws", "type": "minKey", "algo": "det", "method": "explicit", "identifier": "altname", "allowed": false, "value": { "$minKey": 1 } }, "aws_maxKey_rand_explicit_id": { "kms": "aws", "type": "maxKey", "algo": "rand", "method": "explicit", "identifier": "id", "allowed": false, "value": { "$maxKey": 1 } }, "aws_maxKey_rand_explicit_altname": { "kms": "aws", "type": "maxKey", "algo": "rand", "method": "explicit", "identifier": "altname", "allowed": false, "value": { "$maxKey": 1 } }, "aws_maxKey_det_explicit_id": { "kms": "aws", "type": "maxKey", "algo": "det", "method": "explicit", "identifier": "id", "allowed": false, "value": { "$maxKey": 1 } }, "aws_maxKey_det_explicit_altname": { "kms": "aws", "type": "maxKey", "algo": "det", "method": "explicit", "identifier": "altname", "allowed": false, "value": { "$maxKey": 1 } }, "local_double_rand_auto_id": { "kms": "local", "type": "double", "algo": "rand", "method": "auto", "identifier": "id", "allowed": true, "value": { "$numberDouble": "1.234" } }, "local_double_rand_auto_altname": { "kms": "local", "type": "double", "algo": "rand", "method": "auto", "identifier": "altname", "allowed": true, "value": { "$numberDouble": "1.234" } }, "local_double_rand_explicit_id": { "kms": "local", "type": "double", "algo": "rand", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$numberDouble": "1.234" } }, "local_double_rand_explicit_altname": { "kms": "local", "type": "double", "algo": "rand", "method": "explicit", "identifier": "altname", "allowed": true, "value": { "$numberDouble": "1.234" } }, "local_double_det_explicit_id": { "kms": "local", "type": "double", "algo": "det", "method": "explicit", "identifier": "id", "allowed": false, "value": { "$numberDouble": "1.234" } }, "local_double_det_explicit_altname": { "kms": "local", "type": "double", "algo": "det", "method": "explicit", "identifier": "altname", "allowed": false, "value": { "$numberDouble": "1.234" } }, "local_string_rand_auto_id": { "kms": "local", "type": "string", "algo": "rand", "method": "auto", "identifier": "id", "allowed": true, "value": "mongodb" }, "local_string_rand_auto_altname": { "kms": "local", "type": "string", "algo": "rand", "method": "auto", "identifier": "altname", "allowed": true, "value": "mongodb" }, "local_string_rand_explicit_id": { "kms": "local", "type": "string", "algo": "rand", "method": "explicit", "identifier": "id", "allowed": true, "value": "mongodb" }, "local_string_rand_explicit_altname": { "kms": "local", "type": "string", "algo": "rand", "method": "explicit", "identifier": "altname", "allowed": true, "value": "mongodb" }, "local_string_det_auto_id": { "kms": "local", "type": "string", "algo": "det", "method": "auto", "identifier": "id", "allowed": true, "value": "mongodb" }, "local_string_det_explicit_id": { "kms": "local", "type": "string", "algo": "det", "method": "explicit", "identifier": "id", "allowed": true, "value": "mongodb" }, "local_string_det_explicit_altname": { "kms": "local", "type": "string", "algo": "det", "method": "explicit", "identifier": "altname", "allowed": true, "value": "mongodb" }, "local_object_rand_auto_id": { "kms": "local", "type": "object", "algo": "rand", "method": "auto", "identifier": "id", "allowed": true, "value": { "x": { "$numberInt": "1" } } }, "local_object_rand_auto_altname": { "kms": "local", "type": "object", "algo": "rand", "method": "auto", "identifier": "altname", "allowed": true, "value": { "x": { "$numberInt": "1" } } }, "local_object_rand_explicit_id": { "kms": "local", "type": "object", "algo": "rand", "method": "explicit", "identifier": "id", "allowed": true, "value": { "x": { "$numberInt": "1" } } }, "local_object_rand_explicit_altname": { "kms": "local", "type": "object", "algo": "rand", "method": "explicit", "identifier": "altname", "allowed": true, "value": { "x": { "$numberInt": "1" } } }, "local_object_det_explicit_id": { "kms": "local", "type": "object", "algo": "det", "method": "explicit", "identifier": "id", "allowed": false, "value": { "x": { "$numberInt": "1" } } }, "local_object_det_explicit_altname": { "kms": "local", "type": "object", "algo": "det", "method": "explicit", "identifier": "altname", "allowed": false, "value": { "x": { "$numberInt": "1" } } }, "local_array_rand_auto_id": { "kms": "local", "type": "array", "algo": "rand", "method": "auto", "identifier": "id", "allowed": true, "value": [ { "$numberInt": "1" }, { "$numberInt": "2" }, { "$numberInt": "3" } ] }, "local_array_rand_auto_altname": { "kms": "local", "type": "array", "algo": "rand", "method": "auto", "identifier": "altname", "allowed": true, "value": [ { "$numberInt": "1" }, { "$numberInt": "2" }, { "$numberInt": "3" } ] }, "local_array_rand_explicit_id": { "kms": "local", "type": "array", "algo": "rand", "method": "explicit", "identifier": "id", "allowed": true, "value": [ { "$numberInt": "1" }, { "$numberInt": "2" }, { "$numberInt": "3" } ] }, "local_array_rand_explicit_altname": { "kms": "local", "type": "array", "algo": "rand", "method": "explicit", "identifier": "altname", "allowed": true, "value": [ { "$numberInt": "1" }, { "$numberInt": "2" }, { "$numberInt": "3" } ] }, "local_array_det_explicit_id": { "kms": "local", "type": "array", "algo": "det", "method": "explicit", "identifier": "id", "allowed": false, "value": [ { "$numberInt": "1" }, { "$numberInt": "2" }, { "$numberInt": "3" } ] }, "local_array_det_explicit_altname": { "kms": "local", "type": "array", "algo": "det", "method": "explicit", "identifier": "altname", "allowed": false, "value": [ { "$numberInt": "1" }, { "$numberInt": "2" }, { "$numberInt": "3" } ] }, "local_binData=00_rand_auto_id": { "kms": "local", "type": "binData=00", "algo": "rand", "method": "auto", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "AQIDBA==", "subType": "00" } } }, "local_binData=00_rand_auto_altname": { "kms": "local", "type": "binData=00", "algo": "rand", "method": "auto", "identifier": "altname", "allowed": true, "value": { "$binary": { "base64": "AQIDBA==", "subType": "00" } } }, "local_binData=00_rand_explicit_id": { "kms": "local", "type": "binData=00", "algo": "rand", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "AQIDBA==", "subType": "00" } } }, "local_binData=00_rand_explicit_altname": { "kms": "local", "type": "binData=00", "algo": "rand", "method": "explicit", "identifier": "altname", "allowed": true, "value": { "$binary": { "base64": "AQIDBA==", "subType": "00" } } }, "local_binData=00_det_auto_id": { "kms": "local", "type": "binData=00", "algo": "det", "method": "auto", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "AQIDBA==", "subType": "00" } } }, "local_binData=00_det_explicit_id": { "kms": "local", "type": "binData=00", "algo": "det", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "AQIDBA==", "subType": "00" } } }, "local_binData=00_det_explicit_altname": { "kms": "local", "type": "binData=00", "algo": "det", "method": "explicit", "identifier": "altname", "allowed": true, "value": { "$binary": { "base64": "AQIDBA==", "subType": "00" } } }, "local_binData=04_rand_auto_id": { "kms": "local", "type": "binData=04", "algo": "rand", "method": "auto", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "AAECAwQFBgcICQoLDA0ODw==", "subType": "04" } } }, "local_binData=04_rand_auto_altname": { "kms": "local", "type": "binData=04", "algo": "rand", "method": "auto", "identifier": "altname", "allowed": true, "value": { "$binary": { "base64": "AAECAwQFBgcICQoLDA0ODw==", "subType": "04" } } }, "local_binData=04_rand_explicit_id": { "kms": "local", "type": "binData=04", "algo": "rand", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "AAECAwQFBgcICQoLDA0ODw==", "subType": "04" } } }, "local_binData=04_rand_explicit_altname": { "kms": "local", "type": "binData=04", "algo": "rand", "method": "explicit", "identifier": "altname", "allowed": true, "value": { "$binary": { "base64": "AAECAwQFBgcICQoLDA0ODw==", "subType": "04" } } }, "local_binData=04_det_auto_id": { "kms": "local", "type": "binData=04", "algo": "det", "method": "auto", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "AAECAwQFBgcICQoLDA0ODw==", "subType": "04" } } }, "local_binData=04_det_explicit_id": { "kms": "local", "type": "binData=04", "algo": "det", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "AAECAwQFBgcICQoLDA0ODw==", "subType": "04" } } }, "local_binData=04_det_explicit_altname": { "kms": "local", "type": "binData=04", "algo": "det", "method": "explicit", "identifier": "altname", "allowed": true, "value": { "$binary": { "base64": "AAECAwQFBgcICQoLDA0ODw==", "subType": "04" } } }, "local_undefined_rand_explicit_id": { "kms": "local", "type": "undefined", "algo": "rand", "method": "explicit", "identifier": "id", "allowed": false, "value": { "$undefined": true } }, "local_undefined_rand_explicit_altname": { "kms": "local", "type": "undefined", "algo": "rand", "method": "explicit", "identifier": "altname", "allowed": false, "value": { "$undefined": true } }, "local_undefined_det_explicit_id": { "kms": "local", "type": "undefined", "algo": "det", "method": "explicit", "identifier": "id", "allowed": false, "value": { "$undefined": true } }, "local_undefined_det_explicit_altname": { "kms": "local", "type": "undefined", "algo": "det", "method": "explicit", "identifier": "altname", "allowed": false, "value": { "$undefined": true } }, "local_objectId_rand_auto_id": { "kms": "local", "type": "objectId", "algo": "rand", "method": "auto", "identifier": "id", "allowed": true, "value": { "$oid": "01234567890abcdef0123456" } }, "local_objectId_rand_auto_altname": { "kms": "local", "type": "objectId", "algo": "rand", "method": "auto", "identifier": "altname", "allowed": true, "value": { "$oid": "01234567890abcdef0123456" } }, "local_objectId_rand_explicit_id": { "kms": "local", "type": "objectId", "algo": "rand", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$oid": "01234567890abcdef0123456" } }, "local_objectId_rand_explicit_altname": { "kms": "local", "type": "objectId", "algo": "rand", "method": "explicit", "identifier": "altname", "allowed": true, "value": { "$oid": "01234567890abcdef0123456" } }, "local_objectId_det_auto_id": { "kms": "local", "type": "objectId", "algo": "det", "method": "auto", "identifier": "id", "allowed": true, "value": { "$oid": "01234567890abcdef0123456" } }, "local_objectId_det_explicit_id": { "kms": "local", "type": "objectId", "algo": "det", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$oid": "01234567890abcdef0123456" } }, "local_objectId_det_explicit_altname": { "kms": "local", "type": "objectId", "algo": "det", "method": "explicit", "identifier": "altname", "allowed": true, "value": { "$oid": "01234567890abcdef0123456" } }, "local_bool_rand_auto_id": { "kms": "local", "type": "bool", "algo": "rand", "method": "auto", "identifier": "id", "allowed": true, "value": true }, "local_bool_rand_auto_altname": { "kms": "local", "type": "bool", "algo": "rand", "method": "auto", "identifier": "altname", "allowed": true, "value": true }, "local_bool_rand_explicit_id": { "kms": "local", "type": "bool", "algo": "rand", "method": "explicit", "identifier": "id", "allowed": true, "value": true }, "local_bool_rand_explicit_altname": { "kms": "local", "type": "bool", "algo": "rand", "method": "explicit", "identifier": "altname", "allowed": true, "value": true }, "local_bool_det_explicit_id": { "kms": "local", "type": "bool", "algo": "det", "method": "explicit", "identifier": "id", "allowed": false, "value": true }, "local_bool_det_explicit_altname": { "kms": "local", "type": "bool", "algo": "det", "method": "explicit", "identifier": "altname", "allowed": false, "value": true }, "local_date_rand_auto_id": { "kms": "local", "type": "date", "algo": "rand", "method": "auto", "identifier": "id", "allowed": true, "value": { "$date": { "$numberLong": "12345" } } }, "local_date_rand_auto_altname": { "kms": "local", "type": "date", "algo": "rand", "method": "auto", "identifier": "altname", "allowed": true, "value": { "$date": { "$numberLong": "12345" } } }, "local_date_rand_explicit_id": { "kms": "local", "type": "date", "algo": "rand", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$date": { "$numberLong": "12345" } } }, "local_date_rand_explicit_altname": { "kms": "local", "type": "date", "algo": "rand", "method": "explicit", "identifier": "altname", "allowed": true, "value": { "$date": { "$numberLong": "12345" } } }, "local_date_det_auto_id": { "kms": "local", "type": "date", "algo": "det", "method": "auto", "identifier": "id", "allowed": true, "value": { "$date": { "$numberLong": "12345" } } }, "local_date_det_explicit_id": { "kms": "local", "type": "date", "algo": "det", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$date": { "$numberLong": "12345" } } }, "local_date_det_explicit_altname": { "kms": "local", "type": "date", "algo": "det", "method": "explicit", "identifier": "altname", "allowed": true, "value": { "$date": { "$numberLong": "12345" } } }, "local_null_rand_explicit_id": { "kms": "local", "type": "null", "algo": "rand", "method": "explicit", "identifier": "id", "allowed": false, "value": null }, "local_null_rand_explicit_altname": { "kms": "local", "type": "null", "algo": "rand", "method": "explicit", "identifier": "altname", "allowed": false, "value": null }, "local_null_det_explicit_id": { "kms": "local", "type": "null", "algo": "det", "method": "explicit", "identifier": "id", "allowed": false, "value": null }, "local_null_det_explicit_altname": { "kms": "local", "type": "null", "algo": "det", "method": "explicit", "identifier": "altname", "allowed": false, "value": null }, "local_regex_rand_auto_id": { "kms": "local", "type": "regex", "algo": "rand", "method": "auto", "identifier": "id", "allowed": true, "value": { "$regularExpression": { "pattern": ".*", "options": "" } } }, "local_regex_rand_auto_altname": { "kms": "local", "type": "regex", "algo": "rand", "method": "auto", "identifier": "altname", "allowed": true, "value": { "$regularExpression": { "pattern": ".*", "options": "" } } }, "local_regex_rand_explicit_id": { "kms": "local", "type": "regex", "algo": "rand", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$regularExpression": { "pattern": ".*", "options": "" } } }, "local_regex_rand_explicit_altname": { "kms": "local", "type": "regex", "algo": "rand", "method": "explicit", "identifier": "altname", "allowed": true, "value": { "$regularExpression": { "pattern": ".*", "options": "" } } }, "local_regex_det_auto_id": { "kms": "local", "type": "regex", "algo": "det", "method": "auto", "identifier": "id", "allowed": true, "value": { "$regularExpression": { "pattern": ".*", "options": "" } } }, "local_regex_det_explicit_id": { "kms": "local", "type": "regex", "algo": "det", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$regularExpression": { "pattern": ".*", "options": "" } } }, "local_regex_det_explicit_altname": { "kms": "local", "type": "regex", "algo": "det", "method": "explicit", "identifier": "altname", "allowed": true, "value": { "$regularExpression": { "pattern": ".*", "options": "" } } }, "local_dbPointer_rand_auto_id": { "kms": "local", "type": "dbPointer", "algo": "rand", "method": "auto", "identifier": "id", "allowed": true, "value": { "$dbPointer": { "$ref": "db.example", "$id": { "$oid": "01234567890abcdef0123456" } } } }, "local_dbPointer_rand_auto_altname": { "kms": "local", "type": "dbPointer", "algo": "rand", "method": "auto", "identifier": "altname", "allowed": true, "value": { "$dbPointer": { "$ref": "db.example", "$id": { "$oid": "01234567890abcdef0123456" } } } }, "local_dbPointer_rand_explicit_id": { "kms": "local", "type": "dbPointer", "algo": "rand", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$dbPointer": { "$ref": "db.example", "$id": { "$oid": "01234567890abcdef0123456" } } } }, "local_dbPointer_rand_explicit_altname": { "kms": "local", "type": "dbPointer", "algo": "rand", "method": "explicit", "identifier": "altname", "allowed": true, "value": { "$dbPointer": { "$ref": "db.example", "$id": { "$oid": "01234567890abcdef0123456" } } } }, "local_dbPointer_det_auto_id": { "kms": "local", "type": "dbPointer", "algo": "det", "method": "auto", "identifier": "id", "allowed": true, "value": { "$dbPointer": { "$ref": "db.example", "$id": { "$oid": "01234567890abcdef0123456" } } } }, "local_dbPointer_det_explicit_id": { "kms": "local", "type": "dbPointer", "algo": "det", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$dbPointer": { "$ref": "db.example", "$id": { "$oid": "01234567890abcdef0123456" } } } }, "local_dbPointer_det_explicit_altname": { "kms": "local", "type": "dbPointer", "algo": "det", "method": "explicit", "identifier": "altname", "allowed": true, "value": { "$dbPointer": { "$ref": "db.example", "$id": { "$oid": "01234567890abcdef0123456" } } } }, "local_javascript_rand_auto_id": { "kms": "local", "type": "javascript", "algo": "rand", "method": "auto", "identifier": "id", "allowed": true, "value": { "$code": "x=1" } }, "local_javascript_rand_auto_altname": { "kms": "local", "type": "javascript", "algo": "rand", "method": "auto", "identifier": "altname", "allowed": true, "value": { "$code": "x=1" } }, "local_javascript_rand_explicit_id": { "kms": "local", "type": "javascript", "algo": "rand", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$code": "x=1" } }, "local_javascript_rand_explicit_altname": { "kms": "local", "type": "javascript", "algo": "rand", "method": "explicit", "identifier": "altname", "allowed": true, "value": { "$code": "x=1" } }, "local_javascript_det_auto_id": { "kms": "local", "type": "javascript", "algo": "det", "method": "auto", "identifier": "id", "allowed": true, "value": { "$code": "x=1" } }, "local_javascript_det_explicit_id": { "kms": "local", "type": "javascript", "algo": "det", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$code": "x=1" } }, "local_javascript_det_explicit_altname": { "kms": "local", "type": "javascript", "algo": "det", "method": "explicit", "identifier": "altname", "allowed": true, "value": { "$code": "x=1" } }, "local_symbol_rand_auto_id": { "kms": "local", "type": "symbol", "algo": "rand", "method": "auto", "identifier": "id", "allowed": true, "value": { "$symbol": "mongodb-symbol" } }, "local_symbol_rand_auto_altname": { "kms": "local", "type": "symbol", "algo": "rand", "method": "auto", "identifier": "altname", "allowed": true, "value": { "$symbol": "mongodb-symbol" } }, "local_symbol_rand_explicit_id": { "kms": "local", "type": "symbol", "algo": "rand", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$symbol": "mongodb-symbol" } }, "local_symbol_rand_explicit_altname": { "kms": "local", "type": "symbol", "algo": "rand", "method": "explicit", "identifier": "altname", "allowed": true, "value": { "$symbol": "mongodb-symbol" } }, "local_symbol_det_auto_id": { "kms": "local", "type": "symbol", "algo": "det", "method": "auto", "identifier": "id", "allowed": true, "value": { "$symbol": "mongodb-symbol" } }, "local_symbol_det_explicit_id": { "kms": "local", "type": "symbol", "algo": "det", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$symbol": "mongodb-symbol" } }, "local_symbol_det_explicit_altname": { "kms": "local", "type": "symbol", "algo": "det", "method": "explicit", "identifier": "altname", "allowed": true, "value": { "$symbol": "mongodb-symbol" } }, "local_javascriptWithScope_rand_auto_id": { "kms": "local", "type": "javascriptWithScope", "algo": "rand", "method": "auto", "identifier": "id", "allowed": true, "value": { "$code": "x=1", "$scope": {} } }, "local_javascriptWithScope_rand_auto_altname": { "kms": "local", "type": "javascriptWithScope", "algo": "rand", "method": "auto", "identifier": "altname", "allowed": true, "value": { "$code": "x=1", "$scope": {} } }, "local_javascriptWithScope_rand_explicit_id": { "kms": "local", "type": "javascriptWithScope", "algo": "rand", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$code": "x=1", "$scope": {} } }, "local_javascriptWithScope_rand_explicit_altname": { "kms": "local", "type": "javascriptWithScope", "algo": "rand", "method": "explicit", "identifier": "altname", "allowed": true, "value": { "$code": "x=1", "$scope": {} } }, "local_javascriptWithScope_det_explicit_id": { "kms": "local", "type": "javascriptWithScope", "algo": "det", "method": "explicit", "identifier": "id", "allowed": false, "value": { "$code": "x=1", "$scope": {} } }, "local_javascriptWithScope_det_explicit_altname": { "kms": "local", "type": "javascriptWithScope", "algo": "det", "method": "explicit", "identifier": "altname", "allowed": false, "value": { "$code": "x=1", "$scope": {} } }, "local_int_rand_auto_id": { "kms": "local", "type": "int", "algo": "rand", "method": "auto", "identifier": "id", "allowed": true, "value": { "$numberInt": "123" } }, "local_int_rand_auto_altname": { "kms": "local", "type": "int", "algo": "rand", "method": "auto", "identifier": "altname", "allowed": true, "value": { "$numberInt": "123" } }, "local_int_rand_explicit_id": { "kms": "local", "type": "int", "algo": "rand", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$numberInt": "123" } }, "local_int_rand_explicit_altname": { "kms": "local", "type": "int", "algo": "rand", "method": "explicit", "identifier": "altname", "allowed": true, "value": { "$numberInt": "123" } }, "local_int_det_auto_id": { "kms": "local", "type": "int", "algo": "det", "method": "auto", "identifier": "id", "allowed": true, "value": { "$numberInt": "123" } }, "local_int_det_explicit_id": { "kms": "local", "type": "int", "algo": "det", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$numberInt": "123" } }, "local_int_det_explicit_altname": { "kms": "local", "type": "int", "algo": "det", "method": "explicit", "identifier": "altname", "allowed": true, "value": { "$numberInt": "123" } }, "local_timestamp_rand_auto_id": { "kms": "local", "type": "timestamp", "algo": "rand", "method": "auto", "identifier": "id", "allowed": true, "value": { "$timestamp": { "t": 0, "i": 12345 } } }, "local_timestamp_rand_auto_altname": { "kms": "local", "type": "timestamp", "algo": "rand", "method": "auto", "identifier": "altname", "allowed": true, "value": { "$timestamp": { "t": 0, "i": 12345 } } }, "local_timestamp_rand_explicit_id": { "kms": "local", "type": "timestamp", "algo": "rand", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$timestamp": { "t": 0, "i": 12345 } } }, "local_timestamp_rand_explicit_altname": { "kms": "local", "type": "timestamp", "algo": "rand", "method": "explicit", "identifier": "altname", "allowed": true, "value": { "$timestamp": { "t": 0, "i": 12345 } } }, "local_timestamp_det_auto_id": { "kms": "local", "type": "timestamp", "algo": "det", "method": "auto", "identifier": "id", "allowed": true, "value": { "$timestamp": { "t": 0, "i": 12345 } } }, "local_timestamp_det_explicit_id": { "kms": "local", "type": "timestamp", "algo": "det", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$timestamp": { "t": 0, "i": 12345 } } }, "local_timestamp_det_explicit_altname": { "kms": "local", "type": "timestamp", "algo": "det", "method": "explicit", "identifier": "altname", "allowed": true, "value": { "$timestamp": { "t": 0, "i": 12345 } } }, "local_long_rand_auto_id": { "kms": "local", "type": "long", "algo": "rand", "method": "auto", "identifier": "id", "allowed": true, "value": { "$numberLong": "456" } }, "local_long_rand_auto_altname": { "kms": "local", "type": "long", "algo": "rand", "method": "auto", "identifier": "altname", "allowed": true, "value": { "$numberLong": "456" } }, "local_long_rand_explicit_id": { "kms": "local", "type": "long", "algo": "rand", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$numberLong": "456" } }, "local_long_rand_explicit_altname": { "kms": "local", "type": "long", "algo": "rand", "method": "explicit", "identifier": "altname", "allowed": true, "value": { "$numberLong": "456" } }, "local_long_det_auto_id": { "kms": "local", "type": "long", "algo": "det", "method": "auto", "identifier": "id", "allowed": true, "value": { "$numberLong": "456" } }, "local_long_det_explicit_id": { "kms": "local", "type": "long", "algo": "det", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$numberLong": "456" } }, "local_long_det_explicit_altname": { "kms": "local", "type": "long", "algo": "det", "method": "explicit", "identifier": "altname", "allowed": true, "value": { "$numberLong": "456" } }, "local_decimal_rand_auto_id": { "kms": "local", "type": "decimal", "algo": "rand", "method": "auto", "identifier": "id", "allowed": true, "value": { "$numberDecimal": "1.234" } }, "local_decimal_rand_auto_altname": { "kms": "local", "type": "decimal", "algo": "rand", "method": "auto", "identifier": "altname", "allowed": true, "value": { "$numberDecimal": "1.234" } }, "local_decimal_rand_explicit_id": { "kms": "local", "type": "decimal", "algo": "rand", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$numberDecimal": "1.234" } }, "local_decimal_rand_explicit_altname": { "kms": "local", "type": "decimal", "algo": "rand", "method": "explicit", "identifier": "altname", "allowed": true, "value": { "$numberDecimal": "1.234" } }, "local_decimal_det_explicit_id": { "kms": "local", "type": "decimal", "algo": "det", "method": "explicit", "identifier": "id", "allowed": false, "value": { "$numberDecimal": "1.234" } }, "local_decimal_det_explicit_altname": { "kms": "local", "type": "decimal", "algo": "det", "method": "explicit", "identifier": "altname", "allowed": false, "value": { "$numberDecimal": "1.234" } }, "local_minKey_rand_explicit_id": { "kms": "local", "type": "minKey", "algo": "rand", "method": "explicit", "identifier": "id", "allowed": false, "value": { "$minKey": 1 } }, "local_minKey_rand_explicit_altname": { "kms": "local", "type": "minKey", "algo": "rand", "method": "explicit", "identifier": "altname", "allowed": false, "value": { "$minKey": 1 } }, "local_minKey_det_explicit_id": { "kms": "local", "type": "minKey", "algo": "det", "method": "explicit", "identifier": "id", "allowed": false, "value": { "$minKey": 1 } }, "local_minKey_det_explicit_altname": { "kms": "local", "type": "minKey", "algo": "det", "method": "explicit", "identifier": "altname", "allowed": false, "value": { "$minKey": 1 } }, "local_maxKey_rand_explicit_id": { "kms": "local", "type": "maxKey", "algo": "rand", "method": "explicit", "identifier": "id", "allowed": false, "value": { "$maxKey": 1 } }, "local_maxKey_rand_explicit_altname": { "kms": "local", "type": "maxKey", "algo": "rand", "method": "explicit", "identifier": "altname", "allowed": false, "value": { "$maxKey": 1 } }, "local_maxKey_det_explicit_id": { "kms": "local", "type": "maxKey", "algo": "det", "method": "explicit", "identifier": "id", "allowed": false, "value": { "$maxKey": 1 } }, "local_maxKey_det_explicit_altname": { "kms": "local", "type": "maxKey", "algo": "det", "method": "explicit", "identifier": "altname", "allowed": false, "value": { "$maxKey": 1 } }, "azure_double_rand_auto_id": { "kms": "azure", "type": "double", "algo": "rand", "method": "auto", "identifier": "id", "allowed": true, "value": { "$numberDouble": "1.234" } }, "azure_double_rand_auto_altname": { "kms": "azure", "type": "double", "algo": "rand", "method": "auto", "identifier": "altname", "allowed": true, "value": { "$numberDouble": "1.234" } }, "azure_double_rand_explicit_id": { "kms": "azure", "type": "double", "algo": "rand", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$numberDouble": "1.234" } }, "azure_double_rand_explicit_altname": { "kms": "azure", "type": "double", "algo": "rand", "method": "explicit", "identifier": "altname", "allowed": true, "value": { "$numberDouble": "1.234" } }, "azure_double_det_explicit_id": { "kms": "azure", "type": "double", "algo": "det", "method": "explicit", "identifier": "id", "allowed": false, "value": { "$numberDouble": "1.234" } }, "azure_double_det_explicit_altname": { "kms": "azure", "type": "double", "algo": "det", "method": "explicit", "identifier": "altname", "allowed": false, "value": { "$numberDouble": "1.234" } }, "azure_string_rand_auto_id": { "kms": "azure", "type": "string", "algo": "rand", "method": "auto", "identifier": "id", "allowed": true, "value": "mongodb" }, "azure_string_rand_auto_altname": { "kms": "azure", "type": "string", "algo": "rand", "method": "auto", "identifier": "altname", "allowed": true, "value": "mongodb" }, "azure_string_rand_explicit_id": { "kms": "azure", "type": "string", "algo": "rand", "method": "explicit", "identifier": "id", "allowed": true, "value": "mongodb" }, "azure_string_rand_explicit_altname": { "kms": "azure", "type": "string", "algo": "rand", "method": "explicit", "identifier": "altname", "allowed": true, "value": "mongodb" }, "azure_string_det_auto_id": { "kms": "azure", "type": "string", "algo": "det", "method": "auto", "identifier": "id", "allowed": true, "value": "mongodb" }, "azure_string_det_explicit_id": { "kms": "azure", "type": "string", "algo": "det", "method": "explicit", "identifier": "id", "allowed": true, "value": "mongodb" }, "azure_string_det_explicit_altname": { "kms": "azure", "type": "string", "algo": "det", "method": "explicit", "identifier": "altname", "allowed": true, "value": "mongodb" }, "azure_object_rand_auto_id": { "kms": "azure", "type": "object", "algo": "rand", "method": "auto", "identifier": "id", "allowed": true, "value": { "x": { "$numberInt": "1" } } }, "azure_object_rand_auto_altname": { "kms": "azure", "type": "object", "algo": "rand", "method": "auto", "identifier": "altname", "allowed": true, "value": { "x": { "$numberInt": "1" } } }, "azure_object_rand_explicit_id": { "kms": "azure", "type": "object", "algo": "rand", "method": "explicit", "identifier": "id", "allowed": true, "value": { "x": { "$numberInt": "1" } } }, "azure_object_rand_explicit_altname": { "kms": "azure", "type": "object", "algo": "rand", "method": "explicit", "identifier": "altname", "allowed": true, "value": { "x": { "$numberInt": "1" } } }, "azure_object_det_explicit_id": { "kms": "azure", "type": "object", "algo": "det", "method": "explicit", "identifier": "id", "allowed": false, "value": { "x": { "$numberInt": "1" } } }, "azure_object_det_explicit_altname": { "kms": "azure", "type": "object", "algo": "det", "method": "explicit", "identifier": "altname", "allowed": false, "value": { "x": { "$numberInt": "1" } } }, "azure_array_rand_auto_id": { "kms": "azure", "type": "array", "algo": "rand", "method": "auto", "identifier": "id", "allowed": true, "value": [ { "$numberInt": "1" }, { "$numberInt": "2" }, { "$numberInt": "3" } ] }, "azure_array_rand_auto_altname": { "kms": "azure", "type": "array", "algo": "rand", "method": "auto", "identifier": "altname", "allowed": true, "value": [ { "$numberInt": "1" }, { "$numberInt": "2" }, { "$numberInt": "3" } ] }, "azure_array_rand_explicit_id": { "kms": "azure", "type": "array", "algo": "rand", "method": "explicit", "identifier": "id", "allowed": true, "value": [ { "$numberInt": "1" }, { "$numberInt": "2" }, { "$numberInt": "3" } ] }, "azure_array_rand_explicit_altname": { "kms": "azure", "type": "array", "algo": "rand", "method": "explicit", "identifier": "altname", "allowed": true, "value": [ { "$numberInt": "1" }, { "$numberInt": "2" }, { "$numberInt": "3" } ] }, "azure_array_det_explicit_id": { "kms": "azure", "type": "array", "algo": "det", "method": "explicit", "identifier": "id", "allowed": false, "value": [ { "$numberInt": "1" }, { "$numberInt": "2" }, { "$numberInt": "3" } ] }, "azure_array_det_explicit_altname": { "kms": "azure", "type": "array", "algo": "det", "method": "explicit", "identifier": "altname", "allowed": false, "value": [ { "$numberInt": "1" }, { "$numberInt": "2" }, { "$numberInt": "3" } ] }, "azure_binData=00_rand_auto_id": { "kms": "azure", "type": "binData=00", "algo": "rand", "method": "auto", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "AQIDBA==", "subType": "00" } } }, "azure_binData=00_rand_auto_altname": { "kms": "azure", "type": "binData=00", "algo": "rand", "method": "auto", "identifier": "altname", "allowed": true, "value": { "$binary": { "base64": "AQIDBA==", "subType": "00" } } }, "azure_binData=00_rand_explicit_id": { "kms": "azure", "type": "binData=00", "algo": "rand", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "AQIDBA==", "subType": "00" } } }, "azure_binData=00_rand_explicit_altname": { "kms": "azure", "type": "binData=00", "algo": "rand", "method": "explicit", "identifier": "altname", "allowed": true, "value": { "$binary": { "base64": "AQIDBA==", "subType": "00" } } }, "azure_binData=00_det_auto_id": { "kms": "azure", "type": "binData=00", "algo": "det", "method": "auto", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "AQIDBA==", "subType": "00" } } }, "azure_binData=00_det_explicit_id": { "kms": "azure", "type": "binData=00", "algo": "det", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "AQIDBA==", "subType": "00" } } }, "azure_binData=00_det_explicit_altname": { "kms": "azure", "type": "binData=00", "algo": "det", "method": "explicit", "identifier": "altname", "allowed": true, "value": { "$binary": { "base64": "AQIDBA==", "subType": "00" } } }, "azure_binData=04_rand_auto_id": { "kms": "azure", "type": "binData=04", "algo": "rand", "method": "auto", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "AAECAwQFBgcICQoLDA0ODw==", "subType": "04" } } }, "azure_binData=04_rand_auto_altname": { "kms": "azure", "type": "binData=04", "algo": "rand", "method": "auto", "identifier": "altname", "allowed": true, "value": { "$binary": { "base64": "AAECAwQFBgcICQoLDA0ODw==", "subType": "04" } } }, "azure_binData=04_rand_explicit_id": { "kms": "azure", "type": "binData=04", "algo": "rand", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "AAECAwQFBgcICQoLDA0ODw==", "subType": "04" } } }, "azure_binData=04_rand_explicit_altname": { "kms": "azure", "type": "binData=04", "algo": "rand", "method": "explicit", "identifier": "altname", "allowed": true, "value": { "$binary": { "base64": "AAECAwQFBgcICQoLDA0ODw==", "subType": "04" } } }, "azure_binData=04_det_auto_id": { "kms": "azure", "type": "binData=04", "algo": "det", "method": "auto", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "AAECAwQFBgcICQoLDA0ODw==", "subType": "04" } } }, "azure_binData=04_det_explicit_id": { "kms": "azure", "type": "binData=04", "algo": "det", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "AAECAwQFBgcICQoLDA0ODw==", "subType": "04" } } }, "azure_binData=04_det_explicit_altname": { "kms": "azure", "type": "binData=04", "algo": "det", "method": "explicit", "identifier": "altname", "allowed": true, "value": { "$binary": { "base64": "AAECAwQFBgcICQoLDA0ODw==", "subType": "04" } } }, "azure_undefined_rand_explicit_id": { "kms": "azure", "type": "undefined", "algo": "rand", "method": "explicit", "identifier": "id", "allowed": false, "value": { "$undefined": true } }, "azure_undefined_rand_explicit_altname": { "kms": "azure", "type": "undefined", "algo": "rand", "method": "explicit", "identifier": "altname", "allowed": false, "value": { "$undefined": true } }, "azure_undefined_det_explicit_id": { "kms": "azure", "type": "undefined", "algo": "det", "method": "explicit", "identifier": "id", "allowed": false, "value": { "$undefined": true } }, "azure_undefined_det_explicit_altname": { "kms": "azure", "type": "undefined", "algo": "det", "method": "explicit", "identifier": "altname", "allowed": false, "value": { "$undefined": true } }, "azure_objectId_rand_auto_id": { "kms": "azure", "type": "objectId", "algo": "rand", "method": "auto", "identifier": "id", "allowed": true, "value": { "$oid": "01234567890abcdef0123456" } }, "azure_objectId_rand_auto_altname": { "kms": "azure", "type": "objectId", "algo": "rand", "method": "auto", "identifier": "altname", "allowed": true, "value": { "$oid": "01234567890abcdef0123456" } }, "azure_objectId_rand_explicit_id": { "kms": "azure", "type": "objectId", "algo": "rand", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$oid": "01234567890abcdef0123456" } }, "azure_objectId_rand_explicit_altname": { "kms": "azure", "type": "objectId", "algo": "rand", "method": "explicit", "identifier": "altname", "allowed": true, "value": { "$oid": "01234567890abcdef0123456" } }, "azure_objectId_det_auto_id": { "kms": "azure", "type": "objectId", "algo": "det", "method": "auto", "identifier": "id", "allowed": true, "value": { "$oid": "01234567890abcdef0123456" } }, "azure_objectId_det_explicit_id": { "kms": "azure", "type": "objectId", "algo": "det", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$oid": "01234567890abcdef0123456" } }, "azure_objectId_det_explicit_altname": { "kms": "azure", "type": "objectId", "algo": "det", "method": "explicit", "identifier": "altname", "allowed": true, "value": { "$oid": "01234567890abcdef0123456" } }, "azure_bool_rand_auto_id": { "kms": "azure", "type": "bool", "algo": "rand", "method": "auto", "identifier": "id", "allowed": true, "value": true }, "azure_bool_rand_auto_altname": { "kms": "azure", "type": "bool", "algo": "rand", "method": "auto", "identifier": "altname", "allowed": true, "value": true }, "azure_bool_rand_explicit_id": { "kms": "azure", "type": "bool", "algo": "rand", "method": "explicit", "identifier": "id", "allowed": true, "value": true }, "azure_bool_rand_explicit_altname": { "kms": "azure", "type": "bool", "algo": "rand", "method": "explicit", "identifier": "altname", "allowed": true, "value": true }, "azure_bool_det_explicit_id": { "kms": "azure", "type": "bool", "algo": "det", "method": "explicit", "identifier": "id", "allowed": false, "value": true }, "azure_bool_det_explicit_altname": { "kms": "azure", "type": "bool", "algo": "det", "method": "explicit", "identifier": "altname", "allowed": false, "value": true }, "azure_date_rand_auto_id": { "kms": "azure", "type": "date", "algo": "rand", "method": "auto", "identifier": "id", "allowed": true, "value": { "$date": { "$numberLong": "12345" } } }, "azure_date_rand_auto_altname": { "kms": "azure", "type": "date", "algo": "rand", "method": "auto", "identifier": "altname", "allowed": true, "value": { "$date": { "$numberLong": "12345" } } }, "azure_date_rand_explicit_id": { "kms": "azure", "type": "date", "algo": "rand", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$date": { "$numberLong": "12345" } } }, "azure_date_rand_explicit_altname": { "kms": "azure", "type": "date", "algo": "rand", "method": "explicit", "identifier": "altname", "allowed": true, "value": { "$date": { "$numberLong": "12345" } } }, "azure_date_det_auto_id": { "kms": "azure", "type": "date", "algo": "det", "method": "auto", "identifier": "id", "allowed": true, "value": { "$date": { "$numberLong": "12345" } } }, "azure_date_det_explicit_id": { "kms": "azure", "type": "date", "algo": "det", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$date": { "$numberLong": "12345" } } }, "azure_date_det_explicit_altname": { "kms": "azure", "type": "date", "algo": "det", "method": "explicit", "identifier": "altname", "allowed": true, "value": { "$date": { "$numberLong": "12345" } } }, "azure_null_rand_explicit_id": { "kms": "azure", "type": "null", "algo": "rand", "method": "explicit", "identifier": "id", "allowed": false, "value": null }, "azure_null_rand_explicit_altname": { "kms": "azure", "type": "null", "algo": "rand", "method": "explicit", "identifier": "altname", "allowed": false, "value": null }, "azure_null_det_explicit_id": { "kms": "azure", "type": "null", "algo": "det", "method": "explicit", "identifier": "id", "allowed": false, "value": null }, "azure_null_det_explicit_altname": { "kms": "azure", "type": "null", "algo": "det", "method": "explicit", "identifier": "altname", "allowed": false, "value": null }, "azure_regex_rand_auto_id": { "kms": "azure", "type": "regex", "algo": "rand", "method": "auto", "identifier": "id", "allowed": true, "value": { "$regularExpression": { "pattern": ".*", "options": "" } } }, "azure_regex_rand_auto_altname": { "kms": "azure", "type": "regex", "algo": "rand", "method": "auto", "identifier": "altname", "allowed": true, "value": { "$regularExpression": { "pattern": ".*", "options": "" } } }, "azure_regex_rand_explicit_id": { "kms": "azure", "type": "regex", "algo": "rand", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$regularExpression": { "pattern": ".*", "options": "" } } }, "azure_regex_rand_explicit_altname": { "kms": "azure", "type": "regex", "algo": "rand", "method": "explicit", "identifier": "altname", "allowed": true, "value": { "$regularExpression": { "pattern": ".*", "options": "" } } }, "azure_regex_det_auto_id": { "kms": "azure", "type": "regex", "algo": "det", "method": "auto", "identifier": "id", "allowed": true, "value": { "$regularExpression": { "pattern": ".*", "options": "" } } }, "azure_regex_det_explicit_id": { "kms": "azure", "type": "regex", "algo": "det", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$regularExpression": { "pattern": ".*", "options": "" } } }, "azure_regex_det_explicit_altname": { "kms": "azure", "type": "regex", "algo": "det", "method": "explicit", "identifier": "altname", "allowed": true, "value": { "$regularExpression": { "pattern": ".*", "options": "" } } }, "azure_dbPointer_rand_auto_id": { "kms": "azure", "type": "dbPointer", "algo": "rand", "method": "auto", "identifier": "id", "allowed": true, "value": { "$dbPointer": { "$ref": "db.example", "$id": { "$oid": "01234567890abcdef0123456" } } } }, "azure_dbPointer_rand_auto_altname": { "kms": "azure", "type": "dbPointer", "algo": "rand", "method": "auto", "identifier": "altname", "allowed": true, "value": { "$dbPointer": { "$ref": "db.example", "$id": { "$oid": "01234567890abcdef0123456" } } } }, "azure_dbPointer_rand_explicit_id": { "kms": "azure", "type": "dbPointer", "algo": "rand", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$dbPointer": { "$ref": "db.example", "$id": { "$oid": "01234567890abcdef0123456" } } } }, "azure_dbPointer_rand_explicit_altname": { "kms": "azure", "type": "dbPointer", "algo": "rand", "method": "explicit", "identifier": "altname", "allowed": true, "value": { "$dbPointer": { "$ref": "db.example", "$id": { "$oid": "01234567890abcdef0123456" } } } }, "azure_dbPointer_det_auto_id": { "kms": "azure", "type": "dbPointer", "algo": "det", "method": "auto", "identifier": "id", "allowed": true, "value": { "$dbPointer": { "$ref": "db.example", "$id": { "$oid": "01234567890abcdef0123456" } } } }, "azure_dbPointer_det_explicit_id": { "kms": "azure", "type": "dbPointer", "algo": "det", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$dbPointer": { "$ref": "db.example", "$id": { "$oid": "01234567890abcdef0123456" } } } }, "azure_dbPointer_det_explicit_altname": { "kms": "azure", "type": "dbPointer", "algo": "det", "method": "explicit", "identifier": "altname", "allowed": true, "value": { "$dbPointer": { "$ref": "db.example", "$id": { "$oid": "01234567890abcdef0123456" } } } }, "azure_javascript_rand_auto_id": { "kms": "azure", "type": "javascript", "algo": "rand", "method": "auto", "identifier": "id", "allowed": true, "value": { "$code": "x=1" } }, "azure_javascript_rand_auto_altname": { "kms": "azure", "type": "javascript", "algo": "rand", "method": "auto", "identifier": "altname", "allowed": true, "value": { "$code": "x=1" } }, "azure_javascript_rand_explicit_id": { "kms": "azure", "type": "javascript", "algo": "rand", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$code": "x=1" } }, "azure_javascript_rand_explicit_altname": { "kms": "azure", "type": "javascript", "algo": "rand", "method": "explicit", "identifier": "altname", "allowed": true, "value": { "$code": "x=1" } }, "azure_javascript_det_auto_id": { "kms": "azure", "type": "javascript", "algo": "det", "method": "auto", "identifier": "id", "allowed": true, "value": { "$code": "x=1" } }, "azure_javascript_det_explicit_id": { "kms": "azure", "type": "javascript", "algo": "det", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$code": "x=1" } }, "azure_javascript_det_explicit_altname": { "kms": "azure", "type": "javascript", "algo": "det", "method": "explicit", "identifier": "altname", "allowed": true, "value": { "$code": "x=1" } }, "azure_symbol_rand_auto_id": { "kms": "azure", "type": "symbol", "algo": "rand", "method": "auto", "identifier": "id", "allowed": true, "value": { "$symbol": "mongodb-symbol" } }, "azure_symbol_rand_auto_altname": { "kms": "azure", "type": "symbol", "algo": "rand", "method": "auto", "identifier": "altname", "allowed": true, "value": { "$symbol": "mongodb-symbol" } }, "azure_symbol_rand_explicit_id": { "kms": "azure", "type": "symbol", "algo": "rand", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$symbol": "mongodb-symbol" } }, "azure_symbol_rand_explicit_altname": { "kms": "azure", "type": "symbol", "algo": "rand", "method": "explicit", "identifier": "altname", "allowed": true, "value": { "$symbol": "mongodb-symbol" } }, "azure_symbol_det_auto_id": { "kms": "azure", "type": "symbol", "algo": "det", "method": "auto", "identifier": "id", "allowed": true, "value": { "$symbol": "mongodb-symbol" } }, "azure_symbol_det_explicit_id": { "kms": "azure", "type": "symbol", "algo": "det", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$symbol": "mongodb-symbol" } }, "azure_symbol_det_explicit_altname": { "kms": "azure", "type": "symbol", "algo": "det", "method": "explicit", "identifier": "altname", "allowed": true, "value": { "$symbol": "mongodb-symbol" } }, "azure_javascriptWithScope_rand_auto_id": { "kms": "azure", "type": "javascriptWithScope", "algo": "rand", "method": "auto", "identifier": "id", "allowed": true, "value": { "$code": "x=1", "$scope": {} } }, "azure_javascriptWithScope_rand_auto_altname": { "kms": "azure", "type": "javascriptWithScope", "algo": "rand", "method": "auto", "identifier": "altname", "allowed": true, "value": { "$code": "x=1", "$scope": {} } }, "azure_javascriptWithScope_rand_explicit_id": { "kms": "azure", "type": "javascriptWithScope", "algo": "rand", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$code": "x=1", "$scope": {} } }, "azure_javascriptWithScope_rand_explicit_altname": { "kms": "azure", "type": "javascriptWithScope", "algo": "rand", "method": "explicit", "identifier": "altname", "allowed": true, "value": { "$code": "x=1", "$scope": {} } }, "azure_javascriptWithScope_det_explicit_id": { "kms": "azure", "type": "javascriptWithScope", "algo": "det", "method": "explicit", "identifier": "id", "allowed": false, "value": { "$code": "x=1", "$scope": {} } }, "azure_javascriptWithScope_det_explicit_altname": { "kms": "azure", "type": "javascriptWithScope", "algo": "det", "method": "explicit", "identifier": "altname", "allowed": false, "value": { "$code": "x=1", "$scope": {} } }, "azure_int_rand_auto_id": { "kms": "azure", "type": "int", "algo": "rand", "method": "auto", "identifier": "id", "allowed": true, "value": { "$numberInt": "123" } }, "azure_int_rand_auto_altname": { "kms": "azure", "type": "int", "algo": "rand", "method": "auto", "identifier": "altname", "allowed": true, "value": { "$numberInt": "123" } }, "azure_int_rand_explicit_id": { "kms": "azure", "type": "int", "algo": "rand", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$numberInt": "123" } }, "azure_int_rand_explicit_altname": { "kms": "azure", "type": "int", "algo": "rand", "method": "explicit", "identifier": "altname", "allowed": true, "value": { "$numberInt": "123" } }, "azure_int_det_auto_id": { "kms": "azure", "type": "int", "algo": "det", "method": "auto", "identifier": "id", "allowed": true, "value": { "$numberInt": "123" } }, "azure_int_det_explicit_id": { "kms": "azure", "type": "int", "algo": "det", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$numberInt": "123" } }, "azure_int_det_explicit_altname": { "kms": "azure", "type": "int", "algo": "det", "method": "explicit", "identifier": "altname", "allowed": true, "value": { "$numberInt": "123" } }, "azure_timestamp_rand_auto_id": { "kms": "azure", "type": "timestamp", "algo": "rand", "method": "auto", "identifier": "id", "allowed": true, "value": { "$timestamp": { "t": 0, "i": 12345 } } }, "azure_timestamp_rand_auto_altname": { "kms": "azure", "type": "timestamp", "algo": "rand", "method": "auto", "identifier": "altname", "allowed": true, "value": { "$timestamp": { "t": 0, "i": 12345 } } }, "azure_timestamp_rand_explicit_id": { "kms": "azure", "type": "timestamp", "algo": "rand", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$timestamp": { "t": 0, "i": 12345 } } }, "azure_timestamp_rand_explicit_altname": { "kms": "azure", "type": "timestamp", "algo": "rand", "method": "explicit", "identifier": "altname", "allowed": true, "value": { "$timestamp": { "t": 0, "i": 12345 } } }, "azure_timestamp_det_auto_id": { "kms": "azure", "type": "timestamp", "algo": "det", "method": "auto", "identifier": "id", "allowed": true, "value": { "$timestamp": { "t": 0, "i": 12345 } } }, "azure_timestamp_det_explicit_id": { "kms": "azure", "type": "timestamp", "algo": "det", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$timestamp": { "t": 0, "i": 12345 } } }, "azure_timestamp_det_explicit_altname": { "kms": "azure", "type": "timestamp", "algo": "det", "method": "explicit", "identifier": "altname", "allowed": true, "value": { "$timestamp": { "t": 0, "i": 12345 } } }, "azure_long_rand_auto_id": { "kms": "azure", "type": "long", "algo": "rand", "method": "auto", "identifier": "id", "allowed": true, "value": { "$numberLong": "456" } }, "azure_long_rand_auto_altname": { "kms": "azure", "type": "long", "algo": "rand", "method": "auto", "identifier": "altname", "allowed": true, "value": { "$numberLong": "456" } }, "azure_long_rand_explicit_id": { "kms": "azure", "type": "long", "algo": "rand", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$numberLong": "456" } }, "azure_long_rand_explicit_altname": { "kms": "azure", "type": "long", "algo": "rand", "method": "explicit", "identifier": "altname", "allowed": true, "value": { "$numberLong": "456" } }, "azure_long_det_auto_id": { "kms": "azure", "type": "long", "algo": "det", "method": "auto", "identifier": "id", "allowed": true, "value": { "$numberLong": "456" } }, "azure_long_det_explicit_id": { "kms": "azure", "type": "long", "algo": "det", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$numberLong": "456" } }, "azure_long_det_explicit_altname": { "kms": "azure", "type": "long", "algo": "det", "method": "explicit", "identifier": "altname", "allowed": true, "value": { "$numberLong": "456" } }, "azure_decimal_rand_auto_id": { "kms": "azure", "type": "decimal", "algo": "rand", "method": "auto", "identifier": "id", "allowed": true, "value": { "$numberDecimal": "1.234" } }, "azure_decimal_rand_auto_altname": { "kms": "azure", "type": "decimal", "algo": "rand", "method": "auto", "identifier": "altname", "allowed": true, "value": { "$numberDecimal": "1.234" } }, "azure_decimal_rand_explicit_id": { "kms": "azure", "type": "decimal", "algo": "rand", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$numberDecimal": "1.234" } }, "azure_decimal_rand_explicit_altname": { "kms": "azure", "type": "decimal", "algo": "rand", "method": "explicit", "identifier": "altname", "allowed": true, "value": { "$numberDecimal": "1.234" } }, "azure_decimal_det_explicit_id": { "kms": "azure", "type": "decimal", "algo": "det", "method": "explicit", "identifier": "id", "allowed": false, "value": { "$numberDecimal": "1.234" } }, "azure_decimal_det_explicit_altname": { "kms": "azure", "type": "decimal", "algo": "det", "method": "explicit", "identifier": "altname", "allowed": false, "value": { "$numberDecimal": "1.234" } }, "azure_minKey_rand_explicit_id": { "kms": "azure", "type": "minKey", "algo": "rand", "method": "explicit", "identifier": "id", "allowed": false, "value": { "$minKey": 1 } }, "azure_minKey_rand_explicit_altname": { "kms": "azure", "type": "minKey", "algo": "rand", "method": "explicit", "identifier": "altname", "allowed": false, "value": { "$minKey": 1 } }, "azure_minKey_det_explicit_id": { "kms": "azure", "type": "minKey", "algo": "det", "method": "explicit", "identifier": "id", "allowed": false, "value": { "$minKey": 1 } }, "azure_minKey_det_explicit_altname": { "kms": "azure", "type": "minKey", "algo": "det", "method": "explicit", "identifier": "altname", "allowed": false, "value": { "$minKey": 1 } }, "azure_maxKey_rand_explicit_id": { "kms": "azure", "type": "maxKey", "algo": "rand", "method": "explicit", "identifier": "id", "allowed": false, "value": { "$maxKey": 1 } }, "azure_maxKey_rand_explicit_altname": { "kms": "azure", "type": "maxKey", "algo": "rand", "method": "explicit", "identifier": "altname", "allowed": false, "value": { "$maxKey": 1 } }, "azure_maxKey_det_explicit_id": { "kms": "azure", "type": "maxKey", "algo": "det", "method": "explicit", "identifier": "id", "allowed": false, "value": { "$maxKey": 1 } }, "azure_maxKey_det_explicit_altname": { "kms": "azure", "type": "maxKey", "algo": "det", "method": "explicit", "identifier": "altname", "allowed": false, "value": { "$maxKey": 1 } }, "gcp_double_rand_auto_id": { "kms": "gcp", "type": "double", "algo": "rand", "method": "auto", "identifier": "id", "allowed": true, "value": { "$numberDouble": "1.234" } }, "gcp_double_rand_auto_altname": { "kms": "gcp", "type": "double", "algo": "rand", "method": "auto", "identifier": "altname", "allowed": true, "value": { "$numberDouble": "1.234" } }, "gcp_double_rand_explicit_id": { "kms": "gcp", "type": "double", "algo": "rand", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$numberDouble": "1.234" } }, "gcp_double_rand_explicit_altname": { "kms": "gcp", "type": "double", "algo": "rand", "method": "explicit", "identifier": "altname", "allowed": true, "value": { "$numberDouble": "1.234" } }, "gcp_double_det_explicit_id": { "kms": "gcp", "type": "double", "algo": "det", "method": "explicit", "identifier": "id", "allowed": false, "value": { "$numberDouble": "1.234" } }, "gcp_double_det_explicit_altname": { "kms": "gcp", "type": "double", "algo": "det", "method": "explicit", "identifier": "altname", "allowed": false, "value": { "$numberDouble": "1.234" } }, "gcp_string_rand_auto_id": { "kms": "gcp", "type": "string", "algo": "rand", "method": "auto", "identifier": "id", "allowed": true, "value": "mongodb" }, "gcp_string_rand_auto_altname": { "kms": "gcp", "type": "string", "algo": "rand", "method": "auto", "identifier": "altname", "allowed": true, "value": "mongodb" }, "gcp_string_rand_explicit_id": { "kms": "gcp", "type": "string", "algo": "rand", "method": "explicit", "identifier": "id", "allowed": true, "value": "mongodb" }, "gcp_string_rand_explicit_altname": { "kms": "gcp", "type": "string", "algo": "rand", "method": "explicit", "identifier": "altname", "allowed": true, "value": "mongodb" }, "gcp_string_det_auto_id": { "kms": "gcp", "type": "string", "algo": "det", "method": "auto", "identifier": "id", "allowed": true, "value": "mongodb" }, "gcp_string_det_explicit_id": { "kms": "gcp", "type": "string", "algo": "det", "method": "explicit", "identifier": "id", "allowed": true, "value": "mongodb" }, "gcp_string_det_explicit_altname": { "kms": "gcp", "type": "string", "algo": "det", "method": "explicit", "identifier": "altname", "allowed": true, "value": "mongodb" }, "gcp_object_rand_auto_id": { "kms": "gcp", "type": "object", "algo": "rand", "method": "auto", "identifier": "id", "allowed": true, "value": { "x": { "$numberInt": "1" } } }, "gcp_object_rand_auto_altname": { "kms": "gcp", "type": "object", "algo": "rand", "method": "auto", "identifier": "altname", "allowed": true, "value": { "x": { "$numberInt": "1" } } }, "gcp_object_rand_explicit_id": { "kms": "gcp", "type": "object", "algo": "rand", "method": "explicit", "identifier": "id", "allowed": true, "value": { "x": { "$numberInt": "1" } } }, "gcp_object_rand_explicit_altname": { "kms": "gcp", "type": "object", "algo": "rand", "method": "explicit", "identifier": "altname", "allowed": true, "value": { "x": { "$numberInt": "1" } } }, "gcp_object_det_explicit_id": { "kms": "gcp", "type": "object", "algo": "det", "method": "explicit", "identifier": "id", "allowed": false, "value": { "x": { "$numberInt": "1" } } }, "gcp_object_det_explicit_altname": { "kms": "gcp", "type": "object", "algo": "det", "method": "explicit", "identifier": "altname", "allowed": false, "value": { "x": { "$numberInt": "1" } } }, "gcp_array_rand_auto_id": { "kms": "gcp", "type": "array", "algo": "rand", "method": "auto", "identifier": "id", "allowed": true, "value": [ { "$numberInt": "1" }, { "$numberInt": "2" }, { "$numberInt": "3" } ] }, "gcp_array_rand_auto_altname": { "kms": "gcp", "type": "array", "algo": "rand", "method": "auto", "identifier": "altname", "allowed": true, "value": [ { "$numberInt": "1" }, { "$numberInt": "2" }, { "$numberInt": "3" } ] }, "gcp_array_rand_explicit_id": { "kms": "gcp", "type": "array", "algo": "rand", "method": "explicit", "identifier": "id", "allowed": true, "value": [ { "$numberInt": "1" }, { "$numberInt": "2" }, { "$numberInt": "3" } ] }, "gcp_array_rand_explicit_altname": { "kms": "gcp", "type": "array", "algo": "rand", "method": "explicit", "identifier": "altname", "allowed": true, "value": [ { "$numberInt": "1" }, { "$numberInt": "2" }, { "$numberInt": "3" } ] }, "gcp_array_det_explicit_id": { "kms": "gcp", "type": "array", "algo": "det", "method": "explicit", "identifier": "id", "allowed": false, "value": [ { "$numberInt": "1" }, { "$numberInt": "2" }, { "$numberInt": "3" } ] }, "gcp_array_det_explicit_altname": { "kms": "gcp", "type": "array", "algo": "det", "method": "explicit", "identifier": "altname", "allowed": false, "value": [ { "$numberInt": "1" }, { "$numberInt": "2" }, { "$numberInt": "3" } ] }, "gcp_binData=00_rand_auto_id": { "kms": "gcp", "type": "binData=00", "algo": "rand", "method": "auto", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "AQIDBA==", "subType": "00" } } }, "gcp_binData=00_rand_auto_altname": { "kms": "gcp", "type": "binData=00", "algo": "rand", "method": "auto", "identifier": "altname", "allowed": true, "value": { "$binary": { "base64": "AQIDBA==", "subType": "00" } } }, "gcp_binData=00_rand_explicit_id": { "kms": "gcp", "type": "binData=00", "algo": "rand", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "AQIDBA==", "subType": "00" } } }, "gcp_binData=00_rand_explicit_altname": { "kms": "gcp", "type": "binData=00", "algo": "rand", "method": "explicit", "identifier": "altname", "allowed": true, "value": { "$binary": { "base64": "AQIDBA==", "subType": "00" } } }, "gcp_binData=00_det_auto_id": { "kms": "gcp", "type": "binData=00", "algo": "det", "method": "auto", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "AQIDBA==", "subType": "00" } } }, "gcp_binData=00_det_explicit_id": { "kms": "gcp", "type": "binData=00", "algo": "det", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "AQIDBA==", "subType": "00" } } }, "gcp_binData=00_det_explicit_altname": { "kms": "gcp", "type": "binData=00", "algo": "det", "method": "explicit", "identifier": "altname", "allowed": true, "value": { "$binary": { "base64": "AQIDBA==", "subType": "00" } } }, "gcp_binData=04_rand_auto_id": { "kms": "gcp", "type": "binData=04", "algo": "rand", "method": "auto", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "AAECAwQFBgcICQoLDA0ODw==", "subType": "04" } } }, "gcp_binData=04_rand_auto_altname": { "kms": "gcp", "type": "binData=04", "algo": "rand", "method": "auto", "identifier": "altname", "allowed": true, "value": { "$binary": { "base64": "AAECAwQFBgcICQoLDA0ODw==", "subType": "04" } } }, "gcp_binData=04_rand_explicit_id": { "kms": "gcp", "type": "binData=04", "algo": "rand", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "AAECAwQFBgcICQoLDA0ODw==", "subType": "04" } } }, "gcp_binData=04_rand_explicit_altname": { "kms": "gcp", "type": "binData=04", "algo": "rand", "method": "explicit", "identifier": "altname", "allowed": true, "value": { "$binary": { "base64": "AAECAwQFBgcICQoLDA0ODw==", "subType": "04" } } }, "gcp_binData=04_det_auto_id": { "kms": "gcp", "type": "binData=04", "algo": "det", "method": "auto", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "AAECAwQFBgcICQoLDA0ODw==", "subType": "04" } } }, "gcp_binData=04_det_explicit_id": { "kms": "gcp", "type": "binData=04", "algo": "det", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "AAECAwQFBgcICQoLDA0ODw==", "subType": "04" } } }, "gcp_binData=04_det_explicit_altname": { "kms": "gcp", "type": "binData=04", "algo": "det", "method": "explicit", "identifier": "altname", "allowed": true, "value": { "$binary": { "base64": "AAECAwQFBgcICQoLDA0ODw==", "subType": "04" } } }, "gcp_undefined_rand_explicit_id": { "kms": "gcp", "type": "undefined", "algo": "rand", "method": "explicit", "identifier": "id", "allowed": false, "value": { "$undefined": true } }, "gcp_undefined_rand_explicit_altname": { "kms": "gcp", "type": "undefined", "algo": "rand", "method": "explicit", "identifier": "altname", "allowed": false, "value": { "$undefined": true } }, "gcp_undefined_det_explicit_id": { "kms": "gcp", "type": "undefined", "algo": "det", "method": "explicit", "identifier": "id", "allowed": false, "value": { "$undefined": true } }, "gcp_undefined_det_explicit_altname": { "kms": "gcp", "type": "undefined", "algo": "det", "method": "explicit", "identifier": "altname", "allowed": false, "value": { "$undefined": true } }, "gcp_objectId_rand_auto_id": { "kms": "gcp", "type": "objectId", "algo": "rand", "method": "auto", "identifier": "id", "allowed": true, "value": { "$oid": "01234567890abcdef0123456" } }, "gcp_objectId_rand_auto_altname": { "kms": "gcp", "type": "objectId", "algo": "rand", "method": "auto", "identifier": "altname", "allowed": true, "value": { "$oid": "01234567890abcdef0123456" } }, "gcp_objectId_rand_explicit_id": { "kms": "gcp", "type": "objectId", "algo": "rand", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$oid": "01234567890abcdef0123456" } }, "gcp_objectId_rand_explicit_altname": { "kms": "gcp", "type": "objectId", "algo": "rand", "method": "explicit", "identifier": "altname", "allowed": true, "value": { "$oid": "01234567890abcdef0123456" } }, "gcp_objectId_det_auto_id": { "kms": "gcp", "type": "objectId", "algo": "det", "method": "auto", "identifier": "id", "allowed": true, "value": { "$oid": "01234567890abcdef0123456" } }, "gcp_objectId_det_explicit_id": { "kms": "gcp", "type": "objectId", "algo": "det", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$oid": "01234567890abcdef0123456" } }, "gcp_objectId_det_explicit_altname": { "kms": "gcp", "type": "objectId", "algo": "det", "method": "explicit", "identifier": "altname", "allowed": true, "value": { "$oid": "01234567890abcdef0123456" } }, "gcp_bool_rand_auto_id": { "kms": "gcp", "type": "bool", "algo": "rand", "method": "auto", "identifier": "id", "allowed": true, "value": true }, "gcp_bool_rand_auto_altname": { "kms": "gcp", "type": "bool", "algo": "rand", "method": "auto", "identifier": "altname", "allowed": true, "value": true }, "gcp_bool_rand_explicit_id": { "kms": "gcp", "type": "bool", "algo": "rand", "method": "explicit", "identifier": "id", "allowed": true, "value": true }, "gcp_bool_rand_explicit_altname": { "kms": "gcp", "type": "bool", "algo": "rand", "method": "explicit", "identifier": "altname", "allowed": true, "value": true }, "gcp_bool_det_explicit_id": { "kms": "gcp", "type": "bool", "algo": "det", "method": "explicit", "identifier": "id", "allowed": false, "value": true }, "gcp_bool_det_explicit_altname": { "kms": "gcp", "type": "bool", "algo": "det", "method": "explicit", "identifier": "altname", "allowed": false, "value": true }, "gcp_date_rand_auto_id": { "kms": "gcp", "type": "date", "algo": "rand", "method": "auto", "identifier": "id", "allowed": true, "value": { "$date": { "$numberLong": "12345" } } }, "gcp_date_rand_auto_altname": { "kms": "gcp", "type": "date", "algo": "rand", "method": "auto", "identifier": "altname", "allowed": true, "value": { "$date": { "$numberLong": "12345" } } }, "gcp_date_rand_explicit_id": { "kms": "gcp", "type": "date", "algo": "rand", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$date": { "$numberLong": "12345" } } }, "gcp_date_rand_explicit_altname": { "kms": "gcp", "type": "date", "algo": "rand", "method": "explicit", "identifier": "altname", "allowed": true, "value": { "$date": { "$numberLong": "12345" } } }, "gcp_date_det_auto_id": { "kms": "gcp", "type": "date", "algo": "det", "method": "auto", "identifier": "id", "allowed": true, "value": { "$date": { "$numberLong": "12345" } } }, "gcp_date_det_explicit_id": { "kms": "gcp", "type": "date", "algo": "det", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$date": { "$numberLong": "12345" } } }, "gcp_date_det_explicit_altname": { "kms": "gcp", "type": "date", "algo": "det", "method": "explicit", "identifier": "altname", "allowed": true, "value": { "$date": { "$numberLong": "12345" } } }, "gcp_null_rand_explicit_id": { "kms": "gcp", "type": "null", "algo": "rand", "method": "explicit", "identifier": "id", "allowed": false, "value": null }, "gcp_null_rand_explicit_altname": { "kms": "gcp", "type": "null", "algo": "rand", "method": "explicit", "identifier": "altname", "allowed": false, "value": null }, "gcp_null_det_explicit_id": { "kms": "gcp", "type": "null", "algo": "det", "method": "explicit", "identifier": "id", "allowed": false, "value": null }, "gcp_null_det_explicit_altname": { "kms": "gcp", "type": "null", "algo": "det", "method": "explicit", "identifier": "altname", "allowed": false, "value": null }, "gcp_regex_rand_auto_id": { "kms": "gcp", "type": "regex", "algo": "rand", "method": "auto", "identifier": "id", "allowed": true, "value": { "$regularExpression": { "pattern": ".*", "options": "" } } }, "gcp_regex_rand_auto_altname": { "kms": "gcp", "type": "regex", "algo": "rand", "method": "auto", "identifier": "altname", "allowed": true, "value": { "$regularExpression": { "pattern": ".*", "options": "" } } }, "gcp_regex_rand_explicit_id": { "kms": "gcp", "type": "regex", "algo": "rand", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$regularExpression": { "pattern": ".*", "options": "" } } }, "gcp_regex_rand_explicit_altname": { "kms": "gcp", "type": "regex", "algo": "rand", "method": "explicit", "identifier": "altname", "allowed": true, "value": { "$regularExpression": { "pattern": ".*", "options": "" } } }, "gcp_regex_det_auto_id": { "kms": "gcp", "type": "regex", "algo": "det", "method": "auto", "identifier": "id", "allowed": true, "value": { "$regularExpression": { "pattern": ".*", "options": "" } } }, "gcp_regex_det_explicit_id": { "kms": "gcp", "type": "regex", "algo": "det", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$regularExpression": { "pattern": ".*", "options": "" } } }, "gcp_regex_det_explicit_altname": { "kms": "gcp", "type": "regex", "algo": "det", "method": "explicit", "identifier": "altname", "allowed": true, "value": { "$regularExpression": { "pattern": ".*", "options": "" } } }, "gcp_dbPointer_rand_auto_id": { "kms": "gcp", "type": "dbPointer", "algo": "rand", "method": "auto", "identifier": "id", "allowed": true, "value": { "$dbPointer": { "$ref": "db.example", "$id": { "$oid": "01234567890abcdef0123456" } } } }, "gcp_dbPointer_rand_auto_altname": { "kms": "gcp", "type": "dbPointer", "algo": "rand", "method": "auto", "identifier": "altname", "allowed": true, "value": { "$dbPointer": { "$ref": "db.example", "$id": { "$oid": "01234567890abcdef0123456" } } } }, "gcp_dbPointer_rand_explicit_id": { "kms": "gcp", "type": "dbPointer", "algo": "rand", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$dbPointer": { "$ref": "db.example", "$id": { "$oid": "01234567890abcdef0123456" } } } }, "gcp_dbPointer_rand_explicit_altname": { "kms": "gcp", "type": "dbPointer", "algo": "rand", "method": "explicit", "identifier": "altname", "allowed": true, "value": { "$dbPointer": { "$ref": "db.example", "$id": { "$oid": "01234567890abcdef0123456" } } } }, "gcp_dbPointer_det_auto_id": { "kms": "gcp", "type": "dbPointer", "algo": "det", "method": "auto", "identifier": "id", "allowed": true, "value": { "$dbPointer": { "$ref": "db.example", "$id": { "$oid": "01234567890abcdef0123456" } } } }, "gcp_dbPointer_det_explicit_id": { "kms": "gcp", "type": "dbPointer", "algo": "det", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$dbPointer": { "$ref": "db.example", "$id": { "$oid": "01234567890abcdef0123456" } } } }, "gcp_dbPointer_det_explicit_altname": { "kms": "gcp", "type": "dbPointer", "algo": "det", "method": "explicit", "identifier": "altname", "allowed": true, "value": { "$dbPointer": { "$ref": "db.example", "$id": { "$oid": "01234567890abcdef0123456" } } } }, "gcp_javascript_rand_auto_id": { "kms": "gcp", "type": "javascript", "algo": "rand", "method": "auto", "identifier": "id", "allowed": true, "value": { "$code": "x=1" } }, "gcp_javascript_rand_auto_altname": { "kms": "gcp", "type": "javascript", "algo": "rand", "method": "auto", "identifier": "altname", "allowed": true, "value": { "$code": "x=1" } }, "gcp_javascript_rand_explicit_id": { "kms": "gcp", "type": "javascript", "algo": "rand", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$code": "x=1" } }, "gcp_javascript_rand_explicit_altname": { "kms": "gcp", "type": "javascript", "algo": "rand", "method": "explicit", "identifier": "altname", "allowed": true, "value": { "$code": "x=1" } }, "gcp_javascript_det_auto_id": { "kms": "gcp", "type": "javascript", "algo": "det", "method": "auto", "identifier": "id", "allowed": true, "value": { "$code": "x=1" } }, "gcp_javascript_det_explicit_id": { "kms": "gcp", "type": "javascript", "algo": "det", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$code": "x=1" } }, "gcp_javascript_det_explicit_altname": { "kms": "gcp", "type": "javascript", "algo": "det", "method": "explicit", "identifier": "altname", "allowed": true, "value": { "$code": "x=1" } }, "gcp_symbol_rand_auto_id": { "kms": "gcp", "type": "symbol", "algo": "rand", "method": "auto", "identifier": "id", "allowed": true, "value": { "$symbol": "mongodb-symbol" } }, "gcp_symbol_rand_auto_altname": { "kms": "gcp", "type": "symbol", "algo": "rand", "method": "auto", "identifier": "altname", "allowed": true, "value": { "$symbol": "mongodb-symbol" } }, "gcp_symbol_rand_explicit_id": { "kms": "gcp", "type": "symbol", "algo": "rand", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$symbol": "mongodb-symbol" } }, "gcp_symbol_rand_explicit_altname": { "kms": "gcp", "type": "symbol", "algo": "rand", "method": "explicit", "identifier": "altname", "allowed": true, "value": { "$symbol": "mongodb-symbol" } }, "gcp_symbol_det_auto_id": { "kms": "gcp", "type": "symbol", "algo": "det", "method": "auto", "identifier": "id", "allowed": true, "value": { "$symbol": "mongodb-symbol" } }, "gcp_symbol_det_explicit_id": { "kms": "gcp", "type": "symbol", "algo": "det", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$symbol": "mongodb-symbol" } }, "gcp_symbol_det_explicit_altname": { "kms": "gcp", "type": "symbol", "algo": "det", "method": "explicit", "identifier": "altname", "allowed": true, "value": { "$symbol": "mongodb-symbol" } }, "gcp_javascriptWithScope_rand_auto_id": { "kms": "gcp", "type": "javascriptWithScope", "algo": "rand", "method": "auto", "identifier": "id", "allowed": true, "value": { "$code": "x=1", "$scope": {} } }, "gcp_javascriptWithScope_rand_auto_altname": { "kms": "gcp", "type": "javascriptWithScope", "algo": "rand", "method": "auto", "identifier": "altname", "allowed": true, "value": { "$code": "x=1", "$scope": {} } }, "gcp_javascriptWithScope_rand_explicit_id": { "kms": "gcp", "type": "javascriptWithScope", "algo": "rand", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$code": "x=1", "$scope": {} } }, "gcp_javascriptWithScope_rand_explicit_altname": { "kms": "gcp", "type": "javascriptWithScope", "algo": "rand", "method": "explicit", "identifier": "altname", "allowed": true, "value": { "$code": "x=1", "$scope": {} } }, "gcp_javascriptWithScope_det_explicit_id": { "kms": "gcp", "type": "javascriptWithScope", "algo": "det", "method": "explicit", "identifier": "id", "allowed": false, "value": { "$code": "x=1", "$scope": {} } }, "gcp_javascriptWithScope_det_explicit_altname": { "kms": "gcp", "type": "javascriptWithScope", "algo": "det", "method": "explicit", "identifier": "altname", "allowed": false, "value": { "$code": "x=1", "$scope": {} } }, "gcp_int_rand_auto_id": { "kms": "gcp", "type": "int", "algo": "rand", "method": "auto", "identifier": "id", "allowed": true, "value": { "$numberInt": "123" } }, "gcp_int_rand_auto_altname": { "kms": "gcp", "type": "int", "algo": "rand", "method": "auto", "identifier": "altname", "allowed": true, "value": { "$numberInt": "123" } }, "gcp_int_rand_explicit_id": { "kms": "gcp", "type": "int", "algo": "rand", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$numberInt": "123" } }, "gcp_int_rand_explicit_altname": { "kms": "gcp", "type": "int", "algo": "rand", "method": "explicit", "identifier": "altname", "allowed": true, "value": { "$numberInt": "123" } }, "gcp_int_det_auto_id": { "kms": "gcp", "type": "int", "algo": "det", "method": "auto", "identifier": "id", "allowed": true, "value": { "$numberInt": "123" } }, "gcp_int_det_explicit_id": { "kms": "gcp", "type": "int", "algo": "det", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$numberInt": "123" } }, "gcp_int_det_explicit_altname": { "kms": "gcp", "type": "int", "algo": "det", "method": "explicit", "identifier": "altname", "allowed": true, "value": { "$numberInt": "123" } }, "gcp_timestamp_rand_auto_id": { "kms": "gcp", "type": "timestamp", "algo": "rand", "method": "auto", "identifier": "id", "allowed": true, "value": { "$timestamp": { "t": 0, "i": 12345 } } }, "gcp_timestamp_rand_auto_altname": { "kms": "gcp", "type": "timestamp", "algo": "rand", "method": "auto", "identifier": "altname", "allowed": true, "value": { "$timestamp": { "t": 0, "i": 12345 } } }, "gcp_timestamp_rand_explicit_id": { "kms": "gcp", "type": "timestamp", "algo": "rand", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$timestamp": { "t": 0, "i": 12345 } } }, "gcp_timestamp_rand_explicit_altname": { "kms": "gcp", "type": "timestamp", "algo": "rand", "method": "explicit", "identifier": "altname", "allowed": true, "value": { "$timestamp": { "t": 0, "i": 12345 } } }, "gcp_timestamp_det_auto_id": { "kms": "gcp", "type": "timestamp", "algo": "det", "method": "auto", "identifier": "id", "allowed": true, "value": { "$timestamp": { "t": 0, "i": 12345 } } }, "gcp_timestamp_det_explicit_id": { "kms": "gcp", "type": "timestamp", "algo": "det", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$timestamp": { "t": 0, "i": 12345 } } }, "gcp_timestamp_det_explicit_altname": { "kms": "gcp", "type": "timestamp", "algo": "det", "method": "explicit", "identifier": "altname", "allowed": true, "value": { "$timestamp": { "t": 0, "i": 12345 } } }, "gcp_long_rand_auto_id": { "kms": "gcp", "type": "long", "algo": "rand", "method": "auto", "identifier": "id", "allowed": true, "value": { "$numberLong": "456" } }, "gcp_long_rand_auto_altname": { "kms": "gcp", "type": "long", "algo": "rand", "method": "auto", "identifier": "altname", "allowed": true, "value": { "$numberLong": "456" } }, "gcp_long_rand_explicit_id": { "kms": "gcp", "type": "long", "algo": "rand", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$numberLong": "456" } }, "gcp_long_rand_explicit_altname": { "kms": "gcp", "type": "long", "algo": "rand", "method": "explicit", "identifier": "altname", "allowed": true, "value": { "$numberLong": "456" } }, "gcp_long_det_auto_id": { "kms": "gcp", "type": "long", "algo": "det", "method": "auto", "identifier": "id", "allowed": true, "value": { "$numberLong": "456" } }, "gcp_long_det_explicit_id": { "kms": "gcp", "type": "long", "algo": "det", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$numberLong": "456" } }, "gcp_long_det_explicit_altname": { "kms": "gcp", "type": "long", "algo": "det", "method": "explicit", "identifier": "altname", "allowed": true, "value": { "$numberLong": "456" } }, "gcp_decimal_rand_auto_id": { "kms": "gcp", "type": "decimal", "algo": "rand", "method": "auto", "identifier": "id", "allowed": true, "value": { "$numberDecimal": "1.234" } }, "gcp_decimal_rand_auto_altname": { "kms": "gcp", "type": "decimal", "algo": "rand", "method": "auto", "identifier": "altname", "allowed": true, "value": { "$numberDecimal": "1.234" } }, "gcp_decimal_rand_explicit_id": { "kms": "gcp", "type": "decimal", "algo": "rand", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$numberDecimal": "1.234" } }, "gcp_decimal_rand_explicit_altname": { "kms": "gcp", "type": "decimal", "algo": "rand", "method": "explicit", "identifier": "altname", "allowed": true, "value": { "$numberDecimal": "1.234" } }, "gcp_decimal_det_explicit_id": { "kms": "gcp", "type": "decimal", "algo": "det", "method": "explicit", "identifier": "id", "allowed": false, "value": { "$numberDecimal": "1.234" } }, "gcp_decimal_det_explicit_altname": { "kms": "gcp", "type": "decimal", "algo": "det", "method": "explicit", "identifier": "altname", "allowed": false, "value": { "$numberDecimal": "1.234" } }, "gcp_minKey_rand_explicit_id": { "kms": "gcp", "type": "minKey", "algo": "rand", "method": "explicit", "identifier": "id", "allowed": false, "value": { "$minKey": 1 } }, "gcp_minKey_rand_explicit_altname": { "kms": "gcp", "type": "minKey", "algo": "rand", "method": "explicit", "identifier": "altname", "allowed": false, "value": { "$minKey": 1 } }, "gcp_minKey_det_explicit_id": { "kms": "gcp", "type": "minKey", "algo": "det", "method": "explicit", "identifier": "id", "allowed": false, "value": { "$minKey": 1 } }, "gcp_minKey_det_explicit_altname": { "kms": "gcp", "type": "minKey", "algo": "det", "method": "explicit", "identifier": "altname", "allowed": false, "value": { "$minKey": 1 } }, "gcp_maxKey_rand_explicit_id": { "kms": "gcp", "type": "maxKey", "algo": "rand", "method": "explicit", "identifier": "id", "allowed": false, "value": { "$maxKey": 1 } }, "gcp_maxKey_rand_explicit_altname": { "kms": "gcp", "type": "maxKey", "algo": "rand", "method": "explicit", "identifier": "altname", "allowed": false, "value": { "$maxKey": 1 } }, "gcp_maxKey_det_explicit_id": { "kms": "gcp", "type": "maxKey", "algo": "det", "method": "explicit", "identifier": "id", "allowed": false, "value": { "$maxKey": 1 } }, "gcp_maxKey_det_explicit_altname": { "kms": "gcp", "type": "maxKey", "algo": "det", "method": "explicit", "identifier": "altname", "allowed": false, "value": { "$maxKey": 1 } }, "kmip_double_rand_auto_id": { "kms": "kmip", "type": "double", "algo": "rand", "method": "auto", "identifier": "id", "allowed": true, "value": { "$numberDouble": "1.234" } }, "kmip_double_rand_auto_altname": { "kms": "kmip", "type": "double", "algo": "rand", "method": "auto", "identifier": "altname", "allowed": true, "value": { "$numberDouble": "1.234" } }, "kmip_double_rand_explicit_id": { "kms": "kmip", "type": "double", "algo": "rand", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$numberDouble": "1.234" } }, "kmip_double_rand_explicit_altname": { "kms": "kmip", "type": "double", "algo": "rand", "method": "explicit", "identifier": "altname", "allowed": true, "value": { "$numberDouble": "1.234" } }, "kmip_double_det_explicit_id": { "kms": "kmip", "type": "double", "algo": "det", "method": "explicit", "identifier": "id", "allowed": false, "value": { "$numberDouble": "1.234" } }, "kmip_double_det_explicit_altname": { "kms": "kmip", "type": "double", "algo": "det", "method": "explicit", "identifier": "altname", "allowed": false, "value": { "$numberDouble": "1.234" } }, "kmip_string_rand_auto_id": { "kms": "kmip", "type": "string", "algo": "rand", "method": "auto", "identifier": "id", "allowed": true, "value": "mongodb" }, "kmip_string_rand_auto_altname": { "kms": "kmip", "type": "string", "algo": "rand", "method": "auto", "identifier": "altname", "allowed": true, "value": "mongodb" }, "kmip_string_rand_explicit_id": { "kms": "kmip", "type": "string", "algo": "rand", "method": "explicit", "identifier": "id", "allowed": true, "value": "mongodb" }, "kmip_string_rand_explicit_altname": { "kms": "kmip", "type": "string", "algo": "rand", "method": "explicit", "identifier": "altname", "allowed": true, "value": "mongodb" }, "kmip_string_det_auto_id": { "kms": "kmip", "type": "string", "algo": "det", "method": "auto", "identifier": "id", "allowed": true, "value": "mongodb" }, "kmip_string_det_explicit_id": { "kms": "kmip", "type": "string", "algo": "det", "method": "explicit", "identifier": "id", "allowed": true, "value": "mongodb" }, "kmip_string_det_explicit_altname": { "kms": "kmip", "type": "string", "algo": "det", "method": "explicit", "identifier": "altname", "allowed": true, "value": "mongodb" }, "kmip_object_rand_auto_id": { "kms": "kmip", "type": "object", "algo": "rand", "method": "auto", "identifier": "id", "allowed": true, "value": { "x": { "$numberInt": "1" } } }, "kmip_object_rand_auto_altname": { "kms": "kmip", "type": "object", "algo": "rand", "method": "auto", "identifier": "altname", "allowed": true, "value": { "x": { "$numberInt": "1" } } }, "kmip_object_rand_explicit_id": { "kms": "kmip", "type": "object", "algo": "rand", "method": "explicit", "identifier": "id", "allowed": true, "value": { "x": { "$numberInt": "1" } } }, "kmip_object_rand_explicit_altname": { "kms": "kmip", "type": "object", "algo": "rand", "method": "explicit", "identifier": "altname", "allowed": true, "value": { "x": { "$numberInt": "1" } } }, "kmip_object_det_explicit_id": { "kms": "kmip", "type": "object", "algo": "det", "method": "explicit", "identifier": "id", "allowed": false, "value": { "x": { "$numberInt": "1" } } }, "kmip_object_det_explicit_altname": { "kms": "kmip", "type": "object", "algo": "det", "method": "explicit", "identifier": "altname", "allowed": false, "value": { "x": { "$numberInt": "1" } } }, "kmip_array_rand_auto_id": { "kms": "kmip", "type": "array", "algo": "rand", "method": "auto", "identifier": "id", "allowed": true, "value": [ { "$numberInt": "1" }, { "$numberInt": "2" }, { "$numberInt": "3" } ] }, "kmip_array_rand_auto_altname": { "kms": "kmip", "type": "array", "algo": "rand", "method": "auto", "identifier": "altname", "allowed": true, "value": [ { "$numberInt": "1" }, { "$numberInt": "2" }, { "$numberInt": "3" } ] }, "kmip_array_rand_explicit_id": { "kms": "kmip", "type": "array", "algo": "rand", "method": "explicit", "identifier": "id", "allowed": true, "value": [ { "$numberInt": "1" }, { "$numberInt": "2" }, { "$numberInt": "3" } ] }, "kmip_array_rand_explicit_altname": { "kms": "kmip", "type": "array", "algo": "rand", "method": "explicit", "identifier": "altname", "allowed": true, "value": [ { "$numberInt": "1" }, { "$numberInt": "2" }, { "$numberInt": "3" } ] }, "kmip_array_det_explicit_id": { "kms": "kmip", "type": "array", "algo": "det", "method": "explicit", "identifier": "id", "allowed": false, "value": [ { "$numberInt": "1" }, { "$numberInt": "2" }, { "$numberInt": "3" } ] }, "kmip_array_det_explicit_altname": { "kms": "kmip", "type": "array", "algo": "det", "method": "explicit", "identifier": "altname", "allowed": false, "value": [ { "$numberInt": "1" }, { "$numberInt": "2" }, { "$numberInt": "3" } ] }, "kmip_binData=00_rand_auto_id": { "kms": "kmip", "type": "binData=00", "algo": "rand", "method": "auto", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "AQIDBA==", "subType": "00" } } }, "kmip_binData=00_rand_auto_altname": { "kms": "kmip", "type": "binData=00", "algo": "rand", "method": "auto", "identifier": "altname", "allowed": true, "value": { "$binary": { "base64": "AQIDBA==", "subType": "00" } } }, "kmip_binData=00_rand_explicit_id": { "kms": "kmip", "type": "binData=00", "algo": "rand", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "AQIDBA==", "subType": "00" } } }, "kmip_binData=00_rand_explicit_altname": { "kms": "kmip", "type": "binData=00", "algo": "rand", "method": "explicit", "identifier": "altname", "allowed": true, "value": { "$binary": { "base64": "AQIDBA==", "subType": "00" } } }, "kmip_binData=00_det_auto_id": { "kms": "kmip", "type": "binData=00", "algo": "det", "method": "auto", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "AQIDBA==", "subType": "00" } } }, "kmip_binData=00_det_explicit_id": { "kms": "kmip", "type": "binData=00", "algo": "det", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "AQIDBA==", "subType": "00" } } }, "kmip_binData=00_det_explicit_altname": { "kms": "kmip", "type": "binData=00", "algo": "det", "method": "explicit", "identifier": "altname", "allowed": true, "value": { "$binary": { "base64": "AQIDBA==", "subType": "00" } } }, "kmip_binData=04_rand_auto_id": { "kms": "kmip", "type": "binData=04", "algo": "rand", "method": "auto", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "AAECAwQFBgcICQoLDA0ODw==", "subType": "04" } } }, "kmip_binData=04_rand_auto_altname": { "kms": "kmip", "type": "binData=04", "algo": "rand", "method": "auto", "identifier": "altname", "allowed": true, "value": { "$binary": { "base64": "AAECAwQFBgcICQoLDA0ODw==", "subType": "04" } } }, "kmip_binData=04_rand_explicit_id": { "kms": "kmip", "type": "binData=04", "algo": "rand", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "AAECAwQFBgcICQoLDA0ODw==", "subType": "04" } } }, "kmip_binData=04_rand_explicit_altname": { "kms": "kmip", "type": "binData=04", "algo": "rand", "method": "explicit", "identifier": "altname", "allowed": true, "value": { "$binary": { "base64": "AAECAwQFBgcICQoLDA0ODw==", "subType": "04" } } }, "kmip_binData=04_det_auto_id": { "kms": "kmip", "type": "binData=04", "algo": "det", "method": "auto", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "AAECAwQFBgcICQoLDA0ODw==", "subType": "04" } } }, "kmip_binData=04_det_explicit_id": { "kms": "kmip", "type": "binData=04", "algo": "det", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$binary": { "base64": "AAECAwQFBgcICQoLDA0ODw==", "subType": "04" } } }, "kmip_binData=04_det_explicit_altname": { "kms": "kmip", "type": "binData=04", "algo": "det", "method": "explicit", "identifier": "altname", "allowed": true, "value": { "$binary": { "base64": "AAECAwQFBgcICQoLDA0ODw==", "subType": "04" } } }, "kmip_undefined_rand_explicit_id": { "kms": "kmip", "type": "undefined", "algo": "rand", "method": "explicit", "identifier": "id", "allowed": false, "value": { "$undefined": true } }, "kmip_undefined_rand_explicit_altname": { "kms": "kmip", "type": "undefined", "algo": "rand", "method": "explicit", "identifier": "altname", "allowed": false, "value": { "$undefined": true } }, "kmip_undefined_det_explicit_id": { "kms": "kmip", "type": "undefined", "algo": "det", "method": "explicit", "identifier": "id", "allowed": false, "value": { "$undefined": true } }, "kmip_undefined_det_explicit_altname": { "kms": "kmip", "type": "undefined", "algo": "det", "method": "explicit", "identifier": "altname", "allowed": false, "value": { "$undefined": true } }, "kmip_objectId_rand_auto_id": { "kms": "kmip", "type": "objectId", "algo": "rand", "method": "auto", "identifier": "id", "allowed": true, "value": { "$oid": "01234567890abcdef0123456" } }, "kmip_objectId_rand_auto_altname": { "kms": "kmip", "type": "objectId", "algo": "rand", "method": "auto", "identifier": "altname", "allowed": true, "value": { "$oid": "01234567890abcdef0123456" } }, "kmip_objectId_rand_explicit_id": { "kms": "kmip", "type": "objectId", "algo": "rand", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$oid": "01234567890abcdef0123456" } }, "kmip_objectId_rand_explicit_altname": { "kms": "kmip", "type": "objectId", "algo": "rand", "method": "explicit", "identifier": "altname", "allowed": true, "value": { "$oid": "01234567890abcdef0123456" } }, "kmip_objectId_det_auto_id": { "kms": "kmip", "type": "objectId", "algo": "det", "method": "auto", "identifier": "id", "allowed": true, "value": { "$oid": "01234567890abcdef0123456" } }, "kmip_objectId_det_explicit_id": { "kms": "kmip", "type": "objectId", "algo": "det", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$oid": "01234567890abcdef0123456" } }, "kmip_objectId_det_explicit_altname": { "kms": "kmip", "type": "objectId", "algo": "det", "method": "explicit", "identifier": "altname", "allowed": true, "value": { "$oid": "01234567890abcdef0123456" } }, "kmip_bool_rand_auto_id": { "kms": "kmip", "type": "bool", "algo": "rand", "method": "auto", "identifier": "id", "allowed": true, "value": true }, "kmip_bool_rand_auto_altname": { "kms": "kmip", "type": "bool", "algo": "rand", "method": "auto", "identifier": "altname", "allowed": true, "value": true }, "kmip_bool_rand_explicit_id": { "kms": "kmip", "type": "bool", "algo": "rand", "method": "explicit", "identifier": "id", "allowed": true, "value": true }, "kmip_bool_rand_explicit_altname": { "kms": "kmip", "type": "bool", "algo": "rand", "method": "explicit", "identifier": "altname", "allowed": true, "value": true }, "kmip_bool_det_explicit_id": { "kms": "kmip", "type": "bool", "algo": "det", "method": "explicit", "identifier": "id", "allowed": false, "value": true }, "kmip_bool_det_explicit_altname": { "kms": "kmip", "type": "bool", "algo": "det", "method": "explicit", "identifier": "altname", "allowed": false, "value": true }, "kmip_date_rand_auto_id": { "kms": "kmip", "type": "date", "algo": "rand", "method": "auto", "identifier": "id", "allowed": true, "value": { "$date": { "$numberLong": "12345" } } }, "kmip_date_rand_auto_altname": { "kms": "kmip", "type": "date", "algo": "rand", "method": "auto", "identifier": "altname", "allowed": true, "value": { "$date": { "$numberLong": "12345" } } }, "kmip_date_rand_explicit_id": { "kms": "kmip", "type": "date", "algo": "rand", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$date": { "$numberLong": "12345" } } }, "kmip_date_rand_explicit_altname": { "kms": "kmip", "type": "date", "algo": "rand", "method": "explicit", "identifier": "altname", "allowed": true, "value": { "$date": { "$numberLong": "12345" } } }, "kmip_date_det_auto_id": { "kms": "kmip", "type": "date", "algo": "det", "method": "auto", "identifier": "id", "allowed": true, "value": { "$date": { "$numberLong": "12345" } } }, "kmip_date_det_explicit_id": { "kms": "kmip", "type": "date", "algo": "det", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$date": { "$numberLong": "12345" } } }, "kmip_date_det_explicit_altname": { "kms": "kmip", "type": "date", "algo": "det", "method": "explicit", "identifier": "altname", "allowed": true, "value": { "$date": { "$numberLong": "12345" } } }, "kmip_null_rand_explicit_id": { "kms": "kmip", "type": "null", "algo": "rand", "method": "explicit", "identifier": "id", "allowed": false, "value": null }, "kmip_null_rand_explicit_altname": { "kms": "kmip", "type": "null", "algo": "rand", "method": "explicit", "identifier": "altname", "allowed": false, "value": null }, "kmip_null_det_explicit_id": { "kms": "kmip", "type": "null", "algo": "det", "method": "explicit", "identifier": "id", "allowed": false, "value": null }, "kmip_null_det_explicit_altname": { "kms": "kmip", "type": "null", "algo": "det", "method": "explicit", "identifier": "altname", "allowed": false, "value": null }, "kmip_regex_rand_auto_id": { "kms": "kmip", "type": "regex", "algo": "rand", "method": "auto", "identifier": "id", "allowed": true, "value": { "$regularExpression": { "pattern": ".*", "options": "" } } }, "kmip_regex_rand_auto_altname": { "kms": "kmip", "type": "regex", "algo": "rand", "method": "auto", "identifier": "altname", "allowed": true, "value": { "$regularExpression": { "pattern": ".*", "options": "" } } }, "kmip_regex_rand_explicit_id": { "kms": "kmip", "type": "regex", "algo": "rand", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$regularExpression": { "pattern": ".*", "options": "" } } }, "kmip_regex_rand_explicit_altname": { "kms": "kmip", "type": "regex", "algo": "rand", "method": "explicit", "identifier": "altname", "allowed": true, "value": { "$regularExpression": { "pattern": ".*", "options": "" } } }, "kmip_regex_det_auto_id": { "kms": "kmip", "type": "regex", "algo": "det", "method": "auto", "identifier": "id", "allowed": true, "value": { "$regularExpression": { "pattern": ".*", "options": "" } } }, "kmip_regex_det_explicit_id": { "kms": "kmip", "type": "regex", "algo": "det", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$regularExpression": { "pattern": ".*", "options": "" } } }, "kmip_regex_det_explicit_altname": { "kms": "kmip", "type": "regex", "algo": "det", "method": "explicit", "identifier": "altname", "allowed": true, "value": { "$regularExpression": { "pattern": ".*", "options": "" } } }, "kmip_dbPointer_rand_auto_id": { "kms": "kmip", "type": "dbPointer", "algo": "rand", "method": "auto", "identifier": "id", "allowed": true, "value": { "$dbPointer": { "$ref": "db.example", "$id": { "$oid": "01234567890abcdef0123456" } } } }, "kmip_dbPointer_rand_auto_altname": { "kms": "kmip", "type": "dbPointer", "algo": "rand", "method": "auto", "identifier": "altname", "allowed": true, "value": { "$dbPointer": { "$ref": "db.example", "$id": { "$oid": "01234567890abcdef0123456" } } } }, "kmip_dbPointer_rand_explicit_id": { "kms": "kmip", "type": "dbPointer", "algo": "rand", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$dbPointer": { "$ref": "db.example", "$id": { "$oid": "01234567890abcdef0123456" } } } }, "kmip_dbPointer_rand_explicit_altname": { "kms": "kmip", "type": "dbPointer", "algo": "rand", "method": "explicit", "identifier": "altname", "allowed": true, "value": { "$dbPointer": { "$ref": "db.example", "$id": { "$oid": "01234567890abcdef0123456" } } } }, "kmip_dbPointer_det_auto_id": { "kms": "kmip", "type": "dbPointer", "algo": "det", "method": "auto", "identifier": "id", "allowed": true, "value": { "$dbPointer": { "$ref": "db.example", "$id": { "$oid": "01234567890abcdef0123456" } } } }, "kmip_dbPointer_det_explicit_id": { "kms": "kmip", "type": "dbPointer", "algo": "det", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$dbPointer": { "$ref": "db.example", "$id": { "$oid": "01234567890abcdef0123456" } } } }, "kmip_dbPointer_det_explicit_altname": { "kms": "kmip", "type": "dbPointer", "algo": "det", "method": "explicit", "identifier": "altname", "allowed": true, "value": { "$dbPointer": { "$ref": "db.example", "$id": { "$oid": "01234567890abcdef0123456" } } } }, "kmip_javascript_rand_auto_id": { "kms": "kmip", "type": "javascript", "algo": "rand", "method": "auto", "identifier": "id", "allowed": true, "value": { "$code": "x=1" } }, "kmip_javascript_rand_auto_altname": { "kms": "kmip", "type": "javascript", "algo": "rand", "method": "auto", "identifier": "altname", "allowed": true, "value": { "$code": "x=1" } }, "kmip_javascript_rand_explicit_id": { "kms": "kmip", "type": "javascript", "algo": "rand", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$code": "x=1" } }, "kmip_javascript_rand_explicit_altname": { "kms": "kmip", "type": "javascript", "algo": "rand", "method": "explicit", "identifier": "altname", "allowed": true, "value": { "$code": "x=1" } }, "kmip_javascript_det_auto_id": { "kms": "kmip", "type": "javascript", "algo": "det", "method": "auto", "identifier": "id", "allowed": true, "value": { "$code": "x=1" } }, "kmip_javascript_det_explicit_id": { "kms": "kmip", "type": "javascript", "algo": "det", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$code": "x=1" } }, "kmip_javascript_det_explicit_altname": { "kms": "kmip", "type": "javascript", "algo": "det", "method": "explicit", "identifier": "altname", "allowed": true, "value": { "$code": "x=1" } }, "kmip_symbol_rand_auto_id": { "kms": "kmip", "type": "symbol", "algo": "rand", "method": "auto", "identifier": "id", "allowed": true, "value": { "$symbol": "mongodb-symbol" } }, "kmip_symbol_rand_auto_altname": { "kms": "kmip", "type": "symbol", "algo": "rand", "method": "auto", "identifier": "altname", "allowed": true, "value": { "$symbol": "mongodb-symbol" } }, "kmip_symbol_rand_explicit_id": { "kms": "kmip", "type": "symbol", "algo": "rand", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$symbol": "mongodb-symbol" } }, "kmip_symbol_rand_explicit_altname": { "kms": "kmip", "type": "symbol", "algo": "rand", "method": "explicit", "identifier": "altname", "allowed": true, "value": { "$symbol": "mongodb-symbol" } }, "kmip_symbol_det_auto_id": { "kms": "kmip", "type": "symbol", "algo": "det", "method": "auto", "identifier": "id", "allowed": true, "value": { "$symbol": "mongodb-symbol" } }, "kmip_symbol_det_explicit_id": { "kms": "kmip", "type": "symbol", "algo": "det", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$symbol": "mongodb-symbol" } }, "kmip_symbol_det_explicit_altname": { "kms": "kmip", "type": "symbol", "algo": "det", "method": "explicit", "identifier": "altname", "allowed": true, "value": { "$symbol": "mongodb-symbol" } }, "kmip_javascriptWithScope_rand_auto_id": { "kms": "kmip", "type": "javascriptWithScope", "algo": "rand", "method": "auto", "identifier": "id", "allowed": true, "value": { "$code": "x=1", "$scope": {} } }, "kmip_javascriptWithScope_rand_auto_altname": { "kms": "kmip", "type": "javascriptWithScope", "algo": "rand", "method": "auto", "identifier": "altname", "allowed": true, "value": { "$code": "x=1", "$scope": {} } }, "kmip_javascriptWithScope_rand_explicit_id": { "kms": "kmip", "type": "javascriptWithScope", "algo": "rand", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$code": "x=1", "$scope": {} } }, "kmip_javascriptWithScope_rand_explicit_altname": { "kms": "kmip", "type": "javascriptWithScope", "algo": "rand", "method": "explicit", "identifier": "altname", "allowed": true, "value": { "$code": "x=1", "$scope": {} } }, "kmip_javascriptWithScope_det_explicit_id": { "kms": "kmip", "type": "javascriptWithScope", "algo": "det", "method": "explicit", "identifier": "id", "allowed": false, "value": { "$code": "x=1", "$scope": {} } }, "kmip_javascriptWithScope_det_explicit_altname": { "kms": "kmip", "type": "javascriptWithScope", "algo": "det", "method": "explicit", "identifier": "altname", "allowed": false, "value": { "$code": "x=1", "$scope": {} } }, "kmip_int_rand_auto_id": { "kms": "kmip", "type": "int", "algo": "rand", "method": "auto", "identifier": "id", "allowed": true, "value": { "$numberInt": "123" } }, "kmip_int_rand_auto_altname": { "kms": "kmip", "type": "int", "algo": "rand", "method": "auto", "identifier": "altname", "allowed": true, "value": { "$numberInt": "123" } }, "kmip_int_rand_explicit_id": { "kms": "kmip", "type": "int", "algo": "rand", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$numberInt": "123" } }, "kmip_int_rand_explicit_altname": { "kms": "kmip", "type": "int", "algo": "rand", "method": "explicit", "identifier": "altname", "allowed": true, "value": { "$numberInt": "123" } }, "kmip_int_det_auto_id": { "kms": "kmip", "type": "int", "algo": "det", "method": "auto", "identifier": "id", "allowed": true, "value": { "$numberInt": "123" } }, "kmip_int_det_explicit_id": { "kms": "kmip", "type": "int", "algo": "det", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$numberInt": "123" } }, "kmip_int_det_explicit_altname": { "kms": "kmip", "type": "int", "algo": "det", "method": "explicit", "identifier": "altname", "allowed": true, "value": { "$numberInt": "123" } }, "kmip_timestamp_rand_auto_id": { "kms": "kmip", "type": "timestamp", "algo": "rand", "method": "auto", "identifier": "id", "allowed": true, "value": { "$timestamp": { "t": 0, "i": 12345 } } }, "kmip_timestamp_rand_auto_altname": { "kms": "kmip", "type": "timestamp", "algo": "rand", "method": "auto", "identifier": "altname", "allowed": true, "value": { "$timestamp": { "t": 0, "i": 12345 } } }, "kmip_timestamp_rand_explicit_id": { "kms": "kmip", "type": "timestamp", "algo": "rand", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$timestamp": { "t": 0, "i": 12345 } } }, "kmip_timestamp_rand_explicit_altname": { "kms": "kmip", "type": "timestamp", "algo": "rand", "method": "explicit", "identifier": "altname", "allowed": true, "value": { "$timestamp": { "t": 0, "i": 12345 } } }, "kmip_timestamp_det_auto_id": { "kms": "kmip", "type": "timestamp", "algo": "det", "method": "auto", "identifier": "id", "allowed": true, "value": { "$timestamp": { "t": 0, "i": 12345 } } }, "kmip_timestamp_det_explicit_id": { "kms": "kmip", "type": "timestamp", "algo": "det", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$timestamp": { "t": 0, "i": 12345 } } }, "kmip_timestamp_det_explicit_altname": { "kms": "kmip", "type": "timestamp", "algo": "det", "method": "explicit", "identifier": "altname", "allowed": true, "value": { "$timestamp": { "t": 0, "i": 12345 } } }, "kmip_long_rand_auto_id": { "kms": "kmip", "type": "long", "algo": "rand", "method": "auto", "identifier": "id", "allowed": true, "value": { "$numberLong": "456" } }, "kmip_long_rand_auto_altname": { "kms": "kmip", "type": "long", "algo": "rand", "method": "auto", "identifier": "altname", "allowed": true, "value": { "$numberLong": "456" } }, "kmip_long_rand_explicit_id": { "kms": "kmip", "type": "long", "algo": "rand", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$numberLong": "456" } }, "kmip_long_rand_explicit_altname": { "kms": "kmip", "type": "long", "algo": "rand", "method": "explicit", "identifier": "altname", "allowed": true, "value": { "$numberLong": "456" } }, "kmip_long_det_auto_id": { "kms": "kmip", "type": "long", "algo": "det", "method": "auto", "identifier": "id", "allowed": true, "value": { "$numberLong": "456" } }, "kmip_long_det_explicit_id": { "kms": "kmip", "type": "long", "algo": "det", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$numberLong": "456" } }, "kmip_long_det_explicit_altname": { "kms": "kmip", "type": "long", "algo": "det", "method": "explicit", "identifier": "altname", "allowed": true, "value": { "$numberLong": "456" } }, "kmip_decimal_rand_auto_id": { "kms": "kmip", "type": "decimal", "algo": "rand", "method": "auto", "identifier": "id", "allowed": true, "value": { "$numberDecimal": "1.234" } }, "kmip_decimal_rand_auto_altname": { "kms": "kmip", "type": "decimal", "algo": "rand", "method": "auto", "identifier": "altname", "allowed": true, "value": { "$numberDecimal": "1.234" } }, "kmip_decimal_rand_explicit_id": { "kms": "kmip", "type": "decimal", "algo": "rand", "method": "explicit", "identifier": "id", "allowed": true, "value": { "$numberDecimal": "1.234" } }, "kmip_decimal_rand_explicit_altname": { "kms": "kmip", "type": "decimal", "algo": "rand", "method": "explicit", "identifier": "altname", "allowed": true, "value": { "$numberDecimal": "1.234" } }, "kmip_decimal_det_explicit_id": { "kms": "kmip", "type": "decimal", "algo": "det", "method": "explicit", "identifier": "id", "allowed": false, "value": { "$numberDecimal": "1.234" } }, "kmip_decimal_det_explicit_altname": { "kms": "kmip", "type": "decimal", "algo": "det", "method": "explicit", "identifier": "altname", "allowed": false, "value": { "$numberDecimal": "1.234" } }, "kmip_minKey_rand_explicit_id": { "kms": "kmip", "type": "minKey", "algo": "rand", "method": "explicit", "identifier": "id", "allowed": false, "value": { "$minKey": 1 } }, "kmip_minKey_rand_explicit_altname": { "kms": "kmip", "type": "minKey", "algo": "rand", "method": "explicit", "identifier": "altname", "allowed": false, "value": { "$minKey": 1 } }, "kmip_minKey_det_explicit_id": { "kms": "kmip", "type": "minKey", "algo": "det", "method": "explicit", "identifier": "id", "allowed": false, "value": { "$minKey": 1 } }, "kmip_minKey_det_explicit_altname": { "kms": "kmip", "type": "minKey", "algo": "det", "method": "explicit", "identifier": "altname", "allowed": false, "value": { "$minKey": 1 } }, "kmip_maxKey_rand_explicit_id": { "kms": "kmip", "type": "maxKey", "algo": "rand", "method": "explicit", "identifier": "id", "allowed": false, "value": { "$maxKey": 1 } }, "kmip_maxKey_rand_explicit_altname": { "kms": "kmip", "type": "maxKey", "algo": "rand", "method": "explicit", "identifier": "altname", "allowed": false, "value": { "$maxKey": 1 } }, "kmip_maxKey_det_explicit_id": { "kms": "kmip", "type": "maxKey", "algo": "det", "method": "explicit", "identifier": "id", "allowed": false, "value": { "$maxKey": 1 } }, "kmip_maxKey_det_explicit_altname": { "kms": "kmip", "type": "maxKey", "algo": "det", "method": "explicit", "identifier": "altname", "allowed": false, "value": { "$maxKey": 1 } }, "payload=0,algo=rand": { "kms": "local", "type": "string", "algo": "rand", "method": "explicit", "identifier": "id", "allowed": true, "value": "" }, "payload=1,algo=rand": { "kms": "local", "type": "string", "algo": "rand", "method": "explicit", "identifier": "id", "allowed": true, "value": "a" }, "payload=2,algo=rand": { "kms": "local", "type": "string", "algo": "rand", "method": "explicit", "identifier": "id", "allowed": true, "value": "aa" }, "payload=3,algo=rand": { "kms": "local", "type": "string", "algo": "rand", "method": "explicit", "identifier": "id", "allowed": true, "value": "aaa" }, "payload=4,algo=rand": { "kms": "local", "type": "string", "algo": "rand", "method": "explicit", "identifier": "id", "allowed": true, "value": "aaaa" }, "payload=5,algo=rand": { "kms": "local", "type": "string", "algo": "rand", "method": "explicit", "identifier": "id", "allowed": true, "value": "aaaaa" }, "payload=6,algo=rand": { "kms": "local", "type": "string", "algo": "rand", "method": "explicit", "identifier": "id", "allowed": true, "value": "aaaaaa" }, "payload=7,algo=rand": { "kms": "local", "type": "string", "algo": "rand", "method": "explicit", "identifier": "id", "allowed": true, "value": "aaaaaaa" }, "payload=8,algo=rand": { "kms": "local", "type": "string", "algo": "rand", "method": "explicit", "identifier": "id", "allowed": true, "value": "aaaaaaaa" }, "payload=9,algo=rand": { "kms": "local", "type": "string", "algo": "rand", "method": "explicit", "identifier": "id", "allowed": true, "value": "aaaaaaaaa" }, "payload=10,algo=rand": { "kms": "local", "type": "string", "algo": "rand", "method": "explicit", "identifier": "id", "allowed": true, "value": "aaaaaaaaaa" }, "payload=11,algo=rand": { "kms": "local", "type": "string", "algo": "rand", "method": "explicit", "identifier": "id", "allowed": true, "value": "aaaaaaaaaaa" }, "payload=12,algo=rand": { "kms": "local", "type": "string", "algo": "rand", "method": "explicit", "identifier": "id", "allowed": true, "value": "aaaaaaaaaaaa" }, "payload=13,algo=rand": { "kms": "local", "type": "string", "algo": "rand", "method": "explicit", "identifier": "id", "allowed": true, "value": "aaaaaaaaaaaaa" }, "payload=14,algo=rand": { "kms": "local", "type": "string", "algo": "rand", "method": "explicit", "identifier": "id", "allowed": true, "value": "aaaaaaaaaaaaaa" }, "payload=15,algo=rand": { "kms": "local", "type": "string", "algo": "rand", "method": "explicit", "identifier": "id", "allowed": true, "value": "aaaaaaaaaaaaaaa" }, "payload=16,algo=rand": { "kms": "local", "type": "string", "algo": "rand", "method": "explicit", "identifier": "id", "allowed": true, "value": "aaaaaaaaaaaaaaaa" }, "payload=0,algo=det": { "kms": "local", "type": "string", "algo": "det", "method": "explicit", "identifier": "id", "allowed": true, "value": "" }, "payload=1,algo=det": { "kms": "local", "type": "string", "algo": "det", "method": "explicit", "identifier": "id", "allowed": true, "value": "a" }, "payload=2,algo=det": { "kms": "local", "type": "string", "algo": "det", "method": "explicit", "identifier": "id", "allowed": true, "value": "aa" }, "payload=3,algo=det": { "kms": "local", "type": "string", "algo": "det", "method": "explicit", "identifier": "id", "allowed": true, "value": "aaa" }, "payload=4,algo=det": { "kms": "local", "type": "string", "algo": "det", "method": "explicit", "identifier": "id", "allowed": true, "value": "aaaa" }, "payload=5,algo=det": { "kms": "local", "type": "string", "algo": "det", "method": "explicit", "identifier": "id", "allowed": true, "value": "aaaaa" }, "payload=6,algo=det": { "kms": "local", "type": "string", "algo": "det", "method": "explicit", "identifier": "id", "allowed": true, "value": "aaaaaa" }, "payload=7,algo=det": { "kms": "local", "type": "string", "algo": "det", "method": "explicit", "identifier": "id", "allowed": true, "value": "aaaaaaa" }, "payload=8,algo=det": { "kms": "local", "type": "string", "algo": "det", "method": "explicit", "identifier": "id", "allowed": true, "value": "aaaaaaaa" }, "payload=9,algo=det": { "kms": "local", "type": "string", "algo": "det", "method": "explicit", "identifier": "id", "allowed": true, "value": "aaaaaaaaa" }, "payload=10,algo=det": { "kms": "local", "type": "string", "algo": "det", "method": "explicit", "identifier": "id", "allowed": true, "value": "aaaaaaaaaa" }, "payload=11,algo=det": { "kms": "local", "type": "string", "algo": "det", "method": "explicit", "identifier": "id", "allowed": true, "value": "aaaaaaaaaaa" }, "payload=12,algo=det": { "kms": "local", "type": "string", "algo": "det", "method": "explicit", "identifier": "id", "allowed": true, "value": "aaaaaaaaaaaa" }, "payload=13,algo=det": { "kms": "local", "type": "string", "algo": "det", "method": "explicit", "identifier": "id", "allowed": true, "value": "aaaaaaaaaaaaa" }, "payload=14,algo=det": { "kms": "local", "type": "string", "algo": "det", "method": "explicit", "identifier": "id", "allowed": true, "value": "aaaaaaaaaaaaaa" }, "payload=15,algo=det": { "kms": "local", "type": "string", "algo": "det", "method": "explicit", "identifier": "id", "allowed": true, "value": "aaaaaaaaaaaaaaa" }, "payload=16,algo=det": { "kms": "local", "type": "string", "algo": "det", "method": "explicit", "identifier": "id", "allowed": true, "value": "aaaaaaaaaaaaaaaa" } }mongodb-mongo-python-driver-509e9b7/test/client-side-encryption/custom/000077500000000000000000000000001462766011000263165ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/client-side-encryption/custom/azure-dek.json000066400000000000000000000020211462766011000310730ustar00rootroot00000000000000{ "_id": { "$binary": { "base64": "AZURE+AAAAAAAAAAAAAAAA==", "subType": "04" } }, "keyMaterial": { "$binary": { "base64": "n+HWZ0ZSVOYA3cvQgP7inN4JSXfOH85IngmeQxRpQHjCCcqT3IFqEWNlrsVHiz3AELimHhX4HKqOLWMUeSIT6emUDDoQX9BAv8DR1+E1w4nGs/NyEneac78EYFkK3JysrFDOgl2ypCCTKAypkn9CkAx1if4cfgQE93LW4kczcyHdGiH36CIxrCDGv1UzAvERN5Qa47DVwsM6a+hWsF2AAAJVnF0wYLLJU07TuRHdMrrphPWXZsFgyV+lRqJ7DDpReKNO8nMPLV/mHqHBHGPGQiRdb9NoJo8CvokGz4+KE8oLwzKf6V24dtwZmRkrsDV4iOhvROAzz+Euo1ypSkL3mw==", "subType": "00" } }, "creationDate": { "$date": { "$numberLong": "1601573901680" } }, "updateDate": { "$date": { "$numberLong": "1601573901680" } }, "status": { "$numberInt": "0" }, "masterKey": { "provider": "azure", "keyVaultEndpoint": "key-vault-csfle.vault.azure.net", "keyName": "key-name-csfle" }, "keyAltNames": ["altname", "azure_altname"] } mongodb-mongo-python-driver-509e9b7/test/client-side-encryption/custom/azure-gcp-schema.json000066400000000000000000000017141462766011000323470ustar00rootroot00000000000000{ "db.coll": { "bsonType": "object", "properties": { "secret_azure": { "encrypt": { "keyId": [{ "$binary": { "base64": "AZURE+AAAAAAAAAAAAAAAA==", "subType": "04" } }], "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic", "bsonType": "string" } }, "secret_gcp": { "encrypt": { "keyId": [{ "$binary": { "base64": "GCP+AAAAAAAAAAAAAAAAAA==", "subType": "04" } }], "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic", "bsonType": "string" } } } } } mongodb-mongo-python-driver-509e9b7/test/client-side-encryption/custom/gcp-dek.json000066400000000000000000000017211462766011000305240ustar00rootroot00000000000000{ "_id": { "$binary": { "base64": "GCP+AAAAAAAAAAAAAAAAAA==", "subType": "04" } }, "keyMaterial": { "$binary": { "base64": "CiQAIgLj0WyktnB4dfYHo5SLZ41K4ASQrjJUaSzl5vvVH0G12G0SiQEAjlV8XPlbnHDEDFbdTO4QIe8ER2/172U1ouLazG0ysDtFFIlSvWX5ZnZUrRMmp/R2aJkzLXEt/zf8Mn4Lfm+itnjgo5R9K4pmPNvvPKNZX5C16lrPT+aA+rd+zXFSmlMg3i5jnxvTdLHhg3G7Q/Uv1ZIJskKt95bzLoe0tUVzRWMYXLIEcohnQg==", "subType": "00" } }, "creationDate": { "$date": { "$numberLong": "1601574333107" } }, "updateDate": { "$date": { "$numberLong": "1601574333107" } }, "status": { "$numberInt": "0" }, "masterKey": { "provider": "gcp", "projectId": "devprod-drivers", "location": "global", "keyRing": "key-ring-csfle", "keyName": "key-name-csfle" }, "keyAltNames": ["altname", "gcp_altname"] } mongodb-mongo-python-driver-509e9b7/test/client-side-encryption/custom/key-document-local.json000066400000000000000000000011561462766011000327100ustar00rootroot00000000000000{ "_id": { "$binary": { "base64": "YWFhYWFhYWFhYWFhYWFhYQ==", "subType": "04" } }, "keyMaterial": { "$binary": { "base64": "db27rshiqK4Jqhb2xnwK4RfdFb9JuKeUe6xt5aYQF4o62tS75b7B4wxVN499gND9UVLUbpVKoyUoaZAeA895OENP335b8n8OwchcTFqS44t+P3zmhteYUQLIWQXaIgon7gEgLeJbaDHmSXS6/7NbfDDFlB37N7BP/2hx1yCOTN6NG/8M1ppw3LYT3CfP6EfXVEttDYtPbJpbb7nBVlxD7w==", "subType": "00" } }, "creationDate": { "$date": { "$numberLong": "1564354142963" } }, "updateDate": { "$date": { "$numberLong": "1564354142963" } }, "status": { "$numberInt": "0" }, "masterKey": { "provider": "local" } } mongodb-mongo-python-driver-509e9b7/test/client-side-encryption/custom/schema.json000066400000000000000000000005261462766011000304540ustar00rootroot00000000000000{ "properties": { "ssn": { "encrypt": { "keyId": [{ "$binary": { "base64": "YWFhYWFhYWFhYWFhYWFhYQ==", "subType": "04" } }], "bsonType": "string", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" } } }, "bsonType": "object" } mongodb-mongo-python-driver-509e9b7/test/client-side-encryption/etc/000077500000000000000000000000001462766011000255575ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/client-side-encryption/etc/data/000077500000000000000000000000001462766011000264705ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/client-side-encryption/etc/data/encryptedFields.json000066400000000000000000000010541462766011000325070ustar00rootroot00000000000000{ "fields": [ { "keyId": { "$binary": { "base64": "EjRWeBI0mHYSNBI0VniQEg==", "subType": "04" } }, "path": "encryptedIndexed", "bsonType": "string", "queries": { "queryType": "equality", "contention": { "$numberLong": "0" } } }, { "keyId": { "$binary": { "base64": "q83vqxI0mHYSNBI0VniQEg==", "subType": "04" } }, "path": "encryptedUnindexed", "bsonType": "string" } ] }mongodb-mongo-python-driver-509e9b7/test/client-side-encryption/etc/data/keys/000077500000000000000000000000001462766011000274435ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/client-side-encryption/etc/data/keys/key1-document.json000066400000000000000000000013741462766011000330300ustar00rootroot00000000000000{ "_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" } } mongodb-mongo-python-driver-509e9b7/test/client-side-encryption/etc/data/keys/key1-id.json000066400000000000000000000001411462766011000315750ustar00rootroot00000000000000{ "$binary": { "base64": "EjRWeBI0mHYSNBI0VniQEg==", "subType": "04" } } mongodb-mongo-python-driver-509e9b7/test/client-side-encryption/etc/data/keys/key2-document.json000066400000000000000000000013041462766011000330220ustar00rootroot00000000000000{ "_id": { "$binary": { "base64": "q83vqxI0mHYSNBI0VniQEg==", "subType": "04" } }, "keyMaterial": { "$binary": { "base64": "HBk9BWihXExNDvTp1lUxOuxuZK2Pe2ZdVdlsxPEBkiO1bS4mG5NNDsQ7zVxJAH8BtdOYp72Ku4Y3nwc0BUpIKsvAKX4eYXtlhv5zUQxWdeNFhg9qK7qb8nqhnnLeT0f25jFSqzWJoT379hfwDeu0bebJHr35QrJ8myZdPMTEDYF08QYQ48ShRBli0S+QzBHHAQiM2iJNr4svg2WR8JSeWQ==", "subType": "00" } }, "creationDate": { "$date": { "$numberLong": "1648914851981" } }, "updateDate": { "$date": { "$numberLong": "1648914851981" } }, "status": { "$numberInt": "0" }, "masterKey": { "provider": "local" } } mongodb-mongo-python-driver-509e9b7/test/client-side-encryption/etc/data/keys/key2-id.json000066400000000000000000000001311462766011000315750ustar00rootroot00000000000000{ "$binary": { "base64": "q83vqxI0mHYSNBI0VniQEg==", "subType": "04" } } range-encryptedFields-Date.json000066400000000000000000000011251462766011000343740ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/client-side-encryption/etc/data{ "fields": [ { "keyId": { "$binary": { "base64": "EjRWeBI0mHYSNBI0VniQEg==", "subType": "04" } }, "path": "encryptedDate", "bsonType": "date", "queries": { "queryType": "rangePreview", "contention": { "$numberLong": "0" }, "sparsity": { "$numberLong": "1" }, "min": { "$date": { "$numberLong": "0" } }, "max": { "$date": { "$numberLong": "200" } } } } ] } range-encryptedFields-DecimalNoPrecision.json000066400000000000000000000006541462766011000372340ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/client-side-encryption/etc/data{ "fields": [ { "keyId": { "$binary": { "base64": "EjRWeBI0mHYSNBI0VniQEg==", "subType": "04" } }, "path": "encryptedDecimalNoPrecision", "bsonType": "decimal", "queries": { "queryType": "rangePreview", "contention": { "$numberLong": "0" }, "sparsity": { "$numberLong": "1" } } } ] } range-encryptedFields-DecimalPrecision.json000066400000000000000000000011461462766011000367340ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/client-side-encryption/etc/data{ "fields": [ { "keyId": { "$binary": { "base64": "EjRWeBI0mHYSNBI0VniQEg==", "subType": "04" } }, "path": "encryptedDecimalPrecision", "bsonType": "decimal", "queries": { "queryType": "rangePreview", "contention": { "$numberLong": "0" }, "sparsity": { "$numberLong": "1" }, "min": { "$numberDecimal": "0.0" }, "max": { "$numberDecimal": "200.0" }, "precision": { "$numberInt": "2" } } } ] } range-encryptedFields-DoubleNoPrecision.json000066400000000000000000000006521462766011000371060ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/client-side-encryption/etc/data{ "fields": [ { "keyId": { "$binary": { "base64": "EjRWeBI0mHYSNBI0VniQEg==", "subType": "04" } }, "path": "encryptedDoubleNoPrecision", "bsonType": "double", "queries": { "queryType": "rangePreview", "contention": { "$numberLong": "0" }, "sparsity": { "$numberLong": "1" } } } ] } range-encryptedFields-DoublePrecision.json000066400000000000000000000011421462766011000366040ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/client-side-encryption/etc/data{ "fields": [ { "keyId": { "$binary": { "base64": "EjRWeBI0mHYSNBI0VniQEg==", "subType": "04" } }, "path": "encryptedDoublePrecision", "bsonType": "double", "queries": { "queryType": "rangePreview", "contention": { "$numberLong": "0" }, "sparsity": { "$numberLong": "1" }, "min": { "$numberDouble": "0.0" }, "max": { "$numberDouble": "200.0" }, "precision": { "$numberInt": "2" } } } ] } range-encryptedFields-Int.json000066400000000000000000000010131462766011000342450ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/client-side-encryption/etc/data{ "fields": [ { "keyId": { "$binary": { "base64": "EjRWeBI0mHYSNBI0VniQEg==", "subType": "04" } }, "path": "encryptedInt", "bsonType": "int", "queries": { "queryType": "rangePreview", "contention": { "$numberLong": "0" }, "sparsity": { "$numberLong": "1" }, "min": { "$numberInt": "0" }, "max": { "$numberInt": "200" } } } ] } range-encryptedFields-Long.json000066400000000000000000000010171462766011000344160ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/client-side-encryption/etc/data{ "fields": [ { "keyId": { "$binary": { "base64": "EjRWeBI0mHYSNBI0VniQEg==", "subType": "04" } }, "path": "encryptedLong", "bsonType": "long", "queries": { "queryType": "rangePreview", "contention": { "$numberLong": "0" }, "sparsity": { "$numberLong": "1" }, "min": { "$numberLong": "0" }, "max": { "$numberLong": "200" } } } ] } mongodb-mongo-python-driver-509e9b7/test/client-side-encryption/external/000077500000000000000000000000001462766011000266265ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/client-side-encryption/external/external-key.json000066400000000000000000000014421462766011000321320ustar00rootroot00000000000000{ "status": { "$numberInt": "1" }, "_id": { "$binary": { "base64": "LOCALAAAAAAAAAAAAAAAAA==", "subType": "04" } }, "masterKey": { "provider": "local" }, "updateDate": { "$date": { "$numberLong": "1557827033449" } }, "keyMaterial": { "$binary": { "base64": "Ce9HSz/HKKGkIt4uyy+jDuKGA+rLC2cycykMo6vc8jXxqa1UVDYHWq1r+vZKbnnSRBfB981akzRKZCFpC05CTyFqDhXv6OnMjpG97OZEREGIsHEYiJkBW0jJJvfLLgeLsEpBzsro9FztGGXASxyxFRZFhXvHxyiLOKrdWfs7X1O/iK3pEoHMx6uSNSfUOgbebLfIqW7TO++iQS5g1xovXA==", "subType": "00" } }, "creationDate": { "$date": { "$numberLong": "1557827033449" } }, "keyAltNames": [ "local" ] }mongodb-mongo-python-driver-509e9b7/test/client-side-encryption/external/external-schema.json000066400000000000000000000007551462766011000326100ustar00rootroot00000000000000{ "properties": { "encrypted": { "encrypt": { "keyId": [ { "$binary": { "base64": "LOCALAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "bsonType": "string", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" } } }, "bsonType": "object" } mongodb-mongo-python-driver-509e9b7/test/client-side-encryption/limits/000077500000000000000000000000001462766011000263055ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/client-side-encryption/limits/limits-doc.json000066400000000000000000000031011462766011000312370ustar00rootroot00000000000000{ "00": "a", "01": "a", "02": "a", "03": "a", "04": "a", "05": "a", "06": "a", "07": "a", "08": "a", "09": "a", "10": "a", "11": "a", "12": "a", "13": "a", "14": "a", "15": "a", "16": "a", "17": "a", "18": "a", "19": "a", "20": "a", "21": "a", "22": "a", "23": "a", "24": "a", "25": "a", "26": "a", "27": "a", "28": "a", "29": "a", "30": "a", "31": "a", "32": "a", "33": "a", "34": "a", "35": "a", "36": "a", "37": "a", "38": "a", "39": "a", "40": "a", "41": "a", "42": "a", "43": "a", "44": "a", "45": "a", "46": "a", "47": "a", "48": "a", "49": "a", "50": "a", "51": "a", "52": "a", "53": "a", "54": "a", "55": "a", "56": "a", "57": "a", "58": "a", "59": "a", "60": "a", "61": "a", "62": "a", "63": "a", "64": "a", "65": "a", "66": "a", "67": "a", "68": "a", "69": "a", "70": "a", "71": "a", "72": "a", "73": "a", "74": "a", "75": "a", "76": "a", "77": "a", "78": "a", "79": "a", "80": "a", "81": "a", "82": "a", "83": "a", "84": "a", "85": "a", "86": "a", "87": "a", "88": "a", "89": "a", "90": "a", "91": "a", "92": "a", "93": "a", "94": "a", "95": "a", "96": "a", "97": "a", "98": "a", "99": "a" }mongodb-mongo-python-driver-509e9b7/test/client-side-encryption/limits/limits-key.json000066400000000000000000000014421462766011000312700ustar00rootroot00000000000000{ "status": { "$numberInt": "1" }, "_id": { "$binary": { "base64": "LOCALAAAAAAAAAAAAAAAAA==", "subType": "04" } }, "masterKey": { "provider": "local" }, "updateDate": { "$date": { "$numberLong": "1557827033449" } }, "keyMaterial": { "$binary": { "base64": "Ce9HSz/HKKGkIt4uyy+jDuKGA+rLC2cycykMo6vc8jXxqa1UVDYHWq1r+vZKbnnSRBfB981akzRKZCFpC05CTyFqDhXv6OnMjpG97OZEREGIsHEYiJkBW0jJJvfLLgeLsEpBzsro9FztGGXASxyxFRZFhXvHxyiLOKrdWfs7X1O/iK3pEoHMx6uSNSfUOgbebLfIqW7TO++iQS5g1xovXA==", "subType": "00" } }, "creationDate": { "$date": { "$numberLong": "1557827033449" } }, "keyAltNames": [ "local" ] }mongodb-mongo-python-driver-509e9b7/test/client-side-encryption/limits/limits-schema.json000066400000000000000000001271561462766011000317530ustar00rootroot00000000000000{ "properties": { "00": { "encrypt": { "keyId": [ { "$binary": { "base64": "LOCALAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "bsonType": "string", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" } }, "01": { "encrypt": { "keyId": [ { "$binary": { "base64": "LOCALAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "bsonType": "string", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" } }, "02": { "encrypt": { "keyId": [ { "$binary": { "base64": "LOCALAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "bsonType": "string", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" } }, "03": { "encrypt": { "keyId": [ { "$binary": { "base64": "LOCALAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "bsonType": "string", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" } }, "04": { "encrypt": { "keyId": [ { "$binary": { "base64": "LOCALAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "bsonType": "string", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" } }, "05": { "encrypt": { "keyId": [ { "$binary": { "base64": "LOCALAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "bsonType": "string", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" } }, "06": { "encrypt": { "keyId": [ { "$binary": { "base64": "LOCALAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "bsonType": "string", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" } }, "07": { "encrypt": { "keyId": [ { "$binary": { "base64": "LOCALAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "bsonType": "string", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" } }, "08": { "encrypt": { "keyId": [ { "$binary": { "base64": "LOCALAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "bsonType": "string", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" } }, "09": { "encrypt": { "keyId": [ { "$binary": { "base64": "LOCALAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "bsonType": "string", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" } }, "10": { "encrypt": { "keyId": [ { "$binary": { "base64": "LOCALAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "bsonType": "string", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" } }, "11": { "encrypt": { "keyId": [ { "$binary": { "base64": "LOCALAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "bsonType": "string", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" } }, "12": { "encrypt": { "keyId": [ { "$binary": { "base64": "LOCALAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "bsonType": "string", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" } }, "13": { "encrypt": { "keyId": [ { "$binary": { "base64": "LOCALAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "bsonType": "string", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" } }, "14": { "encrypt": { "keyId": [ { "$binary": { "base64": "LOCALAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "bsonType": "string", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" } }, "15": { "encrypt": { "keyId": [ { "$binary": { "base64": "LOCALAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "bsonType": "string", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" } }, "16": { "encrypt": { "keyId": [ { "$binary": { "base64": "LOCALAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "bsonType": "string", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" } }, "17": { "encrypt": { "keyId": [ { "$binary": { "base64": "LOCALAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "bsonType": "string", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" } }, "18": { "encrypt": { "keyId": [ { "$binary": { "base64": "LOCALAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "bsonType": "string", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" } }, "19": { "encrypt": { "keyId": [ { "$binary": { "base64": "LOCALAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "bsonType": "string", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" } }, "20": { "encrypt": { "keyId": [ { "$binary": { "base64": "LOCALAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "bsonType": "string", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" } }, "21": { "encrypt": { "keyId": [ { "$binary": { "base64": "LOCALAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "bsonType": "string", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" } }, "22": { "encrypt": { "keyId": [ { "$binary": { "base64": "LOCALAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "bsonType": "string", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" } }, "23": { "encrypt": { "keyId": [ { "$binary": { "base64": "LOCALAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "bsonType": "string", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" } }, "24": { "encrypt": { "keyId": [ { "$binary": { "base64": "LOCALAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "bsonType": "string", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" } }, "25": { "encrypt": { "keyId": [ { "$binary": { "base64": "LOCALAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "bsonType": "string", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" } }, "26": { "encrypt": { "keyId": [ { "$binary": { "base64": "LOCALAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "bsonType": "string", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" } }, "27": { "encrypt": { "keyId": [ { "$binary": { "base64": "LOCALAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "bsonType": "string", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" } }, "28": { "encrypt": { "keyId": [ { "$binary": { "base64": "LOCALAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "bsonType": "string", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" } }, "29": { "encrypt": { "keyId": [ { "$binary": { "base64": "LOCALAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "bsonType": "string", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" } }, "30": { "encrypt": { "keyId": [ { "$binary": { "base64": "LOCALAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "bsonType": "string", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" } }, "31": { "encrypt": { "keyId": [ { "$binary": { "base64": "LOCALAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "bsonType": "string", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" } }, "32": { "encrypt": { "keyId": [ { "$binary": { "base64": "LOCALAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "bsonType": "string", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" } }, "33": { "encrypt": { "keyId": [ { "$binary": { "base64": "LOCALAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "bsonType": "string", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" } }, "34": { "encrypt": { "keyId": [ { "$binary": { "base64": "LOCALAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "bsonType": "string", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" } }, "35": { "encrypt": { "keyId": [ { "$binary": { "base64": "LOCALAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "bsonType": "string", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" } }, "36": { "encrypt": { "keyId": [ { "$binary": { "base64": "LOCALAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "bsonType": "string", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" } }, "37": { "encrypt": { "keyId": [ { "$binary": { "base64": "LOCALAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "bsonType": "string", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" } }, "38": { "encrypt": { "keyId": [ { "$binary": { "base64": "LOCALAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "bsonType": "string", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" } }, "39": { "encrypt": { "keyId": [ { "$binary": { "base64": "LOCALAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "bsonType": "string", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" } }, "40": { "encrypt": { "keyId": [ { "$binary": { "base64": "LOCALAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "bsonType": "string", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" } }, "41": { "encrypt": { "keyId": [ { "$binary": { "base64": "LOCALAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "bsonType": "string", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" } }, "42": { "encrypt": { "keyId": [ { "$binary": { "base64": "LOCALAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "bsonType": "string", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" } }, "43": { "encrypt": { "keyId": [ { "$binary": { "base64": "LOCALAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "bsonType": "string", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" } }, "44": { "encrypt": { "keyId": [ { "$binary": { "base64": "LOCALAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "bsonType": "string", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" } }, "45": { "encrypt": { "keyId": [ { "$binary": { "base64": "LOCALAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "bsonType": "string", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" } }, "46": { "encrypt": { "keyId": [ { "$binary": { "base64": "LOCALAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "bsonType": "string", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" } }, "47": { "encrypt": { "keyId": [ { "$binary": { "base64": "LOCALAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "bsonType": "string", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" } }, "48": { "encrypt": { "keyId": [ { "$binary": { "base64": "LOCALAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "bsonType": "string", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" } }, "49": { "encrypt": { "keyId": [ { "$binary": { "base64": "LOCALAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "bsonType": "string", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" } }, "50": { "encrypt": { "keyId": [ { "$binary": { "base64": "LOCALAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "bsonType": "string", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" } }, "51": { "encrypt": { "keyId": [ { "$binary": { "base64": "LOCALAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "bsonType": "string", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" } }, "52": { "encrypt": { "keyId": [ { "$binary": { "base64": "LOCALAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "bsonType": "string", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" } }, "53": { "encrypt": { "keyId": [ { "$binary": { "base64": "LOCALAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "bsonType": "string", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" } }, "54": { "encrypt": { "keyId": [ { "$binary": { "base64": "LOCALAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "bsonType": "string", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" } }, "55": { "encrypt": { "keyId": [ { "$binary": { "base64": "LOCALAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "bsonType": "string", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" } }, "56": { "encrypt": { "keyId": [ { "$binary": { "base64": "LOCALAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "bsonType": "string", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" } }, "57": { "encrypt": { "keyId": [ { "$binary": { "base64": "LOCALAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "bsonType": "string", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" } }, "58": { "encrypt": { "keyId": [ { "$binary": { "base64": "LOCALAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "bsonType": "string", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" } }, "59": { "encrypt": { "keyId": [ { "$binary": { "base64": "LOCALAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "bsonType": "string", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" } }, "60": { "encrypt": { "keyId": [ { "$binary": { "base64": "LOCALAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "bsonType": "string", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" } }, "61": { "encrypt": { "keyId": [ { "$binary": { "base64": "LOCALAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "bsonType": "string", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" } }, "62": { "encrypt": { "keyId": [ { "$binary": { "base64": "LOCALAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "bsonType": "string", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" } }, "63": { "encrypt": { "keyId": [ { "$binary": { "base64": "LOCALAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "bsonType": "string", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" } }, "64": { "encrypt": { "keyId": [ { "$binary": { "base64": "LOCALAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "bsonType": "string", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" } }, "65": { "encrypt": { "keyId": [ { "$binary": { "base64": "LOCALAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "bsonType": "string", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" } }, "66": { "encrypt": { "keyId": [ { "$binary": { "base64": "LOCALAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "bsonType": "string", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" } }, "67": { "encrypt": { "keyId": [ { "$binary": { "base64": "LOCALAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "bsonType": "string", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" } }, "68": { "encrypt": { "keyId": [ { "$binary": { "base64": "LOCALAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "bsonType": "string", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" } }, "69": { "encrypt": { "keyId": [ { "$binary": { "base64": "LOCALAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "bsonType": "string", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" } }, "70": { "encrypt": { "keyId": [ { "$binary": { "base64": "LOCALAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "bsonType": "string", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" } }, "71": { "encrypt": { "keyId": [ { "$binary": { "base64": "LOCALAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "bsonType": "string", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" } }, "72": { "encrypt": { "keyId": [ { "$binary": { "base64": "LOCALAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "bsonType": "string", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" } }, "73": { "encrypt": { "keyId": [ { "$binary": { "base64": "LOCALAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "bsonType": "string", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" } }, "74": { "encrypt": { "keyId": [ { "$binary": { "base64": "LOCALAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "bsonType": "string", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" } }, "75": { "encrypt": { "keyId": [ { "$binary": { "base64": "LOCALAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "bsonType": "string", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" } }, "76": { "encrypt": { "keyId": [ { "$binary": { "base64": "LOCALAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "bsonType": "string", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" } }, "77": { "encrypt": { "keyId": [ { "$binary": { "base64": "LOCALAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "bsonType": "string", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" } }, "78": { "encrypt": { "keyId": [ { "$binary": { "base64": "LOCALAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "bsonType": "string", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" } }, "79": { "encrypt": { "keyId": [ { "$binary": { "base64": "LOCALAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "bsonType": "string", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" } }, "80": { "encrypt": { "keyId": [ { "$binary": { "base64": "LOCALAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "bsonType": "string", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" } }, "81": { "encrypt": { "keyId": [ { "$binary": { "base64": "LOCALAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "bsonType": "string", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" } }, "82": { "encrypt": { "keyId": [ { "$binary": { "base64": "LOCALAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "bsonType": "string", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" } }, "83": { "encrypt": { "keyId": [ { "$binary": { "base64": "LOCALAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "bsonType": "string", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" } }, "84": { "encrypt": { "keyId": [ { "$binary": { "base64": "LOCALAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "bsonType": "string", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" } }, "85": { "encrypt": { "keyId": [ { "$binary": { "base64": "LOCALAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "bsonType": "string", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" } }, "86": { "encrypt": { "keyId": [ { "$binary": { "base64": "LOCALAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "bsonType": "string", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" } }, "87": { "encrypt": { "keyId": [ { "$binary": { "base64": "LOCALAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "bsonType": "string", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" } }, "88": { "encrypt": { "keyId": [ { "$binary": { "base64": "LOCALAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "bsonType": "string", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" } }, "89": { "encrypt": { "keyId": [ { "$binary": { "base64": "LOCALAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "bsonType": "string", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" } }, "90": { "encrypt": { "keyId": [ { "$binary": { "base64": "LOCALAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "bsonType": "string", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" } }, "91": { "encrypt": { "keyId": [ { "$binary": { "base64": "LOCALAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "bsonType": "string", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" } }, "92": { "encrypt": { "keyId": [ { "$binary": { "base64": "LOCALAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "bsonType": "string", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" } }, "93": { "encrypt": { "keyId": [ { "$binary": { "base64": "LOCALAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "bsonType": "string", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" } }, "94": { "encrypt": { "keyId": [ { "$binary": { "base64": "LOCALAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "bsonType": "string", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" } }, "95": { "encrypt": { "keyId": [ { "$binary": { "base64": "LOCALAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "bsonType": "string", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" } }, "96": { "encrypt": { "keyId": [ { "$binary": { "base64": "LOCALAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "bsonType": "string", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" } }, "97": { "encrypt": { "keyId": [ { "$binary": { "base64": "LOCALAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "bsonType": "string", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" } }, "98": { "encrypt": { "keyId": [ { "$binary": { "base64": "LOCALAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "bsonType": "string", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" } }, "99": { "encrypt": { "keyId": [ { "$binary": { "base64": "LOCALAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "bsonType": "string", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" } } }, "bsonType": "object" }mongodb-mongo-python-driver-509e9b7/test/client-side-encryption/spec/000077500000000000000000000000001462766011000257365ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/client-side-encryption/spec/legacy/000077500000000000000000000000001462766011000272025ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/client-side-encryption/spec/legacy/aggregate.json000066400000000000000000000227551462766011000320360ustar00rootroot00000000000000{ "runOn": [ { "minServerVersion": "4.1.10" } ], "database_name": "default", "collection_name": "default", "data": [ { "_id": 1, "encrypted_string": { "$binary": { "base64": "AQAAAAAAAAAAAAAAAAAAAAACwj+3zkv2VM+aTfk60RqhXq6a/77WlLwu/BxXFkL7EppGsju/m8f0x5kBDD3EZTtGALGXlym5jnpZAoSIkswHoA==", "subType": "06" } } } ], "json_schema": { "properties": { "encrypted_w_altname": { "encrypt": { "keyId": "/altname", "bsonType": "string", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Random" } }, "encrypted_string": { "encrypt": { "keyId": [ { "$binary": { "base64": "AAAAAAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "bsonType": "string", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" } }, "random": { "encrypt": { "keyId": [ { "$binary": { "base64": "AAAAAAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "bsonType": "string", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Random" } }, "encrypted_string_equivalent": { "encrypt": { "keyId": [ { "$binary": { "base64": "AAAAAAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "bsonType": "string", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" } } }, "bsonType": "object" }, "key_vault_data": [ { "status": 1, "_id": { "$binary": { "base64": "AAAAAAAAAAAAAAAAAAAAAA==", "subType": "04" } }, "masterKey": { "provider": "aws", "key": "arn:aws:kms:us-east-1:579766882180:key/89fcc2c4-08b0-4bd9-9f25-e30687b580d0", "region": "us-east-1" }, "updateDate": { "$date": { "$numberLong": "1552949630483" } }, "keyMaterial": { "$binary": { "base64": "AQICAHhQNmWG2CzOm1dq3kWLM+iDUZhEqnhJwH9wZVpuZ94A8gEqnsxXlR51T5EbEVezUqqKAAAAwjCBvwYJKoZIhvcNAQcGoIGxMIGuAgEAMIGoBgkqhkiG9w0BBwEwHgYJYIZIAWUDBAEuMBEEDHa4jo6yp0Z18KgbUgIBEIB74sKxWtV8/YHje5lv5THTl0HIbhSwM6EqRlmBiFFatmEWaeMk4tO4xBX65eq670I5TWPSLMzpp8ncGHMmvHqRajNBnmFtbYxN3E3/WjxmdbOOe+OXpnGJPcGsftc7cB2shRfA4lICPnE26+oVNXT6p0Lo20nY5XC7jyCO", "subType": "00" } }, "creationDate": { "$date": { "$numberLong": "1552949630483" } }, "keyAltNames": [ "altname", "another_altname" ] } ], "tests": [ { "description": "Aggregate with deterministic encryption", "skipReason": "SERVER-39395", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "aws": {} } } }, "operations": [ { "name": "aggregate", "arguments": { "pipeline": [ { "$match": { "encrypted_string": "457-55-5642" } } ] }, "result": [ { "_id": 1, "encrypted_string": "string0" } ] } ], "expectations": [ { "command_started_event": { "command": { "listCollections": 1, "filter": { "name": "default" } }, "command_name": "listCollections" } }, { "command_started_event": { "command": { "find": "datakeys", "filter": { "$or": [ { "_id": { "$in": [ { "$binary": { "base64": "AAAAAAAAAAAAAAAAAAAAAA==", "subType": "04" } } ] } }, { "keyAltNames": { "$in": [] } } ] }, "$db": "keyvault", "readConcern": { "level": "majority" } }, "command_name": "find" } }, { "command_started_event": { "command": { "aggregate": "default", "pipeline": [ { "$match": { "encrypted_string": "457-55-5642" } } ] }, "command_name": "aggregate" } } ], "outcome": { "collection": { "data": [ { "_id": 1, "encrypted_string": { "$binary": { "base64": "AQAAAAAAAAAAAAAAAAAAAAACwj+3zkv2VM+aTfk60RqhXq6a/77WlLwu/BxXFkL7EppGsju/m8f0x5kBDD3EZTtGALGXlym5jnpZAoSIkswHoA==", "subType": "06" } } } ] } } }, { "description": "Aggregate with empty pipeline", "skipReason": "SERVER-40829 hides agg support behind enableTestCommands flag.", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "aws": {} } } }, "operations": [ { "name": "aggregate", "arguments": { "pipeline": [] }, "result": [ { "_id": 1, "encrypted_string": "string0" } ] } ], "expectations": [ { "command_started_event": { "command": { "listCollections": 1, "filter": { "name": "default" } }, "command_name": "listCollections" } }, { "command_started_event": { "command": { "aggregate": "default", "pipeline": [], "cursor": {} }, "command_name": "aggregate" } }, { "command_started_event": { "command": { "find": "datakeys", "filter": { "$or": [ { "_id": { "$in": [ { "$binary": { "base64": "AAAAAAAAAAAAAAAAAAAAAA==", "subType": "04" } } ] } }, { "keyAltNames": { "$in": [] } } ] }, "$db": "keyvault", "readConcern": { "level": "majority" } }, "command_name": "find" } } ], "outcome": { "collection": { "data": [ { "_id": 1, "encrypted_string": { "$binary": { "base64": "AQAAAAAAAAAAAAAAAAAAAAACwj+3zkv2VM+aTfk60RqhXq6a/77WlLwu/BxXFkL7EppGsju/m8f0x5kBDD3EZTtGALGXlym5jnpZAoSIkswHoA==", "subType": "06" } } } ] } } }, { "description": "Aggregate should fail with random encryption", "skipReason": "SERVER-39395", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "aws": {} } } }, "operations": [ { "name": "aggregate", "arguments": { "pipeline": [ { "$match": { "random": "abc" } } ] }, "result": { "errorContains": "Cannot query on fields encrypted with the randomized encryption" } } ] }, { "description": "Database aggregate should fail", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "aws": {} } } }, "operations": [ { "name": "aggregate", "object": "database", "arguments": { "pipeline": [ { "$currentOp": { "allUsers": false, "idleConnections": false, "localOps": true } }, { "$match": { "command.aggregate": { "$eq": 1 } } }, { "$project": { "command": 1 } }, { "$project": { "command.lsid": 0 } } ] }, "result": { "errorContains": "non-collection command not supported for auto encryption: aggregate" } } ] } ] } mongodb-mongo-python-driver-509e9b7/test/client-side-encryption/spec/legacy/awsTemporary.json000066400000000000000000000132411462766011000325730ustar00rootroot00000000000000{ "runOn": [ { "minServerVersion": "4.1.10" } ], "database_name": "default", "collection_name": "default", "data": [], "json_schema": { "properties": { "encrypted_w_altname": { "encrypt": { "keyId": "/altname", "bsonType": "string", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Random" } }, "encrypted_string": { "encrypt": { "keyId": [ { "$binary": { "base64": "AAAAAAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "bsonType": "string", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" } }, "random": { "encrypt": { "keyId": [ { "$binary": { "base64": "AAAAAAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "bsonType": "string", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Random" } }, "encrypted_string_equivalent": { "encrypt": { "keyId": [ { "$binary": { "base64": "AAAAAAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "bsonType": "string", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" } } }, "bsonType": "object" }, "key_vault_data": [ { "status": 1, "_id": { "$binary": { "base64": "AAAAAAAAAAAAAAAAAAAAAA==", "subType": "04" } }, "masterKey": { "provider": "aws", "key": "arn:aws:kms:us-east-1:579766882180:key/89fcc2c4-08b0-4bd9-9f25-e30687b580d0", "region": "us-east-1" }, "updateDate": { "$date": { "$numberLong": "1552949630483" } }, "keyMaterial": { "$binary": { "base64": "AQICAHhQNmWG2CzOm1dq3kWLM+iDUZhEqnhJwH9wZVpuZ94A8gEqnsxXlR51T5EbEVezUqqKAAAAwjCBvwYJKoZIhvcNAQcGoIGxMIGuAgEAMIGoBgkqhkiG9w0BBwEwHgYJYIZIAWUDBAEuMBEEDHa4jo6yp0Z18KgbUgIBEIB74sKxWtV8/YHje5lv5THTl0HIbhSwM6EqRlmBiFFatmEWaeMk4tO4xBX65eq670I5TWPSLMzpp8ncGHMmvHqRajNBnmFtbYxN3E3/WjxmdbOOe+OXpnGJPcGsftc7cB2shRfA4lICPnE26+oVNXT6p0Lo20nY5XC7jyCO", "subType": "00" } }, "creationDate": { "$date": { "$numberLong": "1552949630483" } }, "keyAltNames": [ "altname", "another_altname" ] } ], "tests": [ { "description": "Insert a document with auto encryption using the AWS provider with temporary credentials", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "awsTemporary": {} } } }, "operations": [ { "name": "insertOne", "arguments": { "document": { "_id": 1, "encrypted_string": "string0" } } } ], "expectations": [ { "command_started_event": { "command": { "listCollections": 1, "filter": { "name": "default" } }, "command_name": "listCollections" } }, { "command_started_event": { "command": { "find": "datakeys", "filter": { "$or": [ { "_id": { "$in": [ { "$binary": { "base64": "AAAAAAAAAAAAAAAAAAAAAA==", "subType": "04" } } ] } }, { "keyAltNames": { "$in": [] } } ] }, "$db": "keyvault" }, "command_name": "find" } }, { "command_started_event": { "command": { "insert": "default", "documents": [ { "_id": 1, "encrypted_string": { "$binary": { "base64": "AQAAAAAAAAAAAAAAAAAAAAACwj+3zkv2VM+aTfk60RqhXq6a/77WlLwu/BxXFkL7EppGsju/m8f0x5kBDD3EZTtGALGXlym5jnpZAoSIkswHoA==", "subType": "06" } } } ], "ordered": true }, "command_name": "insert" } } ], "outcome": { "collection": { "data": [ { "_id": 1, "encrypted_string": { "$binary": { "base64": "AQAAAAAAAAAAAAAAAAAAAAACwj+3zkv2VM+aTfk60RqhXq6a/77WlLwu/BxXFkL7EppGsju/m8f0x5kBDD3EZTtGALGXlym5jnpZAoSIkswHoA==", "subType": "06" } } } ] } } }, { "description": "Insert with invalid temporary credentials", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "awsTemporaryNoSessionToken": {} } } }, "operations": [ { "name": "insertOne", "arguments": { "document": { "_id": 1, "encrypted_string": "string0" } }, "result": { "errorContains": "security token" } } ] } ] } mongodb-mongo-python-driver-509e9b7/test/client-side-encryption/spec/legacy/azureKMS.json000066400000000000000000000132571462766011000316060ustar00rootroot00000000000000{ "runOn": [ { "minServerVersion": "4.1.10" } ], "database_name": "default", "collection_name": "default", "data": [], "json_schema": { "properties": { "encrypted_string_aws": { "encrypt": { "keyId": [ { "$binary": { "base64": "AAAAAAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "bsonType": "string", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" } }, "encrypted_string_azure": { "encrypt": { "keyId": [ { "$binary": { "base64": "AZURE+AAAAAAAAAAAAAAAA==", "subType": "04" } } ], "bsonType": "string", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" } }, "encrypted_string_gcp": { "encrypt": { "keyId": [ { "$binary": { "base64": "GCP+AAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "bsonType": "string", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" } }, "encrypted_string_local": { "encrypt": { "keyId": [ { "$binary": { "base64": "AAAAAAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "bsonType": "string", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" } }, "encrypted_string_kmip": { "encrypt": { "keyId": [ { "$binary": { "base64": "dBHpr8aITfeBQ15grpbLpQ==", "subType": "04" } } ], "bsonType": "string", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" } } }, "bsonType": "object" }, "key_vault_data": [ { "_id": { "$binary": { "base64": "AZURE+AAAAAAAAAAAAAAAA==", "subType": "04" } }, "keyMaterial": { "$binary": { "base64": "n+HWZ0ZSVOYA3cvQgP7inN4JSXfOH85IngmeQxRpQHjCCcqT3IFqEWNlrsVHiz3AELimHhX4HKqOLWMUeSIT6emUDDoQX9BAv8DR1+E1w4nGs/NyEneac78EYFkK3JysrFDOgl2ypCCTKAypkn9CkAx1if4cfgQE93LW4kczcyHdGiH36CIxrCDGv1UzAvERN5Qa47DVwsM6a+hWsF2AAAJVnF0wYLLJU07TuRHdMrrphPWXZsFgyV+lRqJ7DDpReKNO8nMPLV/mHqHBHGPGQiRdb9NoJo8CvokGz4+KE8oLwzKf6V24dtwZmRkrsDV4iOhvROAzz+Euo1ypSkL3mw==", "subType": "00" } }, "creationDate": { "$date": { "$numberLong": "1601573901680" } }, "updateDate": { "$date": { "$numberLong": "1601573901680" } }, "status": { "$numberInt": "0" }, "masterKey": { "provider": "azure", "keyVaultEndpoint": "key-vault-csfle.vault.azure.net", "keyName": "key-name-csfle" }, "keyAltNames": [ "altname", "azure_altname" ] } ], "tests": [ { "description": "Insert a document with auto encryption using Azure KMS provider", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "azure": {} } } }, "operations": [ { "name": "insertOne", "arguments": { "document": { "_id": 1, "encrypted_string_azure": "string0" } } } ], "expectations": [ { "command_started_event": { "command": { "listCollections": 1, "filter": { "name": "default" } }, "command_name": "listCollections" } }, { "command_started_event": { "command": { "find": "datakeys", "filter": { "$or": [ { "_id": { "$in": [ { "$binary": { "base64": "AZURE+AAAAAAAAAAAAAAAA==", "subType": "04" } } ] } }, { "keyAltNames": { "$in": [] } } ] }, "$db": "keyvault" }, "command_name": "find" } }, { "command_started_event": { "command": { "insert": "default", "documents": [ { "_id": 1, "encrypted_string_azure": { "$binary": { "base64": "AQGVERPgAAAAAAAAAAAAAAAC5DbBSwPwfSlBrDtRuglvNvCXD1KzDuCKY2P+4bRFtHDjpTOE2XuytPAUaAbXf1orsPq59PVZmsbTZbt2CB8qaQ==", "subType": "06" } } } ], "ordered": true }, "command_name": "insert" } } ], "outcome": { "collection": { "data": [ { "_id": 1, "encrypted_string_azure": { "$binary": { "base64": "AQGVERPgAAAAAAAAAAAAAAAC5DbBSwPwfSlBrDtRuglvNvCXD1KzDuCKY2P+4bRFtHDjpTOE2XuytPAUaAbXf1orsPq59PVZmsbTZbt2CB8qaQ==", "subType": "06" } } } ] } } } ] } mongodb-mongo-python-driver-509e9b7/test/client-side-encryption/spec/legacy/badQueries.json000066400000000000000000001021661462766011000321670ustar00rootroot00000000000000{ "runOn": [ { "minServerVersion": "4.1.10" } ], "database_name": "default", "collection_name": "default", "data": [ { "_id": 1, "encrypted_string": { "$binary": { "base64": "AQAAAAAAAAAAAAAAAAAAAAACwj+3zkv2VM+aTfk60RqhXq6a/77WlLwu/BxXFkL7EppGsju/m8f0x5kBDD3EZTtGALGXlym5jnpZAoSIkswHoA==", "subType": "06" } } }, { "_id": 2, "encrypted_string": { "$binary": { "base64": "AQAAAAAAAAAAAAAAAAAAAAACDdw4KFz3ZLquhsbt7RmDjD0N67n0uSXx7IGnQNCLeIKvot6s/ouI21Eo84IOtb6lhwUNPlSEBNY0/hbszWAKJg==", "subType": "06" } } } ], "json_schema": { "properties": { "encrypted_w_altname": { "encrypt": { "keyId": "/altname", "bsonType": "string", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Random" } }, "encrypted_string": { "encrypt": { "keyId": [ { "$binary": { "base64": "AAAAAAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "bsonType": "string", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" } }, "random": { "encrypt": { "keyId": [ { "$binary": { "base64": "AAAAAAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "bsonType": "string", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Random" } }, "encrypted_string_equivalent": { "encrypt": { "keyId": [ { "$binary": { "base64": "AAAAAAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "bsonType": "string", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" } } }, "bsonType": "object" }, "key_vault_data": [ { "status": 1, "_id": { "$binary": { "base64": "AAAAAAAAAAAAAAAAAAAAAA==", "subType": "04" } }, "masterKey": { "provider": "aws", "key": "arn:aws:kms:us-east-1:579766882180:key/89fcc2c4-08b0-4bd9-9f25-e30687b580d0", "region": "us-east-1" }, "updateDate": { "$date": { "$numberLong": "1552949630483" } }, "keyMaterial": { "$binary": { "base64": "AQICAHhQNmWG2CzOm1dq3kWLM+iDUZhEqnhJwH9wZVpuZ94A8gEqnsxXlR51T5EbEVezUqqKAAAAwjCBvwYJKoZIhvcNAQcGoIGxMIGuAgEAMIGoBgkqhkiG9w0BBwEwHgYJYIZIAWUDBAEuMBEEDHa4jo6yp0Z18KgbUgIBEIB74sKxWtV8/YHje5lv5THTl0HIbhSwM6EqRlmBiFFatmEWaeMk4tO4xBX65eq670I5TWPSLMzpp8ncGHMmvHqRajNBnmFtbYxN3E3/WjxmdbOOe+OXpnGJPcGsftc7cB2shRfA4lICPnE26+oVNXT6p0Lo20nY5XC7jyCO", "subType": "00" } }, "creationDate": { "$date": { "$numberLong": "1552949630483" } }, "keyAltNames": [ "altname", "another_altname" ] } ], "tests": [ { "description": "$text unconditionally fails", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "aws": {} } } }, "operations": [ { "name": "find", "arguments": { "filter": { "$text": { "$search": "search text" } } }, "result": { "errorContains": "Unsupported match expression operator for encryption" } } ] }, { "description": "$where unconditionally fails", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "aws": {} } } }, "operations": [ { "name": "find", "arguments": { "filter": { "$where": { "$code": "function() { return true }" } } }, "result": { "errorContains": "Unsupported match expression operator for encryption" } } ] }, { "description": "$bit operators succeed on unencrypted, error on encrypted", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "aws": {} } } }, "operations": [ { "name": "find", "arguments": { "filter": { "unencrypted": { "$bitsAllClear": 35 } } }, "result": [] }, { "name": "find", "arguments": { "filter": { "encrypted_string": { "$bitsAllClear": 35 } } }, "result": { "errorContains": "Invalid match expression operator on encrypted field" } }, { "name": "find", "arguments": { "filter": { "unencrypted": { "$bitsAllSet": 35 } } }, "result": [] }, { "name": "find", "arguments": { "filter": { "encrypted_string": { "$bitsAllSet": 35 } } }, "result": { "errorContains": "Invalid match expression operator on encrypted field" } }, { "name": "find", "arguments": { "filter": { "unencrypted": { "$bitsAnyClear": 35 } } }, "result": [] }, { "name": "find", "arguments": { "filter": { "encrypted_string": { "$bitsAnyClear": 35 } } }, "result": { "errorContains": "Invalid match expression operator on encrypted field" } }, { "name": "find", "arguments": { "filter": { "unencrypted": { "$bitsAnySet": 35 } } }, "result": [] }, { "name": "find", "arguments": { "filter": { "encrypted_string": { "$bitsAnySet": 35 } } }, "result": { "errorContains": "Invalid match expression operator on encrypted field" } } ] }, { "description": "geo operators succeed on unencrypted, error on encrypted", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "aws": {} } } }, "operations": [ { "name": "find", "arguments": { "filter": { "unencrypted": { "$near": [ 0, 0 ] } } }, "result": { "errorContains": "unable to find index" } }, { "name": "find", "arguments": { "filter": { "encrypted_string": { "$near": [ 0, 0 ] } } }, "result": { "errorContains": "Invalid match expression operator on encrypted field" } }, { "name": "find", "arguments": { "filter": { "unencrypted": { "$nearSphere": [ 0, 0 ] } } }, "result": { "errorContains": "unable to find index" } }, { "name": "find", "arguments": { "filter": { "encrypted_string": { "$nearSphere": [ 0, 0 ] } } }, "result": { "errorContains": "Invalid match expression operator on encrypted field" } }, { "name": "find", "arguments": { "filter": { "unencrypted": { "$geoIntersects": { "$geometry": { "type": "Polygon", "coordinates": [ [ [ 0, 0 ], [ 1, 0 ], [ 1, 1 ], [ 0, 0 ] ] ] } } } } }, "result": [] }, { "name": "find", "arguments": { "filter": { "encrypted_string": { "$geoIntersects": { "$geometry": { "type": "Polygon", "coordinates": [ [ [ 0, 0 ], [ 1, 0 ], [ 1, 1 ], [ 0, 0 ] ] ] } } } } }, "result": { "errorContains": "Invalid match expression operator on encrypted field" } }, { "name": "find", "arguments": { "filter": { "unencrypted": { "$geoWithin": { "$geometry": { "type": "Polygon", "coordinates": [ [ [ 0, 0 ], [ 1, 0 ], [ 1, 1 ], [ 0, 0 ] ] ] } } } } }, "result": [] }, { "name": "find", "arguments": { "filter": { "encrypted_string": { "$geoWithin": { "$geometry": { "type": "Polygon", "coordinates": [ [ [ 0, 0 ], [ 1, 0 ], [ 1, 1 ], [ 0, 0 ] ] ] } } } } }, "result": { "errorContains": "Invalid match expression operator on encrypted field" } } ] }, { "description": "inequality operators succeed on unencrypted, error on encrypted", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "aws": {} } } }, "operations": [ { "name": "find", "arguments": { "filter": { "unencrypted": { "$gt": 1 } } }, "result": [] }, { "name": "find", "arguments": { "filter": { "encrypted_string": { "$gt": 1 } } }, "result": { "errorContains": "Invalid match expression operator on encrypted field" } }, { "name": "find", "arguments": { "filter": { "unencrypted": { "$lt": 1 } } }, "result": [] }, { "name": "find", "arguments": { "filter": { "encrypted_string": { "$lt": 1 } } }, "result": { "errorContains": "Invalid match expression operator on encrypted field" } }, { "name": "find", "arguments": { "filter": { "unencrypted": { "$gte": 1 } } }, "result": [] }, { "name": "find", "arguments": { "filter": { "encrypted_string": { "$gte": 1 } } }, "result": { "errorContains": "Invalid match expression operator on encrypted field" } }, { "name": "find", "arguments": { "filter": { "unencrypted": { "$lte": 1 } } }, "result": [] }, { "name": "find", "arguments": { "filter": { "encrypted_string": { "$lte": 1 } } }, "result": { "errorContains": "Invalid match expression operator on encrypted field" } } ] }, { "description": "other misc operators succeed on unencrypted, error on encrypted", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "aws": {} } } }, "operations": [ { "name": "find", "arguments": { "filter": { "unencrypted": { "$mod": [ 3, 1 ] } } }, "result": [] }, { "name": "find", "arguments": { "filter": { "encrypted_string": { "$mod": [ 3, 1 ] } } }, "result": { "errorContains": "Invalid match expression operator on encrypted field" } }, { "name": "find", "arguments": { "filter": { "unencrypted": { "$regex": "pattern", "$options": "" } } }, "result": [] }, { "name": "find", "arguments": { "filter": { "encrypted_string": { "$regex": "pattern", "$options": "" } } }, "result": { "errorContains": "Invalid match expression operator on encrypted field" } }, { "name": "find", "arguments": { "filter": { "unencrypted": { "$size": 2 } } }, "result": [] }, { "name": "find", "arguments": { "filter": { "encrypted_string": { "$size": 2 } } }, "result": { "errorContains": "Invalid match expression operator on encrypted field" } }, { "name": "find", "arguments": { "filter": { "unencrypted": { "$type": 2 } } }, "result": [] }, { "name": "find", "arguments": { "filter": { "encrypted_string": { "$type": 2 } } }, "result": { "errorContains": "Invalid match expression operator on encrypted field" } }, { "name": "find", "arguments": { "filter": { "unencrypted": { "$eq": null } } }, "result": [ { "_id": 1, "encrypted_string": "string0" }, { "_id": 2, "encrypted_string": "string1" } ] }, { "name": "find", "arguments": { "filter": { "encrypted_string": { "$eq": null } } }, "result": { "errorContains": "Illegal equality to null predicate for encrypted field" } }, { "name": "find", "arguments": { "filter": { "unencrypted": { "$in": [ null ] } } }, "result": [ { "_id": 1, "encrypted_string": "string0" }, { "_id": 2, "encrypted_string": "string1" } ] }, { "name": "find", "arguments": { "filter": { "encrypted_string": { "$in": [ null ] } } }, "result": { "errorContains": "Illegal equality to null inside $in against an encrypted field" } } ] }, { "description": "$addToSet succeeds on unencrypted, error on encrypted", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "aws": {} } } }, "operations": [ { "name": "updateOne", "arguments": { "filter": {}, "update": { "$addToSet": { "unencrypted": [ "a" ] } } }, "result": { "matchedCount": 1, "modifiedCount": 1, "upsertedCount": 0 } }, { "name": "updateOne", "arguments": { "filter": {}, "update": { "$addToSet": { "encrypted_string": [ "a" ] } } }, "result": { "errorContains": "$addToSet not allowed on encrypted values" } } ] }, { "description": "$inc succeeds on unencrypted, error on encrypted", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "aws": {} } } }, "operations": [ { "name": "updateOne", "arguments": { "filter": {}, "update": { "$inc": { "unencrypted": 1 } } }, "result": { "matchedCount": 1, "modifiedCount": 1, "upsertedCount": 0 } }, { "name": "updateOne", "arguments": { "filter": {}, "update": { "$inc": { "encrypted_string": 1 } } }, "result": { "errorContains": "$inc and $mul not allowed on encrypted values" } } ] }, { "description": "$mul succeeds on unencrypted, error on encrypted", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "aws": {} } } }, "operations": [ { "name": "updateOne", "arguments": { "filter": {}, "update": { "$mul": { "unencrypted": 1 } } }, "result": { "matchedCount": 1, "modifiedCount": 1, "upsertedCount": 0 } }, { "name": "updateOne", "arguments": { "filter": {}, "update": { "$mul": { "encrypted_string": 1 } } }, "result": { "errorContains": "$inc and $mul not allowed on encrypted values" } } ] }, { "description": "$max succeeds on unencrypted, error on encrypted", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "aws": {} } } }, "operations": [ { "name": "updateOne", "arguments": { "filter": {}, "update": { "$max": { "unencrypted": 1 } } }, "result": { "matchedCount": 1, "modifiedCount": 1, "upsertedCount": 0 } }, { "name": "updateOne", "arguments": { "filter": {}, "update": { "$max": { "encrypted_string": 1 } } }, "result": { "errorContains": "$max and $min not allowed on encrypted values" } } ] }, { "description": "$min succeeds on unencrypted, error on encrypted", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "aws": {} } } }, "operations": [ { "name": "updateOne", "arguments": { "filter": {}, "update": { "$min": { "unencrypted": 1 } } }, "result": { "matchedCount": 1, "modifiedCount": 1, "upsertedCount": 0 } }, { "name": "updateOne", "arguments": { "filter": {}, "update": { "$min": { "encrypted_string": 1 } } }, "result": { "errorContains": "$max and $min not allowed on encrypted values" } } ] }, { "description": "$currentDate succeeds on unencrypted, error on encrypted", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "aws": {} } } }, "operations": [ { "name": "updateOne", "arguments": { "filter": {}, "update": { "$currentDate": { "unencrypted": true } } }, "result": { "matchedCount": 1, "modifiedCount": 1, "upsertedCount": 0 } }, { "name": "updateOne", "arguments": { "filter": {}, "update": { "$currentDate": { "encrypted_string": true } } }, "result": { "errorContains": "$currentDate not allowed on encrypted values" } } ] }, { "description": "$pop succeeds on unencrypted, error on encrypted", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "aws": {} } } }, "operations": [ { "name": "updateOne", "arguments": { "filter": {}, "update": { "$pop": { "unencrypted": 1 } } }, "result": { "matchedCount": 1, "modifiedCount": 0, "upsertedCount": 0 } }, { "name": "updateOne", "arguments": { "filter": {}, "update": { "$pop": { "encrypted_string": 1 } } }, "result": { "errorContains": "$pop not allowed on encrypted values" } } ] }, { "description": "$pull succeeds on unencrypted, error on encrypted", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "aws": {} } } }, "operations": [ { "name": "updateOne", "arguments": { "filter": {}, "update": { "$pull": { "unencrypted": 1 } } }, "result": { "matchedCount": 1, "modifiedCount": 0, "upsertedCount": 0 } }, { "name": "updateOne", "arguments": { "filter": {}, "update": { "$pull": { "encrypted_string": 1 } } }, "result": { "errorContains": "$pull not allowed on encrypted values" } } ] }, { "description": "$pullAll succeeds on unencrypted, error on encrypted", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "aws": {} } } }, "operations": [ { "name": "updateOne", "arguments": { "filter": {}, "update": { "$pullAll": { "unencrypted": [ 1 ] } } }, "result": { "matchedCount": 1, "modifiedCount": 0, "upsertedCount": 0 } }, { "name": "updateOne", "arguments": { "filter": {}, "update": { "$pullAll": { "encrypted_string": [ 1 ] } } }, "result": { "errorContains": "$pullAll not allowed on encrypted values" } } ] }, { "description": "$push succeeds on unencrypted, error on encrypted", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "aws": {} } } }, "operations": [ { "name": "updateOne", "arguments": { "filter": {}, "update": { "$push": { "unencrypted": 1 } } }, "result": { "matchedCount": 1, "modifiedCount": 1, "upsertedCount": 0 } }, { "name": "updateOne", "arguments": { "filter": {}, "update": { "$push": { "encrypted_string": 1 } } }, "result": { "errorContains": "$push not allowed on encrypted values" } } ] }, { "description": "array filters on encrypted fields does not error in mongocryptd, but errors in mongod", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "aws": {} } } }, "operations": [ { "name": "updateOne", "arguments": { "filter": {}, "update": { "$set": { "encrypted_string.$[i].x": 1 } }, "arrayFilters": [ { "i.x": 1 } ] }, "result": { "errorContains": "Array update operations not allowed on encrypted values" } } ] }, { "description": "positional operator succeeds on unencrypted, errors on encrypted", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "aws": {} } } }, "operations": [ { "name": "updateOne", "arguments": { "filter": { "unencrypted": 1 }, "update": { "$set": { "unencrypted.$": 1 } } }, "result": { "matchedCount": 0, "modifiedCount": 0, "upsertedCount": 0 } }, { "name": "updateOne", "arguments": { "filter": { "encrypted_string": "abc" }, "update": { "$set": { "encrypted_string.$": "abc" } } }, "result": { "errorContains": "Cannot encrypt fields below '$' positional update operator" } } ] }, { "description": "an update that would produce an array on an encrypted field errors", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "aws": {} } } }, "operations": [ { "name": "updateOne", "arguments": { "filter": {}, "update": { "$set": { "encrypted_string": [ 1, 2 ] } } }, "result": { "errorContains": "Cannot encrypt element of type" } } ] }, { "description": "an insert with encrypted field on _id errors", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "aws": {} }, "schemaMap": { "default.default": { "properties": { "_id": { "encrypt": { "keyId": [ { "$binary": { "base64": "AAAAAAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "bsonType": "string", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" } } } } } } }, "operations": [ { "name": "insertOne", "arguments": { "document": { "_id": 1 } }, "result": { "errorContains": "Invalid schema containing the 'encrypt' keyword." } } ] }, { "description": "an insert with an array value for an encrypted field fails", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "aws": {} } } }, "operations": [ { "name": "insertOne", "arguments": { "document": { "encrypted_string": [ "123", "456" ] } }, "result": { "errorContains": "Cannot encrypt element of type" } } ] }, { "description": "an insert with a Timestamp(0,0) value in the top-level fails", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "aws": {} } } }, "operations": [ { "name": "insertOne", "arguments": { "document": { "random": { "$timestamp": { "t": 0, "i": 0 } } } }, "result": { "errorContains": "A command that inserts cannot supply Timestamp(0, 0) for an encrypted" } } ] }, { "description": "distinct with the key referring to a field where the keyID is a JSON Pointer errors", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "aws": {} } } }, "operations": [ { "name": "distinct", "arguments": { "filter": {}, "fieldName": "encrypted_w_altname" }, "result": { "errorContains": "The distinct key is not allowed to be marked for encryption with a non-UUID keyId" } } ] } ] } mongodb-mongo-python-driver-509e9b7/test/client-side-encryption/spec/legacy/badSchema.json000066400000000000000000000146321462766011000317520ustar00rootroot00000000000000{ "runOn": [ { "minServerVersion": "4.1.10" } ], "database_name": "default", "collection_name": "default", "data": [], "key_vault_data": [ { "status": 1, "_id": { "$binary": { "base64": "AAAAAAAAAAAAAAAAAAAAAA==", "subType": "04" } }, "masterKey": { "provider": "aws", "key": "arn:aws:kms:us-east-1:579766882180:key/89fcc2c4-08b0-4bd9-9f25-e30687b580d0", "region": "us-east-1" }, "updateDate": { "$date": { "$numberLong": "1552949630483" } }, "keyMaterial": { "$binary": { "base64": "AQICAHhQNmWG2CzOm1dq3kWLM+iDUZhEqnhJwH9wZVpuZ94A8gEqnsxXlR51T5EbEVezUqqKAAAAwjCBvwYJKoZIhvcNAQcGoIGxMIGuAgEAMIGoBgkqhkiG9w0BBwEwHgYJYIZIAWUDBAEuMBEEDHa4jo6yp0Z18KgbUgIBEIB74sKxWtV8/YHje5lv5THTl0HIbhSwM6EqRlmBiFFatmEWaeMk4tO4xBX65eq670I5TWPSLMzpp8ncGHMmvHqRajNBnmFtbYxN3E3/WjxmdbOOe+OXpnGJPcGsftc7cB2shRfA4lICPnE26+oVNXT6p0Lo20nY5XC7jyCO", "subType": "00" } }, "creationDate": { "$date": { "$numberLong": "1552949630483" } }, "keyAltNames": [ "altname", "another_altname" ] } ], "tests": [ { "description": "Schema with an encrypted field in an array", "clientOptions": { "autoEncryptOpts": { "schemaMap": { "default.default": { "properties": { "encrypted_string": { "encrypt": { "keyId": [ { "$binary": { "base64": "AAAAAAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "bsonType": "string", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Random" } } }, "bsonType": "array" } }, "kmsProviders": { "aws": {} } } }, "operations": [ { "name": "insertOne", "arguments": { "document": { "_id": 1, "encrypted_string": "string0" } }, "result": { "errorContains": "Invalid schema" } } ], "outcome": { "collection": { "data": [] } } }, { "description": "Schema without specifying parent object types", "clientOptions": { "autoEncryptOpts": { "schemaMap": { "default.default": { "properties": { "foo": { "properties": { "bar": { "encrypt": { "keyId": [ { "$binary": { "base64": "AAAAAAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "bsonType": "string", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Random" } } } } } } }, "kmsProviders": { "aws": {} } } }, "operations": [ { "name": "insertOne", "arguments": { "document": { "_id": 1, "encrypted_string": "string0" } }, "result": { "errorContains": "Invalid schema" } } ], "outcome": { "collection": { "data": [] } } }, { "description": "Schema with siblings of encrypt document", "clientOptions": { "autoEncryptOpts": { "schemaMap": { "default.default": { "properties": { "encrypted_string": { "encrypt": { "keyId": [ { "$binary": { "base64": "AAAAAAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "bsonType": "string", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Random" }, "bsonType": "object" } } } }, "kmsProviders": { "aws": {} } } }, "operations": [ { "name": "insertOne", "arguments": { "document": { "_id": 1, "encrypted_string": "string0" } }, "result": { "errorContains": "'encrypt' cannot be used in conjunction with 'bsonType'" } } ], "outcome": { "collection": { "data": [] } } }, { "description": "Schema with logical keywords", "clientOptions": { "autoEncryptOpts": { "schemaMap": { "default.default": { "anyOf": [ { "properties": { "encrypted_string": { "encrypt": { "keyId": [ { "$binary": { "base64": "AAAAAAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "bsonType": "string", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Random" } } } } ] } }, "kmsProviders": { "aws": {} } } }, "operations": [ { "name": "insertOne", "arguments": { "document": { "_id": 1, "encrypted_string": "string0" } }, "result": { "errorContains": "Invalid schema" } } ], "outcome": { "collection": { "data": [] } } } ] } mongodb-mongo-python-driver-509e9b7/test/client-side-encryption/spec/legacy/basic.json000066400000000000000000000205721462766011000311640ustar00rootroot00000000000000{ "runOn": [ { "minServerVersion": "4.1.10" } ], "database_name": "default", "collection_name": "default", "data": [], "json_schema": { "properties": { "encrypted_w_altname": { "encrypt": { "keyId": "/altname", "bsonType": "string", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Random" } }, "encrypted_string": { "encrypt": { "keyId": [ { "$binary": { "base64": "AAAAAAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "bsonType": "string", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" } }, "random": { "encrypt": { "keyId": [ { "$binary": { "base64": "AAAAAAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "bsonType": "string", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Random" } }, "encrypted_string_equivalent": { "encrypt": { "keyId": [ { "$binary": { "base64": "AAAAAAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "bsonType": "string", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" } } }, "bsonType": "object" }, "key_vault_data": [ { "status": 1, "_id": { "$binary": { "base64": "AAAAAAAAAAAAAAAAAAAAAA==", "subType": "04" } }, "masterKey": { "provider": "aws", "key": "arn:aws:kms:us-east-1:579766882180:key/89fcc2c4-08b0-4bd9-9f25-e30687b580d0", "region": "us-east-1" }, "updateDate": { "$date": { "$numberLong": "1552949630483" } }, "keyMaterial": { "$binary": { "base64": "AQICAHhQNmWG2CzOm1dq3kWLM+iDUZhEqnhJwH9wZVpuZ94A8gEqnsxXlR51T5EbEVezUqqKAAAAwjCBvwYJKoZIhvcNAQcGoIGxMIGuAgEAMIGoBgkqhkiG9w0BBwEwHgYJYIZIAWUDBAEuMBEEDHa4jo6yp0Z18KgbUgIBEIB74sKxWtV8/YHje5lv5THTl0HIbhSwM6EqRlmBiFFatmEWaeMk4tO4xBX65eq670I5TWPSLMzpp8ncGHMmvHqRajNBnmFtbYxN3E3/WjxmdbOOe+OXpnGJPcGsftc7cB2shRfA4lICPnE26+oVNXT6p0Lo20nY5XC7jyCO", "subType": "00" } }, "creationDate": { "$date": { "$numberLong": "1552949630483" } }, "keyAltNames": [ "altname", "another_altname" ] } ], "tests": [ { "description": "Insert with deterministic encryption, then find it", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "aws": {} } } }, "operations": [ { "name": "insertOne", "arguments": { "document": { "_id": 1, "encrypted_string": "string0" } } }, { "name": "find", "arguments": { "filter": { "_id": 1 } }, "result": [ { "_id": 1, "encrypted_string": "string0" } ] } ], "expectations": [ { "command_started_event": { "command": { "listCollections": 1, "filter": { "name": "default" } }, "command_name": "listCollections" } }, { "command_started_event": { "command": { "find": "datakeys", "filter": { "$or": [ { "_id": { "$in": [ { "$binary": { "base64": "AAAAAAAAAAAAAAAAAAAAAA==", "subType": "04" } } ] } }, { "keyAltNames": { "$in": [] } } ] }, "$db": "keyvault", "readConcern": { "level": "majority" } }, "command_name": "find" } }, { "command_started_event": { "command": { "insert": "default", "documents": [ { "_id": 1, "encrypted_string": { "$binary": { "base64": "AQAAAAAAAAAAAAAAAAAAAAACwj+3zkv2VM+aTfk60RqhXq6a/77WlLwu/BxXFkL7EppGsju/m8f0x5kBDD3EZTtGALGXlym5jnpZAoSIkswHoA==", "subType": "06" } } } ], "ordered": true }, "command_name": "insert" } }, { "command_started_event": { "command": { "find": "default", "filter": { "_id": 1 } }, "command_name": "find" } } ], "outcome": { "collection": { "data": [ { "_id": 1, "encrypted_string": { "$binary": { "base64": "AQAAAAAAAAAAAAAAAAAAAAACwj+3zkv2VM+aTfk60RqhXq6a/77WlLwu/BxXFkL7EppGsju/m8f0x5kBDD3EZTtGALGXlym5jnpZAoSIkswHoA==", "subType": "06" } } } ] } } }, { "description": "Insert with randomized encryption, then find it", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "aws": {} } } }, "operations": [ { "name": "insertOne", "arguments": { "document": { "_id": 1, "random": "123" } } }, { "name": "find", "arguments": { "filter": { "_id": 1 } }, "result": [ { "_id": 1, "random": "123" } ] } ], "expectations": [ { "command_started_event": { "command": { "listCollections": 1, "filter": { "name": "default" } }, "command_name": "listCollections" } }, { "command_started_event": { "command": { "find": "datakeys", "filter": { "$or": [ { "_id": { "$in": [ { "$binary": { "base64": "AAAAAAAAAAAAAAAAAAAAAA==", "subType": "04" } } ] } }, { "keyAltNames": { "$in": [] } } ] }, "$db": "keyvault", "readConcern": { "level": "majority" } }, "command_name": "find" } }, { "command_started_event": { "command": { "insert": "default", "documents": [ { "_id": 1, "random": { "$$type": "binData" } } ], "ordered": true }, "command_name": "insert" } }, { "command_started_event": { "command": { "find": "default", "filter": { "_id": 1 } }, "command_name": "find" } } ], "outcome": { "collection": { "data": [ { "_id": 1, "random": { "$$type": "binData" } } ] } } } ] } mongodb-mongo-python-driver-509e9b7/test/client-side-encryption/spec/legacy/bulk.json000066400000000000000000000220671462766011000310410ustar00rootroot00000000000000{ "runOn": [ { "minServerVersion": "4.1.10" } ], "database_name": "default", "collection_name": "default", "data": [], "json_schema": { "properties": { "encrypted_w_altname": { "encrypt": { "keyId": "/altname", "bsonType": "string", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Random" } }, "encrypted_string": { "encrypt": { "keyId": [ { "$binary": { "base64": "AAAAAAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "bsonType": "string", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" } }, "random": { "encrypt": { "keyId": [ { "$binary": { "base64": "AAAAAAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "bsonType": "string", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Random" } }, "encrypted_string_equivalent": { "encrypt": { "keyId": [ { "$binary": { "base64": "AAAAAAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "bsonType": "string", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" } } }, "bsonType": "object" }, "key_vault_data": [ { "status": 1, "_id": { "$binary": { "base64": "AAAAAAAAAAAAAAAAAAAAAA==", "subType": "04" } }, "masterKey": { "provider": "aws", "key": "arn:aws:kms:us-east-1:579766882180:key/89fcc2c4-08b0-4bd9-9f25-e30687b580d0", "region": "us-east-1" }, "updateDate": { "$date": { "$numberLong": "1552949630483" } }, "keyMaterial": { "$binary": { "base64": "AQICAHhQNmWG2CzOm1dq3kWLM+iDUZhEqnhJwH9wZVpuZ94A8gEqnsxXlR51T5EbEVezUqqKAAAAwjCBvwYJKoZIhvcNAQcGoIGxMIGuAgEAMIGoBgkqhkiG9w0BBwEwHgYJYIZIAWUDBAEuMBEEDHa4jo6yp0Z18KgbUgIBEIB74sKxWtV8/YHje5lv5THTl0HIbhSwM6EqRlmBiFFatmEWaeMk4tO4xBX65eq670I5TWPSLMzpp8ncGHMmvHqRajNBnmFtbYxN3E3/WjxmdbOOe+OXpnGJPcGsftc7cB2shRfA4lICPnE26+oVNXT6p0Lo20nY5XC7jyCO", "subType": "00" } }, "creationDate": { "$date": { "$numberLong": "1552949630483" } }, "keyAltNames": [ "altname", "another_altname" ] } ], "tests": [ { "description": "Bulk write with encryption", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "aws": {} } } }, "operations": [ { "name": "bulkWrite", "arguments": { "requests": [ { "name": "insertOne", "arguments": { "document": { "_id": 1, "encrypted_string": "string0", "random": "abc" } } }, { "name": "insertOne", "arguments": { "document": { "_id": 2, "encrypted_string": "string1" } } }, { "name": "updateOne", "arguments": { "filter": { "encrypted_string": "string0" }, "update": { "$set": { "encrypted_string": "string1" } } } }, { "name": "deleteOne", "arguments": { "filter": { "$and": [ { "encrypted_string": "string1" }, { "_id": 2 } ] } } } ], "options": { "ordered": true } } } ], "expectations": [ { "command_started_event": { "command": { "listCollections": 1, "filter": { "name": "default" } }, "command_name": "listCollections" } }, { "command_started_event": { "command": { "find": "datakeys", "filter": { "$or": [ { "_id": { "$in": [ { "$binary": { "base64": "AAAAAAAAAAAAAAAAAAAAAA==", "subType": "04" } } ] } }, { "keyAltNames": { "$in": [] } } ] }, "$db": "keyvault", "readConcern": { "level": "majority" } }, "command_name": "find" } }, { "command_started_event": { "command": { "insert": "default", "documents": [ { "_id": 1, "encrypted_string": { "$binary": { "base64": "AQAAAAAAAAAAAAAAAAAAAAACwj+3zkv2VM+aTfk60RqhXq6a/77WlLwu/BxXFkL7EppGsju/m8f0x5kBDD3EZTtGALGXlym5jnpZAoSIkswHoA==", "subType": "06" } }, "random": { "$$type": "binData" } }, { "_id": 2, "encrypted_string": { "$binary": { "base64": "AQAAAAAAAAAAAAAAAAAAAAACDdw4KFz3ZLquhsbt7RmDjD0N67n0uSXx7IGnQNCLeIKvot6s/ouI21Eo84IOtb6lhwUNPlSEBNY0/hbszWAKJg==", "subType": "06" } } } ], "ordered": true }, "command_name": "insert" } }, { "command_started_event": { "command": { "update": "default", "updates": [ { "q": { "encrypted_string": { "$eq": { "$binary": { "base64": "AQAAAAAAAAAAAAAAAAAAAAACwj+3zkv2VM+aTfk60RqhXq6a/77WlLwu/BxXFkL7EppGsju/m8f0x5kBDD3EZTtGALGXlym5jnpZAoSIkswHoA==", "subType": "06" } } } }, "u": { "$set": { "encrypted_string": { "$binary": { "base64": "AQAAAAAAAAAAAAAAAAAAAAACDdw4KFz3ZLquhsbt7RmDjD0N67n0uSXx7IGnQNCLeIKvot6s/ouI21Eo84IOtb6lhwUNPlSEBNY0/hbszWAKJg==", "subType": "06" } } } } } ], "ordered": true }, "command_name": "update" } }, { "command_started_event": { "command": { "delete": "default", "deletes": [ { "q": { "$and": [ { "encrypted_string": { "$eq": { "$binary": { "base64": "AQAAAAAAAAAAAAAAAAAAAAACDdw4KFz3ZLquhsbt7RmDjD0N67n0uSXx7IGnQNCLeIKvot6s/ouI21Eo84IOtb6lhwUNPlSEBNY0/hbszWAKJg==", "subType": "06" } } } }, { "_id": { "$eq": 2 } } ] }, "limit": 1 } ], "ordered": true }, "command_name": "delete" } } ], "outcome": { "collection": { "data": [ { "_id": 1, "encrypted_string": { "$binary": { "base64": "AQAAAAAAAAAAAAAAAAAAAAACDdw4KFz3ZLquhsbt7RmDjD0N67n0uSXx7IGnQNCLeIKvot6s/ouI21Eo84IOtb6lhwUNPlSEBNY0/hbszWAKJg==", "subType": "06" } }, "random": { "$$type": "binData" } } ] } } } ] } bypassAutoEncryption.json000066400000000000000000000244601462766011000342310ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/client-side-encryption/spec/legacy{ "runOn": [ { "minServerVersion": "4.1.10" } ], "database_name": "default", "collection_name": "default", "data": [ { "_id": 1, "encrypted_string": { "$binary": { "base64": "AQAAAAAAAAAAAAAAAAAAAAACwj+3zkv2VM+aTfk60RqhXq6a/77WlLwu/BxXFkL7EppGsju/m8f0x5kBDD3EZTtGALGXlym5jnpZAoSIkswHoA==", "subType": "06" } } } ], "json_schema": { "properties": { "encrypted_w_altname": { "encrypt": { "keyId": "/altname", "bsonType": "string", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Random" } }, "encrypted_string": { "encrypt": { "keyId": [ { "$binary": { "base64": "AAAAAAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "bsonType": "string", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" } }, "random": { "encrypt": { "keyId": [ { "$binary": { "base64": "AAAAAAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "bsonType": "string", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Random" } }, "encrypted_string_equivalent": { "encrypt": { "keyId": [ { "$binary": { "base64": "AAAAAAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "bsonType": "string", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" } } }, "bsonType": "object" }, "key_vault_data": [ { "status": 1, "_id": { "$binary": { "base64": "AAAAAAAAAAAAAAAAAAAAAA==", "subType": "04" } }, "masterKey": { "provider": "aws", "key": "arn:aws:kms:us-east-1:579766882180:key/89fcc2c4-08b0-4bd9-9f25-e30687b580d0", "region": "us-east-1" }, "updateDate": { "$date": { "$numberLong": "1552949630483" } }, "keyMaterial": { "$binary": { "base64": "AQICAHhQNmWG2CzOm1dq3kWLM+iDUZhEqnhJwH9wZVpuZ94A8gEqnsxXlR51T5EbEVezUqqKAAAAwjCBvwYJKoZIhvcNAQcGoIGxMIGuAgEAMIGoBgkqhkiG9w0BBwEwHgYJYIZIAWUDBAEuMBEEDHa4jo6yp0Z18KgbUgIBEIB74sKxWtV8/YHje5lv5THTl0HIbhSwM6EqRlmBiFFatmEWaeMk4tO4xBX65eq670I5TWPSLMzpp8ncGHMmvHqRajNBnmFtbYxN3E3/WjxmdbOOe+OXpnGJPcGsftc7cB2shRfA4lICPnE26+oVNXT6p0Lo20nY5XC7jyCO", "subType": "00" } }, "creationDate": { "$date": { "$numberLong": "1552949630483" } }, "keyAltNames": [ "altname", "another_altname" ] } ], "tests": [ { "description": "Insert with bypassAutoEncryption", "clientOptions": { "autoEncryptOpts": { "bypassAutoEncryption": true, "kmsProviders": { "aws": {} } } }, "operations": [ { "name": "insertOne", "arguments": { "document": { "_id": 2, "encrypted_string": "string0" }, "bypassDocumentValidation": true } }, { "name": "find", "arguments": { "filter": {} }, "result": [ { "_id": 1, "encrypted_string": "string0" }, { "_id": 2, "encrypted_string": "string0" } ] } ], "expectations": [ { "command_started_event": { "command": { "insert": "default", "documents": [ { "_id": 2, "encrypted_string": "string0" } ], "ordered": true }, "command_name": "insert" } }, { "command_started_event": { "command": { "find": "default", "filter": {} }, "command_name": "find" } }, { "command_started_event": { "command": { "find": "datakeys", "filter": { "$or": [ { "_id": { "$in": [ { "$binary": { "base64": "AAAAAAAAAAAAAAAAAAAAAA==", "subType": "04" } } ] } }, { "keyAltNames": { "$in": [] } } ] }, "$db": "keyvault", "readConcern": { "level": "majority" } }, "command_name": "find" } } ], "outcome": { "collection": { "data": [ { "_id": 1, "encrypted_string": { "$binary": { "base64": "AQAAAAAAAAAAAAAAAAAAAAACwj+3zkv2VM+aTfk60RqhXq6a/77WlLwu/BxXFkL7EppGsju/m8f0x5kBDD3EZTtGALGXlym5jnpZAoSIkswHoA==", "subType": "06" } } }, { "_id": 2, "encrypted_string": "string0" } ] } } }, { "description": "Insert with bypassAutoEncryption for local schema", "clientOptions": { "autoEncryptOpts": { "schemaMap": { "default.default": { "properties": { "encrypted_w_altname": { "encrypt": { "keyId": "/altname", "bsonType": "string", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Random" } }, "encrypted_string": { "encrypt": { "keyId": [ { "$binary": { "base64": "AAAAAAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "bsonType": "string", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" } }, "random": { "encrypt": { "keyId": [ { "$binary": { "base64": "AAAAAAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "bsonType": "string", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Random" } }, "encrypted_string_equivalent": { "encrypt": { "keyId": [ { "$binary": { "base64": "AAAAAAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "bsonType": "string", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" } } }, "bsonType": "object" } }, "bypassAutoEncryption": true, "kmsProviders": { "aws": {} } } }, "operations": [ { "name": "insertOne", "arguments": { "document": { "_id": 2, "encrypted_string": "string0" }, "bypassDocumentValidation": true } }, { "name": "find", "arguments": { "filter": {} }, "result": [ { "_id": 1, "encrypted_string": "string0" }, { "_id": 2, "encrypted_string": "string0" } ] } ], "expectations": [ { "command_started_event": { "command": { "insert": "default", "documents": [ { "_id": 2, "encrypted_string": "string0" } ], "ordered": true }, "command_name": "insert" } }, { "command_started_event": { "command": { "find": "default", "filter": {} }, "command_name": "find" } }, { "command_started_event": { "command": { "find": "datakeys", "filter": { "$or": [ { "_id": { "$in": [ { "$binary": { "base64": "AAAAAAAAAAAAAAAAAAAAAA==", "subType": "04" } } ] } }, { "keyAltNames": { "$in": [] } } ] }, "$db": "keyvault", "readConcern": { "level": "majority" } }, "command_name": "find" } } ], "outcome": { "collection": { "data": [ { "_id": 1, "encrypted_string": { "$binary": { "base64": "AQAAAAAAAAAAAAAAAAAAAAACwj+3zkv2VM+aTfk60RqhXq6a/77WlLwu/BxXFkL7EppGsju/m8f0x5kBDD3EZTtGALGXlym5jnpZAoSIkswHoA==", "subType": "06" } } }, { "_id": 2, "encrypted_string": "string0" } ] } } } ] } mongodb-mongo-python-driver-509e9b7/test/client-side-encryption/spec/legacy/bypassedCommand.json000066400000000000000000000047131462766011000332130ustar00rootroot00000000000000{ "runOn": [ { "minServerVersion": "4.1.10" } ], "database_name": "default", "collection_name": "default", "data": [], "json_schema": {}, "key_vault_data": [ { "status": 1, "_id": { "$binary": { "base64": "AAAAAAAAAAAAAAAAAAAAAA==", "subType": "04" } }, "masterKey": { "provider": "aws", "key": "arn:aws:kms:us-east-1:579766882180:key/89fcc2c4-08b0-4bd9-9f25-e30687b580d0", "region": "us-east-1" }, "updateDate": { "$date": { "$numberLong": "1552949630483" } }, "keyMaterial": { "$binary": { "base64": "AQICAHhQNmWG2CzOm1dq3kWLM+iDUZhEqnhJwH9wZVpuZ94A8gEqnsxXlR51T5EbEVezUqqKAAAAwjCBvwYJKoZIhvcNAQcGoIGxMIGuAgEAMIGoBgkqhkiG9w0BBwEwHgYJYIZIAWUDBAEuMBEEDHa4jo6yp0Z18KgbUgIBEIB74sKxWtV8/YHje5lv5THTl0HIbhSwM6EqRlmBiFFatmEWaeMk4tO4xBX65eq670I5TWPSLMzpp8ncGHMmvHqRajNBnmFtbYxN3E3/WjxmdbOOe+OXpnGJPcGsftc7cB2shRfA4lICPnE26+oVNXT6p0Lo20nY5XC7jyCO", "subType": "00" } }, "creationDate": { "$date": { "$numberLong": "1552949630483" } }, "keyAltNames": [ "altname", "another_altname" ] } ], "tests": [ { "description": "ping is bypassed", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "aws": {} } } }, "operations": [ { "name": "runCommand", "object": "database", "command_name": "ping", "arguments": { "command": { "ping": 1 } } } ], "expectations": [ { "command_started_event": { "command": { "ping": 1 }, "command_name": "ping" } } ] }, { "description": "kill op is not bypassed", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "aws": {} } } }, "operations": [ { "name": "runCommand", "object": "database", "command_name": "killOp", "arguments": { "command": { "killOp": 1, "op": 1234 } }, "result": { "errorContains": "command not supported for auto encryption: killOp" } } ] } ] } mongodb-mongo-python-driver-509e9b7/test/client-side-encryption/spec/legacy/count.json000066400000000000000000000133201462766011000312240ustar00rootroot00000000000000{ "runOn": [ { "minServerVersion": "4.1.10" } ], "database_name": "default", "collection_name": "default", "data": [ { "_id": 1, "encrypted_string": { "$binary": { "base64": "AQAAAAAAAAAAAAAAAAAAAAACwj+3zkv2VM+aTfk60RqhXq6a/77WlLwu/BxXFkL7EppGsju/m8f0x5kBDD3EZTtGALGXlym5jnpZAoSIkswHoA==", "subType": "06" } } }, { "_id": 2, "encrypted_string": { "$binary": { "base64": "AQAAAAAAAAAAAAAAAAAAAAACwj+3zkv2VM+aTfk60RqhXq6a/77WlLwu/BxXFkL7EppGsju/m8f0x5kBDD3EZTtGALGXlym5jnpZAoSIkswHoA==", "subType": "06" } } } ], "json_schema": { "properties": { "encrypted_w_altname": { "encrypt": { "keyId": "/altname", "bsonType": "string", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Random" } }, "encrypted_string": { "encrypt": { "keyId": [ { "$binary": { "base64": "AAAAAAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "bsonType": "string", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" } }, "random": { "encrypt": { "keyId": [ { "$binary": { "base64": "AAAAAAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "bsonType": "string", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Random" } }, "encrypted_string_equivalent": { "encrypt": { "keyId": [ { "$binary": { "base64": "AAAAAAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "bsonType": "string", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" } } }, "bsonType": "object" }, "key_vault_data": [ { "status": 1, "_id": { "$binary": { "base64": "AAAAAAAAAAAAAAAAAAAAAA==", "subType": "04" } }, "masterKey": { "provider": "aws", "key": "arn:aws:kms:us-east-1:579766882180:key/89fcc2c4-08b0-4bd9-9f25-e30687b580d0", "region": "us-east-1" }, "updateDate": { "$date": { "$numberLong": "1552949630483" } }, "keyMaterial": { "$binary": { "base64": "AQICAHhQNmWG2CzOm1dq3kWLM+iDUZhEqnhJwH9wZVpuZ94A8gEqnsxXlR51T5EbEVezUqqKAAAAwjCBvwYJKoZIhvcNAQcGoIGxMIGuAgEAMIGoBgkqhkiG9w0BBwEwHgYJYIZIAWUDBAEuMBEEDHa4jo6yp0Z18KgbUgIBEIB74sKxWtV8/YHje5lv5THTl0HIbhSwM6EqRlmBiFFatmEWaeMk4tO4xBX65eq670I5TWPSLMzpp8ncGHMmvHqRajNBnmFtbYxN3E3/WjxmdbOOe+OXpnGJPcGsftc7cB2shRfA4lICPnE26+oVNXT6p0Lo20nY5XC7jyCO", "subType": "00" } }, "creationDate": { "$date": { "$numberLong": "1552949630483" } }, "keyAltNames": [ "altname", "another_altname" ] } ], "tests": [ { "description": "Count with deterministic encryption", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "aws": {} } } }, "operations": [ { "name": "count", "arguments": { "filter": { "encrypted_string": "string0" } }, "result": 2 } ], "expectations": [ { "command_started_event": { "command": { "listCollections": 1, "filter": { "name": "default" } }, "command_name": "listCollections" } }, { "command_started_event": { "command": { "find": "datakeys", "filter": { "$or": [ { "_id": { "$in": [ { "$binary": { "base64": "AAAAAAAAAAAAAAAAAAAAAA==", "subType": "04" } } ] } }, { "keyAltNames": { "$in": [] } } ] }, "$db": "keyvault", "readConcern": { "level": "majority" } }, "command_name": "find" } }, { "command_started_event": { "command": { "count": "default", "query": { "encrypted_string": { "$eq": { "$binary": { "base64": "AQAAAAAAAAAAAAAAAAAAAAACwj+3zkv2VM+aTfk60RqhXq6a/77WlLwu/BxXFkL7EppGsju/m8f0x5kBDD3EZTtGALGXlym5jnpZAoSIkswHoA==", "subType": "06" } } } } }, "command_name": "count" } } ] }, { "description": "Count fails when filtering on a random encrypted field", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "aws": {} } } }, "operations": [ { "name": "count", "arguments": { "filter": { "random": "abc" } }, "result": { "errorContains": "Cannot query on fields encrypted with the randomized encryption" } } ] } ] } mongodb-mongo-python-driver-509e9b7/test/client-side-encryption/spec/legacy/countDocuments.json000066400000000000000000000143571462766011000331210ustar00rootroot00000000000000{ "runOn": [ { "minServerVersion": "4.1.10" } ], "database_name": "default", "collection_name": "default", "data": [ { "_id": 1, "encrypted_string": { "$binary": { "base64": "AQAAAAAAAAAAAAAAAAAAAAACwj+3zkv2VM+aTfk60RqhXq6a/77WlLwu/BxXFkL7EppGsju/m8f0x5kBDD3EZTtGALGXlym5jnpZAoSIkswHoA==", "subType": "06" } } }, { "_id": 2, "encrypted_string": { "$binary": { "base64": "AQAAAAAAAAAAAAAAAAAAAAACDdw4KFz3ZLquhsbt7RmDjD0N67n0uSXx7IGnQNCLeIKvot6s/ouI21Eo84IOtb6lhwUNPlSEBNY0/hbszWAKJg==", "subType": "06" } } } ], "json_schema": { "properties": { "encrypted_w_altname": { "encrypt": { "keyId": "/altname", "bsonType": "string", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Random" } }, "encrypted_string": { "encrypt": { "keyId": [ { "$binary": { "base64": "AAAAAAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "bsonType": "string", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" } }, "random": { "encrypt": { "keyId": [ { "$binary": { "base64": "AAAAAAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "bsonType": "string", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Random" } }, "encrypted_string_equivalent": { "encrypt": { "keyId": [ { "$binary": { "base64": "AAAAAAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "bsonType": "string", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" } } }, "bsonType": "object" }, "key_vault_data": [ { "status": 1, "_id": { "$binary": { "base64": "AAAAAAAAAAAAAAAAAAAAAA==", "subType": "04" } }, "masterKey": { "provider": "aws", "key": "arn:aws:kms:us-east-1:579766882180:key/89fcc2c4-08b0-4bd9-9f25-e30687b580d0", "region": "us-east-1" }, "updateDate": { "$date": { "$numberLong": "1552949630483" } }, "keyMaterial": { "$binary": { "base64": "AQICAHhQNmWG2CzOm1dq3kWLM+iDUZhEqnhJwH9wZVpuZ94A8gEqnsxXlR51T5EbEVezUqqKAAAAwjCBvwYJKoZIhvcNAQcGoIGxMIGuAgEAMIGoBgkqhkiG9w0BBwEwHgYJYIZIAWUDBAEuMBEEDHa4jo6yp0Z18KgbUgIBEIB74sKxWtV8/YHje5lv5THTl0HIbhSwM6EqRlmBiFFatmEWaeMk4tO4xBX65eq670I5TWPSLMzpp8ncGHMmvHqRajNBnmFtbYxN3E3/WjxmdbOOe+OXpnGJPcGsftc7cB2shRfA4lICPnE26+oVNXT6p0Lo20nY5XC7jyCO", "subType": "00" } }, "creationDate": { "$date": { "$numberLong": "1552949630483" } }, "keyAltNames": [ "altname", "another_altname" ] } ], "tests": [ { "description": "countDocuments with deterministic encryption", "skipReason": "waiting on SERVER-39395", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "aws": {} } } }, "operations": [ { "name": "countDocuments", "arguments": { "filter": { "encrypted_string": "string0" } }, "result": 1 } ], "expectations": [ { "command_started_event": { "command": { "listCollections": 1, "filter": { "name": "default" } }, "command_name": "listCollections" } }, { "command_started_event": { "command": { "find": "datakeys", "filter": { "$or": [ { "_id": { "$in": [ { "$binary": { "base64": "AAAAAAAAAAAAAAAAAAAAAA==", "subType": "04" } } ] } }, { "keyAltNames": { "$in": [] } } ] }, "$db": "keyvault", "readConcern": { "level": "majority" } }, "command_name": "find" } }, { "command_started_event": { "command": { "aggregate": "default", "pipeline": [ { "$match": { "encrypted_string": { "$binary": { "base64": "AQAAAAAAAAAAAAAAAAAAAAACwj+3zkv2VM+aTfk60RqhXq6a/77WlLwu/BxXFkL7EppGsju/m8f0x5kBDD3EZTtGALGXlym5jnpZAoSIkswHoA==", "subType": "06" } } } }, { "$group": { "_id": 1, "n": { "$sum": 1 } } } ] }, "command_name": "aggregate" } } ], "outcome": { "collection": { "data": [ { "_id": 1, "encrypted_string": { "$binary": { "base64": "AQAAAAAAAAAAAAAAAAAAAAACwj+3zkv2VM+aTfk60RqhXq6a/77WlLwu/BxXFkL7EppGsju/m8f0x5kBDD3EZTtGALGXlym5jnpZAoSIkswHoA==", "subType": "06" } } }, { "_id": 2, "encrypted_string": { "$binary": { "base64": "AQAAAAAAAAAAAAAAAAAAAAACDdw4KFz3ZLquhsbt7RmDjD0N67n0uSXx7IGnQNCLeIKvot6s/ouI21Eo84IOtb6lhwUNPlSEBNY0/hbszWAKJg==", "subType": "06" } } } ] } } } ] } create-and-createIndexes.json000066400000000000000000000054431462766011000346100ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/client-side-encryption/spec/legacy{ "runOn": [ { "minServerVersion": "4.1.10" } ], "database_name": "default", "collection_name": "default", "data": [], "tests": [ { "description": "create is OK", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "local": { "key": { "$binary": { "base64": "Mng0NCt4ZHVUYUJCa1kxNkVyNUR1QURhZ2h2UzR2d2RrZzh0cFBwM3R6NmdWMDFBMUN3YkQ5aXRRMkhGRGdQV09wOGVNYUMxT2k3NjZKelhaQmRCZGJkTXVyZG9uSjFk", "subType": "00" } } } } } }, "operations": [ { "name": "dropCollection", "object": "database", "arguments": { "collection": "unencryptedCollection" } }, { "name": "createCollection", "object": "database", "arguments": { "collection": "unencryptedCollection", "validator": { "unencrypted_string": "foo" } } }, { "name": "assertCollectionExists", "object": "testRunner", "arguments": { "database": "default", "collection": "unencryptedCollection" } } ] }, { "description": "createIndexes is OK", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "local": { "key": { "$binary": { "base64": "Mng0NCt4ZHVUYUJCa1kxNkVyNUR1QURhZ2h2UzR2d2RrZzh0cFBwM3R6NmdWMDFBMUN3YkQ5aXRRMkhGRGdQV09wOGVNYUMxT2k3NjZKelhaQmRCZGJkTXVyZG9uSjFk", "subType": "00" } } } } } }, "operations": [ { "name": "dropCollection", "object": "database", "arguments": { "collection": "unencryptedCollection" } }, { "name": "createCollection", "object": "database", "arguments": { "collection": "unencryptedCollection" } }, { "name": "runCommand", "object": "database", "arguments": { "command": { "createIndexes": "unencryptedCollection", "indexes": [ { "name": "name", "key": { "name": 1 } } ] } } }, { "name": "assertIndexExists", "object": "testRunner", "arguments": { "database": "default", "collection": "unencryptedCollection", "index": "name" } } ] } ] } mongodb-mongo-python-driver-509e9b7/test/client-side-encryption/spec/legacy/delete.json000066400000000000000000000213431462766011000313420ustar00rootroot00000000000000{ "runOn": [ { "minServerVersion": "4.1.10" } ], "database_name": "default", "collection_name": "default", "data": [ { "_id": 1, "encrypted_string": { "$binary": { "base64": "AQAAAAAAAAAAAAAAAAAAAAACwj+3zkv2VM+aTfk60RqhXq6a/77WlLwu/BxXFkL7EppGsju/m8f0x5kBDD3EZTtGALGXlym5jnpZAoSIkswHoA==", "subType": "06" } } }, { "_id": 2, "encrypted_string": { "$binary": { "base64": "AQAAAAAAAAAAAAAAAAAAAAACDdw4KFz3ZLquhsbt7RmDjD0N67n0uSXx7IGnQNCLeIKvot6s/ouI21Eo84IOtb6lhwUNPlSEBNY0/hbszWAKJg==", "subType": "06" } } } ], "json_schema": { "properties": { "encrypted_w_altname": { "encrypt": { "keyId": "/altname", "bsonType": "string", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Random" } }, "encrypted_string": { "encrypt": { "keyId": [ { "$binary": { "base64": "AAAAAAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "bsonType": "string", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" } }, "random": { "encrypt": { "keyId": [ { "$binary": { "base64": "AAAAAAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "bsonType": "string", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Random" } }, "encrypted_string_equivalent": { "encrypt": { "keyId": [ { "$binary": { "base64": "AAAAAAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "bsonType": "string", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" } } }, "bsonType": "object" }, "key_vault_data": [ { "status": 1, "_id": { "$binary": { "base64": "AAAAAAAAAAAAAAAAAAAAAA==", "subType": "04" } }, "masterKey": { "provider": "aws", "key": "arn:aws:kms:us-east-1:579766882180:key/89fcc2c4-08b0-4bd9-9f25-e30687b580d0", "region": "us-east-1" }, "updateDate": { "$date": { "$numberLong": "1552949630483" } }, "keyMaterial": { "$binary": { "base64": "AQICAHhQNmWG2CzOm1dq3kWLM+iDUZhEqnhJwH9wZVpuZ94A8gEqnsxXlR51T5EbEVezUqqKAAAAwjCBvwYJKoZIhvcNAQcGoIGxMIGuAgEAMIGoBgkqhkiG9w0BBwEwHgYJYIZIAWUDBAEuMBEEDHa4jo6yp0Z18KgbUgIBEIB74sKxWtV8/YHje5lv5THTl0HIbhSwM6EqRlmBiFFatmEWaeMk4tO4xBX65eq670I5TWPSLMzpp8ncGHMmvHqRajNBnmFtbYxN3E3/WjxmdbOOe+OXpnGJPcGsftc7cB2shRfA4lICPnE26+oVNXT6p0Lo20nY5XC7jyCO", "subType": "00" } }, "creationDate": { "$date": { "$numberLong": "1552949630483" } }, "keyAltNames": [ "altname", "another_altname" ] } ], "tests": [ { "description": "deleteOne with deterministic encryption", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "aws": {} } } }, "operations": [ { "name": "deleteOne", "arguments": { "filter": { "encrypted_string": "string0" } }, "result": { "deletedCount": 1 } } ], "expectations": [ { "command_started_event": { "command": { "listCollections": 1, "filter": { "name": "default" } }, "command_name": "listCollections" } }, { "command_started_event": { "command": { "find": "datakeys", "filter": { "$or": [ { "_id": { "$in": [ { "$binary": { "base64": "AAAAAAAAAAAAAAAAAAAAAA==", "subType": "04" } } ] } }, { "keyAltNames": { "$in": [] } } ] }, "$db": "keyvault", "readConcern": { "level": "majority" } }, "command_name": "find" } }, { "command_started_event": { "command": { "delete": "default", "deletes": [ { "q": { "encrypted_string": { "$eq": { "$binary": { "base64": "AQAAAAAAAAAAAAAAAAAAAAACwj+3zkv2VM+aTfk60RqhXq6a/77WlLwu/BxXFkL7EppGsju/m8f0x5kBDD3EZTtGALGXlym5jnpZAoSIkswHoA==", "subType": "06" } } } }, "limit": 1 } ], "ordered": true }, "command_name": "delete" } } ], "outcome": { "collection": { "data": [ { "_id": 2, "encrypted_string": { "$binary": { "base64": "AQAAAAAAAAAAAAAAAAAAAAACDdw4KFz3ZLquhsbt7RmDjD0N67n0uSXx7IGnQNCLeIKvot6s/ouI21Eo84IOtb6lhwUNPlSEBNY0/hbszWAKJg==", "subType": "06" } } } ] } } }, { "description": "deleteMany with deterministic encryption", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "aws": {} } } }, "operations": [ { "name": "deleteMany", "arguments": { "filter": { "encrypted_string": { "$in": [ "string0", "string1" ] } } }, "result": { "deletedCount": 2 } } ], "expectations": [ { "command_started_event": { "command": { "listCollections": 1, "filter": { "name": "default" } }, "command_name": "listCollections" } }, { "command_started_event": { "command": { "find": "datakeys", "filter": { "$or": [ { "_id": { "$in": [ { "$binary": { "base64": "AAAAAAAAAAAAAAAAAAAAAA==", "subType": "04" } } ] } }, { "keyAltNames": { "$in": [] } } ] }, "$db": "keyvault", "readConcern": { "level": "majority" } }, "command_name": "find" } }, { "command_started_event": { "command": { "delete": "default", "deletes": [ { "q": { "encrypted_string": { "$in": [ { "$binary": { "base64": "AQAAAAAAAAAAAAAAAAAAAAACwj+3zkv2VM+aTfk60RqhXq6a/77WlLwu/BxXFkL7EppGsju/m8f0x5kBDD3EZTtGALGXlym5jnpZAoSIkswHoA==", "subType": "06" } }, { "$binary": { "base64": "AQAAAAAAAAAAAAAAAAAAAAACDdw4KFz3ZLquhsbt7RmDjD0N67n0uSXx7IGnQNCLeIKvot6s/ouI21Eo84IOtb6lhwUNPlSEBNY0/hbszWAKJg==", "subType": "06" } } ] } }, "limit": 0 } ], "ordered": true }, "command_name": "delete" } } ], "outcome": { "collection": { "data": [] } } } ] } mongodb-mongo-python-driver-509e9b7/test/client-side-encryption/spec/legacy/distinct.json000066400000000000000000000163041462766011000317220ustar00rootroot00000000000000{ "runOn": [ { "minServerVersion": "4.1.10" } ], "database_name": "default", "collection_name": "default", "data": [ { "_id": 1, "encrypted_string": { "$binary": { "base64": "AQAAAAAAAAAAAAAAAAAAAAACwj+3zkv2VM+aTfk60RqhXq6a/77WlLwu/BxXFkL7EppGsju/m8f0x5kBDD3EZTtGALGXlym5jnpZAoSIkswHoA==", "subType": "06" } } }, { "_id": 2, "encrypted_string": { "$binary": { "base64": "AQAAAAAAAAAAAAAAAAAAAAACwj+3zkv2VM+aTfk60RqhXq6a/77WlLwu/BxXFkL7EppGsju/m8f0x5kBDD3EZTtGALGXlym5jnpZAoSIkswHoA==", "subType": "06" } } }, { "_id": 3, "encrypted_string": { "$binary": { "base64": "AQAAAAAAAAAAAAAAAAAAAAACDdw4KFz3ZLquhsbt7RmDjD0N67n0uSXx7IGnQNCLeIKvot6s/ouI21Eo84IOtb6lhwUNPlSEBNY0/hbszWAKJg==", "subType": "06" } } } ], "json_schema": { "properties": { "encrypted_w_altname": { "encrypt": { "keyId": "/altname", "bsonType": "string", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Random" } }, "encrypted_string": { "encrypt": { "keyId": [ { "$binary": { "base64": "AAAAAAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "bsonType": "string", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" } }, "random": { "encrypt": { "keyId": [ { "$binary": { "base64": "AAAAAAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "bsonType": "string", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Random" } }, "encrypted_string_equivalent": { "encrypt": { "keyId": [ { "$binary": { "base64": "AAAAAAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "bsonType": "string", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" } } }, "bsonType": "object" }, "key_vault_data": [ { "status": 1, "_id": { "$binary": { "base64": "AAAAAAAAAAAAAAAAAAAAAA==", "subType": "04" } }, "masterKey": { "provider": "aws", "key": "arn:aws:kms:us-east-1:579766882180:key/89fcc2c4-08b0-4bd9-9f25-e30687b580d0", "region": "us-east-1" }, "updateDate": { "$date": { "$numberLong": "1552949630483" } }, "keyMaterial": { "$binary": { "base64": "AQICAHhQNmWG2CzOm1dq3kWLM+iDUZhEqnhJwH9wZVpuZ94A8gEqnsxXlR51T5EbEVezUqqKAAAAwjCBvwYJKoZIhvcNAQcGoIGxMIGuAgEAMIGoBgkqhkiG9w0BBwEwHgYJYIZIAWUDBAEuMBEEDHa4jo6yp0Z18KgbUgIBEIB74sKxWtV8/YHje5lv5THTl0HIbhSwM6EqRlmBiFFatmEWaeMk4tO4xBX65eq670I5TWPSLMzpp8ncGHMmvHqRajNBnmFtbYxN3E3/WjxmdbOOe+OXpnGJPcGsftc7cB2shRfA4lICPnE26+oVNXT6p0Lo20nY5XC7jyCO", "subType": "00" } }, "creationDate": { "$date": { "$numberLong": "1552949630483" } }, "keyAltNames": [ "altname", "another_altname" ] } ], "tests": [ { "description": "distinct with deterministic encryption", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "aws": {} } } }, "operations": [ { "name": "distinct", "arguments": { "filter": { "encrypted_string": "string0" }, "fieldName": "encrypted_string" }, "result": [ "string0" ] } ], "expectations": [ { "command_started_event": { "command": { "listCollections": 1, "filter": { "name": "default" } }, "command_name": "listCollections" } }, { "command_started_event": { "command": { "find": "datakeys", "filter": { "$or": [ { "_id": { "$in": [ { "$binary": { "base64": "AAAAAAAAAAAAAAAAAAAAAA==", "subType": "04" } } ] } }, { "keyAltNames": { "$in": [] } } ] }, "$db": "keyvault", "readConcern": { "level": "majority" } }, "command_name": "find" } }, { "command_started_event": { "command": { "distinct": "default", "key": "encrypted_string", "query": { "encrypted_string": { "$eq": { "$binary": { "base64": "AQAAAAAAAAAAAAAAAAAAAAACwj+3zkv2VM+aTfk60RqhXq6a/77WlLwu/BxXFkL7EppGsju/m8f0x5kBDD3EZTtGALGXlym5jnpZAoSIkswHoA==", "subType": "06" } } } } }, "command_name": "distinct" } } ], "outcome": { "collection": { "data": [ { "_id": 1, "encrypted_string": { "$binary": { "base64": "AQAAAAAAAAAAAAAAAAAAAAACwj+3zkv2VM+aTfk60RqhXq6a/77WlLwu/BxXFkL7EppGsju/m8f0x5kBDD3EZTtGALGXlym5jnpZAoSIkswHoA==", "subType": "06" } } }, { "_id": 2, "encrypted_string": { "$binary": { "base64": "AQAAAAAAAAAAAAAAAAAAAAACwj+3zkv2VM+aTfk60RqhXq6a/77WlLwu/BxXFkL7EppGsju/m8f0x5kBDD3EZTtGALGXlym5jnpZAoSIkswHoA==", "subType": "06" } } }, { "_id": 3, "encrypted_string": { "$binary": { "base64": "AQAAAAAAAAAAAAAAAAAAAAACDdw4KFz3ZLquhsbt7RmDjD0N67n0uSXx7IGnQNCLeIKvot6s/ouI21Eo84IOtb6lhwUNPlSEBNY0/hbszWAKJg==", "subType": "06" } } } ] } } }, { "description": "Distinct fails when filtering on a random encrypted field", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "aws": {} } } }, "operations": [ { "name": "distinct", "arguments": { "filter": { "random": "abc" }, "fieldName": "encrypted_string" }, "result": { "errorContains": "Cannot query on fields encrypted with the randomized encryption" } } ] } ] } mongodb-mongo-python-driver-509e9b7/test/client-side-encryption/spec/legacy/explain.json000066400000000000000000000143251462766011000315420ustar00rootroot00000000000000{ "runOn": [ { "minServerVersion": "7.0.0" } ], "database_name": "default", "collection_name": "default", "data": [ { "_id": 1, "encrypted_string": { "$binary": { "base64": "AQAAAAAAAAAAAAAAAAAAAAACwj+3zkv2VM+aTfk60RqhXq6a/77WlLwu/BxXFkL7EppGsju/m8f0x5kBDD3EZTtGALGXlym5jnpZAoSIkswHoA==", "subType": "06" } } }, { "_id": 2, "encrypted_string": { "$binary": { "base64": "AQAAAAAAAAAAAAAAAAAAAAACDdw4KFz3ZLquhsbt7RmDjD0N67n0uSXx7IGnQNCLeIKvot6s/ouI21Eo84IOtb6lhwUNPlSEBNY0/hbszWAKJg==", "subType": "06" } } } ], "json_schema": { "properties": { "encrypted_w_altname": { "encrypt": { "keyId": "/altname", "bsonType": "string", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Random" } }, "encrypted_string": { "encrypt": { "keyId": [ { "$binary": { "base64": "AAAAAAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "bsonType": "string", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" } }, "random": { "encrypt": { "keyId": [ { "$binary": { "base64": "AAAAAAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "bsonType": "string", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Random" } }, "encrypted_string_equivalent": { "encrypt": { "keyId": [ { "$binary": { "base64": "AAAAAAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "bsonType": "string", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" } } }, "bsonType": "object" }, "key_vault_data": [ { "status": 1, "_id": { "$binary": { "base64": "AAAAAAAAAAAAAAAAAAAAAA==", "subType": "04" } }, "masterKey": { "provider": "aws", "key": "arn:aws:kms:us-east-1:579766882180:key/89fcc2c4-08b0-4bd9-9f25-e30687b580d0", "region": "us-east-1" }, "updateDate": { "$date": { "$numberLong": "1552949630483" } }, "keyMaterial": { "$binary": { "base64": "AQICAHhQNmWG2CzOm1dq3kWLM+iDUZhEqnhJwH9wZVpuZ94A8gEqnsxXlR51T5EbEVezUqqKAAAAwjCBvwYJKoZIhvcNAQcGoIGxMIGuAgEAMIGoBgkqhkiG9w0BBwEwHgYJYIZIAWUDBAEuMBEEDHa4jo6yp0Z18KgbUgIBEIB74sKxWtV8/YHje5lv5THTl0HIbhSwM6EqRlmBiFFatmEWaeMk4tO4xBX65eq670I5TWPSLMzpp8ncGHMmvHqRajNBnmFtbYxN3E3/WjxmdbOOe+OXpnGJPcGsftc7cB2shRfA4lICPnE26+oVNXT6p0Lo20nY5XC7jyCO", "subType": "00" } }, "creationDate": { "$date": { "$numberLong": "1552949630483" } }, "keyAltNames": [ "altname", "another_altname" ] } ], "tests": [ { "description": "Explain a find with deterministic encryption", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "aws": {} } } }, "operations": [ { "name": "runCommand", "object": "database", "command_name": "explain", "arguments": { "command": { "explain": { "find": "default", "filter": { "encrypted_string": "string1" } } } } } ], "expectations": [ { "command_started_event": { "command": { "listCollections": 1, "filter": { "name": "default" } }, "command_name": "listCollections" } }, { "command_started_event": { "command": { "find": "datakeys", "filter": { "$or": [ { "_id": { "$in": [ { "$binary": { "base64": "AAAAAAAAAAAAAAAAAAAAAA==", "subType": "04" } } ] } }, { "keyAltNames": { "$in": [] } } ] }, "$db": "keyvault", "readConcern": { "level": "majority" } }, "command_name": "find" } }, { "command_started_event": { "command": { "explain": { "find": "default", "filter": { "encrypted_string": { "$eq": { "$binary": { "base64": "AQAAAAAAAAAAAAAAAAAAAAACDdw4KFz3ZLquhsbt7RmDjD0N67n0uSXx7IGnQNCLeIKvot6s/ouI21Eo84IOtb6lhwUNPlSEBNY0/hbszWAKJg==", "subType": "06" } } } } }, "verbosity": "allPlansExecution" }, "command_name": "explain" } } ], "outcome": { "collection": { "data": [ { "_id": 1, "encrypted_string": { "$binary": { "base64": "AQAAAAAAAAAAAAAAAAAAAAACwj+3zkv2VM+aTfk60RqhXq6a/77WlLwu/BxXFkL7EppGsju/m8f0x5kBDD3EZTtGALGXlym5jnpZAoSIkswHoA==", "subType": "06" } } }, { "_id": 2, "encrypted_string": { "$binary": { "base64": "AQAAAAAAAAAAAAAAAAAAAAACDdw4KFz3ZLquhsbt7RmDjD0N67n0uSXx7IGnQNCLeIKvot6s/ouI21Eo84IOtb6lhwUNPlSEBNY0/hbszWAKJg==", "subType": "06" } } } ] } } } ] } mongodb-mongo-python-driver-509e9b7/test/client-side-encryption/spec/legacy/find.json000066400000000000000000000255111462766011000310210ustar00rootroot00000000000000{ "runOn": [ { "minServerVersion": "4.1.10" } ], "database_name": "default", "collection_name": "default", "data": [ { "_id": 1, "encrypted_string": { "$binary": { "base64": "AQAAAAAAAAAAAAAAAAAAAAACwj+3zkv2VM+aTfk60RqhXq6a/77WlLwu/BxXFkL7EppGsju/m8f0x5kBDD3EZTtGALGXlym5jnpZAoSIkswHoA==", "subType": "06" } } }, { "_id": 2, "encrypted_string": { "$binary": { "base64": "AQAAAAAAAAAAAAAAAAAAAAACDdw4KFz3ZLquhsbt7RmDjD0N67n0uSXx7IGnQNCLeIKvot6s/ouI21Eo84IOtb6lhwUNPlSEBNY0/hbszWAKJg==", "subType": "06" } }, "random": { "$binary": { "base64": "AgAAAAAAAAAAAAAAAAAAAAACyfp+lXvKOi7f5vh6ZsCijLEaXFKq1X06RmyS98ZvmMQGixTw8HM1f/bGxZjGwvYwjXOkIEb7Exgb8p2KCDI5TQ==", "subType": "06" } } } ], "json_schema": { "properties": { "encrypted_w_altname": { "encrypt": { "keyId": "/altname", "bsonType": "string", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Random" } }, "encrypted_string": { "encrypt": { "keyId": [ { "$binary": { "base64": "AAAAAAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "bsonType": "string", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" } }, "random": { "encrypt": { "keyId": [ { "$binary": { "base64": "AAAAAAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "bsonType": "string", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Random" } }, "encrypted_string_equivalent": { "encrypt": { "keyId": [ { "$binary": { "base64": "AAAAAAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "bsonType": "string", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" } } }, "bsonType": "object" }, "key_vault_data": [ { "status": 1, "_id": { "$binary": { "base64": "AAAAAAAAAAAAAAAAAAAAAA==", "subType": "04" } }, "masterKey": { "provider": "aws", "key": "arn:aws:kms:us-east-1:579766882180:key/89fcc2c4-08b0-4bd9-9f25-e30687b580d0", "region": "us-east-1" }, "updateDate": { "$date": { "$numberLong": "1552949630483" } }, "keyMaterial": { "$binary": { "base64": "AQICAHhQNmWG2CzOm1dq3kWLM+iDUZhEqnhJwH9wZVpuZ94A8gEqnsxXlR51T5EbEVezUqqKAAAAwjCBvwYJKoZIhvcNAQcGoIGxMIGuAgEAMIGoBgkqhkiG9w0BBwEwHgYJYIZIAWUDBAEuMBEEDHa4jo6yp0Z18KgbUgIBEIB74sKxWtV8/YHje5lv5THTl0HIbhSwM6EqRlmBiFFatmEWaeMk4tO4xBX65eq670I5TWPSLMzpp8ncGHMmvHqRajNBnmFtbYxN3E3/WjxmdbOOe+OXpnGJPcGsftc7cB2shRfA4lICPnE26+oVNXT6p0Lo20nY5XC7jyCO", "subType": "00" } }, "creationDate": { "$date": { "$numberLong": "1552949630483" } }, "keyAltNames": [ "altname", "another_altname" ] } ], "tests": [ { "description": "Find with deterministic encryption", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "aws": {} } } }, "operations": [ { "name": "find", "arguments": { "filter": { "encrypted_string": "string0" } }, "result": [ { "_id": 1, "encrypted_string": "string0" } ] } ], "expectations": [ { "command_started_event": { "command": { "listCollections": 1, "filter": { "name": "default" } }, "command_name": "listCollections" } }, { "command_started_event": { "command": { "find": "datakeys", "filter": { "$or": [ { "_id": { "$in": [ { "$binary": { "base64": "AAAAAAAAAAAAAAAAAAAAAA==", "subType": "04" } } ] } }, { "keyAltNames": { "$in": [] } } ] }, "$db": "keyvault", "readConcern": { "level": "majority" } }, "command_name": "find" } }, { "command_started_event": { "command": { "find": "default", "filter": { "encrypted_string": { "$eq": { "$binary": { "base64": "AQAAAAAAAAAAAAAAAAAAAAACwj+3zkv2VM+aTfk60RqhXq6a/77WlLwu/BxXFkL7EppGsju/m8f0x5kBDD3EZTtGALGXlym5jnpZAoSIkswHoA==", "subType": "06" } } } } }, "command_name": "find" } } ], "outcome": { "collection": { "data": [ { "_id": 1, "encrypted_string": { "$binary": { "base64": "AQAAAAAAAAAAAAAAAAAAAAACwj+3zkv2VM+aTfk60RqhXq6a/77WlLwu/BxXFkL7EppGsju/m8f0x5kBDD3EZTtGALGXlym5jnpZAoSIkswHoA==", "subType": "06" } } }, { "_id": 2, "encrypted_string": { "$binary": { "base64": "AQAAAAAAAAAAAAAAAAAAAAACDdw4KFz3ZLquhsbt7RmDjD0N67n0uSXx7IGnQNCLeIKvot6s/ouI21Eo84IOtb6lhwUNPlSEBNY0/hbszWAKJg==", "subType": "06" } }, "random": { "$binary": { "base64": "AgAAAAAAAAAAAAAAAAAAAAACyfp+lXvKOi7f5vh6ZsCijLEaXFKq1X06RmyS98ZvmMQGixTw8HM1f/bGxZjGwvYwjXOkIEb7Exgb8p2KCDI5TQ==", "subType": "06" } } } ] } } }, { "description": "Find with $in with deterministic encryption", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "aws": {} } } }, "operations": [ { "name": "find", "arguments": { "filter": { "encrypted_string": { "$in": [ "string0", "string1" ] } } }, "result": [ { "_id": 1, "encrypted_string": "string0" }, { "_id": 2, "encrypted_string": "string1", "random": "abc" } ] } ], "expectations": [ { "command_started_event": { "command": { "listCollections": 1, "filter": { "name": "default" } }, "command_name": "listCollections" } }, { "command_started_event": { "command": { "find": "datakeys", "filter": { "$or": [ { "_id": { "$in": [ { "$binary": { "base64": "AAAAAAAAAAAAAAAAAAAAAA==", "subType": "04" } } ] } }, { "keyAltNames": { "$in": [] } } ] }, "$db": "keyvault", "readConcern": { "level": "majority" } }, "command_name": "find" } }, { "command_started_event": { "command": { "find": "default", "filter": { "encrypted_string": { "$in": [ { "$binary": { "base64": "AQAAAAAAAAAAAAAAAAAAAAACwj+3zkv2VM+aTfk60RqhXq6a/77WlLwu/BxXFkL7EppGsju/m8f0x5kBDD3EZTtGALGXlym5jnpZAoSIkswHoA==", "subType": "06" } }, { "$binary": { "base64": "AQAAAAAAAAAAAAAAAAAAAAACDdw4KFz3ZLquhsbt7RmDjD0N67n0uSXx7IGnQNCLeIKvot6s/ouI21Eo84IOtb6lhwUNPlSEBNY0/hbszWAKJg==", "subType": "06" } } ] } } }, "command_name": "find" } } ], "outcome": { "collection": { "data": [ { "_id": 1, "encrypted_string": { "$binary": { "base64": "AQAAAAAAAAAAAAAAAAAAAAACwj+3zkv2VM+aTfk60RqhXq6a/77WlLwu/BxXFkL7EppGsju/m8f0x5kBDD3EZTtGALGXlym5jnpZAoSIkswHoA==", "subType": "06" } } }, { "_id": 2, "encrypted_string": { "$binary": { "base64": "AQAAAAAAAAAAAAAAAAAAAAACDdw4KFz3ZLquhsbt7RmDjD0N67n0uSXx7IGnQNCLeIKvot6s/ouI21Eo84IOtb6lhwUNPlSEBNY0/hbszWAKJg==", "subType": "06" } }, "random": { "$binary": { "base64": "AgAAAAAAAAAAAAAAAAAAAAACyfp+lXvKOi7f5vh6ZsCijLEaXFKq1X06RmyS98ZvmMQGixTw8HM1f/bGxZjGwvYwjXOkIEb7Exgb8p2KCDI5TQ==", "subType": "06" } } } ] } } }, { "description": "Find fails when filtering on a random encrypted field", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "aws": {} } } }, "operations": [ { "name": "find", "arguments": { "filter": { "random": "abc" } }, "result": { "errorContains": "Cannot query on fields encrypted with the randomized encryption" } } ] } ] } mongodb-mongo-python-driver-509e9b7/test/client-side-encryption/spec/legacy/findOneAndDelete.json000066400000000000000000000132111462766011000332230ustar00rootroot00000000000000{ "runOn": [ { "minServerVersion": "4.1.10" } ], "database_name": "default", "collection_name": "default", "data": [ { "_id": 1, "encrypted_string": { "$binary": { "base64": "AQAAAAAAAAAAAAAAAAAAAAACwj+3zkv2VM+aTfk60RqhXq6a/77WlLwu/BxXFkL7EppGsju/m8f0x5kBDD3EZTtGALGXlym5jnpZAoSIkswHoA==", "subType": "06" } } }, { "_id": 2, "encrypted_string": { "$binary": { "base64": "AQAAAAAAAAAAAAAAAAAAAAACDdw4KFz3ZLquhsbt7RmDjD0N67n0uSXx7IGnQNCLeIKvot6s/ouI21Eo84IOtb6lhwUNPlSEBNY0/hbszWAKJg==", "subType": "06" } } } ], "json_schema": { "properties": { "encrypted_w_altname": { "encrypt": { "keyId": "/altname", "bsonType": "string", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Random" } }, "encrypted_string": { "encrypt": { "keyId": [ { "$binary": { "base64": "AAAAAAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "bsonType": "string", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" } }, "random": { "encrypt": { "keyId": [ { "$binary": { "base64": "AAAAAAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "bsonType": "string", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Random" } }, "encrypted_string_equivalent": { "encrypt": { "keyId": [ { "$binary": { "base64": "AAAAAAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "bsonType": "string", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" } } }, "bsonType": "object" }, "key_vault_data": [ { "status": 1, "_id": { "$binary": { "base64": "AAAAAAAAAAAAAAAAAAAAAA==", "subType": "04" } }, "masterKey": { "provider": "aws", "key": "arn:aws:kms:us-east-1:579766882180:key/89fcc2c4-08b0-4bd9-9f25-e30687b580d0", "region": "us-east-1" }, "updateDate": { "$date": { "$numberLong": "1552949630483" } }, "keyMaterial": { "$binary": { "base64": "AQICAHhQNmWG2CzOm1dq3kWLM+iDUZhEqnhJwH9wZVpuZ94A8gEqnsxXlR51T5EbEVezUqqKAAAAwjCBvwYJKoZIhvcNAQcGoIGxMIGuAgEAMIGoBgkqhkiG9w0BBwEwHgYJYIZIAWUDBAEuMBEEDHa4jo6yp0Z18KgbUgIBEIB74sKxWtV8/YHje5lv5THTl0HIbhSwM6EqRlmBiFFatmEWaeMk4tO4xBX65eq670I5TWPSLMzpp8ncGHMmvHqRajNBnmFtbYxN3E3/WjxmdbOOe+OXpnGJPcGsftc7cB2shRfA4lICPnE26+oVNXT6p0Lo20nY5XC7jyCO", "subType": "00" } }, "creationDate": { "$date": { "$numberLong": "1552949630483" } }, "keyAltNames": [ "altname", "another_altname" ] } ], "tests": [ { "description": "findOneAndDelete with deterministic encryption", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "aws": {} } } }, "operations": [ { "name": "findOneAndDelete", "arguments": { "filter": { "encrypted_string": "string0" } } } ], "expectations": [ { "command_started_event": { "command": { "listCollections": 1, "filter": { "name": "default" } }, "command_name": "listCollections" } }, { "command_started_event": { "command": { "find": "datakeys", "filter": { "$or": [ { "_id": { "$in": [ { "$binary": { "base64": "AAAAAAAAAAAAAAAAAAAAAA==", "subType": "04" } } ] } }, { "keyAltNames": { "$in": [] } } ] }, "$db": "keyvault", "readConcern": { "level": "majority" } }, "command_name": "find" } }, { "command_started_event": { "command": { "findAndModify": "default", "query": { "encrypted_string": { "$eq": { "$binary": { "base64": "AQAAAAAAAAAAAAAAAAAAAAACwj+3zkv2VM+aTfk60RqhXq6a/77WlLwu/BxXFkL7EppGsju/m8f0x5kBDD3EZTtGALGXlym5jnpZAoSIkswHoA==", "subType": "06" } } } }, "remove": true }, "command_name": "findAndModify" } } ], "outcome": { "collection": { "data": [ { "_id": 2, "encrypted_string": { "$binary": { "base64": "AQAAAAAAAAAAAAAAAAAAAAACDdw4KFz3ZLquhsbt7RmDjD0N67n0uSXx7IGnQNCLeIKvot6s/ouI21Eo84IOtb6lhwUNPlSEBNY0/hbszWAKJg==", "subType": "06" } } } ] } } } ] } mongodb-mongo-python-driver-509e9b7/test/client-side-encryption/spec/legacy/findOneAndReplace.json000066400000000000000000000136321462766011000334030ustar00rootroot00000000000000{ "runOn": [ { "minServerVersion": "4.1.10" } ], "database_name": "default", "collection_name": "default", "data": [ { "_id": 1, "encrypted_string": { "$binary": { "base64": "AQAAAAAAAAAAAAAAAAAAAAACwj+3zkv2VM+aTfk60RqhXq6a/77WlLwu/BxXFkL7EppGsju/m8f0x5kBDD3EZTtGALGXlym5jnpZAoSIkswHoA==", "subType": "06" } } } ], "json_schema": { "properties": { "encrypted_w_altname": { "encrypt": { "keyId": "/altname", "bsonType": "string", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Random" } }, "encrypted_string": { "encrypt": { "keyId": [ { "$binary": { "base64": "AAAAAAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "bsonType": "string", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" } }, "random": { "encrypt": { "keyId": [ { "$binary": { "base64": "AAAAAAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "bsonType": "string", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Random" } }, "encrypted_string_equivalent": { "encrypt": { "keyId": [ { "$binary": { "base64": "AAAAAAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "bsonType": "string", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" } } }, "bsonType": "object" }, "key_vault_data": [ { "status": 1, "_id": { "$binary": { "base64": "AAAAAAAAAAAAAAAAAAAAAA==", "subType": "04" } }, "masterKey": { "provider": "aws", "key": "arn:aws:kms:us-east-1:579766882180:key/89fcc2c4-08b0-4bd9-9f25-e30687b580d0", "region": "us-east-1" }, "updateDate": { "$date": { "$numberLong": "1552949630483" } }, "keyMaterial": { "$binary": { "base64": "AQICAHhQNmWG2CzOm1dq3kWLM+iDUZhEqnhJwH9wZVpuZ94A8gEqnsxXlR51T5EbEVezUqqKAAAAwjCBvwYJKoZIhvcNAQcGoIGxMIGuAgEAMIGoBgkqhkiG9w0BBwEwHgYJYIZIAWUDBAEuMBEEDHa4jo6yp0Z18KgbUgIBEIB74sKxWtV8/YHje5lv5THTl0HIbhSwM6EqRlmBiFFatmEWaeMk4tO4xBX65eq670I5TWPSLMzpp8ncGHMmvHqRajNBnmFtbYxN3E3/WjxmdbOOe+OXpnGJPcGsftc7cB2shRfA4lICPnE26+oVNXT6p0Lo20nY5XC7jyCO", "subType": "00" } }, "creationDate": { "$date": { "$numberLong": "1552949630483" } }, "keyAltNames": [ "altname", "another_altname" ] } ], "tests": [ { "description": "findOneAndReplace with deterministic encryption", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "aws": {} } } }, "operations": [ { "name": "findOneAndReplace", "arguments": { "filter": { "encrypted_string": "string0" }, "replacement": { "encrypted_string": "string1" }, "returnDocument": "Before" }, "result": { "_id": 1, "encrypted_string": "string0" } } ], "expectations": [ { "command_started_event": { "command": { "listCollections": 1, "filter": { "name": "default" } }, "command_name": "listCollections" } }, { "command_started_event": { "command": { "find": "datakeys", "filter": { "$or": [ { "_id": { "$in": [ { "$binary": { "base64": "AAAAAAAAAAAAAAAAAAAAAA==", "subType": "04" } } ] } }, { "keyAltNames": { "$in": [] } } ] }, "$db": "keyvault", "readConcern": { "level": "majority" } }, "command_name": "find" } }, { "command_started_event": { "command": { "findAndModify": "default", "query": { "encrypted_string": { "$eq": { "$binary": { "base64": "AQAAAAAAAAAAAAAAAAAAAAACwj+3zkv2VM+aTfk60RqhXq6a/77WlLwu/BxXFkL7EppGsju/m8f0x5kBDD3EZTtGALGXlym5jnpZAoSIkswHoA==", "subType": "06" } } } }, "update": { "encrypted_string": { "$binary": { "base64": "AQAAAAAAAAAAAAAAAAAAAAACDdw4KFz3ZLquhsbt7RmDjD0N67n0uSXx7IGnQNCLeIKvot6s/ouI21Eo84IOtb6lhwUNPlSEBNY0/hbszWAKJg==", "subType": "06" } } } }, "command_name": "findAndModify" } } ], "outcome": { "collection": { "data": [ { "_id": 1, "encrypted_string": { "$binary": { "base64": "AQAAAAAAAAAAAAAAAAAAAAACDdw4KFz3ZLquhsbt7RmDjD0N67n0uSXx7IGnQNCLeIKvot6s/ouI21Eo84IOtb6lhwUNPlSEBNY0/hbszWAKJg==", "subType": "06" } } } ] } } } ] } mongodb-mongo-python-driver-509e9b7/test/client-side-encryption/spec/legacy/findOneAndUpdate.json000066400000000000000000000137651462766011000332610ustar00rootroot00000000000000{ "runOn": [ { "minServerVersion": "4.1.10" } ], "database_name": "default", "collection_name": "default", "data": [ { "_id": 1, "encrypted_string": { "$binary": { "base64": "AQAAAAAAAAAAAAAAAAAAAAACwj+3zkv2VM+aTfk60RqhXq6a/77WlLwu/BxXFkL7EppGsju/m8f0x5kBDD3EZTtGALGXlym5jnpZAoSIkswHoA==", "subType": "06" } } } ], "json_schema": { "properties": { "encrypted_w_altname": { "encrypt": { "keyId": "/altname", "bsonType": "string", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Random" } }, "encrypted_string": { "encrypt": { "keyId": [ { "$binary": { "base64": "AAAAAAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "bsonType": "string", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" } }, "random": { "encrypt": { "keyId": [ { "$binary": { "base64": "AAAAAAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "bsonType": "string", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Random" } }, "encrypted_string_equivalent": { "encrypt": { "keyId": [ { "$binary": { "base64": "AAAAAAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "bsonType": "string", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" } } }, "bsonType": "object" }, "key_vault_data": [ { "status": 1, "_id": { "$binary": { "base64": "AAAAAAAAAAAAAAAAAAAAAA==", "subType": "04" } }, "masterKey": { "provider": "aws", "key": "arn:aws:kms:us-east-1:579766882180:key/89fcc2c4-08b0-4bd9-9f25-e30687b580d0", "region": "us-east-1" }, "updateDate": { "$date": { "$numberLong": "1552949630483" } }, "keyMaterial": { "$binary": { "base64": "AQICAHhQNmWG2CzOm1dq3kWLM+iDUZhEqnhJwH9wZVpuZ94A8gEqnsxXlR51T5EbEVezUqqKAAAAwjCBvwYJKoZIhvcNAQcGoIGxMIGuAgEAMIGoBgkqhkiG9w0BBwEwHgYJYIZIAWUDBAEuMBEEDHa4jo6yp0Z18KgbUgIBEIB74sKxWtV8/YHje5lv5THTl0HIbhSwM6EqRlmBiFFatmEWaeMk4tO4xBX65eq670I5TWPSLMzpp8ncGHMmvHqRajNBnmFtbYxN3E3/WjxmdbOOe+OXpnGJPcGsftc7cB2shRfA4lICPnE26+oVNXT6p0Lo20nY5XC7jyCO", "subType": "00" } }, "creationDate": { "$date": { "$numberLong": "1552949630483" } }, "keyAltNames": [ "altname", "another_altname" ] } ], "tests": [ { "description": "findOneAndUpdate with deterministic encryption", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "aws": {} } } }, "operations": [ { "name": "findOneAndUpdate", "arguments": { "filter": { "encrypted_string": "string0" }, "update": { "$set": { "encrypted_string": "string1" } }, "returnDocument": "Before" }, "result": { "_id": 1, "encrypted_string": "string0" } } ], "expectations": [ { "command_started_event": { "command": { "listCollections": 1, "filter": { "name": "default" } }, "command_name": "listCollections" } }, { "command_started_event": { "command": { "find": "datakeys", "filter": { "$or": [ { "_id": { "$in": [ { "$binary": { "base64": "AAAAAAAAAAAAAAAAAAAAAA==", "subType": "04" } } ] } }, { "keyAltNames": { "$in": [] } } ] }, "$db": "keyvault", "readConcern": { "level": "majority" } }, "command_name": "find" } }, { "command_started_event": { "command": { "findAndModify": "default", "query": { "encrypted_string": { "$eq": { "$binary": { "base64": "AQAAAAAAAAAAAAAAAAAAAAACwj+3zkv2VM+aTfk60RqhXq6a/77WlLwu/BxXFkL7EppGsju/m8f0x5kBDD3EZTtGALGXlym5jnpZAoSIkswHoA==", "subType": "06" } } } }, "update": { "$set": { "encrypted_string": { "$binary": { "base64": "AQAAAAAAAAAAAAAAAAAAAAACDdw4KFz3ZLquhsbt7RmDjD0N67n0uSXx7IGnQNCLeIKvot6s/ouI21Eo84IOtb6lhwUNPlSEBNY0/hbszWAKJg==", "subType": "06" } } } } }, "command_name": "findAndModify" } } ], "outcome": { "collection": { "data": [ { "_id": 1, "encrypted_string": { "$binary": { "base64": "AQAAAAAAAAAAAAAAAAAAAAACDdw4KFz3ZLquhsbt7RmDjD0N67n0uSXx7IGnQNCLeIKvot6s/ouI21Eo84IOtb6lhwUNPlSEBNY0/hbszWAKJg==", "subType": "06" } } } ] } } } ] } fle2v2-BypassQueryAnalysis.json000066400000000000000000000166611462766011000351210ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/client-side-encryption/spec/legacy{ "runOn": [ { "minServerVersion": "7.0.0", "topology": [ "replicaset", "sharded", "load-balanced" ] } ], "database_name": "default", "collection_name": "default", "data": [], "encrypted_fields": { "fields": [ { "keyId": { "$binary": { "base64": "EjRWeBI0mHYSNBI0VniQEg==", "subType": "04" } }, "path": "encryptedIndexed", "bsonType": "string", "queries": { "queryType": "equality", "contention": { "$numberLong": "0" } } }, { "keyId": { "$binary": { "base64": "q83vqxI0mHYSNBI0VniQEg==", "subType": "04" } }, "path": "encryptedUnindexed", "bsonType": "string" } ] }, "key_vault_data": [ { "_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" } } ], "tests": [ { "description": "BypassQueryAnalysis decrypts", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "local": { "key": { "$binary": { "base64": "Mng0NCt4ZHVUYUJCa1kxNkVyNUR1QURhZ2h2UzR2d2RrZzh0cFBwM3R6NmdWMDFBMUN3YkQ5aXRRMkhGRGdQV09wOGVNYUMxT2k3NjZKelhaQmRCZGJkTXVyZG9uSjFk", "subType": "00" } } } }, "bypassQueryAnalysis": true } }, "operations": [ { "name": "insertOne", "arguments": { "document": { "_id": 1, "encryptedIndexed": { "$binary": { "base64": "C18BAAAFZAAgAAAAANnt+eLTkv4GdDPl8IAfJOvTzArOgFJQ2S/DcLza4W0DBXMAIAAAAAD2u+omZme3P2gBPehMQyQHQ153tPN1+z7bksYA9jKTpAVwADAAAAAAUnCOQqIvmR65YKyYnsiVfVrg9hwUVO3RhhKExo3RWOzgaS0QdsBL5xKFS0JhZSoWBXUAEAAAAAQSNFZ4EjSYdhI0EjRWeJASEHQAAgAAAAV2AFAAAAAAEjRWeBI0mHYSNBI0VniQEpQbp/ZJpWBKeDtKLiXb0P2E9wvc0g3f373jnYQYlJquOrlPOoEy3ngsHPJuSUijvWDsrQzqYa349K7G/66qaXEFZQAgAAAAAOuac/eRLYakKX6B0vZ1r3QodOQFfjqJD+xlGiPu4/PsBWwAIAAAAACkm0o9bj6j0HuADKc0svbqO2UHj6GrlNdF6yKNxh63xRJrAAAAAAAAAAAAAA==", "subType": "06" } } } } }, { "name": "find", "arguments": { "filter": { "_id": 1 } }, "result": [ { "_id": 1, "encryptedIndexed": "123" } ] } ], "expectations": [ { "command_started_event": { "command": { "listCollections": 1, "filter": { "name": "default" } }, "command_name": "listCollections" } }, { "command_started_event": { "command": { "insert": "default", "documents": [ { "_id": 1, "encryptedIndexed": { "$binary": { "base64": "C18BAAAFZAAgAAAAANnt+eLTkv4GdDPl8IAfJOvTzArOgFJQ2S/DcLza4W0DBXMAIAAAAAD2u+omZme3P2gBPehMQyQHQ153tPN1+z7bksYA9jKTpAVwADAAAAAAUnCOQqIvmR65YKyYnsiVfVrg9hwUVO3RhhKExo3RWOzgaS0QdsBL5xKFS0JhZSoWBXUAEAAAAAQSNFZ4EjSYdhI0EjRWeJASEHQAAgAAAAV2AFAAAAAAEjRWeBI0mHYSNBI0VniQEpQbp/ZJpWBKeDtKLiXb0P2E9wvc0g3f373jnYQYlJquOrlPOoEy3ngsHPJuSUijvWDsrQzqYa349K7G/66qaXEFZQAgAAAAAOuac/eRLYakKX6B0vZ1r3QodOQFfjqJD+xlGiPu4/PsBWwAIAAAAACkm0o9bj6j0HuADKc0svbqO2UHj6GrlNdF6yKNxh63xRJrAAAAAAAAAAAAAA==", "subType": "06" } } } ], "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" } } }, { "keyId": { "$binary": { "base64": "q83vqxI0mHYSNBI0VniQEg==", "subType": "04" } }, "path": "encryptedUnindexed", "bsonType": "string" } ] } } } }, "command_name": "insert" } }, { "command_started_event": { "command": { "find": "default", "filter": { "_id": 1 } }, "command_name": "find" } }, { "command_started_event": { "command": { "find": "datakeys", "filter": { "$or": [ { "_id": { "$in": [ { "$binary": { "base64": "EjRWeBI0mHYSNBI0VniQEg==", "subType": "04" } } ] } }, { "keyAltNames": { "$in": [] } } ] }, "$db": "keyvault", "readConcern": { "level": "majority" } }, "command_name": "find" } } ], "outcome": { "collection": { "data": [ { "_id": 1, "encryptedIndexed": { "$$type": "binData" }, "__safeContent__": [ { "$binary": { "base64": "31eCYlbQoVboc5zwC8IoyJVSkag9PxREka8dkmbXJeY=", "subType": "00" } } ] } ] } } } ] } mongodb-mongo-python-driver-509e9b7/test/client-side-encryption/spec/legacy/fle2v2-Compact.json000066400000000000000000000134651462766011000325720ustar00rootroot00000000000000{ "runOn": [ { "minServerVersion": "7.0.0", "topology": [ "replicaset", "sharded", "load-balanced" ] } ], "database_name": "default", "collection_name": "default", "data": [], "encrypted_fields": { "fields": [ { "keyId": { "$binary": { "base64": "EjRWeBI0mHYSNBI0VniQEg==", "subType": "04" } }, "path": "encryptedIndexed", "bsonType": "string", "queries": { "queryType": "equality", "contention": { "$numberLong": "0" } } }, { "keyId": { "$binary": { "base64": "q83vqxI0mHYSNBI0VniQEg==", "subType": "04" } }, "path": "encryptedUnindexed", "bsonType": "string" } ] }, "key_vault_data": [ { "_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" } }, { "_id": { "$binary": { "base64": "q83vqxI0mHYSNBI0VniQEg==", "subType": "04" } }, "keyMaterial": { "$binary": { "base64": "HBk9BWihXExNDvTp1lUxOuxuZK2Pe2ZdVdlsxPEBkiO1bS4mG5NNDsQ7zVxJAH8BtdOYp72Ku4Y3nwc0BUpIKsvAKX4eYXtlhv5zUQxWdeNFhg9qK7qb8nqhnnLeT0f25jFSqzWJoT379hfwDeu0bebJHr35QrJ8myZdPMTEDYF08QYQ48ShRBli0S+QzBHHAQiM2iJNr4svg2WR8JSeWQ==", "subType": "00" } }, "creationDate": { "$date": { "$numberLong": "1648914851981" } }, "updateDate": { "$date": { "$numberLong": "1648914851981" } }, "status": { "$numberInt": "0" }, "masterKey": { "provider": "local" } } ], "tests": [ { "description": "Compact works", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "local": { "key": { "$binary": { "base64": "Mng0NCt4ZHVUYUJCa1kxNkVyNUR1QURhZ2h2UzR2d2RrZzh0cFBwM3R6NmdWMDFBMUN3YkQ5aXRRMkhGRGdQV09wOGVNYUMxT2k3NjZKelhaQmRCZGJkTXVyZG9uSjFk", "subType": "00" } } } } } }, "operations": [ { "name": "runCommand", "object": "database", "command_name": "compactStructuredEncryptionData", "arguments": { "command": { "compactStructuredEncryptionData": "default" } } } ], "expectations": [ { "command_started_event": { "command": { "listCollections": 1, "filter": { "name": "default" } }, "command_name": "listCollections" } }, { "command_started_event": { "command": { "find": "datakeys", "filter": { "$or": [ { "_id": { "$in": [ { "$binary": { "base64": "EjRWeBI0mHYSNBI0VniQEg==", "subType": "04" } }, { "$binary": { "base64": "q83vqxI0mHYSNBI0VniQEg==", "subType": "04" } } ] } }, { "keyAltNames": { "$in": [] } } ] }, "$db": "keyvault", "readConcern": { "level": "majority" } }, "command_name": "find" } }, { "command_started_event": { "command": { "compactStructuredEncryptionData": "default", "compactionTokens": { "encryptedIndexed": { "$binary": { "base64": "noN+05JsuO1oDg59yypIGj45i+eFH6HOTXOPpeZ//Mk=", "subType": "00" } }, "encryptedUnindexed": { "$binary": { "base64": "SWO8WEoZ2r2Kx/muQKb7+COizy85nIIUFiHh4K9kcvA=", "subType": "00" } } } }, "command_name": "compactStructuredEncryptionData" } } ] }, { "description": "Compact errors on an unencrypted client", "operations": [ { "name": "runCommand", "object": "database", "command_name": "compactStructuredEncryptionData", "arguments": { "command": { "compactStructuredEncryptionData": "default" } }, "result": { "errorContains": "'compactStructuredEncryptionData.compactionTokens' is missing" } } ] } ] } fle2v2-CreateCollection-OldServer.json000066400000000000000000000046471462766011000362510ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/client-side-encryption/spec/legacy{ "runOn": [ { "minServerVersion": "6.0.0", "maxServerVersion": "6.3.99", "topology": [ "replicaset", "sharded", "load-balanced" ] } ], "database_name": "default", "collection_name": "default", "tests": [ { "description": "driver returns an error if creating a QEv2 collection on unsupported server", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "aws": {} }, "encryptedFieldsMap": { "default.encryptedCollection": { "fields": [ { "path": "firstName", "bsonType": "string", "keyId": { "$binary": { "base64": "AAAAAAAAAAAAAAAAAAAAAA==", "subType": "04" } } } ] } } } }, "operations": [ { "name": "dropCollection", "object": "database", "arguments": { "collection": "encryptedCollection" } }, { "name": "createCollection", "object": "database", "arguments": { "collection": "encryptedCollection" }, "result": { "errorContains": "Driver support of Queryable Encryption is incompatible with server. Upgrade server to use Queryable Encryption." } }, { "name": "assertCollectionNotExists", "object": "testRunner", "arguments": { "database": "default", "collection": "enxcol_.encryptedCollection.esc" } }, { "name": "assertCollectionNotExists", "object": "testRunner", "arguments": { "database": "default", "collection": "enxcol_.encryptedCollection.ecc" } }, { "name": "assertCollectionNotExists", "object": "testRunner", "arguments": { "database": "default", "collection": "enxcol_.encryptedCollection.ecoc" } }, { "name": "assertCollectionNotExists", "object": "testRunner", "arguments": { "database": "default", "collection": "encryptedCollection" } } ] } ] } fle2v2-CreateCollection.json000066400000000000000000001337731462766011000343510ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/client-side-encryption/spec/legacy{ "runOn": [ { "minServerVersion": "7.0.0", "topology": [ "replicaset", "sharded", "load-balanced" ] } ], "database_name": "default", "collection_name": "default", "tests": [ { "description": "state collections and index are created", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "aws": {} }, "encryptedFieldsMap": { "default.encryptedCollection": { "fields": [ { "path": "firstName", "bsonType": "string", "keyId": { "$binary": { "subType": "04", "base64": "AAAAAAAAAAAAAAAAAAAAAA==" } } } ] } } } }, "operations": [ { "name": "dropCollection", "object": "database", "arguments": { "collection": "encryptedCollection" } }, { "name": "createCollection", "object": "database", "arguments": { "collection": "encryptedCollection" } }, { "name": "assertCollectionExists", "object": "testRunner", "arguments": { "database": "default", "collection": "enxcol_.encryptedCollection.esc" } }, { "name": "assertCollectionNotExists", "object": "testRunner", "arguments": { "database": "default", "collection": "enxcol_.encryptedCollection.ecc" } }, { "name": "assertCollectionExists", "object": "testRunner", "arguments": { "database": "default", "collection": "enxcol_.encryptedCollection.ecoc" } }, { "name": "assertCollectionExists", "object": "testRunner", "arguments": { "database": "default", "collection": "encryptedCollection" } }, { "name": "assertIndexExists", "object": "testRunner", "arguments": { "database": "default", "collection": "encryptedCollection", "index": "__safeContent___1" } } ], "expectations": [ { "command_started_event": { "command": { "drop": "enxcol_.encryptedCollection.esc" }, "command_name": "drop", "database_name": "default" } }, { "command_started_event": { "command": { "drop": "enxcol_.encryptedCollection.ecoc" }, "command_name": "drop", "database_name": "default" } }, { "command_started_event": { "command": { "drop": "encryptedCollection" }, "command_name": "drop", "database_name": "default" } }, { "command_started_event": { "command": { "create": "enxcol_.encryptedCollection.esc", "clusteredIndex": { "key": { "_id": 1 }, "unique": true } }, "command_name": "create", "database_name": "default" } }, { "command_started_event": { "command": { "create": "enxcol_.encryptedCollection.ecoc", "clusteredIndex": { "key": { "_id": 1 }, "unique": true } }, "command_name": "create", "database_name": "default" } }, { "command_started_event": { "command": { "create": "encryptedCollection", "encryptedFields": { "fields": [ { "path": "firstName", "bsonType": "string", "keyId": { "$binary": { "subType": "04", "base64": "AAAAAAAAAAAAAAAAAAAAAA==" } } } ] } }, "command_name": "create", "database_name": "default" } }, { "command_started_event": { "command": { "createIndexes": "encryptedCollection", "indexes": [ { "name": "__safeContent___1", "key": { "__safeContent__": 1 } } ] }, "command_name": "createIndexes", "database_name": "default" } } ] }, { "description": "default state collection names are applied", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "aws": {} }, "encryptedFieldsMap": { "default.encryptedCollection": { "fields": [ { "path": "firstName", "bsonType": "string", "keyId": { "$binary": { "subType": "04", "base64": "AAAAAAAAAAAAAAAAAAAAAA==" } } } ] } } } }, "operations": [ { "name": "dropCollection", "object": "database", "arguments": { "collection": "encryptedCollection" } }, { "name": "createCollection", "object": "database", "arguments": { "collection": "encryptedCollection" } }, { "name": "assertCollectionExists", "object": "testRunner", "arguments": { "database": "default", "collection": "enxcol_.encryptedCollection.esc" } }, { "name": "assertCollectionNotExists", "object": "testRunner", "arguments": { "database": "default", "collection": "enxcol_.encryptedCollection.ecc" } }, { "name": "assertCollectionExists", "object": "testRunner", "arguments": { "database": "default", "collection": "enxcol_.encryptedCollection.ecoc" } }, { "name": "assertCollectionExists", "object": "testRunner", "arguments": { "database": "default", "collection": "encryptedCollection" } }, { "name": "assertIndexExists", "object": "testRunner", "arguments": { "database": "default", "collection": "encryptedCollection", "index": "__safeContent___1" } } ], "expectations": [ { "command_started_event": { "command": { "drop": "enxcol_.encryptedCollection.esc" }, "command_name": "drop", "database_name": "default" } }, { "command_started_event": { "command": { "drop": "enxcol_.encryptedCollection.ecoc" }, "command_name": "drop", "database_name": "default" } }, { "command_started_event": { "command": { "drop": "encryptedCollection" }, "command_name": "drop", "database_name": "default" } }, { "command_started_event": { "command": { "create": "enxcol_.encryptedCollection.esc", "clusteredIndex": { "key": { "_id": 1 }, "unique": true } }, "command_name": "create", "database_name": "default" } }, { "command_started_event": { "command": { "create": "enxcol_.encryptedCollection.ecoc", "clusteredIndex": { "key": { "_id": 1 }, "unique": true } }, "command_name": "create", "database_name": "default" } }, { "command_started_event": { "command": { "create": "encryptedCollection", "encryptedFields": { "fields": [ { "path": "firstName", "bsonType": "string", "keyId": { "$binary": { "subType": "04", "base64": "AAAAAAAAAAAAAAAAAAAAAA==" } } } ] } }, "command_name": "create", "database_name": "default" } }, { "command_started_event": { "command": { "createIndexes": "encryptedCollection", "indexes": [ { "name": "__safeContent___1", "key": { "__safeContent__": 1 } } ] }, "command_name": "createIndexes", "database_name": "default" } } ] }, { "description": "drop removes all state collections", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "aws": {} }, "encryptedFieldsMap": { "default.encryptedCollection": { "fields": [ { "path": "firstName", "bsonType": "string", "keyId": { "$binary": { "subType": "04", "base64": "AAAAAAAAAAAAAAAAAAAAAA==" } } } ] } } } }, "operations": [ { "name": "dropCollection", "object": "database", "arguments": { "collection": "encryptedCollection" } }, { "name": "createCollection", "object": "database", "arguments": { "collection": "encryptedCollection" } }, { "name": "assertCollectionExists", "object": "testRunner", "arguments": { "database": "default", "collection": "enxcol_.encryptedCollection.esc" } }, { "name": "assertCollectionNotExists", "object": "testRunner", "arguments": { "database": "default", "collection": "enxcol_.encryptedCollection.ecc" } }, { "name": "assertCollectionExists", "object": "testRunner", "arguments": { "database": "default", "collection": "enxcol_.encryptedCollection.ecoc" } }, { "name": "assertCollectionExists", "object": "testRunner", "arguments": { "database": "default", "collection": "encryptedCollection" } }, { "name": "assertIndexExists", "object": "testRunner", "arguments": { "database": "default", "collection": "encryptedCollection", "index": "__safeContent___1" } }, { "name": "dropCollection", "object": "database", "arguments": { "collection": "encryptedCollection" } }, { "name": "assertCollectionNotExists", "object": "testRunner", "arguments": { "database": "default", "collection": "enxcol_.encryptedCollection.ecoc" } }, { "name": "assertCollectionNotExists", "object": "testRunner", "arguments": { "database": "default", "collection": "encryptedCollection" } }, { "name": "assertIndexNotExists", "object": "testRunner", "arguments": { "database": "default", "collection": "encryptedCollection", "index": "__safeContent___1" } } ], "expectations": [ { "command_started_event": { "command": { "drop": "enxcol_.encryptedCollection.esc" }, "command_name": "drop", "database_name": "default" } }, { "command_started_event": { "command": { "drop": "enxcol_.encryptedCollection.ecoc" }, "command_name": "drop", "database_name": "default" } }, { "command_started_event": { "command": { "drop": "encryptedCollection" }, "command_name": "drop", "database_name": "default" } }, { "command_started_event": { "command": { "create": "enxcol_.encryptedCollection.esc", "clusteredIndex": { "key": { "_id": 1 }, "unique": true } }, "command_name": "create", "database_name": "default" } }, { "command_started_event": { "command": { "create": "enxcol_.encryptedCollection.ecoc", "clusteredIndex": { "key": { "_id": 1 }, "unique": true } }, "command_name": "create", "database_name": "default" } }, { "command_started_event": { "command": { "create": "encryptedCollection", "encryptedFields": { "fields": [ { "path": "firstName", "bsonType": "string", "keyId": { "$binary": { "subType": "04", "base64": "AAAAAAAAAAAAAAAAAAAAAA==" } } } ] } }, "command_name": "create", "database_name": "default" } }, { "command_started_event": { "command": { "createIndexes": "encryptedCollection", "indexes": [ { "name": "__safeContent___1", "key": { "__safeContent__": 1 } } ] }, "command_name": "createIndexes", "database_name": "default" } }, { "command_started_event": { "command": { "drop": "enxcol_.encryptedCollection.esc" }, "command_name": "drop", "database_name": "default" } }, { "command_started_event": { "command": { "drop": "enxcol_.encryptedCollection.ecoc" }, "command_name": "drop", "database_name": "default" } }, { "command_started_event": { "command": { "drop": "encryptedCollection" }, "command_name": "drop", "database_name": "default" } } ] }, { "description": "CreateCollection without encryptedFields.", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "aws": {} }, "encryptedFieldsMap": { "default.encryptedCollection": { "fields": [ { "path": "firstName", "bsonType": "string", "keyId": { "$binary": { "subType": "04", "base64": "AAAAAAAAAAAAAAAAAAAAAA==" } } } ] } } } }, "operations": [ { "name": "dropCollection", "object": "database", "arguments": { "collection": "plaintextCollection" } }, { "name": "createCollection", "object": "database", "arguments": { "collection": "plaintextCollection" } }, { "name": "assertCollectionExists", "object": "testRunner", "arguments": { "database": "default", "collection": "plaintextCollection" } } ], "expectations": [ { "command_started_event": { "command": { "listCollections": 1, "filter": { "name": "plaintextCollection" } }, "command_name": "listCollections", "database_name": "default" } }, { "command_started_event": { "command": { "drop": "plaintextCollection" }, "command_name": "drop", "database_name": "default" } }, { "command_started_event": { "command": { "create": "plaintextCollection" }, "command_name": "create", "database_name": "default" } } ] }, { "description": "CreateCollection from encryptedFieldsMap.", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "aws": {} }, "encryptedFieldsMap": { "default.encryptedCollection": { "fields": [ { "path": "firstName", "bsonType": "string", "keyId": { "$binary": { "subType": "04", "base64": "AAAAAAAAAAAAAAAAAAAAAA==" } } } ] } } } }, "operations": [ { "name": "dropCollection", "object": "database", "arguments": { "collection": "encryptedCollection" } }, { "name": "createCollection", "object": "database", "arguments": { "collection": "encryptedCollection" } }, { "name": "assertCollectionExists", "object": "testRunner", "arguments": { "database": "default", "collection": "enxcol_.encryptedCollection.esc" } }, { "name": "assertCollectionNotExists", "object": "testRunner", "arguments": { "database": "default", "collection": "enxcol_.encryptedCollection.ecc" } }, { "name": "assertCollectionExists", "object": "testRunner", "arguments": { "database": "default", "collection": "enxcol_.encryptedCollection.ecoc" } }, { "name": "assertCollectionExists", "object": "testRunner", "arguments": { "database": "default", "collection": "encryptedCollection" } }, { "name": "assertIndexExists", "object": "testRunner", "arguments": { "database": "default", "collection": "encryptedCollection", "index": "__safeContent___1" } } ], "expectations": [ { "command_started_event": { "command": { "drop": "enxcol_.encryptedCollection.esc" }, "command_name": "drop", "database_name": "default" } }, { "command_started_event": { "command": { "drop": "enxcol_.encryptedCollection.ecoc" }, "command_name": "drop", "database_name": "default" } }, { "command_started_event": { "command": { "drop": "encryptedCollection" }, "command_name": "drop", "database_name": "default" } }, { "command_started_event": { "command": { "create": "enxcol_.encryptedCollection.esc", "clusteredIndex": { "key": { "_id": 1 }, "unique": true } }, "command_name": "create", "database_name": "default" } }, { "command_started_event": { "command": { "create": "enxcol_.encryptedCollection.ecoc", "clusteredIndex": { "key": { "_id": 1 }, "unique": true } }, "command_name": "create", "database_name": "default" } }, { "command_started_event": { "command": { "create": "encryptedCollection", "encryptedFields": { "fields": [ { "path": "firstName", "bsonType": "string", "keyId": { "$binary": { "subType": "04", "base64": "AAAAAAAAAAAAAAAAAAAAAA==" } } } ] } }, "command_name": "create", "database_name": "default" } }, { "command_started_event": { "command": { "createIndexes": "encryptedCollection", "indexes": [ { "name": "__safeContent___1", "key": { "__safeContent__": 1 } } ] }, "command_name": "createIndexes", "database_name": "default" } } ] }, { "description": "CreateCollection from encryptedFields.", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "aws": {} } } }, "operations": [ { "name": "dropCollection", "object": "database", "arguments": { "collection": "encryptedCollection", "encryptedFields": { "fields": [ { "path": "firstName", "bsonType": "string", "keyId": { "$binary": { "subType": "04", "base64": "AAAAAAAAAAAAAAAAAAAAAA==" } } } ] } } }, { "name": "createCollection", "object": "database", "arguments": { "collection": "encryptedCollection", "encryptedFields": { "fields": [ { "path": "firstName", "bsonType": "string", "keyId": { "$binary": { "subType": "04", "base64": "AAAAAAAAAAAAAAAAAAAAAA==" } } } ] } } }, { "name": "assertCollectionExists", "object": "testRunner", "arguments": { "database": "default", "collection": "enxcol_.encryptedCollection.esc" } }, { "name": "assertCollectionNotExists", "object": "testRunner", "arguments": { "database": "default", "collection": "enxcol_.encryptedCollection.ecc" } }, { "name": "assertCollectionExists", "object": "testRunner", "arguments": { "database": "default", "collection": "enxcol_.encryptedCollection.ecoc" } }, { "name": "assertCollectionExists", "object": "testRunner", "arguments": { "database": "default", "collection": "encryptedCollection" } }, { "name": "assertIndexExists", "object": "testRunner", "arguments": { "database": "default", "collection": "encryptedCollection", "index": "__safeContent___1" } } ], "expectations": [ { "command_started_event": { "command": { "drop": "enxcol_.encryptedCollection.esc" }, "command_name": "drop", "database_name": "default" } }, { "command_started_event": { "command": { "drop": "enxcol_.encryptedCollection.ecoc" }, "command_name": "drop", "database_name": "default" } }, { "command_started_event": { "command": { "drop": "encryptedCollection" }, "command_name": "drop", "database_name": "default" } }, { "command_started_event": { "command": { "create": "enxcol_.encryptedCollection.esc", "clusteredIndex": { "key": { "_id": 1 }, "unique": true } }, "command_name": "create", "database_name": "default" } }, { "command_started_event": { "command": { "create": "enxcol_.encryptedCollection.ecoc", "clusteredIndex": { "key": { "_id": 1 }, "unique": true } }, "command_name": "create", "database_name": "default" } }, { "command_started_event": { "command": { "create": "encryptedCollection", "encryptedFields": { "fields": [ { "path": "firstName", "bsonType": "string", "keyId": { "$binary": { "subType": "04", "base64": "AAAAAAAAAAAAAAAAAAAAAA==" } } } ] } }, "command_name": "create", "database_name": "default" } }, { "command_started_event": { "command": { "listCollections": 1, "filter": { "name": "encryptedCollection" } }, "command_name": "listCollections", "database_name": "default" } }, { "command_started_event": { "command": { "createIndexes": "encryptedCollection", "indexes": [ { "name": "__safeContent___1", "key": { "__safeContent__": 1 } } ] }, "command_name": "createIndexes", "database_name": "default" } } ] }, { "description": "DropCollection from encryptedFieldsMap", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "aws": {} }, "encryptedFieldsMap": { "default.encryptedCollection": { "fields": [ { "path": "firstName", "bsonType": "string", "keyId": { "$binary": { "subType": "04", "base64": "AAAAAAAAAAAAAAAAAAAAAA==" } } } ] } } } }, "operations": [ { "name": "dropCollection", "object": "database", "arguments": { "collection": "encryptedCollection" } } ], "expectations": [ { "command_started_event": { "command": { "drop": "enxcol_.encryptedCollection.esc" }, "command_name": "drop", "database_name": "default" } }, { "command_started_event": { "command": { "drop": "enxcol_.encryptedCollection.ecoc" }, "command_name": "drop", "database_name": "default" } }, { "command_started_event": { "command": { "drop": "encryptedCollection" }, "command_name": "drop", "database_name": "default" } } ] }, { "description": "DropCollection from encryptedFields", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "aws": {} }, "encryptedFieldsMap": {} } }, "operations": [ { "name": "dropCollection", "object": "database", "arguments": { "collection": "encryptedCollection", "encryptedFields": { "fields": [ { "path": "firstName", "bsonType": "string", "keyId": { "$binary": { "subType": "04", "base64": "AAAAAAAAAAAAAAAAAAAAAA==" } } } ] } } }, { "name": "createCollection", "object": "database", "arguments": { "collection": "encryptedCollection", "encryptedFields": { "fields": [ { "path": "firstName", "bsonType": "string", "keyId": { "$binary": { "subType": "04", "base64": "AAAAAAAAAAAAAAAAAAAAAA==" } } } ] } } }, { "name": "assertCollectionExists", "object": "testRunner", "arguments": { "database": "default", "collection": "enxcol_.encryptedCollection.esc" } }, { "name": "assertCollectionNotExists", "object": "testRunner", "arguments": { "database": "default", "collection": "enxcol_.encryptedCollection.ecc" } }, { "name": "assertCollectionExists", "object": "testRunner", "arguments": { "database": "default", "collection": "enxcol_.encryptedCollection.ecoc" } }, { "name": "assertCollectionExists", "object": "testRunner", "arguments": { "database": "default", "collection": "encryptedCollection" } }, { "name": "assertIndexExists", "object": "testRunner", "arguments": { "database": "default", "collection": "encryptedCollection", "index": "__safeContent___1" } }, { "name": "dropCollection", "object": "database", "arguments": { "collection": "encryptedCollection", "encryptedFields": { "fields": [ { "path": "firstName", "bsonType": "string", "keyId": { "$binary": { "subType": "04", "base64": "AAAAAAAAAAAAAAAAAAAAAA==" } } } ] } } }, { "name": "assertCollectionNotExists", "object": "testRunner", "arguments": { "database": "default", "collection": "enxcol_.encryptedCollection.esc" } }, { "name": "assertCollectionNotExists", "object": "testRunner", "arguments": { "database": "default", "collection": "enxcol_.encryptedCollection.ecoc" } }, { "name": "assertCollectionNotExists", "object": "testRunner", "arguments": { "database": "default", "collection": "encryptedCollection" } } ], "expectations": [ { "command_started_event": { "command": { "drop": "enxcol_.encryptedCollection.esc" }, "command_name": "drop", "database_name": "default" } }, { "command_started_event": { "command": { "drop": "enxcol_.encryptedCollection.ecoc" }, "command_name": "drop", "database_name": "default" } }, { "command_started_event": { "command": { "drop": "encryptedCollection" }, "command_name": "drop", "database_name": "default" } }, { "command_started_event": { "command": { "create": "enxcol_.encryptedCollection.esc", "clusteredIndex": { "key": { "_id": 1 }, "unique": true } }, "command_name": "create", "database_name": "default" } }, { "command_started_event": { "command": { "create": "enxcol_.encryptedCollection.ecoc", "clusteredIndex": { "key": { "_id": 1 }, "unique": true } }, "command_name": "create", "database_name": "default" } }, { "command_started_event": { "command": { "create": "encryptedCollection", "encryptedFields": { "fields": [ { "path": "firstName", "bsonType": "string", "keyId": { "$binary": { "subType": "04", "base64": "AAAAAAAAAAAAAAAAAAAAAA==" } } } ] } }, "command_name": "create", "database_name": "default" } }, { "command_started_event": { "command": { "listCollections": 1, "filter": { "name": "encryptedCollection" } }, "command_name": "listCollections", "database_name": "default" } }, { "command_started_event": { "command": { "createIndexes": "encryptedCollection", "indexes": [ { "name": "__safeContent___1", "key": { "__safeContent__": 1 } } ] }, "command_name": "createIndexes", "database_name": "default" } }, { "command_started_event": { "command": { "drop": "enxcol_.encryptedCollection.esc" }, "command_name": "drop", "database_name": "default" } }, { "command_started_event": { "command": { "drop": "enxcol_.encryptedCollection.ecoc" }, "command_name": "drop", "database_name": "default" } }, { "command_started_event": { "command": { "drop": "encryptedCollection" }, "command_name": "drop", "database_name": "default" } } ] }, { "description": "DropCollection from remote encryptedFields", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "aws": {} }, "encryptedFieldsMap": {} } }, "operations": [ { "name": "dropCollection", "object": "database", "arguments": { "collection": "encryptedCollection", "encryptedFields": { "fields": [ { "path": "firstName", "bsonType": "string", "keyId": { "$binary": { "subType": "04", "base64": "AAAAAAAAAAAAAAAAAAAAAA==" } } } ] } } }, { "name": "createCollection", "object": "database", "arguments": { "collection": "encryptedCollection", "encryptedFields": { "fields": [ { "path": "firstName", "bsonType": "string", "keyId": { "$binary": { "subType": "04", "base64": "AAAAAAAAAAAAAAAAAAAAAA==" } } } ] } } }, { "name": "assertCollectionExists", "object": "testRunner", "arguments": { "database": "default", "collection": "enxcol_.encryptedCollection.esc" } }, { "name": "assertCollectionNotExists", "object": "testRunner", "arguments": { "database": "default", "collection": "enxcol_.encryptedCollection.ecc" } }, { "name": "assertCollectionExists", "object": "testRunner", "arguments": { "database": "default", "collection": "enxcol_.encryptedCollection.ecoc" } }, { "name": "assertCollectionExists", "object": "testRunner", "arguments": { "database": "default", "collection": "encryptedCollection" } }, { "name": "assertIndexExists", "object": "testRunner", "arguments": { "database": "default", "collection": "encryptedCollection", "index": "__safeContent___1" } }, { "name": "dropCollection", "object": "database", "arguments": { "collection": "encryptedCollection" } }, { "name": "assertCollectionNotExists", "object": "testRunner", "arguments": { "database": "default", "collection": "enxcol_.encryptedCollection.esc" } }, { "name": "assertCollectionNotExists", "object": "testRunner", "arguments": { "database": "default", "collection": "enxcol_.encryptedCollection.ecoc" } }, { "name": "assertCollectionNotExists", "object": "testRunner", "arguments": { "database": "default", "collection": "encryptedCollection" } } ], "expectations": [ { "command_started_event": { "command": { "drop": "enxcol_.encryptedCollection.esc" }, "command_name": "drop", "database_name": "default" } }, { "command_started_event": { "command": { "drop": "enxcol_.encryptedCollection.ecoc" }, "command_name": "drop", "database_name": "default" } }, { "command_started_event": { "command": { "drop": "encryptedCollection" }, "command_name": "drop", "database_name": "default" } }, { "command_started_event": { "command": { "create": "enxcol_.encryptedCollection.esc", "clusteredIndex": { "key": { "_id": 1 }, "unique": true } }, "command_name": "create", "database_name": "default" } }, { "command_started_event": { "command": { "create": "enxcol_.encryptedCollection.ecoc", "clusteredIndex": { "key": { "_id": 1 }, "unique": true } }, "command_name": "create", "database_name": "default" } }, { "command_started_event": { "command": { "create": "encryptedCollection", "encryptedFields": { "fields": [ { "path": "firstName", "bsonType": "string", "keyId": { "$binary": { "subType": "04", "base64": "AAAAAAAAAAAAAAAAAAAAAA==" } } } ] } }, "command_name": "create", "database_name": "default" } }, { "command_started_event": { "command": { "listCollections": 1, "filter": { "name": "encryptedCollection" } }, "command_name": "listCollections", "database_name": "default" } }, { "command_started_event": { "command": { "createIndexes": "encryptedCollection", "indexes": [ { "name": "__safeContent___1", "key": { "__safeContent__": 1 } } ] }, "command_name": "createIndexes", "database_name": "default" } }, { "command_started_event": { "command": { "listCollections": 1, "filter": { "name": "encryptedCollection" } }, "command_name": "listCollections", "database_name": "default" } }, { "command_started_event": { "command": { "drop": "enxcol_.encryptedCollection.esc" }, "command_name": "drop", "database_name": "default" } }, { "command_started_event": { "command": { "drop": "enxcol_.encryptedCollection.ecoc" }, "command_name": "drop", "database_name": "default" } }, { "command_started_event": { "command": { "drop": "encryptedCollection" }, "command_name": "drop", "database_name": "default" } } ] }, { "description": "encryptedFields are consulted for metadata collection names", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "aws": {} }, "encryptedFieldsMap": { "default.encryptedCollection": { "escCollection": "invalid_esc_name", "ecocCollection": "invalid_ecoc_name", "fields": [ { "path": "firstName", "bsonType": "string", "keyId": { "$binary": { "subType": "04", "base64": "AAAAAAAAAAAAAAAAAAAAAA==" } } } ] } } } }, "operations": [ { "name": "dropCollection", "object": "database", "arguments": { "collection": "encryptedCollection" } }, { "name": "createCollection", "object": "database", "arguments": { "collection": "encryptedCollection" }, "result": { "errorContains": "Encrypted State Collection name should follow" } } ] } ] } fle2v2-DecryptExistingData.json000066400000000000000000000067621462766011000350460ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/client-side-encryption/spec/legacy{ "runOn": [ { "minServerVersion": "7.0.0", "topology": [ "replicaset", "sharded", "load-balanced" ] } ], "database_name": "default", "collection_name": "default", "data": [ { "_id": 1, "encryptedUnindexed": { "$binary": { "base64": "BqvN76sSNJh2EjQSNFZ4kBICTQaVZPWgXp41I7mPV1rLFTtw1tXzjcdSEyxpKKqujlko5TeizkB9hHQ009dVY1+fgIiDcefh+eQrm3CkhQ==", "subType": "06" } } } ], "key_vault_data": [ { "_id": { "$binary": { "base64": "q83vqxI0mHYSNBI0VniQEg==", "subType": "04" } }, "keyMaterial": { "$binary": { "base64": "HBk9BWihXExNDvTp1lUxOuxuZK2Pe2ZdVdlsxPEBkiO1bS4mG5NNDsQ7zVxJAH8BtdOYp72Ku4Y3nwc0BUpIKsvAKX4eYXtlhv5zUQxWdeNFhg9qK7qb8nqhnnLeT0f25jFSqzWJoT379hfwDeu0bebJHr35QrJ8myZdPMTEDYF08QYQ48ShRBli0S+QzBHHAQiM2iJNr4svg2WR8JSeWQ==", "subType": "00" } }, "creationDate": { "$date": { "$numberLong": "1648914851981" } }, "updateDate": { "$date": { "$numberLong": "1648914851981" } }, "status": { "$numberInt": "0" }, "masterKey": { "provider": "local" } } ], "tests": [ { "description": "FLE2 decrypt of existing data succeeds", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "local": { "key": { "$binary": { "base64": "Mng0NCt4ZHVUYUJCa1kxNkVyNUR1QURhZ2h2UzR2d2RrZzh0cFBwM3R6NmdWMDFBMUN3YkQ5aXRRMkhGRGdQV09wOGVNYUMxT2k3NjZKelhaQmRCZGJkTXVyZG9uSjFk", "subType": "00" } } } } } }, "operations": [ { "name": "find", "arguments": { "filter": { "_id": 1 } }, "result": [ { "_id": 1, "encryptedUnindexed": "value123" } ] } ], "expectations": [ { "command_started_event": { "command": { "listCollections": 1, "filter": { "name": "default" } }, "command_name": "listCollections" } }, { "command_started_event": { "command": { "find": "default", "filter": { "_id": 1 } }, "command_name": "find" } }, { "command_started_event": { "command": { "find": "datakeys", "filter": { "$or": [ { "_id": { "$in": [ { "$binary": { "base64": "q83vqxI0mHYSNBI0VniQEg==", "subType": "04" } } ] } }, { "keyAltNames": { "$in": [] } } ] }, "$db": "keyvault", "readConcern": { "level": "majority" } }, "command_name": "find" } } ] } ] } mongodb-mongo-python-driver-509e9b7/test/client-side-encryption/spec/legacy/fle2v2-Delete.json000066400000000000000000000173571462766011000324120ustar00rootroot00000000000000{ "runOn": [ { "minServerVersion": "7.0.0", "topology": [ "replicaset", "sharded", "load-balanced" ] } ], "database_name": "default", "collection_name": "default", "data": [], "encrypted_fields": { "fields": [ { "keyId": { "$binary": { "base64": "EjRWeBI0mHYSNBI0VniQEg==", "subType": "04" } }, "path": "encryptedIndexed", "bsonType": "string", "queries": { "queryType": "equality", "contention": { "$numberLong": "0" } } }, { "keyId": { "$binary": { "base64": "q83vqxI0mHYSNBI0VniQEg==", "subType": "04" } }, "path": "encryptedUnindexed", "bsonType": "string" } ] }, "key_vault_data": [ { "_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" } } ], "tests": [ { "description": "Delete can query an FLE2 indexed field", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "local": { "key": { "$binary": { "base64": "Mng0NCt4ZHVUYUJCa1kxNkVyNUR1QURhZ2h2UzR2d2RrZzh0cFBwM3R6NmdWMDFBMUN3YkQ5aXRRMkhGRGdQV09wOGVNYUMxT2k3NjZKelhaQmRCZGJkTXVyZG9uSjFk", "subType": "00" } } } } } }, "operations": [ { "name": "insertOne", "arguments": { "document": { "_id": 1, "encryptedIndexed": "value123" } } }, { "name": "deleteOne", "arguments": { "filter": { "encryptedIndexed": "value123" } }, "result": { "deletedCount": 1 } } ], "expectations": [ { "command_started_event": { "command": { "listCollections": 1, "filter": { "name": "default" } }, "command_name": "listCollections" } }, { "command_started_event": { "command": { "find": "datakeys", "filter": { "$or": [ { "_id": { "$in": [ { "$binary": { "base64": "EjRWeBI0mHYSNBI0VniQEg==", "subType": "04" } } ] } }, { "keyAltNames": { "$in": [] } } ] }, "$db": "keyvault", "readConcern": { "level": "majority" } }, "command_name": "find" } }, { "command_started_event": { "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" } } }, { "keyId": { "$binary": { "base64": "q83vqxI0mHYSNBI0VniQEg==", "subType": "04" } }, "path": "encryptedUnindexed", "bsonType": "string" } ] } } } }, "command_name": "insert" } }, { "command_started_event": { "command": { "delete": "default", "deletes": [ { "q": { "encryptedIndexed": { "$eq": { "$binary": { "base64": "DIkAAAAFZAAgAAAAAPtVteJQAlgb2YMa/+7YWH00sbQPyt7L6Rb8OwBdMmL2BXMAIAAAAAAd44hgVKnEnTFlwNVC14oyc9OZOTspeymusqkRQj57nAVsACAAAAAAaZ9s3G+4znfxStxeOZwcZy1OhzjMGc5hjmdMN+b/w6kSY20AAAAAAAAAAAAA", "subType": "06" } } } }, "limit": 1 } ], "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" } } }, { "keyId": { "$binary": { "base64": "q83vqxI0mHYSNBI0VniQEg==", "subType": "04" } }, "path": "encryptedUnindexed", "bsonType": "string" } ] } } } }, "command_name": "delete" } } ], "outcome": { "collection": { "data": [] } } } ] } fle2v2-EncryptedFields-vs-EncryptedFieldsMap.json000066400000000000000000000122561462766011000403540ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/client-side-encryption/spec/legacy{ "runOn": [ { "minServerVersion": "7.0.0", "topology": [ "replicaset", "sharded", "load-balanced" ] } ], "database_name": "default", "collection_name": "default", "data": [], "encrypted_fields": { "fields": [ { "keyId": { "$binary": { "base64": "EjRWeBI0mHYSNBI0VniQEg==", "subType": "04" } }, "path": "encryptedIndexed", "bsonType": "string", "queries": { "queryType": "equality", "contention": { "$numberLong": "0" } } }, { "keyId": { "$binary": { "base64": "q83vqxI0mHYSNBI0VniQEg==", "subType": "04" } }, "path": "encryptedUnindexed", "bsonType": "string" } ] }, "key_vault_data": [ { "_id": { "$binary": { "base64": "q83vqxI0mHYSNBI0VniQEg==", "subType": "04" } }, "keyMaterial": { "$binary": { "base64": "HBk9BWihXExNDvTp1lUxOuxuZK2Pe2ZdVdlsxPEBkiO1bS4mG5NNDsQ7zVxJAH8BtdOYp72Ku4Y3nwc0BUpIKsvAKX4eYXtlhv5zUQxWdeNFhg9qK7qb8nqhnnLeT0f25jFSqzWJoT379hfwDeu0bebJHr35QrJ8myZdPMTEDYF08QYQ48ShRBli0S+QzBHHAQiM2iJNr4svg2WR8JSeWQ==", "subType": "00" } }, "creationDate": { "$date": { "$numberLong": "1648914851981" } }, "updateDate": { "$date": { "$numberLong": "1648914851981" } }, "status": { "$numberInt": "0" }, "masterKey": { "provider": "local" } } ], "tests": [ { "description": "encryptedFieldsMap is preferred over remote encryptedFields", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "local": { "key": { "$binary": { "base64": "Mng0NCt4ZHVUYUJCa1kxNkVyNUR1QURhZ2h2UzR2d2RrZzh0cFBwM3R6NmdWMDFBMUN3YkQ5aXRRMkhGRGdQV09wOGVNYUMxT2k3NjZKelhaQmRCZGJkTXVyZG9uSjFk", "subType": "00" } } } }, "encryptedFieldsMap": { "default.default": { "fields": [] } } } }, "operations": [ { "name": "insertOne", "arguments": { "document": { "_id": 1, "encryptedUnindexed": { "$binary": { "base64": "BqvN76sSNJh2EjQSNFZ4kBICTQaVZPWgXp41I7mPV1rLFTtw1tXzjcdSEyxpKKqujlko5TeizkB9hHQ009dVY1+fgIiDcefh+eQrm3CkhQ==", "subType": "06" } } } } }, { "name": "find", "arguments": { "filter": { "_id": 1 } }, "result": [ { "_id": 1, "encryptedUnindexed": "value123" } ] } ], "expectations": [ { "command_started_event": { "command": { "insert": "default", "documents": [ { "_id": 1, "encryptedUnindexed": { "$binary": { "base64": "BqvN76sSNJh2EjQSNFZ4kBICTQaVZPWgXp41I7mPV1rLFTtw1tXzjcdSEyxpKKqujlko5TeizkB9hHQ009dVY1+fgIiDcefh+eQrm3CkhQ==", "subType": "06" } } } ], "ordered": true }, "command_name": "insert" } }, { "command_started_event": { "command": { "find": "default", "filter": { "_id": 1 } }, "command_name": "find" } }, { "command_started_event": { "command": { "find": "datakeys", "filter": { "$or": [ { "_id": { "$in": [ { "$binary": { "base64": "q83vqxI0mHYSNBI0VniQEg==", "subType": "04" } } ] } }, { "keyAltNames": { "$in": [] } } ] }, "$db": "keyvault", "readConcern": { "level": "majority" } }, "command_name": "find" } } ], "outcome": { "collection": { "data": [ { "_id": 1, "encryptedUnindexed": { "$binary": { "base64": "BqvN76sSNJh2EjQSNFZ4kBICTQaVZPWgXp41I7mPV1rLFTtw1tXzjcdSEyxpKKqujlko5TeizkB9hHQ009dVY1+fgIiDcefh+eQrm3CkhQ==", "subType": "06" } } } ] } } } ] } fle2v2-EncryptedFields-vs-jsonSchema.json000066400000000000000000000201141462766011000367140ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/client-side-encryption/spec/legacy{ "runOn": [ { "minServerVersion": "7.0.0", "topology": [ "replicaset", "sharded", "load-balanced" ] } ], "database_name": "default", "collection_name": "default", "data": [], "json_schema": { "properties": {}, "bsonType": "object" }, "encrypted_fields": { "fields": [ { "keyId": { "$binary": { "base64": "EjRWeBI0mHYSNBI0VniQEg==", "subType": "04" } }, "path": "encryptedIndexed", "bsonType": "string", "queries": { "queryType": "equality", "contention": { "$numberLong": "0" } } }, { "keyId": { "$binary": { "base64": "q83vqxI0mHYSNBI0VniQEg==", "subType": "04" } }, "path": "encryptedUnindexed", "bsonType": "string" } ] }, "key_vault_data": [ { "_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" } } ], "tests": [ { "description": "encryptedFields is preferred over jsonSchema", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "local": { "key": { "$binary": { "base64": "Mng0NCt4ZHVUYUJCa1kxNkVyNUR1QURhZ2h2UzR2d2RrZzh0cFBwM3R6NmdWMDFBMUN3YkQ5aXRRMkhGRGdQV09wOGVNYUMxT2k3NjZKelhaQmRCZGJkTXVyZG9uSjFk", "subType": "00" } } } } } }, "operations": [ { "name": "insertOne", "arguments": { "document": { "_id": 1, "encryptedIndexed": "123" } } }, { "name": "find", "arguments": { "filter": { "encryptedIndexed": "123" } }, "result": [ { "_id": 1, "encryptedIndexed": "123" } ] } ], "expectations": [ { "command_started_event": { "command": { "listCollections": 1, "filter": { "name": "default" } }, "command_name": "listCollections" } }, { "command_started_event": { "command": { "find": "datakeys", "filter": { "$or": [ { "_id": { "$in": [ { "$binary": { "base64": "EjRWeBI0mHYSNBI0VniQEg==", "subType": "04" } } ] } }, { "keyAltNames": { "$in": [] } } ] }, "$db": "keyvault", "readConcern": { "level": "majority" } }, "command_name": "find" } }, { "command_started_event": { "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" } } }, { "keyId": { "$binary": { "base64": "q83vqxI0mHYSNBI0VniQEg==", "subType": "04" } }, "path": "encryptedUnindexed", "bsonType": "string" } ] } } } }, "command_name": "insert" } }, { "command_started_event": { "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" } } }, { "keyId": { "$binary": { "base64": "q83vqxI0mHYSNBI0VniQEg==", "subType": "04" } }, "path": "encryptedUnindexed", "bsonType": "string" } ] } } } }, "command_name": "find" } } ], "outcome": { "collection": { "data": [ { "_id": 1, "encryptedIndexed": { "$$type": "binData" }, "__safeContent__": [ { "$binary": { "base64": "31eCYlbQoVboc5zwC8IoyJVSkag9PxREka8dkmbXJeY=", "subType": "00" } } ] } ] } } } ] } fle2v2-EncryptedFieldsMap-defaults.json000066400000000000000000000057421462766011000364530ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/client-side-encryption/spec/legacy{ "runOn": [ { "minServerVersion": "7.0.0", "topology": [ "replicaset", "sharded", "load-balanced" ] } ], "database_name": "default", "collection_name": "default", "data": [], "key_vault_data": [], "tests": [ { "description": "default state collections are applied to encryptionInformation", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "local": { "key": { "$binary": { "base64": "Mng0NCt4ZHVUYUJCa1kxNkVyNUR1QURhZ2h2UzR2d2RrZzh0cFBwM3R6NmdWMDFBMUN3YkQ5aXRRMkhGRGdQV09wOGVNYUMxT2k3NjZKelhaQmRCZGJkTXVyZG9uSjFk", "subType": "00" } } } }, "encryptedFieldsMap": { "default.default": { "fields": [] } } } }, "operations": [ { "name": "insertOne", "arguments": { "document": { "_id": 1, "foo": { "$binary": { "base64": "BYkAAAAFZAAgAAAAAE8KGPgq7h3n9nH5lfHcia8wtOTLwGkZNLBesb6PULqbBXMAIAAAAACq0558QyD3c3jkR5k0Zc9UpQK8ByhXhtn2d1xVQnuJ3AVjACAAAAAA1003zUWGwD4zVZ0KeihnZOthS3V6CEHUfnJZcIYHefISY20AAAAAAAAAAAAA", "subType": "06" } } } } } ], "expectations": [ { "command_started_event": { "command": { "insert": "default", "documents": [ { "_id": 1, "foo": { "$binary": { "base64": "BYkAAAAFZAAgAAAAAE8KGPgq7h3n9nH5lfHcia8wtOTLwGkZNLBesb6PULqbBXMAIAAAAACq0558QyD3c3jkR5k0Zc9UpQK8ByhXhtn2d1xVQnuJ3AVjACAAAAAA1003zUWGwD4zVZ0KeihnZOthS3V6CEHUfnJZcIYHefISY20AAAAAAAAAAAAA", "subType": "06" } } } ], "encryptionInformation": { "type": { "$numberInt": "1" }, "schema": { "default.default": { "escCollection": "enxcol_.default.esc", "ecocCollection": "enxcol_.default.ecoc", "fields": [] } } }, "ordered": true }, "command_name": "insert" } } ], "outcome": { "collection": { "data": [ { "_id": 1, "foo": { "$binary": { "base64": "BYkAAAAFZAAgAAAAAE8KGPgq7h3n9nH5lfHcia8wtOTLwGkZNLBesb6PULqbBXMAIAAAAACq0558QyD3c3jkR5k0Zc9UpQK8ByhXhtn2d1xVQnuJ3AVjACAAAAAA1003zUWGwD4zVZ0KeihnZOthS3V6CEHUfnJZcIYHefISY20AAAAAAAAAAAAA", "subType": "06" } } } ] } } } ] } fle2v2-FindOneAndUpdate.json000066400000000000000000000370521462766011000342330ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/client-side-encryption/spec/legacy{ "runOn": [ { "minServerVersion": "7.0.0", "topology": [ "replicaset", "sharded", "load-balanced" ] } ], "database_name": "default", "collection_name": "default", "data": [], "encrypted_fields": { "fields": [ { "keyId": { "$binary": { "base64": "EjRWeBI0mHYSNBI0VniQEg==", "subType": "04" } }, "path": "encryptedIndexed", "bsonType": "string", "queries": { "queryType": "equality", "contention": { "$numberLong": "0" } } }, { "keyId": { "$binary": { "base64": "q83vqxI0mHYSNBI0VniQEg==", "subType": "04" } }, "path": "encryptedUnindexed", "bsonType": "string" } ] }, "key_vault_data": [ { "_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" } } ], "tests": [ { "description": "findOneAndUpdate can query an FLE2 indexed field", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "local": { "key": { "$binary": { "base64": "Mng0NCt4ZHVUYUJCa1kxNkVyNUR1QURhZ2h2UzR2d2RrZzh0cFBwM3R6NmdWMDFBMUN3YkQ5aXRRMkhGRGdQV09wOGVNYUMxT2k3NjZKelhaQmRCZGJkTXVyZG9uSjFk", "subType": "00" } } } } } }, "operations": [ { "name": "insertOne", "arguments": { "document": { "_id": 1, "encryptedIndexed": "value123" } } }, { "name": "findOneAndUpdate", "arguments": { "filter": { "encryptedIndexed": "value123" }, "update": { "$set": { "foo": "bar" } }, "returnDocument": "Before" }, "result": { "_id": 1, "encryptedIndexed": "value123" } } ], "expectations": [ { "command_started_event": { "command": { "listCollections": 1, "filter": { "name": "default" } }, "command_name": "listCollections" } }, { "command_started_event": { "command": { "find": "datakeys", "filter": { "$or": [ { "_id": { "$in": [ { "$binary": { "base64": "EjRWeBI0mHYSNBI0VniQEg==", "subType": "04" } } ] } }, { "keyAltNames": { "$in": [] } } ] }, "$db": "keyvault", "readConcern": { "level": "majority" } }, "command_name": "find" } }, { "command_started_event": { "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" } } }, { "keyId": { "$binary": { "base64": "q83vqxI0mHYSNBI0VniQEg==", "subType": "04" } }, "path": "encryptedUnindexed", "bsonType": "string" } ] } } } }, "command_name": "insert" } }, { "command_started_event": { "command": { "findAndModify": "default", "query": { "encryptedIndexed": { "$eq": { "$binary": { "base64": "DIkAAAAFZAAgAAAAAPtVteJQAlgb2YMa/+7YWH00sbQPyt7L6Rb8OwBdMmL2BXMAIAAAAAAd44hgVKnEnTFlwNVC14oyc9OZOTspeymusqkRQj57nAVsACAAAAAAaZ9s3G+4znfxStxeOZwcZy1OhzjMGc5hjmdMN+b/w6kSY20AAAAAAAAAAAAA", "subType": "06" } } } }, "update": { "$set": { "foo": "bar" } }, "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" } } }, { "keyId": { "$binary": { "base64": "q83vqxI0mHYSNBI0VniQEg==", "subType": "04" } }, "path": "encryptedUnindexed", "bsonType": "string" } ] } } } }, "command_name": "findAndModify" } } ], "outcome": { "collection": { "data": [ { "_id": 1, "encryptedIndexed": { "$$type": "binData" }, "foo": "bar", "__safeContent__": [ { "$binary": { "base64": "ThpoKfQ8AkOzkFfNC1+9PF0pY2nIzfXvRdxQgjkNbBw=", "subType": "00" } } ] } ] } } }, { "description": "findOneAndUpdate can modify an FLE2 indexed field", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "local": { "key": { "$binary": { "base64": "Mng0NCt4ZHVUYUJCa1kxNkVyNUR1QURhZ2h2UzR2d2RrZzh0cFBwM3R6NmdWMDFBMUN3YkQ5aXRRMkhGRGdQV09wOGVNYUMxT2k3NjZKelhaQmRCZGJkTXVyZG9uSjFk", "subType": "00" } } } } } }, "operations": [ { "name": "insertOne", "arguments": { "document": { "_id": 1, "encryptedIndexed": "value123" } } }, { "name": "findOneAndUpdate", "arguments": { "filter": { "encryptedIndexed": "value123" }, "update": { "$set": { "encryptedIndexed": "value456" } }, "returnDocument": "Before" }, "result": { "_id": 1, "encryptedIndexed": "value123" } }, { "name": "find", "arguments": { "filter": { "_id": 1 } }, "result": [ { "encryptedIndexed": "value456" } ] } ], "expectations": [ { "command_started_event": { "command": { "listCollections": 1, "filter": { "name": "default" } }, "command_name": "listCollections" } }, { "command_started_event": { "command": { "find": "datakeys", "filter": { "$or": [ { "_id": { "$in": [ { "$binary": { "base64": "EjRWeBI0mHYSNBI0VniQEg==", "subType": "04" } } ] } }, { "keyAltNames": { "$in": [] } } ] }, "$db": "keyvault", "readConcern": { "level": "majority" } }, "command_name": "find" } }, { "command_started_event": { "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" } } }, { "keyId": { "$binary": { "base64": "q83vqxI0mHYSNBI0VniQEg==", "subType": "04" } }, "path": "encryptedUnindexed", "bsonType": "string" } ] } } } }, "command_name": "insert" } }, { "command_started_event": { "command": { "findAndModify": "default", "query": { "encryptedIndexed": { "$eq": { "$binary": { "base64": "DIkAAAAFZAAgAAAAAPtVteJQAlgb2YMa/+7YWH00sbQPyt7L6Rb8OwBdMmL2BXMAIAAAAAAd44hgVKnEnTFlwNVC14oyc9OZOTspeymusqkRQj57nAVsACAAAAAAaZ9s3G+4znfxStxeOZwcZy1OhzjMGc5hjmdMN+b/w6kSY20AAAAAAAAAAAAA", "subType": "06" } } } }, "update": { "$set": { "encryptedIndexed": { "$$type": "binData" } } }, "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" } } }, { "keyId": { "$binary": { "base64": "q83vqxI0mHYSNBI0VniQEg==", "subType": "04" } }, "path": "encryptedUnindexed", "bsonType": "string" } ] } } } }, "command_name": "findAndModify" } }, { "command_started_event": { "command": { "find": "default", "filter": { "_id": { "$eq": 1 } } }, "command_name": "find" } } ], "outcome": { "collection": { "data": [ { "_id": 1, "encryptedIndexed": { "$$type": "binData" }, "__safeContent__": [ { "$binary": { "base64": "rhe7/w8Ob8Unl44rGr/moScx6m5VODQnscDhF4Nkn6g=", "subType": "00" } } ] } ] } } } ] } fle2v2-InsertFind-Indexed.json000066400000000000000000000177731462766011000345560ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/client-side-encryption/spec/legacy{ "runOn": [ { "minServerVersion": "7.0.0", "topology": [ "replicaset", "sharded", "load-balanced" ] } ], "database_name": "default", "collection_name": "default", "data": [], "encrypted_fields": { "fields": [ { "keyId": { "$binary": { "base64": "EjRWeBI0mHYSNBI0VniQEg==", "subType": "04" } }, "path": "encryptedIndexed", "bsonType": "string", "queries": { "queryType": "equality", "contention": { "$numberLong": "0" } } }, { "keyId": { "$binary": { "base64": "q83vqxI0mHYSNBI0VniQEg==", "subType": "04" } }, "path": "encryptedUnindexed", "bsonType": "string" } ] }, "key_vault_data": [ { "_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" } } ], "tests": [ { "description": "Insert and find FLE2 indexed field", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "local": { "key": { "$binary": { "base64": "Mng0NCt4ZHVUYUJCa1kxNkVyNUR1QURhZ2h2UzR2d2RrZzh0cFBwM3R6NmdWMDFBMUN3YkQ5aXRRMkhGRGdQV09wOGVNYUMxT2k3NjZKelhaQmRCZGJkTXVyZG9uSjFk", "subType": "00" } } } } } }, "operations": [ { "name": "insertOne", "arguments": { "document": { "_id": 1, "encryptedIndexed": "123" } } }, { "name": "find", "arguments": { "filter": { "encryptedIndexed": "123" } }, "result": [ { "_id": 1, "encryptedIndexed": "123" } ] } ], "expectations": [ { "command_started_event": { "command": { "listCollections": 1, "filter": { "name": "default" } }, "command_name": "listCollections" } }, { "command_started_event": { "command": { "find": "datakeys", "filter": { "$or": [ { "_id": { "$in": [ { "$binary": { "base64": "EjRWeBI0mHYSNBI0VniQEg==", "subType": "04" } } ] } }, { "keyAltNames": { "$in": [] } } ] }, "$db": "keyvault", "readConcern": { "level": "majority" } }, "command_name": "find" } }, { "command_started_event": { "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" } } }, { "keyId": { "$binary": { "base64": "q83vqxI0mHYSNBI0VniQEg==", "subType": "04" } }, "path": "encryptedUnindexed", "bsonType": "string" } ] } } } }, "command_name": "insert" } }, { "command_started_event": { "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" } } }, { "keyId": { "$binary": { "base64": "q83vqxI0mHYSNBI0VniQEg==", "subType": "04" } }, "path": "encryptedUnindexed", "bsonType": "string" } ] } } } }, "command_name": "find" } } ], "outcome": { "collection": { "data": [ { "_id": 1, "encryptedIndexed": { "$$type": "binData" }, "__safeContent__": [ { "$binary": { "base64": "31eCYlbQoVboc5zwC8IoyJVSkag9PxREka8dkmbXJeY=", "subType": "00" } } ] } ] } } } ] } fle2v2-InsertFind-Unindexed.json000066400000000000000000000133041462766011000351030ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/client-side-encryption/spec/legacy{ "runOn": [ { "minServerVersion": "7.0.0", "topology": [ "replicaset", "sharded", "load-balanced" ] } ], "database_name": "default", "collection_name": "default", "data": [], "encrypted_fields": { "fields": [ { "keyId": { "$binary": { "base64": "EjRWeBI0mHYSNBI0VniQEg==", "subType": "04" } }, "path": "encryptedIndexed", "bsonType": "string", "queries": { "queryType": "equality", "contention": { "$numberLong": "0" } } }, { "keyId": { "$binary": { "base64": "q83vqxI0mHYSNBI0VniQEg==", "subType": "04" } }, "path": "encryptedUnindexed", "bsonType": "string" } ] }, "key_vault_data": [ { "_id": { "$binary": { "base64": "q83vqxI0mHYSNBI0VniQEg==", "subType": "04" } }, "keyMaterial": { "$binary": { "base64": "HBk9BWihXExNDvTp1lUxOuxuZK2Pe2ZdVdlsxPEBkiO1bS4mG5NNDsQ7zVxJAH8BtdOYp72Ku4Y3nwc0BUpIKsvAKX4eYXtlhv5zUQxWdeNFhg9qK7qb8nqhnnLeT0f25jFSqzWJoT379hfwDeu0bebJHr35QrJ8myZdPMTEDYF08QYQ48ShRBli0S+QzBHHAQiM2iJNr4svg2WR8JSeWQ==", "subType": "00" } }, "creationDate": { "$date": { "$numberLong": "1648914851981" } }, "updateDate": { "$date": { "$numberLong": "1648914851981" } }, "status": { "$numberInt": "0" }, "masterKey": { "provider": "local" } } ], "tests": [ { "description": "Insert and find FLE2 unindexed field", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "local": { "key": { "$binary": { "base64": "Mng0NCt4ZHVUYUJCa1kxNkVyNUR1QURhZ2h2UzR2d2RrZzh0cFBwM3R6NmdWMDFBMUN3YkQ5aXRRMkhGRGdQV09wOGVNYUMxT2k3NjZKelhaQmRCZGJkTXVyZG9uSjFk", "subType": "00" } } } } } }, "operations": [ { "name": "insertOne", "arguments": { "document": { "_id": 1, "encryptedUnindexed": "value123" } } }, { "name": "find", "arguments": { "filter": { "_id": 1 } }, "result": [ { "_id": 1, "encryptedUnindexed": "value123" } ] } ], "expectations": [ { "command_started_event": { "command": { "listCollections": 1, "filter": { "name": "default" } }, "command_name": "listCollections" } }, { "command_started_event": { "command": { "find": "datakeys", "filter": { "$or": [ { "_id": { "$in": [ { "$binary": { "base64": "q83vqxI0mHYSNBI0VniQEg==", "subType": "04" } } ] } }, { "keyAltNames": { "$in": [] } } ] }, "$db": "keyvault", "readConcern": { "level": "majority" } }, "command_name": "find" } }, { "command_started_event": { "command": { "insert": "default", "documents": [ { "_id": 1, "encryptedUnindexed": { "$$type": "binData" } } ], "ordered": true }, "command_name": "insert" } }, { "command_started_event": { "command": { "find": "default", "filter": { "_id": { "$eq": 1 } } }, "command_name": "find" } } ], "outcome": { "collection": { "data": [ { "_id": 1, "encryptedUnindexed": { "$$type": "binData" } } ] } } }, { "description": "Query with an unindexed field fails", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "local": { "key": { "$binary": { "base64": "Mng0NCt4ZHVUYUJCa1kxNkVyNUR1QURhZ2h2UzR2d2RrZzh0cFBwM3R6NmdWMDFBMUN3YkQ5aXRRMkhGRGdQV09wOGVNYUMxT2k3NjZKelhaQmRCZGJkTXVyZG9uSjFk", "subType": "00" } } } } } }, "operations": [ { "name": "insertOne", "arguments": { "document": { "_id": 1, "encryptedUnindexed": "value123" } } }, { "name": "find", "arguments": { "filter": { "encryptedUnindexed": "value123" } }, "result": { "errorContains": "encrypt" } } ] } ] } mongodb-mongo-python-driver-509e9b7/test/client-side-encryption/spec/legacy/fle2v2-MissingKey.json000066400000000000000000000052541462766011000332630ustar00rootroot00000000000000{ "runOn": [ { "minServerVersion": "7.0.0", "topology": [ "replicaset", "sharded", "load-balanced" ] } ], "database_name": "default", "collection_name": "default", "data": [ { "encryptedUnindexed": { "$binary": { "base64": "BqvN76sSNJh2EjQSNFZ4kBICTQaVZPWgXp41I7mPV1rLFTtw1tXzjcdSEyxpKKqujlko5TeizkB9hHQ009dVY1+fgIiDcefh+eQrm3CkhQ==", "subType": "06" } } } ], "encrypted_fields": { "fields": [ { "keyId": { "$binary": { "base64": "EjRWeBI0mHYSNBI0VniQEg==", "subType": "04" } }, "path": "encryptedIndexed", "bsonType": "string", "queries": { "queryType": "equality", "contention": { "$numberLong": "0" } } }, { "keyId": { "$binary": { "base64": "q83vqxI0mHYSNBI0VniQEg==", "subType": "04" } }, "path": "encryptedUnindexed", "bsonType": "string" } ] }, "key_vault_data": [], "tests": [ { "description": "FLE2 encrypt fails with missing key", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "local": { "key": { "$binary": { "base64": "Mng0NCt4ZHVUYUJCa1kxNkVyNUR1QURhZ2h2UzR2d2RrZzh0cFBwM3R6NmdWMDFBMUN3YkQ5aXRRMkhGRGdQV09wOGVNYUMxT2k3NjZKelhaQmRCZGJkTXVyZG9uSjFk", "subType": "00" } } } } } }, "operations": [ { "name": "insertOne", "arguments": { "document": { "_id": 1, "encryptedIndexed": "123" } }, "result": { "errorContains": "not all keys requested were satisfied" } } ] }, { "description": "FLE2 decrypt fails with missing key", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "local": { "key": { "$binary": { "base64": "Mng0NCt4ZHVUYUJCa1kxNkVyNUR1QURhZ2h2UzR2d2RrZzh0cFBwM3R6NmdWMDFBMUN3YkQ5aXRRMkhGRGdQV09wOGVNYUMxT2k3NjZKelhaQmRCZGJkTXVyZG9uSjFk", "subType": "00" } } } } } }, "operations": [ { "name": "find", "arguments": { "filter": {} }, "result": { "errorContains": "not all keys requested were satisfied" } } ] } ] } mongodb-mongo-python-driver-509e9b7/test/client-side-encryption/spec/legacy/fle2v2-NoEncryption.json000066400000000000000000000035051462766011000336250ustar00rootroot00000000000000{ "runOn": [ { "minServerVersion": "7.0.0", "topology": [ "replicaset", "sharded", "load-balanced" ] } ], "database_name": "default", "collection_name": "default", "data": [], "key_vault_data": [], "encrypted_fields": { "fields": [] }, "tests": [ { "description": "insert with no encryption succeeds", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "local": { "key": { "$binary": { "base64": "Mng0NCt4ZHVUYUJCa1kxNkVyNUR1QURhZ2h2UzR2d2RrZzh0cFBwM3R6NmdWMDFBMUN3YkQ5aXRRMkhGRGdQV09wOGVNYUMxT2k3NjZKelhaQmRCZGJkTXVyZG9uSjFk", "subType": "00" } } } } } }, "operations": [ { "name": "insertOne", "arguments": { "document": { "_id": 1, "foo": "bar" } } } ], "expectations": [ { "command_started_event": { "command": { "listCollections": 1, "filter": { "name": "default" } }, "command_name": "listCollections" } }, { "command_started_event": { "command": { "insert": "default", "documents": [ { "_id": 1, "foo": "bar" } ], "ordered": true }, "command_name": "insert" } } ], "outcome": { "collection": { "data": [ { "_id": 1, "foo": "bar" } ] } } } ] } fle2v2-Range-Date-Aggregate.json000066400000000000000000000400331462766011000347070ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/client-side-encryption/spec/legacy{ "runOn": [ { "minServerVersion": "7.0.0", "topology": [ "replicaset", "sharded", "load-balanced" ] } ], "database_name": "default", "collection_name": "default", "data": [], "encrypted_fields": { "fields": [ { "keyId": { "$binary": { "base64": "EjRWeBI0mHYSNBI0VniQEg==", "subType": "04" } }, "path": "encryptedDate", "bsonType": "date", "queries": { "queryType": "rangePreview", "contention": { "$numberLong": "0" }, "sparsity": { "$numberLong": "1" }, "min": { "$date": { "$numberLong": "0" } }, "max": { "$date": { "$numberLong": "200" } } } } ] }, "key_vault_data": [ { "_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" } } ], "tests": [ { "description": "FLE2 Range Date. Aggregate.", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "local": { "key": { "$binary": { "base64": "Mng0NCt4ZHVUYUJCa1kxNkVyNUR1QURhZ2h2UzR2d2RrZzh0cFBwM3R6NmdWMDFBMUN3YkQ5aXRRMkhGRGdQV09wOGVNYUMxT2k3NjZKelhaQmRCZGJkTXVyZG9uSjFk", "subType": "00" } } } } } }, "operations": [ { "name": "insertOne", "arguments": { "document": { "_id": 0, "encryptedDate": { "$date": { "$numberLong": "0" } } } } }, { "name": "insertOne", "arguments": { "document": { "_id": 1, "encryptedDate": { "$date": { "$numberLong": "1" } } } } }, { "name": "aggregate", "arguments": { "pipeline": [ { "$match": { "encryptedDate": { "$gt": { "$date": { "$numberLong": "0" } } } } } ] }, "result": [ { "_id": 1, "encryptedDate": { "$date": { "$numberLong": "1" } } } ] } ], "expectations": [ { "command_started_event": { "command": { "listCollections": 1, "filter": { "name": "default" } }, "command_name": "listCollections" } }, { "command_started_event": { "command": { "find": "datakeys", "filter": { "$or": [ { "_id": { "$in": [ { "$binary": { "base64": "EjRWeBI0mHYSNBI0VniQEg==", "subType": "04" } } ] } }, { "keyAltNames": { "$in": [] } } ] }, "$db": "keyvault", "readConcern": { "level": "majority" } }, "command_name": "find" } }, { "command_started_event": { "command": { "insert": "default", "documents": [ { "_id": 0, "encryptedDate": { "$$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": "encryptedDate", "bsonType": "date", "queries": { "queryType": "rangePreview", "contention": { "$numberLong": "0" }, "sparsity": { "$numberLong": "1" }, "min": { "$date": { "$numberLong": "0" } }, "max": { "$date": { "$numberLong": "200" } } } } ] } } } }, "command_name": "insert" } }, { "command_started_event": { "command": { "insert": "default", "documents": [ { "_id": 1, "encryptedDate": { "$$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": "encryptedDate", "bsonType": "date", "queries": { "queryType": "rangePreview", "contention": { "$numberLong": "0" }, "sparsity": { "$numberLong": "1" }, "min": { "$date": { "$numberLong": "0" } }, "max": { "$date": { "$numberLong": "200" } } } } ] } } } }, "command_name": "insert" } }, { "command_started_event": { "command": { "aggregate": "default", "pipeline": [ { "$match": { "encryptedDate": { "$gt": { "$binary": { "base64": "DUkFAAADcGF5bG9hZAAZBQAABGcABQUAAAMwAH0AAAAFZAAgAAAAALGGQ/CRD+pGLD53BZzWcCcYbuGLVEyjzXIx7b+ux/q2BXMAIAAAAACOC6mXEZL27P9hethZbtKYsTXKK+FpgQ9Axxmn9N/cCwVsACAAAAAA+MFEd8XfZSpbXKqqPC2L3TEFswkaG5Ff6aSgf8p+XVIAAzEAfQAAAAVkACAAAAAAtL3QIvnZqCF72eS6lKr8ilff7R6kiNklokiTuaU5wNsFcwAgAAAAAEtqr3/X731VB+VrbFcY8ZrJKRo2E0Fd+C8L0EMNcvcCBWwAIAAAAABNPhSriux8W8qbwnhCczE3IzlhNEnGDpUwTFDZSL+eYQADMgB9AAAABWQAIAAAAAB99ZW/7KwXKzl5M3XQsAJ3JbEef90IoxFYBArNiYzlgQVzACAAAAAAYO/qaw0+92HAryxOUG7iK6hnIy3OaUA9jIqtHdvcq8YFbAAgAAAAAHrUYj8A0hVgc6VklpDiljOnykrUSfEsjm56XO/bsfKdAAMzAH0AAAAFZAAgAAAAAOK8brUuc2onBNDRtfYMR736dHj4dQqXod8JG7tAMTsDBXMAIAAAAAAW6SrGAL6Bx0s7ZlsYULFfOAiYIGhEWu6md3r+Rk40awVsACAAAAAAIHYXP8RLcCboUmHN3+OlnEw1DxaLSnbTB9PdF228fFAAAzQAfQAAAAVkACAAAAAAV22FGF7ZDwK/EYiGNMlm/QuT3saQdyJM/Fn+ZyQug1oFcwAgAAAAACo7GwCvbcs5UHQMgds9/1QMklEVdjZigpuOFGrDmmxtBWwAIAAAAADQbYYPxlCMMGe2MulbiurApFLoeJSMvTeDU3pyEA2jNwADNQB9AAAABWQAIAAAAADFspsMG7yHjKppyllon1KqAsTrHaZ6JzNqnSz8o6iTvwVzACAAAAAAeiA5pqVIQQ9s6UY/P8v5Jjkl3I7iFNeLDYehikrINrsFbAAgAAAAAFjBTzTpNxDEkA0vSRj0jCED9KDRlboMVyilKyDz5YR4AAM2AH0AAAAFZAAgAAAAAPcLmtq+V1e+MRlZ7NHq1+mrRVBQje5zj685ZvdsfKvSBXMAIAAAAABdHz/3w2k5km97QN9m7oLFYJaVJneNlMboIlz5yUASQAVsACAAAAAAWbp8JVJnx8fEVAJFa7WMfMa7wXeP5M3C8MX20J/i9n0AAzcAfQAAAAVkACAAAAAAYfLwnoxK6XAGQrJFy8+TIJoq38ldBaO75h4zA4ZX5tQFcwAgAAAAAC2wk8UcJH5X5XGnDBYmel6srpBkzBhHtt3Jw1u5TSJ1BWwAIAAAAAA9/YU9eI3D7QbXKIw/3/gzWJ6MZrCYhG0j1wNKgRQp5wADOAB9AAAABWQAIAAAAADGvyrtKkIcaV17ynZA7b2k5Pz6OhvxdWNkDvDWJIja8wVzACAAAAAAOLypVKNxf/wR1G8OZjUUsTQzDYeNNhhITxGMSp7euS4FbAAgAAAAAA9EsxoV1B2DcQ1NJRwuxXnvVR+vkD0wbbDYEI/zFEnDAAM5AH0AAAAFZAAgAAAAAEocREw1L0g+roFUchJI2Yd0M0ME2bnErNUYnpyJP1SqBXMAIAAAAAAcE2/JK/8MoSeOchIuAkKh1X3ImoA7p8ujAZIfvIDo6QVsACAAAAAA+W0+zgLr85/PD7P9a94wk6MgNgrizx/XU9aCxAkp1IwAABJjbQAAAAAAAAAAAAAQcGF5bG9hZElkAAAAAAAQZmlyc3RPcGVyYXRvcgABAAAAAA==", "subType": "06" } } } } } ], "cursor": {}, "encryptionInformation": { "type": 1, "schema": { "default.default": { "escCollection": "enxcol_.default.esc", "ecocCollection": "enxcol_.default.ecoc", "fields": [ { "keyId": { "$binary": { "base64": "EjRWeBI0mHYSNBI0VniQEg==", "subType": "04" } }, "path": "encryptedDate", "bsonType": "date", "queries": { "queryType": "rangePreview", "contention": { "$numberLong": "0" }, "sparsity": { "$numberLong": "1" }, "min": { "$date": { "$numberLong": "0" } }, "max": { "$date": { "$numberLong": "200" } } } } ] } } } }, "command_name": "aggregate" } } ], "outcome": { "collection": { "data": [ { "_id": 0, "encryptedDate": { "$$type": "binData" }, "__safeContent__": [ { "$binary": { "base64": "5nRutVIyq7URVOVtbE4vM01APSIajAVnsShMwjBlzkM=", "subType": "00" } }, { "$binary": { "base64": "RjBYT2h3ZAoHxhf8DU6/dFbDkEBZp0IxREcsRTu2MXs=", "subType": "00" } }, { "$binary": { "base64": "x7GR49EN0t3WXQDihkrbonK7qNIBYC87tpL/XEUyIYc=", "subType": "00" } }, { "$binary": { "base64": "JfYUqWF+OoGjiYkRI4L5iPlF+T1Eleul7Fki22jp4Qc=", "subType": "00" } }, { "$binary": { "base64": "q1RyGfIgsaQHoZFRw+DD28V26rN5hweApPLwExncvT8=", "subType": "00" } }, { "$binary": { "base64": "L2PFeKGvLS6C+DLudR6fGlBq3ERPvjWvRyNRIA2HVb0=", "subType": "00" } }, { "$binary": { "base64": "CWxaNqL3iP1yCixDkcmf9bmW3E5VeN8TJkg1jJe528s=", "subType": "00" } }, { "$binary": { "base64": "+vC6araOEo+fpW7PSIP40/EnzBCj1d2N10Jr3rrXJJM=", "subType": "00" } }, { "$binary": { "base64": "6SV63Mf51Z6A6p2X3rCnJKCu6ku3Oeb45mBYbz+IoAo=", "subType": "00" } } ] }, { "_id": 1, "encryptedDate": { "$$type": "binData" }, "__safeContent__": [ { "$binary": { "base64": "bE1vqWj3KNyM7cCYUv/cnYm8BPaUL3eMp5syTHq6NF4=", "subType": "00" } }, { "$binary": { "base64": "25j9sQXZCihCmHKvTHgaBsAVZFcGPn7JjHdrCGlwyyw=", "subType": "00" } }, { "$binary": { "base64": "FA74j21GUEJb1DJBOpR9nVnjaDZnd8yAQNuaW9Qi26g=", "subType": "00" } }, { "$binary": { "base64": "kJv//KVkbrobIBf+QeWC5jxn20mx/P0R1N6aCSMgKM8=", "subType": "00" } }, { "$binary": { "base64": "zB+Whi9IUUGxfLEe+lGuIzLX4LFbIhaIAm5lRk65QTc=", "subType": "00" } }, { "$binary": { "base64": "ybO1QU3CgvhO8JgRXH+HxKszWcpl5aGDYYVa75fHa1g=", "subType": "00" } }, { "$binary": { "base64": "X3Y3eSAbbMg//JgiHHiFpYOpV61t8kkDexI+CQyitH4=", "subType": "00" } }, { "$binary": { "base64": "SlNHXyqVFGDPrX/2ppwog6l4pwj3PKda2TkZbqgfSfA=", "subType": "00" } }, { "$binary": { "base64": "McjV8xwTF3xI7863DYOBdyvIv6UpzThl6v9vBRk05bI=", "subType": "00" } } ] } ] } } } ] } fle2v2-Range-Date-Correctness.json000066400000000000000000001244161462766011000353230ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/client-side-encryption/spec/legacy{ "runOn": [ { "minServerVersion": "7.0.0", "topology": [ "replicaset", "sharded", "load-balanced" ] } ], "database_name": "default", "collection_name": "default", "data": [], "encrypted_fields": { "fields": [ { "keyId": { "$binary": { "base64": "EjRWeBI0mHYSNBI0VniQEg==", "subType": "04" } }, "path": "encryptedDate", "bsonType": "date", "queries": { "queryType": "rangePreview", "contention": { "$numberLong": "0" }, "sparsity": { "$numberLong": "1" }, "min": { "$date": { "$numberLong": "0" } }, "max": { "$date": { "$numberLong": "200" } } } } ] }, "key_vault_data": [ { "_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" } } ], "tests": [ { "description": "Find with $gt", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "local": { "key": { "$binary": { "base64": "Mng0NCt4ZHVUYUJCa1kxNkVyNUR1QURhZ2h2UzR2d2RrZzh0cFBwM3R6NmdWMDFBMUN3YkQ5aXRRMkhGRGdQV09wOGVNYUMxT2k3NjZKelhaQmRCZGJkTXVyZG9uSjFk", "subType": "00" } } } } } }, "operations": [ { "name": "insertOne", "arguments": { "document": { "_id": 0, "encryptedDate": { "$date": { "$numberLong": "0" } } } } }, { "name": "insertOne", "arguments": { "document": { "_id": 1, "encryptedDate": { "$date": { "$numberLong": "1" } } } } }, { "name": "find", "arguments": { "filter": { "encryptedDate": { "$gt": { "$date": { "$numberLong": "0" } } } } }, "result": [ { "_id": 1, "encryptedDate": { "$date": { "$numberLong": "1" } } } ] } ] }, { "description": "Find with $gte", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "local": { "key": { "$binary": { "base64": "Mng0NCt4ZHVUYUJCa1kxNkVyNUR1QURhZ2h2UzR2d2RrZzh0cFBwM3R6NmdWMDFBMUN3YkQ5aXRRMkhGRGdQV09wOGVNYUMxT2k3NjZKelhaQmRCZGJkTXVyZG9uSjFk", "subType": "00" } } } } } }, "operations": [ { "name": "insertOne", "arguments": { "document": { "_id": 0, "encryptedDate": { "$date": { "$numberLong": "0" } } } } }, { "name": "insertOne", "arguments": { "document": { "_id": 1, "encryptedDate": { "$date": { "$numberLong": "1" } } } } }, { "name": "find", "arguments": { "filter": { "encryptedDate": { "$gte": { "$date": { "$numberLong": "0" } } } }, "sort": { "_id": 1 } }, "result": [ { "_id": 0, "encryptedDate": { "$date": { "$numberLong": "0" } } }, { "_id": 1, "encryptedDate": { "$date": { "$numberLong": "1" } } } ] } ] }, { "description": "Find with $gt with no results", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "local": { "key": { "$binary": { "base64": "Mng0NCt4ZHVUYUJCa1kxNkVyNUR1QURhZ2h2UzR2d2RrZzh0cFBwM3R6NmdWMDFBMUN3YkQ5aXRRMkhGRGdQV09wOGVNYUMxT2k3NjZKelhaQmRCZGJkTXVyZG9uSjFk", "subType": "00" } } } } } }, "operations": [ { "name": "insertOne", "arguments": { "document": { "_id": 0, "encryptedDate": { "$date": { "$numberLong": "0" } } } } }, { "name": "insertOne", "arguments": { "document": { "_id": 1, "encryptedDate": { "$date": { "$numberLong": "1" } } } } }, { "name": "find", "arguments": { "filter": { "encryptedDate": { "$gt": { "$date": { "$numberLong": "1" } } } } }, "result": [] } ] }, { "description": "Find with $lt", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "local": { "key": { "$binary": { "base64": "Mng0NCt4ZHVUYUJCa1kxNkVyNUR1QURhZ2h2UzR2d2RrZzh0cFBwM3R6NmdWMDFBMUN3YkQ5aXRRMkhGRGdQV09wOGVNYUMxT2k3NjZKelhaQmRCZGJkTXVyZG9uSjFk", "subType": "00" } } } } } }, "operations": [ { "name": "insertOne", "arguments": { "document": { "_id": 0, "encryptedDate": { "$date": { "$numberLong": "0" } } } } }, { "name": "insertOne", "arguments": { "document": { "_id": 1, "encryptedDate": { "$date": { "$numberLong": "1" } } } } }, { "name": "find", "arguments": { "filter": { "encryptedDate": { "$lt": { "$date": { "$numberLong": "1" } } } } }, "result": [ { "_id": 0, "encryptedDate": { "$date": { "$numberLong": "0" } } } ] } ] }, { "description": "Find with $lte", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "local": { "key": { "$binary": { "base64": "Mng0NCt4ZHVUYUJCa1kxNkVyNUR1QURhZ2h2UzR2d2RrZzh0cFBwM3R6NmdWMDFBMUN3YkQ5aXRRMkhGRGdQV09wOGVNYUMxT2k3NjZKelhaQmRCZGJkTXVyZG9uSjFk", "subType": "00" } } } } } }, "operations": [ { "name": "insertOne", "arguments": { "document": { "_id": 0, "encryptedDate": { "$date": { "$numberLong": "0" } } } } }, { "name": "insertOne", "arguments": { "document": { "_id": 1, "encryptedDate": { "$date": { "$numberLong": "1" } } } } }, { "name": "find", "arguments": { "filter": { "encryptedDate": { "$lte": { "$date": { "$numberLong": "1" } } } }, "sort": { "_id": 1 } }, "result": [ { "_id": 0, "encryptedDate": { "$date": { "$numberLong": "0" } } }, { "_id": 1, "encryptedDate": { "$date": { "$numberLong": "1" } } } ] } ] }, { "description": "Find with $lt below min", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "local": { "key": { "$binary": { "base64": "Mng0NCt4ZHVUYUJCa1kxNkVyNUR1QURhZ2h2UzR2d2RrZzh0cFBwM3R6NmdWMDFBMUN3YkQ5aXRRMkhGRGdQV09wOGVNYUMxT2k3NjZKelhaQmRCZGJkTXVyZG9uSjFk", "subType": "00" } } } } } }, "operations": [ { "name": "insertOne", "arguments": { "document": { "_id": 0, "encryptedDate": { "$date": { "$numberLong": "0" } } } } }, { "name": "insertOne", "arguments": { "document": { "_id": 1, "encryptedDate": { "$date": { "$numberLong": "1" } } } } }, { "name": "find", "arguments": { "filter": { "encryptedDate": { "$lt": { "$date": { "$numberLong": "0" } } } } }, "result": { "errorContains": "must be greater than the range minimum" } } ] }, { "description": "Find with $gt above max", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "local": { "key": { "$binary": { "base64": "Mng0NCt4ZHVUYUJCa1kxNkVyNUR1QURhZ2h2UzR2d2RrZzh0cFBwM3R6NmdWMDFBMUN3YkQ5aXRRMkhGRGdQV09wOGVNYUMxT2k3NjZKelhaQmRCZGJkTXVyZG9uSjFk", "subType": "00" } } } } } }, "operations": [ { "name": "insertOne", "arguments": { "document": { "_id": 0, "encryptedDate": { "$date": { "$numberLong": "0" } } } } }, { "name": "insertOne", "arguments": { "document": { "_id": 1, "encryptedDate": { "$date": { "$numberLong": "1" } } } } }, { "name": "find", "arguments": { "filter": { "encryptedDate": { "$gt": { "$date": { "$numberLong": "200" } } } } }, "result": { "errorContains": "must be less than the range maximum" } } ] }, { "description": "Find with $gt and $lt", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "local": { "key": { "$binary": { "base64": "Mng0NCt4ZHVUYUJCa1kxNkVyNUR1QURhZ2h2UzR2d2RrZzh0cFBwM3R6NmdWMDFBMUN3YkQ5aXRRMkhGRGdQV09wOGVNYUMxT2k3NjZKelhaQmRCZGJkTXVyZG9uSjFk", "subType": "00" } } } } } }, "operations": [ { "name": "insertOne", "arguments": { "document": { "_id": 0, "encryptedDate": { "$date": { "$numberLong": "0" } } } } }, { "name": "insertOne", "arguments": { "document": { "_id": 1, "encryptedDate": { "$date": { "$numberLong": "1" } } } } }, { "name": "find", "arguments": { "filter": { "encryptedDate": { "$gt": { "$date": { "$numberLong": "0" } }, "$lt": { "$date": { "$numberLong": "2" } } } } }, "result": [ { "_id": 1, "encryptedDate": { "$date": { "$numberLong": "1" } } } ] } ] }, { "description": "Find with equality", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "local": { "key": { "$binary": { "base64": "Mng0NCt4ZHVUYUJCa1kxNkVyNUR1QURhZ2h2UzR2d2RrZzh0cFBwM3R6NmdWMDFBMUN3YkQ5aXRRMkhGRGdQV09wOGVNYUMxT2k3NjZKelhaQmRCZGJkTXVyZG9uSjFk", "subType": "00" } } } } } }, "operations": [ { "name": "insertOne", "arguments": { "document": { "_id": 0, "encryptedDate": { "$date": { "$numberLong": "0" } } } } }, { "name": "insertOne", "arguments": { "document": { "_id": 1, "encryptedDate": { "$date": { "$numberLong": "1" } } } } }, { "name": "find", "arguments": { "filter": { "encryptedDate": { "$date": { "$numberLong": "0" } } } }, "result": [ { "_id": 0, "encryptedDate": { "$date": { "$numberLong": "0" } } } ] }, { "name": "find", "arguments": { "filter": { "encryptedDate": { "$date": { "$numberLong": "1" } } } }, "result": [ { "_id": 1, "encryptedDate": { "$date": { "$numberLong": "1" } } } ] } ] }, { "description": "Find with full range", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "local": { "key": { "$binary": { "base64": "Mng0NCt4ZHVUYUJCa1kxNkVyNUR1QURhZ2h2UzR2d2RrZzh0cFBwM3R6NmdWMDFBMUN3YkQ5aXRRMkhGRGdQV09wOGVNYUMxT2k3NjZKelhaQmRCZGJkTXVyZG9uSjFk", "subType": "00" } } } } } }, "operations": [ { "name": "insertOne", "arguments": { "document": { "_id": 0, "encryptedDate": { "$date": { "$numberLong": "0" } } } } }, { "name": "insertOne", "arguments": { "document": { "_id": 1, "encryptedDate": { "$date": { "$numberLong": "1" } } } } }, { "name": "find", "arguments": { "filter": { "encryptedDate": { "$gte": { "$date": { "$numberLong": "0" } }, "$lte": { "$date": { "$numberLong": "200" } } } }, "sort": { "_id": 1 } }, "result": [ { "_id": 0, "encryptedDate": { "$date": { "$numberLong": "0" } } }, { "_id": 1, "encryptedDate": { "$date": { "$numberLong": "1" } } } ] } ] }, { "description": "Find with $in", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "local": { "key": { "$binary": { "base64": "Mng0NCt4ZHVUYUJCa1kxNkVyNUR1QURhZ2h2UzR2d2RrZzh0cFBwM3R6NmdWMDFBMUN3YkQ5aXRRMkhGRGdQV09wOGVNYUMxT2k3NjZKelhaQmRCZGJkTXVyZG9uSjFk", "subType": "00" } } } } } }, "operations": [ { "name": "insertOne", "arguments": { "document": { "_id": 0, "encryptedDate": { "$date": { "$numberLong": "0" } } } } }, { "name": "insertOne", "arguments": { "document": { "_id": 1, "encryptedDate": { "$date": { "$numberLong": "1" } } } } }, { "name": "find", "arguments": { "filter": { "encryptedDate": { "$in": [ { "$date": { "$numberLong": "0" } } ] } } }, "result": [ { "_id": 0, "encryptedDate": { "$date": { "$numberLong": "0" } } } ] } ] }, { "description": "Insert out of range", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "local": { "key": { "$binary": { "base64": "Mng0NCt4ZHVUYUJCa1kxNkVyNUR1QURhZ2h2UzR2d2RrZzh0cFBwM3R6NmdWMDFBMUN3YkQ5aXRRMkhGRGdQV09wOGVNYUMxT2k3NjZKelhaQmRCZGJkTXVyZG9uSjFk", "subType": "00" } } } } } }, "operations": [ { "name": "insertOne", "arguments": { "document": { "_id": 0, "encryptedDate": { "$date": { "$numberLong": "-1" } } } }, "result": { "errorContains": "value must be greater than or equal to the minimum value" } } ] }, { "description": "Insert min and max", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "local": { "key": { "$binary": { "base64": "Mng0NCt4ZHVUYUJCa1kxNkVyNUR1QURhZ2h2UzR2d2RrZzh0cFBwM3R6NmdWMDFBMUN3YkQ5aXRRMkhGRGdQV09wOGVNYUMxT2k3NjZKelhaQmRCZGJkTXVyZG9uSjFk", "subType": "00" } } } } } }, "operations": [ { "name": "insertOne", "arguments": { "document": { "_id": 0, "encryptedDate": { "$date": { "$numberLong": "0" } } } } }, { "name": "insertOne", "arguments": { "document": { "_id": 200, "encryptedDate": { "$date": { "$numberLong": "200" } } } } }, { "name": "find", "arguments": { "filter": {}, "sort": { "_id": 1 } }, "result": [ { "_id": 0, "encryptedDate": { "$date": { "$numberLong": "0" } } }, { "_id": 200, "encryptedDate": { "$date": { "$numberLong": "200" } } } ] } ] }, { "description": "Aggregate with $gte", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "local": { "key": { "$binary": { "base64": "Mng0NCt4ZHVUYUJCa1kxNkVyNUR1QURhZ2h2UzR2d2RrZzh0cFBwM3R6NmdWMDFBMUN3YkQ5aXRRMkhGRGdQV09wOGVNYUMxT2k3NjZKelhaQmRCZGJkTXVyZG9uSjFk", "subType": "00" } } } } } }, "operations": [ { "name": "insertOne", "arguments": { "document": { "_id": 0, "encryptedDate": { "$date": { "$numberLong": "0" } } } } }, { "name": "insertOne", "arguments": { "document": { "_id": 1, "encryptedDate": { "$date": { "$numberLong": "1" } } } } }, { "name": "aggregate", "arguments": { "pipeline": [ { "$match": { "encryptedDate": { "$gte": { "$date": { "$numberLong": "0" } } } } }, { "$sort": { "_id": 1 } } ] }, "result": [ { "_id": 0, "encryptedDate": { "$date": { "$numberLong": "0" } } }, { "_id": 1, "encryptedDate": { "$date": { "$numberLong": "1" } } } ] } ] }, { "description": "Aggregate with $gt with no results", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "local": { "key": { "$binary": { "base64": "Mng0NCt4ZHVUYUJCa1kxNkVyNUR1QURhZ2h2UzR2d2RrZzh0cFBwM3R6NmdWMDFBMUN3YkQ5aXRRMkhGRGdQV09wOGVNYUMxT2k3NjZKelhaQmRCZGJkTXVyZG9uSjFk", "subType": "00" } } } } } }, "operations": [ { "name": "insertOne", "arguments": { "document": { "_id": 0, "encryptedDate": { "$date": { "$numberLong": "0" } } } } }, { "name": "insertOne", "arguments": { "document": { "_id": 1, "encryptedDate": { "$date": { "$numberLong": "1" } } } } }, { "name": "aggregate", "arguments": { "pipeline": [ { "$match": { "encryptedDate": { "$gt": { "$date": { "$numberLong": "1" } } } } } ] }, "result": [] } ] }, { "description": "Aggregate with $lt", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "local": { "key": { "$binary": { "base64": "Mng0NCt4ZHVUYUJCa1kxNkVyNUR1QURhZ2h2UzR2d2RrZzh0cFBwM3R6NmdWMDFBMUN3YkQ5aXRRMkhGRGdQV09wOGVNYUMxT2k3NjZKelhaQmRCZGJkTXVyZG9uSjFk", "subType": "00" } } } } } }, "operations": [ { "name": "insertOne", "arguments": { "document": { "_id": 0, "encryptedDate": { "$date": { "$numberLong": "0" } } } } }, { "name": "insertOne", "arguments": { "document": { "_id": 1, "encryptedDate": { "$date": { "$numberLong": "1" } } } } }, { "name": "aggregate", "arguments": { "pipeline": [ { "$match": { "encryptedDate": { "$lt": { "$date": { "$numberLong": "1" } } } } } ] }, "result": [ { "_id": 0, "encryptedDate": { "$date": { "$numberLong": "0" } } } ] } ] }, { "description": "Aggregate with $lte", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "local": { "key": { "$binary": { "base64": "Mng0NCt4ZHVUYUJCa1kxNkVyNUR1QURhZ2h2UzR2d2RrZzh0cFBwM3R6NmdWMDFBMUN3YkQ5aXRRMkhGRGdQV09wOGVNYUMxT2k3NjZKelhaQmRCZGJkTXVyZG9uSjFk", "subType": "00" } } } } } }, "operations": [ { "name": "insertOne", "arguments": { "document": { "_id": 0, "encryptedDate": { "$date": { "$numberLong": "0" } } } } }, { "name": "insertOne", "arguments": { "document": { "_id": 1, "encryptedDate": { "$date": { "$numberLong": "1" } } } } }, { "name": "aggregate", "arguments": { "pipeline": [ { "$match": { "encryptedDate": { "$lte": { "$date": { "$numberLong": "1" } } } } }, { "$sort": { "_id": 1 } } ] }, "result": [ { "_id": 0, "encryptedDate": { "$date": { "$numberLong": "0" } } }, { "_id": 1, "encryptedDate": { "$date": { "$numberLong": "1" } } } ] } ] }, { "description": "Aggregate with $lt below min", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "local": { "key": { "$binary": { "base64": "Mng0NCt4ZHVUYUJCa1kxNkVyNUR1QURhZ2h2UzR2d2RrZzh0cFBwM3R6NmdWMDFBMUN3YkQ5aXRRMkhGRGdQV09wOGVNYUMxT2k3NjZKelhaQmRCZGJkTXVyZG9uSjFk", "subType": "00" } } } } } }, "operations": [ { "name": "insertOne", "arguments": { "document": { "_id": 0, "encryptedDate": { "$date": { "$numberLong": "0" } } } } }, { "name": "insertOne", "arguments": { "document": { "_id": 1, "encryptedDate": { "$date": { "$numberLong": "1" } } } } }, { "name": "aggregate", "arguments": { "pipeline": [ { "$match": { "encryptedDate": { "$lt": { "$date": { "$numberLong": "0" } } } } } ] }, "result": { "errorContains": "must be greater than the range minimum" } } ] }, { "description": "Aggregate with $gt above max", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "local": { "key": { "$binary": { "base64": "Mng0NCt4ZHVUYUJCa1kxNkVyNUR1QURhZ2h2UzR2d2RrZzh0cFBwM3R6NmdWMDFBMUN3YkQ5aXRRMkhGRGdQV09wOGVNYUMxT2k3NjZKelhaQmRCZGJkTXVyZG9uSjFk", "subType": "00" } } } } } }, "operations": [ { "name": "insertOne", "arguments": { "document": { "_id": 0, "encryptedDate": { "$date": { "$numberLong": "0" } } } } }, { "name": "insertOne", "arguments": { "document": { "_id": 1, "encryptedDate": { "$date": { "$numberLong": "1" } } } } }, { "name": "aggregate", "arguments": { "pipeline": [ { "$match": { "encryptedDate": { "$gt": { "$date": { "$numberLong": "200" } } } } } ] }, "result": { "errorContains": "must be less than the range maximum" } } ] }, { "description": "Aggregate with $gt and $lt", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "local": { "key": { "$binary": { "base64": "Mng0NCt4ZHVUYUJCa1kxNkVyNUR1QURhZ2h2UzR2d2RrZzh0cFBwM3R6NmdWMDFBMUN3YkQ5aXRRMkhGRGdQV09wOGVNYUMxT2k3NjZKelhaQmRCZGJkTXVyZG9uSjFk", "subType": "00" } } } } } }, "operations": [ { "name": "insertOne", "arguments": { "document": { "_id": 0, "encryptedDate": { "$date": { "$numberLong": "0" } } } } }, { "name": "insertOne", "arguments": { "document": { "_id": 1, "encryptedDate": { "$date": { "$numberLong": "1" } } } } }, { "name": "aggregate", "arguments": { "pipeline": [ { "$match": { "encryptedDate": { "$gt": { "$date": { "$numberLong": "0" } }, "$lt": { "$date": { "$numberLong": "2" } } } } } ] }, "result": [ { "_id": 1, "encryptedDate": { "$date": { "$numberLong": "1" } } } ] } ] }, { "description": "Aggregate with equality", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "local": { "key": { "$binary": { "base64": "Mng0NCt4ZHVUYUJCa1kxNkVyNUR1QURhZ2h2UzR2d2RrZzh0cFBwM3R6NmdWMDFBMUN3YkQ5aXRRMkhGRGdQV09wOGVNYUMxT2k3NjZKelhaQmRCZGJkTXVyZG9uSjFk", "subType": "00" } } } } } }, "operations": [ { "name": "insertOne", "arguments": { "document": { "_id": 0, "encryptedDate": { "$date": { "$numberLong": "0" } } } } }, { "name": "insertOne", "arguments": { "document": { "_id": 1, "encryptedDate": { "$date": { "$numberLong": "1" } } } } }, { "name": "aggregate", "arguments": { "pipeline": [ { "$match": { "encryptedDate": { "$date": { "$numberLong": "0" } } } } ] }, "result": [ { "_id": 0, "encryptedDate": { "$date": { "$numberLong": "0" } } } ] }, { "name": "aggregate", "arguments": { "pipeline": [ { "$match": { "encryptedDate": { "$date": { "$numberLong": "1" } } } } ] }, "result": [ { "_id": 1, "encryptedDate": { "$date": { "$numberLong": "1" } } } ] } ] }, { "description": "Aggregate with full range", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "local": { "key": { "$binary": { "base64": "Mng0NCt4ZHVUYUJCa1kxNkVyNUR1QURhZ2h2UzR2d2RrZzh0cFBwM3R6NmdWMDFBMUN3YkQ5aXRRMkhGRGdQV09wOGVNYUMxT2k3NjZKelhaQmRCZGJkTXVyZG9uSjFk", "subType": "00" } } } } } }, "operations": [ { "name": "insertOne", "arguments": { "document": { "_id": 0, "encryptedDate": { "$date": { "$numberLong": "0" } } } } }, { "name": "insertOne", "arguments": { "document": { "_id": 1, "encryptedDate": { "$date": { "$numberLong": "1" } } } } }, { "name": "aggregate", "arguments": { "pipeline": [ { "$match": { "encryptedDate": { "$gte": { "$date": { "$numberLong": "0" } }, "$lte": { "$date": { "$numberLong": "200" } } } } }, { "$sort": { "_id": 1 } } ] }, "result": [ { "_id": 0, "encryptedDate": { "$date": { "$numberLong": "0" } } }, { "_id": 1, "encryptedDate": { "$date": { "$numberLong": "1" } } } ] } ] }, { "description": "Aggregate with $in", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "local": { "key": { "$binary": { "base64": "Mng0NCt4ZHVUYUJCa1kxNkVyNUR1QURhZ2h2UzR2d2RrZzh0cFBwM3R6NmdWMDFBMUN3YkQ5aXRRMkhGRGdQV09wOGVNYUMxT2k3NjZKelhaQmRCZGJkTXVyZG9uSjFk", "subType": "00" } } } } } }, "operations": [ { "name": "insertOne", "arguments": { "document": { "_id": 0, "encryptedDate": { "$date": { "$numberLong": "0" } } } } }, { "name": "insertOne", "arguments": { "document": { "_id": 1, "encryptedDate": { "$date": { "$numberLong": "1" } } } } }, { "name": "aggregate", "arguments": { "pipeline": [ { "$match": { "encryptedDate": { "$in": [ { "$date": { "$numberLong": "0" } } ] } } } ] }, "result": [ { "_id": 0, "encryptedDate": { "$date": { "$numberLong": "0" } } } ] } ] }, { "description": "Wrong type: Insert Double", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "local": { "key": { "$binary": { "base64": "Mng0NCt4ZHVUYUJCa1kxNkVyNUR1QURhZ2h2UzR2d2RrZzh0cFBwM3R6NmdWMDFBMUN3YkQ5aXRRMkhGRGdQV09wOGVNYUMxT2k3NjZKelhaQmRCZGJkTXVyZG9uSjFk", "subType": "00" } } } } } }, "operations": [ { "name": "insertOne", "arguments": { "document": { "_id": 0, "encryptedDate": { "$numberDouble": "0" } } }, "result": { "errorContains": "cannot encrypt element" } } ] }, { "description": "Wrong type: Find Double", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "local": { "key": { "$binary": { "base64": "Mng0NCt4ZHVUYUJCa1kxNkVyNUR1QURhZ2h2UzR2d2RrZzh0cFBwM3R6NmdWMDFBMUN3YkQ5aXRRMkhGRGdQV09wOGVNYUMxT2k3NjZKelhaQmRCZGJkTXVyZG9uSjFk", "subType": "00" } } } } } }, "operations": [ { "name": "find", "arguments": { "filter": { "encryptedDate": { "$gte": { "$numberDouble": "0" } } } }, "result": { "errorContains": "value type is a date" } } ] } ] } fle2v2-Range-Date-Delete.json000066400000000000000000000335211462766011000342270ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/client-side-encryption/spec/legacy{ "runOn": [ { "minServerVersion": "7.0.0", "topology": [ "replicaset", "sharded", "load-balanced" ] } ], "database_name": "default", "collection_name": "default", "data": [], "encrypted_fields": { "fields": [ { "keyId": { "$binary": { "base64": "EjRWeBI0mHYSNBI0VniQEg==", "subType": "04" } }, "path": "encryptedDate", "bsonType": "date", "queries": { "queryType": "rangePreview", "contention": { "$numberLong": "0" }, "sparsity": { "$numberLong": "1" }, "min": { "$date": { "$numberLong": "0" } }, "max": { "$date": { "$numberLong": "200" } } } } ] }, "key_vault_data": [ { "_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" } } ], "tests": [ { "description": "FLE2 Range Date. Delete.", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "local": { "key": { "$binary": { "base64": "Mng0NCt4ZHVUYUJCa1kxNkVyNUR1QURhZ2h2UzR2d2RrZzh0cFBwM3R6NmdWMDFBMUN3YkQ5aXRRMkhGRGdQV09wOGVNYUMxT2k3NjZKelhaQmRCZGJkTXVyZG9uSjFk", "subType": "00" } } } } } }, "operations": [ { "name": "insertOne", "arguments": { "document": { "_id": 0, "encryptedDate": { "$date": { "$numberLong": "0" } } } } }, { "name": "insertOne", "arguments": { "document": { "_id": 1, "encryptedDate": { "$date": { "$numberLong": "1" } } } } }, { "name": "deleteOne", "arguments": { "filter": { "encryptedDate": { "$gt": { "$date": { "$numberLong": "0" } } } } }, "result": { "deletedCount": 1 } } ], "expectations": [ { "command_started_event": { "command": { "listCollections": 1, "filter": { "name": "default" } }, "command_name": "listCollections" } }, { "command_started_event": { "command": { "find": "datakeys", "filter": { "$or": [ { "_id": { "$in": [ { "$binary": { "base64": "EjRWeBI0mHYSNBI0VniQEg==", "subType": "04" } } ] } }, { "keyAltNames": { "$in": [] } } ] }, "$db": "keyvault", "readConcern": { "level": "majority" } }, "command_name": "find" } }, { "command_started_event": { "command": { "insert": "default", "documents": [ { "_id": 0, "encryptedDate": { "$$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": "encryptedDate", "bsonType": "date", "queries": { "queryType": "rangePreview", "contention": { "$numberLong": "0" }, "sparsity": { "$numberLong": "1" }, "min": { "$date": { "$numberLong": "0" } }, "max": { "$date": { "$numberLong": "200" } } } } ] } } } }, "command_name": "insert" } }, { "command_started_event": { "command": { "insert": "default", "documents": [ { "_id": 1, "encryptedDate": { "$$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": "encryptedDate", "bsonType": "date", "queries": { "queryType": "rangePreview", "contention": { "$numberLong": "0" }, "sparsity": { "$numberLong": "1" }, "min": { "$date": { "$numberLong": "0" } }, "max": { "$date": { "$numberLong": "200" } } } } ] } } } }, "command_name": "insert" } }, { "command_started_event": { "command": { "delete": "default", "deletes": [ { "q": { "encryptedDate": { "$gt": { "$binary": { "base64": "DUkFAAADcGF5bG9hZAAZBQAABGcABQUAAAMwAH0AAAAFZAAgAAAAALGGQ/CRD+pGLD53BZzWcCcYbuGLVEyjzXIx7b+ux/q2BXMAIAAAAACOC6mXEZL27P9hethZbtKYsTXKK+FpgQ9Axxmn9N/cCwVsACAAAAAA+MFEd8XfZSpbXKqqPC2L3TEFswkaG5Ff6aSgf8p+XVIAAzEAfQAAAAVkACAAAAAAtL3QIvnZqCF72eS6lKr8ilff7R6kiNklokiTuaU5wNsFcwAgAAAAAEtqr3/X731VB+VrbFcY8ZrJKRo2E0Fd+C8L0EMNcvcCBWwAIAAAAABNPhSriux8W8qbwnhCczE3IzlhNEnGDpUwTFDZSL+eYQADMgB9AAAABWQAIAAAAAB99ZW/7KwXKzl5M3XQsAJ3JbEef90IoxFYBArNiYzlgQVzACAAAAAAYO/qaw0+92HAryxOUG7iK6hnIy3OaUA9jIqtHdvcq8YFbAAgAAAAAHrUYj8A0hVgc6VklpDiljOnykrUSfEsjm56XO/bsfKdAAMzAH0AAAAFZAAgAAAAAOK8brUuc2onBNDRtfYMR736dHj4dQqXod8JG7tAMTsDBXMAIAAAAAAW6SrGAL6Bx0s7ZlsYULFfOAiYIGhEWu6md3r+Rk40awVsACAAAAAAIHYXP8RLcCboUmHN3+OlnEw1DxaLSnbTB9PdF228fFAAAzQAfQAAAAVkACAAAAAAV22FGF7ZDwK/EYiGNMlm/QuT3saQdyJM/Fn+ZyQug1oFcwAgAAAAACo7GwCvbcs5UHQMgds9/1QMklEVdjZigpuOFGrDmmxtBWwAIAAAAADQbYYPxlCMMGe2MulbiurApFLoeJSMvTeDU3pyEA2jNwADNQB9AAAABWQAIAAAAADFspsMG7yHjKppyllon1KqAsTrHaZ6JzNqnSz8o6iTvwVzACAAAAAAeiA5pqVIQQ9s6UY/P8v5Jjkl3I7iFNeLDYehikrINrsFbAAgAAAAAFjBTzTpNxDEkA0vSRj0jCED9KDRlboMVyilKyDz5YR4AAM2AH0AAAAFZAAgAAAAAPcLmtq+V1e+MRlZ7NHq1+mrRVBQje5zj685ZvdsfKvSBXMAIAAAAABdHz/3w2k5km97QN9m7oLFYJaVJneNlMboIlz5yUASQAVsACAAAAAAWbp8JVJnx8fEVAJFa7WMfMa7wXeP5M3C8MX20J/i9n0AAzcAfQAAAAVkACAAAAAAYfLwnoxK6XAGQrJFy8+TIJoq38ldBaO75h4zA4ZX5tQFcwAgAAAAAC2wk8UcJH5X5XGnDBYmel6srpBkzBhHtt3Jw1u5TSJ1BWwAIAAAAAA9/YU9eI3D7QbXKIw/3/gzWJ6MZrCYhG0j1wNKgRQp5wADOAB9AAAABWQAIAAAAADGvyrtKkIcaV17ynZA7b2k5Pz6OhvxdWNkDvDWJIja8wVzACAAAAAAOLypVKNxf/wR1G8OZjUUsTQzDYeNNhhITxGMSp7euS4FbAAgAAAAAA9EsxoV1B2DcQ1NJRwuxXnvVR+vkD0wbbDYEI/zFEnDAAM5AH0AAAAFZAAgAAAAAEocREw1L0g+roFUchJI2Yd0M0ME2bnErNUYnpyJP1SqBXMAIAAAAAAcE2/JK/8MoSeOchIuAkKh1X3ImoA7p8ujAZIfvIDo6QVsACAAAAAA+W0+zgLr85/PD7P9a94wk6MgNgrizx/XU9aCxAkp1IwAABJjbQAAAAAAAAAAAAAQcGF5bG9hZElkAAAAAAAQZmlyc3RPcGVyYXRvcgABAAAAAA==", "subType": "06" } } } }, "limit": 1 } ], "ordered": true, "encryptionInformation": { "type": 1, "schema": { "default.default": { "escCollection": "enxcol_.default.esc", "ecocCollection": "enxcol_.default.ecoc", "fields": [ { "keyId": { "$binary": { "base64": "EjRWeBI0mHYSNBI0VniQEg==", "subType": "04" } }, "path": "encryptedDate", "bsonType": "date", "queries": { "queryType": "rangePreview", "contention": { "$numberLong": "0" }, "sparsity": { "$numberLong": "1" }, "min": { "$date": { "$numberLong": "0" } }, "max": { "$date": { "$numberLong": "200" } } } } ] } } } }, "command_name": "delete" } } ], "outcome": { "collection": { "data": [ { "_id": 0, "encryptedDate": { "$$type": "binData" }, "__safeContent__": [ { "$binary": { "base64": "5nRutVIyq7URVOVtbE4vM01APSIajAVnsShMwjBlzkM=", "subType": "00" } }, { "$binary": { "base64": "RjBYT2h3ZAoHxhf8DU6/dFbDkEBZp0IxREcsRTu2MXs=", "subType": "00" } }, { "$binary": { "base64": "x7GR49EN0t3WXQDihkrbonK7qNIBYC87tpL/XEUyIYc=", "subType": "00" } }, { "$binary": { "base64": "JfYUqWF+OoGjiYkRI4L5iPlF+T1Eleul7Fki22jp4Qc=", "subType": "00" } }, { "$binary": { "base64": "q1RyGfIgsaQHoZFRw+DD28V26rN5hweApPLwExncvT8=", "subType": "00" } }, { "$binary": { "base64": "L2PFeKGvLS6C+DLudR6fGlBq3ERPvjWvRyNRIA2HVb0=", "subType": "00" } }, { "$binary": { "base64": "CWxaNqL3iP1yCixDkcmf9bmW3E5VeN8TJkg1jJe528s=", "subType": "00" } }, { "$binary": { "base64": "+vC6araOEo+fpW7PSIP40/EnzBCj1d2N10Jr3rrXJJM=", "subType": "00" } }, { "$binary": { "base64": "6SV63Mf51Z6A6p2X3rCnJKCu6ku3Oeb45mBYbz+IoAo=", "subType": "00" } } ] } ] } } } ] } fle2v2-Range-Date-FindOneAndUpdate.json000066400000000000000000000403041462766011000361320ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/client-side-encryption/spec/legacy{ "runOn": [ { "minServerVersion": "7.0.0", "topology": [ "replicaset", "sharded", "load-balanced" ] } ], "database_name": "default", "collection_name": "default", "data": [], "encrypted_fields": { "fields": [ { "keyId": { "$binary": { "base64": "EjRWeBI0mHYSNBI0VniQEg==", "subType": "04" } }, "path": "encryptedDate", "bsonType": "date", "queries": { "queryType": "rangePreview", "contention": { "$numberLong": "0" }, "sparsity": { "$numberLong": "1" }, "min": { "$date": { "$numberLong": "0" } }, "max": { "$date": { "$numberLong": "200" } } } } ] }, "key_vault_data": [ { "_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" } } ], "tests": [ { "description": "FLE2 Range Date. FindOneAndUpdate.", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "local": { "key": { "$binary": { "base64": "Mng0NCt4ZHVUYUJCa1kxNkVyNUR1QURhZ2h2UzR2d2RrZzh0cFBwM3R6NmdWMDFBMUN3YkQ5aXRRMkhGRGdQV09wOGVNYUMxT2k3NjZKelhaQmRCZGJkTXVyZG9uSjFk", "subType": "00" } } } } } }, "operations": [ { "name": "insertOne", "arguments": { "document": { "_id": 0, "encryptedDate": { "$date": { "$numberLong": "0" } } } } }, { "name": "insertOne", "arguments": { "document": { "_id": 1, "encryptedDate": { "$date": { "$numberLong": "1" } } } } }, { "name": "findOneAndUpdate", "arguments": { "filter": { "encryptedDate": { "$gt": { "$date": { "$numberLong": "0" } } } }, "update": { "$set": { "encryptedDate": { "$date": { "$numberLong": "2" } } } }, "returnDocument": "Before" }, "result": { "_id": 1, "encryptedDate": { "$date": { "$numberLong": "1" } } } } ], "expectations": [ { "command_started_event": { "command": { "listCollections": 1, "filter": { "name": "default" } }, "command_name": "listCollections" } }, { "command_started_event": { "command": { "find": "datakeys", "filter": { "$or": [ { "_id": { "$in": [ { "$binary": { "base64": "EjRWeBI0mHYSNBI0VniQEg==", "subType": "04" } } ] } }, { "keyAltNames": { "$in": [] } } ] }, "$db": "keyvault", "readConcern": { "level": "majority" } }, "command_name": "find" } }, { "command_started_event": { "command": { "insert": "default", "documents": [ { "_id": 0, "encryptedDate": { "$$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": "encryptedDate", "bsonType": "date", "queries": { "queryType": "rangePreview", "contention": { "$numberLong": "0" }, "sparsity": { "$numberLong": "1" }, "min": { "$date": { "$numberLong": "0" } }, "max": { "$date": { "$numberLong": "200" } } } } ] } } } }, "command_name": "insert" } }, { "command_started_event": { "command": { "insert": "default", "documents": [ { "_id": 1, "encryptedDate": { "$$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": "encryptedDate", "bsonType": "date", "queries": { "queryType": "rangePreview", "contention": { "$numberLong": "0" }, "sparsity": { "$numberLong": "1" }, "min": { "$date": { "$numberLong": "0" } }, "max": { "$date": { "$numberLong": "200" } } } } ] } } } }, "command_name": "insert" } }, { "command_started_event": { "command": { "findAndModify": "default", "query": { "encryptedDate": { "$gt": { "$binary": { "base64": "DUkFAAADcGF5bG9hZAAZBQAABGcABQUAAAMwAH0AAAAFZAAgAAAAALGGQ/CRD+pGLD53BZzWcCcYbuGLVEyjzXIx7b+ux/q2BXMAIAAAAACOC6mXEZL27P9hethZbtKYsTXKK+FpgQ9Axxmn9N/cCwVsACAAAAAA+MFEd8XfZSpbXKqqPC2L3TEFswkaG5Ff6aSgf8p+XVIAAzEAfQAAAAVkACAAAAAAtL3QIvnZqCF72eS6lKr8ilff7R6kiNklokiTuaU5wNsFcwAgAAAAAEtqr3/X731VB+VrbFcY8ZrJKRo2E0Fd+C8L0EMNcvcCBWwAIAAAAABNPhSriux8W8qbwnhCczE3IzlhNEnGDpUwTFDZSL+eYQADMgB9AAAABWQAIAAAAAB99ZW/7KwXKzl5M3XQsAJ3JbEef90IoxFYBArNiYzlgQVzACAAAAAAYO/qaw0+92HAryxOUG7iK6hnIy3OaUA9jIqtHdvcq8YFbAAgAAAAAHrUYj8A0hVgc6VklpDiljOnykrUSfEsjm56XO/bsfKdAAMzAH0AAAAFZAAgAAAAAOK8brUuc2onBNDRtfYMR736dHj4dQqXod8JG7tAMTsDBXMAIAAAAAAW6SrGAL6Bx0s7ZlsYULFfOAiYIGhEWu6md3r+Rk40awVsACAAAAAAIHYXP8RLcCboUmHN3+OlnEw1DxaLSnbTB9PdF228fFAAAzQAfQAAAAVkACAAAAAAV22FGF7ZDwK/EYiGNMlm/QuT3saQdyJM/Fn+ZyQug1oFcwAgAAAAACo7GwCvbcs5UHQMgds9/1QMklEVdjZigpuOFGrDmmxtBWwAIAAAAADQbYYPxlCMMGe2MulbiurApFLoeJSMvTeDU3pyEA2jNwADNQB9AAAABWQAIAAAAADFspsMG7yHjKppyllon1KqAsTrHaZ6JzNqnSz8o6iTvwVzACAAAAAAeiA5pqVIQQ9s6UY/P8v5Jjkl3I7iFNeLDYehikrINrsFbAAgAAAAAFjBTzTpNxDEkA0vSRj0jCED9KDRlboMVyilKyDz5YR4AAM2AH0AAAAFZAAgAAAAAPcLmtq+V1e+MRlZ7NHq1+mrRVBQje5zj685ZvdsfKvSBXMAIAAAAABdHz/3w2k5km97QN9m7oLFYJaVJneNlMboIlz5yUASQAVsACAAAAAAWbp8JVJnx8fEVAJFa7WMfMa7wXeP5M3C8MX20J/i9n0AAzcAfQAAAAVkACAAAAAAYfLwnoxK6XAGQrJFy8+TIJoq38ldBaO75h4zA4ZX5tQFcwAgAAAAAC2wk8UcJH5X5XGnDBYmel6srpBkzBhHtt3Jw1u5TSJ1BWwAIAAAAAA9/YU9eI3D7QbXKIw/3/gzWJ6MZrCYhG0j1wNKgRQp5wADOAB9AAAABWQAIAAAAADGvyrtKkIcaV17ynZA7b2k5Pz6OhvxdWNkDvDWJIja8wVzACAAAAAAOLypVKNxf/wR1G8OZjUUsTQzDYeNNhhITxGMSp7euS4FbAAgAAAAAA9EsxoV1B2DcQ1NJRwuxXnvVR+vkD0wbbDYEI/zFEnDAAM5AH0AAAAFZAAgAAAAAEocREw1L0g+roFUchJI2Yd0M0ME2bnErNUYnpyJP1SqBXMAIAAAAAAcE2/JK/8MoSeOchIuAkKh1X3ImoA7p8ujAZIfvIDo6QVsACAAAAAA+W0+zgLr85/PD7P9a94wk6MgNgrizx/XU9aCxAkp1IwAABJjbQAAAAAAAAAAAAAQcGF5bG9hZElkAAAAAAAQZmlyc3RPcGVyYXRvcgABAAAAAA==", "subType": "06" } } } }, "update": { "$set": { "encryptedDate": { "$$type": "binData" } } }, "encryptionInformation": { "type": 1, "schema": { "default.default": { "escCollection": "enxcol_.default.esc", "ecocCollection": "enxcol_.default.ecoc", "fields": [ { "keyId": { "$binary": { "base64": "EjRWeBI0mHYSNBI0VniQEg==", "subType": "04" } }, "path": "encryptedDate", "bsonType": "date", "queries": { "queryType": "rangePreview", "contention": { "$numberLong": "0" }, "sparsity": { "$numberLong": "1" }, "min": { "$date": { "$numberLong": "0" } }, "max": { "$date": { "$numberLong": "200" } } } } ] } } } }, "command_name": "findAndModify" } } ], "outcome": { "collection": { "data": [ { "_id": 0, "encryptedDate": { "$$type": "binData" }, "__safeContent__": [ { "$binary": { "base64": "5nRutVIyq7URVOVtbE4vM01APSIajAVnsShMwjBlzkM=", "subType": "00" } }, { "$binary": { "base64": "RjBYT2h3ZAoHxhf8DU6/dFbDkEBZp0IxREcsRTu2MXs=", "subType": "00" } }, { "$binary": { "base64": "x7GR49EN0t3WXQDihkrbonK7qNIBYC87tpL/XEUyIYc=", "subType": "00" } }, { "$binary": { "base64": "JfYUqWF+OoGjiYkRI4L5iPlF+T1Eleul7Fki22jp4Qc=", "subType": "00" } }, { "$binary": { "base64": "q1RyGfIgsaQHoZFRw+DD28V26rN5hweApPLwExncvT8=", "subType": "00" } }, { "$binary": { "base64": "L2PFeKGvLS6C+DLudR6fGlBq3ERPvjWvRyNRIA2HVb0=", "subType": "00" } }, { "$binary": { "base64": "CWxaNqL3iP1yCixDkcmf9bmW3E5VeN8TJkg1jJe528s=", "subType": "00" } }, { "$binary": { "base64": "+vC6araOEo+fpW7PSIP40/EnzBCj1d2N10Jr3rrXJJM=", "subType": "00" } }, { "$binary": { "base64": "6SV63Mf51Z6A6p2X3rCnJKCu6ku3Oeb45mBYbz+IoAo=", "subType": "00" } } ] }, { "_id": 1, "encryptedDate": { "$$type": "binData" }, "__safeContent__": [ { "$binary": { "base64": "DLCAJs+W2PL2DV5YChCL6dYrQNr+j4p3L7xhVaub4ic=", "subType": "00" } }, { "$binary": { "base64": "hyDcE6QQjPrYJaIS/n7evEZFYcm31Tj89CpEYGF45cI=", "subType": "00" } }, { "$binary": { "base64": "F08nMDWDZc+DbWM7XCEJNNCEYyinRmrvGP7EWhmp4is=", "subType": "00" } }, { "$binary": { "base64": "cXH4688amcDc8kZOJq4UP8cE3R58Zl7e+Qo/1jyspps=", "subType": "00" } }, { "$binary": { "base64": "uURBxvTp3FBCVkd+LPqyuY7d6rMW6SGIJQEPY/wtkZI=", "subType": "00" } }, { "$binary": { "base64": "jG3hax1L3RBp9t38vUt53FsBxgr/+Si/vVISpAylYpE=", "subType": "00" } }, { "$binary": { "base64": "kwtIW8MhH9Ky5xNjBx8gFA/SHh2YVphie7g5FGBzals=", "subType": "00" } }, { "$binary": { "base64": "FHflwFuEMu4xX0ZApHi+pdlBH+oevAtXckCUb5Wv0xU=", "subType": "00" } }, { "$binary": { "base64": "ty4cnzJdAlbQKnh7px3GEYjBnvO+jIOaKjoTRDtmh3M=", "subType": "00" } } ] } ] } } } ] } fle2v2-Range-Date-InsertFind.json000066400000000000000000000374221462766011000350760ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/client-side-encryption/spec/legacy{ "runOn": [ { "minServerVersion": "7.0.0", "topology": [ "replicaset", "sharded", "load-balanced" ] } ], "database_name": "default", "collection_name": "default", "data": [], "encrypted_fields": { "fields": [ { "keyId": { "$binary": { "base64": "EjRWeBI0mHYSNBI0VniQEg==", "subType": "04" } }, "path": "encryptedDate", "bsonType": "date", "queries": { "queryType": "rangePreview", "contention": { "$numberLong": "0" }, "sparsity": { "$numberLong": "1" }, "min": { "$date": { "$numberLong": "0" } }, "max": { "$date": { "$numberLong": "200" } } } } ] }, "key_vault_data": [ { "_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" } } ], "tests": [ { "description": "FLE2 Range Date. Insert and Find.", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "local": { "key": { "$binary": { "base64": "Mng0NCt4ZHVUYUJCa1kxNkVyNUR1QURhZ2h2UzR2d2RrZzh0cFBwM3R6NmdWMDFBMUN3YkQ5aXRRMkhGRGdQV09wOGVNYUMxT2k3NjZKelhaQmRCZGJkTXVyZG9uSjFk", "subType": "00" } } } } } }, "operations": [ { "name": "insertOne", "arguments": { "document": { "_id": 0, "encryptedDate": { "$date": { "$numberLong": "0" } } } } }, { "name": "insertOne", "arguments": { "document": { "_id": 1, "encryptedDate": { "$date": { "$numberLong": "1" } } } } }, { "name": "find", "arguments": { "filter": { "encryptedDate": { "$gt": { "$date": { "$numberLong": "0" } } } } }, "result": [ { "_id": 1, "encryptedDate": { "$date": { "$numberLong": "1" } } } ] } ], "expectations": [ { "command_started_event": { "command": { "listCollections": 1, "filter": { "name": "default" } }, "command_name": "listCollections" } }, { "command_started_event": { "command": { "find": "datakeys", "filter": { "$or": [ { "_id": { "$in": [ { "$binary": { "base64": "EjRWeBI0mHYSNBI0VniQEg==", "subType": "04" } } ] } }, { "keyAltNames": { "$in": [] } } ] }, "$db": "keyvault", "readConcern": { "level": "majority" } }, "command_name": "find" } }, { "command_started_event": { "command": { "insert": "default", "documents": [ { "_id": 0, "encryptedDate": { "$$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": "encryptedDate", "bsonType": "date", "queries": { "queryType": "rangePreview", "contention": { "$numberLong": "0" }, "sparsity": { "$numberLong": "1" }, "min": { "$date": { "$numberLong": "0" } }, "max": { "$date": { "$numberLong": "200" } } } } ] } } } }, "command_name": "insert" } }, { "command_started_event": { "command": { "insert": "default", "documents": [ { "_id": 1, "encryptedDate": { "$$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": "encryptedDate", "bsonType": "date", "queries": { "queryType": "rangePreview", "contention": { "$numberLong": "0" }, "sparsity": { "$numberLong": "1" }, "min": { "$date": { "$numberLong": "0" } }, "max": { "$date": { "$numberLong": "200" } } } } ] } } } }, "command_name": "insert" } }, { "command_started_event": { "command": { "find": "default", "filter": { "encryptedDate": { "$gt": { "$binary": { "base64": "DUkFAAADcGF5bG9hZAAZBQAABGcABQUAAAMwAH0AAAAFZAAgAAAAALGGQ/CRD+pGLD53BZzWcCcYbuGLVEyjzXIx7b+ux/q2BXMAIAAAAACOC6mXEZL27P9hethZbtKYsTXKK+FpgQ9Axxmn9N/cCwVsACAAAAAA+MFEd8XfZSpbXKqqPC2L3TEFswkaG5Ff6aSgf8p+XVIAAzEAfQAAAAVkACAAAAAAtL3QIvnZqCF72eS6lKr8ilff7R6kiNklokiTuaU5wNsFcwAgAAAAAEtqr3/X731VB+VrbFcY8ZrJKRo2E0Fd+C8L0EMNcvcCBWwAIAAAAABNPhSriux8W8qbwnhCczE3IzlhNEnGDpUwTFDZSL+eYQADMgB9AAAABWQAIAAAAAB99ZW/7KwXKzl5M3XQsAJ3JbEef90IoxFYBArNiYzlgQVzACAAAAAAYO/qaw0+92HAryxOUG7iK6hnIy3OaUA9jIqtHdvcq8YFbAAgAAAAAHrUYj8A0hVgc6VklpDiljOnykrUSfEsjm56XO/bsfKdAAMzAH0AAAAFZAAgAAAAAOK8brUuc2onBNDRtfYMR736dHj4dQqXod8JG7tAMTsDBXMAIAAAAAAW6SrGAL6Bx0s7ZlsYULFfOAiYIGhEWu6md3r+Rk40awVsACAAAAAAIHYXP8RLcCboUmHN3+OlnEw1DxaLSnbTB9PdF228fFAAAzQAfQAAAAVkACAAAAAAV22FGF7ZDwK/EYiGNMlm/QuT3saQdyJM/Fn+ZyQug1oFcwAgAAAAACo7GwCvbcs5UHQMgds9/1QMklEVdjZigpuOFGrDmmxtBWwAIAAAAADQbYYPxlCMMGe2MulbiurApFLoeJSMvTeDU3pyEA2jNwADNQB9AAAABWQAIAAAAADFspsMG7yHjKppyllon1KqAsTrHaZ6JzNqnSz8o6iTvwVzACAAAAAAeiA5pqVIQQ9s6UY/P8v5Jjkl3I7iFNeLDYehikrINrsFbAAgAAAAAFjBTzTpNxDEkA0vSRj0jCED9KDRlboMVyilKyDz5YR4AAM2AH0AAAAFZAAgAAAAAPcLmtq+V1e+MRlZ7NHq1+mrRVBQje5zj685ZvdsfKvSBXMAIAAAAABdHz/3w2k5km97QN9m7oLFYJaVJneNlMboIlz5yUASQAVsACAAAAAAWbp8JVJnx8fEVAJFa7WMfMa7wXeP5M3C8MX20J/i9n0AAzcAfQAAAAVkACAAAAAAYfLwnoxK6XAGQrJFy8+TIJoq38ldBaO75h4zA4ZX5tQFcwAgAAAAAC2wk8UcJH5X5XGnDBYmel6srpBkzBhHtt3Jw1u5TSJ1BWwAIAAAAAA9/YU9eI3D7QbXKIw/3/gzWJ6MZrCYhG0j1wNKgRQp5wADOAB9AAAABWQAIAAAAADGvyrtKkIcaV17ynZA7b2k5Pz6OhvxdWNkDvDWJIja8wVzACAAAAAAOLypVKNxf/wR1G8OZjUUsTQzDYeNNhhITxGMSp7euS4FbAAgAAAAAA9EsxoV1B2DcQ1NJRwuxXnvVR+vkD0wbbDYEI/zFEnDAAM5AH0AAAAFZAAgAAAAAEocREw1L0g+roFUchJI2Yd0M0ME2bnErNUYnpyJP1SqBXMAIAAAAAAcE2/JK/8MoSeOchIuAkKh1X3ImoA7p8ujAZIfvIDo6QVsACAAAAAA+W0+zgLr85/PD7P9a94wk6MgNgrizx/XU9aCxAkp1IwAABJjbQAAAAAAAAAAAAAQcGF5bG9hZElkAAAAAAAQZmlyc3RPcGVyYXRvcgABAAAAAA==", "subType": "06" } } } }, "encryptionInformation": { "type": 1, "schema": { "default.default": { "escCollection": "enxcol_.default.esc", "ecocCollection": "enxcol_.default.ecoc", "fields": [ { "keyId": { "$binary": { "base64": "EjRWeBI0mHYSNBI0VniQEg==", "subType": "04" } }, "path": "encryptedDate", "bsonType": "date", "queries": { "queryType": "rangePreview", "contention": { "$numberLong": "0" }, "sparsity": { "$numberLong": "1" }, "min": { "$date": { "$numberLong": "0" } }, "max": { "$date": { "$numberLong": "200" } } } } ] } } } }, "command_name": "find" } } ], "outcome": { "collection": { "data": [ { "_id": 0, "encryptedDate": { "$$type": "binData" }, "__safeContent__": [ { "$binary": { "base64": "5nRutVIyq7URVOVtbE4vM01APSIajAVnsShMwjBlzkM=", "subType": "00" } }, { "$binary": { "base64": "RjBYT2h3ZAoHxhf8DU6/dFbDkEBZp0IxREcsRTu2MXs=", "subType": "00" } }, { "$binary": { "base64": "x7GR49EN0t3WXQDihkrbonK7qNIBYC87tpL/XEUyIYc=", "subType": "00" } }, { "$binary": { "base64": "JfYUqWF+OoGjiYkRI4L5iPlF+T1Eleul7Fki22jp4Qc=", "subType": "00" } }, { "$binary": { "base64": "q1RyGfIgsaQHoZFRw+DD28V26rN5hweApPLwExncvT8=", "subType": "00" } }, { "$binary": { "base64": "L2PFeKGvLS6C+DLudR6fGlBq3ERPvjWvRyNRIA2HVb0=", "subType": "00" } }, { "$binary": { "base64": "CWxaNqL3iP1yCixDkcmf9bmW3E5VeN8TJkg1jJe528s=", "subType": "00" } }, { "$binary": { "base64": "+vC6araOEo+fpW7PSIP40/EnzBCj1d2N10Jr3rrXJJM=", "subType": "00" } }, { "$binary": { "base64": "6SV63Mf51Z6A6p2X3rCnJKCu6ku3Oeb45mBYbz+IoAo=", "subType": "00" } } ] }, { "_id": 1, "encryptedDate": { "$$type": "binData" }, "__safeContent__": [ { "$binary": { "base64": "bE1vqWj3KNyM7cCYUv/cnYm8BPaUL3eMp5syTHq6NF4=", "subType": "00" } }, { "$binary": { "base64": "25j9sQXZCihCmHKvTHgaBsAVZFcGPn7JjHdrCGlwyyw=", "subType": "00" } }, { "$binary": { "base64": "FA74j21GUEJb1DJBOpR9nVnjaDZnd8yAQNuaW9Qi26g=", "subType": "00" } }, { "$binary": { "base64": "kJv//KVkbrobIBf+QeWC5jxn20mx/P0R1N6aCSMgKM8=", "subType": "00" } }, { "$binary": { "base64": "zB+Whi9IUUGxfLEe+lGuIzLX4LFbIhaIAm5lRk65QTc=", "subType": "00" } }, { "$binary": { "base64": "ybO1QU3CgvhO8JgRXH+HxKszWcpl5aGDYYVa75fHa1g=", "subType": "00" } }, { "$binary": { "base64": "X3Y3eSAbbMg//JgiHHiFpYOpV61t8kkDexI+CQyitH4=", "subType": "00" } }, { "$binary": { "base64": "SlNHXyqVFGDPrX/2ppwog6l4pwj3PKda2TkZbqgfSfA=", "subType": "00" } }, { "$binary": { "base64": "McjV8xwTF3xI7863DYOBdyvIv6UpzThl6v9vBRk05bI=", "subType": "00" } } ] } ] } } } ] } fle2v2-Range-Date-Update.json000066400000000000000000000404251462766011000342500ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/client-side-encryption/spec/legacy{ "runOn": [ { "minServerVersion": "7.0.0", "topology": [ "replicaset", "sharded", "load-balanced" ] } ], "database_name": "default", "collection_name": "default", "data": [], "encrypted_fields": { "fields": [ { "keyId": { "$binary": { "base64": "EjRWeBI0mHYSNBI0VniQEg==", "subType": "04" } }, "path": "encryptedDate", "bsonType": "date", "queries": { "queryType": "rangePreview", "contention": { "$numberLong": "0" }, "sparsity": { "$numberLong": "1" }, "min": { "$date": { "$numberLong": "0" } }, "max": { "$date": { "$numberLong": "200" } } } } ] }, "key_vault_data": [ { "_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" } } ], "tests": [ { "description": "FLE2 Range Date. Update.", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "local": { "key": { "$binary": { "base64": "Mng0NCt4ZHVUYUJCa1kxNkVyNUR1QURhZ2h2UzR2d2RrZzh0cFBwM3R6NmdWMDFBMUN3YkQ5aXRRMkhGRGdQV09wOGVNYUMxT2k3NjZKelhaQmRCZGJkTXVyZG9uSjFk", "subType": "00" } } } } } }, "operations": [ { "name": "insertOne", "arguments": { "document": { "_id": 0, "encryptedDate": { "$date": { "$numberLong": "0" } } } } }, { "name": "insertOne", "arguments": { "document": { "_id": 1, "encryptedDate": { "$date": { "$numberLong": "1" } } } } }, { "name": "updateOne", "arguments": { "filter": { "encryptedDate": { "$gt": { "$date": { "$numberLong": "0" } } } }, "update": { "$set": { "encryptedDate": { "$date": { "$numberLong": "2" } } } } }, "result": { "matchedCount": 1, "modifiedCount": 1, "upsertedCount": 0 } } ], "expectations": [ { "command_started_event": { "command": { "listCollections": 1, "filter": { "name": "default" } }, "command_name": "listCollections" } }, { "command_started_event": { "command": { "find": "datakeys", "filter": { "$or": [ { "_id": { "$in": [ { "$binary": { "base64": "EjRWeBI0mHYSNBI0VniQEg==", "subType": "04" } } ] } }, { "keyAltNames": { "$in": [] } } ] }, "$db": "keyvault", "readConcern": { "level": "majority" } }, "command_name": "find" } }, { "command_started_event": { "command": { "insert": "default", "documents": [ { "_id": 0, "encryptedDate": { "$$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": "encryptedDate", "bsonType": "date", "queries": { "queryType": "rangePreview", "contention": { "$numberLong": "0" }, "sparsity": { "$numberLong": "1" }, "min": { "$date": { "$numberLong": "0" } }, "max": { "$date": { "$numberLong": "200" } } } } ] } } } }, "command_name": "insert" } }, { "command_started_event": { "command": { "insert": "default", "documents": [ { "_id": 1, "encryptedDate": { "$$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": "encryptedDate", "bsonType": "date", "queries": { "queryType": "rangePreview", "contention": { "$numberLong": "0" }, "sparsity": { "$numberLong": "1" }, "min": { "$date": { "$numberLong": "0" } }, "max": { "$date": { "$numberLong": "200" } } } } ] } } } }, "command_name": "insert" } }, { "command_started_event": { "command_name": "update", "command": { "update": "default", "ordered": true, "updates": [ { "q": { "encryptedDate": { "$gt": { "$binary": { "base64": "DUkFAAADcGF5bG9hZAAZBQAABGcABQUAAAMwAH0AAAAFZAAgAAAAALGGQ/CRD+pGLD53BZzWcCcYbuGLVEyjzXIx7b+ux/q2BXMAIAAAAACOC6mXEZL27P9hethZbtKYsTXKK+FpgQ9Axxmn9N/cCwVsACAAAAAA+MFEd8XfZSpbXKqqPC2L3TEFswkaG5Ff6aSgf8p+XVIAAzEAfQAAAAVkACAAAAAAtL3QIvnZqCF72eS6lKr8ilff7R6kiNklokiTuaU5wNsFcwAgAAAAAEtqr3/X731VB+VrbFcY8ZrJKRo2E0Fd+C8L0EMNcvcCBWwAIAAAAABNPhSriux8W8qbwnhCczE3IzlhNEnGDpUwTFDZSL+eYQADMgB9AAAABWQAIAAAAAB99ZW/7KwXKzl5M3XQsAJ3JbEef90IoxFYBArNiYzlgQVzACAAAAAAYO/qaw0+92HAryxOUG7iK6hnIy3OaUA9jIqtHdvcq8YFbAAgAAAAAHrUYj8A0hVgc6VklpDiljOnykrUSfEsjm56XO/bsfKdAAMzAH0AAAAFZAAgAAAAAOK8brUuc2onBNDRtfYMR736dHj4dQqXod8JG7tAMTsDBXMAIAAAAAAW6SrGAL6Bx0s7ZlsYULFfOAiYIGhEWu6md3r+Rk40awVsACAAAAAAIHYXP8RLcCboUmHN3+OlnEw1DxaLSnbTB9PdF228fFAAAzQAfQAAAAVkACAAAAAAV22FGF7ZDwK/EYiGNMlm/QuT3saQdyJM/Fn+ZyQug1oFcwAgAAAAACo7GwCvbcs5UHQMgds9/1QMklEVdjZigpuOFGrDmmxtBWwAIAAAAADQbYYPxlCMMGe2MulbiurApFLoeJSMvTeDU3pyEA2jNwADNQB9AAAABWQAIAAAAADFspsMG7yHjKppyllon1KqAsTrHaZ6JzNqnSz8o6iTvwVzACAAAAAAeiA5pqVIQQ9s6UY/P8v5Jjkl3I7iFNeLDYehikrINrsFbAAgAAAAAFjBTzTpNxDEkA0vSRj0jCED9KDRlboMVyilKyDz5YR4AAM2AH0AAAAFZAAgAAAAAPcLmtq+V1e+MRlZ7NHq1+mrRVBQje5zj685ZvdsfKvSBXMAIAAAAABdHz/3w2k5km97QN9m7oLFYJaVJneNlMboIlz5yUASQAVsACAAAAAAWbp8JVJnx8fEVAJFa7WMfMa7wXeP5M3C8MX20J/i9n0AAzcAfQAAAAVkACAAAAAAYfLwnoxK6XAGQrJFy8+TIJoq38ldBaO75h4zA4ZX5tQFcwAgAAAAAC2wk8UcJH5X5XGnDBYmel6srpBkzBhHtt3Jw1u5TSJ1BWwAIAAAAAA9/YU9eI3D7QbXKIw/3/gzWJ6MZrCYhG0j1wNKgRQp5wADOAB9AAAABWQAIAAAAADGvyrtKkIcaV17ynZA7b2k5Pz6OhvxdWNkDvDWJIja8wVzACAAAAAAOLypVKNxf/wR1G8OZjUUsTQzDYeNNhhITxGMSp7euS4FbAAgAAAAAA9EsxoV1B2DcQ1NJRwuxXnvVR+vkD0wbbDYEI/zFEnDAAM5AH0AAAAFZAAgAAAAAEocREw1L0g+roFUchJI2Yd0M0ME2bnErNUYnpyJP1SqBXMAIAAAAAAcE2/JK/8MoSeOchIuAkKh1X3ImoA7p8ujAZIfvIDo6QVsACAAAAAA+W0+zgLr85/PD7P9a94wk6MgNgrizx/XU9aCxAkp1IwAABJjbQAAAAAAAAAAAAAQcGF5bG9hZElkAAAAAAAQZmlyc3RPcGVyYXRvcgABAAAAAA==", "subType": "06" } } } }, "u": { "$set": { "encryptedDate": { "$$type": "binData" } } } } ], "encryptionInformation": { "type": 1, "schema": { "default.default": { "escCollection": "enxcol_.default.esc", "ecocCollection": "enxcol_.default.ecoc", "fields": [ { "keyId": { "$binary": { "base64": "EjRWeBI0mHYSNBI0VniQEg==", "subType": "04" } }, "path": "encryptedDate", "bsonType": "date", "queries": { "queryType": "rangePreview", "contention": { "$numberLong": "0" }, "sparsity": { "$numberLong": "1" }, "min": { "$date": { "$numberLong": "0" } }, "max": { "$date": { "$numberLong": "200" } } } } ] } } }, "$db": "default" } } } ], "outcome": { "collection": { "data": [ { "_id": 0, "encryptedDate": { "$$type": "binData" }, "__safeContent__": [ { "$binary": { "base64": "5nRutVIyq7URVOVtbE4vM01APSIajAVnsShMwjBlzkM=", "subType": "00" } }, { "$binary": { "base64": "RjBYT2h3ZAoHxhf8DU6/dFbDkEBZp0IxREcsRTu2MXs=", "subType": "00" } }, { "$binary": { "base64": "x7GR49EN0t3WXQDihkrbonK7qNIBYC87tpL/XEUyIYc=", "subType": "00" } }, { "$binary": { "base64": "JfYUqWF+OoGjiYkRI4L5iPlF+T1Eleul7Fki22jp4Qc=", "subType": "00" } }, { "$binary": { "base64": "q1RyGfIgsaQHoZFRw+DD28V26rN5hweApPLwExncvT8=", "subType": "00" } }, { "$binary": { "base64": "L2PFeKGvLS6C+DLudR6fGlBq3ERPvjWvRyNRIA2HVb0=", "subType": "00" } }, { "$binary": { "base64": "CWxaNqL3iP1yCixDkcmf9bmW3E5VeN8TJkg1jJe528s=", "subType": "00" } }, { "$binary": { "base64": "+vC6araOEo+fpW7PSIP40/EnzBCj1d2N10Jr3rrXJJM=", "subType": "00" } }, { "$binary": { "base64": "6SV63Mf51Z6A6p2X3rCnJKCu6ku3Oeb45mBYbz+IoAo=", "subType": "00" } } ] }, { "_id": 1, "encryptedDate": { "$$type": "binData" }, "__safeContent__": [ { "$binary": { "base64": "DLCAJs+W2PL2DV5YChCL6dYrQNr+j4p3L7xhVaub4ic=", "subType": "00" } }, { "$binary": { "base64": "hyDcE6QQjPrYJaIS/n7evEZFYcm31Tj89CpEYGF45cI=", "subType": "00" } }, { "$binary": { "base64": "F08nMDWDZc+DbWM7XCEJNNCEYyinRmrvGP7EWhmp4is=", "subType": "00" } }, { "$binary": { "base64": "cXH4688amcDc8kZOJq4UP8cE3R58Zl7e+Qo/1jyspps=", "subType": "00" } }, { "$binary": { "base64": "uURBxvTp3FBCVkd+LPqyuY7d6rMW6SGIJQEPY/wtkZI=", "subType": "00" } }, { "$binary": { "base64": "jG3hax1L3RBp9t38vUt53FsBxgr/+Si/vVISpAylYpE=", "subType": "00" } }, { "$binary": { "base64": "kwtIW8MhH9Ky5xNjBx8gFA/SHh2YVphie7g5FGBzals=", "subType": "00" } }, { "$binary": { "base64": "FHflwFuEMu4xX0ZApHi+pdlBH+oevAtXckCUb5Wv0xU=", "subType": "00" } }, { "$binary": { "base64": "ty4cnzJdAlbQKnh7px3GEYjBnvO+jIOaKjoTRDtmh3M=", "subType": "00" } } ] } ] } } } ] } fle2v2-Range-Decimal-Aggregate.json000066400000000000000000002725541462766011000354070ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/client-side-encryption/spec/legacy{ "runOn": [ { "minServerVersion": "7.0.0", "topology": [ "replicaset" ] } ], "database_name": "default", "collection_name": "default", "data": [], "encrypted_fields": { "fields": [ { "keyId": { "$binary": { "base64": "EjRWeBI0mHYSNBI0VniQEg==", "subType": "04" } }, "path": "encryptedDecimalNoPrecision", "bsonType": "decimal", "queries": { "queryType": "rangePreview", "contention": { "$numberLong": "0" }, "sparsity": { "$numberLong": "1" } } } ] }, "key_vault_data": [ { "_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" } } ], "tests": [ { "description": "FLE2 Range Decimal. Aggregate.", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "local": { "key": { "$binary": { "base64": "Mng0NCt4ZHVUYUJCa1kxNkVyNUR1QURhZ2h2UzR2d2RrZzh0cFBwM3R6NmdWMDFBMUN3YkQ5aXRRMkhGRGdQV09wOGVNYUMxT2k3NjZKelhaQmRCZGJkTXVyZG9uSjFk", "subType": "00" } } } } } }, "operations": [ { "name": "insertOne", "arguments": { "document": { "_id": 0, "encryptedDecimalNoPrecision": { "$numberDecimal": "0" } } } }, { "name": "insertOne", "arguments": { "document": { "_id": 1, "encryptedDecimalNoPrecision": { "$numberDecimal": "1" } } } }, { "name": "aggregate", "arguments": { "pipeline": [ { "$match": { "encryptedDecimalNoPrecision": { "$gt": { "$numberDecimal": "0" } } } } ] }, "result": [ { "_id": 1, "encryptedDecimalNoPrecision": { "$numberDecimal": "1" } } ] } ], "expectations": [ { "command_started_event": { "command": { "listCollections": 1, "filter": { "name": "default" } }, "command_name": "listCollections" } }, { "command_started_event": { "command": { "find": "datakeys", "filter": { "$or": [ { "_id": { "$in": [ { "$binary": { "base64": "EjRWeBI0mHYSNBI0VniQEg==", "subType": "04" } } ] } }, { "keyAltNames": { "$in": [] } } ] }, "$db": "keyvault", "readConcern": { "level": "majority" } }, "command_name": "find" } }, { "command_started_event": { "command": { "insert": "default", "documents": [ { "_id": 0, "encryptedDecimalNoPrecision": { "$$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": "encryptedDecimalNoPrecision", "bsonType": "decimal", "queries": { "queryType": "rangePreview", "contention": { "$numberLong": "0" }, "sparsity": { "$numberLong": "1" } } } ] } } } }, "command_name": "insert" } }, { "command_started_event": { "command": { "insert": "default", "documents": [ { "_id": 1, "encryptedDecimalNoPrecision": { "$$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": "encryptedDecimalNoPrecision", "bsonType": "decimal", "queries": { "queryType": "rangePreview", "contention": { "$numberLong": "0" }, "sparsity": { "$numberLong": "1" } } } ] } } } }, "command_name": "insert" } }, { "command_started_event": { "command": { "aggregate": "default", "pipeline": [ { "$match": { "encryptedDecimalNoPrecision": { "$gt": { "$binary": { "base64": "DeFiAAADcGF5bG9hZACxYgAABGcAnWIAAAMwAH0AAAAFZAAgAAAAAJu2KgiI8vM+kz9qD3ZQzFQY5qbgYqCqHG5R4jAlnlwXBXMAIAAAAAAAUXxFXsz764T79sGCdhxvNd5b6E/9p61FonsHyEIhogVsACAAAAAAt19RL3Oo5ni5L8kcvgOJYLgVYyXJExwP8pkuzLG7f/kAAzEAfQAAAAVkACAAAAAAPQPvL0ARjujSv2Rkm8r7spVsgeC1K3FWcskGGZ3OdDIFcwAgAAAAACgNn660GmefR8jLqzgR1u5O+Uocx9GyEHiBqVGko5FZBWwAIAAAAADflr+fsnZngm6KRWYgHa9JzK+bXogWl9evBU9sQUHPHQADMgB9AAAABWQAIAAAAAD2Zi6kcxmaD2mY3VWrP+wYJMPg6cSBIYPapxaFQxYFdQVzACAAAAAAM/cV36BLBY3xFBXsXJY8M9EHHOc/qrmdc2CJmj3M89gFbAAgAAAAAOpydOrKxx6m2gquSDV2Vv3w10GocmNCFeOo/fRhRH9JAAMzAH0AAAAFZAAgAAAAAOaNqI9srQ/mI9gwbk+VkizGBBH/PPWOVusgnfPk3tY1BXMAIAAAAAAc96O/pwKCmHCagT6T/QV/wz4vqO+R22GsZ1dse2Vg6QVsACAAAAAAgzIak+Q3UFLTHXPmJ+MuEklFtR3eLtvM+jdKkmGCV/YAAzQAfQAAAAVkACAAAAAA0XlQgy/Yu97EQOjronl9b3dcR1DFn3deuVhtTLbJZHkFcwAgAAAAACoMnpVl6EFJak8A+t5N4RFnQhkQEBnNAx8wDqmq5U/dBWwAIAAAAACR26FJif673qpwF1J1FEkQGJ1Ywcr/ZW6JQ7meGqzt1QADNQB9AAAABWQAIAAAAAAOtpNexRxfv0yRFvZO9DhlkpU4mDuAb8ykdLnE5Vf1VAVzACAAAAAAeblFKm/30orP16uQpZslvsoS8s0xfNPIBlw3VkHeekYFbAAgAAAAAPEoHj87sYE+nBut52/LPvleWQBzB/uaJFnosxp4NRO2AAM2AH0AAAAFZAAgAAAAAIr8xAFm1zPmrvW4Vy5Ct0W8FxMmyPmFzdWVzesBhAJFBXMAIAAAAABYeeXjJEzTHwxab6pUiCRiZjxgtN59a1y8Szy3hfkg+gVsACAAAAAAJuoY4rF8mbI+nKb+5XbZShJ8191o/e8ZCRHE0O4Ey8MAAzcAfQAAAAVkACAAAAAAl+ibLk0/+EwoqeC8S8cGgAtjtpQWGEZDsybMPnrrkwEFcwAgAAAAAHPPBudWgQ+HUorLDpJMqhS9VBF2VF5aLcxgrM1s+yU7BWwAIAAAAAAcCcBR2Vyv5pAFbaOU97yovuOi1+ATDnLLcAUqHecXcAADOAB9AAAABWQAIAAAAACR9erwLTb+tcWFZgJ2MEfM0PKI9uuwIjDTHADRFgD+SQVzACAAAAAAcOop8TXsGUVQoKhzUllMYWxL93xCOkwtIpV8Q6hiSYYFbAAgAAAAAKXKmh4V8veYwob1H03Q3p3PN8SRAaQwDT34KlNVUjiDAAM5AH0AAAAFZAAgAAAAALv0vCPgh7QpmM8Ug6ad5ioZJCh7pLMdT8FYyQioBQ6KBXMAIAAAAADsCPyIG8t6ApQkRk1fX/sfc1kpuWCWP8gAEpnYoBSHrQVsACAAAAAAJe/r67N6d8uTiogvfoR9rEXbIDjyLb9EVdqkayFFGaYAAzEwAH0AAAAFZAAgAAAAAIW4AxJgYoM0pcNTwk1RSbyjZGIqgKL1hcTJmNrnZmoPBXMAIAAAAAAZpfx3EFO0vY0f1eHnE0PazgqeNDTaj+pPJMUNW8lFrAVsACAAAAAAP+Um2vwW6Bj6vuz9DKz6+6aWkoKoEmFNoiz/xXm7lOsAAzExAH0AAAAFZAAgAAAAAKliO6L9zgeuufjj174hvmQGNRbmYYs9yAirL7OxwEW3BXMAIAAAAAAqU7vs3DWUQ95Eq8OejwWnD0GuXd+ASi/uD6S0l8MM1QVsACAAAAAAb9legYzsfctBPpHyl7YWpPmLr5QiNZFND/50N1vv2MUAAzEyAH0AAAAFZAAgAAAAAOGQcCBkk+j/Kzjt/Cs6g3BZPJG81wIHBS8JewHGpgk+BXMAIAAAAABjrxZXWCkdzrExwCgyHaafuPSQ4V4x2k9kUCAqUaYKDQVsACAAAAAADBU6KefT0v8zSmseaMNmQxKjJar72y7MojLFhkEHqrUAAzEzAH0AAAAFZAAgAAAAAPmCNEt4t97waOSd5hNi2fNCdWEkmcFJ37LI9k4Az4/5BXMAIAAAAABX7DuDPNg+duvELf3NbLWkPMFw2HGLgWGHyVWcPvSNCAVsACAAAAAAS7El1FtZ5STh8Q1FguvieyYX9b2DF1DFVsb9hzxXYRsAAzE0AH0AAAAFZAAgAAAAAD4vtVUYRNB+FD9yoQ2FVJH3nMeJeKbi6eZfth638YqbBXMAIAAAAAANCuUB4OdmuD6LaDK2f3vaqfgYYvg40wDXOBbcFjTqLwVsACAAAAAA9hqC2VoJBjwR7hcQ45xO8ZVojwC83jiRacCaDj6Px2gAAzE1AH0AAAAFZAAgAAAAAJPIRzjmTjbdIvshG6UslbEOd797ZSIdjGAhGWxVQvK1BXMAIAAAAABgmJ0Jh8WLs9IYs/a7DBjDWd8J3thW/AGJK7zDnMeYOAVsACAAAAAAi9zAsyAuou2oiCUHGc6QefLUkACa9IgeBhGu9W/r0X8AAzE2AH0AAAAFZAAgAAAAAABQyKQPoW8wGPIqnsTv69+DzIdRkohRhOhDmyVHkw9WBXMAIAAAAAAqWA2X4tB/h3O1Xlawtz6ndI6WaTwgU1QYflL35opu5gVsACAAAAAAWI/Gj5aZMwDIxztqmVL0g5LBcI8EdKEc2UA28pnekQoAAzE3AH0AAAAFZAAgAAAAACB7NOyGQ1Id3MYnxtBXqyZ5Ul/lHH6p1b10U63DfT6bBXMAIAAAAADpOryIcndxztkHSfLN3Kzq29sD8djS0PspDSqERMqokQVsACAAAAAADatsMW4ezgnyi1PiP7xk+gA4AFIN/fb5uJqfVkjg4UoAAzE4AH0AAAAFZAAgAAAAAKVfXLfs8XA14CRTB56oZwV+bFJN5BHraTXbqEXZDmTkBXMAIAAAAAASRWTsfGOpqdffiOodoqIgBzG/yzFyjR5CfUsIUIWGpgVsACAAAAAAkgCHbCwyX640/0Ni8+MoYxeHUiC+FSU4Mn9jTLYtgZgAAzE5AH0AAAAFZAAgAAAAAH/aZr4EuS0/noQR9rcF8vwoaxnxrwgOsSJ0ys8PkHhGBXMAIAAAAACd7ObGQW7qfddcvyxRTkPuvq/PHu7+6I5dxwS1Lzy5XAVsACAAAAAA3q0eKdV7KeU3pc+CtfypKR7BPxwaf30yu0j9FXeOOboAAzIwAH0AAAAFZAAgAAAAAKvlcpFFNq0oA+urq3w6d80PK1HHHw0H0yVWvU9aHijXBXMAIAAAAADWnAHQ5Fhlcjawki7kWzdqjM2f6IdGJblojrYElWjsZgVsACAAAAAAO0wvY66l24gx8nRxyVGC0QcTztIi81Kx3ndRhuZr6W4AAzIxAH0AAAAFZAAgAAAAAH/2aMezEOddrq+dNOkDrdqf13h2ttOnexZsJxG1G6PNBXMAIAAAAABNtgnibjC4VKy5poYjvdsBBnVvDTF/4mmEAxsXVgZVKgVsACAAAAAAqvadzJFLqQbs8WxgZ2D2X+XnaPSDMLCVVgWxx5jnLcYAAzIyAH0AAAAFZAAgAAAAAF2wZoDL6/V59QqO8vdRZWDpXpkV4h4KOCSn5e7x7nmzBXMAIAAAAADLZBu7LCYjbThaVUqMK14H/elrVOYIKJQCx4C9Yjw37gVsACAAAAAAEh6Vs81jLU204aGpL90fmYTm5i5R8/RT1uIbg6VU3HwAAzIzAH0AAAAFZAAgAAAAAH27yYaLn9zh2CpvaoomUPercSfJRUmBY6XFqmhcXi9QBXMAIAAAAAAUwumVlIYIs9JhDhSj0R0+59psCMsFk94E62VxkPt42QVsACAAAAAAT5x2hCCd2bpmpnyWaxas8nSxTc8e4C9DfKaqr0ABEysAAzI0AH0AAAAFZAAgAAAAALMg2kNAO4AFFs/mW3In04yFeN4AP6Vo0klyUoT06RquBXMAIAAAAAAgGWJbeIdwlpqXCyVIYSs0dt54Rfc8JF4b8uYc+YUj0AVsACAAAAAAWHeWxIkyvXTOWvfZzqtPXjfGaWWKjGSIQENTU3zBCrsAAzI1AH0AAAAFZAAgAAAAALas/i1T2DFCEmrrLEi7O2ngJZyFHialOoedVXS+OjenBXMAIAAAAAA1kK0QxY4REcGxHeMkgumyF7iwlsRFtw9MlbSSoQY7uAVsACAAAAAAUNlpMJZs1p4HfsD4Q4WZ4TBEi6Oc2fX34rzyynqWCdwAAzI2AH0AAAAFZAAgAAAAAP1TejmWg1CEuNSMt6NUgeQ5lT+oBoeyF7d2l5xQrbXWBXMAIAAAAABPX0kj6obggdJShmqtVfueKHplH4ZrXusiwrRDHMOKeQVsACAAAAAAIYOsNwC3DA7fLcOzqdr0bOFdHCfmK8tLwPoaE9uKOosAAzI3AH0AAAAFZAAgAAAAAMrKn+QPa/NxYezNhlOX9nyEkN1kE/gW7EuZkVqYl0b8BXMAIAAAAABUoZMSPUywRGfX2EEencJEKH5x/P9ySUVrhStAwgR/LgVsACAAAAAAMgZFH6lQIIDrgHnFeslv3ld20ynwQjQJt3cAp4GgrFkAAzI4AH0AAAAFZAAgAAAAAMmD1+a+oVbiUZd1HuZqdgtdVsVKwuWAn3/M1B6QGBM3BXMAIAAAAACLyytOYuZ9WEsIrrtJbXUx4QgipbaAbmlJvSZVkGi0CAVsACAAAAAA4v1lSp5H9BB+HYJ4bH43tC8aeuPZMf78Ng1JOhJh190AAzI5AH0AAAAFZAAgAAAAAOVKV7IuFwmYP1qVv8h0NvJmfPICu8yQhzjG7oJdTLDoBXMAIAAAAABL70XLfQLKRsw1deJ2MUvxSWKxpF/Ez73jqtbLvqbuogVsACAAAAAAvfgzIorXxE91dDt4nQxYfntTsx0M8Gzdsao5naQqcRUAAzMwAH0AAAAFZAAgAAAAAKS/1RSAQma+xV9rz04IcdzmavtrBDjOKPM+Z2NEyYfPBXMAIAAAAAAOJDWGORDgfRv8+w5nunh41wXb2hCA0MRzwnLnQtIqPgVsACAAAAAAf42C1+T7xdHEFF83+c2mF5S8PuuL22ogXXELnRAZ4boAAzMxAH0AAAAFZAAgAAAAAFeq8o82uNY1X8cH6OhdTzHNBUnCChsEDs5tm0kPBz3qBXMAIAAAAABaxMBbsaeEj/EDtr8nZfrhhhirBRPJwVamDo5WwbgvTQVsACAAAAAAMbH453A+BYAaDOTo5kdhV1VdND1avNwvshEG/4MIJjQAAzMyAH0AAAAFZAAgAAAAAI8IKIfDrohHh2cjspJHCovqroSr5N3QyVtNzFvT5+FzBXMAIAAAAABXHXteKG0DoOMmECKp6ro1MZNQvXGzqTDdZ0DUc8QfFAVsACAAAAAA/w5s++XYmO+9TWTbtGc3n3ndV4T9JUribIbF4jmDLSMAAzMzAH0AAAAFZAAgAAAAAJkHvm15kIu1OtAiaByj5ieWqzxiu/epK6c/9+KYIrB0BXMAIAAAAACzg5TcyANk0nes/wCJudd1BwlkWWF6zw3nGclq5v3SJQVsACAAAAAAvruXHTT3irPJLyWpI1j/Xwf2FeIE/IV+6Z49pqRzISoAAzM0AH0AAAAFZAAgAAAAAAYSOvEWWuSg1Aym7EssNLR+xsY7e9BcwsX4JKlnSHJcBXMAIAAAAABT48eY3PXVDOjw7JpNjOe1j2JyI3LjDnQoqZ8Je5B2KgVsACAAAAAAU2815RR57TQ9uDg0XjWjBkAKvf8yssxDMzrM4+FqP6AAAzM1AH0AAAAFZAAgAAAAAGQxC9L1e9DfO5XZvX1yvc3hTLtQEdKO9FPMkyg0Y9ZABXMAIAAAAADtmcMNJwdWLxQEArMGZQyzpnu+Z5yMmPAkvgq4eAKwNQVsACAAAAAAJ88zt4Y/Hoqh+zrf6KCOiUwHbOzCxSfp6k/qsZaYGEgAAzM2AH0AAAAFZAAgAAAAADLHK2LNCNRO0pv8n4fAsxwtUqCNnVK8rRgNiQfXpHSdBXMAIAAAAACf16EBIHRKD3SzjRW+LMOl+47QXA3CJhMzlcqyFRW22AVsACAAAAAAMGz4fAOa0EoVv90fUffwLjBrQhHATf+NdlgCR65vujAAAzM3AH0AAAAFZAAgAAAAAHiZJiXKNF8bbukQGsdYkEi95I+FSBHy1I5/hK2uEZruBXMAIAAAAADE+lZBa8HDUJPN+bF6xI9x4N7GF9pj3vBR7y0BcfFhBAVsACAAAAAAGIEN6sfqq30nyxW4dxDgXr/jz5HmvA9T1jx/pKCn4zgAAzM4AH0AAAAFZAAgAAAAAI1oa2OIw5TvhT14tYCGmhanUoYcCZtNbrVbeoMldHNZBXMAIAAAAAAx2nS0Ipblf2XOgBiUOuJFBupBhe7nb6QPLZlA4aMPCgVsACAAAAAA9xu828hugIgo0E3de9dZD+gTpVUGlwtDba+tw/WcbUoAAzM5AH0AAAAFZAAgAAAAABgTWS3Yap7Q59hii/uPPimHWXsr+DUmsqfwt/X73qsOBXMAIAAAAACKK05liW5KrmEAvtpCB1WUltruzUylDDpjea//UlWoOAVsACAAAAAAcgN4P/wakJ5aJK5c1bvJBqpVGND221dli2YicPFfuAYAAzQwAH0AAAAFZAAgAAAAABOAnBPXDp6i9TISQXvcNKwGDLepZTu3cKrB4vKnSCjBBXMAIAAAAADjjzZO7UowAAvpwyG8BNOVqLCccMFk3aDK4unUeft5ywVsACAAAAAA4zkCd4k9gvfXoD1C7vwTjNcdVJwEARh8h/cxZ4PNMfgAAzQxAH0AAAAFZAAgAAAAAHN8hyvT1lYrAsdiV5GBdd5jhtrAYE/KnSjw2Ka9hjz9BXMAIAAAAAD794JK7EeXBs+D7yOVK7nWF8SbZ/7U8gZ7nnT9JFNwTAVsACAAAAAAg8Wt1HO3NhByq2ggux2a4Lo6Gryr24rEFIqh2acrwWMAAzQyAH0AAAAFZAAgAAAAAO93bPrq8bsnp1AtNd9ETnXIz0lH/2HYN/vuw9wA3fyFBXMAIAAAAABHlls5fbaF2oAGqptC481XQ4eYxInTC29aElfmVZgDUgVsACAAAAAANoQXEWpXJpgrSNK/cKi/m7oYhuSRlp1IZBF0bqTEATcAAzQzAH0AAAAFZAAgAAAAAL1YsAZm1SA0ztU6ySIrQgCCA74V6rr0/4iIygCcaJL6BXMAIAAAAADTXWTHWovGmUR1Zg9l/Aqq9H5mOCJQQrb/Dfae7e3wKAVsACAAAAAA5dunyJK6/SVfDD0t9QlNBcFqoZnf9legRjHaLSKAoQMAAzQ0AH0AAAAFZAAgAAAAAEoFAeHk0RZ9kD+cJRD3j7PcE5gzWKnyBrF1I/MDNp5mBXMAIAAAAACgHtc2hMBRSZjKw8RAdDHK+Pi1HeyjiBuAslGVNcW5tAVsACAAAAAAXzBLfq+GxRtX4Wa9fazA49DBLG6AjZm2XODStJKH8D0AAzQ1AH0AAAAFZAAgAAAAAAW+7DmSN/LX+/0uBVJDHIc2dhxAGz4+ehyyz8fAnNGoBXMAIAAAAAA6Ilw42EvvfLJ3Eq8Afd+FjPoPcQutZO6ltmCLEr8kxQVsACAAAAAAbbZalyo07BbFjPFlYmbmv0z023eT9eLkHqeVUnfUAUAAAzQ2AH0AAAAFZAAgAAAAANBdV7M7kuYO3EMoQItAbXv4t2cIhfaT9V6+s4cg9djlBXMAIAAAAABvz4MIvZWxxrcJCL5qxLfFhXiUYB1OLHdKEjco94SgDgVsACAAAAAAK2GVGvyPIKolF/ECcmfmkVcf1/IZNcaTv96N92yGrkEAAzQ3AH0AAAAFZAAgAAAAAMoAoiAn1kc79j5oPZtlMWHMhhgwNhLUnvqkqIFvcH1NBXMAIAAAAADcJTW7WiCyW0Z9YDUYwppXhLj4Ac1povpJvcAq+i48MQVsACAAAAAAIGxGDzoeB3PTmudl4+j6piQB++e33EEzuzAiXcqGxvUAAzQ4AH0AAAAFZAAgAAAAACI3j5QP7dWHpcT6WO/OhsWwRJNASBYqIBDNzW8IorEyBXMAIAAAAABxUpBSjXwCKDdGP9hYU+RvyR+96kChfvyyRC4jZmztqAVsACAAAAAAvBCHguWswb4X0xdcAryCvZgQuthXzt7597bJ5VxAMdgAAzQ5AH0AAAAFZAAgAAAAAKsbycEuQSeNrF8Qnxqw3x3og8JmQabwGqnDbqzFRVrrBXMAIAAAAACno/3ef2JZJS93SVVzmOZSN+jjJHT8s0XYq2M46d2sLAVsACAAAAAAAt5zLJG+/j4K8rnkFtAn8IvdUVNefe6utJ3rdzgwudIAAzUwAH0AAAAFZAAgAAAAAPXIcoO8TiULqlxzb74NFg+I8kWX5uXIDUPnh2DobIoMBXMAIAAAAADR6/drkdTpnr9g1XNvKDwtBRBdKn7c2c4ZNUVK5CThdQVsACAAAAAAJqOA1c6KVog3F4Hb/GfDb3jCxXDRTqpXWSbMH4ePIJsAAzUxAH0AAAAFZAAgAAAAAEa03ZOJmfHT6/nVadvIw71jVxEuIloyvxXraYEW7u7pBXMAIAAAAADzRlBJK75FLiKjz3djqcgjCLo/e3yntI3MnPS48OORhgVsACAAAAAAnQhx4Rnyj081XrLRLD5NLpWmRWCsd0M9Hl7Jl19R0h8AAzUyAH0AAAAFZAAgAAAAAKx8NLSZUU04pSSGmHa5fh2oLHsEN5mmNMNHL95/tuC9BXMAIAAAAAA59hcXVaN3MNdHoo11OcH1aPRzHCwpVjO9mGfMz4xh3QVsACAAAAAAYIPdjV2XbPj7dBeHPwnwhVU7zMuJ+xtMUW5mIOYtmdAAAzUzAH0AAAAFZAAgAAAAAHNKAUxUqBFNS9Ea9NgCZoXMWgwhP4x0/OvoaPRWMquXBXMAIAAAAABUZ551mnP4ZjX+PXU9ttomzuOpo427MVynpkyq+nsYCQVsACAAAAAALnVK5p2tTTeZEh1zYt4iqKIQT9Z0si//Hy1L85oF+5IAAzU0AH0AAAAFZAAgAAAAALfGXDlyDVcGaqtyHkLT0qpuRhJQLgCxtznazhFtuyn/BXMAIAAAAABipxlXDq14C62pXhwAeen5+syA+/C6bN4rtZYcO4zKwAVsACAAAAAAXUf0pzUq0NhLYagWDap4uEiwq5rLpcx29rWbt1NYMsMAAzU1AH0AAAAFZAAgAAAAANoEr8sheJjg4UCfBkuUzarU9NFoy1xwbXjs5ifVDeA9BXMAIAAAAABPoyTf6M+xeZVGES4aNzVlq7LgjqZXJ/QunjYVusGUEAVsACAAAAAA1hA2gMeZZPUNytk9K+lB1RCqWRudRr7GtadJlExJf8oAAzU2AH0AAAAFZAAgAAAAAKvDiK+xjlBe1uQ3SZTNQl2lClIIvpP/5CHwY6Kb3WlgBXMAIAAAAAANnxImq5MFbWaRBHdJp+yD09bVlcFtiFDYsy1eDZj+iQVsACAAAAAAWtsyO+FxMPSIezwsV1TJD8ZrXAdRnQM6DJ+f+1V3qEkAAzU3AH0AAAAFZAAgAAAAAF49IlFH9RmSUSvUQpEPUedEksrQUcjsOv44nMkwXhjzBXMAIAAAAADJtWGbk0bZzmk20obz+mNsp86UCu/nLLlbg7ppxYn7PgVsACAAAAAA3k0Tj/XgPQtcYijH8cIlQoe/VXf15q1nrZNmg7yWYEgAAzU4AH0AAAAFZAAgAAAAAOuSJyuvz50lp3BzXlFKnq62QkN2quNU1Gq1IDsnFoJCBXMAIAAAAAAqavH1d93XV3IzshWlMnzznucadBF0ND092/2ApI1AcAVsACAAAAAAzUrK4kpoKCmcpdZlZNI13fddjdoAseVe67jaX1LobIIAAzU5AH0AAAAFZAAgAAAAALtgC4Whb4ZdkCiI30zY6fwlsxSa7lEaOAU3SfUXr02XBXMAIAAAAACgdZ6U1ZVgUaZZwbIaCdlANpCw6TZV0bwg3DS1NC/mnAVsACAAAAAAzI49hdpp0PbO7S2KexISxC16sE73EUAEyuqUFAC/J48AAzYwAH0AAAAFZAAgAAAAAF6PfplcGp6vek1ThwenMHVkbZgrc/dHgdsgx1VdPqZ5BXMAIAAAAACha3qhWkqmuwJSEXPozDO8y1ZdRLyzt9Crt2vjGnT7AAVsACAAAAAA7nvcU59+LwxGupSF21jAeAE0x7JE94tjRkJfgM1yKU8AAzYxAH0AAAAFZAAgAAAAAKoLEhLvLjKc7lhOJfx+VrGJCx9tXlOSa9bxQzGR6rfbBXMAIAAAAAAIDK5wNnjRMBzET7x/KAMExL/zi1IumJM92XTgXfoPoAVsACAAAAAAFkUYWFwNr815dEdFqp+TiIozDcq5IBNVkyMoDjharDQAAzYyAH0AAAAFZAAgAAAAADoQv6lutRmh5scQFvIW6K5JBquLxszuygM1tzBiGknIBXMAIAAAAADAD+JjW7FoBQ76/rsECmmcL76bmyfXpUU/awqIsZdO+wVsACAAAAAAPFHdLw3jssmEXsgtvl/RBNaUCRA1kgSwsofG364VOvQAAzYzAH0AAAAFZAAgAAAAAJNHUGAgn56KekghO19d11nai3lAh0JAlWfeP+6w4lJBBXMAIAAAAAD9XGJlvz59msJvA6St9fKW9CG4JoHV61rlWWnkdBRLzwVsACAAAAAAxwP/X/InJJHmrjznvahIMgj6pQR30B62UtHCthSjrP0AAzY0AH0AAAAFZAAgAAAAAHgYoMGjEE6fAlAhICv0+doHcVX8CmMVxyq7+jlyGrvmBXMAIAAAAAC/5MQZgTHuIr/O5Z3mXPvqrom5JTQ8IeSpQGhO9sB+8gVsACAAAAAAuPSXVmJUAUpTQg/A9Bu1hYczZF58KEhVofakygbsvJQAAzY1AH0AAAAFZAAgAAAAANpIljbxHOM7pydY877gpRQvYY2TGK7igqgGsavqGPBABXMAIAAAAAAqHyEu9gpurPOulApPnr0x9wrygY/7mXe9rAC+tPK80wVsACAAAAAA7gkPzNsS3gCxdFBWbSW9tkBjoR5ib+saDvpGSB3A3ogAAzY2AH0AAAAFZAAgAAAAAGR+gEaZTeGNgG9BuM1bX2R9ed4FCxBA9F9QvdQDAjZwBXMAIAAAAABSkrYFQ6pf8MZ1flgmeIRkxaSh/Eep4Btdx4QYnGGnwAVsACAAAAAApRovMiV00hm/pEcT4XBsyPNw0eo8RLAX/fuabjdU+uwAAzY3AH0AAAAFZAAgAAAAAFNprhQ3ZwIcYbuzLolAT5n/vc14P9kUUQComDu6eFyKBXMAIAAAAAAcx9z9pk32YbPV/sfPZl9ALIEVsqoLXgqWLVK/tP+heAVsACAAAAAA/qxvuvJbAHwwhfrPVpmCFzNvg2cU/NXaWgqgYUZpgXwAAzY4AH0AAAAFZAAgAAAAADgyPqQdqQrgfmJjRFAILTHzXbdw5kpKyfeoEcy6YYG/BXMAIAAAAAAE+3XsBQ8VAxAkN81au+f3FDeCD/s7KoZD+fnM1MJSSAVsACAAAAAAhRnjrXecwV0yeCWKJ5J/x12Xx4qVJahsCEVHB/1U2rcAAzY5AH0AAAAFZAAgAAAAAI0CT7JNngTCTUSei1Arw7eHWCD0jumv2rb7imjWIlWABXMAIAAAAABSP8t6ya0SyCphXMwnru6ZUDXWElN0NfBvEOhDvW9bJQVsACAAAAAAGWeGmBNDRaMtvm7Rv+8TJ2sJ4WNXKcp3tqpv5Se9Ut4AAzcwAH0AAAAFZAAgAAAAAD/FIrGYFDjyYmVb7oTMVwweWP7A6F9LnyIuNO4MjBnXBXMAIAAAAACIZgJCQRZu7NhuNMyOqCn1tf+DfU1qm10TPCfj5JYV3wVsACAAAAAA5hmY4ptuNxULGf87SUFXQWGAONsL9U29duh8xqsHtxoAAzcxAH0AAAAFZAAgAAAAAHIkVuNDkSS1cHIThKc/O0r2/ubaABTOi8Q1r/dvBAsEBXMAIAAAAADdHYqchEiJLM340c3Q4vJABmmth3+MKzwLYlsG6GS7sQVsACAAAAAADa+KP/pdTiG22l+ZWd30P1iHjnBF4zSNRdFm0oEK82kAAzcyAH0AAAAFZAAgAAAAAJmoDILNhC6kn3masElfnjIjP1VjsjRavGk1gSUIjh1NBXMAIAAAAAD97Ilvp3XF8T6MmVVcxMPcdL80RgQ09UoC6PnoOvZ1IQVsACAAAAAA2RK3Xng6v8kpvfVW9tkVXjpE+BSnx9/+Fw85Evs+kUEAAzczAH0AAAAFZAAgAAAAAI5bm3YO0Xgf0VT+qjVTTfvckecM3Cwqj7DTKZXf8/NXBXMAIAAAAAD/m+h8fBhWaHm6Ykuz0WX1xL4Eme3ErLObyEVJf8NCywVsACAAAAAAfb1VZZCqs2ivYbRzX4p5CtaCkKW+g20Pr57FWXzEZi8AAzc0AH0AAAAFZAAgAAAAANqo4+p6qdtCzcB4BX1wQ6llU7eFBnuu4MtZwp4B6mDlBXMAIAAAAAAGiz+VaukMZ+6IH4jtn4KWWdKK4/W+O+gRioQDrfzpMgVsACAAAAAAG4YYkTp80EKo59mlHExDodRQFR7njhR5dmISwUJ6ukAAAzc1AH0AAAAFZAAgAAAAAPrFXmHP2Y4YAm7b/aqsdn/DPoDkv7B8egWkfe23XsM1BXMAIAAAAAAGhwpKAr7skeqHm3oseSbO7qKNhmYsuUrECBxJ5k+D2AVsACAAAAAAAqPQi9luYAu3GrFCEsVjd9z2zIDcp6SPTR2w6KQEr+IAAzc2AH0AAAAFZAAgAAAAABzjYxwAjXxXc0Uxv18rH8I3my0Aguow0kTwKyxbrm+cBXMAIAAAAADVbqJVr6IdokuhXkEtXF0C2gINLiAjMVN20lE20Vmp2QVsACAAAAAAD7K1Fx4gFaaizkIUrf+EGXQeG7QX1jadhGc6Ji471H8AAzc3AH0AAAAFZAAgAAAAAFMm2feF2fFCm/UC6AfIyepX/xJDSmnnolQIBnHcPmb5BXMAIAAAAABLI11kFrQoaNVZFmq/38aRNImPOjdJh0Lo6irI8M/AaAVsACAAAAAAOWul0oVqJ9CejD2RqphhTC98DJeRQy5EwbNerU2+4l8AAzc4AH0AAAAFZAAgAAAAAJvXB3KyNiNtQko4SSzo/9b2qmM2zU9CQTTDfLSBWMgRBXMAIAAAAAAvjuVP7KsLRDeqVqRziTKpBrjVyqKiIbO9Gw8Wl2wFTAVsACAAAAAADlE+oc1ins+paNcaOZJhBlKlObDJ4VQORWjFYocM4LgAAzc5AH0AAAAFZAAgAAAAAPGdcxDiid8z8XYnfdDivNMYVPgBKdGOUw6UStU+48CdBXMAIAAAAAARj6g1Ap0eEfuCZ4X2TsEw+Djrhto3fA5nLwPaY0vCTgVsACAAAAAAoHqiwGOUkBu8SX5U1yHho+UIFdSN2MdQN5s6bQ0EsJYAAzgwAH0AAAAFZAAgAAAAAP5rGPrYGt3aKob5f/ldP0qrW7bmWvqnKY4QwdDWz400BXMAIAAAAADTQkW2ymaaf/bhteOOGmSrIR97bAnJx+yN3yMj1bTeewVsACAAAAAADyQnHGH2gF4w4L8axUsSTf6Ubk7L5/eoFOJk12MtZAoAAzgxAH0AAAAFZAAgAAAAAAlz6wJze5UkIxKpJOZFGCOf3v2KByWyI6NB6JM9wNcBBXMAIAAAAABUC7P/neUIHHoZtq0jFVBHY75tSFYr1Y5S16YN5XxC1QVsACAAAAAAgvxRbXDisNnLY3pfsjDdnFLtkvYUC4lhA68eBXc7KAwAAzgyAH0AAAAFZAAgAAAAAFJ8AtHcjia/9Y5pLEc3qVgH5xKiXw12G9Kn2A1EY8McBXMAIAAAAAAxe7Bdw7eUSBk/oAawa7uicTEDgXLymRNhBy1LAxhDvwVsACAAAAAAxKPaIBKVx3jTA+R/el7P7AZ7efrmTGjJs3Hj/YdMddwAAzgzAH0AAAAFZAAgAAAAAO8uwQUaKFb6vqR3Sv3Wn4QAonC2exOC9lGG1juqP5DtBXMAIAAAAABZf1KyJgQg8/Rf5c02DgDK2aQu0rNCOvaL60ohDHyY+gVsACAAAAAAqyEjfKC8lYoIfoXYHUqHZPoaA6EK5BAZy5dxXZmay4kAAzg0AH0AAAAFZAAgAAAAAE8YtqyRsGCeiR6hhiyisR/hccmK4nZqIMzO4lUBmEFzBXMAIAAAAAC1UYOSKqAeG1UJiKjWFVskRhuFKpj9Ezy+lICZvFlN5AVsACAAAAAA6Ct9nNMKyRazn1OKnRKagm746CGu+jyhbL1qJnZxGi0AAzg1AH0AAAAFZAAgAAAAAPhCrMausDx1QUIEqp9rUdRKyM6a9AAx7jQ3ILIu8wNIBXMAIAAAAACmH8lotGCiF2q9VQxhsS+7LAZv79VUAsOUALaGxE/EpAVsACAAAAAAnc1xCKfdvbUEc8F7XZqlNn1C+hZTtC0I9I3LL06iaNkAAzg2AH0AAAAFZAAgAAAAAOBi/GAYFcstMSJPgp3VkMiuuUUCrZytvqYaU8dwm8v2BXMAIAAAAACEZSZVyD3pKzGlbdwlYmWQhHHTV5SnNLknl2Gw8IaUTQVsACAAAAAAfsLZsEDcWSuNsIo/TD1ReyQW75HPMgmuKZuWFOLKRLoAAzg3AH0AAAAFZAAgAAAAAIQuup+YGfH3mflzWopN8J1X8o8a0d9CSGIvrA5HOzraBXMAIAAAAADYvNLURXsC2ITMqK14LABQBI+hZZ5wNf24JMcKLW+84AVsACAAAAAACzfjbTBH7IwDU91OqLAz94RFkoqBOkzKAqQb55gT4/MAAzg4AH0AAAAFZAAgAAAAAKsh0ADyOnVocFrOrf6MpTrNvAj8iaiE923DPryu124gBXMAIAAAAADg24a8NVE1GyScc6tmnTbmu5ulzO+896fE92lN08MeswVsACAAAAAAaPxcOIxnU7But88/yadOuDJDMcCywwrRitaxMODT4msAAzg5AH0AAAAFZAAgAAAAAKkVC2Y6HtRmv72tDnPUSjJBvse7SxLqnr09/Uuj9sVVBXMAIAAAAABYNFUkH7ylPMN+Bc3HWX1e0flGYNbtJNCY9SltJCW/UAVsACAAAAAAZYK/f9H4OeihmpiFMH7Wm7uLvs2s92zNA8wyrNZTsuMAAzkwAH0AAAAFZAAgAAAAADDggcwcb/Yn1Kk39sOHsv7BO/MfP3m/AJzjGH506Wf9BXMAIAAAAAAYZIsdjICS0+BDyRUPnrSAZfPrwtuMaEDEn0/ijLNQmAVsACAAAAAAGPnYVvo2ulO9z4LGd/69NAklfIcZqZvFX2KK0s+FcTUAAzkxAH0AAAAFZAAgAAAAAEWY7dEUOJBgjOoWVht1wLehsWAzB3rSOBtLgTuM2HC8BXMAIAAAAAAAoswiHRROurjwUW8u8D5EUT+67yvrgpB/j6PzBDAfVwVsACAAAAAA6NhRTYFL/Sz4tao7vpPjLNgAJ0FX6P/IyMW65qT6YsMAAzkyAH0AAAAFZAAgAAAAAPZaapeAUUFPA7JTCMOWHJa9lnPFh0/gXfAPjA1ezm4ZBXMAIAAAAACmJvLY2nivw7/b3DOKH/X7bBXjJwoowqb1GtEFO3OYgAVsACAAAAAA/JcUoyKacCB1NfmH8vYqC1f7rd13KShrQqV2r9QBP44AAzkzAH0AAAAFZAAgAAAAAK00u6jadxCZAiA+fTsPVDsnW5p5LCr4+kZZZOTDuZlfBXMAIAAAAAAote4zTEYMDgaaQbAdN8Dzv93ljPLdGjJzvnRn3KXgtQVsACAAAAAAxXd9Mh6R3mnJy8m7UfqMKi6oD5DlZpkaOz6bEjMOdiwAAzk0AH0AAAAFZAAgAAAAAFbgabdyymiEVYYwtJSWa7lfl/oYuj/SukzJeDOR6wPVBXMAIAAAAADAFGFjS1vPbN6mQEhkDYTD6V2V23Ys9gUEUMGNvMPkaAVsACAAAAAAL/D5Sze/ZoEanZLK0IeEkhgVkxEjMWVCfmJaD3a8uNIAAzk1AH0AAAAFZAAgAAAAABNMR6UBv2E627CqLtQ/eDYx7OEwQ7JrR4mSHFa1N8tLBXMAIAAAAAAxH4gucI4UmNVB7625C6hFSVCuIpJO3lusJlPuL8H5EQVsACAAAAAAVLHNg0OUVqZ7WGOP53BkTap9FOw9dr1P4J8HxqFqU04AAzk2AH0AAAAFZAAgAAAAAG8cd6WBneNunlqrQ2EmNf35W7OGObGq9WL4ePX+LUDmBXMAIAAAAAAjJ2+sX87NSis9hBsgb1QprVRnO7Bf+GObCGoUqyPE4wVsACAAAAAAs9c9SM49/pWmyUQKslpt3RTMBNSRppfNO0JBvUqHPg0AAzk3AH0AAAAFZAAgAAAAAFWOUGkUpy8yf6gB3dio/aOfRKh7XuhvsUj48iESFJrGBXMAIAAAAAAY7sCDMcrUXvNuL6dO0m11WyijzXZvPIcOKob6IpC4PQVsACAAAAAAJOP+EHz6awDb1qK2bZQ3kTV7wsj5Daj/IGAWh4g7omAAAzk4AH0AAAAFZAAgAAAAAGUrIdKxOihwNmo6B+aG+Ag1qa0+iqdksHOjQj+Oy9bZBXMAIAAAAABwa5dbI2KmzBDNBTQBEkjZv4sPaeRkRNejcjdVymRFKQVsACAAAAAA4ml/nm0gJNTcJ4vuD+T2Qfq2fQZlibJp/j6MOGDrbHMAAzk5AH0AAAAFZAAgAAAAAOx89xV/hRk64/CkM9N2EMK6aldII0c8smdcsZ46NbP8BXMAIAAAAADBF6tfQ+7q9kTuLyuyrSnDgmrdmrXkdhl980i1KHuGHgVsACAAAAAACUqiFqHZdGbwAA+hN0YUE5zFg+H+dabIB4dj5/75W/YAAzEwMAB9AAAABWQAIAAAAADJDdC9aEFl4Y8J/awHbnXGHjfP+VXQilPHJg7ewaJI7AVzACAAAAAAE+tqRl6EcBMXvbr4GDiNIYObTsYpa1n6BJk9EjIJVicFbAAgAAAAAJVc+HYYqa0m1Hq6OiRX8c0iRnJYOt6AJAJoG0sG3GMSAAMxMDEAfQAAAAVkACAAAAAA3F9rjEKhpoHuTULVGgfUsGGwJs3bISrXkFP1v6KoQLgFcwAgAAAAAIBf0tXw96Z/Ds0XSIHX/zk3MzUR/7WZR/J6FpxRWChtBWwAIAAAAABWrjGlvKYuTS2s8L9rYy8Hf0juFGJfwQmxVIjkTmFIGQADMTAyAH0AAAAFZAAgAAAAAOYIYoWkX7dGuyKfi3XssUlc7u/gWzqrR9KMkikKVdmSBXMAIAAAAABVF2OYjRTGi9Tw8XCAwZWLpX35Yl271TlNWp6N/nROhAVsACAAAAAA0nWwYzXQ1+EkDvnGq+SMlq20z+j32Su+i/A95SggPb4AAzEwMwB9AAAABWQAIAAAAACMtPm12YtdEAvqu6Eji1yuRXnu1RJP6h0l7pH3lSH4MwVzACAAAAAAENyCFfyUAh1veQBGx+cxiB7Sasrj41jzCGflZkB5cRMFbAAgAAAAAKdI2LMqISr/T5vuJPg6ZRBm5fVi2aQCc4ra3A4+AjbDAAMxMDQAfQAAAAVkACAAAAAAvlI4lDcs6GB1cnm/Tzo014CXWqidCdyE5t2lknWQd4QFcwAgAAAAAD60SpNc4O2KT7J0llKdSpcX1/Xxs97N715a1HsTFkmBBWwAIAAAAABuuRkJWAH1CynggBt1/5sPh9PoGiqTlS24D/OE2uHXLQADMTA1AH0AAAAFZAAgAAAAAKl8zcHJRDjSjJeV/WvMxulW1zrTFtaeBy/aKKhadc6UBXMAIAAAAADBdWQl5SBIvtZZLIHszePwkO14W1mQ0izUk2Ov21cPNAVsACAAAAAAHErCYycpqiIcCZHdmPL1hi+ovLQk4TAvENpfLdTRamQAAzEwNgB9AAAABWQAIAAAAABb6LXDWqCp1beQgQjj8I3sRTtFhlrmiBi+h/+ikmrvugVzACAAAAAA9stpgTecT7uTyaGNs3K9Bp0A7R0QaIAOfscyMXHBPX8FbAAgAAAAAHUt+McyXrJ1H8SwnHNVO181Ki8vDAM1f7XI26mg95ZDAAMxMDcAfQAAAAVkACAAAAAA97NTT+81PhDhgptNtp4epzA0tP4iNb9j1AWkiiiKGM8FcwAgAAAAAKPbHg7ise16vxmdPCzksA/2Mn/qST0L9Xe8vnQugVkcBWwAIAAAAABB0EMXfvju4JU/mUH/OvxWbPEl9NJkcEp4iCbkXI41fAADMTA4AH0AAAAFZAAgAAAAAMqpayM2XotEFmm0gwQd9rIzApy0X+7HfOhNk6VU7F5lBXMAIAAAAACJR9+q5T9qFHXFNgGbZnPubG8rkO6cwWhzITQTmd6VgwVsACAAAAAAOZLQ6o7e4mVfDzbpQioa4d3RoTvqwgnbmc5Qh2wsZuoAAzEwOQB9AAAABWQAIAAAAADQnslvt6Hm2kJPmqsTVYQHE/wWeZ4bE1XSkt7TKy0r1gVzACAAAAAA8URTA4ZMrhHPvlp53TH6FDCzS+0+61qHm5XK6UiOrKEFbAAgAAAAAHQbgTCdZcbdA0avaTmZXUKnIS7Nwf1tNrcXDCw+PdBRAAMxMTAAfQAAAAVkACAAAAAAhujlgFPFczsdCGXtQ/002Ck8YWQHHzvWvUHrkbjv4rwFcwAgAAAAALbV0lLGcSGfE7mDM3n/fgEvi+ifjl7WZ5b3aqjDNvx9BWwAIAAAAACbceTZy8E3QA1pHmPN5kTlOx3EO8kJM5PUjTVftw1VpgADMTExAH0AAAAFZAAgAAAAABm/6pF96j26Jm7z5KkY1y33zcAEXLx2n0DwC03bs/ixBXMAIAAAAAD01OMvTZI/mqMgxIhA5nLs068mW+GKl3OW3ilf2D8+LgVsACAAAAAAaLvJDrqBESTNZSdcXsd+8GXPl8ZkUsGpeYuyYVv/kygAAzExMgB9AAAABWQAIAAAAACfw9/te4GkHZAapC9sDMHHHZgmlTrccyJDPFciOMSOcwVzACAAAAAAIIC1ZpHObvmMwUfqDRPl4C1aeuHwujM1G/yJbvybMNAFbAAgAAAAAAs9x1SnVpMfNv5Bm1aXGwHmbbI9keWa9HRD35XuCBK5AAMxMTMAfQAAAAVkACAAAAAAkxHJRbnShpPOylLoDdNShfILeA1hChKFQY9qQyZ5VmsFcwAgAAAAAKidrY+rC3hTY+YWu2a7fuMH2RD/XaiTIBW1hrxNCQOJBWwAIAAAAACW0kkqMIzIFMn7g+R0MI8l15fr3k/w/mHtY5n6SYTEwAADMTE0AH0AAAAFZAAgAAAAAByuYl8dBvfaZ0LO/81JW4hYypeNmvLMaxsIdvqMPrWoBXMAIAAAAABNddwobOUJzm9HOUD8BMZJqkNCUCqstHZkC76FIdNg9AVsACAAAAAAQQOkIQtkyNavqCnhQbNg3HfqrJdsAGaoxSJePJl1qXsAAzExNQB9AAAABWQAIAAAAABxMy7X5hf7AXGDz3Y/POu1ZpkMlNcSvSP92NOO/Gs7wAVzACAAAAAAHJshWo2T5wU2zvqCyJzcJQKQaHFHpCpMc9oWBXkpUPoFbAAgAAAAAGeiJKzlUXAvL0gOlW+Hz1mSa2HsV4RGmyLmCHlzbAkoAAMxMTYAfQAAAAVkACAAAAAAlqbslixl7Zw3bRlibZbe/WmKw23k8uKeIzPKYEtbIy0FcwAgAAAAAHEKwpUxkxOfef5HYvulXPmdbzTivwdwrSYIHDeNRcpcBWwAIAAAAADuPckac21Hrg/h0kt5ShJwVEZ9rx6SOHd2+HDjqxEWTQADMTE3AH0AAAAFZAAgAAAAAMXrXx0saZ+5gORmwM2FLuZG6iuO2YS+1IGPoAtDKoKBBXMAIAAAAADIQsxCr8CfFKaBcx8kIeSywnGh7JHjKRJ9vJd9x79y7wVsACAAAAAAcvBV+SykDYhmRFyVYwFYB9oBKBSHr55Jdz2cXeowsUQAAzExOAB9AAAABWQAIAAAAAAm83FA9yDUpwkbKTihe7m53u+DivS9BU2b4vQMtCVQ2AVzACAAAAAAz3m1UB/AbZPa4QSKFDnUgHaT78+6iGOFAtouiBorEgEFbAAgAAAAAIgbpyYtJj5513Z5XYqviH/HXG/5+mqR52iBbfqMmDtZAAMxMTkAfQAAAAVkACAAAAAAJRzYK0PUwr9RPG2/7yID0WgcTJPB2Xjccp5LAPDYunkFcwAgAAAAAIIh24h3DrltAzNFhF+MEmPrZtzr1PhCofhChZqfCW+jBWwAIAAAAAAzRNXtL5o9VXMk5D5ylI0odPDJDSZZry1wfN+TedH70gADMTIwAH0AAAAFZAAgAAAAAHSaHWs/dnmI9sc7nB50VB2Bzs0kHapMHCQdyVEYY30TBXMAIAAAAACkV22lhEjWv/9/DubfHBAcwJggKI5mIbSK5L2nyqloqQVsACAAAAAAS19m7DccQxgryOsBJ3GsCs37yfQqNi1G+S6fCXpEhn4AAzEyMQB9AAAABWQAIAAAAAAC/I4TQRtCl12YZmdGz17X4GqSQgfwCPgRBwdHmdwu+QVzACAAAAAAx8f3z2ut/RAZhleari4vCEE+tNIn4ikjoUwzitfQ588FbAAgAAAAAJci0w1ZB8W2spJQ+kMpod6HSCtSR2jrabOH+B0fj3A4AAMxMjIAfQAAAAVkACAAAAAADGB5yU2XT0fse/MPWgvBvZikVxrl5pf3S5K1hceKWooFcwAgAAAAAIxTmlLHMjNaVDEfJbXvRez0SEPWFREBJCT6qTHsrljoBWwAIAAAAAAlswzAl81+0DteibwHD+CG5mZJrfHXa9NnEFRtXybzzwADMTIzAH0AAAAFZAAgAAAAABmO7QD9vxWMmFjIHz13lyOeV6vHT6mYCsWxF7hb/yOjBXMAIAAAAACT9lmgkiqzuWG24afuzYiCeK9gmJqacmxAruIukd0xEAVsACAAAAAAZa0/FI/GkZR7CtX18Xg9Tn9zfxkD0UoaSt+pIO5t1t4AAzEyNAB9AAAABWQAIAAAAAAfPUoy7QyZKhIIURso+mkP9qr1izbjETqF5s22GwjCjAVzACAAAAAAvLMsIDQ/go4VUxeh50UHmsvMvfx51cwyONnRD2odvC0FbAAgAAAAAKMb+1CodEalAFnDrEL1Ndt8ztamZ+9134m9Kp3GQgd+AAMxMjUAfQAAAAVkACAAAAAAE3ZqUar0Bq2zWbARE0bAv98jBlK9UJ73/xcwdMWWlSkFcwAgAAAAAK4M+MmC+9sFiFsumMyJZQKxWmmJiuG9H7IzKw083xxkBWwAIAAAAAAqkAONzhvMhkyL1D/6h7QQxEkdhC3p2WjXH+VGq5qCqQADMTI2AH0AAAAFZAAgAAAAAMo8FJiOq63cAmyk2O7eI7GcbQh/1j4RrMTqly3rexftBXMAIAAAAADjVmpd0WiRGTw/gAqEgGolt2EI7Csv14vKdmYoMD0aAgVsACAAAAAA07XQBzBUQMNw7F2/YxJjZNuPVpHTTgbLd1oGk77+bygAAzEyNwB9AAAABWQAIAAAAACu5IGaIx7A3Jvly/kzlCsSA4s3iJwuIl8jEdRH0k93NwVzACAAAAAA9NRUyxYE+t0Xyosyt6vIfMFW/vBoYg6sR+jBNs4JAxIFbAAgAAAAAAzyZ91dx+0oMlOVAjRGiMrPySikY/U9eMEB4WJb3uWtAAMxMjgAfQAAAAVkACAAAAAALkRy0GJInXYLA+cgjs6Myb0a+Gu9hgXhHvhLNoGWfckFcwAgAAAAANbALyt9zCSvwnLaWCd2/y2eoB7qkWTvv1Ldu8r40JPuBWwAIAAAAAD4Fl5bV5sz4isIE9bX+lmAp+aAKaZgVYVZeVfrItkCZAADMTI5AH0AAAAFZAAgAAAAAGoUK/DSWhT8LZhszSUqDbTrp8cSA7rdqmADKL+MILtTBXMAIAAAAABHnEE9bVa6lvhfhEMkkV2kzSSxH/sMW/FIJuw3CzWs6wVsACAAAAAAanavcBdqZxgRGKvEK95wTmeL1K1CeDSXZsXUAs81uOgAAzEzMAB9AAAABWQAIAAAAAC922ZDQE3h2fQKibGMZ9hV0WNlmrPYYSdtaSyYxsWYqgVzACAAAAAAagMovciKK6WVjIc2cCj8nK5O/gVOFFVeVAJpRp89tmQFbAAgAAAAAKcTFfPQzaFiAtSFhqbN02sCE1BKWJSrRfGN5L6oZwzkAAMxMzEAfQAAAAVkACAAAAAAtK+JqX3K/z2txjAU15DgX4y90DS2YLfIJFolCOkJJJwFcwAgAAAAAMnR5V7gfX7MNqqUdL5AkWlkhyFXaBRVNej+Rcn8lrQkBWwAIAAAAAA2cDNRXZuiC241TGRvdFyctJnrNcdbZOP9zHio81tkngADMTMyAH0AAAAFZAAgAAAAAAeGrIMK/bac6kPczxbvRYqKMkcpeI2FjdMpD91FDWIvBXMAIAAAAAAix62z1LeS8yvSXCl5gHSIomjyx76fF3S1lp9k900hygVsACAAAAAAiYwzf2m71aWFD5ajcXyW2JX2EzQOkBroTGMg29nLPYIAAzEzMwB9AAAABWQAIAAAAACphf298InM0Us4HT8o1W1MGw0D/02vd7Jh+U0h7qaFaQVzACAAAAAAFXtk7YpqsOJxsqGWSIL+YcBE96G3Zz9D31gPqDW94y8FbAAgAAAAAAOrS1KVA94rjB1jZ1pPocpCeBG+B14RzWoHqVDpp7JbAAMxMzQAfQAAAAVkACAAAAAATLDS2cuDVM3yDMuWNgk2iGKBTzPpfJMbvxVOSY39ZfcFcwAgAAAAAPT5wRi2cLHIUflXzm6EQB/m7xdThP80ir1VV/JBBqvxBWwAIAAAAAB9lEtZS0aXCFbCtSbhnis27S5IPcfWGygHW8AHn3QqzwADMTM1AH0AAAAFZAAgAAAAAJNjExiZVX7jfFGfYpQu16qxLN0YPqVU/5CQ/Y67YSinBXMAIAAAAABMpm2+6KrkRUlXzQoMPHrQmIO6dkQz66tYdfTeA3dKqQVsACAAAAAAFXobHiMLvNZuEPr8jtewCX2J93EZG3JNeyVg92fue6YAAzEzNgB9AAAABWQAIAAAAABlFkYtLCx901X6QVVMkSn6Z7k30UF4xHaA0OZJJ9bdyQVzACAAAAAATez+F9GHcGzTp7jjv4feboUNb8JCkIp4EqcPFisnq7MFbAAgAAAAACE7JvOpBgMoZ7kRd4QbxIhxukPTUxXpzhjnBHiR7XoRAAMxMzcAfQAAAAVkACAAAAAA8NJKN0IxZnruhswGQkiruv8Ih0EMwDcSZx/Xasup9dkFcwAgAAAAAKaJZRxzA+Igeydvuk6cSwUHXcrmT4PjhuPu//FslpdnBWwAIAAAAAD53Rok1Vq/PMAnXmarqoHJ0PEyYUBmVESa9hIpCv/G9QADMTM4AH0AAAAFZAAgAAAAABHxHdEClz7hbSSgE58+dWLlSMJnoPz+jFxp4bB1GmLQBXMAIAAAAAD3nSvT6aGD+A110J/NwEfp0nPutlmuB5B+wA3CC3noGAVsACAAAAAA3Apjd+TapONB7k5wBVwTWgn8t+Sq2oyyU5/+as109RcAAzEzOQB9AAAABWQAIAAAAAC/o8qW/ifk3KuJ01VFkyNLgQafxB5/bGs2G5VyyVafOwVzACAAAAAA1bMqAFGDHSl6BYNLbxApvkAv2K1/oafywiX0MDz1dGUFbAAgAAAAAHJXLlId3edFoniLD/9K2A5973MeP2Ro31flDyqm3l5QAAMxNDAAfQAAAAVkACAAAAAAY2V8I1bz3a1AxTtmED6UhdhA09huFkuuEX8R+d/WDPUFcwAgAAAAAPTVoNRiI76tcRKqd+JBBVyy4+YcKST42p0QX2BtmQ2VBWwAIAAAAACcxt9hg14WqPNiDv1MkqVljM2e2KJEv53lA17LhV6ZigADMTQxAH0AAAAFZAAgAAAAAO2kSsW0WGN9AOtK4xK2SHrGhWiaAbMEKT4iZkRpaDN/BXMAIAAAAABKGzQcPM8LT2dwOggxoWjv/1imYWabbG/G4kBw8OWaxAVsACAAAAAAC9hLK1dScQTAqg+YAG3ObdPzg2Xet57HmOFpGmyUR9UAAzE0MgB9AAAABWQAIAAAAAAiCwzNEEaH/mDam68IdDftnhthyUFdb+ZCNSBQ91WlHQVzACAAAAAA7tHyHcxCzmbJeFYZyPm4mEgkTGKOvwY4MX82OvH0Jn8FbAAgAAAAAAb5IAbZ1hXCNegQ+S+C9i/Z8y6sS8KeU04V6hXa2ml6AAMxNDMAfQAAAAVkACAAAAAAGuCHVNJSuoVkpPOnS5s89GuA+BLi2IPBUr2Bg1sWEPIFcwAgAAAAAEl1gncS5/xO7bQ/KQSstRV3rOT2SW6nV92ZANeG2SR6BWwAIAAAAAA9LOcKmhek8F2wAh8yvT/vjp2gaouuO+Hmv10lwAeWPAADMTQ0AH0AAAAFZAAgAAAAAMfxz7gEaoCdPvXrubDhCZUS0ARLZc1svgbXgMDlVBPgBXMAIAAAAAB6a5dDA3fuT5Vz2KvAcbUEFX/+B7Nw2p1QqbPoQ5TTuAVsACAAAAAAcf/y75UOuI62A6vWH7bYr/5Jz+nirZVYK/81trN6XOQAAzE0NQB9AAAABWQAIAAAAACnYsqF/VzmjIImC9+dqrHO1TM6lJ6fRwM0mM6Wf6paOwVzACAAAAAA5tgZzch8uDCR1ky3SllVaKVpxAlbrhvlNDTazZZRZOAFbAAgAAAAALeGiLJS4z2zhgVpxzyPdRYyACP9QzQBOob34YrIZumCAAMxNDYAfQAAAAVkACAAAAAAEC0sIVmadtW4YMuRXH7RpAhXclsd+3bmqGXCMeaT014FcwAgAAAAABPpXh0uzpsJJB+IRUNajmMB9WGwswfpw5T9xk3Xj6ANBWwAIAAAAAAmf+NYh9TZ/QRu3w/GQz66n7DtfbJijN3G7KzeL8lstAADMTQ3AH0AAAAFZAAgAAAAABaIB3n49Xm9cOafSrQsE0WCcYp8rMIO/qVwIlMF5YLRBXMAIAAAAAC9EyWJV3xOu9bzgdJ/yX+ko7qLf1u3AxNMataW2C9EzQVsACAAAAAAvVbDkLxXx2DcMLifIQ3K0IIJcLcAG9DUrNfI6aoUjNcAAzE0OAB9AAAABWQAIAAAAAA5rZItA/cocRnngYqcJ3nBXQ+l688aKz3EQyLbYYunPAVzACAAAAAAwKyA+L7TgxztPClLrIMk2JXR+w7c04N3ZOqPgjvrIvsFbAAgAAAAACzvZ33h6aWEe8hmo+1f6OXJ72FY5hvWaUuha64ZV3KFAAMxNDkAfQAAAAVkACAAAAAA3htn7oHJ0YYpIrs+Mzyh85Ys67HwAdv5LQl1mCdoMWkFcwAgAAAAAEHjCtNNLenHuSIYux6ezAHsXDaj2DlTF67ToDhDDe6HBWwAIAAAAAD+P4H0sk9jOd+7vOANt2/1Ectb+4ZRGPE8GkHWNXW3MgADMTUwAH0AAAAFZAAgAAAAAEnt18Km/nqggfIJWxzTr9r3hnXNaueG6XO9A5G11LnGBXMAIAAAAAD7QxzGMN/ard5TfFLecE6uusMmXG2+RBsBR+/NCQHUwAVsACAAAAAAQEZ1ZZ8GC8rdbg7s87OM5Gr9qkTXS9+P5DuAZxj5Gl4AAzE1MQB9AAAABWQAIAAAAAAVAKK/GoY8AACu/hyMpO4hdLq6JnEyWNzkyci9sbaD/wVzACAAAAAA2HmeqpMlvvBpV2zQTYIRmsc4MFlfHRwLof0ycJgMg/MFbAAgAAAAACdltCeWi5E/q1Li1eXLChpM2D9QQSGLBZ82NklQSc0oAAMxNTIAfQAAAAVkACAAAAAAhHyq1GQC/GiMwpYjcsfkNxolJ10ARKjIjfkW1Wipzi0FcwAgAAAAAD/uaGWxTDq87F8XZ6CrFI+RNa8yMqfSZdqK00Kj833BBWwAIAAAAAD6aEdOO0CsQGagioOCvANPCEHSpJ8BSixlPBq5ERhB7AADMTUzAH0AAAAFZAAgAAAAABAJJxHoZD+MQBWqm9UM9Dd3z5ZohIZGWRaRVRsMptKQBXMAIAAAAADrE/ca+gqj/SH4oao4wE4qn2ovoTydzcMbDbrfnUs3zAVsACAAAAAAeNCIQN6hVnGJinytQRFGlQ2ocoprXNqpia+BSxzl+uwAAzE1NAB9AAAABWQAIAAAAAAv01wz7VG9mTepjXQi6Zma+7b/OVBaKVkWNbgDLr1mFgVzACAAAAAA0I5sxz8r6wkCp5Tgvr+iL4p6MxSOq5d3e1kZG+0b7NkFbAAgAAAAAIA32v6oGkAOS96HexGouNTex+tLahtx9QF2dgGClk6WAAMxNTUAfQAAAAVkACAAAAAAWXecRwxSon68xaa9THXnRDw5ZfzARKnvvjTjtbae6T0FcwAgAAAAAPh0UfUMEo7eILCMv2tiJQe1bF9qtXq7GJtC6H5Va4fIBWwAIAAAAADqFr1ThRrTXNgIOrJWScO9mk86Ufi95IDu5gi4vP+HWQADMTU2AH0AAAAFZAAgAAAAAEY5WL8/LpX36iAB1wlQrMO/xHVjoO9BePVzbUlBYo+bBXMAIAAAAABoKcpadDXUARedDvTmzUzWPe1jTuvD0z9oIcZmKuiSXwVsACAAAAAAJuJbwuaMrAFoI+jU/IYr+k4RzAqITrOjAd3HWCpJHqEAAzE1NwB9AAAABWQAIAAAAADnJnWqsfx0xqNnqfFGCxIplVu8mXjaHTViJT9+y2RuTgVzACAAAAAAWAaSCwIXDwdYxWf2NZTly/iKVfG/KDjHUcA1BokN5sMFbAAgAAAAAJVxavipE0H4/JQvhagdytXBZ8qGooeXpkbPQ1RfYMVHAAMxNTgAfQAAAAVkACAAAAAAsPG7LaIpJvcwqcbtfFUpIjj+vpNj70Zjaw3eV9T+QYsFcwAgAAAAAJQ71zi0NlCyY8ZQs3IasJ4gB1PmWx57HpnlCf3+hmhqBWwAIAAAAACD58TO6d+71GaOoS+r73rAxliAO9GMs4Uc8JbOTmC0OwADMTU5AH0AAAAFZAAgAAAAAAGiSqKaQDakMi1W87rFAhkogfRAevnwQ41onWNUJKtuBXMAIAAAAAASgiDpXfGh7E47KkOD8MAcX8+BnDShlnU5JAGdnPdqOAVsACAAAAAAI+2TTQIgbFq4Yr3lkzGwhG/tqChP7hRAx2W0fNaH6jcAAzE2MAB9AAAABWQAIAAAAAB7L4EnhjKA5xJD3ORhH2wOA1BvpnQ+7IjRYi+jjVEaJAVzACAAAAAAuhBIm0nL3FJnVJId+7CKDASEo+l2E89Z9/5aWSITK4AFbAAgAAAAALtSICOzQDfV9d+gZuYxpEj6cCeHnKTT+2G3ceP2H65kAAMxNjEAfQAAAAVkACAAAAAAaROn1NaDZFOGEWw724dsXBAm6bgmL5i0cki6QZQNrOoFcwAgAAAAANVT8R6UvhrAlyqYlxtmnvkR4uYK/hlvyQmBu/LP6/3ZBWwAIAAAAAD+aHNMP/X+jcRHyUtrCNkk1KfMtoD3GTmShS8pWGLt+AADMTYyAH0AAAAFZAAgAAAAADqSR5e0/Th59LrauDA7OnGD1Xr3H3NokfVxzDWOFaN7BXMAIAAAAACt30faNwTWRbvmykDpiDYUOCwA6QDbBBYBFWS7rdOB4AVsACAAAAAAF7SvnjjRk5v2flFOKaBAEDvjXaL1cpjsQLtK2fv9zdQAAzE2MwB9AAAABWQAIAAAAADmtb1ZgpZjSeodPG/hIVlsnS8hoRRwRbrTVx89VwL62AVzACAAAAAAi38e1g6sEyVfSDkzZbaZXGxKI/zKNbMasOl2LYoWrq8FbAAgAAAAAALACk0KcCDN/Kv8WuazY8ORtUGkOZ5Dsm0ys1oOppp/AAMxNjQAfQAAAAVkACAAAAAAf/f7AWVgBxoKjr7YsEQ4w/fqSvuQWV2HMiA3rQ7ur0sFcwAgAAAAADkkeJozP6FFhUdRIN74H4UhIHue+eVbOs1NvbdWYFQrBWwAIAAAAAB55FlHAkmTzAYj/TWrGkRJw2EhrVWUnZXDoMYjyfB/ZwADMTY1AH0AAAAFZAAgAAAAAI2WEOymtuFpdKi4ctanPLnlQud+yMKKb8p/nfKmIy56BXMAIAAAAADVKrJmhjr1rfF3p+T+tl7UFd1B7+BfJRk0e7a4im7ozgVsACAAAAAA5E7Ti3PnFiBQoCcb/DN7V1uM3Xd6VKiexPKntssFL7kAAzE2NgB9AAAABWQAIAAAAAAuHU9Qd79hjyvKOujGanSGDIQlxzsql8JytTZhEnPw+AVzACAAAAAAjF2gV/4+sOHVgDd/oR5wDi9zL7NGpGD+NsEpGXy/a4QFbAAgAAAAAJzMoyojYV6Ed/LpVN5zge93Odv3U7JgP7wxeRaJZGTdAAMxNjcAfQAAAAVkACAAAAAA7dQDkt3iyWYCT94d7yqUtPPwp4qkC0ddu+HFdHgVKEkFcwAgAAAAANuYvtvZBTEq4Rm9+5eb7VuFopowkrAuv86PGP8Q8/QvBWwAIAAAAACeqXoAOQOE4j0zRMlkVd8plaW0RX1npsFvB38Xmzv7sAADMTY4AH0AAAAFZAAgAAAAAAwnZSDhL4tNGYxlHPhKYB8s28dY5ScSwiKZm3UhT8U3BXMAIAAAAABDoY6dhivufTURQExyC9Gx3ocpl09bgbbQLChj3qVGbgVsACAAAAAAF+1nS7O0v85s3CCy+9HkdeoEfm2C6ZiNbPMMnSfsMHUAAzE2OQB9AAAABWQAIAAAAAC2VuRdaC4ZJmLdNOvD6R2tnvkyARteqXouJmI46V306QVzACAAAAAAMn1Z6B35wFTX9mEYAPM+IiJ5hauEwfD0CyIvBrxHg7IFbAAgAAAAAOG6DvDZkT9B/xZWmjao2AevN7MMbs3Oh9YJeSd/hZ+hAAMxNzAAfQAAAAVkACAAAAAAVerb7qVNy457rNOHOgDSKyWl5ojun7iWrv1uHPXrIZQFcwAgAAAAAIDcYS9j5z+gx0xdJj09L7876r/vjvKTi/d3bXDE3PhyBWwAIAAAAADuhVLqb1Bkrx8aNymS+bx2cL8GvLFNH4SAi690DUgnWQADMTcxAH0AAAAFZAAgAAAAAH/E44yLxKCJjuSmU9A8SEhbmkDOx1PqqtYcZtgOzJdrBXMAIAAAAABgLh9v2HjBbogrRoQ82LS6KjZQnzjxyJH4PH+F3jupSAVsACAAAAAAIlO46ehXp4TqpDV0t6op++KO+uWBFh8iFORZjmx2IjkAAzE3MgB9AAAABWQAIAAAAAAlNUdDL+f/SSQ5074mrq0JNh7CTXwTbbhsQyDwWeDVMwVzACAAAAAANIH2IlSNG0kUw4qz0budjcWn8mNR9cJlYUqPYdonucAFbAAgAAAAAJMrOUOyiu5Y3sV76zwEFct8L7+i8WGlQI2+8z2W2kzaAAMxNzMAfQAAAAVkACAAAAAASZ+CvUDtlk/R4HAQ3a+PHrKeY/8ifAfh0oXYFqliu80FcwAgAAAAAJelpzPgM65OZFt/mvGGpwibclQ49wH+1gbUGzd9OindBWwAIAAAAAD9qeDchteEpVXWcycmD9kl9449C1dOw0r60TBm5jK+cQADMTc0AH0AAAAFZAAgAAAAAN9fkoUVbvFV2vMNMAkak4gYfEnzwKI3eDM3pnDK5q3lBXMAIAAAAACnDkgVNVNUlbQ9RhR6Aot2nVy+U4km6+GHPkLr631jEAVsACAAAAAANzg/BnkvkmvOr8nS4omF+q9EG/4oisB+ul4YHi938hwAAzE3NQB9AAAABWQAIAAAAAASyK3b1nmNCMptVEGOjwoxYLLS9fYWm/Zxilqea0jpEQVzACAAAAAADDHsGrbqlKGEpxlvfyqOJKQJjwJrzsrB7k3HG0AUJbkFbAAgAAAAAKwx3S4XfDZh4+LuI9jf7XgUh5qiefNv87JD4qvVRfPSAAMxNzYAfQAAAAVkACAAAAAAlSP9iK31GlcG9MKGbLmq+VXMslURr+As736rrVNXcsUFcwAgAAAAAAvbj0zfq9zzi8XReheKFbCB+h9IsOLgXPPpI5vrEJNZBWwAIAAAAABXvoZhaQE7ogWjeBjceVkp03N20cKYP3TA8vuNsgpfAgADMTc3AH0AAAAFZAAgAAAAAOJNORH8Bev97gVU7y6bznOxJ+E6Qoykur1QP76hG1/7BXMAIAAAAAC+C1PtOOrSZgzBAGhr+dPe/kR0JUw9GTwLVNr61xC1aAVsACAAAAAAeA/L8MQIXkamaObtMPLpoDoi5FypA5WAPtMeMrgi0eQAAzE3OAB9AAAABWQAIAAAAAAKcHzLUomavInN6upPkyWhAqYQACP/vdVCIYpiy6U6HgVzACAAAAAATsR4KItY6R2+U7Gg6sJdaEcf58gjd1OulyWovIqfxKcFbAAgAAAAAFbm10ko67ahboAejQdAV0U2uA5OhZYdb8XUFJ8OL46LAAMxNzkAfQAAAAVkACAAAAAAqTOLiMpCdR59tLZzzIPqJvbCNvz2XQL9ust0qYaehtcFcwAgAAAAAArefox/3k5xGOeiw2m6NUdzuGxmPwcu5IFcj+jMwHgHBWwAIAAAAADLZGFJ7MQd5JXMgMXjqZO5LDLxcFClcXPlnRMWRn+1oAADMTgwAH0AAAAFZAAgAAAAAIPSqSeVzSRgNVNmrPYHmUMgykCY27NbdDUNhE5kx/SgBXMAIAAAAAAhX90nNfxyXmZe/+btZ7q6xMX4PFyj0paM1ccJ/5IUUQVsACAAAAAA419oHmD2W0SYoOMwhrhrp8jf68fg9hTkaRdCuVd3CN0AAzE4MQB9AAAABWQAIAAAAACLn5DxiqAosHGXIAY96FwFKjeqrzXWf3VJIQMwx1fl4gVzACAAAAAAindvU27nveutopdvuHmzdENBbeGFtI3Qcsr07jxmvm8FbAAgAAAAAPvl9pBStQvP4OGkN5v0MghUY6djm9n7XdKKfrW0l1sMAAMxODIAfQAAAAVkACAAAAAA7i2S6rHRSPBwZEn59yxaS7HiYBOmObIkeyCcFU42kf8FcwAgAAAAAGb3RSEyBmgarkTvyLWtOLJcPwCKbCRkESG4RZjVmY4iBWwAIAAAAADB2/wo5CSHR4ANtifY6ZRXNTO5+O8qP82DfAiAeanpZwADMTgzAH0AAAAFZAAgAAAAAFz+M+H/Z94mdPW5oP51B4HWptp1rxcMWAjnlHvWJDWrBXMAIAAAAACBFEOQyL7ZHu4Cq33QvXkmKuH5ibG/Md3RaED9CtG5HwVsACAAAAAAfggtJTprQ/yZzj7y5z9KvXsdeXMWP0yUXMMJqpOwI88AAzE4NAB9AAAABWQAIAAAAAAE7c2x3Z3aM1XGfLNk/XQ9jCazNRbGhVm7H8c2NjS5ywVzACAAAAAARJ9h8fdcwA19velF3L/Wcvi2rCzewlKZ2nA0p8bT9uwFbAAgAAAAAJtWe6b4wK2Hae2dZm/OEpYQnvoZjz4Sz5IgJC2wInecAAMxODUAfQAAAAVkACAAAAAAVoRt9B9dNVvIMGN+ea5TzRzQC+lqSZ8dd/170zU5o9cFcwAgAAAAAEwM95XZin5mv2yhCI8+ugtKuvRVmNgzzIQN0yi1+9aIBWwAIAAAAAAMGBq72n00rox3uqhxSB98mkenTGCdbbUF1gXrgottzgADMTg2AH0AAAAFZAAgAAAAAKRDkjyWv/etlYT4GyoXrmBED2FgZHnhc+l9Wsl06cH2BXMAIAAAAABohlpm3K850Vndf3NmNE0hHqDlNbSR8/IvMidQ3LnIZAVsACAAAAAAW42nGHa6q2MCAaaPVwaIDfr8QLyQwjKq23onZJYsqVsAAzE4NwB9AAAABWQAIAAAAAC3DFh5oklLCNLY90bgWm68dFXz65JpAZSp1K99MBTPAQVzACAAAAAAQgZecmxEUZVHoptEQClDwAf8smI3WynQ/i+JBP0g+kQFbAAgAAAAAEUSQGVnAPISD6voD0DiBUqyWKgt2rta0tjmoe+LNt6IAAMxODgAfQAAAAVkACAAAAAAQ5WKvWSB503qeNlOI2Tpjd5blheNr6OBO8pfJfPNstcFcwAgAAAAAKwHgQLSDJ5NwLBQbY5OnblQIsVDpGV7q3RCbFLD1U4/BWwAIAAAAACQ5nED99LnpbqXZuUOUjnO2HTphEAFBjLD4OZeDEYybgADMTg5AH0AAAAFZAAgAAAAAGfhFY3RGRm5ZgWRQef1tXxHBq5Y6fXaLAR4yJhrTBplBXMAIAAAAACKEF0ApLoB6lP2UqTFsTQYNc9OdDrs/vziPGzttGVLKQVsACAAAAAArOO6FyfNRyBi0sPT5iye7M8d16MTLcwRfodZq4uCYKEAAzE5MAB9AAAABWQAIAAAAAAIM73gPcgzgotYHLeMa2zAU4mFsr7CbILUZWfnuKSwagVzACAAAAAAJCSu98uV8xv88f2BIOWzt6p+6EjQStMBdkGPUkgN79cFbAAgAAAAAMGqPGMPxXbmYbVfSa/japvUljht1zZT33TY7ZjAiuPfAAMxOTEAfQAAAAVkACAAAAAAkWmHCUsiMy1pwZTHxVPBzPTrWFBUDqHNrVqcyyt7nO8FcwAgAAAAAMv2CebFRG/br7USELR98sIdgE9OQCRBGV5JZCO+uPMgBWwAIAAAAABt7qSmn3gxJu7aswsbUiwvO+G6lXj/Xhx+J/zQyZxzLAADMTkyAH0AAAAFZAAgAAAAAGInUYv0lP/rK7McM8taEHXRefk8Q2AunrvWqdfSV7UaBXMAIAAAAACE+WPxJ3gan7iRTbIxXXx+bKVcaf8kP4JD8DcwU0aL7wVsACAAAAAAUC4eTprX4DUZn2X+UXYU6QjtiXk+u57yoOPBbPQUmDkAAzE5MwB9AAAABWQAIAAAAACmHlg2ud3cplXlTsNTpvNnY6Qm1Fce0m899COamoDjaQVzACAAAAAArtJQeJIlepBWRU2aYar7+YGYVQ7dfDc1oxgTmA8r9q0FbAAgAAAAAOk45vg5VqZHAFCO3i0Z52SZi5RADf8NXwf68T5yad/DAAMxOTQAfQAAAAVkACAAAAAApzcWSAbZWV/Rq+ylRNqqlJqNVR4fhXrz4633/MQOQgcFcwAgAAAAAN/jz/bsEleiuCl+li83EWlG6UMHA8CyaOMRKCkXkSCPBWwAIAAAAAC3Sd+Qg+uFDKpGZHbrQgokXHQ1az1aFl4YK343OB6hcQAAEmNtAAAAAAAAAAAAABBwYXlsb2FkSWQAAAAAABBmaXJzdE9wZXJhdG9yAAEAAAAA", "subType": "06" } } } } } ], "cursor": {}, "encryptionInformation": { "type": 1, "schema": { "default.default": { "escCollection": "enxcol_.default.esc", "ecocCollection": "enxcol_.default.ecoc", "fields": [ { "keyId": { "$binary": { "base64": "EjRWeBI0mHYSNBI0VniQEg==", "subType": "04" } }, "path": "encryptedDecimalNoPrecision", "bsonType": "decimal", "queries": { "queryType": "rangePreview", "contention": { "$numberLong": "0" }, "sparsity": { "$numberLong": "1" } } } ] } } } }, "command_name": "aggregate" } } ], "outcome": { "collection": { "data": [ { "_id": { "$numberInt": "0" }, "encryptedDecimalNoPrecision": { "$$type": "binData" }, "__safeContent__": [ { "$binary": { "base64": "5nRutVIyq7URVOVtbE4vM01APSIajAVnsShMwjBlzkM=", "subType": "00" } }, { "$binary": { "base64": "rbf3AeBEv4wWFAKknqDxRW5cLNkFvbIs6iJjc6LShQY=", "subType": "00" } }, { "$binary": { "base64": "n+XAuFnP8Dov9TnhGFxNx0K/MnVM9WbJ7RouEu0ndO0=", "subType": "00" } }, { "$binary": { "base64": "yRXojuVdn5GQtD97qYlaCL6cOLmZ7Cvcb3wFjkLUIdM=", "subType": "00" } }, { "$binary": { "base64": "DuIkdRPITRs55I4SZmgomAHCIsDQmXRhW8+MOznkzSk=", "subType": "00" } }, { "$binary": { "base64": "SsBk+Et1lTbU+QRPx+xyJ/jMkmfG+QCvQEpip2YYrzA=", "subType": "00" } }, { "$binary": { "base64": "crCIzOd8KhHvvUlX7M1v9bhvU4pLdTc+X2SuqoKU5Ek=", "subType": "00" } }, { "$binary": { "base64": "YOWdCw4UrqnxkAaVjqmC4sKQDMVMHEpFGnlxpxdaU6E=", "subType": "00" } }, { "$binary": { "base64": "M3SShp81Ff8tQ632qKbv9MUcN6wjDaBReI0VXNu6Xh4=", "subType": "00" } }, { "$binary": { "base64": "gzHlSPxpM0hT75kQvWFzGlOxKvDoiKQZOr19V6l2zXI=", "subType": "00" } }, { "$binary": { "base64": "s3JnppOGYw9SL2Q1kMAZs948v2F5PrpXjGei/HioDWs=", "subType": "00" } }, { "$binary": { "base64": "cG6+3Gk/zEH68P/uuuwiAUVCuyJwa1LeV+t29FlPPAo=", "subType": "00" } }, { "$binary": { "base64": "dupdvR3AyJtM+g9NDKiaLVOtGca387JQp8w+V03m7Ig=", "subType": "00" } }, { "$binary": { "base64": "JqEQc5svj2jTvZ6LLA5ivE+kTb/0aRemSEmxk4G7Zrg=", "subType": "00" } }, { "$binary": { "base64": "szcXXXKnob+p3SoM4yED2R920LeJ7cVsclPMFTe4CeI=", "subType": "00" } }, { "$binary": { "base64": "o1QoGVXmuBdHwHm7aCtGMlMVKrjFdYvJXpoq6uhIAZ0=", "subType": "00" } }, { "$binary": { "base64": "Jfm5wPlqqLCJRGQIqRq2NGmpn7s0Vrih2H3YAOoI2YU=", "subType": "00" } }, { "$binary": { "base64": "zMHLb8ARbsYo8Ld05bqnGFf1Usha6EGb8QKwdSAyps0=", "subType": "00" } }, { "$binary": { "base64": "yQdtq9lh5pugL7/i0Bj/PuZUUBUIzf+7wj1rl5y736w=", "subType": "00" } }, { "$binary": { "base64": "wGWVZdO7qIuyDg/BqDgqjgoQ02h5YYgwXQB1oCin2NE=", "subType": "00" } }, { "$binary": { "base64": "by9HMLj6NTEpgztZ5HSN6GxImkXPcaFINYDzgZY33X8=", "subType": "00" } }, { "$binary": { "base64": "tWo0vbasi7bXmn/MsOx13VC1IsWtpx/nYp0uj4iMzdA=", "subType": "00" } }, { "$binary": { "base64": "tQQpndUYd5O87lOtrGjH3wl9VsOK0ray7RMasL90sBM=", "subType": "00" } }, { "$binary": { "base64": "cQjXEDCMsOpKLLf+vlTgIHA+cbSJdzqhbSX9Wvh95aA=", "subType": "00" } }, { "$binary": { "base64": "7yMpU48IxK9SzP2cx3VnTownGEwFmeFofuuFT97SuuY=", "subType": "00" } }, { "$binary": { "base64": "kSOx1kz0CmBgzKQHZlo65ZUY1DIv9A99JRm+Us2y6Ew=", "subType": "00" } }, { "$binary": { "base64": "ubQpdPBe6/xvtr+AcXdfYLSvYCR4ot0tivehkCsupb4=", "subType": "00" } }, { "$binary": { "base64": "xal+iCJ6FTefRQToyoNksc9NCZShyn04NDGi4IYrcoM=", "subType": "00" } }, { "$binary": { "base64": "d7jU4iOK50xHxlkSifcxlZFCM46TSgQzoYivxG3HNLY=", "subType": "00" } }, { "$binary": { "base64": "tJvl2nsBLBVzL3pp6sKWCL4UXeh3q/roYBJjSb74ve0=", "subType": "00" } }, { "$binary": { "base64": "OIUCaKRvIx9t1w6Hxlz1IcQTdPNCfdRNwnnTm10W+X0=", "subType": "00" } }, { "$binary": { "base64": "A9tvzsiElotOUVIB4CqfQp9mAwqvTM35YkmAR170aHA=", "subType": "00" } }, { "$binary": { "base64": "lI8gpK7hpb7c9x4RQugsxMnQay5LZJmwslZdvMx/dcE=", "subType": "00" } }, { "$binary": { "base64": "dNCzh40U0XvdKnSDi3HRQOWQftEsDVqc4uUvsVFGoq8=", "subType": "00" } }, { "$binary": { "base64": "IP+iwEBWBwVVZIdpaMu8k5+soFCz+TZkYn3drKZ9grE=", "subType": "00" } }, { "$binary": { "base64": "pnqyh6e0y5svHkJDShlN9CHV0WvMBE4QbtJpQw5ZCXc=", "subType": "00" } }, { "$binary": { "base64": "elEl42tbVDoRTLjAhZUFEtXiut4b3PVhg/1ZLZSQdtE=", "subType": "00" } }, { "$binary": { "base64": "vHuu2FxwclMHqyE6JBYbTYgbEkB0dqb/JuaxsvfwsmY=", "subType": "00" } }, { "$binary": { "base64": "xTf7NCe3Gf8QpE78HR5OknlLTKfs9J+RN9UZpH6fnso=", "subType": "00" } }, { "$binary": { "base64": "XiWSasRnJAulGR6+LCVD3mwRObXylqYWR9jvpywq12c=", "subType": "00" } }, { "$binary": { "base64": "MZMxEQ5ikx0PG1YFIExv0UnTZogsvgeOEZTpzvBDn4w=", "subType": "00" } }, { "$binary": { "base64": "yZMyMZBDrWbAhvnic7vvIYhmO9m5H2iuv0c8KNZrBzY=", "subType": "00" } }, { "$binary": { "base64": "xxM14hTPY5j0vvcK2C7YAEjzdsfUTFHozHC0hEo1bxI=", "subType": "00" } }, { "$binary": { "base64": "+01rqR1xVwkpGXcstbk1ItJqFVjH6Q8MGxEN3Cm9Y1A=", "subType": "00" } }, { "$binary": { "base64": "xOpLV0Z2VTRJ3iWtnWZcsyjXubTIkYWo31cO+HV1o1k=", "subType": "00" } }, { "$binary": { "base64": "BWUOLqgLBqc5NwxVlSV5H3KFQPXbCp7mdo+jF+8cJqY=", "subType": "00" } }, { "$binary": { "base64": "fuQb1S6xZDGlrEbK+kI23aL53PP1PVNwqICnZNt9Yzg=", "subType": "00" } }, { "$binary": { "base64": "SfscnoibFttahLdPVC4Ee+47ewGFKpDSU7M6HX19bKE=", "subType": "00" } }, { "$binary": { "base64": "rpSW2awybNVeKtat91VFxqbINoTfNhPfQAu+d73Xtf8=", "subType": "00" } }, { "$binary": { "base64": "9M/CP9ccOIIj2LLFmE0GFDO0Ban2wsNalEXfM6+h+1s=", "subType": "00" } }, { "$binary": { "base64": "WrEMG49l1ye4MhXs5ZS9tz8P6h+hDvthIg/2wW9ne1Q=", "subType": "00" } }, { "$binary": { "base64": "ImNhbfeyfH8qIEeA5ic0s3dAQBdzzTBS+CPsNih9vZ0=", "subType": "00" } }, { "$binary": { "base64": "dWP33YDSn04UKJN2ogh2Rui0iW/0q2y18OCDRVcfyoo=", "subType": "00" } }, { "$binary": { "base64": "lYv0isAtfGh6H9tdp3cp2eHU7q2J+uk7QrgcxtK3w7Y=", "subType": "00" } }, { "$binary": { "base64": "VGMoamB/+7zTOYcY/pqJc96xlv2PdW4hwsIAEIslTDQ=", "subType": "00" } }, { "$binary": { "base64": "yNeBWMF7BnD9wVwz2PgJsvWr77QiVvvWUvJF0+fqBug=", "subType": "00" } }, { "$binary": { "base64": "SfpvObJ+tJBXSvqeN7vlOfmhYign635lciYAJIjUtY8=", "subType": "00" } }, { "$binary": { "base64": "dsen4NqjzVGjpjufiTMs3+gqeD09EbnuogPgxrJECwg=", "subType": "00" } }, { "$binary": { "base64": "pxCWVM3sn19NsFEpgHbgLa+PmYlhN3mMiP0Wk8kJhYw=", "subType": "00" } }, { "$binary": { "base64": "q11KNvJszjYIB9n9HcC+N4uz11a3eRj1L3BH9scKMDQ=", "subType": "00" } }, { "$binary": { "base64": "A1PmkgcEToWh1JiVWE6mI5jUu7poxWWuCUt/cgRUUDc=", "subType": "00" } }, { "$binary": { "base64": "qJo3Hu4PJeanL7XEaWXO/n3YsodhZyd+MJOOmB9Kpd8=", "subType": "00" } }, { "$binary": { "base64": "BkBKLO8URFscfRY9Bav/1+L9mLohDgNr/MkZtGiraIs=", "subType": "00" } }, { "$binary": { "base64": "rZq5WA3Hx3xthOyHAJXK//f8pE2qbz7YKu3TIMp9GFY=", "subType": "00" } }, { "$binary": { "base64": "X07a/Lm80p5xd4RFs1dNmw+90tmPDPdGiAKVZkxd4zY=", "subType": "00" } }, { "$binary": { "base64": "6YrBn2ofIw1b5ooakrLOwF41BWrps8OO0H9WH4/rtlE=", "subType": "00" } }, { "$binary": { "base64": "0l86Ag5OszXpa78SlOUV3K9nff5iC1p0mRXtLg9M1s4=", "subType": "00" } }, { "$binary": { "base64": "Hn6yuxFHodeyu7ISlhYrbSf9pTiH4TDEvbYLWjTwFO0=", "subType": "00" } }, { "$binary": { "base64": "zdf4y2etKBuIpkEU1zMwoCkCsdisfXZCh8QPamm+drY=", "subType": "00" } }, { "$binary": { "base64": "rOQ9oMdiK5xxGH+jPzOvwVqdGGnF3+HkJXxn81s6hp4=", "subType": "00" } }, { "$binary": { "base64": "61aKKsE3+BJHHWYvs3xSIBvlRmKswmaOo5rygQJguUg=", "subType": "00" } }, { "$binary": { "base64": "KuDb/GIzqDM8wv7m7m8AECiWJbae5EKKtJRugZx7kR0=", "subType": "00" } }, { "$binary": { "base64": "Q+t8t2TmNUiCIorVr9F3AlVnX+Mpt2ZYvN+s8UGict8=", "subType": "00" } }, { "$binary": { "base64": "tJRZIpKxUgHyL83kW8cvfjkxN3z6WoNnUg+SQw+LK+k=", "subType": "00" } }, { "$binary": { "base64": "pnUsYjip8SvW0+m9mR5WWTkpK+p6uwJ6yBUAlBnFKMk=", "subType": "00" } }, { "$binary": { "base64": "PArHlz+yPRYDycAP/PgnI/AkP8Wgmfg++Vf4UG1Bf0E=", "subType": "00" } }, { "$binary": { "base64": "wnIh53Q3jeK8jEBe1n8kJLa89/H0BxO26ZU8SRIAs9Q=", "subType": "00" } }, { "$binary": { "base64": "4F8U59gzBLGhq58PEWQk2nch+R0Va7eTUoxMneReUIA=", "subType": "00" } }, { "$binary": { "base64": "ihKagIW3uT1dm22ROr/g5QaCpxZVj2+Fs/YSdM2Noco=", "subType": "00" } }, { "$binary": { "base64": "EJtUOOwjkrPUi9mavYAi+Gom9Y2DuFll7aDwo4mq0M0=", "subType": "00" } }, { "$binary": { "base64": "dIkr8dbaVRQFskAVT6B286BbcBBt1pZPEOcTZqk4ZcI=", "subType": "00" } }, { "$binary": { "base64": "aYVAcZYkH/Tieoa1XOjE/zCy5AJcVTHjS0NG2QB7muA=", "subType": "00" } }, { "$binary": { "base64": "sBidL6y8TenseetpioIAAtn0lK/7C8MoW4JXpVYi3z8=", "subType": "00" } }, { "$binary": { "base64": "0Dd2klU/t4R86c2WJcJDAd57k/N7OjvYSO5Vf8KH8sw=", "subType": "00" } }, { "$binary": { "base64": "I3jZ92WEVmZmgaIkLbuWhBxl7EM6bEjiEttgBJunArA=", "subType": "00" } }, { "$binary": { "base64": "aGHoQMlgJoGvArjfIbc3nnkoc8SWBxcrN7hSmjMRzos=", "subType": "00" } }, { "$binary": { "base64": "bpiWPnF/KVBQr5F6MEwc5ZZayzIRvQOLDAm4ntwOi8g=", "subType": "00" } }, { "$binary": { "base64": "tI7QVKbE6avWgDD9h4QKyFlnTxFCwd2iLySKakxNR/I=", "subType": "00" } }, { "$binary": { "base64": "XGsge0CnoaXgE3rcpKm8AEeku5QVfokS3kcI+JKV1lk=", "subType": "00" } }, { "$binary": { "base64": "JQxlryW2Q5WOwfrjAnaZxDvC83Dg6sjRVP5zegf2WiM=", "subType": "00" } }, { "$binary": { "base64": "YFuHKJOfoqp1iGVxoFjx7bLYgVdsN4GuUFxEgO9HJ5s=", "subType": "00" } }, { "$binary": { "base64": "Z6vUdiCR18ylKomf08uxcQHeRtmyav7/Ecvzz4av3k4=", "subType": "00" } }, { "$binary": { "base64": "SPGo1Ib5AiP/tSllL7Z5PAypvnKdwJLzt8imfIMSEJQ=", "subType": "00" } }, { "$binary": { "base64": "m94Nh6PFFQFLIib9Cu5LAKavhXnagSHG6F5EF8lD96I=", "subType": "00" } }, { "$binary": { "base64": "pfEkQI98mB+gm1+JbmVurPAODMFPJ4E8DnqfVyUWbSo=", "subType": "00" } }, { "$binary": { "base64": "DNj3OVRLbr43s0vd+rgWghOL3FqeO/60npdojC8Ry/M=", "subType": "00" } }, { "$binary": { "base64": "kAYIQrjHVu49W8FTxyxJeiLVRWWjC9fPcBn+Hx1F+Ss=", "subType": "00" } }, { "$binary": { "base64": "aCSO7UVOpoQvu/iridarxkxV1SVxU1i9HVSYXUAeXk4=", "subType": "00" } }, { "$binary": { "base64": "Gh6hTP/yj1IKlXQ+Q69KTfMlGZjEcXoRLGbQHNFo/1s=", "subType": "00" } }, { "$binary": { "base64": "/gDgIFQ4tAlJk3GN48IS5Qa5IPmErwGk8CHxAbp6gs0=", "subType": "00" } }, { "$binary": { "base64": "PICyimwPjxpusyKxNssOOwUotAUbygpyEtORsVGXT8g=", "subType": "00" } }, { "$binary": { "base64": "4lu+cBHyAUvuxC6JUNyHLzHsCogGSWFFnUCkDwfQdgI=", "subType": "00" } }, { "$binary": { "base64": "pSndkmoNUJwXjgkbkgOrT5f9nSvuoMEZOkwAN9ElRaE=", "subType": "00" } }, { "$binary": { "base64": "tyW+D4i26QihNM5MuBM+wnt5AdWGSJaJ4X5ydc9iWTU=", "subType": "00" } }, { "$binary": { "base64": "9Syjr8RoxUgPKr+O5rsCu07AvcebA4P8IVKyS1NVLWc=", "subType": "00" } }, { "$binary": { "base64": "67tPfDYnK2tmrioI51fOBG0ygajcV0pLo5+Zm/rEW7U=", "subType": "00" } }, { "$binary": { "base64": "y0EiPRxYTuS1eVTIaPQUQBBxwkyxNckbePvKgChwd0M=", "subType": "00" } }, { "$binary": { "base64": "NWd+2veAaeXQgR3vCvzlI4R1WW67D5YsVLdoXfdb8qg=", "subType": "00" } }, { "$binary": { "base64": "PY5RQqKQsL2GqBBSPNOEVpojNFRX/NijCghIpxD6CZk=", "subType": "00" } }, { "$binary": { "base64": "lcvwTyEjFlssCJtdjRpdN6oY+C7bxZY+WA+QAqzj9zg=", "subType": "00" } }, { "$binary": { "base64": "CWE7XRNylvTwO/9Fv56dNqUaQWMmESNS/GNIwgBaEI0=", "subType": "00" } }, { "$binary": { "base64": "ijwlrUeS8nRYqK1F8kiCYF0mNDolEZS+/lJO1Lg93C8=", "subType": "00" } }, { "$binary": { "base64": "8KzV+qYGYuIjoNj8eEpnTuHrMYuhzphl80rS6wrODuU=", "subType": "00" } }, { "$binary": { "base64": "wDyTLjSEFF895hSQsHvmoEQVS6KIkZOtq1c9dVogm9I=", "subType": "00" } }, { "$binary": { "base64": "SGrtPuMYCjUrfKF0Pq/thdaQzmGBMUvlwN3ORIu9tHU=", "subType": "00" } }, { "$binary": { "base64": "KySHON3hIoUk4xWcwTqk6IL0kgjzjxgMBObVIkCGvk4=", "subType": "00" } }, { "$binary": { "base64": "hBIdS9j0XJPeT4ot73ngELkpUoSixvRBvdOL9z48jY8=", "subType": "00" } }, { "$binary": { "base64": "Tx6um0q9HjS5ZvlFhvukpI6ORnyrXMWVW1OoxvgqII0=", "subType": "00" } }, { "$binary": { "base64": "zFKlyfX5H81+d4A4J3FKn4T5JfG+OWtR06ddyX4Mxas=", "subType": "00" } }, { "$binary": { "base64": "cGgCDuPV7MeMMYEDpgOupqyNP4BQ4H7rBnd2QygumgM=", "subType": "00" } }, { "$binary": { "base64": "IPaUoy98v11EoglTpJ4kBlEawoZ8y7BPwzjLYBpkvHQ=", "subType": "00" } }, { "$binary": { "base64": "Pfo4Am6tOWAyZNn8G9W5HWWGC3ZWmX0igI/RRB870Ro=", "subType": "00" } }, { "$binary": { "base64": "fnTSjd7bC1Udoq6iM7UDnHAC/lsIXSHp/Gy332qw+/I=", "subType": "00" } }, { "$binary": { "base64": "fApBgVRrTDyEumkeWs5p3ag9KB48SbU4Si0dl7Ns9rc=", "subType": "00" } }, { "$binary": { "base64": "QxudfBItgoCnUj5NXVnSmWH3HK76YtKkMmzn4lyyUYY=", "subType": "00" } }, { "$binary": { "base64": "sSOvwhKa29Wq94bZ5jGIiJQGbG1uBrKSBfOYBz/oZeI=", "subType": "00" } }, { "$binary": { "base64": "FdaMgwwJ0NKsqmPZLC5oE+/0D74Dfpvig3LaI5yW5Fs=", "subType": "00" } }, { "$binary": { "base64": "sRWBy12IERN43BSZIrnBfC9+zFBUdvjTlkqIH81NGt4=", "subType": "00" } }, { "$binary": { "base64": "/4tIRpxKhoOwnXAiFn1Z7Xmric4USOIfKvTYQXk3QTc=", "subType": "00" } } ] }, { "_id": { "$numberInt": "1" }, "encryptedDecimalNoPrecision": { "$$type": "binData" }, "__safeContent__": [ { "$binary": { "base64": "bE1vqWj3KNyM7cCYUv/cnYm8BPaUL3eMp5syTHq6NF4=", "subType": "00" } }, { "$binary": { "base64": "RGTjNVEsNJb+DG7DpPOam8rQWD5HZAMpRyiTQaw7tk8=", "subType": "00" } }, { "$binary": { "base64": "I93Md7QNPGmEEGYU1+VVCqBPBEvXdqHPtTJtMOn06Yk=", "subType": "00" } }, { "$binary": { "base64": "GecBFQ1PemlECWZWCl7f74vmsL6eB6mzQ9n6tK6FYfs=", "subType": "00" } }, { "$binary": { "base64": "QpjhZl+O1ORifgtCZuWAdcP6OKL7IZ2cA46v8FJcV28=", "subType": "00" } }, { "$binary": { "base64": "RlQWwhU+uVv0a+9IB5cUkEfvHBvOw3B1Sx6WfPWMqes=", "subType": "00" } }, { "$binary": { "base64": "ubb81XTC7U+4tcNzf1oYvOY6gR5hC2Izqx54f4GuJ0E=", "subType": "00" } }, { "$binary": { "base64": "6M4Q5NMQ9TqNnjzGOxIkiUIY8TEL0I3XD1QnhefQUqU=", "subType": "00" } }, { "$binary": { "base64": "BtInzk9t2FFMCEY6AQ7zN8jwrrZEs2irSv6q0Q4NaIw=", "subType": "00" } }, { "$binary": { "base64": "6vxXfETu9cuBIpRBo3jUUU04mJIH/aAhLX8K6VI5Xv0=", "subType": "00" } }, { "$binary": { "base64": "wXPCdS+q23zi1bkPnaVG2j0PsVtxdeSLJ//h6J1x8RU=", "subType": "00" } }, { "$binary": { "base64": "KY3KkfBAsN2l80wbpj41G0gwBR5KmmFnZcagg7D3ENk=", "subType": "00" } }, { "$binary": { "base64": "tI8NFAxXCX4VOnY5X73K6KI/Yspd3aR94KV39MhJlAw=", "subType": "00" } }, { "$binary": { "base64": "nFxH0UC3mATKA6Vboz+QX/hAjj19kF/SH6H5Cne7qC0=", "subType": "00" } }, { "$binary": { "base64": "q8hYqIYaIi7nOdG/7qQZYnz8Bsacfi66M1nVku4SH08=", "subType": "00" } }, { "$binary": { "base64": "4saA92R4arp4anvD9xFtze+sNcQqTEhPHyl1h70A8NE=", "subType": "00" } }, { "$binary": { "base64": "DbIziOBRRyeQS6RtBR09E37LV+CTKrEjGoRMLSpG6eE=", "subType": "00" } }, { "$binary": { "base64": "Fv80Plp/7w2gnVqrwawLd6qhJ10G4NCDm3re67cNq4Y=", "subType": "00" } }, { "$binary": { "base64": "T/T2oiQCBBES4YN7EodzPRdabZSFlYIClHBym+bQUZE=", "subType": "00" } }, { "$binary": { "base64": "ZQgHD3l46Ujqtbnj1VbbeM29C9wJzOhz+yZ/7XdSrxk=", "subType": "00" } }, { "$binary": { "base64": "ltlFKzWvyZvHxDFOYDd/XXJ6kUiJj0ln2HTCEz2o4Z4=", "subType": "00" } }, { "$binary": { "base64": "flW8A7bltC1u8bzx0WJtxosGJdOVsJFfbx33jxnpFGg=", "subType": "00" } }, { "$binary": { "base64": "SXO+92QbMKwUSG2t27ciunV1c3VvFkUuDmSczpRe008=", "subType": "00" } }, { "$binary": { "base64": "+KioGs1GM+xRBzFE67ePTWj04KMSE5/Y6qUF7nJ5kvU=", "subType": "00" } }, { "$binary": { "base64": "L3xNVbh6YH+RzqABN+5Jgb7T234Efpn766DmUvxIxgg=", "subType": "00" } }, { "$binary": { "base64": "hPF+60mBYPjh21dEmPlBhKgyc9S2qLtTkypYvnqP2Fc=", "subType": "00" } }, { "$binary": { "base64": "EletRsETy2HcjaPIm2c8CkT7ch/P3pJJDC8hasepcSU=", "subType": "00" } }, { "$binary": { "base64": "r5bMXUaNKqLPxZ+TG9HYTG4aSDgcpim27rN8rQFkM0w=", "subType": "00" } }, { "$binary": { "base64": "0Q7Erdr8+/S0wUEDDIqlS5XjBVWvhZY65K0uUDb6+Ns=", "subType": "00" } }, { "$binary": { "base64": "xEcnhXy35hbXNVBPOOt3TUHbxvKfQ48KjA9b6/rbMqQ=", "subType": "00" } }, { "$binary": { "base64": "T8bEpiQNgsEudXvyKE9SZlSvbpV/LUaslsdqgSFltyo=", "subType": "00" } }, { "$binary": { "base64": "hIoiaF2YjnxDbODfhFEB+JGZ5nf8suD3Shck5bwQ3N0=", "subType": "00" } }, { "$binary": { "base64": "qnA6qzejeRJ0rsZaZ0zOvKAaXyxt5lpscKQNYFZNl4k=", "subType": "00" } }, { "$binary": { "base64": "anAKCL2DN/le2VaP0n2ucYSEH/DaaEH/8Sa4OqTZsRA=", "subType": "00" } }, { "$binary": { "base64": "JCZlBJaFm618oWYSnT9Jr1MtwFVw4BZjOzO+5yWgR90=", "subType": "00" } }, { "$binary": { "base64": "yxyk4n9762WzcDVGnTn4jCqUnSMIVCrLDIjCX1QVj34=", "subType": "00" } }, { "$binary": { "base64": "fDI6fdKvDJwim5/CQwWZEzcrXE3LHgy7FTtffcC7tXE=", "subType": "00" } }, { "$binary": { "base64": "Vex+gcz5T+WkzsVZQrkqUR2ryyZbnaOGuWpYvjN0zCw=", "subType": "00" } }, { "$binary": { "base64": "8TLEXz+Gbbp6llHpZXVjLsdlYY9f6hrKpHVpyfDe0RY=", "subType": "00" } }, { "$binary": { "base64": "7fTyt5BrunypS65TfOzFW2E2qdIuT4SLeDeGlbQoJCs=", "subType": "00" } }, { "$binary": { "base64": "8fKGrkqN0/KuSjyXgDBmRauDKrSa//JBKRWHEB9xBf4=", "subType": "00" } }, { "$binary": { "base64": "s4codmG7uN4ss6P357jL21lazEe90M9GOK5WrOknSV0=", "subType": "00" } }, { "$binary": { "base64": "RkSpua8XF+NUdxVDU90EbLUTTyZFX3tt3atBTroFaRk=", "subType": "00" } }, { "$binary": { "base64": "LnTCuCDyAHK5B9KXzjtwGmWB+qergQk2OCjnIx9MI2A=", "subType": "00" } }, { "$binary": { "base64": "cBFh0virAX4pVXf/udIGI2951i0+0aZAdJcBVGtYnT4=", "subType": "00" } }, { "$binary": { "base64": "G54X6myQXWZ5fw/G31en3QbdgfXzL9+hFTtJpnWMqDI=", "subType": "00" } }, { "$binary": { "base64": "EdsiiuezcsFJFnYIyGjCOhnqMj1BOwTB5EFxN+ERUkg=", "subType": "00" } }, { "$binary": { "base64": "dVH9MXLtk0WTwGQ3xmrhOqfropMUkDW3o6paNPGl3NU=", "subType": "00" } }, { "$binary": { "base64": "sB3HqXKWY3pKbuEH8BTbfNIGfbY+7/ZbOc3XC+JRNNI=", "subType": "00" } }, { "$binary": { "base64": "WHyDk62Xhqbo4/iie2aLIM4x2uuAjv6102dJSHI58oM=", "subType": "00" } }, { "$binary": { "base64": "pNUFuHpeNRDUZ/NrtII2c6sNc9eGR1lIUlIyXKERA+0=", "subType": "00" } }, { "$binary": { "base64": "UPa+pdCqnN0bfAptdzldQOSd01gidrDKy8KhWrpSKAI=", "subType": "00" } }, { "$binary": { "base64": "l+7dOAlo+HUffMqFYXL6pgUFeTbwOM9CjKQLxEoLtc4=", "subType": "00" } }, { "$binary": { "base64": "SRnDXV/rN6C8xwMutv9E1luv3DOUio3VkgPr8Cpm7Ew=", "subType": "00" } }, { "$binary": { "base64": "QcH6gl+gX7xZ7OWhUNQMbndJy0Piz49pDo6RsnLkVSA=", "subType": "00" } }, { "$binary": { "base64": "t+uL4DnfsI/Zll/KXWW1cOKX3Hu8WIkm3pt9efCVSAQ=", "subType": "00" } }, { "$binary": { "base64": "myutHDctku/+Uug/nD8gRbYvmx/IovtoAAC2/fz2oHA=", "subType": "00" } }, { "$binary": { "base64": "6C+cjD0e0nSCP6cPqQYbNG7SlOd6Mfvi8hyfm7Ng+D8=", "subType": "00" } }, { "$binary": { "base64": "zg01JSoOj9oBKT0S1ldJucXzY5AKgreS+h2xJreWTOs=", "subType": "00" } }, { "$binary": { "base64": "7qQ80/FjodHl1m1py/Oii0/9C/xWbLdhaRXQ+kkCP10=", "subType": "00" } }, { "$binary": { "base64": "YwWMNH07vL6c5Nhg+MRnVByhzUunu8y0VLM9z/XvR5U=", "subType": "00" } }, { "$binary": { "base64": "Dle8bU98+fudAbc14SToZFkwvV3tcYVsjDug0NWljpc=", "subType": "00" } }, { "$binary": { "base64": "J+eKL1vPJmlzltvhI6Li5Fz/TJmi3Ng+ehRTcs46API=", "subType": "00" } }, { "$binary": { "base64": "zB3XzfFygLwC3WHkj0up+VbEd25KKoce1vOpG/5bwK4=", "subType": "00" } }, { "$binary": { "base64": "vnVnmOnL+z2pqwE+A6cVKS0Iwy4F4/2IiElJca9bUQM=", "subType": "00" } }, { "$binary": { "base64": "+lG5r/Fpqry3BtFuvY67+RntmHAMDoLVOSGc6ZoXPb0=", "subType": "00" } }, { "$binary": { "base64": "L5MXQertqc6uj7ADe8aWKbd1sYHPCE7P1VYVg9Zc3VI=", "subType": "00" } }, { "$binary": { "base64": "imKONuZgopt0bhM3GMX2WVPwQYMTobuUUEdhcLfHs4c=", "subType": "00" } }, { "$binary": { "base64": "eOkU1J1uVbiVFWBerbXsSIVcF2nqiicTkFy4x7kFHB8=", "subType": "00" } }, { "$binary": { "base64": "gI0uDhXeoH/UatDQKEf4qo8FHzWZDhb/wuWTqbq/ID4=", "subType": "00" } }, { "$binary": { "base64": "cOkd5Aa3btYhtojE/smsF/PJnULqQ4NNqTkU6KXTFmo=", "subType": "00" } }, { "$binary": { "base64": "AWNJMs1MTe294oFipp8Y6P0CjpkZ4qCZoClQF3XcHq8=", "subType": "00" } }, { "$binary": { "base64": "6gJtlzXOFhGYrVbTuRMmvMlDTwXdNtR9aGBlHZPwIMw=", "subType": "00" } }, { "$binary": { "base64": "LEmwVGA/xsEG7UrcOoYLFu6KCXgijzFznenknuDacm8=", "subType": "00" } }, { "$binary": { "base64": "mIRFPTXRrGaPtp/Ydij2jgkRe4uoUvAKxW2d8b9zYL0=", "subType": "00" } }, { "$binary": { "base64": "B+Uv2u48WALOO0L311z+eryjYQzKJVMfdHMZPhOAFmY=", "subType": "00" } }, { "$binary": { "base64": "INXXp0wDyVCq+NtfIrrC2ciETmyW/dWB/48/u4yLEZ4=", "subType": "00" } }, { "$binary": { "base64": "se7DGo8XrlrQDLEcco1tZrQt9kDe+0RTyl2bw/quG4w=", "subType": "00" } }, { "$binary": { "base64": "vr0m2+Zk9lbN6UgWCyn8xJWJOokU3IDYab5U5q1+CgQ=", "subType": "00" } }, { "$binary": { "base64": "XI+eJ8Gy2JktG1gICgoj1qpsfy1tKmH0kglWbaQH6DA=", "subType": "00" } }, { "$binary": { "base64": "A+UCuNnuAUqnQzspA6TVqUPRmtZmpSex5HFw7THRxs0=", "subType": "00" } }, { "$binary": { "base64": "xaH2Ehfljd19uo0Fvb3iwkdaiWEVQd2YPoitgEPkhSM=", "subType": "00" } }, { "$binary": { "base64": "S/iZBJGcc8+qZxyMtab65MMBoSglybwk3x58Nb86gnY=", "subType": "00" } }, { "$binary": { "base64": "w14ZE5qqY5YgkS4Zcs9YNbrQbY1XfGOOHNn9bOYnFVQ=", "subType": "00" } }, { "$binary": { "base64": "0MhGd/jEF1vjkKGp+ZMn9SjLK54jkp9W4Hg+Sp/oxaI=", "subType": "00" } }, { "$binary": { "base64": "92QZ73e/NRTYgCm4aifaKth6aAsKnLLccBc0zx/qUTY=", "subType": "00" } }, { "$binary": { "base64": "WOjzemCgFJOiGIp81RSVh/tFlzSTj9eFWcBnsiv2Ycs=", "subType": "00" } }, { "$binary": { "base64": "DrsP9CmfKPjw5yLL8bnSeAxfNzAwlb+Z8OqCiKgBY7o=", "subType": "00" } }, { "$binary": { "base64": "lMogqg8veBv6mri3/drMe9afJiKMvevkmGcw9BedfLo=", "subType": "00" } }, { "$binary": { "base64": "TxqwNcY8Tg2MPpNdkPBwvfpuTttSYRHU26DGECKYQ9o=", "subType": "00" } }, { "$binary": { "base64": "l0u1b4b4vYACWIwfnB7PZac4oDEgjQZCzHruNPTgAIY=", "subType": "00" } }, { "$binary": { "base64": "iVSGQ+cCfhbWIrY/v/WBORK92elu9gfRKyGhr6r/k00=", "subType": "00" } }, { "$binary": { "base64": "yK1forG50diEXte8ECzjfpHeYsPyuQ/dgxbxn/nzY5k=", "subType": "00" } }, { "$binary": { "base64": "gIfTLCD3VwnOwkC0zPXWTqaITxX6ZplA69PO2a6zolc=", "subType": "00" } }, { "$binary": { "base64": "O/Zxlgh3WqpzJ7+Sd8XWMVID4/GXJUUWaSqfgDUi3b0=", "subType": "00" } }, { "$binary": { "base64": "ZQ6yv368zwahUqSUYH/StL0Qgz/TwS1CzlMjVDvCciI=", "subType": "00" } }, { "$binary": { "base64": "m2rPEYkjwyiKdonMrKlcF7hya4lFOAUwEePJ3SgrNx8=", "subType": "00" } }, { "$binary": { "base64": "Mq0yl5iVKlq71bT/dT/fXOWf2n90bTnXFnOdGDN0JOc=", "subType": "00" } }, { "$binary": { "base64": "6qDGMXipPLC2O6EAAMjO2F9xx4rdqZso4IkPpH2304U=", "subType": "00" } }, { "$binary": { "base64": "jvQHRQQa2RIszE2LX2Hv2LbRhYawJ6qmtRt8HZzFQXg=", "subType": "00" } }, { "$binary": { "base64": "ovJXQrkZlpeHRciKyE/WWNm5O389gRgzx1W+Dw596X4=", "subType": "00" } }, { "$binary": { "base64": "a4kgRNvYctGYqyQv9qScL/WkljTYVylJ9pE9KDULlxU=", "subType": "00" } }, { "$binary": { "base64": "qV4Q48vPiCJMTjljotzYKI/zfExWpkKOSHGcAjGyDig=", "subType": "00" } }, { "$binary": { "base64": "jtI7zbBF+QW/aYYTkn90zzyHLXLgmy7l1bzgMb2oqic=", "subType": "00" } }, { "$binary": { "base64": "q0KmJl9txPdn962UNvnfe6UFhdk9YaFZuTm33F+csso=", "subType": "00" } }, { "$binary": { "base64": "ULNdEqeZJgtmNOhN/Y9INzsE9AnxWYwOMn+pIbRXIFs=", "subType": "00" } }, { "$binary": { "base64": "R4oz9+wkdjpKe5tE1jpG7IURAnfvS5fLP4LrD5cZfTE=", "subType": "00" } }, { "$binary": { "base64": "qG5Z7VhwSu/HT/YFTgDzyAAzJKq51xPw2HeEV5btYC4=", "subType": "00" } }, { "$binary": { "base64": "OM/1DmIIZ5Qyhtq8TGkHTBEMVKjAnKRZMRXYtTG8ctc=", "subType": "00" } }, { "$binary": { "base64": "2R5vZbljLXnDFA99YfGuRB7pAdPJVKsT25zLNMC0fUk=", "subType": "00" } }, { "$binary": { "base64": "OMbavF2EmdAz1fHkLV3ctFEUDfriKhoT2gidwHZ9z1o=", "subType": "00" } }, { "$binary": { "base64": "MWT4Zrw3/vVvTYMa1Is5Pjr3wEwnBfnEAPPUAHKQhNU=", "subType": "00" } }, { "$binary": { "base64": "tBkRPfG9yxfKocQx5pAJX0oEHKPL0Tgtr+0UYe09InE=", "subType": "00" } }, { "$binary": { "base64": "lqxpnDR/H0YgH7RcfKoNoaaRhe1SIazIeMbQ1fu9y3Q=", "subType": "00" } }, { "$binary": { "base64": "utT1UdR22PWOTrOkZauztX613lAplV4eh/ejTRb7ZSk=", "subType": "00" } }, { "$binary": { "base64": "S+Y2yFyKi/a6FXhih4yGo29X8I8OT6/zwEoX6NMKT4o=", "subType": "00" } }, { "$binary": { "base64": "QSjVppg29x6oS5yBg8OFjrFt0tuTpWCuKxfIy0k8YnE=", "subType": "00" } }, { "$binary": { "base64": "y3r6/Xsfvsl3HksXlVYkJgHUqpQGfICxg3x9f8Zw1qM=", "subType": "00" } }, { "$binary": { "base64": "BSltHzEwDjFN4du9rDHAPvl22atlcTioEtt+gC5L1tk=", "subType": "00" } }, { "$binary": { "base64": "0arGXjSN0006UnXbrWsGqhvBair569DeFDUME3Df3rA=", "subType": "00" } }, { "$binary": { "base64": "s/DumaMad08S+PBUUcrS+v42K0z8HgcdiQtrFAEu2Qs=", "subType": "00" } }, { "$binary": { "base64": "EzJ8Y8N0OQBTlnvrK82PdevDNZZO4E6CNgYVu8Cj6Ks=", "subType": "00" } }, { "$binary": { "base64": "VA4vr8jBPI5QdiPrULzzZjBMIUbG3V7Slg5zm0bFcKc=", "subType": "00" } }, { "$binary": { "base64": "YAOvEB2ZLtq9LQiFViBHWaxxWVVonC2rNYj9tN9s3L0=", "subType": "00" } }, { "$binary": { "base64": "hgaHMo9aAGS+nBwvqnTjZO+YkiQPY1c1XcIYeaYKHyI=", "subType": "00" } }, { "$binary": { "base64": "YvaoLt3ZpH0atB0tNzwMjpoxRYJXl0DqSjisMJiGVBE=", "subType": "00" } }, { "$binary": { "base64": "EMmW6CptFsiLoPOi5/uAJQ2FmeLg6mCpuVLLrRWk7Mc=", "subType": "00" } }, { "$binary": { "base64": "1jQsNMarSnarlYmXEuoFokeBMg/090qUD9wqo1Zn8Gs=", "subType": "00" } }, { "$binary": { "base64": "hupXNKhRpJxpyDAAP1TgJ5JMZh9lhbMk6s7D7dMS3C8=", "subType": "00" } } ] } ] } } } ] } fle2v2-Range-Decimal-Correctness.json000066400000000000000000000667071462766011000360140ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/client-side-encryption/spec/legacy{ "runOn": [ { "minServerVersion": "7.0.0", "topology": [ "replicaset" ] } ], "database_name": "default", "collection_name": "default", "data": [], "encrypted_fields": { "fields": [ { "keyId": { "$binary": { "base64": "EjRWeBI0mHYSNBI0VniQEg==", "subType": "04" } }, "path": "encryptedDecimalNoPrecision", "bsonType": "decimal", "queries": { "queryType": "rangePreview", "contention": { "$numberLong": "0" }, "sparsity": { "$numberLong": "1" } } } ] }, "key_vault_data": [ { "_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" } } ], "tests": [ { "description": "Find with $gt", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "local": { "key": { "$binary": { "base64": "Mng0NCt4ZHVUYUJCa1kxNkVyNUR1QURhZ2h2UzR2d2RrZzh0cFBwM3R6NmdWMDFBMUN3YkQ5aXRRMkhGRGdQV09wOGVNYUMxT2k3NjZKelhaQmRCZGJkTXVyZG9uSjFk", "subType": "00" } } } } } }, "operations": [ { "name": "insertOne", "arguments": { "document": { "_id": 0, "encryptedDecimalNoPrecision": { "$numberDecimal": "0.0" } } } }, { "name": "insertOne", "arguments": { "document": { "_id": 1, "encryptedDecimalNoPrecision": { "$numberDecimal": "1.0" } } } }, { "name": "find", "arguments": { "filter": { "encryptedDecimalNoPrecision": { "$gt": { "$numberDecimal": "0.0" } } } }, "result": [ { "_id": 1, "encryptedDecimalNoPrecision": { "$numberDecimal": "1.0" } } ] } ] }, { "description": "Find with $gte", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "local": { "key": { "$binary": { "base64": "Mng0NCt4ZHVUYUJCa1kxNkVyNUR1QURhZ2h2UzR2d2RrZzh0cFBwM3R6NmdWMDFBMUN3YkQ5aXRRMkhGRGdQV09wOGVNYUMxT2k3NjZKelhaQmRCZGJkTXVyZG9uSjFk", "subType": "00" } } } } } }, "operations": [ { "name": "insertOne", "arguments": { "document": { "_id": 0, "encryptedDecimalNoPrecision": { "$numberDecimal": "0.0" } } } }, { "name": "insertOne", "arguments": { "document": { "_id": 1, "encryptedDecimalNoPrecision": { "$numberDecimal": "1.0" } } } }, { "name": "find", "arguments": { "filter": { "encryptedDecimalNoPrecision": { "$gte": { "$numberDecimal": "0.0" } } }, "sort": { "_id": 1 } }, "result": [ { "_id": 0, "encryptedDecimalNoPrecision": { "$numberDecimal": "0.0" } }, { "_id": 1, "encryptedDecimalNoPrecision": { "$numberDecimal": "1.0" } } ] } ] }, { "description": "Find with $gt with no results", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "local": { "key": { "$binary": { "base64": "Mng0NCt4ZHVUYUJCa1kxNkVyNUR1QURhZ2h2UzR2d2RrZzh0cFBwM3R6NmdWMDFBMUN3YkQ5aXRRMkhGRGdQV09wOGVNYUMxT2k3NjZKelhaQmRCZGJkTXVyZG9uSjFk", "subType": "00" } } } } } }, "operations": [ { "name": "insertOne", "arguments": { "document": { "_id": 0, "encryptedDecimalNoPrecision": { "$numberDecimal": "0.0" } } } }, { "name": "insertOne", "arguments": { "document": { "_id": 1, "encryptedDecimalNoPrecision": { "$numberDecimal": "1.0" } } } }, { "name": "find", "arguments": { "filter": { "encryptedDecimalNoPrecision": { "$gt": { "$numberDecimal": "1.0" } } } }, "result": [] } ] }, { "description": "Find with $lt", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "local": { "key": { "$binary": { "base64": "Mng0NCt4ZHVUYUJCa1kxNkVyNUR1QURhZ2h2UzR2d2RrZzh0cFBwM3R6NmdWMDFBMUN3YkQ5aXRRMkhGRGdQV09wOGVNYUMxT2k3NjZKelhaQmRCZGJkTXVyZG9uSjFk", "subType": "00" } } } } } }, "operations": [ { "name": "insertOne", "arguments": { "document": { "_id": 0, "encryptedDecimalNoPrecision": { "$numberDecimal": "0.0" } } } }, { "name": "insertOne", "arguments": { "document": { "_id": 1, "encryptedDecimalNoPrecision": { "$numberDecimal": "1.0" } } } }, { "name": "find", "arguments": { "filter": { "encryptedDecimalNoPrecision": { "$lt": { "$numberDecimal": "1.0" } } } }, "result": [ { "_id": 0, "encryptedDecimalNoPrecision": { "$numberDecimal": "0.0" } } ] } ] }, { "description": "Find with $lte", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "local": { "key": { "$binary": { "base64": "Mng0NCt4ZHVUYUJCa1kxNkVyNUR1QURhZ2h2UzR2d2RrZzh0cFBwM3R6NmdWMDFBMUN3YkQ5aXRRMkhGRGdQV09wOGVNYUMxT2k3NjZKelhaQmRCZGJkTXVyZG9uSjFk", "subType": "00" } } } } } }, "operations": [ { "name": "insertOne", "arguments": { "document": { "_id": 0, "encryptedDecimalNoPrecision": { "$numberDecimal": "0.0" } } } }, { "name": "insertOne", "arguments": { "document": { "_id": 1, "encryptedDecimalNoPrecision": { "$numberDecimal": "1.0" } } } }, { "name": "find", "arguments": { "filter": { "encryptedDecimalNoPrecision": { "$lte": { "$numberDecimal": "1.0" } } }, "sort": { "_id": 1 } }, "result": [ { "_id": 0, "encryptedDecimalNoPrecision": { "$numberDecimal": "0.0" } }, { "_id": 1, "encryptedDecimalNoPrecision": { "$numberDecimal": "1.0" } } ] } ] }, { "description": "Find with $gt and $lt", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "local": { "key": { "$binary": { "base64": "Mng0NCt4ZHVUYUJCa1kxNkVyNUR1QURhZ2h2UzR2d2RrZzh0cFBwM3R6NmdWMDFBMUN3YkQ5aXRRMkhGRGdQV09wOGVNYUMxT2k3NjZKelhaQmRCZGJkTXVyZG9uSjFk", "subType": "00" } } } } } }, "operations": [ { "name": "insertOne", "arguments": { "document": { "_id": 0, "encryptedDecimalNoPrecision": { "$numberDecimal": "0.0" } } } }, { "name": "insertOne", "arguments": { "document": { "_id": 1, "encryptedDecimalNoPrecision": { "$numberDecimal": "1.0" } } } }, { "name": "find", "arguments": { "filter": { "encryptedDecimalNoPrecision": { "$gt": { "$numberDecimal": "0.0" }, "$lt": { "$numberDecimal": "2.0" } } } }, "result": [ { "_id": 1, "encryptedDecimalNoPrecision": { "$numberDecimal": "1.0" } } ] } ] }, { "description": "Find with equality", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "local": { "key": { "$binary": { "base64": "Mng0NCt4ZHVUYUJCa1kxNkVyNUR1QURhZ2h2UzR2d2RrZzh0cFBwM3R6NmdWMDFBMUN3YkQ5aXRRMkhGRGdQV09wOGVNYUMxT2k3NjZKelhaQmRCZGJkTXVyZG9uSjFk", "subType": "00" } } } } } }, "operations": [ { "name": "insertOne", "arguments": { "document": { "_id": 0, "encryptedDecimalNoPrecision": { "$numberDecimal": "0.0" } } } }, { "name": "insertOne", "arguments": { "document": { "_id": 1, "encryptedDecimalNoPrecision": { "$numberDecimal": "1.0" } } } }, { "name": "find", "arguments": { "filter": { "encryptedDecimalNoPrecision": { "$numberDecimal": "0.0" } } }, "result": [ { "_id": 0, "encryptedDecimalNoPrecision": { "$numberDecimal": "0.0" } } ] }, { "name": "find", "arguments": { "filter": { "encryptedDecimalNoPrecision": { "$numberDecimal": "1.0" } } }, "result": [ { "_id": 1, "encryptedDecimalNoPrecision": { "$numberDecimal": "1.0" } } ] } ] }, { "description": "Find with $in", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "local": { "key": { "$binary": { "base64": "Mng0NCt4ZHVUYUJCa1kxNkVyNUR1QURhZ2h2UzR2d2RrZzh0cFBwM3R6NmdWMDFBMUN3YkQ5aXRRMkhGRGdQV09wOGVNYUMxT2k3NjZKelhaQmRCZGJkTXVyZG9uSjFk", "subType": "00" } } } } } }, "operations": [ { "name": "insertOne", "arguments": { "document": { "_id": 0, "encryptedDecimalNoPrecision": { "$numberDecimal": "0.0" } } } }, { "name": "insertOne", "arguments": { "document": { "_id": 1, "encryptedDecimalNoPrecision": { "$numberDecimal": "1.0" } } } }, { "name": "find", "arguments": { "filter": { "encryptedDecimalNoPrecision": { "$in": [ { "$numberDecimal": "0.0" } ] } } }, "result": [ { "_id": 0, "encryptedDecimalNoPrecision": { "$numberDecimal": "0.0" } } ] } ] }, { "description": "Aggregate with $gte", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "local": { "key": { "$binary": { "base64": "Mng0NCt4ZHVUYUJCa1kxNkVyNUR1QURhZ2h2UzR2d2RrZzh0cFBwM3R6NmdWMDFBMUN3YkQ5aXRRMkhGRGdQV09wOGVNYUMxT2k3NjZKelhaQmRCZGJkTXVyZG9uSjFk", "subType": "00" } } } } } }, "operations": [ { "name": "insertOne", "arguments": { "document": { "_id": 0, "encryptedDecimalNoPrecision": { "$numberDecimal": "0.0" } } } }, { "name": "insertOne", "arguments": { "document": { "_id": 1, "encryptedDecimalNoPrecision": { "$numberDecimal": "1.0" } } } }, { "name": "aggregate", "arguments": { "pipeline": [ { "$match": { "encryptedDecimalNoPrecision": { "$gte": { "$numberDecimal": "0.0" } } } }, { "$sort": { "_id": 1 } } ] }, "result": [ { "_id": 0, "encryptedDecimalNoPrecision": { "$numberDecimal": "0.0" } }, { "_id": 1, "encryptedDecimalNoPrecision": { "$numberDecimal": "1.0" } } ] } ] }, { "description": "Aggregate with $gt with no results", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "local": { "key": { "$binary": { "base64": "Mng0NCt4ZHVUYUJCa1kxNkVyNUR1QURhZ2h2UzR2d2RrZzh0cFBwM3R6NmdWMDFBMUN3YkQ5aXRRMkhGRGdQV09wOGVNYUMxT2k3NjZKelhaQmRCZGJkTXVyZG9uSjFk", "subType": "00" } } } } } }, "operations": [ { "name": "insertOne", "arguments": { "document": { "_id": 0, "encryptedDecimalNoPrecision": { "$numberDecimal": "0.0" } } } }, { "name": "insertOne", "arguments": { "document": { "_id": 1, "encryptedDecimalNoPrecision": { "$numberDecimal": "1.0" } } } }, { "name": "aggregate", "arguments": { "pipeline": [ { "$match": { "encryptedDecimalNoPrecision": { "$gt": { "$numberDecimal": "1.0" } } } } ] }, "result": [] } ] }, { "description": "Aggregate with $lt", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "local": { "key": { "$binary": { "base64": "Mng0NCt4ZHVUYUJCa1kxNkVyNUR1QURhZ2h2UzR2d2RrZzh0cFBwM3R6NmdWMDFBMUN3YkQ5aXRRMkhGRGdQV09wOGVNYUMxT2k3NjZKelhaQmRCZGJkTXVyZG9uSjFk", "subType": "00" } } } } } }, "operations": [ { "name": "insertOne", "arguments": { "document": { "_id": 0, "encryptedDecimalNoPrecision": { "$numberDecimal": "0.0" } } } }, { "name": "insertOne", "arguments": { "document": { "_id": 1, "encryptedDecimalNoPrecision": { "$numberDecimal": "1.0" } } } }, { "name": "aggregate", "arguments": { "pipeline": [ { "$match": { "encryptedDecimalNoPrecision": { "$lt": { "$numberDecimal": "1.0" } } } } ] }, "result": [ { "_id": 0, "encryptedDecimalNoPrecision": { "$numberDecimal": "0.0" } } ] } ] }, { "description": "Aggregate with $lte", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "local": { "key": { "$binary": { "base64": "Mng0NCt4ZHVUYUJCa1kxNkVyNUR1QURhZ2h2UzR2d2RrZzh0cFBwM3R6NmdWMDFBMUN3YkQ5aXRRMkhGRGdQV09wOGVNYUMxT2k3NjZKelhaQmRCZGJkTXVyZG9uSjFk", "subType": "00" } } } } } }, "operations": [ { "name": "insertOne", "arguments": { "document": { "_id": 0, "encryptedDecimalNoPrecision": { "$numberDecimal": "0.0" } } } }, { "name": "insertOne", "arguments": { "document": { "_id": 1, "encryptedDecimalNoPrecision": { "$numberDecimal": "1.0" } } } }, { "name": "aggregate", "arguments": { "pipeline": [ { "$match": { "encryptedDecimalNoPrecision": { "$lte": { "$numberDecimal": "1.0" } } } }, { "$sort": { "_id": 1 } } ] }, "result": [ { "_id": 0, "encryptedDecimalNoPrecision": { "$numberDecimal": "0.0" } }, { "_id": 1, "encryptedDecimalNoPrecision": { "$numberDecimal": "1.0" } } ] } ] }, { "description": "Aggregate with $gt and $lt", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "local": { "key": { "$binary": { "base64": "Mng0NCt4ZHVUYUJCa1kxNkVyNUR1QURhZ2h2UzR2d2RrZzh0cFBwM3R6NmdWMDFBMUN3YkQ5aXRRMkhGRGdQV09wOGVNYUMxT2k3NjZKelhaQmRCZGJkTXVyZG9uSjFk", "subType": "00" } } } } } }, "operations": [ { "name": "insertOne", "arguments": { "document": { "_id": 0, "encryptedDecimalNoPrecision": { "$numberDecimal": "0.0" } } } }, { "name": "insertOne", "arguments": { "document": { "_id": 1, "encryptedDecimalNoPrecision": { "$numberDecimal": "1.0" } } } }, { "name": "aggregate", "arguments": { "pipeline": [ { "$match": { "encryptedDecimalNoPrecision": { "$gt": { "$numberDecimal": "0.0" }, "$lt": { "$numberDecimal": "2.0" } } } } ] }, "result": [ { "_id": 1, "encryptedDecimalNoPrecision": { "$numberDecimal": "1.0" } } ] } ] }, { "description": "Aggregate with equality", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "local": { "key": { "$binary": { "base64": "Mng0NCt4ZHVUYUJCa1kxNkVyNUR1QURhZ2h2UzR2d2RrZzh0cFBwM3R6NmdWMDFBMUN3YkQ5aXRRMkhGRGdQV09wOGVNYUMxT2k3NjZKelhaQmRCZGJkTXVyZG9uSjFk", "subType": "00" } } } } } }, "operations": [ { "name": "insertOne", "arguments": { "document": { "_id": 0, "encryptedDecimalNoPrecision": { "$numberDecimal": "0.0" } } } }, { "name": "insertOne", "arguments": { "document": { "_id": 1, "encryptedDecimalNoPrecision": { "$numberDecimal": "1.0" } } } }, { "name": "aggregate", "arguments": { "pipeline": [ { "$match": { "encryptedDecimalNoPrecision": { "$numberDecimal": "0.0" } } } ] }, "result": [ { "_id": 0, "encryptedDecimalNoPrecision": { "$numberDecimal": "0.0" } } ] }, { "name": "aggregate", "arguments": { "pipeline": [ { "$match": { "encryptedDecimalNoPrecision": { "$numberDecimal": "1.0" } } } ] }, "result": [ { "_id": 1, "encryptedDecimalNoPrecision": { "$numberDecimal": "1.0" } } ] } ] }, { "description": "Aggregate with $in", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "local": { "key": { "$binary": { "base64": "Mng0NCt4ZHVUYUJCa1kxNkVyNUR1QURhZ2h2UzR2d2RrZzh0cFBwM3R6NmdWMDFBMUN3YkQ5aXRRMkhGRGdQV09wOGVNYUMxT2k3NjZKelhaQmRCZGJkTXVyZG9uSjFk", "subType": "00" } } } } } }, "operations": [ { "name": "insertOne", "arguments": { "document": { "_id": 0, "encryptedDecimalNoPrecision": { "$numberDecimal": "0.0" } } } }, { "name": "insertOne", "arguments": { "document": { "_id": 1, "encryptedDecimalNoPrecision": { "$numberDecimal": "1.0" } } } }, { "name": "aggregate", "arguments": { "pipeline": [ { "$match": { "encryptedDecimalNoPrecision": { "$in": [ { "$numberDecimal": "0.0" } ] } } } ] }, "result": [ { "_id": 0, "encryptedDecimalNoPrecision": { "$numberDecimal": "0.0" } } ] } ] }, { "description": "Wrong type: Insert Int", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "local": { "key": { "$binary": { "base64": "Mng0NCt4ZHVUYUJCa1kxNkVyNUR1QURhZ2h2UzR2d2RrZzh0cFBwM3R6NmdWMDFBMUN3YkQ5aXRRMkhGRGdQV09wOGVNYUMxT2k3NjZKelhaQmRCZGJkTXVyZG9uSjFk", "subType": "00" } } } } } }, "operations": [ { "name": "insertOne", "arguments": { "document": { "_id": 0, "encryptedDecimalNoPrecision": { "$numberInt": "0" } } }, "result": { "errorContains": "cannot encrypt element" } } ] }, { "description": "Wrong type: Find Int", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "local": { "key": { "$binary": { "base64": "Mng0NCt4ZHVUYUJCa1kxNkVyNUR1QURhZ2h2UzR2d2RrZzh0cFBwM3R6NmdWMDFBMUN3YkQ5aXRRMkhGRGdQV09wOGVNYUMxT2k3NjZKelhaQmRCZGJkTXVyZG9uSjFk", "subType": "00" } } } } } }, "operations": [ { "name": "find", "arguments": { "filter": { "encryptedDecimalNoPrecision": { "$gte": { "$numberInt": "0" } } }, "sort": { "_id": 1 } }, "result": { "errorContains": "field type is not supported" } } ] } ] } fle2v2-Range-Decimal-Delete.json000066400000000000000000002067301462766011000347140ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/client-side-encryption/spec/legacy{ "runOn": [ { "minServerVersion": "7.0.0", "topology": [ "replicaset" ] } ], "database_name": "default", "collection_name": "default", "data": [], "encrypted_fields": { "fields": [ { "keyId": { "$binary": { "base64": "EjRWeBI0mHYSNBI0VniQEg==", "subType": "04" } }, "path": "encryptedDecimalNoPrecision", "bsonType": "decimal", "queries": { "queryType": "rangePreview", "contention": { "$numberLong": "0" }, "sparsity": { "$numberLong": "1" } } } ] }, "key_vault_data": [ { "_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" } } ], "tests": [ { "description": "FLE2 Range Decimal. Delete.", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "local": { "key": { "$binary": { "base64": "Mng0NCt4ZHVUYUJCa1kxNkVyNUR1QURhZ2h2UzR2d2RrZzh0cFBwM3R6NmdWMDFBMUN3YkQ5aXRRMkhGRGdQV09wOGVNYUMxT2k3NjZKelhaQmRCZGJkTXVyZG9uSjFk", "subType": "00" } } } } } }, "operations": [ { "name": "insertOne", "arguments": { "document": { "_id": 0, "encryptedDecimalNoPrecision": { "$numberDecimal": "0" } } } }, { "name": "insertOne", "arguments": { "document": { "_id": 1, "encryptedDecimalNoPrecision": { "$numberDecimal": "1" } } } }, { "name": "deleteOne", "arguments": { "filter": { "encryptedDecimalNoPrecision": { "$gt": { "$numberDecimal": "0" } } } }, "result": { "deletedCount": 1 } } ], "expectations": [ { "command_started_event": { "command": { "listCollections": 1, "filter": { "name": "default" } }, "command_name": "listCollections" } }, { "command_started_event": { "command": { "find": "datakeys", "filter": { "$or": [ { "_id": { "$in": [ { "$binary": { "base64": "EjRWeBI0mHYSNBI0VniQEg==", "subType": "04" } } ] } }, { "keyAltNames": { "$in": [] } } ] }, "$db": "keyvault", "readConcern": { "level": "majority" } }, "command_name": "find" } }, { "command_started_event": { "command": { "insert": "default", "documents": [ { "_id": 0, "encryptedDecimalNoPrecision": { "$$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": "encryptedDecimalNoPrecision", "bsonType": "decimal", "queries": { "queryType": "rangePreview", "contention": { "$numberLong": "0" }, "sparsity": { "$numberLong": "1" } } } ] } } } }, "command_name": "insert" } }, { "command_started_event": { "command": { "insert": "default", "documents": [ { "_id": 1, "encryptedDecimalNoPrecision": { "$$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": "encryptedDecimalNoPrecision", "bsonType": "decimal", "queries": { "queryType": "rangePreview", "contention": { "$numberLong": "0" }, "sparsity": { "$numberLong": "1" } } } ] } } } }, "command_name": "insert" } }, { "command_started_event": { "command": { "delete": "default", "deletes": [ { "q": { "encryptedDecimalNoPrecision": { "$gt": { "$binary": { "base64": "DeFiAAADcGF5bG9hZACxYgAABGcAnWIAAAMwAH0AAAAFZAAgAAAAAJu2KgiI8vM+kz9qD3ZQzFQY5qbgYqCqHG5R4jAlnlwXBXMAIAAAAAAAUXxFXsz764T79sGCdhxvNd5b6E/9p61FonsHyEIhogVsACAAAAAAt19RL3Oo5ni5L8kcvgOJYLgVYyXJExwP8pkuzLG7f/kAAzEAfQAAAAVkACAAAAAAPQPvL0ARjujSv2Rkm8r7spVsgeC1K3FWcskGGZ3OdDIFcwAgAAAAACgNn660GmefR8jLqzgR1u5O+Uocx9GyEHiBqVGko5FZBWwAIAAAAADflr+fsnZngm6KRWYgHa9JzK+bXogWl9evBU9sQUHPHQADMgB9AAAABWQAIAAAAAD2Zi6kcxmaD2mY3VWrP+wYJMPg6cSBIYPapxaFQxYFdQVzACAAAAAAM/cV36BLBY3xFBXsXJY8M9EHHOc/qrmdc2CJmj3M89gFbAAgAAAAAOpydOrKxx6m2gquSDV2Vv3w10GocmNCFeOo/fRhRH9JAAMzAH0AAAAFZAAgAAAAAOaNqI9srQ/mI9gwbk+VkizGBBH/PPWOVusgnfPk3tY1BXMAIAAAAAAc96O/pwKCmHCagT6T/QV/wz4vqO+R22GsZ1dse2Vg6QVsACAAAAAAgzIak+Q3UFLTHXPmJ+MuEklFtR3eLtvM+jdKkmGCV/YAAzQAfQAAAAVkACAAAAAA0XlQgy/Yu97EQOjronl9b3dcR1DFn3deuVhtTLbJZHkFcwAgAAAAACoMnpVl6EFJak8A+t5N4RFnQhkQEBnNAx8wDqmq5U/dBWwAIAAAAACR26FJif673qpwF1J1FEkQGJ1Ywcr/ZW6JQ7meGqzt1QADNQB9AAAABWQAIAAAAAAOtpNexRxfv0yRFvZO9DhlkpU4mDuAb8ykdLnE5Vf1VAVzACAAAAAAeblFKm/30orP16uQpZslvsoS8s0xfNPIBlw3VkHeekYFbAAgAAAAAPEoHj87sYE+nBut52/LPvleWQBzB/uaJFnosxp4NRO2AAM2AH0AAAAFZAAgAAAAAIr8xAFm1zPmrvW4Vy5Ct0W8FxMmyPmFzdWVzesBhAJFBXMAIAAAAABYeeXjJEzTHwxab6pUiCRiZjxgtN59a1y8Szy3hfkg+gVsACAAAAAAJuoY4rF8mbI+nKb+5XbZShJ8191o/e8ZCRHE0O4Ey8MAAzcAfQAAAAVkACAAAAAAl+ibLk0/+EwoqeC8S8cGgAtjtpQWGEZDsybMPnrrkwEFcwAgAAAAAHPPBudWgQ+HUorLDpJMqhS9VBF2VF5aLcxgrM1s+yU7BWwAIAAAAAAcCcBR2Vyv5pAFbaOU97yovuOi1+ATDnLLcAUqHecXcAADOAB9AAAABWQAIAAAAACR9erwLTb+tcWFZgJ2MEfM0PKI9uuwIjDTHADRFgD+SQVzACAAAAAAcOop8TXsGUVQoKhzUllMYWxL93xCOkwtIpV8Q6hiSYYFbAAgAAAAAKXKmh4V8veYwob1H03Q3p3PN8SRAaQwDT34KlNVUjiDAAM5AH0AAAAFZAAgAAAAALv0vCPgh7QpmM8Ug6ad5ioZJCh7pLMdT8FYyQioBQ6KBXMAIAAAAADsCPyIG8t6ApQkRk1fX/sfc1kpuWCWP8gAEpnYoBSHrQVsACAAAAAAJe/r67N6d8uTiogvfoR9rEXbIDjyLb9EVdqkayFFGaYAAzEwAH0AAAAFZAAgAAAAAIW4AxJgYoM0pcNTwk1RSbyjZGIqgKL1hcTJmNrnZmoPBXMAIAAAAAAZpfx3EFO0vY0f1eHnE0PazgqeNDTaj+pPJMUNW8lFrAVsACAAAAAAP+Um2vwW6Bj6vuz9DKz6+6aWkoKoEmFNoiz/xXm7lOsAAzExAH0AAAAFZAAgAAAAAKliO6L9zgeuufjj174hvmQGNRbmYYs9yAirL7OxwEW3BXMAIAAAAAAqU7vs3DWUQ95Eq8OejwWnD0GuXd+ASi/uD6S0l8MM1QVsACAAAAAAb9legYzsfctBPpHyl7YWpPmLr5QiNZFND/50N1vv2MUAAzEyAH0AAAAFZAAgAAAAAOGQcCBkk+j/Kzjt/Cs6g3BZPJG81wIHBS8JewHGpgk+BXMAIAAAAABjrxZXWCkdzrExwCgyHaafuPSQ4V4x2k9kUCAqUaYKDQVsACAAAAAADBU6KefT0v8zSmseaMNmQxKjJar72y7MojLFhkEHqrUAAzEzAH0AAAAFZAAgAAAAAPmCNEt4t97waOSd5hNi2fNCdWEkmcFJ37LI9k4Az4/5BXMAIAAAAABX7DuDPNg+duvELf3NbLWkPMFw2HGLgWGHyVWcPvSNCAVsACAAAAAAS7El1FtZ5STh8Q1FguvieyYX9b2DF1DFVsb9hzxXYRsAAzE0AH0AAAAFZAAgAAAAAD4vtVUYRNB+FD9yoQ2FVJH3nMeJeKbi6eZfth638YqbBXMAIAAAAAANCuUB4OdmuD6LaDK2f3vaqfgYYvg40wDXOBbcFjTqLwVsACAAAAAA9hqC2VoJBjwR7hcQ45xO8ZVojwC83jiRacCaDj6Px2gAAzE1AH0AAAAFZAAgAAAAAJPIRzjmTjbdIvshG6UslbEOd797ZSIdjGAhGWxVQvK1BXMAIAAAAABgmJ0Jh8WLs9IYs/a7DBjDWd8J3thW/AGJK7zDnMeYOAVsACAAAAAAi9zAsyAuou2oiCUHGc6QefLUkACa9IgeBhGu9W/r0X8AAzE2AH0AAAAFZAAgAAAAAABQyKQPoW8wGPIqnsTv69+DzIdRkohRhOhDmyVHkw9WBXMAIAAAAAAqWA2X4tB/h3O1Xlawtz6ndI6WaTwgU1QYflL35opu5gVsACAAAAAAWI/Gj5aZMwDIxztqmVL0g5LBcI8EdKEc2UA28pnekQoAAzE3AH0AAAAFZAAgAAAAACB7NOyGQ1Id3MYnxtBXqyZ5Ul/lHH6p1b10U63DfT6bBXMAIAAAAADpOryIcndxztkHSfLN3Kzq29sD8djS0PspDSqERMqokQVsACAAAAAADatsMW4ezgnyi1PiP7xk+gA4AFIN/fb5uJqfVkjg4UoAAzE4AH0AAAAFZAAgAAAAAKVfXLfs8XA14CRTB56oZwV+bFJN5BHraTXbqEXZDmTkBXMAIAAAAAASRWTsfGOpqdffiOodoqIgBzG/yzFyjR5CfUsIUIWGpgVsACAAAAAAkgCHbCwyX640/0Ni8+MoYxeHUiC+FSU4Mn9jTLYtgZgAAzE5AH0AAAAFZAAgAAAAAH/aZr4EuS0/noQR9rcF8vwoaxnxrwgOsSJ0ys8PkHhGBXMAIAAAAACd7ObGQW7qfddcvyxRTkPuvq/PHu7+6I5dxwS1Lzy5XAVsACAAAAAA3q0eKdV7KeU3pc+CtfypKR7BPxwaf30yu0j9FXeOOboAAzIwAH0AAAAFZAAgAAAAAKvlcpFFNq0oA+urq3w6d80PK1HHHw0H0yVWvU9aHijXBXMAIAAAAADWnAHQ5Fhlcjawki7kWzdqjM2f6IdGJblojrYElWjsZgVsACAAAAAAO0wvY66l24gx8nRxyVGC0QcTztIi81Kx3ndRhuZr6W4AAzIxAH0AAAAFZAAgAAAAAH/2aMezEOddrq+dNOkDrdqf13h2ttOnexZsJxG1G6PNBXMAIAAAAABNtgnibjC4VKy5poYjvdsBBnVvDTF/4mmEAxsXVgZVKgVsACAAAAAAqvadzJFLqQbs8WxgZ2D2X+XnaPSDMLCVVgWxx5jnLcYAAzIyAH0AAAAFZAAgAAAAAF2wZoDL6/V59QqO8vdRZWDpXpkV4h4KOCSn5e7x7nmzBXMAIAAAAADLZBu7LCYjbThaVUqMK14H/elrVOYIKJQCx4C9Yjw37gVsACAAAAAAEh6Vs81jLU204aGpL90fmYTm5i5R8/RT1uIbg6VU3HwAAzIzAH0AAAAFZAAgAAAAAH27yYaLn9zh2CpvaoomUPercSfJRUmBY6XFqmhcXi9QBXMAIAAAAAAUwumVlIYIs9JhDhSj0R0+59psCMsFk94E62VxkPt42QVsACAAAAAAT5x2hCCd2bpmpnyWaxas8nSxTc8e4C9DfKaqr0ABEysAAzI0AH0AAAAFZAAgAAAAALMg2kNAO4AFFs/mW3In04yFeN4AP6Vo0klyUoT06RquBXMAIAAAAAAgGWJbeIdwlpqXCyVIYSs0dt54Rfc8JF4b8uYc+YUj0AVsACAAAAAAWHeWxIkyvXTOWvfZzqtPXjfGaWWKjGSIQENTU3zBCrsAAzI1AH0AAAAFZAAgAAAAALas/i1T2DFCEmrrLEi7O2ngJZyFHialOoedVXS+OjenBXMAIAAAAAA1kK0QxY4REcGxHeMkgumyF7iwlsRFtw9MlbSSoQY7uAVsACAAAAAAUNlpMJZs1p4HfsD4Q4WZ4TBEi6Oc2fX34rzyynqWCdwAAzI2AH0AAAAFZAAgAAAAAP1TejmWg1CEuNSMt6NUgeQ5lT+oBoeyF7d2l5xQrbXWBXMAIAAAAABPX0kj6obggdJShmqtVfueKHplH4ZrXusiwrRDHMOKeQVsACAAAAAAIYOsNwC3DA7fLcOzqdr0bOFdHCfmK8tLwPoaE9uKOosAAzI3AH0AAAAFZAAgAAAAAMrKn+QPa/NxYezNhlOX9nyEkN1kE/gW7EuZkVqYl0b8BXMAIAAAAABUoZMSPUywRGfX2EEencJEKH5x/P9ySUVrhStAwgR/LgVsACAAAAAAMgZFH6lQIIDrgHnFeslv3ld20ynwQjQJt3cAp4GgrFkAAzI4AH0AAAAFZAAgAAAAAMmD1+a+oVbiUZd1HuZqdgtdVsVKwuWAn3/M1B6QGBM3BXMAIAAAAACLyytOYuZ9WEsIrrtJbXUx4QgipbaAbmlJvSZVkGi0CAVsACAAAAAA4v1lSp5H9BB+HYJ4bH43tC8aeuPZMf78Ng1JOhJh190AAzI5AH0AAAAFZAAgAAAAAOVKV7IuFwmYP1qVv8h0NvJmfPICu8yQhzjG7oJdTLDoBXMAIAAAAABL70XLfQLKRsw1deJ2MUvxSWKxpF/Ez73jqtbLvqbuogVsACAAAAAAvfgzIorXxE91dDt4nQxYfntTsx0M8Gzdsao5naQqcRUAAzMwAH0AAAAFZAAgAAAAAKS/1RSAQma+xV9rz04IcdzmavtrBDjOKPM+Z2NEyYfPBXMAIAAAAAAOJDWGORDgfRv8+w5nunh41wXb2hCA0MRzwnLnQtIqPgVsACAAAAAAf42C1+T7xdHEFF83+c2mF5S8PuuL22ogXXELnRAZ4boAAzMxAH0AAAAFZAAgAAAAAFeq8o82uNY1X8cH6OhdTzHNBUnCChsEDs5tm0kPBz3qBXMAIAAAAABaxMBbsaeEj/EDtr8nZfrhhhirBRPJwVamDo5WwbgvTQVsACAAAAAAMbH453A+BYAaDOTo5kdhV1VdND1avNwvshEG/4MIJjQAAzMyAH0AAAAFZAAgAAAAAI8IKIfDrohHh2cjspJHCovqroSr5N3QyVtNzFvT5+FzBXMAIAAAAABXHXteKG0DoOMmECKp6ro1MZNQvXGzqTDdZ0DUc8QfFAVsACAAAAAA/w5s++XYmO+9TWTbtGc3n3ndV4T9JUribIbF4jmDLSMAAzMzAH0AAAAFZAAgAAAAAJkHvm15kIu1OtAiaByj5ieWqzxiu/epK6c/9+KYIrB0BXMAIAAAAACzg5TcyANk0nes/wCJudd1BwlkWWF6zw3nGclq5v3SJQVsACAAAAAAvruXHTT3irPJLyWpI1j/Xwf2FeIE/IV+6Z49pqRzISoAAzM0AH0AAAAFZAAgAAAAAAYSOvEWWuSg1Aym7EssNLR+xsY7e9BcwsX4JKlnSHJcBXMAIAAAAABT48eY3PXVDOjw7JpNjOe1j2JyI3LjDnQoqZ8Je5B2KgVsACAAAAAAU2815RR57TQ9uDg0XjWjBkAKvf8yssxDMzrM4+FqP6AAAzM1AH0AAAAFZAAgAAAAAGQxC9L1e9DfO5XZvX1yvc3hTLtQEdKO9FPMkyg0Y9ZABXMAIAAAAADtmcMNJwdWLxQEArMGZQyzpnu+Z5yMmPAkvgq4eAKwNQVsACAAAAAAJ88zt4Y/Hoqh+zrf6KCOiUwHbOzCxSfp6k/qsZaYGEgAAzM2AH0AAAAFZAAgAAAAADLHK2LNCNRO0pv8n4fAsxwtUqCNnVK8rRgNiQfXpHSdBXMAIAAAAACf16EBIHRKD3SzjRW+LMOl+47QXA3CJhMzlcqyFRW22AVsACAAAAAAMGz4fAOa0EoVv90fUffwLjBrQhHATf+NdlgCR65vujAAAzM3AH0AAAAFZAAgAAAAAHiZJiXKNF8bbukQGsdYkEi95I+FSBHy1I5/hK2uEZruBXMAIAAAAADE+lZBa8HDUJPN+bF6xI9x4N7GF9pj3vBR7y0BcfFhBAVsACAAAAAAGIEN6sfqq30nyxW4dxDgXr/jz5HmvA9T1jx/pKCn4zgAAzM4AH0AAAAFZAAgAAAAAI1oa2OIw5TvhT14tYCGmhanUoYcCZtNbrVbeoMldHNZBXMAIAAAAAAx2nS0Ipblf2XOgBiUOuJFBupBhe7nb6QPLZlA4aMPCgVsACAAAAAA9xu828hugIgo0E3de9dZD+gTpVUGlwtDba+tw/WcbUoAAzM5AH0AAAAFZAAgAAAAABgTWS3Yap7Q59hii/uPPimHWXsr+DUmsqfwt/X73qsOBXMAIAAAAACKK05liW5KrmEAvtpCB1WUltruzUylDDpjea//UlWoOAVsACAAAAAAcgN4P/wakJ5aJK5c1bvJBqpVGND221dli2YicPFfuAYAAzQwAH0AAAAFZAAgAAAAABOAnBPXDp6i9TISQXvcNKwGDLepZTu3cKrB4vKnSCjBBXMAIAAAAADjjzZO7UowAAvpwyG8BNOVqLCccMFk3aDK4unUeft5ywVsACAAAAAA4zkCd4k9gvfXoD1C7vwTjNcdVJwEARh8h/cxZ4PNMfgAAzQxAH0AAAAFZAAgAAAAAHN8hyvT1lYrAsdiV5GBdd5jhtrAYE/KnSjw2Ka9hjz9BXMAIAAAAAD794JK7EeXBs+D7yOVK7nWF8SbZ/7U8gZ7nnT9JFNwTAVsACAAAAAAg8Wt1HO3NhByq2ggux2a4Lo6Gryr24rEFIqh2acrwWMAAzQyAH0AAAAFZAAgAAAAAO93bPrq8bsnp1AtNd9ETnXIz0lH/2HYN/vuw9wA3fyFBXMAIAAAAABHlls5fbaF2oAGqptC481XQ4eYxInTC29aElfmVZgDUgVsACAAAAAANoQXEWpXJpgrSNK/cKi/m7oYhuSRlp1IZBF0bqTEATcAAzQzAH0AAAAFZAAgAAAAAL1YsAZm1SA0ztU6ySIrQgCCA74V6rr0/4iIygCcaJL6BXMAIAAAAADTXWTHWovGmUR1Zg9l/Aqq9H5mOCJQQrb/Dfae7e3wKAVsACAAAAAA5dunyJK6/SVfDD0t9QlNBcFqoZnf9legRjHaLSKAoQMAAzQ0AH0AAAAFZAAgAAAAAEoFAeHk0RZ9kD+cJRD3j7PcE5gzWKnyBrF1I/MDNp5mBXMAIAAAAACgHtc2hMBRSZjKw8RAdDHK+Pi1HeyjiBuAslGVNcW5tAVsACAAAAAAXzBLfq+GxRtX4Wa9fazA49DBLG6AjZm2XODStJKH8D0AAzQ1AH0AAAAFZAAgAAAAAAW+7DmSN/LX+/0uBVJDHIc2dhxAGz4+ehyyz8fAnNGoBXMAIAAAAAA6Ilw42EvvfLJ3Eq8Afd+FjPoPcQutZO6ltmCLEr8kxQVsACAAAAAAbbZalyo07BbFjPFlYmbmv0z023eT9eLkHqeVUnfUAUAAAzQ2AH0AAAAFZAAgAAAAANBdV7M7kuYO3EMoQItAbXv4t2cIhfaT9V6+s4cg9djlBXMAIAAAAABvz4MIvZWxxrcJCL5qxLfFhXiUYB1OLHdKEjco94SgDgVsACAAAAAAK2GVGvyPIKolF/ECcmfmkVcf1/IZNcaTv96N92yGrkEAAzQ3AH0AAAAFZAAgAAAAAMoAoiAn1kc79j5oPZtlMWHMhhgwNhLUnvqkqIFvcH1NBXMAIAAAAADcJTW7WiCyW0Z9YDUYwppXhLj4Ac1povpJvcAq+i48MQVsACAAAAAAIGxGDzoeB3PTmudl4+j6piQB++e33EEzuzAiXcqGxvUAAzQ4AH0AAAAFZAAgAAAAACI3j5QP7dWHpcT6WO/OhsWwRJNASBYqIBDNzW8IorEyBXMAIAAAAABxUpBSjXwCKDdGP9hYU+RvyR+96kChfvyyRC4jZmztqAVsACAAAAAAvBCHguWswb4X0xdcAryCvZgQuthXzt7597bJ5VxAMdgAAzQ5AH0AAAAFZAAgAAAAAKsbycEuQSeNrF8Qnxqw3x3og8JmQabwGqnDbqzFRVrrBXMAIAAAAACno/3ef2JZJS93SVVzmOZSN+jjJHT8s0XYq2M46d2sLAVsACAAAAAAAt5zLJG+/j4K8rnkFtAn8IvdUVNefe6utJ3rdzgwudIAAzUwAH0AAAAFZAAgAAAAAPXIcoO8TiULqlxzb74NFg+I8kWX5uXIDUPnh2DobIoMBXMAIAAAAADR6/drkdTpnr9g1XNvKDwtBRBdKn7c2c4ZNUVK5CThdQVsACAAAAAAJqOA1c6KVog3F4Hb/GfDb3jCxXDRTqpXWSbMH4ePIJsAAzUxAH0AAAAFZAAgAAAAAEa03ZOJmfHT6/nVadvIw71jVxEuIloyvxXraYEW7u7pBXMAIAAAAADzRlBJK75FLiKjz3djqcgjCLo/e3yntI3MnPS48OORhgVsACAAAAAAnQhx4Rnyj081XrLRLD5NLpWmRWCsd0M9Hl7Jl19R0h8AAzUyAH0AAAAFZAAgAAAAAKx8NLSZUU04pSSGmHa5fh2oLHsEN5mmNMNHL95/tuC9BXMAIAAAAAA59hcXVaN3MNdHoo11OcH1aPRzHCwpVjO9mGfMz4xh3QVsACAAAAAAYIPdjV2XbPj7dBeHPwnwhVU7zMuJ+xtMUW5mIOYtmdAAAzUzAH0AAAAFZAAgAAAAAHNKAUxUqBFNS9Ea9NgCZoXMWgwhP4x0/OvoaPRWMquXBXMAIAAAAABUZ551mnP4ZjX+PXU9ttomzuOpo427MVynpkyq+nsYCQVsACAAAAAALnVK5p2tTTeZEh1zYt4iqKIQT9Z0si//Hy1L85oF+5IAAzU0AH0AAAAFZAAgAAAAALfGXDlyDVcGaqtyHkLT0qpuRhJQLgCxtznazhFtuyn/BXMAIAAAAABipxlXDq14C62pXhwAeen5+syA+/C6bN4rtZYcO4zKwAVsACAAAAAAXUf0pzUq0NhLYagWDap4uEiwq5rLpcx29rWbt1NYMsMAAzU1AH0AAAAFZAAgAAAAANoEr8sheJjg4UCfBkuUzarU9NFoy1xwbXjs5ifVDeA9BXMAIAAAAABPoyTf6M+xeZVGES4aNzVlq7LgjqZXJ/QunjYVusGUEAVsACAAAAAA1hA2gMeZZPUNytk9K+lB1RCqWRudRr7GtadJlExJf8oAAzU2AH0AAAAFZAAgAAAAAKvDiK+xjlBe1uQ3SZTNQl2lClIIvpP/5CHwY6Kb3WlgBXMAIAAAAAANnxImq5MFbWaRBHdJp+yD09bVlcFtiFDYsy1eDZj+iQVsACAAAAAAWtsyO+FxMPSIezwsV1TJD8ZrXAdRnQM6DJ+f+1V3qEkAAzU3AH0AAAAFZAAgAAAAAF49IlFH9RmSUSvUQpEPUedEksrQUcjsOv44nMkwXhjzBXMAIAAAAADJtWGbk0bZzmk20obz+mNsp86UCu/nLLlbg7ppxYn7PgVsACAAAAAA3k0Tj/XgPQtcYijH8cIlQoe/VXf15q1nrZNmg7yWYEgAAzU4AH0AAAAFZAAgAAAAAOuSJyuvz50lp3BzXlFKnq62QkN2quNU1Gq1IDsnFoJCBXMAIAAAAAAqavH1d93XV3IzshWlMnzznucadBF0ND092/2ApI1AcAVsACAAAAAAzUrK4kpoKCmcpdZlZNI13fddjdoAseVe67jaX1LobIIAAzU5AH0AAAAFZAAgAAAAALtgC4Whb4ZdkCiI30zY6fwlsxSa7lEaOAU3SfUXr02XBXMAIAAAAACgdZ6U1ZVgUaZZwbIaCdlANpCw6TZV0bwg3DS1NC/mnAVsACAAAAAAzI49hdpp0PbO7S2KexISxC16sE73EUAEyuqUFAC/J48AAzYwAH0AAAAFZAAgAAAAAF6PfplcGp6vek1ThwenMHVkbZgrc/dHgdsgx1VdPqZ5BXMAIAAAAACha3qhWkqmuwJSEXPozDO8y1ZdRLyzt9Crt2vjGnT7AAVsACAAAAAA7nvcU59+LwxGupSF21jAeAE0x7JE94tjRkJfgM1yKU8AAzYxAH0AAAAFZAAgAAAAAKoLEhLvLjKc7lhOJfx+VrGJCx9tXlOSa9bxQzGR6rfbBXMAIAAAAAAIDK5wNnjRMBzET7x/KAMExL/zi1IumJM92XTgXfoPoAVsACAAAAAAFkUYWFwNr815dEdFqp+TiIozDcq5IBNVkyMoDjharDQAAzYyAH0AAAAFZAAgAAAAADoQv6lutRmh5scQFvIW6K5JBquLxszuygM1tzBiGknIBXMAIAAAAADAD+JjW7FoBQ76/rsECmmcL76bmyfXpUU/awqIsZdO+wVsACAAAAAAPFHdLw3jssmEXsgtvl/RBNaUCRA1kgSwsofG364VOvQAAzYzAH0AAAAFZAAgAAAAAJNHUGAgn56KekghO19d11nai3lAh0JAlWfeP+6w4lJBBXMAIAAAAAD9XGJlvz59msJvA6St9fKW9CG4JoHV61rlWWnkdBRLzwVsACAAAAAAxwP/X/InJJHmrjznvahIMgj6pQR30B62UtHCthSjrP0AAzY0AH0AAAAFZAAgAAAAAHgYoMGjEE6fAlAhICv0+doHcVX8CmMVxyq7+jlyGrvmBXMAIAAAAAC/5MQZgTHuIr/O5Z3mXPvqrom5JTQ8IeSpQGhO9sB+8gVsACAAAAAAuPSXVmJUAUpTQg/A9Bu1hYczZF58KEhVofakygbsvJQAAzY1AH0AAAAFZAAgAAAAANpIljbxHOM7pydY877gpRQvYY2TGK7igqgGsavqGPBABXMAIAAAAAAqHyEu9gpurPOulApPnr0x9wrygY/7mXe9rAC+tPK80wVsACAAAAAA7gkPzNsS3gCxdFBWbSW9tkBjoR5ib+saDvpGSB3A3ogAAzY2AH0AAAAFZAAgAAAAAGR+gEaZTeGNgG9BuM1bX2R9ed4FCxBA9F9QvdQDAjZwBXMAIAAAAABSkrYFQ6pf8MZ1flgmeIRkxaSh/Eep4Btdx4QYnGGnwAVsACAAAAAApRovMiV00hm/pEcT4XBsyPNw0eo8RLAX/fuabjdU+uwAAzY3AH0AAAAFZAAgAAAAAFNprhQ3ZwIcYbuzLolAT5n/vc14P9kUUQComDu6eFyKBXMAIAAAAAAcx9z9pk32YbPV/sfPZl9ALIEVsqoLXgqWLVK/tP+heAVsACAAAAAA/qxvuvJbAHwwhfrPVpmCFzNvg2cU/NXaWgqgYUZpgXwAAzY4AH0AAAAFZAAgAAAAADgyPqQdqQrgfmJjRFAILTHzXbdw5kpKyfeoEcy6YYG/BXMAIAAAAAAE+3XsBQ8VAxAkN81au+f3FDeCD/s7KoZD+fnM1MJSSAVsACAAAAAAhRnjrXecwV0yeCWKJ5J/x12Xx4qVJahsCEVHB/1U2rcAAzY5AH0AAAAFZAAgAAAAAI0CT7JNngTCTUSei1Arw7eHWCD0jumv2rb7imjWIlWABXMAIAAAAABSP8t6ya0SyCphXMwnru6ZUDXWElN0NfBvEOhDvW9bJQVsACAAAAAAGWeGmBNDRaMtvm7Rv+8TJ2sJ4WNXKcp3tqpv5Se9Ut4AAzcwAH0AAAAFZAAgAAAAAD/FIrGYFDjyYmVb7oTMVwweWP7A6F9LnyIuNO4MjBnXBXMAIAAAAACIZgJCQRZu7NhuNMyOqCn1tf+DfU1qm10TPCfj5JYV3wVsACAAAAAA5hmY4ptuNxULGf87SUFXQWGAONsL9U29duh8xqsHtxoAAzcxAH0AAAAFZAAgAAAAAHIkVuNDkSS1cHIThKc/O0r2/ubaABTOi8Q1r/dvBAsEBXMAIAAAAADdHYqchEiJLM340c3Q4vJABmmth3+MKzwLYlsG6GS7sQVsACAAAAAADa+KP/pdTiG22l+ZWd30P1iHjnBF4zSNRdFm0oEK82kAAzcyAH0AAAAFZAAgAAAAAJmoDILNhC6kn3masElfnjIjP1VjsjRavGk1gSUIjh1NBXMAIAAAAAD97Ilvp3XF8T6MmVVcxMPcdL80RgQ09UoC6PnoOvZ1IQVsACAAAAAA2RK3Xng6v8kpvfVW9tkVXjpE+BSnx9/+Fw85Evs+kUEAAzczAH0AAAAFZAAgAAAAAI5bm3YO0Xgf0VT+qjVTTfvckecM3Cwqj7DTKZXf8/NXBXMAIAAAAAD/m+h8fBhWaHm6Ykuz0WX1xL4Eme3ErLObyEVJf8NCywVsACAAAAAAfb1VZZCqs2ivYbRzX4p5CtaCkKW+g20Pr57FWXzEZi8AAzc0AH0AAAAFZAAgAAAAANqo4+p6qdtCzcB4BX1wQ6llU7eFBnuu4MtZwp4B6mDlBXMAIAAAAAAGiz+VaukMZ+6IH4jtn4KWWdKK4/W+O+gRioQDrfzpMgVsACAAAAAAG4YYkTp80EKo59mlHExDodRQFR7njhR5dmISwUJ6ukAAAzc1AH0AAAAFZAAgAAAAAPrFXmHP2Y4YAm7b/aqsdn/DPoDkv7B8egWkfe23XsM1BXMAIAAAAAAGhwpKAr7skeqHm3oseSbO7qKNhmYsuUrECBxJ5k+D2AVsACAAAAAAAqPQi9luYAu3GrFCEsVjd9z2zIDcp6SPTR2w6KQEr+IAAzc2AH0AAAAFZAAgAAAAABzjYxwAjXxXc0Uxv18rH8I3my0Aguow0kTwKyxbrm+cBXMAIAAAAADVbqJVr6IdokuhXkEtXF0C2gINLiAjMVN20lE20Vmp2QVsACAAAAAAD7K1Fx4gFaaizkIUrf+EGXQeG7QX1jadhGc6Ji471H8AAzc3AH0AAAAFZAAgAAAAAFMm2feF2fFCm/UC6AfIyepX/xJDSmnnolQIBnHcPmb5BXMAIAAAAABLI11kFrQoaNVZFmq/38aRNImPOjdJh0Lo6irI8M/AaAVsACAAAAAAOWul0oVqJ9CejD2RqphhTC98DJeRQy5EwbNerU2+4l8AAzc4AH0AAAAFZAAgAAAAAJvXB3KyNiNtQko4SSzo/9b2qmM2zU9CQTTDfLSBWMgRBXMAIAAAAAAvjuVP7KsLRDeqVqRziTKpBrjVyqKiIbO9Gw8Wl2wFTAVsACAAAAAADlE+oc1ins+paNcaOZJhBlKlObDJ4VQORWjFYocM4LgAAzc5AH0AAAAFZAAgAAAAAPGdcxDiid8z8XYnfdDivNMYVPgBKdGOUw6UStU+48CdBXMAIAAAAAARj6g1Ap0eEfuCZ4X2TsEw+Djrhto3fA5nLwPaY0vCTgVsACAAAAAAoHqiwGOUkBu8SX5U1yHho+UIFdSN2MdQN5s6bQ0EsJYAAzgwAH0AAAAFZAAgAAAAAP5rGPrYGt3aKob5f/ldP0qrW7bmWvqnKY4QwdDWz400BXMAIAAAAADTQkW2ymaaf/bhteOOGmSrIR97bAnJx+yN3yMj1bTeewVsACAAAAAADyQnHGH2gF4w4L8axUsSTf6Ubk7L5/eoFOJk12MtZAoAAzgxAH0AAAAFZAAgAAAAAAlz6wJze5UkIxKpJOZFGCOf3v2KByWyI6NB6JM9wNcBBXMAIAAAAABUC7P/neUIHHoZtq0jFVBHY75tSFYr1Y5S16YN5XxC1QVsACAAAAAAgvxRbXDisNnLY3pfsjDdnFLtkvYUC4lhA68eBXc7KAwAAzgyAH0AAAAFZAAgAAAAAFJ8AtHcjia/9Y5pLEc3qVgH5xKiXw12G9Kn2A1EY8McBXMAIAAAAAAxe7Bdw7eUSBk/oAawa7uicTEDgXLymRNhBy1LAxhDvwVsACAAAAAAxKPaIBKVx3jTA+R/el7P7AZ7efrmTGjJs3Hj/YdMddwAAzgzAH0AAAAFZAAgAAAAAO8uwQUaKFb6vqR3Sv3Wn4QAonC2exOC9lGG1juqP5DtBXMAIAAAAABZf1KyJgQg8/Rf5c02DgDK2aQu0rNCOvaL60ohDHyY+gVsACAAAAAAqyEjfKC8lYoIfoXYHUqHZPoaA6EK5BAZy5dxXZmay4kAAzg0AH0AAAAFZAAgAAAAAE8YtqyRsGCeiR6hhiyisR/hccmK4nZqIMzO4lUBmEFzBXMAIAAAAAC1UYOSKqAeG1UJiKjWFVskRhuFKpj9Ezy+lICZvFlN5AVsACAAAAAA6Ct9nNMKyRazn1OKnRKagm746CGu+jyhbL1qJnZxGi0AAzg1AH0AAAAFZAAgAAAAAPhCrMausDx1QUIEqp9rUdRKyM6a9AAx7jQ3ILIu8wNIBXMAIAAAAACmH8lotGCiF2q9VQxhsS+7LAZv79VUAsOUALaGxE/EpAVsACAAAAAAnc1xCKfdvbUEc8F7XZqlNn1C+hZTtC0I9I3LL06iaNkAAzg2AH0AAAAFZAAgAAAAAOBi/GAYFcstMSJPgp3VkMiuuUUCrZytvqYaU8dwm8v2BXMAIAAAAACEZSZVyD3pKzGlbdwlYmWQhHHTV5SnNLknl2Gw8IaUTQVsACAAAAAAfsLZsEDcWSuNsIo/TD1ReyQW75HPMgmuKZuWFOLKRLoAAzg3AH0AAAAFZAAgAAAAAIQuup+YGfH3mflzWopN8J1X8o8a0d9CSGIvrA5HOzraBXMAIAAAAADYvNLURXsC2ITMqK14LABQBI+hZZ5wNf24JMcKLW+84AVsACAAAAAACzfjbTBH7IwDU91OqLAz94RFkoqBOkzKAqQb55gT4/MAAzg4AH0AAAAFZAAgAAAAAKsh0ADyOnVocFrOrf6MpTrNvAj8iaiE923DPryu124gBXMAIAAAAADg24a8NVE1GyScc6tmnTbmu5ulzO+896fE92lN08MeswVsACAAAAAAaPxcOIxnU7But88/yadOuDJDMcCywwrRitaxMODT4msAAzg5AH0AAAAFZAAgAAAAAKkVC2Y6HtRmv72tDnPUSjJBvse7SxLqnr09/Uuj9sVVBXMAIAAAAABYNFUkH7ylPMN+Bc3HWX1e0flGYNbtJNCY9SltJCW/UAVsACAAAAAAZYK/f9H4OeihmpiFMH7Wm7uLvs2s92zNA8wyrNZTsuMAAzkwAH0AAAAFZAAgAAAAADDggcwcb/Yn1Kk39sOHsv7BO/MfP3m/AJzjGH506Wf9BXMAIAAAAAAYZIsdjICS0+BDyRUPnrSAZfPrwtuMaEDEn0/ijLNQmAVsACAAAAAAGPnYVvo2ulO9z4LGd/69NAklfIcZqZvFX2KK0s+FcTUAAzkxAH0AAAAFZAAgAAAAAEWY7dEUOJBgjOoWVht1wLehsWAzB3rSOBtLgTuM2HC8BXMAIAAAAAAAoswiHRROurjwUW8u8D5EUT+67yvrgpB/j6PzBDAfVwVsACAAAAAA6NhRTYFL/Sz4tao7vpPjLNgAJ0FX6P/IyMW65qT6YsMAAzkyAH0AAAAFZAAgAAAAAPZaapeAUUFPA7JTCMOWHJa9lnPFh0/gXfAPjA1ezm4ZBXMAIAAAAACmJvLY2nivw7/b3DOKH/X7bBXjJwoowqb1GtEFO3OYgAVsACAAAAAA/JcUoyKacCB1NfmH8vYqC1f7rd13KShrQqV2r9QBP44AAzkzAH0AAAAFZAAgAAAAAK00u6jadxCZAiA+fTsPVDsnW5p5LCr4+kZZZOTDuZlfBXMAIAAAAAAote4zTEYMDgaaQbAdN8Dzv93ljPLdGjJzvnRn3KXgtQVsACAAAAAAxXd9Mh6R3mnJy8m7UfqMKi6oD5DlZpkaOz6bEjMOdiwAAzk0AH0AAAAFZAAgAAAAAFbgabdyymiEVYYwtJSWa7lfl/oYuj/SukzJeDOR6wPVBXMAIAAAAADAFGFjS1vPbN6mQEhkDYTD6V2V23Ys9gUEUMGNvMPkaAVsACAAAAAAL/D5Sze/ZoEanZLK0IeEkhgVkxEjMWVCfmJaD3a8uNIAAzk1AH0AAAAFZAAgAAAAABNMR6UBv2E627CqLtQ/eDYx7OEwQ7JrR4mSHFa1N8tLBXMAIAAAAAAxH4gucI4UmNVB7625C6hFSVCuIpJO3lusJlPuL8H5EQVsACAAAAAAVLHNg0OUVqZ7WGOP53BkTap9FOw9dr1P4J8HxqFqU04AAzk2AH0AAAAFZAAgAAAAAG8cd6WBneNunlqrQ2EmNf35W7OGObGq9WL4ePX+LUDmBXMAIAAAAAAjJ2+sX87NSis9hBsgb1QprVRnO7Bf+GObCGoUqyPE4wVsACAAAAAAs9c9SM49/pWmyUQKslpt3RTMBNSRppfNO0JBvUqHPg0AAzk3AH0AAAAFZAAgAAAAAFWOUGkUpy8yf6gB3dio/aOfRKh7XuhvsUj48iESFJrGBXMAIAAAAAAY7sCDMcrUXvNuL6dO0m11WyijzXZvPIcOKob6IpC4PQVsACAAAAAAJOP+EHz6awDb1qK2bZQ3kTV7wsj5Daj/IGAWh4g7omAAAzk4AH0AAAAFZAAgAAAAAGUrIdKxOihwNmo6B+aG+Ag1qa0+iqdksHOjQj+Oy9bZBXMAIAAAAABwa5dbI2KmzBDNBTQBEkjZv4sPaeRkRNejcjdVymRFKQVsACAAAAAA4ml/nm0gJNTcJ4vuD+T2Qfq2fQZlibJp/j6MOGDrbHMAAzk5AH0AAAAFZAAgAAAAAOx89xV/hRk64/CkM9N2EMK6aldII0c8smdcsZ46NbP8BXMAIAAAAADBF6tfQ+7q9kTuLyuyrSnDgmrdmrXkdhl980i1KHuGHgVsACAAAAAACUqiFqHZdGbwAA+hN0YUE5zFg+H+dabIB4dj5/75W/YAAzEwMAB9AAAABWQAIAAAAADJDdC9aEFl4Y8J/awHbnXGHjfP+VXQilPHJg7ewaJI7AVzACAAAAAAE+tqRl6EcBMXvbr4GDiNIYObTsYpa1n6BJk9EjIJVicFbAAgAAAAAJVc+HYYqa0m1Hq6OiRX8c0iRnJYOt6AJAJoG0sG3GMSAAMxMDEAfQAAAAVkACAAAAAA3F9rjEKhpoHuTULVGgfUsGGwJs3bISrXkFP1v6KoQLgFcwAgAAAAAIBf0tXw96Z/Ds0XSIHX/zk3MzUR/7WZR/J6FpxRWChtBWwAIAAAAABWrjGlvKYuTS2s8L9rYy8Hf0juFGJfwQmxVIjkTmFIGQADMTAyAH0AAAAFZAAgAAAAAOYIYoWkX7dGuyKfi3XssUlc7u/gWzqrR9KMkikKVdmSBXMAIAAAAABVF2OYjRTGi9Tw8XCAwZWLpX35Yl271TlNWp6N/nROhAVsACAAAAAA0nWwYzXQ1+EkDvnGq+SMlq20z+j32Su+i/A95SggPb4AAzEwMwB9AAAABWQAIAAAAACMtPm12YtdEAvqu6Eji1yuRXnu1RJP6h0l7pH3lSH4MwVzACAAAAAAENyCFfyUAh1veQBGx+cxiB7Sasrj41jzCGflZkB5cRMFbAAgAAAAAKdI2LMqISr/T5vuJPg6ZRBm5fVi2aQCc4ra3A4+AjbDAAMxMDQAfQAAAAVkACAAAAAAvlI4lDcs6GB1cnm/Tzo014CXWqidCdyE5t2lknWQd4QFcwAgAAAAAD60SpNc4O2KT7J0llKdSpcX1/Xxs97N715a1HsTFkmBBWwAIAAAAABuuRkJWAH1CynggBt1/5sPh9PoGiqTlS24D/OE2uHXLQADMTA1AH0AAAAFZAAgAAAAAKl8zcHJRDjSjJeV/WvMxulW1zrTFtaeBy/aKKhadc6UBXMAIAAAAADBdWQl5SBIvtZZLIHszePwkO14W1mQ0izUk2Ov21cPNAVsACAAAAAAHErCYycpqiIcCZHdmPL1hi+ovLQk4TAvENpfLdTRamQAAzEwNgB9AAAABWQAIAAAAABb6LXDWqCp1beQgQjj8I3sRTtFhlrmiBi+h/+ikmrvugVzACAAAAAA9stpgTecT7uTyaGNs3K9Bp0A7R0QaIAOfscyMXHBPX8FbAAgAAAAAHUt+McyXrJ1H8SwnHNVO181Ki8vDAM1f7XI26mg95ZDAAMxMDcAfQAAAAVkACAAAAAA97NTT+81PhDhgptNtp4epzA0tP4iNb9j1AWkiiiKGM8FcwAgAAAAAKPbHg7ise16vxmdPCzksA/2Mn/qST0L9Xe8vnQugVkcBWwAIAAAAABB0EMXfvju4JU/mUH/OvxWbPEl9NJkcEp4iCbkXI41fAADMTA4AH0AAAAFZAAgAAAAAMqpayM2XotEFmm0gwQd9rIzApy0X+7HfOhNk6VU7F5lBXMAIAAAAACJR9+q5T9qFHXFNgGbZnPubG8rkO6cwWhzITQTmd6VgwVsACAAAAAAOZLQ6o7e4mVfDzbpQioa4d3RoTvqwgnbmc5Qh2wsZuoAAzEwOQB9AAAABWQAIAAAAADQnslvt6Hm2kJPmqsTVYQHE/wWeZ4bE1XSkt7TKy0r1gVzACAAAAAA8URTA4ZMrhHPvlp53TH6FDCzS+0+61qHm5XK6UiOrKEFbAAgAAAAAHQbgTCdZcbdA0avaTmZXUKnIS7Nwf1tNrcXDCw+PdBRAAMxMTAAfQAAAAVkACAAAAAAhujlgFPFczsdCGXtQ/002Ck8YWQHHzvWvUHrkbjv4rwFcwAgAAAAALbV0lLGcSGfE7mDM3n/fgEvi+ifjl7WZ5b3aqjDNvx9BWwAIAAAAACbceTZy8E3QA1pHmPN5kTlOx3EO8kJM5PUjTVftw1VpgADMTExAH0AAAAFZAAgAAAAABm/6pF96j26Jm7z5KkY1y33zcAEXLx2n0DwC03bs/ixBXMAIAAAAAD01OMvTZI/mqMgxIhA5nLs068mW+GKl3OW3ilf2D8+LgVsACAAAAAAaLvJDrqBESTNZSdcXsd+8GXPl8ZkUsGpeYuyYVv/kygAAzExMgB9AAAABWQAIAAAAACfw9/te4GkHZAapC9sDMHHHZgmlTrccyJDPFciOMSOcwVzACAAAAAAIIC1ZpHObvmMwUfqDRPl4C1aeuHwujM1G/yJbvybMNAFbAAgAAAAAAs9x1SnVpMfNv5Bm1aXGwHmbbI9keWa9HRD35XuCBK5AAMxMTMAfQAAAAVkACAAAAAAkxHJRbnShpPOylLoDdNShfILeA1hChKFQY9qQyZ5VmsFcwAgAAAAAKidrY+rC3hTY+YWu2a7fuMH2RD/XaiTIBW1hrxNCQOJBWwAIAAAAACW0kkqMIzIFMn7g+R0MI8l15fr3k/w/mHtY5n6SYTEwAADMTE0AH0AAAAFZAAgAAAAAByuYl8dBvfaZ0LO/81JW4hYypeNmvLMaxsIdvqMPrWoBXMAIAAAAABNddwobOUJzm9HOUD8BMZJqkNCUCqstHZkC76FIdNg9AVsACAAAAAAQQOkIQtkyNavqCnhQbNg3HfqrJdsAGaoxSJePJl1qXsAAzExNQB9AAAABWQAIAAAAABxMy7X5hf7AXGDz3Y/POu1ZpkMlNcSvSP92NOO/Gs7wAVzACAAAAAAHJshWo2T5wU2zvqCyJzcJQKQaHFHpCpMc9oWBXkpUPoFbAAgAAAAAGeiJKzlUXAvL0gOlW+Hz1mSa2HsV4RGmyLmCHlzbAkoAAMxMTYAfQAAAAVkACAAAAAAlqbslixl7Zw3bRlibZbe/WmKw23k8uKeIzPKYEtbIy0FcwAgAAAAAHEKwpUxkxOfef5HYvulXPmdbzTivwdwrSYIHDeNRcpcBWwAIAAAAADuPckac21Hrg/h0kt5ShJwVEZ9rx6SOHd2+HDjqxEWTQADMTE3AH0AAAAFZAAgAAAAAMXrXx0saZ+5gORmwM2FLuZG6iuO2YS+1IGPoAtDKoKBBXMAIAAAAADIQsxCr8CfFKaBcx8kIeSywnGh7JHjKRJ9vJd9x79y7wVsACAAAAAAcvBV+SykDYhmRFyVYwFYB9oBKBSHr55Jdz2cXeowsUQAAzExOAB9AAAABWQAIAAAAAAm83FA9yDUpwkbKTihe7m53u+DivS9BU2b4vQMtCVQ2AVzACAAAAAAz3m1UB/AbZPa4QSKFDnUgHaT78+6iGOFAtouiBorEgEFbAAgAAAAAIgbpyYtJj5513Z5XYqviH/HXG/5+mqR52iBbfqMmDtZAAMxMTkAfQAAAAVkACAAAAAAJRzYK0PUwr9RPG2/7yID0WgcTJPB2Xjccp5LAPDYunkFcwAgAAAAAIIh24h3DrltAzNFhF+MEmPrZtzr1PhCofhChZqfCW+jBWwAIAAAAAAzRNXtL5o9VXMk5D5ylI0odPDJDSZZry1wfN+TedH70gADMTIwAH0AAAAFZAAgAAAAAHSaHWs/dnmI9sc7nB50VB2Bzs0kHapMHCQdyVEYY30TBXMAIAAAAACkV22lhEjWv/9/DubfHBAcwJggKI5mIbSK5L2nyqloqQVsACAAAAAAS19m7DccQxgryOsBJ3GsCs37yfQqNi1G+S6fCXpEhn4AAzEyMQB9AAAABWQAIAAAAAAC/I4TQRtCl12YZmdGz17X4GqSQgfwCPgRBwdHmdwu+QVzACAAAAAAx8f3z2ut/RAZhleari4vCEE+tNIn4ikjoUwzitfQ588FbAAgAAAAAJci0w1ZB8W2spJQ+kMpod6HSCtSR2jrabOH+B0fj3A4AAMxMjIAfQAAAAVkACAAAAAADGB5yU2XT0fse/MPWgvBvZikVxrl5pf3S5K1hceKWooFcwAgAAAAAIxTmlLHMjNaVDEfJbXvRez0SEPWFREBJCT6qTHsrljoBWwAIAAAAAAlswzAl81+0DteibwHD+CG5mZJrfHXa9NnEFRtXybzzwADMTIzAH0AAAAFZAAgAAAAABmO7QD9vxWMmFjIHz13lyOeV6vHT6mYCsWxF7hb/yOjBXMAIAAAAACT9lmgkiqzuWG24afuzYiCeK9gmJqacmxAruIukd0xEAVsACAAAAAAZa0/FI/GkZR7CtX18Xg9Tn9zfxkD0UoaSt+pIO5t1t4AAzEyNAB9AAAABWQAIAAAAAAfPUoy7QyZKhIIURso+mkP9qr1izbjETqF5s22GwjCjAVzACAAAAAAvLMsIDQ/go4VUxeh50UHmsvMvfx51cwyONnRD2odvC0FbAAgAAAAAKMb+1CodEalAFnDrEL1Ndt8ztamZ+9134m9Kp3GQgd+AAMxMjUAfQAAAAVkACAAAAAAE3ZqUar0Bq2zWbARE0bAv98jBlK9UJ73/xcwdMWWlSkFcwAgAAAAAK4M+MmC+9sFiFsumMyJZQKxWmmJiuG9H7IzKw083xxkBWwAIAAAAAAqkAONzhvMhkyL1D/6h7QQxEkdhC3p2WjXH+VGq5qCqQADMTI2AH0AAAAFZAAgAAAAAMo8FJiOq63cAmyk2O7eI7GcbQh/1j4RrMTqly3rexftBXMAIAAAAADjVmpd0WiRGTw/gAqEgGolt2EI7Csv14vKdmYoMD0aAgVsACAAAAAA07XQBzBUQMNw7F2/YxJjZNuPVpHTTgbLd1oGk77+bygAAzEyNwB9AAAABWQAIAAAAACu5IGaIx7A3Jvly/kzlCsSA4s3iJwuIl8jEdRH0k93NwVzACAAAAAA9NRUyxYE+t0Xyosyt6vIfMFW/vBoYg6sR+jBNs4JAxIFbAAgAAAAAAzyZ91dx+0oMlOVAjRGiMrPySikY/U9eMEB4WJb3uWtAAMxMjgAfQAAAAVkACAAAAAALkRy0GJInXYLA+cgjs6Myb0a+Gu9hgXhHvhLNoGWfckFcwAgAAAAANbALyt9zCSvwnLaWCd2/y2eoB7qkWTvv1Ldu8r40JPuBWwAIAAAAAD4Fl5bV5sz4isIE9bX+lmAp+aAKaZgVYVZeVfrItkCZAADMTI5AH0AAAAFZAAgAAAAAGoUK/DSWhT8LZhszSUqDbTrp8cSA7rdqmADKL+MILtTBXMAIAAAAABHnEE9bVa6lvhfhEMkkV2kzSSxH/sMW/FIJuw3CzWs6wVsACAAAAAAanavcBdqZxgRGKvEK95wTmeL1K1CeDSXZsXUAs81uOgAAzEzMAB9AAAABWQAIAAAAAC922ZDQE3h2fQKibGMZ9hV0WNlmrPYYSdtaSyYxsWYqgVzACAAAAAAagMovciKK6WVjIc2cCj8nK5O/gVOFFVeVAJpRp89tmQFbAAgAAAAAKcTFfPQzaFiAtSFhqbN02sCE1BKWJSrRfGN5L6oZwzkAAMxMzEAfQAAAAVkACAAAAAAtK+JqX3K/z2txjAU15DgX4y90DS2YLfIJFolCOkJJJwFcwAgAAAAAMnR5V7gfX7MNqqUdL5AkWlkhyFXaBRVNej+Rcn8lrQkBWwAIAAAAAA2cDNRXZuiC241TGRvdFyctJnrNcdbZOP9zHio81tkngADMTMyAH0AAAAFZAAgAAAAAAeGrIMK/bac6kPczxbvRYqKMkcpeI2FjdMpD91FDWIvBXMAIAAAAAAix62z1LeS8yvSXCl5gHSIomjyx76fF3S1lp9k900hygVsACAAAAAAiYwzf2m71aWFD5ajcXyW2JX2EzQOkBroTGMg29nLPYIAAzEzMwB9AAAABWQAIAAAAACphf298InM0Us4HT8o1W1MGw0D/02vd7Jh+U0h7qaFaQVzACAAAAAAFXtk7YpqsOJxsqGWSIL+YcBE96G3Zz9D31gPqDW94y8FbAAgAAAAAAOrS1KVA94rjB1jZ1pPocpCeBG+B14RzWoHqVDpp7JbAAMxMzQAfQAAAAVkACAAAAAATLDS2cuDVM3yDMuWNgk2iGKBTzPpfJMbvxVOSY39ZfcFcwAgAAAAAPT5wRi2cLHIUflXzm6EQB/m7xdThP80ir1VV/JBBqvxBWwAIAAAAAB9lEtZS0aXCFbCtSbhnis27S5IPcfWGygHW8AHn3QqzwADMTM1AH0AAAAFZAAgAAAAAJNjExiZVX7jfFGfYpQu16qxLN0YPqVU/5CQ/Y67YSinBXMAIAAAAABMpm2+6KrkRUlXzQoMPHrQmIO6dkQz66tYdfTeA3dKqQVsACAAAAAAFXobHiMLvNZuEPr8jtewCX2J93EZG3JNeyVg92fue6YAAzEzNgB9AAAABWQAIAAAAABlFkYtLCx901X6QVVMkSn6Z7k30UF4xHaA0OZJJ9bdyQVzACAAAAAATez+F9GHcGzTp7jjv4feboUNb8JCkIp4EqcPFisnq7MFbAAgAAAAACE7JvOpBgMoZ7kRd4QbxIhxukPTUxXpzhjnBHiR7XoRAAMxMzcAfQAAAAVkACAAAAAA8NJKN0IxZnruhswGQkiruv8Ih0EMwDcSZx/Xasup9dkFcwAgAAAAAKaJZRxzA+Igeydvuk6cSwUHXcrmT4PjhuPu//FslpdnBWwAIAAAAAD53Rok1Vq/PMAnXmarqoHJ0PEyYUBmVESa9hIpCv/G9QADMTM4AH0AAAAFZAAgAAAAABHxHdEClz7hbSSgE58+dWLlSMJnoPz+jFxp4bB1GmLQBXMAIAAAAAD3nSvT6aGD+A110J/NwEfp0nPutlmuB5B+wA3CC3noGAVsACAAAAAA3Apjd+TapONB7k5wBVwTWgn8t+Sq2oyyU5/+as109RcAAzEzOQB9AAAABWQAIAAAAAC/o8qW/ifk3KuJ01VFkyNLgQafxB5/bGs2G5VyyVafOwVzACAAAAAA1bMqAFGDHSl6BYNLbxApvkAv2K1/oafywiX0MDz1dGUFbAAgAAAAAHJXLlId3edFoniLD/9K2A5973MeP2Ro31flDyqm3l5QAAMxNDAAfQAAAAVkACAAAAAAY2V8I1bz3a1AxTtmED6UhdhA09huFkuuEX8R+d/WDPUFcwAgAAAAAPTVoNRiI76tcRKqd+JBBVyy4+YcKST42p0QX2BtmQ2VBWwAIAAAAACcxt9hg14WqPNiDv1MkqVljM2e2KJEv53lA17LhV6ZigADMTQxAH0AAAAFZAAgAAAAAO2kSsW0WGN9AOtK4xK2SHrGhWiaAbMEKT4iZkRpaDN/BXMAIAAAAABKGzQcPM8LT2dwOggxoWjv/1imYWabbG/G4kBw8OWaxAVsACAAAAAAC9hLK1dScQTAqg+YAG3ObdPzg2Xet57HmOFpGmyUR9UAAzE0MgB9AAAABWQAIAAAAAAiCwzNEEaH/mDam68IdDftnhthyUFdb+ZCNSBQ91WlHQVzACAAAAAA7tHyHcxCzmbJeFYZyPm4mEgkTGKOvwY4MX82OvH0Jn8FbAAgAAAAAAb5IAbZ1hXCNegQ+S+C9i/Z8y6sS8KeU04V6hXa2ml6AAMxNDMAfQAAAAVkACAAAAAAGuCHVNJSuoVkpPOnS5s89GuA+BLi2IPBUr2Bg1sWEPIFcwAgAAAAAEl1gncS5/xO7bQ/KQSstRV3rOT2SW6nV92ZANeG2SR6BWwAIAAAAAA9LOcKmhek8F2wAh8yvT/vjp2gaouuO+Hmv10lwAeWPAADMTQ0AH0AAAAFZAAgAAAAAMfxz7gEaoCdPvXrubDhCZUS0ARLZc1svgbXgMDlVBPgBXMAIAAAAAB6a5dDA3fuT5Vz2KvAcbUEFX/+B7Nw2p1QqbPoQ5TTuAVsACAAAAAAcf/y75UOuI62A6vWH7bYr/5Jz+nirZVYK/81trN6XOQAAzE0NQB9AAAABWQAIAAAAACnYsqF/VzmjIImC9+dqrHO1TM6lJ6fRwM0mM6Wf6paOwVzACAAAAAA5tgZzch8uDCR1ky3SllVaKVpxAlbrhvlNDTazZZRZOAFbAAgAAAAALeGiLJS4z2zhgVpxzyPdRYyACP9QzQBOob34YrIZumCAAMxNDYAfQAAAAVkACAAAAAAEC0sIVmadtW4YMuRXH7RpAhXclsd+3bmqGXCMeaT014FcwAgAAAAABPpXh0uzpsJJB+IRUNajmMB9WGwswfpw5T9xk3Xj6ANBWwAIAAAAAAmf+NYh9TZ/QRu3w/GQz66n7DtfbJijN3G7KzeL8lstAADMTQ3AH0AAAAFZAAgAAAAABaIB3n49Xm9cOafSrQsE0WCcYp8rMIO/qVwIlMF5YLRBXMAIAAAAAC9EyWJV3xOu9bzgdJ/yX+ko7qLf1u3AxNMataW2C9EzQVsACAAAAAAvVbDkLxXx2DcMLifIQ3K0IIJcLcAG9DUrNfI6aoUjNcAAzE0OAB9AAAABWQAIAAAAAA5rZItA/cocRnngYqcJ3nBXQ+l688aKz3EQyLbYYunPAVzACAAAAAAwKyA+L7TgxztPClLrIMk2JXR+w7c04N3ZOqPgjvrIvsFbAAgAAAAACzvZ33h6aWEe8hmo+1f6OXJ72FY5hvWaUuha64ZV3KFAAMxNDkAfQAAAAVkACAAAAAA3htn7oHJ0YYpIrs+Mzyh85Ys67HwAdv5LQl1mCdoMWkFcwAgAAAAAEHjCtNNLenHuSIYux6ezAHsXDaj2DlTF67ToDhDDe6HBWwAIAAAAAD+P4H0sk9jOd+7vOANt2/1Ectb+4ZRGPE8GkHWNXW3MgADMTUwAH0AAAAFZAAgAAAAAEnt18Km/nqggfIJWxzTr9r3hnXNaueG6XO9A5G11LnGBXMAIAAAAAD7QxzGMN/ard5TfFLecE6uusMmXG2+RBsBR+/NCQHUwAVsACAAAAAAQEZ1ZZ8GC8rdbg7s87OM5Gr9qkTXS9+P5DuAZxj5Gl4AAzE1MQB9AAAABWQAIAAAAAAVAKK/GoY8AACu/hyMpO4hdLq6JnEyWNzkyci9sbaD/wVzACAAAAAA2HmeqpMlvvBpV2zQTYIRmsc4MFlfHRwLof0ycJgMg/MFbAAgAAAAACdltCeWi5E/q1Li1eXLChpM2D9QQSGLBZ82NklQSc0oAAMxNTIAfQAAAAVkACAAAAAAhHyq1GQC/GiMwpYjcsfkNxolJ10ARKjIjfkW1Wipzi0FcwAgAAAAAD/uaGWxTDq87F8XZ6CrFI+RNa8yMqfSZdqK00Kj833BBWwAIAAAAAD6aEdOO0CsQGagioOCvANPCEHSpJ8BSixlPBq5ERhB7AADMTUzAH0AAAAFZAAgAAAAABAJJxHoZD+MQBWqm9UM9Dd3z5ZohIZGWRaRVRsMptKQBXMAIAAAAADrE/ca+gqj/SH4oao4wE4qn2ovoTydzcMbDbrfnUs3zAVsACAAAAAAeNCIQN6hVnGJinytQRFGlQ2ocoprXNqpia+BSxzl+uwAAzE1NAB9AAAABWQAIAAAAAAv01wz7VG9mTepjXQi6Zma+7b/OVBaKVkWNbgDLr1mFgVzACAAAAAA0I5sxz8r6wkCp5Tgvr+iL4p6MxSOq5d3e1kZG+0b7NkFbAAgAAAAAIA32v6oGkAOS96HexGouNTex+tLahtx9QF2dgGClk6WAAMxNTUAfQAAAAVkACAAAAAAWXecRwxSon68xaa9THXnRDw5ZfzARKnvvjTjtbae6T0FcwAgAAAAAPh0UfUMEo7eILCMv2tiJQe1bF9qtXq7GJtC6H5Va4fIBWwAIAAAAADqFr1ThRrTXNgIOrJWScO9mk86Ufi95IDu5gi4vP+HWQADMTU2AH0AAAAFZAAgAAAAAEY5WL8/LpX36iAB1wlQrMO/xHVjoO9BePVzbUlBYo+bBXMAIAAAAABoKcpadDXUARedDvTmzUzWPe1jTuvD0z9oIcZmKuiSXwVsACAAAAAAJuJbwuaMrAFoI+jU/IYr+k4RzAqITrOjAd3HWCpJHqEAAzE1NwB9AAAABWQAIAAAAADnJnWqsfx0xqNnqfFGCxIplVu8mXjaHTViJT9+y2RuTgVzACAAAAAAWAaSCwIXDwdYxWf2NZTly/iKVfG/KDjHUcA1BokN5sMFbAAgAAAAAJVxavipE0H4/JQvhagdytXBZ8qGooeXpkbPQ1RfYMVHAAMxNTgAfQAAAAVkACAAAAAAsPG7LaIpJvcwqcbtfFUpIjj+vpNj70Zjaw3eV9T+QYsFcwAgAAAAAJQ71zi0NlCyY8ZQs3IasJ4gB1PmWx57HpnlCf3+hmhqBWwAIAAAAACD58TO6d+71GaOoS+r73rAxliAO9GMs4Uc8JbOTmC0OwADMTU5AH0AAAAFZAAgAAAAAAGiSqKaQDakMi1W87rFAhkogfRAevnwQ41onWNUJKtuBXMAIAAAAAASgiDpXfGh7E47KkOD8MAcX8+BnDShlnU5JAGdnPdqOAVsACAAAAAAI+2TTQIgbFq4Yr3lkzGwhG/tqChP7hRAx2W0fNaH6jcAAzE2MAB9AAAABWQAIAAAAAB7L4EnhjKA5xJD3ORhH2wOA1BvpnQ+7IjRYi+jjVEaJAVzACAAAAAAuhBIm0nL3FJnVJId+7CKDASEo+l2E89Z9/5aWSITK4AFbAAgAAAAALtSICOzQDfV9d+gZuYxpEj6cCeHnKTT+2G3ceP2H65kAAMxNjEAfQAAAAVkACAAAAAAaROn1NaDZFOGEWw724dsXBAm6bgmL5i0cki6QZQNrOoFcwAgAAAAANVT8R6UvhrAlyqYlxtmnvkR4uYK/hlvyQmBu/LP6/3ZBWwAIAAAAAD+aHNMP/X+jcRHyUtrCNkk1KfMtoD3GTmShS8pWGLt+AADMTYyAH0AAAAFZAAgAAAAADqSR5e0/Th59LrauDA7OnGD1Xr3H3NokfVxzDWOFaN7BXMAIAAAAACt30faNwTWRbvmykDpiDYUOCwA6QDbBBYBFWS7rdOB4AVsACAAAAAAF7SvnjjRk5v2flFOKaBAEDvjXaL1cpjsQLtK2fv9zdQAAzE2MwB9AAAABWQAIAAAAADmtb1ZgpZjSeodPG/hIVlsnS8hoRRwRbrTVx89VwL62AVzACAAAAAAi38e1g6sEyVfSDkzZbaZXGxKI/zKNbMasOl2LYoWrq8FbAAgAAAAAALACk0KcCDN/Kv8WuazY8ORtUGkOZ5Dsm0ys1oOppp/AAMxNjQAfQAAAAVkACAAAAAAf/f7AWVgBxoKjr7YsEQ4w/fqSvuQWV2HMiA3rQ7ur0sFcwAgAAAAADkkeJozP6FFhUdRIN74H4UhIHue+eVbOs1NvbdWYFQrBWwAIAAAAAB55FlHAkmTzAYj/TWrGkRJw2EhrVWUnZXDoMYjyfB/ZwADMTY1AH0AAAAFZAAgAAAAAI2WEOymtuFpdKi4ctanPLnlQud+yMKKb8p/nfKmIy56BXMAIAAAAADVKrJmhjr1rfF3p+T+tl7UFd1B7+BfJRk0e7a4im7ozgVsACAAAAAA5E7Ti3PnFiBQoCcb/DN7V1uM3Xd6VKiexPKntssFL7kAAzE2NgB9AAAABWQAIAAAAAAuHU9Qd79hjyvKOujGanSGDIQlxzsql8JytTZhEnPw+AVzACAAAAAAjF2gV/4+sOHVgDd/oR5wDi9zL7NGpGD+NsEpGXy/a4QFbAAgAAAAAJzMoyojYV6Ed/LpVN5zge93Odv3U7JgP7wxeRaJZGTdAAMxNjcAfQAAAAVkACAAAAAA7dQDkt3iyWYCT94d7yqUtPPwp4qkC0ddu+HFdHgVKEkFcwAgAAAAANuYvtvZBTEq4Rm9+5eb7VuFopowkrAuv86PGP8Q8/QvBWwAIAAAAACeqXoAOQOE4j0zRMlkVd8plaW0RX1npsFvB38Xmzv7sAADMTY4AH0AAAAFZAAgAAAAAAwnZSDhL4tNGYxlHPhKYB8s28dY5ScSwiKZm3UhT8U3BXMAIAAAAABDoY6dhivufTURQExyC9Gx3ocpl09bgbbQLChj3qVGbgVsACAAAAAAF+1nS7O0v85s3CCy+9HkdeoEfm2C6ZiNbPMMnSfsMHUAAzE2OQB9AAAABWQAIAAAAAC2VuRdaC4ZJmLdNOvD6R2tnvkyARteqXouJmI46V306QVzACAAAAAAMn1Z6B35wFTX9mEYAPM+IiJ5hauEwfD0CyIvBrxHg7IFbAAgAAAAAOG6DvDZkT9B/xZWmjao2AevN7MMbs3Oh9YJeSd/hZ+hAAMxNzAAfQAAAAVkACAAAAAAVerb7qVNy457rNOHOgDSKyWl5ojun7iWrv1uHPXrIZQFcwAgAAAAAIDcYS9j5z+gx0xdJj09L7876r/vjvKTi/d3bXDE3PhyBWwAIAAAAADuhVLqb1Bkrx8aNymS+bx2cL8GvLFNH4SAi690DUgnWQADMTcxAH0AAAAFZAAgAAAAAH/E44yLxKCJjuSmU9A8SEhbmkDOx1PqqtYcZtgOzJdrBXMAIAAAAABgLh9v2HjBbogrRoQ82LS6KjZQnzjxyJH4PH+F3jupSAVsACAAAAAAIlO46ehXp4TqpDV0t6op++KO+uWBFh8iFORZjmx2IjkAAzE3MgB9AAAABWQAIAAAAAAlNUdDL+f/SSQ5074mrq0JNh7CTXwTbbhsQyDwWeDVMwVzACAAAAAANIH2IlSNG0kUw4qz0budjcWn8mNR9cJlYUqPYdonucAFbAAgAAAAAJMrOUOyiu5Y3sV76zwEFct8L7+i8WGlQI2+8z2W2kzaAAMxNzMAfQAAAAVkACAAAAAASZ+CvUDtlk/R4HAQ3a+PHrKeY/8ifAfh0oXYFqliu80FcwAgAAAAAJelpzPgM65OZFt/mvGGpwibclQ49wH+1gbUGzd9OindBWwAIAAAAAD9qeDchteEpVXWcycmD9kl9449C1dOw0r60TBm5jK+cQADMTc0AH0AAAAFZAAgAAAAAN9fkoUVbvFV2vMNMAkak4gYfEnzwKI3eDM3pnDK5q3lBXMAIAAAAACnDkgVNVNUlbQ9RhR6Aot2nVy+U4km6+GHPkLr631jEAVsACAAAAAANzg/BnkvkmvOr8nS4omF+q9EG/4oisB+ul4YHi938hwAAzE3NQB9AAAABWQAIAAAAAASyK3b1nmNCMptVEGOjwoxYLLS9fYWm/Zxilqea0jpEQVzACAAAAAADDHsGrbqlKGEpxlvfyqOJKQJjwJrzsrB7k3HG0AUJbkFbAAgAAAAAKwx3S4XfDZh4+LuI9jf7XgUh5qiefNv87JD4qvVRfPSAAMxNzYAfQAAAAVkACAAAAAAlSP9iK31GlcG9MKGbLmq+VXMslURr+As736rrVNXcsUFcwAgAAAAAAvbj0zfq9zzi8XReheKFbCB+h9IsOLgXPPpI5vrEJNZBWwAIAAAAABXvoZhaQE7ogWjeBjceVkp03N20cKYP3TA8vuNsgpfAgADMTc3AH0AAAAFZAAgAAAAAOJNORH8Bev97gVU7y6bznOxJ+E6Qoykur1QP76hG1/7BXMAIAAAAAC+C1PtOOrSZgzBAGhr+dPe/kR0JUw9GTwLVNr61xC1aAVsACAAAAAAeA/L8MQIXkamaObtMPLpoDoi5FypA5WAPtMeMrgi0eQAAzE3OAB9AAAABWQAIAAAAAAKcHzLUomavInN6upPkyWhAqYQACP/vdVCIYpiy6U6HgVzACAAAAAATsR4KItY6R2+U7Gg6sJdaEcf58gjd1OulyWovIqfxKcFbAAgAAAAAFbm10ko67ahboAejQdAV0U2uA5OhZYdb8XUFJ8OL46LAAMxNzkAfQAAAAVkACAAAAAAqTOLiMpCdR59tLZzzIPqJvbCNvz2XQL9ust0qYaehtcFcwAgAAAAAArefox/3k5xGOeiw2m6NUdzuGxmPwcu5IFcj+jMwHgHBWwAIAAAAADLZGFJ7MQd5JXMgMXjqZO5LDLxcFClcXPlnRMWRn+1oAADMTgwAH0AAAAFZAAgAAAAAIPSqSeVzSRgNVNmrPYHmUMgykCY27NbdDUNhE5kx/SgBXMAIAAAAAAhX90nNfxyXmZe/+btZ7q6xMX4PFyj0paM1ccJ/5IUUQVsACAAAAAA419oHmD2W0SYoOMwhrhrp8jf68fg9hTkaRdCuVd3CN0AAzE4MQB9AAAABWQAIAAAAACLn5DxiqAosHGXIAY96FwFKjeqrzXWf3VJIQMwx1fl4gVzACAAAAAAindvU27nveutopdvuHmzdENBbeGFtI3Qcsr07jxmvm8FbAAgAAAAAPvl9pBStQvP4OGkN5v0MghUY6djm9n7XdKKfrW0l1sMAAMxODIAfQAAAAVkACAAAAAA7i2S6rHRSPBwZEn59yxaS7HiYBOmObIkeyCcFU42kf8FcwAgAAAAAGb3RSEyBmgarkTvyLWtOLJcPwCKbCRkESG4RZjVmY4iBWwAIAAAAADB2/wo5CSHR4ANtifY6ZRXNTO5+O8qP82DfAiAeanpZwADMTgzAH0AAAAFZAAgAAAAAFz+M+H/Z94mdPW5oP51B4HWptp1rxcMWAjnlHvWJDWrBXMAIAAAAACBFEOQyL7ZHu4Cq33QvXkmKuH5ibG/Md3RaED9CtG5HwVsACAAAAAAfggtJTprQ/yZzj7y5z9KvXsdeXMWP0yUXMMJqpOwI88AAzE4NAB9AAAABWQAIAAAAAAE7c2x3Z3aM1XGfLNk/XQ9jCazNRbGhVm7H8c2NjS5ywVzACAAAAAARJ9h8fdcwA19velF3L/Wcvi2rCzewlKZ2nA0p8bT9uwFbAAgAAAAAJtWe6b4wK2Hae2dZm/OEpYQnvoZjz4Sz5IgJC2wInecAAMxODUAfQAAAAVkACAAAAAAVoRt9B9dNVvIMGN+ea5TzRzQC+lqSZ8dd/170zU5o9cFcwAgAAAAAEwM95XZin5mv2yhCI8+ugtKuvRVmNgzzIQN0yi1+9aIBWwAIAAAAAAMGBq72n00rox3uqhxSB98mkenTGCdbbUF1gXrgottzgADMTg2AH0AAAAFZAAgAAAAAKRDkjyWv/etlYT4GyoXrmBED2FgZHnhc+l9Wsl06cH2BXMAIAAAAABohlpm3K850Vndf3NmNE0hHqDlNbSR8/IvMidQ3LnIZAVsACAAAAAAW42nGHa6q2MCAaaPVwaIDfr8QLyQwjKq23onZJYsqVsAAzE4NwB9AAAABWQAIAAAAAC3DFh5oklLCNLY90bgWm68dFXz65JpAZSp1K99MBTPAQVzACAAAAAAQgZecmxEUZVHoptEQClDwAf8smI3WynQ/i+JBP0g+kQFbAAgAAAAAEUSQGVnAPISD6voD0DiBUqyWKgt2rta0tjmoe+LNt6IAAMxODgAfQAAAAVkACAAAAAAQ5WKvWSB503qeNlOI2Tpjd5blheNr6OBO8pfJfPNstcFcwAgAAAAAKwHgQLSDJ5NwLBQbY5OnblQIsVDpGV7q3RCbFLD1U4/BWwAIAAAAACQ5nED99LnpbqXZuUOUjnO2HTphEAFBjLD4OZeDEYybgADMTg5AH0AAAAFZAAgAAAAAGfhFY3RGRm5ZgWRQef1tXxHBq5Y6fXaLAR4yJhrTBplBXMAIAAAAACKEF0ApLoB6lP2UqTFsTQYNc9OdDrs/vziPGzttGVLKQVsACAAAAAArOO6FyfNRyBi0sPT5iye7M8d16MTLcwRfodZq4uCYKEAAzE5MAB9AAAABWQAIAAAAAAIM73gPcgzgotYHLeMa2zAU4mFsr7CbILUZWfnuKSwagVzACAAAAAAJCSu98uV8xv88f2BIOWzt6p+6EjQStMBdkGPUkgN79cFbAAgAAAAAMGqPGMPxXbmYbVfSa/japvUljht1zZT33TY7ZjAiuPfAAMxOTEAfQAAAAVkACAAAAAAkWmHCUsiMy1pwZTHxVPBzPTrWFBUDqHNrVqcyyt7nO8FcwAgAAAAAMv2CebFRG/br7USELR98sIdgE9OQCRBGV5JZCO+uPMgBWwAIAAAAABt7qSmn3gxJu7aswsbUiwvO+G6lXj/Xhx+J/zQyZxzLAADMTkyAH0AAAAFZAAgAAAAAGInUYv0lP/rK7McM8taEHXRefk8Q2AunrvWqdfSV7UaBXMAIAAAAACE+WPxJ3gan7iRTbIxXXx+bKVcaf8kP4JD8DcwU0aL7wVsACAAAAAAUC4eTprX4DUZn2X+UXYU6QjtiXk+u57yoOPBbPQUmDkAAzE5MwB9AAAABWQAIAAAAACmHlg2ud3cplXlTsNTpvNnY6Qm1Fce0m899COamoDjaQVzACAAAAAArtJQeJIlepBWRU2aYar7+YGYVQ7dfDc1oxgTmA8r9q0FbAAgAAAAAOk45vg5VqZHAFCO3i0Z52SZi5RADf8NXwf68T5yad/DAAMxOTQAfQAAAAVkACAAAAAApzcWSAbZWV/Rq+ylRNqqlJqNVR4fhXrz4633/MQOQgcFcwAgAAAAAN/jz/bsEleiuCl+li83EWlG6UMHA8CyaOMRKCkXkSCPBWwAIAAAAAC3Sd+Qg+uFDKpGZHbrQgokXHQ1az1aFl4YK343OB6hcQAAEmNtAAAAAAAAAAAAABBwYXlsb2FkSWQAAAAAABBmaXJzdE9wZXJhdG9yAAEAAAAA", "subType": "06" } } } }, "limit": 1 } ], "ordered": true, "encryptionInformation": { "type": 1, "schema": { "default.default": { "escCollection": "enxcol_.default.esc", "ecocCollection": "enxcol_.default.ecoc", "fields": [ { "keyId": { "$binary": { "base64": "EjRWeBI0mHYSNBI0VniQEg==", "subType": "04" } }, "path": "encryptedDecimalNoPrecision", "bsonType": "decimal", "queries": { "queryType": "rangePreview", "contention": { "$numberLong": "0" }, "sparsity": { "$numberLong": "1" } } } ] } } } }, "command_name": "delete" } } ], "outcome": { "collection": { "data": [ { "_id": { "$numberInt": "0" }, "encryptedDecimalNoPrecision": { "$$type": "binData" }, "__safeContent__": [ { "$binary": { "base64": "5nRutVIyq7URVOVtbE4vM01APSIajAVnsShMwjBlzkM=", "subType": "00" } }, { "$binary": { "base64": "rbf3AeBEv4wWFAKknqDxRW5cLNkFvbIs6iJjc6LShQY=", "subType": "00" } }, { "$binary": { "base64": "n+XAuFnP8Dov9TnhGFxNx0K/MnVM9WbJ7RouEu0ndO0=", "subType": "00" } }, { "$binary": { "base64": "yRXojuVdn5GQtD97qYlaCL6cOLmZ7Cvcb3wFjkLUIdM=", "subType": "00" } }, { "$binary": { "base64": "DuIkdRPITRs55I4SZmgomAHCIsDQmXRhW8+MOznkzSk=", "subType": "00" } }, { "$binary": { "base64": "SsBk+Et1lTbU+QRPx+xyJ/jMkmfG+QCvQEpip2YYrzA=", "subType": "00" } }, { "$binary": { "base64": "crCIzOd8KhHvvUlX7M1v9bhvU4pLdTc+X2SuqoKU5Ek=", "subType": "00" } }, { "$binary": { "base64": "YOWdCw4UrqnxkAaVjqmC4sKQDMVMHEpFGnlxpxdaU6E=", "subType": "00" } }, { "$binary": { "base64": "M3SShp81Ff8tQ632qKbv9MUcN6wjDaBReI0VXNu6Xh4=", "subType": "00" } }, { "$binary": { "base64": "gzHlSPxpM0hT75kQvWFzGlOxKvDoiKQZOr19V6l2zXI=", "subType": "00" } }, { "$binary": { "base64": "s3JnppOGYw9SL2Q1kMAZs948v2F5PrpXjGei/HioDWs=", "subType": "00" } }, { "$binary": { "base64": "cG6+3Gk/zEH68P/uuuwiAUVCuyJwa1LeV+t29FlPPAo=", "subType": "00" } }, { "$binary": { "base64": "dupdvR3AyJtM+g9NDKiaLVOtGca387JQp8w+V03m7Ig=", "subType": "00" } }, { "$binary": { "base64": "JqEQc5svj2jTvZ6LLA5ivE+kTb/0aRemSEmxk4G7Zrg=", "subType": "00" } }, { "$binary": { "base64": "szcXXXKnob+p3SoM4yED2R920LeJ7cVsclPMFTe4CeI=", "subType": "00" } }, { "$binary": { "base64": "o1QoGVXmuBdHwHm7aCtGMlMVKrjFdYvJXpoq6uhIAZ0=", "subType": "00" } }, { "$binary": { "base64": "Jfm5wPlqqLCJRGQIqRq2NGmpn7s0Vrih2H3YAOoI2YU=", "subType": "00" } }, { "$binary": { "base64": "zMHLb8ARbsYo8Ld05bqnGFf1Usha6EGb8QKwdSAyps0=", "subType": "00" } }, { "$binary": { "base64": "yQdtq9lh5pugL7/i0Bj/PuZUUBUIzf+7wj1rl5y736w=", "subType": "00" } }, { "$binary": { "base64": "wGWVZdO7qIuyDg/BqDgqjgoQ02h5YYgwXQB1oCin2NE=", "subType": "00" } }, { "$binary": { "base64": "by9HMLj6NTEpgztZ5HSN6GxImkXPcaFINYDzgZY33X8=", "subType": "00" } }, { "$binary": { "base64": "tWo0vbasi7bXmn/MsOx13VC1IsWtpx/nYp0uj4iMzdA=", "subType": "00" } }, { "$binary": { "base64": "tQQpndUYd5O87lOtrGjH3wl9VsOK0ray7RMasL90sBM=", "subType": "00" } }, { "$binary": { "base64": "cQjXEDCMsOpKLLf+vlTgIHA+cbSJdzqhbSX9Wvh95aA=", "subType": "00" } }, { "$binary": { "base64": "7yMpU48IxK9SzP2cx3VnTownGEwFmeFofuuFT97SuuY=", "subType": "00" } }, { "$binary": { "base64": "kSOx1kz0CmBgzKQHZlo65ZUY1DIv9A99JRm+Us2y6Ew=", "subType": "00" } }, { "$binary": { "base64": "ubQpdPBe6/xvtr+AcXdfYLSvYCR4ot0tivehkCsupb4=", "subType": "00" } }, { "$binary": { "base64": "xal+iCJ6FTefRQToyoNksc9NCZShyn04NDGi4IYrcoM=", "subType": "00" } }, { "$binary": { "base64": "d7jU4iOK50xHxlkSifcxlZFCM46TSgQzoYivxG3HNLY=", "subType": "00" } }, { "$binary": { "base64": "tJvl2nsBLBVzL3pp6sKWCL4UXeh3q/roYBJjSb74ve0=", "subType": "00" } }, { "$binary": { "base64": "OIUCaKRvIx9t1w6Hxlz1IcQTdPNCfdRNwnnTm10W+X0=", "subType": "00" } }, { "$binary": { "base64": "A9tvzsiElotOUVIB4CqfQp9mAwqvTM35YkmAR170aHA=", "subType": "00" } }, { "$binary": { "base64": "lI8gpK7hpb7c9x4RQugsxMnQay5LZJmwslZdvMx/dcE=", "subType": "00" } }, { "$binary": { "base64": "dNCzh40U0XvdKnSDi3HRQOWQftEsDVqc4uUvsVFGoq8=", "subType": "00" } }, { "$binary": { "base64": "IP+iwEBWBwVVZIdpaMu8k5+soFCz+TZkYn3drKZ9grE=", "subType": "00" } }, { "$binary": { "base64": "pnqyh6e0y5svHkJDShlN9CHV0WvMBE4QbtJpQw5ZCXc=", "subType": "00" } }, { "$binary": { "base64": "elEl42tbVDoRTLjAhZUFEtXiut4b3PVhg/1ZLZSQdtE=", "subType": "00" } }, { "$binary": { "base64": "vHuu2FxwclMHqyE6JBYbTYgbEkB0dqb/JuaxsvfwsmY=", "subType": "00" } }, { "$binary": { "base64": "xTf7NCe3Gf8QpE78HR5OknlLTKfs9J+RN9UZpH6fnso=", "subType": "00" } }, { "$binary": { "base64": "XiWSasRnJAulGR6+LCVD3mwRObXylqYWR9jvpywq12c=", "subType": "00" } }, { "$binary": { "base64": "MZMxEQ5ikx0PG1YFIExv0UnTZogsvgeOEZTpzvBDn4w=", "subType": "00" } }, { "$binary": { "base64": "yZMyMZBDrWbAhvnic7vvIYhmO9m5H2iuv0c8KNZrBzY=", "subType": "00" } }, { "$binary": { "base64": "xxM14hTPY5j0vvcK2C7YAEjzdsfUTFHozHC0hEo1bxI=", "subType": "00" } }, { "$binary": { "base64": "+01rqR1xVwkpGXcstbk1ItJqFVjH6Q8MGxEN3Cm9Y1A=", "subType": "00" } }, { "$binary": { "base64": "xOpLV0Z2VTRJ3iWtnWZcsyjXubTIkYWo31cO+HV1o1k=", "subType": "00" } }, { "$binary": { "base64": "BWUOLqgLBqc5NwxVlSV5H3KFQPXbCp7mdo+jF+8cJqY=", "subType": "00" } }, { "$binary": { "base64": "fuQb1S6xZDGlrEbK+kI23aL53PP1PVNwqICnZNt9Yzg=", "subType": "00" } }, { "$binary": { "base64": "SfscnoibFttahLdPVC4Ee+47ewGFKpDSU7M6HX19bKE=", "subType": "00" } }, { "$binary": { "base64": "rpSW2awybNVeKtat91VFxqbINoTfNhPfQAu+d73Xtf8=", "subType": "00" } }, { "$binary": { "base64": "9M/CP9ccOIIj2LLFmE0GFDO0Ban2wsNalEXfM6+h+1s=", "subType": "00" } }, { "$binary": { "base64": "WrEMG49l1ye4MhXs5ZS9tz8P6h+hDvthIg/2wW9ne1Q=", "subType": "00" } }, { "$binary": { "base64": "ImNhbfeyfH8qIEeA5ic0s3dAQBdzzTBS+CPsNih9vZ0=", "subType": "00" } }, { "$binary": { "base64": "dWP33YDSn04UKJN2ogh2Rui0iW/0q2y18OCDRVcfyoo=", "subType": "00" } }, { "$binary": { "base64": "lYv0isAtfGh6H9tdp3cp2eHU7q2J+uk7QrgcxtK3w7Y=", "subType": "00" } }, { "$binary": { "base64": "VGMoamB/+7zTOYcY/pqJc96xlv2PdW4hwsIAEIslTDQ=", "subType": "00" } }, { "$binary": { "base64": "yNeBWMF7BnD9wVwz2PgJsvWr77QiVvvWUvJF0+fqBug=", "subType": "00" } }, { "$binary": { "base64": "SfpvObJ+tJBXSvqeN7vlOfmhYign635lciYAJIjUtY8=", "subType": "00" } }, { "$binary": { "base64": "dsen4NqjzVGjpjufiTMs3+gqeD09EbnuogPgxrJECwg=", "subType": "00" } }, { "$binary": { "base64": "pxCWVM3sn19NsFEpgHbgLa+PmYlhN3mMiP0Wk8kJhYw=", "subType": "00" } }, { "$binary": { "base64": "q11KNvJszjYIB9n9HcC+N4uz11a3eRj1L3BH9scKMDQ=", "subType": "00" } }, { "$binary": { "base64": "A1PmkgcEToWh1JiVWE6mI5jUu7poxWWuCUt/cgRUUDc=", "subType": "00" } }, { "$binary": { "base64": "qJo3Hu4PJeanL7XEaWXO/n3YsodhZyd+MJOOmB9Kpd8=", "subType": "00" } }, { "$binary": { "base64": "BkBKLO8URFscfRY9Bav/1+L9mLohDgNr/MkZtGiraIs=", "subType": "00" } }, { "$binary": { "base64": "rZq5WA3Hx3xthOyHAJXK//f8pE2qbz7YKu3TIMp9GFY=", "subType": "00" } }, { "$binary": { "base64": "X07a/Lm80p5xd4RFs1dNmw+90tmPDPdGiAKVZkxd4zY=", "subType": "00" } }, { "$binary": { "base64": "6YrBn2ofIw1b5ooakrLOwF41BWrps8OO0H9WH4/rtlE=", "subType": "00" } }, { "$binary": { "base64": "0l86Ag5OszXpa78SlOUV3K9nff5iC1p0mRXtLg9M1s4=", "subType": "00" } }, { "$binary": { "base64": "Hn6yuxFHodeyu7ISlhYrbSf9pTiH4TDEvbYLWjTwFO0=", "subType": "00" } }, { "$binary": { "base64": "zdf4y2etKBuIpkEU1zMwoCkCsdisfXZCh8QPamm+drY=", "subType": "00" } }, { "$binary": { "base64": "rOQ9oMdiK5xxGH+jPzOvwVqdGGnF3+HkJXxn81s6hp4=", "subType": "00" } }, { "$binary": { "base64": "61aKKsE3+BJHHWYvs3xSIBvlRmKswmaOo5rygQJguUg=", "subType": "00" } }, { "$binary": { "base64": "KuDb/GIzqDM8wv7m7m8AECiWJbae5EKKtJRugZx7kR0=", "subType": "00" } }, { "$binary": { "base64": "Q+t8t2TmNUiCIorVr9F3AlVnX+Mpt2ZYvN+s8UGict8=", "subType": "00" } }, { "$binary": { "base64": "tJRZIpKxUgHyL83kW8cvfjkxN3z6WoNnUg+SQw+LK+k=", "subType": "00" } }, { "$binary": { "base64": "pnUsYjip8SvW0+m9mR5WWTkpK+p6uwJ6yBUAlBnFKMk=", "subType": "00" } }, { "$binary": { "base64": "PArHlz+yPRYDycAP/PgnI/AkP8Wgmfg++Vf4UG1Bf0E=", "subType": "00" } }, { "$binary": { "base64": "wnIh53Q3jeK8jEBe1n8kJLa89/H0BxO26ZU8SRIAs9Q=", "subType": "00" } }, { "$binary": { "base64": "4F8U59gzBLGhq58PEWQk2nch+R0Va7eTUoxMneReUIA=", "subType": "00" } }, { "$binary": { "base64": "ihKagIW3uT1dm22ROr/g5QaCpxZVj2+Fs/YSdM2Noco=", "subType": "00" } }, { "$binary": { "base64": "EJtUOOwjkrPUi9mavYAi+Gom9Y2DuFll7aDwo4mq0M0=", "subType": "00" } }, { "$binary": { "base64": "dIkr8dbaVRQFskAVT6B286BbcBBt1pZPEOcTZqk4ZcI=", "subType": "00" } }, { "$binary": { "base64": "aYVAcZYkH/Tieoa1XOjE/zCy5AJcVTHjS0NG2QB7muA=", "subType": "00" } }, { "$binary": { "base64": "sBidL6y8TenseetpioIAAtn0lK/7C8MoW4JXpVYi3z8=", "subType": "00" } }, { "$binary": { "base64": "0Dd2klU/t4R86c2WJcJDAd57k/N7OjvYSO5Vf8KH8sw=", "subType": "00" } }, { "$binary": { "base64": "I3jZ92WEVmZmgaIkLbuWhBxl7EM6bEjiEttgBJunArA=", "subType": "00" } }, { "$binary": { "base64": "aGHoQMlgJoGvArjfIbc3nnkoc8SWBxcrN7hSmjMRzos=", "subType": "00" } }, { "$binary": { "base64": "bpiWPnF/KVBQr5F6MEwc5ZZayzIRvQOLDAm4ntwOi8g=", "subType": "00" } }, { "$binary": { "base64": "tI7QVKbE6avWgDD9h4QKyFlnTxFCwd2iLySKakxNR/I=", "subType": "00" } }, { "$binary": { "base64": "XGsge0CnoaXgE3rcpKm8AEeku5QVfokS3kcI+JKV1lk=", "subType": "00" } }, { "$binary": { "base64": "JQxlryW2Q5WOwfrjAnaZxDvC83Dg6sjRVP5zegf2WiM=", "subType": "00" } }, { "$binary": { "base64": "YFuHKJOfoqp1iGVxoFjx7bLYgVdsN4GuUFxEgO9HJ5s=", "subType": "00" } }, { "$binary": { "base64": "Z6vUdiCR18ylKomf08uxcQHeRtmyav7/Ecvzz4av3k4=", "subType": "00" } }, { "$binary": { "base64": "SPGo1Ib5AiP/tSllL7Z5PAypvnKdwJLzt8imfIMSEJQ=", "subType": "00" } }, { "$binary": { "base64": "m94Nh6PFFQFLIib9Cu5LAKavhXnagSHG6F5EF8lD96I=", "subType": "00" } }, { "$binary": { "base64": "pfEkQI98mB+gm1+JbmVurPAODMFPJ4E8DnqfVyUWbSo=", "subType": "00" } }, { "$binary": { "base64": "DNj3OVRLbr43s0vd+rgWghOL3FqeO/60npdojC8Ry/M=", "subType": "00" } }, { "$binary": { "base64": "kAYIQrjHVu49W8FTxyxJeiLVRWWjC9fPcBn+Hx1F+Ss=", "subType": "00" } }, { "$binary": { "base64": "aCSO7UVOpoQvu/iridarxkxV1SVxU1i9HVSYXUAeXk4=", "subType": "00" } }, { "$binary": { "base64": "Gh6hTP/yj1IKlXQ+Q69KTfMlGZjEcXoRLGbQHNFo/1s=", "subType": "00" } }, { "$binary": { "base64": "/gDgIFQ4tAlJk3GN48IS5Qa5IPmErwGk8CHxAbp6gs0=", "subType": "00" } }, { "$binary": { "base64": "PICyimwPjxpusyKxNssOOwUotAUbygpyEtORsVGXT8g=", "subType": "00" } }, { "$binary": { "base64": "4lu+cBHyAUvuxC6JUNyHLzHsCogGSWFFnUCkDwfQdgI=", "subType": "00" } }, { "$binary": { "base64": "pSndkmoNUJwXjgkbkgOrT5f9nSvuoMEZOkwAN9ElRaE=", "subType": "00" } }, { "$binary": { "base64": "tyW+D4i26QihNM5MuBM+wnt5AdWGSJaJ4X5ydc9iWTU=", "subType": "00" } }, { "$binary": { "base64": "9Syjr8RoxUgPKr+O5rsCu07AvcebA4P8IVKyS1NVLWc=", "subType": "00" } }, { "$binary": { "base64": "67tPfDYnK2tmrioI51fOBG0ygajcV0pLo5+Zm/rEW7U=", "subType": "00" } }, { "$binary": { "base64": "y0EiPRxYTuS1eVTIaPQUQBBxwkyxNckbePvKgChwd0M=", "subType": "00" } }, { "$binary": { "base64": "NWd+2veAaeXQgR3vCvzlI4R1WW67D5YsVLdoXfdb8qg=", "subType": "00" } }, { "$binary": { "base64": "PY5RQqKQsL2GqBBSPNOEVpojNFRX/NijCghIpxD6CZk=", "subType": "00" } }, { "$binary": { "base64": "lcvwTyEjFlssCJtdjRpdN6oY+C7bxZY+WA+QAqzj9zg=", "subType": "00" } }, { "$binary": { "base64": "CWE7XRNylvTwO/9Fv56dNqUaQWMmESNS/GNIwgBaEI0=", "subType": "00" } }, { "$binary": { "base64": "ijwlrUeS8nRYqK1F8kiCYF0mNDolEZS+/lJO1Lg93C8=", "subType": "00" } }, { "$binary": { "base64": "8KzV+qYGYuIjoNj8eEpnTuHrMYuhzphl80rS6wrODuU=", "subType": "00" } }, { "$binary": { "base64": "wDyTLjSEFF895hSQsHvmoEQVS6KIkZOtq1c9dVogm9I=", "subType": "00" } }, { "$binary": { "base64": "SGrtPuMYCjUrfKF0Pq/thdaQzmGBMUvlwN3ORIu9tHU=", "subType": "00" } }, { "$binary": { "base64": "KySHON3hIoUk4xWcwTqk6IL0kgjzjxgMBObVIkCGvk4=", "subType": "00" } }, { "$binary": { "base64": "hBIdS9j0XJPeT4ot73ngELkpUoSixvRBvdOL9z48jY8=", "subType": "00" } }, { "$binary": { "base64": "Tx6um0q9HjS5ZvlFhvukpI6ORnyrXMWVW1OoxvgqII0=", "subType": "00" } }, { "$binary": { "base64": "zFKlyfX5H81+d4A4J3FKn4T5JfG+OWtR06ddyX4Mxas=", "subType": "00" } }, { "$binary": { "base64": "cGgCDuPV7MeMMYEDpgOupqyNP4BQ4H7rBnd2QygumgM=", "subType": "00" } }, { "$binary": { "base64": "IPaUoy98v11EoglTpJ4kBlEawoZ8y7BPwzjLYBpkvHQ=", "subType": "00" } }, { "$binary": { "base64": "Pfo4Am6tOWAyZNn8G9W5HWWGC3ZWmX0igI/RRB870Ro=", "subType": "00" } }, { "$binary": { "base64": "fnTSjd7bC1Udoq6iM7UDnHAC/lsIXSHp/Gy332qw+/I=", "subType": "00" } }, { "$binary": { "base64": "fApBgVRrTDyEumkeWs5p3ag9KB48SbU4Si0dl7Ns9rc=", "subType": "00" } }, { "$binary": { "base64": "QxudfBItgoCnUj5NXVnSmWH3HK76YtKkMmzn4lyyUYY=", "subType": "00" } }, { "$binary": { "base64": "sSOvwhKa29Wq94bZ5jGIiJQGbG1uBrKSBfOYBz/oZeI=", "subType": "00" } }, { "$binary": { "base64": "FdaMgwwJ0NKsqmPZLC5oE+/0D74Dfpvig3LaI5yW5Fs=", "subType": "00" } }, { "$binary": { "base64": "sRWBy12IERN43BSZIrnBfC9+zFBUdvjTlkqIH81NGt4=", "subType": "00" } }, { "$binary": { "base64": "/4tIRpxKhoOwnXAiFn1Z7Xmric4USOIfKvTYQXk3QTc=", "subType": "00" } } ] } ] } } } ] } fle2v2-Range-Decimal-FindOneAndUpdate.json000066400000000000000000002730151462766011000366220ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/client-side-encryption/spec/legacy{ "runOn": [ { "minServerVersion": "7.0.0", "topology": [ "replicaset" ] } ], "database_name": "default", "collection_name": "default", "data": [], "encrypted_fields": { "fields": [ { "keyId": { "$binary": { "base64": "EjRWeBI0mHYSNBI0VniQEg==", "subType": "04" } }, "path": "encryptedDecimalNoPrecision", "bsonType": "decimal", "queries": { "queryType": "rangePreview", "contention": { "$numberLong": "0" }, "sparsity": { "$numberLong": "1" } } } ] }, "key_vault_data": [ { "_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" } } ], "tests": [ { "description": "FLE2 Range Decimal. FindOneAndUpdate.", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "local": { "key": { "$binary": { "base64": "Mng0NCt4ZHVUYUJCa1kxNkVyNUR1QURhZ2h2UzR2d2RrZzh0cFBwM3R6NmdWMDFBMUN3YkQ5aXRRMkhGRGdQV09wOGVNYUMxT2k3NjZKelhaQmRCZGJkTXVyZG9uSjFk", "subType": "00" } } } } } }, "operations": [ { "name": "insertOne", "arguments": { "document": { "_id": 0, "encryptedDecimalNoPrecision": { "$numberDecimal": "0" } } } }, { "name": "insertOne", "arguments": { "document": { "_id": 1, "encryptedDecimalNoPrecision": { "$numberDecimal": "1" } } } }, { "name": "findOneAndUpdate", "arguments": { "filter": { "encryptedDecimalNoPrecision": { "$gt": { "$numberDecimal": "0" } } }, "update": { "$set": { "encryptedDecimalNoPrecision": { "$numberDecimal": "2" } } }, "returnDocument": "Before" }, "result": { "_id": 1, "encryptedDecimalNoPrecision": { "$numberDecimal": "1" } } } ], "expectations": [ { "command_started_event": { "command": { "listCollections": 1, "filter": { "name": "default" } }, "command_name": "listCollections" } }, { "command_started_event": { "command": { "find": "datakeys", "filter": { "$or": [ { "_id": { "$in": [ { "$binary": { "base64": "EjRWeBI0mHYSNBI0VniQEg==", "subType": "04" } } ] } }, { "keyAltNames": { "$in": [] } } ] }, "$db": "keyvault", "readConcern": { "level": "majority" } }, "command_name": "find" } }, { "command_started_event": { "command": { "insert": "default", "documents": [ { "_id": 0, "encryptedDecimalNoPrecision": { "$$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": "encryptedDecimalNoPrecision", "bsonType": "decimal", "queries": { "queryType": "rangePreview", "contention": { "$numberLong": "0" }, "sparsity": { "$numberLong": "1" } } } ] } } } }, "command_name": "insert" } }, { "command_started_event": { "command": { "insert": "default", "documents": [ { "_id": 1, "encryptedDecimalNoPrecision": { "$$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": "encryptedDecimalNoPrecision", "bsonType": "decimal", "queries": { "queryType": "rangePreview", "contention": { "$numberLong": "0" }, "sparsity": { "$numberLong": "1" } } } ] } } } }, "command_name": "insert" } }, { "command_started_event": { "command": { "findAndModify": "default", "query": { "encryptedDecimalNoPrecision": { "$gt": { "$binary": { "base64": "DeFiAAADcGF5bG9hZACxYgAABGcAnWIAAAMwAH0AAAAFZAAgAAAAAJu2KgiI8vM+kz9qD3ZQzFQY5qbgYqCqHG5R4jAlnlwXBXMAIAAAAAAAUXxFXsz764T79sGCdhxvNd5b6E/9p61FonsHyEIhogVsACAAAAAAt19RL3Oo5ni5L8kcvgOJYLgVYyXJExwP8pkuzLG7f/kAAzEAfQAAAAVkACAAAAAAPQPvL0ARjujSv2Rkm8r7spVsgeC1K3FWcskGGZ3OdDIFcwAgAAAAACgNn660GmefR8jLqzgR1u5O+Uocx9GyEHiBqVGko5FZBWwAIAAAAADflr+fsnZngm6KRWYgHa9JzK+bXogWl9evBU9sQUHPHQADMgB9AAAABWQAIAAAAAD2Zi6kcxmaD2mY3VWrP+wYJMPg6cSBIYPapxaFQxYFdQVzACAAAAAAM/cV36BLBY3xFBXsXJY8M9EHHOc/qrmdc2CJmj3M89gFbAAgAAAAAOpydOrKxx6m2gquSDV2Vv3w10GocmNCFeOo/fRhRH9JAAMzAH0AAAAFZAAgAAAAAOaNqI9srQ/mI9gwbk+VkizGBBH/PPWOVusgnfPk3tY1BXMAIAAAAAAc96O/pwKCmHCagT6T/QV/wz4vqO+R22GsZ1dse2Vg6QVsACAAAAAAgzIak+Q3UFLTHXPmJ+MuEklFtR3eLtvM+jdKkmGCV/YAAzQAfQAAAAVkACAAAAAA0XlQgy/Yu97EQOjronl9b3dcR1DFn3deuVhtTLbJZHkFcwAgAAAAACoMnpVl6EFJak8A+t5N4RFnQhkQEBnNAx8wDqmq5U/dBWwAIAAAAACR26FJif673qpwF1J1FEkQGJ1Ywcr/ZW6JQ7meGqzt1QADNQB9AAAABWQAIAAAAAAOtpNexRxfv0yRFvZO9DhlkpU4mDuAb8ykdLnE5Vf1VAVzACAAAAAAeblFKm/30orP16uQpZslvsoS8s0xfNPIBlw3VkHeekYFbAAgAAAAAPEoHj87sYE+nBut52/LPvleWQBzB/uaJFnosxp4NRO2AAM2AH0AAAAFZAAgAAAAAIr8xAFm1zPmrvW4Vy5Ct0W8FxMmyPmFzdWVzesBhAJFBXMAIAAAAABYeeXjJEzTHwxab6pUiCRiZjxgtN59a1y8Szy3hfkg+gVsACAAAAAAJuoY4rF8mbI+nKb+5XbZShJ8191o/e8ZCRHE0O4Ey8MAAzcAfQAAAAVkACAAAAAAl+ibLk0/+EwoqeC8S8cGgAtjtpQWGEZDsybMPnrrkwEFcwAgAAAAAHPPBudWgQ+HUorLDpJMqhS9VBF2VF5aLcxgrM1s+yU7BWwAIAAAAAAcCcBR2Vyv5pAFbaOU97yovuOi1+ATDnLLcAUqHecXcAADOAB9AAAABWQAIAAAAACR9erwLTb+tcWFZgJ2MEfM0PKI9uuwIjDTHADRFgD+SQVzACAAAAAAcOop8TXsGUVQoKhzUllMYWxL93xCOkwtIpV8Q6hiSYYFbAAgAAAAAKXKmh4V8veYwob1H03Q3p3PN8SRAaQwDT34KlNVUjiDAAM5AH0AAAAFZAAgAAAAALv0vCPgh7QpmM8Ug6ad5ioZJCh7pLMdT8FYyQioBQ6KBXMAIAAAAADsCPyIG8t6ApQkRk1fX/sfc1kpuWCWP8gAEpnYoBSHrQVsACAAAAAAJe/r67N6d8uTiogvfoR9rEXbIDjyLb9EVdqkayFFGaYAAzEwAH0AAAAFZAAgAAAAAIW4AxJgYoM0pcNTwk1RSbyjZGIqgKL1hcTJmNrnZmoPBXMAIAAAAAAZpfx3EFO0vY0f1eHnE0PazgqeNDTaj+pPJMUNW8lFrAVsACAAAAAAP+Um2vwW6Bj6vuz9DKz6+6aWkoKoEmFNoiz/xXm7lOsAAzExAH0AAAAFZAAgAAAAAKliO6L9zgeuufjj174hvmQGNRbmYYs9yAirL7OxwEW3BXMAIAAAAAAqU7vs3DWUQ95Eq8OejwWnD0GuXd+ASi/uD6S0l8MM1QVsACAAAAAAb9legYzsfctBPpHyl7YWpPmLr5QiNZFND/50N1vv2MUAAzEyAH0AAAAFZAAgAAAAAOGQcCBkk+j/Kzjt/Cs6g3BZPJG81wIHBS8JewHGpgk+BXMAIAAAAABjrxZXWCkdzrExwCgyHaafuPSQ4V4x2k9kUCAqUaYKDQVsACAAAAAADBU6KefT0v8zSmseaMNmQxKjJar72y7MojLFhkEHqrUAAzEzAH0AAAAFZAAgAAAAAPmCNEt4t97waOSd5hNi2fNCdWEkmcFJ37LI9k4Az4/5BXMAIAAAAABX7DuDPNg+duvELf3NbLWkPMFw2HGLgWGHyVWcPvSNCAVsACAAAAAAS7El1FtZ5STh8Q1FguvieyYX9b2DF1DFVsb9hzxXYRsAAzE0AH0AAAAFZAAgAAAAAD4vtVUYRNB+FD9yoQ2FVJH3nMeJeKbi6eZfth638YqbBXMAIAAAAAANCuUB4OdmuD6LaDK2f3vaqfgYYvg40wDXOBbcFjTqLwVsACAAAAAA9hqC2VoJBjwR7hcQ45xO8ZVojwC83jiRacCaDj6Px2gAAzE1AH0AAAAFZAAgAAAAAJPIRzjmTjbdIvshG6UslbEOd797ZSIdjGAhGWxVQvK1BXMAIAAAAABgmJ0Jh8WLs9IYs/a7DBjDWd8J3thW/AGJK7zDnMeYOAVsACAAAAAAi9zAsyAuou2oiCUHGc6QefLUkACa9IgeBhGu9W/r0X8AAzE2AH0AAAAFZAAgAAAAAABQyKQPoW8wGPIqnsTv69+DzIdRkohRhOhDmyVHkw9WBXMAIAAAAAAqWA2X4tB/h3O1Xlawtz6ndI6WaTwgU1QYflL35opu5gVsACAAAAAAWI/Gj5aZMwDIxztqmVL0g5LBcI8EdKEc2UA28pnekQoAAzE3AH0AAAAFZAAgAAAAACB7NOyGQ1Id3MYnxtBXqyZ5Ul/lHH6p1b10U63DfT6bBXMAIAAAAADpOryIcndxztkHSfLN3Kzq29sD8djS0PspDSqERMqokQVsACAAAAAADatsMW4ezgnyi1PiP7xk+gA4AFIN/fb5uJqfVkjg4UoAAzE4AH0AAAAFZAAgAAAAAKVfXLfs8XA14CRTB56oZwV+bFJN5BHraTXbqEXZDmTkBXMAIAAAAAASRWTsfGOpqdffiOodoqIgBzG/yzFyjR5CfUsIUIWGpgVsACAAAAAAkgCHbCwyX640/0Ni8+MoYxeHUiC+FSU4Mn9jTLYtgZgAAzE5AH0AAAAFZAAgAAAAAH/aZr4EuS0/noQR9rcF8vwoaxnxrwgOsSJ0ys8PkHhGBXMAIAAAAACd7ObGQW7qfddcvyxRTkPuvq/PHu7+6I5dxwS1Lzy5XAVsACAAAAAA3q0eKdV7KeU3pc+CtfypKR7BPxwaf30yu0j9FXeOOboAAzIwAH0AAAAFZAAgAAAAAKvlcpFFNq0oA+urq3w6d80PK1HHHw0H0yVWvU9aHijXBXMAIAAAAADWnAHQ5Fhlcjawki7kWzdqjM2f6IdGJblojrYElWjsZgVsACAAAAAAO0wvY66l24gx8nRxyVGC0QcTztIi81Kx3ndRhuZr6W4AAzIxAH0AAAAFZAAgAAAAAH/2aMezEOddrq+dNOkDrdqf13h2ttOnexZsJxG1G6PNBXMAIAAAAABNtgnibjC4VKy5poYjvdsBBnVvDTF/4mmEAxsXVgZVKgVsACAAAAAAqvadzJFLqQbs8WxgZ2D2X+XnaPSDMLCVVgWxx5jnLcYAAzIyAH0AAAAFZAAgAAAAAF2wZoDL6/V59QqO8vdRZWDpXpkV4h4KOCSn5e7x7nmzBXMAIAAAAADLZBu7LCYjbThaVUqMK14H/elrVOYIKJQCx4C9Yjw37gVsACAAAAAAEh6Vs81jLU204aGpL90fmYTm5i5R8/RT1uIbg6VU3HwAAzIzAH0AAAAFZAAgAAAAAH27yYaLn9zh2CpvaoomUPercSfJRUmBY6XFqmhcXi9QBXMAIAAAAAAUwumVlIYIs9JhDhSj0R0+59psCMsFk94E62VxkPt42QVsACAAAAAAT5x2hCCd2bpmpnyWaxas8nSxTc8e4C9DfKaqr0ABEysAAzI0AH0AAAAFZAAgAAAAALMg2kNAO4AFFs/mW3In04yFeN4AP6Vo0klyUoT06RquBXMAIAAAAAAgGWJbeIdwlpqXCyVIYSs0dt54Rfc8JF4b8uYc+YUj0AVsACAAAAAAWHeWxIkyvXTOWvfZzqtPXjfGaWWKjGSIQENTU3zBCrsAAzI1AH0AAAAFZAAgAAAAALas/i1T2DFCEmrrLEi7O2ngJZyFHialOoedVXS+OjenBXMAIAAAAAA1kK0QxY4REcGxHeMkgumyF7iwlsRFtw9MlbSSoQY7uAVsACAAAAAAUNlpMJZs1p4HfsD4Q4WZ4TBEi6Oc2fX34rzyynqWCdwAAzI2AH0AAAAFZAAgAAAAAP1TejmWg1CEuNSMt6NUgeQ5lT+oBoeyF7d2l5xQrbXWBXMAIAAAAABPX0kj6obggdJShmqtVfueKHplH4ZrXusiwrRDHMOKeQVsACAAAAAAIYOsNwC3DA7fLcOzqdr0bOFdHCfmK8tLwPoaE9uKOosAAzI3AH0AAAAFZAAgAAAAAMrKn+QPa/NxYezNhlOX9nyEkN1kE/gW7EuZkVqYl0b8BXMAIAAAAABUoZMSPUywRGfX2EEencJEKH5x/P9ySUVrhStAwgR/LgVsACAAAAAAMgZFH6lQIIDrgHnFeslv3ld20ynwQjQJt3cAp4GgrFkAAzI4AH0AAAAFZAAgAAAAAMmD1+a+oVbiUZd1HuZqdgtdVsVKwuWAn3/M1B6QGBM3BXMAIAAAAACLyytOYuZ9WEsIrrtJbXUx4QgipbaAbmlJvSZVkGi0CAVsACAAAAAA4v1lSp5H9BB+HYJ4bH43tC8aeuPZMf78Ng1JOhJh190AAzI5AH0AAAAFZAAgAAAAAOVKV7IuFwmYP1qVv8h0NvJmfPICu8yQhzjG7oJdTLDoBXMAIAAAAABL70XLfQLKRsw1deJ2MUvxSWKxpF/Ez73jqtbLvqbuogVsACAAAAAAvfgzIorXxE91dDt4nQxYfntTsx0M8Gzdsao5naQqcRUAAzMwAH0AAAAFZAAgAAAAAKS/1RSAQma+xV9rz04IcdzmavtrBDjOKPM+Z2NEyYfPBXMAIAAAAAAOJDWGORDgfRv8+w5nunh41wXb2hCA0MRzwnLnQtIqPgVsACAAAAAAf42C1+T7xdHEFF83+c2mF5S8PuuL22ogXXELnRAZ4boAAzMxAH0AAAAFZAAgAAAAAFeq8o82uNY1X8cH6OhdTzHNBUnCChsEDs5tm0kPBz3qBXMAIAAAAABaxMBbsaeEj/EDtr8nZfrhhhirBRPJwVamDo5WwbgvTQVsACAAAAAAMbH453A+BYAaDOTo5kdhV1VdND1avNwvshEG/4MIJjQAAzMyAH0AAAAFZAAgAAAAAI8IKIfDrohHh2cjspJHCovqroSr5N3QyVtNzFvT5+FzBXMAIAAAAABXHXteKG0DoOMmECKp6ro1MZNQvXGzqTDdZ0DUc8QfFAVsACAAAAAA/w5s++XYmO+9TWTbtGc3n3ndV4T9JUribIbF4jmDLSMAAzMzAH0AAAAFZAAgAAAAAJkHvm15kIu1OtAiaByj5ieWqzxiu/epK6c/9+KYIrB0BXMAIAAAAACzg5TcyANk0nes/wCJudd1BwlkWWF6zw3nGclq5v3SJQVsACAAAAAAvruXHTT3irPJLyWpI1j/Xwf2FeIE/IV+6Z49pqRzISoAAzM0AH0AAAAFZAAgAAAAAAYSOvEWWuSg1Aym7EssNLR+xsY7e9BcwsX4JKlnSHJcBXMAIAAAAABT48eY3PXVDOjw7JpNjOe1j2JyI3LjDnQoqZ8Je5B2KgVsACAAAAAAU2815RR57TQ9uDg0XjWjBkAKvf8yssxDMzrM4+FqP6AAAzM1AH0AAAAFZAAgAAAAAGQxC9L1e9DfO5XZvX1yvc3hTLtQEdKO9FPMkyg0Y9ZABXMAIAAAAADtmcMNJwdWLxQEArMGZQyzpnu+Z5yMmPAkvgq4eAKwNQVsACAAAAAAJ88zt4Y/Hoqh+zrf6KCOiUwHbOzCxSfp6k/qsZaYGEgAAzM2AH0AAAAFZAAgAAAAADLHK2LNCNRO0pv8n4fAsxwtUqCNnVK8rRgNiQfXpHSdBXMAIAAAAACf16EBIHRKD3SzjRW+LMOl+47QXA3CJhMzlcqyFRW22AVsACAAAAAAMGz4fAOa0EoVv90fUffwLjBrQhHATf+NdlgCR65vujAAAzM3AH0AAAAFZAAgAAAAAHiZJiXKNF8bbukQGsdYkEi95I+FSBHy1I5/hK2uEZruBXMAIAAAAADE+lZBa8HDUJPN+bF6xI9x4N7GF9pj3vBR7y0BcfFhBAVsACAAAAAAGIEN6sfqq30nyxW4dxDgXr/jz5HmvA9T1jx/pKCn4zgAAzM4AH0AAAAFZAAgAAAAAI1oa2OIw5TvhT14tYCGmhanUoYcCZtNbrVbeoMldHNZBXMAIAAAAAAx2nS0Ipblf2XOgBiUOuJFBupBhe7nb6QPLZlA4aMPCgVsACAAAAAA9xu828hugIgo0E3de9dZD+gTpVUGlwtDba+tw/WcbUoAAzM5AH0AAAAFZAAgAAAAABgTWS3Yap7Q59hii/uPPimHWXsr+DUmsqfwt/X73qsOBXMAIAAAAACKK05liW5KrmEAvtpCB1WUltruzUylDDpjea//UlWoOAVsACAAAAAAcgN4P/wakJ5aJK5c1bvJBqpVGND221dli2YicPFfuAYAAzQwAH0AAAAFZAAgAAAAABOAnBPXDp6i9TISQXvcNKwGDLepZTu3cKrB4vKnSCjBBXMAIAAAAADjjzZO7UowAAvpwyG8BNOVqLCccMFk3aDK4unUeft5ywVsACAAAAAA4zkCd4k9gvfXoD1C7vwTjNcdVJwEARh8h/cxZ4PNMfgAAzQxAH0AAAAFZAAgAAAAAHN8hyvT1lYrAsdiV5GBdd5jhtrAYE/KnSjw2Ka9hjz9BXMAIAAAAAD794JK7EeXBs+D7yOVK7nWF8SbZ/7U8gZ7nnT9JFNwTAVsACAAAAAAg8Wt1HO3NhByq2ggux2a4Lo6Gryr24rEFIqh2acrwWMAAzQyAH0AAAAFZAAgAAAAAO93bPrq8bsnp1AtNd9ETnXIz0lH/2HYN/vuw9wA3fyFBXMAIAAAAABHlls5fbaF2oAGqptC481XQ4eYxInTC29aElfmVZgDUgVsACAAAAAANoQXEWpXJpgrSNK/cKi/m7oYhuSRlp1IZBF0bqTEATcAAzQzAH0AAAAFZAAgAAAAAL1YsAZm1SA0ztU6ySIrQgCCA74V6rr0/4iIygCcaJL6BXMAIAAAAADTXWTHWovGmUR1Zg9l/Aqq9H5mOCJQQrb/Dfae7e3wKAVsACAAAAAA5dunyJK6/SVfDD0t9QlNBcFqoZnf9legRjHaLSKAoQMAAzQ0AH0AAAAFZAAgAAAAAEoFAeHk0RZ9kD+cJRD3j7PcE5gzWKnyBrF1I/MDNp5mBXMAIAAAAACgHtc2hMBRSZjKw8RAdDHK+Pi1HeyjiBuAslGVNcW5tAVsACAAAAAAXzBLfq+GxRtX4Wa9fazA49DBLG6AjZm2XODStJKH8D0AAzQ1AH0AAAAFZAAgAAAAAAW+7DmSN/LX+/0uBVJDHIc2dhxAGz4+ehyyz8fAnNGoBXMAIAAAAAA6Ilw42EvvfLJ3Eq8Afd+FjPoPcQutZO6ltmCLEr8kxQVsACAAAAAAbbZalyo07BbFjPFlYmbmv0z023eT9eLkHqeVUnfUAUAAAzQ2AH0AAAAFZAAgAAAAANBdV7M7kuYO3EMoQItAbXv4t2cIhfaT9V6+s4cg9djlBXMAIAAAAABvz4MIvZWxxrcJCL5qxLfFhXiUYB1OLHdKEjco94SgDgVsACAAAAAAK2GVGvyPIKolF/ECcmfmkVcf1/IZNcaTv96N92yGrkEAAzQ3AH0AAAAFZAAgAAAAAMoAoiAn1kc79j5oPZtlMWHMhhgwNhLUnvqkqIFvcH1NBXMAIAAAAADcJTW7WiCyW0Z9YDUYwppXhLj4Ac1povpJvcAq+i48MQVsACAAAAAAIGxGDzoeB3PTmudl4+j6piQB++e33EEzuzAiXcqGxvUAAzQ4AH0AAAAFZAAgAAAAACI3j5QP7dWHpcT6WO/OhsWwRJNASBYqIBDNzW8IorEyBXMAIAAAAABxUpBSjXwCKDdGP9hYU+RvyR+96kChfvyyRC4jZmztqAVsACAAAAAAvBCHguWswb4X0xdcAryCvZgQuthXzt7597bJ5VxAMdgAAzQ5AH0AAAAFZAAgAAAAAKsbycEuQSeNrF8Qnxqw3x3og8JmQabwGqnDbqzFRVrrBXMAIAAAAACno/3ef2JZJS93SVVzmOZSN+jjJHT8s0XYq2M46d2sLAVsACAAAAAAAt5zLJG+/j4K8rnkFtAn8IvdUVNefe6utJ3rdzgwudIAAzUwAH0AAAAFZAAgAAAAAPXIcoO8TiULqlxzb74NFg+I8kWX5uXIDUPnh2DobIoMBXMAIAAAAADR6/drkdTpnr9g1XNvKDwtBRBdKn7c2c4ZNUVK5CThdQVsACAAAAAAJqOA1c6KVog3F4Hb/GfDb3jCxXDRTqpXWSbMH4ePIJsAAzUxAH0AAAAFZAAgAAAAAEa03ZOJmfHT6/nVadvIw71jVxEuIloyvxXraYEW7u7pBXMAIAAAAADzRlBJK75FLiKjz3djqcgjCLo/e3yntI3MnPS48OORhgVsACAAAAAAnQhx4Rnyj081XrLRLD5NLpWmRWCsd0M9Hl7Jl19R0h8AAzUyAH0AAAAFZAAgAAAAAKx8NLSZUU04pSSGmHa5fh2oLHsEN5mmNMNHL95/tuC9BXMAIAAAAAA59hcXVaN3MNdHoo11OcH1aPRzHCwpVjO9mGfMz4xh3QVsACAAAAAAYIPdjV2XbPj7dBeHPwnwhVU7zMuJ+xtMUW5mIOYtmdAAAzUzAH0AAAAFZAAgAAAAAHNKAUxUqBFNS9Ea9NgCZoXMWgwhP4x0/OvoaPRWMquXBXMAIAAAAABUZ551mnP4ZjX+PXU9ttomzuOpo427MVynpkyq+nsYCQVsACAAAAAALnVK5p2tTTeZEh1zYt4iqKIQT9Z0si//Hy1L85oF+5IAAzU0AH0AAAAFZAAgAAAAALfGXDlyDVcGaqtyHkLT0qpuRhJQLgCxtznazhFtuyn/BXMAIAAAAABipxlXDq14C62pXhwAeen5+syA+/C6bN4rtZYcO4zKwAVsACAAAAAAXUf0pzUq0NhLYagWDap4uEiwq5rLpcx29rWbt1NYMsMAAzU1AH0AAAAFZAAgAAAAANoEr8sheJjg4UCfBkuUzarU9NFoy1xwbXjs5ifVDeA9BXMAIAAAAABPoyTf6M+xeZVGES4aNzVlq7LgjqZXJ/QunjYVusGUEAVsACAAAAAA1hA2gMeZZPUNytk9K+lB1RCqWRudRr7GtadJlExJf8oAAzU2AH0AAAAFZAAgAAAAAKvDiK+xjlBe1uQ3SZTNQl2lClIIvpP/5CHwY6Kb3WlgBXMAIAAAAAANnxImq5MFbWaRBHdJp+yD09bVlcFtiFDYsy1eDZj+iQVsACAAAAAAWtsyO+FxMPSIezwsV1TJD8ZrXAdRnQM6DJ+f+1V3qEkAAzU3AH0AAAAFZAAgAAAAAF49IlFH9RmSUSvUQpEPUedEksrQUcjsOv44nMkwXhjzBXMAIAAAAADJtWGbk0bZzmk20obz+mNsp86UCu/nLLlbg7ppxYn7PgVsACAAAAAA3k0Tj/XgPQtcYijH8cIlQoe/VXf15q1nrZNmg7yWYEgAAzU4AH0AAAAFZAAgAAAAAOuSJyuvz50lp3BzXlFKnq62QkN2quNU1Gq1IDsnFoJCBXMAIAAAAAAqavH1d93XV3IzshWlMnzznucadBF0ND092/2ApI1AcAVsACAAAAAAzUrK4kpoKCmcpdZlZNI13fddjdoAseVe67jaX1LobIIAAzU5AH0AAAAFZAAgAAAAALtgC4Whb4ZdkCiI30zY6fwlsxSa7lEaOAU3SfUXr02XBXMAIAAAAACgdZ6U1ZVgUaZZwbIaCdlANpCw6TZV0bwg3DS1NC/mnAVsACAAAAAAzI49hdpp0PbO7S2KexISxC16sE73EUAEyuqUFAC/J48AAzYwAH0AAAAFZAAgAAAAAF6PfplcGp6vek1ThwenMHVkbZgrc/dHgdsgx1VdPqZ5BXMAIAAAAACha3qhWkqmuwJSEXPozDO8y1ZdRLyzt9Crt2vjGnT7AAVsACAAAAAA7nvcU59+LwxGupSF21jAeAE0x7JE94tjRkJfgM1yKU8AAzYxAH0AAAAFZAAgAAAAAKoLEhLvLjKc7lhOJfx+VrGJCx9tXlOSa9bxQzGR6rfbBXMAIAAAAAAIDK5wNnjRMBzET7x/KAMExL/zi1IumJM92XTgXfoPoAVsACAAAAAAFkUYWFwNr815dEdFqp+TiIozDcq5IBNVkyMoDjharDQAAzYyAH0AAAAFZAAgAAAAADoQv6lutRmh5scQFvIW6K5JBquLxszuygM1tzBiGknIBXMAIAAAAADAD+JjW7FoBQ76/rsECmmcL76bmyfXpUU/awqIsZdO+wVsACAAAAAAPFHdLw3jssmEXsgtvl/RBNaUCRA1kgSwsofG364VOvQAAzYzAH0AAAAFZAAgAAAAAJNHUGAgn56KekghO19d11nai3lAh0JAlWfeP+6w4lJBBXMAIAAAAAD9XGJlvz59msJvA6St9fKW9CG4JoHV61rlWWnkdBRLzwVsACAAAAAAxwP/X/InJJHmrjznvahIMgj6pQR30B62UtHCthSjrP0AAzY0AH0AAAAFZAAgAAAAAHgYoMGjEE6fAlAhICv0+doHcVX8CmMVxyq7+jlyGrvmBXMAIAAAAAC/5MQZgTHuIr/O5Z3mXPvqrom5JTQ8IeSpQGhO9sB+8gVsACAAAAAAuPSXVmJUAUpTQg/A9Bu1hYczZF58KEhVofakygbsvJQAAzY1AH0AAAAFZAAgAAAAANpIljbxHOM7pydY877gpRQvYY2TGK7igqgGsavqGPBABXMAIAAAAAAqHyEu9gpurPOulApPnr0x9wrygY/7mXe9rAC+tPK80wVsACAAAAAA7gkPzNsS3gCxdFBWbSW9tkBjoR5ib+saDvpGSB3A3ogAAzY2AH0AAAAFZAAgAAAAAGR+gEaZTeGNgG9BuM1bX2R9ed4FCxBA9F9QvdQDAjZwBXMAIAAAAABSkrYFQ6pf8MZ1flgmeIRkxaSh/Eep4Btdx4QYnGGnwAVsACAAAAAApRovMiV00hm/pEcT4XBsyPNw0eo8RLAX/fuabjdU+uwAAzY3AH0AAAAFZAAgAAAAAFNprhQ3ZwIcYbuzLolAT5n/vc14P9kUUQComDu6eFyKBXMAIAAAAAAcx9z9pk32YbPV/sfPZl9ALIEVsqoLXgqWLVK/tP+heAVsACAAAAAA/qxvuvJbAHwwhfrPVpmCFzNvg2cU/NXaWgqgYUZpgXwAAzY4AH0AAAAFZAAgAAAAADgyPqQdqQrgfmJjRFAILTHzXbdw5kpKyfeoEcy6YYG/BXMAIAAAAAAE+3XsBQ8VAxAkN81au+f3FDeCD/s7KoZD+fnM1MJSSAVsACAAAAAAhRnjrXecwV0yeCWKJ5J/x12Xx4qVJahsCEVHB/1U2rcAAzY5AH0AAAAFZAAgAAAAAI0CT7JNngTCTUSei1Arw7eHWCD0jumv2rb7imjWIlWABXMAIAAAAABSP8t6ya0SyCphXMwnru6ZUDXWElN0NfBvEOhDvW9bJQVsACAAAAAAGWeGmBNDRaMtvm7Rv+8TJ2sJ4WNXKcp3tqpv5Se9Ut4AAzcwAH0AAAAFZAAgAAAAAD/FIrGYFDjyYmVb7oTMVwweWP7A6F9LnyIuNO4MjBnXBXMAIAAAAACIZgJCQRZu7NhuNMyOqCn1tf+DfU1qm10TPCfj5JYV3wVsACAAAAAA5hmY4ptuNxULGf87SUFXQWGAONsL9U29duh8xqsHtxoAAzcxAH0AAAAFZAAgAAAAAHIkVuNDkSS1cHIThKc/O0r2/ubaABTOi8Q1r/dvBAsEBXMAIAAAAADdHYqchEiJLM340c3Q4vJABmmth3+MKzwLYlsG6GS7sQVsACAAAAAADa+KP/pdTiG22l+ZWd30P1iHjnBF4zSNRdFm0oEK82kAAzcyAH0AAAAFZAAgAAAAAJmoDILNhC6kn3masElfnjIjP1VjsjRavGk1gSUIjh1NBXMAIAAAAAD97Ilvp3XF8T6MmVVcxMPcdL80RgQ09UoC6PnoOvZ1IQVsACAAAAAA2RK3Xng6v8kpvfVW9tkVXjpE+BSnx9/+Fw85Evs+kUEAAzczAH0AAAAFZAAgAAAAAI5bm3YO0Xgf0VT+qjVTTfvckecM3Cwqj7DTKZXf8/NXBXMAIAAAAAD/m+h8fBhWaHm6Ykuz0WX1xL4Eme3ErLObyEVJf8NCywVsACAAAAAAfb1VZZCqs2ivYbRzX4p5CtaCkKW+g20Pr57FWXzEZi8AAzc0AH0AAAAFZAAgAAAAANqo4+p6qdtCzcB4BX1wQ6llU7eFBnuu4MtZwp4B6mDlBXMAIAAAAAAGiz+VaukMZ+6IH4jtn4KWWdKK4/W+O+gRioQDrfzpMgVsACAAAAAAG4YYkTp80EKo59mlHExDodRQFR7njhR5dmISwUJ6ukAAAzc1AH0AAAAFZAAgAAAAAPrFXmHP2Y4YAm7b/aqsdn/DPoDkv7B8egWkfe23XsM1BXMAIAAAAAAGhwpKAr7skeqHm3oseSbO7qKNhmYsuUrECBxJ5k+D2AVsACAAAAAAAqPQi9luYAu3GrFCEsVjd9z2zIDcp6SPTR2w6KQEr+IAAzc2AH0AAAAFZAAgAAAAABzjYxwAjXxXc0Uxv18rH8I3my0Aguow0kTwKyxbrm+cBXMAIAAAAADVbqJVr6IdokuhXkEtXF0C2gINLiAjMVN20lE20Vmp2QVsACAAAAAAD7K1Fx4gFaaizkIUrf+EGXQeG7QX1jadhGc6Ji471H8AAzc3AH0AAAAFZAAgAAAAAFMm2feF2fFCm/UC6AfIyepX/xJDSmnnolQIBnHcPmb5BXMAIAAAAABLI11kFrQoaNVZFmq/38aRNImPOjdJh0Lo6irI8M/AaAVsACAAAAAAOWul0oVqJ9CejD2RqphhTC98DJeRQy5EwbNerU2+4l8AAzc4AH0AAAAFZAAgAAAAAJvXB3KyNiNtQko4SSzo/9b2qmM2zU9CQTTDfLSBWMgRBXMAIAAAAAAvjuVP7KsLRDeqVqRziTKpBrjVyqKiIbO9Gw8Wl2wFTAVsACAAAAAADlE+oc1ins+paNcaOZJhBlKlObDJ4VQORWjFYocM4LgAAzc5AH0AAAAFZAAgAAAAAPGdcxDiid8z8XYnfdDivNMYVPgBKdGOUw6UStU+48CdBXMAIAAAAAARj6g1Ap0eEfuCZ4X2TsEw+Djrhto3fA5nLwPaY0vCTgVsACAAAAAAoHqiwGOUkBu8SX5U1yHho+UIFdSN2MdQN5s6bQ0EsJYAAzgwAH0AAAAFZAAgAAAAAP5rGPrYGt3aKob5f/ldP0qrW7bmWvqnKY4QwdDWz400BXMAIAAAAADTQkW2ymaaf/bhteOOGmSrIR97bAnJx+yN3yMj1bTeewVsACAAAAAADyQnHGH2gF4w4L8axUsSTf6Ubk7L5/eoFOJk12MtZAoAAzgxAH0AAAAFZAAgAAAAAAlz6wJze5UkIxKpJOZFGCOf3v2KByWyI6NB6JM9wNcBBXMAIAAAAABUC7P/neUIHHoZtq0jFVBHY75tSFYr1Y5S16YN5XxC1QVsACAAAAAAgvxRbXDisNnLY3pfsjDdnFLtkvYUC4lhA68eBXc7KAwAAzgyAH0AAAAFZAAgAAAAAFJ8AtHcjia/9Y5pLEc3qVgH5xKiXw12G9Kn2A1EY8McBXMAIAAAAAAxe7Bdw7eUSBk/oAawa7uicTEDgXLymRNhBy1LAxhDvwVsACAAAAAAxKPaIBKVx3jTA+R/el7P7AZ7efrmTGjJs3Hj/YdMddwAAzgzAH0AAAAFZAAgAAAAAO8uwQUaKFb6vqR3Sv3Wn4QAonC2exOC9lGG1juqP5DtBXMAIAAAAABZf1KyJgQg8/Rf5c02DgDK2aQu0rNCOvaL60ohDHyY+gVsACAAAAAAqyEjfKC8lYoIfoXYHUqHZPoaA6EK5BAZy5dxXZmay4kAAzg0AH0AAAAFZAAgAAAAAE8YtqyRsGCeiR6hhiyisR/hccmK4nZqIMzO4lUBmEFzBXMAIAAAAAC1UYOSKqAeG1UJiKjWFVskRhuFKpj9Ezy+lICZvFlN5AVsACAAAAAA6Ct9nNMKyRazn1OKnRKagm746CGu+jyhbL1qJnZxGi0AAzg1AH0AAAAFZAAgAAAAAPhCrMausDx1QUIEqp9rUdRKyM6a9AAx7jQ3ILIu8wNIBXMAIAAAAACmH8lotGCiF2q9VQxhsS+7LAZv79VUAsOUALaGxE/EpAVsACAAAAAAnc1xCKfdvbUEc8F7XZqlNn1C+hZTtC0I9I3LL06iaNkAAzg2AH0AAAAFZAAgAAAAAOBi/GAYFcstMSJPgp3VkMiuuUUCrZytvqYaU8dwm8v2BXMAIAAAAACEZSZVyD3pKzGlbdwlYmWQhHHTV5SnNLknl2Gw8IaUTQVsACAAAAAAfsLZsEDcWSuNsIo/TD1ReyQW75HPMgmuKZuWFOLKRLoAAzg3AH0AAAAFZAAgAAAAAIQuup+YGfH3mflzWopN8J1X8o8a0d9CSGIvrA5HOzraBXMAIAAAAADYvNLURXsC2ITMqK14LABQBI+hZZ5wNf24JMcKLW+84AVsACAAAAAACzfjbTBH7IwDU91OqLAz94RFkoqBOkzKAqQb55gT4/MAAzg4AH0AAAAFZAAgAAAAAKsh0ADyOnVocFrOrf6MpTrNvAj8iaiE923DPryu124gBXMAIAAAAADg24a8NVE1GyScc6tmnTbmu5ulzO+896fE92lN08MeswVsACAAAAAAaPxcOIxnU7But88/yadOuDJDMcCywwrRitaxMODT4msAAzg5AH0AAAAFZAAgAAAAAKkVC2Y6HtRmv72tDnPUSjJBvse7SxLqnr09/Uuj9sVVBXMAIAAAAABYNFUkH7ylPMN+Bc3HWX1e0flGYNbtJNCY9SltJCW/UAVsACAAAAAAZYK/f9H4OeihmpiFMH7Wm7uLvs2s92zNA8wyrNZTsuMAAzkwAH0AAAAFZAAgAAAAADDggcwcb/Yn1Kk39sOHsv7BO/MfP3m/AJzjGH506Wf9BXMAIAAAAAAYZIsdjICS0+BDyRUPnrSAZfPrwtuMaEDEn0/ijLNQmAVsACAAAAAAGPnYVvo2ulO9z4LGd/69NAklfIcZqZvFX2KK0s+FcTUAAzkxAH0AAAAFZAAgAAAAAEWY7dEUOJBgjOoWVht1wLehsWAzB3rSOBtLgTuM2HC8BXMAIAAAAAAAoswiHRROurjwUW8u8D5EUT+67yvrgpB/j6PzBDAfVwVsACAAAAAA6NhRTYFL/Sz4tao7vpPjLNgAJ0FX6P/IyMW65qT6YsMAAzkyAH0AAAAFZAAgAAAAAPZaapeAUUFPA7JTCMOWHJa9lnPFh0/gXfAPjA1ezm4ZBXMAIAAAAACmJvLY2nivw7/b3DOKH/X7bBXjJwoowqb1GtEFO3OYgAVsACAAAAAA/JcUoyKacCB1NfmH8vYqC1f7rd13KShrQqV2r9QBP44AAzkzAH0AAAAFZAAgAAAAAK00u6jadxCZAiA+fTsPVDsnW5p5LCr4+kZZZOTDuZlfBXMAIAAAAAAote4zTEYMDgaaQbAdN8Dzv93ljPLdGjJzvnRn3KXgtQVsACAAAAAAxXd9Mh6R3mnJy8m7UfqMKi6oD5DlZpkaOz6bEjMOdiwAAzk0AH0AAAAFZAAgAAAAAFbgabdyymiEVYYwtJSWa7lfl/oYuj/SukzJeDOR6wPVBXMAIAAAAADAFGFjS1vPbN6mQEhkDYTD6V2V23Ys9gUEUMGNvMPkaAVsACAAAAAAL/D5Sze/ZoEanZLK0IeEkhgVkxEjMWVCfmJaD3a8uNIAAzk1AH0AAAAFZAAgAAAAABNMR6UBv2E627CqLtQ/eDYx7OEwQ7JrR4mSHFa1N8tLBXMAIAAAAAAxH4gucI4UmNVB7625C6hFSVCuIpJO3lusJlPuL8H5EQVsACAAAAAAVLHNg0OUVqZ7WGOP53BkTap9FOw9dr1P4J8HxqFqU04AAzk2AH0AAAAFZAAgAAAAAG8cd6WBneNunlqrQ2EmNf35W7OGObGq9WL4ePX+LUDmBXMAIAAAAAAjJ2+sX87NSis9hBsgb1QprVRnO7Bf+GObCGoUqyPE4wVsACAAAAAAs9c9SM49/pWmyUQKslpt3RTMBNSRppfNO0JBvUqHPg0AAzk3AH0AAAAFZAAgAAAAAFWOUGkUpy8yf6gB3dio/aOfRKh7XuhvsUj48iESFJrGBXMAIAAAAAAY7sCDMcrUXvNuL6dO0m11WyijzXZvPIcOKob6IpC4PQVsACAAAAAAJOP+EHz6awDb1qK2bZQ3kTV7wsj5Daj/IGAWh4g7omAAAzk4AH0AAAAFZAAgAAAAAGUrIdKxOihwNmo6B+aG+Ag1qa0+iqdksHOjQj+Oy9bZBXMAIAAAAABwa5dbI2KmzBDNBTQBEkjZv4sPaeRkRNejcjdVymRFKQVsACAAAAAA4ml/nm0gJNTcJ4vuD+T2Qfq2fQZlibJp/j6MOGDrbHMAAzk5AH0AAAAFZAAgAAAAAOx89xV/hRk64/CkM9N2EMK6aldII0c8smdcsZ46NbP8BXMAIAAAAADBF6tfQ+7q9kTuLyuyrSnDgmrdmrXkdhl980i1KHuGHgVsACAAAAAACUqiFqHZdGbwAA+hN0YUE5zFg+H+dabIB4dj5/75W/YAAzEwMAB9AAAABWQAIAAAAADJDdC9aEFl4Y8J/awHbnXGHjfP+VXQilPHJg7ewaJI7AVzACAAAAAAE+tqRl6EcBMXvbr4GDiNIYObTsYpa1n6BJk9EjIJVicFbAAgAAAAAJVc+HYYqa0m1Hq6OiRX8c0iRnJYOt6AJAJoG0sG3GMSAAMxMDEAfQAAAAVkACAAAAAA3F9rjEKhpoHuTULVGgfUsGGwJs3bISrXkFP1v6KoQLgFcwAgAAAAAIBf0tXw96Z/Ds0XSIHX/zk3MzUR/7WZR/J6FpxRWChtBWwAIAAAAABWrjGlvKYuTS2s8L9rYy8Hf0juFGJfwQmxVIjkTmFIGQADMTAyAH0AAAAFZAAgAAAAAOYIYoWkX7dGuyKfi3XssUlc7u/gWzqrR9KMkikKVdmSBXMAIAAAAABVF2OYjRTGi9Tw8XCAwZWLpX35Yl271TlNWp6N/nROhAVsACAAAAAA0nWwYzXQ1+EkDvnGq+SMlq20z+j32Su+i/A95SggPb4AAzEwMwB9AAAABWQAIAAAAACMtPm12YtdEAvqu6Eji1yuRXnu1RJP6h0l7pH3lSH4MwVzACAAAAAAENyCFfyUAh1veQBGx+cxiB7Sasrj41jzCGflZkB5cRMFbAAgAAAAAKdI2LMqISr/T5vuJPg6ZRBm5fVi2aQCc4ra3A4+AjbDAAMxMDQAfQAAAAVkACAAAAAAvlI4lDcs6GB1cnm/Tzo014CXWqidCdyE5t2lknWQd4QFcwAgAAAAAD60SpNc4O2KT7J0llKdSpcX1/Xxs97N715a1HsTFkmBBWwAIAAAAABuuRkJWAH1CynggBt1/5sPh9PoGiqTlS24D/OE2uHXLQADMTA1AH0AAAAFZAAgAAAAAKl8zcHJRDjSjJeV/WvMxulW1zrTFtaeBy/aKKhadc6UBXMAIAAAAADBdWQl5SBIvtZZLIHszePwkO14W1mQ0izUk2Ov21cPNAVsACAAAAAAHErCYycpqiIcCZHdmPL1hi+ovLQk4TAvENpfLdTRamQAAzEwNgB9AAAABWQAIAAAAABb6LXDWqCp1beQgQjj8I3sRTtFhlrmiBi+h/+ikmrvugVzACAAAAAA9stpgTecT7uTyaGNs3K9Bp0A7R0QaIAOfscyMXHBPX8FbAAgAAAAAHUt+McyXrJ1H8SwnHNVO181Ki8vDAM1f7XI26mg95ZDAAMxMDcAfQAAAAVkACAAAAAA97NTT+81PhDhgptNtp4epzA0tP4iNb9j1AWkiiiKGM8FcwAgAAAAAKPbHg7ise16vxmdPCzksA/2Mn/qST0L9Xe8vnQugVkcBWwAIAAAAABB0EMXfvju4JU/mUH/OvxWbPEl9NJkcEp4iCbkXI41fAADMTA4AH0AAAAFZAAgAAAAAMqpayM2XotEFmm0gwQd9rIzApy0X+7HfOhNk6VU7F5lBXMAIAAAAACJR9+q5T9qFHXFNgGbZnPubG8rkO6cwWhzITQTmd6VgwVsACAAAAAAOZLQ6o7e4mVfDzbpQioa4d3RoTvqwgnbmc5Qh2wsZuoAAzEwOQB9AAAABWQAIAAAAADQnslvt6Hm2kJPmqsTVYQHE/wWeZ4bE1XSkt7TKy0r1gVzACAAAAAA8URTA4ZMrhHPvlp53TH6FDCzS+0+61qHm5XK6UiOrKEFbAAgAAAAAHQbgTCdZcbdA0avaTmZXUKnIS7Nwf1tNrcXDCw+PdBRAAMxMTAAfQAAAAVkACAAAAAAhujlgFPFczsdCGXtQ/002Ck8YWQHHzvWvUHrkbjv4rwFcwAgAAAAALbV0lLGcSGfE7mDM3n/fgEvi+ifjl7WZ5b3aqjDNvx9BWwAIAAAAACbceTZy8E3QA1pHmPN5kTlOx3EO8kJM5PUjTVftw1VpgADMTExAH0AAAAFZAAgAAAAABm/6pF96j26Jm7z5KkY1y33zcAEXLx2n0DwC03bs/ixBXMAIAAAAAD01OMvTZI/mqMgxIhA5nLs068mW+GKl3OW3ilf2D8+LgVsACAAAAAAaLvJDrqBESTNZSdcXsd+8GXPl8ZkUsGpeYuyYVv/kygAAzExMgB9AAAABWQAIAAAAACfw9/te4GkHZAapC9sDMHHHZgmlTrccyJDPFciOMSOcwVzACAAAAAAIIC1ZpHObvmMwUfqDRPl4C1aeuHwujM1G/yJbvybMNAFbAAgAAAAAAs9x1SnVpMfNv5Bm1aXGwHmbbI9keWa9HRD35XuCBK5AAMxMTMAfQAAAAVkACAAAAAAkxHJRbnShpPOylLoDdNShfILeA1hChKFQY9qQyZ5VmsFcwAgAAAAAKidrY+rC3hTY+YWu2a7fuMH2RD/XaiTIBW1hrxNCQOJBWwAIAAAAACW0kkqMIzIFMn7g+R0MI8l15fr3k/w/mHtY5n6SYTEwAADMTE0AH0AAAAFZAAgAAAAAByuYl8dBvfaZ0LO/81JW4hYypeNmvLMaxsIdvqMPrWoBXMAIAAAAABNddwobOUJzm9HOUD8BMZJqkNCUCqstHZkC76FIdNg9AVsACAAAAAAQQOkIQtkyNavqCnhQbNg3HfqrJdsAGaoxSJePJl1qXsAAzExNQB9AAAABWQAIAAAAABxMy7X5hf7AXGDz3Y/POu1ZpkMlNcSvSP92NOO/Gs7wAVzACAAAAAAHJshWo2T5wU2zvqCyJzcJQKQaHFHpCpMc9oWBXkpUPoFbAAgAAAAAGeiJKzlUXAvL0gOlW+Hz1mSa2HsV4RGmyLmCHlzbAkoAAMxMTYAfQAAAAVkACAAAAAAlqbslixl7Zw3bRlibZbe/WmKw23k8uKeIzPKYEtbIy0FcwAgAAAAAHEKwpUxkxOfef5HYvulXPmdbzTivwdwrSYIHDeNRcpcBWwAIAAAAADuPckac21Hrg/h0kt5ShJwVEZ9rx6SOHd2+HDjqxEWTQADMTE3AH0AAAAFZAAgAAAAAMXrXx0saZ+5gORmwM2FLuZG6iuO2YS+1IGPoAtDKoKBBXMAIAAAAADIQsxCr8CfFKaBcx8kIeSywnGh7JHjKRJ9vJd9x79y7wVsACAAAAAAcvBV+SykDYhmRFyVYwFYB9oBKBSHr55Jdz2cXeowsUQAAzExOAB9AAAABWQAIAAAAAAm83FA9yDUpwkbKTihe7m53u+DivS9BU2b4vQMtCVQ2AVzACAAAAAAz3m1UB/AbZPa4QSKFDnUgHaT78+6iGOFAtouiBorEgEFbAAgAAAAAIgbpyYtJj5513Z5XYqviH/HXG/5+mqR52iBbfqMmDtZAAMxMTkAfQAAAAVkACAAAAAAJRzYK0PUwr9RPG2/7yID0WgcTJPB2Xjccp5LAPDYunkFcwAgAAAAAIIh24h3DrltAzNFhF+MEmPrZtzr1PhCofhChZqfCW+jBWwAIAAAAAAzRNXtL5o9VXMk5D5ylI0odPDJDSZZry1wfN+TedH70gADMTIwAH0AAAAFZAAgAAAAAHSaHWs/dnmI9sc7nB50VB2Bzs0kHapMHCQdyVEYY30TBXMAIAAAAACkV22lhEjWv/9/DubfHBAcwJggKI5mIbSK5L2nyqloqQVsACAAAAAAS19m7DccQxgryOsBJ3GsCs37yfQqNi1G+S6fCXpEhn4AAzEyMQB9AAAABWQAIAAAAAAC/I4TQRtCl12YZmdGz17X4GqSQgfwCPgRBwdHmdwu+QVzACAAAAAAx8f3z2ut/RAZhleari4vCEE+tNIn4ikjoUwzitfQ588FbAAgAAAAAJci0w1ZB8W2spJQ+kMpod6HSCtSR2jrabOH+B0fj3A4AAMxMjIAfQAAAAVkACAAAAAADGB5yU2XT0fse/MPWgvBvZikVxrl5pf3S5K1hceKWooFcwAgAAAAAIxTmlLHMjNaVDEfJbXvRez0SEPWFREBJCT6qTHsrljoBWwAIAAAAAAlswzAl81+0DteibwHD+CG5mZJrfHXa9NnEFRtXybzzwADMTIzAH0AAAAFZAAgAAAAABmO7QD9vxWMmFjIHz13lyOeV6vHT6mYCsWxF7hb/yOjBXMAIAAAAACT9lmgkiqzuWG24afuzYiCeK9gmJqacmxAruIukd0xEAVsACAAAAAAZa0/FI/GkZR7CtX18Xg9Tn9zfxkD0UoaSt+pIO5t1t4AAzEyNAB9AAAABWQAIAAAAAAfPUoy7QyZKhIIURso+mkP9qr1izbjETqF5s22GwjCjAVzACAAAAAAvLMsIDQ/go4VUxeh50UHmsvMvfx51cwyONnRD2odvC0FbAAgAAAAAKMb+1CodEalAFnDrEL1Ndt8ztamZ+9134m9Kp3GQgd+AAMxMjUAfQAAAAVkACAAAAAAE3ZqUar0Bq2zWbARE0bAv98jBlK9UJ73/xcwdMWWlSkFcwAgAAAAAK4M+MmC+9sFiFsumMyJZQKxWmmJiuG9H7IzKw083xxkBWwAIAAAAAAqkAONzhvMhkyL1D/6h7QQxEkdhC3p2WjXH+VGq5qCqQADMTI2AH0AAAAFZAAgAAAAAMo8FJiOq63cAmyk2O7eI7GcbQh/1j4RrMTqly3rexftBXMAIAAAAADjVmpd0WiRGTw/gAqEgGolt2EI7Csv14vKdmYoMD0aAgVsACAAAAAA07XQBzBUQMNw7F2/YxJjZNuPVpHTTgbLd1oGk77+bygAAzEyNwB9AAAABWQAIAAAAACu5IGaIx7A3Jvly/kzlCsSA4s3iJwuIl8jEdRH0k93NwVzACAAAAAA9NRUyxYE+t0Xyosyt6vIfMFW/vBoYg6sR+jBNs4JAxIFbAAgAAAAAAzyZ91dx+0oMlOVAjRGiMrPySikY/U9eMEB4WJb3uWtAAMxMjgAfQAAAAVkACAAAAAALkRy0GJInXYLA+cgjs6Myb0a+Gu9hgXhHvhLNoGWfckFcwAgAAAAANbALyt9zCSvwnLaWCd2/y2eoB7qkWTvv1Ldu8r40JPuBWwAIAAAAAD4Fl5bV5sz4isIE9bX+lmAp+aAKaZgVYVZeVfrItkCZAADMTI5AH0AAAAFZAAgAAAAAGoUK/DSWhT8LZhszSUqDbTrp8cSA7rdqmADKL+MILtTBXMAIAAAAABHnEE9bVa6lvhfhEMkkV2kzSSxH/sMW/FIJuw3CzWs6wVsACAAAAAAanavcBdqZxgRGKvEK95wTmeL1K1CeDSXZsXUAs81uOgAAzEzMAB9AAAABWQAIAAAAAC922ZDQE3h2fQKibGMZ9hV0WNlmrPYYSdtaSyYxsWYqgVzACAAAAAAagMovciKK6WVjIc2cCj8nK5O/gVOFFVeVAJpRp89tmQFbAAgAAAAAKcTFfPQzaFiAtSFhqbN02sCE1BKWJSrRfGN5L6oZwzkAAMxMzEAfQAAAAVkACAAAAAAtK+JqX3K/z2txjAU15DgX4y90DS2YLfIJFolCOkJJJwFcwAgAAAAAMnR5V7gfX7MNqqUdL5AkWlkhyFXaBRVNej+Rcn8lrQkBWwAIAAAAAA2cDNRXZuiC241TGRvdFyctJnrNcdbZOP9zHio81tkngADMTMyAH0AAAAFZAAgAAAAAAeGrIMK/bac6kPczxbvRYqKMkcpeI2FjdMpD91FDWIvBXMAIAAAAAAix62z1LeS8yvSXCl5gHSIomjyx76fF3S1lp9k900hygVsACAAAAAAiYwzf2m71aWFD5ajcXyW2JX2EzQOkBroTGMg29nLPYIAAzEzMwB9AAAABWQAIAAAAACphf298InM0Us4HT8o1W1MGw0D/02vd7Jh+U0h7qaFaQVzACAAAAAAFXtk7YpqsOJxsqGWSIL+YcBE96G3Zz9D31gPqDW94y8FbAAgAAAAAAOrS1KVA94rjB1jZ1pPocpCeBG+B14RzWoHqVDpp7JbAAMxMzQAfQAAAAVkACAAAAAATLDS2cuDVM3yDMuWNgk2iGKBTzPpfJMbvxVOSY39ZfcFcwAgAAAAAPT5wRi2cLHIUflXzm6EQB/m7xdThP80ir1VV/JBBqvxBWwAIAAAAAB9lEtZS0aXCFbCtSbhnis27S5IPcfWGygHW8AHn3QqzwADMTM1AH0AAAAFZAAgAAAAAJNjExiZVX7jfFGfYpQu16qxLN0YPqVU/5CQ/Y67YSinBXMAIAAAAABMpm2+6KrkRUlXzQoMPHrQmIO6dkQz66tYdfTeA3dKqQVsACAAAAAAFXobHiMLvNZuEPr8jtewCX2J93EZG3JNeyVg92fue6YAAzEzNgB9AAAABWQAIAAAAABlFkYtLCx901X6QVVMkSn6Z7k30UF4xHaA0OZJJ9bdyQVzACAAAAAATez+F9GHcGzTp7jjv4feboUNb8JCkIp4EqcPFisnq7MFbAAgAAAAACE7JvOpBgMoZ7kRd4QbxIhxukPTUxXpzhjnBHiR7XoRAAMxMzcAfQAAAAVkACAAAAAA8NJKN0IxZnruhswGQkiruv8Ih0EMwDcSZx/Xasup9dkFcwAgAAAAAKaJZRxzA+Igeydvuk6cSwUHXcrmT4PjhuPu//FslpdnBWwAIAAAAAD53Rok1Vq/PMAnXmarqoHJ0PEyYUBmVESa9hIpCv/G9QADMTM4AH0AAAAFZAAgAAAAABHxHdEClz7hbSSgE58+dWLlSMJnoPz+jFxp4bB1GmLQBXMAIAAAAAD3nSvT6aGD+A110J/NwEfp0nPutlmuB5B+wA3CC3noGAVsACAAAAAA3Apjd+TapONB7k5wBVwTWgn8t+Sq2oyyU5/+as109RcAAzEzOQB9AAAABWQAIAAAAAC/o8qW/ifk3KuJ01VFkyNLgQafxB5/bGs2G5VyyVafOwVzACAAAAAA1bMqAFGDHSl6BYNLbxApvkAv2K1/oafywiX0MDz1dGUFbAAgAAAAAHJXLlId3edFoniLD/9K2A5973MeP2Ro31flDyqm3l5QAAMxNDAAfQAAAAVkACAAAAAAY2V8I1bz3a1AxTtmED6UhdhA09huFkuuEX8R+d/WDPUFcwAgAAAAAPTVoNRiI76tcRKqd+JBBVyy4+YcKST42p0QX2BtmQ2VBWwAIAAAAACcxt9hg14WqPNiDv1MkqVljM2e2KJEv53lA17LhV6ZigADMTQxAH0AAAAFZAAgAAAAAO2kSsW0WGN9AOtK4xK2SHrGhWiaAbMEKT4iZkRpaDN/BXMAIAAAAABKGzQcPM8LT2dwOggxoWjv/1imYWabbG/G4kBw8OWaxAVsACAAAAAAC9hLK1dScQTAqg+YAG3ObdPzg2Xet57HmOFpGmyUR9UAAzE0MgB9AAAABWQAIAAAAAAiCwzNEEaH/mDam68IdDftnhthyUFdb+ZCNSBQ91WlHQVzACAAAAAA7tHyHcxCzmbJeFYZyPm4mEgkTGKOvwY4MX82OvH0Jn8FbAAgAAAAAAb5IAbZ1hXCNegQ+S+C9i/Z8y6sS8KeU04V6hXa2ml6AAMxNDMAfQAAAAVkACAAAAAAGuCHVNJSuoVkpPOnS5s89GuA+BLi2IPBUr2Bg1sWEPIFcwAgAAAAAEl1gncS5/xO7bQ/KQSstRV3rOT2SW6nV92ZANeG2SR6BWwAIAAAAAA9LOcKmhek8F2wAh8yvT/vjp2gaouuO+Hmv10lwAeWPAADMTQ0AH0AAAAFZAAgAAAAAMfxz7gEaoCdPvXrubDhCZUS0ARLZc1svgbXgMDlVBPgBXMAIAAAAAB6a5dDA3fuT5Vz2KvAcbUEFX/+B7Nw2p1QqbPoQ5TTuAVsACAAAAAAcf/y75UOuI62A6vWH7bYr/5Jz+nirZVYK/81trN6XOQAAzE0NQB9AAAABWQAIAAAAACnYsqF/VzmjIImC9+dqrHO1TM6lJ6fRwM0mM6Wf6paOwVzACAAAAAA5tgZzch8uDCR1ky3SllVaKVpxAlbrhvlNDTazZZRZOAFbAAgAAAAALeGiLJS4z2zhgVpxzyPdRYyACP9QzQBOob34YrIZumCAAMxNDYAfQAAAAVkACAAAAAAEC0sIVmadtW4YMuRXH7RpAhXclsd+3bmqGXCMeaT014FcwAgAAAAABPpXh0uzpsJJB+IRUNajmMB9WGwswfpw5T9xk3Xj6ANBWwAIAAAAAAmf+NYh9TZ/QRu3w/GQz66n7DtfbJijN3G7KzeL8lstAADMTQ3AH0AAAAFZAAgAAAAABaIB3n49Xm9cOafSrQsE0WCcYp8rMIO/qVwIlMF5YLRBXMAIAAAAAC9EyWJV3xOu9bzgdJ/yX+ko7qLf1u3AxNMataW2C9EzQVsACAAAAAAvVbDkLxXx2DcMLifIQ3K0IIJcLcAG9DUrNfI6aoUjNcAAzE0OAB9AAAABWQAIAAAAAA5rZItA/cocRnngYqcJ3nBXQ+l688aKz3EQyLbYYunPAVzACAAAAAAwKyA+L7TgxztPClLrIMk2JXR+w7c04N3ZOqPgjvrIvsFbAAgAAAAACzvZ33h6aWEe8hmo+1f6OXJ72FY5hvWaUuha64ZV3KFAAMxNDkAfQAAAAVkACAAAAAA3htn7oHJ0YYpIrs+Mzyh85Ys67HwAdv5LQl1mCdoMWkFcwAgAAAAAEHjCtNNLenHuSIYux6ezAHsXDaj2DlTF67ToDhDDe6HBWwAIAAAAAD+P4H0sk9jOd+7vOANt2/1Ectb+4ZRGPE8GkHWNXW3MgADMTUwAH0AAAAFZAAgAAAAAEnt18Km/nqggfIJWxzTr9r3hnXNaueG6XO9A5G11LnGBXMAIAAAAAD7QxzGMN/ard5TfFLecE6uusMmXG2+RBsBR+/NCQHUwAVsACAAAAAAQEZ1ZZ8GC8rdbg7s87OM5Gr9qkTXS9+P5DuAZxj5Gl4AAzE1MQB9AAAABWQAIAAAAAAVAKK/GoY8AACu/hyMpO4hdLq6JnEyWNzkyci9sbaD/wVzACAAAAAA2HmeqpMlvvBpV2zQTYIRmsc4MFlfHRwLof0ycJgMg/MFbAAgAAAAACdltCeWi5E/q1Li1eXLChpM2D9QQSGLBZ82NklQSc0oAAMxNTIAfQAAAAVkACAAAAAAhHyq1GQC/GiMwpYjcsfkNxolJ10ARKjIjfkW1Wipzi0FcwAgAAAAAD/uaGWxTDq87F8XZ6CrFI+RNa8yMqfSZdqK00Kj833BBWwAIAAAAAD6aEdOO0CsQGagioOCvANPCEHSpJ8BSixlPBq5ERhB7AADMTUzAH0AAAAFZAAgAAAAABAJJxHoZD+MQBWqm9UM9Dd3z5ZohIZGWRaRVRsMptKQBXMAIAAAAADrE/ca+gqj/SH4oao4wE4qn2ovoTydzcMbDbrfnUs3zAVsACAAAAAAeNCIQN6hVnGJinytQRFGlQ2ocoprXNqpia+BSxzl+uwAAzE1NAB9AAAABWQAIAAAAAAv01wz7VG9mTepjXQi6Zma+7b/OVBaKVkWNbgDLr1mFgVzACAAAAAA0I5sxz8r6wkCp5Tgvr+iL4p6MxSOq5d3e1kZG+0b7NkFbAAgAAAAAIA32v6oGkAOS96HexGouNTex+tLahtx9QF2dgGClk6WAAMxNTUAfQAAAAVkACAAAAAAWXecRwxSon68xaa9THXnRDw5ZfzARKnvvjTjtbae6T0FcwAgAAAAAPh0UfUMEo7eILCMv2tiJQe1bF9qtXq7GJtC6H5Va4fIBWwAIAAAAADqFr1ThRrTXNgIOrJWScO9mk86Ufi95IDu5gi4vP+HWQADMTU2AH0AAAAFZAAgAAAAAEY5WL8/LpX36iAB1wlQrMO/xHVjoO9BePVzbUlBYo+bBXMAIAAAAABoKcpadDXUARedDvTmzUzWPe1jTuvD0z9oIcZmKuiSXwVsACAAAAAAJuJbwuaMrAFoI+jU/IYr+k4RzAqITrOjAd3HWCpJHqEAAzE1NwB9AAAABWQAIAAAAADnJnWqsfx0xqNnqfFGCxIplVu8mXjaHTViJT9+y2RuTgVzACAAAAAAWAaSCwIXDwdYxWf2NZTly/iKVfG/KDjHUcA1BokN5sMFbAAgAAAAAJVxavipE0H4/JQvhagdytXBZ8qGooeXpkbPQ1RfYMVHAAMxNTgAfQAAAAVkACAAAAAAsPG7LaIpJvcwqcbtfFUpIjj+vpNj70Zjaw3eV9T+QYsFcwAgAAAAAJQ71zi0NlCyY8ZQs3IasJ4gB1PmWx57HpnlCf3+hmhqBWwAIAAAAACD58TO6d+71GaOoS+r73rAxliAO9GMs4Uc8JbOTmC0OwADMTU5AH0AAAAFZAAgAAAAAAGiSqKaQDakMi1W87rFAhkogfRAevnwQ41onWNUJKtuBXMAIAAAAAASgiDpXfGh7E47KkOD8MAcX8+BnDShlnU5JAGdnPdqOAVsACAAAAAAI+2TTQIgbFq4Yr3lkzGwhG/tqChP7hRAx2W0fNaH6jcAAzE2MAB9AAAABWQAIAAAAAB7L4EnhjKA5xJD3ORhH2wOA1BvpnQ+7IjRYi+jjVEaJAVzACAAAAAAuhBIm0nL3FJnVJId+7CKDASEo+l2E89Z9/5aWSITK4AFbAAgAAAAALtSICOzQDfV9d+gZuYxpEj6cCeHnKTT+2G3ceP2H65kAAMxNjEAfQAAAAVkACAAAAAAaROn1NaDZFOGEWw724dsXBAm6bgmL5i0cki6QZQNrOoFcwAgAAAAANVT8R6UvhrAlyqYlxtmnvkR4uYK/hlvyQmBu/LP6/3ZBWwAIAAAAAD+aHNMP/X+jcRHyUtrCNkk1KfMtoD3GTmShS8pWGLt+AADMTYyAH0AAAAFZAAgAAAAADqSR5e0/Th59LrauDA7OnGD1Xr3H3NokfVxzDWOFaN7BXMAIAAAAACt30faNwTWRbvmykDpiDYUOCwA6QDbBBYBFWS7rdOB4AVsACAAAAAAF7SvnjjRk5v2flFOKaBAEDvjXaL1cpjsQLtK2fv9zdQAAzE2MwB9AAAABWQAIAAAAADmtb1ZgpZjSeodPG/hIVlsnS8hoRRwRbrTVx89VwL62AVzACAAAAAAi38e1g6sEyVfSDkzZbaZXGxKI/zKNbMasOl2LYoWrq8FbAAgAAAAAALACk0KcCDN/Kv8WuazY8ORtUGkOZ5Dsm0ys1oOppp/AAMxNjQAfQAAAAVkACAAAAAAf/f7AWVgBxoKjr7YsEQ4w/fqSvuQWV2HMiA3rQ7ur0sFcwAgAAAAADkkeJozP6FFhUdRIN74H4UhIHue+eVbOs1NvbdWYFQrBWwAIAAAAAB55FlHAkmTzAYj/TWrGkRJw2EhrVWUnZXDoMYjyfB/ZwADMTY1AH0AAAAFZAAgAAAAAI2WEOymtuFpdKi4ctanPLnlQud+yMKKb8p/nfKmIy56BXMAIAAAAADVKrJmhjr1rfF3p+T+tl7UFd1B7+BfJRk0e7a4im7ozgVsACAAAAAA5E7Ti3PnFiBQoCcb/DN7V1uM3Xd6VKiexPKntssFL7kAAzE2NgB9AAAABWQAIAAAAAAuHU9Qd79hjyvKOujGanSGDIQlxzsql8JytTZhEnPw+AVzACAAAAAAjF2gV/4+sOHVgDd/oR5wDi9zL7NGpGD+NsEpGXy/a4QFbAAgAAAAAJzMoyojYV6Ed/LpVN5zge93Odv3U7JgP7wxeRaJZGTdAAMxNjcAfQAAAAVkACAAAAAA7dQDkt3iyWYCT94d7yqUtPPwp4qkC0ddu+HFdHgVKEkFcwAgAAAAANuYvtvZBTEq4Rm9+5eb7VuFopowkrAuv86PGP8Q8/QvBWwAIAAAAACeqXoAOQOE4j0zRMlkVd8plaW0RX1npsFvB38Xmzv7sAADMTY4AH0AAAAFZAAgAAAAAAwnZSDhL4tNGYxlHPhKYB8s28dY5ScSwiKZm3UhT8U3BXMAIAAAAABDoY6dhivufTURQExyC9Gx3ocpl09bgbbQLChj3qVGbgVsACAAAAAAF+1nS7O0v85s3CCy+9HkdeoEfm2C6ZiNbPMMnSfsMHUAAzE2OQB9AAAABWQAIAAAAAC2VuRdaC4ZJmLdNOvD6R2tnvkyARteqXouJmI46V306QVzACAAAAAAMn1Z6B35wFTX9mEYAPM+IiJ5hauEwfD0CyIvBrxHg7IFbAAgAAAAAOG6DvDZkT9B/xZWmjao2AevN7MMbs3Oh9YJeSd/hZ+hAAMxNzAAfQAAAAVkACAAAAAAVerb7qVNy457rNOHOgDSKyWl5ojun7iWrv1uHPXrIZQFcwAgAAAAAIDcYS9j5z+gx0xdJj09L7876r/vjvKTi/d3bXDE3PhyBWwAIAAAAADuhVLqb1Bkrx8aNymS+bx2cL8GvLFNH4SAi690DUgnWQADMTcxAH0AAAAFZAAgAAAAAH/E44yLxKCJjuSmU9A8SEhbmkDOx1PqqtYcZtgOzJdrBXMAIAAAAABgLh9v2HjBbogrRoQ82LS6KjZQnzjxyJH4PH+F3jupSAVsACAAAAAAIlO46ehXp4TqpDV0t6op++KO+uWBFh8iFORZjmx2IjkAAzE3MgB9AAAABWQAIAAAAAAlNUdDL+f/SSQ5074mrq0JNh7CTXwTbbhsQyDwWeDVMwVzACAAAAAANIH2IlSNG0kUw4qz0budjcWn8mNR9cJlYUqPYdonucAFbAAgAAAAAJMrOUOyiu5Y3sV76zwEFct8L7+i8WGlQI2+8z2W2kzaAAMxNzMAfQAAAAVkACAAAAAASZ+CvUDtlk/R4HAQ3a+PHrKeY/8ifAfh0oXYFqliu80FcwAgAAAAAJelpzPgM65OZFt/mvGGpwibclQ49wH+1gbUGzd9OindBWwAIAAAAAD9qeDchteEpVXWcycmD9kl9449C1dOw0r60TBm5jK+cQADMTc0AH0AAAAFZAAgAAAAAN9fkoUVbvFV2vMNMAkak4gYfEnzwKI3eDM3pnDK5q3lBXMAIAAAAACnDkgVNVNUlbQ9RhR6Aot2nVy+U4km6+GHPkLr631jEAVsACAAAAAANzg/BnkvkmvOr8nS4omF+q9EG/4oisB+ul4YHi938hwAAzE3NQB9AAAABWQAIAAAAAASyK3b1nmNCMptVEGOjwoxYLLS9fYWm/Zxilqea0jpEQVzACAAAAAADDHsGrbqlKGEpxlvfyqOJKQJjwJrzsrB7k3HG0AUJbkFbAAgAAAAAKwx3S4XfDZh4+LuI9jf7XgUh5qiefNv87JD4qvVRfPSAAMxNzYAfQAAAAVkACAAAAAAlSP9iK31GlcG9MKGbLmq+VXMslURr+As736rrVNXcsUFcwAgAAAAAAvbj0zfq9zzi8XReheKFbCB+h9IsOLgXPPpI5vrEJNZBWwAIAAAAABXvoZhaQE7ogWjeBjceVkp03N20cKYP3TA8vuNsgpfAgADMTc3AH0AAAAFZAAgAAAAAOJNORH8Bev97gVU7y6bznOxJ+E6Qoykur1QP76hG1/7BXMAIAAAAAC+C1PtOOrSZgzBAGhr+dPe/kR0JUw9GTwLVNr61xC1aAVsACAAAAAAeA/L8MQIXkamaObtMPLpoDoi5FypA5WAPtMeMrgi0eQAAzE3OAB9AAAABWQAIAAAAAAKcHzLUomavInN6upPkyWhAqYQACP/vdVCIYpiy6U6HgVzACAAAAAATsR4KItY6R2+U7Gg6sJdaEcf58gjd1OulyWovIqfxKcFbAAgAAAAAFbm10ko67ahboAejQdAV0U2uA5OhZYdb8XUFJ8OL46LAAMxNzkAfQAAAAVkACAAAAAAqTOLiMpCdR59tLZzzIPqJvbCNvz2XQL9ust0qYaehtcFcwAgAAAAAArefox/3k5xGOeiw2m6NUdzuGxmPwcu5IFcj+jMwHgHBWwAIAAAAADLZGFJ7MQd5JXMgMXjqZO5LDLxcFClcXPlnRMWRn+1oAADMTgwAH0AAAAFZAAgAAAAAIPSqSeVzSRgNVNmrPYHmUMgykCY27NbdDUNhE5kx/SgBXMAIAAAAAAhX90nNfxyXmZe/+btZ7q6xMX4PFyj0paM1ccJ/5IUUQVsACAAAAAA419oHmD2W0SYoOMwhrhrp8jf68fg9hTkaRdCuVd3CN0AAzE4MQB9AAAABWQAIAAAAACLn5DxiqAosHGXIAY96FwFKjeqrzXWf3VJIQMwx1fl4gVzACAAAAAAindvU27nveutopdvuHmzdENBbeGFtI3Qcsr07jxmvm8FbAAgAAAAAPvl9pBStQvP4OGkN5v0MghUY6djm9n7XdKKfrW0l1sMAAMxODIAfQAAAAVkACAAAAAA7i2S6rHRSPBwZEn59yxaS7HiYBOmObIkeyCcFU42kf8FcwAgAAAAAGb3RSEyBmgarkTvyLWtOLJcPwCKbCRkESG4RZjVmY4iBWwAIAAAAADB2/wo5CSHR4ANtifY6ZRXNTO5+O8qP82DfAiAeanpZwADMTgzAH0AAAAFZAAgAAAAAFz+M+H/Z94mdPW5oP51B4HWptp1rxcMWAjnlHvWJDWrBXMAIAAAAACBFEOQyL7ZHu4Cq33QvXkmKuH5ibG/Md3RaED9CtG5HwVsACAAAAAAfggtJTprQ/yZzj7y5z9KvXsdeXMWP0yUXMMJqpOwI88AAzE4NAB9AAAABWQAIAAAAAAE7c2x3Z3aM1XGfLNk/XQ9jCazNRbGhVm7H8c2NjS5ywVzACAAAAAARJ9h8fdcwA19velF3L/Wcvi2rCzewlKZ2nA0p8bT9uwFbAAgAAAAAJtWe6b4wK2Hae2dZm/OEpYQnvoZjz4Sz5IgJC2wInecAAMxODUAfQAAAAVkACAAAAAAVoRt9B9dNVvIMGN+ea5TzRzQC+lqSZ8dd/170zU5o9cFcwAgAAAAAEwM95XZin5mv2yhCI8+ugtKuvRVmNgzzIQN0yi1+9aIBWwAIAAAAAAMGBq72n00rox3uqhxSB98mkenTGCdbbUF1gXrgottzgADMTg2AH0AAAAFZAAgAAAAAKRDkjyWv/etlYT4GyoXrmBED2FgZHnhc+l9Wsl06cH2BXMAIAAAAABohlpm3K850Vndf3NmNE0hHqDlNbSR8/IvMidQ3LnIZAVsACAAAAAAW42nGHa6q2MCAaaPVwaIDfr8QLyQwjKq23onZJYsqVsAAzE4NwB9AAAABWQAIAAAAAC3DFh5oklLCNLY90bgWm68dFXz65JpAZSp1K99MBTPAQVzACAAAAAAQgZecmxEUZVHoptEQClDwAf8smI3WynQ/i+JBP0g+kQFbAAgAAAAAEUSQGVnAPISD6voD0DiBUqyWKgt2rta0tjmoe+LNt6IAAMxODgAfQAAAAVkACAAAAAAQ5WKvWSB503qeNlOI2Tpjd5blheNr6OBO8pfJfPNstcFcwAgAAAAAKwHgQLSDJ5NwLBQbY5OnblQIsVDpGV7q3RCbFLD1U4/BWwAIAAAAACQ5nED99LnpbqXZuUOUjnO2HTphEAFBjLD4OZeDEYybgADMTg5AH0AAAAFZAAgAAAAAGfhFY3RGRm5ZgWRQef1tXxHBq5Y6fXaLAR4yJhrTBplBXMAIAAAAACKEF0ApLoB6lP2UqTFsTQYNc9OdDrs/vziPGzttGVLKQVsACAAAAAArOO6FyfNRyBi0sPT5iye7M8d16MTLcwRfodZq4uCYKEAAzE5MAB9AAAABWQAIAAAAAAIM73gPcgzgotYHLeMa2zAU4mFsr7CbILUZWfnuKSwagVzACAAAAAAJCSu98uV8xv88f2BIOWzt6p+6EjQStMBdkGPUkgN79cFbAAgAAAAAMGqPGMPxXbmYbVfSa/japvUljht1zZT33TY7ZjAiuPfAAMxOTEAfQAAAAVkACAAAAAAkWmHCUsiMy1pwZTHxVPBzPTrWFBUDqHNrVqcyyt7nO8FcwAgAAAAAMv2CebFRG/br7USELR98sIdgE9OQCRBGV5JZCO+uPMgBWwAIAAAAABt7qSmn3gxJu7aswsbUiwvO+G6lXj/Xhx+J/zQyZxzLAADMTkyAH0AAAAFZAAgAAAAAGInUYv0lP/rK7McM8taEHXRefk8Q2AunrvWqdfSV7UaBXMAIAAAAACE+WPxJ3gan7iRTbIxXXx+bKVcaf8kP4JD8DcwU0aL7wVsACAAAAAAUC4eTprX4DUZn2X+UXYU6QjtiXk+u57yoOPBbPQUmDkAAzE5MwB9AAAABWQAIAAAAACmHlg2ud3cplXlTsNTpvNnY6Qm1Fce0m899COamoDjaQVzACAAAAAArtJQeJIlepBWRU2aYar7+YGYVQ7dfDc1oxgTmA8r9q0FbAAgAAAAAOk45vg5VqZHAFCO3i0Z52SZi5RADf8NXwf68T5yad/DAAMxOTQAfQAAAAVkACAAAAAApzcWSAbZWV/Rq+ylRNqqlJqNVR4fhXrz4633/MQOQgcFcwAgAAAAAN/jz/bsEleiuCl+li83EWlG6UMHA8CyaOMRKCkXkSCPBWwAIAAAAAC3Sd+Qg+uFDKpGZHbrQgokXHQ1az1aFl4YK343OB6hcQAAEmNtAAAAAAAAAAAAABBwYXlsb2FkSWQAAAAAABBmaXJzdE9wZXJhdG9yAAEAAAAA", "subType": "06" } } } }, "update": { "$set": { "encryptedDecimalNoPrecision": { "$$type": "binData" } } }, "encryptionInformation": { "type": 1, "schema": { "default.default": { "escCollection": "enxcol_.default.esc", "ecocCollection": "enxcol_.default.ecoc", "fields": [ { "keyId": { "$binary": { "base64": "EjRWeBI0mHYSNBI0VniQEg==", "subType": "04" } }, "path": "encryptedDecimalNoPrecision", "bsonType": "decimal", "queries": { "queryType": "rangePreview", "contention": { "$numberLong": "0" }, "sparsity": { "$numberLong": "1" } } } ] } } } }, "command_name": "findAndModify" } } ], "outcome": { "collection": { "data": [ { "_id": { "$numberInt": "0" }, "encryptedDecimalNoPrecision": { "$$type": "binData" }, "__safeContent__": [ { "$binary": { "base64": "5nRutVIyq7URVOVtbE4vM01APSIajAVnsShMwjBlzkM=", "subType": "00" } }, { "$binary": { "base64": "rbf3AeBEv4wWFAKknqDxRW5cLNkFvbIs6iJjc6LShQY=", "subType": "00" } }, { "$binary": { "base64": "n+XAuFnP8Dov9TnhGFxNx0K/MnVM9WbJ7RouEu0ndO0=", "subType": "00" } }, { "$binary": { "base64": "yRXojuVdn5GQtD97qYlaCL6cOLmZ7Cvcb3wFjkLUIdM=", "subType": "00" } }, { "$binary": { "base64": "DuIkdRPITRs55I4SZmgomAHCIsDQmXRhW8+MOznkzSk=", "subType": "00" } }, { "$binary": { "base64": "SsBk+Et1lTbU+QRPx+xyJ/jMkmfG+QCvQEpip2YYrzA=", "subType": "00" } }, { "$binary": { "base64": "crCIzOd8KhHvvUlX7M1v9bhvU4pLdTc+X2SuqoKU5Ek=", "subType": "00" } }, { "$binary": { "base64": "YOWdCw4UrqnxkAaVjqmC4sKQDMVMHEpFGnlxpxdaU6E=", "subType": "00" } }, { "$binary": { "base64": "M3SShp81Ff8tQ632qKbv9MUcN6wjDaBReI0VXNu6Xh4=", "subType": "00" } }, { "$binary": { "base64": "gzHlSPxpM0hT75kQvWFzGlOxKvDoiKQZOr19V6l2zXI=", "subType": "00" } }, { "$binary": { "base64": "s3JnppOGYw9SL2Q1kMAZs948v2F5PrpXjGei/HioDWs=", "subType": "00" } }, { "$binary": { "base64": "cG6+3Gk/zEH68P/uuuwiAUVCuyJwa1LeV+t29FlPPAo=", "subType": "00" } }, { "$binary": { "base64": "dupdvR3AyJtM+g9NDKiaLVOtGca387JQp8w+V03m7Ig=", "subType": "00" } }, { "$binary": { "base64": "JqEQc5svj2jTvZ6LLA5ivE+kTb/0aRemSEmxk4G7Zrg=", "subType": "00" } }, { "$binary": { "base64": "szcXXXKnob+p3SoM4yED2R920LeJ7cVsclPMFTe4CeI=", "subType": "00" } }, { "$binary": { "base64": "o1QoGVXmuBdHwHm7aCtGMlMVKrjFdYvJXpoq6uhIAZ0=", "subType": "00" } }, { "$binary": { "base64": "Jfm5wPlqqLCJRGQIqRq2NGmpn7s0Vrih2H3YAOoI2YU=", "subType": "00" } }, { "$binary": { "base64": "zMHLb8ARbsYo8Ld05bqnGFf1Usha6EGb8QKwdSAyps0=", "subType": "00" } }, { "$binary": { "base64": "yQdtq9lh5pugL7/i0Bj/PuZUUBUIzf+7wj1rl5y736w=", "subType": "00" } }, { "$binary": { "base64": "wGWVZdO7qIuyDg/BqDgqjgoQ02h5YYgwXQB1oCin2NE=", "subType": "00" } }, { "$binary": { "base64": "by9HMLj6NTEpgztZ5HSN6GxImkXPcaFINYDzgZY33X8=", "subType": "00" } }, { "$binary": { "base64": "tWo0vbasi7bXmn/MsOx13VC1IsWtpx/nYp0uj4iMzdA=", "subType": "00" } }, { "$binary": { "base64": "tQQpndUYd5O87lOtrGjH3wl9VsOK0ray7RMasL90sBM=", "subType": "00" } }, { "$binary": { "base64": "cQjXEDCMsOpKLLf+vlTgIHA+cbSJdzqhbSX9Wvh95aA=", "subType": "00" } }, { "$binary": { "base64": "7yMpU48IxK9SzP2cx3VnTownGEwFmeFofuuFT97SuuY=", "subType": "00" } }, { "$binary": { "base64": "kSOx1kz0CmBgzKQHZlo65ZUY1DIv9A99JRm+Us2y6Ew=", "subType": "00" } }, { "$binary": { "base64": "ubQpdPBe6/xvtr+AcXdfYLSvYCR4ot0tivehkCsupb4=", "subType": "00" } }, { "$binary": { "base64": "xal+iCJ6FTefRQToyoNksc9NCZShyn04NDGi4IYrcoM=", "subType": "00" } }, { "$binary": { "base64": "d7jU4iOK50xHxlkSifcxlZFCM46TSgQzoYivxG3HNLY=", "subType": "00" } }, { "$binary": { "base64": "tJvl2nsBLBVzL3pp6sKWCL4UXeh3q/roYBJjSb74ve0=", "subType": "00" } }, { "$binary": { "base64": "OIUCaKRvIx9t1w6Hxlz1IcQTdPNCfdRNwnnTm10W+X0=", "subType": "00" } }, { "$binary": { "base64": "A9tvzsiElotOUVIB4CqfQp9mAwqvTM35YkmAR170aHA=", "subType": "00" } }, { "$binary": { "base64": "lI8gpK7hpb7c9x4RQugsxMnQay5LZJmwslZdvMx/dcE=", "subType": "00" } }, { "$binary": { "base64": "dNCzh40U0XvdKnSDi3HRQOWQftEsDVqc4uUvsVFGoq8=", "subType": "00" } }, { "$binary": { "base64": "IP+iwEBWBwVVZIdpaMu8k5+soFCz+TZkYn3drKZ9grE=", "subType": "00" } }, { "$binary": { "base64": "pnqyh6e0y5svHkJDShlN9CHV0WvMBE4QbtJpQw5ZCXc=", "subType": "00" } }, { "$binary": { "base64": "elEl42tbVDoRTLjAhZUFEtXiut4b3PVhg/1ZLZSQdtE=", "subType": "00" } }, { "$binary": { "base64": "vHuu2FxwclMHqyE6JBYbTYgbEkB0dqb/JuaxsvfwsmY=", "subType": "00" } }, { "$binary": { "base64": "xTf7NCe3Gf8QpE78HR5OknlLTKfs9J+RN9UZpH6fnso=", "subType": "00" } }, { "$binary": { "base64": "XiWSasRnJAulGR6+LCVD3mwRObXylqYWR9jvpywq12c=", "subType": "00" } }, { "$binary": { "base64": "MZMxEQ5ikx0PG1YFIExv0UnTZogsvgeOEZTpzvBDn4w=", "subType": "00" } }, { "$binary": { "base64": "yZMyMZBDrWbAhvnic7vvIYhmO9m5H2iuv0c8KNZrBzY=", "subType": "00" } }, { "$binary": { "base64": "xxM14hTPY5j0vvcK2C7YAEjzdsfUTFHozHC0hEo1bxI=", "subType": "00" } }, { "$binary": { "base64": "+01rqR1xVwkpGXcstbk1ItJqFVjH6Q8MGxEN3Cm9Y1A=", "subType": "00" } }, { "$binary": { "base64": "xOpLV0Z2VTRJ3iWtnWZcsyjXubTIkYWo31cO+HV1o1k=", "subType": "00" } }, { "$binary": { "base64": "BWUOLqgLBqc5NwxVlSV5H3KFQPXbCp7mdo+jF+8cJqY=", "subType": "00" } }, { "$binary": { "base64": "fuQb1S6xZDGlrEbK+kI23aL53PP1PVNwqICnZNt9Yzg=", "subType": "00" } }, { "$binary": { "base64": "SfscnoibFttahLdPVC4Ee+47ewGFKpDSU7M6HX19bKE=", "subType": "00" } }, { "$binary": { "base64": "rpSW2awybNVeKtat91VFxqbINoTfNhPfQAu+d73Xtf8=", "subType": "00" } }, { "$binary": { "base64": "9M/CP9ccOIIj2LLFmE0GFDO0Ban2wsNalEXfM6+h+1s=", "subType": "00" } }, { "$binary": { "base64": "WrEMG49l1ye4MhXs5ZS9tz8P6h+hDvthIg/2wW9ne1Q=", "subType": "00" } }, { "$binary": { "base64": "ImNhbfeyfH8qIEeA5ic0s3dAQBdzzTBS+CPsNih9vZ0=", "subType": "00" } }, { "$binary": { "base64": "dWP33YDSn04UKJN2ogh2Rui0iW/0q2y18OCDRVcfyoo=", "subType": "00" } }, { "$binary": { "base64": "lYv0isAtfGh6H9tdp3cp2eHU7q2J+uk7QrgcxtK3w7Y=", "subType": "00" } }, { "$binary": { "base64": "VGMoamB/+7zTOYcY/pqJc96xlv2PdW4hwsIAEIslTDQ=", "subType": "00" } }, { "$binary": { "base64": "yNeBWMF7BnD9wVwz2PgJsvWr77QiVvvWUvJF0+fqBug=", "subType": "00" } }, { "$binary": { "base64": "SfpvObJ+tJBXSvqeN7vlOfmhYign635lciYAJIjUtY8=", "subType": "00" } }, { "$binary": { "base64": "dsen4NqjzVGjpjufiTMs3+gqeD09EbnuogPgxrJECwg=", "subType": "00" } }, { "$binary": { "base64": "pxCWVM3sn19NsFEpgHbgLa+PmYlhN3mMiP0Wk8kJhYw=", "subType": "00" } }, { "$binary": { "base64": "q11KNvJszjYIB9n9HcC+N4uz11a3eRj1L3BH9scKMDQ=", "subType": "00" } }, { "$binary": { "base64": "A1PmkgcEToWh1JiVWE6mI5jUu7poxWWuCUt/cgRUUDc=", "subType": "00" } }, { "$binary": { "base64": "qJo3Hu4PJeanL7XEaWXO/n3YsodhZyd+MJOOmB9Kpd8=", "subType": "00" } }, { "$binary": { "base64": "BkBKLO8URFscfRY9Bav/1+L9mLohDgNr/MkZtGiraIs=", "subType": "00" } }, { "$binary": { "base64": "rZq5WA3Hx3xthOyHAJXK//f8pE2qbz7YKu3TIMp9GFY=", "subType": "00" } }, { "$binary": { "base64": "X07a/Lm80p5xd4RFs1dNmw+90tmPDPdGiAKVZkxd4zY=", "subType": "00" } }, { "$binary": { "base64": "6YrBn2ofIw1b5ooakrLOwF41BWrps8OO0H9WH4/rtlE=", "subType": "00" } }, { "$binary": { "base64": "0l86Ag5OszXpa78SlOUV3K9nff5iC1p0mRXtLg9M1s4=", "subType": "00" } }, { "$binary": { "base64": "Hn6yuxFHodeyu7ISlhYrbSf9pTiH4TDEvbYLWjTwFO0=", "subType": "00" } }, { "$binary": { "base64": "zdf4y2etKBuIpkEU1zMwoCkCsdisfXZCh8QPamm+drY=", "subType": "00" } }, { "$binary": { "base64": "rOQ9oMdiK5xxGH+jPzOvwVqdGGnF3+HkJXxn81s6hp4=", "subType": "00" } }, { "$binary": { "base64": "61aKKsE3+BJHHWYvs3xSIBvlRmKswmaOo5rygQJguUg=", "subType": "00" } }, { "$binary": { "base64": "KuDb/GIzqDM8wv7m7m8AECiWJbae5EKKtJRugZx7kR0=", "subType": "00" } }, { "$binary": { "base64": "Q+t8t2TmNUiCIorVr9F3AlVnX+Mpt2ZYvN+s8UGict8=", "subType": "00" } }, { "$binary": { "base64": "tJRZIpKxUgHyL83kW8cvfjkxN3z6WoNnUg+SQw+LK+k=", "subType": "00" } }, { "$binary": { "base64": "pnUsYjip8SvW0+m9mR5WWTkpK+p6uwJ6yBUAlBnFKMk=", "subType": "00" } }, { "$binary": { "base64": "PArHlz+yPRYDycAP/PgnI/AkP8Wgmfg++Vf4UG1Bf0E=", "subType": "00" } }, { "$binary": { "base64": "wnIh53Q3jeK8jEBe1n8kJLa89/H0BxO26ZU8SRIAs9Q=", "subType": "00" } }, { "$binary": { "base64": "4F8U59gzBLGhq58PEWQk2nch+R0Va7eTUoxMneReUIA=", "subType": "00" } }, { "$binary": { "base64": "ihKagIW3uT1dm22ROr/g5QaCpxZVj2+Fs/YSdM2Noco=", "subType": "00" } }, { "$binary": { "base64": "EJtUOOwjkrPUi9mavYAi+Gom9Y2DuFll7aDwo4mq0M0=", "subType": "00" } }, { "$binary": { "base64": "dIkr8dbaVRQFskAVT6B286BbcBBt1pZPEOcTZqk4ZcI=", "subType": "00" } }, { "$binary": { "base64": "aYVAcZYkH/Tieoa1XOjE/zCy5AJcVTHjS0NG2QB7muA=", "subType": "00" } }, { "$binary": { "base64": "sBidL6y8TenseetpioIAAtn0lK/7C8MoW4JXpVYi3z8=", "subType": "00" } }, { "$binary": { "base64": "0Dd2klU/t4R86c2WJcJDAd57k/N7OjvYSO5Vf8KH8sw=", "subType": "00" } }, { "$binary": { "base64": "I3jZ92WEVmZmgaIkLbuWhBxl7EM6bEjiEttgBJunArA=", "subType": "00" } }, { "$binary": { "base64": "aGHoQMlgJoGvArjfIbc3nnkoc8SWBxcrN7hSmjMRzos=", "subType": "00" } }, { "$binary": { "base64": "bpiWPnF/KVBQr5F6MEwc5ZZayzIRvQOLDAm4ntwOi8g=", "subType": "00" } }, { "$binary": { "base64": "tI7QVKbE6avWgDD9h4QKyFlnTxFCwd2iLySKakxNR/I=", "subType": "00" } }, { "$binary": { "base64": "XGsge0CnoaXgE3rcpKm8AEeku5QVfokS3kcI+JKV1lk=", "subType": "00" } }, { "$binary": { "base64": "JQxlryW2Q5WOwfrjAnaZxDvC83Dg6sjRVP5zegf2WiM=", "subType": "00" } }, { "$binary": { "base64": "YFuHKJOfoqp1iGVxoFjx7bLYgVdsN4GuUFxEgO9HJ5s=", "subType": "00" } }, { "$binary": { "base64": "Z6vUdiCR18ylKomf08uxcQHeRtmyav7/Ecvzz4av3k4=", "subType": "00" } }, { "$binary": { "base64": "SPGo1Ib5AiP/tSllL7Z5PAypvnKdwJLzt8imfIMSEJQ=", "subType": "00" } }, { "$binary": { "base64": "m94Nh6PFFQFLIib9Cu5LAKavhXnagSHG6F5EF8lD96I=", "subType": "00" } }, { "$binary": { "base64": "pfEkQI98mB+gm1+JbmVurPAODMFPJ4E8DnqfVyUWbSo=", "subType": "00" } }, { "$binary": { "base64": "DNj3OVRLbr43s0vd+rgWghOL3FqeO/60npdojC8Ry/M=", "subType": "00" } }, { "$binary": { "base64": "kAYIQrjHVu49W8FTxyxJeiLVRWWjC9fPcBn+Hx1F+Ss=", "subType": "00" } }, { "$binary": { "base64": "aCSO7UVOpoQvu/iridarxkxV1SVxU1i9HVSYXUAeXk4=", "subType": "00" } }, { "$binary": { "base64": "Gh6hTP/yj1IKlXQ+Q69KTfMlGZjEcXoRLGbQHNFo/1s=", "subType": "00" } }, { "$binary": { "base64": "/gDgIFQ4tAlJk3GN48IS5Qa5IPmErwGk8CHxAbp6gs0=", "subType": "00" } }, { "$binary": { "base64": "PICyimwPjxpusyKxNssOOwUotAUbygpyEtORsVGXT8g=", "subType": "00" } }, { "$binary": { "base64": "4lu+cBHyAUvuxC6JUNyHLzHsCogGSWFFnUCkDwfQdgI=", "subType": "00" } }, { "$binary": { "base64": "pSndkmoNUJwXjgkbkgOrT5f9nSvuoMEZOkwAN9ElRaE=", "subType": "00" } }, { "$binary": { "base64": "tyW+D4i26QihNM5MuBM+wnt5AdWGSJaJ4X5ydc9iWTU=", "subType": "00" } }, { "$binary": { "base64": "9Syjr8RoxUgPKr+O5rsCu07AvcebA4P8IVKyS1NVLWc=", "subType": "00" } }, { "$binary": { "base64": "67tPfDYnK2tmrioI51fOBG0ygajcV0pLo5+Zm/rEW7U=", "subType": "00" } }, { "$binary": { "base64": "y0EiPRxYTuS1eVTIaPQUQBBxwkyxNckbePvKgChwd0M=", "subType": "00" } }, { "$binary": { "base64": "NWd+2veAaeXQgR3vCvzlI4R1WW67D5YsVLdoXfdb8qg=", "subType": "00" } }, { "$binary": { "base64": "PY5RQqKQsL2GqBBSPNOEVpojNFRX/NijCghIpxD6CZk=", "subType": "00" } }, { "$binary": { "base64": "lcvwTyEjFlssCJtdjRpdN6oY+C7bxZY+WA+QAqzj9zg=", "subType": "00" } }, { "$binary": { "base64": "CWE7XRNylvTwO/9Fv56dNqUaQWMmESNS/GNIwgBaEI0=", "subType": "00" } }, { "$binary": { "base64": "ijwlrUeS8nRYqK1F8kiCYF0mNDolEZS+/lJO1Lg93C8=", "subType": "00" } }, { "$binary": { "base64": "8KzV+qYGYuIjoNj8eEpnTuHrMYuhzphl80rS6wrODuU=", "subType": "00" } }, { "$binary": { "base64": "wDyTLjSEFF895hSQsHvmoEQVS6KIkZOtq1c9dVogm9I=", "subType": "00" } }, { "$binary": { "base64": "SGrtPuMYCjUrfKF0Pq/thdaQzmGBMUvlwN3ORIu9tHU=", "subType": "00" } }, { "$binary": { "base64": "KySHON3hIoUk4xWcwTqk6IL0kgjzjxgMBObVIkCGvk4=", "subType": "00" } }, { "$binary": { "base64": "hBIdS9j0XJPeT4ot73ngELkpUoSixvRBvdOL9z48jY8=", "subType": "00" } }, { "$binary": { "base64": "Tx6um0q9HjS5ZvlFhvukpI6ORnyrXMWVW1OoxvgqII0=", "subType": "00" } }, { "$binary": { "base64": "zFKlyfX5H81+d4A4J3FKn4T5JfG+OWtR06ddyX4Mxas=", "subType": "00" } }, { "$binary": { "base64": "cGgCDuPV7MeMMYEDpgOupqyNP4BQ4H7rBnd2QygumgM=", "subType": "00" } }, { "$binary": { "base64": "IPaUoy98v11EoglTpJ4kBlEawoZ8y7BPwzjLYBpkvHQ=", "subType": "00" } }, { "$binary": { "base64": "Pfo4Am6tOWAyZNn8G9W5HWWGC3ZWmX0igI/RRB870Ro=", "subType": "00" } }, { "$binary": { "base64": "fnTSjd7bC1Udoq6iM7UDnHAC/lsIXSHp/Gy332qw+/I=", "subType": "00" } }, { "$binary": { "base64": "fApBgVRrTDyEumkeWs5p3ag9KB48SbU4Si0dl7Ns9rc=", "subType": "00" } }, { "$binary": { "base64": "QxudfBItgoCnUj5NXVnSmWH3HK76YtKkMmzn4lyyUYY=", "subType": "00" } }, { "$binary": { "base64": "sSOvwhKa29Wq94bZ5jGIiJQGbG1uBrKSBfOYBz/oZeI=", "subType": "00" } }, { "$binary": { "base64": "FdaMgwwJ0NKsqmPZLC5oE+/0D74Dfpvig3LaI5yW5Fs=", "subType": "00" } }, { "$binary": { "base64": "sRWBy12IERN43BSZIrnBfC9+zFBUdvjTlkqIH81NGt4=", "subType": "00" } }, { "$binary": { "base64": "/4tIRpxKhoOwnXAiFn1Z7Xmric4USOIfKvTYQXk3QTc=", "subType": "00" } } ] }, { "_id": { "$numberInt": "1" }, "encryptedDecimalNoPrecision": { "$$type": "binData" }, "__safeContent__": [ { "$binary": { "base64": "DLCAJs+W2PL2DV5YChCL6dYrQNr+j4p3L7xhVaub4ic=", "subType": "00" } }, { "$binary": { "base64": "Mr/laWHUijZT5VT3x2a7crb7wgd/UXOGz8jr8BVqBpM=", "subType": "00" } }, { "$binary": { "base64": "wXVD/HSbBljko0jJcaxJ1nrzs2+pchLQqYR3vywS8SU=", "subType": "00" } }, { "$binary": { "base64": "VDCpBYsJIxTfcI6Zgf7FTmKMxUffQv+Ys8zt5dlK76I=", "subType": "00" } }, { "$binary": { "base64": "zYDslUwOUVNwTYkETfjceH/PU3bac9X3UuQyYJ19qK0=", "subType": "00" } }, { "$binary": { "base64": "rAOmHSz18Jx107xpbv9fYcPOmh/KPAqge0PAtuhIRnc=", "subType": "00" } }, { "$binary": { "base64": "BFOB1OGVUen7VsOuS0g8Ti7oDsTt2Yj/k/7ta8YAdGM=", "subType": "00" } }, { "$binary": { "base64": "2fckE5SPs0GU+akDkUEM6mm0EtcV3WDE/sQsnTtodlk=", "subType": "00" } }, { "$binary": { "base64": "mi9+aNjuwIvaMpSHENvKzKRAmX9cYguo2mXLvOoftHQ=", "subType": "00" } }, { "$binary": { "base64": "K6TWn4VcWWkz/gkUkLmbtwkG7SNeABICmLDnoYJFlLU=", "subType": "00" } }, { "$binary": { "base64": "Z+2/cEtGU0Fq7QJFNGA/0y4aWAsw0ncG6X0LYRqwS3c=", "subType": "00" } }, { "$binary": { "base64": "rrSIf+lgcNZFbbUkS9BmE045jRWBpcBJXHzfMVEFuzE=", "subType": "00" } }, { "$binary": { "base64": "KlHL3Kyje1/LMIfgbCqw1SolxffJvvgsYBV5y77wxuA=", "subType": "00" } }, { "$binary": { "base64": "hzJ1YBoETmYeCh352dBmG8d8Wse/bUcqojTWpWQlgsc=", "subType": "00" } }, { "$binary": { "base64": "lSdcllDXx8MA+s0GULjDA1lQkcV0L8/aHtZ6dM2pZ2c=", "subType": "00" } }, { "$binary": { "base64": "HGr7JLTTA7ksAnlmjSIwwdBVvgr3fv46/FTdiCPYpos=", "subType": "00" } }, { "$binary": { "base64": "mMr25v1VwOEVZ8xaNUTHJCcsYqV+kwK6RzGYilxPtJ4=", "subType": "00" } }, { "$binary": { "base64": "129hJbziPJzNo0IoTU3bECdge0FtaPW8dm4dyNVNwYU=", "subType": "00" } }, { "$binary": { "base64": "doiLJ96qoo+v7NqIAZLq6BI5axV8Id8gT5vyJ1ZZ0PM=", "subType": "00" } }, { "$binary": { "base64": "cW/Lcul3xYmfyvI/0x/+ybN78aQmBK1XIGs1EEU09N8=", "subType": "00" } }, { "$binary": { "base64": "1aVIwzu9N5EJV9yEES+/g6hOTH7cA2NTcLIc59cu0wU=", "subType": "00" } }, { "$binary": { "base64": "kw5tyl7Ew0r1wFyrN1mB9FiVW2hK2BxxxUuJDNWjyjQ=", "subType": "00" } }, { "$binary": { "base64": "ADAY2YBrm6RJBDY/eLLcfNxmSJku+mefz74gH66oyco=", "subType": "00" } }, { "$binary": { "base64": "8gkqB1LojzPrstpFG7RHYmWxXpIlPDTqWnNsXH7XDRU=", "subType": "00" } }, { "$binary": { "base64": "TESfVQMDQjfTZmHmUeYUE2XrokJ6CcrsKx/GmypGjOw=", "subType": "00" } }, { "$binary": { "base64": "qFM+HFVQ539S0Ouynd1fBHoemFxtU9PRxE5+Dq7Ljy4=", "subType": "00" } }, { "$binary": { "base64": "jPiFgUZteSmOg4wf3bsEKCZzcnxmMoILsgp/GaZD+dM=", "subType": "00" } }, { "$binary": { "base64": "YaWUgJhYgPNN7TkFK16H8SsQS226JguaVhOIQxZwQNQ=", "subType": "00" } }, { "$binary": { "base64": "x90/Qk3AgyaFsvWf2KUCu5XF3j76WFSjt/GrnG01060=", "subType": "00" } }, { "$binary": { "base64": "ZGWybWL/xlEdMYRFCZDUoz10sywTf7U/7wufsb78lH0=", "subType": "00" } }, { "$binary": { "base64": "8l4ganN66jIcdxfHAdYLaym/mdzUUQ8TViw3MDRySPc=", "subType": "00" } }, { "$binary": { "base64": "c8p5XEGTqxqvRGVlR+nkxw9uUdoqDqTB0jlYQ361qMA=", "subType": "00" } }, { "$binary": { "base64": "1ZGFLlpQBcU3zIUg8MmgWwFKVz/SaA7eSYFrfe3Hb70=", "subType": "00" } }, { "$binary": { "base64": "34529174M77rHr3Ftn9r8jU4a5ztYtyVhMn1wryZSkU=", "subType": "00" } }, { "$binary": { "base64": "YkQ4pxFWzc49MS0vZM6S8mNo4wAwo21rePBeF3C+9mI=", "subType": "00" } }, { "$binary": { "base64": "MhOf4mYY00KKVhptOcXf0bXB7WfuuM801MRJg4vXPgc=", "subType": "00" } }, { "$binary": { "base64": "7pbbD8ihNIYIBJ3tAUPGzHpFPpIeCTAk5L88qCB0/9w=", "subType": "00" } }, { "$binary": { "base64": "C9Q5PoNJTQo6pmNzXEEXUEqH22//UUWY1gqILcIywec=", "subType": "00" } }, { "$binary": { "base64": "AqGVk1QjDNDLYWGRBX/nv9QdGR2SEgXZEhF0EWBAiSE=", "subType": "00" } }, { "$binary": { "base64": "/sGI3VCbJUKATULJmhTayPOeVW+5MjWSvVCqS77sRbU=", "subType": "00" } }, { "$binary": { "base64": "yOtbL0ih7gsuoxVtRrACMz+4N5uo7jIR7zzmtih2Beo=", "subType": "00" } }, { "$binary": { "base64": "uA6dkb2Iyg9Su8UNDvZzkPx33kPZtWr/CCuEY+XgzUM=", "subType": "00" } }, { "$binary": { "base64": "1DoSFPdHIplqZk+DyWAmEPckWwXw/GdB25NLmzeEZhk=", "subType": "00" } }, { "$binary": { "base64": "OfDVS0T3ZuIXI/LNbTp6C9UbPIWLKiMy6Wx+9tqNl+g=", "subType": "00" } }, { "$binary": { "base64": "3PZjHXbmG6GtPz+iapKtQ3yY4PoFFgjIy+fV2xQv1YU=", "subType": "00" } }, { "$binary": { "base64": "kaoLN0BoBWsmqE7kKkJQejATmLShd8qffcAmlhsxsGY=", "subType": "00" } }, { "$binary": { "base64": "vpiw9KgQdegGmp7IJnSGX2miujRLU0xzs0ITTqbPW7c=", "subType": "00" } }, { "$binary": { "base64": "NuXFf7xGUefYjIUTuMxNUTCfVHrF8oL0AT7dPv5Plk4=", "subType": "00" } }, { "$binary": { "base64": "8Tz53LxtfEBJ9eR+d2690kwNsqPV6XyKo2PlqZCbUrc=", "subType": "00" } }, { "$binary": { "base64": "e6zsOmHSyV8tyQtSX6BSwui6wK9v1xG3giY/IILJQ2w=", "subType": "00" } }, { "$binary": { "base64": "2fedFMCxa2DzmIpfbDKGXhQg0PPwbUv6vIWdwwlvhms=", "subType": "00" } }, { "$binary": { "base64": "yEJKMFnWXTC8tJUfzCInzQRByNEPjHxpw4L4m8No91Q=", "subType": "00" } }, { "$binary": { "base64": "YbFuWwOiFuQyOzIJXDbOkCWC2DyrG+248TBuVCa1pXU=", "subType": "00" } }, { "$binary": { "base64": "w7IkwGdrguwDrar5+w0Z3va5wXyZ4VXJkDMISyRjPGo=", "subType": "00" } }, { "$binary": { "base64": "YmJUoILTRJPhyIyWyXJTsQ6KSZHHbEpwPVup6Ldm/Ko=", "subType": "00" } }, { "$binary": { "base64": "FvMjcwVZJmfh6FP/yBg2wgskK+KHD8YVUY6WtrE8xbg=", "subType": "00" } }, { "$binary": { "base64": "h4HCtD4HyYz0nci49IVAa10Z4NJD/FHnRMV4sRX6qro=", "subType": "00" } }, { "$binary": { "base64": "nC7BpXCmym+a0Is2kReM9cYN2M1Eh5rVo8fjms14Oiw=", "subType": "00" } }, { "$binary": { "base64": "1qtVWaeVo649ZZZtN8gXbwLgMWGLhz8beODbvru0I7Q=", "subType": "00" } }, { "$binary": { "base64": "Ej+mC0QFyMNIiSjR939S+iGBm7dm+1xObu5IcF/OpbU=", "subType": "00" } }, { "$binary": { "base64": "UQ8LbUG3cMegbr9yKfKanAPQE1EfPkFciVDrNqZ5GHY=", "subType": "00" } }, { "$binary": { "base64": "4iI3mXIDjnX+ralk1HhJY43mZx2uTJM7hsv9MQzTX7E=", "subType": "00" } }, { "$binary": { "base64": "0WQCcs3rvsasgohERHHCaBM4Iy6yomS4qJ5To3/yYiw=", "subType": "00" } }, { "$binary": { "base64": "qDCTVPoue1/DOAGNAlUstdA9Sid8MgEY4e5EzHcVHRk=", "subType": "00" } }, { "$binary": { "base64": "9F9Mus0UnlzHb8E8ImxgXtz6SU98YXD0JqswOKw/Bzs=", "subType": "00" } }, { "$binary": { "base64": "pctHpHKVBBcsahQ6TNh6/1V1ZrqOtKSAPtATV6BJqh0=", "subType": "00" } }, { "$binary": { "base64": "vfR3C/4cPkVdxtNaqtF/v635ONbhTf5WbwJM6s4EXNE=", "subType": "00" } }, { "$binary": { "base64": "ejP43xUBIex6szDcqExAFpx1IE/Ksi5ywJ84GKDFRrs=", "subType": "00" } }, { "$binary": { "base64": "jbP4AWYd3S2f3ejmMG7dS5IbrFol48UUoT+ve3JLN6U=", "subType": "00" } }, { "$binary": { "base64": "CiDifI7958sUjNqJUBQULeyF7x0Up3loPWvYKw9uAuw=", "subType": "00" } }, { "$binary": { "base64": "e2dQFsiHqd2BFHNhlSxocjd+cPs4wkcUW/CnCz4KNuM=", "subType": "00" } }, { "$binary": { "base64": "PJFckVmzBipqaEqsuP2mkjhJE4qhw36NhfQ9DcOHyEU=", "subType": "00" } }, { "$binary": { "base64": "S3MeuJhET/B8VcfZYDR9fvX0nscDj416jdDekhmK11s=", "subType": "00" } }, { "$binary": { "base64": "CGVHZRXpuNtQviDB2Kj03Q8uvs4w3RwTgV847R7GwPw=", "subType": "00" } }, { "$binary": { "base64": "yUGgmgyLrxbEpDVy89XN3c2cmFpZXWWmuJ/35zVZ+Jw=", "subType": "00" } }, { "$binary": { "base64": "inb6Q97mL1a9onfNTT8v9wsoi/fz7KXKq3p8j90AU9c=", "subType": "00" } }, { "$binary": { "base64": "CCyYx/4npq9xGO1lsCo8ZJhFO9/tN7DB+/DTE778rYg=", "subType": "00" } }, { "$binary": { "base64": "LNnYw4fwbiAZu0kBdAHPEm/OFnreS+oArdB5O/l/I98=", "subType": "00" } }, { "$binary": { "base64": "P006SxmUS/RjiQJVYPdMFnNo3827GIEmSzagggkg05Q=", "subType": "00" } }, { "$binary": { "base64": "oyvwY+WsnYV6UHuPki1o0ILJ2jN4uyXf9yaUNtZJyBA=", "subType": "00" } }, { "$binary": { "base64": "36Lk3RHWh1wmtCWC/Yj6jNIo17U5y6SofAgQjzjVxD8=", "subType": "00" } }, { "$binary": { "base64": "vOOo8FqeHnuO9mqOYjIb4vgwIwVyXZ5Y+bY5d9tGFUM=", "subType": "00" } }, { "$binary": { "base64": "bJiDJjwQRNxqxlGjRm5lLziFhcfTDCnQ/qU1V85qcRg=", "subType": "00" } }, { "$binary": { "base64": "2Qgrm1n0wUELAQnpkEiIHB856yv76q8jLbpiucetcm0=", "subType": "00" } }, { "$binary": { "base64": "5ciPOYxTK0WDwwYyfs7yiVymwtYQXDELLxmM4JLl4/o=", "subType": "00" } }, { "$binary": { "base64": "31dC2WUSIOKQc4jwT6PikfeYTwi80mTlh7P31T5KNQU=", "subType": "00" } }, { "$binary": { "base64": "YluTV2Mu53EGCKLcWfHZb0BM/IPW2xJdG3vYlDMEsM4=", "subType": "00" } }, { "$binary": { "base64": "dh/8lGo2Ek6KukSwutH6Q35iy8TgV0FN0SJqe0ZVHN8=", "subType": "00" } }, { "$binary": { "base64": "EVw6HpIs3BKen2qY2gz4y5dw1JpXilfh07msZfQqJpc=", "subType": "00" } }, { "$binary": { "base64": "FYolLla9L8EZMROEdWetozroU40Dnmwwx2jIMrr7c1A=", "subType": "00" } }, { "$binary": { "base64": "8M6k4QIutSIj6CM41vvkQtuFsaGrjoR9SZJVSLbfGKQ=", "subType": "00" } }, { "$binary": { "base64": "9LM0VoddDNHway442MqY+Z7vohB2UHau/cddshhzf40=", "subType": "00" } }, { "$binary": { "base64": "66i8Ytco4Yq/FMl6pIRZazz3CZlu8fO2OI6Pne0pvHU=", "subType": "00" } }, { "$binary": { "base64": "2a/HgX+MjZxjXtSvHgF1yEpHMJBkl8Caee8XrJtn0WM=", "subType": "00" } }, { "$binary": { "base64": "frhBM662c4ZVG7mWP8K/HhRjd01lydW/cPcHnDjifqc=", "subType": "00" } }, { "$binary": { "base64": "6k1T7Q1t668PBqv6fwpVnT1HWh7Am5LtbKvwPJKcpGU=", "subType": "00" } }, { "$binary": { "base64": "UlJ5Edfusp8S/Pyhw6KTglIejmbr1HO0zUeHn/qFETA=", "subType": "00" } }, { "$binary": { "base64": "jsxsB+1ECB3assUdoC333do9tYH+LglHmVSJHy4N8Hg=", "subType": "00" } }, { "$binary": { "base64": "2nzIQxGYF7j3bGsIesECEOqhObKs/9ywknPHeJ3yges=", "subType": "00" } }, { "$binary": { "base64": "xJYKtuWrX90JrJVoYtnwP7Ce59XQGFYoalxpNfBXEH0=", "subType": "00" } }, { "$binary": { "base64": "NLI5lriBTleGCELcHBtNnmnvwSRkHHaLOX4cKboMgTw=", "subType": "00" } }, { "$binary": { "base64": "hUOQV0RmE5aJdJww1AR9rirJG4zOYPo+6cCkgn/BGvQ=", "subType": "00" } }, { "$binary": { "base64": "h4G2Of76AgxcUziBwCyH+ayMOpdBWzg4yFrTfehSC2c=", "subType": "00" } }, { "$binary": { "base64": "VuamM75RzGfQpj2/Y1jSVuQLrhy6OAwlZxjuQLB/9Ss=", "subType": "00" } }, { "$binary": { "base64": "kn9+hLq7hvw02xr9vrplOCDXKBTuFhfbX7d5v/l85Pg=", "subType": "00" } }, { "$binary": { "base64": "fAiGqKyLZpGngBYFbtYUYt8LUrJ49vYafiboifTDjxs=", "subType": "00" } }, { "$binary": { "base64": "BxRILymgfVJCczqjUIWXcfrfSgrrYkxTM5VTg0HkZLY=", "subType": "00" } }, { "$binary": { "base64": "CrFY/PzfPU2zsFkGLu/dI6mEeizZzCR+uYgjZBAHro0=", "subType": "00" } }, { "$binary": { "base64": "AEbrIuwvXLTtYgMjOqnGQ8y8axUn5Ukrn7UZRSyfQVw=", "subType": "00" } }, { "$binary": { "base64": "ouWeVH3PEFg+dKWlXc6BmqirJOaVWjJbMzZbCsce4dA=", "subType": "00" } }, { "$binary": { "base64": "+hd6xFB+EG+kVP7WH4uMd1CLaWMnt5xJRaY/Guuga9Q=", "subType": "00" } }, { "$binary": { "base64": "zmpGalfAOL3gmcUMJYcLYIRT/2VDO/1Dw4KdYZoNcng=", "subType": "00" } }, { "$binary": { "base64": "2PbHAoM/46J2UIZ/vyksKzmVVfxA7YUyIxWeL/N/vBk=", "subType": "00" } }, { "$binary": { "base64": "7fD9x+zk5MVFesb59Klqiwwmve7P5ON/5COURXj5smE=", "subType": "00" } }, { "$binary": { "base64": "tlrNQ4jaq051iaWonuv1sSrYhKkL1LtNZuHsvATha3s=", "subType": "00" } }, { "$binary": { "base64": "fBodm28iClNpvlRyVq0dOdXQ08S7/N3aDwid+PdWvRo=", "subType": "00" } }, { "$binary": { "base64": "O+/nnRqT3Zv7yMMGug8GhKHaWy6u7BfRGtZoj0sdN1c=", "subType": "00" } }, { "$binary": { "base64": "5AZZ/RTMY4Photnm/cpXZr/HnFRi3eljacMsipkJLHA=", "subType": "00" } }, { "$binary": { "base64": "oFVyo/kgoMxBIk2VE52ySSimeyU+Gr0EfCwapXnTpKA=", "subType": "00" } }, { "$binary": { "base64": "Z8v59DfcnviA0mzvnUk+URVO0UuqAWvtarEgJva/n1c=", "subType": "00" } }, { "$binary": { "base64": "P64GOntZ+zBJEHkigoh9FSxSO+rJTqR20z5aiGQ9an4=", "subType": "00" } }, { "$binary": { "base64": "xMbSuDPfWuO/Dm7wuVl06GnzG9uzTlJJX9vFy7boGlY=", "subType": "00" } }, { "$binary": { "base64": "kXPB19mRClxdH2UsHwlttS6lLU2uHvzuZgZz7kC45jU=", "subType": "00" } }, { "$binary": { "base64": "NDVjVYXAw4k0w4tFzvs7QDq39aaU3HQor4I2XMKKnCk=", "subType": "00" } }, { "$binary": { "base64": "uKw/+ErVfpTO1dGUfd3T/eWfZW3nUxXCdBGdjvHtZ88=", "subType": "00" } }, { "$binary": { "base64": "av0uxEzWkizYWm0QUM/MN1hLibnxPvCWJKwjOV4yVQY=", "subType": "00" } }, { "$binary": { "base64": "ERwUC47dvgOBzIsEESMIioLYbFOxOe8PtJTnmDkKuHM=", "subType": "00" } }, { "$binary": { "base64": "2gseKlG5Le12fS/vj4eaED4lturF16kAgJ1TpW3HxEE=", "subType": "00" } }, { "$binary": { "base64": "7Cvg0Y3j/5i2F1TeXxlMmU7xwif5dCmwkZAOrVC5K2Y=", "subType": "00" } } ] } ] } } } ] } fle2v2-Range-Decimal-InsertFind.json000066400000000000000000002721531462766011000355610ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/client-side-encryption/spec/legacy{ "runOn": [ { "minServerVersion": "7.0.0", "topology": [ "replicaset" ] } ], "database_name": "default", "collection_name": "default", "data": [], "encrypted_fields": { "fields": [ { "keyId": { "$binary": { "base64": "EjRWeBI0mHYSNBI0VniQEg==", "subType": "04" } }, "path": "encryptedDecimalNoPrecision", "bsonType": "decimal", "queries": { "queryType": "rangePreview", "contention": { "$numberLong": "0" }, "sparsity": { "$numberLong": "1" } } } ] }, "key_vault_data": [ { "_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" } } ], "tests": [ { "description": "FLE2 Range Decimal. Insert and Find.", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "local": { "key": { "$binary": { "base64": "Mng0NCt4ZHVUYUJCa1kxNkVyNUR1QURhZ2h2UzR2d2RrZzh0cFBwM3R6NmdWMDFBMUN3YkQ5aXRRMkhGRGdQV09wOGVNYUMxT2k3NjZKelhaQmRCZGJkTXVyZG9uSjFk", "subType": "00" } } } } } }, "operations": [ { "name": "insertOne", "arguments": { "document": { "_id": 0, "encryptedDecimalNoPrecision": { "$numberDecimal": "0" } } } }, { "name": "insertOne", "arguments": { "document": { "_id": 1, "encryptedDecimalNoPrecision": { "$numberDecimal": "1" } } } }, { "name": "find", "arguments": { "filter": { "encryptedDecimalNoPrecision": { "$gt": { "$numberDecimal": "0" } } } }, "result": [ { "_id": 1, "encryptedDecimalNoPrecision": { "$numberDecimal": "1" } } ] } ], "expectations": [ { "command_started_event": { "command": { "listCollections": 1, "filter": { "name": "default" } }, "command_name": "listCollections" } }, { "command_started_event": { "command": { "find": "datakeys", "filter": { "$or": [ { "_id": { "$in": [ { "$binary": { "base64": "EjRWeBI0mHYSNBI0VniQEg==", "subType": "04" } } ] } }, { "keyAltNames": { "$in": [] } } ] }, "$db": "keyvault", "readConcern": { "level": "majority" } }, "command_name": "find" } }, { "command_started_event": { "command": { "insert": "default", "documents": [ { "_id": 0, "encryptedDecimalNoPrecision": { "$$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": "encryptedDecimalNoPrecision", "bsonType": "decimal", "queries": { "queryType": "rangePreview", "contention": { "$numberLong": "0" }, "sparsity": { "$numberLong": "1" } } } ] } } } }, "command_name": "insert" } }, { "command_started_event": { "command": { "insert": "default", "documents": [ { "_id": 1, "encryptedDecimalNoPrecision": { "$$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": "encryptedDecimalNoPrecision", "bsonType": "decimal", "queries": { "queryType": "rangePreview", "contention": { "$numberLong": "0" }, "sparsity": { "$numberLong": "1" } } } ] } } } }, "command_name": "insert" } }, { "command_started_event": { "command": { "find": "default", "filter": { "encryptedDecimalNoPrecision": { "$gt": { "$binary": { "base64": "DeFiAAADcGF5bG9hZACxYgAABGcAnWIAAAMwAH0AAAAFZAAgAAAAAJu2KgiI8vM+kz9qD3ZQzFQY5qbgYqCqHG5R4jAlnlwXBXMAIAAAAAAAUXxFXsz764T79sGCdhxvNd5b6E/9p61FonsHyEIhogVsACAAAAAAt19RL3Oo5ni5L8kcvgOJYLgVYyXJExwP8pkuzLG7f/kAAzEAfQAAAAVkACAAAAAAPQPvL0ARjujSv2Rkm8r7spVsgeC1K3FWcskGGZ3OdDIFcwAgAAAAACgNn660GmefR8jLqzgR1u5O+Uocx9GyEHiBqVGko5FZBWwAIAAAAADflr+fsnZngm6KRWYgHa9JzK+bXogWl9evBU9sQUHPHQADMgB9AAAABWQAIAAAAAD2Zi6kcxmaD2mY3VWrP+wYJMPg6cSBIYPapxaFQxYFdQVzACAAAAAAM/cV36BLBY3xFBXsXJY8M9EHHOc/qrmdc2CJmj3M89gFbAAgAAAAAOpydOrKxx6m2gquSDV2Vv3w10GocmNCFeOo/fRhRH9JAAMzAH0AAAAFZAAgAAAAAOaNqI9srQ/mI9gwbk+VkizGBBH/PPWOVusgnfPk3tY1BXMAIAAAAAAc96O/pwKCmHCagT6T/QV/wz4vqO+R22GsZ1dse2Vg6QVsACAAAAAAgzIak+Q3UFLTHXPmJ+MuEklFtR3eLtvM+jdKkmGCV/YAAzQAfQAAAAVkACAAAAAA0XlQgy/Yu97EQOjronl9b3dcR1DFn3deuVhtTLbJZHkFcwAgAAAAACoMnpVl6EFJak8A+t5N4RFnQhkQEBnNAx8wDqmq5U/dBWwAIAAAAACR26FJif673qpwF1J1FEkQGJ1Ywcr/ZW6JQ7meGqzt1QADNQB9AAAABWQAIAAAAAAOtpNexRxfv0yRFvZO9DhlkpU4mDuAb8ykdLnE5Vf1VAVzACAAAAAAeblFKm/30orP16uQpZslvsoS8s0xfNPIBlw3VkHeekYFbAAgAAAAAPEoHj87sYE+nBut52/LPvleWQBzB/uaJFnosxp4NRO2AAM2AH0AAAAFZAAgAAAAAIr8xAFm1zPmrvW4Vy5Ct0W8FxMmyPmFzdWVzesBhAJFBXMAIAAAAABYeeXjJEzTHwxab6pUiCRiZjxgtN59a1y8Szy3hfkg+gVsACAAAAAAJuoY4rF8mbI+nKb+5XbZShJ8191o/e8ZCRHE0O4Ey8MAAzcAfQAAAAVkACAAAAAAl+ibLk0/+EwoqeC8S8cGgAtjtpQWGEZDsybMPnrrkwEFcwAgAAAAAHPPBudWgQ+HUorLDpJMqhS9VBF2VF5aLcxgrM1s+yU7BWwAIAAAAAAcCcBR2Vyv5pAFbaOU97yovuOi1+ATDnLLcAUqHecXcAADOAB9AAAABWQAIAAAAACR9erwLTb+tcWFZgJ2MEfM0PKI9uuwIjDTHADRFgD+SQVzACAAAAAAcOop8TXsGUVQoKhzUllMYWxL93xCOkwtIpV8Q6hiSYYFbAAgAAAAAKXKmh4V8veYwob1H03Q3p3PN8SRAaQwDT34KlNVUjiDAAM5AH0AAAAFZAAgAAAAALv0vCPgh7QpmM8Ug6ad5ioZJCh7pLMdT8FYyQioBQ6KBXMAIAAAAADsCPyIG8t6ApQkRk1fX/sfc1kpuWCWP8gAEpnYoBSHrQVsACAAAAAAJe/r67N6d8uTiogvfoR9rEXbIDjyLb9EVdqkayFFGaYAAzEwAH0AAAAFZAAgAAAAAIW4AxJgYoM0pcNTwk1RSbyjZGIqgKL1hcTJmNrnZmoPBXMAIAAAAAAZpfx3EFO0vY0f1eHnE0PazgqeNDTaj+pPJMUNW8lFrAVsACAAAAAAP+Um2vwW6Bj6vuz9DKz6+6aWkoKoEmFNoiz/xXm7lOsAAzExAH0AAAAFZAAgAAAAAKliO6L9zgeuufjj174hvmQGNRbmYYs9yAirL7OxwEW3BXMAIAAAAAAqU7vs3DWUQ95Eq8OejwWnD0GuXd+ASi/uD6S0l8MM1QVsACAAAAAAb9legYzsfctBPpHyl7YWpPmLr5QiNZFND/50N1vv2MUAAzEyAH0AAAAFZAAgAAAAAOGQcCBkk+j/Kzjt/Cs6g3BZPJG81wIHBS8JewHGpgk+BXMAIAAAAABjrxZXWCkdzrExwCgyHaafuPSQ4V4x2k9kUCAqUaYKDQVsACAAAAAADBU6KefT0v8zSmseaMNmQxKjJar72y7MojLFhkEHqrUAAzEzAH0AAAAFZAAgAAAAAPmCNEt4t97waOSd5hNi2fNCdWEkmcFJ37LI9k4Az4/5BXMAIAAAAABX7DuDPNg+duvELf3NbLWkPMFw2HGLgWGHyVWcPvSNCAVsACAAAAAAS7El1FtZ5STh8Q1FguvieyYX9b2DF1DFVsb9hzxXYRsAAzE0AH0AAAAFZAAgAAAAAD4vtVUYRNB+FD9yoQ2FVJH3nMeJeKbi6eZfth638YqbBXMAIAAAAAANCuUB4OdmuD6LaDK2f3vaqfgYYvg40wDXOBbcFjTqLwVsACAAAAAA9hqC2VoJBjwR7hcQ45xO8ZVojwC83jiRacCaDj6Px2gAAzE1AH0AAAAFZAAgAAAAAJPIRzjmTjbdIvshG6UslbEOd797ZSIdjGAhGWxVQvK1BXMAIAAAAABgmJ0Jh8WLs9IYs/a7DBjDWd8J3thW/AGJK7zDnMeYOAVsACAAAAAAi9zAsyAuou2oiCUHGc6QefLUkACa9IgeBhGu9W/r0X8AAzE2AH0AAAAFZAAgAAAAAABQyKQPoW8wGPIqnsTv69+DzIdRkohRhOhDmyVHkw9WBXMAIAAAAAAqWA2X4tB/h3O1Xlawtz6ndI6WaTwgU1QYflL35opu5gVsACAAAAAAWI/Gj5aZMwDIxztqmVL0g5LBcI8EdKEc2UA28pnekQoAAzE3AH0AAAAFZAAgAAAAACB7NOyGQ1Id3MYnxtBXqyZ5Ul/lHH6p1b10U63DfT6bBXMAIAAAAADpOryIcndxztkHSfLN3Kzq29sD8djS0PspDSqERMqokQVsACAAAAAADatsMW4ezgnyi1PiP7xk+gA4AFIN/fb5uJqfVkjg4UoAAzE4AH0AAAAFZAAgAAAAAKVfXLfs8XA14CRTB56oZwV+bFJN5BHraTXbqEXZDmTkBXMAIAAAAAASRWTsfGOpqdffiOodoqIgBzG/yzFyjR5CfUsIUIWGpgVsACAAAAAAkgCHbCwyX640/0Ni8+MoYxeHUiC+FSU4Mn9jTLYtgZgAAzE5AH0AAAAFZAAgAAAAAH/aZr4EuS0/noQR9rcF8vwoaxnxrwgOsSJ0ys8PkHhGBXMAIAAAAACd7ObGQW7qfddcvyxRTkPuvq/PHu7+6I5dxwS1Lzy5XAVsACAAAAAA3q0eKdV7KeU3pc+CtfypKR7BPxwaf30yu0j9FXeOOboAAzIwAH0AAAAFZAAgAAAAAKvlcpFFNq0oA+urq3w6d80PK1HHHw0H0yVWvU9aHijXBXMAIAAAAADWnAHQ5Fhlcjawki7kWzdqjM2f6IdGJblojrYElWjsZgVsACAAAAAAO0wvY66l24gx8nRxyVGC0QcTztIi81Kx3ndRhuZr6W4AAzIxAH0AAAAFZAAgAAAAAH/2aMezEOddrq+dNOkDrdqf13h2ttOnexZsJxG1G6PNBXMAIAAAAABNtgnibjC4VKy5poYjvdsBBnVvDTF/4mmEAxsXVgZVKgVsACAAAAAAqvadzJFLqQbs8WxgZ2D2X+XnaPSDMLCVVgWxx5jnLcYAAzIyAH0AAAAFZAAgAAAAAF2wZoDL6/V59QqO8vdRZWDpXpkV4h4KOCSn5e7x7nmzBXMAIAAAAADLZBu7LCYjbThaVUqMK14H/elrVOYIKJQCx4C9Yjw37gVsACAAAAAAEh6Vs81jLU204aGpL90fmYTm5i5R8/RT1uIbg6VU3HwAAzIzAH0AAAAFZAAgAAAAAH27yYaLn9zh2CpvaoomUPercSfJRUmBY6XFqmhcXi9QBXMAIAAAAAAUwumVlIYIs9JhDhSj0R0+59psCMsFk94E62VxkPt42QVsACAAAAAAT5x2hCCd2bpmpnyWaxas8nSxTc8e4C9DfKaqr0ABEysAAzI0AH0AAAAFZAAgAAAAALMg2kNAO4AFFs/mW3In04yFeN4AP6Vo0klyUoT06RquBXMAIAAAAAAgGWJbeIdwlpqXCyVIYSs0dt54Rfc8JF4b8uYc+YUj0AVsACAAAAAAWHeWxIkyvXTOWvfZzqtPXjfGaWWKjGSIQENTU3zBCrsAAzI1AH0AAAAFZAAgAAAAALas/i1T2DFCEmrrLEi7O2ngJZyFHialOoedVXS+OjenBXMAIAAAAAA1kK0QxY4REcGxHeMkgumyF7iwlsRFtw9MlbSSoQY7uAVsACAAAAAAUNlpMJZs1p4HfsD4Q4WZ4TBEi6Oc2fX34rzyynqWCdwAAzI2AH0AAAAFZAAgAAAAAP1TejmWg1CEuNSMt6NUgeQ5lT+oBoeyF7d2l5xQrbXWBXMAIAAAAABPX0kj6obggdJShmqtVfueKHplH4ZrXusiwrRDHMOKeQVsACAAAAAAIYOsNwC3DA7fLcOzqdr0bOFdHCfmK8tLwPoaE9uKOosAAzI3AH0AAAAFZAAgAAAAAMrKn+QPa/NxYezNhlOX9nyEkN1kE/gW7EuZkVqYl0b8BXMAIAAAAABUoZMSPUywRGfX2EEencJEKH5x/P9ySUVrhStAwgR/LgVsACAAAAAAMgZFH6lQIIDrgHnFeslv3ld20ynwQjQJt3cAp4GgrFkAAzI4AH0AAAAFZAAgAAAAAMmD1+a+oVbiUZd1HuZqdgtdVsVKwuWAn3/M1B6QGBM3BXMAIAAAAACLyytOYuZ9WEsIrrtJbXUx4QgipbaAbmlJvSZVkGi0CAVsACAAAAAA4v1lSp5H9BB+HYJ4bH43tC8aeuPZMf78Ng1JOhJh190AAzI5AH0AAAAFZAAgAAAAAOVKV7IuFwmYP1qVv8h0NvJmfPICu8yQhzjG7oJdTLDoBXMAIAAAAABL70XLfQLKRsw1deJ2MUvxSWKxpF/Ez73jqtbLvqbuogVsACAAAAAAvfgzIorXxE91dDt4nQxYfntTsx0M8Gzdsao5naQqcRUAAzMwAH0AAAAFZAAgAAAAAKS/1RSAQma+xV9rz04IcdzmavtrBDjOKPM+Z2NEyYfPBXMAIAAAAAAOJDWGORDgfRv8+w5nunh41wXb2hCA0MRzwnLnQtIqPgVsACAAAAAAf42C1+T7xdHEFF83+c2mF5S8PuuL22ogXXELnRAZ4boAAzMxAH0AAAAFZAAgAAAAAFeq8o82uNY1X8cH6OhdTzHNBUnCChsEDs5tm0kPBz3qBXMAIAAAAABaxMBbsaeEj/EDtr8nZfrhhhirBRPJwVamDo5WwbgvTQVsACAAAAAAMbH453A+BYAaDOTo5kdhV1VdND1avNwvshEG/4MIJjQAAzMyAH0AAAAFZAAgAAAAAI8IKIfDrohHh2cjspJHCovqroSr5N3QyVtNzFvT5+FzBXMAIAAAAABXHXteKG0DoOMmECKp6ro1MZNQvXGzqTDdZ0DUc8QfFAVsACAAAAAA/w5s++XYmO+9TWTbtGc3n3ndV4T9JUribIbF4jmDLSMAAzMzAH0AAAAFZAAgAAAAAJkHvm15kIu1OtAiaByj5ieWqzxiu/epK6c/9+KYIrB0BXMAIAAAAACzg5TcyANk0nes/wCJudd1BwlkWWF6zw3nGclq5v3SJQVsACAAAAAAvruXHTT3irPJLyWpI1j/Xwf2FeIE/IV+6Z49pqRzISoAAzM0AH0AAAAFZAAgAAAAAAYSOvEWWuSg1Aym7EssNLR+xsY7e9BcwsX4JKlnSHJcBXMAIAAAAABT48eY3PXVDOjw7JpNjOe1j2JyI3LjDnQoqZ8Je5B2KgVsACAAAAAAU2815RR57TQ9uDg0XjWjBkAKvf8yssxDMzrM4+FqP6AAAzM1AH0AAAAFZAAgAAAAAGQxC9L1e9DfO5XZvX1yvc3hTLtQEdKO9FPMkyg0Y9ZABXMAIAAAAADtmcMNJwdWLxQEArMGZQyzpnu+Z5yMmPAkvgq4eAKwNQVsACAAAAAAJ88zt4Y/Hoqh+zrf6KCOiUwHbOzCxSfp6k/qsZaYGEgAAzM2AH0AAAAFZAAgAAAAADLHK2LNCNRO0pv8n4fAsxwtUqCNnVK8rRgNiQfXpHSdBXMAIAAAAACf16EBIHRKD3SzjRW+LMOl+47QXA3CJhMzlcqyFRW22AVsACAAAAAAMGz4fAOa0EoVv90fUffwLjBrQhHATf+NdlgCR65vujAAAzM3AH0AAAAFZAAgAAAAAHiZJiXKNF8bbukQGsdYkEi95I+FSBHy1I5/hK2uEZruBXMAIAAAAADE+lZBa8HDUJPN+bF6xI9x4N7GF9pj3vBR7y0BcfFhBAVsACAAAAAAGIEN6sfqq30nyxW4dxDgXr/jz5HmvA9T1jx/pKCn4zgAAzM4AH0AAAAFZAAgAAAAAI1oa2OIw5TvhT14tYCGmhanUoYcCZtNbrVbeoMldHNZBXMAIAAAAAAx2nS0Ipblf2XOgBiUOuJFBupBhe7nb6QPLZlA4aMPCgVsACAAAAAA9xu828hugIgo0E3de9dZD+gTpVUGlwtDba+tw/WcbUoAAzM5AH0AAAAFZAAgAAAAABgTWS3Yap7Q59hii/uPPimHWXsr+DUmsqfwt/X73qsOBXMAIAAAAACKK05liW5KrmEAvtpCB1WUltruzUylDDpjea//UlWoOAVsACAAAAAAcgN4P/wakJ5aJK5c1bvJBqpVGND221dli2YicPFfuAYAAzQwAH0AAAAFZAAgAAAAABOAnBPXDp6i9TISQXvcNKwGDLepZTu3cKrB4vKnSCjBBXMAIAAAAADjjzZO7UowAAvpwyG8BNOVqLCccMFk3aDK4unUeft5ywVsACAAAAAA4zkCd4k9gvfXoD1C7vwTjNcdVJwEARh8h/cxZ4PNMfgAAzQxAH0AAAAFZAAgAAAAAHN8hyvT1lYrAsdiV5GBdd5jhtrAYE/KnSjw2Ka9hjz9BXMAIAAAAAD794JK7EeXBs+D7yOVK7nWF8SbZ/7U8gZ7nnT9JFNwTAVsACAAAAAAg8Wt1HO3NhByq2ggux2a4Lo6Gryr24rEFIqh2acrwWMAAzQyAH0AAAAFZAAgAAAAAO93bPrq8bsnp1AtNd9ETnXIz0lH/2HYN/vuw9wA3fyFBXMAIAAAAABHlls5fbaF2oAGqptC481XQ4eYxInTC29aElfmVZgDUgVsACAAAAAANoQXEWpXJpgrSNK/cKi/m7oYhuSRlp1IZBF0bqTEATcAAzQzAH0AAAAFZAAgAAAAAL1YsAZm1SA0ztU6ySIrQgCCA74V6rr0/4iIygCcaJL6BXMAIAAAAADTXWTHWovGmUR1Zg9l/Aqq9H5mOCJQQrb/Dfae7e3wKAVsACAAAAAA5dunyJK6/SVfDD0t9QlNBcFqoZnf9legRjHaLSKAoQMAAzQ0AH0AAAAFZAAgAAAAAEoFAeHk0RZ9kD+cJRD3j7PcE5gzWKnyBrF1I/MDNp5mBXMAIAAAAACgHtc2hMBRSZjKw8RAdDHK+Pi1HeyjiBuAslGVNcW5tAVsACAAAAAAXzBLfq+GxRtX4Wa9fazA49DBLG6AjZm2XODStJKH8D0AAzQ1AH0AAAAFZAAgAAAAAAW+7DmSN/LX+/0uBVJDHIc2dhxAGz4+ehyyz8fAnNGoBXMAIAAAAAA6Ilw42EvvfLJ3Eq8Afd+FjPoPcQutZO6ltmCLEr8kxQVsACAAAAAAbbZalyo07BbFjPFlYmbmv0z023eT9eLkHqeVUnfUAUAAAzQ2AH0AAAAFZAAgAAAAANBdV7M7kuYO3EMoQItAbXv4t2cIhfaT9V6+s4cg9djlBXMAIAAAAABvz4MIvZWxxrcJCL5qxLfFhXiUYB1OLHdKEjco94SgDgVsACAAAAAAK2GVGvyPIKolF/ECcmfmkVcf1/IZNcaTv96N92yGrkEAAzQ3AH0AAAAFZAAgAAAAAMoAoiAn1kc79j5oPZtlMWHMhhgwNhLUnvqkqIFvcH1NBXMAIAAAAADcJTW7WiCyW0Z9YDUYwppXhLj4Ac1povpJvcAq+i48MQVsACAAAAAAIGxGDzoeB3PTmudl4+j6piQB++e33EEzuzAiXcqGxvUAAzQ4AH0AAAAFZAAgAAAAACI3j5QP7dWHpcT6WO/OhsWwRJNASBYqIBDNzW8IorEyBXMAIAAAAABxUpBSjXwCKDdGP9hYU+RvyR+96kChfvyyRC4jZmztqAVsACAAAAAAvBCHguWswb4X0xdcAryCvZgQuthXzt7597bJ5VxAMdgAAzQ5AH0AAAAFZAAgAAAAAKsbycEuQSeNrF8Qnxqw3x3og8JmQabwGqnDbqzFRVrrBXMAIAAAAACno/3ef2JZJS93SVVzmOZSN+jjJHT8s0XYq2M46d2sLAVsACAAAAAAAt5zLJG+/j4K8rnkFtAn8IvdUVNefe6utJ3rdzgwudIAAzUwAH0AAAAFZAAgAAAAAPXIcoO8TiULqlxzb74NFg+I8kWX5uXIDUPnh2DobIoMBXMAIAAAAADR6/drkdTpnr9g1XNvKDwtBRBdKn7c2c4ZNUVK5CThdQVsACAAAAAAJqOA1c6KVog3F4Hb/GfDb3jCxXDRTqpXWSbMH4ePIJsAAzUxAH0AAAAFZAAgAAAAAEa03ZOJmfHT6/nVadvIw71jVxEuIloyvxXraYEW7u7pBXMAIAAAAADzRlBJK75FLiKjz3djqcgjCLo/e3yntI3MnPS48OORhgVsACAAAAAAnQhx4Rnyj081XrLRLD5NLpWmRWCsd0M9Hl7Jl19R0h8AAzUyAH0AAAAFZAAgAAAAAKx8NLSZUU04pSSGmHa5fh2oLHsEN5mmNMNHL95/tuC9BXMAIAAAAAA59hcXVaN3MNdHoo11OcH1aPRzHCwpVjO9mGfMz4xh3QVsACAAAAAAYIPdjV2XbPj7dBeHPwnwhVU7zMuJ+xtMUW5mIOYtmdAAAzUzAH0AAAAFZAAgAAAAAHNKAUxUqBFNS9Ea9NgCZoXMWgwhP4x0/OvoaPRWMquXBXMAIAAAAABUZ551mnP4ZjX+PXU9ttomzuOpo427MVynpkyq+nsYCQVsACAAAAAALnVK5p2tTTeZEh1zYt4iqKIQT9Z0si//Hy1L85oF+5IAAzU0AH0AAAAFZAAgAAAAALfGXDlyDVcGaqtyHkLT0qpuRhJQLgCxtznazhFtuyn/BXMAIAAAAABipxlXDq14C62pXhwAeen5+syA+/C6bN4rtZYcO4zKwAVsACAAAAAAXUf0pzUq0NhLYagWDap4uEiwq5rLpcx29rWbt1NYMsMAAzU1AH0AAAAFZAAgAAAAANoEr8sheJjg4UCfBkuUzarU9NFoy1xwbXjs5ifVDeA9BXMAIAAAAABPoyTf6M+xeZVGES4aNzVlq7LgjqZXJ/QunjYVusGUEAVsACAAAAAA1hA2gMeZZPUNytk9K+lB1RCqWRudRr7GtadJlExJf8oAAzU2AH0AAAAFZAAgAAAAAKvDiK+xjlBe1uQ3SZTNQl2lClIIvpP/5CHwY6Kb3WlgBXMAIAAAAAANnxImq5MFbWaRBHdJp+yD09bVlcFtiFDYsy1eDZj+iQVsACAAAAAAWtsyO+FxMPSIezwsV1TJD8ZrXAdRnQM6DJ+f+1V3qEkAAzU3AH0AAAAFZAAgAAAAAF49IlFH9RmSUSvUQpEPUedEksrQUcjsOv44nMkwXhjzBXMAIAAAAADJtWGbk0bZzmk20obz+mNsp86UCu/nLLlbg7ppxYn7PgVsACAAAAAA3k0Tj/XgPQtcYijH8cIlQoe/VXf15q1nrZNmg7yWYEgAAzU4AH0AAAAFZAAgAAAAAOuSJyuvz50lp3BzXlFKnq62QkN2quNU1Gq1IDsnFoJCBXMAIAAAAAAqavH1d93XV3IzshWlMnzznucadBF0ND092/2ApI1AcAVsACAAAAAAzUrK4kpoKCmcpdZlZNI13fddjdoAseVe67jaX1LobIIAAzU5AH0AAAAFZAAgAAAAALtgC4Whb4ZdkCiI30zY6fwlsxSa7lEaOAU3SfUXr02XBXMAIAAAAACgdZ6U1ZVgUaZZwbIaCdlANpCw6TZV0bwg3DS1NC/mnAVsACAAAAAAzI49hdpp0PbO7S2KexISxC16sE73EUAEyuqUFAC/J48AAzYwAH0AAAAFZAAgAAAAAF6PfplcGp6vek1ThwenMHVkbZgrc/dHgdsgx1VdPqZ5BXMAIAAAAACha3qhWkqmuwJSEXPozDO8y1ZdRLyzt9Crt2vjGnT7AAVsACAAAAAA7nvcU59+LwxGupSF21jAeAE0x7JE94tjRkJfgM1yKU8AAzYxAH0AAAAFZAAgAAAAAKoLEhLvLjKc7lhOJfx+VrGJCx9tXlOSa9bxQzGR6rfbBXMAIAAAAAAIDK5wNnjRMBzET7x/KAMExL/zi1IumJM92XTgXfoPoAVsACAAAAAAFkUYWFwNr815dEdFqp+TiIozDcq5IBNVkyMoDjharDQAAzYyAH0AAAAFZAAgAAAAADoQv6lutRmh5scQFvIW6K5JBquLxszuygM1tzBiGknIBXMAIAAAAADAD+JjW7FoBQ76/rsECmmcL76bmyfXpUU/awqIsZdO+wVsACAAAAAAPFHdLw3jssmEXsgtvl/RBNaUCRA1kgSwsofG364VOvQAAzYzAH0AAAAFZAAgAAAAAJNHUGAgn56KekghO19d11nai3lAh0JAlWfeP+6w4lJBBXMAIAAAAAD9XGJlvz59msJvA6St9fKW9CG4JoHV61rlWWnkdBRLzwVsACAAAAAAxwP/X/InJJHmrjznvahIMgj6pQR30B62UtHCthSjrP0AAzY0AH0AAAAFZAAgAAAAAHgYoMGjEE6fAlAhICv0+doHcVX8CmMVxyq7+jlyGrvmBXMAIAAAAAC/5MQZgTHuIr/O5Z3mXPvqrom5JTQ8IeSpQGhO9sB+8gVsACAAAAAAuPSXVmJUAUpTQg/A9Bu1hYczZF58KEhVofakygbsvJQAAzY1AH0AAAAFZAAgAAAAANpIljbxHOM7pydY877gpRQvYY2TGK7igqgGsavqGPBABXMAIAAAAAAqHyEu9gpurPOulApPnr0x9wrygY/7mXe9rAC+tPK80wVsACAAAAAA7gkPzNsS3gCxdFBWbSW9tkBjoR5ib+saDvpGSB3A3ogAAzY2AH0AAAAFZAAgAAAAAGR+gEaZTeGNgG9BuM1bX2R9ed4FCxBA9F9QvdQDAjZwBXMAIAAAAABSkrYFQ6pf8MZ1flgmeIRkxaSh/Eep4Btdx4QYnGGnwAVsACAAAAAApRovMiV00hm/pEcT4XBsyPNw0eo8RLAX/fuabjdU+uwAAzY3AH0AAAAFZAAgAAAAAFNprhQ3ZwIcYbuzLolAT5n/vc14P9kUUQComDu6eFyKBXMAIAAAAAAcx9z9pk32YbPV/sfPZl9ALIEVsqoLXgqWLVK/tP+heAVsACAAAAAA/qxvuvJbAHwwhfrPVpmCFzNvg2cU/NXaWgqgYUZpgXwAAzY4AH0AAAAFZAAgAAAAADgyPqQdqQrgfmJjRFAILTHzXbdw5kpKyfeoEcy6YYG/BXMAIAAAAAAE+3XsBQ8VAxAkN81au+f3FDeCD/s7KoZD+fnM1MJSSAVsACAAAAAAhRnjrXecwV0yeCWKJ5J/x12Xx4qVJahsCEVHB/1U2rcAAzY5AH0AAAAFZAAgAAAAAI0CT7JNngTCTUSei1Arw7eHWCD0jumv2rb7imjWIlWABXMAIAAAAABSP8t6ya0SyCphXMwnru6ZUDXWElN0NfBvEOhDvW9bJQVsACAAAAAAGWeGmBNDRaMtvm7Rv+8TJ2sJ4WNXKcp3tqpv5Se9Ut4AAzcwAH0AAAAFZAAgAAAAAD/FIrGYFDjyYmVb7oTMVwweWP7A6F9LnyIuNO4MjBnXBXMAIAAAAACIZgJCQRZu7NhuNMyOqCn1tf+DfU1qm10TPCfj5JYV3wVsACAAAAAA5hmY4ptuNxULGf87SUFXQWGAONsL9U29duh8xqsHtxoAAzcxAH0AAAAFZAAgAAAAAHIkVuNDkSS1cHIThKc/O0r2/ubaABTOi8Q1r/dvBAsEBXMAIAAAAADdHYqchEiJLM340c3Q4vJABmmth3+MKzwLYlsG6GS7sQVsACAAAAAADa+KP/pdTiG22l+ZWd30P1iHjnBF4zSNRdFm0oEK82kAAzcyAH0AAAAFZAAgAAAAAJmoDILNhC6kn3masElfnjIjP1VjsjRavGk1gSUIjh1NBXMAIAAAAAD97Ilvp3XF8T6MmVVcxMPcdL80RgQ09UoC6PnoOvZ1IQVsACAAAAAA2RK3Xng6v8kpvfVW9tkVXjpE+BSnx9/+Fw85Evs+kUEAAzczAH0AAAAFZAAgAAAAAI5bm3YO0Xgf0VT+qjVTTfvckecM3Cwqj7DTKZXf8/NXBXMAIAAAAAD/m+h8fBhWaHm6Ykuz0WX1xL4Eme3ErLObyEVJf8NCywVsACAAAAAAfb1VZZCqs2ivYbRzX4p5CtaCkKW+g20Pr57FWXzEZi8AAzc0AH0AAAAFZAAgAAAAANqo4+p6qdtCzcB4BX1wQ6llU7eFBnuu4MtZwp4B6mDlBXMAIAAAAAAGiz+VaukMZ+6IH4jtn4KWWdKK4/W+O+gRioQDrfzpMgVsACAAAAAAG4YYkTp80EKo59mlHExDodRQFR7njhR5dmISwUJ6ukAAAzc1AH0AAAAFZAAgAAAAAPrFXmHP2Y4YAm7b/aqsdn/DPoDkv7B8egWkfe23XsM1BXMAIAAAAAAGhwpKAr7skeqHm3oseSbO7qKNhmYsuUrECBxJ5k+D2AVsACAAAAAAAqPQi9luYAu3GrFCEsVjd9z2zIDcp6SPTR2w6KQEr+IAAzc2AH0AAAAFZAAgAAAAABzjYxwAjXxXc0Uxv18rH8I3my0Aguow0kTwKyxbrm+cBXMAIAAAAADVbqJVr6IdokuhXkEtXF0C2gINLiAjMVN20lE20Vmp2QVsACAAAAAAD7K1Fx4gFaaizkIUrf+EGXQeG7QX1jadhGc6Ji471H8AAzc3AH0AAAAFZAAgAAAAAFMm2feF2fFCm/UC6AfIyepX/xJDSmnnolQIBnHcPmb5BXMAIAAAAABLI11kFrQoaNVZFmq/38aRNImPOjdJh0Lo6irI8M/AaAVsACAAAAAAOWul0oVqJ9CejD2RqphhTC98DJeRQy5EwbNerU2+4l8AAzc4AH0AAAAFZAAgAAAAAJvXB3KyNiNtQko4SSzo/9b2qmM2zU9CQTTDfLSBWMgRBXMAIAAAAAAvjuVP7KsLRDeqVqRziTKpBrjVyqKiIbO9Gw8Wl2wFTAVsACAAAAAADlE+oc1ins+paNcaOZJhBlKlObDJ4VQORWjFYocM4LgAAzc5AH0AAAAFZAAgAAAAAPGdcxDiid8z8XYnfdDivNMYVPgBKdGOUw6UStU+48CdBXMAIAAAAAARj6g1Ap0eEfuCZ4X2TsEw+Djrhto3fA5nLwPaY0vCTgVsACAAAAAAoHqiwGOUkBu8SX5U1yHho+UIFdSN2MdQN5s6bQ0EsJYAAzgwAH0AAAAFZAAgAAAAAP5rGPrYGt3aKob5f/ldP0qrW7bmWvqnKY4QwdDWz400BXMAIAAAAADTQkW2ymaaf/bhteOOGmSrIR97bAnJx+yN3yMj1bTeewVsACAAAAAADyQnHGH2gF4w4L8axUsSTf6Ubk7L5/eoFOJk12MtZAoAAzgxAH0AAAAFZAAgAAAAAAlz6wJze5UkIxKpJOZFGCOf3v2KByWyI6NB6JM9wNcBBXMAIAAAAABUC7P/neUIHHoZtq0jFVBHY75tSFYr1Y5S16YN5XxC1QVsACAAAAAAgvxRbXDisNnLY3pfsjDdnFLtkvYUC4lhA68eBXc7KAwAAzgyAH0AAAAFZAAgAAAAAFJ8AtHcjia/9Y5pLEc3qVgH5xKiXw12G9Kn2A1EY8McBXMAIAAAAAAxe7Bdw7eUSBk/oAawa7uicTEDgXLymRNhBy1LAxhDvwVsACAAAAAAxKPaIBKVx3jTA+R/el7P7AZ7efrmTGjJs3Hj/YdMddwAAzgzAH0AAAAFZAAgAAAAAO8uwQUaKFb6vqR3Sv3Wn4QAonC2exOC9lGG1juqP5DtBXMAIAAAAABZf1KyJgQg8/Rf5c02DgDK2aQu0rNCOvaL60ohDHyY+gVsACAAAAAAqyEjfKC8lYoIfoXYHUqHZPoaA6EK5BAZy5dxXZmay4kAAzg0AH0AAAAFZAAgAAAAAE8YtqyRsGCeiR6hhiyisR/hccmK4nZqIMzO4lUBmEFzBXMAIAAAAAC1UYOSKqAeG1UJiKjWFVskRhuFKpj9Ezy+lICZvFlN5AVsACAAAAAA6Ct9nNMKyRazn1OKnRKagm746CGu+jyhbL1qJnZxGi0AAzg1AH0AAAAFZAAgAAAAAPhCrMausDx1QUIEqp9rUdRKyM6a9AAx7jQ3ILIu8wNIBXMAIAAAAACmH8lotGCiF2q9VQxhsS+7LAZv79VUAsOUALaGxE/EpAVsACAAAAAAnc1xCKfdvbUEc8F7XZqlNn1C+hZTtC0I9I3LL06iaNkAAzg2AH0AAAAFZAAgAAAAAOBi/GAYFcstMSJPgp3VkMiuuUUCrZytvqYaU8dwm8v2BXMAIAAAAACEZSZVyD3pKzGlbdwlYmWQhHHTV5SnNLknl2Gw8IaUTQVsACAAAAAAfsLZsEDcWSuNsIo/TD1ReyQW75HPMgmuKZuWFOLKRLoAAzg3AH0AAAAFZAAgAAAAAIQuup+YGfH3mflzWopN8J1X8o8a0d9CSGIvrA5HOzraBXMAIAAAAADYvNLURXsC2ITMqK14LABQBI+hZZ5wNf24JMcKLW+84AVsACAAAAAACzfjbTBH7IwDU91OqLAz94RFkoqBOkzKAqQb55gT4/MAAzg4AH0AAAAFZAAgAAAAAKsh0ADyOnVocFrOrf6MpTrNvAj8iaiE923DPryu124gBXMAIAAAAADg24a8NVE1GyScc6tmnTbmu5ulzO+896fE92lN08MeswVsACAAAAAAaPxcOIxnU7But88/yadOuDJDMcCywwrRitaxMODT4msAAzg5AH0AAAAFZAAgAAAAAKkVC2Y6HtRmv72tDnPUSjJBvse7SxLqnr09/Uuj9sVVBXMAIAAAAABYNFUkH7ylPMN+Bc3HWX1e0flGYNbtJNCY9SltJCW/UAVsACAAAAAAZYK/f9H4OeihmpiFMH7Wm7uLvs2s92zNA8wyrNZTsuMAAzkwAH0AAAAFZAAgAAAAADDggcwcb/Yn1Kk39sOHsv7BO/MfP3m/AJzjGH506Wf9BXMAIAAAAAAYZIsdjICS0+BDyRUPnrSAZfPrwtuMaEDEn0/ijLNQmAVsACAAAAAAGPnYVvo2ulO9z4LGd/69NAklfIcZqZvFX2KK0s+FcTUAAzkxAH0AAAAFZAAgAAAAAEWY7dEUOJBgjOoWVht1wLehsWAzB3rSOBtLgTuM2HC8BXMAIAAAAAAAoswiHRROurjwUW8u8D5EUT+67yvrgpB/j6PzBDAfVwVsACAAAAAA6NhRTYFL/Sz4tao7vpPjLNgAJ0FX6P/IyMW65qT6YsMAAzkyAH0AAAAFZAAgAAAAAPZaapeAUUFPA7JTCMOWHJa9lnPFh0/gXfAPjA1ezm4ZBXMAIAAAAACmJvLY2nivw7/b3DOKH/X7bBXjJwoowqb1GtEFO3OYgAVsACAAAAAA/JcUoyKacCB1NfmH8vYqC1f7rd13KShrQqV2r9QBP44AAzkzAH0AAAAFZAAgAAAAAK00u6jadxCZAiA+fTsPVDsnW5p5LCr4+kZZZOTDuZlfBXMAIAAAAAAote4zTEYMDgaaQbAdN8Dzv93ljPLdGjJzvnRn3KXgtQVsACAAAAAAxXd9Mh6R3mnJy8m7UfqMKi6oD5DlZpkaOz6bEjMOdiwAAzk0AH0AAAAFZAAgAAAAAFbgabdyymiEVYYwtJSWa7lfl/oYuj/SukzJeDOR6wPVBXMAIAAAAADAFGFjS1vPbN6mQEhkDYTD6V2V23Ys9gUEUMGNvMPkaAVsACAAAAAAL/D5Sze/ZoEanZLK0IeEkhgVkxEjMWVCfmJaD3a8uNIAAzk1AH0AAAAFZAAgAAAAABNMR6UBv2E627CqLtQ/eDYx7OEwQ7JrR4mSHFa1N8tLBXMAIAAAAAAxH4gucI4UmNVB7625C6hFSVCuIpJO3lusJlPuL8H5EQVsACAAAAAAVLHNg0OUVqZ7WGOP53BkTap9FOw9dr1P4J8HxqFqU04AAzk2AH0AAAAFZAAgAAAAAG8cd6WBneNunlqrQ2EmNf35W7OGObGq9WL4ePX+LUDmBXMAIAAAAAAjJ2+sX87NSis9hBsgb1QprVRnO7Bf+GObCGoUqyPE4wVsACAAAAAAs9c9SM49/pWmyUQKslpt3RTMBNSRppfNO0JBvUqHPg0AAzk3AH0AAAAFZAAgAAAAAFWOUGkUpy8yf6gB3dio/aOfRKh7XuhvsUj48iESFJrGBXMAIAAAAAAY7sCDMcrUXvNuL6dO0m11WyijzXZvPIcOKob6IpC4PQVsACAAAAAAJOP+EHz6awDb1qK2bZQ3kTV7wsj5Daj/IGAWh4g7omAAAzk4AH0AAAAFZAAgAAAAAGUrIdKxOihwNmo6B+aG+Ag1qa0+iqdksHOjQj+Oy9bZBXMAIAAAAABwa5dbI2KmzBDNBTQBEkjZv4sPaeRkRNejcjdVymRFKQVsACAAAAAA4ml/nm0gJNTcJ4vuD+T2Qfq2fQZlibJp/j6MOGDrbHMAAzk5AH0AAAAFZAAgAAAAAOx89xV/hRk64/CkM9N2EMK6aldII0c8smdcsZ46NbP8BXMAIAAAAADBF6tfQ+7q9kTuLyuyrSnDgmrdmrXkdhl980i1KHuGHgVsACAAAAAACUqiFqHZdGbwAA+hN0YUE5zFg+H+dabIB4dj5/75W/YAAzEwMAB9AAAABWQAIAAAAADJDdC9aEFl4Y8J/awHbnXGHjfP+VXQilPHJg7ewaJI7AVzACAAAAAAE+tqRl6EcBMXvbr4GDiNIYObTsYpa1n6BJk9EjIJVicFbAAgAAAAAJVc+HYYqa0m1Hq6OiRX8c0iRnJYOt6AJAJoG0sG3GMSAAMxMDEAfQAAAAVkACAAAAAA3F9rjEKhpoHuTULVGgfUsGGwJs3bISrXkFP1v6KoQLgFcwAgAAAAAIBf0tXw96Z/Ds0XSIHX/zk3MzUR/7WZR/J6FpxRWChtBWwAIAAAAABWrjGlvKYuTS2s8L9rYy8Hf0juFGJfwQmxVIjkTmFIGQADMTAyAH0AAAAFZAAgAAAAAOYIYoWkX7dGuyKfi3XssUlc7u/gWzqrR9KMkikKVdmSBXMAIAAAAABVF2OYjRTGi9Tw8XCAwZWLpX35Yl271TlNWp6N/nROhAVsACAAAAAA0nWwYzXQ1+EkDvnGq+SMlq20z+j32Su+i/A95SggPb4AAzEwMwB9AAAABWQAIAAAAACMtPm12YtdEAvqu6Eji1yuRXnu1RJP6h0l7pH3lSH4MwVzACAAAAAAENyCFfyUAh1veQBGx+cxiB7Sasrj41jzCGflZkB5cRMFbAAgAAAAAKdI2LMqISr/T5vuJPg6ZRBm5fVi2aQCc4ra3A4+AjbDAAMxMDQAfQAAAAVkACAAAAAAvlI4lDcs6GB1cnm/Tzo014CXWqidCdyE5t2lknWQd4QFcwAgAAAAAD60SpNc4O2KT7J0llKdSpcX1/Xxs97N715a1HsTFkmBBWwAIAAAAABuuRkJWAH1CynggBt1/5sPh9PoGiqTlS24D/OE2uHXLQADMTA1AH0AAAAFZAAgAAAAAKl8zcHJRDjSjJeV/WvMxulW1zrTFtaeBy/aKKhadc6UBXMAIAAAAADBdWQl5SBIvtZZLIHszePwkO14W1mQ0izUk2Ov21cPNAVsACAAAAAAHErCYycpqiIcCZHdmPL1hi+ovLQk4TAvENpfLdTRamQAAzEwNgB9AAAABWQAIAAAAABb6LXDWqCp1beQgQjj8I3sRTtFhlrmiBi+h/+ikmrvugVzACAAAAAA9stpgTecT7uTyaGNs3K9Bp0A7R0QaIAOfscyMXHBPX8FbAAgAAAAAHUt+McyXrJ1H8SwnHNVO181Ki8vDAM1f7XI26mg95ZDAAMxMDcAfQAAAAVkACAAAAAA97NTT+81PhDhgptNtp4epzA0tP4iNb9j1AWkiiiKGM8FcwAgAAAAAKPbHg7ise16vxmdPCzksA/2Mn/qST0L9Xe8vnQugVkcBWwAIAAAAABB0EMXfvju4JU/mUH/OvxWbPEl9NJkcEp4iCbkXI41fAADMTA4AH0AAAAFZAAgAAAAAMqpayM2XotEFmm0gwQd9rIzApy0X+7HfOhNk6VU7F5lBXMAIAAAAACJR9+q5T9qFHXFNgGbZnPubG8rkO6cwWhzITQTmd6VgwVsACAAAAAAOZLQ6o7e4mVfDzbpQioa4d3RoTvqwgnbmc5Qh2wsZuoAAzEwOQB9AAAABWQAIAAAAADQnslvt6Hm2kJPmqsTVYQHE/wWeZ4bE1XSkt7TKy0r1gVzACAAAAAA8URTA4ZMrhHPvlp53TH6FDCzS+0+61qHm5XK6UiOrKEFbAAgAAAAAHQbgTCdZcbdA0avaTmZXUKnIS7Nwf1tNrcXDCw+PdBRAAMxMTAAfQAAAAVkACAAAAAAhujlgFPFczsdCGXtQ/002Ck8YWQHHzvWvUHrkbjv4rwFcwAgAAAAALbV0lLGcSGfE7mDM3n/fgEvi+ifjl7WZ5b3aqjDNvx9BWwAIAAAAACbceTZy8E3QA1pHmPN5kTlOx3EO8kJM5PUjTVftw1VpgADMTExAH0AAAAFZAAgAAAAABm/6pF96j26Jm7z5KkY1y33zcAEXLx2n0DwC03bs/ixBXMAIAAAAAD01OMvTZI/mqMgxIhA5nLs068mW+GKl3OW3ilf2D8+LgVsACAAAAAAaLvJDrqBESTNZSdcXsd+8GXPl8ZkUsGpeYuyYVv/kygAAzExMgB9AAAABWQAIAAAAACfw9/te4GkHZAapC9sDMHHHZgmlTrccyJDPFciOMSOcwVzACAAAAAAIIC1ZpHObvmMwUfqDRPl4C1aeuHwujM1G/yJbvybMNAFbAAgAAAAAAs9x1SnVpMfNv5Bm1aXGwHmbbI9keWa9HRD35XuCBK5AAMxMTMAfQAAAAVkACAAAAAAkxHJRbnShpPOylLoDdNShfILeA1hChKFQY9qQyZ5VmsFcwAgAAAAAKidrY+rC3hTY+YWu2a7fuMH2RD/XaiTIBW1hrxNCQOJBWwAIAAAAACW0kkqMIzIFMn7g+R0MI8l15fr3k/w/mHtY5n6SYTEwAADMTE0AH0AAAAFZAAgAAAAAByuYl8dBvfaZ0LO/81JW4hYypeNmvLMaxsIdvqMPrWoBXMAIAAAAABNddwobOUJzm9HOUD8BMZJqkNCUCqstHZkC76FIdNg9AVsACAAAAAAQQOkIQtkyNavqCnhQbNg3HfqrJdsAGaoxSJePJl1qXsAAzExNQB9AAAABWQAIAAAAABxMy7X5hf7AXGDz3Y/POu1ZpkMlNcSvSP92NOO/Gs7wAVzACAAAAAAHJshWo2T5wU2zvqCyJzcJQKQaHFHpCpMc9oWBXkpUPoFbAAgAAAAAGeiJKzlUXAvL0gOlW+Hz1mSa2HsV4RGmyLmCHlzbAkoAAMxMTYAfQAAAAVkACAAAAAAlqbslixl7Zw3bRlibZbe/WmKw23k8uKeIzPKYEtbIy0FcwAgAAAAAHEKwpUxkxOfef5HYvulXPmdbzTivwdwrSYIHDeNRcpcBWwAIAAAAADuPckac21Hrg/h0kt5ShJwVEZ9rx6SOHd2+HDjqxEWTQADMTE3AH0AAAAFZAAgAAAAAMXrXx0saZ+5gORmwM2FLuZG6iuO2YS+1IGPoAtDKoKBBXMAIAAAAADIQsxCr8CfFKaBcx8kIeSywnGh7JHjKRJ9vJd9x79y7wVsACAAAAAAcvBV+SykDYhmRFyVYwFYB9oBKBSHr55Jdz2cXeowsUQAAzExOAB9AAAABWQAIAAAAAAm83FA9yDUpwkbKTihe7m53u+DivS9BU2b4vQMtCVQ2AVzACAAAAAAz3m1UB/AbZPa4QSKFDnUgHaT78+6iGOFAtouiBorEgEFbAAgAAAAAIgbpyYtJj5513Z5XYqviH/HXG/5+mqR52iBbfqMmDtZAAMxMTkAfQAAAAVkACAAAAAAJRzYK0PUwr9RPG2/7yID0WgcTJPB2Xjccp5LAPDYunkFcwAgAAAAAIIh24h3DrltAzNFhF+MEmPrZtzr1PhCofhChZqfCW+jBWwAIAAAAAAzRNXtL5o9VXMk5D5ylI0odPDJDSZZry1wfN+TedH70gADMTIwAH0AAAAFZAAgAAAAAHSaHWs/dnmI9sc7nB50VB2Bzs0kHapMHCQdyVEYY30TBXMAIAAAAACkV22lhEjWv/9/DubfHBAcwJggKI5mIbSK5L2nyqloqQVsACAAAAAAS19m7DccQxgryOsBJ3GsCs37yfQqNi1G+S6fCXpEhn4AAzEyMQB9AAAABWQAIAAAAAAC/I4TQRtCl12YZmdGz17X4GqSQgfwCPgRBwdHmdwu+QVzACAAAAAAx8f3z2ut/RAZhleari4vCEE+tNIn4ikjoUwzitfQ588FbAAgAAAAAJci0w1ZB8W2spJQ+kMpod6HSCtSR2jrabOH+B0fj3A4AAMxMjIAfQAAAAVkACAAAAAADGB5yU2XT0fse/MPWgvBvZikVxrl5pf3S5K1hceKWooFcwAgAAAAAIxTmlLHMjNaVDEfJbXvRez0SEPWFREBJCT6qTHsrljoBWwAIAAAAAAlswzAl81+0DteibwHD+CG5mZJrfHXa9NnEFRtXybzzwADMTIzAH0AAAAFZAAgAAAAABmO7QD9vxWMmFjIHz13lyOeV6vHT6mYCsWxF7hb/yOjBXMAIAAAAACT9lmgkiqzuWG24afuzYiCeK9gmJqacmxAruIukd0xEAVsACAAAAAAZa0/FI/GkZR7CtX18Xg9Tn9zfxkD0UoaSt+pIO5t1t4AAzEyNAB9AAAABWQAIAAAAAAfPUoy7QyZKhIIURso+mkP9qr1izbjETqF5s22GwjCjAVzACAAAAAAvLMsIDQ/go4VUxeh50UHmsvMvfx51cwyONnRD2odvC0FbAAgAAAAAKMb+1CodEalAFnDrEL1Ndt8ztamZ+9134m9Kp3GQgd+AAMxMjUAfQAAAAVkACAAAAAAE3ZqUar0Bq2zWbARE0bAv98jBlK9UJ73/xcwdMWWlSkFcwAgAAAAAK4M+MmC+9sFiFsumMyJZQKxWmmJiuG9H7IzKw083xxkBWwAIAAAAAAqkAONzhvMhkyL1D/6h7QQxEkdhC3p2WjXH+VGq5qCqQADMTI2AH0AAAAFZAAgAAAAAMo8FJiOq63cAmyk2O7eI7GcbQh/1j4RrMTqly3rexftBXMAIAAAAADjVmpd0WiRGTw/gAqEgGolt2EI7Csv14vKdmYoMD0aAgVsACAAAAAA07XQBzBUQMNw7F2/YxJjZNuPVpHTTgbLd1oGk77+bygAAzEyNwB9AAAABWQAIAAAAACu5IGaIx7A3Jvly/kzlCsSA4s3iJwuIl8jEdRH0k93NwVzACAAAAAA9NRUyxYE+t0Xyosyt6vIfMFW/vBoYg6sR+jBNs4JAxIFbAAgAAAAAAzyZ91dx+0oMlOVAjRGiMrPySikY/U9eMEB4WJb3uWtAAMxMjgAfQAAAAVkACAAAAAALkRy0GJInXYLA+cgjs6Myb0a+Gu9hgXhHvhLNoGWfckFcwAgAAAAANbALyt9zCSvwnLaWCd2/y2eoB7qkWTvv1Ldu8r40JPuBWwAIAAAAAD4Fl5bV5sz4isIE9bX+lmAp+aAKaZgVYVZeVfrItkCZAADMTI5AH0AAAAFZAAgAAAAAGoUK/DSWhT8LZhszSUqDbTrp8cSA7rdqmADKL+MILtTBXMAIAAAAABHnEE9bVa6lvhfhEMkkV2kzSSxH/sMW/FIJuw3CzWs6wVsACAAAAAAanavcBdqZxgRGKvEK95wTmeL1K1CeDSXZsXUAs81uOgAAzEzMAB9AAAABWQAIAAAAAC922ZDQE3h2fQKibGMZ9hV0WNlmrPYYSdtaSyYxsWYqgVzACAAAAAAagMovciKK6WVjIc2cCj8nK5O/gVOFFVeVAJpRp89tmQFbAAgAAAAAKcTFfPQzaFiAtSFhqbN02sCE1BKWJSrRfGN5L6oZwzkAAMxMzEAfQAAAAVkACAAAAAAtK+JqX3K/z2txjAU15DgX4y90DS2YLfIJFolCOkJJJwFcwAgAAAAAMnR5V7gfX7MNqqUdL5AkWlkhyFXaBRVNej+Rcn8lrQkBWwAIAAAAAA2cDNRXZuiC241TGRvdFyctJnrNcdbZOP9zHio81tkngADMTMyAH0AAAAFZAAgAAAAAAeGrIMK/bac6kPczxbvRYqKMkcpeI2FjdMpD91FDWIvBXMAIAAAAAAix62z1LeS8yvSXCl5gHSIomjyx76fF3S1lp9k900hygVsACAAAAAAiYwzf2m71aWFD5ajcXyW2JX2EzQOkBroTGMg29nLPYIAAzEzMwB9AAAABWQAIAAAAACphf298InM0Us4HT8o1W1MGw0D/02vd7Jh+U0h7qaFaQVzACAAAAAAFXtk7YpqsOJxsqGWSIL+YcBE96G3Zz9D31gPqDW94y8FbAAgAAAAAAOrS1KVA94rjB1jZ1pPocpCeBG+B14RzWoHqVDpp7JbAAMxMzQAfQAAAAVkACAAAAAATLDS2cuDVM3yDMuWNgk2iGKBTzPpfJMbvxVOSY39ZfcFcwAgAAAAAPT5wRi2cLHIUflXzm6EQB/m7xdThP80ir1VV/JBBqvxBWwAIAAAAAB9lEtZS0aXCFbCtSbhnis27S5IPcfWGygHW8AHn3QqzwADMTM1AH0AAAAFZAAgAAAAAJNjExiZVX7jfFGfYpQu16qxLN0YPqVU/5CQ/Y67YSinBXMAIAAAAABMpm2+6KrkRUlXzQoMPHrQmIO6dkQz66tYdfTeA3dKqQVsACAAAAAAFXobHiMLvNZuEPr8jtewCX2J93EZG3JNeyVg92fue6YAAzEzNgB9AAAABWQAIAAAAABlFkYtLCx901X6QVVMkSn6Z7k30UF4xHaA0OZJJ9bdyQVzACAAAAAATez+F9GHcGzTp7jjv4feboUNb8JCkIp4EqcPFisnq7MFbAAgAAAAACE7JvOpBgMoZ7kRd4QbxIhxukPTUxXpzhjnBHiR7XoRAAMxMzcAfQAAAAVkACAAAAAA8NJKN0IxZnruhswGQkiruv8Ih0EMwDcSZx/Xasup9dkFcwAgAAAAAKaJZRxzA+Igeydvuk6cSwUHXcrmT4PjhuPu//FslpdnBWwAIAAAAAD53Rok1Vq/PMAnXmarqoHJ0PEyYUBmVESa9hIpCv/G9QADMTM4AH0AAAAFZAAgAAAAABHxHdEClz7hbSSgE58+dWLlSMJnoPz+jFxp4bB1GmLQBXMAIAAAAAD3nSvT6aGD+A110J/NwEfp0nPutlmuB5B+wA3CC3noGAVsACAAAAAA3Apjd+TapONB7k5wBVwTWgn8t+Sq2oyyU5/+as109RcAAzEzOQB9AAAABWQAIAAAAAC/o8qW/ifk3KuJ01VFkyNLgQafxB5/bGs2G5VyyVafOwVzACAAAAAA1bMqAFGDHSl6BYNLbxApvkAv2K1/oafywiX0MDz1dGUFbAAgAAAAAHJXLlId3edFoniLD/9K2A5973MeP2Ro31flDyqm3l5QAAMxNDAAfQAAAAVkACAAAAAAY2V8I1bz3a1AxTtmED6UhdhA09huFkuuEX8R+d/WDPUFcwAgAAAAAPTVoNRiI76tcRKqd+JBBVyy4+YcKST42p0QX2BtmQ2VBWwAIAAAAACcxt9hg14WqPNiDv1MkqVljM2e2KJEv53lA17LhV6ZigADMTQxAH0AAAAFZAAgAAAAAO2kSsW0WGN9AOtK4xK2SHrGhWiaAbMEKT4iZkRpaDN/BXMAIAAAAABKGzQcPM8LT2dwOggxoWjv/1imYWabbG/G4kBw8OWaxAVsACAAAAAAC9hLK1dScQTAqg+YAG3ObdPzg2Xet57HmOFpGmyUR9UAAzE0MgB9AAAABWQAIAAAAAAiCwzNEEaH/mDam68IdDftnhthyUFdb+ZCNSBQ91WlHQVzACAAAAAA7tHyHcxCzmbJeFYZyPm4mEgkTGKOvwY4MX82OvH0Jn8FbAAgAAAAAAb5IAbZ1hXCNegQ+S+C9i/Z8y6sS8KeU04V6hXa2ml6AAMxNDMAfQAAAAVkACAAAAAAGuCHVNJSuoVkpPOnS5s89GuA+BLi2IPBUr2Bg1sWEPIFcwAgAAAAAEl1gncS5/xO7bQ/KQSstRV3rOT2SW6nV92ZANeG2SR6BWwAIAAAAAA9LOcKmhek8F2wAh8yvT/vjp2gaouuO+Hmv10lwAeWPAADMTQ0AH0AAAAFZAAgAAAAAMfxz7gEaoCdPvXrubDhCZUS0ARLZc1svgbXgMDlVBPgBXMAIAAAAAB6a5dDA3fuT5Vz2KvAcbUEFX/+B7Nw2p1QqbPoQ5TTuAVsACAAAAAAcf/y75UOuI62A6vWH7bYr/5Jz+nirZVYK/81trN6XOQAAzE0NQB9AAAABWQAIAAAAACnYsqF/VzmjIImC9+dqrHO1TM6lJ6fRwM0mM6Wf6paOwVzACAAAAAA5tgZzch8uDCR1ky3SllVaKVpxAlbrhvlNDTazZZRZOAFbAAgAAAAALeGiLJS4z2zhgVpxzyPdRYyACP9QzQBOob34YrIZumCAAMxNDYAfQAAAAVkACAAAAAAEC0sIVmadtW4YMuRXH7RpAhXclsd+3bmqGXCMeaT014FcwAgAAAAABPpXh0uzpsJJB+IRUNajmMB9WGwswfpw5T9xk3Xj6ANBWwAIAAAAAAmf+NYh9TZ/QRu3w/GQz66n7DtfbJijN3G7KzeL8lstAADMTQ3AH0AAAAFZAAgAAAAABaIB3n49Xm9cOafSrQsE0WCcYp8rMIO/qVwIlMF5YLRBXMAIAAAAAC9EyWJV3xOu9bzgdJ/yX+ko7qLf1u3AxNMataW2C9EzQVsACAAAAAAvVbDkLxXx2DcMLifIQ3K0IIJcLcAG9DUrNfI6aoUjNcAAzE0OAB9AAAABWQAIAAAAAA5rZItA/cocRnngYqcJ3nBXQ+l688aKz3EQyLbYYunPAVzACAAAAAAwKyA+L7TgxztPClLrIMk2JXR+w7c04N3ZOqPgjvrIvsFbAAgAAAAACzvZ33h6aWEe8hmo+1f6OXJ72FY5hvWaUuha64ZV3KFAAMxNDkAfQAAAAVkACAAAAAA3htn7oHJ0YYpIrs+Mzyh85Ys67HwAdv5LQl1mCdoMWkFcwAgAAAAAEHjCtNNLenHuSIYux6ezAHsXDaj2DlTF67ToDhDDe6HBWwAIAAAAAD+P4H0sk9jOd+7vOANt2/1Ectb+4ZRGPE8GkHWNXW3MgADMTUwAH0AAAAFZAAgAAAAAEnt18Km/nqggfIJWxzTr9r3hnXNaueG6XO9A5G11LnGBXMAIAAAAAD7QxzGMN/ard5TfFLecE6uusMmXG2+RBsBR+/NCQHUwAVsACAAAAAAQEZ1ZZ8GC8rdbg7s87OM5Gr9qkTXS9+P5DuAZxj5Gl4AAzE1MQB9AAAABWQAIAAAAAAVAKK/GoY8AACu/hyMpO4hdLq6JnEyWNzkyci9sbaD/wVzACAAAAAA2HmeqpMlvvBpV2zQTYIRmsc4MFlfHRwLof0ycJgMg/MFbAAgAAAAACdltCeWi5E/q1Li1eXLChpM2D9QQSGLBZ82NklQSc0oAAMxNTIAfQAAAAVkACAAAAAAhHyq1GQC/GiMwpYjcsfkNxolJ10ARKjIjfkW1Wipzi0FcwAgAAAAAD/uaGWxTDq87F8XZ6CrFI+RNa8yMqfSZdqK00Kj833BBWwAIAAAAAD6aEdOO0CsQGagioOCvANPCEHSpJ8BSixlPBq5ERhB7AADMTUzAH0AAAAFZAAgAAAAABAJJxHoZD+MQBWqm9UM9Dd3z5ZohIZGWRaRVRsMptKQBXMAIAAAAADrE/ca+gqj/SH4oao4wE4qn2ovoTydzcMbDbrfnUs3zAVsACAAAAAAeNCIQN6hVnGJinytQRFGlQ2ocoprXNqpia+BSxzl+uwAAzE1NAB9AAAABWQAIAAAAAAv01wz7VG9mTepjXQi6Zma+7b/OVBaKVkWNbgDLr1mFgVzACAAAAAA0I5sxz8r6wkCp5Tgvr+iL4p6MxSOq5d3e1kZG+0b7NkFbAAgAAAAAIA32v6oGkAOS96HexGouNTex+tLahtx9QF2dgGClk6WAAMxNTUAfQAAAAVkACAAAAAAWXecRwxSon68xaa9THXnRDw5ZfzARKnvvjTjtbae6T0FcwAgAAAAAPh0UfUMEo7eILCMv2tiJQe1bF9qtXq7GJtC6H5Va4fIBWwAIAAAAADqFr1ThRrTXNgIOrJWScO9mk86Ufi95IDu5gi4vP+HWQADMTU2AH0AAAAFZAAgAAAAAEY5WL8/LpX36iAB1wlQrMO/xHVjoO9BePVzbUlBYo+bBXMAIAAAAABoKcpadDXUARedDvTmzUzWPe1jTuvD0z9oIcZmKuiSXwVsACAAAAAAJuJbwuaMrAFoI+jU/IYr+k4RzAqITrOjAd3HWCpJHqEAAzE1NwB9AAAABWQAIAAAAADnJnWqsfx0xqNnqfFGCxIplVu8mXjaHTViJT9+y2RuTgVzACAAAAAAWAaSCwIXDwdYxWf2NZTly/iKVfG/KDjHUcA1BokN5sMFbAAgAAAAAJVxavipE0H4/JQvhagdytXBZ8qGooeXpkbPQ1RfYMVHAAMxNTgAfQAAAAVkACAAAAAAsPG7LaIpJvcwqcbtfFUpIjj+vpNj70Zjaw3eV9T+QYsFcwAgAAAAAJQ71zi0NlCyY8ZQs3IasJ4gB1PmWx57HpnlCf3+hmhqBWwAIAAAAACD58TO6d+71GaOoS+r73rAxliAO9GMs4Uc8JbOTmC0OwADMTU5AH0AAAAFZAAgAAAAAAGiSqKaQDakMi1W87rFAhkogfRAevnwQ41onWNUJKtuBXMAIAAAAAASgiDpXfGh7E47KkOD8MAcX8+BnDShlnU5JAGdnPdqOAVsACAAAAAAI+2TTQIgbFq4Yr3lkzGwhG/tqChP7hRAx2W0fNaH6jcAAzE2MAB9AAAABWQAIAAAAAB7L4EnhjKA5xJD3ORhH2wOA1BvpnQ+7IjRYi+jjVEaJAVzACAAAAAAuhBIm0nL3FJnVJId+7CKDASEo+l2E89Z9/5aWSITK4AFbAAgAAAAALtSICOzQDfV9d+gZuYxpEj6cCeHnKTT+2G3ceP2H65kAAMxNjEAfQAAAAVkACAAAAAAaROn1NaDZFOGEWw724dsXBAm6bgmL5i0cki6QZQNrOoFcwAgAAAAANVT8R6UvhrAlyqYlxtmnvkR4uYK/hlvyQmBu/LP6/3ZBWwAIAAAAAD+aHNMP/X+jcRHyUtrCNkk1KfMtoD3GTmShS8pWGLt+AADMTYyAH0AAAAFZAAgAAAAADqSR5e0/Th59LrauDA7OnGD1Xr3H3NokfVxzDWOFaN7BXMAIAAAAACt30faNwTWRbvmykDpiDYUOCwA6QDbBBYBFWS7rdOB4AVsACAAAAAAF7SvnjjRk5v2flFOKaBAEDvjXaL1cpjsQLtK2fv9zdQAAzE2MwB9AAAABWQAIAAAAADmtb1ZgpZjSeodPG/hIVlsnS8hoRRwRbrTVx89VwL62AVzACAAAAAAi38e1g6sEyVfSDkzZbaZXGxKI/zKNbMasOl2LYoWrq8FbAAgAAAAAALACk0KcCDN/Kv8WuazY8ORtUGkOZ5Dsm0ys1oOppp/AAMxNjQAfQAAAAVkACAAAAAAf/f7AWVgBxoKjr7YsEQ4w/fqSvuQWV2HMiA3rQ7ur0sFcwAgAAAAADkkeJozP6FFhUdRIN74H4UhIHue+eVbOs1NvbdWYFQrBWwAIAAAAAB55FlHAkmTzAYj/TWrGkRJw2EhrVWUnZXDoMYjyfB/ZwADMTY1AH0AAAAFZAAgAAAAAI2WEOymtuFpdKi4ctanPLnlQud+yMKKb8p/nfKmIy56BXMAIAAAAADVKrJmhjr1rfF3p+T+tl7UFd1B7+BfJRk0e7a4im7ozgVsACAAAAAA5E7Ti3PnFiBQoCcb/DN7V1uM3Xd6VKiexPKntssFL7kAAzE2NgB9AAAABWQAIAAAAAAuHU9Qd79hjyvKOujGanSGDIQlxzsql8JytTZhEnPw+AVzACAAAAAAjF2gV/4+sOHVgDd/oR5wDi9zL7NGpGD+NsEpGXy/a4QFbAAgAAAAAJzMoyojYV6Ed/LpVN5zge93Odv3U7JgP7wxeRaJZGTdAAMxNjcAfQAAAAVkACAAAAAA7dQDkt3iyWYCT94d7yqUtPPwp4qkC0ddu+HFdHgVKEkFcwAgAAAAANuYvtvZBTEq4Rm9+5eb7VuFopowkrAuv86PGP8Q8/QvBWwAIAAAAACeqXoAOQOE4j0zRMlkVd8plaW0RX1npsFvB38Xmzv7sAADMTY4AH0AAAAFZAAgAAAAAAwnZSDhL4tNGYxlHPhKYB8s28dY5ScSwiKZm3UhT8U3BXMAIAAAAABDoY6dhivufTURQExyC9Gx3ocpl09bgbbQLChj3qVGbgVsACAAAAAAF+1nS7O0v85s3CCy+9HkdeoEfm2C6ZiNbPMMnSfsMHUAAzE2OQB9AAAABWQAIAAAAAC2VuRdaC4ZJmLdNOvD6R2tnvkyARteqXouJmI46V306QVzACAAAAAAMn1Z6B35wFTX9mEYAPM+IiJ5hauEwfD0CyIvBrxHg7IFbAAgAAAAAOG6DvDZkT9B/xZWmjao2AevN7MMbs3Oh9YJeSd/hZ+hAAMxNzAAfQAAAAVkACAAAAAAVerb7qVNy457rNOHOgDSKyWl5ojun7iWrv1uHPXrIZQFcwAgAAAAAIDcYS9j5z+gx0xdJj09L7876r/vjvKTi/d3bXDE3PhyBWwAIAAAAADuhVLqb1Bkrx8aNymS+bx2cL8GvLFNH4SAi690DUgnWQADMTcxAH0AAAAFZAAgAAAAAH/E44yLxKCJjuSmU9A8SEhbmkDOx1PqqtYcZtgOzJdrBXMAIAAAAABgLh9v2HjBbogrRoQ82LS6KjZQnzjxyJH4PH+F3jupSAVsACAAAAAAIlO46ehXp4TqpDV0t6op++KO+uWBFh8iFORZjmx2IjkAAzE3MgB9AAAABWQAIAAAAAAlNUdDL+f/SSQ5074mrq0JNh7CTXwTbbhsQyDwWeDVMwVzACAAAAAANIH2IlSNG0kUw4qz0budjcWn8mNR9cJlYUqPYdonucAFbAAgAAAAAJMrOUOyiu5Y3sV76zwEFct8L7+i8WGlQI2+8z2W2kzaAAMxNzMAfQAAAAVkACAAAAAASZ+CvUDtlk/R4HAQ3a+PHrKeY/8ifAfh0oXYFqliu80FcwAgAAAAAJelpzPgM65OZFt/mvGGpwibclQ49wH+1gbUGzd9OindBWwAIAAAAAD9qeDchteEpVXWcycmD9kl9449C1dOw0r60TBm5jK+cQADMTc0AH0AAAAFZAAgAAAAAN9fkoUVbvFV2vMNMAkak4gYfEnzwKI3eDM3pnDK5q3lBXMAIAAAAACnDkgVNVNUlbQ9RhR6Aot2nVy+U4km6+GHPkLr631jEAVsACAAAAAANzg/BnkvkmvOr8nS4omF+q9EG/4oisB+ul4YHi938hwAAzE3NQB9AAAABWQAIAAAAAASyK3b1nmNCMptVEGOjwoxYLLS9fYWm/Zxilqea0jpEQVzACAAAAAADDHsGrbqlKGEpxlvfyqOJKQJjwJrzsrB7k3HG0AUJbkFbAAgAAAAAKwx3S4XfDZh4+LuI9jf7XgUh5qiefNv87JD4qvVRfPSAAMxNzYAfQAAAAVkACAAAAAAlSP9iK31GlcG9MKGbLmq+VXMslURr+As736rrVNXcsUFcwAgAAAAAAvbj0zfq9zzi8XReheKFbCB+h9IsOLgXPPpI5vrEJNZBWwAIAAAAABXvoZhaQE7ogWjeBjceVkp03N20cKYP3TA8vuNsgpfAgADMTc3AH0AAAAFZAAgAAAAAOJNORH8Bev97gVU7y6bznOxJ+E6Qoykur1QP76hG1/7BXMAIAAAAAC+C1PtOOrSZgzBAGhr+dPe/kR0JUw9GTwLVNr61xC1aAVsACAAAAAAeA/L8MQIXkamaObtMPLpoDoi5FypA5WAPtMeMrgi0eQAAzE3OAB9AAAABWQAIAAAAAAKcHzLUomavInN6upPkyWhAqYQACP/vdVCIYpiy6U6HgVzACAAAAAATsR4KItY6R2+U7Gg6sJdaEcf58gjd1OulyWovIqfxKcFbAAgAAAAAFbm10ko67ahboAejQdAV0U2uA5OhZYdb8XUFJ8OL46LAAMxNzkAfQAAAAVkACAAAAAAqTOLiMpCdR59tLZzzIPqJvbCNvz2XQL9ust0qYaehtcFcwAgAAAAAArefox/3k5xGOeiw2m6NUdzuGxmPwcu5IFcj+jMwHgHBWwAIAAAAADLZGFJ7MQd5JXMgMXjqZO5LDLxcFClcXPlnRMWRn+1oAADMTgwAH0AAAAFZAAgAAAAAIPSqSeVzSRgNVNmrPYHmUMgykCY27NbdDUNhE5kx/SgBXMAIAAAAAAhX90nNfxyXmZe/+btZ7q6xMX4PFyj0paM1ccJ/5IUUQVsACAAAAAA419oHmD2W0SYoOMwhrhrp8jf68fg9hTkaRdCuVd3CN0AAzE4MQB9AAAABWQAIAAAAACLn5DxiqAosHGXIAY96FwFKjeqrzXWf3VJIQMwx1fl4gVzACAAAAAAindvU27nveutopdvuHmzdENBbeGFtI3Qcsr07jxmvm8FbAAgAAAAAPvl9pBStQvP4OGkN5v0MghUY6djm9n7XdKKfrW0l1sMAAMxODIAfQAAAAVkACAAAAAA7i2S6rHRSPBwZEn59yxaS7HiYBOmObIkeyCcFU42kf8FcwAgAAAAAGb3RSEyBmgarkTvyLWtOLJcPwCKbCRkESG4RZjVmY4iBWwAIAAAAADB2/wo5CSHR4ANtifY6ZRXNTO5+O8qP82DfAiAeanpZwADMTgzAH0AAAAFZAAgAAAAAFz+M+H/Z94mdPW5oP51B4HWptp1rxcMWAjnlHvWJDWrBXMAIAAAAACBFEOQyL7ZHu4Cq33QvXkmKuH5ibG/Md3RaED9CtG5HwVsACAAAAAAfggtJTprQ/yZzj7y5z9KvXsdeXMWP0yUXMMJqpOwI88AAzE4NAB9AAAABWQAIAAAAAAE7c2x3Z3aM1XGfLNk/XQ9jCazNRbGhVm7H8c2NjS5ywVzACAAAAAARJ9h8fdcwA19velF3L/Wcvi2rCzewlKZ2nA0p8bT9uwFbAAgAAAAAJtWe6b4wK2Hae2dZm/OEpYQnvoZjz4Sz5IgJC2wInecAAMxODUAfQAAAAVkACAAAAAAVoRt9B9dNVvIMGN+ea5TzRzQC+lqSZ8dd/170zU5o9cFcwAgAAAAAEwM95XZin5mv2yhCI8+ugtKuvRVmNgzzIQN0yi1+9aIBWwAIAAAAAAMGBq72n00rox3uqhxSB98mkenTGCdbbUF1gXrgottzgADMTg2AH0AAAAFZAAgAAAAAKRDkjyWv/etlYT4GyoXrmBED2FgZHnhc+l9Wsl06cH2BXMAIAAAAABohlpm3K850Vndf3NmNE0hHqDlNbSR8/IvMidQ3LnIZAVsACAAAAAAW42nGHa6q2MCAaaPVwaIDfr8QLyQwjKq23onZJYsqVsAAzE4NwB9AAAABWQAIAAAAAC3DFh5oklLCNLY90bgWm68dFXz65JpAZSp1K99MBTPAQVzACAAAAAAQgZecmxEUZVHoptEQClDwAf8smI3WynQ/i+JBP0g+kQFbAAgAAAAAEUSQGVnAPISD6voD0DiBUqyWKgt2rta0tjmoe+LNt6IAAMxODgAfQAAAAVkACAAAAAAQ5WKvWSB503qeNlOI2Tpjd5blheNr6OBO8pfJfPNstcFcwAgAAAAAKwHgQLSDJ5NwLBQbY5OnblQIsVDpGV7q3RCbFLD1U4/BWwAIAAAAACQ5nED99LnpbqXZuUOUjnO2HTphEAFBjLD4OZeDEYybgADMTg5AH0AAAAFZAAgAAAAAGfhFY3RGRm5ZgWRQef1tXxHBq5Y6fXaLAR4yJhrTBplBXMAIAAAAACKEF0ApLoB6lP2UqTFsTQYNc9OdDrs/vziPGzttGVLKQVsACAAAAAArOO6FyfNRyBi0sPT5iye7M8d16MTLcwRfodZq4uCYKEAAzE5MAB9AAAABWQAIAAAAAAIM73gPcgzgotYHLeMa2zAU4mFsr7CbILUZWfnuKSwagVzACAAAAAAJCSu98uV8xv88f2BIOWzt6p+6EjQStMBdkGPUkgN79cFbAAgAAAAAMGqPGMPxXbmYbVfSa/japvUljht1zZT33TY7ZjAiuPfAAMxOTEAfQAAAAVkACAAAAAAkWmHCUsiMy1pwZTHxVPBzPTrWFBUDqHNrVqcyyt7nO8FcwAgAAAAAMv2CebFRG/br7USELR98sIdgE9OQCRBGV5JZCO+uPMgBWwAIAAAAABt7qSmn3gxJu7aswsbUiwvO+G6lXj/Xhx+J/zQyZxzLAADMTkyAH0AAAAFZAAgAAAAAGInUYv0lP/rK7McM8taEHXRefk8Q2AunrvWqdfSV7UaBXMAIAAAAACE+WPxJ3gan7iRTbIxXXx+bKVcaf8kP4JD8DcwU0aL7wVsACAAAAAAUC4eTprX4DUZn2X+UXYU6QjtiXk+u57yoOPBbPQUmDkAAzE5MwB9AAAABWQAIAAAAACmHlg2ud3cplXlTsNTpvNnY6Qm1Fce0m899COamoDjaQVzACAAAAAArtJQeJIlepBWRU2aYar7+YGYVQ7dfDc1oxgTmA8r9q0FbAAgAAAAAOk45vg5VqZHAFCO3i0Z52SZi5RADf8NXwf68T5yad/DAAMxOTQAfQAAAAVkACAAAAAApzcWSAbZWV/Rq+ylRNqqlJqNVR4fhXrz4633/MQOQgcFcwAgAAAAAN/jz/bsEleiuCl+li83EWlG6UMHA8CyaOMRKCkXkSCPBWwAIAAAAAC3Sd+Qg+uFDKpGZHbrQgokXHQ1az1aFl4YK343OB6hcQAAEmNtAAAAAAAAAAAAABBwYXlsb2FkSWQAAAAAABBmaXJzdE9wZXJhdG9yAAEAAAAA", "subType": "06" } } } }, "encryptionInformation": { "type": 1, "schema": { "default.default": { "escCollection": "enxcol_.default.esc", "ecocCollection": "enxcol_.default.ecoc", "fields": [ { "keyId": { "$binary": { "base64": "EjRWeBI0mHYSNBI0VniQEg==", "subType": "04" } }, "path": "encryptedDecimalNoPrecision", "bsonType": "decimal", "queries": { "queryType": "rangePreview", "contention": { "$numberLong": "0" }, "sparsity": { "$numberLong": "1" } } } ] } } } }, "command_name": "find" } } ], "outcome": { "collection": { "data": [ { "_id": { "$numberInt": "0" }, "encryptedDecimalNoPrecision": { "$$type": "binData" }, "__safeContent__": [ { "$binary": { "base64": "5nRutVIyq7URVOVtbE4vM01APSIajAVnsShMwjBlzkM=", "subType": "00" } }, { "$binary": { "base64": "rbf3AeBEv4wWFAKknqDxRW5cLNkFvbIs6iJjc6LShQY=", "subType": "00" } }, { "$binary": { "base64": "n+XAuFnP8Dov9TnhGFxNx0K/MnVM9WbJ7RouEu0ndO0=", "subType": "00" } }, { "$binary": { "base64": "yRXojuVdn5GQtD97qYlaCL6cOLmZ7Cvcb3wFjkLUIdM=", "subType": "00" } }, { "$binary": { "base64": "DuIkdRPITRs55I4SZmgomAHCIsDQmXRhW8+MOznkzSk=", "subType": "00" } }, { "$binary": { "base64": "SsBk+Et1lTbU+QRPx+xyJ/jMkmfG+QCvQEpip2YYrzA=", "subType": "00" } }, { "$binary": { "base64": "crCIzOd8KhHvvUlX7M1v9bhvU4pLdTc+X2SuqoKU5Ek=", "subType": "00" } }, { "$binary": { "base64": "YOWdCw4UrqnxkAaVjqmC4sKQDMVMHEpFGnlxpxdaU6E=", "subType": "00" } }, { "$binary": { "base64": "M3SShp81Ff8tQ632qKbv9MUcN6wjDaBReI0VXNu6Xh4=", "subType": "00" } }, { "$binary": { "base64": "gzHlSPxpM0hT75kQvWFzGlOxKvDoiKQZOr19V6l2zXI=", "subType": "00" } }, { "$binary": { "base64": "s3JnppOGYw9SL2Q1kMAZs948v2F5PrpXjGei/HioDWs=", "subType": "00" } }, { "$binary": { "base64": "cG6+3Gk/zEH68P/uuuwiAUVCuyJwa1LeV+t29FlPPAo=", "subType": "00" } }, { "$binary": { "base64": "dupdvR3AyJtM+g9NDKiaLVOtGca387JQp8w+V03m7Ig=", "subType": "00" } }, { "$binary": { "base64": "JqEQc5svj2jTvZ6LLA5ivE+kTb/0aRemSEmxk4G7Zrg=", "subType": "00" } }, { "$binary": { "base64": "szcXXXKnob+p3SoM4yED2R920LeJ7cVsclPMFTe4CeI=", "subType": "00" } }, { "$binary": { "base64": "o1QoGVXmuBdHwHm7aCtGMlMVKrjFdYvJXpoq6uhIAZ0=", "subType": "00" } }, { "$binary": { "base64": "Jfm5wPlqqLCJRGQIqRq2NGmpn7s0Vrih2H3YAOoI2YU=", "subType": "00" } }, { "$binary": { "base64": "zMHLb8ARbsYo8Ld05bqnGFf1Usha6EGb8QKwdSAyps0=", "subType": "00" } }, { "$binary": { "base64": "yQdtq9lh5pugL7/i0Bj/PuZUUBUIzf+7wj1rl5y736w=", "subType": "00" } }, { "$binary": { "base64": "wGWVZdO7qIuyDg/BqDgqjgoQ02h5YYgwXQB1oCin2NE=", "subType": "00" } }, { "$binary": { "base64": "by9HMLj6NTEpgztZ5HSN6GxImkXPcaFINYDzgZY33X8=", "subType": "00" } }, { "$binary": { "base64": "tWo0vbasi7bXmn/MsOx13VC1IsWtpx/nYp0uj4iMzdA=", "subType": "00" } }, { "$binary": { "base64": "tQQpndUYd5O87lOtrGjH3wl9VsOK0ray7RMasL90sBM=", "subType": "00" } }, { "$binary": { "base64": "cQjXEDCMsOpKLLf+vlTgIHA+cbSJdzqhbSX9Wvh95aA=", "subType": "00" } }, { "$binary": { "base64": "7yMpU48IxK9SzP2cx3VnTownGEwFmeFofuuFT97SuuY=", "subType": "00" } }, { "$binary": { "base64": "kSOx1kz0CmBgzKQHZlo65ZUY1DIv9A99JRm+Us2y6Ew=", "subType": "00" } }, { "$binary": { "base64": "ubQpdPBe6/xvtr+AcXdfYLSvYCR4ot0tivehkCsupb4=", "subType": "00" } }, { "$binary": { "base64": "xal+iCJ6FTefRQToyoNksc9NCZShyn04NDGi4IYrcoM=", "subType": "00" } }, { "$binary": { "base64": "d7jU4iOK50xHxlkSifcxlZFCM46TSgQzoYivxG3HNLY=", "subType": "00" } }, { "$binary": { "base64": "tJvl2nsBLBVzL3pp6sKWCL4UXeh3q/roYBJjSb74ve0=", "subType": "00" } }, { "$binary": { "base64": "OIUCaKRvIx9t1w6Hxlz1IcQTdPNCfdRNwnnTm10W+X0=", "subType": "00" } }, { "$binary": { "base64": "A9tvzsiElotOUVIB4CqfQp9mAwqvTM35YkmAR170aHA=", "subType": "00" } }, { "$binary": { "base64": "lI8gpK7hpb7c9x4RQugsxMnQay5LZJmwslZdvMx/dcE=", "subType": "00" } }, { "$binary": { "base64": "dNCzh40U0XvdKnSDi3HRQOWQftEsDVqc4uUvsVFGoq8=", "subType": "00" } }, { "$binary": { "base64": "IP+iwEBWBwVVZIdpaMu8k5+soFCz+TZkYn3drKZ9grE=", "subType": "00" } }, { "$binary": { "base64": "pnqyh6e0y5svHkJDShlN9CHV0WvMBE4QbtJpQw5ZCXc=", "subType": "00" } }, { "$binary": { "base64": "elEl42tbVDoRTLjAhZUFEtXiut4b3PVhg/1ZLZSQdtE=", "subType": "00" } }, { "$binary": { "base64": "vHuu2FxwclMHqyE6JBYbTYgbEkB0dqb/JuaxsvfwsmY=", "subType": "00" } }, { "$binary": { "base64": "xTf7NCe3Gf8QpE78HR5OknlLTKfs9J+RN9UZpH6fnso=", "subType": "00" } }, { "$binary": { "base64": "XiWSasRnJAulGR6+LCVD3mwRObXylqYWR9jvpywq12c=", "subType": "00" } }, { "$binary": { "base64": "MZMxEQ5ikx0PG1YFIExv0UnTZogsvgeOEZTpzvBDn4w=", "subType": "00" } }, { "$binary": { "base64": "yZMyMZBDrWbAhvnic7vvIYhmO9m5H2iuv0c8KNZrBzY=", "subType": "00" } }, { "$binary": { "base64": "xxM14hTPY5j0vvcK2C7YAEjzdsfUTFHozHC0hEo1bxI=", "subType": "00" } }, { "$binary": { "base64": "+01rqR1xVwkpGXcstbk1ItJqFVjH6Q8MGxEN3Cm9Y1A=", "subType": "00" } }, { "$binary": { "base64": "xOpLV0Z2VTRJ3iWtnWZcsyjXubTIkYWo31cO+HV1o1k=", "subType": "00" } }, { "$binary": { "base64": "BWUOLqgLBqc5NwxVlSV5H3KFQPXbCp7mdo+jF+8cJqY=", "subType": "00" } }, { "$binary": { "base64": "fuQb1S6xZDGlrEbK+kI23aL53PP1PVNwqICnZNt9Yzg=", "subType": "00" } }, { "$binary": { "base64": "SfscnoibFttahLdPVC4Ee+47ewGFKpDSU7M6HX19bKE=", "subType": "00" } }, { "$binary": { "base64": "rpSW2awybNVeKtat91VFxqbINoTfNhPfQAu+d73Xtf8=", "subType": "00" } }, { "$binary": { "base64": "9M/CP9ccOIIj2LLFmE0GFDO0Ban2wsNalEXfM6+h+1s=", "subType": "00" } }, { "$binary": { "base64": "WrEMG49l1ye4MhXs5ZS9tz8P6h+hDvthIg/2wW9ne1Q=", "subType": "00" } }, { "$binary": { "base64": "ImNhbfeyfH8qIEeA5ic0s3dAQBdzzTBS+CPsNih9vZ0=", "subType": "00" } }, { "$binary": { "base64": "dWP33YDSn04UKJN2ogh2Rui0iW/0q2y18OCDRVcfyoo=", "subType": "00" } }, { "$binary": { "base64": "lYv0isAtfGh6H9tdp3cp2eHU7q2J+uk7QrgcxtK3w7Y=", "subType": "00" } }, { "$binary": { "base64": "VGMoamB/+7zTOYcY/pqJc96xlv2PdW4hwsIAEIslTDQ=", "subType": "00" } }, { "$binary": { "base64": "yNeBWMF7BnD9wVwz2PgJsvWr77QiVvvWUvJF0+fqBug=", "subType": "00" } }, { "$binary": { "base64": "SfpvObJ+tJBXSvqeN7vlOfmhYign635lciYAJIjUtY8=", "subType": "00" } }, { "$binary": { "base64": "dsen4NqjzVGjpjufiTMs3+gqeD09EbnuogPgxrJECwg=", "subType": "00" } }, { "$binary": { "base64": "pxCWVM3sn19NsFEpgHbgLa+PmYlhN3mMiP0Wk8kJhYw=", "subType": "00" } }, { "$binary": { "base64": "q11KNvJszjYIB9n9HcC+N4uz11a3eRj1L3BH9scKMDQ=", "subType": "00" } }, { "$binary": { "base64": "A1PmkgcEToWh1JiVWE6mI5jUu7poxWWuCUt/cgRUUDc=", "subType": "00" } }, { "$binary": { "base64": "qJo3Hu4PJeanL7XEaWXO/n3YsodhZyd+MJOOmB9Kpd8=", "subType": "00" } }, { "$binary": { "base64": "BkBKLO8URFscfRY9Bav/1+L9mLohDgNr/MkZtGiraIs=", "subType": "00" } }, { "$binary": { "base64": "rZq5WA3Hx3xthOyHAJXK//f8pE2qbz7YKu3TIMp9GFY=", "subType": "00" } }, { "$binary": { "base64": "X07a/Lm80p5xd4RFs1dNmw+90tmPDPdGiAKVZkxd4zY=", "subType": "00" } }, { "$binary": { "base64": "6YrBn2ofIw1b5ooakrLOwF41BWrps8OO0H9WH4/rtlE=", "subType": "00" } }, { "$binary": { "base64": "0l86Ag5OszXpa78SlOUV3K9nff5iC1p0mRXtLg9M1s4=", "subType": "00" } }, { "$binary": { "base64": "Hn6yuxFHodeyu7ISlhYrbSf9pTiH4TDEvbYLWjTwFO0=", "subType": "00" } }, { "$binary": { "base64": "zdf4y2etKBuIpkEU1zMwoCkCsdisfXZCh8QPamm+drY=", "subType": "00" } }, { "$binary": { "base64": "rOQ9oMdiK5xxGH+jPzOvwVqdGGnF3+HkJXxn81s6hp4=", "subType": "00" } }, { "$binary": { "base64": "61aKKsE3+BJHHWYvs3xSIBvlRmKswmaOo5rygQJguUg=", "subType": "00" } }, { "$binary": { "base64": "KuDb/GIzqDM8wv7m7m8AECiWJbae5EKKtJRugZx7kR0=", "subType": "00" } }, { "$binary": { "base64": "Q+t8t2TmNUiCIorVr9F3AlVnX+Mpt2ZYvN+s8UGict8=", "subType": "00" } }, { "$binary": { "base64": "tJRZIpKxUgHyL83kW8cvfjkxN3z6WoNnUg+SQw+LK+k=", "subType": "00" } }, { "$binary": { "base64": "pnUsYjip8SvW0+m9mR5WWTkpK+p6uwJ6yBUAlBnFKMk=", "subType": "00" } }, { "$binary": { "base64": "PArHlz+yPRYDycAP/PgnI/AkP8Wgmfg++Vf4UG1Bf0E=", "subType": "00" } }, { "$binary": { "base64": "wnIh53Q3jeK8jEBe1n8kJLa89/H0BxO26ZU8SRIAs9Q=", "subType": "00" } }, { "$binary": { "base64": "4F8U59gzBLGhq58PEWQk2nch+R0Va7eTUoxMneReUIA=", "subType": "00" } }, { "$binary": { "base64": "ihKagIW3uT1dm22ROr/g5QaCpxZVj2+Fs/YSdM2Noco=", "subType": "00" } }, { "$binary": { "base64": "EJtUOOwjkrPUi9mavYAi+Gom9Y2DuFll7aDwo4mq0M0=", "subType": "00" } }, { "$binary": { "base64": "dIkr8dbaVRQFskAVT6B286BbcBBt1pZPEOcTZqk4ZcI=", "subType": "00" } }, { "$binary": { "base64": "aYVAcZYkH/Tieoa1XOjE/zCy5AJcVTHjS0NG2QB7muA=", "subType": "00" } }, { "$binary": { "base64": "sBidL6y8TenseetpioIAAtn0lK/7C8MoW4JXpVYi3z8=", "subType": "00" } }, { "$binary": { "base64": "0Dd2klU/t4R86c2WJcJDAd57k/N7OjvYSO5Vf8KH8sw=", "subType": "00" } }, { "$binary": { "base64": "I3jZ92WEVmZmgaIkLbuWhBxl7EM6bEjiEttgBJunArA=", "subType": "00" } }, { "$binary": { "base64": "aGHoQMlgJoGvArjfIbc3nnkoc8SWBxcrN7hSmjMRzos=", "subType": "00" } }, { "$binary": { "base64": "bpiWPnF/KVBQr5F6MEwc5ZZayzIRvQOLDAm4ntwOi8g=", "subType": "00" } }, { "$binary": { "base64": "tI7QVKbE6avWgDD9h4QKyFlnTxFCwd2iLySKakxNR/I=", "subType": "00" } }, { "$binary": { "base64": "XGsge0CnoaXgE3rcpKm8AEeku5QVfokS3kcI+JKV1lk=", "subType": "00" } }, { "$binary": { "base64": "JQxlryW2Q5WOwfrjAnaZxDvC83Dg6sjRVP5zegf2WiM=", "subType": "00" } }, { "$binary": { "base64": "YFuHKJOfoqp1iGVxoFjx7bLYgVdsN4GuUFxEgO9HJ5s=", "subType": "00" } }, { "$binary": { "base64": "Z6vUdiCR18ylKomf08uxcQHeRtmyav7/Ecvzz4av3k4=", "subType": "00" } }, { "$binary": { "base64": "SPGo1Ib5AiP/tSllL7Z5PAypvnKdwJLzt8imfIMSEJQ=", "subType": "00" } }, { "$binary": { "base64": "m94Nh6PFFQFLIib9Cu5LAKavhXnagSHG6F5EF8lD96I=", "subType": "00" } }, { "$binary": { "base64": "pfEkQI98mB+gm1+JbmVurPAODMFPJ4E8DnqfVyUWbSo=", "subType": "00" } }, { "$binary": { "base64": "DNj3OVRLbr43s0vd+rgWghOL3FqeO/60npdojC8Ry/M=", "subType": "00" } }, { "$binary": { "base64": "kAYIQrjHVu49W8FTxyxJeiLVRWWjC9fPcBn+Hx1F+Ss=", "subType": "00" } }, { "$binary": { "base64": "aCSO7UVOpoQvu/iridarxkxV1SVxU1i9HVSYXUAeXk4=", "subType": "00" } }, { "$binary": { "base64": "Gh6hTP/yj1IKlXQ+Q69KTfMlGZjEcXoRLGbQHNFo/1s=", "subType": "00" } }, { "$binary": { "base64": "/gDgIFQ4tAlJk3GN48IS5Qa5IPmErwGk8CHxAbp6gs0=", "subType": "00" } }, { "$binary": { "base64": "PICyimwPjxpusyKxNssOOwUotAUbygpyEtORsVGXT8g=", "subType": "00" } }, { "$binary": { "base64": "4lu+cBHyAUvuxC6JUNyHLzHsCogGSWFFnUCkDwfQdgI=", "subType": "00" } }, { "$binary": { "base64": "pSndkmoNUJwXjgkbkgOrT5f9nSvuoMEZOkwAN9ElRaE=", "subType": "00" } }, { "$binary": { "base64": "tyW+D4i26QihNM5MuBM+wnt5AdWGSJaJ4X5ydc9iWTU=", "subType": "00" } }, { "$binary": { "base64": "9Syjr8RoxUgPKr+O5rsCu07AvcebA4P8IVKyS1NVLWc=", "subType": "00" } }, { "$binary": { "base64": "67tPfDYnK2tmrioI51fOBG0ygajcV0pLo5+Zm/rEW7U=", "subType": "00" } }, { "$binary": { "base64": "y0EiPRxYTuS1eVTIaPQUQBBxwkyxNckbePvKgChwd0M=", "subType": "00" } }, { "$binary": { "base64": "NWd+2veAaeXQgR3vCvzlI4R1WW67D5YsVLdoXfdb8qg=", "subType": "00" } }, { "$binary": { "base64": "PY5RQqKQsL2GqBBSPNOEVpojNFRX/NijCghIpxD6CZk=", "subType": "00" } }, { "$binary": { "base64": "lcvwTyEjFlssCJtdjRpdN6oY+C7bxZY+WA+QAqzj9zg=", "subType": "00" } }, { "$binary": { "base64": "CWE7XRNylvTwO/9Fv56dNqUaQWMmESNS/GNIwgBaEI0=", "subType": "00" } }, { "$binary": { "base64": "ijwlrUeS8nRYqK1F8kiCYF0mNDolEZS+/lJO1Lg93C8=", "subType": "00" } }, { "$binary": { "base64": "8KzV+qYGYuIjoNj8eEpnTuHrMYuhzphl80rS6wrODuU=", "subType": "00" } }, { "$binary": { "base64": "wDyTLjSEFF895hSQsHvmoEQVS6KIkZOtq1c9dVogm9I=", "subType": "00" } }, { "$binary": { "base64": "SGrtPuMYCjUrfKF0Pq/thdaQzmGBMUvlwN3ORIu9tHU=", "subType": "00" } }, { "$binary": { "base64": "KySHON3hIoUk4xWcwTqk6IL0kgjzjxgMBObVIkCGvk4=", "subType": "00" } }, { "$binary": { "base64": "hBIdS9j0XJPeT4ot73ngELkpUoSixvRBvdOL9z48jY8=", "subType": "00" } }, { "$binary": { "base64": "Tx6um0q9HjS5ZvlFhvukpI6ORnyrXMWVW1OoxvgqII0=", "subType": "00" } }, { "$binary": { "base64": "zFKlyfX5H81+d4A4J3FKn4T5JfG+OWtR06ddyX4Mxas=", "subType": "00" } }, { "$binary": { "base64": "cGgCDuPV7MeMMYEDpgOupqyNP4BQ4H7rBnd2QygumgM=", "subType": "00" } }, { "$binary": { "base64": "IPaUoy98v11EoglTpJ4kBlEawoZ8y7BPwzjLYBpkvHQ=", "subType": "00" } }, { "$binary": { "base64": "Pfo4Am6tOWAyZNn8G9W5HWWGC3ZWmX0igI/RRB870Ro=", "subType": "00" } }, { "$binary": { "base64": "fnTSjd7bC1Udoq6iM7UDnHAC/lsIXSHp/Gy332qw+/I=", "subType": "00" } }, { "$binary": { "base64": "fApBgVRrTDyEumkeWs5p3ag9KB48SbU4Si0dl7Ns9rc=", "subType": "00" } }, { "$binary": { "base64": "QxudfBItgoCnUj5NXVnSmWH3HK76YtKkMmzn4lyyUYY=", "subType": "00" } }, { "$binary": { "base64": "sSOvwhKa29Wq94bZ5jGIiJQGbG1uBrKSBfOYBz/oZeI=", "subType": "00" } }, { "$binary": { "base64": "FdaMgwwJ0NKsqmPZLC5oE+/0D74Dfpvig3LaI5yW5Fs=", "subType": "00" } }, { "$binary": { "base64": "sRWBy12IERN43BSZIrnBfC9+zFBUdvjTlkqIH81NGt4=", "subType": "00" } }, { "$binary": { "base64": "/4tIRpxKhoOwnXAiFn1Z7Xmric4USOIfKvTYQXk3QTc=", "subType": "00" } } ] }, { "_id": { "$numberInt": "1" }, "encryptedDecimalNoPrecision": { "$$type": "binData" }, "__safeContent__": [ { "$binary": { "base64": "bE1vqWj3KNyM7cCYUv/cnYm8BPaUL3eMp5syTHq6NF4=", "subType": "00" } }, { "$binary": { "base64": "RGTjNVEsNJb+DG7DpPOam8rQWD5HZAMpRyiTQaw7tk8=", "subType": "00" } }, { "$binary": { "base64": "I93Md7QNPGmEEGYU1+VVCqBPBEvXdqHPtTJtMOn06Yk=", "subType": "00" } }, { "$binary": { "base64": "GecBFQ1PemlECWZWCl7f74vmsL6eB6mzQ9n6tK6FYfs=", "subType": "00" } }, { "$binary": { "base64": "QpjhZl+O1ORifgtCZuWAdcP6OKL7IZ2cA46v8FJcV28=", "subType": "00" } }, { "$binary": { "base64": "RlQWwhU+uVv0a+9IB5cUkEfvHBvOw3B1Sx6WfPWMqes=", "subType": "00" } }, { "$binary": { "base64": "ubb81XTC7U+4tcNzf1oYvOY6gR5hC2Izqx54f4GuJ0E=", "subType": "00" } }, { "$binary": { "base64": "6M4Q5NMQ9TqNnjzGOxIkiUIY8TEL0I3XD1QnhefQUqU=", "subType": "00" } }, { "$binary": { "base64": "BtInzk9t2FFMCEY6AQ7zN8jwrrZEs2irSv6q0Q4NaIw=", "subType": "00" } }, { "$binary": { "base64": "6vxXfETu9cuBIpRBo3jUUU04mJIH/aAhLX8K6VI5Xv0=", "subType": "00" } }, { "$binary": { "base64": "wXPCdS+q23zi1bkPnaVG2j0PsVtxdeSLJ//h6J1x8RU=", "subType": "00" } }, { "$binary": { "base64": "KY3KkfBAsN2l80wbpj41G0gwBR5KmmFnZcagg7D3ENk=", "subType": "00" } }, { "$binary": { "base64": "tI8NFAxXCX4VOnY5X73K6KI/Yspd3aR94KV39MhJlAw=", "subType": "00" } }, { "$binary": { "base64": "nFxH0UC3mATKA6Vboz+QX/hAjj19kF/SH6H5Cne7qC0=", "subType": "00" } }, { "$binary": { "base64": "q8hYqIYaIi7nOdG/7qQZYnz8Bsacfi66M1nVku4SH08=", "subType": "00" } }, { "$binary": { "base64": "4saA92R4arp4anvD9xFtze+sNcQqTEhPHyl1h70A8NE=", "subType": "00" } }, { "$binary": { "base64": "DbIziOBRRyeQS6RtBR09E37LV+CTKrEjGoRMLSpG6eE=", "subType": "00" } }, { "$binary": { "base64": "Fv80Plp/7w2gnVqrwawLd6qhJ10G4NCDm3re67cNq4Y=", "subType": "00" } }, { "$binary": { "base64": "T/T2oiQCBBES4YN7EodzPRdabZSFlYIClHBym+bQUZE=", "subType": "00" } }, { "$binary": { "base64": "ZQgHD3l46Ujqtbnj1VbbeM29C9wJzOhz+yZ/7XdSrxk=", "subType": "00" } }, { "$binary": { "base64": "ltlFKzWvyZvHxDFOYDd/XXJ6kUiJj0ln2HTCEz2o4Z4=", "subType": "00" } }, { "$binary": { "base64": "flW8A7bltC1u8bzx0WJtxosGJdOVsJFfbx33jxnpFGg=", "subType": "00" } }, { "$binary": { "base64": "SXO+92QbMKwUSG2t27ciunV1c3VvFkUuDmSczpRe008=", "subType": "00" } }, { "$binary": { "base64": "+KioGs1GM+xRBzFE67ePTWj04KMSE5/Y6qUF7nJ5kvU=", "subType": "00" } }, { "$binary": { "base64": "L3xNVbh6YH+RzqABN+5Jgb7T234Efpn766DmUvxIxgg=", "subType": "00" } }, { "$binary": { "base64": "hPF+60mBYPjh21dEmPlBhKgyc9S2qLtTkypYvnqP2Fc=", "subType": "00" } }, { "$binary": { "base64": "EletRsETy2HcjaPIm2c8CkT7ch/P3pJJDC8hasepcSU=", "subType": "00" } }, { "$binary": { "base64": "r5bMXUaNKqLPxZ+TG9HYTG4aSDgcpim27rN8rQFkM0w=", "subType": "00" } }, { "$binary": { "base64": "0Q7Erdr8+/S0wUEDDIqlS5XjBVWvhZY65K0uUDb6+Ns=", "subType": "00" } }, { "$binary": { "base64": "xEcnhXy35hbXNVBPOOt3TUHbxvKfQ48KjA9b6/rbMqQ=", "subType": "00" } }, { "$binary": { "base64": "T8bEpiQNgsEudXvyKE9SZlSvbpV/LUaslsdqgSFltyo=", "subType": "00" } }, { "$binary": { "base64": "hIoiaF2YjnxDbODfhFEB+JGZ5nf8suD3Shck5bwQ3N0=", "subType": "00" } }, { "$binary": { "base64": "qnA6qzejeRJ0rsZaZ0zOvKAaXyxt5lpscKQNYFZNl4k=", "subType": "00" } }, { "$binary": { "base64": "anAKCL2DN/le2VaP0n2ucYSEH/DaaEH/8Sa4OqTZsRA=", "subType": "00" } }, { "$binary": { "base64": "JCZlBJaFm618oWYSnT9Jr1MtwFVw4BZjOzO+5yWgR90=", "subType": "00" } }, { "$binary": { "base64": "yxyk4n9762WzcDVGnTn4jCqUnSMIVCrLDIjCX1QVj34=", "subType": "00" } }, { "$binary": { "base64": "fDI6fdKvDJwim5/CQwWZEzcrXE3LHgy7FTtffcC7tXE=", "subType": "00" } }, { "$binary": { "base64": "Vex+gcz5T+WkzsVZQrkqUR2ryyZbnaOGuWpYvjN0zCw=", "subType": "00" } }, { "$binary": { "base64": "8TLEXz+Gbbp6llHpZXVjLsdlYY9f6hrKpHVpyfDe0RY=", "subType": "00" } }, { "$binary": { "base64": "7fTyt5BrunypS65TfOzFW2E2qdIuT4SLeDeGlbQoJCs=", "subType": "00" } }, { "$binary": { "base64": "8fKGrkqN0/KuSjyXgDBmRauDKrSa//JBKRWHEB9xBf4=", "subType": "00" } }, { "$binary": { "base64": "s4codmG7uN4ss6P357jL21lazEe90M9GOK5WrOknSV0=", "subType": "00" } }, { "$binary": { "base64": "RkSpua8XF+NUdxVDU90EbLUTTyZFX3tt3atBTroFaRk=", "subType": "00" } }, { "$binary": { "base64": "LnTCuCDyAHK5B9KXzjtwGmWB+qergQk2OCjnIx9MI2A=", "subType": "00" } }, { "$binary": { "base64": "cBFh0virAX4pVXf/udIGI2951i0+0aZAdJcBVGtYnT4=", "subType": "00" } }, { "$binary": { "base64": "G54X6myQXWZ5fw/G31en3QbdgfXzL9+hFTtJpnWMqDI=", "subType": "00" } }, { "$binary": { "base64": "EdsiiuezcsFJFnYIyGjCOhnqMj1BOwTB5EFxN+ERUkg=", "subType": "00" } }, { "$binary": { "base64": "dVH9MXLtk0WTwGQ3xmrhOqfropMUkDW3o6paNPGl3NU=", "subType": "00" } }, { "$binary": { "base64": "sB3HqXKWY3pKbuEH8BTbfNIGfbY+7/ZbOc3XC+JRNNI=", "subType": "00" } }, { "$binary": { "base64": "WHyDk62Xhqbo4/iie2aLIM4x2uuAjv6102dJSHI58oM=", "subType": "00" } }, { "$binary": { "base64": "pNUFuHpeNRDUZ/NrtII2c6sNc9eGR1lIUlIyXKERA+0=", "subType": "00" } }, { "$binary": { "base64": "UPa+pdCqnN0bfAptdzldQOSd01gidrDKy8KhWrpSKAI=", "subType": "00" } }, { "$binary": { "base64": "l+7dOAlo+HUffMqFYXL6pgUFeTbwOM9CjKQLxEoLtc4=", "subType": "00" } }, { "$binary": { "base64": "SRnDXV/rN6C8xwMutv9E1luv3DOUio3VkgPr8Cpm7Ew=", "subType": "00" } }, { "$binary": { "base64": "QcH6gl+gX7xZ7OWhUNQMbndJy0Piz49pDo6RsnLkVSA=", "subType": "00" } }, { "$binary": { "base64": "t+uL4DnfsI/Zll/KXWW1cOKX3Hu8WIkm3pt9efCVSAQ=", "subType": "00" } }, { "$binary": { "base64": "myutHDctku/+Uug/nD8gRbYvmx/IovtoAAC2/fz2oHA=", "subType": "00" } }, { "$binary": { "base64": "6C+cjD0e0nSCP6cPqQYbNG7SlOd6Mfvi8hyfm7Ng+D8=", "subType": "00" } }, { "$binary": { "base64": "zg01JSoOj9oBKT0S1ldJucXzY5AKgreS+h2xJreWTOs=", "subType": "00" } }, { "$binary": { "base64": "7qQ80/FjodHl1m1py/Oii0/9C/xWbLdhaRXQ+kkCP10=", "subType": "00" } }, { "$binary": { "base64": "YwWMNH07vL6c5Nhg+MRnVByhzUunu8y0VLM9z/XvR5U=", "subType": "00" } }, { "$binary": { "base64": "Dle8bU98+fudAbc14SToZFkwvV3tcYVsjDug0NWljpc=", "subType": "00" } }, { "$binary": { "base64": "J+eKL1vPJmlzltvhI6Li5Fz/TJmi3Ng+ehRTcs46API=", "subType": "00" } }, { "$binary": { "base64": "zB3XzfFygLwC3WHkj0up+VbEd25KKoce1vOpG/5bwK4=", "subType": "00" } }, { "$binary": { "base64": "vnVnmOnL+z2pqwE+A6cVKS0Iwy4F4/2IiElJca9bUQM=", "subType": "00" } }, { "$binary": { "base64": "+lG5r/Fpqry3BtFuvY67+RntmHAMDoLVOSGc6ZoXPb0=", "subType": "00" } }, { "$binary": { "base64": "L5MXQertqc6uj7ADe8aWKbd1sYHPCE7P1VYVg9Zc3VI=", "subType": "00" } }, { "$binary": { "base64": "imKONuZgopt0bhM3GMX2WVPwQYMTobuUUEdhcLfHs4c=", "subType": "00" } }, { "$binary": { "base64": "eOkU1J1uVbiVFWBerbXsSIVcF2nqiicTkFy4x7kFHB8=", "subType": "00" } }, { "$binary": { "base64": "gI0uDhXeoH/UatDQKEf4qo8FHzWZDhb/wuWTqbq/ID4=", "subType": "00" } }, { "$binary": { "base64": "cOkd5Aa3btYhtojE/smsF/PJnULqQ4NNqTkU6KXTFmo=", "subType": "00" } }, { "$binary": { "base64": "AWNJMs1MTe294oFipp8Y6P0CjpkZ4qCZoClQF3XcHq8=", "subType": "00" } }, { "$binary": { "base64": "6gJtlzXOFhGYrVbTuRMmvMlDTwXdNtR9aGBlHZPwIMw=", "subType": "00" } }, { "$binary": { "base64": "LEmwVGA/xsEG7UrcOoYLFu6KCXgijzFznenknuDacm8=", "subType": "00" } }, { "$binary": { "base64": "mIRFPTXRrGaPtp/Ydij2jgkRe4uoUvAKxW2d8b9zYL0=", "subType": "00" } }, { "$binary": { "base64": "B+Uv2u48WALOO0L311z+eryjYQzKJVMfdHMZPhOAFmY=", "subType": "00" } }, { "$binary": { "base64": "INXXp0wDyVCq+NtfIrrC2ciETmyW/dWB/48/u4yLEZ4=", "subType": "00" } }, { "$binary": { "base64": "se7DGo8XrlrQDLEcco1tZrQt9kDe+0RTyl2bw/quG4w=", "subType": "00" } }, { "$binary": { "base64": "vr0m2+Zk9lbN6UgWCyn8xJWJOokU3IDYab5U5q1+CgQ=", "subType": "00" } }, { "$binary": { "base64": "XI+eJ8Gy2JktG1gICgoj1qpsfy1tKmH0kglWbaQH6DA=", "subType": "00" } }, { "$binary": { "base64": "A+UCuNnuAUqnQzspA6TVqUPRmtZmpSex5HFw7THRxs0=", "subType": "00" } }, { "$binary": { "base64": "xaH2Ehfljd19uo0Fvb3iwkdaiWEVQd2YPoitgEPkhSM=", "subType": "00" } }, { "$binary": { "base64": "S/iZBJGcc8+qZxyMtab65MMBoSglybwk3x58Nb86gnY=", "subType": "00" } }, { "$binary": { "base64": "w14ZE5qqY5YgkS4Zcs9YNbrQbY1XfGOOHNn9bOYnFVQ=", "subType": "00" } }, { "$binary": { "base64": "0MhGd/jEF1vjkKGp+ZMn9SjLK54jkp9W4Hg+Sp/oxaI=", "subType": "00" } }, { "$binary": { "base64": "92QZ73e/NRTYgCm4aifaKth6aAsKnLLccBc0zx/qUTY=", "subType": "00" } }, { "$binary": { "base64": "WOjzemCgFJOiGIp81RSVh/tFlzSTj9eFWcBnsiv2Ycs=", "subType": "00" } }, { "$binary": { "base64": "DrsP9CmfKPjw5yLL8bnSeAxfNzAwlb+Z8OqCiKgBY7o=", "subType": "00" } }, { "$binary": { "base64": "lMogqg8veBv6mri3/drMe9afJiKMvevkmGcw9BedfLo=", "subType": "00" } }, { "$binary": { "base64": "TxqwNcY8Tg2MPpNdkPBwvfpuTttSYRHU26DGECKYQ9o=", "subType": "00" } }, { "$binary": { "base64": "l0u1b4b4vYACWIwfnB7PZac4oDEgjQZCzHruNPTgAIY=", "subType": "00" } }, { "$binary": { "base64": "iVSGQ+cCfhbWIrY/v/WBORK92elu9gfRKyGhr6r/k00=", "subType": "00" } }, { "$binary": { "base64": "yK1forG50diEXte8ECzjfpHeYsPyuQ/dgxbxn/nzY5k=", "subType": "00" } }, { "$binary": { "base64": "gIfTLCD3VwnOwkC0zPXWTqaITxX6ZplA69PO2a6zolc=", "subType": "00" } }, { "$binary": { "base64": "O/Zxlgh3WqpzJ7+Sd8XWMVID4/GXJUUWaSqfgDUi3b0=", "subType": "00" } }, { "$binary": { "base64": "ZQ6yv368zwahUqSUYH/StL0Qgz/TwS1CzlMjVDvCciI=", "subType": "00" } }, { "$binary": { "base64": "m2rPEYkjwyiKdonMrKlcF7hya4lFOAUwEePJ3SgrNx8=", "subType": "00" } }, { "$binary": { "base64": "Mq0yl5iVKlq71bT/dT/fXOWf2n90bTnXFnOdGDN0JOc=", "subType": "00" } }, { "$binary": { "base64": "6qDGMXipPLC2O6EAAMjO2F9xx4rdqZso4IkPpH2304U=", "subType": "00" } }, { "$binary": { "base64": "jvQHRQQa2RIszE2LX2Hv2LbRhYawJ6qmtRt8HZzFQXg=", "subType": "00" } }, { "$binary": { "base64": "ovJXQrkZlpeHRciKyE/WWNm5O389gRgzx1W+Dw596X4=", "subType": "00" } }, { "$binary": { "base64": "a4kgRNvYctGYqyQv9qScL/WkljTYVylJ9pE9KDULlxU=", "subType": "00" } }, { "$binary": { "base64": "qV4Q48vPiCJMTjljotzYKI/zfExWpkKOSHGcAjGyDig=", "subType": "00" } }, { "$binary": { "base64": "jtI7zbBF+QW/aYYTkn90zzyHLXLgmy7l1bzgMb2oqic=", "subType": "00" } }, { "$binary": { "base64": "q0KmJl9txPdn962UNvnfe6UFhdk9YaFZuTm33F+csso=", "subType": "00" } }, { "$binary": { "base64": "ULNdEqeZJgtmNOhN/Y9INzsE9AnxWYwOMn+pIbRXIFs=", "subType": "00" } }, { "$binary": { "base64": "R4oz9+wkdjpKe5tE1jpG7IURAnfvS5fLP4LrD5cZfTE=", "subType": "00" } }, { "$binary": { "base64": "qG5Z7VhwSu/HT/YFTgDzyAAzJKq51xPw2HeEV5btYC4=", "subType": "00" } }, { "$binary": { "base64": "OM/1DmIIZ5Qyhtq8TGkHTBEMVKjAnKRZMRXYtTG8ctc=", "subType": "00" } }, { "$binary": { "base64": "2R5vZbljLXnDFA99YfGuRB7pAdPJVKsT25zLNMC0fUk=", "subType": "00" } }, { "$binary": { "base64": "OMbavF2EmdAz1fHkLV3ctFEUDfriKhoT2gidwHZ9z1o=", "subType": "00" } }, { "$binary": { "base64": "MWT4Zrw3/vVvTYMa1Is5Pjr3wEwnBfnEAPPUAHKQhNU=", "subType": "00" } }, { "$binary": { "base64": "tBkRPfG9yxfKocQx5pAJX0oEHKPL0Tgtr+0UYe09InE=", "subType": "00" } }, { "$binary": { "base64": "lqxpnDR/H0YgH7RcfKoNoaaRhe1SIazIeMbQ1fu9y3Q=", "subType": "00" } }, { "$binary": { "base64": "utT1UdR22PWOTrOkZauztX613lAplV4eh/ejTRb7ZSk=", "subType": "00" } }, { "$binary": { "base64": "S+Y2yFyKi/a6FXhih4yGo29X8I8OT6/zwEoX6NMKT4o=", "subType": "00" } }, { "$binary": { "base64": "QSjVppg29x6oS5yBg8OFjrFt0tuTpWCuKxfIy0k8YnE=", "subType": "00" } }, { "$binary": { "base64": "y3r6/Xsfvsl3HksXlVYkJgHUqpQGfICxg3x9f8Zw1qM=", "subType": "00" } }, { "$binary": { "base64": "BSltHzEwDjFN4du9rDHAPvl22atlcTioEtt+gC5L1tk=", "subType": "00" } }, { "$binary": { "base64": "0arGXjSN0006UnXbrWsGqhvBair569DeFDUME3Df3rA=", "subType": "00" } }, { "$binary": { "base64": "s/DumaMad08S+PBUUcrS+v42K0z8HgcdiQtrFAEu2Qs=", "subType": "00" } }, { "$binary": { "base64": "EzJ8Y8N0OQBTlnvrK82PdevDNZZO4E6CNgYVu8Cj6Ks=", "subType": "00" } }, { "$binary": { "base64": "VA4vr8jBPI5QdiPrULzzZjBMIUbG3V7Slg5zm0bFcKc=", "subType": "00" } }, { "$binary": { "base64": "YAOvEB2ZLtq9LQiFViBHWaxxWVVonC2rNYj9tN9s3L0=", "subType": "00" } }, { "$binary": { "base64": "hgaHMo9aAGS+nBwvqnTjZO+YkiQPY1c1XcIYeaYKHyI=", "subType": "00" } }, { "$binary": { "base64": "YvaoLt3ZpH0atB0tNzwMjpoxRYJXl0DqSjisMJiGVBE=", "subType": "00" } }, { "$binary": { "base64": "EMmW6CptFsiLoPOi5/uAJQ2FmeLg6mCpuVLLrRWk7Mc=", "subType": "00" } }, { "$binary": { "base64": "1jQsNMarSnarlYmXEuoFokeBMg/090qUD9wqo1Zn8Gs=", "subType": "00" } }, { "$binary": { "base64": "hupXNKhRpJxpyDAAP1TgJ5JMZh9lhbMk6s7D7dMS3C8=", "subType": "00" } } ] } ] } } } ] } fle2v2-Range-Decimal-Update.json000066400000000000000000002731701462766011000347360ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/client-side-encryption/spec/legacy{ "runOn": [ { "minServerVersion": "7.0.0", "topology": [ "replicaset" ] } ], "database_name": "default", "collection_name": "default", "data": [], "encrypted_fields": { "fields": [ { "keyId": { "$binary": { "base64": "EjRWeBI0mHYSNBI0VniQEg==", "subType": "04" } }, "path": "encryptedDecimalNoPrecision", "bsonType": "decimal", "queries": { "queryType": "rangePreview", "contention": { "$numberLong": "0" }, "sparsity": { "$numberLong": "1" } } } ] }, "key_vault_data": [ { "_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" } } ], "tests": [ { "description": "FLE2 Range Decimal. Update.", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "local": { "key": { "$binary": { "base64": "Mng0NCt4ZHVUYUJCa1kxNkVyNUR1QURhZ2h2UzR2d2RrZzh0cFBwM3R6NmdWMDFBMUN3YkQ5aXRRMkhGRGdQV09wOGVNYUMxT2k3NjZKelhaQmRCZGJkTXVyZG9uSjFk", "subType": "00" } } } } } }, "operations": [ { "name": "insertOne", "arguments": { "document": { "_id": 0, "encryptedDecimalNoPrecision": { "$numberDecimal": "0" } } } }, { "name": "insertOne", "arguments": { "document": { "_id": 1, "encryptedDecimalNoPrecision": { "$numberDecimal": "1" } } } }, { "name": "updateOne", "arguments": { "filter": { "encryptedDecimalNoPrecision": { "$gt": { "$numberDecimal": "0" } } }, "update": { "$set": { "encryptedDecimalNoPrecision": { "$numberDecimal": "2" } } } }, "result": { "matchedCount": 1, "modifiedCount": 1, "upsertedCount": 0 } } ], "expectations": [ { "command_started_event": { "command": { "listCollections": 1, "filter": { "name": "default" } }, "command_name": "listCollections" } }, { "command_started_event": { "command": { "find": "datakeys", "filter": { "$or": [ { "_id": { "$in": [ { "$binary": { "base64": "EjRWeBI0mHYSNBI0VniQEg==", "subType": "04" } } ] } }, { "keyAltNames": { "$in": [] } } ] }, "$db": "keyvault", "readConcern": { "level": "majority" } }, "command_name": "find" } }, { "command_started_event": { "command": { "insert": "default", "documents": [ { "_id": 0, "encryptedDecimalNoPrecision": { "$$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": "encryptedDecimalNoPrecision", "bsonType": "decimal", "queries": { "queryType": "rangePreview", "contention": { "$numberLong": "0" }, "sparsity": { "$numberLong": "1" } } } ] } } } }, "command_name": "insert" } }, { "command_started_event": { "command": { "insert": "default", "documents": [ { "_id": 1, "encryptedDecimalNoPrecision": { "$$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": "encryptedDecimalNoPrecision", "bsonType": "decimal", "queries": { "queryType": "rangePreview", "contention": { "$numberLong": "0" }, "sparsity": { "$numberLong": "1" } } } ] } } } }, "command_name": "insert" } }, { "command_started_event": { "command_name": "update", "command": { "update": "default", "ordered": true, "updates": [ { "q": { "encryptedDecimalNoPrecision": { "$gt": { "$binary": { "base64": "DeFiAAADcGF5bG9hZACxYgAABGcAnWIAAAMwAH0AAAAFZAAgAAAAAJu2KgiI8vM+kz9qD3ZQzFQY5qbgYqCqHG5R4jAlnlwXBXMAIAAAAAAAUXxFXsz764T79sGCdhxvNd5b6E/9p61FonsHyEIhogVsACAAAAAAt19RL3Oo5ni5L8kcvgOJYLgVYyXJExwP8pkuzLG7f/kAAzEAfQAAAAVkACAAAAAAPQPvL0ARjujSv2Rkm8r7spVsgeC1K3FWcskGGZ3OdDIFcwAgAAAAACgNn660GmefR8jLqzgR1u5O+Uocx9GyEHiBqVGko5FZBWwAIAAAAADflr+fsnZngm6KRWYgHa9JzK+bXogWl9evBU9sQUHPHQADMgB9AAAABWQAIAAAAAD2Zi6kcxmaD2mY3VWrP+wYJMPg6cSBIYPapxaFQxYFdQVzACAAAAAAM/cV36BLBY3xFBXsXJY8M9EHHOc/qrmdc2CJmj3M89gFbAAgAAAAAOpydOrKxx6m2gquSDV2Vv3w10GocmNCFeOo/fRhRH9JAAMzAH0AAAAFZAAgAAAAAOaNqI9srQ/mI9gwbk+VkizGBBH/PPWOVusgnfPk3tY1BXMAIAAAAAAc96O/pwKCmHCagT6T/QV/wz4vqO+R22GsZ1dse2Vg6QVsACAAAAAAgzIak+Q3UFLTHXPmJ+MuEklFtR3eLtvM+jdKkmGCV/YAAzQAfQAAAAVkACAAAAAA0XlQgy/Yu97EQOjronl9b3dcR1DFn3deuVhtTLbJZHkFcwAgAAAAACoMnpVl6EFJak8A+t5N4RFnQhkQEBnNAx8wDqmq5U/dBWwAIAAAAACR26FJif673qpwF1J1FEkQGJ1Ywcr/ZW6JQ7meGqzt1QADNQB9AAAABWQAIAAAAAAOtpNexRxfv0yRFvZO9DhlkpU4mDuAb8ykdLnE5Vf1VAVzACAAAAAAeblFKm/30orP16uQpZslvsoS8s0xfNPIBlw3VkHeekYFbAAgAAAAAPEoHj87sYE+nBut52/LPvleWQBzB/uaJFnosxp4NRO2AAM2AH0AAAAFZAAgAAAAAIr8xAFm1zPmrvW4Vy5Ct0W8FxMmyPmFzdWVzesBhAJFBXMAIAAAAABYeeXjJEzTHwxab6pUiCRiZjxgtN59a1y8Szy3hfkg+gVsACAAAAAAJuoY4rF8mbI+nKb+5XbZShJ8191o/e8ZCRHE0O4Ey8MAAzcAfQAAAAVkACAAAAAAl+ibLk0/+EwoqeC8S8cGgAtjtpQWGEZDsybMPnrrkwEFcwAgAAAAAHPPBudWgQ+HUorLDpJMqhS9VBF2VF5aLcxgrM1s+yU7BWwAIAAAAAAcCcBR2Vyv5pAFbaOU97yovuOi1+ATDnLLcAUqHecXcAADOAB9AAAABWQAIAAAAACR9erwLTb+tcWFZgJ2MEfM0PKI9uuwIjDTHADRFgD+SQVzACAAAAAAcOop8TXsGUVQoKhzUllMYWxL93xCOkwtIpV8Q6hiSYYFbAAgAAAAAKXKmh4V8veYwob1H03Q3p3PN8SRAaQwDT34KlNVUjiDAAM5AH0AAAAFZAAgAAAAALv0vCPgh7QpmM8Ug6ad5ioZJCh7pLMdT8FYyQioBQ6KBXMAIAAAAADsCPyIG8t6ApQkRk1fX/sfc1kpuWCWP8gAEpnYoBSHrQVsACAAAAAAJe/r67N6d8uTiogvfoR9rEXbIDjyLb9EVdqkayFFGaYAAzEwAH0AAAAFZAAgAAAAAIW4AxJgYoM0pcNTwk1RSbyjZGIqgKL1hcTJmNrnZmoPBXMAIAAAAAAZpfx3EFO0vY0f1eHnE0PazgqeNDTaj+pPJMUNW8lFrAVsACAAAAAAP+Um2vwW6Bj6vuz9DKz6+6aWkoKoEmFNoiz/xXm7lOsAAzExAH0AAAAFZAAgAAAAAKliO6L9zgeuufjj174hvmQGNRbmYYs9yAirL7OxwEW3BXMAIAAAAAAqU7vs3DWUQ95Eq8OejwWnD0GuXd+ASi/uD6S0l8MM1QVsACAAAAAAb9legYzsfctBPpHyl7YWpPmLr5QiNZFND/50N1vv2MUAAzEyAH0AAAAFZAAgAAAAAOGQcCBkk+j/Kzjt/Cs6g3BZPJG81wIHBS8JewHGpgk+BXMAIAAAAABjrxZXWCkdzrExwCgyHaafuPSQ4V4x2k9kUCAqUaYKDQVsACAAAAAADBU6KefT0v8zSmseaMNmQxKjJar72y7MojLFhkEHqrUAAzEzAH0AAAAFZAAgAAAAAPmCNEt4t97waOSd5hNi2fNCdWEkmcFJ37LI9k4Az4/5BXMAIAAAAABX7DuDPNg+duvELf3NbLWkPMFw2HGLgWGHyVWcPvSNCAVsACAAAAAAS7El1FtZ5STh8Q1FguvieyYX9b2DF1DFVsb9hzxXYRsAAzE0AH0AAAAFZAAgAAAAAD4vtVUYRNB+FD9yoQ2FVJH3nMeJeKbi6eZfth638YqbBXMAIAAAAAANCuUB4OdmuD6LaDK2f3vaqfgYYvg40wDXOBbcFjTqLwVsACAAAAAA9hqC2VoJBjwR7hcQ45xO8ZVojwC83jiRacCaDj6Px2gAAzE1AH0AAAAFZAAgAAAAAJPIRzjmTjbdIvshG6UslbEOd797ZSIdjGAhGWxVQvK1BXMAIAAAAABgmJ0Jh8WLs9IYs/a7DBjDWd8J3thW/AGJK7zDnMeYOAVsACAAAAAAi9zAsyAuou2oiCUHGc6QefLUkACa9IgeBhGu9W/r0X8AAzE2AH0AAAAFZAAgAAAAAABQyKQPoW8wGPIqnsTv69+DzIdRkohRhOhDmyVHkw9WBXMAIAAAAAAqWA2X4tB/h3O1Xlawtz6ndI6WaTwgU1QYflL35opu5gVsACAAAAAAWI/Gj5aZMwDIxztqmVL0g5LBcI8EdKEc2UA28pnekQoAAzE3AH0AAAAFZAAgAAAAACB7NOyGQ1Id3MYnxtBXqyZ5Ul/lHH6p1b10U63DfT6bBXMAIAAAAADpOryIcndxztkHSfLN3Kzq29sD8djS0PspDSqERMqokQVsACAAAAAADatsMW4ezgnyi1PiP7xk+gA4AFIN/fb5uJqfVkjg4UoAAzE4AH0AAAAFZAAgAAAAAKVfXLfs8XA14CRTB56oZwV+bFJN5BHraTXbqEXZDmTkBXMAIAAAAAASRWTsfGOpqdffiOodoqIgBzG/yzFyjR5CfUsIUIWGpgVsACAAAAAAkgCHbCwyX640/0Ni8+MoYxeHUiC+FSU4Mn9jTLYtgZgAAzE5AH0AAAAFZAAgAAAAAH/aZr4EuS0/noQR9rcF8vwoaxnxrwgOsSJ0ys8PkHhGBXMAIAAAAACd7ObGQW7qfddcvyxRTkPuvq/PHu7+6I5dxwS1Lzy5XAVsACAAAAAA3q0eKdV7KeU3pc+CtfypKR7BPxwaf30yu0j9FXeOOboAAzIwAH0AAAAFZAAgAAAAAKvlcpFFNq0oA+urq3w6d80PK1HHHw0H0yVWvU9aHijXBXMAIAAAAADWnAHQ5Fhlcjawki7kWzdqjM2f6IdGJblojrYElWjsZgVsACAAAAAAO0wvY66l24gx8nRxyVGC0QcTztIi81Kx3ndRhuZr6W4AAzIxAH0AAAAFZAAgAAAAAH/2aMezEOddrq+dNOkDrdqf13h2ttOnexZsJxG1G6PNBXMAIAAAAABNtgnibjC4VKy5poYjvdsBBnVvDTF/4mmEAxsXVgZVKgVsACAAAAAAqvadzJFLqQbs8WxgZ2D2X+XnaPSDMLCVVgWxx5jnLcYAAzIyAH0AAAAFZAAgAAAAAF2wZoDL6/V59QqO8vdRZWDpXpkV4h4KOCSn5e7x7nmzBXMAIAAAAADLZBu7LCYjbThaVUqMK14H/elrVOYIKJQCx4C9Yjw37gVsACAAAAAAEh6Vs81jLU204aGpL90fmYTm5i5R8/RT1uIbg6VU3HwAAzIzAH0AAAAFZAAgAAAAAH27yYaLn9zh2CpvaoomUPercSfJRUmBY6XFqmhcXi9QBXMAIAAAAAAUwumVlIYIs9JhDhSj0R0+59psCMsFk94E62VxkPt42QVsACAAAAAAT5x2hCCd2bpmpnyWaxas8nSxTc8e4C9DfKaqr0ABEysAAzI0AH0AAAAFZAAgAAAAALMg2kNAO4AFFs/mW3In04yFeN4AP6Vo0klyUoT06RquBXMAIAAAAAAgGWJbeIdwlpqXCyVIYSs0dt54Rfc8JF4b8uYc+YUj0AVsACAAAAAAWHeWxIkyvXTOWvfZzqtPXjfGaWWKjGSIQENTU3zBCrsAAzI1AH0AAAAFZAAgAAAAALas/i1T2DFCEmrrLEi7O2ngJZyFHialOoedVXS+OjenBXMAIAAAAAA1kK0QxY4REcGxHeMkgumyF7iwlsRFtw9MlbSSoQY7uAVsACAAAAAAUNlpMJZs1p4HfsD4Q4WZ4TBEi6Oc2fX34rzyynqWCdwAAzI2AH0AAAAFZAAgAAAAAP1TejmWg1CEuNSMt6NUgeQ5lT+oBoeyF7d2l5xQrbXWBXMAIAAAAABPX0kj6obggdJShmqtVfueKHplH4ZrXusiwrRDHMOKeQVsACAAAAAAIYOsNwC3DA7fLcOzqdr0bOFdHCfmK8tLwPoaE9uKOosAAzI3AH0AAAAFZAAgAAAAAMrKn+QPa/NxYezNhlOX9nyEkN1kE/gW7EuZkVqYl0b8BXMAIAAAAABUoZMSPUywRGfX2EEencJEKH5x/P9ySUVrhStAwgR/LgVsACAAAAAAMgZFH6lQIIDrgHnFeslv3ld20ynwQjQJt3cAp4GgrFkAAzI4AH0AAAAFZAAgAAAAAMmD1+a+oVbiUZd1HuZqdgtdVsVKwuWAn3/M1B6QGBM3BXMAIAAAAACLyytOYuZ9WEsIrrtJbXUx4QgipbaAbmlJvSZVkGi0CAVsACAAAAAA4v1lSp5H9BB+HYJ4bH43tC8aeuPZMf78Ng1JOhJh190AAzI5AH0AAAAFZAAgAAAAAOVKV7IuFwmYP1qVv8h0NvJmfPICu8yQhzjG7oJdTLDoBXMAIAAAAABL70XLfQLKRsw1deJ2MUvxSWKxpF/Ez73jqtbLvqbuogVsACAAAAAAvfgzIorXxE91dDt4nQxYfntTsx0M8Gzdsao5naQqcRUAAzMwAH0AAAAFZAAgAAAAAKS/1RSAQma+xV9rz04IcdzmavtrBDjOKPM+Z2NEyYfPBXMAIAAAAAAOJDWGORDgfRv8+w5nunh41wXb2hCA0MRzwnLnQtIqPgVsACAAAAAAf42C1+T7xdHEFF83+c2mF5S8PuuL22ogXXELnRAZ4boAAzMxAH0AAAAFZAAgAAAAAFeq8o82uNY1X8cH6OhdTzHNBUnCChsEDs5tm0kPBz3qBXMAIAAAAABaxMBbsaeEj/EDtr8nZfrhhhirBRPJwVamDo5WwbgvTQVsACAAAAAAMbH453A+BYAaDOTo5kdhV1VdND1avNwvshEG/4MIJjQAAzMyAH0AAAAFZAAgAAAAAI8IKIfDrohHh2cjspJHCovqroSr5N3QyVtNzFvT5+FzBXMAIAAAAABXHXteKG0DoOMmECKp6ro1MZNQvXGzqTDdZ0DUc8QfFAVsACAAAAAA/w5s++XYmO+9TWTbtGc3n3ndV4T9JUribIbF4jmDLSMAAzMzAH0AAAAFZAAgAAAAAJkHvm15kIu1OtAiaByj5ieWqzxiu/epK6c/9+KYIrB0BXMAIAAAAACzg5TcyANk0nes/wCJudd1BwlkWWF6zw3nGclq5v3SJQVsACAAAAAAvruXHTT3irPJLyWpI1j/Xwf2FeIE/IV+6Z49pqRzISoAAzM0AH0AAAAFZAAgAAAAAAYSOvEWWuSg1Aym7EssNLR+xsY7e9BcwsX4JKlnSHJcBXMAIAAAAABT48eY3PXVDOjw7JpNjOe1j2JyI3LjDnQoqZ8Je5B2KgVsACAAAAAAU2815RR57TQ9uDg0XjWjBkAKvf8yssxDMzrM4+FqP6AAAzM1AH0AAAAFZAAgAAAAAGQxC9L1e9DfO5XZvX1yvc3hTLtQEdKO9FPMkyg0Y9ZABXMAIAAAAADtmcMNJwdWLxQEArMGZQyzpnu+Z5yMmPAkvgq4eAKwNQVsACAAAAAAJ88zt4Y/Hoqh+zrf6KCOiUwHbOzCxSfp6k/qsZaYGEgAAzM2AH0AAAAFZAAgAAAAADLHK2LNCNRO0pv8n4fAsxwtUqCNnVK8rRgNiQfXpHSdBXMAIAAAAACf16EBIHRKD3SzjRW+LMOl+47QXA3CJhMzlcqyFRW22AVsACAAAAAAMGz4fAOa0EoVv90fUffwLjBrQhHATf+NdlgCR65vujAAAzM3AH0AAAAFZAAgAAAAAHiZJiXKNF8bbukQGsdYkEi95I+FSBHy1I5/hK2uEZruBXMAIAAAAADE+lZBa8HDUJPN+bF6xI9x4N7GF9pj3vBR7y0BcfFhBAVsACAAAAAAGIEN6sfqq30nyxW4dxDgXr/jz5HmvA9T1jx/pKCn4zgAAzM4AH0AAAAFZAAgAAAAAI1oa2OIw5TvhT14tYCGmhanUoYcCZtNbrVbeoMldHNZBXMAIAAAAAAx2nS0Ipblf2XOgBiUOuJFBupBhe7nb6QPLZlA4aMPCgVsACAAAAAA9xu828hugIgo0E3de9dZD+gTpVUGlwtDba+tw/WcbUoAAzM5AH0AAAAFZAAgAAAAABgTWS3Yap7Q59hii/uPPimHWXsr+DUmsqfwt/X73qsOBXMAIAAAAACKK05liW5KrmEAvtpCB1WUltruzUylDDpjea//UlWoOAVsACAAAAAAcgN4P/wakJ5aJK5c1bvJBqpVGND221dli2YicPFfuAYAAzQwAH0AAAAFZAAgAAAAABOAnBPXDp6i9TISQXvcNKwGDLepZTu3cKrB4vKnSCjBBXMAIAAAAADjjzZO7UowAAvpwyG8BNOVqLCccMFk3aDK4unUeft5ywVsACAAAAAA4zkCd4k9gvfXoD1C7vwTjNcdVJwEARh8h/cxZ4PNMfgAAzQxAH0AAAAFZAAgAAAAAHN8hyvT1lYrAsdiV5GBdd5jhtrAYE/KnSjw2Ka9hjz9BXMAIAAAAAD794JK7EeXBs+D7yOVK7nWF8SbZ/7U8gZ7nnT9JFNwTAVsACAAAAAAg8Wt1HO3NhByq2ggux2a4Lo6Gryr24rEFIqh2acrwWMAAzQyAH0AAAAFZAAgAAAAAO93bPrq8bsnp1AtNd9ETnXIz0lH/2HYN/vuw9wA3fyFBXMAIAAAAABHlls5fbaF2oAGqptC481XQ4eYxInTC29aElfmVZgDUgVsACAAAAAANoQXEWpXJpgrSNK/cKi/m7oYhuSRlp1IZBF0bqTEATcAAzQzAH0AAAAFZAAgAAAAAL1YsAZm1SA0ztU6ySIrQgCCA74V6rr0/4iIygCcaJL6BXMAIAAAAADTXWTHWovGmUR1Zg9l/Aqq9H5mOCJQQrb/Dfae7e3wKAVsACAAAAAA5dunyJK6/SVfDD0t9QlNBcFqoZnf9legRjHaLSKAoQMAAzQ0AH0AAAAFZAAgAAAAAEoFAeHk0RZ9kD+cJRD3j7PcE5gzWKnyBrF1I/MDNp5mBXMAIAAAAACgHtc2hMBRSZjKw8RAdDHK+Pi1HeyjiBuAslGVNcW5tAVsACAAAAAAXzBLfq+GxRtX4Wa9fazA49DBLG6AjZm2XODStJKH8D0AAzQ1AH0AAAAFZAAgAAAAAAW+7DmSN/LX+/0uBVJDHIc2dhxAGz4+ehyyz8fAnNGoBXMAIAAAAAA6Ilw42EvvfLJ3Eq8Afd+FjPoPcQutZO6ltmCLEr8kxQVsACAAAAAAbbZalyo07BbFjPFlYmbmv0z023eT9eLkHqeVUnfUAUAAAzQ2AH0AAAAFZAAgAAAAANBdV7M7kuYO3EMoQItAbXv4t2cIhfaT9V6+s4cg9djlBXMAIAAAAABvz4MIvZWxxrcJCL5qxLfFhXiUYB1OLHdKEjco94SgDgVsACAAAAAAK2GVGvyPIKolF/ECcmfmkVcf1/IZNcaTv96N92yGrkEAAzQ3AH0AAAAFZAAgAAAAAMoAoiAn1kc79j5oPZtlMWHMhhgwNhLUnvqkqIFvcH1NBXMAIAAAAADcJTW7WiCyW0Z9YDUYwppXhLj4Ac1povpJvcAq+i48MQVsACAAAAAAIGxGDzoeB3PTmudl4+j6piQB++e33EEzuzAiXcqGxvUAAzQ4AH0AAAAFZAAgAAAAACI3j5QP7dWHpcT6WO/OhsWwRJNASBYqIBDNzW8IorEyBXMAIAAAAABxUpBSjXwCKDdGP9hYU+RvyR+96kChfvyyRC4jZmztqAVsACAAAAAAvBCHguWswb4X0xdcAryCvZgQuthXzt7597bJ5VxAMdgAAzQ5AH0AAAAFZAAgAAAAAKsbycEuQSeNrF8Qnxqw3x3og8JmQabwGqnDbqzFRVrrBXMAIAAAAACno/3ef2JZJS93SVVzmOZSN+jjJHT8s0XYq2M46d2sLAVsACAAAAAAAt5zLJG+/j4K8rnkFtAn8IvdUVNefe6utJ3rdzgwudIAAzUwAH0AAAAFZAAgAAAAAPXIcoO8TiULqlxzb74NFg+I8kWX5uXIDUPnh2DobIoMBXMAIAAAAADR6/drkdTpnr9g1XNvKDwtBRBdKn7c2c4ZNUVK5CThdQVsACAAAAAAJqOA1c6KVog3F4Hb/GfDb3jCxXDRTqpXWSbMH4ePIJsAAzUxAH0AAAAFZAAgAAAAAEa03ZOJmfHT6/nVadvIw71jVxEuIloyvxXraYEW7u7pBXMAIAAAAADzRlBJK75FLiKjz3djqcgjCLo/e3yntI3MnPS48OORhgVsACAAAAAAnQhx4Rnyj081XrLRLD5NLpWmRWCsd0M9Hl7Jl19R0h8AAzUyAH0AAAAFZAAgAAAAAKx8NLSZUU04pSSGmHa5fh2oLHsEN5mmNMNHL95/tuC9BXMAIAAAAAA59hcXVaN3MNdHoo11OcH1aPRzHCwpVjO9mGfMz4xh3QVsACAAAAAAYIPdjV2XbPj7dBeHPwnwhVU7zMuJ+xtMUW5mIOYtmdAAAzUzAH0AAAAFZAAgAAAAAHNKAUxUqBFNS9Ea9NgCZoXMWgwhP4x0/OvoaPRWMquXBXMAIAAAAABUZ551mnP4ZjX+PXU9ttomzuOpo427MVynpkyq+nsYCQVsACAAAAAALnVK5p2tTTeZEh1zYt4iqKIQT9Z0si//Hy1L85oF+5IAAzU0AH0AAAAFZAAgAAAAALfGXDlyDVcGaqtyHkLT0qpuRhJQLgCxtznazhFtuyn/BXMAIAAAAABipxlXDq14C62pXhwAeen5+syA+/C6bN4rtZYcO4zKwAVsACAAAAAAXUf0pzUq0NhLYagWDap4uEiwq5rLpcx29rWbt1NYMsMAAzU1AH0AAAAFZAAgAAAAANoEr8sheJjg4UCfBkuUzarU9NFoy1xwbXjs5ifVDeA9BXMAIAAAAABPoyTf6M+xeZVGES4aNzVlq7LgjqZXJ/QunjYVusGUEAVsACAAAAAA1hA2gMeZZPUNytk9K+lB1RCqWRudRr7GtadJlExJf8oAAzU2AH0AAAAFZAAgAAAAAKvDiK+xjlBe1uQ3SZTNQl2lClIIvpP/5CHwY6Kb3WlgBXMAIAAAAAANnxImq5MFbWaRBHdJp+yD09bVlcFtiFDYsy1eDZj+iQVsACAAAAAAWtsyO+FxMPSIezwsV1TJD8ZrXAdRnQM6DJ+f+1V3qEkAAzU3AH0AAAAFZAAgAAAAAF49IlFH9RmSUSvUQpEPUedEksrQUcjsOv44nMkwXhjzBXMAIAAAAADJtWGbk0bZzmk20obz+mNsp86UCu/nLLlbg7ppxYn7PgVsACAAAAAA3k0Tj/XgPQtcYijH8cIlQoe/VXf15q1nrZNmg7yWYEgAAzU4AH0AAAAFZAAgAAAAAOuSJyuvz50lp3BzXlFKnq62QkN2quNU1Gq1IDsnFoJCBXMAIAAAAAAqavH1d93XV3IzshWlMnzznucadBF0ND092/2ApI1AcAVsACAAAAAAzUrK4kpoKCmcpdZlZNI13fddjdoAseVe67jaX1LobIIAAzU5AH0AAAAFZAAgAAAAALtgC4Whb4ZdkCiI30zY6fwlsxSa7lEaOAU3SfUXr02XBXMAIAAAAACgdZ6U1ZVgUaZZwbIaCdlANpCw6TZV0bwg3DS1NC/mnAVsACAAAAAAzI49hdpp0PbO7S2KexISxC16sE73EUAEyuqUFAC/J48AAzYwAH0AAAAFZAAgAAAAAF6PfplcGp6vek1ThwenMHVkbZgrc/dHgdsgx1VdPqZ5BXMAIAAAAACha3qhWkqmuwJSEXPozDO8y1ZdRLyzt9Crt2vjGnT7AAVsACAAAAAA7nvcU59+LwxGupSF21jAeAE0x7JE94tjRkJfgM1yKU8AAzYxAH0AAAAFZAAgAAAAAKoLEhLvLjKc7lhOJfx+VrGJCx9tXlOSa9bxQzGR6rfbBXMAIAAAAAAIDK5wNnjRMBzET7x/KAMExL/zi1IumJM92XTgXfoPoAVsACAAAAAAFkUYWFwNr815dEdFqp+TiIozDcq5IBNVkyMoDjharDQAAzYyAH0AAAAFZAAgAAAAADoQv6lutRmh5scQFvIW6K5JBquLxszuygM1tzBiGknIBXMAIAAAAADAD+JjW7FoBQ76/rsECmmcL76bmyfXpUU/awqIsZdO+wVsACAAAAAAPFHdLw3jssmEXsgtvl/RBNaUCRA1kgSwsofG364VOvQAAzYzAH0AAAAFZAAgAAAAAJNHUGAgn56KekghO19d11nai3lAh0JAlWfeP+6w4lJBBXMAIAAAAAD9XGJlvz59msJvA6St9fKW9CG4JoHV61rlWWnkdBRLzwVsACAAAAAAxwP/X/InJJHmrjznvahIMgj6pQR30B62UtHCthSjrP0AAzY0AH0AAAAFZAAgAAAAAHgYoMGjEE6fAlAhICv0+doHcVX8CmMVxyq7+jlyGrvmBXMAIAAAAAC/5MQZgTHuIr/O5Z3mXPvqrom5JTQ8IeSpQGhO9sB+8gVsACAAAAAAuPSXVmJUAUpTQg/A9Bu1hYczZF58KEhVofakygbsvJQAAzY1AH0AAAAFZAAgAAAAANpIljbxHOM7pydY877gpRQvYY2TGK7igqgGsavqGPBABXMAIAAAAAAqHyEu9gpurPOulApPnr0x9wrygY/7mXe9rAC+tPK80wVsACAAAAAA7gkPzNsS3gCxdFBWbSW9tkBjoR5ib+saDvpGSB3A3ogAAzY2AH0AAAAFZAAgAAAAAGR+gEaZTeGNgG9BuM1bX2R9ed4FCxBA9F9QvdQDAjZwBXMAIAAAAABSkrYFQ6pf8MZ1flgmeIRkxaSh/Eep4Btdx4QYnGGnwAVsACAAAAAApRovMiV00hm/pEcT4XBsyPNw0eo8RLAX/fuabjdU+uwAAzY3AH0AAAAFZAAgAAAAAFNprhQ3ZwIcYbuzLolAT5n/vc14P9kUUQComDu6eFyKBXMAIAAAAAAcx9z9pk32YbPV/sfPZl9ALIEVsqoLXgqWLVK/tP+heAVsACAAAAAA/qxvuvJbAHwwhfrPVpmCFzNvg2cU/NXaWgqgYUZpgXwAAzY4AH0AAAAFZAAgAAAAADgyPqQdqQrgfmJjRFAILTHzXbdw5kpKyfeoEcy6YYG/BXMAIAAAAAAE+3XsBQ8VAxAkN81au+f3FDeCD/s7KoZD+fnM1MJSSAVsACAAAAAAhRnjrXecwV0yeCWKJ5J/x12Xx4qVJahsCEVHB/1U2rcAAzY5AH0AAAAFZAAgAAAAAI0CT7JNngTCTUSei1Arw7eHWCD0jumv2rb7imjWIlWABXMAIAAAAABSP8t6ya0SyCphXMwnru6ZUDXWElN0NfBvEOhDvW9bJQVsACAAAAAAGWeGmBNDRaMtvm7Rv+8TJ2sJ4WNXKcp3tqpv5Se9Ut4AAzcwAH0AAAAFZAAgAAAAAD/FIrGYFDjyYmVb7oTMVwweWP7A6F9LnyIuNO4MjBnXBXMAIAAAAACIZgJCQRZu7NhuNMyOqCn1tf+DfU1qm10TPCfj5JYV3wVsACAAAAAA5hmY4ptuNxULGf87SUFXQWGAONsL9U29duh8xqsHtxoAAzcxAH0AAAAFZAAgAAAAAHIkVuNDkSS1cHIThKc/O0r2/ubaABTOi8Q1r/dvBAsEBXMAIAAAAADdHYqchEiJLM340c3Q4vJABmmth3+MKzwLYlsG6GS7sQVsACAAAAAADa+KP/pdTiG22l+ZWd30P1iHjnBF4zSNRdFm0oEK82kAAzcyAH0AAAAFZAAgAAAAAJmoDILNhC6kn3masElfnjIjP1VjsjRavGk1gSUIjh1NBXMAIAAAAAD97Ilvp3XF8T6MmVVcxMPcdL80RgQ09UoC6PnoOvZ1IQVsACAAAAAA2RK3Xng6v8kpvfVW9tkVXjpE+BSnx9/+Fw85Evs+kUEAAzczAH0AAAAFZAAgAAAAAI5bm3YO0Xgf0VT+qjVTTfvckecM3Cwqj7DTKZXf8/NXBXMAIAAAAAD/m+h8fBhWaHm6Ykuz0WX1xL4Eme3ErLObyEVJf8NCywVsACAAAAAAfb1VZZCqs2ivYbRzX4p5CtaCkKW+g20Pr57FWXzEZi8AAzc0AH0AAAAFZAAgAAAAANqo4+p6qdtCzcB4BX1wQ6llU7eFBnuu4MtZwp4B6mDlBXMAIAAAAAAGiz+VaukMZ+6IH4jtn4KWWdKK4/W+O+gRioQDrfzpMgVsACAAAAAAG4YYkTp80EKo59mlHExDodRQFR7njhR5dmISwUJ6ukAAAzc1AH0AAAAFZAAgAAAAAPrFXmHP2Y4YAm7b/aqsdn/DPoDkv7B8egWkfe23XsM1BXMAIAAAAAAGhwpKAr7skeqHm3oseSbO7qKNhmYsuUrECBxJ5k+D2AVsACAAAAAAAqPQi9luYAu3GrFCEsVjd9z2zIDcp6SPTR2w6KQEr+IAAzc2AH0AAAAFZAAgAAAAABzjYxwAjXxXc0Uxv18rH8I3my0Aguow0kTwKyxbrm+cBXMAIAAAAADVbqJVr6IdokuhXkEtXF0C2gINLiAjMVN20lE20Vmp2QVsACAAAAAAD7K1Fx4gFaaizkIUrf+EGXQeG7QX1jadhGc6Ji471H8AAzc3AH0AAAAFZAAgAAAAAFMm2feF2fFCm/UC6AfIyepX/xJDSmnnolQIBnHcPmb5BXMAIAAAAABLI11kFrQoaNVZFmq/38aRNImPOjdJh0Lo6irI8M/AaAVsACAAAAAAOWul0oVqJ9CejD2RqphhTC98DJeRQy5EwbNerU2+4l8AAzc4AH0AAAAFZAAgAAAAAJvXB3KyNiNtQko4SSzo/9b2qmM2zU9CQTTDfLSBWMgRBXMAIAAAAAAvjuVP7KsLRDeqVqRziTKpBrjVyqKiIbO9Gw8Wl2wFTAVsACAAAAAADlE+oc1ins+paNcaOZJhBlKlObDJ4VQORWjFYocM4LgAAzc5AH0AAAAFZAAgAAAAAPGdcxDiid8z8XYnfdDivNMYVPgBKdGOUw6UStU+48CdBXMAIAAAAAARj6g1Ap0eEfuCZ4X2TsEw+Djrhto3fA5nLwPaY0vCTgVsACAAAAAAoHqiwGOUkBu8SX5U1yHho+UIFdSN2MdQN5s6bQ0EsJYAAzgwAH0AAAAFZAAgAAAAAP5rGPrYGt3aKob5f/ldP0qrW7bmWvqnKY4QwdDWz400BXMAIAAAAADTQkW2ymaaf/bhteOOGmSrIR97bAnJx+yN3yMj1bTeewVsACAAAAAADyQnHGH2gF4w4L8axUsSTf6Ubk7L5/eoFOJk12MtZAoAAzgxAH0AAAAFZAAgAAAAAAlz6wJze5UkIxKpJOZFGCOf3v2KByWyI6NB6JM9wNcBBXMAIAAAAABUC7P/neUIHHoZtq0jFVBHY75tSFYr1Y5S16YN5XxC1QVsACAAAAAAgvxRbXDisNnLY3pfsjDdnFLtkvYUC4lhA68eBXc7KAwAAzgyAH0AAAAFZAAgAAAAAFJ8AtHcjia/9Y5pLEc3qVgH5xKiXw12G9Kn2A1EY8McBXMAIAAAAAAxe7Bdw7eUSBk/oAawa7uicTEDgXLymRNhBy1LAxhDvwVsACAAAAAAxKPaIBKVx3jTA+R/el7P7AZ7efrmTGjJs3Hj/YdMddwAAzgzAH0AAAAFZAAgAAAAAO8uwQUaKFb6vqR3Sv3Wn4QAonC2exOC9lGG1juqP5DtBXMAIAAAAABZf1KyJgQg8/Rf5c02DgDK2aQu0rNCOvaL60ohDHyY+gVsACAAAAAAqyEjfKC8lYoIfoXYHUqHZPoaA6EK5BAZy5dxXZmay4kAAzg0AH0AAAAFZAAgAAAAAE8YtqyRsGCeiR6hhiyisR/hccmK4nZqIMzO4lUBmEFzBXMAIAAAAAC1UYOSKqAeG1UJiKjWFVskRhuFKpj9Ezy+lICZvFlN5AVsACAAAAAA6Ct9nNMKyRazn1OKnRKagm746CGu+jyhbL1qJnZxGi0AAzg1AH0AAAAFZAAgAAAAAPhCrMausDx1QUIEqp9rUdRKyM6a9AAx7jQ3ILIu8wNIBXMAIAAAAACmH8lotGCiF2q9VQxhsS+7LAZv79VUAsOUALaGxE/EpAVsACAAAAAAnc1xCKfdvbUEc8F7XZqlNn1C+hZTtC0I9I3LL06iaNkAAzg2AH0AAAAFZAAgAAAAAOBi/GAYFcstMSJPgp3VkMiuuUUCrZytvqYaU8dwm8v2BXMAIAAAAACEZSZVyD3pKzGlbdwlYmWQhHHTV5SnNLknl2Gw8IaUTQVsACAAAAAAfsLZsEDcWSuNsIo/TD1ReyQW75HPMgmuKZuWFOLKRLoAAzg3AH0AAAAFZAAgAAAAAIQuup+YGfH3mflzWopN8J1X8o8a0d9CSGIvrA5HOzraBXMAIAAAAADYvNLURXsC2ITMqK14LABQBI+hZZ5wNf24JMcKLW+84AVsACAAAAAACzfjbTBH7IwDU91OqLAz94RFkoqBOkzKAqQb55gT4/MAAzg4AH0AAAAFZAAgAAAAAKsh0ADyOnVocFrOrf6MpTrNvAj8iaiE923DPryu124gBXMAIAAAAADg24a8NVE1GyScc6tmnTbmu5ulzO+896fE92lN08MeswVsACAAAAAAaPxcOIxnU7But88/yadOuDJDMcCywwrRitaxMODT4msAAzg5AH0AAAAFZAAgAAAAAKkVC2Y6HtRmv72tDnPUSjJBvse7SxLqnr09/Uuj9sVVBXMAIAAAAABYNFUkH7ylPMN+Bc3HWX1e0flGYNbtJNCY9SltJCW/UAVsACAAAAAAZYK/f9H4OeihmpiFMH7Wm7uLvs2s92zNA8wyrNZTsuMAAzkwAH0AAAAFZAAgAAAAADDggcwcb/Yn1Kk39sOHsv7BO/MfP3m/AJzjGH506Wf9BXMAIAAAAAAYZIsdjICS0+BDyRUPnrSAZfPrwtuMaEDEn0/ijLNQmAVsACAAAAAAGPnYVvo2ulO9z4LGd/69NAklfIcZqZvFX2KK0s+FcTUAAzkxAH0AAAAFZAAgAAAAAEWY7dEUOJBgjOoWVht1wLehsWAzB3rSOBtLgTuM2HC8BXMAIAAAAAAAoswiHRROurjwUW8u8D5EUT+67yvrgpB/j6PzBDAfVwVsACAAAAAA6NhRTYFL/Sz4tao7vpPjLNgAJ0FX6P/IyMW65qT6YsMAAzkyAH0AAAAFZAAgAAAAAPZaapeAUUFPA7JTCMOWHJa9lnPFh0/gXfAPjA1ezm4ZBXMAIAAAAACmJvLY2nivw7/b3DOKH/X7bBXjJwoowqb1GtEFO3OYgAVsACAAAAAA/JcUoyKacCB1NfmH8vYqC1f7rd13KShrQqV2r9QBP44AAzkzAH0AAAAFZAAgAAAAAK00u6jadxCZAiA+fTsPVDsnW5p5LCr4+kZZZOTDuZlfBXMAIAAAAAAote4zTEYMDgaaQbAdN8Dzv93ljPLdGjJzvnRn3KXgtQVsACAAAAAAxXd9Mh6R3mnJy8m7UfqMKi6oD5DlZpkaOz6bEjMOdiwAAzk0AH0AAAAFZAAgAAAAAFbgabdyymiEVYYwtJSWa7lfl/oYuj/SukzJeDOR6wPVBXMAIAAAAADAFGFjS1vPbN6mQEhkDYTD6V2V23Ys9gUEUMGNvMPkaAVsACAAAAAAL/D5Sze/ZoEanZLK0IeEkhgVkxEjMWVCfmJaD3a8uNIAAzk1AH0AAAAFZAAgAAAAABNMR6UBv2E627CqLtQ/eDYx7OEwQ7JrR4mSHFa1N8tLBXMAIAAAAAAxH4gucI4UmNVB7625C6hFSVCuIpJO3lusJlPuL8H5EQVsACAAAAAAVLHNg0OUVqZ7WGOP53BkTap9FOw9dr1P4J8HxqFqU04AAzk2AH0AAAAFZAAgAAAAAG8cd6WBneNunlqrQ2EmNf35W7OGObGq9WL4ePX+LUDmBXMAIAAAAAAjJ2+sX87NSis9hBsgb1QprVRnO7Bf+GObCGoUqyPE4wVsACAAAAAAs9c9SM49/pWmyUQKslpt3RTMBNSRppfNO0JBvUqHPg0AAzk3AH0AAAAFZAAgAAAAAFWOUGkUpy8yf6gB3dio/aOfRKh7XuhvsUj48iESFJrGBXMAIAAAAAAY7sCDMcrUXvNuL6dO0m11WyijzXZvPIcOKob6IpC4PQVsACAAAAAAJOP+EHz6awDb1qK2bZQ3kTV7wsj5Daj/IGAWh4g7omAAAzk4AH0AAAAFZAAgAAAAAGUrIdKxOihwNmo6B+aG+Ag1qa0+iqdksHOjQj+Oy9bZBXMAIAAAAABwa5dbI2KmzBDNBTQBEkjZv4sPaeRkRNejcjdVymRFKQVsACAAAAAA4ml/nm0gJNTcJ4vuD+T2Qfq2fQZlibJp/j6MOGDrbHMAAzk5AH0AAAAFZAAgAAAAAOx89xV/hRk64/CkM9N2EMK6aldII0c8smdcsZ46NbP8BXMAIAAAAADBF6tfQ+7q9kTuLyuyrSnDgmrdmrXkdhl980i1KHuGHgVsACAAAAAACUqiFqHZdGbwAA+hN0YUE5zFg+H+dabIB4dj5/75W/YAAzEwMAB9AAAABWQAIAAAAADJDdC9aEFl4Y8J/awHbnXGHjfP+VXQilPHJg7ewaJI7AVzACAAAAAAE+tqRl6EcBMXvbr4GDiNIYObTsYpa1n6BJk9EjIJVicFbAAgAAAAAJVc+HYYqa0m1Hq6OiRX8c0iRnJYOt6AJAJoG0sG3GMSAAMxMDEAfQAAAAVkACAAAAAA3F9rjEKhpoHuTULVGgfUsGGwJs3bISrXkFP1v6KoQLgFcwAgAAAAAIBf0tXw96Z/Ds0XSIHX/zk3MzUR/7WZR/J6FpxRWChtBWwAIAAAAABWrjGlvKYuTS2s8L9rYy8Hf0juFGJfwQmxVIjkTmFIGQADMTAyAH0AAAAFZAAgAAAAAOYIYoWkX7dGuyKfi3XssUlc7u/gWzqrR9KMkikKVdmSBXMAIAAAAABVF2OYjRTGi9Tw8XCAwZWLpX35Yl271TlNWp6N/nROhAVsACAAAAAA0nWwYzXQ1+EkDvnGq+SMlq20z+j32Su+i/A95SggPb4AAzEwMwB9AAAABWQAIAAAAACMtPm12YtdEAvqu6Eji1yuRXnu1RJP6h0l7pH3lSH4MwVzACAAAAAAENyCFfyUAh1veQBGx+cxiB7Sasrj41jzCGflZkB5cRMFbAAgAAAAAKdI2LMqISr/T5vuJPg6ZRBm5fVi2aQCc4ra3A4+AjbDAAMxMDQAfQAAAAVkACAAAAAAvlI4lDcs6GB1cnm/Tzo014CXWqidCdyE5t2lknWQd4QFcwAgAAAAAD60SpNc4O2KT7J0llKdSpcX1/Xxs97N715a1HsTFkmBBWwAIAAAAABuuRkJWAH1CynggBt1/5sPh9PoGiqTlS24D/OE2uHXLQADMTA1AH0AAAAFZAAgAAAAAKl8zcHJRDjSjJeV/WvMxulW1zrTFtaeBy/aKKhadc6UBXMAIAAAAADBdWQl5SBIvtZZLIHszePwkO14W1mQ0izUk2Ov21cPNAVsACAAAAAAHErCYycpqiIcCZHdmPL1hi+ovLQk4TAvENpfLdTRamQAAzEwNgB9AAAABWQAIAAAAABb6LXDWqCp1beQgQjj8I3sRTtFhlrmiBi+h/+ikmrvugVzACAAAAAA9stpgTecT7uTyaGNs3K9Bp0A7R0QaIAOfscyMXHBPX8FbAAgAAAAAHUt+McyXrJ1H8SwnHNVO181Ki8vDAM1f7XI26mg95ZDAAMxMDcAfQAAAAVkACAAAAAA97NTT+81PhDhgptNtp4epzA0tP4iNb9j1AWkiiiKGM8FcwAgAAAAAKPbHg7ise16vxmdPCzksA/2Mn/qST0L9Xe8vnQugVkcBWwAIAAAAABB0EMXfvju4JU/mUH/OvxWbPEl9NJkcEp4iCbkXI41fAADMTA4AH0AAAAFZAAgAAAAAMqpayM2XotEFmm0gwQd9rIzApy0X+7HfOhNk6VU7F5lBXMAIAAAAACJR9+q5T9qFHXFNgGbZnPubG8rkO6cwWhzITQTmd6VgwVsACAAAAAAOZLQ6o7e4mVfDzbpQioa4d3RoTvqwgnbmc5Qh2wsZuoAAzEwOQB9AAAABWQAIAAAAADQnslvt6Hm2kJPmqsTVYQHE/wWeZ4bE1XSkt7TKy0r1gVzACAAAAAA8URTA4ZMrhHPvlp53TH6FDCzS+0+61qHm5XK6UiOrKEFbAAgAAAAAHQbgTCdZcbdA0avaTmZXUKnIS7Nwf1tNrcXDCw+PdBRAAMxMTAAfQAAAAVkACAAAAAAhujlgFPFczsdCGXtQ/002Ck8YWQHHzvWvUHrkbjv4rwFcwAgAAAAALbV0lLGcSGfE7mDM3n/fgEvi+ifjl7WZ5b3aqjDNvx9BWwAIAAAAACbceTZy8E3QA1pHmPN5kTlOx3EO8kJM5PUjTVftw1VpgADMTExAH0AAAAFZAAgAAAAABm/6pF96j26Jm7z5KkY1y33zcAEXLx2n0DwC03bs/ixBXMAIAAAAAD01OMvTZI/mqMgxIhA5nLs068mW+GKl3OW3ilf2D8+LgVsACAAAAAAaLvJDrqBESTNZSdcXsd+8GXPl8ZkUsGpeYuyYVv/kygAAzExMgB9AAAABWQAIAAAAACfw9/te4GkHZAapC9sDMHHHZgmlTrccyJDPFciOMSOcwVzACAAAAAAIIC1ZpHObvmMwUfqDRPl4C1aeuHwujM1G/yJbvybMNAFbAAgAAAAAAs9x1SnVpMfNv5Bm1aXGwHmbbI9keWa9HRD35XuCBK5AAMxMTMAfQAAAAVkACAAAAAAkxHJRbnShpPOylLoDdNShfILeA1hChKFQY9qQyZ5VmsFcwAgAAAAAKidrY+rC3hTY+YWu2a7fuMH2RD/XaiTIBW1hrxNCQOJBWwAIAAAAACW0kkqMIzIFMn7g+R0MI8l15fr3k/w/mHtY5n6SYTEwAADMTE0AH0AAAAFZAAgAAAAAByuYl8dBvfaZ0LO/81JW4hYypeNmvLMaxsIdvqMPrWoBXMAIAAAAABNddwobOUJzm9HOUD8BMZJqkNCUCqstHZkC76FIdNg9AVsACAAAAAAQQOkIQtkyNavqCnhQbNg3HfqrJdsAGaoxSJePJl1qXsAAzExNQB9AAAABWQAIAAAAABxMy7X5hf7AXGDz3Y/POu1ZpkMlNcSvSP92NOO/Gs7wAVzACAAAAAAHJshWo2T5wU2zvqCyJzcJQKQaHFHpCpMc9oWBXkpUPoFbAAgAAAAAGeiJKzlUXAvL0gOlW+Hz1mSa2HsV4RGmyLmCHlzbAkoAAMxMTYAfQAAAAVkACAAAAAAlqbslixl7Zw3bRlibZbe/WmKw23k8uKeIzPKYEtbIy0FcwAgAAAAAHEKwpUxkxOfef5HYvulXPmdbzTivwdwrSYIHDeNRcpcBWwAIAAAAADuPckac21Hrg/h0kt5ShJwVEZ9rx6SOHd2+HDjqxEWTQADMTE3AH0AAAAFZAAgAAAAAMXrXx0saZ+5gORmwM2FLuZG6iuO2YS+1IGPoAtDKoKBBXMAIAAAAADIQsxCr8CfFKaBcx8kIeSywnGh7JHjKRJ9vJd9x79y7wVsACAAAAAAcvBV+SykDYhmRFyVYwFYB9oBKBSHr55Jdz2cXeowsUQAAzExOAB9AAAABWQAIAAAAAAm83FA9yDUpwkbKTihe7m53u+DivS9BU2b4vQMtCVQ2AVzACAAAAAAz3m1UB/AbZPa4QSKFDnUgHaT78+6iGOFAtouiBorEgEFbAAgAAAAAIgbpyYtJj5513Z5XYqviH/HXG/5+mqR52iBbfqMmDtZAAMxMTkAfQAAAAVkACAAAAAAJRzYK0PUwr9RPG2/7yID0WgcTJPB2Xjccp5LAPDYunkFcwAgAAAAAIIh24h3DrltAzNFhF+MEmPrZtzr1PhCofhChZqfCW+jBWwAIAAAAAAzRNXtL5o9VXMk5D5ylI0odPDJDSZZry1wfN+TedH70gADMTIwAH0AAAAFZAAgAAAAAHSaHWs/dnmI9sc7nB50VB2Bzs0kHapMHCQdyVEYY30TBXMAIAAAAACkV22lhEjWv/9/DubfHBAcwJggKI5mIbSK5L2nyqloqQVsACAAAAAAS19m7DccQxgryOsBJ3GsCs37yfQqNi1G+S6fCXpEhn4AAzEyMQB9AAAABWQAIAAAAAAC/I4TQRtCl12YZmdGz17X4GqSQgfwCPgRBwdHmdwu+QVzACAAAAAAx8f3z2ut/RAZhleari4vCEE+tNIn4ikjoUwzitfQ588FbAAgAAAAAJci0w1ZB8W2spJQ+kMpod6HSCtSR2jrabOH+B0fj3A4AAMxMjIAfQAAAAVkACAAAAAADGB5yU2XT0fse/MPWgvBvZikVxrl5pf3S5K1hceKWooFcwAgAAAAAIxTmlLHMjNaVDEfJbXvRez0SEPWFREBJCT6qTHsrljoBWwAIAAAAAAlswzAl81+0DteibwHD+CG5mZJrfHXa9NnEFRtXybzzwADMTIzAH0AAAAFZAAgAAAAABmO7QD9vxWMmFjIHz13lyOeV6vHT6mYCsWxF7hb/yOjBXMAIAAAAACT9lmgkiqzuWG24afuzYiCeK9gmJqacmxAruIukd0xEAVsACAAAAAAZa0/FI/GkZR7CtX18Xg9Tn9zfxkD0UoaSt+pIO5t1t4AAzEyNAB9AAAABWQAIAAAAAAfPUoy7QyZKhIIURso+mkP9qr1izbjETqF5s22GwjCjAVzACAAAAAAvLMsIDQ/go4VUxeh50UHmsvMvfx51cwyONnRD2odvC0FbAAgAAAAAKMb+1CodEalAFnDrEL1Ndt8ztamZ+9134m9Kp3GQgd+AAMxMjUAfQAAAAVkACAAAAAAE3ZqUar0Bq2zWbARE0bAv98jBlK9UJ73/xcwdMWWlSkFcwAgAAAAAK4M+MmC+9sFiFsumMyJZQKxWmmJiuG9H7IzKw083xxkBWwAIAAAAAAqkAONzhvMhkyL1D/6h7QQxEkdhC3p2WjXH+VGq5qCqQADMTI2AH0AAAAFZAAgAAAAAMo8FJiOq63cAmyk2O7eI7GcbQh/1j4RrMTqly3rexftBXMAIAAAAADjVmpd0WiRGTw/gAqEgGolt2EI7Csv14vKdmYoMD0aAgVsACAAAAAA07XQBzBUQMNw7F2/YxJjZNuPVpHTTgbLd1oGk77+bygAAzEyNwB9AAAABWQAIAAAAACu5IGaIx7A3Jvly/kzlCsSA4s3iJwuIl8jEdRH0k93NwVzACAAAAAA9NRUyxYE+t0Xyosyt6vIfMFW/vBoYg6sR+jBNs4JAxIFbAAgAAAAAAzyZ91dx+0oMlOVAjRGiMrPySikY/U9eMEB4WJb3uWtAAMxMjgAfQAAAAVkACAAAAAALkRy0GJInXYLA+cgjs6Myb0a+Gu9hgXhHvhLNoGWfckFcwAgAAAAANbALyt9zCSvwnLaWCd2/y2eoB7qkWTvv1Ldu8r40JPuBWwAIAAAAAD4Fl5bV5sz4isIE9bX+lmAp+aAKaZgVYVZeVfrItkCZAADMTI5AH0AAAAFZAAgAAAAAGoUK/DSWhT8LZhszSUqDbTrp8cSA7rdqmADKL+MILtTBXMAIAAAAABHnEE9bVa6lvhfhEMkkV2kzSSxH/sMW/FIJuw3CzWs6wVsACAAAAAAanavcBdqZxgRGKvEK95wTmeL1K1CeDSXZsXUAs81uOgAAzEzMAB9AAAABWQAIAAAAAC922ZDQE3h2fQKibGMZ9hV0WNlmrPYYSdtaSyYxsWYqgVzACAAAAAAagMovciKK6WVjIc2cCj8nK5O/gVOFFVeVAJpRp89tmQFbAAgAAAAAKcTFfPQzaFiAtSFhqbN02sCE1BKWJSrRfGN5L6oZwzkAAMxMzEAfQAAAAVkACAAAAAAtK+JqX3K/z2txjAU15DgX4y90DS2YLfIJFolCOkJJJwFcwAgAAAAAMnR5V7gfX7MNqqUdL5AkWlkhyFXaBRVNej+Rcn8lrQkBWwAIAAAAAA2cDNRXZuiC241TGRvdFyctJnrNcdbZOP9zHio81tkngADMTMyAH0AAAAFZAAgAAAAAAeGrIMK/bac6kPczxbvRYqKMkcpeI2FjdMpD91FDWIvBXMAIAAAAAAix62z1LeS8yvSXCl5gHSIomjyx76fF3S1lp9k900hygVsACAAAAAAiYwzf2m71aWFD5ajcXyW2JX2EzQOkBroTGMg29nLPYIAAzEzMwB9AAAABWQAIAAAAACphf298InM0Us4HT8o1W1MGw0D/02vd7Jh+U0h7qaFaQVzACAAAAAAFXtk7YpqsOJxsqGWSIL+YcBE96G3Zz9D31gPqDW94y8FbAAgAAAAAAOrS1KVA94rjB1jZ1pPocpCeBG+B14RzWoHqVDpp7JbAAMxMzQAfQAAAAVkACAAAAAATLDS2cuDVM3yDMuWNgk2iGKBTzPpfJMbvxVOSY39ZfcFcwAgAAAAAPT5wRi2cLHIUflXzm6EQB/m7xdThP80ir1VV/JBBqvxBWwAIAAAAAB9lEtZS0aXCFbCtSbhnis27S5IPcfWGygHW8AHn3QqzwADMTM1AH0AAAAFZAAgAAAAAJNjExiZVX7jfFGfYpQu16qxLN0YPqVU/5CQ/Y67YSinBXMAIAAAAABMpm2+6KrkRUlXzQoMPHrQmIO6dkQz66tYdfTeA3dKqQVsACAAAAAAFXobHiMLvNZuEPr8jtewCX2J93EZG3JNeyVg92fue6YAAzEzNgB9AAAABWQAIAAAAABlFkYtLCx901X6QVVMkSn6Z7k30UF4xHaA0OZJJ9bdyQVzACAAAAAATez+F9GHcGzTp7jjv4feboUNb8JCkIp4EqcPFisnq7MFbAAgAAAAACE7JvOpBgMoZ7kRd4QbxIhxukPTUxXpzhjnBHiR7XoRAAMxMzcAfQAAAAVkACAAAAAA8NJKN0IxZnruhswGQkiruv8Ih0EMwDcSZx/Xasup9dkFcwAgAAAAAKaJZRxzA+Igeydvuk6cSwUHXcrmT4PjhuPu//FslpdnBWwAIAAAAAD53Rok1Vq/PMAnXmarqoHJ0PEyYUBmVESa9hIpCv/G9QADMTM4AH0AAAAFZAAgAAAAABHxHdEClz7hbSSgE58+dWLlSMJnoPz+jFxp4bB1GmLQBXMAIAAAAAD3nSvT6aGD+A110J/NwEfp0nPutlmuB5B+wA3CC3noGAVsACAAAAAA3Apjd+TapONB7k5wBVwTWgn8t+Sq2oyyU5/+as109RcAAzEzOQB9AAAABWQAIAAAAAC/o8qW/ifk3KuJ01VFkyNLgQafxB5/bGs2G5VyyVafOwVzACAAAAAA1bMqAFGDHSl6BYNLbxApvkAv2K1/oafywiX0MDz1dGUFbAAgAAAAAHJXLlId3edFoniLD/9K2A5973MeP2Ro31flDyqm3l5QAAMxNDAAfQAAAAVkACAAAAAAY2V8I1bz3a1AxTtmED6UhdhA09huFkuuEX8R+d/WDPUFcwAgAAAAAPTVoNRiI76tcRKqd+JBBVyy4+YcKST42p0QX2BtmQ2VBWwAIAAAAACcxt9hg14WqPNiDv1MkqVljM2e2KJEv53lA17LhV6ZigADMTQxAH0AAAAFZAAgAAAAAO2kSsW0WGN9AOtK4xK2SHrGhWiaAbMEKT4iZkRpaDN/BXMAIAAAAABKGzQcPM8LT2dwOggxoWjv/1imYWabbG/G4kBw8OWaxAVsACAAAAAAC9hLK1dScQTAqg+YAG3ObdPzg2Xet57HmOFpGmyUR9UAAzE0MgB9AAAABWQAIAAAAAAiCwzNEEaH/mDam68IdDftnhthyUFdb+ZCNSBQ91WlHQVzACAAAAAA7tHyHcxCzmbJeFYZyPm4mEgkTGKOvwY4MX82OvH0Jn8FbAAgAAAAAAb5IAbZ1hXCNegQ+S+C9i/Z8y6sS8KeU04V6hXa2ml6AAMxNDMAfQAAAAVkACAAAAAAGuCHVNJSuoVkpPOnS5s89GuA+BLi2IPBUr2Bg1sWEPIFcwAgAAAAAEl1gncS5/xO7bQ/KQSstRV3rOT2SW6nV92ZANeG2SR6BWwAIAAAAAA9LOcKmhek8F2wAh8yvT/vjp2gaouuO+Hmv10lwAeWPAADMTQ0AH0AAAAFZAAgAAAAAMfxz7gEaoCdPvXrubDhCZUS0ARLZc1svgbXgMDlVBPgBXMAIAAAAAB6a5dDA3fuT5Vz2KvAcbUEFX/+B7Nw2p1QqbPoQ5TTuAVsACAAAAAAcf/y75UOuI62A6vWH7bYr/5Jz+nirZVYK/81trN6XOQAAzE0NQB9AAAABWQAIAAAAACnYsqF/VzmjIImC9+dqrHO1TM6lJ6fRwM0mM6Wf6paOwVzACAAAAAA5tgZzch8uDCR1ky3SllVaKVpxAlbrhvlNDTazZZRZOAFbAAgAAAAALeGiLJS4z2zhgVpxzyPdRYyACP9QzQBOob34YrIZumCAAMxNDYAfQAAAAVkACAAAAAAEC0sIVmadtW4YMuRXH7RpAhXclsd+3bmqGXCMeaT014FcwAgAAAAABPpXh0uzpsJJB+IRUNajmMB9WGwswfpw5T9xk3Xj6ANBWwAIAAAAAAmf+NYh9TZ/QRu3w/GQz66n7DtfbJijN3G7KzeL8lstAADMTQ3AH0AAAAFZAAgAAAAABaIB3n49Xm9cOafSrQsE0WCcYp8rMIO/qVwIlMF5YLRBXMAIAAAAAC9EyWJV3xOu9bzgdJ/yX+ko7qLf1u3AxNMataW2C9EzQVsACAAAAAAvVbDkLxXx2DcMLifIQ3K0IIJcLcAG9DUrNfI6aoUjNcAAzE0OAB9AAAABWQAIAAAAAA5rZItA/cocRnngYqcJ3nBXQ+l688aKz3EQyLbYYunPAVzACAAAAAAwKyA+L7TgxztPClLrIMk2JXR+w7c04N3ZOqPgjvrIvsFbAAgAAAAACzvZ33h6aWEe8hmo+1f6OXJ72FY5hvWaUuha64ZV3KFAAMxNDkAfQAAAAVkACAAAAAA3htn7oHJ0YYpIrs+Mzyh85Ys67HwAdv5LQl1mCdoMWkFcwAgAAAAAEHjCtNNLenHuSIYux6ezAHsXDaj2DlTF67ToDhDDe6HBWwAIAAAAAD+P4H0sk9jOd+7vOANt2/1Ectb+4ZRGPE8GkHWNXW3MgADMTUwAH0AAAAFZAAgAAAAAEnt18Km/nqggfIJWxzTr9r3hnXNaueG6XO9A5G11LnGBXMAIAAAAAD7QxzGMN/ard5TfFLecE6uusMmXG2+RBsBR+/NCQHUwAVsACAAAAAAQEZ1ZZ8GC8rdbg7s87OM5Gr9qkTXS9+P5DuAZxj5Gl4AAzE1MQB9AAAABWQAIAAAAAAVAKK/GoY8AACu/hyMpO4hdLq6JnEyWNzkyci9sbaD/wVzACAAAAAA2HmeqpMlvvBpV2zQTYIRmsc4MFlfHRwLof0ycJgMg/MFbAAgAAAAACdltCeWi5E/q1Li1eXLChpM2D9QQSGLBZ82NklQSc0oAAMxNTIAfQAAAAVkACAAAAAAhHyq1GQC/GiMwpYjcsfkNxolJ10ARKjIjfkW1Wipzi0FcwAgAAAAAD/uaGWxTDq87F8XZ6CrFI+RNa8yMqfSZdqK00Kj833BBWwAIAAAAAD6aEdOO0CsQGagioOCvANPCEHSpJ8BSixlPBq5ERhB7AADMTUzAH0AAAAFZAAgAAAAABAJJxHoZD+MQBWqm9UM9Dd3z5ZohIZGWRaRVRsMptKQBXMAIAAAAADrE/ca+gqj/SH4oao4wE4qn2ovoTydzcMbDbrfnUs3zAVsACAAAAAAeNCIQN6hVnGJinytQRFGlQ2ocoprXNqpia+BSxzl+uwAAzE1NAB9AAAABWQAIAAAAAAv01wz7VG9mTepjXQi6Zma+7b/OVBaKVkWNbgDLr1mFgVzACAAAAAA0I5sxz8r6wkCp5Tgvr+iL4p6MxSOq5d3e1kZG+0b7NkFbAAgAAAAAIA32v6oGkAOS96HexGouNTex+tLahtx9QF2dgGClk6WAAMxNTUAfQAAAAVkACAAAAAAWXecRwxSon68xaa9THXnRDw5ZfzARKnvvjTjtbae6T0FcwAgAAAAAPh0UfUMEo7eILCMv2tiJQe1bF9qtXq7GJtC6H5Va4fIBWwAIAAAAADqFr1ThRrTXNgIOrJWScO9mk86Ufi95IDu5gi4vP+HWQADMTU2AH0AAAAFZAAgAAAAAEY5WL8/LpX36iAB1wlQrMO/xHVjoO9BePVzbUlBYo+bBXMAIAAAAABoKcpadDXUARedDvTmzUzWPe1jTuvD0z9oIcZmKuiSXwVsACAAAAAAJuJbwuaMrAFoI+jU/IYr+k4RzAqITrOjAd3HWCpJHqEAAzE1NwB9AAAABWQAIAAAAADnJnWqsfx0xqNnqfFGCxIplVu8mXjaHTViJT9+y2RuTgVzACAAAAAAWAaSCwIXDwdYxWf2NZTly/iKVfG/KDjHUcA1BokN5sMFbAAgAAAAAJVxavipE0H4/JQvhagdytXBZ8qGooeXpkbPQ1RfYMVHAAMxNTgAfQAAAAVkACAAAAAAsPG7LaIpJvcwqcbtfFUpIjj+vpNj70Zjaw3eV9T+QYsFcwAgAAAAAJQ71zi0NlCyY8ZQs3IasJ4gB1PmWx57HpnlCf3+hmhqBWwAIAAAAACD58TO6d+71GaOoS+r73rAxliAO9GMs4Uc8JbOTmC0OwADMTU5AH0AAAAFZAAgAAAAAAGiSqKaQDakMi1W87rFAhkogfRAevnwQ41onWNUJKtuBXMAIAAAAAASgiDpXfGh7E47KkOD8MAcX8+BnDShlnU5JAGdnPdqOAVsACAAAAAAI+2TTQIgbFq4Yr3lkzGwhG/tqChP7hRAx2W0fNaH6jcAAzE2MAB9AAAABWQAIAAAAAB7L4EnhjKA5xJD3ORhH2wOA1BvpnQ+7IjRYi+jjVEaJAVzACAAAAAAuhBIm0nL3FJnVJId+7CKDASEo+l2E89Z9/5aWSITK4AFbAAgAAAAALtSICOzQDfV9d+gZuYxpEj6cCeHnKTT+2G3ceP2H65kAAMxNjEAfQAAAAVkACAAAAAAaROn1NaDZFOGEWw724dsXBAm6bgmL5i0cki6QZQNrOoFcwAgAAAAANVT8R6UvhrAlyqYlxtmnvkR4uYK/hlvyQmBu/LP6/3ZBWwAIAAAAAD+aHNMP/X+jcRHyUtrCNkk1KfMtoD3GTmShS8pWGLt+AADMTYyAH0AAAAFZAAgAAAAADqSR5e0/Th59LrauDA7OnGD1Xr3H3NokfVxzDWOFaN7BXMAIAAAAACt30faNwTWRbvmykDpiDYUOCwA6QDbBBYBFWS7rdOB4AVsACAAAAAAF7SvnjjRk5v2flFOKaBAEDvjXaL1cpjsQLtK2fv9zdQAAzE2MwB9AAAABWQAIAAAAADmtb1ZgpZjSeodPG/hIVlsnS8hoRRwRbrTVx89VwL62AVzACAAAAAAi38e1g6sEyVfSDkzZbaZXGxKI/zKNbMasOl2LYoWrq8FbAAgAAAAAALACk0KcCDN/Kv8WuazY8ORtUGkOZ5Dsm0ys1oOppp/AAMxNjQAfQAAAAVkACAAAAAAf/f7AWVgBxoKjr7YsEQ4w/fqSvuQWV2HMiA3rQ7ur0sFcwAgAAAAADkkeJozP6FFhUdRIN74H4UhIHue+eVbOs1NvbdWYFQrBWwAIAAAAAB55FlHAkmTzAYj/TWrGkRJw2EhrVWUnZXDoMYjyfB/ZwADMTY1AH0AAAAFZAAgAAAAAI2WEOymtuFpdKi4ctanPLnlQud+yMKKb8p/nfKmIy56BXMAIAAAAADVKrJmhjr1rfF3p+T+tl7UFd1B7+BfJRk0e7a4im7ozgVsACAAAAAA5E7Ti3PnFiBQoCcb/DN7V1uM3Xd6VKiexPKntssFL7kAAzE2NgB9AAAABWQAIAAAAAAuHU9Qd79hjyvKOujGanSGDIQlxzsql8JytTZhEnPw+AVzACAAAAAAjF2gV/4+sOHVgDd/oR5wDi9zL7NGpGD+NsEpGXy/a4QFbAAgAAAAAJzMoyojYV6Ed/LpVN5zge93Odv3U7JgP7wxeRaJZGTdAAMxNjcAfQAAAAVkACAAAAAA7dQDkt3iyWYCT94d7yqUtPPwp4qkC0ddu+HFdHgVKEkFcwAgAAAAANuYvtvZBTEq4Rm9+5eb7VuFopowkrAuv86PGP8Q8/QvBWwAIAAAAACeqXoAOQOE4j0zRMlkVd8plaW0RX1npsFvB38Xmzv7sAADMTY4AH0AAAAFZAAgAAAAAAwnZSDhL4tNGYxlHPhKYB8s28dY5ScSwiKZm3UhT8U3BXMAIAAAAABDoY6dhivufTURQExyC9Gx3ocpl09bgbbQLChj3qVGbgVsACAAAAAAF+1nS7O0v85s3CCy+9HkdeoEfm2C6ZiNbPMMnSfsMHUAAzE2OQB9AAAABWQAIAAAAAC2VuRdaC4ZJmLdNOvD6R2tnvkyARteqXouJmI46V306QVzACAAAAAAMn1Z6B35wFTX9mEYAPM+IiJ5hauEwfD0CyIvBrxHg7IFbAAgAAAAAOG6DvDZkT9B/xZWmjao2AevN7MMbs3Oh9YJeSd/hZ+hAAMxNzAAfQAAAAVkACAAAAAAVerb7qVNy457rNOHOgDSKyWl5ojun7iWrv1uHPXrIZQFcwAgAAAAAIDcYS9j5z+gx0xdJj09L7876r/vjvKTi/d3bXDE3PhyBWwAIAAAAADuhVLqb1Bkrx8aNymS+bx2cL8GvLFNH4SAi690DUgnWQADMTcxAH0AAAAFZAAgAAAAAH/E44yLxKCJjuSmU9A8SEhbmkDOx1PqqtYcZtgOzJdrBXMAIAAAAABgLh9v2HjBbogrRoQ82LS6KjZQnzjxyJH4PH+F3jupSAVsACAAAAAAIlO46ehXp4TqpDV0t6op++KO+uWBFh8iFORZjmx2IjkAAzE3MgB9AAAABWQAIAAAAAAlNUdDL+f/SSQ5074mrq0JNh7CTXwTbbhsQyDwWeDVMwVzACAAAAAANIH2IlSNG0kUw4qz0budjcWn8mNR9cJlYUqPYdonucAFbAAgAAAAAJMrOUOyiu5Y3sV76zwEFct8L7+i8WGlQI2+8z2W2kzaAAMxNzMAfQAAAAVkACAAAAAASZ+CvUDtlk/R4HAQ3a+PHrKeY/8ifAfh0oXYFqliu80FcwAgAAAAAJelpzPgM65OZFt/mvGGpwibclQ49wH+1gbUGzd9OindBWwAIAAAAAD9qeDchteEpVXWcycmD9kl9449C1dOw0r60TBm5jK+cQADMTc0AH0AAAAFZAAgAAAAAN9fkoUVbvFV2vMNMAkak4gYfEnzwKI3eDM3pnDK5q3lBXMAIAAAAACnDkgVNVNUlbQ9RhR6Aot2nVy+U4km6+GHPkLr631jEAVsACAAAAAANzg/BnkvkmvOr8nS4omF+q9EG/4oisB+ul4YHi938hwAAzE3NQB9AAAABWQAIAAAAAASyK3b1nmNCMptVEGOjwoxYLLS9fYWm/Zxilqea0jpEQVzACAAAAAADDHsGrbqlKGEpxlvfyqOJKQJjwJrzsrB7k3HG0AUJbkFbAAgAAAAAKwx3S4XfDZh4+LuI9jf7XgUh5qiefNv87JD4qvVRfPSAAMxNzYAfQAAAAVkACAAAAAAlSP9iK31GlcG9MKGbLmq+VXMslURr+As736rrVNXcsUFcwAgAAAAAAvbj0zfq9zzi8XReheKFbCB+h9IsOLgXPPpI5vrEJNZBWwAIAAAAABXvoZhaQE7ogWjeBjceVkp03N20cKYP3TA8vuNsgpfAgADMTc3AH0AAAAFZAAgAAAAAOJNORH8Bev97gVU7y6bznOxJ+E6Qoykur1QP76hG1/7BXMAIAAAAAC+C1PtOOrSZgzBAGhr+dPe/kR0JUw9GTwLVNr61xC1aAVsACAAAAAAeA/L8MQIXkamaObtMPLpoDoi5FypA5WAPtMeMrgi0eQAAzE3OAB9AAAABWQAIAAAAAAKcHzLUomavInN6upPkyWhAqYQACP/vdVCIYpiy6U6HgVzACAAAAAATsR4KItY6R2+U7Gg6sJdaEcf58gjd1OulyWovIqfxKcFbAAgAAAAAFbm10ko67ahboAejQdAV0U2uA5OhZYdb8XUFJ8OL46LAAMxNzkAfQAAAAVkACAAAAAAqTOLiMpCdR59tLZzzIPqJvbCNvz2XQL9ust0qYaehtcFcwAgAAAAAArefox/3k5xGOeiw2m6NUdzuGxmPwcu5IFcj+jMwHgHBWwAIAAAAADLZGFJ7MQd5JXMgMXjqZO5LDLxcFClcXPlnRMWRn+1oAADMTgwAH0AAAAFZAAgAAAAAIPSqSeVzSRgNVNmrPYHmUMgykCY27NbdDUNhE5kx/SgBXMAIAAAAAAhX90nNfxyXmZe/+btZ7q6xMX4PFyj0paM1ccJ/5IUUQVsACAAAAAA419oHmD2W0SYoOMwhrhrp8jf68fg9hTkaRdCuVd3CN0AAzE4MQB9AAAABWQAIAAAAACLn5DxiqAosHGXIAY96FwFKjeqrzXWf3VJIQMwx1fl4gVzACAAAAAAindvU27nveutopdvuHmzdENBbeGFtI3Qcsr07jxmvm8FbAAgAAAAAPvl9pBStQvP4OGkN5v0MghUY6djm9n7XdKKfrW0l1sMAAMxODIAfQAAAAVkACAAAAAA7i2S6rHRSPBwZEn59yxaS7HiYBOmObIkeyCcFU42kf8FcwAgAAAAAGb3RSEyBmgarkTvyLWtOLJcPwCKbCRkESG4RZjVmY4iBWwAIAAAAADB2/wo5CSHR4ANtifY6ZRXNTO5+O8qP82DfAiAeanpZwADMTgzAH0AAAAFZAAgAAAAAFz+M+H/Z94mdPW5oP51B4HWptp1rxcMWAjnlHvWJDWrBXMAIAAAAACBFEOQyL7ZHu4Cq33QvXkmKuH5ibG/Md3RaED9CtG5HwVsACAAAAAAfggtJTprQ/yZzj7y5z9KvXsdeXMWP0yUXMMJqpOwI88AAzE4NAB9AAAABWQAIAAAAAAE7c2x3Z3aM1XGfLNk/XQ9jCazNRbGhVm7H8c2NjS5ywVzACAAAAAARJ9h8fdcwA19velF3L/Wcvi2rCzewlKZ2nA0p8bT9uwFbAAgAAAAAJtWe6b4wK2Hae2dZm/OEpYQnvoZjz4Sz5IgJC2wInecAAMxODUAfQAAAAVkACAAAAAAVoRt9B9dNVvIMGN+ea5TzRzQC+lqSZ8dd/170zU5o9cFcwAgAAAAAEwM95XZin5mv2yhCI8+ugtKuvRVmNgzzIQN0yi1+9aIBWwAIAAAAAAMGBq72n00rox3uqhxSB98mkenTGCdbbUF1gXrgottzgADMTg2AH0AAAAFZAAgAAAAAKRDkjyWv/etlYT4GyoXrmBED2FgZHnhc+l9Wsl06cH2BXMAIAAAAABohlpm3K850Vndf3NmNE0hHqDlNbSR8/IvMidQ3LnIZAVsACAAAAAAW42nGHa6q2MCAaaPVwaIDfr8QLyQwjKq23onZJYsqVsAAzE4NwB9AAAABWQAIAAAAAC3DFh5oklLCNLY90bgWm68dFXz65JpAZSp1K99MBTPAQVzACAAAAAAQgZecmxEUZVHoptEQClDwAf8smI3WynQ/i+JBP0g+kQFbAAgAAAAAEUSQGVnAPISD6voD0DiBUqyWKgt2rta0tjmoe+LNt6IAAMxODgAfQAAAAVkACAAAAAAQ5WKvWSB503qeNlOI2Tpjd5blheNr6OBO8pfJfPNstcFcwAgAAAAAKwHgQLSDJ5NwLBQbY5OnblQIsVDpGV7q3RCbFLD1U4/BWwAIAAAAACQ5nED99LnpbqXZuUOUjnO2HTphEAFBjLD4OZeDEYybgADMTg5AH0AAAAFZAAgAAAAAGfhFY3RGRm5ZgWRQef1tXxHBq5Y6fXaLAR4yJhrTBplBXMAIAAAAACKEF0ApLoB6lP2UqTFsTQYNc9OdDrs/vziPGzttGVLKQVsACAAAAAArOO6FyfNRyBi0sPT5iye7M8d16MTLcwRfodZq4uCYKEAAzE5MAB9AAAABWQAIAAAAAAIM73gPcgzgotYHLeMa2zAU4mFsr7CbILUZWfnuKSwagVzACAAAAAAJCSu98uV8xv88f2BIOWzt6p+6EjQStMBdkGPUkgN79cFbAAgAAAAAMGqPGMPxXbmYbVfSa/japvUljht1zZT33TY7ZjAiuPfAAMxOTEAfQAAAAVkACAAAAAAkWmHCUsiMy1pwZTHxVPBzPTrWFBUDqHNrVqcyyt7nO8FcwAgAAAAAMv2CebFRG/br7USELR98sIdgE9OQCRBGV5JZCO+uPMgBWwAIAAAAABt7qSmn3gxJu7aswsbUiwvO+G6lXj/Xhx+J/zQyZxzLAADMTkyAH0AAAAFZAAgAAAAAGInUYv0lP/rK7McM8taEHXRefk8Q2AunrvWqdfSV7UaBXMAIAAAAACE+WPxJ3gan7iRTbIxXXx+bKVcaf8kP4JD8DcwU0aL7wVsACAAAAAAUC4eTprX4DUZn2X+UXYU6QjtiXk+u57yoOPBbPQUmDkAAzE5MwB9AAAABWQAIAAAAACmHlg2ud3cplXlTsNTpvNnY6Qm1Fce0m899COamoDjaQVzACAAAAAArtJQeJIlepBWRU2aYar7+YGYVQ7dfDc1oxgTmA8r9q0FbAAgAAAAAOk45vg5VqZHAFCO3i0Z52SZi5RADf8NXwf68T5yad/DAAMxOTQAfQAAAAVkACAAAAAApzcWSAbZWV/Rq+ylRNqqlJqNVR4fhXrz4633/MQOQgcFcwAgAAAAAN/jz/bsEleiuCl+li83EWlG6UMHA8CyaOMRKCkXkSCPBWwAIAAAAAC3Sd+Qg+uFDKpGZHbrQgokXHQ1az1aFl4YK343OB6hcQAAEmNtAAAAAAAAAAAAABBwYXlsb2FkSWQAAAAAABBmaXJzdE9wZXJhdG9yAAEAAAAA", "subType": "06" } } } }, "u": { "$set": { "encryptedDecimalNoPrecision": { "$$type": "binData" } } } } ], "encryptionInformation": { "type": 1, "schema": { "default.default": { "escCollection": "enxcol_.default.esc", "ecocCollection": "enxcol_.default.ecoc", "fields": [ { "keyId": { "$binary": { "base64": "EjRWeBI0mHYSNBI0VniQEg==", "subType": "04" } }, "path": "encryptedDecimalNoPrecision", "bsonType": "decimal", "queries": { "queryType": "rangePreview", "contention": { "$numberLong": "0" }, "sparsity": { "$numberLong": "1" } } } ] } } }, "$db": "default" } } } ], "outcome": { "collection": { "data": [ { "_id": { "$numberInt": "0" }, "encryptedDecimalNoPrecision": { "$$type": "binData" }, "__safeContent__": [ { "$binary": { "base64": "5nRutVIyq7URVOVtbE4vM01APSIajAVnsShMwjBlzkM=", "subType": "00" } }, { "$binary": { "base64": "rbf3AeBEv4wWFAKknqDxRW5cLNkFvbIs6iJjc6LShQY=", "subType": "00" } }, { "$binary": { "base64": "n+XAuFnP8Dov9TnhGFxNx0K/MnVM9WbJ7RouEu0ndO0=", "subType": "00" } }, { "$binary": { "base64": "yRXojuVdn5GQtD97qYlaCL6cOLmZ7Cvcb3wFjkLUIdM=", "subType": "00" } }, { "$binary": { "base64": "DuIkdRPITRs55I4SZmgomAHCIsDQmXRhW8+MOznkzSk=", "subType": "00" } }, { "$binary": { "base64": "SsBk+Et1lTbU+QRPx+xyJ/jMkmfG+QCvQEpip2YYrzA=", "subType": "00" } }, { "$binary": { "base64": "crCIzOd8KhHvvUlX7M1v9bhvU4pLdTc+X2SuqoKU5Ek=", "subType": "00" } }, { "$binary": { "base64": "YOWdCw4UrqnxkAaVjqmC4sKQDMVMHEpFGnlxpxdaU6E=", "subType": "00" } }, { "$binary": { "base64": "M3SShp81Ff8tQ632qKbv9MUcN6wjDaBReI0VXNu6Xh4=", "subType": "00" } }, { "$binary": { "base64": "gzHlSPxpM0hT75kQvWFzGlOxKvDoiKQZOr19V6l2zXI=", "subType": "00" } }, { "$binary": { "base64": "s3JnppOGYw9SL2Q1kMAZs948v2F5PrpXjGei/HioDWs=", "subType": "00" } }, { "$binary": { "base64": "cG6+3Gk/zEH68P/uuuwiAUVCuyJwa1LeV+t29FlPPAo=", "subType": "00" } }, { "$binary": { "base64": "dupdvR3AyJtM+g9NDKiaLVOtGca387JQp8w+V03m7Ig=", "subType": "00" } }, { "$binary": { "base64": "JqEQc5svj2jTvZ6LLA5ivE+kTb/0aRemSEmxk4G7Zrg=", "subType": "00" } }, { "$binary": { "base64": "szcXXXKnob+p3SoM4yED2R920LeJ7cVsclPMFTe4CeI=", "subType": "00" } }, { "$binary": { "base64": "o1QoGVXmuBdHwHm7aCtGMlMVKrjFdYvJXpoq6uhIAZ0=", "subType": "00" } }, { "$binary": { "base64": "Jfm5wPlqqLCJRGQIqRq2NGmpn7s0Vrih2H3YAOoI2YU=", "subType": "00" } }, { "$binary": { "base64": "zMHLb8ARbsYo8Ld05bqnGFf1Usha6EGb8QKwdSAyps0=", "subType": "00" } }, { "$binary": { "base64": "yQdtq9lh5pugL7/i0Bj/PuZUUBUIzf+7wj1rl5y736w=", "subType": "00" } }, { "$binary": { "base64": "wGWVZdO7qIuyDg/BqDgqjgoQ02h5YYgwXQB1oCin2NE=", "subType": "00" } }, { "$binary": { "base64": "by9HMLj6NTEpgztZ5HSN6GxImkXPcaFINYDzgZY33X8=", "subType": "00" } }, { "$binary": { "base64": "tWo0vbasi7bXmn/MsOx13VC1IsWtpx/nYp0uj4iMzdA=", "subType": "00" } }, { "$binary": { "base64": "tQQpndUYd5O87lOtrGjH3wl9VsOK0ray7RMasL90sBM=", "subType": "00" } }, { "$binary": { "base64": "cQjXEDCMsOpKLLf+vlTgIHA+cbSJdzqhbSX9Wvh95aA=", "subType": "00" } }, { "$binary": { "base64": "7yMpU48IxK9SzP2cx3VnTownGEwFmeFofuuFT97SuuY=", "subType": "00" } }, { "$binary": { "base64": "kSOx1kz0CmBgzKQHZlo65ZUY1DIv9A99JRm+Us2y6Ew=", "subType": "00" } }, { "$binary": { "base64": "ubQpdPBe6/xvtr+AcXdfYLSvYCR4ot0tivehkCsupb4=", "subType": "00" } }, { "$binary": { "base64": "xal+iCJ6FTefRQToyoNksc9NCZShyn04NDGi4IYrcoM=", "subType": "00" } }, { "$binary": { "base64": "d7jU4iOK50xHxlkSifcxlZFCM46TSgQzoYivxG3HNLY=", "subType": "00" } }, { "$binary": { "base64": "tJvl2nsBLBVzL3pp6sKWCL4UXeh3q/roYBJjSb74ve0=", "subType": "00" } }, { "$binary": { "base64": "OIUCaKRvIx9t1w6Hxlz1IcQTdPNCfdRNwnnTm10W+X0=", "subType": "00" } }, { "$binary": { "base64": "A9tvzsiElotOUVIB4CqfQp9mAwqvTM35YkmAR170aHA=", "subType": "00" } }, { "$binary": { "base64": "lI8gpK7hpb7c9x4RQugsxMnQay5LZJmwslZdvMx/dcE=", "subType": "00" } }, { "$binary": { "base64": "dNCzh40U0XvdKnSDi3HRQOWQftEsDVqc4uUvsVFGoq8=", "subType": "00" } }, { "$binary": { "base64": "IP+iwEBWBwVVZIdpaMu8k5+soFCz+TZkYn3drKZ9grE=", "subType": "00" } }, { "$binary": { "base64": "pnqyh6e0y5svHkJDShlN9CHV0WvMBE4QbtJpQw5ZCXc=", "subType": "00" } }, { "$binary": { "base64": "elEl42tbVDoRTLjAhZUFEtXiut4b3PVhg/1ZLZSQdtE=", "subType": "00" } }, { "$binary": { "base64": "vHuu2FxwclMHqyE6JBYbTYgbEkB0dqb/JuaxsvfwsmY=", "subType": "00" } }, { "$binary": { "base64": "xTf7NCe3Gf8QpE78HR5OknlLTKfs9J+RN9UZpH6fnso=", "subType": "00" } }, { "$binary": { "base64": "XiWSasRnJAulGR6+LCVD3mwRObXylqYWR9jvpywq12c=", "subType": "00" } }, { "$binary": { "base64": "MZMxEQ5ikx0PG1YFIExv0UnTZogsvgeOEZTpzvBDn4w=", "subType": "00" } }, { "$binary": { "base64": "yZMyMZBDrWbAhvnic7vvIYhmO9m5H2iuv0c8KNZrBzY=", "subType": "00" } }, { "$binary": { "base64": "xxM14hTPY5j0vvcK2C7YAEjzdsfUTFHozHC0hEo1bxI=", "subType": "00" } }, { "$binary": { "base64": "+01rqR1xVwkpGXcstbk1ItJqFVjH6Q8MGxEN3Cm9Y1A=", "subType": "00" } }, { "$binary": { "base64": "xOpLV0Z2VTRJ3iWtnWZcsyjXubTIkYWo31cO+HV1o1k=", "subType": "00" } }, { "$binary": { "base64": "BWUOLqgLBqc5NwxVlSV5H3KFQPXbCp7mdo+jF+8cJqY=", "subType": "00" } }, { "$binary": { "base64": "fuQb1S6xZDGlrEbK+kI23aL53PP1PVNwqICnZNt9Yzg=", "subType": "00" } }, { "$binary": { "base64": "SfscnoibFttahLdPVC4Ee+47ewGFKpDSU7M6HX19bKE=", "subType": "00" } }, { "$binary": { "base64": "rpSW2awybNVeKtat91VFxqbINoTfNhPfQAu+d73Xtf8=", "subType": "00" } }, { "$binary": { "base64": "9M/CP9ccOIIj2LLFmE0GFDO0Ban2wsNalEXfM6+h+1s=", "subType": "00" } }, { "$binary": { "base64": "WrEMG49l1ye4MhXs5ZS9tz8P6h+hDvthIg/2wW9ne1Q=", "subType": "00" } }, { "$binary": { "base64": "ImNhbfeyfH8qIEeA5ic0s3dAQBdzzTBS+CPsNih9vZ0=", "subType": "00" } }, { "$binary": { "base64": "dWP33YDSn04UKJN2ogh2Rui0iW/0q2y18OCDRVcfyoo=", "subType": "00" } }, { "$binary": { "base64": "lYv0isAtfGh6H9tdp3cp2eHU7q2J+uk7QrgcxtK3w7Y=", "subType": "00" } }, { "$binary": { "base64": "VGMoamB/+7zTOYcY/pqJc96xlv2PdW4hwsIAEIslTDQ=", "subType": "00" } }, { "$binary": { "base64": "yNeBWMF7BnD9wVwz2PgJsvWr77QiVvvWUvJF0+fqBug=", "subType": "00" } }, { "$binary": { "base64": "SfpvObJ+tJBXSvqeN7vlOfmhYign635lciYAJIjUtY8=", "subType": "00" } }, { "$binary": { "base64": "dsen4NqjzVGjpjufiTMs3+gqeD09EbnuogPgxrJECwg=", "subType": "00" } }, { "$binary": { "base64": "pxCWVM3sn19NsFEpgHbgLa+PmYlhN3mMiP0Wk8kJhYw=", "subType": "00" } }, { "$binary": { "base64": "q11KNvJszjYIB9n9HcC+N4uz11a3eRj1L3BH9scKMDQ=", "subType": "00" } }, { "$binary": { "base64": "A1PmkgcEToWh1JiVWE6mI5jUu7poxWWuCUt/cgRUUDc=", "subType": "00" } }, { "$binary": { "base64": "qJo3Hu4PJeanL7XEaWXO/n3YsodhZyd+MJOOmB9Kpd8=", "subType": "00" } }, { "$binary": { "base64": "BkBKLO8URFscfRY9Bav/1+L9mLohDgNr/MkZtGiraIs=", "subType": "00" } }, { "$binary": { "base64": "rZq5WA3Hx3xthOyHAJXK//f8pE2qbz7YKu3TIMp9GFY=", "subType": "00" } }, { "$binary": { "base64": "X07a/Lm80p5xd4RFs1dNmw+90tmPDPdGiAKVZkxd4zY=", "subType": "00" } }, { "$binary": { "base64": "6YrBn2ofIw1b5ooakrLOwF41BWrps8OO0H9WH4/rtlE=", "subType": "00" } }, { "$binary": { "base64": "0l86Ag5OszXpa78SlOUV3K9nff5iC1p0mRXtLg9M1s4=", "subType": "00" } }, { "$binary": { "base64": "Hn6yuxFHodeyu7ISlhYrbSf9pTiH4TDEvbYLWjTwFO0=", "subType": "00" } }, { "$binary": { "base64": "zdf4y2etKBuIpkEU1zMwoCkCsdisfXZCh8QPamm+drY=", "subType": "00" } }, { "$binary": { "base64": "rOQ9oMdiK5xxGH+jPzOvwVqdGGnF3+HkJXxn81s6hp4=", "subType": "00" } }, { "$binary": { "base64": "61aKKsE3+BJHHWYvs3xSIBvlRmKswmaOo5rygQJguUg=", "subType": "00" } }, { "$binary": { "base64": "KuDb/GIzqDM8wv7m7m8AECiWJbae5EKKtJRugZx7kR0=", "subType": "00" } }, { "$binary": { "base64": "Q+t8t2TmNUiCIorVr9F3AlVnX+Mpt2ZYvN+s8UGict8=", "subType": "00" } }, { "$binary": { "base64": "tJRZIpKxUgHyL83kW8cvfjkxN3z6WoNnUg+SQw+LK+k=", "subType": "00" } }, { "$binary": { "base64": "pnUsYjip8SvW0+m9mR5WWTkpK+p6uwJ6yBUAlBnFKMk=", "subType": "00" } }, { "$binary": { "base64": "PArHlz+yPRYDycAP/PgnI/AkP8Wgmfg++Vf4UG1Bf0E=", "subType": "00" } }, { "$binary": { "base64": "wnIh53Q3jeK8jEBe1n8kJLa89/H0BxO26ZU8SRIAs9Q=", "subType": "00" } }, { "$binary": { "base64": "4F8U59gzBLGhq58PEWQk2nch+R0Va7eTUoxMneReUIA=", "subType": "00" } }, { "$binary": { "base64": "ihKagIW3uT1dm22ROr/g5QaCpxZVj2+Fs/YSdM2Noco=", "subType": "00" } }, { "$binary": { "base64": "EJtUOOwjkrPUi9mavYAi+Gom9Y2DuFll7aDwo4mq0M0=", "subType": "00" } }, { "$binary": { "base64": "dIkr8dbaVRQFskAVT6B286BbcBBt1pZPEOcTZqk4ZcI=", "subType": "00" } }, { "$binary": { "base64": "aYVAcZYkH/Tieoa1XOjE/zCy5AJcVTHjS0NG2QB7muA=", "subType": "00" } }, { "$binary": { "base64": "sBidL6y8TenseetpioIAAtn0lK/7C8MoW4JXpVYi3z8=", "subType": "00" } }, { "$binary": { "base64": "0Dd2klU/t4R86c2WJcJDAd57k/N7OjvYSO5Vf8KH8sw=", "subType": "00" } }, { "$binary": { "base64": "I3jZ92WEVmZmgaIkLbuWhBxl7EM6bEjiEttgBJunArA=", "subType": "00" } }, { "$binary": { "base64": "aGHoQMlgJoGvArjfIbc3nnkoc8SWBxcrN7hSmjMRzos=", "subType": "00" } }, { "$binary": { "base64": "bpiWPnF/KVBQr5F6MEwc5ZZayzIRvQOLDAm4ntwOi8g=", "subType": "00" } }, { "$binary": { "base64": "tI7QVKbE6avWgDD9h4QKyFlnTxFCwd2iLySKakxNR/I=", "subType": "00" } }, { "$binary": { "base64": "XGsge0CnoaXgE3rcpKm8AEeku5QVfokS3kcI+JKV1lk=", "subType": "00" } }, { "$binary": { "base64": "JQxlryW2Q5WOwfrjAnaZxDvC83Dg6sjRVP5zegf2WiM=", "subType": "00" } }, { "$binary": { "base64": "YFuHKJOfoqp1iGVxoFjx7bLYgVdsN4GuUFxEgO9HJ5s=", "subType": "00" } }, { "$binary": { "base64": "Z6vUdiCR18ylKomf08uxcQHeRtmyav7/Ecvzz4av3k4=", "subType": "00" } }, { "$binary": { "base64": "SPGo1Ib5AiP/tSllL7Z5PAypvnKdwJLzt8imfIMSEJQ=", "subType": "00" } }, { "$binary": { "base64": "m94Nh6PFFQFLIib9Cu5LAKavhXnagSHG6F5EF8lD96I=", "subType": "00" } }, { "$binary": { "base64": "pfEkQI98mB+gm1+JbmVurPAODMFPJ4E8DnqfVyUWbSo=", "subType": "00" } }, { "$binary": { "base64": "DNj3OVRLbr43s0vd+rgWghOL3FqeO/60npdojC8Ry/M=", "subType": "00" } }, { "$binary": { "base64": "kAYIQrjHVu49W8FTxyxJeiLVRWWjC9fPcBn+Hx1F+Ss=", "subType": "00" } }, { "$binary": { "base64": "aCSO7UVOpoQvu/iridarxkxV1SVxU1i9HVSYXUAeXk4=", "subType": "00" } }, { "$binary": { "base64": "Gh6hTP/yj1IKlXQ+Q69KTfMlGZjEcXoRLGbQHNFo/1s=", "subType": "00" } }, { "$binary": { "base64": "/gDgIFQ4tAlJk3GN48IS5Qa5IPmErwGk8CHxAbp6gs0=", "subType": "00" } }, { "$binary": { "base64": "PICyimwPjxpusyKxNssOOwUotAUbygpyEtORsVGXT8g=", "subType": "00" } }, { "$binary": { "base64": "4lu+cBHyAUvuxC6JUNyHLzHsCogGSWFFnUCkDwfQdgI=", "subType": "00" } }, { "$binary": { "base64": "pSndkmoNUJwXjgkbkgOrT5f9nSvuoMEZOkwAN9ElRaE=", "subType": "00" } }, { "$binary": { "base64": "tyW+D4i26QihNM5MuBM+wnt5AdWGSJaJ4X5ydc9iWTU=", "subType": "00" } }, { "$binary": { "base64": "9Syjr8RoxUgPKr+O5rsCu07AvcebA4P8IVKyS1NVLWc=", "subType": "00" } }, { "$binary": { "base64": "67tPfDYnK2tmrioI51fOBG0ygajcV0pLo5+Zm/rEW7U=", "subType": "00" } }, { "$binary": { "base64": "y0EiPRxYTuS1eVTIaPQUQBBxwkyxNckbePvKgChwd0M=", "subType": "00" } }, { "$binary": { "base64": "NWd+2veAaeXQgR3vCvzlI4R1WW67D5YsVLdoXfdb8qg=", "subType": "00" } }, { "$binary": { "base64": "PY5RQqKQsL2GqBBSPNOEVpojNFRX/NijCghIpxD6CZk=", "subType": "00" } }, { "$binary": { "base64": "lcvwTyEjFlssCJtdjRpdN6oY+C7bxZY+WA+QAqzj9zg=", "subType": "00" } }, { "$binary": { "base64": "CWE7XRNylvTwO/9Fv56dNqUaQWMmESNS/GNIwgBaEI0=", "subType": "00" } }, { "$binary": { "base64": "ijwlrUeS8nRYqK1F8kiCYF0mNDolEZS+/lJO1Lg93C8=", "subType": "00" } }, { "$binary": { "base64": "8KzV+qYGYuIjoNj8eEpnTuHrMYuhzphl80rS6wrODuU=", "subType": "00" } }, { "$binary": { "base64": "wDyTLjSEFF895hSQsHvmoEQVS6KIkZOtq1c9dVogm9I=", "subType": "00" } }, { "$binary": { "base64": "SGrtPuMYCjUrfKF0Pq/thdaQzmGBMUvlwN3ORIu9tHU=", "subType": "00" } }, { "$binary": { "base64": "KySHON3hIoUk4xWcwTqk6IL0kgjzjxgMBObVIkCGvk4=", "subType": "00" } }, { "$binary": { "base64": "hBIdS9j0XJPeT4ot73ngELkpUoSixvRBvdOL9z48jY8=", "subType": "00" } }, { "$binary": { "base64": "Tx6um0q9HjS5ZvlFhvukpI6ORnyrXMWVW1OoxvgqII0=", "subType": "00" } }, { "$binary": { "base64": "zFKlyfX5H81+d4A4J3FKn4T5JfG+OWtR06ddyX4Mxas=", "subType": "00" } }, { "$binary": { "base64": "cGgCDuPV7MeMMYEDpgOupqyNP4BQ4H7rBnd2QygumgM=", "subType": "00" } }, { "$binary": { "base64": "IPaUoy98v11EoglTpJ4kBlEawoZ8y7BPwzjLYBpkvHQ=", "subType": "00" } }, { "$binary": { "base64": "Pfo4Am6tOWAyZNn8G9W5HWWGC3ZWmX0igI/RRB870Ro=", "subType": "00" } }, { "$binary": { "base64": "fnTSjd7bC1Udoq6iM7UDnHAC/lsIXSHp/Gy332qw+/I=", "subType": "00" } }, { "$binary": { "base64": "fApBgVRrTDyEumkeWs5p3ag9KB48SbU4Si0dl7Ns9rc=", "subType": "00" } }, { "$binary": { "base64": "QxudfBItgoCnUj5NXVnSmWH3HK76YtKkMmzn4lyyUYY=", "subType": "00" } }, { "$binary": { "base64": "sSOvwhKa29Wq94bZ5jGIiJQGbG1uBrKSBfOYBz/oZeI=", "subType": "00" } }, { "$binary": { "base64": "FdaMgwwJ0NKsqmPZLC5oE+/0D74Dfpvig3LaI5yW5Fs=", "subType": "00" } }, { "$binary": { "base64": "sRWBy12IERN43BSZIrnBfC9+zFBUdvjTlkqIH81NGt4=", "subType": "00" } }, { "$binary": { "base64": "/4tIRpxKhoOwnXAiFn1Z7Xmric4USOIfKvTYQXk3QTc=", "subType": "00" } } ] }, { "_id": { "$numberInt": "1" }, "encryptedDecimalNoPrecision": { "$$type": "binData" }, "__safeContent__": [ { "$binary": { "base64": "DLCAJs+W2PL2DV5YChCL6dYrQNr+j4p3L7xhVaub4ic=", "subType": "00" } }, { "$binary": { "base64": "Mr/laWHUijZT5VT3x2a7crb7wgd/UXOGz8jr8BVqBpM=", "subType": "00" } }, { "$binary": { "base64": "wXVD/HSbBljko0jJcaxJ1nrzs2+pchLQqYR3vywS8SU=", "subType": "00" } }, { "$binary": { "base64": "VDCpBYsJIxTfcI6Zgf7FTmKMxUffQv+Ys8zt5dlK76I=", "subType": "00" } }, { "$binary": { "base64": "zYDslUwOUVNwTYkETfjceH/PU3bac9X3UuQyYJ19qK0=", "subType": "00" } }, { "$binary": { "base64": "rAOmHSz18Jx107xpbv9fYcPOmh/KPAqge0PAtuhIRnc=", "subType": "00" } }, { "$binary": { "base64": "BFOB1OGVUen7VsOuS0g8Ti7oDsTt2Yj/k/7ta8YAdGM=", "subType": "00" } }, { "$binary": { "base64": "2fckE5SPs0GU+akDkUEM6mm0EtcV3WDE/sQsnTtodlk=", "subType": "00" } }, { "$binary": { "base64": "mi9+aNjuwIvaMpSHENvKzKRAmX9cYguo2mXLvOoftHQ=", "subType": "00" } }, { "$binary": { "base64": "K6TWn4VcWWkz/gkUkLmbtwkG7SNeABICmLDnoYJFlLU=", "subType": "00" } }, { "$binary": { "base64": "Z+2/cEtGU0Fq7QJFNGA/0y4aWAsw0ncG6X0LYRqwS3c=", "subType": "00" } }, { "$binary": { "base64": "rrSIf+lgcNZFbbUkS9BmE045jRWBpcBJXHzfMVEFuzE=", "subType": "00" } }, { "$binary": { "base64": "KlHL3Kyje1/LMIfgbCqw1SolxffJvvgsYBV5y77wxuA=", "subType": "00" } }, { "$binary": { "base64": "hzJ1YBoETmYeCh352dBmG8d8Wse/bUcqojTWpWQlgsc=", "subType": "00" } }, { "$binary": { "base64": "lSdcllDXx8MA+s0GULjDA1lQkcV0L8/aHtZ6dM2pZ2c=", "subType": "00" } }, { "$binary": { "base64": "HGr7JLTTA7ksAnlmjSIwwdBVvgr3fv46/FTdiCPYpos=", "subType": "00" } }, { "$binary": { "base64": "mMr25v1VwOEVZ8xaNUTHJCcsYqV+kwK6RzGYilxPtJ4=", "subType": "00" } }, { "$binary": { "base64": "129hJbziPJzNo0IoTU3bECdge0FtaPW8dm4dyNVNwYU=", "subType": "00" } }, { "$binary": { "base64": "doiLJ96qoo+v7NqIAZLq6BI5axV8Id8gT5vyJ1ZZ0PM=", "subType": "00" } }, { "$binary": { "base64": "cW/Lcul3xYmfyvI/0x/+ybN78aQmBK1XIGs1EEU09N8=", "subType": "00" } }, { "$binary": { "base64": "1aVIwzu9N5EJV9yEES+/g6hOTH7cA2NTcLIc59cu0wU=", "subType": "00" } }, { "$binary": { "base64": "kw5tyl7Ew0r1wFyrN1mB9FiVW2hK2BxxxUuJDNWjyjQ=", "subType": "00" } }, { "$binary": { "base64": "ADAY2YBrm6RJBDY/eLLcfNxmSJku+mefz74gH66oyco=", "subType": "00" } }, { "$binary": { "base64": "8gkqB1LojzPrstpFG7RHYmWxXpIlPDTqWnNsXH7XDRU=", "subType": "00" } }, { "$binary": { "base64": "TESfVQMDQjfTZmHmUeYUE2XrokJ6CcrsKx/GmypGjOw=", "subType": "00" } }, { "$binary": { "base64": "qFM+HFVQ539S0Ouynd1fBHoemFxtU9PRxE5+Dq7Ljy4=", "subType": "00" } }, { "$binary": { "base64": "jPiFgUZteSmOg4wf3bsEKCZzcnxmMoILsgp/GaZD+dM=", "subType": "00" } }, { "$binary": { "base64": "YaWUgJhYgPNN7TkFK16H8SsQS226JguaVhOIQxZwQNQ=", "subType": "00" } }, { "$binary": { "base64": "x90/Qk3AgyaFsvWf2KUCu5XF3j76WFSjt/GrnG01060=", "subType": "00" } }, { "$binary": { "base64": "ZGWybWL/xlEdMYRFCZDUoz10sywTf7U/7wufsb78lH0=", "subType": "00" } }, { "$binary": { "base64": "8l4ganN66jIcdxfHAdYLaym/mdzUUQ8TViw3MDRySPc=", "subType": "00" } }, { "$binary": { "base64": "c8p5XEGTqxqvRGVlR+nkxw9uUdoqDqTB0jlYQ361qMA=", "subType": "00" } }, { "$binary": { "base64": "1ZGFLlpQBcU3zIUg8MmgWwFKVz/SaA7eSYFrfe3Hb70=", "subType": "00" } }, { "$binary": { "base64": "34529174M77rHr3Ftn9r8jU4a5ztYtyVhMn1wryZSkU=", "subType": "00" } }, { "$binary": { "base64": "YkQ4pxFWzc49MS0vZM6S8mNo4wAwo21rePBeF3C+9mI=", "subType": "00" } }, { "$binary": { "base64": "MhOf4mYY00KKVhptOcXf0bXB7WfuuM801MRJg4vXPgc=", "subType": "00" } }, { "$binary": { "base64": "7pbbD8ihNIYIBJ3tAUPGzHpFPpIeCTAk5L88qCB0/9w=", "subType": "00" } }, { "$binary": { "base64": "C9Q5PoNJTQo6pmNzXEEXUEqH22//UUWY1gqILcIywec=", "subType": "00" } }, { "$binary": { "base64": "AqGVk1QjDNDLYWGRBX/nv9QdGR2SEgXZEhF0EWBAiSE=", "subType": "00" } }, { "$binary": { "base64": "/sGI3VCbJUKATULJmhTayPOeVW+5MjWSvVCqS77sRbU=", "subType": "00" } }, { "$binary": { "base64": "yOtbL0ih7gsuoxVtRrACMz+4N5uo7jIR7zzmtih2Beo=", "subType": "00" } }, { "$binary": { "base64": "uA6dkb2Iyg9Su8UNDvZzkPx33kPZtWr/CCuEY+XgzUM=", "subType": "00" } }, { "$binary": { "base64": "1DoSFPdHIplqZk+DyWAmEPckWwXw/GdB25NLmzeEZhk=", "subType": "00" } }, { "$binary": { "base64": "OfDVS0T3ZuIXI/LNbTp6C9UbPIWLKiMy6Wx+9tqNl+g=", "subType": "00" } }, { "$binary": { "base64": "3PZjHXbmG6GtPz+iapKtQ3yY4PoFFgjIy+fV2xQv1YU=", "subType": "00" } }, { "$binary": { "base64": "kaoLN0BoBWsmqE7kKkJQejATmLShd8qffcAmlhsxsGY=", "subType": "00" } }, { "$binary": { "base64": "vpiw9KgQdegGmp7IJnSGX2miujRLU0xzs0ITTqbPW7c=", "subType": "00" } }, { "$binary": { "base64": "NuXFf7xGUefYjIUTuMxNUTCfVHrF8oL0AT7dPv5Plk4=", "subType": "00" } }, { "$binary": { "base64": "8Tz53LxtfEBJ9eR+d2690kwNsqPV6XyKo2PlqZCbUrc=", "subType": "00" } }, { "$binary": { "base64": "e6zsOmHSyV8tyQtSX6BSwui6wK9v1xG3giY/IILJQ2w=", "subType": "00" } }, { "$binary": { "base64": "2fedFMCxa2DzmIpfbDKGXhQg0PPwbUv6vIWdwwlvhms=", "subType": "00" } }, { "$binary": { "base64": "yEJKMFnWXTC8tJUfzCInzQRByNEPjHxpw4L4m8No91Q=", "subType": "00" } }, { "$binary": { "base64": "YbFuWwOiFuQyOzIJXDbOkCWC2DyrG+248TBuVCa1pXU=", "subType": "00" } }, { "$binary": { "base64": "w7IkwGdrguwDrar5+w0Z3va5wXyZ4VXJkDMISyRjPGo=", "subType": "00" } }, { "$binary": { "base64": "YmJUoILTRJPhyIyWyXJTsQ6KSZHHbEpwPVup6Ldm/Ko=", "subType": "00" } }, { "$binary": { "base64": "FvMjcwVZJmfh6FP/yBg2wgskK+KHD8YVUY6WtrE8xbg=", "subType": "00" } }, { "$binary": { "base64": "h4HCtD4HyYz0nci49IVAa10Z4NJD/FHnRMV4sRX6qro=", "subType": "00" } }, { "$binary": { "base64": "nC7BpXCmym+a0Is2kReM9cYN2M1Eh5rVo8fjms14Oiw=", "subType": "00" } }, { "$binary": { "base64": "1qtVWaeVo649ZZZtN8gXbwLgMWGLhz8beODbvru0I7Q=", "subType": "00" } }, { "$binary": { "base64": "Ej+mC0QFyMNIiSjR939S+iGBm7dm+1xObu5IcF/OpbU=", "subType": "00" } }, { "$binary": { "base64": "UQ8LbUG3cMegbr9yKfKanAPQE1EfPkFciVDrNqZ5GHY=", "subType": "00" } }, { "$binary": { "base64": "4iI3mXIDjnX+ralk1HhJY43mZx2uTJM7hsv9MQzTX7E=", "subType": "00" } }, { "$binary": { "base64": "0WQCcs3rvsasgohERHHCaBM4Iy6yomS4qJ5To3/yYiw=", "subType": "00" } }, { "$binary": { "base64": "qDCTVPoue1/DOAGNAlUstdA9Sid8MgEY4e5EzHcVHRk=", "subType": "00" } }, { "$binary": { "base64": "9F9Mus0UnlzHb8E8ImxgXtz6SU98YXD0JqswOKw/Bzs=", "subType": "00" } }, { "$binary": { "base64": "pctHpHKVBBcsahQ6TNh6/1V1ZrqOtKSAPtATV6BJqh0=", "subType": "00" } }, { "$binary": { "base64": "vfR3C/4cPkVdxtNaqtF/v635ONbhTf5WbwJM6s4EXNE=", "subType": "00" } }, { "$binary": { "base64": "ejP43xUBIex6szDcqExAFpx1IE/Ksi5ywJ84GKDFRrs=", "subType": "00" } }, { "$binary": { "base64": "jbP4AWYd3S2f3ejmMG7dS5IbrFol48UUoT+ve3JLN6U=", "subType": "00" } }, { "$binary": { "base64": "CiDifI7958sUjNqJUBQULeyF7x0Up3loPWvYKw9uAuw=", "subType": "00" } }, { "$binary": { "base64": "e2dQFsiHqd2BFHNhlSxocjd+cPs4wkcUW/CnCz4KNuM=", "subType": "00" } }, { "$binary": { "base64": "PJFckVmzBipqaEqsuP2mkjhJE4qhw36NhfQ9DcOHyEU=", "subType": "00" } }, { "$binary": { "base64": "S3MeuJhET/B8VcfZYDR9fvX0nscDj416jdDekhmK11s=", "subType": "00" } }, { "$binary": { "base64": "CGVHZRXpuNtQviDB2Kj03Q8uvs4w3RwTgV847R7GwPw=", "subType": "00" } }, { "$binary": { "base64": "yUGgmgyLrxbEpDVy89XN3c2cmFpZXWWmuJ/35zVZ+Jw=", "subType": "00" } }, { "$binary": { "base64": "inb6Q97mL1a9onfNTT8v9wsoi/fz7KXKq3p8j90AU9c=", "subType": "00" } }, { "$binary": { "base64": "CCyYx/4npq9xGO1lsCo8ZJhFO9/tN7DB+/DTE778rYg=", "subType": "00" } }, { "$binary": { "base64": "LNnYw4fwbiAZu0kBdAHPEm/OFnreS+oArdB5O/l/I98=", "subType": "00" } }, { "$binary": { "base64": "P006SxmUS/RjiQJVYPdMFnNo3827GIEmSzagggkg05Q=", "subType": "00" } }, { "$binary": { "base64": "oyvwY+WsnYV6UHuPki1o0ILJ2jN4uyXf9yaUNtZJyBA=", "subType": "00" } }, { "$binary": { "base64": "36Lk3RHWh1wmtCWC/Yj6jNIo17U5y6SofAgQjzjVxD8=", "subType": "00" } }, { "$binary": { "base64": "vOOo8FqeHnuO9mqOYjIb4vgwIwVyXZ5Y+bY5d9tGFUM=", "subType": "00" } }, { "$binary": { "base64": "bJiDJjwQRNxqxlGjRm5lLziFhcfTDCnQ/qU1V85qcRg=", "subType": "00" } }, { "$binary": { "base64": "2Qgrm1n0wUELAQnpkEiIHB856yv76q8jLbpiucetcm0=", "subType": "00" } }, { "$binary": { "base64": "5ciPOYxTK0WDwwYyfs7yiVymwtYQXDELLxmM4JLl4/o=", "subType": "00" } }, { "$binary": { "base64": "31dC2WUSIOKQc4jwT6PikfeYTwi80mTlh7P31T5KNQU=", "subType": "00" } }, { "$binary": { "base64": "YluTV2Mu53EGCKLcWfHZb0BM/IPW2xJdG3vYlDMEsM4=", "subType": "00" } }, { "$binary": { "base64": "dh/8lGo2Ek6KukSwutH6Q35iy8TgV0FN0SJqe0ZVHN8=", "subType": "00" } }, { "$binary": { "base64": "EVw6HpIs3BKen2qY2gz4y5dw1JpXilfh07msZfQqJpc=", "subType": "00" } }, { "$binary": { "base64": "FYolLla9L8EZMROEdWetozroU40Dnmwwx2jIMrr7c1A=", "subType": "00" } }, { "$binary": { "base64": "8M6k4QIutSIj6CM41vvkQtuFsaGrjoR9SZJVSLbfGKQ=", "subType": "00" } }, { "$binary": { "base64": "9LM0VoddDNHway442MqY+Z7vohB2UHau/cddshhzf40=", "subType": "00" } }, { "$binary": { "base64": "66i8Ytco4Yq/FMl6pIRZazz3CZlu8fO2OI6Pne0pvHU=", "subType": "00" } }, { "$binary": { "base64": "2a/HgX+MjZxjXtSvHgF1yEpHMJBkl8Caee8XrJtn0WM=", "subType": "00" } }, { "$binary": { "base64": "frhBM662c4ZVG7mWP8K/HhRjd01lydW/cPcHnDjifqc=", "subType": "00" } }, { "$binary": { "base64": "6k1T7Q1t668PBqv6fwpVnT1HWh7Am5LtbKvwPJKcpGU=", "subType": "00" } }, { "$binary": { "base64": "UlJ5Edfusp8S/Pyhw6KTglIejmbr1HO0zUeHn/qFETA=", "subType": "00" } }, { "$binary": { "base64": "jsxsB+1ECB3assUdoC333do9tYH+LglHmVSJHy4N8Hg=", "subType": "00" } }, { "$binary": { "base64": "2nzIQxGYF7j3bGsIesECEOqhObKs/9ywknPHeJ3yges=", "subType": "00" } }, { "$binary": { "base64": "xJYKtuWrX90JrJVoYtnwP7Ce59XQGFYoalxpNfBXEH0=", "subType": "00" } }, { "$binary": { "base64": "NLI5lriBTleGCELcHBtNnmnvwSRkHHaLOX4cKboMgTw=", "subType": "00" } }, { "$binary": { "base64": "hUOQV0RmE5aJdJww1AR9rirJG4zOYPo+6cCkgn/BGvQ=", "subType": "00" } }, { "$binary": { "base64": "h4G2Of76AgxcUziBwCyH+ayMOpdBWzg4yFrTfehSC2c=", "subType": "00" } }, { "$binary": { "base64": "VuamM75RzGfQpj2/Y1jSVuQLrhy6OAwlZxjuQLB/9Ss=", "subType": "00" } }, { "$binary": { "base64": "kn9+hLq7hvw02xr9vrplOCDXKBTuFhfbX7d5v/l85Pg=", "subType": "00" } }, { "$binary": { "base64": "fAiGqKyLZpGngBYFbtYUYt8LUrJ49vYafiboifTDjxs=", "subType": "00" } }, { "$binary": { "base64": "BxRILymgfVJCczqjUIWXcfrfSgrrYkxTM5VTg0HkZLY=", "subType": "00" } }, { "$binary": { "base64": "CrFY/PzfPU2zsFkGLu/dI6mEeizZzCR+uYgjZBAHro0=", "subType": "00" } }, { "$binary": { "base64": "AEbrIuwvXLTtYgMjOqnGQ8y8axUn5Ukrn7UZRSyfQVw=", "subType": "00" } }, { "$binary": { "base64": "ouWeVH3PEFg+dKWlXc6BmqirJOaVWjJbMzZbCsce4dA=", "subType": "00" } }, { "$binary": { "base64": "+hd6xFB+EG+kVP7WH4uMd1CLaWMnt5xJRaY/Guuga9Q=", "subType": "00" } }, { "$binary": { "base64": "zmpGalfAOL3gmcUMJYcLYIRT/2VDO/1Dw4KdYZoNcng=", "subType": "00" } }, { "$binary": { "base64": "2PbHAoM/46J2UIZ/vyksKzmVVfxA7YUyIxWeL/N/vBk=", "subType": "00" } }, { "$binary": { "base64": "7fD9x+zk5MVFesb59Klqiwwmve7P5ON/5COURXj5smE=", "subType": "00" } }, { "$binary": { "base64": "tlrNQ4jaq051iaWonuv1sSrYhKkL1LtNZuHsvATha3s=", "subType": "00" } }, { "$binary": { "base64": "fBodm28iClNpvlRyVq0dOdXQ08S7/N3aDwid+PdWvRo=", "subType": "00" } }, { "$binary": { "base64": "O+/nnRqT3Zv7yMMGug8GhKHaWy6u7BfRGtZoj0sdN1c=", "subType": "00" } }, { "$binary": { "base64": "5AZZ/RTMY4Photnm/cpXZr/HnFRi3eljacMsipkJLHA=", "subType": "00" } }, { "$binary": { "base64": "oFVyo/kgoMxBIk2VE52ySSimeyU+Gr0EfCwapXnTpKA=", "subType": "00" } }, { "$binary": { "base64": "Z8v59DfcnviA0mzvnUk+URVO0UuqAWvtarEgJva/n1c=", "subType": "00" } }, { "$binary": { "base64": "P64GOntZ+zBJEHkigoh9FSxSO+rJTqR20z5aiGQ9an4=", "subType": "00" } }, { "$binary": { "base64": "xMbSuDPfWuO/Dm7wuVl06GnzG9uzTlJJX9vFy7boGlY=", "subType": "00" } }, { "$binary": { "base64": "kXPB19mRClxdH2UsHwlttS6lLU2uHvzuZgZz7kC45jU=", "subType": "00" } }, { "$binary": { "base64": "NDVjVYXAw4k0w4tFzvs7QDq39aaU3HQor4I2XMKKnCk=", "subType": "00" } }, { "$binary": { "base64": "uKw/+ErVfpTO1dGUfd3T/eWfZW3nUxXCdBGdjvHtZ88=", "subType": "00" } }, { "$binary": { "base64": "av0uxEzWkizYWm0QUM/MN1hLibnxPvCWJKwjOV4yVQY=", "subType": "00" } }, { "$binary": { "base64": "ERwUC47dvgOBzIsEESMIioLYbFOxOe8PtJTnmDkKuHM=", "subType": "00" } }, { "$binary": { "base64": "2gseKlG5Le12fS/vj4eaED4lturF16kAgJ1TpW3HxEE=", "subType": "00" } }, { "$binary": { "base64": "7Cvg0Y3j/5i2F1TeXxlMmU7xwif5dCmwkZAOrVC5K2Y=", "subType": "00" } } ] } ] } } } ] } fle2v2-Range-DecimalPrecision-Aggregate.json000066400000000000000000000505371462766011000372560ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/client-side-encryption/spec/legacy{ "runOn": [ { "minServerVersion": "7.0.0", "topology": [ "replicaset", "sharded", "load-balanced" ] } ], "database_name": "default", "collection_name": "default", "data": [], "encrypted_fields": { "fields": [ { "keyId": { "$binary": { "base64": "EjRWeBI0mHYSNBI0VniQEg==", "subType": "04" } }, "path": "encryptedDecimalPrecision", "bsonType": "decimal", "queries": { "queryType": "rangePreview", "contention": { "$numberLong": "0" }, "sparsity": { "$numberLong": "1" }, "min": { "$numberDecimal": "0.0" }, "max": { "$numberDecimal": "200.0" }, "precision": { "$numberInt": "2" } } } ] }, "key_vault_data": [ { "_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" } } ], "tests": [ { "description": "FLE2 Range DecimalPrecision. Aggregate.", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "local": { "key": { "$binary": { "base64": "Mng0NCt4ZHVUYUJCa1kxNkVyNUR1QURhZ2h2UzR2d2RrZzh0cFBwM3R6NmdWMDFBMUN3YkQ5aXRRMkhGRGdQV09wOGVNYUMxT2k3NjZKelhaQmRCZGJkTXVyZG9uSjFk", "subType": "00" } } } } } }, "operations": [ { "name": "insertOne", "arguments": { "document": { "_id": 0, "encryptedDecimalPrecision": { "$numberDecimal": "0" } } } }, { "name": "insertOne", "arguments": { "document": { "_id": 1, "encryptedDecimalPrecision": { "$numberDecimal": "1" } } } }, { "name": "aggregate", "arguments": { "pipeline": [ { "$match": { "encryptedDecimalPrecision": { "$gt": { "$numberDecimal": "0" } } } } ] }, "result": [ { "_id": 1, "encryptedDecimalPrecision": { "$numberDecimal": "1" } } ] } ], "expectations": [ { "command_started_event": { "command": { "listCollections": 1, "filter": { "name": "default" } }, "command_name": "listCollections" } }, { "command_started_event": { "command": { "find": "datakeys", "filter": { "$or": [ { "_id": { "$in": [ { "$binary": { "base64": "EjRWeBI0mHYSNBI0VniQEg==", "subType": "04" } } ] } }, { "keyAltNames": { "$in": [] } } ] }, "$db": "keyvault", "readConcern": { "level": "majority" } }, "command_name": "find" } }, { "command_started_event": { "command": { "insert": "default", "documents": [ { "_id": 0, "encryptedDecimalPrecision": { "$$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": "encryptedDecimalPrecision", "bsonType": "decimal", "queries": { "queryType": "rangePreview", "contention": { "$numberLong": "0" }, "sparsity": { "$numberLong": "1" }, "min": { "$numberDecimal": "0.0" }, "max": { "$numberDecimal": "200.0" }, "precision": { "$numberInt": "2" } } } ] } } } }, "command_name": "insert" } }, { "command_started_event": { "command": { "insert": "default", "documents": [ { "_id": 1, "encryptedDecimalPrecision": { "$$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": "encryptedDecimalPrecision", "bsonType": "decimal", "queries": { "queryType": "rangePreview", "contention": { "$numberLong": "0" }, "sparsity": { "$numberLong": "1" }, "min": { "$numberDecimal": "0.0" }, "max": { "$numberDecimal": "200.0" }, "precision": { "$numberInt": "2" } } } ] } } } }, "command_name": "insert" } }, { "command_started_event": { "command": { "aggregate": "default", "pipeline": [ { "$match": { "encryptedDecimalPrecision": { "$gt": { "$binary": { "base64": "DdIJAAADcGF5bG9hZACiCQAABGcAjgkAAAMwAH0AAAAFZAAgAAAAAHdJ2Vnb4MMzqVYVssjSdDy8XU4GVzMTfGifGETgQ2mYBXMAIAAAAAD7cFfKJGIXo6PjyeX2ria02CckW7dWFDoY/3FyBdm1NQVsACAAAAAAhEPSNv4M023A3hzNFuy83+hIKuZ2mKRY954N++aEOBUAAzEAfQAAAAVkACAAAAAAlmvfDrZoydUet4eCVMq7z6a58Ea+1HLJOWxN5lNcrWEFcwAgAAAAAEBo5AWZyC41b9ayjWNQSL4iYEAIwR/JG+ssN8bdoK9RBWwAIAAAAACEndE0SLxFSElOrNnqeX0EPmgDio3udZjVREy4JLS3sQADMgB9AAAABWQAIAAAAABbiLaoxAA6rinMJw1hC8ZUiq6UU1AQaPFn/py/Y06WuQVzACAAAAAAhtDasFkvYE7SCNu1je/hxdE9TJtAvvH3NtdEbKzNbCUFbAAgAAAAAIGepU1RSCF8sWODHEpKglsoqw3VBBH4a/URGxgGzbq2AAMzAH0AAAAFZAAgAAAAALORWwSr+tYNxcil2KIGSbNhTHvcPbdj+rLVQNx21S/KBXMAIAAAAAD6diZBkPEJ1cQy06LAxdbNK8Nlxbb44fH4Wk3Y3260nQVsACAAAAAA1eYAZBFHlDiaDAljWi8blGQ2nvvZa5AO5doeo0SFZsgAAzQAfQAAAAVkACAAAAAAG5XMK96PjClNlUvg82j4pMY1YxsznZfj4uNweD394FoFcwAgAAAAAKHgQLdGJHkrfFg9nB93Ac+3VgBw6aU44MTkKIQ91dZoBWwAIAAAAAAPxXmi+SDJ+40A0KdwfRczexlZQrHjIA+D3oUB0EY9tAADNQB9AAAABWQAIAAAAAA6M++b9I0YFemmWBAWAE3glu2Ah3Ta1FBxAQEIWS0toAVzACAAAAAANXYTqPf1Y6X3Ns6YQIX0C3FKCyWUo+Kk+fNcQvc0WSoFbAAgAAAAAA+uJUw1ICYgyeygSRe206VTWVtUnhdci3iHbyP5YtEVAAM2AH0AAAAFZAAgAAAAAKl8bV1riH/uyJ+X0HHd3+18k2cJl2dQFXCdoagutFcaBXMAIAAAAABm8F2Ew9f0VOABdcF+lP0Bi+zWvEUPniWgrxPq/Sx3uwVsACAAAAAAJfFErjZ6BPhsw5LjJLqNtKDLJ4zV0eIZppQpd9b0wZoAAzcAfQAAAAVkACAAAAAAsYZD8JEP6kYsPncFnNZwJxhu4YtUTKPNcjHtv67H+rYFcwAgAAAAAI4LqZcRkvbs/2F62Flu0pixNcor4WmBD0DHGaf039wLBWwAIAAAAAD4wUR3xd9lKltcqqo8LYvdMQWzCRobkV/ppKB/yn5dUgADOAB9AAAABWQAIAAAAAC0vdAi+dmoIXvZ5LqUqvyKV9/tHqSI2SWiSJO5pTnA2wVzACAAAAAAS2qvf9fvfVUH5WtsVxjxmskpGjYTQV34LwvQQw1y9wIFbAAgAAAAAE0+FKuK7HxbypvCeEJzMTcjOWE0ScYOlTBMUNlIv55hAAM5AH0AAAAFZAAgAAAAAH31lb/srBcrOXkzddCwAnclsR5/3QijEVgECs2JjOWBBXMAIAAAAABg7+prDT73YcCvLE5QbuIrqGcjLc5pQD2Miq0d29yrxgVsACAAAAAAetRiPwDSFWBzpWSWkOKWM6fKStRJ8SyObnpc79ux8p0AAzEwAH0AAAAFZAAgAAAAAOK8brUuc2onBNDRtfYMR736dHj4dQqXod8JG7tAMTsDBXMAIAAAAAAW6SrGAL6Bx0s7ZlsYULFfOAiYIGhEWu6md3r+Rk40awVsACAAAAAAIHYXP8RLcCboUmHN3+OlnEw1DxaLSnbTB9PdF228fFAAAzExAH0AAAAFZAAgAAAAAFdthRhe2Q8CvxGIhjTJZv0Lk97GkHciTPxZ/mckLoNaBXMAIAAAAAAqOxsAr23LOVB0DIHbPf9UDJJRFXY2YoKbjhRqw5psbQVsACAAAAAA0G2GD8ZQjDBntjLpW4rqwKRS6HiUjL03g1N6chANozcAAzEyAH0AAAAFZAAgAAAAAMWymwwbvIeMqmnKWWifUqoCxOsdpnonM2qdLPyjqJO/BXMAIAAAAAB6IDmmpUhBD2zpRj8/y/kmOSXcjuIU14sNh6GKSsg2uwVsACAAAAAAWMFPNOk3EMSQDS9JGPSMIQP0oNGVugxXKKUrIPPlhHgAAzEzAH0AAAAFZAAgAAAAAPcLmtq+V1e+MRlZ7NHq1+mrRVBQje5zj685ZvdsfKvSBXMAIAAAAABdHz/3w2k5km97QN9m7oLFYJaVJneNlMboIlz5yUASQAVsACAAAAAAWbp8JVJnx8fEVAJFa7WMfMa7wXeP5M3C8MX20J/i9n0AAzE0AH0AAAAFZAAgAAAAAJaRYmo8zqI2BEUzdSwp4tVRpPmVWsfydkYN3UHh6TMuBXMAIAAAAAAeD6mDnQeLlbC9i0sVgE8+RH6y+e94OJQ0tJ0PvblVSgVsACAAAAAAWp4jvretbDEsqEMzP/WLTnwOiJwCtfrCiB6m8k+yEMoAAzE1AH0AAAAFZAAgAAAAAAZZ538coNPwyRjhEwr5P8Xw32oWOJF+R+nfCGgy2qO3BXMAIAAAAACOPLnJlKwGNPDBReRKnHfteq0wFb3ezhrc7BVXs8RUHwVsACAAAAAA+lGesNk3+SyB/60rSvdQ2aN2vfJPR7llJVhufGTNhHkAAzE2AH0AAAAFZAAgAAAAAFH9l9GGA1I52atJV5jNUf1lx8jBjoEoVoME97v5GFJiBXMAIAAAAAC1qH3Kd78Dr9NGbw7y9D/XYBwv5h1LLO8la5OU7g8UkQVsACAAAAAArZ6atJCYrVfHB8dSNPOFf6nnDADBMJcIEj8ljPvxHp8AAzE3AH0AAAAFZAAgAAAAADtbVEI2tdkrowEMdkacD2w0Y3T3Ofi7PH6HmA6sP0c/BXMAIAAAAADuBSROnZHA+NgUPH8d0LnWFiDsM2bY8bzjC1+elSsIygVsACAAAAAAR0G2m+uANoWknkr/NerFcG+fECVxNIs0cqbY1t/U/0MAAzE4AH0AAAAFZAAgAAAAAAh3WpeMVlikPFYj9hLj+fmIqVt6omCSF75W3TPExyWpBXMAIAAAAAAsQkRmwqeVj2gGE03orb6PtrIzDt6dDU3hgSQi8E2wKgVsACAAAAAA3GHaRE2RAcaBRd8VzmYzWeBD2Gmy91eTK1k8YdWObZcAABJjbQAAAAAAAAAAAAAQcGF5bG9hZElkAAAAAAAQZmlyc3RPcGVyYXRvcgABAAAAAA==", "subType": "06" } } } } } ], "cursor": {}, "encryptionInformation": { "type": 1, "schema": { "default.default": { "escCollection": "enxcol_.default.esc", "ecocCollection": "enxcol_.default.ecoc", "fields": [ { "keyId": { "$binary": { "base64": "EjRWeBI0mHYSNBI0VniQEg==", "subType": "04" } }, "path": "encryptedDecimalPrecision", "bsonType": "decimal", "queries": { "queryType": "rangePreview", "contention": { "$numberLong": "0" }, "sparsity": { "$numberLong": "1" }, "min": { "$numberDecimal": "0.0" }, "max": { "$numberDecimal": "200.0" }, "precision": { "$numberInt": "2" } } } ] } } } }, "command_name": "aggregate" } } ], "outcome": { "collection": { "data": [ { "_id": { "$numberInt": "0" }, "encryptedDecimalPrecision": { "$$type": "binData" }, "__safeContent__": [ { "$binary": { "base64": "5nRutVIyq7URVOVtbE4vM01APSIajAVnsShMwjBlzkM=", "subType": "00" } }, { "$binary": { "base64": "Dri0CXmL78L2DOgk9w0DwxHOMGMzih7m6l59vgy+WWo=", "subType": "00" } }, { "$binary": { "base64": "x7GR49EN0t3WXQDihkrbonK7qNIBYC87tpL/XEUyIYc=", "subType": "00" } }, { "$binary": { "base64": "JfYUqWF+OoGjiYkRI4L5iPlF+T1Eleul7Fki22jp4Qc=", "subType": "00" } }, { "$binary": { "base64": "q1RyGfIgsaQHoZFRw+DD28V26rN5hweApPLwExncvT8=", "subType": "00" } }, { "$binary": { "base64": "L2PFeKGvLS6C+DLudR6fGlBq3ERPvjWvRyNRIA2HVb0=", "subType": "00" } }, { "$binary": { "base64": "CWxaNqL3iP1yCixDkcmf9bmW3E5VeN8TJkg1jJe528s=", "subType": "00" } }, { "$binary": { "base64": "+vC6araOEo+fpW7PSIP40/EnzBCj1d2N10Jr3rrXJJM=", "subType": "00" } }, { "$binary": { "base64": "6SV63Mf51Z6A6p2X3rCnJKCu6ku3Oeb45mBYbz+IoAo=", "subType": "00" } }, { "$binary": { "base64": "RjBYT2h3ZAoHxhf8DU6/dFbDkEBZp0IxREcsRTu2MXs=", "subType": "00" } }, { "$binary": { "base64": "b7d8mRzD1kI1tdc7uNL+YAUonJ6pODLsRLkArfEKSkM=", "subType": "00" } }, { "$binary": { "base64": "Xg8C1/A0KJaXOw4i+26Rv03/CydaaunOzXh0CIT+gn8=", "subType": "00" } }, { "$binary": { "base64": "UoKUDw2wJYToUCcFaIs03YQSTksYR0MIOTJllwODqKc=", "subType": "00" } }, { "$binary": { "base64": "c/5cwAT0C5jber2xlJnWD3a5tVDy0nRtr5HG02hoFOY=", "subType": "00" } }, { "$binary": { "base64": "wSUrRXavAGaajNeqC5mEUH1K67oYl5Wy9RNIzKjwLAM=", "subType": "00" } }, { "$binary": { "base64": "6vrp4wWDtHEgHWR99I70WVDzevg1Fk/Pw5U8gUDa0OU=", "subType": "00" } } ] }, { "_id": { "$numberInt": "1" }, "encryptedDecimalPrecision": { "$$type": "binData" }, "__safeContent__": [ { "$binary": { "base64": "bE1vqWj3KNyM7cCYUv/cnYm8BPaUL3eMp5syTHq6NF4=", "subType": "00" } }, { "$binary": { "base64": "mVZb+Ra0EYjQ4Zrh9X//E2T8MRj7NMqm5GUJXhRrBEI=", "subType": "00" } }, { "$binary": { "base64": "FA74j21GUEJb1DJBOpR9nVnjaDZnd8yAQNuaW9Qi26g=", "subType": "00" } }, { "$binary": { "base64": "kJv//KVkbrobIBf+QeWC5jxn20mx/P0R1N6aCSMgKM8=", "subType": "00" } }, { "$binary": { "base64": "zB+Whi9IUUGxfLEe+lGuIzLX4LFbIhaIAm5lRk65QTc=", "subType": "00" } }, { "$binary": { "base64": "ybO1QU3CgvhO8JgRXH+HxKszWcpl5aGDYYVa75fHa1g=", "subType": "00" } }, { "$binary": { "base64": "X3Y3eSAbbMg//JgiHHiFpYOpV61t8kkDexI+CQyitH4=", "subType": "00" } }, { "$binary": { "base64": "SlNHXyqVFGDPrX/2ppwog6l4pwj3PKda2TkZbqgfSfA=", "subType": "00" } }, { "$binary": { "base64": "McjV8xwTF3xI7863DYOBdyvIv6UpzThl6v9vBRk05bI=", "subType": "00" } }, { "$binary": { "base64": "MgwakFvPyBlwqFTbhWUF79URJQWFoJTGotlEVSPPUsQ=", "subType": "00" } }, { "$binary": { "base64": "DyBERpMSD5lEM5Nhpcn4WGgxgn/mkUVJp+PYSLX5jsE=", "subType": "00" } }, { "$binary": { "base64": "I43iazc0xj1WVbYB/V+uTL/tughN1bBlxh1iypBnNsA=", "subType": "00" } }, { "$binary": { "base64": "wjOBa/ATMuOywFmuPgC0GF/oeLqu0Z7eK5udzkTPbis=", "subType": "00" } }, { "$binary": { "base64": "gRQVwiR+m+0Vg8ZDXqrQQcVnTyobwCXNaA4BCJVXtMc=", "subType": "00" } }, { "$binary": { "base64": "WUZ6huwx0ZbLb0R00uiC9FOJzsUocUN8qE5+YRenkvQ=", "subType": "00" } }, { "$binary": { "base64": "7s79aKEuPgQcS/YPOOVcYNZvHIo7FFsWtFCrnDKXefA=", "subType": "00" } } ] } ] } } } ] } fle2v2-Range-DecimalPrecision-Correctness.json000066400000000000000000001164101462766011000376530ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/client-side-encryption/spec/legacy{ "runOn": [ { "minServerVersion": "7.0.0", "topology": [ "replicaset", "sharded", "load-balanced" ] } ], "database_name": "default", "collection_name": "default", "data": [], "encrypted_fields": { "fields": [ { "keyId": { "$binary": { "base64": "EjRWeBI0mHYSNBI0VniQEg==", "subType": "04" } }, "path": "encryptedDecimalPrecision", "bsonType": "decimal", "queries": { "queryType": "rangePreview", "contention": { "$numberLong": "0" }, "sparsity": { "$numberLong": "1" }, "min": { "$numberDecimal": "0.0" }, "max": { "$numberDecimal": "200.0" }, "precision": { "$numberInt": "2" } } } ] }, "key_vault_data": [ { "_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" } } ], "tests": [ { "description": "Find with $gt", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "local": { "key": { "$binary": { "base64": "Mng0NCt4ZHVUYUJCa1kxNkVyNUR1QURhZ2h2UzR2d2RrZzh0cFBwM3R6NmdWMDFBMUN3YkQ5aXRRMkhGRGdQV09wOGVNYUMxT2k3NjZKelhaQmRCZGJkTXVyZG9uSjFk", "subType": "00" } } } } } }, "operations": [ { "name": "insertOne", "arguments": { "document": { "_id": 0, "encryptedDecimalPrecision": { "$numberDecimal": "0.0" } } } }, { "name": "insertOne", "arguments": { "document": { "_id": 1, "encryptedDecimalPrecision": { "$numberDecimal": "1.0" } } } }, { "name": "find", "arguments": { "filter": { "encryptedDecimalPrecision": { "$gt": { "$numberDecimal": "0.0" } } } }, "result": [ { "_id": 1, "encryptedDecimalPrecision": { "$numberDecimal": "1.0" } } ] } ] }, { "description": "Find with $gte", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "local": { "key": { "$binary": { "base64": "Mng0NCt4ZHVUYUJCa1kxNkVyNUR1QURhZ2h2UzR2d2RrZzh0cFBwM3R6NmdWMDFBMUN3YkQ5aXRRMkhGRGdQV09wOGVNYUMxT2k3NjZKelhaQmRCZGJkTXVyZG9uSjFk", "subType": "00" } } } } } }, "operations": [ { "name": "insertOne", "arguments": { "document": { "_id": 0, "encryptedDecimalPrecision": { "$numberDecimal": "0.0" } } } }, { "name": "insertOne", "arguments": { "document": { "_id": 1, "encryptedDecimalPrecision": { "$numberDecimal": "1.0" } } } }, { "name": "find", "arguments": { "filter": { "encryptedDecimalPrecision": { "$gte": { "$numberDecimal": "0.0" } } }, "sort": { "_id": 1 } }, "result": [ { "_id": 0, "encryptedDecimalPrecision": { "$numberDecimal": "0.0" } }, { "_id": 1, "encryptedDecimalPrecision": { "$numberDecimal": "1.0" } } ] } ] }, { "description": "Find with $gt with no results", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "local": { "key": { "$binary": { "base64": "Mng0NCt4ZHVUYUJCa1kxNkVyNUR1QURhZ2h2UzR2d2RrZzh0cFBwM3R6NmdWMDFBMUN3YkQ5aXRRMkhGRGdQV09wOGVNYUMxT2k3NjZKelhaQmRCZGJkTXVyZG9uSjFk", "subType": "00" } } } } } }, "operations": [ { "name": "insertOne", "arguments": { "document": { "_id": 0, "encryptedDecimalPrecision": { "$numberDecimal": "0.0" } } } }, { "name": "insertOne", "arguments": { "document": { "_id": 1, "encryptedDecimalPrecision": { "$numberDecimal": "1.0" } } } }, { "name": "find", "arguments": { "filter": { "encryptedDecimalPrecision": { "$gt": { "$numberDecimal": "1.0" } } } }, "result": [] } ] }, { "description": "Find with $lt", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "local": { "key": { "$binary": { "base64": "Mng0NCt4ZHVUYUJCa1kxNkVyNUR1QURhZ2h2UzR2d2RrZzh0cFBwM3R6NmdWMDFBMUN3YkQ5aXRRMkhGRGdQV09wOGVNYUMxT2k3NjZKelhaQmRCZGJkTXVyZG9uSjFk", "subType": "00" } } } } } }, "operations": [ { "name": "insertOne", "arguments": { "document": { "_id": 0, "encryptedDecimalPrecision": { "$numberDecimal": "0.0" } } } }, { "name": "insertOne", "arguments": { "document": { "_id": 1, "encryptedDecimalPrecision": { "$numberDecimal": "1.0" } } } }, { "name": "find", "arguments": { "filter": { "encryptedDecimalPrecision": { "$lt": { "$numberDecimal": "1.0" } } } }, "result": [ { "_id": 0, "encryptedDecimalPrecision": { "$numberDecimal": "0.0" } } ] } ] }, { "description": "Find with $lte", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "local": { "key": { "$binary": { "base64": "Mng0NCt4ZHVUYUJCa1kxNkVyNUR1QURhZ2h2UzR2d2RrZzh0cFBwM3R6NmdWMDFBMUN3YkQ5aXRRMkhGRGdQV09wOGVNYUMxT2k3NjZKelhaQmRCZGJkTXVyZG9uSjFk", "subType": "00" } } } } } }, "operations": [ { "name": "insertOne", "arguments": { "document": { "_id": 0, "encryptedDecimalPrecision": { "$numberDecimal": "0.0" } } } }, { "name": "insertOne", "arguments": { "document": { "_id": 1, "encryptedDecimalPrecision": { "$numberDecimal": "1.0" } } } }, { "name": "find", "arguments": { "filter": { "encryptedDecimalPrecision": { "$lte": { "$numberDecimal": "1.0" } } }, "sort": { "_id": 1 } }, "result": [ { "_id": 0, "encryptedDecimalPrecision": { "$numberDecimal": "0.0" } }, { "_id": 1, "encryptedDecimalPrecision": { "$numberDecimal": "1.0" } } ] } ] }, { "description": "Find with $lt below min", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "local": { "key": { "$binary": { "base64": "Mng0NCt4ZHVUYUJCa1kxNkVyNUR1QURhZ2h2UzR2d2RrZzh0cFBwM3R6NmdWMDFBMUN3YkQ5aXRRMkhGRGdQV09wOGVNYUMxT2k3NjZKelhaQmRCZGJkTXVyZG9uSjFk", "subType": "00" } } } } } }, "operations": [ { "name": "insertOne", "arguments": { "document": { "_id": 0, "encryptedDecimalPrecision": { "$numberDecimal": "0.0" } } } }, { "name": "insertOne", "arguments": { "document": { "_id": 1, "encryptedDecimalPrecision": { "$numberDecimal": "1.0" } } } }, { "name": "find", "arguments": { "filter": { "encryptedDecimalPrecision": { "$lt": { "$numberDecimal": "0.0" } } } }, "result": { "errorContains": "must be greater than the range minimum" } } ] }, { "description": "Find with $gt above max", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "local": { "key": { "$binary": { "base64": "Mng0NCt4ZHVUYUJCa1kxNkVyNUR1QURhZ2h2UzR2d2RrZzh0cFBwM3R6NmdWMDFBMUN3YkQ5aXRRMkhGRGdQV09wOGVNYUMxT2k3NjZKelhaQmRCZGJkTXVyZG9uSjFk", "subType": "00" } } } } } }, "operations": [ { "name": "insertOne", "arguments": { "document": { "_id": 0, "encryptedDecimalPrecision": { "$numberDecimal": "0.0" } } } }, { "name": "insertOne", "arguments": { "document": { "_id": 1, "encryptedDecimalPrecision": { "$numberDecimal": "1.0" } } } }, { "name": "find", "arguments": { "filter": { "encryptedDecimalPrecision": { "$gt": { "$numberDecimal": "200.0" } } } }, "result": { "errorContains": "must be less than the range max" } } ] }, { "description": "Find with $gt and $lt", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "local": { "key": { "$binary": { "base64": "Mng0NCt4ZHVUYUJCa1kxNkVyNUR1QURhZ2h2UzR2d2RrZzh0cFBwM3R6NmdWMDFBMUN3YkQ5aXRRMkhGRGdQV09wOGVNYUMxT2k3NjZKelhaQmRCZGJkTXVyZG9uSjFk", "subType": "00" } } } } } }, "operations": [ { "name": "insertOne", "arguments": { "document": { "_id": 0, "encryptedDecimalPrecision": { "$numberDecimal": "0.0" } } } }, { "name": "insertOne", "arguments": { "document": { "_id": 1, "encryptedDecimalPrecision": { "$numberDecimal": "1.0" } } } }, { "name": "find", "arguments": { "filter": { "encryptedDecimalPrecision": { "$gt": { "$numberDecimal": "0.0" }, "$lt": { "$numberDecimal": "2.0" } } } }, "result": [ { "_id": 1, "encryptedDecimalPrecision": { "$numberDecimal": "1.0" } } ] } ] }, { "description": "Find with equality", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "local": { "key": { "$binary": { "base64": "Mng0NCt4ZHVUYUJCa1kxNkVyNUR1QURhZ2h2UzR2d2RrZzh0cFBwM3R6NmdWMDFBMUN3YkQ5aXRRMkhGRGdQV09wOGVNYUMxT2k3NjZKelhaQmRCZGJkTXVyZG9uSjFk", "subType": "00" } } } } } }, "operations": [ { "name": "insertOne", "arguments": { "document": { "_id": 0, "encryptedDecimalPrecision": { "$numberDecimal": "0.0" } } } }, { "name": "insertOne", "arguments": { "document": { "_id": 1, "encryptedDecimalPrecision": { "$numberDecimal": "1.0" } } } }, { "name": "find", "arguments": { "filter": { "encryptedDecimalPrecision": { "$numberDecimal": "0.0" } } }, "result": [ { "_id": 0, "encryptedDecimalPrecision": { "$numberDecimal": "0.0" } } ] }, { "name": "find", "arguments": { "filter": { "encryptedDecimalPrecision": { "$numberDecimal": "1.0" } } }, "result": [ { "_id": 1, "encryptedDecimalPrecision": { "$numberDecimal": "1.0" } } ] } ] }, { "description": "Find with full range", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "local": { "key": { "$binary": { "base64": "Mng0NCt4ZHVUYUJCa1kxNkVyNUR1QURhZ2h2UzR2d2RrZzh0cFBwM3R6NmdWMDFBMUN3YkQ5aXRRMkhGRGdQV09wOGVNYUMxT2k3NjZKelhaQmRCZGJkTXVyZG9uSjFk", "subType": "00" } } } } } }, "operations": [ { "name": "insertOne", "arguments": { "document": { "_id": 0, "encryptedDecimalPrecision": { "$numberDecimal": "0.0" } } } }, { "name": "insertOne", "arguments": { "document": { "_id": 1, "encryptedDecimalPrecision": { "$numberDecimal": "1.0" } } } }, { "name": "find", "arguments": { "filter": { "encryptedDecimalPrecision": { "$gte": { "$numberDecimal": "0.0" }, "$lte": { "$numberDecimal": "200.0" } } }, "sort": { "_id": 1 } }, "result": [ { "_id": 0, "encryptedDecimalPrecision": { "$numberDecimal": "0.0" } }, { "_id": 1, "encryptedDecimalPrecision": { "$numberDecimal": "1.0" } } ] } ] }, { "description": "Find with $in", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "local": { "key": { "$binary": { "base64": "Mng0NCt4ZHVUYUJCa1kxNkVyNUR1QURhZ2h2UzR2d2RrZzh0cFBwM3R6NmdWMDFBMUN3YkQ5aXRRMkhGRGdQV09wOGVNYUMxT2k3NjZKelhaQmRCZGJkTXVyZG9uSjFk", "subType": "00" } } } } } }, "operations": [ { "name": "insertOne", "arguments": { "document": { "_id": 0, "encryptedDecimalPrecision": { "$numberDecimal": "0.0" } } } }, { "name": "insertOne", "arguments": { "document": { "_id": 1, "encryptedDecimalPrecision": { "$numberDecimal": "1.0" } } } }, { "name": "find", "arguments": { "filter": { "encryptedDecimalPrecision": { "$in": [ { "$numberDecimal": "0.0" } ] } } }, "result": [ { "_id": 0, "encryptedDecimalPrecision": { "$numberDecimal": "0.0" } } ] } ] }, { "description": "Insert out of range", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "local": { "key": { "$binary": { "base64": "Mng0NCt4ZHVUYUJCa1kxNkVyNUR1QURhZ2h2UzR2d2RrZzh0cFBwM3R6NmdWMDFBMUN3YkQ5aXRRMkhGRGdQV09wOGVNYUMxT2k3NjZKelhaQmRCZGJkTXVyZG9uSjFk", "subType": "00" } } } } } }, "operations": [ { "name": "insertOne", "arguments": { "document": { "_id": 0, "encryptedDecimalPrecision": { "$numberDecimal": "-1" } } }, "result": { "errorContains": "value must be greater than or equal to the minimum value" } } ] }, { "description": "Insert min and max", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "local": { "key": { "$binary": { "base64": "Mng0NCt4ZHVUYUJCa1kxNkVyNUR1QURhZ2h2UzR2d2RrZzh0cFBwM3R6NmdWMDFBMUN3YkQ5aXRRMkhGRGdQV09wOGVNYUMxT2k3NjZKelhaQmRCZGJkTXVyZG9uSjFk", "subType": "00" } } } } } }, "operations": [ { "name": "insertOne", "arguments": { "document": { "_id": 0, "encryptedDecimalPrecision": { "$numberDecimal": "0.0" } } } }, { "name": "insertOne", "arguments": { "document": { "_id": 200, "encryptedDecimalPrecision": { "$numberDecimal": "200.0" } } } }, { "name": "find", "arguments": { "filter": {}, "sort": { "_id": 1 } }, "result": [ { "_id": 0, "encryptedDecimalPrecision": { "$numberDecimal": "0.0" } }, { "_id": 200, "encryptedDecimalPrecision": { "$numberDecimal": "200.0" } } ] } ] }, { "description": "Aggregate with $gte", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "local": { "key": { "$binary": { "base64": "Mng0NCt4ZHVUYUJCa1kxNkVyNUR1QURhZ2h2UzR2d2RrZzh0cFBwM3R6NmdWMDFBMUN3YkQ5aXRRMkhGRGdQV09wOGVNYUMxT2k3NjZKelhaQmRCZGJkTXVyZG9uSjFk", "subType": "00" } } } } } }, "operations": [ { "name": "insertOne", "arguments": { "document": { "_id": 0, "encryptedDecimalPrecision": { "$numberDecimal": "0.0" } } } }, { "name": "insertOne", "arguments": { "document": { "_id": 1, "encryptedDecimalPrecision": { "$numberDecimal": "1.0" } } } }, { "name": "aggregate", "arguments": { "pipeline": [ { "$match": { "encryptedDecimalPrecision": { "$gte": { "$numberDecimal": "0.0" } } } }, { "$sort": { "_id": 1 } } ] }, "result": [ { "_id": 0, "encryptedDecimalPrecision": { "$numberDecimal": "0.0" } }, { "_id": 1, "encryptedDecimalPrecision": { "$numberDecimal": "1.0" } } ] } ] }, { "description": "Aggregate with $gt with no results", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "local": { "key": { "$binary": { "base64": "Mng0NCt4ZHVUYUJCa1kxNkVyNUR1QURhZ2h2UzR2d2RrZzh0cFBwM3R6NmdWMDFBMUN3YkQ5aXRRMkhGRGdQV09wOGVNYUMxT2k3NjZKelhaQmRCZGJkTXVyZG9uSjFk", "subType": "00" } } } } } }, "operations": [ { "name": "insertOne", "arguments": { "document": { "_id": 0, "encryptedDecimalPrecision": { "$numberDecimal": "0.0" } } } }, { "name": "insertOne", "arguments": { "document": { "_id": 1, "encryptedDecimalPrecision": { "$numberDecimal": "1.0" } } } }, { "name": "aggregate", "arguments": { "pipeline": [ { "$match": { "encryptedDecimalPrecision": { "$gt": { "$numberDecimal": "1.0" } } } } ] }, "result": [] } ] }, { "description": "Aggregate with $lt", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "local": { "key": { "$binary": { "base64": "Mng0NCt4ZHVUYUJCa1kxNkVyNUR1QURhZ2h2UzR2d2RrZzh0cFBwM3R6NmdWMDFBMUN3YkQ5aXRRMkhGRGdQV09wOGVNYUMxT2k3NjZKelhaQmRCZGJkTXVyZG9uSjFk", "subType": "00" } } } } } }, "operations": [ { "name": "insertOne", "arguments": { "document": { "_id": 0, "encryptedDecimalPrecision": { "$numberDecimal": "0.0" } } } }, { "name": "insertOne", "arguments": { "document": { "_id": 1, "encryptedDecimalPrecision": { "$numberDecimal": "1.0" } } } }, { "name": "aggregate", "arguments": { "pipeline": [ { "$match": { "encryptedDecimalPrecision": { "$lt": { "$numberDecimal": "1.0" } } } } ] }, "result": [ { "_id": 0, "encryptedDecimalPrecision": { "$numberDecimal": "0.0" } } ] } ] }, { "description": "Aggregate with $lte", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "local": { "key": { "$binary": { "base64": "Mng0NCt4ZHVUYUJCa1kxNkVyNUR1QURhZ2h2UzR2d2RrZzh0cFBwM3R6NmdWMDFBMUN3YkQ5aXRRMkhGRGdQV09wOGVNYUMxT2k3NjZKelhaQmRCZGJkTXVyZG9uSjFk", "subType": "00" } } } } } }, "operations": [ { "name": "insertOne", "arguments": { "document": { "_id": 0, "encryptedDecimalPrecision": { "$numberDecimal": "0.0" } } } }, { "name": "insertOne", "arguments": { "document": { "_id": 1, "encryptedDecimalPrecision": { "$numberDecimal": "1.0" } } } }, { "name": "aggregate", "arguments": { "pipeline": [ { "$match": { "encryptedDecimalPrecision": { "$lte": { "$numberDecimal": "1.0" } } } }, { "$sort": { "_id": 1 } } ] }, "result": [ { "_id": 0, "encryptedDecimalPrecision": { "$numberDecimal": "0.0" } }, { "_id": 1, "encryptedDecimalPrecision": { "$numberDecimal": "1.0" } } ] } ] }, { "description": "Aggregate with $lt below min", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "local": { "key": { "$binary": { "base64": "Mng0NCt4ZHVUYUJCa1kxNkVyNUR1QURhZ2h2UzR2d2RrZzh0cFBwM3R6NmdWMDFBMUN3YkQ5aXRRMkhGRGdQV09wOGVNYUMxT2k3NjZKelhaQmRCZGJkTXVyZG9uSjFk", "subType": "00" } } } } } }, "operations": [ { "name": "insertOne", "arguments": { "document": { "_id": 0, "encryptedDecimalPrecision": { "$numberDecimal": "0.0" } } } }, { "name": "insertOne", "arguments": { "document": { "_id": 1, "encryptedDecimalPrecision": { "$numberDecimal": "1.0" } } } }, { "name": "aggregate", "arguments": { "pipeline": [ { "$match": { "encryptedDecimalPrecision": { "$lt": { "$numberDecimal": "0.0" } } } } ] }, "result": { "errorContains": "must be greater than the range minimum" } } ] }, { "description": "Aggregate with $gt above max", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "local": { "key": { "$binary": { "base64": "Mng0NCt4ZHVUYUJCa1kxNkVyNUR1QURhZ2h2UzR2d2RrZzh0cFBwM3R6NmdWMDFBMUN3YkQ5aXRRMkhGRGdQV09wOGVNYUMxT2k3NjZKelhaQmRCZGJkTXVyZG9uSjFk", "subType": "00" } } } } } }, "operations": [ { "name": "insertOne", "arguments": { "document": { "_id": 0, "encryptedDecimalPrecision": { "$numberDecimal": "0.0" } } } }, { "name": "insertOne", "arguments": { "document": { "_id": 1, "encryptedDecimalPrecision": { "$numberDecimal": "1.0" } } } }, { "name": "aggregate", "arguments": { "pipeline": [ { "$match": { "encryptedDecimalPrecision": { "$gt": { "$numberDecimal": "200.0" } } } } ] }, "result": { "errorContains": "must be less than the range max" } } ] }, { "description": "Aggregate with $gt and $lt", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "local": { "key": { "$binary": { "base64": "Mng0NCt4ZHVUYUJCa1kxNkVyNUR1QURhZ2h2UzR2d2RrZzh0cFBwM3R6NmdWMDFBMUN3YkQ5aXRRMkhGRGdQV09wOGVNYUMxT2k3NjZKelhaQmRCZGJkTXVyZG9uSjFk", "subType": "00" } } } } } }, "operations": [ { "name": "insertOne", "arguments": { "document": { "_id": 0, "encryptedDecimalPrecision": { "$numberDecimal": "0.0" } } } }, { "name": "insertOne", "arguments": { "document": { "_id": 1, "encryptedDecimalPrecision": { "$numberDecimal": "1.0" } } } }, { "name": "aggregate", "arguments": { "pipeline": [ { "$match": { "encryptedDecimalPrecision": { "$gt": { "$numberDecimal": "0.0" }, "$lt": { "$numberDecimal": "2.0" } } } } ] }, "result": [ { "_id": 1, "encryptedDecimalPrecision": { "$numberDecimal": "1.0" } } ] } ] }, { "description": "Aggregate with equality", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "local": { "key": { "$binary": { "base64": "Mng0NCt4ZHVUYUJCa1kxNkVyNUR1QURhZ2h2UzR2d2RrZzh0cFBwM3R6NmdWMDFBMUN3YkQ5aXRRMkhGRGdQV09wOGVNYUMxT2k3NjZKelhaQmRCZGJkTXVyZG9uSjFk", "subType": "00" } } } } } }, "operations": [ { "name": "insertOne", "arguments": { "document": { "_id": 0, "encryptedDecimalPrecision": { "$numberDecimal": "0.0" } } } }, { "name": "insertOne", "arguments": { "document": { "_id": 1, "encryptedDecimalPrecision": { "$numberDecimal": "1.0" } } } }, { "name": "aggregate", "arguments": { "pipeline": [ { "$match": { "encryptedDecimalPrecision": { "$numberDecimal": "0.0" } } } ] }, "result": [ { "_id": 0, "encryptedDecimalPrecision": { "$numberDecimal": "0.0" } } ] }, { "name": "aggregate", "arguments": { "pipeline": [ { "$match": { "encryptedDecimalPrecision": { "$numberDecimal": "1.0" } } } ] }, "result": [ { "_id": 1, "encryptedDecimalPrecision": { "$numberDecimal": "1.0" } } ] } ] }, { "description": "Aggregate with full range", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "local": { "key": { "$binary": { "base64": "Mng0NCt4ZHVUYUJCa1kxNkVyNUR1QURhZ2h2UzR2d2RrZzh0cFBwM3R6NmdWMDFBMUN3YkQ5aXRRMkhGRGdQV09wOGVNYUMxT2k3NjZKelhaQmRCZGJkTXVyZG9uSjFk", "subType": "00" } } } } } }, "operations": [ { "name": "insertOne", "arguments": { "document": { "_id": 0, "encryptedDecimalPrecision": { "$numberDecimal": "0.0" } } } }, { "name": "insertOne", "arguments": { "document": { "_id": 1, "encryptedDecimalPrecision": { "$numberDecimal": "1.0" } } } }, { "name": "aggregate", "arguments": { "pipeline": [ { "$match": { "encryptedDecimalPrecision": { "$gte": { "$numberDecimal": "0.0" }, "$lte": { "$numberDecimal": "200.0" } } } }, { "$sort": { "_id": 1 } } ] }, "result": [ { "_id": 0, "encryptedDecimalPrecision": { "$numberDecimal": "0.0" } }, { "_id": 1, "encryptedDecimalPrecision": { "$numberDecimal": "1.0" } } ] } ] }, { "description": "Aggregate with $in", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "local": { "key": { "$binary": { "base64": "Mng0NCt4ZHVUYUJCa1kxNkVyNUR1QURhZ2h2UzR2d2RrZzh0cFBwM3R6NmdWMDFBMUN3YkQ5aXRRMkhGRGdQV09wOGVNYUMxT2k3NjZKelhaQmRCZGJkTXVyZG9uSjFk", "subType": "00" } } } } } }, "operations": [ { "name": "insertOne", "arguments": { "document": { "_id": 0, "encryptedDecimalPrecision": { "$numberDecimal": "0.0" } } } }, { "name": "insertOne", "arguments": { "document": { "_id": 1, "encryptedDecimalPrecision": { "$numberDecimal": "1.0" } } } }, { "name": "aggregate", "arguments": { "pipeline": [ { "$match": { "encryptedDecimalPrecision": { "$in": [ { "$numberDecimal": "0.0" } ] } } } ] }, "result": [ { "_id": 0, "encryptedDecimalPrecision": { "$numberDecimal": "0.0" } } ] } ] }, { "description": "Wrong type: Insert Int", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "local": { "key": { "$binary": { "base64": "Mng0NCt4ZHVUYUJCa1kxNkVyNUR1QURhZ2h2UzR2d2RrZzh0cFBwM3R6NmdWMDFBMUN3YkQ5aXRRMkhGRGdQV09wOGVNYUMxT2k3NjZKelhaQmRCZGJkTXVyZG9uSjFk", "subType": "00" } } } } } }, "operations": [ { "name": "insertOne", "arguments": { "document": { "_id": 0, "encryptedDecimalPrecision": { "$numberInt": "0" } } }, "result": { "errorContains": "cannot encrypt element" } } ] }, { "description": "Wrong type: Find Int", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "local": { "key": { "$binary": { "base64": "Mng0NCt4ZHVUYUJCa1kxNkVyNUR1QURhZ2h2UzR2d2RrZzh0cFBwM3R6NmdWMDFBMUN3YkQ5aXRRMkhGRGdQV09wOGVNYUMxT2k3NjZKelhaQmRCZGJkTXVyZG9uSjFk", "subType": "00" } } } } } }, "operations": [ { "name": "find", "arguments": { "filter": { "encryptedDecimalPrecision": { "$gte": { "$numberInt": "0" } } }, "sort": { "_id": 1 } }, "result": { "errorContains": "field type is not supported" } } ] } ] } fle2v2-Range-DecimalPrecision-Delete.json000066400000000000000000000413711462766011000365660ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/client-side-encryption/spec/legacy{ "runOn": [ { "minServerVersion": "7.0.0", "topology": [ "replicaset", "sharded", "load-balanced" ] } ], "database_name": "default", "collection_name": "default", "data": [], "encrypted_fields": { "fields": [ { "keyId": { "$binary": { "base64": "EjRWeBI0mHYSNBI0VniQEg==", "subType": "04" } }, "path": "encryptedDecimalPrecision", "bsonType": "decimal", "queries": { "queryType": "rangePreview", "contention": { "$numberLong": "0" }, "sparsity": { "$numberLong": "1" }, "min": { "$numberDecimal": "0.0" }, "max": { "$numberDecimal": "200.0" }, "precision": { "$numberInt": "2" } } } ] }, "key_vault_data": [ { "_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" } } ], "tests": [ { "description": "FLE2 Range DecimalPrecision. Delete.", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "local": { "key": { "$binary": { "base64": "Mng0NCt4ZHVUYUJCa1kxNkVyNUR1QURhZ2h2UzR2d2RrZzh0cFBwM3R6NmdWMDFBMUN3YkQ5aXRRMkhGRGdQV09wOGVNYUMxT2k3NjZKelhaQmRCZGJkTXVyZG9uSjFk", "subType": "00" } } } } } }, "operations": [ { "name": "insertOne", "arguments": { "document": { "_id": 0, "encryptedDecimalPrecision": { "$numberDecimal": "0" } } } }, { "name": "insertOne", "arguments": { "document": { "_id": 1, "encryptedDecimalPrecision": { "$numberDecimal": "1" } } } }, { "name": "deleteOne", "arguments": { "filter": { "encryptedDecimalPrecision": { "$gt": { "$numberDecimal": "0" } } } }, "result": { "deletedCount": 1 } } ], "expectations": [ { "command_started_event": { "command": { "listCollections": 1, "filter": { "name": "default" } }, "command_name": "listCollections" } }, { "command_started_event": { "command": { "find": "datakeys", "filter": { "$or": [ { "_id": { "$in": [ { "$binary": { "base64": "EjRWeBI0mHYSNBI0VniQEg==", "subType": "04" } } ] } }, { "keyAltNames": { "$in": [] } } ] }, "$db": "keyvault", "readConcern": { "level": "majority" } }, "command_name": "find" } }, { "command_started_event": { "command": { "insert": "default", "documents": [ { "_id": 0, "encryptedDecimalPrecision": { "$$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": "encryptedDecimalPrecision", "bsonType": "decimal", "queries": { "queryType": "rangePreview", "contention": { "$numberLong": "0" }, "sparsity": { "$numberLong": "1" }, "min": { "$numberDecimal": "0.0" }, "max": { "$numberDecimal": "200.0" }, "precision": { "$numberInt": "2" } } } ] } } } }, "command_name": "insert" } }, { "command_started_event": { "command": { "insert": "default", "documents": [ { "_id": 1, "encryptedDecimalPrecision": { "$$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": "encryptedDecimalPrecision", "bsonType": "decimal", "queries": { "queryType": "rangePreview", "contention": { "$numberLong": "0" }, "sparsity": { "$numberLong": "1" }, "min": { "$numberDecimal": "0.0" }, "max": { "$numberDecimal": "200.0" }, "precision": { "$numberInt": "2" } } } ] } } } }, "command_name": "insert" } }, { "command_started_event": { "command": { "delete": "default", "deletes": [ { "q": { "encryptedDecimalPrecision": { "$gt": { "$binary": { "base64": "DdIJAAADcGF5bG9hZACiCQAABGcAjgkAAAMwAH0AAAAFZAAgAAAAAHdJ2Vnb4MMzqVYVssjSdDy8XU4GVzMTfGifGETgQ2mYBXMAIAAAAAD7cFfKJGIXo6PjyeX2ria02CckW7dWFDoY/3FyBdm1NQVsACAAAAAAhEPSNv4M023A3hzNFuy83+hIKuZ2mKRY954N++aEOBUAAzEAfQAAAAVkACAAAAAAlmvfDrZoydUet4eCVMq7z6a58Ea+1HLJOWxN5lNcrWEFcwAgAAAAAEBo5AWZyC41b9ayjWNQSL4iYEAIwR/JG+ssN8bdoK9RBWwAIAAAAACEndE0SLxFSElOrNnqeX0EPmgDio3udZjVREy4JLS3sQADMgB9AAAABWQAIAAAAABbiLaoxAA6rinMJw1hC8ZUiq6UU1AQaPFn/py/Y06WuQVzACAAAAAAhtDasFkvYE7SCNu1je/hxdE9TJtAvvH3NtdEbKzNbCUFbAAgAAAAAIGepU1RSCF8sWODHEpKglsoqw3VBBH4a/URGxgGzbq2AAMzAH0AAAAFZAAgAAAAALORWwSr+tYNxcil2KIGSbNhTHvcPbdj+rLVQNx21S/KBXMAIAAAAAD6diZBkPEJ1cQy06LAxdbNK8Nlxbb44fH4Wk3Y3260nQVsACAAAAAA1eYAZBFHlDiaDAljWi8blGQ2nvvZa5AO5doeo0SFZsgAAzQAfQAAAAVkACAAAAAAG5XMK96PjClNlUvg82j4pMY1YxsznZfj4uNweD394FoFcwAgAAAAAKHgQLdGJHkrfFg9nB93Ac+3VgBw6aU44MTkKIQ91dZoBWwAIAAAAAAPxXmi+SDJ+40A0KdwfRczexlZQrHjIA+D3oUB0EY9tAADNQB9AAAABWQAIAAAAAA6M++b9I0YFemmWBAWAE3glu2Ah3Ta1FBxAQEIWS0toAVzACAAAAAANXYTqPf1Y6X3Ns6YQIX0C3FKCyWUo+Kk+fNcQvc0WSoFbAAgAAAAAA+uJUw1ICYgyeygSRe206VTWVtUnhdci3iHbyP5YtEVAAM2AH0AAAAFZAAgAAAAAKl8bV1riH/uyJ+X0HHd3+18k2cJl2dQFXCdoagutFcaBXMAIAAAAABm8F2Ew9f0VOABdcF+lP0Bi+zWvEUPniWgrxPq/Sx3uwVsACAAAAAAJfFErjZ6BPhsw5LjJLqNtKDLJ4zV0eIZppQpd9b0wZoAAzcAfQAAAAVkACAAAAAAsYZD8JEP6kYsPncFnNZwJxhu4YtUTKPNcjHtv67H+rYFcwAgAAAAAI4LqZcRkvbs/2F62Flu0pixNcor4WmBD0DHGaf039wLBWwAIAAAAAD4wUR3xd9lKltcqqo8LYvdMQWzCRobkV/ppKB/yn5dUgADOAB9AAAABWQAIAAAAAC0vdAi+dmoIXvZ5LqUqvyKV9/tHqSI2SWiSJO5pTnA2wVzACAAAAAAS2qvf9fvfVUH5WtsVxjxmskpGjYTQV34LwvQQw1y9wIFbAAgAAAAAE0+FKuK7HxbypvCeEJzMTcjOWE0ScYOlTBMUNlIv55hAAM5AH0AAAAFZAAgAAAAAH31lb/srBcrOXkzddCwAnclsR5/3QijEVgECs2JjOWBBXMAIAAAAABg7+prDT73YcCvLE5QbuIrqGcjLc5pQD2Miq0d29yrxgVsACAAAAAAetRiPwDSFWBzpWSWkOKWM6fKStRJ8SyObnpc79ux8p0AAzEwAH0AAAAFZAAgAAAAAOK8brUuc2onBNDRtfYMR736dHj4dQqXod8JG7tAMTsDBXMAIAAAAAAW6SrGAL6Bx0s7ZlsYULFfOAiYIGhEWu6md3r+Rk40awVsACAAAAAAIHYXP8RLcCboUmHN3+OlnEw1DxaLSnbTB9PdF228fFAAAzExAH0AAAAFZAAgAAAAAFdthRhe2Q8CvxGIhjTJZv0Lk97GkHciTPxZ/mckLoNaBXMAIAAAAAAqOxsAr23LOVB0DIHbPf9UDJJRFXY2YoKbjhRqw5psbQVsACAAAAAA0G2GD8ZQjDBntjLpW4rqwKRS6HiUjL03g1N6chANozcAAzEyAH0AAAAFZAAgAAAAAMWymwwbvIeMqmnKWWifUqoCxOsdpnonM2qdLPyjqJO/BXMAIAAAAAB6IDmmpUhBD2zpRj8/y/kmOSXcjuIU14sNh6GKSsg2uwVsACAAAAAAWMFPNOk3EMSQDS9JGPSMIQP0oNGVugxXKKUrIPPlhHgAAzEzAH0AAAAFZAAgAAAAAPcLmtq+V1e+MRlZ7NHq1+mrRVBQje5zj685ZvdsfKvSBXMAIAAAAABdHz/3w2k5km97QN9m7oLFYJaVJneNlMboIlz5yUASQAVsACAAAAAAWbp8JVJnx8fEVAJFa7WMfMa7wXeP5M3C8MX20J/i9n0AAzE0AH0AAAAFZAAgAAAAAJaRYmo8zqI2BEUzdSwp4tVRpPmVWsfydkYN3UHh6TMuBXMAIAAAAAAeD6mDnQeLlbC9i0sVgE8+RH6y+e94OJQ0tJ0PvblVSgVsACAAAAAAWp4jvretbDEsqEMzP/WLTnwOiJwCtfrCiB6m8k+yEMoAAzE1AH0AAAAFZAAgAAAAAAZZ538coNPwyRjhEwr5P8Xw32oWOJF+R+nfCGgy2qO3BXMAIAAAAACOPLnJlKwGNPDBReRKnHfteq0wFb3ezhrc7BVXs8RUHwVsACAAAAAA+lGesNk3+SyB/60rSvdQ2aN2vfJPR7llJVhufGTNhHkAAzE2AH0AAAAFZAAgAAAAAFH9l9GGA1I52atJV5jNUf1lx8jBjoEoVoME97v5GFJiBXMAIAAAAAC1qH3Kd78Dr9NGbw7y9D/XYBwv5h1LLO8la5OU7g8UkQVsACAAAAAArZ6atJCYrVfHB8dSNPOFf6nnDADBMJcIEj8ljPvxHp8AAzE3AH0AAAAFZAAgAAAAADtbVEI2tdkrowEMdkacD2w0Y3T3Ofi7PH6HmA6sP0c/BXMAIAAAAADuBSROnZHA+NgUPH8d0LnWFiDsM2bY8bzjC1+elSsIygVsACAAAAAAR0G2m+uANoWknkr/NerFcG+fECVxNIs0cqbY1t/U/0MAAzE4AH0AAAAFZAAgAAAAAAh3WpeMVlikPFYj9hLj+fmIqVt6omCSF75W3TPExyWpBXMAIAAAAAAsQkRmwqeVj2gGE03orb6PtrIzDt6dDU3hgSQi8E2wKgVsACAAAAAA3GHaRE2RAcaBRd8VzmYzWeBD2Gmy91eTK1k8YdWObZcAABJjbQAAAAAAAAAAAAAQcGF5bG9hZElkAAAAAAAQZmlyc3RPcGVyYXRvcgABAAAAAA==", "subType": "06" } } } }, "limit": 1 } ], "ordered": true, "encryptionInformation": { "type": 1, "schema": { "default.default": { "escCollection": "enxcol_.default.esc", "ecocCollection": "enxcol_.default.ecoc", "fields": [ { "keyId": { "$binary": { "base64": "EjRWeBI0mHYSNBI0VniQEg==", "subType": "04" } }, "path": "encryptedDecimalPrecision", "bsonType": "decimal", "queries": { "queryType": "rangePreview", "contention": { "$numberLong": "0" }, "sparsity": { "$numberLong": "1" }, "min": { "$numberDecimal": "0.0" }, "max": { "$numberDecimal": "200.0" }, "precision": { "$numberInt": "2" } } } ] } } } }, "command_name": "delete" } } ], "outcome": { "collection": { "data": [ { "_id": { "$numberInt": "0" }, "encryptedDecimalPrecision": { "$$type": "binData" }, "__safeContent__": [ { "$binary": { "base64": "5nRutVIyq7URVOVtbE4vM01APSIajAVnsShMwjBlzkM=", "subType": "00" } }, { "$binary": { "base64": "Dri0CXmL78L2DOgk9w0DwxHOMGMzih7m6l59vgy+WWo=", "subType": "00" } }, { "$binary": { "base64": "x7GR49EN0t3WXQDihkrbonK7qNIBYC87tpL/XEUyIYc=", "subType": "00" } }, { "$binary": { "base64": "JfYUqWF+OoGjiYkRI4L5iPlF+T1Eleul7Fki22jp4Qc=", "subType": "00" } }, { "$binary": { "base64": "q1RyGfIgsaQHoZFRw+DD28V26rN5hweApPLwExncvT8=", "subType": "00" } }, { "$binary": { "base64": "L2PFeKGvLS6C+DLudR6fGlBq3ERPvjWvRyNRIA2HVb0=", "subType": "00" } }, { "$binary": { "base64": "CWxaNqL3iP1yCixDkcmf9bmW3E5VeN8TJkg1jJe528s=", "subType": "00" } }, { "$binary": { "base64": "+vC6araOEo+fpW7PSIP40/EnzBCj1d2N10Jr3rrXJJM=", "subType": "00" } }, { "$binary": { "base64": "6SV63Mf51Z6A6p2X3rCnJKCu6ku3Oeb45mBYbz+IoAo=", "subType": "00" } }, { "$binary": { "base64": "RjBYT2h3ZAoHxhf8DU6/dFbDkEBZp0IxREcsRTu2MXs=", "subType": "00" } }, { "$binary": { "base64": "b7d8mRzD1kI1tdc7uNL+YAUonJ6pODLsRLkArfEKSkM=", "subType": "00" } }, { "$binary": { "base64": "Xg8C1/A0KJaXOw4i+26Rv03/CydaaunOzXh0CIT+gn8=", "subType": "00" } }, { "$binary": { "base64": "UoKUDw2wJYToUCcFaIs03YQSTksYR0MIOTJllwODqKc=", "subType": "00" } }, { "$binary": { "base64": "c/5cwAT0C5jber2xlJnWD3a5tVDy0nRtr5HG02hoFOY=", "subType": "00" } }, { "$binary": { "base64": "wSUrRXavAGaajNeqC5mEUH1K67oYl5Wy9RNIzKjwLAM=", "subType": "00" } }, { "$binary": { "base64": "6vrp4wWDtHEgHWR99I70WVDzevg1Fk/Pw5U8gUDa0OU=", "subType": "00" } } ] } ] } } } ] } fle2v2-Range-DecimalPrecision-FindOneAndUpdate.json000066400000000000000000000507741462766011000405030ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/client-side-encryption/spec/legacy{ "runOn": [ { "minServerVersion": "7.0.0", "topology": [ "replicaset", "sharded", "load-balanced" ] } ], "database_name": "default", "collection_name": "default", "data": [], "encrypted_fields": { "fields": [ { "keyId": { "$binary": { "base64": "EjRWeBI0mHYSNBI0VniQEg==", "subType": "04" } }, "path": "encryptedDecimalPrecision", "bsonType": "decimal", "queries": { "queryType": "rangePreview", "contention": { "$numberLong": "0" }, "sparsity": { "$numberLong": "1" }, "min": { "$numberDecimal": "0.0" }, "max": { "$numberDecimal": "200.0" }, "precision": { "$numberInt": "2" } } } ] }, "key_vault_data": [ { "_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" } } ], "tests": [ { "description": "FLE2 Range DecimalPrecision. FindOneAndUpdate.", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "local": { "key": { "$binary": { "base64": "Mng0NCt4ZHVUYUJCa1kxNkVyNUR1QURhZ2h2UzR2d2RrZzh0cFBwM3R6NmdWMDFBMUN3YkQ5aXRRMkhGRGdQV09wOGVNYUMxT2k3NjZKelhaQmRCZGJkTXVyZG9uSjFk", "subType": "00" } } } } } }, "operations": [ { "name": "insertOne", "arguments": { "document": { "_id": 0, "encryptedDecimalPrecision": { "$numberDecimal": "0" } } } }, { "name": "insertOne", "arguments": { "document": { "_id": 1, "encryptedDecimalPrecision": { "$numberDecimal": "1" } } } }, { "name": "findOneAndUpdate", "arguments": { "filter": { "encryptedDecimalPrecision": { "$gt": { "$numberDecimal": "0" } } }, "update": { "$set": { "encryptedDecimalPrecision": { "$numberDecimal": "2" } } }, "returnDocument": "Before" }, "result": { "_id": 1, "encryptedDecimalPrecision": { "$numberDecimal": "1" } } } ], "expectations": [ { "command_started_event": { "command": { "listCollections": 1, "filter": { "name": "default" } }, "command_name": "listCollections" } }, { "command_started_event": { "command": { "find": "datakeys", "filter": { "$or": [ { "_id": { "$in": [ { "$binary": { "base64": "EjRWeBI0mHYSNBI0VniQEg==", "subType": "04" } } ] } }, { "keyAltNames": { "$in": [] } } ] }, "$db": "keyvault", "readConcern": { "level": "majority" } }, "command_name": "find" } }, { "command_started_event": { "command": { "insert": "default", "documents": [ { "_id": 0, "encryptedDecimalPrecision": { "$$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": "encryptedDecimalPrecision", "bsonType": "decimal", "queries": { "queryType": "rangePreview", "contention": { "$numberLong": "0" }, "sparsity": { "$numberLong": "1" }, "min": { "$numberDecimal": "0.0" }, "max": { "$numberDecimal": "200.0" }, "precision": { "$numberInt": "2" } } } ] } } } }, "command_name": "insert" } }, { "command_started_event": { "command": { "insert": "default", "documents": [ { "_id": 1, "encryptedDecimalPrecision": { "$$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": "encryptedDecimalPrecision", "bsonType": "decimal", "queries": { "queryType": "rangePreview", "contention": { "$numberLong": "0" }, "sparsity": { "$numberLong": "1" }, "min": { "$numberDecimal": "0.0" }, "max": { "$numberDecimal": "200.0" }, "precision": { "$numberInt": "2" } } } ] } } } }, "command_name": "insert" } }, { "command_started_event": { "command": { "findAndModify": "default", "query": { "encryptedDecimalPrecision": { "$gt": { "$binary": { "base64": "DdIJAAADcGF5bG9hZACiCQAABGcAjgkAAAMwAH0AAAAFZAAgAAAAAHdJ2Vnb4MMzqVYVssjSdDy8XU4GVzMTfGifGETgQ2mYBXMAIAAAAAD7cFfKJGIXo6PjyeX2ria02CckW7dWFDoY/3FyBdm1NQVsACAAAAAAhEPSNv4M023A3hzNFuy83+hIKuZ2mKRY954N++aEOBUAAzEAfQAAAAVkACAAAAAAlmvfDrZoydUet4eCVMq7z6a58Ea+1HLJOWxN5lNcrWEFcwAgAAAAAEBo5AWZyC41b9ayjWNQSL4iYEAIwR/JG+ssN8bdoK9RBWwAIAAAAACEndE0SLxFSElOrNnqeX0EPmgDio3udZjVREy4JLS3sQADMgB9AAAABWQAIAAAAABbiLaoxAA6rinMJw1hC8ZUiq6UU1AQaPFn/py/Y06WuQVzACAAAAAAhtDasFkvYE7SCNu1je/hxdE9TJtAvvH3NtdEbKzNbCUFbAAgAAAAAIGepU1RSCF8sWODHEpKglsoqw3VBBH4a/URGxgGzbq2AAMzAH0AAAAFZAAgAAAAALORWwSr+tYNxcil2KIGSbNhTHvcPbdj+rLVQNx21S/KBXMAIAAAAAD6diZBkPEJ1cQy06LAxdbNK8Nlxbb44fH4Wk3Y3260nQVsACAAAAAA1eYAZBFHlDiaDAljWi8blGQ2nvvZa5AO5doeo0SFZsgAAzQAfQAAAAVkACAAAAAAG5XMK96PjClNlUvg82j4pMY1YxsznZfj4uNweD394FoFcwAgAAAAAKHgQLdGJHkrfFg9nB93Ac+3VgBw6aU44MTkKIQ91dZoBWwAIAAAAAAPxXmi+SDJ+40A0KdwfRczexlZQrHjIA+D3oUB0EY9tAADNQB9AAAABWQAIAAAAAA6M++b9I0YFemmWBAWAE3glu2Ah3Ta1FBxAQEIWS0toAVzACAAAAAANXYTqPf1Y6X3Ns6YQIX0C3FKCyWUo+Kk+fNcQvc0WSoFbAAgAAAAAA+uJUw1ICYgyeygSRe206VTWVtUnhdci3iHbyP5YtEVAAM2AH0AAAAFZAAgAAAAAKl8bV1riH/uyJ+X0HHd3+18k2cJl2dQFXCdoagutFcaBXMAIAAAAABm8F2Ew9f0VOABdcF+lP0Bi+zWvEUPniWgrxPq/Sx3uwVsACAAAAAAJfFErjZ6BPhsw5LjJLqNtKDLJ4zV0eIZppQpd9b0wZoAAzcAfQAAAAVkACAAAAAAsYZD8JEP6kYsPncFnNZwJxhu4YtUTKPNcjHtv67H+rYFcwAgAAAAAI4LqZcRkvbs/2F62Flu0pixNcor4WmBD0DHGaf039wLBWwAIAAAAAD4wUR3xd9lKltcqqo8LYvdMQWzCRobkV/ppKB/yn5dUgADOAB9AAAABWQAIAAAAAC0vdAi+dmoIXvZ5LqUqvyKV9/tHqSI2SWiSJO5pTnA2wVzACAAAAAAS2qvf9fvfVUH5WtsVxjxmskpGjYTQV34LwvQQw1y9wIFbAAgAAAAAE0+FKuK7HxbypvCeEJzMTcjOWE0ScYOlTBMUNlIv55hAAM5AH0AAAAFZAAgAAAAAH31lb/srBcrOXkzddCwAnclsR5/3QijEVgECs2JjOWBBXMAIAAAAABg7+prDT73YcCvLE5QbuIrqGcjLc5pQD2Miq0d29yrxgVsACAAAAAAetRiPwDSFWBzpWSWkOKWM6fKStRJ8SyObnpc79ux8p0AAzEwAH0AAAAFZAAgAAAAAOK8brUuc2onBNDRtfYMR736dHj4dQqXod8JG7tAMTsDBXMAIAAAAAAW6SrGAL6Bx0s7ZlsYULFfOAiYIGhEWu6md3r+Rk40awVsACAAAAAAIHYXP8RLcCboUmHN3+OlnEw1DxaLSnbTB9PdF228fFAAAzExAH0AAAAFZAAgAAAAAFdthRhe2Q8CvxGIhjTJZv0Lk97GkHciTPxZ/mckLoNaBXMAIAAAAAAqOxsAr23LOVB0DIHbPf9UDJJRFXY2YoKbjhRqw5psbQVsACAAAAAA0G2GD8ZQjDBntjLpW4rqwKRS6HiUjL03g1N6chANozcAAzEyAH0AAAAFZAAgAAAAAMWymwwbvIeMqmnKWWifUqoCxOsdpnonM2qdLPyjqJO/BXMAIAAAAAB6IDmmpUhBD2zpRj8/y/kmOSXcjuIU14sNh6GKSsg2uwVsACAAAAAAWMFPNOk3EMSQDS9JGPSMIQP0oNGVugxXKKUrIPPlhHgAAzEzAH0AAAAFZAAgAAAAAPcLmtq+V1e+MRlZ7NHq1+mrRVBQje5zj685ZvdsfKvSBXMAIAAAAABdHz/3w2k5km97QN9m7oLFYJaVJneNlMboIlz5yUASQAVsACAAAAAAWbp8JVJnx8fEVAJFa7WMfMa7wXeP5M3C8MX20J/i9n0AAzE0AH0AAAAFZAAgAAAAAJaRYmo8zqI2BEUzdSwp4tVRpPmVWsfydkYN3UHh6TMuBXMAIAAAAAAeD6mDnQeLlbC9i0sVgE8+RH6y+e94OJQ0tJ0PvblVSgVsACAAAAAAWp4jvretbDEsqEMzP/WLTnwOiJwCtfrCiB6m8k+yEMoAAzE1AH0AAAAFZAAgAAAAAAZZ538coNPwyRjhEwr5P8Xw32oWOJF+R+nfCGgy2qO3BXMAIAAAAACOPLnJlKwGNPDBReRKnHfteq0wFb3ezhrc7BVXs8RUHwVsACAAAAAA+lGesNk3+SyB/60rSvdQ2aN2vfJPR7llJVhufGTNhHkAAzE2AH0AAAAFZAAgAAAAAFH9l9GGA1I52atJV5jNUf1lx8jBjoEoVoME97v5GFJiBXMAIAAAAAC1qH3Kd78Dr9NGbw7y9D/XYBwv5h1LLO8la5OU7g8UkQVsACAAAAAArZ6atJCYrVfHB8dSNPOFf6nnDADBMJcIEj8ljPvxHp8AAzE3AH0AAAAFZAAgAAAAADtbVEI2tdkrowEMdkacD2w0Y3T3Ofi7PH6HmA6sP0c/BXMAIAAAAADuBSROnZHA+NgUPH8d0LnWFiDsM2bY8bzjC1+elSsIygVsACAAAAAAR0G2m+uANoWknkr/NerFcG+fECVxNIs0cqbY1t/U/0MAAzE4AH0AAAAFZAAgAAAAAAh3WpeMVlikPFYj9hLj+fmIqVt6omCSF75W3TPExyWpBXMAIAAAAAAsQkRmwqeVj2gGE03orb6PtrIzDt6dDU3hgSQi8E2wKgVsACAAAAAA3GHaRE2RAcaBRd8VzmYzWeBD2Gmy91eTK1k8YdWObZcAABJjbQAAAAAAAAAAAAAQcGF5bG9hZElkAAAAAAAQZmlyc3RPcGVyYXRvcgABAAAAAA==", "subType": "06" } } } }, "update": { "$set": { "encryptedDecimalPrecision": { "$$type": "binData" } } }, "encryptionInformation": { "type": 1, "schema": { "default.default": { "escCollection": "enxcol_.default.esc", "ecocCollection": "enxcol_.default.ecoc", "fields": [ { "keyId": { "$binary": { "base64": "EjRWeBI0mHYSNBI0VniQEg==", "subType": "04" } }, "path": "encryptedDecimalPrecision", "bsonType": "decimal", "queries": { "queryType": "rangePreview", "contention": { "$numberLong": "0" }, "sparsity": { "$numberLong": "1" }, "min": { "$numberDecimal": "0.0" }, "max": { "$numberDecimal": "200.0" }, "precision": { "$numberInt": "2" } } } ] } } } }, "command_name": "findAndModify" } } ], "outcome": { "collection": { "data": [ { "_id": { "$numberInt": "0" }, "encryptedDecimalPrecision": { "$$type": "binData" }, "__safeContent__": [ { "$binary": { "base64": "5nRutVIyq7URVOVtbE4vM01APSIajAVnsShMwjBlzkM=", "subType": "00" } }, { "$binary": { "base64": "Dri0CXmL78L2DOgk9w0DwxHOMGMzih7m6l59vgy+WWo=", "subType": "00" } }, { "$binary": { "base64": "x7GR49EN0t3WXQDihkrbonK7qNIBYC87tpL/XEUyIYc=", "subType": "00" } }, { "$binary": { "base64": "JfYUqWF+OoGjiYkRI4L5iPlF+T1Eleul7Fki22jp4Qc=", "subType": "00" } }, { "$binary": { "base64": "q1RyGfIgsaQHoZFRw+DD28V26rN5hweApPLwExncvT8=", "subType": "00" } }, { "$binary": { "base64": "L2PFeKGvLS6C+DLudR6fGlBq3ERPvjWvRyNRIA2HVb0=", "subType": "00" } }, { "$binary": { "base64": "CWxaNqL3iP1yCixDkcmf9bmW3E5VeN8TJkg1jJe528s=", "subType": "00" } }, { "$binary": { "base64": "+vC6araOEo+fpW7PSIP40/EnzBCj1d2N10Jr3rrXJJM=", "subType": "00" } }, { "$binary": { "base64": "6SV63Mf51Z6A6p2X3rCnJKCu6ku3Oeb45mBYbz+IoAo=", "subType": "00" } }, { "$binary": { "base64": "RjBYT2h3ZAoHxhf8DU6/dFbDkEBZp0IxREcsRTu2MXs=", "subType": "00" } }, { "$binary": { "base64": "b7d8mRzD1kI1tdc7uNL+YAUonJ6pODLsRLkArfEKSkM=", "subType": "00" } }, { "$binary": { "base64": "Xg8C1/A0KJaXOw4i+26Rv03/CydaaunOzXh0CIT+gn8=", "subType": "00" } }, { "$binary": { "base64": "UoKUDw2wJYToUCcFaIs03YQSTksYR0MIOTJllwODqKc=", "subType": "00" } }, { "$binary": { "base64": "c/5cwAT0C5jber2xlJnWD3a5tVDy0nRtr5HG02hoFOY=", "subType": "00" } }, { "$binary": { "base64": "wSUrRXavAGaajNeqC5mEUH1K67oYl5Wy9RNIzKjwLAM=", "subType": "00" } }, { "$binary": { "base64": "6vrp4wWDtHEgHWR99I70WVDzevg1Fk/Pw5U8gUDa0OU=", "subType": "00" } } ] }, { "_id": { "$numberInt": "1" }, "encryptedDecimalPrecision": { "$$type": "binData" }, "__safeContent__": [ { "$binary": { "base64": "DLCAJs+W2PL2DV5YChCL6dYrQNr+j4p3L7xhVaub4ic=", "subType": "00" } }, { "$binary": { "base64": "V6knyt7Zq2CG3++l75UtBx2m32iGAPjHiAe439Bf02w=", "subType": "00" } }, { "$binary": { "base64": "F08nMDWDZc+DbWM7XCEJNNCEYyinRmrvGP7EWhmp4is=", "subType": "00" } }, { "$binary": { "base64": "cXH4688amcDc8kZOJq4UP8cE3R58Zl7e+Qo/1jyspps=", "subType": "00" } }, { "$binary": { "base64": "uURBxvTp3FBCVkd+LPqyuY7d6rMW6SGIJQEPY/wtkZI=", "subType": "00" } }, { "$binary": { "base64": "jG3hax1L3RBp9t38vUt53FsBxgr/+Si/vVISpAylYpE=", "subType": "00" } }, { "$binary": { "base64": "kwtIW8MhH9Ky5xNjBx8gFA/SHh2YVphie7g5FGBzals=", "subType": "00" } }, { "$binary": { "base64": "FHflwFuEMu4xX0ZApHi+pdlBH+oevAtXckCUb5Wv0xU=", "subType": "00" } }, { "$binary": { "base64": "0OKSXELxPP85SBVwDGf3LtMEQCJ8TTkFUl/+6jlkdb0=", "subType": "00" } }, { "$binary": { "base64": "25j9sQXZCihCmHKvTHgaBsAVZFcGPn7JjHdrCGlwyyw=", "subType": "00" } }, { "$binary": { "base64": "uEw0lpQtBppR3vqV9j9+NQRSBF1BzZukb8c9IhyWvxc=", "subType": "00" } }, { "$binary": { "base64": "zVhZ7Q59O087ji49oMJvBIgeir2oqvUpnh4p53GcTow=", "subType": "00" } }, { "$binary": { "base64": "dowrzKs+qJhRMZyKDbhjXbuX43FbmUKOaw9I8YlOZDw=", "subType": "00" } }, { "$binary": { "base64": "ep5B6cska6THLIF7Mn3tn3RvV9EiwLSt0eZM/CLRUDc=", "subType": "00" } }, { "$binary": { "base64": "URNp/YmmDh5wIZUfAzzgPyJeMNiVx9PMsz52DZRujGY=", "subType": "00" } }, { "$binary": { "base64": "wlM4IAQhhKQEzoVqS8b1Ddd50GB95OFb9LnzOwyjCP4=", "subType": "00" } } ] } ] } } } ] } fle2v2-Range-DecimalPrecision-InsertFind.json000066400000000000000000000477721462766011000374440ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/client-side-encryption/spec/legacy{ "runOn": [ { "minServerVersion": "7.0.0", "topology": [ "replicaset", "sharded", "load-balanced" ] } ], "database_name": "default", "collection_name": "default", "data": [], "encrypted_fields": { "fields": [ { "keyId": { "$binary": { "base64": "EjRWeBI0mHYSNBI0VniQEg==", "subType": "04" } }, "path": "encryptedDecimalPrecision", "bsonType": "decimal", "queries": { "queryType": "rangePreview", "contention": { "$numberLong": "0" }, "sparsity": { "$numberLong": "1" }, "min": { "$numberDecimal": "0.0" }, "max": { "$numberDecimal": "200.0" }, "precision": { "$numberInt": "2" } } } ] }, "key_vault_data": [ { "_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" } } ], "tests": [ { "description": "FLE2 Range DecimalPrecision. Insert and Find.", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "local": { "key": { "$binary": { "base64": "Mng0NCt4ZHVUYUJCa1kxNkVyNUR1QURhZ2h2UzR2d2RrZzh0cFBwM3R6NmdWMDFBMUN3YkQ5aXRRMkhGRGdQV09wOGVNYUMxT2k3NjZKelhaQmRCZGJkTXVyZG9uSjFk", "subType": "00" } } } } } }, "operations": [ { "name": "insertOne", "arguments": { "document": { "_id": 0, "encryptedDecimalPrecision": { "$numberDecimal": "0" } } } }, { "name": "insertOne", "arguments": { "document": { "_id": 1, "encryptedDecimalPrecision": { "$numberDecimal": "1" } } } }, { "name": "find", "arguments": { "filter": { "encryptedDecimalPrecision": { "$gt": { "$numberDecimal": "0" } } } }, "result": [ { "_id": 1, "encryptedDecimalPrecision": { "$numberDecimal": "1" } } ] } ], "expectations": [ { "command_started_event": { "command": { "listCollections": 1, "filter": { "name": "default" } }, "command_name": "listCollections" } }, { "command_started_event": { "command": { "find": "datakeys", "filter": { "$or": [ { "_id": { "$in": [ { "$binary": { "base64": "EjRWeBI0mHYSNBI0VniQEg==", "subType": "04" } } ] } }, { "keyAltNames": { "$in": [] } } ] }, "$db": "keyvault", "readConcern": { "level": "majority" } }, "command_name": "find" } }, { "command_started_event": { "command": { "insert": "default", "documents": [ { "_id": 0, "encryptedDecimalPrecision": { "$$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": "encryptedDecimalPrecision", "bsonType": "decimal", "queries": { "queryType": "rangePreview", "contention": { "$numberLong": "0" }, "sparsity": { "$numberLong": "1" }, "min": { "$numberDecimal": "0.0" }, "max": { "$numberDecimal": "200.0" }, "precision": { "$numberInt": "2" } } } ] } } } }, "command_name": "insert" } }, { "command_started_event": { "command": { "insert": "default", "documents": [ { "_id": 1, "encryptedDecimalPrecision": { "$$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": "encryptedDecimalPrecision", "bsonType": "decimal", "queries": { "queryType": "rangePreview", "contention": { "$numberLong": "0" }, "sparsity": { "$numberLong": "1" }, "min": { "$numberDecimal": "0.0" }, "max": { "$numberDecimal": "200.0" }, "precision": { "$numberInt": "2" } } } ] } } } }, "command_name": "insert" } }, { "command_started_event": { "command": { "find": "default", "filter": { "encryptedDecimalPrecision": { "$gt": { "$binary": { "base64": "DdIJAAADcGF5bG9hZACiCQAABGcAjgkAAAMwAH0AAAAFZAAgAAAAAHdJ2Vnb4MMzqVYVssjSdDy8XU4GVzMTfGifGETgQ2mYBXMAIAAAAAD7cFfKJGIXo6PjyeX2ria02CckW7dWFDoY/3FyBdm1NQVsACAAAAAAhEPSNv4M023A3hzNFuy83+hIKuZ2mKRY954N++aEOBUAAzEAfQAAAAVkACAAAAAAlmvfDrZoydUet4eCVMq7z6a58Ea+1HLJOWxN5lNcrWEFcwAgAAAAAEBo5AWZyC41b9ayjWNQSL4iYEAIwR/JG+ssN8bdoK9RBWwAIAAAAACEndE0SLxFSElOrNnqeX0EPmgDio3udZjVREy4JLS3sQADMgB9AAAABWQAIAAAAABbiLaoxAA6rinMJw1hC8ZUiq6UU1AQaPFn/py/Y06WuQVzACAAAAAAhtDasFkvYE7SCNu1je/hxdE9TJtAvvH3NtdEbKzNbCUFbAAgAAAAAIGepU1RSCF8sWODHEpKglsoqw3VBBH4a/URGxgGzbq2AAMzAH0AAAAFZAAgAAAAALORWwSr+tYNxcil2KIGSbNhTHvcPbdj+rLVQNx21S/KBXMAIAAAAAD6diZBkPEJ1cQy06LAxdbNK8Nlxbb44fH4Wk3Y3260nQVsACAAAAAA1eYAZBFHlDiaDAljWi8blGQ2nvvZa5AO5doeo0SFZsgAAzQAfQAAAAVkACAAAAAAG5XMK96PjClNlUvg82j4pMY1YxsznZfj4uNweD394FoFcwAgAAAAAKHgQLdGJHkrfFg9nB93Ac+3VgBw6aU44MTkKIQ91dZoBWwAIAAAAAAPxXmi+SDJ+40A0KdwfRczexlZQrHjIA+D3oUB0EY9tAADNQB9AAAABWQAIAAAAAA6M++b9I0YFemmWBAWAE3glu2Ah3Ta1FBxAQEIWS0toAVzACAAAAAANXYTqPf1Y6X3Ns6YQIX0C3FKCyWUo+Kk+fNcQvc0WSoFbAAgAAAAAA+uJUw1ICYgyeygSRe206VTWVtUnhdci3iHbyP5YtEVAAM2AH0AAAAFZAAgAAAAAKl8bV1riH/uyJ+X0HHd3+18k2cJl2dQFXCdoagutFcaBXMAIAAAAABm8F2Ew9f0VOABdcF+lP0Bi+zWvEUPniWgrxPq/Sx3uwVsACAAAAAAJfFErjZ6BPhsw5LjJLqNtKDLJ4zV0eIZppQpd9b0wZoAAzcAfQAAAAVkACAAAAAAsYZD8JEP6kYsPncFnNZwJxhu4YtUTKPNcjHtv67H+rYFcwAgAAAAAI4LqZcRkvbs/2F62Flu0pixNcor4WmBD0DHGaf039wLBWwAIAAAAAD4wUR3xd9lKltcqqo8LYvdMQWzCRobkV/ppKB/yn5dUgADOAB9AAAABWQAIAAAAAC0vdAi+dmoIXvZ5LqUqvyKV9/tHqSI2SWiSJO5pTnA2wVzACAAAAAAS2qvf9fvfVUH5WtsVxjxmskpGjYTQV34LwvQQw1y9wIFbAAgAAAAAE0+FKuK7HxbypvCeEJzMTcjOWE0ScYOlTBMUNlIv55hAAM5AH0AAAAFZAAgAAAAAH31lb/srBcrOXkzddCwAnclsR5/3QijEVgECs2JjOWBBXMAIAAAAABg7+prDT73YcCvLE5QbuIrqGcjLc5pQD2Miq0d29yrxgVsACAAAAAAetRiPwDSFWBzpWSWkOKWM6fKStRJ8SyObnpc79ux8p0AAzEwAH0AAAAFZAAgAAAAAOK8brUuc2onBNDRtfYMR736dHj4dQqXod8JG7tAMTsDBXMAIAAAAAAW6SrGAL6Bx0s7ZlsYULFfOAiYIGhEWu6md3r+Rk40awVsACAAAAAAIHYXP8RLcCboUmHN3+OlnEw1DxaLSnbTB9PdF228fFAAAzExAH0AAAAFZAAgAAAAAFdthRhe2Q8CvxGIhjTJZv0Lk97GkHciTPxZ/mckLoNaBXMAIAAAAAAqOxsAr23LOVB0DIHbPf9UDJJRFXY2YoKbjhRqw5psbQVsACAAAAAA0G2GD8ZQjDBntjLpW4rqwKRS6HiUjL03g1N6chANozcAAzEyAH0AAAAFZAAgAAAAAMWymwwbvIeMqmnKWWifUqoCxOsdpnonM2qdLPyjqJO/BXMAIAAAAAB6IDmmpUhBD2zpRj8/y/kmOSXcjuIU14sNh6GKSsg2uwVsACAAAAAAWMFPNOk3EMSQDS9JGPSMIQP0oNGVugxXKKUrIPPlhHgAAzEzAH0AAAAFZAAgAAAAAPcLmtq+V1e+MRlZ7NHq1+mrRVBQje5zj685ZvdsfKvSBXMAIAAAAABdHz/3w2k5km97QN9m7oLFYJaVJneNlMboIlz5yUASQAVsACAAAAAAWbp8JVJnx8fEVAJFa7WMfMa7wXeP5M3C8MX20J/i9n0AAzE0AH0AAAAFZAAgAAAAAJaRYmo8zqI2BEUzdSwp4tVRpPmVWsfydkYN3UHh6TMuBXMAIAAAAAAeD6mDnQeLlbC9i0sVgE8+RH6y+e94OJQ0tJ0PvblVSgVsACAAAAAAWp4jvretbDEsqEMzP/WLTnwOiJwCtfrCiB6m8k+yEMoAAzE1AH0AAAAFZAAgAAAAAAZZ538coNPwyRjhEwr5P8Xw32oWOJF+R+nfCGgy2qO3BXMAIAAAAACOPLnJlKwGNPDBReRKnHfteq0wFb3ezhrc7BVXs8RUHwVsACAAAAAA+lGesNk3+SyB/60rSvdQ2aN2vfJPR7llJVhufGTNhHkAAzE2AH0AAAAFZAAgAAAAAFH9l9GGA1I52atJV5jNUf1lx8jBjoEoVoME97v5GFJiBXMAIAAAAAC1qH3Kd78Dr9NGbw7y9D/XYBwv5h1LLO8la5OU7g8UkQVsACAAAAAArZ6atJCYrVfHB8dSNPOFf6nnDADBMJcIEj8ljPvxHp8AAzE3AH0AAAAFZAAgAAAAADtbVEI2tdkrowEMdkacD2w0Y3T3Ofi7PH6HmA6sP0c/BXMAIAAAAADuBSROnZHA+NgUPH8d0LnWFiDsM2bY8bzjC1+elSsIygVsACAAAAAAR0G2m+uANoWknkr/NerFcG+fECVxNIs0cqbY1t/U/0MAAzE4AH0AAAAFZAAgAAAAAAh3WpeMVlikPFYj9hLj+fmIqVt6omCSF75W3TPExyWpBXMAIAAAAAAsQkRmwqeVj2gGE03orb6PtrIzDt6dDU3hgSQi8E2wKgVsACAAAAAA3GHaRE2RAcaBRd8VzmYzWeBD2Gmy91eTK1k8YdWObZcAABJjbQAAAAAAAAAAAAAQcGF5bG9hZElkAAAAAAAQZmlyc3RPcGVyYXRvcgABAAAAAA==", "subType": "06" } } } }, "encryptionInformation": { "type": 1, "schema": { "default.default": { "escCollection": "enxcol_.default.esc", "ecocCollection": "enxcol_.default.ecoc", "fields": [ { "keyId": { "$binary": { "base64": "EjRWeBI0mHYSNBI0VniQEg==", "subType": "04" } }, "path": "encryptedDecimalPrecision", "bsonType": "decimal", "queries": { "queryType": "rangePreview", "contention": { "$numberLong": "0" }, "sparsity": { "$numberLong": "1" }, "min": { "$numberDecimal": "0.0" }, "max": { "$numberDecimal": "200.0" }, "precision": { "$numberInt": "2" } } } ] } } } }, "command_name": "find" } } ], "outcome": { "collection": { "data": [ { "_id": 0, "encryptedDecimalPrecision": { "$$type": "binData" }, "__safeContent__": [ { "$binary": { "base64": "5nRutVIyq7URVOVtbE4vM01APSIajAVnsShMwjBlzkM=", "subType": "00" } }, { "$binary": { "base64": "Dri0CXmL78L2DOgk9w0DwxHOMGMzih7m6l59vgy+WWo=", "subType": "00" } }, { "$binary": { "base64": "x7GR49EN0t3WXQDihkrbonK7qNIBYC87tpL/XEUyIYc=", "subType": "00" } }, { "$binary": { "base64": "JfYUqWF+OoGjiYkRI4L5iPlF+T1Eleul7Fki22jp4Qc=", "subType": "00" } }, { "$binary": { "base64": "q1RyGfIgsaQHoZFRw+DD28V26rN5hweApPLwExncvT8=", "subType": "00" } }, { "$binary": { "base64": "L2PFeKGvLS6C+DLudR6fGlBq3ERPvjWvRyNRIA2HVb0=", "subType": "00" } }, { "$binary": { "base64": "CWxaNqL3iP1yCixDkcmf9bmW3E5VeN8TJkg1jJe528s=", "subType": "00" } }, { "$binary": { "base64": "+vC6araOEo+fpW7PSIP40/EnzBCj1d2N10Jr3rrXJJM=", "subType": "00" } }, { "$binary": { "base64": "6SV63Mf51Z6A6p2X3rCnJKCu6ku3Oeb45mBYbz+IoAo=", "subType": "00" } }, { "$binary": { "base64": "RjBYT2h3ZAoHxhf8DU6/dFbDkEBZp0IxREcsRTu2MXs=", "subType": "00" } }, { "$binary": { "base64": "b7d8mRzD1kI1tdc7uNL+YAUonJ6pODLsRLkArfEKSkM=", "subType": "00" } }, { "$binary": { "base64": "Xg8C1/A0KJaXOw4i+26Rv03/CydaaunOzXh0CIT+gn8=", "subType": "00" } }, { "$binary": { "base64": "UoKUDw2wJYToUCcFaIs03YQSTksYR0MIOTJllwODqKc=", "subType": "00" } }, { "$binary": { "base64": "c/5cwAT0C5jber2xlJnWD3a5tVDy0nRtr5HG02hoFOY=", "subType": "00" } }, { "$binary": { "base64": "wSUrRXavAGaajNeqC5mEUH1K67oYl5Wy9RNIzKjwLAM=", "subType": "00" } }, { "$binary": { "base64": "6vrp4wWDtHEgHWR99I70WVDzevg1Fk/Pw5U8gUDa0OU=", "subType": "00" } } ] }, { "_id": 1, "encryptedDecimalPrecision": { "$$type": "binData" }, "__safeContent__": [ { "$binary": { "base64": "bE1vqWj3KNyM7cCYUv/cnYm8BPaUL3eMp5syTHq6NF4=", "subType": "00" } }, { "$binary": { "base64": "mVZb+Ra0EYjQ4Zrh9X//E2T8MRj7NMqm5GUJXhRrBEI=", "subType": "00" } }, { "$binary": { "base64": "FA74j21GUEJb1DJBOpR9nVnjaDZnd8yAQNuaW9Qi26g=", "subType": "00" } }, { "$binary": { "base64": "kJv//KVkbrobIBf+QeWC5jxn20mx/P0R1N6aCSMgKM8=", "subType": "00" } }, { "$binary": { "base64": "zB+Whi9IUUGxfLEe+lGuIzLX4LFbIhaIAm5lRk65QTc=", "subType": "00" } }, { "$binary": { "base64": "ybO1QU3CgvhO8JgRXH+HxKszWcpl5aGDYYVa75fHa1g=", "subType": "00" } }, { "$binary": { "base64": "X3Y3eSAbbMg//JgiHHiFpYOpV61t8kkDexI+CQyitH4=", "subType": "00" } }, { "$binary": { "base64": "SlNHXyqVFGDPrX/2ppwog6l4pwj3PKda2TkZbqgfSfA=", "subType": "00" } }, { "$binary": { "base64": "McjV8xwTF3xI7863DYOBdyvIv6UpzThl6v9vBRk05bI=", "subType": "00" } }, { "$binary": { "base64": "MgwakFvPyBlwqFTbhWUF79URJQWFoJTGotlEVSPPUsQ=", "subType": "00" } }, { "$binary": { "base64": "DyBERpMSD5lEM5Nhpcn4WGgxgn/mkUVJp+PYSLX5jsE=", "subType": "00" } }, { "$binary": { "base64": "I43iazc0xj1WVbYB/V+uTL/tughN1bBlxh1iypBnNsA=", "subType": "00" } }, { "$binary": { "base64": "wjOBa/ATMuOywFmuPgC0GF/oeLqu0Z7eK5udzkTPbis=", "subType": "00" } }, { "$binary": { "base64": "gRQVwiR+m+0Vg8ZDXqrQQcVnTyobwCXNaA4BCJVXtMc=", "subType": "00" } }, { "$binary": { "base64": "WUZ6huwx0ZbLb0R00uiC9FOJzsUocUN8qE5+YRenkvQ=", "subType": "00" } }, { "$binary": { "base64": "7s79aKEuPgQcS/YPOOVcYNZvHIo7FFsWtFCrnDKXefA=", "subType": "00" } } ] } ] } } } ] } fle2v2-Range-DecimalPrecision-Update.json000066400000000000000000000510051462766011000366010ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/client-side-encryption/spec/legacy{ "runOn": [ { "minServerVersion": "7.0.0", "topology": [ "replicaset", "sharded", "load-balanced" ] } ], "database_name": "default", "collection_name": "default", "data": [], "encrypted_fields": { "fields": [ { "keyId": { "$binary": { "base64": "EjRWeBI0mHYSNBI0VniQEg==", "subType": "04" } }, "path": "encryptedDecimalPrecision", "bsonType": "decimal", "queries": { "queryType": "rangePreview", "contention": { "$numberLong": "0" }, "sparsity": { "$numberLong": "1" }, "min": { "$numberDecimal": "0.0" }, "max": { "$numberDecimal": "200.0" }, "precision": { "$numberInt": "2" } } } ] }, "key_vault_data": [ { "_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" } } ], "tests": [ { "description": "FLE2 Range DecimalPrecision. Update.", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "local": { "key": { "$binary": { "base64": "Mng0NCt4ZHVUYUJCa1kxNkVyNUR1QURhZ2h2UzR2d2RrZzh0cFBwM3R6NmdWMDFBMUN3YkQ5aXRRMkhGRGdQV09wOGVNYUMxT2k3NjZKelhaQmRCZGJkTXVyZG9uSjFk", "subType": "00" } } } } } }, "operations": [ { "name": "insertOne", "arguments": { "document": { "_id": 0, "encryptedDecimalPrecision": { "$numberDecimal": "0" } } } }, { "name": "insertOne", "arguments": { "document": { "_id": 1, "encryptedDecimalPrecision": { "$numberDecimal": "1" } } } }, { "name": "updateOne", "arguments": { "filter": { "encryptedDecimalPrecision": { "$gt": { "$numberDecimal": "0" } } }, "update": { "$set": { "encryptedDecimalPrecision": { "$numberDecimal": "2" } } } }, "result": { "matchedCount": 1, "modifiedCount": 1, "upsertedCount": 0 } } ], "expectations": [ { "command_started_event": { "command": { "listCollections": 1, "filter": { "name": "default" } }, "command_name": "listCollections" } }, { "command_started_event": { "command": { "find": "datakeys", "filter": { "$or": [ { "_id": { "$in": [ { "$binary": { "base64": "EjRWeBI0mHYSNBI0VniQEg==", "subType": "04" } } ] } }, { "keyAltNames": { "$in": [] } } ] }, "$db": "keyvault", "readConcern": { "level": "majority" } }, "command_name": "find" } }, { "command_started_event": { "command": { "insert": "default", "documents": [ { "_id": 0, "encryptedDecimalPrecision": { "$$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": "encryptedDecimalPrecision", "bsonType": "decimal", "queries": { "queryType": "rangePreview", "contention": { "$numberLong": "0" }, "sparsity": { "$numberLong": "1" }, "min": { "$numberDecimal": "0.0" }, "max": { "$numberDecimal": "200.0" }, "precision": { "$numberInt": "2" } } } ] } } } }, "command_name": "insert" } }, { "command_started_event": { "command": { "insert": "default", "documents": [ { "_id": 1, "encryptedDecimalPrecision": { "$$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": "encryptedDecimalPrecision", "bsonType": "decimal", "queries": { "queryType": "rangePreview", "contention": { "$numberLong": "0" }, "sparsity": { "$numberLong": "1" }, "min": { "$numberDecimal": "0.0" }, "max": { "$numberDecimal": "200.0" }, "precision": { "$numberInt": "2" } } } ] } } } }, "command_name": "insert" } }, { "command_started_event": { "command_name": "update", "command": { "update": "default", "ordered": true, "updates": [ { "q": { "encryptedDecimalPrecision": { "$gt": { "$binary": { "base64": "DdIJAAADcGF5bG9hZACiCQAABGcAjgkAAAMwAH0AAAAFZAAgAAAAAHdJ2Vnb4MMzqVYVssjSdDy8XU4GVzMTfGifGETgQ2mYBXMAIAAAAAD7cFfKJGIXo6PjyeX2ria02CckW7dWFDoY/3FyBdm1NQVsACAAAAAAhEPSNv4M023A3hzNFuy83+hIKuZ2mKRY954N++aEOBUAAzEAfQAAAAVkACAAAAAAlmvfDrZoydUet4eCVMq7z6a58Ea+1HLJOWxN5lNcrWEFcwAgAAAAAEBo5AWZyC41b9ayjWNQSL4iYEAIwR/JG+ssN8bdoK9RBWwAIAAAAACEndE0SLxFSElOrNnqeX0EPmgDio3udZjVREy4JLS3sQADMgB9AAAABWQAIAAAAABbiLaoxAA6rinMJw1hC8ZUiq6UU1AQaPFn/py/Y06WuQVzACAAAAAAhtDasFkvYE7SCNu1je/hxdE9TJtAvvH3NtdEbKzNbCUFbAAgAAAAAIGepU1RSCF8sWODHEpKglsoqw3VBBH4a/URGxgGzbq2AAMzAH0AAAAFZAAgAAAAALORWwSr+tYNxcil2KIGSbNhTHvcPbdj+rLVQNx21S/KBXMAIAAAAAD6diZBkPEJ1cQy06LAxdbNK8Nlxbb44fH4Wk3Y3260nQVsACAAAAAA1eYAZBFHlDiaDAljWi8blGQ2nvvZa5AO5doeo0SFZsgAAzQAfQAAAAVkACAAAAAAG5XMK96PjClNlUvg82j4pMY1YxsznZfj4uNweD394FoFcwAgAAAAAKHgQLdGJHkrfFg9nB93Ac+3VgBw6aU44MTkKIQ91dZoBWwAIAAAAAAPxXmi+SDJ+40A0KdwfRczexlZQrHjIA+D3oUB0EY9tAADNQB9AAAABWQAIAAAAAA6M++b9I0YFemmWBAWAE3glu2Ah3Ta1FBxAQEIWS0toAVzACAAAAAANXYTqPf1Y6X3Ns6YQIX0C3FKCyWUo+Kk+fNcQvc0WSoFbAAgAAAAAA+uJUw1ICYgyeygSRe206VTWVtUnhdci3iHbyP5YtEVAAM2AH0AAAAFZAAgAAAAAKl8bV1riH/uyJ+X0HHd3+18k2cJl2dQFXCdoagutFcaBXMAIAAAAABm8F2Ew9f0VOABdcF+lP0Bi+zWvEUPniWgrxPq/Sx3uwVsACAAAAAAJfFErjZ6BPhsw5LjJLqNtKDLJ4zV0eIZppQpd9b0wZoAAzcAfQAAAAVkACAAAAAAsYZD8JEP6kYsPncFnNZwJxhu4YtUTKPNcjHtv67H+rYFcwAgAAAAAI4LqZcRkvbs/2F62Flu0pixNcor4WmBD0DHGaf039wLBWwAIAAAAAD4wUR3xd9lKltcqqo8LYvdMQWzCRobkV/ppKB/yn5dUgADOAB9AAAABWQAIAAAAAC0vdAi+dmoIXvZ5LqUqvyKV9/tHqSI2SWiSJO5pTnA2wVzACAAAAAAS2qvf9fvfVUH5WtsVxjxmskpGjYTQV34LwvQQw1y9wIFbAAgAAAAAE0+FKuK7HxbypvCeEJzMTcjOWE0ScYOlTBMUNlIv55hAAM5AH0AAAAFZAAgAAAAAH31lb/srBcrOXkzddCwAnclsR5/3QijEVgECs2JjOWBBXMAIAAAAABg7+prDT73YcCvLE5QbuIrqGcjLc5pQD2Miq0d29yrxgVsACAAAAAAetRiPwDSFWBzpWSWkOKWM6fKStRJ8SyObnpc79ux8p0AAzEwAH0AAAAFZAAgAAAAAOK8brUuc2onBNDRtfYMR736dHj4dQqXod8JG7tAMTsDBXMAIAAAAAAW6SrGAL6Bx0s7ZlsYULFfOAiYIGhEWu6md3r+Rk40awVsACAAAAAAIHYXP8RLcCboUmHN3+OlnEw1DxaLSnbTB9PdF228fFAAAzExAH0AAAAFZAAgAAAAAFdthRhe2Q8CvxGIhjTJZv0Lk97GkHciTPxZ/mckLoNaBXMAIAAAAAAqOxsAr23LOVB0DIHbPf9UDJJRFXY2YoKbjhRqw5psbQVsACAAAAAA0G2GD8ZQjDBntjLpW4rqwKRS6HiUjL03g1N6chANozcAAzEyAH0AAAAFZAAgAAAAAMWymwwbvIeMqmnKWWifUqoCxOsdpnonM2qdLPyjqJO/BXMAIAAAAAB6IDmmpUhBD2zpRj8/y/kmOSXcjuIU14sNh6GKSsg2uwVsACAAAAAAWMFPNOk3EMSQDS9JGPSMIQP0oNGVugxXKKUrIPPlhHgAAzEzAH0AAAAFZAAgAAAAAPcLmtq+V1e+MRlZ7NHq1+mrRVBQje5zj685ZvdsfKvSBXMAIAAAAABdHz/3w2k5km97QN9m7oLFYJaVJneNlMboIlz5yUASQAVsACAAAAAAWbp8JVJnx8fEVAJFa7WMfMa7wXeP5M3C8MX20J/i9n0AAzE0AH0AAAAFZAAgAAAAAJaRYmo8zqI2BEUzdSwp4tVRpPmVWsfydkYN3UHh6TMuBXMAIAAAAAAeD6mDnQeLlbC9i0sVgE8+RH6y+e94OJQ0tJ0PvblVSgVsACAAAAAAWp4jvretbDEsqEMzP/WLTnwOiJwCtfrCiB6m8k+yEMoAAzE1AH0AAAAFZAAgAAAAAAZZ538coNPwyRjhEwr5P8Xw32oWOJF+R+nfCGgy2qO3BXMAIAAAAACOPLnJlKwGNPDBReRKnHfteq0wFb3ezhrc7BVXs8RUHwVsACAAAAAA+lGesNk3+SyB/60rSvdQ2aN2vfJPR7llJVhufGTNhHkAAzE2AH0AAAAFZAAgAAAAAFH9l9GGA1I52atJV5jNUf1lx8jBjoEoVoME97v5GFJiBXMAIAAAAAC1qH3Kd78Dr9NGbw7y9D/XYBwv5h1LLO8la5OU7g8UkQVsACAAAAAArZ6atJCYrVfHB8dSNPOFf6nnDADBMJcIEj8ljPvxHp8AAzE3AH0AAAAFZAAgAAAAADtbVEI2tdkrowEMdkacD2w0Y3T3Ofi7PH6HmA6sP0c/BXMAIAAAAADuBSROnZHA+NgUPH8d0LnWFiDsM2bY8bzjC1+elSsIygVsACAAAAAAR0G2m+uANoWknkr/NerFcG+fECVxNIs0cqbY1t/U/0MAAzE4AH0AAAAFZAAgAAAAAAh3WpeMVlikPFYj9hLj+fmIqVt6omCSF75W3TPExyWpBXMAIAAAAAAsQkRmwqeVj2gGE03orb6PtrIzDt6dDU3hgSQi8E2wKgVsACAAAAAA3GHaRE2RAcaBRd8VzmYzWeBD2Gmy91eTK1k8YdWObZcAABJjbQAAAAAAAAAAAAAQcGF5bG9hZElkAAAAAAAQZmlyc3RPcGVyYXRvcgABAAAAAA==", "subType": "06" } } } }, "u": { "$set": { "encryptedDecimalPrecision": { "$$type": "binData" } } } } ], "encryptionInformation": { "type": 1, "schema": { "default.default": { "escCollection": "enxcol_.default.esc", "ecocCollection": "enxcol_.default.ecoc", "fields": [ { "keyId": { "$binary": { "base64": "EjRWeBI0mHYSNBI0VniQEg==", "subType": "04" } }, "path": "encryptedDecimalPrecision", "bsonType": "decimal", "queries": { "queryType": "rangePreview", "contention": { "$numberLong": "0" }, "sparsity": { "$numberLong": "1" }, "min": { "$numberDecimal": "0.0" }, "max": { "$numberDecimal": "200.0" }, "precision": { "$numberInt": "2" } } } ] } } }, "$db": "default" } } } ], "outcome": { "collection": { "data": [ { "_id": 0, "encryptedDecimalPrecision": { "$$type": "binData" }, "__safeContent__": [ { "$binary": { "base64": "5nRutVIyq7URVOVtbE4vM01APSIajAVnsShMwjBlzkM=", "subType": "00" } }, { "$binary": { "base64": "Dri0CXmL78L2DOgk9w0DwxHOMGMzih7m6l59vgy+WWo=", "subType": "00" } }, { "$binary": { "base64": "x7GR49EN0t3WXQDihkrbonK7qNIBYC87tpL/XEUyIYc=", "subType": "00" } }, { "$binary": { "base64": "JfYUqWF+OoGjiYkRI4L5iPlF+T1Eleul7Fki22jp4Qc=", "subType": "00" } }, { "$binary": { "base64": "q1RyGfIgsaQHoZFRw+DD28V26rN5hweApPLwExncvT8=", "subType": "00" } }, { "$binary": { "base64": "L2PFeKGvLS6C+DLudR6fGlBq3ERPvjWvRyNRIA2HVb0=", "subType": "00" } }, { "$binary": { "base64": "CWxaNqL3iP1yCixDkcmf9bmW3E5VeN8TJkg1jJe528s=", "subType": "00" } }, { "$binary": { "base64": "+vC6araOEo+fpW7PSIP40/EnzBCj1d2N10Jr3rrXJJM=", "subType": "00" } }, { "$binary": { "base64": "6SV63Mf51Z6A6p2X3rCnJKCu6ku3Oeb45mBYbz+IoAo=", "subType": "00" } }, { "$binary": { "base64": "RjBYT2h3ZAoHxhf8DU6/dFbDkEBZp0IxREcsRTu2MXs=", "subType": "00" } }, { "$binary": { "base64": "b7d8mRzD1kI1tdc7uNL+YAUonJ6pODLsRLkArfEKSkM=", "subType": "00" } }, { "$binary": { "base64": "Xg8C1/A0KJaXOw4i+26Rv03/CydaaunOzXh0CIT+gn8=", "subType": "00" } }, { "$binary": { "base64": "UoKUDw2wJYToUCcFaIs03YQSTksYR0MIOTJllwODqKc=", "subType": "00" } }, { "$binary": { "base64": "c/5cwAT0C5jber2xlJnWD3a5tVDy0nRtr5HG02hoFOY=", "subType": "00" } }, { "$binary": { "base64": "wSUrRXavAGaajNeqC5mEUH1K67oYl5Wy9RNIzKjwLAM=", "subType": "00" } }, { "$binary": { "base64": "6vrp4wWDtHEgHWR99I70WVDzevg1Fk/Pw5U8gUDa0OU=", "subType": "00" } } ] }, { "_id": 1, "encryptedDecimalPrecision": { "$$type": "binData" }, "__safeContent__": [ { "$binary": { "base64": "DLCAJs+W2PL2DV5YChCL6dYrQNr+j4p3L7xhVaub4ic=", "subType": "00" } }, { "$binary": { "base64": "V6knyt7Zq2CG3++l75UtBx2m32iGAPjHiAe439Bf02w=", "subType": "00" } }, { "$binary": { "base64": "F08nMDWDZc+DbWM7XCEJNNCEYyinRmrvGP7EWhmp4is=", "subType": "00" } }, { "$binary": { "base64": "cXH4688amcDc8kZOJq4UP8cE3R58Zl7e+Qo/1jyspps=", "subType": "00" } }, { "$binary": { "base64": "uURBxvTp3FBCVkd+LPqyuY7d6rMW6SGIJQEPY/wtkZI=", "subType": "00" } }, { "$binary": { "base64": "jG3hax1L3RBp9t38vUt53FsBxgr/+Si/vVISpAylYpE=", "subType": "00" } }, { "$binary": { "base64": "kwtIW8MhH9Ky5xNjBx8gFA/SHh2YVphie7g5FGBzals=", "subType": "00" } }, { "$binary": { "base64": "FHflwFuEMu4xX0ZApHi+pdlBH+oevAtXckCUb5Wv0xU=", "subType": "00" } }, { "$binary": { "base64": "0OKSXELxPP85SBVwDGf3LtMEQCJ8TTkFUl/+6jlkdb0=", "subType": "00" } }, { "$binary": { "base64": "25j9sQXZCihCmHKvTHgaBsAVZFcGPn7JjHdrCGlwyyw=", "subType": "00" } }, { "$binary": { "base64": "uEw0lpQtBppR3vqV9j9+NQRSBF1BzZukb8c9IhyWvxc=", "subType": "00" } }, { "$binary": { "base64": "zVhZ7Q59O087ji49oMJvBIgeir2oqvUpnh4p53GcTow=", "subType": "00" } }, { "$binary": { "base64": "dowrzKs+qJhRMZyKDbhjXbuX43FbmUKOaw9I8YlOZDw=", "subType": "00" } }, { "$binary": { "base64": "ep5B6cska6THLIF7Mn3tn3RvV9EiwLSt0eZM/CLRUDc=", "subType": "00" } }, { "$binary": { "base64": "URNp/YmmDh5wIZUfAzzgPyJeMNiVx9PMsz52DZRujGY=", "subType": "00" } }, { "$binary": { "base64": "wlM4IAQhhKQEzoVqS8b1Ddd50GB95OFb9LnzOwyjCP4=", "subType": "00" } } ] } ] } } } ] } fle2v2-Range-Double-Aggregate.json000066400000000000000000001363761462766011000352640ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/client-side-encryption/spec/legacy{ "runOn": [ { "minServerVersion": "7.0.0", "topology": [ "replicaset", "sharded", "load-balanced" ] } ], "database_name": "default", "collection_name": "default", "data": [], "encrypted_fields": { "fields": [ { "keyId": { "$binary": { "base64": "EjRWeBI0mHYSNBI0VniQEg==", "subType": "04" } }, "path": "encryptedDoubleNoPrecision", "bsonType": "double", "queries": { "queryType": "rangePreview", "contention": { "$numberLong": "0" }, "sparsity": { "$numberLong": "1" } } } ] }, "key_vault_data": [ { "_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" } } ], "tests": [ { "description": "FLE2 Range Double. Aggregate.", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "local": { "key": { "$binary": { "base64": "Mng0NCt4ZHVUYUJCa1kxNkVyNUR1QURhZ2h2UzR2d2RrZzh0cFBwM3R6NmdWMDFBMUN3YkQ5aXRRMkhGRGdQV09wOGVNYUMxT2k3NjZKelhaQmRCZGJkTXVyZG9uSjFk", "subType": "00" } } } } } }, "operations": [ { "name": "insertOne", "arguments": { "document": { "_id": 0, "encryptedDoubleNoPrecision": { "$numberDouble": "0" } } } }, { "name": "insertOne", "arguments": { "document": { "_id": 1, "encryptedDoubleNoPrecision": { "$numberDouble": "1" } } } }, { "name": "aggregate", "arguments": { "pipeline": [ { "$match": { "encryptedDoubleNoPrecision": { "$gt": { "$numberDouble": "0" } } } } ] }, "result": [ { "_id": 1, "encryptedDoubleNoPrecision": { "$numberDouble": "1" } } ] } ], "expectations": [ { "command_started_event": { "command": { "listCollections": 1, "filter": { "name": "default" } }, "command_name": "listCollections" } }, { "command_started_event": { "command": { "find": "datakeys", "filter": { "$or": [ { "_id": { "$in": [ { "$binary": { "base64": "EjRWeBI0mHYSNBI0VniQEg==", "subType": "04" } } ] } }, { "keyAltNames": { "$in": [] } } ] }, "$db": "keyvault", "readConcern": { "level": "majority" } }, "command_name": "find" } }, { "command_started_event": { "command": { "insert": "default", "documents": [ { "_id": 0, "encryptedDoubleNoPrecision": { "$$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": "encryptedDoubleNoPrecision", "bsonType": "double", "queries": { "queryType": "rangePreview", "contention": { "$numberLong": "0" }, "sparsity": { "$numberLong": "1" } } } ] } } } }, "command_name": "insert" } }, { "command_started_event": { "command": { "insert": "default", "documents": [ { "_id": 1, "encryptedDoubleNoPrecision": { "$$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": "encryptedDoubleNoPrecision", "bsonType": "double", "queries": { "queryType": "rangePreview", "contention": { "$numberLong": "0" }, "sparsity": { "$numberLong": "1" } } } ] } } } }, "command_name": "insert" } }, { "command_started_event": { "command": { "aggregate": "default", "pipeline": [ { "$match": { "encryptedDoubleNoPrecision": { "$gt": { "$binary": { "base64": "DYckAAADcGF5bG9hZABXJAAABGcAQyQAAAMwAH0AAAAFZAAgAAAAAHgYoMGjEE6fAlAhICv0+doHcVX8CmMVxyq7+jlyGrvmBXMAIAAAAAC/5MQZgTHuIr/O5Z3mXPvqrom5JTQ8IeSpQGhO9sB+8gVsACAAAAAAuPSXVmJUAUpTQg/A9Bu1hYczZF58KEhVofakygbsvJQAAzEAfQAAAAVkACAAAAAA2kiWNvEc4zunJ1jzvuClFC9hjZMYruKCqAaxq+oY8EAFcwAgAAAAACofIS72Cm6s866UCk+evTH3CvKBj/uZd72sAL608rzTBWwAIAAAAADuCQ/M2xLeALF0UFZtJb22QGOhHmJv6xoO+kZIHcDeiAADMgB9AAAABWQAIAAAAABkfoBGmU3hjYBvQbjNW19kfXneBQsQQPRfUL3UAwI2cAVzACAAAAAAUpK2BUOqX/DGdX5YJniEZMWkofxHqeAbXceEGJxhp8AFbAAgAAAAAKUaLzIldNIZv6RHE+FwbMjzcNHqPESwF/37mm43VPrsAAMzAH0AAAAFZAAgAAAAAFNprhQ3ZwIcYbuzLolAT5n/vc14P9kUUQComDu6eFyKBXMAIAAAAAAcx9z9pk32YbPV/sfPZl9ALIEVsqoLXgqWLVK/tP+heAVsACAAAAAA/qxvuvJbAHwwhfrPVpmCFzNvg2cU/NXaWgqgYUZpgXwAAzQAfQAAAAVkACAAAAAAODI+pB2pCuB+YmNEUAgtMfNdt3DmSkrJ96gRzLphgb8FcwAgAAAAAAT7dewFDxUDECQ3zVq75/cUN4IP+zsqhkP5+czUwlJIBWwAIAAAAACFGeOtd5zBXTJ4JYonkn/HXZfHipUlqGwIRUcH/VTatwADNQB9AAAABWQAIAAAAACNAk+yTZ4Ewk1EnotQK8O3h1gg9I7pr9q2+4po1iJVgAVzACAAAAAAUj/LesmtEsgqYVzMJ67umVA11hJTdDXwbxDoQ71vWyUFbAAgAAAAABlnhpgTQ0WjLb5u0b/vEydrCeFjVynKd7aqb+UnvVLeAAM2AH0AAAAFZAAgAAAAAD/FIrGYFDjyYmVb7oTMVwweWP7A6F9LnyIuNO4MjBnXBXMAIAAAAACIZgJCQRZu7NhuNMyOqCn1tf+DfU1qm10TPCfj5JYV3wVsACAAAAAA5hmY4ptuNxULGf87SUFXQWGAONsL9U29duh8xqsHtxoAAzcAfQAAAAVkACAAAAAAciRW40ORJLVwchOEpz87Svb+5toAFM6LxDWv928ECwQFcwAgAAAAAN0dipyESIkszfjRzdDi8kAGaa2Hf4wrPAtiWwboZLuxBWwAIAAAAAANr4o/+l1OIbbaX5lZ3fQ/WIeOcEXjNI1F0WbSgQrzaQADOAB9AAAABWQAIAAAAACZqAyCzYQupJ95mrBJX54yIz9VY7I0WrxpNYElCI4dTQVzACAAAAAA/eyJb6d1xfE+jJlVXMTD3HS/NEYENPVKAuj56Dr2dSEFbAAgAAAAANkSt154Or/JKb31VvbZFV46RPgUp8ff/hcPORL7PpFBAAM5AH0AAAAFZAAgAAAAAI5bm3YO0Xgf0VT+qjVTTfvckecM3Cwqj7DTKZXf8/NXBXMAIAAAAAD/m+h8fBhWaHm6Ykuz0WX1xL4Eme3ErLObyEVJf8NCywVsACAAAAAAfb1VZZCqs2ivYbRzX4p5CtaCkKW+g20Pr57FWXzEZi8AAzEwAH0AAAAFZAAgAAAAANqo4+p6qdtCzcB4BX1wQ6llU7eFBnuu4MtZwp4B6mDlBXMAIAAAAAAGiz+VaukMZ+6IH4jtn4KWWdKK4/W+O+gRioQDrfzpMgVsACAAAAAAG4YYkTp80EKo59mlHExDodRQFR7njhR5dmISwUJ6ukAAAzExAH0AAAAFZAAgAAAAAPrFXmHP2Y4YAm7b/aqsdn/DPoDkv7B8egWkfe23XsM1BXMAIAAAAAAGhwpKAr7skeqHm3oseSbO7qKNhmYsuUrECBxJ5k+D2AVsACAAAAAAAqPQi9luYAu3GrFCEsVjd9z2zIDcp6SPTR2w6KQEr+IAAzEyAH0AAAAFZAAgAAAAABzjYxwAjXxXc0Uxv18rH8I3my0Aguow0kTwKyxbrm+cBXMAIAAAAADVbqJVr6IdokuhXkEtXF0C2gINLiAjMVN20lE20Vmp2QVsACAAAAAAD7K1Fx4gFaaizkIUrf+EGXQeG7QX1jadhGc6Ji471H8AAzEzAH0AAAAFZAAgAAAAAFMm2feF2fFCm/UC6AfIyepX/xJDSmnnolQIBnHcPmb5BXMAIAAAAABLI11kFrQoaNVZFmq/38aRNImPOjdJh0Lo6irI8M/AaAVsACAAAAAAOWul0oVqJ9CejD2RqphhTC98DJeRQy5EwbNerU2+4l8AAzE0AH0AAAAFZAAgAAAAAJvXB3KyNiNtQko4SSzo/9b2qmM2zU9CQTTDfLSBWMgRBXMAIAAAAAAvjuVP7KsLRDeqVqRziTKpBrjVyqKiIbO9Gw8Wl2wFTAVsACAAAAAADlE+oc1ins+paNcaOZJhBlKlObDJ4VQORWjFYocM4LgAAzE1AH0AAAAFZAAgAAAAAPGdcxDiid8z8XYnfdDivNMYVPgBKdGOUw6UStU+48CdBXMAIAAAAAARj6g1Ap0eEfuCZ4X2TsEw+Djrhto3fA5nLwPaY0vCTgVsACAAAAAAoHqiwGOUkBu8SX5U1yHho+UIFdSN2MdQN5s6bQ0EsJYAAzE2AH0AAAAFZAAgAAAAAP5rGPrYGt3aKob5f/ldP0qrW7bmWvqnKY4QwdDWz400BXMAIAAAAADTQkW2ymaaf/bhteOOGmSrIR97bAnJx+yN3yMj1bTeewVsACAAAAAADyQnHGH2gF4w4L8axUsSTf6Ubk7L5/eoFOJk12MtZAoAAzE3AH0AAAAFZAAgAAAAAAlz6wJze5UkIxKpJOZFGCOf3v2KByWyI6NB6JM9wNcBBXMAIAAAAABUC7P/neUIHHoZtq0jFVBHY75tSFYr1Y5S16YN5XxC1QVsACAAAAAAgvxRbXDisNnLY3pfsjDdnFLtkvYUC4lhA68eBXc7KAwAAzE4AH0AAAAFZAAgAAAAAFJ8AtHcjia/9Y5pLEc3qVgH5xKiXw12G9Kn2A1EY8McBXMAIAAAAAAxe7Bdw7eUSBk/oAawa7uicTEDgXLymRNhBy1LAxhDvwVsACAAAAAAxKPaIBKVx3jTA+R/el7P7AZ7efrmTGjJs3Hj/YdMddwAAzE5AH0AAAAFZAAgAAAAAO8uwQUaKFb6vqR3Sv3Wn4QAonC2exOC9lGG1juqP5DtBXMAIAAAAABZf1KyJgQg8/Rf5c02DgDK2aQu0rNCOvaL60ohDHyY+gVsACAAAAAAqyEjfKC8lYoIfoXYHUqHZPoaA6EK5BAZy5dxXZmay4kAAzIwAH0AAAAFZAAgAAAAAE8YtqyRsGCeiR6hhiyisR/hccmK4nZqIMzO4lUBmEFzBXMAIAAAAAC1UYOSKqAeG1UJiKjWFVskRhuFKpj9Ezy+lICZvFlN5AVsACAAAAAA6Ct9nNMKyRazn1OKnRKagm746CGu+jyhbL1qJnZxGi0AAzIxAH0AAAAFZAAgAAAAAPhCrMausDx1QUIEqp9rUdRKyM6a9AAx7jQ3ILIu8wNIBXMAIAAAAACmH8lotGCiF2q9VQxhsS+7LAZv79VUAsOUALaGxE/EpAVsACAAAAAAnc1xCKfdvbUEc8F7XZqlNn1C+hZTtC0I9I3LL06iaNkAAzIyAH0AAAAFZAAgAAAAAOBi/GAYFcstMSJPgp3VkMiuuUUCrZytvqYaU8dwm8v2BXMAIAAAAACEZSZVyD3pKzGlbdwlYmWQhHHTV5SnNLknl2Gw8IaUTQVsACAAAAAAfsLZsEDcWSuNsIo/TD1ReyQW75HPMgmuKZuWFOLKRLoAAzIzAH0AAAAFZAAgAAAAAIQuup+YGfH3mflzWopN8J1X8o8a0d9CSGIvrA5HOzraBXMAIAAAAADYvNLURXsC2ITMqK14LABQBI+hZZ5wNf24JMcKLW+84AVsACAAAAAACzfjbTBH7IwDU91OqLAz94RFkoqBOkzKAqQb55gT4/MAAzI0AH0AAAAFZAAgAAAAAKsh0ADyOnVocFrOrf6MpTrNvAj8iaiE923DPryu124gBXMAIAAAAADg24a8NVE1GyScc6tmnTbmu5ulzO+896fE92lN08MeswVsACAAAAAAaPxcOIxnU7But88/yadOuDJDMcCywwrRitaxMODT4msAAzI1AH0AAAAFZAAgAAAAAKkVC2Y6HtRmv72tDnPUSjJBvse7SxLqnr09/Uuj9sVVBXMAIAAAAABYNFUkH7ylPMN+Bc3HWX1e0flGYNbtJNCY9SltJCW/UAVsACAAAAAAZYK/f9H4OeihmpiFMH7Wm7uLvs2s92zNA8wyrNZTsuMAAzI2AH0AAAAFZAAgAAAAADDggcwcb/Yn1Kk39sOHsv7BO/MfP3m/AJzjGH506Wf9BXMAIAAAAAAYZIsdjICS0+BDyRUPnrSAZfPrwtuMaEDEn0/ijLNQmAVsACAAAAAAGPnYVvo2ulO9z4LGd/69NAklfIcZqZvFX2KK0s+FcTUAAzI3AH0AAAAFZAAgAAAAAEWY7dEUOJBgjOoWVht1wLehsWAzB3rSOBtLgTuM2HC8BXMAIAAAAAAAoswiHRROurjwUW8u8D5EUT+67yvrgpB/j6PzBDAfVwVsACAAAAAA6NhRTYFL/Sz4tao7vpPjLNgAJ0FX6P/IyMW65qT6YsMAAzI4AH0AAAAFZAAgAAAAAPZaapeAUUFPA7JTCMOWHJa9lnPFh0/gXfAPjA1ezm4ZBXMAIAAAAACmJvLY2nivw7/b3DOKH/X7bBXjJwoowqb1GtEFO3OYgAVsACAAAAAA/JcUoyKacCB1NfmH8vYqC1f7rd13KShrQqV2r9QBP44AAzI5AH0AAAAFZAAgAAAAAK00u6jadxCZAiA+fTsPVDsnW5p5LCr4+kZZZOTDuZlfBXMAIAAAAAAote4zTEYMDgaaQbAdN8Dzv93ljPLdGjJzvnRn3KXgtQVsACAAAAAAxXd9Mh6R3mnJy8m7UfqMKi6oD5DlZpkaOz6bEjMOdiwAAzMwAH0AAAAFZAAgAAAAAFbgabdyymiEVYYwtJSWa7lfl/oYuj/SukzJeDOR6wPVBXMAIAAAAADAFGFjS1vPbN6mQEhkDYTD6V2V23Ys9gUEUMGNvMPkaAVsACAAAAAAL/D5Sze/ZoEanZLK0IeEkhgVkxEjMWVCfmJaD3a8uNIAAzMxAH0AAAAFZAAgAAAAABNMR6UBv2E627CqLtQ/eDYx7OEwQ7JrR4mSHFa1N8tLBXMAIAAAAAAxH4gucI4UmNVB7625C6hFSVCuIpJO3lusJlPuL8H5EQVsACAAAAAAVLHNg0OUVqZ7WGOP53BkTap9FOw9dr1P4J8HxqFqU04AAzMyAH0AAAAFZAAgAAAAAG8cd6WBneNunlqrQ2EmNf35W7OGObGq9WL4ePX+LUDmBXMAIAAAAAAjJ2+sX87NSis9hBsgb1QprVRnO7Bf+GObCGoUqyPE4wVsACAAAAAAs9c9SM49/pWmyUQKslpt3RTMBNSRppfNO0JBvUqHPg0AAzMzAH0AAAAFZAAgAAAAAFWOUGkUpy8yf6gB3dio/aOfRKh7XuhvsUj48iESFJrGBXMAIAAAAAAY7sCDMcrUXvNuL6dO0m11WyijzXZvPIcOKob6IpC4PQVsACAAAAAAJOP+EHz6awDb1qK2bZQ3kTV7wsj5Daj/IGAWh4g7omAAAzM0AH0AAAAFZAAgAAAAAGUrIdKxOihwNmo6B+aG+Ag1qa0+iqdksHOjQj+Oy9bZBXMAIAAAAABwa5dbI2KmzBDNBTQBEkjZv4sPaeRkRNejcjdVymRFKQVsACAAAAAA4ml/nm0gJNTcJ4vuD+T2Qfq2fQZlibJp/j6MOGDrbHMAAzM1AH0AAAAFZAAgAAAAAOx89xV/hRk64/CkM9N2EMK6aldII0c8smdcsZ46NbP8BXMAIAAAAADBF6tfQ+7q9kTuLyuyrSnDgmrdmrXkdhl980i1KHuGHgVsACAAAAAACUqiFqHZdGbwAA+hN0YUE5zFg+H+dabIB4dj5/75W/YAAzM2AH0AAAAFZAAgAAAAAMkN0L1oQWXhjwn9rAdudcYeN8/5VdCKU8cmDt7BokjsBXMAIAAAAAAT62pGXoRwExe9uvgYOI0hg5tOxilrWfoEmT0SMglWJwVsACAAAAAAlVz4dhiprSbUero6JFfxzSJGclg63oAkAmgbSwbcYxIAAzM3AH0AAAAFZAAgAAAAANxfa4xCoaaB7k1C1RoH1LBhsCbN2yEq15BT9b+iqEC4BXMAIAAAAACAX9LV8Pemfw7NF0iB1/85NzM1Ef+1mUfyehacUVgobQVsACAAAAAAVq4xpbymLk0trPC/a2MvB39I7hRiX8EJsVSI5E5hSBkAAzM4AH0AAAAFZAAgAAAAAOYIYoWkX7dGuyKfi3XssUlc7u/gWzqrR9KMkikKVdmSBXMAIAAAAABVF2OYjRTGi9Tw8XCAwZWLpX35Yl271TlNWp6N/nROhAVsACAAAAAA0nWwYzXQ1+EkDvnGq+SMlq20z+j32Su+i/A95SggPb4AAzM5AH0AAAAFZAAgAAAAAIy0+bXZi10QC+q7oSOLXK5Fee7VEk/qHSXukfeVIfgzBXMAIAAAAAAQ3IIV/JQCHW95AEbH5zGIHtJqyuPjWPMIZ+VmQHlxEwVsACAAAAAAp0jYsyohKv9Pm+4k+DplEGbl9WLZpAJzitrcDj4CNsMAAzQwAH0AAAAFZAAgAAAAAL5SOJQ3LOhgdXJ5v086NNeAl1qonQnchObdpZJ1kHeEBXMAIAAAAAA+tEqTXODtik+ydJZSnUqXF9f18bPeze9eWtR7ExZJgQVsACAAAAAAbrkZCVgB9Qsp4IAbdf+bD4fT6Boqk5UtuA/zhNrh1y0AAzQxAH0AAAAFZAAgAAAAAKl8zcHJRDjSjJeV/WvMxulW1zrTFtaeBy/aKKhadc6UBXMAIAAAAADBdWQl5SBIvtZZLIHszePwkO14W1mQ0izUk2Ov21cPNAVsACAAAAAAHErCYycpqiIcCZHdmPL1hi+ovLQk4TAvENpfLdTRamQAAzQyAH0AAAAFZAAgAAAAAFvotcNaoKnVt5CBCOPwjexFO0WGWuaIGL6H/6KSau+6BXMAIAAAAAD2y2mBN5xPu5PJoY2zcr0GnQDtHRBogA5+xzIxccE9fwVsACAAAAAAdS34xzJesnUfxLCcc1U7XzUqLy8MAzV/tcjbqaD3lkMAAzQzAH0AAAAFZAAgAAAAAPezU0/vNT4Q4YKbTbaeHqcwNLT+IjW/Y9QFpIooihjPBXMAIAAAAACj2x4O4rHter8ZnTws5LAP9jJ/6kk9C/V3vL50LoFZHAVsACAAAAAAQdBDF3747uCVP5lB/zr8VmzxJfTSZHBKeIgm5FyONXwAAzQ0AH0AAAAFZAAgAAAAAMqpayM2XotEFmm0gwQd9rIzApy0X+7HfOhNk6VU7F5lBXMAIAAAAACJR9+q5T9qFHXFNgGbZnPubG8rkO6cwWhzITQTmd6VgwVsACAAAAAAOZLQ6o7e4mVfDzbpQioa4d3RoTvqwgnbmc5Qh2wsZuoAAzQ1AH0AAAAFZAAgAAAAANCeyW+3oebaQk+aqxNVhAcT/BZ5nhsTVdKS3tMrLSvWBXMAIAAAAADxRFMDhkyuEc++WnndMfoUMLNL7T7rWoeblcrpSI6soQVsACAAAAAAdBuBMJ1lxt0DRq9pOZldQqchLs3B/W02txcMLD490FEAAzQ2AH0AAAAFZAAgAAAAAIbo5YBTxXM7HQhl7UP9NNgpPGFkBx871r1B65G47+K8BXMAIAAAAAC21dJSxnEhnxO5gzN5/34BL4von45e1meW92qowzb8fQVsACAAAAAAm3Hk2cvBN0ANaR5jzeZE5TsdxDvJCTOT1I01X7cNVaYAAzQ3AH0AAAAFZAAgAAAAABm/6pF96j26Jm7z5KkY1y33zcAEXLx2n0DwC03bs/ixBXMAIAAAAAD01OMvTZI/mqMgxIhA5nLs068mW+GKl3OW3ilf2D8+LgVsACAAAAAAaLvJDrqBESTNZSdcXsd+8GXPl8ZkUsGpeYuyYVv/kygAAzQ4AH0AAAAFZAAgAAAAAJ/D3+17gaQdkBqkL2wMwccdmCaVOtxzIkM8VyI4xI5zBXMAIAAAAAAggLVmkc5u+YzBR+oNE+XgLVp64fC6MzUb/Ilu/Jsw0AVsACAAAAAACz3HVKdWkx82/kGbVpcbAeZtsj2R5Zr0dEPfle4IErkAAzQ5AH0AAAAFZAAgAAAAAJMRyUW50oaTzspS6A3TUoXyC3gNYQoShUGPakMmeVZrBXMAIAAAAACona2Pqwt4U2PmFrtmu37jB9kQ/12okyAVtYa8TQkDiQVsACAAAAAAltJJKjCMyBTJ+4PkdDCPJdeX695P8P5h7WOZ+kmExMAAAzUwAH0AAAAFZAAgAAAAAByuYl8dBvfaZ0LO/81JW4hYypeNmvLMaxsIdvqMPrWoBXMAIAAAAABNddwobOUJzm9HOUD8BMZJqkNCUCqstHZkC76FIdNg9AVsACAAAAAAQQOkIQtkyNavqCnhQbNg3HfqrJdsAGaoxSJePJl1qXsAAzUxAH0AAAAFZAAgAAAAAHEzLtfmF/sBcYPPdj8867VmmQyU1xK9I/3Y0478azvABXMAIAAAAAAcmyFajZPnBTbO+oLInNwlApBocUekKkxz2hYFeSlQ+gVsACAAAAAAZ6IkrOVRcC8vSA6Vb4fPWZJrYexXhEabIuYIeXNsCSgAAzUyAH0AAAAFZAAgAAAAAJam7JYsZe2cN20ZYm2W3v1pisNt5PLiniMzymBLWyMtBXMAIAAAAABxCsKVMZMTn3n+R2L7pVz5nW804r8HcK0mCBw3jUXKXAVsACAAAAAA7j3JGnNtR64P4dJLeUoScFRGfa8ekjh3dvhw46sRFk0AAzUzAH0AAAAFZAAgAAAAAMXrXx0saZ+5gORmwM2FLuZG6iuO2YS+1IGPoAtDKoKBBXMAIAAAAADIQsxCr8CfFKaBcx8kIeSywnGh7JHjKRJ9vJd9x79y7wVsACAAAAAAcvBV+SykDYhmRFyVYwFYB9oBKBSHr55Jdz2cXeowsUQAAzU0AH0AAAAFZAAgAAAAACbzcUD3INSnCRspOKF7ubne74OK9L0FTZvi9Ay0JVDYBXMAIAAAAADPebVQH8Btk9rhBIoUOdSAdpPvz7qIY4UC2i6IGisSAQVsACAAAAAAiBunJi0mPnnXdnldiq+If8dcb/n6apHnaIFt+oyYO1kAAzU1AH0AAAAFZAAgAAAAACUc2CtD1MK/UTxtv+8iA9FoHEyTwdl43HKeSwDw2Lp5BXMAIAAAAACCIduIdw65bQMzRYRfjBJj62bc69T4QqH4QoWanwlvowVsACAAAAAAM0TV7S+aPVVzJOQ+cpSNKHTwyQ0mWa8tcHzfk3nR+9IAAzU2AH0AAAAFZAAgAAAAAHSaHWs/dnmI9sc7nB50VB2Bzs0kHapMHCQdyVEYY30TBXMAIAAAAACkV22lhEjWv/9/DubfHBAcwJggKI5mIbSK5L2nyqloqQVsACAAAAAAS19m7DccQxgryOsBJ3GsCs37yfQqNi1G+S6fCXpEhn4AAzU3AH0AAAAFZAAgAAAAAAL8jhNBG0KXXZhmZ0bPXtfgapJCB/AI+BEHB0eZ3C75BXMAIAAAAADHx/fPa639EBmGV5quLi8IQT600ifiKSOhTDOK19DnzwVsACAAAAAAlyLTDVkHxbayklD6Qymh3odIK1JHaOtps4f4HR+PcDgAAzU4AH0AAAAFZAAgAAAAAAxgeclNl09H7HvzD1oLwb2YpFca5eaX90uStYXHilqKBXMAIAAAAACMU5pSxzIzWlQxHyW170Xs9EhD1hURASQk+qkx7K5Y6AVsACAAAAAAJbMMwJfNftA7Xom8Bw/ghuZmSa3x12vTZxBUbV8m888AAzU5AH0AAAAFZAAgAAAAABmO7QD9vxWMmFjIHz13lyOeV6vHT6mYCsWxF7hb/yOjBXMAIAAAAACT9lmgkiqzuWG24afuzYiCeK9gmJqacmxAruIukd0xEAVsACAAAAAAZa0/FI/GkZR7CtX18Xg9Tn9zfxkD0UoaSt+pIO5t1t4AAzYwAH0AAAAFZAAgAAAAAB89SjLtDJkqEghRGyj6aQ/2qvWLNuMROoXmzbYbCMKMBXMAIAAAAAC8sywgND+CjhVTF6HnRQeay8y9/HnVzDI42dEPah28LQVsACAAAAAAoxv7UKh0RqUAWcOsQvU123zO1qZn73Xfib0qncZCB34AAzYxAH0AAAAFZAAgAAAAABN2alGq9Aats1mwERNGwL/fIwZSvVCe9/8XMHTFlpUpBXMAIAAAAACuDPjJgvvbBYhbLpjMiWUCsVppiYrhvR+yMysNPN8cZAVsACAAAAAAKpADjc4bzIZMi9Q/+oe0EMRJHYQt6dlo1x/lRquagqkAAzYyAH0AAAAFZAAgAAAAAL8YB6VAqGBiWD4CBv16IBscg5J7VQCTZu87n6pj+86KBXMAIAAAAAAmxm8e68geeyAdUjSMWBHzUjneVB0pG9TBXIoE6467hAVsACAAAAAAV76JZAlYpgC/Zl8awx2ArCg1uuyy2XVTSkp0wUMi/7UAAzYzAH0AAAAFZAAgAAAAAL4yLkCTV5Dmxa5toBu4JT8ge/cITAaURIOuFuOtFUkeBXMAIAAAAAAXoFNQOMGkAj7qEJP0wQafmFSXgWGeorDVbwyOxWLIsgVsACAAAAAAc4Un6dtIFe+AQ+RSfNWs3q63RTHhmyc+5GKRRdpWRv8AAzY0AH0AAAAFZAAgAAAAAEU8DoUp46YtYjNFS9kNXwdYxQ9IW27vCTb+VcqqfnKNBXMAIAAAAADe7vBOgYReE8X78k5ARuUnv4GmzPZzg6SbConf4L2G3wVsACAAAAAA78YHWVkp6HbZ0zS4UL2z/2pj9vPDcMDt7zTv6NcRsVsAAzY1AH0AAAAFZAAgAAAAAPa4yKTtkUtySuWo1ZQsp2QXtPb5SYqzA5vYDnS1P6c0BXMAIAAAAADKnF58R1sXlHlsHIvCBR3YWW/qk54z9CTDhZydkD1cOQVsACAAAAAAHW3ERalTFWKMzjuXF3nFh0pSrQxM/ojnPbPhc4v5MaQAAzY2AH0AAAAFZAAgAAAAAN5WJnMBmfgpuQPyonmY5X6OdRvuHw4nhsnGRnFAQ95VBXMAIAAAAACwftzu7KVV1rmGKwXtJjs3cJ1gE3apr8+N0SAg1F2cHwVsACAAAAAATDW0reyaCjbJuVLJzbSLx1OBuBoQu+090kgW4RurVacAAzY3AH0AAAAFZAAgAAAAACHvDsaPhoSb6DeGnKQ1QOpGYAgK82qpnqwcmzSeWaJHBXMAIAAAAABRq3C5+dOfnkAHM5Mg5hPB3O4jhwQlBgQWLA7Ph5bhgwVsACAAAAAAqkC8zYASvkVrp0pqmDyFCkPaDmD/ePAJpMuNOCBhni8AAzY4AH0AAAAFZAAgAAAAAOBePJvccPMJmy515KB1AkXF5Pi8NOG4V8psWy0SPRP+BXMAIAAAAAB3dOJG9xIDtEKCRzeNnPS3bFZepMj8UKBobKpSoCPqpgVsACAAAAAAPG3IxQVOdZrr509ggm5FKizWWoZPuVtOgOIGZ3m+pdEAAzY5AH0AAAAFZAAgAAAAABUvRrDQKEXLMdhnzXRdhiL6AGNs2TojPky+YVLXs+JnBXMAIAAAAAD1kYicbEEcPzD4QtuSYQQWDPq8fuUWGddpWayKn3dT9QVsACAAAAAA9+Sf7PbyFcY45hP9oTfjQiOUS3vEIAT8C0vOHymwYSUAAzcwAH0AAAAFZAAgAAAAAOvSnpujeKNen4pqc2HR63C5s5oJ1Vf4CsbKoYQvkwl5BXMAIAAAAACw2+vAMdibzd2YVVNfk81yXkFZP0WLJ82JBxJmXnYE+QVsACAAAAAArQ/E1ACyhK4ZyLqH9mNkCU7WClqRQTGyW9tciSGG/EMAAzcxAH0AAAAFZAAgAAAAAAo0xfGG7tJ3GWhgPVhW5Zn239nTD3PadShCNRc9TwdNBXMAIAAAAADZh243oOhenu0s/P/5KZLBDh9ADqKHtSWcXpO9D2sIjgVsACAAAAAAlgTPaoQKz+saU8rwCT3UiNOdG6hdpjzFx9GBn08ZkBEAABJjbQAAAAAAAAAAAAAQcGF5bG9hZElkAAAAAAAQZmlyc3RPcGVyYXRvcgABAAAAAA==", "subType": "06" } } } } } ], "cursor": {}, "encryptionInformation": { "type": 1, "schema": { "default.default": { "escCollection": "enxcol_.default.esc", "ecocCollection": "enxcol_.default.ecoc", "fields": [ { "keyId": { "$binary": { "base64": "EjRWeBI0mHYSNBI0VniQEg==", "subType": "04" } }, "path": "encryptedDoubleNoPrecision", "bsonType": "double", "queries": { "queryType": "rangePreview", "contention": { "$numberLong": "0" }, "sparsity": { "$numberLong": "1" } } } ] } } } }, "command_name": "aggregate" } } ], "outcome": { "collection": { "data": [ { "_id": 0, "encryptedDoubleNoPrecision": { "$$type": "binData" }, "__safeContent__": [ { "$binary": { "base64": "5nRutVIyq7URVOVtbE4vM01APSIajAVnsShMwjBlzkM=", "subType": "00" } }, { "$binary": { "base64": "6YrBn2ofIw1b5ooakrLOwF41BWrps8OO0H9WH4/rtlE=", "subType": "00" } }, { "$binary": { "base64": "n+XAuFnP8Dov9TnhGFxNx0K/MnVM9WbJ7RouEu0ndO0=", "subType": "00" } }, { "$binary": { "base64": "yRXojuVdn5GQtD97qYlaCL6cOLmZ7Cvcb3wFjkLUIdM=", "subType": "00" } }, { "$binary": { "base64": "DuIkdRPITRs55I4SZmgomAHCIsDQmXRhW8+MOznkzSk=", "subType": "00" } }, { "$binary": { "base64": "SsBk+Et1lTbU+QRPx+xyJ/jMkmfG+QCvQEpip2YYrzA=", "subType": "00" } }, { "$binary": { "base64": "crCIzOd8KhHvvUlX7M1v9bhvU4pLdTc+X2SuqoKU5Ek=", "subType": "00" } }, { "$binary": { "base64": "YOWdCw4UrqnxkAaVjqmC4sKQDMVMHEpFGnlxpxdaU6E=", "subType": "00" } }, { "$binary": { "base64": "M3SShp81Ff8tQ632qKbv9MUcN6wjDaBReI0VXNu6Xh4=", "subType": "00" } }, { "$binary": { "base64": "gzHlSPxpM0hT75kQvWFzGlOxKvDoiKQZOr19V6l2zXI=", "subType": "00" } }, { "$binary": { "base64": "s3JnppOGYw9SL2Q1kMAZs948v2F5PrpXjGei/HioDWs=", "subType": "00" } }, { "$binary": { "base64": "cG6+3Gk/zEH68P/uuuwiAUVCuyJwa1LeV+t29FlPPAo=", "subType": "00" } }, { "$binary": { "base64": "dupdvR3AyJtM+g9NDKiaLVOtGca387JQp8w+V03m7Ig=", "subType": "00" } }, { "$binary": { "base64": "JqEQc5svj2jTvZ6LLA5ivE+kTb/0aRemSEmxk4G7Zrg=", "subType": "00" } }, { "$binary": { "base64": "szcXXXKnob+p3SoM4yED2R920LeJ7cVsclPMFTe4CeI=", "subType": "00" } }, { "$binary": { "base64": "o1QoGVXmuBdHwHm7aCtGMlMVKrjFdYvJXpoq6uhIAZ0=", "subType": "00" } }, { "$binary": { "base64": "Jfm5wPlqqLCJRGQIqRq2NGmpn7s0Vrih2H3YAOoI2YU=", "subType": "00" } }, { "$binary": { "base64": "zMHLb8ARbsYo8Ld05bqnGFf1Usha6EGb8QKwdSAyps0=", "subType": "00" } }, { "$binary": { "base64": "yQdtq9lh5pugL7/i0Bj/PuZUUBUIzf+7wj1rl5y736w=", "subType": "00" } }, { "$binary": { "base64": "wGWVZdO7qIuyDg/BqDgqjgoQ02h5YYgwXQB1oCin2NE=", "subType": "00" } }, { "$binary": { "base64": "by9HMLj6NTEpgztZ5HSN6GxImkXPcaFINYDzgZY33X8=", "subType": "00" } }, { "$binary": { "base64": "tWo0vbasi7bXmn/MsOx13VC1IsWtpx/nYp0uj4iMzdA=", "subType": "00" } }, { "$binary": { "base64": "tQQpndUYd5O87lOtrGjH3wl9VsOK0ray7RMasL90sBM=", "subType": "00" } }, { "$binary": { "base64": "cQjXEDCMsOpKLLf+vlTgIHA+cbSJdzqhbSX9Wvh95aA=", "subType": "00" } }, { "$binary": { "base64": "7yMpU48IxK9SzP2cx3VnTownGEwFmeFofuuFT97SuuY=", "subType": "00" } }, { "$binary": { "base64": "kSOx1kz0CmBgzKQHZlo65ZUY1DIv9A99JRm+Us2y6Ew=", "subType": "00" } }, { "$binary": { "base64": "ubQpdPBe6/xvtr+AcXdfYLSvYCR4ot0tivehkCsupb4=", "subType": "00" } }, { "$binary": { "base64": "xal+iCJ6FTefRQToyoNksc9NCZShyn04NDGi4IYrcoM=", "subType": "00" } }, { "$binary": { "base64": "d7jU4iOK50xHxlkSifcxlZFCM46TSgQzoYivxG3HNLY=", "subType": "00" } }, { "$binary": { "base64": "tJvl2nsBLBVzL3pp6sKWCL4UXeh3q/roYBJjSb74ve0=", "subType": "00" } }, { "$binary": { "base64": "OIUCaKRvIx9t1w6Hxlz1IcQTdPNCfdRNwnnTm10W+X0=", "subType": "00" } }, { "$binary": { "base64": "A9tvzsiElotOUVIB4CqfQp9mAwqvTM35YkmAR170aHA=", "subType": "00" } }, { "$binary": { "base64": "lI8gpK7hpb7c9x4RQugsxMnQay5LZJmwslZdvMx/dcE=", "subType": "00" } }, { "$binary": { "base64": "dNCzh40U0XvdKnSDi3HRQOWQftEsDVqc4uUvsVFGoq8=", "subType": "00" } }, { "$binary": { "base64": "IP+iwEBWBwVVZIdpaMu8k5+soFCz+TZkYn3drKZ9grE=", "subType": "00" } }, { "$binary": { "base64": "pnqyh6e0y5svHkJDShlN9CHV0WvMBE4QbtJpQw5ZCXc=", "subType": "00" } }, { "$binary": { "base64": "elEl42tbVDoRTLjAhZUFEtXiut4b3PVhg/1ZLZSQdtE=", "subType": "00" } }, { "$binary": { "base64": "vHuu2FxwclMHqyE6JBYbTYgbEkB0dqb/JuaxsvfwsmY=", "subType": "00" } }, { "$binary": { "base64": "xTf7NCe3Gf8QpE78HR5OknlLTKfs9J+RN9UZpH6fnso=", "subType": "00" } }, { "$binary": { "base64": "XiWSasRnJAulGR6+LCVD3mwRObXylqYWR9jvpywq12c=", "subType": "00" } }, { "$binary": { "base64": "MZMxEQ5ikx0PG1YFIExv0UnTZogsvgeOEZTpzvBDn4w=", "subType": "00" } }, { "$binary": { "base64": "yZMyMZBDrWbAhvnic7vvIYhmO9m5H2iuv0c8KNZrBzY=", "subType": "00" } }, { "$binary": { "base64": "xxM14hTPY5j0vvcK2C7YAEjzdsfUTFHozHC0hEo1bxI=", "subType": "00" } }, { "$binary": { "base64": "+01rqR1xVwkpGXcstbk1ItJqFVjH6Q8MGxEN3Cm9Y1A=", "subType": "00" } }, { "$binary": { "base64": "xOpLV0Z2VTRJ3iWtnWZcsyjXubTIkYWo31cO+HV1o1k=", "subType": "00" } }, { "$binary": { "base64": "BWUOLqgLBqc5NwxVlSV5H3KFQPXbCp7mdo+jF+8cJqY=", "subType": "00" } }, { "$binary": { "base64": "fuQb1S6xZDGlrEbK+kI23aL53PP1PVNwqICnZNt9Yzg=", "subType": "00" } }, { "$binary": { "base64": "SfscnoibFttahLdPVC4Ee+47ewGFKpDSU7M6HX19bKE=", "subType": "00" } }, { "$binary": { "base64": "rpSW2awybNVeKtat91VFxqbINoTfNhPfQAu+d73Xtf8=", "subType": "00" } }, { "$binary": { "base64": "9M/CP9ccOIIj2LLFmE0GFDO0Ban2wsNalEXfM6+h+1s=", "subType": "00" } }, { "$binary": { "base64": "WrEMG49l1ye4MhXs5ZS9tz8P6h+hDvthIg/2wW9ne1Q=", "subType": "00" } }, { "$binary": { "base64": "ImNhbfeyfH8qIEeA5ic0s3dAQBdzzTBS+CPsNih9vZ0=", "subType": "00" } }, { "$binary": { "base64": "dWP33YDSn04UKJN2ogh2Rui0iW/0q2y18OCDRVcfyoo=", "subType": "00" } }, { "$binary": { "base64": "lYv0isAtfGh6H9tdp3cp2eHU7q2J+uk7QrgcxtK3w7Y=", "subType": "00" } }, { "$binary": { "base64": "VGMoamB/+7zTOYcY/pqJc96xlv2PdW4hwsIAEIslTDQ=", "subType": "00" } }, { "$binary": { "base64": "yNeBWMF7BnD9wVwz2PgJsvWr77QiVvvWUvJF0+fqBug=", "subType": "00" } }, { "$binary": { "base64": "SfpvObJ+tJBXSvqeN7vlOfmhYign635lciYAJIjUtY8=", "subType": "00" } }, { "$binary": { "base64": "dsen4NqjzVGjpjufiTMs3+gqeD09EbnuogPgxrJECwg=", "subType": "00" } }, { "$binary": { "base64": "pxCWVM3sn19NsFEpgHbgLa+PmYlhN3mMiP0Wk8kJhYw=", "subType": "00" } }, { "$binary": { "base64": "q11KNvJszjYIB9n9HcC+N4uz11a3eRj1L3BH9scKMDQ=", "subType": "00" } }, { "$binary": { "base64": "A1PmkgcEToWh1JiVWE6mI5jUu7poxWWuCUt/cgRUUDc=", "subType": "00" } }, { "$binary": { "base64": "qJo3Hu4PJeanL7XEaWXO/n3YsodhZyd+MJOOmB9Kpd8=", "subType": "00" } }, { "$binary": { "base64": "BkBKLO8URFscfRY9Bav/1+L9mLohDgNr/MkZtGiraIs=", "subType": "00" } }, { "$binary": { "base64": "rZq5WA3Hx3xthOyHAJXK//f8pE2qbz7YKu3TIMp9GFY=", "subType": "00" } }, { "$binary": { "base64": "X07a/Lm80p5xd4RFs1dNmw+90tmPDPdGiAKVZkxd4zY=", "subType": "00" } } ] }, { "_id": 1, "encryptedDoubleNoPrecision": { "$$type": "binData" }, "__safeContent__": [ { "$binary": { "base64": "bE1vqWj3KNyM7cCYUv/cnYm8BPaUL3eMp5syTHq6NF4=", "subType": "00" } }, { "$binary": { "base64": "2FIZh/9N+NeJEQwxYIX5ikQT85xJzulBNReXk8PnG/s=", "subType": "00" } }, { "$binary": { "base64": "I93Md7QNPGmEEGYU1+VVCqBPBEvXdqHPtTJtMOn06Yk=", "subType": "00" } }, { "$binary": { "base64": "GecBFQ1PemlECWZWCl7f74vmsL6eB6mzQ9n6tK6FYfs=", "subType": "00" } }, { "$binary": { "base64": "QpjhZl+O1ORifgtCZuWAdcP6OKL7IZ2cA46v8FJcV28=", "subType": "00" } }, { "$binary": { "base64": "FWXI/yZ1M+2fIboeMCDMlp+I2NwPQDtoM/wWselOPYw=", "subType": "00" } }, { "$binary": { "base64": "uk26nvN/LdRLaBphiBgIZzT0sSpoO1z0RdDWRm/xrSA=", "subType": "00" } }, { "$binary": { "base64": "hiiYSH1KZovAULc7rlmEU74wCjzDR+mm6ZnsgvFQjMw=", "subType": "00" } }, { "$binary": { "base64": "hRzvMvWPX0sJme+wck67lwbKDFaWOa+Eyef+JSdc1s4=", "subType": "00" } }, { "$binary": { "base64": "PSx5D+zqC9c295dguX4+EobT4IEzfffdfjzC8DWpB5Q=", "subType": "00" } }, { "$binary": { "base64": "QzfXQCVTjPQv2h21v95HYPq8uCsVJ2tPnjv79gAaM9M=", "subType": "00" } }, { "$binary": { "base64": "XcGDO/dlTcEMLqwcm55UmOqK+KpBmbzZO1LIzX7GPaQ=", "subType": "00" } }, { "$binary": { "base64": "Lf+o4E7YB5ynzUPC6KTyW0lj6Cg9oLIu1Sdd1ODHctA=", "subType": "00" } }, { "$binary": { "base64": "wAuVn02LAVo5Y+TUocvkoenFYWzpu38k0NmGZOsAjS4=", "subType": "00" } }, { "$binary": { "base64": "yJGDtveLbbo/0HtCtiTSsvVI/0agg/U1bFaQ0yhK12o=", "subType": "00" } }, { "$binary": { "base64": "KsEy0zgYcmkM+O/fWF9z3aJGIk22XCk+Aw96HB6JU68=", "subType": "00" } }, { "$binary": { "base64": "p+AnMI5ZxdJMSIEJmXXya+FeH5yubmOdViwUO89j0Rc=", "subType": "00" } }, { "$binary": { "base64": "/jLix56jzeywBtNuGw55lCXyebQoSIhbful0hOKxKDY=", "subType": "00" } }, { "$binary": { "base64": "fvDvSPomtJsl1S3+8/tzFCE8scHIdJY5hB9CdTEsoFo=", "subType": "00" } }, { "$binary": { "base64": "oV5hOJzPXxfTuRdKIlF4uYEoMDuqH+G7/3qgndDr0PM=", "subType": "00" } }, { "$binary": { "base64": "3ALwcvLj3VOfgD6OqXAO13h1ZkOv46R6+Oy6SUKh53I=", "subType": "00" } }, { "$binary": { "base64": "gxaB9FJj0IM+InhvAjwWaex3UIZ9SAnDiUd5WHSY/l0=", "subType": "00" } }, { "$binary": { "base64": "66NPvDygJzKJqddfNuDuNOpvGajjFRtvhkwfUkiYmXw=", "subType": "00" } }, { "$binary": { "base64": "1dWcQIocRAcO9XnXYqbhl83jc0RgjQpsrWd8dC27trg=", "subType": "00" } }, { "$binary": { "base64": "npos0Uf1DT3ztSCjPVY9EImlRnTHB1KLrvmVSqBQ/8E=", "subType": "00" } }, { "$binary": { "base64": "TEI9qBx/tK1l1H0v1scMG8Srmtwo5VxWHADPBSlWrXk=", "subType": "00" } }, { "$binary": { "base64": "3wUN2ypQKoj+5ASkeIK9ycxhahVxyTmGopigoUAlyYs=", "subType": "00" } }, { "$binary": { "base64": "o/oksSnUS+nIq6ozWTbB5bJh+NoaPj8deAA23uxiWCk=", "subType": "00" } }, { "$binary": { "base64": "KExYPruhA31e8xuSwvfUfDcyY/H2Va6taUd0k4yFgLc=", "subType": "00" } }, { "$binary": { "base64": "/x+dNfxdd/lkx8Z8VZVfoYl7LPoaZ/iKEzZXBrAtIJc=", "subType": "00" } }, { "$binary": { "base64": "DE4cmjFLPqZlmRomO0qQiruUBtzoCe8ZdNRcfNH92pU=", "subType": "00" } }, { "$binary": { "base64": "M6EKNcLPw/iojAChgYUSieaBYWcbsjKtB94SaHOr8vk=", "subType": "00" } }, { "$binary": { "base64": "+qP49lDPeyhaduTvXJgtJEqHNEYANVu9Bg3Bxz7Td9w=", "subType": "00" } }, { "$binary": { "base64": "ruMrC2VIS+VKbJwCFb3bfkaLTju9nE+yPONV9s0M0Vo=", "subType": "00" } }, { "$binary": { "base64": "EbjDlSB5JKnDKff4d8hOmaOwJ7B9Q6NQFisLj+DPC+0=", "subType": "00" } }, { "$binary": { "base64": "C/yYOTB94edyqAbiQNu8/H7FoG3yRRjHDkMykz4+Mv0=", "subType": "00" } }, { "$binary": { "base64": "CBxqrejG+qQQq2YTd6iP/06kiu2CxxzBFaZK3Ofb1CM=", "subType": "00" } }, { "$binary": { "base64": "2ZOQ/fpho+AbDENWBZaln7wRoepIRdhyT648dr8O5cU=", "subType": "00" } }, { "$binary": { "base64": "EghIgEPz01+myPgj8oid+PgncvobvC7vjvG3THEEQ0M=", "subType": "00" } }, { "$binary": { "base64": "92CysZYNF8riwAMhdrIPKxfODw9p07cKQy/Snn8XmVY=", "subType": "00" } }, { "$binary": { "base64": "VO0LeTBQmsEf7sCHzTnZwUPNTqRZ49R8V5E9XnZ/5N4=", "subType": "00" } }, { "$binary": { "base64": "exs8BQMJq7U6ZXYgIizT7XN+X/hOmmn4YEuzev9zgSI=", "subType": "00" } }, { "$binary": { "base64": "qHpS4k1I+gPniNp4CA8TY8lLN36vBYmgbKMFpbYMEqg=", "subType": "00" } }, { "$binary": { "base64": "+7lWKCKAWFw6gPZdHE6E8KIfI14/fSvtWUmllb5WLi0=", "subType": "00" } }, { "$binary": { "base64": "YiH/US0q6679hWblFDDKNqUjCgggoU8sUCssTIF1QbU=", "subType": "00" } }, { "$binary": { "base64": "YgwkKElEubNfvXL9hJxzqQUQtHiXN/OCGxNL1MUZZlM=", "subType": "00" } }, { "$binary": { "base64": "hZFST4INZTTuhvJlGJeMwlUAK270UCOTCDeBAnN4a7g=", "subType": "00" } }, { "$binary": { "base64": "24I1Zw35AuGnK3CqJhbCwYb0IPuu5sCRrM5iyeITOLc=", "subType": "00" } }, { "$binary": { "base64": "vgD12JB4Q1S/kGPSQ1KOgp386KnG1GbM/5+60oRGcGw=", "subType": "00" } }, { "$binary": { "base64": "+wNE+OL+CB9d4AUJdVxd56jUJCAXmmk9fapuB2TAc4g=", "subType": "00" } }, { "$binary": { "base64": "uhQh1B2Pe4RkNw/kPEcgaLenuikKoRf1iyfZhpXdodc=", "subType": "00" } }, { "$binary": { "base64": "eu8gjAUIp8ybO204AgeOq5v1neI1yljqy5v3I6lo1lM=", "subType": "00" } }, { "$binary": { "base64": "7QG6oVbASBAjrnCPxzzUNnuFSFNlKhbuBafkF8pr7Is=", "subType": "00" } }, { "$binary": { "base64": "PUS1xb2oHSDTdYltutoSSxBiJ1NjxH3l2kA4P1CZLEs=", "subType": "00" } }, { "$binary": { "base64": "XPMh/JDC/O93gJJCwwgJDb8ssWZvRvezNmKmyn3nIfk=", "subType": "00" } }, { "$binary": { "base64": "jWz+KGwMk/GOvFAK2rOxF3OjxeZAWfmUQ1HGJ7icw4A=", "subType": "00" } }, { "$binary": { "base64": "o7XbW68pc6flYigf3LW4WAGUWxpeqxaQLkHUhUR9RZ8=", "subType": "00" } }, { "$binary": { "base64": "nqR+g60+5U0okbqJadSqGgnC+j1JcP8rwMcfzOs2ACI=", "subType": "00" } }, { "$binary": { "base64": "Hz43qVK95tSfbYFtaE/8fE97XMk1RiO8XpWjwZHB80o=", "subType": "00" } }, { "$binary": { "base64": "noZUWlZ8M6KXU5rkifyo8/duw5IL7/fXbJvT7bNmW9k=", "subType": "00" } }, { "$binary": { "base64": "WONVHCuPSanXDRQQ/3tmyJ0Vq+Lu/4hRaMUf0g0kSuw=", "subType": "00" } }, { "$binary": { "base64": "UEaj6vQRoIghE8Movd8AGXhtwIOXlP4cBsECIUvE5Y8=", "subType": "00" } }, { "$binary": { "base64": "D3n2YcO8+PB4C8brDo7kxKjF9Y844rVkdRMLTgsQkrw=", "subType": "00" } }, { "$binary": { "base64": "C+YA0G9KjxZVaWwOMuh/dcnHnHAlYnbFrRl0IEpmsY0=", "subType": "00" } }, { "$binary": { "base64": "rUnmbmQanxrbFPYYrwyQ53x66OSt27yAvF+s48ezKDc=", "subType": "00" } } ] } ] } } } ] } fle2v2-Range-Double-Correctness.json000066400000000000000000000665511462766011000356650ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/client-side-encryption/spec/legacy{ "runOn": [ { "minServerVersion": "7.0.0", "topology": [ "replicaset", "sharded", "load-balanced" ] } ], "database_name": "default", "collection_name": "default", "data": [], "encrypted_fields": { "fields": [ { "keyId": { "$binary": { "base64": "EjRWeBI0mHYSNBI0VniQEg==", "subType": "04" } }, "path": "encryptedDoubleNoPrecision", "bsonType": "double", "queries": { "queryType": "rangePreview", "contention": { "$numberLong": "0" }, "sparsity": { "$numberLong": "1" } } } ] }, "key_vault_data": [ { "_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" } } ], "tests": [ { "description": "Find with $gt", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "local": { "key": { "$binary": { "base64": "Mng0NCt4ZHVUYUJCa1kxNkVyNUR1QURhZ2h2UzR2d2RrZzh0cFBwM3R6NmdWMDFBMUN3YkQ5aXRRMkhGRGdQV09wOGVNYUMxT2k3NjZKelhaQmRCZGJkTXVyZG9uSjFk", "subType": "00" } } } } } }, "operations": [ { "name": "insertOne", "arguments": { "document": { "_id": 0, "encryptedDoubleNoPrecision": { "$numberDouble": "0.0" } } } }, { "name": "insertOne", "arguments": { "document": { "_id": 1, "encryptedDoubleNoPrecision": { "$numberDouble": "1.0" } } } }, { "name": "find", "arguments": { "filter": { "encryptedDoubleNoPrecision": { "$gt": { "$numberDouble": "0.0" } } } }, "result": [ { "_id": 1, "encryptedDoubleNoPrecision": { "$numberDouble": "1.0" } } ] } ] }, { "description": "Find with $gte", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "local": { "key": { "$binary": { "base64": "Mng0NCt4ZHVUYUJCa1kxNkVyNUR1QURhZ2h2UzR2d2RrZzh0cFBwM3R6NmdWMDFBMUN3YkQ5aXRRMkhGRGdQV09wOGVNYUMxT2k3NjZKelhaQmRCZGJkTXVyZG9uSjFk", "subType": "00" } } } } } }, "operations": [ { "name": "insertOne", "arguments": { "document": { "_id": 0, "encryptedDoubleNoPrecision": { "$numberDouble": "0.0" } } } }, { "name": "insertOne", "arguments": { "document": { "_id": 1, "encryptedDoubleNoPrecision": { "$numberDouble": "1.0" } } } }, { "name": "find", "arguments": { "filter": { "encryptedDoubleNoPrecision": { "$gte": { "$numberDouble": "0.0" } } }, "sort": { "_id": 1 } }, "result": [ { "_id": 0, "encryptedDoubleNoPrecision": { "$numberDouble": "0.0" } }, { "_id": 1, "encryptedDoubleNoPrecision": { "$numberDouble": "1.0" } } ] } ] }, { "description": "Find with $gt with no results", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "local": { "key": { "$binary": { "base64": "Mng0NCt4ZHVUYUJCa1kxNkVyNUR1QURhZ2h2UzR2d2RrZzh0cFBwM3R6NmdWMDFBMUN3YkQ5aXRRMkhGRGdQV09wOGVNYUMxT2k3NjZKelhaQmRCZGJkTXVyZG9uSjFk", "subType": "00" } } } } } }, "operations": [ { "name": "insertOne", "arguments": { "document": { "_id": 0, "encryptedDoubleNoPrecision": { "$numberDouble": "0.0" } } } }, { "name": "insertOne", "arguments": { "document": { "_id": 1, "encryptedDoubleNoPrecision": { "$numberDouble": "1.0" } } } }, { "name": "find", "arguments": { "filter": { "encryptedDoubleNoPrecision": { "$gt": { "$numberDouble": "1.0" } } } }, "result": [] } ] }, { "description": "Find with $lt", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "local": { "key": { "$binary": { "base64": "Mng0NCt4ZHVUYUJCa1kxNkVyNUR1QURhZ2h2UzR2d2RrZzh0cFBwM3R6NmdWMDFBMUN3YkQ5aXRRMkhGRGdQV09wOGVNYUMxT2k3NjZKelhaQmRCZGJkTXVyZG9uSjFk", "subType": "00" } } } } } }, "operations": [ { "name": "insertOne", "arguments": { "document": { "_id": 0, "encryptedDoubleNoPrecision": { "$numberDouble": "0.0" } } } }, { "name": "insertOne", "arguments": { "document": { "_id": 1, "encryptedDoubleNoPrecision": { "$numberDouble": "1.0" } } } }, { "name": "find", "arguments": { "filter": { "encryptedDoubleNoPrecision": { "$lt": { "$numberDouble": "1.0" } } } }, "result": [ { "_id": 0, "encryptedDoubleNoPrecision": { "$numberDouble": "0.0" } } ] } ] }, { "description": "Find with $lte", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "local": { "key": { "$binary": { "base64": "Mng0NCt4ZHVUYUJCa1kxNkVyNUR1QURhZ2h2UzR2d2RrZzh0cFBwM3R6NmdWMDFBMUN3YkQ5aXRRMkhGRGdQV09wOGVNYUMxT2k3NjZKelhaQmRCZGJkTXVyZG9uSjFk", "subType": "00" } } } } } }, "operations": [ { "name": "insertOne", "arguments": { "document": { "_id": 0, "encryptedDoubleNoPrecision": { "$numberDouble": "0.0" } } } }, { "name": "insertOne", "arguments": { "document": { "_id": 1, "encryptedDoubleNoPrecision": { "$numberDouble": "1.0" } } } }, { "name": "find", "arguments": { "filter": { "encryptedDoubleNoPrecision": { "$lte": { "$numberDouble": "1.0" } } }, "sort": { "_id": 1 } }, "result": [ { "_id": 0, "encryptedDoubleNoPrecision": { "$numberDouble": "0.0" } }, { "_id": 1, "encryptedDoubleNoPrecision": { "$numberDouble": "1.0" } } ] } ] }, { "description": "Find with $gt and $lt", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "local": { "key": { "$binary": { "base64": "Mng0NCt4ZHVUYUJCa1kxNkVyNUR1QURhZ2h2UzR2d2RrZzh0cFBwM3R6NmdWMDFBMUN3YkQ5aXRRMkhGRGdQV09wOGVNYUMxT2k3NjZKelhaQmRCZGJkTXVyZG9uSjFk", "subType": "00" } } } } } }, "operations": [ { "name": "insertOne", "arguments": { "document": { "_id": 0, "encryptedDoubleNoPrecision": { "$numberDouble": "0.0" } } } }, { "name": "insertOne", "arguments": { "document": { "_id": 1, "encryptedDoubleNoPrecision": { "$numberDouble": "1.0" } } } }, { "name": "find", "arguments": { "filter": { "encryptedDoubleNoPrecision": { "$gt": { "$numberDouble": "0.0" }, "$lt": { "$numberDouble": "2.0" } } } }, "result": [ { "_id": 1, "encryptedDoubleNoPrecision": { "$numberDouble": "1.0" } } ] } ] }, { "description": "Find with equality", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "local": { "key": { "$binary": { "base64": "Mng0NCt4ZHVUYUJCa1kxNkVyNUR1QURhZ2h2UzR2d2RrZzh0cFBwM3R6NmdWMDFBMUN3YkQ5aXRRMkhGRGdQV09wOGVNYUMxT2k3NjZKelhaQmRCZGJkTXVyZG9uSjFk", "subType": "00" } } } } } }, "operations": [ { "name": "insertOne", "arguments": { "document": { "_id": 0, "encryptedDoubleNoPrecision": { "$numberDouble": "0.0" } } } }, { "name": "insertOne", "arguments": { "document": { "_id": 1, "encryptedDoubleNoPrecision": { "$numberDouble": "1.0" } } } }, { "name": "find", "arguments": { "filter": { "encryptedDoubleNoPrecision": { "$numberDouble": "0.0" } } }, "result": [ { "_id": 0, "encryptedDoubleNoPrecision": { "$numberDouble": "0.0" } } ] }, { "name": "find", "arguments": { "filter": { "encryptedDoubleNoPrecision": { "$numberDouble": "1.0" } } }, "result": [ { "_id": 1, "encryptedDoubleNoPrecision": { "$numberDouble": "1.0" } } ] } ] }, { "description": "Find with $in", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "local": { "key": { "$binary": { "base64": "Mng0NCt4ZHVUYUJCa1kxNkVyNUR1QURhZ2h2UzR2d2RrZzh0cFBwM3R6NmdWMDFBMUN3YkQ5aXRRMkhGRGdQV09wOGVNYUMxT2k3NjZKelhaQmRCZGJkTXVyZG9uSjFk", "subType": "00" } } } } } }, "operations": [ { "name": "insertOne", "arguments": { "document": { "_id": 0, "encryptedDoubleNoPrecision": { "$numberDouble": "0.0" } } } }, { "name": "insertOne", "arguments": { "document": { "_id": 1, "encryptedDoubleNoPrecision": { "$numberDouble": "1.0" } } } }, { "name": "find", "arguments": { "filter": { "encryptedDoubleNoPrecision": { "$in": [ { "$numberDouble": "0.0" } ] } } }, "result": [ { "_id": 0, "encryptedDoubleNoPrecision": { "$numberDouble": "0.0" } } ] } ] }, { "description": "Aggregate with $gte", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "local": { "key": { "$binary": { "base64": "Mng0NCt4ZHVUYUJCa1kxNkVyNUR1QURhZ2h2UzR2d2RrZzh0cFBwM3R6NmdWMDFBMUN3YkQ5aXRRMkhGRGdQV09wOGVNYUMxT2k3NjZKelhaQmRCZGJkTXVyZG9uSjFk", "subType": "00" } } } } } }, "operations": [ { "name": "insertOne", "arguments": { "document": { "_id": 0, "encryptedDoubleNoPrecision": { "$numberDouble": "0.0" } } } }, { "name": "insertOne", "arguments": { "document": { "_id": 1, "encryptedDoubleNoPrecision": { "$numberDouble": "1.0" } } } }, { "name": "aggregate", "arguments": { "pipeline": [ { "$match": { "encryptedDoubleNoPrecision": { "$gte": { "$numberDouble": "0.0" } } } }, { "$sort": { "_id": 1 } } ] }, "result": [ { "_id": 0, "encryptedDoubleNoPrecision": { "$numberDouble": "0.0" } }, { "_id": 1, "encryptedDoubleNoPrecision": { "$numberDouble": "1.0" } } ] } ] }, { "description": "Aggregate with $gt with no results", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "local": { "key": { "$binary": { "base64": "Mng0NCt4ZHVUYUJCa1kxNkVyNUR1QURhZ2h2UzR2d2RrZzh0cFBwM3R6NmdWMDFBMUN3YkQ5aXRRMkhGRGdQV09wOGVNYUMxT2k3NjZKelhaQmRCZGJkTXVyZG9uSjFk", "subType": "00" } } } } } }, "operations": [ { "name": "insertOne", "arguments": { "document": { "_id": 0, "encryptedDoubleNoPrecision": { "$numberDouble": "0.0" } } } }, { "name": "insertOne", "arguments": { "document": { "_id": 1, "encryptedDoubleNoPrecision": { "$numberDouble": "1.0" } } } }, { "name": "aggregate", "arguments": { "pipeline": [ { "$match": { "encryptedDoubleNoPrecision": { "$gt": { "$numberDouble": "1.0" } } } } ] }, "result": [] } ] }, { "description": "Aggregate with $lt", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "local": { "key": { "$binary": { "base64": "Mng0NCt4ZHVUYUJCa1kxNkVyNUR1QURhZ2h2UzR2d2RrZzh0cFBwM3R6NmdWMDFBMUN3YkQ5aXRRMkhGRGdQV09wOGVNYUMxT2k3NjZKelhaQmRCZGJkTXVyZG9uSjFk", "subType": "00" } } } } } }, "operations": [ { "name": "insertOne", "arguments": { "document": { "_id": 0, "encryptedDoubleNoPrecision": { "$numberDouble": "0.0" } } } }, { "name": "insertOne", "arguments": { "document": { "_id": 1, "encryptedDoubleNoPrecision": { "$numberDouble": "1.0" } } } }, { "name": "aggregate", "arguments": { "pipeline": [ { "$match": { "encryptedDoubleNoPrecision": { "$lt": { "$numberDouble": "1.0" } } } } ] }, "result": [ { "_id": 0, "encryptedDoubleNoPrecision": { "$numberDouble": "0.0" } } ] } ] }, { "description": "Aggregate with $lte", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "local": { "key": { "$binary": { "base64": "Mng0NCt4ZHVUYUJCa1kxNkVyNUR1QURhZ2h2UzR2d2RrZzh0cFBwM3R6NmdWMDFBMUN3YkQ5aXRRMkhGRGdQV09wOGVNYUMxT2k3NjZKelhaQmRCZGJkTXVyZG9uSjFk", "subType": "00" } } } } } }, "operations": [ { "name": "insertOne", "arguments": { "document": { "_id": 0, "encryptedDoubleNoPrecision": { "$numberDouble": "0.0" } } } }, { "name": "insertOne", "arguments": { "document": { "_id": 1, "encryptedDoubleNoPrecision": { "$numberDouble": "1.0" } } } }, { "name": "aggregate", "arguments": { "pipeline": [ { "$match": { "encryptedDoubleNoPrecision": { "$lte": { "$numberDouble": "1.0" } } } }, { "$sort": { "_id": 1 } } ] }, "result": [ { "_id": 0, "encryptedDoubleNoPrecision": { "$numberDouble": "0.0" } }, { "_id": 1, "encryptedDoubleNoPrecision": { "$numberDouble": "1.0" } } ] } ] }, { "description": "Aggregate with $gt and $lt", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "local": { "key": { "$binary": { "base64": "Mng0NCt4ZHVUYUJCa1kxNkVyNUR1QURhZ2h2UzR2d2RrZzh0cFBwM3R6NmdWMDFBMUN3YkQ5aXRRMkhGRGdQV09wOGVNYUMxT2k3NjZKelhaQmRCZGJkTXVyZG9uSjFk", "subType": "00" } } } } } }, "operations": [ { "name": "insertOne", "arguments": { "document": { "_id": 0, "encryptedDoubleNoPrecision": { "$numberDouble": "0.0" } } } }, { "name": "insertOne", "arguments": { "document": { "_id": 1, "encryptedDoubleNoPrecision": { "$numberDouble": "1.0" } } } }, { "name": "aggregate", "arguments": { "pipeline": [ { "$match": { "encryptedDoubleNoPrecision": { "$gt": { "$numberDouble": "0.0" }, "$lt": { "$numberDouble": "2.0" } } } } ] }, "result": [ { "_id": 1, "encryptedDoubleNoPrecision": { "$numberDouble": "1.0" } } ] } ] }, { "description": "Aggregate with equality", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "local": { "key": { "$binary": { "base64": "Mng0NCt4ZHVUYUJCa1kxNkVyNUR1QURhZ2h2UzR2d2RrZzh0cFBwM3R6NmdWMDFBMUN3YkQ5aXRRMkhGRGdQV09wOGVNYUMxT2k3NjZKelhaQmRCZGJkTXVyZG9uSjFk", "subType": "00" } } } } } }, "operations": [ { "name": "insertOne", "arguments": { "document": { "_id": 0, "encryptedDoubleNoPrecision": { "$numberDouble": "0.0" } } } }, { "name": "insertOne", "arguments": { "document": { "_id": 1, "encryptedDoubleNoPrecision": { "$numberDouble": "1.0" } } } }, { "name": "aggregate", "arguments": { "pipeline": [ { "$match": { "encryptedDoubleNoPrecision": { "$numberDouble": "0.0" } } } ] }, "result": [ { "_id": 0, "encryptedDoubleNoPrecision": { "$numberDouble": "0.0" } } ] }, { "name": "aggregate", "arguments": { "pipeline": [ { "$match": { "encryptedDoubleNoPrecision": { "$numberDouble": "1.0" } } } ] }, "result": [ { "_id": 1, "encryptedDoubleNoPrecision": { "$numberDouble": "1.0" } } ] } ] }, { "description": "Aggregate with $in", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "local": { "key": { "$binary": { "base64": "Mng0NCt4ZHVUYUJCa1kxNkVyNUR1QURhZ2h2UzR2d2RrZzh0cFBwM3R6NmdWMDFBMUN3YkQ5aXRRMkhGRGdQV09wOGVNYUMxT2k3NjZKelhaQmRCZGJkTXVyZG9uSjFk", "subType": "00" } } } } } }, "operations": [ { "name": "insertOne", "arguments": { "document": { "_id": 0, "encryptedDoubleNoPrecision": { "$numberDouble": "0.0" } } } }, { "name": "insertOne", "arguments": { "document": { "_id": 1, "encryptedDoubleNoPrecision": { "$numberDouble": "1.0" } } } }, { "name": "aggregate", "arguments": { "pipeline": [ { "$match": { "encryptedDoubleNoPrecision": { "$in": [ { "$numberDouble": "0.0" } ] } } } ] }, "result": [ { "_id": 0, "encryptedDoubleNoPrecision": { "$numberDouble": "0.0" } } ] } ] }, { "description": "Wrong type: Insert Int", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "local": { "key": { "$binary": { "base64": "Mng0NCt4ZHVUYUJCa1kxNkVyNUR1QURhZ2h2UzR2d2RrZzh0cFBwM3R6NmdWMDFBMUN3YkQ5aXRRMkhGRGdQV09wOGVNYUMxT2k3NjZKelhaQmRCZGJkTXVyZG9uSjFk", "subType": "00" } } } } } }, "operations": [ { "name": "insertOne", "arguments": { "document": { "_id": 0, "encryptedDoubleNoPrecision": { "$numberInt": "0" } } }, "result": { "errorContains": "cannot encrypt element" } } ] }, { "description": "Wrong type: Find Int", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "local": { "key": { "$binary": { "base64": "Mng0NCt4ZHVUYUJCa1kxNkVyNUR1QURhZ2h2UzR2d2RrZzh0cFBwM3R6NmdWMDFBMUN3YkQ5aXRRMkhGRGdQV09wOGVNYUMxT2k3NjZKelhaQmRCZGJkTXVyZG9uSjFk", "subType": "00" } } } } } }, "operations": [ { "name": "find", "arguments": { "filter": { "encryptedDoubleNoPrecision": { "$gte": { "$numberInt": "0" } } }, "sort": { "_id": 1 } }, "result": { "errorContains": "field type is not supported" } } ] } ] } fle2v2-Range-Double-Delete.json000066400000000000000000001040371462766011000345650ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/client-side-encryption/spec/legacy{ "runOn": [ { "minServerVersion": "7.0.0", "topology": [ "replicaset", "sharded", "load-balanced" ] } ], "database_name": "default", "collection_name": "default", "data": [], "encrypted_fields": { "fields": [ { "keyId": { "$binary": { "base64": "EjRWeBI0mHYSNBI0VniQEg==", "subType": "04" } }, "path": "encryptedDoubleNoPrecision", "bsonType": "double", "queries": { "queryType": "rangePreview", "contention": { "$numberLong": "0" }, "sparsity": { "$numberLong": "1" } } } ] }, "key_vault_data": [ { "_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" } } ], "tests": [ { "description": "FLE2 Range Double. Delete.", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "local": { "key": { "$binary": { "base64": "Mng0NCt4ZHVUYUJCa1kxNkVyNUR1QURhZ2h2UzR2d2RrZzh0cFBwM3R6NmdWMDFBMUN3YkQ5aXRRMkhGRGdQV09wOGVNYUMxT2k3NjZKelhaQmRCZGJkTXVyZG9uSjFk", "subType": "00" } } } } } }, "operations": [ { "name": "insertOne", "arguments": { "document": { "_id": 0, "encryptedDoubleNoPrecision": { "$numberDouble": "0" } } } }, { "name": "insertOne", "arguments": { "document": { "_id": 1, "encryptedDoubleNoPrecision": { "$numberDouble": "1" } } } }, { "name": "deleteOne", "arguments": { "filter": { "encryptedDoubleNoPrecision": { "$gt": { "$numberDouble": "0" } } } }, "result": { "deletedCount": 1 } } ], "expectations": [ { "command_started_event": { "command": { "listCollections": 1, "filter": { "name": "default" } }, "command_name": "listCollections" } }, { "command_started_event": { "command": { "find": "datakeys", "filter": { "$or": [ { "_id": { "$in": [ { "$binary": { "base64": "EjRWeBI0mHYSNBI0VniQEg==", "subType": "04" } } ] } }, { "keyAltNames": { "$in": [] } } ] }, "$db": "keyvault", "readConcern": { "level": "majority" } }, "command_name": "find" } }, { "command_started_event": { "command": { "insert": "default", "documents": [ { "_id": 0, "encryptedDoubleNoPrecision": { "$$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": "encryptedDoubleNoPrecision", "bsonType": "double", "queries": { "queryType": "rangePreview", "contention": { "$numberLong": "0" }, "sparsity": { "$numberLong": "1" } } } ] } } } }, "command_name": "insert" } }, { "command_started_event": { "command": { "insert": "default", "documents": [ { "_id": 1, "encryptedDoubleNoPrecision": { "$$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": "encryptedDoubleNoPrecision", "bsonType": "double", "queries": { "queryType": "rangePreview", "contention": { "$numberLong": "0" }, "sparsity": { "$numberLong": "1" } } } ] } } } }, "command_name": "insert" } }, { "command_started_event": { "command": { "delete": "default", "deletes": [ { "q": { "encryptedDoubleNoPrecision": { "$gt": { "$binary": { "base64": "DYckAAADcGF5bG9hZABXJAAABGcAQyQAAAMwAH0AAAAFZAAgAAAAAHgYoMGjEE6fAlAhICv0+doHcVX8CmMVxyq7+jlyGrvmBXMAIAAAAAC/5MQZgTHuIr/O5Z3mXPvqrom5JTQ8IeSpQGhO9sB+8gVsACAAAAAAuPSXVmJUAUpTQg/A9Bu1hYczZF58KEhVofakygbsvJQAAzEAfQAAAAVkACAAAAAA2kiWNvEc4zunJ1jzvuClFC9hjZMYruKCqAaxq+oY8EAFcwAgAAAAACofIS72Cm6s866UCk+evTH3CvKBj/uZd72sAL608rzTBWwAIAAAAADuCQ/M2xLeALF0UFZtJb22QGOhHmJv6xoO+kZIHcDeiAADMgB9AAAABWQAIAAAAABkfoBGmU3hjYBvQbjNW19kfXneBQsQQPRfUL3UAwI2cAVzACAAAAAAUpK2BUOqX/DGdX5YJniEZMWkofxHqeAbXceEGJxhp8AFbAAgAAAAAKUaLzIldNIZv6RHE+FwbMjzcNHqPESwF/37mm43VPrsAAMzAH0AAAAFZAAgAAAAAFNprhQ3ZwIcYbuzLolAT5n/vc14P9kUUQComDu6eFyKBXMAIAAAAAAcx9z9pk32YbPV/sfPZl9ALIEVsqoLXgqWLVK/tP+heAVsACAAAAAA/qxvuvJbAHwwhfrPVpmCFzNvg2cU/NXaWgqgYUZpgXwAAzQAfQAAAAVkACAAAAAAODI+pB2pCuB+YmNEUAgtMfNdt3DmSkrJ96gRzLphgb8FcwAgAAAAAAT7dewFDxUDECQ3zVq75/cUN4IP+zsqhkP5+czUwlJIBWwAIAAAAACFGeOtd5zBXTJ4JYonkn/HXZfHipUlqGwIRUcH/VTatwADNQB9AAAABWQAIAAAAACNAk+yTZ4Ewk1EnotQK8O3h1gg9I7pr9q2+4po1iJVgAVzACAAAAAAUj/LesmtEsgqYVzMJ67umVA11hJTdDXwbxDoQ71vWyUFbAAgAAAAABlnhpgTQ0WjLb5u0b/vEydrCeFjVynKd7aqb+UnvVLeAAM2AH0AAAAFZAAgAAAAAD/FIrGYFDjyYmVb7oTMVwweWP7A6F9LnyIuNO4MjBnXBXMAIAAAAACIZgJCQRZu7NhuNMyOqCn1tf+DfU1qm10TPCfj5JYV3wVsACAAAAAA5hmY4ptuNxULGf87SUFXQWGAONsL9U29duh8xqsHtxoAAzcAfQAAAAVkACAAAAAAciRW40ORJLVwchOEpz87Svb+5toAFM6LxDWv928ECwQFcwAgAAAAAN0dipyESIkszfjRzdDi8kAGaa2Hf4wrPAtiWwboZLuxBWwAIAAAAAANr4o/+l1OIbbaX5lZ3fQ/WIeOcEXjNI1F0WbSgQrzaQADOAB9AAAABWQAIAAAAACZqAyCzYQupJ95mrBJX54yIz9VY7I0WrxpNYElCI4dTQVzACAAAAAA/eyJb6d1xfE+jJlVXMTD3HS/NEYENPVKAuj56Dr2dSEFbAAgAAAAANkSt154Or/JKb31VvbZFV46RPgUp8ff/hcPORL7PpFBAAM5AH0AAAAFZAAgAAAAAI5bm3YO0Xgf0VT+qjVTTfvckecM3Cwqj7DTKZXf8/NXBXMAIAAAAAD/m+h8fBhWaHm6Ykuz0WX1xL4Eme3ErLObyEVJf8NCywVsACAAAAAAfb1VZZCqs2ivYbRzX4p5CtaCkKW+g20Pr57FWXzEZi8AAzEwAH0AAAAFZAAgAAAAANqo4+p6qdtCzcB4BX1wQ6llU7eFBnuu4MtZwp4B6mDlBXMAIAAAAAAGiz+VaukMZ+6IH4jtn4KWWdKK4/W+O+gRioQDrfzpMgVsACAAAAAAG4YYkTp80EKo59mlHExDodRQFR7njhR5dmISwUJ6ukAAAzExAH0AAAAFZAAgAAAAAPrFXmHP2Y4YAm7b/aqsdn/DPoDkv7B8egWkfe23XsM1BXMAIAAAAAAGhwpKAr7skeqHm3oseSbO7qKNhmYsuUrECBxJ5k+D2AVsACAAAAAAAqPQi9luYAu3GrFCEsVjd9z2zIDcp6SPTR2w6KQEr+IAAzEyAH0AAAAFZAAgAAAAABzjYxwAjXxXc0Uxv18rH8I3my0Aguow0kTwKyxbrm+cBXMAIAAAAADVbqJVr6IdokuhXkEtXF0C2gINLiAjMVN20lE20Vmp2QVsACAAAAAAD7K1Fx4gFaaizkIUrf+EGXQeG7QX1jadhGc6Ji471H8AAzEzAH0AAAAFZAAgAAAAAFMm2feF2fFCm/UC6AfIyepX/xJDSmnnolQIBnHcPmb5BXMAIAAAAABLI11kFrQoaNVZFmq/38aRNImPOjdJh0Lo6irI8M/AaAVsACAAAAAAOWul0oVqJ9CejD2RqphhTC98DJeRQy5EwbNerU2+4l8AAzE0AH0AAAAFZAAgAAAAAJvXB3KyNiNtQko4SSzo/9b2qmM2zU9CQTTDfLSBWMgRBXMAIAAAAAAvjuVP7KsLRDeqVqRziTKpBrjVyqKiIbO9Gw8Wl2wFTAVsACAAAAAADlE+oc1ins+paNcaOZJhBlKlObDJ4VQORWjFYocM4LgAAzE1AH0AAAAFZAAgAAAAAPGdcxDiid8z8XYnfdDivNMYVPgBKdGOUw6UStU+48CdBXMAIAAAAAARj6g1Ap0eEfuCZ4X2TsEw+Djrhto3fA5nLwPaY0vCTgVsACAAAAAAoHqiwGOUkBu8SX5U1yHho+UIFdSN2MdQN5s6bQ0EsJYAAzE2AH0AAAAFZAAgAAAAAP5rGPrYGt3aKob5f/ldP0qrW7bmWvqnKY4QwdDWz400BXMAIAAAAADTQkW2ymaaf/bhteOOGmSrIR97bAnJx+yN3yMj1bTeewVsACAAAAAADyQnHGH2gF4w4L8axUsSTf6Ubk7L5/eoFOJk12MtZAoAAzE3AH0AAAAFZAAgAAAAAAlz6wJze5UkIxKpJOZFGCOf3v2KByWyI6NB6JM9wNcBBXMAIAAAAABUC7P/neUIHHoZtq0jFVBHY75tSFYr1Y5S16YN5XxC1QVsACAAAAAAgvxRbXDisNnLY3pfsjDdnFLtkvYUC4lhA68eBXc7KAwAAzE4AH0AAAAFZAAgAAAAAFJ8AtHcjia/9Y5pLEc3qVgH5xKiXw12G9Kn2A1EY8McBXMAIAAAAAAxe7Bdw7eUSBk/oAawa7uicTEDgXLymRNhBy1LAxhDvwVsACAAAAAAxKPaIBKVx3jTA+R/el7P7AZ7efrmTGjJs3Hj/YdMddwAAzE5AH0AAAAFZAAgAAAAAO8uwQUaKFb6vqR3Sv3Wn4QAonC2exOC9lGG1juqP5DtBXMAIAAAAABZf1KyJgQg8/Rf5c02DgDK2aQu0rNCOvaL60ohDHyY+gVsACAAAAAAqyEjfKC8lYoIfoXYHUqHZPoaA6EK5BAZy5dxXZmay4kAAzIwAH0AAAAFZAAgAAAAAE8YtqyRsGCeiR6hhiyisR/hccmK4nZqIMzO4lUBmEFzBXMAIAAAAAC1UYOSKqAeG1UJiKjWFVskRhuFKpj9Ezy+lICZvFlN5AVsACAAAAAA6Ct9nNMKyRazn1OKnRKagm746CGu+jyhbL1qJnZxGi0AAzIxAH0AAAAFZAAgAAAAAPhCrMausDx1QUIEqp9rUdRKyM6a9AAx7jQ3ILIu8wNIBXMAIAAAAACmH8lotGCiF2q9VQxhsS+7LAZv79VUAsOUALaGxE/EpAVsACAAAAAAnc1xCKfdvbUEc8F7XZqlNn1C+hZTtC0I9I3LL06iaNkAAzIyAH0AAAAFZAAgAAAAAOBi/GAYFcstMSJPgp3VkMiuuUUCrZytvqYaU8dwm8v2BXMAIAAAAACEZSZVyD3pKzGlbdwlYmWQhHHTV5SnNLknl2Gw8IaUTQVsACAAAAAAfsLZsEDcWSuNsIo/TD1ReyQW75HPMgmuKZuWFOLKRLoAAzIzAH0AAAAFZAAgAAAAAIQuup+YGfH3mflzWopN8J1X8o8a0d9CSGIvrA5HOzraBXMAIAAAAADYvNLURXsC2ITMqK14LABQBI+hZZ5wNf24JMcKLW+84AVsACAAAAAACzfjbTBH7IwDU91OqLAz94RFkoqBOkzKAqQb55gT4/MAAzI0AH0AAAAFZAAgAAAAAKsh0ADyOnVocFrOrf6MpTrNvAj8iaiE923DPryu124gBXMAIAAAAADg24a8NVE1GyScc6tmnTbmu5ulzO+896fE92lN08MeswVsACAAAAAAaPxcOIxnU7But88/yadOuDJDMcCywwrRitaxMODT4msAAzI1AH0AAAAFZAAgAAAAAKkVC2Y6HtRmv72tDnPUSjJBvse7SxLqnr09/Uuj9sVVBXMAIAAAAABYNFUkH7ylPMN+Bc3HWX1e0flGYNbtJNCY9SltJCW/UAVsACAAAAAAZYK/f9H4OeihmpiFMH7Wm7uLvs2s92zNA8wyrNZTsuMAAzI2AH0AAAAFZAAgAAAAADDggcwcb/Yn1Kk39sOHsv7BO/MfP3m/AJzjGH506Wf9BXMAIAAAAAAYZIsdjICS0+BDyRUPnrSAZfPrwtuMaEDEn0/ijLNQmAVsACAAAAAAGPnYVvo2ulO9z4LGd/69NAklfIcZqZvFX2KK0s+FcTUAAzI3AH0AAAAFZAAgAAAAAEWY7dEUOJBgjOoWVht1wLehsWAzB3rSOBtLgTuM2HC8BXMAIAAAAAAAoswiHRROurjwUW8u8D5EUT+67yvrgpB/j6PzBDAfVwVsACAAAAAA6NhRTYFL/Sz4tao7vpPjLNgAJ0FX6P/IyMW65qT6YsMAAzI4AH0AAAAFZAAgAAAAAPZaapeAUUFPA7JTCMOWHJa9lnPFh0/gXfAPjA1ezm4ZBXMAIAAAAACmJvLY2nivw7/b3DOKH/X7bBXjJwoowqb1GtEFO3OYgAVsACAAAAAA/JcUoyKacCB1NfmH8vYqC1f7rd13KShrQqV2r9QBP44AAzI5AH0AAAAFZAAgAAAAAK00u6jadxCZAiA+fTsPVDsnW5p5LCr4+kZZZOTDuZlfBXMAIAAAAAAote4zTEYMDgaaQbAdN8Dzv93ljPLdGjJzvnRn3KXgtQVsACAAAAAAxXd9Mh6R3mnJy8m7UfqMKi6oD5DlZpkaOz6bEjMOdiwAAzMwAH0AAAAFZAAgAAAAAFbgabdyymiEVYYwtJSWa7lfl/oYuj/SukzJeDOR6wPVBXMAIAAAAADAFGFjS1vPbN6mQEhkDYTD6V2V23Ys9gUEUMGNvMPkaAVsACAAAAAAL/D5Sze/ZoEanZLK0IeEkhgVkxEjMWVCfmJaD3a8uNIAAzMxAH0AAAAFZAAgAAAAABNMR6UBv2E627CqLtQ/eDYx7OEwQ7JrR4mSHFa1N8tLBXMAIAAAAAAxH4gucI4UmNVB7625C6hFSVCuIpJO3lusJlPuL8H5EQVsACAAAAAAVLHNg0OUVqZ7WGOP53BkTap9FOw9dr1P4J8HxqFqU04AAzMyAH0AAAAFZAAgAAAAAG8cd6WBneNunlqrQ2EmNf35W7OGObGq9WL4ePX+LUDmBXMAIAAAAAAjJ2+sX87NSis9hBsgb1QprVRnO7Bf+GObCGoUqyPE4wVsACAAAAAAs9c9SM49/pWmyUQKslpt3RTMBNSRppfNO0JBvUqHPg0AAzMzAH0AAAAFZAAgAAAAAFWOUGkUpy8yf6gB3dio/aOfRKh7XuhvsUj48iESFJrGBXMAIAAAAAAY7sCDMcrUXvNuL6dO0m11WyijzXZvPIcOKob6IpC4PQVsACAAAAAAJOP+EHz6awDb1qK2bZQ3kTV7wsj5Daj/IGAWh4g7omAAAzM0AH0AAAAFZAAgAAAAAGUrIdKxOihwNmo6B+aG+Ag1qa0+iqdksHOjQj+Oy9bZBXMAIAAAAABwa5dbI2KmzBDNBTQBEkjZv4sPaeRkRNejcjdVymRFKQVsACAAAAAA4ml/nm0gJNTcJ4vuD+T2Qfq2fQZlibJp/j6MOGDrbHMAAzM1AH0AAAAFZAAgAAAAAOx89xV/hRk64/CkM9N2EMK6aldII0c8smdcsZ46NbP8BXMAIAAAAADBF6tfQ+7q9kTuLyuyrSnDgmrdmrXkdhl980i1KHuGHgVsACAAAAAACUqiFqHZdGbwAA+hN0YUE5zFg+H+dabIB4dj5/75W/YAAzM2AH0AAAAFZAAgAAAAAMkN0L1oQWXhjwn9rAdudcYeN8/5VdCKU8cmDt7BokjsBXMAIAAAAAAT62pGXoRwExe9uvgYOI0hg5tOxilrWfoEmT0SMglWJwVsACAAAAAAlVz4dhiprSbUero6JFfxzSJGclg63oAkAmgbSwbcYxIAAzM3AH0AAAAFZAAgAAAAANxfa4xCoaaB7k1C1RoH1LBhsCbN2yEq15BT9b+iqEC4BXMAIAAAAACAX9LV8Pemfw7NF0iB1/85NzM1Ef+1mUfyehacUVgobQVsACAAAAAAVq4xpbymLk0trPC/a2MvB39I7hRiX8EJsVSI5E5hSBkAAzM4AH0AAAAFZAAgAAAAAOYIYoWkX7dGuyKfi3XssUlc7u/gWzqrR9KMkikKVdmSBXMAIAAAAABVF2OYjRTGi9Tw8XCAwZWLpX35Yl271TlNWp6N/nROhAVsACAAAAAA0nWwYzXQ1+EkDvnGq+SMlq20z+j32Su+i/A95SggPb4AAzM5AH0AAAAFZAAgAAAAAIy0+bXZi10QC+q7oSOLXK5Fee7VEk/qHSXukfeVIfgzBXMAIAAAAAAQ3IIV/JQCHW95AEbH5zGIHtJqyuPjWPMIZ+VmQHlxEwVsACAAAAAAp0jYsyohKv9Pm+4k+DplEGbl9WLZpAJzitrcDj4CNsMAAzQwAH0AAAAFZAAgAAAAAL5SOJQ3LOhgdXJ5v086NNeAl1qonQnchObdpZJ1kHeEBXMAIAAAAAA+tEqTXODtik+ydJZSnUqXF9f18bPeze9eWtR7ExZJgQVsACAAAAAAbrkZCVgB9Qsp4IAbdf+bD4fT6Boqk5UtuA/zhNrh1y0AAzQxAH0AAAAFZAAgAAAAAKl8zcHJRDjSjJeV/WvMxulW1zrTFtaeBy/aKKhadc6UBXMAIAAAAADBdWQl5SBIvtZZLIHszePwkO14W1mQ0izUk2Ov21cPNAVsACAAAAAAHErCYycpqiIcCZHdmPL1hi+ovLQk4TAvENpfLdTRamQAAzQyAH0AAAAFZAAgAAAAAFvotcNaoKnVt5CBCOPwjexFO0WGWuaIGL6H/6KSau+6BXMAIAAAAAD2y2mBN5xPu5PJoY2zcr0GnQDtHRBogA5+xzIxccE9fwVsACAAAAAAdS34xzJesnUfxLCcc1U7XzUqLy8MAzV/tcjbqaD3lkMAAzQzAH0AAAAFZAAgAAAAAPezU0/vNT4Q4YKbTbaeHqcwNLT+IjW/Y9QFpIooihjPBXMAIAAAAACj2x4O4rHter8ZnTws5LAP9jJ/6kk9C/V3vL50LoFZHAVsACAAAAAAQdBDF3747uCVP5lB/zr8VmzxJfTSZHBKeIgm5FyONXwAAzQ0AH0AAAAFZAAgAAAAAMqpayM2XotEFmm0gwQd9rIzApy0X+7HfOhNk6VU7F5lBXMAIAAAAACJR9+q5T9qFHXFNgGbZnPubG8rkO6cwWhzITQTmd6VgwVsACAAAAAAOZLQ6o7e4mVfDzbpQioa4d3RoTvqwgnbmc5Qh2wsZuoAAzQ1AH0AAAAFZAAgAAAAANCeyW+3oebaQk+aqxNVhAcT/BZ5nhsTVdKS3tMrLSvWBXMAIAAAAADxRFMDhkyuEc++WnndMfoUMLNL7T7rWoeblcrpSI6soQVsACAAAAAAdBuBMJ1lxt0DRq9pOZldQqchLs3B/W02txcMLD490FEAAzQ2AH0AAAAFZAAgAAAAAIbo5YBTxXM7HQhl7UP9NNgpPGFkBx871r1B65G47+K8BXMAIAAAAAC21dJSxnEhnxO5gzN5/34BL4von45e1meW92qowzb8fQVsACAAAAAAm3Hk2cvBN0ANaR5jzeZE5TsdxDvJCTOT1I01X7cNVaYAAzQ3AH0AAAAFZAAgAAAAABm/6pF96j26Jm7z5KkY1y33zcAEXLx2n0DwC03bs/ixBXMAIAAAAAD01OMvTZI/mqMgxIhA5nLs068mW+GKl3OW3ilf2D8+LgVsACAAAAAAaLvJDrqBESTNZSdcXsd+8GXPl8ZkUsGpeYuyYVv/kygAAzQ4AH0AAAAFZAAgAAAAAJ/D3+17gaQdkBqkL2wMwccdmCaVOtxzIkM8VyI4xI5zBXMAIAAAAAAggLVmkc5u+YzBR+oNE+XgLVp64fC6MzUb/Ilu/Jsw0AVsACAAAAAACz3HVKdWkx82/kGbVpcbAeZtsj2R5Zr0dEPfle4IErkAAzQ5AH0AAAAFZAAgAAAAAJMRyUW50oaTzspS6A3TUoXyC3gNYQoShUGPakMmeVZrBXMAIAAAAACona2Pqwt4U2PmFrtmu37jB9kQ/12okyAVtYa8TQkDiQVsACAAAAAAltJJKjCMyBTJ+4PkdDCPJdeX695P8P5h7WOZ+kmExMAAAzUwAH0AAAAFZAAgAAAAAByuYl8dBvfaZ0LO/81JW4hYypeNmvLMaxsIdvqMPrWoBXMAIAAAAABNddwobOUJzm9HOUD8BMZJqkNCUCqstHZkC76FIdNg9AVsACAAAAAAQQOkIQtkyNavqCnhQbNg3HfqrJdsAGaoxSJePJl1qXsAAzUxAH0AAAAFZAAgAAAAAHEzLtfmF/sBcYPPdj8867VmmQyU1xK9I/3Y0478azvABXMAIAAAAAAcmyFajZPnBTbO+oLInNwlApBocUekKkxz2hYFeSlQ+gVsACAAAAAAZ6IkrOVRcC8vSA6Vb4fPWZJrYexXhEabIuYIeXNsCSgAAzUyAH0AAAAFZAAgAAAAAJam7JYsZe2cN20ZYm2W3v1pisNt5PLiniMzymBLWyMtBXMAIAAAAABxCsKVMZMTn3n+R2L7pVz5nW804r8HcK0mCBw3jUXKXAVsACAAAAAA7j3JGnNtR64P4dJLeUoScFRGfa8ekjh3dvhw46sRFk0AAzUzAH0AAAAFZAAgAAAAAMXrXx0saZ+5gORmwM2FLuZG6iuO2YS+1IGPoAtDKoKBBXMAIAAAAADIQsxCr8CfFKaBcx8kIeSywnGh7JHjKRJ9vJd9x79y7wVsACAAAAAAcvBV+SykDYhmRFyVYwFYB9oBKBSHr55Jdz2cXeowsUQAAzU0AH0AAAAFZAAgAAAAACbzcUD3INSnCRspOKF7ubne74OK9L0FTZvi9Ay0JVDYBXMAIAAAAADPebVQH8Btk9rhBIoUOdSAdpPvz7qIY4UC2i6IGisSAQVsACAAAAAAiBunJi0mPnnXdnldiq+If8dcb/n6apHnaIFt+oyYO1kAAzU1AH0AAAAFZAAgAAAAACUc2CtD1MK/UTxtv+8iA9FoHEyTwdl43HKeSwDw2Lp5BXMAIAAAAACCIduIdw65bQMzRYRfjBJj62bc69T4QqH4QoWanwlvowVsACAAAAAAM0TV7S+aPVVzJOQ+cpSNKHTwyQ0mWa8tcHzfk3nR+9IAAzU2AH0AAAAFZAAgAAAAAHSaHWs/dnmI9sc7nB50VB2Bzs0kHapMHCQdyVEYY30TBXMAIAAAAACkV22lhEjWv/9/DubfHBAcwJggKI5mIbSK5L2nyqloqQVsACAAAAAAS19m7DccQxgryOsBJ3GsCs37yfQqNi1G+S6fCXpEhn4AAzU3AH0AAAAFZAAgAAAAAAL8jhNBG0KXXZhmZ0bPXtfgapJCB/AI+BEHB0eZ3C75BXMAIAAAAADHx/fPa639EBmGV5quLi8IQT600ifiKSOhTDOK19DnzwVsACAAAAAAlyLTDVkHxbayklD6Qymh3odIK1JHaOtps4f4HR+PcDgAAzU4AH0AAAAFZAAgAAAAAAxgeclNl09H7HvzD1oLwb2YpFca5eaX90uStYXHilqKBXMAIAAAAACMU5pSxzIzWlQxHyW170Xs9EhD1hURASQk+qkx7K5Y6AVsACAAAAAAJbMMwJfNftA7Xom8Bw/ghuZmSa3x12vTZxBUbV8m888AAzU5AH0AAAAFZAAgAAAAABmO7QD9vxWMmFjIHz13lyOeV6vHT6mYCsWxF7hb/yOjBXMAIAAAAACT9lmgkiqzuWG24afuzYiCeK9gmJqacmxAruIukd0xEAVsACAAAAAAZa0/FI/GkZR7CtX18Xg9Tn9zfxkD0UoaSt+pIO5t1t4AAzYwAH0AAAAFZAAgAAAAAB89SjLtDJkqEghRGyj6aQ/2qvWLNuMROoXmzbYbCMKMBXMAIAAAAAC8sywgND+CjhVTF6HnRQeay8y9/HnVzDI42dEPah28LQVsACAAAAAAoxv7UKh0RqUAWcOsQvU123zO1qZn73Xfib0qncZCB34AAzYxAH0AAAAFZAAgAAAAABN2alGq9Aats1mwERNGwL/fIwZSvVCe9/8XMHTFlpUpBXMAIAAAAACuDPjJgvvbBYhbLpjMiWUCsVppiYrhvR+yMysNPN8cZAVsACAAAAAAKpADjc4bzIZMi9Q/+oe0EMRJHYQt6dlo1x/lRquagqkAAzYyAH0AAAAFZAAgAAAAAL8YB6VAqGBiWD4CBv16IBscg5J7VQCTZu87n6pj+86KBXMAIAAAAAAmxm8e68geeyAdUjSMWBHzUjneVB0pG9TBXIoE6467hAVsACAAAAAAV76JZAlYpgC/Zl8awx2ArCg1uuyy2XVTSkp0wUMi/7UAAzYzAH0AAAAFZAAgAAAAAL4yLkCTV5Dmxa5toBu4JT8ge/cITAaURIOuFuOtFUkeBXMAIAAAAAAXoFNQOMGkAj7qEJP0wQafmFSXgWGeorDVbwyOxWLIsgVsACAAAAAAc4Un6dtIFe+AQ+RSfNWs3q63RTHhmyc+5GKRRdpWRv8AAzY0AH0AAAAFZAAgAAAAAEU8DoUp46YtYjNFS9kNXwdYxQ9IW27vCTb+VcqqfnKNBXMAIAAAAADe7vBOgYReE8X78k5ARuUnv4GmzPZzg6SbConf4L2G3wVsACAAAAAA78YHWVkp6HbZ0zS4UL2z/2pj9vPDcMDt7zTv6NcRsVsAAzY1AH0AAAAFZAAgAAAAAPa4yKTtkUtySuWo1ZQsp2QXtPb5SYqzA5vYDnS1P6c0BXMAIAAAAADKnF58R1sXlHlsHIvCBR3YWW/qk54z9CTDhZydkD1cOQVsACAAAAAAHW3ERalTFWKMzjuXF3nFh0pSrQxM/ojnPbPhc4v5MaQAAzY2AH0AAAAFZAAgAAAAAN5WJnMBmfgpuQPyonmY5X6OdRvuHw4nhsnGRnFAQ95VBXMAIAAAAACwftzu7KVV1rmGKwXtJjs3cJ1gE3apr8+N0SAg1F2cHwVsACAAAAAATDW0reyaCjbJuVLJzbSLx1OBuBoQu+090kgW4RurVacAAzY3AH0AAAAFZAAgAAAAACHvDsaPhoSb6DeGnKQ1QOpGYAgK82qpnqwcmzSeWaJHBXMAIAAAAABRq3C5+dOfnkAHM5Mg5hPB3O4jhwQlBgQWLA7Ph5bhgwVsACAAAAAAqkC8zYASvkVrp0pqmDyFCkPaDmD/ePAJpMuNOCBhni8AAzY4AH0AAAAFZAAgAAAAAOBePJvccPMJmy515KB1AkXF5Pi8NOG4V8psWy0SPRP+BXMAIAAAAAB3dOJG9xIDtEKCRzeNnPS3bFZepMj8UKBobKpSoCPqpgVsACAAAAAAPG3IxQVOdZrr509ggm5FKizWWoZPuVtOgOIGZ3m+pdEAAzY5AH0AAAAFZAAgAAAAABUvRrDQKEXLMdhnzXRdhiL6AGNs2TojPky+YVLXs+JnBXMAIAAAAAD1kYicbEEcPzD4QtuSYQQWDPq8fuUWGddpWayKn3dT9QVsACAAAAAA9+Sf7PbyFcY45hP9oTfjQiOUS3vEIAT8C0vOHymwYSUAAzcwAH0AAAAFZAAgAAAAAOvSnpujeKNen4pqc2HR63C5s5oJ1Vf4CsbKoYQvkwl5BXMAIAAAAACw2+vAMdibzd2YVVNfk81yXkFZP0WLJ82JBxJmXnYE+QVsACAAAAAArQ/E1ACyhK4ZyLqH9mNkCU7WClqRQTGyW9tciSGG/EMAAzcxAH0AAAAFZAAgAAAAAAo0xfGG7tJ3GWhgPVhW5Zn239nTD3PadShCNRc9TwdNBXMAIAAAAADZh243oOhenu0s/P/5KZLBDh9ADqKHtSWcXpO9D2sIjgVsACAAAAAAlgTPaoQKz+saU8rwCT3UiNOdG6hdpjzFx9GBn08ZkBEAABJjbQAAAAAAAAAAAAAQcGF5bG9hZElkAAAAAAAQZmlyc3RPcGVyYXRvcgABAAAAAA==", "subType": "06" } } } }, "limit": 1 } ], "ordered": true, "encryptionInformation": { "type": 1, "schema": { "default.default": { "escCollection": "enxcol_.default.esc", "ecocCollection": "enxcol_.default.ecoc", "fields": [ { "keyId": { "$binary": { "base64": "EjRWeBI0mHYSNBI0VniQEg==", "subType": "04" } }, "path": "encryptedDoubleNoPrecision", "bsonType": "double", "queries": { "queryType": "rangePreview", "contention": { "$numberLong": "0" }, "sparsity": { "$numberLong": "1" } } } ] } } } }, "command_name": "delete" } } ], "outcome": { "collection": { "data": [ { "_id": 0, "encryptedDoubleNoPrecision": { "$$type": "binData" }, "__safeContent__": [ { "$binary": { "base64": "5nRutVIyq7URVOVtbE4vM01APSIajAVnsShMwjBlzkM=", "subType": "00" } }, { "$binary": { "base64": "6YrBn2ofIw1b5ooakrLOwF41BWrps8OO0H9WH4/rtlE=", "subType": "00" } }, { "$binary": { "base64": "n+XAuFnP8Dov9TnhGFxNx0K/MnVM9WbJ7RouEu0ndO0=", "subType": "00" } }, { "$binary": { "base64": "yRXojuVdn5GQtD97qYlaCL6cOLmZ7Cvcb3wFjkLUIdM=", "subType": "00" } }, { "$binary": { "base64": "DuIkdRPITRs55I4SZmgomAHCIsDQmXRhW8+MOznkzSk=", "subType": "00" } }, { "$binary": { "base64": "SsBk+Et1lTbU+QRPx+xyJ/jMkmfG+QCvQEpip2YYrzA=", "subType": "00" } }, { "$binary": { "base64": "crCIzOd8KhHvvUlX7M1v9bhvU4pLdTc+X2SuqoKU5Ek=", "subType": "00" } }, { "$binary": { "base64": "YOWdCw4UrqnxkAaVjqmC4sKQDMVMHEpFGnlxpxdaU6E=", "subType": "00" } }, { "$binary": { "base64": "M3SShp81Ff8tQ632qKbv9MUcN6wjDaBReI0VXNu6Xh4=", "subType": "00" } }, { "$binary": { "base64": "gzHlSPxpM0hT75kQvWFzGlOxKvDoiKQZOr19V6l2zXI=", "subType": "00" } }, { "$binary": { "base64": "s3JnppOGYw9SL2Q1kMAZs948v2F5PrpXjGei/HioDWs=", "subType": "00" } }, { "$binary": { "base64": "cG6+3Gk/zEH68P/uuuwiAUVCuyJwa1LeV+t29FlPPAo=", "subType": "00" } }, { "$binary": { "base64": "dupdvR3AyJtM+g9NDKiaLVOtGca387JQp8w+V03m7Ig=", "subType": "00" } }, { "$binary": { "base64": "JqEQc5svj2jTvZ6LLA5ivE+kTb/0aRemSEmxk4G7Zrg=", "subType": "00" } }, { "$binary": { "base64": "szcXXXKnob+p3SoM4yED2R920LeJ7cVsclPMFTe4CeI=", "subType": "00" } }, { "$binary": { "base64": "o1QoGVXmuBdHwHm7aCtGMlMVKrjFdYvJXpoq6uhIAZ0=", "subType": "00" } }, { "$binary": { "base64": "Jfm5wPlqqLCJRGQIqRq2NGmpn7s0Vrih2H3YAOoI2YU=", "subType": "00" } }, { "$binary": { "base64": "zMHLb8ARbsYo8Ld05bqnGFf1Usha6EGb8QKwdSAyps0=", "subType": "00" } }, { "$binary": { "base64": "yQdtq9lh5pugL7/i0Bj/PuZUUBUIzf+7wj1rl5y736w=", "subType": "00" } }, { "$binary": { "base64": "wGWVZdO7qIuyDg/BqDgqjgoQ02h5YYgwXQB1oCin2NE=", "subType": "00" } }, { "$binary": { "base64": "by9HMLj6NTEpgztZ5HSN6GxImkXPcaFINYDzgZY33X8=", "subType": "00" } }, { "$binary": { "base64": "tWo0vbasi7bXmn/MsOx13VC1IsWtpx/nYp0uj4iMzdA=", "subType": "00" } }, { "$binary": { "base64": "tQQpndUYd5O87lOtrGjH3wl9VsOK0ray7RMasL90sBM=", "subType": "00" } }, { "$binary": { "base64": "cQjXEDCMsOpKLLf+vlTgIHA+cbSJdzqhbSX9Wvh95aA=", "subType": "00" } }, { "$binary": { "base64": "7yMpU48IxK9SzP2cx3VnTownGEwFmeFofuuFT97SuuY=", "subType": "00" } }, { "$binary": { "base64": "kSOx1kz0CmBgzKQHZlo65ZUY1DIv9A99JRm+Us2y6Ew=", "subType": "00" } }, { "$binary": { "base64": "ubQpdPBe6/xvtr+AcXdfYLSvYCR4ot0tivehkCsupb4=", "subType": "00" } }, { "$binary": { "base64": "xal+iCJ6FTefRQToyoNksc9NCZShyn04NDGi4IYrcoM=", "subType": "00" } }, { "$binary": { "base64": "d7jU4iOK50xHxlkSifcxlZFCM46TSgQzoYivxG3HNLY=", "subType": "00" } }, { "$binary": { "base64": "tJvl2nsBLBVzL3pp6sKWCL4UXeh3q/roYBJjSb74ve0=", "subType": "00" } }, { "$binary": { "base64": "OIUCaKRvIx9t1w6Hxlz1IcQTdPNCfdRNwnnTm10W+X0=", "subType": "00" } }, { "$binary": { "base64": "A9tvzsiElotOUVIB4CqfQp9mAwqvTM35YkmAR170aHA=", "subType": "00" } }, { "$binary": { "base64": "lI8gpK7hpb7c9x4RQugsxMnQay5LZJmwslZdvMx/dcE=", "subType": "00" } }, { "$binary": { "base64": "dNCzh40U0XvdKnSDi3HRQOWQftEsDVqc4uUvsVFGoq8=", "subType": "00" } }, { "$binary": { "base64": "IP+iwEBWBwVVZIdpaMu8k5+soFCz+TZkYn3drKZ9grE=", "subType": "00" } }, { "$binary": { "base64": "pnqyh6e0y5svHkJDShlN9CHV0WvMBE4QbtJpQw5ZCXc=", "subType": "00" } }, { "$binary": { "base64": "elEl42tbVDoRTLjAhZUFEtXiut4b3PVhg/1ZLZSQdtE=", "subType": "00" } }, { "$binary": { "base64": "vHuu2FxwclMHqyE6JBYbTYgbEkB0dqb/JuaxsvfwsmY=", "subType": "00" } }, { "$binary": { "base64": "xTf7NCe3Gf8QpE78HR5OknlLTKfs9J+RN9UZpH6fnso=", "subType": "00" } }, { "$binary": { "base64": "XiWSasRnJAulGR6+LCVD3mwRObXylqYWR9jvpywq12c=", "subType": "00" } }, { "$binary": { "base64": "MZMxEQ5ikx0PG1YFIExv0UnTZogsvgeOEZTpzvBDn4w=", "subType": "00" } }, { "$binary": { "base64": "yZMyMZBDrWbAhvnic7vvIYhmO9m5H2iuv0c8KNZrBzY=", "subType": "00" } }, { "$binary": { "base64": "xxM14hTPY5j0vvcK2C7YAEjzdsfUTFHozHC0hEo1bxI=", "subType": "00" } }, { "$binary": { "base64": "+01rqR1xVwkpGXcstbk1ItJqFVjH6Q8MGxEN3Cm9Y1A=", "subType": "00" } }, { "$binary": { "base64": "xOpLV0Z2VTRJ3iWtnWZcsyjXubTIkYWo31cO+HV1o1k=", "subType": "00" } }, { "$binary": { "base64": "BWUOLqgLBqc5NwxVlSV5H3KFQPXbCp7mdo+jF+8cJqY=", "subType": "00" } }, { "$binary": { "base64": "fuQb1S6xZDGlrEbK+kI23aL53PP1PVNwqICnZNt9Yzg=", "subType": "00" } }, { "$binary": { "base64": "SfscnoibFttahLdPVC4Ee+47ewGFKpDSU7M6HX19bKE=", "subType": "00" } }, { "$binary": { "base64": "rpSW2awybNVeKtat91VFxqbINoTfNhPfQAu+d73Xtf8=", "subType": "00" } }, { "$binary": { "base64": "9M/CP9ccOIIj2LLFmE0GFDO0Ban2wsNalEXfM6+h+1s=", "subType": "00" } }, { "$binary": { "base64": "WrEMG49l1ye4MhXs5ZS9tz8P6h+hDvthIg/2wW9ne1Q=", "subType": "00" } }, { "$binary": { "base64": "ImNhbfeyfH8qIEeA5ic0s3dAQBdzzTBS+CPsNih9vZ0=", "subType": "00" } }, { "$binary": { "base64": "dWP33YDSn04UKJN2ogh2Rui0iW/0q2y18OCDRVcfyoo=", "subType": "00" } }, { "$binary": { "base64": "lYv0isAtfGh6H9tdp3cp2eHU7q2J+uk7QrgcxtK3w7Y=", "subType": "00" } }, { "$binary": { "base64": "VGMoamB/+7zTOYcY/pqJc96xlv2PdW4hwsIAEIslTDQ=", "subType": "00" } }, { "$binary": { "base64": "yNeBWMF7BnD9wVwz2PgJsvWr77QiVvvWUvJF0+fqBug=", "subType": "00" } }, { "$binary": { "base64": "SfpvObJ+tJBXSvqeN7vlOfmhYign635lciYAJIjUtY8=", "subType": "00" } }, { "$binary": { "base64": "dsen4NqjzVGjpjufiTMs3+gqeD09EbnuogPgxrJECwg=", "subType": "00" } }, { "$binary": { "base64": "pxCWVM3sn19NsFEpgHbgLa+PmYlhN3mMiP0Wk8kJhYw=", "subType": "00" } }, { "$binary": { "base64": "q11KNvJszjYIB9n9HcC+N4uz11a3eRj1L3BH9scKMDQ=", "subType": "00" } }, { "$binary": { "base64": "A1PmkgcEToWh1JiVWE6mI5jUu7poxWWuCUt/cgRUUDc=", "subType": "00" } }, { "$binary": { "base64": "qJo3Hu4PJeanL7XEaWXO/n3YsodhZyd+MJOOmB9Kpd8=", "subType": "00" } }, { "$binary": { "base64": "BkBKLO8URFscfRY9Bav/1+L9mLohDgNr/MkZtGiraIs=", "subType": "00" } }, { "$binary": { "base64": "rZq5WA3Hx3xthOyHAJXK//f8pE2qbz7YKu3TIMp9GFY=", "subType": "00" } }, { "$binary": { "base64": "X07a/Lm80p5xd4RFs1dNmw+90tmPDPdGiAKVZkxd4zY=", "subType": "00" } } ] } ] } } } ] } fle2v2-Range-Double-FindOneAndUpdate.json000066400000000000000000001366341462766011000365030ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/client-side-encryption/spec/legacy{ "runOn": [ { "minServerVersion": "7.0.0", "topology": [ "replicaset", "sharded", "load-balanced" ] } ], "database_name": "default", "collection_name": "default", "data": [], "encrypted_fields": { "fields": [ { "keyId": { "$binary": { "base64": "EjRWeBI0mHYSNBI0VniQEg==", "subType": "04" } }, "path": "encryptedDoubleNoPrecision", "bsonType": "double", "queries": { "queryType": "rangePreview", "contention": { "$numberLong": "0" }, "sparsity": { "$numberLong": "1" } } } ] }, "key_vault_data": [ { "_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" } } ], "tests": [ { "description": "FLE2 Range Double. FindOneAndUpdate.", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "local": { "key": { "$binary": { "base64": "Mng0NCt4ZHVUYUJCa1kxNkVyNUR1QURhZ2h2UzR2d2RrZzh0cFBwM3R6NmdWMDFBMUN3YkQ5aXRRMkhGRGdQV09wOGVNYUMxT2k3NjZKelhaQmRCZGJkTXVyZG9uSjFk", "subType": "00" } } } } } }, "operations": [ { "name": "insertOne", "arguments": { "document": { "_id": 0, "encryptedDoubleNoPrecision": { "$numberDouble": "0" } } } }, { "name": "insertOne", "arguments": { "document": { "_id": 1, "encryptedDoubleNoPrecision": { "$numberDouble": "1" } } } }, { "name": "findOneAndUpdate", "arguments": { "filter": { "encryptedDoubleNoPrecision": { "$gt": { "$numberDouble": "0" } } }, "update": { "$set": { "encryptedDoubleNoPrecision": { "$numberDouble": "2" } } }, "returnDocument": "Before" }, "result": { "_id": 1, "encryptedDoubleNoPrecision": { "$numberDouble": "1" } } } ], "expectations": [ { "command_started_event": { "command": { "listCollections": 1, "filter": { "name": "default" } }, "command_name": "listCollections" } }, { "command_started_event": { "command": { "find": "datakeys", "filter": { "$or": [ { "_id": { "$in": [ { "$binary": { "base64": "EjRWeBI0mHYSNBI0VniQEg==", "subType": "04" } } ] } }, { "keyAltNames": { "$in": [] } } ] }, "$db": "keyvault", "readConcern": { "level": "majority" } }, "command_name": "find" } }, { "command_started_event": { "command": { "insert": "default", "documents": [ { "_id": 0, "encryptedDoubleNoPrecision": { "$$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": "encryptedDoubleNoPrecision", "bsonType": "double", "queries": { "queryType": "rangePreview", "contention": { "$numberLong": "0" }, "sparsity": { "$numberLong": "1" } } } ] } } } }, "command_name": "insert" } }, { "command_started_event": { "command": { "insert": "default", "documents": [ { "_id": 1, "encryptedDoubleNoPrecision": { "$$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": "encryptedDoubleNoPrecision", "bsonType": "double", "queries": { "queryType": "rangePreview", "contention": { "$numberLong": "0" }, "sparsity": { "$numberLong": "1" } } } ] } } } }, "command_name": "insert" } }, { "command_started_event": { "command": { "findAndModify": "default", "query": { "encryptedDoubleNoPrecision": { "$gt": { "$binary": { "base64": "DYckAAADcGF5bG9hZABXJAAABGcAQyQAAAMwAH0AAAAFZAAgAAAAAHgYoMGjEE6fAlAhICv0+doHcVX8CmMVxyq7+jlyGrvmBXMAIAAAAAC/5MQZgTHuIr/O5Z3mXPvqrom5JTQ8IeSpQGhO9sB+8gVsACAAAAAAuPSXVmJUAUpTQg/A9Bu1hYczZF58KEhVofakygbsvJQAAzEAfQAAAAVkACAAAAAA2kiWNvEc4zunJ1jzvuClFC9hjZMYruKCqAaxq+oY8EAFcwAgAAAAACofIS72Cm6s866UCk+evTH3CvKBj/uZd72sAL608rzTBWwAIAAAAADuCQ/M2xLeALF0UFZtJb22QGOhHmJv6xoO+kZIHcDeiAADMgB9AAAABWQAIAAAAABkfoBGmU3hjYBvQbjNW19kfXneBQsQQPRfUL3UAwI2cAVzACAAAAAAUpK2BUOqX/DGdX5YJniEZMWkofxHqeAbXceEGJxhp8AFbAAgAAAAAKUaLzIldNIZv6RHE+FwbMjzcNHqPESwF/37mm43VPrsAAMzAH0AAAAFZAAgAAAAAFNprhQ3ZwIcYbuzLolAT5n/vc14P9kUUQComDu6eFyKBXMAIAAAAAAcx9z9pk32YbPV/sfPZl9ALIEVsqoLXgqWLVK/tP+heAVsACAAAAAA/qxvuvJbAHwwhfrPVpmCFzNvg2cU/NXaWgqgYUZpgXwAAzQAfQAAAAVkACAAAAAAODI+pB2pCuB+YmNEUAgtMfNdt3DmSkrJ96gRzLphgb8FcwAgAAAAAAT7dewFDxUDECQ3zVq75/cUN4IP+zsqhkP5+czUwlJIBWwAIAAAAACFGeOtd5zBXTJ4JYonkn/HXZfHipUlqGwIRUcH/VTatwADNQB9AAAABWQAIAAAAACNAk+yTZ4Ewk1EnotQK8O3h1gg9I7pr9q2+4po1iJVgAVzACAAAAAAUj/LesmtEsgqYVzMJ67umVA11hJTdDXwbxDoQ71vWyUFbAAgAAAAABlnhpgTQ0WjLb5u0b/vEydrCeFjVynKd7aqb+UnvVLeAAM2AH0AAAAFZAAgAAAAAD/FIrGYFDjyYmVb7oTMVwweWP7A6F9LnyIuNO4MjBnXBXMAIAAAAACIZgJCQRZu7NhuNMyOqCn1tf+DfU1qm10TPCfj5JYV3wVsACAAAAAA5hmY4ptuNxULGf87SUFXQWGAONsL9U29duh8xqsHtxoAAzcAfQAAAAVkACAAAAAAciRW40ORJLVwchOEpz87Svb+5toAFM6LxDWv928ECwQFcwAgAAAAAN0dipyESIkszfjRzdDi8kAGaa2Hf4wrPAtiWwboZLuxBWwAIAAAAAANr4o/+l1OIbbaX5lZ3fQ/WIeOcEXjNI1F0WbSgQrzaQADOAB9AAAABWQAIAAAAACZqAyCzYQupJ95mrBJX54yIz9VY7I0WrxpNYElCI4dTQVzACAAAAAA/eyJb6d1xfE+jJlVXMTD3HS/NEYENPVKAuj56Dr2dSEFbAAgAAAAANkSt154Or/JKb31VvbZFV46RPgUp8ff/hcPORL7PpFBAAM5AH0AAAAFZAAgAAAAAI5bm3YO0Xgf0VT+qjVTTfvckecM3Cwqj7DTKZXf8/NXBXMAIAAAAAD/m+h8fBhWaHm6Ykuz0WX1xL4Eme3ErLObyEVJf8NCywVsACAAAAAAfb1VZZCqs2ivYbRzX4p5CtaCkKW+g20Pr57FWXzEZi8AAzEwAH0AAAAFZAAgAAAAANqo4+p6qdtCzcB4BX1wQ6llU7eFBnuu4MtZwp4B6mDlBXMAIAAAAAAGiz+VaukMZ+6IH4jtn4KWWdKK4/W+O+gRioQDrfzpMgVsACAAAAAAG4YYkTp80EKo59mlHExDodRQFR7njhR5dmISwUJ6ukAAAzExAH0AAAAFZAAgAAAAAPrFXmHP2Y4YAm7b/aqsdn/DPoDkv7B8egWkfe23XsM1BXMAIAAAAAAGhwpKAr7skeqHm3oseSbO7qKNhmYsuUrECBxJ5k+D2AVsACAAAAAAAqPQi9luYAu3GrFCEsVjd9z2zIDcp6SPTR2w6KQEr+IAAzEyAH0AAAAFZAAgAAAAABzjYxwAjXxXc0Uxv18rH8I3my0Aguow0kTwKyxbrm+cBXMAIAAAAADVbqJVr6IdokuhXkEtXF0C2gINLiAjMVN20lE20Vmp2QVsACAAAAAAD7K1Fx4gFaaizkIUrf+EGXQeG7QX1jadhGc6Ji471H8AAzEzAH0AAAAFZAAgAAAAAFMm2feF2fFCm/UC6AfIyepX/xJDSmnnolQIBnHcPmb5BXMAIAAAAABLI11kFrQoaNVZFmq/38aRNImPOjdJh0Lo6irI8M/AaAVsACAAAAAAOWul0oVqJ9CejD2RqphhTC98DJeRQy5EwbNerU2+4l8AAzE0AH0AAAAFZAAgAAAAAJvXB3KyNiNtQko4SSzo/9b2qmM2zU9CQTTDfLSBWMgRBXMAIAAAAAAvjuVP7KsLRDeqVqRziTKpBrjVyqKiIbO9Gw8Wl2wFTAVsACAAAAAADlE+oc1ins+paNcaOZJhBlKlObDJ4VQORWjFYocM4LgAAzE1AH0AAAAFZAAgAAAAAPGdcxDiid8z8XYnfdDivNMYVPgBKdGOUw6UStU+48CdBXMAIAAAAAARj6g1Ap0eEfuCZ4X2TsEw+Djrhto3fA5nLwPaY0vCTgVsACAAAAAAoHqiwGOUkBu8SX5U1yHho+UIFdSN2MdQN5s6bQ0EsJYAAzE2AH0AAAAFZAAgAAAAAP5rGPrYGt3aKob5f/ldP0qrW7bmWvqnKY4QwdDWz400BXMAIAAAAADTQkW2ymaaf/bhteOOGmSrIR97bAnJx+yN3yMj1bTeewVsACAAAAAADyQnHGH2gF4w4L8axUsSTf6Ubk7L5/eoFOJk12MtZAoAAzE3AH0AAAAFZAAgAAAAAAlz6wJze5UkIxKpJOZFGCOf3v2KByWyI6NB6JM9wNcBBXMAIAAAAABUC7P/neUIHHoZtq0jFVBHY75tSFYr1Y5S16YN5XxC1QVsACAAAAAAgvxRbXDisNnLY3pfsjDdnFLtkvYUC4lhA68eBXc7KAwAAzE4AH0AAAAFZAAgAAAAAFJ8AtHcjia/9Y5pLEc3qVgH5xKiXw12G9Kn2A1EY8McBXMAIAAAAAAxe7Bdw7eUSBk/oAawa7uicTEDgXLymRNhBy1LAxhDvwVsACAAAAAAxKPaIBKVx3jTA+R/el7P7AZ7efrmTGjJs3Hj/YdMddwAAzE5AH0AAAAFZAAgAAAAAO8uwQUaKFb6vqR3Sv3Wn4QAonC2exOC9lGG1juqP5DtBXMAIAAAAABZf1KyJgQg8/Rf5c02DgDK2aQu0rNCOvaL60ohDHyY+gVsACAAAAAAqyEjfKC8lYoIfoXYHUqHZPoaA6EK5BAZy5dxXZmay4kAAzIwAH0AAAAFZAAgAAAAAE8YtqyRsGCeiR6hhiyisR/hccmK4nZqIMzO4lUBmEFzBXMAIAAAAAC1UYOSKqAeG1UJiKjWFVskRhuFKpj9Ezy+lICZvFlN5AVsACAAAAAA6Ct9nNMKyRazn1OKnRKagm746CGu+jyhbL1qJnZxGi0AAzIxAH0AAAAFZAAgAAAAAPhCrMausDx1QUIEqp9rUdRKyM6a9AAx7jQ3ILIu8wNIBXMAIAAAAACmH8lotGCiF2q9VQxhsS+7LAZv79VUAsOUALaGxE/EpAVsACAAAAAAnc1xCKfdvbUEc8F7XZqlNn1C+hZTtC0I9I3LL06iaNkAAzIyAH0AAAAFZAAgAAAAAOBi/GAYFcstMSJPgp3VkMiuuUUCrZytvqYaU8dwm8v2BXMAIAAAAACEZSZVyD3pKzGlbdwlYmWQhHHTV5SnNLknl2Gw8IaUTQVsACAAAAAAfsLZsEDcWSuNsIo/TD1ReyQW75HPMgmuKZuWFOLKRLoAAzIzAH0AAAAFZAAgAAAAAIQuup+YGfH3mflzWopN8J1X8o8a0d9CSGIvrA5HOzraBXMAIAAAAADYvNLURXsC2ITMqK14LABQBI+hZZ5wNf24JMcKLW+84AVsACAAAAAACzfjbTBH7IwDU91OqLAz94RFkoqBOkzKAqQb55gT4/MAAzI0AH0AAAAFZAAgAAAAAKsh0ADyOnVocFrOrf6MpTrNvAj8iaiE923DPryu124gBXMAIAAAAADg24a8NVE1GyScc6tmnTbmu5ulzO+896fE92lN08MeswVsACAAAAAAaPxcOIxnU7But88/yadOuDJDMcCywwrRitaxMODT4msAAzI1AH0AAAAFZAAgAAAAAKkVC2Y6HtRmv72tDnPUSjJBvse7SxLqnr09/Uuj9sVVBXMAIAAAAABYNFUkH7ylPMN+Bc3HWX1e0flGYNbtJNCY9SltJCW/UAVsACAAAAAAZYK/f9H4OeihmpiFMH7Wm7uLvs2s92zNA8wyrNZTsuMAAzI2AH0AAAAFZAAgAAAAADDggcwcb/Yn1Kk39sOHsv7BO/MfP3m/AJzjGH506Wf9BXMAIAAAAAAYZIsdjICS0+BDyRUPnrSAZfPrwtuMaEDEn0/ijLNQmAVsACAAAAAAGPnYVvo2ulO9z4LGd/69NAklfIcZqZvFX2KK0s+FcTUAAzI3AH0AAAAFZAAgAAAAAEWY7dEUOJBgjOoWVht1wLehsWAzB3rSOBtLgTuM2HC8BXMAIAAAAAAAoswiHRROurjwUW8u8D5EUT+67yvrgpB/j6PzBDAfVwVsACAAAAAA6NhRTYFL/Sz4tao7vpPjLNgAJ0FX6P/IyMW65qT6YsMAAzI4AH0AAAAFZAAgAAAAAPZaapeAUUFPA7JTCMOWHJa9lnPFh0/gXfAPjA1ezm4ZBXMAIAAAAACmJvLY2nivw7/b3DOKH/X7bBXjJwoowqb1GtEFO3OYgAVsACAAAAAA/JcUoyKacCB1NfmH8vYqC1f7rd13KShrQqV2r9QBP44AAzI5AH0AAAAFZAAgAAAAAK00u6jadxCZAiA+fTsPVDsnW5p5LCr4+kZZZOTDuZlfBXMAIAAAAAAote4zTEYMDgaaQbAdN8Dzv93ljPLdGjJzvnRn3KXgtQVsACAAAAAAxXd9Mh6R3mnJy8m7UfqMKi6oD5DlZpkaOz6bEjMOdiwAAzMwAH0AAAAFZAAgAAAAAFbgabdyymiEVYYwtJSWa7lfl/oYuj/SukzJeDOR6wPVBXMAIAAAAADAFGFjS1vPbN6mQEhkDYTD6V2V23Ys9gUEUMGNvMPkaAVsACAAAAAAL/D5Sze/ZoEanZLK0IeEkhgVkxEjMWVCfmJaD3a8uNIAAzMxAH0AAAAFZAAgAAAAABNMR6UBv2E627CqLtQ/eDYx7OEwQ7JrR4mSHFa1N8tLBXMAIAAAAAAxH4gucI4UmNVB7625C6hFSVCuIpJO3lusJlPuL8H5EQVsACAAAAAAVLHNg0OUVqZ7WGOP53BkTap9FOw9dr1P4J8HxqFqU04AAzMyAH0AAAAFZAAgAAAAAG8cd6WBneNunlqrQ2EmNf35W7OGObGq9WL4ePX+LUDmBXMAIAAAAAAjJ2+sX87NSis9hBsgb1QprVRnO7Bf+GObCGoUqyPE4wVsACAAAAAAs9c9SM49/pWmyUQKslpt3RTMBNSRppfNO0JBvUqHPg0AAzMzAH0AAAAFZAAgAAAAAFWOUGkUpy8yf6gB3dio/aOfRKh7XuhvsUj48iESFJrGBXMAIAAAAAAY7sCDMcrUXvNuL6dO0m11WyijzXZvPIcOKob6IpC4PQVsACAAAAAAJOP+EHz6awDb1qK2bZQ3kTV7wsj5Daj/IGAWh4g7omAAAzM0AH0AAAAFZAAgAAAAAGUrIdKxOihwNmo6B+aG+Ag1qa0+iqdksHOjQj+Oy9bZBXMAIAAAAABwa5dbI2KmzBDNBTQBEkjZv4sPaeRkRNejcjdVymRFKQVsACAAAAAA4ml/nm0gJNTcJ4vuD+T2Qfq2fQZlibJp/j6MOGDrbHMAAzM1AH0AAAAFZAAgAAAAAOx89xV/hRk64/CkM9N2EMK6aldII0c8smdcsZ46NbP8BXMAIAAAAADBF6tfQ+7q9kTuLyuyrSnDgmrdmrXkdhl980i1KHuGHgVsACAAAAAACUqiFqHZdGbwAA+hN0YUE5zFg+H+dabIB4dj5/75W/YAAzM2AH0AAAAFZAAgAAAAAMkN0L1oQWXhjwn9rAdudcYeN8/5VdCKU8cmDt7BokjsBXMAIAAAAAAT62pGXoRwExe9uvgYOI0hg5tOxilrWfoEmT0SMglWJwVsACAAAAAAlVz4dhiprSbUero6JFfxzSJGclg63oAkAmgbSwbcYxIAAzM3AH0AAAAFZAAgAAAAANxfa4xCoaaB7k1C1RoH1LBhsCbN2yEq15BT9b+iqEC4BXMAIAAAAACAX9LV8Pemfw7NF0iB1/85NzM1Ef+1mUfyehacUVgobQVsACAAAAAAVq4xpbymLk0trPC/a2MvB39I7hRiX8EJsVSI5E5hSBkAAzM4AH0AAAAFZAAgAAAAAOYIYoWkX7dGuyKfi3XssUlc7u/gWzqrR9KMkikKVdmSBXMAIAAAAABVF2OYjRTGi9Tw8XCAwZWLpX35Yl271TlNWp6N/nROhAVsACAAAAAA0nWwYzXQ1+EkDvnGq+SMlq20z+j32Su+i/A95SggPb4AAzM5AH0AAAAFZAAgAAAAAIy0+bXZi10QC+q7oSOLXK5Fee7VEk/qHSXukfeVIfgzBXMAIAAAAAAQ3IIV/JQCHW95AEbH5zGIHtJqyuPjWPMIZ+VmQHlxEwVsACAAAAAAp0jYsyohKv9Pm+4k+DplEGbl9WLZpAJzitrcDj4CNsMAAzQwAH0AAAAFZAAgAAAAAL5SOJQ3LOhgdXJ5v086NNeAl1qonQnchObdpZJ1kHeEBXMAIAAAAAA+tEqTXODtik+ydJZSnUqXF9f18bPeze9eWtR7ExZJgQVsACAAAAAAbrkZCVgB9Qsp4IAbdf+bD4fT6Boqk5UtuA/zhNrh1y0AAzQxAH0AAAAFZAAgAAAAAKl8zcHJRDjSjJeV/WvMxulW1zrTFtaeBy/aKKhadc6UBXMAIAAAAADBdWQl5SBIvtZZLIHszePwkO14W1mQ0izUk2Ov21cPNAVsACAAAAAAHErCYycpqiIcCZHdmPL1hi+ovLQk4TAvENpfLdTRamQAAzQyAH0AAAAFZAAgAAAAAFvotcNaoKnVt5CBCOPwjexFO0WGWuaIGL6H/6KSau+6BXMAIAAAAAD2y2mBN5xPu5PJoY2zcr0GnQDtHRBogA5+xzIxccE9fwVsACAAAAAAdS34xzJesnUfxLCcc1U7XzUqLy8MAzV/tcjbqaD3lkMAAzQzAH0AAAAFZAAgAAAAAPezU0/vNT4Q4YKbTbaeHqcwNLT+IjW/Y9QFpIooihjPBXMAIAAAAACj2x4O4rHter8ZnTws5LAP9jJ/6kk9C/V3vL50LoFZHAVsACAAAAAAQdBDF3747uCVP5lB/zr8VmzxJfTSZHBKeIgm5FyONXwAAzQ0AH0AAAAFZAAgAAAAAMqpayM2XotEFmm0gwQd9rIzApy0X+7HfOhNk6VU7F5lBXMAIAAAAACJR9+q5T9qFHXFNgGbZnPubG8rkO6cwWhzITQTmd6VgwVsACAAAAAAOZLQ6o7e4mVfDzbpQioa4d3RoTvqwgnbmc5Qh2wsZuoAAzQ1AH0AAAAFZAAgAAAAANCeyW+3oebaQk+aqxNVhAcT/BZ5nhsTVdKS3tMrLSvWBXMAIAAAAADxRFMDhkyuEc++WnndMfoUMLNL7T7rWoeblcrpSI6soQVsACAAAAAAdBuBMJ1lxt0DRq9pOZldQqchLs3B/W02txcMLD490FEAAzQ2AH0AAAAFZAAgAAAAAIbo5YBTxXM7HQhl7UP9NNgpPGFkBx871r1B65G47+K8BXMAIAAAAAC21dJSxnEhnxO5gzN5/34BL4von45e1meW92qowzb8fQVsACAAAAAAm3Hk2cvBN0ANaR5jzeZE5TsdxDvJCTOT1I01X7cNVaYAAzQ3AH0AAAAFZAAgAAAAABm/6pF96j26Jm7z5KkY1y33zcAEXLx2n0DwC03bs/ixBXMAIAAAAAD01OMvTZI/mqMgxIhA5nLs068mW+GKl3OW3ilf2D8+LgVsACAAAAAAaLvJDrqBESTNZSdcXsd+8GXPl8ZkUsGpeYuyYVv/kygAAzQ4AH0AAAAFZAAgAAAAAJ/D3+17gaQdkBqkL2wMwccdmCaVOtxzIkM8VyI4xI5zBXMAIAAAAAAggLVmkc5u+YzBR+oNE+XgLVp64fC6MzUb/Ilu/Jsw0AVsACAAAAAACz3HVKdWkx82/kGbVpcbAeZtsj2R5Zr0dEPfle4IErkAAzQ5AH0AAAAFZAAgAAAAAJMRyUW50oaTzspS6A3TUoXyC3gNYQoShUGPakMmeVZrBXMAIAAAAACona2Pqwt4U2PmFrtmu37jB9kQ/12okyAVtYa8TQkDiQVsACAAAAAAltJJKjCMyBTJ+4PkdDCPJdeX695P8P5h7WOZ+kmExMAAAzUwAH0AAAAFZAAgAAAAAByuYl8dBvfaZ0LO/81JW4hYypeNmvLMaxsIdvqMPrWoBXMAIAAAAABNddwobOUJzm9HOUD8BMZJqkNCUCqstHZkC76FIdNg9AVsACAAAAAAQQOkIQtkyNavqCnhQbNg3HfqrJdsAGaoxSJePJl1qXsAAzUxAH0AAAAFZAAgAAAAAHEzLtfmF/sBcYPPdj8867VmmQyU1xK9I/3Y0478azvABXMAIAAAAAAcmyFajZPnBTbO+oLInNwlApBocUekKkxz2hYFeSlQ+gVsACAAAAAAZ6IkrOVRcC8vSA6Vb4fPWZJrYexXhEabIuYIeXNsCSgAAzUyAH0AAAAFZAAgAAAAAJam7JYsZe2cN20ZYm2W3v1pisNt5PLiniMzymBLWyMtBXMAIAAAAABxCsKVMZMTn3n+R2L7pVz5nW804r8HcK0mCBw3jUXKXAVsACAAAAAA7j3JGnNtR64P4dJLeUoScFRGfa8ekjh3dvhw46sRFk0AAzUzAH0AAAAFZAAgAAAAAMXrXx0saZ+5gORmwM2FLuZG6iuO2YS+1IGPoAtDKoKBBXMAIAAAAADIQsxCr8CfFKaBcx8kIeSywnGh7JHjKRJ9vJd9x79y7wVsACAAAAAAcvBV+SykDYhmRFyVYwFYB9oBKBSHr55Jdz2cXeowsUQAAzU0AH0AAAAFZAAgAAAAACbzcUD3INSnCRspOKF7ubne74OK9L0FTZvi9Ay0JVDYBXMAIAAAAADPebVQH8Btk9rhBIoUOdSAdpPvz7qIY4UC2i6IGisSAQVsACAAAAAAiBunJi0mPnnXdnldiq+If8dcb/n6apHnaIFt+oyYO1kAAzU1AH0AAAAFZAAgAAAAACUc2CtD1MK/UTxtv+8iA9FoHEyTwdl43HKeSwDw2Lp5BXMAIAAAAACCIduIdw65bQMzRYRfjBJj62bc69T4QqH4QoWanwlvowVsACAAAAAAM0TV7S+aPVVzJOQ+cpSNKHTwyQ0mWa8tcHzfk3nR+9IAAzU2AH0AAAAFZAAgAAAAAHSaHWs/dnmI9sc7nB50VB2Bzs0kHapMHCQdyVEYY30TBXMAIAAAAACkV22lhEjWv/9/DubfHBAcwJggKI5mIbSK5L2nyqloqQVsACAAAAAAS19m7DccQxgryOsBJ3GsCs37yfQqNi1G+S6fCXpEhn4AAzU3AH0AAAAFZAAgAAAAAAL8jhNBG0KXXZhmZ0bPXtfgapJCB/AI+BEHB0eZ3C75BXMAIAAAAADHx/fPa639EBmGV5quLi8IQT600ifiKSOhTDOK19DnzwVsACAAAAAAlyLTDVkHxbayklD6Qymh3odIK1JHaOtps4f4HR+PcDgAAzU4AH0AAAAFZAAgAAAAAAxgeclNl09H7HvzD1oLwb2YpFca5eaX90uStYXHilqKBXMAIAAAAACMU5pSxzIzWlQxHyW170Xs9EhD1hURASQk+qkx7K5Y6AVsACAAAAAAJbMMwJfNftA7Xom8Bw/ghuZmSa3x12vTZxBUbV8m888AAzU5AH0AAAAFZAAgAAAAABmO7QD9vxWMmFjIHz13lyOeV6vHT6mYCsWxF7hb/yOjBXMAIAAAAACT9lmgkiqzuWG24afuzYiCeK9gmJqacmxAruIukd0xEAVsACAAAAAAZa0/FI/GkZR7CtX18Xg9Tn9zfxkD0UoaSt+pIO5t1t4AAzYwAH0AAAAFZAAgAAAAAB89SjLtDJkqEghRGyj6aQ/2qvWLNuMROoXmzbYbCMKMBXMAIAAAAAC8sywgND+CjhVTF6HnRQeay8y9/HnVzDI42dEPah28LQVsACAAAAAAoxv7UKh0RqUAWcOsQvU123zO1qZn73Xfib0qncZCB34AAzYxAH0AAAAFZAAgAAAAABN2alGq9Aats1mwERNGwL/fIwZSvVCe9/8XMHTFlpUpBXMAIAAAAACuDPjJgvvbBYhbLpjMiWUCsVppiYrhvR+yMysNPN8cZAVsACAAAAAAKpADjc4bzIZMi9Q/+oe0EMRJHYQt6dlo1x/lRquagqkAAzYyAH0AAAAFZAAgAAAAAL8YB6VAqGBiWD4CBv16IBscg5J7VQCTZu87n6pj+86KBXMAIAAAAAAmxm8e68geeyAdUjSMWBHzUjneVB0pG9TBXIoE6467hAVsACAAAAAAV76JZAlYpgC/Zl8awx2ArCg1uuyy2XVTSkp0wUMi/7UAAzYzAH0AAAAFZAAgAAAAAL4yLkCTV5Dmxa5toBu4JT8ge/cITAaURIOuFuOtFUkeBXMAIAAAAAAXoFNQOMGkAj7qEJP0wQafmFSXgWGeorDVbwyOxWLIsgVsACAAAAAAc4Un6dtIFe+AQ+RSfNWs3q63RTHhmyc+5GKRRdpWRv8AAzY0AH0AAAAFZAAgAAAAAEU8DoUp46YtYjNFS9kNXwdYxQ9IW27vCTb+VcqqfnKNBXMAIAAAAADe7vBOgYReE8X78k5ARuUnv4GmzPZzg6SbConf4L2G3wVsACAAAAAA78YHWVkp6HbZ0zS4UL2z/2pj9vPDcMDt7zTv6NcRsVsAAzY1AH0AAAAFZAAgAAAAAPa4yKTtkUtySuWo1ZQsp2QXtPb5SYqzA5vYDnS1P6c0BXMAIAAAAADKnF58R1sXlHlsHIvCBR3YWW/qk54z9CTDhZydkD1cOQVsACAAAAAAHW3ERalTFWKMzjuXF3nFh0pSrQxM/ojnPbPhc4v5MaQAAzY2AH0AAAAFZAAgAAAAAN5WJnMBmfgpuQPyonmY5X6OdRvuHw4nhsnGRnFAQ95VBXMAIAAAAACwftzu7KVV1rmGKwXtJjs3cJ1gE3apr8+N0SAg1F2cHwVsACAAAAAATDW0reyaCjbJuVLJzbSLx1OBuBoQu+090kgW4RurVacAAzY3AH0AAAAFZAAgAAAAACHvDsaPhoSb6DeGnKQ1QOpGYAgK82qpnqwcmzSeWaJHBXMAIAAAAABRq3C5+dOfnkAHM5Mg5hPB3O4jhwQlBgQWLA7Ph5bhgwVsACAAAAAAqkC8zYASvkVrp0pqmDyFCkPaDmD/ePAJpMuNOCBhni8AAzY4AH0AAAAFZAAgAAAAAOBePJvccPMJmy515KB1AkXF5Pi8NOG4V8psWy0SPRP+BXMAIAAAAAB3dOJG9xIDtEKCRzeNnPS3bFZepMj8UKBobKpSoCPqpgVsACAAAAAAPG3IxQVOdZrr509ggm5FKizWWoZPuVtOgOIGZ3m+pdEAAzY5AH0AAAAFZAAgAAAAABUvRrDQKEXLMdhnzXRdhiL6AGNs2TojPky+YVLXs+JnBXMAIAAAAAD1kYicbEEcPzD4QtuSYQQWDPq8fuUWGddpWayKn3dT9QVsACAAAAAA9+Sf7PbyFcY45hP9oTfjQiOUS3vEIAT8C0vOHymwYSUAAzcwAH0AAAAFZAAgAAAAAOvSnpujeKNen4pqc2HR63C5s5oJ1Vf4CsbKoYQvkwl5BXMAIAAAAACw2+vAMdibzd2YVVNfk81yXkFZP0WLJ82JBxJmXnYE+QVsACAAAAAArQ/E1ACyhK4ZyLqH9mNkCU7WClqRQTGyW9tciSGG/EMAAzcxAH0AAAAFZAAgAAAAAAo0xfGG7tJ3GWhgPVhW5Zn239nTD3PadShCNRc9TwdNBXMAIAAAAADZh243oOhenu0s/P/5KZLBDh9ADqKHtSWcXpO9D2sIjgVsACAAAAAAlgTPaoQKz+saU8rwCT3UiNOdG6hdpjzFx9GBn08ZkBEAABJjbQAAAAAAAAAAAAAQcGF5bG9hZElkAAAAAAAQZmlyc3RPcGVyYXRvcgABAAAAAA==", "subType": "06" } } } }, "update": { "$set": { "encryptedDoubleNoPrecision": { "$$type": "binData" } } }, "encryptionInformation": { "type": 1, "schema": { "default.default": { "escCollection": "enxcol_.default.esc", "ecocCollection": "enxcol_.default.ecoc", "fields": [ { "keyId": { "$binary": { "base64": "EjRWeBI0mHYSNBI0VniQEg==", "subType": "04" } }, "path": "encryptedDoubleNoPrecision", "bsonType": "double", "queries": { "queryType": "rangePreview", "contention": { "$numberLong": "0" }, "sparsity": { "$numberLong": "1" } } } ] } } } }, "command_name": "findAndModify" } } ], "outcome": { "collection": { "data": [ { "_id": 0, "encryptedDoubleNoPrecision": { "$$type": "binData" }, "__safeContent__": [ { "$binary": { "base64": "5nRutVIyq7URVOVtbE4vM01APSIajAVnsShMwjBlzkM=", "subType": "00" } }, { "$binary": { "base64": "6YrBn2ofIw1b5ooakrLOwF41BWrps8OO0H9WH4/rtlE=", "subType": "00" } }, { "$binary": { "base64": "n+XAuFnP8Dov9TnhGFxNx0K/MnVM9WbJ7RouEu0ndO0=", "subType": "00" } }, { "$binary": { "base64": "yRXojuVdn5GQtD97qYlaCL6cOLmZ7Cvcb3wFjkLUIdM=", "subType": "00" } }, { "$binary": { "base64": "DuIkdRPITRs55I4SZmgomAHCIsDQmXRhW8+MOznkzSk=", "subType": "00" } }, { "$binary": { "base64": "SsBk+Et1lTbU+QRPx+xyJ/jMkmfG+QCvQEpip2YYrzA=", "subType": "00" } }, { "$binary": { "base64": "crCIzOd8KhHvvUlX7M1v9bhvU4pLdTc+X2SuqoKU5Ek=", "subType": "00" } }, { "$binary": { "base64": "YOWdCw4UrqnxkAaVjqmC4sKQDMVMHEpFGnlxpxdaU6E=", "subType": "00" } }, { "$binary": { "base64": "M3SShp81Ff8tQ632qKbv9MUcN6wjDaBReI0VXNu6Xh4=", "subType": "00" } }, { "$binary": { "base64": "gzHlSPxpM0hT75kQvWFzGlOxKvDoiKQZOr19V6l2zXI=", "subType": "00" } }, { "$binary": { "base64": "s3JnppOGYw9SL2Q1kMAZs948v2F5PrpXjGei/HioDWs=", "subType": "00" } }, { "$binary": { "base64": "cG6+3Gk/zEH68P/uuuwiAUVCuyJwa1LeV+t29FlPPAo=", "subType": "00" } }, { "$binary": { "base64": "dupdvR3AyJtM+g9NDKiaLVOtGca387JQp8w+V03m7Ig=", "subType": "00" } }, { "$binary": { "base64": "JqEQc5svj2jTvZ6LLA5ivE+kTb/0aRemSEmxk4G7Zrg=", "subType": "00" } }, { "$binary": { "base64": "szcXXXKnob+p3SoM4yED2R920LeJ7cVsclPMFTe4CeI=", "subType": "00" } }, { "$binary": { "base64": "o1QoGVXmuBdHwHm7aCtGMlMVKrjFdYvJXpoq6uhIAZ0=", "subType": "00" } }, { "$binary": { "base64": "Jfm5wPlqqLCJRGQIqRq2NGmpn7s0Vrih2H3YAOoI2YU=", "subType": "00" } }, { "$binary": { "base64": "zMHLb8ARbsYo8Ld05bqnGFf1Usha6EGb8QKwdSAyps0=", "subType": "00" } }, { "$binary": { "base64": "yQdtq9lh5pugL7/i0Bj/PuZUUBUIzf+7wj1rl5y736w=", "subType": "00" } }, { "$binary": { "base64": "wGWVZdO7qIuyDg/BqDgqjgoQ02h5YYgwXQB1oCin2NE=", "subType": "00" } }, { "$binary": { "base64": "by9HMLj6NTEpgztZ5HSN6GxImkXPcaFINYDzgZY33X8=", "subType": "00" } }, { "$binary": { "base64": "tWo0vbasi7bXmn/MsOx13VC1IsWtpx/nYp0uj4iMzdA=", "subType": "00" } }, { "$binary": { "base64": "tQQpndUYd5O87lOtrGjH3wl9VsOK0ray7RMasL90sBM=", "subType": "00" } }, { "$binary": { "base64": "cQjXEDCMsOpKLLf+vlTgIHA+cbSJdzqhbSX9Wvh95aA=", "subType": "00" } }, { "$binary": { "base64": "7yMpU48IxK9SzP2cx3VnTownGEwFmeFofuuFT97SuuY=", "subType": "00" } }, { "$binary": { "base64": "kSOx1kz0CmBgzKQHZlo65ZUY1DIv9A99JRm+Us2y6Ew=", "subType": "00" } }, { "$binary": { "base64": "ubQpdPBe6/xvtr+AcXdfYLSvYCR4ot0tivehkCsupb4=", "subType": "00" } }, { "$binary": { "base64": "xal+iCJ6FTefRQToyoNksc9NCZShyn04NDGi4IYrcoM=", "subType": "00" } }, { "$binary": { "base64": "d7jU4iOK50xHxlkSifcxlZFCM46TSgQzoYivxG3HNLY=", "subType": "00" } }, { "$binary": { "base64": "tJvl2nsBLBVzL3pp6sKWCL4UXeh3q/roYBJjSb74ve0=", "subType": "00" } }, { "$binary": { "base64": "OIUCaKRvIx9t1w6Hxlz1IcQTdPNCfdRNwnnTm10W+X0=", "subType": "00" } }, { "$binary": { "base64": "A9tvzsiElotOUVIB4CqfQp9mAwqvTM35YkmAR170aHA=", "subType": "00" } }, { "$binary": { "base64": "lI8gpK7hpb7c9x4RQugsxMnQay5LZJmwslZdvMx/dcE=", "subType": "00" } }, { "$binary": { "base64": "dNCzh40U0XvdKnSDi3HRQOWQftEsDVqc4uUvsVFGoq8=", "subType": "00" } }, { "$binary": { "base64": "IP+iwEBWBwVVZIdpaMu8k5+soFCz+TZkYn3drKZ9grE=", "subType": "00" } }, { "$binary": { "base64": "pnqyh6e0y5svHkJDShlN9CHV0WvMBE4QbtJpQw5ZCXc=", "subType": "00" } }, { "$binary": { "base64": "elEl42tbVDoRTLjAhZUFEtXiut4b3PVhg/1ZLZSQdtE=", "subType": "00" } }, { "$binary": { "base64": "vHuu2FxwclMHqyE6JBYbTYgbEkB0dqb/JuaxsvfwsmY=", "subType": "00" } }, { "$binary": { "base64": "xTf7NCe3Gf8QpE78HR5OknlLTKfs9J+RN9UZpH6fnso=", "subType": "00" } }, { "$binary": { "base64": "XiWSasRnJAulGR6+LCVD3mwRObXylqYWR9jvpywq12c=", "subType": "00" } }, { "$binary": { "base64": "MZMxEQ5ikx0PG1YFIExv0UnTZogsvgeOEZTpzvBDn4w=", "subType": "00" } }, { "$binary": { "base64": "yZMyMZBDrWbAhvnic7vvIYhmO9m5H2iuv0c8KNZrBzY=", "subType": "00" } }, { "$binary": { "base64": "xxM14hTPY5j0vvcK2C7YAEjzdsfUTFHozHC0hEo1bxI=", "subType": "00" } }, { "$binary": { "base64": "+01rqR1xVwkpGXcstbk1ItJqFVjH6Q8MGxEN3Cm9Y1A=", "subType": "00" } }, { "$binary": { "base64": "xOpLV0Z2VTRJ3iWtnWZcsyjXubTIkYWo31cO+HV1o1k=", "subType": "00" } }, { "$binary": { "base64": "BWUOLqgLBqc5NwxVlSV5H3KFQPXbCp7mdo+jF+8cJqY=", "subType": "00" } }, { "$binary": { "base64": "fuQb1S6xZDGlrEbK+kI23aL53PP1PVNwqICnZNt9Yzg=", "subType": "00" } }, { "$binary": { "base64": "SfscnoibFttahLdPVC4Ee+47ewGFKpDSU7M6HX19bKE=", "subType": "00" } }, { "$binary": { "base64": "rpSW2awybNVeKtat91VFxqbINoTfNhPfQAu+d73Xtf8=", "subType": "00" } }, { "$binary": { "base64": "9M/CP9ccOIIj2LLFmE0GFDO0Ban2wsNalEXfM6+h+1s=", "subType": "00" } }, { "$binary": { "base64": "WrEMG49l1ye4MhXs5ZS9tz8P6h+hDvthIg/2wW9ne1Q=", "subType": "00" } }, { "$binary": { "base64": "ImNhbfeyfH8qIEeA5ic0s3dAQBdzzTBS+CPsNih9vZ0=", "subType": "00" } }, { "$binary": { "base64": "dWP33YDSn04UKJN2ogh2Rui0iW/0q2y18OCDRVcfyoo=", "subType": "00" } }, { "$binary": { "base64": "lYv0isAtfGh6H9tdp3cp2eHU7q2J+uk7QrgcxtK3w7Y=", "subType": "00" } }, { "$binary": { "base64": "VGMoamB/+7zTOYcY/pqJc96xlv2PdW4hwsIAEIslTDQ=", "subType": "00" } }, { "$binary": { "base64": "yNeBWMF7BnD9wVwz2PgJsvWr77QiVvvWUvJF0+fqBug=", "subType": "00" } }, { "$binary": { "base64": "SfpvObJ+tJBXSvqeN7vlOfmhYign635lciYAJIjUtY8=", "subType": "00" } }, { "$binary": { "base64": "dsen4NqjzVGjpjufiTMs3+gqeD09EbnuogPgxrJECwg=", "subType": "00" } }, { "$binary": { "base64": "pxCWVM3sn19NsFEpgHbgLa+PmYlhN3mMiP0Wk8kJhYw=", "subType": "00" } }, { "$binary": { "base64": "q11KNvJszjYIB9n9HcC+N4uz11a3eRj1L3BH9scKMDQ=", "subType": "00" } }, { "$binary": { "base64": "A1PmkgcEToWh1JiVWE6mI5jUu7poxWWuCUt/cgRUUDc=", "subType": "00" } }, { "$binary": { "base64": "qJo3Hu4PJeanL7XEaWXO/n3YsodhZyd+MJOOmB9Kpd8=", "subType": "00" } }, { "$binary": { "base64": "BkBKLO8URFscfRY9Bav/1+L9mLohDgNr/MkZtGiraIs=", "subType": "00" } }, { "$binary": { "base64": "rZq5WA3Hx3xthOyHAJXK//f8pE2qbz7YKu3TIMp9GFY=", "subType": "00" } }, { "$binary": { "base64": "X07a/Lm80p5xd4RFs1dNmw+90tmPDPdGiAKVZkxd4zY=", "subType": "00" } } ] }, { "_id": 1, "encryptedDoubleNoPrecision": { "$$type": "binData" }, "__safeContent__": [ { "$binary": { "base64": "DLCAJs+W2PL2DV5YChCL6dYrQNr+j4p3L7xhVaub4ic=", "subType": "00" } }, { "$binary": { "base64": "HI88j1zrIsFoijIXKybr9mYubNV5uVeODyLHFH4Ueco=", "subType": "00" } }, { "$binary": { "base64": "wXVD/HSbBljko0jJcaxJ1nrzs2+pchLQqYR3vywS8SU=", "subType": "00" } }, { "$binary": { "base64": "KhscCh+tt/pp8lxtKZQSPPUU94RvJYPKG/sjtzIa4Ws=", "subType": "00" } }, { "$binary": { "base64": "RISnuNrTTVNW5HnwCgQJ301pFw8DOcYrAMQIwVwjOkI=", "subType": "00" } }, { "$binary": { "base64": "Ra5zukLh2boua0Bh74qA+mtIoixGXlsNsxiJqHtqdTI=", "subType": "00" } }, { "$binary": { "base64": "eqr0v+NNWXWszi9ni8qH58Q6gw5x737tJvH3lPaNHO4=", "subType": "00" } }, { "$binary": { "base64": "d42QupriWIwGrFAquXNFi0ehEuidIbHLFZtg1Sm2nN8=", "subType": "00" } }, { "$binary": { "base64": "2azRVxaaTIJKcgY2FU012gcyP8Y05cRDpfUaMnCBaQU=", "subType": "00" } }, { "$binary": { "base64": "3nlgkM4K/AAcHesRYYdEu24UGetHodVnVfHzw4yxZBM=", "subType": "00" } }, { "$binary": { "base64": "hqy91FNmAAac2zUaPO6eWFkx0/37rOWGrwXN+fzL0tU=", "subType": "00" } }, { "$binary": { "base64": "akX+fmscSDSF9pB5MPj56iaJPtohr0hfXNk/OPWsGv8=", "subType": "00" } }, { "$binary": { "base64": "1ZvUb10Q7cN4cNLktd5yNjqgtawsYnkbeVBZV6WuY/I=", "subType": "00" } }, { "$binary": { "base64": "otCwtuKiY4hCyXvYzXvo10OcnzZppebo38KsAlq49QM=", "subType": "00" } }, { "$binary": { "base64": "Mty8EscckeT/dhMfrPFyDbLnmMOcYRUQ3mLK4KTu6V8=", "subType": "00" } }, { "$binary": { "base64": "tnvgLLkJINO7csREYu4dEVe1ICrBeu7OP+HdfoX3M2E=", "subType": "00" } }, { "$binary": { "base64": "kOefsHgEVhkJ17UuP7Dxogy6sAQbzf1SFPKCj6XRlrQ=", "subType": "00" } }, { "$binary": { "base64": "F+JQ79xavpaHdJzdhvwyHbzdZJLNHAymc/+67La3gao=", "subType": "00" } }, { "$binary": { "base64": "NCZ9zp5rDRceENuSgAfTLEyKg0YgmXAhK0B8WSj7+Pw=", "subType": "00" } }, { "$binary": { "base64": "wL1CJ7cYR5slx8mHq++uMdjDfkt9037lQTUztEMF56M=", "subType": "00" } }, { "$binary": { "base64": "txefkzTMITZE+XvvRFZ7QcgwDT/7m8jNmxRk4QBaoZI=", "subType": "00" } }, { "$binary": { "base64": "jFunW3v1tSYMyZtQQD28eEy9qqDp4Kqo7gMN29N4bfQ=", "subType": "00" } }, { "$binary": { "base64": "QMO915KUiS3X3R1bU1YoafVM2s0NeHo3EjgTA9PnGwY=", "subType": "00" } }, { "$binary": { "base64": "nwdKJEXdilzvb7494vbuDJ+y6SrfJahza1dYIsHIWVI=", "subType": "00" } }, { "$binary": { "base64": "vpWMX+T/VXXajFo0UbuYjtp0AEzBU0Y+lP+ih2EQ7mg=", "subType": "00" } }, { "$binary": { "base64": "1lmzG0J1DhKDRhhq5y5Buygu4G8eV2X0t7kUY90EohM=", "subType": "00" } }, { "$binary": { "base64": "SiKqpXqO0trwhFvBWK274hMklpCgMhNs/JY84yyn/NE=", "subType": "00" } }, { "$binary": { "base64": "7cPGPYCKPTay+ZR9Gx6oOueduOgaFrSuAXmNDpDHXdI=", "subType": "00" } }, { "$binary": { "base64": "4THEYvAkjs2Fh7FIe5LC45P4i4N0L7ob67UOVbhp6Nk=", "subType": "00" } }, { "$binary": { "base64": "B+UGsChLLZR7iqnt8yq91OgmTgwiUKTJhFxY4NT0O6c=", "subType": "00" } }, { "$binary": { "base64": "X1uYwBCsCg1H+PnKdwtBqXlt0zKEURi8bOM940GcPfk=", "subType": "00" } }, { "$binary": { "base64": "xYOgT5l7shlNXCwHlguovmDkcEnF8dXyYlTyYrgZ8GE=", "subType": "00" } }, { "$binary": { "base64": "vFMTZqV8bh1+gcKzTkXweMddJlgdUnwX0DWzUUaMok4=", "subType": "00" } }, { "$binary": { "base64": "4HI0y9FrtleZxZ7M6INdNhLelrQ2Rv/+ykWCBl+tMC8=", "subType": "00" } }, { "$binary": { "base64": "jpJ0bBE474OUkn1vUiLWumIBtYmwc7J5+LQU/nyeLQc=", "subType": "00" } }, { "$binary": { "base64": "jQTPeXZvdxY/DjtPfYfKUArIDsf0E9MVFy2O26sv1ec=", "subType": "00" } }, { "$binary": { "base64": "QLLto0ExR2ZYMGqlyaMZc/hXFFTlwmgtKbiVq/xJIeI=", "subType": "00" } }, { "$binary": { "base64": "yBJNviU1nchbGbhx6InXCVRXa90sEepz1EwbYuKXu2U=", "subType": "00" } }, { "$binary": { "base64": "jpEf0vHxrPu9gTJutNXSi2g/2Mc4WXFEN7yHonZEb7A=", "subType": "00" } }, { "$binary": { "base64": "E09kLFckMYwNuhggMxmPtwndyvIAx+Vl+b2CV6FP75s=", "subType": "00" } }, { "$binary": { "base64": "N+ue6/cLPb5NssmJCCeo18LlbKPz6r2z20AsnTKRvOo=", "subType": "00" } }, { "$binary": { "base64": "yVQNZP8hhsvNGyDph2QP2qTNdXZTiIEVineKg+Qf33o=", "subType": "00" } }, { "$binary": { "base64": "cSC9uI+9c5S8X+0G7amVyug1p0ZlgBsbEDYYyezBevQ=", "subType": "00" } }, { "$binary": { "base64": "1NpZGjoQzuQtekj80Rifxe9HbE08W07dfwxaFHaVn84=", "subType": "00" } }, { "$binary": { "base64": "5Ghuq/8l11Ug9Uf/RTwf9On3OxOwIXUcb9soiy4J7/w=", "subType": "00" } }, { "$binary": { "base64": "0LWKaEty6ywxLFhDaAqulqfMnYc+tgPfH4apyEeKg80=", "subType": "00" } }, { "$binary": { "base64": "OwSthmCBtt6NIAoAh7aCbj82Yr/+9t8U7WuBQhFT3AQ=", "subType": "00" } }, { "$binary": { "base64": "iYiyg6/1isqbMdvFPIGucu3cNM4NAZNtJhHpGZ4eM+c=", "subType": "00" } }, { "$binary": { "base64": "waBgs8jWuGJPIF5zCRh6OmIyfK5GCBQgTMfmKSR2wyY=", "subType": "00" } }, { "$binary": { "base64": "1Jdtbe2BKJXPU2G9ywOrlODZ/cNYEQlKzAW3aMe1Hy4=", "subType": "00" } }, { "$binary": { "base64": "xaLEnNUS/2ySerBpb9dN/D31t+wYcKekwTfkwtni0Mc=", "subType": "00" } }, { "$binary": { "base64": "bIVBrOhOvr6cL55Tr24+B+CC9MiG7U6K54aAr2IXXuw=", "subType": "00" } }, { "$binary": { "base64": "6Cdq5wroGu2TEFnekuT7LhOpd/K/+PcipIljcHU9QL4=", "subType": "00" } }, { "$binary": { "base64": "K5l64vI4S/pLviLW6Pl0U3iQkI3ge0xg4RAHcEsyKJo=", "subType": "00" } }, { "$binary": { "base64": "bzhuvZ0Ls22yIOX+Hz51eAHlSuDbWR/e0u4EhfdpHbc=", "subType": "00" } }, { "$binary": { "base64": "Qv+fr6uD4o0bZRp69QJCFL6zvn3G82c7L+N1IFzj7H0=", "subType": "00" } }, { "$binary": { "base64": "XAmISMbD3aEyQT+BQEphCKFNa0F0GDKFuhM9cGceKoQ=", "subType": "00" } }, { "$binary": { "base64": "4VLCokntMfm1AogpUnYGvhV7nllWSo3mS3hVESMy+hA=", "subType": "00" } }, { "$binary": { "base64": "xiXNLj/CipEH63Vb5cidi8q9X47EF4f3HtJSOH7mfM8=", "subType": "00" } }, { "$binary": { "base64": "4XlCYfYBjI9XA5zOSgTiEBYcZsdwyXL+f5XtH2xUIOc=", "subType": "00" } }, { "$binary": { "base64": "k6DfQy7ZYJIkEly2B5hjOZznL4NcgMkllZjJLb7yq7w=", "subType": "00" } }, { "$binary": { "base64": "ZzM6gwWesa3lxbZVZthpPFs2s3GV0RZREE2zOMhBRBo=", "subType": "00" } }, { "$binary": { "base64": "US+jeMeeOd7J0wR0efJtq2/18lcO8YFvhT4O3DeaonQ=", "subType": "00" } }, { "$binary": { "base64": "b6iSxiI1FM9SzxuG1bHqGA1i4+3GOi0/SPW00XB4L7o=", "subType": "00" } }, { "$binary": { "base64": "kn3LsxAVkzIZKK9I6fi0Cctr0yjXOYgaQWMCoj4hLpM=", "subType": "00" } } ] } ] } } } ] } fle2v2-Range-Double-InsertFind.json000066400000000000000000001357751462766011000354450ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/client-side-encryption/spec/legacy{ "runOn": [ { "minServerVersion": "7.0.0", "topology": [ "replicaset", "sharded", "load-balanced" ] } ], "database_name": "default", "collection_name": "default", "data": [], "encrypted_fields": { "fields": [ { "keyId": { "$binary": { "base64": "EjRWeBI0mHYSNBI0VniQEg==", "subType": "04" } }, "path": "encryptedDoubleNoPrecision", "bsonType": "double", "queries": { "queryType": "rangePreview", "contention": { "$numberLong": "0" }, "sparsity": { "$numberLong": "1" } } } ] }, "key_vault_data": [ { "_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" } } ], "tests": [ { "description": "FLE2 Range Double. Insert and Find.", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "local": { "key": { "$binary": { "base64": "Mng0NCt4ZHVUYUJCa1kxNkVyNUR1QURhZ2h2UzR2d2RrZzh0cFBwM3R6NmdWMDFBMUN3YkQ5aXRRMkhGRGdQV09wOGVNYUMxT2k3NjZKelhaQmRCZGJkTXVyZG9uSjFk", "subType": "00" } } } } } }, "operations": [ { "name": "insertOne", "arguments": { "document": { "_id": 0, "encryptedDoubleNoPrecision": { "$numberDouble": "0" } } } }, { "name": "insertOne", "arguments": { "document": { "_id": 1, "encryptedDoubleNoPrecision": { "$numberDouble": "1" } } } }, { "name": "find", "arguments": { "filter": { "encryptedDoubleNoPrecision": { "$gt": { "$numberDouble": "0" } } } }, "result": [ { "_id": 1, "encryptedDoubleNoPrecision": { "$numberDouble": "1" } } ] } ], "expectations": [ { "command_started_event": { "command": { "listCollections": 1, "filter": { "name": "default" } }, "command_name": "listCollections" } }, { "command_started_event": { "command": { "find": "datakeys", "filter": { "$or": [ { "_id": { "$in": [ { "$binary": { "base64": "EjRWeBI0mHYSNBI0VniQEg==", "subType": "04" } } ] } }, { "keyAltNames": { "$in": [] } } ] }, "$db": "keyvault", "readConcern": { "level": "majority" } }, "command_name": "find" } }, { "command_started_event": { "command": { "insert": "default", "documents": [ { "_id": 0, "encryptedDoubleNoPrecision": { "$$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": "encryptedDoubleNoPrecision", "bsonType": "double", "queries": { "queryType": "rangePreview", "contention": { "$numberLong": "0" }, "sparsity": { "$numberLong": "1" } } } ] } } } }, "command_name": "insert" } }, { "command_started_event": { "command": { "insert": "default", "documents": [ { "_id": 1, "encryptedDoubleNoPrecision": { "$$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": "encryptedDoubleNoPrecision", "bsonType": "double", "queries": { "queryType": "rangePreview", "contention": { "$numberLong": "0" }, "sparsity": { "$numberLong": "1" } } } ] } } } }, "command_name": "insert" } }, { "command_started_event": { "command": { "find": "default", "filter": { "encryptedDoubleNoPrecision": { "$gt": { "$binary": { "base64": "DYckAAADcGF5bG9hZABXJAAABGcAQyQAAAMwAH0AAAAFZAAgAAAAAHgYoMGjEE6fAlAhICv0+doHcVX8CmMVxyq7+jlyGrvmBXMAIAAAAAC/5MQZgTHuIr/O5Z3mXPvqrom5JTQ8IeSpQGhO9sB+8gVsACAAAAAAuPSXVmJUAUpTQg/A9Bu1hYczZF58KEhVofakygbsvJQAAzEAfQAAAAVkACAAAAAA2kiWNvEc4zunJ1jzvuClFC9hjZMYruKCqAaxq+oY8EAFcwAgAAAAACofIS72Cm6s866UCk+evTH3CvKBj/uZd72sAL608rzTBWwAIAAAAADuCQ/M2xLeALF0UFZtJb22QGOhHmJv6xoO+kZIHcDeiAADMgB9AAAABWQAIAAAAABkfoBGmU3hjYBvQbjNW19kfXneBQsQQPRfUL3UAwI2cAVzACAAAAAAUpK2BUOqX/DGdX5YJniEZMWkofxHqeAbXceEGJxhp8AFbAAgAAAAAKUaLzIldNIZv6RHE+FwbMjzcNHqPESwF/37mm43VPrsAAMzAH0AAAAFZAAgAAAAAFNprhQ3ZwIcYbuzLolAT5n/vc14P9kUUQComDu6eFyKBXMAIAAAAAAcx9z9pk32YbPV/sfPZl9ALIEVsqoLXgqWLVK/tP+heAVsACAAAAAA/qxvuvJbAHwwhfrPVpmCFzNvg2cU/NXaWgqgYUZpgXwAAzQAfQAAAAVkACAAAAAAODI+pB2pCuB+YmNEUAgtMfNdt3DmSkrJ96gRzLphgb8FcwAgAAAAAAT7dewFDxUDECQ3zVq75/cUN4IP+zsqhkP5+czUwlJIBWwAIAAAAACFGeOtd5zBXTJ4JYonkn/HXZfHipUlqGwIRUcH/VTatwADNQB9AAAABWQAIAAAAACNAk+yTZ4Ewk1EnotQK8O3h1gg9I7pr9q2+4po1iJVgAVzACAAAAAAUj/LesmtEsgqYVzMJ67umVA11hJTdDXwbxDoQ71vWyUFbAAgAAAAABlnhpgTQ0WjLb5u0b/vEydrCeFjVynKd7aqb+UnvVLeAAM2AH0AAAAFZAAgAAAAAD/FIrGYFDjyYmVb7oTMVwweWP7A6F9LnyIuNO4MjBnXBXMAIAAAAACIZgJCQRZu7NhuNMyOqCn1tf+DfU1qm10TPCfj5JYV3wVsACAAAAAA5hmY4ptuNxULGf87SUFXQWGAONsL9U29duh8xqsHtxoAAzcAfQAAAAVkACAAAAAAciRW40ORJLVwchOEpz87Svb+5toAFM6LxDWv928ECwQFcwAgAAAAAN0dipyESIkszfjRzdDi8kAGaa2Hf4wrPAtiWwboZLuxBWwAIAAAAAANr4o/+l1OIbbaX5lZ3fQ/WIeOcEXjNI1F0WbSgQrzaQADOAB9AAAABWQAIAAAAACZqAyCzYQupJ95mrBJX54yIz9VY7I0WrxpNYElCI4dTQVzACAAAAAA/eyJb6d1xfE+jJlVXMTD3HS/NEYENPVKAuj56Dr2dSEFbAAgAAAAANkSt154Or/JKb31VvbZFV46RPgUp8ff/hcPORL7PpFBAAM5AH0AAAAFZAAgAAAAAI5bm3YO0Xgf0VT+qjVTTfvckecM3Cwqj7DTKZXf8/NXBXMAIAAAAAD/m+h8fBhWaHm6Ykuz0WX1xL4Eme3ErLObyEVJf8NCywVsACAAAAAAfb1VZZCqs2ivYbRzX4p5CtaCkKW+g20Pr57FWXzEZi8AAzEwAH0AAAAFZAAgAAAAANqo4+p6qdtCzcB4BX1wQ6llU7eFBnuu4MtZwp4B6mDlBXMAIAAAAAAGiz+VaukMZ+6IH4jtn4KWWdKK4/W+O+gRioQDrfzpMgVsACAAAAAAG4YYkTp80EKo59mlHExDodRQFR7njhR5dmISwUJ6ukAAAzExAH0AAAAFZAAgAAAAAPrFXmHP2Y4YAm7b/aqsdn/DPoDkv7B8egWkfe23XsM1BXMAIAAAAAAGhwpKAr7skeqHm3oseSbO7qKNhmYsuUrECBxJ5k+D2AVsACAAAAAAAqPQi9luYAu3GrFCEsVjd9z2zIDcp6SPTR2w6KQEr+IAAzEyAH0AAAAFZAAgAAAAABzjYxwAjXxXc0Uxv18rH8I3my0Aguow0kTwKyxbrm+cBXMAIAAAAADVbqJVr6IdokuhXkEtXF0C2gINLiAjMVN20lE20Vmp2QVsACAAAAAAD7K1Fx4gFaaizkIUrf+EGXQeG7QX1jadhGc6Ji471H8AAzEzAH0AAAAFZAAgAAAAAFMm2feF2fFCm/UC6AfIyepX/xJDSmnnolQIBnHcPmb5BXMAIAAAAABLI11kFrQoaNVZFmq/38aRNImPOjdJh0Lo6irI8M/AaAVsACAAAAAAOWul0oVqJ9CejD2RqphhTC98DJeRQy5EwbNerU2+4l8AAzE0AH0AAAAFZAAgAAAAAJvXB3KyNiNtQko4SSzo/9b2qmM2zU9CQTTDfLSBWMgRBXMAIAAAAAAvjuVP7KsLRDeqVqRziTKpBrjVyqKiIbO9Gw8Wl2wFTAVsACAAAAAADlE+oc1ins+paNcaOZJhBlKlObDJ4VQORWjFYocM4LgAAzE1AH0AAAAFZAAgAAAAAPGdcxDiid8z8XYnfdDivNMYVPgBKdGOUw6UStU+48CdBXMAIAAAAAARj6g1Ap0eEfuCZ4X2TsEw+Djrhto3fA5nLwPaY0vCTgVsACAAAAAAoHqiwGOUkBu8SX5U1yHho+UIFdSN2MdQN5s6bQ0EsJYAAzE2AH0AAAAFZAAgAAAAAP5rGPrYGt3aKob5f/ldP0qrW7bmWvqnKY4QwdDWz400BXMAIAAAAADTQkW2ymaaf/bhteOOGmSrIR97bAnJx+yN3yMj1bTeewVsACAAAAAADyQnHGH2gF4w4L8axUsSTf6Ubk7L5/eoFOJk12MtZAoAAzE3AH0AAAAFZAAgAAAAAAlz6wJze5UkIxKpJOZFGCOf3v2KByWyI6NB6JM9wNcBBXMAIAAAAABUC7P/neUIHHoZtq0jFVBHY75tSFYr1Y5S16YN5XxC1QVsACAAAAAAgvxRbXDisNnLY3pfsjDdnFLtkvYUC4lhA68eBXc7KAwAAzE4AH0AAAAFZAAgAAAAAFJ8AtHcjia/9Y5pLEc3qVgH5xKiXw12G9Kn2A1EY8McBXMAIAAAAAAxe7Bdw7eUSBk/oAawa7uicTEDgXLymRNhBy1LAxhDvwVsACAAAAAAxKPaIBKVx3jTA+R/el7P7AZ7efrmTGjJs3Hj/YdMddwAAzE5AH0AAAAFZAAgAAAAAO8uwQUaKFb6vqR3Sv3Wn4QAonC2exOC9lGG1juqP5DtBXMAIAAAAABZf1KyJgQg8/Rf5c02DgDK2aQu0rNCOvaL60ohDHyY+gVsACAAAAAAqyEjfKC8lYoIfoXYHUqHZPoaA6EK5BAZy5dxXZmay4kAAzIwAH0AAAAFZAAgAAAAAE8YtqyRsGCeiR6hhiyisR/hccmK4nZqIMzO4lUBmEFzBXMAIAAAAAC1UYOSKqAeG1UJiKjWFVskRhuFKpj9Ezy+lICZvFlN5AVsACAAAAAA6Ct9nNMKyRazn1OKnRKagm746CGu+jyhbL1qJnZxGi0AAzIxAH0AAAAFZAAgAAAAAPhCrMausDx1QUIEqp9rUdRKyM6a9AAx7jQ3ILIu8wNIBXMAIAAAAACmH8lotGCiF2q9VQxhsS+7LAZv79VUAsOUALaGxE/EpAVsACAAAAAAnc1xCKfdvbUEc8F7XZqlNn1C+hZTtC0I9I3LL06iaNkAAzIyAH0AAAAFZAAgAAAAAOBi/GAYFcstMSJPgp3VkMiuuUUCrZytvqYaU8dwm8v2BXMAIAAAAACEZSZVyD3pKzGlbdwlYmWQhHHTV5SnNLknl2Gw8IaUTQVsACAAAAAAfsLZsEDcWSuNsIo/TD1ReyQW75HPMgmuKZuWFOLKRLoAAzIzAH0AAAAFZAAgAAAAAIQuup+YGfH3mflzWopN8J1X8o8a0d9CSGIvrA5HOzraBXMAIAAAAADYvNLURXsC2ITMqK14LABQBI+hZZ5wNf24JMcKLW+84AVsACAAAAAACzfjbTBH7IwDU91OqLAz94RFkoqBOkzKAqQb55gT4/MAAzI0AH0AAAAFZAAgAAAAAKsh0ADyOnVocFrOrf6MpTrNvAj8iaiE923DPryu124gBXMAIAAAAADg24a8NVE1GyScc6tmnTbmu5ulzO+896fE92lN08MeswVsACAAAAAAaPxcOIxnU7But88/yadOuDJDMcCywwrRitaxMODT4msAAzI1AH0AAAAFZAAgAAAAAKkVC2Y6HtRmv72tDnPUSjJBvse7SxLqnr09/Uuj9sVVBXMAIAAAAABYNFUkH7ylPMN+Bc3HWX1e0flGYNbtJNCY9SltJCW/UAVsACAAAAAAZYK/f9H4OeihmpiFMH7Wm7uLvs2s92zNA8wyrNZTsuMAAzI2AH0AAAAFZAAgAAAAADDggcwcb/Yn1Kk39sOHsv7BO/MfP3m/AJzjGH506Wf9BXMAIAAAAAAYZIsdjICS0+BDyRUPnrSAZfPrwtuMaEDEn0/ijLNQmAVsACAAAAAAGPnYVvo2ulO9z4LGd/69NAklfIcZqZvFX2KK0s+FcTUAAzI3AH0AAAAFZAAgAAAAAEWY7dEUOJBgjOoWVht1wLehsWAzB3rSOBtLgTuM2HC8BXMAIAAAAAAAoswiHRROurjwUW8u8D5EUT+67yvrgpB/j6PzBDAfVwVsACAAAAAA6NhRTYFL/Sz4tao7vpPjLNgAJ0FX6P/IyMW65qT6YsMAAzI4AH0AAAAFZAAgAAAAAPZaapeAUUFPA7JTCMOWHJa9lnPFh0/gXfAPjA1ezm4ZBXMAIAAAAACmJvLY2nivw7/b3DOKH/X7bBXjJwoowqb1GtEFO3OYgAVsACAAAAAA/JcUoyKacCB1NfmH8vYqC1f7rd13KShrQqV2r9QBP44AAzI5AH0AAAAFZAAgAAAAAK00u6jadxCZAiA+fTsPVDsnW5p5LCr4+kZZZOTDuZlfBXMAIAAAAAAote4zTEYMDgaaQbAdN8Dzv93ljPLdGjJzvnRn3KXgtQVsACAAAAAAxXd9Mh6R3mnJy8m7UfqMKi6oD5DlZpkaOz6bEjMOdiwAAzMwAH0AAAAFZAAgAAAAAFbgabdyymiEVYYwtJSWa7lfl/oYuj/SukzJeDOR6wPVBXMAIAAAAADAFGFjS1vPbN6mQEhkDYTD6V2V23Ys9gUEUMGNvMPkaAVsACAAAAAAL/D5Sze/ZoEanZLK0IeEkhgVkxEjMWVCfmJaD3a8uNIAAzMxAH0AAAAFZAAgAAAAABNMR6UBv2E627CqLtQ/eDYx7OEwQ7JrR4mSHFa1N8tLBXMAIAAAAAAxH4gucI4UmNVB7625C6hFSVCuIpJO3lusJlPuL8H5EQVsACAAAAAAVLHNg0OUVqZ7WGOP53BkTap9FOw9dr1P4J8HxqFqU04AAzMyAH0AAAAFZAAgAAAAAG8cd6WBneNunlqrQ2EmNf35W7OGObGq9WL4ePX+LUDmBXMAIAAAAAAjJ2+sX87NSis9hBsgb1QprVRnO7Bf+GObCGoUqyPE4wVsACAAAAAAs9c9SM49/pWmyUQKslpt3RTMBNSRppfNO0JBvUqHPg0AAzMzAH0AAAAFZAAgAAAAAFWOUGkUpy8yf6gB3dio/aOfRKh7XuhvsUj48iESFJrGBXMAIAAAAAAY7sCDMcrUXvNuL6dO0m11WyijzXZvPIcOKob6IpC4PQVsACAAAAAAJOP+EHz6awDb1qK2bZQ3kTV7wsj5Daj/IGAWh4g7omAAAzM0AH0AAAAFZAAgAAAAAGUrIdKxOihwNmo6B+aG+Ag1qa0+iqdksHOjQj+Oy9bZBXMAIAAAAABwa5dbI2KmzBDNBTQBEkjZv4sPaeRkRNejcjdVymRFKQVsACAAAAAA4ml/nm0gJNTcJ4vuD+T2Qfq2fQZlibJp/j6MOGDrbHMAAzM1AH0AAAAFZAAgAAAAAOx89xV/hRk64/CkM9N2EMK6aldII0c8smdcsZ46NbP8BXMAIAAAAADBF6tfQ+7q9kTuLyuyrSnDgmrdmrXkdhl980i1KHuGHgVsACAAAAAACUqiFqHZdGbwAA+hN0YUE5zFg+H+dabIB4dj5/75W/YAAzM2AH0AAAAFZAAgAAAAAMkN0L1oQWXhjwn9rAdudcYeN8/5VdCKU8cmDt7BokjsBXMAIAAAAAAT62pGXoRwExe9uvgYOI0hg5tOxilrWfoEmT0SMglWJwVsACAAAAAAlVz4dhiprSbUero6JFfxzSJGclg63oAkAmgbSwbcYxIAAzM3AH0AAAAFZAAgAAAAANxfa4xCoaaB7k1C1RoH1LBhsCbN2yEq15BT9b+iqEC4BXMAIAAAAACAX9LV8Pemfw7NF0iB1/85NzM1Ef+1mUfyehacUVgobQVsACAAAAAAVq4xpbymLk0trPC/a2MvB39I7hRiX8EJsVSI5E5hSBkAAzM4AH0AAAAFZAAgAAAAAOYIYoWkX7dGuyKfi3XssUlc7u/gWzqrR9KMkikKVdmSBXMAIAAAAABVF2OYjRTGi9Tw8XCAwZWLpX35Yl271TlNWp6N/nROhAVsACAAAAAA0nWwYzXQ1+EkDvnGq+SMlq20z+j32Su+i/A95SggPb4AAzM5AH0AAAAFZAAgAAAAAIy0+bXZi10QC+q7oSOLXK5Fee7VEk/qHSXukfeVIfgzBXMAIAAAAAAQ3IIV/JQCHW95AEbH5zGIHtJqyuPjWPMIZ+VmQHlxEwVsACAAAAAAp0jYsyohKv9Pm+4k+DplEGbl9WLZpAJzitrcDj4CNsMAAzQwAH0AAAAFZAAgAAAAAL5SOJQ3LOhgdXJ5v086NNeAl1qonQnchObdpZJ1kHeEBXMAIAAAAAA+tEqTXODtik+ydJZSnUqXF9f18bPeze9eWtR7ExZJgQVsACAAAAAAbrkZCVgB9Qsp4IAbdf+bD4fT6Boqk5UtuA/zhNrh1y0AAzQxAH0AAAAFZAAgAAAAAKl8zcHJRDjSjJeV/WvMxulW1zrTFtaeBy/aKKhadc6UBXMAIAAAAADBdWQl5SBIvtZZLIHszePwkO14W1mQ0izUk2Ov21cPNAVsACAAAAAAHErCYycpqiIcCZHdmPL1hi+ovLQk4TAvENpfLdTRamQAAzQyAH0AAAAFZAAgAAAAAFvotcNaoKnVt5CBCOPwjexFO0WGWuaIGL6H/6KSau+6BXMAIAAAAAD2y2mBN5xPu5PJoY2zcr0GnQDtHRBogA5+xzIxccE9fwVsACAAAAAAdS34xzJesnUfxLCcc1U7XzUqLy8MAzV/tcjbqaD3lkMAAzQzAH0AAAAFZAAgAAAAAPezU0/vNT4Q4YKbTbaeHqcwNLT+IjW/Y9QFpIooihjPBXMAIAAAAACj2x4O4rHter8ZnTws5LAP9jJ/6kk9C/V3vL50LoFZHAVsACAAAAAAQdBDF3747uCVP5lB/zr8VmzxJfTSZHBKeIgm5FyONXwAAzQ0AH0AAAAFZAAgAAAAAMqpayM2XotEFmm0gwQd9rIzApy0X+7HfOhNk6VU7F5lBXMAIAAAAACJR9+q5T9qFHXFNgGbZnPubG8rkO6cwWhzITQTmd6VgwVsACAAAAAAOZLQ6o7e4mVfDzbpQioa4d3RoTvqwgnbmc5Qh2wsZuoAAzQ1AH0AAAAFZAAgAAAAANCeyW+3oebaQk+aqxNVhAcT/BZ5nhsTVdKS3tMrLSvWBXMAIAAAAADxRFMDhkyuEc++WnndMfoUMLNL7T7rWoeblcrpSI6soQVsACAAAAAAdBuBMJ1lxt0DRq9pOZldQqchLs3B/W02txcMLD490FEAAzQ2AH0AAAAFZAAgAAAAAIbo5YBTxXM7HQhl7UP9NNgpPGFkBx871r1B65G47+K8BXMAIAAAAAC21dJSxnEhnxO5gzN5/34BL4von45e1meW92qowzb8fQVsACAAAAAAm3Hk2cvBN0ANaR5jzeZE5TsdxDvJCTOT1I01X7cNVaYAAzQ3AH0AAAAFZAAgAAAAABm/6pF96j26Jm7z5KkY1y33zcAEXLx2n0DwC03bs/ixBXMAIAAAAAD01OMvTZI/mqMgxIhA5nLs068mW+GKl3OW3ilf2D8+LgVsACAAAAAAaLvJDrqBESTNZSdcXsd+8GXPl8ZkUsGpeYuyYVv/kygAAzQ4AH0AAAAFZAAgAAAAAJ/D3+17gaQdkBqkL2wMwccdmCaVOtxzIkM8VyI4xI5zBXMAIAAAAAAggLVmkc5u+YzBR+oNE+XgLVp64fC6MzUb/Ilu/Jsw0AVsACAAAAAACz3HVKdWkx82/kGbVpcbAeZtsj2R5Zr0dEPfle4IErkAAzQ5AH0AAAAFZAAgAAAAAJMRyUW50oaTzspS6A3TUoXyC3gNYQoShUGPakMmeVZrBXMAIAAAAACona2Pqwt4U2PmFrtmu37jB9kQ/12okyAVtYa8TQkDiQVsACAAAAAAltJJKjCMyBTJ+4PkdDCPJdeX695P8P5h7WOZ+kmExMAAAzUwAH0AAAAFZAAgAAAAAByuYl8dBvfaZ0LO/81JW4hYypeNmvLMaxsIdvqMPrWoBXMAIAAAAABNddwobOUJzm9HOUD8BMZJqkNCUCqstHZkC76FIdNg9AVsACAAAAAAQQOkIQtkyNavqCnhQbNg3HfqrJdsAGaoxSJePJl1qXsAAzUxAH0AAAAFZAAgAAAAAHEzLtfmF/sBcYPPdj8867VmmQyU1xK9I/3Y0478azvABXMAIAAAAAAcmyFajZPnBTbO+oLInNwlApBocUekKkxz2hYFeSlQ+gVsACAAAAAAZ6IkrOVRcC8vSA6Vb4fPWZJrYexXhEabIuYIeXNsCSgAAzUyAH0AAAAFZAAgAAAAAJam7JYsZe2cN20ZYm2W3v1pisNt5PLiniMzymBLWyMtBXMAIAAAAABxCsKVMZMTn3n+R2L7pVz5nW804r8HcK0mCBw3jUXKXAVsACAAAAAA7j3JGnNtR64P4dJLeUoScFRGfa8ekjh3dvhw46sRFk0AAzUzAH0AAAAFZAAgAAAAAMXrXx0saZ+5gORmwM2FLuZG6iuO2YS+1IGPoAtDKoKBBXMAIAAAAADIQsxCr8CfFKaBcx8kIeSywnGh7JHjKRJ9vJd9x79y7wVsACAAAAAAcvBV+SykDYhmRFyVYwFYB9oBKBSHr55Jdz2cXeowsUQAAzU0AH0AAAAFZAAgAAAAACbzcUD3INSnCRspOKF7ubne74OK9L0FTZvi9Ay0JVDYBXMAIAAAAADPebVQH8Btk9rhBIoUOdSAdpPvz7qIY4UC2i6IGisSAQVsACAAAAAAiBunJi0mPnnXdnldiq+If8dcb/n6apHnaIFt+oyYO1kAAzU1AH0AAAAFZAAgAAAAACUc2CtD1MK/UTxtv+8iA9FoHEyTwdl43HKeSwDw2Lp5BXMAIAAAAACCIduIdw65bQMzRYRfjBJj62bc69T4QqH4QoWanwlvowVsACAAAAAAM0TV7S+aPVVzJOQ+cpSNKHTwyQ0mWa8tcHzfk3nR+9IAAzU2AH0AAAAFZAAgAAAAAHSaHWs/dnmI9sc7nB50VB2Bzs0kHapMHCQdyVEYY30TBXMAIAAAAACkV22lhEjWv/9/DubfHBAcwJggKI5mIbSK5L2nyqloqQVsACAAAAAAS19m7DccQxgryOsBJ3GsCs37yfQqNi1G+S6fCXpEhn4AAzU3AH0AAAAFZAAgAAAAAAL8jhNBG0KXXZhmZ0bPXtfgapJCB/AI+BEHB0eZ3C75BXMAIAAAAADHx/fPa639EBmGV5quLi8IQT600ifiKSOhTDOK19DnzwVsACAAAAAAlyLTDVkHxbayklD6Qymh3odIK1JHaOtps4f4HR+PcDgAAzU4AH0AAAAFZAAgAAAAAAxgeclNl09H7HvzD1oLwb2YpFca5eaX90uStYXHilqKBXMAIAAAAACMU5pSxzIzWlQxHyW170Xs9EhD1hURASQk+qkx7K5Y6AVsACAAAAAAJbMMwJfNftA7Xom8Bw/ghuZmSa3x12vTZxBUbV8m888AAzU5AH0AAAAFZAAgAAAAABmO7QD9vxWMmFjIHz13lyOeV6vHT6mYCsWxF7hb/yOjBXMAIAAAAACT9lmgkiqzuWG24afuzYiCeK9gmJqacmxAruIukd0xEAVsACAAAAAAZa0/FI/GkZR7CtX18Xg9Tn9zfxkD0UoaSt+pIO5t1t4AAzYwAH0AAAAFZAAgAAAAAB89SjLtDJkqEghRGyj6aQ/2qvWLNuMROoXmzbYbCMKMBXMAIAAAAAC8sywgND+CjhVTF6HnRQeay8y9/HnVzDI42dEPah28LQVsACAAAAAAoxv7UKh0RqUAWcOsQvU123zO1qZn73Xfib0qncZCB34AAzYxAH0AAAAFZAAgAAAAABN2alGq9Aats1mwERNGwL/fIwZSvVCe9/8XMHTFlpUpBXMAIAAAAACuDPjJgvvbBYhbLpjMiWUCsVppiYrhvR+yMysNPN8cZAVsACAAAAAAKpADjc4bzIZMi9Q/+oe0EMRJHYQt6dlo1x/lRquagqkAAzYyAH0AAAAFZAAgAAAAAL8YB6VAqGBiWD4CBv16IBscg5J7VQCTZu87n6pj+86KBXMAIAAAAAAmxm8e68geeyAdUjSMWBHzUjneVB0pG9TBXIoE6467hAVsACAAAAAAV76JZAlYpgC/Zl8awx2ArCg1uuyy2XVTSkp0wUMi/7UAAzYzAH0AAAAFZAAgAAAAAL4yLkCTV5Dmxa5toBu4JT8ge/cITAaURIOuFuOtFUkeBXMAIAAAAAAXoFNQOMGkAj7qEJP0wQafmFSXgWGeorDVbwyOxWLIsgVsACAAAAAAc4Un6dtIFe+AQ+RSfNWs3q63RTHhmyc+5GKRRdpWRv8AAzY0AH0AAAAFZAAgAAAAAEU8DoUp46YtYjNFS9kNXwdYxQ9IW27vCTb+VcqqfnKNBXMAIAAAAADe7vBOgYReE8X78k5ARuUnv4GmzPZzg6SbConf4L2G3wVsACAAAAAA78YHWVkp6HbZ0zS4UL2z/2pj9vPDcMDt7zTv6NcRsVsAAzY1AH0AAAAFZAAgAAAAAPa4yKTtkUtySuWo1ZQsp2QXtPb5SYqzA5vYDnS1P6c0BXMAIAAAAADKnF58R1sXlHlsHIvCBR3YWW/qk54z9CTDhZydkD1cOQVsACAAAAAAHW3ERalTFWKMzjuXF3nFh0pSrQxM/ojnPbPhc4v5MaQAAzY2AH0AAAAFZAAgAAAAAN5WJnMBmfgpuQPyonmY5X6OdRvuHw4nhsnGRnFAQ95VBXMAIAAAAACwftzu7KVV1rmGKwXtJjs3cJ1gE3apr8+N0SAg1F2cHwVsACAAAAAATDW0reyaCjbJuVLJzbSLx1OBuBoQu+090kgW4RurVacAAzY3AH0AAAAFZAAgAAAAACHvDsaPhoSb6DeGnKQ1QOpGYAgK82qpnqwcmzSeWaJHBXMAIAAAAABRq3C5+dOfnkAHM5Mg5hPB3O4jhwQlBgQWLA7Ph5bhgwVsACAAAAAAqkC8zYASvkVrp0pqmDyFCkPaDmD/ePAJpMuNOCBhni8AAzY4AH0AAAAFZAAgAAAAAOBePJvccPMJmy515KB1AkXF5Pi8NOG4V8psWy0SPRP+BXMAIAAAAAB3dOJG9xIDtEKCRzeNnPS3bFZepMj8UKBobKpSoCPqpgVsACAAAAAAPG3IxQVOdZrr509ggm5FKizWWoZPuVtOgOIGZ3m+pdEAAzY5AH0AAAAFZAAgAAAAABUvRrDQKEXLMdhnzXRdhiL6AGNs2TojPky+YVLXs+JnBXMAIAAAAAD1kYicbEEcPzD4QtuSYQQWDPq8fuUWGddpWayKn3dT9QVsACAAAAAA9+Sf7PbyFcY45hP9oTfjQiOUS3vEIAT8C0vOHymwYSUAAzcwAH0AAAAFZAAgAAAAAOvSnpujeKNen4pqc2HR63C5s5oJ1Vf4CsbKoYQvkwl5BXMAIAAAAACw2+vAMdibzd2YVVNfk81yXkFZP0WLJ82JBxJmXnYE+QVsACAAAAAArQ/E1ACyhK4ZyLqH9mNkCU7WClqRQTGyW9tciSGG/EMAAzcxAH0AAAAFZAAgAAAAAAo0xfGG7tJ3GWhgPVhW5Zn239nTD3PadShCNRc9TwdNBXMAIAAAAADZh243oOhenu0s/P/5KZLBDh9ADqKHtSWcXpO9D2sIjgVsACAAAAAAlgTPaoQKz+saU8rwCT3UiNOdG6hdpjzFx9GBn08ZkBEAABJjbQAAAAAAAAAAAAAQcGF5bG9hZElkAAAAAAAQZmlyc3RPcGVyYXRvcgABAAAAAA==", "subType": "06" } } } }, "encryptionInformation": { "type": 1, "schema": { "default.default": { "escCollection": "enxcol_.default.esc", "ecocCollection": "enxcol_.default.ecoc", "fields": [ { "keyId": { "$binary": { "base64": "EjRWeBI0mHYSNBI0VniQEg==", "subType": "04" } }, "path": "encryptedDoubleNoPrecision", "bsonType": "double", "queries": { "queryType": "rangePreview", "contention": { "$numberLong": "0" }, "sparsity": { "$numberLong": "1" } } } ] } } } }, "command_name": "find" } } ], "outcome": { "collection": { "data": [ { "_id": 0, "encryptedDoubleNoPrecision": { "$$type": "binData" }, "__safeContent__": [ { "$binary": { "base64": "5nRutVIyq7URVOVtbE4vM01APSIajAVnsShMwjBlzkM=", "subType": "00" } }, { "$binary": { "base64": "6YrBn2ofIw1b5ooakrLOwF41BWrps8OO0H9WH4/rtlE=", "subType": "00" } }, { "$binary": { "base64": "n+XAuFnP8Dov9TnhGFxNx0K/MnVM9WbJ7RouEu0ndO0=", "subType": "00" } }, { "$binary": { "base64": "yRXojuVdn5GQtD97qYlaCL6cOLmZ7Cvcb3wFjkLUIdM=", "subType": "00" } }, { "$binary": { "base64": "DuIkdRPITRs55I4SZmgomAHCIsDQmXRhW8+MOznkzSk=", "subType": "00" } }, { "$binary": { "base64": "SsBk+Et1lTbU+QRPx+xyJ/jMkmfG+QCvQEpip2YYrzA=", "subType": "00" } }, { "$binary": { "base64": "crCIzOd8KhHvvUlX7M1v9bhvU4pLdTc+X2SuqoKU5Ek=", "subType": "00" } }, { "$binary": { "base64": "YOWdCw4UrqnxkAaVjqmC4sKQDMVMHEpFGnlxpxdaU6E=", "subType": "00" } }, { "$binary": { "base64": "M3SShp81Ff8tQ632qKbv9MUcN6wjDaBReI0VXNu6Xh4=", "subType": "00" } }, { "$binary": { "base64": "gzHlSPxpM0hT75kQvWFzGlOxKvDoiKQZOr19V6l2zXI=", "subType": "00" } }, { "$binary": { "base64": "s3JnppOGYw9SL2Q1kMAZs948v2F5PrpXjGei/HioDWs=", "subType": "00" } }, { "$binary": { "base64": "cG6+3Gk/zEH68P/uuuwiAUVCuyJwa1LeV+t29FlPPAo=", "subType": "00" } }, { "$binary": { "base64": "dupdvR3AyJtM+g9NDKiaLVOtGca387JQp8w+V03m7Ig=", "subType": "00" } }, { "$binary": { "base64": "JqEQc5svj2jTvZ6LLA5ivE+kTb/0aRemSEmxk4G7Zrg=", "subType": "00" } }, { "$binary": { "base64": "szcXXXKnob+p3SoM4yED2R920LeJ7cVsclPMFTe4CeI=", "subType": "00" } }, { "$binary": { "base64": "o1QoGVXmuBdHwHm7aCtGMlMVKrjFdYvJXpoq6uhIAZ0=", "subType": "00" } }, { "$binary": { "base64": "Jfm5wPlqqLCJRGQIqRq2NGmpn7s0Vrih2H3YAOoI2YU=", "subType": "00" } }, { "$binary": { "base64": "zMHLb8ARbsYo8Ld05bqnGFf1Usha6EGb8QKwdSAyps0=", "subType": "00" } }, { "$binary": { "base64": "yQdtq9lh5pugL7/i0Bj/PuZUUBUIzf+7wj1rl5y736w=", "subType": "00" } }, { "$binary": { "base64": "wGWVZdO7qIuyDg/BqDgqjgoQ02h5YYgwXQB1oCin2NE=", "subType": "00" } }, { "$binary": { "base64": "by9HMLj6NTEpgztZ5HSN6GxImkXPcaFINYDzgZY33X8=", "subType": "00" } }, { "$binary": { "base64": "tWo0vbasi7bXmn/MsOx13VC1IsWtpx/nYp0uj4iMzdA=", "subType": "00" } }, { "$binary": { "base64": "tQQpndUYd5O87lOtrGjH3wl9VsOK0ray7RMasL90sBM=", "subType": "00" } }, { "$binary": { "base64": "cQjXEDCMsOpKLLf+vlTgIHA+cbSJdzqhbSX9Wvh95aA=", "subType": "00" } }, { "$binary": { "base64": "7yMpU48IxK9SzP2cx3VnTownGEwFmeFofuuFT97SuuY=", "subType": "00" } }, { "$binary": { "base64": "kSOx1kz0CmBgzKQHZlo65ZUY1DIv9A99JRm+Us2y6Ew=", "subType": "00" } }, { "$binary": { "base64": "ubQpdPBe6/xvtr+AcXdfYLSvYCR4ot0tivehkCsupb4=", "subType": "00" } }, { "$binary": { "base64": "xal+iCJ6FTefRQToyoNksc9NCZShyn04NDGi4IYrcoM=", "subType": "00" } }, { "$binary": { "base64": "d7jU4iOK50xHxlkSifcxlZFCM46TSgQzoYivxG3HNLY=", "subType": "00" } }, { "$binary": { "base64": "tJvl2nsBLBVzL3pp6sKWCL4UXeh3q/roYBJjSb74ve0=", "subType": "00" } }, { "$binary": { "base64": "OIUCaKRvIx9t1w6Hxlz1IcQTdPNCfdRNwnnTm10W+X0=", "subType": "00" } }, { "$binary": { "base64": "A9tvzsiElotOUVIB4CqfQp9mAwqvTM35YkmAR170aHA=", "subType": "00" } }, { "$binary": { "base64": "lI8gpK7hpb7c9x4RQugsxMnQay5LZJmwslZdvMx/dcE=", "subType": "00" } }, { "$binary": { "base64": "dNCzh40U0XvdKnSDi3HRQOWQftEsDVqc4uUvsVFGoq8=", "subType": "00" } }, { "$binary": { "base64": "IP+iwEBWBwVVZIdpaMu8k5+soFCz+TZkYn3drKZ9grE=", "subType": "00" } }, { "$binary": { "base64": "pnqyh6e0y5svHkJDShlN9CHV0WvMBE4QbtJpQw5ZCXc=", "subType": "00" } }, { "$binary": { "base64": "elEl42tbVDoRTLjAhZUFEtXiut4b3PVhg/1ZLZSQdtE=", "subType": "00" } }, { "$binary": { "base64": "vHuu2FxwclMHqyE6JBYbTYgbEkB0dqb/JuaxsvfwsmY=", "subType": "00" } }, { "$binary": { "base64": "xTf7NCe3Gf8QpE78HR5OknlLTKfs9J+RN9UZpH6fnso=", "subType": "00" } }, { "$binary": { "base64": "XiWSasRnJAulGR6+LCVD3mwRObXylqYWR9jvpywq12c=", "subType": "00" } }, { "$binary": { "base64": "MZMxEQ5ikx0PG1YFIExv0UnTZogsvgeOEZTpzvBDn4w=", "subType": "00" } }, { "$binary": { "base64": "yZMyMZBDrWbAhvnic7vvIYhmO9m5H2iuv0c8KNZrBzY=", "subType": "00" } }, { "$binary": { "base64": "xxM14hTPY5j0vvcK2C7YAEjzdsfUTFHozHC0hEo1bxI=", "subType": "00" } }, { "$binary": { "base64": "+01rqR1xVwkpGXcstbk1ItJqFVjH6Q8MGxEN3Cm9Y1A=", "subType": "00" } }, { "$binary": { "base64": "xOpLV0Z2VTRJ3iWtnWZcsyjXubTIkYWo31cO+HV1o1k=", "subType": "00" } }, { "$binary": { "base64": "BWUOLqgLBqc5NwxVlSV5H3KFQPXbCp7mdo+jF+8cJqY=", "subType": "00" } }, { "$binary": { "base64": "fuQb1S6xZDGlrEbK+kI23aL53PP1PVNwqICnZNt9Yzg=", "subType": "00" } }, { "$binary": { "base64": "SfscnoibFttahLdPVC4Ee+47ewGFKpDSU7M6HX19bKE=", "subType": "00" } }, { "$binary": { "base64": "rpSW2awybNVeKtat91VFxqbINoTfNhPfQAu+d73Xtf8=", "subType": "00" } }, { "$binary": { "base64": "9M/CP9ccOIIj2LLFmE0GFDO0Ban2wsNalEXfM6+h+1s=", "subType": "00" } }, { "$binary": { "base64": "WrEMG49l1ye4MhXs5ZS9tz8P6h+hDvthIg/2wW9ne1Q=", "subType": "00" } }, { "$binary": { "base64": "ImNhbfeyfH8qIEeA5ic0s3dAQBdzzTBS+CPsNih9vZ0=", "subType": "00" } }, { "$binary": { "base64": "dWP33YDSn04UKJN2ogh2Rui0iW/0q2y18OCDRVcfyoo=", "subType": "00" } }, { "$binary": { "base64": "lYv0isAtfGh6H9tdp3cp2eHU7q2J+uk7QrgcxtK3w7Y=", "subType": "00" } }, { "$binary": { "base64": "VGMoamB/+7zTOYcY/pqJc96xlv2PdW4hwsIAEIslTDQ=", "subType": "00" } }, { "$binary": { "base64": "yNeBWMF7BnD9wVwz2PgJsvWr77QiVvvWUvJF0+fqBug=", "subType": "00" } }, { "$binary": { "base64": "SfpvObJ+tJBXSvqeN7vlOfmhYign635lciYAJIjUtY8=", "subType": "00" } }, { "$binary": { "base64": "dsen4NqjzVGjpjufiTMs3+gqeD09EbnuogPgxrJECwg=", "subType": "00" } }, { "$binary": { "base64": "pxCWVM3sn19NsFEpgHbgLa+PmYlhN3mMiP0Wk8kJhYw=", "subType": "00" } }, { "$binary": { "base64": "q11KNvJszjYIB9n9HcC+N4uz11a3eRj1L3BH9scKMDQ=", "subType": "00" } }, { "$binary": { "base64": "A1PmkgcEToWh1JiVWE6mI5jUu7poxWWuCUt/cgRUUDc=", "subType": "00" } }, { "$binary": { "base64": "qJo3Hu4PJeanL7XEaWXO/n3YsodhZyd+MJOOmB9Kpd8=", "subType": "00" } }, { "$binary": { "base64": "BkBKLO8URFscfRY9Bav/1+L9mLohDgNr/MkZtGiraIs=", "subType": "00" } }, { "$binary": { "base64": "rZq5WA3Hx3xthOyHAJXK//f8pE2qbz7YKu3TIMp9GFY=", "subType": "00" } }, { "$binary": { "base64": "X07a/Lm80p5xd4RFs1dNmw+90tmPDPdGiAKVZkxd4zY=", "subType": "00" } } ] }, { "_id": 1, "encryptedDoubleNoPrecision": { "$$type": "binData" }, "__safeContent__": [ { "$binary": { "base64": "bE1vqWj3KNyM7cCYUv/cnYm8BPaUL3eMp5syTHq6NF4=", "subType": "00" } }, { "$binary": { "base64": "2FIZh/9N+NeJEQwxYIX5ikQT85xJzulBNReXk8PnG/s=", "subType": "00" } }, { "$binary": { "base64": "I93Md7QNPGmEEGYU1+VVCqBPBEvXdqHPtTJtMOn06Yk=", "subType": "00" } }, { "$binary": { "base64": "GecBFQ1PemlECWZWCl7f74vmsL6eB6mzQ9n6tK6FYfs=", "subType": "00" } }, { "$binary": { "base64": "QpjhZl+O1ORifgtCZuWAdcP6OKL7IZ2cA46v8FJcV28=", "subType": "00" } }, { "$binary": { "base64": "FWXI/yZ1M+2fIboeMCDMlp+I2NwPQDtoM/wWselOPYw=", "subType": "00" } }, { "$binary": { "base64": "uk26nvN/LdRLaBphiBgIZzT0sSpoO1z0RdDWRm/xrSA=", "subType": "00" } }, { "$binary": { "base64": "hiiYSH1KZovAULc7rlmEU74wCjzDR+mm6ZnsgvFQjMw=", "subType": "00" } }, { "$binary": { "base64": "hRzvMvWPX0sJme+wck67lwbKDFaWOa+Eyef+JSdc1s4=", "subType": "00" } }, { "$binary": { "base64": "PSx5D+zqC9c295dguX4+EobT4IEzfffdfjzC8DWpB5Q=", "subType": "00" } }, { "$binary": { "base64": "QzfXQCVTjPQv2h21v95HYPq8uCsVJ2tPnjv79gAaM9M=", "subType": "00" } }, { "$binary": { "base64": "XcGDO/dlTcEMLqwcm55UmOqK+KpBmbzZO1LIzX7GPaQ=", "subType": "00" } }, { "$binary": { "base64": "Lf+o4E7YB5ynzUPC6KTyW0lj6Cg9oLIu1Sdd1ODHctA=", "subType": "00" } }, { "$binary": { "base64": "wAuVn02LAVo5Y+TUocvkoenFYWzpu38k0NmGZOsAjS4=", "subType": "00" } }, { "$binary": { "base64": "yJGDtveLbbo/0HtCtiTSsvVI/0agg/U1bFaQ0yhK12o=", "subType": "00" } }, { "$binary": { "base64": "KsEy0zgYcmkM+O/fWF9z3aJGIk22XCk+Aw96HB6JU68=", "subType": "00" } }, { "$binary": { "base64": "p+AnMI5ZxdJMSIEJmXXya+FeH5yubmOdViwUO89j0Rc=", "subType": "00" } }, { "$binary": { "base64": "/jLix56jzeywBtNuGw55lCXyebQoSIhbful0hOKxKDY=", "subType": "00" } }, { "$binary": { "base64": "fvDvSPomtJsl1S3+8/tzFCE8scHIdJY5hB9CdTEsoFo=", "subType": "00" } }, { "$binary": { "base64": "oV5hOJzPXxfTuRdKIlF4uYEoMDuqH+G7/3qgndDr0PM=", "subType": "00" } }, { "$binary": { "base64": "3ALwcvLj3VOfgD6OqXAO13h1ZkOv46R6+Oy6SUKh53I=", "subType": "00" } }, { "$binary": { "base64": "gxaB9FJj0IM+InhvAjwWaex3UIZ9SAnDiUd5WHSY/l0=", "subType": "00" } }, { "$binary": { "base64": "66NPvDygJzKJqddfNuDuNOpvGajjFRtvhkwfUkiYmXw=", "subType": "00" } }, { "$binary": { "base64": "1dWcQIocRAcO9XnXYqbhl83jc0RgjQpsrWd8dC27trg=", "subType": "00" } }, { "$binary": { "base64": "npos0Uf1DT3ztSCjPVY9EImlRnTHB1KLrvmVSqBQ/8E=", "subType": "00" } }, { "$binary": { "base64": "TEI9qBx/tK1l1H0v1scMG8Srmtwo5VxWHADPBSlWrXk=", "subType": "00" } }, { "$binary": { "base64": "3wUN2ypQKoj+5ASkeIK9ycxhahVxyTmGopigoUAlyYs=", "subType": "00" } }, { "$binary": { "base64": "o/oksSnUS+nIq6ozWTbB5bJh+NoaPj8deAA23uxiWCk=", "subType": "00" } }, { "$binary": { "base64": "KExYPruhA31e8xuSwvfUfDcyY/H2Va6taUd0k4yFgLc=", "subType": "00" } }, { "$binary": { "base64": "/x+dNfxdd/lkx8Z8VZVfoYl7LPoaZ/iKEzZXBrAtIJc=", "subType": "00" } }, { "$binary": { "base64": "DE4cmjFLPqZlmRomO0qQiruUBtzoCe8ZdNRcfNH92pU=", "subType": "00" } }, { "$binary": { "base64": "M6EKNcLPw/iojAChgYUSieaBYWcbsjKtB94SaHOr8vk=", "subType": "00" } }, { "$binary": { "base64": "+qP49lDPeyhaduTvXJgtJEqHNEYANVu9Bg3Bxz7Td9w=", "subType": "00" } }, { "$binary": { "base64": "ruMrC2VIS+VKbJwCFb3bfkaLTju9nE+yPONV9s0M0Vo=", "subType": "00" } }, { "$binary": { "base64": "EbjDlSB5JKnDKff4d8hOmaOwJ7B9Q6NQFisLj+DPC+0=", "subType": "00" } }, { "$binary": { "base64": "C/yYOTB94edyqAbiQNu8/H7FoG3yRRjHDkMykz4+Mv0=", "subType": "00" } }, { "$binary": { "base64": "CBxqrejG+qQQq2YTd6iP/06kiu2CxxzBFaZK3Ofb1CM=", "subType": "00" } }, { "$binary": { "base64": "2ZOQ/fpho+AbDENWBZaln7wRoepIRdhyT648dr8O5cU=", "subType": "00" } }, { "$binary": { "base64": "EghIgEPz01+myPgj8oid+PgncvobvC7vjvG3THEEQ0M=", "subType": "00" } }, { "$binary": { "base64": "92CysZYNF8riwAMhdrIPKxfODw9p07cKQy/Snn8XmVY=", "subType": "00" } }, { "$binary": { "base64": "VO0LeTBQmsEf7sCHzTnZwUPNTqRZ49R8V5E9XnZ/5N4=", "subType": "00" } }, { "$binary": { "base64": "exs8BQMJq7U6ZXYgIizT7XN+X/hOmmn4YEuzev9zgSI=", "subType": "00" } }, { "$binary": { "base64": "qHpS4k1I+gPniNp4CA8TY8lLN36vBYmgbKMFpbYMEqg=", "subType": "00" } }, { "$binary": { "base64": "+7lWKCKAWFw6gPZdHE6E8KIfI14/fSvtWUmllb5WLi0=", "subType": "00" } }, { "$binary": { "base64": "YiH/US0q6679hWblFDDKNqUjCgggoU8sUCssTIF1QbU=", "subType": "00" } }, { "$binary": { "base64": "YgwkKElEubNfvXL9hJxzqQUQtHiXN/OCGxNL1MUZZlM=", "subType": "00" } }, { "$binary": { "base64": "hZFST4INZTTuhvJlGJeMwlUAK270UCOTCDeBAnN4a7g=", "subType": "00" } }, { "$binary": { "base64": "24I1Zw35AuGnK3CqJhbCwYb0IPuu5sCRrM5iyeITOLc=", "subType": "00" } }, { "$binary": { "base64": "vgD12JB4Q1S/kGPSQ1KOgp386KnG1GbM/5+60oRGcGw=", "subType": "00" } }, { "$binary": { "base64": "+wNE+OL+CB9d4AUJdVxd56jUJCAXmmk9fapuB2TAc4g=", "subType": "00" } }, { "$binary": { "base64": "uhQh1B2Pe4RkNw/kPEcgaLenuikKoRf1iyfZhpXdodc=", "subType": "00" } }, { "$binary": { "base64": "eu8gjAUIp8ybO204AgeOq5v1neI1yljqy5v3I6lo1lM=", "subType": "00" } }, { "$binary": { "base64": "7QG6oVbASBAjrnCPxzzUNnuFSFNlKhbuBafkF8pr7Is=", "subType": "00" } }, { "$binary": { "base64": "PUS1xb2oHSDTdYltutoSSxBiJ1NjxH3l2kA4P1CZLEs=", "subType": "00" } }, { "$binary": { "base64": "XPMh/JDC/O93gJJCwwgJDb8ssWZvRvezNmKmyn3nIfk=", "subType": "00" } }, { "$binary": { "base64": "jWz+KGwMk/GOvFAK2rOxF3OjxeZAWfmUQ1HGJ7icw4A=", "subType": "00" } }, { "$binary": { "base64": "o7XbW68pc6flYigf3LW4WAGUWxpeqxaQLkHUhUR9RZ8=", "subType": "00" } }, { "$binary": { "base64": "nqR+g60+5U0okbqJadSqGgnC+j1JcP8rwMcfzOs2ACI=", "subType": "00" } }, { "$binary": { "base64": "Hz43qVK95tSfbYFtaE/8fE97XMk1RiO8XpWjwZHB80o=", "subType": "00" } }, { "$binary": { "base64": "noZUWlZ8M6KXU5rkifyo8/duw5IL7/fXbJvT7bNmW9k=", "subType": "00" } }, { "$binary": { "base64": "WONVHCuPSanXDRQQ/3tmyJ0Vq+Lu/4hRaMUf0g0kSuw=", "subType": "00" } }, { "$binary": { "base64": "UEaj6vQRoIghE8Movd8AGXhtwIOXlP4cBsECIUvE5Y8=", "subType": "00" } }, { "$binary": { "base64": "D3n2YcO8+PB4C8brDo7kxKjF9Y844rVkdRMLTgsQkrw=", "subType": "00" } }, { "$binary": { "base64": "C+YA0G9KjxZVaWwOMuh/dcnHnHAlYnbFrRl0IEpmsY0=", "subType": "00" } }, { "$binary": { "base64": "rUnmbmQanxrbFPYYrwyQ53x66OSt27yAvF+s48ezKDc=", "subType": "00" } } ] } ] } } } ] } fle2v2-Range-Double-Update.json000066400000000000000000001370111462766011000346030ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/client-side-encryption/spec/legacy{ "runOn": [ { "minServerVersion": "7.0.0", "topology": [ "replicaset", "sharded", "load-balanced" ] } ], "database_name": "default", "collection_name": "default", "data": [], "encrypted_fields": { "fields": [ { "keyId": { "$binary": { "base64": "EjRWeBI0mHYSNBI0VniQEg==", "subType": "04" } }, "path": "encryptedDoubleNoPrecision", "bsonType": "double", "queries": { "queryType": "rangePreview", "contention": { "$numberLong": "0" }, "sparsity": { "$numberLong": "1" } } } ] }, "key_vault_data": [ { "_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" } } ], "tests": [ { "description": "FLE2 Range Double. Update.", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "local": { "key": { "$binary": { "base64": "Mng0NCt4ZHVUYUJCa1kxNkVyNUR1QURhZ2h2UzR2d2RrZzh0cFBwM3R6NmdWMDFBMUN3YkQ5aXRRMkhGRGdQV09wOGVNYUMxT2k3NjZKelhaQmRCZGJkTXVyZG9uSjFk", "subType": "00" } } } } } }, "operations": [ { "name": "insertOne", "arguments": { "document": { "_id": 0, "encryptedDoubleNoPrecision": { "$numberDouble": "0" } } } }, { "name": "insertOne", "arguments": { "document": { "_id": 1, "encryptedDoubleNoPrecision": { "$numberDouble": "1" } } } }, { "name": "updateOne", "arguments": { "filter": { "encryptedDoubleNoPrecision": { "$gt": { "$numberDouble": "0" } } }, "update": { "$set": { "encryptedDoubleNoPrecision": { "$numberDouble": "2" } } } }, "result": { "matchedCount": 1, "modifiedCount": 1, "upsertedCount": 0 } } ], "expectations": [ { "command_started_event": { "command": { "listCollections": 1, "filter": { "name": "default" } }, "command_name": "listCollections" } }, { "command_started_event": { "command": { "find": "datakeys", "filter": { "$or": [ { "_id": { "$in": [ { "$binary": { "base64": "EjRWeBI0mHYSNBI0VniQEg==", "subType": "04" } } ] } }, { "keyAltNames": { "$in": [] } } ] }, "$db": "keyvault", "readConcern": { "level": "majority" } }, "command_name": "find" } }, { "command_started_event": { "command": { "insert": "default", "documents": [ { "_id": 0, "encryptedDoubleNoPrecision": { "$$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": "encryptedDoubleNoPrecision", "bsonType": "double", "queries": { "queryType": "rangePreview", "contention": { "$numberLong": "0" }, "sparsity": { "$numberLong": "1" } } } ] } } } }, "command_name": "insert" } }, { "command_started_event": { "command": { "insert": "default", "documents": [ { "_id": 1, "encryptedDoubleNoPrecision": { "$$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": "encryptedDoubleNoPrecision", "bsonType": "double", "queries": { "queryType": "rangePreview", "contention": { "$numberLong": "0" }, "sparsity": { "$numberLong": "1" } } } ] } } } }, "command_name": "insert" } }, { "command_started_event": { "command_name": "update", "command": { "update": "default", "ordered": true, "updates": [ { "q": { "encryptedDoubleNoPrecision": { "$gt": { "$binary": { "base64": "DYckAAADcGF5bG9hZABXJAAABGcAQyQAAAMwAH0AAAAFZAAgAAAAAHgYoMGjEE6fAlAhICv0+doHcVX8CmMVxyq7+jlyGrvmBXMAIAAAAAC/5MQZgTHuIr/O5Z3mXPvqrom5JTQ8IeSpQGhO9sB+8gVsACAAAAAAuPSXVmJUAUpTQg/A9Bu1hYczZF58KEhVofakygbsvJQAAzEAfQAAAAVkACAAAAAA2kiWNvEc4zunJ1jzvuClFC9hjZMYruKCqAaxq+oY8EAFcwAgAAAAACofIS72Cm6s866UCk+evTH3CvKBj/uZd72sAL608rzTBWwAIAAAAADuCQ/M2xLeALF0UFZtJb22QGOhHmJv6xoO+kZIHcDeiAADMgB9AAAABWQAIAAAAABkfoBGmU3hjYBvQbjNW19kfXneBQsQQPRfUL3UAwI2cAVzACAAAAAAUpK2BUOqX/DGdX5YJniEZMWkofxHqeAbXceEGJxhp8AFbAAgAAAAAKUaLzIldNIZv6RHE+FwbMjzcNHqPESwF/37mm43VPrsAAMzAH0AAAAFZAAgAAAAAFNprhQ3ZwIcYbuzLolAT5n/vc14P9kUUQComDu6eFyKBXMAIAAAAAAcx9z9pk32YbPV/sfPZl9ALIEVsqoLXgqWLVK/tP+heAVsACAAAAAA/qxvuvJbAHwwhfrPVpmCFzNvg2cU/NXaWgqgYUZpgXwAAzQAfQAAAAVkACAAAAAAODI+pB2pCuB+YmNEUAgtMfNdt3DmSkrJ96gRzLphgb8FcwAgAAAAAAT7dewFDxUDECQ3zVq75/cUN4IP+zsqhkP5+czUwlJIBWwAIAAAAACFGeOtd5zBXTJ4JYonkn/HXZfHipUlqGwIRUcH/VTatwADNQB9AAAABWQAIAAAAACNAk+yTZ4Ewk1EnotQK8O3h1gg9I7pr9q2+4po1iJVgAVzACAAAAAAUj/LesmtEsgqYVzMJ67umVA11hJTdDXwbxDoQ71vWyUFbAAgAAAAABlnhpgTQ0WjLb5u0b/vEydrCeFjVynKd7aqb+UnvVLeAAM2AH0AAAAFZAAgAAAAAD/FIrGYFDjyYmVb7oTMVwweWP7A6F9LnyIuNO4MjBnXBXMAIAAAAACIZgJCQRZu7NhuNMyOqCn1tf+DfU1qm10TPCfj5JYV3wVsACAAAAAA5hmY4ptuNxULGf87SUFXQWGAONsL9U29duh8xqsHtxoAAzcAfQAAAAVkACAAAAAAciRW40ORJLVwchOEpz87Svb+5toAFM6LxDWv928ECwQFcwAgAAAAAN0dipyESIkszfjRzdDi8kAGaa2Hf4wrPAtiWwboZLuxBWwAIAAAAAANr4o/+l1OIbbaX5lZ3fQ/WIeOcEXjNI1F0WbSgQrzaQADOAB9AAAABWQAIAAAAACZqAyCzYQupJ95mrBJX54yIz9VY7I0WrxpNYElCI4dTQVzACAAAAAA/eyJb6d1xfE+jJlVXMTD3HS/NEYENPVKAuj56Dr2dSEFbAAgAAAAANkSt154Or/JKb31VvbZFV46RPgUp8ff/hcPORL7PpFBAAM5AH0AAAAFZAAgAAAAAI5bm3YO0Xgf0VT+qjVTTfvckecM3Cwqj7DTKZXf8/NXBXMAIAAAAAD/m+h8fBhWaHm6Ykuz0WX1xL4Eme3ErLObyEVJf8NCywVsACAAAAAAfb1VZZCqs2ivYbRzX4p5CtaCkKW+g20Pr57FWXzEZi8AAzEwAH0AAAAFZAAgAAAAANqo4+p6qdtCzcB4BX1wQ6llU7eFBnuu4MtZwp4B6mDlBXMAIAAAAAAGiz+VaukMZ+6IH4jtn4KWWdKK4/W+O+gRioQDrfzpMgVsACAAAAAAG4YYkTp80EKo59mlHExDodRQFR7njhR5dmISwUJ6ukAAAzExAH0AAAAFZAAgAAAAAPrFXmHP2Y4YAm7b/aqsdn/DPoDkv7B8egWkfe23XsM1BXMAIAAAAAAGhwpKAr7skeqHm3oseSbO7qKNhmYsuUrECBxJ5k+D2AVsACAAAAAAAqPQi9luYAu3GrFCEsVjd9z2zIDcp6SPTR2w6KQEr+IAAzEyAH0AAAAFZAAgAAAAABzjYxwAjXxXc0Uxv18rH8I3my0Aguow0kTwKyxbrm+cBXMAIAAAAADVbqJVr6IdokuhXkEtXF0C2gINLiAjMVN20lE20Vmp2QVsACAAAAAAD7K1Fx4gFaaizkIUrf+EGXQeG7QX1jadhGc6Ji471H8AAzEzAH0AAAAFZAAgAAAAAFMm2feF2fFCm/UC6AfIyepX/xJDSmnnolQIBnHcPmb5BXMAIAAAAABLI11kFrQoaNVZFmq/38aRNImPOjdJh0Lo6irI8M/AaAVsACAAAAAAOWul0oVqJ9CejD2RqphhTC98DJeRQy5EwbNerU2+4l8AAzE0AH0AAAAFZAAgAAAAAJvXB3KyNiNtQko4SSzo/9b2qmM2zU9CQTTDfLSBWMgRBXMAIAAAAAAvjuVP7KsLRDeqVqRziTKpBrjVyqKiIbO9Gw8Wl2wFTAVsACAAAAAADlE+oc1ins+paNcaOZJhBlKlObDJ4VQORWjFYocM4LgAAzE1AH0AAAAFZAAgAAAAAPGdcxDiid8z8XYnfdDivNMYVPgBKdGOUw6UStU+48CdBXMAIAAAAAARj6g1Ap0eEfuCZ4X2TsEw+Djrhto3fA5nLwPaY0vCTgVsACAAAAAAoHqiwGOUkBu8SX5U1yHho+UIFdSN2MdQN5s6bQ0EsJYAAzE2AH0AAAAFZAAgAAAAAP5rGPrYGt3aKob5f/ldP0qrW7bmWvqnKY4QwdDWz400BXMAIAAAAADTQkW2ymaaf/bhteOOGmSrIR97bAnJx+yN3yMj1bTeewVsACAAAAAADyQnHGH2gF4w4L8axUsSTf6Ubk7L5/eoFOJk12MtZAoAAzE3AH0AAAAFZAAgAAAAAAlz6wJze5UkIxKpJOZFGCOf3v2KByWyI6NB6JM9wNcBBXMAIAAAAABUC7P/neUIHHoZtq0jFVBHY75tSFYr1Y5S16YN5XxC1QVsACAAAAAAgvxRbXDisNnLY3pfsjDdnFLtkvYUC4lhA68eBXc7KAwAAzE4AH0AAAAFZAAgAAAAAFJ8AtHcjia/9Y5pLEc3qVgH5xKiXw12G9Kn2A1EY8McBXMAIAAAAAAxe7Bdw7eUSBk/oAawa7uicTEDgXLymRNhBy1LAxhDvwVsACAAAAAAxKPaIBKVx3jTA+R/el7P7AZ7efrmTGjJs3Hj/YdMddwAAzE5AH0AAAAFZAAgAAAAAO8uwQUaKFb6vqR3Sv3Wn4QAonC2exOC9lGG1juqP5DtBXMAIAAAAABZf1KyJgQg8/Rf5c02DgDK2aQu0rNCOvaL60ohDHyY+gVsACAAAAAAqyEjfKC8lYoIfoXYHUqHZPoaA6EK5BAZy5dxXZmay4kAAzIwAH0AAAAFZAAgAAAAAE8YtqyRsGCeiR6hhiyisR/hccmK4nZqIMzO4lUBmEFzBXMAIAAAAAC1UYOSKqAeG1UJiKjWFVskRhuFKpj9Ezy+lICZvFlN5AVsACAAAAAA6Ct9nNMKyRazn1OKnRKagm746CGu+jyhbL1qJnZxGi0AAzIxAH0AAAAFZAAgAAAAAPhCrMausDx1QUIEqp9rUdRKyM6a9AAx7jQ3ILIu8wNIBXMAIAAAAACmH8lotGCiF2q9VQxhsS+7LAZv79VUAsOUALaGxE/EpAVsACAAAAAAnc1xCKfdvbUEc8F7XZqlNn1C+hZTtC0I9I3LL06iaNkAAzIyAH0AAAAFZAAgAAAAAOBi/GAYFcstMSJPgp3VkMiuuUUCrZytvqYaU8dwm8v2BXMAIAAAAACEZSZVyD3pKzGlbdwlYmWQhHHTV5SnNLknl2Gw8IaUTQVsACAAAAAAfsLZsEDcWSuNsIo/TD1ReyQW75HPMgmuKZuWFOLKRLoAAzIzAH0AAAAFZAAgAAAAAIQuup+YGfH3mflzWopN8J1X8o8a0d9CSGIvrA5HOzraBXMAIAAAAADYvNLURXsC2ITMqK14LABQBI+hZZ5wNf24JMcKLW+84AVsACAAAAAACzfjbTBH7IwDU91OqLAz94RFkoqBOkzKAqQb55gT4/MAAzI0AH0AAAAFZAAgAAAAAKsh0ADyOnVocFrOrf6MpTrNvAj8iaiE923DPryu124gBXMAIAAAAADg24a8NVE1GyScc6tmnTbmu5ulzO+896fE92lN08MeswVsACAAAAAAaPxcOIxnU7But88/yadOuDJDMcCywwrRitaxMODT4msAAzI1AH0AAAAFZAAgAAAAAKkVC2Y6HtRmv72tDnPUSjJBvse7SxLqnr09/Uuj9sVVBXMAIAAAAABYNFUkH7ylPMN+Bc3HWX1e0flGYNbtJNCY9SltJCW/UAVsACAAAAAAZYK/f9H4OeihmpiFMH7Wm7uLvs2s92zNA8wyrNZTsuMAAzI2AH0AAAAFZAAgAAAAADDggcwcb/Yn1Kk39sOHsv7BO/MfP3m/AJzjGH506Wf9BXMAIAAAAAAYZIsdjICS0+BDyRUPnrSAZfPrwtuMaEDEn0/ijLNQmAVsACAAAAAAGPnYVvo2ulO9z4LGd/69NAklfIcZqZvFX2KK0s+FcTUAAzI3AH0AAAAFZAAgAAAAAEWY7dEUOJBgjOoWVht1wLehsWAzB3rSOBtLgTuM2HC8BXMAIAAAAAAAoswiHRROurjwUW8u8D5EUT+67yvrgpB/j6PzBDAfVwVsACAAAAAA6NhRTYFL/Sz4tao7vpPjLNgAJ0FX6P/IyMW65qT6YsMAAzI4AH0AAAAFZAAgAAAAAPZaapeAUUFPA7JTCMOWHJa9lnPFh0/gXfAPjA1ezm4ZBXMAIAAAAACmJvLY2nivw7/b3DOKH/X7bBXjJwoowqb1GtEFO3OYgAVsACAAAAAA/JcUoyKacCB1NfmH8vYqC1f7rd13KShrQqV2r9QBP44AAzI5AH0AAAAFZAAgAAAAAK00u6jadxCZAiA+fTsPVDsnW5p5LCr4+kZZZOTDuZlfBXMAIAAAAAAote4zTEYMDgaaQbAdN8Dzv93ljPLdGjJzvnRn3KXgtQVsACAAAAAAxXd9Mh6R3mnJy8m7UfqMKi6oD5DlZpkaOz6bEjMOdiwAAzMwAH0AAAAFZAAgAAAAAFbgabdyymiEVYYwtJSWa7lfl/oYuj/SukzJeDOR6wPVBXMAIAAAAADAFGFjS1vPbN6mQEhkDYTD6V2V23Ys9gUEUMGNvMPkaAVsACAAAAAAL/D5Sze/ZoEanZLK0IeEkhgVkxEjMWVCfmJaD3a8uNIAAzMxAH0AAAAFZAAgAAAAABNMR6UBv2E627CqLtQ/eDYx7OEwQ7JrR4mSHFa1N8tLBXMAIAAAAAAxH4gucI4UmNVB7625C6hFSVCuIpJO3lusJlPuL8H5EQVsACAAAAAAVLHNg0OUVqZ7WGOP53BkTap9FOw9dr1P4J8HxqFqU04AAzMyAH0AAAAFZAAgAAAAAG8cd6WBneNunlqrQ2EmNf35W7OGObGq9WL4ePX+LUDmBXMAIAAAAAAjJ2+sX87NSis9hBsgb1QprVRnO7Bf+GObCGoUqyPE4wVsACAAAAAAs9c9SM49/pWmyUQKslpt3RTMBNSRppfNO0JBvUqHPg0AAzMzAH0AAAAFZAAgAAAAAFWOUGkUpy8yf6gB3dio/aOfRKh7XuhvsUj48iESFJrGBXMAIAAAAAAY7sCDMcrUXvNuL6dO0m11WyijzXZvPIcOKob6IpC4PQVsACAAAAAAJOP+EHz6awDb1qK2bZQ3kTV7wsj5Daj/IGAWh4g7omAAAzM0AH0AAAAFZAAgAAAAAGUrIdKxOihwNmo6B+aG+Ag1qa0+iqdksHOjQj+Oy9bZBXMAIAAAAABwa5dbI2KmzBDNBTQBEkjZv4sPaeRkRNejcjdVymRFKQVsACAAAAAA4ml/nm0gJNTcJ4vuD+T2Qfq2fQZlibJp/j6MOGDrbHMAAzM1AH0AAAAFZAAgAAAAAOx89xV/hRk64/CkM9N2EMK6aldII0c8smdcsZ46NbP8BXMAIAAAAADBF6tfQ+7q9kTuLyuyrSnDgmrdmrXkdhl980i1KHuGHgVsACAAAAAACUqiFqHZdGbwAA+hN0YUE5zFg+H+dabIB4dj5/75W/YAAzM2AH0AAAAFZAAgAAAAAMkN0L1oQWXhjwn9rAdudcYeN8/5VdCKU8cmDt7BokjsBXMAIAAAAAAT62pGXoRwExe9uvgYOI0hg5tOxilrWfoEmT0SMglWJwVsACAAAAAAlVz4dhiprSbUero6JFfxzSJGclg63oAkAmgbSwbcYxIAAzM3AH0AAAAFZAAgAAAAANxfa4xCoaaB7k1C1RoH1LBhsCbN2yEq15BT9b+iqEC4BXMAIAAAAACAX9LV8Pemfw7NF0iB1/85NzM1Ef+1mUfyehacUVgobQVsACAAAAAAVq4xpbymLk0trPC/a2MvB39I7hRiX8EJsVSI5E5hSBkAAzM4AH0AAAAFZAAgAAAAAOYIYoWkX7dGuyKfi3XssUlc7u/gWzqrR9KMkikKVdmSBXMAIAAAAABVF2OYjRTGi9Tw8XCAwZWLpX35Yl271TlNWp6N/nROhAVsACAAAAAA0nWwYzXQ1+EkDvnGq+SMlq20z+j32Su+i/A95SggPb4AAzM5AH0AAAAFZAAgAAAAAIy0+bXZi10QC+q7oSOLXK5Fee7VEk/qHSXukfeVIfgzBXMAIAAAAAAQ3IIV/JQCHW95AEbH5zGIHtJqyuPjWPMIZ+VmQHlxEwVsACAAAAAAp0jYsyohKv9Pm+4k+DplEGbl9WLZpAJzitrcDj4CNsMAAzQwAH0AAAAFZAAgAAAAAL5SOJQ3LOhgdXJ5v086NNeAl1qonQnchObdpZJ1kHeEBXMAIAAAAAA+tEqTXODtik+ydJZSnUqXF9f18bPeze9eWtR7ExZJgQVsACAAAAAAbrkZCVgB9Qsp4IAbdf+bD4fT6Boqk5UtuA/zhNrh1y0AAzQxAH0AAAAFZAAgAAAAAKl8zcHJRDjSjJeV/WvMxulW1zrTFtaeBy/aKKhadc6UBXMAIAAAAADBdWQl5SBIvtZZLIHszePwkO14W1mQ0izUk2Ov21cPNAVsACAAAAAAHErCYycpqiIcCZHdmPL1hi+ovLQk4TAvENpfLdTRamQAAzQyAH0AAAAFZAAgAAAAAFvotcNaoKnVt5CBCOPwjexFO0WGWuaIGL6H/6KSau+6BXMAIAAAAAD2y2mBN5xPu5PJoY2zcr0GnQDtHRBogA5+xzIxccE9fwVsACAAAAAAdS34xzJesnUfxLCcc1U7XzUqLy8MAzV/tcjbqaD3lkMAAzQzAH0AAAAFZAAgAAAAAPezU0/vNT4Q4YKbTbaeHqcwNLT+IjW/Y9QFpIooihjPBXMAIAAAAACj2x4O4rHter8ZnTws5LAP9jJ/6kk9C/V3vL50LoFZHAVsACAAAAAAQdBDF3747uCVP5lB/zr8VmzxJfTSZHBKeIgm5FyONXwAAzQ0AH0AAAAFZAAgAAAAAMqpayM2XotEFmm0gwQd9rIzApy0X+7HfOhNk6VU7F5lBXMAIAAAAACJR9+q5T9qFHXFNgGbZnPubG8rkO6cwWhzITQTmd6VgwVsACAAAAAAOZLQ6o7e4mVfDzbpQioa4d3RoTvqwgnbmc5Qh2wsZuoAAzQ1AH0AAAAFZAAgAAAAANCeyW+3oebaQk+aqxNVhAcT/BZ5nhsTVdKS3tMrLSvWBXMAIAAAAADxRFMDhkyuEc++WnndMfoUMLNL7T7rWoeblcrpSI6soQVsACAAAAAAdBuBMJ1lxt0DRq9pOZldQqchLs3B/W02txcMLD490FEAAzQ2AH0AAAAFZAAgAAAAAIbo5YBTxXM7HQhl7UP9NNgpPGFkBx871r1B65G47+K8BXMAIAAAAAC21dJSxnEhnxO5gzN5/34BL4von45e1meW92qowzb8fQVsACAAAAAAm3Hk2cvBN0ANaR5jzeZE5TsdxDvJCTOT1I01X7cNVaYAAzQ3AH0AAAAFZAAgAAAAABm/6pF96j26Jm7z5KkY1y33zcAEXLx2n0DwC03bs/ixBXMAIAAAAAD01OMvTZI/mqMgxIhA5nLs068mW+GKl3OW3ilf2D8+LgVsACAAAAAAaLvJDrqBESTNZSdcXsd+8GXPl8ZkUsGpeYuyYVv/kygAAzQ4AH0AAAAFZAAgAAAAAJ/D3+17gaQdkBqkL2wMwccdmCaVOtxzIkM8VyI4xI5zBXMAIAAAAAAggLVmkc5u+YzBR+oNE+XgLVp64fC6MzUb/Ilu/Jsw0AVsACAAAAAACz3HVKdWkx82/kGbVpcbAeZtsj2R5Zr0dEPfle4IErkAAzQ5AH0AAAAFZAAgAAAAAJMRyUW50oaTzspS6A3TUoXyC3gNYQoShUGPakMmeVZrBXMAIAAAAACona2Pqwt4U2PmFrtmu37jB9kQ/12okyAVtYa8TQkDiQVsACAAAAAAltJJKjCMyBTJ+4PkdDCPJdeX695P8P5h7WOZ+kmExMAAAzUwAH0AAAAFZAAgAAAAAByuYl8dBvfaZ0LO/81JW4hYypeNmvLMaxsIdvqMPrWoBXMAIAAAAABNddwobOUJzm9HOUD8BMZJqkNCUCqstHZkC76FIdNg9AVsACAAAAAAQQOkIQtkyNavqCnhQbNg3HfqrJdsAGaoxSJePJl1qXsAAzUxAH0AAAAFZAAgAAAAAHEzLtfmF/sBcYPPdj8867VmmQyU1xK9I/3Y0478azvABXMAIAAAAAAcmyFajZPnBTbO+oLInNwlApBocUekKkxz2hYFeSlQ+gVsACAAAAAAZ6IkrOVRcC8vSA6Vb4fPWZJrYexXhEabIuYIeXNsCSgAAzUyAH0AAAAFZAAgAAAAAJam7JYsZe2cN20ZYm2W3v1pisNt5PLiniMzymBLWyMtBXMAIAAAAABxCsKVMZMTn3n+R2L7pVz5nW804r8HcK0mCBw3jUXKXAVsACAAAAAA7j3JGnNtR64P4dJLeUoScFRGfa8ekjh3dvhw46sRFk0AAzUzAH0AAAAFZAAgAAAAAMXrXx0saZ+5gORmwM2FLuZG6iuO2YS+1IGPoAtDKoKBBXMAIAAAAADIQsxCr8CfFKaBcx8kIeSywnGh7JHjKRJ9vJd9x79y7wVsACAAAAAAcvBV+SykDYhmRFyVYwFYB9oBKBSHr55Jdz2cXeowsUQAAzU0AH0AAAAFZAAgAAAAACbzcUD3INSnCRspOKF7ubne74OK9L0FTZvi9Ay0JVDYBXMAIAAAAADPebVQH8Btk9rhBIoUOdSAdpPvz7qIY4UC2i6IGisSAQVsACAAAAAAiBunJi0mPnnXdnldiq+If8dcb/n6apHnaIFt+oyYO1kAAzU1AH0AAAAFZAAgAAAAACUc2CtD1MK/UTxtv+8iA9FoHEyTwdl43HKeSwDw2Lp5BXMAIAAAAACCIduIdw65bQMzRYRfjBJj62bc69T4QqH4QoWanwlvowVsACAAAAAAM0TV7S+aPVVzJOQ+cpSNKHTwyQ0mWa8tcHzfk3nR+9IAAzU2AH0AAAAFZAAgAAAAAHSaHWs/dnmI9sc7nB50VB2Bzs0kHapMHCQdyVEYY30TBXMAIAAAAACkV22lhEjWv/9/DubfHBAcwJggKI5mIbSK5L2nyqloqQVsACAAAAAAS19m7DccQxgryOsBJ3GsCs37yfQqNi1G+S6fCXpEhn4AAzU3AH0AAAAFZAAgAAAAAAL8jhNBG0KXXZhmZ0bPXtfgapJCB/AI+BEHB0eZ3C75BXMAIAAAAADHx/fPa639EBmGV5quLi8IQT600ifiKSOhTDOK19DnzwVsACAAAAAAlyLTDVkHxbayklD6Qymh3odIK1JHaOtps4f4HR+PcDgAAzU4AH0AAAAFZAAgAAAAAAxgeclNl09H7HvzD1oLwb2YpFca5eaX90uStYXHilqKBXMAIAAAAACMU5pSxzIzWlQxHyW170Xs9EhD1hURASQk+qkx7K5Y6AVsACAAAAAAJbMMwJfNftA7Xom8Bw/ghuZmSa3x12vTZxBUbV8m888AAzU5AH0AAAAFZAAgAAAAABmO7QD9vxWMmFjIHz13lyOeV6vHT6mYCsWxF7hb/yOjBXMAIAAAAACT9lmgkiqzuWG24afuzYiCeK9gmJqacmxAruIukd0xEAVsACAAAAAAZa0/FI/GkZR7CtX18Xg9Tn9zfxkD0UoaSt+pIO5t1t4AAzYwAH0AAAAFZAAgAAAAAB89SjLtDJkqEghRGyj6aQ/2qvWLNuMROoXmzbYbCMKMBXMAIAAAAAC8sywgND+CjhVTF6HnRQeay8y9/HnVzDI42dEPah28LQVsACAAAAAAoxv7UKh0RqUAWcOsQvU123zO1qZn73Xfib0qncZCB34AAzYxAH0AAAAFZAAgAAAAABN2alGq9Aats1mwERNGwL/fIwZSvVCe9/8XMHTFlpUpBXMAIAAAAACuDPjJgvvbBYhbLpjMiWUCsVppiYrhvR+yMysNPN8cZAVsACAAAAAAKpADjc4bzIZMi9Q/+oe0EMRJHYQt6dlo1x/lRquagqkAAzYyAH0AAAAFZAAgAAAAAL8YB6VAqGBiWD4CBv16IBscg5J7VQCTZu87n6pj+86KBXMAIAAAAAAmxm8e68geeyAdUjSMWBHzUjneVB0pG9TBXIoE6467hAVsACAAAAAAV76JZAlYpgC/Zl8awx2ArCg1uuyy2XVTSkp0wUMi/7UAAzYzAH0AAAAFZAAgAAAAAL4yLkCTV5Dmxa5toBu4JT8ge/cITAaURIOuFuOtFUkeBXMAIAAAAAAXoFNQOMGkAj7qEJP0wQafmFSXgWGeorDVbwyOxWLIsgVsACAAAAAAc4Un6dtIFe+AQ+RSfNWs3q63RTHhmyc+5GKRRdpWRv8AAzY0AH0AAAAFZAAgAAAAAEU8DoUp46YtYjNFS9kNXwdYxQ9IW27vCTb+VcqqfnKNBXMAIAAAAADe7vBOgYReE8X78k5ARuUnv4GmzPZzg6SbConf4L2G3wVsACAAAAAA78YHWVkp6HbZ0zS4UL2z/2pj9vPDcMDt7zTv6NcRsVsAAzY1AH0AAAAFZAAgAAAAAPa4yKTtkUtySuWo1ZQsp2QXtPb5SYqzA5vYDnS1P6c0BXMAIAAAAADKnF58R1sXlHlsHIvCBR3YWW/qk54z9CTDhZydkD1cOQVsACAAAAAAHW3ERalTFWKMzjuXF3nFh0pSrQxM/ojnPbPhc4v5MaQAAzY2AH0AAAAFZAAgAAAAAN5WJnMBmfgpuQPyonmY5X6OdRvuHw4nhsnGRnFAQ95VBXMAIAAAAACwftzu7KVV1rmGKwXtJjs3cJ1gE3apr8+N0SAg1F2cHwVsACAAAAAATDW0reyaCjbJuVLJzbSLx1OBuBoQu+090kgW4RurVacAAzY3AH0AAAAFZAAgAAAAACHvDsaPhoSb6DeGnKQ1QOpGYAgK82qpnqwcmzSeWaJHBXMAIAAAAABRq3C5+dOfnkAHM5Mg5hPB3O4jhwQlBgQWLA7Ph5bhgwVsACAAAAAAqkC8zYASvkVrp0pqmDyFCkPaDmD/ePAJpMuNOCBhni8AAzY4AH0AAAAFZAAgAAAAAOBePJvccPMJmy515KB1AkXF5Pi8NOG4V8psWy0SPRP+BXMAIAAAAAB3dOJG9xIDtEKCRzeNnPS3bFZepMj8UKBobKpSoCPqpgVsACAAAAAAPG3IxQVOdZrr509ggm5FKizWWoZPuVtOgOIGZ3m+pdEAAzY5AH0AAAAFZAAgAAAAABUvRrDQKEXLMdhnzXRdhiL6AGNs2TojPky+YVLXs+JnBXMAIAAAAAD1kYicbEEcPzD4QtuSYQQWDPq8fuUWGddpWayKn3dT9QVsACAAAAAA9+Sf7PbyFcY45hP9oTfjQiOUS3vEIAT8C0vOHymwYSUAAzcwAH0AAAAFZAAgAAAAAOvSnpujeKNen4pqc2HR63C5s5oJ1Vf4CsbKoYQvkwl5BXMAIAAAAACw2+vAMdibzd2YVVNfk81yXkFZP0WLJ82JBxJmXnYE+QVsACAAAAAArQ/E1ACyhK4ZyLqH9mNkCU7WClqRQTGyW9tciSGG/EMAAzcxAH0AAAAFZAAgAAAAAAo0xfGG7tJ3GWhgPVhW5Zn239nTD3PadShCNRc9TwdNBXMAIAAAAADZh243oOhenu0s/P/5KZLBDh9ADqKHtSWcXpO9D2sIjgVsACAAAAAAlgTPaoQKz+saU8rwCT3UiNOdG6hdpjzFx9GBn08ZkBEAABJjbQAAAAAAAAAAAAAQcGF5bG9hZElkAAAAAAAQZmlyc3RPcGVyYXRvcgABAAAAAA==", "subType": "06" } } } }, "u": { "$set": { "encryptedDoubleNoPrecision": { "$$type": "binData" } } } } ], "encryptionInformation": { "type": 1, "schema": { "default.default": { "escCollection": "enxcol_.default.esc", "ecocCollection": "enxcol_.default.ecoc", "fields": [ { "keyId": { "$binary": { "base64": "EjRWeBI0mHYSNBI0VniQEg==", "subType": "04" } }, "path": "encryptedDoubleNoPrecision", "bsonType": "double", "queries": { "queryType": "rangePreview", "contention": { "$numberLong": "0" }, "sparsity": { "$numberLong": "1" } } } ] } } }, "$db": "default" } } } ], "outcome": { "collection": { "data": [ { "_id": 0, "encryptedDoubleNoPrecision": { "$$type": "binData" }, "__safeContent__": [ { "$binary": { "base64": "5nRutVIyq7URVOVtbE4vM01APSIajAVnsShMwjBlzkM=", "subType": "00" } }, { "$binary": { "base64": "6YrBn2ofIw1b5ooakrLOwF41BWrps8OO0H9WH4/rtlE=", "subType": "00" } }, { "$binary": { "base64": "n+XAuFnP8Dov9TnhGFxNx0K/MnVM9WbJ7RouEu0ndO0=", "subType": "00" } }, { "$binary": { "base64": "yRXojuVdn5GQtD97qYlaCL6cOLmZ7Cvcb3wFjkLUIdM=", "subType": "00" } }, { "$binary": { "base64": "DuIkdRPITRs55I4SZmgomAHCIsDQmXRhW8+MOznkzSk=", "subType": "00" } }, { "$binary": { "base64": "SsBk+Et1lTbU+QRPx+xyJ/jMkmfG+QCvQEpip2YYrzA=", "subType": "00" } }, { "$binary": { "base64": "crCIzOd8KhHvvUlX7M1v9bhvU4pLdTc+X2SuqoKU5Ek=", "subType": "00" } }, { "$binary": { "base64": "YOWdCw4UrqnxkAaVjqmC4sKQDMVMHEpFGnlxpxdaU6E=", "subType": "00" } }, { "$binary": { "base64": "M3SShp81Ff8tQ632qKbv9MUcN6wjDaBReI0VXNu6Xh4=", "subType": "00" } }, { "$binary": { "base64": "gzHlSPxpM0hT75kQvWFzGlOxKvDoiKQZOr19V6l2zXI=", "subType": "00" } }, { "$binary": { "base64": "s3JnppOGYw9SL2Q1kMAZs948v2F5PrpXjGei/HioDWs=", "subType": "00" } }, { "$binary": { "base64": "cG6+3Gk/zEH68P/uuuwiAUVCuyJwa1LeV+t29FlPPAo=", "subType": "00" } }, { "$binary": { "base64": "dupdvR3AyJtM+g9NDKiaLVOtGca387JQp8w+V03m7Ig=", "subType": "00" } }, { "$binary": { "base64": "JqEQc5svj2jTvZ6LLA5ivE+kTb/0aRemSEmxk4G7Zrg=", "subType": "00" } }, { "$binary": { "base64": "szcXXXKnob+p3SoM4yED2R920LeJ7cVsclPMFTe4CeI=", "subType": "00" } }, { "$binary": { "base64": "o1QoGVXmuBdHwHm7aCtGMlMVKrjFdYvJXpoq6uhIAZ0=", "subType": "00" } }, { "$binary": { "base64": "Jfm5wPlqqLCJRGQIqRq2NGmpn7s0Vrih2H3YAOoI2YU=", "subType": "00" } }, { "$binary": { "base64": "zMHLb8ARbsYo8Ld05bqnGFf1Usha6EGb8QKwdSAyps0=", "subType": "00" } }, { "$binary": { "base64": "yQdtq9lh5pugL7/i0Bj/PuZUUBUIzf+7wj1rl5y736w=", "subType": "00" } }, { "$binary": { "base64": "wGWVZdO7qIuyDg/BqDgqjgoQ02h5YYgwXQB1oCin2NE=", "subType": "00" } }, { "$binary": { "base64": "by9HMLj6NTEpgztZ5HSN6GxImkXPcaFINYDzgZY33X8=", "subType": "00" } }, { "$binary": { "base64": "tWo0vbasi7bXmn/MsOx13VC1IsWtpx/nYp0uj4iMzdA=", "subType": "00" } }, { "$binary": { "base64": "tQQpndUYd5O87lOtrGjH3wl9VsOK0ray7RMasL90sBM=", "subType": "00" } }, { "$binary": { "base64": "cQjXEDCMsOpKLLf+vlTgIHA+cbSJdzqhbSX9Wvh95aA=", "subType": "00" } }, { "$binary": { "base64": "7yMpU48IxK9SzP2cx3VnTownGEwFmeFofuuFT97SuuY=", "subType": "00" } }, { "$binary": { "base64": "kSOx1kz0CmBgzKQHZlo65ZUY1DIv9A99JRm+Us2y6Ew=", "subType": "00" } }, { "$binary": { "base64": "ubQpdPBe6/xvtr+AcXdfYLSvYCR4ot0tivehkCsupb4=", "subType": "00" } }, { "$binary": { "base64": "xal+iCJ6FTefRQToyoNksc9NCZShyn04NDGi4IYrcoM=", "subType": "00" } }, { "$binary": { "base64": "d7jU4iOK50xHxlkSifcxlZFCM46TSgQzoYivxG3HNLY=", "subType": "00" } }, { "$binary": { "base64": "tJvl2nsBLBVzL3pp6sKWCL4UXeh3q/roYBJjSb74ve0=", "subType": "00" } }, { "$binary": { "base64": "OIUCaKRvIx9t1w6Hxlz1IcQTdPNCfdRNwnnTm10W+X0=", "subType": "00" } }, { "$binary": { "base64": "A9tvzsiElotOUVIB4CqfQp9mAwqvTM35YkmAR170aHA=", "subType": "00" } }, { "$binary": { "base64": "lI8gpK7hpb7c9x4RQugsxMnQay5LZJmwslZdvMx/dcE=", "subType": "00" } }, { "$binary": { "base64": "dNCzh40U0XvdKnSDi3HRQOWQftEsDVqc4uUvsVFGoq8=", "subType": "00" } }, { "$binary": { "base64": "IP+iwEBWBwVVZIdpaMu8k5+soFCz+TZkYn3drKZ9grE=", "subType": "00" } }, { "$binary": { "base64": "pnqyh6e0y5svHkJDShlN9CHV0WvMBE4QbtJpQw5ZCXc=", "subType": "00" } }, { "$binary": { "base64": "elEl42tbVDoRTLjAhZUFEtXiut4b3PVhg/1ZLZSQdtE=", "subType": "00" } }, { "$binary": { "base64": "vHuu2FxwclMHqyE6JBYbTYgbEkB0dqb/JuaxsvfwsmY=", "subType": "00" } }, { "$binary": { "base64": "xTf7NCe3Gf8QpE78HR5OknlLTKfs9J+RN9UZpH6fnso=", "subType": "00" } }, { "$binary": { "base64": "XiWSasRnJAulGR6+LCVD3mwRObXylqYWR9jvpywq12c=", "subType": "00" } }, { "$binary": { "base64": "MZMxEQ5ikx0PG1YFIExv0UnTZogsvgeOEZTpzvBDn4w=", "subType": "00" } }, { "$binary": { "base64": "yZMyMZBDrWbAhvnic7vvIYhmO9m5H2iuv0c8KNZrBzY=", "subType": "00" } }, { "$binary": { "base64": "xxM14hTPY5j0vvcK2C7YAEjzdsfUTFHozHC0hEo1bxI=", "subType": "00" } }, { "$binary": { "base64": "+01rqR1xVwkpGXcstbk1ItJqFVjH6Q8MGxEN3Cm9Y1A=", "subType": "00" } }, { "$binary": { "base64": "xOpLV0Z2VTRJ3iWtnWZcsyjXubTIkYWo31cO+HV1o1k=", "subType": "00" } }, { "$binary": { "base64": "BWUOLqgLBqc5NwxVlSV5H3KFQPXbCp7mdo+jF+8cJqY=", "subType": "00" } }, { "$binary": { "base64": "fuQb1S6xZDGlrEbK+kI23aL53PP1PVNwqICnZNt9Yzg=", "subType": "00" } }, { "$binary": { "base64": "SfscnoibFttahLdPVC4Ee+47ewGFKpDSU7M6HX19bKE=", "subType": "00" } }, { "$binary": { "base64": "rpSW2awybNVeKtat91VFxqbINoTfNhPfQAu+d73Xtf8=", "subType": "00" } }, { "$binary": { "base64": "9M/CP9ccOIIj2LLFmE0GFDO0Ban2wsNalEXfM6+h+1s=", "subType": "00" } }, { "$binary": { "base64": "WrEMG49l1ye4MhXs5ZS9tz8P6h+hDvthIg/2wW9ne1Q=", "subType": "00" } }, { "$binary": { "base64": "ImNhbfeyfH8qIEeA5ic0s3dAQBdzzTBS+CPsNih9vZ0=", "subType": "00" } }, { "$binary": { "base64": "dWP33YDSn04UKJN2ogh2Rui0iW/0q2y18OCDRVcfyoo=", "subType": "00" } }, { "$binary": { "base64": "lYv0isAtfGh6H9tdp3cp2eHU7q2J+uk7QrgcxtK3w7Y=", "subType": "00" } }, { "$binary": { "base64": "VGMoamB/+7zTOYcY/pqJc96xlv2PdW4hwsIAEIslTDQ=", "subType": "00" } }, { "$binary": { "base64": "yNeBWMF7BnD9wVwz2PgJsvWr77QiVvvWUvJF0+fqBug=", "subType": "00" } }, { "$binary": { "base64": "SfpvObJ+tJBXSvqeN7vlOfmhYign635lciYAJIjUtY8=", "subType": "00" } }, { "$binary": { "base64": "dsen4NqjzVGjpjufiTMs3+gqeD09EbnuogPgxrJECwg=", "subType": "00" } }, { "$binary": { "base64": "pxCWVM3sn19NsFEpgHbgLa+PmYlhN3mMiP0Wk8kJhYw=", "subType": "00" } }, { "$binary": { "base64": "q11KNvJszjYIB9n9HcC+N4uz11a3eRj1L3BH9scKMDQ=", "subType": "00" } }, { "$binary": { "base64": "A1PmkgcEToWh1JiVWE6mI5jUu7poxWWuCUt/cgRUUDc=", "subType": "00" } }, { "$binary": { "base64": "qJo3Hu4PJeanL7XEaWXO/n3YsodhZyd+MJOOmB9Kpd8=", "subType": "00" } }, { "$binary": { "base64": "BkBKLO8URFscfRY9Bav/1+L9mLohDgNr/MkZtGiraIs=", "subType": "00" } }, { "$binary": { "base64": "rZq5WA3Hx3xthOyHAJXK//f8pE2qbz7YKu3TIMp9GFY=", "subType": "00" } }, { "$binary": { "base64": "X07a/Lm80p5xd4RFs1dNmw+90tmPDPdGiAKVZkxd4zY=", "subType": "00" } } ] }, { "_id": 1, "encryptedDoubleNoPrecision": { "$$type": "binData" }, "__safeContent__": [ { "$binary": { "base64": "DLCAJs+W2PL2DV5YChCL6dYrQNr+j4p3L7xhVaub4ic=", "subType": "00" } }, { "$binary": { "base64": "HI88j1zrIsFoijIXKybr9mYubNV5uVeODyLHFH4Ueco=", "subType": "00" } }, { "$binary": { "base64": "wXVD/HSbBljko0jJcaxJ1nrzs2+pchLQqYR3vywS8SU=", "subType": "00" } }, { "$binary": { "base64": "KhscCh+tt/pp8lxtKZQSPPUU94RvJYPKG/sjtzIa4Ws=", "subType": "00" } }, { "$binary": { "base64": "RISnuNrTTVNW5HnwCgQJ301pFw8DOcYrAMQIwVwjOkI=", "subType": "00" } }, { "$binary": { "base64": "Ra5zukLh2boua0Bh74qA+mtIoixGXlsNsxiJqHtqdTI=", "subType": "00" } }, { "$binary": { "base64": "eqr0v+NNWXWszi9ni8qH58Q6gw5x737tJvH3lPaNHO4=", "subType": "00" } }, { "$binary": { "base64": "d42QupriWIwGrFAquXNFi0ehEuidIbHLFZtg1Sm2nN8=", "subType": "00" } }, { "$binary": { "base64": "2azRVxaaTIJKcgY2FU012gcyP8Y05cRDpfUaMnCBaQU=", "subType": "00" } }, { "$binary": { "base64": "3nlgkM4K/AAcHesRYYdEu24UGetHodVnVfHzw4yxZBM=", "subType": "00" } }, { "$binary": { "base64": "hqy91FNmAAac2zUaPO6eWFkx0/37rOWGrwXN+fzL0tU=", "subType": "00" } }, { "$binary": { "base64": "akX+fmscSDSF9pB5MPj56iaJPtohr0hfXNk/OPWsGv8=", "subType": "00" } }, { "$binary": { "base64": "1ZvUb10Q7cN4cNLktd5yNjqgtawsYnkbeVBZV6WuY/I=", "subType": "00" } }, { "$binary": { "base64": "otCwtuKiY4hCyXvYzXvo10OcnzZppebo38KsAlq49QM=", "subType": "00" } }, { "$binary": { "base64": "Mty8EscckeT/dhMfrPFyDbLnmMOcYRUQ3mLK4KTu6V8=", "subType": "00" } }, { "$binary": { "base64": "tnvgLLkJINO7csREYu4dEVe1ICrBeu7OP+HdfoX3M2E=", "subType": "00" } }, { "$binary": { "base64": "kOefsHgEVhkJ17UuP7Dxogy6sAQbzf1SFPKCj6XRlrQ=", "subType": "00" } }, { "$binary": { "base64": "F+JQ79xavpaHdJzdhvwyHbzdZJLNHAymc/+67La3gao=", "subType": "00" } }, { "$binary": { "base64": "NCZ9zp5rDRceENuSgAfTLEyKg0YgmXAhK0B8WSj7+Pw=", "subType": "00" } }, { "$binary": { "base64": "wL1CJ7cYR5slx8mHq++uMdjDfkt9037lQTUztEMF56M=", "subType": "00" } }, { "$binary": { "base64": "txefkzTMITZE+XvvRFZ7QcgwDT/7m8jNmxRk4QBaoZI=", "subType": "00" } }, { "$binary": { "base64": "jFunW3v1tSYMyZtQQD28eEy9qqDp4Kqo7gMN29N4bfQ=", "subType": "00" } }, { "$binary": { "base64": "QMO915KUiS3X3R1bU1YoafVM2s0NeHo3EjgTA9PnGwY=", "subType": "00" } }, { "$binary": { "base64": "nwdKJEXdilzvb7494vbuDJ+y6SrfJahza1dYIsHIWVI=", "subType": "00" } }, { "$binary": { "base64": "vpWMX+T/VXXajFo0UbuYjtp0AEzBU0Y+lP+ih2EQ7mg=", "subType": "00" } }, { "$binary": { "base64": "1lmzG0J1DhKDRhhq5y5Buygu4G8eV2X0t7kUY90EohM=", "subType": "00" } }, { "$binary": { "base64": "SiKqpXqO0trwhFvBWK274hMklpCgMhNs/JY84yyn/NE=", "subType": "00" } }, { "$binary": { "base64": "7cPGPYCKPTay+ZR9Gx6oOueduOgaFrSuAXmNDpDHXdI=", "subType": "00" } }, { "$binary": { "base64": "4THEYvAkjs2Fh7FIe5LC45P4i4N0L7ob67UOVbhp6Nk=", "subType": "00" } }, { "$binary": { "base64": "B+UGsChLLZR7iqnt8yq91OgmTgwiUKTJhFxY4NT0O6c=", "subType": "00" } }, { "$binary": { "base64": "X1uYwBCsCg1H+PnKdwtBqXlt0zKEURi8bOM940GcPfk=", "subType": "00" } }, { "$binary": { "base64": "xYOgT5l7shlNXCwHlguovmDkcEnF8dXyYlTyYrgZ8GE=", "subType": "00" } }, { "$binary": { "base64": "vFMTZqV8bh1+gcKzTkXweMddJlgdUnwX0DWzUUaMok4=", "subType": "00" } }, { "$binary": { "base64": "4HI0y9FrtleZxZ7M6INdNhLelrQ2Rv/+ykWCBl+tMC8=", "subType": "00" } }, { "$binary": { "base64": "jpJ0bBE474OUkn1vUiLWumIBtYmwc7J5+LQU/nyeLQc=", "subType": "00" } }, { "$binary": { "base64": "jQTPeXZvdxY/DjtPfYfKUArIDsf0E9MVFy2O26sv1ec=", "subType": "00" } }, { "$binary": { "base64": "QLLto0ExR2ZYMGqlyaMZc/hXFFTlwmgtKbiVq/xJIeI=", "subType": "00" } }, { "$binary": { "base64": "yBJNviU1nchbGbhx6InXCVRXa90sEepz1EwbYuKXu2U=", "subType": "00" } }, { "$binary": { "base64": "jpEf0vHxrPu9gTJutNXSi2g/2Mc4WXFEN7yHonZEb7A=", "subType": "00" } }, { "$binary": { "base64": "E09kLFckMYwNuhggMxmPtwndyvIAx+Vl+b2CV6FP75s=", "subType": "00" } }, { "$binary": { "base64": "N+ue6/cLPb5NssmJCCeo18LlbKPz6r2z20AsnTKRvOo=", "subType": "00" } }, { "$binary": { "base64": "yVQNZP8hhsvNGyDph2QP2qTNdXZTiIEVineKg+Qf33o=", "subType": "00" } }, { "$binary": { "base64": "cSC9uI+9c5S8X+0G7amVyug1p0ZlgBsbEDYYyezBevQ=", "subType": "00" } }, { "$binary": { "base64": "1NpZGjoQzuQtekj80Rifxe9HbE08W07dfwxaFHaVn84=", "subType": "00" } }, { "$binary": { "base64": "5Ghuq/8l11Ug9Uf/RTwf9On3OxOwIXUcb9soiy4J7/w=", "subType": "00" } }, { "$binary": { "base64": "0LWKaEty6ywxLFhDaAqulqfMnYc+tgPfH4apyEeKg80=", "subType": "00" } }, { "$binary": { "base64": "OwSthmCBtt6NIAoAh7aCbj82Yr/+9t8U7WuBQhFT3AQ=", "subType": "00" } }, { "$binary": { "base64": "iYiyg6/1isqbMdvFPIGucu3cNM4NAZNtJhHpGZ4eM+c=", "subType": "00" } }, { "$binary": { "base64": "waBgs8jWuGJPIF5zCRh6OmIyfK5GCBQgTMfmKSR2wyY=", "subType": "00" } }, { "$binary": { "base64": "1Jdtbe2BKJXPU2G9ywOrlODZ/cNYEQlKzAW3aMe1Hy4=", "subType": "00" } }, { "$binary": { "base64": "xaLEnNUS/2ySerBpb9dN/D31t+wYcKekwTfkwtni0Mc=", "subType": "00" } }, { "$binary": { "base64": "bIVBrOhOvr6cL55Tr24+B+CC9MiG7U6K54aAr2IXXuw=", "subType": "00" } }, { "$binary": { "base64": "6Cdq5wroGu2TEFnekuT7LhOpd/K/+PcipIljcHU9QL4=", "subType": "00" } }, { "$binary": { "base64": "K5l64vI4S/pLviLW6Pl0U3iQkI3ge0xg4RAHcEsyKJo=", "subType": "00" } }, { "$binary": { "base64": "bzhuvZ0Ls22yIOX+Hz51eAHlSuDbWR/e0u4EhfdpHbc=", "subType": "00" } }, { "$binary": { "base64": "Qv+fr6uD4o0bZRp69QJCFL6zvn3G82c7L+N1IFzj7H0=", "subType": "00" } }, { "$binary": { "base64": "XAmISMbD3aEyQT+BQEphCKFNa0F0GDKFuhM9cGceKoQ=", "subType": "00" } }, { "$binary": { "base64": "4VLCokntMfm1AogpUnYGvhV7nllWSo3mS3hVESMy+hA=", "subType": "00" } }, { "$binary": { "base64": "xiXNLj/CipEH63Vb5cidi8q9X47EF4f3HtJSOH7mfM8=", "subType": "00" } }, { "$binary": { "base64": "4XlCYfYBjI9XA5zOSgTiEBYcZsdwyXL+f5XtH2xUIOc=", "subType": "00" } }, { "$binary": { "base64": "k6DfQy7ZYJIkEly2B5hjOZznL4NcgMkllZjJLb7yq7w=", "subType": "00" } }, { "$binary": { "base64": "ZzM6gwWesa3lxbZVZthpPFs2s3GV0RZREE2zOMhBRBo=", "subType": "00" } }, { "$binary": { "base64": "US+jeMeeOd7J0wR0efJtq2/18lcO8YFvhT4O3DeaonQ=", "subType": "00" } }, { "$binary": { "base64": "b6iSxiI1FM9SzxuG1bHqGA1i4+3GOi0/SPW00XB4L7o=", "subType": "00" } }, { "$binary": { "base64": "kn3LsxAVkzIZKK9I6fi0Cctr0yjXOYgaQWMCoj4hLpM=", "subType": "00" } } ] } ] } } } ] } fle2v2-Range-DoublePrecision-Aggregate.json000066400000000000000000000503351462766011000371260ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/client-side-encryption/spec/legacy{ "runOn": [ { "minServerVersion": "7.0.0", "topology": [ "replicaset", "sharded", "load-balanced" ] } ], "database_name": "default", "collection_name": "default", "data": [], "encrypted_fields": { "fields": [ { "keyId": { "$binary": { "base64": "EjRWeBI0mHYSNBI0VniQEg==", "subType": "04" } }, "path": "encryptedDoublePrecision", "bsonType": "double", "queries": { "queryType": "rangePreview", "contention": { "$numberLong": "0" }, "sparsity": { "$numberLong": "1" }, "min": { "$numberDouble": "0.0" }, "max": { "$numberDouble": "200.0" }, "precision": { "$numberInt": "2" } } } ] }, "key_vault_data": [ { "_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" } } ], "tests": [ { "description": "FLE2 Range DoublePrecision. Aggregate.", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "local": { "key": { "$binary": { "base64": "Mng0NCt4ZHVUYUJCa1kxNkVyNUR1QURhZ2h2UzR2d2RrZzh0cFBwM3R6NmdWMDFBMUN3YkQ5aXRRMkhGRGdQV09wOGVNYUMxT2k3NjZKelhaQmRCZGJkTXVyZG9uSjFk", "subType": "00" } } } } } }, "operations": [ { "name": "insertOne", "arguments": { "document": { "_id": 0, "encryptedDoublePrecision": { "$numberDouble": "0" } } } }, { "name": "insertOne", "arguments": { "document": { "_id": 1, "encryptedDoublePrecision": { "$numberDouble": "1" } } } }, { "name": "aggregate", "arguments": { "pipeline": [ { "$match": { "encryptedDoublePrecision": { "$gt": { "$numberDouble": "0" } } } } ] }, "result": [ { "_id": 1, "encryptedDoublePrecision": { "$numberDouble": "1" } } ] } ], "expectations": [ { "command_started_event": { "command": { "listCollections": 1, "filter": { "name": "default" } }, "command_name": "listCollections" } }, { "command_started_event": { "command": { "find": "datakeys", "filter": { "$or": [ { "_id": { "$in": [ { "$binary": { "base64": "EjRWeBI0mHYSNBI0VniQEg==", "subType": "04" } } ] } }, { "keyAltNames": { "$in": [] } } ] }, "$db": "keyvault", "readConcern": { "level": "majority" } }, "command_name": "find" } }, { "command_started_event": { "command": { "insert": "default", "documents": [ { "_id": 0, "encryptedDoublePrecision": { "$$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": "encryptedDoublePrecision", "bsonType": "double", "queries": { "queryType": "rangePreview", "contention": { "$numberLong": "0" }, "sparsity": { "$numberLong": "1" }, "min": { "$numberDouble": "0.0" }, "max": { "$numberDouble": "200.0" }, "precision": { "$numberInt": "2" } } } ] } } } }, "command_name": "insert" } }, { "command_started_event": { "command": { "insert": "default", "documents": [ { "_id": 1, "encryptedDoublePrecision": { "$$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": "encryptedDoublePrecision", "bsonType": "double", "queries": { "queryType": "rangePreview", "contention": { "$numberLong": "0" }, "sparsity": { "$numberLong": "1" }, "min": { "$numberDouble": "0.0" }, "max": { "$numberDouble": "200.0" }, "precision": { "$numberInt": "2" } } } ] } } } }, "command_name": "insert" } }, { "command_started_event": { "command": { "aggregate": "default", "pipeline": [ { "$match": { "encryptedDoublePrecision": { "$gt": { "$binary": { "base64": "DdIJAAADcGF5bG9hZACiCQAABGcAjgkAAAMwAH0AAAAFZAAgAAAAAHdJ2Vnb4MMzqVYVssjSdDy8XU4GVzMTfGifGETgQ2mYBXMAIAAAAAD7cFfKJGIXo6PjyeX2ria02CckW7dWFDoY/3FyBdm1NQVsACAAAAAAhEPSNv4M023A3hzNFuy83+hIKuZ2mKRY954N++aEOBUAAzEAfQAAAAVkACAAAAAAlmvfDrZoydUet4eCVMq7z6a58Ea+1HLJOWxN5lNcrWEFcwAgAAAAAEBo5AWZyC41b9ayjWNQSL4iYEAIwR/JG+ssN8bdoK9RBWwAIAAAAACEndE0SLxFSElOrNnqeX0EPmgDio3udZjVREy4JLS3sQADMgB9AAAABWQAIAAAAABbiLaoxAA6rinMJw1hC8ZUiq6UU1AQaPFn/py/Y06WuQVzACAAAAAAhtDasFkvYE7SCNu1je/hxdE9TJtAvvH3NtdEbKzNbCUFbAAgAAAAAIGepU1RSCF8sWODHEpKglsoqw3VBBH4a/URGxgGzbq2AAMzAH0AAAAFZAAgAAAAALORWwSr+tYNxcil2KIGSbNhTHvcPbdj+rLVQNx21S/KBXMAIAAAAAD6diZBkPEJ1cQy06LAxdbNK8Nlxbb44fH4Wk3Y3260nQVsACAAAAAA1eYAZBFHlDiaDAljWi8blGQ2nvvZa5AO5doeo0SFZsgAAzQAfQAAAAVkACAAAAAAG5XMK96PjClNlUvg82j4pMY1YxsznZfj4uNweD394FoFcwAgAAAAAKHgQLdGJHkrfFg9nB93Ac+3VgBw6aU44MTkKIQ91dZoBWwAIAAAAAAPxXmi+SDJ+40A0KdwfRczexlZQrHjIA+D3oUB0EY9tAADNQB9AAAABWQAIAAAAAA6M++b9I0YFemmWBAWAE3glu2Ah3Ta1FBxAQEIWS0toAVzACAAAAAANXYTqPf1Y6X3Ns6YQIX0C3FKCyWUo+Kk+fNcQvc0WSoFbAAgAAAAAA+uJUw1ICYgyeygSRe206VTWVtUnhdci3iHbyP5YtEVAAM2AH0AAAAFZAAgAAAAAKl8bV1riH/uyJ+X0HHd3+18k2cJl2dQFXCdoagutFcaBXMAIAAAAABm8F2Ew9f0VOABdcF+lP0Bi+zWvEUPniWgrxPq/Sx3uwVsACAAAAAAJfFErjZ6BPhsw5LjJLqNtKDLJ4zV0eIZppQpd9b0wZoAAzcAfQAAAAVkACAAAAAAsYZD8JEP6kYsPncFnNZwJxhu4YtUTKPNcjHtv67H+rYFcwAgAAAAAI4LqZcRkvbs/2F62Flu0pixNcor4WmBD0DHGaf039wLBWwAIAAAAAD4wUR3xd9lKltcqqo8LYvdMQWzCRobkV/ppKB/yn5dUgADOAB9AAAABWQAIAAAAAC0vdAi+dmoIXvZ5LqUqvyKV9/tHqSI2SWiSJO5pTnA2wVzACAAAAAAS2qvf9fvfVUH5WtsVxjxmskpGjYTQV34LwvQQw1y9wIFbAAgAAAAAE0+FKuK7HxbypvCeEJzMTcjOWE0ScYOlTBMUNlIv55hAAM5AH0AAAAFZAAgAAAAAH31lb/srBcrOXkzddCwAnclsR5/3QijEVgECs2JjOWBBXMAIAAAAABg7+prDT73YcCvLE5QbuIrqGcjLc5pQD2Miq0d29yrxgVsACAAAAAAetRiPwDSFWBzpWSWkOKWM6fKStRJ8SyObnpc79ux8p0AAzEwAH0AAAAFZAAgAAAAAOK8brUuc2onBNDRtfYMR736dHj4dQqXod8JG7tAMTsDBXMAIAAAAAAW6SrGAL6Bx0s7ZlsYULFfOAiYIGhEWu6md3r+Rk40awVsACAAAAAAIHYXP8RLcCboUmHN3+OlnEw1DxaLSnbTB9PdF228fFAAAzExAH0AAAAFZAAgAAAAAFdthRhe2Q8CvxGIhjTJZv0Lk97GkHciTPxZ/mckLoNaBXMAIAAAAAAqOxsAr23LOVB0DIHbPf9UDJJRFXY2YoKbjhRqw5psbQVsACAAAAAA0G2GD8ZQjDBntjLpW4rqwKRS6HiUjL03g1N6chANozcAAzEyAH0AAAAFZAAgAAAAAMWymwwbvIeMqmnKWWifUqoCxOsdpnonM2qdLPyjqJO/BXMAIAAAAAB6IDmmpUhBD2zpRj8/y/kmOSXcjuIU14sNh6GKSsg2uwVsACAAAAAAWMFPNOk3EMSQDS9JGPSMIQP0oNGVugxXKKUrIPPlhHgAAzEzAH0AAAAFZAAgAAAAAPcLmtq+V1e+MRlZ7NHq1+mrRVBQje5zj685ZvdsfKvSBXMAIAAAAABdHz/3w2k5km97QN9m7oLFYJaVJneNlMboIlz5yUASQAVsACAAAAAAWbp8JVJnx8fEVAJFa7WMfMa7wXeP5M3C8MX20J/i9n0AAzE0AH0AAAAFZAAgAAAAAJaRYmo8zqI2BEUzdSwp4tVRpPmVWsfydkYN3UHh6TMuBXMAIAAAAAAeD6mDnQeLlbC9i0sVgE8+RH6y+e94OJQ0tJ0PvblVSgVsACAAAAAAWp4jvretbDEsqEMzP/WLTnwOiJwCtfrCiB6m8k+yEMoAAzE1AH0AAAAFZAAgAAAAAAZZ538coNPwyRjhEwr5P8Xw32oWOJF+R+nfCGgy2qO3BXMAIAAAAACOPLnJlKwGNPDBReRKnHfteq0wFb3ezhrc7BVXs8RUHwVsACAAAAAA+lGesNk3+SyB/60rSvdQ2aN2vfJPR7llJVhufGTNhHkAAzE2AH0AAAAFZAAgAAAAAFH9l9GGA1I52atJV5jNUf1lx8jBjoEoVoME97v5GFJiBXMAIAAAAAC1qH3Kd78Dr9NGbw7y9D/XYBwv5h1LLO8la5OU7g8UkQVsACAAAAAArZ6atJCYrVfHB8dSNPOFf6nnDADBMJcIEj8ljPvxHp8AAzE3AH0AAAAFZAAgAAAAADtbVEI2tdkrowEMdkacD2w0Y3T3Ofi7PH6HmA6sP0c/BXMAIAAAAADuBSROnZHA+NgUPH8d0LnWFiDsM2bY8bzjC1+elSsIygVsACAAAAAAR0G2m+uANoWknkr/NerFcG+fECVxNIs0cqbY1t/U/0MAAzE4AH0AAAAFZAAgAAAAAAh3WpeMVlikPFYj9hLj+fmIqVt6omCSF75W3TPExyWpBXMAIAAAAAAsQkRmwqeVj2gGE03orb6PtrIzDt6dDU3hgSQi8E2wKgVsACAAAAAA3GHaRE2RAcaBRd8VzmYzWeBD2Gmy91eTK1k8YdWObZcAABJjbQAAAAAAAAAAAAAQcGF5bG9hZElkAAAAAAAQZmlyc3RPcGVyYXRvcgABAAAAAA==", "subType": "06" } } } } } ], "cursor": {}, "encryptionInformation": { "type": 1, "schema": { "default.default": { "escCollection": "enxcol_.default.esc", "ecocCollection": "enxcol_.default.ecoc", "fields": [ { "keyId": { "$binary": { "base64": "EjRWeBI0mHYSNBI0VniQEg==", "subType": "04" } }, "path": "encryptedDoublePrecision", "bsonType": "double", "queries": { "queryType": "rangePreview", "contention": { "$numberLong": "0" }, "sparsity": { "$numberLong": "1" }, "min": { "$numberDouble": "0.0" }, "max": { "$numberDouble": "200.0" }, "precision": { "$numberInt": "2" } } } ] } } } }, "command_name": "aggregate" } } ], "outcome": { "collection": { "data": [ { "_id": 0, "encryptedDoublePrecision": { "$$type": "binData" }, "__safeContent__": [ { "$binary": { "base64": "5nRutVIyq7URVOVtbE4vM01APSIajAVnsShMwjBlzkM=", "subType": "00" } }, { "$binary": { "base64": "Dri0CXmL78L2DOgk9w0DwxHOMGMzih7m6l59vgy+WWo=", "subType": "00" } }, { "$binary": { "base64": "x7GR49EN0t3WXQDihkrbonK7qNIBYC87tpL/XEUyIYc=", "subType": "00" } }, { "$binary": { "base64": "JfYUqWF+OoGjiYkRI4L5iPlF+T1Eleul7Fki22jp4Qc=", "subType": "00" } }, { "$binary": { "base64": "q1RyGfIgsaQHoZFRw+DD28V26rN5hweApPLwExncvT8=", "subType": "00" } }, { "$binary": { "base64": "L2PFeKGvLS6C+DLudR6fGlBq3ERPvjWvRyNRIA2HVb0=", "subType": "00" } }, { "$binary": { "base64": "CWxaNqL3iP1yCixDkcmf9bmW3E5VeN8TJkg1jJe528s=", "subType": "00" } }, { "$binary": { "base64": "+vC6araOEo+fpW7PSIP40/EnzBCj1d2N10Jr3rrXJJM=", "subType": "00" } }, { "$binary": { "base64": "6SV63Mf51Z6A6p2X3rCnJKCu6ku3Oeb45mBYbz+IoAo=", "subType": "00" } }, { "$binary": { "base64": "RjBYT2h3ZAoHxhf8DU6/dFbDkEBZp0IxREcsRTu2MXs=", "subType": "00" } }, { "$binary": { "base64": "b7d8mRzD1kI1tdc7uNL+YAUonJ6pODLsRLkArfEKSkM=", "subType": "00" } }, { "$binary": { "base64": "Xg8C1/A0KJaXOw4i+26Rv03/CydaaunOzXh0CIT+gn8=", "subType": "00" } }, { "$binary": { "base64": "UoKUDw2wJYToUCcFaIs03YQSTksYR0MIOTJllwODqKc=", "subType": "00" } }, { "$binary": { "base64": "c/5cwAT0C5jber2xlJnWD3a5tVDy0nRtr5HG02hoFOY=", "subType": "00" } }, { "$binary": { "base64": "wSUrRXavAGaajNeqC5mEUH1K67oYl5Wy9RNIzKjwLAM=", "subType": "00" } }, { "$binary": { "base64": "6vrp4wWDtHEgHWR99I70WVDzevg1Fk/Pw5U8gUDa0OU=", "subType": "00" } } ] }, { "_id": 1, "encryptedDoublePrecision": { "$$type": "binData" }, "__safeContent__": [ { "$binary": { "base64": "bE1vqWj3KNyM7cCYUv/cnYm8BPaUL3eMp5syTHq6NF4=", "subType": "00" } }, { "$binary": { "base64": "mVZb+Ra0EYjQ4Zrh9X//E2T8MRj7NMqm5GUJXhRrBEI=", "subType": "00" } }, { "$binary": { "base64": "FA74j21GUEJb1DJBOpR9nVnjaDZnd8yAQNuaW9Qi26g=", "subType": "00" } }, { "$binary": { "base64": "kJv//KVkbrobIBf+QeWC5jxn20mx/P0R1N6aCSMgKM8=", "subType": "00" } }, { "$binary": { "base64": "zB+Whi9IUUGxfLEe+lGuIzLX4LFbIhaIAm5lRk65QTc=", "subType": "00" } }, { "$binary": { "base64": "ybO1QU3CgvhO8JgRXH+HxKszWcpl5aGDYYVa75fHa1g=", "subType": "00" } }, { "$binary": { "base64": "X3Y3eSAbbMg//JgiHHiFpYOpV61t8kkDexI+CQyitH4=", "subType": "00" } }, { "$binary": { "base64": "SlNHXyqVFGDPrX/2ppwog6l4pwj3PKda2TkZbqgfSfA=", "subType": "00" } }, { "$binary": { "base64": "McjV8xwTF3xI7863DYOBdyvIv6UpzThl6v9vBRk05bI=", "subType": "00" } }, { "$binary": { "base64": "MgwakFvPyBlwqFTbhWUF79URJQWFoJTGotlEVSPPUsQ=", "subType": "00" } }, { "$binary": { "base64": "DyBERpMSD5lEM5Nhpcn4WGgxgn/mkUVJp+PYSLX5jsE=", "subType": "00" } }, { "$binary": { "base64": "I43iazc0xj1WVbYB/V+uTL/tughN1bBlxh1iypBnNsA=", "subType": "00" } }, { "$binary": { "base64": "wjOBa/ATMuOywFmuPgC0GF/oeLqu0Z7eK5udzkTPbis=", "subType": "00" } }, { "$binary": { "base64": "gRQVwiR+m+0Vg8ZDXqrQQcVnTyobwCXNaA4BCJVXtMc=", "subType": "00" } }, { "$binary": { "base64": "WUZ6huwx0ZbLb0R00uiC9FOJzsUocUN8qE5+YRenkvQ=", "subType": "00" } }, { "$binary": { "base64": "7s79aKEuPgQcS/YPOOVcYNZvHIo7FFsWtFCrnDKXefA=", "subType": "00" } } ] } ] } } } ] } fle2v2-Range-DoublePrecision-Correctness.json000066400000000000000000001161041462766011000375270ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/client-side-encryption/spec/legacy{ "runOn": [ { "minServerVersion": "7.0.0", "topology": [ "replicaset", "sharded", "load-balanced" ] } ], "database_name": "default", "collection_name": "default", "data": [], "encrypted_fields": { "fields": [ { "keyId": { "$binary": { "base64": "EjRWeBI0mHYSNBI0VniQEg==", "subType": "04" } }, "path": "encryptedDoublePrecision", "bsonType": "double", "queries": { "queryType": "rangePreview", "contention": { "$numberLong": "0" }, "sparsity": { "$numberLong": "1" }, "min": { "$numberDouble": "0.0" }, "max": { "$numberDouble": "200.0" }, "precision": { "$numberInt": "2" } } } ] }, "key_vault_data": [ { "_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" } } ], "tests": [ { "description": "Find with $gt", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "local": { "key": { "$binary": { "base64": "Mng0NCt4ZHVUYUJCa1kxNkVyNUR1QURhZ2h2UzR2d2RrZzh0cFBwM3R6NmdWMDFBMUN3YkQ5aXRRMkhGRGdQV09wOGVNYUMxT2k3NjZKelhaQmRCZGJkTXVyZG9uSjFk", "subType": "00" } } } } } }, "operations": [ { "name": "insertOne", "arguments": { "document": { "_id": 0, "encryptedDoublePrecision": { "$numberDouble": "0.0" } } } }, { "name": "insertOne", "arguments": { "document": { "_id": 1, "encryptedDoublePrecision": { "$numberDouble": "1.0" } } } }, { "name": "find", "arguments": { "filter": { "encryptedDoublePrecision": { "$gt": { "$numberDouble": "0.0" } } } }, "result": [ { "_id": 1, "encryptedDoublePrecision": { "$numberDouble": "1.0" } } ] } ] }, { "description": "Find with $gte", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "local": { "key": { "$binary": { "base64": "Mng0NCt4ZHVUYUJCa1kxNkVyNUR1QURhZ2h2UzR2d2RrZzh0cFBwM3R6NmdWMDFBMUN3YkQ5aXRRMkhGRGdQV09wOGVNYUMxT2k3NjZKelhaQmRCZGJkTXVyZG9uSjFk", "subType": "00" } } } } } }, "operations": [ { "name": "insertOne", "arguments": { "document": { "_id": 0, "encryptedDoublePrecision": { "$numberDouble": "0.0" } } } }, { "name": "insertOne", "arguments": { "document": { "_id": 1, "encryptedDoublePrecision": { "$numberDouble": "1.0" } } } }, { "name": "find", "arguments": { "filter": { "encryptedDoublePrecision": { "$gte": { "$numberDouble": "0.0" } } }, "sort": { "_id": 1 } }, "result": [ { "_id": 0, "encryptedDoublePrecision": { "$numberDouble": "0.0" } }, { "_id": 1, "encryptedDoublePrecision": { "$numberDouble": "1.0" } } ] } ] }, { "description": "Find with $gt with no results", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "local": { "key": { "$binary": { "base64": "Mng0NCt4ZHVUYUJCa1kxNkVyNUR1QURhZ2h2UzR2d2RrZzh0cFBwM3R6NmdWMDFBMUN3YkQ5aXRRMkhGRGdQV09wOGVNYUMxT2k3NjZKelhaQmRCZGJkTXVyZG9uSjFk", "subType": "00" } } } } } }, "operations": [ { "name": "insertOne", "arguments": { "document": { "_id": 0, "encryptedDoublePrecision": { "$numberDouble": "0.0" } } } }, { "name": "insertOne", "arguments": { "document": { "_id": 1, "encryptedDoublePrecision": { "$numberDouble": "1.0" } } } }, { "name": "find", "arguments": { "filter": { "encryptedDoublePrecision": { "$gt": { "$numberDouble": "1.0" } } } }, "result": [] } ] }, { "description": "Find with $lt", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "local": { "key": { "$binary": { "base64": "Mng0NCt4ZHVUYUJCa1kxNkVyNUR1QURhZ2h2UzR2d2RrZzh0cFBwM3R6NmdWMDFBMUN3YkQ5aXRRMkhGRGdQV09wOGVNYUMxT2k3NjZKelhaQmRCZGJkTXVyZG9uSjFk", "subType": "00" } } } } } }, "operations": [ { "name": "insertOne", "arguments": { "document": { "_id": 0, "encryptedDoublePrecision": { "$numberDouble": "0.0" } } } }, { "name": "insertOne", "arguments": { "document": { "_id": 1, "encryptedDoublePrecision": { "$numberDouble": "1.0" } } } }, { "name": "find", "arguments": { "filter": { "encryptedDoublePrecision": { "$lt": { "$numberDouble": "1.0" } } } }, "result": [ { "_id": 0, "encryptedDoublePrecision": { "$numberDouble": "0.0" } } ] } ] }, { "description": "Find with $lte", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "local": { "key": { "$binary": { "base64": "Mng0NCt4ZHVUYUJCa1kxNkVyNUR1QURhZ2h2UzR2d2RrZzh0cFBwM3R6NmdWMDFBMUN3YkQ5aXRRMkhGRGdQV09wOGVNYUMxT2k3NjZKelhaQmRCZGJkTXVyZG9uSjFk", "subType": "00" } } } } } }, "operations": [ { "name": "insertOne", "arguments": { "document": { "_id": 0, "encryptedDoublePrecision": { "$numberDouble": "0.0" } } } }, { "name": "insertOne", "arguments": { "document": { "_id": 1, "encryptedDoublePrecision": { "$numberDouble": "1.0" } } } }, { "name": "find", "arguments": { "filter": { "encryptedDoublePrecision": { "$lte": { "$numberDouble": "1.0" } } }, "sort": { "_id": 1 } }, "result": [ { "_id": 0, "encryptedDoublePrecision": { "$numberDouble": "0.0" } }, { "_id": 1, "encryptedDoublePrecision": { "$numberDouble": "1.0" } } ] } ] }, { "description": "Find with $lt below min", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "local": { "key": { "$binary": { "base64": "Mng0NCt4ZHVUYUJCa1kxNkVyNUR1QURhZ2h2UzR2d2RrZzh0cFBwM3R6NmdWMDFBMUN3YkQ5aXRRMkhGRGdQV09wOGVNYUMxT2k3NjZKelhaQmRCZGJkTXVyZG9uSjFk", "subType": "00" } } } } } }, "operations": [ { "name": "insertOne", "arguments": { "document": { "_id": 0, "encryptedDoublePrecision": { "$numberDouble": "0.0" } } } }, { "name": "insertOne", "arguments": { "document": { "_id": 1, "encryptedDoublePrecision": { "$numberDouble": "1.0" } } } }, { "name": "find", "arguments": { "filter": { "encryptedDoublePrecision": { "$lt": { "$numberDouble": "0.0" } } } }, "result": { "errorContains": "must be greater than the range minimum" } } ] }, { "description": "Find with $gt above max", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "local": { "key": { "$binary": { "base64": "Mng0NCt4ZHVUYUJCa1kxNkVyNUR1QURhZ2h2UzR2d2RrZzh0cFBwM3R6NmdWMDFBMUN3YkQ5aXRRMkhGRGdQV09wOGVNYUMxT2k3NjZKelhaQmRCZGJkTXVyZG9uSjFk", "subType": "00" } } } } } }, "operations": [ { "name": "insertOne", "arguments": { "document": { "_id": 0, "encryptedDoublePrecision": { "$numberDouble": "0.0" } } } }, { "name": "insertOne", "arguments": { "document": { "_id": 1, "encryptedDoublePrecision": { "$numberDouble": "1.0" } } } }, { "name": "find", "arguments": { "filter": { "encryptedDoublePrecision": { "$gt": { "$numberDouble": "200.0" } } } }, "result": { "errorContains": "must be less than the range max" } } ] }, { "description": "Find with $gt and $lt", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "local": { "key": { "$binary": { "base64": "Mng0NCt4ZHVUYUJCa1kxNkVyNUR1QURhZ2h2UzR2d2RrZzh0cFBwM3R6NmdWMDFBMUN3YkQ5aXRRMkhGRGdQV09wOGVNYUMxT2k3NjZKelhaQmRCZGJkTXVyZG9uSjFk", "subType": "00" } } } } } }, "operations": [ { "name": "insertOne", "arguments": { "document": { "_id": 0, "encryptedDoublePrecision": { "$numberDouble": "0.0" } } } }, { "name": "insertOne", "arguments": { "document": { "_id": 1, "encryptedDoublePrecision": { "$numberDouble": "1.0" } } } }, { "name": "find", "arguments": { "filter": { "encryptedDoublePrecision": { "$gt": { "$numberDouble": "0.0" }, "$lt": { "$numberDouble": "2.0" } } } }, "result": [ { "_id": 1, "encryptedDoublePrecision": { "$numberDouble": "1.0" } } ] } ] }, { "description": "Find with equality", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "local": { "key": { "$binary": { "base64": "Mng0NCt4ZHVUYUJCa1kxNkVyNUR1QURhZ2h2UzR2d2RrZzh0cFBwM3R6NmdWMDFBMUN3YkQ5aXRRMkhGRGdQV09wOGVNYUMxT2k3NjZKelhaQmRCZGJkTXVyZG9uSjFk", "subType": "00" } } } } } }, "operations": [ { "name": "insertOne", "arguments": { "document": { "_id": 0, "encryptedDoublePrecision": { "$numberDouble": "0.0" } } } }, { "name": "insertOne", "arguments": { "document": { "_id": 1, "encryptedDoublePrecision": { "$numberDouble": "1.0" } } } }, { "name": "find", "arguments": { "filter": { "encryptedDoublePrecision": { "$numberDouble": "0.0" } } }, "result": [ { "_id": 0, "encryptedDoublePrecision": { "$numberDouble": "0.0" } } ] }, { "name": "find", "arguments": { "filter": { "encryptedDoublePrecision": { "$numberDouble": "1.0" } } }, "result": [ { "_id": 1, "encryptedDoublePrecision": { "$numberDouble": "1.0" } } ] } ] }, { "description": "Find with full range", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "local": { "key": { "$binary": { "base64": "Mng0NCt4ZHVUYUJCa1kxNkVyNUR1QURhZ2h2UzR2d2RrZzh0cFBwM3R6NmdWMDFBMUN3YkQ5aXRRMkhGRGdQV09wOGVNYUMxT2k3NjZKelhaQmRCZGJkTXVyZG9uSjFk", "subType": "00" } } } } } }, "operations": [ { "name": "insertOne", "arguments": { "document": { "_id": 0, "encryptedDoublePrecision": { "$numberDouble": "0.0" } } } }, { "name": "insertOne", "arguments": { "document": { "_id": 1, "encryptedDoublePrecision": { "$numberDouble": "1.0" } } } }, { "name": "find", "arguments": { "filter": { "encryptedDoublePrecision": { "$gte": { "$numberDouble": "0.0" }, "$lte": { "$numberDouble": "200.0" } } }, "sort": { "_id": 1 } }, "result": [ { "_id": 0, "encryptedDoublePrecision": { "$numberDouble": "0.0" } }, { "_id": 1, "encryptedDoublePrecision": { "$numberDouble": "1.0" } } ] } ] }, { "description": "Find with $in", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "local": { "key": { "$binary": { "base64": "Mng0NCt4ZHVUYUJCa1kxNkVyNUR1QURhZ2h2UzR2d2RrZzh0cFBwM3R6NmdWMDFBMUN3YkQ5aXRRMkhGRGdQV09wOGVNYUMxT2k3NjZKelhaQmRCZGJkTXVyZG9uSjFk", "subType": "00" } } } } } }, "operations": [ { "name": "insertOne", "arguments": { "document": { "_id": 0, "encryptedDoublePrecision": { "$numberDouble": "0.0" } } } }, { "name": "insertOne", "arguments": { "document": { "_id": 1, "encryptedDoublePrecision": { "$numberDouble": "1.0" } } } }, { "name": "find", "arguments": { "filter": { "encryptedDoublePrecision": { "$in": [ { "$numberDouble": "0.0" } ] } } }, "result": [ { "_id": 0, "encryptedDoublePrecision": { "$numberDouble": "0.0" } } ] } ] }, { "description": "Insert out of range", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "local": { "key": { "$binary": { "base64": "Mng0NCt4ZHVUYUJCa1kxNkVyNUR1QURhZ2h2UzR2d2RrZzh0cFBwM3R6NmdWMDFBMUN3YkQ5aXRRMkhGRGdQV09wOGVNYUMxT2k3NjZKelhaQmRCZGJkTXVyZG9uSjFk", "subType": "00" } } } } } }, "operations": [ { "name": "insertOne", "arguments": { "document": { "_id": 0, "encryptedDoublePrecision": { "$numberDouble": "-1" } } }, "result": { "errorContains": "value must be greater than or equal to the minimum value" } } ] }, { "description": "Insert min and max", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "local": { "key": { "$binary": { "base64": "Mng0NCt4ZHVUYUJCa1kxNkVyNUR1QURhZ2h2UzR2d2RrZzh0cFBwM3R6NmdWMDFBMUN3YkQ5aXRRMkhGRGdQV09wOGVNYUMxT2k3NjZKelhaQmRCZGJkTXVyZG9uSjFk", "subType": "00" } } } } } }, "operations": [ { "name": "insertOne", "arguments": { "document": { "_id": 0, "encryptedDoublePrecision": { "$numberDouble": "0.0" } } } }, { "name": "insertOne", "arguments": { "document": { "_id": 200, "encryptedDoublePrecision": { "$numberDouble": "200.0" } } } }, { "name": "find", "arguments": { "filter": {}, "sort": { "_id": 1 } }, "result": [ { "_id": 0, "encryptedDoublePrecision": { "$numberDouble": "0.0" } }, { "_id": 200, "encryptedDoublePrecision": { "$numberDouble": "200.0" } } ] } ] }, { "description": "Aggregate with $gte", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "local": { "key": { "$binary": { "base64": "Mng0NCt4ZHVUYUJCa1kxNkVyNUR1QURhZ2h2UzR2d2RrZzh0cFBwM3R6NmdWMDFBMUN3YkQ5aXRRMkhGRGdQV09wOGVNYUMxT2k3NjZKelhaQmRCZGJkTXVyZG9uSjFk", "subType": "00" } } } } } }, "operations": [ { "name": "insertOne", "arguments": { "document": { "_id": 0, "encryptedDoublePrecision": { "$numberDouble": "0.0" } } } }, { "name": "insertOne", "arguments": { "document": { "_id": 1, "encryptedDoublePrecision": { "$numberDouble": "1.0" } } } }, { "name": "aggregate", "arguments": { "pipeline": [ { "$match": { "encryptedDoublePrecision": { "$gte": { "$numberDouble": "0.0" } } } }, { "$sort": { "_id": 1 } } ] }, "result": [ { "_id": 0, "encryptedDoublePrecision": { "$numberDouble": "0.0" } }, { "_id": 1, "encryptedDoublePrecision": { "$numberDouble": "1.0" } } ] } ] }, { "description": "Aggregate with $gt with no results", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "local": { "key": { "$binary": { "base64": "Mng0NCt4ZHVUYUJCa1kxNkVyNUR1QURhZ2h2UzR2d2RrZzh0cFBwM3R6NmdWMDFBMUN3YkQ5aXRRMkhGRGdQV09wOGVNYUMxT2k3NjZKelhaQmRCZGJkTXVyZG9uSjFk", "subType": "00" } } } } } }, "operations": [ { "name": "insertOne", "arguments": { "document": { "_id": 0, "encryptedDoublePrecision": { "$numberDouble": "0.0" } } } }, { "name": "insertOne", "arguments": { "document": { "_id": 1, "encryptedDoublePrecision": { "$numberDouble": "1.0" } } } }, { "name": "aggregate", "arguments": { "pipeline": [ { "$match": { "encryptedDoublePrecision": { "$gt": { "$numberDouble": "1.0" } } } } ] }, "result": [] } ] }, { "description": "Aggregate with $lt", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "local": { "key": { "$binary": { "base64": "Mng0NCt4ZHVUYUJCa1kxNkVyNUR1QURhZ2h2UzR2d2RrZzh0cFBwM3R6NmdWMDFBMUN3YkQ5aXRRMkhGRGdQV09wOGVNYUMxT2k3NjZKelhaQmRCZGJkTXVyZG9uSjFk", "subType": "00" } } } } } }, "operations": [ { "name": "insertOne", "arguments": { "document": { "_id": 0, "encryptedDoublePrecision": { "$numberDouble": "0.0" } } } }, { "name": "insertOne", "arguments": { "document": { "_id": 1, "encryptedDoublePrecision": { "$numberDouble": "1.0" } } } }, { "name": "aggregate", "arguments": { "pipeline": [ { "$match": { "encryptedDoublePrecision": { "$lt": { "$numberDouble": "1.0" } } } } ] }, "result": [ { "_id": 0, "encryptedDoublePrecision": { "$numberDouble": "0.0" } } ] } ] }, { "description": "Aggregate with $lte", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "local": { "key": { "$binary": { "base64": "Mng0NCt4ZHVUYUJCa1kxNkVyNUR1QURhZ2h2UzR2d2RrZzh0cFBwM3R6NmdWMDFBMUN3YkQ5aXRRMkhGRGdQV09wOGVNYUMxT2k3NjZKelhaQmRCZGJkTXVyZG9uSjFk", "subType": "00" } } } } } }, "operations": [ { "name": "insertOne", "arguments": { "document": { "_id": 0, "encryptedDoublePrecision": { "$numberDouble": "0.0" } } } }, { "name": "insertOne", "arguments": { "document": { "_id": 1, "encryptedDoublePrecision": { "$numberDouble": "1.0" } } } }, { "name": "aggregate", "arguments": { "pipeline": [ { "$match": { "encryptedDoublePrecision": { "$lte": { "$numberDouble": "1.0" } } } }, { "$sort": { "_id": 1 } } ] }, "result": [ { "_id": 0, "encryptedDoublePrecision": { "$numberDouble": "0.0" } }, { "_id": 1, "encryptedDoublePrecision": { "$numberDouble": "1.0" } } ] } ] }, { "description": "Aggregate with $lt below min", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "local": { "key": { "$binary": { "base64": "Mng0NCt4ZHVUYUJCa1kxNkVyNUR1QURhZ2h2UzR2d2RrZzh0cFBwM3R6NmdWMDFBMUN3YkQ5aXRRMkhGRGdQV09wOGVNYUMxT2k3NjZKelhaQmRCZGJkTXVyZG9uSjFk", "subType": "00" } } } } } }, "operations": [ { "name": "insertOne", "arguments": { "document": { "_id": 0, "encryptedDoublePrecision": { "$numberDouble": "0.0" } } } }, { "name": "insertOne", "arguments": { "document": { "_id": 1, "encryptedDoublePrecision": { "$numberDouble": "1.0" } } } }, { "name": "aggregate", "arguments": { "pipeline": [ { "$match": { "encryptedDoublePrecision": { "$lt": { "$numberDouble": "0.0" } } } } ] }, "result": { "errorContains": "must be greater than the range minimum" } } ] }, { "description": "Aggregate with $gt above max", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "local": { "key": { "$binary": { "base64": "Mng0NCt4ZHVUYUJCa1kxNkVyNUR1QURhZ2h2UzR2d2RrZzh0cFBwM3R6NmdWMDFBMUN3YkQ5aXRRMkhGRGdQV09wOGVNYUMxT2k3NjZKelhaQmRCZGJkTXVyZG9uSjFk", "subType": "00" } } } } } }, "operations": [ { "name": "insertOne", "arguments": { "document": { "_id": 0, "encryptedDoublePrecision": { "$numberDouble": "0.0" } } } }, { "name": "insertOne", "arguments": { "document": { "_id": 1, "encryptedDoublePrecision": { "$numberDouble": "1.0" } } } }, { "name": "aggregate", "arguments": { "pipeline": [ { "$match": { "encryptedDoublePrecision": { "$gt": { "$numberDouble": "200.0" } } } } ] }, "result": { "errorContains": "must be less than the range max" } } ] }, { "description": "Aggregate with $gt and $lt", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "local": { "key": { "$binary": { "base64": "Mng0NCt4ZHVUYUJCa1kxNkVyNUR1QURhZ2h2UzR2d2RrZzh0cFBwM3R6NmdWMDFBMUN3YkQ5aXRRMkhGRGdQV09wOGVNYUMxT2k3NjZKelhaQmRCZGJkTXVyZG9uSjFk", "subType": "00" } } } } } }, "operations": [ { "name": "insertOne", "arguments": { "document": { "_id": 0, "encryptedDoublePrecision": { "$numberDouble": "0.0" } } } }, { "name": "insertOne", "arguments": { "document": { "_id": 1, "encryptedDoublePrecision": { "$numberDouble": "1.0" } } } }, { "name": "aggregate", "arguments": { "pipeline": [ { "$match": { "encryptedDoublePrecision": { "$gt": { "$numberDouble": "0.0" }, "$lt": { "$numberDouble": "2.0" } } } } ] }, "result": [ { "_id": 1, "encryptedDoublePrecision": { "$numberDouble": "1.0" } } ] } ] }, { "description": "Aggregate with equality", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "local": { "key": { "$binary": { "base64": "Mng0NCt4ZHVUYUJCa1kxNkVyNUR1QURhZ2h2UzR2d2RrZzh0cFBwM3R6NmdWMDFBMUN3YkQ5aXRRMkhGRGdQV09wOGVNYUMxT2k3NjZKelhaQmRCZGJkTXVyZG9uSjFk", "subType": "00" } } } } } }, "operations": [ { "name": "insertOne", "arguments": { "document": { "_id": 0, "encryptedDoublePrecision": { "$numberDouble": "0.0" } } } }, { "name": "insertOne", "arguments": { "document": { "_id": 1, "encryptedDoublePrecision": { "$numberDouble": "1.0" } } } }, { "name": "aggregate", "arguments": { "pipeline": [ { "$match": { "encryptedDoublePrecision": { "$numberDouble": "0.0" } } } ] }, "result": [ { "_id": 0, "encryptedDoublePrecision": { "$numberDouble": "0.0" } } ] }, { "name": "aggregate", "arguments": { "pipeline": [ { "$match": { "encryptedDoublePrecision": { "$numberDouble": "1.0" } } } ] }, "result": [ { "_id": 1, "encryptedDoublePrecision": { "$numberDouble": "1.0" } } ] } ] }, { "description": "Aggregate with full range", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "local": { "key": { "$binary": { "base64": "Mng0NCt4ZHVUYUJCa1kxNkVyNUR1QURhZ2h2UzR2d2RrZzh0cFBwM3R6NmdWMDFBMUN3YkQ5aXRRMkhGRGdQV09wOGVNYUMxT2k3NjZKelhaQmRCZGJkTXVyZG9uSjFk", "subType": "00" } } } } } }, "operations": [ { "name": "insertOne", "arguments": { "document": { "_id": 0, "encryptedDoublePrecision": { "$numberDouble": "0.0" } } } }, { "name": "insertOne", "arguments": { "document": { "_id": 1, "encryptedDoublePrecision": { "$numberDouble": "1.0" } } } }, { "name": "aggregate", "arguments": { "pipeline": [ { "$match": { "encryptedDoublePrecision": { "$gte": { "$numberDouble": "0.0" }, "$lte": { "$numberDouble": "200.0" } } } }, { "$sort": { "_id": 1 } } ] }, "result": [ { "_id": 0, "encryptedDoublePrecision": { "$numberDouble": "0.0" } }, { "_id": 1, "encryptedDoublePrecision": { "$numberDouble": "1.0" } } ] } ] }, { "description": "Aggregate with $in", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "local": { "key": { "$binary": { "base64": "Mng0NCt4ZHVUYUJCa1kxNkVyNUR1QURhZ2h2UzR2d2RrZzh0cFBwM3R6NmdWMDFBMUN3YkQ5aXRRMkhGRGdQV09wOGVNYUMxT2k3NjZKelhaQmRCZGJkTXVyZG9uSjFk", "subType": "00" } } } } } }, "operations": [ { "name": "insertOne", "arguments": { "document": { "_id": 0, "encryptedDoublePrecision": { "$numberDouble": "0.0" } } } }, { "name": "insertOne", "arguments": { "document": { "_id": 1, "encryptedDoublePrecision": { "$numberDouble": "1.0" } } } }, { "name": "aggregate", "arguments": { "pipeline": [ { "$match": { "encryptedDoublePrecision": { "$in": [ { "$numberDouble": "0.0" } ] } } } ] }, "result": [ { "_id": 0, "encryptedDoublePrecision": { "$numberDouble": "0.0" } } ] } ] }, { "description": "Wrong type: Insert Int", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "local": { "key": { "$binary": { "base64": "Mng0NCt4ZHVUYUJCa1kxNkVyNUR1QURhZ2h2UzR2d2RrZzh0cFBwM3R6NmdWMDFBMUN3YkQ5aXRRMkhGRGdQV09wOGVNYUMxT2k3NjZKelhaQmRCZGJkTXVyZG9uSjFk", "subType": "00" } } } } } }, "operations": [ { "name": "insertOne", "arguments": { "document": { "_id": 0, "encryptedDoublePrecision": { "$numberInt": "0" } } }, "result": { "errorContains": "cannot encrypt element" } } ] }, { "description": "Wrong type: Find Int", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "local": { "key": { "$binary": { "base64": "Mng0NCt4ZHVUYUJCa1kxNkVyNUR1QURhZ2h2UzR2d2RrZzh0cFBwM3R6NmdWMDFBMUN3YkQ5aXRRMkhGRGdQV09wOGVNYUMxT2k3NjZKelhaQmRCZGJkTXVyZG9uSjFk", "subType": "00" } } } } } }, "operations": [ { "name": "find", "arguments": { "filter": { "encryptedDoublePrecision": { "$gte": { "$numberInt": "0" } } }, "sort": { "_id": 1 } }, "result": { "errorContains": "field type is not supported" } } ] } ] } fle2v2-Range-DoublePrecision-Delete.json000066400000000000000000000412541462766011000364420ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/client-side-encryption/spec/legacy{ "runOn": [ { "minServerVersion": "7.0.0", "topology": [ "replicaset", "sharded", "load-balanced" ] } ], "database_name": "default", "collection_name": "default", "data": [], "encrypted_fields": { "fields": [ { "keyId": { "$binary": { "base64": "EjRWeBI0mHYSNBI0VniQEg==", "subType": "04" } }, "path": "encryptedDoublePrecision", "bsonType": "double", "queries": { "queryType": "rangePreview", "contention": { "$numberLong": "0" }, "sparsity": { "$numberLong": "1" }, "min": { "$numberDouble": "0.0" }, "max": { "$numberDouble": "200.0" }, "precision": { "$numberInt": "2" } } } ] }, "key_vault_data": [ { "_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" } } ], "tests": [ { "description": "FLE2 Range DoublePrecision. Delete.", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "local": { "key": { "$binary": { "base64": "Mng0NCt4ZHVUYUJCa1kxNkVyNUR1QURhZ2h2UzR2d2RrZzh0cFBwM3R6NmdWMDFBMUN3YkQ5aXRRMkhGRGdQV09wOGVNYUMxT2k3NjZKelhaQmRCZGJkTXVyZG9uSjFk", "subType": "00" } } } } } }, "operations": [ { "name": "insertOne", "arguments": { "document": { "_id": 0, "encryptedDoublePrecision": { "$numberDouble": "0" } } } }, { "name": "insertOne", "arguments": { "document": { "_id": 1, "encryptedDoublePrecision": { "$numberDouble": "1" } } } }, { "name": "deleteOne", "arguments": { "filter": { "encryptedDoublePrecision": { "$gt": { "$numberDouble": "0" } } } }, "result": { "deletedCount": 1 } } ], "expectations": [ { "command_started_event": { "command": { "listCollections": 1, "filter": { "name": "default" } }, "command_name": "listCollections" } }, { "command_started_event": { "command": { "find": "datakeys", "filter": { "$or": [ { "_id": { "$in": [ { "$binary": { "base64": "EjRWeBI0mHYSNBI0VniQEg==", "subType": "04" } } ] } }, { "keyAltNames": { "$in": [] } } ] }, "$db": "keyvault", "readConcern": { "level": "majority" } }, "command_name": "find" } }, { "command_started_event": { "command": { "insert": "default", "documents": [ { "_id": 0, "encryptedDoublePrecision": { "$$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": "encryptedDoublePrecision", "bsonType": "double", "queries": { "queryType": "rangePreview", "contention": { "$numberLong": "0" }, "sparsity": { "$numberLong": "1" }, "min": { "$numberDouble": "0.0" }, "max": { "$numberDouble": "200.0" }, "precision": { "$numberInt": "2" } } } ] } } } }, "command_name": "insert" } }, { "command_started_event": { "command": { "insert": "default", "documents": [ { "_id": 1, "encryptedDoublePrecision": { "$$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": "encryptedDoublePrecision", "bsonType": "double", "queries": { "queryType": "rangePreview", "contention": { "$numberLong": "0" }, "sparsity": { "$numberLong": "1" }, "min": { "$numberDouble": "0.0" }, "max": { "$numberDouble": "200.0" }, "precision": { "$numberInt": "2" } } } ] } } } }, "command_name": "insert" } }, { "command_started_event": { "command": { "delete": "default", "deletes": [ { "q": { "encryptedDoublePrecision": { "$gt": { "$binary": { "base64": "DdIJAAADcGF5bG9hZACiCQAABGcAjgkAAAMwAH0AAAAFZAAgAAAAAHdJ2Vnb4MMzqVYVssjSdDy8XU4GVzMTfGifGETgQ2mYBXMAIAAAAAD7cFfKJGIXo6PjyeX2ria02CckW7dWFDoY/3FyBdm1NQVsACAAAAAAhEPSNv4M023A3hzNFuy83+hIKuZ2mKRY954N++aEOBUAAzEAfQAAAAVkACAAAAAAlmvfDrZoydUet4eCVMq7z6a58Ea+1HLJOWxN5lNcrWEFcwAgAAAAAEBo5AWZyC41b9ayjWNQSL4iYEAIwR/JG+ssN8bdoK9RBWwAIAAAAACEndE0SLxFSElOrNnqeX0EPmgDio3udZjVREy4JLS3sQADMgB9AAAABWQAIAAAAABbiLaoxAA6rinMJw1hC8ZUiq6UU1AQaPFn/py/Y06WuQVzACAAAAAAhtDasFkvYE7SCNu1je/hxdE9TJtAvvH3NtdEbKzNbCUFbAAgAAAAAIGepU1RSCF8sWODHEpKglsoqw3VBBH4a/URGxgGzbq2AAMzAH0AAAAFZAAgAAAAALORWwSr+tYNxcil2KIGSbNhTHvcPbdj+rLVQNx21S/KBXMAIAAAAAD6diZBkPEJ1cQy06LAxdbNK8Nlxbb44fH4Wk3Y3260nQVsACAAAAAA1eYAZBFHlDiaDAljWi8blGQ2nvvZa5AO5doeo0SFZsgAAzQAfQAAAAVkACAAAAAAG5XMK96PjClNlUvg82j4pMY1YxsznZfj4uNweD394FoFcwAgAAAAAKHgQLdGJHkrfFg9nB93Ac+3VgBw6aU44MTkKIQ91dZoBWwAIAAAAAAPxXmi+SDJ+40A0KdwfRczexlZQrHjIA+D3oUB0EY9tAADNQB9AAAABWQAIAAAAAA6M++b9I0YFemmWBAWAE3glu2Ah3Ta1FBxAQEIWS0toAVzACAAAAAANXYTqPf1Y6X3Ns6YQIX0C3FKCyWUo+Kk+fNcQvc0WSoFbAAgAAAAAA+uJUw1ICYgyeygSRe206VTWVtUnhdci3iHbyP5YtEVAAM2AH0AAAAFZAAgAAAAAKl8bV1riH/uyJ+X0HHd3+18k2cJl2dQFXCdoagutFcaBXMAIAAAAABm8F2Ew9f0VOABdcF+lP0Bi+zWvEUPniWgrxPq/Sx3uwVsACAAAAAAJfFErjZ6BPhsw5LjJLqNtKDLJ4zV0eIZppQpd9b0wZoAAzcAfQAAAAVkACAAAAAAsYZD8JEP6kYsPncFnNZwJxhu4YtUTKPNcjHtv67H+rYFcwAgAAAAAI4LqZcRkvbs/2F62Flu0pixNcor4WmBD0DHGaf039wLBWwAIAAAAAD4wUR3xd9lKltcqqo8LYvdMQWzCRobkV/ppKB/yn5dUgADOAB9AAAABWQAIAAAAAC0vdAi+dmoIXvZ5LqUqvyKV9/tHqSI2SWiSJO5pTnA2wVzACAAAAAAS2qvf9fvfVUH5WtsVxjxmskpGjYTQV34LwvQQw1y9wIFbAAgAAAAAE0+FKuK7HxbypvCeEJzMTcjOWE0ScYOlTBMUNlIv55hAAM5AH0AAAAFZAAgAAAAAH31lb/srBcrOXkzddCwAnclsR5/3QijEVgECs2JjOWBBXMAIAAAAABg7+prDT73YcCvLE5QbuIrqGcjLc5pQD2Miq0d29yrxgVsACAAAAAAetRiPwDSFWBzpWSWkOKWM6fKStRJ8SyObnpc79ux8p0AAzEwAH0AAAAFZAAgAAAAAOK8brUuc2onBNDRtfYMR736dHj4dQqXod8JG7tAMTsDBXMAIAAAAAAW6SrGAL6Bx0s7ZlsYULFfOAiYIGhEWu6md3r+Rk40awVsACAAAAAAIHYXP8RLcCboUmHN3+OlnEw1DxaLSnbTB9PdF228fFAAAzExAH0AAAAFZAAgAAAAAFdthRhe2Q8CvxGIhjTJZv0Lk97GkHciTPxZ/mckLoNaBXMAIAAAAAAqOxsAr23LOVB0DIHbPf9UDJJRFXY2YoKbjhRqw5psbQVsACAAAAAA0G2GD8ZQjDBntjLpW4rqwKRS6HiUjL03g1N6chANozcAAzEyAH0AAAAFZAAgAAAAAMWymwwbvIeMqmnKWWifUqoCxOsdpnonM2qdLPyjqJO/BXMAIAAAAAB6IDmmpUhBD2zpRj8/y/kmOSXcjuIU14sNh6GKSsg2uwVsACAAAAAAWMFPNOk3EMSQDS9JGPSMIQP0oNGVugxXKKUrIPPlhHgAAzEzAH0AAAAFZAAgAAAAAPcLmtq+V1e+MRlZ7NHq1+mrRVBQje5zj685ZvdsfKvSBXMAIAAAAABdHz/3w2k5km97QN9m7oLFYJaVJneNlMboIlz5yUASQAVsACAAAAAAWbp8JVJnx8fEVAJFa7WMfMa7wXeP5M3C8MX20J/i9n0AAzE0AH0AAAAFZAAgAAAAAJaRYmo8zqI2BEUzdSwp4tVRpPmVWsfydkYN3UHh6TMuBXMAIAAAAAAeD6mDnQeLlbC9i0sVgE8+RH6y+e94OJQ0tJ0PvblVSgVsACAAAAAAWp4jvretbDEsqEMzP/WLTnwOiJwCtfrCiB6m8k+yEMoAAzE1AH0AAAAFZAAgAAAAAAZZ538coNPwyRjhEwr5P8Xw32oWOJF+R+nfCGgy2qO3BXMAIAAAAACOPLnJlKwGNPDBReRKnHfteq0wFb3ezhrc7BVXs8RUHwVsACAAAAAA+lGesNk3+SyB/60rSvdQ2aN2vfJPR7llJVhufGTNhHkAAzE2AH0AAAAFZAAgAAAAAFH9l9GGA1I52atJV5jNUf1lx8jBjoEoVoME97v5GFJiBXMAIAAAAAC1qH3Kd78Dr9NGbw7y9D/XYBwv5h1LLO8la5OU7g8UkQVsACAAAAAArZ6atJCYrVfHB8dSNPOFf6nnDADBMJcIEj8ljPvxHp8AAzE3AH0AAAAFZAAgAAAAADtbVEI2tdkrowEMdkacD2w0Y3T3Ofi7PH6HmA6sP0c/BXMAIAAAAADuBSROnZHA+NgUPH8d0LnWFiDsM2bY8bzjC1+elSsIygVsACAAAAAAR0G2m+uANoWknkr/NerFcG+fECVxNIs0cqbY1t/U/0MAAzE4AH0AAAAFZAAgAAAAAAh3WpeMVlikPFYj9hLj+fmIqVt6omCSF75W3TPExyWpBXMAIAAAAAAsQkRmwqeVj2gGE03orb6PtrIzDt6dDU3hgSQi8E2wKgVsACAAAAAA3GHaRE2RAcaBRd8VzmYzWeBD2Gmy91eTK1k8YdWObZcAABJjbQAAAAAAAAAAAAAQcGF5bG9hZElkAAAAAAAQZmlyc3RPcGVyYXRvcgABAAAAAA==", "subType": "06" } } } }, "limit": 1 } ], "ordered": true, "encryptionInformation": { "type": 1, "schema": { "default.default": { "escCollection": "enxcol_.default.esc", "ecocCollection": "enxcol_.default.ecoc", "fields": [ { "keyId": { "$binary": { "base64": "EjRWeBI0mHYSNBI0VniQEg==", "subType": "04" } }, "path": "encryptedDoublePrecision", "bsonType": "double", "queries": { "queryType": "rangePreview", "contention": { "$numberLong": "0" }, "sparsity": { "$numberLong": "1" }, "min": { "$numberDouble": "0.0" }, "max": { "$numberDouble": "200.0" }, "precision": { "$numberInt": "2" } } } ] } } } }, "command_name": "delete" } } ], "outcome": { "collection": { "data": [ { "_id": 0, "encryptedDoublePrecision": { "$$type": "binData" }, "__safeContent__": [ { "$binary": { "base64": "5nRutVIyq7URVOVtbE4vM01APSIajAVnsShMwjBlzkM=", "subType": "00" } }, { "$binary": { "base64": "Dri0CXmL78L2DOgk9w0DwxHOMGMzih7m6l59vgy+WWo=", "subType": "00" } }, { "$binary": { "base64": "x7GR49EN0t3WXQDihkrbonK7qNIBYC87tpL/XEUyIYc=", "subType": "00" } }, { "$binary": { "base64": "JfYUqWF+OoGjiYkRI4L5iPlF+T1Eleul7Fki22jp4Qc=", "subType": "00" } }, { "$binary": { "base64": "q1RyGfIgsaQHoZFRw+DD28V26rN5hweApPLwExncvT8=", "subType": "00" } }, { "$binary": { "base64": "L2PFeKGvLS6C+DLudR6fGlBq3ERPvjWvRyNRIA2HVb0=", "subType": "00" } }, { "$binary": { "base64": "CWxaNqL3iP1yCixDkcmf9bmW3E5VeN8TJkg1jJe528s=", "subType": "00" } }, { "$binary": { "base64": "+vC6araOEo+fpW7PSIP40/EnzBCj1d2N10Jr3rrXJJM=", "subType": "00" } }, { "$binary": { "base64": "6SV63Mf51Z6A6p2X3rCnJKCu6ku3Oeb45mBYbz+IoAo=", "subType": "00" } }, { "$binary": { "base64": "RjBYT2h3ZAoHxhf8DU6/dFbDkEBZp0IxREcsRTu2MXs=", "subType": "00" } }, { "$binary": { "base64": "b7d8mRzD1kI1tdc7uNL+YAUonJ6pODLsRLkArfEKSkM=", "subType": "00" } }, { "$binary": { "base64": "Xg8C1/A0KJaXOw4i+26Rv03/CydaaunOzXh0CIT+gn8=", "subType": "00" } }, { "$binary": { "base64": "UoKUDw2wJYToUCcFaIs03YQSTksYR0MIOTJllwODqKc=", "subType": "00" } }, { "$binary": { "base64": "c/5cwAT0C5jber2xlJnWD3a5tVDy0nRtr5HG02hoFOY=", "subType": "00" } }, { "$binary": { "base64": "wSUrRXavAGaajNeqC5mEUH1K67oYl5Wy9RNIzKjwLAM=", "subType": "00" } }, { "$binary": { "base64": "6vrp4wWDtHEgHWR99I70WVDzevg1Fk/Pw5U8gUDa0OU=", "subType": "00" } } ] } ] } } } ] } fle2v2-Range-DoublePrecision-FindOneAndUpdate.json000066400000000000000000000505671462766011000403570ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/client-side-encryption/spec/legacy{ "runOn": [ { "minServerVersion": "7.0.0", "topology": [ "replicaset", "sharded", "load-balanced" ] } ], "database_name": "default", "collection_name": "default", "data": [], "encrypted_fields": { "fields": [ { "keyId": { "$binary": { "base64": "EjRWeBI0mHYSNBI0VniQEg==", "subType": "04" } }, "path": "encryptedDoublePrecision", "bsonType": "double", "queries": { "queryType": "rangePreview", "contention": { "$numberLong": "0" }, "sparsity": { "$numberLong": "1" }, "min": { "$numberDouble": "0.0" }, "max": { "$numberDouble": "200.0" }, "precision": { "$numberInt": "2" } } } ] }, "key_vault_data": [ { "_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" } } ], "tests": [ { "description": "FLE2 Range DoublePrecision. FindOneAndUpdate.", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "local": { "key": { "$binary": { "base64": "Mng0NCt4ZHVUYUJCa1kxNkVyNUR1QURhZ2h2UzR2d2RrZzh0cFBwM3R6NmdWMDFBMUN3YkQ5aXRRMkhGRGdQV09wOGVNYUMxT2k3NjZKelhaQmRCZGJkTXVyZG9uSjFk", "subType": "00" } } } } } }, "operations": [ { "name": "insertOne", "arguments": { "document": { "_id": 0, "encryptedDoublePrecision": { "$numberDouble": "0" } } } }, { "name": "insertOne", "arguments": { "document": { "_id": 1, "encryptedDoublePrecision": { "$numberDouble": "1" } } } }, { "name": "findOneAndUpdate", "arguments": { "filter": { "encryptedDoublePrecision": { "$gt": { "$numberDouble": "0" } } }, "update": { "$set": { "encryptedDoublePrecision": { "$numberDouble": "2" } } }, "returnDocument": "Before" }, "result": { "_id": 1, "encryptedDoublePrecision": { "$numberDouble": "1" } } } ], "expectations": [ { "command_started_event": { "command": { "listCollections": 1, "filter": { "name": "default" } }, "command_name": "listCollections" } }, { "command_started_event": { "command": { "find": "datakeys", "filter": { "$or": [ { "_id": { "$in": [ { "$binary": { "base64": "EjRWeBI0mHYSNBI0VniQEg==", "subType": "04" } } ] } }, { "keyAltNames": { "$in": [] } } ] }, "$db": "keyvault", "readConcern": { "level": "majority" } }, "command_name": "find" } }, { "command_started_event": { "command": { "insert": "default", "documents": [ { "_id": 0, "encryptedDoublePrecision": { "$$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": "encryptedDoublePrecision", "bsonType": "double", "queries": { "queryType": "rangePreview", "contention": { "$numberLong": "0" }, "sparsity": { "$numberLong": "1" }, "min": { "$numberDouble": "0.0" }, "max": { "$numberDouble": "200.0" }, "precision": { "$numberInt": "2" } } } ] } } } }, "command_name": "insert" } }, { "command_started_event": { "command": { "insert": "default", "documents": [ { "_id": 1, "encryptedDoublePrecision": { "$$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": "encryptedDoublePrecision", "bsonType": "double", "queries": { "queryType": "rangePreview", "contention": { "$numberLong": "0" }, "sparsity": { "$numberLong": "1" }, "min": { "$numberDouble": "0.0" }, "max": { "$numberDouble": "200.0" }, "precision": { "$numberInt": "2" } } } ] } } } }, "command_name": "insert" } }, { "command_started_event": { "command": { "findAndModify": "default", "query": { "encryptedDoublePrecision": { "$gt": { "$binary": { "base64": "DdIJAAADcGF5bG9hZACiCQAABGcAjgkAAAMwAH0AAAAFZAAgAAAAAHdJ2Vnb4MMzqVYVssjSdDy8XU4GVzMTfGifGETgQ2mYBXMAIAAAAAD7cFfKJGIXo6PjyeX2ria02CckW7dWFDoY/3FyBdm1NQVsACAAAAAAhEPSNv4M023A3hzNFuy83+hIKuZ2mKRY954N++aEOBUAAzEAfQAAAAVkACAAAAAAlmvfDrZoydUet4eCVMq7z6a58Ea+1HLJOWxN5lNcrWEFcwAgAAAAAEBo5AWZyC41b9ayjWNQSL4iYEAIwR/JG+ssN8bdoK9RBWwAIAAAAACEndE0SLxFSElOrNnqeX0EPmgDio3udZjVREy4JLS3sQADMgB9AAAABWQAIAAAAABbiLaoxAA6rinMJw1hC8ZUiq6UU1AQaPFn/py/Y06WuQVzACAAAAAAhtDasFkvYE7SCNu1je/hxdE9TJtAvvH3NtdEbKzNbCUFbAAgAAAAAIGepU1RSCF8sWODHEpKglsoqw3VBBH4a/URGxgGzbq2AAMzAH0AAAAFZAAgAAAAALORWwSr+tYNxcil2KIGSbNhTHvcPbdj+rLVQNx21S/KBXMAIAAAAAD6diZBkPEJ1cQy06LAxdbNK8Nlxbb44fH4Wk3Y3260nQVsACAAAAAA1eYAZBFHlDiaDAljWi8blGQ2nvvZa5AO5doeo0SFZsgAAzQAfQAAAAVkACAAAAAAG5XMK96PjClNlUvg82j4pMY1YxsznZfj4uNweD394FoFcwAgAAAAAKHgQLdGJHkrfFg9nB93Ac+3VgBw6aU44MTkKIQ91dZoBWwAIAAAAAAPxXmi+SDJ+40A0KdwfRczexlZQrHjIA+D3oUB0EY9tAADNQB9AAAABWQAIAAAAAA6M++b9I0YFemmWBAWAE3glu2Ah3Ta1FBxAQEIWS0toAVzACAAAAAANXYTqPf1Y6X3Ns6YQIX0C3FKCyWUo+Kk+fNcQvc0WSoFbAAgAAAAAA+uJUw1ICYgyeygSRe206VTWVtUnhdci3iHbyP5YtEVAAM2AH0AAAAFZAAgAAAAAKl8bV1riH/uyJ+X0HHd3+18k2cJl2dQFXCdoagutFcaBXMAIAAAAABm8F2Ew9f0VOABdcF+lP0Bi+zWvEUPniWgrxPq/Sx3uwVsACAAAAAAJfFErjZ6BPhsw5LjJLqNtKDLJ4zV0eIZppQpd9b0wZoAAzcAfQAAAAVkACAAAAAAsYZD8JEP6kYsPncFnNZwJxhu4YtUTKPNcjHtv67H+rYFcwAgAAAAAI4LqZcRkvbs/2F62Flu0pixNcor4WmBD0DHGaf039wLBWwAIAAAAAD4wUR3xd9lKltcqqo8LYvdMQWzCRobkV/ppKB/yn5dUgADOAB9AAAABWQAIAAAAAC0vdAi+dmoIXvZ5LqUqvyKV9/tHqSI2SWiSJO5pTnA2wVzACAAAAAAS2qvf9fvfVUH5WtsVxjxmskpGjYTQV34LwvQQw1y9wIFbAAgAAAAAE0+FKuK7HxbypvCeEJzMTcjOWE0ScYOlTBMUNlIv55hAAM5AH0AAAAFZAAgAAAAAH31lb/srBcrOXkzddCwAnclsR5/3QijEVgECs2JjOWBBXMAIAAAAABg7+prDT73YcCvLE5QbuIrqGcjLc5pQD2Miq0d29yrxgVsACAAAAAAetRiPwDSFWBzpWSWkOKWM6fKStRJ8SyObnpc79ux8p0AAzEwAH0AAAAFZAAgAAAAAOK8brUuc2onBNDRtfYMR736dHj4dQqXod8JG7tAMTsDBXMAIAAAAAAW6SrGAL6Bx0s7ZlsYULFfOAiYIGhEWu6md3r+Rk40awVsACAAAAAAIHYXP8RLcCboUmHN3+OlnEw1DxaLSnbTB9PdF228fFAAAzExAH0AAAAFZAAgAAAAAFdthRhe2Q8CvxGIhjTJZv0Lk97GkHciTPxZ/mckLoNaBXMAIAAAAAAqOxsAr23LOVB0DIHbPf9UDJJRFXY2YoKbjhRqw5psbQVsACAAAAAA0G2GD8ZQjDBntjLpW4rqwKRS6HiUjL03g1N6chANozcAAzEyAH0AAAAFZAAgAAAAAMWymwwbvIeMqmnKWWifUqoCxOsdpnonM2qdLPyjqJO/BXMAIAAAAAB6IDmmpUhBD2zpRj8/y/kmOSXcjuIU14sNh6GKSsg2uwVsACAAAAAAWMFPNOk3EMSQDS9JGPSMIQP0oNGVugxXKKUrIPPlhHgAAzEzAH0AAAAFZAAgAAAAAPcLmtq+V1e+MRlZ7NHq1+mrRVBQje5zj685ZvdsfKvSBXMAIAAAAABdHz/3w2k5km97QN9m7oLFYJaVJneNlMboIlz5yUASQAVsACAAAAAAWbp8JVJnx8fEVAJFa7WMfMa7wXeP5M3C8MX20J/i9n0AAzE0AH0AAAAFZAAgAAAAAJaRYmo8zqI2BEUzdSwp4tVRpPmVWsfydkYN3UHh6TMuBXMAIAAAAAAeD6mDnQeLlbC9i0sVgE8+RH6y+e94OJQ0tJ0PvblVSgVsACAAAAAAWp4jvretbDEsqEMzP/WLTnwOiJwCtfrCiB6m8k+yEMoAAzE1AH0AAAAFZAAgAAAAAAZZ538coNPwyRjhEwr5P8Xw32oWOJF+R+nfCGgy2qO3BXMAIAAAAACOPLnJlKwGNPDBReRKnHfteq0wFb3ezhrc7BVXs8RUHwVsACAAAAAA+lGesNk3+SyB/60rSvdQ2aN2vfJPR7llJVhufGTNhHkAAzE2AH0AAAAFZAAgAAAAAFH9l9GGA1I52atJV5jNUf1lx8jBjoEoVoME97v5GFJiBXMAIAAAAAC1qH3Kd78Dr9NGbw7y9D/XYBwv5h1LLO8la5OU7g8UkQVsACAAAAAArZ6atJCYrVfHB8dSNPOFf6nnDADBMJcIEj8ljPvxHp8AAzE3AH0AAAAFZAAgAAAAADtbVEI2tdkrowEMdkacD2w0Y3T3Ofi7PH6HmA6sP0c/BXMAIAAAAADuBSROnZHA+NgUPH8d0LnWFiDsM2bY8bzjC1+elSsIygVsACAAAAAAR0G2m+uANoWknkr/NerFcG+fECVxNIs0cqbY1t/U/0MAAzE4AH0AAAAFZAAgAAAAAAh3WpeMVlikPFYj9hLj+fmIqVt6omCSF75W3TPExyWpBXMAIAAAAAAsQkRmwqeVj2gGE03orb6PtrIzDt6dDU3hgSQi8E2wKgVsACAAAAAA3GHaRE2RAcaBRd8VzmYzWeBD2Gmy91eTK1k8YdWObZcAABJjbQAAAAAAAAAAAAAQcGF5bG9hZElkAAAAAAAQZmlyc3RPcGVyYXRvcgABAAAAAA==", "subType": "06" } } } }, "update": { "$set": { "encryptedDoublePrecision": { "$$type": "binData" } } }, "encryptionInformation": { "type": 1, "schema": { "default.default": { "escCollection": "enxcol_.default.esc", "ecocCollection": "enxcol_.default.ecoc", "fields": [ { "keyId": { "$binary": { "base64": "EjRWeBI0mHYSNBI0VniQEg==", "subType": "04" } }, "path": "encryptedDoublePrecision", "bsonType": "double", "queries": { "queryType": "rangePreview", "contention": { "$numberLong": "0" }, "sparsity": { "$numberLong": "1" }, "min": { "$numberDouble": "0.0" }, "max": { "$numberDouble": "200.0" }, "precision": { "$numberInt": "2" } } } ] } } } }, "command_name": "findAndModify" } } ], "outcome": { "collection": { "data": [ { "_id": 0, "encryptedDoublePrecision": { "$$type": "binData" }, "__safeContent__": [ { "$binary": { "base64": "5nRutVIyq7URVOVtbE4vM01APSIajAVnsShMwjBlzkM=", "subType": "00" } }, { "$binary": { "base64": "Dri0CXmL78L2DOgk9w0DwxHOMGMzih7m6l59vgy+WWo=", "subType": "00" } }, { "$binary": { "base64": "x7GR49EN0t3WXQDihkrbonK7qNIBYC87tpL/XEUyIYc=", "subType": "00" } }, { "$binary": { "base64": "JfYUqWF+OoGjiYkRI4L5iPlF+T1Eleul7Fki22jp4Qc=", "subType": "00" } }, { "$binary": { "base64": "q1RyGfIgsaQHoZFRw+DD28V26rN5hweApPLwExncvT8=", "subType": "00" } }, { "$binary": { "base64": "L2PFeKGvLS6C+DLudR6fGlBq3ERPvjWvRyNRIA2HVb0=", "subType": "00" } }, { "$binary": { "base64": "CWxaNqL3iP1yCixDkcmf9bmW3E5VeN8TJkg1jJe528s=", "subType": "00" } }, { "$binary": { "base64": "+vC6araOEo+fpW7PSIP40/EnzBCj1d2N10Jr3rrXJJM=", "subType": "00" } }, { "$binary": { "base64": "6SV63Mf51Z6A6p2X3rCnJKCu6ku3Oeb45mBYbz+IoAo=", "subType": "00" } }, { "$binary": { "base64": "RjBYT2h3ZAoHxhf8DU6/dFbDkEBZp0IxREcsRTu2MXs=", "subType": "00" } }, { "$binary": { "base64": "b7d8mRzD1kI1tdc7uNL+YAUonJ6pODLsRLkArfEKSkM=", "subType": "00" } }, { "$binary": { "base64": "Xg8C1/A0KJaXOw4i+26Rv03/CydaaunOzXh0CIT+gn8=", "subType": "00" } }, { "$binary": { "base64": "UoKUDw2wJYToUCcFaIs03YQSTksYR0MIOTJllwODqKc=", "subType": "00" } }, { "$binary": { "base64": "c/5cwAT0C5jber2xlJnWD3a5tVDy0nRtr5HG02hoFOY=", "subType": "00" } }, { "$binary": { "base64": "wSUrRXavAGaajNeqC5mEUH1K67oYl5Wy9RNIzKjwLAM=", "subType": "00" } }, { "$binary": { "base64": "6vrp4wWDtHEgHWR99I70WVDzevg1Fk/Pw5U8gUDa0OU=", "subType": "00" } } ] }, { "_id": 1, "encryptedDoublePrecision": { "$$type": "binData" }, "__safeContent__": [ { "$binary": { "base64": "DLCAJs+W2PL2DV5YChCL6dYrQNr+j4p3L7xhVaub4ic=", "subType": "00" } }, { "$binary": { "base64": "V6knyt7Zq2CG3++l75UtBx2m32iGAPjHiAe439Bf02w=", "subType": "00" } }, { "$binary": { "base64": "F08nMDWDZc+DbWM7XCEJNNCEYyinRmrvGP7EWhmp4is=", "subType": "00" } }, { "$binary": { "base64": "cXH4688amcDc8kZOJq4UP8cE3R58Zl7e+Qo/1jyspps=", "subType": "00" } }, { "$binary": { "base64": "uURBxvTp3FBCVkd+LPqyuY7d6rMW6SGIJQEPY/wtkZI=", "subType": "00" } }, { "$binary": { "base64": "jG3hax1L3RBp9t38vUt53FsBxgr/+Si/vVISpAylYpE=", "subType": "00" } }, { "$binary": { "base64": "kwtIW8MhH9Ky5xNjBx8gFA/SHh2YVphie7g5FGBzals=", "subType": "00" } }, { "$binary": { "base64": "FHflwFuEMu4xX0ZApHi+pdlBH+oevAtXckCUb5Wv0xU=", "subType": "00" } }, { "$binary": { "base64": "0OKSXELxPP85SBVwDGf3LtMEQCJ8TTkFUl/+6jlkdb0=", "subType": "00" } }, { "$binary": { "base64": "25j9sQXZCihCmHKvTHgaBsAVZFcGPn7JjHdrCGlwyyw=", "subType": "00" } }, { "$binary": { "base64": "uEw0lpQtBppR3vqV9j9+NQRSBF1BzZukb8c9IhyWvxc=", "subType": "00" } }, { "$binary": { "base64": "zVhZ7Q59O087ji49oMJvBIgeir2oqvUpnh4p53GcTow=", "subType": "00" } }, { "$binary": { "base64": "dowrzKs+qJhRMZyKDbhjXbuX43FbmUKOaw9I8YlOZDw=", "subType": "00" } }, { "$binary": { "base64": "ep5B6cska6THLIF7Mn3tn3RvV9EiwLSt0eZM/CLRUDc=", "subType": "00" } }, { "$binary": { "base64": "URNp/YmmDh5wIZUfAzzgPyJeMNiVx9PMsz52DZRujGY=", "subType": "00" } }, { "$binary": { "base64": "wlM4IAQhhKQEzoVqS8b1Ddd50GB95OFb9LnzOwyjCP4=", "subType": "00" } } ] } ] } } } ] } fle2v2-Range-DoublePrecision-InsertFind.json000066400000000000000000000477341462766011000373160ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/client-side-encryption/spec/legacy{ "runOn": [ { "minServerVersion": "7.0.0", "topology": [ "replicaset", "sharded", "load-balanced" ] } ], "database_name": "default", "collection_name": "default", "data": [], "encrypted_fields": { "fields": [ { "keyId": { "$binary": { "base64": "EjRWeBI0mHYSNBI0VniQEg==", "subType": "04" } }, "path": "encryptedDoublePrecision", "bsonType": "double", "queries": { "queryType": "rangePreview", "contention": { "$numberLong": "0" }, "sparsity": { "$numberLong": "1" }, "min": { "$numberDouble": "0.0" }, "max": { "$numberDouble": "200.0" }, "precision": { "$numberInt": "2" } } } ] }, "key_vault_data": [ { "_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" } } ], "tests": [ { "description": "FLE2 Range DoublePrecision. Insert and Find.", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "local": { "key": { "$binary": { "base64": "Mng0NCt4ZHVUYUJCa1kxNkVyNUR1QURhZ2h2UzR2d2RrZzh0cFBwM3R6NmdWMDFBMUN3YkQ5aXRRMkhGRGdQV09wOGVNYUMxT2k3NjZKelhaQmRCZGJkTXVyZG9uSjFk", "subType": "00" } } } } } }, "operations": [ { "name": "insertOne", "arguments": { "document": { "_id": 0, "encryptedDoublePrecision": { "$numberDouble": "0" } } } }, { "name": "insertOne", "arguments": { "document": { "_id": 1, "encryptedDoublePrecision": { "$numberDouble": "1" } } } }, { "name": "find", "arguments": { "filter": { "encryptedDoublePrecision": { "$gt": { "$numberDouble": "0" } } } }, "result": [ { "_id": 1, "encryptedDoublePrecision": { "$numberDouble": "1" } } ] } ], "expectations": [ { "command_started_event": { "command": { "listCollections": 1, "filter": { "name": "default" } }, "command_name": "listCollections" } }, { "command_started_event": { "command": { "find": "datakeys", "filter": { "$or": [ { "_id": { "$in": [ { "$binary": { "base64": "EjRWeBI0mHYSNBI0VniQEg==", "subType": "04" } } ] } }, { "keyAltNames": { "$in": [] } } ] }, "$db": "keyvault", "readConcern": { "level": "majority" } }, "command_name": "find" } }, { "command_started_event": { "command": { "insert": "default", "documents": [ { "_id": 0, "encryptedDoublePrecision": { "$$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": "encryptedDoublePrecision", "bsonType": "double", "queries": { "queryType": "rangePreview", "contention": { "$numberLong": "0" }, "sparsity": { "$numberLong": "1" }, "min": { "$numberDouble": "0.0" }, "max": { "$numberDouble": "200.0" }, "precision": { "$numberInt": "2" } } } ] } } } }, "command_name": "insert" } }, { "command_started_event": { "command": { "insert": "default", "documents": [ { "_id": 1, "encryptedDoublePrecision": { "$$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": "encryptedDoublePrecision", "bsonType": "double", "queries": { "queryType": "rangePreview", "contention": { "$numberLong": "0" }, "sparsity": { "$numberLong": "1" }, "min": { "$numberDouble": "0.0" }, "max": { "$numberDouble": "200.0" }, "precision": { "$numberInt": "2" } } } ] } } } }, "command_name": "insert" } }, { "command_started_event": { "command": { "find": "default", "filter": { "encryptedDoublePrecision": { "$gt": { "$binary": { "base64": "DdIJAAADcGF5bG9hZACiCQAABGcAjgkAAAMwAH0AAAAFZAAgAAAAAHdJ2Vnb4MMzqVYVssjSdDy8XU4GVzMTfGifGETgQ2mYBXMAIAAAAAD7cFfKJGIXo6PjyeX2ria02CckW7dWFDoY/3FyBdm1NQVsACAAAAAAhEPSNv4M023A3hzNFuy83+hIKuZ2mKRY954N++aEOBUAAzEAfQAAAAVkACAAAAAAlmvfDrZoydUet4eCVMq7z6a58Ea+1HLJOWxN5lNcrWEFcwAgAAAAAEBo5AWZyC41b9ayjWNQSL4iYEAIwR/JG+ssN8bdoK9RBWwAIAAAAACEndE0SLxFSElOrNnqeX0EPmgDio3udZjVREy4JLS3sQADMgB9AAAABWQAIAAAAABbiLaoxAA6rinMJw1hC8ZUiq6UU1AQaPFn/py/Y06WuQVzACAAAAAAhtDasFkvYE7SCNu1je/hxdE9TJtAvvH3NtdEbKzNbCUFbAAgAAAAAIGepU1RSCF8sWODHEpKglsoqw3VBBH4a/URGxgGzbq2AAMzAH0AAAAFZAAgAAAAALORWwSr+tYNxcil2KIGSbNhTHvcPbdj+rLVQNx21S/KBXMAIAAAAAD6diZBkPEJ1cQy06LAxdbNK8Nlxbb44fH4Wk3Y3260nQVsACAAAAAA1eYAZBFHlDiaDAljWi8blGQ2nvvZa5AO5doeo0SFZsgAAzQAfQAAAAVkACAAAAAAG5XMK96PjClNlUvg82j4pMY1YxsznZfj4uNweD394FoFcwAgAAAAAKHgQLdGJHkrfFg9nB93Ac+3VgBw6aU44MTkKIQ91dZoBWwAIAAAAAAPxXmi+SDJ+40A0KdwfRczexlZQrHjIA+D3oUB0EY9tAADNQB9AAAABWQAIAAAAAA6M++b9I0YFemmWBAWAE3glu2Ah3Ta1FBxAQEIWS0toAVzACAAAAAANXYTqPf1Y6X3Ns6YQIX0C3FKCyWUo+Kk+fNcQvc0WSoFbAAgAAAAAA+uJUw1ICYgyeygSRe206VTWVtUnhdci3iHbyP5YtEVAAM2AH0AAAAFZAAgAAAAAKl8bV1riH/uyJ+X0HHd3+18k2cJl2dQFXCdoagutFcaBXMAIAAAAABm8F2Ew9f0VOABdcF+lP0Bi+zWvEUPniWgrxPq/Sx3uwVsACAAAAAAJfFErjZ6BPhsw5LjJLqNtKDLJ4zV0eIZppQpd9b0wZoAAzcAfQAAAAVkACAAAAAAsYZD8JEP6kYsPncFnNZwJxhu4YtUTKPNcjHtv67H+rYFcwAgAAAAAI4LqZcRkvbs/2F62Flu0pixNcor4WmBD0DHGaf039wLBWwAIAAAAAD4wUR3xd9lKltcqqo8LYvdMQWzCRobkV/ppKB/yn5dUgADOAB9AAAABWQAIAAAAAC0vdAi+dmoIXvZ5LqUqvyKV9/tHqSI2SWiSJO5pTnA2wVzACAAAAAAS2qvf9fvfVUH5WtsVxjxmskpGjYTQV34LwvQQw1y9wIFbAAgAAAAAE0+FKuK7HxbypvCeEJzMTcjOWE0ScYOlTBMUNlIv55hAAM5AH0AAAAFZAAgAAAAAH31lb/srBcrOXkzddCwAnclsR5/3QijEVgECs2JjOWBBXMAIAAAAABg7+prDT73YcCvLE5QbuIrqGcjLc5pQD2Miq0d29yrxgVsACAAAAAAetRiPwDSFWBzpWSWkOKWM6fKStRJ8SyObnpc79ux8p0AAzEwAH0AAAAFZAAgAAAAAOK8brUuc2onBNDRtfYMR736dHj4dQqXod8JG7tAMTsDBXMAIAAAAAAW6SrGAL6Bx0s7ZlsYULFfOAiYIGhEWu6md3r+Rk40awVsACAAAAAAIHYXP8RLcCboUmHN3+OlnEw1DxaLSnbTB9PdF228fFAAAzExAH0AAAAFZAAgAAAAAFdthRhe2Q8CvxGIhjTJZv0Lk97GkHciTPxZ/mckLoNaBXMAIAAAAAAqOxsAr23LOVB0DIHbPf9UDJJRFXY2YoKbjhRqw5psbQVsACAAAAAA0G2GD8ZQjDBntjLpW4rqwKRS6HiUjL03g1N6chANozcAAzEyAH0AAAAFZAAgAAAAAMWymwwbvIeMqmnKWWifUqoCxOsdpnonM2qdLPyjqJO/BXMAIAAAAAB6IDmmpUhBD2zpRj8/y/kmOSXcjuIU14sNh6GKSsg2uwVsACAAAAAAWMFPNOk3EMSQDS9JGPSMIQP0oNGVugxXKKUrIPPlhHgAAzEzAH0AAAAFZAAgAAAAAPcLmtq+V1e+MRlZ7NHq1+mrRVBQje5zj685ZvdsfKvSBXMAIAAAAABdHz/3w2k5km97QN9m7oLFYJaVJneNlMboIlz5yUASQAVsACAAAAAAWbp8JVJnx8fEVAJFa7WMfMa7wXeP5M3C8MX20J/i9n0AAzE0AH0AAAAFZAAgAAAAAJaRYmo8zqI2BEUzdSwp4tVRpPmVWsfydkYN3UHh6TMuBXMAIAAAAAAeD6mDnQeLlbC9i0sVgE8+RH6y+e94OJQ0tJ0PvblVSgVsACAAAAAAWp4jvretbDEsqEMzP/WLTnwOiJwCtfrCiB6m8k+yEMoAAzE1AH0AAAAFZAAgAAAAAAZZ538coNPwyRjhEwr5P8Xw32oWOJF+R+nfCGgy2qO3BXMAIAAAAACOPLnJlKwGNPDBReRKnHfteq0wFb3ezhrc7BVXs8RUHwVsACAAAAAA+lGesNk3+SyB/60rSvdQ2aN2vfJPR7llJVhufGTNhHkAAzE2AH0AAAAFZAAgAAAAAFH9l9GGA1I52atJV5jNUf1lx8jBjoEoVoME97v5GFJiBXMAIAAAAAC1qH3Kd78Dr9NGbw7y9D/XYBwv5h1LLO8la5OU7g8UkQVsACAAAAAArZ6atJCYrVfHB8dSNPOFf6nnDADBMJcIEj8ljPvxHp8AAzE3AH0AAAAFZAAgAAAAADtbVEI2tdkrowEMdkacD2w0Y3T3Ofi7PH6HmA6sP0c/BXMAIAAAAADuBSROnZHA+NgUPH8d0LnWFiDsM2bY8bzjC1+elSsIygVsACAAAAAAR0G2m+uANoWknkr/NerFcG+fECVxNIs0cqbY1t/U/0MAAzE4AH0AAAAFZAAgAAAAAAh3WpeMVlikPFYj9hLj+fmIqVt6omCSF75W3TPExyWpBXMAIAAAAAAsQkRmwqeVj2gGE03orb6PtrIzDt6dDU3hgSQi8E2wKgVsACAAAAAA3GHaRE2RAcaBRd8VzmYzWeBD2Gmy91eTK1k8YdWObZcAABJjbQAAAAAAAAAAAAAQcGF5bG9hZElkAAAAAAAQZmlyc3RPcGVyYXRvcgABAAAAAA==", "subType": "06" } } } }, "encryptionInformation": { "type": 1, "schema": { "default.default": { "escCollection": "enxcol_.default.esc", "ecocCollection": "enxcol_.default.ecoc", "fields": [ { "keyId": { "$binary": { "base64": "EjRWeBI0mHYSNBI0VniQEg==", "subType": "04" } }, "path": "encryptedDoublePrecision", "bsonType": "double", "queries": { "queryType": "rangePreview", "contention": { "$numberLong": "0" }, "sparsity": { "$numberLong": "1" }, "min": { "$numberDouble": "0.0" }, "max": { "$numberDouble": "200.0" }, "precision": { "$numberInt": "2" } } } ] } } } }, "command_name": "find" } } ], "outcome": { "collection": { "data": [ { "_id": 0, "encryptedDoublePrecision": { "$$type": "binData" }, "__safeContent__": [ { "$binary": { "base64": "5nRutVIyq7URVOVtbE4vM01APSIajAVnsShMwjBlzkM=", "subType": "00" } }, { "$binary": { "base64": "Dri0CXmL78L2DOgk9w0DwxHOMGMzih7m6l59vgy+WWo=", "subType": "00" } }, { "$binary": { "base64": "x7GR49EN0t3WXQDihkrbonK7qNIBYC87tpL/XEUyIYc=", "subType": "00" } }, { "$binary": { "base64": "JfYUqWF+OoGjiYkRI4L5iPlF+T1Eleul7Fki22jp4Qc=", "subType": "00" } }, { "$binary": { "base64": "q1RyGfIgsaQHoZFRw+DD28V26rN5hweApPLwExncvT8=", "subType": "00" } }, { "$binary": { "base64": "L2PFeKGvLS6C+DLudR6fGlBq3ERPvjWvRyNRIA2HVb0=", "subType": "00" } }, { "$binary": { "base64": "CWxaNqL3iP1yCixDkcmf9bmW3E5VeN8TJkg1jJe528s=", "subType": "00" } }, { "$binary": { "base64": "+vC6araOEo+fpW7PSIP40/EnzBCj1d2N10Jr3rrXJJM=", "subType": "00" } }, { "$binary": { "base64": "6SV63Mf51Z6A6p2X3rCnJKCu6ku3Oeb45mBYbz+IoAo=", "subType": "00" } }, { "$binary": { "base64": "RjBYT2h3ZAoHxhf8DU6/dFbDkEBZp0IxREcsRTu2MXs=", "subType": "00" } }, { "$binary": { "base64": "b7d8mRzD1kI1tdc7uNL+YAUonJ6pODLsRLkArfEKSkM=", "subType": "00" } }, { "$binary": { "base64": "Xg8C1/A0KJaXOw4i+26Rv03/CydaaunOzXh0CIT+gn8=", "subType": "00" } }, { "$binary": { "base64": "UoKUDw2wJYToUCcFaIs03YQSTksYR0MIOTJllwODqKc=", "subType": "00" } }, { "$binary": { "base64": "c/5cwAT0C5jber2xlJnWD3a5tVDy0nRtr5HG02hoFOY=", "subType": "00" } }, { "$binary": { "base64": "wSUrRXavAGaajNeqC5mEUH1K67oYl5Wy9RNIzKjwLAM=", "subType": "00" } }, { "$binary": { "base64": "6vrp4wWDtHEgHWR99I70WVDzevg1Fk/Pw5U8gUDa0OU=", "subType": "00" } } ] }, { "_id": 1, "encryptedDoublePrecision": { "$$type": "binData" }, "__safeContent__": [ { "$binary": { "base64": "bE1vqWj3KNyM7cCYUv/cnYm8BPaUL3eMp5syTHq6NF4=", "subType": "00" } }, { "$binary": { "base64": "mVZb+Ra0EYjQ4Zrh9X//E2T8MRj7NMqm5GUJXhRrBEI=", "subType": "00" } }, { "$binary": { "base64": "FA74j21GUEJb1DJBOpR9nVnjaDZnd8yAQNuaW9Qi26g=", "subType": "00" } }, { "$binary": { "base64": "kJv//KVkbrobIBf+QeWC5jxn20mx/P0R1N6aCSMgKM8=", "subType": "00" } }, { "$binary": { "base64": "zB+Whi9IUUGxfLEe+lGuIzLX4LFbIhaIAm5lRk65QTc=", "subType": "00" } }, { "$binary": { "base64": "ybO1QU3CgvhO8JgRXH+HxKszWcpl5aGDYYVa75fHa1g=", "subType": "00" } }, { "$binary": { "base64": "X3Y3eSAbbMg//JgiHHiFpYOpV61t8kkDexI+CQyitH4=", "subType": "00" } }, { "$binary": { "base64": "SlNHXyqVFGDPrX/2ppwog6l4pwj3PKda2TkZbqgfSfA=", "subType": "00" } }, { "$binary": { "base64": "McjV8xwTF3xI7863DYOBdyvIv6UpzThl6v9vBRk05bI=", "subType": "00" } }, { "$binary": { "base64": "MgwakFvPyBlwqFTbhWUF79URJQWFoJTGotlEVSPPUsQ=", "subType": "00" } }, { "$binary": { "base64": "DyBERpMSD5lEM5Nhpcn4WGgxgn/mkUVJp+PYSLX5jsE=", "subType": "00" } }, { "$binary": { "base64": "I43iazc0xj1WVbYB/V+uTL/tughN1bBlxh1iypBnNsA=", "subType": "00" } }, { "$binary": { "base64": "wjOBa/ATMuOywFmuPgC0GF/oeLqu0Z7eK5udzkTPbis=", "subType": "00" } }, { "$binary": { "base64": "gRQVwiR+m+0Vg8ZDXqrQQcVnTyobwCXNaA4BCJVXtMc=", "subType": "00" } }, { "$binary": { "base64": "WUZ6huwx0ZbLb0R00uiC9FOJzsUocUN8qE5+YRenkvQ=", "subType": "00" } }, { "$binary": { "base64": "7s79aKEuPgQcS/YPOOVcYNZvHIo7FFsWtFCrnDKXefA=", "subType": "00" } } ] } ] } } } ] } fle2v2-Range-DoublePrecision-Update.json000066400000000000000000000507461462766011000364700ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/client-side-encryption/spec/legacy{ "runOn": [ { "minServerVersion": "7.0.0", "topology": [ "replicaset", "sharded", "load-balanced" ] } ], "database_name": "default", "collection_name": "default", "data": [], "encrypted_fields": { "fields": [ { "keyId": { "$binary": { "base64": "EjRWeBI0mHYSNBI0VniQEg==", "subType": "04" } }, "path": "encryptedDoublePrecision", "bsonType": "double", "queries": { "queryType": "rangePreview", "contention": { "$numberLong": "0" }, "sparsity": { "$numberLong": "1" }, "min": { "$numberDouble": "0.0" }, "max": { "$numberDouble": "200.0" }, "precision": { "$numberInt": "2" } } } ] }, "key_vault_data": [ { "_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" } } ], "tests": [ { "description": "FLE2 Range DoublePrecision. Update.", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "local": { "key": { "$binary": { "base64": "Mng0NCt4ZHVUYUJCa1kxNkVyNUR1QURhZ2h2UzR2d2RrZzh0cFBwM3R6NmdWMDFBMUN3YkQ5aXRRMkhGRGdQV09wOGVNYUMxT2k3NjZKelhaQmRCZGJkTXVyZG9uSjFk", "subType": "00" } } } } } }, "operations": [ { "name": "insertOne", "arguments": { "document": { "_id": 0, "encryptedDoublePrecision": { "$numberDouble": "0" } } } }, { "name": "insertOne", "arguments": { "document": { "_id": 1, "encryptedDoublePrecision": { "$numberDouble": "1" } } } }, { "name": "updateOne", "arguments": { "filter": { "encryptedDoublePrecision": { "$gt": { "$numberDouble": "0" } } }, "update": { "$set": { "encryptedDoublePrecision": { "$numberDouble": "2" } } } }, "result": { "matchedCount": 1, "modifiedCount": 1, "upsertedCount": 0 } } ], "expectations": [ { "command_started_event": { "command": { "listCollections": 1, "filter": { "name": "default" } }, "command_name": "listCollections" } }, { "command_started_event": { "command": { "find": "datakeys", "filter": { "$or": [ { "_id": { "$in": [ { "$binary": { "base64": "EjRWeBI0mHYSNBI0VniQEg==", "subType": "04" } } ] } }, { "keyAltNames": { "$in": [] } } ] }, "$db": "keyvault", "readConcern": { "level": "majority" } }, "command_name": "find" } }, { "command_started_event": { "command": { "insert": "default", "documents": [ { "_id": 0, "encryptedDoublePrecision": { "$$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": "encryptedDoublePrecision", "bsonType": "double", "queries": { "queryType": "rangePreview", "contention": { "$numberLong": "0" }, "sparsity": { "$numberLong": "1" }, "min": { "$numberDouble": "0.0" }, "max": { "$numberDouble": "200.0" }, "precision": { "$numberInt": "2" } } } ] } } } }, "command_name": "insert" } }, { "command_started_event": { "command": { "insert": "default", "documents": [ { "_id": 1, "encryptedDoublePrecision": { "$$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": "encryptedDoublePrecision", "bsonType": "double", "queries": { "queryType": "rangePreview", "contention": { "$numberLong": "0" }, "sparsity": { "$numberLong": "1" }, "min": { "$numberDouble": "0.0" }, "max": { "$numberDouble": "200.0" }, "precision": { "$numberInt": "2" } } } ] } } } }, "command_name": "insert" } }, { "command_started_event": { "command_name": "update", "command": { "update": "default", "ordered": true, "updates": [ { "q": { "encryptedDoublePrecision": { "$gt": { "$binary": { "base64": "DdIJAAADcGF5bG9hZACiCQAABGcAjgkAAAMwAH0AAAAFZAAgAAAAAHdJ2Vnb4MMzqVYVssjSdDy8XU4GVzMTfGifGETgQ2mYBXMAIAAAAAD7cFfKJGIXo6PjyeX2ria02CckW7dWFDoY/3FyBdm1NQVsACAAAAAAhEPSNv4M023A3hzNFuy83+hIKuZ2mKRY954N++aEOBUAAzEAfQAAAAVkACAAAAAAlmvfDrZoydUet4eCVMq7z6a58Ea+1HLJOWxN5lNcrWEFcwAgAAAAAEBo5AWZyC41b9ayjWNQSL4iYEAIwR/JG+ssN8bdoK9RBWwAIAAAAACEndE0SLxFSElOrNnqeX0EPmgDio3udZjVREy4JLS3sQADMgB9AAAABWQAIAAAAABbiLaoxAA6rinMJw1hC8ZUiq6UU1AQaPFn/py/Y06WuQVzACAAAAAAhtDasFkvYE7SCNu1je/hxdE9TJtAvvH3NtdEbKzNbCUFbAAgAAAAAIGepU1RSCF8sWODHEpKglsoqw3VBBH4a/URGxgGzbq2AAMzAH0AAAAFZAAgAAAAALORWwSr+tYNxcil2KIGSbNhTHvcPbdj+rLVQNx21S/KBXMAIAAAAAD6diZBkPEJ1cQy06LAxdbNK8Nlxbb44fH4Wk3Y3260nQVsACAAAAAA1eYAZBFHlDiaDAljWi8blGQ2nvvZa5AO5doeo0SFZsgAAzQAfQAAAAVkACAAAAAAG5XMK96PjClNlUvg82j4pMY1YxsznZfj4uNweD394FoFcwAgAAAAAKHgQLdGJHkrfFg9nB93Ac+3VgBw6aU44MTkKIQ91dZoBWwAIAAAAAAPxXmi+SDJ+40A0KdwfRczexlZQrHjIA+D3oUB0EY9tAADNQB9AAAABWQAIAAAAAA6M++b9I0YFemmWBAWAE3glu2Ah3Ta1FBxAQEIWS0toAVzACAAAAAANXYTqPf1Y6X3Ns6YQIX0C3FKCyWUo+Kk+fNcQvc0WSoFbAAgAAAAAA+uJUw1ICYgyeygSRe206VTWVtUnhdci3iHbyP5YtEVAAM2AH0AAAAFZAAgAAAAAKl8bV1riH/uyJ+X0HHd3+18k2cJl2dQFXCdoagutFcaBXMAIAAAAABm8F2Ew9f0VOABdcF+lP0Bi+zWvEUPniWgrxPq/Sx3uwVsACAAAAAAJfFErjZ6BPhsw5LjJLqNtKDLJ4zV0eIZppQpd9b0wZoAAzcAfQAAAAVkACAAAAAAsYZD8JEP6kYsPncFnNZwJxhu4YtUTKPNcjHtv67H+rYFcwAgAAAAAI4LqZcRkvbs/2F62Flu0pixNcor4WmBD0DHGaf039wLBWwAIAAAAAD4wUR3xd9lKltcqqo8LYvdMQWzCRobkV/ppKB/yn5dUgADOAB9AAAABWQAIAAAAAC0vdAi+dmoIXvZ5LqUqvyKV9/tHqSI2SWiSJO5pTnA2wVzACAAAAAAS2qvf9fvfVUH5WtsVxjxmskpGjYTQV34LwvQQw1y9wIFbAAgAAAAAE0+FKuK7HxbypvCeEJzMTcjOWE0ScYOlTBMUNlIv55hAAM5AH0AAAAFZAAgAAAAAH31lb/srBcrOXkzddCwAnclsR5/3QijEVgECs2JjOWBBXMAIAAAAABg7+prDT73YcCvLE5QbuIrqGcjLc5pQD2Miq0d29yrxgVsACAAAAAAetRiPwDSFWBzpWSWkOKWM6fKStRJ8SyObnpc79ux8p0AAzEwAH0AAAAFZAAgAAAAAOK8brUuc2onBNDRtfYMR736dHj4dQqXod8JG7tAMTsDBXMAIAAAAAAW6SrGAL6Bx0s7ZlsYULFfOAiYIGhEWu6md3r+Rk40awVsACAAAAAAIHYXP8RLcCboUmHN3+OlnEw1DxaLSnbTB9PdF228fFAAAzExAH0AAAAFZAAgAAAAAFdthRhe2Q8CvxGIhjTJZv0Lk97GkHciTPxZ/mckLoNaBXMAIAAAAAAqOxsAr23LOVB0DIHbPf9UDJJRFXY2YoKbjhRqw5psbQVsACAAAAAA0G2GD8ZQjDBntjLpW4rqwKRS6HiUjL03g1N6chANozcAAzEyAH0AAAAFZAAgAAAAAMWymwwbvIeMqmnKWWifUqoCxOsdpnonM2qdLPyjqJO/BXMAIAAAAAB6IDmmpUhBD2zpRj8/y/kmOSXcjuIU14sNh6GKSsg2uwVsACAAAAAAWMFPNOk3EMSQDS9JGPSMIQP0oNGVugxXKKUrIPPlhHgAAzEzAH0AAAAFZAAgAAAAAPcLmtq+V1e+MRlZ7NHq1+mrRVBQje5zj685ZvdsfKvSBXMAIAAAAABdHz/3w2k5km97QN9m7oLFYJaVJneNlMboIlz5yUASQAVsACAAAAAAWbp8JVJnx8fEVAJFa7WMfMa7wXeP5M3C8MX20J/i9n0AAzE0AH0AAAAFZAAgAAAAAJaRYmo8zqI2BEUzdSwp4tVRpPmVWsfydkYN3UHh6TMuBXMAIAAAAAAeD6mDnQeLlbC9i0sVgE8+RH6y+e94OJQ0tJ0PvblVSgVsACAAAAAAWp4jvretbDEsqEMzP/WLTnwOiJwCtfrCiB6m8k+yEMoAAzE1AH0AAAAFZAAgAAAAAAZZ538coNPwyRjhEwr5P8Xw32oWOJF+R+nfCGgy2qO3BXMAIAAAAACOPLnJlKwGNPDBReRKnHfteq0wFb3ezhrc7BVXs8RUHwVsACAAAAAA+lGesNk3+SyB/60rSvdQ2aN2vfJPR7llJVhufGTNhHkAAzE2AH0AAAAFZAAgAAAAAFH9l9GGA1I52atJV5jNUf1lx8jBjoEoVoME97v5GFJiBXMAIAAAAAC1qH3Kd78Dr9NGbw7y9D/XYBwv5h1LLO8la5OU7g8UkQVsACAAAAAArZ6atJCYrVfHB8dSNPOFf6nnDADBMJcIEj8ljPvxHp8AAzE3AH0AAAAFZAAgAAAAADtbVEI2tdkrowEMdkacD2w0Y3T3Ofi7PH6HmA6sP0c/BXMAIAAAAADuBSROnZHA+NgUPH8d0LnWFiDsM2bY8bzjC1+elSsIygVsACAAAAAAR0G2m+uANoWknkr/NerFcG+fECVxNIs0cqbY1t/U/0MAAzE4AH0AAAAFZAAgAAAAAAh3WpeMVlikPFYj9hLj+fmIqVt6omCSF75W3TPExyWpBXMAIAAAAAAsQkRmwqeVj2gGE03orb6PtrIzDt6dDU3hgSQi8E2wKgVsACAAAAAA3GHaRE2RAcaBRd8VzmYzWeBD2Gmy91eTK1k8YdWObZcAABJjbQAAAAAAAAAAAAAQcGF5bG9hZElkAAAAAAAQZmlyc3RPcGVyYXRvcgABAAAAAA==", "subType": "06" } } } }, "u": { "$set": { "encryptedDoublePrecision": { "$$type": "binData" } } } } ], "encryptionInformation": { "type": 1, "schema": { "default.default": { "escCollection": "enxcol_.default.esc", "ecocCollection": "enxcol_.default.ecoc", "fields": [ { "keyId": { "$binary": { "base64": "EjRWeBI0mHYSNBI0VniQEg==", "subType": "04" } }, "path": "encryptedDoublePrecision", "bsonType": "double", "queries": { "queryType": "rangePreview", "contention": { "$numberLong": "0" }, "sparsity": { "$numberLong": "1" }, "min": { "$numberDouble": "0.0" }, "max": { "$numberDouble": "200.0" }, "precision": { "$numberInt": "2" } } } ] } } }, "$db": "default" } } } ], "outcome": { "collection": { "data": [ { "_id": 0, "encryptedDoublePrecision": { "$$type": "binData" }, "__safeContent__": [ { "$binary": { "base64": "5nRutVIyq7URVOVtbE4vM01APSIajAVnsShMwjBlzkM=", "subType": "00" } }, { "$binary": { "base64": "Dri0CXmL78L2DOgk9w0DwxHOMGMzih7m6l59vgy+WWo=", "subType": "00" } }, { "$binary": { "base64": "x7GR49EN0t3WXQDihkrbonK7qNIBYC87tpL/XEUyIYc=", "subType": "00" } }, { "$binary": { "base64": "JfYUqWF+OoGjiYkRI4L5iPlF+T1Eleul7Fki22jp4Qc=", "subType": "00" } }, { "$binary": { "base64": "q1RyGfIgsaQHoZFRw+DD28V26rN5hweApPLwExncvT8=", "subType": "00" } }, { "$binary": { "base64": "L2PFeKGvLS6C+DLudR6fGlBq3ERPvjWvRyNRIA2HVb0=", "subType": "00" } }, { "$binary": { "base64": "CWxaNqL3iP1yCixDkcmf9bmW3E5VeN8TJkg1jJe528s=", "subType": "00" } }, { "$binary": { "base64": "+vC6araOEo+fpW7PSIP40/EnzBCj1d2N10Jr3rrXJJM=", "subType": "00" } }, { "$binary": { "base64": "6SV63Mf51Z6A6p2X3rCnJKCu6ku3Oeb45mBYbz+IoAo=", "subType": "00" } }, { "$binary": { "base64": "RjBYT2h3ZAoHxhf8DU6/dFbDkEBZp0IxREcsRTu2MXs=", "subType": "00" } }, { "$binary": { "base64": "b7d8mRzD1kI1tdc7uNL+YAUonJ6pODLsRLkArfEKSkM=", "subType": "00" } }, { "$binary": { "base64": "Xg8C1/A0KJaXOw4i+26Rv03/CydaaunOzXh0CIT+gn8=", "subType": "00" } }, { "$binary": { "base64": "UoKUDw2wJYToUCcFaIs03YQSTksYR0MIOTJllwODqKc=", "subType": "00" } }, { "$binary": { "base64": "c/5cwAT0C5jber2xlJnWD3a5tVDy0nRtr5HG02hoFOY=", "subType": "00" } }, { "$binary": { "base64": "wSUrRXavAGaajNeqC5mEUH1K67oYl5Wy9RNIzKjwLAM=", "subType": "00" } }, { "$binary": { "base64": "6vrp4wWDtHEgHWR99I70WVDzevg1Fk/Pw5U8gUDa0OU=", "subType": "00" } } ] }, { "_id": 1, "encryptedDoublePrecision": { "$$type": "binData" }, "__safeContent__": [ { "$binary": { "base64": "DLCAJs+W2PL2DV5YChCL6dYrQNr+j4p3L7xhVaub4ic=", "subType": "00" } }, { "$binary": { "base64": "V6knyt7Zq2CG3++l75UtBx2m32iGAPjHiAe439Bf02w=", "subType": "00" } }, { "$binary": { "base64": "F08nMDWDZc+DbWM7XCEJNNCEYyinRmrvGP7EWhmp4is=", "subType": "00" } }, { "$binary": { "base64": "cXH4688amcDc8kZOJq4UP8cE3R58Zl7e+Qo/1jyspps=", "subType": "00" } }, { "$binary": { "base64": "uURBxvTp3FBCVkd+LPqyuY7d6rMW6SGIJQEPY/wtkZI=", "subType": "00" } }, { "$binary": { "base64": "jG3hax1L3RBp9t38vUt53FsBxgr/+Si/vVISpAylYpE=", "subType": "00" } }, { "$binary": { "base64": "kwtIW8MhH9Ky5xNjBx8gFA/SHh2YVphie7g5FGBzals=", "subType": "00" } }, { "$binary": { "base64": "FHflwFuEMu4xX0ZApHi+pdlBH+oevAtXckCUb5Wv0xU=", "subType": "00" } }, { "$binary": { "base64": "0OKSXELxPP85SBVwDGf3LtMEQCJ8TTkFUl/+6jlkdb0=", "subType": "00" } }, { "$binary": { "base64": "25j9sQXZCihCmHKvTHgaBsAVZFcGPn7JjHdrCGlwyyw=", "subType": "00" } }, { "$binary": { "base64": "uEw0lpQtBppR3vqV9j9+NQRSBF1BzZukb8c9IhyWvxc=", "subType": "00" } }, { "$binary": { "base64": "zVhZ7Q59O087ji49oMJvBIgeir2oqvUpnh4p53GcTow=", "subType": "00" } }, { "$binary": { "base64": "dowrzKs+qJhRMZyKDbhjXbuX43FbmUKOaw9I8YlOZDw=", "subType": "00" } }, { "$binary": { "base64": "ep5B6cska6THLIF7Mn3tn3RvV9EiwLSt0eZM/CLRUDc=", "subType": "00" } }, { "$binary": { "base64": "URNp/YmmDh5wIZUfAzzgPyJeMNiVx9PMsz52DZRujGY=", "subType": "00" } }, { "$binary": { "base64": "wlM4IAQhhKQEzoVqS8b1Ddd50GB95OFb9LnzOwyjCP4=", "subType": "00" } } ] } ] } } } ] } fle2v2-Range-Int-Aggregate.json000066400000000000000000000364751462766011000346030ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/client-side-encryption/spec/legacy{ "runOn": [ { "minServerVersion": "7.0.0", "topology": [ "replicaset", "sharded", "load-balanced" ] } ], "database_name": "default", "collection_name": "default", "data": [], "encrypted_fields": { "fields": [ { "keyId": { "$binary": { "base64": "EjRWeBI0mHYSNBI0VniQEg==", "subType": "04" } }, "path": "encryptedInt", "bsonType": "int", "queries": { "queryType": "rangePreview", "contention": { "$numberLong": "0" }, "sparsity": { "$numberLong": "1" }, "min": { "$numberInt": "0" }, "max": { "$numberInt": "200" } } } ] }, "key_vault_data": [ { "_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" } } ], "tests": [ { "description": "FLE2 Range Int. Aggregate.", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "local": { "key": { "$binary": { "base64": "Mng0NCt4ZHVUYUJCa1kxNkVyNUR1QURhZ2h2UzR2d2RrZzh0cFBwM3R6NmdWMDFBMUN3YkQ5aXRRMkhGRGdQV09wOGVNYUMxT2k3NjZKelhaQmRCZGJkTXVyZG9uSjFk", "subType": "00" } } } } } }, "operations": [ { "name": "insertOne", "arguments": { "document": { "_id": 0, "encryptedInt": { "$numberInt": "0" } } } }, { "name": "insertOne", "arguments": { "document": { "_id": 1, "encryptedInt": { "$numberInt": "1" } } } }, { "name": "aggregate", "arguments": { "pipeline": [ { "$match": { "encryptedInt": { "$gt": { "$numberInt": "0" } } } } ] }, "result": [ { "_id": 1, "encryptedInt": { "$numberInt": "1" } } ] } ], "expectations": [ { "command_started_event": { "command": { "listCollections": 1, "filter": { "name": "default" } }, "command_name": "listCollections" } }, { "command_started_event": { "command": { "find": "datakeys", "filter": { "$or": [ { "_id": { "$in": [ { "$binary": { "base64": "EjRWeBI0mHYSNBI0VniQEg==", "subType": "04" } } ] } }, { "keyAltNames": { "$in": [] } } ] }, "$db": "keyvault", "readConcern": { "level": "majority" } }, "command_name": "find" } }, { "command_started_event": { "command": { "insert": "default", "documents": [ { "_id": 0, "encryptedInt": { "$$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": "encryptedInt", "bsonType": "int", "queries": { "queryType": "rangePreview", "contention": { "$numberLong": "0" }, "sparsity": { "$numberLong": "1" }, "min": { "$numberInt": "0" }, "max": { "$numberInt": "200" } } } ] } } } }, "command_name": "insert" } }, { "command_started_event": { "command": { "insert": "default", "documents": [ { "_id": 1, "encryptedInt": { "$$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": "encryptedInt", "bsonType": "int", "queries": { "queryType": "rangePreview", "contention": { "$numberLong": "0" }, "sparsity": { "$numberLong": "1" }, "min": { "$numberInt": "0" }, "max": { "$numberInt": "200" } } } ] } } } }, "command_name": "insert" } }, { "command_started_event": { "command": { "aggregate": "default", "pipeline": [ { "$match": { "encryptedInt": { "$gt": { "$binary": { "base64": "DUkFAAADcGF5bG9hZAAZBQAABGcABQUAAAMwAH0AAAAFZAAgAAAAALGGQ/CRD+pGLD53BZzWcCcYbuGLVEyjzXIx7b+ux/q2BXMAIAAAAACOC6mXEZL27P9hethZbtKYsTXKK+FpgQ9Axxmn9N/cCwVsACAAAAAA+MFEd8XfZSpbXKqqPC2L3TEFswkaG5Ff6aSgf8p+XVIAAzEAfQAAAAVkACAAAAAAtL3QIvnZqCF72eS6lKr8ilff7R6kiNklokiTuaU5wNsFcwAgAAAAAEtqr3/X731VB+VrbFcY8ZrJKRo2E0Fd+C8L0EMNcvcCBWwAIAAAAABNPhSriux8W8qbwnhCczE3IzlhNEnGDpUwTFDZSL+eYQADMgB9AAAABWQAIAAAAAB99ZW/7KwXKzl5M3XQsAJ3JbEef90IoxFYBArNiYzlgQVzACAAAAAAYO/qaw0+92HAryxOUG7iK6hnIy3OaUA9jIqtHdvcq8YFbAAgAAAAAHrUYj8A0hVgc6VklpDiljOnykrUSfEsjm56XO/bsfKdAAMzAH0AAAAFZAAgAAAAAOK8brUuc2onBNDRtfYMR736dHj4dQqXod8JG7tAMTsDBXMAIAAAAAAW6SrGAL6Bx0s7ZlsYULFfOAiYIGhEWu6md3r+Rk40awVsACAAAAAAIHYXP8RLcCboUmHN3+OlnEw1DxaLSnbTB9PdF228fFAAAzQAfQAAAAVkACAAAAAAV22FGF7ZDwK/EYiGNMlm/QuT3saQdyJM/Fn+ZyQug1oFcwAgAAAAACo7GwCvbcs5UHQMgds9/1QMklEVdjZigpuOFGrDmmxtBWwAIAAAAADQbYYPxlCMMGe2MulbiurApFLoeJSMvTeDU3pyEA2jNwADNQB9AAAABWQAIAAAAADFspsMG7yHjKppyllon1KqAsTrHaZ6JzNqnSz8o6iTvwVzACAAAAAAeiA5pqVIQQ9s6UY/P8v5Jjkl3I7iFNeLDYehikrINrsFbAAgAAAAAFjBTzTpNxDEkA0vSRj0jCED9KDRlboMVyilKyDz5YR4AAM2AH0AAAAFZAAgAAAAAPcLmtq+V1e+MRlZ7NHq1+mrRVBQje5zj685ZvdsfKvSBXMAIAAAAABdHz/3w2k5km97QN9m7oLFYJaVJneNlMboIlz5yUASQAVsACAAAAAAWbp8JVJnx8fEVAJFa7WMfMa7wXeP5M3C8MX20J/i9n0AAzcAfQAAAAVkACAAAAAAYfLwnoxK6XAGQrJFy8+TIJoq38ldBaO75h4zA4ZX5tQFcwAgAAAAAC2wk8UcJH5X5XGnDBYmel6srpBkzBhHtt3Jw1u5TSJ1BWwAIAAAAAA9/YU9eI3D7QbXKIw/3/gzWJ6MZrCYhG0j1wNKgRQp5wADOAB9AAAABWQAIAAAAADGvyrtKkIcaV17ynZA7b2k5Pz6OhvxdWNkDvDWJIja8wVzACAAAAAAOLypVKNxf/wR1G8OZjUUsTQzDYeNNhhITxGMSp7euS4FbAAgAAAAAA9EsxoV1B2DcQ1NJRwuxXnvVR+vkD0wbbDYEI/zFEnDAAM5AH0AAAAFZAAgAAAAAEocREw1L0g+roFUchJI2Yd0M0ME2bnErNUYnpyJP1SqBXMAIAAAAAAcE2/JK/8MoSeOchIuAkKh1X3ImoA7p8ujAZIfvIDo6QVsACAAAAAA+W0+zgLr85/PD7P9a94wk6MgNgrizx/XU9aCxAkp1IwAABJjbQAAAAAAAAAAAAAQcGF5bG9hZElkAAAAAAAQZmlyc3RPcGVyYXRvcgABAAAAAA==", "subType": "06" } } } } } ], "cursor": {}, "encryptionInformation": { "type": 1, "schema": { "default.default": { "escCollection": "enxcol_.default.esc", "ecocCollection": "enxcol_.default.ecoc", "fields": [ { "keyId": { "$binary": { "base64": "EjRWeBI0mHYSNBI0VniQEg==", "subType": "04" } }, "path": "encryptedInt", "bsonType": "int", "queries": { "queryType": "rangePreview", "contention": { "$numberLong": "0" }, "sparsity": { "$numberLong": "1" }, "min": { "$numberInt": "0" }, "max": { "$numberInt": "200" } } } ] } } } }, "command_name": "aggregate" } } ], "outcome": { "collection": { "data": [ { "_id": 0, "encryptedInt": { "$$type": "binData" }, "__safeContent__": [ { "$binary": { "base64": "5nRutVIyq7URVOVtbE4vM01APSIajAVnsShMwjBlzkM=", "subType": "00" } }, { "$binary": { "base64": "RjBYT2h3ZAoHxhf8DU6/dFbDkEBZp0IxREcsRTu2MXs=", "subType": "00" } }, { "$binary": { "base64": "x7GR49EN0t3WXQDihkrbonK7qNIBYC87tpL/XEUyIYc=", "subType": "00" } }, { "$binary": { "base64": "JfYUqWF+OoGjiYkRI4L5iPlF+T1Eleul7Fki22jp4Qc=", "subType": "00" } }, { "$binary": { "base64": "q1RyGfIgsaQHoZFRw+DD28V26rN5hweApPLwExncvT8=", "subType": "00" } }, { "$binary": { "base64": "L2PFeKGvLS6C+DLudR6fGlBq3ERPvjWvRyNRIA2HVb0=", "subType": "00" } }, { "$binary": { "base64": "CWxaNqL3iP1yCixDkcmf9bmW3E5VeN8TJkg1jJe528s=", "subType": "00" } }, { "$binary": { "base64": "+vC6araOEo+fpW7PSIP40/EnzBCj1d2N10Jr3rrXJJM=", "subType": "00" } }, { "$binary": { "base64": "6SV63Mf51Z6A6p2X3rCnJKCu6ku3Oeb45mBYbz+IoAo=", "subType": "00" } } ] }, { "_id": 1, "encryptedInt": { "$$type": "binData" }, "__safeContent__": [ { "$binary": { "base64": "bE1vqWj3KNyM7cCYUv/cnYm8BPaUL3eMp5syTHq6NF4=", "subType": "00" } }, { "$binary": { "base64": "25j9sQXZCihCmHKvTHgaBsAVZFcGPn7JjHdrCGlwyyw=", "subType": "00" } }, { "$binary": { "base64": "FA74j21GUEJb1DJBOpR9nVnjaDZnd8yAQNuaW9Qi26g=", "subType": "00" } }, { "$binary": { "base64": "kJv//KVkbrobIBf+QeWC5jxn20mx/P0R1N6aCSMgKM8=", "subType": "00" } }, { "$binary": { "base64": "zB+Whi9IUUGxfLEe+lGuIzLX4LFbIhaIAm5lRk65QTc=", "subType": "00" } }, { "$binary": { "base64": "ybO1QU3CgvhO8JgRXH+HxKszWcpl5aGDYYVa75fHa1g=", "subType": "00" } }, { "$binary": { "base64": "X3Y3eSAbbMg//JgiHHiFpYOpV61t8kkDexI+CQyitH4=", "subType": "00" } }, { "$binary": { "base64": "SlNHXyqVFGDPrX/2ppwog6l4pwj3PKda2TkZbqgfSfA=", "subType": "00" } }, { "$binary": { "base64": "McjV8xwTF3xI7863DYOBdyvIv6UpzThl6v9vBRk05bI=", "subType": "00" } } ] } ] } } } ] } fle2v2-Range-Int-Correctness.json000066400000000000000000001125501462766011000351740ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/client-side-encryption/spec/legacy{ "runOn": [ { "minServerVersion": "7.0.0", "topology": [ "replicaset", "sharded", "load-balanced" ] } ], "database_name": "default", "collection_name": "default", "data": [], "encrypted_fields": { "fields": [ { "keyId": { "$binary": { "base64": "EjRWeBI0mHYSNBI0VniQEg==", "subType": "04" } }, "path": "encryptedInt", "bsonType": "int", "queries": { "queryType": "rangePreview", "contention": { "$numberLong": "0" }, "sparsity": { "$numberLong": "1" }, "min": { "$numberInt": "0" }, "max": { "$numberInt": "200" } } } ] }, "key_vault_data": [ { "_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" } } ], "tests": [ { "description": "Find with $gt", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "local": { "key": { "$binary": { "base64": "Mng0NCt4ZHVUYUJCa1kxNkVyNUR1QURhZ2h2UzR2d2RrZzh0cFBwM3R6NmdWMDFBMUN3YkQ5aXRRMkhGRGdQV09wOGVNYUMxT2k3NjZKelhaQmRCZGJkTXVyZG9uSjFk", "subType": "00" } } } } } }, "operations": [ { "name": "insertOne", "arguments": { "document": { "_id": 0, "encryptedInt": { "$numberInt": "0" } } } }, { "name": "insertOne", "arguments": { "document": { "_id": 1, "encryptedInt": { "$numberInt": "1" } } } }, { "name": "find", "arguments": { "filter": { "encryptedInt": { "$gt": { "$numberInt": "0" } } } }, "result": [ { "_id": 1, "encryptedInt": { "$numberInt": "1" } } ] } ] }, { "description": "Find with $gte", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "local": { "key": { "$binary": { "base64": "Mng0NCt4ZHVUYUJCa1kxNkVyNUR1QURhZ2h2UzR2d2RrZzh0cFBwM3R6NmdWMDFBMUN3YkQ5aXRRMkhGRGdQV09wOGVNYUMxT2k3NjZKelhaQmRCZGJkTXVyZG9uSjFk", "subType": "00" } } } } } }, "operations": [ { "name": "insertOne", "arguments": { "document": { "_id": 0, "encryptedInt": { "$numberInt": "0" } } } }, { "name": "insertOne", "arguments": { "document": { "_id": 1, "encryptedInt": { "$numberInt": "1" } } } }, { "name": "find", "arguments": { "filter": { "encryptedInt": { "$gte": { "$numberInt": "0" } } }, "sort": { "_id": 1 } }, "result": [ { "_id": 0, "encryptedInt": { "$numberInt": "0" } }, { "_id": 1, "encryptedInt": { "$numberInt": "1" } } ] } ] }, { "description": "Find with $gt with no results", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "local": { "key": { "$binary": { "base64": "Mng0NCt4ZHVUYUJCa1kxNkVyNUR1QURhZ2h2UzR2d2RrZzh0cFBwM3R6NmdWMDFBMUN3YkQ5aXRRMkhGRGdQV09wOGVNYUMxT2k3NjZKelhaQmRCZGJkTXVyZG9uSjFk", "subType": "00" } } } } } }, "operations": [ { "name": "insertOne", "arguments": { "document": { "_id": 0, "encryptedInt": { "$numberInt": "0" } } } }, { "name": "insertOne", "arguments": { "document": { "_id": 1, "encryptedInt": { "$numberInt": "1" } } } }, { "name": "find", "arguments": { "filter": { "encryptedInt": { "$gt": { "$numberInt": "1" } } } }, "result": [] } ] }, { "description": "Find with $lt", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "local": { "key": { "$binary": { "base64": "Mng0NCt4ZHVUYUJCa1kxNkVyNUR1QURhZ2h2UzR2d2RrZzh0cFBwM3R6NmdWMDFBMUN3YkQ5aXRRMkhGRGdQV09wOGVNYUMxT2k3NjZKelhaQmRCZGJkTXVyZG9uSjFk", "subType": "00" } } } } } }, "operations": [ { "name": "insertOne", "arguments": { "document": { "_id": 0, "encryptedInt": { "$numberInt": "0" } } } }, { "name": "insertOne", "arguments": { "document": { "_id": 1, "encryptedInt": { "$numberInt": "1" } } } }, { "name": "find", "arguments": { "filter": { "encryptedInt": { "$lt": { "$numberInt": "1" } } } }, "result": [ { "_id": 0, "encryptedInt": { "$numberInt": "0" } } ] } ] }, { "description": "Find with $lte", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "local": { "key": { "$binary": { "base64": "Mng0NCt4ZHVUYUJCa1kxNkVyNUR1QURhZ2h2UzR2d2RrZzh0cFBwM3R6NmdWMDFBMUN3YkQ5aXRRMkhGRGdQV09wOGVNYUMxT2k3NjZKelhaQmRCZGJkTXVyZG9uSjFk", "subType": "00" } } } } } }, "operations": [ { "name": "insertOne", "arguments": { "document": { "_id": 0, "encryptedInt": { "$numberInt": "0" } } } }, { "name": "insertOne", "arguments": { "document": { "_id": 1, "encryptedInt": { "$numberInt": "1" } } } }, { "name": "find", "arguments": { "filter": { "encryptedInt": { "$lte": { "$numberInt": "1" } } }, "sort": { "_id": 1 } }, "result": [ { "_id": 0, "encryptedInt": { "$numberInt": "0" } }, { "_id": 1, "encryptedInt": { "$numberInt": "1" } } ] } ] }, { "description": "Find with $lt below min", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "local": { "key": { "$binary": { "base64": "Mng0NCt4ZHVUYUJCa1kxNkVyNUR1QURhZ2h2UzR2d2RrZzh0cFBwM3R6NmdWMDFBMUN3YkQ5aXRRMkhGRGdQV09wOGVNYUMxT2k3NjZKelhaQmRCZGJkTXVyZG9uSjFk", "subType": "00" } } } } } }, "operations": [ { "name": "insertOne", "arguments": { "document": { "_id": 0, "encryptedInt": { "$numberInt": "0" } } } }, { "name": "insertOne", "arguments": { "document": { "_id": 1, "encryptedInt": { "$numberInt": "1" } } } }, { "name": "find", "arguments": { "filter": { "encryptedInt": { "$lt": { "$numberInt": "0" } } } }, "result": { "errorContains": "must be greater than the range minimum" } } ] }, { "description": "Find with $gt above max", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "local": { "key": { "$binary": { "base64": "Mng0NCt4ZHVUYUJCa1kxNkVyNUR1QURhZ2h2UzR2d2RrZzh0cFBwM3R6NmdWMDFBMUN3YkQ5aXRRMkhGRGdQV09wOGVNYUMxT2k3NjZKelhaQmRCZGJkTXVyZG9uSjFk", "subType": "00" } } } } } }, "operations": [ { "name": "insertOne", "arguments": { "document": { "_id": 0, "encryptedInt": { "$numberInt": "0" } } } }, { "name": "insertOne", "arguments": { "document": { "_id": 1, "encryptedInt": { "$numberInt": "1" } } } }, { "name": "find", "arguments": { "filter": { "encryptedInt": { "$gt": { "$numberInt": "200" } } } }, "result": { "errorContains": "must be less than the range maximum" } } ] }, { "description": "Find with $gt and $lt", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "local": { "key": { "$binary": { "base64": "Mng0NCt4ZHVUYUJCa1kxNkVyNUR1QURhZ2h2UzR2d2RrZzh0cFBwM3R6NmdWMDFBMUN3YkQ5aXRRMkhGRGdQV09wOGVNYUMxT2k3NjZKelhaQmRCZGJkTXVyZG9uSjFk", "subType": "00" } } } } } }, "operations": [ { "name": "insertOne", "arguments": { "document": { "_id": 0, "encryptedInt": { "$numberInt": "0" } } } }, { "name": "insertOne", "arguments": { "document": { "_id": 1, "encryptedInt": { "$numberInt": "1" } } } }, { "name": "find", "arguments": { "filter": { "encryptedInt": { "$gt": { "$numberInt": "0" }, "$lt": { "$numberInt": "2" } } } }, "result": [ { "_id": 1, "encryptedInt": { "$numberInt": "1" } } ] } ] }, { "description": "Find with equality", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "local": { "key": { "$binary": { "base64": "Mng0NCt4ZHVUYUJCa1kxNkVyNUR1QURhZ2h2UzR2d2RrZzh0cFBwM3R6NmdWMDFBMUN3YkQ5aXRRMkhGRGdQV09wOGVNYUMxT2k3NjZKelhaQmRCZGJkTXVyZG9uSjFk", "subType": "00" } } } } } }, "operations": [ { "name": "insertOne", "arguments": { "document": { "_id": 0, "encryptedInt": { "$numberInt": "0" } } } }, { "name": "insertOne", "arguments": { "document": { "_id": 1, "encryptedInt": { "$numberInt": "1" } } } }, { "name": "find", "arguments": { "filter": { "encryptedInt": { "$numberInt": "0" } } }, "result": [ { "_id": 0, "encryptedInt": { "$numberInt": "0" } } ] }, { "name": "find", "arguments": { "filter": { "encryptedInt": { "$numberInt": "1" } } }, "result": [ { "_id": 1, "encryptedInt": { "$numberInt": "1" } } ] } ] }, { "description": "Find with full range", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "local": { "key": { "$binary": { "base64": "Mng0NCt4ZHVUYUJCa1kxNkVyNUR1QURhZ2h2UzR2d2RrZzh0cFBwM3R6NmdWMDFBMUN3YkQ5aXRRMkhGRGdQV09wOGVNYUMxT2k3NjZKelhaQmRCZGJkTXVyZG9uSjFk", "subType": "00" } } } } } }, "operations": [ { "name": "insertOne", "arguments": { "document": { "_id": 0, "encryptedInt": { "$numberInt": "0" } } } }, { "name": "insertOne", "arguments": { "document": { "_id": 1, "encryptedInt": { "$numberInt": "1" } } } }, { "name": "find", "arguments": { "filter": { "encryptedInt": { "$gte": { "$numberInt": "0" }, "$lte": { "$numberInt": "200" } } }, "sort": { "_id": 1 } }, "result": [ { "_id": 0, "encryptedInt": { "$numberInt": "0" } }, { "_id": 1, "encryptedInt": { "$numberInt": "1" } } ] } ] }, { "description": "Find with $in", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "local": { "key": { "$binary": { "base64": "Mng0NCt4ZHVUYUJCa1kxNkVyNUR1QURhZ2h2UzR2d2RrZzh0cFBwM3R6NmdWMDFBMUN3YkQ5aXRRMkhGRGdQV09wOGVNYUMxT2k3NjZKelhaQmRCZGJkTXVyZG9uSjFk", "subType": "00" } } } } } }, "operations": [ { "name": "insertOne", "arguments": { "document": { "_id": 0, "encryptedInt": { "$numberInt": "0" } } } }, { "name": "insertOne", "arguments": { "document": { "_id": 1, "encryptedInt": { "$numberInt": "1" } } } }, { "name": "find", "arguments": { "filter": { "encryptedInt": { "$in": [ { "$numberInt": "0" } ] } } }, "result": [ { "_id": 0, "encryptedInt": { "$numberInt": "0" } } ] } ] }, { "description": "Insert out of range", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "local": { "key": { "$binary": { "base64": "Mng0NCt4ZHVUYUJCa1kxNkVyNUR1QURhZ2h2UzR2d2RrZzh0cFBwM3R6NmdWMDFBMUN3YkQ5aXRRMkhGRGdQV09wOGVNYUMxT2k3NjZKelhaQmRCZGJkTXVyZG9uSjFk", "subType": "00" } } } } } }, "operations": [ { "name": "insertOne", "arguments": { "document": { "_id": 0, "encryptedInt": { "$numberInt": "-1" } } }, "result": { "errorContains": "value must be greater than or equal to the minimum value" } } ] }, { "description": "Insert min and max", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "local": { "key": { "$binary": { "base64": "Mng0NCt4ZHVUYUJCa1kxNkVyNUR1QURhZ2h2UzR2d2RrZzh0cFBwM3R6NmdWMDFBMUN3YkQ5aXRRMkhGRGdQV09wOGVNYUMxT2k3NjZKelhaQmRCZGJkTXVyZG9uSjFk", "subType": "00" } } } } } }, "operations": [ { "name": "insertOne", "arguments": { "document": { "_id": 0, "encryptedInt": { "$numberInt": "0" } } } }, { "name": "insertOne", "arguments": { "document": { "_id": 200, "encryptedInt": { "$numberInt": "200" } } } }, { "name": "find", "arguments": { "filter": {}, "sort": { "_id": 1 } }, "result": [ { "_id": 0, "encryptedInt": { "$numberInt": "0" } }, { "_id": 200, "encryptedInt": { "$numberInt": "200" } } ] } ] }, { "description": "Aggregate with $gte", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "local": { "key": { "$binary": { "base64": "Mng0NCt4ZHVUYUJCa1kxNkVyNUR1QURhZ2h2UzR2d2RrZzh0cFBwM3R6NmdWMDFBMUN3YkQ5aXRRMkhGRGdQV09wOGVNYUMxT2k3NjZKelhaQmRCZGJkTXVyZG9uSjFk", "subType": "00" } } } } } }, "operations": [ { "name": "insertOne", "arguments": { "document": { "_id": 0, "encryptedInt": { "$numberInt": "0" } } } }, { "name": "insertOne", "arguments": { "document": { "_id": 1, "encryptedInt": { "$numberInt": "1" } } } }, { "name": "aggregate", "arguments": { "pipeline": [ { "$match": { "encryptedInt": { "$gte": { "$numberInt": "0" } } } }, { "$sort": { "_id": 1 } } ] }, "result": [ { "_id": 0, "encryptedInt": { "$numberInt": "0" } }, { "_id": 1, "encryptedInt": { "$numberInt": "1" } } ] } ] }, { "description": "Aggregate with $gt with no results", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "local": { "key": { "$binary": { "base64": "Mng0NCt4ZHVUYUJCa1kxNkVyNUR1QURhZ2h2UzR2d2RrZzh0cFBwM3R6NmdWMDFBMUN3YkQ5aXRRMkhGRGdQV09wOGVNYUMxT2k3NjZKelhaQmRCZGJkTXVyZG9uSjFk", "subType": "00" } } } } } }, "operations": [ { "name": "insertOne", "arguments": { "document": { "_id": 0, "encryptedInt": { "$numberInt": "0" } } } }, { "name": "insertOne", "arguments": { "document": { "_id": 1, "encryptedInt": { "$numberInt": "1" } } } }, { "name": "aggregate", "arguments": { "pipeline": [ { "$match": { "encryptedInt": { "$gt": { "$numberInt": "1" } } } } ] }, "result": [] } ] }, { "description": "Aggregate with $lt", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "local": { "key": { "$binary": { "base64": "Mng0NCt4ZHVUYUJCa1kxNkVyNUR1QURhZ2h2UzR2d2RrZzh0cFBwM3R6NmdWMDFBMUN3YkQ5aXRRMkhGRGdQV09wOGVNYUMxT2k3NjZKelhaQmRCZGJkTXVyZG9uSjFk", "subType": "00" } } } } } }, "operations": [ { "name": "insertOne", "arguments": { "document": { "_id": 0, "encryptedInt": { "$numberInt": "0" } } } }, { "name": "insertOne", "arguments": { "document": { "_id": 1, "encryptedInt": { "$numberInt": "1" } } } }, { "name": "aggregate", "arguments": { "pipeline": [ { "$match": { "encryptedInt": { "$lt": { "$numberInt": "1" } } } } ] }, "result": [ { "_id": 0, "encryptedInt": { "$numberInt": "0" } } ] } ] }, { "description": "Aggregate with $lte", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "local": { "key": { "$binary": { "base64": "Mng0NCt4ZHVUYUJCa1kxNkVyNUR1QURhZ2h2UzR2d2RrZzh0cFBwM3R6NmdWMDFBMUN3YkQ5aXRRMkhGRGdQV09wOGVNYUMxT2k3NjZKelhaQmRCZGJkTXVyZG9uSjFk", "subType": "00" } } } } } }, "operations": [ { "name": "insertOne", "arguments": { "document": { "_id": 0, "encryptedInt": { "$numberInt": "0" } } } }, { "name": "insertOne", "arguments": { "document": { "_id": 1, "encryptedInt": { "$numberInt": "1" } } } }, { "name": "aggregate", "arguments": { "pipeline": [ { "$match": { "encryptedInt": { "$lte": { "$numberInt": "1" } } } }, { "$sort": { "_id": 1 } } ] }, "result": [ { "_id": 0, "encryptedInt": { "$numberInt": "0" } }, { "_id": 1, "encryptedInt": { "$numberInt": "1" } } ] } ] }, { "description": "Aggregate with $lt below min", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "local": { "key": { "$binary": { "base64": "Mng0NCt4ZHVUYUJCa1kxNkVyNUR1QURhZ2h2UzR2d2RrZzh0cFBwM3R6NmdWMDFBMUN3YkQ5aXRRMkhGRGdQV09wOGVNYUMxT2k3NjZKelhaQmRCZGJkTXVyZG9uSjFk", "subType": "00" } } } } } }, "operations": [ { "name": "insertOne", "arguments": { "document": { "_id": 0, "encryptedInt": { "$numberInt": "0" } } } }, { "name": "insertOne", "arguments": { "document": { "_id": 1, "encryptedInt": { "$numberInt": "1" } } } }, { "name": "aggregate", "arguments": { "pipeline": [ { "$match": { "encryptedInt": { "$lt": { "$numberInt": "0" } } } } ] }, "result": { "errorContains": "must be greater than the range minimum" } } ] }, { "description": "Aggregate with $gt above max", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "local": { "key": { "$binary": { "base64": "Mng0NCt4ZHVUYUJCa1kxNkVyNUR1QURhZ2h2UzR2d2RrZzh0cFBwM3R6NmdWMDFBMUN3YkQ5aXRRMkhGRGdQV09wOGVNYUMxT2k3NjZKelhaQmRCZGJkTXVyZG9uSjFk", "subType": "00" } } } } } }, "operations": [ { "name": "insertOne", "arguments": { "document": { "_id": 0, "encryptedInt": { "$numberInt": "0" } } } }, { "name": "insertOne", "arguments": { "document": { "_id": 1, "encryptedInt": { "$numberInt": "1" } } } }, { "name": "aggregate", "arguments": { "pipeline": [ { "$match": { "encryptedInt": { "$gt": { "$numberInt": "200" } } } } ] }, "result": { "errorContains": "must be less than the range maximum" } } ] }, { "description": "Aggregate with $gt and $lt", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "local": { "key": { "$binary": { "base64": "Mng0NCt4ZHVUYUJCa1kxNkVyNUR1QURhZ2h2UzR2d2RrZzh0cFBwM3R6NmdWMDFBMUN3YkQ5aXRRMkhGRGdQV09wOGVNYUMxT2k3NjZKelhaQmRCZGJkTXVyZG9uSjFk", "subType": "00" } } } } } }, "operations": [ { "name": "insertOne", "arguments": { "document": { "_id": 0, "encryptedInt": { "$numberInt": "0" } } } }, { "name": "insertOne", "arguments": { "document": { "_id": 1, "encryptedInt": { "$numberInt": "1" } } } }, { "name": "aggregate", "arguments": { "pipeline": [ { "$match": { "encryptedInt": { "$gt": { "$numberInt": "0" }, "$lt": { "$numberInt": "2" } } } } ] }, "result": [ { "_id": 1, "encryptedInt": { "$numberInt": "1" } } ] } ] }, { "description": "Aggregate with equality", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "local": { "key": { "$binary": { "base64": "Mng0NCt4ZHVUYUJCa1kxNkVyNUR1QURhZ2h2UzR2d2RrZzh0cFBwM3R6NmdWMDFBMUN3YkQ5aXRRMkhGRGdQV09wOGVNYUMxT2k3NjZKelhaQmRCZGJkTXVyZG9uSjFk", "subType": "00" } } } } } }, "operations": [ { "name": "insertOne", "arguments": { "document": { "_id": 0, "encryptedInt": { "$numberInt": "0" } } } }, { "name": "insertOne", "arguments": { "document": { "_id": 1, "encryptedInt": { "$numberInt": "1" } } } }, { "name": "aggregate", "arguments": { "pipeline": [ { "$match": { "encryptedInt": { "$numberInt": "0" } } } ] }, "result": [ { "_id": 0, "encryptedInt": { "$numberInt": "0" } } ] }, { "name": "aggregate", "arguments": { "pipeline": [ { "$match": { "encryptedInt": { "$numberInt": "1" } } } ] }, "result": [ { "_id": 1, "encryptedInt": { "$numberInt": "1" } } ] } ] }, { "description": "Aggregate with full range", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "local": { "key": { "$binary": { "base64": "Mng0NCt4ZHVUYUJCa1kxNkVyNUR1QURhZ2h2UzR2d2RrZzh0cFBwM3R6NmdWMDFBMUN3YkQ5aXRRMkhGRGdQV09wOGVNYUMxT2k3NjZKelhaQmRCZGJkTXVyZG9uSjFk", "subType": "00" } } } } } }, "operations": [ { "name": "insertOne", "arguments": { "document": { "_id": 0, "encryptedInt": { "$numberInt": "0" } } } }, { "name": "insertOne", "arguments": { "document": { "_id": 1, "encryptedInt": { "$numberInt": "1" } } } }, { "name": "aggregate", "arguments": { "pipeline": [ { "$match": { "encryptedInt": { "$gte": { "$numberInt": "0" }, "$lte": { "$numberInt": "200" } } } }, { "$sort": { "_id": 1 } } ] }, "result": [ { "_id": 0, "encryptedInt": { "$numberInt": "0" } }, { "_id": 1, "encryptedInt": { "$numberInt": "1" } } ] } ] }, { "description": "Aggregate with $in", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "local": { "key": { "$binary": { "base64": "Mng0NCt4ZHVUYUJCa1kxNkVyNUR1QURhZ2h2UzR2d2RrZzh0cFBwM3R6NmdWMDFBMUN3YkQ5aXRRMkhGRGdQV09wOGVNYUMxT2k3NjZKelhaQmRCZGJkTXVyZG9uSjFk", "subType": "00" } } } } } }, "operations": [ { "name": "insertOne", "arguments": { "document": { "_id": 0, "encryptedInt": { "$numberInt": "0" } } } }, { "name": "insertOne", "arguments": { "document": { "_id": 1, "encryptedInt": { "$numberInt": "1" } } } }, { "name": "aggregate", "arguments": { "pipeline": [ { "$match": { "encryptedInt": { "$in": [ { "$numberInt": "0" } ] } } } ] }, "result": [ { "_id": 0, "encryptedInt": { "$numberInt": "0" } } ] } ] }, { "description": "Wrong type: Insert Double", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "local": { "key": { "$binary": { "base64": "Mng0NCt4ZHVUYUJCa1kxNkVyNUR1QURhZ2h2UzR2d2RrZzh0cFBwM3R6NmdWMDFBMUN3YkQ5aXRRMkhGRGdQV09wOGVNYUMxT2k3NjZKelhaQmRCZGJkTXVyZG9uSjFk", "subType": "00" } } } } } }, "operations": [ { "name": "insertOne", "arguments": { "document": { "_id": 0, "encryptedInt": { "$numberDouble": "0" } } }, "result": { "errorContains": "cannot encrypt element" } } ] }, { "description": "Wrong type: Find Double", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "local": { "key": { "$binary": { "base64": "Mng0NCt4ZHVUYUJCa1kxNkVyNUR1QURhZ2h2UzR2d2RrZzh0cFBwM3R6NmdWMDFBMUN3YkQ5aXRRMkhGRGdQV09wOGVNYUMxT2k3NjZKelhaQmRCZGJkTXVyZG9uSjFk", "subType": "00" } } } } } }, "operations": [ { "name": "find", "arguments": { "filter": { "encryptedInt": { "$gte": { "$numberDouble": "0" } } } }, "result": { "errorContains": "field type is not supported" } } ] } ] } fle2v2-Range-Int-Delete.json000066400000000000000000000322551462766011000341070ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/client-side-encryption/spec/legacy{ "runOn": [ { "minServerVersion": "7.0.0", "topology": [ "replicaset", "sharded", "load-balanced" ] } ], "database_name": "default", "collection_name": "default", "data": [], "encrypted_fields": { "fields": [ { "keyId": { "$binary": { "base64": "EjRWeBI0mHYSNBI0VniQEg==", "subType": "04" } }, "path": "encryptedInt", "bsonType": "int", "queries": { "queryType": "rangePreview", "contention": { "$numberLong": "0" }, "sparsity": { "$numberLong": "1" }, "min": { "$numberInt": "0" }, "max": { "$numberInt": "200" } } } ] }, "key_vault_data": [ { "_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" } } ], "tests": [ { "description": "FLE2 Range Int. Delete.", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "local": { "key": { "$binary": { "base64": "Mng0NCt4ZHVUYUJCa1kxNkVyNUR1QURhZ2h2UzR2d2RrZzh0cFBwM3R6NmdWMDFBMUN3YkQ5aXRRMkhGRGdQV09wOGVNYUMxT2k3NjZKelhaQmRCZGJkTXVyZG9uSjFk", "subType": "00" } } } } } }, "operations": [ { "name": "insertOne", "arguments": { "document": { "_id": 0, "encryptedInt": { "$numberInt": "0" } } } }, { "name": "insertOne", "arguments": { "document": { "_id": 1, "encryptedInt": { "$numberInt": "1" } } } }, { "name": "deleteOne", "arguments": { "filter": { "encryptedInt": { "$gt": { "$numberInt": "0" } } } }, "result": { "deletedCount": 1 } } ], "expectations": [ { "command_started_event": { "command": { "listCollections": 1, "filter": { "name": "default" } }, "command_name": "listCollections" } }, { "command_started_event": { "command": { "find": "datakeys", "filter": { "$or": [ { "_id": { "$in": [ { "$binary": { "base64": "EjRWeBI0mHYSNBI0VniQEg==", "subType": "04" } } ] } }, { "keyAltNames": { "$in": [] } } ] }, "$db": "keyvault", "readConcern": { "level": "majority" } }, "command_name": "find" } }, { "command_started_event": { "command": { "insert": "default", "documents": [ { "_id": 0, "encryptedInt": { "$$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": "encryptedInt", "bsonType": "int", "queries": { "queryType": "rangePreview", "contention": { "$numberLong": "0" }, "sparsity": { "$numberLong": "1" }, "min": { "$numberInt": "0" }, "max": { "$numberInt": "200" } } } ] } } } }, "command_name": "insert" } }, { "command_started_event": { "command": { "insert": "default", "documents": [ { "_id": 1, "encryptedInt": { "$$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": "encryptedInt", "bsonType": "int", "queries": { "queryType": "rangePreview", "contention": { "$numberLong": "0" }, "sparsity": { "$numberLong": "1" }, "min": { "$numberInt": "0" }, "max": { "$numberInt": "200" } } } ] } } } }, "command_name": "insert" } }, { "command_started_event": { "command": { "delete": "default", "deletes": [ { "q": { "encryptedInt": { "$gt": { "$binary": { "base64": "DUkFAAADcGF5bG9hZAAZBQAABGcABQUAAAMwAH0AAAAFZAAgAAAAALGGQ/CRD+pGLD53BZzWcCcYbuGLVEyjzXIx7b+ux/q2BXMAIAAAAACOC6mXEZL27P9hethZbtKYsTXKK+FpgQ9Axxmn9N/cCwVsACAAAAAA+MFEd8XfZSpbXKqqPC2L3TEFswkaG5Ff6aSgf8p+XVIAAzEAfQAAAAVkACAAAAAAtL3QIvnZqCF72eS6lKr8ilff7R6kiNklokiTuaU5wNsFcwAgAAAAAEtqr3/X731VB+VrbFcY8ZrJKRo2E0Fd+C8L0EMNcvcCBWwAIAAAAABNPhSriux8W8qbwnhCczE3IzlhNEnGDpUwTFDZSL+eYQADMgB9AAAABWQAIAAAAAB99ZW/7KwXKzl5M3XQsAJ3JbEef90IoxFYBArNiYzlgQVzACAAAAAAYO/qaw0+92HAryxOUG7iK6hnIy3OaUA9jIqtHdvcq8YFbAAgAAAAAHrUYj8A0hVgc6VklpDiljOnykrUSfEsjm56XO/bsfKdAAMzAH0AAAAFZAAgAAAAAOK8brUuc2onBNDRtfYMR736dHj4dQqXod8JG7tAMTsDBXMAIAAAAAAW6SrGAL6Bx0s7ZlsYULFfOAiYIGhEWu6md3r+Rk40awVsACAAAAAAIHYXP8RLcCboUmHN3+OlnEw1DxaLSnbTB9PdF228fFAAAzQAfQAAAAVkACAAAAAAV22FGF7ZDwK/EYiGNMlm/QuT3saQdyJM/Fn+ZyQug1oFcwAgAAAAACo7GwCvbcs5UHQMgds9/1QMklEVdjZigpuOFGrDmmxtBWwAIAAAAADQbYYPxlCMMGe2MulbiurApFLoeJSMvTeDU3pyEA2jNwADNQB9AAAABWQAIAAAAADFspsMG7yHjKppyllon1KqAsTrHaZ6JzNqnSz8o6iTvwVzACAAAAAAeiA5pqVIQQ9s6UY/P8v5Jjkl3I7iFNeLDYehikrINrsFbAAgAAAAAFjBTzTpNxDEkA0vSRj0jCED9KDRlboMVyilKyDz5YR4AAM2AH0AAAAFZAAgAAAAAPcLmtq+V1e+MRlZ7NHq1+mrRVBQje5zj685ZvdsfKvSBXMAIAAAAABdHz/3w2k5km97QN9m7oLFYJaVJneNlMboIlz5yUASQAVsACAAAAAAWbp8JVJnx8fEVAJFa7WMfMa7wXeP5M3C8MX20J/i9n0AAzcAfQAAAAVkACAAAAAAYfLwnoxK6XAGQrJFy8+TIJoq38ldBaO75h4zA4ZX5tQFcwAgAAAAAC2wk8UcJH5X5XGnDBYmel6srpBkzBhHtt3Jw1u5TSJ1BWwAIAAAAAA9/YU9eI3D7QbXKIw/3/gzWJ6MZrCYhG0j1wNKgRQp5wADOAB9AAAABWQAIAAAAADGvyrtKkIcaV17ynZA7b2k5Pz6OhvxdWNkDvDWJIja8wVzACAAAAAAOLypVKNxf/wR1G8OZjUUsTQzDYeNNhhITxGMSp7euS4FbAAgAAAAAA9EsxoV1B2DcQ1NJRwuxXnvVR+vkD0wbbDYEI/zFEnDAAM5AH0AAAAFZAAgAAAAAEocREw1L0g+roFUchJI2Yd0M0ME2bnErNUYnpyJP1SqBXMAIAAAAAAcE2/JK/8MoSeOchIuAkKh1X3ImoA7p8ujAZIfvIDo6QVsACAAAAAA+W0+zgLr85/PD7P9a94wk6MgNgrizx/XU9aCxAkp1IwAABJjbQAAAAAAAAAAAAAQcGF5bG9hZElkAAAAAAAQZmlyc3RPcGVyYXRvcgABAAAAAA==", "subType": "06" } } } }, "limit": 1 } ], "ordered": true, "encryptionInformation": { "type": 1, "schema": { "default.default": { "escCollection": "enxcol_.default.esc", "ecocCollection": "enxcol_.default.ecoc", "fields": [ { "keyId": { "$binary": { "base64": "EjRWeBI0mHYSNBI0VniQEg==", "subType": "04" } }, "path": "encryptedInt", "bsonType": "int", "queries": { "queryType": "rangePreview", "contention": { "$numberLong": "0" }, "sparsity": { "$numberLong": "1" }, "min": { "$numberInt": "0" }, "max": { "$numberInt": "200" } } } ] } } } }, "command_name": "delete" } } ], "outcome": { "collection": { "data": [ { "_id": 0, "encryptedInt": { "$$type": "binData" }, "__safeContent__": [ { "$binary": { "base64": "5nRutVIyq7URVOVtbE4vM01APSIajAVnsShMwjBlzkM=", "subType": "00" } }, { "$binary": { "base64": "RjBYT2h3ZAoHxhf8DU6/dFbDkEBZp0IxREcsRTu2MXs=", "subType": "00" } }, { "$binary": { "base64": "x7GR49EN0t3WXQDihkrbonK7qNIBYC87tpL/XEUyIYc=", "subType": "00" } }, { "$binary": { "base64": "JfYUqWF+OoGjiYkRI4L5iPlF+T1Eleul7Fki22jp4Qc=", "subType": "00" } }, { "$binary": { "base64": "q1RyGfIgsaQHoZFRw+DD28V26rN5hweApPLwExncvT8=", "subType": "00" } }, { "$binary": { "base64": "L2PFeKGvLS6C+DLudR6fGlBq3ERPvjWvRyNRIA2HVb0=", "subType": "00" } }, { "$binary": { "base64": "CWxaNqL3iP1yCixDkcmf9bmW3E5VeN8TJkg1jJe528s=", "subType": "00" } }, { "$binary": { "base64": "+vC6araOEo+fpW7PSIP40/EnzBCj1d2N10Jr3rrXJJM=", "subType": "00" } }, { "$binary": { "base64": "6SV63Mf51Z6A6p2X3rCnJKCu6ku3Oeb45mBYbz+IoAo=", "subType": "00" } } ] } ] } } } ] } fle2v2-Range-Int-FindOneAndUpdate.json000066400000000000000000000366741462766011000360260ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/client-side-encryption/spec/legacy{ "runOn": [ { "minServerVersion": "7.0.0", "topology": [ "replicaset", "sharded", "load-balanced" ] } ], "database_name": "default", "collection_name": "default", "data": [], "encrypted_fields": { "fields": [ { "keyId": { "$binary": { "base64": "EjRWeBI0mHYSNBI0VniQEg==", "subType": "04" } }, "path": "encryptedInt", "bsonType": "int", "queries": { "queryType": "rangePreview", "contention": { "$numberLong": "0" }, "sparsity": { "$numberLong": "1" }, "min": { "$numberInt": "0" }, "max": { "$numberInt": "200" } } } ] }, "key_vault_data": [ { "_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" } } ], "tests": [ { "description": "FLE2 Range Int. FindOneAndUpdate.", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "local": { "key": { "$binary": { "base64": "Mng0NCt4ZHVUYUJCa1kxNkVyNUR1QURhZ2h2UzR2d2RrZzh0cFBwM3R6NmdWMDFBMUN3YkQ5aXRRMkhGRGdQV09wOGVNYUMxT2k3NjZKelhaQmRCZGJkTXVyZG9uSjFk", "subType": "00" } } } } } }, "operations": [ { "name": "insertOne", "arguments": { "document": { "_id": 0, "encryptedInt": { "$numberInt": "0" } } } }, { "name": "insertOne", "arguments": { "document": { "_id": 1, "encryptedInt": { "$numberInt": "1" } } } }, { "name": "findOneAndUpdate", "arguments": { "filter": { "encryptedInt": { "$gt": { "$numberInt": "0" } } }, "update": { "$set": { "encryptedInt": { "$numberInt": "2" } } }, "returnDocument": "Before" }, "result": { "_id": 1, "encryptedInt": { "$numberInt": "1" } } } ], "expectations": [ { "command_started_event": { "command": { "listCollections": 1, "filter": { "name": "default" } }, "command_name": "listCollections" } }, { "command_started_event": { "command": { "find": "datakeys", "filter": { "$or": [ { "_id": { "$in": [ { "$binary": { "base64": "EjRWeBI0mHYSNBI0VniQEg==", "subType": "04" } } ] } }, { "keyAltNames": { "$in": [] } } ] }, "$db": "keyvault", "readConcern": { "level": "majority" } }, "command_name": "find" } }, { "command_started_event": { "command": { "insert": "default", "documents": [ { "_id": 0, "encryptedInt": { "$$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": "encryptedInt", "bsonType": "int", "queries": { "queryType": "rangePreview", "contention": { "$numberLong": "0" }, "sparsity": { "$numberLong": "1" }, "min": { "$numberInt": "0" }, "max": { "$numberInt": "200" } } } ] } } } }, "command_name": "insert" } }, { "command_started_event": { "command": { "insert": "default", "documents": [ { "_id": 1, "encryptedInt": { "$$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": "encryptedInt", "bsonType": "int", "queries": { "queryType": "rangePreview", "contention": { "$numberLong": "0" }, "sparsity": { "$numberLong": "1" }, "min": { "$numberInt": "0" }, "max": { "$numberInt": "200" } } } ] } } } }, "command_name": "insert" } }, { "command_started_event": { "command": { "findAndModify": "default", "query": { "encryptedInt": { "$gt": { "$binary": { "base64": "DUkFAAADcGF5bG9hZAAZBQAABGcABQUAAAMwAH0AAAAFZAAgAAAAALGGQ/CRD+pGLD53BZzWcCcYbuGLVEyjzXIx7b+ux/q2BXMAIAAAAACOC6mXEZL27P9hethZbtKYsTXKK+FpgQ9Axxmn9N/cCwVsACAAAAAA+MFEd8XfZSpbXKqqPC2L3TEFswkaG5Ff6aSgf8p+XVIAAzEAfQAAAAVkACAAAAAAtL3QIvnZqCF72eS6lKr8ilff7R6kiNklokiTuaU5wNsFcwAgAAAAAEtqr3/X731VB+VrbFcY8ZrJKRo2E0Fd+C8L0EMNcvcCBWwAIAAAAABNPhSriux8W8qbwnhCczE3IzlhNEnGDpUwTFDZSL+eYQADMgB9AAAABWQAIAAAAAB99ZW/7KwXKzl5M3XQsAJ3JbEef90IoxFYBArNiYzlgQVzACAAAAAAYO/qaw0+92HAryxOUG7iK6hnIy3OaUA9jIqtHdvcq8YFbAAgAAAAAHrUYj8A0hVgc6VklpDiljOnykrUSfEsjm56XO/bsfKdAAMzAH0AAAAFZAAgAAAAAOK8brUuc2onBNDRtfYMR736dHj4dQqXod8JG7tAMTsDBXMAIAAAAAAW6SrGAL6Bx0s7ZlsYULFfOAiYIGhEWu6md3r+Rk40awVsACAAAAAAIHYXP8RLcCboUmHN3+OlnEw1DxaLSnbTB9PdF228fFAAAzQAfQAAAAVkACAAAAAAV22FGF7ZDwK/EYiGNMlm/QuT3saQdyJM/Fn+ZyQug1oFcwAgAAAAACo7GwCvbcs5UHQMgds9/1QMklEVdjZigpuOFGrDmmxtBWwAIAAAAADQbYYPxlCMMGe2MulbiurApFLoeJSMvTeDU3pyEA2jNwADNQB9AAAABWQAIAAAAADFspsMG7yHjKppyllon1KqAsTrHaZ6JzNqnSz8o6iTvwVzACAAAAAAeiA5pqVIQQ9s6UY/P8v5Jjkl3I7iFNeLDYehikrINrsFbAAgAAAAAFjBTzTpNxDEkA0vSRj0jCED9KDRlboMVyilKyDz5YR4AAM2AH0AAAAFZAAgAAAAAPcLmtq+V1e+MRlZ7NHq1+mrRVBQje5zj685ZvdsfKvSBXMAIAAAAABdHz/3w2k5km97QN9m7oLFYJaVJneNlMboIlz5yUASQAVsACAAAAAAWbp8JVJnx8fEVAJFa7WMfMa7wXeP5M3C8MX20J/i9n0AAzcAfQAAAAVkACAAAAAAYfLwnoxK6XAGQrJFy8+TIJoq38ldBaO75h4zA4ZX5tQFcwAgAAAAAC2wk8UcJH5X5XGnDBYmel6srpBkzBhHtt3Jw1u5TSJ1BWwAIAAAAAA9/YU9eI3D7QbXKIw/3/gzWJ6MZrCYhG0j1wNKgRQp5wADOAB9AAAABWQAIAAAAADGvyrtKkIcaV17ynZA7b2k5Pz6OhvxdWNkDvDWJIja8wVzACAAAAAAOLypVKNxf/wR1G8OZjUUsTQzDYeNNhhITxGMSp7euS4FbAAgAAAAAA9EsxoV1B2DcQ1NJRwuxXnvVR+vkD0wbbDYEI/zFEnDAAM5AH0AAAAFZAAgAAAAAEocREw1L0g+roFUchJI2Yd0M0ME2bnErNUYnpyJP1SqBXMAIAAAAAAcE2/JK/8MoSeOchIuAkKh1X3ImoA7p8ujAZIfvIDo6QVsACAAAAAA+W0+zgLr85/PD7P9a94wk6MgNgrizx/XU9aCxAkp1IwAABJjbQAAAAAAAAAAAAAQcGF5bG9hZElkAAAAAAAQZmlyc3RPcGVyYXRvcgABAAAAAA==", "subType": "06" } } } }, "update": { "$set": { "encryptedInt": { "$$type": "binData" } } }, "encryptionInformation": { "type": 1, "schema": { "default.default": { "escCollection": "enxcol_.default.esc", "ecocCollection": "enxcol_.default.ecoc", "fields": [ { "keyId": { "$binary": { "base64": "EjRWeBI0mHYSNBI0VniQEg==", "subType": "04" } }, "path": "encryptedInt", "bsonType": "int", "queries": { "queryType": "rangePreview", "contention": { "$numberLong": "0" }, "sparsity": { "$numberLong": "1" }, "min": { "$numberInt": "0" }, "max": { "$numberInt": "200" } } } ] } } } }, "command_name": "findAndModify" } } ], "outcome": { "collection": { "data": [ { "_id": 0, "encryptedInt": { "$$type": "binData" }, "__safeContent__": [ { "$binary": { "base64": "5nRutVIyq7URVOVtbE4vM01APSIajAVnsShMwjBlzkM=", "subType": "00" } }, { "$binary": { "base64": "RjBYT2h3ZAoHxhf8DU6/dFbDkEBZp0IxREcsRTu2MXs=", "subType": "00" } }, { "$binary": { "base64": "x7GR49EN0t3WXQDihkrbonK7qNIBYC87tpL/XEUyIYc=", "subType": "00" } }, { "$binary": { "base64": "JfYUqWF+OoGjiYkRI4L5iPlF+T1Eleul7Fki22jp4Qc=", "subType": "00" } }, { "$binary": { "base64": "q1RyGfIgsaQHoZFRw+DD28V26rN5hweApPLwExncvT8=", "subType": "00" } }, { "$binary": { "base64": "L2PFeKGvLS6C+DLudR6fGlBq3ERPvjWvRyNRIA2HVb0=", "subType": "00" } }, { "$binary": { "base64": "CWxaNqL3iP1yCixDkcmf9bmW3E5VeN8TJkg1jJe528s=", "subType": "00" } }, { "$binary": { "base64": "+vC6araOEo+fpW7PSIP40/EnzBCj1d2N10Jr3rrXJJM=", "subType": "00" } }, { "$binary": { "base64": "6SV63Mf51Z6A6p2X3rCnJKCu6ku3Oeb45mBYbz+IoAo=", "subType": "00" } } ] }, { "_id": 1, "encryptedInt": { "$$type": "binData" }, "__safeContent__": [ { "$binary": { "base64": "DLCAJs+W2PL2DV5YChCL6dYrQNr+j4p3L7xhVaub4ic=", "subType": "00" } }, { "$binary": { "base64": "hyDcE6QQjPrYJaIS/n7evEZFYcm31Tj89CpEYGF45cI=", "subType": "00" } }, { "$binary": { "base64": "F08nMDWDZc+DbWM7XCEJNNCEYyinRmrvGP7EWhmp4is=", "subType": "00" } }, { "$binary": { "base64": "cXH4688amcDc8kZOJq4UP8cE3R58Zl7e+Qo/1jyspps=", "subType": "00" } }, { "$binary": { "base64": "uURBxvTp3FBCVkd+LPqyuY7d6rMW6SGIJQEPY/wtkZI=", "subType": "00" } }, { "$binary": { "base64": "jG3hax1L3RBp9t38vUt53FsBxgr/+Si/vVISpAylYpE=", "subType": "00" } }, { "$binary": { "base64": "kwtIW8MhH9Ky5xNjBx8gFA/SHh2YVphie7g5FGBzals=", "subType": "00" } }, { "$binary": { "base64": "FHflwFuEMu4xX0ZApHi+pdlBH+oevAtXckCUb5Wv0xU=", "subType": "00" } }, { "$binary": { "base64": "ty4cnzJdAlbQKnh7px3GEYjBnvO+jIOaKjoTRDtmh3M=", "subType": "00" } } ] } ] } } } ] } fle2v2-Range-Int-InsertFind.json000066400000000000000000000360741462766011000347550ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/client-side-encryption/spec/legacy{ "runOn": [ { "minServerVersion": "7.0.0", "topology": [ "replicaset", "sharded", "load-balanced" ] } ], "database_name": "default", "collection_name": "default", "data": [], "encrypted_fields": { "fields": [ { "keyId": { "$binary": { "base64": "EjRWeBI0mHYSNBI0VniQEg==", "subType": "04" } }, "path": "encryptedInt", "bsonType": "int", "queries": { "queryType": "rangePreview", "contention": { "$numberLong": "0" }, "sparsity": { "$numberLong": "1" }, "min": { "$numberInt": "0" }, "max": { "$numberInt": "200" } } } ] }, "key_vault_data": [ { "_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" } } ], "tests": [ { "description": "FLE2 Range Int. Insert and Find.", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "local": { "key": { "$binary": { "base64": "Mng0NCt4ZHVUYUJCa1kxNkVyNUR1QURhZ2h2UzR2d2RrZzh0cFBwM3R6NmdWMDFBMUN3YkQ5aXRRMkhGRGdQV09wOGVNYUMxT2k3NjZKelhaQmRCZGJkTXVyZG9uSjFk", "subType": "00" } } } } } }, "operations": [ { "name": "insertOne", "arguments": { "document": { "_id": 0, "encryptedInt": { "$numberInt": "0" } } } }, { "name": "insertOne", "arguments": { "document": { "_id": 1, "encryptedInt": { "$numberInt": "1" } } } }, { "name": "find", "arguments": { "filter": { "encryptedInt": { "$gt": { "$numberInt": "0" } } } }, "result": [ { "_id": 1, "encryptedInt": { "$numberInt": "1" } } ] } ], "expectations": [ { "command_started_event": { "command": { "listCollections": 1, "filter": { "name": "default" } }, "command_name": "listCollections" } }, { "command_started_event": { "command": { "find": "datakeys", "filter": { "$or": [ { "_id": { "$in": [ { "$binary": { "base64": "EjRWeBI0mHYSNBI0VniQEg==", "subType": "04" } } ] } }, { "keyAltNames": { "$in": [] } } ] }, "$db": "keyvault", "readConcern": { "level": "majority" } }, "command_name": "find" } }, { "command_started_event": { "command": { "insert": "default", "documents": [ { "_id": 0, "encryptedInt": { "$$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": "encryptedInt", "bsonType": "int", "queries": { "queryType": "rangePreview", "contention": { "$numberLong": "0" }, "sparsity": { "$numberLong": "1" }, "min": { "$numberInt": "0" }, "max": { "$numberInt": "200" } } } ] } } } }, "command_name": "insert" } }, { "command_started_event": { "command": { "insert": "default", "documents": [ { "_id": 1, "encryptedInt": { "$$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": "encryptedInt", "bsonType": "int", "queries": { "queryType": "rangePreview", "contention": { "$numberLong": "0" }, "sparsity": { "$numberLong": "1" }, "min": { "$numberInt": "0" }, "max": { "$numberInt": "200" } } } ] } } } }, "command_name": "insert" } }, { "command_started_event": { "command": { "find": "default", "filter": { "encryptedInt": { "$gt": { "$binary": { "base64": "DUkFAAADcGF5bG9hZAAZBQAABGcABQUAAAMwAH0AAAAFZAAgAAAAALGGQ/CRD+pGLD53BZzWcCcYbuGLVEyjzXIx7b+ux/q2BXMAIAAAAACOC6mXEZL27P9hethZbtKYsTXKK+FpgQ9Axxmn9N/cCwVsACAAAAAA+MFEd8XfZSpbXKqqPC2L3TEFswkaG5Ff6aSgf8p+XVIAAzEAfQAAAAVkACAAAAAAtL3QIvnZqCF72eS6lKr8ilff7R6kiNklokiTuaU5wNsFcwAgAAAAAEtqr3/X731VB+VrbFcY8ZrJKRo2E0Fd+C8L0EMNcvcCBWwAIAAAAABNPhSriux8W8qbwnhCczE3IzlhNEnGDpUwTFDZSL+eYQADMgB9AAAABWQAIAAAAAB99ZW/7KwXKzl5M3XQsAJ3JbEef90IoxFYBArNiYzlgQVzACAAAAAAYO/qaw0+92HAryxOUG7iK6hnIy3OaUA9jIqtHdvcq8YFbAAgAAAAAHrUYj8A0hVgc6VklpDiljOnykrUSfEsjm56XO/bsfKdAAMzAH0AAAAFZAAgAAAAAOK8brUuc2onBNDRtfYMR736dHj4dQqXod8JG7tAMTsDBXMAIAAAAAAW6SrGAL6Bx0s7ZlsYULFfOAiYIGhEWu6md3r+Rk40awVsACAAAAAAIHYXP8RLcCboUmHN3+OlnEw1DxaLSnbTB9PdF228fFAAAzQAfQAAAAVkACAAAAAAV22FGF7ZDwK/EYiGNMlm/QuT3saQdyJM/Fn+ZyQug1oFcwAgAAAAACo7GwCvbcs5UHQMgds9/1QMklEVdjZigpuOFGrDmmxtBWwAIAAAAADQbYYPxlCMMGe2MulbiurApFLoeJSMvTeDU3pyEA2jNwADNQB9AAAABWQAIAAAAADFspsMG7yHjKppyllon1KqAsTrHaZ6JzNqnSz8o6iTvwVzACAAAAAAeiA5pqVIQQ9s6UY/P8v5Jjkl3I7iFNeLDYehikrINrsFbAAgAAAAAFjBTzTpNxDEkA0vSRj0jCED9KDRlboMVyilKyDz5YR4AAM2AH0AAAAFZAAgAAAAAPcLmtq+V1e+MRlZ7NHq1+mrRVBQje5zj685ZvdsfKvSBXMAIAAAAABdHz/3w2k5km97QN9m7oLFYJaVJneNlMboIlz5yUASQAVsACAAAAAAWbp8JVJnx8fEVAJFa7WMfMa7wXeP5M3C8MX20J/i9n0AAzcAfQAAAAVkACAAAAAAYfLwnoxK6XAGQrJFy8+TIJoq38ldBaO75h4zA4ZX5tQFcwAgAAAAAC2wk8UcJH5X5XGnDBYmel6srpBkzBhHtt3Jw1u5TSJ1BWwAIAAAAAA9/YU9eI3D7QbXKIw/3/gzWJ6MZrCYhG0j1wNKgRQp5wADOAB9AAAABWQAIAAAAADGvyrtKkIcaV17ynZA7b2k5Pz6OhvxdWNkDvDWJIja8wVzACAAAAAAOLypVKNxf/wR1G8OZjUUsTQzDYeNNhhITxGMSp7euS4FbAAgAAAAAA9EsxoV1B2DcQ1NJRwuxXnvVR+vkD0wbbDYEI/zFEnDAAM5AH0AAAAFZAAgAAAAAEocREw1L0g+roFUchJI2Yd0M0ME2bnErNUYnpyJP1SqBXMAIAAAAAAcE2/JK/8MoSeOchIuAkKh1X3ImoA7p8ujAZIfvIDo6QVsACAAAAAA+W0+zgLr85/PD7P9a94wk6MgNgrizx/XU9aCxAkp1IwAABJjbQAAAAAAAAAAAAAQcGF5bG9hZElkAAAAAAAQZmlyc3RPcGVyYXRvcgABAAAAAA==", "subType": "06" } } } }, "encryptionInformation": { "type": 1, "schema": { "default.default": { "escCollection": "enxcol_.default.esc", "ecocCollection": "enxcol_.default.ecoc", "fields": [ { "keyId": { "$binary": { "base64": "EjRWeBI0mHYSNBI0VniQEg==", "subType": "04" } }, "path": "encryptedInt", "bsonType": "int", "queries": { "queryType": "rangePreview", "contention": { "$numberLong": "0" }, "sparsity": { "$numberLong": "1" }, "min": { "$numberInt": "0" }, "max": { "$numberInt": "200" } } } ] } } } }, "command_name": "find" } } ], "outcome": { "collection": { "data": [ { "_id": 0, "encryptedInt": { "$$type": "binData" }, "__safeContent__": [ { "$binary": { "base64": "5nRutVIyq7URVOVtbE4vM01APSIajAVnsShMwjBlzkM=", "subType": "00" } }, { "$binary": { "base64": "RjBYT2h3ZAoHxhf8DU6/dFbDkEBZp0IxREcsRTu2MXs=", "subType": "00" } }, { "$binary": { "base64": "x7GR49EN0t3WXQDihkrbonK7qNIBYC87tpL/XEUyIYc=", "subType": "00" } }, { "$binary": { "base64": "JfYUqWF+OoGjiYkRI4L5iPlF+T1Eleul7Fki22jp4Qc=", "subType": "00" } }, { "$binary": { "base64": "q1RyGfIgsaQHoZFRw+DD28V26rN5hweApPLwExncvT8=", "subType": "00" } }, { "$binary": { "base64": "L2PFeKGvLS6C+DLudR6fGlBq3ERPvjWvRyNRIA2HVb0=", "subType": "00" } }, { "$binary": { "base64": "CWxaNqL3iP1yCixDkcmf9bmW3E5VeN8TJkg1jJe528s=", "subType": "00" } }, { "$binary": { "base64": "+vC6araOEo+fpW7PSIP40/EnzBCj1d2N10Jr3rrXJJM=", "subType": "00" } }, { "$binary": { "base64": "6SV63Mf51Z6A6p2X3rCnJKCu6ku3Oeb45mBYbz+IoAo=", "subType": "00" } } ] }, { "_id": 1, "encryptedInt": { "$$type": "binData" }, "__safeContent__": [ { "$binary": { "base64": "bE1vqWj3KNyM7cCYUv/cnYm8BPaUL3eMp5syTHq6NF4=", "subType": "00" } }, { "$binary": { "base64": "25j9sQXZCihCmHKvTHgaBsAVZFcGPn7JjHdrCGlwyyw=", "subType": "00" } }, { "$binary": { "base64": "FA74j21GUEJb1DJBOpR9nVnjaDZnd8yAQNuaW9Qi26g=", "subType": "00" } }, { "$binary": { "base64": "kJv//KVkbrobIBf+QeWC5jxn20mx/P0R1N6aCSMgKM8=", "subType": "00" } }, { "$binary": { "base64": "zB+Whi9IUUGxfLEe+lGuIzLX4LFbIhaIAm5lRk65QTc=", "subType": "00" } }, { "$binary": { "base64": "ybO1QU3CgvhO8JgRXH+HxKszWcpl5aGDYYVa75fHa1g=", "subType": "00" } }, { "$binary": { "base64": "X3Y3eSAbbMg//JgiHHiFpYOpV61t8kkDexI+CQyitH4=", "subType": "00" } }, { "$binary": { "base64": "SlNHXyqVFGDPrX/2ppwog6l4pwj3PKda2TkZbqgfSfA=", "subType": "00" } }, { "$binary": { "base64": "McjV8xwTF3xI7863DYOBdyvIv6UpzThl6v9vBRk05bI=", "subType": "00" } } ] } ] } } } ] } fle2v2-Range-Int-Update.json000066400000000000000000000370721462766011000341310ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/client-side-encryption/spec/legacy{ "runOn": [ { "minServerVersion": "7.0.0", "topology": [ "replicaset", "sharded", "load-balanced" ] } ], "database_name": "default", "collection_name": "default", "data": [], "encrypted_fields": { "fields": [ { "keyId": { "$binary": { "base64": "EjRWeBI0mHYSNBI0VniQEg==", "subType": "04" } }, "path": "encryptedInt", "bsonType": "int", "queries": { "queryType": "rangePreview", "contention": { "$numberLong": "0" }, "sparsity": { "$numberLong": "1" }, "min": { "$numberInt": "0" }, "max": { "$numberInt": "200" } } } ] }, "key_vault_data": [ { "_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" } } ], "tests": [ { "description": "FLE2 Range Int. Update.", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "local": { "key": { "$binary": { "base64": "Mng0NCt4ZHVUYUJCa1kxNkVyNUR1QURhZ2h2UzR2d2RrZzh0cFBwM3R6NmdWMDFBMUN3YkQ5aXRRMkhGRGdQV09wOGVNYUMxT2k3NjZKelhaQmRCZGJkTXVyZG9uSjFk", "subType": "00" } } } } } }, "operations": [ { "name": "insertOne", "arguments": { "document": { "_id": 0, "encryptedInt": { "$numberInt": "0" } } } }, { "name": "insertOne", "arguments": { "document": { "_id": 1, "encryptedInt": { "$numberInt": "1" } } } }, { "name": "updateOne", "arguments": { "filter": { "encryptedInt": { "$gt": { "$numberInt": "0" } } }, "update": { "$set": { "encryptedInt": { "$numberInt": "2" } } } }, "result": { "matchedCount": 1, "modifiedCount": 1, "upsertedCount": 0 } } ], "expectations": [ { "command_started_event": { "command": { "listCollections": 1, "filter": { "name": "default" } }, "command_name": "listCollections" } }, { "command_started_event": { "command": { "find": "datakeys", "filter": { "$or": [ { "_id": { "$in": [ { "$binary": { "base64": "EjRWeBI0mHYSNBI0VniQEg==", "subType": "04" } } ] } }, { "keyAltNames": { "$in": [] } } ] }, "$db": "keyvault", "readConcern": { "level": "majority" } }, "command_name": "find" } }, { "command_started_event": { "command": { "insert": "default", "documents": [ { "_id": 0, "encryptedInt": { "$$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": "encryptedInt", "bsonType": "int", "queries": { "queryType": "rangePreview", "contention": { "$numberLong": "0" }, "sparsity": { "$numberLong": "1" }, "min": { "$numberInt": "0" }, "max": { "$numberInt": "200" } } } ] } } } }, "command_name": "insert" } }, { "command_started_event": { "command": { "insert": "default", "documents": [ { "_id": 1, "encryptedInt": { "$$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": "encryptedInt", "bsonType": "int", "queries": { "queryType": "rangePreview", "contention": { "$numberLong": "0" }, "sparsity": { "$numberLong": "1" }, "min": { "$numberInt": "0" }, "max": { "$numberInt": "200" } } } ] } } } }, "command_name": "insert" } }, { "command_started_event": { "command_name": "update", "command": { "update": "default", "ordered": true, "updates": [ { "q": { "encryptedInt": { "$gt": { "$binary": { "base64": "DUkFAAADcGF5bG9hZAAZBQAABGcABQUAAAMwAH0AAAAFZAAgAAAAALGGQ/CRD+pGLD53BZzWcCcYbuGLVEyjzXIx7b+ux/q2BXMAIAAAAACOC6mXEZL27P9hethZbtKYsTXKK+FpgQ9Axxmn9N/cCwVsACAAAAAA+MFEd8XfZSpbXKqqPC2L3TEFswkaG5Ff6aSgf8p+XVIAAzEAfQAAAAVkACAAAAAAtL3QIvnZqCF72eS6lKr8ilff7R6kiNklokiTuaU5wNsFcwAgAAAAAEtqr3/X731VB+VrbFcY8ZrJKRo2E0Fd+C8L0EMNcvcCBWwAIAAAAABNPhSriux8W8qbwnhCczE3IzlhNEnGDpUwTFDZSL+eYQADMgB9AAAABWQAIAAAAAB99ZW/7KwXKzl5M3XQsAJ3JbEef90IoxFYBArNiYzlgQVzACAAAAAAYO/qaw0+92HAryxOUG7iK6hnIy3OaUA9jIqtHdvcq8YFbAAgAAAAAHrUYj8A0hVgc6VklpDiljOnykrUSfEsjm56XO/bsfKdAAMzAH0AAAAFZAAgAAAAAOK8brUuc2onBNDRtfYMR736dHj4dQqXod8JG7tAMTsDBXMAIAAAAAAW6SrGAL6Bx0s7ZlsYULFfOAiYIGhEWu6md3r+Rk40awVsACAAAAAAIHYXP8RLcCboUmHN3+OlnEw1DxaLSnbTB9PdF228fFAAAzQAfQAAAAVkACAAAAAAV22FGF7ZDwK/EYiGNMlm/QuT3saQdyJM/Fn+ZyQug1oFcwAgAAAAACo7GwCvbcs5UHQMgds9/1QMklEVdjZigpuOFGrDmmxtBWwAIAAAAADQbYYPxlCMMGe2MulbiurApFLoeJSMvTeDU3pyEA2jNwADNQB9AAAABWQAIAAAAADFspsMG7yHjKppyllon1KqAsTrHaZ6JzNqnSz8o6iTvwVzACAAAAAAeiA5pqVIQQ9s6UY/P8v5Jjkl3I7iFNeLDYehikrINrsFbAAgAAAAAFjBTzTpNxDEkA0vSRj0jCED9KDRlboMVyilKyDz5YR4AAM2AH0AAAAFZAAgAAAAAPcLmtq+V1e+MRlZ7NHq1+mrRVBQje5zj685ZvdsfKvSBXMAIAAAAABdHz/3w2k5km97QN9m7oLFYJaVJneNlMboIlz5yUASQAVsACAAAAAAWbp8JVJnx8fEVAJFa7WMfMa7wXeP5M3C8MX20J/i9n0AAzcAfQAAAAVkACAAAAAAYfLwnoxK6XAGQrJFy8+TIJoq38ldBaO75h4zA4ZX5tQFcwAgAAAAAC2wk8UcJH5X5XGnDBYmel6srpBkzBhHtt3Jw1u5TSJ1BWwAIAAAAAA9/YU9eI3D7QbXKIw/3/gzWJ6MZrCYhG0j1wNKgRQp5wADOAB9AAAABWQAIAAAAADGvyrtKkIcaV17ynZA7b2k5Pz6OhvxdWNkDvDWJIja8wVzACAAAAAAOLypVKNxf/wR1G8OZjUUsTQzDYeNNhhITxGMSp7euS4FbAAgAAAAAA9EsxoV1B2DcQ1NJRwuxXnvVR+vkD0wbbDYEI/zFEnDAAM5AH0AAAAFZAAgAAAAAEocREw1L0g+roFUchJI2Yd0M0ME2bnErNUYnpyJP1SqBXMAIAAAAAAcE2/JK/8MoSeOchIuAkKh1X3ImoA7p8ujAZIfvIDo6QVsACAAAAAA+W0+zgLr85/PD7P9a94wk6MgNgrizx/XU9aCxAkp1IwAABJjbQAAAAAAAAAAAAAQcGF5bG9hZElkAAAAAAAQZmlyc3RPcGVyYXRvcgABAAAAAA==", "subType": "06" } } } }, "u": { "$set": { "encryptedInt": { "$$type": "binData" } } } } ], "encryptionInformation": { "type": 1, "schema": { "default.default": { "escCollection": "enxcol_.default.esc", "ecocCollection": "enxcol_.default.ecoc", "fields": [ { "keyId": { "$binary": { "base64": "EjRWeBI0mHYSNBI0VniQEg==", "subType": "04" } }, "path": "encryptedInt", "bsonType": "int", "queries": { "queryType": "rangePreview", "contention": { "$numberLong": "0" }, "sparsity": { "$numberLong": "1" }, "min": { "$numberInt": "0" }, "max": { "$numberInt": "200" } } } ] } } }, "$db": "default" } } } ], "outcome": { "collection": { "data": [ { "_id": 0, "encryptedInt": { "$$type": "binData" }, "__safeContent__": [ { "$binary": { "base64": "5nRutVIyq7URVOVtbE4vM01APSIajAVnsShMwjBlzkM=", "subType": "00" } }, { "$binary": { "base64": "RjBYT2h3ZAoHxhf8DU6/dFbDkEBZp0IxREcsRTu2MXs=", "subType": "00" } }, { "$binary": { "base64": "x7GR49EN0t3WXQDihkrbonK7qNIBYC87tpL/XEUyIYc=", "subType": "00" } }, { "$binary": { "base64": "JfYUqWF+OoGjiYkRI4L5iPlF+T1Eleul7Fki22jp4Qc=", "subType": "00" } }, { "$binary": { "base64": "q1RyGfIgsaQHoZFRw+DD28V26rN5hweApPLwExncvT8=", "subType": "00" } }, { "$binary": { "base64": "L2PFeKGvLS6C+DLudR6fGlBq3ERPvjWvRyNRIA2HVb0=", "subType": "00" } }, { "$binary": { "base64": "CWxaNqL3iP1yCixDkcmf9bmW3E5VeN8TJkg1jJe528s=", "subType": "00" } }, { "$binary": { "base64": "+vC6araOEo+fpW7PSIP40/EnzBCj1d2N10Jr3rrXJJM=", "subType": "00" } }, { "$binary": { "base64": "6SV63Mf51Z6A6p2X3rCnJKCu6ku3Oeb45mBYbz+IoAo=", "subType": "00" } } ] }, { "_id": 1, "encryptedInt": { "$$type": "binData" }, "__safeContent__": [ { "$binary": { "base64": "DLCAJs+W2PL2DV5YChCL6dYrQNr+j4p3L7xhVaub4ic=", "subType": "00" } }, { "$binary": { "base64": "hyDcE6QQjPrYJaIS/n7evEZFYcm31Tj89CpEYGF45cI=", "subType": "00" } }, { "$binary": { "base64": "F08nMDWDZc+DbWM7XCEJNNCEYyinRmrvGP7EWhmp4is=", "subType": "00" } }, { "$binary": { "base64": "cXH4688amcDc8kZOJq4UP8cE3R58Zl7e+Qo/1jyspps=", "subType": "00" } }, { "$binary": { "base64": "uURBxvTp3FBCVkd+LPqyuY7d6rMW6SGIJQEPY/wtkZI=", "subType": "00" } }, { "$binary": { "base64": "jG3hax1L3RBp9t38vUt53FsBxgr/+Si/vVISpAylYpE=", "subType": "00" } }, { "$binary": { "base64": "kwtIW8MhH9Ky5xNjBx8gFA/SHh2YVphie7g5FGBzals=", "subType": "00" } }, { "$binary": { "base64": "FHflwFuEMu4xX0ZApHi+pdlBH+oevAtXckCUb5Wv0xU=", "subType": "00" } }, { "$binary": { "base64": "ty4cnzJdAlbQKnh7px3GEYjBnvO+jIOaKjoTRDtmh3M=", "subType": "00" } } ] } ] } } } ] } fle2v2-Range-Long-Aggregate.json000066400000000000000000000365331462766011000347430ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/client-side-encryption/spec/legacy{ "runOn": [ { "minServerVersion": "7.0.0", "topology": [ "replicaset", "sharded", "load-balanced" ] } ], "database_name": "default", "collection_name": "default", "data": [], "encrypted_fields": { "fields": [ { "keyId": { "$binary": { "base64": "EjRWeBI0mHYSNBI0VniQEg==", "subType": "04" } }, "path": "encryptedLong", "bsonType": "long", "queries": { "queryType": "rangePreview", "contention": { "$numberLong": "0" }, "sparsity": { "$numberLong": "1" }, "min": { "$numberLong": "0" }, "max": { "$numberLong": "200" } } } ] }, "key_vault_data": [ { "_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" } } ], "tests": [ { "description": "FLE2 Range Long. Aggregate.", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "local": { "key": { "$binary": { "base64": "Mng0NCt4ZHVUYUJCa1kxNkVyNUR1QURhZ2h2UzR2d2RrZzh0cFBwM3R6NmdWMDFBMUN3YkQ5aXRRMkhGRGdQV09wOGVNYUMxT2k3NjZKelhaQmRCZGJkTXVyZG9uSjFk", "subType": "00" } } } } } }, "operations": [ { "name": "insertOne", "arguments": { "document": { "_id": 0, "encryptedLong": { "$numberLong": "0" } } } }, { "name": "insertOne", "arguments": { "document": { "_id": 1, "encryptedLong": { "$numberLong": "1" } } } }, { "name": "aggregate", "arguments": { "pipeline": [ { "$match": { "encryptedLong": { "$gt": { "$numberLong": "0" } } } } ] }, "result": [ { "_id": 1, "encryptedLong": { "$numberLong": "1" } } ] } ], "expectations": [ { "command_started_event": { "command": { "listCollections": 1, "filter": { "name": "default" } }, "command_name": "listCollections" } }, { "command_started_event": { "command": { "find": "datakeys", "filter": { "$or": [ { "_id": { "$in": [ { "$binary": { "base64": "EjRWeBI0mHYSNBI0VniQEg==", "subType": "04" } } ] } }, { "keyAltNames": { "$in": [] } } ] }, "$db": "keyvault", "readConcern": { "level": "majority" } }, "command_name": "find" } }, { "command_started_event": { "command": { "insert": "default", "documents": [ { "_id": 0, "encryptedLong": { "$$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": "encryptedLong", "bsonType": "long", "queries": { "queryType": "rangePreview", "contention": { "$numberLong": "0" }, "sparsity": { "$numberLong": "1" }, "min": { "$numberLong": "0" }, "max": { "$numberLong": "200" } } } ] } } } }, "command_name": "insert" } }, { "command_started_event": { "command": { "insert": "default", "documents": [ { "_id": 1, "encryptedLong": { "$$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": "encryptedLong", "bsonType": "long", "queries": { "queryType": "rangePreview", "contention": { "$numberLong": "0" }, "sparsity": { "$numberLong": "1" }, "min": { "$numberLong": "0" }, "max": { "$numberLong": "200" } } } ] } } } }, "command_name": "insert" } }, { "command_started_event": { "command": { "aggregate": "default", "pipeline": [ { "$match": { "encryptedLong": { "$gt": { "$binary": { "base64": "DUkFAAADcGF5bG9hZAAZBQAABGcABQUAAAMwAH0AAAAFZAAgAAAAALGGQ/CRD+pGLD53BZzWcCcYbuGLVEyjzXIx7b+ux/q2BXMAIAAAAACOC6mXEZL27P9hethZbtKYsTXKK+FpgQ9Axxmn9N/cCwVsACAAAAAA+MFEd8XfZSpbXKqqPC2L3TEFswkaG5Ff6aSgf8p+XVIAAzEAfQAAAAVkACAAAAAAtL3QIvnZqCF72eS6lKr8ilff7R6kiNklokiTuaU5wNsFcwAgAAAAAEtqr3/X731VB+VrbFcY8ZrJKRo2E0Fd+C8L0EMNcvcCBWwAIAAAAABNPhSriux8W8qbwnhCczE3IzlhNEnGDpUwTFDZSL+eYQADMgB9AAAABWQAIAAAAAB99ZW/7KwXKzl5M3XQsAJ3JbEef90IoxFYBArNiYzlgQVzACAAAAAAYO/qaw0+92HAryxOUG7iK6hnIy3OaUA9jIqtHdvcq8YFbAAgAAAAAHrUYj8A0hVgc6VklpDiljOnykrUSfEsjm56XO/bsfKdAAMzAH0AAAAFZAAgAAAAAOK8brUuc2onBNDRtfYMR736dHj4dQqXod8JG7tAMTsDBXMAIAAAAAAW6SrGAL6Bx0s7ZlsYULFfOAiYIGhEWu6md3r+Rk40awVsACAAAAAAIHYXP8RLcCboUmHN3+OlnEw1DxaLSnbTB9PdF228fFAAAzQAfQAAAAVkACAAAAAAV22FGF7ZDwK/EYiGNMlm/QuT3saQdyJM/Fn+ZyQug1oFcwAgAAAAACo7GwCvbcs5UHQMgds9/1QMklEVdjZigpuOFGrDmmxtBWwAIAAAAADQbYYPxlCMMGe2MulbiurApFLoeJSMvTeDU3pyEA2jNwADNQB9AAAABWQAIAAAAADFspsMG7yHjKppyllon1KqAsTrHaZ6JzNqnSz8o6iTvwVzACAAAAAAeiA5pqVIQQ9s6UY/P8v5Jjkl3I7iFNeLDYehikrINrsFbAAgAAAAAFjBTzTpNxDEkA0vSRj0jCED9KDRlboMVyilKyDz5YR4AAM2AH0AAAAFZAAgAAAAAPcLmtq+V1e+MRlZ7NHq1+mrRVBQje5zj685ZvdsfKvSBXMAIAAAAABdHz/3w2k5km97QN9m7oLFYJaVJneNlMboIlz5yUASQAVsACAAAAAAWbp8JVJnx8fEVAJFa7WMfMa7wXeP5M3C8MX20J/i9n0AAzcAfQAAAAVkACAAAAAAYfLwnoxK6XAGQrJFy8+TIJoq38ldBaO75h4zA4ZX5tQFcwAgAAAAAC2wk8UcJH5X5XGnDBYmel6srpBkzBhHtt3Jw1u5TSJ1BWwAIAAAAAA9/YU9eI3D7QbXKIw/3/gzWJ6MZrCYhG0j1wNKgRQp5wADOAB9AAAABWQAIAAAAADGvyrtKkIcaV17ynZA7b2k5Pz6OhvxdWNkDvDWJIja8wVzACAAAAAAOLypVKNxf/wR1G8OZjUUsTQzDYeNNhhITxGMSp7euS4FbAAgAAAAAA9EsxoV1B2DcQ1NJRwuxXnvVR+vkD0wbbDYEI/zFEnDAAM5AH0AAAAFZAAgAAAAAEocREw1L0g+roFUchJI2Yd0M0ME2bnErNUYnpyJP1SqBXMAIAAAAAAcE2/JK/8MoSeOchIuAkKh1X3ImoA7p8ujAZIfvIDo6QVsACAAAAAA+W0+zgLr85/PD7P9a94wk6MgNgrizx/XU9aCxAkp1IwAABJjbQAAAAAAAAAAAAAQcGF5bG9hZElkAAAAAAAQZmlyc3RPcGVyYXRvcgABAAAAAA==", "subType": "06" } } } } } ], "cursor": {}, "encryptionInformation": { "type": 1, "schema": { "default.default": { "escCollection": "enxcol_.default.esc", "ecocCollection": "enxcol_.default.ecoc", "fields": [ { "keyId": { "$binary": { "base64": "EjRWeBI0mHYSNBI0VniQEg==", "subType": "04" } }, "path": "encryptedLong", "bsonType": "long", "queries": { "queryType": "rangePreview", "contention": { "$numberLong": "0" }, "sparsity": { "$numberLong": "1" }, "min": { "$numberLong": "0" }, "max": { "$numberLong": "200" } } } ] } } } }, "command_name": "aggregate" } } ], "outcome": { "collection": { "data": [ { "_id": 0, "encryptedLong": { "$$type": "binData" }, "__safeContent__": [ { "$binary": { "base64": "5nRutVIyq7URVOVtbE4vM01APSIajAVnsShMwjBlzkM=", "subType": "00" } }, { "$binary": { "base64": "RjBYT2h3ZAoHxhf8DU6/dFbDkEBZp0IxREcsRTu2MXs=", "subType": "00" } }, { "$binary": { "base64": "x7GR49EN0t3WXQDihkrbonK7qNIBYC87tpL/XEUyIYc=", "subType": "00" } }, { "$binary": { "base64": "JfYUqWF+OoGjiYkRI4L5iPlF+T1Eleul7Fki22jp4Qc=", "subType": "00" } }, { "$binary": { "base64": "q1RyGfIgsaQHoZFRw+DD28V26rN5hweApPLwExncvT8=", "subType": "00" } }, { "$binary": { "base64": "L2PFeKGvLS6C+DLudR6fGlBq3ERPvjWvRyNRIA2HVb0=", "subType": "00" } }, { "$binary": { "base64": "CWxaNqL3iP1yCixDkcmf9bmW3E5VeN8TJkg1jJe528s=", "subType": "00" } }, { "$binary": { "base64": "+vC6araOEo+fpW7PSIP40/EnzBCj1d2N10Jr3rrXJJM=", "subType": "00" } }, { "$binary": { "base64": "6SV63Mf51Z6A6p2X3rCnJKCu6ku3Oeb45mBYbz+IoAo=", "subType": "00" } } ] }, { "_id": 1, "encryptedLong": { "$$type": "binData" }, "__safeContent__": [ { "$binary": { "base64": "bE1vqWj3KNyM7cCYUv/cnYm8BPaUL3eMp5syTHq6NF4=", "subType": "00" } }, { "$binary": { "base64": "25j9sQXZCihCmHKvTHgaBsAVZFcGPn7JjHdrCGlwyyw=", "subType": "00" } }, { "$binary": { "base64": "FA74j21GUEJb1DJBOpR9nVnjaDZnd8yAQNuaW9Qi26g=", "subType": "00" } }, { "$binary": { "base64": "kJv//KVkbrobIBf+QeWC5jxn20mx/P0R1N6aCSMgKM8=", "subType": "00" } }, { "$binary": { "base64": "zB+Whi9IUUGxfLEe+lGuIzLX4LFbIhaIAm5lRk65QTc=", "subType": "00" } }, { "$binary": { "base64": "ybO1QU3CgvhO8JgRXH+HxKszWcpl5aGDYYVa75fHa1g=", "subType": "00" } }, { "$binary": { "base64": "X3Y3eSAbbMg//JgiHHiFpYOpV61t8kkDexI+CQyitH4=", "subType": "00" } }, { "$binary": { "base64": "SlNHXyqVFGDPrX/2ppwog6l4pwj3PKda2TkZbqgfSfA=", "subType": "00" } }, { "$binary": { "base64": "McjV8xwTF3xI7863DYOBdyvIv6UpzThl6v9vBRk05bI=", "subType": "00" } } ] } ] } } } ] } fle2v2-Range-Long-Correctness.json000066400000000000000000001130541462766011000353410ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/client-side-encryption/spec/legacy{ "runOn": [ { "minServerVersion": "7.0.0", "topology": [ "replicaset", "sharded", "load-balanced" ] } ], "database_name": "default", "collection_name": "default", "data": [], "encrypted_fields": { "fields": [ { "keyId": { "$binary": { "base64": "EjRWeBI0mHYSNBI0VniQEg==", "subType": "04" } }, "path": "encryptedLong", "bsonType": "long", "queries": { "queryType": "rangePreview", "contention": { "$numberLong": "0" }, "sparsity": { "$numberLong": "1" }, "min": { "$numberLong": "0" }, "max": { "$numberLong": "200" } } } ] }, "key_vault_data": [ { "_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" } } ], "tests": [ { "description": "Find with $gt", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "local": { "key": { "$binary": { "base64": "Mng0NCt4ZHVUYUJCa1kxNkVyNUR1QURhZ2h2UzR2d2RrZzh0cFBwM3R6NmdWMDFBMUN3YkQ5aXRRMkhGRGdQV09wOGVNYUMxT2k3NjZKelhaQmRCZGJkTXVyZG9uSjFk", "subType": "00" } } } } } }, "operations": [ { "name": "insertOne", "arguments": { "document": { "_id": 0, "encryptedLong": { "$numberLong": "0" } } } }, { "name": "insertOne", "arguments": { "document": { "_id": 1, "encryptedLong": { "$numberLong": "1" } } } }, { "name": "find", "arguments": { "filter": { "encryptedLong": { "$gt": { "$numberLong": "0" } } } }, "result": [ { "_id": 1, "encryptedLong": { "$numberLong": "1" } } ] } ] }, { "description": "Find with $gte", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "local": { "key": { "$binary": { "base64": "Mng0NCt4ZHVUYUJCa1kxNkVyNUR1QURhZ2h2UzR2d2RrZzh0cFBwM3R6NmdWMDFBMUN3YkQ5aXRRMkhGRGdQV09wOGVNYUMxT2k3NjZKelhaQmRCZGJkTXVyZG9uSjFk", "subType": "00" } } } } } }, "operations": [ { "name": "insertOne", "arguments": { "document": { "_id": 0, "encryptedLong": { "$numberLong": "0" } } } }, { "name": "insertOne", "arguments": { "document": { "_id": 1, "encryptedLong": { "$numberLong": "1" } } } }, { "name": "find", "arguments": { "filter": { "encryptedLong": { "$gte": { "$numberLong": "0" } } }, "sort": { "_id": 1 } }, "result": [ { "_id": 0, "encryptedLong": { "$numberLong": "0" } }, { "_id": 1, "encryptedLong": { "$numberLong": "1" } } ] } ] }, { "description": "Find with $gt with no results", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "local": { "key": { "$binary": { "base64": "Mng0NCt4ZHVUYUJCa1kxNkVyNUR1QURhZ2h2UzR2d2RrZzh0cFBwM3R6NmdWMDFBMUN3YkQ5aXRRMkhGRGdQV09wOGVNYUMxT2k3NjZKelhaQmRCZGJkTXVyZG9uSjFk", "subType": "00" } } } } } }, "operations": [ { "name": "insertOne", "arguments": { "document": { "_id": 0, "encryptedLong": { "$numberLong": "0" } } } }, { "name": "insertOne", "arguments": { "document": { "_id": 1, "encryptedLong": { "$numberLong": "1" } } } }, { "name": "find", "arguments": { "filter": { "encryptedLong": { "$gt": { "$numberLong": "1" } } } }, "result": [] } ] }, { "description": "Find with $lt", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "local": { "key": { "$binary": { "base64": "Mng0NCt4ZHVUYUJCa1kxNkVyNUR1QURhZ2h2UzR2d2RrZzh0cFBwM3R6NmdWMDFBMUN3YkQ5aXRRMkhGRGdQV09wOGVNYUMxT2k3NjZKelhaQmRCZGJkTXVyZG9uSjFk", "subType": "00" } } } } } }, "operations": [ { "name": "insertOne", "arguments": { "document": { "_id": 0, "encryptedLong": { "$numberLong": "0" } } } }, { "name": "insertOne", "arguments": { "document": { "_id": 1, "encryptedLong": { "$numberLong": "1" } } } }, { "name": "find", "arguments": { "filter": { "encryptedLong": { "$lt": { "$numberLong": "1" } } } }, "result": [ { "_id": 0, "encryptedLong": { "$numberLong": "0" } } ] } ] }, { "description": "Find with $lte", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "local": { "key": { "$binary": { "base64": "Mng0NCt4ZHVUYUJCa1kxNkVyNUR1QURhZ2h2UzR2d2RrZzh0cFBwM3R6NmdWMDFBMUN3YkQ5aXRRMkhGRGdQV09wOGVNYUMxT2k3NjZKelhaQmRCZGJkTXVyZG9uSjFk", "subType": "00" } } } } } }, "operations": [ { "name": "insertOne", "arguments": { "document": { "_id": 0, "encryptedLong": { "$numberLong": "0" } } } }, { "name": "insertOne", "arguments": { "document": { "_id": 1, "encryptedLong": { "$numberLong": "1" } } } }, { "name": "find", "arguments": { "filter": { "encryptedLong": { "$lte": { "$numberLong": "1" } } }, "sort": { "_id": 1 } }, "result": [ { "_id": 0, "encryptedLong": { "$numberLong": "0" } }, { "_id": 1, "encryptedLong": { "$numberLong": "1" } } ] } ] }, { "description": "Find with $lt below min", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "local": { "key": { "$binary": { "base64": "Mng0NCt4ZHVUYUJCa1kxNkVyNUR1QURhZ2h2UzR2d2RrZzh0cFBwM3R6NmdWMDFBMUN3YkQ5aXRRMkhGRGdQV09wOGVNYUMxT2k3NjZKelhaQmRCZGJkTXVyZG9uSjFk", "subType": "00" } } } } } }, "operations": [ { "name": "insertOne", "arguments": { "document": { "_id": 0, "encryptedLong": { "$numberLong": "0" } } } }, { "name": "insertOne", "arguments": { "document": { "_id": 1, "encryptedLong": { "$numberLong": "1" } } } }, { "name": "find", "arguments": { "filter": { "encryptedLong": { "$lt": { "$numberLong": "0" } } } }, "result": { "errorContains": "must be greater than the range minimum" } } ] }, { "description": "Find with $gt above max", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "local": { "key": { "$binary": { "base64": "Mng0NCt4ZHVUYUJCa1kxNkVyNUR1QURhZ2h2UzR2d2RrZzh0cFBwM3R6NmdWMDFBMUN3YkQ5aXRRMkhGRGdQV09wOGVNYUMxT2k3NjZKelhaQmRCZGJkTXVyZG9uSjFk", "subType": "00" } } } } } }, "operations": [ { "name": "insertOne", "arguments": { "document": { "_id": 0, "encryptedLong": { "$numberLong": "0" } } } }, { "name": "insertOne", "arguments": { "document": { "_id": 1, "encryptedLong": { "$numberLong": "1" } } } }, { "name": "find", "arguments": { "filter": { "encryptedLong": { "$gt": { "$numberLong": "200" } } } }, "result": { "errorContains": "must be less than the range maximum" } } ] }, { "description": "Find with $gt and $lt", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "local": { "key": { "$binary": { "base64": "Mng0NCt4ZHVUYUJCa1kxNkVyNUR1QURhZ2h2UzR2d2RrZzh0cFBwM3R6NmdWMDFBMUN3YkQ5aXRRMkhGRGdQV09wOGVNYUMxT2k3NjZKelhaQmRCZGJkTXVyZG9uSjFk", "subType": "00" } } } } } }, "operations": [ { "name": "insertOne", "arguments": { "document": { "_id": 0, "encryptedLong": { "$numberLong": "0" } } } }, { "name": "insertOne", "arguments": { "document": { "_id": 1, "encryptedLong": { "$numberLong": "1" } } } }, { "name": "find", "arguments": { "filter": { "encryptedLong": { "$gt": { "$numberLong": "0" }, "$lt": { "$numberLong": "2" } } } }, "result": [ { "_id": 1, "encryptedLong": { "$numberLong": "1" } } ] } ] }, { "description": "Find with equality", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "local": { "key": { "$binary": { "base64": "Mng0NCt4ZHVUYUJCa1kxNkVyNUR1QURhZ2h2UzR2d2RrZzh0cFBwM3R6NmdWMDFBMUN3YkQ5aXRRMkhGRGdQV09wOGVNYUMxT2k3NjZKelhaQmRCZGJkTXVyZG9uSjFk", "subType": "00" } } } } } }, "operations": [ { "name": "insertOne", "arguments": { "document": { "_id": 0, "encryptedLong": { "$numberLong": "0" } } } }, { "name": "insertOne", "arguments": { "document": { "_id": 1, "encryptedLong": { "$numberLong": "1" } } } }, { "name": "find", "arguments": { "filter": { "encryptedLong": { "$numberLong": "0" } } }, "result": [ { "_id": 0, "encryptedLong": { "$numberLong": "0" } } ] }, { "name": "find", "arguments": { "filter": { "encryptedLong": { "$numberLong": "1" } } }, "result": [ { "_id": 1, "encryptedLong": { "$numberLong": "1" } } ] } ] }, { "description": "Find with full range", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "local": { "key": { "$binary": { "base64": "Mng0NCt4ZHVUYUJCa1kxNkVyNUR1QURhZ2h2UzR2d2RrZzh0cFBwM3R6NmdWMDFBMUN3YkQ5aXRRMkhGRGdQV09wOGVNYUMxT2k3NjZKelhaQmRCZGJkTXVyZG9uSjFk", "subType": "00" } } } } } }, "operations": [ { "name": "insertOne", "arguments": { "document": { "_id": 0, "encryptedLong": { "$numberLong": "0" } } } }, { "name": "insertOne", "arguments": { "document": { "_id": 1, "encryptedLong": { "$numberLong": "1" } } } }, { "name": "find", "arguments": { "filter": { "encryptedLong": { "$gte": { "$numberLong": "0" }, "$lte": { "$numberLong": "200" } } }, "sort": { "_id": 1 } }, "result": [ { "_id": 0, "encryptedLong": { "$numberLong": "0" } }, { "_id": 1, "encryptedLong": { "$numberLong": "1" } } ] } ] }, { "description": "Find with $in", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "local": { "key": { "$binary": { "base64": "Mng0NCt4ZHVUYUJCa1kxNkVyNUR1QURhZ2h2UzR2d2RrZzh0cFBwM3R6NmdWMDFBMUN3YkQ5aXRRMkhGRGdQV09wOGVNYUMxT2k3NjZKelhaQmRCZGJkTXVyZG9uSjFk", "subType": "00" } } } } } }, "operations": [ { "name": "insertOne", "arguments": { "document": { "_id": 0, "encryptedLong": { "$numberLong": "0" } } } }, { "name": "insertOne", "arguments": { "document": { "_id": 1, "encryptedLong": { "$numberLong": "1" } } } }, { "name": "find", "arguments": { "filter": { "encryptedLong": { "$in": [ { "$numberLong": "0" } ] } } }, "result": [ { "_id": 0, "encryptedLong": { "$numberLong": "0" } } ] } ] }, { "description": "Insert out of range", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "local": { "key": { "$binary": { "base64": "Mng0NCt4ZHVUYUJCa1kxNkVyNUR1QURhZ2h2UzR2d2RrZzh0cFBwM3R6NmdWMDFBMUN3YkQ5aXRRMkhGRGdQV09wOGVNYUMxT2k3NjZKelhaQmRCZGJkTXVyZG9uSjFk", "subType": "00" } } } } } }, "operations": [ { "name": "insertOne", "arguments": { "document": { "_id": 0, "encryptedLong": { "$numberLong": "-1" } } }, "result": { "errorContains": "value must be greater than or equal to the minimum value" } } ] }, { "description": "Insert min and max", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "local": { "key": { "$binary": { "base64": "Mng0NCt4ZHVUYUJCa1kxNkVyNUR1QURhZ2h2UzR2d2RrZzh0cFBwM3R6NmdWMDFBMUN3YkQ5aXRRMkhGRGdQV09wOGVNYUMxT2k3NjZKelhaQmRCZGJkTXVyZG9uSjFk", "subType": "00" } } } } } }, "operations": [ { "name": "insertOne", "arguments": { "document": { "_id": 0, "encryptedLong": { "$numberLong": "0" } } } }, { "name": "insertOne", "arguments": { "document": { "_id": 200, "encryptedLong": { "$numberLong": "200" } } } }, { "name": "find", "arguments": { "filter": {}, "sort": { "_id": 1 } }, "result": [ { "_id": 0, "encryptedLong": { "$numberLong": "0" } }, { "_id": 200, "encryptedLong": { "$numberLong": "200" } } ] } ] }, { "description": "Aggregate with $gte", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "local": { "key": { "$binary": { "base64": "Mng0NCt4ZHVUYUJCa1kxNkVyNUR1QURhZ2h2UzR2d2RrZzh0cFBwM3R6NmdWMDFBMUN3YkQ5aXRRMkhGRGdQV09wOGVNYUMxT2k3NjZKelhaQmRCZGJkTXVyZG9uSjFk", "subType": "00" } } } } } }, "operations": [ { "name": "insertOne", "arguments": { "document": { "_id": 0, "encryptedLong": { "$numberLong": "0" } } } }, { "name": "insertOne", "arguments": { "document": { "_id": 1, "encryptedLong": { "$numberLong": "1" } } } }, { "name": "aggregate", "arguments": { "pipeline": [ { "$match": { "encryptedLong": { "$gte": { "$numberLong": "0" } } } }, { "$sort": { "_id": 1 } } ] }, "result": [ { "_id": 0, "encryptedLong": { "$numberLong": "0" } }, { "_id": 1, "encryptedLong": { "$numberLong": "1" } } ] } ] }, { "description": "Aggregate with $gt with no results", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "local": { "key": { "$binary": { "base64": "Mng0NCt4ZHVUYUJCa1kxNkVyNUR1QURhZ2h2UzR2d2RrZzh0cFBwM3R6NmdWMDFBMUN3YkQ5aXRRMkhGRGdQV09wOGVNYUMxT2k3NjZKelhaQmRCZGJkTXVyZG9uSjFk", "subType": "00" } } } } } }, "operations": [ { "name": "insertOne", "arguments": { "document": { "_id": 0, "encryptedLong": { "$numberLong": "0" } } } }, { "name": "insertOne", "arguments": { "document": { "_id": 1, "encryptedLong": { "$numberLong": "1" } } } }, { "name": "aggregate", "arguments": { "pipeline": [ { "$match": { "encryptedLong": { "$gt": { "$numberLong": "1" } } } } ] }, "result": [] } ] }, { "description": "Aggregate with $lt", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "local": { "key": { "$binary": { "base64": "Mng0NCt4ZHVUYUJCa1kxNkVyNUR1QURhZ2h2UzR2d2RrZzh0cFBwM3R6NmdWMDFBMUN3YkQ5aXRRMkhGRGdQV09wOGVNYUMxT2k3NjZKelhaQmRCZGJkTXVyZG9uSjFk", "subType": "00" } } } } } }, "operations": [ { "name": "insertOne", "arguments": { "document": { "_id": 0, "encryptedLong": { "$numberLong": "0" } } } }, { "name": "insertOne", "arguments": { "document": { "_id": 1, "encryptedLong": { "$numberLong": "1" } } } }, { "name": "aggregate", "arguments": { "pipeline": [ { "$match": { "encryptedLong": { "$lt": { "$numberLong": "1" } } } } ] }, "result": [ { "_id": 0, "encryptedLong": { "$numberLong": "0" } } ] } ] }, { "description": "Aggregate with $lte", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "local": { "key": { "$binary": { "base64": "Mng0NCt4ZHVUYUJCa1kxNkVyNUR1QURhZ2h2UzR2d2RrZzh0cFBwM3R6NmdWMDFBMUN3YkQ5aXRRMkhGRGdQV09wOGVNYUMxT2k3NjZKelhaQmRCZGJkTXVyZG9uSjFk", "subType": "00" } } } } } }, "operations": [ { "name": "insertOne", "arguments": { "document": { "_id": 0, "encryptedLong": { "$numberLong": "0" } } } }, { "name": "insertOne", "arguments": { "document": { "_id": 1, "encryptedLong": { "$numberLong": "1" } } } }, { "name": "aggregate", "arguments": { "pipeline": [ { "$match": { "encryptedLong": { "$lte": { "$numberLong": "1" } } } }, { "$sort": { "_id": 1 } } ] }, "result": [ { "_id": 0, "encryptedLong": { "$numberLong": "0" } }, { "_id": 1, "encryptedLong": { "$numberLong": "1" } } ] } ] }, { "description": "Aggregate with $lt below min", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "local": { "key": { "$binary": { "base64": "Mng0NCt4ZHVUYUJCa1kxNkVyNUR1QURhZ2h2UzR2d2RrZzh0cFBwM3R6NmdWMDFBMUN3YkQ5aXRRMkhGRGdQV09wOGVNYUMxT2k3NjZKelhaQmRCZGJkTXVyZG9uSjFk", "subType": "00" } } } } } }, "operations": [ { "name": "insertOne", "arguments": { "document": { "_id": 0, "encryptedLong": { "$numberLong": "0" } } } }, { "name": "insertOne", "arguments": { "document": { "_id": 1, "encryptedLong": { "$numberLong": "1" } } } }, { "name": "aggregate", "arguments": { "pipeline": [ { "$match": { "encryptedLong": { "$lt": { "$numberLong": "0" } } } } ] }, "result": { "errorContains": "must be greater than the range minimum" } } ] }, { "description": "Aggregate with $gt above max", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "local": { "key": { "$binary": { "base64": "Mng0NCt4ZHVUYUJCa1kxNkVyNUR1QURhZ2h2UzR2d2RrZzh0cFBwM3R6NmdWMDFBMUN3YkQ5aXRRMkhGRGdQV09wOGVNYUMxT2k3NjZKelhaQmRCZGJkTXVyZG9uSjFk", "subType": "00" } } } } } }, "operations": [ { "name": "insertOne", "arguments": { "document": { "_id": 0, "encryptedLong": { "$numberLong": "0" } } } }, { "name": "insertOne", "arguments": { "document": { "_id": 1, "encryptedLong": { "$numberLong": "1" } } } }, { "name": "aggregate", "arguments": { "pipeline": [ { "$match": { "encryptedLong": { "$gt": { "$numberLong": "200" } } } } ] }, "result": { "errorContains": "must be less than the range maximum" } } ] }, { "description": "Aggregate with $gt and $lt", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "local": { "key": { "$binary": { "base64": "Mng0NCt4ZHVUYUJCa1kxNkVyNUR1QURhZ2h2UzR2d2RrZzh0cFBwM3R6NmdWMDFBMUN3YkQ5aXRRMkhGRGdQV09wOGVNYUMxT2k3NjZKelhaQmRCZGJkTXVyZG9uSjFk", "subType": "00" } } } } } }, "operations": [ { "name": "insertOne", "arguments": { "document": { "_id": 0, "encryptedLong": { "$numberLong": "0" } } } }, { "name": "insertOne", "arguments": { "document": { "_id": 1, "encryptedLong": { "$numberLong": "1" } } } }, { "name": "aggregate", "arguments": { "pipeline": [ { "$match": { "encryptedLong": { "$gt": { "$numberLong": "0" }, "$lt": { "$numberLong": "2" } } } } ] }, "result": [ { "_id": 1, "encryptedLong": { "$numberLong": "1" } } ] } ] }, { "description": "Aggregate with equality", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "local": { "key": { "$binary": { "base64": "Mng0NCt4ZHVUYUJCa1kxNkVyNUR1QURhZ2h2UzR2d2RrZzh0cFBwM3R6NmdWMDFBMUN3YkQ5aXRRMkhGRGdQV09wOGVNYUMxT2k3NjZKelhaQmRCZGJkTXVyZG9uSjFk", "subType": "00" } } } } } }, "operations": [ { "name": "insertOne", "arguments": { "document": { "_id": 0, "encryptedLong": { "$numberLong": "0" } } } }, { "name": "insertOne", "arguments": { "document": { "_id": 1, "encryptedLong": { "$numberLong": "1" } } } }, { "name": "aggregate", "arguments": { "pipeline": [ { "$match": { "encryptedLong": { "$numberLong": "0" } } } ] }, "result": [ { "_id": 0, "encryptedLong": { "$numberLong": "0" } } ] }, { "name": "aggregate", "arguments": { "pipeline": [ { "$match": { "encryptedLong": { "$numberLong": "1" } } } ] }, "result": [ { "_id": 1, "encryptedLong": { "$numberLong": "1" } } ] } ] }, { "description": "Aggregate with full range", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "local": { "key": { "$binary": { "base64": "Mng0NCt4ZHVUYUJCa1kxNkVyNUR1QURhZ2h2UzR2d2RrZzh0cFBwM3R6NmdWMDFBMUN3YkQ5aXRRMkhGRGdQV09wOGVNYUMxT2k3NjZKelhaQmRCZGJkTXVyZG9uSjFk", "subType": "00" } } } } } }, "operations": [ { "name": "insertOne", "arguments": { "document": { "_id": 0, "encryptedLong": { "$numberLong": "0" } } } }, { "name": "insertOne", "arguments": { "document": { "_id": 1, "encryptedLong": { "$numberLong": "1" } } } }, { "name": "aggregate", "arguments": { "pipeline": [ { "$match": { "encryptedLong": { "$gte": { "$numberLong": "0" }, "$lte": { "$numberLong": "200" } } } }, { "$sort": { "_id": 1 } } ] }, "result": [ { "_id": 0, "encryptedLong": { "$numberLong": "0" } }, { "_id": 1, "encryptedLong": { "$numberLong": "1" } } ] } ] }, { "description": "Aggregate with $in", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "local": { "key": { "$binary": { "base64": "Mng0NCt4ZHVUYUJCa1kxNkVyNUR1QURhZ2h2UzR2d2RrZzh0cFBwM3R6NmdWMDFBMUN3YkQ5aXRRMkhGRGdQV09wOGVNYUMxT2k3NjZKelhaQmRCZGJkTXVyZG9uSjFk", "subType": "00" } } } } } }, "operations": [ { "name": "insertOne", "arguments": { "document": { "_id": 0, "encryptedLong": { "$numberLong": "0" } } } }, { "name": "insertOne", "arguments": { "document": { "_id": 1, "encryptedLong": { "$numberLong": "1" } } } }, { "name": "aggregate", "arguments": { "pipeline": [ { "$match": { "encryptedLong": { "$in": [ { "$numberLong": "0" } ] } } } ] }, "result": [ { "_id": 0, "encryptedLong": { "$numberLong": "0" } } ] } ] }, { "description": "Wrong type: Insert Double", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "local": { "key": { "$binary": { "base64": "Mng0NCt4ZHVUYUJCa1kxNkVyNUR1QURhZ2h2UzR2d2RrZzh0cFBwM3R6NmdWMDFBMUN3YkQ5aXRRMkhGRGdQV09wOGVNYUMxT2k3NjZKelhaQmRCZGJkTXVyZG9uSjFk", "subType": "00" } } } } } }, "operations": [ { "name": "insertOne", "arguments": { "document": { "_id": 0, "encryptedLong": { "$numberDouble": "0" } } }, "result": { "errorContains": "cannot encrypt element" } } ] }, { "description": "Wrong type: Find Double", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "local": { "key": { "$binary": { "base64": "Mng0NCt4ZHVUYUJCa1kxNkVyNUR1QURhZ2h2UzR2d2RrZzh0cFBwM3R6NmdWMDFBMUN3YkQ5aXRRMkhGRGdQV09wOGVNYUMxT2k3NjZKelhaQmRCZGJkTXVyZG9uSjFk", "subType": "00" } } } } } }, "operations": [ { "name": "find", "arguments": { "filter": { "encryptedLong": { "$gte": { "$numberDouble": "0" } } } }, "result": { "errorContains": "field type is not supported" } } ] } ] } fle2v2-Range-Long-Delete.json000066400000000000000000000323101462766011000342440ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/client-side-encryption/spec/legacy{ "runOn": [ { "minServerVersion": "7.0.0", "topology": [ "replicaset", "sharded", "load-balanced" ] } ], "database_name": "default", "collection_name": "default", "data": [], "encrypted_fields": { "fields": [ { "keyId": { "$binary": { "base64": "EjRWeBI0mHYSNBI0VniQEg==", "subType": "04" } }, "path": "encryptedLong", "bsonType": "long", "queries": { "queryType": "rangePreview", "contention": { "$numberLong": "0" }, "sparsity": { "$numberLong": "1" }, "min": { "$numberLong": "0" }, "max": { "$numberLong": "200" } } } ] }, "key_vault_data": [ { "_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" } } ], "tests": [ { "description": "FLE2 Range Long. Delete.", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "local": { "key": { "$binary": { "base64": "Mng0NCt4ZHVUYUJCa1kxNkVyNUR1QURhZ2h2UzR2d2RrZzh0cFBwM3R6NmdWMDFBMUN3YkQ5aXRRMkhGRGdQV09wOGVNYUMxT2k3NjZKelhaQmRCZGJkTXVyZG9uSjFk", "subType": "00" } } } } } }, "operations": [ { "name": "insertOne", "arguments": { "document": { "_id": 0, "encryptedLong": { "$numberLong": "0" } } } }, { "name": "insertOne", "arguments": { "document": { "_id": 1, "encryptedLong": { "$numberLong": "1" } } } }, { "name": "deleteOne", "arguments": { "filter": { "encryptedLong": { "$gt": { "$numberLong": "0" } } } }, "result": { "deletedCount": 1 } } ], "expectations": [ { "command_started_event": { "command": { "listCollections": 1, "filter": { "name": "default" } }, "command_name": "listCollections" } }, { "command_started_event": { "command": { "find": "datakeys", "filter": { "$or": [ { "_id": { "$in": [ { "$binary": { "base64": "EjRWeBI0mHYSNBI0VniQEg==", "subType": "04" } } ] } }, { "keyAltNames": { "$in": [] } } ] }, "$db": "keyvault", "readConcern": { "level": "majority" } }, "command_name": "find" } }, { "command_started_event": { "command": { "insert": "default", "documents": [ { "_id": 0, "encryptedLong": { "$$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": "encryptedLong", "bsonType": "long", "queries": { "queryType": "rangePreview", "contention": { "$numberLong": "0" }, "sparsity": { "$numberLong": "1" }, "min": { "$numberLong": "0" }, "max": { "$numberLong": "200" } } } ] } } } }, "command_name": "insert" } }, { "command_started_event": { "command": { "insert": "default", "documents": [ { "_id": 1, "encryptedLong": { "$$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": "encryptedLong", "bsonType": "long", "queries": { "queryType": "rangePreview", "contention": { "$numberLong": "0" }, "sparsity": { "$numberLong": "1" }, "min": { "$numberLong": "0" }, "max": { "$numberLong": "200" } } } ] } } } }, "command_name": "insert" } }, { "command_started_event": { "command": { "delete": "default", "deletes": [ { "q": { "encryptedLong": { "$gt": { "$binary": { "base64": "DUkFAAADcGF5bG9hZAAZBQAABGcABQUAAAMwAH0AAAAFZAAgAAAAALGGQ/CRD+pGLD53BZzWcCcYbuGLVEyjzXIx7b+ux/q2BXMAIAAAAACOC6mXEZL27P9hethZbtKYsTXKK+FpgQ9Axxmn9N/cCwVsACAAAAAA+MFEd8XfZSpbXKqqPC2L3TEFswkaG5Ff6aSgf8p+XVIAAzEAfQAAAAVkACAAAAAAtL3QIvnZqCF72eS6lKr8ilff7R6kiNklokiTuaU5wNsFcwAgAAAAAEtqr3/X731VB+VrbFcY8ZrJKRo2E0Fd+C8L0EMNcvcCBWwAIAAAAABNPhSriux8W8qbwnhCczE3IzlhNEnGDpUwTFDZSL+eYQADMgB9AAAABWQAIAAAAAB99ZW/7KwXKzl5M3XQsAJ3JbEef90IoxFYBArNiYzlgQVzACAAAAAAYO/qaw0+92HAryxOUG7iK6hnIy3OaUA9jIqtHdvcq8YFbAAgAAAAAHrUYj8A0hVgc6VklpDiljOnykrUSfEsjm56XO/bsfKdAAMzAH0AAAAFZAAgAAAAAOK8brUuc2onBNDRtfYMR736dHj4dQqXod8JG7tAMTsDBXMAIAAAAAAW6SrGAL6Bx0s7ZlsYULFfOAiYIGhEWu6md3r+Rk40awVsACAAAAAAIHYXP8RLcCboUmHN3+OlnEw1DxaLSnbTB9PdF228fFAAAzQAfQAAAAVkACAAAAAAV22FGF7ZDwK/EYiGNMlm/QuT3saQdyJM/Fn+ZyQug1oFcwAgAAAAACo7GwCvbcs5UHQMgds9/1QMklEVdjZigpuOFGrDmmxtBWwAIAAAAADQbYYPxlCMMGe2MulbiurApFLoeJSMvTeDU3pyEA2jNwADNQB9AAAABWQAIAAAAADFspsMG7yHjKppyllon1KqAsTrHaZ6JzNqnSz8o6iTvwVzACAAAAAAeiA5pqVIQQ9s6UY/P8v5Jjkl3I7iFNeLDYehikrINrsFbAAgAAAAAFjBTzTpNxDEkA0vSRj0jCED9KDRlboMVyilKyDz5YR4AAM2AH0AAAAFZAAgAAAAAPcLmtq+V1e+MRlZ7NHq1+mrRVBQje5zj685ZvdsfKvSBXMAIAAAAABdHz/3w2k5km97QN9m7oLFYJaVJneNlMboIlz5yUASQAVsACAAAAAAWbp8JVJnx8fEVAJFa7WMfMa7wXeP5M3C8MX20J/i9n0AAzcAfQAAAAVkACAAAAAAYfLwnoxK6XAGQrJFy8+TIJoq38ldBaO75h4zA4ZX5tQFcwAgAAAAAC2wk8UcJH5X5XGnDBYmel6srpBkzBhHtt3Jw1u5TSJ1BWwAIAAAAAA9/YU9eI3D7QbXKIw/3/gzWJ6MZrCYhG0j1wNKgRQp5wADOAB9AAAABWQAIAAAAADGvyrtKkIcaV17ynZA7b2k5Pz6OhvxdWNkDvDWJIja8wVzACAAAAAAOLypVKNxf/wR1G8OZjUUsTQzDYeNNhhITxGMSp7euS4FbAAgAAAAAA9EsxoV1B2DcQ1NJRwuxXnvVR+vkD0wbbDYEI/zFEnDAAM5AH0AAAAFZAAgAAAAAEocREw1L0g+roFUchJI2Yd0M0ME2bnErNUYnpyJP1SqBXMAIAAAAAAcE2/JK/8MoSeOchIuAkKh1X3ImoA7p8ujAZIfvIDo6QVsACAAAAAA+W0+zgLr85/PD7P9a94wk6MgNgrizx/XU9aCxAkp1IwAABJjbQAAAAAAAAAAAAAQcGF5bG9hZElkAAAAAAAQZmlyc3RPcGVyYXRvcgABAAAAAA==", "subType": "06" } } } }, "limit": 1 } ], "ordered": true, "encryptionInformation": { "type": 1, "schema": { "default.default": { "escCollection": "enxcol_.default.esc", "ecocCollection": "enxcol_.default.ecoc", "fields": [ { "keyId": { "$binary": { "base64": "EjRWeBI0mHYSNBI0VniQEg==", "subType": "04" } }, "path": "encryptedLong", "bsonType": "long", "queries": { "queryType": "rangePreview", "contention": { "$numberLong": "0" }, "sparsity": { "$numberLong": "1" }, "min": { "$numberLong": "0" }, "max": { "$numberLong": "200" } } } ] } } } }, "command_name": "delete" } } ], "outcome": { "collection": { "data": [ { "_id": 0, "encryptedLong": { "$$type": "binData" }, "__safeContent__": [ { "$binary": { "base64": "5nRutVIyq7URVOVtbE4vM01APSIajAVnsShMwjBlzkM=", "subType": "00" } }, { "$binary": { "base64": "RjBYT2h3ZAoHxhf8DU6/dFbDkEBZp0IxREcsRTu2MXs=", "subType": "00" } }, { "$binary": { "base64": "x7GR49EN0t3WXQDihkrbonK7qNIBYC87tpL/XEUyIYc=", "subType": "00" } }, { "$binary": { "base64": "JfYUqWF+OoGjiYkRI4L5iPlF+T1Eleul7Fki22jp4Qc=", "subType": "00" } }, { "$binary": { "base64": "q1RyGfIgsaQHoZFRw+DD28V26rN5hweApPLwExncvT8=", "subType": "00" } }, { "$binary": { "base64": "L2PFeKGvLS6C+DLudR6fGlBq3ERPvjWvRyNRIA2HVb0=", "subType": "00" } }, { "$binary": { "base64": "CWxaNqL3iP1yCixDkcmf9bmW3E5VeN8TJkg1jJe528s=", "subType": "00" } }, { "$binary": { "base64": "+vC6araOEo+fpW7PSIP40/EnzBCj1d2N10Jr3rrXJJM=", "subType": "00" } }, { "$binary": { "base64": "6SV63Mf51Z6A6p2X3rCnJKCu6ku3Oeb45mBYbz+IoAo=", "subType": "00" } } ] } ] } } } ] } fle2v2-Range-Long-FindOneAndUpdate.json000066400000000000000000000367351462766011000361710ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/client-side-encryption/spec/legacy{ "runOn": [ { "minServerVersion": "7.0.0", "topology": [ "replicaset", "sharded", "load-balanced" ] } ], "database_name": "default", "collection_name": "default", "data": [], "encrypted_fields": { "fields": [ { "keyId": { "$binary": { "base64": "EjRWeBI0mHYSNBI0VniQEg==", "subType": "04" } }, "path": "encryptedLong", "bsonType": "long", "queries": { "queryType": "rangePreview", "contention": { "$numberLong": "0" }, "sparsity": { "$numberLong": "1" }, "min": { "$numberLong": "0" }, "max": { "$numberLong": "200" } } } ] }, "key_vault_data": [ { "_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" } } ], "tests": [ { "description": "FLE2 Range Long. FindOneAndUpdate.", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "local": { "key": { "$binary": { "base64": "Mng0NCt4ZHVUYUJCa1kxNkVyNUR1QURhZ2h2UzR2d2RrZzh0cFBwM3R6NmdWMDFBMUN3YkQ5aXRRMkhGRGdQV09wOGVNYUMxT2k3NjZKelhaQmRCZGJkTXVyZG9uSjFk", "subType": "00" } } } } } }, "operations": [ { "name": "insertOne", "arguments": { "document": { "_id": 0, "encryptedLong": { "$numberLong": "0" } } } }, { "name": "insertOne", "arguments": { "document": { "_id": 1, "encryptedLong": { "$numberLong": "1" } } } }, { "name": "findOneAndUpdate", "arguments": { "filter": { "encryptedLong": { "$gt": { "$numberLong": "0" } } }, "update": { "$set": { "encryptedLong": { "$numberLong": "2" } } }, "returnDocument": "Before" }, "result": { "_id": 1, "encryptedLong": { "$numberLong": "1" } } } ], "expectations": [ { "command_started_event": { "command": { "listCollections": 1, "filter": { "name": "default" } }, "command_name": "listCollections" } }, { "command_started_event": { "command": { "find": "datakeys", "filter": { "$or": [ { "_id": { "$in": [ { "$binary": { "base64": "EjRWeBI0mHYSNBI0VniQEg==", "subType": "04" } } ] } }, { "keyAltNames": { "$in": [] } } ] }, "$db": "keyvault", "readConcern": { "level": "majority" } }, "command_name": "find" } }, { "command_started_event": { "command": { "insert": "default", "documents": [ { "_id": 0, "encryptedLong": { "$$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": "encryptedLong", "bsonType": "long", "queries": { "queryType": "rangePreview", "contention": { "$numberLong": "0" }, "sparsity": { "$numberLong": "1" }, "min": { "$numberLong": "0" }, "max": { "$numberLong": "200" } } } ] } } } }, "command_name": "insert" } }, { "command_started_event": { "command": { "insert": "default", "documents": [ { "_id": 1, "encryptedLong": { "$$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": "encryptedLong", "bsonType": "long", "queries": { "queryType": "rangePreview", "contention": { "$numberLong": "0" }, "sparsity": { "$numberLong": "1" }, "min": { "$numberLong": "0" }, "max": { "$numberLong": "200" } } } ] } } } }, "command_name": "insert" } }, { "command_started_event": { "command": { "findAndModify": "default", "query": { "encryptedLong": { "$gt": { "$binary": { "base64": "DUkFAAADcGF5bG9hZAAZBQAABGcABQUAAAMwAH0AAAAFZAAgAAAAALGGQ/CRD+pGLD53BZzWcCcYbuGLVEyjzXIx7b+ux/q2BXMAIAAAAACOC6mXEZL27P9hethZbtKYsTXKK+FpgQ9Axxmn9N/cCwVsACAAAAAA+MFEd8XfZSpbXKqqPC2L3TEFswkaG5Ff6aSgf8p+XVIAAzEAfQAAAAVkACAAAAAAtL3QIvnZqCF72eS6lKr8ilff7R6kiNklokiTuaU5wNsFcwAgAAAAAEtqr3/X731VB+VrbFcY8ZrJKRo2E0Fd+C8L0EMNcvcCBWwAIAAAAABNPhSriux8W8qbwnhCczE3IzlhNEnGDpUwTFDZSL+eYQADMgB9AAAABWQAIAAAAAB99ZW/7KwXKzl5M3XQsAJ3JbEef90IoxFYBArNiYzlgQVzACAAAAAAYO/qaw0+92HAryxOUG7iK6hnIy3OaUA9jIqtHdvcq8YFbAAgAAAAAHrUYj8A0hVgc6VklpDiljOnykrUSfEsjm56XO/bsfKdAAMzAH0AAAAFZAAgAAAAAOK8brUuc2onBNDRtfYMR736dHj4dQqXod8JG7tAMTsDBXMAIAAAAAAW6SrGAL6Bx0s7ZlsYULFfOAiYIGhEWu6md3r+Rk40awVsACAAAAAAIHYXP8RLcCboUmHN3+OlnEw1DxaLSnbTB9PdF228fFAAAzQAfQAAAAVkACAAAAAAV22FGF7ZDwK/EYiGNMlm/QuT3saQdyJM/Fn+ZyQug1oFcwAgAAAAACo7GwCvbcs5UHQMgds9/1QMklEVdjZigpuOFGrDmmxtBWwAIAAAAADQbYYPxlCMMGe2MulbiurApFLoeJSMvTeDU3pyEA2jNwADNQB9AAAABWQAIAAAAADFspsMG7yHjKppyllon1KqAsTrHaZ6JzNqnSz8o6iTvwVzACAAAAAAeiA5pqVIQQ9s6UY/P8v5Jjkl3I7iFNeLDYehikrINrsFbAAgAAAAAFjBTzTpNxDEkA0vSRj0jCED9KDRlboMVyilKyDz5YR4AAM2AH0AAAAFZAAgAAAAAPcLmtq+V1e+MRlZ7NHq1+mrRVBQje5zj685ZvdsfKvSBXMAIAAAAABdHz/3w2k5km97QN9m7oLFYJaVJneNlMboIlz5yUASQAVsACAAAAAAWbp8JVJnx8fEVAJFa7WMfMa7wXeP5M3C8MX20J/i9n0AAzcAfQAAAAVkACAAAAAAYfLwnoxK6XAGQrJFy8+TIJoq38ldBaO75h4zA4ZX5tQFcwAgAAAAAC2wk8UcJH5X5XGnDBYmel6srpBkzBhHtt3Jw1u5TSJ1BWwAIAAAAAA9/YU9eI3D7QbXKIw/3/gzWJ6MZrCYhG0j1wNKgRQp5wADOAB9AAAABWQAIAAAAADGvyrtKkIcaV17ynZA7b2k5Pz6OhvxdWNkDvDWJIja8wVzACAAAAAAOLypVKNxf/wR1G8OZjUUsTQzDYeNNhhITxGMSp7euS4FbAAgAAAAAA9EsxoV1B2DcQ1NJRwuxXnvVR+vkD0wbbDYEI/zFEnDAAM5AH0AAAAFZAAgAAAAAEocREw1L0g+roFUchJI2Yd0M0ME2bnErNUYnpyJP1SqBXMAIAAAAAAcE2/JK/8MoSeOchIuAkKh1X3ImoA7p8ujAZIfvIDo6QVsACAAAAAA+W0+zgLr85/PD7P9a94wk6MgNgrizx/XU9aCxAkp1IwAABJjbQAAAAAAAAAAAAAQcGF5bG9hZElkAAAAAAAQZmlyc3RPcGVyYXRvcgABAAAAAA==", "subType": "06" } } } }, "update": { "$set": { "encryptedLong": { "$$type": "binData" } } }, "encryptionInformation": { "type": 1, "schema": { "default.default": { "escCollection": "enxcol_.default.esc", "ecocCollection": "enxcol_.default.ecoc", "fields": [ { "keyId": { "$binary": { "base64": "EjRWeBI0mHYSNBI0VniQEg==", "subType": "04" } }, "path": "encryptedLong", "bsonType": "long", "queries": { "queryType": "rangePreview", "contention": { "$numberLong": "0" }, "sparsity": { "$numberLong": "1" }, "min": { "$numberLong": "0" }, "max": { "$numberLong": "200" } } } ] } } } }, "command_name": "findAndModify" } } ], "outcome": { "collection": { "data": [ { "_id": 0, "encryptedLong": { "$$type": "binData" }, "__safeContent__": [ { "$binary": { "base64": "5nRutVIyq7URVOVtbE4vM01APSIajAVnsShMwjBlzkM=", "subType": "00" } }, { "$binary": { "base64": "RjBYT2h3ZAoHxhf8DU6/dFbDkEBZp0IxREcsRTu2MXs=", "subType": "00" } }, { "$binary": { "base64": "x7GR49EN0t3WXQDihkrbonK7qNIBYC87tpL/XEUyIYc=", "subType": "00" } }, { "$binary": { "base64": "JfYUqWF+OoGjiYkRI4L5iPlF+T1Eleul7Fki22jp4Qc=", "subType": "00" } }, { "$binary": { "base64": "q1RyGfIgsaQHoZFRw+DD28V26rN5hweApPLwExncvT8=", "subType": "00" } }, { "$binary": { "base64": "L2PFeKGvLS6C+DLudR6fGlBq3ERPvjWvRyNRIA2HVb0=", "subType": "00" } }, { "$binary": { "base64": "CWxaNqL3iP1yCixDkcmf9bmW3E5VeN8TJkg1jJe528s=", "subType": "00" } }, { "$binary": { "base64": "+vC6araOEo+fpW7PSIP40/EnzBCj1d2N10Jr3rrXJJM=", "subType": "00" } }, { "$binary": { "base64": "6SV63Mf51Z6A6p2X3rCnJKCu6ku3Oeb45mBYbz+IoAo=", "subType": "00" } } ] }, { "_id": 1, "encryptedLong": { "$$type": "binData" }, "__safeContent__": [ { "$binary": { "base64": "DLCAJs+W2PL2DV5YChCL6dYrQNr+j4p3L7xhVaub4ic=", "subType": "00" } }, { "$binary": { "base64": "hyDcE6QQjPrYJaIS/n7evEZFYcm31Tj89CpEYGF45cI=", "subType": "00" } }, { "$binary": { "base64": "F08nMDWDZc+DbWM7XCEJNNCEYyinRmrvGP7EWhmp4is=", "subType": "00" } }, { "$binary": { "base64": "cXH4688amcDc8kZOJq4UP8cE3R58Zl7e+Qo/1jyspps=", "subType": "00" } }, { "$binary": { "base64": "uURBxvTp3FBCVkd+LPqyuY7d6rMW6SGIJQEPY/wtkZI=", "subType": "00" } }, { "$binary": { "base64": "jG3hax1L3RBp9t38vUt53FsBxgr/+Si/vVISpAylYpE=", "subType": "00" } }, { "$binary": { "base64": "kwtIW8MhH9Ky5xNjBx8gFA/SHh2YVphie7g5FGBzals=", "subType": "00" } }, { "$binary": { "base64": "FHflwFuEMu4xX0ZApHi+pdlBH+oevAtXckCUb5Wv0xU=", "subType": "00" } }, { "$binary": { "base64": "ty4cnzJdAlbQKnh7px3GEYjBnvO+jIOaKjoTRDtmh3M=", "subType": "00" } } ] } ] } } } ] } fle2v2-Range-Long-InsertFind.json000066400000000000000000000361321462766011000351150ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/client-side-encryption/spec/legacy{ "runOn": [ { "minServerVersion": "7.0.0", "topology": [ "replicaset", "sharded", "load-balanced" ] } ], "database_name": "default", "collection_name": "default", "data": [], "encrypted_fields": { "fields": [ { "keyId": { "$binary": { "base64": "EjRWeBI0mHYSNBI0VniQEg==", "subType": "04" } }, "path": "encryptedLong", "bsonType": "long", "queries": { "queryType": "rangePreview", "contention": { "$numberLong": "0" }, "sparsity": { "$numberLong": "1" }, "min": { "$numberLong": "0" }, "max": { "$numberLong": "200" } } } ] }, "key_vault_data": [ { "_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" } } ], "tests": [ { "description": "FLE2 Range Long. Insert and Find.", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "local": { "key": { "$binary": { "base64": "Mng0NCt4ZHVUYUJCa1kxNkVyNUR1QURhZ2h2UzR2d2RrZzh0cFBwM3R6NmdWMDFBMUN3YkQ5aXRRMkhGRGdQV09wOGVNYUMxT2k3NjZKelhaQmRCZGJkTXVyZG9uSjFk", "subType": "00" } } } } } }, "operations": [ { "name": "insertOne", "arguments": { "document": { "_id": 0, "encryptedLong": { "$numberLong": "0" } } } }, { "name": "insertOne", "arguments": { "document": { "_id": 1, "encryptedLong": { "$numberLong": "1" } } } }, { "name": "find", "arguments": { "filter": { "encryptedLong": { "$gt": { "$numberLong": "0" } } } }, "result": [ { "_id": 1, "encryptedLong": { "$numberLong": "1" } } ] } ], "expectations": [ { "command_started_event": { "command": { "listCollections": 1, "filter": { "name": "default" } }, "command_name": "listCollections" } }, { "command_started_event": { "command": { "find": "datakeys", "filter": { "$or": [ { "_id": { "$in": [ { "$binary": { "base64": "EjRWeBI0mHYSNBI0VniQEg==", "subType": "04" } } ] } }, { "keyAltNames": { "$in": [] } } ] }, "$db": "keyvault", "readConcern": { "level": "majority" } }, "command_name": "find" } }, { "command_started_event": { "command": { "insert": "default", "documents": [ { "_id": 0, "encryptedLong": { "$$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": "encryptedLong", "bsonType": "long", "queries": { "queryType": "rangePreview", "contention": { "$numberLong": "0" }, "sparsity": { "$numberLong": "1" }, "min": { "$numberLong": "0" }, "max": { "$numberLong": "200" } } } ] } } } }, "command_name": "insert" } }, { "command_started_event": { "command": { "insert": "default", "documents": [ { "_id": 1, "encryptedLong": { "$$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": "encryptedLong", "bsonType": "long", "queries": { "queryType": "rangePreview", "contention": { "$numberLong": "0" }, "sparsity": { "$numberLong": "1" }, "min": { "$numberLong": "0" }, "max": { "$numberLong": "200" } } } ] } } } }, "command_name": "insert" } }, { "command_started_event": { "command": { "find": "default", "filter": { "encryptedLong": { "$gt": { "$binary": { "base64": "DUkFAAADcGF5bG9hZAAZBQAABGcABQUAAAMwAH0AAAAFZAAgAAAAALGGQ/CRD+pGLD53BZzWcCcYbuGLVEyjzXIx7b+ux/q2BXMAIAAAAACOC6mXEZL27P9hethZbtKYsTXKK+FpgQ9Axxmn9N/cCwVsACAAAAAA+MFEd8XfZSpbXKqqPC2L3TEFswkaG5Ff6aSgf8p+XVIAAzEAfQAAAAVkACAAAAAAtL3QIvnZqCF72eS6lKr8ilff7R6kiNklokiTuaU5wNsFcwAgAAAAAEtqr3/X731VB+VrbFcY8ZrJKRo2E0Fd+C8L0EMNcvcCBWwAIAAAAABNPhSriux8W8qbwnhCczE3IzlhNEnGDpUwTFDZSL+eYQADMgB9AAAABWQAIAAAAAB99ZW/7KwXKzl5M3XQsAJ3JbEef90IoxFYBArNiYzlgQVzACAAAAAAYO/qaw0+92HAryxOUG7iK6hnIy3OaUA9jIqtHdvcq8YFbAAgAAAAAHrUYj8A0hVgc6VklpDiljOnykrUSfEsjm56XO/bsfKdAAMzAH0AAAAFZAAgAAAAAOK8brUuc2onBNDRtfYMR736dHj4dQqXod8JG7tAMTsDBXMAIAAAAAAW6SrGAL6Bx0s7ZlsYULFfOAiYIGhEWu6md3r+Rk40awVsACAAAAAAIHYXP8RLcCboUmHN3+OlnEw1DxaLSnbTB9PdF228fFAAAzQAfQAAAAVkACAAAAAAV22FGF7ZDwK/EYiGNMlm/QuT3saQdyJM/Fn+ZyQug1oFcwAgAAAAACo7GwCvbcs5UHQMgds9/1QMklEVdjZigpuOFGrDmmxtBWwAIAAAAADQbYYPxlCMMGe2MulbiurApFLoeJSMvTeDU3pyEA2jNwADNQB9AAAABWQAIAAAAADFspsMG7yHjKppyllon1KqAsTrHaZ6JzNqnSz8o6iTvwVzACAAAAAAeiA5pqVIQQ9s6UY/P8v5Jjkl3I7iFNeLDYehikrINrsFbAAgAAAAAFjBTzTpNxDEkA0vSRj0jCED9KDRlboMVyilKyDz5YR4AAM2AH0AAAAFZAAgAAAAAPcLmtq+V1e+MRlZ7NHq1+mrRVBQje5zj685ZvdsfKvSBXMAIAAAAABdHz/3w2k5km97QN9m7oLFYJaVJneNlMboIlz5yUASQAVsACAAAAAAWbp8JVJnx8fEVAJFa7WMfMa7wXeP5M3C8MX20J/i9n0AAzcAfQAAAAVkACAAAAAAYfLwnoxK6XAGQrJFy8+TIJoq38ldBaO75h4zA4ZX5tQFcwAgAAAAAC2wk8UcJH5X5XGnDBYmel6srpBkzBhHtt3Jw1u5TSJ1BWwAIAAAAAA9/YU9eI3D7QbXKIw/3/gzWJ6MZrCYhG0j1wNKgRQp5wADOAB9AAAABWQAIAAAAADGvyrtKkIcaV17ynZA7b2k5Pz6OhvxdWNkDvDWJIja8wVzACAAAAAAOLypVKNxf/wR1G8OZjUUsTQzDYeNNhhITxGMSp7euS4FbAAgAAAAAA9EsxoV1B2DcQ1NJRwuxXnvVR+vkD0wbbDYEI/zFEnDAAM5AH0AAAAFZAAgAAAAAEocREw1L0g+roFUchJI2Yd0M0ME2bnErNUYnpyJP1SqBXMAIAAAAAAcE2/JK/8MoSeOchIuAkKh1X3ImoA7p8ujAZIfvIDo6QVsACAAAAAA+W0+zgLr85/PD7P9a94wk6MgNgrizx/XU9aCxAkp1IwAABJjbQAAAAAAAAAAAAAQcGF5bG9hZElkAAAAAAAQZmlyc3RPcGVyYXRvcgABAAAAAA==", "subType": "06" } } } }, "encryptionInformation": { "type": 1, "schema": { "default.default": { "escCollection": "enxcol_.default.esc", "ecocCollection": "enxcol_.default.ecoc", "fields": [ { "keyId": { "$binary": { "base64": "EjRWeBI0mHYSNBI0VniQEg==", "subType": "04" } }, "path": "encryptedLong", "bsonType": "long", "queries": { "queryType": "rangePreview", "contention": { "$numberLong": "0" }, "sparsity": { "$numberLong": "1" }, "min": { "$numberLong": "0" }, "max": { "$numberLong": "200" } } } ] } } } }, "command_name": "find" } } ], "outcome": { "collection": { "data": [ { "_id": 0, "encryptedLong": { "$$type": "binData" }, "__safeContent__": [ { "$binary": { "base64": "5nRutVIyq7URVOVtbE4vM01APSIajAVnsShMwjBlzkM=", "subType": "00" } }, { "$binary": { "base64": "RjBYT2h3ZAoHxhf8DU6/dFbDkEBZp0IxREcsRTu2MXs=", "subType": "00" } }, { "$binary": { "base64": "x7GR49EN0t3WXQDihkrbonK7qNIBYC87tpL/XEUyIYc=", "subType": "00" } }, { "$binary": { "base64": "JfYUqWF+OoGjiYkRI4L5iPlF+T1Eleul7Fki22jp4Qc=", "subType": "00" } }, { "$binary": { "base64": "q1RyGfIgsaQHoZFRw+DD28V26rN5hweApPLwExncvT8=", "subType": "00" } }, { "$binary": { "base64": "L2PFeKGvLS6C+DLudR6fGlBq3ERPvjWvRyNRIA2HVb0=", "subType": "00" } }, { "$binary": { "base64": "CWxaNqL3iP1yCixDkcmf9bmW3E5VeN8TJkg1jJe528s=", "subType": "00" } }, { "$binary": { "base64": "+vC6araOEo+fpW7PSIP40/EnzBCj1d2N10Jr3rrXJJM=", "subType": "00" } }, { "$binary": { "base64": "6SV63Mf51Z6A6p2X3rCnJKCu6ku3Oeb45mBYbz+IoAo=", "subType": "00" } } ] }, { "_id": 1, "encryptedLong": { "$$type": "binData" }, "__safeContent__": [ { "$binary": { "base64": "bE1vqWj3KNyM7cCYUv/cnYm8BPaUL3eMp5syTHq6NF4=", "subType": "00" } }, { "$binary": { "base64": "25j9sQXZCihCmHKvTHgaBsAVZFcGPn7JjHdrCGlwyyw=", "subType": "00" } }, { "$binary": { "base64": "FA74j21GUEJb1DJBOpR9nVnjaDZnd8yAQNuaW9Qi26g=", "subType": "00" } }, { "$binary": { "base64": "kJv//KVkbrobIBf+QeWC5jxn20mx/P0R1N6aCSMgKM8=", "subType": "00" } }, { "$binary": { "base64": "zB+Whi9IUUGxfLEe+lGuIzLX4LFbIhaIAm5lRk65QTc=", "subType": "00" } }, { "$binary": { "base64": "ybO1QU3CgvhO8JgRXH+HxKszWcpl5aGDYYVa75fHa1g=", "subType": "00" } }, { "$binary": { "base64": "X3Y3eSAbbMg//JgiHHiFpYOpV61t8kkDexI+CQyitH4=", "subType": "00" } }, { "$binary": { "base64": "SlNHXyqVFGDPrX/2ppwog6l4pwj3PKda2TkZbqgfSfA=", "subType": "00" } }, { "$binary": { "base64": "McjV8xwTF3xI7863DYOBdyvIv6UpzThl6v9vBRk05bI=", "subType": "00" } } ] } ] } } } ] } fle2v2-Range-Long-Update.json000066400000000000000000000371311462766011000342720ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/client-side-encryption/spec/legacy{ "runOn": [ { "minServerVersion": "7.0.0", "topology": [ "replicaset", "sharded", "load-balanced" ] } ], "database_name": "default", "collection_name": "default", "data": [], "encrypted_fields": { "fields": [ { "keyId": { "$binary": { "base64": "EjRWeBI0mHYSNBI0VniQEg==", "subType": "04" } }, "path": "encryptedLong", "bsonType": "long", "queries": { "queryType": "rangePreview", "contention": { "$numberLong": "0" }, "sparsity": { "$numberLong": "1" }, "min": { "$numberLong": "0" }, "max": { "$numberLong": "200" } } } ] }, "key_vault_data": [ { "_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" } } ], "tests": [ { "description": "FLE2 Range Long. Update.", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "local": { "key": { "$binary": { "base64": "Mng0NCt4ZHVUYUJCa1kxNkVyNUR1QURhZ2h2UzR2d2RrZzh0cFBwM3R6NmdWMDFBMUN3YkQ5aXRRMkhGRGdQV09wOGVNYUMxT2k3NjZKelhaQmRCZGJkTXVyZG9uSjFk", "subType": "00" } } } } } }, "operations": [ { "name": "insertOne", "arguments": { "document": { "_id": 0, "encryptedLong": { "$numberLong": "0" } } } }, { "name": "insertOne", "arguments": { "document": { "_id": 1, "encryptedLong": { "$numberLong": "1" } } } }, { "name": "updateOne", "arguments": { "filter": { "encryptedLong": { "$gt": { "$numberLong": "0" } } }, "update": { "$set": { "encryptedLong": { "$numberLong": "2" } } } }, "result": { "matchedCount": 1, "modifiedCount": 1, "upsertedCount": 0 } } ], "expectations": [ { "command_started_event": { "command": { "listCollections": 1, "filter": { "name": "default" } }, "command_name": "listCollections" } }, { "command_started_event": { "command": { "find": "datakeys", "filter": { "$or": [ { "_id": { "$in": [ { "$binary": { "base64": "EjRWeBI0mHYSNBI0VniQEg==", "subType": "04" } } ] } }, { "keyAltNames": { "$in": [] } } ] }, "$db": "keyvault", "readConcern": { "level": "majority" } }, "command_name": "find" } }, { "command_started_event": { "command": { "insert": "default", "documents": [ { "_id": 0, "encryptedLong": { "$$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": "encryptedLong", "bsonType": "long", "queries": { "queryType": "rangePreview", "contention": { "$numberLong": "0" }, "sparsity": { "$numberLong": "1" }, "min": { "$numberLong": "0" }, "max": { "$numberLong": "200" } } } ] } } } }, "command_name": "insert" } }, { "command_started_event": { "command": { "insert": "default", "documents": [ { "_id": 1, "encryptedLong": { "$$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": "encryptedLong", "bsonType": "long", "queries": { "queryType": "rangePreview", "contention": { "$numberLong": "0" }, "sparsity": { "$numberLong": "1" }, "min": { "$numberLong": "0" }, "max": { "$numberLong": "200" } } } ] } } } }, "command_name": "insert" } }, { "command_started_event": { "command_name": "update", "command": { "update": "default", "ordered": true, "updates": [ { "q": { "encryptedLong": { "$gt": { "$binary": { "base64": "DUkFAAADcGF5bG9hZAAZBQAABGcABQUAAAMwAH0AAAAFZAAgAAAAALGGQ/CRD+pGLD53BZzWcCcYbuGLVEyjzXIx7b+ux/q2BXMAIAAAAACOC6mXEZL27P9hethZbtKYsTXKK+FpgQ9Axxmn9N/cCwVsACAAAAAA+MFEd8XfZSpbXKqqPC2L3TEFswkaG5Ff6aSgf8p+XVIAAzEAfQAAAAVkACAAAAAAtL3QIvnZqCF72eS6lKr8ilff7R6kiNklokiTuaU5wNsFcwAgAAAAAEtqr3/X731VB+VrbFcY8ZrJKRo2E0Fd+C8L0EMNcvcCBWwAIAAAAABNPhSriux8W8qbwnhCczE3IzlhNEnGDpUwTFDZSL+eYQADMgB9AAAABWQAIAAAAAB99ZW/7KwXKzl5M3XQsAJ3JbEef90IoxFYBArNiYzlgQVzACAAAAAAYO/qaw0+92HAryxOUG7iK6hnIy3OaUA9jIqtHdvcq8YFbAAgAAAAAHrUYj8A0hVgc6VklpDiljOnykrUSfEsjm56XO/bsfKdAAMzAH0AAAAFZAAgAAAAAOK8brUuc2onBNDRtfYMR736dHj4dQqXod8JG7tAMTsDBXMAIAAAAAAW6SrGAL6Bx0s7ZlsYULFfOAiYIGhEWu6md3r+Rk40awVsACAAAAAAIHYXP8RLcCboUmHN3+OlnEw1DxaLSnbTB9PdF228fFAAAzQAfQAAAAVkACAAAAAAV22FGF7ZDwK/EYiGNMlm/QuT3saQdyJM/Fn+ZyQug1oFcwAgAAAAACo7GwCvbcs5UHQMgds9/1QMklEVdjZigpuOFGrDmmxtBWwAIAAAAADQbYYPxlCMMGe2MulbiurApFLoeJSMvTeDU3pyEA2jNwADNQB9AAAABWQAIAAAAADFspsMG7yHjKppyllon1KqAsTrHaZ6JzNqnSz8o6iTvwVzACAAAAAAeiA5pqVIQQ9s6UY/P8v5Jjkl3I7iFNeLDYehikrINrsFbAAgAAAAAFjBTzTpNxDEkA0vSRj0jCED9KDRlboMVyilKyDz5YR4AAM2AH0AAAAFZAAgAAAAAPcLmtq+V1e+MRlZ7NHq1+mrRVBQje5zj685ZvdsfKvSBXMAIAAAAABdHz/3w2k5km97QN9m7oLFYJaVJneNlMboIlz5yUASQAVsACAAAAAAWbp8JVJnx8fEVAJFa7WMfMa7wXeP5M3C8MX20J/i9n0AAzcAfQAAAAVkACAAAAAAYfLwnoxK6XAGQrJFy8+TIJoq38ldBaO75h4zA4ZX5tQFcwAgAAAAAC2wk8UcJH5X5XGnDBYmel6srpBkzBhHtt3Jw1u5TSJ1BWwAIAAAAAA9/YU9eI3D7QbXKIw/3/gzWJ6MZrCYhG0j1wNKgRQp5wADOAB9AAAABWQAIAAAAADGvyrtKkIcaV17ynZA7b2k5Pz6OhvxdWNkDvDWJIja8wVzACAAAAAAOLypVKNxf/wR1G8OZjUUsTQzDYeNNhhITxGMSp7euS4FbAAgAAAAAA9EsxoV1B2DcQ1NJRwuxXnvVR+vkD0wbbDYEI/zFEnDAAM5AH0AAAAFZAAgAAAAAEocREw1L0g+roFUchJI2Yd0M0ME2bnErNUYnpyJP1SqBXMAIAAAAAAcE2/JK/8MoSeOchIuAkKh1X3ImoA7p8ujAZIfvIDo6QVsACAAAAAA+W0+zgLr85/PD7P9a94wk6MgNgrizx/XU9aCxAkp1IwAABJjbQAAAAAAAAAAAAAQcGF5bG9hZElkAAAAAAAQZmlyc3RPcGVyYXRvcgABAAAAAA==", "subType": "06" } } } }, "u": { "$set": { "encryptedLong": { "$$type": "binData" } } } } ], "encryptionInformation": { "type": 1, "schema": { "default.default": { "escCollection": "enxcol_.default.esc", "ecocCollection": "enxcol_.default.ecoc", "fields": [ { "keyId": { "$binary": { "base64": "EjRWeBI0mHYSNBI0VniQEg==", "subType": "04" } }, "path": "encryptedLong", "bsonType": "long", "queries": { "queryType": "rangePreview", "contention": { "$numberLong": "0" }, "sparsity": { "$numberLong": "1" }, "min": { "$numberLong": "0" }, "max": { "$numberLong": "200" } } } ] } } }, "$db": "default" } } } ], "outcome": { "collection": { "data": [ { "_id": 0, "encryptedLong": { "$$type": "binData" }, "__safeContent__": [ { "$binary": { "base64": "5nRutVIyq7URVOVtbE4vM01APSIajAVnsShMwjBlzkM=", "subType": "00" } }, { "$binary": { "base64": "RjBYT2h3ZAoHxhf8DU6/dFbDkEBZp0IxREcsRTu2MXs=", "subType": "00" } }, { "$binary": { "base64": "x7GR49EN0t3WXQDihkrbonK7qNIBYC87tpL/XEUyIYc=", "subType": "00" } }, { "$binary": { "base64": "JfYUqWF+OoGjiYkRI4L5iPlF+T1Eleul7Fki22jp4Qc=", "subType": "00" } }, { "$binary": { "base64": "q1RyGfIgsaQHoZFRw+DD28V26rN5hweApPLwExncvT8=", "subType": "00" } }, { "$binary": { "base64": "L2PFeKGvLS6C+DLudR6fGlBq3ERPvjWvRyNRIA2HVb0=", "subType": "00" } }, { "$binary": { "base64": "CWxaNqL3iP1yCixDkcmf9bmW3E5VeN8TJkg1jJe528s=", "subType": "00" } }, { "$binary": { "base64": "+vC6araOEo+fpW7PSIP40/EnzBCj1d2N10Jr3rrXJJM=", "subType": "00" } }, { "$binary": { "base64": "6SV63Mf51Z6A6p2X3rCnJKCu6ku3Oeb45mBYbz+IoAo=", "subType": "00" } } ] }, { "_id": 1, "encryptedLong": { "$$type": "binData" }, "__safeContent__": [ { "$binary": { "base64": "DLCAJs+W2PL2DV5YChCL6dYrQNr+j4p3L7xhVaub4ic=", "subType": "00" } }, { "$binary": { "base64": "hyDcE6QQjPrYJaIS/n7evEZFYcm31Tj89CpEYGF45cI=", "subType": "00" } }, { "$binary": { "base64": "F08nMDWDZc+DbWM7XCEJNNCEYyinRmrvGP7EWhmp4is=", "subType": "00" } }, { "$binary": { "base64": "cXH4688amcDc8kZOJq4UP8cE3R58Zl7e+Qo/1jyspps=", "subType": "00" } }, { "$binary": { "base64": "uURBxvTp3FBCVkd+LPqyuY7d6rMW6SGIJQEPY/wtkZI=", "subType": "00" } }, { "$binary": { "base64": "jG3hax1L3RBp9t38vUt53FsBxgr/+Si/vVISpAylYpE=", "subType": "00" } }, { "$binary": { "base64": "kwtIW8MhH9Ky5xNjBx8gFA/SHh2YVphie7g5FGBzals=", "subType": "00" } }, { "$binary": { "base64": "FHflwFuEMu4xX0ZApHi+pdlBH+oevAtXckCUb5Wv0xU=", "subType": "00" } }, { "$binary": { "base64": "ty4cnzJdAlbQKnh7px3GEYjBnvO+jIOaKjoTRDtmh3M=", "subType": "00" } } ] } ] } } } ] } fle2v2-Range-WrongType.json000066400000000000000000000071361462766011000341130ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/client-side-encryption/spec/legacy{ "runOn": [ { "minServerVersion": "7.0.0", "topology": [ "replicaset", "sharded", "load-balanced" ] } ], "database_name": "default", "collection_name": "default", "data": [], "encrypted_fields": { "fields": [ { "keyId": { "$binary": { "base64": "EjRWeBI0mHYSNBI0VniQEg==", "subType": "04" } }, "path": "encryptedInt", "bsonType": "int", "queries": { "queryType": "rangePreview", "contention": { "$numberLong": "0" }, "sparsity": { "$numberLong": "1" }, "min": { "$numberInt": "0" }, "max": { "$numberInt": "200" } } } ] }, "key_vault_data": [ { "_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" } } ], "tests": [ { "description": "Wrong type: Insert Double", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "local": { "key": { "$binary": { "base64": "Mng0NCt4ZHVUYUJCa1kxNkVyNUR1QURhZ2h2UzR2d2RrZzh0cFBwM3R6NmdWMDFBMUN3YkQ5aXRRMkhGRGdQV09wOGVNYUMxT2k3NjZKelhaQmRCZGJkTXVyZG9uSjFk", "subType": "00" } } } } } }, "operations": [ { "name": "insertOne", "arguments": { "document": { "_id": 0, "encryptedInt": { "$numberDouble": "0" } } }, "result": { "errorContains": "cannot encrypt element" } } ] }, { "description": "Wrong type: Find Double", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "local": { "key": { "$binary": { "base64": "Mng0NCt4ZHVUYUJCa1kxNkVyNUR1QURhZ2h2UzR2d2RrZzh0cFBwM3R6NmdWMDFBMUN3YkQ5aXRRMkhGRGdQV09wOGVNYUMxT2k3NjZKelhaQmRCZGJkTXVyZG9uSjFk", "subType": "00" } } } } } }, "operations": [ { "name": "insertOne", "arguments": { "document": { "_id": 0, "encryptedInt": { "$numberInt": "0" } } } }, { "name": "find", "arguments": { "filter": { "encryptedInt": { "$gte": { "$numberDouble": "0" } } }, "sort": { "_id": 1 } }, "result": { "errorContains": "field type is not supported" } } ] } ] } mongodb-mongo-python-driver-509e9b7/test/client-side-encryption/spec/legacy/fle2v2-Update.json000066400000000000000000000374401462766011000324250ustar00rootroot00000000000000{ "runOn": [ { "minServerVersion": "7.0.0", "topology": [ "replicaset", "sharded", "load-balanced" ] } ], "database_name": "default", "collection_name": "default", "data": [], "encrypted_fields": { "fields": [ { "keyId": { "$binary": { "base64": "EjRWeBI0mHYSNBI0VniQEg==", "subType": "04" } }, "path": "encryptedIndexed", "bsonType": "string", "queries": { "queryType": "equality", "contention": { "$numberLong": "0" } } }, { "keyId": { "$binary": { "base64": "q83vqxI0mHYSNBI0VniQEg==", "subType": "04" } }, "path": "encryptedUnindexed", "bsonType": "string" } ] }, "key_vault_data": [ { "_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" } } ], "tests": [ { "description": "Update can query an FLE2 indexed field", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "local": { "key": { "$binary": { "base64": "Mng0NCt4ZHVUYUJCa1kxNkVyNUR1QURhZ2h2UzR2d2RrZzh0cFBwM3R6NmdWMDFBMUN3YkQ5aXRRMkhGRGdQV09wOGVNYUMxT2k3NjZKelhaQmRCZGJkTXVyZG9uSjFk", "subType": "00" } } } } } }, "operations": [ { "name": "insertOne", "arguments": { "document": { "_id": 1, "encryptedIndexed": "value123" } } }, { "name": "updateOne", "arguments": { "filter": { "encryptedIndexed": "value123" }, "update": { "$set": { "foo": "bar" } } }, "result": { "matchedCount": 1, "modifiedCount": 1, "upsertedCount": 0 } } ], "expectations": [ { "command_started_event": { "command": { "listCollections": 1, "filter": { "name": "default" } }, "command_name": "listCollections" } }, { "command_started_event": { "command": { "find": "datakeys", "filter": { "$or": [ { "_id": { "$in": [ { "$binary": { "base64": "EjRWeBI0mHYSNBI0VniQEg==", "subType": "04" } } ] } }, { "keyAltNames": { "$in": [] } } ] }, "$db": "keyvault", "readConcern": { "level": "majority" } }, "command_name": "find" } }, { "command_started_event": { "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" } } }, { "keyId": { "$binary": { "base64": "q83vqxI0mHYSNBI0VniQEg==", "subType": "04" } }, "path": "encryptedUnindexed", "bsonType": "string" } ] } } } }, "command_name": "insert" } }, { "command_started_event": { "command": { "update": "default", "updates": [ { "q": { "encryptedIndexed": { "$eq": { "$binary": { "base64": "DIkAAAAFZAAgAAAAAPtVteJQAlgb2YMa/+7YWH00sbQPyt7L6Rb8OwBdMmL2BXMAIAAAAAAd44hgVKnEnTFlwNVC14oyc9OZOTspeymusqkRQj57nAVsACAAAAAAaZ9s3G+4znfxStxeOZwcZy1OhzjMGc5hjmdMN+b/w6kSY20AAAAAAAAAAAAA", "subType": "06" } } } }, "u": { "$set": { "foo": "bar" } } } ], "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" } } }, { "keyId": { "$binary": { "base64": "q83vqxI0mHYSNBI0VniQEg==", "subType": "04" } }, "path": "encryptedUnindexed", "bsonType": "string" } ] } } } }, "command_name": "update" } } ], "outcome": { "collection": { "data": [ { "_id": 1, "encryptedIndexed": { "$$type": "binData" }, "foo": "bar", "__safeContent__": [ { "$binary": { "base64": "ThpoKfQ8AkOzkFfNC1+9PF0pY2nIzfXvRdxQgjkNbBw=", "subType": "00" } } ] } ] } } }, { "description": "Update can modify an FLE2 indexed field", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "local": { "key": { "$binary": { "base64": "Mng0NCt4ZHVUYUJCa1kxNkVyNUR1QURhZ2h2UzR2d2RrZzh0cFBwM3R6NmdWMDFBMUN3YkQ5aXRRMkhGRGdQV09wOGVNYUMxT2k3NjZKelhaQmRCZGJkTXVyZG9uSjFk", "subType": "00" } } } } } }, "operations": [ { "name": "insertOne", "arguments": { "document": { "_id": 1, "encryptedIndexed": "value123" } } }, { "name": "updateOne", "arguments": { "filter": { "encryptedIndexed": "value123" }, "update": { "$set": { "encryptedIndexed": "value456" } } }, "result": { "matchedCount": 1, "modifiedCount": 1, "upsertedCount": 0 } }, { "name": "find", "arguments": { "filter": { "_id": 1 } }, "result": [ { "encryptedIndexed": "value456" } ] } ], "expectations": [ { "command_started_event": { "command": { "listCollections": 1, "filter": { "name": "default" } }, "command_name": "listCollections" } }, { "command_started_event": { "command": { "find": "datakeys", "filter": { "$or": [ { "_id": { "$in": [ { "$binary": { "base64": "EjRWeBI0mHYSNBI0VniQEg==", "subType": "04" } } ] } }, { "keyAltNames": { "$in": [] } } ] }, "$db": "keyvault", "readConcern": { "level": "majority" } }, "command_name": "find" } }, { "command_started_event": { "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" } } }, { "keyId": { "$binary": { "base64": "q83vqxI0mHYSNBI0VniQEg==", "subType": "04" } }, "path": "encryptedUnindexed", "bsonType": "string" } ] } } } }, "command_name": "insert" } }, { "command_started_event": { "command": { "update": "default", "updates": [ { "q": { "encryptedIndexed": { "$eq": { "$binary": { "base64": "DIkAAAAFZAAgAAAAAPtVteJQAlgb2YMa/+7YWH00sbQPyt7L6Rb8OwBdMmL2BXMAIAAAAAAd44hgVKnEnTFlwNVC14oyc9OZOTspeymusqkRQj57nAVsACAAAAAAaZ9s3G+4znfxStxeOZwcZy1OhzjMGc5hjmdMN+b/w6kSY20AAAAAAAAAAAAA", "subType": "06" } } } }, "u": { "$set": { "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" } } }, { "keyId": { "$binary": { "base64": "q83vqxI0mHYSNBI0VniQEg==", "subType": "04" } }, "path": "encryptedUnindexed", "bsonType": "string" } ] } } } }, "command_name": "update" } }, { "command_started_event": { "command": { "find": "default", "filter": { "_id": { "$eq": 1 } } }, "command_name": "find" } } ], "outcome": { "collection": { "data": [ { "_id": 1, "encryptedIndexed": { "$$type": "binData" }, "__safeContent__": [ { "$binary": { "base64": "rhe7/w8Ob8Unl44rGr/moScx6m5VODQnscDhF4Nkn6g=", "subType": "00" } } ] } ] } } } ] } fle2v2-validatorAndPartialFieldExpression.json000066400000000000000000000337031462766011000400730ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/client-side-encryption/spec/legacy{ "runOn": [ { "minServerVersion": "7.0.0", "topology": [ "replicaset", "sharded", "load-balanced" ] } ], "database_name": "default", "collection_name": "default", "data": [], "tests": [ { "description": "create with a validator on an unencrypted field is OK", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "local": { "key": { "$binary": { "base64": "Mng0NCt4ZHVUYUJCa1kxNkVyNUR1QURhZ2h2UzR2d2RrZzh0cFBwM3R6NmdWMDFBMUN3YkQ5aXRRMkhGRGdQV09wOGVNYUMxT2k3NjZKelhaQmRCZGJkTXVyZG9uSjFk", "subType": "00" } } } }, "encryptedFieldsMap": { "default.encryptedCollection": { "fields": [ { "keyId": { "$binary": { "base64": "EjRWeBI0mHYSNBI0VniQEg==", "subType": "04" } }, "path": "encryptedIndexed", "bsonType": "string", "queries": { "queryType": "equality", "contention": { "$numberLong": "0" } } }, { "keyId": { "$binary": { "base64": "q83vqxI0mHYSNBI0VniQEg==", "subType": "04" } }, "path": "encryptedUnindexed", "bsonType": "string" } ] } } } }, "operations": [ { "name": "dropCollection", "object": "database", "arguments": { "collection": "encryptedCollection" } }, { "name": "createCollection", "object": "database", "arguments": { "collection": "encryptedCollection", "validator": { "unencrypted_string": "foo" } } }, { "name": "assertCollectionExists", "object": "testRunner", "arguments": { "database": "default", "collection": "encryptedCollection" } } ] }, { "description": "create with a validator on an encrypted field is an error", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "local": { "key": { "$binary": { "base64": "Mng0NCt4ZHVUYUJCa1kxNkVyNUR1QURhZ2h2UzR2d2RrZzh0cFBwM3R6NmdWMDFBMUN3YkQ5aXRRMkhGRGdQV09wOGVNYUMxT2k3NjZKelhaQmRCZGJkTXVyZG9uSjFk", "subType": "00" } } } }, "encryptedFieldsMap": { "default.encryptedCollection": { "fields": [ { "keyId": { "$binary": { "base64": "EjRWeBI0mHYSNBI0VniQEg==", "subType": "04" } }, "path": "encryptedIndexed", "bsonType": "string", "queries": { "queryType": "equality", "contention": { "$numberLong": "0" } } }, { "keyId": { "$binary": { "base64": "q83vqxI0mHYSNBI0VniQEg==", "subType": "04" } }, "path": "encryptedUnindexed", "bsonType": "string" } ] } } } }, "operations": [ { "name": "dropCollection", "object": "database", "arguments": { "collection": "encryptedCollection" } }, { "name": "createCollection", "object": "database", "arguments": { "collection": "encryptedCollection", "validator": { "encryptedIndexed": "foo" } }, "result": { "errorContains": "Comparison to encrypted fields not supported" } } ] }, { "description": "collMod with a validator on an unencrypted field is OK", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "local": { "key": { "$binary": { "base64": "Mng0NCt4ZHVUYUJCa1kxNkVyNUR1QURhZ2h2UzR2d2RrZzh0cFBwM3R6NmdWMDFBMUN3YkQ5aXRRMkhGRGdQV09wOGVNYUMxT2k3NjZKelhaQmRCZGJkTXVyZG9uSjFk", "subType": "00" } } } }, "encryptedFieldsMap": { "default.encryptedCollection": { "fields": [ { "keyId": { "$binary": { "base64": "EjRWeBI0mHYSNBI0VniQEg==", "subType": "04" } }, "path": "encryptedIndexed", "bsonType": "string", "queries": { "queryType": "equality", "contention": { "$numberLong": "0" } } }, { "keyId": { "$binary": { "base64": "q83vqxI0mHYSNBI0VniQEg==", "subType": "04" } }, "path": "encryptedUnindexed", "bsonType": "string" } ] } } } }, "operations": [ { "name": "dropCollection", "object": "database", "arguments": { "collection": "encryptedCollection" } }, { "name": "createCollection", "object": "database", "arguments": { "collection": "encryptedCollection" } }, { "name": "runCommand", "object": "database", "arguments": { "command": { "collMod": "encryptedCollection", "validator": { "unencrypted_string": "foo" } } } } ] }, { "description": "collMod with a validator on an encrypted field is an error", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "local": { "key": { "$binary": { "base64": "Mng0NCt4ZHVUYUJCa1kxNkVyNUR1QURhZ2h2UzR2d2RrZzh0cFBwM3R6NmdWMDFBMUN3YkQ5aXRRMkhGRGdQV09wOGVNYUMxT2k3NjZKelhaQmRCZGJkTXVyZG9uSjFk", "subType": "00" } } } }, "encryptedFieldsMap": { "default.encryptedCollection": { "fields": [ { "keyId": { "$binary": { "base64": "EjRWeBI0mHYSNBI0VniQEg==", "subType": "04" } }, "path": "encryptedIndexed", "bsonType": "string", "queries": { "queryType": "equality", "contention": { "$numberLong": "0" } } }, { "keyId": { "$binary": { "base64": "q83vqxI0mHYSNBI0VniQEg==", "subType": "04" } }, "path": "encryptedUnindexed", "bsonType": "string" } ] } } } }, "operations": [ { "name": "dropCollection", "object": "database", "arguments": { "collection": "encryptedCollection" } }, { "name": "createCollection", "object": "database", "arguments": { "collection": "encryptedCollection" } }, { "name": "runCommand", "object": "database", "arguments": { "command": { "collMod": "encryptedCollection", "validator": { "encryptedIndexed": "foo" } } }, "result": { "errorContains": "Comparison to encrypted fields not supported" } } ] }, { "description": "createIndexes with a partialFilterExpression on an unencrypted field is OK", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "local": { "key": { "$binary": { "base64": "Mng0NCt4ZHVUYUJCa1kxNkVyNUR1QURhZ2h2UzR2d2RrZzh0cFBwM3R6NmdWMDFBMUN3YkQ5aXRRMkhGRGdQV09wOGVNYUMxT2k3NjZKelhaQmRCZGJkTXVyZG9uSjFk", "subType": "00" } } } }, "encryptedFieldsMap": { "default.encryptedCollection": { "fields": [ { "keyId": { "$binary": { "base64": "EjRWeBI0mHYSNBI0VniQEg==", "subType": "04" } }, "path": "encryptedIndexed", "bsonType": "string", "queries": { "queryType": "equality", "contention": { "$numberLong": "0" } } }, { "keyId": { "$binary": { "base64": "q83vqxI0mHYSNBI0VniQEg==", "subType": "04" } }, "path": "encryptedUnindexed", "bsonType": "string" } ] } } } }, "operations": [ { "name": "dropCollection", "object": "database", "arguments": { "collection": "encryptedCollection" } }, { "name": "createCollection", "object": "database", "arguments": { "collection": "encryptedCollection" } }, { "name": "runCommand", "object": "database", "arguments": { "command": { "createIndexes": "encryptedCollection", "indexes": [ { "name": "name", "key": { "name": 1 }, "partialFilterExpression": { "unencrypted_string": "foo" } } ] } } }, { "name": "assertIndexExists", "object": "testRunner", "arguments": { "database": "default", "collection": "encryptedCollection", "index": "name" } } ] }, { "description": "createIndexes with a partialFilterExpression on an encrypted field is an error", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "local": { "key": { "$binary": { "base64": "Mng0NCt4ZHVUYUJCa1kxNkVyNUR1QURhZ2h2UzR2d2RrZzh0cFBwM3R6NmdWMDFBMUN3YkQ5aXRRMkhGRGdQV09wOGVNYUMxT2k3NjZKelhaQmRCZGJkTXVyZG9uSjFk", "subType": "00" } } } }, "encryptedFieldsMap": { "default.encryptedCollection": { "fields": [ { "keyId": { "$binary": { "base64": "EjRWeBI0mHYSNBI0VniQEg==", "subType": "04" } }, "path": "encryptedIndexed", "bsonType": "string", "queries": { "queryType": "equality", "contention": { "$numberLong": "0" } } }, { "keyId": { "$binary": { "base64": "q83vqxI0mHYSNBI0VniQEg==", "subType": "04" } }, "path": "encryptedUnindexed", "bsonType": "string" } ] } } } }, "operations": [ { "name": "dropCollection", "object": "database", "arguments": { "collection": "encryptedCollection" } }, { "name": "createCollection", "object": "database", "arguments": { "collection": "encryptedCollection" } }, { "name": "runCommand", "object": "database", "arguments": { "command": { "createIndexes": "encryptedCollection", "indexes": [ { "name": "name", "key": { "name": 1 }, "partialFilterExpression": { "encryptedIndexed": "foo" } } ] } }, "result": { "errorContains": "Comparison to encrypted fields not supported" } } ] } ] } mongodb-mongo-python-driver-509e9b7/test/client-side-encryption/spec/legacy/gcpKMS.json000066400000000000000000000131451462766011000312250ustar00rootroot00000000000000{ "runOn": [ { "minServerVersion": "4.1.10" } ], "database_name": "default", "collection_name": "default", "data": [], "json_schema": { "properties": { "encrypted_string_aws": { "encrypt": { "keyId": [ { "$binary": { "base64": "AAAAAAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "bsonType": "string", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" } }, "encrypted_string_azure": { "encrypt": { "keyId": [ { "$binary": { "base64": "AZURE+AAAAAAAAAAAAAAAA==", "subType": "04" } } ], "bsonType": "string", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" } }, "encrypted_string_gcp": { "encrypt": { "keyId": [ { "$binary": { "base64": "GCP+AAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "bsonType": "string", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" } }, "encrypted_string_local": { "encrypt": { "keyId": [ { "$binary": { "base64": "AAAAAAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "bsonType": "string", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" } }, "encrypted_string_kmip": { "encrypt": { "keyId": [ { "$binary": { "base64": "dBHpr8aITfeBQ15grpbLpQ==", "subType": "04" } } ], "bsonType": "string", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" } } }, "bsonType": "object" }, "key_vault_data": [ { "_id": { "$binary": { "base64": "GCP+AAAAAAAAAAAAAAAAAA==", "subType": "04" } }, "keyMaterial": { "$binary": { "base64": "CiQAIgLj0WyktnB4dfYHo5SLZ41K4ASQrjJUaSzl5vvVH0G12G0SiQEAjlV8XPlbnHDEDFbdTO4QIe8ER2/172U1ouLazG0ysDtFFIlSvWX5ZnZUrRMmp/R2aJkzLXEt/zf8Mn4Lfm+itnjgo5R9K4pmPNvvPKNZX5C16lrPT+aA+rd+zXFSmlMg3i5jnxvTdLHhg3G7Q/Uv1ZIJskKt95bzLoe0tUVzRWMYXLIEcohnQg==", "subType": "00" } }, "creationDate": { "$date": { "$numberLong": "1601574333107" } }, "updateDate": { "$date": { "$numberLong": "1601574333107" } }, "status": { "$numberInt": "0" }, "masterKey": { "provider": "gcp", "projectId": "devprod-drivers", "location": "global", "keyRing": "key-ring-csfle", "keyName": "key-name-csfle" }, "keyAltNames": [ "altname", "gcp_altname" ] } ], "tests": [ { "description": "Insert a document with auto encryption using GCP KMS provider", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "gcp": {} } } }, "operations": [ { "name": "insertOne", "arguments": { "document": { "_id": 1, "encrypted_string_gcp": "string0" } } } ], "expectations": [ { "command_started_event": { "command": { "listCollections": 1, "filter": { "name": "default" } }, "command_name": "listCollections" } }, { "command_started_event": { "command": { "find": "datakeys", "filter": { "$or": [ { "_id": { "$in": [ { "$binary": { "base64": "GCP+AAAAAAAAAAAAAAAAAA==", "subType": "04" } } ] } }, { "keyAltNames": { "$in": [] } } ] }, "$db": "keyvault" }, "command_name": "find" } }, { "command_started_event": { "command": { "insert": "default", "documents": [ { "_id": 1, "encrypted_string_gcp": { "$binary": { "base64": "ARgj/gAAAAAAAAAAAAAAAAACwFd+Y5Ojw45GUXNvbcIpN9YkRdoHDHkR4kssdn0tIMKlDQOLFkWFY9X07IRlXsxPD8DcTiKnl6XINK28vhcGlg==", "subType": "06" } } } ], "ordered": true }, "command_name": "insert" } } ], "outcome": { "collection": { "data": [ { "_id": 1, "encrypted_string_gcp": { "$binary": { "base64": "ARgj/gAAAAAAAAAAAAAAAAACwFd+Y5Ojw45GUXNvbcIpN9YkRdoHDHkR4kssdn0tIMKlDQOLFkWFY9X07IRlXsxPD8DcTiKnl6XINK28vhcGlg==", "subType": "06" } } } ] } } } ] } mongodb-mongo-python-driver-509e9b7/test/client-side-encryption/spec/legacy/getMore.json000066400000000000000000000153641462766011000315100ustar00rootroot00000000000000{ "runOn": [ { "minServerVersion": "4.1.10" } ], "database_name": "default", "collection_name": "default", "data": [ { "_id": 1, "encrypted_string": { "$binary": { "base64": "AQAAAAAAAAAAAAAAAAAAAAACwj+3zkv2VM+aTfk60RqhXq6a/77WlLwu/BxXFkL7EppGsju/m8f0x5kBDD3EZTtGALGXlym5jnpZAoSIkswHoA==", "subType": "06" } } }, { "_id": 2, "encrypted_string": { "$binary": { "base64": "AQAAAAAAAAAAAAAAAAAAAAACDdw4KFz3ZLquhsbt7RmDjD0N67n0uSXx7IGnQNCLeIKvot6s/ouI21Eo84IOtb6lhwUNPlSEBNY0/hbszWAKJg==", "subType": "06" } } }, { "_id": 3, "encrypted_string": { "$binary": { "base64": "AQAAAAAAAAAAAAAAAAAAAAACQ76HWOut3DZtQuV90hp1aaCpZn95vZIaWmn+wrBehcEtcFwyJlBdlyzDzZTWPZCPgiFq72Wvh6Y7VbpU9NAp3A==", "subType": "06" } } } ], "json_schema": { "properties": { "encrypted_w_altname": { "encrypt": { "keyId": "/altname", "bsonType": "string", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Random" } }, "encrypted_string": { "encrypt": { "keyId": [ { "$binary": { "base64": "AAAAAAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "bsonType": "string", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" } }, "random": { "encrypt": { "keyId": [ { "$binary": { "base64": "AAAAAAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "bsonType": "string", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Random" } }, "encrypted_string_equivalent": { "encrypt": { "keyId": [ { "$binary": { "base64": "AAAAAAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "bsonType": "string", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" } } }, "bsonType": "object" }, "key_vault_data": [ { "status": 1, "_id": { "$binary": { "base64": "AAAAAAAAAAAAAAAAAAAAAA==", "subType": "04" } }, "masterKey": { "provider": "aws", "key": "arn:aws:kms:us-east-1:579766882180:key/89fcc2c4-08b0-4bd9-9f25-e30687b580d0", "region": "us-east-1" }, "updateDate": { "$date": { "$numberLong": "1552949630483" } }, "keyMaterial": { "$binary": { "base64": "AQICAHhQNmWG2CzOm1dq3kWLM+iDUZhEqnhJwH9wZVpuZ94A8gEqnsxXlR51T5EbEVezUqqKAAAAwjCBvwYJKoZIhvcNAQcGoIGxMIGuAgEAMIGoBgkqhkiG9w0BBwEwHgYJYIZIAWUDBAEuMBEEDHa4jo6yp0Z18KgbUgIBEIB74sKxWtV8/YHje5lv5THTl0HIbhSwM6EqRlmBiFFatmEWaeMk4tO4xBX65eq670I5TWPSLMzpp8ncGHMmvHqRajNBnmFtbYxN3E3/WjxmdbOOe+OXpnGJPcGsftc7cB2shRfA4lICPnE26+oVNXT6p0Lo20nY5XC7jyCO", "subType": "00" } }, "creationDate": { "$date": { "$numberLong": "1552949630483" } }, "keyAltNames": [ "altname", "another_altname" ] } ], "tests": [ { "description": "getMore with encryption", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "aws": {} } } }, "operations": [ { "name": "find", "arguments": { "batchSize": 2, "filter": {} }, "result": [ { "_id": 1, "encrypted_string": "string0" }, { "_id": 2, "encrypted_string": "string1" }, { "_id": 3, "encrypted_string": "string2" } ] } ], "expectations": [ { "command_started_event": { "command": { "listCollections": 1, "filter": { "name": "default" } }, "command_name": "listCollections" } }, { "command_started_event": { "command": { "find": "default", "batchSize": 2 }, "command_name": "find" } }, { "command_started_event": { "command": { "find": "datakeys", "filter": { "$or": [ { "_id": { "$in": [ { "$binary": { "base64": "AAAAAAAAAAAAAAAAAAAAAA==", "subType": "04" } } ] } }, { "keyAltNames": { "$in": [] } } ] }, "$db": "keyvault", "readConcern": { "level": "majority" } }, "command_name": "find" } }, { "command_started_event": { "command": { "getMore": { "$$type": [ "int", "long" ] }, "collection": "default", "batchSize": 2 }, "command_name": "getMore" } } ], "outcome": { "collection": { "data": [ { "_id": 1, "encrypted_string": { "$binary": { "base64": "AQAAAAAAAAAAAAAAAAAAAAACwj+3zkv2VM+aTfk60RqhXq6a/77WlLwu/BxXFkL7EppGsju/m8f0x5kBDD3EZTtGALGXlym5jnpZAoSIkswHoA==", "subType": "06" } } }, { "_id": 2, "encrypted_string": { "$binary": { "base64": "AQAAAAAAAAAAAAAAAAAAAAACDdw4KFz3ZLquhsbt7RmDjD0N67n0uSXx7IGnQNCLeIKvot6s/ouI21Eo84IOtb6lhwUNPlSEBNY0/hbszWAKJg==", "subType": "06" } } }, { "_id": 3, "encrypted_string": { "$binary": { "base64": "AQAAAAAAAAAAAAAAAAAAAAACQ76HWOut3DZtQuV90hp1aaCpZn95vZIaWmn+wrBehcEtcFwyJlBdlyzDzZTWPZCPgiFq72Wvh6Y7VbpU9NAp3A==", "subType": "06" } } } ] } } } ] } mongodb-mongo-python-driver-509e9b7/test/client-side-encryption/spec/legacy/insert.json000066400000000000000000000217131462766011000314050ustar00rootroot00000000000000{ "runOn": [ { "minServerVersion": "4.1.10" } ], "database_name": "default", "collection_name": "default", "data": [], "json_schema": { "properties": { "encrypted_w_altname": { "encrypt": { "keyId": "/altname", "bsonType": "string", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Random" } }, "encrypted_string": { "encrypt": { "keyId": [ { "$binary": { "base64": "AAAAAAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "bsonType": "string", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" } }, "random": { "encrypt": { "keyId": [ { "$binary": { "base64": "AAAAAAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "bsonType": "string", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Random" } }, "encrypted_string_equivalent": { "encrypt": { "keyId": [ { "$binary": { "base64": "AAAAAAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "bsonType": "string", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" } } }, "bsonType": "object" }, "key_vault_data": [ { "status": 1, "_id": { "$binary": { "base64": "AAAAAAAAAAAAAAAAAAAAAA==", "subType": "04" } }, "masterKey": { "provider": "aws", "key": "arn:aws:kms:us-east-1:579766882180:key/89fcc2c4-08b0-4bd9-9f25-e30687b580d0", "region": "us-east-1" }, "updateDate": { "$date": { "$numberLong": "1552949630483" } }, "keyMaterial": { "$binary": { "base64": "AQICAHhQNmWG2CzOm1dq3kWLM+iDUZhEqnhJwH9wZVpuZ94A8gEqnsxXlR51T5EbEVezUqqKAAAAwjCBvwYJKoZIhvcNAQcGoIGxMIGuAgEAMIGoBgkqhkiG9w0BBwEwHgYJYIZIAWUDBAEuMBEEDHa4jo6yp0Z18KgbUgIBEIB74sKxWtV8/YHje5lv5THTl0HIbhSwM6EqRlmBiFFatmEWaeMk4tO4xBX65eq670I5TWPSLMzpp8ncGHMmvHqRajNBnmFtbYxN3E3/WjxmdbOOe+OXpnGJPcGsftc7cB2shRfA4lICPnE26+oVNXT6p0Lo20nY5XC7jyCO", "subType": "00" } }, "creationDate": { "$date": { "$numberLong": "1552949630483" } }, "keyAltNames": [ "altname", "another_altname" ] } ], "tests": [ { "description": "insertOne with encryption", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "aws": {} } } }, "operations": [ { "name": "insertOne", "arguments": { "document": { "_id": 1, "encrypted_string": "string0", "random": "abc" } } } ], "expectations": [ { "command_started_event": { "command": { "listCollections": 1, "filter": { "name": "default" } }, "command_name": "listCollections" } }, { "command_started_event": { "command": { "find": "datakeys", "filter": { "$or": [ { "_id": { "$in": [ { "$binary": { "base64": "AAAAAAAAAAAAAAAAAAAAAA==", "subType": "04" } } ] } }, { "keyAltNames": { "$in": [] } } ] }, "$db": "keyvault", "readConcern": { "level": "majority" } }, "command_name": "find" } }, { "command_started_event": { "command": { "insert": "default", "documents": [ { "_id": 1, "encrypted_string": { "$binary": { "base64": "AQAAAAAAAAAAAAAAAAAAAAACwj+3zkv2VM+aTfk60RqhXq6a/77WlLwu/BxXFkL7EppGsju/m8f0x5kBDD3EZTtGALGXlym5jnpZAoSIkswHoA==", "subType": "06" } }, "random": { "$$type": "binData" } } ], "ordered": true }, "command_name": "insert" } } ], "outcome": { "collection": { "data": [ { "_id": 1, "encrypted_string": { "$binary": { "base64": "AQAAAAAAAAAAAAAAAAAAAAACwj+3zkv2VM+aTfk60RqhXq6a/77WlLwu/BxXFkL7EppGsju/m8f0x5kBDD3EZTtGALGXlym5jnpZAoSIkswHoA==", "subType": "06" } }, "random": { "$$type": "binData" } } ] } } }, { "description": "insertMany with encryption", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "aws": {} } } }, "operations": [ { "name": "insertMany", "arguments": { "documents": [ { "_id": 1, "encrypted_string": "string0", "random": "abc" }, { "_id": 2, "encrypted_string": "string1" } ] } } ], "expectations": [ { "command_started_event": { "command": { "listCollections": 1, "filter": { "name": "default" } }, "command_name": "listCollections" } }, { "command_started_event": { "command": { "find": "datakeys", "filter": { "$or": [ { "_id": { "$in": [ { "$binary": { "base64": "AAAAAAAAAAAAAAAAAAAAAA==", "subType": "04" } } ] } }, { "keyAltNames": { "$in": [] } } ] }, "$db": "keyvault", "readConcern": { "level": "majority" } }, "command_name": "find" } }, { "command_started_event": { "command": { "insert": "default", "documents": [ { "_id": 1, "encrypted_string": { "$binary": { "base64": "AQAAAAAAAAAAAAAAAAAAAAACwj+3zkv2VM+aTfk60RqhXq6a/77WlLwu/BxXFkL7EppGsju/m8f0x5kBDD3EZTtGALGXlym5jnpZAoSIkswHoA==", "subType": "06" } }, "random": { "$$type": "binData" } }, { "_id": 2, "encrypted_string": { "$binary": { "base64": "AQAAAAAAAAAAAAAAAAAAAAACDdw4KFz3ZLquhsbt7RmDjD0N67n0uSXx7IGnQNCLeIKvot6s/ouI21Eo84IOtb6lhwUNPlSEBNY0/hbszWAKJg==", "subType": "06" } } } ], "ordered": true }, "command_name": "insert" } } ], "outcome": { "collection": { "data": [ { "_id": 1, "encrypted_string": { "$binary": { "base64": "AQAAAAAAAAAAAAAAAAAAAAACwj+3zkv2VM+aTfk60RqhXq6a/77WlLwu/BxXFkL7EppGsju/m8f0x5kBDD3EZTtGALGXlym5jnpZAoSIkswHoA==", "subType": "06" } }, "random": { "$$type": "binData" } }, { "_id": 2, "encrypted_string": { "$binary": { "base64": "AQAAAAAAAAAAAAAAAAAAAAACDdw4KFz3ZLquhsbt7RmDjD0N67n0uSXx7IGnQNCLeIKvot6s/ouI21Eo84IOtb6lhwUNPlSEBNY0/hbszWAKJg==", "subType": "06" } } } ] } } } ] } mongodb-mongo-python-driver-509e9b7/test/client-side-encryption/spec/legacy/keyAltName.json000066400000000000000000000126131462766011000321320ustar00rootroot00000000000000{ "runOn": [ { "minServerVersion": "4.1.10" } ], "database_name": "default", "collection_name": "default", "data": [], "json_schema": { "properties": { "encrypted_w_altname": { "encrypt": { "keyId": "/altname", "bsonType": "string", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Random" } }, "encrypted_string": { "encrypt": { "keyId": [ { "$binary": { "base64": "AAAAAAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "bsonType": "string", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" } }, "random": { "encrypt": { "keyId": [ { "$binary": { "base64": "AAAAAAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "bsonType": "string", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Random" } }, "encrypted_string_equivalent": { "encrypt": { "keyId": [ { "$binary": { "base64": "AAAAAAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "bsonType": "string", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" } } }, "bsonType": "object" }, "key_vault_data": [ { "status": 1, "_id": { "$binary": { "base64": "AAAAAAAAAAAAAAAAAAAAAA==", "subType": "04" } }, "masterKey": { "provider": "aws", "key": "arn:aws:kms:us-east-1:579766882180:key/89fcc2c4-08b0-4bd9-9f25-e30687b580d0", "region": "us-east-1" }, "updateDate": { "$date": { "$numberLong": "1552949630483" } }, "keyMaterial": { "$binary": { "base64": "AQICAHhQNmWG2CzOm1dq3kWLM+iDUZhEqnhJwH9wZVpuZ94A8gEqnsxXlR51T5EbEVezUqqKAAAAwjCBvwYJKoZIhvcNAQcGoIGxMIGuAgEAMIGoBgkqhkiG9w0BBwEwHgYJYIZIAWUDBAEuMBEEDHa4jo6yp0Z18KgbUgIBEIB74sKxWtV8/YHje5lv5THTl0HIbhSwM6EqRlmBiFFatmEWaeMk4tO4xBX65eq670I5TWPSLMzpp8ncGHMmvHqRajNBnmFtbYxN3E3/WjxmdbOOe+OXpnGJPcGsftc7cB2shRfA4lICPnE26+oVNXT6p0Lo20nY5XC7jyCO", "subType": "00" } }, "creationDate": { "$date": { "$numberLong": "1552949630483" } }, "keyAltNames": [ "altname", "another_altname" ] } ], "tests": [ { "description": "Insert with encryption using key alt name", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "aws": {} } } }, "operations": [ { "name": "insertOne", "arguments": { "document": { "_id": 1, "encrypted_w_altname": "string0", "altname": "altname" } } } ], "expectations": [ { "command_started_event": { "command": { "listCollections": 1, "filter": { "name": "default" } }, "command_name": "listCollections" } }, { "command_started_event": { "command": { "find": "datakeys", "filter": { "$or": [ { "_id": { "$in": [] } }, { "keyAltNames": { "$in": [ "altname" ] } } ] }, "$db": "keyvault", "readConcern": { "level": "majority" } }, "command_name": "find" } }, { "command_started_event": { "command": { "insert": "default", "documents": [ { "_id": 1, "encrypted_w_altname": { "$$type": "binData" }, "altname": "altname" } ], "ordered": true }, "command_name": "insert" } } ], "outcome": { "collection": { "data": [ { "_id": 1, "encrypted_w_altname": { "$$type": "binData" }, "altname": "altname" } ] } } }, { "description": "Replace with key alt name fails", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "aws": {} } } }, "operations": [ { "name": "updateOne", "arguments": { "filter": {}, "update": { "$set": { "encrypted_w_altname": "string0" } }, "upsert": true }, "result": { "errorContains": "A non-static (JSONPointer) keyId is not supported" } } ], "outcome": { "collection": { "data": [] } } } ] } mongodb-mongo-python-driver-509e9b7/test/client-side-encryption/spec/legacy/kmipKMS.json000066400000000000000000000127321462766011000314150ustar00rootroot00000000000000{ "runOn": [ { "minServerVersion": "4.1.10" } ], "database_name": "default", "collection_name": "default", "data": [], "json_schema": { "properties": { "encrypted_string_aws": { "encrypt": { "keyId": [ { "$binary": { "base64": "AAAAAAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "bsonType": "string", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" } }, "encrypted_string_azure": { "encrypt": { "keyId": [ { "$binary": { "base64": "AZURE+AAAAAAAAAAAAAAAA==", "subType": "04" } } ], "bsonType": "string", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" } }, "encrypted_string_gcp": { "encrypt": { "keyId": [ { "$binary": { "base64": "GCP+AAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "bsonType": "string", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" } }, "encrypted_string_local": { "encrypt": { "keyId": [ { "$binary": { "base64": "AAAAAAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "bsonType": "string", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" } }, "encrypted_string_kmip": { "encrypt": { "keyId": [ { "$binary": { "base64": "dBHpr8aITfeBQ15grpbLpQ==", "subType": "04" } } ], "bsonType": "string", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" } } }, "bsonType": "object" }, "key_vault_data": [ { "_id": { "$binary": { "base64": "dBHpr8aITfeBQ15grpbLpQ==", "subType": "04" } }, "keyMaterial": { "$binary": { "base64": "eUYDyB0HuWb+lQgUwO+6qJQyTTDTY2gp9FbemL7ZFo0pvr0x6rm6Ff9OVUTGH6HyMKipaeHdiIJU1dzsLwvqKvi7Beh+U4iaIWX/K0oEg1GOsJc0+Z/in8gNHbGUYLmycHViM3LES3kdt7FdFSUl5rEBHrM71yoNEXImz17QJWMGOuT4x6yoi2pvnaRJwfrI4DjpmnnTrDMac92jgZehbg==", "subType": "00" } }, "creationDate": { "$date": { "$numberLong": "1634220190041" } }, "updateDate": { "$date": { "$numberLong": "1634220190041" } }, "status": { "$numberInt": "0" }, "masterKey": { "provider": "kmip", "keyId": "1" }, "keyAltNames": [ "altname", "kmip_altname" ] } ], "tests": [ { "description": "Insert a document with auto encryption using KMIP KMS provider", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "kmip": {} } } }, "operations": [ { "name": "insertOne", "arguments": { "document": { "_id": 1, "encrypted_string_kmip": "string0" } } } ], "expectations": [ { "command_started_event": { "command": { "listCollections": 1, "filter": { "name": "default" } }, "command_name": "listCollections" } }, { "command_started_event": { "command": { "find": "datakeys", "filter": { "$or": [ { "_id": { "$in": [ { "$binary": { "base64": "dBHpr8aITfeBQ15grpbLpQ==", "subType": "04" } } ] } }, { "keyAltNames": { "$in": [] } } ] }, "$db": "keyvault" }, "command_name": "find" } }, { "command_started_event": { "command": { "insert": "default", "documents": [ { "_id": 1, "encrypted_string_kmip": { "$binary": { "base64": "AXQR6a/GiE33gUNeYK6Wy6UCKCwtKFIsL8eKObDVxvqGupJNUk7kXswHhB7G5j/C1D+6no+Asra0KgSU43bTL3ooIBLVyIzbV5CDJYqzAsa4WQ==", "subType": "06" } } } ], "ordered": true }, "command_name": "insert" } } ], "outcome": { "collection": { "data": [ { "_id": 1, "encrypted_string_kmip": { "$binary": { "base64": "AXQR6a/GiE33gUNeYK6Wy6UCKCwtKFIsL8eKObDVxvqGupJNUk7kXswHhB7G5j/C1D+6no+Asra0KgSU43bTL3ooIBLVyIzbV5CDJYqzAsa4WQ==", "subType": "06" } } } ] } } } ] } mongodb-mongo-python-driver-509e9b7/test/client-side-encryption/spec/legacy/localKMS.json000066400000000000000000000114211462766011000315410ustar00rootroot00000000000000{ "runOn": [ { "minServerVersion": "4.1.10" } ], "database_name": "default", "collection_name": "default", "data": [], "json_schema": { "properties": { "encrypted_string": { "encrypt": { "keyId": [ { "$binary": { "base64": "AAAAAAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "bsonType": "string", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" } }, "random": { "encrypt": { "keyId": [ { "$binary": { "base64": "AAAAAAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "bsonType": "string", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Random" } } }, "bsonType": "object" }, "key_vault_data": [ { "_id": { "$binary": { "base64": "AAAAAAAAAAAAAAAAAAAAAA==", "subType": "04" } }, "keyMaterial": { "$binary": { "base64": "Ce9HSz/HKKGkIt4uyy+jDuKGA+rLC2cycykMo6vc8jXxqa1UVDYHWq1r+vZKbnnSRBfB981akzRKZCFpC05CTyFqDhXv6OnMjpG97OZEREGIsHEYiJkBW0jJJvfLLgeLsEpBzsro9FztGGXASxyxFRZFhXvHxyiLOKrdWfs7X1O/iK3pEoHMx6uSNSfUOgbebLfIqW7TO++iQS5g1xovXA==", "subType": "00" } }, "creationDate": { "$date": { "$numberLong": "1552949630483" } }, "updateDate": { "$date": { "$numberLong": "1552949630483" } }, "status": { "$numberInt": "0" }, "masterKey": { "provider": "local" } } ], "tests": [ { "description": "Insert a document with auto encryption using local KMS provider", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "aws": {}, "local": { "key": { "$binary": { "base64": "Mng0NCt4ZHVUYUJCa1kxNkVyNUR1QURhZ2h2UzR2d2RrZzh0cFBwM3R6NmdWMDFBMUN3YkQ5aXRRMkhGRGdQV09wOGVNYUMxT2k3NjZKelhaQmRCZGJkTXVyZG9uSjFk", "subType": "00" } } } } } }, "operations": [ { "name": "insertOne", "arguments": { "document": { "_id": 1, "encrypted_string": "string0", "random": "abc" } } } ], "expectations": [ { "command_started_event": { "command": { "listCollections": 1, "filter": { "name": "default" } }, "command_name": "listCollections" } }, { "command_started_event": { "command": { "find": "datakeys", "filter": { "$or": [ { "_id": { "$in": [ { "$binary": { "base64": "AAAAAAAAAAAAAAAAAAAAAA==", "subType": "04" } } ] } }, { "keyAltNames": { "$in": [] } } ] }, "$db": "keyvault" }, "command_name": "find" } }, { "command_started_event": { "command": { "insert": "default", "documents": [ { "_id": 1, "encrypted_string": { "$binary": { "base64": "AQAAAAAAAAAAAAAAAAAAAAACV/+zJmpqMU47yxS/xIVAviGi7wHDuFwaULAixEAoIh0xHz73UYOM3D8D44gcJn67EROjbz4ITpYzzlCJovDL0Q==", "subType": "06" } }, "random": { "$$type": "binData" } } ], "ordered": true }, "command_name": "insert" } } ], "outcome": { "collection": { "data": [ { "_id": 1, "encrypted_string": { "$binary": { "base64": "AQAAAAAAAAAAAAAAAAAAAAACV/+zJmpqMU47yxS/xIVAviGi7wHDuFwaULAixEAoIh0xHz73UYOM3D8D44gcJn67EROjbz4ITpYzzlCJovDL0Q==", "subType": "06" } }, "random": { "$$type": "binData" } } ] } } } ] } mongodb-mongo-python-driver-509e9b7/test/client-side-encryption/spec/legacy/localSchema.json000066400000000000000000000155511462766011000323170ustar00rootroot00000000000000{ "runOn": [ { "minServerVersion": "4.1.10" } ], "database_name": "default", "collection_name": "default", "data": [], "json_schema": {}, "key_vault_data": [ { "status": 1, "_id": { "$binary": { "base64": "AAAAAAAAAAAAAAAAAAAAAA==", "subType": "04" } }, "masterKey": { "provider": "aws", "key": "arn:aws:kms:us-east-1:579766882180:key/89fcc2c4-08b0-4bd9-9f25-e30687b580d0", "region": "us-east-1" }, "updateDate": { "$date": { "$numberLong": "1552949630483" } }, "keyMaterial": { "$binary": { "base64": "AQICAHhQNmWG2CzOm1dq3kWLM+iDUZhEqnhJwH9wZVpuZ94A8gEqnsxXlR51T5EbEVezUqqKAAAAwjCBvwYJKoZIhvcNAQcGoIGxMIGuAgEAMIGoBgkqhkiG9w0BBwEwHgYJYIZIAWUDBAEuMBEEDHa4jo6yp0Z18KgbUgIBEIB74sKxWtV8/YHje5lv5THTl0HIbhSwM6EqRlmBiFFatmEWaeMk4tO4xBX65eq670I5TWPSLMzpp8ncGHMmvHqRajNBnmFtbYxN3E3/WjxmdbOOe+OXpnGJPcGsftc7cB2shRfA4lICPnE26+oVNXT6p0Lo20nY5XC7jyCO", "subType": "00" } }, "creationDate": { "$date": { "$numberLong": "1552949630483" } }, "keyAltNames": [ "altname", "another_altname" ] } ], "tests": [ { "description": "A local schema should override", "clientOptions": { "autoEncryptOpts": { "schemaMap": { "default.default": { "properties": { "encrypted_w_altname": { "encrypt": { "keyId": "/altname", "bsonType": "string", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Random" } }, "encrypted_string": { "encrypt": { "keyId": [ { "$binary": { "base64": "AAAAAAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "bsonType": "string", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" } }, "random": { "encrypt": { "keyId": [ { "$binary": { "base64": "AAAAAAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "bsonType": "string", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Random" } }, "encrypted_string_equivalent": { "encrypt": { "keyId": [ { "$binary": { "base64": "AAAAAAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "bsonType": "string", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" } } }, "bsonType": "object" } }, "kmsProviders": { "aws": {} } } }, "operations": [ { "name": "insertOne", "arguments": { "document": { "_id": 1, "encrypted_string": "string0" } } }, { "name": "find", "arguments": { "filter": { "_id": 1 } }, "result": [ { "_id": 1, "encrypted_string": "string0" } ] } ], "expectations": [ { "command_started_event": { "command": { "find": "datakeys", "filter": { "$or": [ { "_id": { "$in": [ { "$binary": { "base64": "AAAAAAAAAAAAAAAAAAAAAA==", "subType": "04" } } ] } }, { "keyAltNames": { "$in": [] } } ] }, "$db": "keyvault", "readConcern": { "level": "majority" } }, "command_name": "find" } }, { "command_started_event": { "command": { "insert": "default", "documents": [ { "_id": 1, "encrypted_string": { "$binary": { "base64": "AQAAAAAAAAAAAAAAAAAAAAACwj+3zkv2VM+aTfk60RqhXq6a/77WlLwu/BxXFkL7EppGsju/m8f0x5kBDD3EZTtGALGXlym5jnpZAoSIkswHoA==", "subType": "06" } } } ], "ordered": true }, "command_name": "insert" } }, { "command_started_event": { "command": { "find": "default", "filter": { "_id": 1 } }, "command_name": "find" } } ], "outcome": { "collection": { "data": [ { "_id": 1, "encrypted_string": { "$binary": { "base64": "AQAAAAAAAAAAAAAAAAAAAAACwj+3zkv2VM+aTfk60RqhXq6a/77WlLwu/BxXFkL7EppGsju/m8f0x5kBDD3EZTtGALGXlym5jnpZAoSIkswHoA==", "subType": "06" } } } ] } } }, { "description": "A local schema with no encryption is an error", "clientOptions": { "autoEncryptOpts": { "schemaMap": { "default.default": { "properties": { "test": { "bsonType": "string" } }, "bsonType": "object", "required": [ "test" ] } }, "kmsProviders": { "aws": {} } } }, "operations": [ { "name": "insertOne", "arguments": { "document": { "_id": 1, "encrypted_string": "string0" } }, "result": { "errorContains": "JSON schema keyword 'required' is only allowed with a remote schema" } } ] } ] } mongodb-mongo-python-driver-509e9b7/test/client-side-encryption/spec/legacy/malformedCiphertext.json000066400000000000000000000220451462766011000341060ustar00rootroot00000000000000{ "runOn": [ { "minServerVersion": "4.1.10" } ], "database_name": "default", "collection_name": "default", "data": [ { "_id": 1, "encrypted_string": { "$binary": { "base64": "AQAAAAAAAAAAAAAAAAAAAAACDdw4KFz3ZLquhsbt7RmDjD0N67n0uSXx7IGnQNCLeIKvot6s/ouI21Eo84IOtb6lhwUNPlSEBNY0/hbszWAKJg==", "subType": "00" } } }, { "_id": 2, "encrypted_string": { "$binary": { "base64": "AQ==", "subType": "06" } } }, { "_id": 3, "encrypted_string": { "$binary": { "base64": "AQAAa2V2aW4gYWxiZXJ0c29uCg==", "subType": "06" } } } ], "key_vault_data": [ { "status": 1, "_id": { "$binary": { "base64": "AAAAAAAAAAAAAAAAAAAAAA==", "subType": "04" } }, "masterKey": { "provider": "aws", "key": "arn:aws:kms:us-east-1:579766882180:key/89fcc2c4-08b0-4bd9-9f25-e30687b580d0", "region": "us-east-1" }, "updateDate": { "$date": { "$numberLong": "1552949630483" } }, "keyMaterial": { "$binary": { "base64": "AQICAHhQNmWG2CzOm1dq3kWLM+iDUZhEqnhJwH9wZVpuZ94A8gEqnsxXlR51T5EbEVezUqqKAAAAwjCBvwYJKoZIhvcNAQcGoIGxMIGuAgEAMIGoBgkqhkiG9w0BBwEwHgYJYIZIAWUDBAEuMBEEDHa4jo6yp0Z18KgbUgIBEIB74sKxWtV8/YHje5lv5THTl0HIbhSwM6EqRlmBiFFatmEWaeMk4tO4xBX65eq670I5TWPSLMzpp8ncGHMmvHqRajNBnmFtbYxN3E3/WjxmdbOOe+OXpnGJPcGsftc7cB2shRfA4lICPnE26+oVNXT6p0Lo20nY5XC7jyCO", "subType": "00" } }, "creationDate": { "$date": { "$numberLong": "1552949630483" } }, "keyAltNames": [ "altname", "another_altname" ] } ], "tests": [ { "description": "Wrong subtype", "clientOptions": { "autoEncryptOpts": { "schemaMap": { "default.default": { "properties": { "encrypted_w_altname": { "encrypt": { "keyId": "/altname", "bsonType": "string", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Random" } }, "encrypted_string": { "encrypt": { "keyId": [ { "$binary": { "base64": "AAAAAAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "bsonType": "string", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" } }, "random": { "encrypt": { "keyId": [ { "$binary": { "base64": "AAAAAAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "bsonType": "string", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Random" } }, "encrypted_string_equivalent": { "encrypt": { "keyId": [ { "$binary": { "base64": "AAAAAAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "bsonType": "string", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" } } }, "bsonType": "object" } }, "kmsProviders": { "aws": {} } } }, "operations": [ { "name": "find", "arguments": { "filter": { "_id": 1 } }, "result": [ { "_id": 1, "encrypted_string": { "$binary": { "base64": "AQAAAAAAAAAAAAAAAAAAAAACDdw4KFz3ZLquhsbt7RmDjD0N67n0uSXx7IGnQNCLeIKvot6s/ouI21Eo84IOtb6lhwUNPlSEBNY0/hbszWAKJg==", "subType": "00" } } } ] } ] }, { "description": "Empty data", "clientOptions": { "autoEncryptOpts": { "schemaMap": { "default.default": { "properties": { "encrypted_w_altname": { "encrypt": { "keyId": "/altname", "bsonType": "string", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Random" } }, "encrypted_string": { "encrypt": { "keyId": [ { "$binary": { "base64": "AAAAAAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "bsonType": "string", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" } }, "random": { "encrypt": { "keyId": [ { "$binary": { "base64": "AAAAAAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "bsonType": "string", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Random" } }, "encrypted_string_equivalent": { "encrypt": { "keyId": [ { "$binary": { "base64": "AAAAAAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "bsonType": "string", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" } } }, "bsonType": "object" } }, "kmsProviders": { "aws": {} } } }, "operations": [ { "name": "find", "arguments": { "filter": { "_id": 2 } }, "result": { "errorContains": "malformed ciphertext" } } ] }, { "description": "Malformed data", "clientOptions": { "autoEncryptOpts": { "schemaMap": { "default.default": { "properties": { "encrypted_w_altname": { "encrypt": { "keyId": "/altname", "bsonType": "string", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Random" } }, "encrypted_string": { "encrypt": { "keyId": [ { "$binary": { "base64": "AAAAAAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "bsonType": "string", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" } }, "random": { "encrypt": { "keyId": [ { "$binary": { "base64": "AAAAAAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "bsonType": "string", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Random" } }, "encrypted_string_equivalent": { "encrypt": { "keyId": [ { "$binary": { "base64": "AAAAAAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "bsonType": "string", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" } } }, "bsonType": "object" } }, "kmsProviders": { "aws": {} } } }, "operations": [ { "name": "find", "arguments": { "filter": { "_id": 3 } }, "result": { "errorContains": "not all keys requested were satisfied" } } ] } ] } mongodb-mongo-python-driver-509e9b7/test/client-side-encryption/spec/legacy/maxWireVersion.json000066400000000000000000000035301462766011000330600ustar00rootroot00000000000000{ "runOn": [ { "maxServerVersion": "4.0.99" } ], "database_name": "default", "collection_name": "default", "data": [], "key_vault_data": [ { "status": 1, "_id": { "$binary": { "base64": "AAAAAAAAAAAAAAAAAAAAAA==", "subType": "04" } }, "masterKey": { "provider": "aws", "key": "arn:aws:kms:us-east-1:579766882180:key/89fcc2c4-08b0-4bd9-9f25-e30687b580d0", "region": "us-east-1" }, "updateDate": { "$date": { "$numberLong": "1552949630483" } }, "keyMaterial": { "$binary": { "base64": "AQICAHhQNmWG2CzOm1dq3kWLM+iDUZhEqnhJwH9wZVpuZ94A8gEqnsxXlR51T5EbEVezUqqKAAAAwjCBvwYJKoZIhvcNAQcGoIGxMIGuAgEAMIGoBgkqhkiG9w0BBwEwHgYJYIZIAWUDBAEuMBEEDHa4jo6yp0Z18KgbUgIBEIB74sKxWtV8/YHje5lv5THTl0HIbhSwM6EqRlmBiFFatmEWaeMk4tO4xBX65eq670I5TWPSLMzpp8ncGHMmvHqRajNBnmFtbYxN3E3/WjxmdbOOe+OXpnGJPcGsftc7cB2shRfA4lICPnE26+oVNXT6p0Lo20nY5XC7jyCO", "subType": "00" } }, "creationDate": { "$date": { "$numberLong": "1552949630483" } }, "keyAltNames": [ "altname", "another_altname" ] } ], "tests": [ { "description": "operation fails with maxWireVersion < 8", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "aws": {} }, "extraOptions": { "mongocryptdBypassSpawn": true } } }, "operations": [ { "name": "insertOne", "arguments": { "document": { "encrypted_string": "string0" } }, "result": { "errorContains": "Auto-encryption requires a minimum MongoDB version of 4.2" } } ] } ] } mongodb-mongo-python-driver-509e9b7/test/client-side-encryption/spec/legacy/missingKey.json000066400000000000000000000106251462766011000322230ustar00rootroot00000000000000{ "runOn": [ { "minServerVersion": "4.1.10" } ], "database_name": "default", "collection_name": "default", "data": [], "json_schema": { "properties": { "encrypted_w_altname": { "encrypt": { "keyId": "/altname", "bsonType": "string", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Random" } }, "encrypted_string": { "encrypt": { "keyId": [ { "$binary": { "base64": "AAAAAAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "bsonType": "string", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" } }, "random": { "encrypt": { "keyId": [ { "$binary": { "base64": "AAAAAAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "bsonType": "string", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Random" } }, "encrypted_string_equivalent": { "encrypt": { "keyId": [ { "$binary": { "base64": "AAAAAAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "bsonType": "string", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" } } }, "bsonType": "object" }, "key_vault_data": [ { "status": 1, "_id": { "$binary": { "base64": "AAAAAAAAAAAAAAAAAAAAAA==", "subType": "04" } }, "masterKey": { "provider": "aws", "key": "arn:aws:kms:us-east-1:579766882180:key/89fcc2c4-08b0-4bd9-9f25-e30687b580d0", "region": "us-east-1" }, "updateDate": { "$date": { "$numberLong": "1552949630483" } }, "keyMaterial": { "$binary": { "base64": "AQICAHhQNmWG2CzOm1dq3kWLM+iDUZhEqnhJwH9wZVpuZ94A8gEqnsxXlR51T5EbEVezUqqKAAAAwjCBvwYJKoZIhvcNAQcGoIGxMIGuAgEAMIGoBgkqhkiG9w0BBwEwHgYJYIZIAWUDBAEuMBEEDHa4jo6yp0Z18KgbUgIBEIB74sKxWtV8/YHje5lv5THTl0HIbhSwM6EqRlmBiFFatmEWaeMk4tO4xBX65eq670I5TWPSLMzpp8ncGHMmvHqRajNBnmFtbYxN3E3/WjxmdbOOe+OXpnGJPcGsftc7cB2shRfA4lICPnE26+oVNXT6p0Lo20nY5XC7jyCO", "subType": "00" } }, "creationDate": { "$date": { "$numberLong": "1552949630483" } }, "keyAltNames": [ "altname", "another_altname" ] } ], "tests": [ { "description": "Insert with encryption on a missing key", "clientOptions": { "autoEncryptOpts": { "keyVaultNamespace": "keyvault.different", "kmsProviders": { "aws": {} } } }, "operations": [ { "name": "insertOne", "arguments": { "document": { "_id": 1, "encrypted_string": "string0", "random": "abc" } }, "result": { "errorContains": "not all keys requested were satisfied" } } ], "outcome": { "collection": { "data": [] } }, "expectations": [ { "command_started_event": { "command": { "listCollections": 1, "filter": { "name": "default" } }, "command_name": "listCollections" } }, { "command_started_event": { "command": { "find": "different", "filter": { "$or": [ { "_id": { "$in": [ { "$binary": { "base64": "AAAAAAAAAAAAAAAAAAAAAA==", "subType": "04" } } ] } }, { "keyAltNames": { "$in": [] } } ] }, "$db": "keyvault", "readConcern": { "level": "majority" } }, "command_name": "find" } } ] } ] } mongodb-mongo-python-driver-509e9b7/test/client-side-encryption/spec/legacy/namedKMS.json000066400000000000000000000114771462766011000315460ustar00rootroot00000000000000{ "runOn": [ { "minServerVersion": "4.1.10" } ], "database_name": "default", "collection_name": "default", "data": [], "json_schema": { "properties": { "encrypted_string": { "encrypt": { "keyId": [ { "$binary": { "base64": "local+name2+AAAAAAAAAA==", "subType": "04" } } ], "bsonType": "string", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" } } }, "bsonType": "object" }, "key_vault_data": [ { "_id": { "$binary": { "base64": "local+name2+AAAAAAAAAA==", "subType": "04" } }, "keyMaterial": { "$binary": { "base64": "DX3iUuOlBsx6wBX9UZ3v/qXk1HNeBace2J+h/JwsDdF/vmSXLZ1l1VmZYIcpVFy6ODhdbzLjd4pNgg9wcm4etYig62KNkmtZ0/s1tAL5VsuW/s7/3PYnYGznZTFhLjIVcOH/RNoRj2eQb/sRTyivL85wePEpAU/JzuBj6qO9Y5txQgs1k0J3aNy10R9aQ8kC1NuSSpLAIXwE6DlNDDJXhw==", "subType": "00" } }, "creationDate": { "$date": { "$numberLong": "1552949630483" } }, "updateDate": { "$date": { "$numberLong": "1552949630483" } }, "status": { "$numberInt": "0" }, "masterKey": { "provider": "local:name2" } } ], "tests": [ { "description": "Automatically encrypt and decrypt with a named KMS provider", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "local:name2": { "key": { "$binary": { "base64": "local+name2+YUJCa1kxNkVyNUR1QURhZ2h2UzR2d2RrZzh0cFBwM3R6NmdWMDFBMUN3YkQ5aXRRMkhGRGdQV09wOGVNYUMxT2k3NjZKelhaQmRCZGJkTXVyZG9uSjFk", "subType": "00" } } } } } }, "operations": [ { "name": "insertOne", "arguments": { "document": { "_id": 1, "encrypted_string": "string0" } } }, { "name": "find", "arguments": { "filter": { "_id": 1 } }, "result": [ { "_id": 1, "encrypted_string": "string0" } ] } ], "expectations": [ { "command_started_event": { "command": { "listCollections": 1, "filter": { "name": "default" } }, "command_name": "listCollections" } }, { "command_started_event": { "command": { "find": "datakeys", "filter": { "$or": [ { "_id": { "$in": [ { "$binary": { "base64": "local+name2+AAAAAAAAAA==", "subType": "04" } } ] } }, { "keyAltNames": { "$in": [] } } ] }, "$db": "keyvault", "readConcern": { "level": "majority" } }, "command_name": "find" } }, { "command_started_event": { "command": { "insert": "default", "documents": [ { "_id": 1, "encrypted_string": { "$binary": { "base64": "AZaHGpfp2pntvgAAAAAAAAAC07sFvTQ0I4O2U49hpr4HezaK44Ivluzv5ntQBTYHDlAJMLyRMyB6Dl+UGHBgqhHe/Xw+pcT9XdiUoOJYAx9g+w==", "subType": "06" } } } ], "ordered": true }, "command_name": "insert" } }, { "command_started_event": { "command": { "find": "default", "filter": { "_id": 1 } }, "command_name": "find" } } ], "outcome": { "collection": { "data": [ { "_id": 1, "encrypted_string": { "$binary": { "base64": "AZaHGpfp2pntvgAAAAAAAAAC07sFvTQ0I4O2U49hpr4HezaK44Ivluzv5ntQBTYHDlAJMLyRMyB6Dl+UGHBgqhHe/Xw+pcT9XdiUoOJYAx9g+w==", "subType": "06" } } } ] } } } ] } mongodb-mongo-python-driver-509e9b7/test/client-side-encryption/spec/legacy/noSchema.json000066400000000000000000000024421462766011000316340ustar00rootroot00000000000000{ "runOn": [ { "minServerVersion": "4.1.10" } ], "database_name": "default", "collection_name": "unencrypted", "tests": [ { "description": "Insert on an unencrypted collection", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "aws": {} } } }, "operations": [ { "name": "insertOne", "arguments": { "document": { "_id": 1 } } } ], "expectations": [ { "command_started_event": { "command": { "listCollections": 1, "filter": { "name": "unencrypted" } }, "command_name": "listCollections" } }, { "command_started_event": { "command": { "insert": "unencrypted", "documents": [ { "_id": 1 } ], "ordered": true }, "command_name": "insert" } } ], "outcome": { "collection": { "data": [ { "_id": 1 } ] } } } ] } mongodb-mongo-python-driver-509e9b7/test/client-side-encryption/spec/legacy/replaceOne.json000066400000000000000000000143421462766011000321560ustar00rootroot00000000000000{ "runOn": [ { "minServerVersion": "4.1.10" } ], "database_name": "default", "collection_name": "default", "data": [ { "_id": 1, "encrypted_string": { "$binary": { "base64": "AQAAAAAAAAAAAAAAAAAAAAACwj+3zkv2VM+aTfk60RqhXq6a/77WlLwu/BxXFkL7EppGsju/m8f0x5kBDD3EZTtGALGXlym5jnpZAoSIkswHoA==", "subType": "06" } } } ], "json_schema": { "properties": { "encrypted_w_altname": { "encrypt": { "keyId": "/altname", "bsonType": "string", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Random" } }, "encrypted_string": { "encrypt": { "keyId": [ { "$binary": { "base64": "AAAAAAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "bsonType": "string", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" } }, "random": { "encrypt": { "keyId": [ { "$binary": { "base64": "AAAAAAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "bsonType": "string", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Random" } }, "encrypted_string_equivalent": { "encrypt": { "keyId": [ { "$binary": { "base64": "AAAAAAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "bsonType": "string", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" } } }, "bsonType": "object" }, "key_vault_data": [ { "status": 1, "_id": { "$binary": { "base64": "AAAAAAAAAAAAAAAAAAAAAA==", "subType": "04" } }, "masterKey": { "provider": "aws", "key": "arn:aws:kms:us-east-1:579766882180:key/89fcc2c4-08b0-4bd9-9f25-e30687b580d0", "region": "us-east-1" }, "updateDate": { "$date": { "$numberLong": "1552949630483" } }, "keyMaterial": { "$binary": { "base64": "AQICAHhQNmWG2CzOm1dq3kWLM+iDUZhEqnhJwH9wZVpuZ94A8gEqnsxXlR51T5EbEVezUqqKAAAAwjCBvwYJKoZIhvcNAQcGoIGxMIGuAgEAMIGoBgkqhkiG9w0BBwEwHgYJYIZIAWUDBAEuMBEEDHa4jo6yp0Z18KgbUgIBEIB74sKxWtV8/YHje5lv5THTl0HIbhSwM6EqRlmBiFFatmEWaeMk4tO4xBX65eq670I5TWPSLMzpp8ncGHMmvHqRajNBnmFtbYxN3E3/WjxmdbOOe+OXpnGJPcGsftc7cB2shRfA4lICPnE26+oVNXT6p0Lo20nY5XC7jyCO", "subType": "00" } }, "creationDate": { "$date": { "$numberLong": "1552949630483" } }, "keyAltNames": [ "altname", "another_altname" ] } ], "tests": [ { "description": "replaceOne with encryption", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "aws": {} } } }, "operations": [ { "name": "replaceOne", "arguments": { "filter": { "encrypted_string": "string0" }, "replacement": { "encrypted_string": "string1", "random": "abc" } }, "result": { "matchedCount": 1, "modifiedCount": 1, "upsertedCount": 0 } } ], "expectations": [ { "command_started_event": { "command": { "listCollections": 1, "filter": { "name": "default" } }, "command_name": "listCollections" } }, { "command_started_event": { "command": { "find": "datakeys", "filter": { "$or": [ { "_id": { "$in": [ { "$binary": { "base64": "AAAAAAAAAAAAAAAAAAAAAA==", "subType": "04" } } ] } }, { "keyAltNames": { "$in": [] } } ] }, "$db": "keyvault", "readConcern": { "level": "majority" } }, "command_name": "find" } }, { "command_started_event": { "command": { "update": "default", "updates": [ { "q": { "encrypted_string": { "$eq": { "$binary": { "base64": "AQAAAAAAAAAAAAAAAAAAAAACwj+3zkv2VM+aTfk60RqhXq6a/77WlLwu/BxXFkL7EppGsju/m8f0x5kBDD3EZTtGALGXlym5jnpZAoSIkswHoA==", "subType": "06" } } } }, "u": { "encrypted_string": { "$binary": { "base64": "AQAAAAAAAAAAAAAAAAAAAAACDdw4KFz3ZLquhsbt7RmDjD0N67n0uSXx7IGnQNCLeIKvot6s/ouI21Eo84IOtb6lhwUNPlSEBNY0/hbszWAKJg==", "subType": "06" } }, "random": { "$$type": "binData" } } } ], "ordered": true }, "command_name": "update" } } ], "outcome": { "collection": { "data": [ { "_id": 1, "encrypted_string": { "$binary": { "base64": "AQAAAAAAAAAAAAAAAAAAAAACDdw4KFz3ZLquhsbt7RmDjD0N67n0uSXx7IGnQNCLeIKvot6s/ouI21Eo84IOtb6lhwUNPlSEBNY0/hbszWAKJg==", "subType": "06" } }, "random": { "$$type": "binData" } } ] } } } ] } mongodb-mongo-python-driver-509e9b7/test/client-side-encryption/spec/legacy/timeoutMS.json000066400000000000000000000113371462766011000320300ustar00rootroot00000000000000{ "runOn": [ { "minServerVersion": "4.4" } ], "database_name": "cse-timeouts-db", "collection_name": "cse-timeouts-coll", "data": [], "json_schema": { "properties": { "encrypted_w_altname": { "encrypt": { "keyId": "/altname", "bsonType": "string", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Random" } }, "encrypted_string": { "encrypt": { "keyId": [ { "$binary": { "base64": "AAAAAAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "bsonType": "string", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" } }, "random": { "encrypt": { "keyId": [ { "$binary": { "base64": "AAAAAAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "bsonType": "string", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Random" } }, "encrypted_string_equivalent": { "encrypt": { "keyId": [ { "$binary": { "base64": "AAAAAAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "bsonType": "string", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" } } }, "bsonType": "object" }, "key_vault_data": [ { "status": 1, "_id": { "$binary": { "base64": "AAAAAAAAAAAAAAAAAAAAAA==", "subType": "04" } }, "masterKey": { "provider": "aws", "key": "arn:aws:kms:us-east-1:579766882180:key/89fcc2c4-08b0-4bd9-9f25-e30687b580d0", "region": "us-east-1" }, "updateDate": { "$date": { "$numberLong": "1552949630483" } }, "keyMaterial": { "$binary": { "base64": "AQICAHhQNmWG2CzOm1dq3kWLM+iDUZhEqnhJwH9wZVpuZ94A8gEqnsxXlR51T5EbEVezUqqKAAAAwjCBvwYJKoZIhvcNAQcGoIGxMIGuAgEAMIGoBgkqhkiG9w0BBwEwHgYJYIZIAWUDBAEuMBEEDHa4jo6yp0Z18KgbUgIBEIB74sKxWtV8/YHje5lv5THTl0HIbhSwM6EqRlmBiFFatmEWaeMk4tO4xBX65eq670I5TWPSLMzpp8ncGHMmvHqRajNBnmFtbYxN3E3/WjxmdbOOe+OXpnGJPcGsftc7cB2shRfA4lICPnE26+oVNXT6p0Lo20nY5XC7jyCO", "subType": "00" } }, "creationDate": { "$date": { "$numberLong": "1552949630483" } }, "keyAltNames": [ "altname", "another_altname" ] } ], "tests": [ { "description": "timeoutMS applied to listCollections to get collection schema", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "listCollections" ], "blockConnection": true, "blockTimeMS": 60 } }, "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "aws": {} } }, "timeoutMS": 50 }, "operations": [ { "name": "insertOne", "arguments": { "document": { "_id": 1, "encrypted_string": "string0", "random": "abc" } }, "result": { "isTimeoutError": true } } ], "expectations": [ { "command_started_event": { "command": { "listCollections": 1, "filter": { "name": "cse-timeouts-coll" }, "maxTimeMS": { "$$type": [ "int", "long" ] } }, "command_name": "listCollections" } } ] }, { "description": "remaining timeoutMS applied to find to get keyvault data", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 3 }, "data": { "failCommands": [ "listCollections", "find" ], "blockConnection": true, "blockTimeMS": 20 } }, "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "aws": {} } }, "timeoutMS": 50 }, "operations": [ { "name": "insertOne", "arguments": { "document": { "_id": 1, "encrypted_string": "string0", "random": "abc" } }, "result": { "isTimeoutError": true } } ] } ] } mongodb-mongo-python-driver-509e9b7/test/client-side-encryption/spec/legacy/types.json000066400000000000000000001236031462766011000312460ustar00rootroot00000000000000{ "runOn": [ { "minServerVersion": "4.1.10" } ], "database_name": "default", "collection_name": "default", "data": [], "json_schema": {}, "key_vault_data": [ { "status": 1, "_id": { "$binary": { "base64": "AAAAAAAAAAAAAAAAAAAAAA==", "subType": "04" } }, "masterKey": { "provider": "aws", "key": "arn:aws:kms:us-east-1:579766882180:key/89fcc2c4-08b0-4bd9-9f25-e30687b580d0", "region": "us-east-1" }, "updateDate": { "$date": { "$numberLong": "1552949630483" } }, "keyMaterial": { "$binary": { "base64": "AQICAHhQNmWG2CzOm1dq3kWLM+iDUZhEqnhJwH9wZVpuZ94A8gEqnsxXlR51T5EbEVezUqqKAAAAwjCBvwYJKoZIhvcNAQcGoIGxMIGuAgEAMIGoBgkqhkiG9w0BBwEwHgYJYIZIAWUDBAEuMBEEDHa4jo6yp0Z18KgbUgIBEIB74sKxWtV8/YHje5lv5THTl0HIbhSwM6EqRlmBiFFatmEWaeMk4tO4xBX65eq670I5TWPSLMzpp8ncGHMmvHqRajNBnmFtbYxN3E3/WjxmdbOOe+OXpnGJPcGsftc7cB2shRfA4lICPnE26+oVNXT6p0Lo20nY5XC7jyCO", "subType": "00" } }, "creationDate": { "$date": { "$numberLong": "1552949630483" } }, "keyAltNames": [ "altname", "another_altname" ] } ], "tests": [ { "description": "type=objectId", "clientOptions": { "autoEncryptOpts": { "schemaMap": { "default.default": { "properties": { "encrypted_objectId": { "encrypt": { "keyId": [ { "$binary": { "base64": "AAAAAAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "bsonType": "objectId", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" } } }, "bsonType": "object" } }, "kmsProviders": { "aws": {} } } }, "operations": [ { "name": "insertOne", "arguments": { "document": { "_id": 1, "encrypted_objectId": { "$oid": "AAAAAAAAAAAAAAAAAAAAAAAA" } } } }, { "name": "findOne", "arguments": { "filter": { "_id": 1 } }, "result": { "_id": 1, "encrypted_objectId": { "$oid": "AAAAAAAAAAAAAAAAAAAAAAAA" } } } ], "expectations": [ { "command_started_event": { "command": { "find": "datakeys", "filter": { "$or": [ { "_id": { "$in": [ { "$binary": { "base64": "AAAAAAAAAAAAAAAAAAAAAA==", "subType": "04" } } ] } }, { "keyAltNames": { "$in": [] } } ] }, "$db": "keyvault", "readConcern": { "level": "majority" } }, "command_name": "find" } }, { "command_started_event": { "command": { "insert": "default", "documents": [ { "_id": 1, "encrypted_objectId": { "$binary": { "base64": "AQAAAAAAAAAAAAAAAAAAAAAHmkTPqvzfHMWpvS1mEsrjOxVQ2dyihEgIFWD5E0eNEsiMBQsC0GuvjdqYRL5DHLFI1vKuGek7EYYp0Qyii/tHqA==", "subType": "06" } } } ], "ordered": true }, "command_name": "insert" } }, { "command_started_event": { "command": { "find": "default", "filter": { "_id": 1 } }, "command_name": "find" } } ], "outcome": { "collection": { "data": [ { "_id": 1, "encrypted_objectId": { "$binary": { "base64": "AQAAAAAAAAAAAAAAAAAAAAAHmkTPqvzfHMWpvS1mEsrjOxVQ2dyihEgIFWD5E0eNEsiMBQsC0GuvjdqYRL5DHLFI1vKuGek7EYYp0Qyii/tHqA==", "subType": "06" } } } ] } } }, { "description": "type=symbol", "clientOptions": { "autoEncryptOpts": { "schemaMap": { "default.default": { "properties": { "encrypted_symbol": { "encrypt": { "keyId": [ { "$binary": { "base64": "AAAAAAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "bsonType": "symbol", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" } } }, "bsonType": "object" } }, "kmsProviders": { "aws": {} } } }, "operations": [ { "name": "insertOne", "arguments": { "document": { "_id": 1, "encrypted_symbol": { "$symbol": "test" } } } }, { "name": "findOne", "arguments": { "filter": { "_id": 1 } }, "result": { "_id": 1, "encrypted_symbol": { "$symbol": "test" } } } ], "expectations": [ { "command_started_event": { "command": { "find": "datakeys", "filter": { "$or": [ { "_id": { "$in": [ { "$binary": { "base64": "AAAAAAAAAAAAAAAAAAAAAA==", "subType": "04" } } ] } }, { "keyAltNames": { "$in": [] } } ] }, "$db": "keyvault", "readConcern": { "level": "majority" } }, "command_name": "find" } }, { "command_started_event": { "command": { "insert": "default", "documents": [ { "_id": 1, "encrypted_symbol": { "$binary": { "base64": "AQAAAAAAAAAAAAAAAAAAAAAOOmvDmWjcuKsSCO7U/7t9HJ8eI73B6wduyMbdkvn7n7V4uTJes/j+BTtneSdyG2JHKHGkevWAJSIU2XoO66BSXw==", "subType": "06" } } } ], "ordered": true }, "command_name": "insert" } }, { "command_started_event": { "command": { "find": "default", "filter": { "_id": 1 } }, "command_name": "find" } } ], "outcome": { "collection": { "data": [ { "_id": 1, "encrypted_symbol": { "$binary": { "base64": "AQAAAAAAAAAAAAAAAAAAAAAOOmvDmWjcuKsSCO7U/7t9HJ8eI73B6wduyMbdkvn7n7V4uTJes/j+BTtneSdyG2JHKHGkevWAJSIU2XoO66BSXw==", "subType": "06" } } } ] } } }, { "description": "type=int", "clientOptions": { "autoEncryptOpts": { "schemaMap": { "default.default": { "properties": { "encrypted_int": { "encrypt": { "keyId": [ { "$binary": { "base64": "AAAAAAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "bsonType": "int", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" } } }, "bsonType": "object" } }, "kmsProviders": { "aws": {} } } }, "operations": [ { "name": "insertOne", "arguments": { "document": { "_id": 1, "encrypted_int": { "$numberInt": "123" } } } }, { "name": "findOne", "arguments": { "filter": { "_id": 1 } }, "result": { "_id": 1, "encrypted_int": { "$numberInt": "123" } } } ], "expectations": [ { "command_started_event": { "command": { "find": "datakeys", "filter": { "$or": [ { "_id": { "$in": [ { "$binary": { "base64": "AAAAAAAAAAAAAAAAAAAAAA==", "subType": "04" } } ] } }, { "keyAltNames": { "$in": [] } } ] }, "$db": "keyvault", "readConcern": { "level": "majority" } }, "command_name": "find" } }, { "command_started_event": { "command": { "insert": "default", "documents": [ { "_id": 1, "encrypted_int": { "$binary": { "base64": "AQAAAAAAAAAAAAAAAAAAAAAQPNXJVXMEjGZnftMuf2INKufXCtQIRHdw5wTgn6QYt3ejcoAXyiwI4XIUizkpsob494qpt2in4tWeiO7b9zkA8Q==", "subType": "06" } } } ], "ordered": true }, "command_name": "insert" } }, { "command_started_event": { "command": { "find": "default", "filter": { "_id": 1 } }, "command_name": "find" } } ], "outcome": { "collection": { "data": [ { "_id": 1, "encrypted_int": { "$binary": { "base64": "AQAAAAAAAAAAAAAAAAAAAAAQPNXJVXMEjGZnftMuf2INKufXCtQIRHdw5wTgn6QYt3ejcoAXyiwI4XIUizkpsob494qpt2in4tWeiO7b9zkA8Q==", "subType": "06" } } } ] } } }, { "description": "type=double", "clientOptions": { "autoEncryptOpts": { "schemaMap": { "default.default": { "properties": { "encrypted_double": { "encrypt": { "keyId": [ { "$binary": { "base64": "AAAAAAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "bsonType": "double", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" } } }, "bsonType": "object" } }, "kmsProviders": { "aws": {} } } }, "operations": [ { "name": "insertOne", "arguments": { "document": { "_id": 1, "encrypted_double": { "$numberDouble": "1.23" } } }, "result": { "errorContains": "element of type: double" } } ] }, { "description": "type=decimal", "clientOptions": { "autoEncryptOpts": { "schemaMap": { "default.default": { "properties": { "encrypted_decimal": { "encrypt": { "keyId": [ { "$binary": { "base64": "AAAAAAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "bsonType": "decimal", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" } } }, "bsonType": "object" } }, "kmsProviders": { "aws": {} } } }, "operations": [ { "name": "insertOne", "arguments": { "document": { "_id": 1, "encrypted_decimal": { "$numberDecimal": "1.23" } } }, "result": { "errorContains": "element of type: decimal" } } ] }, { "description": "type=binData", "clientOptions": { "autoEncryptOpts": { "schemaMap": { "default.default": { "properties": { "encrypted_binData": { "encrypt": { "keyId": [ { "$binary": { "base64": "AAAAAAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "bsonType": "binData", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" } } }, "bsonType": "object" } }, "kmsProviders": { "aws": {} } } }, "operations": [ { "name": "insertOne", "arguments": { "document": { "_id": 1, "encrypted_binData": { "$binary": { "base64": "AAAA", "subType": "00" } } } } }, { "name": "findOne", "arguments": { "filter": { "_id": 1 } }, "result": { "_id": 1, "encrypted_binData": { "$binary": { "base64": "AAAA", "subType": "00" } } } } ], "expectations": [ { "command_started_event": { "command": { "find": "datakeys", "filter": { "$or": [ { "_id": { "$in": [ { "$binary": { "base64": "AAAAAAAAAAAAAAAAAAAAAA==", "subType": "04" } } ] } }, { "keyAltNames": { "$in": [] } } ] }, "$db": "keyvault", "readConcern": { "level": "majority" } }, "command_name": "find" } }, { "command_started_event": { "command": { "insert": "default", "documents": [ { "_id": 1, "encrypted_binData": { "$binary": { "base64": "AQAAAAAAAAAAAAAAAAAAAAAFB/KHZQHaHHo8fctcl7v6kR+sLkJoTRx2cPSSck9ya+nbGROSeFhdhDRHaCzhV78fDEqnMDSVPNi+ZkbaIh46GQ==", "subType": "06" } } } ], "ordered": true }, "command_name": "insert" } }, { "command_started_event": { "command": { "find": "default", "filter": { "_id": 1 } }, "command_name": "find" } } ], "outcome": { "collection": { "data": [ { "_id": 1, "encrypted_binData": { "$binary": { "base64": "AQAAAAAAAAAAAAAAAAAAAAAFB/KHZQHaHHo8fctcl7v6kR+sLkJoTRx2cPSSck9ya+nbGROSeFhdhDRHaCzhV78fDEqnMDSVPNi+ZkbaIh46GQ==", "subType": "06" } } } ] } } }, { "description": "type=javascript", "clientOptions": { "autoEncryptOpts": { "schemaMap": { "default.default": { "properties": { "encrypted_javascript": { "encrypt": { "keyId": [ { "$binary": { "base64": "AAAAAAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "bsonType": "javascript", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" } } }, "bsonType": "object" } }, "kmsProviders": { "aws": {} } } }, "operations": [ { "name": "insertOne", "arguments": { "document": { "_id": 1, "encrypted_javascript": { "$code": "var x = 1;" } } } }, { "name": "findOne", "arguments": { "filter": { "_id": 1 } }, "result": { "_id": 1, "encrypted_javascript": { "$code": "var x = 1;" } } } ], "expectations": [ { "command_started_event": { "command": { "find": "datakeys", "filter": { "$or": [ { "_id": { "$in": [ { "$binary": { "base64": "AAAAAAAAAAAAAAAAAAAAAA==", "subType": "04" } } ] } }, { "keyAltNames": { "$in": [] } } ] }, "$db": "keyvault", "readConcern": { "level": "majority" } }, "command_name": "find" } }, { "command_started_event": { "command": { "insert": "default", "documents": [ { "_id": 1, "encrypted_javascript": { "$binary": { "base64": "AQAAAAAAAAAAAAAAAAAAAAANrvMgJkTKWGMc9wt3E2RBR2Hu5gL9p+vIIdHe9FcOm99t1W480/oX1Gnd87ON3B399DuFaxi/aaIiQSo7gTX6Lw==", "subType": "06" } } } ], "ordered": true }, "command_name": "insert" } }, { "command_started_event": { "command": { "find": "default", "filter": { "_id": 1 } }, "command_name": "find" } } ], "outcome": { "collection": { "data": [ { "_id": 1, "encrypted_javascript": { "$binary": { "base64": "AQAAAAAAAAAAAAAAAAAAAAANrvMgJkTKWGMc9wt3E2RBR2Hu5gL9p+vIIdHe9FcOm99t1W480/oX1Gnd87ON3B399DuFaxi/aaIiQSo7gTX6Lw==", "subType": "06" } } } ] } } }, { "description": "type=javascriptWithScope", "clientOptions": { "autoEncryptOpts": { "schemaMap": { "default.default": { "properties": { "encrypted_javascriptWithScope": { "encrypt": { "keyId": [ { "$binary": { "base64": "AAAAAAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "bsonType": "javascriptWithScope", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" } } }, "bsonType": "object" } }, "kmsProviders": { "aws": {} } } }, "operations": [ { "name": "insertOne", "arguments": { "document": { "_id": 1, "encrypted_javascriptWithScope": { "$code": "var x = 1;", "$scope": {} } } }, "result": { "errorContains": "element of type: javascriptWithScope" } } ] }, { "description": "type=object", "clientOptions": { "autoEncryptOpts": { "schemaMap": { "default.default": { "properties": { "encrypted_object": { "encrypt": { "keyId": [ { "$binary": { "base64": "AAAAAAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "bsonType": "object", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" } } }, "bsonType": "object" } }, "kmsProviders": { "aws": {} } } }, "operations": [ { "name": "insertOne", "arguments": { "document": { "_id": 1, "encrypted_object": {} } }, "result": { "errorContains": "element of type: object" } } ] }, { "description": "type=timestamp", "clientOptions": { "autoEncryptOpts": { "schemaMap": { "default.default": { "properties": { "encrypted_timestamp": { "encrypt": { "keyId": [ { "$binary": { "base64": "AAAAAAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "bsonType": "timestamp", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" } } }, "bsonType": "object" } }, "kmsProviders": { "aws": {} } } }, "operations": [ { "name": "insertOne", "arguments": { "document": { "_id": 1, "encrypted_timestamp": { "$timestamp": { "t": 123, "i": 456 } } } } }, { "name": "findOne", "arguments": { "filter": { "_id": 1 } }, "result": { "_id": 1, "encrypted_timestamp": { "$timestamp": { "t": 123, "i": 456 } } } } ], "expectations": [ { "command_started_event": { "command": { "find": "datakeys", "filter": { "$or": [ { "_id": { "$in": [ { "$binary": { "base64": "AAAAAAAAAAAAAAAAAAAAAA==", "subType": "04" } } ] } }, { "keyAltNames": { "$in": [] } } ] }, "$db": "keyvault", "readConcern": { "level": "majority" } }, "command_name": "find" } }, { "command_started_event": { "command": { "insert": "default", "documents": [ { "_id": 1, "encrypted_timestamp": { "$binary": { "base64": "AQAAAAAAAAAAAAAAAAAAAAARJHaM4Gq3MpDTdBasBsEolQaOmxJQU1wsZVaSFAOLpEh1QihDglXI95xemePFMKhg+KNpFg7lw1ChCs2Wn/c26Q==", "subType": "06" } } } ], "ordered": true }, "command_name": "insert" } }, { "command_started_event": { "command": { "find": "default", "filter": { "_id": 1 } }, "command_name": "find" } } ], "outcome": { "collection": { "data": [ { "_id": 1, "encrypted_timestamp": { "$binary": { "base64": "AQAAAAAAAAAAAAAAAAAAAAARJHaM4Gq3MpDTdBasBsEolQaOmxJQU1wsZVaSFAOLpEh1QihDglXI95xemePFMKhg+KNpFg7lw1ChCs2Wn/c26Q==", "subType": "06" } } } ] } } }, { "description": "type=regex", "clientOptions": { "autoEncryptOpts": { "schemaMap": { "default.default": { "properties": { "encrypted_regex": { "encrypt": { "keyId": [ { "$binary": { "base64": "AAAAAAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "bsonType": "regex", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" } } }, "bsonType": "object" } }, "kmsProviders": { "aws": {} } } }, "operations": [ { "name": "insertOne", "arguments": { "document": { "_id": 1, "encrypted_regex": { "$regularExpression": { "pattern": "test", "options": "" } } } } }, { "name": "findOne", "arguments": { "filter": { "_id": 1 } }, "result": { "_id": 1, "encrypted_regex": { "$regularExpression": { "pattern": "test", "options": "" } } } } ], "expectations": [ { "command_started_event": { "command": { "find": "datakeys", "filter": { "$or": [ { "_id": { "$in": [ { "$binary": { "base64": "AAAAAAAAAAAAAAAAAAAAAA==", "subType": "04" } } ] } }, { "keyAltNames": { "$in": [] } } ] }, "$db": "keyvault", "readConcern": { "level": "majority" } }, "command_name": "find" } }, { "command_started_event": { "command": { "insert": "default", "documents": [ { "_id": 1, "encrypted_regex": { "$binary": { "base64": "AQAAAAAAAAAAAAAAAAAAAAALVnxM4UqGhqf5eXw6nsS08am3YJrTf1EvjKitT8tyyMAbHsICIU3GUjuC7EBofCHbusvgo7pDyaClGostFz44nA==", "subType": "06" } } } ], "ordered": true }, "command_name": "insert" } }, { "command_started_event": { "command": { "find": "default", "filter": { "_id": 1 } }, "command_name": "find" } } ], "outcome": { "collection": { "data": [ { "_id": 1, "encrypted_regex": { "$binary": { "base64": "AQAAAAAAAAAAAAAAAAAAAAALVnxM4UqGhqf5eXw6nsS08am3YJrTf1EvjKitT8tyyMAbHsICIU3GUjuC7EBofCHbusvgo7pDyaClGostFz44nA==", "subType": "06" } } } ] } } }, { "description": "type=date", "clientOptions": { "autoEncryptOpts": { "schemaMap": { "default.default": { "properties": { "encrypted_date": { "encrypt": { "keyId": [ { "$binary": { "base64": "AAAAAAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "bsonType": "date", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" } } }, "bsonType": "object" } }, "kmsProviders": { "aws": {} } } }, "operations": [ { "name": "insertOne", "arguments": { "document": { "_id": 1, "encrypted_date": { "$date": { "$numberLong": "123" } } } } }, { "name": "findOne", "arguments": { "filter": { "_id": 1 } }, "result": { "_id": 1, "encrypted_date": { "$date": { "$numberLong": "123" } } } } ], "expectations": [ { "command_started_event": { "command": { "find": "datakeys", "filter": { "$or": [ { "_id": { "$in": [ { "$binary": { "base64": "AAAAAAAAAAAAAAAAAAAAAA==", "subType": "04" } } ] } }, { "keyAltNames": { "$in": [] } } ] }, "$db": "keyvault", "readConcern": { "level": "majority" } }, "command_name": "find" } }, { "command_started_event": { "command": { "insert": "default", "documents": [ { "_id": 1, "encrypted_date": { "$binary": { "base64": "AQAAAAAAAAAAAAAAAAAAAAAJ5sN7u6l97+DswfKTqZAijSTSOo5htinGKQKUD7pHNJYlLXGOkB4glrCu7ibu0g3344RHQ5yUp4YxMEa8GD+Snw==", "subType": "06" } } } ], "ordered": true }, "command_name": "insert" } }, { "command_started_event": { "command": { "find": "default", "filter": { "_id": 1 } }, "command_name": "find" } } ], "outcome": { "collection": { "data": [ { "_id": 1, "encrypted_date": { "$binary": { "base64": "AQAAAAAAAAAAAAAAAAAAAAAJ5sN7u6l97+DswfKTqZAijSTSOo5htinGKQKUD7pHNJYlLXGOkB4glrCu7ibu0g3344RHQ5yUp4YxMEa8GD+Snw==", "subType": "06" } } } ] } } }, { "description": "type=minKey", "clientOptions": { "autoEncryptOpts": { "schemaMap": { "default.default": { "properties": { "encrypted_minKey": { "encrypt": { "keyId": [ { "$binary": { "base64": "AAAAAAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "bsonType": "minKey", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" } } }, "bsonType": "object" } }, "kmsProviders": { "aws": {} } } }, "operations": [ { "name": "insertOne", "arguments": { "document": { "_id": 1, "encrypted_minKey": { "$minKey": 1 } } }, "result": { "errorContains": "Cannot encrypt element of type: minKey" } } ] }, { "description": "type=maxKey", "clientOptions": { "autoEncryptOpts": { "schemaMap": { "default.default": { "properties": { "encrypted_maxKey": { "encrypt": { "keyId": [ { "$binary": { "base64": "AAAAAAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "bsonType": "maxKey", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" } } }, "bsonType": "object" } }, "kmsProviders": { "aws": {} } } }, "operations": [ { "name": "insertOne", "arguments": { "document": { "_id": 1, "encrypted_maxKey": { "$maxKey": 1 } } }, "result": { "errorContains": "Cannot encrypt element of type: maxKey" } } ] }, { "description": "type=undefined", "clientOptions": { "autoEncryptOpts": { "schemaMap": { "default.default": { "properties": { "encrypted_undefined": { "encrypt": { "keyId": [ { "$binary": { "base64": "AAAAAAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "bsonType": "undefined", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" } } }, "bsonType": "object" } }, "kmsProviders": { "aws": {} } } }, "operations": [ { "name": "insertOne", "arguments": { "document": { "_id": 1, "encrypted_undefined": { "$undefined": true } } }, "result": { "errorContains": "Cannot encrypt element of type: undefined" } } ] }, { "description": "type=array", "clientOptions": { "autoEncryptOpts": { "schemaMap": { "default.default": { "properties": { "encrypted_array": { "encrypt": { "keyId": [ { "$binary": { "base64": "AAAAAAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "bsonType": "array", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" } } }, "bsonType": "object" } }, "kmsProviders": { "aws": {} } } }, "operations": [ { "name": "insertOne", "arguments": { "document": { "_id": 1, "encrypted_array": [] } }, "result": { "errorContains": "element of type: array" } } ] }, { "description": "type=bool", "clientOptions": { "autoEncryptOpts": { "schemaMap": { "default.default": { "properties": { "encrypted_bool": { "encrypt": { "keyId": [ { "$binary": { "base64": "AAAAAAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "bsonType": "bool", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" } } }, "bsonType": "object" } }, "kmsProviders": { "aws": {} } } }, "operations": [ { "name": "insertOne", "arguments": { "document": { "_id": 1, "encrypted_bool": true } }, "result": { "errorContains": "element of type: bool" } } ] }, { "description": "type=null", "clientOptions": { "autoEncryptOpts": { "schemaMap": { "default.default": { "properties": { "encrypted_null": { "encrypt": { "keyId": [ { "$binary": { "base64": "AAAAAAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "bsonType": "null", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" } } }, "bsonType": "object" } }, "kmsProviders": { "aws": {} } } }, "operations": [ { "name": "insertOne", "arguments": { "document": { "_id": 1, "encrypted_null": true } }, "result": { "errorContains": "Cannot encrypt element of type: null" } } ] } ] } mongodb-mongo-python-driver-509e9b7/test/client-side-encryption/spec/legacy/unsupportedCommand.json000066400000000000000000000075101462766011000337670ustar00rootroot00000000000000{ "runOn": [ { "minServerVersion": "4.1.10" } ], "database_name": "default", "collection_name": "default", "data": [ { "_id": 1, "x": 1, "encrypted_string": { "$binary": { "base64": "AQAAAAAAAAAAAAAAAAAAAAACwj+3zkv2VM+aTfk60RqhXq6a/77WlLwu/BxXFkL7EppGsju/m8f0x5kBDD3EZTtGALGXlym5jnpZAoSIkswHoA==", "subType": "06" } } }, { "_id": 2, "x": 2, "encrypted_string": { "$binary": { "base64": "AQAAAAAAAAAAAAAAAAAAAAACDdw4KFz3ZLquhsbt7RmDjD0N67n0uSXx7IGnQNCLeIKvot6s/ouI21Eo84IOtb6lhwUNPlSEBNY0/hbszWAKJg==", "subType": "06" } } } ], "json_schema": { "properties": { "encrypted_w_altname": { "encrypt": { "keyId": "/altname", "bsonType": "string", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Random" } }, "encrypted_string": { "encrypt": { "keyId": [ { "$binary": { "base64": "AAAAAAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "bsonType": "string", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" } }, "random": { "encrypt": { "keyId": [ { "$binary": { "base64": "AAAAAAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "bsonType": "string", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Random" } }, "encrypted_string_equivalent": { "encrypt": { "keyId": [ { "$binary": { "base64": "AAAAAAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "bsonType": "string", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" } } }, "bsonType": "object" }, "key_vault_data": [ { "status": 1, "_id": { "$binary": { "base64": "AAAAAAAAAAAAAAAAAAAAAA==", "subType": "04" } }, "masterKey": { "provider": "aws", "key": "arn:aws:kms:us-east-1:579766882180:key/89fcc2c4-08b0-4bd9-9f25-e30687b580d0", "region": "us-east-1" }, "updateDate": { "$date": { "$numberLong": "1552949630483" } }, "keyMaterial": { "$binary": { "base64": "AQICAHhQNmWG2CzOm1dq3kWLM+iDUZhEqnhJwH9wZVpuZ94A8gEqnsxXlR51T5EbEVezUqqKAAAAwjCBvwYJKoZIhvcNAQcGoIGxMIGuAgEAMIGoBgkqhkiG9w0BBwEwHgYJYIZIAWUDBAEuMBEEDHa4jo6yp0Z18KgbUgIBEIB74sKxWtV8/YHje5lv5THTl0HIbhSwM6EqRlmBiFFatmEWaeMk4tO4xBX65eq670I5TWPSLMzpp8ncGHMmvHqRajNBnmFtbYxN3E3/WjxmdbOOe+OXpnGJPcGsftc7cB2shRfA4lICPnE26+oVNXT6p0Lo20nY5XC7jyCO", "subType": "00" } }, "creationDate": { "$date": { "$numberLong": "1552949630483" } }, "keyAltNames": [ "altname", "another_altname" ] } ], "tests": [ { "description": "mapReduce deterministic encryption (unsupported)", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "aws": {} } } }, "operations": [ { "name": "mapReduce", "arguments": { "map": { "$code": "function inc() { return emit(0, this.x + 1) }" }, "reduce": { "$code": "function sum(key, values) { return values.reduce((acc, x) => acc + x); }" }, "out": { "inline": 1 } }, "result": { "errorContains": "command not supported for auto encryption: mapreduce" } } ] } ] } mongodb-mongo-python-driver-509e9b7/test/client-side-encryption/spec/legacy/updateMany.json000066400000000000000000000202721462766011000322070ustar00rootroot00000000000000{ "runOn": [ { "minServerVersion": "4.1.10" } ], "database_name": "default", "collection_name": "default", "data": [ { "_id": 1, "encrypted_string": { "$binary": { "base64": "AQAAAAAAAAAAAAAAAAAAAAACwj+3zkv2VM+aTfk60RqhXq6a/77WlLwu/BxXFkL7EppGsju/m8f0x5kBDD3EZTtGALGXlym5jnpZAoSIkswHoA==", "subType": "06" } } }, { "_id": 2, "encrypted_string": { "$binary": { "base64": "AQAAAAAAAAAAAAAAAAAAAAACDdw4KFz3ZLquhsbt7RmDjD0N67n0uSXx7IGnQNCLeIKvot6s/ouI21Eo84IOtb6lhwUNPlSEBNY0/hbszWAKJg==", "subType": "06" } } } ], "json_schema": { "properties": { "encrypted_w_altname": { "encrypt": { "keyId": "/altname", "bsonType": "string", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Random" } }, "encrypted_string": { "encrypt": { "keyId": [ { "$binary": { "base64": "AAAAAAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "bsonType": "string", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" } }, "random": { "encrypt": { "keyId": [ { "$binary": { "base64": "AAAAAAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "bsonType": "string", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Random" } }, "encrypted_string_equivalent": { "encrypt": { "keyId": [ { "$binary": { "base64": "AAAAAAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "bsonType": "string", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" } } }, "bsonType": "object" }, "key_vault_data": [ { "status": 1, "_id": { "$binary": { "base64": "AAAAAAAAAAAAAAAAAAAAAA==", "subType": "04" } }, "masterKey": { "provider": "aws", "key": "arn:aws:kms:us-east-1:579766882180:key/89fcc2c4-08b0-4bd9-9f25-e30687b580d0", "region": "us-east-1" }, "updateDate": { "$date": { "$numberLong": "1552949630483" } }, "keyMaterial": { "$binary": { "base64": "AQICAHhQNmWG2CzOm1dq3kWLM+iDUZhEqnhJwH9wZVpuZ94A8gEqnsxXlR51T5EbEVezUqqKAAAAwjCBvwYJKoZIhvcNAQcGoIGxMIGuAgEAMIGoBgkqhkiG9w0BBwEwHgYJYIZIAWUDBAEuMBEEDHa4jo6yp0Z18KgbUgIBEIB74sKxWtV8/YHje5lv5THTl0HIbhSwM6EqRlmBiFFatmEWaeMk4tO4xBX65eq670I5TWPSLMzpp8ncGHMmvHqRajNBnmFtbYxN3E3/WjxmdbOOe+OXpnGJPcGsftc7cB2shRfA4lICPnE26+oVNXT6p0Lo20nY5XC7jyCO", "subType": "00" } }, "creationDate": { "$date": { "$numberLong": "1552949630483" } }, "keyAltNames": [ "altname", "another_altname" ] } ], "tests": [ { "description": "updateMany with deterministic encryption", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "aws": {} } } }, "operations": [ { "name": "updateMany", "arguments": { "filter": { "encrypted_string": { "$in": [ "string0", "string1" ] } }, "update": { "$set": { "encrypted_string": "string2", "random": "abc" } } }, "result": { "matchedCount": 2, "modifiedCount": 2, "upsertedCount": 0 } } ], "expectations": [ { "command_started_event": { "command": { "listCollections": 1, "filter": { "name": "default" } }, "command_name": "listCollections" } }, { "command_started_event": { "command": { "find": "datakeys", "filter": { "$or": [ { "_id": { "$in": [ { "$binary": { "base64": "AAAAAAAAAAAAAAAAAAAAAA==", "subType": "04" } } ] } }, { "keyAltNames": { "$in": [] } } ] }, "$db": "keyvault", "readConcern": { "level": "majority" } }, "command_name": "find" } }, { "command_started_event": { "command": { "update": "default", "updates": [ { "q": { "encrypted_string": { "$in": [ { "$binary": { "base64": "AQAAAAAAAAAAAAAAAAAAAAACwj+3zkv2VM+aTfk60RqhXq6a/77WlLwu/BxXFkL7EppGsju/m8f0x5kBDD3EZTtGALGXlym5jnpZAoSIkswHoA==", "subType": "06" } }, { "$binary": { "base64": "AQAAAAAAAAAAAAAAAAAAAAACDdw4KFz3ZLquhsbt7RmDjD0N67n0uSXx7IGnQNCLeIKvot6s/ouI21Eo84IOtb6lhwUNPlSEBNY0/hbszWAKJg==", "subType": "06" } } ] } }, "u": { "$set": { "encrypted_string": { "$binary": { "base64": "AQAAAAAAAAAAAAAAAAAAAAACQ76HWOut3DZtQuV90hp1aaCpZn95vZIaWmn+wrBehcEtcFwyJlBdlyzDzZTWPZCPgiFq72Wvh6Y7VbpU9NAp3A==", "subType": "06" } }, "random": { "$$type": "binData" } } }, "multi": true, "upsert": false } ], "ordered": true }, "command_name": "update" } } ], "outcome": { "collection": { "data": [ { "_id": 1, "encrypted_string": { "$binary": { "base64": "AQAAAAAAAAAAAAAAAAAAAAACQ76HWOut3DZtQuV90hp1aaCpZn95vZIaWmn+wrBehcEtcFwyJlBdlyzDzZTWPZCPgiFq72Wvh6Y7VbpU9NAp3A==", "subType": "06" } }, "random": { "$$type": "binData" } }, { "_id": 2, "encrypted_string": { "$binary": { "base64": "AQAAAAAAAAAAAAAAAAAAAAACQ76HWOut3DZtQuV90hp1aaCpZn95vZIaWmn+wrBehcEtcFwyJlBdlyzDzZTWPZCPgiFq72Wvh6Y7VbpU9NAp3A==", "subType": "06" } }, "random": { "$$type": "binData" } } ] } } }, { "description": "updateMany fails when filtering on a random field", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "aws": {} } } }, "operations": [ { "name": "updateMany", "arguments": { "filter": { "random": "abc" }, "update": { "$set": { "encrypted_string": "string1" } } }, "result": { "errorContains": "Cannot query on fields encrypted with the randomized encryption" } } ] } ] } mongodb-mongo-python-driver-509e9b7/test/client-side-encryption/spec/legacy/updateOne.json000066400000000000000000000267071462766011000320350ustar00rootroot00000000000000{ "runOn": [ { "minServerVersion": "4.1.10" } ], "database_name": "default", "collection_name": "default", "data": [ { "_id": 1, "encrypted_string": { "$binary": { "base64": "AQAAAAAAAAAAAAAAAAAAAAACwj+3zkv2VM+aTfk60RqhXq6a/77WlLwu/BxXFkL7EppGsju/m8f0x5kBDD3EZTtGALGXlym5jnpZAoSIkswHoA==", "subType": "06" } } } ], "json_schema": { "properties": { "encrypted_w_altname": { "encrypt": { "keyId": "/altname", "bsonType": "string", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Random" } }, "encrypted_string": { "encrypt": { "keyId": [ { "$binary": { "base64": "AAAAAAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "bsonType": "string", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" } }, "random": { "encrypt": { "keyId": [ { "$binary": { "base64": "AAAAAAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "bsonType": "string", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Random" } }, "encrypted_string_equivalent": { "encrypt": { "keyId": [ { "$binary": { "base64": "AAAAAAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "bsonType": "string", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" } } }, "bsonType": "object" }, "key_vault_data": [ { "status": 1, "_id": { "$binary": { "base64": "AAAAAAAAAAAAAAAAAAAAAA==", "subType": "04" } }, "masterKey": { "provider": "aws", "key": "arn:aws:kms:us-east-1:579766882180:key/89fcc2c4-08b0-4bd9-9f25-e30687b580d0", "region": "us-east-1" }, "updateDate": { "$date": { "$numberLong": "1552949630483" } }, "keyMaterial": { "$binary": { "base64": "AQICAHhQNmWG2CzOm1dq3kWLM+iDUZhEqnhJwH9wZVpuZ94A8gEqnsxXlR51T5EbEVezUqqKAAAAwjCBvwYJKoZIhvcNAQcGoIGxMIGuAgEAMIGoBgkqhkiG9w0BBwEwHgYJYIZIAWUDBAEuMBEEDHa4jo6yp0Z18KgbUgIBEIB74sKxWtV8/YHje5lv5THTl0HIbhSwM6EqRlmBiFFatmEWaeMk4tO4xBX65eq670I5TWPSLMzpp8ncGHMmvHqRajNBnmFtbYxN3E3/WjxmdbOOe+OXpnGJPcGsftc7cB2shRfA4lICPnE26+oVNXT6p0Lo20nY5XC7jyCO", "subType": "00" } }, "creationDate": { "$date": { "$numberLong": "1552949630483" } }, "keyAltNames": [ "altname", "another_altname" ] } ], "tests": [ { "description": "updateOne with deterministic encryption", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "aws": {} } } }, "operations": [ { "name": "updateOne", "arguments": { "filter": { "encrypted_string": "string0" }, "update": { "$set": { "encrypted_string": "string1", "random": "abc" } } }, "result": { "matchedCount": 1, "modifiedCount": 1, "upsertedCount": 0 } } ], "expectations": [ { "command_started_event": { "command": { "listCollections": 1, "filter": { "name": "default" } }, "command_name": "listCollections" } }, { "command_started_event": { "command": { "find": "datakeys", "filter": { "$or": [ { "_id": { "$in": [ { "$binary": { "base64": "AAAAAAAAAAAAAAAAAAAAAA==", "subType": "04" } } ] } }, { "keyAltNames": { "$in": [] } } ] }, "$db": "keyvault", "readConcern": { "level": "majority" } }, "command_name": "find" } }, { "command_started_event": { "command": { "update": "default", "updates": [ { "q": { "encrypted_string": { "$eq": { "$binary": { "base64": "AQAAAAAAAAAAAAAAAAAAAAACwj+3zkv2VM+aTfk60RqhXq6a/77WlLwu/BxXFkL7EppGsju/m8f0x5kBDD3EZTtGALGXlym5jnpZAoSIkswHoA==", "subType": "06" } } } }, "u": { "$set": { "encrypted_string": { "$binary": { "base64": "AQAAAAAAAAAAAAAAAAAAAAACDdw4KFz3ZLquhsbt7RmDjD0N67n0uSXx7IGnQNCLeIKvot6s/ouI21Eo84IOtb6lhwUNPlSEBNY0/hbszWAKJg==", "subType": "06" } }, "random": { "$$type": "binData" } } } } ], "ordered": true }, "command_name": "update" } } ], "outcome": { "collection": { "data": [ { "_id": 1, "encrypted_string": { "$binary": { "base64": "AQAAAAAAAAAAAAAAAAAAAAACDdw4KFz3ZLquhsbt7RmDjD0N67n0uSXx7IGnQNCLeIKvot6s/ouI21Eo84IOtb6lhwUNPlSEBNY0/hbszWAKJg==", "subType": "06" } }, "random": { "$$type": "binData" } } ] } } }, { "description": "updateOne fails when filtering on a random field", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "aws": {} } } }, "operations": [ { "name": "updateOne", "arguments": { "filter": { "random": "abc" }, "update": { "$set": { "encrypted_string": "string1" } } }, "result": { "errorContains": "Cannot query on fields encrypted with the randomized encryption" } } ] }, { "description": "$unset works with an encrypted field", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "aws": {} } } }, "operations": [ { "name": "updateOne", "arguments": { "filter": {}, "update": { "$unset": { "encrypted_string": "" } } }, "result": { "matchedCount": 1, "modifiedCount": 1, "upsertedCount": 0 } } ], "expectations": [ { "command_started_event": { "command": { "listCollections": 1, "filter": { "name": "default" } }, "command_name": "listCollections" } }, { "command_started_event": { "command": { "update": "default", "updates": [ { "q": {}, "u": { "$unset": { "encrypted_string": "" } } } ], "ordered": true }, "command_name": "update" } } ], "outcome": { "collection": { "data": [ { "_id": 1 } ] } } }, { "description": "$rename works if target value has same encryption options", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "aws": {} } } }, "operations": [ { "name": "updateOne", "arguments": { "filter": {}, "update": { "$rename": { "encrypted_string": "encrypted_string_equivalent" } } }, "result": { "matchedCount": 1, "modifiedCount": 1, "upsertedCount": 0 } } ], "expectations": [ { "command_started_event": { "command": { "listCollections": 1, "filter": { "name": "default" } }, "command_name": "listCollections" } }, { "command_started_event": { "command": { "update": "default", "updates": [ { "q": {}, "u": { "$rename": { "encrypted_string": "encrypted_string_equivalent" } } } ], "ordered": true }, "command_name": "update" } } ], "outcome": { "collection": { "data": [ { "_id": 1, "encrypted_string_equivalent": { "$binary": { "base64": "AQAAAAAAAAAAAAAAAAAAAAACwj+3zkv2VM+aTfk60RqhXq6a/77WlLwu/BxXFkL7EppGsju/m8f0x5kBDD3EZTtGALGXlym5jnpZAoSIkswHoA==", "subType": "06" } } } ] } } }, { "description": "$rename fails if target value has different encryption options", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "aws": {} } } }, "operations": [ { "name": "updateOne", "arguments": { "filter": {}, "update": { "$rename": { "encrypted_string": "random" } } }, "result": { "errorContains": "$rename between two encrypted fields must have the same metadata or both be unencrypted" } } ] }, { "description": "an invalid update (no $ operators) is validated and errors", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "aws": {} } } }, "operations": [ { "name": "updateOne", "arguments": { "filter": {}, "update": { "encrypted_string": "random" } }, "result": { "errorContains": "" } } ] } ] } validatorAndPartialFieldExpression.json000066400000000000000000000465771462766011000370120ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/client-side-encryption/spec/legacy{ "runOn": [ { "minServerVersion": "6.0.0" } ], "database_name": "default", "collection_name": "default", "data": [], "tests": [ { "description": "create with a validator on an unencrypted field is OK", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "local": { "key": { "$binary": { "base64": "Mng0NCt4ZHVUYUJCa1kxNkVyNUR1QURhZ2h2UzR2d2RrZzh0cFBwM3R6NmdWMDFBMUN3YkQ5aXRRMkhGRGdQV09wOGVNYUMxT2k3NjZKelhaQmRCZGJkTXVyZG9uSjFk", "subType": "00" } } } }, "schemaMap": { "default.encryptedCollection": { "properties": { "encrypted_w_altname": { "encrypt": { "keyId": "/altname", "bsonType": "string", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Random" } }, "encrypted_string": { "encrypt": { "keyId": [ { "$binary": { "base64": "AAAAAAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "bsonType": "string", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" } }, "random": { "encrypt": { "keyId": [ { "$binary": { "base64": "AAAAAAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "bsonType": "string", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Random" } }, "encrypted_string_equivalent": { "encrypt": { "keyId": [ { "$binary": { "base64": "AAAAAAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "bsonType": "string", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" } } }, "bsonType": "object" } } } }, "operations": [ { "name": "dropCollection", "object": "database", "arguments": { "collection": "encryptedCollection" } }, { "name": "createCollection", "object": "database", "arguments": { "collection": "encryptedCollection", "validator": { "unencrypted_string": "foo" } } }, { "name": "assertCollectionExists", "object": "testRunner", "arguments": { "database": "default", "collection": "encryptedCollection" } } ] }, { "description": "create with a validator on an encrypted field is an error", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "local": { "key": { "$binary": { "base64": "Mng0NCt4ZHVUYUJCa1kxNkVyNUR1QURhZ2h2UzR2d2RrZzh0cFBwM3R6NmdWMDFBMUN3YkQ5aXRRMkhGRGdQV09wOGVNYUMxT2k3NjZKelhaQmRCZGJkTXVyZG9uSjFk", "subType": "00" } } } }, "schemaMap": { "default.encryptedCollection": { "properties": { "encrypted_w_altname": { "encrypt": { "keyId": "/altname", "bsonType": "string", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Random" } }, "encrypted_string": { "encrypt": { "keyId": [ { "$binary": { "base64": "AAAAAAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "bsonType": "string", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" } }, "random": { "encrypt": { "keyId": [ { "$binary": { "base64": "AAAAAAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "bsonType": "string", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Random" } }, "encrypted_string_equivalent": { "encrypt": { "keyId": [ { "$binary": { "base64": "AAAAAAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "bsonType": "string", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" } } }, "bsonType": "object" } } } }, "operations": [ { "name": "dropCollection", "object": "database", "arguments": { "collection": "encryptedCollection" } }, { "name": "createCollection", "object": "database", "arguments": { "collection": "encryptedCollection", "validator": { "encrypted_string": "foo" } }, "result": { "errorContains": "Comparison to encrypted fields not supported" } } ] }, { "description": "collMod with a validator on an unencrypted field is OK", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "local": { "key": { "$binary": { "base64": "Mng0NCt4ZHVUYUJCa1kxNkVyNUR1QURhZ2h2UzR2d2RrZzh0cFBwM3R6NmdWMDFBMUN3YkQ5aXRRMkhGRGdQV09wOGVNYUMxT2k3NjZKelhaQmRCZGJkTXVyZG9uSjFk", "subType": "00" } } } }, "schemaMap": { "default.encryptedCollection": { "properties": { "encrypted_w_altname": { "encrypt": { "keyId": "/altname", "bsonType": "string", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Random" } }, "encrypted_string": { "encrypt": { "keyId": [ { "$binary": { "base64": "AAAAAAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "bsonType": "string", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" } }, "random": { "encrypt": { "keyId": [ { "$binary": { "base64": "AAAAAAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "bsonType": "string", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Random" } }, "encrypted_string_equivalent": { "encrypt": { "keyId": [ { "$binary": { "base64": "AAAAAAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "bsonType": "string", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" } } }, "bsonType": "object" } } } }, "operations": [ { "name": "dropCollection", "object": "database", "arguments": { "collection": "encryptedCollection" } }, { "name": "createCollection", "object": "database", "arguments": { "collection": "encryptedCollection" } }, { "name": "runCommand", "object": "database", "arguments": { "command": { "collMod": "encryptedCollection", "validator": { "unencrypted_string": "foo" } } } } ] }, { "description": "collMod with a validator on an encrypted field is an error", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "local": { "key": { "$binary": { "base64": "Mng0NCt4ZHVUYUJCa1kxNkVyNUR1QURhZ2h2UzR2d2RrZzh0cFBwM3R6NmdWMDFBMUN3YkQ5aXRRMkhGRGdQV09wOGVNYUMxT2k3NjZKelhaQmRCZGJkTXVyZG9uSjFk", "subType": "00" } } } }, "schemaMap": { "default.encryptedCollection": { "properties": { "encrypted_w_altname": { "encrypt": { "keyId": "/altname", "bsonType": "string", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Random" } }, "encrypted_string": { "encrypt": { "keyId": [ { "$binary": { "base64": "AAAAAAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "bsonType": "string", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" } }, "random": { "encrypt": { "keyId": [ { "$binary": { "base64": "AAAAAAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "bsonType": "string", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Random" } }, "encrypted_string_equivalent": { "encrypt": { "keyId": [ { "$binary": { "base64": "AAAAAAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "bsonType": "string", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" } } }, "bsonType": "object" } } } }, "operations": [ { "name": "dropCollection", "object": "database", "arguments": { "collection": "encryptedCollection" } }, { "name": "createCollection", "object": "database", "arguments": { "collection": "encryptedCollection" } }, { "name": "runCommand", "object": "database", "arguments": { "command": { "collMod": "encryptedCollection", "validator": { "encrypted_string": "foo" } } }, "result": { "errorContains": "Comparison to encrypted fields not supported" } } ] }, { "description": "createIndexes with a partialFilterExpression on an unencrypted field is OK", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "local": { "key": { "$binary": { "base64": "Mng0NCt4ZHVUYUJCa1kxNkVyNUR1QURhZ2h2UzR2d2RrZzh0cFBwM3R6NmdWMDFBMUN3YkQ5aXRRMkhGRGdQV09wOGVNYUMxT2k3NjZKelhaQmRCZGJkTXVyZG9uSjFk", "subType": "00" } } } }, "schemaMap": { "default.encryptedCollection": { "properties": { "encrypted_w_altname": { "encrypt": { "keyId": "/altname", "bsonType": "string", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Random" } }, "encrypted_string": { "encrypt": { "keyId": [ { "$binary": { "base64": "AAAAAAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "bsonType": "string", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" } }, "random": { "encrypt": { "keyId": [ { "$binary": { "base64": "AAAAAAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "bsonType": "string", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Random" } }, "encrypted_string_equivalent": { "encrypt": { "keyId": [ { "$binary": { "base64": "AAAAAAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "bsonType": "string", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" } } }, "bsonType": "object" } } } }, "operations": [ { "name": "dropCollection", "object": "database", "arguments": { "collection": "encryptedCollection" } }, { "name": "createCollection", "object": "database", "arguments": { "collection": "encryptedCollection" } }, { "name": "runCommand", "object": "database", "arguments": { "command": { "createIndexes": "encryptedCollection", "indexes": [ { "name": "name", "key": { "name": 1 }, "partialFilterExpression": { "unencrypted_string": "foo" } } ] } } }, { "name": "assertIndexExists", "object": "testRunner", "arguments": { "database": "default", "collection": "encryptedCollection", "index": "name" } } ] }, { "description": "createIndexes with a partialFilterExpression on an encrypted field is an error", "clientOptions": { "autoEncryptOpts": { "kmsProviders": { "local": { "key": { "$binary": { "base64": "Mng0NCt4ZHVUYUJCa1kxNkVyNUR1QURhZ2h2UzR2d2RrZzh0cFBwM3R6NmdWMDFBMUN3YkQ5aXRRMkhGRGdQV09wOGVNYUMxT2k3NjZKelhaQmRCZGJkTXVyZG9uSjFk", "subType": "00" } } } }, "schemaMap": { "default.encryptedCollection": { "properties": { "encrypted_w_altname": { "encrypt": { "keyId": "/altname", "bsonType": "string", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Random" } }, "encrypted_string": { "encrypt": { "keyId": [ { "$binary": { "base64": "AAAAAAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "bsonType": "string", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" } }, "random": { "encrypt": { "keyId": [ { "$binary": { "base64": "AAAAAAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "bsonType": "string", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Random" } }, "encrypted_string_equivalent": { "encrypt": { "keyId": [ { "$binary": { "base64": "AAAAAAAAAAAAAAAAAAAAAA==", "subType": "04" } } ], "bsonType": "string", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" } } }, "bsonType": "object" } } } }, "operations": [ { "name": "dropCollection", "object": "database", "arguments": { "collection": "encryptedCollection" } }, { "name": "createCollection", "object": "database", "arguments": { "collection": "encryptedCollection" } }, { "name": "runCommand", "object": "database", "arguments": { "command": { "createIndexes": "encryptedCollection", "indexes": [ { "name": "name", "key": { "name": 1 }, "partialFilterExpression": { "encrypted_string": "foo" } } ] } }, "result": { "errorContains": "Comparison to encrypted fields not supported" } } ] } ] } mongodb-mongo-python-driver-509e9b7/test/client-side-encryption/spec/unified/000077500000000000000000000000001462766011000273615ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/client-side-encryption/spec/unified/addKeyAltName.json000066400000000000000000000377421462766011000327340ustar00rootroot00000000000000{ "description": "addKeyAltName", "schemaVersion": "1.8", "runOnRequirements": [ { "csfle": true } ], "createEntities": [ { "client": { "id": "client0", "observeEvents": [ "commandStartedEvent" ] } }, { "clientEncryption": { "id": "clientEncryption0", "clientEncryptionOpts": { "keyVaultClient": "client0", "keyVaultNamespace": "keyvault.datakeys", "kmsProviders": { "local": { "key": { "$$placeholder": 1 } } } } } }, { "database": { "id": "database0", "client": "client0", "databaseName": "keyvault" } }, { "collection": { "id": "collection0", "database": "database0", "collectionName": "datakeys" } } ], "initialData": [ { "databaseName": "keyvault", "collectionName": "datakeys", "documents": [ { "_id": { "$binary": { "base64": "bG9jYWxrZXlsb2NhbGtleQ==", "subType": "04" } }, "keyMaterial": { "$binary": { "base64": "ABKBldDEoDW323yejOnIRk6YQmlD9d3eQthd16scKL75nz2LjNL9fgPDZWrFFOlqlhMCFaSrNJfGrFUjYk5JFDO7soG5Syb50k1niJoKg4ilsj0L4mpimFUtTpOr2nzZOeQtvAksEXc7gsFgq8gV7t/U3lsaXPY7I0t42DfSE8EGlPdxRjFdHnxh+OR8h7U9b8Qs5K5UuhgyeyxaBZ1Hgw==", "subType": "00" } }, "creationDate": { "$date": { "$numberLong": "1641024000000" } }, "updateDate": { "$date": { "$numberLong": "1641024000000" } }, "status": 1, "masterKey": { "provider": "local" } } ] } ], "tests": [ { "description": "add keyAltName to non-existent data key", "operations": [ { "name": "addKeyAltName", "object": "clientEncryption0", "arguments": { "id": { "$binary": { "base64": "AAAjYWxrZXlsb2NhbGtleQ==", "subType": "04" } }, "keyAltName": "new_key_alt_name" }, "expectResult": { "$$unsetOrMatches": null } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "databaseName": "keyvault", "command": { "findAndModify": "datakeys", "query": { "_id": { "$binary": { "base64": "AAAjYWxrZXlsb2NhbGtleQ==", "subType": "04" } } }, "update": { "$addToSet": { "keyAltNames": "new_key_alt_name" } }, "writeConcern": { "w": "majority" } } } } ] } ], "outcome": [ { "collectionName": "datakeys", "databaseName": "keyvault", "documents": [ { "_id": { "$binary": { "base64": "bG9jYWxrZXlsb2NhbGtleQ==", "subType": "04" } }, "keyMaterial": { "$binary": { "base64": "ABKBldDEoDW323yejOnIRk6YQmlD9d3eQthd16scKL75nz2LjNL9fgPDZWrFFOlqlhMCFaSrNJfGrFUjYk5JFDO7soG5Syb50k1niJoKg4ilsj0L4mpimFUtTpOr2nzZOeQtvAksEXc7gsFgq8gV7t/U3lsaXPY7I0t42DfSE8EGlPdxRjFdHnxh+OR8h7U9b8Qs5K5UuhgyeyxaBZ1Hgw==", "subType": "00" } }, "creationDate": { "$date": { "$numberLong": "1641024000000" } }, "updateDate": { "$date": { "$numberLong": "1641024000000" } }, "status": 1, "masterKey": { "provider": "local" } } ] } ] }, { "description": "add new keyAltName to data key with no keyAltNames", "operations": [ { "name": "addKeyAltName", "object": "clientEncryption0", "arguments": { "id": { "$binary": { "base64": "bG9jYWxrZXlsb2NhbGtleQ==", "subType": "04" } }, "keyAltName": "local_key" }, "expectResult": { "_id": { "$binary": { "base64": "bG9jYWxrZXlsb2NhbGtleQ==", "subType": "04" } }, "keyMaterial": { "$binary": { "base64": "ABKBldDEoDW323yejOnIRk6YQmlD9d3eQthd16scKL75nz2LjNL9fgPDZWrFFOlqlhMCFaSrNJfGrFUjYk5JFDO7soG5Syb50k1niJoKg4ilsj0L4mpimFUtTpOr2nzZOeQtvAksEXc7gsFgq8gV7t/U3lsaXPY7I0t42DfSE8EGlPdxRjFdHnxh+OR8h7U9b8Qs5K5UuhgyeyxaBZ1Hgw==", "subType": "00" } }, "creationDate": { "$date": { "$numberLong": "1641024000000" } }, "updateDate": { "$date": { "$numberLong": "1641024000000" } }, "status": 1, "masterKey": { "provider": "local" } } }, { "name": "find", "object": "collection0", "arguments": { "filter": {}, "projection": { "_id": 0, "keyAltNames": 1 } }, "expectResult": [ { "keyAltNames": [ "local_key" ] } ] } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "databaseName": "keyvault", "command": { "findAndModify": "datakeys", "query": { "_id": { "$binary": { "base64": "bG9jYWxrZXlsb2NhbGtleQ==", "subType": "04" } } }, "update": { "$addToSet": { "keyAltNames": "local_key" } }, "writeConcern": { "w": "majority" } } } }, { "commandStartedEvent": { "commandName": "find" } } ] } ] }, { "description": "add existing keyAltName to existing data key", "operations": [ { "name": "addKeyAltName", "object": "clientEncryption0", "arguments": { "id": { "$binary": { "base64": "bG9jYWxrZXlsb2NhbGtleQ==", "subType": "04" } }, "keyAltName": "local_key" }, "expectResult": { "_id": { "$binary": { "base64": "bG9jYWxrZXlsb2NhbGtleQ==", "subType": "04" } }, "keyMaterial": { "$binary": { "base64": "ABKBldDEoDW323yejOnIRk6YQmlD9d3eQthd16scKL75nz2LjNL9fgPDZWrFFOlqlhMCFaSrNJfGrFUjYk5JFDO7soG5Syb50k1niJoKg4ilsj0L4mpimFUtTpOr2nzZOeQtvAksEXc7gsFgq8gV7t/U3lsaXPY7I0t42DfSE8EGlPdxRjFdHnxh+OR8h7U9b8Qs5K5UuhgyeyxaBZ1Hgw==", "subType": "00" } }, "creationDate": { "$date": { "$numberLong": "1641024000000" } }, "updateDate": { "$date": { "$numberLong": "1641024000000" } }, "status": 1, "masterKey": { "provider": "local" } } }, { "name": "addKeyAltName", "object": "clientEncryption0", "arguments": { "id": { "$binary": { "base64": "bG9jYWxrZXlsb2NhbGtleQ==", "subType": "04" } }, "keyAltName": "local_key" }, "expectResult": { "_id": { "$binary": { "base64": "bG9jYWxrZXlsb2NhbGtleQ==", "subType": "04" } }, "keyAltNames": [ "local_key" ], "keyMaterial": { "$$type": "binData" }, "creationDate": { "$$type": "date" }, "updateDate": { "$$type": "date" }, "status": 1, "masterKey": { "provider": "local" } } }, { "name": "find", "object": "collection0", "arguments": { "filter": {}, "projection": { "_id": 0, "keyAltNames": 1 } }, "expectResult": [ { "keyAltNames": [ "local_key" ] } ] } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "databaseName": "keyvault", "command": { "findAndModify": "datakeys", "query": { "_id": { "$binary": { "base64": "bG9jYWxrZXlsb2NhbGtleQ==", "subType": "04" } } }, "update": { "$addToSet": { "keyAltNames": "local_key" } }, "writeConcern": { "w": "majority" } } } }, { "commandStartedEvent": { "databaseName": "keyvault", "command": { "findAndModify": "datakeys", "query": { "_id": { "$binary": { "base64": "bG9jYWxrZXlsb2NhbGtleQ==", "subType": "04" } } }, "update": { "$addToSet": { "keyAltNames": "local_key" } }, "writeConcern": { "w": "majority" } } } }, { "commandStartedEvent": { "commandName": "find" } } ] } ] }, { "description": "add new keyAltName to data key with keyAltNames", "operations": [ { "name": "addKeyAltName", "object": "clientEncryption0", "arguments": { "id": { "$binary": { "base64": "bG9jYWxrZXlsb2NhbGtleQ==", "subType": "04" } }, "keyAltName": "local_key" }, "expectResult": { "_id": { "$binary": { "base64": "bG9jYWxrZXlsb2NhbGtleQ==", "subType": "04" } }, "keyMaterial": { "$binary": { "base64": "ABKBldDEoDW323yejOnIRk6YQmlD9d3eQthd16scKL75nz2LjNL9fgPDZWrFFOlqlhMCFaSrNJfGrFUjYk5JFDO7soG5Syb50k1niJoKg4ilsj0L4mpimFUtTpOr2nzZOeQtvAksEXc7gsFgq8gV7t/U3lsaXPY7I0t42DfSE8EGlPdxRjFdHnxh+OR8h7U9b8Qs5K5UuhgyeyxaBZ1Hgw==", "subType": "00" } }, "creationDate": { "$date": { "$numberLong": "1641024000000" } }, "updateDate": { "$date": { "$numberLong": "1641024000000" } }, "status": 1, "masterKey": { "provider": "local" } } }, { "name": "addKeyAltName", "object": "clientEncryption0", "arguments": { "id": { "$binary": { "base64": "bG9jYWxrZXlsb2NhbGtleQ==", "subType": "04" } }, "keyAltName": "another_name" }, "expectResult": { "_id": { "$binary": { "base64": "bG9jYWxrZXlsb2NhbGtleQ==", "subType": "04" } }, "keyAltNames": [ "local_key" ], "keyMaterial": { "$$type": "binData" }, "creationDate": { "$$type": "date" }, "updateDate": { "$$type": "date" }, "status": 1, "masterKey": { "provider": "local" } } }, { "name": "aggregate", "object": "collection0", "arguments": { "pipeline": [ { "$project": { "_id": 0, "keyAltNames": "$keyAltNames" } }, { "$unwind": "$keyAltNames" }, { "$sort": { "keyAltNames": 1 } } ] }, "expectResult": [ { "keyAltNames": "another_name" }, { "keyAltNames": "local_key" } ] } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "databaseName": "keyvault", "command": { "findAndModify": "datakeys", "query": { "_id": { "$binary": { "base64": "bG9jYWxrZXlsb2NhbGtleQ==", "subType": "04" } } }, "update": { "$addToSet": { "keyAltNames": "local_key" } }, "writeConcern": { "w": "majority" } } } }, { "commandStartedEvent": { "databaseName": "keyvault", "command": { "findAndModify": "datakeys", "query": { "_id": { "$binary": { "base64": "bG9jYWxrZXlsb2NhbGtleQ==", "subType": "04" } } }, "update": { "$addToSet": { "keyAltNames": "another_name" } }, "writeConcern": { "w": "majority" } } } }, { "commandStartedEvent": { "commandName": "aggregate" } } ] } ] } ] } createDataKey-kms_providers-invalid.json000066400000000000000000000051101462766011000372110ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/client-side-encryption/spec/unified{ "description": "createDataKey-kms_providers-invalid", "schemaVersion": "1.8", "runOnRequirements": [ { "csfle": true } ], "createEntities": [ { "client": { "id": "client0", "observeEvents": [ "commandStartedEvent", "commandSucceededEvent", "commandFailedEvent" ] } }, { "clientEncryption": { "id": "clientEncryption0", "clientEncryptionOpts": { "keyVaultClient": "client0", "keyVaultNamespace": "keyvault.datakeys", "kmsProviders": { "aws": { "accessKeyId": { "$$placeholder": 1 }, "secretAccessKey": { "$$placeholder": 1 } } } } } } ], "tests": [ { "description": "create data key without required master key fields", "operations": [ { "name": "createDataKey", "object": "clientEncryption0", "arguments": { "kmsProvider": "aws", "opts": { "masterKey": {} } }, "expectError": { "isClientError": true } } ], "expectEvents": [ { "client": "client0", "events": [] } ] }, { "description": "create data key with invalid master key field", "operations": [ { "name": "createDataKey", "object": "clientEncryption0", "arguments": { "kmsProvider": "local", "opts": { "masterKey": { "invalid": 1 } } }, "expectError": { "isClientError": true } } ], "expectEvents": [ { "client": "client0", "events": [] } ] }, { "description": "create data key with invalid master key", "operations": [ { "name": "createDataKey", "object": "clientEncryption0", "arguments": { "kmsProvider": "aws", "opts": { "masterKey": { "key": "arn:aws:kms:us-east-1:579766882180:key/89fcc2c4-08b0-4bd9-9f25-e30687b580d0", "region": "invalid" } } }, "expectError": { "isClientError": true } } ], "expectEvents": [ { "client": "client0", "events": [] } ] } ] } mongodb-mongo-python-driver-509e9b7/test/client-side-encryption/spec/unified/createDataKey.json000066400000000000000000000452021462766011000327650ustar00rootroot00000000000000{ "description": "createDataKey", "schemaVersion": "1.8", "runOnRequirements": [ { "csfle": true } ], "createEntities": [ { "client": { "id": "client0", "observeEvents": [ "commandStartedEvent" ] } }, { "clientEncryption": { "id": "clientEncryption0", "clientEncryptionOpts": { "keyVaultClient": "client0", "keyVaultNamespace": "keyvault.datakeys", "kmsProviders": { "aws": { "accessKeyId": { "$$placeholder": 1 }, "secretAccessKey": { "$$placeholder": 1 } }, "azure": { "tenantId": { "$$placeholder": 1 }, "clientId": { "$$placeholder": 1 }, "clientSecret": { "$$placeholder": 1 } }, "gcp": { "email": { "$$placeholder": 1 }, "privateKey": { "$$placeholder": 1 } }, "kmip": { "endpoint": { "$$placeholder": 1 } }, "local": { "key": { "$$placeholder": 1 } } } } } }, { "database": { "id": "database0", "client": "client0", "databaseName": "keyvault" } }, { "collection": { "id": "collection0", "database": "database0", "collectionName": "datakeys" } } ], "initialData": [ { "databaseName": "keyvault", "collectionName": "datakeys", "documents": [] } ], "tests": [ { "description": "create data key with AWS KMS provider", "operations": [ { "name": "createDataKey", "object": "clientEncryption0", "arguments": { "kmsProvider": "aws", "opts": { "masterKey": { "key": "arn:aws:kms:us-east-1:579766882180:key/89fcc2c4-08b0-4bd9-9f25-e30687b580d0", "region": "us-east-1" } } }, "expectResult": { "$$type": "binData" } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "databaseName": "keyvault", "command": { "insert": "datakeys", "documents": [ { "_id": { "$$type": "binData" }, "keyMaterial": { "$$type": "binData" }, "creationDate": { "$$type": "date" }, "updateDate": { "$$type": "date" }, "status": { "$$exists": true }, "masterKey": { "provider": "aws", "key": "arn:aws:kms:us-east-1:579766882180:key/89fcc2c4-08b0-4bd9-9f25-e30687b580d0", "region": "us-east-1" } } ], "writeConcern": { "w": "majority" } } } } ] } ] }, { "description": "create datakey with Azure KMS provider", "operations": [ { "name": "createDataKey", "object": "clientEncryption0", "arguments": { "kmsProvider": "azure", "opts": { "masterKey": { "keyVaultEndpoint": "key-vault-csfle.vault.azure.net", "keyName": "key-name-csfle" } } }, "expectResult": { "$$type": "binData" } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "databaseName": "keyvault", "command": { "insert": "datakeys", "documents": [ { "_id": { "$$type": "binData" }, "keyMaterial": { "$$type": "binData" }, "creationDate": { "$$type": "date" }, "updateDate": { "$$type": "date" }, "status": { "$$exists": true }, "masterKey": { "provider": "azure", "keyVaultEndpoint": "key-vault-csfle.vault.azure.net", "keyName": "key-name-csfle" } } ], "writeConcern": { "w": "majority" } } } } ] } ] }, { "description": "create datakey with GCP KMS provider", "operations": [ { "name": "createDataKey", "object": "clientEncryption0", "arguments": { "kmsProvider": "gcp", "opts": { "masterKey": { "projectId": "devprod-drivers", "location": "global", "keyRing": "key-ring-csfle", "keyName": "key-name-csfle" } } }, "expectResult": { "$$type": "binData" } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "databaseName": "keyvault", "command": { "insert": "datakeys", "documents": [ { "_id": { "$$type": "binData" }, "keyMaterial": { "$$type": "binData" }, "creationDate": { "$$type": "date" }, "updateDate": { "$$type": "date" }, "status": { "$$exists": true }, "masterKey": { "provider": "gcp", "projectId": "devprod-drivers", "location": "global", "keyRing": "key-ring-csfle", "keyName": "key-name-csfle" } } ], "writeConcern": { "w": "majority" } } } } ] } ] }, { "description": "create datakey with KMIP KMS provider", "operations": [ { "name": "createDataKey", "object": "clientEncryption0", "arguments": { "kmsProvider": "kmip" }, "expectResult": { "$$type": "binData" } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "databaseName": "keyvault", "command": { "insert": "datakeys", "documents": [ { "_id": { "$$type": "binData" }, "keyMaterial": { "$$type": "binData" }, "creationDate": { "$$type": "date" }, "updateDate": { "$$type": "date" }, "status": { "$$exists": true }, "masterKey": { "provider": "kmip", "keyId": { "$$type": "string" } } } ], "writeConcern": { "w": "majority" } } } } ] } ] }, { "description": "create datakey with local KMS provider", "operations": [ { "name": "createDataKey", "object": "clientEncryption0", "arguments": { "kmsProvider": "local" }, "expectResult": { "$$type": "binData" } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "databaseName": "keyvault", "command": { "insert": "datakeys", "documents": [ { "_id": { "$$type": "binData" }, "keyMaterial": { "$$type": "binData" }, "creationDate": { "$$type": "date" }, "updateDate": { "$$type": "date" }, "status": { "$$exists": true }, "masterKey": { "provider": "local" } } ], "writeConcern": { "w": "majority" } } } } ] } ] }, { "description": "create datakey with no keyAltName", "operations": [ { "name": "createDataKey", "object": "clientEncryption0", "arguments": { "kmsProvider": "local", "opts": { "keyAltNames": [] } }, "expectResult": { "$$type": "binData" } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "databaseName": "keyvault", "command": { "insert": "datakeys", "documents": [ { "_id": { "$$type": "binData" }, "keyAltNames": { "$$exists": false }, "keyMaterial": { "$$type": "binData" }, "creationDate": { "$$type": "date" }, "updateDate": { "$$type": "date" }, "status": { "$$type": "int" }, "masterKey": { "$$type": "object" } } ], "writeConcern": { "w": "majority" } } } } ] } ] }, { "description": "create datakey with single keyAltName", "operations": [ { "name": "createDataKey", "object": "clientEncryption0", "arguments": { "kmsProvider": "local", "opts": { "keyAltNames": [ "local_key" ] } }, "expectResult": { "$$type": "binData" } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "databaseName": "keyvault", "command": { "insert": "datakeys", "documents": [ { "_id": { "$$type": "binData" }, "keyAltNames": [ "local_key" ], "keyMaterial": { "$$type": "binData" }, "creationDate": { "$$type": "date" }, "updateDate": { "$$type": "date" }, "status": { "$$type": "int" }, "masterKey": { "$$type": "object" } } ], "writeConcern": { "w": "majority" } } } } ] } ] }, { "description": "create datakey with multiple keyAltNames", "operations": [ { "name": "createDataKey", "object": "clientEncryption0", "arguments": { "kmsProvider": "local", "opts": { "keyAltNames": [ "abc", "def" ] } }, "expectResult": { "$$type": "binData" } }, { "name": "aggregate", "object": "collection0", "arguments": { "pipeline": [ { "$project": { "_id": 0, "keyAltNames": 1 } }, { "$unwind": "$keyAltNames" }, { "$sort": { "keyAltNames": 1 } } ] }, "expectResult": [ { "keyAltNames": "abc" }, { "keyAltNames": "def" } ] } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "databaseName": "keyvault", "command": { "insert": "datakeys", "documents": [ { "_id": { "$$type": "binData" }, "keyAltNames": { "$$type": "array" }, "keyMaterial": { "$$type": "binData" }, "creationDate": { "$$type": "date" }, "updateDate": { "$$type": "date" }, "status": { "$$type": "int" }, "masterKey": { "$$type": "object" } } ], "writeConcern": { "w": "majority" } } } }, { "commandStartedEvent": { "commandName": "aggregate" } } ] } ] }, { "description": "create datakey with custom key material", "operations": [ { "name": "createDataKey", "object": "clientEncryption0", "arguments": { "kmsProvider": "local", "opts": { "keyMaterial": { "$binary": { "base64": "a2V5X21hdGVyaWFsa2V5X21hdGVyaWFsa2V5X21hdGVyaWFsa2V5X21hdGVyaWFsa2V5X21hdGVyaWFsa2V5X21hdGVyaWFsa2V5X21hdGVyaWFsa2V5X21hdGVyaWFs", "subType": "00" } } } }, "expectResult": { "$$type": "binData" } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "databaseName": "keyvault", "command": { "insert": "datakeys", "documents": [ { "_id": { "$$type": "binData" }, "keyMaterial": { "$$type": "binData" }, "creationDate": { "$$type": "date" }, "updateDate": { "$$type": "date" }, "status": { "$$type": "int" }, "masterKey": { "$$type": "object" } } ], "writeConcern": { "w": "majority" } } } } ] } ] }, { "description": "create datakey with invalid custom key material (too short)", "operations": [ { "name": "createDataKey", "object": "clientEncryption0", "arguments": { "kmsProvider": "local", "opts": { "keyMaterial": { "$binary": { "base64": "a2V5X21hdGVyaWFsa2V5X21hdGVyaWFsa2V5X21hdGVyaWFsa2V5X21hdGVyaWFsa2V5X21hdGVyaWFsa2V5X21hdGVyaWFsa2V5X21hdGVyaWFs", "subType": "00" } } } }, "expectError": { "isClientError": true } } ], "expectEvents": [ { "client": "client0", "events": [] } ] } ] } mongodb-mongo-python-driver-509e9b7/test/client-side-encryption/spec/unified/deleteKey.json000066400000000000000000000370311462766011000321730ustar00rootroot00000000000000{ "description": "deleteKey", "schemaVersion": "1.8", "runOnRequirements": [ { "csfle": true } ], "createEntities": [ { "client": { "id": "client0", "observeEvents": [ "commandStartedEvent" ] } }, { "clientEncryption": { "id": "clientEncryption0", "clientEncryptionOpts": { "keyVaultClient": "client0", "keyVaultNamespace": "keyvault.datakeys", "kmsProviders": { "local": { "key": { "$$placeholder": 1 } } } } } }, { "database": { "id": "database0", "client": "client0", "databaseName": "keyvault" } }, { "collection": { "id": "collection0", "database": "database0", "collectionName": "datakeys" } } ], "initialData": [ { "databaseName": "keyvault", "collectionName": "datakeys", "documents": [ { "_id": { "$binary": { "base64": "YXdzYXdzYXdzYXdzYXdzYQ==", "subType": "04" } }, "keyAltNames": [ "aws_key" ], "keyMaterial": { "$binary": { "base64": "AQICAHhQNmWG2CzOm1dq3kWLM+iDUZhEqnhJwH9wZVpuZ94A8gFXJqbF0Fy872MD7xl56D/2AAAAwjCBvwYJKoZIhvcNAQcGoIGxMIGuAgEAMIGoBgkqhkiG9w0BBwEwHgYJYIZIAWUDBAEuMBEEDO7HPisPUlGzaio9vgIBEIB7/Qow46PMh/8JbEUbdXgTGhLfXPE+KIVW7T8s6YEMlGiRvMu7TV0QCIUJlSHPKZxzlJ2iwuz5yXeOag+EdY+eIQ0RKrsJ3b8UTisZYzGjfzZnxUKLzLoeXremtRCm3x47wCuHKd1dhh6FBbYt5TL2tDaj+vL2GBrKat2L", "subType": "00" } }, "creationDate": { "$date": { "$numberLong": "1641024000000" } }, "updateDate": { "$date": { "$numberLong": "1641024000000" } }, "status": 1, "masterKey": { "provider": "aws", "key": "arn:aws:kms:us-east-1:579766882180:key/89fcc2c4-08b0-4bd9-9f25-e30687b580d0", "region": "us-east-1" } }, { "_id": { "$binary": { "base64": "bG9jYWxrZXlsb2NhbGtleQ==", "subType": "04" } }, "keyAltNames": [ "local_key" ], "keyMaterial": { "$binary": { "base64": "ABKBldDEoDW323yejOnIRk6YQmlD9d3eQthd16scKL75nz2LjNL9fgPDZWrFFOlqlhMCFaSrNJfGrFUjYk5JFDO7soG5Syb50k1niJoKg4ilsj0L4mpimFUtTpOr2nzZOeQtvAksEXc7gsFgq8gV7t/U3lsaXPY7I0t42DfSE8EGlPdxRjFdHnxh+OR8h7U9b8Qs5K5UuhgyeyxaBZ1Hgw==", "subType": "00" } }, "creationDate": { "$date": { "$numberLong": "1641024000000" } }, "updateDate": { "$date": { "$numberLong": "1641024000000" } }, "status": 1, "masterKey": { "provider": "local" } } ] } ], "tests": [ { "description": "delete non-existent data key", "operations": [ { "name": "deleteKey", "object": "clientEncryption0", "arguments": { "id": { "$binary": { "base64": "AAAzYXdzYXdzYXdzYXdzYQ==", "subType": "04" } } }, "expectResult": { "deletedCount": 0 } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "databaseName": "keyvault", "command": { "delete": "datakeys", "deletes": [ { "q": { "_id": { "$binary": { "base64": "AAAzYXdzYXdzYXdzYXdzYQ==", "subType": "04" } } }, "limit": 1 } ], "writeConcern": { "w": "majority" } } } } ] } ], "outcome": [ { "collectionName": "datakeys", "databaseName": "keyvault", "documents": [ { "_id": { "$binary": { "base64": "YXdzYXdzYXdzYXdzYXdzYQ==", "subType": "04" } }, "keyAltNames": [ "aws_key" ], "keyMaterial": { "$binary": { "base64": "AQICAHhQNmWG2CzOm1dq3kWLM+iDUZhEqnhJwH9wZVpuZ94A8gFXJqbF0Fy872MD7xl56D/2AAAAwjCBvwYJKoZIhvcNAQcGoIGxMIGuAgEAMIGoBgkqhkiG9w0BBwEwHgYJYIZIAWUDBAEuMBEEDO7HPisPUlGzaio9vgIBEIB7/Qow46PMh/8JbEUbdXgTGhLfXPE+KIVW7T8s6YEMlGiRvMu7TV0QCIUJlSHPKZxzlJ2iwuz5yXeOag+EdY+eIQ0RKrsJ3b8UTisZYzGjfzZnxUKLzLoeXremtRCm3x47wCuHKd1dhh6FBbYt5TL2tDaj+vL2GBrKat2L", "subType": "00" } }, "creationDate": { "$date": { "$numberLong": "1641024000000" } }, "updateDate": { "$date": { "$numberLong": "1641024000000" } }, "status": 1, "masterKey": { "provider": "aws", "key": "arn:aws:kms:us-east-1:579766882180:key/89fcc2c4-08b0-4bd9-9f25-e30687b580d0", "region": "us-east-1" } }, { "_id": { "$binary": { "base64": "bG9jYWxrZXlsb2NhbGtleQ==", "subType": "04" } }, "keyAltNames": [ "local_key" ], "keyMaterial": { "$binary": { "base64": "ABKBldDEoDW323yejOnIRk6YQmlD9d3eQthd16scKL75nz2LjNL9fgPDZWrFFOlqlhMCFaSrNJfGrFUjYk5JFDO7soG5Syb50k1niJoKg4ilsj0L4mpimFUtTpOr2nzZOeQtvAksEXc7gsFgq8gV7t/U3lsaXPY7I0t42DfSE8EGlPdxRjFdHnxh+OR8h7U9b8Qs5K5UuhgyeyxaBZ1Hgw==", "subType": "00" } }, "creationDate": { "$date": { "$numberLong": "1641024000000" } }, "updateDate": { "$date": { "$numberLong": "1641024000000" } }, "status": 1, "masterKey": { "provider": "local" } } ] } ] }, { "description": "delete existing AWS data key", "operations": [ { "name": "deleteKey", "object": "clientEncryption0", "arguments": { "id": { "$binary": { "base64": "YXdzYXdzYXdzYXdzYXdzYQ==", "subType": "04" } } }, "expectResult": { "deletedCount": 1 } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "databaseName": "keyvault", "command": { "delete": "datakeys", "deletes": [ { "q": { "_id": { "$binary": { "base64": "YXdzYXdzYXdzYXdzYXdzYQ==", "subType": "04" } } }, "limit": 1 } ], "writeConcern": { "w": "majority" } } } } ] } ], "outcome": [ { "collectionName": "datakeys", "databaseName": "keyvault", "documents": [ { "_id": { "$binary": { "base64": "bG9jYWxrZXlsb2NhbGtleQ==", "subType": "04" } }, "keyAltNames": [ "local_key" ], "keyMaterial": { "$binary": { "base64": "ABKBldDEoDW323yejOnIRk6YQmlD9d3eQthd16scKL75nz2LjNL9fgPDZWrFFOlqlhMCFaSrNJfGrFUjYk5JFDO7soG5Syb50k1niJoKg4ilsj0L4mpimFUtTpOr2nzZOeQtvAksEXc7gsFgq8gV7t/U3lsaXPY7I0t42DfSE8EGlPdxRjFdHnxh+OR8h7U9b8Qs5K5UuhgyeyxaBZ1Hgw==", "subType": "00" } }, "creationDate": { "$date": { "$numberLong": "1641024000000" } }, "updateDate": { "$date": { "$numberLong": "1641024000000" } }, "status": 1, "masterKey": { "provider": "local" } } ] } ] }, { "description": "delete existing local data key", "operations": [ { "name": "deleteKey", "object": "clientEncryption0", "arguments": { "id": { "$binary": { "base64": "bG9jYWxrZXlsb2NhbGtleQ==", "subType": "04" } } }, "expectResult": { "deletedCount": 1 } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "databaseName": "keyvault", "command": { "delete": "datakeys", "deletes": [ { "q": { "_id": { "$binary": { "base64": "bG9jYWxrZXlsb2NhbGtleQ==", "subType": "04" } } }, "limit": 1 } ], "writeConcern": { "w": "majority" } } } } ] } ], "outcome": [ { "collectionName": "datakeys", "databaseName": "keyvault", "documents": [ { "_id": { "$binary": { "base64": "YXdzYXdzYXdzYXdzYXdzYQ==", "subType": "04" } }, "keyAltNames": [ "aws_key" ], "keyMaterial": { "$binary": { "base64": "AQICAHhQNmWG2CzOm1dq3kWLM+iDUZhEqnhJwH9wZVpuZ94A8gFXJqbF0Fy872MD7xl56D/2AAAAwjCBvwYJKoZIhvcNAQcGoIGxMIGuAgEAMIGoBgkqhkiG9w0BBwEwHgYJYIZIAWUDBAEuMBEEDO7HPisPUlGzaio9vgIBEIB7/Qow46PMh/8JbEUbdXgTGhLfXPE+KIVW7T8s6YEMlGiRvMu7TV0QCIUJlSHPKZxzlJ2iwuz5yXeOag+EdY+eIQ0RKrsJ3b8UTisZYzGjfzZnxUKLzLoeXremtRCm3x47wCuHKd1dhh6FBbYt5TL2tDaj+vL2GBrKat2L", "subType": "00" } }, "creationDate": { "$date": { "$numberLong": "1641024000000" } }, "updateDate": { "$date": { "$numberLong": "1641024000000" } }, "status": 1, "masterKey": { "provider": "aws", "key": "arn:aws:kms:us-east-1:579766882180:key/89fcc2c4-08b0-4bd9-9f25-e30687b580d0", "region": "us-east-1" } } ] } ] }, { "description": "delete existing data key twice", "operations": [ { "name": "deleteKey", "object": "clientEncryption0", "arguments": { "id": { "$binary": { "base64": "YXdzYXdzYXdzYXdzYXdzYQ==", "subType": "04" } } }, "expectResult": { "deletedCount": 1 } }, { "name": "deleteKey", "object": "clientEncryption0", "arguments": { "id": { "$binary": { "base64": "YXdzYXdzYXdzYXdzYXdzYQ==", "subType": "04" } } }, "expectResult": { "deletedCount": 0 } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "databaseName": "keyvault", "command": { "delete": "datakeys", "deletes": [ { "q": { "_id": { "$binary": { "base64": "YXdzYXdzYXdzYXdzYXdzYQ==", "subType": "04" } } }, "limit": 1 } ], "writeConcern": { "w": "majority" } } } }, { "commandStartedEvent": { "databaseName": "keyvault", "command": { "delete": "datakeys", "deletes": [ { "q": { "_id": { "$binary": { "base64": "YXdzYXdzYXdzYXdzYXdzYQ==", "subType": "04" } } }, "limit": 1 } ], "writeConcern": { "w": "majority" } } } } ] } ], "outcome": [ { "collectionName": "datakeys", "databaseName": "keyvault", "documents": [ { "_id": { "$binary": { "base64": "bG9jYWxrZXlsb2NhbGtleQ==", "subType": "04" } }, "keyAltNames": [ "local_key" ], "keyMaterial": { "$binary": { "base64": "ABKBldDEoDW323yejOnIRk6YQmlD9d3eQthd16scKL75nz2LjNL9fgPDZWrFFOlqlhMCFaSrNJfGrFUjYk5JFDO7soG5Syb50k1niJoKg4ilsj0L4mpimFUtTpOr2nzZOeQtvAksEXc7gsFgq8gV7t/U3lsaXPY7I0t42DfSE8EGlPdxRjFdHnxh+OR8h7U9b8Qs5K5UuhgyeyxaBZ1Hgw==", "subType": "00" } }, "creationDate": { "$date": { "$numberLong": "1641024000000" } }, "updateDate": { "$date": { "$numberLong": "1641024000000" } }, "status": 1, "masterKey": { "provider": "local" } } ] } ] } ] } mongodb-mongo-python-driver-509e9b7/test/client-side-encryption/spec/unified/getKey.json000066400000000000000000000210301462766011000315000ustar00rootroot00000000000000{ "description": "getKey", "schemaVersion": "1.8", "runOnRequirements": [ { "csfle": true } ], "createEntities": [ { "client": { "id": "client0", "observeEvents": [ "commandStartedEvent" ] } }, { "clientEncryption": { "id": "clientEncryption0", "clientEncryptionOpts": { "keyVaultClient": "client0", "keyVaultNamespace": "keyvault.datakeys", "kmsProviders": { "local": { "key": { "$$placeholder": 1 } } } } } }, { "database": { "id": "database0", "client": "client0", "databaseName": "keyvault" } }, { "collection": { "id": "collection0", "database": "database0", "collectionName": "datakeys" } } ], "initialData": [ { "databaseName": "keyvault", "collectionName": "datakeys", "documents": [ { "_id": { "$binary": { "base64": "YXdzYXdzYXdzYXdzYXdzYQ==", "subType": "04" } }, "keyAltNames": [ "aws_key" ], "keyMaterial": { "$binary": { "base64": "AQICAHhQNmWG2CzOm1dq3kWLM+iDUZhEqnhJwH9wZVpuZ94A8gFXJqbF0Fy872MD7xl56D/2AAAAwjCBvwYJKoZIhvcNAQcGoIGxMIGuAgEAMIGoBgkqhkiG9w0BBwEwHgYJYIZIAWUDBAEuMBEEDO7HPisPUlGzaio9vgIBEIB7/Qow46PMh/8JbEUbdXgTGhLfXPE+KIVW7T8s6YEMlGiRvMu7TV0QCIUJlSHPKZxzlJ2iwuz5yXeOag+EdY+eIQ0RKrsJ3b8UTisZYzGjfzZnxUKLzLoeXremtRCm3x47wCuHKd1dhh6FBbYt5TL2tDaj+vL2GBrKat2L", "subType": "00" } }, "creationDate": { "$date": { "$numberLong": "1641024000000" } }, "updateDate": { "$date": { "$numberLong": "1641024000000" } }, "status": 1, "masterKey": { "provider": "aws", "key": "arn:aws:kms:us-east-1:579766882180:key/89fcc2c4-08b0-4bd9-9f25-e30687b580d0", "region": "us-east-1" } }, { "_id": { "$binary": { "base64": "bG9jYWxrZXlsb2NhbGtleQ==", "subType": "04" } }, "keyAltNames": [ "local_key" ], "keyMaterial": { "$binary": { "base64": "ABKBldDEoDW323yejOnIRk6YQmlD9d3eQthd16scKL75nz2LjNL9fgPDZWrFFOlqlhMCFaSrNJfGrFUjYk5JFDO7soG5Syb50k1niJoKg4ilsj0L4mpimFUtTpOr2nzZOeQtvAksEXc7gsFgq8gV7t/U3lsaXPY7I0t42DfSE8EGlPdxRjFdHnxh+OR8h7U9b8Qs5K5UuhgyeyxaBZ1Hgw==", "subType": "00" } }, "creationDate": { "$date": { "$numberLong": "1641024000000" } }, "updateDate": { "$date": { "$numberLong": "1641024000000" } }, "status": 1, "masterKey": { "provider": "local" } } ] } ], "tests": [ { "description": "get non-existent data key", "operations": [ { "name": "getKey", "object": "clientEncryption0", "arguments": { "id": { "$binary": { "base64": "AAAzYXdzYXdzYXdzYXdzYQ==", "subType": "04" } } }, "expectResult": { "$$unsetOrMatches": null } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "databaseName": "keyvault", "command": { "find": "datakeys", "filter": { "_id": { "$binary": { "base64": "AAAzYXdzYXdzYXdzYXdzYQ==", "subType": "04" } } }, "readConcern": { "level": "majority" } } } } ] } ] }, { "description": "get existing AWS data key", "operations": [ { "name": "getKey", "object": "clientEncryption0", "arguments": { "id": { "$binary": { "base64": "YXdzYXdzYXdzYXdzYXdzYQ==", "subType": "04" } } }, "expectResult": { "_id": { "$binary": { "base64": "YXdzYXdzYXdzYXdzYXdzYQ==", "subType": "04" } }, "keyAltNames": [ "aws_key" ], "keyMaterial": { "$binary": { "base64": "AQICAHhQNmWG2CzOm1dq3kWLM+iDUZhEqnhJwH9wZVpuZ94A8gFXJqbF0Fy872MD7xl56D/2AAAAwjCBvwYJKoZIhvcNAQcGoIGxMIGuAgEAMIGoBgkqhkiG9w0BBwEwHgYJYIZIAWUDBAEuMBEEDO7HPisPUlGzaio9vgIBEIB7/Qow46PMh/8JbEUbdXgTGhLfXPE+KIVW7T8s6YEMlGiRvMu7TV0QCIUJlSHPKZxzlJ2iwuz5yXeOag+EdY+eIQ0RKrsJ3b8UTisZYzGjfzZnxUKLzLoeXremtRCm3x47wCuHKd1dhh6FBbYt5TL2tDaj+vL2GBrKat2L", "subType": "00" } }, "creationDate": { "$date": { "$numberLong": "1641024000000" } }, "updateDate": { "$date": { "$numberLong": "1641024000000" } }, "status": 1, "masterKey": { "provider": "aws", "key": "arn:aws:kms:us-east-1:579766882180:key/89fcc2c4-08b0-4bd9-9f25-e30687b580d0", "region": "us-east-1" } } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "databaseName": "keyvault", "command": { "find": "datakeys", "filter": { "_id": { "$binary": { "base64": "YXdzYXdzYXdzYXdzYXdzYQ==", "subType": "04" } } }, "readConcern": { "level": "majority" } } } } ] } ] }, { "description": "get existing local data key", "operations": [ { "name": "getKey", "object": "clientEncryption0", "arguments": { "id": { "$binary": { "base64": "bG9jYWxrZXlsb2NhbGtleQ==", "subType": "04" } } }, "expectResult": { "_id": { "$binary": { "base64": "bG9jYWxrZXlsb2NhbGtleQ==", "subType": "04" } }, "keyAltNames": [ "local_key" ], "keyMaterial": { "$binary": { "base64": "ABKBldDEoDW323yejOnIRk6YQmlD9d3eQthd16scKL75nz2LjNL9fgPDZWrFFOlqlhMCFaSrNJfGrFUjYk5JFDO7soG5Syb50k1niJoKg4ilsj0L4mpimFUtTpOr2nzZOeQtvAksEXc7gsFgq8gV7t/U3lsaXPY7I0t42DfSE8EGlPdxRjFdHnxh+OR8h7U9b8Qs5K5UuhgyeyxaBZ1Hgw==", "subType": "00" } }, "creationDate": { "$date": { "$numberLong": "1641024000000" } }, "updateDate": { "$date": { "$numberLong": "1641024000000" } }, "status": 1, "masterKey": { "provider": "local" } } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "databaseName": "keyvault", "command": { "find": "datakeys", "filter": { "_id": { "$binary": { "base64": "bG9jYWxrZXlsb2NhbGtleQ==", "subType": "04" } } }, "readConcern": { "level": "majority" } } } } ] } ] } ] } mongodb-mongo-python-driver-509e9b7/test/client-side-encryption/spec/unified/getKeyByAltName.json000066400000000000000000000173341462766011000332510ustar00rootroot00000000000000{ "description": "getKeyByAltName", "schemaVersion": "1.8", "runOnRequirements": [ { "csfle": true } ], "createEntities": [ { "client": { "id": "client0", "observeEvents": [ "commandStartedEvent" ] } }, { "clientEncryption": { "id": "clientEncryption0", "clientEncryptionOpts": { "keyVaultClient": "client0", "keyVaultNamespace": "keyvault.datakeys", "kmsProviders": { "local": { "key": { "$$placeholder": 1 } } } } } }, { "database": { "id": "database0", "client": "client0", "databaseName": "keyvault" } }, { "collection": { "id": "collection0", "database": "database0", "collectionName": "datakeys" } } ], "initialData": [ { "databaseName": "keyvault", "collectionName": "datakeys", "documents": [ { "_id": { "$binary": { "base64": "YXdzYXdzYXdzYXdzYXdzYQ==", "subType": "04" } }, "keyAltNames": [ "aws_key" ], "keyMaterial": { "$binary": { "base64": "AQICAHhQNmWG2CzOm1dq3kWLM+iDUZhEqnhJwH9wZVpuZ94A8gFXJqbF0Fy872MD7xl56D/2AAAAwjCBvwYJKoZIhvcNAQcGoIGxMIGuAgEAMIGoBgkqhkiG9w0BBwEwHgYJYIZIAWUDBAEuMBEEDO7HPisPUlGzaio9vgIBEIB7/Qow46PMh/8JbEUbdXgTGhLfXPE+KIVW7T8s6YEMlGiRvMu7TV0QCIUJlSHPKZxzlJ2iwuz5yXeOag+EdY+eIQ0RKrsJ3b8UTisZYzGjfzZnxUKLzLoeXremtRCm3x47wCuHKd1dhh6FBbYt5TL2tDaj+vL2GBrKat2L", "subType": "00" } }, "creationDate": { "$date": { "$numberLong": "1641024000000" } }, "updateDate": { "$date": { "$numberLong": "1641024000000" } }, "status": 1, "masterKey": { "provider": "aws", "key": "arn:aws:kms:us-east-1:579766882180:key/89fcc2c4-08b0-4bd9-9f25-e30687b580d0", "region": "us-east-1" } }, { "_id": { "$binary": { "base64": "bG9jYWxrZXlsb2NhbGtleQ==", "subType": "04" } }, "keyAltNames": [ "local_key" ], "keyMaterial": { "$binary": { "base64": "ABKBldDEoDW323yejOnIRk6YQmlD9d3eQthd16scKL75nz2LjNL9fgPDZWrFFOlqlhMCFaSrNJfGrFUjYk5JFDO7soG5Syb50k1niJoKg4ilsj0L4mpimFUtTpOr2nzZOeQtvAksEXc7gsFgq8gV7t/U3lsaXPY7I0t42DfSE8EGlPdxRjFdHnxh+OR8h7U9b8Qs5K5UuhgyeyxaBZ1Hgw==", "subType": "00" } }, "creationDate": { "$date": { "$numberLong": "1641024000000" } }, "updateDate": { "$date": { "$numberLong": "1641024000000" } }, "status": 1, "masterKey": { "provider": "local" } } ] } ], "tests": [ { "description": "get non-existent data key", "operations": [ { "name": "getKeyByAltName", "object": "clientEncryption0", "arguments": { "keyAltName": "does_not_exist" }, "expectResult": { "$$unsetOrMatches": null } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "databaseName": "keyvault", "command": { "find": "datakeys", "filter": { "keyAltNames": "does_not_exist" }, "readConcern": { "level": "majority" } } } } ] } ] }, { "description": "get existing AWS data key", "operations": [ { "name": "getKeyByAltName", "object": "clientEncryption0", "arguments": { "keyAltName": "aws_key" }, "expectResult": { "_id": { "$binary": { "base64": "YXdzYXdzYXdzYXdzYXdzYQ==", "subType": "04" } }, "keyAltNames": [ "aws_key" ], "keyMaterial": { "$binary": { "base64": "AQICAHhQNmWG2CzOm1dq3kWLM+iDUZhEqnhJwH9wZVpuZ94A8gFXJqbF0Fy872MD7xl56D/2AAAAwjCBvwYJKoZIhvcNAQcGoIGxMIGuAgEAMIGoBgkqhkiG9w0BBwEwHgYJYIZIAWUDBAEuMBEEDO7HPisPUlGzaio9vgIBEIB7/Qow46PMh/8JbEUbdXgTGhLfXPE+KIVW7T8s6YEMlGiRvMu7TV0QCIUJlSHPKZxzlJ2iwuz5yXeOag+EdY+eIQ0RKrsJ3b8UTisZYzGjfzZnxUKLzLoeXremtRCm3x47wCuHKd1dhh6FBbYt5TL2tDaj+vL2GBrKat2L", "subType": "00" } }, "creationDate": { "$date": { "$numberLong": "1641024000000" } }, "updateDate": { "$date": { "$numberLong": "1641024000000" } }, "status": 1, "masterKey": { "provider": "aws", "key": "arn:aws:kms:us-east-1:579766882180:key/89fcc2c4-08b0-4bd9-9f25-e30687b580d0", "region": "us-east-1" } } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "databaseName": "keyvault", "command": { "find": "datakeys", "filter": { "keyAltNames": "aws_key" }, "readConcern": { "level": "majority" } } } } ] } ] }, { "description": "get existing local data key", "operations": [ { "name": "getKeyByAltName", "object": "clientEncryption0", "arguments": { "keyAltName": "local_key" }, "expectResult": { "_id": { "$binary": { "base64": "bG9jYWxrZXlsb2NhbGtleQ==", "subType": "04" } }, "keyAltNames": [ "local_key" ], "keyMaterial": { "$binary": { "base64": "ABKBldDEoDW323yejOnIRk6YQmlD9d3eQthd16scKL75nz2LjNL9fgPDZWrFFOlqlhMCFaSrNJfGrFUjYk5JFDO7soG5Syb50k1niJoKg4ilsj0L4mpimFUtTpOr2nzZOeQtvAksEXc7gsFgq8gV7t/U3lsaXPY7I0t42DfSE8EGlPdxRjFdHnxh+OR8h7U9b8Qs5K5UuhgyeyxaBZ1Hgw==", "subType": "00" } }, "creationDate": { "$date": { "$numberLong": "1641024000000" } }, "updateDate": { "$date": { "$numberLong": "1641024000000" } }, "status": 1, "masterKey": { "provider": "local" } } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "databaseName": "keyvault", "command": { "find": "datakeys", "filter": { "keyAltNames": "local_key" }, "readConcern": { "level": "majority" } } } } ] } ] } ] } mongodb-mongo-python-driver-509e9b7/test/client-side-encryption/spec/unified/getKeys.json000066400000000000000000000134221462766011000316710ustar00rootroot00000000000000{ "description": "getKeys", "schemaVersion": "1.8", "runOnRequirements": [ { "csfle": true } ], "createEntities": [ { "client": { "id": "client0", "observeEvents": [ "commandStartedEvent" ] } }, { "clientEncryption": { "id": "clientEncryption0", "clientEncryptionOpts": { "keyVaultClient": "client0", "keyVaultNamespace": "keyvault.datakeys", "kmsProviders": { "local": { "key": { "$$placeholder": 1 } } } } } }, { "database": { "id": "database0", "client": "client0", "databaseName": "keyvault" } }, { "collection": { "id": "collection0", "database": "database0", "collectionName": "datakeys" } } ], "initialData": [ { "databaseName": "keyvault", "collectionName": "datakeys", "documents": [] } ], "tests": [ { "description": "getKeys with zero key documents", "operations": [ { "name": "getKeys", "object": "clientEncryption0", "expectResult": [] } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "databaseName": "keyvault", "command": { "find": "datakeys", "filter": {}, "readConcern": { "level": "majority" } } } } ] } ] }, { "description": "getKeys with single key documents", "operations": [ { "name": "createDataKey", "object": "clientEncryption0", "arguments": { "kmsProvider": "local", "opts": { "keyAltNames": [ "abc" ] } }, "expectResult": { "$$type": "binData" } }, { "name": "getKeys", "object": "clientEncryption0", "expectResult": [ { "_id": { "$$type": "binData" }, "keyAltNames": [ "abc" ], "keyMaterial": { "$$type": "binData" }, "creationDate": { "$$type": "date" }, "updateDate": { "$$type": "date" }, "status": { "$$type": "int" }, "masterKey": { "$$type": "object" } } ] } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "commandName": "insert" } }, { "commandStartedEvent": { "databaseName": "keyvault", "command": { "find": "datakeys", "filter": {}, "readConcern": { "level": "majority" } } } } ] } ] }, { "description": "getKeys with many key documents", "operations": [ { "name": "createDataKey", "object": "clientEncryption0", "arguments": { "kmsProvider": "local" }, "expectResult": { "$$type": "binData" } }, { "name": "createDataKey", "object": "clientEncryption0", "arguments": { "kmsProvider": "local" }, "expectResult": { "$$type": "binData" } }, { "name": "getKeys", "object": "clientEncryption0", "expectResult": [ { "_id": { "$$type": "binData" }, "keyMaterial": { "$$type": "binData" }, "creationDate": { "$$type": "date" }, "updateDate": { "$$type": "date" }, "status": { "$$type": "int" }, "masterKey": { "$$type": "object" } }, { "_id": { "$$type": "binData" }, "keyMaterial": { "$$type": "binData" }, "creationDate": { "$$type": "date" }, "updateDate": { "$$type": "date" }, "status": { "$$type": "int" }, "masterKey": { "$$type": "object" } } ] } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "commandName": "insert" } }, { "commandStartedEvent": { "commandName": "insert" } }, { "commandStartedEvent": { "databaseName": "keyvault", "command": { "find": "datakeys", "filter": {}, "readConcern": { "level": "majority" } } } } ] } ] } ] } namedKMS-createDataKey.json000066400000000000000000000247451462766011000343540ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/client-side-encryption/spec/unified{ "description": "namedKMS-createDataKey", "schemaVersion": "1.18", "runOnRequirements": [ { "csfle": true } ], "createEntities": [ { "client": { "id": "client0", "observeEvents": [ "commandStartedEvent" ] } }, { "clientEncryption": { "id": "clientEncryption0", "clientEncryptionOpts": { "keyVaultClient": "client0", "keyVaultNamespace": "keyvault.datakeys", "kmsProviders": { "aws:name1": { "accessKeyId": { "$$placeholder": 1 }, "secretAccessKey": { "$$placeholder": 1 } }, "azure:name1": { "tenantId": { "$$placeholder": 1 }, "clientId": { "$$placeholder": 1 }, "clientSecret": { "$$placeholder": 1 } }, "gcp:name1": { "email": { "$$placeholder": 1 }, "privateKey": { "$$placeholder": 1 } }, "kmip:name1": { "endpoint": { "$$placeholder": 1 } }, "local:name1": { "key": { "$$placeholder": 1 } } } } } }, { "database": { "id": "database0", "client": "client0", "databaseName": "keyvault" } }, { "collection": { "id": "collection0", "database": "database0", "collectionName": "datakeys" } } ], "initialData": [ { "databaseName": "keyvault", "collectionName": "datakeys", "documents": [] } ], "tests": [ { "description": "create data key with named AWS KMS provider", "operations": [ { "name": "createDataKey", "object": "clientEncryption0", "arguments": { "kmsProvider": "aws:name1", "opts": { "masterKey": { "key": "arn:aws:kms:us-east-1:579766882180:key/89fcc2c4-08b0-4bd9-9f25-e30687b580d0", "region": "us-east-1" } } }, "expectResult": { "$$type": "binData" } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "databaseName": "keyvault", "command": { "insert": "datakeys", "documents": [ { "_id": { "$$type": "binData" }, "keyMaterial": { "$$type": "binData" }, "creationDate": { "$$type": "date" }, "updateDate": { "$$type": "date" }, "status": { "$$exists": true }, "masterKey": { "provider": "aws:name1", "key": "arn:aws:kms:us-east-1:579766882180:key/89fcc2c4-08b0-4bd9-9f25-e30687b580d0", "region": "us-east-1" } } ], "writeConcern": { "w": "majority" } } } } ] } ] }, { "description": "create datakey with named Azure KMS provider", "operations": [ { "name": "createDataKey", "object": "clientEncryption0", "arguments": { "kmsProvider": "azure:name1", "opts": { "masterKey": { "keyVaultEndpoint": "key-vault-csfle.vault.azure.net", "keyName": "key-name-csfle" } } }, "expectResult": { "$$type": "binData" } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "databaseName": "keyvault", "command": { "insert": "datakeys", "documents": [ { "_id": { "$$type": "binData" }, "keyMaterial": { "$$type": "binData" }, "creationDate": { "$$type": "date" }, "updateDate": { "$$type": "date" }, "status": { "$$exists": true }, "masterKey": { "provider": "azure:name1", "keyVaultEndpoint": "key-vault-csfle.vault.azure.net", "keyName": "key-name-csfle" } } ], "writeConcern": { "w": "majority" } } } } ] } ] }, { "description": "create datakey with named GCP KMS provider", "operations": [ { "name": "createDataKey", "object": "clientEncryption0", "arguments": { "kmsProvider": "gcp:name1", "opts": { "masterKey": { "projectId": "devprod-drivers", "location": "global", "keyRing": "key-ring-csfle", "keyName": "key-name-csfle" } } }, "expectResult": { "$$type": "binData" } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "databaseName": "keyvault", "command": { "insert": "datakeys", "documents": [ { "_id": { "$$type": "binData" }, "keyMaterial": { "$$type": "binData" }, "creationDate": { "$$type": "date" }, "updateDate": { "$$type": "date" }, "status": { "$$exists": true }, "masterKey": { "provider": "gcp:name1", "projectId": "devprod-drivers", "location": "global", "keyRing": "key-ring-csfle", "keyName": "key-name-csfle" } } ], "writeConcern": { "w": "majority" } } } } ] } ] }, { "description": "create datakey with named KMIP KMS provider", "operations": [ { "name": "createDataKey", "object": "clientEncryption0", "arguments": { "kmsProvider": "kmip:name1" }, "expectResult": { "$$type": "binData" } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "databaseName": "keyvault", "command": { "insert": "datakeys", "documents": [ { "_id": { "$$type": "binData" }, "keyMaterial": { "$$type": "binData" }, "creationDate": { "$$type": "date" }, "updateDate": { "$$type": "date" }, "status": { "$$exists": true }, "masterKey": { "provider": "kmip:name1", "keyId": { "$$type": "string" } } } ], "writeConcern": { "w": "majority" } } } } ] } ] }, { "description": "create datakey with named local KMS provider", "operations": [ { "name": "createDataKey", "object": "clientEncryption0", "arguments": { "kmsProvider": "local:name1" }, "expectResult": { "$$type": "binData" } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "databaseName": "keyvault", "command": { "insert": "datakeys", "documents": [ { "_id": { "$$type": "binData" }, "keyMaterial": { "$$type": "binData" }, "creationDate": { "$$type": "date" }, "updateDate": { "$$type": "date" }, "status": { "$$exists": true }, "masterKey": { "provider": "local:name1" } } ], "writeConcern": { "w": "majority" } } } } ] } ] } ] } mongodb-mongo-python-driver-509e9b7/test/client-side-encryption/spec/unified/namedKMS-explicit.json000066400000000000000000000064321462766011000335370ustar00rootroot00000000000000{ "description": "namedKMS-explicit", "schemaVersion": "1.18", "runOnRequirements": [ { "csfle": true } ], "createEntities": [ { "client": { "id": "client0", "observeEvents": [ "commandStartedEvent" ] } }, { "clientEncryption": { "id": "clientEncryption0", "clientEncryptionOpts": { "keyVaultClient": "client0", "keyVaultNamespace": "keyvault.datakeys", "kmsProviders": { "local:name2": { "key": "local+name2+YUJCa1kxNkVyNUR1QURhZ2h2UzR2d2RrZzh0cFBwM3R6NmdWMDFBMUN3YkQ5aXRRMkhGRGdQV09wOGVNYUMxT2k3NjZKelhaQmRCZGJkTXVyZG9uSjFk" } } } } }, { "database": { "id": "database0", "client": "client0", "databaseName": "keyvault" } }, { "collection": { "id": "collection0", "database": "database0", "collectionName": "datakeys" } } ], "initialData": [ { "databaseName": "keyvault", "collectionName": "datakeys", "documents": [ { "_id": { "$binary": { "base64": "local+name2+AAAAAAAAAA==", "subType": "04" } }, "keyAltNames": [ "local:name2" ], "keyMaterial": { "$binary": { "base64": "DX3iUuOlBsx6wBX9UZ3v/qXk1HNeBace2J+h/JwsDdF/vmSXLZ1l1VmZYIcpVFy6ODhdbzLjd4pNgg9wcm4etYig62KNkmtZ0/s1tAL5VsuW/s7/3PYnYGznZTFhLjIVcOH/RNoRj2eQb/sRTyivL85wePEpAU/JzuBj6qO9Y5txQgs1k0J3aNy10R9aQ8kC1NuSSpLAIXwE6DlNDDJXhw==", "subType": "00" } }, "creationDate": { "$date": { "$numberLong": "1552949630483" } }, "updateDate": { "$date": { "$numberLong": "1552949630483" } }, "status": { "$numberInt": "0" }, "masterKey": { "provider": "local:name2" } } ] } ], "tests": [ { "description": "can explicitly encrypt with a named KMS provider", "operations": [ { "name": "encrypt", "object": "clientEncryption0", "arguments": { "value": "foobar", "opts": { "keyAltName": "local:name2", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" } }, "expectResult": { "$binary": { "base64": "AZaHGpfp2pntvgAAAAAAAAAC4yX2LTAuN253GAkEO2ZXp4GpCyM7yoVNJMQQl+6uzxMs03IprLC7DL2vr18x9LwOimjTS9YbMJhrnFkEPuNhbg==", "subType": "06" } } } ] }, { "description": "can explicitly decrypt with a named KMS provider", "operations": [ { "name": "decrypt", "object": "clientEncryption0", "arguments": { "value": { "$binary": { "base64": "AZaHGpfp2pntvgAAAAAAAAAC4yX2LTAuN253GAkEO2ZXp4GpCyM7yoVNJMQQl+6uzxMs03IprLC7DL2vr18x9LwOimjTS9YbMJhrnFkEPuNhbg==", "subType": "06" } } }, "expectResult": "foobar" } ] } ] } namedKMS-rewrapManyDataKey.json000066400000000000000000001243721462766011000352330ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/client-side-encryption/spec/unified{ "description": "namedKMS-rewrapManyDataKey", "schemaVersion": "1.18", "runOnRequirements": [ { "csfle": true } ], "createEntities": [ { "client": { "id": "client0", "observeEvents": [ "commandStartedEvent" ] } }, { "clientEncryption": { "id": "clientEncryption0", "clientEncryptionOpts": { "keyVaultClient": "client0", "keyVaultNamespace": "keyvault.datakeys", "kmsProviders": { "aws:name1": { "accessKeyId": { "$$placeholder": 1 }, "secretAccessKey": { "$$placeholder": 1 } }, "azure:name1": { "tenantId": { "$$placeholder": 1 }, "clientId": { "$$placeholder": 1 }, "clientSecret": { "$$placeholder": 1 } }, "gcp:name1": { "email": { "$$placeholder": 1 }, "privateKey": { "$$placeholder": 1 } }, "kmip:name1": { "endpoint": { "$$placeholder": 1 } }, "local:name1": { "key": { "$$placeholder": 1 } }, "local:name2": { "key": "local+name2+YUJCa1kxNkVyNUR1QURhZ2h2UzR2d2RrZzh0cFBwM3R6NmdWMDFBMUN3YkQ5aXRRMkhGRGdQV09wOGVNYUMxT2k3NjZKelhaQmRCZGJkTXVyZG9uSjFk" }, "aws:name2": { "accessKeyId": { "$$placeholder": 1 }, "secretAccessKey": { "$$placeholder": 1 } } } } } }, { "database": { "id": "database0", "client": "client0", "databaseName": "keyvault" } }, { "collection": { "id": "collection0", "database": "database0", "collectionName": "datakeys" } } ], "initialData": [ { "databaseName": "keyvault", "collectionName": "datakeys", "documents": [ { "_id": { "$binary": { "base64": "YXdzYXdzYXdzYXdzYXdzYQ==", "subType": "04" } }, "keyAltNames": [ "aws:name1_key" ], "keyMaterial": { "$binary": { "base64": "AQICAHhQNmWG2CzOm1dq3kWLM+iDUZhEqnhJwH9wZVpuZ94A8gFXJqbF0Fy872MD7xl56D/2AAAAwjCBvwYJKoZIhvcNAQcGoIGxMIGuAgEAMIGoBgkqhkiG9w0BBwEwHgYJYIZIAWUDBAEuMBEEDO7HPisPUlGzaio9vgIBEIB7/Qow46PMh/8JbEUbdXgTGhLfXPE+KIVW7T8s6YEMlGiRvMu7TV0QCIUJlSHPKZxzlJ2iwuz5yXeOag+EdY+eIQ0RKrsJ3b8UTisZYzGjfzZnxUKLzLoeXremtRCm3x47wCuHKd1dhh6FBbYt5TL2tDaj+vL2GBrKat2L", "subType": "00" } }, "creationDate": { "$date": { "$numberLong": "1641024000000" } }, "updateDate": { "$date": { "$numberLong": "1641024000000" } }, "status": 1, "masterKey": { "provider": "aws:name1", "key": "arn:aws:kms:us-east-1:579766882180:key/89fcc2c4-08b0-4bd9-9f25-e30687b580d0", "region": "us-east-1" } }, { "_id": { "$binary": { "base64": "YXp1cmVhenVyZWF6dXJlYQ==", "subType": "04" } }, "keyAltNames": [ "azure:name1_key" ], "keyMaterial": { "$binary": { "base64": "pr01l7qDygUkFE/0peFwpnNlv3iIy8zrQK38Q9i12UCN2jwZHDmfyx8wokiIKMb9kAleeY+vnt3Cf1MKu9kcDmI+KxbNDd+V3ytAAGzOVLDJr77CiWjF9f8ntkXRHrAY9WwnVDANYkDwXlyU0Y2GQFTiW65jiQhUtYLYH63Tk48SsJuQvnWw1Q+PzY8ga+QeVec8wbcThwtm+r2IHsCFnc72Gv73qq7weISw+O4mN08z3wOp5FOS2ZM3MK7tBGmPdBcktW7F8ODGsOQ1FU53OrWUnyX2aTi2ftFFFMWVHqQo7EYuBZHru8RRODNKMyQk0BFfKovAeTAVRv9WH9QU7g==", "subType": "00" } }, "creationDate": { "$date": { "$numberLong": "1641024000000" } }, "updateDate": { "$date": { "$numberLong": "1641024000000" } }, "status": 1, "masterKey": { "provider": "azure:name1", "keyVaultEndpoint": "key-vault-csfle.vault.azure.net", "keyName": "key-name-csfle" } }, { "_id": { "$binary": { "base64": "Z2NwZ2NwZ2NwZ2NwZ2NwZw==", "subType": "04" } }, "keyAltNames": [ "gcp:name1_key" ], "keyMaterial": { "$binary": { "base64": "CiQAIgLj0USbQtof/pYRLQO96yg/JEtZbD1UxKueaC37yzT5tTkSiQEAhClWB5ZCSgzHgxv8raWjNB4r7e8ePGdsmSuYTYmLC5oHHS/BdQisConzNKFaobEQZHamTCjyhy5NotKF8MWoo+dyfQApwI29+vAGyrUIQCXzKwRnNdNQ+lb3vJtS5bqvLTvSxKHpVca2kqyC9nhonV+u4qru5Q2bAqUgVFc8fL4pBuvlowZFTQ==", "subType": "00" } }, "creationDate": { "$date": { "$numberLong": "1641024000000" } }, "updateDate": { "$date": { "$numberLong": "1641024000000" } }, "status": 1, "masterKey": { "provider": "gcp:name1", "projectId": "devprod-drivers", "location": "global", "keyRing": "key-ring-csfle", "keyName": "key-name-csfle" } }, { "_id": { "$binary": { "base64": "a21pcGttaXBrbWlwa21pcA==", "subType": "04" } }, "keyAltNames": [ "kmip:name1_key" ], "keyMaterial": { "$binary": { "base64": "CklVctHzke4mcytd0TxGqvepkdkQN8NUF4+jV7aZQITAKdz6WjdDpq3lMt9nSzWGG2vAEfvRb3mFEVjV57qqGqxjq2751gmiMRHXz0btStbIK3mQ5xbY9kdye4tsixlCryEwQONr96gwlwKKI9Nubl9/8+uRF6tgYjje7Q7OjauEf1SrJwKcoQ3WwnjZmEqAug0kImCpJ/irhdqPzivRiA==", "subType": "00" } }, "creationDate": { "$date": { "$numberLong": "1641024000000" } }, "updateDate": { "$date": { "$numberLong": "1641024000000" } }, "status": 1, "masterKey": { "provider": "kmip:name1", "keyId": "1" } }, { "_id": { "$binary": { "base64": "bG9jYWxrZXlsb2NhbGtleQ==", "subType": "04" } }, "keyAltNames": [ "local:name1_key" ], "keyMaterial": { "$binary": { "base64": "ABKBldDEoDW323yejOnIRk6YQmlD9d3eQthd16scKL75nz2LjNL9fgPDZWrFFOlqlhMCFaSrNJfGrFUjYk5JFDO7soG5Syb50k1niJoKg4ilsj0L4mpimFUtTpOr2nzZOeQtvAksEXc7gsFgq8gV7t/U3lsaXPY7I0t42DfSE8EGlPdxRjFdHnxh+OR8h7U9b8Qs5K5UuhgyeyxaBZ1Hgw==", "subType": "00" } }, "creationDate": { "$date": { "$numberLong": "1641024000000" } }, "updateDate": { "$date": { "$numberLong": "1641024000000" } }, "status": 1, "masterKey": { "provider": "local:name1" } } ] } ], "tests": [ { "description": "rewrap to aws:name1", "operations": [ { "name": "rewrapManyDataKey", "object": "clientEncryption0", "arguments": { "filter": { "keyAltNames": { "$ne": "aws:name1_key" } }, "opts": { "provider": "aws:name1", "masterKey": { "key": "arn:aws:kms:us-east-1:579766882180:key/061334ae-07a8-4ceb-a813-8135540e837d", "region": "us-east-1" } } }, "expectResult": { "bulkWriteResult": { "insertedCount": 0, "matchedCount": 4, "modifiedCount": 4, "deletedCount": 0, "upsertedCount": 0, "upsertedIds": {}, "insertedIds": { "$$unsetOrMatches": {} } } } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "databaseName": "keyvault", "command": { "find": "datakeys", "filter": { "keyAltNames": { "$ne": "aws:name1_key" } }, "readConcern": { "level": "majority" } } } }, { "commandStartedEvent": { "databaseName": "keyvault", "command": { "update": "datakeys", "ordered": true, "updates": [ { "q": { "_id": { "$$type": "binData" } }, "u": { "$set": { "masterKey": { "provider": "aws:name1", "key": "arn:aws:kms:us-east-1:579766882180:key/061334ae-07a8-4ceb-a813-8135540e837d", "region": "us-east-1" }, "keyMaterial": { "$$type": "binData" } }, "$currentDate": { "updateDate": true } }, "multi": { "$$unsetOrMatches": false }, "upsert": { "$$unsetOrMatches": false } }, { "q": { "_id": { "$$type": "binData" } }, "u": { "$set": { "masterKey": { "provider": "aws:name1", "key": "arn:aws:kms:us-east-1:579766882180:key/061334ae-07a8-4ceb-a813-8135540e837d", "region": "us-east-1" }, "keyMaterial": { "$$type": "binData" } }, "$currentDate": { "updateDate": true } }, "multi": { "$$unsetOrMatches": false }, "upsert": { "$$unsetOrMatches": false } }, { "q": { "_id": { "$$type": "binData" } }, "u": { "$set": { "masterKey": { "provider": "aws:name1", "key": "arn:aws:kms:us-east-1:579766882180:key/061334ae-07a8-4ceb-a813-8135540e837d", "region": "us-east-1" }, "keyMaterial": { "$$type": "binData" } }, "$currentDate": { "updateDate": true } }, "multi": { "$$unsetOrMatches": false }, "upsert": { "$$unsetOrMatches": false } }, { "q": { "_id": { "$$type": "binData" } }, "u": { "$set": { "masterKey": { "provider": "aws:name1", "key": "arn:aws:kms:us-east-1:579766882180:key/061334ae-07a8-4ceb-a813-8135540e837d", "region": "us-east-1" }, "keyMaterial": { "$$type": "binData" } }, "$currentDate": { "updateDate": true } }, "multi": { "$$unsetOrMatches": false }, "upsert": { "$$unsetOrMatches": false } } ], "writeConcern": { "w": "majority" } } } } ] } ] }, { "description": "rewrap to azure:name1", "operations": [ { "name": "rewrapManyDataKey", "object": "clientEncryption0", "arguments": { "filter": { "keyAltNames": { "$ne": "azure:name1_key" } }, "opts": { "provider": "azure:name1", "masterKey": { "keyVaultEndpoint": "key-vault-csfle.vault.azure.net", "keyName": "key-name-csfle" } } }, "expectResult": { "bulkWriteResult": { "insertedCount": 0, "matchedCount": 4, "modifiedCount": 4, "deletedCount": 0, "upsertedCount": 0, "upsertedIds": {}, "insertedIds": { "$$unsetOrMatches": {} } } } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "databaseName": "keyvault", "command": { "find": "datakeys", "filter": { "keyAltNames": { "$ne": "azure:name1_key" } }, "readConcern": { "level": "majority" } } } }, { "commandStartedEvent": { "databaseName": "keyvault", "command": { "update": "datakeys", "ordered": true, "updates": [ { "q": { "_id": { "$$type": "binData" } }, "u": { "$set": { "masterKey": { "provider": "azure:name1", "keyVaultEndpoint": "key-vault-csfle.vault.azure.net", "keyName": "key-name-csfle" }, "keyMaterial": { "$$type": "binData" } }, "$currentDate": { "updateDate": true } }, "multi": { "$$unsetOrMatches": false }, "upsert": { "$$unsetOrMatches": false } }, { "q": { "_id": { "$$type": "binData" } }, "u": { "$set": { "masterKey": { "provider": "azure:name1", "keyVaultEndpoint": "key-vault-csfle.vault.azure.net", "keyName": "key-name-csfle" }, "keyMaterial": { "$$type": "binData" } }, "$currentDate": { "updateDate": true } }, "multi": { "$$unsetOrMatches": false }, "upsert": { "$$unsetOrMatches": false } }, { "q": { "_id": { "$$type": "binData" } }, "u": { "$set": { "masterKey": { "provider": "azure:name1", "keyVaultEndpoint": "key-vault-csfle.vault.azure.net", "keyName": "key-name-csfle" }, "keyMaterial": { "$$type": "binData" } }, "$currentDate": { "updateDate": true } }, "multi": { "$$unsetOrMatches": false }, "upsert": { "$$unsetOrMatches": false } }, { "q": { "_id": { "$$type": "binData" } }, "u": { "$set": { "masterKey": { "provider": "azure:name1", "keyVaultEndpoint": "key-vault-csfle.vault.azure.net", "keyName": "key-name-csfle" }, "keyMaterial": { "$$type": "binData" } }, "$currentDate": { "updateDate": true } }, "multi": { "$$unsetOrMatches": false }, "upsert": { "$$unsetOrMatches": false } } ], "writeConcern": { "w": "majority" } } } } ] } ] }, { "description": "rewrap to gcp:name1", "operations": [ { "name": "rewrapManyDataKey", "object": "clientEncryption0", "arguments": { "filter": { "keyAltNames": { "$ne": "gcp:name1_key" } }, "opts": { "provider": "gcp:name1", "masterKey": { "projectId": "devprod-drivers", "location": "global", "keyRing": "key-ring-csfle", "keyName": "key-name-csfle" } } }, "expectResult": { "bulkWriteResult": { "insertedCount": 0, "matchedCount": 4, "modifiedCount": 4, "deletedCount": 0, "upsertedCount": 0, "upsertedIds": {}, "insertedIds": { "$$unsetOrMatches": {} } } } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "databaseName": "keyvault", "command": { "find": "datakeys", "filter": { "keyAltNames": { "$ne": "gcp:name1_key" } }, "readConcern": { "level": "majority" } } } }, { "commandStartedEvent": { "databaseName": "keyvault", "command": { "update": "datakeys", "ordered": true, "updates": [ { "q": { "_id": { "$$type": "binData" } }, "u": { "$set": { "masterKey": { "provider": "gcp:name1", "projectId": "devprod-drivers", "location": "global", "keyRing": "key-ring-csfle", "keyName": "key-name-csfle" }, "keyMaterial": { "$$type": "binData" } }, "$currentDate": { "updateDate": true } }, "multi": { "$$unsetOrMatches": false }, "upsert": { "$$unsetOrMatches": false } }, { "q": { "_id": { "$$type": "binData" } }, "u": { "$set": { "masterKey": { "provider": "gcp:name1", "projectId": "devprod-drivers", "location": "global", "keyRing": "key-ring-csfle", "keyName": "key-name-csfle" }, "keyMaterial": { "$$type": "binData" } }, "$currentDate": { "updateDate": true } }, "multi": { "$$unsetOrMatches": false }, "upsert": { "$$unsetOrMatches": false } }, { "q": { "_id": { "$$type": "binData" } }, "u": { "$set": { "masterKey": { "provider": "gcp:name1", "projectId": "devprod-drivers", "location": "global", "keyRing": "key-ring-csfle", "keyName": "key-name-csfle" }, "keyMaterial": { "$$type": "binData" } }, "$currentDate": { "updateDate": true } }, "multi": { "$$unsetOrMatches": false }, "upsert": { "$$unsetOrMatches": false } }, { "q": { "_id": { "$$type": "binData" } }, "u": { "$set": { "masterKey": { "provider": "gcp:name1", "projectId": "devprod-drivers", "location": "global", "keyRing": "key-ring-csfle", "keyName": "key-name-csfle" }, "keyMaterial": { "$$type": "binData" } }, "$currentDate": { "updateDate": true } }, "multi": { "$$unsetOrMatches": false }, "upsert": { "$$unsetOrMatches": false } } ], "writeConcern": { "w": "majority" } } } } ] } ] }, { "description": "rewrap to kmip:name1", "operations": [ { "name": "rewrapManyDataKey", "object": "clientEncryption0", "arguments": { "filter": { "keyAltNames": { "$ne": "kmip:name1_key" } }, "opts": { "provider": "kmip:name1" } }, "expectResult": { "bulkWriteResult": { "insertedCount": 0, "matchedCount": 4, "modifiedCount": 4, "deletedCount": 0, "upsertedCount": 0, "upsertedIds": {}, "insertedIds": { "$$unsetOrMatches": {} } } } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "databaseName": "keyvault", "command": { "find": "datakeys", "filter": { "keyAltNames": { "$ne": "kmip:name1_key" } }, "readConcern": { "level": "majority" } } } }, { "commandStartedEvent": { "databaseName": "keyvault", "command": { "update": "datakeys", "ordered": true, "updates": [ { "q": { "_id": { "$$type": "binData" } }, "u": { "$set": { "masterKey": { "provider": "kmip:name1", "keyId": { "$$type": "string" } }, "keyMaterial": { "$$type": "binData" } }, "$currentDate": { "updateDate": true } }, "multi": { "$$unsetOrMatches": false }, "upsert": { "$$unsetOrMatches": false } }, { "q": { "_id": { "$$type": "binData" } }, "u": { "$set": { "masterKey": { "provider": "kmip:name1", "keyId": { "$$type": "string" } }, "keyMaterial": { "$$type": "binData" } }, "$currentDate": { "updateDate": true } }, "multi": { "$$unsetOrMatches": false }, "upsert": { "$$unsetOrMatches": false } }, { "q": { "_id": { "$$type": "binData" } }, "u": { "$set": { "masterKey": { "provider": "kmip:name1", "keyId": { "$$type": "string" } }, "keyMaterial": { "$$type": "binData" } }, "$currentDate": { "updateDate": true } }, "multi": { "$$unsetOrMatches": false }, "upsert": { "$$unsetOrMatches": false } }, { "q": { "_id": { "$$type": "binData" } }, "u": { "$set": { "masterKey": { "provider": "kmip:name1", "keyId": { "$$type": "string" } }, "keyMaterial": { "$$type": "binData" } }, "$currentDate": { "updateDate": true } }, "multi": { "$$unsetOrMatches": false }, "upsert": { "$$unsetOrMatches": false } } ], "writeConcern": { "w": "majority" } } } } ] } ] }, { "description": "rewrap to local:name1", "operations": [ { "name": "rewrapManyDataKey", "object": "clientEncryption0", "arguments": { "filter": { "keyAltNames": { "$ne": "local:name1_key" } }, "opts": { "provider": "local:name1" } }, "expectResult": { "bulkWriteResult": { "insertedCount": 0, "matchedCount": 4, "modifiedCount": 4, "deletedCount": 0, "upsertedCount": 0, "upsertedIds": {}, "insertedIds": { "$$unsetOrMatches": {} } } } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "databaseName": "keyvault", "command": { "find": "datakeys", "filter": { "keyAltNames": { "$ne": "local:name1_key" } }, "readConcern": { "level": "majority" } } } }, { "commandStartedEvent": { "databaseName": "keyvault", "command": { "update": "datakeys", "ordered": true, "updates": [ { "q": { "_id": { "$$type": "binData" } }, "u": { "$set": { "masterKey": { "provider": "local:name1" }, "keyMaterial": { "$$type": "binData" } }, "$currentDate": { "updateDate": true } }, "multi": { "$$unsetOrMatches": false }, "upsert": { "$$unsetOrMatches": false } }, { "q": { "_id": { "$$type": "binData" } }, "u": { "$set": { "masterKey": { "provider": "local:name1" }, "keyMaterial": { "$$type": "binData" } }, "$currentDate": { "updateDate": true } }, "multi": { "$$unsetOrMatches": false }, "upsert": { "$$unsetOrMatches": false } }, { "q": { "_id": { "$$type": "binData" } }, "u": { "$set": { "masterKey": { "provider": "local:name1" }, "keyMaterial": { "$$type": "binData" } }, "$currentDate": { "updateDate": true } }, "multi": { "$$unsetOrMatches": false }, "upsert": { "$$unsetOrMatches": false } }, { "q": { "_id": { "$$type": "binData" } }, "u": { "$set": { "masterKey": { "provider": "local:name1" }, "keyMaterial": { "$$type": "binData" } }, "$currentDate": { "updateDate": true } }, "multi": { "$$unsetOrMatches": false }, "upsert": { "$$unsetOrMatches": false } } ], "writeConcern": { "w": "majority" } } } } ] } ] }, { "description": "rewrap from local:name1 to local:name2", "operations": [ { "name": "rewrapManyDataKey", "object": "clientEncryption0", "arguments": { "filter": { "keyAltNames": { "$eq": "local:name1_key" } }, "opts": { "provider": "local:name2" } }, "expectResult": { "bulkWriteResult": { "insertedCount": 0, "matchedCount": 1, "modifiedCount": 1, "deletedCount": 0, "upsertedCount": 0, "upsertedIds": {}, "insertedIds": { "$$unsetOrMatches": {} } } } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "databaseName": "keyvault", "command": { "find": "datakeys", "filter": { "keyAltNames": { "$eq": "local:name1_key" } }, "readConcern": { "level": "majority" } } } }, { "commandStartedEvent": { "databaseName": "keyvault", "command": { "update": "datakeys", "ordered": true, "updates": [ { "q": { "_id": { "$$type": "binData" } }, "u": { "$set": { "masterKey": { "provider": "local:name2" }, "keyMaterial": { "$$type": "binData" } }, "$currentDate": { "updateDate": true } }, "multi": { "$$unsetOrMatches": false }, "upsert": { "$$unsetOrMatches": false } } ], "writeConcern": { "w": "majority" } } } } ] } ] }, { "description": "rewrap from aws:name1 to aws:name2", "operations": [ { "name": "rewrapManyDataKey", "object": "clientEncryption0", "arguments": { "filter": { "keyAltNames": { "$eq": "aws:name1_key" } }, "opts": { "provider": "aws:name2", "masterKey": { "key": "arn:aws:kms:us-east-1:857654397073:key/0f8468f0-f135-4226-aa0b-bd05c4c30df5", "region": "us-east-1" } } }, "expectResult": { "bulkWriteResult": { "insertedCount": 0, "matchedCount": 1, "modifiedCount": 1, "deletedCount": 0, "upsertedCount": 0, "upsertedIds": {}, "insertedIds": { "$$unsetOrMatches": {} } } } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "databaseName": "keyvault", "command": { "find": "datakeys", "filter": { "keyAltNames": { "$eq": "aws:name1_key" } }, "readConcern": { "level": "majority" } } } }, { "commandStartedEvent": { "databaseName": "keyvault", "command": { "update": "datakeys", "ordered": true, "updates": [ { "q": { "_id": { "$$type": "binData" } }, "u": { "$set": { "masterKey": { "provider": "aws:name2", "key": "arn:aws:kms:us-east-1:857654397073:key/0f8468f0-f135-4226-aa0b-bd05c4c30df5", "region": "us-east-1" }, "keyMaterial": { "$$type": "binData" } }, "$currentDate": { "updateDate": true } }, "multi": { "$$unsetOrMatches": false }, "upsert": { "$$unsetOrMatches": false } } ], "writeConcern": { "w": "majority" } } } } ] } ] } ] } mongodb-mongo-python-driver-509e9b7/test/client-side-encryption/spec/unified/removeKeyAltName.json000066400000000000000000000462261462766011000334760ustar00rootroot00000000000000{ "description": "removeKeyAltName", "schemaVersion": "1.8", "runOnRequirements": [ { "csfle": true } ], "createEntities": [ { "client": { "id": "client0", "observeEvents": [ "commandStartedEvent" ] } }, { "clientEncryption": { "id": "clientEncryption0", "clientEncryptionOpts": { "keyVaultClient": "client0", "keyVaultNamespace": "keyvault.datakeys", "kmsProviders": { "local": { "key": { "$$placeholder": 1 } } } } } }, { "database": { "id": "database0", "client": "client0", "databaseName": "keyvault" } }, { "collection": { "id": "collection0", "database": "database0", "collectionName": "datakeys" } } ], "initialData": [ { "databaseName": "keyvault", "collectionName": "datakeys", "documents": [ { "_id": { "$binary": { "base64": "bG9jYWxrZXlsb2NhbGtleQ==", "subType": "04" } }, "keyAltNames": [ "alternate_name", "local_key" ], "keyMaterial": { "$binary": { "base64": "ABKBldDEoDW323yejOnIRk6YQmlD9d3eQthd16scKL75nz2LjNL9fgPDZWrFFOlqlhMCFaSrNJfGrFUjYk5JFDO7soG5Syb50k1niJoKg4ilsj0L4mpimFUtTpOr2nzZOeQtvAksEXc7gsFgq8gV7t/U3lsaXPY7I0t42DfSE8EGlPdxRjFdHnxh+OR8h7U9b8Qs5K5UuhgyeyxaBZ1Hgw==", "subType": "00" } }, "creationDate": { "$date": { "$numberLong": "1641024000000" } }, "updateDate": { "$date": { "$numberLong": "1641024000000" } }, "status": 1, "masterKey": { "provider": "local" } } ] } ], "tests": [ { "description": "remove keyAltName from non-existent data key", "operations": [ { "name": "removeKeyAltName", "object": "clientEncryption0", "arguments": { "id": { "$binary": { "base64": "AAAjYWxrZXlsb2NhbGtleQ==", "subType": "04" } }, "keyAltName": "does_not_exist" }, "expectResult": { "$$unsetOrMatches": null } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "databaseName": "keyvault", "command": { "findAndModify": "datakeys", "query": { "_id": { "$binary": { "base64": "AAAjYWxrZXlsb2NhbGtleQ==", "subType": "04" } } }, "update": [ { "$set": { "keyAltNames": { "$cond": [ { "$eq": [ "$keyAltNames", [ "does_not_exist" ] ] }, "$$REMOVE", { "$filter": { "input": "$keyAltNames", "cond": { "$ne": [ "$$this", "does_not_exist" ] } } } ] } } } ], "writeConcern": { "w": "majority" } } } } ] } ], "outcome": [ { "collectionName": "datakeys", "databaseName": "keyvault", "documents": [ { "_id": { "$binary": { "base64": "bG9jYWxrZXlsb2NhbGtleQ==", "subType": "04" } }, "keyAltNames": [ "alternate_name", "local_key" ], "keyMaterial": { "$binary": { "base64": "ABKBldDEoDW323yejOnIRk6YQmlD9d3eQthd16scKL75nz2LjNL9fgPDZWrFFOlqlhMCFaSrNJfGrFUjYk5JFDO7soG5Syb50k1niJoKg4ilsj0L4mpimFUtTpOr2nzZOeQtvAksEXc7gsFgq8gV7t/U3lsaXPY7I0t42DfSE8EGlPdxRjFdHnxh+OR8h7U9b8Qs5K5UuhgyeyxaBZ1Hgw==", "subType": "00" } }, "creationDate": { "$date": { "$numberLong": "1641024000000" } }, "updateDate": { "$date": { "$numberLong": "1641024000000" } }, "status": 1, "masterKey": { "provider": "local" } } ] } ] }, { "description": "remove non-existent keyAltName from existing data key", "operations": [ { "name": "removeKeyAltName", "object": "clientEncryption0", "arguments": { "id": { "$binary": { "base64": "bG9jYWxrZXlsb2NhbGtleQ==", "subType": "04" } }, "keyAltName": "does_not_exist" }, "expectResult": { "_id": { "$binary": { "base64": "bG9jYWxrZXlsb2NhbGtleQ==", "subType": "04" } }, "keyAltNames": [ "alternate_name", "local_key" ], "keyMaterial": { "$binary": { "base64": "ABKBldDEoDW323yejOnIRk6YQmlD9d3eQthd16scKL75nz2LjNL9fgPDZWrFFOlqlhMCFaSrNJfGrFUjYk5JFDO7soG5Syb50k1niJoKg4ilsj0L4mpimFUtTpOr2nzZOeQtvAksEXc7gsFgq8gV7t/U3lsaXPY7I0t42DfSE8EGlPdxRjFdHnxh+OR8h7U9b8Qs5K5UuhgyeyxaBZ1Hgw==", "subType": "00" } }, "creationDate": { "$date": { "$numberLong": "1641024000000" } }, "updateDate": { "$date": { "$numberLong": "1641024000000" } }, "status": 1, "masterKey": { "provider": "local" } } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "databaseName": "keyvault", "command": { "findAndModify": "datakeys", "query": { "_id": { "$binary": { "base64": "bG9jYWxrZXlsb2NhbGtleQ==", "subType": "04" } } }, "update": [ { "$set": { "keyAltNames": { "$cond": [ { "$eq": [ "$keyAltNames", [ "does_not_exist" ] ] }, "$$REMOVE", { "$filter": { "input": "$keyAltNames", "cond": { "$ne": [ "$$this", "does_not_exist" ] } } } ] } } } ], "writeConcern": { "w": "majority" } } } } ] } ], "outcome": [ { "collectionName": "datakeys", "databaseName": "keyvault", "documents": [ { "_id": { "$binary": { "base64": "bG9jYWxrZXlsb2NhbGtleQ==", "subType": "04" } }, "keyAltNames": [ "alternate_name", "local_key" ], "keyMaterial": { "$binary": { "base64": "ABKBldDEoDW323yejOnIRk6YQmlD9d3eQthd16scKL75nz2LjNL9fgPDZWrFFOlqlhMCFaSrNJfGrFUjYk5JFDO7soG5Syb50k1niJoKg4ilsj0L4mpimFUtTpOr2nzZOeQtvAksEXc7gsFgq8gV7t/U3lsaXPY7I0t42DfSE8EGlPdxRjFdHnxh+OR8h7U9b8Qs5K5UuhgyeyxaBZ1Hgw==", "subType": "00" } }, "creationDate": { "$date": { "$numberLong": "1641024000000" } }, "updateDate": { "$date": { "$numberLong": "1641024000000" } }, "status": 1, "masterKey": { "provider": "local" } } ] } ] }, { "description": "remove an existing keyAltName from an existing data key", "operations": [ { "name": "removeKeyAltName", "object": "clientEncryption0", "arguments": { "id": { "$binary": { "base64": "bG9jYWxrZXlsb2NhbGtleQ==", "subType": "04" } }, "keyAltName": "alternate_name" }, "expectResult": { "_id": { "$binary": { "base64": "bG9jYWxrZXlsb2NhbGtleQ==", "subType": "04" } }, "keyAltNames": [ "alternate_name", "local_key" ], "keyMaterial": { "$binary": { "base64": "ABKBldDEoDW323yejOnIRk6YQmlD9d3eQthd16scKL75nz2LjNL9fgPDZWrFFOlqlhMCFaSrNJfGrFUjYk5JFDO7soG5Syb50k1niJoKg4ilsj0L4mpimFUtTpOr2nzZOeQtvAksEXc7gsFgq8gV7t/U3lsaXPY7I0t42DfSE8EGlPdxRjFdHnxh+OR8h7U9b8Qs5K5UuhgyeyxaBZ1Hgw==", "subType": "00" } }, "creationDate": { "$date": { "$numberLong": "1641024000000" } }, "updateDate": { "$date": { "$numberLong": "1641024000000" } }, "status": 1, "masterKey": { "provider": "local" } } }, { "name": "find", "object": "collection0", "arguments": { "filter": {}, "projection": { "_id": 0, "keyAltNames": 1 } }, "expectResult": [ { "keyAltNames": [ "local_key" ] } ] } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "databaseName": "keyvault", "command": { "findAndModify": "datakeys", "query": { "_id": { "$binary": { "base64": "bG9jYWxrZXlsb2NhbGtleQ==", "subType": "04" } } }, "update": [ { "$set": { "keyAltNames": { "$cond": [ { "$eq": [ "$keyAltNames", [ "alternate_name" ] ] }, "$$REMOVE", { "$filter": { "input": "$keyAltNames", "cond": { "$ne": [ "$$this", "alternate_name" ] } } } ] } } } ], "writeConcern": { "w": "majority" } } } }, { "commandStartedEvent": { "commandName": "find" } } ] } ] }, { "description": "remove the last keyAltName from an existing data key", "operations": [ { "name": "removeKeyAltName", "object": "clientEncryption0", "arguments": { "id": { "$binary": { "base64": "bG9jYWxrZXlsb2NhbGtleQ==", "subType": "04" } }, "keyAltName": "alternate_name" }, "expectResult": { "_id": { "$binary": { "base64": "bG9jYWxrZXlsb2NhbGtleQ==", "subType": "04" } }, "keyAltNames": [ "alternate_name", "local_key" ], "keyMaterial": { "$binary": { "base64": "ABKBldDEoDW323yejOnIRk6YQmlD9d3eQthd16scKL75nz2LjNL9fgPDZWrFFOlqlhMCFaSrNJfGrFUjYk5JFDO7soG5Syb50k1niJoKg4ilsj0L4mpimFUtTpOr2nzZOeQtvAksEXc7gsFgq8gV7t/U3lsaXPY7I0t42DfSE8EGlPdxRjFdHnxh+OR8h7U9b8Qs5K5UuhgyeyxaBZ1Hgw==", "subType": "00" } }, "creationDate": { "$date": { "$numberLong": "1641024000000" } }, "updateDate": { "$date": { "$numberLong": "1641024000000" } }, "status": 1, "masterKey": { "provider": "local" } } }, { "name": "removeKeyAltName", "object": "clientEncryption0", "arguments": { "id": { "$binary": { "base64": "bG9jYWxrZXlsb2NhbGtleQ==", "subType": "04" } }, "keyAltName": "local_key" }, "expectResult": { "_id": { "$binary": { "base64": "bG9jYWxrZXlsb2NhbGtleQ==", "subType": "04" } }, "keyAltNames": [ "local_key" ], "keyMaterial": { "$$type": "binData" }, "creationDate": { "$$type": "date" }, "updateDate": { "$$type": "date" }, "status": 1, "masterKey": { "provider": "local" } } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "databaseName": "keyvault", "command": { "findAndModify": "datakeys", "query": { "_id": { "$binary": { "base64": "bG9jYWxrZXlsb2NhbGtleQ==", "subType": "04" } } }, "update": [ { "$set": { "keyAltNames": { "$cond": [ { "$eq": [ "$keyAltNames", [ "alternate_name" ] ] }, "$$REMOVE", { "$filter": { "input": "$keyAltNames", "cond": { "$ne": [ "$$this", "alternate_name" ] } } } ] } } } ], "writeConcern": { "w": "majority" } } } }, { "commandStartedEvent": { "databaseName": "keyvault", "command": { "findAndModify": "datakeys", "query": { "_id": { "$binary": { "base64": "bG9jYWxrZXlsb2NhbGtleQ==", "subType": "04" } } }, "update": [ { "$set": { "keyAltNames": { "$cond": [ { "$eq": [ "$keyAltNames", [ "local_key" ] ] }, "$$REMOVE", { "$filter": { "input": "$keyAltNames", "cond": { "$ne": [ "$$this", "local_key" ] } } } ] } } } ] } } } ] } ] } ] } rewrapManyDataKey-decrypt_failure.json000066400000000000000000000076531462766011000367570ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/client-side-encryption/spec/unified{ "description": "rewrapManyDataKey-decrypt_failure", "schemaVersion": "1.8", "runOnRequirements": [ { "csfle": true } ], "createEntities": [ { "client": { "id": "client0", "observeEvents": [ "commandStartedEvent" ] } }, { "clientEncryption": { "id": "clientEncryption0", "clientEncryptionOpts": { "keyVaultClient": "client0", "keyVaultNamespace": "keyvault.datakeys", "kmsProviders": { "aws": { "accessKeyId": { "$$placeholder": 1 }, "secretAccessKey": { "$$placeholder": 1 } }, "azure": { "tenantId": { "$$placeholder": 1 }, "clientId": { "$$placeholder": 1 }, "clientSecret": { "$$placeholder": 1 } }, "gcp": { "email": { "$$placeholder": 1 }, "privateKey": { "$$placeholder": 1 } }, "kmip": { "endpoint": { "$$placeholder": 1 } }, "local": { "key": { "$$placeholder": 1 } } } } } }, { "database": { "id": "database0", "client": "client0", "databaseName": "keyvault" } }, { "collection": { "id": "collection0", "database": "database0", "collectionName": "datakeys" } } ], "initialData": [ { "databaseName": "keyvault", "collectionName": "datakeys", "documents": [ { "_id": { "$binary": { "base64": "YXdzYXdzYXdzYXdzYXdzYQ==", "subType": "04" } }, "keyAltNames": [ "aws_key" ], "keyMaterial": { "$binary": { "base64": "AQICAHhQNmWG2CzOm1dq3kWLM+iDUZhEqnhJwH9wZVpuZ94A8gFXJqbF0Fy872MD7xl56D/2AAAAwjCBvwYJKoZIhvcNAQcGoIGxMIGuAgEAMIGoBgkqhkiG9w0BBwEwHgYJYIZIAWUDBAEuMBEEDO7HPisPUlGzaio9vgIBEIB7/Qow46PMh/8JbEUbdXgTGhLfXPE+KIVW7T8s6YEMlGiRvMu7TV0QCIUJlSHPKZxzlJ2iwuz5yXeOag+EdY+eIQ0RKrsJ3b8UTisZYzGjfzZnxUKLzLoeXremtRCm3x47wCuHKd1dhh6FBbYt5TL2tDaj+vL2GBrKat2L", "subType": "00" } }, "creationDate": { "$date": { "$numberLong": "1641024000000" } }, "updateDate": { "$date": { "$numberLong": "1641024000000" } }, "status": 1, "masterKey": { "provider": "aws", "key": "arn:aws:kms:us-east-2:579766882180:key/89fcc2c4-08b0-4bd9-9f25-e30687b580d0", "region": "us-east-2" } } ] } ], "tests": [ { "description": "rewrap data key that fails during decryption due to invalid masterKey", "operations": [ { "name": "rewrapManyDataKey", "object": "clientEncryption0", "arguments": { "filter": {}, "opts": { "provider": "local" } }, "expectError": { "isClientError": true } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "commandName": "find", "databaseName": "keyvault", "command": { "find": "datakeys", "filter": {}, "readConcern": { "level": "majority" } } } } ] } ] } ] } rewrapManyDataKey-encrypt_failure.json000066400000000000000000000140271462766011000367620ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/client-side-encryption/spec/unified{ "description": "rewrapManyDataKey-encrypt_failure", "schemaVersion": "1.8", "runOnRequirements": [ { "csfle": true } ], "createEntities": [ { "client": { "id": "client0", "observeEvents": [ "commandStartedEvent" ] } }, { "clientEncryption": { "id": "clientEncryption0", "clientEncryptionOpts": { "keyVaultClient": "client0", "keyVaultNamespace": "keyvault.datakeys", "kmsProviders": { "aws": { "accessKeyId": { "$$placeholder": 1 }, "secretAccessKey": { "$$placeholder": 1 } }, "azure": { "tenantId": { "$$placeholder": 1 }, "clientId": { "$$placeholder": 1 }, "clientSecret": { "$$placeholder": 1 } }, "gcp": { "email": { "$$placeholder": 1 }, "privateKey": { "$$placeholder": 1 } }, "kmip": { "endpoint": { "$$placeholder": 1 } }, "local": { "key": { "$$placeholder": 1 } } } } } }, { "database": { "id": "database0", "client": "client0", "databaseName": "keyvault" } }, { "collection": { "id": "collection0", "database": "database0", "collectionName": "datakeys" } } ], "initialData": [ { "databaseName": "keyvault", "collectionName": "datakeys", "documents": [ { "_id": { "$binary": { "base64": "bG9jYWxrZXlsb2NhbGtleQ==", "subType": "04" } }, "keyAltNames": [ "local_key" ], "keyMaterial": { "$binary": { "base64": "ABKBldDEoDW323yejOnIRk6YQmlD9d3eQthd16scKL75nz2LjNL9fgPDZWrFFOlqlhMCFaSrNJfGrFUjYk5JFDO7soG5Syb50k1niJoKg4ilsj0L4mpimFUtTpOr2nzZOeQtvAksEXc7gsFgq8gV7t/U3lsaXPY7I0t42DfSE8EGlPdxRjFdHnxh+OR8h7U9b8Qs5K5UuhgyeyxaBZ1Hgw==", "subType": "00" } }, "creationDate": { "$date": { "$numberLong": "1641024000000" } }, "updateDate": { "$date": { "$numberLong": "1641024000000" } }, "status": 1, "masterKey": { "provider": "local" } } ] } ], "tests": [ { "description": "rewrap with invalid masterKey for AWS KMS provider", "operations": [ { "name": "rewrapManyDataKey", "object": "clientEncryption0", "arguments": { "filter": {}, "opts": { "provider": "aws", "masterKey": { "key": "arn:aws:kms:us-east-2:579766882180:key/89fcc2c4-08b0-4bd9-9f25-e30687b580d0", "region": "us-east-2" } } }, "expectError": { "isClientError": true } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "commandName": "find", "databaseName": "keyvault", "command": { "find": "datakeys", "filter": {}, "readConcern": { "level": "majority" } } } } ] } ] }, { "description": "rewrap with invalid masterKey for Azure KMS provider", "operations": [ { "name": "rewrapManyDataKey", "object": "clientEncryption0", "arguments": { "filter": {}, "opts": { "provider": "azure", "masterKey": { "keyVaultEndpoint": "invalid-vault-csfle.vault.azure.net", "keyName": "invalid-name-csfle" } } }, "expectError": { "isClientError": true } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "commandName": "find", "databaseName": "keyvault", "command": { "find": "datakeys", "filter": {}, "readConcern": { "level": "majority" } } } } ] } ] }, { "description": "rewrap with invalid masterKey for GCP KMS provider", "operations": [ { "name": "rewrapManyDataKey", "object": "clientEncryption0", "arguments": { "filter": {}, "opts": { "provider": "gcp", "masterKey": { "projectId": "devprod-drivers", "location": "global", "keyRing": "invalid-ring-csfle", "keyName": "invalid-name-csfle" } } }, "expectError": { "isClientError": true } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "commandName": "find", "databaseName": "keyvault", "command": { "find": "datakeys", "filter": {}, "readConcern": { "level": "majority" } } } } ] } ] } ] } mongodb-mongo-python-driver-509e9b7/test/client-side-encryption/spec/unified/rewrapManyDataKey.json000066400000000000000000001321611462766011000336500ustar00rootroot00000000000000{ "description": "rewrapManyDataKey", "schemaVersion": "1.8", "runOnRequirements": [ { "csfle": true } ], "createEntities": [ { "client": { "id": "client0", "observeEvents": [ "commandStartedEvent" ] } }, { "clientEncryption": { "id": "clientEncryption0", "clientEncryptionOpts": { "keyVaultClient": "client0", "keyVaultNamespace": "keyvault.datakeys", "kmsProviders": { "aws": { "accessKeyId": { "$$placeholder": 1 }, "secretAccessKey": { "$$placeholder": 1 } }, "azure": { "tenantId": { "$$placeholder": 1 }, "clientId": { "$$placeholder": 1 }, "clientSecret": { "$$placeholder": 1 } }, "gcp": { "email": { "$$placeholder": 1 }, "privateKey": { "$$placeholder": 1 } }, "kmip": { "endpoint": { "$$placeholder": 1 } }, "local": { "key": { "$$placeholder": 1 } } } } } }, { "database": { "id": "database0", "client": "client0", "databaseName": "keyvault" } }, { "collection": { "id": "collection0", "database": "database0", "collectionName": "datakeys" } } ], "initialData": [ { "databaseName": "keyvault", "collectionName": "datakeys", "documents": [ { "_id": { "$binary": { "base64": "YXdzYXdzYXdzYXdzYXdzYQ==", "subType": "04" } }, "keyAltNames": [ "aws_key" ], "keyMaterial": { "$binary": { "base64": "AQICAHhQNmWG2CzOm1dq3kWLM+iDUZhEqnhJwH9wZVpuZ94A8gFXJqbF0Fy872MD7xl56D/2AAAAwjCBvwYJKoZIhvcNAQcGoIGxMIGuAgEAMIGoBgkqhkiG9w0BBwEwHgYJYIZIAWUDBAEuMBEEDO7HPisPUlGzaio9vgIBEIB7/Qow46PMh/8JbEUbdXgTGhLfXPE+KIVW7T8s6YEMlGiRvMu7TV0QCIUJlSHPKZxzlJ2iwuz5yXeOag+EdY+eIQ0RKrsJ3b8UTisZYzGjfzZnxUKLzLoeXremtRCm3x47wCuHKd1dhh6FBbYt5TL2tDaj+vL2GBrKat2L", "subType": "00" } }, "creationDate": { "$date": { "$numberLong": "1641024000000" } }, "updateDate": { "$date": { "$numberLong": "1641024000000" } }, "status": 1, "masterKey": { "provider": "aws", "key": "arn:aws:kms:us-east-1:579766882180:key/89fcc2c4-08b0-4bd9-9f25-e30687b580d0", "region": "us-east-1" } }, { "_id": { "$binary": { "base64": "YXp1cmVhenVyZWF6dXJlYQ==", "subType": "04" } }, "keyAltNames": [ "azure_key" ], "keyMaterial": { "$binary": { "base64": "pr01l7qDygUkFE/0peFwpnNlv3iIy8zrQK38Q9i12UCN2jwZHDmfyx8wokiIKMb9kAleeY+vnt3Cf1MKu9kcDmI+KxbNDd+V3ytAAGzOVLDJr77CiWjF9f8ntkXRHrAY9WwnVDANYkDwXlyU0Y2GQFTiW65jiQhUtYLYH63Tk48SsJuQvnWw1Q+PzY8ga+QeVec8wbcThwtm+r2IHsCFnc72Gv73qq7weISw+O4mN08z3wOp5FOS2ZM3MK7tBGmPdBcktW7F8ODGsOQ1FU53OrWUnyX2aTi2ftFFFMWVHqQo7EYuBZHru8RRODNKMyQk0BFfKovAeTAVRv9WH9QU7g==", "subType": "00" } }, "creationDate": { "$date": { "$numberLong": "1641024000000" } }, "updateDate": { "$date": { "$numberLong": "1641024000000" } }, "status": 1, "masterKey": { "provider": "azure", "keyVaultEndpoint": "key-vault-csfle.vault.azure.net", "keyName": "key-name-csfle" } }, { "_id": { "$binary": { "base64": "Z2NwZ2NwZ2NwZ2NwZ2NwZw==", "subType": "04" } }, "keyAltNames": [ "gcp_key" ], "keyMaterial": { "$binary": { "base64": "CiQAIgLj0USbQtof/pYRLQO96yg/JEtZbD1UxKueaC37yzT5tTkSiQEAhClWB5ZCSgzHgxv8raWjNB4r7e8ePGdsmSuYTYmLC5oHHS/BdQisConzNKFaobEQZHamTCjyhy5NotKF8MWoo+dyfQApwI29+vAGyrUIQCXzKwRnNdNQ+lb3vJtS5bqvLTvSxKHpVca2kqyC9nhonV+u4qru5Q2bAqUgVFc8fL4pBuvlowZFTQ==", "subType": "00" } }, "creationDate": { "$date": { "$numberLong": "1641024000000" } }, "updateDate": { "$date": { "$numberLong": "1641024000000" } }, "status": 1, "masterKey": { "provider": "gcp", "projectId": "devprod-drivers", "location": "global", "keyRing": "key-ring-csfle", "keyName": "key-name-csfle" } }, { "_id": { "$binary": { "base64": "a21pcGttaXBrbWlwa21pcA==", "subType": "04" } }, "keyAltNames": [ "kmip_key" ], "keyMaterial": { "$binary": { "base64": "CklVctHzke4mcytd0TxGqvepkdkQN8NUF4+jV7aZQITAKdz6WjdDpq3lMt9nSzWGG2vAEfvRb3mFEVjV57qqGqxjq2751gmiMRHXz0btStbIK3mQ5xbY9kdye4tsixlCryEwQONr96gwlwKKI9Nubl9/8+uRF6tgYjje7Q7OjauEf1SrJwKcoQ3WwnjZmEqAug0kImCpJ/irhdqPzivRiA==", "subType": "00" } }, "creationDate": { "$date": { "$numberLong": "1641024000000" } }, "updateDate": { "$date": { "$numberLong": "1641024000000" } }, "status": 1, "masterKey": { "provider": "kmip", "keyId": "1" } }, { "_id": { "$binary": { "base64": "bG9jYWxrZXlsb2NhbGtleQ==", "subType": "04" } }, "keyAltNames": [ "local_key" ], "keyMaterial": { "$binary": { "base64": "ABKBldDEoDW323yejOnIRk6YQmlD9d3eQthd16scKL75nz2LjNL9fgPDZWrFFOlqlhMCFaSrNJfGrFUjYk5JFDO7soG5Syb50k1niJoKg4ilsj0L4mpimFUtTpOr2nzZOeQtvAksEXc7gsFgq8gV7t/U3lsaXPY7I0t42DfSE8EGlPdxRjFdHnxh+OR8h7U9b8Qs5K5UuhgyeyxaBZ1Hgw==", "subType": "00" } }, "creationDate": { "$date": { "$numberLong": "1641024000000" } }, "updateDate": { "$date": { "$numberLong": "1641024000000" } }, "status": 1, "masterKey": { "provider": "local" } } ] } ], "tests": [ { "description": "no keys to rewrap due to no filter matches", "operations": [ { "name": "rewrapManyDataKey", "object": "clientEncryption0", "arguments": { "filter": { "keyAltNames": "no_matching_keys" }, "opts": { "provider": "local" } }, "expectResult": { "bulkWriteResult": { "$$exists": false } } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "databaseName": "keyvault", "command": { "find": "datakeys", "filter": { "keyAltNames": "no_matching_keys" }, "readConcern": { "level": "majority" } } } } ] } ] }, { "description": "rewrap with new AWS KMS provider", "operations": [ { "name": "rewrapManyDataKey", "object": "clientEncryption0", "arguments": { "filter": { "keyAltNames": { "$ne": "aws_key" } }, "opts": { "provider": "aws", "masterKey": { "key": "arn:aws:kms:us-east-1:579766882180:key/061334ae-07a8-4ceb-a813-8135540e837d", "region": "us-east-1" } } }, "expectResult": { "bulkWriteResult": { "insertedCount": 0, "matchedCount": 4, "modifiedCount": 4, "deletedCount": 0, "upsertedCount": 0, "upsertedIds": {}, "insertedIds": { "$$unsetOrMatches": {} } } } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "databaseName": "keyvault", "command": { "find": "datakeys", "filter": { "keyAltNames": { "$ne": "aws_key" } }, "readConcern": { "level": "majority" } } } }, { "commandStartedEvent": { "databaseName": "keyvault", "command": { "update": "datakeys", "ordered": true, "updates": [ { "q": { "_id": { "$$type": "binData" } }, "u": { "$set": { "masterKey": { "provider": "aws", "key": "arn:aws:kms:us-east-1:579766882180:key/061334ae-07a8-4ceb-a813-8135540e837d", "region": "us-east-1" }, "keyMaterial": { "$$type": "binData" } }, "$currentDate": { "updateDate": true } }, "multi": { "$$unsetOrMatches": false }, "upsert": { "$$unsetOrMatches": false } }, { "q": { "_id": { "$$type": "binData" } }, "u": { "$set": { "masterKey": { "provider": "aws", "key": "arn:aws:kms:us-east-1:579766882180:key/061334ae-07a8-4ceb-a813-8135540e837d", "region": "us-east-1" }, "keyMaterial": { "$$type": "binData" } }, "$currentDate": { "updateDate": true } }, "multi": { "$$unsetOrMatches": false }, "upsert": { "$$unsetOrMatches": false } }, { "q": { "_id": { "$$type": "binData" } }, "u": { "$set": { "masterKey": { "provider": "aws", "key": "arn:aws:kms:us-east-1:579766882180:key/061334ae-07a8-4ceb-a813-8135540e837d", "region": "us-east-1" }, "keyMaterial": { "$$type": "binData" } }, "$currentDate": { "updateDate": true } }, "multi": { "$$unsetOrMatches": false }, "upsert": { "$$unsetOrMatches": false } }, { "q": { "_id": { "$$type": "binData" } }, "u": { "$set": { "masterKey": { "provider": "aws", "key": "arn:aws:kms:us-east-1:579766882180:key/061334ae-07a8-4ceb-a813-8135540e837d", "region": "us-east-1" }, "keyMaterial": { "$$type": "binData" } }, "$currentDate": { "updateDate": true } }, "multi": { "$$unsetOrMatches": false }, "upsert": { "$$unsetOrMatches": false } } ], "writeConcern": { "w": "majority" } } } } ] } ] }, { "description": "rewrap with new Azure KMS provider", "operations": [ { "name": "rewrapManyDataKey", "object": "clientEncryption0", "arguments": { "filter": { "keyAltNames": { "$ne": "azure_key" } }, "opts": { "provider": "azure", "masterKey": { "keyVaultEndpoint": "key-vault-csfle.vault.azure.net", "keyName": "key-name-csfle" } } }, "expectResult": { "bulkWriteResult": { "insertedCount": 0, "matchedCount": 4, "modifiedCount": 4, "deletedCount": 0, "upsertedCount": 0, "upsertedIds": {}, "insertedIds": { "$$unsetOrMatches": {} } } } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "databaseName": "keyvault", "command": { "find": "datakeys", "filter": { "keyAltNames": { "$ne": "azure_key" } }, "readConcern": { "level": "majority" } } } }, { "commandStartedEvent": { "databaseName": "keyvault", "command": { "update": "datakeys", "ordered": true, "updates": [ { "q": { "_id": { "$$type": "binData" } }, "u": { "$set": { "masterKey": { "provider": "azure", "keyVaultEndpoint": "key-vault-csfle.vault.azure.net", "keyName": "key-name-csfle" }, "keyMaterial": { "$$type": "binData" } }, "$currentDate": { "updateDate": true } }, "multi": { "$$unsetOrMatches": false }, "upsert": { "$$unsetOrMatches": false } }, { "q": { "_id": { "$$type": "binData" } }, "u": { "$set": { "masterKey": { "provider": "azure", "keyVaultEndpoint": "key-vault-csfle.vault.azure.net", "keyName": "key-name-csfle" }, "keyMaterial": { "$$type": "binData" } }, "$currentDate": { "updateDate": true } }, "multi": { "$$unsetOrMatches": false }, "upsert": { "$$unsetOrMatches": false } }, { "q": { "_id": { "$$type": "binData" } }, "u": { "$set": { "masterKey": { "provider": "azure", "keyVaultEndpoint": "key-vault-csfle.vault.azure.net", "keyName": "key-name-csfle" }, "keyMaterial": { "$$type": "binData" } }, "$currentDate": { "updateDate": true } }, "multi": { "$$unsetOrMatches": false }, "upsert": { "$$unsetOrMatches": false } }, { "q": { "_id": { "$$type": "binData" } }, "u": { "$set": { "masterKey": { "provider": "azure", "keyVaultEndpoint": "key-vault-csfle.vault.azure.net", "keyName": "key-name-csfle" }, "keyMaterial": { "$$type": "binData" } }, "$currentDate": { "updateDate": true } }, "multi": { "$$unsetOrMatches": false }, "upsert": { "$$unsetOrMatches": false } } ], "writeConcern": { "w": "majority" } } } } ] } ] }, { "description": "rewrap with new GCP KMS provider", "operations": [ { "name": "rewrapManyDataKey", "object": "clientEncryption0", "arguments": { "filter": { "keyAltNames": { "$ne": "gcp_key" } }, "opts": { "provider": "gcp", "masterKey": { "projectId": "devprod-drivers", "location": "global", "keyRing": "key-ring-csfle", "keyName": "key-name-csfle" } } }, "expectResult": { "bulkWriteResult": { "insertedCount": 0, "matchedCount": 4, "modifiedCount": 4, "deletedCount": 0, "upsertedCount": 0, "upsertedIds": {}, "insertedIds": { "$$unsetOrMatches": {} } } } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "databaseName": "keyvault", "command": { "find": "datakeys", "filter": { "keyAltNames": { "$ne": "gcp_key" } }, "readConcern": { "level": "majority" } } } }, { "commandStartedEvent": { "databaseName": "keyvault", "command": { "update": "datakeys", "ordered": true, "updates": [ { "q": { "_id": { "$$type": "binData" } }, "u": { "$set": { "masterKey": { "provider": "gcp", "projectId": "devprod-drivers", "location": "global", "keyRing": "key-ring-csfle", "keyName": "key-name-csfle" }, "keyMaterial": { "$$type": "binData" } }, "$currentDate": { "updateDate": true } }, "multi": { "$$unsetOrMatches": false }, "upsert": { "$$unsetOrMatches": false } }, { "q": { "_id": { "$$type": "binData" } }, "u": { "$set": { "masterKey": { "provider": "gcp", "projectId": "devprod-drivers", "location": "global", "keyRing": "key-ring-csfle", "keyName": "key-name-csfle" }, "keyMaterial": { "$$type": "binData" } }, "$currentDate": { "updateDate": true } }, "multi": { "$$unsetOrMatches": false }, "upsert": { "$$unsetOrMatches": false } }, { "q": { "_id": { "$$type": "binData" } }, "u": { "$set": { "masterKey": { "provider": "gcp", "projectId": "devprod-drivers", "location": "global", "keyRing": "key-ring-csfle", "keyName": "key-name-csfle" }, "keyMaterial": { "$$type": "binData" } }, "$currentDate": { "updateDate": true } }, "multi": { "$$unsetOrMatches": false }, "upsert": { "$$unsetOrMatches": false } }, { "q": { "_id": { "$$type": "binData" } }, "u": { "$set": { "masterKey": { "provider": "gcp", "projectId": "devprod-drivers", "location": "global", "keyRing": "key-ring-csfle", "keyName": "key-name-csfle" }, "keyMaterial": { "$$type": "binData" } }, "$currentDate": { "updateDate": true } }, "multi": { "$$unsetOrMatches": false }, "upsert": { "$$unsetOrMatches": false } } ], "writeConcern": { "w": "majority" } } } } ] } ] }, { "description": "rewrap with new KMIP KMS provider", "operations": [ { "name": "rewrapManyDataKey", "object": "clientEncryption0", "arguments": { "filter": { "keyAltNames": { "$ne": "kmip_key" } }, "opts": { "provider": "kmip" } }, "expectResult": { "bulkWriteResult": { "insertedCount": 0, "matchedCount": 4, "modifiedCount": 4, "deletedCount": 0, "upsertedCount": 0, "upsertedIds": {}, "insertedIds": { "$$unsetOrMatches": {} } } } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "databaseName": "keyvault", "command": { "find": "datakeys", "filter": { "keyAltNames": { "$ne": "kmip_key" } }, "readConcern": { "level": "majority" } } } }, { "commandStartedEvent": { "databaseName": "keyvault", "command": { "update": "datakeys", "ordered": true, "updates": [ { "q": { "_id": { "$$type": "binData" } }, "u": { "$set": { "masterKey": { "provider": "kmip", "keyId": { "$$type": "string" } }, "keyMaterial": { "$$type": "binData" } }, "$currentDate": { "updateDate": true } }, "multi": { "$$unsetOrMatches": false }, "upsert": { "$$unsetOrMatches": false } }, { "q": { "_id": { "$$type": "binData" } }, "u": { "$set": { "masterKey": { "provider": "kmip", "keyId": { "$$type": "string" } }, "keyMaterial": { "$$type": "binData" } }, "$currentDate": { "updateDate": true } }, "multi": { "$$unsetOrMatches": false }, "upsert": { "$$unsetOrMatches": false } }, { "q": { "_id": { "$$type": "binData" } }, "u": { "$set": { "masterKey": { "provider": "kmip", "keyId": { "$$type": "string" } }, "keyMaterial": { "$$type": "binData" } }, "$currentDate": { "updateDate": true } }, "multi": { "$$unsetOrMatches": false }, "upsert": { "$$unsetOrMatches": false } }, { "q": { "_id": { "$$type": "binData" } }, "u": { "$set": { "masterKey": { "provider": "kmip", "keyId": { "$$type": "string" } }, "keyMaterial": { "$$type": "binData" } }, "$currentDate": { "updateDate": true } }, "multi": { "$$unsetOrMatches": false }, "upsert": { "$$unsetOrMatches": false } } ], "writeConcern": { "w": "majority" } } } } ] } ] }, { "description": "rewrap with new local KMS provider", "operations": [ { "name": "rewrapManyDataKey", "object": "clientEncryption0", "arguments": { "filter": { "keyAltNames": { "$ne": "local_key" } }, "opts": { "provider": "local" } }, "expectResult": { "bulkWriteResult": { "insertedCount": 0, "matchedCount": 4, "modifiedCount": 4, "deletedCount": 0, "upsertedCount": 0, "upsertedIds": {}, "insertedIds": { "$$unsetOrMatches": {} } } } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "databaseName": "keyvault", "command": { "find": "datakeys", "filter": { "keyAltNames": { "$ne": "local_key" } }, "readConcern": { "level": "majority" } } } }, { "commandStartedEvent": { "databaseName": "keyvault", "command": { "update": "datakeys", "ordered": true, "updates": [ { "q": { "_id": { "$$type": "binData" } }, "u": { "$set": { "masterKey": { "provider": "local" }, "keyMaterial": { "$$type": "binData" } }, "$currentDate": { "updateDate": true } }, "multi": { "$$unsetOrMatches": false }, "upsert": { "$$unsetOrMatches": false } }, { "q": { "_id": { "$$type": "binData" } }, "u": { "$set": { "masterKey": { "provider": "local" }, "keyMaterial": { "$$type": "binData" } }, "$currentDate": { "updateDate": true } }, "multi": { "$$unsetOrMatches": false }, "upsert": { "$$unsetOrMatches": false } }, { "q": { "_id": { "$$type": "binData" } }, "u": { "$set": { "masterKey": { "provider": "local" }, "keyMaterial": { "$$type": "binData" } }, "$currentDate": { "updateDate": true } }, "multi": { "$$unsetOrMatches": false }, "upsert": { "$$unsetOrMatches": false } }, { "q": { "_id": { "$$type": "binData" } }, "u": { "$set": { "masterKey": { "provider": "local" }, "keyMaterial": { "$$type": "binData" } }, "$currentDate": { "updateDate": true } }, "multi": { "$$unsetOrMatches": false }, "upsert": { "$$unsetOrMatches": false } } ], "writeConcern": { "w": "majority" } } } } ] } ] }, { "description": "rewrap with current KMS provider", "operations": [ { "name": "rewrapManyDataKey", "object": "clientEncryption0", "arguments": { "filter": {} }, "expectResult": { "bulkWriteResult": { "insertedCount": 0, "matchedCount": 5, "modifiedCount": 5, "deletedCount": 0, "upsertedCount": 0, "upsertedIds": {}, "insertedIds": { "$$unsetOrMatches": {} } } } }, { "name": "find", "object": "collection0", "arguments": { "filter": {}, "projection": { "masterKey": 1 }, "sort": { "keyAltNames": 1 } }, "expectResult": [ { "_id": { "$binary": { "base64": "YXdzYXdzYXdzYXdzYXdzYQ==", "subType": "04" } }, "masterKey": { "provider": "aws", "key": "arn:aws:kms:us-east-1:579766882180:key/89fcc2c4-08b0-4bd9-9f25-e30687b580d0", "region": "us-east-1" } }, { "_id": { "$binary": { "base64": "YXp1cmVhenVyZWF6dXJlYQ==", "subType": "04" } }, "masterKey": { "provider": "azure", "keyVaultEndpoint": "key-vault-csfle.vault.azure.net", "keyName": "key-name-csfle" } }, { "_id": { "$binary": { "base64": "Z2NwZ2NwZ2NwZ2NwZ2NwZw==", "subType": "04" } }, "masterKey": { "provider": "gcp", "projectId": "devprod-drivers", "location": "global", "keyRing": "key-ring-csfle", "keyName": "key-name-csfle" } }, { "_id": { "$binary": { "base64": "a21pcGttaXBrbWlwa21pcA==", "subType": "04" } }, "masterKey": { "provider": "kmip", "keyId": "1" } }, { "_id": { "$binary": { "base64": "bG9jYWxrZXlsb2NhbGtleQ==", "subType": "04" } }, "masterKey": { "provider": "local" } } ] } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "databaseName": "keyvault", "command": { "find": "datakeys", "filter": {}, "readConcern": { "level": "majority" } } } }, { "commandStartedEvent": { "databaseName": "keyvault", "command": { "update": "datakeys", "ordered": true, "updates": [ { "q": { "_id": { "$$type": "binData" } }, "u": { "$set": { "masterKey": { "$$type": "object" }, "keyMaterial": { "$$type": "binData" } }, "$currentDate": { "updateDate": true } }, "multi": { "$$unsetOrMatches": false }, "upsert": { "$$unsetOrMatches": false } }, { "q": { "_id": { "$$type": "binData" } }, "u": { "$set": { "masterKey": { "$$type": "object" }, "keyMaterial": { "$$type": "binData" } }, "$currentDate": { "updateDate": true } }, "multi": { "$$unsetOrMatches": false }, "upsert": { "$$unsetOrMatches": false } }, { "q": { "_id": { "$$type": "binData" } }, "u": { "$set": { "masterKey": { "$$type": "object" }, "keyMaterial": { "$$type": "binData" } }, "$currentDate": { "updateDate": true } }, "multi": { "$$unsetOrMatches": false }, "upsert": { "$$unsetOrMatches": false } }, { "q": { "_id": { "$$type": "binData" } }, "u": { "$set": { "masterKey": { "$$type": "object" }, "keyMaterial": { "$$type": "binData" } }, "$currentDate": { "updateDate": true } }, "multi": { "$$unsetOrMatches": false }, "upsert": { "$$unsetOrMatches": false } }, { "q": { "_id": { "$$type": "binData" } }, "u": { "$set": { "masterKey": { "$$type": "object" }, "keyMaterial": { "$$type": "binData" } }, "$currentDate": { "updateDate": true } }, "multi": { "$$unsetOrMatches": false }, "upsert": { "$$unsetOrMatches": false } } ], "writeConcern": { "w": "majority" } } } }, { "commandStartedEvent": { "commandName": "find" } } ] } ] } ] } mongodb-mongo-python-driver-509e9b7/test/collection_management/000077500000000000000000000000001462766011000247435ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/collection_management/clustered-indexes.json000066400000000000000000000151741462766011000312750ustar00rootroot00000000000000{ "description": "clustered-indexes", "schemaVersion": "1.4", "runOnRequirements": [ { "minServerVersion": "5.3", "serverless": "forbid" } ], "createEntities": [ { "client": { "id": "client0", "observeEvents": [ "commandStartedEvent" ] } }, { "database": { "id": "database0", "client": "client0", "databaseName": "ci-tests" } }, { "collection": { "id": "collection0", "database": "database0", "collectionName": "test" } } ], "initialData": [ { "collectionName": "test", "databaseName": "ci-tests", "documents": [] } ], "tests": [ { "description": "createCollection with clusteredIndex", "operations": [ { "name": "dropCollection", "object": "database0", "arguments": { "collection": "test" } }, { "name": "createCollection", "object": "database0", "arguments": { "collection": "test", "clusteredIndex": { "key": { "_id": 1 }, "unique": true, "name": "test index" } } }, { "name": "assertCollectionExists", "object": "testRunner", "arguments": { "databaseName": "ci-tests", "collectionName": "test" } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "drop": "test" }, "databaseName": "ci-tests" } }, { "commandStartedEvent": { "command": { "create": "test", "clusteredIndex": { "key": { "_id": 1 }, "unique": true, "name": "test index" } }, "databaseName": "ci-tests" } } ] } ] }, { "description": "listCollections includes clusteredIndex", "operations": [ { "name": "dropCollection", "object": "database0", "arguments": { "collection": "test" } }, { "name": "createCollection", "object": "database0", "arguments": { "collection": "test", "clusteredIndex": { "key": { "_id": 1 }, "unique": true, "name": "test index" } } }, { "name": "listCollections", "object": "database0", "arguments": { "filter": { "name": { "$eq": "test" } } }, "expectResult": [ { "name": "test", "options": { "clusteredIndex": { "key": { "_id": 1 }, "unique": true, "name": "test index", "v": { "$$type": [ "int", "long" ] } } } } ] } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "drop": "test" }, "databaseName": "ci-tests" } }, { "commandStartedEvent": { "command": { "create": "test", "clusteredIndex": { "key": { "_id": 1 }, "unique": true, "name": "test index" } }, "databaseName": "ci-tests" } }, { "commandStartedEvent": { "command": { "listCollections": 1, "filter": { "name": { "$eq": "test" } } }, "databaseName": "ci-tests" } } ] } ] }, { "description": "listIndexes returns the index", "operations": [ { "name": "dropCollection", "object": "database0", "arguments": { "collection": "test" } }, { "name": "createCollection", "object": "database0", "arguments": { "collection": "test", "clusteredIndex": { "key": { "_id": 1 }, "unique": true, "name": "test index" } } }, { "name": "listIndexes", "object": "collection0", "expectResult": [ { "key": { "_id": 1 }, "name": "test index", "clustered": true, "unique": true, "v": { "$$type": [ "int", "long" ] } } ] } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "drop": "test" }, "databaseName": "ci-tests" } }, { "commandStartedEvent": { "command": { "create": "test", "clusteredIndex": { "key": { "_id": 1 }, "unique": true, "name": "test index" } }, "databaseName": "ci-tests" } }, { "commandStartedEvent": { "command": { "listIndexes": "test" }, "databaseName": "ci-tests" } } ] } ] } ] } createCollection-pre_and_post_images.json000066400000000000000000000037671462766011000350530ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/collection_management{ "description": "createCollection-pre_and_post_images", "schemaVersion": "1.4", "runOnRequirements": [ { "minServerVersion": "6.0", "serverless": "forbid" } ], "createEntities": [ { "client": { "id": "client0", "observeEvents": [ "commandStartedEvent" ] } }, { "database": { "id": "database0", "client": "client0", "databaseName": "papi-tests" } }, { "collection": { "id": "collection0", "database": "database0", "collectionName": "test" } } ], "tests": [ { "description": "createCollection with changeStreamPreAndPostImages enabled", "operations": [ { "name": "dropCollection", "object": "database0", "arguments": { "collection": "test" } }, { "name": "createCollection", "object": "database0", "arguments": { "collection": "test", "changeStreamPreAndPostImages": { "enabled": true } } }, { "name": "assertCollectionExists", "object": "testRunner", "arguments": { "databaseName": "papi-tests", "collectionName": "test" } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "drop": "test" }, "databaseName": "papi-tests" } }, { "commandStartedEvent": { "command": { "create": "test", "changeStreamPreAndPostImages": { "enabled": true } }, "databaseName": "papi-tests" } } ] } ] } ] } modifyCollection-pre_and_post_images.json000066400000000000000000000047321462766011000350700ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/collection_management{ "description": "modifyCollection-pre_and_post_images", "schemaVersion": "1.4", "runOnRequirements": [ { "minServerVersion": "6.0", "serverless": "forbid" } ], "createEntities": [ { "client": { "id": "client0", "observeEvents": [ "commandStartedEvent" ] } }, { "database": { "id": "database0", "client": "client0", "databaseName": "papi-tests" } }, { "collection": { "id": "collection0", "database": "database0", "collectionName": "test" } } ], "tests": [ { "description": "modifyCollection to changeStreamPreAndPostImages enabled", "operations": [ { "name": "dropCollection", "object": "database0", "arguments": { "collection": "test" } }, { "name": "createCollection", "object": "database0", "arguments": { "collection": "test", "changeStreamPreAndPostImages": { "enabled": false } } }, { "name": "assertCollectionExists", "object": "testRunner", "arguments": { "databaseName": "papi-tests", "collectionName": "test" } }, { "name": "modifyCollection", "object": "database0", "arguments": { "collection": "test", "changeStreamPreAndPostImages": { "enabled": true } } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "drop": "test" }, "databaseName": "papi-tests" } }, { "commandStartedEvent": { "command": { "create": "test", "changeStreamPreAndPostImages": { "enabled": false } } } }, { "commandStartedEvent": { "command": { "collMod": "test", "changeStreamPreAndPostImages": { "enabled": true } } } } ] } ] } ] } mongodb-mongo-python-driver-509e9b7/test/collection_management/timeseries-collection.json000066400000000000000000000171211462766011000321420ustar00rootroot00000000000000{ "description": "timeseries-collection", "schemaVersion": "1.0", "runOnRequirements": [ { "minServerVersion": "5.0" } ], "createEntities": [ { "client": { "id": "client0", "observeEvents": [ "commandStartedEvent" ] } }, { "database": { "id": "database0", "client": "client0", "databaseName": "ts-tests" } }, { "collection": { "id": "collection0", "database": "database0", "collectionName": "test" } } ], "initialData": [ { "collectionName": "test", "databaseName": "ts-tests", "documents": [] } ], "tests": [ { "description": "createCollection with all options", "operations": [ { "name": "dropCollection", "object": "database0", "arguments": { "collection": "test" } }, { "name": "createCollection", "object": "database0", "arguments": { "collection": "test", "expireAfterSeconds": 604800, "timeseries": { "timeField": "time", "metaField": "meta", "granularity": "minutes" } } }, { "name": "assertCollectionExists", "object": "testRunner", "arguments": { "databaseName": "ts-tests", "collectionName": "test" } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "drop": "test" }, "databaseName": "ts-tests" } }, { "commandStartedEvent": { "command": { "create": "test", "expireAfterSeconds": 604800, "timeseries": { "timeField": "time", "metaField": "meta", "granularity": "minutes" } }, "databaseName": "ts-tests" } } ] } ] }, { "description": "insertMany with duplicate ids", "operations": [ { "name": "dropCollection", "object": "database0", "arguments": { "collection": "test" } }, { "name": "createCollection", "object": "database0", "arguments": { "collection": "test", "expireAfterSeconds": 604800, "timeseries": { "timeField": "time", "metaField": "meta", "granularity": "minutes" } } }, { "name": "assertCollectionExists", "object": "testRunner", "arguments": { "databaseName": "ts-tests", "collectionName": "test" } }, { "name": "insertMany", "object": "collection0", "arguments": { "documents": [ { "_id": 1, "time": { "$date": { "$numberLong": "1552949630482" } } }, { "_id": 1, "time": { "$date": { "$numberLong": "1552949630483" } } } ] } }, { "name": "find", "object": "collection0", "arguments": { "filter": {}, "sort": { "time": 1 } }, "expectResult": [ { "_id": 1, "time": { "$date": { "$numberLong": "1552949630482" } } }, { "_id": 1, "time": { "$date": { "$numberLong": "1552949630483" } } } ] } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "drop": "test" }, "databaseName": "ts-tests" } }, { "commandStartedEvent": { "command": { "create": "test", "expireAfterSeconds": 604800, "timeseries": { "timeField": "time", "metaField": "meta", "granularity": "minutes" } }, "databaseName": "ts-tests" } }, { "commandStartedEvent": { "command": { "insert": "test", "documents": [ { "_id": 1, "time": { "$date": { "$numberLong": "1552949630482" } } }, { "_id": 1, "time": { "$date": { "$numberLong": "1552949630483" } } } ] } } }, { "commandStartedEvent": { "command": { "find": "test", "filter": {}, "sort": { "time": 1 } }, "databaseName": "ts-tests" } } ] } ] }, { "description": "createCollection with bucketing options", "runOnRequirements": [ { "minServerVersion": "7.0" } ], "operations": [ { "name": "dropCollection", "object": "database0", "arguments": { "collection": "test" } }, { "name": "createCollection", "object": "database0", "arguments": { "collection": "test", "timeseries": { "timeField": "time", "bucketMaxSpanSeconds": 3600, "bucketRoundingSeconds": 3600 } } }, { "name": "assertCollectionExists", "object": "testRunner", "arguments": { "databaseName": "ts-tests", "collectionName": "test" } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "drop": "test" }, "databaseName": "ts-tests" } }, { "commandStartedEvent": { "command": { "create": "test", "timeseries": { "timeField": "time", "bucketMaxSpanSeconds": 3600, "bucketRoundingSeconds": 3600 } }, "databaseName": "ts-tests" } } ] } ] } ] } mongodb-mongo-python-driver-509e9b7/test/command_logging/000077500000000000000000000000001462766011000235405ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/command_logging/command.json000066400000000000000000000121031462766011000260460ustar00rootroot00000000000000{ "description": "command-logging", "schemaVersion": "1.13", "createEntities": [ { "client": { "id": "client", "observeLogMessages": { "command": "debug" } } }, { "database": { "id": "database", "client": "client", "databaseName": "logging-tests" } }, { "collection": { "id": "collection", "database": "database", "collectionName": "logging-tests-collection" } } ], "initialData": [ { "collectionName": "logging-tests-collection", "databaseName": "logging-tests", "documents": [ { "_id": 1, "x": 11 } ] } ], "tests": [ { "description": "A successful command", "operations": [ { "name": "runCommand", "object": "database", "arguments": { "command": { "ping": 1 }, "commandName": "ping" } } ], "expectLogMessages": [ { "client": "client", "messages": [ { "level": "debug", "component": "command", "data": { "message": "Command started", "databaseName": "logging-tests", "commandName": "ping", "command": { "$$matchAsDocument": { "$$matchAsRoot": { "ping": 1, "$db": "logging-tests" } } }, "requestId": { "$$type": [ "int", "long" ] }, "serverHost": { "$$type": "string" }, "serverPort": { "$$type": [ "int", "long" ] } } }, { "level": "debug", "component": "command", "data": { "message": "Command succeeded", "databaseName": "logging-tests", "commandName": "ping", "reply": { "$$type": "string" }, "requestId": { "$$type": [ "int", "long" ] }, "serverHost": { "$$type": "string" }, "serverPort": { "$$type": [ "int", "long" ] }, "durationMS": { "$$type": [ "double", "int", "long" ] } } } ] } ] }, { "description": "A failed command", "operations": [ { "name": "find", "object": "collection", "arguments": { "filter": { "$or": true } }, "expectError": { "isClientError": false } } ], "expectLogMessages": [ { "client": "client", "messages": [ { "level": "debug", "component": "command", "data": { "message": "Command started", "databaseName": "logging-tests", "commandName": "find", "command": { "$$type": "string" }, "requestId": { "$$type": [ "int", "long" ] }, "serverHost": { "$$type": "string" }, "serverPort": { "$$type": [ "int", "long" ] } } }, { "level": "debug", "component": "command", "data": { "message": "Command failed", "databaseName": "logging-tests", "commandName": "find", "failure": { "$$exists": true }, "requestId": { "$$type": [ "int", "long" ] }, "serverHost": { "$$type": "string" }, "serverPort": { "$$type": [ "int", "long" ] }, "durationMS": { "$$type": [ "double", "int", "long" ] } } } ] } ] } ] } mongodb-mongo-python-driver-509e9b7/test/command_logging/driver-connection-id.json000066400000000000000000000063311462766011000304600ustar00rootroot00000000000000{ "description": "driver-connection-id", "schemaVersion": "1.13", "createEntities": [ { "client": { "id": "client", "observeLogMessages": { "command": "debug" } } }, { "database": { "id": "database", "client": "client", "databaseName": "logging-tests" } }, { "collection": { "id": "collection", "database": "database", "collectionName": "logging-tests-collection" } } ], "initialData": [ { "collectionName": "logging-tests-collection", "databaseName": "logging-tests", "documents": [ { "_id": 1, "x": 11 } ] } ], "tests": [ { "description": "A successful command", "operations": [ { "name": "runCommand", "object": "database", "arguments": { "command": { "ping": 1 }, "commandName": "ping" } } ], "expectLogMessages": [ { "client": "client", "messages": [ { "level": "debug", "component": "command", "data": { "message": "Command started", "databaseName": "logging-tests", "commandName": "ping", "driverConnectionId": { "$$type": [ "int", "long" ] } } }, { "level": "debug", "component": "command", "data": { "message": "Command succeeded", "commandName": "ping", "driverConnectionId": { "$$type": [ "int", "long" ] } } } ] } ] }, { "description": "A failed command", "operations": [ { "name": "find", "object": "collection", "arguments": { "filter": { "$or": true } }, "expectError": { "isClientError": false } } ], "expectLogMessages": [ { "client": "client", "messages": [ { "level": "debug", "component": "command", "data": { "message": "Command started", "databaseName": "logging-tests", "commandName": "find", "driverConnectionId": { "$$type": [ "int", "long" ] } } }, { "level": "debug", "component": "command", "data": { "message": "Command failed", "commandName": "find", "driverConnectionId": { "$$type": [ "int", "long" ] } } } ] } ] } ] } mongodb-mongo-python-driver-509e9b7/test/command_logging/no-handshake-messages.json000066400000000000000000000044021462766011000306000ustar00rootroot00000000000000{ "description": "no-handshake-command-logs", "schemaVersion": "1.13", "tests": [ { "description": "Handshake commands should not generate log messages", "operations": [ { "name": "createEntities", "object": "testRunner", "arguments": { "entities": [ { "client": { "id": "client", "observeLogMessages": { "command": "debug" }, "observeEvents": [ "connectionCreatedEvent", "connectionReadyEvent" ] } }, { "database": { "id": "database", "client": "client", "databaseName": "logging-tests" } } ] } }, { "name": "runCommand", "object": "database", "arguments": { "command": { "ping": 1 }, "commandName": "ping" } }, { "name": "waitForEvent", "object": "testRunner", "arguments": { "client": "client", "event": { "connectionCreatedEvent": {} }, "count": 1 } }, { "name": "waitForEvent", "object": "testRunner", "arguments": { "client": "client", "event": { "connectionReadyEvent": {} }, "count": 1 } } ], "expectLogMessages": [ { "client": "client", "messages": [ { "level": "debug", "component": "command", "data": { "message": "Command started", "databaseName": "logging-tests", "commandName": "ping" } }, { "level": "debug", "component": "command", "data": { "message": "Command succeeded", "commandName": "ping" } } ] } ] } ] } mongodb-mongo-python-driver-509e9b7/test/command_logging/no-heartbeat-messages.json000066400000000000000000000041421462766011000306120ustar00rootroot00000000000000{ "description": "no-heartbeat-command-logs", "schemaVersion": "1.13", "runOnRequirements": [ { "topologies": [ "single", "replicaset", "sharded" ] } ], "tests": [ { "description": "Heartbeat commands should not generate log messages", "operations": [ { "name": "createEntities", "object": "testRunner", "arguments": { "entities": [ { "client": { "id": "client", "observeLogMessages": { "command": "debug" }, "observeEvents": [ "serverDescriptionChangedEvent" ] } }, { "database": { "id": "database", "client": "client", "databaseName": "logging-tests" } } ] } }, { "name": "waitForEvent", "object": "testRunner", "arguments": { "client": "client", "event": { "serverDescriptionChangedEvent": {} }, "count": 1 } }, { "name": "runCommand", "object": "database", "arguments": { "command": { "ping": 1 }, "commandName": "ping" } } ], "expectLogMessages": [ { "client": "client", "messages": [ { "level": "debug", "component": "command", "data": { "message": "Command started", "databaseName": "logging-tests", "commandName": "ping" } }, { "level": "debug", "component": "command", "data": { "message": "Command succeeded", "commandName": "ping" } } ] } ] } ] } mongodb-mongo-python-driver-509e9b7/test/command_logging/operation-id.json000066400000000000000000000111361462766011000270270ustar00rootroot00000000000000{ "description": "operation-id", "schemaVersion": "1.13", "createEntities": [ { "client": { "id": "client", "observeLogMessages": { "command": "debug" } } }, { "database": { "id": "database", "client": "client", "databaseName": "logging-tests" } }, { "collection": { "id": "collection", "database": "database", "collectionName": "logging-tests-collection" } } ], "initialData": [ { "collectionName": "logging-tests-collection", "databaseName": "logging-tests", "documents": [ { "_id": 1, "x": 11 } ] } ], "tests": [ { "description": "Successful bulk write command log messages include operationIds", "operations": [ { "name": "bulkWrite", "object": "collection", "arguments": { "requests": [ { "insertOne": { "document": { "x": 1 } } }, { "deleteOne": { "filter": { "x": 1 } } } ] } } ], "expectLogMessages": [ { "client": "client", "messages": [ { "level": "debug", "component": "command", "data": { "message": "Command started", "databaseName": "logging-tests", "commandName": "insert", "operationId": { "$$type": [ "int", "long" ] } } }, { "level": "debug", "component": "command", "data": { "message": "Command succeeded", "commandName": "insert", "operationId": { "$$type": [ "int", "long" ] } } }, { "level": "debug", "component": "command", "data": { "message": "Command started", "databaseName": "logging-tests", "commandName": "delete", "operationId": { "$$type": [ "int", "long" ] } } }, { "level": "debug", "component": "command", "data": { "message": "Command succeeded", "commandName": "delete", "operationId": { "$$type": [ "int", "long" ] } } } ] } ] }, { "description": "Failed bulk write command log message includes operationId", "operations": [ { "name": "bulkWrite", "object": "collection", "arguments": { "requests": [ { "updateOne": { "filter": { "x": 1 }, "update": [ { "$invalidOperator": true } ] } } ] }, "expectError": { "isClientError": false } } ], "expectLogMessages": [ { "client": "client", "messages": [ { "level": "debug", "component": "command", "data": { "message": "Command started", "databaseName": "logging-tests", "commandName": "update", "operationId": { "$$type": [ "int", "long" ] } } }, { "level": "debug", "component": "command", "data": { "message": "Command failed", "commandName": "update", "operationId": { "$$type": [ "int", "long" ] } } } ] } ] } ] } mongodb-mongo-python-driver-509e9b7/test/command_logging/pre-42-server-connection-id.json000066400000000000000000000053231462766011000315020ustar00rootroot00000000000000{ "description": "pre-42-server-connection-id", "schemaVersion": "1.13", "runOnRequirements": [ { "maxServerVersion": "4.0.99" } ], "createEntities": [ { "client": { "id": "client", "observeLogMessages": { "command": "debug" } } }, { "database": { "id": "database", "client": "client", "databaseName": "logging-server-connection-id-tests" } }, { "collection": { "id": "collection", "database": "database", "collectionName": "logging-tests-collection" } } ], "initialData": [ { "databaseName": "logging-server-connection-id-tests", "collectionName": "logging-tests-collection", "documents": [] } ], "tests": [ { "description": "command log messages do not include server connection id", "operations": [ { "name": "insertOne", "object": "collection", "arguments": { "document": { "x": 1 } } }, { "name": "find", "object": "collection", "arguments": { "filter": { "$or": true } }, "expectError": { "isError": true } } ], "expectLogMessages": [ { "client": "client", "messages": [ { "level": "debug", "component": "command", "data": { "message": "Command started", "commandName": "insert", "serverConnectionId": { "$$exists": false } } }, { "level": "debug", "component": "command", "data": { "message": "Command succeeded", "commandName": "insert", "serverConnectionId": { "$$exists": false } } }, { "level": "debug", "component": "command", "data": { "message": "Command started", "commandName": "find", "serverConnectionId": { "$$exists": false } } }, { "level": "debug", "component": "command", "data": { "message": "Command failed", "commandName": "find", "serverConnectionId": { "$$exists": false } } } ] } ] } ] } mongodb-mongo-python-driver-509e9b7/test/command_logging/redacted-commands.json000066400000000000000000001115331462766011000300110ustar00rootroot00000000000000{ "description": "redacted-commands", "schemaVersion": "1.13", "runOnRequirements": [ { "minServerVersion": "5.0", "auth": false } ], "createEntities": [ { "client": { "id": "client", "useMultipleMongoses": false, "observeLogMessages": { "command": "debug" } } }, { "client": { "id": "failPointClient", "useMultipleMongoses": false } }, { "database": { "id": "database", "client": "client", "databaseName": "logging-redaction-tests" } } ], "tests": [ { "description": "authenticate command and resulting server-generated error are redacted", "operations": [ { "name": "runCommand", "object": "database", "arguments": { "commandName": "authenticate", "command": { "authenticate": 1, "mechanism": "MONGODB-X509", "user": "CN=myName,OU=myOrgUnit,O=myOrg,L=myLocality,ST=myState,C=myCountry", "db": "$external" } }, "expectError": { "isClientError": false } } ], "expectLogMessages": [ { "client": "client", "messages": [ { "level": "debug", "component": "command", "data": { "message": "Command started", "databaseName": "logging-redaction-tests", "commandName": "authenticate", "command": { "$$matchAsDocument": {} } } }, { "level": "debug", "component": "command", "failureIsRedacted": true, "data": { "message": "Command failed", "commandName": "authenticate", "failure": { "$$exists": true } } } ] } ] }, { "description": "network error in response to authenticate is not redacted", "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "authenticate" ], "closeConnection": true } } } }, { "name": "runCommand", "object": "database", "arguments": { "commandName": "authenticate", "command": { "authenticate": 1, "mechanism": "MONGODB-X509", "user": "CN=myName,OU=myOrgUnit,O=myOrg,L=myLocality,ST=myState,C=myCountry" } }, "expectError": { "isClientError": true } } ], "expectLogMessages": [ { "client": "client", "messages": [ { "level": "debug", "component": "command", "data": { "message": "Command started", "databaseName": "logging-redaction-tests", "commandName": "authenticate", "command": { "$$matchAsDocument": {} } } }, { "level": "debug", "component": "command", "failureIsRedacted": false, "data": { "message": "Command failed", "commandName": "authenticate", "failure": { "$$exists": true } } } ] } ] }, { "description": "saslStart command and resulting server-generated error are redacted", "operations": [ { "name": "runCommand", "object": "database", "arguments": { "commandName": "saslStart", "command": { "saslStart": 1, "payload": "definitely-invalid-payload", "db": "admin" } }, "expectError": { "isClientError": false } } ], "expectLogMessages": [ { "client": "client", "messages": [ { "level": "debug", "component": "command", "data": { "message": "Command started", "databaseName": "logging-redaction-tests", "commandName": "saslStart", "command": { "$$matchAsDocument": {} } } }, { "level": "debug", "component": "command", "failureIsRedacted": true, "data": { "message": "Command failed", "commandName": "saslStart", "failure": { "$$exists": true } } } ] } ] }, { "description": "network error in response to saslStart is not redacted", "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "saslStart" ], "closeConnection": true } } } }, { "name": "runCommand", "object": "database", "arguments": { "commandName": "saslStart", "command": { "saslStart": 1, "payload": "ZmFrZXNhc2xwYXlsb2Fk", "mechanism": "MONGODB-X509" } }, "expectError": { "isClientError": true } } ], "expectLogMessages": [ { "client": "client", "messages": [ { "level": "debug", "component": "command", "data": { "message": "Command started", "databaseName": "logging-redaction-tests", "commandName": "saslStart", "command": { "$$matchAsDocument": {} } } }, { "level": "debug", "component": "command", "failureIsRedacted": false, "data": { "message": "Command failed", "commandName": "saslStart", "failure": { "$$exists": true } } } ] } ] }, { "description": "saslContinue command and resulting server-generated error are redacted", "operations": [ { "name": "runCommand", "object": "database", "arguments": { "commandName": "saslContinue", "command": { "saslContinue": 1, "conversationId": 0, "payload": "definitely-invalid-payload" } }, "expectError": { "isClientError": false } } ], "expectLogMessages": [ { "client": "client", "messages": [ { "level": "debug", "component": "command", "data": { "message": "Command started", "databaseName": "logging-redaction-tests", "commandName": "saslContinue", "command": { "$$matchAsDocument": {} } } }, { "level": "debug", "component": "command", "failureIsRedacted": true, "data": { "message": "Command failed", "commandName": "saslContinue", "failure": { "$$exists": true } } } ] } ] }, { "description": "network error in response to saslContinue is not redacted", "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "saslContinue" ], "closeConnection": true } } } }, { "name": "runCommand", "object": "database", "arguments": { "commandName": "saslContinue", "command": { "saslContinue": 1, "conversationId": 0, "payload": "ZmFrZXNhc2xwYXlsb2Fk" } }, "expectError": { "isClientError": true } } ], "expectLogMessages": [ { "client": "client", "messages": [ { "level": "debug", "component": "command", "data": { "message": "Command started", "databaseName": "logging-redaction-tests", "commandName": "saslContinue", "command": { "$$matchAsDocument": {} } } }, { "level": "debug", "component": "command", "failureIsRedacted": false, "data": { "message": "Command failed", "commandName": "saslContinue", "failure": { "$$exists": true } } } ] } ] }, { "description": "getnonce command and server reply are redacted", "runOnRequirements": [ { "maxServerVersion": "6.1.99" } ], "operations": [ { "name": "runCommand", "object": "database", "arguments": { "commandName": "getnonce", "command": { "getnonce": 1 } } } ], "expectLogMessages": [ { "client": "client", "messages": [ { "level": "debug", "component": "command", "data": { "message": "Command started", "databaseName": "logging-redaction-tests", "commandName": "getnonce", "command": { "$$matchAsDocument": {} } } }, { "level": "debug", "component": "command", "data": { "message": "Command succeeded", "commandName": "getnonce", "reply": { "$$matchAsDocument": {} } } } ] } ] }, { "description": "network error in response to getnonce is not redacted", "runOnRequirements": [ { "maxServerVersion": "6.1.99" } ], "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "getnonce" ], "closeConnection": true } } } }, { "name": "runCommand", "object": "database", "arguments": { "commandName": "getnonce", "command": { "getnonce": 1 } }, "expectError": { "isClientError": true } } ], "expectLogMessages": [ { "client": "client", "messages": [ { "level": "debug", "component": "command", "data": { "message": "Command started", "databaseName": "logging-redaction-tests", "commandName": "getnonce", "command": { "$$matchAsDocument": {} } } }, { "level": "debug", "component": "command", "failureIsRedacted": false, "data": { "message": "Command failed", "commandName": "getnonce", "failure": { "$$exists": true } } } ] } ] }, { "description": "createUser command and resulting server-generated error are redacted", "operations": [ { "name": "runCommand", "object": "database", "arguments": { "commandName": "createUser", "command": { "createUser": "private", "pwd": {}, "roles": [] } }, "expectError": { "isClientError": false } } ], "expectLogMessages": [ { "client": "client", "messages": [ { "level": "debug", "component": "command", "data": { "message": "Command started", "databaseName": "logging-redaction-tests", "commandName": "createUser", "command": { "$$matchAsDocument": {} } } }, { "level": "debug", "component": "command", "failureIsRedacted": true, "data": { "message": "Command failed", "commandName": "createUser", "failure": { "$$exists": true } } } ] } ] }, { "description": "network error in response to createUser is not redacted", "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "createUser" ], "closeConnection": true } } } }, { "name": "runCommand", "object": "database", "arguments": { "commandName": "createUser", "command": { "createUser": "private", "pwd": "pwd", "roles": [] } }, "expectError": { "isClientError": true } } ], "expectLogMessages": [ { "client": "client", "messages": [ { "level": "debug", "component": "command", "data": { "message": "Command started", "databaseName": "logging-redaction-tests", "commandName": "createUser", "command": { "$$matchAsDocument": {} } } }, { "level": "debug", "component": "command", "failureIsRedacted": false, "data": { "message": "Command failed", "commandName": "createUser", "failure": { "$$exists": true } } } ] } ] }, { "description": "updateUser command and resulting server-generated error are redacted", "operations": [ { "name": "runCommand", "object": "database", "arguments": { "commandName": "updateUser", "command": { "updateUser": "private", "pwd": {}, "roles": [] } }, "expectError": { "isClientError": false } } ], "expectLogMessages": [ { "client": "client", "messages": [ { "level": "debug", "component": "command", "data": { "message": "Command started", "databaseName": "logging-redaction-tests", "commandName": "updateUser", "command": { "$$matchAsDocument": {} } } }, { "level": "debug", "component": "command", "failureIsRedacted": true, "data": { "message": "Command failed", "commandName": "updateUser", "failure": { "$$exists": true } } } ] } ] }, { "description": "network error in response to updateUser is not redacted", "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "updateUser" ], "closeConnection": true } } } }, { "name": "runCommand", "object": "database", "arguments": { "commandName": "updateUser", "command": { "updateUser": "private", "pwd": "pwd", "roles": [] } }, "expectError": { "isClientError": true } } ], "expectLogMessages": [ { "client": "client", "messages": [ { "level": "debug", "component": "command", "data": { "message": "Command started", "databaseName": "logging-redaction-tests", "commandName": "updateUser", "command": { "$$matchAsDocument": {} } } }, { "level": "debug", "component": "command", "failureIsRedacted": false, "data": { "message": "Command failed", "commandName": "updateUser", "failure": { "$$exists": true } } } ] } ] }, { "description": "copydbgetnonce command and resulting server-generated error are redacted", "runOnRequirements": [ { "maxServerVersion": "3.6.99" } ], "operations": [ { "name": "runCommand", "object": "database", "arguments": { "commandName": "copydbgetnonce", "command": { "copydbgetnonce": "private" } }, "expectError": { "isClientError": false } } ], "expectLogMessages": [ { "client": "client", "messages": [ { "level": "debug", "component": "command", "data": { "message": "Command started", "databaseName": "logging-redaction-tests", "commandName": "copydbgetnonce", "command": { "$$matchAsDocument": {} } } }, { "level": "debug", "component": "command", "failureIsRedacted": true, "data": { "message": "Command failed", "commandName": "copydbgetnonce", "failure": { "$$exists": true } } } ] } ] }, { "description": "network error in response to copydbgetnonce is not redacted", "runOnRequirements": [ { "maxServerVersion": "3.6.99" } ], "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "copydbgetnonce" ], "closeConnection": true } } } }, { "name": "runCommand", "object": "database", "arguments": { "commandName": "copydbgetnonce", "command": { "copydbgetnonce": "private" } }, "expectError": { "isClientError": true } } ], "expectLogMessages": [ { "client": "client", "messages": [ { "level": "debug", "component": "command", "data": { "message": "Command started", "databaseName": "logging-redaction-tests", "commandName": "copydbgetnonce", "command": { "$$matchAsDocument": {} } } }, { "level": "debug", "component": "command", "failureIsRedacted": false, "data": { "message": "Command failed", "commandName": "copydbgetnonce", "failure": { "$$exists": true } } } ] } ] }, { "description": "copydbsaslstart command and resulting server-generated error are redacted", "runOnRequirements": [ { "maxServerVersion": "4.0.99" } ], "operations": [ { "name": "runCommand", "object": "database", "arguments": { "commandName": "copydbsaslstart", "command": { "copydbsaslstart": "private" } }, "expectError": { "isClientError": false } } ], "expectLogMessages": [ { "client": "client", "messages": [ { "level": "debug", "component": "command", "data": { "message": "Command started", "databaseName": "logging-redaction-tests", "commandName": "copydbsaslstart", "command": { "$$matchAsDocument": {} } } }, { "level": "debug", "component": "command", "failureIsRedacted": true, "data": { "message": "Command failed", "commandName": "copydbsaslstart", "failure": { "$$exists": true } } } ] } ] }, { "description": "network error in response to copydbsaslstart is not redacted", "runOnRequirements": [ { "maxServerVersion": "4.0.99" } ], "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "copydbsaslstart" ], "closeConnection": true } } } }, { "name": "runCommand", "object": "database", "arguments": { "commandName": "copydbsaslstart", "command": { "copydbsaslstart": "private" } }, "expectError": { "isClientError": true } } ], "expectLogMessages": [ { "client": "client", "messages": [ { "level": "debug", "component": "command", "data": { "message": "Command started", "databaseName": "logging-redaction-tests", "commandName": "copydbgetnonce", "command": { "$$matchAsDocument": {} } } }, { "level": "debug", "component": "command", "failureIsRedacted": false, "data": { "message": "Command failed", "commandName": "copydbgetnonce", "failure": { "$$exists": true } } } ] } ] }, { "description": "copydb command and resulting server-generated error are redacted", "runOnRequirements": [ { "maxServerVersion": "4.0.99" } ], "operations": [ { "name": "runCommand", "object": "database", "arguments": { "commandName": "copydb", "command": { "copydb": "private" } }, "expectError": { "isClientError": false } } ], "expectLogMessages": [ { "client": "client", "messages": [ { "level": "debug", "component": "command", "data": { "message": "Command started", "databaseName": "logging-redaction-tests", "commandName": "copydb", "command": { "$$matchAsDocument": {} } } }, { "level": "debug", "component": "command", "failureIsRedacted": true, "data": { "message": "Command failed", "commandName": "copydb", "failure": { "$$exists": true } } } ] } ] }, { "description": "network error in response to copydb is not redacted", "runOnRequirements": [ { "maxServerVersion": "4.0.99" } ], "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "copydb" ], "closeConnection": true } } } }, { "name": "runCommand", "object": "database", "arguments": { "commandName": "copydb", "command": { "copydb": "private" } }, "expectError": { "isClientError": true } } ], "expectLogMessages": [ { "client": "client", "messages": [ { "level": "debug", "component": "command", "data": { "message": "Command started", "databaseName": "logging-redaction-tests", "commandName": "copydb", "command": { "$$matchAsDocument": {} } } }, { "level": "debug", "component": "command", "failureIsRedacted": false, "data": { "message": "Command failed", "commandName": "copydb", "failure": { "$$exists": true } } } ] } ] }, { "description": "hello with speculative authenticate command and server reply are redacted", "runOnRequirements": [ { "minServerVersion": "4.9" } ], "operations": [ { "name": "runCommand", "object": "database", "arguments": { "commandName": "hello", "command": { "hello": 1, "speculativeAuthenticate": { "saslStart": 1 } } } } ], "expectLogMessages": [ { "client": "client", "messages": [ { "level": "debug", "component": "command", "data": { "message": "Command started", "databaseName": "logging-redaction-tests", "commandName": "hello", "command": { "$$matchAsDocument": {} } } }, { "level": "debug", "component": "command", "data": { "message": "Command succeeded", "commandName": "hello", "reply": { "$$matchAsDocument": {} } } } ] } ] }, { "description": "legacy hello with speculative authenticate command and server reply are redacted", "operations": [ { "name": "runCommand", "object": "database", "arguments": { "commandName": "ismaster", "command": { "ismaster": 1, "speculativeAuthenticate": { "saslStart": 1 } } } }, { "name": "runCommand", "object": "database", "arguments": { "commandName": "isMaster", "command": { "isMaster": 1, "speculativeAuthenticate": { "saslStart": 1 } } } } ], "expectLogMessages": [ { "client": "client", "messages": [ { "level": "debug", "component": "command", "data": { "message": "Command started", "databaseName": "logging-redaction-tests", "commandName": "ismaster", "command": { "$$matchAsDocument": {} } } }, { "level": "debug", "component": "command", "data": { "message": "Command succeeded", "commandName": "ismaster", "reply": { "$$matchAsDocument": {} } } }, { "level": "debug", "component": "command", "data": { "message": "Command started", "databaseName": "logging-redaction-tests", "commandName": "isMaster", "command": { "$$matchAsDocument": {} } } }, { "level": "debug", "component": "command", "data": { "message": "Command succeeded", "commandName": "isMaster", "reply": { "$$matchAsDocument": {} } } } ] } ] }, { "description": "hello without speculative authenticate command and server reply are not redacted", "runOnRequirements": [ { "minServerVersion": "4.9" } ], "operations": [ { "name": "runCommand", "object": "database", "arguments": { "commandName": "hello", "command": { "hello": 1 } } } ], "expectLogMessages": [ { "client": "client", "messages": [ { "level": "debug", "component": "command", "data": { "message": "Command started", "databaseName": "logging-redaction-tests", "commandName": "hello", "command": { "$$matchAsDocument": { "$$matchAsRoot": { "hello": 1 } } } } }, { "level": "debug", "component": "command", "data": { "message": "Command succeeded", "commandName": "hello", "reply": { "$$matchAsDocument": { "$$matchAsRoot": { "ok": 1, "isWritablePrimary": true } } } } } ] } ] }, { "description": "legacy hello without speculative authenticate command and server reply are not redacted", "operations": [ { "name": "runCommand", "object": "database", "arguments": { "commandName": "ismaster", "command": { "ismaster": 1 } } }, { "name": "runCommand", "object": "database", "arguments": { "commandName": "isMaster", "command": { "isMaster": 1 } } } ], "expectLogMessages": [ { "client": "client", "messages": [ { "level": "debug", "component": "command", "data": { "message": "Command started", "databaseName": "logging-redaction-tests", "commandName": "ismaster", "command": { "$$matchAsDocument": { "$$matchAsRoot": { "ismaster": 1 } } } } }, { "level": "debug", "component": "command", "data": { "message": "Command succeeded", "commandName": "ismaster", "reply": { "$$matchAsDocument": { "$$matchAsRoot": { "ok": 1, "ismaster": true } } } } }, { "level": "debug", "component": "command", "data": { "message": "Command started", "databaseName": "logging-redaction-tests", "commandName": "isMaster", "command": { "$$matchAsDocument": { "$$matchAsRoot": { "isMaster": 1 } } } } }, { "level": "debug", "component": "command", "data": { "message": "Command succeeded", "commandName": "isMaster", "reply": { "$$matchAsDocument": { "$$matchAsRoot": { "ok": 1, "ismaster": true } } } } } ] } ] } ] } mongodb-mongo-python-driver-509e9b7/test/command_logging/server-connection-id.json000066400000000000000000000057221462766011000304760ustar00rootroot00000000000000{ "description": "server-connection-id", "schemaVersion": "1.13", "runOnRequirements": [ { "minServerVersion": "4.2" } ], "createEntities": [ { "client": { "id": "client", "observeLogMessages": { "command": "debug" } } }, { "database": { "id": "database", "client": "client", "databaseName": "logging-server-connection-id-tests" } }, { "collection": { "id": "collection", "database": "database", "collectionName": "logging-tests-collection" } } ], "initialData": [ { "databaseName": "logging-server-connection-id-tests", "collectionName": "logging-tests-collection", "documents": [] } ], "tests": [ { "description": "command log messages include server connection id", "operations": [ { "name": "insertOne", "object": "collection", "arguments": { "document": { "x": 1 } } }, { "name": "find", "object": "collection", "arguments": { "filter": { "$or": true } }, "expectError": { "isError": true } } ], "expectLogMessages": [ { "client": "client", "messages": [ { "level": "debug", "component": "command", "data": { "message": "Command started", "commandName": "insert", "serverConnectionId": { "$$type": [ "int", "long" ] } } }, { "level": "debug", "component": "command", "data": { "message": "Command succeeded", "commandName": "insert", "serverConnectionId": { "$$type": [ "int", "long" ] } } }, { "level": "debug", "component": "command", "data": { "message": "Command started", "commandName": "find", "serverConnectionId": { "$$type": [ "int", "long" ] } } }, { "level": "debug", "component": "command", "data": { "message": "Command failed", "commandName": "find", "serverConnectionId": { "$$type": [ "int", "long" ] } } } ] } ] } ] } mongodb-mongo-python-driver-509e9b7/test/command_logging/service-id.json000066400000000000000000000113651462766011000264730ustar00rootroot00000000000000{ "description": "service-id", "schemaVersion": "1.13", "createEntities": [ { "client": { "id": "client", "observeLogMessages": { "command": "debug" } } }, { "database": { "id": "database", "client": "client", "databaseName": "logging-server-connection-id-tests" } }, { "collection": { "id": "collection", "database": "database", "collectionName": "logging-tests-collection" } } ], "initialData": [ { "databaseName": "logging-server-connection-id-tests", "collectionName": "logging-tests-collection", "documents": [] } ], "tests": [ { "description": "command log messages include serviceId when in LB mode", "runOnRequirements": [ { "topologies": [ "load-balanced" ] } ], "operations": [ { "name": "insertOne", "object": "collection", "arguments": { "document": { "x": 1 } } }, { "name": "find", "object": "collection", "arguments": { "filter": { "$or": true } }, "expectError": { "isError": true } } ], "expectLogMessages": [ { "client": "client", "messages": [ { "level": "debug", "component": "command", "data": { "message": "Command started", "commandName": "insert", "serviceId": { "$$type": "string" } } }, { "level": "debug", "component": "command", "data": { "message": "Command succeeded", "commandName": "insert", "serviceId": { "$$type": "string" } } }, { "level": "debug", "component": "command", "data": { "message": "Command started", "commandName": "find", "serviceId": { "$$type": "string" } } }, { "level": "debug", "component": "command", "data": { "message": "Command failed", "commandName": "find", "serviceId": { "$$type": "string" } } } ] } ] }, { "description": "command log messages omit serviceId when not in LB mode", "runOnRequirements": [ { "topologies": [ "single", "replicaset", "sharded" ] } ], "operations": [ { "name": "insertOne", "object": "collection", "arguments": { "document": { "x": 1 } } }, { "name": "find", "object": "collection", "arguments": { "filter": { "$or": true } }, "expectError": { "isError": true } } ], "expectLogMessages": [ { "client": "client", "messages": [ { "level": "debug", "component": "command", "data": { "message": "Command started", "commandName": "insert", "serviceId": { "$$exists": false } } }, { "level": "debug", "component": "command", "data": { "message": "Command succeeded", "commandName": "insert", "serviceId": { "$$exists": false } } }, { "level": "debug", "component": "command", "data": { "message": "Command started", "commandName": "find", "serviceId": { "$$exists": false } } }, { "level": "debug", "component": "command", "data": { "message": "Command failed", "commandName": "find", "serviceId": { "$$exists": false } } } ] } ] } ] } mongodb-mongo-python-driver-509e9b7/test/command_logging/unacknowledged-write.json000066400000000000000000000066551462766011000305710ustar00rootroot00000000000000{ "description": "unacknowledged-write", "schemaVersion": "1.16", "createEntities": [ { "client": { "id": "client", "observeLogMessages": { "command": "debug" } } }, { "database": { "id": "database", "client": "client", "databaseName": "logging-tests" } }, { "collection": { "id": "collection", "database": "database", "collectionName": "logging-tests-collection", "collectionOptions": { "writeConcern": { "w": 0 } } } } ], "initialData": [ { "collectionName": "logging-tests-collection", "databaseName": "logging-tests", "documents": [ { "_id": 1 } ] } ], "tests": [ { "description": "An unacknowledged write generates a succeeded log message with ok: 1 reply", "operations": [ { "name": "insertOne", "object": "collection", "arguments": { "document": { "_id": 2 } } }, { "name": "find", "object": "collection", "arguments": { "filter": {} }, "expectResult": [ { "_id": 1 }, { "_id": 2 } ] } ], "expectLogMessages": [ { "client": "client", "ignoreExtraMessages": true, "messages": [ { "level": "debug", "component": "command", "data": { "message": "Command started", "databaseName": "logging-tests", "commandName": "insert", "command": { "$$matchAsDocument": { "$$matchAsRoot": { "insert": "logging-tests-collection", "$db": "logging-tests" } } }, "requestId": { "$$type": [ "int", "long" ] }, "serverHost": { "$$type": "string" }, "serverPort": { "$$type": [ "int", "long" ] } } }, { "level": "debug", "component": "command", "data": { "message": "Command succeeded", "commandName": "insert", "reply": { "$$matchAsDocument": { "ok": 1 } }, "requestId": { "$$type": [ "int", "long" ] }, "serverHost": { "$$type": "string" }, "serverPort": { "$$type": [ "int", "long" ] }, "durationMS": { "$$type": [ "double", "int", "long" ] } } } ] } ] } ] } mongodb-mongo-python-driver-509e9b7/test/command_monitoring/000077500000000000000000000000001462766011000242775ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/command_monitoring/bulkWrite.json000066400000000000000000000067071462766011000271540ustar00rootroot00000000000000{ "description": "bulkWrite", "schemaVersion": "1.0", "createEntities": [ { "client": { "id": "client", "observeEvents": [ "commandStartedEvent", "commandSucceededEvent", "commandFailedEvent" ] } }, { "database": { "id": "database", "client": "client", "databaseName": "command-monitoring-tests" } }, { "collection": { "id": "collection", "database": "database", "collectionName": "test" } } ], "initialData": [ { "collectionName": "test", "databaseName": "command-monitoring-tests", "documents": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 22 }, { "_id": 3, "x": 33 } ] } ], "tests": [ { "description": "A successful mixed bulk write", "operations": [ { "name": "bulkWrite", "object": "collection", "arguments": { "requests": [ { "insertOne": { "document": { "_id": 4, "x": 44 } } }, { "updateOne": { "filter": { "_id": 3 }, "update": { "$set": { "x": 333 } } } } ] } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "command": { "insert": "test", "documents": [ { "_id": 4, "x": 44 } ], "ordered": true }, "commandName": "insert", "databaseName": "command-monitoring-tests" } }, { "commandSucceededEvent": { "reply": { "ok": 1, "n": 1 }, "commandName": "insert" } }, { "commandStartedEvent": { "command": { "update": "test", "updates": [ { "q": { "_id": 3 }, "u": { "$set": { "x": 333 } }, "upsert": { "$$unsetOrMatches": false }, "multi": { "$$unsetOrMatches": false } } ], "ordered": true }, "commandName": "update", "databaseName": "command-monitoring-tests" } }, { "commandSucceededEvent": { "reply": { "ok": 1, "n": 1 }, "commandName": "update" } } ] } ] } ] } mongodb-mongo-python-driver-509e9b7/test/command_monitoring/command.json000066400000000000000000000031771462766011000266200ustar00rootroot00000000000000{ "description": "command", "schemaVersion": "1.0", "createEntities": [ { "client": { "id": "client", "observeEvents": [ "commandStartedEvent", "commandSucceededEvent", "commandFailedEvent" ] } }, { "database": { "id": "database", "client": "client", "databaseName": "command-monitoring-tests" } }, { "collection": { "id": "collection", "database": "database", "collectionName": "test" } } ], "initialData": [ { "collectionName": "test", "databaseName": "command-monitoring-tests", "documents": [ { "_id": 1, "x": 11 } ] } ], "tests": [ { "description": "A successful command", "operations": [ { "name": "runCommand", "object": "database", "arguments": { "command": { "ping": 1 }, "commandName": "ping" } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "command": { "ping": 1 }, "commandName": "ping", "databaseName": "command-monitoring-tests" } }, { "commandSucceededEvent": { "reply": { "ok": 1 }, "commandName": "ping" } } ] } ] } ] } mongodb-mongo-python-driver-509e9b7/test/command_monitoring/deleteMany.json000066400000000000000000000067761462766011000273010ustar00rootroot00000000000000{ "description": "deleteMany", "schemaVersion": "1.0", "createEntities": [ { "client": { "id": "client", "observeEvents": [ "commandStartedEvent", "commandSucceededEvent", "commandFailedEvent" ] } }, { "database": { "id": "database", "client": "client", "databaseName": "command-monitoring-tests" } }, { "collection": { "id": "collection", "database": "database", "collectionName": "test" } } ], "initialData": [ { "collectionName": "test", "databaseName": "command-monitoring-tests", "documents": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 22 }, { "_id": 3, "x": 33 } ] } ], "tests": [ { "description": "A successful deleteMany", "operations": [ { "name": "deleteMany", "object": "collection", "arguments": { "filter": { "_id": { "$gt": 1 } } } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "command": { "delete": "test", "deletes": [ { "q": { "_id": { "$gt": 1 } }, "limit": 0 } ], "ordered": true }, "commandName": "delete", "databaseName": "command-monitoring-tests" } }, { "commandSucceededEvent": { "reply": { "ok": 1, "n": 2 }, "commandName": "delete" } } ] } ] }, { "description": "A successful deleteMany with write errors", "operations": [ { "name": "deleteMany", "object": "collection", "arguments": { "filter": { "_id": { "$unsupported": 1 } } }, "expectError": { "isClientError": false } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "command": { "delete": "test", "deletes": [ { "q": { "_id": { "$unsupported": 1 } }, "limit": 0 } ], "ordered": true }, "commandName": "delete", "databaseName": "command-monitoring-tests" } }, { "commandSucceededEvent": { "reply": { "ok": 1, "n": 0, "writeErrors": { "$$type": "array" } }, "commandName": "delete" } } ] } ] } ] } mongodb-mongo-python-driver-509e9b7/test/command_monitoring/deleteOne.json000066400000000000000000000067711462766011000271110ustar00rootroot00000000000000{ "description": "deleteOne", "schemaVersion": "1.0", "createEntities": [ { "client": { "id": "client", "observeEvents": [ "commandStartedEvent", "commandSucceededEvent", "commandFailedEvent" ] } }, { "database": { "id": "database", "client": "client", "databaseName": "command-monitoring-tests" } }, { "collection": { "id": "collection", "database": "database", "collectionName": "test" } } ], "initialData": [ { "collectionName": "test", "databaseName": "command-monitoring-tests", "documents": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 22 }, { "_id": 3, "x": 33 } ] } ], "tests": [ { "description": "A successful deleteOne", "operations": [ { "name": "deleteOne", "object": "collection", "arguments": { "filter": { "_id": { "$gt": 1 } } } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "command": { "delete": "test", "deletes": [ { "q": { "_id": { "$gt": 1 } }, "limit": 1 } ], "ordered": true }, "commandName": "delete", "databaseName": "command-monitoring-tests" } }, { "commandSucceededEvent": { "reply": { "ok": 1, "n": 1 }, "commandName": "delete" } } ] } ] }, { "description": "A successful deleteOne with write errors", "operations": [ { "name": "deleteOne", "object": "collection", "arguments": { "filter": { "_id": { "$unsupported": 1 } } }, "expectError": { "isClientError": false } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "command": { "delete": "test", "deletes": [ { "q": { "_id": { "$unsupported": 1 } }, "limit": 1 } ], "ordered": true }, "commandName": "delete", "databaseName": "command-monitoring-tests" } }, { "commandSucceededEvent": { "reply": { "ok": 1, "n": 0, "writeErrors": { "$$type": "array" } }, "commandName": "delete" } } ] } ] } ] } mongodb-mongo-python-driver-509e9b7/test/command_monitoring/find.json000066400000000000000000000331421462766011000261150ustar00rootroot00000000000000{ "description": "find", "schemaVersion": "1.15", "createEntities": [ { "client": { "id": "client", "observeEvents": [ "commandStartedEvent", "commandSucceededEvent", "commandFailedEvent" ] } }, { "database": { "id": "database", "client": "client", "databaseName": "command-monitoring-tests" } }, { "collection": { "id": "collection", "database": "database", "collectionName": "test" } } ], "_yamlAnchors": { "namespace": "command-monitoring-tests.test" }, "initialData": [ { "collectionName": "test", "databaseName": "command-monitoring-tests", "documents": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 22 }, { "_id": 3, "x": 33 }, { "_id": 4, "x": 44 }, { "_id": 5, "x": 55 } ] } ], "tests": [ { "description": "A successful find with no options", "operations": [ { "name": "find", "object": "collection", "arguments": { "filter": { "_id": 1 } } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "command": { "find": "test", "filter": { "_id": 1 } }, "commandName": "find", "databaseName": "command-monitoring-tests" } }, { "commandSucceededEvent": { "reply": { "ok": 1, "cursor": { "id": 0, "ns": "command-monitoring-tests.test", "firstBatch": [ { "_id": 1, "x": 11 } ] } }, "commandName": "find", "databaseName": "command-monitoring-tests" } } ] } ] }, { "description": "A successful find with options", "operations": [ { "name": "find", "object": "collection", "arguments": { "filter": { "_id": { "$gt": 1 } }, "sort": { "x": -1 }, "projection": { "_id": 0, "x": 1 }, "skip": 2, "comment": "test", "hint": { "_id": 1 }, "max": { "_id": 6 }, "maxTimeMS": 6000, "min": { "_id": 0 } } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "command": { "find": "test", "filter": { "_id": { "$gt": 1 } }, "sort": { "x": -1 }, "projection": { "_id": 0, "x": 1 }, "skip": 2, "comment": "test", "hint": { "_id": 1 }, "max": { "_id": 6 }, "maxTimeMS": 6000, "min": { "_id": 0 } }, "commandName": "find", "databaseName": "command-monitoring-tests" } }, { "commandSucceededEvent": { "reply": { "ok": 1, "cursor": { "id": 0, "ns": "command-monitoring-tests.test", "firstBatch": [ { "x": 33 }, { "x": 22 } ] } }, "commandName": "find", "databaseName": "command-monitoring-tests" } } ] } ] }, { "description": "A successful find with showRecordId and returnKey", "operations": [ { "name": "find", "object": "collection", "arguments": { "filter": {}, "sort": { "_id": 1 }, "showRecordId": true, "returnKey": true } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "command": { "find": "test", "showRecordId": true, "returnKey": true }, "commandName": "find", "databaseName": "command-monitoring-tests" } }, { "commandSucceededEvent": { "reply": { "ok": 1, "cursor": { "id": 0, "ns": "command-monitoring-tests.test", "firstBatch": [ { "_id": 1 }, { "_id": 2 }, { "_id": 3 }, { "_id": 4 }, { "_id": 5 } ] } }, "commandName": "find", "databaseName": "command-monitoring-tests" } } ] } ] }, { "description": "A successful find with a getMore", "operations": [ { "name": "find", "object": "collection", "arguments": { "filter": { "_id": { "$gte": 1 } }, "sort": { "_id": 1 }, "batchSize": 3 } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "command": { "find": "test", "filter": { "_id": { "$gte": 1 } }, "sort": { "_id": 1 }, "batchSize": 3 }, "commandName": "find", "databaseName": "command-monitoring-tests" } }, { "commandSucceededEvent": { "reply": { "ok": 1, "cursor": { "id": { "$$type": [ "int", "long" ] }, "ns": "command-monitoring-tests.test", "firstBatch": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 22 }, { "_id": 3, "x": 33 } ] } }, "commandName": "find", "databaseName": "command-monitoring-tests" } }, { "commandStartedEvent": { "command": { "getMore": { "$$type": [ "int", "long" ] }, "collection": "test", "batchSize": 3 }, "commandName": "getMore", "databaseName": "command-monitoring-tests" } }, { "commandSucceededEvent": { "reply": { "ok": 1, "cursor": { "id": 0, "ns": "command-monitoring-tests.test", "nextBatch": [ { "_id": 4, "x": 44 }, { "_id": 5, "x": 55 } ] } }, "commandName": "getMore", "databaseName": "command-monitoring-tests" } } ] } ] }, { "description": "A successful find event with a getmore and the server kills the cursor (<= 4.4)", "runOnRequirements": [ { "minServerVersion": "3.1", "maxServerVersion": "4.4.99", "topologies": [ "single", "replicaset" ] } ], "operations": [ { "name": "find", "object": "collection", "arguments": { "filter": { "_id": { "$gte": 1 } }, "sort": { "_id": 1 }, "batchSize": 3, "limit": 4 } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "command": { "find": "test", "filter": { "_id": { "$gte": 1 } }, "sort": { "_id": 1 }, "batchSize": 3, "limit": 4 }, "commandName": "find", "databaseName": "command-monitoring-tests" } }, { "commandSucceededEvent": { "reply": { "ok": 1, "cursor": { "id": { "$$type": [ "int", "long" ] }, "ns": "command-monitoring-tests.test", "firstBatch": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 22 }, { "_id": 3, "x": 33 } ] } }, "commandName": "find", "databaseName": "command-monitoring-tests" } }, { "commandStartedEvent": { "command": { "getMore": { "$$type": [ "int", "long" ] }, "collection": "test", "batchSize": 1 }, "commandName": "getMore", "databaseName": "command-monitoring-tests" } }, { "commandSucceededEvent": { "reply": { "ok": 1, "cursor": { "id": 0, "ns": "command-monitoring-tests.test", "nextBatch": [ { "_id": 4, "x": 44 } ] } }, "commandName": "getMore", "databaseName": "command-monitoring-tests" } } ] } ] }, { "description": "A failed find event", "operations": [ { "name": "find", "object": "collection", "arguments": { "filter": { "$or": true } }, "expectError": { "isClientError": false } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "command": { "find": "test", "filter": { "$or": true } }, "commandName": "find", "databaseName": "command-monitoring-tests" } }, { "commandFailedEvent": { "commandName": "find", "databaseName": "command-monitoring-tests" } } ] } ] } ] } mongodb-mongo-python-driver-509e9b7/test/command_monitoring/insertMany.json000066400000000000000000000062661462766011000273350ustar00rootroot00000000000000{ "description": "insertMany", "schemaVersion": "1.0", "createEntities": [ { "client": { "id": "client", "observeEvents": [ "commandStartedEvent", "commandSucceededEvent", "commandFailedEvent" ] } }, { "database": { "id": "database", "client": "client", "databaseName": "command-monitoring-tests" } }, { "collection": { "id": "collection", "database": "database", "collectionName": "test" } } ], "initialData": [ { "collectionName": "test", "databaseName": "command-monitoring-tests", "documents": [ { "_id": 1, "x": 11 } ] } ], "tests": [ { "description": "A successful insertMany", "operations": [ { "name": "insertMany", "object": "collection", "arguments": { "documents": [ { "_id": 2, "x": 22 } ] } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "command": { "insert": "test", "documents": [ { "_id": 2, "x": 22 } ], "ordered": true }, "commandName": "insert", "databaseName": "command-monitoring-tests" } }, { "commandSucceededEvent": { "reply": { "ok": 1, "n": 1 }, "commandName": "insert" } } ] } ] }, { "description": "A successful insertMany with write errors", "operations": [ { "name": "insertMany", "object": "collection", "arguments": { "documents": [ { "_id": 1, "x": 11 } ] }, "expectError": { "isClientError": false } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "command": { "insert": "test", "documents": [ { "_id": 1, "x": 11 } ], "ordered": true }, "commandName": "insert", "databaseName": "command-monitoring-tests" } }, { "commandSucceededEvent": { "reply": { "ok": 1, "n": 0, "writeErrors": { "$$type": "array" } }, "commandName": "insert" } } ] } ] } ] } mongodb-mongo-python-driver-509e9b7/test/command_monitoring/insertOne.json000066400000000000000000000061471462766011000271500ustar00rootroot00000000000000{ "description": "insertOne", "schemaVersion": "1.0", "createEntities": [ { "client": { "id": "client", "observeEvents": [ "commandStartedEvent", "commandSucceededEvent", "commandFailedEvent" ] } }, { "database": { "id": "database", "client": "client", "databaseName": "command-monitoring-tests" } }, { "collection": { "id": "collection", "database": "database", "collectionName": "test" } } ], "initialData": [ { "collectionName": "test", "databaseName": "command-monitoring-tests", "documents": [ { "_id": 1, "x": 11 } ] } ], "tests": [ { "description": "A successful insertOne", "operations": [ { "name": "insertOne", "object": "collection", "arguments": { "document": { "_id": 2, "x": 22 } } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "command": { "insert": "test", "documents": [ { "_id": 2, "x": 22 } ], "ordered": true }, "commandName": "insert", "databaseName": "command-monitoring-tests" } }, { "commandSucceededEvent": { "reply": { "ok": 1, "n": 1 }, "commandName": "insert" } } ] } ] }, { "description": "A successful insertOne with write errors", "operations": [ { "name": "insertOne", "object": "collection", "arguments": { "document": { "_id": 1, "x": 11 } }, "expectError": { "isClientError": false } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "command": { "insert": "test", "documents": [ { "_id": 1, "x": 11 } ], "ordered": true }, "commandName": "insert", "databaseName": "command-monitoring-tests" } }, { "commandSucceededEvent": { "reply": { "ok": 1, "n": 0, "writeErrors": { "$$type": "array" } }, "commandName": "insert" } } ] } ] } ] } mongodb-mongo-python-driver-509e9b7/test/command_monitoring/pre-42-server-connection-id.json000066400000000000000000000041761462766011000322460ustar00rootroot00000000000000{ "description": "pre-42-server-connection-id", "schemaVersion": "1.6", "runOnRequirements": [ { "maxServerVersion": "4.0.99" } ], "createEntities": [ { "client": { "id": "client", "observeEvents": [ "commandStartedEvent", "commandSucceededEvent", "commandFailedEvent" ] } }, { "database": { "id": "database", "client": "client", "databaseName": "server-connection-id-tests" } }, { "collection": { "id": "collection", "database": "database", "collectionName": "coll" } } ], "initialData": [ { "databaseName": "server-connection-id-tests", "collectionName": "coll", "documents": [] } ], "tests": [ { "description": "command events do not include server connection id", "operations": [ { "name": "insertOne", "object": "collection", "arguments": { "document": { "x": 1 } } }, { "name": "find", "object": "collection", "arguments": { "filter": { "$or": true } }, "expectError": { "isError": true } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "insert", "hasServerConnectionId": false } }, { "commandSucceededEvent": { "commandName": "insert", "hasServerConnectionId": false } }, { "commandStartedEvent": { "commandName": "find", "hasServerConnectionId": false } }, { "commandFailedEvent": { "commandName": "find", "hasServerConnectionId": false } } ] } ] } ] } mongodb-mongo-python-driver-509e9b7/test/command_monitoring/redacted-commands.json000066400000000000000000000370751462766011000305600ustar00rootroot00000000000000{ "description": "redacted-commands", "schemaVersion": "1.5", "runOnRequirements": [ { "minServerVersion": "5.0", "auth": false } ], "createEntities": [ { "client": { "id": "client", "observeEvents": [ "commandStartedEvent", "commandSucceededEvent" ], "observeSensitiveCommands": true } }, { "database": { "id": "database", "client": "client", "databaseName": "command-monitoring-tests" } } ], "tests": [ { "description": "authenticate", "operations": [ { "name": "runCommand", "object": "database", "arguments": { "commandName": "authenticate", "command": { "authenticate": 1, "mechanism": "MONGODB-X509", "user": "CN=myName,OU=myOrgUnit,O=myOrg,L=myLocality,ST=myState,C=myCountry", "db": "$external" } }, "expectError": { "isError": true } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "authenticate", "command": { "authenticate": { "$$exists": false }, "mechanism": { "$$exists": false }, "user": { "$$exists": false }, "db": { "$$exists": false } } } } ] } ] }, { "description": "saslStart", "operations": [ { "name": "runCommand", "object": "database", "arguments": { "commandName": "saslStart", "command": { "saslStart": 1, "payload": "definitely-invalid-payload", "db": "admin" } }, "expectError": { "isError": true } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "saslStart", "command": { "saslStart": { "$$exists": false }, "payload": { "$$exists": false }, "db": { "$$exists": false } } } } ] } ] }, { "description": "saslContinue", "operations": [ { "name": "runCommand", "object": "database", "arguments": { "commandName": "saslContinue", "command": { "saslContinue": 1, "conversationId": 0, "payload": "definitely-invalid-payload" } }, "expectError": { "isError": true } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "saslContinue", "command": { "saslContinue": { "$$exists": false }, "conversationId": { "$$exists": false }, "payload": { "$$exists": false } } } } ] } ] }, { "description": "getnonce", "runOnRequirements": [ { "maxServerVersion": "6.1.99" } ], "operations": [ { "name": "runCommand", "object": "database", "arguments": { "commandName": "getnonce", "command": { "getnonce": 1 } } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "getnonce", "command": { "getnonce": { "$$exists": false } } } }, { "commandSucceededEvent": { "commandName": "getnonce", "reply": { "ok": { "$$exists": false }, "nonce": { "$$exists": false } } } } ] } ] }, { "description": "createUser", "operations": [ { "name": "runCommand", "object": "database", "arguments": { "commandName": "createUser", "command": { "createUser": "private", "pwd": {}, "roles": [] } }, "expectError": { "isError": true } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "createUser", "command": { "createUser": { "$$exists": false }, "pwd": { "$$exists": false }, "roles": { "$$exists": false } } } } ] } ] }, { "description": "updateUser", "operations": [ { "name": "runCommand", "object": "database", "arguments": { "commandName": "updateUser", "command": { "updateUser": "private", "pwd": {}, "roles": [] } }, "expectError": { "isError": true } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "updateUser", "command": { "updateUser": { "$$exists": false }, "pwd": { "$$exists": false }, "roles": { "$$exists": false } } } } ] } ] }, { "description": "copydbgetnonce", "runOnRequirements": [ { "maxServerVersion": "3.6.99" } ], "operations": [ { "name": "runCommand", "object": "database", "arguments": { "commandName": "copydbgetnonce", "command": { "copydbgetnonce": "private" } }, "expectError": { "isError": true } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "copydbgetnonce", "command": { "copydbgetnonce": { "$$exists": false } } } } ] } ] }, { "description": "copydbsaslstart", "runOnRequirements": [ { "maxServerVersion": "4.0.99" } ], "operations": [ { "name": "runCommand", "object": "database", "arguments": { "commandName": "copydbsaslstart", "command": { "copydbsaslstart": "private" } }, "expectError": { "isError": true } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "copydbsaslstart", "command": { "copydbsaslstart": { "$$exists": false } } } } ] } ] }, { "description": "copydb", "runOnRequirements": [ { "maxServerVersion": "4.0.99" } ], "operations": [ { "name": "runCommand", "object": "database", "arguments": { "commandName": "copydb", "command": { "copydb": "private" } }, "expectError": { "isError": true } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "copydb", "command": { "copydb": { "$$exists": false } } } } ] } ] }, { "description": "hello with speculative authenticate", "runOnRequirements": [ { "minServerVersion": "4.9" } ], "operations": [ { "name": "runCommand", "object": "database", "arguments": { "commandName": "hello", "command": { "hello": 1, "speculativeAuthenticate": { "saslStart": 1 } } } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "hello", "command": { "hello": { "$$exists": false }, "speculativeAuthenticate": { "$$exists": false } } } }, { "commandSucceededEvent": { "commandName": "hello", "reply": { "isWritablePrimary": { "$$exists": false }, "speculativeAuthenticate": { "$$exists": false } } } } ] } ] }, { "description": "legacy hello with speculative authenticate", "operations": [ { "name": "runCommand", "object": "database", "arguments": { "commandName": "ismaster", "command": { "ismaster": 1, "speculativeAuthenticate": { "saslStart": 1 } } } }, { "name": "runCommand", "object": "database", "arguments": { "commandName": "isMaster", "command": { "isMaster": 1, "speculativeAuthenticate": { "saslStart": 1 } } } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "ismaster", "command": { "ismaster": { "$$exists": false }, "speculativeAuthenticate": { "$$exists": false } } } }, { "commandSucceededEvent": { "commandName": "ismaster", "reply": { "ismaster": { "$$exists": false }, "speculativeAuthenticate": { "$$exists": false } } } }, { "commandStartedEvent": { "commandName": "isMaster", "command": { "isMaster": { "$$exists": false }, "speculativeAuthenticate": { "$$exists": false } } } }, { "commandSucceededEvent": { "commandName": "isMaster", "reply": { "ismaster": { "$$exists": false }, "speculativeAuthenticate": { "$$exists": false } } } } ] } ] }, { "description": "hello without speculative authenticate is not redacted", "runOnRequirements": [ { "minServerVersion": "4.9" } ], "operations": [ { "name": "runCommand", "object": "database", "arguments": { "commandName": "hello", "command": { "hello": 1 } } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "hello", "command": { "hello": 1 } } }, { "commandSucceededEvent": { "commandName": "hello", "reply": { "isWritablePrimary": { "$$exists": true } } } } ] } ] }, { "description": "legacy hello without speculative authenticate is not redacted", "operations": [ { "name": "runCommand", "object": "database", "arguments": { "commandName": "ismaster", "command": { "ismaster": 1 } } }, { "name": "runCommand", "object": "database", "arguments": { "commandName": "isMaster", "command": { "isMaster": 1 } } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "ismaster", "command": { "ismaster": 1 } } }, { "commandSucceededEvent": { "commandName": "ismaster", "reply": { "ismaster": { "$$exists": true } } } }, { "commandStartedEvent": { "commandName": "isMaster", "command": { "isMaster": 1 } } }, { "commandSucceededEvent": { "commandName": "isMaster", "reply": { "ismaster": { "$$exists": true } } } } ] } ] } ] } mongodb-mongo-python-driver-509e9b7/test/command_monitoring/server-connection-id.json000066400000000000000000000041511462766011000312300ustar00rootroot00000000000000{ "description": "server-connection-id", "schemaVersion": "1.6", "runOnRequirements": [ { "minServerVersion": "4.2" } ], "createEntities": [ { "client": { "id": "client", "observeEvents": [ "commandStartedEvent", "commandSucceededEvent", "commandFailedEvent" ] } }, { "database": { "id": "database", "client": "client", "databaseName": "server-connection-id-tests" } }, { "collection": { "id": "collection", "database": "database", "collectionName": "coll" } } ], "initialData": [ { "databaseName": "server-connection-id-tests", "collectionName": "coll", "documents": [] } ], "tests": [ { "description": "command events include server connection id", "operations": [ { "name": "insertOne", "object": "collection", "arguments": { "document": { "x": 1 } } }, { "name": "find", "object": "collection", "arguments": { "filter": { "$or": true } }, "expectError": { "isError": true } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "insert", "hasServerConnectionId": true } }, { "commandSucceededEvent": { "commandName": "insert", "hasServerConnectionId": true } }, { "commandStartedEvent": { "commandName": "find", "hasServerConnectionId": true } }, { "commandFailedEvent": { "commandName": "find", "hasServerConnectionId": true } } ] } ] } ] } mongodb-mongo-python-driver-509e9b7/test/command_monitoring/unacknowledgedBulkWrite.json000066400000000000000000000054041462766011000320200ustar00rootroot00000000000000{ "description": "unacknowledgedBulkWrite", "schemaVersion": "1.7", "createEntities": [ { "client": { "id": "client", "observeEvents": [ "commandStartedEvent", "commandSucceededEvent", "commandFailedEvent" ] } }, { "database": { "id": "database", "client": "client", "databaseName": "command-monitoring-tests" } }, { "collection": { "id": "collection", "database": "database", "collectionName": "test", "collectionOptions": { "writeConcern": { "w": 0 } } } } ], "initialData": [ { "collectionName": "test", "databaseName": "command-monitoring-tests", "documents": [ { "_id": 1, "x": 11 } ] } ], "tests": [ { "description": "A successful unordered bulk write with an unacknowledged write concern", "operations": [ { "name": "bulkWrite", "object": "collection", "arguments": { "requests": [ { "insertOne": { "document": { "_id": "unorderedBulkWriteInsertW0", "x": 44 } } } ], "ordered": false } }, { "name": "find", "object": "collection", "arguments": { "filter": {} }, "expectResult": [ { "_id": 1, "x": 11 }, { "_id": "unorderedBulkWriteInsertW0", "x": 44 } ] } ], "expectEvents": [ { "client": "client", "ignoreExtraEvents": true, "events": [ { "commandStartedEvent": { "command": { "insert": "test", "documents": [ { "_id": "unorderedBulkWriteInsertW0", "x": 44 } ], "ordered": false, "writeConcern": { "w": 0 } }, "commandName": "insert", "databaseName": "command-monitoring-tests" } }, { "commandSucceededEvent": { "reply": { "ok": 1, "n": { "$$exists": false } }, "commandName": "insert" } } ] } ] } ] } mongodb-mongo-python-driver-509e9b7/test/command_monitoring/updateMany.json000066400000000000000000000103161462766011000273020ustar00rootroot00000000000000{ "description": "updateMany", "schemaVersion": "1.0", "createEntities": [ { "client": { "id": "client", "observeEvents": [ "commandStartedEvent", "commandSucceededEvent", "commandFailedEvent" ] } }, { "database": { "id": "database", "client": "client", "databaseName": "command-monitoring-tests" } }, { "collection": { "id": "collection", "database": "database", "collectionName": "test" } } ], "initialData": [ { "collectionName": "test", "databaseName": "command-monitoring-tests", "documents": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 22 }, { "_id": 3, "x": 33 } ] } ], "tests": [ { "description": "A successful updateMany", "operations": [ { "name": "updateMany", "object": "collection", "arguments": { "filter": { "_id": { "$gt": 1 } }, "update": { "$inc": { "x": 1 } } } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "command": { "update": "test", "updates": [ { "q": { "_id": { "$gt": 1 } }, "u": { "$inc": { "x": 1 } }, "upsert": { "$$unsetOrMatches": false }, "multi": true } ], "ordered": true }, "commandName": "update", "databaseName": "command-monitoring-tests" } }, { "commandSucceededEvent": { "reply": { "ok": 1, "n": 2 }, "commandName": "update" } } ] } ] }, { "description": "A successful updateMany with write errors", "operations": [ { "name": "updateMany", "object": "collection", "arguments": { "filter": { "_id": { "$gt": 1 } }, "update": { "$unsupported": { "x": 1 } } }, "expectError": { "isClientError": false } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "command": { "update": "test", "updates": [ { "q": { "_id": { "$gt": 1 } }, "u": { "$unsupported": { "x": 1 } }, "upsert": { "$$unsetOrMatches": false }, "multi": true } ], "ordered": true }, "commandName": "update", "databaseName": "command-monitoring-tests" } }, { "commandSucceededEvent": { "reply": { "ok": 1, "n": 0, "writeErrors": { "$$type": "array" } }, "commandName": "update" } } ] } ] } ] } mongodb-mongo-python-driver-509e9b7/test/command_monitoring/updateOne.json000066400000000000000000000140361462766011000271220ustar00rootroot00000000000000{ "description": "updateOne", "schemaVersion": "1.0", "createEntities": [ { "client": { "id": "client", "observeEvents": [ "commandStartedEvent", "commandSucceededEvent", "commandFailedEvent" ] } }, { "database": { "id": "database", "client": "client", "databaseName": "command-monitoring-tests" } }, { "collection": { "id": "collection", "database": "database", "collectionName": "test" } } ], "initialData": [ { "collectionName": "test", "databaseName": "command-monitoring-tests", "documents": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 22 }, { "_id": 3, "x": 33 } ] } ], "tests": [ { "description": "A successful updateOne", "operations": [ { "name": "updateOne", "object": "collection", "arguments": { "filter": { "_id": { "$gt": 1 } }, "update": { "$inc": { "x": 1 } } } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "command": { "update": "test", "updates": [ { "q": { "_id": { "$gt": 1 } }, "u": { "$inc": { "x": 1 } }, "upsert": { "$$unsetOrMatches": false }, "multi": { "$$unsetOrMatches": false } } ], "ordered": true }, "commandName": "update", "databaseName": "command-monitoring-tests" } }, { "commandSucceededEvent": { "reply": { "ok": 1, "n": 1 }, "commandName": "update" } } ] } ] }, { "description": "A successful updateOne with upsert where the upserted id is not an ObjectId", "operations": [ { "name": "updateOne", "object": "collection", "arguments": { "filter": { "_id": 4 }, "update": { "$inc": { "x": 1 } }, "upsert": true } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "command": { "update": "test", "updates": [ { "q": { "_id": 4 }, "u": { "$inc": { "x": 1 } }, "upsert": true, "multi": { "$$unsetOrMatches": false } } ], "ordered": true }, "commandName": "update", "databaseName": "command-monitoring-tests" } }, { "commandSucceededEvent": { "reply": { "ok": 1, "n": 1, "upserted": [ { "index": 0, "_id": 4 } ] }, "commandName": "update" } } ] } ] }, { "description": "A successful updateOne with write errors", "operations": [ { "name": "updateOne", "object": "collection", "arguments": { "filter": { "_id": { "$gt": 1 } }, "update": { "$unsupported": { "x": 1 } } }, "expectError": { "isClientError": false } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "command": { "update": "test", "updates": [ { "q": { "_id": { "$gt": 1 } }, "u": { "$unsupported": { "x": 1 } }, "upsert": { "$$unsetOrMatches": false }, "multi": { "$$unsetOrMatches": false } } ], "ordered": true }, "commandName": "update", "databaseName": "command-monitoring-tests" } }, { "commandSucceededEvent": { "reply": { "ok": 1, "n": 0, "writeErrors": { "$$type": "array" } }, "commandName": "update" } } ] } ] } ] } mongodb-mongo-python-driver-509e9b7/test/command_monitoring/writeConcernError.json000066400000000000000000000070041462766011000306470ustar00rootroot00000000000000{ "description": "writeConcernError", "schemaVersion": "1.4", "runOnRequirements": [ { "minServerVersion": "4.3.1", "topologies": [ "replicaset" ], "serverless": "forbid" } ], "createEntities": [ { "client": { "id": "client", "observeEvents": [ "commandStartedEvent", "commandSucceededEvent", "commandFailedEvent" ] } }, { "database": { "id": "database", "client": "client", "databaseName": "command-monitoring-tests" } }, { "collection": { "id": "collection", "database": "database", "collectionName": "test" } } ], "initialData": [ { "collectionName": "test", "databaseName": "command-monitoring-tests", "documents": [ { "_id": 1, "x": 11 } ] } ], "tests": [ { "description": "A retryable write with write concern errors publishes success event", "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "client", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "insert" ], "errorLabels": [ "RetryableWriteError" ], "writeConcernError": { "code": 91 } } } } }, { "name": "insertOne", "object": "collection", "arguments": { "document": { "_id": 2, "x": 22 } } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "command": { "insert": "test", "documents": [ { "_id": 2, "x": 22 } ], "ordered": true }, "commandName": "insert", "databaseName": "command-monitoring-tests" } }, { "commandSucceededEvent": { "reply": { "ok": 1, "n": 1, "errorLabels": [ "RetryableWriteError" ], "writeConcernError": { "code": 91 } }, "commandName": "insert" } }, { "commandStartedEvent": { "command": { "insert": "test", "documents": [ { "_id": 2, "x": 22 } ], "ordered": true }, "commandName": "insert", "databaseName": "command-monitoring-tests" } }, { "commandSucceededEvent": { "reply": { "ok": 1, "n": 1 }, "commandName": "insert" } } ] } ] } ] }mongodb-mongo-python-driver-509e9b7/test/conftest.py000066400000000000000000000003111462766011000226060ustar00rootroot00000000000000from __future__ import annotations from test import setup, teardown import pytest @pytest.fixture(scope="session", autouse=True) def test_setup_and_teardown(): setup() yield teardown() mongodb-mongo-python-driver-509e9b7/test/connection_logging/000077500000000000000000000000001462766011000242615ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/connection_logging/connection-logging.json000066400000000000000000000326201462766011000307420ustar00rootroot00000000000000{ "description": "connection-logging", "schemaVersion": "1.13", "runOnRequirements": [ { "topologies": [ "single" ] } ], "createEntities": [ { "client": { "id": "failPointClient" } } ], "tests": [ { "description": "Create a client, run a command, and close the client", "operations": [ { "name": "createEntities", "object": "testRunner", "arguments": { "entities": [ { "client": { "id": "client", "observeLogMessages": { "connection": "debug" } } } ] } }, { "name": "listDatabases", "object": "client", "arguments": { "filter": {} } }, { "name": "close", "object": "client" } ], "expectLogMessages": [ { "client": "client", "messages": [ { "level": "debug", "component": "connection", "data": { "message": "Connection pool created", "serverHost": { "$$type": "string" }, "serverPort": { "$$type": [ "int", "long" ] } } }, { "level": "debug", "component": "connection", "data": { "message": "Connection pool ready", "serverHost": { "$$type": "string" }, "serverPort": { "$$type": [ "int", "long" ] } } }, { "level": "debug", "component": "connection", "data": { "message": "Connection checkout started", "serverHost": { "$$type": "string" }, "serverPort": { "$$type": [ "int", "long" ] } } }, { "level": "debug", "component": "connection", "data": { "message": "Connection created", "driverConnectionId": { "$$type": [ "int", "long" ] }, "serverHost": { "$$type": "string" }, "serverPort": { "$$type": [ "int", "long" ] } } }, { "level": "debug", "component": "connection", "data": { "message": "Connection ready", "driverConnectionId": { "$$type": [ "int", "long" ] }, "serverHost": { "$$type": "string" }, "serverPort": { "$$type": [ "int", "long" ] }, "durationMS": { "$$type": [ "double", "int", "long" ] } } }, { "level": "debug", "component": "connection", "data": { "message": "Connection checked out", "driverConnectionId": { "$$type": [ "int", "long" ] }, "serverHost": { "$$type": "string" }, "serverPort": { "$$type": [ "int", "long" ] }, "durationMS": { "$$type": [ "double", "int", "long" ] } } }, { "level": "debug", "component": "connection", "data": { "message": "Connection checked in", "driverConnectionId": { "$$type": [ "int", "long" ] }, "serverHost": { "$$type": "string" }, "serverPort": { "$$type": [ "int", "long" ] } } }, { "level": "debug", "component": "connection", "data": { "message": "Connection checkout started", "serverHost": { "$$type": "string" }, "serverPort": { "$$type": [ "int", "long" ] } } }, { "level": "debug", "component": "connection", "data": { "message": "Connection checked out", "driverConnectionId": { "$$type": [ "int", "long" ] }, "serverHost": { "$$type": "string" }, "serverPort": { "$$type": [ "int", "long" ] }, "durationMS": { "$$type": [ "double", "int", "long" ] } } }, { "level": "debug", "component": "connection", "data": { "message": "Connection checked in", "driverConnectionId": { "$$type": [ "int", "long" ] }, "serverHost": { "$$type": "string" }, "serverPort": { "$$type": [ "int", "long" ] } } }, { "level": "debug", "component": "connection", "data": { "message": "Connection closed", "driverConnectionId": { "$$type": [ "int", "long" ] }, "serverHost": { "$$type": "string" }, "serverPort": { "$$type": [ "int", "long" ] }, "reason": "Connection pool was closed" } }, { "level": "debug", "component": "connection", "data": { "message": "Connection pool closed", "serverHost": { "$$type": "string" }, "serverPort": { "$$type": [ "int", "long" ] } } } ] } ] }, { "description": "Connection checkout fails due to error establishing connection", "runOnRequirements": [ { "auth": true, "minServerVersion": "4.0" } ], "operations": [ { "name": "createEntities", "object": "testRunner", "arguments": { "entities": [ { "client": { "id": "client", "uriOptions": { "retryReads": false, "appname": "clientAppName", "heartbeatFrequencyMS": 10000 }, "observeLogMessages": { "connection": "debug" } } } ] } }, { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "saslContinue" ], "closeConnection": true, "appName": "clientAppName" } } } }, { "name": "listDatabases", "object": "client", "arguments": { "filter": {} }, "expectError": { "isClientError": true } } ], "expectLogMessages": [ { "client": "client", "messages": [ { "level": "debug", "component": "connection", "data": { "message": "Connection pool created", "serverHost": { "$$type": "string" }, "serverPort": { "$$type": [ "int", "long" ] } } }, { "level": "debug", "component": "connection", "data": { "message": "Connection pool ready", "serverHost": { "$$type": "string" }, "serverPort": { "$$type": [ "int", "long" ] } } }, { "level": "debug", "component": "connection", "data": { "message": "Connection checkout started", "serverHost": { "$$type": "string" }, "serverPort": { "$$type": [ "int", "long" ] } } }, { "level": "debug", "component": "connection", "data": { "message": "Connection created", "driverConnectionId": { "$$type": [ "int", "long" ] }, "serverHost": { "$$type": "string" }, "serverPort": { "$$type": [ "int", "long" ] } } }, { "level": "debug", "component": "connection", "data": { "message": "Connection closed", "driverConnectionId": { "$$type": [ "int", "long" ] }, "serverHost": { "$$type": "string" }, "serverPort": { "$$type": [ "int", "long" ] }, "reason": "An error occurred while using the connection", "error": { "$$exists": true } } }, { "level": "debug", "component": "connection", "data": { "message": "Connection checkout failed", "serverHost": { "$$type": "string" }, "serverPort": { "$$type": [ "int", "long" ] }, "reason": "An error occurred while trying to establish a new connection", "error": { "$$exists": true }, "durationMS": { "$$type": [ "double", "int", "long" ] } } }, { "level": "debug", "component": "connection", "data": { "message": "Connection pool cleared", "serverHost": { "$$type": "string" }, "serverPort": { "$$type": [ "int", "long" ] } } } ] } ] } ] }mongodb-mongo-python-driver-509e9b7/test/connection_logging/connection-pool-options.json000066400000000000000000000270211462766011000317550ustar00rootroot00000000000000{ "description": "connection-pool-options", "schemaVersion": "1.13", "runOnRequirements": [ { "topologies": [ "single" ] } ], "tests": [ { "description": "Options should be included in connection pool created message when specified", "operations": [ { "name": "createEntities", "object": "testRunner", "arguments": { "entities": [ { "client": { "id": "client", "observeEvents": [ "connectionReadyEvent" ], "observeLogMessages": { "connection": "debug" }, "uriOptions": { "minPoolSize": 1, "maxPoolSize": 5, "maxIdleTimeMS": 10000 } } } ] } }, { "name": "waitForEvent", "object": "testRunner", "arguments": { "client": "client", "event": { "connectionReadyEvent": {} }, "count": 1 } } ], "expectLogMessages": [ { "client": "client", "messages": [ { "level": "debug", "component": "connection", "data": { "message": "Connection pool created", "serverHost": { "$$type": "string" }, "serverPort": { "$$type": [ "int", "long" ] }, "minPoolSize": 1, "maxPoolSize": 5, "maxIdleTimeMS": 10000 } }, { "level": "debug", "component": "connection", "data": { "message": "Connection pool ready", "serverHost": { "$$type": "string" }, "serverPort": { "$$type": [ "int", "long" ] } } }, { "level": "debug", "component": "connection", "data": { "message": "Connection created", "driverConnectionId": { "$$type": [ "int", "long" ] }, "serverHost": { "$$type": "string" }, "serverPort": { "$$type": [ "int", "long" ] } } }, { "level": "debug", "component": "connection", "data": { "message": "Connection ready", "driverConnectionId": { "$$type": [ "int", "long" ] }, "serverHost": { "$$type": "string" }, "serverPort": { "$$type": [ "int", "long" ] }, "durationMS": { "$$type": [ "double", "int", "long" ] } } } ] } ] }, { "description": "maxConnecting should be included in connection pool created message when specified", "operations": [ { "name": "createEntities", "object": "testRunner", "arguments": { "entities": [ { "client": { "id": "client", "observeEvents": [ "poolReadyEvent" ], "observeLogMessages": { "connection": "debug" }, "uriOptions": { "maxConnecting": 5 } } } ] } }, { "name": "waitForEvent", "object": "testRunner", "arguments": { "client": "client", "event": { "poolReadyEvent": {} }, "count": 1 } } ], "expectLogMessages": [ { "client": "client", "messages": [ { "level": "debug", "component": "connection", "data": { "message": "Connection pool created", "serverHost": { "$$type": "string" }, "serverPort": { "$$type": [ "int", "long" ] }, "maxConnecting": 5 } }, { "level": "debug", "component": "connection", "data": { "message": "Connection pool ready", "serverHost": { "$$type": "string" }, "serverPort": { "$$type": [ "int", "long" ] } } } ] } ] }, { "description": "waitQueueTimeoutMS should be included in connection pool created message when specified", "operations": [ { "name": "createEntities", "object": "testRunner", "arguments": { "entities": [ { "client": { "id": "client", "observeEvents": [ "poolReadyEvent" ], "observeLogMessages": { "connection": "debug" }, "uriOptions": { "waitQueueTimeoutMS": 10000 } } } ] } }, { "name": "waitForEvent", "object": "testRunner", "arguments": { "client": "client", "event": { "poolReadyEvent": {} }, "count": 1 } } ], "expectLogMessages": [ { "client": "client", "messages": [ { "level": "debug", "component": "connection", "data": { "message": "Connection pool created", "serverHost": { "$$type": "string" }, "serverPort": { "$$type": [ "int", "long" ] }, "waitQueueTimeoutMS": 10000 } }, { "level": "debug", "component": "connection", "data": { "message": "Connection pool ready", "serverHost": { "$$type": "string" }, "serverPort": { "$$type": [ "int", "long" ] } } } ] } ] }, { "description": "waitQueueSize should be included in connection pool created message when specified", "operations": [ { "name": "createEntities", "object": "testRunner", "arguments": { "entities": [ { "client": { "id": "client", "observeEvents": [ "poolReadyEvent" ], "observeLogMessages": { "connection": "debug" }, "uriOptions": { "waitQueueSize": 100 } } } ] } }, { "name": "waitForEvent", "object": "testRunner", "arguments": { "client": "client", "event": { "poolReadyEvent": {} }, "count": 1 } } ], "expectLogMessages": [ { "client": "client", "messages": [ { "level": "debug", "component": "connection", "data": { "message": "Connection pool created", "serverHost": { "$$type": "string" }, "serverPort": { "$$type": [ "int", "long" ] }, "waitQueueSize": 100 } }, { "level": "debug", "component": "connection", "data": { "message": "Connection pool ready", "serverHost": { "$$type": "string" }, "serverPort": { "$$type": [ "int", "long" ] } } } ] } ] }, { "description": "waitQueueMultiple should be included in connection pool created message when specified", "operations": [ { "name": "createEntities", "object": "testRunner", "arguments": { "entities": [ { "client": { "id": "client", "observeEvents": [ "poolReadyEvent" ], "observeLogMessages": { "connection": "debug" }, "uriOptions": { "waitQueueSize": 5 } } } ] } }, { "name": "waitForEvent", "object": "testRunner", "arguments": { "client": "client", "event": { "poolReadyEvent": {} }, "count": 1 } } ], "expectLogMessages": [ { "client": "client", "messages": [ { "level": "debug", "component": "connection", "data": { "message": "Connection pool created", "serverHost": { "$$type": "string" }, "serverPort": { "$$type": [ "int", "long" ] }, "waitQueueMultiple": 5 } }, { "level": "debug", "component": "connection", "data": { "message": "Connection pool ready", "serverHost": { "$$type": "string" }, "serverPort": { "$$type": [ "int", "long" ] } } } ] } ] } ] } mongodb-mongo-python-driver-509e9b7/test/connection_monitoring/000077500000000000000000000000001462766011000250205ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/connection_monitoring/connection-must-have-id.json000066400000000000000000000016161462766011000323570ustar00rootroot00000000000000{ "version": 1, "style": "unit", "description": "must have an ID number associated with it", "operations": [ { "name": "ready" }, { "name": "checkOut" }, { "name": "checkOut" } ], "events": [ { "type": "ConnectionCheckOutStarted", "address": 42 }, { "type": "ConnectionCreated", "connectionId": 42, "address": 42 }, { "type": "ConnectionCheckedOut", "connectionId": 42, "address": 42 }, { "type": "ConnectionCheckOutStarted", "address": 42 }, { "type": "ConnectionCreated", "connectionId": 42, "address": 42 }, { "type": "ConnectionCheckedOut", "connectionId": 42, "address": 42 } ], "ignore": [ "ConnectionPoolCreated", "ConnectionPoolReady", "ConnectionPoolClosed", "ConnectionReady" ] } mongodb-mongo-python-driver-509e9b7/test/connection_monitoring/connection-must-order-ids.json000066400000000000000000000016141462766011000327300ustar00rootroot00000000000000{ "version": 1, "style": "unit", "description": "must have IDs assigned in order of creation", "operations": [ { "name": "ready" }, { "name": "checkOut" }, { "name": "checkOut" } ], "events": [ { "type": "ConnectionCheckOutStarted", "address": 42 }, { "type": "ConnectionCreated", "connectionId": 1, "address": 42 }, { "type": "ConnectionCheckedOut", "connectionId": 1, "address": 42 }, { "type": "ConnectionCheckOutStarted", "address": 42 }, { "type": "ConnectionCreated", "connectionId": 2, "address": 42 }, { "type": "ConnectionCheckedOut", "connectionId": 2, "address": 42 } ], "ignore": [ "ConnectionPoolCreated", "ConnectionPoolReady", "ConnectionPoolClosed", "ConnectionReady" ] } mongodb-mongo-python-driver-509e9b7/test/connection_monitoring/pool-checkin-destroy-closed.json000066400000000000000000000015741462766011000332330ustar00rootroot00000000000000{ "version": 1, "style": "unit", "description": "must destroy checked in connection if pool has been closed", "operations": [ { "name": "ready" }, { "name": "checkOut", "label": "conn" }, { "name": "close" }, { "name": "checkIn", "connection": "conn" } ], "events": [ { "type": "ConnectionCheckedOut", "connectionId": 1, "address": 42 }, { "type": "ConnectionPoolClosed", "address": 42 }, { "type": "ConnectionCheckedIn", "connectionId": 1, "address": 42 }, { "type": "ConnectionClosed", "connectionId": 1, "reason": "poolClosed", "address": 42 } ], "ignore": [ "ConnectionPoolCreated", "ConnectionPoolReady", "ConnectionCreated", "ConnectionReady", "ConnectionCheckOutStarted" ] } mongodb-mongo-python-driver-509e9b7/test/connection_monitoring/pool-checkin-destroy-stale.json000066400000000000000000000015571462766011000330730ustar00rootroot00000000000000{ "version": 1, "style": "unit", "description": "must destroy checked in connection if it is stale", "operations": [ { "name": "ready" }, { "name": "checkOut", "label": "conn" }, { "name": "clear" }, { "name": "checkIn", "connection": "conn" } ], "events": [ { "type": "ConnectionCheckedOut", "connectionId": 1, "address": 42 }, { "type": "ConnectionPoolCleared", "address": 42 }, { "type": "ConnectionCheckedIn", "connectionId": 1, "address": 42 }, { "type": "ConnectionClosed", "connectionId": 1, "reason": "stale", "address": 42 } ], "ignore": [ "ConnectionPoolCreated", "ConnectionPoolReady", "ConnectionCreated", "ConnectionReady", "ConnectionCheckOutStarted" ] } mongodb-mongo-python-driver-509e9b7/test/connection_monitoring/pool-checkin-make-available.json000066400000000000000000000014231462766011000331170ustar00rootroot00000000000000{ "version": 1, "style": "unit", "description": "must make valid checked in connection available", "operations": [ { "name": "ready" }, { "name": "checkOut", "label": "conn" }, { "name": "checkIn", "connection": "conn" }, { "name": "checkOut" } ], "events": [ { "type": "ConnectionCheckedOut", "connectionId": 1, "address": 42 }, { "type": "ConnectionCheckedIn", "connectionId": 1, "address": 42 }, { "type": "ConnectionCheckedOut", "connectionId": 1, "address": 42 } ], "ignore": [ "ConnectionPoolCreated", "ConnectionPoolReady", "ConnectionCreated", "ConnectionReady", "ConnectionCheckOutStarted" ] } mongodb-mongo-python-driver-509e9b7/test/connection_monitoring/pool-checkin.json000066400000000000000000000011651462766011000302710ustar00rootroot00000000000000{ "version": 1, "style": "unit", "description": "must have a method of allowing the driver to check in a connection", "operations": [ { "name": "ready" }, { "name": "checkOut", "label": "conn" }, { "name": "checkIn", "connection": "conn" } ], "events": [ { "type": "ConnectionCheckedIn", "connectionId": 42, "address": 42 } ], "ignore": [ "ConnectionPoolCreated", "ConnectionPoolReady", "ConnectionCreated", "ConnectionReady", "ConnectionClosed", "ConnectionCheckOutStarted", "ConnectionCheckedOut" ] } mongodb-mongo-python-driver-509e9b7/test/connection_monitoring/pool-checkout-connection.json000066400000000000000000000012001462766011000326150ustar00rootroot00000000000000{ "version": 1, "style": "unit", "description": "must be able to check out a connection", "operations": [ { "name": "ready" }, { "name": "checkOut" } ], "events": [ { "type": "ConnectionCheckOutStarted", "address": 42 }, { "type": "ConnectionCreated", "connectionId": 1, "address": 42 }, { "type": "ConnectionReady", "connectionId": 1, "address": 42 }, { "type": "ConnectionCheckedOut", "connectionId": 1, "address": 42 } ], "ignore": [ "ConnectionPoolReady", "ConnectionPoolCreated" ] } pool-checkout-custom-maxConnecting-is-enforced.json000066400000000000000000000026101462766011000367060ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/connection_monitoring{ "version": 1, "style": "integration", "description": "custom maxConnecting is enforced", "runOn": [ { "minServerVersion": "4.4.0" } ], "failPoint": { "configureFailPoint": "failCommand", "mode": "alwaysOn", "data": { "failCommands": [ "isMaster", "hello" ], "closeConnection": false, "blockConnection": true, "blockTimeMS": 500 } }, "poolOptions": { "maxConnecting": 1, "maxPoolSize": 2, "waitQueueTimeoutMS": 5000 }, "operations": [ { "name": "ready" }, { "name": "start", "target": "thread1" }, { "name": "start", "target": "thread2" }, { "name": "checkOut", "thread": "thread1" }, { "name": "waitForEvent", "event": "ConnectionCreated", "count": 1 }, { "name": "checkOut", "thread": "thread2" }, { "name": "waitForEvent", "event": "ConnectionReady", "count": 2 } ], "events": [ { "type": "ConnectionCreated" }, { "type": "ConnectionReady" }, { "type": "ConnectionCreated" }, { "type": "ConnectionReady" } ], "ignore": [ "ConnectionCheckOutStarted", "ConnectionCheckedIn", "ConnectionCheckedOut", "ConnectionClosed", "ConnectionPoolCreated", "ConnectionPoolReady" ] } mongodb-mongo-python-driver-509e9b7/test/connection_monitoring/pool-checkout-error-closed.json000066400000000000000000000023431462766011000330670ustar00rootroot00000000000000{ "version": 1, "style": "unit", "description": "must throw error if checkOut is called on a closed pool", "operations": [ { "name": "ready" }, { "name": "checkOut", "label": "conn1" }, { "name": "checkIn", "connection": "conn1" }, { "name": "close" }, { "name": "checkOut" } ], "error": { "type": "PoolClosedError", "message": "Attempted to check out a connection from closed connection pool" }, "events": [ { "type": "ConnectionPoolCreated", "address": 42, "options": 42 }, { "type": "ConnectionCheckOutStarted", "address": 42 }, { "type": "ConnectionCheckedOut", "address": 42, "connectionId": 42 }, { "type": "ConnectionCheckedIn", "address": 42, "connectionId": 42 }, { "type": "ConnectionPoolClosed", "address": 42 }, { "type": "ConnectionCheckOutStarted", "address": 42 }, { "type": "ConnectionCheckOutFailed", "address": 42, "reason": "poolClosed" } ], "ignore": [ "ConnectionPoolReady", "ConnectionCreated", "ConnectionReady", "ConnectionClosed" ] } pool-checkout-maxConnecting-is-enforced.json000066400000000000000000000034671462766011000354110ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/connection_monitoring{ "version": 1, "style": "integration", "description": "maxConnecting is enforced", "runOn": [ { "minServerVersion": "4.4.0" } ], "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 50 }, "data": { "failCommands": [ "isMaster", "hello" ], "closeConnection": false, "blockConnection": true, "blockTimeMS": 800 } }, "poolOptions": { "maxPoolSize": 10, "waitQueueTimeoutMS": 5000 }, "operations": [ { "name": "ready" }, { "name": "start", "target": "thread1" }, { "name": "start", "target": "thread2" }, { "name": "start", "target": "thread3" }, { "name": "checkOut", "thread": "thread1" }, { "name": "waitForEvent", "event": "ConnectionCreated", "count": 1 }, { "name": "wait", "ms": 400 }, { "name": "checkOut", "thread": "thread2" }, { "name": "checkOut", "thread": "thread3" }, { "name": "waitForEvent", "event": "ConnectionReady", "count": 3 } ], "events": [ { "type": "ConnectionCreated", "address": 42, "connectionId": 1 }, { "type": "ConnectionCreated", "address": 42 }, { "type": "ConnectionReady", "address": 42, "connectionId": 1 }, { "type": "ConnectionCreated", "address": 42 }, { "type": "ConnectionReady", "address": 42 }, { "type": "ConnectionReady", "address": 42 } ], "ignore": [ "ConnectionCheckOutStarted", "ConnectionCheckedIn", "ConnectionCheckedOut", "ConnectionClosed", "ConnectionPoolCreated", "ConnectionPoolReady" ] } pool-checkout-maxConnecting-timeout.json000066400000000000000000000035661462766011000347010ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/connection_monitoring{ "version": 1, "style": "integration", "description": "waiting on maxConnecting is limited by WaitQueueTimeoutMS", "runOn": [ { "minServerVersion": "4.4.0" } ], "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 50 }, "data": { "failCommands": [ "isMaster", "hello" ], "closeConnection": false, "blockConnection": true, "blockTimeMS": 750 } }, "poolOptions": { "maxPoolSize": 10, "waitQueueTimeoutMS": 50 }, "operations": [ { "name": "ready" }, { "name": "start", "target": "thread1" }, { "name": "checkOut", "thread": "thread1" }, { "name": "start", "target": "thread2" }, { "name": "checkOut", "thread": "thread2" }, { "name": "waitForEvent", "event": "ConnectionCreated", "count": 2 }, { "name": "start", "target": "thread3" }, { "name": "checkOut", "thread": "thread3" }, { "name": "waitForEvent", "event": "ConnectionCheckOutFailed", "count": 1 }, { "name": "waitForThread", "target": "thread3" } ], "error": { "type": "WaitQueueTimeoutError", "message": "Timed out while checking out a connection from connection pool" }, "events": [ { "type": "ConnectionCheckOutStarted", "address": 42 }, { "type": "ConnectionCheckOutStarted", "address": 42 }, { "type": "ConnectionCheckOutStarted", "address": 42 }, { "type": "ConnectionCheckOutFailed", "reason": "timeout", "address": 42 } ], "ignore": [ "ConnectionCreated", "ConnectionCheckedIn", "ConnectionCheckedOut", "ConnectionClosed", "ConnectionPoolCreated", "ConnectionPoolReady" ] } pool-checkout-minPoolSize-connection-maxConnecting.json000066400000000000000000000030361462766011000376100ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/connection_monitoring{ "version": 1, "style": "integration", "description": "threads blocked by maxConnecting check out minPoolSize connections", "runOn": [ { "minServerVersion": "4.4.0" } ], "failPoint": { "configureFailPoint": "failCommand", "mode": "alwaysOn", "data": { "failCommands": [ "isMaster", "hello" ], "closeConnection": false, "blockConnection": true, "blockTimeMS": 500 } }, "poolOptions": { "minPoolSize": 2, "maxPoolSize": 3, "waitQueueTimeoutMS": 5000 }, "operations": [ { "name": "ready" }, { "name": "start", "target": "thread1" }, { "name": "start", "target": "thread2" }, { "name": "wait", "ms": 200 }, { "name": "checkOut", "thread": "thread1" }, { "name": "waitForEvent", "event": "ConnectionCreated", "count": 2 }, { "name": "checkOut", "thread": "thread2" }, { "name": "waitForEvent", "event": "ConnectionCheckedOut", "count": 2 } ], "events": [ { "type": "ConnectionCreated", "address": 42 }, { "type": "ConnectionCreated", "address": 42 }, { "type": "ConnectionCheckedOut", "address": 42 }, { "type": "ConnectionCheckedOut", "address": 42 } ], "ignore": [ "ConnectionPoolReady", "ConnectionClosed", "ConnectionReady", "ConnectionPoolCreated", "ConnectionCheckOutStarted" ] } mongodb-mongo-python-driver-509e9b7/test/connection_monitoring/pool-checkout-multiple.json000066400000000000000000000023221462766011000323170ustar00rootroot00000000000000{ "version": 1, "style": "unit", "description": "must be able to check out multiple connections at the same time", "operations": [ { "name": "ready" }, { "name": "start", "target": "thread1" }, { "name": "start", "target": "thread2" }, { "name": "start", "target": "thread3" }, { "name": "checkOut", "thread": "thread1" }, { "name": "checkOut", "thread": "thread2" }, { "name": "checkOut", "thread": "thread3" }, { "name": "waitForThread", "target": "thread1" }, { "name": "waitForThread", "target": "thread2" }, { "name": "waitForThread", "target": "thread3" } ], "events": [ { "type": "ConnectionCheckedOut", "connectionId": 42, "address": 42 }, { "type": "ConnectionCheckedOut", "connectionId": 42, "address": 42 }, { "type": "ConnectionCheckedOut", "connectionId": 42, "address": 42 } ], "ignore": [ "ConnectionCreated", "ConnectionPoolReady", "ConnectionReady", "ConnectionPoolCreated", "ConnectionCheckOutStarted" ] } mongodb-mongo-python-driver-509e9b7/test/connection_monitoring/pool-checkout-no-idle.json000066400000000000000000000023501462766011000320140ustar00rootroot00000000000000{ "version": 1, "style": "unit", "description": "must destroy and must not check out an idle connection if found while iterating available connections", "poolOptions": { "maxIdleTimeMS": 10, "backgroundThreadIntervalMS": -1 }, "operations": [ { "name": "ready" }, { "name": "checkOut", "label": "conn" }, { "name": "checkIn", "connection": "conn" }, { "name": "wait", "ms": 50 }, { "name": "checkOut" }, { "name": "waitForEvent", "event": "ConnectionCheckedOut", "count": 2 } ], "events": [ { "type": "ConnectionPoolCreated", "address": 42, "options": 42 }, { "type": "ConnectionCheckedOut", "connectionId": 1, "address": 42 }, { "type": "ConnectionCheckedIn", "connectionId": 1, "address": 42 }, { "type": "ConnectionClosed", "connectionId": 1, "reason": "idle", "address": 42 }, { "type": "ConnectionCheckedOut", "connectionId": 2, "address": 42 } ], "ignore": [ "ConnectionReady", "ConnectionPoolReady", "ConnectionCreated", "ConnectionCheckOutStarted" ] } mongodb-mongo-python-driver-509e9b7/test/connection_monitoring/pool-checkout-no-stale.json000066400000000000000000000024541462766011000322140ustar00rootroot00000000000000{ "version": 1, "style": "unit", "description": "must destroy and must not check out a stale connection if found while iterating available connections", "poolOptions": { "backgroundThreadIntervalMS": -1 }, "operations": [ { "name": "ready" }, { "name": "checkOut", "label": "conn" }, { "name": "checkIn", "connection": "conn" }, { "name": "clear" }, { "name": "ready" }, { "name": "checkOut" }, { "name": "waitForEvent", "event": "ConnectionCheckedOut", "count": 2 } ], "events": [ { "type": "ConnectionPoolCreated", "address": 42, "options": 42 }, { "type": "ConnectionCheckedOut", "connectionId": 1, "address": 42 }, { "type": "ConnectionCheckedIn", "connectionId": 1, "address": 42 }, { "type": "ConnectionPoolCleared", "address": 42 }, { "type": "ConnectionClosed", "connectionId": 1, "reason": "stale", "address": 42 }, { "type": "ConnectionCheckedOut", "connectionId": 2, "address": 42 } ], "ignore": [ "ConnectionReady", "ConnectionPoolReady", "ConnectionCreated", "ConnectionCheckOutStarted" ] } pool-checkout-returned-connection-maxConnecting.json000066400000000000000000000041771462766011000371770ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/connection_monitoring{ "version": 1, "style": "integration", "description": "threads blocked by maxConnecting check out returned connections", "runOn": [ { "minServerVersion": "4.4.0" } ], "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 50 }, "data": { "failCommands": [ "isMaster", "hello" ], "closeConnection": false, "blockConnection": true, "blockTimeMS": 750 } }, "poolOptions": { "maxPoolSize": 10, "waitQueueTimeoutMS": 5000 }, "operations": [ { "name": "ready" }, { "name": "checkOut", "label": "conn0" }, { "name": "start", "target": "thread1" }, { "name": "checkOut", "thread": "thread1" }, { "name": "start", "target": "thread2" }, { "name": "checkOut", "thread": "thread2" }, { "name": "start", "target": "thread3" }, { "name": "checkOut", "thread": "thread3" }, { "name": "waitForEvent", "event": "ConnectionCheckOutStarted", "count": 4 }, { "name": "wait", "ms": 100 }, { "name": "checkIn", "connection": "conn0" }, { "name": "waitForEvent", "event": "ConnectionCheckedOut", "count": 4 } ], "events": [ { "type": "ConnectionCreated", "address": 42, "connectionId": 1 }, { "type": "ConnectionCheckedOut", "address": 42 }, { "type": "ConnectionCreated", "address": 42 }, { "type": "ConnectionCreated", "address": 42 }, { "type": "ConnectionCheckedIn", "connectionId": 1, "address": 42 }, { "type": "ConnectionCheckedOut", "connectionId": 1, "address": 42 }, { "type": "ConnectionCheckedOut", "address": 42 }, { "type": "ConnectionCheckedOut", "address": 42 } ], "ignore": [ "ConnectionPoolReady", "ConnectionClosed", "ConnectionReady", "ConnectionPoolCreated", "ConnectionCheckOutStarted" ] } mongodb-mongo-python-driver-509e9b7/test/connection_monitoring/pool-clear-clears-waitqueue.json000066400000000000000000000034551462766011000332350ustar00rootroot00000000000000{ "version": 1, "style": "unit", "description": "clearing pool clears the WaitQueue", "poolOptions": { "maxPoolSize": 1, "waitQueueTimeoutMS": 30000 }, "operations": [ { "name": "ready" }, { "name": "checkOut" }, { "name": "start", "target": "thread1" }, { "name": "checkOut", "thread": "thread1" }, { "name": "start", "target": "thread2" }, { "name": "checkOut", "thread": "thread2" }, { "name": "start", "target": "thread3" }, { "name": "checkOut", "thread": "thread3" }, { "name": "waitForEvent", "event": "ConnectionCheckOutStarted", "count": 4 }, { "name": "clear" }, { "name": "waitForEvent", "event": "ConnectionCheckOutFailed", "count": 3, "timeout": 1000 } ], "events": [ { "type": "ConnectionCheckOutStarted", "address": 42 }, { "type": "ConnectionCheckedOut", "address": 42 }, { "type": "ConnectionCheckOutStarted", "address": 42 }, { "type": "ConnectionCheckOutStarted", "address": 42 }, { "type": "ConnectionCheckOutStarted", "address": 42 }, { "type": "ConnectionCheckOutFailed", "reason": "connectionError", "address": 42 }, { "type": "ConnectionCheckOutFailed", "reason": "connectionError", "address": 42 }, { "type": "ConnectionCheckOutFailed", "reason": "connectionError", "address": 42 } ], "ignore": [ "ConnectionPoolReady", "ConnectionPoolCleared", "ConnectionPoolCreated", "ConnectionCreated", "ConnectionReady", "ConnectionCheckedIn", "ConnectionClosed" ] } pool-clear-interrupting-pending-connections.json000066400000000000000000000026031462766011000363640ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/connection_monitoring{ "version": 1, "style": "integration", "description": "clear with interruptInUseConnections = true closes pending connections", "runOn": [ { "minServerVersion": "4.9.0" } ], "failPoint": { "configureFailPoint": "failCommand", "mode": "alwaysOn", "data": { "failCommands": [ "isMaster", "hello" ], "closeConnection": false, "blockConnection": true, "blockTimeMS": 10000 } }, "poolOptions": { "minPoolSize": 0 }, "operations": [ { "name": "ready" }, { "name": "start", "target": "thread1" }, { "name": "checkOut", "thread": "thread1" }, { "name": "waitForEvent", "event": "ConnectionCreated", "count": 1 }, { "name": "clear", "interruptInUseConnections": true }, { "name": "waitForEvent", "event": "ConnectionCheckOutFailed", "count": 1 } ], "events": [ { "type": "ConnectionCheckOutStarted" }, { "type": "ConnectionCreated" }, { "type": "ConnectionPoolCleared", "interruptInUseConnections": true }, { "type": "ConnectionClosed" }, { "type": "ConnectionCheckOutFailed" } ], "ignore": [ "ConnectionCheckedIn", "ConnectionCheckedOut", "ConnectionPoolCreated", "ConnectionPoolReady" ] } mongodb-mongo-python-driver-509e9b7/test/connection_monitoring/pool-clear-min-size.json000066400000000000000000000021531462766011000315020ustar00rootroot00000000000000{ "version": 1, "style": "unit", "description": "pool clear halts background minPoolSize establishments", "poolOptions": { "minPoolSize": 1, "backgroundThreadIntervalMS": 50 }, "operations": [ { "name": "ready" }, { "name": "waitForEvent", "event": "ConnectionReady", "count": 1 }, { "name": "clear" }, { "name": "wait", "ms": 200 }, { "name": "ready" }, { "name": "waitForEvent", "event": "ConnectionReady", "count": 2 } ], "events": [ { "type": "ConnectionPoolReady", "address": 42 }, { "type": "ConnectionCreated", "address": 42 }, { "type": "ConnectionReady", "address": 42 }, { "type": "ConnectionPoolCleared", "address": 42 }, { "type": "ConnectionPoolReady", "address": 42 }, { "type": "ConnectionCreated", "address": 42 }, { "type": "ConnectionReady", "address": 42 } ], "ignore": [ "ConnectionPoolCreated", "ConnectionClosed" ] } mongodb-mongo-python-driver-509e9b7/test/connection_monitoring/pool-clear-paused.json000066400000000000000000000007221462766011000312300ustar00rootroot00000000000000{ "version": 1, "style": "unit", "description": "clearing a paused pool emits no events", "operations": [ { "name": "clear" }, { "name": "ready" }, { "name": "clear" }, { "name": "clear" } ], "events": [ { "type": "ConnectionPoolReady", "address": 42 }, { "type": "ConnectionPoolCleared", "address": 42 } ], "ignore": [ "ConnectionPoolCreated" ] } mongodb-mongo-python-driver-509e9b7/test/connection_monitoring/pool-clear-ready.json000066400000000000000000000022421462766011000310520ustar00rootroot00000000000000{ "version": 1, "style": "unit", "description": "after clear, cannot check out connections until pool ready", "operations": [ { "name": "ready" }, { "name": "checkOut" }, { "name": "clear" }, { "name": "start", "target": "thread1" }, { "name": "checkOut", "thread": "thread1" }, { "name": "waitForEvent", "event": "ConnectionCheckOutFailed", "count": 1 }, { "name": "ready" }, { "name": "checkOut" } ], "events": [ { "type": "ConnectionPoolReady", "address": 42 }, { "type": "ConnectionCheckedOut", "address": 42, "connectionId": 42 }, { "type": "ConnectionPoolCleared", "address": 42 }, { "type": "ConnectionCheckOutFailed", "address": 42, "reason": "connectionError" }, { "type": "ConnectionPoolReady", "address": 42 }, { "type": "ConnectionCheckedOut", "address": 42 } ], "ignore": [ "ConnectionPoolCreated", "ConnectionReady", "ConnectionCheckOutStarted", "ConnectionCreated" ] } pool-clear-schedule-run-interruptInUseConnections-false.json000066400000000000000000000030071462766011000405560ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/connection_monitoring{ "version": 1, "style": "unit", "description": "Pool clear SHOULD schedule the next background thread run immediately (interruptInUseConnections = false)", "poolOptions": { "backgroundThreadIntervalMS": 10000 }, "operations": [ { "name": "ready" }, { "name": "checkOut" }, { "name": "checkOut", "label": "conn" }, { "name": "checkIn", "connection": "conn" }, { "name": "clear", "interruptInUseConnections": false }, { "name": "waitForEvent", "event": "ConnectionPoolCleared", "count": 1, "timeout": 1000 }, { "name": "waitForEvent", "event": "ConnectionClosed", "count": 1, "timeout": 1000 }, { "name": "close" } ], "events": [ { "type": "ConnectionCheckedOut", "connectionId": 1, "address": 42 }, { "type": "ConnectionCheckedOut", "connectionId": 2, "address": 42 }, { "type": "ConnectionCheckedIn", "connectionId": 2, "address": 42 }, { "type": "ConnectionPoolCleared", "interruptInUseConnections": false }, { "type": "ConnectionClosed", "connectionId": 2, "reason": "stale", "address": 42 }, { "type": "ConnectionPoolClosed", "address": 42 } ], "ignore": [ "ConnectionCreated", "ConnectionPoolReady", "ConnectionReady", "ConnectionCheckOutStarted", "ConnectionPoolCreated" ] } mongodb-mongo-python-driver-509e9b7/test/connection_monitoring/pool-close-destroy-conns.json000066400000000000000000000016351462766011000326010ustar00rootroot00000000000000{ "version": 1, "style": "unit", "description": "When a pool is closed, it MUST first destroy all available connections in that pool", "operations": [ { "name": "ready" }, { "name": "checkOut" }, { "name": "checkOut", "label": "conn" }, { "name": "checkOut" }, { "name": "checkIn", "connection": "conn" }, { "name": "close" } ], "events": [ { "type": "ConnectionCheckedIn", "connectionId": 2, "address": 42 }, { "type": "ConnectionClosed", "connectionId": 2, "reason": "poolClosed", "address": 42 }, { "type": "ConnectionPoolClosed", "address": 42 } ], "ignore": [ "ConnectionCreated", "ConnectionPoolReady", "ConnectionReady", "ConnectionPoolCreated", "ConnectionCheckOutStarted", "ConnectionCheckedOut" ] } mongodb-mongo-python-driver-509e9b7/test/connection_monitoring/pool-close.json000066400000000000000000000005171462766011000277720ustar00rootroot00000000000000{ "version": 1, "style": "unit", "description": "must be able to manually close a pool", "operations": [ { "name": "close" } ], "events": [ { "type": "ConnectionPoolCreated", "address": 42, "options": 42 }, { "type": "ConnectionPoolClosed", "address": 42 } ] } mongodb-mongo-python-driver-509e9b7/test/connection_monitoring/pool-create-max-size.json000066400000000000000000000044671462766011000316730ustar00rootroot00000000000000{ "version": 1, "style": "unit", "description": "must never exceed maxPoolSize total connections", "poolOptions": { "maxPoolSize": 3 }, "operations": [ { "name": "ready" }, { "name": "checkOut", "label": "conn1" }, { "name": "checkOut" }, { "name": "checkOut", "label": "conn2" }, { "name": "checkIn", "connection": "conn2" }, { "name": "checkOut" }, { "name": "start", "target": "thread1" }, { "name": "checkOut", "thread": "thread1" }, { "name": "waitForEvent", "event": "ConnectionCheckOutStarted", "count": 5 }, { "name": "checkIn", "connection": "conn1" }, { "name": "waitForThread", "target": "thread1" } ], "events": [ { "type": "ConnectionPoolCreated", "address": 42, "options": 42 }, { "type": "ConnectionCheckOutStarted", "address": 42 }, { "type": "ConnectionCreated", "connectionId": 42, "address": 42 }, { "type": "ConnectionCheckedOut", "connectionId": 42, "address": 42 }, { "type": "ConnectionCheckOutStarted", "address": 42 }, { "type": "ConnectionCreated", "connectionId": 42, "address": 42 }, { "type": "ConnectionCheckedOut", "connectionId": 42, "address": 42 }, { "type": "ConnectionCheckOutStarted", "address": 42 }, { "type": "ConnectionCreated", "connectionId": 42, "address": 42 }, { "type": "ConnectionCheckedOut", "connectionId": 42, "address": 42 }, { "type": "ConnectionCheckedIn", "connectionId": 42, "address": 42 }, { "type": "ConnectionCheckOutStarted", "address": 42 }, { "type": "ConnectionCheckedOut", "connectionId": 42, "address": 42 }, { "type": "ConnectionCheckOutStarted", "address": 42 }, { "type": "ConnectionCheckedIn", "connectionId": 42, "address": 42 }, { "type": "ConnectionCheckedOut", "connectionId": 42, "address": 42 } ], "ignore": [ "ConnectionReady", "ConnectionPoolReady" ] } mongodb-mongo-python-driver-509e9b7/test/connection_monitoring/pool-create-min-size-error.json000066400000000000000000000022261462766011000330070ustar00rootroot00000000000000{ "version": 1, "style": "integration", "description": "error during minPoolSize population clears pool", "runOn": [ { "minServerVersion": "4.9.0" } ], "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 50 }, "data": { "failCommands": [ "isMaster", "hello" ], "closeConnection": true, "appName": "poolCreateMinSizeErrorTest" } }, "poolOptions": { "minPoolSize": 1, "backgroundThreadIntervalMS": 50, "appName": "poolCreateMinSizeErrorTest" }, "operations": [ { "name": "ready" }, { "name": "waitForEvent", "event": "ConnectionPoolCleared", "count": 1 }, { "name": "wait", "ms": 200 } ], "events": [ { "type": "ConnectionPoolReady", "address": 42 }, { "type": "ConnectionCreated", "address": 42 }, { "type": "ConnectionClosed", "address": 42, "connectionId": 42, "reason": "error" }, { "type": "ConnectionPoolCleared", "address": 42 } ], "ignore": [ "ConnectionPoolCreated" ] } mongodb-mongo-python-driver-509e9b7/test/connection_monitoring/pool-create-min-size.json000066400000000000000000000022031462766011000316530ustar00rootroot00000000000000{ "version": 1, "style": "unit", "description": "must be able to start a pool with minPoolSize connections", "poolOptions": { "minPoolSize": 3 }, "operations": [ { "name": "wait", "ms": 200 }, { "name": "ready" }, { "name": "waitForEvent", "event": "ConnectionCreated", "count": 3 }, { "name": "waitForEvent", "event": "ConnectionReady", "count": 3 }, { "name": "checkOut" } ], "events": [ { "type": "ConnectionPoolCreated", "address": 42, "options": 42 }, { "type": "ConnectionPoolReady", "address": 42 }, { "type": "ConnectionCreated", "connectionId": 42, "address": 42 }, { "type": "ConnectionCreated", "connectionId": 42, "address": 42 }, { "type": "ConnectionCreated", "connectionId": 42, "address": 42 }, { "type": "ConnectionCheckedOut", "connectionId": 42, "address": 42 } ], "ignore": [ "ConnectionReady", "ConnectionClosed", "ConnectionCheckOutStarted" ] } mongodb-mongo-python-driver-509e9b7/test/connection_monitoring/pool-create-with-options.json000066400000000000000000000011221462766011000325630ustar00rootroot00000000000000{ "version": 1, "style": "unit", "description": "must be able to start a pool with various options set", "poolOptions": { "maxPoolSize": 50, "minPoolSize": 5, "maxIdleTimeMS": 100 }, "operations": [ { "name": "waitForEvent", "event": "ConnectionPoolCreated", "count": 1 } ], "events": [ { "type": "ConnectionPoolCreated", "address": 42, "options": { "maxPoolSize": 50, "minPoolSize": 5, "maxIdleTimeMS": 100 } } ], "ignore": [ "ConnectionCreated", "ConnectionReady" ] } mongodb-mongo-python-driver-509e9b7/test/connection_monitoring/pool-create.json000066400000000000000000000005011462766011000301210ustar00rootroot00000000000000{ "version": 1, "style": "unit", "description": "must be able to create a pool", "operations": [ { "name": "waitForEvent", "event": "ConnectionPoolCreated", "count": 1 } ], "events": [ { "type": "ConnectionPoolCreated", "address": 42, "options": 42 } ] } mongodb-mongo-python-driver-509e9b7/test/connection_monitoring/pool-ready-ready.json000066400000000000000000000010721462766011000310700ustar00rootroot00000000000000{ "version": 1, "style": "unit", "description": "readying a ready pool emits no events", "operations": [ { "name": "ready" }, { "name": "ready" }, { "name": "ready" }, { "name": "clear" }, { "name": "ready" } ], "events": [ { "type": "ConnectionPoolReady", "address": 42 }, { "type": "ConnectionPoolCleared", "address": 42 }, { "type": "ConnectionPoolReady", "address": 42 } ], "ignore": [ "ConnectionPoolCreated" ] } mongodb-mongo-python-driver-509e9b7/test/connection_monitoring/pool-ready.json000066400000000000000000000017271462766011000277750ustar00rootroot00000000000000{ "version": 1, "style": "unit", "description": "pool starts as cleared and becomes ready", "operations": [ { "name": "start", "target": "thread1" }, { "name": "checkOut", "thread": "thread1" }, { "name": "waitForEvent", "event": "ConnectionCheckOutFailed", "count": 1 }, { "name": "ready" }, { "name": "checkOut" } ], "events": [ { "type": "ConnectionCheckOutStarted", "address": 42 }, { "type": "ConnectionCheckOutFailed", "reason": "connectionError", "address": 42 }, { "type": "ConnectionPoolReady", "address": 42 }, { "type": "ConnectionCheckOutStarted", "address": 42 }, { "type": "ConnectionCreated", "address": 42 }, { "type": "ConnectionCheckedOut", "address": 42 } ], "ignore": [ "ConnectionPoolCreated", "ConnectionReady" ] } mongodb-mongo-python-driver-509e9b7/test/connection_monitoring/wait-queue-timeout.json000066400000000000000000000026361462766011000314740ustar00rootroot00000000000000{ "version": 1, "style": "unit", "description": "must aggressively timeout threads enqueued longer than waitQueueTimeoutMS", "poolOptions": { "maxPoolSize": 1, "waitQueueTimeoutMS": 50 }, "operations": [ { "name": "ready" }, { "name": "checkOut", "label": "conn0" }, { "name": "start", "target": "thread1" }, { "name": "checkOut", "thread": "thread1" }, { "name": "waitForEvent", "event": "ConnectionCheckOutFailed", "count": 1 }, { "name": "checkIn", "connection": "conn0" }, { "name": "waitForThread", "target": "thread1" } ], "error": { "type": "WaitQueueTimeoutError", "message": "Timed out while checking out a connection from connection pool" }, "events": [ { "type": "ConnectionCheckOutStarted", "address": 42 }, { "type": "ConnectionCheckedOut", "connectionId": 42, "address": 42 }, { "type": "ConnectionCheckOutStarted", "address": 42 }, { "type": "ConnectionCheckOutFailed", "reason": "timeout", "address": 42 }, { "type": "ConnectionCheckedIn", "connectionId": 42, "address": 42 } ], "ignore": [ "ConnectionCreated", "ConnectionReady", "ConnectionClosed", "ConnectionPoolCreated", "ConnectionPoolReady" ] } mongodb-mongo-python-driver-509e9b7/test/connection_string/000077500000000000000000000000001462766011000241415ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/connection_string/test/000077500000000000000000000000001462766011000251205ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/connection_string/test/invalid-uris.json000066400000000000000000000161531462766011000304270ustar00rootroot00000000000000{ "tests": [ { "description": "Empty string", "uri": "", "valid": false, "warning": null, "hosts": null, "auth": null, "options": null }, { "description": "Invalid scheme", "uri": "mongo://localhost:27017", "valid": false, "warning": null, "hosts": null, "auth": null, "options": null }, { "description": "Missing host", "uri": "mongodb://", "valid": false, "warning": null, "hosts": null, "auth": null, "options": null }, { "description": "Double colon in host identifier", "uri": "mongodb://localhost::27017", "valid": false, "warning": null, "hosts": null, "auth": null, "options": null }, { "description": "Double colon in host identifier and trailing slash", "uri": "mongodb://localhost::27017/", "valid": false, "warning": null, "hosts": null, "auth": null, "options": null }, { "description": "Double colon in host identifier with missing host and port", "uri": "mongodb://::", "valid": false, "warning": null, "hosts": null, "auth": null, "options": null }, { "description": "Double colon in host identifier with missing port", "uri": "mongodb://localhost,localhost::", "valid": false, "warning": null, "hosts": null, "auth": null, "options": null }, { "description": "Double colon in host identifier and second host", "uri": "mongodb://localhost::27017,abc", "valid": false, "warning": null, "hosts": null, "auth": null, "options": null }, { "description": "Invalid port (negative number) with hostname", "uri": "mongodb://localhost:-1", "valid": false, "warning": null, "hosts": null, "auth": null, "options": null }, { "description": "Invalid port (zero) with hostname", "uri": "mongodb://localhost:0/", "valid": false, "warning": null, "hosts": null, "auth": null, "options": null }, { "description": "Invalid port (positive number) with hostname", "uri": "mongodb://localhost:65536", "valid": false, "warning": null, "hosts": null, "auth": null, "options": null }, { "description": "Invalid port (positive number) with hostname and trailing slash", "uri": "mongodb://localhost:65536/", "valid": false, "warning": null, "hosts": null, "auth": null, "options": null }, { "description": "Invalid port (non-numeric string) with hostname", "uri": "mongodb://localhost:foo", "valid": false, "warning": null, "hosts": null, "auth": null, "options": null }, { "description": "Invalid port (negative number) with IP literal", "uri": "mongodb://[::1]:-1", "valid": false, "warning": null, "hosts": null, "auth": null, "options": null }, { "description": "Invalid port (zero) with IP literal", "uri": "mongodb://[::1]:0/", "valid": false, "warning": null, "hosts": null, "auth": null, "options": null }, { "description": "Invalid port (positive number) with IP literal", "uri": "mongodb://[::1]:65536", "valid": false, "warning": null, "hosts": null, "auth": null, "options": null }, { "description": "Invalid port (positive number) with IP literal and trailing slash", "uri": "mongodb://[::1]:65536/", "valid": false, "warning": null, "hosts": null, "auth": null, "options": null }, { "description": "Invalid port (non-numeric string) with IP literal", "uri": "mongodb://[::1]:foo", "valid": false, "warning": null, "hosts": null, "auth": null, "options": null }, { "description": "Incomplete key value pair for option", "uri": "mongodb://example.com/?w", "valid": false, "warning": null, "hosts": null, "auth": null, "options": null }, { "description": "Username with password containing an unescaped colon", "uri": "mongodb://alice:foo:bar@127.0.0.1", "valid": false, "warning": null, "hosts": null, "auth": null, "options": null }, { "description": "Username containing an unescaped at-sign", "uri": "mongodb://alice@@127.0.0.1", "valid": false, "warning": null, "hosts": null, "auth": null, "options": null }, { "description": "Username with password containing an unescaped at-sign", "uri": "mongodb://alice@foo:bar@127.0.0.1", "valid": false, "warning": null, "hosts": null, "auth": null, "options": null }, { "description": "Username containing an unescaped slash", "uri": "mongodb://alice/@localhost/db", "valid": false, "warning": null, "hosts": null, "auth": null, "options": null }, { "description": "Username containing unescaped slash with password", "uri": "mongodb://alice/bob:foo@localhost/db", "valid": false, "warning": null, "hosts": null, "auth": null, "options": null }, { "description": "Username with password containing an unescaped slash", "uri": "mongodb://alice:foo/bar@localhost/db", "valid": false, "warning": null, "hosts": null, "auth": null, "options": null }, { "description": "Host with unescaped slash", "uri": "mongodb:///tmp/mongodb-27017.sock/", "valid": false, "warning": null, "hosts": null, "auth": null, "options": null }, { "description": "mongodb+srv with multiple service names", "uri": "mongodb+srv://test5.test.mongodb.com,test6.test.mongodb.com", "valid": false, "warning": null, "hosts": null, "auth": null, "options": null }, { "description": "mongodb+srv with port number", "uri": "mongodb+srv://test7.test.mongodb.com:27018", "valid": false, "warning": null, "hosts": null, "auth": null, "options": null }, { "description": "Username with password containing an unescaped percent sign", "uri": "mongodb://alice%foo:bar@127.0.0.1", "valid": false, "warning": null, "hosts": null, "auth": null, "options": null }, { "description": "Username with password containing an unescaped percent sign and an escaped one", "uri": "mongodb://user%20%:password@localhost", "valid": false, "warning": null, "hosts": null, "auth": null, "options": null }, { "description": "Username with password containing an unescaped percent sign (non hex digit)", "uri": "mongodb://user%w:password@localhost", "valid": false, "warning": null, "hosts": null, "auth": null, "options": null } ] } mongodb-mongo-python-driver-509e9b7/test/connection_string/test/valid-auth.json000066400000000000000000000172401462766011000300550ustar00rootroot00000000000000{ "tests": [ { "description": "User info for single IPv4 host without database", "uri": "mongodb://alice:foo@127.0.0.1", "valid": true, "warning": false, "hosts": [ { "type": "ipv4", "host": "127.0.0.1", "port": null } ], "auth": { "username": "alice", "password": "foo", "db": null }, "options": null }, { "description": "User info for single IPv4 host with database", "uri": "mongodb://alice:foo@127.0.0.1/test", "valid": true, "warning": false, "hosts": [ { "type": "ipv4", "host": "127.0.0.1", "port": null } ], "auth": { "username": "alice", "password": "foo", "db": "test" }, "options": null }, { "description": "User info for single IP literal host without database", "uri": "mongodb://bob:bar@[::1]:27018", "valid": true, "warning": false, "hosts": [ { "type": "ip_literal", "host": "::1", "port": 27018 } ], "auth": { "username": "bob", "password": "bar", "db": null }, "options": null }, { "description": "User info for single IP literal host with database", "uri": "mongodb://bob:bar@[::1]:27018/admin", "valid": true, "warning": false, "hosts": [ { "type": "ip_literal", "host": "::1", "port": 27018 } ], "auth": { "username": "bob", "password": "bar", "db": "admin" }, "options": null }, { "description": "User info for single hostname without database", "uri": "mongodb://eve:baz@example.com", "valid": true, "warning": false, "hosts": [ { "type": "hostname", "host": "example.com", "port": null } ], "auth": { "username": "eve", "password": "baz", "db": null }, "options": null }, { "description": "User info for single hostname with database", "uri": "mongodb://eve:baz@example.com/db2", "valid": true, "warning": false, "hosts": [ { "type": "hostname", "host": "example.com", "port": null } ], "auth": { "username": "eve", "password": "baz", "db": "db2" }, "options": null }, { "description": "User info for multiple hosts without database", "uri": "mongodb://alice:secret@127.0.0.1,example.com:27018", "valid": true, "warning": false, "hosts": [ { "type": "ipv4", "host": "127.0.0.1", "port": null }, { "type": "hostname", "host": "example.com", "port": 27018 } ], "auth": { "username": "alice", "password": "secret", "db": null }, "options": null }, { "description": "User info for multiple hosts with database", "uri": "mongodb://alice:secret@example.com,[::1]:27019/admin", "valid": true, "warning": false, "hosts": [ { "type": "hostname", "host": "example.com", "port": null }, { "type": "ip_literal", "host": "::1", "port": 27019 } ], "auth": { "username": "alice", "password": "secret", "db": "admin" }, "options": null }, { "description": "Username without password", "uri": "mongodb://alice@127.0.0.1", "valid": true, "warning": false, "hosts": [ { "type": "ipv4", "host": "127.0.0.1", "port": null } ], "auth": { "username": "alice", "password": null, "db": null }, "options": null }, { "description": "Username with empty password", "uri": "mongodb://alice:@127.0.0.1", "valid": true, "warning": false, "hosts": [ { "type": "ipv4", "host": "127.0.0.1", "port": null } ], "auth": { "username": "alice", "password": "", "db": null }, "options": null }, { "description": "Escaped username and database without password", "uri": "mongodb://%40l%3Ace%2F%3D@example.com/my%3Ddb", "valid": true, "warning": false, "hosts": [ { "type": "hostname", "host": "example.com", "port": null } ], "auth": { "username": "@l:ce/=", "password": null, "db": "my=db" }, "options": null }, { "description": "Escaped user info and database (MONGODB-CR)", "uri": "mongodb://%24am:f%3Azzb%40z%2Fz%3D@127.0.0.1/admin%3F?authMechanism=MONGODB-CR", "valid": true, "warning": false, "hosts": [ { "type": "ipv4", "host": "127.0.0.1", "port": null } ], "auth": { "username": "$am", "password": "f:zzb@z/z=", "db": "admin?" }, "options": { "authmechanism": "MONGODB-CR" } }, { "description": "Subdelimiters in user/pass don't need escaping (MONGODB-CR)", "uri": "mongodb://!$&'()*+,;=:!$&'()*+,;=@127.0.0.1/admin?authMechanism=MONGODB-CR", "valid": true, "warning": false, "hosts": [ { "type": "ipv4", "host": "127.0.0.1", "port": null } ], "auth": { "username": "!$&'()*+,;=", "password": "!$&'()*+,;=", "db": "admin" }, "options": { "authmechanism": "MONGODB-CR" } }, { "description": "Escaped username (MONGODB-X509)", "uri": "mongodb://CN%3DmyName%2COU%3DmyOrgUnit%2CO%3DmyOrg%2CL%3DmyLocality%2CST%3DmyState%2CC%3DmyCountry@localhost/?authMechanism=MONGODB-X509", "valid": true, "warning": false, "hosts": [ { "type": "hostname", "host": "localhost", "port": null } ], "auth": { "username": "CN=myName,OU=myOrgUnit,O=myOrg,L=myLocality,ST=myState,C=myCountry", "password": null, "db": null }, "options": { "authmechanism": "MONGODB-X509" } }, { "description": "Escaped username (GSSAPI)", "uri": "mongodb://user%40EXAMPLE.COM:secret@localhost/?authMechanismProperties=SERVICE_NAME:other,CANONICALIZE_HOST_NAME:true&authMechanism=GSSAPI", "valid": true, "warning": false, "hosts": [ { "type": "hostname", "host": "localhost", "port": null } ], "auth": { "username": "user@EXAMPLE.COM", "password": "secret", "db": null }, "options": { "authmechanism": "GSSAPI", "authmechanismproperties": { "SERVICE_NAME": "other", "CANONICALIZE_HOST_NAME": true } } }, { "description": "At-signs in options aren't part of the userinfo", "uri": "mongodb://alice:secret@example.com/admin?replicaset=my@replicaset", "valid": true, "warning": false, "hosts": [ { "type": "hostname", "host": "example.com", "port": null } ], "auth": { "username": "alice", "password": "secret", "db": "admin" }, "options": { "replicaset": "my@replicaset" } } ] } mongodb-mongo-python-driver-509e9b7/test/connection_string/test/valid-db-with-dotted-name.json000066400000000000000000000047461462766011000326600ustar00rootroot00000000000000{ "tests": [ { "description": "Multiple Unix domain sockets and auth DB resembling a socket (relative path)", "uri": "mongodb://rel%2Fmongodb-27017.sock,rel%2Fmongodb-27018.sock/admin.sock", "valid": true, "warning": false, "hosts": [ { "type": "unix", "host": "rel/mongodb-27017.sock", "port": null }, { "type": "unix", "host": "rel/mongodb-27018.sock", "port": null } ], "auth": { "username": null, "password": null, "db": "admin.sock" }, "options": null }, { "description": "Multiple Unix domain sockets with auth DB resembling a path (relative path)", "uri": "mongodb://rel%2Fmongodb-27017.sock,rel%2Fmongodb-27018.sock/admin.shoe", "valid": true, "warning": false, "hosts": [ { "type": "unix", "host": "rel/mongodb-27017.sock", "port": null }, { "type": "unix", "host": "rel/mongodb-27018.sock", "port": null } ], "auth": { "username": null, "password": null, "db": "admin.shoe" }, "options": null }, { "description": "Multiple Unix domain sockets and auth DB resembling a socket (absolute path)", "uri": "mongodb://%2Ftmp%2Fmongodb-27017.sock,%2Ftmp%2Fmongodb-27018.sock/admin.sock", "valid": true, "warning": false, "hosts": [ { "type": "unix", "host": "/tmp/mongodb-27017.sock", "port": null }, { "type": "unix", "host": "/tmp/mongodb-27018.sock", "port": null } ], "auth": { "username": null, "password": null, "db": "admin.sock" }, "options": null }, { "description": "Multiple Unix domain sockets with auth DB resembling a path (absolute path)", "uri": "mongodb://%2Ftmp%2Fmongodb-27017.sock,%2Ftmp%2Fmongodb-27018.sock/admin.shoe", "valid": true, "warning": false, "hosts": [ { "type": "unix", "host": "/tmp/mongodb-27017.sock", "port": null }, { "type": "unix", "host": "/tmp/mongodb-27018.sock", "port": null } ], "auth": { "username": null, "password": null, "db": "admin.shoe" }, "options": null } ] } mongodb-mongo-python-driver-509e9b7/test/connection_string/test/valid-host_identifiers.json000066400000000000000000000063421462766011000324570ustar00rootroot00000000000000{ "tests": [ { "description": "Single IPv4 host without port", "uri": "mongodb://127.0.0.1", "valid": true, "warning": false, "hosts": [ { "type": "ipv4", "host": "127.0.0.1", "port": null } ], "auth": null, "options": null }, { "description": "Single IPv4 host with port", "uri": "mongodb://127.0.0.1:27018", "valid": true, "warning": false, "hosts": [ { "type": "ipv4", "host": "127.0.0.1", "port": 27018 } ], "auth": null, "options": null }, { "description": "Single IP literal host without port", "uri": "mongodb://[::1]", "valid": true, "warning": false, "hosts": [ { "type": "ip_literal", "host": "::1", "port": null } ], "auth": null, "options": null }, { "description": "Single IP literal host with port", "uri": "mongodb://[::1]:27019", "valid": true, "warning": false, "hosts": [ { "type": "ip_literal", "host": "::1", "port": 27019 } ], "auth": null, "options": null }, { "description": "Single hostname without port", "uri": "mongodb://example.com", "valid": true, "warning": false, "hosts": [ { "type": "hostname", "host": "example.com", "port": null } ], "auth": null, "options": null }, { "description": "Single hostname with port", "uri": "mongodb://example.com:27020", "valid": true, "warning": false, "hosts": [ { "type": "hostname", "host": "example.com", "port": 27020 } ], "auth": null, "options": null }, { "description": "Single hostname (resembling IPv4) without port", "uri": "mongodb://256.0.0.1", "valid": true, "warning": false, "hosts": [ { "type": "hostname", "host": "256.0.0.1", "port": null } ], "auth": null, "options": null }, { "description": "Multiple hosts (mixed formats)", "uri": "mongodb://127.0.0.1,[::1]:27018,example.com:27019", "valid": true, "warning": false, "hosts": [ { "type": "ipv4", "host": "127.0.0.1", "port": null }, { "type": "ip_literal", "host": "::1", "port": 27018 }, { "type": "hostname", "host": "example.com", "port": 27019 } ], "auth": null, "options": null }, { "description": "UTF-8 hosts", "uri": "mongodb://bücher.example.com,umläut.example.com/", "valid": true, "warning": false, "hosts": [ { "type": "hostname", "host": "bücher.example.com", "port": null }, { "type": "hostname", "host": "umläut.example.com", "port": null } ], "auth": null, "options": null } ] } mongodb-mongo-python-driver-509e9b7/test/connection_string/test/valid-options.json000066400000000000000000000016131462766011000306040ustar00rootroot00000000000000{ "tests": [ { "description": "Option names are normalized to lowercase", "uri": "mongodb://alice:secret@example.com/admin?AUTHMechanism=MONGODB-CR", "valid": true, "warning": false, "hosts": [ { "type": "hostname", "host": "example.com", "port": null } ], "auth": { "username": "alice", "password": "secret", "db": "admin" }, "options": { "authmechanism": "MONGODB-CR" } }, { "description": "Missing delimiting slash between hosts and options", "uri": "mongodb://example.com?tls=true", "valid": true, "warning": false, "hosts": [ { "type": "hostname", "host": "example.com", "port": null } ], "auth": null, "options": { "tls": true } } ] } mongodb-mongo-python-driver-509e9b7/test/connection_string/test/valid-unix_socket-absolute.json000066400000000000000000000151021462766011000332560ustar00rootroot00000000000000{ "tests": [ { "description": "Unix domain socket (absolute path with trailing slash)", "uri": "mongodb://%2Ftmp%2Fmongodb-27017.sock/", "valid": true, "warning": false, "hosts": [ { "type": "unix", "host": "/tmp/mongodb-27017.sock", "port": null } ], "auth": null, "options": null }, { "description": "Unix domain socket (absolute path without trailing slash)", "uri": "mongodb://%2Ftmp%2Fmongodb-27017.sock", "valid": true, "warning": false, "hosts": [ { "type": "unix", "host": "/tmp/mongodb-27017.sock", "port": null } ], "auth": null, "options": null }, { "description": "Unix domain socket (mixed case)", "uri": "mongodb://%2Ftmp%2FMongoDB-27017.sock", "valid": true, "warning": false, "hosts": [ { "type": "unix", "host": "/tmp/MongoDB-27017.sock", "port": null } ], "auth": null, "options": null }, { "description": "Unix domain socket (absolute path with spaces in path)", "uri": "mongodb://%2Ftmp%2F %2Fmongodb-27017.sock", "valid": true, "warning": false, "hosts": [ { "type": "unix", "host": "/tmp/ /mongodb-27017.sock", "port": null } ], "auth": null, "options": null }, { "description": "Multiple Unix domain sockets (absolute paths)", "uri": "mongodb://%2Ftmp%2Fmongodb-27017.sock,%2Ftmp%2Fmongodb-27018.sock", "valid": true, "warning": false, "hosts": [ { "type": "unix", "host": "/tmp/mongodb-27017.sock", "port": null }, { "type": "unix", "host": "/tmp/mongodb-27018.sock", "port": null } ], "auth": null, "options": null }, { "description": "Multiple hosts (absolute path and ipv4)", "uri": "mongodb://127.0.0.1:27017,%2Ftmp%2Fmongodb-27017.sock", "valid": true, "warning": false, "hosts": [ { "type": "ipv4", "host": "127.0.0.1", "port": 27017 }, { "type": "unix", "host": "/tmp/mongodb-27017.sock", "port": null } ], "auth": null, "options": null }, { "description": "Multiple hosts (absolute path and hostname resembling relative path)", "uri": "mongodb://mongodb-27017.sock,%2Ftmp%2Fmongodb-27018.sock", "valid": true, "warning": false, "hosts": [ { "type": "hostname", "host": "mongodb-27017.sock", "port": null }, { "type": "unix", "host": "/tmp/mongodb-27018.sock", "port": null } ], "auth": null, "options": null }, { "description": "Unix domain socket with auth database (absolute path)", "uri": "mongodb://alice:foo@%2Ftmp%2Fmongodb-27017.sock/admin", "valid": true, "warning": false, "hosts": [ { "type": "unix", "host": "/tmp/mongodb-27017.sock", "port": null } ], "auth": { "username": "alice", "password": "foo", "db": "admin" }, "options": null }, { "description": "Unix domain socket with path resembling socket file (absolute path with trailing slash)", "uri": "mongodb://%2Ftmp%2Fpath.to.sock%2Fmongodb-27017.sock/", "valid": true, "warning": false, "hosts": [ { "type": "unix", "host": "/tmp/path.to.sock/mongodb-27017.sock", "port": null } ], "auth": null, "options": null }, { "description": "Unix domain socket with path resembling socket file (absolute path without trailing slash)", "uri": "mongodb://%2Ftmp%2Fpath.to.sock%2Fmongodb-27017.sock", "valid": true, "warning": false, "hosts": [ { "type": "unix", "host": "/tmp/path.to.sock/mongodb-27017.sock", "port": null } ], "auth": null, "options": null }, { "description": "Unix domain socket with path resembling socket file and auth (absolute path)", "uri": "mongodb://bob:bar@%2Ftmp%2Fpath.to.sock%2Fmongodb-27017.sock/admin", "valid": true, "warning": false, "hosts": [ { "type": "unix", "host": "/tmp/path.to.sock/mongodb-27017.sock", "port": null } ], "auth": { "username": "bob", "password": "bar", "db": "admin" }, "options": null }, { "description": "Multiple Unix domain sockets and auth DB (absolute path)", "uri": "mongodb://%2Ftmp%2Fmongodb-27017.sock,%2Ftmp%2Fmongodb-27018.sock/admin", "valid": true, "warning": false, "hosts": [ { "type": "unix", "host": "/tmp/mongodb-27017.sock", "port": null }, { "type": "unix", "host": "/tmp/mongodb-27018.sock", "port": null } ], "auth": { "username": null, "password": null, "db": "admin" }, "options": null }, { "description": "Multiple Unix domain sockets with auth DB (absolute path)", "uri": "mongodb://%2Ftmp%2Fmongodb-27017.sock,%2Ftmp%2Fmongodb-27018.sock/admin", "valid": true, "warning": false, "hosts": [ { "type": "unix", "host": "/tmp/mongodb-27017.sock", "port": null }, { "type": "unix", "host": "/tmp/mongodb-27018.sock", "port": null } ], "auth": { "username": null, "password": null, "db": "admin" }, "options": null }, { "description": "Multiple Unix domain sockets with auth and query string (absolute path)", "uri": "mongodb://bob:bar@%2Ftmp%2Fmongodb-27017.sock,%2Ftmp%2Fmongodb-27018.sock/admin?w=1", "valid": true, "warning": false, "hosts": [ { "type": "unix", "host": "/tmp/mongodb-27017.sock", "port": null }, { "type": "unix", "host": "/tmp/mongodb-27018.sock", "port": null } ], "auth": { "username": "bob", "password": "bar", "db": "admin" }, "options": { "w": 1 } } ] } mongodb-mongo-python-driver-509e9b7/test/connection_string/test/valid-unix_socket-relative.json000066400000000000000000000160341462766011000332600ustar00rootroot00000000000000{ "tests": [ { "description": "Unix domain socket (relative path with trailing slash)", "uri": "mongodb://rel%2Fmongodb-27017.sock/", "valid": true, "warning": false, "hosts": [ { "type": "unix", "host": "rel/mongodb-27017.sock", "port": null } ], "auth": null, "options": null }, { "description": "Unix domain socket (relative path without trailing slash)", "uri": "mongodb://rel%2Fmongodb-27017.sock", "valid": true, "warning": false, "hosts": [ { "type": "unix", "host": "rel/mongodb-27017.sock", "port": null } ], "auth": null, "options": null }, { "description": "Unix domain socket (mixed case)", "uri": "mongodb://rel%2FMongoDB-27017.sock", "valid": true, "warning": false, "hosts": [ { "type": "unix", "host": "rel/MongoDB-27017.sock", "port": null } ], "auth": null, "options": null }, { "description": "Unix domain socket (relative path with spaces)", "uri": "mongodb://rel%2F %2Fmongodb-27017.sock", "valid": true, "warning": false, "hosts": [ { "type": "unix", "host": "rel/ /mongodb-27017.sock", "port": null } ], "auth": null, "options": null }, { "description": "Multiple Unix domain sockets (relative paths)", "uri": "mongodb://rel%2Fmongodb-27017.sock,rel%2Fmongodb-27018.sock", "valid": true, "warning": false, "hosts": [ { "type": "unix", "host": "rel/mongodb-27017.sock", "port": null }, { "type": "unix", "host": "rel/mongodb-27018.sock", "port": null } ], "auth": null, "options": null }, { "description": "Multiple Unix domain sockets (relative and absolute paths)", "uri": "mongodb://rel%2Fmongodb-27017.sock,%2Ftmp%2Fmongodb-27018.sock", "valid": true, "warning": false, "hosts": [ { "type": "unix", "host": "rel/mongodb-27017.sock", "port": null }, { "type": "unix", "host": "/tmp/mongodb-27018.sock", "port": null } ], "auth": null, "options": null }, { "description": "Multiple hosts (relative path and ipv4)", "uri": "mongodb://127.0.0.1:27017,rel%2Fmongodb-27017.sock", "valid": true, "warning": false, "hosts": [ { "type": "ipv4", "host": "127.0.0.1", "port": 27017 }, { "type": "unix", "host": "rel/mongodb-27017.sock", "port": null } ], "auth": null, "options": null }, { "description": "Multiple hosts (relative path and hostname resembling relative path)", "uri": "mongodb://mongodb-27017.sock,rel%2Fmongodb-27018.sock", "valid": true, "warning": false, "hosts": [ { "type": "hostname", "host": "mongodb-27017.sock", "port": null }, { "type": "unix", "host": "rel/mongodb-27018.sock", "port": null } ], "auth": null, "options": null }, { "description": "Unix domain socket with auth database (relative path)", "uri": "mongodb://alice:foo@rel%2Fmongodb-27017.sock/admin", "valid": true, "warning": false, "hosts": [ { "type": "unix", "host": "rel/mongodb-27017.sock", "port": null } ], "auth": { "username": "alice", "password": "foo", "db": "admin" }, "options": null }, { "description": "Unix domain socket with path resembling socket file (relative path with trailing slash)", "uri": "mongodb://rel%2Fpath.to.sock%2Fmongodb-27017.sock/", "valid": true, "warning": false, "hosts": [ { "type": "unix", "host": "rel/path.to.sock/mongodb-27017.sock", "port": null } ], "auth": null, "options": null }, { "description": "Unix domain socket with path resembling socket file (relative path without trailing slash)", "uri": "mongodb://rel%2Fpath.to.sock%2Fmongodb-27017.sock", "valid": true, "warning": false, "hosts": [ { "type": "unix", "host": "rel/path.to.sock/mongodb-27017.sock", "port": null } ], "auth": null, "options": null }, { "description": "Unix domain socket with path resembling socket file and auth (relative path)", "uri": "mongodb://bob:bar@rel%2Fpath.to.sock%2Fmongodb-27017.sock/admin", "valid": true, "warning": false, "hosts": [ { "type": "unix", "host": "rel/path.to.sock/mongodb-27017.sock", "port": null } ], "auth": { "username": "bob", "password": "bar", "db": "admin" }, "options": null }, { "description": "Multiple Unix domain sockets and auth DB resembling a socket (relative path)", "uri": "mongodb://rel%2Fmongodb-27017.sock,rel%2Fmongodb-27018.sock/admin", "valid": true, "warning": false, "hosts": [ { "type": "unix", "host": "rel/mongodb-27017.sock", "port": null }, { "type": "unix", "host": "rel/mongodb-27018.sock", "port": null } ], "auth": { "username": null, "password": null, "db": "admin" }, "options": null }, { "description": "Multiple Unix domain sockets with auth DB resembling a path (relative path)", "uri": "mongodb://rel%2Fmongodb-27017.sock,rel%2Fmongodb-27018.sock/admin", "valid": true, "warning": false, "hosts": [ { "type": "unix", "host": "rel/mongodb-27017.sock", "port": null }, { "type": "unix", "host": "rel/mongodb-27018.sock", "port": null } ], "auth": { "username": null, "password": null, "db": "admin" }, "options": null }, { "description": "Multiple Unix domain sockets with auth and query string (relative path)", "uri": "mongodb://bob:bar@rel%2Fmongodb-27017.sock,rel%2Fmongodb-27018.sock/admin?w=1", "valid": true, "warning": false, "hosts": [ { "type": "unix", "host": "rel/mongodb-27017.sock", "port": null }, { "type": "unix", "host": "rel/mongodb-27018.sock", "port": null } ], "auth": { "username": "bob", "password": "bar", "db": "admin" }, "options": { "w": 1 } } ] } mongodb-mongo-python-driver-509e9b7/test/connection_string/test/valid-warnings.json000066400000000000000000000042131462766011000307400ustar00rootroot00000000000000{ "tests": [ { "description": "Unrecognized option keys are ignored", "uri": "mongodb://example.com/?foo=bar", "valid": true, "warning": true, "hosts": [ { "type": "hostname", "host": "example.com", "port": null } ], "auth": null, "options": null }, { "description": "Unsupported option values are ignored", "uri": "mongodb://example.com/?fsync=ifPossible", "valid": true, "warning": true, "hosts": [ { "type": "hostname", "host": "example.com", "port": null } ], "auth": null, "options": null }, { "description": "Repeated option keys", "uri": "mongodb://example.com/?replicaSet=test&replicaSet=test", "valid": true, "warning": true, "hosts": [ { "type": "hostname", "host": "example.com", "port": null } ], "auth": null, "options": { "replicaset": "test" } }, { "description": "Deprecated (or unknown) options are ignored if replacement exists", "uri": "mongodb://example.com/?wtimeout=5&wtimeoutMS=10", "valid": true, "warning": true, "hosts": [ { "type": "hostname", "host": "example.com", "port": null } ], "auth": null, "options": { "wtimeoutms": 10 } }, { "description": "Empty integer option values are ignored", "uri": "mongodb://localhost/?maxIdleTimeMS=", "valid": true, "warning": true, "hosts": [ { "type": "hostname", "host": "localhost", "port": null } ], "auth": null, "options": null }, { "description": "Empty boolean option value are ignored", "uri": "mongodb://localhost/?journal=", "valid": true, "warning": true, "hosts": [ { "type": "hostname", "host": "localhost", "port": null } ], "auth": null, "options": null } ] } mongodb-mongo-python-driver-509e9b7/test/crud/000077500000000000000000000000001462766011000213515ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/crud/unified/000077500000000000000000000000001462766011000227745ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/crud/unified/aggregate-allowdiskuse.json000066400000000000000000000066221462766011000303270ustar00rootroot00000000000000{ "description": "aggregate-allowdiskuse", "schemaVersion": "1.0", "createEntities": [ { "client": { "id": "client0", "observeEvents": [ "commandStartedEvent" ] } }, { "database": { "id": "database0", "client": "client0", "databaseName": "crud-tests" } }, { "collection": { "id": "collection0", "database": "database0", "collectionName": "coll0" } } ], "initialData": [ { "collectionName": "coll0", "databaseName": "crud-tests", "documents": [] } ], "tests": [ { "description": "Aggregate does not send allowDiskUse when value is not specified", "operations": [ { "object": "collection0", "name": "aggregate", "arguments": { "pipeline": [ { "$match": {} } ] } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "aggregate": "coll0", "pipeline": [ { "$match": {} } ], "allowDiskUse": { "$$exists": false } }, "commandName": "aggregate", "databaseName": "crud-tests" } } ] } ] }, { "description": "Aggregate sends allowDiskUse false when false is specified", "operations": [ { "object": "collection0", "name": "aggregate", "arguments": { "pipeline": [ { "$match": {} } ], "allowDiskUse": false } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "aggregate": "coll0", "pipeline": [ { "$match": {} } ], "allowDiskUse": false }, "commandName": "aggregate", "databaseName": "crud-tests" } } ] } ] }, { "description": "Aggregate sends allowDiskUse true when true is specified", "operations": [ { "object": "collection0", "name": "aggregate", "arguments": { "pipeline": [ { "$match": {} } ], "allowDiskUse": true } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "aggregate": "coll0", "pipeline": [ { "$match": {} } ], "allowDiskUse": true }, "commandName": "aggregate", "databaseName": "crud-tests" } } ] } ] } ] } mongodb-mongo-python-driver-509e9b7/test/crud/unified/aggregate-let.json000066400000000000000000000206021462766011000263770ustar00rootroot00000000000000{ "description": "aggregate-let", "schemaVersion": "1.4", "createEntities": [ { "client": { "id": "client0", "observeEvents": [ "commandStartedEvent" ] } }, { "database": { "id": "database0", "client": "client0", "databaseName": "crud-tests" } }, { "collection": { "id": "collection0", "database": "database0", "collectionName": "coll0" } }, { "collection": { "id": "collection1", "database": "database0", "collectionName": "coll1" } } ], "initialData": [ { "collectionName": "coll0", "databaseName": "crud-tests", "documents": [ { "_id": 1 } ] }, { "collectionName": "coll1", "databaseName": "crud-tests", "documents": [] } ], "tests": [ { "description": "Aggregate with let option", "runOnRequirements": [ { "minServerVersion": "5.0" } ], "operations": [ { "name": "aggregate", "object": "collection0", "arguments": { "pipeline": [ { "$match": { "$expr": { "$eq": [ "$_id", "$$id" ] } } }, { "$project": { "_id": 0, "x": "$$x", "y": "$$y", "rand": "$$rand" } } ], "let": { "id": 1, "x": "foo", "y": { "$literal": "$bar" }, "rand": { "$rand": {} } } }, "expectResult": [ { "x": "foo", "y": "$bar", "rand": { "$$type": "double" } } ] } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "aggregate": "coll0", "pipeline": [ { "$match": { "$expr": { "$eq": [ "$_id", "$$id" ] } } }, { "$project": { "_id": 0, "x": "$$x", "y": "$$y", "rand": "$$rand" } } ], "let": { "id": 1, "x": "foo", "y": { "$literal": "$bar" }, "rand": { "$rand": {} } } } } } ] } ] }, { "description": "Aggregate with let option unsupported (server-side error)", "runOnRequirements": [ { "minServerVersion": "2.6.0", "maxServerVersion": "4.4.99" } ], "operations": [ { "name": "aggregate", "object": "collection0", "arguments": { "pipeline": [ { "$match": { "_id": 1 } } ], "let": { "x": "foo" } }, "expectError": { "errorContains": "unrecognized field 'let'", "isClientError": false } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "aggregate": "coll0", "pipeline": [ { "$match": { "_id": 1 } } ], "let": { "x": "foo" } } } } ] } ] }, { "description": "Aggregate to collection with let option", "runOnRequirements": [ { "minServerVersion": "5.0", "serverless": "forbid" } ], "operations": [ { "name": "aggregate", "object": "collection0", "arguments": { "pipeline": [ { "$match": { "$expr": { "$eq": [ "$_id", "$$id" ] } } }, { "$project": { "_id": 1 } }, { "$out": "coll1" } ], "let": { "id": 1 } } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "aggregate": "coll0", "pipeline": [ { "$match": { "$expr": { "$eq": [ "$_id", "$$id" ] } } }, { "$project": { "_id": 1 } }, { "$out": "coll1" } ], "let": { "id": 1 } } } } ] } ], "outcome": [ { "collectionName": "coll1", "databaseName": "crud-tests", "documents": [ { "_id": 1 } ] } ] }, { "description": "Aggregate to collection with let option unsupported (server-side error)", "runOnRequirements": [ { "minServerVersion": "2.6.0", "maxServerVersion": "4.4.99" } ], "operations": [ { "name": "aggregate", "object": "collection0", "arguments": { "pipeline": [ { "$match": { "$expr": { "$eq": [ "$_id", "$$id" ] } } }, { "$project": { "_id": 1 } }, { "$out": "coll1" } ], "let": { "id": 1 } }, "expectError": { "errorContains": "unrecognized field 'let'", "isClientError": false } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "aggregate": "coll0", "pipeline": [ { "$match": { "$expr": { "$eq": [ "$_id", "$$id" ] } } }, { "$project": { "_id": 1 } }, { "$out": "coll1" } ], "let": { "id": 1 } } } } ] } ] } ] } mongodb-mongo-python-driver-509e9b7/test/crud/unified/aggregate-merge-errorResponse.json000066400000000000000000000033321462766011000315610ustar00rootroot00000000000000{ "description": "aggregate-merge-errorResponse", "schemaVersion": "1.12", "createEntities": [ { "client": { "id": "client0" } }, { "database": { "id": "database0", "client": "client0", "databaseName": "crud-tests" } }, { "collection": { "id": "collection0", "database": "database0", "collectionName": "test" } } ], "initialData": [ { "collectionName": "test", "databaseName": "crud-tests", "documents": [ { "_id": 1, "x": 1 }, { "_id": 2, "x": 1 } ] } ], "tests": [ { "description": "aggregate $merge DuplicateKey error is accessible", "runOnRequirements": [ { "minServerVersion": "5.1", "topologies": [ "single", "replicaset" ] } ], "operations": [ { "name": "aggregate", "object": "database0", "arguments": { "pipeline": [ { "$documents": [ { "_id": 2, "x": 1 } ] }, { "$merge": { "into": "test", "whenMatched": "fail" } } ] }, "expectError": { "errorCode": 11000, "errorResponse": { "keyPattern": { "_id": 1 }, "keyValue": { "_id": 2 } } } } ] } ] } mongodb-mongo-python-driver-509e9b7/test/crud/unified/aggregate-merge.json000066400000000000000000000260501462766011000267150ustar00rootroot00000000000000{ "description": "aggregate-merge", "schemaVersion": "1.0", "runOnRequirements": [ { "minServerVersion": "4.1.11" } ], "createEntities": [ { "client": { "id": "client0", "observeEvents": [ "commandStartedEvent" ] } }, { "database": { "id": "database0", "client": "client0", "databaseName": "crud-v2" } }, { "collection": { "id": "collection0", "database": "database0", "collectionName": "test_aggregate_merge" } }, { "collection": { "id": "collection_readConcern_majority", "database": "database0", "collectionName": "test_aggregate_merge", "collectionOptions": { "readConcern": { "level": "majority" } } } }, { "collection": { "id": "collection_readConcern_local", "database": "database0", "collectionName": "test_aggregate_merge", "collectionOptions": { "readConcern": { "level": "local" } } } }, { "collection": { "id": "collection_readConcern_available", "database": "database0", "collectionName": "test_aggregate_merge", "collectionOptions": { "readConcern": { "level": "available" } } } } ], "initialData": [ { "collectionName": "test_aggregate_merge", "databaseName": "crud-v2", "documents": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 22 }, { "_id": 3, "x": 33 } ] } ], "tests": [ { "description": "Aggregate with $merge", "operations": [ { "object": "collection0", "name": "aggregate", "arguments": { "pipeline": [ { "$sort": { "x": 1 } }, { "$match": { "_id": { "$gt": 1 } } }, { "$merge": { "into": "other_test_collection" } } ] } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "aggregate": "test_aggregate_merge", "pipeline": [ { "$sort": { "x": 1 } }, { "$match": { "_id": { "$gt": 1 } } }, { "$merge": { "into": "other_test_collection" } } ] } } } ] } ], "outcome": [ { "collectionName": "other_test_collection", "databaseName": "crud-v2", "documents": [ { "_id": 2, "x": 22 }, { "_id": 3, "x": 33 } ] } ] }, { "description": "Aggregate with $merge and batch size of 0", "operations": [ { "object": "collection0", "name": "aggregate", "arguments": { "pipeline": [ { "$sort": { "x": 1 } }, { "$match": { "_id": { "$gt": 1 } } }, { "$merge": { "into": "other_test_collection" } } ], "batchSize": 0 } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "aggregate": "test_aggregate_merge", "pipeline": [ { "$sort": { "x": 1 } }, { "$match": { "_id": { "$gt": 1 } } }, { "$merge": { "into": "other_test_collection" } } ], "cursor": {} } } } ] } ], "outcome": [ { "collectionName": "other_test_collection", "databaseName": "crud-v2", "documents": [ { "_id": 2, "x": 22 }, { "_id": 3, "x": 33 } ] } ] }, { "description": "Aggregate with $merge and majority readConcern", "operations": [ { "object": "collection_readConcern_majority", "name": "aggregate", "arguments": { "pipeline": [ { "$sort": { "x": 1 } }, { "$match": { "_id": { "$gt": 1 } } }, { "$merge": { "into": "other_test_collection" } } ] } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "aggregate": "test_aggregate_merge", "pipeline": [ { "$sort": { "x": 1 } }, { "$match": { "_id": { "$gt": 1 } } }, { "$merge": { "into": "other_test_collection" } } ], "readConcern": { "level": "majority" } } } } ] } ], "outcome": [ { "collectionName": "other_test_collection", "databaseName": "crud-v2", "documents": [ { "_id": 2, "x": 22 }, { "_id": 3, "x": 33 } ] } ] }, { "description": "Aggregate with $merge and local readConcern", "operations": [ { "object": "collection_readConcern_local", "name": "aggregate", "arguments": { "pipeline": [ { "$sort": { "x": 1 } }, { "$match": { "_id": { "$gt": 1 } } }, { "$merge": { "into": "other_test_collection" } } ] } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "aggregate": "test_aggregate_merge", "pipeline": [ { "$sort": { "x": 1 } }, { "$match": { "_id": { "$gt": 1 } } }, { "$merge": { "into": "other_test_collection" } } ], "readConcern": { "level": "local" } } } } ] } ], "outcome": [ { "collectionName": "other_test_collection", "databaseName": "crud-v2", "documents": [ { "_id": 2, "x": 22 }, { "_id": 3, "x": 33 } ] } ] }, { "description": "Aggregate with $merge and available readConcern", "operations": [ { "object": "collection_readConcern_available", "name": "aggregate", "arguments": { "pipeline": [ { "$sort": { "x": 1 } }, { "$match": { "_id": { "$gt": 1 } } }, { "$merge": { "into": "other_test_collection" } } ] } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "aggregate": "test_aggregate_merge", "pipeline": [ { "$sort": { "x": 1 } }, { "$match": { "_id": { "$gt": 1 } } }, { "$merge": { "into": "other_test_collection" } } ], "readConcern": { "level": "available" } } } } ] } ], "outcome": [ { "collectionName": "other_test_collection", "databaseName": "crud-v2", "documents": [ { "_id": 2, "x": 22 }, { "_id": 3, "x": 33 } ] } ] } ] } mongodb-mongo-python-driver-509e9b7/test/crud/unified/aggregate-out-readConcern.json000066400000000000000000000222011462766011000306400ustar00rootroot00000000000000{ "description": "aggregate-out-readConcern", "schemaVersion": "1.4", "runOnRequirements": [ { "minServerVersion": "4.1.0", "topologies": [ "replicaset", "sharded" ], "serverless": "forbid" } ], "createEntities": [ { "client": { "id": "client0", "observeEvents": [ "commandStartedEvent" ] } }, { "database": { "id": "database0", "client": "client0", "databaseName": "crud-v2" } }, { "collection": { "id": "collection0", "database": "database0", "collectionName": "test_aggregate_out_readconcern" } }, { "collection": { "id": "collection_readConcern_majority", "database": "database0", "collectionName": "test_aggregate_out_readconcern", "collectionOptions": { "readConcern": { "level": "majority" } } } }, { "collection": { "id": "collection_readConcern_local", "database": "database0", "collectionName": "test_aggregate_out_readconcern", "collectionOptions": { "readConcern": { "level": "local" } } } }, { "collection": { "id": "collection_readConcern_available", "database": "database0", "collectionName": "test_aggregate_out_readconcern", "collectionOptions": { "readConcern": { "level": "available" } } } }, { "collection": { "id": "collection_readConcern_linearizable", "database": "database0", "collectionName": "test_aggregate_out_readconcern", "collectionOptions": { "readConcern": { "level": "linearizable" } } } } ], "initialData": [ { "collectionName": "test_aggregate_out_readconcern", "databaseName": "crud-v2", "documents": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 22 }, { "_id": 3, "x": 33 } ] } ], "tests": [ { "description": "readConcern majority with out stage", "operations": [ { "object": "collection_readConcern_majority", "name": "aggregate", "arguments": { "pipeline": [ { "$sort": { "x": 1 } }, { "$match": { "_id": { "$gt": 1 } } }, { "$out": "other_test_collection" } ] } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "aggregate": "test_aggregate_out_readconcern", "pipeline": [ { "$sort": { "x": 1 } }, { "$match": { "_id": { "$gt": 1 } } }, { "$out": "other_test_collection" } ], "readConcern": { "level": "majority" } } } } ] } ], "outcome": [ { "collectionName": "other_test_collection", "databaseName": "crud-v2", "documents": [ { "_id": 2, "x": 22 }, { "_id": 3, "x": 33 } ] } ] }, { "description": "readConcern local with out stage", "operations": [ { "object": "collection_readConcern_local", "name": "aggregate", "arguments": { "pipeline": [ { "$sort": { "x": 1 } }, { "$match": { "_id": { "$gt": 1 } } }, { "$out": "other_test_collection" } ] } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "aggregate": "test_aggregate_out_readconcern", "pipeline": [ { "$sort": { "x": 1 } }, { "$match": { "_id": { "$gt": 1 } } }, { "$out": "other_test_collection" } ], "readConcern": { "level": "local" } } } } ] } ], "outcome": [ { "collectionName": "other_test_collection", "databaseName": "crud-v2", "documents": [ { "_id": 2, "x": 22 }, { "_id": 3, "x": 33 } ] } ] }, { "description": "readConcern available with out stage", "operations": [ { "object": "collection_readConcern_available", "name": "aggregate", "arguments": { "pipeline": [ { "$sort": { "x": 1 } }, { "$match": { "_id": { "$gt": 1 } } }, { "$out": "other_test_collection" } ] } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "aggregate": "test_aggregate_out_readconcern", "pipeline": [ { "$sort": { "x": 1 } }, { "$match": { "_id": { "$gt": 1 } } }, { "$out": "other_test_collection" } ], "readConcern": { "level": "available" } } } } ] } ], "outcome": [ { "collectionName": "other_test_collection", "databaseName": "crud-v2", "documents": [ { "_id": 2, "x": 22 }, { "_id": 3, "x": 33 } ] } ] }, { "description": "readConcern linearizable with out stage", "operations": [ { "object": "collection_readConcern_linearizable", "name": "aggregate", "arguments": { "pipeline": [ { "$sort": { "x": 1 } }, { "$match": { "_id": { "$gt": 1 } } }, { "$out": "other_test_collection" } ] }, "expectError": { "isError": true } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "aggregate": "test_aggregate_out_readconcern", "pipeline": [ { "$sort": { "x": 1 } }, { "$match": { "_id": { "$gt": 1 } } }, { "$out": "other_test_collection" } ], "readConcern": { "level": "linearizable" } } } } ] } ] } ] } mongodb-mongo-python-driver-509e9b7/test/crud/unified/aggregate-write-readPreference.json000066400000000000000000000240021462766011000316530ustar00rootroot00000000000000{ "description": "aggregate-write-readPreference", "schemaVersion": "1.4", "runOnRequirements": [ { "minServerVersion": "3.6", "topologies": [ "replicaset", "sharded", "load-balanced" ] } ], "_yamlAnchors": { "readConcern": { "level": "local" }, "writeConcern": { "w": 1 } }, "createEntities": [ { "client": { "id": "client0", "observeEvents": [ "commandStartedEvent" ], "uriOptions": { "readConcernLevel": "local", "w": 1 } } }, { "database": { "id": "database0", "client": "client0", "databaseName": "db0" } }, { "collection": { "id": "collection0", "database": "database0", "collectionName": "coll0", "collectionOptions": { "readPreference": { "mode": "secondaryPreferred", "maxStalenessSeconds": 600 } } } }, { "collection": { "id": "collection1", "database": "database0", "collectionName": "coll1" } } ], "initialData": [ { "collectionName": "coll0", "databaseName": "db0", "documents": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 22 }, { "_id": 3, "x": 33 } ] }, { "collectionName": "coll1", "databaseName": "db0", "documents": [] } ], "tests": [ { "description": "Aggregate with $out includes read preference for 5.0+ server", "runOnRequirements": [ { "minServerVersion": "5.0", "serverless": "forbid" } ], "operations": [ { "object": "collection0", "name": "aggregate", "arguments": { "pipeline": [ { "$match": { "_id": { "$gt": 1 } } }, { "$sort": { "x": 1 } }, { "$out": "coll1" } ] } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "aggregate": "coll0", "pipeline": [ { "$match": { "_id": { "$gt": 1 } } }, { "$sort": { "x": 1 } }, { "$out": "coll1" } ], "$readPreference": { "mode": "secondaryPreferred", "maxStalenessSeconds": 600 }, "readConcern": { "level": "local" }, "writeConcern": { "w": 1 } } } } ] } ], "outcome": [ { "collectionName": "coll1", "databaseName": "db0", "documents": [ { "_id": 2, "x": 22 }, { "_id": 3, "x": 33 } ] } ] }, { "description": "Aggregate with $out omits read preference for pre-5.0 server", "runOnRequirements": [ { "minServerVersion": "4.2", "maxServerVersion": "4.4.99", "serverless": "forbid" } ], "operations": [ { "object": "collection0", "name": "aggregate", "arguments": { "pipeline": [ { "$match": { "_id": { "$gt": 1 } } }, { "$sort": { "x": 1 } }, { "$out": "coll1" } ] } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "aggregate": "coll0", "pipeline": [ { "$match": { "_id": { "$gt": 1 } } }, { "$sort": { "x": 1 } }, { "$out": "coll1" } ], "$readPreference": { "$$exists": false }, "readConcern": { "level": "local" }, "writeConcern": { "w": 1 } } } } ] } ], "outcome": [ { "collectionName": "coll1", "databaseName": "db0", "documents": [ { "_id": 2, "x": 22 }, { "_id": 3, "x": 33 } ] } ] }, { "description": "Aggregate with $merge includes read preference for 5.0+ server", "runOnRequirements": [ { "minServerVersion": "5.0" } ], "operations": [ { "object": "collection0", "name": "aggregate", "arguments": { "pipeline": [ { "$match": { "_id": { "$gt": 1 } } }, { "$sort": { "x": 1 } }, { "$merge": { "into": "coll1" } } ] } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "aggregate": "coll0", "pipeline": [ { "$match": { "_id": { "$gt": 1 } } }, { "$sort": { "x": 1 } }, { "$merge": { "into": "coll1" } } ], "$readPreference": { "mode": "secondaryPreferred", "maxStalenessSeconds": 600 }, "readConcern": { "level": "local" }, "writeConcern": { "w": 1 } } } } ] } ], "outcome": [ { "collectionName": "coll1", "databaseName": "db0", "documents": [ { "_id": 2, "x": 22 }, { "_id": 3, "x": 33 } ] } ] }, { "description": "Aggregate with $merge omits read preference for pre-5.0 server", "runOnRequirements": [ { "minServerVersion": "4.2", "maxServerVersion": "4.4.99" } ], "operations": [ { "object": "collection0", "name": "aggregate", "arguments": { "pipeline": [ { "$match": { "_id": { "$gt": 1 } } }, { "$sort": { "x": 1 } }, { "$merge": { "into": "coll1" } } ] } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "aggregate": "coll0", "pipeline": [ { "$match": { "_id": { "$gt": 1 } } }, { "$sort": { "x": 1 } }, { "$merge": { "into": "coll1" } } ], "$readPreference": { "$$exists": false }, "readConcern": { "level": "local" }, "writeConcern": { "w": 1 } } } } ] } ], "outcome": [ { "collectionName": "coll1", "databaseName": "db0", "documents": [ { "_id": 2, "x": 22 }, { "_id": 3, "x": 33 } ] } ] } ] } mongodb-mongo-python-driver-509e9b7/test/crud/unified/aggregate.json000066400000000000000000000316041462766011000256210ustar00rootroot00000000000000{ "description": "aggregate", "schemaVersion": "1.0", "createEntities": [ { "client": { "id": "client0", "useMultipleMongoses": true, "observeEvents": [ "commandStartedEvent" ] } }, { "database": { "id": "database0", "client": "client0", "databaseName": "aggregate-tests" } }, { "collection": { "id": "collection0", "database": "database0", "collectionName": "coll0" } } ], "initialData": [ { "collectionName": "coll0", "databaseName": "aggregate-tests", "documents": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 22 }, { "_id": 3, "x": 33 }, { "_id": 4, "x": 44 }, { "_id": 5, "x": 55 }, { "_id": 6, "x": 66 } ] } ], "tests": [ { "description": "aggregate with multiple batches works", "operations": [ { "name": "aggregate", "arguments": { "pipeline": [ { "$match": { "_id": { "$gt": 1 } } } ], "batchSize": 2 }, "object": "collection0", "expectResult": [ { "_id": 2, "x": 22 }, { "_id": 3, "x": 33 }, { "_id": 4, "x": 44 }, { "_id": 5, "x": 55 }, { "_id": 6, "x": 66 } ] } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "aggregate": "coll0", "pipeline": [ { "$match": { "_id": { "$gt": 1 } } } ], "cursor": { "batchSize": 2 } }, "commandName": "aggregate", "databaseName": "aggregate-tests" } }, { "commandStartedEvent": { "command": { "getMore": { "$$type": [ "int", "long" ] }, "collection": "coll0", "batchSize": 2 }, "commandName": "getMore", "databaseName": "aggregate-tests" } }, { "commandStartedEvent": { "command": { "getMore": { "$$type": [ "int", "long" ] }, "collection": "coll0", "batchSize": 2 }, "commandName": "getMore", "databaseName": "aggregate-tests" } } ] } ] }, { "description": "aggregate with a string comment", "runOnRequirements": [ { "minServerVersion": "3.6.0" } ], "operations": [ { "name": "aggregate", "arguments": { "pipeline": [ { "$match": { "_id": { "$gt": 1 } } } ], "comment": "comment" }, "object": "collection0" } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "aggregate": "coll0", "pipeline": [ { "$match": { "_id": { "$gt": 1 } } } ], "comment": "comment" } } } ] } ] }, { "description": "aggregate with a document comment", "runOnRequirements": [ { "minServerVersion": "4.4" } ], "operations": [ { "name": "aggregate", "arguments": { "pipeline": [ { "$match": { "_id": { "$gt": 1 } } } ], "comment": { "content": "test" } }, "object": "collection0" } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "aggregate": "coll0", "pipeline": [ { "$match": { "_id": { "$gt": 1 } } } ], "comment": { "content": "test" } } } } ] } ] }, { "description": "aggregate with a document comment - pre 4.4", "runOnRequirements": [ { "minServerVersion": "3.6.0", "maxServerVersion": "4.2.99" } ], "operations": [ { "name": "aggregate", "object": "collection0", "arguments": { "pipeline": [ { "$match": { "_id": { "$gt": 1 } } } ], "comment": { "content": "test" } }, "expectError": { "isClientError": false } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "aggregate": "coll0", "pipeline": [ { "$match": { "_id": { "$gt": 1 } } } ], "comment": { "content": "test" } }, "commandName": "aggregate", "databaseName": "aggregate-tests" } } ] } ] }, { "description": "aggregate with comment sets comment on getMore", "runOnRequirements": [ { "minServerVersion": "4.4.0" } ], "operations": [ { "name": "aggregate", "arguments": { "pipeline": [ { "$match": { "_id": { "$gt": 1 } } } ], "batchSize": 2, "comment": { "content": "test" } }, "object": "collection0", "expectResult": [ { "_id": 2, "x": 22 }, { "_id": 3, "x": 33 }, { "_id": 4, "x": 44 }, { "_id": 5, "x": 55 }, { "_id": 6, "x": 66 } ] } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "aggregate": "coll0", "pipeline": [ { "$match": { "_id": { "$gt": 1 } } } ], "cursor": { "batchSize": 2 }, "comment": { "content": "test" } }, "commandName": "aggregate", "databaseName": "aggregate-tests" } }, { "commandStartedEvent": { "command": { "getMore": { "$$type": [ "int", "long" ] }, "collection": "coll0", "batchSize": 2, "comment": { "content": "test" } }, "commandName": "getMore", "databaseName": "aggregate-tests" } }, { "commandStartedEvent": { "command": { "getMore": { "$$type": [ "int", "long" ] }, "collection": "coll0", "batchSize": 2, "comment": { "content": "test" } }, "commandName": "getMore", "databaseName": "aggregate-tests" } } ] } ] }, { "description": "aggregate with comment does not set comment on getMore - pre 4.4", "runOnRequirements": [ { "minServerVersion": "3.6.0", "maxServerVersion": "4.3.99" } ], "operations": [ { "name": "aggregate", "arguments": { "pipeline": [ { "$match": { "_id": { "$gt": 1 } } } ], "batchSize": 2, "comment": "comment" }, "object": "collection0", "expectResult": [ { "_id": 2, "x": 22 }, { "_id": 3, "x": 33 }, { "_id": 4, "x": 44 }, { "_id": 5, "x": 55 }, { "_id": 6, "x": 66 } ] } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "aggregate": "coll0", "pipeline": [ { "$match": { "_id": { "$gt": 1 } } } ], "cursor": { "batchSize": 2 }, "comment": "comment" }, "commandName": "aggregate", "databaseName": "aggregate-tests" } }, { "commandStartedEvent": { "command": { "getMore": { "$$type": [ "int", "long" ] }, "collection": "coll0", "batchSize": 2, "comment": { "$$exists": false } }, "commandName": "getMore", "databaseName": "aggregate-tests" } }, { "commandStartedEvent": { "command": { "getMore": { "$$type": [ "int", "long" ] }, "collection": "coll0", "batchSize": 2, "comment": { "$$exists": false } }, "commandName": "getMore", "databaseName": "aggregate-tests" } } ] } ] } ] } mongodb-mongo-python-driver-509e9b7/test/crud/unified/bulkWrite-arrayFilters-clientError.json000066400000000000000000000060321462766011000325730ustar00rootroot00000000000000{ "description": "bulkWrite-arrayFilters-clientError", "schemaVersion": "1.0", "runOnRequirements": [ { "maxServerVersion": "3.5.5" } ], "createEntities": [ { "client": { "id": "client0", "observeEvents": [ "commandStartedEvent" ] } }, { "database": { "id": "database0", "client": "client0", "databaseName": "crud-v2" } }, { "collection": { "id": "collection0", "database": "database0", "collectionName": "crud-v2" } } ], "initialData": [ { "collectionName": "crud-v2", "databaseName": "crud-v2", "documents": [ { "_id": 1, "y": [ { "b": 3 }, { "b": 1 } ] }, { "_id": 2, "y": [ { "b": 0 }, { "b": 1 } ] } ] } ], "tests": [ { "description": "BulkWrite on server that doesn't support arrayFilters", "operations": [ { "object": "collection0", "name": "bulkWrite", "arguments": { "requests": [ { "updateOne": { "filter": {}, "update": { "$set": { "y.0.b": 2 } }, "arrayFilters": [ { "i.b": 1 } ] } } ], "ordered": true }, "expectError": { "isError": true } } ], "expectEvents": [ { "client": "client0", "events": [] } ] }, { "description": "BulkWrite on server that doesn't support arrayFilters with arrayFilters on second op", "operations": [ { "object": "collection0", "name": "bulkWrite", "arguments": { "requests": [ { "updateOne": { "filter": {}, "update": { "$set": { "y.0.b": 2 } } } }, { "updateMany": { "filter": {}, "update": { "$set": { "y.$[i].b": 2 } }, "arrayFilters": [ { "i.b": 1 } ] } } ], "ordered": true }, "expectError": { "isError": true } } ], "expectEvents": [ { "client": "client0", "events": [] } ] } ] } mongodb-mongo-python-driver-509e9b7/test/crud/unified/bulkWrite-arrayFilters.json000066400000000000000000000141611462766011000303070ustar00rootroot00000000000000{ "description": "bulkWrite-arrayFilters", "schemaVersion": "1.0", "runOnRequirements": [ { "minServerVersion": "3.5.6" } ], "createEntities": [ { "client": { "id": "client0", "observeEvents": [ "commandStartedEvent" ] } }, { "database": { "id": "database0", "client": "client0", "databaseName": "crud-tests" } }, { "collection": { "id": "collection0", "database": "database0", "collectionName": "test" } } ], "initialData": [ { "collectionName": "test", "databaseName": "crud-tests", "documents": [ { "_id": 1, "y": [ { "b": 3 }, { "b": 1 } ] }, { "_id": 2, "y": [ { "b": 0 }, { "b": 1 } ] } ] } ], "tests": [ { "description": "BulkWrite updateOne with arrayFilters", "operations": [ { "object": "collection0", "name": "bulkWrite", "arguments": { "requests": [ { "updateOne": { "filter": {}, "update": { "$set": { "y.$[i].b": 2 } }, "arrayFilters": [ { "i.b": 3 } ] } } ], "ordered": true }, "expectResult": { "deletedCount": 0, "insertedCount": 0, "insertedIds": { "$$unsetOrMatches": {} }, "matchedCount": 1, "modifiedCount": 1, "upsertedCount": 0, "upsertedIds": {} } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "update": "test", "updates": [ { "q": {}, "u": { "$set": { "y.$[i].b": 2 } }, "multi": { "$$unsetOrMatches": false }, "upsert": { "$$unsetOrMatches": false }, "arrayFilters": [ { "i.b": 3 } ] } ], "ordered": true }, "commandName": "update", "databaseName": "crud-tests" } } ] } ], "outcome": [ { "collectionName": "test", "databaseName": "crud-tests", "documents": [ { "_id": 1, "y": [ { "b": 2 }, { "b": 1 } ] }, { "_id": 2, "y": [ { "b": 0 }, { "b": 1 } ] } ] } ] }, { "description": "BulkWrite updateMany with arrayFilters", "operations": [ { "object": "collection0", "name": "bulkWrite", "arguments": { "requests": [ { "updateMany": { "filter": {}, "update": { "$set": { "y.$[i].b": 2 } }, "arrayFilters": [ { "i.b": 1 } ] } } ], "ordered": true }, "expectResult": { "deletedCount": 0, "insertedCount": 0, "insertedIds": { "$$unsetOrMatches": {} }, "matchedCount": 2, "modifiedCount": 2, "upsertedCount": 0, "upsertedIds": {} } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "update": "test", "updates": [ { "q": {}, "u": { "$set": { "y.$[i].b": 2 } }, "multi": true, "upsert": { "$$unsetOrMatches": false }, "arrayFilters": [ { "i.b": 1 } ] } ], "ordered": true }, "commandName": "update", "databaseName": "crud-tests" } } ] } ], "outcome": [ { "collectionName": "test", "databaseName": "crud-tests", "documents": [ { "_id": 1, "y": [ { "b": 3 }, { "b": 2 } ] }, { "_id": 2, "y": [ { "b": 0 }, { "b": 2 } ] } ] } ] } ] } mongodb-mongo-python-driver-509e9b7/test/crud/unified/bulkWrite-comment.json000066400000000000000000000302751462766011000273060ustar00rootroot00000000000000{ "description": "bulkWrite-comment", "schemaVersion": "1.0", "createEntities": [ { "client": { "id": "client0", "observeEvents": [ "commandStartedEvent" ] } }, { "database": { "id": "database0", "client": "client0", "databaseName": "crud-v2" } }, { "collection": { "id": "collection0", "database": "database0", "collectionName": "BulkWrite_comment" } } ], "initialData": [ { "collectionName": "BulkWrite_comment", "databaseName": "crud-v2", "documents": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 22 }, { "_id": 3, "x": 33 }, { "_id": 4, "x": 44 } ] } ], "tests": [ { "description": "BulkWrite with string comment", "runOnRequirements": [ { "minServerVersion": "4.4" } ], "operations": [ { "object": "collection0", "name": "bulkWrite", "arguments": { "requests": [ { "insertOne": { "document": { "_id": 5, "x": "inserted" } } }, { "replaceOne": { "filter": { "_id": 1 }, "replacement": { "_id": 1, "x": "replaced" } } }, { "updateOne": { "filter": { "_id": 2 }, "update": { "$set": { "x": "updated" } } } }, { "deleteOne": { "filter": { "_id": 3 } } } ], "comment": "comment" }, "expectResult": { "deletedCount": 1, "insertedCount": 1, "insertedIds": { "$$unsetOrMatches": { "0": 5 } }, "matchedCount": 2, "modifiedCount": 2, "upsertedCount": 0, "upsertedIds": {} } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "insert": "BulkWrite_comment", "documents": [ { "_id": 5, "x": "inserted" } ], "ordered": true, "comment": "comment" } } }, { "commandStartedEvent": { "command": { "update": "BulkWrite_comment", "updates": [ { "q": { "_id": 1 }, "u": { "_id": 1, "x": "replaced" }, "multi": { "$$unsetOrMatches": false }, "upsert": { "$$unsetOrMatches": false } }, { "q": { "_id": 2 }, "u": { "$set": { "x": "updated" } }, "multi": { "$$unsetOrMatches": false }, "upsert": { "$$unsetOrMatches": false } } ], "ordered": true, "comment": "comment" } } }, { "commandStartedEvent": { "command": { "delete": "BulkWrite_comment", "deletes": [ { "q": { "_id": 3 }, "limit": 1 } ], "ordered": true, "comment": "comment" } } } ] } ], "outcome": [ { "collectionName": "BulkWrite_comment", "databaseName": "crud-v2", "documents": [ { "_id": 1, "x": "replaced" }, { "_id": 2, "x": "updated" }, { "_id": 4, "x": 44 }, { "_id": 5, "x": "inserted" } ] } ] }, { "description": "BulkWrite with document comment", "runOnRequirements": [ { "minServerVersion": "4.4" } ], "operations": [ { "object": "collection0", "name": "bulkWrite", "arguments": { "requests": [ { "insertOne": { "document": { "_id": 5, "x": "inserted" } } }, { "replaceOne": { "filter": { "_id": 1 }, "replacement": { "_id": 1, "x": "replaced" } } }, { "updateOne": { "filter": { "_id": 2 }, "update": { "$set": { "x": "updated" } } } }, { "deleteOne": { "filter": { "_id": 3 } } } ], "comment": { "key": "value" } }, "expectResult": { "deletedCount": 1, "insertedCount": 1, "insertedIds": { "$$unsetOrMatches": { "0": 5 } }, "matchedCount": 2, "modifiedCount": 2, "upsertedCount": 0, "upsertedIds": {} } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "insert": "BulkWrite_comment", "documents": [ { "_id": 5, "x": "inserted" } ], "ordered": true, "comment": { "key": "value" } } } }, { "commandStartedEvent": { "command": { "update": "BulkWrite_comment", "updates": [ { "q": { "_id": 1 }, "u": { "_id": 1, "x": "replaced" }, "multi": { "$$unsetOrMatches": false }, "upsert": { "$$unsetOrMatches": false } }, { "q": { "_id": 2 }, "u": { "$set": { "x": "updated" } }, "multi": { "$$unsetOrMatches": false }, "upsert": { "$$unsetOrMatches": false } } ], "ordered": true, "comment": { "key": "value" } } } }, { "commandStartedEvent": { "command": { "delete": "BulkWrite_comment", "deletes": [ { "q": { "_id": 3 }, "limit": 1 } ], "ordered": true, "comment": { "key": "value" } } } } ] } ], "outcome": [ { "collectionName": "BulkWrite_comment", "databaseName": "crud-v2", "documents": [ { "_id": 1, "x": "replaced" }, { "_id": 2, "x": "updated" }, { "_id": 4, "x": 44 }, { "_id": 5, "x": "inserted" } ] } ] }, { "description": "BulkWrite with comment - pre 4.4", "runOnRequirements": [ { "minServerVersion": "3.4.0", "maxServerVersion": "4.2.99" } ], "operations": [ { "object": "collection0", "name": "bulkWrite", "arguments": { "requests": [ { "insertOne": { "document": { "_id": 5, "x": "inserted" } } }, { "replaceOne": { "filter": { "_id": 1 }, "replacement": { "_id": 1, "x": "replaced" } } }, { "updateOne": { "filter": { "_id": 2 }, "update": { "$set": { "x": "updated" } } } }, { "deleteOne": { "filter": { "_id": 3 } } } ], "comment": "comment" }, "expectError": { "isClientError": false } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "insert": "BulkWrite_comment", "documents": [ { "_id": 5, "x": "inserted" } ], "ordered": true, "comment": "comment" } } } ] } ], "outcome": [ { "collectionName": "BulkWrite_comment", "databaseName": "crud-v2", "documents": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 22 }, { "_id": 3, "x": 33 }, { "_id": 4, "x": 44 } ] } ] } ] } mongodb-mongo-python-driver-509e9b7/test/crud/unified/bulkWrite-delete-hint-clientError.json000066400000000000000000000075221462766011000323330ustar00rootroot00000000000000{ "description": "bulkWrite-delete-hint-clientError", "schemaVersion": "1.0", "runOnRequirements": [ { "maxServerVersion": "3.3.99" } ], "createEntities": [ { "client": { "id": "client0", "observeEvents": [ "commandStartedEvent" ] } }, { "database": { "id": "database0", "client": "client0", "databaseName": "crud-v2" } }, { "collection": { "id": "collection0", "database": "database0", "collectionName": "BulkWrite_delete_hint" } } ], "initialData": [ { "collectionName": "BulkWrite_delete_hint", "databaseName": "crud-v2", "documents": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 22 }, { "_id": 3, "x": 33 }, { "_id": 4, "x": 44 } ] } ], "tests": [ { "description": "BulkWrite deleteOne with hints unsupported (client-side error)", "operations": [ { "object": "collection0", "name": "bulkWrite", "arguments": { "requests": [ { "deleteOne": { "filter": { "_id": 1 }, "hint": "_id_" } }, { "deleteOne": { "filter": { "_id": 2 }, "hint": { "_id": 1 } } } ], "ordered": true }, "expectError": { "isError": true } } ], "expectEvents": [ { "client": "client0", "events": [] } ], "outcome": [ { "collectionName": "BulkWrite_delete_hint", "databaseName": "crud-v2", "documents": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 22 }, { "_id": 3, "x": 33 }, { "_id": 4, "x": 44 } ] } ] }, { "description": "BulkWrite deleteMany with hints unsupported (client-side error)", "operations": [ { "object": "collection0", "name": "bulkWrite", "arguments": { "requests": [ { "deleteMany": { "filter": { "_id": { "$lt": 3 } }, "hint": "_id_" } }, { "deleteMany": { "filter": { "_id": { "$gte": 4 } }, "hint": { "_id": 1 } } } ], "ordered": true }, "expectError": { "isError": true } } ], "expectEvents": [ { "client": "client0", "events": [] } ], "outcome": [ { "collectionName": "BulkWrite_delete_hint", "databaseName": "crud-v2", "documents": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 22 }, { "_id": 3, "x": 33 }, { "_id": 4, "x": 44 } ] } ] } ] } mongodb-mongo-python-driver-509e9b7/test/crud/unified/bulkWrite-delete-hint-serverError.json000066400000000000000000000126611462766011000323630ustar00rootroot00000000000000{ "description": "bulkWrite-delete-hint-serverError", "schemaVersion": "1.0", "runOnRequirements": [ { "minServerVersion": "3.4.0", "maxServerVersion": "4.3.3" } ], "createEntities": [ { "client": { "id": "client0", "observeEvents": [ "commandStartedEvent" ] } }, { "database": { "id": "database0", "client": "client0", "databaseName": "crud-v2" } }, { "collection": { "id": "collection0", "database": "database0", "collectionName": "BulkWrite_delete_hint" } } ], "initialData": [ { "collectionName": "BulkWrite_delete_hint", "databaseName": "crud-v2", "documents": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 22 }, { "_id": 3, "x": 33 }, { "_id": 4, "x": 44 } ] } ], "tests": [ { "description": "BulkWrite deleteOne with hints unsupported (server-side error)", "operations": [ { "object": "collection0", "name": "bulkWrite", "arguments": { "requests": [ { "deleteOne": { "filter": { "_id": 1 }, "hint": "_id_" } }, { "deleteOne": { "filter": { "_id": 2 }, "hint": { "_id": 1 } } } ], "ordered": true }, "expectError": { "isError": true } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "delete": "BulkWrite_delete_hint", "deletes": [ { "q": { "_id": 1 }, "hint": "_id_", "limit": 1 }, { "q": { "_id": 2 }, "hint": { "_id": 1 }, "limit": 1 } ], "ordered": true } } } ] } ], "outcome": [ { "collectionName": "BulkWrite_delete_hint", "databaseName": "crud-v2", "documents": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 22 }, { "_id": 3, "x": 33 }, { "_id": 4, "x": 44 } ] } ] }, { "description": "BulkWrite deleteMany with hints unsupported (server-side error)", "operations": [ { "object": "collection0", "name": "bulkWrite", "arguments": { "requests": [ { "deleteMany": { "filter": { "_id": { "$lt": 3 } }, "hint": "_id_" } }, { "deleteMany": { "filter": { "_id": { "$gte": 4 } }, "hint": { "_id": 1 } } } ], "ordered": true }, "expectError": { "isError": true } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "delete": "BulkWrite_delete_hint", "deletes": [ { "q": { "_id": { "$lt": 3 } }, "hint": "_id_", "limit": 0 }, { "q": { "_id": { "$gte": 4 } }, "hint": { "_id": 1 }, "limit": 0 } ], "ordered": true } } } ] } ], "outcome": [ { "collectionName": "BulkWrite_delete_hint", "databaseName": "crud-v2", "documents": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 22 }, { "_id": 3, "x": 33 }, { "_id": 4, "x": 44 } ] } ] } ] } mongodb-mongo-python-driver-509e9b7/test/crud/unified/bulkWrite-delete-hint.json000066400000000000000000000126571462766011000300520ustar00rootroot00000000000000{ "description": "bulkWrite-delete-hint", "schemaVersion": "1.0", "runOnRequirements": [ { "minServerVersion": "4.3.4" } ], "createEntities": [ { "client": { "id": "client0", "observeEvents": [ "commandStartedEvent" ] } }, { "database": { "id": "database0", "client": "client0", "databaseName": "crud-v2" } }, { "collection": { "id": "collection0", "database": "database0", "collectionName": "BulkWrite_delete_hint" } } ], "initialData": [ { "collectionName": "BulkWrite_delete_hint", "databaseName": "crud-v2", "documents": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 22 }, { "_id": 3, "x": 33 }, { "_id": 4, "x": 44 } ] } ], "tests": [ { "description": "BulkWrite deleteOne with hints", "operations": [ { "object": "collection0", "name": "bulkWrite", "arguments": { "requests": [ { "deleteOne": { "filter": { "_id": 1 }, "hint": "_id_" } }, { "deleteOne": { "filter": { "_id": 2 }, "hint": { "_id": 1 } } } ], "ordered": true }, "expectResult": { "deletedCount": 2, "insertedCount": 0, "insertedIds": { "$$unsetOrMatches": {} }, "matchedCount": 0, "modifiedCount": 0, "upsertedCount": 0, "upsertedIds": {} } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "delete": "BulkWrite_delete_hint", "deletes": [ { "q": { "_id": 1 }, "hint": "_id_", "limit": 1 }, { "q": { "_id": 2 }, "hint": { "_id": 1 }, "limit": 1 } ], "ordered": true } } } ] } ], "outcome": [ { "collectionName": "BulkWrite_delete_hint", "databaseName": "crud-v2", "documents": [ { "_id": 3, "x": 33 }, { "_id": 4, "x": 44 } ] } ] }, { "description": "BulkWrite deleteMany with hints", "operations": [ { "object": "collection0", "name": "bulkWrite", "arguments": { "requests": [ { "deleteMany": { "filter": { "_id": { "$lt": 3 } }, "hint": "_id_" } }, { "deleteMany": { "filter": { "_id": { "$gte": 4 } }, "hint": { "_id": 1 } } } ], "ordered": true }, "expectResult": { "deletedCount": 3, "insertedCount": 0, "insertedIds": { "$$unsetOrMatches": {} }, "matchedCount": 0, "modifiedCount": 0, "upsertedCount": 0, "upsertedIds": {} } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "delete": "BulkWrite_delete_hint", "deletes": [ { "q": { "_id": { "$lt": 3 } }, "hint": "_id_", "limit": 0 }, { "q": { "_id": { "$gte": 4 } }, "hint": { "_id": 1 }, "limit": 0 } ], "ordered": true } } } ] } ], "outcome": [ { "collectionName": "BulkWrite_delete_hint", "databaseName": "crud-v2", "documents": [ { "_id": 3, "x": 33 } ] } ] } ] } mongodb-mongo-python-driver-509e9b7/test/crud/unified/bulkWrite-deleteMany-hint-unacknowledged.json000066400000000000000000000135741462766011000336660ustar00rootroot00000000000000{ "description": "bulkWrite-deleteMany-hint-unacknowledged", "schemaVersion": "1.0", "createEntities": [ { "client": { "id": "client0", "observeEvents": [ "commandStartedEvent" ] } }, { "database": { "id": "database0", "client": "client0", "databaseName": "db0" } }, { "collection": { "id": "collection0", "database": "database0", "collectionName": "coll0", "collectionOptions": { "writeConcern": { "w": 0 } } } } ], "initialData": [ { "collectionName": "coll0", "databaseName": "db0", "documents": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 22 }, { "_id": 3, "x": 33 } ] } ], "tests": [ { "description": "Unacknowledged deleteMany with hint string fails with client-side error on pre-4.4 server", "runOnRequirements": [ { "maxServerVersion": "4.2.99" } ], "operations": [ { "object": "collection0", "name": "bulkWrite", "arguments": { "requests": [ { "deleteMany": { "filter": { "_id": { "$gt": 1 } }, "hint": "_id_" } } ] }, "expectError": { "isClientError": true } } ], "expectEvents": [ { "client": "client0", "events": [] } ] }, { "description": "Unacknowledged deleteMany with hint document fails with client-side error on pre-4.4 server", "runOnRequirements": [ { "maxServerVersion": "4.2.99" } ], "operations": [ { "object": "collection0", "name": "bulkWrite", "arguments": { "requests": [ { "deleteMany": { "filter": { "_id": { "$gt": 1 } }, "hint": { "_id": 1 } } } ] }, "expectError": { "isClientError": true } } ], "expectEvents": [ { "client": "client0", "events": [] } ] }, { "description": "Unacknowledged deleteMany with hint string on 4.4+ server", "runOnRequirements": [ { "minServerVersion": "4.4.0" } ], "operations": [ { "object": "collection0", "name": "bulkWrite", "arguments": { "requests": [ { "deleteMany": { "filter": { "_id": { "$gt": 1 } }, "hint": "_id_" } } ] }, "expectResult": { "$$unsetOrMatches": { "acknowledged": { "$$unsetOrMatches": false } } } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "delete": "coll0", "deletes": [ { "q": { "_id": { "$gt": 1 } }, "hint": { "$$type": [ "string", "object" ] }, "limit": 0 } ], "writeConcern": { "w": 0 } } } } ] } ] }, { "description": "Unacknowledged deleteMany with hint document on 4.4+ server", "runOnRequirements": [ { "minServerVersion": "4.4.0" } ], "operations": [ { "object": "collection0", "name": "bulkWrite", "arguments": { "requests": [ { "deleteMany": { "filter": { "_id": { "$gt": 1 } }, "hint": { "_id": 1 } } } ] }, "expectResult": { "$$unsetOrMatches": { "acknowledged": { "$$unsetOrMatches": false } } } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "delete": "coll0", "deletes": [ { "q": { "_id": { "$gt": 1 } }, "hint": { "$$type": [ "string", "object" ] }, "limit": 0 } ], "writeConcern": { "w": 0 } } } } ] } ] } ] } mongodb-mongo-python-driver-509e9b7/test/crud/unified/bulkWrite-deleteMany-let.json000066400000000000000000000103731462766011000305120ustar00rootroot00000000000000{ "description": "BulkWrite deleteMany-let", "schemaVersion": "1.0", "createEntities": [ { "client": { "id": "client0", "observeEvents": [ "commandStartedEvent" ] } }, { "database": { "id": "database0", "client": "client0", "databaseName": "crud-tests" } }, { "collection": { "id": "collection0", "database": "database0", "collectionName": "coll0" } } ], "initialData": [ { "collectionName": "coll0", "databaseName": "crud-tests", "documents": [ { "_id": 1 }, { "_id": 2 } ] } ], "tests": [ { "description": "BulkWrite deleteMany with let option", "runOnRequirements": [ { "minServerVersion": "5.0" } ], "operations": [ { "object": "collection0", "name": "bulkWrite", "arguments": { "requests": [ { "deleteMany": { "filter": { "$expr": { "$eq": [ "$_id", "$$id" ] } } } } ], "let": { "id": 1 } } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "delete": "coll0", "deletes": [ { "q": { "$expr": { "$eq": [ "$_id", "$$id" ] } }, "limit": 0 } ], "let": { "id": 1 } } } } ] } ], "outcome": [ { "collectionName": "coll0", "databaseName": "crud-tests", "documents": [ { "_id": 2 } ] } ] }, { "description": "BulkWrite deleteMany with let option unsupported (server-side error)", "runOnRequirements": [ { "minServerVersion": "3.6.0", "maxServerVersion": "4.4.99" } ], "operations": [ { "object": "collection0", "name": "bulkWrite", "arguments": { "requests": [ { "deleteOne": { "filter": { "$expr": { "$eq": [ "$_id", "$$id" ] } } } } ], "let": { "id": 1 } }, "expectError": { "errorContains": "'delete.let' is an unknown field", "isClientError": false } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "delete": "coll0", "deletes": [ { "q": { "$expr": { "$eq": [ "$_id", "$$id" ] } }, "limit": 1 } ], "let": { "id": 1 } } } } ] } ], "outcome": [ { "collectionName": "coll0", "databaseName": "crud-tests", "documents": [ { "_id": 1 }, { "_id": 2 } ] } ] } ] } mongodb-mongo-python-driver-509e9b7/test/crud/unified/bulkWrite-deleteOne-hint-unacknowledged.json000066400000000000000000000134701462766011000334760ustar00rootroot00000000000000{ "description": "bulkWrite-deleteOne-hint-unacknowledged", "schemaVersion": "1.0", "createEntities": [ { "client": { "id": "client0", "observeEvents": [ "commandStartedEvent" ] } }, { "database": { "id": "database0", "client": "client0", "databaseName": "db0" } }, { "collection": { "id": "collection0", "database": "database0", "collectionName": "coll0", "collectionOptions": { "writeConcern": { "w": 0 } } } } ], "initialData": [ { "collectionName": "coll0", "databaseName": "db0", "documents": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 22 } ] } ], "tests": [ { "description": "Unacknowledged deleteOne with hint string fails with client-side error on pre-4.4 server", "runOnRequirements": [ { "maxServerVersion": "4.2.99" } ], "operations": [ { "object": "collection0", "name": "bulkWrite", "arguments": { "requests": [ { "deleteOne": { "filter": { "_id": { "$gt": 1 } }, "hint": "_id_" } } ] }, "expectError": { "isClientError": true } } ], "expectEvents": [ { "client": "client0", "events": [] } ] }, { "description": "Unacknowledged deleteOne with hint document fails with client-side error on pre-4.4 server", "runOnRequirements": [ { "maxServerVersion": "4.2.99" } ], "operations": [ { "object": "collection0", "name": "bulkWrite", "arguments": { "requests": [ { "deleteOne": { "filter": { "_id": { "$gt": 1 } }, "hint": { "_id": 1 } } } ] }, "expectError": { "isClientError": true } } ], "expectEvents": [ { "client": "client0", "events": [] } ] }, { "description": "Unacknowledged deleteOne with hint string on 4.4+ server", "runOnRequirements": [ { "minServerVersion": "4.4.0" } ], "operations": [ { "object": "collection0", "name": "bulkWrite", "arguments": { "requests": [ { "deleteOne": { "filter": { "_id": { "$gt": 1 } }, "hint": "_id_" } } ] }, "expectResult": { "$$unsetOrMatches": { "acknowledged": { "$$unsetOrMatches": false } } } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "delete": "coll0", "deletes": [ { "q": { "_id": { "$gt": 1 } }, "hint": { "$$type": [ "string", "object" ] }, "limit": 1 } ], "writeConcern": { "w": 0 } } } } ] } ] }, { "description": "Unacknowledged deleteOne with hint document on 4.4+ server", "runOnRequirements": [ { "minServerVersion": "4.4.0" } ], "operations": [ { "object": "collection0", "name": "bulkWrite", "arguments": { "requests": [ { "deleteOne": { "filter": { "_id": { "$gt": 1 } }, "hint": { "_id": 1 } } } ] }, "expectResult": { "$$unsetOrMatches": { "acknowledged": { "$$unsetOrMatches": false } } } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "delete": "coll0", "deletes": [ { "q": { "_id": { "$gt": 1 } }, "hint": { "$$type": [ "string", "object" ] }, "limit": 1 } ], "writeConcern": { "w": 0 } } } } ] } ] } ] } mongodb-mongo-python-driver-509e9b7/test/crud/unified/bulkWrite-deleteOne-let.json000066400000000000000000000103641462766011000303270ustar00rootroot00000000000000{ "description": "BulkWrite deleteOne-let", "schemaVersion": "1.0", "createEntities": [ { "client": { "id": "client0", "observeEvents": [ "commandStartedEvent" ] } }, { "database": { "id": "database0", "client": "client0", "databaseName": "crud-tests" } }, { "collection": { "id": "collection0", "database": "database0", "collectionName": "coll0" } } ], "initialData": [ { "collectionName": "coll0", "databaseName": "crud-tests", "documents": [ { "_id": 1 }, { "_id": 2 } ] } ], "tests": [ { "description": "BulkWrite deleteOne with let option", "runOnRequirements": [ { "minServerVersion": "5.0" } ], "operations": [ { "object": "collection0", "name": "bulkWrite", "arguments": { "requests": [ { "deleteOne": { "filter": { "$expr": { "$eq": [ "$_id", "$$id" ] } } } } ], "let": { "id": 1 } } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "delete": "coll0", "deletes": [ { "q": { "$expr": { "$eq": [ "$_id", "$$id" ] } }, "limit": 1 } ], "let": { "id": 1 } } } } ] } ], "outcome": [ { "collectionName": "coll0", "databaseName": "crud-tests", "documents": [ { "_id": 2 } ] } ] }, { "description": "BulkWrite deleteOne with let option unsupported (server-side error)", "runOnRequirements": [ { "minServerVersion": "3.6.0", "maxServerVersion": "4.9" } ], "operations": [ { "object": "collection0", "name": "bulkWrite", "arguments": { "requests": [ { "deleteOne": { "filter": { "$expr": { "$eq": [ "$_id", "$$id" ] } } } } ], "let": { "id": 1 } }, "expectError": { "errorContains": "'delete.let' is an unknown field", "isClientError": false } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "delete": "coll0", "deletes": [ { "q": { "$expr": { "$eq": [ "$_id", "$$id" ] } }, "limit": 1 } ], "let": { "id": 1 } } } } ] } ], "outcome": [ { "collectionName": "coll0", "databaseName": "crud-tests", "documents": [ { "_id": 1 }, { "_id": 2 } ] } ] } ] } mongodb-mongo-python-driver-509e9b7/test/crud/unified/bulkWrite-errorResponse.json000066400000000000000000000034621462766011000305120ustar00rootroot00000000000000{ "description": "bulkWrite-errorResponse", "schemaVersion": "1.12", "createEntities": [ { "client": { "id": "client0", "useMultipleMongoses": false } }, { "database": { "id": "database0", "client": "client0", "databaseName": "crud-tests" } }, { "collection": { "id": "collection0", "database": "database0", "collectionName": "test" } } ], "tests": [ { "description": "bulkWrite operations support errorResponse assertions", "runOnRequirements": [ { "minServerVersion": "4.0.0", "topologies": [ "single", "replicaset" ] }, { "minServerVersion": "4.2.0", "topologies": [ "sharded" ] } ], "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "client0", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "insert" ], "errorCode": 8 } } } }, { "name": "bulkWrite", "object": "collection0", "arguments": { "requests": [ { "insertOne": { "document": { "_id": 1 } } } ] }, "expectError": { "errorCode": 8, "errorResponse": { "code": 8 } } } ] } ] } mongodb-mongo-python-driver-509e9b7/test/crud/unified/bulkWrite-insertOne-dots_and_dollars.json000066400000000000000000000202441462766011000331160ustar00rootroot00000000000000{ "description": "bulkWrite-insertOne-dots_and_dollars", "schemaVersion": "1.0", "createEntities": [ { "client": { "id": "client0", "observeEvents": [ "commandStartedEvent" ] } }, { "database": { "id": "database0", "client": "client0", "databaseName": "crud-tests" } }, { "collection": { "id": "collection0", "database": "database0", "collectionName": "coll0" } } ], "initialData": [ { "collectionName": "coll0", "databaseName": "crud-tests", "documents": [] } ], "tests": [ { "description": "Inserting document with top-level dollar-prefixed key on 5.0+ server", "runOnRequirements": [ { "minServerVersion": "5.0" } ], "operations": [ { "name": "bulkWrite", "object": "collection0", "arguments": { "requests": [ { "insertOne": { "document": { "_id": 1, "$a": 1 } } } ] }, "expectResult": { "deletedCount": 0, "insertedCount": 1, "insertedIds": { "$$unsetOrMatches": { "0": 1 } }, "matchedCount": 0, "modifiedCount": 0, "upsertedCount": 0, "upsertedIds": {} } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "insert": "coll0", "documents": [ { "_id": 1, "$a": 1 } ] } } } ] } ], "outcome": [ { "collectionName": "coll0", "databaseName": "crud-tests", "documents": [ { "_id": 1, "$a": 1 } ] } ] }, { "description": "Inserting document with top-level dollar-prefixed key on pre-5.0 server yields server-side error", "runOnRequirements": [ { "maxServerVersion": "4.99" } ], "operations": [ { "name": "bulkWrite", "object": "collection0", "arguments": { "requests": [ { "insertOne": { "document": { "_id": 1, "$a": 1 } } } ] }, "expectError": { "isClientError": false } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "insert": "coll0", "documents": [ { "_id": 1, "$a": 1 } ] } } } ] } ], "outcome": [ { "collectionName": "coll0", "databaseName": "crud-tests", "documents": [] } ] }, { "description": "Inserting document with top-level dotted key", "operations": [ { "name": "bulkWrite", "object": "collection0", "arguments": { "requests": [ { "insertOne": { "document": { "_id": 1, "a.b": 1 } } } ] }, "expectResult": { "deletedCount": 0, "insertedCount": 1, "insertedIds": { "$$unsetOrMatches": { "0": 1 } }, "matchedCount": 0, "modifiedCount": 0, "upsertedCount": 0, "upsertedIds": {} } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "insert": "coll0", "documents": [ { "_id": 1, "a.b": 1 } ] } } } ] } ], "outcome": [ { "collectionName": "coll0", "databaseName": "crud-tests", "documents": [ { "_id": 1, "a.b": 1 } ] } ] }, { "description": "Inserting document with dollar-prefixed key in embedded doc", "operations": [ { "name": "bulkWrite", "object": "collection0", "arguments": { "requests": [ { "insertOne": { "document": { "_id": 1, "a": { "$b": 1 } } } } ] }, "expectResult": { "deletedCount": 0, "insertedCount": 1, "insertedIds": { "$$unsetOrMatches": { "0": 1 } }, "matchedCount": 0, "modifiedCount": 0, "upsertedCount": 0, "upsertedIds": {} } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "insert": "coll0", "documents": [ { "_id": 1, "a": { "$b": 1 } } ] } } } ] } ], "outcome": [ { "collectionName": "coll0", "databaseName": "crud-tests", "documents": [ { "_id": 1, "a": { "$b": 1 } } ] } ] }, { "description": "Inserting document with dotted key in embedded doc", "operations": [ { "name": "bulkWrite", "object": "collection0", "arguments": { "requests": [ { "insertOne": { "document": { "_id": 1, "a": { "b.c": 1 } } } } ] }, "expectResult": { "deletedCount": 0, "insertedCount": 1, "insertedIds": { "$$unsetOrMatches": { "0": 1 } }, "matchedCount": 0, "modifiedCount": 0, "upsertedCount": 0, "upsertedIds": {} } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "insert": "coll0", "documents": [ { "_id": 1, "a": { "b.c": 1 } } ] } } } ] } ], "outcome": [ { "collectionName": "coll0", "databaseName": "crud-tests", "documents": [ { "_id": 1, "a": { "b.c": 1 } } ] } ] } ] } mongodb-mongo-python-driver-509e9b7/test/crud/unified/bulkWrite-replaceOne-dots_and_dollars.json000066400000000000000000000305441462766011000332310ustar00rootroot00000000000000{ "description": "bulkWrite-replaceOne-dots_and_dollars", "schemaVersion": "1.0", "createEntities": [ { "client": { "id": "client0", "observeEvents": [ "commandStartedEvent" ] } }, { "database": { "id": "database0", "client": "client0", "databaseName": "crud-tests" } }, { "collection": { "id": "collection0", "database": "database0", "collectionName": "coll0" } } ], "initialData": [ { "collectionName": "coll0", "databaseName": "crud-tests", "documents": [ { "_id": 1 } ] } ], "tests": [ { "description": "Replacing document with top-level dotted key on 3.6+ server", "runOnRequirements": [ { "minServerVersion": "3.6" } ], "operations": [ { "name": "bulkWrite", "object": "collection0", "arguments": { "requests": [ { "replaceOne": { "filter": { "_id": 1 }, "replacement": { "_id": 1, "a.b": 1 } } } ] }, "expectResult": { "deletedCount": 0, "insertedCount": 0, "insertedIds": { "$$unsetOrMatches": {} }, "matchedCount": 1, "modifiedCount": 1, "upsertedCount": 0, "upsertedIds": {} } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "update": "coll0", "updates": [ { "q": { "_id": 1 }, "u": { "_id": 1, "a.b": 1 }, "multi": { "$$unsetOrMatches": false }, "upsert": { "$$unsetOrMatches": false } } ] } } } ] } ], "outcome": [ { "collectionName": "coll0", "databaseName": "crud-tests", "documents": [ { "_id": 1, "a.b": 1 } ] } ] }, { "description": "Replacing document with top-level dotted key on pre-3.6 server yields server-side error", "runOnRequirements": [ { "maxServerVersion": "3.4.99" } ], "operations": [ { "name": "bulkWrite", "object": "collection0", "arguments": { "requests": [ { "replaceOne": { "filter": { "_id": 1 }, "replacement": { "_id": 1, "a.b": 1 } } } ] }, "expectError": { "isClientError": false } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "update": "coll0", "updates": [ { "q": { "_id": 1 }, "u": { "_id": 1, "a.b": 1 }, "multi": { "$$unsetOrMatches": false }, "upsert": { "$$unsetOrMatches": false } } ] } } } ] } ], "outcome": [ { "collectionName": "coll0", "databaseName": "crud-tests", "documents": [ { "_id": 1 } ] } ] }, { "description": "Replacing document with dollar-prefixed key in embedded doc on 5.0+ server", "runOnRequirements": [ { "minServerVersion": "5.0" } ], "operations": [ { "name": "bulkWrite", "object": "collection0", "arguments": { "requests": [ { "replaceOne": { "filter": { "_id": 1 }, "replacement": { "_id": 1, "a": { "$b": 1 } } } } ] }, "expectResult": { "deletedCount": 0, "insertedCount": 0, "insertedIds": { "$$unsetOrMatches": {} }, "matchedCount": 1, "modifiedCount": 1, "upsertedCount": 0, "upsertedIds": {} } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "update": "coll0", "updates": [ { "q": { "_id": 1 }, "u": { "_id": 1, "a": { "$b": 1 } }, "multi": { "$$unsetOrMatches": false }, "upsert": { "$$unsetOrMatches": false } } ] } } } ] } ], "outcome": [ { "collectionName": "coll0", "databaseName": "crud-tests", "documents": [ { "_id": 1, "a": { "$b": 1 } } ] } ] }, { "description": "Replacing document with dollar-prefixed key in embedded doc on pre-5.0 server yields server-side error", "runOnRequirements": [ { "maxServerVersion": "4.99" } ], "operations": [ { "name": "bulkWrite", "object": "collection0", "arguments": { "requests": [ { "replaceOne": { "filter": { "_id": 1 }, "replacement": { "_id": 1, "a": { "$b": 1 } } } } ] }, "expectError": { "isClientError": false } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "update": "coll0", "updates": [ { "q": { "_id": 1 }, "u": { "_id": 1, "a": { "$b": 1 } }, "multi": { "$$unsetOrMatches": false }, "upsert": { "$$unsetOrMatches": false } } ] } } } ] } ], "outcome": [ { "collectionName": "coll0", "databaseName": "crud-tests", "documents": [ { "_id": 1 } ] } ] }, { "description": "Replacing document with dotted key in embedded doc on 3.6+ server", "runOnRequirements": [ { "minServerVersion": "3.6" } ], "operations": [ { "name": "bulkWrite", "object": "collection0", "arguments": { "requests": [ { "replaceOne": { "filter": { "_id": 1 }, "replacement": { "_id": 1, "a": { "b.c": 1 } } } } ] }, "expectResult": { "deletedCount": 0, "insertedCount": 0, "insertedIds": { "$$unsetOrMatches": {} }, "matchedCount": 1, "modifiedCount": 1, "upsertedCount": 0, "upsertedIds": {} } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "update": "coll0", "updates": [ { "q": { "_id": 1 }, "u": { "_id": 1, "a": { "b.c": 1 } }, "multi": { "$$unsetOrMatches": false }, "upsert": { "$$unsetOrMatches": false } } ] } } } ] } ], "outcome": [ { "collectionName": "coll0", "databaseName": "crud-tests", "documents": [ { "_id": 1, "a": { "b.c": 1 } } ] } ] }, { "description": "Replacing document with dotted key in embedded doc on pre-3.6 server yields server-side error", "runOnRequirements": [ { "maxServerVersion": "3.4.99" } ], "operations": [ { "name": "bulkWrite", "object": "collection0", "arguments": { "requests": [ { "replaceOne": { "filter": { "_id": 1 }, "replacement": { "_id": 1, "a": { "b.c": 1 } } } } ] }, "expectError": { "isClientError": false } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "update": "coll0", "updates": [ { "q": { "_id": 1 }, "u": { "_id": 1, "a": { "b.c": 1 } }, "multi": { "$$unsetOrMatches": false }, "upsert": { "$$unsetOrMatches": false } } ] } } } ] } ], "outcome": [ { "collectionName": "coll0", "databaseName": "crud-tests", "documents": [ { "_id": 1 } ] } ] } ] } mongodb-mongo-python-driver-509e9b7/test/crud/unified/bulkWrite-replaceOne-hint-unacknowledged.json000066400000000000000000000152611462766011000336470ustar00rootroot00000000000000{ "description": "bulkWrite-replaceOne-hint-unacknowledged", "schemaVersion": "1.0", "createEntities": [ { "client": { "id": "client0", "observeEvents": [ "commandStartedEvent" ] } }, { "database": { "id": "database0", "client": "client0", "databaseName": "db0" } }, { "collection": { "id": "collection0", "database": "database0", "collectionName": "coll0", "collectionOptions": { "writeConcern": { "w": 0 } } } } ], "initialData": [ { "collectionName": "coll0", "databaseName": "db0", "documents": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 22 } ] } ], "tests": [ { "description": "Unacknowledged replaceOne with hint string fails with client-side error on pre-4.2 server", "runOnRequirements": [ { "maxServerVersion": "4.0.99" } ], "operations": [ { "object": "collection0", "name": "bulkWrite", "arguments": { "requests": [ { "replaceOne": { "filter": { "_id": { "$gt": 1 } }, "replacement": { "x": 111 }, "hint": "_id_" } } ] }, "expectError": { "isClientError": true } } ], "expectEvents": [ { "client": "client0", "events": [] } ] }, { "description": "Unacknowledged replaceOne with hint document fails with client-side error on pre-4.2 server", "runOnRequirements": [ { "maxServerVersion": "4.0.99" } ], "operations": [ { "object": "collection0", "name": "bulkWrite", "arguments": { "requests": [ { "replaceOne": { "filter": { "_id": { "$gt": 1 } }, "replacement": { "x": 111 }, "hint": { "_id": 1 } } } ] }, "expectError": { "isClientError": true } } ], "expectEvents": [ { "client": "client0", "events": [] } ] }, { "description": "Unacknowledged replaceOne with hint string on 4.2+ server", "runOnRequirements": [ { "minServerVersion": "4.2.0" } ], "operations": [ { "object": "collection0", "name": "bulkWrite", "arguments": { "requests": [ { "replaceOne": { "filter": { "_id": { "$gt": 1 } }, "replacement": { "x": 111 }, "hint": "_id_" } } ] }, "expectResult": { "$$unsetOrMatches": { "acknowledged": { "$$unsetOrMatches": false } } } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "update": "coll0", "updates": [ { "q": { "_id": { "$gt": 1 } }, "u": { "x": 111 }, "multi": { "$$unsetOrMatches": false }, "upsert": { "$$unsetOrMatches": false }, "hint": { "$$type": [ "string", "object" ] } } ], "writeConcern": { "w": 0 } } } } ] } ] }, { "description": "Unacknowledged replaceOne with hint document on 4.2+ server", "runOnRequirements": [ { "minServerVersion": "4.2.0" } ], "operations": [ { "object": "collection0", "name": "bulkWrite", "arguments": { "requests": [ { "replaceOne": { "filter": { "_id": { "$gt": 1 } }, "replacement": { "x": 111 }, "hint": { "_id": 1 } } } ] }, "expectResult": { "$$unsetOrMatches": { "acknowledged": { "$$unsetOrMatches": false } } } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "update": "coll0", "updates": [ { "q": { "_id": { "$gt": 1 } }, "u": { "x": 111 }, "multi": { "$$unsetOrMatches": false }, "upsert": { "$$unsetOrMatches": false }, "hint": { "$$type": [ "string", "object" ] } } ], "writeConcern": { "w": 0 } } } } ] } ] } ] } mongodb-mongo-python-driver-509e9b7/test/crud/unified/bulkWrite-replaceOne-let.json000066400000000000000000000117771462766011000305110ustar00rootroot00000000000000{ "description": "BulkWrite replaceOne-let", "schemaVersion": "1.0", "createEntities": [ { "client": { "id": "client0", "observeEvents": [ "commandStartedEvent" ] } }, { "database": { "id": "database0", "client": "client0", "databaseName": "crud-tests" } }, { "collection": { "id": "collection0", "database": "database0", "collectionName": "coll0" } } ], "initialData": [ { "collectionName": "coll0", "databaseName": "crud-tests", "documents": [ { "_id": 1 }, { "_id": 2 } ] } ], "tests": [ { "description": "BulkWrite replaceOne with let option", "runOnRequirements": [ { "minServerVersion": "5.0" } ], "operations": [ { "object": "collection0", "name": "bulkWrite", "arguments": { "requests": [ { "replaceOne": { "filter": { "$expr": { "$eq": [ "$_id", "$$id" ] } }, "replacement": { "x": 3 } } } ], "let": { "id": 1 } } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "update": "coll0", "updates": [ { "q": { "$expr": { "$eq": [ "$_id", "$$id" ] } }, "u": { "x": 3 }, "multi": { "$$unsetOrMatches": false }, "upsert": { "$$unsetOrMatches": false } } ], "let": { "id": 1 } } } } ] } ], "outcome": [ { "collectionName": "coll0", "databaseName": "crud-tests", "documents": [ { "_id": 1, "x": 3 }, { "_id": 2 } ] } ] }, { "description": "BulkWrite replaceOne with let option unsupported (server-side error)", "runOnRequirements": [ { "minServerVersion": "4.2", "maxServerVersion": "4.9" } ], "operations": [ { "object": "collection0", "name": "bulkWrite", "arguments": { "requests": [ { "replaceOne": { "filter": { "$expr": { "$eq": [ "$_id", "$$id" ] } }, "replacement": { "x": 3 } } } ], "let": { "id": 1 } }, "expectError": { "errorContains": "'update.let' is an unknown field", "isClientError": false } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "update": "coll0", "updates": [ { "q": { "$expr": { "$eq": [ "$_id", "$$id" ] } }, "u": { "x": 3 }, "multi": { "$$unsetOrMatches": false }, "upsert": { "$$unsetOrMatches": false } } ], "let": { "id": 1 } } } } ] } ], "outcome": [ { "collectionName": "coll0", "databaseName": "crud-tests", "documents": [ { "_id": 1 }, { "_id": 2 } ] } ] } ] } mongodb-mongo-python-driver-509e9b7/test/crud/unified/bulkWrite-update-hint-clientError.json000066400000000000000000000136701462766011000323540ustar00rootroot00000000000000{ "description": "bulkWrite-update-hint-clientError", "schemaVersion": "1.0", "runOnRequirements": [ { "maxServerVersion": "3.3.99" } ], "createEntities": [ { "client": { "id": "client0", "observeEvents": [ "commandStartedEvent" ] } }, { "database": { "id": "database0", "client": "client0", "databaseName": "crud-v2" } }, { "collection": { "id": "collection0", "database": "database0", "collectionName": "test_bulkwrite_update_hint" } } ], "initialData": [ { "collectionName": "test_bulkwrite_update_hint", "databaseName": "crud-v2", "documents": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 22 }, { "_id": 3, "x": 33 }, { "_id": 4, "x": 44 } ] } ], "tests": [ { "description": "BulkWrite updateOne with update hints unsupported (client-side error)", "operations": [ { "object": "collection0", "name": "bulkWrite", "arguments": { "requests": [ { "updateOne": { "filter": { "_id": 1 }, "update": { "$inc": { "x": 1 } }, "hint": "_id_" } }, { "updateOne": { "filter": { "_id": 1 }, "update": { "$inc": { "x": 1 } }, "hint": { "_id": 1 } } } ], "ordered": true }, "expectError": { "isError": true } } ], "expectEvents": [ { "client": "client0", "events": [] } ], "outcome": [ { "collectionName": "test_bulkwrite_update_hint", "databaseName": "crud-v2", "documents": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 22 }, { "_id": 3, "x": 33 }, { "_id": 4, "x": 44 } ] } ] }, { "description": "BulkWrite updateMany with update hints unsupported (client-side error)", "operations": [ { "object": "collection0", "name": "bulkWrite", "arguments": { "requests": [ { "updateMany": { "filter": { "_id": { "$lt": 3 } }, "update": { "$inc": { "x": 1 } }, "hint": "_id_" } }, { "updateMany": { "filter": { "_id": { "$lt": 3 } }, "update": { "$inc": { "x": 1 } }, "hint": { "_id": 1 } } } ], "ordered": true }, "expectError": { "isError": true } } ], "expectEvents": [ { "client": "client0", "events": [] } ], "outcome": [ { "collectionName": "test_bulkwrite_update_hint", "databaseName": "crud-v2", "documents": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 22 }, { "_id": 3, "x": 33 }, { "_id": 4, "x": 44 } ] } ] }, { "description": "BulkWrite replaceOne with update hints unsupported (client-side error)", "operations": [ { "object": "collection0", "name": "bulkWrite", "arguments": { "requests": [ { "replaceOne": { "filter": { "_id": 3 }, "replacement": { "x": 333 }, "hint": "_id_" } }, { "replaceOne": { "filter": { "_id": 4 }, "replacement": { "x": 444 }, "hint": { "_id": 1 } } } ], "ordered": true }, "expectError": { "isError": true } } ], "expectEvents": [ { "client": "client0", "events": [] } ], "outcome": [ { "collectionName": "test_bulkwrite_update_hint", "databaseName": "crud-v2", "documents": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 22 }, { "_id": 3, "x": 33 }, { "_id": 4, "x": 44 } ] } ] } ] } mongodb-mongo-python-driver-509e9b7/test/crud/unified/bulkWrite-update-hint-serverError.json000066400000000000000000000236741462766011000324110ustar00rootroot00000000000000{ "description": "bulkWrite-update-hint-serverError", "schemaVersion": "1.0", "runOnRequirements": [ { "minServerVersion": "3.4.0", "maxServerVersion": "4.1.9" } ], "createEntities": [ { "client": { "id": "client0", "observeEvents": [ "commandStartedEvent" ] } }, { "database": { "id": "database0", "client": "client0", "databaseName": "crud-v2" } }, { "collection": { "id": "collection0", "database": "database0", "collectionName": "test_bulkwrite_update_hint" } } ], "initialData": [ { "collectionName": "test_bulkwrite_update_hint", "databaseName": "crud-v2", "documents": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 22 }, { "_id": 3, "x": 33 }, { "_id": 4, "x": 44 } ] } ], "tests": [ { "description": "BulkWrite updateOne with update hints unsupported (server-side error)", "operations": [ { "object": "collection0", "name": "bulkWrite", "arguments": { "requests": [ { "updateOne": { "filter": { "_id": 1 }, "update": { "$inc": { "x": 1 } }, "hint": "_id_" } }, { "updateOne": { "filter": { "_id": 1 }, "update": { "$inc": { "x": 1 } }, "hint": { "_id": 1 } } } ], "ordered": true }, "expectError": { "isError": true } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "update": "test_bulkwrite_update_hint", "updates": [ { "q": { "_id": 1 }, "u": { "$inc": { "x": 1 } }, "hint": "_id_", "multi": { "$$unsetOrMatches": false }, "upsert": { "$$unsetOrMatches": false } }, { "q": { "_id": 1 }, "u": { "$inc": { "x": 1 } }, "hint": { "_id": 1 }, "multi": { "$$unsetOrMatches": false }, "upsert": { "$$unsetOrMatches": false } } ], "ordered": true } } } ] } ], "outcome": [ { "collectionName": "test_bulkwrite_update_hint", "databaseName": "crud-v2", "documents": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 22 }, { "_id": 3, "x": 33 }, { "_id": 4, "x": 44 } ] } ] }, { "description": "BulkWrite updateMany with update hints unsupported (server-side error)", "operations": [ { "object": "collection0", "name": "bulkWrite", "arguments": { "requests": [ { "updateMany": { "filter": { "_id": { "$lt": 3 } }, "update": { "$inc": { "x": 1 } }, "hint": "_id_" } }, { "updateMany": { "filter": { "_id": { "$lt": 3 } }, "update": { "$inc": { "x": 1 } }, "hint": { "_id": 1 } } } ], "ordered": true }, "expectError": { "isError": true } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "update": "test_bulkwrite_update_hint", "updates": [ { "q": { "_id": { "$lt": 3 } }, "u": { "$inc": { "x": 1 } }, "multi": true, "hint": "_id_", "upsert": { "$$unsetOrMatches": false } }, { "q": { "_id": { "$lt": 3 } }, "u": { "$inc": { "x": 1 } }, "multi": true, "hint": { "_id": 1 }, "upsert": { "$$unsetOrMatches": false } } ], "ordered": true } } } ] } ], "outcome": [ { "collectionName": "test_bulkwrite_update_hint", "databaseName": "crud-v2", "documents": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 22 }, { "_id": 3, "x": 33 }, { "_id": 4, "x": 44 } ] } ] }, { "description": "BulkWrite replaceOne with update hints unsupported (server-side error)", "operations": [ { "object": "collection0", "name": "bulkWrite", "arguments": { "requests": [ { "replaceOne": { "filter": { "_id": 3 }, "replacement": { "x": 333 }, "hint": "_id_" } }, { "replaceOne": { "filter": { "_id": 4 }, "replacement": { "x": 444 }, "hint": { "_id": 1 } } } ], "ordered": true }, "expectError": { "isError": true } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "update": "test_bulkwrite_update_hint", "updates": [ { "q": { "_id": 3 }, "u": { "x": 333 }, "hint": "_id_", "multi": { "$$unsetOrMatches": false }, "upsert": { "$$unsetOrMatches": false } }, { "q": { "_id": 4 }, "u": { "x": 444 }, "hint": { "_id": 1 }, "multi": { "$$unsetOrMatches": false }, "upsert": { "$$unsetOrMatches": false } } ], "ordered": true } } } ] } ], "outcome": [ { "collectionName": "test_bulkwrite_update_hint", "databaseName": "crud-v2", "documents": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 22 }, { "_id": 3, "x": 33 }, { "_id": 4, "x": 44 } ] } ] } ] } mongodb-mongo-python-driver-509e9b7/test/crud/unified/bulkWrite-update-hint.json000066400000000000000000000250051462766011000300610ustar00rootroot00000000000000{ "description": "bulkWrite-update-hint", "schemaVersion": "1.0", "runOnRequirements": [ { "minServerVersion": "4.2.0" } ], "createEntities": [ { "client": { "id": "client0", "observeEvents": [ "commandStartedEvent" ] } }, { "database": { "id": "database0", "client": "client0", "databaseName": "crud-v2" } }, { "collection": { "id": "collection0", "database": "database0", "collectionName": "test_bulkwrite_update_hint" } } ], "initialData": [ { "collectionName": "test_bulkwrite_update_hint", "databaseName": "crud-v2", "documents": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 22 }, { "_id": 3, "x": 33 }, { "_id": 4, "x": 44 } ] } ], "tests": [ { "description": "BulkWrite updateOne with update hints", "operations": [ { "object": "collection0", "name": "bulkWrite", "arguments": { "requests": [ { "updateOne": { "filter": { "_id": 1 }, "update": { "$inc": { "x": 1 } }, "hint": "_id_" } }, { "updateOne": { "filter": { "_id": 1 }, "update": { "$inc": { "x": 1 } }, "hint": { "_id": 1 } } } ], "ordered": true }, "expectResult": { "deletedCount": 0, "insertedCount": 0, "insertedIds": { "$$unsetOrMatches": {} }, "matchedCount": 2, "modifiedCount": 2, "upsertedCount": 0, "upsertedIds": {} } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "update": "test_bulkwrite_update_hint", "updates": [ { "q": { "_id": 1 }, "u": { "$inc": { "x": 1 } }, "multi": { "$$unsetOrMatches": false }, "upsert": { "$$unsetOrMatches": false }, "hint": "_id_" }, { "q": { "_id": 1 }, "u": { "$inc": { "x": 1 } }, "multi": { "$$unsetOrMatches": false }, "upsert": { "$$unsetOrMatches": false }, "hint": { "_id": 1 } } ], "ordered": true } } } ] } ], "outcome": [ { "collectionName": "test_bulkwrite_update_hint", "databaseName": "crud-v2", "documents": [ { "_id": 1, "x": 13 }, { "_id": 2, "x": 22 }, { "_id": 3, "x": 33 }, { "_id": 4, "x": 44 } ] } ] }, { "description": "BulkWrite updateMany with update hints", "operations": [ { "object": "collection0", "name": "bulkWrite", "arguments": { "requests": [ { "updateMany": { "filter": { "_id": { "$lt": 3 } }, "update": { "$inc": { "x": 1 } }, "hint": "_id_" } }, { "updateMany": { "filter": { "_id": { "$lt": 3 } }, "update": { "$inc": { "x": 1 } }, "hint": { "_id": 1 } } } ], "ordered": true }, "expectResult": { "deletedCount": 0, "insertedCount": 0, "insertedIds": { "$$unsetOrMatches": {} }, "matchedCount": 4, "modifiedCount": 4, "upsertedCount": 0, "upsertedIds": {} } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "update": "test_bulkwrite_update_hint", "updates": [ { "q": { "_id": { "$lt": 3 } }, "u": { "$inc": { "x": 1 } }, "multi": true, "upsert": { "$$unsetOrMatches": false }, "hint": "_id_" }, { "q": { "_id": { "$lt": 3 } }, "u": { "$inc": { "x": 1 } }, "multi": true, "upsert": { "$$unsetOrMatches": false }, "hint": { "_id": 1 } } ], "ordered": true } } } ] } ], "outcome": [ { "collectionName": "test_bulkwrite_update_hint", "databaseName": "crud-v2", "documents": [ { "_id": 1, "x": 13 }, { "_id": 2, "x": 24 }, { "_id": 3, "x": 33 }, { "_id": 4, "x": 44 } ] } ] }, { "description": "BulkWrite replaceOne with update hints", "operations": [ { "object": "collection0", "name": "bulkWrite", "arguments": { "requests": [ { "replaceOne": { "filter": { "_id": 3 }, "replacement": { "x": 333 }, "hint": "_id_" } }, { "replaceOne": { "filter": { "_id": 4 }, "replacement": { "x": 444 }, "hint": { "_id": 1 } } } ], "ordered": true }, "expectResult": { "deletedCount": 0, "insertedCount": 0, "insertedIds": { "$$unsetOrMatches": {} }, "matchedCount": 2, "modifiedCount": 2, "upsertedCount": 0, "upsertedIds": {} } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "update": "test_bulkwrite_update_hint", "updates": [ { "q": { "_id": 3 }, "u": { "x": 333 }, "multi": { "$$unsetOrMatches": false }, "upsert": { "$$unsetOrMatches": false }, "hint": "_id_" }, { "q": { "_id": 4 }, "u": { "x": 444 }, "multi": { "$$unsetOrMatches": false }, "upsert": { "$$unsetOrMatches": false }, "hint": { "_id": 1 } } ], "ordered": true } } } ] } ], "outcome": [ { "collectionName": "test_bulkwrite_update_hint", "databaseName": "crud-v2", "documents": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 22 }, { "_id": 3, "x": 333 }, { "_id": 4, "x": 444 } ] } ] } ] } mongodb-mongo-python-driver-509e9b7/test/crud/unified/bulkWrite-update-validation.json000066400000000000000000000101471462766011000312520ustar00rootroot00000000000000{ "description": "bulkWrite-update-validation", "schemaVersion": "1.0", "createEntities": [ { "client": { "id": "client0", "observeEvents": [ "commandStartedEvent" ] } }, { "database": { "id": "database0", "client": "client0", "databaseName": "crud-tests" } }, { "collection": { "id": "collection0", "database": "database0", "collectionName": "coll0" } } ], "initialData": [ { "collectionName": "coll0", "databaseName": "crud-tests", "documents": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 22 }, { "_id": 3, "x": 33 } ] } ], "tests": [ { "description": "BulkWrite replaceOne prohibits atomic modifiers", "operations": [ { "name": "bulkWrite", "object": "collection0", "arguments": { "requests": [ { "replaceOne": { "filter": { "_id": 1 }, "replacement": { "$set": { "x": 22 } } } } ] }, "expectError": { "isClientError": true } } ], "expectEvents": [ { "client": "client0", "events": [] } ], "outcome": [ { "collectionName": "coll0", "databaseName": "crud-tests", "documents": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 22 }, { "_id": 3, "x": 33 } ] } ] }, { "description": "BulkWrite updateOne requires atomic modifiers", "operations": [ { "name": "bulkWrite", "object": "collection0", "arguments": { "requests": [ { "updateOne": { "filter": { "_id": 1 }, "update": { "x": 22 } } } ] }, "expectError": { "isClientError": true } } ], "expectEvents": [ { "client": "client0", "events": [] } ], "outcome": [ { "collectionName": "coll0", "databaseName": "crud-tests", "documents": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 22 }, { "_id": 3, "x": 33 } ] } ] }, { "description": "BulkWrite updateMany requires atomic modifiers", "operations": [ { "name": "bulkWrite", "object": "collection0", "arguments": { "requests": [ { "updateMany": { "filter": { "_id": { "$gt": 1 } }, "update": { "x": 44 } } } ] }, "expectError": { "isClientError": true } } ], "expectEvents": [ { "client": "client0", "events": [] } ], "outcome": [ { "collectionName": "coll0", "databaseName": "crud-tests", "documents": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 22 }, { "_id": 3, "x": 33 } ] } ] } ] } mongodb-mongo-python-driver-509e9b7/test/crud/unified/bulkWrite-updateMany-dots_and_dollars.json000066400000000000000000000263621462766011000332660ustar00rootroot00000000000000{ "description": "bulkWrite-updateMany-dots_and_dollars", "schemaVersion": "1.0", "createEntities": [ { "client": { "id": "client0", "observeEvents": [ "commandStartedEvent" ] } }, { "database": { "id": "database0", "client": "client0", "databaseName": "crud-tests" } }, { "collection": { "id": "collection0", "database": "database0", "collectionName": "coll0" } } ], "initialData": [ { "collectionName": "coll0", "databaseName": "crud-tests", "documents": [ { "_id": 1, "foo": {} } ] } ], "tests": [ { "description": "Updating document to set top-level dollar-prefixed key on 5.0+ server", "runOnRequirements": [ { "minServerVersion": "5.0" } ], "operations": [ { "name": "bulkWrite", "object": "collection0", "arguments": { "requests": [ { "updateMany": { "filter": { "_id": 1 }, "update": [ { "$replaceWith": { "$setField": { "field": { "$literal": "$a" }, "value": 1, "input": "$$ROOT" } } } ] } } ] }, "expectResult": { "deletedCount": 0, "insertedCount": 0, "insertedIds": { "$$unsetOrMatches": {} }, "matchedCount": 1, "modifiedCount": 1, "upsertedCount": 0, "upsertedIds": {} } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "update": "coll0", "updates": [ { "q": { "_id": 1 }, "u": [ { "$replaceWith": { "$setField": { "field": { "$literal": "$a" }, "value": 1, "input": "$$ROOT" } } } ], "multi": true, "upsert": { "$$unsetOrMatches": false } } ] } } } ] } ], "outcome": [ { "collectionName": "coll0", "databaseName": "crud-tests", "documents": [ { "_id": 1, "foo": {}, "$a": 1 } ] } ] }, { "description": "Updating document to set top-level dotted key on 5.0+ server", "runOnRequirements": [ { "minServerVersion": "5.0" } ], "operations": [ { "name": "bulkWrite", "object": "collection0", "arguments": { "requests": [ { "updateMany": { "filter": { "_id": 1 }, "update": [ { "$replaceWith": { "$setField": { "field": { "$literal": "a.b" }, "value": 1, "input": "$$ROOT" } } } ] } } ] }, "expectResult": { "deletedCount": 0, "insertedCount": 0, "insertedIds": { "$$unsetOrMatches": {} }, "matchedCount": 1, "modifiedCount": 1, "upsertedCount": 0, "upsertedIds": {} } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "update": "coll0", "updates": [ { "q": { "_id": 1 }, "u": [ { "$replaceWith": { "$setField": { "field": { "$literal": "a.b" }, "value": 1, "input": "$$ROOT" } } } ], "multi": true, "upsert": { "$$unsetOrMatches": false } } ] } } } ] } ], "outcome": [ { "collectionName": "coll0", "databaseName": "crud-tests", "documents": [ { "_id": 1, "foo": {}, "a.b": 1 } ] } ] }, { "description": "Updating document to set dollar-prefixed key in embedded doc on 5.0+ server", "runOnRequirements": [ { "minServerVersion": "5.0" } ], "operations": [ { "name": "bulkWrite", "object": "collection0", "arguments": { "requests": [ { "updateMany": { "filter": { "_id": 1 }, "update": [ { "$set": { "foo": { "$setField": { "field": { "$literal": "$a" }, "value": 1, "input": "$foo" } } } } ] } } ] }, "expectResult": { "deletedCount": 0, "insertedCount": 0, "insertedIds": { "$$unsetOrMatches": {} }, "matchedCount": 1, "modifiedCount": 1, "upsertedCount": 0, "upsertedIds": {} } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "update": "coll0", "updates": [ { "q": { "_id": 1 }, "u": [ { "$set": { "foo": { "$setField": { "field": { "$literal": "$a" }, "value": 1, "input": "$foo" } } } } ], "multi": true, "upsert": { "$$unsetOrMatches": false } } ] } } } ] } ], "outcome": [ { "collectionName": "coll0", "databaseName": "crud-tests", "documents": [ { "_id": 1, "foo": { "$a": 1 } } ] } ] }, { "description": "Updating document to set dotted key in embedded doc on 5.0+ server", "runOnRequirements": [ { "minServerVersion": "5.0" } ], "operations": [ { "name": "bulkWrite", "object": "collection0", "arguments": { "requests": [ { "updateMany": { "filter": { "_id": 1 }, "update": [ { "$set": { "foo": { "$setField": { "field": { "$literal": "a.b" }, "value": 1, "input": "$foo" } } } } ] } } ] }, "expectResult": { "deletedCount": 0, "insertedCount": 0, "insertedIds": { "$$unsetOrMatches": {} }, "matchedCount": 1, "modifiedCount": 1, "upsertedCount": 0, "upsertedIds": {} } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "update": "coll0", "updates": [ { "q": { "_id": 1 }, "u": [ { "$set": { "foo": { "$setField": { "field": { "$literal": "a.b" }, "value": 1, "input": "$foo" } } } } ], "multi": true, "upsert": { "$$unsetOrMatches": false } } ] } } } ] } ], "outcome": [ { "collectionName": "coll0", "databaseName": "crud-tests", "documents": [ { "_id": 1, "foo": { "a.b": 1 } } ] } ] } ] } mongodb-mongo-python-driver-509e9b7/test/crud/unified/bulkWrite-updateMany-hint-unacknowledged.json000066400000000000000000000156221462766011000337020ustar00rootroot00000000000000{ "description": "bulkWrite-updateMany-hint-unacknowledged", "schemaVersion": "1.0", "createEntities": [ { "client": { "id": "client0", "observeEvents": [ "commandStartedEvent" ] } }, { "database": { "id": "database0", "client": "client0", "databaseName": "db0" } }, { "collection": { "id": "collection0", "database": "database0", "collectionName": "coll0", "collectionOptions": { "writeConcern": { "w": 0 } } } } ], "initialData": [ { "collectionName": "coll0", "databaseName": "db0", "documents": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 22 }, { "_id": 3, "x": 33 } ] } ], "tests": [ { "description": "Unacknowledged updateMany with hint string fails with client-side error on pre-4.2 server", "runOnRequirements": [ { "maxServerVersion": "4.0.99" } ], "operations": [ { "object": "collection0", "name": "bulkWrite", "arguments": { "requests": [ { "updateMany": { "filter": { "_id": { "$gt": 1 } }, "update": { "$inc": { "x": 1 } }, "hint": "_id_" } } ] }, "expectError": { "isClientError": true } } ], "expectEvents": [ { "client": "client0", "events": [] } ] }, { "description": "Unacknowledged updateMany with hint document fails with client-side error on pre-4.2 server", "runOnRequirements": [ { "maxServerVersion": "4.0.99" } ], "operations": [ { "object": "collection0", "name": "bulkWrite", "arguments": { "requests": [ { "updateMany": { "filter": { "_id": { "$gt": 1 } }, "update": { "$inc": { "x": 1 } }, "hint": { "_id": 1 } } } ] }, "expectError": { "isClientError": true } } ], "expectEvents": [ { "client": "client0", "events": [] } ] }, { "description": "Unacknowledged updateMany with hint string on 4.2+ server", "runOnRequirements": [ { "minServerVersion": "4.2.0" } ], "operations": [ { "object": "collection0", "name": "bulkWrite", "arguments": { "requests": [ { "updateMany": { "filter": { "_id": { "$gt": 1 } }, "update": { "$inc": { "x": 1 } }, "hint": "_id_" } } ] }, "expectResult": { "$$unsetOrMatches": { "acknowledged": { "$$unsetOrMatches": false } } } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "update": "coll0", "updates": [ { "q": { "_id": { "$gt": 1 } }, "u": { "$inc": { "x": 1 } }, "multi": true, "upsert": { "$$unsetOrMatches": false }, "hint": { "$$type": [ "string", "object" ] } } ], "writeConcern": { "w": 0 } } } } ] } ] }, { "description": "Unacknowledged updateMany with hint document on 4.2+ server", "runOnRequirements": [ { "minServerVersion": "4.2.0" } ], "operations": [ { "object": "collection0", "name": "bulkWrite", "arguments": { "requests": [ { "updateMany": { "filter": { "_id": { "$gt": 1 } }, "update": { "$inc": { "x": 1 } }, "hint": { "_id": 1 } } } ] }, "expectResult": { "$$unsetOrMatches": { "acknowledged": { "$$unsetOrMatches": false } } } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "update": "coll0", "updates": [ { "q": { "_id": { "$gt": 1 } }, "u": { "$inc": { "x": 1 } }, "multi": true, "upsert": { "$$unsetOrMatches": false }, "hint": { "$$type": [ "string", "object" ] } } ], "writeConcern": { "w": 0 } } } } ] } ] } ] } mongodb-mongo-python-driver-509e9b7/test/crud/unified/bulkWrite-updateMany-let.json000066400000000000000000000126311462766011000305310ustar00rootroot00000000000000{ "description": "BulkWrite updateMany-let", "schemaVersion": "1.0", "createEntities": [ { "client": { "id": "client0", "observeEvents": [ "commandStartedEvent" ] } }, { "database": { "id": "database0", "client": "client0", "databaseName": "crud-tests" } }, { "collection": { "id": "collection0", "database": "database0", "collectionName": "coll0" } } ], "initialData": [ { "collectionName": "coll0", "databaseName": "crud-tests", "documents": [ { "_id": 1, "x": 20 }, { "_id": 2, "x": 21 } ] } ], "tests": [ { "description": "BulkWrite updateMany with let option", "runOnRequirements": [ { "minServerVersion": "5.0" } ], "operations": [ { "object": "collection0", "name": "bulkWrite", "arguments": { "requests": [ { "updateMany": { "filter": { "$expr": { "$eq": [ "$_id", "$$id" ] } }, "update": [ { "$set": { "x": 21 } } ] } } ], "let": { "id": 1 } } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "update": "coll0", "updates": [ { "q": { "$expr": { "$eq": [ "$_id", "$$id" ] } }, "u": [ { "$set": { "x": 21 } } ], "multi": true, "upsert": { "$$unsetOrMatches": false } } ], "let": { "id": 1 } } } } ] } ], "outcome": [ { "collectionName": "coll0", "databaseName": "crud-tests", "documents": [ { "_id": 1, "x": 21 }, { "_id": 2, "x": 21 } ] } ] }, { "description": "BulkWrite updateMany with let option unsupported (server-side error)", "runOnRequirements": [ { "minServerVersion": "4.2.0", "maxServerVersion": "4.9" } ], "operations": [ { "object": "collection0", "name": "bulkWrite", "arguments": { "requests": [ { "updateMany": { "filter": { "$expr": { "$eq": [ "$_id", "$$id" ] } }, "update": [ { "$set": { "x": 21 } } ] } } ], "let": { "id": 1 } }, "expectError": { "errorContains": "'update.let' is an unknown field", "isClientError": false } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "update": "coll0", "updates": [ { "q": { "$expr": { "$eq": [ "$_id", "$$id" ] } }, "u": [ { "$set": { "x": 21 } } ], "multi": true, "upsert": { "$$unsetOrMatches": false } } ], "let": { "id": 1 } } } } ] } ], "outcome": [ { "collectionName": "coll0", "databaseName": "crud-tests", "documents": [ { "_id": 1, "x": 20 }, { "_id": 2, "x": 21 } ] } ] } ] } mongodb-mongo-python-driver-509e9b7/test/crud/unified/bulkWrite-updateOne-dots_and_dollars.json000066400000000000000000000270111462766011000330730ustar00rootroot00000000000000{ "description": "bulkWrite-updateOne-dots_and_dollars", "schemaVersion": "1.0", "createEntities": [ { "client": { "id": "client0", "observeEvents": [ "commandStartedEvent" ] } }, { "database": { "id": "database0", "client": "client0", "databaseName": "crud-tests" } }, { "collection": { "id": "collection0", "database": "database0", "collectionName": "coll0" } } ], "initialData": [ { "collectionName": "coll0", "databaseName": "crud-tests", "documents": [ { "_id": 1, "foo": {} } ] } ], "tests": [ { "description": "Updating document to set top-level dollar-prefixed key on 5.0+ server", "runOnRequirements": [ { "minServerVersion": "5.0" } ], "operations": [ { "name": "bulkWrite", "object": "collection0", "arguments": { "requests": [ { "updateOne": { "filter": { "_id": 1 }, "update": [ { "$replaceWith": { "$setField": { "field": { "$literal": "$a" }, "value": 1, "input": "$$ROOT" } } } ] } } ] }, "expectResult": { "deletedCount": 0, "insertedCount": 0, "insertedIds": { "$$unsetOrMatches": {} }, "matchedCount": 1, "modifiedCount": 1, "upsertedCount": 0, "upsertedIds": {} } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "update": "coll0", "updates": [ { "q": { "_id": 1 }, "u": [ { "$replaceWith": { "$setField": { "field": { "$literal": "$a" }, "value": 1, "input": "$$ROOT" } } } ], "multi": { "$$unsetOrMatches": false }, "upsert": { "$$unsetOrMatches": false } } ] } } } ] } ], "outcome": [ { "collectionName": "coll0", "databaseName": "crud-tests", "documents": [ { "_id": 1, "foo": {}, "$a": 1 } ] } ] }, { "description": "Updating document to set top-level dotted key on 5.0+ server", "runOnRequirements": [ { "minServerVersion": "5.0" } ], "operations": [ { "name": "bulkWrite", "object": "collection0", "arguments": { "requests": [ { "updateOne": { "filter": { "_id": 1 }, "update": [ { "$replaceWith": { "$setField": { "field": { "$literal": "a.b" }, "value": 1, "input": "$$ROOT" } } } ] } } ] }, "expectResult": { "deletedCount": 0, "insertedCount": 0, "insertedIds": { "$$unsetOrMatches": {} }, "matchedCount": 1, "modifiedCount": 1, "upsertedCount": 0, "upsertedIds": {} } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "update": "coll0", "updates": [ { "q": { "_id": 1 }, "u": [ { "$replaceWith": { "$setField": { "field": { "$literal": "a.b" }, "value": 1, "input": "$$ROOT" } } } ], "multi": { "$$unsetOrMatches": false }, "upsert": { "$$unsetOrMatches": false } } ] } } } ] } ], "outcome": [ { "collectionName": "coll0", "databaseName": "crud-tests", "documents": [ { "_id": 1, "foo": {}, "a.b": 1 } ] } ] }, { "description": "Updating document to set dollar-prefixed key in embedded doc on 5.0+ server", "runOnRequirements": [ { "minServerVersion": "5.0" } ], "operations": [ { "name": "bulkWrite", "object": "collection0", "arguments": { "requests": [ { "updateOne": { "filter": { "_id": 1 }, "update": [ { "$set": { "foo": { "$setField": { "field": { "$literal": "$a" }, "value": 1, "input": "$foo" } } } } ] } } ] }, "expectResult": { "deletedCount": 0, "insertedCount": 0, "insertedIds": { "$$unsetOrMatches": {} }, "matchedCount": 1, "modifiedCount": 1, "upsertedCount": 0, "upsertedIds": {} } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "update": "coll0", "updates": [ { "q": { "_id": 1 }, "u": [ { "$set": { "foo": { "$setField": { "field": { "$literal": "$a" }, "value": 1, "input": "$foo" } } } } ], "multi": { "$$unsetOrMatches": false }, "upsert": { "$$unsetOrMatches": false } } ] } } } ] } ], "outcome": [ { "collectionName": "coll0", "databaseName": "crud-tests", "documents": [ { "_id": 1, "foo": { "$a": 1 } } ] } ] }, { "description": "Updating document to set dotted key in embedded doc on 5.0+ server", "runOnRequirements": [ { "minServerVersion": "5.0" } ], "operations": [ { "name": "bulkWrite", "object": "collection0", "arguments": { "requests": [ { "updateOne": { "filter": { "_id": 1 }, "update": [ { "$set": { "foo": { "$setField": { "field": { "$literal": "a.b" }, "value": 1, "input": "$foo" } } } } ] } } ] }, "expectResult": { "deletedCount": 0, "insertedCount": 0, "insertedIds": { "$$unsetOrMatches": {} }, "matchedCount": 1, "modifiedCount": 1, "upsertedCount": 0, "upsertedIds": {} } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "update": "coll0", "updates": [ { "q": { "_id": 1 }, "u": [ { "$set": { "foo": { "$setField": { "field": { "$literal": "a.b" }, "value": 1, "input": "$foo" } } } } ], "multi": { "$$unsetOrMatches": false }, "upsert": { "$$unsetOrMatches": false } } ] } } } ] } ], "outcome": [ { "collectionName": "coll0", "databaseName": "crud-tests", "documents": [ { "_id": 1, "foo": { "a.b": 1 } } ] } ] } ] } mongodb-mongo-python-driver-509e9b7/test/crud/unified/bulkWrite-updateOne-hint-unacknowledged.json000066400000000000000000000157341462766011000335230ustar00rootroot00000000000000{ "description": "bulkWrite-updateOne-hint-unacknowledged", "schemaVersion": "1.0", "createEntities": [ { "client": { "id": "client0", "observeEvents": [ "commandStartedEvent" ] } }, { "database": { "id": "database0", "client": "client0", "databaseName": "db0" } }, { "collection": { "id": "collection0", "database": "database0", "collectionName": "coll0", "collectionOptions": { "writeConcern": { "w": 0 } } } } ], "initialData": [ { "collectionName": "coll0", "databaseName": "db0", "documents": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 22 } ] } ], "tests": [ { "description": "Unacknowledged updateOne with hint string fails with client-side error on pre-4.2 server", "runOnRequirements": [ { "maxServerVersion": "4.0.99" } ], "operations": [ { "object": "collection0", "name": "bulkWrite", "arguments": { "requests": [ { "updateOne": { "filter": { "_id": { "$gt": 1 } }, "update": { "$inc": { "x": 1 } }, "hint": "_id_" } } ] }, "expectError": { "isClientError": true } } ], "expectEvents": [ { "client": "client0", "events": [] } ] }, { "description": "Unacknowledged updateOne with hint document fails with client-side error on pre-4.2 server", "runOnRequirements": [ { "maxServerVersion": "4.0.99" } ], "operations": [ { "object": "collection0", "name": "bulkWrite", "arguments": { "requests": [ { "updateOne": { "filter": { "_id": { "$gt": 1 } }, "update": { "$inc": { "x": 1 } }, "hint": { "_id": 1 } } } ] }, "expectError": { "isClientError": true } } ], "expectEvents": [ { "client": "client0", "events": [] } ] }, { "description": "Unacknowledged updateOne with hint string on 4.2+ server", "runOnRequirements": [ { "minServerVersion": "4.2.0" } ], "operations": [ { "object": "collection0", "name": "bulkWrite", "arguments": { "requests": [ { "updateOne": { "filter": { "_id": { "$gt": 1 } }, "update": { "$inc": { "x": 1 } }, "hint": "_id_" } } ] }, "expectResult": { "$$unsetOrMatches": { "acknowledged": { "$$unsetOrMatches": false } } } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "update": "coll0", "updates": [ { "q": { "_id": { "$gt": 1 } }, "u": { "$inc": { "x": 1 } }, "multi": { "$$unsetOrMatches": false }, "upsert": { "$$unsetOrMatches": false }, "hint": { "$$type": [ "string", "object" ] } } ], "writeConcern": { "w": 0 } } } } ] } ] }, { "description": "Unacknowledged updateOne with hint document on 4.2+ server", "runOnRequirements": [ { "minServerVersion": "4.2.0" } ], "operations": [ { "object": "collection0", "name": "bulkWrite", "arguments": { "requests": [ { "updateOne": { "filter": { "_id": { "$gt": 1 } }, "update": { "$inc": { "x": 1 } }, "hint": { "_id": 1 } } } ] }, "expectResult": { "$$unsetOrMatches": { "acknowledged": { "$$unsetOrMatches": false } } } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "update": "coll0", "updates": [ { "q": { "_id": { "$gt": 1 } }, "u": { "$inc": { "x": 1 } }, "multi": { "$$unsetOrMatches": false }, "upsert": { "$$unsetOrMatches": false }, "hint": { "$$type": [ "string", "object" ] } } ], "writeConcern": { "w": 0 } } } } ] } ] } ] } mongodb-mongo-python-driver-509e9b7/test/crud/unified/bulkWrite-updateOne-let.json000066400000000000000000000130421462766011000303430ustar00rootroot00000000000000{ "description": "BulkWrite updateOne-let", "schemaVersion": "1.0", "createEntities": [ { "client": { "id": "client0", "observeEvents": [ "commandStartedEvent" ] } }, { "database": { "id": "database0", "client": "client0", "databaseName": "crud-tests" } }, { "collection": { "id": "collection0", "database": "database0", "collectionName": "coll0" } } ], "initialData": [ { "collectionName": "coll0", "databaseName": "crud-tests", "documents": [ { "_id": 1, "x": 20 }, { "_id": 2, "x": 21 } ] } ], "tests": [ { "description": "BulkWrite updateOne with let option", "runOnRequirements": [ { "minServerVersion": "5.0" } ], "operations": [ { "object": "collection0", "name": "bulkWrite", "arguments": { "requests": [ { "updateOne": { "filter": { "$expr": { "$eq": [ "$_id", "$$id" ] } }, "update": [ { "$set": { "x": 22 } } ] } } ], "let": { "id": 1 } } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "update": "coll0", "updates": [ { "q": { "$expr": { "$eq": [ "$_id", "$$id" ] } }, "u": [ { "$set": { "x": 22 } } ], "multi": { "$$unsetOrMatches": false }, "upsert": { "$$unsetOrMatches": false } } ], "let": { "id": 1 } } } } ] } ], "outcome": [ { "collectionName": "coll0", "databaseName": "crud-tests", "documents": [ { "_id": 1, "x": 22 }, { "_id": 2, "x": 21 } ] } ] }, { "description": "BulkWrite updateOne with let option unsupported (server-side error)", "runOnRequirements": [ { "minServerVersion": "4.2.0", "maxServerVersion": "4.9" } ], "operations": [ { "object": "collection0", "name": "bulkWrite", "arguments": { "requests": [ { "updateOne": { "filter": { "$expr": { "$eq": [ "$_id", "$$id" ] } }, "update": [ { "$set": { "x": 22 } } ] } } ], "let": { "id": 1 } }, "expectError": { "errorContains": "'update.let' is an unknown field", "isClientError": false } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "update": "coll0", "updates": [ { "q": { "$expr": { "$eq": [ "$_id", "$$id" ] } }, "u": [ { "$set": { "x": 22 } } ], "multi": { "$$unsetOrMatches": false }, "upsert": { "$$unsetOrMatches": false } } ], "let": { "id": 1 } } } } ] } ], "outcome": [ { "collectionName": "coll0", "databaseName": "crud-tests", "documents": [ { "_id": 1, "x": 20 }, { "_id": 2, "x": 21 } ] } ] } ] } mongodb-mongo-python-driver-509e9b7/test/crud/unified/countDocuments-comment.json000066400000000000000000000112641462766011000303450ustar00rootroot00000000000000{ "description": "countDocuments-comment", "schemaVersion": "1.0", "createEntities": [ { "client": { "id": "client0", "observeEvents": [ "commandStartedEvent" ] } }, { "database": { "id": "database0", "client": "client0", "databaseName": "countDocuments-comments-test" } }, { "collection": { "id": "collection0", "database": "database0", "collectionName": "coll0" } } ], "initialData": [ { "collectionName": "coll0", "databaseName": "countDocuments-comments-test", "documents": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 22 }, { "_id": 3, "x": 33 } ] } ], "tests": [ { "description": "countDocuments with document comment", "runOnRequirements": [ { "minServerVersion": "4.4.0" } ], "operations": [ { "name": "countDocuments", "object": "collection0", "arguments": { "filter": {}, "comment": { "key": "value" } }, "expectResult": 3 } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "aggregate": "coll0", "pipeline": [ { "$match": {} }, { "$group": { "_id": 1, "n": { "$sum": 1 } } } ], "comment": { "key": "value" } }, "commandName": "aggregate", "databaseName": "countDocuments-comments-test" } } ] } ] }, { "description": "countDocuments with string comment", "runOnRequirements": [ { "minServerVersion": "3.6.0" } ], "operations": [ { "name": "countDocuments", "object": "collection0", "arguments": { "filter": {}, "comment": "comment" }, "expectResult": 3 } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "aggregate": "coll0", "pipeline": [ { "$match": {} }, { "$group": { "_id": 1, "n": { "$sum": 1 } } } ], "comment": "comment" }, "commandName": "aggregate", "databaseName": "countDocuments-comments-test" } } ] } ] }, { "description": "countDocuments with document comment on less than 4.4.0 - server error", "runOnRequirements": [ { "minServerVersion": "3.6.0", "maxServerVersion": "4.3.99" } ], "operations": [ { "name": "countDocuments", "object": "collection0", "arguments": { "filter": {}, "comment": { "key": "value" } }, "expectError": { "isClientError": false } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "aggregate": "coll0", "pipeline": [ { "$match": {} }, { "$group": { "_id": 1, "n": { "$sum": 1 } } } ], "comment": { "key": "value" } }, "commandName": "aggregate", "databaseName": "countDocuments-comments-test" } } ] } ] } ] } mongodb-mongo-python-driver-509e9b7/test/crud/unified/db-aggregate-write-readPreference.json000066400000000000000000000240761462766011000322510ustar00rootroot00000000000000{ "description": "db-aggregate-write-readPreference", "schemaVersion": "1.4", "runOnRequirements": [ { "minServerVersion": "3.6", "topologies": [ "replicaset" ], "serverless": "forbid" } ], "_yamlAnchors": { "readConcern": { "level": "local" }, "writeConcern": { "w": 1 } }, "createEntities": [ { "client": { "id": "client0", "observeEvents": [ "commandStartedEvent" ], "uriOptions": { "readConcernLevel": "local", "w": 1 } } }, { "database": { "id": "database0", "client": "client0", "databaseName": "db0", "databaseOptions": { "readPreference": { "mode": "secondaryPreferred", "maxStalenessSeconds": 600 } } } }, { "collection": { "id": "collection0", "database": "database0", "collectionName": "coll0" } } ], "initialData": [ { "collectionName": "coll0", "databaseName": "db0", "documents": [] } ], "tests": [ { "description": "Database-level aggregate with $out includes read preference for 5.0+ server", "runOnRequirements": [ { "minServerVersion": "5.0", "serverless": "forbid" } ], "operations": [ { "object": "database0", "name": "aggregate", "arguments": { "pipeline": [ { "$listLocalSessions": {} }, { "$limit": 1 }, { "$addFields": { "_id": 1 } }, { "$project": { "_id": 1 } }, { "$out": "coll0" } ] } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "aggregate": 1, "pipeline": [ { "$listLocalSessions": {} }, { "$limit": 1 }, { "$addFields": { "_id": 1 } }, { "$project": { "_id": 1 } }, { "$out": "coll0" } ], "$readPreference": { "mode": "secondaryPreferred", "maxStalenessSeconds": 600 }, "readConcern": { "level": "local" }, "writeConcern": { "w": 1 } } } } ] } ], "outcome": [ { "collectionName": "coll0", "databaseName": "db0", "documents": [ { "_id": 1 } ] } ] }, { "description": "Database-level aggregate with $out omits read preference for pre-5.0 server", "runOnRequirements": [ { "minServerVersion": "4.2", "maxServerVersion": "4.4.99", "serverless": "forbid" } ], "operations": [ { "object": "database0", "name": "aggregate", "arguments": { "pipeline": [ { "$listLocalSessions": {} }, { "$limit": 1 }, { "$addFields": { "_id": 1 } }, { "$project": { "_id": 1 } }, { "$out": "coll0" } ] } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "aggregate": 1, "pipeline": [ { "$listLocalSessions": {} }, { "$limit": 1 }, { "$addFields": { "_id": 1 } }, { "$project": { "_id": 1 } }, { "$out": "coll0" } ], "$readPreference": { "$$exists": false }, "readConcern": { "level": "local" }, "writeConcern": { "w": 1 } } } } ] } ], "outcome": [ { "collectionName": "coll0", "databaseName": "db0", "documents": [ { "_id": 1 } ] } ] }, { "description": "Database-level aggregate with $merge includes read preference for 5.0+ server", "runOnRequirements": [ { "minServerVersion": "5.0" } ], "operations": [ { "object": "database0", "name": "aggregate", "arguments": { "pipeline": [ { "$listLocalSessions": {} }, { "$limit": 1 }, { "$addFields": { "_id": 1 } }, { "$project": { "_id": 1 } }, { "$merge": { "into": "coll0" } } ] } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "aggregate": 1, "pipeline": [ { "$listLocalSessions": {} }, { "$limit": 1 }, { "$addFields": { "_id": 1 } }, { "$project": { "_id": 1 } }, { "$merge": { "into": "coll0" } } ], "$readPreference": { "mode": "secondaryPreferred", "maxStalenessSeconds": 600 }, "readConcern": { "level": "local" }, "writeConcern": { "w": 1 } } } } ] } ], "outcome": [ { "collectionName": "coll0", "databaseName": "db0", "documents": [ { "_id": 1 } ] } ] }, { "description": "Database-level aggregate with $merge omits read preference for pre-5.0 server", "runOnRequirements": [ { "minServerVersion": "4.2", "maxServerVersion": "4.4.99" } ], "operations": [ { "object": "database0", "name": "aggregate", "arguments": { "pipeline": [ { "$listLocalSessions": {} }, { "$limit": 1 }, { "$addFields": { "_id": 1 } }, { "$project": { "_id": 1 } }, { "$merge": { "into": "coll0" } } ] } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "aggregate": 1, "pipeline": [ { "$listLocalSessions": {} }, { "$limit": 1 }, { "$addFields": { "_id": 1 } }, { "$project": { "_id": 1 } }, { "$merge": { "into": "coll0" } } ], "$readPreference": { "$$exists": false }, "readConcern": { "level": "local" }, "writeConcern": { "w": 1 } } } } ] } ], "outcome": [ { "collectionName": "coll0", "databaseName": "db0", "documents": [ { "_id": 1 } ] } ] } ] } mongodb-mongo-python-driver-509e9b7/test/crud/unified/db-aggregate.json000066400000000000000000000042211462766011000261770ustar00rootroot00000000000000{ "description": "db-aggregate", "schemaVersion": "1.4", "runOnRequirements": [ { "minServerVersion": "3.6.0", "serverless": "forbid" } ], "createEntities": [ { "client": { "id": "client0", "observeEvents": [ "commandStartedEvent" ] } }, { "database": { "id": "database0", "client": "client0", "databaseName": "admin" } }, { "collection": { "id": "collection0", "database": "database0", "collectionName": "crud-v2" } } ], "tests": [ { "description": "Aggregate with $listLocalSessions", "operations": [ { "object": "database0", "name": "aggregate", "arguments": { "pipeline": [ { "$listLocalSessions": {} }, { "$limit": 1 }, { "$addFields": { "dummy": "dummy field" } }, { "$project": { "_id": 0, "dummy": 1 } } ] }, "expectResult": [ { "dummy": "dummy field" } ] } ] }, { "description": "Aggregate with $listLocalSessions and allowDiskUse", "operations": [ { "object": "database0", "name": "aggregate", "arguments": { "pipeline": [ { "$listLocalSessions": {} }, { "$limit": 1 }, { "$addFields": { "dummy": "dummy field" } }, { "$project": { "_id": 0, "dummy": 1 } } ], "allowDiskUse": true }, "expectResult": [ { "dummy": "dummy field" } ] } ] } ] } mongodb-mongo-python-driver-509e9b7/test/crud/unified/deleteMany-comment.json000066400000000000000000000120161462766011000274160ustar00rootroot00000000000000{ "description": "deleteMany-comment", "schemaVersion": "1.0", "createEntities": [ { "client": { "id": "client0", "observeEvents": [ "commandStartedEvent" ] } }, { "database": { "id": "database0", "client": "client0", "databaseName": "crud-tests" } }, { "collection": { "id": "collection0", "database": "database0", "collectionName": "coll0" } } ], "initialData": [ { "collectionName": "coll0", "databaseName": "crud-tests", "documents": [ { "_id": 1 }, { "_id": 2, "name": "name2" }, { "_id": 3, "name": "name3" } ] } ], "tests": [ { "description": "deleteMany with string comment", "runOnRequirements": [ { "minServerVersion": "4.4" } ], "operations": [ { "name": "deleteMany", "object": "collection0", "arguments": { "filter": { "_id": { "$gt": 1 } }, "comment": "comment" }, "expectResult": { "deletedCount": 2 } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "delete": "coll0", "deletes": [ { "q": { "_id": { "$gt": 1 } }, "limit": 0 } ], "comment": "comment" } } } ] } ], "outcome": [ { "collectionName": "coll0", "databaseName": "crud-tests", "documents": [ { "_id": 1 } ] } ] }, { "description": "deleteMany with document comment", "runOnRequirements": [ { "minServerVersion": "4.4" } ], "operations": [ { "name": "deleteMany", "object": "collection0", "arguments": { "filter": { "_id": { "$gt": 1 } }, "comment": { "key": "value" } }, "expectResult": { "deletedCount": 2 } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "delete": "coll0", "deletes": [ { "q": { "_id": { "$gt": 1 } }, "limit": 0 } ], "comment": { "key": "value" } } } } ] } ], "outcome": [ { "collectionName": "coll0", "databaseName": "crud-tests", "documents": [ { "_id": 1 } ] } ] }, { "description": "deleteMany with comment - pre 4.4", "runOnRequirements": [ { "minServerVersion": "3.4.0", "maxServerVersion": "4.2.99" } ], "operations": [ { "name": "deleteMany", "object": "collection0", "arguments": { "filter": { "_id": { "$gt": 1 } }, "comment": "comment" }, "expectError": { "isClientError": false } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "delete": "coll0", "deletes": [ { "q": { "_id": { "$gt": 1 } }, "limit": 0 } ], "comment": "comment" } } } ] } ], "outcome": [ { "collectionName": "coll0", "databaseName": "crud-tests", "documents": [ { "_id": 1 }, { "_id": 2, "name": "name2" }, { "_id": 3, "name": "name3" } ] } ] } ] } mongodb-mongo-python-driver-509e9b7/test/crud/unified/deleteMany-hint-clientError.json000066400000000000000000000054531462766011000312130ustar00rootroot00000000000000{ "description": "deleteMany-hint-clientError", "schemaVersion": "1.0", "runOnRequirements": [ { "maxServerVersion": "3.3.99" } ], "createEntities": [ { "client": { "id": "client0", "observeEvents": [ "commandStartedEvent" ] } }, { "database": { "id": "database0", "client": "client0", "databaseName": "crud-v2" } }, { "collection": { "id": "collection0", "database": "database0", "collectionName": "DeleteMany_hint" } } ], "initialData": [ { "collectionName": "DeleteMany_hint", "databaseName": "crud-v2", "documents": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 22 }, { "_id": 3, "x": 33 } ] } ], "tests": [ { "description": "DeleteMany with hint string unsupported (client-side error)", "operations": [ { "object": "collection0", "name": "deleteMany", "arguments": { "filter": { "_id": { "$gt": 1 } }, "hint": "_id_" }, "expectError": { "isError": true } } ], "expectEvents": [ { "client": "client0", "events": [] } ], "outcome": [ { "collectionName": "DeleteMany_hint", "databaseName": "crud-v2", "documents": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 22 }, { "_id": 3, "x": 33 } ] } ] }, { "description": "DeleteMany with hint document unsupported (client-side error)", "operations": [ { "object": "collection0", "name": "deleteMany", "arguments": { "filter": { "_id": { "$gt": 1 } }, "hint": { "_id": 1 } }, "expectError": { "isError": true } } ], "expectEvents": [ { "client": "client0", "events": [] } ], "outcome": [ { "collectionName": "DeleteMany_hint", "databaseName": "crud-v2", "documents": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 22 }, { "_id": 3, "x": 33 } ] } ] } ] } mongodb-mongo-python-driver-509e9b7/test/crud/unified/deleteMany-hint-serverError.json000066400000000000000000000075551462766011000312500ustar00rootroot00000000000000{ "description": "deleteMany-hint-serverError", "schemaVersion": "1.0", "runOnRequirements": [ { "minServerVersion": "3.4.0", "maxServerVersion": "4.3.3" } ], "createEntities": [ { "client": { "id": "client0", "observeEvents": [ "commandStartedEvent" ] } }, { "database": { "id": "database0", "client": "client0", "databaseName": "crud-v2" } }, { "collection": { "id": "collection0", "database": "database0", "collectionName": "DeleteMany_hint" } } ], "initialData": [ { "collectionName": "DeleteMany_hint", "databaseName": "crud-v2", "documents": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 22 }, { "_id": 3, "x": 33 } ] } ], "tests": [ { "description": "DeleteMany with hint string unsupported (server-side error)", "operations": [ { "object": "collection0", "name": "deleteMany", "arguments": { "filter": { "_id": { "$gt": 1 } }, "hint": "_id_" }, "expectError": { "isError": true } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "delete": "DeleteMany_hint", "deletes": [ { "q": { "_id": { "$gt": 1 } }, "hint": "_id_", "limit": 0 } ] } } } ] } ], "outcome": [ { "collectionName": "DeleteMany_hint", "databaseName": "crud-v2", "documents": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 22 }, { "_id": 3, "x": 33 } ] } ] }, { "description": "DeleteMany with hint document unsupported (server-side error)", "operations": [ { "object": "collection0", "name": "deleteMany", "arguments": { "filter": { "_id": { "$gt": 1 } }, "hint": { "_id": 1 } }, "expectError": { "isError": true } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "delete": "DeleteMany_hint", "deletes": [ { "q": { "_id": { "$gt": 1 } }, "hint": { "_id": 1 }, "limit": 0 } ] } } } ] } ], "outcome": [ { "collectionName": "DeleteMany_hint", "databaseName": "crud-v2", "documents": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 22 }, { "_id": 3, "x": 33 } ] } ] } ] } mongodb-mongo-python-driver-509e9b7/test/crud/unified/deleteMany-hint-unacknowledged.json000066400000000000000000000123461462766011000317140ustar00rootroot00000000000000{ "description": "deleteMany-hint-unacknowledged", "schemaVersion": "1.0", "createEntities": [ { "client": { "id": "client0", "observeEvents": [ "commandStartedEvent" ] } }, { "database": { "id": "database0", "client": "client0", "databaseName": "db0" } }, { "collection": { "id": "collection0", "database": "database0", "collectionName": "coll0", "collectionOptions": { "writeConcern": { "w": 0 } } } } ], "initialData": [ { "collectionName": "coll0", "databaseName": "db0", "documents": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 22 }, { "_id": 3, "x": 33 } ] } ], "tests": [ { "description": "Unacknowledged deleteMany with hint string fails with client-side error on pre-4.4 server", "runOnRequirements": [ { "maxServerVersion": "4.2.99" } ], "operations": [ { "object": "collection0", "name": "deleteMany", "arguments": { "filter": { "_id": { "$gt": 1 } }, "hint": "_id_" }, "expectError": { "isClientError": true } } ], "expectEvents": [ { "client": "client0", "events": [] } ] }, { "description": "Unacknowledged deleteMany with hint document fails with client-side error on pre-4.4 server", "runOnRequirements": [ { "maxServerVersion": "4.2.99" } ], "operations": [ { "object": "collection0", "name": "deleteMany", "arguments": { "filter": { "_id": { "$gt": 1 } }, "hint": { "_id": 1 } }, "expectError": { "isClientError": true } } ], "expectEvents": [ { "client": "client0", "events": [] } ] }, { "description": "Unacknowledged deleteMany with hint string on 4.4+ server", "runOnRequirements": [ { "minServerVersion": "4.4.0" } ], "operations": [ { "object": "collection0", "name": "deleteMany", "arguments": { "filter": { "_id": { "$gt": 1 } }, "hint": "_id_" }, "expectResult": { "$$unsetOrMatches": { "acknowledged": { "$$unsetOrMatches": false } } } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "delete": "coll0", "deletes": [ { "q": { "_id": { "$gt": 1 } }, "hint": { "$$type": [ "string", "object" ] }, "limit": 0 } ], "writeConcern": { "w": 0 } } } } ] } ] }, { "description": "Unacknowledged deleteMany with hint document on 4.4+ server", "runOnRequirements": [ { "minServerVersion": "4.4.0" } ], "operations": [ { "object": "collection0", "name": "deleteMany", "arguments": { "filter": { "_id": { "$gt": 1 } }, "hint": { "_id": 1 } }, "expectResult": { "$$unsetOrMatches": { "acknowledged": { "$$unsetOrMatches": false } } } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "delete": "coll0", "deletes": [ { "q": { "_id": { "$gt": 1 } }, "hint": { "$$type": [ "string", "object" ] }, "limit": 0 } ], "writeConcern": { "w": 0 } } } } ] } ] } ] } mongodb-mongo-python-driver-509e9b7/test/crud/unified/deleteMany-hint.json000066400000000000000000000067301462766011000267240ustar00rootroot00000000000000{ "description": "deleteMany-hint", "schemaVersion": "1.0", "runOnRequirements": [ { "minServerVersion": "4.3.4" } ], "createEntities": [ { "client": { "id": "client0", "observeEvents": [ "commandStartedEvent" ] } }, { "database": { "id": "database0", "client": "client0", "databaseName": "crud-v2" } }, { "collection": { "id": "collection0", "database": "database0", "collectionName": "DeleteMany_hint" } } ], "initialData": [ { "collectionName": "DeleteMany_hint", "databaseName": "crud-v2", "documents": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 22 }, { "_id": 3, "x": 33 } ] } ], "tests": [ { "description": "DeleteMany with hint string", "operations": [ { "object": "collection0", "name": "deleteMany", "arguments": { "filter": { "_id": { "$gt": 1 } }, "hint": "_id_" }, "expectResult": { "deletedCount": 2 } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "delete": "DeleteMany_hint", "deletes": [ { "q": { "_id": { "$gt": 1 } }, "hint": "_id_", "limit": 0 } ] } } } ] } ], "outcome": [ { "collectionName": "DeleteMany_hint", "databaseName": "crud-v2", "documents": [ { "_id": 1, "x": 11 } ] } ] }, { "description": "DeleteMany with hint document", "operations": [ { "object": "collection0", "name": "deleteMany", "arguments": { "filter": { "_id": { "$gt": 1 } }, "hint": { "_id": 1 } }, "expectResult": { "deletedCount": 2 } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "delete": "DeleteMany_hint", "deletes": [ { "q": { "_id": { "$gt": 1 } }, "hint": { "_id": 1 }, "limit": 0 } ] } } } ] } ], "outcome": [ { "collectionName": "DeleteMany_hint", "databaseName": "crud-v2", "documents": [ { "_id": 1, "x": 11 } ] } ] } ] } mongodb-mongo-python-driver-509e9b7/test/crud/unified/deleteMany-let.json000066400000000000000000000103071462766011000265410ustar00rootroot00000000000000{ "description": "deleteMany-let", "schemaVersion": "1.0", "createEntities": [ { "client": { "id": "client0", "observeEvents": [ "commandStartedEvent" ] } }, { "database": { "id": "database0", "client": "client0", "databaseName": "crud-tests" } }, { "collection": { "id": "collection0", "database": "database0", "collectionName": "coll0" } } ], "initialData": [ { "collectionName": "coll0", "databaseName": "crud-tests", "documents": [ { "_id": 1 }, { "_id": 2, "name": "name" }, { "_id": 3, "name": "name" } ] } ], "tests": [ { "description": "deleteMany with let option", "runOnRequirements": [ { "minServerVersion": "5.0" } ], "operations": [ { "name": "deleteMany", "object": "collection0", "arguments": { "filter": { "$expr": { "$eq": [ "$name", "$$name" ] } }, "let": { "name": "name" } }, "expectResult": { "deletedCount": 2 } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "delete": "coll0", "deletes": [ { "q": { "$expr": { "$eq": [ "$name", "$$name" ] } }, "limit": 0 } ], "let": { "name": "name" } } } } ] } ], "outcome": [ { "collectionName": "coll0", "databaseName": "crud-tests", "documents": [ { "_id": 1 } ] } ] }, { "description": "deleteMany with let option unsupported (server-side error)", "runOnRequirements": [ { "minServerVersion": "3.6.0", "maxServerVersion": "4.4.99" } ], "operations": [ { "name": "deleteMany", "object": "collection0", "arguments": { "filter": { "$expr": { "$eq": [ "$name", "$$name" ] } }, "let": { "name": "name" } }, "expectError": { "errorContains": "'delete.let' is an unknown field", "isClientError": false } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "delete": "coll0", "deletes": [ { "q": { "$expr": { "$eq": [ "$name", "$$name" ] } }, "limit": 0 } ], "let": { "name": "name" } } } } ] } ], "outcome": [ { "collectionName": "coll0", "databaseName": "crud-tests", "documents": [ { "_id": 1 }, { "_id": 2, "name": "name" }, { "_id": 3, "name": "name" } ] } ] } ] } mongodb-mongo-python-driver-509e9b7/test/crud/unified/deleteOne-comment.json000066400000000000000000000116611462766011000272400ustar00rootroot00000000000000{ "description": "deleteOne-comment", "schemaVersion": "1.0", "createEntities": [ { "client": { "id": "client0", "observeEvents": [ "commandStartedEvent" ] } }, { "database": { "id": "database0", "client": "client0", "databaseName": "crud-tests" } }, { "collection": { "id": "collection0", "database": "database0", "collectionName": "coll0" } } ], "initialData": [ { "collectionName": "coll0", "databaseName": "crud-tests", "documents": [ { "_id": 1 }, { "_id": 2, "name": "name" }, { "_id": 3, "name": "name" } ] } ], "tests": [ { "description": "deleteOne with string comment", "runOnRequirements": [ { "minServerVersion": "4.4" } ], "operations": [ { "name": "deleteOne", "object": "collection0", "arguments": { "filter": { "_id": 1 }, "comment": "comment" }, "expectResult": { "deletedCount": 1 } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "delete": "coll0", "deletes": [ { "q": { "_id": 1 }, "limit": 1 } ], "comment": "comment" } } } ] } ], "outcome": [ { "collectionName": "coll0", "databaseName": "crud-tests", "documents": [ { "_id": 2, "name": "name" }, { "_id": 3, "name": "name" } ] } ] }, { "description": "deleteOne with document comment", "runOnRequirements": [ { "minServerVersion": "4.4" } ], "operations": [ { "name": "deleteOne", "object": "collection0", "arguments": { "filter": { "_id": 1 }, "comment": { "key": "value" } }, "expectResult": { "deletedCount": 1 } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "delete": "coll0", "deletes": [ { "q": { "_id": 1 }, "limit": 1 } ], "comment": { "key": "value" } } } } ] } ], "outcome": [ { "collectionName": "coll0", "databaseName": "crud-tests", "documents": [ { "_id": 2, "name": "name" }, { "_id": 3, "name": "name" } ] } ] }, { "description": "deleteOne with comment - pre 4.4", "runOnRequirements": [ { "minServerVersion": "3.4.0", "maxServerVersion": "4.2.99" } ], "operations": [ { "name": "deleteOne", "object": "collection0", "arguments": { "filter": { "_id": 1 }, "comment": "comment" }, "expectError": { "isClientError": false } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "delete": "coll0", "deletes": [ { "q": { "_id": 1 }, "limit": 1 } ], "comment": "comment" } } } ] } ], "outcome": [ { "collectionName": "coll0", "databaseName": "crud-tests", "documents": [ { "_id": 1 }, { "_id": 2, "name": "name" }, { "_id": 3, "name": "name" } ] } ] } ] } mongodb-mongo-python-driver-509e9b7/test/crud/unified/deleteOne-errorResponse.json000066400000000000000000000032421462766011000304420ustar00rootroot00000000000000{ "description": "deleteOne-errorResponse", "schemaVersion": "1.12", "createEntities": [ { "client": { "id": "client0", "useMultipleMongoses": false } }, { "database": { "id": "database0", "client": "client0", "databaseName": "crud-tests" } }, { "collection": { "id": "collection0", "database": "database0", "collectionName": "test" } } ], "tests": [ { "description": "delete operations support errorResponse assertions", "runOnRequirements": [ { "minServerVersion": "4.0.0", "topologies": [ "single", "replicaset" ] }, { "minServerVersion": "4.2.0", "topologies": [ "sharded" ] } ], "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "client0", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "delete" ], "errorCode": 8 } } } }, { "name": "deleteOne", "object": "collection0", "arguments": { "filter": { "_id": 1 } }, "expectError": { "errorCode": 8, "errorResponse": { "code": 8 } } } ] } ] } mongodb-mongo-python-driver-509e9b7/test/crud/unified/deleteOne-hint-clientError.json000066400000000000000000000047771462766011000310400ustar00rootroot00000000000000{ "description": "deleteOne-hint-clientError", "schemaVersion": "1.0", "runOnRequirements": [ { "maxServerVersion": "3.3.99" } ], "createEntities": [ { "client": { "id": "client0", "observeEvents": [ "commandStartedEvent" ] } }, { "database": { "id": "database0", "client": "client0", "databaseName": "crud-v2" } }, { "collection": { "id": "collection0", "database": "database0", "collectionName": "DeleteOne_hint" } } ], "initialData": [ { "collectionName": "DeleteOne_hint", "databaseName": "crud-v2", "documents": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 22 } ] } ], "tests": [ { "description": "DeleteOne with hint string unsupported (client-side error)", "operations": [ { "object": "collection0", "name": "deleteOne", "arguments": { "filter": { "_id": 1 }, "hint": "_id_" }, "expectError": { "isError": true } } ], "expectEvents": [ { "client": "client0", "events": [] } ], "outcome": [ { "collectionName": "DeleteOne_hint", "databaseName": "crud-v2", "documents": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 22 } ] } ] }, { "description": "DeleteOne with hint document unsupported (client-side error)", "operations": [ { "object": "collection0", "name": "deleteOne", "arguments": { "filter": { "_id": 1 }, "hint": { "_id": 1 } }, "expectError": { "isError": true } } ], "expectEvents": [ { "client": "client0", "events": [] } ], "outcome": [ { "collectionName": "DeleteOne_hint", "databaseName": "crud-v2", "documents": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 22 } ] } ] } ] } mongodb-mongo-python-driver-509e9b7/test/crud/unified/deleteOne-hint-serverError.json000066400000000000000000000067051462766011000310610ustar00rootroot00000000000000{ "description": "deleteOne-hint-serverError", "schemaVersion": "1.0", "runOnRequirements": [ { "minServerVersion": "3.4.0", "maxServerVersion": "4.3.3" } ], "createEntities": [ { "client": { "id": "client0", "observeEvents": [ "commandStartedEvent" ] } }, { "database": { "id": "database0", "client": "client0", "databaseName": "crud-v2" } }, { "collection": { "id": "collection0", "database": "database0", "collectionName": "DeleteOne_hint" } } ], "initialData": [ { "collectionName": "DeleteOne_hint", "databaseName": "crud-v2", "documents": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 22 } ] } ], "tests": [ { "description": "DeleteOne with hint string unsupported (server-side error)", "operations": [ { "object": "collection0", "name": "deleteOne", "arguments": { "filter": { "_id": 1 }, "hint": "_id_" }, "expectError": { "isError": true } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "delete": "DeleteOne_hint", "deletes": [ { "q": { "_id": 1 }, "hint": "_id_", "limit": 1 } ] } } } ] } ], "outcome": [ { "collectionName": "DeleteOne_hint", "databaseName": "crud-v2", "documents": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 22 } ] } ] }, { "description": "DeleteOne with hint document unsupported (server-side error)", "operations": [ { "object": "collection0", "name": "deleteOne", "arguments": { "filter": { "_id": 1 }, "hint": { "_id": 1 } }, "expectError": { "isError": true } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "delete": "DeleteOne_hint", "deletes": [ { "q": { "_id": 1 }, "hint": { "_id": 1 }, "limit": 1 } ] } } } ] } ], "outcome": [ { "collectionName": "DeleteOne_hint", "databaseName": "crud-v2", "documents": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 22 } ] } ] } ] } mongodb-mongo-python-driver-509e9b7/test/crud/unified/deleteOne-hint-unacknowledged.json000066400000000000000000000122421462766011000315240ustar00rootroot00000000000000{ "description": "deleteOne-hint-unacknowledged", "schemaVersion": "1.0", "createEntities": [ { "client": { "id": "client0", "observeEvents": [ "commandStartedEvent" ] } }, { "database": { "id": "database0", "client": "client0", "databaseName": "db0" } }, { "collection": { "id": "collection0", "database": "database0", "collectionName": "coll0", "collectionOptions": { "writeConcern": { "w": 0 } } } } ], "initialData": [ { "collectionName": "coll0", "databaseName": "db0", "documents": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 22 } ] } ], "tests": [ { "description": "Unacknowledged deleteOne with hint string fails with client-side error on pre-4.4 server", "runOnRequirements": [ { "maxServerVersion": "4.2.99" } ], "operations": [ { "object": "collection0", "name": "deleteOne", "arguments": { "filter": { "_id": { "$gt": 1 } }, "hint": "_id_" }, "expectError": { "isClientError": true } } ], "expectEvents": [ { "client": "client0", "events": [] } ] }, { "description": "Unacknowledged deleteOne with hint document fails with client-side error on pre-4.4 server", "runOnRequirements": [ { "maxServerVersion": "4.2.99" } ], "operations": [ { "object": "collection0", "name": "deleteOne", "arguments": { "filter": { "_id": { "$gt": 1 } }, "hint": { "_id": 1 } }, "expectError": { "isClientError": true } } ], "expectEvents": [ { "client": "client0", "events": [] } ] }, { "description": "Unacknowledged deleteOne with hint string on 4.4+ server", "runOnRequirements": [ { "minServerVersion": "4.4.0" } ], "operations": [ { "object": "collection0", "name": "deleteOne", "arguments": { "filter": { "_id": { "$gt": 1 } }, "hint": "_id_" }, "expectResult": { "$$unsetOrMatches": { "acknowledged": { "$$unsetOrMatches": false } } } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "delete": "coll0", "deletes": [ { "q": { "_id": { "$gt": 1 } }, "hint": { "$$type": [ "string", "object" ] }, "limit": 1 } ], "writeConcern": { "w": 0 } } } } ] } ] }, { "description": "Unacknowledged deleteOne with hint document on 4.4+ server", "runOnRequirements": [ { "minServerVersion": "4.4.0" } ], "operations": [ { "object": "collection0", "name": "deleteOne", "arguments": { "filter": { "_id": { "$gt": 1 } }, "hint": { "_id": 1 } }, "expectResult": { "$$unsetOrMatches": { "acknowledged": { "$$unsetOrMatches": false } } } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "delete": "coll0", "deletes": [ { "q": { "_id": { "$gt": 1 } }, "hint": { "$$type": [ "string", "object" ] }, "limit": 1 } ], "writeConcern": { "w": 0 } } } } ] } ] } ] } mongodb-mongo-python-driver-509e9b7/test/crud/unified/deleteOne-hint.json000066400000000000000000000063061462766011000265400ustar00rootroot00000000000000{ "description": "deleteOne-hint", "schemaVersion": "1.0", "runOnRequirements": [ { "minServerVersion": "4.3.4" } ], "createEntities": [ { "client": { "id": "client0", "observeEvents": [ "commandStartedEvent" ] } }, { "database": { "id": "database0", "client": "client0", "databaseName": "crud-v2" } }, { "collection": { "id": "collection0", "database": "database0", "collectionName": "DeleteOne_hint" } } ], "initialData": [ { "collectionName": "DeleteOne_hint", "databaseName": "crud-v2", "documents": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 22 } ] } ], "tests": [ { "description": "DeleteOne with hint string", "operations": [ { "object": "collection0", "name": "deleteOne", "arguments": { "filter": { "_id": 1 }, "hint": "_id_" }, "expectResult": { "deletedCount": 1 } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "delete": "DeleteOne_hint", "deletes": [ { "q": { "_id": 1 }, "hint": "_id_", "limit": 1 } ] } } } ] } ], "outcome": [ { "collectionName": "DeleteOne_hint", "databaseName": "crud-v2", "documents": [ { "_id": 2, "x": 22 } ] } ] }, { "description": "deleteOne with hint document", "operations": [ { "object": "collection0", "name": "deleteOne", "arguments": { "filter": { "_id": 1 }, "hint": { "_id": 1 } }, "expectResult": { "deletedCount": 1 } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "delete": "DeleteOne_hint", "deletes": [ { "q": { "_id": 1 }, "hint": { "_id": 1 }, "limit": 1 } ] } } } ] } ], "outcome": [ { "collectionName": "DeleteOne_hint", "databaseName": "crud-v2", "documents": [ { "_id": 2, "x": 22 } ] } ] } ] } mongodb-mongo-python-driver-509e9b7/test/crud/unified/deleteOne-let.json000066400000000000000000000077161462766011000263700ustar00rootroot00000000000000{ "description": "deleteOne-let", "schemaVersion": "1.0", "createEntities": [ { "client": { "id": "client0", "observeEvents": [ "commandStartedEvent" ] } }, { "database": { "id": "database0", "client": "client0", "databaseName": "crud-tests" } }, { "collection": { "id": "collection0", "database": "database0", "collectionName": "coll0" } } ], "initialData": [ { "collectionName": "coll0", "databaseName": "crud-tests", "documents": [ { "_id": 1 }, { "_id": 2 } ] } ], "tests": [ { "description": "deleteOne with let option", "runOnRequirements": [ { "minServerVersion": "5.0" } ], "operations": [ { "name": "deleteOne", "object": "collection0", "arguments": { "filter": { "$expr": { "$eq": [ "$_id", "$$id" ] } }, "let": { "id": 1 } }, "expectResult": { "deletedCount": 1 } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "delete": "coll0", "deletes": [ { "q": { "$expr": { "$eq": [ "$_id", "$$id" ] } }, "limit": 1 } ], "let": { "id": 1 } } } } ] } ], "outcome": [ { "collectionName": "coll0", "databaseName": "crud-tests", "documents": [ { "_id": 2 } ] } ] }, { "description": "deleteOne with let option unsupported (server-side error)", "runOnRequirements": [ { "minServerVersion": "3.6.0", "maxServerVersion": "4.4.99" } ], "operations": [ { "name": "deleteOne", "object": "collection0", "arguments": { "filter": { "$expr": { "$eq": [ "$_id", "$$id" ] } }, "let": { "id": 1 } }, "expectError": { "errorContains": "'delete.let' is an unknown field", "isClientError": false } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "delete": "coll0", "deletes": [ { "q": { "$expr": { "$eq": [ "$_id", "$$id" ] } }, "limit": 1 } ], "let": { "id": 1 } } } } ] } ], "outcome": [ { "collectionName": "coll0", "databaseName": "crud-tests", "documents": [ { "_id": 1 }, { "_id": 2 } ] } ] } ] } mongodb-mongo-python-driver-509e9b7/test/crud/unified/distinct-comment.json000066400000000000000000000076461462766011000271650ustar00rootroot00000000000000{ "description": "distinct-comment", "schemaVersion": "1.0", "createEntities": [ { "client": { "id": "client0", "observeEvents": [ "commandStartedEvent" ] } }, { "database": { "id": "database0", "client": "client0", "databaseName": "distinct-comment-tests" } }, { "collection": { "id": "collection0", "database": "database0", "collectionName": "coll0" } } ], "initialData": [ { "collectionName": "coll0", "databaseName": "distinct-comment-tests", "documents": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 22 }, { "_id": 3, "x": 33 } ] } ], "tests": [ { "description": "distinct with document comment", "runOnRequirements": [ { "minServerVersion": "4.4.14" } ], "operations": [ { "name": "distinct", "object": "collection0", "arguments": { "fieldName": "x", "filter": {}, "comment": { "key": "value" } }, "expectResult": [ 11, 22, 33 ] } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "distinct": "coll0", "key": "x", "query": {}, "comment": { "key": "value" } }, "commandName": "distinct", "databaseName": "distinct-comment-tests" } } ] } ] }, { "description": "distinct with string comment", "runOnRequirements": [ { "minServerVersion": "4.4.0" } ], "operations": [ { "name": "distinct", "object": "collection0", "arguments": { "fieldName": "x", "filter": {}, "comment": "comment" }, "expectResult": [ 11, 22, 33 ] } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "distinct": "coll0", "key": "x", "query": {}, "comment": "comment" }, "commandName": "distinct", "databaseName": "distinct-comment-tests" } } ] } ] }, { "description": "distinct with document comment - pre 4.4, server error", "runOnRequirements": [ { "minServerVersion": "3.6.0", "maxServerVersion": "4.4.13" } ], "operations": [ { "name": "distinct", "object": "collection0", "arguments": { "fieldName": "x", "filter": {}, "comment": { "key": "value" } }, "expectError": { "isClientError": false } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "distinct": "coll0", "key": "x", "query": {}, "comment": { "key": "value" } }, "commandName": "distinct", "databaseName": "distinct-comment-tests" } } ] } ] } ] } mongodb-mongo-python-driver-509e9b7/test/crud/unified/estimatedDocumentCount-comment.json000066400000000000000000000071411462766011000320210ustar00rootroot00000000000000{ "description": "estimatedDocumentCount-comment", "schemaVersion": "1.0", "createEntities": [ { "client": { "id": "client0", "observeEvents": [ "commandStartedEvent" ] } }, { "database": { "id": "database0", "client": "client0", "databaseName": "edc-comment-tests" } }, { "collection": { "id": "collection0", "database": "database0", "collectionName": "coll0" } } ], "initialData": [ { "collectionName": "coll0", "databaseName": "edc-comment-tests", "documents": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 22 }, { "_id": 3, "x": 33 } ] } ], "tests": [ { "description": "estimatedDocumentCount with document comment", "runOnRequirements": [ { "minServerVersion": "4.4.14" } ], "operations": [ { "name": "estimatedDocumentCount", "object": "collection0", "arguments": { "comment": { "key": "value" } }, "expectResult": 3 } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "count": "coll0", "comment": { "key": "value" } }, "commandName": "count", "databaseName": "edc-comment-tests" } } ] } ] }, { "description": "estimatedDocumentCount with string comment", "runOnRequirements": [ { "minServerVersion": "4.4.0" } ], "operations": [ { "name": "estimatedDocumentCount", "object": "collection0", "arguments": { "comment": "comment" }, "expectResult": 3 } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "count": "coll0", "comment": "comment" }, "commandName": "count", "databaseName": "edc-comment-tests" } } ] } ] }, { "description": "estimatedDocumentCount with document comment - pre 4.4.14, server error", "runOnRequirements": [ { "minServerVersion": "3.6.0", "maxServerVersion": "4.4.13", "topologies": [ "single", "replicaset" ] } ], "operations": [ { "name": "estimatedDocumentCount", "object": "collection0", "arguments": { "comment": { "key": "value" } }, "expectError": { "isClientError": false } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "count": "coll0", "comment": { "key": "value" } }, "commandName": "count", "databaseName": "edc-comment-tests" } } ] } ] } ] } mongodb-mongo-python-driver-509e9b7/test/crud/unified/estimatedDocumentCount.json000066400000000000000000000175751462766011000303750ustar00rootroot00000000000000{ "description": "estimatedDocumentCount", "schemaVersion": "1.0", "createEntities": [ { "client": { "id": "client0", "useMultipleMongoses": false, "uriOptions": { "retryReads": false }, "observeEvents": [ "commandStartedEvent" ] } }, { "database": { "id": "database0", "client": "client0", "databaseName": "edc-tests" } }, { "collection": { "id": "collection0", "database": "database0", "collectionName": "coll0" } }, { "collection": { "id": "collection1", "database": "database0", "collectionName": "coll1" } }, { "collection": { "id": "collection0View", "database": "database0", "collectionName": "coll0view" } } ], "initialData": [ { "collectionName": "coll0", "databaseName": "edc-tests", "documents": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 22 }, { "_id": 3, "x": 33 } ] } ], "tests": [ { "description": "estimatedDocumentCount always uses count", "operations": [ { "name": "estimatedDocumentCount", "object": "collection0", "expectResult": 3 } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "count": "coll0" }, "commandName": "count", "databaseName": "edc-tests" } } ] } ] }, { "description": "estimatedDocumentCount with maxTimeMS", "operations": [ { "name": "estimatedDocumentCount", "object": "collection0", "arguments": { "maxTimeMS": 6000 }, "expectResult": 3 } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "count": "coll0", "maxTimeMS": 6000 }, "commandName": "count", "databaseName": "edc-tests" } } ] } ] }, { "description": "estimatedDocumentCount on non-existent collection", "operations": [ { "name": "estimatedDocumentCount", "object": "collection1", "expectResult": 0 } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "count": "coll1" }, "commandName": "count", "databaseName": "edc-tests" } } ] } ] }, { "description": "estimatedDocumentCount errors correctly--command error", "runOnRequirements": [ { "minServerVersion": "4.0.0", "topologies": [ "single", "replicaset" ] }, { "minServerVersion": "4.2.0", "topologies": [ "sharded" ] } ], "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "client0", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "count" ], "errorCode": 8 } } } }, { "name": "estimatedDocumentCount", "object": "collection0", "expectError": { "errorCode": 8 } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "count": "coll0" }, "commandName": "count", "databaseName": "edc-tests" } } ] } ] }, { "description": "estimatedDocumentCount errors correctly--socket error", "runOnRequirements": [ { "minServerVersion": "4.0.0", "topologies": [ "single", "replicaset" ] }, { "minServerVersion": "4.2.0", "topologies": [ "sharded" ] } ], "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "client0", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "count" ], "closeConnection": true } } } }, { "name": "estimatedDocumentCount", "object": "collection0", "expectError": { "isError": true } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "count": "coll0" }, "commandName": "count", "databaseName": "edc-tests" } } ] } ] }, { "description": "estimatedDocumentCount works correctly on views", "runOnRequirements": [ { "minServerVersion": "3.4.0" } ], "operations": [ { "name": "dropCollection", "object": "database0", "arguments": { "collection": "coll0view" } }, { "name": "createCollection", "object": "database0", "arguments": { "collection": "coll0view", "viewOn": "coll0", "pipeline": [ { "$match": { "_id": { "$gt": 1 } } } ] } }, { "name": "estimatedDocumentCount", "object": "collection0View", "expectResult": 2 } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "drop": "coll0view" }, "commandName": "drop", "databaseName": "edc-tests" } }, { "commandStartedEvent": { "command": { "create": "coll0view", "viewOn": "coll0", "pipeline": [ { "$match": { "_id": { "$gt": 1 } } } ] }, "commandName": "create", "databaseName": "edc-tests" } }, { "commandStartedEvent": { "command": { "count": "coll0view" }, "commandName": "count", "databaseName": "edc-tests" } } ] } ] } ] } mongodb-mongo-python-driver-509e9b7/test/crud/unified/find-allowdiskuse-clientError.json000066400000000000000000000031131462766011000315770ustar00rootroot00000000000000{ "description": "find-allowdiskuse-clientError", "schemaVersion": "1.0", "runOnRequirements": [ { "maxServerVersion": "3.0.99" } ], "createEntities": [ { "client": { "id": "client0", "observeEvents": [ "commandStartedEvent" ] } }, { "database": { "id": "database0", "client": "client0", "databaseName": "crud-v2" } }, { "collection": { "id": "collection0", "database": "database0", "collectionName": "test_find_allowdiskuse_clienterror" } } ], "tests": [ { "description": "Find fails when allowDiskUse true is specified against pre 3.2 server", "operations": [ { "object": "collection0", "name": "find", "arguments": { "filter": {}, "allowDiskUse": true }, "expectError": { "isError": true } } ], "expectEvents": [ { "client": "client0", "events": [] } ] }, { "description": "Find fails when allowDiskUse false is specified against pre 3.2 server", "operations": [ { "object": "collection0", "name": "find", "arguments": { "filter": {}, "allowDiskUse": false }, "expectError": { "isError": true } } ], "expectEvents": [ { "client": "client0", "events": [] } ] } ] } mongodb-mongo-python-driver-509e9b7/test/crud/unified/find-allowdiskuse-serverError.json000066400000000000000000000042741462766011000316400ustar00rootroot00000000000000{ "description": "find-allowdiskuse-serverError", "schemaVersion": "1.0", "runOnRequirements": [ { "minServerVersion": "3.2", "maxServerVersion": "4.3.0" } ], "createEntities": [ { "client": { "id": "client0", "observeEvents": [ "commandStartedEvent" ] } }, { "database": { "id": "database0", "client": "client0", "databaseName": "crud-v2" } }, { "collection": { "id": "collection0", "database": "database0", "collectionName": "test_find_allowdiskuse_servererror" } } ], "tests": [ { "description": "Find fails when allowDiskUse true is specified against pre 4.4 server (server-side error)", "operations": [ { "object": "collection0", "name": "find", "arguments": { "filter": {}, "allowDiskUse": true }, "expectError": { "isError": true } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "find": "test_find_allowdiskuse_servererror", "filter": {}, "allowDiskUse": true } } } ] } ] }, { "description": "Find fails when allowDiskUse false is specified against pre 4.4 server (server-side error)", "operations": [ { "object": "collection0", "name": "find", "arguments": { "filter": {}, "allowDiskUse": false }, "expectError": { "isError": true } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "find": "test_find_allowdiskuse_servererror", "filter": {}, "allowDiskUse": false } } } ] } ] } ] } mongodb-mongo-python-driver-509e9b7/test/crud/unified/find-allowdiskuse.json000066400000000000000000000047601462766011000273220ustar00rootroot00000000000000{ "description": "find-allowdiskuse", "schemaVersion": "1.0", "runOnRequirements": [ { "minServerVersion": "4.3.1" } ], "createEntities": [ { "client": { "id": "client0", "observeEvents": [ "commandStartedEvent" ] } }, { "database": { "id": "database0", "client": "client0", "databaseName": "crud-v2" } }, { "collection": { "id": "collection0", "database": "database0", "collectionName": "test_find_allowdiskuse" } } ], "tests": [ { "description": "Find does not send allowDiskUse when value is not specified", "operations": [ { "object": "collection0", "name": "find", "arguments": { "filter": {} } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "find": "test_find_allowdiskuse", "allowDiskUse": { "$$exists": false } } } } ] } ] }, { "description": "Find sends allowDiskUse false when false is specified", "operations": [ { "object": "collection0", "name": "find", "arguments": { "filter": {}, "allowDiskUse": false } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "find": "test_find_allowdiskuse", "allowDiskUse": false } } } ] } ] }, { "description": "Find sends allowDiskUse true when true is specified", "operations": [ { "object": "collection0", "name": "find", "arguments": { "filter": {}, "allowDiskUse": true } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "find": "test_find_allowdiskuse", "allowDiskUse": true } } } ] } ] } ] } mongodb-mongo-python-driver-509e9b7/test/crud/unified/find-comment.json000066400000000000000000000206661462766011000262610ustar00rootroot00000000000000{ "description": "find-comment", "schemaVersion": "1.0", "createEntities": [ { "client": { "id": "client0", "observeEvents": [ "commandStartedEvent" ] } }, { "database": { "id": "database0", "client": "client0", "databaseName": "crud-tests" } }, { "collection": { "id": "collection0", "database": "database0", "collectionName": "coll0" } } ], "initialData": [ { "collectionName": "coll0", "databaseName": "crud-tests", "documents": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 22 }, { "_id": 3, "x": 33 }, { "_id": 4, "x": 44 }, { "_id": 5, "x": 55 }, { "_id": 6, "x": 66 } ] } ], "tests": [ { "description": "find with string comment", "runOnRequirements": [ { "minServerVersion": "3.6" } ], "operations": [ { "name": "find", "object": "collection0", "arguments": { "filter": { "_id": 1 }, "comment": "comment" }, "expectResult": [ { "_id": 1 } ] } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "find": "coll0", "filter": { "_id": 1 }, "comment": "comment" } } } ] } ] }, { "description": "find with document comment", "runOnRequirements": [ { "minServerVersion": "4.4" } ], "operations": [ { "name": "find", "object": "collection0", "arguments": { "filter": { "_id": 1 }, "comment": { "key": "value" } }, "expectResult": [ { "_id": 1 } ] } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "find": "coll0", "filter": { "_id": 1 }, "comment": { "key": "value" } } } } ] } ] }, { "description": "find with document comment - pre 4.4", "runOnRequirements": [ { "maxServerVersion": "4.2.99", "minServerVersion": "3.6" } ], "operations": [ { "name": "find", "object": "collection0", "arguments": { "filter": { "_id": 1 }, "comment": { "key": "value" } }, "expectError": { "isClientError": false } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "find": "coll0", "filter": { "_id": 1 }, "comment": { "key": "value" } } } } ] } ] }, { "description": "find with comment sets comment on getMore", "runOnRequirements": [ { "minServerVersion": "4.4.0" } ], "operations": [ { "name": "find", "object": "collection0", "arguments": { "filter": { "_id": { "$gt": 1 } }, "batchSize": 2, "comment": { "key": "value" } }, "expectResult": [ { "_id": 2, "x": 22 }, { "_id": 3, "x": 33 }, { "_id": 4, "x": 44 }, { "_id": 5, "x": 55 }, { "_id": 6, "x": 66 } ] } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "find": "coll0", "filter": { "_id": { "$gt": 1 } }, "batchSize": 2, "comment": { "key": "value" } } } }, { "commandStartedEvent": { "command": { "getMore": { "$$type": [ "int", "long" ] }, "collection": "coll0", "batchSize": 2, "comment": { "key": "value" } } } }, { "commandStartedEvent": { "command": { "getMore": { "$$type": [ "int", "long" ] }, "collection": "coll0", "batchSize": 2, "comment": { "key": "value" } } } } ] } ] }, { "description": "find with comment does not set comment on getMore - pre 4.4", "runOnRequirements": [ { "minServerVersion": "3.6.0", "maxServerVersion": "4.3.99" } ], "operations": [ { "name": "find", "object": "collection0", "arguments": { "filter": { "_id": { "$gt": 1 } }, "batchSize": 2, "comment": "comment" }, "expectResult": [ { "_id": 2, "x": 22 }, { "_id": 3, "x": 33 }, { "_id": 4, "x": 44 }, { "_id": 5, "x": 55 }, { "_id": 6, "x": 66 } ] } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "find": "coll0", "filter": { "_id": { "$gt": 1 } }, "batchSize": 2, "comment": "comment" } } }, { "commandStartedEvent": { "command": { "getMore": { "$$type": [ "int", "long" ] }, "collection": "coll0", "batchSize": 2, "comment": { "$$exists": false } } } }, { "commandStartedEvent": { "command": { "getMore": { "$$type": [ "int", "long" ] }, "collection": "coll0", "batchSize": 2, "comment": { "$$exists": false } } } } ] } ] } ] } mongodb-mongo-python-driver-509e9b7/test/crud/unified/find-let.json000066400000000000000000000056501462766011000253770ustar00rootroot00000000000000{ "description": "find-let", "schemaVersion": "1.0", "createEntities": [ { "client": { "id": "client0", "observeEvents": [ "commandStartedEvent" ] } }, { "database": { "id": "database0", "client": "client0", "databaseName": "crud-tests" } }, { "collection": { "id": "collection0", "database": "database0", "collectionName": "coll0" } } ], "initialData": [ { "collectionName": "coll0", "databaseName": "crud-tests", "documents": [ { "_id": 1 }, { "_id": 2 } ] } ], "tests": [ { "description": "Find with let option", "runOnRequirements": [ { "minServerVersion": "5.0" } ], "operations": [ { "name": "find", "object": "collection0", "arguments": { "filter": { "$expr": { "$eq": [ "$_id", "$$id" ] } }, "let": { "id": 1 } }, "expectResult": [ { "_id": 1 } ] } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "find": "coll0", "filter": { "$expr": { "$eq": [ "$_id", "$$id" ] } }, "let": { "id": 1 } } } } ] } ] }, { "description": "Find with let option unsupported (server-side error)", "runOnRequirements": [ { "minServerVersion": "3.6.0", "maxServerVersion": "4.4.99" } ], "operations": [ { "name": "find", "object": "collection0", "arguments": { "filter": { "_id": 1 }, "let": { "x": 1 } }, "expectError": { "errorContains": "Unrecognized field 'let'", "isClientError": false } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "find": "coll0", "filter": { "_id": 1 }, "let": { "x": 1 } } } } ] } ] } ] } mongodb-mongo-python-driver-509e9b7/test/crud/unified/find.json000066400000000000000000000062461462766011000246170ustar00rootroot00000000000000{ "description": "find", "schemaVersion": "1.0", "createEntities": [ { "client": { "id": "client0", "useMultipleMongoses": true, "observeEvents": [ "commandStartedEvent" ] } }, { "database": { "id": "database0", "client": "client0", "databaseName": "find-tests" } }, { "collection": { "id": "collection0", "database": "database0", "collectionName": "coll0" } } ], "initialData": [ { "collectionName": "coll0", "databaseName": "find-tests", "documents": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 22 }, { "_id": 3, "x": 33 }, { "_id": 4, "x": 44 }, { "_id": 5, "x": 55 }, { "_id": 6, "x": 66 } ] } ], "tests": [ { "description": "find with multiple batches works", "operations": [ { "name": "find", "arguments": { "filter": { "_id": { "$gt": 1 } }, "batchSize": 2 }, "object": "collection0", "expectResult": [ { "_id": 2, "x": 22 }, { "_id": 3, "x": 33 }, { "_id": 4, "x": 44 }, { "_id": 5, "x": 55 }, { "_id": 6, "x": 66 } ] } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "find": "coll0", "filter": { "_id": { "$gt": 1 } }, "batchSize": 2 }, "commandName": "find", "databaseName": "find-tests" } }, { "commandStartedEvent": { "command": { "getMore": { "$$type": [ "int", "long" ] }, "collection": "coll0", "batchSize": 2 }, "commandName": "getMore", "databaseName": "find-tests" } }, { "commandStartedEvent": { "command": { "getMore": { "$$type": [ "int", "long" ] }, "collection": "coll0", "batchSize": 2 }, "commandName": "getMore", "databaseName": "find-tests" } } ] } ] } ] } mongodb-mongo-python-driver-509e9b7/test/crud/unified/findOneAndDelete-comment.json000066400000000000000000000104041462766011000304560ustar00rootroot00000000000000{ "description": "findOneAndDelete-comment", "schemaVersion": "1.0", "createEntities": [ { "client": { "id": "client0", "observeEvents": [ "commandStartedEvent" ] } }, { "database": { "id": "database0", "client": "client0", "databaseName": "crud-tests" } }, { "collection": { "id": "collection0", "database": "database0", "collectionName": "coll0" } } ], "initialData": [ { "collectionName": "coll0", "databaseName": "crud-tests", "documents": [ { "_id": 1 }, { "_id": 2 } ] } ], "tests": [ { "description": "findOneAndDelete with string comment", "runOnRequirements": [ { "minServerVersion": "4.4" } ], "operations": [ { "name": "findOneAndDelete", "object": "collection0", "arguments": { "filter": { "_id": 1 }, "comment": "comment" }, "expectResult": { "_id": 1 } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "findAndModify": "coll0", "query": { "_id": 1 }, "remove": true, "comment": "comment" } } } ] } ], "outcome": [ { "collectionName": "coll0", "databaseName": "crud-tests", "documents": [ { "_id": 2 } ] } ] }, { "description": "findOneAndDelete with document comment", "runOnRequirements": [ { "minServerVersion": "4.4" } ], "operations": [ { "name": "findOneAndDelete", "object": "collection0", "arguments": { "filter": { "_id": 1 }, "comment": { "key": "value" } }, "expectResult": { "_id": 1 } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "findAndModify": "coll0", "query": { "_id": 1 }, "remove": true, "comment": { "key": "value" } } } } ] } ], "outcome": [ { "collectionName": "coll0", "databaseName": "crud-tests", "documents": [ { "_id": 2 } ] } ] }, { "description": "findOneAndDelete with comment - pre 4.4", "runOnRequirements": [ { "minServerVersion": "4.2.0", "maxServerVersion": "4.2.99" } ], "operations": [ { "name": "findOneAndDelete", "object": "collection0", "arguments": { "filter": { "_id": 1 }, "comment": "comment" }, "expectError": { "isClientError": false } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "findAndModify": "coll0", "query": { "_id": 1 }, "remove": true, "comment": "comment" } } } ] } ], "outcome": [ { "collectionName": "coll0", "databaseName": "crud-tests", "documents": [ { "_id": 1 }, { "_id": 2 } ] } ] } ] } mongodb-mongo-python-driver-509e9b7/test/crud/unified/findOneAndDelete-hint-clientError.json000066400000000000000000000050361462766011000322510ustar00rootroot00000000000000{ "description": "findOneAndDelete-hint-clientError", "schemaVersion": "1.0", "runOnRequirements": [ { "maxServerVersion": "4.0.99" } ], "createEntities": [ { "client": { "id": "client0", "observeEvents": [ "commandStartedEvent" ] } }, { "database": { "id": "database0", "client": "client0", "databaseName": "crud-v2" } }, { "collection": { "id": "collection0", "database": "database0", "collectionName": "findOneAndDelete_hint" } } ], "initialData": [ { "collectionName": "findOneAndDelete_hint", "databaseName": "crud-v2", "documents": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 22 } ] } ], "tests": [ { "description": "FindOneAndDelete with hint string unsupported (client-side error)", "operations": [ { "object": "collection0", "name": "findOneAndDelete", "arguments": { "filter": { "_id": 1 }, "hint": "_id_" }, "expectError": { "isError": true } } ], "expectEvents": [ { "client": "client0", "events": [] } ], "outcome": [ { "collectionName": "findOneAndDelete_hint", "databaseName": "crud-v2", "documents": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 22 } ] } ] }, { "description": "FindOneAndDelete with hint document", "operations": [ { "object": "collection0", "name": "findOneAndDelete", "arguments": { "filter": { "_id": 1 }, "hint": { "_id": 1 } }, "expectError": { "isError": true } } ], "expectEvents": [ { "client": "client0", "events": [] } ], "outcome": [ { "collectionName": "findOneAndDelete_hint", "databaseName": "crud-v2", "documents": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 22 } ] } ] } ] } mongodb-mongo-python-driver-509e9b7/test/crud/unified/findOneAndDelete-hint-serverError.json000066400000000000000000000065021462766011000323000ustar00rootroot00000000000000{ "description": "findOneAndDelete-hint-serverError", "schemaVersion": "1.0", "runOnRequirements": [ { "minServerVersion": "4.2.0", "maxServerVersion": "4.3.3" } ], "createEntities": [ { "client": { "id": "client0", "observeEvents": [ "commandStartedEvent" ] } }, { "database": { "id": "database0", "client": "client0", "databaseName": "crud-v2" } }, { "collection": { "id": "collection0", "database": "database0", "collectionName": "findOneAndDelete_hint" } } ], "initialData": [ { "collectionName": "findOneAndDelete_hint", "databaseName": "crud-v2", "documents": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 22 } ] } ], "tests": [ { "description": "FindOneAndDelete with hint string unsupported (server-side error)", "operations": [ { "object": "collection0", "name": "findOneAndDelete", "arguments": { "filter": { "_id": 1 }, "hint": "_id_" }, "expectError": { "isError": true } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "findAndModify": "findOneAndDelete_hint", "query": { "_id": 1 }, "hint": "_id_", "remove": true } } } ] } ], "outcome": [ { "collectionName": "findOneAndDelete_hint", "databaseName": "crud-v2", "documents": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 22 } ] } ] }, { "description": "FindOneAndDelete with hint document unsupported (server-side error)", "operations": [ { "object": "collection0", "name": "findOneAndDelete", "arguments": { "filter": { "_id": 1 }, "hint": { "_id": 1 } }, "expectError": { "isError": true } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "findAndModify": "findOneAndDelete_hint", "query": { "_id": 1 }, "hint": { "_id": 1 }, "remove": true } } } ] } ], "outcome": [ { "collectionName": "findOneAndDelete_hint", "databaseName": "crud-v2", "documents": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 22 } ] } ] } ] } mongodb-mongo-python-driver-509e9b7/test/crud/unified/findOneAndDelete-hint-unacknowledged.json000066400000000000000000000114271462766011000327540ustar00rootroot00000000000000{ "description": "findOneAndDelete-hint-unacknowledged", "schemaVersion": "1.0", "createEntities": [ { "client": { "id": "client0", "observeEvents": [ "commandStartedEvent" ] } }, { "database": { "id": "database0", "client": "client0", "databaseName": "db0" } }, { "collection": { "id": "collection0", "database": "database0", "collectionName": "coll0", "collectionOptions": { "writeConcern": { "w": 0 } } } } ], "initialData": [ { "collectionName": "coll0", "databaseName": "db0", "documents": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 22 } ] } ], "tests": [ { "description": "Unacknowledged findOneAndDelete with hint string fails with client-side error on pre-4.4 server", "runOnRequirements": [ { "maxServerVersion": "4.2.99" } ], "operations": [ { "object": "collection0", "name": "findOneAndDelete", "arguments": { "filter": { "_id": { "$gt": 1 } }, "hint": "_id_" }, "expectError": { "isClientError": true } } ], "expectEvents": [ { "client": "client0", "events": [] } ] }, { "description": "Unacknowledged findOneAndDelete with hint document fails with client-side error on pre-4.4 server", "runOnRequirements": [ { "maxServerVersion": "4.2.99" } ], "operations": [ { "object": "collection0", "name": "findOneAndDelete", "arguments": { "filter": { "_id": { "$gt": 1 } }, "hint": { "_id": 1 } }, "expectError": { "isClientError": true } } ], "expectEvents": [ { "client": "client0", "events": [] } ] }, { "description": "Unacknowledged findOneAndDelete with hint string on 4.4+ server", "runOnRequirements": [ { "minServerVersion": "4.4.0" } ], "operations": [ { "object": "collection0", "name": "findOneAndDelete", "arguments": { "filter": { "_id": { "$gt": 1 } }, "hint": "_id_" }, "expectResult": { "$$unsetOrMatches": null } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "findAndModify": "coll0", "query": { "_id": { "$gt": 1 } }, "remove": true, "hint": { "$$type": [ "string", "object" ] }, "writeConcern": { "w": 0 } } } } ] } ] }, { "description": "Unacknowledged findOneAndDelete with hint document on 4.4+ server", "runOnRequirements": [ { "minServerVersion": "4.4.0" } ], "operations": [ { "object": "collection0", "name": "findOneAndDelete", "arguments": { "filter": { "_id": { "$gt": 1 } }, "hint": { "_id": 1 } }, "expectResult": { "$$unsetOrMatches": null } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "findAndModify": "coll0", "query": { "_id": { "$gt": 1 } }, "remove": true, "hint": { "$$type": [ "string", "object" ] }, "writeConcern": { "w": 0 } } } } ] } ] } ] } mongodb-mongo-python-driver-509e9b7/test/crud/unified/findOneAndDelete-hint.json000066400000000000000000000061331462766011000277620ustar00rootroot00000000000000{ "description": "findOneAndDelete-hint", "schemaVersion": "1.0", "runOnRequirements": [ { "minServerVersion": "4.3.4" } ], "createEntities": [ { "client": { "id": "client0", "observeEvents": [ "commandStartedEvent" ] } }, { "database": { "id": "database0", "client": "client0", "databaseName": "crud-v2" } }, { "collection": { "id": "collection0", "database": "database0", "collectionName": "findOneAndDelete_hint" } } ], "initialData": [ { "collectionName": "findOneAndDelete_hint", "databaseName": "crud-v2", "documents": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 22 } ] } ], "tests": [ { "description": "FindOneAndDelete with hint string", "operations": [ { "object": "collection0", "name": "findOneAndDelete", "arguments": { "filter": { "_id": 1 }, "hint": "_id_" }, "expectResult": { "_id": 1, "x": 11 } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "findAndModify": "findOneAndDelete_hint", "query": { "_id": 1 }, "hint": "_id_", "remove": true } } } ] } ], "outcome": [ { "collectionName": "findOneAndDelete_hint", "databaseName": "crud-v2", "documents": [ { "_id": 2, "x": 22 } ] } ] }, { "description": "FindOneAndDelete with hint document", "operations": [ { "object": "collection0", "name": "findOneAndDelete", "arguments": { "filter": { "_id": 1 }, "hint": { "_id": 1 } }, "expectResult": { "_id": 1, "x": 11 } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "findAndModify": "findOneAndDelete_hint", "query": { "_id": 1 }, "hint": { "_id": 1 }, "remove": true } } } ] } ], "outcome": [ { "collectionName": "findOneAndDelete_hint", "databaseName": "crud-v2", "documents": [ { "_id": 2, "x": 22 } ] } ] } ] } mongodb-mongo-python-driver-509e9b7/test/crud/unified/findOneAndDelete-let.json000066400000000000000000000073011462766011000276020ustar00rootroot00000000000000{ "description": "findOneAndDelete-let", "schemaVersion": "1.0", "createEntities": [ { "client": { "id": "client0", "observeEvents": [ "commandStartedEvent" ] } }, { "database": { "id": "database0", "client": "client0", "databaseName": "crud-tests" } }, { "collection": { "id": "collection0", "database": "database0", "collectionName": "coll0" } } ], "initialData": [ { "collectionName": "coll0", "databaseName": "crud-tests", "documents": [ { "_id": 1 }, { "_id": 2 } ] } ], "tests": [ { "description": "findOneAndDelete with let option", "runOnRequirements": [ { "minServerVersion": "5.0" } ], "operations": [ { "name": "findOneAndDelete", "object": "collection0", "arguments": { "filter": { "$expr": { "$eq": [ "$_id", "$$id" ] } }, "let": { "id": 1 } } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "findAndModify": "coll0", "query": { "$expr": { "$eq": [ "$_id", "$$id" ] } }, "remove": true, "let": { "id": 1 } } } } ] } ], "outcome": [ { "collectionName": "coll0", "databaseName": "crud-tests", "documents": [ { "_id": 2 } ] } ] }, { "description": "findOneAndDelete with let option unsupported (server-side error)", "runOnRequirements": [ { "minServerVersion": "4.2.0", "maxServerVersion": "4.4.99" } ], "operations": [ { "name": "findOneAndDelete", "object": "collection0", "arguments": { "filter": { "$expr": { "$eq": [ "$_id", "$$id" ] } }, "let": { "id": 1 } }, "expectError": { "errorContains": "field 'let' is an unknown field", "isClientError": false } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "findAndModify": "coll0", "query": { "$expr": { "$eq": [ "$_id", "$$id" ] } }, "remove": true, "let": { "id": 1 } } } } ] } ], "outcome": [ { "collectionName": "coll0", "databaseName": "crud-tests", "documents": [ { "_id": 1 }, { "_id": 2 } ] } ] } ] } mongodb-mongo-python-driver-509e9b7/test/crud/unified/findOneAndReplace-comment.json000066400000000000000000000113461462766011000306350ustar00rootroot00000000000000{ "description": "findOneAndReplace-comment", "schemaVersion": "1.0", "createEntities": [ { "client": { "id": "client0", "observeEvents": [ "commandStartedEvent" ] } }, { "database": { "id": "database0", "client": "client0", "databaseName": "crud-tests" } }, { "collection": { "id": "collection0", "database": "database0", "collectionName": "coll0" } } ], "initialData": [ { "collectionName": "coll0", "databaseName": "crud-tests", "documents": [ { "_id": 1 }, { "_id": 2 } ] } ], "tests": [ { "description": "findOneAndReplace with string comment", "runOnRequirements": [ { "minServerVersion": "4.4" } ], "operations": [ { "name": "findOneAndReplace", "object": "collection0", "arguments": { "filter": { "_id": 1 }, "replacement": { "x": 5 }, "comment": "comment" }, "expectResult": { "_id": 1 } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "findAndModify": "coll0", "query": { "_id": 1 }, "update": { "x": 5 }, "comment": "comment" } } } ] } ], "outcome": [ { "collectionName": "coll0", "databaseName": "crud-tests", "documents": [ { "_id": 1, "x": 5 }, { "_id": 2 } ] } ] }, { "description": "findOneAndReplace with document comment", "runOnRequirements": [ { "minServerVersion": "4.4" } ], "operations": [ { "name": "findOneAndReplace", "object": "collection0", "arguments": { "filter": { "_id": 1 }, "replacement": { "x": 5 }, "comment": { "key": "value" } }, "expectResult": { "_id": 1 } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "findAndModify": "coll0", "query": { "_id": 1 }, "update": { "x": 5 }, "comment": { "key": "value" } } } } ] } ], "outcome": [ { "collectionName": "coll0", "databaseName": "crud-tests", "documents": [ { "_id": 1, "x": 5 }, { "_id": 2 } ] } ] }, { "description": "findOneAndReplace with comment - pre 4.4", "runOnRequirements": [ { "minServerVersion": "4.2.0", "maxServerVersion": "4.2.99" } ], "operations": [ { "name": "findOneAndReplace", "object": "collection0", "arguments": { "filter": { "_id": 1 }, "replacement": { "x": 5 }, "comment": "comment" }, "expectError": { "isClientError": false } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "findAndModify": "coll0", "query": { "_id": 1 }, "update": { "x": 5 }, "comment": "comment" } } } ] } ], "outcome": [ { "collectionName": "coll0", "databaseName": "crud-tests", "documents": [ { "_id": 1 }, { "_id": 2 } ] } ] } ] } mongodb-mongo-python-driver-509e9b7/test/crud/unified/findOneAndReplace-dots_and_dollars.json000066400000000000000000000224351462766011000325070ustar00rootroot00000000000000{ "description": "findOneAndReplace-dots_and_dollars", "schemaVersion": "1.0", "createEntities": [ { "client": { "id": "client0", "observeEvents": [ "commandStartedEvent" ] } }, { "database": { "id": "database0", "client": "client0", "databaseName": "crud-tests" } }, { "collection": { "id": "collection0", "database": "database0", "collectionName": "coll0" } } ], "initialData": [ { "collectionName": "coll0", "databaseName": "crud-tests", "documents": [ { "_id": 1 } ] } ], "tests": [ { "description": "Replacing document with top-level dotted key on 3.6+ server", "runOnRequirements": [ { "minServerVersion": "3.6" } ], "operations": [ { "name": "findOneAndReplace", "object": "collection0", "arguments": { "filter": { "_id": 1 }, "replacement": { "_id": 1, "a.b": 1 } }, "expectResult": { "_id": 1 } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "findAndModify": "coll0", "query": { "_id": 1 }, "update": { "_id": 1, "a.b": 1 }, "new": { "$$unsetOrMatches": false } } } } ] } ], "outcome": [ { "collectionName": "coll0", "databaseName": "crud-tests", "documents": [ { "_id": 1, "a.b": 1 } ] } ] }, { "description": "Replacing document with top-level dotted key on pre-3.6 server yields server-side error", "runOnRequirements": [ { "maxServerVersion": "3.4.99" } ], "operations": [ { "name": "findOneAndReplace", "object": "collection0", "arguments": { "filter": { "_id": 1 }, "replacement": { "_id": 1, "a.b": 1 } }, "expectError": { "isClientError": false } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "findAndModify": "coll0", "query": { "_id": 1 }, "update": { "_id": 1, "a.b": 1 }, "new": { "$$unsetOrMatches": false } } } } ] } ], "outcome": [ { "collectionName": "coll0", "databaseName": "crud-tests", "documents": [ { "_id": 1 } ] } ] }, { "description": "Replacing document with dollar-prefixed key in embedded doc on 5.0+ server", "runOnRequirements": [ { "minServerVersion": "5.0" } ], "operations": [ { "name": "findOneAndReplace", "object": "collection0", "arguments": { "filter": { "_id": 1 }, "replacement": { "_id": 1, "a": { "$b": 1 } } }, "expectResult": { "_id": 1 } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "findAndModify": "coll0", "query": { "_id": 1 }, "update": { "_id": 1, "a": { "$b": 1 } }, "new": { "$$unsetOrMatches": false } } } } ] } ], "outcome": [ { "collectionName": "coll0", "databaseName": "crud-tests", "documents": [ { "_id": 1, "a": { "$b": 1 } } ] } ] }, { "description": "Replacing document with dollar-prefixed key in embedded doc on pre-5.0 server yields server-side error", "runOnRequirements": [ { "maxServerVersion": "4.99" } ], "operations": [ { "name": "findOneAndReplace", "object": "collection0", "arguments": { "filter": { "_id": 1 }, "replacement": { "_id": 1, "a": { "$b": 1 } } }, "expectError": { "isClientError": false } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "findAndModify": "coll0", "query": { "_id": 1 }, "update": { "_id": 1, "a": { "$b": 1 } }, "new": { "$$unsetOrMatches": false } } } } ] } ], "outcome": [ { "collectionName": "coll0", "databaseName": "crud-tests", "documents": [ { "_id": 1 } ] } ] }, { "description": "Replacing document with dotted key in embedded doc on 3.6+ server", "runOnRequirements": [ { "minServerVersion": "3.6" } ], "operations": [ { "name": "findOneAndReplace", "object": "collection0", "arguments": { "filter": { "_id": 1 }, "replacement": { "_id": 1, "a": { "b.c": 1 } } }, "expectResult": { "_id": 1 } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "findAndModify": "coll0", "query": { "_id": 1 }, "update": { "_id": 1, "a": { "b.c": 1 } }, "new": { "$$unsetOrMatches": false } } } } ] } ], "outcome": [ { "collectionName": "coll0", "databaseName": "crud-tests", "documents": [ { "_id": 1, "a": { "b.c": 1 } } ] } ] }, { "description": "Replacing document with dotted key in embedded doc on pre-3.6 server yields server-side error", "runOnRequirements": [ { "maxServerVersion": "3.4.99" } ], "operations": [ { "name": "findOneAndReplace", "object": "collection0", "arguments": { "filter": { "_id": 1 }, "replacement": { "_id": 1, "a": { "b.c": 1 } } }, "expectError": { "isClientError": false } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "findAndModify": "coll0", "query": { "_id": 1 }, "update": { "_id": 1, "a": { "b.c": 1 } }, "new": { "$$unsetOrMatches": false } } } } ] } ], "outcome": [ { "collectionName": "coll0", "databaseName": "crud-tests", "documents": [ { "_id": 1 } ] } ] } ] } mongodb-mongo-python-driver-509e9b7/test/crud/unified/findOneAndReplace-hint-clientError.json000066400000000000000000000053131462766011000324200ustar00rootroot00000000000000{ "description": "findOneAndReplace-hint-clientError", "schemaVersion": "1.0", "runOnRequirements": [ { "maxServerVersion": "4.0.99" } ], "createEntities": [ { "client": { "id": "client0", "observeEvents": [ "commandStartedEvent" ] } }, { "database": { "id": "database0", "client": "client0", "databaseName": "crud-v2" } }, { "collection": { "id": "collection0", "database": "database0", "collectionName": "findOneAndReplace_hint" } } ], "initialData": [ { "collectionName": "findOneAndReplace_hint", "databaseName": "crud-v2", "documents": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 22 } ] } ], "tests": [ { "description": "FindOneAndReplace with hint string unsupported (client-side error)", "operations": [ { "object": "collection0", "name": "findOneAndReplace", "arguments": { "filter": { "_id": 1 }, "replacement": { "x": 33 }, "hint": "_id_" }, "expectError": { "isError": true } } ], "expectEvents": [ { "client": "client0", "events": [] } ], "outcome": [ { "collectionName": "findOneAndReplace_hint", "databaseName": "crud-v2", "documents": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 22 } ] } ] }, { "description": "FindOneAndReplace with hint document unsupported (client-side error)", "operations": [ { "object": "collection0", "name": "findOneAndReplace", "arguments": { "filter": { "_id": 1 }, "replacement": { "x": 33 }, "hint": { "_id": 1 } }, "expectError": { "isError": true } } ], "expectEvents": [ { "client": "client0", "events": [] } ], "outcome": [ { "collectionName": "findOneAndReplace_hint", "databaseName": "crud-v2", "documents": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 22 } ] } ] } ] } mongodb-mongo-python-driver-509e9b7/test/crud/unified/findOneAndReplace-hint-serverError.json000066400000000000000000000070531462766011000324530ustar00rootroot00000000000000{ "description": "findOneAndReplace-hint-serverError", "schemaVersion": "1.0", "runOnRequirements": [ { "minServerVersion": "4.2.0", "maxServerVersion": "4.3.0" } ], "createEntities": [ { "client": { "id": "client0", "observeEvents": [ "commandStartedEvent" ] } }, { "database": { "id": "database0", "client": "client0", "databaseName": "crud-v2" } }, { "collection": { "id": "collection0", "database": "database0", "collectionName": "findOneAndReplace_hint" } } ], "initialData": [ { "collectionName": "findOneAndReplace_hint", "databaseName": "crud-v2", "documents": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 22 } ] } ], "tests": [ { "description": "FindOneAndReplace with hint string unsupported (server-side error)", "operations": [ { "object": "collection0", "name": "findOneAndReplace", "arguments": { "filter": { "_id": 1 }, "replacement": { "x": 33 }, "hint": "_id_" }, "expectError": { "isError": true } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "findAndModify": "findOneAndReplace_hint", "query": { "_id": 1 }, "update": { "x": 33 }, "hint": "_id_" } } } ] } ], "outcome": [ { "collectionName": "findOneAndReplace_hint", "databaseName": "crud-v2", "documents": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 22 } ] } ] }, { "description": "FindOneAndReplace with hint document unsupported (server-side error)", "operations": [ { "object": "collection0", "name": "findOneAndReplace", "arguments": { "filter": { "_id": 1 }, "replacement": { "x": 33 }, "hint": { "_id": 1 } }, "expectError": { "isError": true } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "findAndModify": "findOneAndReplace_hint", "query": { "_id": 1 }, "update": { "x": 33 }, "hint": { "_id": 1 } } } } ] } ], "outcome": [ { "collectionName": "findOneAndReplace_hint", "databaseName": "crud-v2", "documents": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 22 } ] } ] } ] } mongodb-mongo-python-driver-509e9b7/test/crud/unified/findOneAndReplace-hint-unacknowledged.json000066400000000000000000000124231462766011000331220ustar00rootroot00000000000000{ "description": "findOneAndReplace-hint-unacknowledged", "schemaVersion": "1.0", "createEntities": [ { "client": { "id": "client0", "observeEvents": [ "commandStartedEvent" ] } }, { "database": { "id": "database0", "client": "client0", "databaseName": "db0" } }, { "collection": { "id": "collection0", "database": "database0", "collectionName": "coll0", "collectionOptions": { "writeConcern": { "w": 0 } } } }, { "collection": { "id": "collection1", "database": "database0", "collectionName": "coll0" } } ], "initialData": [ { "collectionName": "coll0", "databaseName": "db0", "documents": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 22 } ] } ], "tests": [ { "description": "Unacknowledged findOneAndReplace with hint string fails with client-side error on pre-4.4 server", "runOnRequirements": [ { "maxServerVersion": "4.2.99" } ], "operations": [ { "object": "collection0", "name": "findOneAndReplace", "arguments": { "filter": { "_id": { "$gt": 1 } }, "replacement": { "x": 111 }, "hint": "_id_" }, "expectError": { "isClientError": true } } ], "expectEvents": [ { "client": "client0", "events": [] } ] }, { "description": "Unacknowledged findOneAndReplace with hint document fails with client-side error on pre-4.4 server", "runOnRequirements": [ { "maxServerVersion": "4.2.99" } ], "operations": [ { "object": "collection0", "name": "findOneAndReplace", "arguments": { "filter": { "_id": { "$gt": 1 } }, "replacement": { "x": 111 }, "hint": { "_id": 1 } }, "expectError": { "isClientError": true } } ], "expectEvents": [ { "client": "client0", "events": [] } ] }, { "description": "Unacknowledged findOneAndReplace with hint string on 4.4+ server", "runOnRequirements": [ { "minServerVersion": "4.4.0" } ], "operations": [ { "object": "collection0", "name": "findOneAndReplace", "arguments": { "filter": { "_id": { "$gt": 1 } }, "replacement": { "x": 111 }, "hint": "_id_" }, "expectResult": { "$$unsetOrMatches": null } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "findAndModify": "coll0", "query": { "_id": { "$gt": 1 } }, "update": { "x": 111 }, "hint": { "$$type": [ "string", "object" ] }, "writeConcern": { "w": 0 } } } } ] } ] }, { "description": "Unacknowledged findOneAndReplace with hint document on 4.4+ server", "runOnRequirements": [ { "minServerVersion": "4.4.0" } ], "operations": [ { "object": "collection0", "name": "findOneAndReplace", "arguments": { "filter": { "_id": { "$gt": 1 } }, "replacement": { "x": 111 }, "hint": { "_id": 1 } }, "expectResult": { "$$unsetOrMatches": null } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "findAndModify": "coll0", "query": { "_id": { "$gt": 1 } }, "update": { "x": 111 }, "hint": { "$$type": [ "string", "object" ] }, "writeConcern": { "w": 0 } } } } ] } ] } ] } mongodb-mongo-python-driver-509e9b7/test/crud/unified/findOneAndReplace-hint.json000066400000000000000000000067321462766011000301400ustar00rootroot00000000000000{ "description": "findOneAndReplace-hint", "schemaVersion": "1.0", "runOnRequirements": [ { "minServerVersion": "4.3.1" } ], "createEntities": [ { "client": { "id": "client0", "observeEvents": [ "commandStartedEvent" ] } }, { "database": { "id": "database0", "client": "client0", "databaseName": "crud-v2" } }, { "collection": { "id": "collection0", "database": "database0", "collectionName": "findOneAndReplace_hint" } } ], "initialData": [ { "collectionName": "findOneAndReplace_hint", "databaseName": "crud-v2", "documents": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 22 } ] } ], "tests": [ { "description": "FindOneAndReplace with hint string", "operations": [ { "object": "collection0", "name": "findOneAndReplace", "arguments": { "filter": { "_id": 1 }, "replacement": { "x": 33 }, "hint": "_id_" }, "expectResult": { "_id": 1, "x": 11 } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "findAndModify": "findOneAndReplace_hint", "query": { "_id": 1 }, "update": { "x": 33 }, "hint": "_id_" } } } ] } ], "outcome": [ { "collectionName": "findOneAndReplace_hint", "databaseName": "crud-v2", "documents": [ { "_id": 1, "x": 33 }, { "_id": 2, "x": 22 } ] } ] }, { "description": "FindOneAndReplace with hint document", "operations": [ { "object": "collection0", "name": "findOneAndReplace", "arguments": { "filter": { "_id": 1 }, "replacement": { "x": 33 }, "hint": { "_id": 1 } }, "expectResult": { "_id": 1, "x": 11 } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "findAndModify": "findOneAndReplace_hint", "query": { "_id": 1 }, "update": { "x": 33 }, "hint": { "_id": 1 } } } } ] } ], "outcome": [ { "collectionName": "findOneAndReplace_hint", "databaseName": "crud-v2", "documents": [ { "_id": 1, "x": 33 }, { "_id": 2, "x": 22 } ] } ] } ] } mongodb-mongo-python-driver-509e9b7/test/crud/unified/findOneAndReplace-let.json000066400000000000000000000100621462766011000277510ustar00rootroot00000000000000{ "description": "findOneAndReplace-let", "schemaVersion": "1.0", "createEntities": [ { "client": { "id": "client0", "observeEvents": [ "commandStartedEvent" ] } }, { "database": { "id": "database0", "client": "client0", "databaseName": "crud-tests" } }, { "collection": { "id": "collection0", "database": "database0", "collectionName": "coll0" } } ], "initialData": [ { "collectionName": "coll0", "databaseName": "crud-tests", "documents": [ { "_id": 1 }, { "_id": 2 } ] } ], "tests": [ { "description": "findOneAndReplace with let option", "runOnRequirements": [ { "minServerVersion": "5.0" } ], "operations": [ { "name": "findOneAndReplace", "object": "collection0", "arguments": { "filter": { "$expr": { "$eq": [ "$_id", "$$id" ] } }, "replacement": { "x": "x" }, "let": { "id": 1 } }, "expectResult": { "_id": 1 } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "findAndModify": "coll0", "query": { "$expr": { "$eq": [ "$_id", "$$id" ] } }, "update": { "x": "x" }, "let": { "id": 1 } } } } ] } ], "outcome": [ { "collectionName": "coll0", "databaseName": "crud-tests", "documents": [ { "_id": 1, "x": "x" }, { "_id": 2 } ] } ] }, { "description": "findOneAndReplace with let option unsupported (server-side error)", "runOnRequirements": [ { "minServerVersion": "4.2.0", "maxServerVersion": "4.4.99" } ], "operations": [ { "name": "findOneAndReplace", "object": "collection0", "arguments": { "filter": { "$expr": { "$eq": [ "$_id", "$$id" ] } }, "replacement": { "x": "x" }, "let": { "id": 1 } }, "expectError": { "errorContains": "field 'let' is an unknown field", "isClientError": false } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "findAndModify": "coll0", "query": { "$expr": { "$eq": [ "$_id", "$$id" ] } }, "update": { "x": "x" }, "let": { "id": 1 } } } } ] } ], "outcome": [ { "collectionName": "coll0", "databaseName": "crud-tests", "documents": [ { "_id": 1 }, { "_id": 2 } ] } ] } ] } mongodb-mongo-python-driver-509e9b7/test/crud/unified/findOneAndUpdate-comment.json000066400000000000000000000112721462766011000305020ustar00rootroot00000000000000{ "description": "findOneAndUpdate-comment", "schemaVersion": "1.0", "createEntities": [ { "client": { "id": "client0", "observeEvents": [ "commandStartedEvent" ] } }, { "database": { "id": "database0", "client": "client0", "databaseName": "crud-tests" } }, { "collection": { "id": "collection0", "database": "database0", "collectionName": "coll0" } } ], "initialData": [ { "collectionName": "coll0", "databaseName": "crud-tests", "documents": [ { "_id": 1 }, { "_id": 2 } ] } ], "tests": [ { "description": "findOneAndUpdate with string comment", "runOnRequirements": [ { "minServerVersion": "4.4" } ], "operations": [ { "name": "findOneAndUpdate", "object": "collection0", "arguments": { "filter": { "_id": 1 }, "update": [ { "$set": { "x": 5 } } ], "comment": "comment" }, "expectResult": { "_id": 1 } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "findAndModify": "coll0", "query": { "_id": 1 }, "update": [ { "$set": { "x": 5 } } ], "comment": "comment" } } } ] } ] }, { "description": "findOneAndUpdate with document comment", "runOnRequirements": [ { "minServerVersion": "4.4" } ], "operations": [ { "name": "findOneAndUpdate", "object": "collection0", "arguments": { "filter": { "_id": 1 }, "update": [ { "$set": { "x": 5 } } ], "comment": { "key": "value" } }, "expectResult": { "_id": 1 } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "findAndModify": "coll0", "query": { "_id": 1 }, "update": [ { "$set": { "x": 5 } } ], "comment": { "key": "value" } } } } ] } ] }, { "description": "findOneAndUpdate with comment - pre 4.4", "runOnRequirements": [ { "minServerVersion": "4.2.0", "maxServerVersion": "4.2.99" } ], "operations": [ { "name": "findOneAndUpdate", "object": "collection0", "arguments": { "filter": { "_id": 1 }, "update": [ { "$set": { "x": 5 } } ], "comment": "comment" }, "expectError": { "isClientError": false } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "findAndModify": "coll0", "query": { "_id": 1 }, "update": [ { "$set": { "x": 5 } } ], "comment": "comment" } } } ] } ], "outcome": [ { "collectionName": "coll0", "databaseName": "crud-tests", "documents": [ { "_id": 1 }, { "_id": 2 } ] } ] } ] } mongodb-mongo-python-driver-509e9b7/test/crud/unified/findOneAndUpdate-dots_and_dollars.json000066400000000000000000000213521462766011000323530ustar00rootroot00000000000000{ "description": "findOneAndUpdate-dots_and_dollars", "schemaVersion": "1.0", "createEntities": [ { "client": { "id": "client0", "observeEvents": [ "commandStartedEvent" ] } }, { "database": { "id": "database0", "client": "client0", "databaseName": "crud-tests" } }, { "collection": { "id": "collection0", "database": "database0", "collectionName": "coll0" } } ], "initialData": [ { "collectionName": "coll0", "databaseName": "crud-tests", "documents": [ { "_id": 1, "foo": {} } ] } ], "tests": [ { "description": "Updating document to set top-level dollar-prefixed key on 5.0+ server", "runOnRequirements": [ { "minServerVersion": "5.0" } ], "operations": [ { "name": "findOneAndUpdate", "object": "collection0", "arguments": { "filter": { "_id": 1 }, "update": [ { "$replaceWith": { "$setField": { "field": { "$literal": "$a" }, "value": 1, "input": "$$ROOT" } } } ] }, "expectResult": { "_id": 1, "foo": {} } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "findAndModify": "coll0", "query": { "_id": 1 }, "update": [ { "$replaceWith": { "$setField": { "field": { "$literal": "$a" }, "value": 1, "input": "$$ROOT" } } } ], "new": { "$$unsetOrMatches": false } } } } ] } ], "outcome": [ { "collectionName": "coll0", "databaseName": "crud-tests", "documents": [ { "_id": 1, "foo": {}, "$a": 1 } ] } ] }, { "description": "Updating document to set top-level dotted key on 5.0+ server", "runOnRequirements": [ { "minServerVersion": "5.0" } ], "operations": [ { "name": "findOneAndUpdate", "object": "collection0", "arguments": { "filter": { "_id": 1 }, "update": [ { "$replaceWith": { "$setField": { "field": { "$literal": "a.b" }, "value": 1, "input": "$$ROOT" } } } ] }, "expectResult": { "_id": 1, "foo": {} } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "findAndModify": "coll0", "query": { "_id": 1 }, "update": [ { "$replaceWith": { "$setField": { "field": { "$literal": "a.b" }, "value": 1, "input": "$$ROOT" } } } ], "new": { "$$unsetOrMatches": false } } } } ] } ], "outcome": [ { "collectionName": "coll0", "databaseName": "crud-tests", "documents": [ { "_id": 1, "foo": {}, "a.b": 1 } ] } ] }, { "description": "Updating document to set dollar-prefixed key in embedded doc on 5.0+ server", "runOnRequirements": [ { "minServerVersion": "5.0" } ], "operations": [ { "name": "findOneAndUpdate", "object": "collection0", "arguments": { "filter": { "_id": 1 }, "update": [ { "$set": { "foo": { "$setField": { "field": { "$literal": "$a" }, "value": 1, "input": "$foo" } } } } ] }, "expectResult": { "_id": 1, "foo": {} } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "findAndModify": "coll0", "query": { "_id": 1 }, "update": [ { "$set": { "foo": { "$setField": { "field": { "$literal": "$a" }, "value": 1, "input": "$foo" } } } } ], "new": { "$$unsetOrMatches": false } } } } ] } ], "outcome": [ { "collectionName": "coll0", "databaseName": "crud-tests", "documents": [ { "_id": 1, "foo": { "$a": 1 } } ] } ] }, { "description": "Updating document to set dotted key in embedded doc on 5.0+ server", "runOnRequirements": [ { "minServerVersion": "5.0" } ], "operations": [ { "name": "findOneAndUpdate", "object": "collection0", "arguments": { "filter": { "_id": 1 }, "update": [ { "$set": { "foo": { "$setField": { "field": { "$literal": "a.b" }, "value": 1, "input": "$foo" } } } } ] }, "expectResult": { "_id": 1, "foo": {} } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "findAndModify": "coll0", "query": { "_id": 1 }, "update": [ { "$set": { "foo": { "$setField": { "field": { "$literal": "a.b" }, "value": 1, "input": "$foo" } } } } ], "new": { "$$unsetOrMatches": false } } } } ] } ], "outcome": [ { "collectionName": "coll0", "databaseName": "crud-tests", "documents": [ { "_id": 1, "foo": { "a.b": 1 } } ] } ] } ] } mongodb-mongo-python-driver-509e9b7/test/crud/unified/findOneAndUpdate-errorResponse.json000066400000000000000000000052501462766011000317070ustar00rootroot00000000000000{ "description": "findOneAndUpdate-errorResponse", "schemaVersion": "1.12", "createEntities": [ { "client": { "id": "client0" } }, { "database": { "id": "database0", "client": "client0", "databaseName": "crud-tests" } }, { "collection": { "id": "collection0", "database": "database0", "collectionName": "test" } } ], "initialData": [ { "collectionName": "test", "databaseName": "crud-tests", "documents": [ { "_id": 1, "x": "foo" } ] } ], "tests": [ { "description": "findOneAndUpdate DuplicateKey error is accessible", "runOnRequirements": [ { "minServerVersion": "4.2" } ], "operations": [ { "name": "createIndex", "object": "collection0", "arguments": { "keys": { "x": 1 }, "unique": true } }, { "name": "findOneAndUpdate", "object": "collection0", "arguments": { "filter": { "_id": 2 }, "update": { "$set": { "x": "foo" } }, "upsert": true }, "expectError": { "errorCode": 11000, "errorResponse": { "keyPattern": { "x": 1 }, "keyValue": { "x": "foo" } } } } ] }, { "description": "findOneAndUpdate document validation errInfo is accessible", "runOnRequirements": [ { "minServerVersion": "5.0" } ], "operations": [ { "name": "modifyCollection", "object": "database0", "arguments": { "collection": "test", "validator": { "x": { "$type": "string" } } } }, { "name": "findOneAndUpdate", "object": "collection0", "arguments": { "filter": { "_id": 1 }, "update": { "$set": { "x": 1 } } }, "expectError": { "errorCode": 121, "errorResponse": { "errInfo": { "failingDocumentId": 1, "details": { "$$type": "object" } } } } } ] } ] } mongodb-mongo-python-driver-509e9b7/test/crud/unified/findOneAndUpdate-hint-clientError.json000066400000000000000000000054121462766011000322670ustar00rootroot00000000000000{ "description": "findOneAndUpdate-hint-clientError", "schemaVersion": "1.0", "runOnRequirements": [ { "maxServerVersion": "4.0.99" } ], "createEntities": [ { "client": { "id": "client0", "observeEvents": [ "commandStartedEvent" ] } }, { "database": { "id": "database0", "client": "client0", "databaseName": "crud-v2" } }, { "collection": { "id": "collection0", "database": "database0", "collectionName": "findOneAndUpdate_hint" } } ], "initialData": [ { "collectionName": "findOneAndUpdate_hint", "databaseName": "crud-v2", "documents": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 22 } ] } ], "tests": [ { "description": "FindOneAndUpdate with hint string unsupported (client-side error)", "operations": [ { "object": "collection0", "name": "findOneAndUpdate", "arguments": { "filter": { "_id": 1 }, "update": { "$inc": { "x": 1 } }, "hint": "_id_" }, "expectError": { "isError": true } } ], "expectEvents": [ { "client": "client0", "events": [] } ], "outcome": [ { "collectionName": "findOneAndUpdate_hint", "databaseName": "crud-v2", "documents": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 22 } ] } ] }, { "description": "FindOneAndUpdate with hint document unsupported (client-side error)", "operations": [ { "object": "collection0", "name": "findOneAndUpdate", "arguments": { "filter": { "_id": 1 }, "update": { "$inc": { "x": 1 } }, "hint": { "_id": 1 } }, "expectError": { "isError": true } } ], "expectEvents": [ { "client": "client0", "events": [] } ], "outcome": [ { "collectionName": "findOneAndUpdate_hint", "databaseName": "crud-v2", "documents": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 22 } ] } ] } ] } mongodb-mongo-python-driver-509e9b7/test/crud/unified/findOneAndUpdate-hint-serverError.json000066400000000000000000000073221462766011000323210ustar00rootroot00000000000000{ "description": "findOneAndUpdate-hint-serverError", "schemaVersion": "1.0", "runOnRequirements": [ { "minServerVersion": "4.2.0", "maxServerVersion": "4.3.0" } ], "createEntities": [ { "client": { "id": "client0", "observeEvents": [ "commandStartedEvent" ] } }, { "database": { "id": "database0", "client": "client0", "databaseName": "crud-v2" } }, { "collection": { "id": "collection0", "database": "database0", "collectionName": "findOneAndUpdate_hint" } } ], "initialData": [ { "collectionName": "findOneAndUpdate_hint", "databaseName": "crud-v2", "documents": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 22 } ] } ], "tests": [ { "description": "FindOneAndUpdate with hint string unsupported (server-side error)", "operations": [ { "object": "collection0", "name": "findOneAndUpdate", "arguments": { "filter": { "_id": 1 }, "update": { "$inc": { "x": 1 } }, "hint": "_id_" }, "expectError": { "isError": true } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "findAndModify": "findOneAndUpdate_hint", "query": { "_id": 1 }, "update": { "$inc": { "x": 1 } }, "hint": "_id_" } } } ] } ], "outcome": [ { "collectionName": "findOneAndUpdate_hint", "databaseName": "crud-v2", "documents": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 22 } ] } ] }, { "description": "FindOneAndUpdate with hint document unsupported (server-side error)", "operations": [ { "object": "collection0", "name": "findOneAndUpdate", "arguments": { "filter": { "_id": 1 }, "update": { "$inc": { "x": 1 } }, "hint": { "_id": 1 } }, "expectError": { "isError": true } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "findAndModify": "findOneAndUpdate_hint", "query": { "_id": 1 }, "update": { "$inc": { "x": 1 } }, "hint": { "_id": 1 } } } } ] } ], "outcome": [ { "collectionName": "findOneAndUpdate_hint", "databaseName": "crud-v2", "documents": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 22 } ] } ] } ] } mongodb-mongo-python-driver-509e9b7/test/crud/unified/findOneAndUpdate-hint-unacknowledged.json000066400000000000000000000125631462766011000327760ustar00rootroot00000000000000{ "description": "findOneAndUpdate-hint-unacknowledged", "schemaVersion": "1.0", "createEntities": [ { "client": { "id": "client0", "observeEvents": [ "commandStartedEvent" ] } }, { "database": { "id": "database0", "client": "client0", "databaseName": "db0" } }, { "collection": { "id": "collection0", "database": "database0", "collectionName": "coll0", "collectionOptions": { "writeConcern": { "w": 0 } } } } ], "initialData": [ { "collectionName": "coll0", "databaseName": "db0", "documents": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 22 } ] } ], "tests": [ { "description": "Unacknowledged findOneAndUpdate with hint string fails with client-side error on pre-4.4 server", "runOnRequirements": [ { "maxServerVersion": "4.2.99" } ], "operations": [ { "object": "collection0", "name": "findOneAndUpdate", "arguments": { "filter": { "_id": { "$gt": 1 } }, "update": { "$inc": { "x": 1 } }, "hint": "_id_" }, "expectError": { "isClientError": true } } ], "expectEvents": [ { "client": "client0", "events": [] } ] }, { "description": "Unacknowledged findOneAndUpdate with hint document fails with client-side error on pre-4.4 server", "runOnRequirements": [ { "maxServerVersion": "4.2.99" } ], "operations": [ { "object": "collection0", "name": "findOneAndUpdate", "arguments": { "filter": { "_id": { "$gt": 1 } }, "update": { "$inc": { "x": 1 } }, "hint": { "_id": 1 } }, "expectError": { "isClientError": true } } ], "expectEvents": [ { "client": "client0", "events": [] } ] }, { "description": "Unacknowledged findOneAndUpdate with hint string on 4.4+ server", "runOnRequirements": [ { "minServerVersion": "4.4.0" } ], "operations": [ { "object": "collection0", "name": "findOneAndUpdate", "arguments": { "filter": { "_id": { "$gt": 1 } }, "update": { "$inc": { "x": 1 } }, "hint": "_id_" }, "expectResult": { "$$unsetOrMatches": null } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "findAndModify": "coll0", "query": { "_id": { "$gt": 1 } }, "update": { "$inc": { "x": 1 } }, "hint": { "$$type": [ "string", "object" ] }, "writeConcern": { "w": 0 } } } } ] } ] }, { "description": "Unacknowledged findOneAndUpdate with hint document on 4.4+ server", "runOnRequirements": [ { "minServerVersion": "4.4.0" } ], "operations": [ { "object": "collection0", "name": "findOneAndUpdate", "arguments": { "filter": { "_id": { "$gt": 1 } }, "update": { "$inc": { "x": 1 } }, "hint": { "_id": 1 } }, "expectResult": { "$$unsetOrMatches": null } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "findAndModify": "coll0", "query": { "_id": { "$gt": 1 } }, "update": { "$inc": { "x": 1 } }, "hint": { "$$type": [ "string", "object" ] }, "writeConcern": { "w": 0 } } } } ] } ] } ] } mongodb-mongo-python-driver-509e9b7/test/crud/unified/findOneAndUpdate-hint.json000066400000000000000000000072011462766011000277770ustar00rootroot00000000000000{ "description": "findOneAndUpdate-hint", "schemaVersion": "1.0", "runOnRequirements": [ { "minServerVersion": "4.3.1" } ], "createEntities": [ { "client": { "id": "client0", "observeEvents": [ "commandStartedEvent" ] } }, { "database": { "id": "database0", "client": "client0", "databaseName": "crud-v2" } }, { "collection": { "id": "collection0", "database": "database0", "collectionName": "findOneAndUpdate_hint" } } ], "initialData": [ { "collectionName": "findOneAndUpdate_hint", "databaseName": "crud-v2", "documents": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 22 } ] } ], "tests": [ { "description": "FindOneAndUpdate with hint string", "operations": [ { "object": "collection0", "name": "findOneAndUpdate", "arguments": { "filter": { "_id": 1 }, "update": { "$inc": { "x": 1 } }, "hint": "_id_" }, "expectResult": { "_id": 1, "x": 11 } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "findAndModify": "findOneAndUpdate_hint", "query": { "_id": 1 }, "update": { "$inc": { "x": 1 } }, "hint": "_id_" } } } ] } ], "outcome": [ { "collectionName": "findOneAndUpdate_hint", "databaseName": "crud-v2", "documents": [ { "_id": 1, "x": 12 }, { "_id": 2, "x": 22 } ] } ] }, { "description": "FindOneAndUpdate with hint document", "operations": [ { "object": "collection0", "name": "findOneAndUpdate", "arguments": { "filter": { "_id": 1 }, "update": { "$inc": { "x": 1 } }, "hint": { "_id": 1 } }, "expectResult": { "_id": 1, "x": 11 } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "findAndModify": "findOneAndUpdate_hint", "query": { "_id": 1 }, "update": { "$inc": { "x": 1 } }, "hint": { "_id": 1 } } } } ] } ], "outcome": [ { "collectionName": "findOneAndUpdate_hint", "databaseName": "crud-v2", "documents": [ { "_id": 1, "x": 12 }, { "_id": 2, "x": 22 } ] } ] } ] } mongodb-mongo-python-driver-509e9b7/test/crud/unified/findOneAndUpdate-let.json000066400000000000000000000110211462766011000276140ustar00rootroot00000000000000{ "description": "findOneAndUpdate-let", "schemaVersion": "1.0", "createEntities": [ { "client": { "id": "client0", "observeEvents": [ "commandStartedEvent" ] } }, { "database": { "id": "database0", "client": "client0", "databaseName": "crud-tests" } }, { "collection": { "id": "collection0", "database": "database0", "collectionName": "coll0" } } ], "initialData": [ { "collectionName": "coll0", "databaseName": "crud-tests", "documents": [ { "_id": 1 }, { "_id": 2 } ] } ], "tests": [ { "description": "findOneAndUpdate with let option", "runOnRequirements": [ { "minServerVersion": "5.0" } ], "operations": [ { "name": "findOneAndUpdate", "object": "collection0", "arguments": { "filter": { "$expr": { "$eq": [ "$_id", "$$id" ] } }, "update": [ { "$set": { "x": "$$x" } } ], "let": { "id": 1, "x": "foo" } }, "expectResult": { "_id": 1 } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "findAndModify": "coll0", "query": { "$expr": { "$eq": [ "$_id", "$$id" ] } }, "update": [ { "$set": { "x": "$$x" } } ], "let": { "id": 1, "x": "foo" } } } } ] } ], "outcome": [ { "collectionName": "coll0", "databaseName": "crud-tests", "documents": [ { "_id": 1, "x": "foo" }, { "_id": 2 } ] } ] }, { "description": "findOneAndUpdate with let option unsupported (server-side error)", "runOnRequirements": [ { "minServerVersion": "4.2.0", "maxServerVersion": "4.4.99" } ], "operations": [ { "name": "findOneAndUpdate", "object": "collection0", "arguments": { "filter": { "$expr": { "$eq": [ "$_id", "$$id" ] } }, "update": [ { "$set": { "x": "$$x" } } ], "let": { "id": 1, "x": "foo" } }, "expectError": { "errorContains": "field 'let' is an unknown field", "isClientError": false } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "findAndModify": "coll0", "query": { "$expr": { "$eq": [ "$_id", "$$id" ] } }, "update": [ { "$set": { "x": "$$x" } } ], "let": { "id": 1, "x": "foo" } } } } ] } ], "outcome": [ { "collectionName": "coll0", "databaseName": "crud-tests", "documents": [ { "_id": 1 }, { "_id": 2 } ] } ] } ] } mongodb-mongo-python-driver-509e9b7/test/crud/unified/insertMany-comment.json000066400000000000000000000110421462766011000274560ustar00rootroot00000000000000{ "description": "insertMany-comment", "schemaVersion": "1.0", "createEntities": [ { "client": { "id": "client0", "observeEvents": [ "commandStartedEvent" ] } }, { "database": { "id": "database0", "client": "client0", "databaseName": "crud-tests" } }, { "collection": { "id": "collection0", "database": "database0", "collectionName": "coll0" } } ], "initialData": [ { "collectionName": "coll0", "databaseName": "crud-tests", "documents": [ { "_id": 1, "x": 11 } ] } ], "tests": [ { "description": "insertMany with string comment", "runOnRequirements": [ { "minServerVersion": "4.4" } ], "operations": [ { "name": "insertMany", "object": "collection0", "arguments": { "documents": [ { "_id": 2, "x": 22 } ], "comment": "comment" } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "insert": "coll0", "documents": [ { "_id": 2, "x": 22 } ], "comment": "comment" } } } ] } ], "outcome": [ { "collectionName": "coll0", "databaseName": "crud-tests", "documents": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 22 } ] } ] }, { "description": "insertMany with document comment", "runOnRequirements": [ { "minServerVersion": "4.4" } ], "operations": [ { "name": "insertMany", "object": "collection0", "arguments": { "documents": [ { "_id": 2, "x": 22 } ], "comment": { "key": "value" } } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "insert": "coll0", "documents": [ { "_id": 2, "x": 22 } ], "comment": { "key": "value" } } } } ] } ], "outcome": [ { "collectionName": "coll0", "databaseName": "crud-tests", "documents": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 22 } ] } ] }, { "description": "insertMany with comment - pre 4.4", "runOnRequirements": [ { "minServerVersion": "3.4.0", "maxServerVersion": "4.2.99" } ], "operations": [ { "name": "insertMany", "object": "collection0", "arguments": { "documents": [ { "_id": 2, "x": 22 } ], "comment": "comment" }, "expectError": { "isClientError": false } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "insert": "coll0", "documents": [ { "_id": 2, "x": 22 } ], "comment": "comment" } } } ] } ], "outcome": [ { "collectionName": "coll0", "databaseName": "crud-tests", "documents": [ { "_id": 1, "x": 11 } ] } ] } ] } mongodb-mongo-python-driver-509e9b7/test/crud/unified/insertMany-dots_and_dollars.json000066400000000000000000000161501462766011000313340ustar00rootroot00000000000000{ "description": "insertMany-dots_and_dollars", "schemaVersion": "1.0", "createEntities": [ { "client": { "id": "client0", "observeEvents": [ "commandStartedEvent" ] } }, { "database": { "id": "database0", "client": "client0", "databaseName": "crud-tests" } }, { "collection": { "id": "collection0", "database": "database0", "collectionName": "coll0" } } ], "initialData": [ { "collectionName": "coll0", "databaseName": "crud-tests", "documents": [] } ], "tests": [ { "description": "Inserting document with top-level dollar-prefixed key on 5.0+ server", "runOnRequirements": [ { "minServerVersion": "5.0" } ], "operations": [ { "name": "insertMany", "object": "collection0", "arguments": { "documents": [ { "_id": 1, "$a": 1 } ] }, "expectResult": { "$$unsetOrMatches": { "insertedIds": { "$$unsetOrMatches": { "0": 1 } } } } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "insert": "coll0", "documents": [ { "_id": 1, "$a": 1 } ] } } } ] } ], "outcome": [ { "collectionName": "coll0", "databaseName": "crud-tests", "documents": [ { "_id": 1, "$a": 1 } ] } ] }, { "description": "Inserting document with top-level dollar-prefixed key on pre-5.0 server yields server-side error", "runOnRequirements": [ { "maxServerVersion": "4.99" } ], "operations": [ { "name": "insertMany", "object": "collection0", "arguments": { "documents": [ { "_id": 1, "$a": 1 } ] }, "expectError": { "isClientError": false } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "insert": "coll0", "documents": [ { "_id": 1, "$a": 1 } ] } } } ] } ], "outcome": [ { "collectionName": "coll0", "databaseName": "crud-tests", "documents": [] } ] }, { "description": "Inserting document with top-level dotted key", "operations": [ { "name": "insertMany", "object": "collection0", "arguments": { "documents": [ { "_id": 1, "a.b": 1 } ] }, "expectResult": { "$$unsetOrMatches": { "insertedIds": { "$$unsetOrMatches": { "0": 1 } } } } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "insert": "coll0", "documents": [ { "_id": 1, "a.b": 1 } ] } } } ] } ], "outcome": [ { "collectionName": "coll0", "databaseName": "crud-tests", "documents": [ { "_id": 1, "a.b": 1 } ] } ] }, { "description": "Inserting document with dollar-prefixed key in embedded doc", "operations": [ { "name": "insertMany", "object": "collection0", "arguments": { "documents": [ { "_id": 1, "a": { "$b": 1 } } ] }, "expectResult": { "$$unsetOrMatches": { "insertedIds": { "$$unsetOrMatches": { "0": 1 } } } } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "insert": "coll0", "documents": [ { "_id": 1, "a": { "$b": 1 } } ] } } } ] } ], "outcome": [ { "collectionName": "coll0", "databaseName": "crud-tests", "documents": [ { "_id": 1, "a": { "$b": 1 } } ] } ] }, { "description": "Inserting document with dotted key in embedded doc", "operations": [ { "name": "insertMany", "object": "collection0", "arguments": { "documents": [ { "_id": 1, "a": { "b.c": 1 } } ] }, "expectResult": { "$$unsetOrMatches": { "insertedIds": { "$$unsetOrMatches": { "0": 1 } } } } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "insert": "coll0", "documents": [ { "_id": 1, "a": { "b.c": 1 } } ] } } } ] } ], "outcome": [ { "collectionName": "coll0", "databaseName": "crud-tests", "documents": [ { "_id": 1, "a": { "b.c": 1 } } ] } ] } ] } mongodb-mongo-python-driver-509e9b7/test/crud/unified/insertOne-comment.json000066400000000000000000000106541462766011000273030ustar00rootroot00000000000000{ "description": "insertOne-comment", "schemaVersion": "1.0", "createEntities": [ { "client": { "id": "client0", "observeEvents": [ "commandStartedEvent" ] } }, { "database": { "id": "database0", "client": "client0", "databaseName": "crud-tests" } }, { "collection": { "id": "collection0", "database": "database0", "collectionName": "coll0" } } ], "initialData": [ { "collectionName": "coll0", "databaseName": "crud-tests", "documents": [ { "_id": 1, "x": 11 } ] } ], "tests": [ { "description": "insertOne with string comment", "runOnRequirements": [ { "minServerVersion": "4.4" } ], "operations": [ { "name": "insertOne", "object": "collection0", "arguments": { "document": { "_id": 2, "x": 22 }, "comment": "comment" } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "insert": "coll0", "documents": [ { "_id": 2, "x": 22 } ], "comment": "comment" } } } ] } ], "outcome": [ { "collectionName": "coll0", "databaseName": "crud-tests", "documents": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 22 } ] } ] }, { "description": "insertOne with document comment", "runOnRequirements": [ { "minServerVersion": "4.4" } ], "operations": [ { "name": "insertOne", "object": "collection0", "arguments": { "document": { "_id": 2, "x": 22 }, "comment": { "key": "value" } } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "insert": "coll0", "documents": [ { "_id": 2, "x": 22 } ], "comment": { "key": "value" } } } } ] } ], "outcome": [ { "collectionName": "coll0", "databaseName": "crud-tests", "documents": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 22 } ] } ] }, { "description": "insertOne with comment - pre 4.4", "runOnRequirements": [ { "minServerVersion": "3.4.0", "maxServerVersion": "4.2.99" } ], "operations": [ { "name": "insertOne", "object": "collection0", "arguments": { "document": { "_id": 2, "x": 22 }, "comment": "comment" }, "expectError": { "isClientError": false } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "insert": "coll0", "documents": [ { "_id": 2, "x": 22 } ], "comment": "comment" } } } ] } ], "outcome": [ { "collectionName": "coll0", "databaseName": "crud-tests", "documents": [ { "_id": 1, "x": 11 } ] } ] } ] } mongodb-mongo-python-driver-509e9b7/test/crud/unified/insertOne-dots_and_dollars.json000066400000000000000000000322111462766011000311450ustar00rootroot00000000000000{ "description": "insertOne-dots_and_dollars", "schemaVersion": "1.0", "createEntities": [ { "client": { "id": "client0", "observeEvents": [ "commandStartedEvent" ] } }, { "database": { "id": "database0", "client": "client0", "databaseName": "crud-tests" } }, { "collection": { "id": "collection0", "database": "database0", "collectionName": "coll0" } }, { "collection": { "id": "collection1", "database": "database0", "collectionName": "coll1", "collectionOptions": { "writeConcern": { "w": 0 } } } } ], "initialData": [ { "collectionName": "coll0", "databaseName": "crud-tests", "documents": [] } ], "tests": [ { "description": "Inserting document with top-level dollar-prefixed key on 5.0+ server", "runOnRequirements": [ { "minServerVersion": "5.0" } ], "operations": [ { "name": "insertOne", "object": "collection0", "arguments": { "document": { "_id": 1, "$a": 1 } }, "expectResult": { "$$unsetOrMatches": { "insertedId": { "$$unsetOrMatches": 1 } } } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "insert": "coll0", "documents": [ { "_id": 1, "$a": 1 } ] } } } ] } ], "outcome": [ { "collectionName": "coll0", "databaseName": "crud-tests", "documents": [ { "_id": 1, "$a": 1 } ] } ] }, { "description": "Inserting document with top-level dollar-prefixed key on pre-5.0 server yields server-side error", "runOnRequirements": [ { "maxServerVersion": "4.99" } ], "operations": [ { "name": "insertOne", "object": "collection0", "arguments": { "document": { "_id": 1, "$a": 1 } }, "expectError": { "isClientError": false } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "insert": "coll0", "documents": [ { "_id": 1, "$a": 1 } ] } } } ] } ], "outcome": [ { "collectionName": "coll0", "databaseName": "crud-tests", "documents": [] } ] }, { "description": "Inserting document with top-level dotted key", "operations": [ { "name": "insertOne", "object": "collection0", "arguments": { "document": { "_id": 1, "a.b": 1 } }, "expectResult": { "$$unsetOrMatches": { "insertedId": { "$$unsetOrMatches": 1 } } } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "insert": "coll0", "documents": [ { "_id": 1, "a.b": 1 } ] } } } ] } ], "outcome": [ { "collectionName": "coll0", "databaseName": "crud-tests", "documents": [ { "_id": 1, "a.b": 1 } ] } ] }, { "description": "Inserting document with dollar-prefixed key in embedded doc", "operations": [ { "name": "insertOne", "object": "collection0", "arguments": { "document": { "_id": 1, "a": { "$b": 1 } } }, "expectResult": { "$$unsetOrMatches": { "insertedId": { "$$unsetOrMatches": 1 } } } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "insert": "coll0", "documents": [ { "_id": 1, "a": { "$b": 1 } } ] } } } ] } ], "outcome": [ { "collectionName": "coll0", "databaseName": "crud-tests", "documents": [ { "_id": 1, "a": { "$b": 1 } } ] } ] }, { "description": "Inserting document with dotted key in embedded doc", "operations": [ { "name": "insertOne", "object": "collection0", "arguments": { "document": { "_id": 1, "a": { "b.c": 1 } } }, "expectResult": { "$$unsetOrMatches": { "insertedId": { "$$unsetOrMatches": 1 } } } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "insert": "coll0", "documents": [ { "_id": 1, "a": { "b.c": 1 } } ] } } } ] } ], "outcome": [ { "collectionName": "coll0", "databaseName": "crud-tests", "documents": [ { "_id": 1, "a": { "b.c": 1 } } ] } ] }, { "description": "Inserting document with dollar-prefixed key in _id yields server-side error", "operations": [ { "name": "insertOne", "object": "collection0", "arguments": { "document": { "_id": { "$a": 1 } } }, "expectError": { "isClientError": false } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "insert": "coll0", "documents": [ { "_id": { "$a": 1 } } ] } } } ] } ], "outcome": [ { "collectionName": "coll0", "databaseName": "crud-tests", "documents": [] } ] }, { "description": "Inserting document with dotted key in _id on 3.6+ server", "runOnRequirements": [ { "minServerVersion": "3.6" } ], "operations": [ { "name": "insertOne", "object": "collection0", "arguments": { "document": { "_id": { "a.b": 1 } } }, "expectResult": { "$$unsetOrMatches": { "insertedId": { "$$unsetOrMatches": { "a.b": 1 } } } } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "insert": "coll0", "documents": [ { "_id": { "a.b": 1 } } ] } } } ] } ], "outcome": [ { "collectionName": "coll0", "databaseName": "crud-tests", "documents": [ { "_id": { "a.b": 1 } } ] } ] }, { "description": "Inserting document with dotted key in _id on pre-3.6 server yields server-side error", "runOnRequirements": [ { "maxServerVersion": "3.4.99" } ], "operations": [ { "name": "insertOne", "object": "collection0", "arguments": { "document": { "_id": { "a.b": 1 } } }, "expectError": { "isClientError": false } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "insert": "coll0", "documents": [ { "_id": { "a.b": 1 } } ] } } } ] } ], "outcome": [ { "collectionName": "coll0", "databaseName": "crud-tests", "documents": [] } ] }, { "description": "Inserting document with DBRef-like keys", "operations": [ { "name": "insertOne", "object": "collection0", "arguments": { "document": { "_id": 1, "a": { "$db": "foo" } } }, "expectResult": { "$$unsetOrMatches": { "insertedId": { "$$unsetOrMatches": 1 } } } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "insert": "coll0", "documents": [ { "_id": 1, "a": { "$db": "foo" } } ] } } } ] } ], "outcome": [ { "collectionName": "coll0", "databaseName": "crud-tests", "documents": [ { "_id": 1, "a": { "$db": "foo" } } ] } ] }, { "description": "Unacknowledged write using dollar-prefixed or dotted keys may be silently rejected on pre-5.0 server", "runOnRequirements": [ { "maxServerVersion": "4.99" } ], "operations": [ { "name": "insertOne", "object": "collection1", "arguments": { "document": { "_id": { "$a": 1 } } }, "expectResult": { "$$unsetOrMatches": { "acknowledged": { "$$unsetOrMatches": false } } } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "insert": "coll1", "documents": [ { "_id": { "$a": 1 } } ], "writeConcern": { "w": 0 } } } } ] } ], "outcome": [ { "collectionName": "coll0", "databaseName": "crud-tests", "documents": [] } ] } ] } mongodb-mongo-python-driver-509e9b7/test/crud/unified/insertOne-errorResponse.json000066400000000000000000000032441462766011000305060ustar00rootroot00000000000000{ "description": "insertOne-errorResponse", "schemaVersion": "1.12", "createEntities": [ { "client": { "id": "client0", "useMultipleMongoses": false } }, { "database": { "id": "database0", "client": "client0", "databaseName": "crud-tests" } }, { "collection": { "id": "collection0", "database": "database0", "collectionName": "test" } } ], "tests": [ { "description": "insert operations support errorResponse assertions", "runOnRequirements": [ { "minServerVersion": "4.0.0", "topologies": [ "single", "replicaset" ] }, { "minServerVersion": "4.2.0", "topologies": [ "sharded" ] } ], "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "client0", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "insert" ], "errorCode": 8 } } } }, { "name": "insertOne", "object": "collection0", "arguments": { "document": { "_id": 1 } }, "expectError": { "errorCode": 8, "errorResponse": { "code": 8 } } } ] } ] } mongodb-mongo-python-driver-509e9b7/test/crud/unified/replaceOne-comment.json000066400000000000000000000125471462766011000274150ustar00rootroot00000000000000{ "description": "replaceOne-comment", "schemaVersion": "1.0", "createEntities": [ { "client": { "id": "client0", "observeEvents": [ "commandStartedEvent" ] } }, { "database": { "id": "database0", "client": "client0", "databaseName": "crud-tests" } }, { "collection": { "id": "collection0", "database": "database0", "collectionName": "coll0" } } ], "initialData": [ { "collectionName": "coll0", "databaseName": "crud-tests", "documents": [ { "_id": 1, "x": 11 } ] } ], "tests": [ { "description": "ReplaceOne with string comment", "runOnRequirements": [ { "minServerVersion": "4.4" } ], "operations": [ { "name": "replaceOne", "object": "collection0", "arguments": { "filter": { "_id": 1 }, "replacement": { "x": 22 }, "comment": "comment" } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "update": "coll0", "updates": [ { "q": { "_id": 1 }, "u": { "x": 22 }, "multi": { "$$unsetOrMatches": false }, "upsert": { "$$unsetOrMatches": false } } ], "comment": "comment" } } } ] } ], "outcome": [ { "collectionName": "coll0", "databaseName": "crud-tests", "documents": [ { "_id": 1, "x": 22 } ] } ] }, { "description": "ReplaceOne with document comment", "runOnRequirements": [ { "minServerVersion": "4.4" } ], "operations": [ { "name": "replaceOne", "object": "collection0", "arguments": { "filter": { "_id": 1 }, "replacement": { "x": 22 }, "comment": { "key": "value" } } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "update": "coll0", "updates": [ { "q": { "_id": 1 }, "u": { "x": 22 }, "multi": { "$$unsetOrMatches": false }, "upsert": { "$$unsetOrMatches": false } } ], "comment": { "key": "value" } } } } ] } ], "outcome": [ { "collectionName": "coll0", "databaseName": "crud-tests", "documents": [ { "_id": 1, "x": 22 } ] } ] }, { "description": "ReplaceOne with comment - pre 4.4", "runOnRequirements": [ { "minServerVersion": "3.4.0", "maxServerVersion": "4.2.99" } ], "operations": [ { "name": "replaceOne", "object": "collection0", "arguments": { "filter": { "_id": 1 }, "replacement": { "x": 22 }, "comment": "comment" }, "expectError": { "isClientError": false } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "update": "coll0", "updates": [ { "q": { "_id": 1 }, "u": { "x": 22 }, "multi": { "$$unsetOrMatches": false }, "upsert": { "$$unsetOrMatches": false } } ], "comment": "comment" } } } ] } ], "outcome": [ { "collectionName": "coll0", "databaseName": "crud-tests", "documents": [ { "_id": 1, "x": 11 } ] } ] } ] } mongodb-mongo-python-driver-509e9b7/test/crud/unified/replaceOne-dots_and_dollars.json000066400000000000000000000316001462766011000312550ustar00rootroot00000000000000{ "description": "replaceOne-dots_and_dollars", "schemaVersion": "1.0", "createEntities": [ { "client": { "id": "client0", "observeEvents": [ "commandStartedEvent" ] } }, { "database": { "id": "database0", "client": "client0", "databaseName": "crud-tests" } }, { "collection": { "id": "collection0", "database": "database0", "collectionName": "coll0" } }, { "collection": { "id": "collection1", "database": "database0", "collectionName": "coll1", "collectionOptions": { "writeConcern": { "w": 0 } } } } ], "initialData": [ { "collectionName": "coll0", "databaseName": "crud-tests", "documents": [ { "_id": 1 } ] } ], "tests": [ { "description": "Replacing document with top-level dotted key on 3.6+ server", "runOnRequirements": [ { "minServerVersion": "3.6" } ], "operations": [ { "name": "replaceOne", "object": "collection0", "arguments": { "filter": { "_id": 1 }, "replacement": { "_id": 1, "a.b": 1 } }, "expectResult": { "matchedCount": 1, "modifiedCount": 1, "upsertedCount": 0 } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "update": "coll0", "updates": [ { "q": { "_id": 1 }, "u": { "_id": 1, "a.b": 1 }, "multi": { "$$unsetOrMatches": false }, "upsert": { "$$unsetOrMatches": false } } ] } } } ] } ], "outcome": [ { "collectionName": "coll0", "databaseName": "crud-tests", "documents": [ { "_id": 1, "a.b": 1 } ] } ] }, { "description": "Replacing document with top-level dotted key on pre-3.6 server yields server-side error", "runOnRequirements": [ { "maxServerVersion": "3.4.99" } ], "operations": [ { "name": "replaceOne", "object": "collection0", "arguments": { "filter": { "_id": 1 }, "replacement": { "_id": 1, "a.b": 1 } }, "expectError": { "isClientError": false } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "update": "coll0", "updates": [ { "q": { "_id": 1 }, "u": { "_id": 1, "a.b": 1 }, "multi": { "$$unsetOrMatches": false }, "upsert": { "$$unsetOrMatches": false } } ] } } } ] } ], "outcome": [ { "collectionName": "coll0", "databaseName": "crud-tests", "documents": [ { "_id": 1 } ] } ] }, { "description": "Replacing document with dollar-prefixed key in embedded doc on 5.0+ server", "runOnRequirements": [ { "minServerVersion": "5.0" } ], "operations": [ { "name": "replaceOne", "object": "collection0", "arguments": { "filter": { "_id": 1 }, "replacement": { "_id": 1, "a": { "$b": 1 } } }, "expectResult": { "matchedCount": 1, "modifiedCount": 1, "upsertedCount": 0 } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "update": "coll0", "updates": [ { "q": { "_id": 1 }, "u": { "_id": 1, "a": { "$b": 1 } }, "multi": { "$$unsetOrMatches": false }, "upsert": { "$$unsetOrMatches": false } } ] } } } ] } ], "outcome": [ { "collectionName": "coll0", "databaseName": "crud-tests", "documents": [ { "_id": 1, "a": { "$b": 1 } } ] } ] }, { "description": "Replacing document with dollar-prefixed key in embedded doc on pre-5.0 server yields server-side error", "runOnRequirements": [ { "maxServerVersion": "4.99" } ], "operations": [ { "name": "replaceOne", "object": "collection0", "arguments": { "filter": { "_id": 1 }, "replacement": { "_id": 1, "a": { "$b": 1 } } }, "expectError": { "isClientError": false } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "update": "coll0", "updates": [ { "q": { "_id": 1 }, "u": { "_id": 1, "a": { "$b": 1 } }, "multi": { "$$unsetOrMatches": false }, "upsert": { "$$unsetOrMatches": false } } ] } } } ] } ], "outcome": [ { "collectionName": "coll0", "databaseName": "crud-tests", "documents": [ { "_id": 1 } ] } ] }, { "description": "Replacing document with dotted key in embedded doc on 3.6+ server", "runOnRequirements": [ { "minServerVersion": "3.6" } ], "operations": [ { "name": "replaceOne", "object": "collection0", "arguments": { "filter": { "_id": 1 }, "replacement": { "_id": 1, "a": { "b.c": 1 } } }, "expectResult": { "matchedCount": 1, "modifiedCount": 1, "upsertedCount": 0 } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "update": "coll0", "updates": [ { "q": { "_id": 1 }, "u": { "_id": 1, "a": { "b.c": 1 } }, "multi": { "$$unsetOrMatches": false }, "upsert": { "$$unsetOrMatches": false } } ] } } } ] } ], "outcome": [ { "collectionName": "coll0", "databaseName": "crud-tests", "documents": [ { "_id": 1, "a": { "b.c": 1 } } ] } ] }, { "description": "Replacing document with dotted key in embedded doc on pre-3.6 server yields server-side error", "runOnRequirements": [ { "maxServerVersion": "3.4.99" } ], "operations": [ { "name": "replaceOne", "object": "collection0", "arguments": { "filter": { "_id": 1 }, "replacement": { "_id": 1, "a": { "b.c": 1 } } }, "expectError": { "isClientError": false } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "update": "coll0", "updates": [ { "q": { "_id": 1 }, "u": { "_id": 1, "a": { "b.c": 1 } }, "multi": { "$$unsetOrMatches": false }, "upsert": { "$$unsetOrMatches": false } } ] } } } ] } ], "outcome": [ { "collectionName": "coll0", "databaseName": "crud-tests", "documents": [ { "_id": 1 } ] } ] }, { "description": "Unacknowledged write using dollar-prefixed or dotted keys may be silently rejected on pre-5.0 server", "runOnRequirements": [ { "maxServerVersion": "4.99" } ], "operations": [ { "name": "replaceOne", "object": "collection1", "arguments": { "filter": { "_id": 1 }, "replacement": { "_id": 1, "a": { "$b": 1 } } }, "expectResult": { "acknowledged": { "$$unsetOrMatches": false } } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "update": "coll1", "updates": [ { "q": { "_id": 1 }, "u": { "_id": 1, "a": { "$b": 1 } }, "multi": { "$$unsetOrMatches": false }, "upsert": { "$$unsetOrMatches": false } } ], "writeConcern": { "w": 0 } } } } ] } ], "outcome": [ { "collectionName": "coll0", "databaseName": "crud-tests", "documents": [ { "_id": 1 } ] } ] } ] } mongodb-mongo-python-driver-509e9b7/test/crud/unified/replaceOne-hint-unacknowledged.json000066400000000000000000000137231462766011000317020ustar00rootroot00000000000000{ "description": "replaceOne-hint-unacknowledged", "schemaVersion": "1.0", "createEntities": [ { "client": { "id": "client0", "observeEvents": [ "commandStartedEvent" ] } }, { "database": { "id": "database0", "client": "client0", "databaseName": "db0" } }, { "collection": { "id": "collection0", "database": "database0", "collectionName": "coll0", "collectionOptions": { "writeConcern": { "w": 0 } } } } ], "initialData": [ { "collectionName": "coll0", "databaseName": "db0", "documents": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 22 } ] } ], "tests": [ { "description": "Unacknowledged replaceOne with hint string fails with client-side error on pre-4.2 server", "runOnRequirements": [ { "maxServerVersion": "4.0.99" } ], "operations": [ { "object": "collection0", "name": "replaceOne", "arguments": { "filter": { "_id": { "$gt": 1 } }, "replacement": { "x": 111 }, "hint": "_id_" }, "expectError": { "isClientError": true } } ], "expectEvents": [ { "client": "client0", "events": [] } ] }, { "description": "Unacknowledged replaceOne with hint document fails with client-side error on pre-4.2 server", "runOnRequirements": [ { "maxServerVersion": "4.0.99" } ], "operations": [ { "object": "collection0", "name": "replaceOne", "arguments": { "filter": { "_id": { "$gt": 1 } }, "replacement": { "x": 111 }, "hint": { "_id": 1 } }, "expectError": { "isClientError": true } } ], "expectEvents": [ { "client": "client0", "events": [] } ] }, { "description": "Unacknowledged replaceOne with hint string on 4.2+ server", "runOnRequirements": [ { "minServerVersion": "4.2.0" } ], "operations": [ { "object": "collection0", "name": "replaceOne", "arguments": { "filter": { "_id": { "$gt": 1 } }, "replacement": { "x": 111 }, "hint": "_id_" }, "expectResult": { "$$unsetOrMatches": { "acknowledged": { "$$unsetOrMatches": false } } } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "update": "coll0", "updates": [ { "q": { "_id": { "$gt": 1 } }, "u": { "x": 111 }, "multi": { "$$unsetOrMatches": false }, "upsert": { "$$unsetOrMatches": false }, "hint": { "$$type": [ "string", "object" ] } } ], "writeConcern": { "w": 0 } } } } ] } ] }, { "description": "Unacknowledged replaceOne with hint document on 4.2+ server", "runOnRequirements": [ { "minServerVersion": "4.2.0" } ], "operations": [ { "object": "collection0", "name": "replaceOne", "arguments": { "filter": { "_id": { "$gt": 1 } }, "replacement": { "x": 111 }, "hint": { "_id": 1 } }, "expectResult": { "$$unsetOrMatches": { "acknowledged": { "$$unsetOrMatches": false } } } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "update": "coll0", "updates": [ { "q": { "_id": { "$gt": 1 } }, "u": { "x": 111 }, "multi": { "$$unsetOrMatches": false }, "upsert": { "$$unsetOrMatches": false }, "hint": { "$$type": [ "string", "object" ] } } ], "writeConcern": { "w": 0 } } } } ] } ] } ] } mongodb-mongo-python-driver-509e9b7/test/crud/unified/replaceOne-hint.json000066400000000000000000000105651462766011000267130ustar00rootroot00000000000000{ "description": "replaceOne-hint", "schemaVersion": "1.0", "runOnRequirements": [ { "minServerVersion": "4.2.0" } ], "createEntities": [ { "client": { "id": "client0", "observeEvents": [ "commandStartedEvent" ] } }, { "database": { "id": "database0", "client": "client0", "databaseName": "crud-v2" } }, { "collection": { "id": "collection0", "database": "database0", "collectionName": "test_replaceone_hint" } } ], "initialData": [ { "collectionName": "test_replaceone_hint", "databaseName": "crud-v2", "documents": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 22 } ] } ], "tests": [ { "description": "ReplaceOne with hint string", "operations": [ { "object": "collection0", "name": "replaceOne", "arguments": { "filter": { "_id": { "$gt": 1 } }, "replacement": { "x": 111 }, "hint": "_id_" }, "expectResult": { "matchedCount": 1, "modifiedCount": 1, "upsertedCount": 0 } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "update": "test_replaceone_hint", "updates": [ { "q": { "_id": { "$gt": 1 } }, "u": { "x": 111 }, "hint": "_id_", "multi": { "$$unsetOrMatches": false }, "upsert": { "$$unsetOrMatches": false } } ] } } } ] } ], "outcome": [ { "collectionName": "test_replaceone_hint", "databaseName": "crud-v2", "documents": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 111 } ] } ] }, { "description": "ReplaceOne with hint document", "operations": [ { "object": "collection0", "name": "replaceOne", "arguments": { "filter": { "_id": { "$gt": 1 } }, "replacement": { "x": 111 }, "hint": { "_id": 1 } }, "expectResult": { "matchedCount": 1, "modifiedCount": 1, "upsertedCount": 0 } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "update": "test_replaceone_hint", "updates": [ { "q": { "_id": { "$gt": 1 } }, "u": { "x": 111 }, "hint": { "_id": 1 }, "multi": { "$$unsetOrMatches": false }, "upsert": { "$$unsetOrMatches": false } } ] } } } ] } ], "outcome": [ { "collectionName": "test_replaceone_hint", "databaseName": "crud-v2", "documents": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 111 } ] } ] } ] } mongodb-mongo-python-driver-509e9b7/test/crud/unified/replaceOne-let.json000066400000000000000000000114131462766011000265260ustar00rootroot00000000000000{ "description": "replaceOne-let", "schemaVersion": "1.0", "createEntities": [ { "client": { "id": "client0", "observeEvents": [ "commandStartedEvent" ] } }, { "database": { "id": "database0", "client": "client0", "databaseName": "crud-tests" } }, { "collection": { "id": "collection0", "database": "database0", "collectionName": "coll0" } } ], "initialData": [ { "collectionName": "coll0", "databaseName": "crud-tests", "documents": [ { "_id": 1 }, { "_id": 2 } ] } ], "tests": [ { "description": "ReplaceOne with let option", "runOnRequirements": [ { "minServerVersion": "5.0" } ], "operations": [ { "name": "replaceOne", "object": "collection0", "arguments": { "filter": { "$expr": { "$eq": [ "$_id", "$$id" ] } }, "replacement": { "x": "foo" }, "let": { "id": 1 } }, "expectResult": { "matchedCount": 1, "modifiedCount": 1, "upsertedCount": 0 } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "update": "coll0", "updates": [ { "q": { "$expr": { "$eq": [ "$_id", "$$id" ] } }, "u": { "x": "foo" }, "multi": { "$$unsetOrMatches": false }, "upsert": { "$$unsetOrMatches": false } } ], "let": { "id": 1 } } } } ] } ], "outcome": [ { "collectionName": "coll0", "databaseName": "crud-tests", "documents": [ { "_id": 1, "x": "foo" }, { "_id": 2 } ] } ] }, { "description": "ReplaceOne with let option unsupported (server-side error)", "runOnRequirements": [ { "minServerVersion": "3.6.0", "maxServerVersion": "4.4.99" } ], "operations": [ { "name": "replaceOne", "object": "collection0", "arguments": { "filter": { "$expr": { "$eq": [ "$_id", "$$id" ] } }, "replacement": { "x": "foo" }, "let": { "id": 1 } }, "expectError": { "errorContains": "'update.let' is an unknown field", "isClientError": false } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "update": "coll0", "updates": [ { "q": { "$expr": { "$eq": [ "$_id", "$$id" ] } }, "u": { "x": "foo" }, "multi": { "$$unsetOrMatches": false }, "upsert": { "$$unsetOrMatches": false } } ], "let": { "id": 1 } } } } ] } ], "outcome": [ { "collectionName": "coll0", "databaseName": "crud-tests", "documents": [ { "_id": 1 }, { "_id": 2 } ] } ] } ] } mongodb-mongo-python-driver-509e9b7/test/crud/unified/replaceOne-validation.json000066400000000000000000000027671462766011000301100ustar00rootroot00000000000000{ "description": "replaceOne-validation", "schemaVersion": "1.0", "createEntities": [ { "client": { "id": "client0", "observeEvents": [ "commandStartedEvent" ] } }, { "database": { "id": "database0", "client": "client0", "databaseName": "crud-tests" } }, { "collection": { "id": "collection0", "database": "database0", "collectionName": "coll0" } } ], "initialData": [ { "collectionName": "coll0", "databaseName": "crud-tests", "documents": [ { "_id": 1, "x": 11 } ] } ], "tests": [ { "description": "ReplaceOne prohibits atomic modifiers", "operations": [ { "name": "replaceOne", "object": "collection0", "arguments": { "filter": { "_id": 1 }, "replacement": { "$set": { "x": 22 } } }, "expectError": { "isClientError": true } } ], "expectEvents": [ { "client": "client0", "events": [] } ], "outcome": [ { "collectionName": "coll0", "databaseName": "crud-tests", "documents": [ { "_id": 1, "x": 11 } ] } ] } ] } mongodb-mongo-python-driver-509e9b7/test/crud/unified/updateMany-comment.json000066400000000000000000000126731462766011000274470ustar00rootroot00000000000000{ "description": "updateMany-comment", "schemaVersion": "1.0", "createEntities": [ { "client": { "id": "client0", "observeEvents": [ "commandStartedEvent" ] } }, { "database": { "id": "database0", "client": "client0", "databaseName": "crud-tests" } }, { "collection": { "id": "collection0", "database": "database0", "collectionName": "coll0" } } ], "initialData": [ { "collectionName": "coll0", "databaseName": "crud-tests", "documents": [ { "_id": 1, "x": 11 } ] } ], "tests": [ { "description": "UpdateMany with string comment", "runOnRequirements": [ { "minServerVersion": "4.4" } ], "operations": [ { "name": "updateMany", "object": "collection0", "arguments": { "filter": { "_id": 1 }, "update": { "$set": { "x": 22 } }, "comment": "comment" } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "update": "coll0", "updates": [ { "q": { "_id": 1 }, "u": { "$set": { "x": 22 } }, "multi": true, "upsert": { "$$unsetOrMatches": false } } ], "comment": "comment" } } } ] } ], "outcome": [ { "collectionName": "coll0", "databaseName": "crud-tests", "documents": [ { "_id": 1, "x": 22 } ] } ] }, { "description": "UpdateMany with document comment", "runOnRequirements": [ { "minServerVersion": "4.4" } ], "operations": [ { "name": "updateMany", "object": "collection0", "arguments": { "filter": { "_id": 1 }, "update": { "$set": { "x": 22 } }, "comment": { "key": "value" } } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "update": "coll0", "updates": [ { "q": { "_id": 1 }, "u": { "$set": { "x": 22 } }, "multi": true, "upsert": { "$$unsetOrMatches": false } } ], "comment": { "key": "value" } } } } ] } ], "outcome": [ { "collectionName": "coll0", "databaseName": "crud-tests", "documents": [ { "_id": 1, "x": 22 } ] } ] }, { "description": "UpdateMany with comment - pre 4.4", "runOnRequirements": [ { "minServerVersion": "3.4.0", "maxServerVersion": "4.2.99" } ], "operations": [ { "name": "updateMany", "object": "collection0", "arguments": { "filter": { "_id": 1 }, "update": { "$set": { "x": 22 } }, "comment": "comment" }, "expectError": { "isClientError": false } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "update": "coll0", "updates": [ { "q": { "_id": 1 }, "u": { "$set": { "x": 22 } }, "multi": true, "upsert": { "$$unsetOrMatches": false } } ], "comment": "comment" } } } ] } ], "outcome": [ { "collectionName": "coll0", "databaseName": "crud-tests", "documents": [ { "_id": 1, "x": 11 } ] } ] } ] } mongodb-mongo-python-driver-509e9b7/test/crud/unified/updateMany-dots_and_dollars.json000066400000000000000000000232601462766011000313120ustar00rootroot00000000000000{ "description": "updateMany-dots_and_dollars", "schemaVersion": "1.0", "createEntities": [ { "client": { "id": "client0", "observeEvents": [ "commandStartedEvent" ] } }, { "database": { "id": "database0", "client": "client0", "databaseName": "crud-tests" } }, { "collection": { "id": "collection0", "database": "database0", "collectionName": "coll0" } } ], "initialData": [ { "collectionName": "coll0", "databaseName": "crud-tests", "documents": [ { "_id": 1, "foo": {} } ] } ], "tests": [ { "description": "Updating document to set top-level dollar-prefixed key on 5.0+ server", "runOnRequirements": [ { "minServerVersion": "5.0" } ], "operations": [ { "name": "updateMany", "object": "collection0", "arguments": { "filter": { "_id": 1 }, "update": [ { "$replaceWith": { "$setField": { "field": { "$literal": "$a" }, "value": 1, "input": "$$ROOT" } } } ] }, "expectResult": { "matchedCount": 1, "modifiedCount": 1, "upsertedCount": 0 } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "update": "coll0", "updates": [ { "q": { "_id": 1 }, "u": [ { "$replaceWith": { "$setField": { "field": { "$literal": "$a" }, "value": 1, "input": "$$ROOT" } } } ], "multi": true, "upsert": { "$$unsetOrMatches": false } } ] } } } ] } ], "outcome": [ { "collectionName": "coll0", "databaseName": "crud-tests", "documents": [ { "_id": 1, "foo": {}, "$a": 1 } ] } ] }, { "description": "Updating document to set top-level dotted key on 5.0+ server", "runOnRequirements": [ { "minServerVersion": "5.0" } ], "operations": [ { "name": "updateMany", "object": "collection0", "arguments": { "filter": { "_id": 1 }, "update": [ { "$replaceWith": { "$setField": { "field": { "$literal": "a.b" }, "value": 1, "input": "$$ROOT" } } } ] }, "expectResult": { "matchedCount": 1, "modifiedCount": 1, "upsertedCount": 0 } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "update": "coll0", "updates": [ { "q": { "_id": 1 }, "u": [ { "$replaceWith": { "$setField": { "field": { "$literal": "a.b" }, "value": 1, "input": "$$ROOT" } } } ], "multi": true, "upsert": { "$$unsetOrMatches": false } } ] } } } ] } ], "outcome": [ { "collectionName": "coll0", "databaseName": "crud-tests", "documents": [ { "_id": 1, "foo": {}, "a.b": 1 } ] } ] }, { "description": "Updating document to set dollar-prefixed key in embedded doc on 5.0+ server", "runOnRequirements": [ { "minServerVersion": "5.0" } ], "operations": [ { "name": "updateMany", "object": "collection0", "arguments": { "filter": { "_id": 1 }, "update": [ { "$set": { "foo": { "$setField": { "field": { "$literal": "$a" }, "value": 1, "input": "$foo" } } } } ] }, "expectResult": { "matchedCount": 1, "modifiedCount": 1, "upsertedCount": 0 } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "update": "coll0", "updates": [ { "q": { "_id": 1 }, "u": [ { "$set": { "foo": { "$setField": { "field": { "$literal": "$a" }, "value": 1, "input": "$foo" } } } } ], "multi": true, "upsert": { "$$unsetOrMatches": false } } ] } } } ] } ], "outcome": [ { "collectionName": "coll0", "databaseName": "crud-tests", "documents": [ { "_id": 1, "foo": { "$a": 1 } } ] } ] }, { "description": "Updating document to set dotted key in embedded doc on 5.0+ server", "runOnRequirements": [ { "minServerVersion": "5.0" } ], "operations": [ { "name": "updateMany", "object": "collection0", "arguments": { "filter": { "_id": 1 }, "update": [ { "$set": { "foo": { "$setField": { "field": { "$literal": "a.b" }, "value": 1, "input": "$foo" } } } } ] }, "expectResult": { "matchedCount": 1, "modifiedCount": 1, "upsertedCount": 0 } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "update": "coll0", "updates": [ { "q": { "_id": 1 }, "u": [ { "$set": { "foo": { "$setField": { "field": { "$literal": "a.b" }, "value": 1, "input": "$foo" } } } } ], "multi": true, "upsert": { "$$unsetOrMatches": false } } ] } } } ] } ], "outcome": [ { "collectionName": "coll0", "databaseName": "crud-tests", "documents": [ { "_id": 1, "foo": { "a.b": 1 } } ] } ] } ] } mongodb-mongo-python-driver-509e9b7/test/crud/unified/updateMany-hint-clientError.json000066400000000000000000000060131462766011000312240ustar00rootroot00000000000000{ "description": "updateMany-hint-clientError", "schemaVersion": "1.0", "runOnRequirements": [ { "maxServerVersion": "3.3.99" } ], "createEntities": [ { "client": { "id": "client0", "observeEvents": [ "commandStartedEvent" ] } }, { "database": { "id": "database0", "client": "client0", "databaseName": "crud-v2" } }, { "collection": { "id": "collection0", "database": "database0", "collectionName": "test_updatemany_hint" } } ], "initialData": [ { "collectionName": "test_updatemany_hint", "databaseName": "crud-v2", "documents": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 22 }, { "_id": 3, "x": 33 } ] } ], "tests": [ { "description": "UpdateMany with hint string unsupported (client-side error)", "operations": [ { "object": "collection0", "name": "updateMany", "arguments": { "filter": { "_id": { "$gt": 1 } }, "update": { "$inc": { "x": 1 } }, "hint": "_id_" }, "expectError": { "isError": true } } ], "expectEvents": [ { "client": "client0", "events": [] } ], "outcome": [ { "collectionName": "test_updatemany_hint", "databaseName": "crud-v2", "documents": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 22 }, { "_id": 3, "x": 33 } ] } ] }, { "description": "UpdateMany with hint document unsupported (client-side error)", "operations": [ { "object": "collection0", "name": "updateMany", "arguments": { "filter": { "_id": { "$gt": 1 } }, "update": { "$inc": { "x": 1 } }, "hint": { "_id": 1 } }, "expectError": { "isError": true } } ], "expectEvents": [ { "client": "client0", "events": [] } ], "outcome": [ { "collectionName": "test_updatemany_hint", "databaseName": "crud-v2", "documents": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 22 }, { "_id": 3, "x": 33 } ] } ] } ] } mongodb-mongo-python-driver-509e9b7/test/crud/unified/updateMany-hint-serverError.json000066400000000000000000000111351462766011000312550ustar00rootroot00000000000000{ "description": "updateMany-hint-serverError", "schemaVersion": "1.0", "runOnRequirements": [ { "minServerVersion": "3.4.0", "maxServerVersion": "4.1.9" } ], "createEntities": [ { "client": { "id": "client0", "observeEvents": [ "commandStartedEvent" ] } }, { "database": { "id": "database0", "client": "client0", "databaseName": "crud-v2" } }, { "collection": { "id": "collection0", "database": "database0", "collectionName": "test_updatemany_hint" } } ], "initialData": [ { "collectionName": "test_updatemany_hint", "databaseName": "crud-v2", "documents": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 22 }, { "_id": 3, "x": 33 } ] } ], "tests": [ { "description": "UpdateMany with hint string unsupported (server-side error)", "operations": [ { "object": "collection0", "name": "updateMany", "arguments": { "filter": { "_id": { "$gt": 1 } }, "update": { "$inc": { "x": 1 } }, "hint": "_id_" }, "expectError": { "isError": true } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "update": "test_updatemany_hint", "updates": [ { "q": { "_id": { "$gt": 1 } }, "u": { "$inc": { "x": 1 } }, "multi": true, "hint": "_id_", "upsert": { "$$unsetOrMatches": false } } ] } } } ] } ], "outcome": [ { "collectionName": "test_updatemany_hint", "databaseName": "crud-v2", "documents": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 22 }, { "_id": 3, "x": 33 } ] } ] }, { "description": "UpdateMany with hint document unsupported (server-side error)", "operations": [ { "object": "collection0", "name": "updateMany", "arguments": { "filter": { "_id": { "$gt": 1 } }, "update": { "$inc": { "x": 1 } }, "hint": { "_id": 1 } }, "expectError": { "isError": true } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "update": "test_updatemany_hint", "updates": [ { "q": { "_id": { "$gt": 1 } }, "u": { "$inc": { "x": 1 } }, "multi": true, "hint": { "_id": 1 }, "upsert": { "$$unsetOrMatches": false } } ] } } } ] } ], "outcome": [ { "collectionName": "test_updatemany_hint", "databaseName": "crud-v2", "documents": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 22 }, { "_id": 3, "x": 33 } ] } ] } ] } mongodb-mongo-python-driver-509e9b7/test/crud/unified/updateMany-hint-unacknowledged.json000066400000000000000000000142041462766011000317270ustar00rootroot00000000000000{ "description": "updateMany-hint-unacknowledged", "schemaVersion": "1.0", "createEntities": [ { "client": { "id": "client0", "observeEvents": [ "commandStartedEvent" ] } }, { "database": { "id": "database0", "client": "client0", "databaseName": "db0" } }, { "collection": { "id": "collection0", "database": "database0", "collectionName": "coll0", "collectionOptions": { "writeConcern": { "w": 0 } } } } ], "initialData": [ { "collectionName": "coll0", "databaseName": "db0", "documents": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 22 }, { "_id": 3, "x": 33 } ] } ], "tests": [ { "description": "Unacknowledged updateMany with hint string fails with client-side error on pre-4.2 server", "runOnRequirements": [ { "maxServerVersion": "4.0.99" } ], "operations": [ { "object": "collection0", "name": "updateMany", "arguments": { "filter": { "_id": { "$gt": 1 } }, "update": { "$inc": { "x": 1 } }, "hint": "_id_" }, "expectError": { "isClientError": true } } ], "expectEvents": [ { "client": "client0", "events": [] } ] }, { "description": "Unacknowledged updateMany with hint document fails with client-side error on pre-4.2 server", "runOnRequirements": [ { "maxServerVersion": "4.0.99" } ], "operations": [ { "object": "collection0", "name": "updateMany", "arguments": { "filter": { "_id": { "$gt": 1 } }, "update": { "$inc": { "x": 1 } }, "hint": { "_id": 1 } }, "expectError": { "isClientError": true } } ], "expectEvents": [ { "client": "client0", "events": [] } ] }, { "description": "Unacknowledged updateMany with hint string on 4.2+ server", "runOnRequirements": [ { "minServerVersion": "4.2.0" } ], "operations": [ { "object": "collection0", "name": "updateMany", "arguments": { "filter": { "_id": { "$gt": 1 } }, "update": { "$inc": { "x": 1 } }, "hint": "_id_" }, "expectResult": { "$$unsetOrMatches": { "acknowledged": { "$$unsetOrMatches": false } } } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "update": "coll0", "updates": [ { "q": { "_id": { "$gt": 1 } }, "u": { "$inc": { "x": 1 } }, "multi": true, "upsert": { "$$unsetOrMatches": false }, "hint": { "$$type": [ "string", "object" ] } } ], "writeConcern": { "w": 0 } } } } ] } ] }, { "description": "Unacknowledged updateMany with hint document on 4.2+ server", "runOnRequirements": [ { "minServerVersion": "4.2.0" } ], "operations": [ { "object": "collection0", "name": "updateMany", "arguments": { "filter": { "_id": { "$gt": 1 } }, "update": { "$inc": { "x": 1 } }, "hint": { "_id": 1 } }, "expectResult": { "$$unsetOrMatches": { "acknowledged": { "$$unsetOrMatches": false } } } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "update": "coll0", "updates": [ { "q": { "_id": { "$gt": 1 } }, "u": { "$inc": { "x": 1 } }, "multi": true, "upsert": { "$$unsetOrMatches": false }, "hint": { "$$type": [ "string", "object" ] } } ], "writeConcern": { "w": 0 } } } } ] } ] } ] } mongodb-mongo-python-driver-509e9b7/test/crud/unified/updateMany-hint.json000066400000000000000000000111641462766011000267410ustar00rootroot00000000000000{ "description": "updateMany-hint", "schemaVersion": "1.0", "runOnRequirements": [ { "minServerVersion": "4.2.0" } ], "createEntities": [ { "client": { "id": "client0", "observeEvents": [ "commandStartedEvent" ] } }, { "database": { "id": "database0", "client": "client0", "databaseName": "crud-v2" } }, { "collection": { "id": "collection0", "database": "database0", "collectionName": "test_updatemany_hint" } } ], "initialData": [ { "collectionName": "test_updatemany_hint", "databaseName": "crud-v2", "documents": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 22 }, { "_id": 3, "x": 33 } ] } ], "tests": [ { "description": "UpdateMany with hint string", "operations": [ { "object": "collection0", "name": "updateMany", "arguments": { "filter": { "_id": { "$gt": 1 } }, "update": { "$inc": { "x": 1 } }, "hint": "_id_" }, "expectResult": { "matchedCount": 2, "modifiedCount": 2, "upsertedCount": 0 } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "update": "test_updatemany_hint", "updates": [ { "q": { "_id": { "$gt": 1 } }, "u": { "$inc": { "x": 1 } }, "multi": true, "hint": "_id_", "upsert": { "$$unsetOrMatches": false } } ] } } } ] } ], "outcome": [ { "collectionName": "test_updatemany_hint", "databaseName": "crud-v2", "documents": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 23 }, { "_id": 3, "x": 34 } ] } ] }, { "description": "UpdateMany with hint document", "operations": [ { "object": "collection0", "name": "updateMany", "arguments": { "filter": { "_id": { "$gt": 1 } }, "update": { "$inc": { "x": 1 } }, "hint": { "_id": 1 } }, "expectResult": { "matchedCount": 2, "modifiedCount": 2, "upsertedCount": 0 } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "update": "test_updatemany_hint", "updates": [ { "q": { "_id": { "$gt": 1 } }, "u": { "$inc": { "x": 1 } }, "multi": true, "hint": { "_id": 1 }, "upsert": { "$$unsetOrMatches": false } } ] } } } ] } ], "outcome": [ { "collectionName": "test_updatemany_hint", "databaseName": "crud-v2", "documents": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 23 }, { "_id": 3, "x": 34 } ] } ] } ] } mongodb-mongo-python-driver-509e9b7/test/crud/unified/updateMany-let.json000066400000000000000000000126671462766011000265740ustar00rootroot00000000000000{ "description": "updateMany-let", "schemaVersion": "1.0", "createEntities": [ { "client": { "id": "client0", "observeEvents": [ "commandStartedEvent" ] } }, { "database": { "id": "database0", "client": "client0", "databaseName": "crud-tests" } }, { "collection": { "id": "collection0", "database": "database0", "collectionName": "coll0" } } ], "initialData": [ { "collectionName": "coll0", "databaseName": "crud-tests", "documents": [ { "_id": 1 }, { "_id": 2, "name": "name" }, { "_id": 3, "name": "name" } ] } ], "tests": [ { "description": "updateMany with let option", "runOnRequirements": [ { "minServerVersion": "5.0" } ], "operations": [ { "name": "updateMany", "object": "collection0", "arguments": { "filter": { "$expr": { "$eq": [ "$name", "$$name" ] } }, "update": [ { "$set": { "x": "$$x", "y": "$$y" } } ], "let": { "name": "name", "x": "foo", "y": { "$literal": "bar" } } }, "expectResult": { "matchedCount": 2, "modifiedCount": 2, "upsertedCount": 0 } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "update": "coll0", "updates": [ { "q": { "$expr": { "$eq": [ "$name", "$$name" ] } }, "u": [ { "$set": { "x": "$$x", "y": "$$y" } } ], "multi": true, "upsert": { "$$unsetOrMatches": false } } ], "let": { "name": "name", "x": "foo", "y": { "$literal": "bar" } } } } } ] } ], "outcome": [ { "collectionName": "coll0", "databaseName": "crud-tests", "documents": [ { "_id": 1 }, { "_id": 2, "name": "name", "x": "foo", "y": "bar" }, { "_id": 3, "name": "name", "x": "foo", "y": "bar" } ] } ] }, { "description": "updateMany with let option unsupported (server-side error)", "runOnRequirements": [ { "minServerVersion": "4.2.0", "maxServerVersion": "4.4.99" } ], "operations": [ { "name": "updateMany", "object": "collection0", "arguments": { "filter": { "_id": 1 }, "update": [ { "$set": { "x": "$$x" } } ], "let": { "x": "foo" } }, "expectError": { "errorContains": "'update.let' is an unknown field", "isClientError": false } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "update": "coll0", "updates": [ { "q": { "_id": 1 }, "u": [ { "$set": { "x": "$$x" } } ], "multi": true, "upsert": { "$$unsetOrMatches": false } } ], "let": { "x": "foo" } } } } ] } ], "outcome": [ { "collectionName": "coll0", "databaseName": "crud-tests", "documents": [ { "_id": 1 }, { "_id": 2, "name": "name" }, { "_id": 3, "name": "name" } ] } ] } ] } mongodb-mongo-python-driver-509e9b7/test/crud/unified/updateMany-validation.json000066400000000000000000000033741462766011000301350ustar00rootroot00000000000000{ "description": "updateMany-validation", "schemaVersion": "1.0", "createEntities": [ { "client": { "id": "client0", "observeEvents": [ "commandStartedEvent" ] } }, { "database": { "id": "database0", "client": "client0", "databaseName": "crud-tests" } }, { "collection": { "id": "collection0", "database": "database0", "collectionName": "coll0" } } ], "initialData": [ { "collectionName": "coll0", "databaseName": "crud-tests", "documents": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 22 }, { "_id": 3, "x": 33 } ] } ], "tests": [ { "description": "UpdateMany requires atomic modifiers", "operations": [ { "name": "updateMany", "object": "collection0", "arguments": { "filter": { "_id": { "$gt": 1 } }, "update": { "x": 44 } }, "expectError": { "isClientError": true } } ], "expectEvents": [ { "client": "client0", "events": [] } ], "outcome": [ { "collectionName": "coll0", "databaseName": "crud-tests", "documents": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 22 }, { "_id": 3, "x": 33 } ] } ] } ] } mongodb-mongo-python-driver-509e9b7/test/crud/unified/updateOne-comment.json000066400000000000000000000132111462766011000272510ustar00rootroot00000000000000{ "description": "updateOne-comment", "schemaVersion": "1.0", "createEntities": [ { "client": { "id": "client0", "observeEvents": [ "commandStartedEvent" ] } }, { "database": { "id": "database0", "client": "client0", "databaseName": "crud-tests" } }, { "collection": { "id": "collection0", "database": "database0", "collectionName": "coll0" } } ], "initialData": [ { "collectionName": "coll0", "databaseName": "crud-tests", "documents": [ { "_id": 1, "x": 11 } ] } ], "tests": [ { "description": "UpdateOne with string comment", "runOnRequirements": [ { "minServerVersion": "4.4" } ], "operations": [ { "name": "updateOne", "object": "collection0", "arguments": { "filter": { "_id": 1 }, "update": { "$set": { "x": 22 } }, "comment": "comment" } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "update": "coll0", "updates": [ { "q": { "_id": 1 }, "u": { "$set": { "x": 22 } }, "multi": { "$$unsetOrMatches": false }, "upsert": { "$$unsetOrMatches": false } } ], "comment": "comment" } } } ] } ], "outcome": [ { "collectionName": "coll0", "databaseName": "crud-tests", "documents": [ { "_id": 1, "x": 22 } ] } ] }, { "description": "UpdateOne with document comment", "runOnRequirements": [ { "minServerVersion": "4.4" } ], "operations": [ { "name": "updateOne", "object": "collection0", "arguments": { "filter": { "_id": 1 }, "update": { "$set": { "x": 22 } }, "comment": { "key": "value" } } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "update": "coll0", "updates": [ { "q": { "_id": 1 }, "u": { "$set": { "x": 22 } }, "multi": { "$$unsetOrMatches": false }, "upsert": { "$$unsetOrMatches": false } } ], "comment": { "key": "value" } } } } ] } ], "outcome": [ { "collectionName": "coll0", "databaseName": "crud-tests", "documents": [ { "_id": 1, "x": 22 } ] } ] }, { "description": "UpdateOne with comment - pre 4.4", "runOnRequirements": [ { "minServerVersion": "3.4.0", "maxServerVersion": "4.2.99" } ], "operations": [ { "name": "updateOne", "object": "collection0", "arguments": { "filter": { "_id": 1 }, "update": { "$set": { "x": 22 } }, "comment": "comment" }, "expectError": { "isClientError": false } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "update": "coll0", "updates": [ { "q": { "_id": 1 }, "u": { "$set": { "x": 22 } }, "multi": { "$$unsetOrMatches": false }, "upsert": { "$$unsetOrMatches": false } } ], "comment": "comment" } } } ] } ], "outcome": [ { "collectionName": "coll0", "databaseName": "crud-tests", "documents": [ { "_id": 1, "x": 11 } ] } ] } ] } mongodb-mongo-python-driver-509e9b7/test/crud/unified/updateOne-dots_and_dollars.json000066400000000000000000000237071462766011000311350ustar00rootroot00000000000000{ "description": "updateOne-dots_and_dollars", "schemaVersion": "1.0", "createEntities": [ { "client": { "id": "client0", "observeEvents": [ "commandStartedEvent" ] } }, { "database": { "id": "database0", "client": "client0", "databaseName": "crud-tests" } }, { "collection": { "id": "collection0", "database": "database0", "collectionName": "coll0" } } ], "initialData": [ { "collectionName": "coll0", "databaseName": "crud-tests", "documents": [ { "_id": 1, "foo": {} } ] } ], "tests": [ { "description": "Updating document to set top-level dollar-prefixed key on 5.0+ server", "runOnRequirements": [ { "minServerVersion": "5.0" } ], "operations": [ { "name": "updateOne", "object": "collection0", "arguments": { "filter": { "_id": 1 }, "update": [ { "$replaceWith": { "$setField": { "field": { "$literal": "$a" }, "value": 1, "input": "$$ROOT" } } } ] }, "expectResult": { "matchedCount": 1, "modifiedCount": 1, "upsertedCount": 0 } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "update": "coll0", "updates": [ { "q": { "_id": 1 }, "u": [ { "$replaceWith": { "$setField": { "field": { "$literal": "$a" }, "value": 1, "input": "$$ROOT" } } } ], "multi": { "$$unsetOrMatches": false }, "upsert": { "$$unsetOrMatches": false } } ] } } } ] } ], "outcome": [ { "collectionName": "coll0", "databaseName": "crud-tests", "documents": [ { "_id": 1, "foo": {}, "$a": 1 } ] } ] }, { "description": "Updating document to set top-level dotted key on 5.0+ server", "runOnRequirements": [ { "minServerVersion": "5.0" } ], "operations": [ { "name": "updateOne", "object": "collection0", "arguments": { "filter": { "_id": 1 }, "update": [ { "$replaceWith": { "$setField": { "field": { "$literal": "a.b" }, "value": 1, "input": "$$ROOT" } } } ] }, "expectResult": { "matchedCount": 1, "modifiedCount": 1, "upsertedCount": 0 } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "update": "coll0", "updates": [ { "q": { "_id": 1 }, "u": [ { "$replaceWith": { "$setField": { "field": { "$literal": "a.b" }, "value": 1, "input": "$$ROOT" } } } ], "multi": { "$$unsetOrMatches": false }, "upsert": { "$$unsetOrMatches": false } } ] } } } ] } ], "outcome": [ { "collectionName": "coll0", "databaseName": "crud-tests", "documents": [ { "_id": 1, "foo": {}, "a.b": 1 } ] } ] }, { "description": "Updating document to set dollar-prefixed key in embedded doc on 5.0+ server", "runOnRequirements": [ { "minServerVersion": "5.0" } ], "operations": [ { "name": "updateOne", "object": "collection0", "arguments": { "filter": { "_id": 1 }, "update": [ { "$set": { "foo": { "$setField": { "field": { "$literal": "$a" }, "value": 1, "input": "$foo" } } } } ] }, "expectResult": { "matchedCount": 1, "modifiedCount": 1, "upsertedCount": 0 } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "update": "coll0", "updates": [ { "q": { "_id": 1 }, "u": [ { "$set": { "foo": { "$setField": { "field": { "$literal": "$a" }, "value": 1, "input": "$foo" } } } } ], "multi": { "$$unsetOrMatches": false }, "upsert": { "$$unsetOrMatches": false } } ] } } } ] } ], "outcome": [ { "collectionName": "coll0", "databaseName": "crud-tests", "documents": [ { "_id": 1, "foo": { "$a": 1 } } ] } ] }, { "description": "Updating document to set dotted key in embedded doc on 5.0+ server", "runOnRequirements": [ { "minServerVersion": "5.0" } ], "operations": [ { "name": "updateOne", "object": "collection0", "arguments": { "filter": { "_id": 1 }, "update": [ { "$set": { "foo": { "$setField": { "field": { "$literal": "a.b" }, "value": 1, "input": "$foo" } } } } ] }, "expectResult": { "matchedCount": 1, "modifiedCount": 1, "upsertedCount": 0 } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "update": "coll0", "updates": [ { "q": { "_id": 1 }, "u": [ { "$set": { "foo": { "$setField": { "field": { "$literal": "a.b" }, "value": 1, "input": "$foo" } } } } ], "multi": { "$$unsetOrMatches": false }, "upsert": { "$$unsetOrMatches": false } } ] } } } ] } ], "outcome": [ { "collectionName": "coll0", "databaseName": "crud-tests", "documents": [ { "_id": 1, "foo": { "a.b": 1 } } ] } ] } ] } mongodb-mongo-python-driver-509e9b7/test/crud/unified/updateOne-errorResponse.json000066400000000000000000000034101462766011000304570ustar00rootroot00000000000000{ "description": "updateOne-errorResponse", "schemaVersion": "1.12", "createEntities": [ { "client": { "id": "client0", "useMultipleMongoses": false } }, { "database": { "id": "database0", "client": "client0", "databaseName": "crud-tests" } }, { "collection": { "id": "collection0", "database": "database0", "collectionName": "test" } } ], "tests": [ { "description": "update operations support errorResponse assertions", "runOnRequirements": [ { "minServerVersion": "4.0.0", "topologies": [ "single", "replicaset" ] }, { "minServerVersion": "4.2.0", "topologies": [ "sharded" ] } ], "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "client0", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "update" ], "errorCode": 8 } } } }, { "name": "updateOne", "object": "collection0", "arguments": { "filter": { "_id": 1 }, "update": { "$set": { "x": 1 } } }, "expectError": { "errorCode": 8, "errorResponse": { "code": 8 } } } ] } ] } mongodb-mongo-python-driver-509e9b7/test/crud/unified/updateOne-hint-clientError.json000066400000000000000000000054611462766011000310470ustar00rootroot00000000000000{ "description": "updateOne-hint-clientError", "schemaVersion": "1.0", "runOnRequirements": [ { "maxServerVersion": "3.3.99" } ], "createEntities": [ { "client": { "id": "client0", "observeEvents": [ "commandStartedEvent" ] } }, { "database": { "id": "database0", "client": "client0", "databaseName": "crud-v2" } }, { "collection": { "id": "collection0", "database": "database0", "collectionName": "test_updateone_hint" } } ], "initialData": [ { "collectionName": "test_updateone_hint", "databaseName": "crud-v2", "documents": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 22 } ] } ], "tests": [ { "description": "UpdateOne with hint string unsupported (client-side error)", "operations": [ { "object": "collection0", "name": "updateOne", "arguments": { "filter": { "_id": { "$gt": 1 } }, "update": { "$inc": { "x": 1 } }, "hint": "_id_" }, "expectError": { "isError": true } } ], "expectEvents": [ { "client": "client0", "events": [] } ], "outcome": [ { "collectionName": "test_updateone_hint", "databaseName": "crud-v2", "documents": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 22 } ] } ] }, { "description": "UpdateOne with hint document unsupported (client-side error)", "operations": [ { "object": "collection0", "name": "updateOne", "arguments": { "filter": { "_id": { "$gt": 1 } }, "update": { "$inc": { "x": 1 } }, "hint": { "_id": 1 } }, "expectError": { "isError": true } } ], "expectEvents": [ { "client": "client0", "events": [] } ], "outcome": [ { "collectionName": "test_updateone_hint", "databaseName": "crud-v2", "documents": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 22 } ] } ] } ] } mongodb-mongo-python-driver-509e9b7/test/crud/unified/updateOne-hint-serverError.json000066400000000000000000000110171462766011000310710ustar00rootroot00000000000000{ "description": "updateOne-hint-serverError", "schemaVersion": "1.0", "runOnRequirements": [ { "minServerVersion": "3.4.0", "maxServerVersion": "4.1.9" } ], "createEntities": [ { "client": { "id": "client0", "observeEvents": [ "commandStartedEvent" ] } }, { "database": { "id": "database0", "client": "client0", "databaseName": "crud-v2" } }, { "collection": { "id": "collection0", "database": "database0", "collectionName": "test_updateone_hint" } } ], "initialData": [ { "collectionName": "test_updateone_hint", "databaseName": "crud-v2", "documents": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 22 } ] } ], "tests": [ { "description": "UpdateOne with hint string unsupported (server-side error)", "operations": [ { "object": "collection0", "name": "updateOne", "arguments": { "filter": { "_id": { "$gt": 1 } }, "update": { "$inc": { "x": 1 } }, "hint": "_id_" }, "expectError": { "isError": true } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "update": "test_updateone_hint", "updates": [ { "q": { "_id": { "$gt": 1 } }, "u": { "$inc": { "x": 1 } }, "hint": "_id_", "multi": { "$$unsetOrMatches": false }, "upsert": { "$$unsetOrMatches": false } } ] } } } ] } ], "outcome": [ { "collectionName": "test_updateone_hint", "databaseName": "crud-v2", "documents": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 22 } ] } ] }, { "description": "UpdateOne with hint document unsupported (server-side error)", "operations": [ { "object": "collection0", "name": "updateOne", "arguments": { "filter": { "_id": { "$gt": 1 } }, "update": { "$inc": { "x": 1 } }, "hint": { "_id": 1 } }, "expectError": { "isError": true } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "update": "test_updateone_hint", "updates": [ { "q": { "_id": { "$gt": 1 } }, "u": { "$inc": { "x": 1 } }, "hint": { "_id": 1 }, "multi": { "$$unsetOrMatches": false }, "upsert": { "$$unsetOrMatches": false } } ] } } } ] } ], "outcome": [ { "collectionName": "test_updateone_hint", "databaseName": "crud-v2", "documents": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 22 } ] } ] } ] } mongodb-mongo-python-driver-509e9b7/test/crud/unified/updateOne-hint-unacknowledged.json000066400000000000000000000143161462766011000315500ustar00rootroot00000000000000{ "description": "updateOne-hint-unacknowledged", "schemaVersion": "1.0", "createEntities": [ { "client": { "id": "client0", "observeEvents": [ "commandStartedEvent" ] } }, { "database": { "id": "database0", "client": "client0", "databaseName": "db0" } }, { "collection": { "id": "collection0", "database": "database0", "collectionName": "coll0", "collectionOptions": { "writeConcern": { "w": 0 } } } } ], "initialData": [ { "collectionName": "coll0", "databaseName": "db0", "documents": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 22 } ] } ], "tests": [ { "description": "Unacknowledged updateOne with hint string fails with client-side error on pre-4.2 server", "runOnRequirements": [ { "maxServerVersion": "4.0.99" } ], "operations": [ { "object": "collection0", "name": "updateOne", "arguments": { "filter": { "_id": { "$gt": 1 } }, "update": { "$inc": { "x": 1 } }, "hint": "_id_" }, "expectError": { "isClientError": true } } ], "expectEvents": [ { "client": "client0", "events": [] } ] }, { "description": "Unacknowledged updateOne with hint document fails with client-side error on pre-4.2 server", "runOnRequirements": [ { "maxServerVersion": "4.0.99" } ], "operations": [ { "object": "collection0", "name": "updateOne", "arguments": { "filter": { "_id": { "$gt": 1 } }, "update": { "$inc": { "x": 1 } }, "hint": { "_id": 1 } }, "expectError": { "isClientError": true } } ], "expectEvents": [ { "client": "client0", "events": [] } ] }, { "description": "Unacknowledged updateOne with hint string on 4.2+ server", "runOnRequirements": [ { "minServerVersion": "4.2.0" } ], "operations": [ { "object": "collection0", "name": "updateOne", "arguments": { "filter": { "_id": { "$gt": 1 } }, "update": { "$inc": { "x": 1 } }, "hint": "_id_" }, "expectResult": { "$$unsetOrMatches": { "acknowledged": { "$$unsetOrMatches": false } } } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "update": "coll0", "updates": [ { "q": { "_id": { "$gt": 1 } }, "u": { "$inc": { "x": 1 } }, "multi": { "$$unsetOrMatches": false }, "upsert": { "$$unsetOrMatches": false }, "hint": { "$$type": [ "string", "object" ] } } ], "writeConcern": { "w": 0 } } } } ] } ] }, { "description": "Unacknowledged updateOne with hint document on 4.2+ server", "runOnRequirements": [ { "minServerVersion": "4.2.0" } ], "operations": [ { "object": "collection0", "name": "updateOne", "arguments": { "filter": { "_id": { "$gt": 1 } }, "update": { "$inc": { "x": 1 } }, "hint": { "_id": 1 } }, "expectResult": { "$$unsetOrMatches": { "acknowledged": { "$$unsetOrMatches": false } } } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "update": "coll0", "updates": [ { "q": { "_id": { "$gt": 1 } }, "u": { "$inc": { "x": 1 } }, "multi": { "$$unsetOrMatches": false }, "upsert": { "$$unsetOrMatches": false }, "hint": { "$$type": [ "string", "object" ] } } ], "writeConcern": { "w": 0 } } } } ] } ] } ] } mongodb-mongo-python-driver-509e9b7/test/crud/unified/updateOne-hint.json000066400000000000000000000110461462766011000265550ustar00rootroot00000000000000{ "description": "updateOne-hint", "schemaVersion": "1.0", "runOnRequirements": [ { "minServerVersion": "4.2.0" } ], "createEntities": [ { "client": { "id": "client0", "observeEvents": [ "commandStartedEvent" ] } }, { "database": { "id": "database0", "client": "client0", "databaseName": "crud-v2" } }, { "collection": { "id": "collection0", "database": "database0", "collectionName": "test_updateone_hint" } } ], "initialData": [ { "collectionName": "test_updateone_hint", "databaseName": "crud-v2", "documents": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 22 } ] } ], "tests": [ { "description": "UpdateOne with hint string", "operations": [ { "object": "collection0", "name": "updateOne", "arguments": { "filter": { "_id": { "$gt": 1 } }, "update": { "$inc": { "x": 1 } }, "hint": "_id_" }, "expectResult": { "matchedCount": 1, "modifiedCount": 1, "upsertedCount": 0 } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "update": "test_updateone_hint", "updates": [ { "q": { "_id": { "$gt": 1 } }, "u": { "$inc": { "x": 1 } }, "hint": "_id_", "multi": { "$$unsetOrMatches": false }, "upsert": { "$$unsetOrMatches": false } } ] } } } ] } ], "outcome": [ { "collectionName": "test_updateone_hint", "databaseName": "crud-v2", "documents": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 23 } ] } ] }, { "description": "UpdateOne with hint document", "operations": [ { "object": "collection0", "name": "updateOne", "arguments": { "filter": { "_id": { "$gt": 1 } }, "update": { "$inc": { "x": 1 } }, "hint": { "_id": 1 } }, "expectResult": { "matchedCount": 1, "modifiedCount": 1, "upsertedCount": 0 } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "update": "test_updateone_hint", "updates": [ { "q": { "_id": { "$gt": 1 } }, "u": { "$inc": { "x": 1 } }, "hint": { "_id": 1 }, "multi": { "$$unsetOrMatches": false }, "upsert": { "$$unsetOrMatches": false } } ] } } } ] } ], "outcome": [ { "collectionName": "test_updateone_hint", "databaseName": "crud-v2", "documents": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 23 } ] } ] } ] } mongodb-mongo-python-driver-509e9b7/test/crud/unified/updateOne-let.json000066400000000000000000000116721462766011000264040ustar00rootroot00000000000000{ "description": "updateOne-let", "schemaVersion": "1.0", "createEntities": [ { "client": { "id": "client0", "observeEvents": [ "commandStartedEvent" ] } }, { "database": { "id": "database0", "client": "client0", "databaseName": "crud-tests" } }, { "collection": { "id": "collection0", "database": "database0", "collectionName": "coll0" } } ], "initialData": [ { "collectionName": "coll0", "databaseName": "crud-tests", "documents": [ { "_id": 1 }, { "_id": 2 } ] } ], "tests": [ { "description": "UpdateOne with let option", "runOnRequirements": [ { "minServerVersion": "5.0" } ], "operations": [ { "name": "updateOne", "object": "collection0", "arguments": { "filter": { "$expr": { "$eq": [ "$_id", "$$id" ] } }, "update": [ { "$set": { "x": "$$x" } } ], "let": { "id": 1, "x": "foo" } }, "expectResult": { "matchedCount": 1, "modifiedCount": 1, "upsertedCount": 0 } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "update": "coll0", "updates": [ { "q": { "$expr": { "$eq": [ "$_id", "$$id" ] } }, "u": [ { "$set": { "x": "$$x" } } ], "multi": { "$$unsetOrMatches": false }, "upsert": { "$$unsetOrMatches": false } } ], "let": { "id": 1, "x": "foo" } } } } ] } ], "outcome": [ { "collectionName": "coll0", "databaseName": "crud-tests", "documents": [ { "_id": 1, "x": "foo" }, { "_id": 2 } ] } ] }, { "description": "UpdateOne with let option unsupported (server-side error)", "runOnRequirements": [ { "minServerVersion": "4.2.0", "maxServerVersion": "4.4.99" } ], "operations": [ { "name": "updateOne", "object": "collection0", "arguments": { "filter": { "_id": 1 }, "update": [ { "$set": { "x": "$$x" } } ], "let": { "x": "foo" } }, "expectError": { "errorContains": "'update.let' is an unknown field", "isClientError": false } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "update": "coll0", "updates": [ { "q": { "_id": 1 }, "u": [ { "$set": { "x": "$$x" } } ], "multi": { "$$unsetOrMatches": false }, "upsert": { "$$unsetOrMatches": false } } ], "let": { "x": "foo" } } } } ] } ], "outcome": [ { "collectionName": "coll0", "databaseName": "crud-tests", "documents": [ { "_id": 1 }, { "_id": 2 } ] } ] } ] } mongodb-mongo-python-driver-509e9b7/test/crud/unified/updateOne-validation.json000066400000000000000000000027041462766011000277460ustar00rootroot00000000000000{ "description": "updateOne-validation", "schemaVersion": "1.0", "createEntities": [ { "client": { "id": "client0", "observeEvents": [ "commandStartedEvent" ] } }, { "database": { "id": "database0", "client": "client0", "databaseName": "crud-tests" } }, { "collection": { "id": "collection0", "database": "database0", "collectionName": "coll0" } } ], "initialData": [ { "collectionName": "coll0", "databaseName": "crud-tests", "documents": [ { "_id": 1, "x": 11 } ] } ], "tests": [ { "description": "UpdateOne requires atomic modifiers", "operations": [ { "name": "updateOne", "object": "collection0", "arguments": { "filter": { "_id": 1 }, "update": { "x": 22 } }, "expectError": { "isClientError": true } } ], "expectEvents": [ { "client": "client0", "events": [] } ], "outcome": [ { "collectionName": "coll0", "databaseName": "crud-tests", "documents": [ { "_id": 1, "x": 11 } ] } ] } ] } mongodb-mongo-python-driver-509e9b7/test/crud/unified/updateWithPipelines.json000066400000000000000000000262751462766011000276720ustar00rootroot00000000000000{ "description": "updateWithPipelines", "schemaVersion": "1.0", "runOnRequirements": [ { "minServerVersion": "4.1.11" } ], "createEntities": [ { "client": { "id": "client0", "observeEvents": [ "commandStartedEvent" ] } }, { "database": { "id": "database0", "client": "client0", "databaseName": "crud-tests" } }, { "collection": { "id": "collection0", "database": "database0", "collectionName": "test" } } ], "initialData": [ { "collectionName": "test", "databaseName": "crud-tests", "documents": [ { "_id": 1, "x": 1, "y": 1, "t": { "u": { "v": 1 } } }, { "_id": 2, "x": 2, "y": 1 } ] } ], "tests": [ { "description": "UpdateOne using pipelines", "operations": [ { "object": "collection0", "name": "updateOne", "arguments": { "filter": { "_id": 1 }, "update": [ { "$replaceRoot": { "newRoot": "$t" } }, { "$addFields": { "foo": 1 } } ] }, "expectResult": { "matchedCount": 1, "modifiedCount": 1, "upsertedCount": 0 } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "update": "test", "updates": [ { "q": { "_id": 1 }, "u": [ { "$replaceRoot": { "newRoot": "$t" } }, { "$addFields": { "foo": 1 } } ], "multi": { "$$unsetOrMatches": false }, "upsert": { "$$unsetOrMatches": false } } ] }, "commandName": "update", "databaseName": "crud-tests" } } ] } ], "outcome": [ { "collectionName": "test", "databaseName": "crud-tests", "documents": [ { "_id": 1, "u": { "v": 1 }, "foo": 1 }, { "_id": 2, "x": 2, "y": 1 } ] } ] }, { "description": "UpdateMany using pipelines", "operations": [ { "object": "collection0", "name": "updateMany", "arguments": { "filter": {}, "update": [ { "$project": { "x": 1 } }, { "$addFields": { "foo": 1 } } ] }, "expectResult": { "matchedCount": 2, "modifiedCount": 2, "upsertedCount": 0 } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "update": "test", "updates": [ { "q": {}, "u": [ { "$project": { "x": 1 } }, { "$addFields": { "foo": 1 } } ], "multi": true, "upsert": { "$$unsetOrMatches": false } } ] }, "commandName": "update", "databaseName": "crud-tests" } } ] } ], "outcome": [ { "collectionName": "test", "databaseName": "crud-tests", "documents": [ { "_id": 1, "x": 1, "foo": 1 }, { "_id": 2, "x": 2, "foo": 1 } ] } ] }, { "description": "FindOneAndUpdate using pipelines", "operations": [ { "object": "collection0", "name": "findOneAndUpdate", "arguments": { "filter": { "_id": 1 }, "update": [ { "$project": { "x": 1 } }, { "$addFields": { "foo": 1 } } ] } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "findAndModify": "test", "update": [ { "$project": { "x": 1 } }, { "$addFields": { "foo": 1 } } ] }, "commandName": "findAndModify", "databaseName": "crud-tests" } } ] } ], "outcome": [ { "collectionName": "test", "databaseName": "crud-tests", "documents": [ { "_id": 1, "x": 1, "foo": 1 }, { "_id": 2, "x": 2, "y": 1 } ] } ] }, { "description": "UpdateOne in bulk write using pipelines", "operations": [ { "object": "collection0", "name": "bulkWrite", "arguments": { "requests": [ { "updateOne": { "filter": { "_id": 1 }, "update": [ { "$replaceRoot": { "newRoot": "$t" } }, { "$addFields": { "foo": 1 } } ] } } ] }, "expectResult": { "matchedCount": 1, "modifiedCount": 1, "upsertedCount": 0 } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "update": "test", "updates": [ { "q": { "_id": 1 }, "u": [ { "$replaceRoot": { "newRoot": "$t" } }, { "$addFields": { "foo": 1 } } ], "multi": { "$$unsetOrMatches": false }, "upsert": { "$$unsetOrMatches": false } } ] }, "commandName": "update", "databaseName": "crud-tests" } } ] } ], "outcome": [ { "collectionName": "test", "databaseName": "crud-tests", "documents": [ { "_id": 1, "u": { "v": 1 }, "foo": 1 }, { "_id": 2, "x": 2, "y": 1 } ] } ] }, { "description": "UpdateMany in bulk write using pipelines", "operations": [ { "object": "collection0", "name": "bulkWrite", "arguments": { "requests": [ { "updateMany": { "filter": {}, "update": [ { "$project": { "x": 1 } }, { "$addFields": { "foo": 1 } } ] } } ] }, "expectResult": { "matchedCount": 2, "modifiedCount": 2, "upsertedCount": 0 } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "update": "test", "updates": [ { "q": {}, "u": [ { "$project": { "x": 1 } }, { "$addFields": { "foo": 1 } } ], "multi": true, "upsert": { "$$unsetOrMatches": false } } ] }, "commandName": "update", "databaseName": "crud-tests" } } ] } ], "outcome": [ { "collectionName": "test", "databaseName": "crud-tests", "documents": [ { "_id": 1, "x": 1, "foo": 1 }, { "_id": 2, "x": 2, "foo": 1 } ] } ] } ] } mongodb-mongo-python-driver-509e9b7/test/crud/v1/000077500000000000000000000000001462766011000216775ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/crud/v1/read/000077500000000000000000000000001462766011000226125ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/crud/v1/read/aggregate-collation.json000066400000000000000000000012101462766011000274070ustar00rootroot00000000000000{ "data": [ { "_id": 1, "x": "ping" } ], "minServerVersion": "3.4", "serverless": "forbid", "tests": [ { "description": "Aggregate with collation", "operation": { "name": "aggregate", "arguments": { "pipeline": [ { "$match": { "x": "PING" } } ], "collation": { "locale": "en_US", "strength": 2 } } }, "outcome": { "result": [ { "_id": 1, "x": "ping" } ] } } ] } mongodb-mongo-python-driver-509e9b7/test/crud/v1/read/aggregate-out.json000066400000000000000000000034701462766011000262440ustar00rootroot00000000000000{ "data": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 22 }, { "_id": 3, "x": 33 } ], "minServerVersion": "2.6", "serverless": "forbid", "tests": [ { "description": "Aggregate with $out", "operation": { "name": "aggregate", "arguments": { "pipeline": [ { "$sort": { "x": 1 } }, { "$match": { "_id": { "$gt": 1 } } }, { "$out": "other_test_collection" } ], "batchSize": 2 } }, "outcome": { "collection": { "name": "other_test_collection", "data": [ { "_id": 2, "x": 22 }, { "_id": 3, "x": 33 } ] } } }, { "description": "Aggregate with $out and batch size of 0", "operation": { "name": "aggregate", "arguments": { "pipeline": [ { "$sort": { "x": 1 } }, { "$match": { "_id": { "$gt": 1 } } }, { "$out": "other_test_collection" } ], "batchSize": 0 } }, "outcome": { "collection": { "name": "other_test_collection", "data": [ { "_id": 2, "x": 22 }, { "_id": 3, "x": 33 } ] } } } ] } mongodb-mongo-python-driver-509e9b7/test/crud/v1/read/aggregate.json000066400000000000000000000014521462766011000254350ustar00rootroot00000000000000{ "data": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 22 }, { "_id": 3, "x": 33 } ], "tests": [ { "description": "Aggregate with multiple stages", "operation": { "name": "aggregate", "arguments": { "pipeline": [ { "$sort": { "x": 1 } }, { "$match": { "_id": { "$gt": 1 } } } ], "batchSize": 2 } }, "outcome": { "result": [ { "_id": 2, "x": 22 }, { "_id": 3, "x": 33 } ] } } ] } mongodb-mongo-python-driver-509e9b7/test/crud/v1/read/count-collation.json000066400000000000000000000015341462766011000266220ustar00rootroot00000000000000{ "data": [ { "_id": 1, "x": "PING" } ], "minServerVersion": "3.4", "serverless": "forbid", "tests": [ { "description": "Count documents with collation", "operation": { "name": "countDocuments", "arguments": { "filter": { "x": "ping" }, "collation": { "locale": "en_US", "strength": 2 } } }, "outcome": { "result": 1 } }, { "description": "Deprecated count with collation", "operation": { "name": "count", "arguments": { "filter": { "x": "ping" }, "collation": { "locale": "en_US", "strength": 2 } } }, "outcome": { "result": 1 } } ] } mongodb-mongo-python-driver-509e9b7/test/crud/v1/read/count-empty.json000066400000000000000000000013411462766011000257700ustar00rootroot00000000000000{ "data": [], "tests": [ { "description": "Estimated document count with empty collection", "operation": { "name": "estimatedDocumentCount", "arguments": {} }, "outcome": { "result": 0 } }, { "description": "Count documents with empty collection", "operation": { "name": "countDocuments", "arguments": { "filter": {} } }, "outcome": { "result": 0 } }, { "description": "Deprecated count with empty collection", "operation": { "name": "count", "arguments": { "filter": {} } }, "outcome": { "result": 0 } } ] } mongodb-mongo-python-driver-509e9b7/test/crud/v1/read/count.json000066400000000000000000000037101462766011000246360ustar00rootroot00000000000000{ "data": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 22 }, { "_id": 3, "x": 33 } ], "tests": [ { "description": "Estimated document count", "operation": { "name": "estimatedDocumentCount", "arguments": {} }, "outcome": { "result": 3 } }, { "description": "Count documents without a filter", "operation": { "name": "countDocuments", "arguments": { "filter": {} } }, "outcome": { "result": 3 } }, { "description": "Count documents with a filter", "operation": { "name": "countDocuments", "arguments": { "filter": { "_id": { "$gt": 1 } } } }, "outcome": { "result": 2 } }, { "description": "Count documents with skip and limit", "operation": { "name": "countDocuments", "arguments": { "filter": {}, "skip": 1, "limit": 3 } }, "outcome": { "result": 2 } }, { "description": "Deprecated count without a filter", "operation": { "name": "count", "arguments": { "filter": {} } }, "outcome": { "result": 3 } }, { "description": "Deprecated count with a filter", "operation": { "name": "count", "arguments": { "filter": { "_id": { "$gt": 1 } } } }, "outcome": { "result": 2 } }, { "description": "Deprecated count with skip and limit", "operation": { "name": "count", "arguments": { "filter": {}, "skip": 1, "limit": 3 } }, "outcome": { "result": 2 } } ] } mongodb-mongo-python-driver-509e9b7/test/crud/v1/read/distinct-collation.json000066400000000000000000000010461462766011000273110ustar00rootroot00000000000000{ "data": [ { "_id": 1, "string": "PING" }, { "_id": 2, "string": "ping" } ], "minServerVersion": "3.4", "serverless": "forbid", "tests": [ { "description": "Distinct with a collation", "operation": { "name": "distinct", "arguments": { "fieldName": "string", "collation": { "locale": "en_US", "strength": 2 } } }, "outcome": { "result": [ "PING" ] } } ] } mongodb-mongo-python-driver-509e9b7/test/crud/v1/read/distinct.json000066400000000000000000000014671462766011000253360ustar00rootroot00000000000000{ "data": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 22 }, { "_id": 3, "x": 33 } ], "tests": [ { "description": "Distinct without a filter", "operation": { "name": "distinct", "arguments": { "fieldName": "x", "filter": {} } }, "outcome": { "result": [ 11, 22, 33 ] } }, { "description": "Distinct with a filter", "operation": { "name": "distinct", "arguments": { "fieldName": "x", "filter": { "_id": { "$gt": 1 } } } }, "outcome": { "result": [ 22, 33 ] } } ] } mongodb-mongo-python-driver-509e9b7/test/crud/v1/read/find-collation.json000066400000000000000000000010641462766011000264100ustar00rootroot00000000000000{ "data": [ { "_id": 1, "x": "ping" } ], "minServerVersion": "3.4", "serverless": "forbid", "tests": [ { "description": "Find with a collation", "operation": { "name": "find", "arguments": { "filter": { "x": "PING" }, "collation": { "locale": "en_US", "strength": 2 } } }, "outcome": { "result": [ { "_id": 1, "x": "ping" } ] } } ] } mongodb-mongo-python-driver-509e9b7/test/crud/v1/read/find.json000066400000000000000000000031701462766011000244260ustar00rootroot00000000000000{ "data": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 22 }, { "_id": 3, "x": 33 }, { "_id": 4, "x": 44 }, { "_id": 5, "x": 55 } ], "tests": [ { "description": "Find with filter", "operation": { "name": "find", "arguments": { "filter": { "_id": 1 } } }, "outcome": { "result": [ { "_id": 1, "x": 11 } ] } }, { "description": "Find with filter, sort, skip, and limit", "operation": { "name": "find", "arguments": { "filter": { "_id": { "$gt": 2 } }, "sort": { "_id": 1 }, "skip": 2, "limit": 2 } }, "outcome": { "result": [ { "_id": 5, "x": 55 } ] } }, { "description": "Find with limit, sort, and batchsize", "operation": { "name": "find", "arguments": { "filter": {}, "sort": { "_id": 1 }, "limit": 4, "batchSize": 2 } }, "outcome": { "result": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 22 }, { "_id": 3, "x": 33 }, { "_id": 4, "x": 44 } ] } } ] } mongodb-mongo-python-driver-509e9b7/test/crud/v1/write/000077500000000000000000000000001462766011000230315ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/crud/v1/write/bulkWrite-arrayFilters.json000066400000000000000000000040721462766011000303440ustar00rootroot00000000000000{ "data": [ { "_id": 1, "y": [ { "b": 3 }, { "b": 1 } ] }, { "_id": 2, "y": [ { "b": 0 }, { "b": 1 } ] } ], "minServerVersion": "3.5.6", "tests": [ { "description": "BulkWrite with arrayFilters", "operation": { "name": "bulkWrite", "arguments": { "requests": [ { "name": "updateOne", "arguments": { "filter": {}, "update": { "$set": { "y.$[i].b": 2 } }, "arrayFilters": [ { "i.b": 3 } ] } }, { "name": "updateMany", "arguments": { "filter": {}, "update": { "$set": { "y.$[i].b": 2 } }, "arrayFilters": [ { "i.b": 1 } ] } } ], "options": { "ordered": true } } }, "outcome": { "result": { "deletedCount": 0, "insertedCount": 0, "insertedIds": {}, "matchedCount": 3, "modifiedCount": 3, "upsertedCount": 0, "upsertedIds": {} }, "collection": { "data": [ { "_id": 1, "y": [ { "b": 2 }, { "b": 2 } ] }, { "_id": 2, "y": [ { "b": 0 }, { "b": 2 } ] } ] } } } ] } mongodb-mongo-python-driver-509e9b7/test/crud/v1/write/bulkWrite-collation.json000066400000000000000000000112261462766011000276600ustar00rootroot00000000000000{ "data": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": "ping" }, { "_id": 3, "x": "pINg" }, { "_id": 4, "x": "pong" }, { "_id": 5, "x": "pONg" } ], "minServerVersion": "3.4", "serverless": "forbid", "tests": [ { "description": "BulkWrite with delete operations and collation", "operation": { "name": "bulkWrite", "arguments": { "requests": [ { "name": "deleteOne", "arguments": { "filter": { "x": "PING" }, "collation": { "locale": "en_US", "strength": 2 } } }, { "name": "deleteOne", "arguments": { "filter": { "x": "PING" }, "collation": { "locale": "en_US", "strength": 2 } } }, { "name": "deleteMany", "arguments": { "filter": { "x": "PONG" }, "collation": { "locale": "en_US", "strength": 2 } } } ], "options": { "ordered": true } } }, "outcome": { "result": { "deletedCount": 4, "insertedCount": 0, "insertedIds": {}, "matchedCount": 0, "modifiedCount": 0, "upsertedCount": 0, "upsertedIds": {} }, "collection": { "data": [ { "_id": 1, "x": 11 } ] } } }, { "description": "BulkWrite with update operations and collation", "operation": { "name": "bulkWrite", "arguments": { "requests": [ { "name": "updateMany", "arguments": { "filter": { "x": "ping" }, "update": { "$set": { "x": "PONG" } }, "collation": { "locale": "en_US", "strength": 3 } } }, { "name": "updateOne", "arguments": { "filter": { "x": "ping" }, "update": { "$set": { "x": "PONG" } }, "collation": { "locale": "en_US", "strength": 2 } } }, { "name": "replaceOne", "arguments": { "filter": { "x": "ping" }, "replacement": { "_id": 6, "x": "ping" }, "upsert": true, "collation": { "locale": "en_US", "strength": 3 } } }, { "name": "updateMany", "arguments": { "filter": { "x": "pong" }, "update": { "$set": { "x": "PONG" } }, "collation": { "locale": "en_US", "strength": 2 } } } ], "options": { "ordered": true } } }, "outcome": { "result": { "deletedCount": 0, "insertedCount": 0, "insertedIds": {}, "matchedCount": 6, "modifiedCount": 4, "upsertedCount": 1, "upsertedIds": { "2": 6 } }, "collection": { "data": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": "PONG" }, { "_id": 3, "x": "PONG" }, { "_id": 4, "x": "PONG" }, { "_id": 5, "x": "PONG" }, { "_id": 6, "x": "ping" } ] } } } ] } mongodb-mongo-python-driver-509e9b7/test/crud/v1/write/bulkWrite.json000066400000000000000000000410311462766011000256730ustar00rootroot00000000000000{ "data": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 22 } ], "minServerVersion": "2.6", "tests": [ { "description": "BulkWrite with deleteOne operations", "operation": { "name": "bulkWrite", "arguments": { "requests": [ { "name": "deleteOne", "arguments": { "filter": { "_id": 3 } } }, { "name": "deleteOne", "arguments": { "filter": { "_id": 2 } } } ], "options": { "ordered": true } } }, "outcome": { "result": { "deletedCount": 1, "insertedCount": 0, "insertedIds": {}, "matchedCount": 0, "modifiedCount": 0, "upsertedCount": 0, "upsertedIds": {} }, "collection": { "data": [ { "_id": 1, "x": 11 } ] } } }, { "description": "BulkWrite with deleteMany operations", "operation": { "name": "bulkWrite", "arguments": { "requests": [ { "name": "deleteMany", "arguments": { "filter": { "x": { "$lt": 11 } } } }, { "name": "deleteMany", "arguments": { "filter": { "x": { "$lte": 22 } } } } ], "options": { "ordered": true } } }, "outcome": { "result": { "deletedCount": 2, "insertedCount": 0, "insertedIds": {}, "matchedCount": 0, "modifiedCount": 0, "upsertedCount": 0, "upsertedIds": {} }, "collection": { "data": [] } } }, { "description": "BulkWrite with insertOne operations", "operation": { "name": "bulkWrite", "arguments": { "requests": [ { "name": "insertOne", "arguments": { "document": { "_id": 3, "x": 33 } } }, { "name": "insertOne", "arguments": { "document": { "_id": 4, "x": 44 } } } ], "options": { "ordered": true } } }, "outcome": { "result": { "deletedCount": 0, "insertedCount": 2, "insertedIds": { "0": 3, "1": 4 }, "matchedCount": 0, "modifiedCount": 0, "upsertedCount": 0, "upsertedIds": {} }, "collection": { "data": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 22 }, { "_id": 3, "x": 33 }, { "_id": 4, "x": 44 } ] } } }, { "description": "BulkWrite with replaceOne operations", "operation": { "name": "bulkWrite", "arguments": { "requests": [ { "name": "replaceOne", "arguments": { "filter": { "_id": 3 }, "replacement": { "x": 33 } } }, { "name": "replaceOne", "arguments": { "filter": { "_id": 1 }, "replacement": { "x": 12 } } }, { "name": "replaceOne", "arguments": { "filter": { "_id": 3 }, "replacement": { "x": 33 }, "upsert": true } } ], "options": { "ordered": true } } }, "outcome": { "result": { "deletedCount": 0, "insertedCount": 0, "insertedIds": {}, "matchedCount": 1, "modifiedCount": 1, "upsertedCount": 1, "upsertedIds": { "2": 3 } }, "collection": { "data": [ { "_id": 1, "x": 12 }, { "_id": 2, "x": 22 }, { "_id": 3, "x": 33 } ] } } }, { "description": "BulkWrite with updateOne operations", "operation": { "name": "bulkWrite", "arguments": { "requests": [ { "name": "updateOne", "arguments": { "filter": { "_id": 0 }, "update": { "$set": { "x": 0 } } } }, { "name": "updateOne", "arguments": { "filter": { "_id": 1 }, "update": { "$set": { "x": 11 } } } }, { "name": "updateOne", "arguments": { "filter": { "_id": 2 }, "update": { "$inc": { "x": 1 } } } }, { "name": "updateOne", "arguments": { "filter": { "_id": 3 }, "update": { "$set": { "x": 33 } }, "upsert": true } } ], "options": { "ordered": true } } }, "outcome": { "result": { "deletedCount": 0, "insertedCount": 0, "insertedIds": {}, "matchedCount": 2, "modifiedCount": 1, "upsertedCount": 1, "upsertedIds": { "3": 3 } }, "collection": { "data": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 23 }, { "_id": 3, "x": 33 } ] } } }, { "description": "BulkWrite with updateMany operations", "operation": { "name": "bulkWrite", "arguments": { "requests": [ { "name": "updateMany", "arguments": { "filter": { "x": { "$lt": 11 } }, "update": { "$set": { "x": 0 } } } }, { "name": "updateMany", "arguments": { "filter": { "x": { "$lte": 22 } }, "update": { "$unset": { "y": 1 } } } }, { "name": "updateMany", "arguments": { "filter": { "x": { "$lte": 22 } }, "update": { "$inc": { "x": 1 } } } }, { "name": "updateMany", "arguments": { "filter": { "_id": 3 }, "update": { "$set": { "x": 33 } }, "upsert": true } } ], "options": { "ordered": true } } }, "outcome": { "result": { "deletedCount": 0, "insertedCount": 0, "insertedIds": {}, "matchedCount": 4, "modifiedCount": 2, "upsertedCount": 1, "upsertedIds": { "3": 3 } }, "collection": { "data": [ { "_id": 1, "x": 12 }, { "_id": 2, "x": 23 }, { "_id": 3, "x": 33 } ] } } }, { "description": "BulkWrite with mixed ordered operations", "operation": { "name": "bulkWrite", "arguments": { "requests": [ { "name": "insertOne", "arguments": { "document": { "_id": 3, "x": 33 } } }, { "name": "updateOne", "arguments": { "filter": { "_id": 2 }, "update": { "$inc": { "x": 1 } } } }, { "name": "updateMany", "arguments": { "filter": { "_id": { "$gt": 1 } }, "update": { "$inc": { "x": 1 } } } }, { "name": "insertOne", "arguments": { "document": { "_id": 4, "x": 44 } } }, { "name": "deleteMany", "arguments": { "filter": { "x": { "$nin": [ 24, 34 ] } } } }, { "name": "replaceOne", "arguments": { "filter": { "_id": 4 }, "replacement": { "_id": 4, "x": 44 }, "upsert": true } } ], "options": { "ordered": true } } }, "outcome": { "result": { "deletedCount": 2, "insertedCount": 2, "insertedIds": { "0": 3, "3": 4 }, "matchedCount": 3, "modifiedCount": 3, "upsertedCount": 1, "upsertedIds": { "5": 4 } }, "collection": { "data": [ { "_id": 2, "x": 24 }, { "_id": 3, "x": 34 }, { "_id": 4, "x": 44 } ] } } }, { "description": "BulkWrite with mixed unordered operations", "operation": { "name": "bulkWrite", "arguments": { "requests": [ { "name": "replaceOne", "arguments": { "filter": { "_id": 3 }, "replacement": { "_id": 3, "x": 33 }, "upsert": true } }, { "name": "deleteOne", "arguments": { "filter": { "_id": 1 } } }, { "name": "updateOne", "arguments": { "filter": { "_id": 2 }, "update": { "$inc": { "x": 1 } } } } ], "options": { "ordered": false } } }, "outcome": { "result": { "deletedCount": 1, "insertedCount": 0, "insertedIds": {}, "matchedCount": 1, "modifiedCount": 1, "upsertedCount": 1, "upsertedIds": { "0": 3 } }, "collection": { "data": [ { "_id": 2, "x": 23 }, { "_id": 3, "x": 33 } ] } } }, { "description": "BulkWrite continue-on-error behavior with unordered (preexisting duplicate key)", "operation": { "name": "bulkWrite", "arguments": { "requests": [ { "name": "insertOne", "arguments": { "document": { "_id": 2, "x": 22 } } }, { "name": "insertOne", "arguments": { "document": { "_id": 3, "x": 33 } } }, { "name": "insertOne", "arguments": { "document": { "_id": 4, "x": 44 } } } ], "options": { "ordered": false } } }, "outcome": { "error": true, "result": { "deletedCount": 0, "insertedCount": 2, "matchedCount": 0, "modifiedCount": 0, "upsertedCount": 0, "upsertedIds": {} }, "collection": { "data": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 22 }, { "_id": 3, "x": 33 }, { "_id": 4, "x": 44 } ] } } }, { "description": "BulkWrite continue-on-error behavior with unordered (duplicate key in requests)", "operation": { "name": "bulkWrite", "arguments": { "requests": [ { "name": "insertOne", "arguments": { "document": { "_id": 3, "x": 33 } } }, { "name": "insertOne", "arguments": { "document": { "_id": 3, "x": 33 } } }, { "name": "insertOne", "arguments": { "document": { "_id": 4, "x": 44 } } } ], "options": { "ordered": false } } }, "outcome": { "error": true, "result": { "deletedCount": 0, "insertedCount": 2, "matchedCount": 0, "modifiedCount": 0, "upsertedCount": 0, "upsertedIds": {} }, "collection": { "data": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 22 }, { "_id": 3, "x": 33 }, { "_id": 4, "x": 44 } ] } } } ] } mongodb-mongo-python-driver-509e9b7/test/crud/v1/write/deleteMany-collation.json000066400000000000000000000014251462766011000277770ustar00rootroot00000000000000{ "data": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": "ping" }, { "_id": 3, "x": "pINg" } ], "minServerVersion": "3.4", "serverless": "forbid", "tests": [ { "description": "DeleteMany when many documents match with collation", "operation": { "name": "deleteMany", "arguments": { "filter": { "x": "PING" }, "collation": { "locale": "en_US", "strength": 2 } } }, "outcome": { "result": { "deletedCount": 2 }, "collection": { "data": [ { "_id": 1, "x": 11 } ] } } } ] } mongodb-mongo-python-driver-509e9b7/test/crud/v1/write/deleteMany.json000066400000000000000000000023371462766011000260200ustar00rootroot00000000000000{ "data": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 22 }, { "_id": 3, "x": 33 } ], "tests": [ { "description": "DeleteMany when many documents match", "operation": { "name": "deleteMany", "arguments": { "filter": { "_id": { "$gt": 1 } } } }, "outcome": { "result": { "deletedCount": 2 }, "collection": { "data": [ { "_id": 1, "x": 11 } ] } } }, { "description": "DeleteMany when no document matches", "operation": { "name": "deleteMany", "arguments": { "filter": { "_id": 4 } } }, "outcome": { "result": { "deletedCount": 0 }, "collection": { "data": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 22 }, { "_id": 3, "x": 33 } ] } } } ] } mongodb-mongo-python-driver-509e9b7/test/crud/v1/write/deleteOne-collation.json000066400000000000000000000015441462766011000276160ustar00rootroot00000000000000{ "data": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": "ping" }, { "_id": 3, "x": "pINg" } ], "minServerVersion": "3.4", "serverless": "forbid", "tests": [ { "description": "DeleteOne when many documents matches with collation", "operation": { "name": "deleteOne", "arguments": { "filter": { "x": "PING" }, "collation": { "locale": "en_US", "strength": 2 } } }, "outcome": { "result": { "deletedCount": 1 }, "collection": { "data": [ { "_id": 1, "x": 11 }, { "_id": 3, "x": "pINg" } ] } } } ] } mongodb-mongo-python-driver-509e9b7/test/crud/v1/write/deleteOne.json000066400000000000000000000031261462766011000256320ustar00rootroot00000000000000{ "data": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 22 }, { "_id": 3, "x": 33 } ], "tests": [ { "description": "DeleteOne when many documents match", "operation": { "name": "deleteOne", "arguments": { "filter": { "_id": { "$gt": 1 } } } }, "outcome": { "result": { "deletedCount": 1 } } }, { "description": "DeleteOne when one document matches", "operation": { "name": "deleteOne", "arguments": { "filter": { "_id": 2 } } }, "outcome": { "result": { "deletedCount": 1 }, "collection": { "data": [ { "_id": 1, "x": 11 }, { "_id": 3, "x": 33 } ] } } }, { "description": "DeleteOne when no documents match", "operation": { "name": "deleteOne", "arguments": { "filter": { "_id": 4 } } }, "outcome": { "result": { "deletedCount": 0 }, "collection": { "data": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 22 }, { "_id": 3, "x": 33 } ] } } } ] } mongodb-mongo-python-driver-509e9b7/test/crud/v1/write/findOneAndDelete-collation.json000066400000000000000000000020041462766011000310320ustar00rootroot00000000000000{ "data": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": "ping" }, { "_id": 3, "x": "pINg" } ], "minServerVersion": "3.4", "serverless": "forbid", "tests": [ { "description": "FindOneAndDelete when one document matches with collation", "operation": { "name": "findOneAndDelete", "arguments": { "filter": { "_id": 2, "x": "PING" }, "projection": { "x": 1, "_id": 0 }, "sort": { "x": 1 }, "collation": { "locale": "en_US", "strength": 2 } } }, "outcome": { "result": { "x": "ping" }, "collection": { "data": [ { "_id": 1, "x": 11 }, { "_id": 3, "x": "pINg" } ] } } } ] } mongodb-mongo-python-driver-509e9b7/test/crud/v1/write/findOneAndDelete.json000066400000000000000000000042551462766011000270620ustar00rootroot00000000000000{ "data": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 22 }, { "_id": 3, "x": 33 } ], "tests": [ { "description": "FindOneAndDelete when many documents match", "operation": { "name": "findOneAndDelete", "arguments": { "filter": { "_id": { "$gt": 1 } }, "projection": { "x": 1, "_id": 0 }, "sort": { "x": 1 } } }, "outcome": { "result": { "x": 22 }, "collection": { "data": [ { "_id": 1, "x": 11 }, { "_id": 3, "x": 33 } ] } } }, { "description": "FindOneAndDelete when one document matches", "operation": { "name": "findOneAndDelete", "arguments": { "filter": { "_id": 2 }, "projection": { "x": 1, "_id": 0 }, "sort": { "x": 1 } } }, "outcome": { "result": { "x": 22 }, "collection": { "data": [ { "_id": 1, "x": 11 }, { "_id": 3, "x": 33 } ] } } }, { "description": "FindOneAndDelete when no documents match", "operation": { "name": "findOneAndDelete", "arguments": { "filter": { "_id": 4 }, "projection": { "x": 1, "_id": 0 }, "sort": { "x": 1 } } }, "outcome": { "result": null, "collection": { "data": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 22 }, { "_id": 3, "x": 33 } ] } } } ] } mongodb-mongo-python-driver-509e9b7/test/crud/v1/write/findOneAndReplace-collation.json000066400000000000000000000021201462766011000312020ustar00rootroot00000000000000{ "data": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": "ping" } ], "minServerVersion": "3.4", "serverless": "forbid", "tests": [ { "description": "FindOneAndReplace when one document matches with collation returning the document after modification", "operation": { "name": "findOneAndReplace", "arguments": { "filter": { "x": "PING" }, "replacement": { "x": "pong" }, "projection": { "x": 1, "_id": 0 }, "returnDocument": "After", "sort": { "x": 1 }, "collation": { "locale": "en_US", "strength": 2 } } }, "outcome": { "result": { "x": "pong" }, "collection": { "data": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": "pong" } ] } } } ] } mongodb-mongo-python-driver-509e9b7/test/crud/v1/write/findOneAndReplace-upsert.json000066400000000000000000000076721462766011000305610ustar00rootroot00000000000000{ "data": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 22 }, { "_id": 3, "x": 33 } ], "minServerVersion": "2.6", "tests": [ { "description": "FindOneAndReplace when no documents match without id specified with upsert returning the document before modification", "operation": { "name": "findOneAndReplace", "arguments": { "filter": { "_id": 4 }, "replacement": { "x": 44 }, "projection": { "x": 1, "_id": 0 }, "upsert": true } }, "outcome": { "result": null, "collection": { "data": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 22 }, { "_id": 3, "x": 33 }, { "_id": 4, "x": 44 } ] } } }, { "description": "FindOneAndReplace when no documents match without id specified with upsert returning the document after modification", "operation": { "name": "findOneAndReplace", "arguments": { "filter": { "_id": 4 }, "replacement": { "x": 44 }, "projection": { "x": 1, "_id": 0 }, "returnDocument": "After", "sort": { "x": 1 }, "upsert": true } }, "outcome": { "result": { "x": 44 }, "collection": { "data": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 22 }, { "_id": 3, "x": 33 }, { "_id": 4, "x": 44 } ] } } }, { "description": "FindOneAndReplace when no documents match with id specified with upsert returning the document before modification", "operation": { "name": "findOneAndReplace", "arguments": { "filter": { "_id": 4 }, "replacement": { "_id": 4, "x": 44 }, "projection": { "x": 1, "_id": 0 }, "upsert": true } }, "outcome": { "result": null, "collection": { "data": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 22 }, { "_id": 3, "x": 33 }, { "_id": 4, "x": 44 } ] } } }, { "description": "FindOneAndReplace when no documents match with id specified with upsert returning the document after modification", "operation": { "name": "findOneAndReplace", "arguments": { "filter": { "_id": 4 }, "replacement": { "_id": 4, "x": 44 }, "projection": { "x": 1, "_id": 0 }, "returnDocument": "After", "sort": { "x": 1 }, "upsert": true } }, "outcome": { "result": { "x": 44 }, "collection": { "data": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 22 }, { "_id": 3, "x": 33 }, { "_id": 4, "x": 44 } ] } } } ] } mongodb-mongo-python-driver-509e9b7/test/crud/v1/write/findOneAndReplace.json000066400000000000000000000123031462766011000272240ustar00rootroot00000000000000{ "data": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 22 }, { "_id": 3, "x": 33 } ], "tests": [ { "description": "FindOneAndReplace when many documents match returning the document before modification", "operation": { "name": "findOneAndReplace", "arguments": { "filter": { "_id": { "$gt": 1 } }, "replacement": { "x": 32 }, "projection": { "x": 1, "_id": 0 }, "sort": { "x": 1 } } }, "outcome": { "result": { "x": 22 }, "collection": { "data": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 32 }, { "_id": 3, "x": 33 } ] } } }, { "description": "FindOneAndReplace when many documents match returning the document after modification", "operation": { "name": "findOneAndReplace", "arguments": { "filter": { "_id": { "$gt": 1 } }, "replacement": { "x": 32 }, "projection": { "x": 1, "_id": 0 }, "returnDocument": "After", "sort": { "x": 1 } } }, "outcome": { "result": { "x": 32 }, "collection": { "data": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 32 }, { "_id": 3, "x": 33 } ] } } }, { "description": "FindOneAndReplace when one document matches returning the document before modification", "operation": { "name": "findOneAndReplace", "arguments": { "filter": { "_id": 2 }, "replacement": { "x": 32 }, "projection": { "x": 1, "_id": 0 }, "sort": { "x": 1 } } }, "outcome": { "result": { "x": 22 }, "collection": { "data": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 32 }, { "_id": 3, "x": 33 } ] } } }, { "description": "FindOneAndReplace when one document matches returning the document after modification", "operation": { "name": "findOneAndReplace", "arguments": { "filter": { "_id": 2 }, "replacement": { "x": 32 }, "projection": { "x": 1, "_id": 0 }, "returnDocument": "After", "sort": { "x": 1 } } }, "outcome": { "result": { "x": 32 }, "collection": { "data": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 32 }, { "_id": 3, "x": 33 } ] } } }, { "description": "FindOneAndReplace when no documents match returning the document before modification", "operation": { "name": "findOneAndReplace", "arguments": { "filter": { "_id": 4 }, "replacement": { "x": 44 }, "projection": { "x": 1, "_id": 0 }, "sort": { "x": 1 } } }, "outcome": { "result": null, "collection": { "data": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 22 }, { "_id": 3, "x": 33 } ] } } }, { "description": "FindOneAndReplace when no documents match returning the document after modification", "operation": { "name": "findOneAndReplace", "arguments": { "filter": { "_id": 4 }, "replacement": { "x": 44 }, "projection": { "x": 1, "_id": 0 }, "returnDocument": "After", "sort": { "x": 1 } } }, "outcome": { "result": null, "collection": { "data": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 22 }, { "_id": 3, "x": 33 } ] } } } ] } mongodb-mongo-python-driver-509e9b7/test/crud/v1/write/findOneAndUpdate-arrayFilters.json000066400000000000000000000070551462766011000315500ustar00rootroot00000000000000{ "data": [ { "_id": 1, "y": [ { "b": 3 }, { "b": 1 } ] }, { "_id": 2, "y": [ { "b": 0 }, { "b": 1 } ] } ], "minServerVersion": "3.5.6", "tests": [ { "description": "FindOneAndUpdate when no document matches arrayFilters", "operation": { "name": "findOneAndUpdate", "arguments": { "filter": {}, "update": { "$set": { "y.$[i].b": 2 } }, "arrayFilters": [ { "i.b": 4 } ] } }, "outcome": { "result": { "_id": 1, "y": [ { "b": 3 }, { "b": 1 } ] }, "collection": { "data": [ { "_id": 1, "y": [ { "b": 3 }, { "b": 1 } ] }, { "_id": 2, "y": [ { "b": 0 }, { "b": 1 } ] } ] } } }, { "description": "FindOneAndUpdate when one document matches arrayFilters", "operation": { "name": "findOneAndUpdate", "arguments": { "filter": {}, "update": { "$set": { "y.$[i].b": 2 } }, "arrayFilters": [ { "i.b": 3 } ] } }, "outcome": { "result": { "_id": 1, "y": [ { "b": 3 }, { "b": 1 } ] }, "collection": { "data": [ { "_id": 1, "y": [ { "b": 2 }, { "b": 1 } ] }, { "_id": 2, "y": [ { "b": 0 }, { "b": 1 } ] } ] } } }, { "description": "FindOneAndUpdate when multiple documents match arrayFilters", "operation": { "name": "findOneAndUpdate", "arguments": { "filter": {}, "update": { "$set": { "y.$[i].b": 2 } }, "arrayFilters": [ { "i.b": 1 } ] } }, "outcome": { "result": { "_id": 1, "y": [ { "b": 3 }, { "b": 1 } ] }, "collection": { "data": [ { "_id": 1, "y": [ { "b": 3 }, { "b": 2 } ] }, { "_id": 2, "y": [ { "b": 0 }, { "b": 1 } ] } ] } } } ] } mongodb-mongo-python-driver-509e9b7/test/crud/v1/write/findOneAndUpdate-collation.json000066400000000000000000000023131462766011000310550ustar00rootroot00000000000000{ "data": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": "ping" }, { "_id": 3, "x": "pINg" } ], "minServerVersion": "3.4", "serverless": "forbid", "tests": [ { "description": "FindOneAndUpdate when many documents match with collation returning the document before modification", "operation": { "name": "findOneAndUpdate", "arguments": { "filter": { "x": "PING" }, "update": { "$set": { "x": "pong" } }, "projection": { "x": 1, "_id": 0 }, "sort": { "_id": 1 }, "collation": { "locale": "en_US", "strength": 2 } } }, "outcome": { "result": { "x": "ping" }, "collection": { "data": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": "pong" }, { "_id": 3, "x": "pINg" } ] } } } ] } mongodb-mongo-python-driver-509e9b7/test/crud/v1/write/findOneAndUpdate.json000066400000000000000000000163571462766011000271100ustar00rootroot00000000000000{ "data": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 22 }, { "_id": 3, "x": 33 } ], "tests": [ { "description": "FindOneAndUpdate when many documents match returning the document before modification", "operation": { "name": "findOneAndUpdate", "arguments": { "filter": { "_id": { "$gt": 1 } }, "update": { "$inc": { "x": 1 } }, "projection": { "x": 1, "_id": 0 }, "sort": { "x": 1 } } }, "outcome": { "result": { "x": 22 }, "collection": { "data": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 23 }, { "_id": 3, "x": 33 } ] } } }, { "description": "FindOneAndUpdate when many documents match returning the document after modification", "operation": { "name": "findOneAndUpdate", "arguments": { "filter": { "_id": { "$gt": 1 } }, "update": { "$inc": { "x": 1 } }, "projection": { "x": 1, "_id": 0 }, "returnDocument": "After", "sort": { "x": 1 } } }, "outcome": { "result": { "x": 23 }, "collection": { "data": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 23 }, { "_id": 3, "x": 33 } ] } } }, { "description": "FindOneAndUpdate when one document matches returning the document before modification", "operation": { "name": "findOneAndUpdate", "arguments": { "filter": { "_id": 2 }, "update": { "$inc": { "x": 1 } }, "projection": { "x": 1, "_id": 0 }, "sort": { "x": 1 } } }, "outcome": { "result": { "x": 22 }, "collection": { "data": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 23 }, { "_id": 3, "x": 33 } ] } } }, { "description": "FindOneAndUpdate when one document matches returning the document after modification", "operation": { "name": "findOneAndUpdate", "arguments": { "filter": { "_id": 2 }, "update": { "$inc": { "x": 1 } }, "projection": { "x": 1, "_id": 0 }, "returnDocument": "After", "sort": { "x": 1 } } }, "outcome": { "result": { "x": 23 }, "collection": { "data": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 23 }, { "_id": 3, "x": 33 } ] } } }, { "description": "FindOneAndUpdate when no documents match returning the document before modification", "operation": { "name": "findOneAndUpdate", "arguments": { "filter": { "_id": 4 }, "update": { "$inc": { "x": 1 } }, "projection": { "x": 1, "_id": 0 }, "sort": { "x": 1 } } }, "outcome": { "result": null, "collection": { "data": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 22 }, { "_id": 3, "x": 33 } ] } } }, { "description": "FindOneAndUpdate when no documents match with upsert returning the document before modification", "operation": { "name": "findOneAndUpdate", "arguments": { "filter": { "_id": 4 }, "update": { "$inc": { "x": 1 } }, "projection": { "x": 1, "_id": 0 }, "upsert": true } }, "outcome": { "result": null, "collection": { "data": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 22 }, { "_id": 3, "x": 33 }, { "_id": 4, "x": 1 } ] } } }, { "description": "FindOneAndUpdate when no documents match returning the document after modification", "operation": { "name": "findOneAndUpdate", "arguments": { "filter": { "_id": 4 }, "update": { "$inc": { "x": 1 } }, "projection": { "x": 1, "_id": 0 }, "returnDocument": "After", "sort": { "x": 1 } } }, "outcome": { "result": null, "collection": { "data": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 22 }, { "_id": 3, "x": 33 } ] } } }, { "description": "FindOneAndUpdate when no documents match with upsert returning the document after modification", "operation": { "name": "findOneAndUpdate", "arguments": { "filter": { "_id": 4 }, "update": { "$inc": { "x": 1 } }, "projection": { "x": 1, "_id": 0 }, "returnDocument": "After", "sort": { "x": 1 }, "upsert": true } }, "outcome": { "result": { "x": 1 }, "collection": { "data": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 22 }, { "_id": 3, "x": 33 }, { "_id": 4, "x": 1 } ] } } } ] } mongodb-mongo-python-driver-509e9b7/test/crud/v1/write/insertMany.json000066400000000000000000000060241462766011000260570ustar00rootroot00000000000000{ "data": [ { "_id": 1, "x": 11 } ], "tests": [ { "description": "InsertMany with non-existing documents", "operation": { "name": "insertMany", "arguments": { "documents": [ { "_id": 2, "x": 22 }, { "_id": 3, "x": 33 } ], "options": { "ordered": true } } }, "outcome": { "result": { "insertedIds": { "0": 2, "1": 3 } }, "collection": { "data": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 22 }, { "_id": 3, "x": 33 } ] } } }, { "description": "InsertMany continue-on-error behavior with unordered (preexisting duplicate key)", "operation": { "name": "insertMany", "arguments": { "documents": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 22 }, { "_id": 3, "x": 33 } ], "options": { "ordered": false } } }, "outcome": { "error": true, "result": { "deletedCount": 0, "insertedCount": 2, "matchedCount": 0, "modifiedCount": 0, "upsertedCount": 0, "upsertedIds": {} }, "collection": { "data": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 22 }, { "_id": 3, "x": 33 } ] } } }, { "description": "InsertMany continue-on-error behavior with unordered (duplicate key in requests)", "operation": { "name": "insertMany", "arguments": { "documents": [ { "_id": 2, "x": 22 }, { "_id": 2, "x": 22 }, { "_id": 3, "x": 33 } ], "options": { "ordered": false } } }, "outcome": { "error": true, "result": { "deletedCount": 0, "insertedCount": 2, "matchedCount": 0, "modifiedCount": 0, "upsertedCount": 0, "upsertedIds": {} }, "collection": { "data": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 22 }, { "_id": 3, "x": 33 } ] } } } ] } mongodb-mongo-python-driver-509e9b7/test/crud/v1/write/insertOne.json000066400000000000000000000011601462766011000256700ustar00rootroot00000000000000{ "data": [ { "_id": 1, "x": 11 } ], "tests": [ { "description": "InsertOne with a non-existing document", "operation": { "name": "insertOne", "arguments": { "document": { "_id": 2, "x": 22 } } }, "outcome": { "result": { "insertedId": 2 }, "collection": { "data": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 22 } ] } } } ] } mongodb-mongo-python-driver-509e9b7/test/crud/v1/write/replaceOne-collation.json000066400000000000000000000017071462766011000277700ustar00rootroot00000000000000{ "data": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": "ping" } ], "minServerVersion": "3.4", "serverless": "forbid", "tests": [ { "description": "ReplaceOne when one document matches with collation", "operation": { "name": "replaceOne", "arguments": { "filter": { "x": "PING" }, "replacement": { "_id": 2, "x": "pong" }, "collation": { "locale": "en_US", "strength": 2 } } }, "outcome": { "result": { "matchedCount": 1, "modifiedCount": 1, "upsertedCount": 0 }, "collection": { "data": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": "pong" } ] } } } ] } mongodb-mongo-python-driver-509e9b7/test/crud/v1/write/replaceOne.json000066400000000000000000000075111462766011000260050ustar00rootroot00000000000000{ "data": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 22 }, { "_id": 3, "x": 33 } ], "minServerVersion": "2.6", "tests": [ { "description": "ReplaceOne when many documents match", "operation": { "name": "replaceOne", "arguments": { "filter": { "_id": { "$gt": 1 } }, "replacement": { "x": 111 } } }, "outcome": { "result": { "matchedCount": 1, "modifiedCount": 1, "upsertedCount": 0 } } }, { "description": "ReplaceOne when one document matches", "operation": { "name": "replaceOne", "arguments": { "filter": { "_id": 1 }, "replacement": { "_id": 1, "x": 111 } } }, "outcome": { "result": { "matchedCount": 1, "modifiedCount": 1, "upsertedCount": 0 }, "collection": { "data": [ { "_id": 1, "x": 111 }, { "_id": 2, "x": 22 }, { "_id": 3, "x": 33 } ] } } }, { "description": "ReplaceOne when no documents match", "operation": { "name": "replaceOne", "arguments": { "filter": { "_id": 4 }, "replacement": { "_id": 4, "x": 1 } } }, "outcome": { "result": { "matchedCount": 0, "modifiedCount": 0, "upsertedCount": 0 }, "collection": { "data": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 22 }, { "_id": 3, "x": 33 } ] } } }, { "description": "ReplaceOne with upsert when no documents match without an id specified", "operation": { "name": "replaceOne", "arguments": { "filter": { "_id": 4 }, "replacement": { "x": 1 }, "upsert": true } }, "outcome": { "result": { "matchedCount": 0, "modifiedCount": 0, "upsertedCount": 1, "upsertedId": 4 }, "collection": { "data": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 22 }, { "_id": 3, "x": 33 }, { "_id": 4, "x": 1 } ] } } }, { "description": "ReplaceOne with upsert when no documents match with an id specified", "operation": { "name": "replaceOne", "arguments": { "filter": { "_id": 4 }, "replacement": { "_id": 4, "x": 1 }, "upsert": true } }, "outcome": { "result": { "matchedCount": 0, "modifiedCount": 0, "upsertedCount": 1, "upsertedId": 4 }, "collection": { "data": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 22 }, { "_id": 3, "x": 33 }, { "_id": 4, "x": 1 } ] } } } ] } mongodb-mongo-python-driver-509e9b7/test/crud/v1/write/updateMany-arrayFilters.json000066400000000000000000000065241462766011000305070ustar00rootroot00000000000000{ "data": [ { "_id": 1, "y": [ { "b": 3 }, { "b": 1 } ] }, { "_id": 2, "y": [ { "b": 0 }, { "b": 1 } ] } ], "minServerVersion": "3.5.6", "tests": [ { "description": "UpdateMany when no documents match arrayFilters", "operation": { "name": "updateMany", "arguments": { "filter": {}, "update": { "$set": { "y.$[i].b": 2 } }, "arrayFilters": [ { "i.b": 4 } ] } }, "outcome": { "result": { "matchedCount": 2, "modifiedCount": 0, "upsertedCount": 0 }, "collection": { "data": [ { "_id": 1, "y": [ { "b": 3 }, { "b": 1 } ] }, { "_id": 2, "y": [ { "b": 0 }, { "b": 1 } ] } ] } } }, { "description": "UpdateMany when one document matches arrayFilters", "operation": { "name": "updateMany", "arguments": { "filter": {}, "update": { "$set": { "y.$[i].b": 2 } }, "arrayFilters": [ { "i.b": 3 } ] } }, "outcome": { "result": { "matchedCount": 2, "modifiedCount": 1, "upsertedCount": 0 }, "collection": { "data": [ { "_id": 1, "y": [ { "b": 2 }, { "b": 1 } ] }, { "_id": 2, "y": [ { "b": 0 }, { "b": 1 } ] } ] } } }, { "description": "UpdateMany when multiple documents match arrayFilters", "operation": { "name": "updateMany", "arguments": { "filter": {}, "update": { "$set": { "y.$[i].b": 2 } }, "arrayFilters": [ { "i.b": 1 } ] } }, "outcome": { "result": { "matchedCount": 2, "modifiedCount": 2, "upsertedCount": 0 }, "collection": { "data": [ { "_id": 1, "y": [ { "b": 3 }, { "b": 2 } ] }, { "_id": 2, "y": [ { "b": 0 }, { "b": 2 } ] } ] } } } ] } mongodb-mongo-python-driver-509e9b7/test/crud/v1/write/updateMany-collation.json000066400000000000000000000021201462766011000300100ustar00rootroot00000000000000{ "data": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": "ping" }, { "_id": 3, "x": "pINg" } ], "minServerVersion": "3.4", "serverless": "forbid", "tests": [ { "description": "UpdateMany when many documents match with collation", "operation": { "name": "updateMany", "arguments": { "filter": { "x": "ping" }, "update": { "$set": { "x": "pong" } }, "collation": { "locale": "en_US", "strength": 2 } } }, "outcome": { "result": { "matchedCount": 2, "modifiedCount": 2, "upsertedCount": 0 }, "collection": { "data": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": "pong" }, { "_id": 3, "x": "pong" } ] } } } ] } mongodb-mongo-python-driver-509e9b7/test/crud/v1/write/updateMany.json000066400000000000000000000064461462766011000260450ustar00rootroot00000000000000{ "data": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 22 }, { "_id": 3, "x": 33 } ], "minServerVersion": "2.6", "tests": [ { "description": "UpdateMany when many documents match", "operation": { "name": "updateMany", "arguments": { "filter": { "_id": { "$gt": 1 } }, "update": { "$inc": { "x": 1 } } } }, "outcome": { "result": { "matchedCount": 2, "modifiedCount": 2, "upsertedCount": 0 }, "collection": { "data": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 23 }, { "_id": 3, "x": 34 } ] } } }, { "description": "UpdateMany when one document matches", "operation": { "name": "updateMany", "arguments": { "filter": { "_id": 1 }, "update": { "$inc": { "x": 1 } } } }, "outcome": { "result": { "matchedCount": 1, "modifiedCount": 1, "upsertedCount": 0 }, "collection": { "data": [ { "_id": 1, "x": 12 }, { "_id": 2, "x": 22 }, { "_id": 3, "x": 33 } ] } } }, { "description": "UpdateMany when no documents match", "operation": { "name": "updateMany", "arguments": { "filter": { "_id": 4 }, "update": { "$inc": { "x": 1 } } } }, "outcome": { "result": { "matchedCount": 0, "modifiedCount": 0, "upsertedCount": 0 }, "collection": { "data": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 22 }, { "_id": 3, "x": 33 } ] } } }, { "description": "UpdateMany with upsert when no documents match", "operation": { "name": "updateMany", "arguments": { "filter": { "_id": 4 }, "update": { "$inc": { "x": 1 } }, "upsert": true } }, "outcome": { "result": { "matchedCount": 0, "modifiedCount": 0, "upsertedCount": 1, "upsertedId": 4 }, "collection": { "data": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 22 }, { "_id": 3, "x": 33 }, { "_id": 4, "x": 1 } ] } } } ] } mongodb-mongo-python-driver-509e9b7/test/crud/v1/write/updateOne-arrayFilters.json000066400000000000000000000166571462766011000303340ustar00rootroot00000000000000{ "data": [ { "_id": 1, "y": [ { "b": 3 }, { "b": 1 } ] }, { "_id": 2, "y": [ { "b": 0 }, { "b": 1 } ] }, { "_id": 3, "y": [ { "b": 5, "c": [ { "d": 2 }, { "d": 1 } ] } ] } ], "minServerVersion": "3.5.6", "tests": [ { "description": "UpdateOne when no document matches arrayFilters", "operation": { "name": "updateOne", "arguments": { "filter": {}, "update": { "$set": { "y.$[i].b": 2 } }, "arrayFilters": [ { "i.b": 4 } ] } }, "outcome": { "result": { "matchedCount": 1, "modifiedCount": 0, "upsertedCount": 0 }, "collection": { "data": [ { "_id": 1, "y": [ { "b": 3 }, { "b": 1 } ] }, { "_id": 2, "y": [ { "b": 0 }, { "b": 1 } ] }, { "_id": 3, "y": [ { "b": 5, "c": [ { "d": 2 }, { "d": 1 } ] } ] } ] } } }, { "description": "UpdateOne when one document matches arrayFilters", "operation": { "name": "updateOne", "arguments": { "filter": {}, "update": { "$set": { "y.$[i].b": 2 } }, "arrayFilters": [ { "i.b": 3 } ] } }, "outcome": { "result": { "matchedCount": 1, "modifiedCount": 1, "upsertedCount": 0 }, "collection": { "data": [ { "_id": 1, "y": [ { "b": 2 }, { "b": 1 } ] }, { "_id": 2, "y": [ { "b": 0 }, { "b": 1 } ] }, { "_id": 3, "y": [ { "b": 5, "c": [ { "d": 2 }, { "d": 1 } ] } ] } ] } } }, { "description": "UpdateOne when multiple documents match arrayFilters", "operation": { "name": "updateOne", "arguments": { "filter": {}, "update": { "$set": { "y.$[i].b": 2 } }, "arrayFilters": [ { "i.b": 1 } ] } }, "outcome": { "result": { "matchedCount": 1, "modifiedCount": 1, "upsertedCount": 0 }, "collection": { "data": [ { "_id": 1, "y": [ { "b": 3 }, { "b": 2 } ] }, { "_id": 2, "y": [ { "b": 0 }, { "b": 1 } ] }, { "_id": 3, "y": [ { "b": 5, "c": [ { "d": 2 }, { "d": 1 } ] } ] } ] } } }, { "description": "UpdateOne when no documents match multiple arrayFilters", "operation": { "name": "updateOne", "arguments": { "filter": { "_id": 3 }, "update": { "$set": { "y.$[i].c.$[j].d": 0 } }, "arrayFilters": [ { "i.b": 5 }, { "j.d": 3 } ] } }, "outcome": { "result": { "matchedCount": 1, "modifiedCount": 0, "upsertedCount": 0 }, "collection": { "data": [ { "_id": 1, "y": [ { "b": 3 }, { "b": 1 } ] }, { "_id": 2, "y": [ { "b": 0 }, { "b": 1 } ] }, { "_id": 3, "y": [ { "b": 5, "c": [ { "d": 2 }, { "d": 1 } ] } ] } ] } } }, { "description": "UpdateOne when one document matches multiple arrayFilters", "operation": { "name": "updateOne", "arguments": { "filter": { "_id": 3 }, "update": { "$set": { "y.$[i].c.$[j].d": 0 } }, "arrayFilters": [ { "i.b": 5 }, { "j.d": 1 } ] } }, "outcome": { "result": { "matchedCount": 1, "modifiedCount": 1, "upsertedCount": 0 }, "collection": { "data": [ { "_id": 1, "y": [ { "b": 3 }, { "b": 1 } ] }, { "_id": 2, "y": [ { "b": 0 }, { "b": 1 } ] }, { "_id": 3, "y": [ { "b": 5, "c": [ { "d": 2 }, { "d": 0 } ] } ] } ] } } } ] } mongodb-mongo-python-driver-509e9b7/test/crud/v1/write/updateOne-collation.json000066400000000000000000000017201462766011000276320ustar00rootroot00000000000000{ "data": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": "ping" } ], "minServerVersion": "3.4", "serverless": "forbid", "tests": [ { "description": "UpdateOne when one document matches with collation", "operation": { "name": "updateOne", "arguments": { "filter": { "x": "PING" }, "update": { "$set": { "x": "pong" } }, "collation": { "locale": "en_US", "strength": 2 } } }, "outcome": { "result": { "matchedCount": 1, "modifiedCount": 1, "upsertedCount": 0 }, "collection": { "data": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": "pong" } ] } } } ] } mongodb-mongo-python-driver-509e9b7/test/crud/v1/write/updateOne.json000066400000000000000000000057731462766011000256640ustar00rootroot00000000000000{ "data": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 22 }, { "_id": 3, "x": 33 } ], "minServerVersion": "2.6", "tests": [ { "description": "UpdateOne when many documents match", "operation": { "name": "updateOne", "arguments": { "filter": { "_id": { "$gt": 1 } }, "update": { "$inc": { "x": 1 } } } }, "outcome": { "result": { "matchedCount": 1, "modifiedCount": 1, "upsertedCount": 0 } } }, { "description": "UpdateOne when one document matches", "operation": { "name": "updateOne", "arguments": { "filter": { "_id": 1 }, "update": { "$inc": { "x": 1 } } } }, "outcome": { "result": { "matchedCount": 1, "modifiedCount": 1, "upsertedCount": 0 }, "collection": { "data": [ { "_id": 1, "x": 12 }, { "_id": 2, "x": 22 }, { "_id": 3, "x": 33 } ] } } }, { "description": "UpdateOne when no documents match", "operation": { "name": "updateOne", "arguments": { "filter": { "_id": 4 }, "update": { "$inc": { "x": 1 } } } }, "outcome": { "result": { "matchedCount": 0, "modifiedCount": 0, "upsertedCount": 0 }, "collection": { "data": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 22 }, { "_id": 3, "x": 33 } ] } } }, { "description": "UpdateOne with upsert when no documents match", "operation": { "name": "updateOne", "arguments": { "filter": { "_id": 4 }, "update": { "$inc": { "x": 1 } }, "upsert": true } }, "outcome": { "result": { "matchedCount": 0, "modifiedCount": 0, "upsertedCount": 1, "upsertedId": 4 }, "collection": { "data": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 22 }, { "_id": 3, "x": 33 }, { "_id": 4, "x": 1 } ] } } } ] } mongodb-mongo-python-driver-509e9b7/test/crud_v2_format.py000066400000000000000000000040201462766011000236760ustar00rootroot00000000000000# Copyright 2020-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. """v2 format CRUD test runner. https://github.com/mongodb/specifications/blob/master/source/crud/tests/README.rst """ from __future__ import annotations from test.utils_spec_runner import SpecRunner class TestCrudV2(SpecRunner): # Default test database and collection names. TEST_DB = None TEST_COLLECTION = None def allowable_errors(self, op): """Override expected error classes.""" errors = super().allowable_errors(op) errors += (ValueError,) return errors def get_scenario_db_name(self, scenario_def): """Crud spec says database_name is optional.""" return scenario_def.get("database_name", self.TEST_DB) def get_scenario_coll_name(self, scenario_def): """Crud spec says collection_name is optional.""" return scenario_def.get("collection_name", self.TEST_COLLECTION) def get_object_name(self, op): """Crud spec says object is optional and defaults to 'collection'.""" return op.get("object", "collection") def get_outcome_coll_name(self, outcome, collection): """Crud spec says outcome has an optional 'collection.name'.""" return outcome["collection"].get("name", collection.name) def setup_scenario(self, scenario_def): """Allow specs to override a test's setup.""" # PYTHON-1935 Only create the collection if there is data to insert. if scenario_def["data"]: super().setup_scenario(scenario_def) mongodb-mongo-python-driver-509e9b7/test/csot/000077500000000000000000000000001462766011000213645ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/csot/bulkWrite.json000066400000000000000000000070471462766011000242370ustar00rootroot00000000000000{ "description": "timeoutMS behaves correctly for bulkWrite operations", "schemaVersion": "1.9", "runOnRequirements": [ { "minServerVersion": "4.4" } ], "createEntities": [ { "client": { "id": "failPointClient", "useMultipleMongoses": false } }, { "client": { "id": "client", "useMultipleMongoses": false, "observeEvents": [ "commandStartedEvent" ], "uriOptions": { "w": 1 } } }, { "database": { "id": "database", "client": "client", "databaseName": "test" } }, { "collection": { "id": "collection", "database": "database", "collectionName": "coll" } } ], "initialData": [ { "collectionName": "coll", "databaseName": "test", "documents": [] } ], "tests": [ { "description": "timeoutMS applied to entire bulkWrite, not individual commands", "operations": [ { "name": "insertOne", "object": "collection", "arguments": { "document": {} } }, { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 2 }, "data": { "failCommands": [ "insert", "update" ], "blockConnection": true, "blockTimeMS": 120 } } } }, { "name": "bulkWrite", "object": "collection", "arguments": { "requests": [ { "insertOne": { "document": { "_id": 1 } } }, { "replaceOne": { "filter": { "_id": 1 }, "replacement": { "x": 1 } } } ], "timeoutMS": 200 }, "expectError": { "isTimeoutError": true } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "insert", "databaseName": "test", "command": { "insert": "coll" } } }, { "commandStartedEvent": { "commandName": "insert", "databaseName": "test", "command": { "insert": "coll", "maxTimeMS": { "$$type": [ "int", "long" ] } } } }, { "commandStartedEvent": { "commandName": "update", "databaseName": "test", "command": { "update": "coll", "maxTimeMS": { "$$type": [ "int", "long" ] } } } } ] } ] } ] } mongodb-mongo-python-driver-509e9b7/test/csot/change-streams.json000066400000000000000000000352731462766011000251720ustar00rootroot00000000000000{ "description": "timeoutMS behaves correctly for change streams", "schemaVersion": "1.9", "runOnRequirements": [ { "minServerVersion": "4.4", "topologies": [ "replicaset", "sharded-replicaset" ] } ], "createEntities": [ { "client": { "id": "failPointClient", "useMultipleMongoses": false } }, { "client": { "id": "client", "useMultipleMongoses": false, "observeEvents": [ "commandStartedEvent" ], "ignoreCommandMonitoringEvents": [ "killCursors" ] } }, { "database": { "id": "database", "client": "client", "databaseName": "test" } }, { "collection": { "id": "collection", "database": "database", "collectionName": "coll" } } ], "initialData": [ { "collectionName": "coll", "databaseName": "test", "documents": [] } ], "tests": [ { "description": "error if maxAwaitTimeMS is greater than timeoutMS", "operations": [ { "name": "createChangeStream", "object": "collection", "arguments": { "pipeline": [], "timeoutMS": 5, "maxAwaitTimeMS": 10 }, "expectError": { "isClientError": true } } ] }, { "description": "error if maxAwaitTimeMS is equal to timeoutMS", "operations": [ { "name": "createChangeStream", "object": "collection", "arguments": { "pipeline": [], "timeoutMS": 5, "maxAwaitTimeMS": 5 }, "expectError": { "isClientError": true } } ] }, { "description": "timeoutMS applied to initial aggregate", "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "aggregate" ], "blockConnection": true, "blockTimeMS": 55 } } } }, { "name": "createChangeStream", "object": "collection", "arguments": { "pipeline": [], "timeoutMS": 50 }, "expectError": { "isTimeoutError": true } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "aggregate", "databaseName": "test", "command": { "aggregate": "coll", "maxTimeMS": { "$$type": [ "int", "long" ] } } } } ] } ] }, { "description": "timeoutMS is refreshed for getMore if maxAwaitTimeMS is not set", "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 2 }, "data": { "failCommands": [ "aggregate", "getMore" ], "blockConnection": true, "blockTimeMS": 30 } } } }, { "name": "createChangeStream", "object": "collection", "arguments": { "pipeline": [], "timeoutMS": 1050 }, "saveResultAsEntity": "changeStream" }, { "name": "iterateOnce", "object": "changeStream" } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "aggregate", "databaseName": "test", "command": { "aggregate": "coll", "maxTimeMS": { "$$type": [ "int", "long" ] } } } }, { "commandStartedEvent": { "commandName": "getMore", "databaseName": "test", "command": { "getMore": { "$$type": [ "int", "long" ] }, "collection": "coll", "maxTimeMS": { "$$exists": false } } } } ] } ] }, { "description": "timeoutMS is refreshed for getMore if maxAwaitTimeMS is set", "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 2 }, "data": { "failCommands": [ "aggregate", "getMore" ], "blockConnection": true, "blockTimeMS": 15 } } } }, { "name": "createChangeStream", "object": "collection", "arguments": { "pipeline": [], "timeoutMS": 20, "batchSize": 2, "maxAwaitTimeMS": 1 }, "saveResultAsEntity": "changeStream" }, { "name": "iterateOnce", "object": "changeStream" } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "aggregate", "databaseName": "test", "command": { "aggregate": "coll", "maxTimeMS": { "$$type": [ "int", "long" ] } } } }, { "commandStartedEvent": { "commandName": "getMore", "databaseName": "test", "command": { "getMore": { "$$type": [ "int", "long" ] }, "collection": "coll", "maxTimeMS": 1 } } } ] } ] }, { "description": "timeoutMS applies to full resume attempt in a next call", "operations": [ { "name": "createChangeStream", "object": "collection", "arguments": { "pipeline": [], "timeoutMS": 20 }, "saveResultAsEntity": "changeStream" }, { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 2 }, "data": { "failCommands": [ "getMore", "aggregate" ], "blockConnection": true, "blockTimeMS": 12, "errorCode": 7, "errorLabels": [ "ResumableChangeStreamError" ] } } } }, { "name": "iterateUntilDocumentOrError", "object": "changeStream", "expectError": { "isTimeoutError": true } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "aggregate", "databaseName": "test", "command": { "aggregate": "coll", "maxTimeMS": { "$$type": [ "int", "long" ] } } } }, { "commandStartedEvent": { "commandName": "getMore", "databaseName": "test", "command": { "getMore": { "$$type": [ "int", "long" ] }, "collection": "coll", "maxTimeMS": { "$$exists": false } } } }, { "commandStartedEvent": { "commandName": "aggregate", "databaseName": "test", "command": { "aggregate": "coll", "maxTimeMS": { "$$type": [ "int", "long" ] } } } } ] } ] }, { "description": "change stream can be iterated again if previous iteration times out", "operations": [ { "name": "createChangeStream", "object": "collection", "arguments": { "pipeline": [], "maxAwaitTimeMS": 1, "timeoutMS": 100 }, "saveResultAsEntity": "changeStream" }, { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "getMore" ], "blockConnection": true, "blockTimeMS": 150 } } } }, { "name": "iterateUntilDocumentOrError", "object": "changeStream", "expectError": { "isTimeoutError": true } }, { "name": "iterateOnce", "object": "changeStream" } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "aggregate", "databaseName": "test", "command": { "aggregate": "coll", "maxTimeMS": { "$$type": [ "int", "long" ] } } } }, { "commandStartedEvent": { "commandName": "getMore", "databaseName": "test", "command": { "getMore": { "$$type": [ "int", "long" ] }, "collection": "coll" } } }, { "commandStartedEvent": { "commandName": "aggregate", "databaseName": "test", "command": { "aggregate": "coll", "maxTimeMS": { "$$type": [ "int", "long" ] } } } }, { "commandStartedEvent": { "commandName": "getMore", "databaseName": "test", "command": { "getMore": { "$$type": [ "int", "long" ] }, "collection": "coll" } } } ] } ] }, { "description": "timeoutMS is refreshed for getMore - failure", "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "getMore" ], "blockConnection": true, "blockTimeMS": 15 } } } }, { "name": "createChangeStream", "object": "collection", "arguments": { "pipeline": [], "timeoutMS": 10 }, "saveResultAsEntity": "changeStream" }, { "name": "iterateUntilDocumentOrError", "object": "changeStream", "expectError": { "isTimeoutError": true } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "aggregate", "databaseName": "test", "command": { "aggregate": "coll", "maxTimeMS": { "$$type": [ "int", "long" ] } } } }, { "commandStartedEvent": { "commandName": "getMore", "databaseName": "test", "command": { "getMore": { "$$type": [ "int", "long" ] }, "collection": "coll" } } } ] } ] } ] } mongodb-mongo-python-driver-509e9b7/test/csot/close-cursors.json000066400000000000000000000124461462766011000250710ustar00rootroot00000000000000{ "description": "timeoutMS behaves correctly when closing cursors", "schemaVersion": "1.9", "runOnRequirements": [ { "minServerVersion": "4.4" } ], "createEntities": [ { "client": { "id": "failPointClient", "useMultipleMongoses": false } }, { "client": { "id": "client", "useMultipleMongoses": false, "observeEvents": [ "commandStartedEvent", "commandSucceededEvent", "commandFailedEvent" ] } }, { "database": { "id": "database", "client": "client", "databaseName": "test" } }, { "collection": { "id": "collection", "database": "database", "collectionName": "coll" } } ], "initialData": [ { "collectionName": "coll", "databaseName": "test", "documents": [ { "_id": 0 }, { "_id": 1 }, { "_id": 2 } ] } ], "tests": [ { "description": "timeoutMS is refreshed for close", "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "getMore" ], "blockConnection": true, "blockTimeMS": 50 } } } }, { "name": "createFindCursor", "object": "collection", "arguments": { "filter": {}, "batchSize": 2, "timeoutMS": 20 }, "saveResultAsEntity": "cursor" }, { "name": "iterateUntilDocumentOrError", "object": "cursor" }, { "name": "iterateUntilDocumentOrError", "object": "cursor" }, { "name": "iterateUntilDocumentOrError", "object": "cursor", "expectError": { "isTimeoutError": true } }, { "name": "close", "object": "cursor" } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "find" } }, { "commandSucceededEvent": { "commandName": "find" } }, { "commandStartedEvent": { "commandName": "getMore" } }, { "commandFailedEvent": { "commandName": "getMore" } }, { "commandStartedEvent": { "command": { "killCursors": "coll", "maxTimeMS": { "$$type": [ "int", "long" ] } }, "commandName": "killCursors" } }, { "commandSucceededEvent": { "commandName": "killCursors" } } ] } ] }, { "description": "timeoutMS can be overridden for close", "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "client", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "killCursors" ], "blockConnection": true, "blockTimeMS": 30 } } } }, { "name": "createFindCursor", "object": "collection", "arguments": { "filter": {}, "batchSize": 2, "timeoutMS": 20 }, "saveResultAsEntity": "cursor" }, { "name": "close", "object": "cursor", "arguments": { "timeoutMS": 40 } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "find" } }, { "commandSucceededEvent": { "commandName": "find" } }, { "commandStartedEvent": { "command": { "killCursors": "collection", "maxTimeMS": { "$$type": [ "int", "long" ] } }, "commandName": "killCursors" } }, { "commandSucceededEvent": { "commandName": "killCursors" } } ] } ] } ] } mongodb-mongo-python-driver-509e9b7/test/csot/command-execution.json000066400000000000000000000232371462766011000257050ustar00rootroot00000000000000{ "description": "timeoutMS behaves correctly during command execution", "schemaVersion": "1.9", "runOnRequirements": [ { "minServerVersion": "4.9", "topologies": [ "single", "replicaset", "sharded-replicaset", "sharded" ], "serverless": "forbid" } ], "createEntities": [ { "client": { "id": "failPointClient", "useMultipleMongoses": false } } ], "initialData": [ { "collectionName": "coll", "databaseName": "test", "documents": [] }, { "collectionName": "timeoutColl", "databaseName": "test", "documents": [] } ], "tests": [ { "description": "maxTimeMS value in the command is less than timeoutMS", "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": "alwaysOn", "data": { "failCommands": [ "hello", "isMaster" ], "appName": "reduceMaxTimeMSTest", "blockConnection": true, "blockTimeMS": 75 } } } }, { "name": "createEntities", "object": "testRunner", "arguments": { "entities": [ { "client": { "id": "client", "useMultipleMongoses": false, "uriOptions": { "appName": "reduceMaxTimeMSTest", "w": 1, "timeoutMS": 500, "heartbeatFrequencyMS": 500 }, "observeEvents": [ "commandStartedEvent" ] } }, { "database": { "id": "database", "client": "client", "databaseName": "test" } }, { "collection": { "id": "timeoutCollection", "database": "database", "collectionName": "timeoutColl" } } ] } }, { "name": "insertOne", "object": "timeoutCollection", "arguments": { "document": { "_id": 1 }, "timeoutMS": 100000 } }, { "name": "wait", "object": "testRunner", "arguments": { "ms": 1000 } }, { "name": "insertOne", "object": "timeoutCollection", "arguments": { "document": { "_id": 2 } } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "insert", "databaseName": "test", "command": { "insert": "timeoutColl" } } }, { "commandStartedEvent": { "commandName": "insert", "databaseName": "test", "command": { "insert": "timeoutColl", "maxTimeMS": { "$$lte": 450 } } } } ] } ] }, { "description": "command is not sent if RTT is greater than timeoutMS", "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": "alwaysOn", "data": { "failCommands": [ "hello", "isMaster" ], "appName": "rttTooHighTest", "blockConnection": true, "blockTimeMS": 50 } } } }, { "name": "createEntities", "object": "testRunner", "arguments": { "entities": [ { "client": { "id": "client", "useMultipleMongoses": false, "uriOptions": { "appName": "rttTooHighTest", "w": 1, "timeoutMS": 10, "heartbeatFrequencyMS": 500 }, "observeEvents": [ "commandStartedEvent" ] } }, { "database": { "id": "database", "client": "client", "databaseName": "test" } }, { "collection": { "id": "timeoutCollection", "database": "database", "collectionName": "timeoutColl" } } ] } }, { "name": "insertOne", "object": "timeoutCollection", "arguments": { "document": { "_id": 1 }, "timeoutMS": 100000 } }, { "name": "wait", "object": "testRunner", "arguments": { "ms": 1000 } }, { "name": "insertOne", "object": "timeoutCollection", "arguments": { "document": { "_id": 2 } }, "expectError": { "isTimeoutError": true } }, { "name": "insertOne", "object": "timeoutCollection", "arguments": { "document": { "_id": 3 } }, "expectError": { "isTimeoutError": true } }, { "name": "insertOne", "object": "timeoutCollection", "arguments": { "document": { "_id": 4 } }, "expectError": { "isTimeoutError": true } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "insert", "databaseName": "test", "command": { "insert": "timeoutColl" } } } ] } ] }, { "description": "short-circuit is not enabled with only 1 RTT measurement", "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": "alwaysOn", "data": { "failCommands": [ "hello", "isMaster" ], "appName": "reduceMaxTimeMSTest", "blockConnection": true, "blockTimeMS": 100 } } } }, { "name": "createEntities", "object": "testRunner", "arguments": { "entities": [ { "client": { "id": "client", "useMultipleMongoses": false, "uriOptions": { "appName": "reduceMaxTimeMSTest", "w": 1, "timeoutMS": 90, "heartbeatFrequencyMS": 100000 }, "observeEvents": [ "commandStartedEvent" ] } }, { "database": { "id": "database", "client": "client", "databaseName": "test" } }, { "collection": { "id": "timeoutCollection", "database": "database", "collectionName": "timeoutColl" } } ] } }, { "name": "insertOne", "object": "timeoutCollection", "arguments": { "document": { "_id": 1 }, "timeoutMS": 100000 } }, { "name": "insertOne", "object": "timeoutCollection", "arguments": { "document": { "_id": 2 } } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "insert", "databaseName": "test", "command": { "insert": "timeoutColl" } } }, { "commandStartedEvent": { "commandName": "insert", "databaseName": "test", "command": { "insert": "timeoutColl", "maxTimeMS": { "$$lte": 450 } } } } ] } ] } ] } mongodb-mongo-python-driver-509e9b7/test/csot/convenient-transactions.json000066400000000000000000000105231462766011000271360ustar00rootroot00000000000000{ "description": "timeoutMS behaves correctly for the withTransaction API", "schemaVersion": "1.9", "runOnRequirements": [ { "minServerVersion": "4.4", "topologies": [ "replicaset", "sharded-replicaset" ] } ], "createEntities": [ { "client": { "id": "failPointClient", "useMultipleMongoses": false } }, { "client": { "id": "client", "uriOptions": { "timeoutMS": 50 }, "useMultipleMongoses": false, "observeEvents": [ "commandStartedEvent" ] } }, { "database": { "id": "database", "client": "client", "databaseName": "test" } }, { "collection": { "id": "collection", "database": "database", "collectionName": "coll" } }, { "session": { "id": "session", "client": "client" } } ], "initialData": [ { "collectionName": "coll", "databaseName": "test", "documents": [] } ], "tests": [ { "description": "withTransaction raises a client-side error if timeoutMS is overridden inside the callback", "operations": [ { "name": "withTransaction", "object": "session", "arguments": { "callback": [ { "name": "insertOne", "object": "collection", "arguments": { "document": { "_id": 1 }, "session": "session", "timeoutMS": 100 }, "expectError": { "isClientError": true } } ] } } ], "expectEvents": [ { "client": "client", "events": [] } ] }, { "description": "timeoutMS is not refreshed for each operation in the callback", "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 2 }, "data": { "failCommands": [ "insert" ], "blockConnection": true, "blockTimeMS": 30 } } } }, { "name": "withTransaction", "object": "session", "arguments": { "callback": [ { "name": "insertOne", "object": "collection", "arguments": { "document": { "_id": 1 }, "session": "session" } }, { "name": "insertOne", "object": "collection", "arguments": { "document": { "_id": 2 }, "session": "session" }, "expectError": { "isTimeoutError": true } } ] }, "expectError": { "isTimeoutError": true } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "insert", "databaseName": "test", "command": { "insert": "coll", "maxTimeMS": { "$$type": [ "int", "long" ] } } } }, { "commandStartedEvent": { "commandName": "insert", "databaseName": "test", "command": { "insert": "coll", "maxTimeMS": { "$$type": [ "int", "long" ] } } } } ] } ] } ] } mongodb-mongo-python-driver-509e9b7/test/csot/cursors.json000066400000000000000000000050031462766011000237550ustar00rootroot00000000000000{ "description": "tests for timeoutMS behavior that applies to all cursor types", "schemaVersion": "1.0", "createEntities": [ { "client": { "id": "client" } }, { "database": { "id": "database", "client": "client", "databaseName": "test" } }, { "collection": { "id": "collection", "database": "database", "collectionName": "coll" } } ], "initialData": [ { "collectionName": "coll", "databaseName": "test", "documents": [] } ], "tests": [ { "description": "find errors if timeoutMode is set and timeoutMS is not", "operations": [ { "name": "find", "object": "collection", "arguments": { "filter": {}, "timeoutMode": "cursorLifetime" }, "expectError": { "isClientError": true } } ] }, { "description": "collection aggregate errors if timeoutMode is set and timeoutMS is not", "operations": [ { "name": "aggregate", "object": "collection", "arguments": { "pipeline": [], "timeoutMode": "cursorLifetime" }, "expectError": { "isClientError": true } } ] }, { "description": "database aggregate errors if timeoutMode is set and timeoutMS is not", "operations": [ { "name": "aggregate", "object": "database", "arguments": { "pipeline": [], "timeoutMode": "cursorLifetime" }, "expectError": { "isClientError": true } } ] }, { "description": "listCollections errors if timeoutMode is set and timeoutMS is not", "operations": [ { "name": "listCollections", "object": "database", "arguments": { "filter": {}, "timeoutMode": "cursorLifetime" }, "expectError": { "isClientError": true } } ] }, { "description": "listIndexes errors if timeoutMode is set and timeoutMS is not", "operations": [ { "name": "listIndexes", "object": "collection", "arguments": { "timeoutMode": "cursorLifetime" }, "expectError": { "isClientError": true } } ] } ] } mongodb-mongo-python-driver-509e9b7/test/csot/deprecated-options.json000066400000000000000000005530001462766011000260530ustar00rootroot00000000000000{ "description": "operations ignore deprecated timeout options if timeoutMS is set", "schemaVersion": "1.9", "runOnRequirements": [ { "minServerVersion": "4.2", "topologies": [ "replicaset", "sharded-replicaset" ] } ], "createEntities": [ { "client": { "id": "failPointClient", "useMultipleMongoses": false } } ], "initialData": [ { "collectionName": "coll", "databaseName": "test", "documents": [] } ], "tests": [ { "description": "commitTransaction ignores socketTimeoutMS if timeoutMS is set", "operations": [ { "name": "createEntities", "object": "testRunner", "arguments": { "entities": [ { "client": { "id": "client", "uriOptions": { "socketTimeoutMS": 20 }, "useMultipleMongoses": false, "observeEvents": [ "commandStartedEvent" ], "ignoreCommandMonitoringEvents": [ "aggregate" ] } }, { "database": { "id": "database", "client": "client", "databaseName": "test" } }, { "collection": { "id": "collection", "database": "database", "collectionName": "coll" } }, { "session": { "id": "session", "client": "client" } } ] } }, { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "commitTransaction" ], "blockConnection": true, "blockTimeMS": 5 } } } }, { "name": "startTransaction", "object": "session" }, { "name": "countDocuments", "object": "collection", "arguments": { "filter": {}, "session": "session" } }, { "name": "commitTransaction", "object": "session", "arguments": { "timeoutMS": 10000 } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "commitTransaction", "databaseName": "admin", "command": { "commitTransaction": 1, "writeConcern": { "$$exists": false }, "maxTimeMS": { "$$type": [ "int", "long" ] } } } } ] } ] }, { "description": "commitTransaction ignores wTimeoutMS if timeoutMS is set", "operations": [ { "name": "createEntities", "object": "testRunner", "arguments": { "entities": [ { "client": { "id": "client", "uriOptions": { "wTimeoutMS": 1 }, "observeEvents": [ "commandStartedEvent" ], "ignoreCommandMonitoringEvents": [ "aggregate" ] } }, { "database": { "id": "database", "client": "client", "databaseName": "test" } }, { "collection": { "id": "collection", "database": "database", "collectionName": "coll" } }, { "session": { "id": "session", "client": "client" } } ] } }, { "name": "startTransaction", "object": "session" }, { "name": "countDocuments", "object": "collection", "arguments": { "filter": {}, "session": "session" } }, { "name": "commitTransaction", "object": "session", "arguments": { "timeoutMS": 10000 } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "commitTransaction", "databaseName": "admin", "command": { "commitTransaction": 1, "writeConcern": { "$$exists": false }, "maxTimeMS": { "$$type": [ "int", "long" ] } } } } ] } ] }, { "description": "commitTransaction ignores maxCommitTimeMS if timeoutMS is set", "operations": [ { "name": "createEntities", "object": "testRunner", "arguments": { "entities": [ { "client": { "id": "client", "useMultipleMongoses": false, "observeEvents": [ "commandStartedEvent" ], "ignoreCommandMonitoringEvents": [ "aggregate" ] } }, { "database": { "id": "database", "client": "client", "databaseName": "test" } }, { "collection": { "id": "collection", "database": "database", "collectionName": "coll" } }, { "session": { "id": "session", "client": "client", "sessionOptions": { "defaultTransactionOptions": { "maxCommitTimeMS": 5000 } } } } ] } }, { "name": "startTransaction", "object": "session" }, { "name": "countDocuments", "object": "collection", "arguments": { "filter": {}, "session": "session" } }, { "name": "commitTransaction", "object": "session", "arguments": { "timeoutMS": 1000 } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "commitTransaction", "databaseName": "admin", "command": { "commitTransaction": 1, "maxTimeMS": { "$$lte": 1000 } } } } ] } ] }, { "description": "abortTransaction ignores socketTimeoutMS if timeoutMS is set", "operations": [ { "name": "createEntities", "object": "testRunner", "arguments": { "entities": [ { "client": { "id": "client", "uriOptions": { "socketTimeoutMS": 20 }, "useMultipleMongoses": false, "observeEvents": [ "commandStartedEvent" ], "ignoreCommandMonitoringEvents": [ "aggregate" ] } }, { "database": { "id": "database", "client": "client", "databaseName": "test" } }, { "collection": { "id": "collection", "database": "database", "collectionName": "coll" } }, { "session": { "id": "session", "client": "client" } } ] } }, { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "abortTransaction" ], "blockConnection": true, "blockTimeMS": 5 } } } }, { "name": "startTransaction", "object": "session" }, { "name": "countDocuments", "object": "collection", "arguments": { "filter": {}, "session": "session" } }, { "name": "abortTransaction", "object": "session", "arguments": { "timeoutMS": 10000 } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "abortTransaction", "databaseName": "admin", "command": { "abortTransaction": 1, "writeConcern": { "$$exists": false }, "maxTimeMS": { "$$type": [ "int", "long" ] } } } } ] } ] }, { "description": "abortTransaction ignores wTimeoutMS if timeoutMS is set", "operations": [ { "name": "createEntities", "object": "testRunner", "arguments": { "entities": [ { "client": { "id": "client", "uriOptions": { "wTimeoutMS": 1 }, "observeEvents": [ "commandStartedEvent" ], "ignoreCommandMonitoringEvents": [ "aggregate" ] } }, { "database": { "id": "database", "client": "client", "databaseName": "test" } }, { "collection": { "id": "collection", "database": "database", "collectionName": "coll" } }, { "session": { "id": "session", "client": "client" } } ] } }, { "name": "startTransaction", "object": "session" }, { "name": "countDocuments", "object": "collection", "arguments": { "filter": {}, "session": "session" } }, { "name": "abortTransaction", "object": "session", "arguments": { "timeoutMS": 10000 } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "abortTransaction", "databaseName": "admin", "command": { "abortTransaction": 1, "writeConcern": { "$$exists": false }, "maxTimeMS": { "$$type": [ "int", "long" ] } } } } ] } ] }, { "description": "withTransaction ignores socketTimeoutMS if timeoutMS is set", "operations": [ { "name": "createEntities", "object": "testRunner", "arguments": { "entities": [ { "client": { "id": "client", "uriOptions": { "socketTimeoutMS": 20 }, "useMultipleMongoses": false, "observeEvents": [ "commandStartedEvent" ] } }, { "database": { "id": "database", "client": "client", "databaseName": "test" } }, { "collection": { "id": "collection", "database": "database", "collectionName": "coll" } }, { "session": { "id": "session", "client": "client" } } ] } }, { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "commitTransaction" ], "blockConnection": true, "blockTimeMS": 5 } } } }, { "name": "withTransaction", "object": "session", "arguments": { "timeoutMS": 10000, "callback": [ { "name": "countDocuments", "object": "collection", "arguments": { "filter": {}, "session": "session" } } ] } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "aggregate", "databaseName": "test", "command": { "aggregate": "coll", "maxTimeMS": { "$$type": [ "int", "long" ] } } } }, { "commandStartedEvent": { "commandName": "commitTransaction", "databaseName": "admin", "command": { "commitTransaction": 1, "writeConcern": { "$$exists": false }, "maxTimeMS": { "$$type": [ "int", "long" ] } } } } ] } ] }, { "description": "withTransaction ignores wTimeoutMS if timeoutMS is set", "operations": [ { "name": "createEntities", "object": "testRunner", "arguments": { "entities": [ { "client": { "id": "client", "uriOptions": { "wTimeoutMS": 1 }, "observeEvents": [ "commandStartedEvent" ] } }, { "database": { "id": "database", "client": "client", "databaseName": "test" } }, { "collection": { "id": "collection", "database": "database", "collectionName": "coll" } }, { "session": { "id": "session", "client": "client" } } ] } }, { "name": "withTransaction", "object": "session", "arguments": { "timeoutMS": 10000, "callback": [ { "name": "countDocuments", "object": "collection", "arguments": { "filter": {}, "session": "session" } } ] } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "aggregate", "databaseName": "test", "command": { "aggregate": "coll", "writeConcern": { "$$exists": false }, "maxTimeMS": { "$$type": [ "int", "long" ] } } } }, { "commandStartedEvent": { "commandName": "commitTransaction", "databaseName": "admin", "command": { "commitTransaction": 1, "writeConcern": { "$$exists": false }, "maxTimeMS": { "$$type": [ "int", "long" ] } } } } ] } ] }, { "description": "withTransaction ignores maxCommitTimeMS if timeoutMS is set", "operations": [ { "name": "createEntities", "object": "testRunner", "arguments": { "entities": [ { "client": { "id": "client", "useMultipleMongoses": false, "observeEvents": [ "commandStartedEvent" ] } }, { "database": { "id": "database", "client": "client", "databaseName": "test" } }, { "collection": { "id": "collection", "database": "database", "collectionName": "coll" } }, { "session": { "id": "session", "client": "client", "sessionOptions": { "defaultTransactionOptions": { "maxCommitTimeMS": 5000 } } } } ] } }, { "name": "withTransaction", "object": "session", "arguments": { "timeoutMS": 1000, "callback": [ { "name": "countDocuments", "object": "collection", "arguments": { "filter": {}, "session": "session" } } ] } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "aggregate", "databaseName": "test", "command": { "aggregate": "coll", "writeConcern": { "$$exists": false }, "maxTimeMS": { "$$type": [ "int", "long" ] } } } }, { "commandStartedEvent": { "commandName": "commitTransaction", "databaseName": "admin", "command": { "commitTransaction": 1, "maxTimeMS": { "$$lte": 1000 } } } } ] } ] }, { "description": "socketTimeoutMS is ignored if timeoutMS is set - listDatabases on client", "operations": [ { "name": "createEntities", "object": "testRunner", "arguments": { "entities": [ { "client": { "id": "client", "uriOptions": { "socketTimeoutMS": 1 }, "useMultipleMongoses": false } }, { "database": { "id": "database", "client": "client", "databaseName": "test" } }, { "collection": { "id": "collection", "database": "database", "collectionName": "coll" } }, { "bucket": { "id": "bucket", "database": "database" } }, { "session": { "id": "session", "client": "client" } } ] } }, { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "listDatabases" ], "blockConnection": true, "blockTimeMS": 5 } } } }, { "name": "listDatabases", "object": "client", "arguments": { "timeoutMS": 100000, "filter": {} } } ] }, { "description": "wTimeoutMS is ignored if timeoutMS is set - listDatabases on client", "operations": [ { "name": "createEntities", "object": "testRunner", "arguments": { "entities": [ { "client": { "id": "client", "uriOptions": { "wTimeoutMS": 1 }, "observeEvents": [ "commandStartedEvent" ], "ignoreCommandMonitoringEvents": [ "killCursors" ] } }, { "database": { "id": "database", "client": "client", "databaseName": "test" } }, { "collection": { "id": "collection", "database": "database", "collectionName": "coll" } }, { "bucket": { "id": "bucket", "database": "database" } }, { "session": { "id": "session", "client": "client" } } ] } }, { "name": "listDatabases", "object": "client", "arguments": { "timeoutMS": 100000, "filter": {} } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "listDatabases", "databaseName": "admin", "command": { "listDatabases": 1, "writeConcern": { "$$exists": false }, "maxTimeMS": { "$$type": [ "int", "long" ] } } } } ] } ] }, { "description": "socketTimeoutMS is ignored if timeoutMS is set - listDatabaseNames on client", "operations": [ { "name": "createEntities", "object": "testRunner", "arguments": { "entities": [ { "client": { "id": "client", "uriOptions": { "socketTimeoutMS": 1 }, "useMultipleMongoses": false } }, { "database": { "id": "database", "client": "client", "databaseName": "test" } }, { "collection": { "id": "collection", "database": "database", "collectionName": "coll" } }, { "bucket": { "id": "bucket", "database": "database" } }, { "session": { "id": "session", "client": "client" } } ] } }, { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "listDatabases" ], "blockConnection": true, "blockTimeMS": 5 } } } }, { "name": "listDatabaseNames", "object": "client", "arguments": { "timeoutMS": 100000 } } ] }, { "description": "wTimeoutMS is ignored if timeoutMS is set - listDatabaseNames on client", "operations": [ { "name": "createEntities", "object": "testRunner", "arguments": { "entities": [ { "client": { "id": "client", "uriOptions": { "wTimeoutMS": 1 }, "observeEvents": [ "commandStartedEvent" ], "ignoreCommandMonitoringEvents": [ "killCursors" ] } }, { "database": { "id": "database", "client": "client", "databaseName": "test" } }, { "collection": { "id": "collection", "database": "database", "collectionName": "coll" } }, { "bucket": { "id": "bucket", "database": "database" } }, { "session": { "id": "session", "client": "client" } } ] } }, { "name": "listDatabaseNames", "object": "client", "arguments": { "timeoutMS": 100000 } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "listDatabases", "databaseName": "admin", "command": { "listDatabases": 1, "writeConcern": { "$$exists": false }, "maxTimeMS": { "$$type": [ "int", "long" ] } } } } ] } ] }, { "description": "socketTimeoutMS is ignored if timeoutMS is set - createChangeStream on client", "operations": [ { "name": "createEntities", "object": "testRunner", "arguments": { "entities": [ { "client": { "id": "client", "uriOptions": { "socketTimeoutMS": 1 }, "useMultipleMongoses": false } }, { "database": { "id": "database", "client": "client", "databaseName": "test" } }, { "collection": { "id": "collection", "database": "database", "collectionName": "coll" } }, { "bucket": { "id": "bucket", "database": "database" } }, { "session": { "id": "session", "client": "client" } } ] } }, { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "aggregate" ], "blockConnection": true, "blockTimeMS": 5 } } } }, { "name": "createChangeStream", "object": "client", "arguments": { "timeoutMS": 100000, "pipeline": [] } } ] }, { "description": "wTimeoutMS is ignored if timeoutMS is set - createChangeStream on client", "operations": [ { "name": "createEntities", "object": "testRunner", "arguments": { "entities": [ { "client": { "id": "client", "uriOptions": { "wTimeoutMS": 1 }, "observeEvents": [ "commandStartedEvent" ], "ignoreCommandMonitoringEvents": [ "killCursors" ] } }, { "database": { "id": "database", "client": "client", "databaseName": "test" } }, { "collection": { "id": "collection", "database": "database", "collectionName": "coll" } }, { "bucket": { "id": "bucket", "database": "database" } }, { "session": { "id": "session", "client": "client" } } ] } }, { "name": "createChangeStream", "object": "client", "arguments": { "timeoutMS": 100000, "pipeline": [] } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "aggregate", "databaseName": "admin", "command": { "aggregate": 1, "writeConcern": { "$$exists": false }, "maxTimeMS": { "$$type": [ "int", "long" ] } } } } ] } ] }, { "description": "socketTimeoutMS is ignored if timeoutMS is set - aggregate on database", "operations": [ { "name": "createEntities", "object": "testRunner", "arguments": { "entities": [ { "client": { "id": "client", "uriOptions": { "socketTimeoutMS": 1 }, "useMultipleMongoses": false } }, { "database": { "id": "database", "client": "client", "databaseName": "test" } }, { "collection": { "id": "collection", "database": "database", "collectionName": "coll" } }, { "bucket": { "id": "bucket", "database": "database" } }, { "session": { "id": "session", "client": "client" } } ] } }, { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "aggregate" ], "blockConnection": true, "blockTimeMS": 5 } } } }, { "name": "aggregate", "object": "database", "arguments": { "timeoutMS": 100000, "pipeline": [ { "$listLocalSessions": {} }, { "$limit": 1 } ] } } ] }, { "description": "wTimeoutMS is ignored if timeoutMS is set - aggregate on database", "operations": [ { "name": "createEntities", "object": "testRunner", "arguments": { "entities": [ { "client": { "id": "client", "uriOptions": { "wTimeoutMS": 1 }, "observeEvents": [ "commandStartedEvent" ], "ignoreCommandMonitoringEvents": [ "killCursors" ] } }, { "database": { "id": "database", "client": "client", "databaseName": "test" } }, { "collection": { "id": "collection", "database": "database", "collectionName": "coll" } }, { "bucket": { "id": "bucket", "database": "database" } }, { "session": { "id": "session", "client": "client" } } ] } }, { "name": "aggregate", "object": "database", "arguments": { "timeoutMS": 100000, "pipeline": [ { "$listLocalSessions": {} }, { "$limit": 1 } ] } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "aggregate", "databaseName": "test", "command": { "aggregate": 1, "writeConcern": { "$$exists": false }, "maxTimeMS": { "$$type": [ "int", "long" ] } } } } ] } ] }, { "description": "maxTimeMS is ignored if timeoutMS is set - aggregate on database", "operations": [ { "name": "createEntities", "object": "testRunner", "arguments": { "entities": [ { "client": { "id": "client", "useMultipleMongoses": false, "observeEvents": [ "commandStartedEvent" ], "ignoreCommandMonitoringEvents": [ "killCursors" ] } }, { "database": { "id": "database", "client": "client", "databaseName": "test" } }, { "collection": { "id": "collection", "database": "database", "collectionName": "coll" } }, { "bucket": { "id": "bucket", "database": "database" } }, { "session": { "id": "session", "client": "client" } } ] } }, { "name": "aggregate", "object": "database", "arguments": { "timeoutMS": 1000, "maxTimeMS": 5000, "pipeline": [ { "$listLocalSessions": {} }, { "$limit": 1 } ] } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "aggregate", "databaseName": "test", "command": { "aggregate": 1, "maxTimeMS": { "$$lte": 1000 } } } } ] } ] }, { "description": "socketTimeoutMS is ignored if timeoutMS is set - listCollections on database", "operations": [ { "name": "createEntities", "object": "testRunner", "arguments": { "entities": [ { "client": { "id": "client", "uriOptions": { "socketTimeoutMS": 1 }, "useMultipleMongoses": false } }, { "database": { "id": "database", "client": "client", "databaseName": "test" } }, { "collection": { "id": "collection", "database": "database", "collectionName": "coll" } }, { "bucket": { "id": "bucket", "database": "database" } }, { "session": { "id": "session", "client": "client" } } ] } }, { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "listCollections" ], "blockConnection": true, "blockTimeMS": 5 } } } }, { "name": "listCollections", "object": "database", "arguments": { "timeoutMS": 100000, "filter": {} } } ] }, { "description": "wTimeoutMS is ignored if timeoutMS is set - listCollections on database", "operations": [ { "name": "createEntities", "object": "testRunner", "arguments": { "entities": [ { "client": { "id": "client", "uriOptions": { "wTimeoutMS": 1 }, "observeEvents": [ "commandStartedEvent" ], "ignoreCommandMonitoringEvents": [ "killCursors" ] } }, { "database": { "id": "database", "client": "client", "databaseName": "test" } }, { "collection": { "id": "collection", "database": "database", "collectionName": "coll" } }, { "bucket": { "id": "bucket", "database": "database" } }, { "session": { "id": "session", "client": "client" } } ] } }, { "name": "listCollections", "object": "database", "arguments": { "timeoutMS": 100000, "filter": {} } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "listCollections", "databaseName": "test", "command": { "listCollections": 1, "writeConcern": { "$$exists": false }, "maxTimeMS": { "$$type": [ "int", "long" ] } } } } ] } ] }, { "description": "socketTimeoutMS is ignored if timeoutMS is set - listCollectionNames on database", "operations": [ { "name": "createEntities", "object": "testRunner", "arguments": { "entities": [ { "client": { "id": "client", "uriOptions": { "socketTimeoutMS": 1 }, "useMultipleMongoses": false } }, { "database": { "id": "database", "client": "client", "databaseName": "test" } }, { "collection": { "id": "collection", "database": "database", "collectionName": "coll" } }, { "bucket": { "id": "bucket", "database": "database" } }, { "session": { "id": "session", "client": "client" } } ] } }, { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "listCollections" ], "blockConnection": true, "blockTimeMS": 5 } } } }, { "name": "listCollectionNames", "object": "database", "arguments": { "timeoutMS": 100000, "filter": {} } } ] }, { "description": "wTimeoutMS is ignored if timeoutMS is set - listCollectionNames on database", "operations": [ { "name": "createEntities", "object": "testRunner", "arguments": { "entities": [ { "client": { "id": "client", "uriOptions": { "wTimeoutMS": 1 }, "observeEvents": [ "commandStartedEvent" ], "ignoreCommandMonitoringEvents": [ "killCursors" ] } }, { "database": { "id": "database", "client": "client", "databaseName": "test" } }, { "collection": { "id": "collection", "database": "database", "collectionName": "coll" } }, { "bucket": { "id": "bucket", "database": "database" } }, { "session": { "id": "session", "client": "client" } } ] } }, { "name": "listCollectionNames", "object": "database", "arguments": { "timeoutMS": 100000, "filter": {} } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "listCollections", "databaseName": "test", "command": { "listCollections": 1, "writeConcern": { "$$exists": false }, "maxTimeMS": { "$$type": [ "int", "long" ] } } } } ] } ] }, { "description": "socketTimeoutMS is ignored if timeoutMS is set - runCommand on database", "operations": [ { "name": "createEntities", "object": "testRunner", "arguments": { "entities": [ { "client": { "id": "client", "uriOptions": { "socketTimeoutMS": 1 }, "useMultipleMongoses": false } }, { "database": { "id": "database", "client": "client", "databaseName": "test" } }, { "collection": { "id": "collection", "database": "database", "collectionName": "coll" } }, { "bucket": { "id": "bucket", "database": "database" } }, { "session": { "id": "session", "client": "client" } } ] } }, { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "ping" ], "blockConnection": true, "blockTimeMS": 5 } } } }, { "name": "runCommand", "object": "database", "arguments": { "timeoutMS": 100000, "command": { "ping": 1 }, "commandName": "ping" } } ] }, { "description": "wTimeoutMS is ignored if timeoutMS is set - runCommand on database", "operations": [ { "name": "createEntities", "object": "testRunner", "arguments": { "entities": [ { "client": { "id": "client", "uriOptions": { "wTimeoutMS": 1 }, "observeEvents": [ "commandStartedEvent" ], "ignoreCommandMonitoringEvents": [ "killCursors" ] } }, { "database": { "id": "database", "client": "client", "databaseName": "test" } }, { "collection": { "id": "collection", "database": "database", "collectionName": "coll" } }, { "bucket": { "id": "bucket", "database": "database" } }, { "session": { "id": "session", "client": "client" } } ] } }, { "name": "runCommand", "object": "database", "arguments": { "timeoutMS": 100000, "command": { "ping": 1 }, "commandName": "ping" } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "ping", "databaseName": "test", "command": { "ping": 1, "writeConcern": { "$$exists": false }, "maxTimeMS": { "$$type": [ "int", "long" ] } } } } ] } ] }, { "description": "socketTimeoutMS is ignored if timeoutMS is set - createChangeStream on database", "operations": [ { "name": "createEntities", "object": "testRunner", "arguments": { "entities": [ { "client": { "id": "client", "uriOptions": { "socketTimeoutMS": 1 }, "useMultipleMongoses": false } }, { "database": { "id": "database", "client": "client", "databaseName": "test" } }, { "collection": { "id": "collection", "database": "database", "collectionName": "coll" } }, { "bucket": { "id": "bucket", "database": "database" } }, { "session": { "id": "session", "client": "client" } } ] } }, { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "aggregate" ], "blockConnection": true, "blockTimeMS": 5 } } } }, { "name": "createChangeStream", "object": "database", "arguments": { "timeoutMS": 100000, "pipeline": [] } } ] }, { "description": "wTimeoutMS is ignored if timeoutMS is set - createChangeStream on database", "operations": [ { "name": "createEntities", "object": "testRunner", "arguments": { "entities": [ { "client": { "id": "client", "uriOptions": { "wTimeoutMS": 1 }, "observeEvents": [ "commandStartedEvent" ], "ignoreCommandMonitoringEvents": [ "killCursors" ] } }, { "database": { "id": "database", "client": "client", "databaseName": "test" } }, { "collection": { "id": "collection", "database": "database", "collectionName": "coll" } }, { "bucket": { "id": "bucket", "database": "database" } }, { "session": { "id": "session", "client": "client" } } ] } }, { "name": "createChangeStream", "object": "database", "arguments": { "timeoutMS": 100000, "pipeline": [] } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "aggregate", "databaseName": "test", "command": { "aggregate": 1, "writeConcern": { "$$exists": false }, "maxTimeMS": { "$$type": [ "int", "long" ] } } } } ] } ] }, { "description": "socketTimeoutMS is ignored if timeoutMS is set - aggregate on collection", "operations": [ { "name": "createEntities", "object": "testRunner", "arguments": { "entities": [ { "client": { "id": "client", "uriOptions": { "socketTimeoutMS": 1 }, "useMultipleMongoses": false } }, { "database": { "id": "database", "client": "client", "databaseName": "test" } }, { "collection": { "id": "collection", "database": "database", "collectionName": "coll" } }, { "bucket": { "id": "bucket", "database": "database" } }, { "session": { "id": "session", "client": "client" } } ] } }, { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "aggregate" ], "blockConnection": true, "blockTimeMS": 5 } } } }, { "name": "aggregate", "object": "collection", "arguments": { "timeoutMS": 100000, "pipeline": [] } } ] }, { "description": "wTimeoutMS is ignored if timeoutMS is set - aggregate on collection", "operations": [ { "name": "createEntities", "object": "testRunner", "arguments": { "entities": [ { "client": { "id": "client", "uriOptions": { "wTimeoutMS": 1 }, "observeEvents": [ "commandStartedEvent" ], "ignoreCommandMonitoringEvents": [ "killCursors" ] } }, { "database": { "id": "database", "client": "client", "databaseName": "test" } }, { "collection": { "id": "collection", "database": "database", "collectionName": "coll" } }, { "bucket": { "id": "bucket", "database": "database" } }, { "session": { "id": "session", "client": "client" } } ] } }, { "name": "aggregate", "object": "collection", "arguments": { "timeoutMS": 100000, "pipeline": [] } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "aggregate", "databaseName": "test", "command": { "aggregate": "coll", "writeConcern": { "$$exists": false }, "maxTimeMS": { "$$type": [ "int", "long" ] } } } } ] } ] }, { "description": "maxTimeMS is ignored if timeoutMS is set - aggregate on collection", "operations": [ { "name": "createEntities", "object": "testRunner", "arguments": { "entities": [ { "client": { "id": "client", "useMultipleMongoses": false, "observeEvents": [ "commandStartedEvent" ], "ignoreCommandMonitoringEvents": [ "killCursors" ] } }, { "database": { "id": "database", "client": "client", "databaseName": "test" } }, { "collection": { "id": "collection", "database": "database", "collectionName": "coll" } }, { "bucket": { "id": "bucket", "database": "database" } }, { "session": { "id": "session", "client": "client" } } ] } }, { "name": "aggregate", "object": "collection", "arguments": { "timeoutMS": 1000, "maxTimeMS": 5000, "pipeline": [] } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "aggregate", "databaseName": "test", "command": { "aggregate": "coll", "maxTimeMS": { "$$lte": 1000 } } } } ] } ] }, { "description": "socketTimeoutMS is ignored if timeoutMS is set - count on collection", "operations": [ { "name": "createEntities", "object": "testRunner", "arguments": { "entities": [ { "client": { "id": "client", "uriOptions": { "socketTimeoutMS": 1 }, "useMultipleMongoses": false } }, { "database": { "id": "database", "client": "client", "databaseName": "test" } }, { "collection": { "id": "collection", "database": "database", "collectionName": "coll" } }, { "bucket": { "id": "bucket", "database": "database" } }, { "session": { "id": "session", "client": "client" } } ] } }, { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "count" ], "blockConnection": true, "blockTimeMS": 5 } } } }, { "name": "count", "object": "collection", "arguments": { "timeoutMS": 100000, "filter": {} } } ] }, { "description": "wTimeoutMS is ignored if timeoutMS is set - count on collection", "operations": [ { "name": "createEntities", "object": "testRunner", "arguments": { "entities": [ { "client": { "id": "client", "uriOptions": { "wTimeoutMS": 1 }, "observeEvents": [ "commandStartedEvent" ], "ignoreCommandMonitoringEvents": [ "killCursors" ] } }, { "database": { "id": "database", "client": "client", "databaseName": "test" } }, { "collection": { "id": "collection", "database": "database", "collectionName": "coll" } }, { "bucket": { "id": "bucket", "database": "database" } }, { "session": { "id": "session", "client": "client" } } ] } }, { "name": "count", "object": "collection", "arguments": { "timeoutMS": 100000, "filter": {} } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "count", "databaseName": "test", "command": { "count": "coll", "writeConcern": { "$$exists": false }, "maxTimeMS": { "$$type": [ "int", "long" ] } } } } ] } ] }, { "description": "maxTimeMS is ignored if timeoutMS is set - count on collection", "operations": [ { "name": "createEntities", "object": "testRunner", "arguments": { "entities": [ { "client": { "id": "client", "useMultipleMongoses": false, "observeEvents": [ "commandStartedEvent" ], "ignoreCommandMonitoringEvents": [ "killCursors" ] } }, { "database": { "id": "database", "client": "client", "databaseName": "test" } }, { "collection": { "id": "collection", "database": "database", "collectionName": "coll" } }, { "bucket": { "id": "bucket", "database": "database" } }, { "session": { "id": "session", "client": "client" } } ] } }, { "name": "count", "object": "collection", "arguments": { "timeoutMS": 1000, "maxTimeMS": 5000, "filter": {} } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "count", "databaseName": "test", "command": { "count": "coll", "maxTimeMS": { "$$lte": 1000 } } } } ] } ] }, { "description": "socketTimeoutMS is ignored if timeoutMS is set - countDocuments on collection", "operations": [ { "name": "createEntities", "object": "testRunner", "arguments": { "entities": [ { "client": { "id": "client", "uriOptions": { "socketTimeoutMS": 1 }, "useMultipleMongoses": false } }, { "database": { "id": "database", "client": "client", "databaseName": "test" } }, { "collection": { "id": "collection", "database": "database", "collectionName": "coll" } }, { "bucket": { "id": "bucket", "database": "database" } }, { "session": { "id": "session", "client": "client" } } ] } }, { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "aggregate" ], "blockConnection": true, "blockTimeMS": 5 } } } }, { "name": "countDocuments", "object": "collection", "arguments": { "timeoutMS": 100000, "filter": {} } } ] }, { "description": "wTimeoutMS is ignored if timeoutMS is set - countDocuments on collection", "operations": [ { "name": "createEntities", "object": "testRunner", "arguments": { "entities": [ { "client": { "id": "client", "uriOptions": { "wTimeoutMS": 1 }, "observeEvents": [ "commandStartedEvent" ], "ignoreCommandMonitoringEvents": [ "killCursors" ] } }, { "database": { "id": "database", "client": "client", "databaseName": "test" } }, { "collection": { "id": "collection", "database": "database", "collectionName": "coll" } }, { "bucket": { "id": "bucket", "database": "database" } }, { "session": { "id": "session", "client": "client" } } ] } }, { "name": "countDocuments", "object": "collection", "arguments": { "timeoutMS": 100000, "filter": {} } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "aggregate", "databaseName": "test", "command": { "aggregate": "coll", "writeConcern": { "$$exists": false }, "maxTimeMS": { "$$type": [ "int", "long" ] } } } } ] } ] }, { "description": "socketTimeoutMS is ignored if timeoutMS is set - estimatedDocumentCount on collection", "operations": [ { "name": "createEntities", "object": "testRunner", "arguments": { "entities": [ { "client": { "id": "client", "uriOptions": { "socketTimeoutMS": 1 }, "useMultipleMongoses": false } }, { "database": { "id": "database", "client": "client", "databaseName": "test" } }, { "collection": { "id": "collection", "database": "database", "collectionName": "coll" } }, { "bucket": { "id": "bucket", "database": "database" } }, { "session": { "id": "session", "client": "client" } } ] } }, { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "count" ], "blockConnection": true, "blockTimeMS": 5 } } } }, { "name": "estimatedDocumentCount", "object": "collection", "arguments": { "timeoutMS": 100000 } } ] }, { "description": "wTimeoutMS is ignored if timeoutMS is set - estimatedDocumentCount on collection", "operations": [ { "name": "createEntities", "object": "testRunner", "arguments": { "entities": [ { "client": { "id": "client", "uriOptions": { "wTimeoutMS": 1 }, "observeEvents": [ "commandStartedEvent" ], "ignoreCommandMonitoringEvents": [ "killCursors" ] } }, { "database": { "id": "database", "client": "client", "databaseName": "test" } }, { "collection": { "id": "collection", "database": "database", "collectionName": "coll" } }, { "bucket": { "id": "bucket", "database": "database" } }, { "session": { "id": "session", "client": "client" } } ] } }, { "name": "estimatedDocumentCount", "object": "collection", "arguments": { "timeoutMS": 100000 } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "count", "databaseName": "test", "command": { "count": "coll", "writeConcern": { "$$exists": false }, "maxTimeMS": { "$$type": [ "int", "long" ] } } } } ] } ] }, { "description": "maxTimeMS is ignored if timeoutMS is set - estimatedDocumentCount on collection", "operations": [ { "name": "createEntities", "object": "testRunner", "arguments": { "entities": [ { "client": { "id": "client", "useMultipleMongoses": false, "observeEvents": [ "commandStartedEvent" ], "ignoreCommandMonitoringEvents": [ "killCursors" ] } }, { "database": { "id": "database", "client": "client", "databaseName": "test" } }, { "collection": { "id": "collection", "database": "database", "collectionName": "coll" } }, { "bucket": { "id": "bucket", "database": "database" } }, { "session": { "id": "session", "client": "client" } } ] } }, { "name": "estimatedDocumentCount", "object": "collection", "arguments": { "timeoutMS": 1000, "maxTimeMS": 5000 } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "count", "databaseName": "test", "command": { "count": "coll", "maxTimeMS": { "$$lte": 1000 } } } } ] } ] }, { "description": "socketTimeoutMS is ignored if timeoutMS is set - distinct on collection", "operations": [ { "name": "createEntities", "object": "testRunner", "arguments": { "entities": [ { "client": { "id": "client", "uriOptions": { "socketTimeoutMS": 1 }, "useMultipleMongoses": false } }, { "database": { "id": "database", "client": "client", "databaseName": "test" } }, { "collection": { "id": "collection", "database": "database", "collectionName": "coll" } }, { "bucket": { "id": "bucket", "database": "database" } }, { "session": { "id": "session", "client": "client" } } ] } }, { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "distinct" ], "blockConnection": true, "blockTimeMS": 5 } } } }, { "name": "distinct", "object": "collection", "arguments": { "timeoutMS": 100000, "fieldName": "x", "filter": {} } } ] }, { "description": "wTimeoutMS is ignored if timeoutMS is set - distinct on collection", "operations": [ { "name": "createEntities", "object": "testRunner", "arguments": { "entities": [ { "client": { "id": "client", "uriOptions": { "wTimeoutMS": 1 }, "observeEvents": [ "commandStartedEvent" ], "ignoreCommandMonitoringEvents": [ "killCursors" ] } }, { "database": { "id": "database", "client": "client", "databaseName": "test" } }, { "collection": { "id": "collection", "database": "database", "collectionName": "coll" } }, { "bucket": { "id": "bucket", "database": "database" } }, { "session": { "id": "session", "client": "client" } } ] } }, { "name": "distinct", "object": "collection", "arguments": { "timeoutMS": 100000, "fieldName": "x", "filter": {} } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "distinct", "databaseName": "test", "command": { "distinct": "coll", "writeConcern": { "$$exists": false }, "maxTimeMS": { "$$type": [ "int", "long" ] } } } } ] } ] }, { "description": "maxTimeMS is ignored if timeoutMS is set - distinct on collection", "operations": [ { "name": "createEntities", "object": "testRunner", "arguments": { "entities": [ { "client": { "id": "client", "useMultipleMongoses": false, "observeEvents": [ "commandStartedEvent" ], "ignoreCommandMonitoringEvents": [ "killCursors" ] } }, { "database": { "id": "database", "client": "client", "databaseName": "test" } }, { "collection": { "id": "collection", "database": "database", "collectionName": "coll" } }, { "bucket": { "id": "bucket", "database": "database" } }, { "session": { "id": "session", "client": "client" } } ] } }, { "name": "distinct", "object": "collection", "arguments": { "timeoutMS": 1000, "maxTimeMS": 5000, "fieldName": "x", "filter": {} } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "distinct", "databaseName": "test", "command": { "distinct": "coll", "maxTimeMS": { "$$lte": 1000 } } } } ] } ] }, { "description": "socketTimeoutMS is ignored if timeoutMS is set - find on collection", "operations": [ { "name": "createEntities", "object": "testRunner", "arguments": { "entities": [ { "client": { "id": "client", "uriOptions": { "socketTimeoutMS": 1 }, "useMultipleMongoses": false } }, { "database": { "id": "database", "client": "client", "databaseName": "test" } }, { "collection": { "id": "collection", "database": "database", "collectionName": "coll" } }, { "bucket": { "id": "bucket", "database": "database" } }, { "session": { "id": "session", "client": "client" } } ] } }, { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "find" ], "blockConnection": true, "blockTimeMS": 5 } } } }, { "name": "find", "object": "collection", "arguments": { "timeoutMS": 100000, "filter": {} } } ] }, { "description": "wTimeoutMS is ignored if timeoutMS is set - find on collection", "operations": [ { "name": "createEntities", "object": "testRunner", "arguments": { "entities": [ { "client": { "id": "client", "uriOptions": { "wTimeoutMS": 1 }, "observeEvents": [ "commandStartedEvent" ], "ignoreCommandMonitoringEvents": [ "killCursors" ] } }, { "database": { "id": "database", "client": "client", "databaseName": "test" } }, { "collection": { "id": "collection", "database": "database", "collectionName": "coll" } }, { "bucket": { "id": "bucket", "database": "database" } }, { "session": { "id": "session", "client": "client" } } ] } }, { "name": "find", "object": "collection", "arguments": { "timeoutMS": 100000, "filter": {} } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "find", "databaseName": "test", "command": { "find": "coll", "writeConcern": { "$$exists": false }, "maxTimeMS": { "$$type": [ "int", "long" ] } } } } ] } ] }, { "description": "maxTimeMS is ignored if timeoutMS is set - find on collection", "operations": [ { "name": "createEntities", "object": "testRunner", "arguments": { "entities": [ { "client": { "id": "client", "useMultipleMongoses": false, "observeEvents": [ "commandStartedEvent" ], "ignoreCommandMonitoringEvents": [ "killCursors" ] } }, { "database": { "id": "database", "client": "client", "databaseName": "test" } }, { "collection": { "id": "collection", "database": "database", "collectionName": "coll" } }, { "bucket": { "id": "bucket", "database": "database" } }, { "session": { "id": "session", "client": "client" } } ] } }, { "name": "find", "object": "collection", "arguments": { "timeoutMS": 1000, "maxTimeMS": 5000, "filter": {} } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "find", "databaseName": "test", "command": { "find": "coll", "maxTimeMS": { "$$lte": 1000 } } } } ] } ] }, { "description": "socketTimeoutMS is ignored if timeoutMS is set - findOne on collection", "operations": [ { "name": "createEntities", "object": "testRunner", "arguments": { "entities": [ { "client": { "id": "client", "uriOptions": { "socketTimeoutMS": 1 }, "useMultipleMongoses": false } }, { "database": { "id": "database", "client": "client", "databaseName": "test" } }, { "collection": { "id": "collection", "database": "database", "collectionName": "coll" } }, { "bucket": { "id": "bucket", "database": "database" } }, { "session": { "id": "session", "client": "client" } } ] } }, { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "find" ], "blockConnection": true, "blockTimeMS": 5 } } } }, { "name": "findOne", "object": "collection", "arguments": { "timeoutMS": 100000, "filter": {} } } ] }, { "description": "wTimeoutMS is ignored if timeoutMS is set - findOne on collection", "operations": [ { "name": "createEntities", "object": "testRunner", "arguments": { "entities": [ { "client": { "id": "client", "uriOptions": { "wTimeoutMS": 1 }, "observeEvents": [ "commandStartedEvent" ], "ignoreCommandMonitoringEvents": [ "killCursors" ] } }, { "database": { "id": "database", "client": "client", "databaseName": "test" } }, { "collection": { "id": "collection", "database": "database", "collectionName": "coll" } }, { "bucket": { "id": "bucket", "database": "database" } }, { "session": { "id": "session", "client": "client" } } ] } }, { "name": "findOne", "object": "collection", "arguments": { "timeoutMS": 100000, "filter": {} } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "find", "databaseName": "test", "command": { "find": "coll", "writeConcern": { "$$exists": false }, "maxTimeMS": { "$$type": [ "int", "long" ] } } } } ] } ] }, { "description": "maxTimeMS is ignored if timeoutMS is set - findOne on collection", "operations": [ { "name": "createEntities", "object": "testRunner", "arguments": { "entities": [ { "client": { "id": "client", "useMultipleMongoses": false, "observeEvents": [ "commandStartedEvent" ], "ignoreCommandMonitoringEvents": [ "killCursors" ] } }, { "database": { "id": "database", "client": "client", "databaseName": "test" } }, { "collection": { "id": "collection", "database": "database", "collectionName": "coll" } }, { "bucket": { "id": "bucket", "database": "database" } }, { "session": { "id": "session", "client": "client" } } ] } }, { "name": "findOne", "object": "collection", "arguments": { "timeoutMS": 1000, "maxTimeMS": 5000, "filter": {} } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "find", "databaseName": "test", "command": { "find": "coll", "maxTimeMS": { "$$lte": 1000 } } } } ] } ] }, { "description": "socketTimeoutMS is ignored if timeoutMS is set - listIndexes on collection", "operations": [ { "name": "createEntities", "object": "testRunner", "arguments": { "entities": [ { "client": { "id": "client", "uriOptions": { "socketTimeoutMS": 1 }, "useMultipleMongoses": false } }, { "database": { "id": "database", "client": "client", "databaseName": "test" } }, { "collection": { "id": "collection", "database": "database", "collectionName": "coll" } }, { "bucket": { "id": "bucket", "database": "database" } }, { "session": { "id": "session", "client": "client" } } ] } }, { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "listIndexes" ], "blockConnection": true, "blockTimeMS": 5 } } } }, { "name": "listIndexes", "object": "collection", "arguments": { "timeoutMS": 100000 } } ] }, { "description": "wTimeoutMS is ignored if timeoutMS is set - listIndexes on collection", "operations": [ { "name": "createEntities", "object": "testRunner", "arguments": { "entities": [ { "client": { "id": "client", "uriOptions": { "wTimeoutMS": 1 }, "observeEvents": [ "commandStartedEvent" ], "ignoreCommandMonitoringEvents": [ "killCursors" ] } }, { "database": { "id": "database", "client": "client", "databaseName": "test" } }, { "collection": { "id": "collection", "database": "database", "collectionName": "coll" } }, { "bucket": { "id": "bucket", "database": "database" } }, { "session": { "id": "session", "client": "client" } } ] } }, { "name": "listIndexes", "object": "collection", "arguments": { "timeoutMS": 100000 } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "listIndexes", "databaseName": "test", "command": { "listIndexes": "coll", "writeConcern": { "$$exists": false }, "maxTimeMS": { "$$type": [ "int", "long" ] } } } } ] } ] }, { "description": "socketTimeoutMS is ignored if timeoutMS is set - listIndexNames on collection", "operations": [ { "name": "createEntities", "object": "testRunner", "arguments": { "entities": [ { "client": { "id": "client", "uriOptions": { "socketTimeoutMS": 1 }, "useMultipleMongoses": false } }, { "database": { "id": "database", "client": "client", "databaseName": "test" } }, { "collection": { "id": "collection", "database": "database", "collectionName": "coll" } }, { "bucket": { "id": "bucket", "database": "database" } }, { "session": { "id": "session", "client": "client" } } ] } }, { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "listIndexes" ], "blockConnection": true, "blockTimeMS": 5 } } } }, { "name": "listIndexNames", "object": "collection", "arguments": { "timeoutMS": 100000 } } ] }, { "description": "wTimeoutMS is ignored if timeoutMS is set - listIndexNames on collection", "operations": [ { "name": "createEntities", "object": "testRunner", "arguments": { "entities": [ { "client": { "id": "client", "uriOptions": { "wTimeoutMS": 1 }, "observeEvents": [ "commandStartedEvent" ], "ignoreCommandMonitoringEvents": [ "killCursors" ] } }, { "database": { "id": "database", "client": "client", "databaseName": "test" } }, { "collection": { "id": "collection", "database": "database", "collectionName": "coll" } }, { "bucket": { "id": "bucket", "database": "database" } }, { "session": { "id": "session", "client": "client" } } ] } }, { "name": "listIndexNames", "object": "collection", "arguments": { "timeoutMS": 100000 } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "listIndexes", "databaseName": "test", "command": { "listIndexes": "coll", "writeConcern": { "$$exists": false }, "maxTimeMS": { "$$type": [ "int", "long" ] } } } } ] } ] }, { "description": "socketTimeoutMS is ignored if timeoutMS is set - createChangeStream on collection", "operations": [ { "name": "createEntities", "object": "testRunner", "arguments": { "entities": [ { "client": { "id": "client", "uriOptions": { "socketTimeoutMS": 1 }, "useMultipleMongoses": false } }, { "database": { "id": "database", "client": "client", "databaseName": "test" } }, { "collection": { "id": "collection", "database": "database", "collectionName": "coll" } }, { "bucket": { "id": "bucket", "database": "database" } }, { "session": { "id": "session", "client": "client" } } ] } }, { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "aggregate" ], "blockConnection": true, "blockTimeMS": 5 } } } }, { "name": "createChangeStream", "object": "collection", "arguments": { "timeoutMS": 100000, "pipeline": [] } } ] }, { "description": "wTimeoutMS is ignored if timeoutMS is set - createChangeStream on collection", "operations": [ { "name": "createEntities", "object": "testRunner", "arguments": { "entities": [ { "client": { "id": "client", "uriOptions": { "wTimeoutMS": 1 }, "observeEvents": [ "commandStartedEvent" ], "ignoreCommandMonitoringEvents": [ "killCursors" ] } }, { "database": { "id": "database", "client": "client", "databaseName": "test" } }, { "collection": { "id": "collection", "database": "database", "collectionName": "coll" } }, { "bucket": { "id": "bucket", "database": "database" } }, { "session": { "id": "session", "client": "client" } } ] } }, { "name": "createChangeStream", "object": "collection", "arguments": { "timeoutMS": 100000, "pipeline": [] } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "aggregate", "databaseName": "test", "command": { "aggregate": "coll", "writeConcern": { "$$exists": false }, "maxTimeMS": { "$$type": [ "int", "long" ] } } } } ] } ] }, { "description": "socketTimeoutMS is ignored if timeoutMS is set - insertOne on collection", "operations": [ { "name": "createEntities", "object": "testRunner", "arguments": { "entities": [ { "client": { "id": "client", "uriOptions": { "socketTimeoutMS": 1 }, "useMultipleMongoses": false } }, { "database": { "id": "database", "client": "client", "databaseName": "test" } }, { "collection": { "id": "collection", "database": "database", "collectionName": "coll" } }, { "bucket": { "id": "bucket", "database": "database" } }, { "session": { "id": "session", "client": "client" } } ] } }, { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "insert" ], "blockConnection": true, "blockTimeMS": 5 } } } }, { "name": "insertOne", "object": "collection", "arguments": { "timeoutMS": 100000, "document": { "x": 1 } } } ] }, { "description": "wTimeoutMS is ignored if timeoutMS is set - insertOne on collection", "operations": [ { "name": "createEntities", "object": "testRunner", "arguments": { "entities": [ { "client": { "id": "client", "uriOptions": { "wTimeoutMS": 1 }, "observeEvents": [ "commandStartedEvent" ], "ignoreCommandMonitoringEvents": [ "killCursors" ] } }, { "database": { "id": "database", "client": "client", "databaseName": "test" } }, { "collection": { "id": "collection", "database": "database", "collectionName": "coll" } }, { "bucket": { "id": "bucket", "database": "database" } }, { "session": { "id": "session", "client": "client" } } ] } }, { "name": "insertOne", "object": "collection", "arguments": { "timeoutMS": 100000, "document": { "x": 1 } } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "insert", "databaseName": "test", "command": { "insert": "coll", "writeConcern": { "$$exists": false }, "maxTimeMS": { "$$type": [ "int", "long" ] } } } } ] } ] }, { "description": "socketTimeoutMS is ignored if timeoutMS is set - insertMany on collection", "operations": [ { "name": "createEntities", "object": "testRunner", "arguments": { "entities": [ { "client": { "id": "client", "uriOptions": { "socketTimeoutMS": 1 }, "useMultipleMongoses": false } }, { "database": { "id": "database", "client": "client", "databaseName": "test" } }, { "collection": { "id": "collection", "database": "database", "collectionName": "coll" } }, { "bucket": { "id": "bucket", "database": "database" } }, { "session": { "id": "session", "client": "client" } } ] } }, { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "insert" ], "blockConnection": true, "blockTimeMS": 5 } } } }, { "name": "insertMany", "object": "collection", "arguments": { "timeoutMS": 100000, "documents": [ { "x": 1 } ] } } ] }, { "description": "wTimeoutMS is ignored if timeoutMS is set - insertMany on collection", "operations": [ { "name": "createEntities", "object": "testRunner", "arguments": { "entities": [ { "client": { "id": "client", "uriOptions": { "wTimeoutMS": 1 }, "observeEvents": [ "commandStartedEvent" ], "ignoreCommandMonitoringEvents": [ "killCursors" ] } }, { "database": { "id": "database", "client": "client", "databaseName": "test" } }, { "collection": { "id": "collection", "database": "database", "collectionName": "coll" } }, { "bucket": { "id": "bucket", "database": "database" } }, { "session": { "id": "session", "client": "client" } } ] } }, { "name": "insertMany", "object": "collection", "arguments": { "timeoutMS": 100000, "documents": [ { "x": 1 } ] } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "insert", "databaseName": "test", "command": { "insert": "coll", "writeConcern": { "$$exists": false }, "maxTimeMS": { "$$type": [ "int", "long" ] } } } } ] } ] }, { "description": "socketTimeoutMS is ignored if timeoutMS is set - deleteOne on collection", "operations": [ { "name": "createEntities", "object": "testRunner", "arguments": { "entities": [ { "client": { "id": "client", "uriOptions": { "socketTimeoutMS": 1 }, "useMultipleMongoses": false } }, { "database": { "id": "database", "client": "client", "databaseName": "test" } }, { "collection": { "id": "collection", "database": "database", "collectionName": "coll" } }, { "bucket": { "id": "bucket", "database": "database" } }, { "session": { "id": "session", "client": "client" } } ] } }, { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "delete" ], "blockConnection": true, "blockTimeMS": 5 } } } }, { "name": "deleteOne", "object": "collection", "arguments": { "timeoutMS": 100000, "filter": {} } } ] }, { "description": "wTimeoutMS is ignored if timeoutMS is set - deleteOne on collection", "operations": [ { "name": "createEntities", "object": "testRunner", "arguments": { "entities": [ { "client": { "id": "client", "uriOptions": { "wTimeoutMS": 1 }, "observeEvents": [ "commandStartedEvent" ], "ignoreCommandMonitoringEvents": [ "killCursors" ] } }, { "database": { "id": "database", "client": "client", "databaseName": "test" } }, { "collection": { "id": "collection", "database": "database", "collectionName": "coll" } }, { "bucket": { "id": "bucket", "database": "database" } }, { "session": { "id": "session", "client": "client" } } ] } }, { "name": "deleteOne", "object": "collection", "arguments": { "timeoutMS": 100000, "filter": {} } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "delete", "databaseName": "test", "command": { "delete": "coll", "writeConcern": { "$$exists": false }, "maxTimeMS": { "$$type": [ "int", "long" ] } } } } ] } ] }, { "description": "socketTimeoutMS is ignored if timeoutMS is set - deleteMany on collection", "operations": [ { "name": "createEntities", "object": "testRunner", "arguments": { "entities": [ { "client": { "id": "client", "uriOptions": { "socketTimeoutMS": 1 }, "useMultipleMongoses": false } }, { "database": { "id": "database", "client": "client", "databaseName": "test" } }, { "collection": { "id": "collection", "database": "database", "collectionName": "coll" } }, { "bucket": { "id": "bucket", "database": "database" } }, { "session": { "id": "session", "client": "client" } } ] } }, { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "delete" ], "blockConnection": true, "blockTimeMS": 5 } } } }, { "name": "deleteMany", "object": "collection", "arguments": { "timeoutMS": 100000, "filter": {} } } ] }, { "description": "wTimeoutMS is ignored if timeoutMS is set - deleteMany on collection", "operations": [ { "name": "createEntities", "object": "testRunner", "arguments": { "entities": [ { "client": { "id": "client", "uriOptions": { "wTimeoutMS": 1 }, "observeEvents": [ "commandStartedEvent" ], "ignoreCommandMonitoringEvents": [ "killCursors" ] } }, { "database": { "id": "database", "client": "client", "databaseName": "test" } }, { "collection": { "id": "collection", "database": "database", "collectionName": "coll" } }, { "bucket": { "id": "bucket", "database": "database" } }, { "session": { "id": "session", "client": "client" } } ] } }, { "name": "deleteMany", "object": "collection", "arguments": { "timeoutMS": 100000, "filter": {} } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "delete", "databaseName": "test", "command": { "delete": "coll", "writeConcern": { "$$exists": false }, "maxTimeMS": { "$$type": [ "int", "long" ] } } } } ] } ] }, { "description": "socketTimeoutMS is ignored if timeoutMS is set - replaceOne on collection", "operations": [ { "name": "createEntities", "object": "testRunner", "arguments": { "entities": [ { "client": { "id": "client", "uriOptions": { "socketTimeoutMS": 1 }, "useMultipleMongoses": false } }, { "database": { "id": "database", "client": "client", "databaseName": "test" } }, { "collection": { "id": "collection", "database": "database", "collectionName": "coll" } }, { "bucket": { "id": "bucket", "database": "database" } }, { "session": { "id": "session", "client": "client" } } ] } }, { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "update" ], "blockConnection": true, "blockTimeMS": 5 } } } }, { "name": "replaceOne", "object": "collection", "arguments": { "timeoutMS": 100000, "filter": {}, "replacement": { "x": 1 } } } ] }, { "description": "wTimeoutMS is ignored if timeoutMS is set - replaceOne on collection", "operations": [ { "name": "createEntities", "object": "testRunner", "arguments": { "entities": [ { "client": { "id": "client", "uriOptions": { "wTimeoutMS": 1 }, "observeEvents": [ "commandStartedEvent" ], "ignoreCommandMonitoringEvents": [ "killCursors" ] } }, { "database": { "id": "database", "client": "client", "databaseName": "test" } }, { "collection": { "id": "collection", "database": "database", "collectionName": "coll" } }, { "bucket": { "id": "bucket", "database": "database" } }, { "session": { "id": "session", "client": "client" } } ] } }, { "name": "replaceOne", "object": "collection", "arguments": { "timeoutMS": 100000, "filter": {}, "replacement": { "x": 1 } } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "update", "databaseName": "test", "command": { "update": "coll", "writeConcern": { "$$exists": false }, "maxTimeMS": { "$$type": [ "int", "long" ] } } } } ] } ] }, { "description": "socketTimeoutMS is ignored if timeoutMS is set - updateOne on collection", "operations": [ { "name": "createEntities", "object": "testRunner", "arguments": { "entities": [ { "client": { "id": "client", "uriOptions": { "socketTimeoutMS": 1 }, "useMultipleMongoses": false } }, { "database": { "id": "database", "client": "client", "databaseName": "test" } }, { "collection": { "id": "collection", "database": "database", "collectionName": "coll" } }, { "bucket": { "id": "bucket", "database": "database" } }, { "session": { "id": "session", "client": "client" } } ] } }, { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "update" ], "blockConnection": true, "blockTimeMS": 5 } } } }, { "name": "updateOne", "object": "collection", "arguments": { "timeoutMS": 100000, "filter": {}, "update": { "$set": { "x": 1 } } } } ] }, { "description": "wTimeoutMS is ignored if timeoutMS is set - updateOne on collection", "operations": [ { "name": "createEntities", "object": "testRunner", "arguments": { "entities": [ { "client": { "id": "client", "uriOptions": { "wTimeoutMS": 1 }, "observeEvents": [ "commandStartedEvent" ], "ignoreCommandMonitoringEvents": [ "killCursors" ] } }, { "database": { "id": "database", "client": "client", "databaseName": "test" } }, { "collection": { "id": "collection", "database": "database", "collectionName": "coll" } }, { "bucket": { "id": "bucket", "database": "database" } }, { "session": { "id": "session", "client": "client" } } ] } }, { "name": "updateOne", "object": "collection", "arguments": { "timeoutMS": 100000, "filter": {}, "update": { "$set": { "x": 1 } } } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "update", "databaseName": "test", "command": { "update": "coll", "writeConcern": { "$$exists": false }, "maxTimeMS": { "$$type": [ "int", "long" ] } } } } ] } ] }, { "description": "socketTimeoutMS is ignored if timeoutMS is set - updateMany on collection", "operations": [ { "name": "createEntities", "object": "testRunner", "arguments": { "entities": [ { "client": { "id": "client", "uriOptions": { "socketTimeoutMS": 1 }, "useMultipleMongoses": false } }, { "database": { "id": "database", "client": "client", "databaseName": "test" } }, { "collection": { "id": "collection", "database": "database", "collectionName": "coll" } }, { "bucket": { "id": "bucket", "database": "database" } }, { "session": { "id": "session", "client": "client" } } ] } }, { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "update" ], "blockConnection": true, "blockTimeMS": 5 } } } }, { "name": "updateMany", "object": "collection", "arguments": { "timeoutMS": 100000, "filter": {}, "update": { "$set": { "x": 1 } } } } ] }, { "description": "wTimeoutMS is ignored if timeoutMS is set - updateMany on collection", "operations": [ { "name": "createEntities", "object": "testRunner", "arguments": { "entities": [ { "client": { "id": "client", "uriOptions": { "wTimeoutMS": 1 }, "observeEvents": [ "commandStartedEvent" ], "ignoreCommandMonitoringEvents": [ "killCursors" ] } }, { "database": { "id": "database", "client": "client", "databaseName": "test" } }, { "collection": { "id": "collection", "database": "database", "collectionName": "coll" } }, { "bucket": { "id": "bucket", "database": "database" } }, { "session": { "id": "session", "client": "client" } } ] } }, { "name": "updateMany", "object": "collection", "arguments": { "timeoutMS": 100000, "filter": {}, "update": { "$set": { "x": 1 } } } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "update", "databaseName": "test", "command": { "update": "coll", "writeConcern": { "$$exists": false }, "maxTimeMS": { "$$type": [ "int", "long" ] } } } } ] } ] }, { "description": "socketTimeoutMS is ignored if timeoutMS is set - findOneAndDelete on collection", "operations": [ { "name": "createEntities", "object": "testRunner", "arguments": { "entities": [ { "client": { "id": "client", "uriOptions": { "socketTimeoutMS": 1 }, "useMultipleMongoses": false } }, { "database": { "id": "database", "client": "client", "databaseName": "test" } }, { "collection": { "id": "collection", "database": "database", "collectionName": "coll" } }, { "bucket": { "id": "bucket", "database": "database" } }, { "session": { "id": "session", "client": "client" } } ] } }, { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "findAndModify" ], "blockConnection": true, "blockTimeMS": 5 } } } }, { "name": "findOneAndDelete", "object": "collection", "arguments": { "timeoutMS": 100000, "filter": {} } } ] }, { "description": "wTimeoutMS is ignored if timeoutMS is set - findOneAndDelete on collection", "operations": [ { "name": "createEntities", "object": "testRunner", "arguments": { "entities": [ { "client": { "id": "client", "uriOptions": { "wTimeoutMS": 1 }, "observeEvents": [ "commandStartedEvent" ], "ignoreCommandMonitoringEvents": [ "killCursors" ] } }, { "database": { "id": "database", "client": "client", "databaseName": "test" } }, { "collection": { "id": "collection", "database": "database", "collectionName": "coll" } }, { "bucket": { "id": "bucket", "database": "database" } }, { "session": { "id": "session", "client": "client" } } ] } }, { "name": "findOneAndDelete", "object": "collection", "arguments": { "timeoutMS": 100000, "filter": {} } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "findAndModify", "databaseName": "test", "command": { "findAndModify": "coll", "writeConcern": { "$$exists": false }, "maxTimeMS": { "$$type": [ "int", "long" ] } } } } ] } ] }, { "description": "maxTimeMS is ignored if timeoutMS is set - findOneAndDelete on collection", "operations": [ { "name": "createEntities", "object": "testRunner", "arguments": { "entities": [ { "client": { "id": "client", "useMultipleMongoses": false, "observeEvents": [ "commandStartedEvent" ], "ignoreCommandMonitoringEvents": [ "killCursors" ] } }, { "database": { "id": "database", "client": "client", "databaseName": "test" } }, { "collection": { "id": "collection", "database": "database", "collectionName": "coll" } }, { "bucket": { "id": "bucket", "database": "database" } }, { "session": { "id": "session", "client": "client" } } ] } }, { "name": "findOneAndDelete", "object": "collection", "arguments": { "timeoutMS": 1000, "maxTimeMS": 5000, "filter": {} } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "findAndModify", "databaseName": "test", "command": { "findAndModify": "coll", "maxTimeMS": { "$$lte": 1000 } } } } ] } ] }, { "description": "socketTimeoutMS is ignored if timeoutMS is set - findOneAndReplace on collection", "operations": [ { "name": "createEntities", "object": "testRunner", "arguments": { "entities": [ { "client": { "id": "client", "uriOptions": { "socketTimeoutMS": 1 }, "useMultipleMongoses": false } }, { "database": { "id": "database", "client": "client", "databaseName": "test" } }, { "collection": { "id": "collection", "database": "database", "collectionName": "coll" } }, { "bucket": { "id": "bucket", "database": "database" } }, { "session": { "id": "session", "client": "client" } } ] } }, { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "findAndModify" ], "blockConnection": true, "blockTimeMS": 5 } } } }, { "name": "findOneAndReplace", "object": "collection", "arguments": { "timeoutMS": 100000, "filter": {}, "replacement": { "x": 1 } } } ] }, { "description": "wTimeoutMS is ignored if timeoutMS is set - findOneAndReplace on collection", "operations": [ { "name": "createEntities", "object": "testRunner", "arguments": { "entities": [ { "client": { "id": "client", "uriOptions": { "wTimeoutMS": 1 }, "observeEvents": [ "commandStartedEvent" ], "ignoreCommandMonitoringEvents": [ "killCursors" ] } }, { "database": { "id": "database", "client": "client", "databaseName": "test" } }, { "collection": { "id": "collection", "database": "database", "collectionName": "coll" } }, { "bucket": { "id": "bucket", "database": "database" } }, { "session": { "id": "session", "client": "client" } } ] } }, { "name": "findOneAndReplace", "object": "collection", "arguments": { "timeoutMS": 100000, "filter": {}, "replacement": { "x": 1 } } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "findAndModify", "databaseName": "test", "command": { "findAndModify": "coll", "writeConcern": { "$$exists": false }, "maxTimeMS": { "$$type": [ "int", "long" ] } } } } ] } ] }, { "description": "maxTimeMS is ignored if timeoutMS is set - findOneAndReplace on collection", "operations": [ { "name": "createEntities", "object": "testRunner", "arguments": { "entities": [ { "client": { "id": "client", "useMultipleMongoses": false, "observeEvents": [ "commandStartedEvent" ], "ignoreCommandMonitoringEvents": [ "killCursors" ] } }, { "database": { "id": "database", "client": "client", "databaseName": "test" } }, { "collection": { "id": "collection", "database": "database", "collectionName": "coll" } }, { "bucket": { "id": "bucket", "database": "database" } }, { "session": { "id": "session", "client": "client" } } ] } }, { "name": "findOneAndReplace", "object": "collection", "arguments": { "timeoutMS": 1000, "maxTimeMS": 5000, "filter": {}, "replacement": { "x": 1 } } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "findAndModify", "databaseName": "test", "command": { "findAndModify": "coll", "maxTimeMS": { "$$lte": 1000 } } } } ] } ] }, { "description": "socketTimeoutMS is ignored if timeoutMS is set - findOneAndUpdate on collection", "operations": [ { "name": "createEntities", "object": "testRunner", "arguments": { "entities": [ { "client": { "id": "client", "uriOptions": { "socketTimeoutMS": 1 }, "useMultipleMongoses": false } }, { "database": { "id": "database", "client": "client", "databaseName": "test" } }, { "collection": { "id": "collection", "database": "database", "collectionName": "coll" } }, { "bucket": { "id": "bucket", "database": "database" } }, { "session": { "id": "session", "client": "client" } } ] } }, { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "findAndModify" ], "blockConnection": true, "blockTimeMS": 5 } } } }, { "name": "findOneAndUpdate", "object": "collection", "arguments": { "timeoutMS": 100000, "filter": {}, "update": { "$set": { "x": 1 } } } } ] }, { "description": "wTimeoutMS is ignored if timeoutMS is set - findOneAndUpdate on collection", "operations": [ { "name": "createEntities", "object": "testRunner", "arguments": { "entities": [ { "client": { "id": "client", "uriOptions": { "wTimeoutMS": 1 }, "observeEvents": [ "commandStartedEvent" ], "ignoreCommandMonitoringEvents": [ "killCursors" ] } }, { "database": { "id": "database", "client": "client", "databaseName": "test" } }, { "collection": { "id": "collection", "database": "database", "collectionName": "coll" } }, { "bucket": { "id": "bucket", "database": "database" } }, { "session": { "id": "session", "client": "client" } } ] } }, { "name": "findOneAndUpdate", "object": "collection", "arguments": { "timeoutMS": 100000, "filter": {}, "update": { "$set": { "x": 1 } } } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "findAndModify", "databaseName": "test", "command": { "findAndModify": "coll", "writeConcern": { "$$exists": false }, "maxTimeMS": { "$$type": [ "int", "long" ] } } } } ] } ] }, { "description": "maxTimeMS is ignored if timeoutMS is set - findOneAndUpdate on collection", "operations": [ { "name": "createEntities", "object": "testRunner", "arguments": { "entities": [ { "client": { "id": "client", "useMultipleMongoses": false, "observeEvents": [ "commandStartedEvent" ], "ignoreCommandMonitoringEvents": [ "killCursors" ] } }, { "database": { "id": "database", "client": "client", "databaseName": "test" } }, { "collection": { "id": "collection", "database": "database", "collectionName": "coll" } }, { "bucket": { "id": "bucket", "database": "database" } }, { "session": { "id": "session", "client": "client" } } ] } }, { "name": "findOneAndUpdate", "object": "collection", "arguments": { "timeoutMS": 1000, "maxTimeMS": 5000, "filter": {}, "update": { "$set": { "x": 1 } } } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "findAndModify", "databaseName": "test", "command": { "findAndModify": "coll", "maxTimeMS": { "$$lte": 1000 } } } } ] } ] }, { "description": "socketTimeoutMS is ignored if timeoutMS is set - bulkWrite on collection", "operations": [ { "name": "createEntities", "object": "testRunner", "arguments": { "entities": [ { "client": { "id": "client", "uriOptions": { "socketTimeoutMS": 1 }, "useMultipleMongoses": false } }, { "database": { "id": "database", "client": "client", "databaseName": "test" } }, { "collection": { "id": "collection", "database": "database", "collectionName": "coll" } }, { "bucket": { "id": "bucket", "database": "database" } }, { "session": { "id": "session", "client": "client" } } ] } }, { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "insert" ], "blockConnection": true, "blockTimeMS": 5 } } } }, { "name": "bulkWrite", "object": "collection", "arguments": { "timeoutMS": 100000, "requests": [ { "insertOne": { "document": { "_id": 1 } } } ] } } ] }, { "description": "wTimeoutMS is ignored if timeoutMS is set - bulkWrite on collection", "operations": [ { "name": "createEntities", "object": "testRunner", "arguments": { "entities": [ { "client": { "id": "client", "uriOptions": { "wTimeoutMS": 1 }, "observeEvents": [ "commandStartedEvent" ], "ignoreCommandMonitoringEvents": [ "killCursors" ] } }, { "database": { "id": "database", "client": "client", "databaseName": "test" } }, { "collection": { "id": "collection", "database": "database", "collectionName": "coll" } }, { "bucket": { "id": "bucket", "database": "database" } }, { "session": { "id": "session", "client": "client" } } ] } }, { "name": "bulkWrite", "object": "collection", "arguments": { "timeoutMS": 100000, "requests": [ { "insertOne": { "document": { "_id": 1 } } } ] } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "insert", "databaseName": "test", "command": { "insert": "coll", "writeConcern": { "$$exists": false }, "maxTimeMS": { "$$type": [ "int", "long" ] } } } } ] } ] }, { "description": "socketTimeoutMS is ignored if timeoutMS is set - createIndex on collection", "operations": [ { "name": "createEntities", "object": "testRunner", "arguments": { "entities": [ { "client": { "id": "client", "uriOptions": { "socketTimeoutMS": 1 }, "useMultipleMongoses": false } }, { "database": { "id": "database", "client": "client", "databaseName": "test" } }, { "collection": { "id": "collection", "database": "database", "collectionName": "coll" } }, { "bucket": { "id": "bucket", "database": "database" } }, { "session": { "id": "session", "client": "client" } } ] } }, { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "createIndexes" ], "blockConnection": true, "blockTimeMS": 5 } } } }, { "name": "createIndex", "object": "collection", "arguments": { "timeoutMS": 100000, "keys": { "x": 1 }, "name": "x_1" } } ] }, { "description": "wTimeoutMS is ignored if timeoutMS is set - createIndex on collection", "operations": [ { "name": "createEntities", "object": "testRunner", "arguments": { "entities": [ { "client": { "id": "client", "uriOptions": { "wTimeoutMS": 1 }, "observeEvents": [ "commandStartedEvent" ], "ignoreCommandMonitoringEvents": [ "killCursors" ] } }, { "database": { "id": "database", "client": "client", "databaseName": "test" } }, { "collection": { "id": "collection", "database": "database", "collectionName": "coll" } }, { "bucket": { "id": "bucket", "database": "database" } }, { "session": { "id": "session", "client": "client" } } ] } }, { "name": "createIndex", "object": "collection", "arguments": { "timeoutMS": 100000, "keys": { "x": 1 }, "name": "x_1" } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "createIndexes", "databaseName": "test", "command": { "createIndexes": "coll", "writeConcern": { "$$exists": false }, "maxTimeMS": { "$$type": [ "int", "long" ] } } } } ] } ] }, { "description": "maxTimeMS is ignored if timeoutMS is set - createIndex on collection", "operations": [ { "name": "createEntities", "object": "testRunner", "arguments": { "entities": [ { "client": { "id": "client", "useMultipleMongoses": false, "observeEvents": [ "commandStartedEvent" ], "ignoreCommandMonitoringEvents": [ "killCursors" ] } }, { "database": { "id": "database", "client": "client", "databaseName": "test" } }, { "collection": { "id": "collection", "database": "database", "collectionName": "coll" } }, { "bucket": { "id": "bucket", "database": "database" } }, { "session": { "id": "session", "client": "client" } } ] } }, { "name": "createIndex", "object": "collection", "arguments": { "timeoutMS": 1000, "maxTimeMS": 5000, "keys": { "x": 1 }, "name": "x_1" } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "createIndexes", "databaseName": "test", "command": { "createIndexes": "coll", "maxTimeMS": { "$$lte": 1000 } } } } ] } ] }, { "description": "socketTimeoutMS is ignored if timeoutMS is set - dropIndex on collection", "operations": [ { "name": "createEntities", "object": "testRunner", "arguments": { "entities": [ { "client": { "id": "client", "uriOptions": { "socketTimeoutMS": 1 }, "useMultipleMongoses": false } }, { "database": { "id": "database", "client": "client", "databaseName": "test" } }, { "collection": { "id": "collection", "database": "database", "collectionName": "coll" } }, { "bucket": { "id": "bucket", "database": "database" } }, { "session": { "id": "session", "client": "client" } } ] } }, { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "dropIndexes" ], "blockConnection": true, "blockTimeMS": 5 } } } }, { "name": "dropIndex", "object": "collection", "arguments": { "timeoutMS": 100000, "name": "x_1" }, "expectError": { "isClientError": false, "isTimeoutError": false } } ] }, { "description": "wTimeoutMS is ignored if timeoutMS is set - dropIndex on collection", "operations": [ { "name": "createEntities", "object": "testRunner", "arguments": { "entities": [ { "client": { "id": "client", "uriOptions": { "wTimeoutMS": 1 }, "observeEvents": [ "commandStartedEvent" ], "ignoreCommandMonitoringEvents": [ "killCursors" ] } }, { "database": { "id": "database", "client": "client", "databaseName": "test" } }, { "collection": { "id": "collection", "database": "database", "collectionName": "coll" } }, { "bucket": { "id": "bucket", "database": "database" } }, { "session": { "id": "session", "client": "client" } } ] } }, { "name": "dropIndex", "object": "collection", "arguments": { "timeoutMS": 100000, "name": "x_1" }, "expectError": { "isClientError": false, "isTimeoutError": false } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "dropIndexes", "databaseName": "test", "command": { "dropIndexes": "coll", "writeConcern": { "$$exists": false }, "maxTimeMS": { "$$type": [ "int", "long" ] } } } } ] } ] }, { "description": "maxTimeMS is ignored if timeoutMS is set - dropIndex on collection", "operations": [ { "name": "createEntities", "object": "testRunner", "arguments": { "entities": [ { "client": { "id": "client", "useMultipleMongoses": false, "observeEvents": [ "commandStartedEvent" ], "ignoreCommandMonitoringEvents": [ "killCursors" ] } }, { "database": { "id": "database", "client": "client", "databaseName": "test" } }, { "collection": { "id": "collection", "database": "database", "collectionName": "coll" } }, { "bucket": { "id": "bucket", "database": "database" } }, { "session": { "id": "session", "client": "client" } } ] } }, { "name": "dropIndex", "object": "collection", "arguments": { "timeoutMS": 1000, "maxTimeMS": 5000, "name": "x_1" }, "expectError": { "isClientError": false, "isTimeoutError": false } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "dropIndexes", "databaseName": "test", "command": { "dropIndexes": "coll", "maxTimeMS": { "$$lte": 1000 } } } } ] } ] }, { "description": "socketTimeoutMS is ignored if timeoutMS is set - dropIndexes on collection", "operations": [ { "name": "createEntities", "object": "testRunner", "arguments": { "entities": [ { "client": { "id": "client", "uriOptions": { "socketTimeoutMS": 1 }, "useMultipleMongoses": false } }, { "database": { "id": "database", "client": "client", "databaseName": "test" } }, { "collection": { "id": "collection", "database": "database", "collectionName": "coll" } }, { "bucket": { "id": "bucket", "database": "database" } }, { "session": { "id": "session", "client": "client" } } ] } }, { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "dropIndexes" ], "blockConnection": true, "blockTimeMS": 5 } } } }, { "name": "dropIndexes", "object": "collection", "arguments": { "timeoutMS": 100000 } } ] }, { "description": "wTimeoutMS is ignored if timeoutMS is set - dropIndexes on collection", "operations": [ { "name": "createEntities", "object": "testRunner", "arguments": { "entities": [ { "client": { "id": "client", "uriOptions": { "wTimeoutMS": 1 }, "observeEvents": [ "commandStartedEvent" ], "ignoreCommandMonitoringEvents": [ "killCursors" ] } }, { "database": { "id": "database", "client": "client", "databaseName": "test" } }, { "collection": { "id": "collection", "database": "database", "collectionName": "coll" } }, { "bucket": { "id": "bucket", "database": "database" } }, { "session": { "id": "session", "client": "client" } } ] } }, { "name": "dropIndexes", "object": "collection", "arguments": { "timeoutMS": 100000 } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "dropIndexes", "databaseName": "test", "command": { "dropIndexes": "coll", "writeConcern": { "$$exists": false }, "maxTimeMS": { "$$type": [ "int", "long" ] } } } } ] } ] }, { "description": "maxTimeMS is ignored if timeoutMS is set - dropIndexes on collection", "operations": [ { "name": "createEntities", "object": "testRunner", "arguments": { "entities": [ { "client": { "id": "client", "useMultipleMongoses": false, "observeEvents": [ "commandStartedEvent" ], "ignoreCommandMonitoringEvents": [ "killCursors" ] } }, { "database": { "id": "database", "client": "client", "databaseName": "test" } }, { "collection": { "id": "collection", "database": "database", "collectionName": "coll" } }, { "bucket": { "id": "bucket", "database": "database" } }, { "session": { "id": "session", "client": "client" } } ] } }, { "name": "dropIndexes", "object": "collection", "arguments": { "timeoutMS": 1000, "maxTimeMS": 5000 } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "dropIndexes", "databaseName": "test", "command": { "dropIndexes": "coll", "maxTimeMS": { "$$lte": 1000 } } } } ] } ] } ] } mongodb-mongo-python-driver-509e9b7/test/csot/error-transformations.json000066400000000000000000000076331462766011000266500ustar00rootroot00000000000000{ "description": "MaxTimeMSExpired server errors are transformed into a custom timeout error", "schemaVersion": "1.9", "runOnRequirements": [ { "minServerVersion": "4.0", "topologies": [ "replicaset" ] }, { "minServerVersion": "4.2", "topologies": [ "replicaset", "sharded" ] } ], "createEntities": [ { "client": { "id": "failPointClient", "useMultipleMongoses": false } }, { "client": { "id": "client", "uriOptions": { "timeoutMS": 250 }, "useMultipleMongoses": false, "observeEvents": [ "commandStartedEvent" ] } }, { "database": { "id": "database", "client": "client", "databaseName": "test" } }, { "collection": { "id": "collection", "database": "database", "collectionName": "coll" } } ], "initialData": [ { "collectionName": "coll", "databaseName": "test", "documents": [] } ], "tests": [ { "description": "basic MaxTimeMSExpired error is transformed", "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "insert" ], "errorCode": 50 } } } }, { "name": "insertOne", "object": "collection", "arguments": { "document": { "_id": 1 } }, "expectError": { "isTimeoutError": true } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "insert", "databaseName": "test", "command": { "insert": "coll", "maxTimeMS": { "$$type": [ "int", "long" ] } } } } ] } ] }, { "description": "write concern error MaxTimeMSExpired is transformed", "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "insert" ], "writeConcernError": { "code": 50, "errmsg": "maxTimeMS expired" } } } } }, { "name": "insertOne", "object": "collection", "arguments": { "document": { "_id": 1 } }, "expectError": { "isTimeoutError": true } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "insert", "databaseName": "test", "command": { "insert": "coll", "maxTimeMS": { "$$type": [ "int", "long" ] } } } } ] } ] } ] } mongodb-mongo-python-driver-509e9b7/test/csot/global-timeoutMS.json000066400000000000000000004457661462766011000254710ustar00rootroot00000000000000{ "description": "timeoutMS can be configured on a MongoClient", "schemaVersion": "1.9", "runOnRequirements": [ { "minServerVersion": "4.4", "topologies": [ "replicaset", "sharded-replicaset" ] } ], "createEntities": [ { "client": { "id": "failPointClient", "useMultipleMongoses": false } } ], "initialData": [ { "collectionName": "coll", "databaseName": "test", "documents": [] } ], "tests": [ { "description": "timeoutMS can be configured on a MongoClient - listDatabases on client", "operations": [ { "name": "createEntities", "object": "testRunner", "arguments": { "entities": [ { "client": { "id": "client", "uriOptions": { "timeoutMS": 250 }, "useMultipleMongoses": false, "observeEvents": [ "commandStartedEvent" ] } }, { "database": { "id": "database", "client": "client", "databaseName": "test" } }, { "collection": { "id": "collection", "database": "database", "collectionName": "coll" } } ] } }, { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 2 }, "data": { "failCommands": [ "listDatabases" ], "blockConnection": true, "blockTimeMS": 350 } } } }, { "name": "listDatabases", "object": "client", "arguments": { "filter": {} }, "expectError": { "isTimeoutError": true } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "listDatabases", "databaseName": "admin", "command": { "listDatabases": 1, "maxTimeMS": { "$$type": [ "int", "long" ] } } } } ] } ] }, { "description": "timeoutMS can be set to 0 on a MongoClient - listDatabases on client", "operations": [ { "name": "createEntities", "object": "testRunner", "arguments": { "entities": [ { "client": { "id": "client", "uriOptions": { "timeoutMS": 0 }, "useMultipleMongoses": false, "observeEvents": [ "commandStartedEvent" ], "ignoreCommandMonitoringEvents": [ "killCursors" ] } }, { "database": { "id": "database", "client": "client", "databaseName": "test" } }, { "collection": { "id": "collection", "database": "database", "collectionName": "coll" } } ] } }, { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "listDatabases" ], "blockConnection": true, "blockTimeMS": 15 } } } }, { "name": "listDatabases", "object": "client", "arguments": { "filter": {} } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "listDatabases", "databaseName": "admin", "command": { "listDatabases": 1, "maxTimeMS": { "$$exists": false } } } } ] } ] }, { "description": "timeoutMS can be configured on a MongoClient - listDatabaseNames on client", "operations": [ { "name": "createEntities", "object": "testRunner", "arguments": { "entities": [ { "client": { "id": "client", "uriOptions": { "timeoutMS": 250 }, "useMultipleMongoses": false, "observeEvents": [ "commandStartedEvent" ] } }, { "database": { "id": "database", "client": "client", "databaseName": "test" } }, { "collection": { "id": "collection", "database": "database", "collectionName": "coll" } } ] } }, { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 2 }, "data": { "failCommands": [ "listDatabases" ], "blockConnection": true, "blockTimeMS": 350 } } } }, { "name": "listDatabaseNames", "object": "client", "expectError": { "isTimeoutError": true } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "listDatabases", "databaseName": "admin", "command": { "listDatabases": 1, "maxTimeMS": { "$$type": [ "int", "long" ] } } } } ] } ] }, { "description": "timeoutMS can be set to 0 on a MongoClient - listDatabaseNames on client", "operations": [ { "name": "createEntities", "object": "testRunner", "arguments": { "entities": [ { "client": { "id": "client", "uriOptions": { "timeoutMS": 0 }, "useMultipleMongoses": false, "observeEvents": [ "commandStartedEvent" ], "ignoreCommandMonitoringEvents": [ "killCursors" ] } }, { "database": { "id": "database", "client": "client", "databaseName": "test" } }, { "collection": { "id": "collection", "database": "database", "collectionName": "coll" } } ] } }, { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "listDatabases" ], "blockConnection": true, "blockTimeMS": 15 } } } }, { "name": "listDatabaseNames", "object": "client" } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "listDatabases", "databaseName": "admin", "command": { "listDatabases": 1, "maxTimeMS": { "$$exists": false } } } } ] } ] }, { "description": "timeoutMS can be configured on a MongoClient - createChangeStream on client", "operations": [ { "name": "createEntities", "object": "testRunner", "arguments": { "entities": [ { "client": { "id": "client", "uriOptions": { "timeoutMS": 250 }, "useMultipleMongoses": false, "observeEvents": [ "commandStartedEvent" ] } }, { "database": { "id": "database", "client": "client", "databaseName": "test" } }, { "collection": { "id": "collection", "database": "database", "collectionName": "coll" } } ] } }, { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 2 }, "data": { "failCommands": [ "aggregate" ], "blockConnection": true, "blockTimeMS": 350 } } } }, { "name": "createChangeStream", "object": "client", "arguments": { "pipeline": [] }, "expectError": { "isTimeoutError": true } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "aggregate", "databaseName": "admin", "command": { "aggregate": 1, "maxTimeMS": { "$$type": [ "int", "long" ] } } } } ] } ] }, { "description": "timeoutMS can be set to 0 on a MongoClient - createChangeStream on client", "operations": [ { "name": "createEntities", "object": "testRunner", "arguments": { "entities": [ { "client": { "id": "client", "uriOptions": { "timeoutMS": 0 }, "useMultipleMongoses": false, "observeEvents": [ "commandStartedEvent" ], "ignoreCommandMonitoringEvents": [ "killCursors" ] } }, { "database": { "id": "database", "client": "client", "databaseName": "test" } }, { "collection": { "id": "collection", "database": "database", "collectionName": "coll" } } ] } }, { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "aggregate" ], "blockConnection": true, "blockTimeMS": 15 } } } }, { "name": "createChangeStream", "object": "client", "arguments": { "pipeline": [] } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "aggregate", "databaseName": "admin", "command": { "aggregate": 1, "maxTimeMS": { "$$exists": false } } } } ] } ] }, { "description": "timeoutMS can be configured on a MongoClient - aggregate on database", "operations": [ { "name": "createEntities", "object": "testRunner", "arguments": { "entities": [ { "client": { "id": "client", "uriOptions": { "timeoutMS": 250 }, "useMultipleMongoses": false, "observeEvents": [ "commandStartedEvent" ] } }, { "database": { "id": "database", "client": "client", "databaseName": "test" } }, { "collection": { "id": "collection", "database": "database", "collectionName": "coll" } } ] } }, { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 2 }, "data": { "failCommands": [ "aggregate" ], "blockConnection": true, "blockTimeMS": 350 } } } }, { "name": "aggregate", "object": "database", "arguments": { "pipeline": [ { "$listLocalSessions": {} }, { "$limit": 1 } ] }, "expectError": { "isTimeoutError": true } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "aggregate", "databaseName": "test", "command": { "aggregate": 1, "maxTimeMS": { "$$type": [ "int", "long" ] } } } } ] } ] }, { "description": "timeoutMS can be set to 0 on a MongoClient - aggregate on database", "operations": [ { "name": "createEntities", "object": "testRunner", "arguments": { "entities": [ { "client": { "id": "client", "uriOptions": { "timeoutMS": 0 }, "useMultipleMongoses": false, "observeEvents": [ "commandStartedEvent" ], "ignoreCommandMonitoringEvents": [ "killCursors" ] } }, { "database": { "id": "database", "client": "client", "databaseName": "test" } }, { "collection": { "id": "collection", "database": "database", "collectionName": "coll" } } ] } }, { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "aggregate" ], "blockConnection": true, "blockTimeMS": 15 } } } }, { "name": "aggregate", "object": "database", "arguments": { "pipeline": [ { "$listLocalSessions": {} }, { "$limit": 1 } ] } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "aggregate", "databaseName": "test", "command": { "aggregate": 1, "maxTimeMS": { "$$exists": false } } } } ] } ] }, { "description": "timeoutMS can be configured on a MongoClient - listCollections on database", "operations": [ { "name": "createEntities", "object": "testRunner", "arguments": { "entities": [ { "client": { "id": "client", "uriOptions": { "timeoutMS": 250 }, "useMultipleMongoses": false, "observeEvents": [ "commandStartedEvent" ] } }, { "database": { "id": "database", "client": "client", "databaseName": "test" } }, { "collection": { "id": "collection", "database": "database", "collectionName": "coll" } } ] } }, { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 2 }, "data": { "failCommands": [ "listCollections" ], "blockConnection": true, "blockTimeMS": 350 } } } }, { "name": "listCollections", "object": "database", "arguments": { "filter": {} }, "expectError": { "isTimeoutError": true } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "listCollections", "databaseName": "test", "command": { "listCollections": 1, "maxTimeMS": { "$$type": [ "int", "long" ] } } } } ] } ] }, { "description": "timeoutMS can be set to 0 on a MongoClient - listCollections on database", "operations": [ { "name": "createEntities", "object": "testRunner", "arguments": { "entities": [ { "client": { "id": "client", "uriOptions": { "timeoutMS": 0 }, "useMultipleMongoses": false, "observeEvents": [ "commandStartedEvent" ], "ignoreCommandMonitoringEvents": [ "killCursors" ] } }, { "database": { "id": "database", "client": "client", "databaseName": "test" } }, { "collection": { "id": "collection", "database": "database", "collectionName": "coll" } } ] } }, { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "listCollections" ], "blockConnection": true, "blockTimeMS": 15 } } } }, { "name": "listCollections", "object": "database", "arguments": { "filter": {} } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "listCollections", "databaseName": "test", "command": { "listCollections": 1, "maxTimeMS": { "$$exists": false } } } } ] } ] }, { "description": "timeoutMS can be configured on a MongoClient - listCollectionNames on database", "operations": [ { "name": "createEntities", "object": "testRunner", "arguments": { "entities": [ { "client": { "id": "client", "uriOptions": { "timeoutMS": 250 }, "useMultipleMongoses": false, "observeEvents": [ "commandStartedEvent" ] } }, { "database": { "id": "database", "client": "client", "databaseName": "test" } }, { "collection": { "id": "collection", "database": "database", "collectionName": "coll" } } ] } }, { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 2 }, "data": { "failCommands": [ "listCollections" ], "blockConnection": true, "blockTimeMS": 350 } } } }, { "name": "listCollectionNames", "object": "database", "arguments": { "filter": {} }, "expectError": { "isTimeoutError": true } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "listCollections", "databaseName": "test", "command": { "listCollections": 1, "maxTimeMS": { "$$type": [ "int", "long" ] } } } } ] } ] }, { "description": "timeoutMS can be set to 0 on a MongoClient - listCollectionNames on database", "operations": [ { "name": "createEntities", "object": "testRunner", "arguments": { "entities": [ { "client": { "id": "client", "uriOptions": { "timeoutMS": 0 }, "useMultipleMongoses": false, "observeEvents": [ "commandStartedEvent" ], "ignoreCommandMonitoringEvents": [ "killCursors" ] } }, { "database": { "id": "database", "client": "client", "databaseName": "test" } }, { "collection": { "id": "collection", "database": "database", "collectionName": "coll" } } ] } }, { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "listCollections" ], "blockConnection": true, "blockTimeMS": 15 } } } }, { "name": "listCollectionNames", "object": "database", "arguments": { "filter": {} } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "listCollections", "databaseName": "test", "command": { "listCollections": 1, "maxTimeMS": { "$$exists": false } } } } ] } ] }, { "description": "timeoutMS can be configured on a MongoClient - runCommand on database", "operations": [ { "name": "createEntities", "object": "testRunner", "arguments": { "entities": [ { "client": { "id": "client", "uriOptions": { "timeoutMS": 250 }, "useMultipleMongoses": false, "observeEvents": [ "commandStartedEvent" ] } }, { "database": { "id": "database", "client": "client", "databaseName": "test" } }, { "collection": { "id": "collection", "database": "database", "collectionName": "coll" } } ] } }, { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 2 }, "data": { "failCommands": [ "ping" ], "blockConnection": true, "blockTimeMS": 350 } } } }, { "name": "runCommand", "object": "database", "arguments": { "command": { "ping": 1 }, "commandName": "ping" }, "expectError": { "isTimeoutError": true } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "ping", "databaseName": "test", "command": { "ping": 1, "maxTimeMS": { "$$type": [ "int", "long" ] } } } } ] } ] }, { "description": "timeoutMS can be set to 0 on a MongoClient - runCommand on database", "operations": [ { "name": "createEntities", "object": "testRunner", "arguments": { "entities": [ { "client": { "id": "client", "uriOptions": { "timeoutMS": 0 }, "useMultipleMongoses": false, "observeEvents": [ "commandStartedEvent" ], "ignoreCommandMonitoringEvents": [ "killCursors" ] } }, { "database": { "id": "database", "client": "client", "databaseName": "test" } }, { "collection": { "id": "collection", "database": "database", "collectionName": "coll" } } ] } }, { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "ping" ], "blockConnection": true, "blockTimeMS": 15 } } } }, { "name": "runCommand", "object": "database", "arguments": { "command": { "ping": 1 }, "commandName": "ping" } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "ping", "databaseName": "test", "command": { "ping": 1, "maxTimeMS": { "$$exists": false } } } } ] } ] }, { "description": "timeoutMS can be configured on a MongoClient - createChangeStream on database", "operations": [ { "name": "createEntities", "object": "testRunner", "arguments": { "entities": [ { "client": { "id": "client", "uriOptions": { "timeoutMS": 250 }, "useMultipleMongoses": false, "observeEvents": [ "commandStartedEvent" ] } }, { "database": { "id": "database", "client": "client", "databaseName": "test" } }, { "collection": { "id": "collection", "database": "database", "collectionName": "coll" } } ] } }, { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 2 }, "data": { "failCommands": [ "aggregate" ], "blockConnection": true, "blockTimeMS": 350 } } } }, { "name": "createChangeStream", "object": "database", "arguments": { "pipeline": [] }, "expectError": { "isTimeoutError": true } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "aggregate", "databaseName": "test", "command": { "aggregate": 1, "maxTimeMS": { "$$type": [ "int", "long" ] } } } } ] } ] }, { "description": "timeoutMS can be set to 0 on a MongoClient - createChangeStream on database", "operations": [ { "name": "createEntities", "object": "testRunner", "arguments": { "entities": [ { "client": { "id": "client", "uriOptions": { "timeoutMS": 0 }, "useMultipleMongoses": false, "observeEvents": [ "commandStartedEvent" ], "ignoreCommandMonitoringEvents": [ "killCursors" ] } }, { "database": { "id": "database", "client": "client", "databaseName": "test" } }, { "collection": { "id": "collection", "database": "database", "collectionName": "coll" } } ] } }, { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "aggregate" ], "blockConnection": true, "blockTimeMS": 15 } } } }, { "name": "createChangeStream", "object": "database", "arguments": { "pipeline": [] } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "aggregate", "databaseName": "test", "command": { "aggregate": 1, "maxTimeMS": { "$$exists": false } } } } ] } ] }, { "description": "timeoutMS can be configured on a MongoClient - aggregate on collection", "operations": [ { "name": "createEntities", "object": "testRunner", "arguments": { "entities": [ { "client": { "id": "client", "uriOptions": { "timeoutMS": 250 }, "useMultipleMongoses": false, "observeEvents": [ "commandStartedEvent" ] } }, { "database": { "id": "database", "client": "client", "databaseName": "test" } }, { "collection": { "id": "collection", "database": "database", "collectionName": "coll" } } ] } }, { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 2 }, "data": { "failCommands": [ "aggregate" ], "blockConnection": true, "blockTimeMS": 350 } } } }, { "name": "aggregate", "object": "collection", "arguments": { "pipeline": [] }, "expectError": { "isTimeoutError": true } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "aggregate", "databaseName": "test", "command": { "aggregate": "coll", "maxTimeMS": { "$$type": [ "int", "long" ] } } } } ] } ] }, { "description": "timeoutMS can be set to 0 on a MongoClient - aggregate on collection", "operations": [ { "name": "createEntities", "object": "testRunner", "arguments": { "entities": [ { "client": { "id": "client", "uriOptions": { "timeoutMS": 0 }, "useMultipleMongoses": false, "observeEvents": [ "commandStartedEvent" ], "ignoreCommandMonitoringEvents": [ "killCursors" ] } }, { "database": { "id": "database", "client": "client", "databaseName": "test" } }, { "collection": { "id": "collection", "database": "database", "collectionName": "coll" } } ] } }, { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "aggregate" ], "blockConnection": true, "blockTimeMS": 15 } } } }, { "name": "aggregate", "object": "collection", "arguments": { "pipeline": [] } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "aggregate", "databaseName": "test", "command": { "aggregate": "coll", "maxTimeMS": { "$$exists": false } } } } ] } ] }, { "description": "timeoutMS can be configured on a MongoClient - count on collection", "operations": [ { "name": "createEntities", "object": "testRunner", "arguments": { "entities": [ { "client": { "id": "client", "uriOptions": { "timeoutMS": 250 }, "useMultipleMongoses": false, "observeEvents": [ "commandStartedEvent" ] } }, { "database": { "id": "database", "client": "client", "databaseName": "test" } }, { "collection": { "id": "collection", "database": "database", "collectionName": "coll" } } ] } }, { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 2 }, "data": { "failCommands": [ "count" ], "blockConnection": true, "blockTimeMS": 350 } } } }, { "name": "count", "object": "collection", "arguments": { "filter": {} }, "expectError": { "isTimeoutError": true } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "count", "databaseName": "test", "command": { "count": "coll", "maxTimeMS": { "$$type": [ "int", "long" ] } } } } ] } ] }, { "description": "timeoutMS can be set to 0 on a MongoClient - count on collection", "operations": [ { "name": "createEntities", "object": "testRunner", "arguments": { "entities": [ { "client": { "id": "client", "uriOptions": { "timeoutMS": 0 }, "useMultipleMongoses": false, "observeEvents": [ "commandStartedEvent" ], "ignoreCommandMonitoringEvents": [ "killCursors" ] } }, { "database": { "id": "database", "client": "client", "databaseName": "test" } }, { "collection": { "id": "collection", "database": "database", "collectionName": "coll" } } ] } }, { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "count" ], "blockConnection": true, "blockTimeMS": 15 } } } }, { "name": "count", "object": "collection", "arguments": { "filter": {} } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "count", "databaseName": "test", "command": { "count": "coll", "maxTimeMS": { "$$exists": false } } } } ] } ] }, { "description": "timeoutMS can be configured on a MongoClient - countDocuments on collection", "operations": [ { "name": "createEntities", "object": "testRunner", "arguments": { "entities": [ { "client": { "id": "client", "uriOptions": { "timeoutMS": 250 }, "useMultipleMongoses": false, "observeEvents": [ "commandStartedEvent" ] } }, { "database": { "id": "database", "client": "client", "databaseName": "test" } }, { "collection": { "id": "collection", "database": "database", "collectionName": "coll" } } ] } }, { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 2 }, "data": { "failCommands": [ "aggregate" ], "blockConnection": true, "blockTimeMS": 350 } } } }, { "name": "countDocuments", "object": "collection", "arguments": { "filter": {} }, "expectError": { "isTimeoutError": true } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "aggregate", "databaseName": "test", "command": { "aggregate": "coll", "maxTimeMS": { "$$type": [ "int", "long" ] } } } } ] } ] }, { "description": "timeoutMS can be set to 0 on a MongoClient - countDocuments on collection", "operations": [ { "name": "createEntities", "object": "testRunner", "arguments": { "entities": [ { "client": { "id": "client", "uriOptions": { "timeoutMS": 0 }, "useMultipleMongoses": false, "observeEvents": [ "commandStartedEvent" ], "ignoreCommandMonitoringEvents": [ "killCursors" ] } }, { "database": { "id": "database", "client": "client", "databaseName": "test" } }, { "collection": { "id": "collection", "database": "database", "collectionName": "coll" } } ] } }, { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "aggregate" ], "blockConnection": true, "blockTimeMS": 15 } } } }, { "name": "countDocuments", "object": "collection", "arguments": { "filter": {} } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "aggregate", "databaseName": "test", "command": { "aggregate": "coll", "maxTimeMS": { "$$exists": false } } } } ] } ] }, { "description": "timeoutMS can be configured on a MongoClient - estimatedDocumentCount on collection", "operations": [ { "name": "createEntities", "object": "testRunner", "arguments": { "entities": [ { "client": { "id": "client", "uriOptions": { "timeoutMS": 250 }, "useMultipleMongoses": false, "observeEvents": [ "commandStartedEvent" ] } }, { "database": { "id": "database", "client": "client", "databaseName": "test" } }, { "collection": { "id": "collection", "database": "database", "collectionName": "coll" } } ] } }, { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 2 }, "data": { "failCommands": [ "count" ], "blockConnection": true, "blockTimeMS": 350 } } } }, { "name": "estimatedDocumentCount", "object": "collection", "expectError": { "isTimeoutError": true } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "count", "databaseName": "test", "command": { "count": "coll", "maxTimeMS": { "$$type": [ "int", "long" ] } } } } ] } ] }, { "description": "timeoutMS can be set to 0 on a MongoClient - estimatedDocumentCount on collection", "operations": [ { "name": "createEntities", "object": "testRunner", "arguments": { "entities": [ { "client": { "id": "client", "uriOptions": { "timeoutMS": 0 }, "useMultipleMongoses": false, "observeEvents": [ "commandStartedEvent" ], "ignoreCommandMonitoringEvents": [ "killCursors" ] } }, { "database": { "id": "database", "client": "client", "databaseName": "test" } }, { "collection": { "id": "collection", "database": "database", "collectionName": "coll" } } ] } }, { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "count" ], "blockConnection": true, "blockTimeMS": 15 } } } }, { "name": "estimatedDocumentCount", "object": "collection" } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "count", "databaseName": "test", "command": { "count": "coll", "maxTimeMS": { "$$exists": false } } } } ] } ] }, { "description": "timeoutMS can be configured on a MongoClient - distinct on collection", "operations": [ { "name": "createEntities", "object": "testRunner", "arguments": { "entities": [ { "client": { "id": "client", "uriOptions": { "timeoutMS": 250 }, "useMultipleMongoses": false, "observeEvents": [ "commandStartedEvent" ] } }, { "database": { "id": "database", "client": "client", "databaseName": "test" } }, { "collection": { "id": "collection", "database": "database", "collectionName": "coll" } } ] } }, { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 2 }, "data": { "failCommands": [ "distinct" ], "blockConnection": true, "blockTimeMS": 350 } } } }, { "name": "distinct", "object": "collection", "arguments": { "fieldName": "x", "filter": {} }, "expectError": { "isTimeoutError": true } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "distinct", "databaseName": "test", "command": { "distinct": "coll", "maxTimeMS": { "$$type": [ "int", "long" ] } } } } ] } ] }, { "description": "timeoutMS can be set to 0 on a MongoClient - distinct on collection", "operations": [ { "name": "createEntities", "object": "testRunner", "arguments": { "entities": [ { "client": { "id": "client", "uriOptions": { "timeoutMS": 0 }, "useMultipleMongoses": false, "observeEvents": [ "commandStartedEvent" ], "ignoreCommandMonitoringEvents": [ "killCursors" ] } }, { "database": { "id": "database", "client": "client", "databaseName": "test" } }, { "collection": { "id": "collection", "database": "database", "collectionName": "coll" } } ] } }, { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "distinct" ], "blockConnection": true, "blockTimeMS": 15 } } } }, { "name": "distinct", "object": "collection", "arguments": { "fieldName": "x", "filter": {} } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "distinct", "databaseName": "test", "command": { "distinct": "coll", "maxTimeMS": { "$$exists": false } } } } ] } ] }, { "description": "timeoutMS can be configured on a MongoClient - find on collection", "operations": [ { "name": "createEntities", "object": "testRunner", "arguments": { "entities": [ { "client": { "id": "client", "uriOptions": { "timeoutMS": 250 }, "useMultipleMongoses": false, "observeEvents": [ "commandStartedEvent" ] } }, { "database": { "id": "database", "client": "client", "databaseName": "test" } }, { "collection": { "id": "collection", "database": "database", "collectionName": "coll" } } ] } }, { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 2 }, "data": { "failCommands": [ "find" ], "blockConnection": true, "blockTimeMS": 350 } } } }, { "name": "find", "object": "collection", "arguments": { "filter": {} }, "expectError": { "isTimeoutError": true } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "find", "databaseName": "test", "command": { "find": "coll", "maxTimeMS": { "$$type": [ "int", "long" ] } } } } ] } ] }, { "description": "timeoutMS can be set to 0 on a MongoClient - find on collection", "operations": [ { "name": "createEntities", "object": "testRunner", "arguments": { "entities": [ { "client": { "id": "client", "uriOptions": { "timeoutMS": 0 }, "useMultipleMongoses": false, "observeEvents": [ "commandStartedEvent" ], "ignoreCommandMonitoringEvents": [ "killCursors" ] } }, { "database": { "id": "database", "client": "client", "databaseName": "test" } }, { "collection": { "id": "collection", "database": "database", "collectionName": "coll" } } ] } }, { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "find" ], "blockConnection": true, "blockTimeMS": 15 } } } }, { "name": "find", "object": "collection", "arguments": { "filter": {} } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "find", "databaseName": "test", "command": { "find": "coll", "maxTimeMS": { "$$exists": false } } } } ] } ] }, { "description": "timeoutMS can be configured on a MongoClient - findOne on collection", "operations": [ { "name": "createEntities", "object": "testRunner", "arguments": { "entities": [ { "client": { "id": "client", "uriOptions": { "timeoutMS": 250 }, "useMultipleMongoses": false, "observeEvents": [ "commandStartedEvent" ] } }, { "database": { "id": "database", "client": "client", "databaseName": "test" } }, { "collection": { "id": "collection", "database": "database", "collectionName": "coll" } } ] } }, { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 2 }, "data": { "failCommands": [ "find" ], "blockConnection": true, "blockTimeMS": 350 } } } }, { "name": "findOne", "object": "collection", "arguments": { "filter": {} }, "expectError": { "isTimeoutError": true } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "find", "databaseName": "test", "command": { "find": "coll", "maxTimeMS": { "$$type": [ "int", "long" ] } } } } ] } ] }, { "description": "timeoutMS can be set to 0 on a MongoClient - findOne on collection", "operations": [ { "name": "createEntities", "object": "testRunner", "arguments": { "entities": [ { "client": { "id": "client", "uriOptions": { "timeoutMS": 0 }, "useMultipleMongoses": false, "observeEvents": [ "commandStartedEvent" ], "ignoreCommandMonitoringEvents": [ "killCursors" ] } }, { "database": { "id": "database", "client": "client", "databaseName": "test" } }, { "collection": { "id": "collection", "database": "database", "collectionName": "coll" } } ] } }, { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "find" ], "blockConnection": true, "blockTimeMS": 15 } } } }, { "name": "findOne", "object": "collection", "arguments": { "filter": {} } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "find", "databaseName": "test", "command": { "find": "coll", "maxTimeMS": { "$$exists": false } } } } ] } ] }, { "description": "timeoutMS can be configured on a MongoClient - listIndexes on collection", "operations": [ { "name": "createEntities", "object": "testRunner", "arguments": { "entities": [ { "client": { "id": "client", "uriOptions": { "timeoutMS": 250 }, "useMultipleMongoses": false, "observeEvents": [ "commandStartedEvent" ] } }, { "database": { "id": "database", "client": "client", "databaseName": "test" } }, { "collection": { "id": "collection", "database": "database", "collectionName": "coll" } } ] } }, { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 2 }, "data": { "failCommands": [ "listIndexes" ], "blockConnection": true, "blockTimeMS": 350 } } } }, { "name": "listIndexes", "object": "collection", "expectError": { "isTimeoutError": true } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "listIndexes", "databaseName": "test", "command": { "listIndexes": "coll", "maxTimeMS": { "$$type": [ "int", "long" ] } } } } ] } ] }, { "description": "timeoutMS can be set to 0 on a MongoClient - listIndexes on collection", "operations": [ { "name": "createEntities", "object": "testRunner", "arguments": { "entities": [ { "client": { "id": "client", "uriOptions": { "timeoutMS": 0 }, "useMultipleMongoses": false, "observeEvents": [ "commandStartedEvent" ], "ignoreCommandMonitoringEvents": [ "killCursors" ] } }, { "database": { "id": "database", "client": "client", "databaseName": "test" } }, { "collection": { "id": "collection", "database": "database", "collectionName": "coll" } } ] } }, { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "listIndexes" ], "blockConnection": true, "blockTimeMS": 15 } } } }, { "name": "listIndexes", "object": "collection" } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "listIndexes", "databaseName": "test", "command": { "listIndexes": "coll", "maxTimeMS": { "$$exists": false } } } } ] } ] }, { "description": "timeoutMS can be configured on a MongoClient - listIndexNames on collection", "operations": [ { "name": "createEntities", "object": "testRunner", "arguments": { "entities": [ { "client": { "id": "client", "uriOptions": { "timeoutMS": 250 }, "useMultipleMongoses": false, "observeEvents": [ "commandStartedEvent" ] } }, { "database": { "id": "database", "client": "client", "databaseName": "test" } }, { "collection": { "id": "collection", "database": "database", "collectionName": "coll" } } ] } }, { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 2 }, "data": { "failCommands": [ "listIndexes" ], "blockConnection": true, "blockTimeMS": 350 } } } }, { "name": "listIndexNames", "object": "collection", "expectError": { "isTimeoutError": true } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "listIndexes", "databaseName": "test", "command": { "listIndexes": "coll", "maxTimeMS": { "$$type": [ "int", "long" ] } } } } ] } ] }, { "description": "timeoutMS can be set to 0 on a MongoClient - listIndexNames on collection", "operations": [ { "name": "createEntities", "object": "testRunner", "arguments": { "entities": [ { "client": { "id": "client", "uriOptions": { "timeoutMS": 0 }, "useMultipleMongoses": false, "observeEvents": [ "commandStartedEvent" ], "ignoreCommandMonitoringEvents": [ "killCursors" ] } }, { "database": { "id": "database", "client": "client", "databaseName": "test" } }, { "collection": { "id": "collection", "database": "database", "collectionName": "coll" } } ] } }, { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "listIndexes" ], "blockConnection": true, "blockTimeMS": 15 } } } }, { "name": "listIndexNames", "object": "collection" } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "listIndexes", "databaseName": "test", "command": { "listIndexes": "coll", "maxTimeMS": { "$$exists": false } } } } ] } ] }, { "description": "timeoutMS can be configured on a MongoClient - createChangeStream on collection", "operations": [ { "name": "createEntities", "object": "testRunner", "arguments": { "entities": [ { "client": { "id": "client", "uriOptions": { "timeoutMS": 250 }, "useMultipleMongoses": false, "observeEvents": [ "commandStartedEvent" ] } }, { "database": { "id": "database", "client": "client", "databaseName": "test" } }, { "collection": { "id": "collection", "database": "database", "collectionName": "coll" } } ] } }, { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 2 }, "data": { "failCommands": [ "aggregate" ], "blockConnection": true, "blockTimeMS": 350 } } } }, { "name": "createChangeStream", "object": "collection", "arguments": { "pipeline": [] }, "expectError": { "isTimeoutError": true } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "aggregate", "databaseName": "test", "command": { "aggregate": "coll", "maxTimeMS": { "$$type": [ "int", "long" ] } } } } ] } ] }, { "description": "timeoutMS can be set to 0 on a MongoClient - createChangeStream on collection", "operations": [ { "name": "createEntities", "object": "testRunner", "arguments": { "entities": [ { "client": { "id": "client", "uriOptions": { "timeoutMS": 0 }, "useMultipleMongoses": false, "observeEvents": [ "commandStartedEvent" ], "ignoreCommandMonitoringEvents": [ "killCursors" ] } }, { "database": { "id": "database", "client": "client", "databaseName": "test" } }, { "collection": { "id": "collection", "database": "database", "collectionName": "coll" } } ] } }, { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "aggregate" ], "blockConnection": true, "blockTimeMS": 15 } } } }, { "name": "createChangeStream", "object": "collection", "arguments": { "pipeline": [] } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "aggregate", "databaseName": "test", "command": { "aggregate": "coll", "maxTimeMS": { "$$exists": false } } } } ] } ] }, { "description": "timeoutMS can be configured on a MongoClient - insertOne on collection", "operations": [ { "name": "createEntities", "object": "testRunner", "arguments": { "entities": [ { "client": { "id": "client", "uriOptions": { "timeoutMS": 250 }, "useMultipleMongoses": false, "observeEvents": [ "commandStartedEvent" ] } }, { "database": { "id": "database", "client": "client", "databaseName": "test" } }, { "collection": { "id": "collection", "database": "database", "collectionName": "coll" } } ] } }, { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 2 }, "data": { "failCommands": [ "insert" ], "blockConnection": true, "blockTimeMS": 350 } } } }, { "name": "insertOne", "object": "collection", "arguments": { "document": { "x": 1 } }, "expectError": { "isTimeoutError": true } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "insert", "databaseName": "test", "command": { "insert": "coll", "maxTimeMS": { "$$type": [ "int", "long" ] } } } } ] } ] }, { "description": "timeoutMS can be set to 0 on a MongoClient - insertOne on collection", "operations": [ { "name": "createEntities", "object": "testRunner", "arguments": { "entities": [ { "client": { "id": "client", "uriOptions": { "timeoutMS": 0 }, "useMultipleMongoses": false, "observeEvents": [ "commandStartedEvent" ], "ignoreCommandMonitoringEvents": [ "killCursors" ] } }, { "database": { "id": "database", "client": "client", "databaseName": "test" } }, { "collection": { "id": "collection", "database": "database", "collectionName": "coll" } } ] } }, { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "insert" ], "blockConnection": true, "blockTimeMS": 15 } } } }, { "name": "insertOne", "object": "collection", "arguments": { "document": { "x": 1 } } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "insert", "databaseName": "test", "command": { "insert": "coll", "maxTimeMS": { "$$exists": false } } } } ] } ] }, { "description": "timeoutMS can be configured on a MongoClient - insertMany on collection", "operations": [ { "name": "createEntities", "object": "testRunner", "arguments": { "entities": [ { "client": { "id": "client", "uriOptions": { "timeoutMS": 250 }, "useMultipleMongoses": false, "observeEvents": [ "commandStartedEvent" ] } }, { "database": { "id": "database", "client": "client", "databaseName": "test" } }, { "collection": { "id": "collection", "database": "database", "collectionName": "coll" } } ] } }, { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 2 }, "data": { "failCommands": [ "insert" ], "blockConnection": true, "blockTimeMS": 350 } } } }, { "name": "insertMany", "object": "collection", "arguments": { "documents": [ { "x": 1 } ] }, "expectError": { "isTimeoutError": true } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "insert", "databaseName": "test", "command": { "insert": "coll", "maxTimeMS": { "$$type": [ "int", "long" ] } } } } ] } ] }, { "description": "timeoutMS can be set to 0 on a MongoClient - insertMany on collection", "operations": [ { "name": "createEntities", "object": "testRunner", "arguments": { "entities": [ { "client": { "id": "client", "uriOptions": { "timeoutMS": 0 }, "useMultipleMongoses": false, "observeEvents": [ "commandStartedEvent" ], "ignoreCommandMonitoringEvents": [ "killCursors" ] } }, { "database": { "id": "database", "client": "client", "databaseName": "test" } }, { "collection": { "id": "collection", "database": "database", "collectionName": "coll" } } ] } }, { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "insert" ], "blockConnection": true, "blockTimeMS": 15 } } } }, { "name": "insertMany", "object": "collection", "arguments": { "documents": [ { "x": 1 } ] } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "insert", "databaseName": "test", "command": { "insert": "coll", "maxTimeMS": { "$$exists": false } } } } ] } ] }, { "description": "timeoutMS can be configured on a MongoClient - deleteOne on collection", "operations": [ { "name": "createEntities", "object": "testRunner", "arguments": { "entities": [ { "client": { "id": "client", "uriOptions": { "timeoutMS": 250 }, "useMultipleMongoses": false, "observeEvents": [ "commandStartedEvent" ] } }, { "database": { "id": "database", "client": "client", "databaseName": "test" } }, { "collection": { "id": "collection", "database": "database", "collectionName": "coll" } } ] } }, { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 2 }, "data": { "failCommands": [ "delete" ], "blockConnection": true, "blockTimeMS": 350 } } } }, { "name": "deleteOne", "object": "collection", "arguments": { "filter": {} }, "expectError": { "isTimeoutError": true } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "delete", "databaseName": "test", "command": { "delete": "coll", "maxTimeMS": { "$$type": [ "int", "long" ] } } } } ] } ] }, { "description": "timeoutMS can be set to 0 on a MongoClient - deleteOne on collection", "operations": [ { "name": "createEntities", "object": "testRunner", "arguments": { "entities": [ { "client": { "id": "client", "uriOptions": { "timeoutMS": 0 }, "useMultipleMongoses": false, "observeEvents": [ "commandStartedEvent" ], "ignoreCommandMonitoringEvents": [ "killCursors" ] } }, { "database": { "id": "database", "client": "client", "databaseName": "test" } }, { "collection": { "id": "collection", "database": "database", "collectionName": "coll" } } ] } }, { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "delete" ], "blockConnection": true, "blockTimeMS": 15 } } } }, { "name": "deleteOne", "object": "collection", "arguments": { "filter": {} } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "delete", "databaseName": "test", "command": { "delete": "coll", "maxTimeMS": { "$$exists": false } } } } ] } ] }, { "description": "timeoutMS can be configured on a MongoClient - deleteMany on collection", "operations": [ { "name": "createEntities", "object": "testRunner", "arguments": { "entities": [ { "client": { "id": "client", "uriOptions": { "timeoutMS": 250 }, "useMultipleMongoses": false, "observeEvents": [ "commandStartedEvent" ] } }, { "database": { "id": "database", "client": "client", "databaseName": "test" } }, { "collection": { "id": "collection", "database": "database", "collectionName": "coll" } } ] } }, { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 2 }, "data": { "failCommands": [ "delete" ], "blockConnection": true, "blockTimeMS": 350 } } } }, { "name": "deleteMany", "object": "collection", "arguments": { "filter": {} }, "expectError": { "isTimeoutError": true } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "delete", "databaseName": "test", "command": { "delete": "coll", "maxTimeMS": { "$$type": [ "int", "long" ] } } } } ] } ] }, { "description": "timeoutMS can be set to 0 on a MongoClient - deleteMany on collection", "operations": [ { "name": "createEntities", "object": "testRunner", "arguments": { "entities": [ { "client": { "id": "client", "uriOptions": { "timeoutMS": 0 }, "useMultipleMongoses": false, "observeEvents": [ "commandStartedEvent" ], "ignoreCommandMonitoringEvents": [ "killCursors" ] } }, { "database": { "id": "database", "client": "client", "databaseName": "test" } }, { "collection": { "id": "collection", "database": "database", "collectionName": "coll" } } ] } }, { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "delete" ], "blockConnection": true, "blockTimeMS": 15 } } } }, { "name": "deleteMany", "object": "collection", "arguments": { "filter": {} } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "delete", "databaseName": "test", "command": { "delete": "coll", "maxTimeMS": { "$$exists": false } } } } ] } ] }, { "description": "timeoutMS can be configured on a MongoClient - replaceOne on collection", "operations": [ { "name": "createEntities", "object": "testRunner", "arguments": { "entities": [ { "client": { "id": "client", "uriOptions": { "timeoutMS": 250 }, "useMultipleMongoses": false, "observeEvents": [ "commandStartedEvent" ] } }, { "database": { "id": "database", "client": "client", "databaseName": "test" } }, { "collection": { "id": "collection", "database": "database", "collectionName": "coll" } } ] } }, { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 2 }, "data": { "failCommands": [ "update" ], "blockConnection": true, "blockTimeMS": 350 } } } }, { "name": "replaceOne", "object": "collection", "arguments": { "filter": {}, "replacement": { "x": 1 } }, "expectError": { "isTimeoutError": true } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "update", "databaseName": "test", "command": { "update": "coll", "maxTimeMS": { "$$type": [ "int", "long" ] } } } } ] } ] }, { "description": "timeoutMS can be set to 0 on a MongoClient - replaceOne on collection", "operations": [ { "name": "createEntities", "object": "testRunner", "arguments": { "entities": [ { "client": { "id": "client", "uriOptions": { "timeoutMS": 0 }, "useMultipleMongoses": false, "observeEvents": [ "commandStartedEvent" ], "ignoreCommandMonitoringEvents": [ "killCursors" ] } }, { "database": { "id": "database", "client": "client", "databaseName": "test" } }, { "collection": { "id": "collection", "database": "database", "collectionName": "coll" } } ] } }, { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "update" ], "blockConnection": true, "blockTimeMS": 15 } } } }, { "name": "replaceOne", "object": "collection", "arguments": { "filter": {}, "replacement": { "x": 1 } } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "update", "databaseName": "test", "command": { "update": "coll", "maxTimeMS": { "$$exists": false } } } } ] } ] }, { "description": "timeoutMS can be configured on a MongoClient - updateOne on collection", "operations": [ { "name": "createEntities", "object": "testRunner", "arguments": { "entities": [ { "client": { "id": "client", "uriOptions": { "timeoutMS": 250 }, "useMultipleMongoses": false, "observeEvents": [ "commandStartedEvent" ] } }, { "database": { "id": "database", "client": "client", "databaseName": "test" } }, { "collection": { "id": "collection", "database": "database", "collectionName": "coll" } } ] } }, { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 2 }, "data": { "failCommands": [ "update" ], "blockConnection": true, "blockTimeMS": 350 } } } }, { "name": "updateOne", "object": "collection", "arguments": { "filter": {}, "update": { "$set": { "x": 1 } } }, "expectError": { "isTimeoutError": true } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "update", "databaseName": "test", "command": { "update": "coll", "maxTimeMS": { "$$type": [ "int", "long" ] } } } } ] } ] }, { "description": "timeoutMS can be set to 0 on a MongoClient - updateOne on collection", "operations": [ { "name": "createEntities", "object": "testRunner", "arguments": { "entities": [ { "client": { "id": "client", "uriOptions": { "timeoutMS": 0 }, "useMultipleMongoses": false, "observeEvents": [ "commandStartedEvent" ], "ignoreCommandMonitoringEvents": [ "killCursors" ] } }, { "database": { "id": "database", "client": "client", "databaseName": "test" } }, { "collection": { "id": "collection", "database": "database", "collectionName": "coll" } } ] } }, { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "update" ], "blockConnection": true, "blockTimeMS": 15 } } } }, { "name": "updateOne", "object": "collection", "arguments": { "filter": {}, "update": { "$set": { "x": 1 } } } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "update", "databaseName": "test", "command": { "update": "coll", "maxTimeMS": { "$$exists": false } } } } ] } ] }, { "description": "timeoutMS can be configured on a MongoClient - updateMany on collection", "operations": [ { "name": "createEntities", "object": "testRunner", "arguments": { "entities": [ { "client": { "id": "client", "uriOptions": { "timeoutMS": 250 }, "useMultipleMongoses": false, "observeEvents": [ "commandStartedEvent" ] } }, { "database": { "id": "database", "client": "client", "databaseName": "test" } }, { "collection": { "id": "collection", "database": "database", "collectionName": "coll" } } ] } }, { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 2 }, "data": { "failCommands": [ "update" ], "blockConnection": true, "blockTimeMS": 350 } } } }, { "name": "updateMany", "object": "collection", "arguments": { "filter": {}, "update": { "$set": { "x": 1 } } }, "expectError": { "isTimeoutError": true } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "update", "databaseName": "test", "command": { "update": "coll", "maxTimeMS": { "$$type": [ "int", "long" ] } } } } ] } ] }, { "description": "timeoutMS can be set to 0 on a MongoClient - updateMany on collection", "operations": [ { "name": "createEntities", "object": "testRunner", "arguments": { "entities": [ { "client": { "id": "client", "uriOptions": { "timeoutMS": 0 }, "useMultipleMongoses": false, "observeEvents": [ "commandStartedEvent" ], "ignoreCommandMonitoringEvents": [ "killCursors" ] } }, { "database": { "id": "database", "client": "client", "databaseName": "test" } }, { "collection": { "id": "collection", "database": "database", "collectionName": "coll" } } ] } }, { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "update" ], "blockConnection": true, "blockTimeMS": 15 } } } }, { "name": "updateMany", "object": "collection", "arguments": { "filter": {}, "update": { "$set": { "x": 1 } } } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "update", "databaseName": "test", "command": { "update": "coll", "maxTimeMS": { "$$exists": false } } } } ] } ] }, { "description": "timeoutMS can be configured on a MongoClient - findOneAndDelete on collection", "operations": [ { "name": "createEntities", "object": "testRunner", "arguments": { "entities": [ { "client": { "id": "client", "uriOptions": { "timeoutMS": 250 }, "useMultipleMongoses": false, "observeEvents": [ "commandStartedEvent" ] } }, { "database": { "id": "database", "client": "client", "databaseName": "test" } }, { "collection": { "id": "collection", "database": "database", "collectionName": "coll" } } ] } }, { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 2 }, "data": { "failCommands": [ "findAndModify" ], "blockConnection": true, "blockTimeMS": 350 } } } }, { "name": "findOneAndDelete", "object": "collection", "arguments": { "filter": {} }, "expectError": { "isTimeoutError": true } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "findAndModify", "databaseName": "test", "command": { "findAndModify": "coll", "maxTimeMS": { "$$type": [ "int", "long" ] } } } } ] } ] }, { "description": "timeoutMS can be set to 0 on a MongoClient - findOneAndDelete on collection", "operations": [ { "name": "createEntities", "object": "testRunner", "arguments": { "entities": [ { "client": { "id": "client", "uriOptions": { "timeoutMS": 0 }, "useMultipleMongoses": false, "observeEvents": [ "commandStartedEvent" ], "ignoreCommandMonitoringEvents": [ "killCursors" ] } }, { "database": { "id": "database", "client": "client", "databaseName": "test" } }, { "collection": { "id": "collection", "database": "database", "collectionName": "coll" } } ] } }, { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "findAndModify" ], "blockConnection": true, "blockTimeMS": 15 } } } }, { "name": "findOneAndDelete", "object": "collection", "arguments": { "filter": {} } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "findAndModify", "databaseName": "test", "command": { "findAndModify": "coll", "maxTimeMS": { "$$exists": false } } } } ] } ] }, { "description": "timeoutMS can be configured on a MongoClient - findOneAndReplace on collection", "operations": [ { "name": "createEntities", "object": "testRunner", "arguments": { "entities": [ { "client": { "id": "client", "uriOptions": { "timeoutMS": 250 }, "useMultipleMongoses": false, "observeEvents": [ "commandStartedEvent" ] } }, { "database": { "id": "database", "client": "client", "databaseName": "test" } }, { "collection": { "id": "collection", "database": "database", "collectionName": "coll" } } ] } }, { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 2 }, "data": { "failCommands": [ "findAndModify" ], "blockConnection": true, "blockTimeMS": 350 } } } }, { "name": "findOneAndReplace", "object": "collection", "arguments": { "filter": {}, "replacement": { "x": 1 } }, "expectError": { "isTimeoutError": true } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "findAndModify", "databaseName": "test", "command": { "findAndModify": "coll", "maxTimeMS": { "$$type": [ "int", "long" ] } } } } ] } ] }, { "description": "timeoutMS can be set to 0 on a MongoClient - findOneAndReplace on collection", "operations": [ { "name": "createEntities", "object": "testRunner", "arguments": { "entities": [ { "client": { "id": "client", "uriOptions": { "timeoutMS": 0 }, "useMultipleMongoses": false, "observeEvents": [ "commandStartedEvent" ], "ignoreCommandMonitoringEvents": [ "killCursors" ] } }, { "database": { "id": "database", "client": "client", "databaseName": "test" } }, { "collection": { "id": "collection", "database": "database", "collectionName": "coll" } } ] } }, { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "findAndModify" ], "blockConnection": true, "blockTimeMS": 15 } } } }, { "name": "findOneAndReplace", "object": "collection", "arguments": { "filter": {}, "replacement": { "x": 1 } } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "findAndModify", "databaseName": "test", "command": { "findAndModify": "coll", "maxTimeMS": { "$$exists": false } } } } ] } ] }, { "description": "timeoutMS can be configured on a MongoClient - findOneAndUpdate on collection", "operations": [ { "name": "createEntities", "object": "testRunner", "arguments": { "entities": [ { "client": { "id": "client", "uriOptions": { "timeoutMS": 250 }, "useMultipleMongoses": false, "observeEvents": [ "commandStartedEvent" ] } }, { "database": { "id": "database", "client": "client", "databaseName": "test" } }, { "collection": { "id": "collection", "database": "database", "collectionName": "coll" } } ] } }, { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 2 }, "data": { "failCommands": [ "findAndModify" ], "blockConnection": true, "blockTimeMS": 350 } } } }, { "name": "findOneAndUpdate", "object": "collection", "arguments": { "filter": {}, "update": { "$set": { "x": 1 } } }, "expectError": { "isTimeoutError": true } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "findAndModify", "databaseName": "test", "command": { "findAndModify": "coll", "maxTimeMS": { "$$type": [ "int", "long" ] } } } } ] } ] }, { "description": "timeoutMS can be set to 0 on a MongoClient - findOneAndUpdate on collection", "operations": [ { "name": "createEntities", "object": "testRunner", "arguments": { "entities": [ { "client": { "id": "client", "uriOptions": { "timeoutMS": 0 }, "useMultipleMongoses": false, "observeEvents": [ "commandStartedEvent" ], "ignoreCommandMonitoringEvents": [ "killCursors" ] } }, { "database": { "id": "database", "client": "client", "databaseName": "test" } }, { "collection": { "id": "collection", "database": "database", "collectionName": "coll" } } ] } }, { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "findAndModify" ], "blockConnection": true, "blockTimeMS": 15 } } } }, { "name": "findOneAndUpdate", "object": "collection", "arguments": { "filter": {}, "update": { "$set": { "x": 1 } } } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "findAndModify", "databaseName": "test", "command": { "findAndModify": "coll", "maxTimeMS": { "$$exists": false } } } } ] } ] }, { "description": "timeoutMS can be configured on a MongoClient - bulkWrite on collection", "operations": [ { "name": "createEntities", "object": "testRunner", "arguments": { "entities": [ { "client": { "id": "client", "uriOptions": { "timeoutMS": 250 }, "useMultipleMongoses": false, "observeEvents": [ "commandStartedEvent" ] } }, { "database": { "id": "database", "client": "client", "databaseName": "test" } }, { "collection": { "id": "collection", "database": "database", "collectionName": "coll" } } ] } }, { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 2 }, "data": { "failCommands": [ "insert" ], "blockConnection": true, "blockTimeMS": 350 } } } }, { "name": "bulkWrite", "object": "collection", "arguments": { "requests": [ { "insertOne": { "document": { "_id": 1 } } } ] }, "expectError": { "isTimeoutError": true } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "insert", "databaseName": "test", "command": { "insert": "coll", "maxTimeMS": { "$$type": [ "int", "long" ] } } } } ] } ] }, { "description": "timeoutMS can be set to 0 on a MongoClient - bulkWrite on collection", "operations": [ { "name": "createEntities", "object": "testRunner", "arguments": { "entities": [ { "client": { "id": "client", "uriOptions": { "timeoutMS": 0 }, "useMultipleMongoses": false, "observeEvents": [ "commandStartedEvent" ], "ignoreCommandMonitoringEvents": [ "killCursors" ] } }, { "database": { "id": "database", "client": "client", "databaseName": "test" } }, { "collection": { "id": "collection", "database": "database", "collectionName": "coll" } } ] } }, { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "insert" ], "blockConnection": true, "blockTimeMS": 15 } } } }, { "name": "bulkWrite", "object": "collection", "arguments": { "requests": [ { "insertOne": { "document": { "_id": 1 } } } ] } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "insert", "databaseName": "test", "command": { "insert": "coll", "maxTimeMS": { "$$exists": false } } } } ] } ] }, { "description": "timeoutMS can be configured on a MongoClient - createIndex on collection", "operations": [ { "name": "createEntities", "object": "testRunner", "arguments": { "entities": [ { "client": { "id": "client", "uriOptions": { "timeoutMS": 250 }, "useMultipleMongoses": false, "observeEvents": [ "commandStartedEvent" ] } }, { "database": { "id": "database", "client": "client", "databaseName": "test" } }, { "collection": { "id": "collection", "database": "database", "collectionName": "coll" } } ] } }, { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 2 }, "data": { "failCommands": [ "createIndexes" ], "blockConnection": true, "blockTimeMS": 350 } } } }, { "name": "createIndex", "object": "collection", "arguments": { "keys": { "x": 1 }, "name": "x_1" }, "expectError": { "isTimeoutError": true } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "createIndexes", "databaseName": "test", "command": { "createIndexes": "coll", "maxTimeMS": { "$$type": [ "int", "long" ] } } } } ] } ] }, { "description": "timeoutMS can be set to 0 on a MongoClient - createIndex on collection", "operations": [ { "name": "createEntities", "object": "testRunner", "arguments": { "entities": [ { "client": { "id": "client", "uriOptions": { "timeoutMS": 0 }, "useMultipleMongoses": false, "observeEvents": [ "commandStartedEvent" ], "ignoreCommandMonitoringEvents": [ "killCursors" ] } }, { "database": { "id": "database", "client": "client", "databaseName": "test" } }, { "collection": { "id": "collection", "database": "database", "collectionName": "coll" } } ] } }, { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "createIndexes" ], "blockConnection": true, "blockTimeMS": 15 } } } }, { "name": "createIndex", "object": "collection", "arguments": { "keys": { "x": 1 }, "name": "x_1" } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "createIndexes", "databaseName": "test", "command": { "createIndexes": "coll", "maxTimeMS": { "$$exists": false } } } } ] } ] }, { "description": "timeoutMS can be configured on a MongoClient - dropIndex on collection", "operations": [ { "name": "createEntities", "object": "testRunner", "arguments": { "entities": [ { "client": { "id": "client", "uriOptions": { "timeoutMS": 250 }, "useMultipleMongoses": false, "observeEvents": [ "commandStartedEvent" ] } }, { "database": { "id": "database", "client": "client", "databaseName": "test" } }, { "collection": { "id": "collection", "database": "database", "collectionName": "coll" } } ] } }, { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 2 }, "data": { "failCommands": [ "dropIndexes" ], "blockConnection": true, "blockTimeMS": 350 } } } }, { "name": "dropIndex", "object": "collection", "arguments": { "name": "x_1" }, "expectError": { "isTimeoutError": true } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "dropIndexes", "databaseName": "test", "command": { "dropIndexes": "coll", "maxTimeMS": { "$$type": [ "int", "long" ] } } } } ] } ] }, { "description": "timeoutMS can be set to 0 on a MongoClient - dropIndex on collection", "operations": [ { "name": "createEntities", "object": "testRunner", "arguments": { "entities": [ { "client": { "id": "client", "uriOptions": { "timeoutMS": 0 }, "useMultipleMongoses": false, "observeEvents": [ "commandStartedEvent" ], "ignoreCommandMonitoringEvents": [ "killCursors" ] } }, { "database": { "id": "database", "client": "client", "databaseName": "test" } }, { "collection": { "id": "collection", "database": "database", "collectionName": "coll" } } ] } }, { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "dropIndexes" ], "blockConnection": true, "blockTimeMS": 15 } } } }, { "name": "dropIndex", "object": "collection", "arguments": { "name": "x_1" }, "expectError": { "isClientError": false, "isTimeoutError": false } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "dropIndexes", "databaseName": "test", "command": { "dropIndexes": "coll", "maxTimeMS": { "$$exists": false } } } } ] } ] }, { "description": "timeoutMS can be configured on a MongoClient - dropIndexes on collection", "operations": [ { "name": "createEntities", "object": "testRunner", "arguments": { "entities": [ { "client": { "id": "client", "uriOptions": { "timeoutMS": 250 }, "useMultipleMongoses": false, "observeEvents": [ "commandStartedEvent" ] } }, { "database": { "id": "database", "client": "client", "databaseName": "test" } }, { "collection": { "id": "collection", "database": "database", "collectionName": "coll" } } ] } }, { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 2 }, "data": { "failCommands": [ "dropIndexes" ], "blockConnection": true, "blockTimeMS": 350 } } } }, { "name": "dropIndexes", "object": "collection", "expectError": { "isTimeoutError": true } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "dropIndexes", "databaseName": "test", "command": { "dropIndexes": "coll", "maxTimeMS": { "$$type": [ "int", "long" ] } } } } ] } ] }, { "description": "timeoutMS can be set to 0 on a MongoClient - dropIndexes on collection", "operations": [ { "name": "createEntities", "object": "testRunner", "arguments": { "entities": [ { "client": { "id": "client", "uriOptions": { "timeoutMS": 0 }, "useMultipleMongoses": false, "observeEvents": [ "commandStartedEvent" ], "ignoreCommandMonitoringEvents": [ "killCursors" ] } }, { "database": { "id": "database", "client": "client", "databaseName": "test" } }, { "collection": { "id": "collection", "database": "database", "collectionName": "coll" } } ] } }, { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "dropIndexes" ], "blockConnection": true, "blockTimeMS": 15 } } } }, { "name": "dropIndexes", "object": "collection" } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "dropIndexes", "databaseName": "test", "command": { "dropIndexes": "coll", "maxTimeMS": { "$$exists": false } } } } ] } ] } ] } mongodb-mongo-python-driver-509e9b7/test/csot/gridfs-advanced.json000066400000000000000000000213521462766011000253030ustar00rootroot00000000000000{ "description": "timeoutMS behaves correctly for advanced GridFS API operations", "schemaVersion": "1.9", "runOnRequirements": [ { "minServerVersion": "4.4", "serverless": "forbid" } ], "createEntities": [ { "client": { "id": "failPointClient", "useMultipleMongoses": false } }, { "client": { "id": "client", "uriOptions": { "timeoutMS": 75 }, "useMultipleMongoses": false, "observeEvents": [ "commandStartedEvent" ] } }, { "database": { "id": "database", "client": "client", "databaseName": "test" } }, { "bucket": { "id": "bucket", "database": "database" } }, { "collection": { "id": "filesCollection", "database": "database", "collectionName": "fs.files" } }, { "collection": { "id": "chunksCollection", "database": "database", "collectionName": "fs.chunks" } } ], "initialData": [ { "collectionName": "fs.files", "databaseName": "test", "documents": [ { "_id": { "$oid": "000000000000000000000005" }, "length": 8, "chunkSize": 4, "uploadDate": { "$date": "1970-01-01T00:00:00.000Z" }, "filename": "length-8", "contentType": "application/octet-stream", "aliases": [], "metadata": {} } ] }, { "collectionName": "fs.chunks", "databaseName": "test", "documents": [ { "_id": { "$oid": "000000000000000000000005" }, "files_id": { "$oid": "000000000000000000000005" }, "n": 0, "data": { "$binary": { "base64": "ESIzRA==", "subType": "00" } } }, { "_id": { "$oid": "000000000000000000000006" }, "files_id": { "$oid": "000000000000000000000005" }, "n": 1, "data": { "$binary": { "base64": "ESIzRA==", "subType": "00" } } } ] } ], "tests": [ { "description": "timeoutMS can be overridden for a rename", "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "update" ], "blockConnection": true, "blockTimeMS": 100 } } } }, { "name": "rename", "object": "bucket", "arguments": { "id": { "$oid": "000000000000000000000005" }, "newFilename": "foo", "timeoutMS": 2000 } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "update", "databaseName": "test", "command": { "update": "fs.files", "maxTimeMS": { "$$type": [ "int", "long" ] } } } } ] } ] }, { "description": "timeoutMS applied to update during a rename", "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "update" ], "blockConnection": true, "blockTimeMS": 100 } } } }, { "name": "rename", "object": "bucket", "arguments": { "id": { "$oid": "000000000000000000000005" }, "newFilename": "foo" }, "expectError": { "isTimeoutError": true } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "update", "databaseName": "test", "command": { "update": "fs.files", "maxTimeMS": { "$$type": [ "int", "long" ] } } } } ] } ] }, { "description": "timeoutMS can be overridden for drop", "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "drop" ], "blockConnection": true, "blockTimeMS": 100 } } } }, { "name": "drop", "object": "bucket", "arguments": { "timeoutMS": 2000 } } ] }, { "description": "timeoutMS applied to files collection drop", "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "drop" ], "blockConnection": true, "blockTimeMS": 100 } } } }, { "name": "drop", "object": "bucket", "expectError": { "isTimeoutError": true } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "drop", "databaseName": "test", "command": { "drop": "fs.files", "maxTimeMS": { "$$type": [ "int", "long" ] } } } } ] } ] }, { "description": "timeoutMS applied to chunks collection drop", "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "skip": 1 }, "data": { "failCommands": [ "drop" ], "blockConnection": true, "blockTimeMS": 100 } } } }, { "name": "drop", "object": "bucket", "expectError": { "isTimeoutError": true } } ] }, { "description": "timeoutMS applied to drop as a whole, not individual parts", "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 2 }, "data": { "failCommands": [ "drop" ], "blockConnection": true, "blockTimeMS": 50 } } } }, { "name": "drop", "object": "bucket", "expectError": { "isTimeoutError": true } } ] } ] } mongodb-mongo-python-driver-509e9b7/test/csot/gridfs-delete.json000066400000000000000000000146041462766011000250020ustar00rootroot00000000000000{ "description": "timeoutMS behaves correctly for GridFS delete operations", "schemaVersion": "1.9", "runOnRequirements": [ { "minServerVersion": "4.4", "serverless": "forbid" } ], "createEntities": [ { "client": { "id": "failPointClient", "useMultipleMongoses": false } }, { "client": { "id": "client", "uriOptions": { "timeoutMS": 75 }, "useMultipleMongoses": false, "observeEvents": [ "commandStartedEvent" ] } }, { "database": { "id": "database", "client": "client", "databaseName": "test" } }, { "bucket": { "id": "bucket", "database": "database" } }, { "collection": { "id": "filesCollection", "database": "database", "collectionName": "fs.files" } }, { "collection": { "id": "chunksCollection", "database": "database", "collectionName": "fs.chunks" } } ], "initialData": [ { "collectionName": "fs.files", "databaseName": "test", "documents": [ { "_id": { "$oid": "000000000000000000000005" }, "length": 8, "chunkSize": 4, "uploadDate": { "$date": "1970-01-01T00:00:00.000Z" }, "filename": "length-8", "contentType": "application/octet-stream", "aliases": [], "metadata": {} } ] }, { "collectionName": "fs.chunks", "databaseName": "test", "documents": [ { "_id": { "$oid": "000000000000000000000005" }, "files_id": { "$oid": "000000000000000000000005" }, "n": 0, "data": { "$binary": { "base64": "ESIzRA==", "subType": "00" } } }, { "_id": { "$oid": "000000000000000000000006" }, "files_id": { "$oid": "000000000000000000000005" }, "n": 1, "data": { "$binary": { "base64": "ESIzRA==", "subType": "00" } } } ] } ], "tests": [ { "description": "timeoutMS can be overridden for delete", "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "delete" ], "blockConnection": true, "blockTimeMS": 100 } } } }, { "name": "delete", "object": "bucket", "arguments": { "id": { "$oid": "000000000000000000000005" }, "timeoutMS": 1000 } } ] }, { "description": "timeoutMS applied to delete against the files collection", "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "delete" ], "blockConnection": true, "blockTimeMS": 100 } } } }, { "name": "delete", "object": "bucket", "arguments": { "id": { "$oid": "000000000000000000000005" } }, "expectError": { "isTimeoutError": true } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "delete", "databaseName": "test", "command": { "delete": "fs.files", "maxTimeMS": { "$$type": [ "int", "long" ] } } } } ] } ] }, { "description": "timeoutMS applied to delete against the chunks collection", "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "skip": 1 }, "data": { "failCommands": [ "delete" ], "blockConnection": true, "blockTimeMS": 100 } } } }, { "name": "delete", "object": "bucket", "arguments": { "id": { "$oid": "000000000000000000000005" } }, "expectError": { "isTimeoutError": true } } ] }, { "description": "timeoutMS applied to entire delete, not individual parts", "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 2 }, "data": { "failCommands": [ "delete" ], "blockConnection": true, "blockTimeMS": 50 } } } }, { "name": "delete", "object": "bucket", "arguments": { "id": { "$oid": "000000000000000000000005" } }, "expectError": { "isTimeoutError": true } } ] } ] } mongodb-mongo-python-driver-509e9b7/test/csot/gridfs-download.json000066400000000000000000000203111462766011000253370ustar00rootroot00000000000000{ "description": "timeoutMS behaves correctly for GridFS download operations", "schemaVersion": "1.9", "runOnRequirements": [ { "minServerVersion": "4.4", "serverless": "forbid" } ], "createEntities": [ { "client": { "id": "failPointClient", "useMultipleMongoses": false } }, { "client": { "id": "client", "uriOptions": { "timeoutMS": 75 }, "useMultipleMongoses": false, "observeEvents": [ "commandStartedEvent" ] } }, { "database": { "id": "database", "client": "client", "databaseName": "test" } }, { "bucket": { "id": "bucket", "database": "database" } }, { "collection": { "id": "filesCollection", "database": "database", "collectionName": "fs.files" } }, { "collection": { "id": "chunksCollection", "database": "database", "collectionName": "fs.chunks" } } ], "initialData": [ { "collectionName": "fs.files", "databaseName": "test", "documents": [ { "_id": { "$oid": "000000000000000000000005" }, "length": 8, "chunkSize": 4, "uploadDate": { "$date": "1970-01-01T00:00:00.000Z" }, "filename": "length-8", "contentType": "application/octet-stream", "aliases": [], "metadata": {} } ] }, { "collectionName": "fs.chunks", "databaseName": "test", "documents": [ { "_id": { "$oid": "000000000000000000000005" }, "files_id": { "$oid": "000000000000000000000005" }, "n": 0, "data": { "$binary": { "base64": "ESIzRA==", "subType": "00" } } }, { "_id": { "$oid": "000000000000000000000006" }, "files_id": { "$oid": "000000000000000000000005" }, "n": 1, "data": { "$binary": { "base64": "ESIzRA==", "subType": "00" } } } ] } ], "tests": [ { "description": "timeoutMS can be overridden for download", "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "find" ], "blockConnection": true, "blockTimeMS": 100 } } } }, { "name": "download", "object": "bucket", "arguments": { "id": { "$oid": "000000000000000000000005" }, "timeoutMS": 1000 } } ] }, { "description": "timeoutMS applied to find to get files document", "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "find" ], "blockConnection": true, "blockTimeMS": 100 } } } }, { "name": "download", "object": "bucket", "arguments": { "id": { "$oid": "000000000000000000000005" } }, "expectError": { "isTimeoutError": true } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "find", "databaseName": "test", "command": { "find": "fs.files", "maxTimeMS": { "$$type": [ "int", "long" ] } } } } ] } ] }, { "description": "timeoutMS applied to find to get chunks", "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "skip": 1 }, "data": { "failCommands": [ "find" ], "blockConnection": true, "blockTimeMS": 100 } } } }, { "name": "download", "object": "bucket", "arguments": { "id": { "$oid": "000000000000000000000005" } }, "expectError": { "isTimeoutError": true } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "find", "databaseName": "test", "command": { "find": "fs.files", "maxTimeMS": { "$$type": [ "int", "long" ] } } } }, { "commandStartedEvent": { "commandName": "find", "databaseName": "test", "command": { "find": "fs.chunks", "maxTimeMS": { "$$type": [ "int", "long" ] } } } } ] } ] }, { "description": "timeoutMS applied to entire download, not individual parts", "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 2 }, "data": { "failCommands": [ "find" ], "blockConnection": true, "blockTimeMS": 50 } } } }, { "name": "download", "object": "bucket", "arguments": { "id": { "$oid": "000000000000000000000005" } }, "expectError": { "isTimeoutError": true } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "find", "databaseName": "test", "command": { "find": "fs.files", "maxTimeMS": { "$$type": [ "int", "long" ] } } } }, { "commandStartedEvent": { "commandName": "find", "databaseName": "test", "command": { "find": "fs.chunks", "maxTimeMS": { "$$type": [ "int", "long" ] } } } } ] } ] } ] } mongodb-mongo-python-driver-509e9b7/test/csot/gridfs-find.json000066400000000000000000000076541462766011000244670ustar00rootroot00000000000000{ "description": "timeoutMS behaves correctly for GridFS find operations", "schemaVersion": "1.9", "runOnRequirements": [ { "minServerVersion": "4.4", "serverless": "forbid" } ], "createEntities": [ { "client": { "id": "failPointClient", "useMultipleMongoses": false } }, { "client": { "id": "client", "uriOptions": { "timeoutMS": 75 }, "useMultipleMongoses": false, "observeEvents": [ "commandStartedEvent" ] } }, { "database": { "id": "database", "client": "client", "databaseName": "test" } }, { "bucket": { "id": "bucket", "database": "database" } }, { "collection": { "id": "filesCollection", "database": "database", "collectionName": "fs.files" } }, { "collection": { "id": "chunksCollection", "database": "database", "collectionName": "fs.chunks" } } ], "initialData": [ { "collectionName": "fs.files", "databaseName": "test", "documents": [] }, { "collectionName": "fs.chunks", "databaseName": "test", "documents": [] } ], "tests": [ { "description": "timeoutMS can be overridden for a find", "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "find" ], "blockConnection": true, "blockTimeMS": 100 } } } }, { "name": "find", "object": "bucket", "arguments": { "filter": {}, "timeoutMS": 1000 } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "find", "databaseName": "test", "command": { "find": "fs.files", "maxTimeMS": { "$$type": [ "int", "long" ] } } } } ] } ] }, { "description": "timeoutMS applied to find command", "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "find" ], "blockConnection": true, "blockTimeMS": 100 } } } }, { "name": "find", "object": "bucket", "arguments": { "filter": {} }, "expectError": { "isTimeoutError": true } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "find", "databaseName": "test", "command": { "find": "fs.files", "maxTimeMS": { "$$type": [ "int", "long" ] } } } } ] } ] } ] } mongodb-mongo-python-driver-509e9b7/test/csot/gridfs-upload.json000066400000000000000000000230311462766011000250160ustar00rootroot00000000000000{ "description": "timeoutMS behaves correctly for GridFS upload operations", "schemaVersion": "1.9", "runOnRequirements": [ { "minServerVersion": "4.4", "serverless": "forbid" } ], "createEntities": [ { "client": { "id": "failPointClient", "useMultipleMongoses": false } }, { "client": { "id": "client", "uriOptions": { "timeoutMS": 75 }, "useMultipleMongoses": false } }, { "database": { "id": "database", "client": "client", "databaseName": "test" } }, { "bucket": { "id": "bucket", "database": "database" } }, { "collection": { "id": "filesCollection", "database": "database", "collectionName": "fs.files" } }, { "collection": { "id": "chunksCollection", "database": "database", "collectionName": "fs.chunks" } } ], "initialData": [ { "collectionName": "fs.files", "databaseName": "test", "documents": [] }, { "collectionName": "fs.chunks", "databaseName": "test", "documents": [] } ], "tests": [ { "description": "timeoutMS can be overridden for upload", "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "find" ], "blockConnection": true, "blockTimeMS": 100 } } } }, { "name": "upload", "object": "bucket", "arguments": { "filename": "filename", "source": { "$$hexBytes": "1122334455" }, "timeoutMS": 1000 } } ] }, { "description": "timeoutMS applied to initial find on files collection", "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "find" ], "blockConnection": true, "blockTimeMS": 100 } } } }, { "name": "upload", "object": "bucket", "arguments": { "filename": "filename", "source": { "$$hexBytes": "1122334455" } }, "expectError": { "isTimeoutError": true } } ] }, { "description": "timeoutMS applied to listIndexes on files collection", "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "listIndexes" ], "blockConnection": true, "blockTimeMS": 100 } } } }, { "name": "upload", "object": "bucket", "arguments": { "filename": "filename", "source": { "$$hexBytes": "1122334455" } }, "expectError": { "isTimeoutError": true } } ] }, { "description": "timeoutMS applied to index creation for files collection", "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "createIndexes" ], "blockConnection": true, "blockTimeMS": 100 } } } }, { "name": "upload", "object": "bucket", "arguments": { "filename": "filename", "source": { "$$hexBytes": "1122334455" } }, "expectError": { "isTimeoutError": true } } ] }, { "description": "timeoutMS applied to listIndexes on chunks collection", "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "skip": 1 }, "data": { "failCommands": [ "listIndexes" ], "blockConnection": true, "blockTimeMS": 100 } } } }, { "name": "upload", "object": "bucket", "arguments": { "filename": "filename", "source": { "$$hexBytes": "1122334455" } }, "expectError": { "isTimeoutError": true } } ] }, { "description": "timeoutMS applied to index creation for chunks collection", "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "skip": 1 }, "data": { "failCommands": [ "createIndexes" ], "blockConnection": true, "blockTimeMS": 100 } } } }, { "name": "upload", "object": "bucket", "arguments": { "filename": "filename", "source": { "$$hexBytes": "1122334455" } }, "expectError": { "isTimeoutError": true } } ] }, { "description": "timeoutMS applied to chunk insertion", "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "insert" ], "blockConnection": true, "blockTimeMS": 100 } } } }, { "name": "upload", "object": "bucket", "arguments": { "filename": "filename", "source": { "$$hexBytes": "1122334455" } }, "expectError": { "isTimeoutError": true } } ] }, { "description": "timeoutMS applied to creation of files document", "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "skip": 1 }, "data": { "failCommands": [ "insert" ], "blockConnection": true, "blockTimeMS": 100 } } } }, { "name": "upload", "object": "bucket", "arguments": { "filename": "filename", "source": { "$$hexBytes": "1122334455" } }, "expectError": { "isTimeoutError": true } } ] }, { "description": "timeoutMS applied to upload as a whole, not individual parts", "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 2 }, "data": { "failCommands": [ "find", "listIndexes" ], "blockConnection": true, "blockTimeMS": 50 } } } }, { "name": "upload", "object": "bucket", "arguments": { "filename": "filename", "source": { "$$hexBytes": "1122334455" } }, "expectError": { "isTimeoutError": true } } ] } ] } mongodb-mongo-python-driver-509e9b7/test/csot/legacy-timeouts.json000066400000000000000000000223171462766011000253770ustar00rootroot00000000000000{ "description": "legacy timeouts continue to work if timeoutMS is not set", "schemaVersion": "1.9", "runOnRequirements": [ { "minServerVersion": "4.4" } ], "initialData": [ { "collectionName": "coll", "databaseName": "test", "documents": [] } ], "tests": [ { "description": "socketTimeoutMS is not used to derive a maxTimeMS command field", "operations": [ { "name": "createEntities", "object": "testRunner", "arguments": { "entities": [ { "client": { "id": "client", "observeEvents": [ "commandStartedEvent" ], "uriOptions": { "socketTimeoutMS": 50000 } } }, { "database": { "id": "database", "client": "client", "databaseName": "test" } }, { "collection": { "id": "collection", "database": "database", "collectionName": "coll" } } ] } }, { "name": "insertOne", "object": "collection", "arguments": { "document": { "x": 1 } } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "insert", "databaseName": "test", "command": { "insert": "coll", "maxTimeMS": { "$$exists": false } } } } ] } ] }, { "description": "waitQueueTimeoutMS is not used to derive a maxTimeMS command field", "operations": [ { "name": "createEntities", "object": "testRunner", "arguments": { "entities": [ { "client": { "id": "client", "observeEvents": [ "commandStartedEvent" ], "uriOptions": { "waitQueueTimeoutMS": 50000 } } }, { "database": { "id": "database", "client": "client", "databaseName": "test" } }, { "collection": { "id": "collection", "database": "database", "collectionName": "coll" } } ] } }, { "name": "insertOne", "object": "collection", "arguments": { "document": { "x": 1 } } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "insert", "databaseName": "test", "command": { "insert": "coll", "maxTimeMS": { "$$exists": false } } } } ] } ] }, { "description": "wTimeoutMS is not used to derive a maxTimeMS command field", "operations": [ { "name": "createEntities", "object": "testRunner", "arguments": { "entities": [ { "client": { "id": "client", "observeEvents": [ "commandStartedEvent" ], "uriOptions": { "wTimeoutMS": 50000 } } }, { "database": { "id": "database", "client": "client", "databaseName": "test" } }, { "collection": { "id": "collection", "database": "database", "collectionName": "coll" } } ] } }, { "name": "insertOne", "object": "collection", "arguments": { "document": { "x": 1 } } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "insert", "databaseName": "test", "command": { "insert": "coll", "maxTimeMS": { "$$exists": false }, "writeConcern": { "wtimeout": 50000 } } } } ] } ] }, { "description": "maxTimeMS option is used directly as the maxTimeMS field on a command", "operations": [ { "name": "createEntities", "object": "testRunner", "arguments": { "entities": [ { "client": { "id": "client", "observeEvents": [ "commandStartedEvent" ] } }, { "database": { "id": "database", "client": "client", "databaseName": "test" } }, { "collection": { "id": "collection", "database": "database", "collectionName": "coll" } } ] } }, { "name": "estimatedDocumentCount", "object": "collection", "arguments": { "maxTimeMS": 50000 } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "count", "databaseName": "test", "command": { "count": "coll", "maxTimeMS": 50000 } } } ] } ] }, { "description": "maxCommitTimeMS option is used directly as the maxTimeMS field on a commitTransaction command", "runOnRequirements": [ { "topologies": [ "replicaset", "sharded-replicaset" ] } ], "operations": [ { "name": "createEntities", "object": "testRunner", "arguments": { "entities": [ { "client": { "id": "client", "observeEvents": [ "commandStartedEvent" ] } }, { "database": { "id": "database", "client": "client", "databaseName": "test" } }, { "collection": { "id": "collection", "database": "database", "collectionName": "coll" } }, { "session": { "id": "session", "client": "client", "sessionOptions": { "defaultTransactionOptions": { "maxCommitTimeMS": 1000 } } } } ] } }, { "name": "startTransaction", "object": "session" }, { "name": "insertOne", "object": "collection", "arguments": { "document": { "_id": 1 }, "session": "session" } }, { "name": "commitTransaction", "object": "session" } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "insert", "databaseName": "test", "command": { "insert": "coll", "maxTimeMS": { "$$exists": false } } } }, { "commandStartedEvent": { "commandName": "commitTransaction", "databaseName": "admin", "command": { "commitTransaction": 1, "maxTimeMS": 1000 } } } ] } ] } ] } mongodb-mongo-python-driver-509e9b7/test/csot/non-tailable-cursors.json000066400000000000000000000314171462766011000263300ustar00rootroot00000000000000{ "description": "timeoutMS behaves correctly for non-tailable cursors", "schemaVersion": "1.9", "runOnRequirements": [ { "minServerVersion": "4.4" } ], "createEntities": [ { "client": { "id": "failPointClient", "useMultipleMongoses": false } }, { "client": { "id": "client", "uriOptions": { "timeoutMS": 10 }, "useMultipleMongoses": false, "observeEvents": [ "commandStartedEvent" ], "ignoreCommandMonitoringEvents": [ "killCursors" ] } }, { "database": { "id": "database", "client": "client", "databaseName": "test" } }, { "collection": { "id": "collection", "database": "database", "collectionName": "coll" } } ], "initialData": [ { "collectionName": "coll", "databaseName": "test", "documents": [ { "_id": 0 }, { "_id": 1 }, { "_id": 2 } ] }, { "collectionName": "aggregateOutputColl", "databaseName": "test", "documents": [] } ], "tests": [ { "description": "timeoutMS applied to find if timeoutMode is cursor_lifetime", "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "find" ], "blockConnection": true, "blockTimeMS": 15 } } } }, { "name": "find", "object": "collection", "arguments": { "filter": {}, "timeoutMode": "cursorLifetime" }, "expectError": { "isTimeoutError": true } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "find", "databaseName": "test", "command": { "find": "coll", "maxTimeMS": { "$$type": [ "int", "long" ] } } } } ] } ] }, { "description": "remaining timeoutMS applied to getMore if timeoutMode is unset", "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 2 }, "data": { "failCommands": [ "find", "getMore" ], "blockConnection": true, "blockTimeMS": 15 } } } }, { "name": "find", "object": "collection", "arguments": { "filter": {}, "timeoutMS": 20, "batchSize": 2 }, "expectError": { "isTimeoutError": true } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "find", "databaseName": "test", "command": { "find": "coll", "maxTimeMS": { "$$type": [ "int", "long" ] } } } }, { "commandStartedEvent": { "commandName": "getMore", "databaseName": "test", "command": { "getMore": { "$$type": [ "int", "long" ] }, "collection": "coll", "maxTimeMS": { "$$exists": false } } } } ] } ] }, { "description": "remaining timeoutMS applied to getMore if timeoutMode is cursor_lifetime", "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 2 }, "data": { "failCommands": [ "find", "getMore" ], "blockConnection": true, "blockTimeMS": 15 } } } }, { "name": "find", "object": "collection", "arguments": { "filter": {}, "timeoutMode": "cursorLifetime", "timeoutMS": 20, "batchSize": 2 }, "expectError": { "isTimeoutError": true } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "find", "databaseName": "test", "command": { "find": "coll", "maxTimeMS": { "$$type": [ "int", "long" ] } } } }, { "commandStartedEvent": { "commandName": "getMore", "databaseName": "test", "command": { "getMore": { "$$type": [ "int", "long" ] }, "collection": "coll", "maxTimeMS": { "$$exists": false } } } } ] } ] }, { "description": "timeoutMS applied to find if timeoutMode is iteration", "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "find" ], "blockConnection": true, "blockTimeMS": 15 } } } }, { "name": "find", "object": "collection", "arguments": { "filter": {}, "timeoutMode": "iteration" }, "expectError": { "isTimeoutError": true } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "find", "databaseName": "test", "command": { "find": "coll", "maxTimeMS": { "$$exists": false } } } } ] } ] }, { "description": "timeoutMS is refreshed for getMore if timeoutMode is iteration - success", "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 2 }, "data": { "failCommands": [ "find", "getMore" ], "blockConnection": true, "blockTimeMS": 15 } } } }, { "name": "find", "object": "collection", "arguments": { "filter": {}, "timeoutMode": "iteration", "timeoutMS": 20, "batchSize": 2 } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "find", "databaseName": "test", "command": { "find": "coll", "maxTimeMS": { "$$exists": false } } } }, { "commandStartedEvent": { "commandName": "getMore", "databaseName": "test", "command": { "getMore": { "$$type": [ "int", "long" ] }, "collection": "coll", "maxTimeMS": { "$$exists": false } } } } ] } ] }, { "description": "timeoutMS is refreshed for getMore if timeoutMode is iteration - failure", "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "getMore" ], "blockConnection": true, "blockTimeMS": 15 } } } }, { "name": "find", "object": "collection", "arguments": { "filter": {}, "timeoutMode": "iteration", "batchSize": 2 }, "expectError": { "isTimeoutError": true } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "find", "databaseName": "test", "command": { "find": "coll", "maxTimeMS": { "$$exists": false } } } }, { "commandStartedEvent": { "commandName": "getMore", "databaseName": "test", "command": { "getMore": { "$$type": [ "int", "long" ] }, "collection": "coll", "maxTimeMS": { "$$exists": false } } } } ] } ] }, { "description": "aggregate with $out errors if timeoutMode is iteration", "operations": [ { "name": "aggregate", "object": "collection", "arguments": { "pipeline": [ { "$out": "aggregateOutputColl" } ], "timeoutMS": 100, "timeoutMode": "iteration" }, "expectError": { "isClientError": true } } ], "expectEvents": [ { "client": "client", "events": [] } ] }, { "description": "aggregate with $merge errors if timeoutMode is iteration", "operations": [ { "name": "aggregate", "object": "collection", "arguments": { "pipeline": [ { "$merge": "aggregateOutputColl" } ], "timeoutMS": 100, "timeoutMode": "iteration" }, "expectError": { "isClientError": true } } ], "expectEvents": [ { "client": "client", "events": [] } ] } ] } mongodb-mongo-python-driver-509e9b7/test/csot/override-operation-timeoutMS.json000066400000000000000000002550531462766011000300320ustar00rootroot00000000000000{ "description": "timeoutMS can be overridden for an operation", "schemaVersion": "1.9", "runOnRequirements": [ { "minServerVersion": "4.4", "topologies": [ "replicaset", "sharded-replicaset" ] } ], "createEntities": [ { "client": { "id": "failPointClient", "useMultipleMongoses": false } }, { "client": { "id": "client", "uriOptions": { "timeoutMS": 10 }, "useMultipleMongoses": false, "observeEvents": [ "commandStartedEvent" ], "ignoreCommandMonitoringEvents": [ "killCursors" ] } }, { "database": { "id": "database", "client": "client", "databaseName": "test" } }, { "collection": { "id": "collection", "database": "database", "collectionName": "coll" } } ], "initialData": [ { "collectionName": "coll", "databaseName": "test", "documents": [] } ], "tests": [ { "description": "timeoutMS can be configured for an operation - listDatabases on client", "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "listDatabases" ], "blockConnection": true, "blockTimeMS": 15 } } } }, { "name": "listDatabases", "object": "client", "arguments": { "timeoutMS": 1000, "filter": {} } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "listDatabases", "databaseName": "admin", "command": { "listDatabases": 1, "maxTimeMS": { "$$type": [ "int", "long" ] } } } } ] } ] }, { "description": "timeoutMS can be set to 0 for an operation - listDatabases on client", "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "listDatabases" ], "blockConnection": true, "blockTimeMS": 15 } } } }, { "name": "listDatabases", "object": "client", "arguments": { "timeoutMS": 0, "filter": {} } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "listDatabases", "databaseName": "admin", "command": { "listDatabases": 1, "maxTimeMS": { "$$exists": false } } } } ] } ] }, { "description": "timeoutMS can be configured for an operation - listDatabaseNames on client", "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "listDatabases" ], "blockConnection": true, "blockTimeMS": 15 } } } }, { "name": "listDatabaseNames", "object": "client", "arguments": { "timeoutMS": 1000 } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "listDatabases", "databaseName": "admin", "command": { "listDatabases": 1, "maxTimeMS": { "$$type": [ "int", "long" ] } } } } ] } ] }, { "description": "timeoutMS can be set to 0 for an operation - listDatabaseNames on client", "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "listDatabases" ], "blockConnection": true, "blockTimeMS": 15 } } } }, { "name": "listDatabaseNames", "object": "client", "arguments": { "timeoutMS": 0 } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "listDatabases", "databaseName": "admin", "command": { "listDatabases": 1, "maxTimeMS": { "$$exists": false } } } } ] } ] }, { "description": "timeoutMS can be configured for an operation - createChangeStream on client", "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "aggregate" ], "blockConnection": true, "blockTimeMS": 15 } } } }, { "name": "createChangeStream", "object": "client", "arguments": { "timeoutMS": 1000, "pipeline": [] } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "aggregate", "databaseName": "admin", "command": { "aggregate": 1, "maxTimeMS": { "$$type": [ "int", "long" ] } } } } ] } ] }, { "description": "timeoutMS can be set to 0 for an operation - createChangeStream on client", "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "aggregate" ], "blockConnection": true, "blockTimeMS": 15 } } } }, { "name": "createChangeStream", "object": "client", "arguments": { "timeoutMS": 0, "pipeline": [] } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "aggregate", "databaseName": "admin", "command": { "aggregate": 1, "maxTimeMS": { "$$exists": false } } } } ] } ] }, { "description": "timeoutMS can be configured for an operation - aggregate on database", "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "aggregate" ], "blockConnection": true, "blockTimeMS": 15 } } } }, { "name": "aggregate", "object": "database", "arguments": { "timeoutMS": 1000, "pipeline": [ { "$listLocalSessions": {} }, { "$limit": 1 } ] } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "aggregate", "databaseName": "test", "command": { "aggregate": 1, "maxTimeMS": { "$$type": [ "int", "long" ] } } } } ] } ] }, { "description": "timeoutMS can be set to 0 for an operation - aggregate on database", "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "aggregate" ], "blockConnection": true, "blockTimeMS": 15 } } } }, { "name": "aggregate", "object": "database", "arguments": { "timeoutMS": 0, "pipeline": [ { "$listLocalSessions": {} }, { "$limit": 1 } ] } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "aggregate", "databaseName": "test", "command": { "aggregate": 1, "maxTimeMS": { "$$exists": false } } } } ] } ] }, { "description": "timeoutMS can be configured for an operation - listCollections on database", "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "listCollections" ], "blockConnection": true, "blockTimeMS": 15 } } } }, { "name": "listCollections", "object": "database", "arguments": { "timeoutMS": 1000, "filter": {} } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "listCollections", "databaseName": "test", "command": { "listCollections": 1, "maxTimeMS": { "$$type": [ "int", "long" ] } } } } ] } ] }, { "description": "timeoutMS can be set to 0 for an operation - listCollections on database", "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "listCollections" ], "blockConnection": true, "blockTimeMS": 15 } } } }, { "name": "listCollections", "object": "database", "arguments": { "timeoutMS": 0, "filter": {} } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "listCollections", "databaseName": "test", "command": { "listCollections": 1, "maxTimeMS": { "$$exists": false } } } } ] } ] }, { "description": "timeoutMS can be configured for an operation - listCollectionNames on database", "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "listCollections" ], "blockConnection": true, "blockTimeMS": 15 } } } }, { "name": "listCollectionNames", "object": "database", "arguments": { "timeoutMS": 1000, "filter": {} } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "listCollections", "databaseName": "test", "command": { "listCollections": 1, "maxTimeMS": { "$$type": [ "int", "long" ] } } } } ] } ] }, { "description": "timeoutMS can be set to 0 for an operation - listCollectionNames on database", "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "listCollections" ], "blockConnection": true, "blockTimeMS": 15 } } } }, { "name": "listCollectionNames", "object": "database", "arguments": { "timeoutMS": 0, "filter": {} } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "listCollections", "databaseName": "test", "command": { "listCollections": 1, "maxTimeMS": { "$$exists": false } } } } ] } ] }, { "description": "timeoutMS can be configured for an operation - runCommand on database", "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "ping" ], "blockConnection": true, "blockTimeMS": 15 } } } }, { "name": "runCommand", "object": "database", "arguments": { "timeoutMS": 1000, "command": { "ping": 1 }, "commandName": "ping" } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "ping", "databaseName": "test", "command": { "ping": 1, "maxTimeMS": { "$$type": [ "int", "long" ] } } } } ] } ] }, { "description": "timeoutMS can be set to 0 for an operation - runCommand on database", "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "ping" ], "blockConnection": true, "blockTimeMS": 15 } } } }, { "name": "runCommand", "object": "database", "arguments": { "timeoutMS": 0, "command": { "ping": 1 }, "commandName": "ping" } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "ping", "databaseName": "test", "command": { "ping": 1, "maxTimeMS": { "$$exists": false } } } } ] } ] }, { "description": "timeoutMS can be configured for an operation - createChangeStream on database", "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "aggregate" ], "blockConnection": true, "blockTimeMS": 15 } } } }, { "name": "createChangeStream", "object": "database", "arguments": { "timeoutMS": 1000, "pipeline": [] } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "aggregate", "databaseName": "test", "command": { "aggregate": 1, "maxTimeMS": { "$$type": [ "int", "long" ] } } } } ] } ] }, { "description": "timeoutMS can be set to 0 for an operation - createChangeStream on database", "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "aggregate" ], "blockConnection": true, "blockTimeMS": 15 } } } }, { "name": "createChangeStream", "object": "database", "arguments": { "timeoutMS": 0, "pipeline": [] } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "aggregate", "databaseName": "test", "command": { "aggregate": 1, "maxTimeMS": { "$$exists": false } } } } ] } ] }, { "description": "timeoutMS can be configured for an operation - aggregate on collection", "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "aggregate" ], "blockConnection": true, "blockTimeMS": 15 } } } }, { "name": "aggregate", "object": "collection", "arguments": { "timeoutMS": 1000, "pipeline": [] } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "aggregate", "databaseName": "test", "command": { "aggregate": "coll", "maxTimeMS": { "$$type": [ "int", "long" ] } } } } ] } ] }, { "description": "timeoutMS can be set to 0 for an operation - aggregate on collection", "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "aggregate" ], "blockConnection": true, "blockTimeMS": 15 } } } }, { "name": "aggregate", "object": "collection", "arguments": { "timeoutMS": 0, "pipeline": [] } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "aggregate", "databaseName": "test", "command": { "aggregate": "coll", "maxTimeMS": { "$$exists": false } } } } ] } ] }, { "description": "timeoutMS can be configured for an operation - count on collection", "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "count" ], "blockConnection": true, "blockTimeMS": 15 } } } }, { "name": "count", "object": "collection", "arguments": { "timeoutMS": 1000, "filter": {} } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "count", "databaseName": "test", "command": { "count": "coll", "maxTimeMS": { "$$type": [ "int", "long" ] } } } } ] } ] }, { "description": "timeoutMS can be set to 0 for an operation - count on collection", "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "count" ], "blockConnection": true, "blockTimeMS": 15 } } } }, { "name": "count", "object": "collection", "arguments": { "timeoutMS": 0, "filter": {} } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "count", "databaseName": "test", "command": { "count": "coll", "maxTimeMS": { "$$exists": false } } } } ] } ] }, { "description": "timeoutMS can be configured for an operation - countDocuments on collection", "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "aggregate" ], "blockConnection": true, "blockTimeMS": 15 } } } }, { "name": "countDocuments", "object": "collection", "arguments": { "timeoutMS": 1000, "filter": {} } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "aggregate", "databaseName": "test", "command": { "aggregate": "coll", "maxTimeMS": { "$$type": [ "int", "long" ] } } } } ] } ] }, { "description": "timeoutMS can be set to 0 for an operation - countDocuments on collection", "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "aggregate" ], "blockConnection": true, "blockTimeMS": 15 } } } }, { "name": "countDocuments", "object": "collection", "arguments": { "timeoutMS": 0, "filter": {} } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "aggregate", "databaseName": "test", "command": { "aggregate": "coll", "maxTimeMS": { "$$exists": false } } } } ] } ] }, { "description": "timeoutMS can be configured for an operation - estimatedDocumentCount on collection", "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "count" ], "blockConnection": true, "blockTimeMS": 15 } } } }, { "name": "estimatedDocumentCount", "object": "collection", "arguments": { "timeoutMS": 1000 } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "count", "databaseName": "test", "command": { "count": "coll", "maxTimeMS": { "$$type": [ "int", "long" ] } } } } ] } ] }, { "description": "timeoutMS can be set to 0 for an operation - estimatedDocumentCount on collection", "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "count" ], "blockConnection": true, "blockTimeMS": 15 } } } }, { "name": "estimatedDocumentCount", "object": "collection", "arguments": { "timeoutMS": 0 } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "count", "databaseName": "test", "command": { "count": "coll", "maxTimeMS": { "$$exists": false } } } } ] } ] }, { "description": "timeoutMS can be configured for an operation - distinct on collection", "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "distinct" ], "blockConnection": true, "blockTimeMS": 15 } } } }, { "name": "distinct", "object": "collection", "arguments": { "timeoutMS": 1000, "fieldName": "x", "filter": {} } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "distinct", "databaseName": "test", "command": { "distinct": "coll", "maxTimeMS": { "$$type": [ "int", "long" ] } } } } ] } ] }, { "description": "timeoutMS can be set to 0 for an operation - distinct on collection", "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "distinct" ], "blockConnection": true, "blockTimeMS": 15 } } } }, { "name": "distinct", "object": "collection", "arguments": { "timeoutMS": 0, "fieldName": "x", "filter": {} } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "distinct", "databaseName": "test", "command": { "distinct": "coll", "maxTimeMS": { "$$exists": false } } } } ] } ] }, { "description": "timeoutMS can be configured for an operation - find on collection", "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "find" ], "blockConnection": true, "blockTimeMS": 15 } } } }, { "name": "find", "object": "collection", "arguments": { "timeoutMS": 1000, "filter": {} } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "find", "databaseName": "test", "command": { "find": "coll", "maxTimeMS": { "$$type": [ "int", "long" ] } } } } ] } ] }, { "description": "timeoutMS can be set to 0 for an operation - find on collection", "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "find" ], "blockConnection": true, "blockTimeMS": 15 } } } }, { "name": "find", "object": "collection", "arguments": { "timeoutMS": 0, "filter": {} } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "find", "databaseName": "test", "command": { "find": "coll", "maxTimeMS": { "$$exists": false } } } } ] } ] }, { "description": "timeoutMS can be configured for an operation - findOne on collection", "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "find" ], "blockConnection": true, "blockTimeMS": 15 } } } }, { "name": "findOne", "object": "collection", "arguments": { "timeoutMS": 1000, "filter": {} } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "find", "databaseName": "test", "command": { "find": "coll", "maxTimeMS": { "$$type": [ "int", "long" ] } } } } ] } ] }, { "description": "timeoutMS can be set to 0 for an operation - findOne on collection", "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "find" ], "blockConnection": true, "blockTimeMS": 15 } } } }, { "name": "findOne", "object": "collection", "arguments": { "timeoutMS": 0, "filter": {} } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "find", "databaseName": "test", "command": { "find": "coll", "maxTimeMS": { "$$exists": false } } } } ] } ] }, { "description": "timeoutMS can be configured for an operation - listIndexes on collection", "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "listIndexes" ], "blockConnection": true, "blockTimeMS": 15 } } } }, { "name": "listIndexes", "object": "collection", "arguments": { "timeoutMS": 1000 } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "listIndexes", "databaseName": "test", "command": { "listIndexes": "coll", "maxTimeMS": { "$$type": [ "int", "long" ] } } } } ] } ] }, { "description": "timeoutMS can be set to 0 for an operation - listIndexes on collection", "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "listIndexes" ], "blockConnection": true, "blockTimeMS": 15 } } } }, { "name": "listIndexes", "object": "collection", "arguments": { "timeoutMS": 0 } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "listIndexes", "databaseName": "test", "command": { "listIndexes": "coll", "maxTimeMS": { "$$exists": false } } } } ] } ] }, { "description": "timeoutMS can be configured for an operation - listIndexNames on collection", "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "listIndexes" ], "blockConnection": true, "blockTimeMS": 15 } } } }, { "name": "listIndexNames", "object": "collection", "arguments": { "timeoutMS": 1000 } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "listIndexes", "databaseName": "test", "command": { "listIndexes": "coll", "maxTimeMS": { "$$type": [ "int", "long" ] } } } } ] } ] }, { "description": "timeoutMS can be set to 0 for an operation - listIndexNames on collection", "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "listIndexes" ], "blockConnection": true, "blockTimeMS": 15 } } } }, { "name": "listIndexNames", "object": "collection", "arguments": { "timeoutMS": 0 } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "listIndexes", "databaseName": "test", "command": { "listIndexes": "coll", "maxTimeMS": { "$$exists": false } } } } ] } ] }, { "description": "timeoutMS can be configured for an operation - createChangeStream on collection", "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "aggregate" ], "blockConnection": true, "blockTimeMS": 15 } } } }, { "name": "createChangeStream", "object": "collection", "arguments": { "timeoutMS": 1000, "pipeline": [] } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "aggregate", "databaseName": "test", "command": { "aggregate": "coll", "maxTimeMS": { "$$type": [ "int", "long" ] } } } } ] } ] }, { "description": "timeoutMS can be set to 0 for an operation - createChangeStream on collection", "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "aggregate" ], "blockConnection": true, "blockTimeMS": 15 } } } }, { "name": "createChangeStream", "object": "collection", "arguments": { "timeoutMS": 0, "pipeline": [] } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "aggregate", "databaseName": "test", "command": { "aggregate": "coll", "maxTimeMS": { "$$exists": false } } } } ] } ] }, { "description": "timeoutMS can be configured for an operation - insertOne on collection", "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "insert" ], "blockConnection": true, "blockTimeMS": 15 } } } }, { "name": "insertOne", "object": "collection", "arguments": { "timeoutMS": 1000, "document": { "x": 1 } } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "insert", "databaseName": "test", "command": { "insert": "coll", "maxTimeMS": { "$$type": [ "int", "long" ] } } } } ] } ] }, { "description": "timeoutMS can be set to 0 for an operation - insertOne on collection", "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "insert" ], "blockConnection": true, "blockTimeMS": 15 } } } }, { "name": "insertOne", "object": "collection", "arguments": { "timeoutMS": 0, "document": { "x": 1 } } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "insert", "databaseName": "test", "command": { "insert": "coll", "maxTimeMS": { "$$exists": false } } } } ] } ] }, { "description": "timeoutMS can be configured for an operation - insertMany on collection", "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "insert" ], "blockConnection": true, "blockTimeMS": 15 } } } }, { "name": "insertMany", "object": "collection", "arguments": { "timeoutMS": 1000, "documents": [ { "x": 1 } ] } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "insert", "databaseName": "test", "command": { "insert": "coll", "maxTimeMS": { "$$type": [ "int", "long" ] } } } } ] } ] }, { "description": "timeoutMS can be set to 0 for an operation - insertMany on collection", "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "insert" ], "blockConnection": true, "blockTimeMS": 15 } } } }, { "name": "insertMany", "object": "collection", "arguments": { "timeoutMS": 0, "documents": [ { "x": 1 } ] } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "insert", "databaseName": "test", "command": { "insert": "coll", "maxTimeMS": { "$$exists": false } } } } ] } ] }, { "description": "timeoutMS can be configured for an operation - deleteOne on collection", "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "delete" ], "blockConnection": true, "blockTimeMS": 15 } } } }, { "name": "deleteOne", "object": "collection", "arguments": { "timeoutMS": 1000, "filter": {} } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "delete", "databaseName": "test", "command": { "delete": "coll", "maxTimeMS": { "$$type": [ "int", "long" ] } } } } ] } ] }, { "description": "timeoutMS can be set to 0 for an operation - deleteOne on collection", "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "delete" ], "blockConnection": true, "blockTimeMS": 15 } } } }, { "name": "deleteOne", "object": "collection", "arguments": { "timeoutMS": 0, "filter": {} } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "delete", "databaseName": "test", "command": { "delete": "coll", "maxTimeMS": { "$$exists": false } } } } ] } ] }, { "description": "timeoutMS can be configured for an operation - deleteMany on collection", "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "delete" ], "blockConnection": true, "blockTimeMS": 15 } } } }, { "name": "deleteMany", "object": "collection", "arguments": { "timeoutMS": 1000, "filter": {} } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "delete", "databaseName": "test", "command": { "delete": "coll", "maxTimeMS": { "$$type": [ "int", "long" ] } } } } ] } ] }, { "description": "timeoutMS can be set to 0 for an operation - deleteMany on collection", "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "delete" ], "blockConnection": true, "blockTimeMS": 15 } } } }, { "name": "deleteMany", "object": "collection", "arguments": { "timeoutMS": 0, "filter": {} } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "delete", "databaseName": "test", "command": { "delete": "coll", "maxTimeMS": { "$$exists": false } } } } ] } ] }, { "description": "timeoutMS can be configured for an operation - replaceOne on collection", "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "update" ], "blockConnection": true, "blockTimeMS": 15 } } } }, { "name": "replaceOne", "object": "collection", "arguments": { "timeoutMS": 1000, "filter": {}, "replacement": { "x": 1 } } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "update", "databaseName": "test", "command": { "update": "coll", "maxTimeMS": { "$$type": [ "int", "long" ] } } } } ] } ] }, { "description": "timeoutMS can be set to 0 for an operation - replaceOne on collection", "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "update" ], "blockConnection": true, "blockTimeMS": 15 } } } }, { "name": "replaceOne", "object": "collection", "arguments": { "timeoutMS": 0, "filter": {}, "replacement": { "x": 1 } } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "update", "databaseName": "test", "command": { "update": "coll", "maxTimeMS": { "$$exists": false } } } } ] } ] }, { "description": "timeoutMS can be configured for an operation - updateOne on collection", "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "update" ], "blockConnection": true, "blockTimeMS": 15 } } } }, { "name": "updateOne", "object": "collection", "arguments": { "timeoutMS": 1000, "filter": {}, "update": { "$set": { "x": 1 } } } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "update", "databaseName": "test", "command": { "update": "coll", "maxTimeMS": { "$$type": [ "int", "long" ] } } } } ] } ] }, { "description": "timeoutMS can be set to 0 for an operation - updateOne on collection", "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "update" ], "blockConnection": true, "blockTimeMS": 15 } } } }, { "name": "updateOne", "object": "collection", "arguments": { "timeoutMS": 0, "filter": {}, "update": { "$set": { "x": 1 } } } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "update", "databaseName": "test", "command": { "update": "coll", "maxTimeMS": { "$$exists": false } } } } ] } ] }, { "description": "timeoutMS can be configured for an operation - updateMany on collection", "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "update" ], "blockConnection": true, "blockTimeMS": 15 } } } }, { "name": "updateMany", "object": "collection", "arguments": { "timeoutMS": 1000, "filter": {}, "update": { "$set": { "x": 1 } } } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "update", "databaseName": "test", "command": { "update": "coll", "maxTimeMS": { "$$type": [ "int", "long" ] } } } } ] } ] }, { "description": "timeoutMS can be set to 0 for an operation - updateMany on collection", "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "update" ], "blockConnection": true, "blockTimeMS": 15 } } } }, { "name": "updateMany", "object": "collection", "arguments": { "timeoutMS": 0, "filter": {}, "update": { "$set": { "x": 1 } } } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "update", "databaseName": "test", "command": { "update": "coll", "maxTimeMS": { "$$exists": false } } } } ] } ] }, { "description": "timeoutMS can be configured for an operation - findOneAndDelete on collection", "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "findAndModify" ], "blockConnection": true, "blockTimeMS": 15 } } } }, { "name": "findOneAndDelete", "object": "collection", "arguments": { "timeoutMS": 1000, "filter": {} } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "findAndModify", "databaseName": "test", "command": { "findAndModify": "coll", "maxTimeMS": { "$$type": [ "int", "long" ] } } } } ] } ] }, { "description": "timeoutMS can be set to 0 for an operation - findOneAndDelete on collection", "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "findAndModify" ], "blockConnection": true, "blockTimeMS": 15 } } } }, { "name": "findOneAndDelete", "object": "collection", "arguments": { "timeoutMS": 0, "filter": {} } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "findAndModify", "databaseName": "test", "command": { "findAndModify": "coll", "maxTimeMS": { "$$exists": false } } } } ] } ] }, { "description": "timeoutMS can be configured for an operation - findOneAndReplace on collection", "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "findAndModify" ], "blockConnection": true, "blockTimeMS": 15 } } } }, { "name": "findOneAndReplace", "object": "collection", "arguments": { "timeoutMS": 1000, "filter": {}, "replacement": { "x": 1 } } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "findAndModify", "databaseName": "test", "command": { "findAndModify": "coll", "maxTimeMS": { "$$type": [ "int", "long" ] } } } } ] } ] }, { "description": "timeoutMS can be set to 0 for an operation - findOneAndReplace on collection", "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "findAndModify" ], "blockConnection": true, "blockTimeMS": 15 } } } }, { "name": "findOneAndReplace", "object": "collection", "arguments": { "timeoutMS": 0, "filter": {}, "replacement": { "x": 1 } } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "findAndModify", "databaseName": "test", "command": { "findAndModify": "coll", "maxTimeMS": { "$$exists": false } } } } ] } ] }, { "description": "timeoutMS can be configured for an operation - findOneAndUpdate on collection", "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "findAndModify" ], "blockConnection": true, "blockTimeMS": 15 } } } }, { "name": "findOneAndUpdate", "object": "collection", "arguments": { "timeoutMS": 1000, "filter": {}, "update": { "$set": { "x": 1 } } } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "findAndModify", "databaseName": "test", "command": { "findAndModify": "coll", "maxTimeMS": { "$$type": [ "int", "long" ] } } } } ] } ] }, { "description": "timeoutMS can be set to 0 for an operation - findOneAndUpdate on collection", "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "findAndModify" ], "blockConnection": true, "blockTimeMS": 15 } } } }, { "name": "findOneAndUpdate", "object": "collection", "arguments": { "timeoutMS": 0, "filter": {}, "update": { "$set": { "x": 1 } } } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "findAndModify", "databaseName": "test", "command": { "findAndModify": "coll", "maxTimeMS": { "$$exists": false } } } } ] } ] }, { "description": "timeoutMS can be configured for an operation - bulkWrite on collection", "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "insert" ], "blockConnection": true, "blockTimeMS": 15 } } } }, { "name": "bulkWrite", "object": "collection", "arguments": { "timeoutMS": 1000, "requests": [ { "insertOne": { "document": { "_id": 1 } } } ] } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "insert", "databaseName": "test", "command": { "insert": "coll", "maxTimeMS": { "$$type": [ "int", "long" ] } } } } ] } ] }, { "description": "timeoutMS can be set to 0 for an operation - bulkWrite on collection", "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "insert" ], "blockConnection": true, "blockTimeMS": 15 } } } }, { "name": "bulkWrite", "object": "collection", "arguments": { "timeoutMS": 0, "requests": [ { "insertOne": { "document": { "_id": 1 } } } ] } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "insert", "databaseName": "test", "command": { "insert": "coll", "maxTimeMS": { "$$exists": false } } } } ] } ] }, { "description": "timeoutMS can be configured for an operation - createIndex on collection", "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "createIndexes" ], "blockConnection": true, "blockTimeMS": 15 } } } }, { "name": "createIndex", "object": "collection", "arguments": { "timeoutMS": 1000, "keys": { "x": 1 }, "name": "x_1" } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "createIndexes", "databaseName": "test", "command": { "createIndexes": "coll", "maxTimeMS": { "$$type": [ "int", "long" ] } } } } ] } ] }, { "description": "timeoutMS can be set to 0 for an operation - createIndex on collection", "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "createIndexes" ], "blockConnection": true, "blockTimeMS": 15 } } } }, { "name": "createIndex", "object": "collection", "arguments": { "timeoutMS": 0, "keys": { "x": 1 }, "name": "x_1" } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "createIndexes", "databaseName": "test", "command": { "createIndexes": "coll", "maxTimeMS": { "$$exists": false } } } } ] } ] }, { "description": "timeoutMS can be configured for an operation - dropIndex on collection", "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "dropIndexes" ], "blockConnection": true, "blockTimeMS": 15 } } } }, { "name": "dropIndex", "object": "collection", "arguments": { "timeoutMS": 1000, "name": "x_1" }, "expectError": { "isTimeoutError": false } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "dropIndexes", "databaseName": "test", "command": { "dropIndexes": "coll", "maxTimeMS": { "$$type": [ "int", "long" ] } } } } ] } ] }, { "description": "timeoutMS can be set to 0 for an operation - dropIndex on collection", "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "dropIndexes" ], "blockConnection": true, "blockTimeMS": 15 } } } }, { "name": "dropIndex", "object": "collection", "arguments": { "timeoutMS": 0, "name": "x_1" }, "expectError": { "isTimeoutError": false } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "dropIndexes", "databaseName": "test", "command": { "dropIndexes": "coll", "maxTimeMS": { "$$exists": false } } } } ] } ] }, { "description": "timeoutMS can be configured for an operation - dropIndexes on collection", "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "dropIndexes" ], "blockConnection": true, "blockTimeMS": 15 } } } }, { "name": "dropIndexes", "object": "collection", "arguments": { "timeoutMS": 1000 } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "dropIndexes", "databaseName": "test", "command": { "dropIndexes": "coll", "maxTimeMS": { "$$type": [ "int", "long" ] } } } } ] } ] }, { "description": "timeoutMS can be set to 0 for an operation - dropIndexes on collection", "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "dropIndexes" ], "blockConnection": true, "blockTimeMS": 15 } } } }, { "name": "dropIndexes", "object": "collection", "arguments": { "timeoutMS": 0 } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "dropIndexes", "databaseName": "test", "command": { "dropIndexes": "coll", "maxTimeMS": { "$$exists": false } } } } ] } ] } ] } mongodb-mongo-python-driver-509e9b7/test/csot/retryability-legacy-timeouts.json000066400000000000000000002243451462766011000301250ustar00rootroot00000000000000{ "description": "legacy timeouts behave correctly for retryable operations", "schemaVersion": "1.9", "runOnRequirements": [ { "minServerVersion": "4.4", "topologies": [ "replicaset", "sharded-replicaset" ] } ], "createEntities": [ { "client": { "id": "failPointClient", "useMultipleMongoses": false } }, { "client": { "id": "client", "uriOptions": { "socketTimeoutMS": 100 }, "useMultipleMongoses": false, "observeEvents": [ "commandStartedEvent" ], "ignoreCommandMonitoringEvents": [ "killCursors" ] } }, { "database": { "id": "database", "client": "client", "databaseName": "test" } }, { "collection": { "id": "collection", "database": "database", "collectionName": "coll" } } ], "initialData": [ { "collectionName": "coll", "databaseName": "test", "documents": [] } ], "tests": [ { "description": "operation succeeds after one socket timeout - insertOne on collection", "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "insert" ], "blockConnection": true, "blockTimeMS": 125 } } } }, { "name": "insertOne", "object": "collection", "arguments": { "document": { "x": 1 } } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "insert", "databaseName": "test", "command": { "insert": "coll" } } }, { "commandStartedEvent": { "commandName": "insert", "databaseName": "test", "command": { "insert": "coll" } } } ] } ] }, { "description": "operation fails after two consecutive socket timeouts - insertOne on collection", "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 2 }, "data": { "failCommands": [ "insert" ], "blockConnection": true, "blockTimeMS": 125 } } } }, { "name": "insertOne", "object": "collection", "arguments": { "document": { "x": 1 } }, "expectError": { "isClientError": true } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "insert", "databaseName": "test", "command": { "insert": "coll" } } }, { "commandStartedEvent": { "commandName": "insert", "databaseName": "test", "command": { "insert": "coll" } } } ] } ] }, { "description": "operation succeeds after one socket timeout - insertMany on collection", "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "insert" ], "blockConnection": true, "blockTimeMS": 125 } } } }, { "name": "insertMany", "object": "collection", "arguments": { "documents": [ { "x": 1 } ] } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "insert", "databaseName": "test", "command": { "insert": "coll" } } }, { "commandStartedEvent": { "commandName": "insert", "databaseName": "test", "command": { "insert": "coll" } } } ] } ] }, { "description": "operation fails after two consecutive socket timeouts - insertMany on collection", "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 2 }, "data": { "failCommands": [ "insert" ], "blockConnection": true, "blockTimeMS": 125 } } } }, { "name": "insertMany", "object": "collection", "arguments": { "documents": [ { "x": 1 } ] }, "expectError": { "isClientError": true } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "insert", "databaseName": "test", "command": { "insert": "coll" } } }, { "commandStartedEvent": { "commandName": "insert", "databaseName": "test", "command": { "insert": "coll" } } } ] } ] }, { "description": "operation succeeds after one socket timeout - deleteOne on collection", "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "delete" ], "blockConnection": true, "blockTimeMS": 125 } } } }, { "name": "deleteOne", "object": "collection", "arguments": { "filter": {} } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "delete", "databaseName": "test", "command": { "delete": "coll" } } }, { "commandStartedEvent": { "commandName": "delete", "databaseName": "test", "command": { "delete": "coll" } } } ] } ] }, { "description": "operation fails after two consecutive socket timeouts - deleteOne on collection", "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 2 }, "data": { "failCommands": [ "delete" ], "blockConnection": true, "blockTimeMS": 125 } } } }, { "name": "deleteOne", "object": "collection", "arguments": { "filter": {} }, "expectError": { "isClientError": true } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "delete", "databaseName": "test", "command": { "delete": "coll" } } }, { "commandStartedEvent": { "commandName": "delete", "databaseName": "test", "command": { "delete": "coll" } } } ] } ] }, { "description": "operation succeeds after one socket timeout - replaceOne on collection", "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "update" ], "blockConnection": true, "blockTimeMS": 125 } } } }, { "name": "replaceOne", "object": "collection", "arguments": { "filter": {}, "replacement": { "x": 1 } } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "update", "databaseName": "test", "command": { "update": "coll" } } }, { "commandStartedEvent": { "commandName": "update", "databaseName": "test", "command": { "update": "coll" } } } ] } ] }, { "description": "operation fails after two consecutive socket timeouts - replaceOne on collection", "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 2 }, "data": { "failCommands": [ "update" ], "blockConnection": true, "blockTimeMS": 125 } } } }, { "name": "replaceOne", "object": "collection", "arguments": { "filter": {}, "replacement": { "x": 1 } }, "expectError": { "isClientError": true } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "update", "databaseName": "test", "command": { "update": "coll" } } }, { "commandStartedEvent": { "commandName": "update", "databaseName": "test", "command": { "update": "coll" } } } ] } ] }, { "description": "operation succeeds after one socket timeout - updateOne on collection", "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "update" ], "blockConnection": true, "blockTimeMS": 125 } } } }, { "name": "updateOne", "object": "collection", "arguments": { "filter": {}, "update": { "$set": { "x": 1 } } } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "update", "databaseName": "test", "command": { "update": "coll" } } }, { "commandStartedEvent": { "commandName": "update", "databaseName": "test", "command": { "update": "coll" } } } ] } ] }, { "description": "operation fails after two consecutive socket timeouts - updateOne on collection", "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 2 }, "data": { "failCommands": [ "update" ], "blockConnection": true, "blockTimeMS": 125 } } } }, { "name": "updateOne", "object": "collection", "arguments": { "filter": {}, "update": { "$set": { "x": 1 } } }, "expectError": { "isClientError": true } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "update", "databaseName": "test", "command": { "update": "coll" } } }, { "commandStartedEvent": { "commandName": "update", "databaseName": "test", "command": { "update": "coll" } } } ] } ] }, { "description": "operation succeeds after one socket timeout - findOneAndDelete on collection", "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "findAndModify" ], "blockConnection": true, "blockTimeMS": 125 } } } }, { "name": "findOneAndDelete", "object": "collection", "arguments": { "filter": {} } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "findAndModify", "databaseName": "test", "command": { "findAndModify": "coll" } } }, { "commandStartedEvent": { "commandName": "findAndModify", "databaseName": "test", "command": { "findAndModify": "coll" } } } ] } ] }, { "description": "operation fails after two consecutive socket timeouts - findOneAndDelete on collection", "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 2 }, "data": { "failCommands": [ "findAndModify" ], "blockConnection": true, "blockTimeMS": 125 } } } }, { "name": "findOneAndDelete", "object": "collection", "arguments": { "filter": {} }, "expectError": { "isClientError": true } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "findAndModify", "databaseName": "test", "command": { "findAndModify": "coll" } } }, { "commandStartedEvent": { "commandName": "findAndModify", "databaseName": "test", "command": { "findAndModify": "coll" } } } ] } ] }, { "description": "operation succeeds after one socket timeout - findOneAndReplace on collection", "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "findAndModify" ], "blockConnection": true, "blockTimeMS": 125 } } } }, { "name": "findOneAndReplace", "object": "collection", "arguments": { "filter": {}, "replacement": { "x": 1 } } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "findAndModify", "databaseName": "test", "command": { "findAndModify": "coll" } } }, { "commandStartedEvent": { "commandName": "findAndModify", "databaseName": "test", "command": { "findAndModify": "coll" } } } ] } ] }, { "description": "operation fails after two consecutive socket timeouts - findOneAndReplace on collection", "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 2 }, "data": { "failCommands": [ "findAndModify" ], "blockConnection": true, "blockTimeMS": 125 } } } }, { "name": "findOneAndReplace", "object": "collection", "arguments": { "filter": {}, "replacement": { "x": 1 } }, "expectError": { "isClientError": true } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "findAndModify", "databaseName": "test", "command": { "findAndModify": "coll" } } }, { "commandStartedEvent": { "commandName": "findAndModify", "databaseName": "test", "command": { "findAndModify": "coll" } } } ] } ] }, { "description": "operation succeeds after one socket timeout - findOneAndUpdate on collection", "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "findAndModify" ], "blockConnection": true, "blockTimeMS": 125 } } } }, { "name": "findOneAndUpdate", "object": "collection", "arguments": { "filter": {}, "update": { "$set": { "x": 1 } } } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "findAndModify", "databaseName": "test", "command": { "findAndModify": "coll" } } }, { "commandStartedEvent": { "commandName": "findAndModify", "databaseName": "test", "command": { "findAndModify": "coll" } } } ] } ] }, { "description": "operation fails after two consecutive socket timeouts - findOneAndUpdate on collection", "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 2 }, "data": { "failCommands": [ "findAndModify" ], "blockConnection": true, "blockTimeMS": 125 } } } }, { "name": "findOneAndUpdate", "object": "collection", "arguments": { "filter": {}, "update": { "$set": { "x": 1 } } }, "expectError": { "isClientError": true } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "findAndModify", "databaseName": "test", "command": { "findAndModify": "coll" } } }, { "commandStartedEvent": { "commandName": "findAndModify", "databaseName": "test", "command": { "findAndModify": "coll" } } } ] } ] }, { "description": "operation succeeds after one socket timeout - bulkWrite on collection", "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "insert" ], "blockConnection": true, "blockTimeMS": 125 } } } }, { "name": "bulkWrite", "object": "collection", "arguments": { "requests": [ { "insertOne": { "document": { "_id": 1 } } } ] } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "insert", "databaseName": "test", "command": { "insert": "coll" } } }, { "commandStartedEvent": { "commandName": "insert", "databaseName": "test", "command": { "insert": "coll" } } } ] } ] }, { "description": "operation fails after two consecutive socket timeouts - bulkWrite on collection", "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 2 }, "data": { "failCommands": [ "insert" ], "blockConnection": true, "blockTimeMS": 125 } } } }, { "name": "bulkWrite", "object": "collection", "arguments": { "requests": [ { "insertOne": { "document": { "_id": 1 } } } ] }, "expectError": { "isClientError": true } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "insert", "databaseName": "test", "command": { "insert": "coll" } } }, { "commandStartedEvent": { "commandName": "insert", "databaseName": "test", "command": { "insert": "coll" } } } ] } ] }, { "description": "operation succeeds after one socket timeout - listDatabases on client", "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "listDatabases" ], "blockConnection": true, "blockTimeMS": 125 } } } }, { "name": "listDatabases", "object": "client", "arguments": { "filter": {} } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "listDatabases", "databaseName": "admin", "command": { "listDatabases": 1 } } }, { "commandStartedEvent": { "commandName": "listDatabases", "databaseName": "admin", "command": { "listDatabases": 1 } } } ] } ] }, { "description": "operation fails after two consecutive socket timeouts - listDatabases on client", "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 2 }, "data": { "failCommands": [ "listDatabases" ], "blockConnection": true, "blockTimeMS": 125 } } } }, { "name": "listDatabases", "object": "client", "arguments": { "filter": {} }, "expectError": { "isClientError": true } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "listDatabases", "databaseName": "admin", "command": { "listDatabases": 1 } } }, { "commandStartedEvent": { "commandName": "listDatabases", "databaseName": "admin", "command": { "listDatabases": 1 } } } ] } ] }, { "description": "operation succeeds after one socket timeout - listDatabaseNames on client", "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "listDatabases" ], "blockConnection": true, "blockTimeMS": 125 } } } }, { "name": "listDatabaseNames", "object": "client" } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "listDatabases", "databaseName": "admin", "command": { "listDatabases": 1 } } }, { "commandStartedEvent": { "commandName": "listDatabases", "databaseName": "admin", "command": { "listDatabases": 1 } } } ] } ] }, { "description": "operation fails after two consecutive socket timeouts - listDatabaseNames on client", "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 2 }, "data": { "failCommands": [ "listDatabases" ], "blockConnection": true, "blockTimeMS": 125 } } } }, { "name": "listDatabaseNames", "object": "client", "expectError": { "isClientError": true } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "listDatabases", "databaseName": "admin", "command": { "listDatabases": 1 } } }, { "commandStartedEvent": { "commandName": "listDatabases", "databaseName": "admin", "command": { "listDatabases": 1 } } } ] } ] }, { "description": "operation succeeds after one socket timeout - createChangeStream on client", "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "aggregate" ], "blockConnection": true, "blockTimeMS": 125 } } } }, { "name": "createChangeStream", "object": "client", "arguments": { "pipeline": [] } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "aggregate", "databaseName": "admin", "command": { "aggregate": 1 } } }, { "commandStartedEvent": { "commandName": "aggregate", "databaseName": "admin", "command": { "aggregate": 1 } } } ] } ] }, { "description": "operation fails after two consecutive socket timeouts - createChangeStream on client", "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 2 }, "data": { "failCommands": [ "aggregate" ], "blockConnection": true, "blockTimeMS": 125 } } } }, { "name": "createChangeStream", "object": "client", "arguments": { "pipeline": [] }, "expectError": { "isClientError": true } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "aggregate", "databaseName": "admin", "command": { "aggregate": 1 } } }, { "commandStartedEvent": { "commandName": "aggregate", "databaseName": "admin", "command": { "aggregate": 1 } } } ] } ] }, { "description": "operation succeeds after one socket timeout - aggregate on database", "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "aggregate" ], "blockConnection": true, "blockTimeMS": 125 } } } }, { "name": "aggregate", "object": "database", "arguments": { "pipeline": [ { "$listLocalSessions": {} }, { "$limit": 1 } ] } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "aggregate", "databaseName": "test", "command": { "aggregate": 1 } } }, { "commandStartedEvent": { "commandName": "aggregate", "databaseName": "test", "command": { "aggregate": 1 } } } ] } ] }, { "description": "operation fails after two consecutive socket timeouts - aggregate on database", "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 2 }, "data": { "failCommands": [ "aggregate" ], "blockConnection": true, "blockTimeMS": 125 } } } }, { "name": "aggregate", "object": "database", "arguments": { "pipeline": [ { "$listLocalSessions": {} }, { "$limit": 1 } ] }, "expectError": { "isClientError": true } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "aggregate", "databaseName": "test", "command": { "aggregate": 1 } } }, { "commandStartedEvent": { "commandName": "aggregate", "databaseName": "test", "command": { "aggregate": 1 } } } ] } ] }, { "description": "operation succeeds after one socket timeout - listCollections on database", "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "listCollections" ], "blockConnection": true, "blockTimeMS": 125 } } } }, { "name": "listCollections", "object": "database", "arguments": { "filter": {} } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "listCollections", "databaseName": "test", "command": { "listCollections": 1 } } }, { "commandStartedEvent": { "commandName": "listCollections", "databaseName": "test", "command": { "listCollections": 1 } } } ] } ] }, { "description": "operation fails after two consecutive socket timeouts - listCollections on database", "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 2 }, "data": { "failCommands": [ "listCollections" ], "blockConnection": true, "blockTimeMS": 125 } } } }, { "name": "listCollections", "object": "database", "arguments": { "filter": {} }, "expectError": { "isClientError": true } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "listCollections", "databaseName": "test", "command": { "listCollections": 1 } } }, { "commandStartedEvent": { "commandName": "listCollections", "databaseName": "test", "command": { "listCollections": 1 } } } ] } ] }, { "description": "operation succeeds after one socket timeout - listCollectionNames on database", "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "listCollections" ], "blockConnection": true, "blockTimeMS": 125 } } } }, { "name": "listCollectionNames", "object": "database", "arguments": { "filter": {} } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "listCollections", "databaseName": "test", "command": { "listCollections": 1 } } }, { "commandStartedEvent": { "commandName": "listCollections", "databaseName": "test", "command": { "listCollections": 1 } } } ] } ] }, { "description": "operation fails after two consecutive socket timeouts - listCollectionNames on database", "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 2 }, "data": { "failCommands": [ "listCollections" ], "blockConnection": true, "blockTimeMS": 125 } } } }, { "name": "listCollectionNames", "object": "database", "arguments": { "filter": {} }, "expectError": { "isClientError": true } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "listCollections", "databaseName": "test", "command": { "listCollections": 1 } } }, { "commandStartedEvent": { "commandName": "listCollections", "databaseName": "test", "command": { "listCollections": 1 } } } ] } ] }, { "description": "operation succeeds after one socket timeout - createChangeStream on database", "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "aggregate" ], "blockConnection": true, "blockTimeMS": 125 } } } }, { "name": "createChangeStream", "object": "database", "arguments": { "pipeline": [] } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "aggregate", "databaseName": "test", "command": { "aggregate": 1 } } }, { "commandStartedEvent": { "commandName": "aggregate", "databaseName": "test", "command": { "aggregate": 1 } } } ] } ] }, { "description": "operation fails after two consecutive socket timeouts - createChangeStream on database", "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 2 }, "data": { "failCommands": [ "aggregate" ], "blockConnection": true, "blockTimeMS": 125 } } } }, { "name": "createChangeStream", "object": "database", "arguments": { "pipeline": [] }, "expectError": { "isClientError": true } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "aggregate", "databaseName": "test", "command": { "aggregate": 1 } } }, { "commandStartedEvent": { "commandName": "aggregate", "databaseName": "test", "command": { "aggregate": 1 } } } ] } ] }, { "description": "operation succeeds after one socket timeout - aggregate on collection", "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "aggregate" ], "blockConnection": true, "blockTimeMS": 125 } } } }, { "name": "aggregate", "object": "collection", "arguments": { "pipeline": [] } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "aggregate", "databaseName": "test", "command": { "aggregate": "coll" } } }, { "commandStartedEvent": { "commandName": "aggregate", "databaseName": "test", "command": { "aggregate": "coll" } } } ] } ] }, { "description": "operation fails after two consecutive socket timeouts - aggregate on collection", "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 2 }, "data": { "failCommands": [ "aggregate" ], "blockConnection": true, "blockTimeMS": 125 } } } }, { "name": "aggregate", "object": "collection", "arguments": { "pipeline": [] }, "expectError": { "isClientError": true } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "aggregate", "databaseName": "test", "command": { "aggregate": "coll" } } }, { "commandStartedEvent": { "commandName": "aggregate", "databaseName": "test", "command": { "aggregate": "coll" } } } ] } ] }, { "description": "operation succeeds after one socket timeout - count on collection", "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "count" ], "blockConnection": true, "blockTimeMS": 125 } } } }, { "name": "count", "object": "collection", "arguments": { "filter": {} } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "count", "databaseName": "test", "command": { "count": "coll" } } }, { "commandStartedEvent": { "commandName": "count", "databaseName": "test", "command": { "count": "coll" } } } ] } ] }, { "description": "operation fails after two consecutive socket timeouts - count on collection", "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 2 }, "data": { "failCommands": [ "count" ], "blockConnection": true, "blockTimeMS": 125 } } } }, { "name": "count", "object": "collection", "arguments": { "filter": {} }, "expectError": { "isClientError": true } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "count", "databaseName": "test", "command": { "count": "coll" } } }, { "commandStartedEvent": { "commandName": "count", "databaseName": "test", "command": { "count": "coll" } } } ] } ] }, { "description": "operation succeeds after one socket timeout - countDocuments on collection", "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "aggregate" ], "blockConnection": true, "blockTimeMS": 125 } } } }, { "name": "countDocuments", "object": "collection", "arguments": { "filter": {} } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "aggregate", "databaseName": "test", "command": { "aggregate": "coll" } } }, { "commandStartedEvent": { "commandName": "aggregate", "databaseName": "test", "command": { "aggregate": "coll" } } } ] } ] }, { "description": "operation fails after two consecutive socket timeouts - countDocuments on collection", "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 2 }, "data": { "failCommands": [ "aggregate" ], "blockConnection": true, "blockTimeMS": 125 } } } }, { "name": "countDocuments", "object": "collection", "arguments": { "filter": {} }, "expectError": { "isClientError": true } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "aggregate", "databaseName": "test", "command": { "aggregate": "coll" } } }, { "commandStartedEvent": { "commandName": "aggregate", "databaseName": "test", "command": { "aggregate": "coll" } } } ] } ] }, { "description": "operation succeeds after one socket timeout - estimatedDocumentCount on collection", "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "count" ], "blockConnection": true, "blockTimeMS": 125 } } } }, { "name": "estimatedDocumentCount", "object": "collection" } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "count", "databaseName": "test", "command": { "count": "coll" } } }, { "commandStartedEvent": { "commandName": "count", "databaseName": "test", "command": { "count": "coll" } } } ] } ] }, { "description": "operation fails after two consecutive socket timeouts - estimatedDocumentCount on collection", "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 2 }, "data": { "failCommands": [ "count" ], "blockConnection": true, "blockTimeMS": 125 } } } }, { "name": "estimatedDocumentCount", "object": "collection", "expectError": { "isClientError": true } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "count", "databaseName": "test", "command": { "count": "coll" } } }, { "commandStartedEvent": { "commandName": "count", "databaseName": "test", "command": { "count": "coll" } } } ] } ] }, { "description": "operation succeeds after one socket timeout - distinct on collection", "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "distinct" ], "blockConnection": true, "blockTimeMS": 125 } } } }, { "name": "distinct", "object": "collection", "arguments": { "fieldName": "x", "filter": {} } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "distinct", "databaseName": "test", "command": { "distinct": "coll" } } }, { "commandStartedEvent": { "commandName": "distinct", "databaseName": "test", "command": { "distinct": "coll" } } } ] } ] }, { "description": "operation fails after two consecutive socket timeouts - distinct on collection", "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 2 }, "data": { "failCommands": [ "distinct" ], "blockConnection": true, "blockTimeMS": 125 } } } }, { "name": "distinct", "object": "collection", "arguments": { "fieldName": "x", "filter": {} }, "expectError": { "isClientError": true } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "distinct", "databaseName": "test", "command": { "distinct": "coll" } } }, { "commandStartedEvent": { "commandName": "distinct", "databaseName": "test", "command": { "distinct": "coll" } } } ] } ] }, { "description": "operation succeeds after one socket timeout - find on collection", "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "find" ], "blockConnection": true, "blockTimeMS": 125 } } } }, { "name": "find", "object": "collection", "arguments": { "filter": {} } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "find", "databaseName": "test", "command": { "find": "coll" } } }, { "commandStartedEvent": { "commandName": "find", "databaseName": "test", "command": { "find": "coll" } } } ] } ] }, { "description": "operation fails after two consecutive socket timeouts - find on collection", "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 2 }, "data": { "failCommands": [ "find" ], "blockConnection": true, "blockTimeMS": 125 } } } }, { "name": "find", "object": "collection", "arguments": { "filter": {} }, "expectError": { "isClientError": true } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "find", "databaseName": "test", "command": { "find": "coll" } } }, { "commandStartedEvent": { "commandName": "find", "databaseName": "test", "command": { "find": "coll" } } } ] } ] }, { "description": "operation succeeds after one socket timeout - findOne on collection", "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "find" ], "blockConnection": true, "blockTimeMS": 125 } } } }, { "name": "findOne", "object": "collection", "arguments": { "filter": {} } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "find", "databaseName": "test", "command": { "find": "coll" } } }, { "commandStartedEvent": { "commandName": "find", "databaseName": "test", "command": { "find": "coll" } } } ] } ] }, { "description": "operation fails after two consecutive socket timeouts - findOne on collection", "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 2 }, "data": { "failCommands": [ "find" ], "blockConnection": true, "blockTimeMS": 125 } } } }, { "name": "findOne", "object": "collection", "arguments": { "filter": {} }, "expectError": { "isClientError": true } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "find", "databaseName": "test", "command": { "find": "coll" } } }, { "commandStartedEvent": { "commandName": "find", "databaseName": "test", "command": { "find": "coll" } } } ] } ] }, { "description": "operation succeeds after one socket timeout - listIndexes on collection", "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "listIndexes" ], "blockConnection": true, "blockTimeMS": 125 } } } }, { "name": "listIndexes", "object": "collection" } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "listIndexes", "databaseName": "test", "command": { "listIndexes": "coll" } } }, { "commandStartedEvent": { "commandName": "listIndexes", "databaseName": "test", "command": { "listIndexes": "coll" } } } ] } ] }, { "description": "operation fails after two consecutive socket timeouts - listIndexes on collection", "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 2 }, "data": { "failCommands": [ "listIndexes" ], "blockConnection": true, "blockTimeMS": 125 } } } }, { "name": "listIndexes", "object": "collection", "expectError": { "isClientError": true } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "listIndexes", "databaseName": "test", "command": { "listIndexes": "coll" } } }, { "commandStartedEvent": { "commandName": "listIndexes", "databaseName": "test", "command": { "listIndexes": "coll" } } } ] } ] }, { "description": "operation succeeds after one socket timeout - createChangeStream on collection", "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "aggregate" ], "blockConnection": true, "blockTimeMS": 125 } } } }, { "name": "createChangeStream", "object": "collection", "arguments": { "pipeline": [] } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "aggregate", "databaseName": "test", "command": { "aggregate": "coll" } } }, { "commandStartedEvent": { "commandName": "aggregate", "databaseName": "test", "command": { "aggregate": "coll" } } } ] } ] }, { "description": "operation fails after two consecutive socket timeouts - createChangeStream on collection", "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 2 }, "data": { "failCommands": [ "aggregate" ], "blockConnection": true, "blockTimeMS": 125 } } } }, { "name": "createChangeStream", "object": "collection", "arguments": { "pipeline": [] }, "expectError": { "isClientError": true } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "aggregate", "databaseName": "test", "command": { "aggregate": "coll" } } }, { "commandStartedEvent": { "commandName": "aggregate", "databaseName": "test", "command": { "aggregate": "coll" } } } ] } ] } ] } mongodb-mongo-python-driver-509e9b7/test/csot/retryability-timeoutMS.json000066400000000000000000004354311462766011000267400ustar00rootroot00000000000000{ "description": "timeoutMS behaves correctly for retryable operations", "schemaVersion": "1.9", "runOnRequirements": [ { "minServerVersion": "4.0", "topologies": [ "replicaset" ] }, { "minServerVersion": "4.2", "topologies": [ "sharded" ] } ], "createEntities": [ { "client": { "id": "failPointClient", "useMultipleMongoses": false } }, { "client": { "id": "client", "uriOptions": { "timeoutMS": 100 }, "useMultipleMongoses": false, "observeEvents": [ "commandStartedEvent" ], "ignoreCommandMonitoringEvents": [ "killCursors" ] } }, { "database": { "id": "database", "client": "client", "databaseName": "test" } }, { "collection": { "id": "collection", "database": "database", "collectionName": "coll" } } ], "initialData": [ { "collectionName": "coll", "databaseName": "test", "documents": [] } ], "tests": [ { "description": "timeoutMS applies to whole operation, not individual attempts - insertOne on collection", "runOnRequirements": [ { "minServerVersion": "4.4" } ], "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 4 }, "data": { "failCommands": [ "insert" ], "blockConnection": true, "blockTimeMS": 60, "errorCode": 7, "errorLabels": [ "RetryableWriteError" ] } } } }, { "name": "insertOne", "object": "collection", "arguments": { "document": { "x": 1 } }, "expectError": { "isTimeoutError": true } } ] }, { "description": "operation is retried multiple times for non-zero timeoutMS - insertOne on collection", "runOnRequirements": [ { "minServerVersion": "4.3.1" } ], "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 2 }, "data": { "failCommands": [ "insert" ], "errorCode": 7, "closeConnection": false, "errorLabels": [ "RetryableWriteError" ] } } } }, { "name": "insertOne", "object": "collection", "arguments": { "timeoutMS": 1000, "document": { "x": 1 } } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "insert", "databaseName": "test", "command": { "insert": "coll", "maxTimeMS": { "$$type": [ "int", "long" ] } } } }, { "commandStartedEvent": { "commandName": "insert", "databaseName": "test", "command": { "insert": "coll", "maxTimeMS": { "$$type": [ "int", "long" ] } } } }, { "commandStartedEvent": { "commandName": "insert", "databaseName": "test", "command": { "insert": "coll", "maxTimeMS": { "$$type": [ "int", "long" ] } } } } ] } ] }, { "description": "operation is retried multiple times if timeoutMS is zero - insertOne on collection", "runOnRequirements": [ { "minServerVersion": "4.3.1" } ], "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 2 }, "data": { "failCommands": [ "insert" ], "errorCode": 7, "closeConnection": false, "errorLabels": [ "RetryableWriteError" ] } } } }, { "name": "insertOne", "object": "collection", "arguments": { "timeoutMS": 0, "document": { "x": 1 } } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "insert", "databaseName": "test", "command": { "insert": "coll", "maxTimeMS": { "$$exists": false } } } }, { "commandStartedEvent": { "commandName": "insert", "databaseName": "test", "command": { "insert": "coll", "maxTimeMS": { "$$exists": false } } } }, { "commandStartedEvent": { "commandName": "insert", "databaseName": "test", "command": { "insert": "coll", "maxTimeMS": { "$$exists": false } } } } ] } ] }, { "description": "timeoutMS applies to whole operation, not individual attempts - insertMany on collection", "runOnRequirements": [ { "minServerVersion": "4.4" } ], "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 4 }, "data": { "failCommands": [ "insert" ], "blockConnection": true, "blockTimeMS": 60, "errorCode": 7, "errorLabels": [ "RetryableWriteError" ] } } } }, { "name": "insertMany", "object": "collection", "arguments": { "documents": [ { "x": 1 } ] }, "expectError": { "isTimeoutError": true } } ] }, { "description": "operation is retried multiple times for non-zero timeoutMS - insertMany on collection", "runOnRequirements": [ { "minServerVersion": "4.3.1" } ], "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 2 }, "data": { "failCommands": [ "insert" ], "errorCode": 7, "closeConnection": false, "errorLabels": [ "RetryableWriteError" ] } } } }, { "name": "insertMany", "object": "collection", "arguments": { "timeoutMS": 1000, "documents": [ { "x": 1 } ] } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "insert", "databaseName": "test", "command": { "insert": "coll", "maxTimeMS": { "$$type": [ "int", "long" ] } } } }, { "commandStartedEvent": { "commandName": "insert", "databaseName": "test", "command": { "insert": "coll", "maxTimeMS": { "$$type": [ "int", "long" ] } } } }, { "commandStartedEvent": { "commandName": "insert", "databaseName": "test", "command": { "insert": "coll", "maxTimeMS": { "$$type": [ "int", "long" ] } } } } ] } ] }, { "description": "operation is retried multiple times if timeoutMS is zero - insertMany on collection", "runOnRequirements": [ { "minServerVersion": "4.3.1" } ], "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 2 }, "data": { "failCommands": [ "insert" ], "errorCode": 7, "closeConnection": false, "errorLabels": [ "RetryableWriteError" ] } } } }, { "name": "insertMany", "object": "collection", "arguments": { "timeoutMS": 0, "documents": [ { "x": 1 } ] } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "insert", "databaseName": "test", "command": { "insert": "coll", "maxTimeMS": { "$$exists": false } } } }, { "commandStartedEvent": { "commandName": "insert", "databaseName": "test", "command": { "insert": "coll", "maxTimeMS": { "$$exists": false } } } }, { "commandStartedEvent": { "commandName": "insert", "databaseName": "test", "command": { "insert": "coll", "maxTimeMS": { "$$exists": false } } } } ] } ] }, { "description": "timeoutMS applies to whole operation, not individual attempts - deleteOne on collection", "runOnRequirements": [ { "minServerVersion": "4.4" } ], "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 4 }, "data": { "failCommands": [ "delete" ], "blockConnection": true, "blockTimeMS": 60, "errorCode": 7, "errorLabels": [ "RetryableWriteError" ] } } } }, { "name": "deleteOne", "object": "collection", "arguments": { "filter": {} }, "expectError": { "isTimeoutError": true } } ] }, { "description": "operation is retried multiple times for non-zero timeoutMS - deleteOne on collection", "runOnRequirements": [ { "minServerVersion": "4.3.1" } ], "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 2 }, "data": { "failCommands": [ "delete" ], "errorCode": 7, "closeConnection": false, "errorLabels": [ "RetryableWriteError" ] } } } }, { "name": "deleteOne", "object": "collection", "arguments": { "timeoutMS": 1000, "filter": {} } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "delete", "databaseName": "test", "command": { "delete": "coll", "maxTimeMS": { "$$type": [ "int", "long" ] } } } }, { "commandStartedEvent": { "commandName": "delete", "databaseName": "test", "command": { "delete": "coll", "maxTimeMS": { "$$type": [ "int", "long" ] } } } }, { "commandStartedEvent": { "commandName": "delete", "databaseName": "test", "command": { "delete": "coll", "maxTimeMS": { "$$type": [ "int", "long" ] } } } } ] } ] }, { "description": "operation is retried multiple times if timeoutMS is zero - deleteOne on collection", "runOnRequirements": [ { "minServerVersion": "4.3.1" } ], "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 2 }, "data": { "failCommands": [ "delete" ], "errorCode": 7, "closeConnection": false, "errorLabels": [ "RetryableWriteError" ] } } } }, { "name": "deleteOne", "object": "collection", "arguments": { "timeoutMS": 0, "filter": {} } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "delete", "databaseName": "test", "command": { "delete": "coll", "maxTimeMS": { "$$exists": false } } } }, { "commandStartedEvent": { "commandName": "delete", "databaseName": "test", "command": { "delete": "coll", "maxTimeMS": { "$$exists": false } } } }, { "commandStartedEvent": { "commandName": "delete", "databaseName": "test", "command": { "delete": "coll", "maxTimeMS": { "$$exists": false } } } } ] } ] }, { "description": "timeoutMS applies to whole operation, not individual attempts - replaceOne on collection", "runOnRequirements": [ { "minServerVersion": "4.4" } ], "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 4 }, "data": { "failCommands": [ "update" ], "blockConnection": true, "blockTimeMS": 60, "errorCode": 7, "errorLabels": [ "RetryableWriteError" ] } } } }, { "name": "replaceOne", "object": "collection", "arguments": { "filter": {}, "replacement": { "x": 1 } }, "expectError": { "isTimeoutError": true } } ] }, { "description": "operation is retried multiple times for non-zero timeoutMS - replaceOne on collection", "runOnRequirements": [ { "minServerVersion": "4.3.1" } ], "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 2 }, "data": { "failCommands": [ "update" ], "errorCode": 7, "closeConnection": false, "errorLabels": [ "RetryableWriteError" ] } } } }, { "name": "replaceOne", "object": "collection", "arguments": { "timeoutMS": 1000, "filter": {}, "replacement": { "x": 1 } } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "update", "databaseName": "test", "command": { "update": "coll", "maxTimeMS": { "$$type": [ "int", "long" ] } } } }, { "commandStartedEvent": { "commandName": "update", "databaseName": "test", "command": { "update": "coll", "maxTimeMS": { "$$type": [ "int", "long" ] } } } }, { "commandStartedEvent": { "commandName": "update", "databaseName": "test", "command": { "update": "coll", "maxTimeMS": { "$$type": [ "int", "long" ] } } } } ] } ] }, { "description": "operation is retried multiple times if timeoutMS is zero - replaceOne on collection", "runOnRequirements": [ { "minServerVersion": "4.3.1" } ], "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 2 }, "data": { "failCommands": [ "update" ], "errorCode": 7, "closeConnection": false, "errorLabels": [ "RetryableWriteError" ] } } } }, { "name": "replaceOne", "object": "collection", "arguments": { "timeoutMS": 0, "filter": {}, "replacement": { "x": 1 } } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "update", "databaseName": "test", "command": { "update": "coll", "maxTimeMS": { "$$exists": false } } } }, { "commandStartedEvent": { "commandName": "update", "databaseName": "test", "command": { "update": "coll", "maxTimeMS": { "$$exists": false } } } }, { "commandStartedEvent": { "commandName": "update", "databaseName": "test", "command": { "update": "coll", "maxTimeMS": { "$$exists": false } } } } ] } ] }, { "description": "timeoutMS applies to whole operation, not individual attempts - updateOne on collection", "runOnRequirements": [ { "minServerVersion": "4.4" } ], "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 4 }, "data": { "failCommands": [ "update" ], "blockConnection": true, "blockTimeMS": 60, "errorCode": 7, "errorLabels": [ "RetryableWriteError" ] } } } }, { "name": "updateOne", "object": "collection", "arguments": { "filter": {}, "update": { "$set": { "x": 1 } } }, "expectError": { "isTimeoutError": true } } ] }, { "description": "operation is retried multiple times for non-zero timeoutMS - updateOne on collection", "runOnRequirements": [ { "minServerVersion": "4.3.1" } ], "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 2 }, "data": { "failCommands": [ "update" ], "errorCode": 7, "closeConnection": false, "errorLabels": [ "RetryableWriteError" ] } } } }, { "name": "updateOne", "object": "collection", "arguments": { "timeoutMS": 1000, "filter": {}, "update": { "$set": { "x": 1 } } } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "update", "databaseName": "test", "command": { "update": "coll", "maxTimeMS": { "$$type": [ "int", "long" ] } } } }, { "commandStartedEvent": { "commandName": "update", "databaseName": "test", "command": { "update": "coll", "maxTimeMS": { "$$type": [ "int", "long" ] } } } }, { "commandStartedEvent": { "commandName": "update", "databaseName": "test", "command": { "update": "coll", "maxTimeMS": { "$$type": [ "int", "long" ] } } } } ] } ] }, { "description": "operation is retried multiple times if timeoutMS is zero - updateOne on collection", "runOnRequirements": [ { "minServerVersion": "4.3.1" } ], "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 2 }, "data": { "failCommands": [ "update" ], "errorCode": 7, "closeConnection": false, "errorLabels": [ "RetryableWriteError" ] } } } }, { "name": "updateOne", "object": "collection", "arguments": { "timeoutMS": 0, "filter": {}, "update": { "$set": { "x": 1 } } } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "update", "databaseName": "test", "command": { "update": "coll", "maxTimeMS": { "$$exists": false } } } }, { "commandStartedEvent": { "commandName": "update", "databaseName": "test", "command": { "update": "coll", "maxTimeMS": { "$$exists": false } } } }, { "commandStartedEvent": { "commandName": "update", "databaseName": "test", "command": { "update": "coll", "maxTimeMS": { "$$exists": false } } } } ] } ] }, { "description": "timeoutMS applies to whole operation, not individual attempts - findOneAndDelete on collection", "runOnRequirements": [ { "minServerVersion": "4.4" } ], "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 4 }, "data": { "failCommands": [ "findAndModify" ], "blockConnection": true, "blockTimeMS": 60, "errorCode": 7, "errorLabels": [ "RetryableWriteError" ] } } } }, { "name": "findOneAndDelete", "object": "collection", "arguments": { "filter": {} }, "expectError": { "isTimeoutError": true } } ] }, { "description": "operation is retried multiple times for non-zero timeoutMS - findOneAndDelete on collection", "runOnRequirements": [ { "minServerVersion": "4.3.1" } ], "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 2 }, "data": { "failCommands": [ "findAndModify" ], "errorCode": 7, "closeConnection": false, "errorLabels": [ "RetryableWriteError" ] } } } }, { "name": "findOneAndDelete", "object": "collection", "arguments": { "timeoutMS": 1000, "filter": {} } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "findAndModify", "databaseName": "test", "command": { "findAndModify": "coll", "maxTimeMS": { "$$type": [ "int", "long" ] } } } }, { "commandStartedEvent": { "commandName": "findAndModify", "databaseName": "test", "command": { "findAndModify": "coll", "maxTimeMS": { "$$type": [ "int", "long" ] } } } }, { "commandStartedEvent": { "commandName": "findAndModify", "databaseName": "test", "command": { "findAndModify": "coll", "maxTimeMS": { "$$type": [ "int", "long" ] } } } } ] } ] }, { "description": "operation is retried multiple times if timeoutMS is zero - findOneAndDelete on collection", "runOnRequirements": [ { "minServerVersion": "4.3.1" } ], "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 2 }, "data": { "failCommands": [ "findAndModify" ], "errorCode": 7, "closeConnection": false, "errorLabels": [ "RetryableWriteError" ] } } } }, { "name": "findOneAndDelete", "object": "collection", "arguments": { "timeoutMS": 0, "filter": {} } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "findAndModify", "databaseName": "test", "command": { "findAndModify": "coll", "maxTimeMS": { "$$exists": false } } } }, { "commandStartedEvent": { "commandName": "findAndModify", "databaseName": "test", "command": { "findAndModify": "coll", "maxTimeMS": { "$$exists": false } } } }, { "commandStartedEvent": { "commandName": "findAndModify", "databaseName": "test", "command": { "findAndModify": "coll", "maxTimeMS": { "$$exists": false } } } } ] } ] }, { "description": "timeoutMS applies to whole operation, not individual attempts - findOneAndReplace on collection", "runOnRequirements": [ { "minServerVersion": "4.4" } ], "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 4 }, "data": { "failCommands": [ "findAndModify" ], "blockConnection": true, "blockTimeMS": 60, "errorCode": 7, "errorLabels": [ "RetryableWriteError" ] } } } }, { "name": "findOneAndReplace", "object": "collection", "arguments": { "filter": {}, "replacement": { "x": 1 } }, "expectError": { "isTimeoutError": true } } ] }, { "description": "operation is retried multiple times for non-zero timeoutMS - findOneAndReplace on collection", "runOnRequirements": [ { "minServerVersion": "4.3.1" } ], "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 2 }, "data": { "failCommands": [ "findAndModify" ], "errorCode": 7, "closeConnection": false, "errorLabels": [ "RetryableWriteError" ] } } } }, { "name": "findOneAndReplace", "object": "collection", "arguments": { "timeoutMS": 1000, "filter": {}, "replacement": { "x": 1 } } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "findAndModify", "databaseName": "test", "command": { "findAndModify": "coll", "maxTimeMS": { "$$type": [ "int", "long" ] } } } }, { "commandStartedEvent": { "commandName": "findAndModify", "databaseName": "test", "command": { "findAndModify": "coll", "maxTimeMS": { "$$type": [ "int", "long" ] } } } }, { "commandStartedEvent": { "commandName": "findAndModify", "databaseName": "test", "command": { "findAndModify": "coll", "maxTimeMS": { "$$type": [ "int", "long" ] } } } } ] } ] }, { "description": "operation is retried multiple times if timeoutMS is zero - findOneAndReplace on collection", "runOnRequirements": [ { "minServerVersion": "4.3.1" } ], "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 2 }, "data": { "failCommands": [ "findAndModify" ], "errorCode": 7, "closeConnection": false, "errorLabels": [ "RetryableWriteError" ] } } } }, { "name": "findOneAndReplace", "object": "collection", "arguments": { "timeoutMS": 0, "filter": {}, "replacement": { "x": 1 } } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "findAndModify", "databaseName": "test", "command": { "findAndModify": "coll", "maxTimeMS": { "$$exists": false } } } }, { "commandStartedEvent": { "commandName": "findAndModify", "databaseName": "test", "command": { "findAndModify": "coll", "maxTimeMS": { "$$exists": false } } } }, { "commandStartedEvent": { "commandName": "findAndModify", "databaseName": "test", "command": { "findAndModify": "coll", "maxTimeMS": { "$$exists": false } } } } ] } ] }, { "description": "timeoutMS applies to whole operation, not individual attempts - findOneAndUpdate on collection", "runOnRequirements": [ { "minServerVersion": "4.4" } ], "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 4 }, "data": { "failCommands": [ "findAndModify" ], "blockConnection": true, "blockTimeMS": 60, "errorCode": 7, "errorLabels": [ "RetryableWriteError" ] } } } }, { "name": "findOneAndUpdate", "object": "collection", "arguments": { "filter": {}, "update": { "$set": { "x": 1 } } }, "expectError": { "isTimeoutError": true } } ] }, { "description": "operation is retried multiple times for non-zero timeoutMS - findOneAndUpdate on collection", "runOnRequirements": [ { "minServerVersion": "4.3.1" } ], "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 2 }, "data": { "failCommands": [ "findAndModify" ], "errorCode": 7, "closeConnection": false, "errorLabels": [ "RetryableWriteError" ] } } } }, { "name": "findOneAndUpdate", "object": "collection", "arguments": { "timeoutMS": 1000, "filter": {}, "update": { "$set": { "x": 1 } } } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "findAndModify", "databaseName": "test", "command": { "findAndModify": "coll", "maxTimeMS": { "$$type": [ "int", "long" ] } } } }, { "commandStartedEvent": { "commandName": "findAndModify", "databaseName": "test", "command": { "findAndModify": "coll", "maxTimeMS": { "$$type": [ "int", "long" ] } } } }, { "commandStartedEvent": { "commandName": "findAndModify", "databaseName": "test", "command": { "findAndModify": "coll", "maxTimeMS": { "$$type": [ "int", "long" ] } } } } ] } ] }, { "description": "operation is retried multiple times if timeoutMS is zero - findOneAndUpdate on collection", "runOnRequirements": [ { "minServerVersion": "4.3.1" } ], "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 2 }, "data": { "failCommands": [ "findAndModify" ], "errorCode": 7, "closeConnection": false, "errorLabels": [ "RetryableWriteError" ] } } } }, { "name": "findOneAndUpdate", "object": "collection", "arguments": { "timeoutMS": 0, "filter": {}, "update": { "$set": { "x": 1 } } } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "findAndModify", "databaseName": "test", "command": { "findAndModify": "coll", "maxTimeMS": { "$$exists": false } } } }, { "commandStartedEvent": { "commandName": "findAndModify", "databaseName": "test", "command": { "findAndModify": "coll", "maxTimeMS": { "$$exists": false } } } }, { "commandStartedEvent": { "commandName": "findAndModify", "databaseName": "test", "command": { "findAndModify": "coll", "maxTimeMS": { "$$exists": false } } } } ] } ] }, { "description": "timeoutMS applies to whole operation, not individual attempts - bulkWrite on collection", "runOnRequirements": [ { "minServerVersion": "4.4" } ], "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 4 }, "data": { "failCommands": [ "insert" ], "blockConnection": true, "blockTimeMS": 60, "errorCode": 7, "errorLabels": [ "RetryableWriteError" ] } } } }, { "name": "bulkWrite", "object": "collection", "arguments": { "requests": [ { "insertOne": { "document": { "_id": 1 } } } ] }, "expectError": { "isTimeoutError": true } } ] }, { "description": "operation is retried multiple times for non-zero timeoutMS - bulkWrite on collection", "runOnRequirements": [ { "minServerVersion": "4.3.1" } ], "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 2 }, "data": { "failCommands": [ "insert" ], "errorCode": 7, "closeConnection": false, "errorLabels": [ "RetryableWriteError" ] } } } }, { "name": "bulkWrite", "object": "collection", "arguments": { "timeoutMS": 1000, "requests": [ { "insertOne": { "document": { "_id": 1 } } } ] } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "insert", "databaseName": "test", "command": { "insert": "coll", "maxTimeMS": { "$$type": [ "int", "long" ] } } } }, { "commandStartedEvent": { "commandName": "insert", "databaseName": "test", "command": { "insert": "coll", "maxTimeMS": { "$$type": [ "int", "long" ] } } } }, { "commandStartedEvent": { "commandName": "insert", "databaseName": "test", "command": { "insert": "coll", "maxTimeMS": { "$$type": [ "int", "long" ] } } } } ] } ] }, { "description": "operation is retried multiple times if timeoutMS is zero - bulkWrite on collection", "runOnRequirements": [ { "minServerVersion": "4.3.1" } ], "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 2 }, "data": { "failCommands": [ "insert" ], "errorCode": 7, "closeConnection": false, "errorLabels": [ "RetryableWriteError" ] } } } }, { "name": "bulkWrite", "object": "collection", "arguments": { "timeoutMS": 0, "requests": [ { "insertOne": { "document": { "_id": 1 } } } ] } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "insert", "databaseName": "test", "command": { "insert": "coll", "maxTimeMS": { "$$exists": false } } } }, { "commandStartedEvent": { "commandName": "insert", "databaseName": "test", "command": { "insert": "coll", "maxTimeMS": { "$$exists": false } } } }, { "commandStartedEvent": { "commandName": "insert", "databaseName": "test", "command": { "insert": "coll", "maxTimeMS": { "$$exists": false } } } } ] } ] }, { "description": "timeoutMS applies to whole operation, not individual attempts - listDatabases on client", "runOnRequirements": [ { "minServerVersion": "4.4" } ], "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 4 }, "data": { "failCommands": [ "listDatabases" ], "blockConnection": true, "blockTimeMS": 60, "errorCode": 7, "errorLabels": [ "RetryableWriteError" ] } } } }, { "name": "listDatabases", "object": "client", "arguments": { "filter": {} }, "expectError": { "isTimeoutError": true } } ] }, { "description": "operation is retried multiple times for non-zero timeoutMS - listDatabases on client", "runOnRequirements": [ { "minServerVersion": "4.3.1" } ], "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 2 }, "data": { "failCommands": [ "listDatabases" ], "errorCode": 7, "closeConnection": false, "errorLabels": [ "RetryableWriteError" ] } } } }, { "name": "listDatabases", "object": "client", "arguments": { "timeoutMS": 1000, "filter": {} } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "listDatabases", "databaseName": "admin", "command": { "listDatabases": 1, "maxTimeMS": { "$$type": [ "int", "long" ] } } } }, { "commandStartedEvent": { "commandName": "listDatabases", "databaseName": "admin", "command": { "listDatabases": 1, "maxTimeMS": { "$$type": [ "int", "long" ] } } } }, { "commandStartedEvent": { "commandName": "listDatabases", "databaseName": "admin", "command": { "listDatabases": 1, "maxTimeMS": { "$$type": [ "int", "long" ] } } } } ] } ] }, { "description": "operation is retried multiple times if timeoutMS is zero - listDatabases on client", "runOnRequirements": [ { "minServerVersion": "4.3.1" } ], "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 2 }, "data": { "failCommands": [ "listDatabases" ], "errorCode": 7, "closeConnection": false, "errorLabels": [ "RetryableWriteError" ] } } } }, { "name": "listDatabases", "object": "client", "arguments": { "timeoutMS": 0, "filter": {} } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "listDatabases", "databaseName": "admin", "command": { "listDatabases": 1, "maxTimeMS": { "$$exists": false } } } }, { "commandStartedEvent": { "commandName": "listDatabases", "databaseName": "admin", "command": { "listDatabases": 1, "maxTimeMS": { "$$exists": false } } } }, { "commandStartedEvent": { "commandName": "listDatabases", "databaseName": "admin", "command": { "listDatabases": 1, "maxTimeMS": { "$$exists": false } } } } ] } ] }, { "description": "timeoutMS applies to whole operation, not individual attempts - listDatabaseNames on client", "runOnRequirements": [ { "minServerVersion": "4.4" } ], "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 4 }, "data": { "failCommands": [ "listDatabases" ], "blockConnection": true, "blockTimeMS": 60, "errorCode": 7, "errorLabels": [ "RetryableWriteError" ] } } } }, { "name": "listDatabaseNames", "object": "client", "expectError": { "isTimeoutError": true } } ] }, { "description": "operation is retried multiple times for non-zero timeoutMS - listDatabaseNames on client", "runOnRequirements": [ { "minServerVersion": "4.3.1" } ], "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 2 }, "data": { "failCommands": [ "listDatabases" ], "errorCode": 7, "closeConnection": false, "errorLabels": [ "RetryableWriteError" ] } } } }, { "name": "listDatabaseNames", "object": "client", "arguments": { "timeoutMS": 1000 } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "listDatabases", "databaseName": "admin", "command": { "listDatabases": 1, "maxTimeMS": { "$$type": [ "int", "long" ] } } } }, { "commandStartedEvent": { "commandName": "listDatabases", "databaseName": "admin", "command": { "listDatabases": 1, "maxTimeMS": { "$$type": [ "int", "long" ] } } } }, { "commandStartedEvent": { "commandName": "listDatabases", "databaseName": "admin", "command": { "listDatabases": 1, "maxTimeMS": { "$$type": [ "int", "long" ] } } } } ] } ] }, { "description": "operation is retried multiple times if timeoutMS is zero - listDatabaseNames on client", "runOnRequirements": [ { "minServerVersion": "4.3.1" } ], "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 2 }, "data": { "failCommands": [ "listDatabases" ], "errorCode": 7, "closeConnection": false, "errorLabels": [ "RetryableWriteError" ] } } } }, { "name": "listDatabaseNames", "object": "client", "arguments": { "timeoutMS": 0 } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "listDatabases", "databaseName": "admin", "command": { "listDatabases": 1, "maxTimeMS": { "$$exists": false } } } }, { "commandStartedEvent": { "commandName": "listDatabases", "databaseName": "admin", "command": { "listDatabases": 1, "maxTimeMS": { "$$exists": false } } } }, { "commandStartedEvent": { "commandName": "listDatabases", "databaseName": "admin", "command": { "listDatabases": 1, "maxTimeMS": { "$$exists": false } } } } ] } ] }, { "description": "timeoutMS applies to whole operation, not individual attempts - createChangeStream on client", "runOnRequirements": [ { "minServerVersion": "4.4" } ], "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 4 }, "data": { "failCommands": [ "aggregate" ], "blockConnection": true, "blockTimeMS": 60, "errorCode": 7, "errorLabels": [ "RetryableWriteError" ] } } } }, { "name": "createChangeStream", "object": "client", "arguments": { "pipeline": [] }, "expectError": { "isTimeoutError": true } } ] }, { "description": "operation is retried multiple times for non-zero timeoutMS - createChangeStream on client", "runOnRequirements": [ { "minServerVersion": "4.3.1" } ], "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 2 }, "data": { "failCommands": [ "aggregate" ], "errorCode": 7, "closeConnection": false, "errorLabels": [ "RetryableWriteError" ] } } } }, { "name": "createChangeStream", "object": "client", "arguments": { "timeoutMS": 1000, "pipeline": [] } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "aggregate", "databaseName": "admin", "command": { "aggregate": 1, "maxTimeMS": { "$$type": [ "int", "long" ] } } } }, { "commandStartedEvent": { "commandName": "aggregate", "databaseName": "admin", "command": { "aggregate": 1, "maxTimeMS": { "$$type": [ "int", "long" ] } } } }, { "commandStartedEvent": { "commandName": "aggregate", "databaseName": "admin", "command": { "aggregate": 1, "maxTimeMS": { "$$type": [ "int", "long" ] } } } } ] } ] }, { "description": "operation is retried multiple times if timeoutMS is zero - createChangeStream on client", "runOnRequirements": [ { "minServerVersion": "4.3.1" } ], "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 2 }, "data": { "failCommands": [ "aggregate" ], "errorCode": 7, "closeConnection": false, "errorLabels": [ "RetryableWriteError" ] } } } }, { "name": "createChangeStream", "object": "client", "arguments": { "timeoutMS": 0, "pipeline": [] } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "aggregate", "databaseName": "admin", "command": { "aggregate": 1, "maxTimeMS": { "$$exists": false } } } }, { "commandStartedEvent": { "commandName": "aggregate", "databaseName": "admin", "command": { "aggregate": 1, "maxTimeMS": { "$$exists": false } } } }, { "commandStartedEvent": { "commandName": "aggregate", "databaseName": "admin", "command": { "aggregate": 1, "maxTimeMS": { "$$exists": false } } } } ] } ] }, { "description": "timeoutMS applies to whole operation, not individual attempts - aggregate on database", "runOnRequirements": [ { "minServerVersion": "4.4" } ], "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 4 }, "data": { "failCommands": [ "aggregate" ], "blockConnection": true, "blockTimeMS": 60, "errorCode": 7, "errorLabels": [ "RetryableWriteError" ] } } } }, { "name": "aggregate", "object": "database", "arguments": { "pipeline": [ { "$listLocalSessions": {} }, { "$limit": 1 } ] }, "expectError": { "isTimeoutError": true } } ] }, { "description": "operation is retried multiple times for non-zero timeoutMS - aggregate on database", "runOnRequirements": [ { "minServerVersion": "4.3.1" } ], "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 2 }, "data": { "failCommands": [ "aggregate" ], "errorCode": 7, "closeConnection": false, "errorLabels": [ "RetryableWriteError" ] } } } }, { "name": "aggregate", "object": "database", "arguments": { "timeoutMS": 1000, "pipeline": [ { "$listLocalSessions": {} }, { "$limit": 1 } ] } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "aggregate", "databaseName": "test", "command": { "aggregate": 1, "maxTimeMS": { "$$type": [ "int", "long" ] } } } }, { "commandStartedEvent": { "commandName": "aggregate", "databaseName": "test", "command": { "aggregate": 1, "maxTimeMS": { "$$type": [ "int", "long" ] } } } }, { "commandStartedEvent": { "commandName": "aggregate", "databaseName": "test", "command": { "aggregate": 1, "maxTimeMS": { "$$type": [ "int", "long" ] } } } } ] } ] }, { "description": "operation is retried multiple times if timeoutMS is zero - aggregate on database", "runOnRequirements": [ { "minServerVersion": "4.3.1" } ], "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 2 }, "data": { "failCommands": [ "aggregate" ], "errorCode": 7, "closeConnection": false, "errorLabels": [ "RetryableWriteError" ] } } } }, { "name": "aggregate", "object": "database", "arguments": { "timeoutMS": 0, "pipeline": [ { "$listLocalSessions": {} }, { "$limit": 1 } ] } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "aggregate", "databaseName": "test", "command": { "aggregate": 1, "maxTimeMS": { "$$exists": false } } } }, { "commandStartedEvent": { "commandName": "aggregate", "databaseName": "test", "command": { "aggregate": 1, "maxTimeMS": { "$$exists": false } } } }, { "commandStartedEvent": { "commandName": "aggregate", "databaseName": "test", "command": { "aggregate": 1, "maxTimeMS": { "$$exists": false } } } } ] } ] }, { "description": "timeoutMS applies to whole operation, not individual attempts - listCollections on database", "runOnRequirements": [ { "minServerVersion": "4.4" } ], "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 4 }, "data": { "failCommands": [ "listCollections" ], "blockConnection": true, "blockTimeMS": 60, "errorCode": 7, "errorLabels": [ "RetryableWriteError" ] } } } }, { "name": "listCollections", "object": "database", "arguments": { "filter": {} }, "expectError": { "isTimeoutError": true } } ] }, { "description": "operation is retried multiple times for non-zero timeoutMS - listCollections on database", "runOnRequirements": [ { "minServerVersion": "4.3.1" } ], "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 2 }, "data": { "failCommands": [ "listCollections" ], "errorCode": 7, "closeConnection": false, "errorLabels": [ "RetryableWriteError" ] } } } }, { "name": "listCollections", "object": "database", "arguments": { "timeoutMS": 1000, "filter": {} } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "listCollections", "databaseName": "test", "command": { "listCollections": 1, "maxTimeMS": { "$$type": [ "int", "long" ] } } } }, { "commandStartedEvent": { "commandName": "listCollections", "databaseName": "test", "command": { "listCollections": 1, "maxTimeMS": { "$$type": [ "int", "long" ] } } } }, { "commandStartedEvent": { "commandName": "listCollections", "databaseName": "test", "command": { "listCollections": 1, "maxTimeMS": { "$$type": [ "int", "long" ] } } } } ] } ] }, { "description": "operation is retried multiple times if timeoutMS is zero - listCollections on database", "runOnRequirements": [ { "minServerVersion": "4.3.1" } ], "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 2 }, "data": { "failCommands": [ "listCollections" ], "errorCode": 7, "closeConnection": false, "errorLabels": [ "RetryableWriteError" ] } } } }, { "name": "listCollections", "object": "database", "arguments": { "timeoutMS": 0, "filter": {} } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "listCollections", "databaseName": "test", "command": { "listCollections": 1, "maxTimeMS": { "$$exists": false } } } }, { "commandStartedEvent": { "commandName": "listCollections", "databaseName": "test", "command": { "listCollections": 1, "maxTimeMS": { "$$exists": false } } } }, { "commandStartedEvent": { "commandName": "listCollections", "databaseName": "test", "command": { "listCollections": 1, "maxTimeMS": { "$$exists": false } } } } ] } ] }, { "description": "timeoutMS applies to whole operation, not individual attempts - listCollectionNames on database", "runOnRequirements": [ { "minServerVersion": "4.4" } ], "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 4 }, "data": { "failCommands": [ "listCollections" ], "blockConnection": true, "blockTimeMS": 60, "errorCode": 7, "errorLabels": [ "RetryableWriteError" ] } } } }, { "name": "listCollectionNames", "object": "database", "arguments": { "filter": {} }, "expectError": { "isTimeoutError": true } } ] }, { "description": "operation is retried multiple times for non-zero timeoutMS - listCollectionNames on database", "runOnRequirements": [ { "minServerVersion": "4.3.1" } ], "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 2 }, "data": { "failCommands": [ "listCollections" ], "errorCode": 7, "closeConnection": false, "errorLabels": [ "RetryableWriteError" ] } } } }, { "name": "listCollectionNames", "object": "database", "arguments": { "timeoutMS": 1000, "filter": {} } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "listCollections", "databaseName": "test", "command": { "listCollections": 1, "maxTimeMS": { "$$type": [ "int", "long" ] } } } }, { "commandStartedEvent": { "commandName": "listCollections", "databaseName": "test", "command": { "listCollections": 1, "maxTimeMS": { "$$type": [ "int", "long" ] } } } }, { "commandStartedEvent": { "commandName": "listCollections", "databaseName": "test", "command": { "listCollections": 1, "maxTimeMS": { "$$type": [ "int", "long" ] } } } } ] } ] }, { "description": "operation is retried multiple times if timeoutMS is zero - listCollectionNames on database", "runOnRequirements": [ { "minServerVersion": "4.3.1" } ], "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 2 }, "data": { "failCommands": [ "listCollections" ], "errorCode": 7, "closeConnection": false, "errorLabels": [ "RetryableWriteError" ] } } } }, { "name": "listCollectionNames", "object": "database", "arguments": { "timeoutMS": 0, "filter": {} } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "listCollections", "databaseName": "test", "command": { "listCollections": 1, "maxTimeMS": { "$$exists": false } } } }, { "commandStartedEvent": { "commandName": "listCollections", "databaseName": "test", "command": { "listCollections": 1, "maxTimeMS": { "$$exists": false } } } }, { "commandStartedEvent": { "commandName": "listCollections", "databaseName": "test", "command": { "listCollections": 1, "maxTimeMS": { "$$exists": false } } } } ] } ] }, { "description": "timeoutMS applies to whole operation, not individual attempts - createChangeStream on database", "runOnRequirements": [ { "minServerVersion": "4.4" } ], "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 4 }, "data": { "failCommands": [ "aggregate" ], "blockConnection": true, "blockTimeMS": 60, "errorCode": 7, "errorLabels": [ "RetryableWriteError" ] } } } }, { "name": "createChangeStream", "object": "database", "arguments": { "pipeline": [] }, "expectError": { "isTimeoutError": true } } ] }, { "description": "operation is retried multiple times for non-zero timeoutMS - createChangeStream on database", "runOnRequirements": [ { "minServerVersion": "4.3.1" } ], "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 2 }, "data": { "failCommands": [ "aggregate" ], "errorCode": 7, "closeConnection": false, "errorLabels": [ "RetryableWriteError" ] } } } }, { "name": "createChangeStream", "object": "database", "arguments": { "timeoutMS": 1000, "pipeline": [] } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "aggregate", "databaseName": "test", "command": { "aggregate": 1, "maxTimeMS": { "$$type": [ "int", "long" ] } } } }, { "commandStartedEvent": { "commandName": "aggregate", "databaseName": "test", "command": { "aggregate": 1, "maxTimeMS": { "$$type": [ "int", "long" ] } } } }, { "commandStartedEvent": { "commandName": "aggregate", "databaseName": "test", "command": { "aggregate": 1, "maxTimeMS": { "$$type": [ "int", "long" ] } } } } ] } ] }, { "description": "operation is retried multiple times if timeoutMS is zero - createChangeStream on database", "runOnRequirements": [ { "minServerVersion": "4.3.1" } ], "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 2 }, "data": { "failCommands": [ "aggregate" ], "errorCode": 7, "closeConnection": false, "errorLabels": [ "RetryableWriteError" ] } } } }, { "name": "createChangeStream", "object": "database", "arguments": { "timeoutMS": 0, "pipeline": [] } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "aggregate", "databaseName": "test", "command": { "aggregate": 1, "maxTimeMS": { "$$exists": false } } } }, { "commandStartedEvent": { "commandName": "aggregate", "databaseName": "test", "command": { "aggregate": 1, "maxTimeMS": { "$$exists": false } } } }, { "commandStartedEvent": { "commandName": "aggregate", "databaseName": "test", "command": { "aggregate": 1, "maxTimeMS": { "$$exists": false } } } } ] } ] }, { "description": "timeoutMS applies to whole operation, not individual attempts - aggregate on collection", "runOnRequirements": [ { "minServerVersion": "4.4" } ], "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 4 }, "data": { "failCommands": [ "aggregate" ], "blockConnection": true, "blockTimeMS": 60, "errorCode": 7, "errorLabels": [ "RetryableWriteError" ] } } } }, { "name": "aggregate", "object": "collection", "arguments": { "pipeline": [] }, "expectError": { "isTimeoutError": true } } ] }, { "description": "operation is retried multiple times for non-zero timeoutMS - aggregate on collection", "runOnRequirements": [ { "minServerVersion": "4.3.1" } ], "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 2 }, "data": { "failCommands": [ "aggregate" ], "errorCode": 7, "closeConnection": false, "errorLabels": [ "RetryableWriteError" ] } } } }, { "name": "aggregate", "object": "collection", "arguments": { "timeoutMS": 1000, "pipeline": [] } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "aggregate", "databaseName": "test", "command": { "aggregate": "coll", "maxTimeMS": { "$$type": [ "int", "long" ] } } } }, { "commandStartedEvent": { "commandName": "aggregate", "databaseName": "test", "command": { "aggregate": "coll", "maxTimeMS": { "$$type": [ "int", "long" ] } } } }, { "commandStartedEvent": { "commandName": "aggregate", "databaseName": "test", "command": { "aggregate": "coll", "maxTimeMS": { "$$type": [ "int", "long" ] } } } } ] } ] }, { "description": "operation is retried multiple times if timeoutMS is zero - aggregate on collection", "runOnRequirements": [ { "minServerVersion": "4.3.1" } ], "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 2 }, "data": { "failCommands": [ "aggregate" ], "errorCode": 7, "closeConnection": false, "errorLabels": [ "RetryableWriteError" ] } } } }, { "name": "aggregate", "object": "collection", "arguments": { "timeoutMS": 0, "pipeline": [] } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "aggregate", "databaseName": "test", "command": { "aggregate": "coll", "maxTimeMS": { "$$exists": false } } } }, { "commandStartedEvent": { "commandName": "aggregate", "databaseName": "test", "command": { "aggregate": "coll", "maxTimeMS": { "$$exists": false } } } }, { "commandStartedEvent": { "commandName": "aggregate", "databaseName": "test", "command": { "aggregate": "coll", "maxTimeMS": { "$$exists": false } } } } ] } ] }, { "description": "timeoutMS applies to whole operation, not individual attempts - count on collection", "runOnRequirements": [ { "minServerVersion": "4.4" } ], "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 4 }, "data": { "failCommands": [ "count" ], "blockConnection": true, "blockTimeMS": 60, "errorCode": 7, "errorLabels": [ "RetryableWriteError" ] } } } }, { "name": "count", "object": "collection", "arguments": { "filter": {} }, "expectError": { "isTimeoutError": true } } ] }, { "description": "operation is retried multiple times for non-zero timeoutMS - count on collection", "runOnRequirements": [ { "minServerVersion": "4.3.1" } ], "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 2 }, "data": { "failCommands": [ "count" ], "errorCode": 7, "closeConnection": false, "errorLabels": [ "RetryableWriteError" ] } } } }, { "name": "count", "object": "collection", "arguments": { "timeoutMS": 1000, "filter": {} } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "count", "databaseName": "test", "command": { "count": "coll", "maxTimeMS": { "$$type": [ "int", "long" ] } } } }, { "commandStartedEvent": { "commandName": "count", "databaseName": "test", "command": { "count": "coll", "maxTimeMS": { "$$type": [ "int", "long" ] } } } }, { "commandStartedEvent": { "commandName": "count", "databaseName": "test", "command": { "count": "coll", "maxTimeMS": { "$$type": [ "int", "long" ] } } } } ] } ] }, { "description": "operation is retried multiple times if timeoutMS is zero - count on collection", "runOnRequirements": [ { "minServerVersion": "4.3.1" } ], "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 2 }, "data": { "failCommands": [ "count" ], "errorCode": 7, "closeConnection": false, "errorLabels": [ "RetryableWriteError" ] } } } }, { "name": "count", "object": "collection", "arguments": { "timeoutMS": 0, "filter": {} } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "count", "databaseName": "test", "command": { "count": "coll", "maxTimeMS": { "$$exists": false } } } }, { "commandStartedEvent": { "commandName": "count", "databaseName": "test", "command": { "count": "coll", "maxTimeMS": { "$$exists": false } } } }, { "commandStartedEvent": { "commandName": "count", "databaseName": "test", "command": { "count": "coll", "maxTimeMS": { "$$exists": false } } } } ] } ] }, { "description": "timeoutMS applies to whole operation, not individual attempts - countDocuments on collection", "runOnRequirements": [ { "minServerVersion": "4.4" } ], "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 4 }, "data": { "failCommands": [ "aggregate" ], "blockConnection": true, "blockTimeMS": 60, "errorCode": 7, "errorLabels": [ "RetryableWriteError" ] } } } }, { "name": "countDocuments", "object": "collection", "arguments": { "filter": {} }, "expectError": { "isTimeoutError": true } } ] }, { "description": "operation is retried multiple times for non-zero timeoutMS - countDocuments on collection", "runOnRequirements": [ { "minServerVersion": "4.3.1" } ], "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 2 }, "data": { "failCommands": [ "aggregate" ], "errorCode": 7, "closeConnection": false, "errorLabels": [ "RetryableWriteError" ] } } } }, { "name": "countDocuments", "object": "collection", "arguments": { "timeoutMS": 1000, "filter": {} } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "aggregate", "databaseName": "test", "command": { "aggregate": "coll", "maxTimeMS": { "$$type": [ "int", "long" ] } } } }, { "commandStartedEvent": { "commandName": "aggregate", "databaseName": "test", "command": { "aggregate": "coll", "maxTimeMS": { "$$type": [ "int", "long" ] } } } }, { "commandStartedEvent": { "commandName": "aggregate", "databaseName": "test", "command": { "aggregate": "coll", "maxTimeMS": { "$$type": [ "int", "long" ] } } } } ] } ] }, { "description": "operation is retried multiple times if timeoutMS is zero - countDocuments on collection", "runOnRequirements": [ { "minServerVersion": "4.3.1" } ], "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 2 }, "data": { "failCommands": [ "aggregate" ], "errorCode": 7, "closeConnection": false, "errorLabels": [ "RetryableWriteError" ] } } } }, { "name": "countDocuments", "object": "collection", "arguments": { "timeoutMS": 0, "filter": {} } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "aggregate", "databaseName": "test", "command": { "aggregate": "coll", "maxTimeMS": { "$$exists": false } } } }, { "commandStartedEvent": { "commandName": "aggregate", "databaseName": "test", "command": { "aggregate": "coll", "maxTimeMS": { "$$exists": false } } } }, { "commandStartedEvent": { "commandName": "aggregate", "databaseName": "test", "command": { "aggregate": "coll", "maxTimeMS": { "$$exists": false } } } } ] } ] }, { "description": "timeoutMS applies to whole operation, not individual attempts - estimatedDocumentCount on collection", "runOnRequirements": [ { "minServerVersion": "4.4" } ], "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 4 }, "data": { "failCommands": [ "count" ], "blockConnection": true, "blockTimeMS": 60, "errorCode": 7, "errorLabels": [ "RetryableWriteError" ] } } } }, { "name": "estimatedDocumentCount", "object": "collection", "expectError": { "isTimeoutError": true } } ] }, { "description": "operation is retried multiple times for non-zero timeoutMS - estimatedDocumentCount on collection", "runOnRequirements": [ { "minServerVersion": "4.3.1" } ], "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 2 }, "data": { "failCommands": [ "count" ], "errorCode": 7, "closeConnection": false, "errorLabels": [ "RetryableWriteError" ] } } } }, { "name": "estimatedDocumentCount", "object": "collection", "arguments": { "timeoutMS": 1000 } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "count", "databaseName": "test", "command": { "count": "coll", "maxTimeMS": { "$$type": [ "int", "long" ] } } } }, { "commandStartedEvent": { "commandName": "count", "databaseName": "test", "command": { "count": "coll", "maxTimeMS": { "$$type": [ "int", "long" ] } } } }, { "commandStartedEvent": { "commandName": "count", "databaseName": "test", "command": { "count": "coll", "maxTimeMS": { "$$type": [ "int", "long" ] } } } } ] } ] }, { "description": "operation is retried multiple times if timeoutMS is zero - estimatedDocumentCount on collection", "runOnRequirements": [ { "minServerVersion": "4.3.1" } ], "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 2 }, "data": { "failCommands": [ "count" ], "errorCode": 7, "closeConnection": false, "errorLabels": [ "RetryableWriteError" ] } } } }, { "name": "estimatedDocumentCount", "object": "collection", "arguments": { "timeoutMS": 0 } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "count", "databaseName": "test", "command": { "count": "coll", "maxTimeMS": { "$$exists": false } } } }, { "commandStartedEvent": { "commandName": "count", "databaseName": "test", "command": { "count": "coll", "maxTimeMS": { "$$exists": false } } } }, { "commandStartedEvent": { "commandName": "count", "databaseName": "test", "command": { "count": "coll", "maxTimeMS": { "$$exists": false } } } } ] } ] }, { "description": "timeoutMS applies to whole operation, not individual attempts - distinct on collection", "runOnRequirements": [ { "minServerVersion": "4.4" } ], "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 4 }, "data": { "failCommands": [ "distinct" ], "blockConnection": true, "blockTimeMS": 60, "errorCode": 7, "errorLabels": [ "RetryableWriteError" ] } } } }, { "name": "distinct", "object": "collection", "arguments": { "fieldName": "x", "filter": {} }, "expectError": { "isTimeoutError": true } } ] }, { "description": "operation is retried multiple times for non-zero timeoutMS - distinct on collection", "runOnRequirements": [ { "minServerVersion": "4.3.1" } ], "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 2 }, "data": { "failCommands": [ "distinct" ], "errorCode": 7, "closeConnection": false, "errorLabels": [ "RetryableWriteError" ] } } } }, { "name": "distinct", "object": "collection", "arguments": { "timeoutMS": 1000, "fieldName": "x", "filter": {} } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "distinct", "databaseName": "test", "command": { "distinct": "coll", "maxTimeMS": { "$$type": [ "int", "long" ] } } } }, { "commandStartedEvent": { "commandName": "distinct", "databaseName": "test", "command": { "distinct": "coll", "maxTimeMS": { "$$type": [ "int", "long" ] } } } }, { "commandStartedEvent": { "commandName": "distinct", "databaseName": "test", "command": { "distinct": "coll", "maxTimeMS": { "$$type": [ "int", "long" ] } } } } ] } ] }, { "description": "operation is retried multiple times if timeoutMS is zero - distinct on collection", "runOnRequirements": [ { "minServerVersion": "4.3.1" } ], "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 2 }, "data": { "failCommands": [ "distinct" ], "errorCode": 7, "closeConnection": false, "errorLabels": [ "RetryableWriteError" ] } } } }, { "name": "distinct", "object": "collection", "arguments": { "timeoutMS": 0, "fieldName": "x", "filter": {} } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "distinct", "databaseName": "test", "command": { "distinct": "coll", "maxTimeMS": { "$$exists": false } } } }, { "commandStartedEvent": { "commandName": "distinct", "databaseName": "test", "command": { "distinct": "coll", "maxTimeMS": { "$$exists": false } } } }, { "commandStartedEvent": { "commandName": "distinct", "databaseName": "test", "command": { "distinct": "coll", "maxTimeMS": { "$$exists": false } } } } ] } ] }, { "description": "timeoutMS applies to whole operation, not individual attempts - find on collection", "runOnRequirements": [ { "minServerVersion": "4.4" } ], "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 4 }, "data": { "failCommands": [ "find" ], "blockConnection": true, "blockTimeMS": 60, "errorCode": 7, "errorLabels": [ "RetryableWriteError" ] } } } }, { "name": "find", "object": "collection", "arguments": { "filter": {} }, "expectError": { "isTimeoutError": true } } ] }, { "description": "operation is retried multiple times for non-zero timeoutMS - find on collection", "runOnRequirements": [ { "minServerVersion": "4.3.1" } ], "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 2 }, "data": { "failCommands": [ "find" ], "errorCode": 7, "closeConnection": false, "errorLabels": [ "RetryableWriteError" ] } } } }, { "name": "find", "object": "collection", "arguments": { "timeoutMS": 1000, "filter": {} } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "find", "databaseName": "test", "command": { "find": "coll", "maxTimeMS": { "$$type": [ "int", "long" ] } } } }, { "commandStartedEvent": { "commandName": "find", "databaseName": "test", "command": { "find": "coll", "maxTimeMS": { "$$type": [ "int", "long" ] } } } }, { "commandStartedEvent": { "commandName": "find", "databaseName": "test", "command": { "find": "coll", "maxTimeMS": { "$$type": [ "int", "long" ] } } } } ] } ] }, { "description": "operation is retried multiple times if timeoutMS is zero - find on collection", "runOnRequirements": [ { "minServerVersion": "4.3.1" } ], "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 2 }, "data": { "failCommands": [ "find" ], "errorCode": 7, "closeConnection": false, "errorLabels": [ "RetryableWriteError" ] } } } }, { "name": "find", "object": "collection", "arguments": { "timeoutMS": 0, "filter": {} } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "find", "databaseName": "test", "command": { "find": "coll", "maxTimeMS": { "$$exists": false } } } }, { "commandStartedEvent": { "commandName": "find", "databaseName": "test", "command": { "find": "coll", "maxTimeMS": { "$$exists": false } } } }, { "commandStartedEvent": { "commandName": "find", "databaseName": "test", "command": { "find": "coll", "maxTimeMS": { "$$exists": false } } } } ] } ] }, { "description": "timeoutMS applies to whole operation, not individual attempts - findOne on collection", "runOnRequirements": [ { "minServerVersion": "4.4" } ], "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 4 }, "data": { "failCommands": [ "find" ], "blockConnection": true, "blockTimeMS": 60, "errorCode": 7, "errorLabels": [ "RetryableWriteError" ] } } } }, { "name": "findOne", "object": "collection", "arguments": { "filter": {} }, "expectError": { "isTimeoutError": true } } ] }, { "description": "operation is retried multiple times for non-zero timeoutMS - findOne on collection", "runOnRequirements": [ { "minServerVersion": "4.3.1" } ], "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 2 }, "data": { "failCommands": [ "find" ], "errorCode": 7, "closeConnection": false, "errorLabels": [ "RetryableWriteError" ] } } } }, { "name": "findOne", "object": "collection", "arguments": { "timeoutMS": 1000, "filter": {} } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "find", "databaseName": "test", "command": { "find": "coll", "maxTimeMS": { "$$type": [ "int", "long" ] } } } }, { "commandStartedEvent": { "commandName": "find", "databaseName": "test", "command": { "find": "coll", "maxTimeMS": { "$$type": [ "int", "long" ] } } } }, { "commandStartedEvent": { "commandName": "find", "databaseName": "test", "command": { "find": "coll", "maxTimeMS": { "$$type": [ "int", "long" ] } } } } ] } ] }, { "description": "operation is retried multiple times if timeoutMS is zero - findOne on collection", "runOnRequirements": [ { "minServerVersion": "4.3.1" } ], "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 2 }, "data": { "failCommands": [ "find" ], "errorCode": 7, "closeConnection": false, "errorLabels": [ "RetryableWriteError" ] } } } }, { "name": "findOne", "object": "collection", "arguments": { "timeoutMS": 0, "filter": {} } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "find", "databaseName": "test", "command": { "find": "coll", "maxTimeMS": { "$$exists": false } } } }, { "commandStartedEvent": { "commandName": "find", "databaseName": "test", "command": { "find": "coll", "maxTimeMS": { "$$exists": false } } } }, { "commandStartedEvent": { "commandName": "find", "databaseName": "test", "command": { "find": "coll", "maxTimeMS": { "$$exists": false } } } } ] } ] }, { "description": "timeoutMS applies to whole operation, not individual attempts - listIndexes on collection", "runOnRequirements": [ { "minServerVersion": "4.4" } ], "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 4 }, "data": { "failCommands": [ "listIndexes" ], "blockConnection": true, "blockTimeMS": 60, "errorCode": 7, "errorLabels": [ "RetryableWriteError" ] } } } }, { "name": "listIndexes", "object": "collection", "expectError": { "isTimeoutError": true } } ] }, { "description": "operation is retried multiple times for non-zero timeoutMS - listIndexes on collection", "runOnRequirements": [ { "minServerVersion": "4.3.1" } ], "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 2 }, "data": { "failCommands": [ "listIndexes" ], "errorCode": 7, "closeConnection": false, "errorLabels": [ "RetryableWriteError" ] } } } }, { "name": "listIndexes", "object": "collection", "arguments": { "timeoutMS": 1000 } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "listIndexes", "databaseName": "test", "command": { "listIndexes": "coll", "maxTimeMS": { "$$type": [ "int", "long" ] } } } }, { "commandStartedEvent": { "commandName": "listIndexes", "databaseName": "test", "command": { "listIndexes": "coll", "maxTimeMS": { "$$type": [ "int", "long" ] } } } }, { "commandStartedEvent": { "commandName": "listIndexes", "databaseName": "test", "command": { "listIndexes": "coll", "maxTimeMS": { "$$type": [ "int", "long" ] } } } } ] } ] }, { "description": "operation is retried multiple times if timeoutMS is zero - listIndexes on collection", "runOnRequirements": [ { "minServerVersion": "4.3.1" } ], "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 2 }, "data": { "failCommands": [ "listIndexes" ], "errorCode": 7, "closeConnection": false, "errorLabels": [ "RetryableWriteError" ] } } } }, { "name": "listIndexes", "object": "collection", "arguments": { "timeoutMS": 0 } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "listIndexes", "databaseName": "test", "command": { "listIndexes": "coll", "maxTimeMS": { "$$exists": false } } } }, { "commandStartedEvent": { "commandName": "listIndexes", "databaseName": "test", "command": { "listIndexes": "coll", "maxTimeMS": { "$$exists": false } } } }, { "commandStartedEvent": { "commandName": "listIndexes", "databaseName": "test", "command": { "listIndexes": "coll", "maxTimeMS": { "$$exists": false } } } } ] } ] }, { "description": "timeoutMS applies to whole operation, not individual attempts - createChangeStream on collection", "runOnRequirements": [ { "minServerVersion": "4.4" } ], "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 4 }, "data": { "failCommands": [ "aggregate" ], "blockConnection": true, "blockTimeMS": 60, "errorCode": 7, "errorLabels": [ "RetryableWriteError" ] } } } }, { "name": "createChangeStream", "object": "collection", "arguments": { "pipeline": [] }, "expectError": { "isTimeoutError": true } } ] }, { "description": "operation is retried multiple times for non-zero timeoutMS - createChangeStream on collection", "runOnRequirements": [ { "minServerVersion": "4.3.1" } ], "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 2 }, "data": { "failCommands": [ "aggregate" ], "errorCode": 7, "closeConnection": false, "errorLabels": [ "RetryableWriteError" ] } } } }, { "name": "createChangeStream", "object": "collection", "arguments": { "timeoutMS": 1000, "pipeline": [] } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "aggregate", "databaseName": "test", "command": { "aggregate": "coll", "maxTimeMS": { "$$type": [ "int", "long" ] } } } }, { "commandStartedEvent": { "commandName": "aggregate", "databaseName": "test", "command": { "aggregate": "coll", "maxTimeMS": { "$$type": [ "int", "long" ] } } } }, { "commandStartedEvent": { "commandName": "aggregate", "databaseName": "test", "command": { "aggregate": "coll", "maxTimeMS": { "$$type": [ "int", "long" ] } } } } ] } ] }, { "description": "operation is retried multiple times if timeoutMS is zero - createChangeStream on collection", "runOnRequirements": [ { "minServerVersion": "4.3.1" } ], "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 2 }, "data": { "failCommands": [ "aggregate" ], "errorCode": 7, "closeConnection": false, "errorLabels": [ "RetryableWriteError" ] } } } }, { "name": "createChangeStream", "object": "collection", "arguments": { "timeoutMS": 0, "pipeline": [] } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "aggregate", "databaseName": "test", "command": { "aggregate": "coll", "maxTimeMS": { "$$exists": false } } } }, { "commandStartedEvent": { "commandName": "aggregate", "databaseName": "test", "command": { "aggregate": "coll", "maxTimeMS": { "$$exists": false } } } }, { "commandStartedEvent": { "commandName": "aggregate", "databaseName": "test", "command": { "aggregate": "coll", "maxTimeMS": { "$$exists": false } } } } ] } ] } ] } mongodb-mongo-python-driver-509e9b7/test/csot/sessions-inherit-timeoutMS.json000066400000000000000000000162261462766011000275200ustar00rootroot00000000000000{ "description": "sessions inherit timeoutMS from their parent MongoClient", "schemaVersion": "1.9", "runOnRequirements": [ { "minServerVersion": "4.4", "topologies": [ "replicaset", "sharded-replicaset" ] } ], "createEntities": [ { "client": { "id": "failPointClient", "useMultipleMongoses": false } }, { "client": { "id": "client", "uriOptions": { "timeoutMS": 50 }, "useMultipleMongoses": false, "observeEvents": [ "commandStartedEvent", "commandSucceededEvent", "commandFailedEvent" ] } }, { "database": { "id": "database", "client": "client", "databaseName": "test" } }, { "collection": { "id": "collection", "database": "database", "collectionName": "coll" } }, { "session": { "id": "session", "client": "client" } } ], "initialData": [ { "collectionName": "coll", "databaseName": "test", "documents": [] } ], "tests": [ { "description": "timeoutMS applied to commitTransaction", "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "commitTransaction" ], "blockConnection": true, "blockTimeMS": 60 } } } }, { "name": "startTransaction", "object": "session" }, { "name": "insertOne", "object": "collection", "arguments": { "session": "session", "document": { "_id": 1 } } }, { "name": "commitTransaction", "object": "session", "expectError": { "isTimeoutError": true } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "insert", "databaseName": "test", "command": { "insert": "coll" } } }, { "commandSucceededEvent": { "commandName": "insert" } }, { "commandStartedEvent": { "commandName": "commitTransaction", "databaseName": "admin", "command": { "commitTransaction": 1, "maxTimeMS": { "$$type": [ "int", "long" ] } } } }, { "commandFailedEvent": { "commandName": "commitTransaction" } } ] } ] }, { "description": "timeoutMS applied to abortTransaction", "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "abortTransaction" ], "blockConnection": true, "blockTimeMS": 60 } } } }, { "name": "startTransaction", "object": "session" }, { "name": "insertOne", "object": "collection", "arguments": { "session": "session", "document": { "_id": 1 } } }, { "name": "abortTransaction", "object": "session" } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "insert", "databaseName": "test", "command": { "insert": "coll" } } }, { "commandSucceededEvent": { "commandName": "insert" } }, { "commandStartedEvent": { "commandName": "abortTransaction", "databaseName": "admin", "command": { "abortTransaction": 1, "maxTimeMS": { "$$type": [ "int", "long" ] } } } }, { "commandFailedEvent": { "commandName": "abortTransaction" } } ] } ] }, { "description": "timeoutMS applied to withTransaction", "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "insert" ], "blockConnection": true, "blockTimeMS": 60 } } } }, { "name": "withTransaction", "object": "session", "arguments": { "callback": [ { "name": "insertOne", "object": "collection", "arguments": { "session": "session", "document": { "_id": 1 } }, "expectError": { "isTimeoutError": true } } ] }, "expectError": { "isTimeoutError": true } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "insert", "databaseName": "test", "command": { "insert": "coll", "maxTimeMS": { "$$type": [ "int", "long" ] } } } }, { "commandFailedEvent": { "commandName": "insert" } } ] } ] } ] } mongodb-mongo-python-driver-509e9b7/test/csot/sessions-override-operation-timeoutMS.json000066400000000000000000000164121462766011000316700ustar00rootroot00000000000000{ "description": "timeoutMS can be overridden for individual session operations", "schemaVersion": "1.9", "runOnRequirements": [ { "minServerVersion": "4.4", "topologies": [ "replicaset", "sharded-replicaset" ] } ], "createEntities": [ { "client": { "id": "failPointClient", "useMultipleMongoses": false } }, { "client": { "id": "client", "useMultipleMongoses": false, "observeEvents": [ "commandStartedEvent", "commandSucceededEvent", "commandFailedEvent" ] } }, { "database": { "id": "database", "client": "client", "databaseName": "test" } }, { "collection": { "id": "collection", "database": "database", "collectionName": "coll" } }, { "session": { "id": "session", "client": "client" } } ], "initialData": [ { "collectionName": "coll", "databaseName": "test", "documents": [] } ], "tests": [ { "description": "timeoutMS can be overridden for commitTransaction", "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "commitTransaction" ], "blockConnection": true, "blockTimeMS": 60 } } } }, { "name": "startTransaction", "object": "session" }, { "name": "insertOne", "object": "collection", "arguments": { "session": "session", "document": { "_id": 1 } } }, { "name": "commitTransaction", "object": "session", "arguments": { "timeoutMS": 50 }, "expectError": { "isTimeoutError": true } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "insert", "databaseName": "test", "command": { "insert": "coll" } } }, { "commandSucceededEvent": { "commandName": "insert" } }, { "commandStartedEvent": { "commandName": "commitTransaction", "databaseName": "admin", "command": { "commitTransaction": 1, "maxTimeMS": { "$$type": [ "int", "long" ] } } } }, { "commandFailedEvent": { "commandName": "commitTransaction" } } ] } ] }, { "description": "timeoutMS applied to abortTransaction", "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "abortTransaction" ], "blockConnection": true, "blockTimeMS": 60 } } } }, { "name": "startTransaction", "object": "session" }, { "name": "insertOne", "object": "collection", "arguments": { "session": "session", "document": { "_id": 1 } } }, { "name": "abortTransaction", "object": "session", "arguments": { "timeoutMS": 50 } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "insert", "databaseName": "test", "command": { "insert": "coll" } } }, { "commandSucceededEvent": { "commandName": "insert" } }, { "commandStartedEvent": { "commandName": "abortTransaction", "databaseName": "admin", "command": { "abortTransaction": 1, "maxTimeMS": { "$$type": [ "int", "long" ] } } } }, { "commandFailedEvent": { "commandName": "abortTransaction" } } ] } ] }, { "description": "timeoutMS applied to withTransaction", "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "insert" ], "blockConnection": true, "blockTimeMS": 60 } } } }, { "name": "withTransaction", "object": "session", "arguments": { "timeoutMS": 50, "callback": [ { "name": "insertOne", "object": "collection", "arguments": { "session": "session", "document": { "_id": 1 } }, "expectError": { "isTimeoutError": true } } ] }, "expectError": { "isTimeoutError": true } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "insert", "databaseName": "test", "command": { "insert": "coll", "maxTimeMS": { "$$type": [ "int", "long" ] } } } }, { "commandFailedEvent": { "commandName": "insert" } } ] } ] } ] } mongodb-mongo-python-driver-509e9b7/test/csot/sessions-override-timeoutMS.json000066400000000000000000000162441462766011000276750ustar00rootroot00000000000000{ "description": "timeoutMS can be overridden at the level of a ClientSession", "schemaVersion": "1.9", "runOnRequirements": [ { "minServerVersion": "4.4", "topologies": [ "replicaset", "sharded-replicaset" ] } ], "createEntities": [ { "client": { "id": "failPointClient", "useMultipleMongoses": false } }, { "client": { "id": "client", "useMultipleMongoses": false, "observeEvents": [ "commandStartedEvent", "commandSucceededEvent", "commandFailedEvent" ] } }, { "database": { "id": "database", "client": "client", "databaseName": "test" } }, { "collection": { "id": "collection", "database": "database", "collectionName": "coll" } }, { "session": { "id": "session", "client": "client", "sessionOptions": { "defaultTimeoutMS": 50 } } } ], "initialData": [ { "collectionName": "coll", "databaseName": "test", "documents": [] } ], "tests": [ { "description": "timeoutMS applied to commitTransaction", "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "commitTransaction" ], "blockConnection": true, "blockTimeMS": 60 } } } }, { "name": "startTransaction", "object": "session" }, { "name": "insertOne", "object": "collection", "arguments": { "session": "session", "document": { "_id": 1 } } }, { "name": "commitTransaction", "object": "session", "expectError": { "isTimeoutError": true } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "insert", "databaseName": "test", "command": { "insert": "coll" } } }, { "commandSucceededEvent": { "commandName": "insert" } }, { "commandStartedEvent": { "commandName": "commitTransaction", "databaseName": "admin", "command": { "commitTransaction": 1, "maxTimeMS": { "$$type": [ "int", "long" ] } } } }, { "commandFailedEvent": { "commandName": "commitTransaction" } } ] } ] }, { "description": "timeoutMS applied to abortTransaction", "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "abortTransaction" ], "blockConnection": true, "blockTimeMS": 60 } } } }, { "name": "startTransaction", "object": "session" }, { "name": "insertOne", "object": "collection", "arguments": { "session": "session", "document": { "_id": 1 } } }, { "name": "abortTransaction", "object": "session" } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "insert", "databaseName": "test", "command": { "insert": "coll" } } }, { "commandSucceededEvent": { "commandName": "insert" } }, { "commandStartedEvent": { "commandName": "abortTransaction", "databaseName": "admin", "command": { "abortTransaction": 1, "maxTimeMS": { "$$type": [ "int", "long" ] } } } }, { "commandFailedEvent": { "commandName": "abortTransaction" } } ] } ] }, { "description": "timeoutMS applied to withTransaction", "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "insert" ], "blockConnection": true, "blockTimeMS": 60 } } } }, { "name": "withTransaction", "object": "session", "arguments": { "callback": [ { "name": "insertOne", "object": "collection", "arguments": { "session": "session", "document": { "_id": 1 } }, "expectError": { "isTimeoutError": true } } ] }, "expectError": { "isTimeoutError": true } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "insert", "databaseName": "test", "command": { "insert": "coll", "maxTimeMS": { "$$type": [ "int", "long" ] } } } }, { "commandFailedEvent": { "commandName": "insert" } } ] } ] } ] } mongodb-mongo-python-driver-509e9b7/test/csot/tailable-awaitData.json000066400000000000000000000241501462766011000257330ustar00rootroot00000000000000{ "description": "timeoutMS behaves correctly for tailable awaitData cursors", "schemaVersion": "1.9", "runOnRequirements": [ { "minServerVersion": "4.4" } ], "createEntities": [ { "client": { "id": "failPointClient", "useMultipleMongoses": false } }, { "client": { "id": "client", "uriOptions": { "timeoutMS": 10 }, "useMultipleMongoses": false, "observeEvents": [ "commandStartedEvent" ] } }, { "database": { "id": "database", "client": "client", "databaseName": "test" } }, { "collection": { "id": "collection", "database": "database", "collectionName": "coll" } } ], "initialData": [ { "collectionName": "coll", "databaseName": "test", "createOptions": { "capped": true, "size": 500 }, "documents": [ { "_id": 0 }, { "_id": 1 } ] } ], "tests": [ { "description": "error if timeoutMode is cursor_lifetime", "operations": [ { "name": "find", "object": "collection", "arguments": { "filter": {}, "timeoutMode": "cursorLifetime", "cursorType": "tailableAwait" }, "expectError": { "isClientError": true } } ] }, { "description": "error if maxAwaitTimeMS is greater than timeoutMS", "operations": [ { "name": "find", "object": "collection", "arguments": { "filter": {}, "cursorType": "tailableAwait", "timeoutMS": 5, "maxAwaitTimeMS": 10 }, "expectError": { "isClientError": true } } ] }, { "description": "error if maxAwaitTimeMS is equal to timeoutMS", "operations": [ { "name": "find", "object": "collection", "arguments": { "filter": {}, "cursorType": "tailableAwait", "timeoutMS": 5, "maxAwaitTimeMS": 5 }, "expectError": { "isClientError": true } } ] }, { "description": "timeoutMS applied to find", "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "find" ], "blockConnection": true, "blockTimeMS": 15 } } } }, { "name": "find", "object": "collection", "arguments": { "filter": {}, "cursorType": "tailableAwait" }, "expectError": { "isTimeoutError": true } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "find", "databaseName": "test", "command": { "find": "coll", "tailable": true, "awaitData": true, "maxTimeMS": { "$$exists": true } } } } ] } ] }, { "description": "timeoutMS is refreshed for getMore if maxAwaitTimeMS is not set", "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 2 }, "data": { "failCommands": [ "find", "getMore" ], "blockConnection": true, "blockTimeMS": 15 } } } }, { "name": "createFindCursor", "object": "collection", "arguments": { "filter": {}, "cursorType": "tailableAwait", "timeoutMS": 20, "batchSize": 1 }, "saveResultAsEntity": "tailableCursor" }, { "name": "iterateUntilDocumentOrError", "object": "tailableCursor" }, { "name": "iterateUntilDocumentOrError", "object": "tailableCursor" } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "find", "databaseName": "test", "command": { "find": "coll", "tailable": true, "awaitData": true, "maxTimeMS": { "$$exists": true } } } }, { "commandStartedEvent": { "commandName": "getMore", "databaseName": "test", "command": { "getMore": { "$$type": [ "int", "long" ] }, "collection": "coll", "maxTimeMS": { "$$exists": false } } } } ] } ] }, { "description": "timeoutMS is refreshed for getMore if maxAwaitTimeMS is set", "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 2 }, "data": { "failCommands": [ "find", "getMore" ], "blockConnection": true, "blockTimeMS": 15 } } } }, { "name": "createFindCursor", "object": "collection", "arguments": { "filter": {}, "cursorType": "tailableAwait", "timeoutMS": 20, "batchSize": 1, "maxAwaitTimeMS": 1 }, "saveResultAsEntity": "tailableCursor" }, { "name": "iterateUntilDocumentOrError", "object": "tailableCursor" }, { "name": "iterateUntilDocumentOrError", "object": "tailableCursor" } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "find", "databaseName": "test", "command": { "find": "coll", "tailable": true, "awaitData": true, "maxTimeMS": { "$$exists": true } } } }, { "commandStartedEvent": { "commandName": "getMore", "databaseName": "test", "command": { "getMore": { "$$type": [ "int", "long" ] }, "collection": "coll", "maxTimeMS": 1 } } } ] } ] }, { "description": "timeoutMS is refreshed for getMore - failure", "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "getMore" ], "blockConnection": true, "blockTimeMS": 15 } } } }, { "name": "createFindCursor", "object": "collection", "arguments": { "filter": {}, "cursorType": "tailableAwait", "batchSize": 1 }, "saveResultAsEntity": "tailableCursor" }, { "name": "iterateUntilDocumentOrError", "object": "tailableCursor" }, { "name": "iterateUntilDocumentOrError", "object": "tailableCursor", "expectError": { "isTimeoutError": true } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "find", "databaseName": "test", "command": { "find": "coll", "tailable": true, "awaitData": true, "maxTimeMS": { "$$exists": true } } } }, { "commandStartedEvent": { "commandName": "getMore", "databaseName": "test", "command": { "getMore": { "$$type": [ "int", "long" ] }, "collection": "coll" } } } ] } ] } ] } mongodb-mongo-python-driver-509e9b7/test/csot/tailable-non-awaitData.json000066400000000000000000000165151462766011000265310ustar00rootroot00000000000000{ "description": "timeoutMS behaves correctly for tailable non-awaitData cursors", "schemaVersion": "1.9", "runOnRequirements": [ { "minServerVersion": "4.4" } ], "createEntities": [ { "client": { "id": "failPointClient", "useMultipleMongoses": false } }, { "client": { "id": "client", "uriOptions": { "timeoutMS": 10 }, "useMultipleMongoses": false, "observeEvents": [ "commandStartedEvent" ] } }, { "database": { "id": "database", "client": "client", "databaseName": "test" } }, { "collection": { "id": "collection", "database": "database", "collectionName": "coll" } } ], "initialData": [ { "collectionName": "coll", "databaseName": "test", "createOptions": { "capped": true, "size": 500 }, "documents": [ { "_id": 0 }, { "_id": 1 } ] } ], "tests": [ { "description": "error if timeoutMode is cursor_lifetime", "operations": [ { "name": "find", "object": "collection", "arguments": { "filter": {}, "timeoutMode": "cursorLifetime", "cursorType": "tailable" }, "expectError": { "isClientError": true } } ] }, { "description": "timeoutMS applied to find", "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "find" ], "blockConnection": true, "blockTimeMS": 15 } } } }, { "name": "find", "object": "collection", "arguments": { "filter": {}, "cursorType": "tailable" }, "expectError": { "isTimeoutError": true } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "find", "databaseName": "test", "command": { "find": "coll", "tailable": true, "awaitData": { "$$exists": false }, "maxTimeMS": { "$$exists": false } } } } ] } ] }, { "description": "timeoutMS is refreshed for getMore - success", "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 2 }, "data": { "failCommands": [ "find", "getMore" ], "blockConnection": true, "blockTimeMS": 15 } } } }, { "name": "createFindCursor", "object": "collection", "arguments": { "filter": {}, "cursorType": "tailable", "timeoutMS": 20, "batchSize": 1 }, "saveResultAsEntity": "tailableCursor" }, { "name": "iterateUntilDocumentOrError", "object": "tailableCursor" }, { "name": "iterateUntilDocumentOrError", "object": "tailableCursor" } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "find", "databaseName": "test", "command": { "find": "coll", "tailable": true, "awaitData": { "$$exists": false }, "maxTimeMS": { "$$exists": false } } } }, { "commandStartedEvent": { "commandName": "getMore", "databaseName": "test", "command": { "getMore": { "$$type": [ "int", "long" ] }, "collection": "coll", "maxTimeMS": { "$$exists": false } } } } ] } ] }, { "description": "timeoutMS is refreshed for getMore - failure", "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "getMore" ], "blockConnection": true, "blockTimeMS": 15 } } } }, { "name": "createFindCursor", "object": "collection", "arguments": { "filter": {}, "cursorType": "tailable", "batchSize": 1 }, "saveResultAsEntity": "tailableCursor" }, { "name": "iterateUntilDocumentOrError", "object": "tailableCursor" }, { "name": "iterateUntilDocumentOrError", "object": "tailableCursor", "expectError": { "isTimeoutError": true } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "find", "databaseName": "test", "command": { "find": "coll", "tailable": true, "awaitData": { "$$exists": false }, "maxTimeMS": { "$$exists": false } } } }, { "commandStartedEvent": { "commandName": "getMore", "databaseName": "test", "command": { "getMore": { "$$type": [ "int", "long" ] }, "collection": "coll", "maxTimeMS": { "$$exists": false } } } } ] } ] } ] } mongodb-mongo-python-driver-509e9b7/test/data_lake/000077500000000000000000000000001462766011000223215ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/data_lake/aggregate.json000066400000000000000000000020101462766011000251330ustar00rootroot00000000000000{ "collection_name": "driverdata", "database_name": "test", "tests": [ { "description": "Aggregate with pipeline (project, sort, limit)", "operations": [ { "object": "collection", "name": "aggregate", "arguments": { "pipeline": [ { "$project": { "_id": 0 } }, { "$sort": { "a": 1 } }, { "$limit": 2 } ] }, "result": [ { "a": 1, "b": 2, "c": 3 }, { "a": 2, "b": 3, "c": 4 } ] } ], "expectations": [ { "command_started_event": { "command": { "aggregate": "driverdata" } } } ] } ] } mongodb-mongo-python-driver-509e9b7/test/data_lake/estimatedDocumentCount.json000066400000000000000000000010511462766011000277000ustar00rootroot00000000000000{ "collection_name": "driverdata", "database_name": "test", "tests": [ { "description": "estimatedDocumentCount succeeds", "operations": [ { "object": "collection", "name": "estimatedDocumentCount", "result": 15 } ], "expectations": [ { "command_started_event": { "command": { "count": "driverdata" }, "command_name": "count", "database_name": "test" } } ] } ] } mongodb-mongo-python-driver-509e9b7/test/data_lake/find.json000066400000000000000000000023131462766011000241330ustar00rootroot00000000000000{ "collection_name": "driverdata", "database_name": "test", "tests": [ { "description": "Find with projection and sort", "operations": [ { "object": "collection", "name": "find", "arguments": { "filter": { "b": { "$gt": 5 } }, "projection": { "_id": 0 }, "sort": { "a": 1 }, "limit": 5 }, "result": [ { "a": 5, "b": 6, "c": 7 }, { "a": 6, "b": 7, "c": 8 }, { "a": 7, "b": 8, "c": 9 }, { "a": 8, "b": 9, "c": 10 }, { "a": 9, "b": 10, "c": 11 } ] } ], "expectations": [ { "command_started_event": { "command": { "find": "driverdata" } } } ] } ] } mongodb-mongo-python-driver-509e9b7/test/data_lake/getMore.json000066400000000000000000000022741462766011000246230ustar00rootroot00000000000000{ "collection_name": "driverdata", "database_name": "test", "tests": [ { "description": "A successful find event with getMore", "operations": [ { "object": "collection", "name": "find", "arguments": { "filter": { "a": { "$gte": 2 } }, "sort": { "a": 1 }, "batchSize": 3, "limit": 4 } } ], "expectations": [ { "command_started_event": { "command": { "find": "driverdata", "filter": { "a": { "$gte": 2 } }, "sort": { "a": 1 }, "batchSize": 3, "limit": 4 }, "command_name": "find", "database_name": "test" } }, { "command_started_event": { "command": { "batchSize": 1 }, "command_name": "getMore", "database_name": "cursors" } } ] } ] } mongodb-mongo-python-driver-509e9b7/test/data_lake/listCollections.json000066400000000000000000000007471462766011000263760ustar00rootroot00000000000000{ "database_name": "test", "tests": [ { "description": "ListCollections succeeds", "operations": [ { "name": "listCollections", "object": "database" } ], "expectations": [ { "command_started_event": { "command_name": "listCollections", "database_name": "test", "command": { "listCollections": 1 } } } ] } ] } mongodb-mongo-python-driver-509e9b7/test/data_lake/listDatabases.json000066400000000000000000000007031462766011000257770ustar00rootroot00000000000000{ "tests": [ { "description": "ListDatabases succeeds", "operations": [ { "name": "listDatabases", "object": "client" } ], "expectations": [ { "command_started_event": { "command_name": "listDatabases", "database_name": "admin", "command": { "listDatabases": 1 } } } ] } ] } mongodb-mongo-python-driver-509e9b7/test/data_lake/runCommand.json000066400000000000000000000011311462766011000253130ustar00rootroot00000000000000{ "database_name": "test", "tests": [ { "description": "ping succeeds using runCommand", "operations": [ { "name": "runCommand", "object": "database", "command_name": "ping", "arguments": { "command": { "ping": 1 } } } ], "expectations": [ { "command_started_event": { "command_name": "ping", "database_name": "test", "command": { "ping": 1 } } } ] } ] } mongodb-mongo-python-driver-509e9b7/test/discovery_and_monitoring/000077500000000000000000000000001462766011000255125ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/discovery_and_monitoring/errors/000077500000000000000000000000001462766011000270265ustar00rootroot00000000000000error_handling_handshake.json000066400000000000000000000054411462766011000346510ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/discovery_and_monitoring/errors{ "description": "Network timeouts before and after the handshake completes", "uri": "mongodb://a/?replicaSet=rs", "phases": [ { "description": "Primary A is discovered", "responses": [ [ "a:27017", { "ok": 1, "helloOk": true, "isWritablePrimary": true, "hosts": [ "a:27017" ], "setName": "rs", "minWireVersion": 0, "maxWireVersion": 9, "topologyVersion": { "processId": { "$oid": "000000000000000000000001" }, "counter": { "$numberLong": "1" } } } ] ], "outcome": { "servers": { "a:27017": { "type": "RSPrimary", "setName": "rs", "topologyVersion": { "processId": { "$oid": "000000000000000000000001" }, "counter": { "$numberLong": "1" } }, "pool": { "generation": 0 } } }, "topologyType": "ReplicaSetWithPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } }, { "description": "Ignore network timeout application error (afterHandshakeCompletes)", "applicationErrors": [ { "address": "a:27017", "when": "afterHandshakeCompletes", "maxWireVersion": 9, "type": "timeout" } ], "outcome": { "servers": { "a:27017": { "type": "RSPrimary", "setName": "rs", "topologyVersion": { "processId": { "$oid": "000000000000000000000001" }, "counter": { "$numberLong": "1" } }, "pool": { "generation": 0 } } }, "topologyType": "ReplicaSetWithPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } }, { "description": "Mark server unknown on network timeout application error (beforeHandshakeCompletes)", "applicationErrors": [ { "address": "a:27017", "when": "beforeHandshakeCompletes", "maxWireVersion": 9, "type": "timeout" } ], "outcome": { "servers": { "a:27017": { "type": "Unknown", "topologyVersion": null, "pool": { "generation": 1 } } }, "topologyType": "ReplicaSetNoPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } } ] } non-stale-network-error.json000066400000000000000000000035711462766011000343660ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/discovery_and_monitoring/errors{ "description": "Non-stale network error", "uri": "mongodb://a/?replicaSet=rs", "phases": [ { "description": "Primary A is discovered", "responses": [ [ "a:27017", { "ok": 1, "helloOk": true, "isWritablePrimary": true, "hosts": [ "a:27017" ], "setName": "rs", "minWireVersion": 0, "maxWireVersion": 9, "topologyVersion": { "processId": { "$oid": "000000000000000000000001" }, "counter": { "$numberLong": "1" } } } ] ], "outcome": { "servers": { "a:27017": { "type": "RSPrimary", "setName": "rs", "topologyVersion": { "processId": { "$oid": "000000000000000000000001" }, "counter": { "$numberLong": "1" } }, "pool": { "generation": 0 } } }, "topologyType": "ReplicaSetWithPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } }, { "description": "Non-stale network error marks server Unknown", "applicationErrors": [ { "address": "a:27017", "when": "afterHandshakeCompletes", "maxWireVersion": 9, "type": "network" } ], "outcome": { "servers": { "a:27017": { "type": "Unknown", "topologyVersion": null, "pool": { "generation": 1 } } }, "topologyType": "ReplicaSetNoPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } } ] } non-stale-network-timeout-error.json000066400000000000000000000041541462766011000360500ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/discovery_and_monitoring/errors{ "description": "Non-stale network timeout error", "uri": "mongodb://a/?replicaSet=rs", "phases": [ { "description": "Primary A is discovered", "responses": [ [ "a:27017", { "ok": 1, "helloOk": true, "isWritablePrimary": true, "hosts": [ "a:27017" ], "setName": "rs", "minWireVersion": 0, "maxWireVersion": 9, "topologyVersion": { "processId": { "$oid": "000000000000000000000001" }, "counter": { "$numberLong": "1" } } } ] ], "outcome": { "servers": { "a:27017": { "type": "RSPrimary", "setName": "rs", "topologyVersion": { "processId": { "$oid": "000000000000000000000001" }, "counter": { "$numberLong": "1" } }, "pool": { "generation": 0 } } }, "topologyType": "ReplicaSetWithPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } }, { "description": "Non-stale network timeout error does not mark server Unknown", "applicationErrors": [ { "address": "a:27017", "when": "afterHandshakeCompletes", "maxWireVersion": 9, "type": "timeout" } ], "outcome": { "servers": { "a:27017": { "type": "RSPrimary", "setName": "rs", "topologyVersion": { "processId": { "$oid": "000000000000000000000001" }, "counter": { "$numberLong": "1" } }, "pool": { "generation": 0 } } }, "topologyType": "ReplicaSetWithPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } } ] } non-stale-topologyVersion-greater-InterruptedAtShutdown.json000066400000000000000000000047411462766011000427430ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/discovery_and_monitoring/errors{ "description": "Non-stale topologyVersion greater InterruptedAtShutdown error", "uri": "mongodb://a/?replicaSet=rs", "phases": [ { "description": "Primary A is discovered", "responses": [ [ "a:27017", { "ok": 1, "helloOk": true, "isWritablePrimary": true, "hosts": [ "a:27017" ], "setName": "rs", "minWireVersion": 0, "maxWireVersion": 9, "topologyVersion": { "processId": { "$oid": "000000000000000000000001" }, "counter": { "$numberLong": "1" } } } ] ], "outcome": { "servers": { "a:27017": { "type": "RSPrimary", "setName": "rs", "topologyVersion": { "processId": { "$oid": "000000000000000000000001" }, "counter": { "$numberLong": "1" } }, "pool": { "generation": 0 } } }, "topologyType": "ReplicaSetWithPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } }, { "description": "Non-stale topologyVersion greater InterruptedAtShutdown error marks server Unknown", "applicationErrors": [ { "address": "a:27017", "when": "afterHandshakeCompletes", "maxWireVersion": 9, "type": "command", "response": { "ok": 0, "errmsg": "InterruptedAtShutdown", "code": 11600, "topologyVersion": { "processId": { "$oid": "000000000000000000000001" }, "counter": { "$numberLong": "2" } } } } ], "outcome": { "servers": { "a:27017": { "type": "Unknown", "topologyVersion": { "processId": { "$oid": "000000000000000000000001" }, "counter": { "$numberLong": "2" } }, "pool": { "generation": 1 } } }, "topologyType": "ReplicaSetNoPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } } ] } non-stale-topologyVersion-greater-InterruptedDueToReplStateChange.json000066400000000000000000000047771462766011000446260ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/discovery_and_monitoring/errors{ "description": "Non-stale topologyVersion greater InterruptedDueToReplStateChange error", "uri": "mongodb://a/?replicaSet=rs", "phases": [ { "description": "Primary A is discovered", "responses": [ [ "a:27017", { "ok": 1, "helloOk": true, "isWritablePrimary": true, "hosts": [ "a:27017" ], "setName": "rs", "minWireVersion": 0, "maxWireVersion": 9, "topologyVersion": { "processId": { "$oid": "000000000000000000000001" }, "counter": { "$numberLong": "1" } } } ] ], "outcome": { "servers": { "a:27017": { "type": "RSPrimary", "setName": "rs", "topologyVersion": { "processId": { "$oid": "000000000000000000000001" }, "counter": { "$numberLong": "1" } }, "pool": { "generation": 0 } } }, "topologyType": "ReplicaSetWithPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } }, { "description": "Non-stale topologyVersion greater InterruptedDueToReplStateChange error marks server Unknown", "applicationErrors": [ { "address": "a:27017", "when": "afterHandshakeCompletes", "maxWireVersion": 9, "type": "command", "response": { "ok": 0, "errmsg": "InterruptedDueToReplStateChange", "code": 11602, "topologyVersion": { "processId": { "$oid": "000000000000000000000001" }, "counter": { "$numberLong": "2" } } } } ], "outcome": { "servers": { "a:27017": { "type": "Unknown", "topologyVersion": { "processId": { "$oid": "000000000000000000000001" }, "counter": { "$numberLong": "2" } }, "pool": { "generation": 0 } } }, "topologyType": "ReplicaSetNoPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } } ] } non-stale-topologyVersion-greater-LegacyNotPrimary.json000066400000000000000000000047221462766011000416450ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/discovery_and_monitoring/errors{ "description": "Non-stale topologyVersion greater LegacyNotPrimary error", "uri": "mongodb://a/?replicaSet=rs", "phases": [ { "description": "Primary A is discovered", "responses": [ [ "a:27017", { "ok": 1, "helloOk": true, "isWritablePrimary": true, "hosts": [ "a:27017" ], "setName": "rs", "minWireVersion": 0, "maxWireVersion": 9, "topologyVersion": { "processId": { "$oid": "000000000000000000000001" }, "counter": { "$numberLong": "1" } } } ] ], "outcome": { "servers": { "a:27017": { "type": "RSPrimary", "setName": "rs", "topologyVersion": { "processId": { "$oid": "000000000000000000000001" }, "counter": { "$numberLong": "1" } }, "pool": { "generation": 0 } } }, "topologyType": "ReplicaSetWithPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } }, { "description": "Non-stale topologyVersion greater LegacyNotPrimary error marks server Unknown", "applicationErrors": [ { "address": "a:27017", "when": "afterHandshakeCompletes", "maxWireVersion": 9, "type": "command", "response": { "ok": 0, "errmsg": "LegacyNotPrimary", "code": 10058, "topologyVersion": { "processId": { "$oid": "000000000000000000000001" }, "counter": { "$numberLong": "2" } } } } ], "outcome": { "servers": { "a:27017": { "type": "Unknown", "topologyVersion": { "processId": { "$oid": "000000000000000000000001" }, "counter": { "$numberLong": "2" } }, "pool": { "generation": 0 } } }, "topologyType": "ReplicaSetNoPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } } ] } non-stale-topologyVersion-greater-NotPrimaryNoSecondaryOk.json000066400000000000000000000047471462766011000431660ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/discovery_and_monitoring/errors{ "description": "Non-stale topologyVersion greater NotPrimaryNoSecondaryOk error", "uri": "mongodb://a/?replicaSet=rs", "phases": [ { "description": "Primary A is discovered", "responses": [ [ "a:27017", { "ok": 1, "helloOk": true, "isWritablePrimary": true, "hosts": [ "a:27017" ], "setName": "rs", "minWireVersion": 0, "maxWireVersion": 9, "topologyVersion": { "processId": { "$oid": "000000000000000000000001" }, "counter": { "$numberLong": "1" } } } ] ], "outcome": { "servers": { "a:27017": { "type": "RSPrimary", "setName": "rs", "topologyVersion": { "processId": { "$oid": "000000000000000000000001" }, "counter": { "$numberLong": "1" } }, "pool": { "generation": 0 } } }, "topologyType": "ReplicaSetWithPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } }, { "description": "Non-stale topologyVersion greater NotPrimaryNoSecondaryOk error marks server Unknown", "applicationErrors": [ { "address": "a:27017", "when": "afterHandshakeCompletes", "maxWireVersion": 9, "type": "command", "response": { "ok": 0, "errmsg": "NotPrimaryNoSecondaryOk", "code": 13435, "topologyVersion": { "processId": { "$oid": "000000000000000000000001" }, "counter": { "$numberLong": "2" } } } } ], "outcome": { "servers": { "a:27017": { "type": "Unknown", "topologyVersion": { "processId": { "$oid": "000000000000000000000001" }, "counter": { "$numberLong": "2" } }, "pool": { "generation": 0 } } }, "topologyType": "ReplicaSetNoPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } } ] } non-stale-topologyVersion-greater-NotPrimaryOrSecondary.json000066400000000000000000000047411462766011000426720ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/discovery_and_monitoring/errors{ "description": "Non-stale topologyVersion greater NotPrimaryOrSecondary error", "uri": "mongodb://a/?replicaSet=rs", "phases": [ { "description": "Primary A is discovered", "responses": [ [ "a:27017", { "ok": 1, "helloOk": true, "isWritablePrimary": true, "hosts": [ "a:27017" ], "setName": "rs", "minWireVersion": 0, "maxWireVersion": 9, "topologyVersion": { "processId": { "$oid": "000000000000000000000001" }, "counter": { "$numberLong": "1" } } } ] ], "outcome": { "servers": { "a:27017": { "type": "RSPrimary", "setName": "rs", "topologyVersion": { "processId": { "$oid": "000000000000000000000001" }, "counter": { "$numberLong": "1" } }, "pool": { "generation": 0 } } }, "topologyType": "ReplicaSetWithPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } }, { "description": "Non-stale topologyVersion greater NotPrimaryOrSecondary error marks server Unknown", "applicationErrors": [ { "address": "a:27017", "when": "afterHandshakeCompletes", "maxWireVersion": 9, "type": "command", "response": { "ok": 0, "errmsg": "NotPrimaryOrSecondary", "code": 13436, "topologyVersion": { "processId": { "$oid": "000000000000000000000001" }, "counter": { "$numberLong": "2" } } } } ], "outcome": { "servers": { "a:27017": { "type": "Unknown", "topologyVersion": { "processId": { "$oid": "000000000000000000000001" }, "counter": { "$numberLong": "2" } }, "pool": { "generation": 0 } } }, "topologyType": "ReplicaSetNoPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } } ] } non-stale-topologyVersion-greater-NotWritablePrimary.json000066400000000000000000000047301462766011000422110ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/discovery_and_monitoring/errors{ "description": "Non-stale topologyVersion greater NotWritablePrimary error", "uri": "mongodb://a/?replicaSet=rs", "phases": [ { "description": "Primary A is discovered", "responses": [ [ "a:27017", { "ok": 1, "helloOk": true, "isWritablePrimary": true, "hosts": [ "a:27017" ], "setName": "rs", "minWireVersion": 0, "maxWireVersion": 9, "topologyVersion": { "processId": { "$oid": "000000000000000000000001" }, "counter": { "$numberLong": "1" } } } ] ], "outcome": { "servers": { "a:27017": { "type": "RSPrimary", "setName": "rs", "topologyVersion": { "processId": { "$oid": "000000000000000000000001" }, "counter": { "$numberLong": "1" } }, "pool": { "generation": 0 } } }, "topologyType": "ReplicaSetWithPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } }, { "description": "Non-stale topologyVersion greater NotWritablePrimary error marks server Unknown", "applicationErrors": [ { "address": "a:27017", "when": "afterHandshakeCompletes", "maxWireVersion": 9, "type": "command", "response": { "ok": 0, "errmsg": "NotWritablePrimary", "code": 10107, "topologyVersion": { "processId": { "$oid": "000000000000000000000001" }, "counter": { "$numberLong": "2" } } } } ], "outcome": { "servers": { "a:27017": { "type": "Unknown", "topologyVersion": { "processId": { "$oid": "000000000000000000000001" }, "counter": { "$numberLong": "2" } }, "pool": { "generation": 0 } } }, "topologyType": "ReplicaSetNoPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } } ] } non-stale-topologyVersion-greater-PrimarySteppedDown.json000066400000000000000000000047261462766011000422200ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/discovery_and_monitoring/errors{ "description": "Non-stale topologyVersion greater PrimarySteppedDown error", "uri": "mongodb://a/?replicaSet=rs", "phases": [ { "description": "Primary A is discovered", "responses": [ [ "a:27017", { "ok": 1, "helloOk": true, "isWritablePrimary": true, "hosts": [ "a:27017" ], "setName": "rs", "minWireVersion": 0, "maxWireVersion": 9, "topologyVersion": { "processId": { "$oid": "000000000000000000000001" }, "counter": { "$numberLong": "1" } } } ] ], "outcome": { "servers": { "a:27017": { "type": "RSPrimary", "setName": "rs", "topologyVersion": { "processId": { "$oid": "000000000000000000000001" }, "counter": { "$numberLong": "1" } }, "pool": { "generation": 0 } } }, "topologyType": "ReplicaSetWithPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } }, { "description": "Non-stale topologyVersion greater PrimarySteppedDown error marks server Unknown", "applicationErrors": [ { "address": "a:27017", "when": "afterHandshakeCompletes", "maxWireVersion": 9, "type": "command", "response": { "ok": 0, "errmsg": "PrimarySteppedDown", "code": 189, "topologyVersion": { "processId": { "$oid": "000000000000000000000001" }, "counter": { "$numberLong": "2" } } } } ], "outcome": { "servers": { "a:27017": { "type": "Unknown", "topologyVersion": { "processId": { "$oid": "000000000000000000000001" }, "counter": { "$numberLong": "2" } }, "pool": { "generation": 0 } } }, "topologyType": "ReplicaSetNoPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } } ] } non-stale-topologyVersion-greater-ShutdownInProgress.json000066400000000000000000000047251462766011000422460ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/discovery_and_monitoring/errors{ "description": "Non-stale topologyVersion greater ShutdownInProgress error", "uri": "mongodb://a/?replicaSet=rs", "phases": [ { "description": "Primary A is discovered", "responses": [ [ "a:27017", { "ok": 1, "helloOk": true, "isWritablePrimary": true, "hosts": [ "a:27017" ], "setName": "rs", "minWireVersion": 0, "maxWireVersion": 9, "topologyVersion": { "processId": { "$oid": "000000000000000000000001" }, "counter": { "$numberLong": "1" } } } ] ], "outcome": { "servers": { "a:27017": { "type": "RSPrimary", "setName": "rs", "topologyVersion": { "processId": { "$oid": "000000000000000000000001" }, "counter": { "$numberLong": "1" } }, "pool": { "generation": 0 } } }, "topologyType": "ReplicaSetWithPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } }, { "description": "Non-stale topologyVersion greater ShutdownInProgress error marks server Unknown", "applicationErrors": [ { "address": "a:27017", "when": "afterHandshakeCompletes", "maxWireVersion": 9, "type": "command", "response": { "ok": 0, "errmsg": "ShutdownInProgress", "code": 91, "topologyVersion": { "processId": { "$oid": "000000000000000000000001" }, "counter": { "$numberLong": "2" } } } } ], "outcome": { "servers": { "a:27017": { "type": "Unknown", "topologyVersion": { "processId": { "$oid": "000000000000000000000001" }, "counter": { "$numberLong": "2" } }, "pool": { "generation": 1 } } }, "topologyType": "ReplicaSetNoPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } } ] } non-stale-topologyVersion-missing-InterruptedAtShutdown.json000066400000000000000000000041101462766011000427510ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/discovery_and_monitoring/errors{ "description": "Non-stale topologyVersion missing InterruptedAtShutdown error", "uri": "mongodb://a/?replicaSet=rs", "phases": [ { "description": "Primary A is discovered", "responses": [ [ "a:27017", { "ok": 1, "helloOk": true, "isWritablePrimary": true, "hosts": [ "a:27017" ], "setName": "rs", "minWireVersion": 0, "maxWireVersion": 9, "topologyVersion": { "processId": { "$oid": "000000000000000000000001" }, "counter": { "$numberLong": "1" } } } ] ], "outcome": { "servers": { "a:27017": { "type": "RSPrimary", "setName": "rs", "topologyVersion": { "processId": { "$oid": "000000000000000000000001" }, "counter": { "$numberLong": "1" } }, "pool": { "generation": 0 } } }, "topologyType": "ReplicaSetWithPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } }, { "description": "Non-stale topologyVersion missing InterruptedAtShutdown error marks server Unknown", "applicationErrors": [ { "address": "a:27017", "when": "afterHandshakeCompletes", "maxWireVersion": 9, "type": "command", "response": { "ok": 0, "errmsg": "InterruptedAtShutdown", "code": 11600 } } ], "outcome": { "servers": { "a:27017": { "type": "Unknown", "topologyVersion": null, "pool": { "generation": 1 } } }, "topologyType": "ReplicaSetNoPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } } ] } non-stale-topologyVersion-missing-InterruptedDueToReplStateChange.json000066400000000000000000000041461462766011000446340ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/discovery_and_monitoring/errors{ "description": "Non-stale topologyVersion missing InterruptedDueToReplStateChange error", "uri": "mongodb://a/?replicaSet=rs", "phases": [ { "description": "Primary A is discovered", "responses": [ [ "a:27017", { "ok": 1, "helloOk": true, "isWritablePrimary": true, "hosts": [ "a:27017" ], "setName": "rs", "minWireVersion": 0, "maxWireVersion": 9, "topologyVersion": { "processId": { "$oid": "000000000000000000000001" }, "counter": { "$numberLong": "1" } } } ] ], "outcome": { "servers": { "a:27017": { "type": "RSPrimary", "setName": "rs", "topologyVersion": { "processId": { "$oid": "000000000000000000000001" }, "counter": { "$numberLong": "1" } }, "pool": { "generation": 0 } } }, "topologyType": "ReplicaSetWithPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } }, { "description": "Non-stale topologyVersion missing InterruptedDueToReplStateChange error marks server Unknown", "applicationErrors": [ { "address": "a:27017", "when": "afterHandshakeCompletes", "maxWireVersion": 9, "type": "command", "response": { "ok": 0, "errmsg": "InterruptedDueToReplStateChange", "code": 11602 } } ], "outcome": { "servers": { "a:27017": { "type": "Unknown", "topologyVersion": null, "pool": { "generation": 0 } } }, "topologyType": "ReplicaSetNoPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } } ] } non-stale-topologyVersion-missing-LegacyNotPrimary.json000066400000000000000000000040711462766011000416620ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/discovery_and_monitoring/errors{ "description": "Non-stale topologyVersion missing LegacyNotPrimary error", "uri": "mongodb://a/?replicaSet=rs", "phases": [ { "description": "Primary A is discovered", "responses": [ [ "a:27017", { "ok": 1, "helloOk": true, "isWritablePrimary": true, "hosts": [ "a:27017" ], "setName": "rs", "minWireVersion": 0, "maxWireVersion": 9, "topologyVersion": { "processId": { "$oid": "000000000000000000000001" }, "counter": { "$numberLong": "1" } } } ] ], "outcome": { "servers": { "a:27017": { "type": "RSPrimary", "setName": "rs", "topologyVersion": { "processId": { "$oid": "000000000000000000000001" }, "counter": { "$numberLong": "1" } }, "pool": { "generation": 0 } } }, "topologyType": "ReplicaSetWithPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } }, { "description": "Non-stale topologyVersion missing LegacyNotPrimary error marks server Unknown", "applicationErrors": [ { "address": "a:27017", "when": "afterHandshakeCompletes", "maxWireVersion": 9, "type": "command", "response": { "ok": 0, "errmsg": "LegacyNotPrimary", "code": 10058 } } ], "outcome": { "servers": { "a:27017": { "type": "Unknown", "topologyVersion": null, "pool": { "generation": 0 } } }, "topologyType": "ReplicaSetNoPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } } ] } non-stale-topologyVersion-missing-NotPrimaryNoSecondaryOk.json000066400000000000000000000041161462766011000431740ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/discovery_and_monitoring/errors{ "description": "Non-stale topologyVersion missing NotPrimaryNoSecondaryOk error", "uri": "mongodb://a/?replicaSet=rs", "phases": [ { "description": "Primary A is discovered", "responses": [ [ "a:27017", { "ok": 1, "helloOk": true, "isWritablePrimary": true, "hosts": [ "a:27017" ], "setName": "rs", "minWireVersion": 0, "maxWireVersion": 9, "topologyVersion": { "processId": { "$oid": "000000000000000000000001" }, "counter": { "$numberLong": "1" } } } ] ], "outcome": { "servers": { "a:27017": { "type": "RSPrimary", "setName": "rs", "topologyVersion": { "processId": { "$oid": "000000000000000000000001" }, "counter": { "$numberLong": "1" } }, "pool": { "generation": 0 } } }, "topologyType": "ReplicaSetWithPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } }, { "description": "Non-stale topologyVersion missing NotPrimaryNoSecondaryOk error marks server Unknown", "applicationErrors": [ { "address": "a:27017", "when": "afterHandshakeCompletes", "maxWireVersion": 9, "type": "command", "response": { "ok": 0, "errmsg": "NotPrimaryNoSecondaryOk", "code": 13435 } } ], "outcome": { "servers": { "a:27017": { "type": "Unknown", "topologyVersion": null, "pool": { "generation": 0 } } }, "topologyType": "ReplicaSetNoPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } } ] } non-stale-topologyVersion-missing-NotPrimaryOrSecondary.json000066400000000000000000000041101462766011000427000ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/discovery_and_monitoring/errors{ "description": "Non-stale topologyVersion missing NotPrimaryOrSecondary error", "uri": "mongodb://a/?replicaSet=rs", "phases": [ { "description": "Primary A is discovered", "responses": [ [ "a:27017", { "ok": 1, "helloOk": true, "isWritablePrimary": true, "hosts": [ "a:27017" ], "setName": "rs", "minWireVersion": 0, "maxWireVersion": 9, "topologyVersion": { "processId": { "$oid": "000000000000000000000001" }, "counter": { "$numberLong": "1" } } } ] ], "outcome": { "servers": { "a:27017": { "type": "RSPrimary", "setName": "rs", "topologyVersion": { "processId": { "$oid": "000000000000000000000001" }, "counter": { "$numberLong": "1" } }, "pool": { "generation": 0 } } }, "topologyType": "ReplicaSetWithPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } }, { "description": "Non-stale topologyVersion missing NotPrimaryOrSecondary error marks server Unknown", "applicationErrors": [ { "address": "a:27017", "when": "afterHandshakeCompletes", "maxWireVersion": 9, "type": "command", "response": { "ok": 0, "errmsg": "NotPrimaryOrSecondary", "code": 13436 } } ], "outcome": { "servers": { "a:27017": { "type": "Unknown", "topologyVersion": null, "pool": { "generation": 0 } } }, "topologyType": "ReplicaSetNoPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } } ] } non-stale-topologyVersion-missing-NotWritablePrimary.json000066400000000000000000000040771462766011000422350ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/discovery_and_monitoring/errors{ "description": "Non-stale topologyVersion missing NotWritablePrimary error", "uri": "mongodb://a/?replicaSet=rs", "phases": [ { "description": "Primary A is discovered", "responses": [ [ "a:27017", { "ok": 1, "helloOk": true, "isWritablePrimary": true, "hosts": [ "a:27017" ], "setName": "rs", "minWireVersion": 0, "maxWireVersion": 9, "topologyVersion": { "processId": { "$oid": "000000000000000000000001" }, "counter": { "$numberLong": "1" } } } ] ], "outcome": { "servers": { "a:27017": { "type": "RSPrimary", "setName": "rs", "topologyVersion": { "processId": { "$oid": "000000000000000000000001" }, "counter": { "$numberLong": "1" } }, "pool": { "generation": 0 } } }, "topologyType": "ReplicaSetWithPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } }, { "description": "Non-stale topologyVersion missing NotWritablePrimary error marks server Unknown", "applicationErrors": [ { "address": "a:27017", "when": "afterHandshakeCompletes", "maxWireVersion": 9, "type": "command", "response": { "ok": 0, "errmsg": "NotWritablePrimary", "code": 10107 } } ], "outcome": { "servers": { "a:27017": { "type": "Unknown", "topologyVersion": null, "pool": { "generation": 0 } } }, "topologyType": "ReplicaSetNoPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } } ] } non-stale-topologyVersion-missing-PrimarySteppedDown.json000066400000000000000000000040751462766011000422350ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/discovery_and_monitoring/errors{ "description": "Non-stale topologyVersion missing PrimarySteppedDown error", "uri": "mongodb://a/?replicaSet=rs", "phases": [ { "description": "Primary A is discovered", "responses": [ [ "a:27017", { "ok": 1, "helloOk": true, "isWritablePrimary": true, "hosts": [ "a:27017" ], "setName": "rs", "minWireVersion": 0, "maxWireVersion": 9, "topologyVersion": { "processId": { "$oid": "000000000000000000000001" }, "counter": { "$numberLong": "1" } } } ] ], "outcome": { "servers": { "a:27017": { "type": "RSPrimary", "setName": "rs", "topologyVersion": { "processId": { "$oid": "000000000000000000000001" }, "counter": { "$numberLong": "1" } }, "pool": { "generation": 0 } } }, "topologyType": "ReplicaSetWithPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } }, { "description": "Non-stale topologyVersion missing PrimarySteppedDown error marks server Unknown", "applicationErrors": [ { "address": "a:27017", "when": "afterHandshakeCompletes", "maxWireVersion": 9, "type": "command", "response": { "ok": 0, "errmsg": "PrimarySteppedDown", "code": 189 } } ], "outcome": { "servers": { "a:27017": { "type": "Unknown", "topologyVersion": null, "pool": { "generation": 0 } } }, "topologyType": "ReplicaSetNoPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } } ] } non-stale-topologyVersion-missing-ShutdownInProgress.json000066400000000000000000000040741462766011000422630ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/discovery_and_monitoring/errors{ "description": "Non-stale topologyVersion missing ShutdownInProgress error", "uri": "mongodb://a/?replicaSet=rs", "phases": [ { "description": "Primary A is discovered", "responses": [ [ "a:27017", { "ok": 1, "helloOk": true, "isWritablePrimary": true, "hosts": [ "a:27017" ], "setName": "rs", "minWireVersion": 0, "maxWireVersion": 9, "topologyVersion": { "processId": { "$oid": "000000000000000000000001" }, "counter": { "$numberLong": "1" } } } ] ], "outcome": { "servers": { "a:27017": { "type": "RSPrimary", "setName": "rs", "topologyVersion": { "processId": { "$oid": "000000000000000000000001" }, "counter": { "$numberLong": "1" } }, "pool": { "generation": 0 } } }, "topologyType": "ReplicaSetWithPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } }, { "description": "Non-stale topologyVersion missing ShutdownInProgress error marks server Unknown", "applicationErrors": [ { "address": "a:27017", "when": "afterHandshakeCompletes", "maxWireVersion": 9, "type": "command", "response": { "ok": 0, "errmsg": "ShutdownInProgress", "code": 91 } } ], "outcome": { "servers": { "a:27017": { "type": "Unknown", "topologyVersion": null, "pool": { "generation": 1 } } }, "topologyType": "ReplicaSetNoPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } } ] } non-stale-topologyVersion-proccessId-changed-InterruptedAtShutdown.json000066400000000000000000000047671462766011000450070ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/discovery_and_monitoring/errors{ "description": "Non-stale topologyVersion proccessId changed InterruptedAtShutdown error", "uri": "mongodb://a/?replicaSet=rs", "phases": [ { "description": "Primary A is discovered", "responses": [ [ "a:27017", { "ok": 1, "helloOk": true, "isWritablePrimary": true, "hosts": [ "a:27017" ], "setName": "rs", "minWireVersion": 0, "maxWireVersion": 9, "topologyVersion": { "processId": { "$oid": "000000000000000000000001" }, "counter": { "$numberLong": "1" } } } ] ], "outcome": { "servers": { "a:27017": { "type": "RSPrimary", "setName": "rs", "topologyVersion": { "processId": { "$oid": "000000000000000000000001" }, "counter": { "$numberLong": "1" } }, "pool": { "generation": 0 } } }, "topologyType": "ReplicaSetWithPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } }, { "description": "Non-stale topologyVersion proccessId changed InterruptedAtShutdown error marks server Unknown", "applicationErrors": [ { "address": "a:27017", "when": "afterHandshakeCompletes", "maxWireVersion": 9, "type": "command", "response": { "ok": 0, "errmsg": "InterruptedAtShutdown", "code": 11600, "topologyVersion": { "processId": { "$oid": "000000000000000000000002" }, "counter": { "$numberLong": "1" } } } } ], "outcome": { "servers": { "a:27017": { "type": "Unknown", "topologyVersion": { "processId": { "$oid": "000000000000000000000002" }, "counter": { "$numberLong": "1" } }, "pool": { "generation": 1 } } }, "topologyType": "ReplicaSetNoPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } } ] } non-stale-topologyVersion-proccessId-changed-InterruptedDueToReplStateChange.json000066400000000000000000000050251462766011000466450ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/discovery_and_monitoring/errors{ "description": "Non-stale topologyVersion proccessId changed InterruptedDueToReplStateChange error", "uri": "mongodb://a/?replicaSet=rs", "phases": [ { "description": "Primary A is discovered", "responses": [ [ "a:27017", { "ok": 1, "helloOk": true, "isWritablePrimary": true, "hosts": [ "a:27017" ], "setName": "rs", "minWireVersion": 0, "maxWireVersion": 9, "topologyVersion": { "processId": { "$oid": "000000000000000000000001" }, "counter": { "$numberLong": "1" } } } ] ], "outcome": { "servers": { "a:27017": { "type": "RSPrimary", "setName": "rs", "topologyVersion": { "processId": { "$oid": "000000000000000000000001" }, "counter": { "$numberLong": "1" } }, "pool": { "generation": 0 } } }, "topologyType": "ReplicaSetWithPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } }, { "description": "Non-stale topologyVersion proccessId changed InterruptedDueToReplStateChange error marks server Unknown", "applicationErrors": [ { "address": "a:27017", "when": "afterHandshakeCompletes", "maxWireVersion": 9, "type": "command", "response": { "ok": 0, "errmsg": "InterruptedDueToReplStateChange", "code": 11602, "topologyVersion": { "processId": { "$oid": "000000000000000000000002" }, "counter": { "$numberLong": "1" } } } } ], "outcome": { "servers": { "a:27017": { "type": "Unknown", "topologyVersion": { "processId": { "$oid": "000000000000000000000002" }, "counter": { "$numberLong": "1" } }, "pool": { "generation": 0 } } }, "topologyType": "ReplicaSetNoPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } } ] } non-stale-topologyVersion-proccessId-changed-LegacyNotPrimary.json000066400000000000000000000047501462766011000437020ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/discovery_and_monitoring/errors{ "description": "Non-stale topologyVersion proccessId changed LegacyNotPrimary error", "uri": "mongodb://a/?replicaSet=rs", "phases": [ { "description": "Primary A is discovered", "responses": [ [ "a:27017", { "ok": 1, "helloOk": true, "isWritablePrimary": true, "hosts": [ "a:27017" ], "setName": "rs", "minWireVersion": 0, "maxWireVersion": 9, "topologyVersion": { "processId": { "$oid": "000000000000000000000001" }, "counter": { "$numberLong": "1" } } } ] ], "outcome": { "servers": { "a:27017": { "type": "RSPrimary", "setName": "rs", "topologyVersion": { "processId": { "$oid": "000000000000000000000001" }, "counter": { "$numberLong": "1" } }, "pool": { "generation": 0 } } }, "topologyType": "ReplicaSetWithPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } }, { "description": "Non-stale topologyVersion proccessId changed LegacyNotPrimary error marks server Unknown", "applicationErrors": [ { "address": "a:27017", "when": "afterHandshakeCompletes", "maxWireVersion": 9, "type": "command", "response": { "ok": 0, "errmsg": "LegacyNotPrimary", "code": 10058, "topologyVersion": { "processId": { "$oid": "000000000000000000000002" }, "counter": { "$numberLong": "1" } } } } ], "outcome": { "servers": { "a:27017": { "type": "Unknown", "topologyVersion": { "processId": { "$oid": "000000000000000000000002" }, "counter": { "$numberLong": "1" } }, "pool": { "generation": 0 } } }, "topologyType": "ReplicaSetNoPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } } ] } non-stale-topologyVersion-proccessId-changed-NotPrimaryNoSecondaryOk.json000066400000000000000000000047751462766011000452230ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/discovery_and_monitoring/errors{ "description": "Non-stale topologyVersion proccessId changed NotPrimaryNoSecondaryOk error", "uri": "mongodb://a/?replicaSet=rs", "phases": [ { "description": "Primary A is discovered", "responses": [ [ "a:27017", { "ok": 1, "helloOk": true, "isWritablePrimary": true, "hosts": [ "a:27017" ], "setName": "rs", "minWireVersion": 0, "maxWireVersion": 9, "topologyVersion": { "processId": { "$oid": "000000000000000000000001" }, "counter": { "$numberLong": "1" } } } ] ], "outcome": { "servers": { "a:27017": { "type": "RSPrimary", "setName": "rs", "topologyVersion": { "processId": { "$oid": "000000000000000000000001" }, "counter": { "$numberLong": "1" } }, "pool": { "generation": 0 } } }, "topologyType": "ReplicaSetWithPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } }, { "description": "Non-stale topologyVersion proccessId changed NotPrimaryNoSecondaryOk error marks server Unknown", "applicationErrors": [ { "address": "a:27017", "when": "afterHandshakeCompletes", "maxWireVersion": 9, "type": "command", "response": { "ok": 0, "errmsg": "NotPrimaryNoSecondaryOk", "code": 13435, "topologyVersion": { "processId": { "$oid": "000000000000000000000002" }, "counter": { "$numberLong": "1" } } } } ], "outcome": { "servers": { "a:27017": { "type": "Unknown", "topologyVersion": { "processId": { "$oid": "000000000000000000000002" }, "counter": { "$numberLong": "1" } }, "pool": { "generation": 0 } } }, "topologyType": "ReplicaSetNoPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } } ] } non-stale-topologyVersion-proccessId-changed-NotPrimaryOrSecondary.json000066400000000000000000000047671462766011000447360ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/discovery_and_monitoring/errors{ "description": "Non-stale topologyVersion proccessId changed NotPrimaryOrSecondary error", "uri": "mongodb://a/?replicaSet=rs", "phases": [ { "description": "Primary A is discovered", "responses": [ [ "a:27017", { "ok": 1, "helloOk": true, "isWritablePrimary": true, "hosts": [ "a:27017" ], "setName": "rs", "minWireVersion": 0, "maxWireVersion": 9, "topologyVersion": { "processId": { "$oid": "000000000000000000000001" }, "counter": { "$numberLong": "1" } } } ] ], "outcome": { "servers": { "a:27017": { "type": "RSPrimary", "setName": "rs", "topologyVersion": { "processId": { "$oid": "000000000000000000000001" }, "counter": { "$numberLong": "1" } }, "pool": { "generation": 0 } } }, "topologyType": "ReplicaSetWithPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } }, { "description": "Non-stale topologyVersion proccessId changed NotPrimaryOrSecondary error marks server Unknown", "applicationErrors": [ { "address": "a:27017", "when": "afterHandshakeCompletes", "maxWireVersion": 9, "type": "command", "response": { "ok": 0, "errmsg": "NotPrimaryOrSecondary", "code": 13436, "topologyVersion": { "processId": { "$oid": "000000000000000000000002" }, "counter": { "$numberLong": "1" } } } } ], "outcome": { "servers": { "a:27017": { "type": "Unknown", "topologyVersion": { "processId": { "$oid": "000000000000000000000002" }, "counter": { "$numberLong": "1" } }, "pool": { "generation": 0 } } }, "topologyType": "ReplicaSetNoPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } } ] } non-stale-topologyVersion-proccessId-changed-NotWritablePrimary.json000066400000000000000000000047561462766011000442550ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/discovery_and_monitoring/errors{ "description": "Non-stale topologyVersion proccessId changed NotWritablePrimary error", "uri": "mongodb://a/?replicaSet=rs", "phases": [ { "description": "Primary A is discovered", "responses": [ [ "a:27017", { "ok": 1, "helloOk": true, "isWritablePrimary": true, "hosts": [ "a:27017" ], "setName": "rs", "minWireVersion": 0, "maxWireVersion": 9, "topologyVersion": { "processId": { "$oid": "000000000000000000000001" }, "counter": { "$numberLong": "1" } } } ] ], "outcome": { "servers": { "a:27017": { "type": "RSPrimary", "setName": "rs", "topologyVersion": { "processId": { "$oid": "000000000000000000000001" }, "counter": { "$numberLong": "1" } }, "pool": { "generation": 0 } } }, "topologyType": "ReplicaSetWithPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } }, { "description": "Non-stale topologyVersion proccessId changed NotWritablePrimary error marks server Unknown", "applicationErrors": [ { "address": "a:27017", "when": "afterHandshakeCompletes", "maxWireVersion": 9, "type": "command", "response": { "ok": 0, "errmsg": "NotWritablePrimary", "code": 10107, "topologyVersion": { "processId": { "$oid": "000000000000000000000002" }, "counter": { "$numberLong": "1" } } } } ], "outcome": { "servers": { "a:27017": { "type": "Unknown", "topologyVersion": { "processId": { "$oid": "000000000000000000000002" }, "counter": { "$numberLong": "1" } }, "pool": { "generation": 0 } } }, "topologyType": "ReplicaSetNoPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } } ] } non-stale-topologyVersion-proccessId-changed-PrimarySteppedDown.json000066400000000000000000000047541462766011000442550ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/discovery_and_monitoring/errors{ "description": "Non-stale topologyVersion proccessId changed PrimarySteppedDown error", "uri": "mongodb://a/?replicaSet=rs", "phases": [ { "description": "Primary A is discovered", "responses": [ [ "a:27017", { "ok": 1, "helloOk": true, "isWritablePrimary": true, "hosts": [ "a:27017" ], "setName": "rs", "minWireVersion": 0, "maxWireVersion": 9, "topologyVersion": { "processId": { "$oid": "000000000000000000000001" }, "counter": { "$numberLong": "1" } } } ] ], "outcome": { "servers": { "a:27017": { "type": "RSPrimary", "setName": "rs", "topologyVersion": { "processId": { "$oid": "000000000000000000000001" }, "counter": { "$numberLong": "1" } }, "pool": { "generation": 0 } } }, "topologyType": "ReplicaSetWithPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } }, { "description": "Non-stale topologyVersion proccessId changed PrimarySteppedDown error marks server Unknown", "applicationErrors": [ { "address": "a:27017", "when": "afterHandshakeCompletes", "maxWireVersion": 9, "type": "command", "response": { "ok": 0, "errmsg": "PrimarySteppedDown", "code": 189, "topologyVersion": { "processId": { "$oid": "000000000000000000000002" }, "counter": { "$numberLong": "1" } } } } ], "outcome": { "servers": { "a:27017": { "type": "Unknown", "topologyVersion": { "processId": { "$oid": "000000000000000000000002" }, "counter": { "$numberLong": "1" } }, "pool": { "generation": 0 } } }, "topologyType": "ReplicaSetNoPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } } ] } non-stale-topologyVersion-proccessId-changed-ShutdownInProgress.json000066400000000000000000000047531462766011000443030ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/discovery_and_monitoring/errors{ "description": "Non-stale topologyVersion proccessId changed ShutdownInProgress error", "uri": "mongodb://a/?replicaSet=rs", "phases": [ { "description": "Primary A is discovered", "responses": [ [ "a:27017", { "ok": 1, "helloOk": true, "isWritablePrimary": true, "hosts": [ "a:27017" ], "setName": "rs", "minWireVersion": 0, "maxWireVersion": 9, "topologyVersion": { "processId": { "$oid": "000000000000000000000001" }, "counter": { "$numberLong": "1" } } } ] ], "outcome": { "servers": { "a:27017": { "type": "RSPrimary", "setName": "rs", "topologyVersion": { "processId": { "$oid": "000000000000000000000001" }, "counter": { "$numberLong": "1" } }, "pool": { "generation": 0 } } }, "topologyType": "ReplicaSetWithPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } }, { "description": "Non-stale topologyVersion proccessId changed ShutdownInProgress error marks server Unknown", "applicationErrors": [ { "address": "a:27017", "when": "afterHandshakeCompletes", "maxWireVersion": 9, "type": "command", "response": { "ok": 0, "errmsg": "ShutdownInProgress", "code": 91, "topologyVersion": { "processId": { "$oid": "000000000000000000000002" }, "counter": { "$numberLong": "1" } } } } ], "outcome": { "servers": { "a:27017": { "type": "Unknown", "topologyVersion": { "processId": { "$oid": "000000000000000000000002" }, "counter": { "$numberLong": "1" } }, "pool": { "generation": 1 } } }, "topologyType": "ReplicaSetNoPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } } ] } post-42-InterruptedAtShutdown.json000066400000000000000000000031751462766011000354040ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/discovery_and_monitoring/errors{ "description": "Post-4.2 InterruptedAtShutdown error", "uri": "mongodb://a/?replicaSet=rs", "phases": [ { "description": "Primary A is discovered", "responses": [ [ "a:27017", { "ok": 1, "helloOk": true, "isWritablePrimary": true, "hosts": [ "a:27017" ], "setName": "rs", "minWireVersion": 0, "maxWireVersion": 8 } ] ], "outcome": { "servers": { "a:27017": { "type": "RSPrimary", "setName": "rs", "topologyVersion": null, "pool": { "generation": 0 } } }, "topologyType": "ReplicaSetWithPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } }, { "description": "Post-4.2 InterruptedAtShutdown error marks server Unknown", "applicationErrors": [ { "address": "a:27017", "when": "afterHandshakeCompletes", "maxWireVersion": 8, "type": "command", "response": { "ok": 0, "errmsg": "InterruptedAtShutdown", "code": 11600 } } ], "outcome": { "servers": { "a:27017": { "type": "Unknown", "topologyVersion": null, "pool": { "generation": 1 } } }, "topologyType": "ReplicaSetNoPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } } ] } post-42-InterruptedDueToReplStateChange.json000066400000000000000000000032331462766011000372510ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/discovery_and_monitoring/errors{ "description": "Post-4.2 InterruptedDueToReplStateChange error", "uri": "mongodb://a/?replicaSet=rs", "phases": [ { "description": "Primary A is discovered", "responses": [ [ "a:27017", { "ok": 1, "helloOk": true, "isWritablePrimary": true, "hosts": [ "a:27017" ], "setName": "rs", "minWireVersion": 0, "maxWireVersion": 8 } ] ], "outcome": { "servers": { "a:27017": { "type": "RSPrimary", "setName": "rs", "topologyVersion": null, "pool": { "generation": 0 } } }, "topologyType": "ReplicaSetWithPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } }, { "description": "Post-4.2 InterruptedDueToReplStateChange error marks server Unknown", "applicationErrors": [ { "address": "a:27017", "when": "afterHandshakeCompletes", "maxWireVersion": 8, "type": "command", "response": { "ok": 0, "errmsg": "InterruptedDueToReplStateChange", "code": 11602 } } ], "outcome": { "servers": { "a:27017": { "type": "Unknown", "topologyVersion": null, "pool": { "generation": 0 } } }, "topologyType": "ReplicaSetNoPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } } ] } post-42-LegacyNotPrimary.json000066400000000000000000000031561462766011000343060ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/discovery_and_monitoring/errors{ "description": "Post-4.2 LegacyNotPrimary error", "uri": "mongodb://a/?replicaSet=rs", "phases": [ { "description": "Primary A is discovered", "responses": [ [ "a:27017", { "ok": 1, "helloOk": true, "isWritablePrimary": true, "hosts": [ "a:27017" ], "setName": "rs", "minWireVersion": 0, "maxWireVersion": 8 } ] ], "outcome": { "servers": { "a:27017": { "type": "RSPrimary", "setName": "rs", "topologyVersion": null, "pool": { "generation": 0 } } }, "topologyType": "ReplicaSetWithPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } }, { "description": "Post-4.2 LegacyNotPrimary error marks server Unknown", "applicationErrors": [ { "address": "a:27017", "when": "afterHandshakeCompletes", "maxWireVersion": 8, "type": "command", "response": { "ok": 0, "errmsg": "LegacyNotPrimary", "code": 10058 } } ], "outcome": { "servers": { "a:27017": { "type": "Unknown", "topologyVersion": null, "pool": { "generation": 0 } } }, "topologyType": "ReplicaSetNoPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } } ] } post-42-NotPrimaryNoSecondaryOk.json000066400000000000000000000032031462766011000356110ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/discovery_and_monitoring/errors{ "description": "Post-4.2 NotPrimaryNoSecondaryOk error", "uri": "mongodb://a/?replicaSet=rs", "phases": [ { "description": "Primary A is discovered", "responses": [ [ "a:27017", { "ok": 1, "helloOk": true, "isWritablePrimary": true, "hosts": [ "a:27017" ], "setName": "rs", "minWireVersion": 0, "maxWireVersion": 8 } ] ], "outcome": { "servers": { "a:27017": { "type": "RSPrimary", "setName": "rs", "topologyVersion": null, "pool": { "generation": 0 } } }, "topologyType": "ReplicaSetWithPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } }, { "description": "Post-4.2 NotPrimaryNoSecondaryOk error marks server Unknown", "applicationErrors": [ { "address": "a:27017", "when": "afterHandshakeCompletes", "maxWireVersion": 8, "type": "command", "response": { "ok": 0, "errmsg": "NotPrimaryNoSecondaryOk", "code": 13435 } } ], "outcome": { "servers": { "a:27017": { "type": "Unknown", "topologyVersion": null, "pool": { "generation": 0 } } }, "topologyType": "ReplicaSetNoPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } } ] } post-42-NotPrimaryOrSecondary.json000066400000000000000000000031751462766011000353330ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/discovery_and_monitoring/errors{ "description": "Post-4.2 NotPrimaryOrSecondary error", "uri": "mongodb://a/?replicaSet=rs", "phases": [ { "description": "Primary A is discovered", "responses": [ [ "a:27017", { "ok": 1, "helloOk": true, "isWritablePrimary": true, "hosts": [ "a:27017" ], "setName": "rs", "minWireVersion": 0, "maxWireVersion": 8 } ] ], "outcome": { "servers": { "a:27017": { "type": "RSPrimary", "setName": "rs", "topologyVersion": null, "pool": { "generation": 0 } } }, "topologyType": "ReplicaSetWithPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } }, { "description": "Post-4.2 NotPrimaryOrSecondary error marks server Unknown", "applicationErrors": [ { "address": "a:27017", "when": "afterHandshakeCompletes", "maxWireVersion": 8, "type": "command", "response": { "ok": 0, "errmsg": "NotPrimaryOrSecondary", "code": 13436 } } ], "outcome": { "servers": { "a:27017": { "type": "Unknown", "topologyVersion": null, "pool": { "generation": 0 } } }, "topologyType": "ReplicaSetNoPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } } ] } post-42-NotWritablePrimary.json000066400000000000000000000031641462766011000346520ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/discovery_and_monitoring/errors{ "description": "Post-4.2 NotWritablePrimary error", "uri": "mongodb://a/?replicaSet=rs", "phases": [ { "description": "Primary A is discovered", "responses": [ [ "a:27017", { "ok": 1, "helloOk": true, "isWritablePrimary": true, "hosts": [ "a:27017" ], "setName": "rs", "minWireVersion": 0, "maxWireVersion": 8 } ] ], "outcome": { "servers": { "a:27017": { "type": "RSPrimary", "setName": "rs", "topologyVersion": null, "pool": { "generation": 0 } } }, "topologyType": "ReplicaSetWithPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } }, { "description": "Post-4.2 NotWritablePrimary error marks server Unknown", "applicationErrors": [ { "address": "a:27017", "when": "afterHandshakeCompletes", "maxWireVersion": 8, "type": "command", "response": { "ok": 0, "errmsg": "NotWritablePrimary", "code": 10107 } } ], "outcome": { "servers": { "a:27017": { "type": "Unknown", "topologyVersion": null, "pool": { "generation": 0 } } }, "topologyType": "ReplicaSetNoPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } } ] } post-42-PrimarySteppedDown.json000066400000000000000000000031621462766011000346520ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/discovery_and_monitoring/errors{ "description": "Post-4.2 PrimarySteppedDown error", "uri": "mongodb://a/?replicaSet=rs", "phases": [ { "description": "Primary A is discovered", "responses": [ [ "a:27017", { "ok": 1, "helloOk": true, "isWritablePrimary": true, "hosts": [ "a:27017" ], "setName": "rs", "minWireVersion": 0, "maxWireVersion": 8 } ] ], "outcome": { "servers": { "a:27017": { "type": "RSPrimary", "setName": "rs", "topologyVersion": null, "pool": { "generation": 0 } } }, "topologyType": "ReplicaSetWithPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } }, { "description": "Post-4.2 PrimarySteppedDown error marks server Unknown", "applicationErrors": [ { "address": "a:27017", "when": "afterHandshakeCompletes", "maxWireVersion": 8, "type": "command", "response": { "ok": 0, "errmsg": "PrimarySteppedDown", "code": 189 } } ], "outcome": { "servers": { "a:27017": { "type": "Unknown", "topologyVersion": null, "pool": { "generation": 0 } } }, "topologyType": "ReplicaSetNoPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } } ] } post-42-ShutdownInProgress.json000066400000000000000000000031611462766011000347000ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/discovery_and_monitoring/errors{ "description": "Post-4.2 ShutdownInProgress error", "uri": "mongodb://a/?replicaSet=rs", "phases": [ { "description": "Primary A is discovered", "responses": [ [ "a:27017", { "ok": 1, "helloOk": true, "isWritablePrimary": true, "hosts": [ "a:27017" ], "setName": "rs", "minWireVersion": 0, "maxWireVersion": 8 } ] ], "outcome": { "servers": { "a:27017": { "type": "RSPrimary", "setName": "rs", "topologyVersion": null, "pool": { "generation": 0 } } }, "topologyType": "ReplicaSetWithPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } }, { "description": "Post-4.2 ShutdownInProgress error marks server Unknown", "applicationErrors": [ { "address": "a:27017", "when": "afterHandshakeCompletes", "maxWireVersion": 8, "type": "command", "response": { "ok": 0, "errmsg": "ShutdownInProgress", "code": 91 } } ], "outcome": { "servers": { "a:27017": { "type": "Unknown", "topologyVersion": null, "pool": { "generation": 1 } } }, "topologyType": "ReplicaSetNoPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } } ] } pre-42-InterruptedAtShutdown.json000066400000000000000000000032171462766011000352020ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/discovery_and_monitoring/errors{ "description": "Pre-4.2 InterruptedAtShutdown error", "uri": "mongodb://a/?replicaSet=rs", "phases": [ { "description": "Primary A is discovered", "responses": [ [ "a:27017", { "ok": 1, "helloOk": true, "isWritablePrimary": true, "hosts": [ "a:27017" ], "setName": "rs", "minWireVersion": 0, "maxWireVersion": 7 } ] ], "outcome": { "servers": { "a:27017": { "type": "RSPrimary", "setName": "rs", "topologyVersion": null, "pool": { "generation": 0 } } }, "topologyType": "ReplicaSetWithPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } }, { "description": "Pre-4.2 InterruptedAtShutdown error marks server Unknown and clears the pool", "applicationErrors": [ { "address": "a:27017", "when": "afterHandshakeCompletes", "maxWireVersion": 7, "type": "command", "response": { "ok": 0, "errmsg": "InterruptedAtShutdown", "code": 11600 } } ], "outcome": { "servers": { "a:27017": { "type": "Unknown", "topologyVersion": null, "pool": { "generation": 1 } } }, "topologyType": "ReplicaSetNoPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } } ] } pre-42-InterruptedDueToReplStateChange.json000066400000000000000000000032551462766011000370560ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/discovery_and_monitoring/errors{ "description": "Pre-4.2 InterruptedDueToReplStateChange error", "uri": "mongodb://a/?replicaSet=rs", "phases": [ { "description": "Primary A is discovered", "responses": [ [ "a:27017", { "ok": 1, "helloOk": true, "isWritablePrimary": true, "hosts": [ "a:27017" ], "setName": "rs", "minWireVersion": 0, "maxWireVersion": 7 } ] ], "outcome": { "servers": { "a:27017": { "type": "RSPrimary", "setName": "rs", "topologyVersion": null, "pool": { "generation": 0 } } }, "topologyType": "ReplicaSetWithPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } }, { "description": "Pre-4.2 InterruptedDueToReplStateChange error marks server Unknown and clears the pool", "applicationErrors": [ { "address": "a:27017", "when": "afterHandshakeCompletes", "maxWireVersion": 7, "type": "command", "response": { "ok": 0, "errmsg": "InterruptedDueToReplStateChange", "code": 11602 } } ], "outcome": { "servers": { "a:27017": { "type": "Unknown", "topologyVersion": null, "pool": { "generation": 1 } } }, "topologyType": "ReplicaSetNoPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } } ] } pre-42-LegacyNotPrimary.json000066400000000000000000000032001462766011000340750ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/discovery_and_monitoring/errors{ "description": "Pre-4.2 LegacyNotPrimary error", "uri": "mongodb://a/?replicaSet=rs", "phases": [ { "description": "Primary A is discovered", "responses": [ [ "a:27017", { "ok": 1, "helloOk": true, "isWritablePrimary": true, "hosts": [ "a:27017" ], "setName": "rs", "minWireVersion": 0, "maxWireVersion": 7 } ] ], "outcome": { "servers": { "a:27017": { "type": "RSPrimary", "setName": "rs", "topologyVersion": null, "pool": { "generation": 0 } } }, "topologyType": "ReplicaSetWithPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } }, { "description": "Pre-4.2 LegacyNotPrimary error marks server Unknown and clears the pool", "applicationErrors": [ { "address": "a:27017", "when": "afterHandshakeCompletes", "maxWireVersion": 7, "type": "command", "response": { "ok": 0, "errmsg": "LegacyNotPrimary", "code": 10058 } } ], "outcome": { "servers": { "a:27017": { "type": "Unknown", "topologyVersion": null, "pool": { "generation": 1 } } }, "topologyType": "ReplicaSetNoPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } } ] } pre-42-NotPrimaryNoSecondaryOk.json000066400000000000000000000032251462766011000354160ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/discovery_and_monitoring/errors{ "description": "Pre-4.2 NotPrimaryNoSecondaryOk error", "uri": "mongodb://a/?replicaSet=rs", "phases": [ { "description": "Primary A is discovered", "responses": [ [ "a:27017", { "ok": 1, "helloOk": true, "isWritablePrimary": true, "hosts": [ "a:27017" ], "setName": "rs", "minWireVersion": 0, "maxWireVersion": 7 } ] ], "outcome": { "servers": { "a:27017": { "type": "RSPrimary", "setName": "rs", "topologyVersion": null, "pool": { "generation": 0 } } }, "topologyType": "ReplicaSetWithPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } }, { "description": "Pre-4.2 NotPrimaryNoSecondaryOk error marks server Unknown and clears the pool", "applicationErrors": [ { "address": "a:27017", "when": "afterHandshakeCompletes", "maxWireVersion": 7, "type": "command", "response": { "ok": 0, "errmsg": "NotPrimaryNoSecondaryOk", "code": 13435 } } ], "outcome": { "servers": { "a:27017": { "type": "Unknown", "topologyVersion": null, "pool": { "generation": 1 } } }, "topologyType": "ReplicaSetNoPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } } ] } pre-42-NotPrimaryOrSecondary.json000066400000000000000000000032171462766011000351310ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/discovery_and_monitoring/errors{ "description": "Pre-4.2 NotPrimaryOrSecondary error", "uri": "mongodb://a/?replicaSet=rs", "phases": [ { "description": "Primary A is discovered", "responses": [ [ "a:27017", { "ok": 1, "helloOk": true, "isWritablePrimary": true, "hosts": [ "a:27017" ], "setName": "rs", "minWireVersion": 0, "maxWireVersion": 7 } ] ], "outcome": { "servers": { "a:27017": { "type": "RSPrimary", "setName": "rs", "topologyVersion": null, "pool": { "generation": 0 } } }, "topologyType": "ReplicaSetWithPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } }, { "description": "Pre-4.2 NotPrimaryOrSecondary error marks server Unknown and clears the pool", "applicationErrors": [ { "address": "a:27017", "when": "afterHandshakeCompletes", "maxWireVersion": 7, "type": "command", "response": { "ok": 0, "errmsg": "NotPrimaryOrSecondary", "code": 13436 } } ], "outcome": { "servers": { "a:27017": { "type": "Unknown", "topologyVersion": null, "pool": { "generation": 1 } } }, "topologyType": "ReplicaSetNoPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } } ] } pre-42-NotWritablePrimary.json000066400000000000000000000032061462766011000344500ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/discovery_and_monitoring/errors{ "description": "Pre-4.2 NotWritablePrimary error", "uri": "mongodb://a/?replicaSet=rs", "phases": [ { "description": "Primary A is discovered", "responses": [ [ "a:27017", { "ok": 1, "helloOk": true, "isWritablePrimary": true, "hosts": [ "a:27017" ], "setName": "rs", "minWireVersion": 0, "maxWireVersion": 7 } ] ], "outcome": { "servers": { "a:27017": { "type": "RSPrimary", "setName": "rs", "topologyVersion": null, "pool": { "generation": 0 } } }, "topologyType": "ReplicaSetWithPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } }, { "description": "Pre-4.2 NotWritablePrimary error marks server Unknown and clears the pool", "applicationErrors": [ { "address": "a:27017", "when": "afterHandshakeCompletes", "maxWireVersion": 7, "type": "command", "response": { "ok": 0, "errmsg": "NotWritablePrimary", "code": 10107 } } ], "outcome": { "servers": { "a:27017": { "type": "Unknown", "topologyVersion": null, "pool": { "generation": 1 } } }, "topologyType": "ReplicaSetNoPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } } ] } pre-42-PrimarySteppedDown.json000066400000000000000000000032041462766011000344500ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/discovery_and_monitoring/errors{ "description": "Pre-4.2 PrimarySteppedDown error", "uri": "mongodb://a/?replicaSet=rs", "phases": [ { "description": "Primary A is discovered", "responses": [ [ "a:27017", { "ok": 1, "helloOk": true, "isWritablePrimary": true, "hosts": [ "a:27017" ], "setName": "rs", "minWireVersion": 0, "maxWireVersion": 7 } ] ], "outcome": { "servers": { "a:27017": { "type": "RSPrimary", "setName": "rs", "topologyVersion": null, "pool": { "generation": 0 } } }, "topologyType": "ReplicaSetWithPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } }, { "description": "Pre-4.2 PrimarySteppedDown error marks server Unknown and clears the pool", "applicationErrors": [ { "address": "a:27017", "when": "afterHandshakeCompletes", "maxWireVersion": 7, "type": "command", "response": { "ok": 0, "errmsg": "PrimarySteppedDown", "code": 189 } } ], "outcome": { "servers": { "a:27017": { "type": "Unknown", "topologyVersion": null, "pool": { "generation": 1 } } }, "topologyType": "ReplicaSetNoPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } } ] } pre-42-ShutdownInProgress.json000066400000000000000000000032031462766011000344760ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/discovery_and_monitoring/errors{ "description": "Pre-4.2 ShutdownInProgress error", "uri": "mongodb://a/?replicaSet=rs", "phases": [ { "description": "Primary A is discovered", "responses": [ [ "a:27017", { "ok": 1, "helloOk": true, "isWritablePrimary": true, "hosts": [ "a:27017" ], "setName": "rs", "minWireVersion": 0, "maxWireVersion": 7 } ] ], "outcome": { "servers": { "a:27017": { "type": "RSPrimary", "setName": "rs", "topologyVersion": null, "pool": { "generation": 0 } } }, "topologyType": "ReplicaSetWithPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } }, { "description": "Pre-4.2 ShutdownInProgress error marks server Unknown and clears the pool", "applicationErrors": [ { "address": "a:27017", "when": "afterHandshakeCompletes", "maxWireVersion": 7, "type": "command", "response": { "ok": 0, "errmsg": "ShutdownInProgress", "code": 91 } } ], "outcome": { "servers": { "a:27017": { "type": "Unknown", "topologyVersion": null, "pool": { "generation": 1 } } }, "topologyType": "ReplicaSetNoPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } } ] } mongodb-mongo-python-driver-509e9b7/test/discovery_and_monitoring/errors/prefer-error-code.json000066400000000000000000000062731462766011000332530ustar00rootroot00000000000000{ "description": "Do not check errmsg when code exists", "uri": "mongodb://a/?replicaSet=rs", "phases": [ { "description": "Primary A is discovered", "responses": [ [ "a:27017", { "ok": 1, "helloOk": true, "isWritablePrimary": true, "hosts": [ "a:27017" ], "setName": "rs", "minWireVersion": 0, "maxWireVersion": 9, "topologyVersion": { "processId": { "$oid": "000000000000000000000001" }, "counter": { "$numberLong": "1" } } } ] ], "outcome": { "servers": { "a:27017": { "type": "RSPrimary", "setName": "rs", "topologyVersion": { "processId": { "$oid": "000000000000000000000001" }, "counter": { "$numberLong": "1" } }, "pool": { "generation": 0 } } }, "topologyType": "ReplicaSetWithPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } }, { "description": "errmsg \"not master\" gets ignored when error code exists", "applicationErrors": [ { "address": "a:27017", "when": "afterHandshakeCompletes", "maxWireVersion": 9, "type": "command", "response": { "ok": 0, "errmsg": "not master", "code": 1 } } ], "outcome": { "servers": { "a:27017": { "type": "RSPrimary", "setName": "rs", "topologyVersion": { "processId": { "$oid": "000000000000000000000001" }, "counter": { "$numberLong": "1" } }, "pool": { "generation": 0 } } }, "topologyType": "ReplicaSetWithPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } }, { "description": "errmsg \"node is recovering\" gets ignored when error code exists", "applicationErrors": [ { "address": "a:27017", "when": "afterHandshakeCompletes", "maxWireVersion": 9, "type": "command", "response": { "ok": 0, "errmsg": "node is recovering", "code": 1 } } ], "outcome": { "servers": { "a:27017": { "type": "RSPrimary", "setName": "rs", "topologyVersion": { "processId": { "$oid": "000000000000000000000001" }, "counter": { "$numberLong": "1" } }, "pool": { "generation": 0 } } }, "topologyType": "ReplicaSetWithPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } } ] } stale-generation-InterruptedAtShutdown.json000066400000000000000000000103771462766011000374370ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/discovery_and_monitoring/errors{ "description": "Stale generation InterruptedAtShutdown error", "uri": "mongodb://a/?replicaSet=rs", "phases": [ { "description": "Primary A is discovered", "responses": [ [ "a:27017", { "ok": 1, "helloOk": true, "isWritablePrimary": true, "hosts": [ "a:27017" ], "setName": "rs", "minWireVersion": 0, "maxWireVersion": 9, "topologyVersion": { "processId": { "$oid": "000000000000000000000001" }, "counter": { "$numberLong": "1" } } } ] ], "outcome": { "servers": { "a:27017": { "type": "RSPrimary", "setName": "rs", "topologyVersion": { "processId": { "$oid": "000000000000000000000001" }, "counter": { "$numberLong": "1" } }, "pool": { "generation": 0 } } }, "topologyType": "ReplicaSetWithPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } }, { "description": "Non-stale application network error", "applicationErrors": [ { "address": "a:27017", "when": "afterHandshakeCompletes", "maxWireVersion": 9, "type": "network" } ], "outcome": { "servers": { "a:27017": { "type": "Unknown", "topologyVersion": null, "pool": { "generation": 1 } } }, "topologyType": "ReplicaSetNoPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } }, { "description": "Primary A is rediscovered", "responses": [ [ "a:27017", { "ok": 1, "helloOk": true, "isWritablePrimary": true, "hosts": [ "a:27017" ], "setName": "rs", "minWireVersion": 0, "maxWireVersion": 9, "topologyVersion": { "processId": { "$oid": "000000000000000000000001" }, "counter": { "$numberLong": "1" } } } ] ], "outcome": { "servers": { "a:27017": { "type": "RSPrimary", "setName": "rs", "topologyVersion": { "processId": { "$oid": "000000000000000000000001" }, "counter": { "$numberLong": "1" } }, "pool": { "generation": 1 } } }, "topologyType": "ReplicaSetWithPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } }, { "description": "Ignore stale InterruptedAtShutdown error (stale generation)", "applicationErrors": [ { "address": "a:27017", "generation": 0, "when": "afterHandshakeCompletes", "maxWireVersion": 9, "type": "command", "response": { "ok": 0, "errmsg": "InterruptedAtShutdown", "code": 11600, "topologyVersion": { "processId": { "$oid": "000000000000000000000001" }, "counter": { "$numberLong": "2" } } } } ], "outcome": { "servers": { "a:27017": { "type": "RSPrimary", "setName": "rs", "topologyVersion": { "processId": { "$oid": "000000000000000000000001" }, "counter": { "$numberLong": "1" } }, "pool": { "generation": 1 } } }, "topologyType": "ReplicaSetWithPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } } ] } stale-generation-InterruptedDueToReplStateChange.json000066400000000000000000000104351462766011000413040ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/discovery_and_monitoring/errors{ "description": "Stale generation InterruptedDueToReplStateChange error", "uri": "mongodb://a/?replicaSet=rs", "phases": [ { "description": "Primary A is discovered", "responses": [ [ "a:27017", { "ok": 1, "helloOk": true, "isWritablePrimary": true, "hosts": [ "a:27017" ], "setName": "rs", "minWireVersion": 0, "maxWireVersion": 9, "topologyVersion": { "processId": { "$oid": "000000000000000000000001" }, "counter": { "$numberLong": "1" } } } ] ], "outcome": { "servers": { "a:27017": { "type": "RSPrimary", "setName": "rs", "topologyVersion": { "processId": { "$oid": "000000000000000000000001" }, "counter": { "$numberLong": "1" } }, "pool": { "generation": 0 } } }, "topologyType": "ReplicaSetWithPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } }, { "description": "Non-stale application network error", "applicationErrors": [ { "address": "a:27017", "when": "afterHandshakeCompletes", "maxWireVersion": 9, "type": "network" } ], "outcome": { "servers": { "a:27017": { "type": "Unknown", "topologyVersion": null, "pool": { "generation": 1 } } }, "topologyType": "ReplicaSetNoPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } }, { "description": "Primary A is rediscovered", "responses": [ [ "a:27017", { "ok": 1, "helloOk": true, "isWritablePrimary": true, "hosts": [ "a:27017" ], "setName": "rs", "minWireVersion": 0, "maxWireVersion": 9, "topologyVersion": { "processId": { "$oid": "000000000000000000000001" }, "counter": { "$numberLong": "1" } } } ] ], "outcome": { "servers": { "a:27017": { "type": "RSPrimary", "setName": "rs", "topologyVersion": { "processId": { "$oid": "000000000000000000000001" }, "counter": { "$numberLong": "1" } }, "pool": { "generation": 1 } } }, "topologyType": "ReplicaSetWithPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } }, { "description": "Ignore stale InterruptedDueToReplStateChange error (stale generation)", "applicationErrors": [ { "address": "a:27017", "generation": 0, "when": "afterHandshakeCompletes", "maxWireVersion": 9, "type": "command", "response": { "ok": 0, "errmsg": "InterruptedDueToReplStateChange", "code": 11602, "topologyVersion": { "processId": { "$oid": "000000000000000000000001" }, "counter": { "$numberLong": "2" } } } } ], "outcome": { "servers": { "a:27017": { "type": "RSPrimary", "setName": "rs", "topologyVersion": { "processId": { "$oid": "000000000000000000000001" }, "counter": { "$numberLong": "1" } }, "pool": { "generation": 1 } } }, "topologyType": "ReplicaSetWithPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } } ] } stale-generation-NotPrimaryNoSecondaryOk.json000066400000000000000000000104051462766011000376440ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/discovery_and_monitoring/errors{ "description": "Stale generation NotPrimaryNoSecondaryOk error", "uri": "mongodb://a/?replicaSet=rs", "phases": [ { "description": "Primary A is discovered", "responses": [ [ "a:27017", { "ok": 1, "helloOk": true, "isWritablePrimary": true, "hosts": [ "a:27017" ], "setName": "rs", "minWireVersion": 0, "maxWireVersion": 9, "topologyVersion": { "processId": { "$oid": "000000000000000000000001" }, "counter": { "$numberLong": "1" } } } ] ], "outcome": { "servers": { "a:27017": { "type": "RSPrimary", "setName": "rs", "topologyVersion": { "processId": { "$oid": "000000000000000000000001" }, "counter": { "$numberLong": "1" } }, "pool": { "generation": 0 } } }, "topologyType": "ReplicaSetWithPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } }, { "description": "Non-stale application network error", "applicationErrors": [ { "address": "a:27017", "when": "afterHandshakeCompletes", "maxWireVersion": 9, "type": "network" } ], "outcome": { "servers": { "a:27017": { "type": "Unknown", "topologyVersion": null, "pool": { "generation": 1 } } }, "topologyType": "ReplicaSetNoPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } }, { "description": "Primary A is rediscovered", "responses": [ [ "a:27017", { "ok": 1, "helloOk": true, "isWritablePrimary": true, "hosts": [ "a:27017" ], "setName": "rs", "minWireVersion": 0, "maxWireVersion": 9, "topologyVersion": { "processId": { "$oid": "000000000000000000000001" }, "counter": { "$numberLong": "1" } } } ] ], "outcome": { "servers": { "a:27017": { "type": "RSPrimary", "setName": "rs", "topologyVersion": { "processId": { "$oid": "000000000000000000000001" }, "counter": { "$numberLong": "1" } }, "pool": { "generation": 1 } } }, "topologyType": "ReplicaSetWithPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } }, { "description": "Ignore stale NotPrimaryNoSecondaryOk error (stale generation)", "applicationErrors": [ { "address": "a:27017", "generation": 0, "when": "afterHandshakeCompletes", "maxWireVersion": 9, "type": "command", "response": { "ok": 0, "errmsg": "NotPrimaryNoSecondaryOk", "code": 13435, "topologyVersion": { "processId": { "$oid": "000000000000000000000001" }, "counter": { "$numberLong": "2" } } } } ], "outcome": { "servers": { "a:27017": { "type": "RSPrimary", "setName": "rs", "topologyVersion": { "processId": { "$oid": "000000000000000000000001" }, "counter": { "$numberLong": "1" } }, "pool": { "generation": 1 } } }, "topologyType": "ReplicaSetWithPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } } ] } stale-generation-NotPrimaryOrSecondary.json000066400000000000000000000103771462766011000373660ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/discovery_and_monitoring/errors{ "description": "Stale generation NotPrimaryOrSecondary error", "uri": "mongodb://a/?replicaSet=rs", "phases": [ { "description": "Primary A is discovered", "responses": [ [ "a:27017", { "ok": 1, "helloOk": true, "isWritablePrimary": true, "hosts": [ "a:27017" ], "setName": "rs", "minWireVersion": 0, "maxWireVersion": 9, "topologyVersion": { "processId": { "$oid": "000000000000000000000001" }, "counter": { "$numberLong": "1" } } } ] ], "outcome": { "servers": { "a:27017": { "type": "RSPrimary", "setName": "rs", "topologyVersion": { "processId": { "$oid": "000000000000000000000001" }, "counter": { "$numberLong": "1" } }, "pool": { "generation": 0 } } }, "topologyType": "ReplicaSetWithPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } }, { "description": "Non-stale application network error", "applicationErrors": [ { "address": "a:27017", "when": "afterHandshakeCompletes", "maxWireVersion": 9, "type": "network" } ], "outcome": { "servers": { "a:27017": { "type": "Unknown", "topologyVersion": null, "pool": { "generation": 1 } } }, "topologyType": "ReplicaSetNoPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } }, { "description": "Primary A is rediscovered", "responses": [ [ "a:27017", { "ok": 1, "helloOk": true, "isWritablePrimary": true, "hosts": [ "a:27017" ], "setName": "rs", "minWireVersion": 0, "maxWireVersion": 9, "topologyVersion": { "processId": { "$oid": "000000000000000000000001" }, "counter": { "$numberLong": "1" } } } ] ], "outcome": { "servers": { "a:27017": { "type": "RSPrimary", "setName": "rs", "topologyVersion": { "processId": { "$oid": "000000000000000000000001" }, "counter": { "$numberLong": "1" } }, "pool": { "generation": 1 } } }, "topologyType": "ReplicaSetWithPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } }, { "description": "Ignore stale NotPrimaryOrSecondary error (stale generation)", "applicationErrors": [ { "address": "a:27017", "generation": 0, "when": "afterHandshakeCompletes", "maxWireVersion": 9, "type": "command", "response": { "ok": 0, "errmsg": "NotPrimaryOrSecondary", "code": 13436, "topologyVersion": { "processId": { "$oid": "000000000000000000000001" }, "counter": { "$numberLong": "2" } } } } ], "outcome": { "servers": { "a:27017": { "type": "RSPrimary", "setName": "rs", "topologyVersion": { "processId": { "$oid": "000000000000000000000001" }, "counter": { "$numberLong": "1" } }, "pool": { "generation": 1 } } }, "topologyType": "ReplicaSetWithPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } } ] } stale-generation-NotWritablePrimary.json000066400000000000000000000103661462766011000367050ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/discovery_and_monitoring/errors{ "description": "Stale generation NotWritablePrimary error", "uri": "mongodb://a/?replicaSet=rs", "phases": [ { "description": "Primary A is discovered", "responses": [ [ "a:27017", { "ok": 1, "helloOk": true, "isWritablePrimary": true, "hosts": [ "a:27017" ], "setName": "rs", "minWireVersion": 0, "maxWireVersion": 9, "topologyVersion": { "processId": { "$oid": "000000000000000000000001" }, "counter": { "$numberLong": "1" } } } ] ], "outcome": { "servers": { "a:27017": { "type": "RSPrimary", "setName": "rs", "topologyVersion": { "processId": { "$oid": "000000000000000000000001" }, "counter": { "$numberLong": "1" } }, "pool": { "generation": 0 } } }, "topologyType": "ReplicaSetWithPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } }, { "description": "Non-stale application network error", "applicationErrors": [ { "address": "a:27017", "when": "afterHandshakeCompletes", "maxWireVersion": 9, "type": "network" } ], "outcome": { "servers": { "a:27017": { "type": "Unknown", "topologyVersion": null, "pool": { "generation": 1 } } }, "topologyType": "ReplicaSetNoPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } }, { "description": "Primary A is rediscovered", "responses": [ [ "a:27017", { "ok": 1, "helloOk": true, "isWritablePrimary": true, "hosts": [ "a:27017" ], "setName": "rs", "minWireVersion": 0, "maxWireVersion": 9, "topologyVersion": { "processId": { "$oid": "000000000000000000000001" }, "counter": { "$numberLong": "1" } } } ] ], "outcome": { "servers": { "a:27017": { "type": "RSPrimary", "setName": "rs", "topologyVersion": { "processId": { "$oid": "000000000000000000000001" }, "counter": { "$numberLong": "1" } }, "pool": { "generation": 1 } } }, "topologyType": "ReplicaSetWithPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } }, { "description": "Ignore stale NotWritablePrimary error (stale generation)", "applicationErrors": [ { "address": "a:27017", "generation": 0, "when": "afterHandshakeCompletes", "maxWireVersion": 9, "type": "command", "response": { "ok": 0, "errmsg": "NotWritablePrimary", "code": 10107, "topologyVersion": { "processId": { "$oid": "000000000000000000000001" }, "counter": { "$numberLong": "2" } } } } ], "outcome": { "servers": { "a:27017": { "type": "RSPrimary", "setName": "rs", "topologyVersion": { "processId": { "$oid": "000000000000000000000001" }, "counter": { "$numberLong": "1" } }, "pool": { "generation": 1 } } }, "topologyType": "ReplicaSetWithPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } } ] } stale-generation-PrimarySteppedDown.json000066400000000000000000000103641462766011000367050ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/discovery_and_monitoring/errors{ "description": "Stale generation PrimarySteppedDown error", "uri": "mongodb://a/?replicaSet=rs", "phases": [ { "description": "Primary A is discovered", "responses": [ [ "a:27017", { "ok": 1, "helloOk": true, "isWritablePrimary": true, "hosts": [ "a:27017" ], "setName": "rs", "minWireVersion": 0, "maxWireVersion": 9, "topologyVersion": { "processId": { "$oid": "000000000000000000000001" }, "counter": { "$numberLong": "1" } } } ] ], "outcome": { "servers": { "a:27017": { "type": "RSPrimary", "setName": "rs", "topologyVersion": { "processId": { "$oid": "000000000000000000000001" }, "counter": { "$numberLong": "1" } }, "pool": { "generation": 0 } } }, "topologyType": "ReplicaSetWithPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } }, { "description": "Non-stale application network error", "applicationErrors": [ { "address": "a:27017", "when": "afterHandshakeCompletes", "maxWireVersion": 9, "type": "network" } ], "outcome": { "servers": { "a:27017": { "type": "Unknown", "topologyVersion": null, "pool": { "generation": 1 } } }, "topologyType": "ReplicaSetNoPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } }, { "description": "Primary A is rediscovered", "responses": [ [ "a:27017", { "ok": 1, "helloOk": true, "isWritablePrimary": true, "hosts": [ "a:27017" ], "setName": "rs", "minWireVersion": 0, "maxWireVersion": 9, "topologyVersion": { "processId": { "$oid": "000000000000000000000001" }, "counter": { "$numberLong": "1" } } } ] ], "outcome": { "servers": { "a:27017": { "type": "RSPrimary", "setName": "rs", "topologyVersion": { "processId": { "$oid": "000000000000000000000001" }, "counter": { "$numberLong": "1" } }, "pool": { "generation": 1 } } }, "topologyType": "ReplicaSetWithPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } }, { "description": "Ignore stale PrimarySteppedDown error (stale generation)", "applicationErrors": [ { "address": "a:27017", "generation": 0, "when": "afterHandshakeCompletes", "maxWireVersion": 9, "type": "command", "response": { "ok": 0, "errmsg": "PrimarySteppedDown", "code": 189, "topologyVersion": { "processId": { "$oid": "000000000000000000000001" }, "counter": { "$numberLong": "2" } } } } ], "outcome": { "servers": { "a:27017": { "type": "RSPrimary", "setName": "rs", "topologyVersion": { "processId": { "$oid": "000000000000000000000001" }, "counter": { "$numberLong": "1" } }, "pool": { "generation": 1 } } }, "topologyType": "ReplicaSetWithPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } } ] } stale-generation-ShutdownInProgress.json000066400000000000000000000103631462766011000367330ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/discovery_and_monitoring/errors{ "description": "Stale generation ShutdownInProgress error", "uri": "mongodb://a/?replicaSet=rs", "phases": [ { "description": "Primary A is discovered", "responses": [ [ "a:27017", { "ok": 1, "helloOk": true, "isWritablePrimary": true, "hosts": [ "a:27017" ], "setName": "rs", "minWireVersion": 0, "maxWireVersion": 9, "topologyVersion": { "processId": { "$oid": "000000000000000000000001" }, "counter": { "$numberLong": "1" } } } ] ], "outcome": { "servers": { "a:27017": { "type": "RSPrimary", "setName": "rs", "topologyVersion": { "processId": { "$oid": "000000000000000000000001" }, "counter": { "$numberLong": "1" } }, "pool": { "generation": 0 } } }, "topologyType": "ReplicaSetWithPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } }, { "description": "Non-stale application network error", "applicationErrors": [ { "address": "a:27017", "when": "afterHandshakeCompletes", "maxWireVersion": 9, "type": "network" } ], "outcome": { "servers": { "a:27017": { "type": "Unknown", "topologyVersion": null, "pool": { "generation": 1 } } }, "topologyType": "ReplicaSetNoPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } }, { "description": "Primary A is rediscovered", "responses": [ [ "a:27017", { "ok": 1, "helloOk": true, "isWritablePrimary": true, "hosts": [ "a:27017" ], "setName": "rs", "minWireVersion": 0, "maxWireVersion": 9, "topologyVersion": { "processId": { "$oid": "000000000000000000000001" }, "counter": { "$numberLong": "1" } } } ] ], "outcome": { "servers": { "a:27017": { "type": "RSPrimary", "setName": "rs", "topologyVersion": { "processId": { "$oid": "000000000000000000000001" }, "counter": { "$numberLong": "1" } }, "pool": { "generation": 1 } } }, "topologyType": "ReplicaSetWithPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } }, { "description": "Ignore stale ShutdownInProgress error (stale generation)", "applicationErrors": [ { "address": "a:27017", "generation": 0, "when": "afterHandshakeCompletes", "maxWireVersion": 9, "type": "command", "response": { "ok": 0, "errmsg": "ShutdownInProgress", "code": 91, "topologyVersion": { "processId": { "$oid": "000000000000000000000001" }, "counter": { "$numberLong": "2" } } } } ], "outcome": { "servers": { "a:27017": { "type": "RSPrimary", "setName": "rs", "topologyVersion": { "processId": { "$oid": "000000000000000000000001" }, "counter": { "$numberLong": "1" } }, "pool": { "generation": 1 } } }, "topologyType": "ReplicaSetWithPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } } ] } stale-generation-afterHandshakeCompletes-InterruptedAtShutdown.json000066400000000000000000000104271462766011000442150ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/discovery_and_monitoring/errors{ "description": "Stale generation InterruptedAtShutdown error afterHandshakeCompletes", "uri": "mongodb://a/?replicaSet=rs", "phases": [ { "description": "Primary A is discovered", "responses": [ [ "a:27017", { "ok": 1, "helloOk": true, "isWritablePrimary": true, "hosts": [ "a:27017" ], "setName": "rs", "minWireVersion": 0, "maxWireVersion": 9, "topologyVersion": { "processId": { "$oid": "000000000000000000000001" }, "counter": { "$numberLong": "1" } } } ] ], "outcome": { "servers": { "a:27017": { "type": "RSPrimary", "setName": "rs", "topologyVersion": { "processId": { "$oid": "000000000000000000000001" }, "counter": { "$numberLong": "1" } }, "pool": { "generation": 0 } } }, "topologyType": "ReplicaSetWithPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } }, { "description": "Non-stale application network error", "applicationErrors": [ { "address": "a:27017", "when": "afterHandshakeCompletes", "maxWireVersion": 9, "type": "network" } ], "outcome": { "servers": { "a:27017": { "type": "Unknown", "topologyVersion": null, "pool": { "generation": 1 } } }, "topologyType": "ReplicaSetNoPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } }, { "description": "Primary A is rediscovered", "responses": [ [ "a:27017", { "ok": 1, "helloOk": true, "isWritablePrimary": true, "hosts": [ "a:27017" ], "setName": "rs", "minWireVersion": 0, "maxWireVersion": 9, "topologyVersion": { "processId": { "$oid": "000000000000000000000001" }, "counter": { "$numberLong": "1" } } } ] ], "outcome": { "servers": { "a:27017": { "type": "RSPrimary", "setName": "rs", "topologyVersion": { "processId": { "$oid": "000000000000000000000001" }, "counter": { "$numberLong": "1" } }, "pool": { "generation": 1 } } }, "topologyType": "ReplicaSetWithPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } }, { "description": "Ignore stale InterruptedAtShutdown error (stale generation)", "applicationErrors": [ { "address": "a:27017", "generation": 0, "when": "afterHandshakeCompletes", "maxWireVersion": 9, "type": "command", "response": { "ok": 0, "errmsg": "InterruptedAtShutdown", "code": 11600, "topologyVersion": { "processId": { "$oid": "000000000000000000000001" }, "counter": { "$numberLong": "2" } } } } ], "outcome": { "servers": { "a:27017": { "type": "RSPrimary", "setName": "rs", "topologyVersion": { "processId": { "$oid": "000000000000000000000001" }, "counter": { "$numberLong": "1" } }, "pool": { "generation": 1 } } }, "topologyType": "ReplicaSetWithPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } } ] } stale-generation-afterHandshakeCompletes-InterruptedDueToReplStateChange.json000066400000000000000000000104651462766011000460710ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/discovery_and_monitoring/errors{ "description": "Stale generation InterruptedDueToReplStateChange error afterHandshakeCompletes", "uri": "mongodb://a/?replicaSet=rs", "phases": [ { "description": "Primary A is discovered", "responses": [ [ "a:27017", { "ok": 1, "helloOk": true, "isWritablePrimary": true, "hosts": [ "a:27017" ], "setName": "rs", "minWireVersion": 0, "maxWireVersion": 9, "topologyVersion": { "processId": { "$oid": "000000000000000000000001" }, "counter": { "$numberLong": "1" } } } ] ], "outcome": { "servers": { "a:27017": { "type": "RSPrimary", "setName": "rs", "topologyVersion": { "processId": { "$oid": "000000000000000000000001" }, "counter": { "$numberLong": "1" } }, "pool": { "generation": 0 } } }, "topologyType": "ReplicaSetWithPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } }, { "description": "Non-stale application network error", "applicationErrors": [ { "address": "a:27017", "when": "afterHandshakeCompletes", "maxWireVersion": 9, "type": "network" } ], "outcome": { "servers": { "a:27017": { "type": "Unknown", "topologyVersion": null, "pool": { "generation": 1 } } }, "topologyType": "ReplicaSetNoPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } }, { "description": "Primary A is rediscovered", "responses": [ [ "a:27017", { "ok": 1, "helloOk": true, "isWritablePrimary": true, "hosts": [ "a:27017" ], "setName": "rs", "minWireVersion": 0, "maxWireVersion": 9, "topologyVersion": { "processId": { "$oid": "000000000000000000000001" }, "counter": { "$numberLong": "1" } } } ] ], "outcome": { "servers": { "a:27017": { "type": "RSPrimary", "setName": "rs", "topologyVersion": { "processId": { "$oid": "000000000000000000000001" }, "counter": { "$numberLong": "1" } }, "pool": { "generation": 1 } } }, "topologyType": "ReplicaSetWithPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } }, { "description": "Ignore stale InterruptedDueToReplStateChange error (stale generation)", "applicationErrors": [ { "address": "a:27017", "generation": 0, "when": "afterHandshakeCompletes", "maxWireVersion": 9, "type": "command", "response": { "ok": 0, "errmsg": "InterruptedDueToReplStateChange", "code": 11602, "topologyVersion": { "processId": { "$oid": "000000000000000000000001" }, "counter": { "$numberLong": "2" } } } } ], "outcome": { "servers": { "a:27017": { "type": "RSPrimary", "setName": "rs", "topologyVersion": { "processId": { "$oid": "000000000000000000000001" }, "counter": { "$numberLong": "1" } }, "pool": { "generation": 1 } } }, "topologyType": "ReplicaSetWithPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } } ] } stale-generation-afterHandshakeCompletes-LegacyNotPrimary.json000066400000000000000000000104101462766011000431100ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/discovery_and_monitoring/errors{ "description": "Stale generation LegacyNotPrimary error afterHandshakeCompletes", "uri": "mongodb://a/?replicaSet=rs", "phases": [ { "description": "Primary A is discovered", "responses": [ [ "a:27017", { "ok": 1, "helloOk": true, "isWritablePrimary": true, "hosts": [ "a:27017" ], "setName": "rs", "minWireVersion": 0, "maxWireVersion": 9, "topologyVersion": { "processId": { "$oid": "000000000000000000000001" }, "counter": { "$numberLong": "1" } } } ] ], "outcome": { "servers": { "a:27017": { "type": "RSPrimary", "setName": "rs", "topologyVersion": { "processId": { "$oid": "000000000000000000000001" }, "counter": { "$numberLong": "1" } }, "pool": { "generation": 0 } } }, "topologyType": "ReplicaSetWithPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } }, { "description": "Non-stale application network error", "applicationErrors": [ { "address": "a:27017", "when": "afterHandshakeCompletes", "maxWireVersion": 9, "type": "network" } ], "outcome": { "servers": { "a:27017": { "type": "Unknown", "topologyVersion": null, "pool": { "generation": 1 } } }, "topologyType": "ReplicaSetNoPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } }, { "description": "Primary A is rediscovered", "responses": [ [ "a:27017", { "ok": 1, "helloOk": true, "isWritablePrimary": true, "hosts": [ "a:27017" ], "setName": "rs", "minWireVersion": 0, "maxWireVersion": 9, "topologyVersion": { "processId": { "$oid": "000000000000000000000001" }, "counter": { "$numberLong": "1" } } } ] ], "outcome": { "servers": { "a:27017": { "type": "RSPrimary", "setName": "rs", "topologyVersion": { "processId": { "$oid": "000000000000000000000001" }, "counter": { "$numberLong": "1" } }, "pool": { "generation": 1 } } }, "topologyType": "ReplicaSetWithPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } }, { "description": "Ignore stale LegacyNotPrimary error (stale generation)", "applicationErrors": [ { "address": "a:27017", "generation": 0, "when": "afterHandshakeCompletes", "maxWireVersion": 9, "type": "command", "response": { "ok": 0, "errmsg": "LegacyNotPrimary", "code": 10058, "topologyVersion": { "processId": { "$oid": "000000000000000000000001" }, "counter": { "$numberLong": "2" } } } } ], "outcome": { "servers": { "a:27017": { "type": "RSPrimary", "setName": "rs", "topologyVersion": { "processId": { "$oid": "000000000000000000000001" }, "counter": { "$numberLong": "1" } }, "pool": { "generation": 1 } } }, "topologyType": "ReplicaSetWithPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } } ] } stale-generation-afterHandshakeCompletes-NotPrimaryNoSecondaryOk.json000066400000000000000000000104351462766011000444310ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/discovery_and_monitoring/errors{ "description": "Stale generation NotPrimaryNoSecondaryOk error afterHandshakeCompletes", "uri": "mongodb://a/?replicaSet=rs", "phases": [ { "description": "Primary A is discovered", "responses": [ [ "a:27017", { "ok": 1, "helloOk": true, "isWritablePrimary": true, "hosts": [ "a:27017" ], "setName": "rs", "minWireVersion": 0, "maxWireVersion": 9, "topologyVersion": { "processId": { "$oid": "000000000000000000000001" }, "counter": { "$numberLong": "1" } } } ] ], "outcome": { "servers": { "a:27017": { "type": "RSPrimary", "setName": "rs", "topologyVersion": { "processId": { "$oid": "000000000000000000000001" }, "counter": { "$numberLong": "1" } }, "pool": { "generation": 0 } } }, "topologyType": "ReplicaSetWithPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } }, { "description": "Non-stale application network error", "applicationErrors": [ { "address": "a:27017", "when": "afterHandshakeCompletes", "maxWireVersion": 9, "type": "network" } ], "outcome": { "servers": { "a:27017": { "type": "Unknown", "topologyVersion": null, "pool": { "generation": 1 } } }, "topologyType": "ReplicaSetNoPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } }, { "description": "Primary A is rediscovered", "responses": [ [ "a:27017", { "ok": 1, "helloOk": true, "isWritablePrimary": true, "hosts": [ "a:27017" ], "setName": "rs", "minWireVersion": 0, "maxWireVersion": 9, "topologyVersion": { "processId": { "$oid": "000000000000000000000001" }, "counter": { "$numberLong": "1" } } } ] ], "outcome": { "servers": { "a:27017": { "type": "RSPrimary", "setName": "rs", "topologyVersion": { "processId": { "$oid": "000000000000000000000001" }, "counter": { "$numberLong": "1" } }, "pool": { "generation": 1 } } }, "topologyType": "ReplicaSetWithPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } }, { "description": "Ignore stale NotPrimaryNoSecondaryOk error (stale generation)", "applicationErrors": [ { "address": "a:27017", "generation": 0, "when": "afterHandshakeCompletes", "maxWireVersion": 9, "type": "command", "response": { "ok": 0, "errmsg": "NotPrimaryNoSecondaryOk", "code": 13435, "topologyVersion": { "processId": { "$oid": "000000000000000000000001" }, "counter": { "$numberLong": "2" } } } } ], "outcome": { "servers": { "a:27017": { "type": "RSPrimary", "setName": "rs", "topologyVersion": { "processId": { "$oid": "000000000000000000000001" }, "counter": { "$numberLong": "1" } }, "pool": { "generation": 1 } } }, "topologyType": "ReplicaSetWithPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } } ] } stale-generation-afterHandshakeCompletes-NotPrimaryOrSecondary.json000066400000000000000000000104271462766011000441440ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/discovery_and_monitoring/errors{ "description": "Stale generation NotPrimaryOrSecondary error afterHandshakeCompletes", "uri": "mongodb://a/?replicaSet=rs", "phases": [ { "description": "Primary A is discovered", "responses": [ [ "a:27017", { "ok": 1, "helloOk": true, "isWritablePrimary": true, "hosts": [ "a:27017" ], "setName": "rs", "minWireVersion": 0, "maxWireVersion": 9, "topologyVersion": { "processId": { "$oid": "000000000000000000000001" }, "counter": { "$numberLong": "1" } } } ] ], "outcome": { "servers": { "a:27017": { "type": "RSPrimary", "setName": "rs", "topologyVersion": { "processId": { "$oid": "000000000000000000000001" }, "counter": { "$numberLong": "1" } }, "pool": { "generation": 0 } } }, "topologyType": "ReplicaSetWithPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } }, { "description": "Non-stale application network error", "applicationErrors": [ { "address": "a:27017", "when": "afterHandshakeCompletes", "maxWireVersion": 9, "type": "network" } ], "outcome": { "servers": { "a:27017": { "type": "Unknown", "topologyVersion": null, "pool": { "generation": 1 } } }, "topologyType": "ReplicaSetNoPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } }, { "description": "Primary A is rediscovered", "responses": [ [ "a:27017", { "ok": 1, "helloOk": true, "isWritablePrimary": true, "hosts": [ "a:27017" ], "setName": "rs", "minWireVersion": 0, "maxWireVersion": 9, "topologyVersion": { "processId": { "$oid": "000000000000000000000001" }, "counter": { "$numberLong": "1" } } } ] ], "outcome": { "servers": { "a:27017": { "type": "RSPrimary", "setName": "rs", "topologyVersion": { "processId": { "$oid": "000000000000000000000001" }, "counter": { "$numberLong": "1" } }, "pool": { "generation": 1 } } }, "topologyType": "ReplicaSetWithPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } }, { "description": "Ignore stale NotPrimaryOrSecondary error (stale generation)", "applicationErrors": [ { "address": "a:27017", "generation": 0, "when": "afterHandshakeCompletes", "maxWireVersion": 9, "type": "command", "response": { "ok": 0, "errmsg": "NotPrimaryOrSecondary", "code": 13436, "topologyVersion": { "processId": { "$oid": "000000000000000000000001" }, "counter": { "$numberLong": "2" } } } } ], "outcome": { "servers": { "a:27017": { "type": "RSPrimary", "setName": "rs", "topologyVersion": { "processId": { "$oid": "000000000000000000000001" }, "counter": { "$numberLong": "1" } }, "pool": { "generation": 1 } } }, "topologyType": "ReplicaSetWithPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } } ] } stale-generation-afterHandshakeCompletes-NotWritablePrimary.json000066400000000000000000000104161462766011000434630ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/discovery_and_monitoring/errors{ "description": "Stale generation NotWritablePrimary error afterHandshakeCompletes", "uri": "mongodb://a/?replicaSet=rs", "phases": [ { "description": "Primary A is discovered", "responses": [ [ "a:27017", { "ok": 1, "helloOk": true, "isWritablePrimary": true, "hosts": [ "a:27017" ], "setName": "rs", "minWireVersion": 0, "maxWireVersion": 9, "topologyVersion": { "processId": { "$oid": "000000000000000000000001" }, "counter": { "$numberLong": "1" } } } ] ], "outcome": { "servers": { "a:27017": { "type": "RSPrimary", "setName": "rs", "topologyVersion": { "processId": { "$oid": "000000000000000000000001" }, "counter": { "$numberLong": "1" } }, "pool": { "generation": 0 } } }, "topologyType": "ReplicaSetWithPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } }, { "description": "Non-stale application network error", "applicationErrors": [ { "address": "a:27017", "when": "afterHandshakeCompletes", "maxWireVersion": 9, "type": "network" } ], "outcome": { "servers": { "a:27017": { "type": "Unknown", "topologyVersion": null, "pool": { "generation": 1 } } }, "topologyType": "ReplicaSetNoPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } }, { "description": "Primary A is rediscovered", "responses": [ [ "a:27017", { "ok": 1, "helloOk": true, "isWritablePrimary": true, "hosts": [ "a:27017" ], "setName": "rs", "minWireVersion": 0, "maxWireVersion": 9, "topologyVersion": { "processId": { "$oid": "000000000000000000000001" }, "counter": { "$numberLong": "1" } } } ] ], "outcome": { "servers": { "a:27017": { "type": "RSPrimary", "setName": "rs", "topologyVersion": { "processId": { "$oid": "000000000000000000000001" }, "counter": { "$numberLong": "1" } }, "pool": { "generation": 1 } } }, "topologyType": "ReplicaSetWithPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } }, { "description": "Ignore stale NotWritablePrimary error (stale generation)", "applicationErrors": [ { "address": "a:27017", "generation": 0, "when": "afterHandshakeCompletes", "maxWireVersion": 9, "type": "command", "response": { "ok": 0, "errmsg": "NotWritablePrimary", "code": 10107, "topologyVersion": { "processId": { "$oid": "000000000000000000000001" }, "counter": { "$numberLong": "2" } } } } ], "outcome": { "servers": { "a:27017": { "type": "RSPrimary", "setName": "rs", "topologyVersion": { "processId": { "$oid": "000000000000000000000001" }, "counter": { "$numberLong": "1" } }, "pool": { "generation": 1 } } }, "topologyType": "ReplicaSetWithPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } } ] } stale-generation-afterHandshakeCompletes-PrimarySteppedDown.json000066400000000000000000000104141462766011000434630ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/discovery_and_monitoring/errors{ "description": "Stale generation PrimarySteppedDown error afterHandshakeCompletes", "uri": "mongodb://a/?replicaSet=rs", "phases": [ { "description": "Primary A is discovered", "responses": [ [ "a:27017", { "ok": 1, "helloOk": true, "isWritablePrimary": true, "hosts": [ "a:27017" ], "setName": "rs", "minWireVersion": 0, "maxWireVersion": 9, "topologyVersion": { "processId": { "$oid": "000000000000000000000001" }, "counter": { "$numberLong": "1" } } } ] ], "outcome": { "servers": { "a:27017": { "type": "RSPrimary", "setName": "rs", "topologyVersion": { "processId": { "$oid": "000000000000000000000001" }, "counter": { "$numberLong": "1" } }, "pool": { "generation": 0 } } }, "topologyType": "ReplicaSetWithPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } }, { "description": "Non-stale application network error", "applicationErrors": [ { "address": "a:27017", "when": "afterHandshakeCompletes", "maxWireVersion": 9, "type": "network" } ], "outcome": { "servers": { "a:27017": { "type": "Unknown", "topologyVersion": null, "pool": { "generation": 1 } } }, "topologyType": "ReplicaSetNoPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } }, { "description": "Primary A is rediscovered", "responses": [ [ "a:27017", { "ok": 1, "helloOk": true, "isWritablePrimary": true, "hosts": [ "a:27017" ], "setName": "rs", "minWireVersion": 0, "maxWireVersion": 9, "topologyVersion": { "processId": { "$oid": "000000000000000000000001" }, "counter": { "$numberLong": "1" } } } ] ], "outcome": { "servers": { "a:27017": { "type": "RSPrimary", "setName": "rs", "topologyVersion": { "processId": { "$oid": "000000000000000000000001" }, "counter": { "$numberLong": "1" } }, "pool": { "generation": 1 } } }, "topologyType": "ReplicaSetWithPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } }, { "description": "Ignore stale PrimarySteppedDown error (stale generation)", "applicationErrors": [ { "address": "a:27017", "generation": 0, "when": "afterHandshakeCompletes", "maxWireVersion": 9, "type": "command", "response": { "ok": 0, "errmsg": "PrimarySteppedDown", "code": 189, "topologyVersion": { "processId": { "$oid": "000000000000000000000001" }, "counter": { "$numberLong": "2" } } } } ], "outcome": { "servers": { "a:27017": { "type": "RSPrimary", "setName": "rs", "topologyVersion": { "processId": { "$oid": "000000000000000000000001" }, "counter": { "$numberLong": "1" } }, "pool": { "generation": 1 } } }, "topologyType": "ReplicaSetWithPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } } ] } stale-generation-afterHandshakeCompletes-ShutdownInProgress.json000066400000000000000000000104131462766011000435110ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/discovery_and_monitoring/errors{ "description": "Stale generation ShutdownInProgress error afterHandshakeCompletes", "uri": "mongodb://a/?replicaSet=rs", "phases": [ { "description": "Primary A is discovered", "responses": [ [ "a:27017", { "ok": 1, "helloOk": true, "isWritablePrimary": true, "hosts": [ "a:27017" ], "setName": "rs", "minWireVersion": 0, "maxWireVersion": 9, "topologyVersion": { "processId": { "$oid": "000000000000000000000001" }, "counter": { "$numberLong": "1" } } } ] ], "outcome": { "servers": { "a:27017": { "type": "RSPrimary", "setName": "rs", "topologyVersion": { "processId": { "$oid": "000000000000000000000001" }, "counter": { "$numberLong": "1" } }, "pool": { "generation": 0 } } }, "topologyType": "ReplicaSetWithPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } }, { "description": "Non-stale application network error", "applicationErrors": [ { "address": "a:27017", "when": "afterHandshakeCompletes", "maxWireVersion": 9, "type": "network" } ], "outcome": { "servers": { "a:27017": { "type": "Unknown", "topologyVersion": null, "pool": { "generation": 1 } } }, "topologyType": "ReplicaSetNoPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } }, { "description": "Primary A is rediscovered", "responses": [ [ "a:27017", { "ok": 1, "helloOk": true, "isWritablePrimary": true, "hosts": [ "a:27017" ], "setName": "rs", "minWireVersion": 0, "maxWireVersion": 9, "topologyVersion": { "processId": { "$oid": "000000000000000000000001" }, "counter": { "$numberLong": "1" } } } ] ], "outcome": { "servers": { "a:27017": { "type": "RSPrimary", "setName": "rs", "topologyVersion": { "processId": { "$oid": "000000000000000000000001" }, "counter": { "$numberLong": "1" } }, "pool": { "generation": 1 } } }, "topologyType": "ReplicaSetWithPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } }, { "description": "Ignore stale ShutdownInProgress error (stale generation)", "applicationErrors": [ { "address": "a:27017", "generation": 0, "when": "afterHandshakeCompletes", "maxWireVersion": 9, "type": "command", "response": { "ok": 0, "errmsg": "ShutdownInProgress", "code": 91, "topologyVersion": { "processId": { "$oid": "000000000000000000000001" }, "counter": { "$numberLong": "2" } } } } ], "outcome": { "servers": { "a:27017": { "type": "RSPrimary", "setName": "rs", "topologyVersion": { "processId": { "$oid": "000000000000000000000001" }, "counter": { "$numberLong": "1" } }, "pool": { "generation": 1 } } }, "topologyType": "ReplicaSetWithPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } } ] } stale-generation-afterHandshakeCompletes-network.json000066400000000000000000000076311462766011000413630ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/discovery_and_monitoring/errors{ "description": "Stale generation network error afterHandshakeCompletes", "uri": "mongodb://a/?replicaSet=rs", "phases": [ { "description": "Primary A is discovered", "responses": [ [ "a:27017", { "ok": 1, "helloOk": true, "isWritablePrimary": true, "hosts": [ "a:27017" ], "setName": "rs", "minWireVersion": 0, "maxWireVersion": 9, "topologyVersion": { "processId": { "$oid": "000000000000000000000001" }, "counter": { "$numberLong": "1" } } } ] ], "outcome": { "servers": { "a:27017": { "type": "RSPrimary", "setName": "rs", "topologyVersion": { "processId": { "$oid": "000000000000000000000001" }, "counter": { "$numberLong": "1" } }, "pool": { "generation": 0 } } }, "topologyType": "ReplicaSetWithPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } }, { "description": "Non-stale application network error", "applicationErrors": [ { "address": "a:27017", "when": "afterHandshakeCompletes", "maxWireVersion": 9, "type": "network" } ], "outcome": { "servers": { "a:27017": { "type": "Unknown", "topologyVersion": null, "pool": { "generation": 1 } } }, "topologyType": "ReplicaSetNoPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } }, { "description": "Primary A is rediscovered", "responses": [ [ "a:27017", { "ok": 1, "helloOk": true, "isWritablePrimary": true, "hosts": [ "a:27017" ], "setName": "rs", "minWireVersion": 0, "maxWireVersion": 9, "topologyVersion": { "processId": { "$oid": "000000000000000000000001" }, "counter": { "$numberLong": "1" } } } ] ], "outcome": { "servers": { "a:27017": { "type": "RSPrimary", "setName": "rs", "topologyVersion": { "processId": { "$oid": "000000000000000000000001" }, "counter": { "$numberLong": "1" } }, "pool": { "generation": 1 } } }, "topologyType": "ReplicaSetWithPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } }, { "description": "Ignore stale network error (stale generation)", "applicationErrors": [ { "address": "a:27017", "generation": 0, "when": "afterHandshakeCompletes", "maxWireVersion": 9, "type": "network" } ], "outcome": { "servers": { "a:27017": { "type": "RSPrimary", "setName": "rs", "topologyVersion": { "processId": { "$oid": "000000000000000000000001" }, "counter": { "$numberLong": "1" } }, "pool": { "generation": 1 } } }, "topologyType": "ReplicaSetWithPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } } ] } stale-generation-afterHandshakeCompletes-timeout.json000066400000000000000000000076311462766011000413600ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/discovery_and_monitoring/errors{ "description": "Stale generation timeout error afterHandshakeCompletes", "uri": "mongodb://a/?replicaSet=rs", "phases": [ { "description": "Primary A is discovered", "responses": [ [ "a:27017", { "ok": 1, "helloOk": true, "isWritablePrimary": true, "hosts": [ "a:27017" ], "setName": "rs", "minWireVersion": 0, "maxWireVersion": 9, "topologyVersion": { "processId": { "$oid": "000000000000000000000001" }, "counter": { "$numberLong": "1" } } } ] ], "outcome": { "servers": { "a:27017": { "type": "RSPrimary", "setName": "rs", "topologyVersion": { "processId": { "$oid": "000000000000000000000001" }, "counter": { "$numberLong": "1" } }, "pool": { "generation": 0 } } }, "topologyType": "ReplicaSetWithPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } }, { "description": "Non-stale application network error", "applicationErrors": [ { "address": "a:27017", "when": "afterHandshakeCompletes", "maxWireVersion": 9, "type": "network" } ], "outcome": { "servers": { "a:27017": { "type": "Unknown", "topologyVersion": null, "pool": { "generation": 1 } } }, "topologyType": "ReplicaSetNoPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } }, { "description": "Primary A is rediscovered", "responses": [ [ "a:27017", { "ok": 1, "helloOk": true, "isWritablePrimary": true, "hosts": [ "a:27017" ], "setName": "rs", "minWireVersion": 0, "maxWireVersion": 9, "topologyVersion": { "processId": { "$oid": "000000000000000000000001" }, "counter": { "$numberLong": "1" } } } ] ], "outcome": { "servers": { "a:27017": { "type": "RSPrimary", "setName": "rs", "topologyVersion": { "processId": { "$oid": "000000000000000000000001" }, "counter": { "$numberLong": "1" } }, "pool": { "generation": 1 } } }, "topologyType": "ReplicaSetWithPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } }, { "description": "Ignore stale timeout error (stale generation)", "applicationErrors": [ { "address": "a:27017", "generation": 0, "when": "afterHandshakeCompletes", "maxWireVersion": 9, "type": "timeout" } ], "outcome": { "servers": { "a:27017": { "type": "RSPrimary", "setName": "rs", "topologyVersion": { "processId": { "$oid": "000000000000000000000001" }, "counter": { "$numberLong": "1" } }, "pool": { "generation": 1 } } }, "topologyType": "ReplicaSetWithPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } } ] } stale-generation-beforeHandshakeCompletes-InterruptedAtShutdown.json000066400000000000000000000104311462766011000443510ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/discovery_and_monitoring/errors{ "description": "Stale generation InterruptedAtShutdown error beforeHandshakeCompletes", "uri": "mongodb://a/?replicaSet=rs", "phases": [ { "description": "Primary A is discovered", "responses": [ [ "a:27017", { "ok": 1, "helloOk": true, "isWritablePrimary": true, "hosts": [ "a:27017" ], "setName": "rs", "minWireVersion": 0, "maxWireVersion": 9, "topologyVersion": { "processId": { "$oid": "000000000000000000000001" }, "counter": { "$numberLong": "1" } } } ] ], "outcome": { "servers": { "a:27017": { "type": "RSPrimary", "setName": "rs", "topologyVersion": { "processId": { "$oid": "000000000000000000000001" }, "counter": { "$numberLong": "1" } }, "pool": { "generation": 0 } } }, "topologyType": "ReplicaSetWithPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } }, { "description": "Non-stale application network error", "applicationErrors": [ { "address": "a:27017", "when": "afterHandshakeCompletes", "maxWireVersion": 9, "type": "network" } ], "outcome": { "servers": { "a:27017": { "type": "Unknown", "topologyVersion": null, "pool": { "generation": 1 } } }, "topologyType": "ReplicaSetNoPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } }, { "description": "Primary A is rediscovered", "responses": [ [ "a:27017", { "ok": 1, "helloOk": true, "isWritablePrimary": true, "hosts": [ "a:27017" ], "setName": "rs", "minWireVersion": 0, "maxWireVersion": 9, "topologyVersion": { "processId": { "$oid": "000000000000000000000001" }, "counter": { "$numberLong": "1" } } } ] ], "outcome": { "servers": { "a:27017": { "type": "RSPrimary", "setName": "rs", "topologyVersion": { "processId": { "$oid": "000000000000000000000001" }, "counter": { "$numberLong": "1" } }, "pool": { "generation": 1 } } }, "topologyType": "ReplicaSetWithPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } }, { "description": "Ignore stale InterruptedAtShutdown error (stale generation)", "applicationErrors": [ { "address": "a:27017", "generation": 0, "when": "beforeHandshakeCompletes", "maxWireVersion": 9, "type": "command", "response": { "ok": 0, "errmsg": "InterruptedAtShutdown", "code": 11600, "topologyVersion": { "processId": { "$oid": "000000000000000000000001" }, "counter": { "$numberLong": "2" } } } } ], "outcome": { "servers": { "a:27017": { "type": "RSPrimary", "setName": "rs", "topologyVersion": { "processId": { "$oid": "000000000000000000000001" }, "counter": { "$numberLong": "1" } }, "pool": { "generation": 1 } } }, "topologyType": "ReplicaSetWithPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } } ] } stale-generation-beforeHandshakeCompletes-InterruptedDueToReplStateChange.json000066400000000000000000000104671462766011000462340ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/discovery_and_monitoring/errors{ "description": "Stale generation InterruptedDueToReplStateChange error beforeHandshakeCompletes", "uri": "mongodb://a/?replicaSet=rs", "phases": [ { "description": "Primary A is discovered", "responses": [ [ "a:27017", { "ok": 1, "helloOk": true, "isWritablePrimary": true, "hosts": [ "a:27017" ], "setName": "rs", "minWireVersion": 0, "maxWireVersion": 9, "topologyVersion": { "processId": { "$oid": "000000000000000000000001" }, "counter": { "$numberLong": "1" } } } ] ], "outcome": { "servers": { "a:27017": { "type": "RSPrimary", "setName": "rs", "topologyVersion": { "processId": { "$oid": "000000000000000000000001" }, "counter": { "$numberLong": "1" } }, "pool": { "generation": 0 } } }, "topologyType": "ReplicaSetWithPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } }, { "description": "Non-stale application network error", "applicationErrors": [ { "address": "a:27017", "when": "afterHandshakeCompletes", "maxWireVersion": 9, "type": "network" } ], "outcome": { "servers": { "a:27017": { "type": "Unknown", "topologyVersion": null, "pool": { "generation": 1 } } }, "topologyType": "ReplicaSetNoPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } }, { "description": "Primary A is rediscovered", "responses": [ [ "a:27017", { "ok": 1, "helloOk": true, "isWritablePrimary": true, "hosts": [ "a:27017" ], "setName": "rs", "minWireVersion": 0, "maxWireVersion": 9, "topologyVersion": { "processId": { "$oid": "000000000000000000000001" }, "counter": { "$numberLong": "1" } } } ] ], "outcome": { "servers": { "a:27017": { "type": "RSPrimary", "setName": "rs", "topologyVersion": { "processId": { "$oid": "000000000000000000000001" }, "counter": { "$numberLong": "1" } }, "pool": { "generation": 1 } } }, "topologyType": "ReplicaSetWithPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } }, { "description": "Ignore stale InterruptedDueToReplStateChange error (stale generation)", "applicationErrors": [ { "address": "a:27017", "generation": 0, "when": "beforeHandshakeCompletes", "maxWireVersion": 9, "type": "command", "response": { "ok": 0, "errmsg": "InterruptedDueToReplStateChange", "code": 11602, "topologyVersion": { "processId": { "$oid": "000000000000000000000001" }, "counter": { "$numberLong": "2" } } } } ], "outcome": { "servers": { "a:27017": { "type": "RSPrimary", "setName": "rs", "topologyVersion": { "processId": { "$oid": "000000000000000000000001" }, "counter": { "$numberLong": "1" } }, "pool": { "generation": 1 } } }, "topologyType": "ReplicaSetWithPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } } ] } stale-generation-beforeHandshakeCompletes-LegacyNotPrimary.json000066400000000000000000000104121462766011000432530ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/discovery_and_monitoring/errors{ "description": "Stale generation LegacyNotPrimary error beforeHandshakeCompletes", "uri": "mongodb://a/?replicaSet=rs", "phases": [ { "description": "Primary A is discovered", "responses": [ [ "a:27017", { "ok": 1, "helloOk": true, "isWritablePrimary": true, "hosts": [ "a:27017" ], "setName": "rs", "minWireVersion": 0, "maxWireVersion": 9, "topologyVersion": { "processId": { "$oid": "000000000000000000000001" }, "counter": { "$numberLong": "1" } } } ] ], "outcome": { "servers": { "a:27017": { "type": "RSPrimary", "setName": "rs", "topologyVersion": { "processId": { "$oid": "000000000000000000000001" }, "counter": { "$numberLong": "1" } }, "pool": { "generation": 0 } } }, "topologyType": "ReplicaSetWithPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } }, { "description": "Non-stale application network error", "applicationErrors": [ { "address": "a:27017", "when": "afterHandshakeCompletes", "maxWireVersion": 9, "type": "network" } ], "outcome": { "servers": { "a:27017": { "type": "Unknown", "topologyVersion": null, "pool": { "generation": 1 } } }, "topologyType": "ReplicaSetNoPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } }, { "description": "Primary A is rediscovered", "responses": [ [ "a:27017", { "ok": 1, "helloOk": true, "isWritablePrimary": true, "hosts": [ "a:27017" ], "setName": "rs", "minWireVersion": 0, "maxWireVersion": 9, "topologyVersion": { "processId": { "$oid": "000000000000000000000001" }, "counter": { "$numberLong": "1" } } } ] ], "outcome": { "servers": { "a:27017": { "type": "RSPrimary", "setName": "rs", "topologyVersion": { "processId": { "$oid": "000000000000000000000001" }, "counter": { "$numberLong": "1" } }, "pool": { "generation": 1 } } }, "topologyType": "ReplicaSetWithPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } }, { "description": "Ignore stale LegacyNotPrimary error (stale generation)", "applicationErrors": [ { "address": "a:27017", "generation": 0, "when": "beforeHandshakeCompletes", "maxWireVersion": 9, "type": "command", "response": { "ok": 0, "errmsg": "LegacyNotPrimary", "code": 10058, "topologyVersion": { "processId": { "$oid": "000000000000000000000001" }, "counter": { "$numberLong": "2" } } } } ], "outcome": { "servers": { "a:27017": { "type": "RSPrimary", "setName": "rs", "topologyVersion": { "processId": { "$oid": "000000000000000000000001" }, "counter": { "$numberLong": "1" } }, "pool": { "generation": 1 } } }, "topologyType": "ReplicaSetWithPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } } ] } stale-generation-beforeHandshakeCompletes-NotPrimaryNoSecondaryOk.json000066400000000000000000000104371462766011000445740ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/discovery_and_monitoring/errors{ "description": "Stale generation NotPrimaryNoSecondaryOk error beforeHandshakeCompletes", "uri": "mongodb://a/?replicaSet=rs", "phases": [ { "description": "Primary A is discovered", "responses": [ [ "a:27017", { "ok": 1, "helloOk": true, "isWritablePrimary": true, "hosts": [ "a:27017" ], "setName": "rs", "minWireVersion": 0, "maxWireVersion": 9, "topologyVersion": { "processId": { "$oid": "000000000000000000000001" }, "counter": { "$numberLong": "1" } } } ] ], "outcome": { "servers": { "a:27017": { "type": "RSPrimary", "setName": "rs", "topologyVersion": { "processId": { "$oid": "000000000000000000000001" }, "counter": { "$numberLong": "1" } }, "pool": { "generation": 0 } } }, "topologyType": "ReplicaSetWithPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } }, { "description": "Non-stale application network error", "applicationErrors": [ { "address": "a:27017", "when": "afterHandshakeCompletes", "maxWireVersion": 9, "type": "network" } ], "outcome": { "servers": { "a:27017": { "type": "Unknown", "topologyVersion": null, "pool": { "generation": 1 } } }, "topologyType": "ReplicaSetNoPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } }, { "description": "Primary A is rediscovered", "responses": [ [ "a:27017", { "ok": 1, "helloOk": true, "isWritablePrimary": true, "hosts": [ "a:27017" ], "setName": "rs", "minWireVersion": 0, "maxWireVersion": 9, "topologyVersion": { "processId": { "$oid": "000000000000000000000001" }, "counter": { "$numberLong": "1" } } } ] ], "outcome": { "servers": { "a:27017": { "type": "RSPrimary", "setName": "rs", "topologyVersion": { "processId": { "$oid": "000000000000000000000001" }, "counter": { "$numberLong": "1" } }, "pool": { "generation": 1 } } }, "topologyType": "ReplicaSetWithPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } }, { "description": "Ignore stale NotPrimaryNoSecondaryOk error (stale generation)", "applicationErrors": [ { "address": "a:27017", "generation": 0, "when": "beforeHandshakeCompletes", "maxWireVersion": 9, "type": "command", "response": { "ok": 0, "errmsg": "NotPrimaryNoSecondaryOk", "code": 13435, "topologyVersion": { "processId": { "$oid": "000000000000000000000001" }, "counter": { "$numberLong": "2" } } } } ], "outcome": { "servers": { "a:27017": { "type": "RSPrimary", "setName": "rs", "topologyVersion": { "processId": { "$oid": "000000000000000000000001" }, "counter": { "$numberLong": "1" } }, "pool": { "generation": 1 } } }, "topologyType": "ReplicaSetWithPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } } ] } stale-generation-beforeHandshakeCompletes-NotPrimaryOrSecondary.json000066400000000000000000000104311462766011000443000ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/discovery_and_monitoring/errors{ "description": "Stale generation NotPrimaryOrSecondary error beforeHandshakeCompletes", "uri": "mongodb://a/?replicaSet=rs", "phases": [ { "description": "Primary A is discovered", "responses": [ [ "a:27017", { "ok": 1, "helloOk": true, "isWritablePrimary": true, "hosts": [ "a:27017" ], "setName": "rs", "minWireVersion": 0, "maxWireVersion": 9, "topologyVersion": { "processId": { "$oid": "000000000000000000000001" }, "counter": { "$numberLong": "1" } } } ] ], "outcome": { "servers": { "a:27017": { "type": "RSPrimary", "setName": "rs", "topologyVersion": { "processId": { "$oid": "000000000000000000000001" }, "counter": { "$numberLong": "1" } }, "pool": { "generation": 0 } } }, "topologyType": "ReplicaSetWithPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } }, { "description": "Non-stale application network error", "applicationErrors": [ { "address": "a:27017", "when": "afterHandshakeCompletes", "maxWireVersion": 9, "type": "network" } ], "outcome": { "servers": { "a:27017": { "type": "Unknown", "topologyVersion": null, "pool": { "generation": 1 } } }, "topologyType": "ReplicaSetNoPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } }, { "description": "Primary A is rediscovered", "responses": [ [ "a:27017", { "ok": 1, "helloOk": true, "isWritablePrimary": true, "hosts": [ "a:27017" ], "setName": "rs", "minWireVersion": 0, "maxWireVersion": 9, "topologyVersion": { "processId": { "$oid": "000000000000000000000001" }, "counter": { "$numberLong": "1" } } } ] ], "outcome": { "servers": { "a:27017": { "type": "RSPrimary", "setName": "rs", "topologyVersion": { "processId": { "$oid": "000000000000000000000001" }, "counter": { "$numberLong": "1" } }, "pool": { "generation": 1 } } }, "topologyType": "ReplicaSetWithPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } }, { "description": "Ignore stale NotPrimaryOrSecondary error (stale generation)", "applicationErrors": [ { "address": "a:27017", "generation": 0, "when": "beforeHandshakeCompletes", "maxWireVersion": 9, "type": "command", "response": { "ok": 0, "errmsg": "NotPrimaryOrSecondary", "code": 13436, "topologyVersion": { "processId": { "$oid": "000000000000000000000001" }, "counter": { "$numberLong": "2" } } } } ], "outcome": { "servers": { "a:27017": { "type": "RSPrimary", "setName": "rs", "topologyVersion": { "processId": { "$oid": "000000000000000000000001" }, "counter": { "$numberLong": "1" } }, "pool": { "generation": 1 } } }, "topologyType": "ReplicaSetWithPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } } ] } stale-generation-beforeHandshakeCompletes-NotWritablePrimary.json000066400000000000000000000104201462766011000436170ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/discovery_and_monitoring/errors{ "description": "Stale generation NotWritablePrimary error beforeHandshakeCompletes", "uri": "mongodb://a/?replicaSet=rs", "phases": [ { "description": "Primary A is discovered", "responses": [ [ "a:27017", { "ok": 1, "helloOk": true, "isWritablePrimary": true, "hosts": [ "a:27017" ], "setName": "rs", "minWireVersion": 0, "maxWireVersion": 9, "topologyVersion": { "processId": { "$oid": "000000000000000000000001" }, "counter": { "$numberLong": "1" } } } ] ], "outcome": { "servers": { "a:27017": { "type": "RSPrimary", "setName": "rs", "topologyVersion": { "processId": { "$oid": "000000000000000000000001" }, "counter": { "$numberLong": "1" } }, "pool": { "generation": 0 } } }, "topologyType": "ReplicaSetWithPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } }, { "description": "Non-stale application network error", "applicationErrors": [ { "address": "a:27017", "when": "afterHandshakeCompletes", "maxWireVersion": 9, "type": "network" } ], "outcome": { "servers": { "a:27017": { "type": "Unknown", "topologyVersion": null, "pool": { "generation": 1 } } }, "topologyType": "ReplicaSetNoPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } }, { "description": "Primary A is rediscovered", "responses": [ [ "a:27017", { "ok": 1, "helloOk": true, "isWritablePrimary": true, "hosts": [ "a:27017" ], "setName": "rs", "minWireVersion": 0, "maxWireVersion": 9, "topologyVersion": { "processId": { "$oid": "000000000000000000000001" }, "counter": { "$numberLong": "1" } } } ] ], "outcome": { "servers": { "a:27017": { "type": "RSPrimary", "setName": "rs", "topologyVersion": { "processId": { "$oid": "000000000000000000000001" }, "counter": { "$numberLong": "1" } }, "pool": { "generation": 1 } } }, "topologyType": "ReplicaSetWithPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } }, { "description": "Ignore stale NotWritablePrimary error (stale generation)", "applicationErrors": [ { "address": "a:27017", "generation": 0, "when": "beforeHandshakeCompletes", "maxWireVersion": 9, "type": "command", "response": { "ok": 0, "errmsg": "NotWritablePrimary", "code": 10107, "topologyVersion": { "processId": { "$oid": "000000000000000000000001" }, "counter": { "$numberLong": "2" } } } } ], "outcome": { "servers": { "a:27017": { "type": "RSPrimary", "setName": "rs", "topologyVersion": { "processId": { "$oid": "000000000000000000000001" }, "counter": { "$numberLong": "1" } }, "pool": { "generation": 1 } } }, "topologyType": "ReplicaSetWithPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } } ] } stale-generation-beforeHandshakeCompletes-PrimarySteppedDown.json000066400000000000000000000104161462766011000436260ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/discovery_and_monitoring/errors{ "description": "Stale generation PrimarySteppedDown error beforeHandshakeCompletes", "uri": "mongodb://a/?replicaSet=rs", "phases": [ { "description": "Primary A is discovered", "responses": [ [ "a:27017", { "ok": 1, "helloOk": true, "isWritablePrimary": true, "hosts": [ "a:27017" ], "setName": "rs", "minWireVersion": 0, "maxWireVersion": 9, "topologyVersion": { "processId": { "$oid": "000000000000000000000001" }, "counter": { "$numberLong": "1" } } } ] ], "outcome": { "servers": { "a:27017": { "type": "RSPrimary", "setName": "rs", "topologyVersion": { "processId": { "$oid": "000000000000000000000001" }, "counter": { "$numberLong": "1" } }, "pool": { "generation": 0 } } }, "topologyType": "ReplicaSetWithPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } }, { "description": "Non-stale application network error", "applicationErrors": [ { "address": "a:27017", "when": "afterHandshakeCompletes", "maxWireVersion": 9, "type": "network" } ], "outcome": { "servers": { "a:27017": { "type": "Unknown", "topologyVersion": null, "pool": { "generation": 1 } } }, "topologyType": "ReplicaSetNoPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } }, { "description": "Primary A is rediscovered", "responses": [ [ "a:27017", { "ok": 1, "helloOk": true, "isWritablePrimary": true, "hosts": [ "a:27017" ], "setName": "rs", "minWireVersion": 0, "maxWireVersion": 9, "topologyVersion": { "processId": { "$oid": "000000000000000000000001" }, "counter": { "$numberLong": "1" } } } ] ], "outcome": { "servers": { "a:27017": { "type": "RSPrimary", "setName": "rs", "topologyVersion": { "processId": { "$oid": "000000000000000000000001" }, "counter": { "$numberLong": "1" } }, "pool": { "generation": 1 } } }, "topologyType": "ReplicaSetWithPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } }, { "description": "Ignore stale PrimarySteppedDown error (stale generation)", "applicationErrors": [ { "address": "a:27017", "generation": 0, "when": "beforeHandshakeCompletes", "maxWireVersion": 9, "type": "command", "response": { "ok": 0, "errmsg": "PrimarySteppedDown", "code": 189, "topologyVersion": { "processId": { "$oid": "000000000000000000000001" }, "counter": { "$numberLong": "2" } } } } ], "outcome": { "servers": { "a:27017": { "type": "RSPrimary", "setName": "rs", "topologyVersion": { "processId": { "$oid": "000000000000000000000001" }, "counter": { "$numberLong": "1" } }, "pool": { "generation": 1 } } }, "topologyType": "ReplicaSetWithPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } } ] } stale-generation-beforeHandshakeCompletes-ShutdownInProgress.json000066400000000000000000000104151462766011000436540ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/discovery_and_monitoring/errors{ "description": "Stale generation ShutdownInProgress error beforeHandshakeCompletes", "uri": "mongodb://a/?replicaSet=rs", "phases": [ { "description": "Primary A is discovered", "responses": [ [ "a:27017", { "ok": 1, "helloOk": true, "isWritablePrimary": true, "hosts": [ "a:27017" ], "setName": "rs", "minWireVersion": 0, "maxWireVersion": 9, "topologyVersion": { "processId": { "$oid": "000000000000000000000001" }, "counter": { "$numberLong": "1" } } } ] ], "outcome": { "servers": { "a:27017": { "type": "RSPrimary", "setName": "rs", "topologyVersion": { "processId": { "$oid": "000000000000000000000001" }, "counter": { "$numberLong": "1" } }, "pool": { "generation": 0 } } }, "topologyType": "ReplicaSetWithPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } }, { "description": "Non-stale application network error", "applicationErrors": [ { "address": "a:27017", "when": "afterHandshakeCompletes", "maxWireVersion": 9, "type": "network" } ], "outcome": { "servers": { "a:27017": { "type": "Unknown", "topologyVersion": null, "pool": { "generation": 1 } } }, "topologyType": "ReplicaSetNoPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } }, { "description": "Primary A is rediscovered", "responses": [ [ "a:27017", { "ok": 1, "helloOk": true, "isWritablePrimary": true, "hosts": [ "a:27017" ], "setName": "rs", "minWireVersion": 0, "maxWireVersion": 9, "topologyVersion": { "processId": { "$oid": "000000000000000000000001" }, "counter": { "$numberLong": "1" } } } ] ], "outcome": { "servers": { "a:27017": { "type": "RSPrimary", "setName": "rs", "topologyVersion": { "processId": { "$oid": "000000000000000000000001" }, "counter": { "$numberLong": "1" } }, "pool": { "generation": 1 } } }, "topologyType": "ReplicaSetWithPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } }, { "description": "Ignore stale ShutdownInProgress error (stale generation)", "applicationErrors": [ { "address": "a:27017", "generation": 0, "when": "beforeHandshakeCompletes", "maxWireVersion": 9, "type": "command", "response": { "ok": 0, "errmsg": "ShutdownInProgress", "code": 91, "topologyVersion": { "processId": { "$oid": "000000000000000000000001" }, "counter": { "$numberLong": "2" } } } } ], "outcome": { "servers": { "a:27017": { "type": "RSPrimary", "setName": "rs", "topologyVersion": { "processId": { "$oid": "000000000000000000000001" }, "counter": { "$numberLong": "1" } }, "pool": { "generation": 1 } } }, "topologyType": "ReplicaSetWithPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } } ] } stale-generation-beforeHandshakeCompletes-network.json000066400000000000000000000076331462766011000415260ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/discovery_and_monitoring/errors{ "description": "Stale generation network error beforeHandshakeCompletes", "uri": "mongodb://a/?replicaSet=rs", "phases": [ { "description": "Primary A is discovered", "responses": [ [ "a:27017", { "ok": 1, "helloOk": true, "isWritablePrimary": true, "hosts": [ "a:27017" ], "setName": "rs", "minWireVersion": 0, "maxWireVersion": 9, "topologyVersion": { "processId": { "$oid": "000000000000000000000001" }, "counter": { "$numberLong": "1" } } } ] ], "outcome": { "servers": { "a:27017": { "type": "RSPrimary", "setName": "rs", "topologyVersion": { "processId": { "$oid": "000000000000000000000001" }, "counter": { "$numberLong": "1" } }, "pool": { "generation": 0 } } }, "topologyType": "ReplicaSetWithPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } }, { "description": "Non-stale application network error", "applicationErrors": [ { "address": "a:27017", "when": "afterHandshakeCompletes", "maxWireVersion": 9, "type": "network" } ], "outcome": { "servers": { "a:27017": { "type": "Unknown", "topologyVersion": null, "pool": { "generation": 1 } } }, "topologyType": "ReplicaSetNoPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } }, { "description": "Primary A is rediscovered", "responses": [ [ "a:27017", { "ok": 1, "helloOk": true, "isWritablePrimary": true, "hosts": [ "a:27017" ], "setName": "rs", "minWireVersion": 0, "maxWireVersion": 9, "topologyVersion": { "processId": { "$oid": "000000000000000000000001" }, "counter": { "$numberLong": "1" } } } ] ], "outcome": { "servers": { "a:27017": { "type": "RSPrimary", "setName": "rs", "topologyVersion": { "processId": { "$oid": "000000000000000000000001" }, "counter": { "$numberLong": "1" } }, "pool": { "generation": 1 } } }, "topologyType": "ReplicaSetWithPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } }, { "description": "Ignore stale network error (stale generation)", "applicationErrors": [ { "address": "a:27017", "generation": 0, "when": "beforeHandshakeCompletes", "maxWireVersion": 9, "type": "network" } ], "outcome": { "servers": { "a:27017": { "type": "RSPrimary", "setName": "rs", "topologyVersion": { "processId": { "$oid": "000000000000000000000001" }, "counter": { "$numberLong": "1" } }, "pool": { "generation": 1 } } }, "topologyType": "ReplicaSetWithPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } } ] } stale-generation-beforeHandshakeCompletes-timeout.json000066400000000000000000000076331462766011000415230ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/discovery_and_monitoring/errors{ "description": "Stale generation timeout error beforeHandshakeCompletes", "uri": "mongodb://a/?replicaSet=rs", "phases": [ { "description": "Primary A is discovered", "responses": [ [ "a:27017", { "ok": 1, "helloOk": true, "isWritablePrimary": true, "hosts": [ "a:27017" ], "setName": "rs", "minWireVersion": 0, "maxWireVersion": 9, "topologyVersion": { "processId": { "$oid": "000000000000000000000001" }, "counter": { "$numberLong": "1" } } } ] ], "outcome": { "servers": { "a:27017": { "type": "RSPrimary", "setName": "rs", "topologyVersion": { "processId": { "$oid": "000000000000000000000001" }, "counter": { "$numberLong": "1" } }, "pool": { "generation": 0 } } }, "topologyType": "ReplicaSetWithPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } }, { "description": "Non-stale application network error", "applicationErrors": [ { "address": "a:27017", "when": "afterHandshakeCompletes", "maxWireVersion": 9, "type": "network" } ], "outcome": { "servers": { "a:27017": { "type": "Unknown", "topologyVersion": null, "pool": { "generation": 1 } } }, "topologyType": "ReplicaSetNoPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } }, { "description": "Primary A is rediscovered", "responses": [ [ "a:27017", { "ok": 1, "helloOk": true, "isWritablePrimary": true, "hosts": [ "a:27017" ], "setName": "rs", "minWireVersion": 0, "maxWireVersion": 9, "topologyVersion": { "processId": { "$oid": "000000000000000000000001" }, "counter": { "$numberLong": "1" } } } ] ], "outcome": { "servers": { "a:27017": { "type": "RSPrimary", "setName": "rs", "topologyVersion": { "processId": { "$oid": "000000000000000000000001" }, "counter": { "$numberLong": "1" } }, "pool": { "generation": 1 } } }, "topologyType": "ReplicaSetWithPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } }, { "description": "Ignore stale timeout error (stale generation)", "applicationErrors": [ { "address": "a:27017", "generation": 0, "when": "beforeHandshakeCompletes", "maxWireVersion": 9, "type": "timeout" } ], "outcome": { "servers": { "a:27017": { "type": "RSPrimary", "setName": "rs", "topologyVersion": { "processId": { "$oid": "000000000000000000000001" }, "counter": { "$numberLong": "1" } }, "pool": { "generation": 1 } } }, "topologyType": "ReplicaSetWithPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } } ] } stale-topologyVersion-InterruptedAtShutdown.json000066400000000000000000000072411462766011000405220ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/discovery_and_monitoring/errors{ "description": "Stale topologyVersion InterruptedAtShutdown error", "uri": "mongodb://a/?replicaSet=rs", "phases": [ { "description": "Primary A is discovered", "responses": [ [ "a:27017", { "ok": 1, "helloOk": true, "isWritablePrimary": true, "hosts": [ "a:27017" ], "setName": "rs", "minWireVersion": 0, "maxWireVersion": 9, "topologyVersion": { "processId": { "$oid": "000000000000000000000001" }, "counter": { "$numberLong": "1" } } } ] ], "outcome": { "servers": { "a:27017": { "type": "RSPrimary", "setName": "rs", "topologyVersion": { "processId": { "$oid": "000000000000000000000001" }, "counter": { "$numberLong": "1" } }, "pool": { "generation": 0 } } }, "topologyType": "ReplicaSetWithPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } }, { "description": "Ignore stale InterruptedAtShutdown error (topologyVersion less)", "applicationErrors": [ { "address": "a:27017", "when": "afterHandshakeCompletes", "maxWireVersion": 9, "type": "command", "response": { "ok": 0, "errmsg": "InterruptedAtShutdown", "code": 11600, "topologyVersion": { "processId": { "$oid": "000000000000000000000001" }, "counter": { "$numberLong": "0" } } } } ], "outcome": { "servers": { "a:27017": { "type": "RSPrimary", "setName": "rs", "topologyVersion": { "processId": { "$oid": "000000000000000000000001" }, "counter": { "$numberLong": "1" } }, "pool": { "generation": 0 } } }, "topologyType": "ReplicaSetWithPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } }, { "description": "Ignore stale InterruptedAtShutdown error (topologyVersion equal)", "applicationErrors": [ { "address": "a:27017", "when": "afterHandshakeCompletes", "maxWireVersion": 9, "type": "command", "response": { "ok": 0, "errmsg": "InterruptedAtShutdown", "code": 11600, "topologyVersion": { "processId": { "$oid": "000000000000000000000001" }, "counter": { "$numberLong": "1" } } } } ], "outcome": { "servers": { "a:27017": { "type": "RSPrimary", "setName": "rs", "topologyVersion": { "processId": { "$oid": "000000000000000000000001" }, "counter": { "$numberLong": "1" } }, "pool": { "generation": 0 } } }, "topologyType": "ReplicaSetWithPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } } ] } stale-topologyVersion-InterruptedDueToReplStateChange.json000066400000000000000000000073231462766011000423750ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/discovery_and_monitoring/errors{ "description": "Stale topologyVersion InterruptedDueToReplStateChange error", "uri": "mongodb://a/?replicaSet=rs", "phases": [ { "description": "Primary A is discovered", "responses": [ [ "a:27017", { "ok": 1, "helloOk": true, "isWritablePrimary": true, "hosts": [ "a:27017" ], "setName": "rs", "minWireVersion": 0, "maxWireVersion": 9, "topologyVersion": { "processId": { "$oid": "000000000000000000000001" }, "counter": { "$numberLong": "1" } } } ] ], "outcome": { "servers": { "a:27017": { "type": "RSPrimary", "setName": "rs", "topologyVersion": { "processId": { "$oid": "000000000000000000000001" }, "counter": { "$numberLong": "1" } }, "pool": { "generation": 0 } } }, "topologyType": "ReplicaSetWithPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } }, { "description": "Ignore stale InterruptedDueToReplStateChange error (topologyVersion less)", "applicationErrors": [ { "address": "a:27017", "when": "afterHandshakeCompletes", "maxWireVersion": 9, "type": "command", "response": { "ok": 0, "errmsg": "InterruptedDueToReplStateChange", "code": 11602, "topologyVersion": { "processId": { "$oid": "000000000000000000000001" }, "counter": { "$numberLong": "0" } } } } ], "outcome": { "servers": { "a:27017": { "type": "RSPrimary", "setName": "rs", "topologyVersion": { "processId": { "$oid": "000000000000000000000001" }, "counter": { "$numberLong": "1" } }, "pool": { "generation": 0 } } }, "topologyType": "ReplicaSetWithPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } }, { "description": "Ignore stale InterruptedDueToReplStateChange error (topologyVersion equal)", "applicationErrors": [ { "address": "a:27017", "when": "afterHandshakeCompletes", "maxWireVersion": 9, "type": "command", "response": { "ok": 0, "errmsg": "InterruptedDueToReplStateChange", "code": 11602, "topologyVersion": { "processId": { "$oid": "000000000000000000000001" }, "counter": { "$numberLong": "1" } } } } ], "outcome": { "servers": { "a:27017": { "type": "RSPrimary", "setName": "rs", "topologyVersion": { "processId": { "$oid": "000000000000000000000001" }, "counter": { "$numberLong": "1" } }, "pool": { "generation": 0 } } }, "topologyType": "ReplicaSetWithPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } } ] } stale-topologyVersion-LegacyNotPrimary.json000066400000000000000000000072101462766011000374210ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/discovery_and_monitoring/errors{ "description": "Stale topologyVersion LegacyNotPrimary error", "uri": "mongodb://a/?replicaSet=rs", "phases": [ { "description": "Primary A is discovered", "responses": [ [ "a:27017", { "ok": 1, "helloOk": true, "isWritablePrimary": true, "hosts": [ "a:27017" ], "setName": "rs", "minWireVersion": 0, "maxWireVersion": 9, "topologyVersion": { "processId": { "$oid": "000000000000000000000001" }, "counter": { "$numberLong": "1" } } } ] ], "outcome": { "servers": { "a:27017": { "type": "RSPrimary", "setName": "rs", "topologyVersion": { "processId": { "$oid": "000000000000000000000001" }, "counter": { "$numberLong": "1" } }, "pool": { "generation": 0 } } }, "topologyType": "ReplicaSetWithPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } }, { "description": "Ignore stale LegacyNotPrimary error (topologyVersion less)", "applicationErrors": [ { "address": "a:27017", "when": "afterHandshakeCompletes", "maxWireVersion": 9, "type": "command", "response": { "ok": 0, "errmsg": "LegacyNotPrimary", "code": 10058, "topologyVersion": { "processId": { "$oid": "000000000000000000000001" }, "counter": { "$numberLong": "0" } } } } ], "outcome": { "servers": { "a:27017": { "type": "RSPrimary", "setName": "rs", "topologyVersion": { "processId": { "$oid": "000000000000000000000001" }, "counter": { "$numberLong": "1" } }, "pool": { "generation": 0 } } }, "topologyType": "ReplicaSetWithPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } }, { "description": "Ignore stale LegacyNotPrimary error (topologyVersion equal)", "applicationErrors": [ { "address": "a:27017", "when": "afterHandshakeCompletes", "maxWireVersion": 9, "type": "command", "response": { "ok": 0, "errmsg": "LegacyNotPrimary", "code": 10058, "topologyVersion": { "processId": { "$oid": "000000000000000000000001" }, "counter": { "$numberLong": "1" } } } } ], "outcome": { "servers": { "a:27017": { "type": "RSPrimary", "setName": "rs", "topologyVersion": { "processId": { "$oid": "000000000000000000000001" }, "counter": { "$numberLong": "1" } }, "pool": { "generation": 0 } } }, "topologyType": "ReplicaSetWithPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } } ] } stale-topologyVersion-NotPrimaryNoSecondaryOk.json000066400000000000000000000072531462766011000407420ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/discovery_and_monitoring/errors{ "description": "Stale topologyVersion NotPrimaryNoSecondaryOk error", "uri": "mongodb://a/?replicaSet=rs", "phases": [ { "description": "Primary A is discovered", "responses": [ [ "a:27017", { "ok": 1, "helloOk": true, "isWritablePrimary": true, "hosts": [ "a:27017" ], "setName": "rs", "minWireVersion": 0, "maxWireVersion": 9, "topologyVersion": { "processId": { "$oid": "000000000000000000000001" }, "counter": { "$numberLong": "1" } } } ] ], "outcome": { "servers": { "a:27017": { "type": "RSPrimary", "setName": "rs", "topologyVersion": { "processId": { "$oid": "000000000000000000000001" }, "counter": { "$numberLong": "1" } }, "pool": { "generation": 0 } } }, "topologyType": "ReplicaSetWithPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } }, { "description": "Ignore stale NotPrimaryNoSecondaryOk error (topologyVersion less)", "applicationErrors": [ { "address": "a:27017", "when": "afterHandshakeCompletes", "maxWireVersion": 9, "type": "command", "response": { "ok": 0, "errmsg": "NotPrimaryNoSecondaryOk", "code": 13435, "topologyVersion": { "processId": { "$oid": "000000000000000000000001" }, "counter": { "$numberLong": "0" } } } } ], "outcome": { "servers": { "a:27017": { "type": "RSPrimary", "setName": "rs", "topologyVersion": { "processId": { "$oid": "000000000000000000000001" }, "counter": { "$numberLong": "1" } }, "pool": { "generation": 0 } } }, "topologyType": "ReplicaSetWithPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } }, { "description": "Ignore stale NotPrimaryNoSecondaryOk error (topologyVersion equal)", "applicationErrors": [ { "address": "a:27017", "when": "afterHandshakeCompletes", "maxWireVersion": 9, "type": "command", "response": { "ok": 0, "errmsg": "NotPrimaryNoSecondaryOk", "code": 13435, "topologyVersion": { "processId": { "$oid": "000000000000000000000001" }, "counter": { "$numberLong": "1" } } } } ], "outcome": { "servers": { "a:27017": { "type": "RSPrimary", "setName": "rs", "topologyVersion": { "processId": { "$oid": "000000000000000000000001" }, "counter": { "$numberLong": "1" } }, "pool": { "generation": 0 } } }, "topologyType": "ReplicaSetWithPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } } ] } stale-topologyVersion-NotPrimaryOrSecondary.json000066400000000000000000000072411462766011000404510ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/discovery_and_monitoring/errors{ "description": "Stale topologyVersion NotPrimaryOrSecondary error", "uri": "mongodb://a/?replicaSet=rs", "phases": [ { "description": "Primary A is discovered", "responses": [ [ "a:27017", { "ok": 1, "helloOk": true, "isWritablePrimary": true, "hosts": [ "a:27017" ], "setName": "rs", "minWireVersion": 0, "maxWireVersion": 9, "topologyVersion": { "processId": { "$oid": "000000000000000000000001" }, "counter": { "$numberLong": "1" } } } ] ], "outcome": { "servers": { "a:27017": { "type": "RSPrimary", "setName": "rs", "topologyVersion": { "processId": { "$oid": "000000000000000000000001" }, "counter": { "$numberLong": "1" } }, "pool": { "generation": 0 } } }, "topologyType": "ReplicaSetWithPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } }, { "description": "Ignore stale NotPrimaryOrSecondary error (topologyVersion less)", "applicationErrors": [ { "address": "a:27017", "when": "afterHandshakeCompletes", "maxWireVersion": 9, "type": "command", "response": { "ok": 0, "errmsg": "NotPrimaryOrSecondary", "code": 13436, "topologyVersion": { "processId": { "$oid": "000000000000000000000001" }, "counter": { "$numberLong": "0" } } } } ], "outcome": { "servers": { "a:27017": { "type": "RSPrimary", "setName": "rs", "topologyVersion": { "processId": { "$oid": "000000000000000000000001" }, "counter": { "$numberLong": "1" } }, "pool": { "generation": 0 } } }, "topologyType": "ReplicaSetWithPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } }, { "description": "Ignore stale NotPrimaryOrSecondary error (topologyVersion equal)", "applicationErrors": [ { "address": "a:27017", "when": "afterHandshakeCompletes", "maxWireVersion": 9, "type": "command", "response": { "ok": 0, "errmsg": "NotPrimaryOrSecondary", "code": 13436, "topologyVersion": { "processId": { "$oid": "000000000000000000000001" }, "counter": { "$numberLong": "1" } } } } ], "outcome": { "servers": { "a:27017": { "type": "RSPrimary", "setName": "rs", "topologyVersion": { "processId": { "$oid": "000000000000000000000001" }, "counter": { "$numberLong": "1" } }, "pool": { "generation": 0 } } }, "topologyType": "ReplicaSetWithPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } } ] } stale-topologyVersion-NotWritablePrimary.json000066400000000000000000000072221462766011000377710ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/discovery_and_monitoring/errors{ "description": "Stale topologyVersion NotWritablePrimary error", "uri": "mongodb://a/?replicaSet=rs", "phases": [ { "description": "Primary A is discovered", "responses": [ [ "a:27017", { "ok": 1, "helloOk": true, "isWritablePrimary": true, "hosts": [ "a:27017" ], "setName": "rs", "minWireVersion": 0, "maxWireVersion": 9, "topologyVersion": { "processId": { "$oid": "000000000000000000000001" }, "counter": { "$numberLong": "1" } } } ] ], "outcome": { "servers": { "a:27017": { "type": "RSPrimary", "setName": "rs", "topologyVersion": { "processId": { "$oid": "000000000000000000000001" }, "counter": { "$numberLong": "1" } }, "pool": { "generation": 0 } } }, "topologyType": "ReplicaSetWithPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } }, { "description": "Ignore stale NotWritablePrimary error (topologyVersion less)", "applicationErrors": [ { "address": "a:27017", "when": "afterHandshakeCompletes", "maxWireVersion": 9, "type": "command", "response": { "ok": 0, "errmsg": "NotWritablePrimary", "code": 10107, "topologyVersion": { "processId": { "$oid": "000000000000000000000001" }, "counter": { "$numberLong": "0" } } } } ], "outcome": { "servers": { "a:27017": { "type": "RSPrimary", "setName": "rs", "topologyVersion": { "processId": { "$oid": "000000000000000000000001" }, "counter": { "$numberLong": "1" } }, "pool": { "generation": 0 } } }, "topologyType": "ReplicaSetWithPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } }, { "description": "Ignore stale NotWritablePrimary error (topologyVersion equal)", "applicationErrors": [ { "address": "a:27017", "when": "afterHandshakeCompletes", "maxWireVersion": 9, "type": "command", "response": { "ok": 0, "errmsg": "NotWritablePrimary", "code": 10107, "topologyVersion": { "processId": { "$oid": "000000000000000000000001" }, "counter": { "$numberLong": "1" } } } } ], "outcome": { "servers": { "a:27017": { "type": "RSPrimary", "setName": "rs", "topologyVersion": { "processId": { "$oid": "000000000000000000000001" }, "counter": { "$numberLong": "1" } }, "pool": { "generation": 0 } } }, "topologyType": "ReplicaSetWithPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } } ] } stale-topologyVersion-PrimarySteppedDown.json000066400000000000000000000072161462766011000377760ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/discovery_and_monitoring/errors{ "description": "Stale topologyVersion PrimarySteppedDown error", "uri": "mongodb://a/?replicaSet=rs", "phases": [ { "description": "Primary A is discovered", "responses": [ [ "a:27017", { "ok": 1, "helloOk": true, "isWritablePrimary": true, "hosts": [ "a:27017" ], "setName": "rs", "minWireVersion": 0, "maxWireVersion": 9, "topologyVersion": { "processId": { "$oid": "000000000000000000000001" }, "counter": { "$numberLong": "1" } } } ] ], "outcome": { "servers": { "a:27017": { "type": "RSPrimary", "setName": "rs", "topologyVersion": { "processId": { "$oid": "000000000000000000000001" }, "counter": { "$numberLong": "1" } }, "pool": { "generation": 0 } } }, "topologyType": "ReplicaSetWithPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } }, { "description": "Ignore stale PrimarySteppedDown error (topologyVersion less)", "applicationErrors": [ { "address": "a:27017", "when": "afterHandshakeCompletes", "maxWireVersion": 9, "type": "command", "response": { "ok": 0, "errmsg": "PrimarySteppedDown", "code": 189, "topologyVersion": { "processId": { "$oid": "000000000000000000000001" }, "counter": { "$numberLong": "0" } } } } ], "outcome": { "servers": { "a:27017": { "type": "RSPrimary", "setName": "rs", "topologyVersion": { "processId": { "$oid": "000000000000000000000001" }, "counter": { "$numberLong": "1" } }, "pool": { "generation": 0 } } }, "topologyType": "ReplicaSetWithPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } }, { "description": "Ignore stale PrimarySteppedDown error (topologyVersion equal)", "applicationErrors": [ { "address": "a:27017", "when": "afterHandshakeCompletes", "maxWireVersion": 9, "type": "command", "response": { "ok": 0, "errmsg": "PrimarySteppedDown", "code": 189, "topologyVersion": { "processId": { "$oid": "000000000000000000000001" }, "counter": { "$numberLong": "1" } } } } ], "outcome": { "servers": { "a:27017": { "type": "RSPrimary", "setName": "rs", "topologyVersion": { "processId": { "$oid": "000000000000000000000001" }, "counter": { "$numberLong": "1" } }, "pool": { "generation": 0 } } }, "topologyType": "ReplicaSetWithPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } } ] } stale-topologyVersion-ShutdownInProgress.json000066400000000000000000000072141462766011000400230ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/discovery_and_monitoring/errors{ "description": "Stale topologyVersion ShutdownInProgress error", "uri": "mongodb://a/?replicaSet=rs", "phases": [ { "description": "Primary A is discovered", "responses": [ [ "a:27017", { "ok": 1, "helloOk": true, "isWritablePrimary": true, "hosts": [ "a:27017" ], "setName": "rs", "minWireVersion": 0, "maxWireVersion": 9, "topologyVersion": { "processId": { "$oid": "000000000000000000000001" }, "counter": { "$numberLong": "1" } } } ] ], "outcome": { "servers": { "a:27017": { "type": "RSPrimary", "setName": "rs", "topologyVersion": { "processId": { "$oid": "000000000000000000000001" }, "counter": { "$numberLong": "1" } }, "pool": { "generation": 0 } } }, "topologyType": "ReplicaSetWithPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } }, { "description": "Ignore stale ShutdownInProgress error (topologyVersion less)", "applicationErrors": [ { "address": "a:27017", "when": "afterHandshakeCompletes", "maxWireVersion": 9, "type": "command", "response": { "ok": 0, "errmsg": "ShutdownInProgress", "code": 91, "topologyVersion": { "processId": { "$oid": "000000000000000000000001" }, "counter": { "$numberLong": "0" } } } } ], "outcome": { "servers": { "a:27017": { "type": "RSPrimary", "setName": "rs", "topologyVersion": { "processId": { "$oid": "000000000000000000000001" }, "counter": { "$numberLong": "1" } }, "pool": { "generation": 0 } } }, "topologyType": "ReplicaSetWithPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } }, { "description": "Ignore stale ShutdownInProgress error (topologyVersion equal)", "applicationErrors": [ { "address": "a:27017", "when": "afterHandshakeCompletes", "maxWireVersion": 9, "type": "command", "response": { "ok": 0, "errmsg": "ShutdownInProgress", "code": 91, "topologyVersion": { "processId": { "$oid": "000000000000000000000001" }, "counter": { "$numberLong": "1" } } } } ], "outcome": { "servers": { "a:27017": { "type": "RSPrimary", "setName": "rs", "topologyVersion": { "processId": { "$oid": "000000000000000000000001" }, "counter": { "$numberLong": "1" } }, "pool": { "generation": 0 } } }, "topologyType": "ReplicaSetWithPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } } ] } mongodb-mongo-python-driver-509e9b7/test/discovery_and_monitoring/errors/write_errors_ignored.json000066400000000000000000000045141462766011000341620ustar00rootroot00000000000000{ "description": "writeErrors field is ignored", "uri": "mongodb://a/?replicaSet=rs", "phases": [ { "description": "Primary A is discovered", "responses": [ [ "a:27017", { "ok": 1, "helloOk": true, "isWritablePrimary": true, "hosts": [ "a:27017" ], "setName": "rs", "minWireVersion": 0, "maxWireVersion": 9, "topologyVersion": { "processId": { "$oid": "000000000000000000000001" }, "counter": { "$numberLong": "1" } } } ] ], "outcome": { "servers": { "a:27017": { "type": "RSPrimary", "setName": "rs", "topologyVersion": { "processId": { "$oid": "000000000000000000000001" }, "counter": { "$numberLong": "1" } }, "pool": { "generation": 0 } } }, "topologyType": "ReplicaSetWithPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } }, { "description": "Ignore command error with writeErrors field", "applicationErrors": [ { "address": "a:27017", "when": "afterHandshakeCompletes", "maxWireVersion": 9, "type": "command", "response": { "ok": 1, "writeErrors": [ { "errmsg": "NotPrimaryNoSecondaryOk", "code": 13435, "index": 0 } ] } } ], "outcome": { "servers": { "a:27017": { "type": "RSPrimary", "setName": "rs", "topologyVersion": { "processId": { "$oid": "000000000000000000000001" }, "counter": { "$numberLong": "1" } }, "pool": { "generation": 0 } } }, "topologyType": "ReplicaSetWithPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } } ] } mongodb-mongo-python-driver-509e9b7/test/discovery_and_monitoring/load-balanced/000077500000000000000000000000001462766011000301605ustar00rootroot00000000000000discover_load_balancer.json000066400000000000000000000013541462766011000354430ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/discovery_and_monitoring/load-balanced{ "description": "Load balancer can be discovered and only has the address property set", "uri": "mongodb://a/?loadBalanced=true", "phases": [ { "outcome": { "servers": { "a:27017": { "type": "LoadBalancer", "setName": null, "setVersion": null, "electionId": null, "logicalSessionTimeoutMinutes": null, "minWireVersion": null, "maxWireVersion": null, "topologyVersion": null } }, "topologyType": "LoadBalanced", "setName": null, "logicalSessionTimeoutMinutes": null, "maxSetVersion": null, "maxElectionId": null, "compatible": true } } ] } mongodb-mongo-python-driver-509e9b7/test/discovery_and_monitoring/rs/000077500000000000000000000000001462766011000261365ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/discovery_and_monitoring/rs/compatible.json000066400000000000000000000023751462766011000311570ustar00rootroot00000000000000{ "description": "Replica set member with large maxWireVersion", "uri": "mongodb://a,b/?replicaSet=rs", "phases": [ { "responses": [ [ "a:27017", { "ok": 1, "helloOk": true, "isWritablePrimary": true, "setName": "rs", "hosts": [ "a:27017", "b:27017" ], "minWireVersion": 0, "maxWireVersion": 6 } ], [ "b:27017", { "ok": 1, "helloOk": true, "isWritablePrimary": false, "secondary": true, "setName": "rs", "hosts": [ "a:27017", "b:27017" ], "minWireVersion": 0, "maxWireVersion": 1000 } ] ], "outcome": { "servers": { "a:27017": { "type": "RSPrimary", "setName": "rs" }, "b:27017": { "type": "RSSecondary", "setName": "rs" } }, "topologyType": "ReplicaSetWithPrimary", "setName": "rs", "logicalSessionTimeoutMinutes": null, "compatible": true } } ] } mongodb-mongo-python-driver-509e9b7/test/discovery_and_monitoring/rs/compatible_unknown.json000066400000000000000000000015451462766011000327340ustar00rootroot00000000000000{ "description": "Replica set member and an unknown server", "uri": "mongodb://a,b/?replicaSet=rs", "phases": [ { "responses": [ [ "a:27017", { "ok": 1, "helloOk": true, "isWritablePrimary": true, "setName": "rs", "hosts": [ "a:27017", "b:27017" ], "minWireVersion": 0, "maxWireVersion": 6 } ] ], "outcome": { "servers": { "a:27017": { "type": "RSPrimary", "setName": "rs" }, "b:27017": { "type": "Unknown" } }, "topologyType": "ReplicaSetWithPrimary", "setName": "rs", "logicalSessionTimeoutMinutes": null, "compatible": true } } ] } mongodb-mongo-python-driver-509e9b7/test/discovery_and_monitoring/rs/discover_arbiters.json000066400000000000000000000016371462766011000325510ustar00rootroot00000000000000{ "description": "Discover arbiters with directConnection URI option", "uri": "mongodb://a/?directConnection=false", "phases": [ { "responses": [ [ "a:27017", { "ok": 1, "helloOk": true, "isWritablePrimary": true, "hosts": [ "a:27017" ], "arbiters": [ "b:27017" ], "setName": "rs", "minWireVersion": 0, "maxWireVersion": 6 } ] ], "outcome": { "servers": { "a:27017": { "type": "RSPrimary", "setName": "rs" }, "b:27017": { "type": "Unknown", "setName": null } }, "topologyType": "ReplicaSetWithPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } } ] } discover_arbiters_replicaset.json000066400000000000000000000016201462766011000346750ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/discovery_and_monitoring/rs{ "description": "Discover arbiters with replicaSet URI option", "uri": "mongodb://a/?replicaSet=rs", "phases": [ { "responses": [ [ "a:27017", { "ok": 1, "helloOk": true, "isWritablePrimary": true, "hosts": [ "a:27017" ], "arbiters": [ "b:27017" ], "setName": "rs", "minWireVersion": 0, "maxWireVersion": 6 } ] ], "outcome": { "servers": { "a:27017": { "type": "RSPrimary", "setName": "rs" }, "b:27017": { "type": "Unknown", "setName": null } }, "topologyType": "ReplicaSetWithPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } } ] } mongodb-mongo-python-driver-509e9b7/test/discovery_and_monitoring/rs/discover_ghost.json000066400000000000000000000012641462766011000320560ustar00rootroot00000000000000{ "description": "Discover ghost with directConnection URI option", "uri": "mongodb://b/?directConnection=false", "phases": [ { "responses": [ [ "b:27017", { "ok": 1, "helloOk": true, "isWritablePrimary": false, "isreplicaset": true, "minWireVersion": 0, "maxWireVersion": 6 } ] ], "outcome": { "servers": { "b:27017": { "type": "RSGhost", "setName": null } }, "topologyType": "Unknown", "logicalSessionTimeoutMinutes": null, "setName": null } } ] } mongodb-mongo-python-driver-509e9b7/test/discovery_and_monitoring/rs/discover_ghost_replicaset.json000066400000000000000000000014221462766011000342650ustar00rootroot00000000000000{ "description": "Discover ghost with replicaSet URI option", "uri": "mongodb://a,b/?replicaSet=rs", "phases": [ { "responses": [ [ "b:27017", { "ok": 1, "helloOk": true, "isWritablePrimary": false, "isreplicaset": true, "minWireVersion": 0, "maxWireVersion": 6 } ] ], "outcome": { "servers": { "a:27017": { "type": "Unknown", "setName": null }, "b:27017": { "type": "RSGhost", "setName": null } }, "topologyType": "ReplicaSetNoPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } } ] } mongodb-mongo-python-driver-509e9b7/test/discovery_and_monitoring/rs/discover_hidden.json000066400000000000000000000020141462766011000321570ustar00rootroot00000000000000{ "description": "Discover hidden with directConnection URI option", "uri": "mongodb://a/?directConnection=false", "phases": [ { "responses": [ [ "a:27017", { "ok": 1, "helloOk": true, "isWritablePrimary": false, "secondary": true, "hidden": true, "hosts": [ "c:27017", "d:27017" ], "setName": "rs", "minWireVersion": 0, "maxWireVersion": 6 } ] ], "outcome": { "servers": { "a:27017": { "type": "RSOther", "setName": "rs" }, "c:27017": { "type": "Unknown", "setName": null }, "d:27017": { "type": "Unknown", "setName": null } }, "topologyType": "ReplicaSetNoPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } } ] } mongodb-mongo-python-driver-509e9b7/test/discovery_and_monitoring/rs/discover_hidden_replicaset.json000066400000000000000000000017751462766011000344070ustar00rootroot00000000000000{ "description": "Discover hidden with replicaSet URI option", "uri": "mongodb://a/?replicaSet=rs", "phases": [ { "responses": [ [ "a:27017", { "ok": 1, "helloOk": true, "isWritablePrimary": false, "secondary": true, "hidden": true, "hosts": [ "c:27017", "d:27017" ], "setName": "rs", "minWireVersion": 0, "maxWireVersion": 6 } ] ], "outcome": { "servers": { "a:27017": { "type": "RSOther", "setName": "rs" }, "c:27017": { "type": "Unknown", "setName": null }, "d:27017": { "type": "Unknown", "setName": null } }, "topologyType": "ReplicaSetNoPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } } ] } mongodb-mongo-python-driver-509e9b7/test/discovery_and_monitoring/rs/discover_passives.json000066400000000000000000000033631462766011000325710ustar00rootroot00000000000000{ "description": "Discover passives with directConnection URI option", "uri": "mongodb://a/?directConnection=false", "phases": [ { "responses": [ [ "a:27017", { "ok": 1, "helloOk": true, "isWritablePrimary": true, "hosts": [ "a:27017" ], "passives": [ "b:27017" ], "setName": "rs", "minWireVersion": 0, "maxWireVersion": 6 } ] ], "outcome": { "servers": { "a:27017": { "type": "RSPrimary", "setName": "rs" }, "b:27017": { "type": "Unknown", "setName": null } }, "topologyType": "ReplicaSetWithPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } }, { "responses": [ [ "b:27017", { "ok": 1, "helloOk": true, "isWritablePrimary": false, "secondary": true, "passive": true, "hosts": [ "a:27017" ], "passives": [ "b:27017" ], "setName": "rs", "minWireVersion": 0, "maxWireVersion": 6 } ] ], "outcome": { "servers": { "a:27017": { "type": "RSPrimary", "setName": "rs" }, "b:27017": { "type": "RSSecondary", "setName": "rs" } }, "topologyType": "ReplicaSetWithPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } } ] } discover_passives_replicaset.json000066400000000000000000000033441462766011000347240ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/discovery_and_monitoring/rs{ "description": "Discover passives with replicaSet URI option", "uri": "mongodb://a/?replicaSet=rs", "phases": [ { "responses": [ [ "a:27017", { "ok": 1, "helloOk": true, "isWritablePrimary": true, "hosts": [ "a:27017" ], "passives": [ "b:27017" ], "setName": "rs", "minWireVersion": 0, "maxWireVersion": 6 } ] ], "outcome": { "servers": { "a:27017": { "type": "RSPrimary", "setName": "rs" }, "b:27017": { "type": "Unknown", "setName": null } }, "topologyType": "ReplicaSetWithPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } }, { "responses": [ [ "b:27017", { "ok": 1, "helloOk": true, "isWritablePrimary": false, "secondary": true, "passive": true, "hosts": [ "a:27017" ], "passives": [ "b:27017" ], "setName": "rs", "minWireVersion": 0, "maxWireVersion": 6 } ] ], "outcome": { "servers": { "a:27017": { "type": "RSPrimary", "setName": "rs" }, "b:27017": { "type": "RSSecondary", "setName": "rs" } }, "topologyType": "ReplicaSetWithPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } } ] } mongodb-mongo-python-driver-509e9b7/test/discovery_and_monitoring/rs/discover_primary.json000066400000000000000000000015661462766011000324220ustar00rootroot00000000000000{ "description": "Discover primary with directConnection URI option", "uri": "mongodb://a/?directConnection=false", "phases": [ { "responses": [ [ "a:27017", { "ok": 1, "helloOk": true, "isWritablePrimary": true, "setName": "rs", "hosts": [ "a:27017", "b:27017" ], "minWireVersion": 0, "maxWireVersion": 6 } ] ], "outcome": { "servers": { "a:27017": { "type": "RSPrimary", "setName": "rs" }, "b:27017": { "type": "Unknown", "setName": null } }, "topologyType": "ReplicaSetWithPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } } ] } discover_primary_replicaset.json000066400000000000000000000015471462766011000345550ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/discovery_and_monitoring/rs{ "description": "Discover primary with replicaSet URI option", "uri": "mongodb://a/?replicaSet=rs", "phases": [ { "responses": [ [ "a:27017", { "ok": 1, "helloOk": true, "isWritablePrimary": true, "setName": "rs", "hosts": [ "a:27017", "b:27017" ], "minWireVersion": 0, "maxWireVersion": 6 } ] ], "outcome": { "servers": { "a:27017": { "type": "RSPrimary", "setName": "rs" }, "b:27017": { "type": "Unknown", "setName": null } }, "topologyType": "ReplicaSetWithPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } } ] } mongodb-mongo-python-driver-509e9b7/test/discovery_and_monitoring/rs/discover_rsother.json000066400000000000000000000017621462766011000324230ustar00rootroot00000000000000{ "description": "Discover RSOther with directConnection URI option", "uri": "mongodb://b/?directConnection=false", "phases": [ { "responses": [ [ "b:27017", { "ok": 1, "helloOk": true, "isWritablePrimary": false, "secondary": false, "hosts": [ "c:27017", "d:27017" ], "setName": "rs", "minWireVersion": 0, "maxWireVersion": 6 } ] ], "outcome": { "servers": { "b:27017": { "type": "RSOther", "setName": "rs" }, "c:27017": { "type": "Unknown", "setName": null }, "d:27017": { "type": "Unknown", "setName": null } }, "topologyType": "ReplicaSetNoPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } } ] } discover_rsother_replicaset.json000066400000000000000000000027201462766011000345520ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/discovery_and_monitoring/rs{ "description": "Discover RSOther with replicaSet URI option", "uri": "mongodb://a,b/?replicaSet=rs", "phases": [ { "responses": [ [ "a:27017", { "ok": 1, "helloOk": true, "isWritablePrimary": false, "secondary": true, "hidden": true, "hosts": [ "c:27017", "d:27017" ], "setName": "rs", "minWireVersion": 0, "maxWireVersion": 6 } ], [ "b:27017", { "ok": 1, "helloOk": true, "isWritablePrimary": false, "secondary": false, "hosts": [ "c:27017", "d:27017" ], "setName": "rs", "minWireVersion": 0, "maxWireVersion": 6 } ] ], "outcome": { "servers": { "a:27017": { "type": "RSOther", "setName": "rs" }, "b:27017": { "type": "RSOther", "setName": "rs" }, "c:27017": { "type": "Unknown", "setName": null }, "d:27017": { "type": "Unknown", "setName": null } }, "topologyType": "ReplicaSetNoPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } } ] } mongodb-mongo-python-driver-509e9b7/test/discovery_and_monitoring/rs/discover_secondary.json000066400000000000000000000016301462766011000327160ustar00rootroot00000000000000{ "description": "Discover secondary with directConnection URI option", "uri": "mongodb://b/?directConnection=false", "phases": [ { "responses": [ [ "b:27017", { "ok": 1, "helloOk": true, "isWritablePrimary": false, "secondary": true, "setName": "rs", "hosts": [ "a:27017", "b:27017" ], "minWireVersion": 0, "maxWireVersion": 6 } ] ], "outcome": { "servers": { "a:27017": { "type": "Unknown", "setName": null }, "b:27017": { "type": "RSSecondary", "setName": "rs" } }, "topologyType": "ReplicaSetNoPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } } ] } discover_secondary_replicaset.json000066400000000000000000000016111462766011000350510ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/discovery_and_monitoring/rs{ "description": "Discover secondary with replicaSet URI option", "uri": "mongodb://b/?replicaSet=rs", "phases": [ { "responses": [ [ "b:27017", { "ok": 1, "helloOk": true, "isWritablePrimary": false, "secondary": true, "setName": "rs", "hosts": [ "a:27017", "b:27017" ], "minWireVersion": 0, "maxWireVersion": 6 } ] ], "outcome": { "servers": { "a:27017": { "type": "Unknown", "setName": null }, "b:27017": { "type": "RSSecondary", "setName": "rs" } }, "topologyType": "ReplicaSetNoPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } } ] } mongodb-mongo-python-driver-509e9b7/test/discovery_and_monitoring/rs/discovery.json000066400000000000000000000077021462766011000310460ustar00rootroot00000000000000{ "description": "Replica set discovery", "uri": "mongodb://a/?replicaSet=rs", "phases": [ { "responses": [ [ "a:27017", { "ok": 1, "helloOk": true, "isWritablePrimary": false, "secondary": true, "setName": "rs", "hosts": [ "a:27017", "b:27017", "c:27017" ], "minWireVersion": 0, "maxWireVersion": 6 } ] ], "outcome": { "servers": { "a:27017": { "type": "RSSecondary", "setName": "rs" }, "b:27017": { "type": "Unknown", "setName": null }, "c:27017": { "type": "Unknown", "setName": null } }, "topologyType": "ReplicaSetNoPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } }, { "responses": [ [ "b:27017", { "ok": 1, "helloOk": true, "isWritablePrimary": false, "secondary": true, "setName": "rs", "primary": "d:27017", "hosts": [ "b:27017", "c:27017", "d:27017" ], "minWireVersion": 0, "maxWireVersion": 6 } ] ], "outcome": { "servers": { "a:27017": { "type": "RSSecondary", "setName": "rs" }, "b:27017": { "type": "RSSecondary", "setName": "rs" }, "c:27017": { "type": "Unknown", "setName": null }, "d:27017": { "type": "PossiblePrimary", "setName": null } }, "topologyType": "ReplicaSetNoPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } }, { "responses": [ [ "d:27017", { "ok": 1, "helloOk": true, "isWritablePrimary": true, "setName": "rs", "hosts": [ "b:27017", "c:27017", "d:27017", "e:27017" ], "minWireVersion": 0, "maxWireVersion": 6 } ] ], "outcome": { "servers": { "b:27017": { "type": "RSSecondary", "setName": "rs" }, "c:27017": { "type": "Unknown", "setName": null }, "d:27017": { "type": "RSPrimary", "setName": "rs" }, "e:27017": { "type": "Unknown", "setName": null } }, "topologyType": "ReplicaSetWithPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } }, { "responses": [ [ "c:27017", { "ok": 1, "helloOk": true, "isWritablePrimary": false, "secondary": true, "setName": "rs", "hosts": [ "a:27017", "b:27017", "c:27017" ], "minWireVersion": 0, "maxWireVersion": 6 } ] ], "outcome": { "servers": { "b:27017": { "type": "RSSecondary", "setName": "rs" }, "c:27017": { "type": "RSSecondary", "setName": "rs" }, "d:27017": { "type": "RSPrimary", "setName": "rs" }, "e:27017": { "type": "Unknown", "setName": null } }, "topologyType": "ReplicaSetWithPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } } ] } electionId_precedence_setVersion.json000066400000000000000000000042541462766011000354340ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/discovery_and_monitoring/rs{ "description": "ElectionId is considered higher precedence than setVersion", "uri": "mongodb://a/?replicaSet=rs", "phases": [ { "responses": [ [ "a:27017", { "ok": 1, "helloOk": true, "isWritablePrimary": true, "hosts": [ "a:27017", "b:27017" ], "setName": "rs", "setVersion": 1, "electionId": { "$oid": "000000000000000000000001" }, "minWireVersion": 0, "maxWireVersion": 17 } ], [ "b:27017", { "ok": 1, "helloOk": true, "isWritablePrimary": true, "hosts": [ "a:27017", "b:27017" ], "setName": "rs", "setVersion": 2, "electionId": { "$oid": "000000000000000000000001" }, "minWireVersion": 0, "maxWireVersion": 17 } ], [ "a:27017", { "ok": 1, "helloOk": true, "isWritablePrimary": true, "hosts": [ "a:27017", "b:27017" ], "setName": "rs", "setVersion": 1, "electionId": { "$oid": "000000000000000000000002" }, "minWireVersion": 0, "maxWireVersion": 17 } ] ], "outcome": { "servers": { "a:27017": { "type": "RSPrimary", "setName": "rs", "setVersion": 1, "electionId": { "$oid": "000000000000000000000002" } }, "b:27017": { "type": "Unknown", "setName": null, "setVersion": null, "electionId": null } }, "topologyType": "ReplicaSetWithPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs", "maxSetVersion": 1, "maxElectionId": { "$oid": "000000000000000000000002" } } } ] } mongodb-mongo-python-driver-509e9b7/test/discovery_and_monitoring/rs/equal_electionids.json000066400000000000000000000033071462766011000325250ustar00rootroot00000000000000{ "description": "New primary with equal electionId", "uri": "mongodb://a/?replicaSet=rs", "phases": [ { "responses": [ [ "a:27017", { "ok": 1, "helloOk": true, "isWritablePrimary": true, "hosts": [ "a:27017", "b:27017" ], "setName": "rs", "setVersion": 1, "electionId": { "$oid": "000000000000000000000001" }, "minWireVersion": 0, "maxWireVersion": 6 } ], [ "b:27017", { "ok": 1, "helloOk": true, "isWritablePrimary": true, "hosts": [ "a:27017", "b:27017" ], "setName": "rs", "setVersion": 1, "electionId": { "$oid": "000000000000000000000001" }, "minWireVersion": 0, "maxWireVersion": 6 } ] ], "outcome": { "servers": { "a:27017": { "type": "Unknown", "setName": null, "setVersion": null, "electionId": null }, "b:27017": { "type": "RSPrimary", "setName": "rs", "setVersion": 1, "electionId": { "$oid": "000000000000000000000001" } } }, "topologyType": "ReplicaSetWithPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs", "maxSetVersion": 1, "maxElectionId": { "$oid": "000000000000000000000001" } } } ] } mongodb-mongo-python-driver-509e9b7/test/discovery_and_monitoring/rs/hosts_differ_from_seeds.json000066400000000000000000000013341462766011000337170ustar00rootroot00000000000000{ "description": "Host list differs from seeds", "uri": "mongodb://a/?replicaSet=rs", "phases": [ { "responses": [ [ "a:27017", { "ok": 1, "helloOk": true, "isWritablePrimary": true, "setName": "rs", "hosts": [ "b:27017" ], "minWireVersion": 0, "maxWireVersion": 6 } ] ], "outcome": { "servers": { "b:27017": { "type": "Unknown", "setName": null } }, "topologyType": "ReplicaSetNoPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } } ] } mongodb-mongo-python-driver-509e9b7/test/discovery_and_monitoring/rs/incompatible_arbiter.json000066400000000000000000000022731462766011000332130ustar00rootroot00000000000000{ "description": "Incompatible arbiter", "uri": "mongodb://a,b/?replicaSet=rs", "phases": [ { "responses": [ [ "a:27017", { "ok": 1, "helloOk": true, "isWritablePrimary": true, "setName": "rs", "hosts": [ "a:27017", "b:27017" ], "minWireVersion": 0, "maxWireVersion": 6 } ], [ "b:27017", { "ok": 1, "helloOk": true, "arbiterOnly": true, "setName": "rs", "hosts": [ "a:27017", "b:27017" ], "minWireVersion": 0, "maxWireVersion": 1 } ] ], "outcome": { "servers": { "a:27017": { "type": "RSPrimary", "setName": "rs" }, "b:27017": { "type": "RSArbiter", "setName": "rs" } }, "topologyType": "ReplicaSetWithPrimary", "setName": "rs", "logicalSessionTimeoutMinutes": null, "compatible": false } } ] } mongodb-mongo-python-driver-509e9b7/test/discovery_and_monitoring/rs/incompatible_ghost.json000066400000000000000000000021041462766011000327000ustar00rootroot00000000000000{ "description": "Incompatible ghost", "uri": "mongodb://a,b/?replicaSet=rs", "phases": [ { "responses": [ [ "a:27017", { "ok": 1, "helloOk": true, "isWritablePrimary": true, "setName": "rs", "hosts": [ "a:27017", "b:27017" ], "minWireVersion": 0, "maxWireVersion": 6 } ], [ "b:27017", { "ok": 1, "helloOk": true, "isreplicaset": true, "minWireVersion": 0, "maxWireVersion": 1 } ] ], "outcome": { "servers": { "a:27017": { "type": "RSPrimary", "setName": "rs" }, "b:27017": { "type": "RSGhost", "setName": null } }, "topologyType": "ReplicaSetWithPrimary", "setName": "rs", "logicalSessionTimeoutMinutes": null, "compatible": false } } ] } mongodb-mongo-python-driver-509e9b7/test/discovery_and_monitoring/rs/incompatible_other.json000066400000000000000000000022621462766011000327020ustar00rootroot00000000000000{ "description": "Incompatible other", "uri": "mongodb://a,b/?replicaSet=rs", "phases": [ { "responses": [ [ "a:27017", { "ok": 1, "helloOk": true, "isWritablePrimary": true, "setName": "rs", "hosts": [ "a:27017", "b:27017" ], "minWireVersion": 0, "maxWireVersion": 6 } ], [ "b:27017", { "ok": 1, "helloOk": true, "hidden": true, "setName": "rs", "hosts": [ "a:27017", "b:27017" ], "minWireVersion": 0, "maxWireVersion": 1 } ] ], "outcome": { "servers": { "a:27017": { "type": "RSPrimary", "setName": "rs" }, "b:27017": { "type": "RSOther", "setName": "rs" } }, "topologyType": "ReplicaSetWithPrimary", "setName": "rs", "logicalSessionTimeoutMinutes": null, "compatible": false } } ] } mongodb-mongo-python-driver-509e9b7/test/discovery_and_monitoring/rs/ls_timeout.json000066400000000000000000000143101462766011000312140ustar00rootroot00000000000000{ "description": "Parse logicalSessionTimeoutMinutes from replica set", "uri": "mongodb://a/?replicaSet=rs", "phases": [ { "responses": [ [ "a:27017", { "ok": 1, "helloOk": true, "isWritablePrimary": true, "hosts": [ "a:27017", "b:27017", "c:27017", "d:27017", "e:27017" ], "setName": "rs", "logicalSessionTimeoutMinutes": 3, "minWireVersion": 0, "maxWireVersion": 6 } ] ], "outcome": { "servers": { "a:27017": { "type": "RSPrimary", "setName": "rs" }, "b:27017": { "type": "Unknown" }, "c:27017": { "type": "Unknown" }, "d:27017": { "type": "Unknown" }, "e:27017": { "type": "Unknown" } }, "topologyType": "ReplicaSetWithPrimary", "logicalSessionTimeoutMinutes": 3, "setName": "rs" } }, { "responses": [ [ "d:27017", { "ok": 1, "helloOk": true, "isWritablePrimary": false, "isreplicaset": true, "minWireVersion": 0, "maxWireVersion": 6 } ] ], "outcome": { "servers": { "a:27017": { "type": "RSPrimary", "setName": "rs" }, "b:27017": { "type": "Unknown" }, "c:27017": { "type": "Unknown" }, "d:27017": { "type": "RSGhost" }, "e:27017": { "type": "Unknown" } }, "topologyType": "ReplicaSetWithPrimary", "logicalSessionTimeoutMinutes": 3, "setName": "rs" } }, { "responses": [ [ "e:27017", { "ok": 1, "helloOk": true, "isWritablePrimary": false, "hosts": [ "a:27017", "b:27017", "c:27017", "d:27017", "e:27017" ], "setName": "rs", "arbiterOnly": true, "minWireVersion": 0, "maxWireVersion": 6 } ] ], "outcome": { "servers": { "a:27017": { "type": "RSPrimary", "setName": "rs" }, "b:27017": { "type": "Unknown" }, "c:27017": { "type": "Unknown" }, "d:27017": { "type": "RSGhost" }, "e:27017": { "type": "RSArbiter", "setName": "rs" } }, "topologyType": "ReplicaSetWithPrimary", "logicalSessionTimeoutMinutes": 3, "setName": "rs" } }, { "responses": [ [ "b:27017", { "ok": 1, "helloOk": true, "isWritablePrimary": false, "secondary": true, "hosts": [ "a:27017", "b:27017", "c:27017", "d:27017", "e:27017" ], "setName": "rs", "logicalSessionTimeoutMinutes": 2, "minWireVersion": 0, "maxWireVersion": 6 } ] ], "outcome": { "servers": { "a:27017": { "type": "RSPrimary", "setName": "rs" }, "b:27017": { "type": "RSSecondary", "setName": "rs" }, "c:27017": { "type": "Unknown" }, "d:27017": { "type": "RSGhost" }, "e:27017": { "type": "RSArbiter", "setName": "rs" } }, "topologyType": "ReplicaSetWithPrimary", "logicalSessionTimeoutMinutes": 2, "setName": "rs" } }, { "responses": [ [ "c:27017", { "ok": 1, "helloOk": true, "isWritablePrimary": false, "setName": "rs", "hidden": true, "logicalSessionTimeoutMinutes": 1, "minWireVersion": 0, "maxWireVersion": 6 } ] ], "outcome": { "servers": { "a:27017": { "type": "RSPrimary", "setName": "rs" }, "b:27017": { "type": "RSSecondary", "setName": "rs" }, "c:27017": { "type": "RSOther", "setName": "rs" }, "d:27017": { "type": "RSGhost" }, "e:27017": { "type": "RSArbiter", "setName": "rs" } }, "topologyType": "ReplicaSetWithPrimary", "logicalSessionTimeoutMinutes": 2, "setName": "rs" } }, { "responses": [ [ "b:27017", { "ok": 1, "helloOk": true, "isWritablePrimary": false, "secondary": true, "hosts": [ "a:27017", "b:27017", "c:27017", "d:27017", "e:27017" ], "setName": "rs", "logicalSessionTimeoutMinutes": null, "minWireVersion": 0, "maxWireVersion": 6 } ] ], "outcome": { "servers": { "a:27017": { "type": "RSPrimary", "setName": "rs" }, "b:27017": { "type": "RSSecondary", "setName": "rs" }, "c:27017": { "type": "RSOther", "setName": "rs" }, "d:27017": { "type": "RSGhost" }, "e:27017": { "type": "RSArbiter", "setName": "rs" } }, "topologyType": "ReplicaSetWithPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } } ] } mongodb-mongo-python-driver-509e9b7/test/discovery_and_monitoring/rs/member_reconfig.json000066400000000000000000000027131462766011000321570ustar00rootroot00000000000000{ "description": "Member removed by reconfig", "uri": "mongodb://a,b/?replicaSet=rs", "phases": [ { "responses": [ [ "a:27017", { "ok": 1, "helloOk": true, "isWritablePrimary": true, "setName": "rs", "hosts": [ "a:27017", "b:27017" ], "minWireVersion": 0, "maxWireVersion": 6 } ] ], "outcome": { "servers": { "a:27017": { "type": "RSPrimary", "setName": "rs" }, "b:27017": { "type": "Unknown", "setName": null } }, "topologyType": "ReplicaSetWithPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } }, { "responses": [ [ "a:27017", { "ok": 1, "helloOk": true, "isWritablePrimary": true, "setName": "rs", "hosts": [ "a:27017" ], "minWireVersion": 0, "maxWireVersion": 6 } ] ], "outcome": { "servers": { "a:27017": { "type": "RSPrimary", "setName": "rs" } }, "topologyType": "ReplicaSetWithPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } } ] } mongodb-mongo-python-driver-509e9b7/test/discovery_and_monitoring/rs/member_standalone.json000066400000000000000000000023361462766011000325140ustar00rootroot00000000000000{ "description": "Member brought up as standalone", "uri": "mongodb://a,b", "phases": [ { "responses": [ [ "b:27017", { "ok": 1, "helloOk": true, "isWritablePrimary": true, "minWireVersion": 0, "maxWireVersion": 6 } ] ], "outcome": { "servers": { "a:27017": { "type": "Unknown", "setName": null } }, "topologyType": "Unknown", "logicalSessionTimeoutMinutes": null, "setName": null } }, { "responses": [ [ "a:27017", { "ok": 1, "helloOk": true, "isWritablePrimary": true, "setName": "rs", "hosts": [ "a:27017" ], "minWireVersion": 0, "maxWireVersion": 6 } ] ], "outcome": { "servers": { "a:27017": { "type": "RSPrimary", "setName": "rs" } }, "topologyType": "ReplicaSetWithPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } } ] } mongodb-mongo-python-driver-509e9b7/test/discovery_and_monitoring/rs/new_primary.json000066400000000000000000000030641462766011000313700ustar00rootroot00000000000000{ "description": "New primary", "uri": "mongodb://a,b/?replicaSet=rs", "phases": [ { "responses": [ [ "a:27017", { "ok": 1, "helloOk": true, "isWritablePrimary": true, "setName": "rs", "hosts": [ "a:27017", "b:27017" ], "minWireVersion": 0, "maxWireVersion": 6 } ] ], "outcome": { "servers": { "a:27017": { "type": "RSPrimary", "setName": "rs" }, "b:27017": { "type": "Unknown", "setName": null } }, "topologyType": "ReplicaSetWithPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } }, { "responses": [ [ "b:27017", { "ok": 1, "helloOk": true, "isWritablePrimary": true, "setName": "rs", "hosts": [ "a:27017", "b:27017" ], "minWireVersion": 0, "maxWireVersion": 6 } ] ], "outcome": { "servers": { "a:27017": { "type": "Unknown", "setName": null }, "b:27017": { "type": "RSPrimary", "setName": "rs" } }, "topologyType": "ReplicaSetWithPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } } ] } mongodb-mongo-python-driver-509e9b7/test/discovery_and_monitoring/rs/new_primary_new_electionid.json000066400000000000000000000067071462766011000344470ustar00rootroot00000000000000{ "description": "New primary with greater setVersion and electionId", "uri": "mongodb://a/?replicaSet=rs", "phases": [ { "responses": [ [ "a:27017", { "ok": 1, "helloOk": true, "isWritablePrimary": true, "hosts": [ "a:27017", "b:27017" ], "setName": "rs", "setVersion": 1, "electionId": { "$oid": "000000000000000000000001" }, "minWireVersion": 0, "maxWireVersion": 6 } ] ], "outcome": { "servers": { "a:27017": { "type": "RSPrimary", "setName": "rs", "setVersion": 1, "electionId": { "$oid": "000000000000000000000001" } }, "b:27017": { "type": "Unknown", "setName": null, "electionId": null } }, "topologyType": "ReplicaSetWithPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs", "maxSetVersion": 1, "maxElectionId": { "$oid": "000000000000000000000001" } } }, { "responses": [ [ "b:27017", { "ok": 1, "helloOk": true, "isWritablePrimary": true, "hosts": [ "a:27017", "b:27017" ], "setName": "rs", "setVersion": 1, "electionId": { "$oid": "000000000000000000000002" }, "minWireVersion": 0, "maxWireVersion": 6 } ] ], "outcome": { "servers": { "a:27017": { "type": "Unknown", "setName": null, "electionId": null }, "b:27017": { "type": "RSPrimary", "setName": "rs", "setVersion": 1, "electionId": { "$oid": "000000000000000000000002" } } }, "topologyType": "ReplicaSetWithPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs", "maxSetVersion": 1, "maxElectionId": { "$oid": "000000000000000000000002" } } }, { "responses": [ [ "a:27017", { "ok": 1, "helloOk": true, "isWritablePrimary": true, "hosts": [ "a:27017", "b:27017" ], "setName": "rs", "setVersion": 1, "electionId": { "$oid": "000000000000000000000001" }, "minWireVersion": 0, "maxWireVersion": 6 } ] ], "outcome": { "servers": { "a:27017": { "type": "Unknown", "setName": null, "electionId": null }, "b:27017": { "type": "RSPrimary", "setName": "rs", "setVersion": 1, "electionId": { "$oid": "000000000000000000000002" } } }, "topologyType": "ReplicaSetWithPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs", "maxSetVersion": 1, "maxElectionId": { "$oid": "000000000000000000000002" } } } ] } mongodb-mongo-python-driver-509e9b7/test/discovery_and_monitoring/rs/new_primary_new_setversion.json000066400000000000000000000066701462766011000345300ustar00rootroot00000000000000{ "description": "New primary with greater setVersion", "uri": "mongodb://a/?replicaSet=rs", "phases": [ { "responses": [ [ "a:27017", { "ok": 1, "helloOk": true, "isWritablePrimary": true, "hosts": [ "a:27017", "b:27017" ], "setName": "rs", "setVersion": 1, "electionId": { "$oid": "000000000000000000000001" }, "minWireVersion": 0, "maxWireVersion": 6 } ] ], "outcome": { "servers": { "a:27017": { "type": "RSPrimary", "setName": "rs", "setVersion": 1, "electionId": { "$oid": "000000000000000000000001" } }, "b:27017": { "type": "Unknown", "setName": null, "electionId": null } }, "topologyType": "ReplicaSetWithPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs", "maxSetVersion": 1, "maxElectionId": { "$oid": "000000000000000000000001" } } }, { "responses": [ [ "b:27017", { "ok": 1, "helloOk": true, "isWritablePrimary": true, "hosts": [ "a:27017", "b:27017" ], "setName": "rs", "setVersion": 2, "electionId": { "$oid": "000000000000000000000001" }, "minWireVersion": 0, "maxWireVersion": 6 } ] ], "outcome": { "servers": { "a:27017": { "type": "Unknown", "setName": null, "electionId": null }, "b:27017": { "type": "RSPrimary", "setName": "rs", "setVersion": 2, "electionId": { "$oid": "000000000000000000000001" } } }, "topologyType": "ReplicaSetWithPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs", "maxSetVersion": 2, "maxElectionId": { "$oid": "000000000000000000000001" } } }, { "responses": [ [ "a:27017", { "ok": 1, "helloOk": true, "isWritablePrimary": true, "hosts": [ "a:27017", "b:27017" ], "setName": "rs", "setVersion": 1, "electionId": { "$oid": "000000000000000000000001" }, "minWireVersion": 0, "maxWireVersion": 6 } ] ], "outcome": { "servers": { "a:27017": { "type": "Unknown", "setName": null, "electionId": null }, "b:27017": { "type": "RSPrimary", "setName": "rs", "setVersion": 2, "electionId": { "$oid": "000000000000000000000001" } } }, "topologyType": "ReplicaSetWithPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs", "maxSetVersion": 2, "maxElectionId": { "$oid": "000000000000000000000001" } } } ] } mongodb-mongo-python-driver-509e9b7/test/discovery_and_monitoring/rs/new_primary_wrong_set_name.json000066400000000000000000000027201462766011000344550ustar00rootroot00000000000000{ "description": "New primary with wrong setName", "uri": "mongodb://a/?replicaSet=rs", "phases": [ { "responses": [ [ "a:27017", { "ok": 1, "helloOk": true, "isWritablePrimary": true, "hosts": [ "a:27017", "b:27017" ], "setName": "rs", "minWireVersion": 0, "maxWireVersion": 6 } ] ], "outcome": { "servers": { "a:27017": { "type": "RSPrimary", "setName": "rs" }, "b:27017": { "type": "Unknown", "setName": null } }, "topologyType": "ReplicaSetWithPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } }, { "responses": [ [ "b:27017", { "ok": 1, "helloOk": true, "isWritablePrimary": true, "hosts": [ "a:27017" ], "setName": "wrong", "minWireVersion": 0, "maxWireVersion": 6 } ] ], "outcome": { "servers": { "a:27017": { "type": "RSPrimary", "setName": "rs" } }, "topologyType": "ReplicaSetWithPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } } ] } mongodb-mongo-python-driver-509e9b7/test/discovery_and_monitoring/rs/non_rs_member.json000066400000000000000000000011361462766011000316570ustar00rootroot00000000000000{ "description": "Non replicaSet member responds", "uri": "mongodb://a,b/?replicaSet=rs", "phases": [ { "responses": [ [ "b:27017", { "ok": 1, "helloOk": true, "minWireVersion": 0, "maxWireVersion": 6 } ] ], "outcome": { "servers": { "a:27017": { "type": "Unknown", "setName": null } }, "topologyType": "ReplicaSetNoPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } } ] } mongodb-mongo-python-driver-509e9b7/test/discovery_and_monitoring/rs/normalize_case.json000066400000000000000000000020421462766011000320220ustar00rootroot00000000000000{ "description": "Replica set case normalization", "uri": "mongodb://A/?replicaSet=rs", "phases": [ { "responses": [ [ "a:27017", { "ok": 1, "helloOk": true, "isWritablePrimary": true, "setName": "rs", "hosts": [ "A:27017" ], "passives": [ "B:27017" ], "arbiters": [ "C:27017" ], "minWireVersion": 0, "maxWireVersion": 6 } ] ], "outcome": { "servers": { "a:27017": { "type": "RSPrimary", "setName": "rs" }, "b:27017": { "type": "Unknown", "setName": null }, "c:27017": { "type": "Unknown", "setName": null } }, "topologyType": "ReplicaSetWithPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } } ] } mongodb-mongo-python-driver-509e9b7/test/discovery_and_monitoring/rs/normalize_case_me.json000066400000000000000000000040711462766011000325070ustar00rootroot00000000000000{ "description": "Replica set mixed case normalization", "uri": "mongodb://A/?replicaSet=rs", "phases": [ { "responses": [ [ "a:27017", { "ok": 1, "helloOk": true, "isWritablePrimary": true, "setName": "rs", "me": "A:27017", "hosts": [ "A:27017" ], "passives": [ "B:27017" ], "arbiters": [ "C:27017" ], "minWireVersion": 0, "maxWireVersion": 6 } ] ], "outcome": { "servers": { "a:27017": { "type": "RSPrimary", "setName": "rs" }, "b:27017": { "type": "Unknown", "setName": null }, "c:27017": { "type": "Unknown", "setName": null } }, "topologyType": "ReplicaSetWithPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } }, { "responses": [ [ "b:27017", { "ok": 1, "helloOk": true, "isWritablePrimary": false, "secondary": true, "setName": "rs", "me": "B:27017", "hosts": [ "A:27017" ], "passives": [ "B:27017" ], "arbiters": [ "C:27017" ], "minWireVersion": 0, "maxWireVersion": 6 } ] ], "outcome": { "servers": { "a:27017": { "type": "RSPrimary", "setName": "rs" }, "b:27017": { "type": "RSSecondary", "setName": "rs" }, "c:27017": { "type": "Unknown", "setName": null } }, "topologyType": "ReplicaSetWithPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } } ] } mongodb-mongo-python-driver-509e9b7/test/discovery_and_monitoring/rs/null_election_id-pre-6.0.json000066400000000000000000000113201462766011000334230ustar00rootroot00000000000000{ "description": "Pre 6.0 Primaries with and without electionIds", "uri": "mongodb://a/?replicaSet=rs", "phases": [ { "responses": [ [ "a:27017", { "ok": 1, "helloOk": true, "isWritablePrimary": true, "hosts": [ "a:27017", "b:27017", "c:27017" ], "setVersion": 1, "setName": "rs", "minWireVersion": 0, "maxWireVersion": 6 } ] ], "outcome": { "servers": { "a:27017": { "type": "RSPrimary", "setName": "rs", "setVersion": 1, "electionId": null }, "b:27017": { "type": "Unknown", "setName": null, "electionId": null }, "c:27017": { "type": "Unknown", "setName": null, "electionId": null } }, "topologyType": "ReplicaSetWithPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs", "maxSetVersion": 1 } }, { "responses": [ [ "b:27017", { "ok": 1, "helloOk": true, "isWritablePrimary": true, "hosts": [ "a:27017", "b:27017", "c:27017" ], "setName": "rs", "setVersion": 1, "electionId": { "$oid": "000000000000000000000002" }, "minWireVersion": 0, "maxWireVersion": 6 } ] ], "outcome": { "servers": { "a:27017": { "type": "Unknown", "setName": null, "electionId": null }, "b:27017": { "type": "RSPrimary", "setName": "rs", "setVersion": 1, "electionId": { "$oid": "000000000000000000000002" } }, "c:27017": { "type": "Unknown", "setName": null, "electionId": null } }, "topologyType": "ReplicaSetWithPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs", "maxSetVersion": 1, "maxElectionId": { "$oid": "000000000000000000000002" } } }, { "responses": [ [ "a:27017", { "ok": 1, "helloOk": true, "isWritablePrimary": true, "hosts": [ "a:27017", "b:27017", "c:27017" ], "setVersion": 1, "setName": "rs", "minWireVersion": 0, "maxWireVersion": 6 } ] ], "outcome": { "servers": { "a:27017": { "type": "RSPrimary", "setName": "rs", "setVersion": 1, "electionId": null }, "b:27017": { "type": "Unknown", "setName": null, "electionId": null }, "c:27017": { "type": "Unknown", "setName": null, "electionId": null } }, "topologyType": "ReplicaSetWithPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs", "maxSetVersion": 1, "maxElectionId": { "$oid": "000000000000000000000002" } } }, { "responses": [ [ "c:27017", { "ok": 1, "helloOk": true, "isWritablePrimary": true, "hosts": [ "a:27017", "b:27017", "c:27017" ], "setName": "rs", "setVersion": 1, "electionId": { "$oid": "000000000000000000000001" }, "minWireVersion": 0, "maxWireVersion": 6 } ] ], "outcome": { "servers": { "a:27017": { "type": "RSPrimary", "setName": "rs", "setVersion": 1, "electionId": null }, "b:27017": { "type": "Unknown", "setName": null, "electionId": null }, "c:27017": { "type": "Unknown", "setName": null, "electionId": null } }, "topologyType": "ReplicaSetWithPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs", "maxSetVersion": 1, "maxElectionId": { "$oid": "000000000000000000000002" } } } ] } mongodb-mongo-python-driver-509e9b7/test/discovery_and_monitoring/rs/null_election_id.json000066400000000000000000000116041462766011000323430ustar00rootroot00000000000000{ "description": "Primaries with and without electionIds", "uri": "mongodb://a/?replicaSet=rs", "phases": [ { "responses": [ [ "a:27017", { "ok": 1, "helloOk": true, "isWritablePrimary": true, "hosts": [ "a:27017", "b:27017", "c:27017" ], "setVersion": 1, "setName": "rs", "minWireVersion": 0, "maxWireVersion": 17 } ] ], "outcome": { "servers": { "a:27017": { "type": "RSPrimary", "setName": "rs", "setVersion": 1, "electionId": null }, "b:27017": { "type": "Unknown", "setName": null, "electionId": null }, "c:27017": { "type": "Unknown", "setName": null, "electionId": null } }, "topologyType": "ReplicaSetWithPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs", "maxSetVersion": 1 } }, { "responses": [ [ "b:27017", { "ok": 1, "helloOk": true, "isWritablePrimary": true, "hosts": [ "a:27017", "b:27017", "c:27017" ], "setName": "rs", "setVersion": 1, "electionId": { "$oid": "000000000000000000000002" }, "minWireVersion": 0, "maxWireVersion": 17 } ] ], "outcome": { "servers": { "a:27017": { "type": "Unknown", "setName": null, "electionId": null }, "b:27017": { "type": "RSPrimary", "setName": "rs", "setVersion": 1, "electionId": { "$oid": "000000000000000000000002" } }, "c:27017": { "type": "Unknown", "setName": null, "electionId": null } }, "topologyType": "ReplicaSetWithPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs", "maxSetVersion": 1, "maxElectionId": { "$oid": "000000000000000000000002" } } }, { "responses": [ [ "a:27017", { "ok": 1, "helloOk": true, "isWritablePrimary": true, "hosts": [ "a:27017", "b:27017", "c:27017" ], "setVersion": 1, "setName": "rs", "minWireVersion": 0, "maxWireVersion": 17 } ] ], "outcome": { "servers": { "a:27017": { "type": "Unknown", "setName": null, "setVersion": null, "electionId": null }, "b:27017": { "type": "RSPrimary", "setName": "rs", "setVersion": 1, "electionId": { "$oid": "000000000000000000000002" } }, "c:27017": { "type": "Unknown", "setName": null, "electionId": null } }, "topologyType": "ReplicaSetWithPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs", "maxSetVersion": 1, "maxElectionId": { "$oid": "000000000000000000000002" } } }, { "responses": [ [ "c:27017", { "ok": 1, "helloOk": true, "isWritablePrimary": true, "hosts": [ "a:27017", "b:27017", "c:27017" ], "setName": "rs", "setVersion": 1, "electionId": { "$oid": "000000000000000000000001" }, "minWireVersion": 0, "maxWireVersion": 17 } ] ], "outcome": { "servers": { "a:27017": { "type": "Unknown", "setName": null, "setVersion": null, "electionId": null }, "b:27017": { "type": "RSPrimary", "setName": "rs", "setVersion": 1, "electionId": { "$oid": "000000000000000000000002" } }, "c:27017": { "type": "Unknown", "setName": null, "electionId": null } }, "topologyType": "ReplicaSetWithPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs", "maxSetVersion": 1, "maxElectionId": { "$oid": "000000000000000000000002" } } } ] } mongodb-mongo-python-driver-509e9b7/test/discovery_and_monitoring/rs/primary_becomes_ghost.json000066400000000000000000000024201462766011000334130ustar00rootroot00000000000000{ "description": "Primary becomes ghost", "uri": "mongodb://a/?replicaSet=rs", "phases": [ { "responses": [ [ "a:27017", { "ok": 1, "helloOk": true, "isWritablePrimary": true, "hosts": [ "a:27017" ], "setName": "rs", "minWireVersion": 0, "maxWireVersion": 6 } ] ], "outcome": { "servers": { "a:27017": { "type": "RSPrimary", "setName": "rs" } }, "topologyType": "ReplicaSetWithPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } }, { "responses": [ [ "a:27017", { "ok": 1, "helloOk": true, "isWritablePrimary": false, "isreplicaset": true, "minWireVersion": 0, "maxWireVersion": 6 } ] ], "outcome": { "servers": { "a:27017": { "type": "RSGhost", "setName": null } }, "topologyType": "ReplicaSetNoPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } } ] } mongodb-mongo-python-driver-509e9b7/test/discovery_and_monitoring/rs/primary_becomes_mongos.json000066400000000000000000000022461462766011000335770ustar00rootroot00000000000000{ "description": "Primary becomes mongos", "uri": "mongodb://a/?replicaSet=rs", "phases": [ { "responses": [ [ "a:27017", { "ok": 1, "helloOk": true, "isWritablePrimary": true, "hosts": [ "a:27017" ], "setName": "rs", "minWireVersion": 0, "maxWireVersion": 6 } ] ], "outcome": { "servers": { "a:27017": { "type": "RSPrimary", "setName": "rs" } }, "topologyType": "ReplicaSetWithPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } }, { "responses": [ [ "a:27017", { "ok": 1, "helloOk": true, "isWritablePrimary": true, "msg": "isdbgrid", "minWireVersion": 0, "maxWireVersion": 6 } ] ], "outcome": { "servers": {}, "topologyType": "ReplicaSetNoPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } } ] } mongodb-mongo-python-driver-509e9b7/test/discovery_and_monitoring/rs/primary_becomes_standalone.json000066400000000000000000000021071462766011000344210ustar00rootroot00000000000000{ "description": "Primary becomes standalone", "uri": "mongodb://a/?replicaSet=rs", "phases": [ { "responses": [ [ "a:27017", { "ok": 1, "helloOk": true, "isWritablePrimary": true, "hosts": [ "a:27017" ], "setName": "rs", "minWireVersion": 0, "maxWireVersion": 6 } ] ], "outcome": { "servers": { "a:27017": { "type": "RSPrimary", "setName": "rs" } }, "topologyType": "ReplicaSetWithPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } }, { "responses": [ [ "a:27017", { "ok": 1, "minWireVersion": 0, "maxWireVersion": 6 } ] ], "outcome": { "servers": {}, "topologyType": "ReplicaSetNoPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } } ] } mongodb-mongo-python-driver-509e9b7/test/discovery_and_monitoring/rs/primary_changes_set_name.json000066400000000000000000000023461462766011000340640ustar00rootroot00000000000000{ "description": "Primary changes setName", "uri": "mongodb://a/?replicaSet=rs", "phases": [ { "responses": [ [ "a:27017", { "ok": 1, "helloOk": true, "isWritablePrimary": true, "hosts": [ "a:27017" ], "setName": "rs", "minWireVersion": 0, "maxWireVersion": 6 } ] ], "outcome": { "servers": { "a:27017": { "type": "RSPrimary", "setName": "rs" } }, "topologyType": "ReplicaSetWithPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } }, { "responses": [ [ "a:27017", { "ok": 1, "helloOk": true, "isWritablePrimary": true, "hosts": [ "a:27017" ], "setName": "wrong", "minWireVersion": 0, "maxWireVersion": 6 } ] ], "outcome": { "servers": {}, "topologyType": "ReplicaSetNoPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } } ] } mongodb-mongo-python-driver-509e9b7/test/discovery_and_monitoring/rs/primary_disconnect.json000066400000000000000000000021141462766011000327230ustar00rootroot00000000000000{ "description": "Disconnected from primary", "uri": "mongodb://a/?replicaSet=rs", "phases": [ { "responses": [ [ "a:27017", { "ok": 1, "helloOk": true, "isWritablePrimary": true, "hosts": [ "a:27017" ], "setName": "rs", "minWireVersion": 0, "maxWireVersion": 6 } ] ], "outcome": { "servers": { "a:27017": { "type": "RSPrimary", "setName": "rs" } }, "topologyType": "ReplicaSetWithPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } }, { "responses": [ [ "a:27017", {} ] ], "outcome": { "servers": { "a:27017": { "type": "Unknown", "setName": null } }, "topologyType": "ReplicaSetNoPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } } ] } primary_disconnect_electionid.json000066400000000000000000000126641462766011000350560ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/discovery_and_monitoring/rs{ "description": "Disconnected from primary, reject primary with stale electionId", "uri": "mongodb://a/?replicaSet=rs", "phases": [ { "responses": [ [ "a:27017", { "ok": 1, "helloOk": true, "isWritablePrimary": true, "hosts": [ "a:27017", "b:27017" ], "setName": "rs", "setVersion": 1, "electionId": { "$oid": "000000000000000000000001" }, "minWireVersion": 0, "maxWireVersion": 6 } ], [ "b:27017", { "ok": 1, "helloOk": true, "isWritablePrimary": true, "hosts": [ "a:27017", "b:27017" ], "setName": "rs", "setVersion": 1, "electionId": { "$oid": "000000000000000000000002" }, "minWireVersion": 0, "maxWireVersion": 6 } ] ], "outcome": { "servers": { "a:27017": { "type": "Unknown", "setName": null, "electionId": null }, "b:27017": { "type": "RSPrimary", "setName": "rs", "setVersion": 1, "electionId": { "$oid": "000000000000000000000002" } } }, "topologyType": "ReplicaSetWithPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs", "maxSetVersion": 1, "maxElectionId": { "$oid": "000000000000000000000002" } } }, { "responses": [ [ "b:27017", {} ] ], "outcome": { "servers": { "a:27017": { "type": "Unknown", "setName": null, "electionId": null }, "b:27017": { "type": "Unknown", "setName": null, "electionId": null } }, "topologyType": "ReplicaSetNoPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs", "maxSetVersion": 1, "maxElectionId": { "$oid": "000000000000000000000002" } } }, { "responses": [ [ "a:27017", { "ok": 1, "helloOk": true, "isWritablePrimary": true, "hosts": [ "a:27017", "b:27017" ], "setName": "rs", "setVersion": 1, "electionId": { "$oid": "000000000000000000000001" }, "minWireVersion": 0, "maxWireVersion": 6 } ] ], "outcome": { "servers": { "a:27017": { "type": "Unknown", "setName": null, "electionId": null }, "b:27017": { "type": "Unknown", "setName": null, "electionId": null } }, "topologyType": "ReplicaSetNoPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs", "maxSetVersion": 1, "maxElectionId": { "$oid": "000000000000000000000002" } } }, { "responses": [ [ "a:27017", { "ok": 1, "helloOk": true, "isWritablePrimary": true, "hosts": [ "a:27017", "b:27017" ], "setName": "rs", "setVersion": 1, "electionId": { "$oid": "000000000000000000000003" }, "minWireVersion": 0, "maxWireVersion": 6 } ] ], "outcome": { "servers": { "a:27017": { "type": "RSPrimary", "setName": "rs", "setVersion": 1, "electionId": { "$oid": "000000000000000000000003" } }, "b:27017": { "type": "Unknown", "setName": null, "electionId": null } }, "topologyType": "ReplicaSetWithPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs", "maxSetVersion": 1, "maxElectionId": { "$oid": "000000000000000000000003" } } }, { "responses": [ [ "b:27017", { "ok": 1, "helloOk": true, "isWritablePrimary": false, "secondary": true, "hosts": [ "a:27017", "b:27017" ], "setName": "rs", "minWireVersion": 0, "maxWireVersion": 6 } ] ], "outcome": { "servers": { "a:27017": { "type": "RSPrimary", "setName": "rs", "setVersion": 1, "electionId": { "$oid": "000000000000000000000003" } }, "b:27017": { "type": "RSSecondary", "setName": "rs" } }, "topologyType": "ReplicaSetWithPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs", "maxSetVersion": 1, "maxElectionId": { "$oid": "000000000000000000000003" } } } ] } primary_disconnect_setversion.json000066400000000000000000000126641462766011000351400ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/discovery_and_monitoring/rs{ "description": "Disconnected from primary, reject primary with stale setVersion", "uri": "mongodb://a/?replicaSet=rs", "phases": [ { "responses": [ [ "a:27017", { "ok": 1, "helloOk": true, "isWritablePrimary": true, "hosts": [ "a:27017", "b:27017" ], "setName": "rs", "setVersion": 1, "electionId": { "$oid": "000000000000000000000001" }, "minWireVersion": 0, "maxWireVersion": 6 } ], [ "b:27017", { "ok": 1, "helloOk": true, "isWritablePrimary": true, "hosts": [ "a:27017", "b:27017" ], "setName": "rs", "setVersion": 2, "electionId": { "$oid": "000000000000000000000001" }, "minWireVersion": 0, "maxWireVersion": 6 } ] ], "outcome": { "servers": { "a:27017": { "type": "Unknown", "setName": null, "electionId": null }, "b:27017": { "type": "RSPrimary", "setName": "rs", "setVersion": 2, "electionId": { "$oid": "000000000000000000000001" } } }, "topologyType": "ReplicaSetWithPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs", "maxSetVersion": 2, "maxElectionId": { "$oid": "000000000000000000000001" } } }, { "responses": [ [ "b:27017", {} ] ], "outcome": { "servers": { "a:27017": { "type": "Unknown", "setName": null, "electionId": null }, "b:27017": { "type": "Unknown", "setName": null, "electionId": null } }, "topologyType": "ReplicaSetNoPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs", "maxSetVersion": 2, "maxElectionId": { "$oid": "000000000000000000000001" } } }, { "responses": [ [ "a:27017", { "ok": 1, "helloOk": true, "isWritablePrimary": true, "hosts": [ "a:27017", "b:27017" ], "setName": "rs", "setVersion": 1, "electionId": { "$oid": "000000000000000000000001" }, "minWireVersion": 0, "maxWireVersion": 6 } ] ], "outcome": { "servers": { "a:27017": { "type": "Unknown", "setName": null, "electionId": null }, "b:27017": { "type": "Unknown", "setName": null, "electionId": null } }, "topologyType": "ReplicaSetNoPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs", "maxSetVersion": 2, "maxElectionId": { "$oid": "000000000000000000000001" } } }, { "responses": [ [ "a:27017", { "ok": 1, "helloOk": true, "isWritablePrimary": true, "hosts": [ "a:27017", "b:27017" ], "setName": "rs", "setVersion": 2, "electionId": { "$oid": "000000000000000000000002" }, "minWireVersion": 0, "maxWireVersion": 6 } ] ], "outcome": { "servers": { "a:27017": { "type": "RSPrimary", "setName": "rs", "setVersion": 2, "electionId": { "$oid": "000000000000000000000002" } }, "b:27017": { "type": "Unknown", "setName": null, "electionId": null } }, "topologyType": "ReplicaSetWithPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs", "maxSetVersion": 2, "maxElectionId": { "$oid": "000000000000000000000002" } } }, { "responses": [ [ "b:27017", { "ok": 1, "helloOk": true, "isWritablePrimary": false, "secondary": true, "hosts": [ "a:27017", "b:27017" ], "setName": "rs", "minWireVersion": 0, "maxWireVersion": 6 } ] ], "outcome": { "servers": { "a:27017": { "type": "RSPrimary", "setName": "rs", "setVersion": 2, "electionId": { "$oid": "000000000000000000000002" } }, "b:27017": { "type": "RSSecondary", "setName": "rs" } }, "topologyType": "ReplicaSetWithPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs", "maxSetVersion": 2, "maxElectionId": { "$oid": "000000000000000000000002" } } } ] } primary_hint_from_secondary_with_mismatched_me.json000066400000000000000000000027611462766011000404710ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/discovery_and_monitoring/rs{ "description": "Secondary with mismatched 'me' tells us who the primary is", "uri": "mongodb://a/?replicaSet=rs", "phases": [ { "responses": [ [ "a:27017", { "ok": 1, "helloOk": true, "isWritablePrimary": false, "secondary": true, "me": "c:27017", "hosts": [ "b:27017" ], "setName": "rs", "primary": "b:27017", "minWireVersion": 0, "maxWireVersion": 6 } ] ], "outcome": { "servers": { "b:27017": { "type": "PossiblePrimary", "setName": null } }, "topologyType": "ReplicaSetNoPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } }, { "responses": [ [ "b:27017", { "ok": 1, "helloOk": true, "isWritablePrimary": true, "me": "b:27017", "hosts": [ "b:27017" ], "setName": "rs", "minWireVersion": 0, "maxWireVersion": 6 } ] ], "outcome": { "servers": { "b:27017": { "type": "RSPrimary", "setName": "rs" } }, "topologyType": "ReplicaSetWithPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } } ] } mongodb-mongo-python-driver-509e9b7/test/discovery_and_monitoring/rs/primary_mismatched_me.json000066400000000000000000000016001462766011000333700ustar00rootroot00000000000000{ "description": "Primary mismatched me", "phases": [ { "outcome": { "servers": { "a:27017": { "setName": null, "type": "Unknown" }, "b:27017": { "setName": null, "type": "Unknown" } }, "setName": "rs", "topologyType": "ReplicaSetNoPrimary", "logicalSessionTimeoutMinutes": null }, "responses": [ [ "localhost:27017", { "me": "a:27017", "hosts": [ "a:27017", "b:27017" ], "helloOk": true, "isWritablePrimary": true, "ok": 1, "setName": "rs", "minWireVersion": 0, "maxWireVersion": 6 } ] ] } ], "uri": "mongodb://localhost:27017/?replicaSet=rs" } primary_mismatched_me_not_removed.json000066400000000000000000000035631462766011000357240ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/discovery_and_monitoring/rs{ "description": "Primary mismatched me is not removed", "uri": "mongodb://localhost:27017,localhost:27018/?replicaSet=rs", "phases": [ { "responses": [ [ "localhost:27017", { "ok": 1, "hosts": [ "localhost:27017", "localhost:27018" ], "helloOk": true, "isWritablePrimary": true, "setName": "rs", "primary": "localhost:27017", "me": "a:27017", "minWireVersion": 0, "maxWireVersion": 7 } ] ], "outcome": { "servers": { "localhost:27017": { "type": "RSPrimary", "setName": "rs" }, "localhost:27018": { "type": "Unknown", "setName": null } }, "topologyType": "ReplicaSetWithPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } }, { "responses": [ [ "localhost:27018", { "ok": 1, "hosts": [ "localhost:27017", "localhost:27018" ], "helloOk": true, "isWritablePrimary": false, "secondary": true, "setName": "rs", "primary": "localhost:27017", "me": "localhost:27018", "minWireVersion": 0, "maxWireVersion": 7 } ] ], "outcome": { "servers": { "localhost:27017": { "type": "RSPrimary", "setName": "rs" }, "localhost:27018": { "type": "RSSecondary", "setName": "rs" } }, "topologyType": "ReplicaSetWithPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } } ] } mongodb-mongo-python-driver-509e9b7/test/discovery_and_monitoring/rs/primary_reports_new_member.json000066400000000000000000000065731462766011000345050ustar00rootroot00000000000000{ "description": "Primary reports a new member", "uri": "mongodb://a/?replicaSet=rs", "phases": [ { "responses": [ [ "a:27017", { "ok": 1, "helloOk": true, "isWritablePrimary": false, "secondary": true, "setName": "rs", "hosts": [ "a:27017", "b:27017" ], "minWireVersion": 0, "maxWireVersion": 6 } ] ], "outcome": { "servers": { "a:27017": { "type": "RSSecondary", "setName": "rs" }, "b:27017": { "type": "Unknown", "setName": null } }, "topologyType": "ReplicaSetNoPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } }, { "responses": [ [ "b:27017", { "ok": 1, "helloOk": true, "isWritablePrimary": true, "setName": "rs", "hosts": [ "a:27017", "b:27017" ], "minWireVersion": 0, "maxWireVersion": 6 } ] ], "outcome": { "servers": { "a:27017": { "type": "RSSecondary", "setName": "rs" }, "b:27017": { "type": "RSPrimary", "setName": "rs" } }, "topologyType": "ReplicaSetWithPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } }, { "responses": [ [ "b:27017", { "ok": 1, "helloOk": true, "isWritablePrimary": true, "setName": "rs", "hosts": [ "a:27017", "b:27017", "c:27017" ], "minWireVersion": 0, "maxWireVersion": 6 } ] ], "outcome": { "servers": { "a:27017": { "type": "RSSecondary", "setName": "rs" }, "b:27017": { "type": "RSPrimary", "setName": "rs" }, "c:27017": { "type": "Unknown", "setName": null } }, "topologyType": "ReplicaSetWithPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } }, { "responses": [ [ "c:27017", { "ok": 1, "helloOk": true, "isWritablePrimary": false, "secondary": true, "setName": "rs", "primary": "b:27017", "hosts": [ "a:27017", "b:27017", "c:27017" ], "minWireVersion": 0, "maxWireVersion": 6 } ] ], "outcome": { "servers": { "a:27017": { "type": "RSSecondary", "setName": "rs" }, "b:27017": { "type": "RSPrimary", "setName": "rs" }, "c:27017": { "type": "RSSecondary", "setName": "rs" } }, "topologyType": "ReplicaSetWithPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } } ] } primary_to_no_primary_mismatched_me.json000066400000000000000000000032051462766011000362550ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/discovery_and_monitoring/rs{ "description": "Primary to no primary with mismatched me", "uri": "mongodb://a/?replicaSet=rs", "phases": [ { "responses": [ [ "a:27017", { "ok": 1, "helloOk": true, "isWritablePrimary": true, "hosts": [ "a:27017", "b:27017" ], "me": "a:27017", "setName": "rs", "minWireVersion": 0, "maxWireVersion": 6 } ] ], "outcome": { "servers": { "a:27017": { "type": "RSPrimary", "setName": "rs" }, "b:27017": { "type": "Unknown", "setName": null } }, "topologyType": "ReplicaSetWithPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } }, { "responses": [ [ "a:27017", { "ok": 1, "helloOk": true, "isWritablePrimary": true, "hosts": [ "c:27017", "d:27017" ], "me": "c:27017", "setName": "rs", "minWireVersion": 0, "maxWireVersion": 6 } ] ], "outcome": { "servers": { "c:27017": { "type": "Unknown", "setName": null }, "d:27017": { "type": "Unknown", "setName": null } }, "topologyType": "ReplicaSetNoPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } } ] } mongodb-mongo-python-driver-509e9b7/test/discovery_and_monitoring/rs/primary_wrong_set_name.json000066400000000000000000000011611462766011000336020ustar00rootroot00000000000000{ "description": "Primary wrong setName", "uri": "mongodb://a/?replicaSet=rs", "phases": [ { "responses": [ [ "a:27017", { "ok": 1, "helloOk": true, "isWritablePrimary": true, "hosts": [ "a:27017" ], "setName": "wrong", "minWireVersion": 0, "maxWireVersion": 6 } ] ], "outcome": { "servers": {}, "topologyType": "ReplicaSetNoPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } } ] } mongodb-mongo-python-driver-509e9b7/test/discovery_and_monitoring/rs/repeated.json000066400000000000000000000061311462766011000306230ustar00rootroot00000000000000{ "description": "Repeated isWritablePrimary response must be processed", "uri": "mongodb://a,b/?replicaSet=rs", "phases": [ { "responses": [ [ "a:27017", { "ok": 1, "helloOk": true, "isWritablePrimary": false, "secondary": true, "hidden": true, "hosts": [ "a:27017", "c:27017" ], "setName": "rs", "minWireVersion": 0, "maxWireVersion": 6 } ] ], "outcome": { "servers": { "a:27017": { "type": "RSOther", "setName": "rs" }, "b:27017": { "type": "Unknown" }, "c:27017": { "type": "Unknown" } }, "topologyType": "ReplicaSetNoPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } }, { "responses": [ [ "c:27017", { "ok": 1, "helloOk": true, "isWritablePrimary": true, "minWireVersion": 0, "maxWireVersion": 6 } ] ], "outcome": { "servers": { "a:27017": { "type": "RSOther", "setName": "rs" }, "b:27017": { "type": "Unknown" } }, "topologyType": "ReplicaSetNoPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } }, { "responses": [ [ "a:27017", { "ok": 1, "helloOk": true, "isWritablePrimary": false, "secondary": true, "hidden": true, "hosts": [ "a:27017", "c:27017" ], "setName": "rs", "minWireVersion": 0, "maxWireVersion": 6 } ] ], "outcome": { "servers": { "a:27017": { "type": "RSOther", "setName": "rs" }, "b:27017": { "type": "Unknown" }, "c:27017": { "type": "Unknown" } }, "topologyType": "ReplicaSetNoPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } }, { "responses": [ [ "c:27017", { "ok": 1, "helloOk": true, "isWritablePrimary": true, "hosts": [ "a:27017", "c:27017" ], "setName": "rs", "minWireVersion": 0, "maxWireVersion": 6 } ] ], "outcome": { "servers": { "a:27017": { "type": "RSOther", "setName": "rs" }, "c:27017": { "type": "RSPrimary", "setName": "rs" } }, "topologyType": "ReplicaSetWithPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } } ] } mongodb-mongo-python-driver-509e9b7/test/discovery_and_monitoring/rs/replicaset_rsnp.json000066400000000000000000000011161462766011000322250ustar00rootroot00000000000000{ "description": "replicaSet URI option causes starting topology to be RSNP", "uri": "mongodb://a/?replicaSet=rs&directConnection=false", "phases": [ { "responses": [ [ "a:27017", { "ok": 1, "helloOk": true, "isWritablePrimary": true, "minWireVersion": 0, "maxWireVersion": 6 } ] ], "outcome": { "servers": {}, "topologyType": "ReplicaSetNoPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } } ] } mongodb-mongo-python-driver-509e9b7/test/discovery_and_monitoring/rs/response_from_removed.json000066400000000000000000000026161462766011000334400ustar00rootroot00000000000000{ "description": "Response from removed server", "uri": "mongodb://a,b/?replicaSet=rs", "phases": [ { "responses": [ [ "a:27017", { "ok": 1, "helloOk": true, "isWritablePrimary": true, "setName": "rs", "hosts": [ "a:27017" ], "minWireVersion": 0, "maxWireVersion": 6 } ] ], "outcome": { "servers": { "a:27017": { "type": "RSPrimary", "setName": "rs" } }, "topologyType": "ReplicaSetWithPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } }, { "responses": [ [ "b:27017", { "ok": 1, "helloOk": true, "isWritablePrimary": false, "secondary": true, "setName": "rs", "hosts": [ "a:27017", "b:27017" ], "minWireVersion": 0, "maxWireVersion": 6 } ] ], "outcome": { "servers": { "a:27017": { "type": "RSPrimary", "setName": "rs" } }, "topologyType": "ReplicaSetWithPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } } ] } mongodb-mongo-python-driver-509e9b7/test/discovery_and_monitoring/rs/sec_not_auth.json000066400000000000000000000023321462766011000315040ustar00rootroot00000000000000{ "description": "Secondary's host list is not authoritative", "uri": "mongodb://a/?replicaSet=rs", "phases": [ { "responses": [ [ "a:27017", { "ok": 1, "helloOk": true, "isWritablePrimary": true, "setName": "rs", "hosts": [ "a:27017", "b:27017" ], "minWireVersion": 0, "maxWireVersion": 6 } ], [ "b:27017", { "ok": 1, "helloOk": true, "isWritablePrimary": false, "secondary": true, "setName": "rs", "hosts": [ "b:27017", "c:27017" ], "minWireVersion": 0, "maxWireVersion": 6 } ] ], "outcome": { "servers": { "a:27017": { "type": "RSPrimary", "setName": "rs" }, "b:27017": { "type": "RSSecondary", "setName": "rs" } }, "topologyType": "ReplicaSetWithPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } } ] } secondary_ignore_ok_0-pre-6.0.json000066400000000000000000000033701462766011000343040ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/discovery_and_monitoring/rs{ "description": "Pre 6.0 New primary", "uri": "mongodb://a,b/?replicaSet=rs", "phases": [ { "responses": [ [ "a:27017", { "ok": 1, "helloOk": true, "isWritablePrimary": true, "setName": "rs", "hosts": [ "a:27017", "b:27017" ], "minWireVersion": 0, "maxWireVersion": 6 } ], [ "b:27017", { "ok": 1, "helloOk": true, "isWritablePrimary": false, "secondary": true, "setName": "rs", "hosts": [ "a:27017", "b:27017" ], "minWireVersion": 0, "maxWireVersion": 6 } ] ], "outcome": { "servers": { "a:27017": { "type": "RSPrimary", "setName": "rs" }, "b:27017": { "type": "RSSecondary", "setName": "rs" } }, "topologyType": "ReplicaSetWithPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } }, { "responses": [ [ "b:27017", { "ok": 0, "minWireVersion": 0, "maxWireVersion": 6 } ] ], "outcome": { "servers": { "a:27017": { "type": "RSPrimary", "setName": "rs" }, "b:27017": { "type": "Unknown", "setName": null } }, "topologyType": "ReplicaSetWithPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } } ] } mongodb-mongo-python-driver-509e9b7/test/discovery_and_monitoring/rs/secondary_ignore_ok_0.json000066400000000000000000000034061462766011000332760ustar00rootroot00000000000000{ "description": "Secondary ignored when ok is zero", "uri": "mongodb://a,b/?replicaSet=rs", "phases": [ { "responses": [ [ "a:27017", { "ok": 1, "helloOk": true, "isWritablePrimary": true, "setName": "rs", "hosts": [ "a:27017", "b:27017" ], "minWireVersion": 0, "maxWireVersion": 6 } ], [ "b:27017", { "ok": 1, "helloOk": true, "isWritablePrimary": false, "secondary": true, "setName": "rs", "hosts": [ "a:27017", "b:27017" ], "minWireVersion": 0, "maxWireVersion": 6 } ] ], "outcome": { "servers": { "a:27017": { "type": "RSPrimary", "setName": "rs" }, "b:27017": { "type": "RSSecondary", "setName": "rs" } }, "topologyType": "ReplicaSetWithPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } }, { "responses": [ [ "b:27017", { "ok": 0, "minWireVersion": 0, "maxWireVersion": 6 } ] ], "outcome": { "servers": { "a:27017": { "type": "RSPrimary", "setName": "rs" }, "b:27017": { "type": "Unknown", "setName": null } }, "topologyType": "ReplicaSetWithPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } } ] } mongodb-mongo-python-driver-509e9b7/test/discovery_and_monitoring/rs/secondary_mismatched_me.json000066400000000000000000000016031462766011000336770ustar00rootroot00000000000000{ "description": "Secondary mismatched me", "uri": "mongodb://localhost:27017/?replicaSet=rs", "phases": [ { "outcome": { "servers": { "a:27017": { "setName": null, "type": "Unknown" }, "b:27017": { "setName": null, "type": "Unknown" } }, "setName": "rs", "topologyType": "ReplicaSetNoPrimary", "logicalSessionTimeoutMinutes": null }, "responses": [ [ "localhost:27017", { "me": "a:27017", "hosts": [ "a:27017", "b:27017" ], "helloOk": true, "isWritablePrimary": false, "ok": 1, "setName": "rs", "minWireVersion": 0, "maxWireVersion": 6 } ] ] } ] } mongodb-mongo-python-driver-509e9b7/test/discovery_and_monitoring/rs/secondary_wrong_set_name.json000066400000000000000000000012231462766011000341050ustar00rootroot00000000000000{ "description": "Secondary wrong setName", "uri": "mongodb://a/?replicaSet=rs", "phases": [ { "responses": [ [ "a:27017", { "ok": 1, "helloOk": true, "isWritablePrimary": false, "secondary": true, "hosts": [ "a:27017" ], "setName": "wrong", "minWireVersion": 0, "maxWireVersion": 6 } ] ], "outcome": { "servers": {}, "topologyType": "ReplicaSetNoPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } } ] } secondary_wrong_set_name_with_primary.json000066400000000000000000000030211462766011000366220ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/discovery_and_monitoring/rs{ "description": "Secondary wrong setName with primary", "uri": "mongodb://a,b/?replicaSet=rs", "phases": [ { "responses": [ [ "a:27017", { "ok": 1, "helloOk": true, "isWritablePrimary": true, "hosts": [ "a:27017", "b:27017" ], "setName": "rs", "minWireVersion": 0, "maxWireVersion": 6 } ] ], "outcome": { "servers": { "a:27017": { "type": "RSPrimary", "setName": "rs" }, "b:27017": { "type": "Unknown", "setName": null } }, "topologyType": "ReplicaSetWithPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } }, { "responses": [ [ "b:27017", { "ok": 1, "helloOk": true, "isWritablePrimary": false, "secondary": true, "hosts": [ "a:27017", "b:27017" ], "setName": "wrong", "minWireVersion": 0, "maxWireVersion": 6 } ] ], "outcome": { "servers": { "a:27017": { "type": "RSPrimary", "setName": "rs" } }, "topologyType": "ReplicaSetWithPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } } ] } mongodb-mongo-python-driver-509e9b7/test/discovery_and_monitoring/rs/set_version_can_rollback.json000066400000000000000000000067301462766011000340710ustar00rootroot00000000000000{ "description": "Set version rolls back after new primary with higher election Id", "uri": "mongodb://a/?replicaSet=rs", "phases": [ { "responses": [ [ "a:27017", { "ok": 1, "helloOk": true, "isWritablePrimary": true, "hosts": [ "a:27017", "b:27017" ], "setName": "rs", "setVersion": 2, "electionId": { "$oid": "000000000000000000000001" }, "minWireVersion": 0, "maxWireVersion": 17 } ] ], "outcome": { "servers": { "a:27017": { "type": "RSPrimary", "setName": "rs", "setVersion": 2, "electionId": { "$oid": "000000000000000000000001" } }, "b:27017": { "type": "Unknown", "setName": null, "electionId": null } }, "topologyType": "ReplicaSetWithPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs", "maxSetVersion": 2, "maxElectionId": { "$oid": "000000000000000000000001" } } }, { "responses": [ [ "b:27017", { "ok": 1, "helloOk": true, "isWritablePrimary": true, "hosts": [ "a:27017", "b:27017" ], "setName": "rs", "setVersion": 1, "electionId": { "$oid": "000000000000000000000002" }, "minWireVersion": 0, "maxWireVersion": 17 } ] ], "outcome": { "servers": { "a:27017": { "type": "Unknown", "setName": null, "electionId": null }, "b:27017": { "type": "RSPrimary", "setName": "rs", "setVersion": 1, "electionId": { "$oid": "000000000000000000000002" } } }, "topologyType": "ReplicaSetWithPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs", "maxSetVersion": 1, "maxElectionId": { "$oid": "000000000000000000000002" } } }, { "responses": [ [ "a:27017", { "ok": 1, "helloOk": true, "isWritablePrimary": true, "hosts": [ "a:27017", "b:27017" ], "setName": "rs", "setVersion": 2, "electionId": { "$oid": "000000000000000000000001" }, "minWireVersion": 0, "maxWireVersion": 17 } ] ], "outcome": { "servers": { "a:27017": { "type": "Unknown", "setName": null, "electionId": null }, "b:27017": { "type": "RSPrimary", "setName": "rs", "setVersion": 1, "electionId": { "$oid": "000000000000000000000002" } } }, "topologyType": "ReplicaSetWithPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs", "maxSetVersion": 1, "maxElectionId": { "$oid": "000000000000000000000002" } } } ] } setversion_equal_max_without_electionid.json000066400000000000000000000036631462766011000372010ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/discovery_and_monitoring/rs{ "description": "setVersion version that is equal is treated the same as greater than if there is no electionId", "uri": "mongodb://a/?replicaSet=rs", "phases": [ { "responses": [ [ "a:27017", { "ok": 1, "helloOk": true, "isWritablePrimary": true, "hosts": [ "a:27017", "b:27017" ], "setName": "rs", "setVersion": 1, "minWireVersion": 0, "maxWireVersion": 17 } ] ], "outcome": { "servers": { "a:27017": { "type": "RSPrimary", "setName": "rs", "setVersion": 1, "electionId": null }, "b:27017": { "type": "Unknown", "setName": null, "electionId": null } }, "topologyType": "ReplicaSetWithPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs", "maxSetVersion": 1 } }, { "responses": [ [ "b:27017", { "ok": 1, "helloOk": true, "isWritablePrimary": true, "hosts": [ "a:27017", "b:27017" ], "setName": "rs", "setVersion": 1, "minWireVersion": 0, "maxWireVersion": 17 } ] ], "outcome": { "servers": { "a:27017": { "type": "Unknown", "setName": null, "electionId": null }, "b:27017": { "type": "RSPrimary", "setName": "rs", "setVersion": 1, "electionId": null } }, "topologyType": "ReplicaSetWithPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs", "maxSetVersion": 1 } } ] } setversion_greaterthan_max_without_electionid.json000066400000000000000000000036441462766011000403750ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/discovery_and_monitoring/rs{ "description": "setVersion that is greater than maxSetVersion is used if there is no electionId", "uri": "mongodb://a/?replicaSet=rs", "phases": [ { "responses": [ [ "a:27017", { "ok": 1, "helloOk": true, "isWritablePrimary": true, "hosts": [ "a:27017", "b:27017" ], "setName": "rs", "setVersion": 1, "minWireVersion": 0, "maxWireVersion": 17 } ] ], "outcome": { "servers": { "a:27017": { "type": "RSPrimary", "setName": "rs", "setVersion": 1, "electionId": null }, "b:27017": { "type": "Unknown", "setName": null, "electionId": null } }, "topologyType": "ReplicaSetWithPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs", "maxSetVersion": 1 } }, { "responses": [ [ "b:27017", { "ok": 1, "helloOk": true, "isWritablePrimary": true, "hosts": [ "a:27017", "b:27017" ], "setName": "rs", "setVersion": 2, "minWireVersion": 0, "maxWireVersion": 17 } ] ], "outcome": { "servers": { "a:27017": { "type": "Unknown", "setName": null, "electionId": null }, "b:27017": { "type": "RSPrimary", "setName": "rs", "setVersion": 2, "electionId": null } }, "topologyType": "ReplicaSetWithPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs", "maxSetVersion": 2 } } ] } setversion_without_electionid-pre-6.0.json000066400000000000000000000036121462766011000362240ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/discovery_and_monitoring/rs{ "description": "Pre 6.0 setVersion is ignored if there is no electionId", "uri": "mongodb://a/?replicaSet=rs", "phases": [ { "responses": [ [ "a:27017", { "ok": 1, "helloOk": true, "isWritablePrimary": true, "hosts": [ "a:27017", "b:27017" ], "setName": "rs", "setVersion": 2, "minWireVersion": 0, "maxWireVersion": 6 } ] ], "outcome": { "servers": { "a:27017": { "type": "RSPrimary", "setName": "rs", "setVersion": 2, "electionId": null }, "b:27017": { "type": "Unknown", "setName": null, "electionId": null } }, "topologyType": "ReplicaSetWithPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs", "maxSetVersion": 2 } }, { "responses": [ [ "b:27017", { "ok": 1, "helloOk": true, "isWritablePrimary": true, "hosts": [ "a:27017", "b:27017" ], "setName": "rs", "setVersion": 1, "minWireVersion": 0, "maxWireVersion": 6 } ] ], "outcome": { "servers": { "a:27017": { "type": "Unknown", "setName": null, "electionId": null }, "b:27017": { "type": "RSPrimary", "setName": "rs", "setVersion": 1, "electionId": null } }, "topologyType": "ReplicaSetWithPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs", "maxSetVersion": 2 } } ] } setversion_without_electionid.json000066400000000000000000000036441462766011000351440ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/discovery_and_monitoring/rs{ "description": "setVersion that is less than maxSetVersion is ignored if there is no electionId", "uri": "mongodb://a/?replicaSet=rs", "phases": [ { "responses": [ [ "a:27017", { "ok": 1, "helloOk": true, "isWritablePrimary": true, "hosts": [ "a:27017", "b:27017" ], "setName": "rs", "setVersion": 2, "minWireVersion": 0, "maxWireVersion": 17 } ] ], "outcome": { "servers": { "a:27017": { "type": "RSPrimary", "setName": "rs", "setVersion": 2, "electionId": null }, "b:27017": { "type": "Unknown", "setName": null, "electionId": null } }, "topologyType": "ReplicaSetWithPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs", "maxSetVersion": 2 } }, { "responses": [ [ "b:27017", { "ok": 1, "helloOk": true, "isWritablePrimary": true, "hosts": [ "a:27017", "b:27017" ], "setName": "rs", "setVersion": 1, "minWireVersion": 0, "maxWireVersion": 17 } ] ], "outcome": { "servers": { "a:27017": { "type": "RSPrimary", "setName": "rs", "setVersion": 2, "electionId": null }, "b:27017": { "type": "Unknown", "setName": null, "electionId": null } }, "topologyType": "ReplicaSetWithPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs", "maxSetVersion": 2 } } ] } mongodb-mongo-python-driver-509e9b7/test/discovery_and_monitoring/rs/stepdown_change_set_name.json000066400000000000000000000024351462766011000340600ustar00rootroot00000000000000{ "description": "Primary becomes a secondary with wrong setName", "uri": "mongodb://a/?replicaSet=rs", "phases": [ { "responses": [ [ "a:27017", { "ok": 1, "helloOk": true, "isWritablePrimary": true, "hosts": [ "a:27017" ], "setName": "rs", "minWireVersion": 0, "maxWireVersion": 6 } ] ], "outcome": { "servers": { "a:27017": { "type": "RSPrimary", "setName": "rs" } }, "topologyType": "ReplicaSetWithPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } }, { "responses": [ [ "a:27017", { "ok": 1, "helloOk": true, "isWritablePrimary": false, "secondary": true, "hosts": [ "a:27017" ], "setName": "wrong", "minWireVersion": 0, "maxWireVersion": 6 } ] ], "outcome": { "servers": {}, "topologyType": "ReplicaSetNoPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } } ] } mongodb-mongo-python-driver-509e9b7/test/discovery_and_monitoring/rs/too_new.json000066400000000000000000000024001462766011000304770ustar00rootroot00000000000000{ "description": "Replica set member with large minWireVersion", "uri": "mongodb://a,b/?replicaSet=rs", "phases": [ { "responses": [ [ "a:27017", { "ok": 1, "helloOk": true, "isWritablePrimary": true, "setName": "rs", "hosts": [ "a:27017", "b:27017" ], "minWireVersion": 0, "maxWireVersion": 6 } ], [ "b:27017", { "ok": 1, "helloOk": true, "isWritablePrimary": false, "secondary": true, "setName": "rs", "hosts": [ "a:27017", "b:27017" ], "minWireVersion": 999, "maxWireVersion": 1000 } ] ], "outcome": { "servers": { "a:27017": { "type": "RSPrimary", "setName": "rs" }, "b:27017": { "type": "RSSecondary", "setName": "rs" } }, "topologyType": "ReplicaSetWithPrimary", "setName": "rs", "logicalSessionTimeoutMinutes": null, "compatible": false } } ] } mongodb-mongo-python-driver-509e9b7/test/discovery_and_monitoring/rs/too_old.json000066400000000000000000000023001462766011000304630ustar00rootroot00000000000000{ "description": "Replica set member with default maxWireVersion of 0", "uri": "mongodb://a,b/?replicaSet=rs", "phases": [ { "responses": [ [ "a:27017", { "ok": 1, "helloOk": true, "isWritablePrimary": true, "setName": "rs", "hosts": [ "a:27017", "b:27017" ], "minWireVersion": 0, "maxWireVersion": 6 } ], [ "b:27017", { "ok": 1, "helloOk": true, "isWritablePrimary": false, "secondary": true, "setName": "rs", "hosts": [ "a:27017", "b:27017" ] } ] ], "outcome": { "servers": { "a:27017": { "type": "RSPrimary", "setName": "rs" }, "b:27017": { "type": "RSSecondary", "setName": "rs" } }, "topologyType": "ReplicaSetWithPrimary", "setName": "rs", "logicalSessionTimeoutMinutes": null, "compatible": false } } ] } mongodb-mongo-python-driver-509e9b7/test/discovery_and_monitoring/rs/topology_version_equal.json000066400000000000000000000045251462766011000336470ustar00rootroot00000000000000{ "description": "Primary with equal topologyVersion", "uri": "mongodb://a/?replicaSet=rs", "phases": [ { "responses": [ [ "a:27017", { "ok": 1, "helloOk": true, "isWritablePrimary": true, "hosts": [ "a:27017" ], "setName": "rs", "minWireVersion": 0, "maxWireVersion": 9, "topologyVersion": { "processId": { "$oid": "000000000000000000000001" }, "counter": { "$numberLong": "1" } } } ] ], "outcome": { "servers": { "a:27017": { "type": "RSPrimary", "setName": "rs", "topologyVersion": { "processId": { "$oid": "000000000000000000000001" }, "counter": { "$numberLong": "1" } } } }, "topologyType": "ReplicaSetWithPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } }, { "responses": [ [ "a:27017", { "ok": 1, "helloOk": true, "isWritablePrimary": true, "hosts": [ "a:27017", "b:27017" ], "setName": "rs", "minWireVersion": 0, "maxWireVersion": 9, "topologyVersion": { "processId": { "$oid": "000000000000000000000001" }, "counter": { "$numberLong": "1" } } } ] ], "outcome": { "servers": { "a:27017": { "type": "RSPrimary", "setName": "rs", "topologyVersion": { "processId": { "$oid": "000000000000000000000001" }, "counter": { "$numberLong": "1" } } }, "b:27017": { "type": "Unknown", "topologyVersion": null } }, "topologyType": "ReplicaSetWithPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } } ] } mongodb-mongo-python-driver-509e9b7/test/discovery_and_monitoring/rs/topology_version_greater.json000066400000000000000000000136551462766011000341750ustar00rootroot00000000000000{ "description": "Primary with newer topologyVersion", "uri": "mongodb://a/?replicaSet=rs", "phases": [ { "responses": [ [ "a:27017", { "ok": 1, "helloOk": true, "isWritablePrimary": true, "hosts": [ "a:27017" ], "setName": "rs", "minWireVersion": 0, "maxWireVersion": 9, "topologyVersion": { "processId": { "$oid": "000000000000000000000001" }, "counter": { "$numberLong": "1" } } } ] ], "outcome": { "servers": { "a:27017": { "type": "RSPrimary", "setName": "rs", "topologyVersion": { "processId": { "$oid": "000000000000000000000001" }, "counter": { "$numberLong": "1" } } } }, "topologyType": "ReplicaSetWithPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } }, { "responses": [ [ "a:27017", { "ok": 1, "helloOk": true, "isWritablePrimary": true, "hosts": [ "a:27017", "b:27017" ], "setName": "rs", "minWireVersion": 0, "maxWireVersion": 9, "topologyVersion": { "processId": { "$oid": "000000000000000000000001" }, "counter": { "$numberLong": "2" } } } ] ], "outcome": { "servers": { "a:27017": { "type": "RSPrimary", "setName": "rs", "topologyVersion": { "processId": { "$oid": "000000000000000000000001" }, "counter": { "$numberLong": "2" } } }, "b:27017": { "type": "Unknown", "topologyVersion": null } }, "topologyType": "ReplicaSetWithPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } }, { "responses": [ [ "a:27017", { "ok": 1, "helloOk": true, "isWritablePrimary": true, "hosts": [ "a:27017", "c:27017" ], "setName": "rs", "minWireVersion": 0, "maxWireVersion": 9, "topologyVersion": { "processId": { "$oid": "000000000000000000000002" }, "counter": { "$numberLong": "0" } } } ] ], "outcome": { "servers": { "a:27017": { "type": "RSPrimary", "setName": "rs", "topologyVersion": { "processId": { "$oid": "000000000000000000000002" }, "counter": { "$numberLong": "0" } } }, "c:27017": { "type": "Unknown", "topologyVersion": null } }, "topologyType": "ReplicaSetWithPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } }, { "responses": [ [ "a:27017", { "ok": 1, "helloOk": true, "isWritablePrimary": true, "hosts": [ "a:27017", "d:27017" ], "setName": "rs", "minWireVersion": 0, "maxWireVersion": 9 } ] ], "outcome": { "servers": { "a:27017": { "type": "RSPrimary", "setName": "rs", "topologyVersion": null }, "d:27017": { "type": "Unknown", "topologyVersion": null } }, "topologyType": "ReplicaSetWithPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } }, { "responses": [ [ "a:27017", { "ok": 1, "helloOk": true, "isWritablePrimary": true, "hosts": [ "a:27017", "e:27017" ], "setName": "rs", "minWireVersion": 0, "maxWireVersion": 9, "topologyVersion": { "processId": { "$oid": "000000000000000000000003" }, "counter": { "$numberLong": "0" } } } ] ], "outcome": { "servers": { "a:27017": { "type": "RSPrimary", "setName": "rs", "topologyVersion": { "processId": { "$oid": "000000000000000000000003" }, "counter": { "$numberLong": "0" } } }, "e:27017": { "type": "Unknown", "topologyVersion": null } }, "topologyType": "ReplicaSetWithPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } }, { "responses": [ [ "a:27017", {} ] ], "outcome": { "servers": { "a:27017": { "type": "Unknown", "topologyVersion": null }, "e:27017": { "type": "Unknown", "topologyVersion": null } }, "topologyType": "ReplicaSetNoPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } } ] } mongodb-mongo-python-driver-509e9b7/test/discovery_and_monitoring/rs/topology_version_less.json000066400000000000000000000043561462766011000335100ustar00rootroot00000000000000{ "description": "Primary with older topologyVersion", "uri": "mongodb://a/?replicaSet=rs", "phases": [ { "responses": [ [ "a:27017", { "ok": 1, "helloOk": true, "isWritablePrimary": true, "hosts": [ "a:27017" ], "setName": "rs", "minWireVersion": 0, "maxWireVersion": 9, "topologyVersion": { "processId": { "$oid": "000000000000000000000001" }, "counter": { "$numberLong": "1" } } } ] ], "outcome": { "servers": { "a:27017": { "type": "RSPrimary", "setName": "rs", "topologyVersion": { "processId": { "$oid": "000000000000000000000001" }, "counter": { "$numberLong": "1" } } } }, "topologyType": "ReplicaSetWithPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } }, { "responses": [ [ "a:27017", { "ok": 1, "helloOk": true, "isWritablePrimary": true, "hosts": [ "a:27017", "b:27017" ], "setName": "rs", "minWireVersion": 0, "maxWireVersion": 9, "topologyVersion": { "processId": { "$oid": "000000000000000000000001" }, "counter": { "$numberLong": "0" } } } ] ], "outcome": { "servers": { "a:27017": { "type": "RSPrimary", "setName": "rs", "topologyVersion": { "processId": { "$oid": "000000000000000000000001" }, "counter": { "$numberLong": "1" } } } }, "topologyType": "ReplicaSetWithPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } } ] } mongodb-mongo-python-driver-509e9b7/test/discovery_and_monitoring/rs/unexpected_mongos.json000066400000000000000000000010561462766011000325610ustar00rootroot00000000000000{ "description": "Unexpected mongos", "uri": "mongodb://b/?replicaSet=rs", "phases": [ { "responses": [ [ "b:27017", { "ok": 1, "helloOk": true, "isWritablePrimary": true, "msg": "isdbgrid", "minWireVersion": 0, "maxWireVersion": 6 } ] ], "outcome": { "servers": {}, "topologyType": "ReplicaSetNoPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } } ] } use_setversion_without_electionid-pre-6.0.json000066400000000000000000000063041462766011000371010ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/discovery_and_monitoring/rs{ "description": "Pre 6.0 Record max setVersion, even from primary without electionId", "uri": "mongodb://a/?replicaSet=rs", "phases": [ { "responses": [ [ "a:27017", { "ok": 1, "helloOk": true, "isWritablePrimary": true, "hosts": [ "a:27017", "b:27017" ], "setName": "rs", "setVersion": 1, "electionId": { "$oid": "000000000000000000000001" }, "minWireVersion": 0, "maxWireVersion": 6 } ] ], "outcome": { "servers": { "a:27017": { "type": "RSPrimary", "setName": "rs", "setVersion": 1, "electionId": { "$oid": "000000000000000000000001" } }, "b:27017": { "type": "Unknown", "setName": null, "electionId": null } }, "topologyType": "ReplicaSetWithPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs", "maxSetVersion": 1, "maxElectionId": { "$oid": "000000000000000000000001" } } }, { "responses": [ [ "b:27017", { "ok": 1, "helloOk": true, "isWritablePrimary": true, "hosts": [ "a:27017", "b:27017" ], "setName": "rs", "setVersion": 2, "minWireVersion": 0, "maxWireVersion": 6 } ] ], "outcome": { "servers": { "a:27017": { "type": "Unknown", "setName": null, "electionId": null }, "b:27017": { "type": "RSPrimary", "setName": "rs", "setVersion": 2 } }, "topologyType": "ReplicaSetWithPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs", "maxSetVersion": 2, "maxElectionId": { "$oid": "000000000000000000000001" } } }, { "responses": [ [ "a:27017", { "ok": 1, "helloOk": true, "isWritablePrimary": true, "hosts": [ "a:27017", "b:27017" ], "setName": "rs", "setVersion": 1, "electionId": { "$oid": "000000000000000000000002" }, "minWireVersion": 0, "maxWireVersion": 6 } ] ], "outcome": { "servers": { "a:27017": { "type": "Unknown", "setName": null, "electionId": null }, "b:27017": { "type": "RSPrimary", "setName": "rs", "setVersion": 2 } }, "topologyType": "ReplicaSetWithPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs", "maxSetVersion": 2, "maxElectionId": { "$oid": "000000000000000000000001" } } } ] } use_setversion_without_electionid.json000066400000000000000000000065671462766011000360270ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/discovery_and_monitoring/rs{ "description": "Record max setVersion, even from primary without electionId", "uri": "mongodb://a/?replicaSet=rs", "phases": [ { "responses": [ [ "a:27017", { "ok": 1, "helloOk": true, "isWritablePrimary": true, "hosts": [ "a:27017", "b:27017" ], "setName": "rs", "setVersion": 1, "electionId": { "$oid": "000000000000000000000001" }, "minWireVersion": 0, "maxWireVersion": 17 } ] ], "outcome": { "servers": { "a:27017": { "type": "RSPrimary", "setName": "rs", "setVersion": 1, "electionId": { "$oid": "000000000000000000000001" } }, "b:27017": { "type": "Unknown", "setName": null, "electionId": null } }, "topologyType": "ReplicaSetWithPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs", "maxSetVersion": 1, "maxElectionId": { "$oid": "000000000000000000000001" } } }, { "responses": [ [ "b:27017", { "ok": 1, "helloOk": true, "isWritablePrimary": true, "hosts": [ "a:27017", "b:27017" ], "setName": "rs", "setVersion": 2, "minWireVersion": 0, "maxWireVersion": 17 } ] ], "outcome": { "servers": { "a:27017": { "type": "RSPrimary", "setName": "rs", "setVersion": 1, "electionId": { "$oid": "000000000000000000000001" } }, "b:27017": { "type": "Unknown", "setName": null, "electionId": null } }, "topologyType": "ReplicaSetWithPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs", "maxSetVersion": 1, "maxElectionId": { "$oid": "000000000000000000000001" } } }, { "responses": [ [ "a:27017", { "ok": 1, "helloOk": true, "isWritablePrimary": true, "hosts": [ "a:27017", "b:27017" ], "setName": "rs", "setVersion": 1, "electionId": { "$oid": "000000000000000000000002" }, "minWireVersion": 0, "maxWireVersion": 17 } ] ], "outcome": { "servers": { "a:27017": { "type": "RSPrimary", "setName": "rs", "setVersion": 1, "electionId": { "$oid": "000000000000000000000002" } }, "b:27017": { "type": "Unknown", "setName": null, "electionId": null } }, "topologyType": "ReplicaSetWithPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs", "maxSetVersion": 1, "maxElectionId": { "$oid": "000000000000000000000002" } } } ] } mongodb-mongo-python-driver-509e9b7/test/discovery_and_monitoring/rs/wrong_set_name.json000066400000000000000000000014131462766011000320370ustar00rootroot00000000000000{ "description": "Wrong setName", "uri": "mongodb://a,b/?replicaSet=rs", "phases": [ { "responses": [ [ "b:27017", { "ok": 1, "helloOk": true, "isWritablePrimary": false, "secondary": true, "hosts": [ "b:27017", "c:27017" ], "setName": "wrong", "minWireVersion": 0, "maxWireVersion": 6 } ] ], "outcome": { "servers": { "a:27017": { "type": "Unknown", "setName": null } }, "topologyType": "ReplicaSetNoPrimary", "logicalSessionTimeoutMinutes": null, "setName": "rs" } } ] } mongodb-mongo-python-driver-509e9b7/test/discovery_and_monitoring/sharded/000077500000000000000000000000001462766011000271245ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/discovery_and_monitoring/sharded/compatible.json000066400000000000000000000020151462766011000321340ustar00rootroot00000000000000{ "description": "Multiple mongoses with large maxWireVersion", "uri": "mongodb://a,b", "phases": [ { "responses": [ [ "a:27017", { "ok": 1, "helloOk": true, "isWritablePrimary": true, "msg": "isdbgrid", "minWireVersion": 0, "maxWireVersion": 1000 } ], [ "b:27017", { "ok": 1, "helloOk": true, "isWritablePrimary": true, "msg": "isdbgrid", "minWireVersion": 0, "maxWireVersion": 6 } ] ], "outcome": { "servers": { "a:27017": { "type": "Mongos", "setName": null }, "b:27017": { "type": "Mongos", "setName": null } }, "topologyType": "Sharded", "logicalSessionTimeoutMinutes": null, "setName": null, "compatible": true } } ] } discover_single_mongos.json000066400000000000000000000011501462766011000344760ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/discovery_and_monitoring/sharded{ "description": "Discover single mongos", "uri": "mongodb://a/?directConnection=false", "phases": [ { "responses": [ [ "a:27017", { "ok": 1, "helloOk": true, "isWritablePrimary": true, "msg": "isdbgrid", "minWireVersion": 0, "maxWireVersion": 6 } ] ], "outcome": { "servers": { "a:27017": { "type": "Mongos", "setName": null } }, "topologyType": "Sharded", "setName": null } } ] } mongodb-mongo-python-driver-509e9b7/test/discovery_and_monitoring/sharded/ls_timeout_mongos.json000066400000000000000000000037741462766011000336000ustar00rootroot00000000000000{ "description": "Parse logicalSessionTimeoutMinutes from mongoses", "uri": "mongodb://a,b", "phases": [ { "responses": [ [ "a:27017", { "ok": 1, "helloOk": true, "isWritablePrimary": true, "msg": "isdbgrid", "logicalSessionTimeoutMinutes": 1, "minWireVersion": 0, "maxWireVersion": 6 } ], [ "b:27017", { "ok": 1, "helloOk": true, "isWritablePrimary": true, "msg": "isdbgrid", "logicalSessionTimeoutMinutes": 2, "minWireVersion": 0, "maxWireVersion": 6 } ] ], "outcome": { "servers": { "a:27017": { "type": "Mongos", "setName": null }, "b:27017": { "type": "Mongos", "setName": null } }, "topologyType": "Sharded", "logicalSessionTimeoutMinutes": 1, "setName": null } }, { "responses": [ [ "a:27017", { "ok": 1, "helloOk": true, "isWritablePrimary": true, "msg": "isdbgrid", "logicalSessionTimeoutMinutes": 1, "minWireVersion": 0, "maxWireVersion": 6 } ], [ "b:27017", { "ok": 1, "helloOk": true, "isWritablePrimary": true, "msg": "isdbgrid", "minWireVersion": 0, "maxWireVersion": 6 } ] ], "outcome": { "servers": { "a:27017": { "type": "Mongos", "setName": null }, "b:27017": { "type": "Mongos", "setName": null } }, "topologyType": "Sharded", "logicalSessionTimeoutMinutes": null, "setName": null } } ] } mongodb-mongo-python-driver-509e9b7/test/discovery_and_monitoring/sharded/mongos_disconnect.json000066400000000000000000000040311462766011000335300ustar00rootroot00000000000000{ "description": "Mongos disconnect", "uri": "mongodb://a,b", "phases": [ { "responses": [ [ "a:27017", { "ok": 1, "helloOk": true, "isWritablePrimary": true, "msg": "isdbgrid", "minWireVersion": 0, "maxWireVersion": 6 } ], [ "b:27017", { "ok": 1, "helloOk": true, "isWritablePrimary": true, "msg": "isdbgrid", "minWireVersion": 0, "maxWireVersion": 6 } ] ], "outcome": { "servers": { "a:27017": { "type": "Mongos", "setName": null }, "b:27017": { "type": "Mongos", "setName": null } }, "topologyType": "Sharded", "logicalSessionTimeoutMinutes": null, "setName": null } }, { "responses": [ [ "a:27017", {} ] ], "outcome": { "servers": { "a:27017": { "type": "Unknown", "setName": null }, "b:27017": { "type": "Mongos", "setName": null } }, "topologyType": "Sharded", "logicalSessionTimeoutMinutes": null, "setName": null } }, { "responses": [ [ "a:27017", { "ok": 1, "helloOk": true, "isWritablePrimary": true, "msg": "isdbgrid", "minWireVersion": 0, "maxWireVersion": 6 } ] ], "outcome": { "servers": { "a:27017": { "type": "Mongos", "setName": null }, "b:27017": { "type": "Mongos", "setName": null } }, "topologyType": "Sharded", "logicalSessionTimeoutMinutes": null, "setName": null } } ] } mongodb-mongo-python-driver-509e9b7/test/discovery_and_monitoring/sharded/multiple_mongoses.json000066400000000000000000000017241462766011000335700ustar00rootroot00000000000000{ "description": "Multiple mongoses", "uri": "mongodb://a,b", "phases": [ { "responses": [ [ "a:27017", { "ok": 1, "helloOk": true, "isWritablePrimary": true, "msg": "isdbgrid", "minWireVersion": 0, "maxWireVersion": 6 } ], [ "b:27017", { "ok": 1, "helloOk": true, "isWritablePrimary": true, "msg": "isdbgrid", "minWireVersion": 0, "maxWireVersion": 6 } ] ], "outcome": { "servers": { "a:27017": { "type": "Mongos", "setName": null }, "b:27017": { "type": "Mongos", "setName": null } }, "topologyType": "Sharded", "logicalSessionTimeoutMinutes": null, "setName": null } } ] } mongodb-mongo-python-driver-509e9b7/test/discovery_and_monitoring/sharded/non_mongos_removed.json000066400000000000000000000017051462766011000337170ustar00rootroot00000000000000{ "description": "Non-Mongos server in sharded cluster", "uri": "mongodb://a,b", "phases": [ { "responses": [ [ "a:27017", { "ok": 1, "helloOk": true, "isWritablePrimary": true, "msg": "isdbgrid", "minWireVersion": 0, "maxWireVersion": 6 } ], [ "b:27017", { "ok": 1, "helloOk": true, "isWritablePrimary": true, "hosts": [ "b:27017" ], "setName": "rs", "minWireVersion": 0, "maxWireVersion": 6 } ] ], "outcome": { "servers": { "a:27017": { "type": "Mongos", "setName": null } }, "topologyType": "Sharded", "logicalSessionTimeoutMinutes": null, "setName": null } } ] } mongodb-mongo-python-driver-509e9b7/test/discovery_and_monitoring/sharded/normalize_uri_case.json000066400000000000000000000007331462766011000336740ustar00rootroot00000000000000{ "description": "Normalize URI case", "uri": "mongodb://A,B", "phases": [ { "responses": [], "outcome": { "servers": { "a:27017": { "type": "Unknown", "setName": null }, "b:27017": { "type": "Unknown", "setName": null } }, "topologyType": "Unknown", "logicalSessionTimeoutMinutes": null, "setName": null } } ] } mongodb-mongo-python-driver-509e9b7/test/discovery_and_monitoring/sharded/too_new.json000066400000000000000000000017161462766011000314760ustar00rootroot00000000000000{ "description": "Multiple mongoses with large minWireVersion", "uri": "mongodb://a,b", "phases": [ { "responses": [ [ "a:27017", { "ok": 1, "helloOk": true, "isWritablePrimary": true, "msg": "isdbgrid", "minWireVersion": 999, "maxWireVersion": 1000 } ], [ "b:27017", { "ok": 1, "helloOk": true, "isWritablePrimary": true, "msg": "isdbgrid" } ] ], "outcome": { "servers": { "a:27017": { "type": "Mongos", "setName": null }, "b:27017": { "type": "Mongos", "setName": null } }, "topologyType": "Sharded", "logicalSessionTimeoutMinutes": null, "setName": null, "compatible": false } } ] } mongodb-mongo-python-driver-509e9b7/test/discovery_and_monitoring/sharded/too_old.json000066400000000000000000000017201462766011000314560ustar00rootroot00000000000000{ "description": "Multiple mongoses with default maxWireVersion of 0", "uri": "mongodb://a,b", "phases": [ { "responses": [ [ "a:27017", { "ok": 1, "helloOk": true, "isWritablePrimary": true, "msg": "isdbgrid", "minWireVersion": 2, "maxWireVersion": 6 } ], [ "b:27017", { "ok": 1, "helloOk": true, "isWritablePrimary": true, "msg": "isdbgrid" } ] ], "outcome": { "servers": { "a:27017": { "type": "Mongos", "setName": null }, "b:27017": { "type": "Mongos", "setName": null } }, "topologyType": "Sharded", "logicalSessionTimeoutMinutes": null, "setName": null, "compatible": false } } ] } mongodb-mongo-python-driver-509e9b7/test/discovery_and_monitoring/single/000077500000000000000000000000001462766011000267735ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/discovery_and_monitoring/single/compatible.json000066400000000000000000000012141462766011000320030ustar00rootroot00000000000000{ "description": "Standalone with large maxWireVersion", "uri": "mongodb://a", "phases": [ { "responses": [ [ "a:27017", { "ok": 1, "helloOk": true, "isWritablePrimary": true, "minWireVersion": 0, "maxWireVersion": 6 } ] ], "outcome": { "servers": { "a:27017": { "type": "Standalone", "setName": null } }, "topologyType": "Single", "logicalSessionTimeoutMinutes": null, "setName": null, "compatible": true } } ] } direct_connection_external_ip.json000066400000000000000000000013531462766011000356740ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/discovery_and_monitoring/single{ "description": "Direct connection to RSPrimary via external IP", "uri": "mongodb://a/?directConnection=true", "phases": [ { "responses": [ [ "a:27017", { "ok": 1, "helloOk": true, "isWritablePrimary": true, "hosts": [ "b:27017" ], "setName": "rs", "minWireVersion": 0, "maxWireVersion": 6 } ] ], "outcome": { "servers": { "a:27017": { "type": "RSPrimary", "setName": "rs" } }, "topologyType": "Single", "logicalSessionTimeoutMinutes": null, "setName": null } } ] } direct_connection_mongos.json000066400000000000000000000012311462766011000346570ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/discovery_and_monitoring/single{ "description": "Direct connection to mongos", "uri": "mongodb://a/?directConnection=true", "phases": [ { "responses": [ [ "a:27017", { "ok": 1, "helloOk": true, "isWritablePrimary": true, "msg": "isdbgrid", "minWireVersion": 0, "maxWireVersion": 6 } ] ], "outcome": { "servers": { "a:27017": { "type": "Mongos", "setName": null } }, "topologyType": "Single", "logicalSessionTimeoutMinutes": null, "setName": null } } ] } direct_connection_replicaset.json000066400000000000000000000012711462766011000355140ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/discovery_and_monitoring/single{ "description": "Direct connection with replicaSet URI option", "uri": "mongodb://a/?replicaSet=rs&directConnection=true", "phases": [ { "responses": [ [ "a:27017", { "ok": 1, "helloOk": true, "isWritablePrimary": true, "setName": "rs", "minWireVersion": 0, "maxWireVersion": 6 } ] ], "outcome": { "servers": { "a:27017": { "type": "RSPrimary", "setName": "rs" } }, "topologyType": "Single", "logicalSessionTimeoutMinutes": null, "setName": "rs" } } ] } direct_connection_rsarbiter.json000066400000000000000000000014261462766011000353600ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/discovery_and_monitoring/single{ "description": "Direct connection to RSArbiter", "uri": "mongodb://a/?directConnection=true", "phases": [ { "responses": [ [ "a:27017", { "ok": 1, "helloOk": true, "isWritablePrimary": false, "arbiterOnly": true, "hosts": [ "a:27017", "b:27017" ], "setName": "rs", "minWireVersion": 0, "maxWireVersion": 6 } ] ], "outcome": { "servers": { "a:27017": { "type": "RSArbiter", "setName": "rs" } }, "topologyType": "Single", "logicalSessionTimeoutMinutes": null, "setName": null } } ] } direct_connection_rsprimary.json000066400000000000000000000013641462766011000354140ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/discovery_and_monitoring/single{ "description": "Direct connection to RSPrimary", "uri": "mongodb://a/?directConnection=true", "phases": [ { "responses": [ [ "a:27017", { "ok": 1, "helloOk": true, "isWritablePrimary": true, "hosts": [ "a:27017", "b:27017" ], "setName": "rs", "minWireVersion": 0, "maxWireVersion": 6 } ] ], "outcome": { "servers": { "a:27017": { "type": "RSPrimary", "setName": "rs" } }, "topologyType": "Single", "logicalSessionTimeoutMinutes": null, "setName": null } } ] } direct_connection_rssecondary.json000066400000000000000000000014301462766011000357120ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/discovery_and_monitoring/single{ "description": "Direct connection to RSSecondary", "uri": "mongodb://a/?directConnection=true", "phases": [ { "responses": [ [ "a:27017", { "ok": 1, "helloOk": true, "isWritablePrimary": false, "secondary": true, "hosts": [ "a:27017", "b:27017" ], "setName": "rs", "minWireVersion": 0, "maxWireVersion": 6 } ] ], "outcome": { "servers": { "a:27017": { "type": "RSSecondary", "setName": "rs" } }, "topologyType": "Single", "logicalSessionTimeoutMinutes": null, "setName": null } } ] } direct_connection_standalone.json000066400000000000000000000012021462766011000355030ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/discovery_and_monitoring/single{ "description": "Direct connection to standalone", "uri": "mongodb://a/?directConnection=true", "phases": [ { "responses": [ [ "a:27017", { "ok": 1, "helloOk": true, "isWritablePrimary": true, "minWireVersion": 0, "maxWireVersion": 6 } ] ], "outcome": { "servers": { "a:27017": { "type": "Standalone", "setName": null } }, "topologyType": "Single", "logicalSessionTimeoutMinutes": null, "setName": null } } ] } direct_connection_unavailable_seed.json000066400000000000000000000007401462766011000366440ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/discovery_and_monitoring/single{ "description": "Direct connection to unavailable seed", "uri": "mongodb://a/?directConnection=true", "phases": [ { "responses": [ [ "a:27017", {} ] ], "outcome": { "servers": { "a:27017": { "type": "Unknown", "setName": null } }, "topologyType": "Single", "logicalSessionTimeoutMinutes": null, "setName": null } } ] } direct_connection_wrong_set_name.json000066400000000000000000000025671462766011000364010ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/discovery_and_monitoring/single{ "description": "Direct connection to RSPrimary with wrong set name", "uri": "mongodb://a/?directConnection=true&replicaSet=rs", "phases": [ { "responses": [ [ "a:27017", { "ok": 1, "helloOk": true, "isWritablePrimary": true, "hosts": [ "a:27017", "b:27017" ], "setName": "wrong", "minWireVersion": 0, "maxWireVersion": 6 } ] ], "outcome": { "servers": { "a:27017": { "type": "Unknown" } }, "topologyType": "Single", "logicalSessionTimeoutMinutes": null, "setName": "rs" } }, { "responses": [ [ "a:27017", { "ok": 1, "helloOk": true, "isWritablePrimary": true, "hosts": [ "a:27017", "b:27017" ], "setName": "rs", "minWireVersion": 0, "maxWireVersion": 6 } ] ], "outcome": { "servers": { "a:27017": { "type": "RSPrimary", "setName": "rs" } }, "topologyType": "Single", "logicalSessionTimeoutMinutes": null, "setName": "rs" } } ] } mongodb-mongo-python-driver-509e9b7/test/discovery_and_monitoring/single/discover_standalone.json000066400000000000000000000011671462766011000337210ustar00rootroot00000000000000{ "description": "Discover standalone", "uri": "mongodb://a/?directConnection=false", "phases": [ { "responses": [ [ "a:27017", { "ok": 1, "helloOk": true, "isWritablePrimary": true, "minWireVersion": 0, "maxWireVersion": 6 } ] ], "outcome": { "servers": { "a:27017": { "type": "Standalone", "setName": null } }, "topologyType": "Single", "logicalSessionTimeoutMinutes": null, "setName": null } } ] } discover_unavailable_seed.json000066400000000000000000000007261462766011000347750ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/discovery_and_monitoring/single{ "description": "Discover unavailable seed", "uri": "mongodb://a/?directConnection=false", "phases": [ { "responses": [ [ "a:27017", {} ] ], "outcome": { "servers": { "a:27017": { "type": "Unknown", "setName": null } }, "topologyType": "Unknown", "logicalSessionTimeoutMinutes": null, "setName": null } } ] } mongodb-mongo-python-driver-509e9b7/test/discovery_and_monitoring/single/ls_timeout_standalone.json000066400000000000000000000012521462766011000342620ustar00rootroot00000000000000{ "description": "Parse logicalSessionTimeoutMinutes from standalone", "uri": "mongodb://a", "phases": [ { "responses": [ [ "a:27017", { "ok": 1, "helloOk": true, "isWritablePrimary": true, "logicalSessionTimeoutMinutes": 7, "minWireVersion": 0, "maxWireVersion": 6 } ] ], "outcome": { "servers": { "a:27017": { "type": "Standalone", "setName": null } }, "topologyType": "Single", "logicalSessionTimeoutMinutes": 7, "setName": null } } ] } mongodb-mongo-python-driver-509e9b7/test/discovery_and_monitoring/single/not_ok_response.json000066400000000000000000000015171462766011000331010ustar00rootroot00000000000000{ "description": "Handle a not-ok isWritablePrimary response", "uri": "mongodb://a", "phases": [ { "responses": [ [ "a:27017", { "ok": 1, "helloOk": true, "isWritablePrimary": true, "minWireVersion": 0, "maxWireVersion": 6 } ], [ "a:27017", { "ok": 0, "helloOk": true, "isWritablePrimary": true, "minWireVersion": 0, "maxWireVersion": 6 } ] ], "outcome": { "servers": { "a:27017": { "type": "Unknown", "setName": null } }, "topologyType": "Single", "logicalSessionTimeoutMinutes": null, "setName": null } } ] } mongodb-mongo-python-driver-509e9b7/test/discovery_and_monitoring/single/standalone_removed.json000066400000000000000000000011711462766011000335370ustar00rootroot00000000000000{ "description": "Standalone removed from multi-server topology", "uri": "mongodb://a,b", "phases": [ { "responses": [ [ "a:27017", { "ok": 1, "helloOk": true, "isWritablePrimary": true, "minWireVersion": 0, "maxWireVersion": 6 } ] ], "outcome": { "servers": { "b:27017": { "type": "Unknown", "setName": null } }, "topologyType": "Unknown", "logicalSessionTimeoutMinutes": null, "setName": null } } ] } standalone_using_legacy_hello.json000066400000000000000000000011161462766011000356520ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/discovery_and_monitoring/single{ "description": "Connect to standalone using legacy hello", "uri": "mongodb://a", "phases": [ { "responses": [ [ "a:27017", { "ok": 1, "ismaster": true, "minWireVersion": 0, "maxWireVersion": 6 } ] ], "outcome": { "servers": { "a:27017": { "type": "Standalone", "setName": null } }, "topologyType": "Single", "logicalSessionTimeoutMinutes": null, "setName": null } } ] } mongodb-mongo-python-driver-509e9b7/test/discovery_and_monitoring/single/too_new.json000066400000000000000000000012221462766011000313350ustar00rootroot00000000000000{ "description": "Standalone with large minWireVersion", "uri": "mongodb://a", "phases": [ { "responses": [ [ "a:27017", { "ok": 1, "helloOk": true, "isWritablePrimary": true, "minWireVersion": 999, "maxWireVersion": 1000 } ] ], "outcome": { "servers": { "a:27017": { "type": "Standalone", "setName": null } }, "topologyType": "Single", "logicalSessionTimeoutMinutes": null, "setName": null, "compatible": false } } ] } mongodb-mongo-python-driver-509e9b7/test/discovery_and_monitoring/single/too_old.json000066400000000000000000000011221462766011000313210ustar00rootroot00000000000000{ "description": "Standalone with default maxWireVersion of 0", "uri": "mongodb://a", "phases": [ { "responses": [ [ "a:27017", { "ok": 1, "helloOk": true, "isWritablePrimary": true } ] ], "outcome": { "servers": { "a:27017": { "type": "Standalone", "setName": null } }, "topologyType": "Single", "logicalSessionTimeoutMinutes": null, "setName": null, "compatible": false } } ] } mongodb-mongo-python-driver-509e9b7/test/discovery_and_monitoring/single/too_old_then_upgraded.json000066400000000000000000000022411462766011000342150ustar00rootroot00000000000000{ "description": "Standalone with default maxWireVersion of 0 is upgraded to one with maxWireVersion 6", "uri": "mongodb://a", "phases": [ { "responses": [ [ "a:27017", { "ok": 1, "helloOk": true, "isWritablePrimary": true } ] ], "outcome": { "servers": { "a:27017": { "type": "Standalone", "setName": null } }, "topologyType": "Single", "logicalSessionTimeoutMinutes": null, "setName": null, "compatible": false } }, { "responses": [ [ "a:27017", { "ok": 1, "helloOk": true, "isWritablePrimary": true, "minWireVersion": 0, "maxWireVersion": 6 } ] ], "outcome": { "servers": { "a:27017": { "type": "Standalone", "setName": null } }, "topologyType": "Single", "logicalSessionTimeoutMinutes": null, "setName": null, "compatible": true } } ] } mongodb-mongo-python-driver-509e9b7/test/discovery_and_monitoring/unified/000077500000000000000000000000001462766011000271355ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/discovery_and_monitoring/unified/auth-error.json000066400000000000000000000121751462766011000321260ustar00rootroot00000000000000{ "description": "auth-error", "schemaVersion": "1.4", "runOnRequirements": [ { "minServerVersion": "4.4", "auth": true, "serverless": "forbid", "topologies": [ "single", "replicaset", "sharded" ] } ], "createEntities": [ { "client": { "id": "setupClient", "useMultipleMongoses": false } } ], "initialData": [ { "collectionName": "auth-error", "databaseName": "sdam-tests", "documents": [ { "_id": 1 }, { "_id": 2 } ] } ], "tests": [ { "description": "Reset server and pool after AuthenticationFailure error", "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "setupClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "saslContinue" ], "appName": "authErrorTest", "errorCode": 18 } } } }, { "name": "createEntities", "object": "testRunner", "arguments": { "entities": [ { "client": { "id": "client", "useMultipleMongoses": false, "observeEvents": [ "commandStartedEvent", "serverDescriptionChangedEvent", "poolClearedEvent" ], "uriOptions": { "retryWrites": false, "appname": "authErrorTest" } } }, { "database": { "id": "database", "client": "client", "databaseName": "sdam-tests" } }, { "collection": { "id": "collection", "database": "database", "collectionName": "auth-error" } } ] } }, { "name": "insertMany", "object": "collection", "arguments": { "documents": [ { "_id": 3 }, { "_id": 4 } ] }, "expectError": { "isError": true } }, { "name": "waitForEvent", "object": "testRunner", "arguments": { "client": "client", "event": { "serverDescriptionChangedEvent": { "newDescription": { "type": "Unknown" } } }, "count": 1 } }, { "name": "waitForEvent", "object": "testRunner", "arguments": { "client": "client", "event": { "poolClearedEvent": {} }, "count": 1 } }, { "name": "insertMany", "object": "collection", "arguments": { "documents": [ { "_id": 5 }, { "_id": 6 } ] } }, { "name": "assertEventCount", "object": "testRunner", "arguments": { "client": "client", "event": { "serverDescriptionChangedEvent": { "newDescription": { "type": "Unknown" } } }, "count": 1 } }, { "name": "assertEventCount", "object": "testRunner", "arguments": { "client": "client", "event": { "poolClearedEvent": {} }, "count": 1 } } ], "expectEvents": [ { "client": "client", "eventType": "command", "events": [ { "commandStartedEvent": { "command": { "insert": "auth-error", "documents": [ { "_id": 5 }, { "_id": 6 } ] }, "commandName": "insert", "databaseName": "sdam-tests" } } ] } ], "outcome": [ { "collectionName": "auth-error", "databaseName": "sdam-tests", "documents": [ { "_id": 1 }, { "_id": 2 }, { "_id": 5 }, { "_id": 6 } ] } ] } ] } auth-misc-command-error.json000066400000000000000000000122341462766011000344100ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/discovery_and_monitoring/unified{ "description": "auth-misc-command-error", "schemaVersion": "1.4", "runOnRequirements": [ { "minServerVersion": "4.4", "auth": true, "serverless": "forbid", "topologies": [ "single", "replicaset", "sharded" ] } ], "createEntities": [ { "client": { "id": "setupClient", "useMultipleMongoses": false } } ], "initialData": [ { "collectionName": "auth-misc-error", "databaseName": "sdam-tests", "documents": [ { "_id": 1 }, { "_id": 2 } ] } ], "tests": [ { "description": "Reset server and pool after misc command error", "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "setupClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "saslContinue" ], "appName": "authMiscErrorTest", "errorCode": 1 } } } }, { "name": "createEntities", "object": "testRunner", "arguments": { "entities": [ { "client": { "id": "client", "useMultipleMongoses": false, "observeEvents": [ "commandStartedEvent", "serverDescriptionChangedEvent", "poolClearedEvent" ], "uriOptions": { "retryWrites": false, "appname": "authMiscErrorTest" } } }, { "database": { "id": "database", "client": "client", "databaseName": "sdam-tests" } }, { "collection": { "id": "collection", "database": "database", "collectionName": "auth-misc-error" } } ] } }, { "name": "insertMany", "object": "collection", "arguments": { "documents": [ { "_id": 3 }, { "_id": 4 } ] }, "expectError": { "isError": true } }, { "name": "waitForEvent", "object": "testRunner", "arguments": { "client": "client", "event": { "serverDescriptionChangedEvent": { "newDescription": { "type": "Unknown" } } }, "count": 1 } }, { "name": "waitForEvent", "object": "testRunner", "arguments": { "client": "client", "event": { "poolClearedEvent": {} }, "count": 1 } }, { "name": "insertMany", "object": "collection", "arguments": { "documents": [ { "_id": 5 }, { "_id": 6 } ] } }, { "name": "assertEventCount", "object": "testRunner", "arguments": { "client": "client", "event": { "serverDescriptionChangedEvent": { "newDescription": { "type": "Unknown" } } }, "count": 1 } }, { "name": "assertEventCount", "object": "testRunner", "arguments": { "client": "client", "event": { "poolClearedEvent": {} }, "count": 1 } } ], "expectEvents": [ { "client": "client", "eventType": "command", "events": [ { "commandStartedEvent": { "command": { "insert": "auth-misc-error", "documents": [ { "_id": 5 }, { "_id": 6 } ] }, "commandName": "insert", "databaseName": "sdam-tests" } } ] } ], "outcome": [ { "collectionName": "auth-misc-error", "databaseName": "sdam-tests", "documents": [ { "_id": 1 }, { "_id": 2 }, { "_id": 5 }, { "_id": 6 } ] } ] } ] } mongodb-mongo-python-driver-509e9b7/test/discovery_and_monitoring/unified/auth-network-error.json000066400000000000000000000123031462766011000336060ustar00rootroot00000000000000{ "description": "auth-network-error", "schemaVersion": "1.4", "runOnRequirements": [ { "minServerVersion": "4.4", "auth": true, "serverless": "forbid", "topologies": [ "single", "replicaset", "sharded" ] } ], "createEntities": [ { "client": { "id": "setupClient", "useMultipleMongoses": false } } ], "initialData": [ { "collectionName": "auth-network-error", "databaseName": "sdam-tests", "documents": [ { "_id": 1 }, { "_id": 2 } ] } ], "tests": [ { "description": "Reset server and pool after network error during authentication", "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "setupClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "saslContinue" ], "closeConnection": true, "appName": "authNetworkErrorTest" } } } }, { "name": "createEntities", "object": "testRunner", "arguments": { "entities": [ { "client": { "id": "client", "useMultipleMongoses": false, "observeEvents": [ "commandStartedEvent", "serverDescriptionChangedEvent", "poolClearedEvent" ], "uriOptions": { "retryWrites": false, "appname": "authNetworkErrorTest" } } }, { "database": { "id": "database", "client": "client", "databaseName": "sdam-tests" } }, { "collection": { "id": "collection", "database": "database", "collectionName": "auth-network-error" } } ] } }, { "name": "insertMany", "object": "collection", "arguments": { "documents": [ { "_id": 3 }, { "_id": 4 } ] }, "expectError": { "isError": true } }, { "name": "waitForEvent", "object": "testRunner", "arguments": { "client": "client", "event": { "serverDescriptionChangedEvent": { "newDescription": { "type": "Unknown" } } }, "count": 1 } }, { "name": "waitForEvent", "object": "testRunner", "arguments": { "client": "client", "event": { "poolClearedEvent": {} }, "count": 1 } }, { "name": "insertMany", "object": "collection", "arguments": { "documents": [ { "_id": 5 }, { "_id": 6 } ] } }, { "name": "assertEventCount", "object": "testRunner", "arguments": { "client": "client", "event": { "serverDescriptionChangedEvent": { "newDescription": { "type": "Unknown" } } }, "count": 1 } }, { "name": "assertEventCount", "object": "testRunner", "arguments": { "client": "client", "event": { "poolClearedEvent": {} }, "count": 1 } } ], "expectEvents": [ { "client": "client", "eventType": "command", "events": [ { "commandStartedEvent": { "command": { "insert": "auth-network-error", "documents": [ { "_id": 5 }, { "_id": 6 } ] }, "commandName": "insert", "databaseName": "sdam-tests" } } ] } ], "outcome": [ { "collectionName": "auth-network-error", "databaseName": "sdam-tests", "documents": [ { "_id": 1 }, { "_id": 2 }, { "_id": 5 }, { "_id": 6 } ] } ] } ] } auth-network-timeout-error.json000066400000000000000000000125761462766011000352270ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/discovery_and_monitoring/unified{ "description": "auth-network-timeout-error", "schemaVersion": "1.4", "runOnRequirements": [ { "minServerVersion": "4.4", "auth": true, "serverless": "forbid", "topologies": [ "single", "replicaset", "sharded" ] } ], "createEntities": [ { "client": { "id": "setupClient", "useMultipleMongoses": false } } ], "initialData": [ { "collectionName": "auth-network-timeout-error", "databaseName": "sdam-tests", "documents": [ { "_id": 1 }, { "_id": 2 } ] } ], "tests": [ { "description": "Reset server and pool after network timeout error during authentication", "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "setupClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "saslContinue" ], "blockConnection": true, "blockTimeMS": 500, "appName": "authNetworkTimeoutErrorTest" } } } }, { "name": "createEntities", "object": "testRunner", "arguments": { "entities": [ { "client": { "id": "client", "useMultipleMongoses": false, "observeEvents": [ "commandStartedEvent", "serverDescriptionChangedEvent", "poolClearedEvent" ], "uriOptions": { "retryWrites": false, "appname": "authNetworkTimeoutErrorTest", "connectTimeoutMS": 250, "socketTimeoutMS": 250 } } }, { "database": { "id": "database", "client": "client", "databaseName": "sdam-tests" } }, { "collection": { "id": "collection", "database": "database", "collectionName": "auth-network-timeout-error" } } ] } }, { "name": "insertMany", "object": "collection", "arguments": { "documents": [ { "_id": 3 }, { "_id": 4 } ] }, "expectError": { "isError": true } }, { "name": "waitForEvent", "object": "testRunner", "arguments": { "client": "client", "event": { "serverDescriptionChangedEvent": { "newDescription": { "type": "Unknown" } } }, "count": 1 } }, { "name": "waitForEvent", "object": "testRunner", "arguments": { "client": "client", "event": { "poolClearedEvent": {} }, "count": 1 } }, { "name": "insertMany", "object": "collection", "arguments": { "documents": [ { "_id": 5 }, { "_id": 6 } ] } }, { "name": "assertEventCount", "object": "testRunner", "arguments": { "client": "client", "event": { "serverDescriptionChangedEvent": { "newDescription": { "type": "Unknown" } } }, "count": 1 } }, { "name": "assertEventCount", "object": "testRunner", "arguments": { "client": "client", "event": { "poolClearedEvent": {} }, "count": 1 } } ], "expectEvents": [ { "client": "client", "eventType": "command", "events": [ { "commandStartedEvent": { "command": { "insert": "auth-network-timeout-error", "documents": [ { "_id": 5 }, { "_id": 6 } ] }, "commandName": "insert", "databaseName": "sdam-tests" } } ] } ], "outcome": [ { "collectionName": "auth-network-timeout-error", "databaseName": "sdam-tests", "documents": [ { "_id": 1 }, { "_id": 2 }, { "_id": 5 }, { "_id": 6 } ] } ] } ] } mongodb-mongo-python-driver-509e9b7/test/discovery_and_monitoring/unified/auth-shutdown-error.json000066400000000000000000000123031462766011000337700ustar00rootroot00000000000000{ "description": "auth-shutdown-error", "schemaVersion": "1.4", "runOnRequirements": [ { "minServerVersion": "4.4", "auth": true, "serverless": "forbid", "topologies": [ "single", "replicaset", "sharded" ] } ], "createEntities": [ { "client": { "id": "setupClient", "useMultipleMongoses": false } } ], "initialData": [ { "collectionName": "auth-shutdown-error", "databaseName": "sdam-tests", "documents": [ { "_id": 1 }, { "_id": 2 } ] } ], "tests": [ { "description": "Reset server and pool after shutdown error during authentication", "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "setupClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "saslContinue" ], "appName": "authShutdownErrorTest", "errorCode": 91 } } } }, { "name": "createEntities", "object": "testRunner", "arguments": { "entities": [ { "client": { "id": "client", "useMultipleMongoses": false, "observeEvents": [ "commandStartedEvent", "serverDescriptionChangedEvent", "poolClearedEvent" ], "uriOptions": { "retryWrites": false, "appname": "authShutdownErrorTest" } } }, { "database": { "id": "database", "client": "client", "databaseName": "sdam-tests" } }, { "collection": { "id": "collection", "database": "database", "collectionName": "auth-shutdown-error" } } ] } }, { "name": "insertMany", "object": "collection", "arguments": { "documents": [ { "_id": 3 }, { "_id": 4 } ] }, "expectError": { "isError": true } }, { "name": "waitForEvent", "object": "testRunner", "arguments": { "client": "client", "event": { "serverDescriptionChangedEvent": { "newDescription": { "type": "Unknown" } } }, "count": 1 } }, { "name": "waitForEvent", "object": "testRunner", "arguments": { "client": "client", "event": { "poolClearedEvent": {} }, "count": 1 } }, { "name": "insertMany", "object": "collection", "arguments": { "documents": [ { "_id": 5 }, { "_id": 6 } ] } }, { "name": "assertEventCount", "object": "testRunner", "arguments": { "client": "client", "event": { "serverDescriptionChangedEvent": { "newDescription": { "type": "Unknown" } } }, "count": 1 } }, { "name": "assertEventCount", "object": "testRunner", "arguments": { "client": "client", "event": { "poolClearedEvent": {} }, "count": 1 } } ], "expectEvents": [ { "client": "client", "eventType": "command", "events": [ { "commandStartedEvent": { "command": { "insert": "auth-shutdown-error", "documents": [ { "_id": 5 }, { "_id": 6 } ] }, "commandName": "insert", "databaseName": "sdam-tests" } } ] } ], "outcome": [ { "collectionName": "auth-shutdown-error", "databaseName": "sdam-tests", "documents": [ { "_id": 1 }, { "_id": 2 }, { "_id": 5 }, { "_id": 6 } ] } ] } ] } mongodb-mongo-python-driver-509e9b7/test/discovery_and_monitoring/unified/cancel-server-check.json000066400000000000000000000110571462766011000336400ustar00rootroot00000000000000{ "description": "cancel-server-check", "schemaVersion": "1.4", "runOnRequirements": [ { "minServerVersion": "4.0", "topologies": [ "replicaset" ], "serverless": "forbid" }, { "minServerVersion": "4.2", "topologies": [ "sharded" ], "serverless": "forbid" } ], "createEntities": [ { "client": { "id": "setupClient", "useMultipleMongoses": false } } ], "initialData": [ { "collectionName": "cancel-server-check", "databaseName": "sdam-tests", "documents": [] } ], "tests": [ { "description": "Cancel server check", "operations": [ { "name": "createEntities", "object": "testRunner", "arguments": { "entities": [ { "client": { "id": "client", "useMultipleMongoses": false, "observeEvents": [ "serverDescriptionChangedEvent", "poolClearedEvent" ], "uriOptions": { "retryWrites": true, "heartbeatFrequencyMS": 10000, "serverSelectionTimeoutMS": 5000, "appname": "cancelServerCheckTest" } } }, { "database": { "id": "database", "client": "client", "databaseName": "sdam-tests" } }, { "collection": { "id": "collection", "database": "database", "collectionName": "cancel-server-check" } } ] } }, { "name": "insertOne", "object": "collection", "arguments": { "document": { "_id": 1 } } }, { "name": "failPoint", "object": "testRunner", "arguments": { "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "insert" ], "closeConnection": true } }, "client": "setupClient" } }, { "name": "insertOne", "object": "collection", "arguments": { "document": { "_id": 2 } }, "expectResult": { "insertedId": 2 } }, { "name": "waitForEvent", "object": "testRunner", "arguments": { "client": "client", "event": { "serverDescriptionChangedEvent": { "newDescription": { "type": "Unknown" } } }, "count": 1 } }, { "name": "waitForEvent", "object": "testRunner", "arguments": { "client": "client", "event": { "poolClearedEvent": {} }, "count": 1 } }, { "name": "insertOne", "object": "collection", "arguments": { "document": { "_id": 3 } }, "expectResult": { "insertedId": 3 } }, { "name": "assertEventCount", "object": "testRunner", "arguments": { "client": "client", "event": { "serverDescriptionChangedEvent": { "newDescription": { "type": "Unknown" } } }, "count": 1 } }, { "name": "assertEventCount", "object": "testRunner", "arguments": { "client": "client", "event": { "poolClearedEvent": {} }, "count": 1 } } ], "outcome": [ { "collectionName": "cancel-server-check", "databaseName": "sdam-tests", "documents": [ { "_id": 1 }, { "_id": 2 }, { "_id": 3 } ] } ] } ] } mongodb-mongo-python-driver-509e9b7/test/discovery_and_monitoring/unified/connectTimeoutMS.json000066400000000000000000000121351462766011000332720ustar00rootroot00000000000000{ "description": "connectTimeoutMS", "schemaVersion": "1.4", "runOnRequirements": [ { "minServerVersion": "4.4", "serverless": "forbid", "topologies": [ "single", "replicaset", "sharded" ] } ], "createEntities": [ { "client": { "id": "setupClient", "useMultipleMongoses": false } } ], "initialData": [ { "collectionName": "connectTimeoutMS", "databaseName": "sdam-tests", "documents": [] } ], "tests": [ { "description": "connectTimeoutMS=0", "operations": [ { "name": "createEntities", "object": "testRunner", "arguments": { "entities": [ { "client": { "id": "client", "observeEvents": [ "commandStartedEvent", "serverDescriptionChangedEvent", "poolClearedEvent" ], "uriOptions": { "retryWrites": false, "connectTimeoutMS": 0, "heartbeatFrequencyMS": 500, "appname": "connectTimeoutMS=0" }, "useMultipleMongoses": false } }, { "database": { "id": "database", "client": "client", "databaseName": "sdam-tests" } }, { "collection": { "id": "collection", "database": "database", "collectionName": "connectTimeoutMS" } } ] } }, { "name": "insertMany", "object": "collection", "arguments": { "documents": [ { "_id": 1 }, { "_id": 2 } ] } }, { "name": "failPoint", "object": "testRunner", "arguments": { "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 2 }, "data": { "failCommands": [ "hello", "isMaster" ], "appName": "connectTimeoutMS=0", "blockConnection": true, "blockTimeMS": 550 } }, "client": "setupClient" } }, { "name": "wait", "object": "testRunner", "arguments": { "ms": 750 } }, { "name": "insertMany", "object": "collection", "arguments": { "documents": [ { "_id": 3 }, { "_id": 4 } ] } }, { "name": "assertEventCount", "object": "testRunner", "arguments": { "client": "client", "event": { "serverDescriptionChangedEvent": { "newDescription": { "type": "Unknown" } } }, "count": 0 } }, { "name": "assertEventCount", "object": "testRunner", "arguments": { "client": "client", "event": { "poolClearedEvent": {} }, "count": 0 } } ], "expectEvents": [ { "client": "client", "eventType": "command", "events": [ { "commandStartedEvent": { "command": { "insert": "connectTimeoutMS", "documents": [ { "_id": 1 }, { "_id": 2 } ] }, "commandName": "insert", "databaseName": "sdam-tests" } }, { "commandStartedEvent": { "command": { "insert": "connectTimeoutMS", "documents": [ { "_id": 3 }, { "_id": 4 } ] }, "commandName": "insert", "databaseName": "sdam-tests" } } ] } ], "outcome": [ { "collectionName": "connectTimeoutMS", "databaseName": "sdam-tests", "documents": [ { "_id": 1 }, { "_id": 2 }, { "_id": 3 }, { "_id": 4 } ] } ] } ] } mongodb-mongo-python-driver-509e9b7/test/discovery_and_monitoring/unified/find-network-error.json000066400000000000000000000125441462766011000335740ustar00rootroot00000000000000{ "description": "find-network-error", "schemaVersion": "1.4", "runOnRequirements": [ { "minServerVersion": "4.4", "serverless": "forbid", "topologies": [ "single", "replicaset", "sharded" ] } ], "createEntities": [ { "client": { "id": "setupClient", "useMultipleMongoses": false } } ], "initialData": [ { "collectionName": "find-network-error", "databaseName": "sdam-tests", "documents": [ { "_id": 1 }, { "_id": 2 } ] } ], "tests": [ { "description": "Reset server and pool after network error on find", "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "setupClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "find" ], "closeConnection": true, "appName": "findNetworkErrorTest" } } } }, { "name": "createEntities", "object": "testRunner", "arguments": { "entities": [ { "client": { "id": "client", "useMultipleMongoses": false, "observeEvents": [ "commandStartedEvent", "serverDescriptionChangedEvent", "poolClearedEvent" ], "uriOptions": { "retryWrites": false, "retryReads": false, "appname": "findNetworkErrorTest" } } }, { "database": { "id": "database", "client": "client", "databaseName": "sdam-tests" } }, { "collection": { "id": "collection", "database": "database", "collectionName": "find-network-error" } } ] } }, { "name": "find", "object": "collection", "arguments": { "filter": { "_id": 1 } }, "expectError": { "isError": true } }, { "name": "waitForEvent", "object": "testRunner", "arguments": { "client": "client", "event": { "serverDescriptionChangedEvent": { "newDescription": { "type": "Unknown" } } }, "count": 1 } }, { "name": "waitForEvent", "object": "testRunner", "arguments": { "client": "client", "event": { "poolClearedEvent": {} }, "count": 1 } }, { "name": "insertMany", "object": "collection", "arguments": { "documents": [ { "_id": 5 }, { "_id": 6 } ] } }, { "name": "assertEventCount", "object": "testRunner", "arguments": { "client": "client", "event": { "serverDescriptionChangedEvent": { "newDescription": { "type": "Unknown" } } }, "count": 1 } }, { "name": "assertEventCount", "object": "testRunner", "arguments": { "client": "client", "event": { "poolClearedEvent": {} }, "count": 1 } } ], "expectEvents": [ { "client": "client", "eventType": "command", "events": [ { "commandStartedEvent": { "command": { "find": "find-network-error" }, "commandName": "find", "databaseName": "sdam-tests" } }, { "commandStartedEvent": { "command": { "insert": "find-network-error", "documents": [ { "_id": 5 }, { "_id": 6 } ] }, "commandName": "insert", "databaseName": "sdam-tests" } } ] } ], "outcome": [ { "collectionName": "find-network-error", "databaseName": "sdam-tests", "documents": [ { "_id": 1 }, { "_id": 2 }, { "_id": 5 }, { "_id": 6 } ] } ] } ] } find-network-timeout-error.json000066400000000000000000000112211462766011000351700ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/discovery_and_monitoring/unified{ "description": "find-network-timeout-error", "schemaVersion": "1.4", "runOnRequirements": [ { "minServerVersion": "4.4", "serverless": "forbid", "topologies": [ "single", "replicaset", "sharded" ] } ], "createEntities": [ { "client": { "id": "setupClient", "useMultipleMongoses": false } } ], "initialData": [ { "collectionName": "find-network-timeout-error", "databaseName": "sdam-tests", "documents": [ { "_id": 1 }, { "_id": 2 } ] } ], "tests": [ { "description": "Ignore network timeout error on find", "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "setupClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "find" ], "blockConnection": true, "blockTimeMS": 500, "appName": "findNetworkTimeoutErrorTest" } } } }, { "name": "createEntities", "object": "testRunner", "arguments": { "entities": [ { "client": { "id": "client", "useMultipleMongoses": false, "observeEvents": [ "commandStartedEvent", "serverDescriptionChangedEvent", "poolClearedEvent" ], "uriOptions": { "retryWrites": false, "retryReads": false, "appname": "findNetworkTimeoutErrorTest", "socketTimeoutMS": 250 } } }, { "database": { "id": "database", "client": "client", "databaseName": "sdam-tests" } }, { "collection": { "id": "collection", "database": "database", "collectionName": "find-network-timeout-error" } } ] } }, { "name": "find", "object": "collection", "arguments": { "filter": { "_id": 1 } }, "expectError": { "isError": true } }, { "name": "insertOne", "object": "collection", "arguments": { "document": { "_id": 3 } } }, { "name": "assertEventCount", "object": "testRunner", "arguments": { "client": "client", "event": { "serverDescriptionChangedEvent": { "newDescription": { "type": "Unknown" } } }, "count": 0 } }, { "name": "assertEventCount", "object": "testRunner", "arguments": { "client": "client", "event": { "poolClearedEvent": {} }, "count": 0 } } ], "expectEvents": [ { "client": "client", "eventType": "command", "events": [ { "commandStartedEvent": { "command": { "find": "find-network-timeout-error" }, "commandName": "find", "databaseName": "sdam-tests" } }, { "commandStartedEvent": { "command": { "insert": "find-network-timeout-error", "documents": [ { "_id": 3 } ] }, "commandName": "insert", "databaseName": "sdam-tests" } } ] } ], "outcome": [ { "collectionName": "find-network-timeout-error", "databaseName": "sdam-tests", "documents": [ { "_id": 1 }, { "_id": 2 }, { "_id": 3 } ] } ] } ] } mongodb-mongo-python-driver-509e9b7/test/discovery_and_monitoring/unified/find-shutdown-error.json000066400000000000000000000135001462766011000337470ustar00rootroot00000000000000{ "description": "find-shutdown-error", "schemaVersion": "1.4", "runOnRequirements": [ { "minServerVersion": "4.4", "serverless": "forbid", "topologies": [ "single", "replicaset", "sharded" ] } ], "createEntities": [ { "client": { "id": "setupClient", "useMultipleMongoses": false } } ], "initialData": [ { "collectionName": "find-shutdown-error", "databaseName": "sdam-tests", "documents": [] } ], "tests": [ { "description": "Concurrent shutdown error on find", "operations": [ { "name": "createEntities", "object": "testRunner", "arguments": { "entities": [ { "client": { "id": "client", "useMultipleMongoses": false, "uriOptions": { "retryWrites": false, "retryReads": false, "heartbeatFrequencyMS": 500, "appname": "shutdownErrorFindTest" }, "observeEvents": [ "serverDescriptionChangedEvent", "poolClearedEvent" ] } }, { "database": { "id": "database", "client": "client", "databaseName": "sdam-tests" } }, { "collection": { "id": "collection", "database": "database", "collectionName": "find-shutdown-error" } } ] } }, { "name": "insertOne", "object": "collection", "arguments": { "document": { "_id": 1 } } }, { "name": "failPoint", "object": "testRunner", "arguments": { "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 2 }, "data": { "failCommands": [ "find" ], "appName": "shutdownErrorFindTest", "errorCode": 91, "blockConnection": true, "blockTimeMS": 500 } }, "client": "setupClient" } }, { "name": "createEntities", "object": "testRunner", "arguments": { "entities": [ { "thread": { "id": "thread0" } }, { "thread": { "id": "thread1" } } ] } }, { "name": "runOnThread", "object": "testRunner", "arguments": { "thread": "thread0", "operation": { "name": "find", "object": "collection", "arguments": { "filter": { "_id": 1 } }, "expectError": { "isError": true } } } }, { "name": "runOnThread", "object": "testRunner", "arguments": { "thread": "thread1", "operation": { "name": "find", "object": "collection", "arguments": { "filter": { "_id": 1 } }, "expectError": { "isError": true } } } }, { "name": "waitForThread", "object": "testRunner", "arguments": { "thread": "thread0" } }, { "name": "waitForThread", "object": "testRunner", "arguments": { "thread": "thread1" } }, { "name": "waitForEvent", "object": "testRunner", "arguments": { "client": "client", "event": { "serverDescriptionChangedEvent": { "newDescription": { "type": "Unknown" } } }, "count": 1 } }, { "name": "waitForEvent", "object": "testRunner", "arguments": { "client": "client", "event": { "poolClearedEvent": {} }, "count": 1 } }, { "name": "insertOne", "object": "collection", "arguments": { "document": { "_id": 4 } } }, { "name": "assertEventCount", "object": "testRunner", "arguments": { "client": "client", "event": { "serverDescriptionChangedEvent": { "newDescription": { "type": "Unknown" } } }, "count": 1 } }, { "name": "assertEventCount", "object": "testRunner", "arguments": { "client": "client", "event": { "poolClearedEvent": {} }, "count": 1 } } ], "outcome": [ { "collectionName": "find-shutdown-error", "databaseName": "sdam-tests", "documents": [ { "_id": 1 }, { "_id": 4 } ] } ] } ] } mongodb-mongo-python-driver-509e9b7/test/discovery_and_monitoring/unified/hello-command-error.json000066400000000000000000000220621462766011000337000ustar00rootroot00000000000000{ "description": "hello-command-error", "schemaVersion": "1.4", "runOnRequirements": [ { "minServerVersion": "4.9", "serverless": "forbid", "topologies": [ "single", "replicaset", "sharded" ] } ], "createEntities": [ { "client": { "id": "setupClient", "useMultipleMongoses": false } } ], "initialData": [ { "collectionName": "hello-command-error", "databaseName": "sdam-tests", "documents": [] } ], "tests": [ { "description": "Command error on Monitor handshake", "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "setupClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 4 }, "data": { "failCommands": [ "hello", "isMaster" ], "appName": "commandErrorHandshakeTest", "closeConnection": false, "errorCode": 91 } } } }, { "name": "createEntities", "object": "testRunner", "arguments": { "entities": [ { "client": { "id": "client", "useMultipleMongoses": false, "observeEvents": [ "serverDescriptionChangedEvent", "poolClearedEvent", "commandStartedEvent" ], "uriOptions": { "retryWrites": false, "connectTimeoutMS": 250, "heartbeatFrequencyMS": 500, "appname": "commandErrorHandshakeTest" } } }, { "database": { "id": "database", "client": "client", "databaseName": "sdam-tests" } }, { "collection": { "id": "collection", "database": "database", "collectionName": "hello-command-error" } } ] } }, { "name": "waitForEvent", "object": "testRunner", "arguments": { "client": "client", "event": { "serverDescriptionChangedEvent": { "newDescription": { "type": "Unknown" } } }, "count": 1 } }, { "name": "insertMany", "object": "collection", "arguments": { "documents": [ { "_id": 1 }, { "_id": 2 } ] } } ], "expectEvents": [ { "client": "client", "eventType": "command", "events": [ { "commandStartedEvent": { "command": { "insert": "hello-command-error", "documents": [ { "_id": 1 }, { "_id": 2 } ] }, "commandName": "insert", "databaseName": "sdam-tests" } } ] } ], "outcome": [ { "collectionName": "hello-command-error", "databaseName": "sdam-tests", "documents": [ { "_id": 1 }, { "_id": 2 } ] } ] }, { "description": "Command error on Monitor check", "operations": [ { "name": "createEntities", "object": "testRunner", "arguments": { "entities": [ { "client": { "id": "client", "useMultipleMongoses": false, "observeEvents": [ "commandStartedEvent", "serverDescriptionChangedEvent", "poolClearedEvent" ], "uriOptions": { "retryWrites": false, "connectTimeoutMS": 1000, "heartbeatFrequencyMS": 500, "appname": "commandErrorCheckTest" } } }, { "database": { "id": "database", "client": "client", "databaseName": "sdam-tests" } }, { "collection": { "id": "collection", "database": "database", "collectionName": "hello-command-error" } } ] } }, { "name": "insertMany", "object": "collection", "arguments": { "documents": [ { "_id": 1 }, { "_id": 2 } ] } }, { "name": "failPoint", "object": "testRunner", "arguments": { "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 2 }, "data": { "failCommands": [ "hello", "isMaster" ], "appName": "commandErrorCheckTest", "closeConnection": false, "blockConnection": true, "blockTimeMS": 750, "errorCode": 91 } }, "client": "setupClient" } }, { "name": "waitForEvent", "object": "testRunner", "arguments": { "client": "client", "event": { "serverDescriptionChangedEvent": { "newDescription": { "type": "Unknown" } } }, "count": 1 } }, { "name": "waitForEvent", "object": "testRunner", "arguments": { "client": "client", "event": { "poolClearedEvent": {} }, "count": 1 } }, { "name": "insertMany", "object": "collection", "arguments": { "documents": [ { "_id": 3 }, { "_id": 4 } ] } }, { "name": "assertEventCount", "object": "testRunner", "arguments": { "client": "client", "event": { "serverDescriptionChangedEvent": { "newDescription": { "type": "Unknown" } } }, "count": 1 } }, { "name": "assertEventCount", "object": "testRunner", "arguments": { "client": "client", "event": { "poolClearedEvent": {} }, "count": 1 } } ], "expectEvents": [ { "client": "client", "eventType": "command", "events": [ { "commandStartedEvent": { "command": { "insert": "hello-command-error", "documents": [ { "_id": 1 }, { "_id": 2 } ] }, "commandName": "insert", "databaseName": "sdam-tests" } }, { "commandStartedEvent": { "command": { "insert": "hello-command-error", "documents": [ { "_id": 3 }, { "_id": 4 } ] }, "commandName": "insert", "databaseName": "sdam-tests" } } ] } ], "outcome": [ { "collectionName": "hello-command-error", "databaseName": "sdam-tests", "documents": [ { "_id": 1 }, { "_id": 2 }, { "_id": 3 }, { "_id": 4 } ] } ] } ] } mongodb-mongo-python-driver-509e9b7/test/discovery_and_monitoring/unified/hello-network-error.json000066400000000000000000000204421462766011000337530ustar00rootroot00000000000000{ "description": "hello-network-error", "schemaVersion": "1.4", "runOnRequirements": [ { "minServerVersion": "4.9", "serverless": "forbid", "topologies": [ "single", "replicaset", "sharded" ] } ], "createEntities": [ { "client": { "id": "setupClient", "useMultipleMongoses": false } } ], "initialData": [ { "collectionName": "hello-network-error", "databaseName": "sdam-tests", "documents": [] } ], "tests": [ { "description": "Network error on Monitor handshake", "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "setupClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 2 }, "data": { "failCommands": [ "hello", "isMaster" ], "appName": "networkErrorHandshakeTest", "closeConnection": true } } } }, { "name": "createEntities", "object": "testRunner", "arguments": { "entities": [ { "client": { "id": "client", "useMultipleMongoses": false, "observeEvents": [ "commandStartedEvent", "serverDescriptionChangedEvent", "poolClearedEvent" ], "uriOptions": { "retryWrites": false, "connectTimeoutMS": 250, "heartbeatFrequencyMS": 500, "appname": "networkErrorHandshakeTest" } } }, { "database": { "id": "database", "client": "client", "databaseName": "sdam-tests" } }, { "collection": { "id": "collection", "database": "database", "collectionName": "hello-network-error" } } ] } }, { "name": "waitForEvent", "object": "testRunner", "arguments": { "client": "client", "event": { "serverDescriptionChangedEvent": { "newDescription": { "type": "Unknown" } } }, "count": 1 } }, { "name": "insertMany", "object": "collection", "arguments": { "documents": [ { "_id": 1 }, { "_id": 2 } ] } } ], "expectEvents": [ { "client": "client", "eventType": "command", "events": [ { "commandStartedEvent": { "command": { "insert": "hello-network-error", "documents": [ { "_id": 1 }, { "_id": 2 } ] }, "commandName": "insert", "databaseName": "sdam-tests" } } ] } ], "outcome": [ { "collectionName": "hello-network-error", "databaseName": "sdam-tests", "documents": [ { "_id": 1 }, { "_id": 2 } ] } ] }, { "description": "Network error on Monitor check", "operations": [ { "name": "createEntities", "object": "testRunner", "arguments": { "entities": [ { "client": { "id": "client", "useMultipleMongoses": false, "observeEvents": [ "commandStartedEvent", "serverDescriptionChangedEvent", "poolClearedEvent" ], "uriOptions": { "retryWrites": false, "connectTimeoutMS": 250, "heartbeatFrequencyMS": 500, "appname": "networkErrorCheckTest" } } }, { "database": { "id": "database", "client": "client", "databaseName": "sdam-tests" } }, { "collection": { "id": "collection", "database": "database", "collectionName": "hello-network-error" } } ] } }, { "name": "insertMany", "object": "collection", "arguments": { "documents": [ { "_id": 1 }, { "_id": 2 } ] } }, { "name": "failPoint", "object": "testRunner", "arguments": { "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 4 }, "data": { "failCommands": [ "hello", "isMaster" ], "appName": "networkErrorCheckTest", "closeConnection": true } }, "client": "setupClient" } }, { "name": "waitForEvent", "object": "testRunner", "arguments": { "client": "client", "event": { "serverDescriptionChangedEvent": { "newDescription": { "type": "Unknown" } } }, "count": 1 } }, { "name": "waitForEvent", "object": "testRunner", "arguments": { "client": "client", "event": { "poolClearedEvent": {} }, "count": 1 } }, { "name": "insertMany", "object": "collection", "arguments": { "documents": [ { "_id": 3 }, { "_id": 4 } ] } } ], "expectEvents": [ { "client": "client", "eventType": "command", "events": [ { "commandStartedEvent": { "command": { "insert": "hello-network-error", "documents": [ { "_id": 1 }, { "_id": 2 } ] }, "commandName": "insert", "databaseName": "sdam-tests" } }, { "commandStartedEvent": { "command": { "insert": "hello-network-error", "documents": [ { "_id": 3 }, { "_id": 4 } ] }, "commandName": "insert", "databaseName": "sdam-tests" } } ] } ], "outcome": [ { "collectionName": "hello-network-error", "databaseName": "sdam-tests", "documents": [ { "_id": 1 }, { "_id": 2 }, { "_id": 3 }, { "_id": 4 } ] } ] } ] } mongodb-mongo-python-driver-509e9b7/test/discovery_and_monitoring/unified/hello-timeout.json000066400000000000000000000304071462766011000326230ustar00rootroot00000000000000{ "description": "hello-timeout", "schemaVersion": "1.4", "runOnRequirements": [ { "minServerVersion": "4.4", "serverless": "forbid", "topologies": [ "single", "replicaset", "sharded" ] } ], "createEntities": [ { "client": { "id": "setupClient", "useMultipleMongoses": false } } ], "initialData": [ { "collectionName": "hello-timeout", "databaseName": "sdam-tests", "documents": [] } ], "tests": [ { "description": "Network timeout on Monitor handshake", "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "setupClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 2 }, "data": { "failCommands": [ "hello", "isMaster" ], "appName": "timeoutMonitorHandshakeTest", "blockConnection": true, "blockTimeMS": 1000 } } } }, { "name": "createEntities", "object": "testRunner", "arguments": { "entities": [ { "client": { "id": "client", "useMultipleMongoses": false, "observeEvents": [ "commandStartedEvent", "serverDescriptionChangedEvent", "poolClearedEvent" ], "uriOptions": { "retryWrites": false, "connectTimeoutMS": 250, "heartbeatFrequencyMS": 500, "appname": "timeoutMonitorHandshakeTest" } } }, { "database": { "id": "database", "client": "client", "databaseName": "sdam-tests" } }, { "collection": { "id": "collection", "database": "database", "collectionName": "hello-timeout" } } ] } }, { "name": "waitForEvent", "object": "testRunner", "arguments": { "client": "client", "event": { "serverDescriptionChangedEvent": { "newDescription": { "type": "Unknown" } } }, "count": 1 } }, { "name": "insertMany", "object": "collection", "arguments": { "documents": [ { "_id": 1 }, { "_id": 2 } ] } } ], "expectEvents": [ { "client": "client", "eventType": "command", "events": [ { "commandStartedEvent": { "command": { "insert": "hello-timeout", "documents": [ { "_id": 1 }, { "_id": 2 } ] }, "commandName": "insert", "databaseName": "sdam-tests" } } ] } ], "outcome": [ { "collectionName": "hello-timeout", "databaseName": "sdam-tests", "documents": [ { "_id": 1 }, { "_id": 2 } ] } ] }, { "description": "Network timeout on Monitor check", "operations": [ { "name": "createEntities", "object": "testRunner", "arguments": { "entities": [ { "client": { "id": "client", "useMultipleMongoses": false, "observeEvents": [ "commandStartedEvent", "serverDescriptionChangedEvent", "poolClearedEvent" ], "uriOptions": { "retryWrites": false, "connectTimeoutMS": 750, "heartbeatFrequencyMS": 500, "appname": "timeoutMonitorCheckTest" } } }, { "database": { "id": "database", "client": "client", "databaseName": "sdam-tests" } }, { "collection": { "id": "collection", "database": "database", "collectionName": "hello-timeout" } } ] } }, { "name": "insertMany", "object": "collection", "arguments": { "documents": [ { "_id": 1 }, { "_id": 2 } ] } }, { "name": "failPoint", "object": "testRunner", "arguments": { "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 4 }, "data": { "failCommands": [ "hello", "isMaster" ], "appName": "timeoutMonitorCheckTest", "blockConnection": true, "blockTimeMS": 1000 } }, "client": "setupClient" } }, { "name": "waitForEvent", "object": "testRunner", "arguments": { "client": "client", "event": { "serverDescriptionChangedEvent": { "newDescription": { "type": "Unknown" } } }, "count": 1 } }, { "name": "waitForEvent", "object": "testRunner", "arguments": { "client": "client", "event": { "poolClearedEvent": {} }, "count": 1 } }, { "name": "insertMany", "object": "collection", "arguments": { "documents": [ { "_id": 3 }, { "_id": 4 } ] } } ], "expectEvents": [ { "client": "client", "eventType": "command", "events": [ { "commandStartedEvent": { "command": { "insert": "hello-timeout", "documents": [ { "_id": 1 }, { "_id": 2 } ] }, "commandName": "insert", "databaseName": "sdam-tests" } }, { "commandStartedEvent": { "command": { "insert": "hello-timeout", "documents": [ { "_id": 3 }, { "_id": 4 } ] }, "commandName": "insert", "databaseName": "sdam-tests" } } ] } ], "outcome": [ { "collectionName": "hello-timeout", "databaseName": "sdam-tests", "documents": [ { "_id": 1 }, { "_id": 2 }, { "_id": 3 }, { "_id": 4 } ] } ] }, { "description": "Driver extends timeout while streaming", "operations": [ { "name": "createEntities", "object": "testRunner", "arguments": { "entities": [ { "client": { "id": "client", "observeEvents": [ "commandStartedEvent", "serverDescriptionChangedEvent", "poolClearedEvent" ], "uriOptions": { "retryWrites": false, "connectTimeoutMS": 250, "heartbeatFrequencyMS": 500, "appname": "extendsTimeoutTest" } } }, { "database": { "id": "database", "client": "client", "databaseName": "sdam-tests" } }, { "collection": { "id": "collection", "database": "database", "collectionName": "hello-timeout" } } ] } }, { "name": "insertMany", "object": "collection", "arguments": { "documents": [ { "_id": 1 }, { "_id": 2 } ] } }, { "name": "wait", "object": "testRunner", "arguments": { "ms": 2000 } }, { "name": "insertMany", "object": "collection", "arguments": { "documents": [ { "_id": 3 }, { "_id": 4 } ] } }, { "name": "assertEventCount", "object": "testRunner", "arguments": { "client": "client", "event": { "serverDescriptionChangedEvent": { "newDescription": { "type": "Unknown" } } }, "count": 0 } }, { "name": "assertEventCount", "object": "testRunner", "arguments": { "client": "client", "event": { "poolClearedEvent": {} }, "count": 0 } } ], "expectEvents": [ { "client": "client", "eventType": "command", "events": [ { "commandStartedEvent": { "command": { "insert": "hello-timeout", "documents": [ { "_id": 1 }, { "_id": 2 } ] }, "commandName": "insert", "databaseName": "sdam-tests" } }, { "commandStartedEvent": { "command": { "insert": "hello-timeout", "documents": [ { "_id": 3 }, { "_id": 4 } ] }, "commandName": "insert", "databaseName": "sdam-tests" } } ] } ], "outcome": [ { "collectionName": "hello-timeout", "databaseName": "sdam-tests", "documents": [ { "_id": 1 }, { "_id": 2 }, { "_id": 3 }, { "_id": 4 } ] } ] } ] } mongodb-mongo-python-driver-509e9b7/test/discovery_and_monitoring/unified/insert-network-error.json000066400000000000000000000132051462766011000341530ustar00rootroot00000000000000{ "description": "insert-network-error", "schemaVersion": "1.4", "runOnRequirements": [ { "minServerVersion": "4.4", "serverless": "forbid", "topologies": [ "single", "replicaset", "sharded" ] } ], "createEntities": [ { "client": { "id": "setupClient", "useMultipleMongoses": false } } ], "initialData": [ { "collectionName": "insert-network-error", "databaseName": "sdam-tests", "documents": [ { "_id": 1 }, { "_id": 2 } ] } ], "tests": [ { "description": "Reset server and pool after network error on insert", "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "setupClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "insert" ], "closeConnection": true, "appName": "insertNetworkErrorTest" } } } }, { "name": "createEntities", "object": "testRunner", "arguments": { "entities": [ { "client": { "id": "client", "observeEvents": [ "commandStartedEvent", "serverDescriptionChangedEvent", "poolClearedEvent" ], "uriOptions": { "retryWrites": false, "appname": "insertNetworkErrorTest" }, "useMultipleMongoses": false } }, { "database": { "id": "database", "client": "client", "databaseName": "sdam-tests" } }, { "collection": { "id": "collection", "database": "database", "collectionName": "insert-network-error" } } ] } }, { "name": "insertMany", "object": "collection", "arguments": { "documents": [ { "_id": 3 }, { "_id": 4 } ] }, "expectError": { "isError": true } }, { "name": "waitForEvent", "object": "testRunner", "arguments": { "client": "client", "event": { "serverDescriptionChangedEvent": { "newDescription": { "type": "Unknown" } } }, "count": 1 } }, { "name": "waitForEvent", "object": "testRunner", "arguments": { "client": "client", "event": { "poolClearedEvent": {} }, "count": 1 } }, { "name": "insertMany", "object": "collection", "arguments": { "documents": [ { "_id": 5 }, { "_id": 6 } ] } }, { "name": "assertEventCount", "object": "testRunner", "arguments": { "client": "client", "event": { "serverDescriptionChangedEvent": { "newDescription": { "type": "Unknown" } } }, "count": 1 } }, { "name": "assertEventCount", "object": "testRunner", "arguments": { "client": "client", "event": { "poolClearedEvent": {} }, "count": 1 } } ], "expectEvents": [ { "client": "client", "eventType": "command", "events": [ { "commandStartedEvent": { "command": { "insert": "insert-network-error", "documents": [ { "_id": 3 }, { "_id": 4 } ] }, "commandName": "insert", "databaseName": "sdam-tests" } }, { "commandStartedEvent": { "command": { "insert": "insert-network-error", "documents": [ { "_id": 5 }, { "_id": 6 } ] }, "commandName": "insert", "databaseName": "sdam-tests" } } ] } ], "outcome": [ { "collectionName": "insert-network-error", "databaseName": "sdam-tests", "documents": [ { "_id": 1 }, { "_id": 2 }, { "_id": 5 }, { "_id": 6 } ] } ] } ] } mongodb-mongo-python-driver-509e9b7/test/discovery_and_monitoring/unified/insert-shutdown-error.json000066400000000000000000000134651462766011000343450ustar00rootroot00000000000000{ "description": "insert-shutdown-error", "schemaVersion": "1.4", "runOnRequirements": [ { "minServerVersion": "4.4", "serverless": "forbid", "topologies": [ "single", "replicaset", "sharded" ] } ], "createEntities": [ { "client": { "id": "setupClient", "useMultipleMongoses": false } } ], "initialData": [ { "collectionName": "insert-shutdown-error", "databaseName": "sdam-tests", "documents": [] } ], "tests": [ { "description": "Concurrent shutdown error on insert", "operations": [ { "name": "createEntities", "object": "testRunner", "arguments": { "entities": [ { "client": { "id": "client", "useMultipleMongoses": false, "uriOptions": { "retryWrites": false, "heartbeatFrequencyMS": 500, "appname": "shutdownErrorInsertTest" }, "observeEvents": [ "serverDescriptionChangedEvent", "poolClearedEvent" ] } }, { "database": { "id": "database", "client": "client", "databaseName": "sdam-tests" } }, { "collection": { "id": "collection", "database": "database", "collectionName": "insert-shutdown-error" } } ] } }, { "name": "insertOne", "object": "collection", "arguments": { "document": { "_id": 1 } } }, { "name": "failPoint", "object": "testRunner", "arguments": { "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 2 }, "data": { "failCommands": [ "insert" ], "appName": "shutdownErrorInsertTest", "errorCode": 91, "blockConnection": true, "blockTimeMS": 500 } }, "client": "setupClient" } }, { "name": "createEntities", "object": "testRunner", "arguments": { "entities": [ { "thread": { "id": "thread0" } }, { "thread": { "id": "thread1" } } ] } }, { "name": "runOnThread", "object": "testRunner", "arguments": { "thread": "thread0", "operation": { "name": "insertOne", "object": "collection", "arguments": { "document": { "_id": 2 } }, "expectError": { "isError": true } } } }, { "name": "runOnThread", "object": "testRunner", "arguments": { "thread": "thread1", "operation": { "name": "insertOne", "object": "collection", "arguments": { "document": { "_id": 3 } }, "expectError": { "isError": true } } } }, { "name": "waitForThread", "object": "testRunner", "arguments": { "thread": "thread0" } }, { "name": "waitForThread", "object": "testRunner", "arguments": { "thread": "thread1" } }, { "name": "waitForEvent", "object": "testRunner", "arguments": { "client": "client", "event": { "serverDescriptionChangedEvent": { "newDescription": { "type": "Unknown" } } }, "count": 1 } }, { "name": "waitForEvent", "object": "testRunner", "arguments": { "client": "client", "event": { "poolClearedEvent": {} }, "count": 1 } }, { "name": "insertOne", "object": "collection", "arguments": { "document": { "_id": 4 } } }, { "name": "assertEventCount", "object": "testRunner", "arguments": { "client": "client", "event": { "serverDescriptionChangedEvent": { "newDescription": { "type": "Unknown" } } }, "count": 1 } }, { "name": "assertEventCount", "object": "testRunner", "arguments": { "client": "client", "event": { "poolClearedEvent": {} }, "count": 1 } } ], "outcome": [ { "collectionName": "insert-shutdown-error", "databaseName": "sdam-tests", "documents": [ { "_id": 1 }, { "_id": 4 } ] } ] } ] } interruptInUse-pool-clear.json000066400000000000000000000343371462766011000350160ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/discovery_and_monitoring/unified{ "description": "interruptInUse", "schemaVersion": "1.11", "runOnRequirements": [ { "minServerVersion": "4.9", "topologies": [ "replicaset", "sharded" ], "serverless": "forbid" } ], "createEntities": [ { "client": { "id": "setupClient", "useMultipleMongoses": false } } ], "initialData": [ { "collectionName": "interruptInUse", "databaseName": "sdam-tests", "documents": [] } ], "tests": [ { "description": "Connection pool clear uses interruptInUseConnections=true after monitor timeout", "operations": [ { "name": "createEntities", "object": "testRunner", "arguments": { "entities": [ { "client": { "id": "client", "useMultipleMongoses": false, "uriOptions": { "connectTimeoutMS": 500, "heartbeatFrequencyMS": 500, "appname": "interruptInUse", "retryReads": false, "minPoolSize": 0 }, "observeEvents": [ "poolClearedEvent", "connectionClosedEvent", "commandStartedEvent", "commandSucceededEvent", "commandFailedEvent", "connectionCheckedOutEvent", "connectionCheckedInEvent" ] } }, { "database": { "id": "database", "client": "client", "databaseName": "sdam-tests" } }, { "collection": { "id": "collection", "database": "database", "collectionName": "interruptInUse" } }, { "thread": { "id": "thread1" } } ] } }, { "name": "insertOne", "object": "collection", "arguments": { "document": { "_id" : 1 } } }, { "name": "runOnThread", "object": "testRunner", "arguments": { "thread": "thread1", "operation": { "name": "find", "object": "collection", "arguments": { "filter": { "$where": "sleep(2000) || true" } }, "expectError": { "isError": true } } } }, { "name": "failPoint", "object": "testRunner", "arguments": { "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 4 }, "data": { "failCommands": [ "hello", "isMaster" ], "blockConnection": true, "blockTimeMS": 1500, "appName": "interruptInUse" } }, "client": "setupClient" } }, { "name": "waitForThread", "object": "testRunner", "arguments": { "thread": "thread1" } } ], "expectEvents": [ { "client": "client", "eventType": "command", "events": [ { "commandStartedEvent": { "commandName": "insert" } }, { "commandSucceededEvent": { "commandName": "insert" } }, { "commandStartedEvent": { "commandName": "find" } }, { "commandFailedEvent": { "commandName": "find" } } ] }, { "client": "client", "eventType": "cmap", "events": [ { "connectionCheckedOutEvent": { } }, { "connectionCheckedInEvent": { } }, { "connectionCheckedOutEvent": { } }, { "poolClearedEvent": { "interruptInUseConnections": true } }, { "connectionCheckedInEvent": {} }, { "connectionClosedEvent": { } } ] } ], "outcome": [{ "collectionName": "interruptInUse", "databaseName": "sdam-tests", "documents": [{ "_id": 1 }] }] }, { "description": "Error returned from connection pool clear with interruptInUseConnections=true is retryable", "operations": [ { "name": "createEntities", "object": "testRunner", "arguments": { "entities": [ { "client": { "id": "client", "useMultipleMongoses": false, "uriOptions": { "connectTimeoutMS": 500, "heartbeatFrequencyMS": 500, "appname": "interruptInUseRetryable", "retryReads": true, "minPoolSize": 0 }, "observeEvents": [ "poolClearedEvent", "connectionClosedEvent", "commandFailedEvent", "commandStartedEvent", "commandSucceededEvent", "connectionCheckedOutEvent", "connectionCheckedInEvent" ] } }, { "database": { "id": "database", "client": "client", "databaseName": "sdam-tests" } }, { "collection": { "id": "collection", "database": "database", "collectionName": "interruptInUse" } }, { "thread": { "id": "thread1" } } ] } }, { "name": "insertOne", "object": "collection", "arguments": { "document": { "_id" : 1 } } }, { "name": "runOnThread", "object": "testRunner", "arguments": { "thread": "thread1", "operation": { "name": "find", "object": "collection", "arguments": { "filter": { "$where": "sleep(2000) || true" } } } } }, { "name": "failPoint", "object": "testRunner", "arguments": { "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 4 }, "data": { "failCommands": [ "hello", "isMaster" ], "blockConnection": true, "blockTimeMS": 1500, "appName": "interruptInUseRetryable" } }, "client": "setupClient" } }, { "name": "waitForThread", "object": "testRunner", "arguments": { "thread": "thread1" } } ], "expectEvents": [ { "client": "client", "eventType": "command", "events": [ { "commandStartedEvent": { "commandName": "insert" } }, { "commandSucceededEvent": { "commandName": "insert" } }, { "commandStartedEvent": { "commandName": "find" } }, { "commandFailedEvent": { "commandName": "find" } }, { "commandStartedEvent": { "commandName": "find" } }, { "commandSucceededEvent": { "commandName": "find" } } ] }, { "client": "client", "eventType": "cmap", "events": [ { "connectionCheckedOutEvent": { } }, { "connectionCheckedInEvent": { } }, { "connectionCheckedOutEvent": { } }, { "poolClearedEvent": { "interruptInUseConnections": true } }, { "connectionCheckedInEvent": {} }, { "connectionClosedEvent": { } }, { "connectionCheckedOutEvent": {} }, { "connectionCheckedInEvent": {} } ] } ], "outcome": [{ "collectionName": "interruptInUse", "databaseName": "sdam-tests", "documents": [{ "_id": 1 }] }] }, { "description": "Error returned from connection pool clear with interruptInUseConnections=true is retryable for write", "operations": [ { "name": "createEntities", "object": "testRunner", "arguments": { "entities": [ { "client": { "id": "client", "useMultipleMongoses": false, "uriOptions": { "connectTimeoutMS": 500, "heartbeatFrequencyMS": 500, "appname": "interruptInUseRetryableWrite", "retryWrites": true, "minPoolSize": 0 }, "observeEvents": [ "poolClearedEvent", "connectionClosedEvent", "commandFailedEvent", "commandStartedEvent", "commandSucceededEvent", "connectionCheckedOutEvent", "connectionCheckedInEvent" ]} }, { "database": { "id": "database", "client": "client", "databaseName": "sdam-tests" } }, { "collection": { "id": "collection", "database": "database", "collectionName": "interruptInUse" } }, { "thread": { "id": "thread1" } } ] } }, { "name": "insertOne", "object": "collection", "arguments": { "document": { "_id": 1 } } }, { "name": "runOnThread", "object": "testRunner", "arguments": { "thread": "thread1", "operation": { "name": "updateOne", "object": "collection", "arguments": { "filter": { "$where": "sleep(2000) || true" }, "update": [ { "$set": { "a": "bar" } } ] } } } }, { "name": "failPoint", "object": "testRunner", "arguments": { "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 4 }, "data": { "failCommands": [ "hello", "isMaster" ], "blockConnection": true, "blockTimeMS": 1500, "appName": "interruptInUseRetryableWrite" } }, "client": "setupClient" } }, { "name": "waitForThread", "object": "testRunner", "arguments": { "thread": "thread1" } } ], "expectEvents": [ { "client": "client", "eventType": "command", "events": [ { "commandStartedEvent": { "commandName": "insert" } }, { "commandSucceededEvent": { "commandName": "insert" } }, { "commandStartedEvent": { "commandName": "update" } }, { "commandFailedEvent": { "commandName": "update" } }, { "commandStartedEvent": { "commandName": "update" } }, { "commandSucceededEvent": { "commandName": "update" } } ] }, { "client": "client", "eventType": "cmap", "events": [ { "connectionCheckedOutEvent": { } }, { "connectionCheckedInEvent": { } }, { "connectionCheckedOutEvent": { } }, { "poolClearedEvent": { "interruptInUseConnections": true } }, { "connectionCheckedInEvent": {} }, { "connectionClosedEvent": { } }, { "connectionCheckedOutEvent": {} }, { "connectionCheckedInEvent": {} } ] } ], "outcome": [{ "collectionName": "interruptInUse", "databaseName": "sdam-tests", "documents": [{ "_id": 1, "a" : "bar"}] }] } ] }mongodb-mongo-python-driver-509e9b7/test/discovery_and_monitoring/unified/minPoolSize-error.json000066400000000000000000000103261462766011000334310ustar00rootroot00000000000000{ "description": "minPoolSize-error", "schemaVersion": "1.4", "runOnRequirements": [ { "minServerVersion": "4.9", "serverless": "forbid", "topologies": [ "single" ] } ], "createEntities": [ { "client": { "id": "setupClient", "useMultipleMongoses": false } } ], "initialData": [ { "collectionName": "sdam-minPoolSize-error", "databaseName": "sdam-tests", "documents": [] } ], "tests": [ { "description": "Network error on minPoolSize background creation", "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "setupClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "skip": 3 }, "data": { "failCommands": [ "hello", "isMaster" ], "appName": "SDAMminPoolSizeError", "closeConnection": true } } } }, { "name": "createEntities", "object": "testRunner", "arguments": { "entities": [ { "client": { "id": "client", "useMultipleMongoses": false, "observeEvents": [ "serverDescriptionChangedEvent", "poolClearedEvent", "poolReadyEvent" ], "uriOptions": { "heartbeatFrequencyMS": 10000, "appname": "SDAMminPoolSizeError", "minPoolSize": 10, "serverSelectionTimeoutMS": 1000 } } }, { "database": { "id": "database", "client": "client", "databaseName": "sdam-tests" } }, { "collection": { "id": "collection", "database": "database", "collectionName": "sdam-minPoolSize-error" } } ] } }, { "name": "waitForEvent", "object": "testRunner", "arguments": { "client": "client", "event": { "poolReadyEvent": {} }, "count": 1 } }, { "name": "waitForEvent", "object": "testRunner", "arguments": { "client": "client", "event": { "poolClearedEvent": {} }, "count": 1 } }, { "name": "waitForEvent", "object": "testRunner", "arguments": { "client": "client", "event": { "serverDescriptionChangedEvent": { "newDescription": { "type": "Unknown" } } }, "count": 1 } }, { "name": "runCommand", "object": "database", "arguments": { "command": { "ping": {} }, "commandName": "ping" }, "expectError": { "isError": true } }, { "name": "failPoint", "object": "testRunner", "arguments": { "failPoint": { "configureFailPoint": "failCommand", "mode": "off" }, "client": "setupClient" } }, { "name": "runCommand", "object": "database", "arguments": { "command": { "ping": 1 }, "commandName": "ping" } }, { "name": "assertEventCount", "object": "testRunner", "arguments": { "client": "client", "event": { "poolReadyEvent": {} }, "count": 2 } } ] } ] } mongodb-mongo-python-driver-509e9b7/test/discovery_and_monitoring/unified/pool-cleared-error.json000066400000000000000000000210171462766011000335260ustar00rootroot00000000000000{ "description": "pool-cleared-error", "schemaVersion": "1.4", "runOnRequirements": [ { "minServerVersion": "4.9", "serverless": "forbid", "topologies": [ "replicaset", "sharded" ] } ], "createEntities": [ { "client": { "id": "setupClient", "useMultipleMongoses": false } } ], "initialData": [ { "collectionName": "pool-cleared-error", "databaseName": "sdam-tests", "documents": [] } ], "tests": [ { "description": "PoolClearedError does not mark server unknown", "operations": [ { "name": "createEntities", "object": "testRunner", "arguments": { "entities": [ { "client": { "id": "client", "useMultipleMongoses": false, "observeEvents": [ "serverDescriptionChangedEvent", "poolClearedEvent" ], "uriOptions": { "retryWrites": true, "maxPoolSize": 1, "appname": "poolClearedErrorTest" } } }, { "database": { "id": "database", "client": "client", "databaseName": "sdam-tests" } }, { "collection": { "id": "collection", "database": "database", "collectionName": "pool-cleared-error" } } ] } }, { "name": "insertOne", "object": "collection", "arguments": { "document": { "_id": 1 } } }, { "name": "failPoint", "object": "testRunner", "arguments": { "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "insert" ], "blockConnection": true, "blockTimeMS": 100, "closeConnection": true, "appName": "poolClearedErrorTest" } }, "client": "setupClient" } }, { "name": "createEntities", "object": "testRunner", "arguments": { "entities": [ { "thread": { "id": "thread0" } }, { "thread": { "id": "thread1" } }, { "thread": { "id": "thread2" } }, { "thread": { "id": "thread3" } }, { "thread": { "id": "thread4" } }, { "thread": { "id": "thread5" } } ] } }, { "name": "runOnThread", "object": "testRunner", "arguments": { "thread": "thread0", "operation": { "name": "insertOne", "object": "collection", "arguments": { "document": { "_id": 2 } } } } }, { "name": "runOnThread", "object": "testRunner", "arguments": { "thread": "thread1", "operation": { "name": "insertOne", "object": "collection", "arguments": { "document": { "_id": 3 } } } } }, { "name": "runOnThread", "object": "testRunner", "arguments": { "thread": "thread2", "operation": { "name": "insertOne", "object": "collection", "arguments": { "document": { "_id": 4 } } } } }, { "name": "runOnThread", "object": "testRunner", "arguments": { "thread": "thread3", "operation": { "name": "insertOne", "object": "collection", "arguments": { "document": { "_id": 5 } } } } }, { "name": "runOnThread", "object": "testRunner", "arguments": { "thread": "thread4", "operation": { "name": "insertOne", "object": "collection", "arguments": { "document": { "_id": 6 } } } } }, { "name": "runOnThread", "object": "testRunner", "arguments": { "thread": "thread5", "operation": { "name": "insertOne", "object": "collection", "arguments": { "document": { "_id": 7 } } } } }, { "name": "waitForThread", "object": "testRunner", "arguments": { "thread": "thread0" } }, { "name": "waitForThread", "object": "testRunner", "arguments": { "thread": "thread1" } }, { "name": "waitForThread", "object": "testRunner", "arguments": { "thread": "thread2" } }, { "name": "waitForThread", "object": "testRunner", "arguments": { "thread": "thread3" } }, { "name": "waitForThread", "object": "testRunner", "arguments": { "thread": "thread4" } }, { "name": "waitForThread", "object": "testRunner", "arguments": { "thread": "thread5" } }, { "name": "waitForEvent", "object": "testRunner", "arguments": { "client": "client", "event": { "serverDescriptionChangedEvent": { "newDescription": { "type": "Unknown" } } }, "count": 1 } }, { "name": "waitForEvent", "object": "testRunner", "arguments": { "client": "client", "event": { "poolClearedEvent": {} }, "count": 1 } }, { "name": "insertOne", "object": "collection", "arguments": { "document": { "_id": 8 } } }, { "name": "assertEventCount", "object": "testRunner", "arguments": { "client": "client", "event": { "serverDescriptionChangedEvent": { "newDescription": { "type": "Unknown" } } }, "count": 1 } }, { "name": "assertEventCount", "object": "testRunner", "arguments": { "client": "client", "event": { "poolClearedEvent": {} }, "count": 1 } } ], "outcome": [ { "collectionName": "pool-cleared-error", "databaseName": "sdam-tests", "documents": [ { "_id": 1 }, { "_id": 2 }, { "_id": 3 }, { "_id": 4 }, { "_id": 5 }, { "_id": 6 }, { "_id": 7 }, { "_id": 8 } ] } ] } ] } rediscover-quickly-after-step-down.json000066400000000000000000000130641462766011000366160ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/discovery_and_monitoring/unified{ "description": "rediscover-quickly-after-step-down", "schemaVersion": "1.4", "runOnRequirements": [ { "minServerVersion": "4.4", "serverless": "forbid", "topologies": [ "replicaset" ] } ], "createEntities": [ { "client": { "id": "setupClient" } }, { "database": { "id": "adminDatabase", "client": "setupClient", "databaseName": "admin" } } ], "initialData": [ { "collectionName": "test-replSetStepDown", "databaseName": "sdam-tests", "documents": [ { "_id": 1 }, { "_id": 2 } ] } ], "tests": [ { "description": "Rediscover quickly after replSetStepDown", "operations": [ { "name": "createEntities", "object": "testRunner", "arguments": { "entities": [ { "client": { "id": "client", "observeEvents": [ "poolClearedEvent", "commandStartedEvent" ], "uriOptions": { "appname": "replSetStepDownTest", "heartbeatFrequencyMS": 60000, "serverSelectionTimeoutMS": 5000, "w": "majority" } } }, { "database": { "id": "database", "client": "client", "databaseName": "sdam-tests" } }, { "collection": { "id": "collection", "database": "database", "collectionName": "test-replSetStepDown" } } ] } }, { "name": "insertMany", "object": "collection", "arguments": { "documents": [ { "_id": 3 }, { "_id": 4 } ] } }, { "name": "recordTopologyDescription", "object": "testRunner", "arguments": { "client": "client", "id": "topologyDescription" } }, { "name": "assertTopologyType", "object": "testRunner", "arguments": { "topologyDescription": "topologyDescription", "topologyType": "ReplicaSetWithPrimary" } }, { "name": "runCommand", "object": "adminDatabase", "arguments": { "command": { "replSetFreeze": 0 }, "readPreference": { "mode": "secondary" }, "commandName": "replSetFreeze" } }, { "name": "runCommand", "object": "adminDatabase", "arguments": { "command": { "replSetStepDown": 30, "secondaryCatchUpPeriodSecs": 30, "force": false }, "commandName": "replSetStepDown" } }, { "name": "waitForPrimaryChange", "object": "testRunner", "arguments": { "client": "client", "priorTopologyDescription": "topologyDescription", "timeoutMS": 15000 } }, { "name": "insertMany", "object": "collection", "arguments": { "documents": [ { "_id": 5 }, { "_id": 6 } ] } }, { "name": "assertEventCount", "object": "testRunner", "arguments": { "client": "client", "event": { "poolClearedEvent": {} }, "count": 0 } } ], "expectEvents": [ { "client": "client", "eventType": "command", "events": [ { "commandStartedEvent": { "command": { "insert": "test-replSetStepDown", "documents": [ { "_id": 3 }, { "_id": 4 } ] }, "commandName": "insert", "databaseName": "sdam-tests" } }, { "commandStartedEvent": { "command": { "insert": "test-replSetStepDown", "documents": [ { "_id": 5 }, { "_id": 6 } ] }, "commandName": "insert", "databaseName": "sdam-tests" } } ] } ], "outcome": [ { "collectionName": "test-replSetStepDown", "databaseName": "sdam-tests", "documents": [ { "_id": 1 }, { "_id": 2 }, { "_id": 3 }, { "_id": 4 }, { "_id": 5 }, { "_id": 6 } ] } ] } ] } mongodb-mongo-python-driver-509e9b7/test/discovery_and_monitoring/unified/serverMonitoringMode.json000066400000000000000000000254611462766011000342210ustar00rootroot00000000000000{ "description": "serverMonitoringMode", "schemaVersion": "1.17", "runOnRequirements": [ { "topologies": [ "single", "sharded", "sharded-replicaset" ], "serverless": "forbid" } ], "tests": [ { "description": "connect with serverMonitoringMode=auto >=4.4", "runOnRequirements": [ { "minServerVersion": "4.4.0" } ], "operations": [ { "name": "createEntities", "object": "testRunner", "arguments": { "entities": [ { "client": { "id": "client", "uriOptions": { "serverMonitoringMode": "auto" }, "useMultipleMongoses": false, "observeEvents": [ "serverHeartbeatStartedEvent", "serverHeartbeatSucceededEvent", "serverHeartbeatFailedEvent" ] } }, { "database": { "id": "db", "client": "client", "databaseName": "sdam-tests" } } ] } }, { "name": "runCommand", "object": "db", "arguments": { "commandName": "ping", "command": { "ping": 1 } }, "expectResult": { "ok": 1 } }, { "name": "waitForEvent", "object": "testRunner", "arguments": { "client": "client", "event": { "serverHeartbeatStartedEvent": {} }, "count": 2 } } ], "expectEvents": [ { "client": "client", "eventType": "sdam", "ignoreExtraEvents": true, "events": [ { "serverHeartbeatStartedEvent": { "awaited": false } }, { "serverHeartbeatSucceededEvent": { "awaited": false } }, { "serverHeartbeatStartedEvent": { "awaited": true } } ] } ] }, { "description": "connect with serverMonitoringMode=auto <4.4", "runOnRequirements": [ { "maxServerVersion": "4.2.99" } ], "operations": [ { "name": "createEntities", "object": "testRunner", "arguments": { "entities": [ { "client": { "id": "client", "uriOptions": { "serverMonitoringMode": "auto", "heartbeatFrequencyMS": 500 }, "useMultipleMongoses": false, "observeEvents": [ "serverHeartbeatStartedEvent", "serverHeartbeatSucceededEvent", "serverHeartbeatFailedEvent" ] } }, { "database": { "id": "db", "client": "client", "databaseName": "sdam-tests" } } ] } }, { "name": "runCommand", "object": "db", "arguments": { "commandName": "ping", "command": { "ping": 1 } }, "expectResult": { "ok": 1 } }, { "name": "waitForEvent", "object": "testRunner", "arguments": { "client": "client", "event": { "serverHeartbeatStartedEvent": {} }, "count": 2 } } ], "expectEvents": [ { "client": "client", "eventType": "sdam", "ignoreExtraEvents": true, "events": [ { "serverHeartbeatStartedEvent": { "awaited": false } }, { "serverHeartbeatSucceededEvent": { "awaited": false } }, { "serverHeartbeatStartedEvent": { "awaited": false } } ] } ] }, { "description": "connect with serverMonitoringMode=stream >=4.4", "runOnRequirements": [ { "minServerVersion": "4.4.0" } ], "operations": [ { "name": "createEntities", "object": "testRunner", "arguments": { "entities": [ { "client": { "id": "client", "uriOptions": { "serverMonitoringMode": "stream" }, "useMultipleMongoses": false, "observeEvents": [ "serverHeartbeatStartedEvent", "serverHeartbeatSucceededEvent", "serverHeartbeatFailedEvent" ] } }, { "database": { "id": "db", "client": "client", "databaseName": "sdam-tests" } } ] } }, { "name": "runCommand", "object": "db", "arguments": { "commandName": "ping", "command": { "ping": 1 } }, "expectResult": { "ok": 1 } }, { "name": "waitForEvent", "object": "testRunner", "arguments": { "client": "client", "event": { "serverHeartbeatStartedEvent": {} }, "count": 2 } } ], "expectEvents": [ { "client": "client", "eventType": "sdam", "ignoreExtraEvents": true, "events": [ { "serverHeartbeatStartedEvent": { "awaited": false } }, { "serverHeartbeatSucceededEvent": { "awaited": false } }, { "serverHeartbeatStartedEvent": { "awaited": true } } ] } ] }, { "description": "connect with serverMonitoringMode=stream <4.4", "runOnRequirements": [ { "maxServerVersion": "4.2.99" } ], "operations": [ { "name": "createEntities", "object": "testRunner", "arguments": { "entities": [ { "client": { "id": "client", "uriOptions": { "serverMonitoringMode": "stream", "heartbeatFrequencyMS": 500 }, "useMultipleMongoses": false, "observeEvents": [ "serverHeartbeatStartedEvent", "serverHeartbeatSucceededEvent", "serverHeartbeatFailedEvent" ] } }, { "database": { "id": "db", "client": "client", "databaseName": "sdam-tests" } } ] } }, { "name": "runCommand", "object": "db", "arguments": { "commandName": "ping", "command": { "ping": 1 } }, "expectResult": { "ok": 1 } }, { "name": "waitForEvent", "object": "testRunner", "arguments": { "client": "client", "event": { "serverHeartbeatStartedEvent": {} }, "count": 2 } } ], "expectEvents": [ { "client": "client", "eventType": "sdam", "ignoreExtraEvents": true, "events": [ { "serverHeartbeatStartedEvent": { "awaited": false } }, { "serverHeartbeatSucceededEvent": { "awaited": false } }, { "serverHeartbeatStartedEvent": { "awaited": false } } ] } ] }, { "description": "connect with serverMonitoringMode=poll", "operations": [ { "name": "createEntities", "object": "testRunner", "arguments": { "entities": [ { "client": { "id": "client", "uriOptions": { "serverMonitoringMode": "poll", "heartbeatFrequencyMS": 500 }, "useMultipleMongoses": false, "observeEvents": [ "serverHeartbeatStartedEvent", "serverHeartbeatSucceededEvent", "serverHeartbeatFailedEvent" ] } }, { "database": { "id": "db", "client": "client", "databaseName": "sdam-tests" } } ] } }, { "name": "runCommand", "object": "db", "arguments": { "commandName": "ping", "command": { "ping": 1 } }, "expectResult": { "ok": 1 } }, { "name": "waitForEvent", "object": "testRunner", "arguments": { "client": "client", "event": { "serverHeartbeatStartedEvent": {} }, "count": 2 } } ], "expectEvents": [ { "client": "client", "eventType": "sdam", "ignoreExtraEvents": true, "events": [ { "serverHeartbeatStartedEvent": { "awaited": false } }, { "serverHeartbeatSucceededEvent": { "awaited": false } }, { "serverHeartbeatStartedEvent": { "awaited": false } } ] } ] } ] } mongodb-mongo-python-driver-509e9b7/test/gridfs/000077500000000000000000000000001462766011000216725ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/gridfs/delete.json000066400000000000000000000515541462766011000240410ustar00rootroot00000000000000{ "description": "gridfs-delete", "schemaVersion": "1.0", "createEntities": [ { "client": { "id": "client0" } }, { "database": { "id": "database0", "client": "client0", "databaseName": "gridfs-tests" } }, { "bucket": { "id": "bucket0", "database": "database0" } }, { "collection": { "id": "bucket0_files_collection", "database": "database0", "collectionName": "fs.files" } }, { "collection": { "id": "bucket0_chunks_collection", "database": "database0", "collectionName": "fs.chunks" } } ], "initialData": [ { "collectionName": "fs.files", "databaseName": "gridfs-tests", "documents": [ { "_id": { "$oid": "000000000000000000000001" }, "length": 0, "chunkSize": 4, "uploadDate": { "$date": "1970-01-01T00:00:00.000Z" }, "md5": "d41d8cd98f00b204e9800998ecf8427e", "filename": "length-0", "contentType": "application/octet-stream", "aliases": [], "metadata": {} }, { "_id": { "$oid": "000000000000000000000002" }, "length": 0, "chunkSize": 4, "uploadDate": { "$date": "1970-01-01T00:00:00.000Z" }, "md5": "d41d8cd98f00b204e9800998ecf8427e", "filename": "length-0-with-empty-chunk", "contentType": "application/octet-stream", "aliases": [], "metadata": {} }, { "_id": { "$oid": "000000000000000000000003" }, "length": 2, "chunkSize": 4, "uploadDate": { "$date": "1970-01-01T00:00:00.000Z" }, "md5": "c700ed4fdb1d27055aa3faa2c2432283", "filename": "length-2", "contentType": "application/octet-stream", "aliases": [], "metadata": {} }, { "_id": { "$oid": "000000000000000000000004" }, "length": 8, "chunkSize": 4, "uploadDate": { "$date": "1970-01-01T00:00:00.000Z" }, "md5": "dd254cdc958e53abaa67da9f797125f5", "filename": "length-8", "contentType": "application/octet-stream", "aliases": [], "metadata": {} } ] }, { "collectionName": "fs.chunks", "databaseName": "gridfs-tests", "documents": [ { "_id": { "$oid": "000000000000000000000001" }, "files_id": { "$oid": "000000000000000000000002" }, "n": 0, "data": { "$binary": { "base64": "", "subType": "00" } } }, { "_id": { "$oid": "000000000000000000000002" }, "files_id": { "$oid": "000000000000000000000003" }, "n": 0, "data": { "$binary": { "base64": "ESI=", "subType": "00" } } }, { "_id": { "$oid": "000000000000000000000003" }, "files_id": { "$oid": "000000000000000000000004" }, "n": 0, "data": { "$binary": { "base64": "ESIzRA==", "subType": "00" } } }, { "_id": { "$oid": "000000000000000000000004" }, "files_id": { "$oid": "000000000000000000000004" }, "n": 1, "data": { "$binary": { "base64": "VWZ3iA==", "subType": "00" } } } ] } ], "tests": [ { "description": "delete when length is 0", "operations": [ { "name": "delete", "object": "bucket0", "arguments": { "id": { "$oid": "000000000000000000000001" } } } ], "outcome": [ { "collectionName": "fs.files", "databaseName": "gridfs-tests", "documents": [ { "_id": { "$oid": "000000000000000000000002" }, "length": 0, "chunkSize": 4, "uploadDate": { "$date": "1970-01-01T00:00:00.000Z" }, "md5": "d41d8cd98f00b204e9800998ecf8427e", "filename": "length-0-with-empty-chunk", "contentType": "application/octet-stream", "aliases": [], "metadata": {} }, { "_id": { "$oid": "000000000000000000000003" }, "length": 2, "chunkSize": 4, "uploadDate": { "$date": "1970-01-01T00:00:00.000Z" }, "md5": "c700ed4fdb1d27055aa3faa2c2432283", "filename": "length-2", "contentType": "application/octet-stream", "aliases": [], "metadata": {} }, { "_id": { "$oid": "000000000000000000000004" }, "length": 8, "chunkSize": 4, "uploadDate": { "$date": "1970-01-01T00:00:00.000Z" }, "md5": "dd254cdc958e53abaa67da9f797125f5", "filename": "length-8", "contentType": "application/octet-stream", "aliases": [], "metadata": {} } ] }, { "collectionName": "fs.chunks", "databaseName": "gridfs-tests", "documents": [ { "_id": { "$oid": "000000000000000000000001" }, "files_id": { "$oid": "000000000000000000000002" }, "n": 0, "data": { "$binary": { "base64": "", "subType": "00" } } }, { "_id": { "$oid": "000000000000000000000002" }, "files_id": { "$oid": "000000000000000000000003" }, "n": 0, "data": { "$binary": { "base64": "ESI=", "subType": "00" } } }, { "_id": { "$oid": "000000000000000000000003" }, "files_id": { "$oid": "000000000000000000000004" }, "n": 0, "data": { "$binary": { "base64": "ESIzRA==", "subType": "00" } } }, { "_id": { "$oid": "000000000000000000000004" }, "files_id": { "$oid": "000000000000000000000004" }, "n": 1, "data": { "$binary": { "base64": "VWZ3iA==", "subType": "00" } } } ] } ] }, { "description": "delete when length is 0 and there is one extra empty chunk", "operations": [ { "name": "delete", "object": "bucket0", "arguments": { "id": { "$oid": "000000000000000000000002" } } } ], "outcome": [ { "collectionName": "fs.files", "databaseName": "gridfs-tests", "documents": [ { "_id": { "$oid": "000000000000000000000001" }, "length": 0, "chunkSize": 4, "uploadDate": { "$date": "1970-01-01T00:00:00.000Z" }, "md5": "d41d8cd98f00b204e9800998ecf8427e", "filename": "length-0", "contentType": "application/octet-stream", "aliases": [], "metadata": {} }, { "_id": { "$oid": "000000000000000000000003" }, "length": 2, "chunkSize": 4, "uploadDate": { "$date": "1970-01-01T00:00:00.000Z" }, "md5": "c700ed4fdb1d27055aa3faa2c2432283", "filename": "length-2", "contentType": "application/octet-stream", "aliases": [], "metadata": {} }, { "_id": { "$oid": "000000000000000000000004" }, "length": 8, "chunkSize": 4, "uploadDate": { "$date": "1970-01-01T00:00:00.000Z" }, "md5": "dd254cdc958e53abaa67da9f797125f5", "filename": "length-8", "contentType": "application/octet-stream", "aliases": [], "metadata": {} } ] }, { "collectionName": "fs.chunks", "databaseName": "gridfs-tests", "documents": [ { "_id": { "$oid": "000000000000000000000002" }, "files_id": { "$oid": "000000000000000000000003" }, "n": 0, "data": { "$binary": { "base64": "ESI=", "subType": "00" } } }, { "_id": { "$oid": "000000000000000000000003" }, "files_id": { "$oid": "000000000000000000000004" }, "n": 0, "data": { "$binary": { "base64": "ESIzRA==", "subType": "00" } } }, { "_id": { "$oid": "000000000000000000000004" }, "files_id": { "$oid": "000000000000000000000004" }, "n": 1, "data": { "$binary": { "base64": "VWZ3iA==", "subType": "00" } } } ] } ] }, { "description": "delete when length is 8", "operations": [ { "name": "delete", "object": "bucket0", "arguments": { "id": { "$oid": "000000000000000000000004" } } } ], "outcome": [ { "collectionName": "fs.files", "databaseName": "gridfs-tests", "documents": [ { "_id": { "$oid": "000000000000000000000001" }, "length": 0, "chunkSize": 4, "uploadDate": { "$date": "1970-01-01T00:00:00.000Z" }, "md5": "d41d8cd98f00b204e9800998ecf8427e", "filename": "length-0", "contentType": "application/octet-stream", "aliases": [], "metadata": {} }, { "_id": { "$oid": "000000000000000000000002" }, "length": 0, "chunkSize": 4, "uploadDate": { "$date": "1970-01-01T00:00:00.000Z" }, "md5": "d41d8cd98f00b204e9800998ecf8427e", "filename": "length-0-with-empty-chunk", "contentType": "application/octet-stream", "aliases": [], "metadata": {} }, { "_id": { "$oid": "000000000000000000000003" }, "length": 2, "chunkSize": 4, "uploadDate": { "$date": "1970-01-01T00:00:00.000Z" }, "md5": "c700ed4fdb1d27055aa3faa2c2432283", "filename": "length-2", "contentType": "application/octet-stream", "aliases": [], "metadata": {} } ] }, { "collectionName": "fs.chunks", "databaseName": "gridfs-tests", "documents": [ { "_id": { "$oid": "000000000000000000000001" }, "files_id": { "$oid": "000000000000000000000002" }, "n": 0, "data": { "$binary": { "base64": "", "subType": "00" } } }, { "_id": { "$oid": "000000000000000000000002" }, "files_id": { "$oid": "000000000000000000000003" }, "n": 0, "data": { "$binary": { "base64": "ESI=", "subType": "00" } } } ] } ] }, { "description": "delete when files entry does not exist", "operations": [ { "name": "delete", "object": "bucket0", "arguments": { "id": { "$oid": "000000000000000000000000" } }, "expectError": { "isError": true } } ], "outcome": [ { "collectionName": "fs.files", "databaseName": "gridfs-tests", "documents": [ { "_id": { "$oid": "000000000000000000000001" }, "length": 0, "chunkSize": 4, "uploadDate": { "$date": "1970-01-01T00:00:00.000Z" }, "md5": "d41d8cd98f00b204e9800998ecf8427e", "filename": "length-0", "contentType": "application/octet-stream", "aliases": [], "metadata": {} }, { "_id": { "$oid": "000000000000000000000002" }, "length": 0, "chunkSize": 4, "uploadDate": { "$date": "1970-01-01T00:00:00.000Z" }, "md5": "d41d8cd98f00b204e9800998ecf8427e", "filename": "length-0-with-empty-chunk", "contentType": "application/octet-stream", "aliases": [], "metadata": {} }, { "_id": { "$oid": "000000000000000000000003" }, "length": 2, "chunkSize": 4, "uploadDate": { "$date": "1970-01-01T00:00:00.000Z" }, "md5": "c700ed4fdb1d27055aa3faa2c2432283", "filename": "length-2", "contentType": "application/octet-stream", "aliases": [], "metadata": {} }, { "_id": { "$oid": "000000000000000000000004" }, "length": 8, "chunkSize": 4, "uploadDate": { "$date": "1970-01-01T00:00:00.000Z" }, "md5": "dd254cdc958e53abaa67da9f797125f5", "filename": "length-8", "contentType": "application/octet-stream", "aliases": [], "metadata": {} } ] }, { "collectionName": "fs.chunks", "databaseName": "gridfs-tests", "documents": [ { "_id": { "$oid": "000000000000000000000001" }, "files_id": { "$oid": "000000000000000000000002" }, "n": 0, "data": { "$binary": { "base64": "", "subType": "00" } } }, { "_id": { "$oid": "000000000000000000000002" }, "files_id": { "$oid": "000000000000000000000003" }, "n": 0, "data": { "$binary": { "base64": "ESI=", "subType": "00" } } }, { "_id": { "$oid": "000000000000000000000003" }, "files_id": { "$oid": "000000000000000000000004" }, "n": 0, "data": { "$binary": { "base64": "ESIzRA==", "subType": "00" } } }, { "_id": { "$oid": "000000000000000000000004" }, "files_id": { "$oid": "000000000000000000000004" }, "n": 1, "data": { "$binary": { "base64": "VWZ3iA==", "subType": "00" } } } ] } ] }, { "description": "delete when files entry does not exist and there are orphaned chunks", "operations": [ { "name": "deleteOne", "object": "bucket0_files_collection", "arguments": { "filter": { "_id": { "$oid": "000000000000000000000004" } } }, "expectResult": { "deletedCount": 1 } }, { "name": "delete", "object": "bucket0", "arguments": { "id": { "$oid": "000000000000000000000004" } }, "expectError": { "isError": true } } ], "outcome": [ { "collectionName": "fs.files", "databaseName": "gridfs-tests", "documents": [ { "_id": { "$oid": "000000000000000000000001" }, "length": 0, "chunkSize": 4, "uploadDate": { "$date": "1970-01-01T00:00:00.000Z" }, "md5": "d41d8cd98f00b204e9800998ecf8427e", "filename": "length-0", "contentType": "application/octet-stream", "aliases": [], "metadata": {} }, { "_id": { "$oid": "000000000000000000000002" }, "length": 0, "chunkSize": 4, "uploadDate": { "$date": "1970-01-01T00:00:00.000Z" }, "md5": "d41d8cd98f00b204e9800998ecf8427e", "filename": "length-0-with-empty-chunk", "contentType": "application/octet-stream", "aliases": [], "metadata": {} }, { "_id": { "$oid": "000000000000000000000003" }, "length": 2, "chunkSize": 4, "uploadDate": { "$date": "1970-01-01T00:00:00.000Z" }, "md5": "c700ed4fdb1d27055aa3faa2c2432283", "filename": "length-2", "contentType": "application/octet-stream", "aliases": [], "metadata": {} } ] }, { "collectionName": "fs.chunks", "databaseName": "gridfs-tests", "documents": [ { "_id": { "$oid": "000000000000000000000001" }, "files_id": { "$oid": "000000000000000000000002" }, "n": 0, "data": { "$binary": { "base64": "", "subType": "00" } } }, { "_id": { "$oid": "000000000000000000000002" }, "files_id": { "$oid": "000000000000000000000003" }, "n": 0, "data": { "$binary": { "base64": "ESI=", "subType": "00" } } } ] } ] } ] } mongodb-mongo-python-driver-509e9b7/test/gridfs/download.json000066400000000000000000000317131462766011000244010ustar00rootroot00000000000000{ "description": "gridfs-download", "schemaVersion": "1.0", "createEntities": [ { "client": { "id": "client0" } }, { "database": { "id": "database0", "client": "client0", "databaseName": "gridfs-tests" } }, { "bucket": { "id": "bucket0", "database": "database0" } }, { "collection": { "id": "bucket0_files_collection", "database": "database0", "collectionName": "fs.files" } }, { "collection": { "id": "bucket0_chunks_collection", "database": "database0", "collectionName": "fs.chunks" } } ], "initialData": [ { "collectionName": "fs.files", "databaseName": "gridfs-tests", "documents": [ { "_id": { "$oid": "000000000000000000000001" }, "length": 0, "chunkSize": 4, "uploadDate": { "$date": "1970-01-01T00:00:00.000Z" }, "md5": "d41d8cd98f00b204e9800998ecf8427e", "filename": "length-0", "contentType": "application/octet-stream", "aliases": [], "metadata": {} }, { "_id": { "$oid": "000000000000000000000002" }, "length": 0, "chunkSize": 4, "uploadDate": { "$date": "1970-01-01T00:00:00.000Z" }, "md5": "d41d8cd98f00b204e9800998ecf8427e", "filename": "length-0-with-empty-chunk", "contentType": "application/octet-stream", "aliases": [], "metadata": {} }, { "_id": { "$oid": "000000000000000000000003" }, "length": 2, "chunkSize": 4, "uploadDate": { "$date": "1970-01-01T00:00:00.000Z" }, "md5": "c700ed4fdb1d27055aa3faa2c2432283", "filename": "length-2", "contentType": "application/octet-stream", "aliases": [], "metadata": {} }, { "_id": { "$oid": "000000000000000000000004" }, "length": 8, "chunkSize": 4, "uploadDate": { "$date": "1970-01-01T00:00:00.000Z" }, "md5": "dd254cdc958e53abaa67da9f797125f5", "filename": "length-8", "contentType": "application/octet-stream", "aliases": [], "metadata": {} }, { "_id": { "$oid": "000000000000000000000005" }, "length": 10, "chunkSize": 4, "uploadDate": { "$date": "1970-01-01T00:00:00.000Z" }, "md5": "57d83cd477bfb1ccd975ab33d827a92b", "filename": "length-10", "contentType": "application/octet-stream", "aliases": [], "metadata": {} }, { "_id": { "$oid": "000000000000000000000006" }, "length": 2, "chunkSize": 4, "uploadDate": { "$date": "1970-01-01T00:00:00.000Z" }, "md5": "c700ed4fdb1d27055aa3faa2c2432283", "contentType": "application/octet-stream", "aliases": [], "metadata": {} } ] }, { "collectionName": "fs.chunks", "databaseName": "gridfs-tests", "documents": [ { "_id": { "$oid": "000000000000000000000001" }, "files_id": { "$oid": "000000000000000000000002" }, "n": 0, "data": { "$binary": { "base64": "", "subType": "00" } } }, { "_id": { "$oid": "000000000000000000000002" }, "files_id": { "$oid": "000000000000000000000003" }, "n": 0, "data": { "$binary": { "base64": "ESI=", "subType": "00" } } }, { "_id": { "$oid": "000000000000000000000003" }, "files_id": { "$oid": "000000000000000000000004" }, "n": 0, "data": { "$binary": { "base64": "ESIzRA==", "subType": "00" } } }, { "_id": { "$oid": "000000000000000000000004" }, "files_id": { "$oid": "000000000000000000000004" }, "n": 1, "data": { "$binary": { "base64": "VWZ3iA==", "subType": "00" } } }, { "_id": { "$oid": "000000000000000000000005" }, "files_id": { "$oid": "000000000000000000000005" }, "n": 0, "data": { "$binary": { "base64": "ESIzRA==", "subType": "00" } } }, { "_id": { "$oid": "000000000000000000000006" }, "files_id": { "$oid": "000000000000000000000005" }, "n": 1, "data": { "$binary": { "base64": "VWZ3iA==", "subType": "00" } } }, { "_id": { "$oid": "000000000000000000000007" }, "files_id": { "$oid": "000000000000000000000005" }, "n": 2, "data": { "$binary": { "base64": "mao=", "subType": "00" } } }, { "_id": { "$oid": "000000000000000000000008" }, "files_id": { "$oid": "000000000000000000000006" }, "n": 0, "data": { "$binary": { "base64": "ESI=", "subType": "00" } } } ] } ], "tests": [ { "description": "download when length is zero", "operations": [ { "name": "download", "object": "bucket0", "arguments": { "id": { "$oid": "000000000000000000000001" } }, "expectResult": { "$$matchesHexBytes": "" } } ] }, { "description": "download when length is zero and there is one empty chunk", "operations": [ { "name": "download", "object": "bucket0", "arguments": { "id": { "$oid": "000000000000000000000002" } }, "expectResult": { "$$matchesHexBytes": "" } } ] }, { "description": "download when there is one chunk", "operations": [ { "name": "download", "object": "bucket0", "arguments": { "id": { "$oid": "000000000000000000000003" } }, "expectResult": { "$$matchesHexBytes": "1122" } } ] }, { "description": "download when there are two chunks", "operations": [ { "name": "download", "object": "bucket0", "arguments": { "id": { "$oid": "000000000000000000000004" } }, "expectResult": { "$$matchesHexBytes": "1122334455667788" } } ] }, { "description": "download when there are three chunks", "operations": [ { "name": "download", "object": "bucket0", "arguments": { "id": { "$oid": "000000000000000000000005" } }, "expectResult": { "$$matchesHexBytes": "112233445566778899aa" } } ] }, { "description": "download when files entry does not exist", "operations": [ { "name": "download", "object": "bucket0", "arguments": { "id": { "$oid": "000000000000000000000000" } }, "expectError": { "isError": true } } ] }, { "description": "download when an intermediate chunk is missing", "operations": [ { "name": "deleteOne", "object": "bucket0_chunks_collection", "arguments": { "filter": { "files_id": { "$oid": "000000000000000000000005" }, "n": 1 } }, "expectResult": { "deletedCount": 1 } }, { "name": "download", "object": "bucket0", "arguments": { "id": { "$oid": "000000000000000000000005" } }, "expectError": { "isError": true } } ] }, { "description": "download when final chunk is missing", "operations": [ { "name": "deleteOne", "object": "bucket0_chunks_collection", "arguments": { "filter": { "files_id": { "$oid": "000000000000000000000005" }, "n": 2 } }, "expectResult": { "deletedCount": 1 } }, { "name": "download", "object": "bucket0", "arguments": { "id": { "$oid": "000000000000000000000005" } }, "expectError": { "isError": true } } ] }, { "description": "download when an intermediate chunk is the wrong size", "operations": [ { "name": "bulkWrite", "object": "bucket0_chunks_collection", "arguments": { "requests": [ { "updateOne": { "filter": { "files_id": { "$oid": "000000000000000000000005" }, "n": 1 }, "update": { "$set": { "data": { "$binary": { "base64": "VWZ3", "subType": "00" } } } } } }, { "updateOne": { "filter": { "files_id": { "$oid": "000000000000000000000005" }, "n": 2 }, "update": { "$set": { "data": { "$binary": { "base64": "iJmq", "subType": "00" } } } } } } ] }, "expectResult": { "matchedCount": 2, "modifiedCount": 2 } }, { "name": "download", "object": "bucket0", "arguments": { "id": { "$oid": "000000000000000000000005" } }, "expectError": { "isError": true } } ] }, { "description": "download when final chunk is the wrong size", "operations": [ { "name": "updateOne", "object": "bucket0_chunks_collection", "arguments": { "filter": { "files_id": { "$oid": "000000000000000000000005" }, "n": 2 }, "update": { "$set": { "data": { "$binary": { "base64": "mQ==", "subType": "00" } } } } }, "expectResult": { "matchedCount": 1, "modifiedCount": 1 } }, { "name": "download", "object": "bucket0", "arguments": { "id": { "$oid": "000000000000000000000005" } }, "expectError": { "isError": true } } ] }, { "description": "download legacy file with no name", "operations": [ { "name": "download", "object": "bucket0", "arguments": { "id": { "$oid": "000000000000000000000006" } }, "expectResult": { "$$matchesHexBytes": "1122" } } ] } ] } mongodb-mongo-python-driver-509e9b7/test/gridfs/downloadByName.json000066400000000000000000000166721462766011000255040ustar00rootroot00000000000000{ "description": "gridfs-downloadByName", "schemaVersion": "1.0", "createEntities": [ { "client": { "id": "client0" } }, { "database": { "id": "database0", "client": "client0", "databaseName": "gridfs-tests" } }, { "bucket": { "id": "bucket0", "database": "database0" } }, { "collection": { "id": "bucket0_files_collection", "database": "database0", "collectionName": "fs.files" } }, { "collection": { "id": "bucket0_chunks_collection", "database": "database0", "collectionName": "fs.chunks" } } ], "initialData": [ { "collectionName": "fs.files", "databaseName": "gridfs-tests", "documents": [ { "_id": { "$oid": "000000000000000000000001" }, "length": 1, "chunkSize": 4, "uploadDate": { "$date": "1970-01-01T00:00:00.000Z" }, "md5": "47ed733b8d10be225eceba344d533586", "filename": "abc", "contentType": "application/octet-stream", "aliases": [], "metadata": {} }, { "_id": { "$oid": "000000000000000000000002" }, "length": 1, "chunkSize": 4, "uploadDate": { "$date": "1970-01-02T00:00:00.000Z" }, "md5": "b15835f133ff2e27c7cb28117bfae8f4", "filename": "abc", "contentType": "application/octet-stream", "aliases": [], "metadata": {} }, { "_id": { "$oid": "000000000000000000000003" }, "length": 1, "chunkSize": 4, "uploadDate": { "$date": "1970-01-03T00:00:00.000Z" }, "md5": "eccbc87e4b5ce2fe28308fd9f2a7baf3", "filename": "abc", "contentType": "application/octet-stream", "aliases": [], "metadata": {} }, { "_id": { "$oid": "000000000000000000000004" }, "length": 1, "chunkSize": 4, "uploadDate": { "$date": "1970-01-04T00:00:00.000Z" }, "md5": "f623e75af30e62bbd73d6df5b50bb7b5", "filename": "abc", "contentType": "application/octet-stream", "aliases": [], "metadata": {} }, { "_id": { "$oid": "000000000000000000000005" }, "length": 1, "chunkSize": 4, "uploadDate": { "$date": "1970-01-05T00:00:00.000Z" }, "md5": "4c614360da93c0a041b22e537de151eb", "filename": "abc", "contentType": "application/octet-stream", "aliases": [], "metadata": {} } ] }, { "collectionName": "fs.chunks", "databaseName": "gridfs-tests", "documents": [ { "_id": { "$oid": "000000000000000000000001" }, "files_id": { "$oid": "000000000000000000000001" }, "n": 0, "data": { "$binary": { "base64": "EQ==", "subType": "00" } } }, { "_id": { "$oid": "000000000000000000000002" }, "files_id": { "$oid": "000000000000000000000002" }, "n": 0, "data": { "$binary": { "base64": "Ig==", "subType": "00" } } }, { "_id": { "$oid": "000000000000000000000003" }, "files_id": { "$oid": "000000000000000000000003" }, "n": 0, "data": { "$binary": { "base64": "Mw==", "subType": "00" } } }, { "_id": { "$oid": "000000000000000000000004" }, "files_id": { "$oid": "000000000000000000000004" }, "n": 0, "data": { "$binary": { "base64": "RA==", "subType": "00" } } }, { "_id": { "$oid": "000000000000000000000005" }, "files_id": { "$oid": "000000000000000000000005" }, "n": 0, "data": { "$binary": { "base64": "VQ==", "subType": "00" } } } ] } ], "tests": [ { "description": "downloadByName defaults to latest revision (-1)", "operations": [ { "name": "downloadByName", "object": "bucket0", "arguments": { "filename": "abc" }, "expectResult": { "$$matchesHexBytes": "55" } } ] }, { "description": "downloadByName when revision is 0", "operations": [ { "name": "downloadByName", "object": "bucket0", "arguments": { "filename": "abc", "revision": 0 }, "expectResult": { "$$matchesHexBytes": "11" } } ] }, { "description": "downloadByName when revision is 1", "operations": [ { "name": "downloadByName", "object": "bucket0", "arguments": { "filename": "abc", "revision": 1 }, "expectResult": { "$$matchesHexBytes": "22" } } ] }, { "description": "downloadByName when revision is 2", "operations": [ { "name": "downloadByName", "object": "bucket0", "arguments": { "filename": "abc", "revision": 2 }, "expectResult": { "$$matchesHexBytes": "33" } } ] }, { "description": "downloadByName when revision is -2", "operations": [ { "name": "downloadByName", "object": "bucket0", "arguments": { "filename": "abc", "revision": -2 }, "expectResult": { "$$matchesHexBytes": "44" } } ] }, { "description": "downloadByName when revision is -1", "operations": [ { "name": "downloadByName", "object": "bucket0", "arguments": { "filename": "abc", "revision": -1 }, "expectResult": { "$$matchesHexBytes": "55" } } ] }, { "description": "downloadByName when files entry does not exist", "operations": [ { "name": "downloadByName", "object": "bucket0", "arguments": { "filename": "xyz" }, "expectError": { "isError": true } } ] }, { "description": "downloadByName when revision does not exist", "operations": [ { "name": "downloadByName", "object": "bucket0", "arguments": { "filename": "abc", "revision": 999 }, "expectError": { "isError": true } } ] } ] } mongodb-mongo-python-driver-509e9b7/test/gridfs/upload-disableMD5.json000066400000000000000000000074721462766011000257720ustar00rootroot00000000000000{ "description": "gridfs-upload-disableMD5", "schemaVersion": "1.0", "createEntities": [ { "client": { "id": "client0" } }, { "database": { "id": "database0", "client": "client0", "databaseName": "gridfs-tests" } }, { "bucket": { "id": "bucket0", "database": "database0" } }, { "collection": { "id": "bucket0_files_collection", "database": "database0", "collectionName": "fs.files" } }, { "collection": { "id": "bucket0_chunks_collection", "database": "database0", "collectionName": "fs.chunks" } } ], "initialData": [ { "collectionName": "fs.files", "databaseName": "gridfs-tests", "documents": [] }, { "collectionName": "fs.chunks", "databaseName": "gridfs-tests", "documents": [] } ], "tests": [ { "description": "upload when length is 0 sans MD5", "operations": [ { "name": "upload", "object": "bucket0", "arguments": { "filename": "filename", "source": { "$$hexBytes": "" }, "chunkSizeBytes": 4, "disableMD5": true }, "expectResult": { "$$type": "objectId" }, "saveResultAsEntity": "uploadedObjectId" }, { "name": "find", "object": "bucket0_files_collection", "arguments": { "filter": {} }, "expectResult": [ { "_id": { "$$matchesEntity": "uploadedObjectId" }, "length": 0, "chunkSize": 4, "uploadDate": { "$$type": "date" }, "md5": { "$$exists": false }, "filename": "filename" } ] }, { "name": "find", "object": "bucket0_chunks_collection", "arguments": { "filter": {} }, "expectResult": [] } ] }, { "description": "upload when length is 1 sans MD5", "operations": [ { "name": "upload", "object": "bucket0", "arguments": { "filename": "filename", "source": { "$$hexBytes": "11" }, "chunkSizeBytes": 4, "disableMD5": true }, "expectResult": { "$$type": "objectId" }, "saveResultAsEntity": "uploadedObjectId" }, { "name": "find", "object": "bucket0_files_collection", "arguments": { "filter": {} }, "expectResult": [ { "_id": { "$$matchesEntity": "uploadedObjectId" }, "length": 1, "chunkSize": 4, "uploadDate": { "$$type": "date" }, "md5": { "$$exists": false }, "filename": "filename" } ] }, { "name": "find", "object": "bucket0_chunks_collection", "arguments": { "filter": {} }, "expectResult": [ { "_id": { "$$type": "objectId" }, "files_id": { "$$matchesEntity": "uploadedObjectId" }, "n": 0, "data": { "$binary": { "base64": "EQ==", "subType": "00" } } } ] } ] } ] } mongodb-mongo-python-driver-509e9b7/test/gridfs/upload.json000066400000000000000000000352361462766011000240620ustar00rootroot00000000000000{ "description": "gridfs-upload", "schemaVersion": "1.0", "createEntities": [ { "client": { "id": "client0" } }, { "database": { "id": "database0", "client": "client0", "databaseName": "gridfs-tests" } }, { "bucket": { "id": "bucket0", "database": "database0" } }, { "collection": { "id": "bucket0_files_collection", "database": "database0", "collectionName": "fs.files" } }, { "collection": { "id": "bucket0_chunks_collection", "database": "database0", "collectionName": "fs.chunks" } } ], "initialData": [ { "collectionName": "fs.files", "databaseName": "gridfs-tests", "documents": [] }, { "collectionName": "fs.chunks", "databaseName": "gridfs-tests", "documents": [] } ], "tests": [ { "description": "upload when length is 0", "operations": [ { "name": "upload", "object": "bucket0", "arguments": { "filename": "filename", "source": { "$$hexBytes": "" }, "chunkSizeBytes": 4 }, "expectResult": { "$$type": "objectId" }, "saveResultAsEntity": "uploadedObjectId" }, { "name": "find", "object": "bucket0_files_collection", "arguments": { "filter": {} }, "expectResult": [ { "_id": { "$$matchesEntity": "uploadedObjectId" }, "length": 0, "chunkSize": 4, "uploadDate": { "$$type": "date" }, "md5": { "$$unsetOrMatches": "d41d8cd98f00b204e9800998ecf8427e" }, "filename": "filename" } ] }, { "name": "find", "object": "bucket0_chunks_collection", "arguments": { "filter": {} }, "expectResult": [] } ] }, { "description": "upload when length is 1", "operations": [ { "name": "upload", "object": "bucket0", "arguments": { "filename": "filename", "source": { "$$hexBytes": "11" }, "chunkSizeBytes": 4 }, "expectResult": { "$$type": "objectId" }, "saveResultAsEntity": "uploadedObjectId" }, { "name": "find", "object": "bucket0_files_collection", "arguments": { "filter": {} }, "expectResult": [ { "_id": { "$$matchesEntity": "uploadedObjectId" }, "length": 1, "chunkSize": 4, "uploadDate": { "$$type": "date" }, "md5": { "$$unsetOrMatches": "47ed733b8d10be225eceba344d533586" }, "filename": "filename" } ] }, { "name": "find", "object": "bucket0_chunks_collection", "arguments": { "filter": {} }, "expectResult": [ { "_id": { "$$type": "objectId" }, "files_id": { "$$matchesEntity": "uploadedObjectId" }, "n": 0, "data": { "$binary": { "base64": "EQ==", "subType": "00" } } } ] } ] }, { "description": "upload when length is 3", "operations": [ { "name": "upload", "object": "bucket0", "arguments": { "filename": "filename", "source": { "$$hexBytes": "112233" }, "chunkSizeBytes": 4 }, "expectResult": { "$$type": "objectId" }, "saveResultAsEntity": "uploadedObjectId" }, { "name": "find", "object": "bucket0_files_collection", "arguments": { "filter": {} }, "expectResult": [ { "_id": { "$$matchesEntity": "uploadedObjectId" }, "length": 3, "chunkSize": 4, "uploadDate": { "$$type": "date" }, "md5": { "$$unsetOrMatches": "bafae3a174ab91fc70db7a6aa50f4f52" }, "filename": "filename" } ] }, { "name": "find", "object": "bucket0_chunks_collection", "arguments": { "filter": {} }, "expectResult": [ { "_id": { "$$type": "objectId" }, "files_id": { "$$matchesEntity": "uploadedObjectId" }, "n": 0, "data": { "$binary": { "base64": "ESIz", "subType": "00" } } } ] } ] }, { "description": "upload when length is 4", "operations": [ { "name": "upload", "object": "bucket0", "arguments": { "filename": "filename", "source": { "$$hexBytes": "11223344" }, "chunkSizeBytes": 4 }, "expectResult": { "$$type": "objectId" }, "saveResultAsEntity": "uploadedObjectId" }, { "name": "find", "object": "bucket0_files_collection", "arguments": { "filter": {} }, "expectResult": [ { "_id": { "$$matchesEntity": "uploadedObjectId" }, "length": 4, "chunkSize": 4, "uploadDate": { "$$type": "date" }, "md5": { "$$unsetOrMatches": "7e7c77cff5705d1f7574a25ef6662117" }, "filename": "filename" } ] }, { "name": "find", "object": "bucket0_chunks_collection", "arguments": { "filter": {} }, "expectResult": [ { "_id": { "$$type": "objectId" }, "files_id": { "$$matchesEntity": "uploadedObjectId" }, "n": 0, "data": { "$binary": { "base64": "ESIzRA==", "subType": "00" } } } ] } ] }, { "description": "upload when length is 5", "operations": [ { "name": "upload", "object": "bucket0", "arguments": { "filename": "filename", "source": { "$$hexBytes": "1122334455" }, "chunkSizeBytes": 4 }, "expectResult": { "$$type": "objectId" }, "saveResultAsEntity": "uploadedObjectId" }, { "name": "find", "object": "bucket0_files_collection", "arguments": { "filter": {} }, "expectResult": [ { "_id": { "$$matchesEntity": "uploadedObjectId" }, "length": 5, "chunkSize": 4, "uploadDate": { "$$type": "date" }, "md5": { "$$unsetOrMatches": "283d4fea5dded59cf837d3047328f5af" }, "filename": "filename" } ] }, { "name": "find", "object": "bucket0_chunks_collection", "arguments": { "filter": {}, "sort": { "n": 1 } }, "expectResult": [ { "_id": { "$$type": "objectId" }, "files_id": { "$$matchesEntity": "uploadedObjectId" }, "n": 0, "data": { "$binary": { "base64": "ESIzRA==", "subType": "00" } } }, { "_id": { "$$type": "objectId" }, "files_id": { "$$matchesEntity": "uploadedObjectId" }, "n": 1, "data": { "$binary": { "base64": "VQ==", "subType": "00" } } } ] } ] }, { "description": "upload when length is 8", "operations": [ { "name": "upload", "object": "bucket0", "arguments": { "filename": "filename", "source": { "$$hexBytes": "1122334455667788" }, "chunkSizeBytes": 4 }, "expectResult": { "$$type": "objectId" }, "saveResultAsEntity": "uploadedObjectId" }, { "name": "find", "object": "bucket0_files_collection", "arguments": { "filter": {} }, "expectResult": [ { "_id": { "$$matchesEntity": "uploadedObjectId" }, "length": 8, "chunkSize": 4, "uploadDate": { "$$type": "date" }, "md5": { "$$unsetOrMatches": "dd254cdc958e53abaa67da9f797125f5" }, "filename": "filename" } ] }, { "name": "find", "object": "bucket0_chunks_collection", "arguments": { "filter": {}, "sort": { "n": 1 } }, "expectResult": [ { "_id": { "$$type": "objectId" }, "files_id": { "$$matchesEntity": "uploadedObjectId" }, "n": 0, "data": { "$binary": { "base64": "ESIzRA==", "subType": "00" } } }, { "_id": { "$$type": "objectId" }, "files_id": { "$$matchesEntity": "uploadedObjectId" }, "n": 1, "data": { "$binary": { "base64": "VWZ3iA==", "subType": "00" } } } ] } ] }, { "description": "upload when contentType is provided", "operations": [ { "name": "upload", "object": "bucket0", "arguments": { "filename": "filename", "source": { "$$hexBytes": "11" }, "chunkSizeBytes": 4, "contentType": "image/jpeg" }, "expectResult": { "$$type": "objectId" }, "saveResultAsEntity": "uploadedObjectId" }, { "name": "find", "object": "bucket0_files_collection", "arguments": { "filter": {} }, "expectResult": [ { "_id": { "$$matchesEntity": "uploadedObjectId" }, "length": 1, "chunkSize": 4, "uploadDate": { "$$type": "date" }, "md5": { "$$unsetOrMatches": "47ed733b8d10be225eceba344d533586" }, "filename": "filename", "contentType": "image/jpeg" } ] }, { "name": "find", "object": "bucket0_chunks_collection", "arguments": { "filter": {} }, "expectResult": [ { "_id": { "$$type": "objectId" }, "files_id": { "$$matchesEntity": "uploadedObjectId" }, "n": 0, "data": { "$binary": { "base64": "EQ==", "subType": "00" } } } ] } ] }, { "description": "upload when metadata is provided", "operations": [ { "name": "upload", "object": "bucket0", "arguments": { "filename": "filename", "source": { "$$hexBytes": "11" }, "chunkSizeBytes": 4, "metadata": { "x": 1 } }, "expectResult": { "$$type": "objectId" }, "saveResultAsEntity": "uploadedObjectId" }, { "name": "find", "object": "bucket0_files_collection", "arguments": { "filter": {} }, "expectResult": [ { "_id": { "$$matchesEntity": "uploadedObjectId" }, "length": 1, "chunkSize": 4, "uploadDate": { "$$type": "date" }, "md5": { "$$unsetOrMatches": "47ed733b8d10be225eceba344d533586" }, "filename": "filename", "metadata": { "x": 1 } } ] }, { "name": "find", "object": "bucket0_chunks_collection", "arguments": { "filter": {} }, "expectResult": [ { "_id": { "$$type": "objectId" }, "files_id": { "$$matchesEntity": "uploadedObjectId" }, "n": 0, "data": { "$binary": { "base64": "EQ==", "subType": "00" } } } ] } ] } ] } mongodb-mongo-python-driver-509e9b7/test/index_management/000077500000000000000000000000001462766011000237175ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/index_management/createSearchIndex.json000066400000000000000000000057741462766011000302100ustar00rootroot00000000000000{ "description": "createSearchIndex", "schemaVersion": "1.4", "createEntities": [ { "client": { "id": "client0", "useMultipleMongoses": false, "observeEvents": [ "commandStartedEvent" ] } }, { "database": { "id": "database0", "client": "client0", "databaseName": "database0" } }, { "collection": { "id": "collection0", "database": "database0", "collectionName": "collection0" } } ], "runOnRequirements": [ { "minServerVersion": "7.0.0", "topologies": [ "replicaset", "load-balanced", "sharded" ], "serverless": "forbid" } ], "tests": [ { "description": "no name provided for an index definition", "operations": [ { "name": "createSearchIndex", "object": "collection0", "arguments": { "model": { "definition": { "mappings": { "dynamic": true } } } }, "expectError": { "isError": true, "errorContains": "Atlas" } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "createSearchIndexes": "collection0", "indexes": [ { "definition": { "mappings": { "dynamic": true } } } ], "$db": "database0" } } } ] } ] }, { "description": "name provided for an index definition", "operations": [ { "name": "createSearchIndex", "object": "collection0", "arguments": { "model": { "definition": { "mappings": { "dynamic": true } }, "name": "test index" } }, "expectError": { "isError": true, "errorContains": "Atlas" } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "createSearchIndexes": "collection0", "indexes": [ { "definition": { "mappings": { "dynamic": true } }, "name": "test index" } ], "$db": "database0" } } } ] } ] } ] } mongodb-mongo-python-driver-509e9b7/test/index_management/createSearchIndexes.json000066400000000000000000000074701462766011000305330ustar00rootroot00000000000000{ "description": "createSearchIndexes", "schemaVersion": "1.4", "createEntities": [ { "client": { "id": "client0", "useMultipleMongoses": false, "observeEvents": [ "commandStartedEvent" ] } }, { "database": { "id": "database0", "client": "client0", "databaseName": "database0" } }, { "collection": { "id": "collection0", "database": "database0", "collectionName": "collection0" } } ], "runOnRequirements": [ { "minServerVersion": "7.0.0", "topologies": [ "replicaset", "load-balanced", "sharded" ], "serverless": "forbid" } ], "tests": [ { "description": "empty index definition array", "operations": [ { "name": "createSearchIndexes", "object": "collection0", "arguments": { "models": [] }, "expectError": { "isError": true, "errorContains": "Atlas" } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "createSearchIndexes": "collection0", "indexes": [], "$db": "database0" } } } ] } ] }, { "description": "no name provided for an index definition", "operations": [ { "name": "createSearchIndexes", "object": "collection0", "arguments": { "models": [ { "definition": { "mappings": { "dynamic": true } } } ] }, "expectError": { "isError": true, "errorContains": "Atlas" } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "createSearchIndexes": "collection0", "indexes": [ { "definition": { "mappings": { "dynamic": true } } } ], "$db": "database0" } } } ] } ] }, { "description": "name provided for an index definition", "operations": [ { "name": "createSearchIndexes", "object": "collection0", "arguments": { "models": [ { "definition": { "mappings": { "dynamic": true } }, "name": "test index" } ] }, "expectError": { "isError": true, "errorContains": "Atlas" } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "createSearchIndexes": "collection0", "indexes": [ { "definition": { "mappings": { "dynamic": true } }, "name": "test index" } ], "$db": "database0" } } } ] } ] } ] } mongodb-mongo-python-driver-509e9b7/test/index_management/dropSearchIndex.json000066400000000000000000000027311462766011000276770ustar00rootroot00000000000000{ "description": "dropSearchIndex", "schemaVersion": "1.4", "createEntities": [ { "client": { "id": "client0", "useMultipleMongoses": false, "observeEvents": [ "commandStartedEvent" ] } }, { "database": { "id": "database0", "client": "client0", "databaseName": "database0" } }, { "collection": { "id": "collection0", "database": "database0", "collectionName": "collection0" } } ], "runOnRequirements": [ { "minServerVersion": "7.0.0", "topologies": [ "replicaset", "load-balanced", "sharded" ], "serverless": "forbid" } ], "tests": [ { "description": "sends the correct command", "operations": [ { "name": "dropSearchIndex", "object": "collection0", "arguments": { "name": "test index" }, "expectError": { "isError": true, "errorContains": "Atlas" } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "dropSearchIndex": "collection0", "name": "test index", "$db": "database0" } } } ] } ] } ] } mongodb-mongo-python-driver-509e9b7/test/index_management/listSearchIndexes.json000066400000000000000000000067301462766011000302410ustar00rootroot00000000000000{ "description": "listSearchIndexes", "schemaVersion": "1.4", "createEntities": [ { "client": { "id": "client0", "useMultipleMongoses": false, "observeEvents": [ "commandStartedEvent" ] } }, { "database": { "id": "database0", "client": "client0", "databaseName": "database0" } }, { "collection": { "id": "collection0", "database": "database0", "collectionName": "collection0" } } ], "runOnRequirements": [ { "minServerVersion": "7.0.0", "topologies": [ "replicaset", "load-balanced", "sharded" ], "serverless": "forbid" } ], "tests": [ { "description": "when no name is provided, it does not populate the filter", "operations": [ { "name": "listSearchIndexes", "object": "collection0", "expectError": { "isError": true, "errorContains": "Atlas" } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "aggregate": "collection0", "pipeline": [ { "$listSearchIndexes": {} } ] } } } ] } ] }, { "description": "when a name is provided, it is present in the filter", "operations": [ { "name": "listSearchIndexes", "object": "collection0", "arguments": { "name": "test index" }, "expectError": { "isError": true, "errorContains": "Atlas" } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "aggregate": "collection0", "pipeline": [ { "$listSearchIndexes": { "name": "test index" } } ], "$db": "database0" } } } ] } ] }, { "description": "aggregation cursor options are supported", "operations": [ { "name": "listSearchIndexes", "object": "collection0", "arguments": { "name": "test index", "aggregationOptions": { "batchSize": 10 } }, "expectError": { "isError": true, "errorContains": "Atlas" } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "aggregate": "collection0", "cursor": { "batchSize": 10 }, "pipeline": [ { "$listSearchIndexes": { "name": "test index" } } ], "$db": "database0" } } } ] } ] } ] } mongodb-mongo-python-driver-509e9b7/test/index_management/searchIndexIgnoresReadWriteConcern.json000066400000000000000000000136521462766011000335240ustar00rootroot00000000000000{ "description": "search index operations ignore read and write concern", "schemaVersion": "1.4", "createEntities": [ { "client": { "id": "client0", "useMultipleMongoses": false, "uriOptions": { "readConcernLevel": "local", "w": 1 }, "observeEvents": [ "commandStartedEvent" ] } }, { "database": { "id": "database0", "client": "client0", "databaseName": "database0" } }, { "collection": { "id": "collection0", "database": "database0", "collectionName": "collection0" } } ], "runOnRequirements": [ { "minServerVersion": "7.0.0", "topologies": [ "replicaset", "load-balanced", "sharded" ], "serverless": "forbid" } ], "tests": [ { "description": "createSearchIndex ignores read and write concern", "operations": [ { "name": "createSearchIndex", "object": "collection0", "arguments": { "model": { "definition": { "mappings": { "dynamic": true } } } }, "expectError": { "isError": true, "errorContains": "Atlas" } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "createSearchIndexes": "collection0", "indexes": [ { "definition": { "mappings": { "dynamic": true } } } ], "$db": "database0", "writeConcern": { "$$exists": false }, "readConcern": { "$$exists": false } } } } ] } ] }, { "description": "createSearchIndexes ignores read and write concern", "operations": [ { "name": "createSearchIndexes", "object": "collection0", "arguments": { "models": [] }, "expectError": { "isError": true, "errorContains": "Atlas" } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "createSearchIndexes": "collection0", "indexes": [], "$db": "database0", "writeConcern": { "$$exists": false }, "readConcern": { "$$exists": false } } } } ] } ] }, { "description": "dropSearchIndex ignores read and write concern", "operations": [ { "name": "dropSearchIndex", "object": "collection0", "arguments": { "name": "test index" }, "expectError": { "isError": true, "errorContains": "Atlas" } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "dropSearchIndex": "collection0", "name": "test index", "$db": "database0", "writeConcern": { "$$exists": false }, "readConcern": { "$$exists": false } } } } ] } ] }, { "description": "listSearchIndexes ignores read and write concern", "operations": [ { "name": "listSearchIndexes", "object": "collection0", "expectError": { "isError": true, "errorContains": "Atlas" } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "aggregate": "collection0", "pipeline": [ { "$listSearchIndexes": {} } ], "writeConcern": { "$$exists": false }, "readConcern": { "$$exists": false } } } } ] } ] }, { "description": "updateSearchIndex ignores the read and write concern", "operations": [ { "name": "updateSearchIndex", "object": "collection0", "arguments": { "name": "test index", "definition": {} }, "expectError": { "isError": true, "errorContains": "Atlas" } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "updateSearchIndex": "collection0", "name": "test index", "definition": {}, "$db": "database0", "writeConcern": { "$$exists": false }, "readConcern": { "$$exists": false } } } } ] } ] } ] } mongodb-mongo-python-driver-509e9b7/test/index_management/updateSearchIndex.json000066400000000000000000000030411462766011000302100ustar00rootroot00000000000000{ "description": "updateSearchIndex", "schemaVersion": "1.4", "createEntities": [ { "client": { "id": "client0", "useMultipleMongoses": false, "observeEvents": [ "commandStartedEvent" ] } }, { "database": { "id": "database0", "client": "client0", "databaseName": "database0" } }, { "collection": { "id": "collection0", "database": "database0", "collectionName": "collection0" } } ], "runOnRequirements": [ { "minServerVersion": "7.0.0", "topologies": [ "replicaset", "load-balanced", "sharded" ], "serverless": "forbid" } ], "tests": [ { "description": "sends the correct command", "operations": [ { "name": "updateSearchIndex", "object": "collection0", "arguments": { "name": "test index", "definition": {} }, "expectError": { "isError": true, "errorContains": "Atlas" } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "updateSearchIndex": "collection0", "name": "test index", "definition": {}, "$db": "database0" } } } ] } ] } ] } mongodb-mongo-python-driver-509e9b7/test/lambda/000077500000000000000000000000001462766011000216345ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/lambda/README.md000066400000000000000000000003401462766011000231100ustar00rootroot00000000000000AWS Lambda Testing ------------------ Running locally =============== Prerequisites: - AWS SAM CLI - Docker daemon running Usage ===== - Start a local mongodb instance on port 27017 - Run ``build.sh`` - Run ``test.sh`` mongodb-mongo-python-driver-509e9b7/test/lambda/build.sh000077500000000000000000000012611462766011000232720ustar00rootroot00000000000000#!/bin/bash set -o errexit # Exit the script with error if any of the commands fail set -o xtrace rm -rf mongodb/pymongo rm -rf mongodb/gridfs rm -rf mongodb/bson pushd ../.. rm -f pymongo/*.so rm -f bson/*.so image="quay.io/pypa/manylinux2014_x86_64:latest" DOCKER=$(command -v docker) || true if [ -z "$DOCKER" ]; then PODMAN=$(command -v podman) || true if [ -z "$PODMAN" ]; then echo "docker or podman are required!" exit 1 fi DOCKER=podman fi $DOCKER run --rm -v "`pwd`:/src" $image /src/test/lambda/build_internal.sh cp -r pymongo ./test/lambda/mongodb/pymongo cp -r bson ./test/lambda/mongodb/bson cp -r gridfs ./test/lambda/mongodb/gridfs popd mongodb-mongo-python-driver-509e9b7/test/lambda/build_internal.sh000077500000000000000000000001401462766011000251610ustar00rootroot00000000000000#!/bin/bash -ex cd /src PYTHON=/opt/python/cp39-cp39/bin/python $PYTHON -m pip install -v -e . mongodb-mongo-python-driver-509e9b7/test/lambda/events/000077500000000000000000000000001462766011000231405ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/lambda/events/event.json000066400000000000000000000036601462766011000251610ustar00rootroot00000000000000{ "body": "{\"message\": \"hello world\"}", "resource": "/hello", "path": "/hello", "httpMethod": "GET", "isBase64Encoded": false, "queryStringParameters": { "foo": "bar" }, "pathParameters": { "proxy": "/path/to/resource" }, "stageVariables": { "baz": "qux" }, "headers": { "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8", "Accept-Encoding": "gzip, deflate, sdch", "Accept-Language": "en-US,en;q=0.8", "Cache-Control": "max-age=0", "CloudFront-Forwarded-Proto": "https", "CloudFront-Is-Desktop-Viewer": "true", "CloudFront-Is-Mobile-Viewer": "false", "CloudFront-Is-SmartTV-Viewer": "false", "CloudFront-Is-Tablet-Viewer": "false", "CloudFront-Viewer-Country": "US", "Host": "1234567890.execute-api.us-east-1.amazonaws.com", "Upgrade-Insecure-Requests": "1", "User-Agent": "Custom User Agent String", "Via": "1.1 08f323deadbeefa7af34d5feb414ce27.cloudfront.net (CloudFront)", "X-Amz-Cf-Id": "cDehVQoZnx43VYQb9j2-nvCh-9z396Uhbp027Y2JvkCPNLmGJHqlaA==", "X-Forwarded-For": "127.0.0.1, 127.0.0.2", "X-Forwarded-Port": "443", "X-Forwarded-Proto": "https" }, "requestContext": { "accountId": "123456789012", "resourceId": "123456", "stage": "prod", "requestId": "c6af9ac6-7b61-11e6-9a41-93e8deadbeef", "requestTime": "09/Apr/2015:12:34:56 +0000", "requestTimeEpoch": 1428582896000, "identity": { "cognitoIdentityPoolId": null, "accountId": null, "cognitoIdentityId": null, "caller": null, "accessKey": null, "sourceIp": "127.0.0.1", "cognitoAuthenticationType": null, "cognitoAuthenticationProvider": null, "userArn": null, "userAgent": "Custom User Agent String", "user": null }, "path": "/prod/hello", "resourcePath": "/hello", "httpMethod": "POST", "apiId": "1234567890", "protocol": "HTTP/1.1" } } mongodb-mongo-python-driver-509e9b7/test/lambda/mongodb/000077500000000000000000000000001462766011000232615ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/lambda/mongodb/Makefile000066400000000000000000000001471462766011000247230ustar00rootroot00000000000000 build-MongoDBFunction: cp -r . $(ARTIFACTS_DIR) python -m pip install -t $(ARTIFACTS_DIR) dnspython mongodb-mongo-python-driver-509e9b7/test/lambda/mongodb/__init__.py000066400000000000000000000000001462766011000253600ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/lambda/mongodb/app.py000066400000000000000000000103771462766011000244230ustar00rootroot00000000000000""" Lambda function for Python Driver testing Creates the client that is cached for all requests, subscribes to relevant events, and forces the connection pool to get populated. """ from __future__ import annotations import json import os from bson import has_c as has_bson_c from pymongo import MongoClient from pymongo import has_c as has_pymongo_c from pymongo.monitoring import ( CommandListener, ConnectionPoolListener, ServerHeartbeatListener, ) open_connections = 0 heartbeat_count = 0 streaming_heartbeat_count = 0 total_heartbeat_duration = 0 total_commands = 0 total_command_duration = 0 # Ensure we are using C extensions assert has_bson_c() assert has_pymongo_c() class CommandHandler(CommandListener): def started(self, event): print("command started", event) def succeeded(self, event): global total_commands, total_command_duration total_commands += 1 total_command_duration += event.duration_micros / 1e6 print("command succeeded", event) def failed(self, event): global total_commands, total_command_duration total_commands += 1 total_command_duration += event.duration_micros / 1e6 print("command failed", event) class ServerHeartbeatHandler(ServerHeartbeatListener): def started(self, event): print("server heartbeat started", event) def succeeded(self, event): global heartbeat_count, total_heartbeat_duration, streaming_heartbeat_count heartbeat_count += 1 total_heartbeat_duration += event.duration if event.awaited: streaming_heartbeat_count += 1 print("server heartbeat succeeded", event) def failed(self, event): global heartbeat_count, total_heartbeat_duration heartbeat_count += 1 total_heartbeat_duration += event.duration print("server heartbeat failed", event) class ConnectionHandler(ConnectionPoolListener): def connection_created(self, event): global open_connections open_connections += 1 print("connection created") def connection_ready(self, event): pass def connection_closed(self, event): global open_connections open_connections -= 1 print("connection closed") def connection_check_out_started(self, event): pass def connection_check_out_failed(self, event): pass def connection_checked_out(self, event): pass def connection_checked_in(self, event): pass def pool_created(self, event): pass def pool_ready(self, event): pass def pool_cleared(self, event): pass def pool_closed(self, event): pass listeners = [CommandHandler(), ServerHeartbeatHandler(), ConnectionHandler()] print("Creating client") client = MongoClient(os.environ["MONGODB_URI"], event_listeners=listeners) # Populate the connection pool. print("Connecting") client.lambdaTest.list_collections() print("Connected") # Create the response to send back. def create_response(): return dict( averageCommandDuration=total_command_duration / total_commands, averageHeartbeatDuration=total_heartbeat_duration / heartbeat_count if heartbeat_count else 0, openConnections=open_connections, heartbeatCount=heartbeat_count, ) # Reset the numbers. def reset(): global \ open_connections, \ heartbeat_count, \ total_heartbeat_duration, \ total_commands, \ total_command_duration open_connections = 0 heartbeat_count = 0 total_heartbeat_duration = 0 total_commands = 0 total_command_duration = 0 def lambda_handler(event, context): """ The handler function itself performs an insert/delete and returns the id of the document in play. """ print("initializing") db = client.lambdaTest collection = db.test result = collection.insert_one({"n": 1}) collection.delete_one({"_id": result.inserted_id}) # Create the response and then reset the numbers. response = json.dumps(create_response()) reset() print("finished!") assert ( streaming_heartbeat_count == 0 ), f"streaming_heartbeat_count was {streaming_heartbeat_count} not 0" return dict(statusCode=200, body=response) mongodb-mongo-python-driver-509e9b7/test/lambda/run.sh000077500000000000000000000003171462766011000230000ustar00rootroot00000000000000#!/bin/bash set -o errexit # Exit the script with error if any of the commands fail sam build sam local invoke --docker-network host --parameter-overrides "MongoDbUri=mongodb://host.docker.internal:27017" mongodb-mongo-python-driver-509e9b7/test/lambda/template.yaml000066400000000000000000000027331462766011000243400ustar00rootroot00000000000000AWSTemplateFormatVersion: '2010-09-09' Transform: AWS::Serverless-2016-10-31 Description: > Python driver lambda function test # More info about Globals: https://github.com/awslabs/serverless-application-model/blob/master/docs/globals.rst Globals: Function: Timeout: 30 MemorySize: 128 Parameters: MongoDbUri: Type: String Description: The MongoDB connection string. Resources: MongoDBFunction: Type: AWS::Serverless::Function Properties: CodeUri: mongodb/ Environment: Variables: MONGODB_URI: !Ref MongoDbUri Handler: app.lambda_handler Runtime: python3.9 Architectures: - x86_64 Events: MongoDB: Type: Api Properties: Path: /mongodb Method: get # Use a custom build method to make sure *.so files are copied. # https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/building-custom-runtimes.html Metadata: BuildMethod: makefile Outputs: MongoDBApi: Description: "API Gateway endpoint URL for Prod stage for Python driver lambda function" Value: !Sub "https://${ServerlessRestApi}.execute-api.${AWS::Region}.amazonaws.com/Prod/hello/" MongoDBFunction: Description: "Python driver lambda Function ARN" Value: !GetAtt MongoDBFunction.Arn MongoDBFunctionIamRole: Description: "Implicit IAM Role created for Python driver lambda function" Value: !GetAtt MongoDBFunctionRole.Arn mongodb-mongo-python-driver-509e9b7/test/load_balancer/000077500000000000000000000000001462766011000231625ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/load_balancer/cursors.json000066400000000000000000000730761462766011000255720ustar00rootroot00000000000000{ "description": "cursors are correctly pinned to connections for load-balanced clusters", "schemaVersion": "1.3", "runOnRequirements": [ { "topologies": [ "load-balanced" ] } ], "createEntities": [ { "client": { "id": "client0", "useMultipleMongoses": true, "observeEvents": [ "commandStartedEvent", "commandSucceededEvent", "commandFailedEvent", "connectionReadyEvent", "connectionClosedEvent", "connectionCheckedOutEvent", "connectionCheckedInEvent" ] } }, { "database": { "id": "database0", "client": "client0", "databaseName": "database0Name" } }, { "collection": { "id": "collection0", "database": "database0", "collectionName": "coll0" } }, { "collection": { "id": "collection1", "database": "database0", "collectionName": "coll1" } }, { "collection": { "id": "collection2", "database": "database0", "collectionName": "coll2" } } ], "initialData": [ { "collectionName": "coll0", "databaseName": "database0Name", "documents": [ { "_id": 1 }, { "_id": 2 }, { "_id": 3 } ] }, { "collectionName": "coll1", "databaseName": "database0Name", "documents": [] }, { "collectionName": "coll2", "databaseName": "database0Name", "documents": [] } ], "tests": [ { "description": "no connection is pinned if all documents are returned in the initial batch", "operations": [ { "name": "createFindCursor", "object": "collection0", "arguments": { "filter": {} }, "saveResultAsEntity": "cursor0" }, { "name": "assertNumberConnectionsCheckedOut", "object": "testRunner", "arguments": { "client": "client0", "connections": 0 } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "find": "coll0", "filter": {} }, "commandName": "find" } }, { "commandSucceededEvent": { "reply": { "cursor": { "id": 0, "firstBatch": { "$$type": "array" }, "ns": { "$$type": "string" } } }, "commandName": "find" } } ] }, { "client": "client0", "eventType": "cmap", "events": [ { "connectionReadyEvent": {} }, { "connectionCheckedOutEvent": {} }, { "connectionCheckedInEvent": {} } ] } ] }, { "description": "pinned connections are returned when the cursor is drained", "operations": [ { "name": "createFindCursor", "object": "collection0", "arguments": { "filter": {}, "batchSize": 2 }, "saveResultAsEntity": "cursor0" }, { "name": "assertNumberConnectionsCheckedOut", "object": "testRunner", "arguments": { "client": "client0", "connections": 1 } }, { "name": "iterateUntilDocumentOrError", "object": "cursor0", "expectResult": { "_id": 1 } }, { "name": "iterateUntilDocumentOrError", "object": "cursor0", "expectResult": { "_id": 2 } }, { "name": "iterateUntilDocumentOrError", "object": "cursor0", "expectResult": { "_id": 3 } }, { "name": "assertNumberConnectionsCheckedOut", "object": "testRunner", "arguments": { "client": "client0", "connections": 0 } }, { "name": "close", "object": "cursor0" } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "find": "coll0", "filter": {}, "batchSize": 2 }, "commandName": "find" } }, { "commandSucceededEvent": { "reply": { "cursor": { "id": { "$$type": "long" }, "firstBatch": { "$$type": "array" }, "ns": { "$$type": "string" } } }, "commandName": "find" } }, { "commandStartedEvent": { "command": { "getMore": { "$$type": "long" }, "collection": "coll0" }, "commandName": "getMore" } }, { "commandSucceededEvent": { "reply": { "cursor": { "id": 0, "ns": { "$$type": "string" }, "nextBatch": { "$$type": "array" } } }, "commandName": "getMore" } } ] }, { "client": "client0", "eventType": "cmap", "events": [ { "connectionReadyEvent": {} }, { "connectionCheckedOutEvent": {} }, { "connectionCheckedInEvent": {} } ] } ] }, { "description": "pinned connections are returned to the pool when the cursor is closed", "operations": [ { "name": "createFindCursor", "object": "collection0", "arguments": { "filter": {}, "batchSize": 2 }, "saveResultAsEntity": "cursor0" }, { "name": "assertNumberConnectionsCheckedOut", "object": "testRunner", "arguments": { "client": "client0", "connections": 1 } }, { "name": "close", "object": "cursor0" }, { "name": "assertNumberConnectionsCheckedOut", "object": "testRunner", "arguments": { "client": "client0", "connections": 0 } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "find": "coll0", "filter": {}, "batchSize": 2 }, "commandName": "find" } }, { "commandSucceededEvent": { "reply": { "cursor": { "id": { "$$type": "long" }, "firstBatch": { "$$type": "array" }, "ns": { "$$type": "string" } } }, "commandName": "find" } }, { "commandStartedEvent": { "commandName": "killCursors" } }, { "commandSucceededEvent": { "commandName": "killCursors" } } ] }, { "client": "client0", "eventType": "cmap", "events": [ { "connectionReadyEvent": {} }, { "connectionCheckedOutEvent": {} }, { "connectionCheckedInEvent": {} } ] } ] }, { "description": "pinned connections are returned after an network error during getMore", "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "client0", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "getMore" ], "closeConnection": true } } } }, { "name": "createFindCursor", "object": "collection0", "arguments": { "filter": {}, "batchSize": 2 }, "saveResultAsEntity": "cursor0" }, { "name": "assertNumberConnectionsCheckedOut", "object": "testRunner", "arguments": { "client": "client0", "connections": 1 } }, { "name": "iterateUntilDocumentOrError", "object": "cursor0", "expectResult": { "_id": 1 } }, { "name": "iterateUntilDocumentOrError", "object": "cursor0", "expectResult": { "_id": 2 } }, { "name": "iterateUntilDocumentOrError", "object": "cursor0", "expectError": { "isClientError": true } }, { "name": "assertNumberConnectionsCheckedOut", "object": "testRunner", "arguments": { "client": "client0", "connections": 0 } }, { "name": "close", "object": "cursor0" }, { "name": "assertNumberConnectionsCheckedOut", "object": "testRunner", "arguments": { "client": "client0", "connections": 0 } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "find": "coll0", "filter": {}, "batchSize": 2 }, "commandName": "find" } }, { "commandSucceededEvent": { "reply": { "cursor": { "id": { "$$type": "long" }, "firstBatch": { "$$type": "array" }, "ns": { "$$type": "string" } } }, "commandName": "find" } }, { "commandStartedEvent": { "command": { "getMore": { "$$type": "long" }, "collection": "coll0" }, "commandName": "getMore" } }, { "commandFailedEvent": { "commandName": "getMore" } } ] }, { "client": "client0", "eventType": "cmap", "events": [ { "connectionReadyEvent": {} }, { "connectionCheckedOutEvent": {} }, { "connectionCheckedInEvent": {} }, { "connectionCheckedOutEvent": {} }, { "connectionCheckedInEvent": {} }, { "connectionClosedEvent": { "reason": "error" } } ] } ] }, { "description": "pinned connections are returned after a network error during a killCursors request", "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "client0", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "killCursors" ], "closeConnection": true } } } }, { "name": "createFindCursor", "object": "collection0", "arguments": { "filter": {}, "batchSize": 2 }, "saveResultAsEntity": "cursor0" }, { "name": "assertNumberConnectionsCheckedOut", "object": "testRunner", "arguments": { "client": "client0", "connections": 1 } }, { "name": "close", "object": "cursor0" }, { "name": "assertNumberConnectionsCheckedOut", "object": "testRunner", "arguments": { "client": "client0", "connections": 0 } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "find": "coll0", "filter": {}, "batchSize": 2 }, "commandName": "find" } }, { "commandSucceededEvent": { "reply": { "cursor": { "id": { "$$type": "long" }, "firstBatch": { "$$type": "array" }, "ns": { "$$type": "string" } } }, "commandName": "find" } }, { "commandStartedEvent": { "commandName": "killCursors" } }, { "commandFailedEvent": { "commandName": "killCursors" } } ] }, { "client": "client0", "eventType": "cmap", "events": [ { "connectionReadyEvent": {} }, { "connectionCheckedOutEvent": {} }, { "connectionCheckedInEvent": {} }, { "connectionCheckedOutEvent": {} }, { "connectionCheckedInEvent": {} }, { "connectionClosedEvent": { "reason": "error" } } ] } ] }, { "description": "pinned connections are returned to the pool after a non-network error on getMore", "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "client0", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "getMore" ], "errorCode": 7 } } } }, { "name": "createFindCursor", "object": "collection0", "arguments": { "filter": {}, "batchSize": 2 }, "saveResultAsEntity": "cursor0" }, { "name": "iterateUntilDocumentOrError", "object": "cursor0", "expectResult": { "_id": 1 } }, { "name": "iterateUntilDocumentOrError", "object": "cursor0", "expectResult": { "_id": 2 } }, { "name": "iterateUntilDocumentOrError", "object": "cursor0", "expectError": { "errorCode": 7 } }, { "name": "assertNumberConnectionsCheckedOut", "object": "testRunner", "arguments": { "client": "client0", "connections": 0 } }, { "name": "close", "object": "cursor0" }, { "name": "assertNumberConnectionsCheckedOut", "object": "testRunner", "arguments": { "client": "client0", "connections": 0 } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "find": "coll0", "filter": {}, "batchSize": 2 }, "commandName": "find" } }, { "commandSucceededEvent": { "reply": { "cursor": { "id": { "$$type": "long" }, "firstBatch": { "$$type": "array" }, "ns": { "$$type": "string" } } }, "commandName": "find" } }, { "commandStartedEvent": { "command": { "getMore": { "$$type": "long" }, "collection": "coll0" }, "commandName": "getMore" } }, { "commandFailedEvent": { "commandName": "getMore" } }, { "commandStartedEvent": { "commandName": "killCursors" } }, { "commandSucceededEvent": { "commandName": "killCursors" } } ] }, { "client": "client0", "eventType": "cmap", "events": [ { "connectionReadyEvent": {} }, { "connectionCheckedOutEvent": {} }, { "connectionCheckedInEvent": {} }, { "connectionCheckedOutEvent": {} }, { "connectionCheckedInEvent": {} } ] } ] }, { "description": "aggregate pins the cursor to a connection", "operations": [ { "name": "aggregate", "object": "collection0", "arguments": { "pipeline": [], "batchSize": 2 } }, { "name": "assertNumberConnectionsCheckedOut", "object": "testRunner", "arguments": { "client": "client0", "connections": 0 } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "aggregate": "coll0", "cursor": { "batchSize": 2 } }, "commandName": "aggregate" } }, { "commandSucceededEvent": { "commandName": "aggregate" } }, { "commandStartedEvent": { "command": { "getMore": { "$$type": "long" }, "collection": "coll0" }, "commandName": "getMore" } }, { "commandSucceededEvent": { "reply": { "cursor": { "id": 0, "ns": { "$$type": "string" }, "nextBatch": { "$$type": "array" } } }, "commandName": "getMore" } } ] }, { "client": "client0", "eventType": "cmap", "events": [ { "connectionReadyEvent": {} }, { "connectionCheckedOutEvent": {} }, { "connectionCheckedInEvent": {} } ] } ] }, { "description": "listCollections pins the cursor to a connection", "runOnRequirements": [ { "serverless": "forbid" } ], "operations": [ { "name": "listCollections", "object": "database0", "arguments": { "filter": {}, "batchSize": 2 } }, { "name": "assertNumberConnectionsCheckedOut", "object": "testRunner", "arguments": { "client": "client0", "connections": 0 } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "listCollections": 1, "cursor": { "batchSize": 2 } }, "commandName": "listCollections", "databaseName": "database0Name" } }, { "commandSucceededEvent": { "commandName": "listCollections" } }, { "commandStartedEvent": { "command": { "getMore": { "$$type": "long" }, "collection": { "$$type": "string" } }, "commandName": "getMore" } }, { "commandSucceededEvent": { "reply": { "cursor": { "id": 0, "ns": { "$$type": "string" }, "nextBatch": { "$$type": "array" } } }, "commandName": "getMore" } } ] }, { "client": "client0", "eventType": "cmap", "events": [ { "connectionReadyEvent": {} }, { "connectionCheckedOutEvent": {} }, { "connectionCheckedInEvent": {} } ] } ] }, { "description": "listIndexes pins the cursor to a connection", "operations": [ { "name": "createIndex", "object": "collection0", "arguments": { "keys": { "x": 1 }, "name": "x_1" } }, { "name": "createIndex", "object": "collection0", "arguments": { "keys": { "y": 1 }, "name": "y_1" } }, { "name": "listIndexes", "object": "collection0", "arguments": { "batchSize": 2 } }, { "name": "assertNumberConnectionsCheckedOut", "object": "testRunner", "arguments": { "client": "client0", "connections": 0 } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "createIndexes": "coll0", "indexes": [ { "name": "x_1", "key": { "x": 1 } } ] }, "commandName": "createIndexes" } }, { "commandSucceededEvent": { "commandName": "createIndexes" } }, { "commandStartedEvent": { "command": { "createIndexes": "coll0", "indexes": [ { "name": "y_1", "key": { "y": 1 } } ] }, "commandName": "createIndexes" } }, { "commandSucceededEvent": { "commandName": "createIndexes" } }, { "commandStartedEvent": { "command": { "listIndexes": "coll0", "cursor": { "batchSize": 2 } }, "commandName": "listIndexes", "databaseName": "database0Name" } }, { "commandSucceededEvent": { "commandName": "listIndexes" } }, { "commandStartedEvent": { "command": { "getMore": { "$$type": "long" }, "collection": "coll0" }, "commandName": "getMore" } }, { "commandSucceededEvent": { "reply": { "cursor": { "id": 0, "ns": { "$$type": "string" }, "nextBatch": { "$$type": "array" } } }, "commandName": "getMore" } } ] }, { "client": "client0", "eventType": "cmap", "events": [ { "connectionReadyEvent": {} }, { "connectionCheckedOutEvent": {} }, { "connectionCheckedInEvent": {} }, { "connectionCheckedOutEvent": {} }, { "connectionCheckedInEvent": {} }, { "connectionCheckedOutEvent": {} }, { "connectionCheckedInEvent": {} } ] } ] }, { "description": "change streams pin to a connection", "runOnRequirements": [ { "serverless": "forbid" } ], "operations": [ { "name": "createChangeStream", "object": "collection0", "arguments": { "pipeline": [] }, "saveResultAsEntity": "changeStream0" }, { "name": "assertNumberConnectionsCheckedOut", "object": "testRunner", "arguments": { "client": "client0", "connections": 1 } }, { "name": "close", "object": "changeStream0" }, { "name": "assertNumberConnectionsCheckedOut", "object": "testRunner", "arguments": { "client": "client0", "connections": 0 } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "commandName": "aggregate" } }, { "commandSucceededEvent": { "commandName": "aggregate" } }, { "commandStartedEvent": { "commandName": "killCursors" } }, { "commandSucceededEvent": { "commandName": "killCursors" } } ] }, { "client": "client0", "eventType": "cmap", "events": [ { "connectionReadyEvent": {} }, { "connectionCheckedOutEvent": {} }, { "connectionCheckedInEvent": {} } ] } ] } ] } mongodb-mongo-python-driver-509e9b7/test/load_balancer/event-monitoring.json000066400000000000000000000076031462766011000273670ustar00rootroot00000000000000{ "description": "monitoring events include correct fields", "schemaVersion": "1.3", "runOnRequirements": [ { "topologies": [ "load-balanced" ] } ], "createEntities": [ { "client": { "id": "client0", "useMultipleMongoses": true, "uriOptions": { "retryReads": false }, "observeEvents": [ "commandStartedEvent", "commandSucceededEvent", "commandFailedEvent", "poolClearedEvent" ] } }, { "database": { "id": "database0", "client": "client0", "databaseName": "database0" } }, { "collection": { "id": "collection0", "database": "database0", "collectionName": "coll0" } } ], "initialData": [ { "databaseName": "database0", "collectionName": "coll0", "documents": [] } ], "tests": [ { "description": "command started and succeeded events include serviceId", "operations": [ { "name": "insertOne", "object": "collection0", "arguments": { "document": { "x": 1 } } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "commandName": "insert", "hasServiceId": true } }, { "commandSucceededEvent": { "commandName": "insert", "hasServiceId": true } } ] } ] }, { "description": "command failed events include serviceId", "operations": [ { "name": "find", "object": "collection0", "arguments": { "filter": { "$or": true } }, "expectError": { "isError": true } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "commandName": "find", "hasServiceId": true } }, { "commandFailedEvent": { "commandName": "find", "hasServiceId": true } } ] } ] }, { "description": "poolClearedEvent events include serviceId", "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "client0", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "find" ], "closeConnection": true } } } }, { "name": "find", "object": "collection0", "arguments": { "filter": {} }, "expectError": { "isClientError": true } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "commandName": "find", "hasServiceId": true } }, { "commandFailedEvent": { "commandName": "find", "hasServiceId": true } } ] }, { "client": "client0", "eventType": "cmap", "events": [ { "poolClearedEvent": { "hasServiceId": true } } ] } ] } ] } mongodb-mongo-python-driver-509e9b7/test/load_balancer/lb-connection-establishment.json000066400000000000000000000023331462766011000314500ustar00rootroot00000000000000{ "description": "connection establishment for load-balanced clusters", "schemaVersion": "1.3", "runOnRequirements": [ { "topologies": [ "load-balanced" ] } ], "createEntities": [ { "client": { "id": "client0", "uriOptions": { "loadBalanced": false }, "observeEvents": [ "commandStartedEvent" ] } }, { "database": { "id": "database0", "client": "client0", "databaseName": "database0" } } ], "tests": [ { "description": "operations against load balancers fail if URI contains loadBalanced=false", "skipReason": "servers have not implemented LB support yet so they will not fail the connection handshake in this case", "operations": [ { "name": "runCommand", "object": "database0", "arguments": { "commandName": "ping", "command": { "ping": 1 } }, "expectError": { "isClientError": false } } ], "expectEvents": [ { "client": "client0", "events": [] } ] } ] } mongodb-mongo-python-driver-509e9b7/test/load_balancer/non-lb-connection-establishment.json000066400000000000000000000037261462766011000322470ustar00rootroot00000000000000{ "description": "connection establishment if loadBalanced is specified for non-load balanced clusters", "schemaVersion": "1.3", "runOnRequirements": [ { "topologies": [ "single", "sharded" ] } ], "createEntities": [ { "client": { "id": "lbTrueClient", "useMultipleMongoses": false, "uriOptions": { "loadBalanced": true } } }, { "database": { "id": "lbTrueDatabase", "client": "lbTrueClient", "databaseName": "lbTrueDb" } }, { "client": { "id": "lbFalseClient", "uriOptions": { "loadBalanced": false } } }, { "database": { "id": "lbFalseDatabase", "client": "lbFalseClient", "databaseName": "lbFalseDb" } } ], "_yamlAnchors": { "runCommandArguments": [ { "arguments": { "commandName": "ping", "command": { "ping": 1 } } } ] }, "tests": [ { "description": "operations against non-load balanced clusters fail if URI contains loadBalanced=true", "operations": [ { "name": "runCommand", "object": "lbTrueDatabase", "arguments": { "commandName": "ping", "command": { "ping": 1 } }, "expectError": { "errorContains": "Driver attempted to initialize in load balancing mode, but the server does not support this mode" } } ] }, { "description": "operations against non-load balanced clusters succeed if URI contains loadBalanced=false", "operations": [ { "name": "runCommand", "object": "lbFalseDatabase", "arguments": { "commandName": "ping", "command": { "ping": 1 } } } ] } ] } mongodb-mongo-python-driver-509e9b7/test/load_balancer/sdam-error-handling.json000066400000000000000000000267001462766011000277170ustar00rootroot00000000000000{ "description": "state change errors are correctly handled", "schemaVersion": "1.3", "runOnRequirements": [ { "topologies": [ "load-balanced" ] } ], "_yamlAnchors": { "observedEvents": [ "connectionCreatedEvent", "connectionReadyEvent", "connectionCheckedOutEvent", "connectionCheckOutFailedEvent", "connectionCheckedInEvent", "connectionClosedEvent", "poolClearedEvent" ] }, "createEntities": [ { "client": { "id": "failPointClient", "useMultipleMongoses": false } }, { "client": { "id": "singleClient", "useMultipleMongoses": false, "uriOptions": { "appname": "lbSDAMErrorTestClient", "retryWrites": false }, "observeEvents": [ "connectionCreatedEvent", "connectionReadyEvent", "connectionCheckedOutEvent", "connectionCheckOutFailedEvent", "connectionCheckedInEvent", "connectionClosedEvent", "poolClearedEvent" ] } }, { "database": { "id": "singleDB", "client": "singleClient", "databaseName": "singleDB" } }, { "collection": { "id": "singleColl", "database": "singleDB", "collectionName": "singleColl" } }, { "client": { "id": "multiClient", "useMultipleMongoses": true, "uriOptions": { "retryWrites": false }, "observeEvents": [ "connectionCreatedEvent", "connectionReadyEvent", "connectionCheckedOutEvent", "connectionCheckOutFailedEvent", "connectionCheckedInEvent", "connectionClosedEvent", "poolClearedEvent" ] } }, { "database": { "id": "multiDB", "client": "multiClient", "databaseName": "multiDB" } }, { "collection": { "id": "multiColl", "database": "multiDB", "collectionName": "multiColl" } } ], "initialData": [ { "collectionName": "singleColl", "databaseName": "singleDB", "documents": [ { "_id": 1 }, { "_id": 2 }, { "_id": 3 } ] }, { "collectionName": "multiColl", "databaseName": "multiDB", "documents": [ { "_id": 1 }, { "_id": 2 }, { "_id": 3 } ] } ], "tests": [ { "description": "only connections for a specific serviceId are closed when pools are cleared", "runOnRequirements": [ { "serverless": "forbid" } ], "operations": [ { "name": "createFindCursor", "object": "multiColl", "arguments": { "filter": {}, "batchSize": 2 }, "saveResultAsEntity": "cursor0" }, { "name": "createFindCursor", "object": "multiColl", "arguments": { "filter": {}, "batchSize": 2 }, "saveResultAsEntity": "cursor1" }, { "name": "close", "object": "cursor0" }, { "name": "close", "object": "cursor1" }, { "name": "failPoint", "object": "testRunner", "arguments": { "client": "multiClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "insert" ], "errorCode": 11600 } } } }, { "name": "insertOne", "object": "multiColl", "arguments": { "document": { "x": 1 } }, "expectError": { "errorCode": 11600 } }, { "name": "insertOne", "object": "multiColl", "arguments": { "document": { "x": 1 } } } ], "expectEvents": [ { "client": "multiClient", "eventType": "cmap", "events": [ { "connectionCreatedEvent": {} }, { "connectionReadyEvent": {} }, { "connectionCheckedOutEvent": {} }, { "connectionCreatedEvent": {} }, { "connectionReadyEvent": {} }, { "connectionCheckedOutEvent": {} }, { "connectionCheckedInEvent": {} }, { "connectionCheckedInEvent": {} }, { "connectionCheckedOutEvent": {} }, { "connectionCheckedInEvent": {} }, { "connectionCheckedOutEvent": {} }, { "poolClearedEvent": {} }, { "connectionCheckedInEvent": {} }, { "connectionClosedEvent": { "reason": "stale" } }, { "connectionCheckedOutEvent": {} }, { "connectionCheckedInEvent": {} } ] } ] }, { "description": "errors during the initial connection hello are ignored", "runOnRequirements": [ { "minServerVersion": "4.9" } ], "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "ismaster", "isMaster", "hello" ], "closeConnection": true, "appName": "lbSDAMErrorTestClient" } } } }, { "name": "insertOne", "object": "singleColl", "arguments": { "document": { "x": 1 } }, "expectError": { "isClientError": true } } ], "expectEvents": [ { "client": "singleClient", "eventType": "cmap", "events": [ { "connectionCreatedEvent": {} }, { "connectionClosedEvent": { "reason": "error" } }, { "connectionCheckOutFailedEvent": { "reason": "connectionError" } } ] } ] }, { "description": "errors during authentication are processed", "runOnRequirements": [ { "auth": true } ], "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "saslContinue" ], "closeConnection": true, "appName": "lbSDAMErrorTestClient" } } } }, { "name": "insertOne", "object": "singleColl", "arguments": { "document": { "x": 1 } }, "expectError": { "isClientError": true } } ], "expectEvents": [ { "client": "singleClient", "eventType": "cmap", "events": [ { "connectionCreatedEvent": {} }, { "connectionClosedEvent": { "reason": "error" } }, { "connectionCheckOutFailedEvent": { "reason": "connectionError" } }, { "poolClearedEvent": {} } ] } ] }, { "description": "stale errors are ignored", "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 2 }, "data": { "failCommands": [ "getMore" ], "closeConnection": true } } } }, { "name": "createFindCursor", "object": "singleColl", "arguments": { "filter": {}, "batchSize": 2 }, "saveResultAsEntity": "cursor0" }, { "name": "createFindCursor", "object": "singleColl", "arguments": { "filter": {}, "batchSize": 2 }, "saveResultAsEntity": "cursor1" }, { "name": "iterateUntilDocumentOrError", "object": "cursor0" }, { "name": "iterateUntilDocumentOrError", "object": "cursor0" }, { "name": "iterateUntilDocumentOrError", "object": "cursor0", "expectError": { "isClientError": true } }, { "name": "close", "object": "cursor0" }, { "name": "iterateUntilDocumentOrError", "object": "cursor1" }, { "name": "iterateUntilDocumentOrError", "object": "cursor1" }, { "name": "iterateUntilDocumentOrError", "object": "cursor1", "expectError": { "isClientError": true } }, { "name": "close", "object": "cursor1" } ], "expectEvents": [ { "client": "singleClient", "eventType": "cmap", "events": [ { "connectionCreatedEvent": {} }, { "connectionReadyEvent": {} }, { "connectionCheckedOutEvent": {} }, { "connectionCreatedEvent": {} }, { "connectionReadyEvent": {} }, { "connectionCheckedOutEvent": {} }, { "poolClearedEvent": {} }, { "connectionCheckedInEvent": {} }, { "connectionClosedEvent": {} }, { "connectionCheckedInEvent": {} }, { "connectionClosedEvent": {} } ] } ] } ] } mongodb-mongo-python-driver-509e9b7/test/load_balancer/server-selection.json000066400000000000000000000032511462766011000273470ustar00rootroot00000000000000{ "description": "server selection for load-balanced clusters", "schemaVersion": "1.3", "runOnRequirements": [ { "topologies": [ "load-balanced" ] } ], "createEntities": [ { "client": { "id": "client0", "useMultipleMongoses": true, "observeEvents": [ "commandStartedEvent" ] } }, { "database": { "id": "database0", "client": "client0", "databaseName": "database0Name" } }, { "collection": { "id": "collection0", "database": "database0", "collectionName": "coll0", "collectionOptions": { "readPreference": { "mode": "secondaryPreferred" } } } } ], "initialData": [ { "collectionName": "coll0", "databaseName": "database0Name", "documents": [] } ], "tests": [ { "description": "$readPreference is sent for load-balanced clusters", "operations": [ { "name": "find", "object": "collection0", "arguments": { "filter": {} } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "find": "coll0", "filter": {}, "$readPreference": { "mode": "secondaryPreferred" } }, "commandName": "find", "databaseName": "database0Name" } } ] } ] } ] } mongodb-mongo-python-driver-509e9b7/test/load_balancer/transactions.json000066400000000000000000001117471462766011000266000ustar00rootroot00000000000000{ "description": "transactions are correctly pinned to connections for load-balanced clusters", "schemaVersion": "1.3", "runOnRequirements": [ { "topologies": [ "load-balanced" ] } ], "createEntities": [ { "client": { "id": "client0", "useMultipleMongoses": true, "observeEvents": [ "commandStartedEvent", "connectionReadyEvent", "connectionClosedEvent", "connectionCheckedOutEvent", "connectionCheckedInEvent" ] } }, { "session": { "id": "session0", "client": "client0" } }, { "database": { "id": "database0", "client": "client0", "databaseName": "database0Name" } }, { "collection": { "id": "collection0", "database": "database0", "collectionName": "coll0" } } ], "initialData": [ { "collectionName": "coll0", "databaseName": "database0Name", "documents": [ { "_id": 1 }, { "_id": 2 }, { "_id": 3 } ] } ], "_yamlAnchors": { "documents": [ { "_id": 4 } ] }, "tests": [ { "description": "sessions are reused in LB mode", "operations": [ { "name": "insertOne", "object": "collection0", "arguments": { "document": { "x": 1 } } }, { "name": "insertOne", "object": "collection0", "arguments": { "document": { "x": 1 } } }, { "name": "assertSameLsidOnLastTwoCommands", "object": "testRunner", "arguments": { "client": "client0" } } ] }, { "description": "all operations go to the same mongos", "operations": [ { "name": "startTransaction", "object": "session0" }, { "name": "insertOne", "object": "collection0", "arguments": { "document": { "x": 1 }, "session": "session0" } }, { "name": "assertNumberConnectionsCheckedOut", "object": "testRunner", "arguments": { "client": "client0", "connections": 1 } }, { "name": "insertOne", "object": "collection0", "arguments": { "document": { "x": 1 }, "session": "session0" } }, { "name": "insertOne", "object": "collection0", "arguments": { "document": { "x": 1 }, "session": "session0" } }, { "name": "insertOne", "object": "collection0", "arguments": { "document": { "x": 1 }, "session": "session0" } }, { "name": "insertOne", "object": "collection0", "arguments": { "document": { "x": 1 }, "session": "session0" } }, { "name": "insertOne", "object": "collection0", "arguments": { "document": { "x": 1 }, "session": "session0" } }, { "name": "assertNumberConnectionsCheckedOut", "object": "testRunner", "arguments": { "client": "client0", "connections": 1 } }, { "name": "commitTransaction", "object": "session0" } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "commandName": "insert" } }, { "commandStartedEvent": { "commandName": "insert" } }, { "commandStartedEvent": { "commandName": "insert" } }, { "commandStartedEvent": { "commandName": "insert" } }, { "commandStartedEvent": { "commandName": "insert" } }, { "commandStartedEvent": { "commandName": "insert" } }, { "commandStartedEvent": { "commandName": "commitTransaction" } } ] }, { "client": "client0", "eventType": "cmap", "events": [ { "connectionReadyEvent": {} }, { "connectionCheckedOutEvent": {} } ] } ] }, { "description": "transaction can be committed multiple times", "operations": [ { "name": "startTransaction", "object": "session0" }, { "name": "insertOne", "object": "collection0", "arguments": { "document": { "x": 1 }, "session": "session0" } }, { "name": "assertNumberConnectionsCheckedOut", "object": "testRunner", "arguments": { "client": "client0", "connections": 1 } }, { "name": "commitTransaction", "object": "session0" }, { "name": "assertNumberConnectionsCheckedOut", "object": "testRunner", "arguments": { "client": "client0", "connections": 1 } }, { "name": "commitTransaction", "object": "session0" }, { "name": "commitTransaction", "object": "session0" }, { "name": "commitTransaction", "object": "session0" }, { "name": "assertNumberConnectionsCheckedOut", "object": "testRunner", "arguments": { "client": "client0", "connections": 1 } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "commandName": "insert" } }, { "commandStartedEvent": { "commandName": "commitTransaction" } }, { "commandStartedEvent": { "commandName": "commitTransaction" } }, { "commandStartedEvent": { "commandName": "commitTransaction" } }, { "commandStartedEvent": { "commandName": "commitTransaction" } } ] }, { "client": "client0", "eventType": "cmap", "events": [ { "connectionReadyEvent": {} }, { "connectionCheckedOutEvent": {} } ] } ] }, { "description": "pinned connection is not released after a non-transient CRUD error", "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "client0", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "insert" ], "errorCode": 51 } } } }, { "name": "startTransaction", "object": "session0" }, { "name": "insertOne", "object": "collection0", "arguments": { "document": { "x": 1 }, "session": "session0" }, "expectError": { "errorCode": 51, "errorLabelsOmit": [ "TransientTransactionError" ] } }, { "name": "assertNumberConnectionsCheckedOut", "object": "testRunner", "arguments": { "client": "client0", "connections": 1 } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "commandName": "insert" } } ] }, { "client": "client0", "eventType": "cmap", "events": [ { "connectionReadyEvent": {} }, { "connectionCheckedOutEvent": {} }, { "connectionCheckedInEvent": {} }, { "connectionCheckedOutEvent": {} } ] } ] }, { "description": "pinned connection is not released after a non-transient commit error", "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "client0", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "commitTransaction" ], "errorCode": 51 } } } }, { "name": "startTransaction", "object": "session0" }, { "name": "insertOne", "object": "collection0", "arguments": { "document": { "x": 1 }, "session": "session0" } }, { "name": "commitTransaction", "object": "session0", "expectError": { "errorCode": 51, "errorLabelsOmit": [ "TransientTransactionError" ] } }, { "name": "assertNumberConnectionsCheckedOut", "object": "testRunner", "arguments": { "client": "client0", "connections": 1 } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "commandName": "insert" } }, { "commandStartedEvent": { "commandName": "commitTransaction" } } ] }, { "client": "client0", "eventType": "cmap", "events": [ { "connectionReadyEvent": {} }, { "connectionCheckedOutEvent": {} }, { "connectionCheckedInEvent": {} }, { "connectionCheckedOutEvent": {} } ] } ] }, { "description": "pinned connection is released after a non-transient abort error", "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "client0", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "abortTransaction" ], "errorCode": 51 } } } }, { "name": "startTransaction", "object": "session0" }, { "name": "insertOne", "object": "collection0", "arguments": { "document": { "x": 1 }, "session": "session0" } }, { "name": "abortTransaction", "object": "session0" }, { "name": "assertNumberConnectionsCheckedOut", "object": "testRunner", "arguments": { "client": "client0", "connections": 0 } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "commandName": "insert" } }, { "commandStartedEvent": { "commandName": "abortTransaction" } } ] }, { "client": "client0", "eventType": "cmap", "events": [ { "connectionReadyEvent": {} }, { "connectionCheckedOutEvent": {} }, { "connectionCheckedInEvent": {} }, { "connectionCheckedOutEvent": {} }, { "connectionCheckedInEvent": {} } ] } ] }, { "description": "pinned connection is released after a transient non-network CRUD error", "runOnRequirements": [ { "serverless": "forbid" } ], "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "client0", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "insert" ], "errorCode": 24 } } } }, { "name": "startTransaction", "object": "session0" }, { "name": "insertOne", "object": "collection0", "arguments": { "document": { "x": 1 }, "session": "session0" }, "expectError": { "errorCode": 24, "errorLabelsContain": [ "TransientTransactionError" ] } }, { "name": "assertNumberConnectionsCheckedOut", "object": "testRunner", "arguments": { "client": "client0", "connections": 0 } }, { "name": "abortTransaction", "object": "session0" }, { "name": "assertNumberConnectionsCheckedOut", "object": "testRunner", "arguments": { "client": "client0", "connections": 0 } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "commandName": "insert" } }, { "commandStartedEvent": { "commandName": "abortTransaction" } } ] }, { "client": "client0", "eventType": "cmap", "events": [ { "connectionReadyEvent": {} }, { "connectionCheckedOutEvent": {} }, { "connectionCheckedInEvent": {} }, { "connectionCheckedOutEvent": {} }, { "connectionCheckedInEvent": {} }, { "connectionCheckedOutEvent": {} }, { "connectionCheckedInEvent": {} } ] } ] }, { "description": "pinned connection is released after a transient network CRUD error", "runOnRequirements": [ { "serverless": "forbid" } ], "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "client0", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "insert" ], "closeConnection": true } } } }, { "name": "startTransaction", "object": "session0" }, { "name": "insertOne", "object": "collection0", "arguments": { "document": { "x": 1 }, "session": "session0" }, "expectError": { "isClientError": true, "errorLabelsContain": [ "TransientTransactionError" ] } }, { "name": "assertNumberConnectionsCheckedOut", "object": "testRunner", "arguments": { "client": "client0", "connections": 0 } }, { "name": "abortTransaction", "object": "session0" }, { "name": "assertNumberConnectionsCheckedOut", "object": "testRunner", "arguments": { "client": "client0", "connections": 0 } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "commandName": "insert" } }, { "commandStartedEvent": { "commandName": "abortTransaction" } } ] }, { "client": "client0", "eventType": "cmap", "events": [ { "connectionReadyEvent": {} }, { "connectionCheckedOutEvent": {} }, { "connectionCheckedInEvent": {} }, { "connectionCheckedOutEvent": {} }, { "connectionCheckedInEvent": {} }, { "connectionClosedEvent": { "reason": "error" } }, { "connectionReadyEvent": {} }, { "connectionCheckedOutEvent": {} }, { "connectionCheckedInEvent": {} } ] } ] }, { "description": "pinned connection is released after a transient non-network commit error", "runOnRequirements": [ { "serverless": "forbid" } ], "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "client0", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "commitTransaction" ], "errorCode": 24 } } } }, { "name": "startTransaction", "object": "session0" }, { "name": "insertOne", "object": "collection0", "arguments": { "document": { "x": 1 }, "session": "session0" } }, { "name": "commitTransaction", "object": "session0", "expectError": { "errorCode": 24, "errorLabelsContain": [ "TransientTransactionError" ] } }, { "name": "assertNumberConnectionsCheckedOut", "object": "testRunner", "arguments": { "client": "client0", "connections": 0 } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "commandName": "insert" } }, { "commandStartedEvent": { "commandName": "commitTransaction" } } ] }, { "client": "client0", "eventType": "cmap", "events": [ { "connectionReadyEvent": {} }, { "connectionCheckedOutEvent": {} }, { "connectionCheckedInEvent": {} }, { "connectionCheckedOutEvent": {} }, { "connectionCheckedInEvent": {} } ] } ] }, { "description": "pinned connection is released after a transient network commit error", "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "client0", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "commitTransaction" ], "closeConnection": true } } } }, { "name": "startTransaction", "object": "session0" }, { "name": "insertOne", "object": "collection0", "arguments": { "document": { "x": 1 }, "session": "session0" } }, { "name": "commitTransaction", "object": "session0", "ignoreResultAndError": true }, { "name": "assertNumberConnectionsCheckedOut", "object": "testRunner", "arguments": { "client": "client0", "connections": 0 } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "commandName": "insert" } }, { "commandStartedEvent": { "commandName": "commitTransaction" } }, { "commandStartedEvent": { "commandName": "commitTransaction" } } ] }, { "client": "client0", "eventType": "cmap", "events": [ { "connectionReadyEvent": {} }, { "connectionCheckedOutEvent": {} }, { "connectionCheckedInEvent": {} }, { "connectionCheckedOutEvent": {} }, { "connectionCheckedInEvent": {} }, { "connectionClosedEvent": { "reason": "error" } }, { "connectionReadyEvent": {} }, { "connectionCheckedOutEvent": {} }, { "connectionCheckedInEvent": {} } ] } ] }, { "description": "pinned connection is released after a transient non-network abort error", "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "client0", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "abortTransaction" ], "errorCode": 24 } } } }, { "name": "startTransaction", "object": "session0" }, { "name": "insertOne", "object": "collection0", "arguments": { "document": { "x": 1 }, "session": "session0" } }, { "name": "abortTransaction", "object": "session0" }, { "name": "assertNumberConnectionsCheckedOut", "object": "testRunner", "arguments": { "client": "client0", "connections": 0 } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "commandName": "insert" } }, { "commandStartedEvent": { "commandName": "abortTransaction" } } ] }, { "client": "client0", "eventType": "cmap", "events": [ { "connectionReadyEvent": {} }, { "connectionCheckedOutEvent": {} }, { "connectionCheckedInEvent": {} }, { "connectionCheckedOutEvent": {} }, { "connectionCheckedInEvent": {} } ] } ] }, { "description": "pinned connection is released after a transient network abort error", "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "client0", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "abortTransaction" ], "closeConnection": true } } } }, { "name": "startTransaction", "object": "session0" }, { "name": "insertOne", "object": "collection0", "arguments": { "document": { "x": 1 }, "session": "session0" } }, { "name": "abortTransaction", "object": "session0" }, { "name": "assertNumberConnectionsCheckedOut", "object": "testRunner", "arguments": { "client": "client0", "connections": 0 } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "commandName": "insert" } }, { "commandStartedEvent": { "commandName": "abortTransaction" } }, { "commandStartedEvent": { "commandName": "abortTransaction" } } ] }, { "client": "client0", "eventType": "cmap", "events": [ { "connectionReadyEvent": {} }, { "connectionCheckedOutEvent": {} }, { "connectionCheckedInEvent": {} }, { "connectionCheckedOutEvent": {} }, { "connectionCheckedInEvent": {} }, { "connectionClosedEvent": { "reason": "error" } }, { "connectionReadyEvent": {} }, { "connectionCheckedOutEvent": {} }, { "connectionCheckedInEvent": {} } ] } ] }, { "description": "pinned connection is released on successful abort", "operations": [ { "name": "startTransaction", "object": "session0" }, { "name": "insertOne", "object": "collection0", "arguments": { "document": { "x": 1 }, "session": "session0" } }, { "name": "abortTransaction", "object": "session0" }, { "name": "assertNumberConnectionsCheckedOut", "object": "testRunner", "arguments": { "client": "client0", "connections": 0 } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "commandName": "insert" } }, { "commandStartedEvent": { "commandName": "abortTransaction" } } ] }, { "client": "client0", "eventType": "cmap", "events": [ { "connectionReadyEvent": {} }, { "connectionCheckedOutEvent": {} }, { "connectionCheckedInEvent": {} } ] } ] }, { "description": "pinned connection is returned when a new transaction is started", "operations": [ { "name": "startTransaction", "object": "session0" }, { "name": "insertOne", "object": "collection0", "arguments": { "document": { "x": 1 }, "session": "session0" } }, { "name": "commitTransaction", "object": "session0" }, { "name": "assertNumberConnectionsCheckedOut", "object": "testRunner", "arguments": { "client": "client0", "connections": 1 } }, { "name": "startTransaction", "object": "session0" }, { "name": "assertNumberConnectionsCheckedOut", "object": "testRunner", "arguments": { "client": "client0", "connections": 0 } }, { "name": "insertOne", "object": "collection0", "arguments": { "document": { "x": 1 }, "session": "session0" } }, { "name": "assertNumberConnectionsCheckedOut", "object": "testRunner", "arguments": { "client": "client0", "connections": 1 } }, { "name": "commitTransaction", "object": "session0" } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "commandName": "insert" } }, { "commandStartedEvent": { "commandName": "commitTransaction" } }, { "commandStartedEvent": { "commandName": "insert" } }, { "commandStartedEvent": { "commandName": "commitTransaction" } } ] }, { "client": "client0", "eventType": "cmap", "events": [ { "connectionReadyEvent": {} }, { "connectionCheckedOutEvent": {} }, { "connectionCheckedInEvent": {} }, { "connectionCheckedOutEvent": {} } ] } ] }, { "description": "pinned connection is returned when a non-transaction operation uses the session", "operations": [ { "name": "startTransaction", "object": "session0" }, { "name": "insertOne", "object": "collection0", "arguments": { "document": { "x": 1 }, "session": "session0" } }, { "name": "commitTransaction", "object": "session0" }, { "name": "assertNumberConnectionsCheckedOut", "object": "testRunner", "arguments": { "client": "client0", "connections": 1 } }, { "name": "insertOne", "object": "collection0", "arguments": { "document": { "x": 1 }, "session": "session0" } }, { "name": "assertNumberConnectionsCheckedOut", "object": "testRunner", "arguments": { "client": "client0", "connections": 0 } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "commandName": "insert" } }, { "commandStartedEvent": { "commandName": "commitTransaction" } }, { "commandStartedEvent": { "commandName": "insert" } } ] }, { "client": "client0", "eventType": "cmap", "events": [ { "connectionReadyEvent": {} }, { "connectionCheckedOutEvent": {} }, { "connectionCheckedInEvent": {} }, { "connectionCheckedOutEvent": {} }, { "connectionCheckedInEvent": {} } ] } ] }, { "description": "a connection can be shared by a transaction and a cursor", "operations": [ { "name": "startTransaction", "object": "session0" }, { "name": "insertOne", "object": "collection0", "arguments": { "document": { "x": 1 }, "session": "session0" } }, { "name": "assertNumberConnectionsCheckedOut", "object": "testRunner", "arguments": { "client": "client0", "connections": 1 } }, { "name": "createFindCursor", "object": "collection0", "arguments": { "filter": {}, "batchSize": 2, "session": "session0" }, "saveResultAsEntity": "cursor0" }, { "name": "assertNumberConnectionsCheckedOut", "object": "testRunner", "arguments": { "client": "client0", "connections": 1 } }, { "name": "close", "object": "cursor0" }, { "name": "assertNumberConnectionsCheckedOut", "object": "testRunner", "arguments": { "client": "client0", "connections": 1 } }, { "name": "abortTransaction", "object": "session0" }, { "name": "assertNumberConnectionsCheckedOut", "object": "testRunner", "arguments": { "client": "client0", "connections": 0 } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "commandName": "insert" } }, { "commandStartedEvent": { "commandName": "find" } }, { "commandStartedEvent": { "commandName": "killCursors" } }, { "commandStartedEvent": { "commandName": "abortTransaction" } } ] }, { "client": "client0", "eventType": "cmap", "events": [ { "connectionReadyEvent": {} }, { "connectionCheckedOutEvent": {} }, { "connectionCheckedInEvent": {} } ] } ] } ] } mongodb-mongo-python-driver-509e9b7/test/load_balancer/wait-queue-timeouts.json000066400000000000000000000065451462766011000300240ustar00rootroot00000000000000{ "description": "wait queue timeout errors include details about checked out connections", "schemaVersion": "1.3", "runOnRequirements": [ { "topologies": [ "load-balanced" ] } ], "createEntities": [ { "client": { "id": "client0", "useMultipleMongoses": true, "uriOptions": { "maxPoolSize": 1, "waitQueueTimeoutMS": 50 }, "observeEvents": [ "connectionCheckedOutEvent", "connectionCheckOutFailedEvent" ] } }, { "session": { "id": "session0", "client": "client0" } }, { "database": { "id": "database0", "client": "client0", "databaseName": "database0Name" } }, { "collection": { "id": "collection0", "database": "database0", "collectionName": "coll0" } } ], "initialData": [ { "collectionName": "coll0", "databaseName": "database0Name", "documents": [ { "_id": 1 }, { "_id": 2 }, { "_id": 3 } ] } ], "tests": [ { "description": "wait queue timeout errors include cursor statistics", "operations": [ { "name": "createFindCursor", "object": "collection0", "arguments": { "filter": {}, "batchSize": 2 }, "saveResultAsEntity": "cursor0" }, { "name": "insertOne", "object": "collection0", "arguments": { "document": { "x": 1 } }, "expectError": { "isClientError": true, "errorContains": "maxPoolSize: 1, connections in use by cursors: 1, connections in use by transactions: 0, connections in use by other operations: 0" } } ], "expectEvents": [ { "client": "client0", "eventType": "cmap", "events": [ { "connectionCheckedOutEvent": {} }, { "connectionCheckOutFailedEvent": {} } ] } ] }, { "description": "wait queue timeout errors include transaction statistics", "operations": [ { "name": "startTransaction", "object": "session0" }, { "name": "insertOne", "object": "collection0", "arguments": { "document": { "x": 1 }, "session": "session0" } }, { "name": "insertOne", "object": "collection0", "arguments": { "document": { "x": 1 } }, "expectError": { "isClientError": true, "errorContains": "maxPoolSize: 1, connections in use by cursors: 0, connections in use by transactions: 1, connections in use by other operations: 0" } } ], "expectEvents": [ { "client": "client0", "eventType": "cmap", "events": [ { "connectionCheckedOutEvent": {} }, { "connectionCheckOutFailedEvent": {} } ] } ] } ] } mongodb-mongo-python-driver-509e9b7/test/max_staleness/000077500000000000000000000000001462766011000232625ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/max_staleness/ReplicaSetNoPrimary/000077500000000000000000000000001462766011000271565ustar00rootroot00000000000000DefaultNoMaxStaleness.json000066400000000000000000000027001462766011000342020ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/max_staleness/ReplicaSetNoPrimary{ "topology_description": { "type": "ReplicaSetNoPrimary", "servers": [ { "address": "a:27017", "type": "RSSecondary", "avg_rtt_ms": 50, "lastUpdateTime": 0, "maxWireVersion": 6, "lastWrite": { "lastWriteDate": { "$numberLong": "1000001" } } }, { "address": "b:27017", "type": "RSSecondary", "avg_rtt_ms": 5, "lastUpdateTime": 0, "maxWireVersion": 6, "lastWrite": { "lastWriteDate": { "$numberLong": "1" } } } ] }, "read_preference": { "mode": "Nearest" }, "suitable_servers": [ { "address": "a:27017", "type": "RSSecondary", "avg_rtt_ms": 50, "lastUpdateTime": 0, "maxWireVersion": 6, "lastWrite": { "lastWriteDate": { "$numberLong": "1000001" } } }, { "address": "b:27017", "type": "RSSecondary", "avg_rtt_ms": 5, "lastUpdateTime": 0, "maxWireVersion": 6, "lastWrite": { "lastWriteDate": { "$numberLong": "1" } } } ], "in_latency_window": [ { "address": "b:27017", "type": "RSSecondary", "avg_rtt_ms": 5, "lastUpdateTime": 0, "maxWireVersion": 6, "lastWrite": { "lastWriteDate": { "$numberLong": "1" } } } ] } mongodb-mongo-python-driver-509e9b7/test/max_staleness/ReplicaSetNoPrimary/LastUpdateTime.json000066400000000000000000000034321462766011000327400ustar00rootroot00000000000000{ "heartbeatFrequencyMS": 25000, "topology_description": { "type": "ReplicaSetNoPrimary", "servers": [ { "address": "a:27017", "type": "RSSecondary", "avg_rtt_ms": 5, "lastUpdateTime": 1, "lastWrite": { "lastWriteDate": { "$numberLong": "125002" } }, "maxWireVersion": 6 }, { "address": "b:27017", "type": "RSSecondary", "avg_rtt_ms": 50, "lastUpdateTime": 25002, "lastWrite": { "lastWriteDate": { "$numberLong": "2" } }, "maxWireVersion": 6 }, { "address": "c:27017", "type": "RSSecondary", "avg_rtt_ms": 5, "lastUpdateTime": 25001, "lastWrite": { "lastWriteDate": { "$numberLong": "1" } }, "maxWireVersion": 6 } ] }, "read_preference": { "mode": "Nearest", "maxStalenessSeconds": 150 }, "suitable_servers": [ { "address": "a:27017", "type": "RSSecondary", "avg_rtt_ms": 5, "lastUpdateTime": 1, "lastWrite": { "lastWriteDate": { "$numberLong": "125002" } }, "maxWireVersion": 6 }, { "address": "b:27017", "type": "RSSecondary", "avg_rtt_ms": 50, "lastUpdateTime": 25002, "lastWrite": { "lastWriteDate": { "$numberLong": "2" } }, "maxWireVersion": 6 } ], "in_latency_window": [ { "address": "a:27017", "type": "RSSecondary", "avg_rtt_ms": 5, "lastUpdateTime": 1, "lastWrite": { "lastWriteDate": { "$numberLong": "125002" } }, "maxWireVersion": 6 } ] } mongodb-mongo-python-driver-509e9b7/test/max_staleness/ReplicaSetNoPrimary/MaxStalenessTooSmall.json000066400000000000000000000005201462766011000341300ustar00rootroot00000000000000{ "topology_description": { "type": "ReplicaSetNoPrimary", "servers": [ { "address": "a:27017", "type": "Unknown" }, { "address": "b:27017", "type": "Unknown" } ] }, "read_preference": { "mode": "Nearest", "maxStalenessSeconds": 1 }, "error": true } mongodb-mongo-python-driver-509e9b7/test/max_staleness/ReplicaSetNoPrimary/Nearest.json000066400000000000000000000034161462766011000314560ustar00rootroot00000000000000{ "heartbeatFrequencyMS": 25000, "topology_description": { "type": "ReplicaSetNoPrimary", "servers": [ { "address": "a:27017", "type": "RSSecondary", "avg_rtt_ms": 5, "lastUpdateTime": 0, "lastWrite": { "lastWriteDate": { "$numberLong": "125002" } }, "maxWireVersion": 6 }, { "address": "b:27017", "type": "RSSecondary", "avg_rtt_ms": 50, "lastUpdateTime": 0, "lastWrite": { "lastWriteDate": { "$numberLong": "2" } }, "maxWireVersion": 6 }, { "address": "c:27017", "avg_rtt_ms": 5, "lastUpdateTime": 0, "type": "RSSecondary", "lastWrite": { "lastWriteDate": { "$numberLong": "1" } }, "maxWireVersion": 6 } ] }, "read_preference": { "mode": "Nearest", "maxStalenessSeconds": 150 }, "suitable_servers": [ { "address": "a:27017", "type": "RSSecondary", "avg_rtt_ms": 5, "lastUpdateTime": 0, "lastWrite": { "lastWriteDate": { "$numberLong": "125002" } }, "maxWireVersion": 6 }, { "address": "b:27017", "type": "RSSecondary", "avg_rtt_ms": 50, "lastUpdateTime": 0, "lastWrite": { "lastWriteDate": { "$numberLong": "2" } }, "maxWireVersion": 6 } ], "in_latency_window": [ { "address": "a:27017", "type": "RSSecondary", "avg_rtt_ms": 5, "lastUpdateTime": 0, "lastWrite": { "lastWriteDate": { "$numberLong": "125002" } }, "maxWireVersion": 6 } ] } mongodb-mongo-python-driver-509e9b7/test/max_staleness/ReplicaSetNoPrimary/Nearest2.json000066400000000000000000000034111462766011000315330ustar00rootroot00000000000000{ "heartbeatFrequencyMS": 25000, "topology_description": { "type": "ReplicaSetNoPrimary", "servers": [ { "address": "a:27017", "type": "RSSecondary", "avg_rtt_ms": 50, "lastUpdateTime": 0, "lastWrite": { "lastWriteDate": { "$numberLong": "125002" } }, "maxWireVersion": 6 }, { "address": "b:27017", "type": "RSSecondary", "avg_rtt_ms": 5, "lastUpdateTime": 0, "lastWrite": { "lastWriteDate": { "$numberLong": "2" } }, "maxWireVersion": 6 }, { "address": "c:27017", "avg_rtt_ms": 5, "lastUpdateTime": 0, "type": "RSSecondary", "lastWrite": { "lastWriteDate": { "$numberLong": "1" } }, "maxWireVersion": 6 } ] }, "read_preference": { "mode": "Nearest", "maxStalenessSeconds": 150 }, "suitable_servers": [ { "address": "a:27017", "type": "RSSecondary", "avg_rtt_ms": 50, "lastUpdateTime": 0, "lastWrite": { "lastWriteDate": { "$numberLong": "125002" } }, "maxWireVersion": 6 }, { "address": "b:27017", "type": "RSSecondary", "avg_rtt_ms": 5, "lastUpdateTime": 0, "lastWrite": { "lastWriteDate": { "$numberLong": "2" } }, "maxWireVersion": 6 } ], "in_latency_window": [ { "address": "b:27017", "type": "RSSecondary", "avg_rtt_ms": 5, "lastUpdateTime": 0, "lastWrite": { "lastWriteDate": { "$numberLong": "2" } }, "maxWireVersion": 6 } ] } mongodb-mongo-python-driver-509e9b7/test/max_staleness/ReplicaSetNoPrimary/NoKnownServers.json000066400000000000000000000005651462766011000330220ustar00rootroot00000000000000{ "topology_description": { "type": "ReplicaSetNoPrimary", "servers": [ { "address": "a:27017", "type": "Unknown" }, { "address": "b:27017", "type": "Unknown" } ] }, "read_preference": { "mode": "Nearest", "maxStalenessSeconds": 90 }, "suitable_servers": [], "in_latency_window": [] } OneKnownTwoUnavailable.json000066400000000000000000000022111462766011000343620ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/max_staleness/ReplicaSetNoPrimary{ "topology_description": { "type": "ReplicaSetNoPrimary", "servers": [ { "address": "a:27017", "type": "PossiblePrimary", "avg_rtt_ms": 5, "maxWireVersion": 0 }, { "address": "b:27017", "type": "Unknown", "avg_rtt_ms": 5, "maxWireVersion": 0 }, { "address": "c:27017", "type": "RSSecondary", "maxWireVersion": 6, "avg_rtt_ms": 5, "lastWrite": { "lastWriteDate": { "$numberLong": "1" } } } ] }, "read_preference": { "mode": "Nearest", "maxStalenessSeconds": 120 }, "suitable_servers": [ { "address": "c:27017", "type": "RSSecondary", "maxWireVersion": 6, "avg_rtt_ms": 5, "lastWrite": { "lastWriteDate": { "$numberLong": "1" } } } ], "in_latency_window": [ { "address": "c:27017", "type": "RSSecondary", "maxWireVersion": 6, "avg_rtt_ms": 5, "lastWrite": { "lastWriteDate": { "$numberLong": "1" } } } ] } mongodb-mongo-python-driver-509e9b7/test/max_staleness/ReplicaSetNoPrimary/PrimaryPreferred.json000066400000000000000000000024331462766011000333350ustar00rootroot00000000000000{ "heartbeatFrequencyMS": 25000, "topology_description": { "type": "ReplicaSetNoPrimary", "servers": [ { "address": "a:27017", "type": "RSSecondary", "avg_rtt_ms": 5, "lastUpdateTime": 0, "maxWireVersion": 6, "lastWrite": { "lastWriteDate": { "$numberLong": "1000001" } } }, { "address": "b:27017", "type": "RSSecondary", "avg_rtt_ms": 5, "lastUpdateTime": 0, "maxWireVersion": 6, "lastWrite": { "lastWriteDate": { "$numberLong": "1" } } } ] }, "read_preference": { "mode": "PrimaryPreferred", "maxStalenessSeconds": 90 }, "suitable_servers": [ { "address": "a:27017", "type": "RSSecondary", "avg_rtt_ms": 5, "lastUpdateTime": 0, "maxWireVersion": 6, "lastWrite": { "lastWriteDate": { "$numberLong": "1000001" } } } ], "in_latency_window": [ { "address": "a:27017", "type": "RSSecondary", "avg_rtt_ms": 5, "lastUpdateTime": 0, "maxWireVersion": 6, "lastWrite": { "lastWriteDate": { "$numberLong": "1000001" } } } ] } PrimaryPreferred_tags.json000066400000000000000000000031711462766011000342740ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/max_staleness/ReplicaSetNoPrimary{ "heartbeatFrequencyMS": 25000, "topology_description": { "type": "ReplicaSetNoPrimary", "servers": [ { "address": "a:27017", "type": "RSSecondary", "avg_rtt_ms": 5, "lastUpdateTime": 0, "lastWrite": { "lastWriteDate": { "$numberLong": "125002" } }, "maxWireVersion": 6, "tags": { "data_center": "tokyo" } }, { "address": "b:27017", "type": "RSSecondary", "avg_rtt_ms": 5, "lastUpdateTime": 0, "lastWrite": { "lastWriteDate": { "$numberLong": "1" } }, "maxWireVersion": 6, "tags": { "data_center": "nyc" } } ] }, "read_preference": { "mode": "PrimaryPreferred", "maxStalenessSeconds": 150, "tag_sets": [ { "data_center": "nyc" }, { "data_center": "tokyo" } ] }, "suitable_servers": [ { "address": "a:27017", "type": "RSSecondary", "avg_rtt_ms": 5, "lastUpdateTime": 0, "lastWrite": { "lastWriteDate": { "$numberLong": "125002" } }, "maxWireVersion": 6, "tags": { "data_center": "tokyo" } } ], "in_latency_window": [ { "address": "a:27017", "type": "RSSecondary", "avg_rtt_ms": 5, "lastUpdateTime": 0, "lastWrite": { "lastWriteDate": { "$numberLong": "125002" } }, "maxWireVersion": 6, "tags": { "data_center": "tokyo" } } ] } mongodb-mongo-python-driver-509e9b7/test/max_staleness/ReplicaSetNoPrimary/Secondary.json000066400000000000000000000043021462766011000317770ustar00rootroot00000000000000{ "heartbeatFrequencyMS": 25000, "topology_description": { "type": "ReplicaSetNoPrimary", "servers": [ { "address": "a:27017", "type": "RSSecondary", "avg_rtt_ms": 5, "lastUpdateTime": 0, "maxWireVersion": 6, "lastWrite": { "lastWriteDate": { "$numberLong": "125002" } }, "tags": { "data_center": "tokyo" } }, { "address": "b:27017", "type": "RSSecondary", "avg_rtt_ms": 5, "lastUpdateTime": 0, "maxWireVersion": 6, "lastWrite": { "lastWriteDate": { "$numberLong": "2" } }, "tags": { "data_center": "nyc" } }, { "address": "c:27017", "type": "RSSecondary", "avg_rtt_ms": 5, "lastUpdateTime": 0, "maxWireVersion": 6, "lastWrite": { "lastWriteDate": { "$numberLong": "1" } }, "tags": { "data_center": "nyc" } }, { "address": "d:27017", "type": "RSSecondary", "avg_rtt_ms": 5, "lastUpdateTime": 0, "maxWireVersion": 6, "lastWrite": { "lastWriteDate": { "$numberLong": "2" } }, "tags": { "data_center": "tokyo" } } ] }, "read_preference": { "mode": "Secondary", "maxStalenessSeconds": 150, "tag_sets": [ { "data_center": "nyc" } ] }, "suitable_servers": [ { "address": "b:27017", "type": "RSSecondary", "avg_rtt_ms": 5, "lastUpdateTime": 0, "maxWireVersion": 6, "lastWrite": { "lastWriteDate": { "$numberLong": "2" } }, "tags": { "data_center": "nyc" } } ], "in_latency_window": [ { "address": "b:27017", "type": "RSSecondary", "avg_rtt_ms": 5, "lastUpdateTime": 0, "maxWireVersion": 6, "lastWrite": { "lastWriteDate": { "$numberLong": "2" } }, "tags": { "data_center": "nyc" } } ] } mongodb-mongo-python-driver-509e9b7/test/max_staleness/ReplicaSetNoPrimary/SecondaryPreferred.json000066400000000000000000000023751462766011000336460ustar00rootroot00000000000000{ "topology_description": { "type": "ReplicaSetNoPrimary", "servers": [ { "address": "a:27017", "type": "RSSecondary", "avg_rtt_ms": 5, "lastUpdateTime": 0, "maxWireVersion": 6, "lastWrite": { "lastWriteDate": { "$numberLong": "1000001" } } }, { "address": "b:27017", "type": "RSSecondary", "avg_rtt_ms": 5, "lastUpdateTime": 0, "maxWireVersion": 6, "lastWrite": { "lastWriteDate": { "$numberLong": "1" } } } ] }, "read_preference": { "mode": "SecondaryPreferred", "maxStalenessSeconds": 120 }, "suitable_servers": [ { "address": "a:27017", "type": "RSSecondary", "avg_rtt_ms": 5, "lastUpdateTime": 0, "maxWireVersion": 6, "lastWrite": { "lastWriteDate": { "$numberLong": "1000001" } } } ], "in_latency_window": [ { "address": "a:27017", "type": "RSSecondary", "avg_rtt_ms": 5, "lastUpdateTime": 0, "maxWireVersion": 6, "lastWrite": { "lastWriteDate": { "$numberLong": "1000001" } } } ] } SecondaryPreferred_tags.json000066400000000000000000000043131462766011000345770ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/max_staleness/ReplicaSetNoPrimary{ "heartbeatFrequencyMS": 25000, "topology_description": { "type": "ReplicaSetNoPrimary", "servers": [ { "address": "a:27017", "type": "RSSecondary", "avg_rtt_ms": 5, "lastUpdateTime": 0, "maxWireVersion": 6, "lastWrite": { "lastWriteDate": { "$numberLong": "125002" } }, "tags": { "data_center": "tokyo" } }, { "address": "b:27017", "type": "RSSecondary", "avg_rtt_ms": 5, "lastUpdateTime": 0, "maxWireVersion": 6, "lastWrite": { "lastWriteDate": { "$numberLong": "2" } }, "tags": { "data_center": "nyc" } }, { "address": "c:27017", "type": "RSSecondary", "avg_rtt_ms": 5, "lastUpdateTime": 0, "maxWireVersion": 6, "lastWrite": { "lastWriteDate": { "$numberLong": "1" } }, "tags": { "data_center": "nyc" } }, { "address": "d:27017", "type": "RSSecondary", "avg_rtt_ms": 5, "lastUpdateTime": 0, "maxWireVersion": 6, "lastWrite": { "lastWriteDate": { "$numberLong": "2" } }, "tags": { "data_center": "tokyo" } } ] }, "read_preference": { "mode": "SecondaryPreferred", "maxStalenessSeconds": 150, "tag_sets": [ { "data_center": "nyc" } ] }, "suitable_servers": [ { "address": "b:27017", "type": "RSSecondary", "avg_rtt_ms": 5, "lastUpdateTime": 0, "maxWireVersion": 6, "lastWrite": { "lastWriteDate": { "$numberLong": "2" } }, "tags": { "data_center": "nyc" } } ], "in_latency_window": [ { "address": "b:27017", "type": "RSSecondary", "avg_rtt_ms": 5, "lastUpdateTime": 0, "maxWireVersion": 6, "lastWrite": { "lastWriteDate": { "$numberLong": "2" } }, "tags": { "data_center": "nyc" } } ] } mongodb-mongo-python-driver-509e9b7/test/max_staleness/ReplicaSetNoPrimary/ZeroMaxStaleness.json000066400000000000000000000013221462766011000333160ustar00rootroot00000000000000{ "topology_description": { "type": "ReplicaSetNoPrimary", "servers": [ { "address": "a:27017", "type": "RSSecondary", "avg_rtt_ms": 5, "lastUpdateTime": 0, "maxWireVersion": 6, "lastWrite": { "lastWriteDate": { "$numberLong": "2" } } }, { "address": "b:27017", "type": "RSSecondary", "avg_rtt_ms": 5, "lastUpdateTime": 0, "maxWireVersion": 6, "lastWrite": { "lastWriteDate": { "$numberLong": "1" } } } ] }, "read_preference": { "mode": "Nearest", "maxStalenessSeconds": 0 }, "error": true } mongodb-mongo-python-driver-509e9b7/test/max_staleness/ReplicaSetWithPrimary/000077500000000000000000000000001462766011000275155ustar00rootroot00000000000000DefaultNoMaxStaleness.json000066400000000000000000000026761462766011000345550ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/max_staleness/ReplicaSetWithPrimary{ "topology_description": { "type": "ReplicaSetWithPrimary", "servers": [ { "address": "a:27017", "type": "RSPrimary", "avg_rtt_ms": 50, "lastUpdateTime": 0, "maxWireVersion": 6, "lastWrite": { "lastWriteDate": { "$numberLong": "1000001" } } }, { "address": "b:27017", "type": "RSSecondary", "avg_rtt_ms": 5, "lastUpdateTime": 0, "maxWireVersion": 6, "lastWrite": { "lastWriteDate": { "$numberLong": "1" } } } ] }, "read_preference": { "mode": "Nearest" }, "suitable_servers": [ { "address": "a:27017", "type": "RSPrimary", "avg_rtt_ms": 50, "lastUpdateTime": 0, "maxWireVersion": 6, "lastWrite": { "lastWriteDate": { "$numberLong": "1000001" } } }, { "address": "b:27017", "type": "RSSecondary", "avg_rtt_ms": 5, "lastUpdateTime": 0, "maxWireVersion": 6, "lastWrite": { "lastWriteDate": { "$numberLong": "1" } } } ], "in_latency_window": [ { "address": "b:27017", "type": "RSSecondary", "avg_rtt_ms": 5, "lastUpdateTime": 0, "maxWireVersion": 6, "lastWrite": { "lastWriteDate": { "$numberLong": "1" } } } ] } mongodb-mongo-python-driver-509e9b7/test/max_staleness/ReplicaSetWithPrimary/LastUpdateTime.json000066400000000000000000000034211462766011000332750ustar00rootroot00000000000000{ "heartbeatFrequencyMS": 25000, "topology_description": { "type": "ReplicaSetWithPrimary", "servers": [ { "address": "a:27017", "type": "RSPrimary", "avg_rtt_ms": 50, "lastUpdateTime": 1, "lastWrite": { "lastWriteDate": { "$numberLong": "2" } }, "maxWireVersion": 6 }, { "address": "b:27017", "type": "RSSecondary", "avg_rtt_ms": 5, "lastUpdateTime": 125001, "lastWrite": { "lastWriteDate": { "$numberLong": "2" } }, "maxWireVersion": 6 }, { "address": "c:27017", "type": "RSSecondary", "avg_rtt_ms": 5, "lastUpdateTime": 125001, "lastWrite": { "lastWriteDate": { "$numberLong": "1" } }, "maxWireVersion": 6 } ] }, "read_preference": { "mode": "Nearest", "maxStalenessSeconds": 150 }, "suitable_servers": [ { "address": "a:27017", "type": "RSPrimary", "avg_rtt_ms": 50, "lastUpdateTime": 1, "lastWrite": { "lastWriteDate": { "$numberLong": "2" } }, "maxWireVersion": 6 }, { "address": "b:27017", "type": "RSSecondary", "avg_rtt_ms": 5, "lastUpdateTime": 125001, "lastWrite": { "lastWriteDate": { "$numberLong": "2" } }, "maxWireVersion": 6 } ], "in_latency_window": [ { "address": "b:27017", "type": "RSSecondary", "avg_rtt_ms": 5, "lastUpdateTime": 125001, "lastWrite": { "lastWriteDate": { "$numberLong": "2" } }, "maxWireVersion": 6 } ] } mongodb-mongo-python-driver-509e9b7/test/max_staleness/ReplicaSetWithPrimary/LongHeartbeat.json000066400000000000000000000027621462766011000331360ustar00rootroot00000000000000{ "heartbeatFrequencyMS": 120000, "topology_description": { "type": "ReplicaSetWithPrimary", "servers": [ { "address": "a:27017", "type": "RSPrimary", "avg_rtt_ms": 5, "lastUpdateTime": 0, "maxWireVersion": 6, "lastWrite": { "lastWriteDate": { "$numberLong": "1" } } }, { "address": "b:27017", "type": "RSSecondary", "avg_rtt_ms": 50, "lastUpdateTime": 0, "maxWireVersion": 6, "lastWrite": { "lastWriteDate": { "$numberLong": "1" } } } ] }, "read_preference": { "mode": "Nearest", "maxStalenessSeconds": 130 }, "suitable_servers": [ { "address": "a:27017", "type": "RSPrimary", "avg_rtt_ms": 5, "lastUpdateTime": 0, "maxWireVersion": 6, "lastWrite": { "lastWriteDate": { "$numberLong": "1" } } }, { "address": "b:27017", "type": "RSSecondary", "avg_rtt_ms": 50, "lastUpdateTime": 0, "maxWireVersion": 6, "lastWrite": { "lastWriteDate": { "$numberLong": "1" } } } ], "in_latency_window": [ { "address": "a:27017", "type": "RSPrimary", "avg_rtt_ms": 5, "lastUpdateTime": 0, "maxWireVersion": 6, "lastWrite": { "lastWriteDate": { "$numberLong": "1" } } } ] } mongodb-mongo-python-driver-509e9b7/test/max_staleness/ReplicaSetWithPrimary/LongHeartbeat2.json000066400000000000000000000013661462766011000332170ustar00rootroot00000000000000{ "heartbeatFrequencyMS": 120000, "topology_description": { "type": "ReplicaSetWithPrimary", "servers": [ { "address": "a:27017", "type": "RSPrimary", "avg_rtt_ms": 5, "lastUpdateTime": 0, "maxWireVersion": 6, "lastWrite": { "lastWriteDate": { "$numberLong": "1" } } }, { "address": "b:27017", "type": "RSSecondary", "avg_rtt_ms": 5, "lastUpdateTime": 0, "maxWireVersion": 6, "lastWrite": { "lastWriteDate": { "$numberLong": "1" } } } ] }, "read_preference": { "mode": "Nearest", "maxStalenessSeconds": 129 }, "error": true } MaxStalenessTooSmall.json000066400000000000000000000013621462766011000344150ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/max_staleness/ReplicaSetWithPrimary{ "heartbeatFrequencyMS": 500, "topology_description": { "type": "ReplicaSetWithPrimary", "servers": [ { "address": "a:27017", "type": "RSPrimary", "avg_rtt_ms": 5, "lastUpdateTime": 0, "maxWireVersion": 6, "lastWrite": { "lastWriteDate": { "$numberLong": "1" } } }, { "address": "b:27017", "type": "RSSecondary", "avg_rtt_ms": 5, "lastUpdateTime": 0, "maxWireVersion": 6, "lastWrite": { "lastWriteDate": { "$numberLong": "1" } } } ] }, "read_preference": { "mode": "Nearest", "maxStalenessSeconds": 89 }, "error": true } MaxStalenessWithModePrimary.json000066400000000000000000000012751462766011000357520ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/max_staleness/ReplicaSetWithPrimary{ "topology_description": { "type": "ReplicaSetWithPrimary", "servers": [ { "address": "a:27017", "type": "RSPrimary", "avg_rtt_ms": 5, "lastUpdateTime": 0, "maxWireVersion": 6, "lastWrite": { "lastWriteDate": { "$numberLong": "1" } } }, { "address": "b:27017", "type": "RSSecondary", "avg_rtt_ms": 5, "lastUpdateTime": 0, "maxWireVersion": 6, "lastWrite": { "lastWriteDate": { "$numberLong": "1" } } } ] }, "read_preference": { "maxStalenessSeconds": 120 }, "error": true } mongodb-mongo-python-driver-509e9b7/test/max_staleness/ReplicaSetWithPrimary/Nearest.json000066400000000000000000000034121462766011000320110ustar00rootroot00000000000000{ "heartbeatFrequencyMS": 25000, "topology_description": { "type": "ReplicaSetWithPrimary", "servers": [ { "address": "a:27017", "type": "RSPrimary", "avg_rtt_ms": 5, "lastUpdateTime": 0, "lastWrite": { "lastWriteDate": { "$numberLong": "125002" } }, "maxWireVersion": 6 }, { "address": "b:27017", "type": "RSSecondary", "avg_rtt_ms": 50, "lastUpdateTime": 0, "lastWrite": { "lastWriteDate": { "$numberLong": "2" } }, "maxWireVersion": 6 }, { "address": "c:27017", "avg_rtt_ms": 5, "lastUpdateTime": 0, "type": "RSSecondary", "lastWrite": { "lastWriteDate": { "$numberLong": "1" } }, "maxWireVersion": 6 } ] }, "read_preference": { "mode": "Nearest", "maxStalenessSeconds": 150 }, "suitable_servers": [ { "address": "a:27017", "type": "RSPrimary", "avg_rtt_ms": 5, "lastUpdateTime": 0, "lastWrite": { "lastWriteDate": { "$numberLong": "125002" } }, "maxWireVersion": 6 }, { "address": "b:27017", "type": "RSSecondary", "avg_rtt_ms": 50, "lastUpdateTime": 0, "lastWrite": { "lastWriteDate": { "$numberLong": "2" } }, "maxWireVersion": 6 } ], "in_latency_window": [ { "address": "a:27017", "type": "RSPrimary", "avg_rtt_ms": 5, "lastUpdateTime": 0, "lastWrite": { "lastWriteDate": { "$numberLong": "125002" } }, "maxWireVersion": 6 } ] } mongodb-mongo-python-driver-509e9b7/test/max_staleness/ReplicaSetWithPrimary/Nearest2.json000066400000000000000000000034071462766011000320770ustar00rootroot00000000000000{ "heartbeatFrequencyMS": 25000, "topology_description": { "type": "ReplicaSetWithPrimary", "servers": [ { "address": "a:27017", "type": "RSPrimary", "avg_rtt_ms": 50, "lastUpdateTime": 0, "lastWrite": { "lastWriteDate": { "$numberLong": "125002" } }, "maxWireVersion": 6 }, { "address": "b:27017", "type": "RSSecondary", "avg_rtt_ms": 5, "lastUpdateTime": 0, "lastWrite": { "lastWriteDate": { "$numberLong": "2" } }, "maxWireVersion": 6 }, { "address": "c:27017", "avg_rtt_ms": 5, "lastUpdateTime": 0, "type": "RSSecondary", "lastWrite": { "lastWriteDate": { "$numberLong": "1" } }, "maxWireVersion": 6 } ] }, "read_preference": { "mode": "Nearest", "maxStalenessSeconds": 150 }, "suitable_servers": [ { "address": "a:27017", "type": "RSPrimary", "avg_rtt_ms": 50, "lastUpdateTime": 0, "lastWrite": { "lastWriteDate": { "$numberLong": "125002" } }, "maxWireVersion": 6 }, { "address": "b:27017", "type": "RSSecondary", "avg_rtt_ms": 5, "lastUpdateTime": 0, "lastWrite": { "lastWriteDate": { "$numberLong": "2" } }, "maxWireVersion": 6 } ], "in_latency_window": [ { "address": "b:27017", "type": "RSSecondary", "avg_rtt_ms": 5, "lastUpdateTime": 0, "lastWrite": { "lastWriteDate": { "$numberLong": "2" } }, "maxWireVersion": 6 } ] } mongodb-mongo-python-driver-509e9b7/test/max_staleness/ReplicaSetWithPrimary/Nearest_tags.json000066400000000000000000000031541462766011000330320ustar00rootroot00000000000000{ "heartbeatFrequencyMS": 25000, "topology_description": { "type": "ReplicaSetWithPrimary", "servers": [ { "address": "a:27017", "type": "RSPrimary", "avg_rtt_ms": 5, "lastUpdateTime": 0, "lastWrite": { "lastWriteDate": { "$numberLong": "125002" } }, "maxWireVersion": 6, "tags": { "data_center": "tokyo" } }, { "address": "b:27017", "type": "RSSecondary", "avg_rtt_ms": 5, "lastUpdateTime": 0, "lastWrite": { "lastWriteDate": { "$numberLong": "1" } }, "maxWireVersion": 6, "tags": { "data_center": "nyc" } } ] }, "read_preference": { "mode": "Nearest", "maxStalenessSeconds": 150, "tag_sets": [ { "data_center": "nyc" }, { "data_center": "tokyo" } ] }, "suitable_servers": [ { "address": "a:27017", "type": "RSPrimary", "avg_rtt_ms": 5, "lastUpdateTime": 0, "lastWrite": { "lastWriteDate": { "$numberLong": "125002" } }, "maxWireVersion": 6, "tags": { "data_center": "tokyo" } } ], "in_latency_window": [ { "address": "a:27017", "type": "RSPrimary", "avg_rtt_ms": 5, "lastUpdateTime": 0, "lastWrite": { "lastWriteDate": { "$numberLong": "125002" } }, "maxWireVersion": 6, "tags": { "data_center": "tokyo" } } ] } mongodb-mongo-python-driver-509e9b7/test/max_staleness/ReplicaSetWithPrimary/PrimaryPreferred.json000066400000000000000000000024061462766011000336740ustar00rootroot00000000000000{ "heartbeatFrequencyMS": 25000, "topology_description": { "type": "ReplicaSetWithPrimary", "servers": [ { "address": "a:27017", "type": "RSPrimary", "avg_rtt_ms": 5, "lastUpdateTime": 0, "maxWireVersion": 6, "lastWrite": { "lastWriteDate": { "$numberLong": "1" } } }, { "address": "b:27017", "type": "RSSecondary", "avg_rtt_ms": 5, "lastUpdateTime": 0, "maxWireVersion": 6, "lastWrite": { "lastWriteDate": { "$numberLong": "1" } } } ] }, "read_preference": { "mode": "PrimaryPreferred", "maxStalenessSeconds": 150 }, "suitable_servers": [ { "address": "a:27017", "type": "RSPrimary", "avg_rtt_ms": 5, "lastUpdateTime": 0, "maxWireVersion": 6, "lastWrite": { "lastWriteDate": { "$numberLong": "1" } } } ], "in_latency_window": [ { "address": "a:27017", "type": "RSPrimary", "avg_rtt_ms": 5, "lastUpdateTime": 0, "maxWireVersion": 6, "lastWrite": { "lastWriteDate": { "$numberLong": "1" } } } ] } mongodb-mongo-python-driver-509e9b7/test/max_staleness/ReplicaSetWithPrimary/SecondaryPreferred.json000066400000000000000000000023711462766011000342010ustar00rootroot00000000000000{ "topology_description": { "type": "ReplicaSetWithPrimary", "servers": [ { "address": "a:27017", "type": "RSPrimary", "avg_rtt_ms": 5, "lastUpdateTime": 0, "maxWireVersion": 6, "lastWrite": { "lastWriteDate": { "$numberLong": "1000001" } } }, { "address": "b:27017", "type": "RSSecondary", "avg_rtt_ms": 5, "lastUpdateTime": 0, "maxWireVersion": 6, "lastWrite": { "lastWriteDate": { "$numberLong": "1" } } } ] }, "read_preference": { "mode": "SecondaryPreferred", "maxStalenessSeconds": 120 }, "suitable_servers": [ { "address": "a:27017", "type": "RSPrimary", "avg_rtt_ms": 5, "lastUpdateTime": 0, "maxWireVersion": 6, "lastWrite": { "lastWriteDate": { "$numberLong": "1000001" } } } ], "in_latency_window": [ { "address": "a:27017", "type": "RSPrimary", "avg_rtt_ms": 5, "lastUpdateTime": 0, "maxWireVersion": 6, "lastWrite": { "lastWriteDate": { "$numberLong": "1000001" } } } ] } SecondaryPreferred_tags.json000066400000000000000000000054111462766011000351360ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/max_staleness/ReplicaSetWithPrimary{ "heartbeatFrequencyMS": 25000, "topology_description": { "type": "ReplicaSetWithPrimary", "servers": [ { "address": "a:27017", "type": "RSPrimary", "avg_rtt_ms": 5, "lastUpdateTime": 0, "maxWireVersion": 6, "lastWrite": { "lastWriteDate": { "$numberLong": "125002" } } }, { "address": "b:27017", "type": "RSSecondary", "avg_rtt_ms": 5, "lastUpdateTime": 0, "maxWireVersion": 6, "lastWrite": { "lastWriteDate": { "$numberLong": "2" } }, "tags": { "data_center": "nyc" } }, { "address": "c:27017", "type": "RSSecondary", "avg_rtt_ms": 50, "lastUpdateTime": 1, "maxWireVersion": 6, "lastWrite": { "lastWriteDate": { "$numberLong": "1000001" } }, "tags": { "data_center": "nyc" } }, { "address": "d:27017", "type": "RSSecondary", "avg_rtt_ms": 5, "lastUpdateTime": 0, "maxWireVersion": 6, "lastWrite": { "lastWriteDate": { "$numberLong": "1" } }, "tags": { "data_center": "nyc" } }, { "address": "e:27017", "type": "RSSecondary", "avg_rtt_ms": 5, "lastUpdateTime": 0, "maxWireVersion": 6, "lastWrite": { "lastWriteDate": { "$numberLong": "2" } }, "tags": { "data_center": "tokyo" } } ] }, "read_preference": { "mode": "SecondaryPreferred", "maxStalenessSeconds": 150, "tag_sets": [ { "data_center": "nyc" } ] }, "suitable_servers": [ { "address": "b:27017", "type": "RSSecondary", "avg_rtt_ms": 5, "lastUpdateTime": 0, "maxWireVersion": 6, "lastWrite": { "lastWriteDate": { "$numberLong": "2" } }, "tags": { "data_center": "nyc" } }, { "address": "c:27017", "type": "RSSecondary", "avg_rtt_ms": 50, "lastUpdateTime": 1, "maxWireVersion": 6, "lastWrite": { "lastWriteDate": { "$numberLong": "1000001" } }, "tags": { "data_center": "nyc" } } ], "in_latency_window": [ { "address": "b:27017", "type": "RSSecondary", "avg_rtt_ms": 5, "lastUpdateTime": 0, "maxWireVersion": 6, "lastWrite": { "lastWriteDate": { "$numberLong": "2" } }, "tags": { "data_center": "nyc" } } ] } SecondaryPreferred_tags2.json000066400000000000000000000035731462766011000352270ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/max_staleness/ReplicaSetWithPrimary{ "heartbeatFrequencyMS": 25000, "topology_description": { "type": "ReplicaSetWithPrimary", "servers": [ { "address": "a:27017", "type": "RSPrimary", "avg_rtt_ms": 5, "lastUpdateTime": 0, "lastWrite": { "lastWriteDate": { "$numberLong": "125002" } }, "maxWireVersion": 6 }, { "address": "b:27017", "type": "RSSecondary", "avg_rtt_ms": 5, "lastUpdateTime": 0, "lastWrite": { "lastWriteDate": { "$numberLong": "2" } }, "maxWireVersion": 6, "tags": { "data_center": "tokyo" } }, { "address": "c:27017", "type": "RSSecondary", "avg_rtt_ms": 5, "lastUpdateTime": 0, "lastWrite": { "lastWriteDate": { "$numberLong": "1" } }, "maxWireVersion": 6, "tags": { "data_center": "nyc" } } ] }, "read_preference": { "mode": "SecondaryPreferred", "maxStalenessSeconds": 150, "tag_sets": [ { "data_center": "nyc" }, { "data_center": "tokyo" } ] }, "suitable_servers": [ { "address": "b:27017", "type": "RSSecondary", "avg_rtt_ms": 5, "lastUpdateTime": 0, "lastWrite": { "lastWriteDate": { "$numberLong": "2" } }, "maxWireVersion": 6, "tags": { "data_center": "tokyo" } } ], "in_latency_window": [ { "address": "b:27017", "type": "RSSecondary", "avg_rtt_ms": 5, "lastUpdateTime": 0, "lastWrite": { "lastWriteDate": { "$numberLong": "2" } }, "maxWireVersion": 6, "tags": { "data_center": "tokyo" } } ] } mongodb-mongo-python-driver-509e9b7/test/max_staleness/ReplicaSetWithPrimary/Secondary_tags.json000066400000000000000000000054001462766011000333540ustar00rootroot00000000000000{ "heartbeatFrequencyMS": 25000, "topology_description": { "type": "ReplicaSetWithPrimary", "servers": [ { "address": "a:27017", "type": "RSPrimary", "avg_rtt_ms": 5, "lastUpdateTime": 0, "maxWireVersion": 6, "lastWrite": { "lastWriteDate": { "$numberLong": "125002" } } }, { "address": "b:27017", "type": "RSSecondary", "avg_rtt_ms": 5, "lastUpdateTime": 0, "maxWireVersion": 6, "lastWrite": { "lastWriteDate": { "$numberLong": "2" } }, "tags": { "data_center": "nyc" } }, { "address": "c:27017", "type": "RSSecondary", "avg_rtt_ms": 50, "lastUpdateTime": 1, "maxWireVersion": 6, "lastWrite": { "lastWriteDate": { "$numberLong": "1000001" } }, "tags": { "data_center": "nyc" } }, { "address": "d:27017", "type": "RSSecondary", "avg_rtt_ms": 5, "lastUpdateTime": 0, "maxWireVersion": 6, "lastWrite": { "lastWriteDate": { "$numberLong": "1" } }, "tags": { "data_center": "nyc" } }, { "address": "e:27017", "type": "RSSecondary", "avg_rtt_ms": 5, "lastUpdateTime": 0, "maxWireVersion": 6, "lastWrite": { "lastWriteDate": { "$numberLong": "2" } }, "tags": { "data_center": "tokyo" } } ] }, "read_preference": { "mode": "Secondary", "maxStalenessSeconds": 150, "tag_sets": [ { "data_center": "nyc" } ] }, "suitable_servers": [ { "address": "b:27017", "type": "RSSecondary", "avg_rtt_ms": 5, "lastUpdateTime": 0, "maxWireVersion": 6, "lastWrite": { "lastWriteDate": { "$numberLong": "2" } }, "tags": { "data_center": "nyc" } }, { "address": "c:27017", "type": "RSSecondary", "avg_rtt_ms": 50, "lastUpdateTime": 1, "maxWireVersion": 6, "lastWrite": { "lastWriteDate": { "$numberLong": "1000001" } }, "tags": { "data_center": "nyc" } } ], "in_latency_window": [ { "address": "b:27017", "type": "RSSecondary", "avg_rtt_ms": 5, "lastUpdateTime": 0, "maxWireVersion": 6, "lastWrite": { "lastWriteDate": { "$numberLong": "2" } }, "tags": { "data_center": "nyc" } } ] } mongodb-mongo-python-driver-509e9b7/test/max_staleness/ReplicaSetWithPrimary/Secondary_tags2.json000066400000000000000000000035621462766011000334450ustar00rootroot00000000000000{ "heartbeatFrequencyMS": 25000, "topology_description": { "type": "ReplicaSetWithPrimary", "servers": [ { "address": "a:27017", "type": "RSPrimary", "avg_rtt_ms": 5, "lastUpdateTime": 0, "lastWrite": { "lastWriteDate": { "$numberLong": "125002" } }, "maxWireVersion": 6 }, { "address": "b:27017", "type": "RSSecondary", "avg_rtt_ms": 5, "lastUpdateTime": 0, "lastWrite": { "lastWriteDate": { "$numberLong": "2" } }, "maxWireVersion": 6, "tags": { "data_center": "tokyo" } }, { "address": "c:27017", "type": "RSSecondary", "avg_rtt_ms": 5, "lastUpdateTime": 0, "lastWrite": { "lastWriteDate": { "$numberLong": "1" } }, "maxWireVersion": 6, "tags": { "data_center": "nyc" } } ] }, "read_preference": { "mode": "Secondary", "maxStalenessSeconds": 150, "tag_sets": [ { "data_center": "nyc" }, { "data_center": "tokyo" } ] }, "suitable_servers": [ { "address": "b:27017", "type": "RSSecondary", "avg_rtt_ms": 5, "lastUpdateTime": 0, "lastWrite": { "lastWriteDate": { "$numberLong": "2" } }, "maxWireVersion": 6, "tags": { "data_center": "tokyo" } } ], "in_latency_window": [ { "address": "b:27017", "type": "RSSecondary", "avg_rtt_ms": 5, "lastUpdateTime": 0, "lastWrite": { "lastWriteDate": { "$numberLong": "2" } }, "maxWireVersion": 6, "tags": { "data_center": "tokyo" } } ] } mongodb-mongo-python-driver-509e9b7/test/max_staleness/ReplicaSetWithPrimary/ZeroMaxStaleness.json000066400000000000000000000013221462766011000336550ustar00rootroot00000000000000{ "topology_description": { "type": "ReplicaSetWithPrimary", "servers": [ { "address": "a:27017", "type": "RSPrimary", "avg_rtt_ms": 5, "lastUpdateTime": 0, "maxWireVersion": 6, "lastWrite": { "lastWriteDate": { "$numberLong": "2" } } }, { "address": "b:27017", "type": "RSSecondary", "avg_rtt_ms": 5, "lastUpdateTime": 0, "maxWireVersion": 6, "lastWrite": { "lastWriteDate": { "$numberLong": "1" } } } ] }, "read_preference": { "mode": "Nearest", "maxStalenessSeconds": 0 }, "error": true } mongodb-mongo-python-driver-509e9b7/test/max_staleness/Sharded/000077500000000000000000000000001462766011000246345ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/max_staleness/Sharded/SmallMaxStaleness.json000066400000000000000000000027161462766011000311350ustar00rootroot00000000000000{ "heartbeatFrequencyMS": 10000, "topology_description": { "type": "Sharded", "servers": [ { "address": "a:27017", "type": "Mongos", "avg_rtt_ms": 5, "lastUpdateTime": 0, "maxWireVersion": 6, "lastWrite": { "lastWriteDate": { "$numberLong": "1" } } }, { "address": "b:27017", "type": "Mongos", "avg_rtt_ms": 50, "lastUpdateTime": 0, "maxWireVersion": 6, "lastWrite": { "lastWriteDate": { "$numberLong": "1" } } } ] }, "read_preference": { "mode": "Nearest", "maxStalenessSeconds": 1 }, "suitable_servers": [ { "address": "a:27017", "type": "Mongos", "avg_rtt_ms": 5, "lastUpdateTime": 0, "maxWireVersion": 6, "lastWrite": { "lastWriteDate": { "$numberLong": "1" } } }, { "address": "b:27017", "type": "Mongos", "avg_rtt_ms": 50, "lastUpdateTime": 0, "maxWireVersion": 6, "lastWrite": { "lastWriteDate": { "$numberLong": "1" } } } ], "in_latency_window": [ { "address": "a:27017", "type": "Mongos", "avg_rtt_ms": 5, "lastUpdateTime": 0, "maxWireVersion": 6, "lastWrite": { "lastWriteDate": { "$numberLong": "1" } } } ] } mongodb-mongo-python-driver-509e9b7/test/max_staleness/Single/000077500000000000000000000000001462766011000245035ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/max_staleness/Single/SmallMaxStaleness.json000066400000000000000000000017451462766011000310050ustar00rootroot00000000000000{ "heartbeatFrequencyMS": 10000, "topology_description": { "type": "Single", "servers": [ { "address": "a:27017", "type": "Standalone", "avg_rtt_ms": 5, "lastUpdateTime": 0, "maxWireVersion": 6, "lastWrite": { "lastWriteDate": { "$numberLong": "1" } } } ] }, "read_preference": { "mode": "Nearest", "maxStalenessSeconds": 1 }, "suitable_servers": [ { "address": "a:27017", "type": "Standalone", "avg_rtt_ms": 5, "lastUpdateTime": 0, "maxWireVersion": 6, "lastWrite": { "lastWriteDate": { "$numberLong": "1" } } } ], "in_latency_window": [ { "address": "a:27017", "type": "Standalone", "avg_rtt_ms": 5, "lastUpdateTime": 0, "maxWireVersion": 6, "lastWrite": { "lastWriteDate": { "$numberLong": "1" } } } ] } mongodb-mongo-python-driver-509e9b7/test/max_staleness/Unknown/000077500000000000000000000000001462766011000247215ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/max_staleness/Unknown/SmallMaxStaleness.json000066400000000000000000000005351462766011000312170ustar00rootroot00000000000000{ "heartbeatFrequencyMS": 10000, "topology_description": { "type": "Unknown", "servers": [ { "address": "a:27017", "type": "Unknown", "maxWireVersion": 6 } ] }, "read_preference": { "mode": "Nearest", "maxStalenessSeconds": 1 }, "suitable_servers": [], "in_latency_window": [] } mongodb-mongo-python-driver-509e9b7/test/mockupdb/000077500000000000000000000000001462766011000222205ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/mockupdb/operations.py000066400000000000000000000100751462766011000247600ustar00rootroot00000000000000# Copyright 2015 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. from __future__ import annotations from collections import namedtuple from mockupdb import OpMsgReply, OpReply from pymongo import ReadPreference __all__ = ["operations", "upgrades"] Operation = namedtuple("Operation", ["name", "function", "reply", "op_type", "not_master"]) """Client operations on MongoDB. Each has a human-readable name, a function that actually executes a test, and a type that maps to one of the types in the Server Selection Spec: 'may-use-secondary', 'must-use-primary', etc. The special type 'always-use-secondary' applies to an operation with an explicit read mode, like the operation "command('c', read_preference=SECONDARY)". The not-master response is how a secondary responds to a must-use-primary op, or how a recovering member responds to a may-use-secondary op. Example uses: We can use "find_one" to validate that the SlaveOk bit is set when querying a standalone, even with mode PRIMARY, but that it isn't set when sent to a mongos with mode PRIMARY. Or it can validate that "$readPreference" is included in mongos queries except with mode PRIMARY or SECONDARY_PREFERRED (PYTHON-865). We can use "options_old" and "options_new" to test that the driver queries an old server's system.namespaces collection, but uses the listCollections command on a new server (PYTHON-857). "secondary command" is good to test that the client can direct reads to 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, ), ] _ops_by_name = {op.name: op for op in operations} Upgrade = namedtuple("Upgrade", ["name", "function", "old", "new", "wire_version"]) upgrades = [] mongodb-mongo-python-driver-509e9b7/test/mockupdb/test_auth_recovering_member.py000066400000000000000000000033661462766011000303540ustar00rootroot00000000000000# Copyright 2015 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. from __future__ import annotations import unittest from mockupdb import MockupDB from pymongo import MongoClient from pymongo.errors import ServerSelectionTimeoutError class TestAuthRecoveringMember(unittest.TestCase): def test_auth_recovering_member(self): # Test that we don't attempt auth against a recovering RS member. server = MockupDB() server.autoresponds( "ismaster", { "minWireVersion": 2, "maxWireVersion": 6, "ismaster": False, "secondary": False, "setName": "rs", }, ) server.run() self.addCleanup(server.stop) client = MongoClient( server.uri, replicaSet="rs", serverSelectionTimeoutMS=100, socketTimeoutMS=100 ) self.addCleanup(client.close) # Should see there's no primary or secondary and raise selection timeout # error. If it raises AutoReconnect we know it actually tried the # server, and that's wrong. with self.assertRaises(ServerSelectionTimeoutError): client.db.command("ping") if __name__ == "__main__": unittest.main() mongodb-mongo-python-driver-509e9b7/test/mockupdb/test_cluster_time.py000066400000000000000000000126641462766011000263410ustar00rootroot00000000000000# Copyright 2017-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. """Test $clusterTime handling.""" from __future__ import annotations import unittest from mockupdb import MockupDB, going from bson import Timestamp from pymongo import DeleteMany, InsertOne, MongoClient, UpdateOne class TestClusterTime(unittest.TestCase): def cluster_time_conversation(self, callback, replies): cluster_time = Timestamp(0, 0) server = MockupDB() # First test all commands include $clusterTime with wire version 6. _ = server.autoresponds( "ismaster", { "minWireVersion": 0, "maxWireVersion": 6, "$clusterTime": {"clusterTime": cluster_time}, }, ) server.run() self.addCleanup(server.stop) client = MongoClient(server.uri) self.addCleanup(client.close) with going(callback, client): for reply in replies: request = server.receives() self.assertIn("$clusterTime", request) self.assertEqual(request["$clusterTime"]["clusterTime"], cluster_time) cluster_time = Timestamp(cluster_time.time, cluster_time.inc + 1) reply["$clusterTime"] = {"clusterTime": cluster_time} request.reply(reply) def test_command(self): def callback(client): client.db.command("ping") client.db.command("ping") self.cluster_time_conversation(callback, [{"ok": 1}] * 2) def test_bulk(self): def callback(client: MongoClient[dict]) -> None: client.db.collection.bulk_write( [InsertOne({}), InsertOne({}), UpdateOne({}, {"$inc": {"x": 1}}), DeleteMany({})] ) self.cluster_time_conversation( callback, [{"ok": 1, "nInserted": 2}, {"ok": 1, "nModified": 1}, {"ok": 1, "nDeleted": 2}], ) batches = [ {"cursor": {"id": 123, "firstBatch": [{"a": 1}]}}, {"cursor": {"id": 123, "nextBatch": [{"a": 2}]}}, {"cursor": {"id": 0, "nextBatch": [{"a": 3}]}}, ] def test_cursor(self): def callback(client): list(client.db.collection.find()) self.cluster_time_conversation(callback, self.batches) def test_aggregate(self): def callback(client): list(client.db.collection.aggregate([])) self.cluster_time_conversation(callback, self.batches) def test_explain(self): def callback(client): client.db.collection.find().explain() self.cluster_time_conversation(callback, [{"ok": 1}]) def test_monitor(self): cluster_time = Timestamp(0, 0) reply = { "minWireVersion": 0, "maxWireVersion": 6, "$clusterTime": {"clusterTime": cluster_time}, } server = MockupDB() server.run() self.addCleanup(server.stop) client = MongoClient(server.uri, heartbeatFrequencyMS=500) self.addCleanup(client.close) request = server.receives("ismaster") # No $clusterTime in first ismaster, only in subsequent ones self.assertNotIn("$clusterTime", request) request.ok(reply) # Next exchange: client returns first clusterTime, we send the second. request = server.receives("ismaster") self.assertIn("$clusterTime", request) self.assertEqual(request["$clusterTime"]["clusterTime"], cluster_time) cluster_time = Timestamp(cluster_time.time, cluster_time.inc + 1) reply["$clusterTime"] = {"clusterTime": cluster_time} request.reply(reply) # Third exchange: client returns second clusterTime. request = server.receives("ismaster") self.assertEqual(request["$clusterTime"]["clusterTime"], cluster_time) # Return command error with a new clusterTime. cluster_time = Timestamp(cluster_time.time, cluster_time.inc + 1) error = { "ok": 0, "code": 211, "errmsg": "Cache Reader No keys found for HMAC ...", "$clusterTime": {"clusterTime": cluster_time}, } request.reply(error) # PyMongo 3.11+ closes the monitoring connection on command errors. # Fourth exchange: the Monitor closes the connection and runs the # handshake on a new connection. request = server.receives("ismaster") # No $clusterTime in first ismaster, only in subsequent ones self.assertNotIn("$clusterTime", request) # Reply without $clusterTime. reply.pop("$clusterTime") request.reply(reply) # Fifth exchange: the Monitor attempt uses the clusterTime from # the previous isMaster error. request = server.receives("ismaster") self.assertEqual(request["$clusterTime"]["clusterTime"], cluster_time) request.reply(reply) client.close() if __name__ == "__main__": unittest.main() mongodb-mongo-python-driver-509e9b7/test/mockupdb/test_cursor.py000066400000000000000000000062601462766011000251520ustar00rootroot00000000000000# Copyright 2023-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. """Test PyMongo cursor does not set exhaustAllowed automatically (PYTHON-4007).""" from __future__ import annotations import unittest from test import PyMongoTestCase from mockupdb import MockupDB, OpMsg, going from bson.objectid import ObjectId from pymongo import MongoClient from pymongo.errors import OperationFailure class TestCursor(unittest.TestCase): def test_getmore_load_balanced(self): server = MockupDB() server.autoresponds( "hello", isWritablePrimary=True, msg="isdbgrid", minWireVersion=0, maxWireVersion=20, helloOk=True, serviceId=ObjectId(), ) server.run() self.addCleanup(server.stop) client = MongoClient(server.uri, loadBalanced=True) self.addCleanup(client.close) collection = client.db.coll cursor = collection.find() with going(next, cursor): request = server.receives(OpMsg({"find": "coll"})) self.assertEqual(request.flags, 0, "exhaustAllowed should not be set") # Respond with a different namespace. request.reply({"cursor": {"id": 123, "firstBatch": [{}]}}) # 3 batches, check exhaustAllowed on all getMores. for i in range(1, 3): with going(next, cursor): request = server.receives(OpMsg({"getMore": 123})) self.assertEqual(request.flags, 0, "exhaustAllowed should not be set") cursor_id = 123 if i < 2 else 0 request.replies({"cursor": {"id": cursor_id, "nextBatch": [{}]}}) class TestRetryableErrorCodeCatch(PyMongoTestCase): def _test_fail_on_operation_failure_with_code(self, code): """Test reads on error codes that should not be retried""" server = MockupDB() server.run() self.addCleanup(server.stop) server.autoresponds("ismaster", maxWireVersion=6) client = MongoClient(server.uri) with going(lambda: server.receives(OpMsg({"find": "collection"})).command_err(code=code)): cursor = client.db.collection.find() with self.assertRaises(OperationFailure) as ctx: cursor.next() self.assertEqual(ctx.exception.code, code) def test_fail_on_operation_failure_none(self): self._test_fail_on_operation_failure_with_code(None) def test_fail_on_operation_failure_zero(self): self._test_fail_on_operation_failure_with_code(0) def test_fail_on_operation_failure_one(self): self._test_fail_on_operation_failure_with_code(1) if __name__ == "__main__": unittest.main() mongodb-mongo-python-driver-509e9b7/test/mockupdb/test_cursor_namespace.py000066400000000000000000000104611462766011000271640ustar00rootroot00000000000000# Copyright 2015 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. """Test list_indexes with more than one batch.""" from __future__ import annotations import unittest from mockupdb import MockupDB, going from pymongo import MongoClient class TestCursorNamespace(unittest.TestCase): server: MockupDB client: MongoClient @classmethod def setUpClass(cls): cls.server = MockupDB(auto_ismaster={"maxWireVersion": 6}) cls.server.run() cls.client = MongoClient(cls.server.uri) @classmethod def tearDownClass(cls): cls.client.close() cls.server.stop() def _test_cursor_namespace(self, cursor_op, command): with going(cursor_op) as docs: request = self.server.receives(**{command: "collection", "namespace": "test"}) # Respond with a different namespace. request.reply( { "cursor": { "firstBatch": [{"doc": 1}], "id": 123, "ns": "different_db.different.coll", } } ) # Client uses the namespace we returned. request = self.server.receives( getMore=123, namespace="different_db", collection="different.coll" ) request.reply({"cursor": {"nextBatch": [{"doc": 2}], "id": 0}}) self.assertEqual([{"doc": 1}, {"doc": 2}], docs()) def test_aggregate_cursor(self): def op(): return list(self.client.test.collection.aggregate([])) self._test_cursor_namespace(op, "aggregate") def test_find_cursor(self): def op(): return list(self.client.test.collection.find()) self._test_cursor_namespace(op, "find") def test_list_indexes(self): def op(): return list(self.client.test.collection.list_indexes()) self._test_cursor_namespace(op, "listIndexes") class TestKillCursorsNamespace(unittest.TestCase): server: MockupDB client: MongoClient @classmethod def setUpClass(cls): cls.server = MockupDB(auto_ismaster={"maxWireVersion": 6}) cls.server.run() cls.client = MongoClient(cls.server.uri) @classmethod def tearDownClass(cls): cls.client.close() cls.server.stop() def _test_killCursors_namespace(self, cursor_op, command): with going(cursor_op): request = self.server.receives(**{command: "collection", "namespace": "test"}) # Respond with a different namespace. request.reply( { "cursor": { "firstBatch": [{"doc": 1}], "id": 123, "ns": "different_db.different.coll", } } ) # Client uses the namespace we returned for killCursors. request = self.server.receives( **{"killCursors": "different.coll", "cursors": [123], "$db": "different_db"} ) request.reply( { "ok": 1, "cursorsKilled": [123], "cursorsNotFound": [], "cursorsAlive": [], "cursorsUnknown": [], } ) def test_aggregate_killCursor(self): def op(): cursor = self.client.test.collection.aggregate([], batchSize=1) next(cursor) cursor.close() self._test_killCursors_namespace(op, "aggregate") def test_find_killCursor(self): def op(): cursor = self.client.test.collection.find(batch_size=1) next(cursor) cursor.close() self._test_killCursors_namespace(op, "find") if __name__ == "__main__": unittest.main() mongodb-mongo-python-driver-509e9b7/test/mockupdb/test_getmore_sharded.py000066400000000000000000000040421462766011000267650ustar00rootroot00000000000000# Copyright 2015 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. """Test PyMongo cursor with a sharded cluster.""" from __future__ import annotations import unittest from queue import Queue from mockupdb import MockupDB, going from pymongo import MongoClient class TestGetmoreSharded(unittest.TestCase): def test_getmore_sharded(self): servers = [MockupDB(), MockupDB()] # Collect queries to either server in one queue. q: Queue = Queue() for server in servers: server.subscribe(q.put) server.autoresponds( "ismaster", ismaster=True, msg="isdbgrid", minWireVersion=2, maxWireVersion=6 ) server.run() self.addCleanup(server.stop) client = MongoClient( "mongodb://%s:%d,%s:%d" % (servers[0].host, servers[0].port, servers[1].host, servers[1].port) ) self.addCleanup(client.close) collection = client.db.collection cursor = collection.find() with going(next, cursor): query = q.get(timeout=1) query.replies({"cursor": {"id": 123, "firstBatch": [{}]}}) # 10 batches, all getMores go to same server. for i in range(1, 10): with going(next, cursor): getmore = q.get(timeout=1) self.assertEqual(query.server, getmore.server) cursor_id = 123 if i < 9 else 0 getmore.replies({"cursor": {"id": cursor_id, "nextBatch": [{}]}}) if __name__ == "__main__": unittest.main() mongodb-mongo-python-driver-509e9b7/test/mockupdb/test_handshake.py000066400000000000000000000251051462766011000255620ustar00rootroot00000000000000# Copyright 2016 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. from __future__ import annotations import unittest from mockupdb import Command, MockupDB, OpMsg, OpMsgReply, OpQuery, OpReply, absent, go from bson.objectid import ObjectId from pymongo import MongoClient from pymongo import version as pymongo_version from pymongo.errors import OperationFailure from pymongo.server_api import ServerApi, ServerApiVersion def _check_handshake_data(request): assert "client" in request data = request["client"] assert data["application"] == {"name": "my app"} assert data["driver"] == {"name": "PyMongo", "version": pymongo_version} # Keep it simple, just check these fields exist. assert "os" in data assert "platform" in data class TestHandshake(unittest.TestCase): def hello_with_option_helper(self, protocol, **kwargs): hello = "ismaster" if isinstance(protocol(), OpQuery) else "hello" # `db.command("hello"|"ismaster")` commands are the same for primaries and # secondaries, so we only need one server. primary = MockupDB() # Set up a custom handler to save the first request from the driver. self.handshake_req = None def respond(r): # Only save the very first request from the driver. if self.handshake_req is None: self.handshake_req = r load_balanced_kwargs = {"serviceId": ObjectId()} if kwargs.get("loadBalanced") else {} return r.reply( OpMsgReply(minWireVersion=0, maxWireVersion=13, **kwargs, **load_balanced_kwargs) ) primary.autoresponds(respond) primary.run() self.addCleanup(primary.stop) # We need a special dict because MongoClient uses "server_api" and all # of the commands use "apiVersion". k_map = {("apiVersion", "1"): ("server_api", ServerApi(ServerApiVersion.V1))} client = MongoClient( "mongodb://" + primary.address_string, appname="my app", # For _check_handshake_data() **dict([k_map.get((k, v), (k, v)) for k, v in kwargs.items()]), # type: ignore[arg-type] ) self.addCleanup(client.close) # We have an autoresponder luckily, so no need for `go()`. assert client.db.command(hello) # We do this checking here rather than in the autoresponder `respond()` # because it runs in another Python thread so there are some funky things # with error handling within that thread, and we want to be able to use # self.assertRaises(). self.handshake_req.assert_matches(protocol(hello, **kwargs)) _check_handshake_data(self.handshake_req) def test_client_handshake_data(self): primary, secondary = MockupDB(), MockupDB() for server in primary, secondary: server.run() self.addCleanup(server.stop) hosts = [server.address_string for server in (primary, secondary)] primary_response = OpReply( "ismaster", True, setName="rs", hosts=hosts, minWireVersion=2, maxWireVersion=6 ) error_response = OpReply(0, errmsg="Cache Reader No keys found for HMAC ...", code=211) secondary_response = OpReply( "ismaster", False, setName="rs", hosts=hosts, secondary=True, minWireVersion=2, maxWireVersion=6, ) client = MongoClient( primary.uri, replicaSet="rs", appname="my app", heartbeatFrequencyMS=500 ) # Speed up the test. self.addCleanup(client.close) # New monitoring connections send data during handshake. heartbeat = primary.receives("ismaster") _check_handshake_data(heartbeat) heartbeat.ok(primary_response) heartbeat = secondary.receives("ismaster") _check_handshake_data(heartbeat) heartbeat.ok(secondary_response) # Subsequent heartbeats have no client data. primary.receives("ismaster", 1, client=absent).ok(error_response) secondary.receives("ismaster", 1, client=absent).ok(error_response) # The heartbeat retry (on a new connection) does have client data. heartbeat = primary.receives("ismaster") _check_handshake_data(heartbeat) heartbeat.ok(primary_response) heartbeat = secondary.receives("ismaster") _check_handshake_data(heartbeat) heartbeat.ok(secondary_response) # Still no client data. primary.receives("ismaster", 1, client=absent).ok(primary_response) secondary.receives("ismaster", 1, client=absent).ok(secondary_response) # After a disconnect, next ismaster has client data again. primary.receives("ismaster", 1, client=absent).hangup() heartbeat = primary.receives("ismaster") _check_handshake_data(heartbeat) heartbeat.ok(primary_response) secondary.autoresponds("ismaster", secondary_response) # Start a command, so the client opens an application socket. future = go(client.db.command, "whatever") for request in primary: if request.matches(Command("ismaster")): if request.client_port == heartbeat.client_port: # This is the monitor again, keep going. request.ok(primary_response) else: # Handshaking a new application socket. _check_handshake_data(request) request.ok(primary_response) else: # Command succeeds. request.assert_matches(OpMsg("whatever")) request.ok() assert future() return def test_client_handshake_saslSupportedMechs(self): server = MockupDB() server.run() self.addCleanup(server.stop) primary_response = OpReply("ismaster", True, minWireVersion=2, maxWireVersion=6) client = MongoClient(server.uri, username="username", password="password") self.addCleanup(client.close) # New monitoring connections send data during handshake. heartbeat = server.receives("ismaster") heartbeat.ok(primary_response) future = go(client.db.command, "whatever") for request in server: if request.matches("ismaster"): if request.client_port == heartbeat.client_port: # This is the monitor again, keep going. request.ok(primary_response) else: # Handshaking a new application socket should send # saslSupportedMechs and speculativeAuthenticate. self.assertEqual(request["saslSupportedMechs"], "admin.username") self.assertIn("saslStart", request["speculativeAuthenticate"]) auth = { "conversationId": 1, "done": False, "payload": b"r=wPleNM8S5p8gMaffMDF7Py4ru9bnmmoqb0" b"1WNPsil6o=pAvr6B1garhlwc6MKNQ93ZfFky" b"tXdF9r,s=4dcxugMJq2P4hQaDbGXZR8uR3ei" b"PHrSmh4uhkg==,i=15000", } request.ok( "ismaster", True, saslSupportedMechs=["SCRAM-SHA-256"], speculativeAuthenticate=auth, minWireVersion=2, maxWireVersion=6, ) # Authentication should immediately fail with: # OperationFailure: Server returned an invalid nonce. with self.assertRaises(OperationFailure): future() return def test_handshake_load_balanced(self): self.hello_with_option_helper(OpMsg, loadBalanced=True) with self.assertRaisesRegex(AssertionError, "does not match"): self.hello_with_option_helper(Command, loadBalanced=True) def test_handshake_versioned_api(self): self.hello_with_option_helper(OpMsg, apiVersion="1") with self.assertRaisesRegex(AssertionError, "does not match"): self.hello_with_option_helper(Command, apiVersion="1") def test_handshake_not_either(self): # If we don't specify either option then it should be using # OP_QUERY for the initial step of the handshake. self.hello_with_option_helper(Command) with self.assertRaisesRegex(AssertionError, "does not match"): self.hello_with_option_helper(OpMsg) def test_handshake_max_wire(self): server = MockupDB() primary_response = {"hello": 1, "ok": 1, "minWireVersion": 0, "maxWireVersion": 6} self.found_auth_msg = False def responder(request): if request.matches(OpMsg, saslStart=1): self.found_auth_msg = True # Immediately closes the connection with # OperationFailure: Server returned an invalid nonce. request.reply( OpMsgReply( **primary_response, payload=b"r=wPleNM8S5p8gMaffMDF7Py4ru9bnmmoqb0" b"1WNPsil6o=pAvr6B1garhlwc6MKNQ93ZfFky" b"tXdF9r," b"s=4dcxugMJq2P4hQaDbGXZR8uR3ei" b"PHrSmh4uhkg==,i=15000", saslSupportedMechs=["SCRAM-SHA-1"], ) ) return None else: return request.reply(**primary_response) server.autoresponds(responder) self.addCleanup(server.stop) server.run() client = MongoClient( server.uri, username="username", password="password", ) self.addCleanup(client.close) self.assertRaises(OperationFailure, client.db.collection.find_one, {"a": 1}) self.assertTrue( self.found_auth_msg, "Could not find authentication command with correct protocol" ) if __name__ == "__main__": unittest.main() mongodb-mongo-python-driver-509e9b7/test/mockupdb/test_initial_ismaster.py000066400000000000000000000027461462766011000272020ustar00rootroot00000000000000# Copyright 2015 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. from __future__ import annotations import time import unittest from mockupdb import MockupDB, wait_until from pymongo import MongoClient class TestInitialIsMaster(unittest.TestCase): def test_initial_ismaster(self): server = MockupDB() server.run() self.addCleanup(server.stop) start = time.time() client = MongoClient(server.uri) self.addCleanup(client.close) # A single ismaster is enough for the client to be connected. self.assertFalse(client.nodes) server.receives("ismaster").ok(ismaster=True, minWireVersion=2, maxWireVersion=6) wait_until(lambda: client.nodes, "update nodes", timeout=1) # At least 10 seconds before next heartbeat. server.receives("ismaster").ok(ismaster=True, minWireVersion=2, maxWireVersion=6) self.assertGreaterEqual(time.time() - start, 10) if __name__ == "__main__": unittest.main() mongodb-mongo-python-driver-509e9b7/test/mockupdb/test_list_indexes.py000066400000000000000000000033101462766011000263200ustar00rootroot00000000000000# Copyright 2015 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. """Test list_indexes with more than one batch.""" from __future__ import annotations import unittest from mockupdb import MockupDB, going from bson import SON from pymongo import MongoClient class TestListIndexes(unittest.TestCase): def test_list_indexes_command(self): server = MockupDB(auto_ismaster={"maxWireVersion": 6}) server.run() self.addCleanup(server.stop) client = MongoClient(server.uri) self.addCleanup(client.close) with going(client.test.collection.list_indexes) as cursor: request = server.receives(listIndexes="collection", namespace="test") request.reply({"cursor": {"firstBatch": [{"name": "index_0"}], "id": 123}}) with going(list, cursor()) as indexes: request = server.receives(getMore=123, namespace="test", collection="collection") request.reply({"cursor": {"nextBatch": [{"name": "index_1"}], "id": 0}}) self.assertEqual([{"name": "index_0"}, {"name": "index_1"}], indexes()) for index_info in indexes(): self.assertIsInstance(index_info, SON) if __name__ == "__main__": unittest.main() mongodb-mongo-python-driver-509e9b7/test/mockupdb/test_max_staleness.py000066400000000000000000000043341462766011000265030ustar00rootroot00000000000000# Copyright 2016 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. from __future__ import annotations import unittest from mockupdb import MockupDB, going from pymongo import MongoClient class TestMaxStalenessMongos(unittest.TestCase): def test_mongos(self): mongos = MockupDB() mongos.autoresponds("ismaster", maxWireVersion=6, ismaster=True, msg="isdbgrid") mongos.run() self.addCleanup(mongos.stop) # No maxStalenessSeconds. uri = "mongodb://localhost:%d/?readPreference=secondary" % mongos.port client = MongoClient(uri) self.addCleanup(client.close) with going(client.db.coll.find_one) as future: request = mongos.receives() self.assertNotIn("maxStalenessSeconds", request.doc["$readPreference"]) self.assertTrue(request.slave_okay) request.ok(cursor={"firstBatch": [], "id": 0}) # find_one succeeds with no result. self.assertIsNone(future()) # Set maxStalenessSeconds to 1. Client has no minimum with mongos, # we let mongos enforce the 90-second minimum and return an error: # SERVER-27146. uri = ( "mongodb://localhost:%d/?readPreference=secondary" "&maxStalenessSeconds=1" % mongos.port ) client = MongoClient(uri) self.addCleanup(client.close) with going(client.db.coll.find_one) as future: request = mongos.receives() self.assertEqual(1, request.doc["$readPreference"]["maxStalenessSeconds"]) self.assertTrue(request.slave_okay) request.ok(cursor={"firstBatch": [], "id": 0}) self.assertIsNone(future()) if __name__ == "__main__": unittest.main() mongodb-mongo-python-driver-509e9b7/test/mockupdb/test_mixed_version_sharded.py000066400000000000000000000056141462766011000302040ustar00rootroot00000000000000# Copyright 2015 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. """Test PyMongo with a mixed-version cluster.""" from __future__ import annotations import time import unittest from queue import Queue from mockupdb import MockupDB, go from operations import upgrades # type: ignore[import] from pymongo import MongoClient class TestMixedVersionSharded(unittest.TestCase): def setup_server(self, upgrade): self.mongos_old, self.mongos_new = MockupDB(), MockupDB() # Collect queries to either server in one queue. self.q: Queue = Queue() for server in self.mongos_old, self.mongos_new: server.subscribe(self.q.put) server.autoresponds("getlasterror") server.run() self.addCleanup(server.stop) # Max wire version is too old for the upgraded operation. self.mongos_old.autoresponds( "ismaster", ismaster=True, msg="isdbgrid", maxWireVersion=upgrade.wire_version - 1 ) # Up-to-date max wire version. self.mongos_new.autoresponds( "ismaster", ismaster=True, msg="isdbgrid", maxWireVersion=upgrade.wire_version ) self.mongoses_uri = "mongodb://{},{}".format( self.mongos_old.address_string, self.mongos_new.address_string, ) self.client = MongoClient(self.mongoses_uri) def tearDown(self): if hasattr(self, "client") and self.client: self.client.close() def create_mixed_version_sharded_test(upgrade): def test(self): self.setup_server(upgrade) start = time.time() servers_used: set = set() while len(servers_used) < 2: go(upgrade.function, self.client) request = self.q.get(timeout=1) servers_used.add(request.server) request.assert_matches( upgrade.old if request.server is self.mongos_old else upgrade.new ) if time.time() > start + 10: self.fail("never used both mongoses") return test def generate_mixed_version_sharded_tests(): for upgrade in upgrades: test = create_mixed_version_sharded_test(upgrade) test_name = "test_%s" % upgrade.name.replace(" ", "_") test.__name__ = test_name setattr(TestMixedVersionSharded, test_name, test) generate_mixed_version_sharded_tests() if __name__ == "__main__": unittest.main() mongodb-mongo-python-driver-509e9b7/test/mockupdb/test_mongos_command_read_mode.py000066400000000000000000000102201462766011000306230ustar00rootroot00000000000000# Copyright 2015 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. from __future__ import annotations import itertools import unittest from mockupdb import MockupDB, OpMsg, going from operations import operations # type: ignore[import] from pymongo import MongoClient, ReadPreference from pymongo.read_preferences import ( _MONGOS_MODES, make_read_preference, read_pref_mode_from_name, ) class TestMongosCommandReadMode(unittest.TestCase): def test_aggregate(self): server = MockupDB() server.autoresponds( "ismaster", ismaster=True, msg="isdbgrid", minWireVersion=2, maxWireVersion=6 ) self.addCleanup(server.stop) server.run() client = MongoClient(server.uri) self.addCleanup(client.close) collection = client.test.collection with going(collection.aggregate, []): command = server.receives(aggregate="collection", pipeline=[]) self.assertFalse(command.slave_ok, "SlaveOkay set") command.ok(result=[{}]) secondary_collection = collection.with_options(read_preference=ReadPreference.SECONDARY) with going(secondary_collection.aggregate, []): command = server.receives( OpMsg( { "aggregate": "collection", "pipeline": [], "$readPreference": {"mode": "secondary"}, } ) ) command.ok(result=[{}]) self.assertTrue(command.slave_ok, "SlaveOkay not set") def create_mongos_read_mode_test(mode, operation): def test(self): server = MockupDB() self.addCleanup(server.stop) server.run() server.autoresponds( "ismaster", ismaster=True, msg="isdbgrid", minWireVersion=2, maxWireVersion=6 ) pref = make_read_preference(read_pref_mode_from_name(mode), tag_sets=None) client = MongoClient(server.uri, read_preference=pref) self.addCleanup(client.close) with going(operation.function, client): request = server.receive() request.reply(operation.reply) if operation.op_type == "always-use-secondary": self.assertEqual(ReadPreference.SECONDARY.document, request.doc.get("$readPreference")) slave_ok = mode != "primary" elif operation.op_type == "must-use-primary": slave_ok = False elif operation.op_type == "may-use-secondary": slave_ok = mode != "primary" actual_pref = request.doc.get("$readPreference") if mode == "primary": self.assertIsNone(actual_pref) else: self.assertEqual(pref.document, actual_pref) else: self.fail("unrecognized op_type %r" % operation.op_type) if slave_ok: self.assertTrue(request.slave_ok, "SlaveOkay not set") else: self.assertFalse(request.slave_ok, "SlaveOkay set") return test def generate_mongos_read_mode_tests(): matrix = itertools.product(_MONGOS_MODES, operations) for entry in matrix: mode, operation = entry if mode == "primary" and operation.op_type == "always-use-secondary": # Skip something like command('foo', read_preference=SECONDARY). continue test = create_mongos_read_mode_test(mode, operation) test_name = "test_{}_with_mode_{}".format(operation.name.replace(" ", "_"), mode) test.__name__ = test_name setattr(TestMongosCommandReadMode, test_name, test) generate_mongos_read_mode_tests() if __name__ == "__main__": unittest.main() mongodb-mongo-python-driver-509e9b7/test/mockupdb/test_network_disconnect_primary.py000066400000000000000000000062311462766011000313000ustar00rootroot00000000000000# Copyright 2015 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. from __future__ import annotations import unittest from mockupdb import Future, MockupDB, OpReply, going, wait_until from pymongo import MongoClient from pymongo.errors import ConnectionFailure from pymongo.topology_description import TOPOLOGY_TYPE class TestNetworkDisconnectPrimary(unittest.TestCase): def test_network_disconnect_primary(self): # Application operation fails against primary. Test that topology # type changes from ReplicaSetWithPrimary to ReplicaSetNoPrimary. # http://bit.ly/1B5ttuL primary, secondary = MockupDB(), MockupDB() for server in primary, secondary: server.run() self.addCleanup(server.stop) hosts = [server.address_string for server in (primary, secondary)] primary_response = OpReply( ismaster=True, setName="rs", hosts=hosts, minWireVersion=2, maxWireVersion=6 ) primary.autoresponds("ismaster", primary_response) secondary.autoresponds( "ismaster", ismaster=False, secondary=True, setName="rs", hosts=hosts, minWireVersion=2, maxWireVersion=6, ) client = MongoClient(primary.uri, replicaSet="rs") self.addCleanup(client.close) wait_until(lambda: client.primary == primary.address, "discover primary") topology = client._topology self.assertEqual(TOPOLOGY_TYPE.ReplicaSetWithPrimary, topology.description.topology_type) # Open a socket in the application pool (calls ismaster). with going(client.db.command, "buildinfo"): primary.receives("buildinfo").ok() # The primary hangs replying to ismaster. ismaster_future = Future() primary.autoresponds("ismaster", lambda r: r.ok(ismaster_future.result())) # Network error on application operation. with self.assertRaises(ConnectionFailure): with going(client.db.command, "buildinfo"): primary.receives("buildinfo").hangup() # Topology type is updated. self.assertEqual(TOPOLOGY_TYPE.ReplicaSetNoPrimary, topology.description.topology_type) # Let ismasters through again. ismaster_future.set_result(primary_response) # Demand a primary. with going(client.db.command, "buildinfo"): wait_until(lambda: client.primary == primary.address, "rediscover primary") primary.receives("buildinfo").ok() self.assertEqual(TOPOLOGY_TYPE.ReplicaSetWithPrimary, topology.description.topology_type) if __name__ == "__main__": unittest.main() mongodb-mongo-python-driver-509e9b7/test/mockupdb/test_op_msg.py000066400000000000000000000245451462766011000251270ustar00rootroot00000000000000# Copyright 2018-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. from __future__ import annotations import unittest from collections import namedtuple from mockupdb import OP_MSG_FLAGS, MockupDB, OpMsg, OpMsgReply, going from pymongo import MongoClient, WriteConcern from pymongo.cursor import CursorType from pymongo.operations import DeleteOne, InsertOne, UpdateOne 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 ), 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} ), 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}} ), 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}} ), 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), ], ), ] class TestOpMsg(unittest.TestCase): server: MockupDB client: MongoClient @classmethod def setUpClass(cls): cls.server = MockupDB(auto_ismaster=True, max_wire_version=8) cls.server.run() cls.client = MongoClient(cls.server.uri) @classmethod def tearDownClass(cls): cls.server.stop() cls.client.close() def _test_operation(self, op): coll = self.client.db.coll with going(op.function, coll) as future: expected_requests = op.request replies = op.reply if not isinstance(op.request, list): expected_requests = [op.request] replies = [op.reply] for expected_request in expected_requests: request = self.server.receives(expected_request) reply = None if replies: reply = replies.pop(0) if reply is not None: request.reply(reply) for reply in replies: if reply is not None: request.reply(reply) future() # No error. def operation_test(op): def test(self): self._test_operation(op) return test def create_tests(ops): for op in ops: test_name = f"test_op_msg_{op.name}" setattr(TestOpMsg, test_name, operation_test(op)) create_tests(operations) create_tests(operations_312) if __name__ == "__main__": unittest.main() mongodb-mongo-python-driver-509e9b7/test/mockupdb/test_op_msg_read_preference.py000066400000000000000000000141061462766011000303100ustar00rootroot00000000000000# Copyright 2018-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. from __future__ import annotations import copy import itertools import unittest from typing import Any from mockupdb import CommandBase, MockupDB, going from operations import operations # type: ignore[import] from pymongo import MongoClient, ReadPreference from pymongo.read_preferences import ( _MONGOS_MODES, make_read_preference, read_pref_mode_from_name, ) class OpMsgReadPrefBase(unittest.TestCase): single_mongod = False primary: MockupDB secondary: MockupDB @classmethod def setUpClass(cls): super().setUpClass() @classmethod def add_test(cls, mode, test_name, test): setattr(cls, test_name, test) def setup_client(self, read_preference): client = MongoClient(self.primary.uri, read_preference=read_preference) self.addCleanup(client.close) return client class TestOpMsgMongos(OpMsgReadPrefBase): @classmethod def setUpClass(cls): super().setUpClass() auto_ismaster = { "ismaster": True, "msg": "isdbgrid", # Mongos. "minWireVersion": 2, "maxWireVersion": 6, } cls.primary = MockupDB(auto_ismaster=auto_ismaster) cls.primary.run() cls.secondary = cls.primary @classmethod def tearDownClass(cls): cls.primary.stop() super().tearDownClass() class TestOpMsgReplicaSet(OpMsgReadPrefBase): @classmethod def setUpClass(cls): super().setUpClass() cls.primary, cls.secondary = MockupDB(), MockupDB() for server in cls.primary, cls.secondary: server.run() hosts = [server.address_string for server in (cls.primary, cls.secondary)] primary_ismaster = { "ismaster": True, "setName": "rs", "hosts": hosts, "minWireVersion": 2, "maxWireVersion": 6, } cls.primary.autoresponds(CommandBase("ismaster"), primary_ismaster) secondary_ismaster = copy.copy(primary_ismaster) secondary_ismaster["ismaster"] = False secondary_ismaster["secondary"] = True cls.secondary.autoresponds(CommandBase("ismaster"), secondary_ismaster) @classmethod def tearDownClass(cls): for server in cls.primary, cls.secondary: server.stop() super().tearDownClass() @classmethod def add_test(cls, mode, test_name, test): # Skip nearest tests since we don't know if we will select the primary # or secondary. if mode != "nearest": setattr(cls, test_name, test) def setup_client(self, read_preference): client = MongoClient(self.primary.uri, replicaSet="rs", read_preference=read_preference) # Run a command on a secondary to discover the topology. This ensures # that secondaryPreferred commands will select the secondary. client.admin.command("ismaster", read_preference=ReadPreference.SECONDARY) self.addCleanup(client.close) return client class TestOpMsgSingle(OpMsgReadPrefBase): single_mongod = True @classmethod def setUpClass(cls): super().setUpClass() auto_ismaster = { "ismaster": True, "minWireVersion": 2, "maxWireVersion": 6, } cls.primary = MockupDB(auto_ismaster=auto_ismaster) cls.primary.run() cls.secondary = cls.primary @classmethod def tearDownClass(cls): cls.primary.stop() super().tearDownClass() def create_op_msg_read_mode_test(mode, operation): def test(self): pref = make_read_preference(read_pref_mode_from_name(mode), tag_sets=None) client = self.setup_client(read_preference=pref) expected_pref: Any if operation.op_type == "always-use-secondary": expected_server = self.secondary expected_pref = ReadPreference.SECONDARY elif operation.op_type == "must-use-primary": expected_server = self.primary expected_pref = None elif operation.op_type == "may-use-secondary": if mode == "primary": expected_server = self.primary expected_pref = None elif mode == "primaryPreferred": expected_server = self.primary expected_pref = pref else: expected_server = self.secondary expected_pref = pref else: self.fail("unrecognized op_type %r" % operation.op_type) # For single mongod we omit the read preference. if self.single_mongod: expected_pref = None with going(operation.function, client): request = expected_server.receive() request.reply(operation.reply) actual_pref = request.doc.get("$readPreference") if expected_pref: self.assertEqual(expected_pref.document, actual_pref) else: self.assertIsNone(actual_pref) self.assertNotIn("$query", request.doc) return test def generate_op_msg_read_mode_tests(): matrix = itertools.product(_MONGOS_MODES, operations) for entry in matrix: mode, operation = entry test = create_op_msg_read_mode_test(mode, operation) test_name = "test_{}_with_mode_{}".format(operation.name.replace(" ", "_"), mode) test.__name__ = test_name for cls in TestOpMsgMongos, TestOpMsgReplicaSet, TestOpMsgSingle: cls.add_test(mode, test_name, test) generate_op_msg_read_mode_tests() if __name__ == "__main__": unittest.main() mongodb-mongo-python-driver-509e9b7/test/mockupdb/test_query_read_pref_sharded.py000066400000000000000000000045641462766011000305100ustar00rootroot00000000000000# Copyright 2015 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. """Test PyMongo query and read preference with a sharded cluster.""" from __future__ import annotations import unittest from mockupdb import MockupDB, OpMsg, going from bson import SON from pymongo import MongoClient from pymongo.read_preferences import ( Nearest, Primary, PrimaryPreferred, Secondary, SecondaryPreferred, ) class TestQueryAndReadModeSharded(unittest.TestCase): def test_query_and_read_mode_sharded_op_msg(self): """Test OP_MSG sends non-primary $readPreference and never $query.""" server = MockupDB() server.autoresponds( "ismaster", ismaster=True, msg="isdbgrid", minWireVersion=2, maxWireVersion=6 ) server.run() self.addCleanup(server.stop) client = MongoClient(server.uri) self.addCleanup(client.close) read_prefs = ( Primary(), SecondaryPreferred(), PrimaryPreferred(), Secondary(), Nearest(), SecondaryPreferred([{"tag": "value"}]), ) for query in ( {"a": 1}, {"$query": {"a": 1}}, ): for pref in read_prefs: collection = client.db.get_collection("test", read_preference=pref) cursor = collection.find(query.copy()) with going(next, cursor): request = server.receives() # Command is not nested in $query. expected_cmd = SON([("find", "test"), ("filter", {"a": 1})]) if pref.mode: expected_cmd["$readPreference"] = pref.document request.assert_matches(OpMsg(expected_cmd)) request.replies({"cursor": {"id": 0, "firstBatch": [{}]}}) if __name__ == "__main__": unittest.main() mongodb-mongo-python-driver-509e9b7/test/mockupdb/test_reset_and_request_check.py000066400000000000000000000125361462766011000305110ustar00rootroot00000000000000# Copyright 2015 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. from __future__ import annotations import itertools import time import unittest from mockupdb import MockupDB, going, wait_until from operations import operations # type: ignore[import] from pymongo import MongoClient from pymongo.errors import ConnectionFailure from pymongo.operations import _Op from pymongo.server_type import SERVER_TYPE class TestResetAndRequestCheck(unittest.TestCase): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.ismaster_time = 0.0 self.client = None self.server = None def setup_server(self): self.server = MockupDB() def responder(request): self.ismaster_time = time.time() return request.ok(ismaster=True, minWireVersion=2, maxWireVersion=6) self.server.autoresponds("ismaster", responder) self.server.run() self.addCleanup(self.server.stop) kwargs = {"socketTimeoutMS": 100} # Disable retryable reads when pymongo supports it. kwargs["retryReads"] = False self.client = MongoClient(self.server.uri, **kwargs) # type: ignore wait_until(lambda: self.client.nodes, "connect to standalone") def tearDown(self): if hasattr(self, "client") and self.client: self.client.close() def _test_disconnect(self, operation): # Application operation fails. Test that client resets server # description and does *not* schedule immediate check. self.setup_server() assert self.server is not None assert self.client is not None # Network error on application operation. with self.assertRaises(ConnectionFailure): with going(operation.function, self.client): self.server.receives().hangup() # Server is Unknown. topology = self.client._topology with self.assertRaises(ConnectionFailure): topology.select_server_by_address(self.server.address, _Op.TEST, 0) time.sleep(0.5) after = time.time() # Demand a reconnect. with going(self.client.db.command, "buildinfo"): self.server.receives("buildinfo").ok() last = self.ismaster_time self.assertGreaterEqual(last, after, "called ismaster before needed") def _test_timeout(self, operation): # Application operation times out. Test that client does *not* reset # server description and does *not* schedule immediate check. self.setup_server() assert self.server is not None assert self.client is not None with self.assertRaises(ConnectionFailure): with going(operation.function, self.client): self.server.receives() before = self.ismaster_time time.sleep(0.5) # Server is *not* Unknown. topology = self.client._topology server = topology.select_server_by_address(self.server.address, _Op.TEST, 0) assert server is not None self.assertEqual(SERVER_TYPE.Standalone, server.description.server_type) after = self.ismaster_time self.assertEqual(after, before, "unneeded ismaster call") def _test_not_master(self, operation): # Application operation gets a "not master" error. self.setup_server() assert self.server is not None assert self.client is not None with self.assertRaises(ConnectionFailure): with going(operation.function, self.client): request = self.server.receives() before = self.ismaster_time request.replies(operation.not_master) time.sleep(1) # Server is rediscovered. topology = self.client._topology server = topology.select_server_by_address(self.server.address, _Op.TEST, 0) assert server is not None self.assertEqual(SERVER_TYPE.Standalone, server.description.server_type) after = self.ismaster_time self.assertGreater(after, before, "ismaster not called") def create_reset_test(operation, test_method): def test(self): test_method(self, operation) return test def generate_reset_tests(): test_methods = [ (TestResetAndRequestCheck._test_disconnect, "test_disconnect"), (TestResetAndRequestCheck._test_timeout, "test_timeout"), (TestResetAndRequestCheck._test_not_master, "test_not_master"), ] matrix = itertools.product(operations, test_methods) for entry in matrix: operation, (test_method, name) = entry test = create_reset_test(operation, test_method) test_name = "{}_{}".format(name, operation.name.replace(" ", "_")) test.__name__ = test_name setattr(TestResetAndRequestCheck, test_name, test) generate_reset_tests() if __name__ == "__main__": unittest.main() mongodb-mongo-python-driver-509e9b7/test/mockupdb/test_rsghost.py000066400000000000000000000041511462766011000253230ustar00rootroot00000000000000# Copyright 2021-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. """Test connections to RSGhost nodes.""" from __future__ import annotations import datetime import unittest from mockupdb import MockupDB, going from pymongo import MongoClient from pymongo.errors import ServerSelectionTimeoutError class TestRSGhost(unittest.TestCase): def test_rsghost(self): rsother_response = { "ok": 1.0, "ismaster": False, "secondary": False, "info": "Does not have a valid replica set config", "isreplicaset": True, "maxBsonObjectSize": 16777216, "maxMessageSizeBytes": 48000000, "maxWriteBatchSize": 100000, "localTime": datetime.datetime(2021, 11, 30, 0, 53, 4, 99000), "logicalSessionTimeoutMinutes": 30, "connectionId": 3, "minWireVersion": 0, "maxWireVersion": 15, "readOnly": False, } server = MockupDB(auto_ismaster=rsother_response) server.run() self.addCleanup(server.stop) # Default auto discovery yields a server selection timeout. with MongoClient(server.uri, serverSelectionTimeoutMS=250) as client: with self.assertRaises(ServerSelectionTimeoutError): client.test.command("ping") # Direct connection succeeds. with MongoClient(server.uri, directConnection=True) as client: with going(client.test.command, "ping"): request = server.receives(ping=1) request.reply() if __name__ == "__main__": unittest.main() mongodb-mongo-python-driver-509e9b7/test/mockupdb/test_slave_okay_rs.py000066400000000000000000000051341462766011000264750ustar00rootroot00000000000000# Copyright 2015 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. """Test PyMongo's SlaveOkay with a replica set connection. Just make sure SlaveOkay is *not* set on primary reads. """ from __future__ import annotations import unittest from mockupdb import MockupDB, going from operations import operations # type: ignore[import] from pymongo import MongoClient class TestSlaveOkayRS(unittest.TestCase): def setup_server(self): self.primary, self.secondary = MockupDB(), MockupDB() for server in self.primary, self.secondary: server.run() self.addCleanup(server.stop) hosts = [server.address_string for server in (self.primary, self.secondary)] self.primary.autoresponds( "ismaster", ismaster=True, setName="rs", hosts=hosts, minWireVersion=2, maxWireVersion=6 ) self.secondary.autoresponds( "ismaster", ismaster=False, secondary=True, setName="rs", hosts=hosts, minWireVersion=2, maxWireVersion=6, ) def create_slave_ok_rs_test(operation): def test(self): self.setup_server() assert operation.op_type != "always-use-secondary" client = MongoClient(self.primary.uri, replicaSet="rs") self.addCleanup(client.close) with going(operation.function, client): request = self.primary.receive() request.reply(operation.reply) self.assertFalse(request.slave_ok, 'SlaveOkay set read mode "primary"') return test def generate_slave_ok_rs_tests(): for operation in operations: # Don't test secondary operations with MockupDB, the server enforces the # SlaveOkay bit so integration tests prove we set it. if operation.op_type == "always-use-secondary": continue test = create_slave_ok_rs_test(operation) test_name = "test_%s" % operation.name.replace(" ", "_") test.__name__ = test_name setattr(TestSlaveOkayRS, test_name, test) generate_slave_ok_rs_tests() if __name__ == "__main__": unittest.main() mongodb-mongo-python-driver-509e9b7/test/mockupdb/test_slave_okay_sharded.py000066400000000000000000000061101462766011000274560ustar00rootroot00000000000000# Copyright 2015 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. """Test PyMongo's SlaveOkay with: - A direct connection to a standalone. - A direct connection to a slave. - A direct connection to a mongos. """ from __future__ import annotations import itertools import unittest from queue import Queue from mockupdb import MockupDB, going from operations import operations # type: ignore[import] from pymongo import MongoClient from pymongo.read_preferences import make_read_preference, read_pref_mode_from_name class TestSlaveOkaySharded(unittest.TestCase): def setup_server(self): self.mongos1, self.mongos2 = MockupDB(), MockupDB() # Collect queries to either server in one queue. self.q: Queue = Queue() for server in self.mongos1, self.mongos2: server.subscribe(self.q.put) server.run() self.addCleanup(server.stop) server.autoresponds( "ismaster", minWireVersion=2, maxWireVersion=6, ismaster=True, msg="isdbgrid" ) self.mongoses_uri = f"mongodb://{self.mongos1.address_string},{self.mongos2.address_string}" def create_slave_ok_sharded_test(mode, operation): def test(self): self.setup_server() if operation.op_type == "always-use-secondary": slave_ok = True elif operation.op_type == "may-use-secondary": slave_ok = mode != "primary" elif operation.op_type == "must-use-primary": slave_ok = False else: raise AssertionError("unrecognized op_type %r" % operation.op_type) pref = make_read_preference(read_pref_mode_from_name(mode), tag_sets=None) client = MongoClient(self.mongoses_uri, read_preference=pref) self.addCleanup(client.close) with going(operation.function, client): request = self.q.get(timeout=1) request.reply(operation.reply) if slave_ok: self.assertTrue(request.slave_ok, "SlaveOkay not set") else: self.assertFalse(request.slave_ok, "SlaveOkay set") return test def generate_slave_ok_sharded_tests(): modes = "primary", "secondary", "nearest" matrix = itertools.product(modes, operations) for entry in matrix: mode, operation = entry test = create_slave_ok_sharded_test(mode, operation) test_name = "test_{}_with_mode_{}".format(operation.name.replace(" ", "_"), mode) test.__name__ = test_name setattr(TestSlaveOkaySharded, test_name, test) generate_slave_ok_sharded_tests() if __name__ == "__main__": unittest.main() mongodb-mongo-python-driver-509e9b7/test/mockupdb/test_slave_okay_single.py000066400000000000000000000057531462766011000273410ustar00rootroot00000000000000# Copyright 2015 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. """Test PyMongo's SlaveOkay with: - A direct connection to a standalone. - A direct connection to a slave. - A direct connection to a mongos. """ from __future__ import annotations import itertools import unittest from mockupdb import MockupDB, going 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 def topology_type_name(client): topology_type = client._topology._description.topology_type return TOPOLOGY_TYPE._fields[topology_type] class TestSlaveOkaySingle(unittest.TestCase): def setUp(self): self.server = MockupDB() self.server.run() self.addCleanup(self.server.stop) def create_slave_ok_single_test(mode, server_type, ismaster, operation): def test(self): ismaster_with_version = ismaster.copy() ismaster_with_version["minWireVersion"] = 2 ismaster_with_version["maxWireVersion"] = 6 self.server.autoresponds("ismaster", **ismaster_with_version) self.assertIn( operation.op_type, ("always-use-secondary", "may-use-secondary", "must-use-primary") ) pref = make_read_preference(read_pref_mode_from_name(mode), tag_sets=None) client = MongoClient(self.server.uri, read_preference=pref) self.addCleanup(client.close) with going(operation.function, client): request = self.server.receive() request.reply(operation.reply) self.assertIn(topology_type_name(client), ["Sharded", "Single"]) return test def generate_slave_ok_single_tests(): modes = "primary", "secondary", "nearest" server_types = [ ("standalone", {"ismaster": True}), ("slave", {"ismaster": False}), ("mongos", {"ismaster": True, "msg": "isdbgrid"}), ] matrix = itertools.product(modes, server_types, operations) for entry in matrix: mode, (server_type, ismaster), operation = entry test = create_slave_ok_single_test(mode, server_type, ismaster, operation) test_name = "test_{}_{}_with_mode_{}".format( operation.name.replace(" ", "_"), server_type, mode, ) test.__name__ = test_name setattr(TestSlaveOkaySingle, test_name, test) generate_slave_ok_single_tests() if __name__ == "__main__": unittest.main() mongodb-mongo-python-driver-509e9b7/test/mockupdb/test_standalone_shard.py000066400000000000000000000037051462766011000271470ustar00rootroot00000000000000# Copyright 2024-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. """Test errors that come from a standalone shard.""" from __future__ import annotations import unittest from mockupdb import MockupDB, going from pymongo import MongoClient from pymongo.errors import OperationFailure class TestStandaloneShard(unittest.TestCase): # See PYTHON-2048 and SERVER-44591. def test_bulk_txn_error_message(self): server = MockupDB(auto_ismaster={"maxWireVersion": 8}) server.run() self.addCleanup(server.stop) client = MongoClient(server.uri) self.addCleanup(client.close) with self.assertRaisesRegex( OperationFailure, "This MongoDB deployment does not support retryable writes" ): with going(client.db.collection.insert_many, [{}, {}]): request = server.receives() request.reply( { "n": 0, "ok": 1.0, "writeErrors": [ { "code": 20, "codeName": "IllegalOperation", "errmsg": "Transaction numbers are only allowed on a replica set member or mongos", "index": 0, } ], } ) if __name__ == "__main__": unittest.main() mongodb-mongo-python-driver-509e9b7/test/mod_wsgi_test/000077500000000000000000000000001462766011000232635ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/mod_wsgi_test/README.rst000066400000000000000000000077721462766011000247670ustar00rootroot00000000000000Testing PyMongo with mod_wsgi ============================= These tests verify that PyMongo works with Apache and mod_wsgi. They are primarily intended to prevent regression of `PYTHON-353 `_, a connection leak when PyMongo 2.2 was used with Python 2.6 and mod_wsgi 2.8. However, the test may also catch concurrency bugs, or incompatibilities between PyMongo's C extensions and the way mod_wsgi manages Python sub interpreters. It is generally useful to test PyMongo in the unconventional environment that mod_wsgi creates. Test Matrix ----------- PyMongo should be tested with several versions of mod_wsgi and a selection of Python versions. Each combination of mod_wsgi and Python version should be tested with a standalone and a replica set. ``mod_wsgi_test.py`` detects if the deployment is a replica set and connects to the whole set. Setup ----- Compile Python .............. We need a Python interpreter built as a shared library. Download the source tarball for each Python version tested, untar it, and run:: ./configure --prefix=/some/directory --enable-shared LDFLAGS="-Wl,--rpath=/some/directory/lib" make make install This results in an executable named "python" or "python3" and a shared library named something like "libpython2.7.so.1.0" or "libpython3.3m.so.1.0". Compile mod_wsgi ................ Compile mod_wsgi for each combination for Python and mod_wsgi version in the test matrix. For example, to compile mod_wsgi 3.4 for Python 2.7 on a RedHat-like Linux:: sudo yum install -y httpd httpd-devel wget https://modwsgi.googlecode.com/files/mod_wsgi-3.4.tar.gz tar xzf mod_wsgi-3.4.tar.gz cd mod_wsgi-3.4 ./configure --with-python=/some/directory/bin/python LDFLAGS="-Wl,--rpath=/some/directory/lib" make make install To ease testing of several matrix combinations, copy the resulting ``mod_wsgi.so`` to a safe place. Start mongod ............ Start a standalone listening on port 27017, or a replica set with a member listening on port 27017. Configure Apache ................ Set a MOD_WSGI_SO environment variable so our ``mod_wsgi_test.conf`` can find and load mod_wsgi.so:: export MOD_WSGI_SO=/path/to/mod_wsgi.so Start Apache with one of the config files in this directory. Run the test ------------ Run the included ``test_client.py`` script:: python test/mod_wsgi_test/test_client.py -n 2500 -t 100 parallel \ http://localhost/interpreter1${WORKSPACE} http://localhost/interpreter2${WORKSPACE} ...where the "n" argument is the total number of requests to make to Apache, and "t" specifies the number of threads. ``WORKSPACE`` is the location of the PyMongo checkout. Note that multiple URLs are passed, each one corresponds to a different sub interpreter. Run this script again with different arguments to make serial requests:: python test/mod_wsgi_test/test_client.py -n 25000 serial \ http://localhost/interpreter1${WORKSPACE} http://localhost/interpreter2${WORKSPACE} The ``test_client.py`` script merely makes HTTP requests to Apache. Its exit code is non-zero if any of its requests fails, for example with an HTTP 500. The core of the test is in the WSGI script, ``mod_wsgi_test.py``. This script inserts some documents into MongoDB at startup, then queries documents for each HTTP request. If PyMongo is leaking connections and "n" is much greater than the ulimit, the test will fail when PyMongo exhausts its file descriptors. The script also encodes and decodes all BSON types to ensure that multiple sub interpreters in the same process are supported. This tests the workaround added in `PYTHON-569 `_. Automation ---------- At MongoDB, Inc. we use a continuous integration job that tests each combination in the matrix. The job starts up Apache, starts a single server or replica set, and runs ``test_client.py`` with the proper arguments. See `run-mod-wsgi-tests.sh `_ mongodb-mongo-python-driver-509e9b7/test/mod_wsgi_test/apache22amazon.conf000066400000000000000000000014171462766011000267300ustar00rootroot00000000000000# This is a minimal httpd.conf file written for Apache 2.2 on Amazon Linux # The modules directory is here by default. # ServerRoot "/etc/httpd" DocumentRoot ${PWD} PidFile ${PWD}/apache2.pid User nobody Group nobody # Bind to localhost only, don't require sudo. Listen 127.0.0.1:8080 # Required modules. LoadModule authz_host_module modules/mod_authz_host.so # Needed so we can set a custom log location. LoadModule log_config_module modules/mod_log_config.so ErrorLog ${PWD}/error_log CustomLog ${PWD}/access_log combined AllowOverride None Order Deny,Allow Deny from All AllowOverride None Order Allow,Deny Allow from All Include ${PROJECT_DIRECTORY}/test/mod_wsgi_test/${MOD_WSGI_CONF} mongodb-mongo-python-driver-509e9b7/test/mod_wsgi_test/apache22ubuntu1204.conf000066400000000000000000000012231462766011000272670ustar00rootroot00000000000000# This is a minimal httpd.conf file written for Apache 2.2 on Ubuntu 12.04 # The modules directory is here on Ubuntu. ServerRoot "/usr/lib/apache2" DocumentRoot ${PWD} PidFile ${PWD}/apache2.pid # Bind to localhost only, don't require sudo. Listen 127.0.0.1:8080 # Required modules. LoadModule authz_host_module modules/mod_authz_host.so ErrorLog ${PWD}/error_log CustomLog ${PWD}/access_log combined AllowOverride None Order Deny,Allow Deny from All AllowOverride None Order Allow,Deny Allow from All Include ${PROJECT_DIRECTORY}/test/mod_wsgi_test/${MOD_WSGI_CONF} mongodb-mongo-python-driver-509e9b7/test/mod_wsgi_test/apache24ubuntu161404.conf000066400000000000000000000012621462766011000274450ustar00rootroot00000000000000# This is a minimal httpd.conf file written for Apache 2.4 on Ubuntu 14.04/16.04 # The modules directory is here on Ubuntu. ServerRoot "/usr/lib/apache2" DocumentRoot ${PWD} PidFile ${PWD}/apache2.pid # Bind to localhost only, don't require sudo. Listen 127.0.0.1:8080 # Required modules. LoadModule mpm_prefork_module modules/mod_mpm_prefork.so LoadModule authz_core_module modules/mod_authz_core.so ErrorLog ${PWD}/error_log CustomLog ${PWD}/access_log combined AllowOverride None Require all denied AllowOverride None Require all granted Include ${PROJECT_DIRECTORY}/test/mod_wsgi_test/${MOD_WSGI_CONF} mongodb-mongo-python-driver-509e9b7/test/mod_wsgi_test/mod_wsgi_test.conf000066400000000000000000000025171462766011000270060ustar00rootroot00000000000000# Copyright 2012-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. # Minimal test of PyMongo in a WSGI application, see bug PYTHON-353 LoadModule wsgi_module ${MOD_WSGI_SO} # Avoid permissions issues WSGISocketPrefix /tmp/ ServerName localhost WSGIDaemonProcess mod_wsgi_test processes=1 threads=15 display-name=mod_wsgi_test WSGIProcessGroup mod_wsgi_test # Mount the script twice so that multiple interpreters are used. # For the convenience of unittests, rather than hard-code the location of # mod_wsgi_test.py, include it in the URL, so # http://localhost/interpreter1/location-of-pymongo-checkout will work: WSGIScriptAliasMatch ^/interpreter1/(.+) $1/test/mod_wsgi_test/mod_wsgi_test.py WSGIScriptAliasMatch ^/interpreter2/(.+) $1/test/mod_wsgi_test/mod_wsgi_test.py mongodb-mongo-python-driver-509e9b7/test/mod_wsgi_test/mod_wsgi_test.py000066400000000000000000000076261462766011000265170ustar00rootroot00000000000000# Copyright 2012-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. """Minimal test of PyMongo in a WSGI application, see bug PYTHON-353 """ from __future__ import annotations import datetime import os import re import sys import uuid this_path = os.path.dirname(os.path.join(os.getcwd(), __file__)) # Location of PyMongo checkout repository_path = os.path.normpath(os.path.join(this_path, "..", "..")) sys.path.insert(0, repository_path) import bson import pymongo from bson.binary import STANDARD, Binary from bson.code import Code from bson.codec_options import CodecOptions from bson.datetime_ms import DatetimeConversion, DatetimeMS from bson.dbref import DBRef from bson.objectid import ObjectId from bson.regex import Regex from pymongo.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] except: mod_wsgi_version = None 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")] mongodb-mongo-python-driver-509e9b7/test/mod_wsgi_test/mod_wsgi_test_embedded.conf000066400000000000000000000023241462766011000306130ustar00rootroot00000000000000# Copyright 2023-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. # Minimal test of PyMongo in an *Embedded mode* WSGI application. LoadModule wsgi_module ${MOD_WSGI_SO} # Avoid permissions issues WSGISocketPrefix /tmp/ ServerName localhost # Mount the script twice so that multiple interpreters are used. # For the convenience of unittests, rather than hard-code the location of # mod_wsgi_test.py, include it in the URL, so # http://localhost/interpreter1/location-of-pymongo-checkout will work: WSGIScriptAliasMatch ^/interpreter1/(.+) $1/test/mod_wsgi_test/mod_wsgi_test.py WSGIScriptAliasMatch ^/interpreter2/(.+) $1/test/mod_wsgi_test/mod_wsgi_test.py mongodb-mongo-python-driver-509e9b7/test/mod_wsgi_test/test_client.py000066400000000000000000000115031462766011000261520ustar00rootroot00000000000000# Copyright 2012-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. """Test client for mod_wsgi application, see bug PYTHON-353.""" from __future__ import annotations import _thread as thread import random import sys import threading import time from optparse import OptionParser from urllib.request import urlopen def parse_args(): parser = OptionParser( """usage: %prog [options] mode url [...] mode:\tparallel or serial""" ) # Should be enough that any connection leak will exhaust available file # descriptors. parser.add_option( "-n", "--nrequests", type="int", dest="nrequests", default=50 * 1000, help="Number of times to GET the URLs, in total", ) parser.add_option( "-t", "--nthreads", type="int", dest="nthreads", default=100, help="Number of threads with mode 'parallel'", ) parser.add_option( "-q", "--quiet", action="store_false", dest="verbose", default=True, help="Don't print status messages to stdout", ) parser.add_option( "-c", "--continue", action="store_true", dest="continue_", default=False, help="Continue after HTTP errors", ) try: options, args = parser.parse_args() mode, urls = args[0], args[1:] except (ValueError, IndexError): parser.print_usage() sys.exit(1) if mode not in ("parallel", "serial"): parser.print_usage() sys.exit(1) return options, mode, urls def get(urls): url = random.choice(urls) urlopen(url).read().strip() class URLGetterThread(threading.Thread): # Class variables. counter_lock = threading.Lock() counter = 0 def __init__(self, options, urls, nrequests_per_thread): super().__init__() self.options = options self.urls = urls self.nrequests_per_thread = nrequests_per_thread self.errors = 0 def run(self): for _i in range(self.nrequests_per_thread): try: get(urls) except Exception as e: print(e) if not options.continue_: thread.interrupt_main() thread.exit() self.errors += 1 with URLGetterThread.counter_lock: URLGetterThread.counter += 1 counter = URLGetterThread.counter should_print = options.verbose and not counter % 1000 if should_print: print(counter) def main(options, mode, urls): start_time = time.time() errors = 0 if mode == "parallel": nrequests_per_thread = options.nrequests // options.nthreads if options.verbose: print( "Getting {} {} times total in {} threads, " "{} times per thread".format( urls, nrequests_per_thread * options.nthreads, options.nthreads, nrequests_per_thread, ) ) threads = [ URLGetterThread(options, urls, nrequests_per_thread) for _ in range(options.nthreads) ] for t in threads: t.start() for t in threads: t.join() errors = sum([t.errors for t in threads]) nthreads_with_errors = len([t for t in threads if t.errors]) if nthreads_with_errors: print("%d threads had errors! %d errors in total" % (nthreads_with_errors, errors)) else: assert mode == "serial" if options.verbose: print(f"Getting {urls} {options.nrequests} times in one thread") for i in range(1, options.nrequests + 1): try: get(urls) except Exception as e: print(e) if not options.continue_: sys.exit(1) errors += 1 if options.verbose and not i % 1000: print(i) if errors: print("%d errors!" % errors) if options.verbose: print("Completed in %.2f seconds" % (time.time() - start_time)) if errors: # Failure sys.exit(1) if __name__ == "__main__": options, mode, urls = parse_args() main(options, mode, urls) mongodb-mongo-python-driver-509e9b7/test/mypy_fails/000077500000000000000000000000001462766011000225705ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/mypy_fails/insert_many_dict.py000066400000000000000000000003651462766011000265010ustar00rootroot00000000000000from __future__ import annotations from pymongo import MongoClient client: MongoClient = MongoClient() client.test.test.insert_many( {"a": 1} ) # error: Dict entry 0 has incompatible type "str": "int"; expected "Mapping[str, Any]": "int" mongodb-mongo-python-driver-509e9b7/test/mypy_fails/insert_one_list.py000066400000000000000000000004351462766011000263440ustar00rootroot00000000000000from __future__ import annotations from pymongo import MongoClient client: MongoClient = MongoClient() client.test.test.insert_one( [{}] ) # error: Argument 1 to "insert_one" of "Collection" has incompatible type "List[Dict[, ]]"; expected "Mapping[str, Any]" mongodb-mongo-python-driver-509e9b7/test/mypy_fails/raw_bson_document.py000066400000000000000000000006771462766011000266640ustar00rootroot00000000000000from __future__ import annotations from bson.raw_bson import RawBSONDocument from pymongo import MongoClient client = MongoClient(document_class=RawBSONDocument) coll = client.test.test doc = {"my": "doc"} coll.insert_one(doc) retrieved = coll.find_one({"_id": doc["_id"]}) assert retrieved is not None assert len(retrieved.raw) > 0 retrieved[ "foo" ] = "bar" # error: Unsupported target for indexed assignment ("RawBSONDocument") [index] mongodb-mongo-python-driver-509e9b7/test/mypy_fails/typedict_client.py000066400000000000000000000007441462766011000263320ustar00rootroot00000000000000from __future__ import annotations from typing import TypedDict from pymongo import MongoClient class Movie(TypedDict): name: str year: int client: MongoClient[Movie] = MongoClient() coll = client.test.test retrieved = coll.find_one({"_id": "foo"}) assert retrieved is not None assert retrieved["year"] == 1 assert ( retrieved["name"] == 2 ) # error: Non-overlapping equality check (left operand type: "str", right operand type: "Literal[2]") [comparison-overlap] mongodb-mongo-python-driver-509e9b7/test/ocsp/000077500000000000000000000000001462766011000213605ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/ocsp/test_ocsp.py000066400000000000000000000042251462766011000237400ustar00rootroot00000000000000# Copyright 2020-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. """Test OCSP.""" from __future__ import annotations import logging import os import sys import unittest sys.path[0:0] = [""] import pymongo from pymongo.errors import ServerSelectionTimeoutError CA_FILE = os.environ.get("CA_FILE") OCSP_TLS_SHOULD_SUCCEED = os.environ.get("OCSP_TLS_SHOULD_SUCCEED") == "true" # Enable logs in this format: # 2020-06-08 23:49:35,982 DEBUG ocsp_support Peer did not staple an OCSP response FORMAT = "%(asctime)s %(levelname)s %(module)s %(message)s" logging.basicConfig(format=FORMAT, level=logging.DEBUG) if sys.platform == "win32": # The non-stapled OCSP endpoint check is slow on Windows. TIMEOUT_MS = 5000 else: TIMEOUT_MS = 500 def _connect(options): uri = ("mongodb://localhost:27017/?serverSelectionTimeoutMS={}&tlsCAFile={}&{}").format( TIMEOUT_MS, CA_FILE, options, ) print(uri) client = pymongo.MongoClient(uri) client.admin.command("ping") class TestOCSP(unittest.TestCase): def test_tls_insecure(self): # Should always succeed options = "tls=true&tlsInsecure=true" _connect(options) def test_allow_invalid_certificates(self): # Should always succeed options = "tls=true&tlsAllowInvalidCertificates=true" _connect(options) def test_tls(self): options = "tls=true" if not OCSP_TLS_SHOULD_SUCCEED: self.assertRaisesRegex( ServerSelectionTimeoutError, "invalid status response", _connect, options ) else: _connect(options) if __name__ == "__main__": unittest.main() mongodb-mongo-python-driver-509e9b7/test/performance/000077500000000000000000000000001462766011000227155ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/performance/perf_test.py000066400000000000000000000433601462766011000252700ustar00rootroot00000000000000# Copyright 2015-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. """Tests for the MongoDB Driver Performance Benchmarking Spec. See https://github.com/mongodb/specifications/blob/master/source/benchmarking/benchmarking.md To set up the benchmarks locally:: python -m pip install simplejson git clone --depth 1 https://github.com/mongodb/specifications.git pushd specifications/source/benchmarking/data tar xf extended_bson.tgz tar xf parallel.tgz tar xf single_and_multi_document.tgz popd export TEST_PATH="specifications/source/benchmarking/data" export OUTPUT_FILE="results.json" Then to run all benchmarks quickly:: FASTBENCH=1 python test/performance/perf_test.py -v To run individual benchmarks quickly:: FASTBENCH=1 python test/performance/perf_test.py -v TestRunCommand TestFindManyAndEmptyCursor """ from __future__ import annotations import multiprocessing as mp import os import sys import tempfile import threading import time import warnings from typing import Any, List, Optional try: import simplejson as json except ImportError: import json # type: ignore[no-redef] sys.path[0:0] = [""] from test import client_context, unittest from bson import decode, encode, json_util from gridfs import GridFSBucket from pymongo import MongoClient # 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 MIN_ITERATION_TIME = 30 MAX_ITERATION_TIME = 60 NUM_DOCS = 10000 # When debugging or prototyping it's often useful to run the benchmarks locally, set FASTBENCH=1 to run quickly. if bool(os.getenv("FASTBENCH")): NUM_ITERATIONS = 2 MIN_ITERATION_TIME = 0.1 MAX_ITERATION_TIME = 0.5 NUM_DOCS = 1000 TEST_PATH = os.environ.get( "TEST_PATH", os.path.join(os.path.dirname(os.path.realpath(__file__)), os.path.join("data")) ) OUTPUT_FILE = os.environ.get("OUTPUT_FILE") result_data: List = [] def tearDownModule(): output = json.dumps(result_data, indent=4) if OUTPUT_FILE: with open(OUTPUT_FILE, "w") as opf: opf.write(output) else: print(output) class Timer: def __enter__(self): self.start = time.monotonic() return self def __exit__(self, *args): self.end = time.monotonic() self.interval = self.end - self.start def threaded(n_threads, func): threads = [threading.Thread(target=func) for _ in range(n_threads)] for t in threads: t.start() for t in threads: t.join() class PerformanceTest: dataset: str data_size: int fail: Any n_threads: int = 1 @classmethod def setUpClass(cls): client_context.init() def setUp(self): self.setup_time = time.monotonic() def tearDown(self): duration = time.monotonic() - self.setup_time # Remove "Test" so that TestFlatEncoding is reported as "FlatEncoding". name = self.__class__.__name__[4:] median = self.percentile(50) megabytes_per_sec = (self.data_size * self.n_threads) / median / 1000000 print( f"Completed {self.__class__.__name__} {megabytes_per_sec:.3f} MB/s, MEDIAN={self.percentile(50):.3f}s, " f"total time={duration:.3f}s, iterations={len(self.results)}" ) result_data.append( { "info": { "test_name": name, "args": { "threads": self.n_threads, }, }, "metrics": [ {"name": "megabytes_per_sec", "type": "MEDIAN", "value": megabytes_per_sec}, ], } ) def before(self): pass def do_task(self): raise NotImplementedError def after(self): pass def percentile(self, percentile): if hasattr(self, "results"): sorted_results = sorted(self.results) percentile_index = int(len(sorted_results) * percentile / 100) - 1 return sorted_results[percentile_index] else: self.fail("Test execution failed") return None def runTest(self): results = [] start = time.monotonic() i = 0 while True: i += 1 self.before() with Timer() as timer: if self.n_threads == 1: self.do_task() else: threaded(self.n_threads, self.do_task) self.after() results.append(timer.interval) duration = time.monotonic() - start if duration > MIN_ITERATION_TIME and i >= NUM_ITERATIONS: break if duration > MAX_ITERATION_TIME: with warnings.catch_warnings(): warnings.simplefilter("default") warnings.warn( f"{self.__class__.__name__} timed out after {MAX_ITERATION_TIME}s, completed {i}/{NUM_ITERATIONS} iterations." ) break self.results = results def mp_map(self, map_func, files): with mp.Pool(initializer=proc_init, initargs=(client_context.client_options,)) as pool: pool.map(map_func, files) # BSON MICRO-BENCHMARKS class MicroTest(PerformanceTest): def setUp(self): super().setUp() # Location of test data. with open(os.path.join(TEST_PATH, os.path.join("extended_bson", self.dataset))) as data: self.file_data = data.read() class BsonEncodingTest(MicroTest): def setUp(self): super().setUp() # Location of test data. self.document = json_util.loads(self.file_data) self.data_size = len(encode(self.document)) * NUM_DOCS def do_task(self): for _ in range(NUM_DOCS): encode(self.document) class BsonDecodingTest(MicroTest): def setUp(self): super().setUp() self.document = encode(json_util.loads(self.file_data)) self.data_size = len(self.document) * NUM_DOCS def do_task(self): for _ in range(NUM_DOCS): decode(self.document) class TestFlatEncoding(BsonEncodingTest, unittest.TestCase): dataset = "flat_bson.json" class TestFlatDecoding(BsonDecodingTest, unittest.TestCase): dataset = "flat_bson.json" class TestDeepEncoding(BsonEncodingTest, unittest.TestCase): dataset = "deep_bson.json" class TestDeepDecoding(BsonDecodingTest, unittest.TestCase): dataset = "deep_bson.json" class TestFullEncoding(BsonEncodingTest, unittest.TestCase): dataset = "full_bson.json" class TestFullDecoding(BsonDecodingTest, unittest.TestCase): dataset = "full_bson.json" # JSON MICRO-BENCHMARKS class JsonEncodingTest(MicroTest): def setUp(self): super().setUp() # Location of test data. self.document = json_util.loads(self.file_data) # Note: use the BSON size as the data size so we can compare BSON vs JSON performance. self.data_size = len(encode(self.document)) * NUM_DOCS def do_task(self): for _ in range(NUM_DOCS): json_util.dumps(self.document) class JsonDecodingTest(MicroTest): def setUp(self): super().setUp() self.document = self.file_data # Note: use the BSON size as the data size so we can compare BSON vs JSON performance. self.data_size = len(encode(json_util.loads(self.file_data))) * NUM_DOCS def do_task(self): for _ in range(NUM_DOCS): json_util.loads(self.document) class TestJsonFlatEncoding(JsonEncodingTest, unittest.TestCase): dataset = "flat_bson.json" class TestJsonFlatDecoding(JsonDecodingTest, unittest.TestCase): dataset = "flat_bson.json" class TestJsonDeepEncoding(JsonEncodingTest, unittest.TestCase): dataset = "deep_bson.json" class TestJsonDeepDecoding(JsonDecodingTest, unittest.TestCase): dataset = "deep_bson.json" class TestJsonFullEncoding(JsonEncodingTest, unittest.TestCase): dataset = "full_bson.json" class TestJsonFullDecoding(JsonDecodingTest, unittest.TestCase): dataset = "full_bson.json" # SINGLE-DOC BENCHMARKS class TestRunCommand(PerformanceTest, unittest.TestCase): data_size = len(encode({"hello": True})) * NUM_DOCS def setUp(self): super().setUp() self.client = client_context.client self.client.drop_database("perftest") def do_task(self): command = self.client.perftest.command for _ in range(NUM_DOCS): command("hello", True) class TestRunCommand8Threads(TestRunCommand): n_threads = 8 class TestDocument(PerformanceTest): def setUp(self): super().setUp() # Location of test data. with open( os.path.join(TEST_PATH, os.path.join("single_and_multi_document", self.dataset)) ) as data: self.document = json.loads(data.read()) self.client = client_context.client self.client.drop_database("perftest") def tearDown(self): super().tearDown() self.client.drop_database("perftest") def before(self): self.corpus = self.client.perftest.create_collection("corpus") def after(self): self.client.perftest.drop_collection("corpus") class FindTest(TestDocument): dataset = "tweet.json" def setUp(self): super().setUp() self.data_size = len(encode(self.document)) * NUM_DOCS documents = [self.document.copy() for _ in range(NUM_DOCS)] self.corpus = self.client.perftest.corpus result = self.corpus.insert_many(documents) self.inserted_ids = result.inserted_ids def before(self): pass def after(self): pass class TestFindOneByID(FindTest, unittest.TestCase): def do_task(self): find_one = self.corpus.find_one for _id in self.inserted_ids: find_one({"_id": _id}) class TestFindOneByID8Threads(TestFindOneByID): n_threads = 8 class SmallDocInsertTest(TestDocument): dataset = "small_doc.json" def setUp(self): super().setUp() self.data_size = len(encode(self.document)) * NUM_DOCS self.documents = [self.document.copy() for _ in range(NUM_DOCS)] class TestSmallDocInsertOne(SmallDocInsertTest, unittest.TestCase): def do_task(self): insert_one = self.corpus.insert_one for doc in self.documents: insert_one(doc) class LargeDocInsertTest(TestDocument): dataset = "large_doc.json" def setUp(self): super().setUp() n_docs = 10 self.data_size = len(encode(self.document)) * n_docs self.documents = [self.document.copy() for _ in range(n_docs)] class TestLargeDocInsertOne(LargeDocInsertTest, unittest.TestCase): def do_task(self): insert_one = self.corpus.insert_one for doc in self.documents: insert_one(doc) # MULTI-DOC BENCHMARKS class TestFindManyAndEmptyCursor(FindTest, unittest.TestCase): def do_task(self): list(self.corpus.find()) class TestFindManyAndEmptyCursor8Threads(TestFindManyAndEmptyCursor): n_threads = 8 class TestSmallDocBulkInsert(SmallDocInsertTest, unittest.TestCase): def do_task(self): self.corpus.insert_many(self.documents, ordered=True) class TestLargeDocBulkInsert(LargeDocInsertTest, unittest.TestCase): def do_task(self): self.corpus.insert_many(self.documents, ordered=True) class GridFsTest(PerformanceTest): def setUp(self): super().setUp() self.client = client_context.client self.client.drop_database("perftest") gridfs_path = os.path.join( TEST_PATH, os.path.join("single_and_multi_document", "gridfs_large.bin") ) with open(gridfs_path, "rb") as data: self.document = data.read() self.data_size = len(self.document) self.bucket = GridFSBucket(self.client.perftest) def tearDown(self): super().tearDown() self.client.drop_database("perftest") class TestGridFsUpload(GridFsTest, unittest.TestCase): def before(self): # Create the bucket. self.bucket.upload_from_stream("init", b"x") def do_task(self): self.bucket.upload_from_stream("gridfstest", self.document) class TestGridFsDownload(GridFsTest, unittest.TestCase): def setUp(self): super().setUp() self.uploaded_id = self.bucket.upload_from_stream("gridfstest", self.document) def do_task(self): self.bucket.open_download_stream(self.uploaded_id).read() proc_client: Optional[MongoClient] = None def proc_init(client_kwargs): global proc_client proc_client = MongoClient(**client_kwargs) # PARALLEL BENCHMARKS def insert_json_file(filename): assert proc_client is not None with open(filename) as data: coll = proc_client.perftest.corpus coll.insert_many([json.loads(line) for line in data]) def insert_json_file_with_file_id(filename): documents = [] with open(filename) as data: for line in data: doc = json.loads(line) doc["file"] = filename documents.append(doc) assert proc_client is not None coll = proc_client.perftest.corpus coll.insert_many(documents) def read_json_file(filename): assert proc_client is not None coll = proc_client.perftest.corpus with tempfile.TemporaryFile(mode="w") as temp: for doc in coll.find({"file": filename}, {"_id": False}): temp.write(json.dumps(doc)) temp.write("\n") def insert_gridfs_file(filename): assert proc_client is not None bucket = GridFSBucket(proc_client.perftest) with open(filename, "rb") as gfile: bucket.upload_from_stream(filename, gfile) def read_gridfs_file(filename): assert proc_client is not None bucket = GridFSBucket(proc_client.perftest) temp = tempfile.TemporaryFile() try: bucket.download_to_stream_by_name(filename, temp) finally: temp.close() class TestJsonMultiImport(PerformanceTest, unittest.TestCase): def setUp(self): super().setUp() self.client = client_context.client self.client.drop_database("perftest") ldjson_path = os.path.join(TEST_PATH, os.path.join("parallel", "ldjson_multi")) self.files = [os.path.join(ldjson_path, s) for s in os.listdir(ldjson_path)] self.data_size = sum(os.path.getsize(fname) for fname in self.files) self.corpus = self.client.perftest.corpus def before(self): self.client.perftest.command({"create": "corpus"}) def do_task(self): self.mp_map(insert_json_file, self.files) def after(self): self.corpus.drop() def tearDown(self): super().tearDown() self.client.drop_database("perftest") class TestJsonMultiExport(PerformanceTest, unittest.TestCase): def setUp(self): super().setUp() self.client = client_context.client self.client.drop_database("perftest") self.client.perfest.corpus.create_index("file") ldjson_path = os.path.join(TEST_PATH, os.path.join("parallel", "ldjson_multi")) self.files = [os.path.join(ldjson_path, s) for s in os.listdir(ldjson_path)] self.data_size = sum(os.path.getsize(fname) for fname in self.files) self.mp_map(insert_json_file_with_file_id, self.files) def do_task(self): self.mp_map(read_json_file, self.files) def tearDown(self): super().tearDown() self.client.drop_database("perftest") class TestGridFsMultiFileUpload(PerformanceTest, unittest.TestCase): def setUp(self): super().setUp() self.client = client_context.client self.client.drop_database("perftest") gridfs_path = os.path.join(TEST_PATH, os.path.join("parallel", "gridfs_multi")) self.files = [os.path.join(gridfs_path, s) for s in os.listdir(gridfs_path)] self.data_size = sum(os.path.getsize(fname) for fname in self.files) def before(self): self.client.perftest.drop_collection("fs.files") self.client.perftest.drop_collection("fs.chunks") self.bucket = GridFSBucket(self.client.perftest) gridfs_path = os.path.join(TEST_PATH, os.path.join("parallel", "gridfs_multi")) self.files = [os.path.join(gridfs_path, s) for s in os.listdir(gridfs_path)] def do_task(self): self.mp_map(insert_gridfs_file, self.files) def tearDown(self): super().tearDown() self.client.drop_database("perftest") class TestGridFsMultiFileDownload(PerformanceTest, unittest.TestCase): def setUp(self): super().setUp() self.client = client_context.client self.client.drop_database("perftest") bucket = GridFSBucket(self.client.perftest) gridfs_path = os.path.join(TEST_PATH, os.path.join("parallel", "gridfs_multi")) self.files = [os.path.join(gridfs_path, s) for s in os.listdir(gridfs_path)] self.data_size = sum(os.path.getsize(fname) for fname in self.files) for fname in self.files: with open(fname, "rb") as gfile: bucket.upload_from_stream(fname, gfile) def do_task(self): self.mp_map(read_gridfs_file, self.files) def tearDown(self): super().tearDown() self.client.drop_database("perftest") if __name__ == "__main__": unittest.main() mongodb-mongo-python-driver-509e9b7/test/pymongo_mocks.py000066400000000000000000000173001462766011000236530ustar00rootroot00000000000000# Copyright 2013-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. """Tools for mocking parts of PyMongo to test other parts.""" from __future__ import annotations import contextlib import weakref from functools import partial from test import client_context from pymongo import MongoClient, common from pymongo.errors import AutoReconnect, NetworkTimeout from pymongo.hello import Hello, HelloCompat from pymongo.monitor import Monitor from pymongo.pool import Pool from pymongo.server_description import ServerDescription class MockPool(Pool): def __init__(self, client, pair, *args, **kwargs): # MockPool gets a 'client' arg, regular pools don't. Weakref it to # avoid cycle with __del__, causing ResourceWarnings in Python 3.3. self.client = weakref.proxy(client) self.mock_host, self.mock_port = pair # Actually connect to the default server. Pool.__init__(self, (client_context.host, client_context.port), *args, **kwargs) @contextlib.contextmanager def checkout(self, handler=None): client = self.client host_and_port = f"{self.mock_host}:{self.mock_port}" if host_and_port in client.mock_down_hosts: raise AutoReconnect("mock error") assert host_and_port in ( client.mock_standalones + client.mock_members + client.mock_mongoses ), "bad host: %s" % host_and_port with Pool.checkout(self, handler) as conn: conn.mock_host = self.mock_host conn.mock_port = self.mock_port yield conn class DummyMonitor: def __init__(self, server_description, topology, pool, topology_settings): self._server_description = server_description self.opened = False def cancel_check(self): pass def join(self): pass def open(self): self.opened = True def request_check(self): pass def close(self): self.opened = False class MockMonitor(Monitor): def __init__(self, client, server_description, topology, pool, topology_settings): # MockMonitor gets a 'client' arg, regular monitors don't. Weakref it # to avoid cycles. self.client = weakref.proxy(client) Monitor.__init__(self, server_description, topology, pool, topology_settings) def _check_once(self): client = self.client address = self._server_description.address response, rtt = client.mock_hello("%s:%d" % address) # type: ignore[str-format] return ServerDescription(address, Hello(response), rtt) class MockClient(MongoClient): def __init__( self, standalones, members, mongoses, hello_hosts=None, arbiters=None, down_hosts=None, *args, **kwargs, ): """A MongoClient connected to the default server, with a mock topology. standalones, members, mongoses, arbiters, and down_hosts determine the configuration of the topology. They are formatted like ['a:1', 'b:2']. hello_hosts provides an alternative host list for the server's mocked hello response; see test_connect_with_internal_ips. """ self.mock_standalones = standalones[:] self.mock_members = members[:] if self.mock_members: self.mock_primary = self.mock_members[0] else: self.mock_primary = None # Hosts that should be considered an arbiter. self.mock_arbiters = arbiters[:] if arbiters else [] if hello_hosts is not None: self.mock_hello_hosts = hello_hosts else: self.mock_hello_hosts = members[:] self.mock_mongoses = mongoses[:] # Hosts that should raise socket errors. self.mock_down_hosts = down_hosts[:] if down_hosts else [] # Hostname -> (min wire version, max wire version) self.mock_wire_versions = {} # Hostname -> max write batch size self.mock_max_write_batch_sizes = {} # Hostname -> round trip time self.mock_rtts = {} kwargs["_pool_class"] = partial(MockPool, self) kwargs["_monitor_class"] = partial(MockMonitor, self) client_options = client_context.default_client_options.copy() client_options.update(kwargs) super().__init__(*args, **client_options) def kill_host(self, host): """Host is like 'a:1'.""" self.mock_down_hosts.append(host) def revive_host(self, host): """Host is like 'a:1'.""" self.mock_down_hosts.remove(host) def set_wire_version_range(self, host, min_version, max_version): self.mock_wire_versions[host] = (min_version, max_version) def set_max_write_batch_size(self, host, size): self.mock_max_write_batch_sizes[host] = size def mock_hello(self, host): """Return mock hello response (a dict) and round trip time.""" if host in self.mock_wire_versions: min_wire_version, max_wire_version = self.mock_wire_versions[host] else: min_wire_version = common.MIN_SUPPORTED_WIRE_VERSION max_wire_version = common.MAX_SUPPORTED_WIRE_VERSION max_write_batch_size = self.mock_max_write_batch_sizes.get( host, common.MAX_WRITE_BATCH_SIZE ) rtt = self.mock_rtts.get(host, 0) # host is like 'a:1'. if host in self.mock_down_hosts: raise NetworkTimeout("mock timeout") elif host in self.mock_standalones: response = { "ok": 1, HelloCompat.LEGACY_CMD: True, "minWireVersion": min_wire_version, "maxWireVersion": max_wire_version, "maxWriteBatchSize": max_write_batch_size, } elif host in self.mock_members: primary = host == self.mock_primary # Simulate a replica set member. response = { "ok": 1, HelloCompat.LEGACY_CMD: primary, "secondary": not primary, "setName": "rs", "hosts": self.mock_hello_hosts, "minWireVersion": min_wire_version, "maxWireVersion": max_wire_version, "maxWriteBatchSize": max_write_batch_size, } if self.mock_primary: response["primary"] = self.mock_primary if host in self.mock_arbiters: response["arbiterOnly"] = True response["secondary"] = False elif host in self.mock_mongoses: response = { "ok": 1, HelloCompat.LEGACY_CMD: True, "minWireVersion": min_wire_version, "maxWireVersion": max_wire_version, "msg": "isdbgrid", "maxWriteBatchSize": max_write_batch_size, } else: # In test_internal_ips(), we try to connect to a host listed # in hello['hosts'] but not publicly accessible. raise AutoReconnect("Unknown host: %s" % host) return response, rtt def _process_periodic_tasks(self): # Avoid the background thread causing races, e.g. a surprising # reconnect while we're trying to test a disconnected client. pass mongodb-mongo-python-driver-509e9b7/test/qcheck.py000066400000000000000000000155031462766011000222300ustar00rootroot00000000000000# Copyright 2009-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. from __future__ import annotations import datetime import random import re import sys import traceback sys.path[0:0] = [""] from bson.dbref import DBRef from bson.objectid import ObjectId from bson.son import SON gen_target = 100 reduction_attempts = 10 examples = 5 def lift(value): return lambda: value def choose_lifted(generator_list): return lambda: random.choice(generator_list) def my_map(generator, function): return lambda: function(generator()) def choose(list): return lambda: random.choice(list)() def gen_range(start, stop): return lambda: random.randint(start, stop) def gen_int(): max_int = 2147483647 return lambda: random.randint(-max_int - 1, max_int) def gen_float(): return lambda: (random.random() - 0.5) * sys.maxsize def gen_boolean(): return lambda: random.choice([True, False]) def gen_printable_char(): return lambda: chr(random.randint(32, 126)) def gen_printable_string(gen_length): return lambda: "".join(gen_list(gen_printable_char(), gen_length)()) def gen_char(set=None): return lambda: bytes([random.randint(0, 255)]) def gen_string(gen_length): return lambda: b"".join(gen_list(gen_char(), gen_length)()) def gen_unichar(): return lambda: chr(random.randint(1, 0xFFF)) def gen_unicode(gen_length): return lambda: "".join([x for x in gen_list(gen_unichar(), gen_length)() if x not in ".$"]) def gen_list(generator, gen_length): return lambda: [generator() for _ in range(gen_length())] def gen_datetime(): return lambda: datetime.datetime( random.randint(1970, 2037), random.randint(1, 12), random.randint(1, 28), random.randint(0, 23), random.randint(0, 59), random.randint(0, 59), random.randint(0, 999) * 1000, ) def gen_dict(gen_key, gen_value, gen_length): def a_dict(gen_key, gen_value, length): result = {} for _ in range(length): result[gen_key()] = gen_value() return result return lambda: a_dict(gen_key, gen_value, gen_length()) def gen_regexp(gen_length): # TODO our patterns only consist of one letter. # this is because of a bug in CPython's regex equality testing, # which I haven't quite tracked down, so I'm just ignoring it... def pattern(): return "".join(gen_list(choose_lifted("a"), gen_length)()) def gen_flags(): flags = 0 if random.random() > 0.5: flags = flags | re.IGNORECASE if random.random() > 0.5: flags = flags | re.MULTILINE if random.random() > 0.5: flags = flags | re.VERBOSE return flags return lambda: re.compile(pattern(), gen_flags()) def gen_objectid(): return lambda: ObjectId() def gen_dbref(): collection = gen_unicode(gen_range(0, 20)) return lambda: DBRef(collection(), gen_mongo_value(1, True)()) def gen_mongo_value(depth, ref): choices = [ gen_unicode(gen_range(0, 50)), gen_printable_string(gen_range(0, 50)), my_map(gen_string(gen_range(0, 1000)), bytes), gen_int(), gen_float(), gen_boolean(), gen_datetime(), gen_objectid(), lift(None), ] if ref: choices.append(gen_dbref()) if depth > 0: choices.append(gen_mongo_list(depth, ref)) choices.append(gen_mongo_dict(depth, ref)) return choose(choices) def gen_mongo_list(depth, ref): return gen_list(gen_mongo_value(depth - 1, ref), gen_range(0, 10)) def gen_mongo_dict(depth, ref=True): return my_map( gen_dict(gen_unicode(gen_range(0, 20)), gen_mongo_value(depth - 1, ref), gen_range(0, 10)), SON, ) def simplify(case): # TODO this is a hack if isinstance(case, SON) and "$ref" not in case: simplified = SON(case) # make a copy! if random.choice([True, False]): # delete simplified_keys = list(simplified) if not len(simplified_keys): return (False, case) simplified.pop(random.choice(simplified_keys)) return (True, simplified) else: # simplify a value simplified_items = list(simplified.items()) if not len(simplified_items): return (False, case) (key, value) = random.choice(simplified_items) (success, value) = simplify(value) simplified[key] = value return (success, success and simplified or case) if isinstance(case, list): simplified = list(case) if random.choice([True, False]): # delete if not len(simplified): return (False, case) simplified.pop(random.randrange(len(simplified))) return (True, simplified) else: # simplify an item if not len(simplified): return (False, case) index = random.randrange(len(simplified)) (success, value) = simplify(simplified[index]) simplified[index] = value return (success, success and simplified or case) return (False, case) def reduce(case, predicate, reductions=0): for _ in range(reduction_attempts): (reduced, simplified) = simplify(case) if reduced and not predicate(simplified): return reduce(simplified, predicate, reductions + 1) return (reductions, case) def isnt(predicate): return lambda x: not predicate(x) def check(predicate, generator): counter_examples = [] for _ in range(gen_target): case = generator() try: if not predicate(case): reduction = reduce(case, predicate) counter_examples.append("after {} reductions: {!r}".format(*reduction)) except: counter_examples.append(f"{case!r} : {traceback.format_exc()}") return counter_examples def check_unittest(test, predicate, generator): counter_examples = check(predicate, generator) if counter_examples: failures = len(counter_examples) message = "\n".join([" -> %s" % f for f in counter_examples[:examples]]) message = "found %d counter examples, displaying first %d:\n%s" % ( failures, min(failures, examples), message, ) test.fail(message) mongodb-mongo-python-driver-509e9b7/test/read_write_concern/000077500000000000000000000000001462766011000242505ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/read_write_concern/connection-string/000077500000000000000000000000001462766011000277135ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/read_write_concern/connection-string/read-concern.json000066400000000000000000000020551462766011000331500ustar00rootroot00000000000000{ "tests": [ { "description": "Default", "uri": "mongodb://localhost/", "valid": true, "warning": false, "readConcern": {} }, { "description": "local specified", "uri": "mongodb://localhost/?readConcernLevel=local", "valid": true, "warning": false, "readConcern": { "level": "local" } }, { "description": "majority specified", "uri": "mongodb://localhost/?readConcernLevel=majority", "valid": true, "warning": false, "readConcern": { "level": "majority" } }, { "description": "linearizable specified", "uri": "mongodb://localhost/?readConcernLevel=linearizable", "valid": true, "warning": false, "readConcern": { "level": "linearizable" } }, { "description": "available specified", "uri": "mongodb://localhost/?readConcernLevel=available", "valid": true, "warning": false, "readConcern": { "level": "available" } } ] } mongodb-mongo-python-driver-509e9b7/test/read_write_concern/connection-string/write-concern.json000066400000000000000000000052311462766011000333660ustar00rootroot00000000000000{ "tests": [ { "description": "Default", "uri": "mongodb://localhost/", "valid": true, "warning": false, "writeConcern": {} }, { "description": "w as a valid number", "uri": "mongodb://localhost/?w=1", "valid": true, "warning": false, "writeConcern": { "w": 1 } }, { "description": "w as an invalid number", "uri": "mongodb://localhost/?w=-2", "valid": false, "warning": null }, { "description": "w as a string", "uri": "mongodb://localhost/?w=majority", "valid": true, "warning": false, "writeConcern": { "w": "majority" } }, { "description": "wtimeoutMS as a valid number", "uri": "mongodb://localhost/?wtimeoutMS=500", "valid": true, "warning": false, "writeConcern": { "wtimeoutMS": 500 } }, { "description": "wtimeoutMS as an invalid number", "uri": "mongodb://localhost/?wtimeoutMS=-500", "valid": false, "warning": null }, { "description": "journal as false", "uri": "mongodb://localhost/?journal=false", "valid": true, "warning": false, "writeConcern": { "journal": false } }, { "description": "journal as true", "uri": "mongodb://localhost/?journal=true", "valid": true, "warning": false, "writeConcern": { "journal": true } }, { "description": "All options combined", "uri": "mongodb://localhost/?w=3&wtimeoutMS=500&journal=true", "valid": true, "warning": false, "writeConcern": { "w": 3, "wtimeoutMS": 500, "journal": true } }, { "description": "Unacknowledged with w", "uri": "mongodb://localhost/?w=0", "valid": true, "warning": false, "writeConcern": { "w": 0 } }, { "description": "Unacknowledged with w and journal", "uri": "mongodb://localhost/?w=0&journal=false", "valid": true, "warning": false, "writeConcern": { "w": 0, "journal": false } }, { "description": "Unacknowledged with w and wtimeoutMS", "uri": "mongodb://localhost/?w=0&wtimeoutMS=500", "valid": true, "warning": false, "writeConcern": { "w": 0, "wtimeoutMS": 500 } }, { "description": "Acknowledged with w as 0 and journal true", "uri": "mongodb://localhost/?w=0&journal=true", "valid": false, "warning": false, "writeConcern": { "w": 0, "journal": true } } ] } mongodb-mongo-python-driver-509e9b7/test/read_write_concern/document/000077500000000000000000000000001462766011000260665ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/read_write_concern/document/read-concern.json000066400000000000000000000024361462766011000313260ustar00rootroot00000000000000{ "tests": [ { "description": "Default", "valid": true, "readConcern": {}, "readConcernDocument": {}, "isServerDefault": true }, { "description": "Majority", "valid": true, "readConcern": { "level": "majority" }, "readConcernDocument": { "level": "majority" }, "isServerDefault": false }, { "description": "Local", "valid": true, "readConcern": { "level": "local" }, "readConcernDocument": { "level": "local" }, "isServerDefault": false }, { "description": "Linearizable", "valid": true, "readConcern": { "level": "linearizable" }, "readConcernDocument": { "level": "linearizable" }, "isServerDefault": false }, { "description": "Snapshot", "valid": true, "readConcern": { "level": "snapshot" }, "readConcernDocument": { "level": "snapshot" }, "isServerDefault": false }, { "description": "Available", "valid": true, "readConcern": { "level": "available" }, "readConcernDocument": { "level": "available" }, "isServerDefault": false } ] } mongodb-mongo-python-driver-509e9b7/test/read_write_concern/document/write-concern.json000066400000000000000000000071331462766011000315440ustar00rootroot00000000000000{ "tests": [ { "description": "Default", "valid": true, "writeConcern": {}, "writeConcernDocument": {}, "isServerDefault": true, "isAcknowledged": true }, { "description": "W as a number", "valid": true, "writeConcern": { "w": 3 }, "writeConcernDocument": { "w": 3 }, "isServerDefault": false, "isAcknowledged": true }, { "description": "W as an invalid number", "valid": false, "writeConcern": { "w": -3 }, "writeConcernDocument": null, "isServerDefault": null, "isAcknowledged": null }, { "description": "W as majority", "valid": true, "writeConcern": { "w": "majority" }, "writeConcernDocument": { "w": "majority" }, "isServerDefault": false, "isAcknowledged": true }, { "description": "W as a custom string", "valid": true, "writeConcern": { "w": "my_mode" }, "writeConcernDocument": { "w": "my_mode" }, "isServerDefault": false, "isAcknowledged": true }, { "description": "WTimeoutMS", "valid": true, "writeConcern": { "wtimeoutMS": 1000 }, "writeConcernDocument": { "wtimeout": 1000 }, "isServerDefault": false, "isAcknowledged": true }, { "description": "WTimeoutMS as an invalid number", "valid": false, "writeConcern": { "wtimeoutMS": -1000 }, "writeConcernDocument": null, "isServerDefault": null, "isAcknowledged": null }, { "description": "Journal as true", "valid": true, "writeConcern": { "journal": true }, "writeConcernDocument": { "j": true }, "isServerDefault": false, "isAcknowledged": true }, { "description": "Journal as false", "valid": true, "writeConcern": { "journal": false }, "writeConcernDocument": { "j": false }, "isServerDefault": false, "isAcknowledged": true }, { "description": "Unacknowledged with only w", "valid": true, "writeConcern": { "w": 0 }, "writeConcernDocument": { "w": 0 }, "isServerDefault": false, "isAcknowledged": false }, { "description": "Unacknowledged with wtimeoutMS", "valid": true, "writeConcern": { "w": 0, "wtimeoutMS": 500 }, "writeConcernDocument": { "w": 0, "wtimeout": 500 }, "isServerDefault": false, "isAcknowledged": false }, { "description": "Unacknowledged with journal", "valid": true, "writeConcern": { "w": 0, "journal": false }, "writeConcernDocument": { "w": 0, "j": false }, "isServerDefault": false, "isAcknowledged": false }, { "description": "W is 0 with journal true", "valid": false, "writeConcern": { "w": 0, "journal": true }, "writeConcernDocument": { "w": 0, "j": true }, "isServerDefault": false, "isAcknowledged": true }, { "description": "Everything", "valid": true, "writeConcern": { "w": 3, "wtimeoutMS": 1000, "journal": true }, "writeConcernDocument": { "w": 3, "wtimeout": 1000, "j": true }, "isServerDefault": false, "isAcknowledged": true } ] } mongodb-mongo-python-driver-509e9b7/test/read_write_concern/operation/000077500000000000000000000000001462766011000262505ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/read_write_concern/operation/default-write-concern-2.6.json000066400000000000000000000277351462766011000336650ustar00rootroot00000000000000{ "data": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 22 } ], "collection_name": "default_write_concern_coll", "database_name": "default_write_concern_db", "runOn": [ { "minServerVersion": "2.6" } ], "tests": [ { "description": "DeleteOne omits default write concern", "operations": [ { "name": "deleteOne", "object": "collection", "collectionOptions": { "writeConcern": {} }, "arguments": { "filter": {} }, "result": { "deletedCount": 1 } } ], "expectations": [ { "command_started_event": { "command": { "delete": "default_write_concern_coll", "deletes": [ { "q": {}, "limit": 1 } ], "writeConcern": null } } } ] }, { "description": "DeleteMany omits default write concern", "operations": [ { "name": "deleteMany", "object": "collection", "collectionOptions": { "writeConcern": {} }, "arguments": { "filter": {} }, "result": { "deletedCount": 2 } } ], "expectations": [ { "command_started_event": { "command": { "delete": "default_write_concern_coll", "deletes": [ { "q": {}, "limit": 0 } ], "writeConcern": null } } } ] }, { "description": "BulkWrite with all models omits default write concern", "operations": [ { "name": "bulkWrite", "object": "collection", "collectionOptions": { "writeConcern": {} }, "arguments": { "ordered": true, "requests": [ { "name": "deleteMany", "arguments": { "filter": {} } }, { "name": "insertOne", "arguments": { "document": { "_id": 1 } } }, { "name": "updateOne", "arguments": { "filter": { "_id": 1 }, "update": { "$set": { "x": 1 } } } }, { "name": "insertOne", "arguments": { "document": { "_id": 2 } } }, { "name": "replaceOne", "arguments": { "filter": { "_id": 1 }, "replacement": { "x": 2 } } }, { "name": "insertOne", "arguments": { "document": { "_id": 3 } } }, { "name": "updateMany", "arguments": { "filter": { "_id": 1 }, "update": { "$set": { "x": 3 } } } }, { "name": "deleteOne", "arguments": { "filter": { "_id": 3 } } } ] } } ], "outcome": { "collection": { "name": "default_write_concern_coll", "data": [ { "_id": 1, "x": 3 }, { "_id": 2 } ] } }, "expectations": [ { "command_started_event": { "command": { "delete": "default_write_concern_coll", "deletes": [ { "q": {}, "limit": 0 } ], "writeConcern": null } } }, { "command_started_event": { "command": { "insert": "default_write_concern_coll", "documents": [ { "_id": 1 } ], "writeConcern": null } } }, { "command_started_event": { "command": { "update": "default_write_concern_coll", "updates": [ { "q": { "_id": 1 }, "u": { "$set": { "x": 1 } } } ], "writeConcern": null } } }, { "command_started_event": { "command": { "insert": "default_write_concern_coll", "documents": [ { "_id": 2 } ], "writeConcern": null } } }, { "command_started_event": { "command": { "update": "default_write_concern_coll", "updates": [ { "q": { "_id": 1 }, "u": { "x": 2 } } ], "writeConcern": null } } }, { "command_started_event": { "command": { "insert": "default_write_concern_coll", "documents": [ { "_id": 3 } ], "writeConcern": null } } }, { "command_started_event": { "command": { "update": "default_write_concern_coll", "updates": [ { "q": { "_id": 1 }, "u": { "$set": { "x": 3 } }, "multi": true } ], "writeConcern": null } } }, { "command_started_event": { "command": { "delete": "default_write_concern_coll", "deletes": [ { "q": { "_id": 3 }, "limit": 1 } ], "writeConcern": null } } } ] }, { "description": "InsertOne and InsertMany omit default write concern", "operations": [ { "name": "insertOne", "object": "collection", "collectionOptions": { "writeConcern": {} }, "arguments": { "document": { "_id": 3 } } }, { "name": "insertMany", "object": "collection", "collectionOptions": { "writeConcern": {} }, "arguments": { "documents": [ { "_id": 4 }, { "_id": 5 } ] } } ], "outcome": { "collection": { "name": "default_write_concern_coll", "data": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 22 }, { "_id": 3 }, { "_id": 4 }, { "_id": 5 } ] } }, "expectations": [ { "command_started_event": { "command": { "insert": "default_write_concern_coll", "documents": [ { "_id": 3 } ], "writeConcern": null } } }, { "command_started_event": { "command": { "insert": "default_write_concern_coll", "documents": [ { "_id": 4 }, { "_id": 5 } ], "writeConcern": null } } } ] }, { "description": "UpdateOne, UpdateMany, and ReplaceOne omit default write concern", "operations": [ { "name": "updateOne", "object": "collection", "collectionOptions": { "writeConcern": {} }, "arguments": { "filter": { "_id": 1 }, "update": { "$set": { "x": 1 } } } }, { "name": "updateMany", "object": "collection", "collectionOptions": { "writeConcern": {} }, "arguments": { "filter": { "_id": 2 }, "update": { "$set": { "x": 2 } } } }, { "name": "replaceOne", "object": "collection", "collectionOptions": { "writeConcern": {} }, "arguments": { "filter": { "_id": 2 }, "replacement": { "x": 3 } } } ], "outcome": { "collection": { "name": "default_write_concern_coll", "data": [ { "_id": 1, "x": 1 }, { "_id": 2, "x": 3 } ] } }, "expectations": [ { "command_started_event": { "command": { "update": "default_write_concern_coll", "updates": [ { "q": { "_id": 1 }, "u": { "$set": { "x": 1 } } } ], "writeConcern": null } } }, { "command_started_event": { "command": { "update": "default_write_concern_coll", "updates": [ { "q": { "_id": 2 }, "u": { "$set": { "x": 2 } }, "multi": true } ], "writeConcern": null } } }, { "command_started_event": { "command": { "update": "default_write_concern_coll", "updates": [ { "q": { "_id": 2 }, "u": { "x": 3 } } ], "writeConcern": null } } } ] } ] } mongodb-mongo-python-driver-509e9b7/test/read_write_concern/operation/default-write-concern-3.2.json000066400000000000000000000051231462766011000336450ustar00rootroot00000000000000{ "data": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 22 } ], "collection_name": "default_write_concern_coll", "database_name": "default_write_concern_db", "runOn": [ { "minServerVersion": "3.2" } ], "tests": [ { "description": "findAndModify operations omit default write concern", "operations": [ { "name": "findOneAndUpdate", "object": "collection", "collectionOptions": { "writeConcern": {} }, "arguments": { "filter": { "_id": 1 }, "update": { "$set": { "x": 1 } } } }, { "name": "findOneAndReplace", "object": "collection", "collectionOptions": { "writeConcern": {} }, "arguments": { "filter": { "_id": 2 }, "replacement": { "x": 2 } } }, { "name": "findOneAndDelete", "object": "collection", "collectionOptions": { "writeConcern": {} }, "arguments": { "filter": { "_id": 2 } } } ], "outcome": { "collection": { "name": "default_write_concern_coll", "data": [ { "_id": 1, "x": 1 } ] } }, "expectations": [ { "command_started_event": { "command": { "findAndModify": "default_write_concern_coll", "query": { "_id": 1 }, "update": { "$set": { "x": 1 } }, "writeConcern": null } } }, { "command_started_event": { "command": { "findAndModify": "default_write_concern_coll", "query": { "_id": 2 }, "update": { "x": 2 }, "writeConcern": null } } }, { "command_started_event": { "command": { "findAndModify": "default_write_concern_coll", "query": { "_id": 2 }, "remove": true, "writeConcern": null } } } ] } ] } mongodb-mongo-python-driver-509e9b7/test/read_write_concern/operation/default-write-concern-3.4.json000066400000000000000000000116641462766011000336560ustar00rootroot00000000000000{ "data": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 22 } ], "collection_name": "default_write_concern_coll", "database_name": "default_write_concern_db", "runOn": [ { "minServerVersion": "3.4" } ], "tests": [ { "description": "Aggregate with $out omits default write concern", "operations": [ { "object": "collection", "collectionOptions": { "writeConcern": {} }, "name": "aggregate", "arguments": { "pipeline": [ { "$match": { "_id": { "$gt": 1 } } }, { "$out": "other_collection_name" } ] } } ], "outcome": { "collection": { "name": "other_collection_name", "data": [ { "_id": 2, "x": 22 } ] } }, "expectations": [ { "command_started_event": { "command": { "aggregate": "default_write_concern_coll", "pipeline": [ { "$match": { "_id": { "$gt": 1 } } }, { "$out": "other_collection_name" } ], "writeConcern": null } } } ] }, { "description": "RunCommand with a write command omits default write concern (runCommand should never inherit write concern)", "operations": [ { "object": "database", "databaseOptions": { "writeConcern": {} }, "name": "runCommand", "command_name": "delete", "arguments": { "command": { "delete": "default_write_concern_coll", "deletes": [ { "q": {}, "limit": 1 } ] } } } ], "expectations": [ { "command_started_event": { "command": { "delete": "default_write_concern_coll", "deletes": [ { "q": {}, "limit": 1 } ], "writeConcern": null } } } ] }, { "description": "CreateIndex and dropIndex omits default write concern", "operations": [ { "object": "collection", "collectionOptions": { "writeConcern": {} }, "name": "createIndex", "arguments": { "keys": { "x": 1 } } }, { "object": "collection", "collectionOptions": { "writeConcern": {} }, "name": "dropIndex", "arguments": { "name": "x_1" } } ], "expectations": [ { "command_started_event": { "command": { "createIndexes": "default_write_concern_coll", "indexes": [ { "name": "x_1", "key": { "x": 1 } } ], "writeConcern": null } } }, { "command_started_event": { "command": { "dropIndexes": "default_write_concern_coll", "index": "x_1", "writeConcern": null } } } ] }, { "description": "MapReduce omits default write concern", "operations": [ { "name": "mapReduce", "object": "collection", "collectionOptions": { "writeConcern": {} }, "arguments": { "map": { "$code": "function inc() { return emit(0, this.x + 1) }" }, "reduce": { "$code": "function sum(key, values) { return values.reduce((acc, x) => acc + x); }" }, "out": { "inline": 1 } } } ], "expectations": [ { "command_started_event": { "command": { "mapReduce": "default_write_concern_coll", "map": { "$code": "function inc() { return emit(0, this.x + 1) }" }, "reduce": { "$code": "function sum(key, values) { return values.reduce((acc, x) => acc + x); }" }, "out": { "inline": 1 }, "writeConcern": null } } } ] } ] } mongodb-mongo-python-driver-509e9b7/test/read_write_concern/operation/default-write-concern-4.2.json000066400000000000000000000034001462766011000336420ustar00rootroot00000000000000{ "data": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 22 } ], "collection_name": "default_write_concern_coll", "database_name": "default_write_concern_db", "runOn": [ { "minServerVersion": "4.2" } ], "tests": [ { "description": "Aggregate with $merge omits default write concern", "operations": [ { "object": "collection", "databaseOptions": { "writeConcern": {} }, "collectionOptions": { "writeConcern": {} }, "name": "aggregate", "arguments": { "pipeline": [ { "$match": { "_id": { "$gt": 1 } } }, { "$merge": { "into": "other_collection_name" } } ] } } ], "expectations": [ { "command_started_event": { "command": { "aggregate": "default_write_concern_coll", "pipeline": [ { "$match": { "_id": { "$gt": 1 } } }, { "$merge": { "into": "other_collection_name" } } ], "writeConcern": null } } } ], "outcome": { "collection": { "name": "other_collection_name", "data": [ { "_id": 2, "x": 22 } ] } } } ] } mongodb-mongo-python-driver-509e9b7/test/retryable_reads/000077500000000000000000000000001462766011000235635ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/retryable_reads/legacy/000077500000000000000000000000001462766011000250275ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/retryable_reads/legacy/aggregate-merge.json000066400000000000000000000036471462766011000307570ustar00rootroot00000000000000{ "runOn": [ { "minServerVersion": "4.1.11" } ], "database_name": "retryable-reads-tests", "collection_name": "coll", "data": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 22 }, { "_id": 3, "x": 33 } ], "tests": [ { "description": "Aggregate with $merge does not retry", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "aggregate" ], "closeConnection": true } }, "operations": [ { "object": "collection", "name": "aggregate", "arguments": { "pipeline": [ { "$match": { "_id": { "$gt": 1 } } }, { "$sort": { "x": 1 } }, { "$merge": { "into": "output-collection" } } ] }, "error": true } ], "expectations": [ { "command_started_event": { "command": { "aggregate": "coll", "pipeline": [ { "$match": { "_id": { "$gt": 1 } } }, { "$sort": { "x": 1 } }, { "$merge": { "into": "output-collection" } } ] }, "command_name": "aggregate", "database_name": "retryable-reads-tests" } } ] } ] } mongodb-mongo-python-driver-509e9b7/test/retryable_reads/legacy/aggregate-serverErrors.json000066400000000000000000000631741462766011000323640ustar00rootroot00000000000000{ "runOn": [ { "minServerVersion": "4.0", "topology": [ "single", "replicaset" ] }, { "minServerVersion": "4.1.7", "topology": [ "sharded", "load-balanced" ] } ], "database_name": "retryable-reads-tests", "collection_name": "coll", "data": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 22 }, { "_id": 3, "x": 33 } ], "tests": [ { "description": "Aggregate succeeds after InterruptedAtShutdown", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "aggregate" ], "errorCode": 11600 } }, "operations": [ { "name": "aggregate", "object": "collection", "arguments": { "pipeline": [ { "$match": { "_id": { "$gt": 1 } } }, { "$sort": { "x": 1 } } ] }, "result": [ { "_id": 2, "x": 22 }, { "_id": 3, "x": 33 } ] } ], "expectations": [ { "command_started_event": { "command": { "aggregate": "coll", "pipeline": [ { "$match": { "_id": { "$gt": 1 } } }, { "$sort": { "x": 1 } } ] }, "database_name": "retryable-reads-tests" } }, { "command_started_event": { "command": { "aggregate": "coll", "pipeline": [ { "$match": { "_id": { "$gt": 1 } } }, { "$sort": { "x": 1 } } ] }, "database_name": "retryable-reads-tests" } } ] }, { "description": "Aggregate succeeds after InterruptedDueToReplStateChange", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "aggregate" ], "errorCode": 11602 } }, "operations": [ { "name": "aggregate", "object": "collection", "arguments": { "pipeline": [ { "$match": { "_id": { "$gt": 1 } } }, { "$sort": { "x": 1 } } ] }, "result": [ { "_id": 2, "x": 22 }, { "_id": 3, "x": 33 } ] } ], "expectations": [ { "command_started_event": { "command": { "aggregate": "coll", "pipeline": [ { "$match": { "_id": { "$gt": 1 } } }, { "$sort": { "x": 1 } } ] }, "database_name": "retryable-reads-tests" } }, { "command_started_event": { "command": { "aggregate": "coll", "pipeline": [ { "$match": { "_id": { "$gt": 1 } } }, { "$sort": { "x": 1 } } ] }, "database_name": "retryable-reads-tests" } } ] }, { "description": "Aggregate succeeds after NotWritablePrimary", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "aggregate" ], "errorCode": 10107 } }, "operations": [ { "name": "aggregate", "object": "collection", "arguments": { "pipeline": [ { "$match": { "_id": { "$gt": 1 } } }, { "$sort": { "x": 1 } } ] }, "result": [ { "_id": 2, "x": 22 }, { "_id": 3, "x": 33 } ] } ], "expectations": [ { "command_started_event": { "command": { "aggregate": "coll", "pipeline": [ { "$match": { "_id": { "$gt": 1 } } }, { "$sort": { "x": 1 } } ] }, "database_name": "retryable-reads-tests" } }, { "command_started_event": { "command": { "aggregate": "coll", "pipeline": [ { "$match": { "_id": { "$gt": 1 } } }, { "$sort": { "x": 1 } } ] }, "database_name": "retryable-reads-tests" } } ] }, { "description": "Aggregate succeeds after NotPrimaryNoSecondaryOk", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "aggregate" ], "errorCode": 13435 } }, "operations": [ { "name": "aggregate", "object": "collection", "arguments": { "pipeline": [ { "$match": { "_id": { "$gt": 1 } } }, { "$sort": { "x": 1 } } ] }, "result": [ { "_id": 2, "x": 22 }, { "_id": 3, "x": 33 } ] } ], "expectations": [ { "command_started_event": { "command": { "aggregate": "coll", "pipeline": [ { "$match": { "_id": { "$gt": 1 } } }, { "$sort": { "x": 1 } } ] }, "database_name": "retryable-reads-tests" } }, { "command_started_event": { "command": { "aggregate": "coll", "pipeline": [ { "$match": { "_id": { "$gt": 1 } } }, { "$sort": { "x": 1 } } ] }, "database_name": "retryable-reads-tests" } } ] }, { "description": "Aggregate succeeds after NotPrimaryOrSecondary", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "aggregate" ], "errorCode": 13436 } }, "operations": [ { "name": "aggregate", "object": "collection", "arguments": { "pipeline": [ { "$match": { "_id": { "$gt": 1 } } }, { "$sort": { "x": 1 } } ] }, "result": [ { "_id": 2, "x": 22 }, { "_id": 3, "x": 33 } ] } ], "expectations": [ { "command_started_event": { "command": { "aggregate": "coll", "pipeline": [ { "$match": { "_id": { "$gt": 1 } } }, { "$sort": { "x": 1 } } ] }, "database_name": "retryable-reads-tests" } }, { "command_started_event": { "command": { "aggregate": "coll", "pipeline": [ { "$match": { "_id": { "$gt": 1 } } }, { "$sort": { "x": 1 } } ] }, "database_name": "retryable-reads-tests" } } ] }, { "description": "Aggregate succeeds after PrimarySteppedDown", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "aggregate" ], "errorCode": 189 } }, "operations": [ { "name": "aggregate", "object": "collection", "arguments": { "pipeline": [ { "$match": { "_id": { "$gt": 1 } } }, { "$sort": { "x": 1 } } ] }, "result": [ { "_id": 2, "x": 22 }, { "_id": 3, "x": 33 } ] } ], "expectations": [ { "command_started_event": { "command": { "aggregate": "coll", "pipeline": [ { "$match": { "_id": { "$gt": 1 } } }, { "$sort": { "x": 1 } } ] }, "database_name": "retryable-reads-tests" } }, { "command_started_event": { "command": { "aggregate": "coll", "pipeline": [ { "$match": { "_id": { "$gt": 1 } } }, { "$sort": { "x": 1 } } ] }, "database_name": "retryable-reads-tests" } } ] }, { "description": "Aggregate succeeds after ShutdownInProgress", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "aggregate" ], "errorCode": 91 } }, "operations": [ { "name": "aggregate", "object": "collection", "arguments": { "pipeline": [ { "$match": { "_id": { "$gt": 1 } } }, { "$sort": { "x": 1 } } ] }, "result": [ { "_id": 2, "x": 22 }, { "_id": 3, "x": 33 } ] } ], "expectations": [ { "command_started_event": { "command": { "aggregate": "coll", "pipeline": [ { "$match": { "_id": { "$gt": 1 } } }, { "$sort": { "x": 1 } } ] }, "database_name": "retryable-reads-tests" } }, { "command_started_event": { "command": { "aggregate": "coll", "pipeline": [ { "$match": { "_id": { "$gt": 1 } } }, { "$sort": { "x": 1 } } ] }, "database_name": "retryable-reads-tests" } } ] }, { "description": "Aggregate succeeds after HostNotFound", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "aggregate" ], "errorCode": 7 } }, "operations": [ { "name": "aggregate", "object": "collection", "arguments": { "pipeline": [ { "$match": { "_id": { "$gt": 1 } } }, { "$sort": { "x": 1 } } ] }, "result": [ { "_id": 2, "x": 22 }, { "_id": 3, "x": 33 } ] } ], "expectations": [ { "command_started_event": { "command": { "aggregate": "coll", "pipeline": [ { "$match": { "_id": { "$gt": 1 } } }, { "$sort": { "x": 1 } } ] }, "database_name": "retryable-reads-tests" } }, { "command_started_event": { "command": { "aggregate": "coll", "pipeline": [ { "$match": { "_id": { "$gt": 1 } } }, { "$sort": { "x": 1 } } ] }, "database_name": "retryable-reads-tests" } } ] }, { "description": "Aggregate succeeds after HostUnreachable", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "aggregate" ], "errorCode": 6 } }, "operations": [ { "name": "aggregate", "object": "collection", "arguments": { "pipeline": [ { "$match": { "_id": { "$gt": 1 } } }, { "$sort": { "x": 1 } } ] }, "result": [ { "_id": 2, "x": 22 }, { "_id": 3, "x": 33 } ] } ], "expectations": [ { "command_started_event": { "command": { "aggregate": "coll", "pipeline": [ { "$match": { "_id": { "$gt": 1 } } }, { "$sort": { "x": 1 } } ] }, "database_name": "retryable-reads-tests" } }, { "command_started_event": { "command": { "aggregate": "coll", "pipeline": [ { "$match": { "_id": { "$gt": 1 } } }, { "$sort": { "x": 1 } } ] }, "database_name": "retryable-reads-tests" } } ] }, { "description": "Aggregate succeeds after NetworkTimeout", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "aggregate" ], "errorCode": 89 } }, "operations": [ { "name": "aggregate", "object": "collection", "arguments": { "pipeline": [ { "$match": { "_id": { "$gt": 1 } } }, { "$sort": { "x": 1 } } ] }, "result": [ { "_id": 2, "x": 22 }, { "_id": 3, "x": 33 } ] } ], "expectations": [ { "command_started_event": { "command": { "aggregate": "coll", "pipeline": [ { "$match": { "_id": { "$gt": 1 } } }, { "$sort": { "x": 1 } } ] }, "database_name": "retryable-reads-tests" } }, { "command_started_event": { "command": { "aggregate": "coll", "pipeline": [ { "$match": { "_id": { "$gt": 1 } } }, { "$sort": { "x": 1 } } ] }, "database_name": "retryable-reads-tests" } } ] }, { "description": "Aggregate succeeds after SocketException", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "aggregate" ], "errorCode": 9001 } }, "operations": [ { "name": "aggregate", "object": "collection", "arguments": { "pipeline": [ { "$match": { "_id": { "$gt": 1 } } }, { "$sort": { "x": 1 } } ] }, "result": [ { "_id": 2, "x": 22 }, { "_id": 3, "x": 33 } ] } ], "expectations": [ { "command_started_event": { "command": { "aggregate": "coll", "pipeline": [ { "$match": { "_id": { "$gt": 1 } } }, { "$sort": { "x": 1 } } ] }, "database_name": "retryable-reads-tests" } }, { "command_started_event": { "command": { "aggregate": "coll", "pipeline": [ { "$match": { "_id": { "$gt": 1 } } }, { "$sort": { "x": 1 } } ] }, "database_name": "retryable-reads-tests" } } ] }, { "description": "Aggregate fails after two NotWritablePrimary errors", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 2 }, "data": { "failCommands": [ "aggregate" ], "errorCode": 10107 } }, "operations": [ { "name": "aggregate", "object": "collection", "arguments": { "pipeline": [ { "$match": { "_id": { "$gt": 1 } } }, { "$sort": { "x": 1 } } ] }, "error": true } ], "expectations": [ { "command_started_event": { "command": { "aggregate": "coll", "pipeline": [ { "$match": { "_id": { "$gt": 1 } } }, { "$sort": { "x": 1 } } ] }, "database_name": "retryable-reads-tests" } }, { "command_started_event": { "command": { "aggregate": "coll", "pipeline": [ { "$match": { "_id": { "$gt": 1 } } }, { "$sort": { "x": 1 } } ] }, "database_name": "retryable-reads-tests" } } ] }, { "description": "Aggregate fails after NotWritablePrimary when retryReads is false", "clientOptions": { "retryReads": false }, "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "aggregate" ], "errorCode": 10107 } }, "operations": [ { "name": "aggregate", "object": "collection", "arguments": { "pipeline": [ { "$match": { "_id": { "$gt": 1 } } }, { "$sort": { "x": 1 } } ] }, "error": true } ], "expectations": [ { "command_started_event": { "command": { "aggregate": "coll", "pipeline": [ { "$match": { "_id": { "$gt": 1 } } }, { "$sort": { "x": 1 } } ] }, "database_name": "retryable-reads-tests" } } ] } ] } mongodb-mongo-python-driver-509e9b7/test/retryable_reads/legacy/aggregate.json000066400000000000000000000206631462766011000276570ustar00rootroot00000000000000{ "runOn": [ { "minServerVersion": "4.0", "topology": [ "single", "replicaset" ] }, { "minServerVersion": "4.1.7", "topology": [ "sharded", "load-balanced" ] } ], "database_name": "retryable-reads-tests", "collection_name": "coll", "data": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 22 }, { "_id": 3, "x": 33 } ], "tests": [ { "description": "Aggregate succeeds on first attempt", "operations": [ { "name": "aggregate", "object": "collection", "arguments": { "pipeline": [ { "$match": { "_id": { "$gt": 1 } } }, { "$sort": { "x": 1 } } ] }, "result": [ { "_id": 2, "x": 22 }, { "_id": 3, "x": 33 } ] } ], "expectations": [ { "command_started_event": { "command": { "aggregate": "coll", "pipeline": [ { "$match": { "_id": { "$gt": 1 } } }, { "$sort": { "x": 1 } } ] }, "database_name": "retryable-reads-tests" } } ] }, { "description": "Aggregate succeeds on second attempt", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "aggregate" ], "closeConnection": true } }, "operations": [ { "name": "aggregate", "object": "collection", "arguments": { "pipeline": [ { "$match": { "_id": { "$gt": 1 } } }, { "$sort": { "x": 1 } } ] }, "result": [ { "_id": 2, "x": 22 }, { "_id": 3, "x": 33 } ] } ], "expectations": [ { "command_started_event": { "command": { "aggregate": "coll", "pipeline": [ { "$match": { "_id": { "$gt": 1 } } }, { "$sort": { "x": 1 } } ] }, "database_name": "retryable-reads-tests" } }, { "command_started_event": { "command": { "aggregate": "coll", "pipeline": [ { "$match": { "_id": { "$gt": 1 } } }, { "$sort": { "x": 1 } } ] }, "database_name": "retryable-reads-tests" } } ] }, { "description": "Aggregate fails on first attempt", "clientOptions": { "retryReads": false }, "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "aggregate" ], "closeConnection": true } }, "operations": [ { "name": "aggregate", "object": "collection", "arguments": { "pipeline": [ { "$match": { "_id": { "$gt": 1 } } }, { "$sort": { "x": 1 } } ] }, "error": true } ], "expectations": [ { "command_started_event": { "command": { "aggregate": "coll", "pipeline": [ { "$match": { "_id": { "$gt": 1 } } }, { "$sort": { "x": 1 } } ] }, "database_name": "retryable-reads-tests" } } ] }, { "description": "Aggregate fails on second attempt", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 2 }, "data": { "failCommands": [ "aggregate" ], "closeConnection": true } }, "operations": [ { "name": "aggregate", "object": "collection", "arguments": { "pipeline": [ { "$match": { "_id": { "$gt": 1 } } }, { "$sort": { "x": 1 } } ] }, "error": true } ], "expectations": [ { "command_started_event": { "command": { "aggregate": "coll", "pipeline": [ { "$match": { "_id": { "$gt": 1 } } }, { "$sort": { "x": 1 } } ] }, "database_name": "retryable-reads-tests" } }, { "command_started_event": { "command": { "aggregate": "coll", "pipeline": [ { "$match": { "_id": { "$gt": 1 } } }, { "$sort": { "x": 1 } } ] }, "database_name": "retryable-reads-tests" } } ] }, { "description": "Aggregate with $out does not retry", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "aggregate" ], "closeConnection": true } }, "operations": [ { "name": "aggregate", "object": "collection", "arguments": { "pipeline": [ { "$match": { "_id": { "$gt": 1 } } }, { "$sort": { "x": 1 } }, { "$out": "output-collection" } ] }, "error": true } ], "expectations": [ { "command_started_event": { "command": { "aggregate": "coll", "pipeline": [ { "$match": { "_id": { "$gt": 1 } } }, { "$sort": { "x": 1 } }, { "$out": "output-collection" } ] }, "command_name": "aggregate", "database_name": "retryable-reads-tests" } } ] } ] } changeStreams-client.watch-serverErrors.json000066400000000000000000000401701462766011000355130ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/retryable_reads/legacy{ "runOn": [ { "minServerVersion": "4.0", "topology": [ "replicaset" ] }, { "minServerVersion": "4.1.7", "topology": [ "sharded", "load-balanced" ], "serverless": "forbid" } ], "database_name": "retryable-reads-tests", "collection_name": "coll", "data": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 22 }, { "_id": 3, "x": 33 } ], "tests": [ { "description": "client.watch succeeds after InterruptedAtShutdown", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "aggregate" ], "errorCode": 11600 } }, "operations": [ { "name": "watch", "object": "client" } ], "expectations": [ { "command_started_event": { "command": { "aggregate": 1, "cursor": {}, "pipeline": [ { "$changeStream": { "allChangesForCluster": true } } ] }, "database_name": "admin" } }, { "command_started_event": { "command": { "aggregate": 1, "cursor": {}, "pipeline": [ { "$changeStream": { "allChangesForCluster": true } } ] }, "database_name": "admin" } } ] }, { "description": "client.watch succeeds after InterruptedDueToReplStateChange", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "aggregate" ], "errorCode": 11602 } }, "operations": [ { "name": "watch", "object": "client" } ], "expectations": [ { "command_started_event": { "command": { "aggregate": 1, "cursor": {}, "pipeline": [ { "$changeStream": { "allChangesForCluster": true } } ] }, "database_name": "admin" } }, { "command_started_event": { "command": { "aggregate": 1, "cursor": {}, "pipeline": [ { "$changeStream": { "allChangesForCluster": true } } ] }, "database_name": "admin" } } ] }, { "description": "client.watch succeeds after NotWritablePrimary", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "aggregate" ], "errorCode": 10107 } }, "operations": [ { "name": "watch", "object": "client" } ], "expectations": [ { "command_started_event": { "command": { "aggregate": 1, "cursor": {}, "pipeline": [ { "$changeStream": { "allChangesForCluster": true } } ] }, "database_name": "admin" } }, { "command_started_event": { "command": { "aggregate": 1, "cursor": {}, "pipeline": [ { "$changeStream": { "allChangesForCluster": true } } ] }, "database_name": "admin" } } ] }, { "description": "client.watch succeeds after NotPrimaryNoSecondaryOk", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "aggregate" ], "errorCode": 13435 } }, "operations": [ { "name": "watch", "object": "client" } ], "expectations": [ { "command_started_event": { "command": { "aggregate": 1, "cursor": {}, "pipeline": [ { "$changeStream": { "allChangesForCluster": true } } ] }, "database_name": "admin" } }, { "command_started_event": { "command": { "aggregate": 1, "cursor": {}, "pipeline": [ { "$changeStream": { "allChangesForCluster": true } } ] }, "database_name": "admin" } } ] }, { "description": "client.watch succeeds after NotPrimaryOrSecondary", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "aggregate" ], "errorCode": 13436 } }, "operations": [ { "name": "watch", "object": "client" } ], "expectations": [ { "command_started_event": { "command": { "aggregate": 1, "cursor": {}, "pipeline": [ { "$changeStream": { "allChangesForCluster": true } } ] }, "database_name": "admin" } }, { "command_started_event": { "command": { "aggregate": 1, "cursor": {}, "pipeline": [ { "$changeStream": { "allChangesForCluster": true } } ] }, "database_name": "admin" } } ] }, { "description": "client.watch succeeds after PrimarySteppedDown", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "aggregate" ], "errorCode": 189 } }, "operations": [ { "name": "watch", "object": "client" } ], "expectations": [ { "command_started_event": { "command": { "aggregate": 1, "cursor": {}, "pipeline": [ { "$changeStream": { "allChangesForCluster": true } } ] }, "database_name": "admin" } }, { "command_started_event": { "command": { "aggregate": 1, "cursor": {}, "pipeline": [ { "$changeStream": { "allChangesForCluster": true } } ] }, "database_name": "admin" } } ] }, { "description": "client.watch succeeds after ShutdownInProgress", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "aggregate" ], "errorCode": 91 } }, "operations": [ { "name": "watch", "object": "client" } ], "expectations": [ { "command_started_event": { "command": { "aggregate": 1, "cursor": {}, "pipeline": [ { "$changeStream": { "allChangesForCluster": true } } ] }, "database_name": "admin" } }, { "command_started_event": { "command": { "aggregate": 1, "cursor": {}, "pipeline": [ { "$changeStream": { "allChangesForCluster": true } } ] }, "database_name": "admin" } } ] }, { "description": "client.watch succeeds after HostNotFound", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "aggregate" ], "errorCode": 7 } }, "operations": [ { "name": "watch", "object": "client" } ], "expectations": [ { "command_started_event": { "command": { "aggregate": 1, "cursor": {}, "pipeline": [ { "$changeStream": { "allChangesForCluster": true } } ] }, "database_name": "admin" } }, { "command_started_event": { "command": { "aggregate": 1, "cursor": {}, "pipeline": [ { "$changeStream": { "allChangesForCluster": true } } ] }, "database_name": "admin" } } ] }, { "description": "client.watch succeeds after HostUnreachable", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "aggregate" ], "errorCode": 6 } }, "operations": [ { "name": "watch", "object": "client" } ], "expectations": [ { "command_started_event": { "command": { "aggregate": 1, "cursor": {}, "pipeline": [ { "$changeStream": { "allChangesForCluster": true } } ] }, "database_name": "admin" } }, { "command_started_event": { "command": { "aggregate": 1, "cursor": {}, "pipeline": [ { "$changeStream": { "allChangesForCluster": true } } ] }, "database_name": "admin" } } ] }, { "description": "client.watch succeeds after NetworkTimeout", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "aggregate" ], "errorCode": 89 } }, "operations": [ { "name": "watch", "object": "client" } ], "expectations": [ { "command_started_event": { "command": { "aggregate": 1, "cursor": {}, "pipeline": [ { "$changeStream": { "allChangesForCluster": true } } ] }, "database_name": "admin" } }, { "command_started_event": { "command": { "aggregate": 1, "cursor": {}, "pipeline": [ { "$changeStream": { "allChangesForCluster": true } } ] }, "database_name": "admin" } } ] }, { "description": "client.watch succeeds after SocketException", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "aggregate" ], "errorCode": 9001 } }, "operations": [ { "name": "watch", "object": "client" } ], "expectations": [ { "command_started_event": { "command": { "aggregate": 1, "cursor": {}, "pipeline": [ { "$changeStream": { "allChangesForCluster": true } } ] }, "database_name": "admin" } }, { "command_started_event": { "command": { "aggregate": 1, "cursor": {}, "pipeline": [ { "$changeStream": { "allChangesForCluster": true } } ] }, "database_name": "admin" } } ] }, { "description": "client.watch fails after two NotWritablePrimary errors", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 2 }, "data": { "failCommands": [ "aggregate" ], "errorCode": 10107 } }, "operations": [ { "name": "watch", "object": "client", "error": true } ], "expectations": [ { "command_started_event": { "command": { "aggregate": 1, "cursor": {}, "pipeline": [ { "$changeStream": { "allChangesForCluster": true } } ] }, "database_name": "admin" } }, { "command_started_event": { "command": { "aggregate": 1, "cursor": {}, "pipeline": [ { "$changeStream": { "allChangesForCluster": true } } ] }, "database_name": "admin" } } ] }, { "description": "client.watch fails after NotWritablePrimary when retryReads is false", "clientOptions": { "retryReads": false }, "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "aggregate" ], "errorCode": 10107 } }, "operations": [ { "name": "watch", "object": "client", "error": true } ], "expectations": [ { "command_started_event": { "command": { "aggregate": 1, "cursor": {}, "pipeline": [ { "$changeStream": { "allChangesForCluster": true } } ] }, "database_name": "admin" } } ] } ] } mongodb-mongo-python-driver-509e9b7/test/retryable_reads/legacy/changeStreams-client.watch.json000066400000000000000000000105771462766011000331010ustar00rootroot00000000000000{ "runOn": [ { "minServerVersion": "4.0", "topology": [ "replicaset" ] }, { "minServerVersion": "4.1.7", "topology": [ "sharded", "load-balanced" ], "serverless": "forbid" } ], "database_name": "retryable-reads-tests", "collection_name": "coll", "data": [ { "_id": 1, "x": 11 } ], "tests": [ { "description": "client.watch succeeds on first attempt", "operations": [ { "name": "watch", "object": "client" } ], "expectations": [ { "command_started_event": { "command": { "aggregate": 1, "cursor": {}, "pipeline": [ { "$changeStream": { "allChangesForCluster": true } } ] }, "database_name": "admin" } } ] }, { "description": "client.watch succeeds on second attempt", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "aggregate" ], "closeConnection": true } }, "operations": [ { "name": "watch", "object": "client" } ], "expectations": [ { "command_started_event": { "command": { "aggregate": 1, "cursor": {}, "pipeline": [ { "$changeStream": { "allChangesForCluster": true } } ] }, "database_name": "admin" } }, { "command_started_event": { "command": { "aggregate": 1, "cursor": {}, "pipeline": [ { "$changeStream": { "allChangesForCluster": true } } ] }, "database_name": "admin" } } ] }, { "description": "client.watch fails on first attempt", "clientOptions": { "retryReads": false }, "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "aggregate" ], "closeConnection": true } }, "operations": [ { "name": "watch", "object": "client", "error": true } ], "expectations": [ { "command_started_event": { "command": { "aggregate": 1, "cursor": {}, "pipeline": [ { "$changeStream": { "allChangesForCluster": true } } ] }, "database_name": "admin" } } ] }, { "description": "client.watch fails on second attempt", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 2 }, "data": { "failCommands": [ "aggregate" ], "closeConnection": true } }, "operations": [ { "name": "watch", "object": "client", "error": true } ], "expectations": [ { "command_started_event": { "command": { "aggregate": 1, "cursor": {}, "pipeline": [ { "$changeStream": { "allChangesForCluster": true } } ] }, "database_name": "admin" } }, { "command_started_event": { "command": { "aggregate": 1, "cursor": {}, "pipeline": [ { "$changeStream": { "allChangesForCluster": true } } ] }, "database_name": "admin" } } ] } ] } changeStreams-db.coll.watch-serverErrors.json000066400000000000000000000360421462766011000355550ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/retryable_reads/legacy{ "runOn": [ { "minServerVersion": "4.0", "topology": [ "replicaset" ] }, { "minServerVersion": "4.1.7", "topology": [ "sharded", "load-balanced" ], "serverless": "forbid" } ], "database_name": "retryable-reads-tests", "collection_name": "coll", "data": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 22 }, { "_id": 3, "x": 33 } ], "tests": [ { "description": "db.coll.watch succeeds after InterruptedAtShutdown", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "aggregate" ], "errorCode": 11600 } }, "operations": [ { "name": "watch", "object": "collection" } ], "expectations": [ { "command_started_event": { "command": { "aggregate": "coll", "cursor": {}, "pipeline": [ { "$changeStream": {} } ] }, "database_name": "retryable-reads-tests" } }, { "command_started_event": { "command": { "aggregate": "coll", "cursor": {}, "pipeline": [ { "$changeStream": {} } ] }, "database_name": "retryable-reads-tests" } } ] }, { "description": "db.coll.watch succeeds after InterruptedDueToReplStateChange", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "aggregate" ], "errorCode": 11602 } }, "operations": [ { "name": "watch", "object": "collection" } ], "expectations": [ { "command_started_event": { "command": { "aggregate": "coll", "cursor": {}, "pipeline": [ { "$changeStream": {} } ] }, "database_name": "retryable-reads-tests" } }, { "command_started_event": { "command": { "aggregate": "coll", "cursor": {}, "pipeline": [ { "$changeStream": {} } ] }, "database_name": "retryable-reads-tests" } } ] }, { "description": "db.coll.watch succeeds after NotWritablePrimary", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "aggregate" ], "errorCode": 10107 } }, "operations": [ { "name": "watch", "object": "collection" } ], "expectations": [ { "command_started_event": { "command": { "aggregate": "coll", "cursor": {}, "pipeline": [ { "$changeStream": {} } ] }, "database_name": "retryable-reads-tests" } }, { "command_started_event": { "command": { "aggregate": "coll", "cursor": {}, "pipeline": [ { "$changeStream": {} } ] }, "database_name": "retryable-reads-tests" } } ] }, { "description": "db.coll.watch succeeds after NotPrimaryNoSecondaryOk", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "aggregate" ], "errorCode": 13435 } }, "operations": [ { "name": "watch", "object": "collection" } ], "expectations": [ { "command_started_event": { "command": { "aggregate": "coll", "cursor": {}, "pipeline": [ { "$changeStream": {} } ] }, "database_name": "retryable-reads-tests" } }, { "command_started_event": { "command": { "aggregate": "coll", "cursor": {}, "pipeline": [ { "$changeStream": {} } ] }, "database_name": "retryable-reads-tests" } } ] }, { "description": "db.coll.watch succeeds after NotPrimaryOrSecondary", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "aggregate" ], "errorCode": 13436 } }, "operations": [ { "name": "watch", "object": "collection" } ], "expectations": [ { "command_started_event": { "command": { "aggregate": "coll", "cursor": {}, "pipeline": [ { "$changeStream": {} } ] }, "database_name": "retryable-reads-tests" } }, { "command_started_event": { "command": { "aggregate": "coll", "cursor": {}, "pipeline": [ { "$changeStream": {} } ] }, "database_name": "retryable-reads-tests" } } ] }, { "description": "db.coll.watch succeeds after PrimarySteppedDown", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "aggregate" ], "errorCode": 189 } }, "operations": [ { "name": "watch", "object": "collection" } ], "expectations": [ { "command_started_event": { "command": { "aggregate": "coll", "cursor": {}, "pipeline": [ { "$changeStream": {} } ] }, "database_name": "retryable-reads-tests" } }, { "command_started_event": { "command": { "aggregate": "coll", "cursor": {}, "pipeline": [ { "$changeStream": {} } ] }, "database_name": "retryable-reads-tests" } } ] }, { "description": "db.coll.watch succeeds after ShutdownInProgress", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "aggregate" ], "errorCode": 91 } }, "operations": [ { "name": "watch", "object": "collection" } ], "expectations": [ { "command_started_event": { "command": { "aggregate": "coll", "cursor": {}, "pipeline": [ { "$changeStream": {} } ] }, "database_name": "retryable-reads-tests" } }, { "command_started_event": { "command": { "aggregate": "coll", "cursor": {}, "pipeline": [ { "$changeStream": {} } ] }, "database_name": "retryable-reads-tests" } } ] }, { "description": "db.coll.watch succeeds after HostNotFound", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "aggregate" ], "errorCode": 7 } }, "operations": [ { "name": "watch", "object": "collection" } ], "expectations": [ { "command_started_event": { "command": { "aggregate": "coll", "cursor": {}, "pipeline": [ { "$changeStream": {} } ] }, "database_name": "retryable-reads-tests" } }, { "command_started_event": { "command": { "aggregate": "coll", "cursor": {}, "pipeline": [ { "$changeStream": {} } ] }, "database_name": "retryable-reads-tests" } } ] }, { "description": "db.coll.watch succeeds after HostUnreachable", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "aggregate" ], "errorCode": 6 } }, "operations": [ { "name": "watch", "object": "collection" } ], "expectations": [ { "command_started_event": { "command": { "aggregate": "coll", "cursor": {}, "pipeline": [ { "$changeStream": {} } ] }, "database_name": "retryable-reads-tests" } }, { "command_started_event": { "command": { "aggregate": "coll", "cursor": {}, "pipeline": [ { "$changeStream": {} } ] }, "database_name": "retryable-reads-tests" } } ] }, { "description": "db.coll.watch succeeds after NetworkTimeout", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "aggregate" ], "errorCode": 89 } }, "operations": [ { "name": "watch", "object": "collection" } ], "expectations": [ { "command_started_event": { "command": { "aggregate": "coll", "cursor": {}, "pipeline": [ { "$changeStream": {} } ] }, "database_name": "retryable-reads-tests" } }, { "command_started_event": { "command": { "aggregate": "coll", "cursor": {}, "pipeline": [ { "$changeStream": {} } ] }, "database_name": "retryable-reads-tests" } } ] }, { "description": "db.coll.watch succeeds after SocketException", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "aggregate" ], "errorCode": 9001 } }, "operations": [ { "name": "watch", "object": "collection" } ], "expectations": [ { "command_started_event": { "command": { "aggregate": "coll", "cursor": {}, "pipeline": [ { "$changeStream": {} } ] }, "database_name": "retryable-reads-tests" } }, { "command_started_event": { "command": { "aggregate": "coll", "cursor": {}, "pipeline": [ { "$changeStream": {} } ] }, "database_name": "retryable-reads-tests" } } ] }, { "description": "db.coll.watch fails after two NotWritablePrimary errors", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 2 }, "data": { "failCommands": [ "aggregate" ], "errorCode": 10107 } }, "operations": [ { "name": "watch", "object": "collection", "error": true } ], "expectations": [ { "command_started_event": { "command": { "aggregate": "coll", "cursor": {}, "pipeline": [ { "$changeStream": {} } ] }, "database_name": "retryable-reads-tests" } }, { "command_started_event": { "command": { "aggregate": "coll", "cursor": {}, "pipeline": [ { "$changeStream": {} } ] }, "database_name": "retryable-reads-tests" } } ] }, { "description": "db.coll.watch fails after NotWritablePrimary when retryReads is false", "clientOptions": { "retryReads": false }, "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "aggregate" ], "errorCode": 10107 } }, "operations": [ { "name": "watch", "object": "collection", "error": true } ], "expectations": [ { "command_started_event": { "command": { "aggregate": "coll", "cursor": {}, "pipeline": [ { "$changeStream": {} } ] }, "database_name": "retryable-reads-tests" } } ] } ] } mongodb-mongo-python-driver-509e9b7/test/retryable_reads/legacy/changeStreams-db.coll.watch.json000066400000000000000000000101711462766011000331260ustar00rootroot00000000000000{ "runOn": [ { "minServerVersion": "4.0", "topology": [ "replicaset" ] }, { "minServerVersion": "4.1.7", "topology": [ "sharded", "load-balanced" ], "serverless": "forbid" } ], "database_name": "retryable-reads-tests", "collection_name": "coll", "data": [ { "_id": 1, "x": 11 } ], "tests": [ { "description": "db.coll.watch succeeds on first attempt", "operations": [ { "name": "watch", "object": "collection" } ], "expectations": [ { "command_started_event": { "command": { "aggregate": "coll", "cursor": {}, "pipeline": [ { "$changeStream": {} } ] }, "database_name": "retryable-reads-tests" } } ] }, { "description": "db.coll.watch succeeds on second attempt", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "aggregate" ], "closeConnection": true } }, "operations": [ { "name": "watch", "object": "collection" } ], "expectations": [ { "command_started_event": { "command": { "aggregate": "coll", "cursor": {}, "pipeline": [ { "$changeStream": {} } ] }, "database_name": "retryable-reads-tests" } }, { "command_started_event": { "command": { "aggregate": "coll", "cursor": {}, "pipeline": [ { "$changeStream": {} } ] }, "database_name": "retryable-reads-tests" } } ] }, { "description": "db.coll.watch fails on first attempt", "clientOptions": { "retryReads": false }, "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "aggregate" ], "closeConnection": true } }, "operations": [ { "name": "watch", "object": "collection", "error": true } ], "expectations": [ { "command_started_event": { "command": { "aggregate": "coll", "cursor": {}, "pipeline": [ { "$changeStream": {} } ] }, "database_name": "retryable-reads-tests" } } ] }, { "description": "db.coll.watch fails on second attempt", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 2 }, "data": { "failCommands": [ "aggregate" ], "closeConnection": true } }, "operations": [ { "name": "watch", "object": "collection", "error": true } ], "expectations": [ { "command_started_event": { "command": { "aggregate": "coll", "cursor": {}, "pipeline": [ { "$changeStream": {} } ] }, "database_name": "retryable-reads-tests" } }, { "command_started_event": { "command": { "aggregate": "coll", "cursor": {}, "pipeline": [ { "$changeStream": {} } ] }, "database_name": "retryable-reads-tests" } } ] } ] } changeStreams-db.watch-serverErrors.json000066400000000000000000000355121462766011000346260ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/retryable_reads/legacy{ "runOn": [ { "minServerVersion": "4.0", "topology": [ "replicaset" ] }, { "minServerVersion": "4.1.7", "topology": [ "sharded", "load-balanced" ], "serverless": "forbid" } ], "database_name": "retryable-reads-tests", "collection_name": "coll", "data": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 22 }, { "_id": 3, "x": 33 } ], "tests": [ { "description": "db.watch succeeds after InterruptedAtShutdown", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "aggregate" ], "errorCode": 11600 } }, "operations": [ { "name": "watch", "object": "database" } ], "expectations": [ { "command_started_event": { "command": { "aggregate": 1, "cursor": {}, "pipeline": [ { "$changeStream": {} } ] }, "database_name": "retryable-reads-tests" } }, { "command_started_event": { "command": { "aggregate": 1, "cursor": {}, "pipeline": [ { "$changeStream": {} } ] }, "database_name": "retryable-reads-tests" } } ] }, { "description": "db.watch succeeds after InterruptedDueToReplStateChange", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "aggregate" ], "errorCode": 11602 } }, "operations": [ { "name": "watch", "object": "database" } ], "expectations": [ { "command_started_event": { "command": { "aggregate": 1, "cursor": {}, "pipeline": [ { "$changeStream": {} } ] }, "database_name": "retryable-reads-tests" } }, { "command_started_event": { "command": { "aggregate": 1, "cursor": {}, "pipeline": [ { "$changeStream": {} } ] }, "database_name": "retryable-reads-tests" } } ] }, { "description": "db.watch succeeds after NotWritablePrimary", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "aggregate" ], "errorCode": 10107 } }, "operations": [ { "name": "watch", "object": "database" } ], "expectations": [ { "command_started_event": { "command": { "aggregate": 1, "cursor": {}, "pipeline": [ { "$changeStream": {} } ] }, "database_name": "retryable-reads-tests" } }, { "command_started_event": { "command": { "aggregate": 1, "cursor": {}, "pipeline": [ { "$changeStream": {} } ] }, "database_name": "retryable-reads-tests" } } ] }, { "description": "db.watch succeeds after NotPrimaryNoSecondaryOk", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "aggregate" ], "errorCode": 13435 } }, "operations": [ { "name": "watch", "object": "database" } ], "expectations": [ { "command_started_event": { "command": { "aggregate": 1, "cursor": {}, "pipeline": [ { "$changeStream": {} } ] }, "database_name": "retryable-reads-tests" } }, { "command_started_event": { "command": { "aggregate": 1, "cursor": {}, "pipeline": [ { "$changeStream": {} } ] }, "database_name": "retryable-reads-tests" } } ] }, { "description": "db.watch succeeds after NotPrimaryOrSecondary", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "aggregate" ], "errorCode": 13436 } }, "operations": [ { "name": "watch", "object": "database" } ], "expectations": [ { "command_started_event": { "command": { "aggregate": 1, "cursor": {}, "pipeline": [ { "$changeStream": {} } ] }, "database_name": "retryable-reads-tests" } }, { "command_started_event": { "command": { "aggregate": 1, "cursor": {}, "pipeline": [ { "$changeStream": {} } ] }, "database_name": "retryable-reads-tests" } } ] }, { "description": "db.watch succeeds after PrimarySteppedDown", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "aggregate" ], "errorCode": 189 } }, "operations": [ { "name": "watch", "object": "database" } ], "expectations": [ { "command_started_event": { "command": { "aggregate": 1, "cursor": {}, "pipeline": [ { "$changeStream": {} } ] }, "database_name": "retryable-reads-tests" } }, { "command_started_event": { "command": { "aggregate": 1, "cursor": {}, "pipeline": [ { "$changeStream": {} } ] }, "database_name": "retryable-reads-tests" } } ] }, { "description": "db.watch succeeds after ShutdownInProgress", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "aggregate" ], "errorCode": 91 } }, "operations": [ { "name": "watch", "object": "database" } ], "expectations": [ { "command_started_event": { "command": { "aggregate": 1, "cursor": {}, "pipeline": [ { "$changeStream": {} } ] }, "database_name": "retryable-reads-tests" } }, { "command_started_event": { "command": { "aggregate": 1, "cursor": {}, "pipeline": [ { "$changeStream": {} } ] }, "database_name": "retryable-reads-tests" } } ] }, { "description": "db.watch succeeds after HostNotFound", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "aggregate" ], "errorCode": 7 } }, "operations": [ { "name": "watch", "object": "database" } ], "expectations": [ { "command_started_event": { "command": { "aggregate": 1, "cursor": {}, "pipeline": [ { "$changeStream": {} } ] }, "database_name": "retryable-reads-tests" } }, { "command_started_event": { "command": { "aggregate": 1, "cursor": {}, "pipeline": [ { "$changeStream": {} } ] }, "database_name": "retryable-reads-tests" } } ] }, { "description": "db.watch succeeds after HostUnreachable", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "aggregate" ], "errorCode": 6 } }, "operations": [ { "name": "watch", "object": "database" } ], "expectations": [ { "command_started_event": { "command": { "aggregate": 1, "cursor": {}, "pipeline": [ { "$changeStream": {} } ] }, "database_name": "retryable-reads-tests" } }, { "command_started_event": { "command": { "aggregate": 1, "cursor": {}, "pipeline": [ { "$changeStream": {} } ] }, "database_name": "retryable-reads-tests" } } ] }, { "description": "db.watch succeeds after NetworkTimeout", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "aggregate" ], "errorCode": 89 } }, "operations": [ { "name": "watch", "object": "database" } ], "expectations": [ { "command_started_event": { "command": { "aggregate": 1, "cursor": {}, "pipeline": [ { "$changeStream": {} } ] }, "database_name": "retryable-reads-tests" } }, { "command_started_event": { "command": { "aggregate": 1, "cursor": {}, "pipeline": [ { "$changeStream": {} } ] }, "database_name": "retryable-reads-tests" } } ] }, { "description": "db.watch succeeds after SocketException", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "aggregate" ], "errorCode": 9001 } }, "operations": [ { "name": "watch", "object": "database" } ], "expectations": [ { "command_started_event": { "command": { "aggregate": 1, "cursor": {}, "pipeline": [ { "$changeStream": {} } ] }, "database_name": "retryable-reads-tests" } }, { "command_started_event": { "command": { "aggregate": 1, "cursor": {}, "pipeline": [ { "$changeStream": {} } ] }, "database_name": "retryable-reads-tests" } } ] }, { "description": "db.watch fails after two NotWritablePrimary errors", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 2 }, "data": { "failCommands": [ "aggregate" ], "errorCode": 10107 } }, "operations": [ { "name": "watch", "object": "database", "error": true } ], "expectations": [ { "command_started_event": { "command": { "aggregate": 1, "cursor": {}, "pipeline": [ { "$changeStream": {} } ] }, "database_name": "retryable-reads-tests" } }, { "command_started_event": { "command": { "aggregate": 1, "cursor": {}, "pipeline": [ { "$changeStream": {} } ] }, "database_name": "retryable-reads-tests" } } ] }, { "description": "db.watch fails after NotWritablePrimary when retryReads is false", "clientOptions": { "retryReads": false }, "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "aggregate" ], "errorCode": 10107 } }, "operations": [ { "name": "watch", "object": "database", "error": true } ], "expectations": [ { "command_started_event": { "command": { "aggregate": 1, "cursor": {}, "pipeline": [ { "$changeStream": {} } ] }, "database_name": "retryable-reads-tests" } } ] } ] } mongodb-mongo-python-driver-509e9b7/test/retryable_reads/legacy/changeStreams-db.watch.json000066400000000000000000000100771462766011000322030ustar00rootroot00000000000000{ "runOn": [ { "minServerVersion": "4.0", "topology": [ "replicaset" ] }, { "minServerVersion": "4.1.7", "topology": [ "sharded", "load-balanced" ], "serverless": "forbid" } ], "database_name": "retryable-reads-tests", "collection_name": "coll", "data": [ { "_id": 1, "x": 11 } ], "tests": [ { "description": "db.watch succeeds on first attempt", "operations": [ { "name": "watch", "object": "database" } ], "expectations": [ { "command_started_event": { "command": { "aggregate": 1, "cursor": {}, "pipeline": [ { "$changeStream": {} } ] }, "database_name": "retryable-reads-tests" } } ] }, { "description": "db.watch succeeds on second attempt", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "aggregate" ], "closeConnection": true } }, "operations": [ { "name": "watch", "object": "database" } ], "expectations": [ { "command_started_event": { "command": { "aggregate": 1, "cursor": {}, "pipeline": [ { "$changeStream": {} } ] }, "database_name": "retryable-reads-tests" } }, { "command_started_event": { "command": { "aggregate": 1, "cursor": {}, "pipeline": [ { "$changeStream": {} } ] }, "database_name": "retryable-reads-tests" } } ] }, { "description": "db.watch fails on first attempt", "clientOptions": { "retryReads": false }, "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "aggregate" ], "closeConnection": true } }, "operations": [ { "name": "watch", "object": "database", "error": true } ], "expectations": [ { "command_started_event": { "command": { "aggregate": 1, "cursor": {}, "pipeline": [ { "$changeStream": {} } ] }, "database_name": "retryable-reads-tests" } } ] }, { "description": "db.watch fails on second attempt", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 2 }, "data": { "failCommands": [ "aggregate" ], "closeConnection": true } }, "operations": [ { "name": "watch", "object": "database", "error": true } ], "expectations": [ { "command_started_event": { "command": { "aggregate": 1, "cursor": {}, "pipeline": [ { "$changeStream": {} } ] }, "database_name": "retryable-reads-tests" } }, { "command_started_event": { "command": { "aggregate": 1, "cursor": {}, "pipeline": [ { "$changeStream": {} } ] }, "database_name": "retryable-reads-tests" } } ] } ] } mongodb-mongo-python-driver-509e9b7/test/retryable_reads/legacy/count-serverErrors.json000066400000000000000000000303001462766011000315470ustar00rootroot00000000000000{ "runOn": [ { "minServerVersion": "4.0", "topology": [ "single", "replicaset" ] }, { "minServerVersion": "4.1.7", "topology": [ "sharded", "load-balanced" ] } ], "database_name": "retryable-reads-tests", "collection_name": "coll", "data": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 22 } ], "tests": [ { "description": "Count succeeds after InterruptedAtShutdown", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "count" ], "errorCode": 11600 } }, "operations": [ { "name": "count", "object": "collection", "arguments": { "filter": {} }, "result": 2 } ], "expectations": [ { "command_started_event": { "command": { "count": "coll" }, "database_name": "retryable-reads-tests" } }, { "command_started_event": { "command": { "count": "coll" }, "database_name": "retryable-reads-tests" } } ] }, { "description": "Count succeeds after InterruptedDueToReplStateChange", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "count" ], "errorCode": 11602 } }, "operations": [ { "name": "count", "object": "collection", "arguments": { "filter": {} }, "result": 2 } ], "expectations": [ { "command_started_event": { "command": { "count": "coll" }, "database_name": "retryable-reads-tests" } }, { "command_started_event": { "command": { "count": "coll" }, "database_name": "retryable-reads-tests" } } ] }, { "description": "Count succeeds after NotWritablePrimary", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "count" ], "errorCode": 10107 } }, "operations": [ { "name": "count", "object": "collection", "arguments": { "filter": {} }, "result": 2 } ], "expectations": [ { "command_started_event": { "command": { "count": "coll" }, "database_name": "retryable-reads-tests" } }, { "command_started_event": { "command": { "count": "coll" }, "database_name": "retryable-reads-tests" } } ] }, { "description": "Count succeeds after NotPrimaryNoSecondaryOk", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "count" ], "errorCode": 13435 } }, "operations": [ { "name": "count", "object": "collection", "arguments": { "filter": {} }, "result": 2 } ], "expectations": [ { "command_started_event": { "command": { "count": "coll" }, "database_name": "retryable-reads-tests" } }, { "command_started_event": { "command": { "count": "coll" }, "database_name": "retryable-reads-tests" } } ] }, { "description": "Count succeeds after NotPrimaryOrSecondary", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "count" ], "errorCode": 13436 } }, "operations": [ { "name": "count", "object": "collection", "arguments": { "filter": {} }, "result": 2 } ], "expectations": [ { "command_started_event": { "command": { "count": "coll" }, "database_name": "retryable-reads-tests" } }, { "command_started_event": { "command": { "count": "coll" }, "database_name": "retryable-reads-tests" } } ] }, { "description": "Count succeeds after PrimarySteppedDown", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "count" ], "errorCode": 189 } }, "operations": [ { "name": "count", "object": "collection", "arguments": { "filter": {} }, "result": 2 } ], "expectations": [ { "command_started_event": { "command": { "count": "coll" }, "database_name": "retryable-reads-tests" } }, { "command_started_event": { "command": { "count": "coll" }, "database_name": "retryable-reads-tests" } } ] }, { "description": "Count succeeds after ShutdownInProgress", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "count" ], "errorCode": 91 } }, "operations": [ { "name": "count", "object": "collection", "arguments": { "filter": {} }, "result": 2 } ], "expectations": [ { "command_started_event": { "command": { "count": "coll" }, "database_name": "retryable-reads-tests" } }, { "command_started_event": { "command": { "count": "coll" }, "database_name": "retryable-reads-tests" } } ] }, { "description": "Count succeeds after HostNotFound", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "count" ], "errorCode": 7 } }, "operations": [ { "name": "count", "object": "collection", "arguments": { "filter": {} }, "result": 2 } ], "expectations": [ { "command_started_event": { "command": { "count": "coll" }, "database_name": "retryable-reads-tests" } }, { "command_started_event": { "command": { "count": "coll" }, "database_name": "retryable-reads-tests" } } ] }, { "description": "Count succeeds after HostUnreachable", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "count" ], "errorCode": 6 } }, "operations": [ { "name": "count", "object": "collection", "arguments": { "filter": {} }, "result": 2 } ], "expectations": [ { "command_started_event": { "command": { "count": "coll" }, "database_name": "retryable-reads-tests" } }, { "command_started_event": { "command": { "count": "coll" }, "database_name": "retryable-reads-tests" } } ] }, { "description": "Count succeeds after NetworkTimeout", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "count" ], "errorCode": 89 } }, "operations": [ { "name": "count", "object": "collection", "arguments": { "filter": {} }, "result": 2 } ], "expectations": [ { "command_started_event": { "command": { "count": "coll" }, "database_name": "retryable-reads-tests" } }, { "command_started_event": { "command": { "count": "coll" }, "database_name": "retryable-reads-tests" } } ] }, { "description": "Count succeeds after SocketException", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "count" ], "errorCode": 9001 } }, "operations": [ { "name": "count", "object": "collection", "arguments": { "filter": {} }, "result": 2 } ], "expectations": [ { "command_started_event": { "command": { "count": "coll" }, "database_name": "retryable-reads-tests" } }, { "command_started_event": { "command": { "count": "coll" }, "database_name": "retryable-reads-tests" } } ] }, { "description": "Count fails after two NotWritablePrimary errors", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 2 }, "data": { "failCommands": [ "count" ], "errorCode": 10107 } }, "operations": [ { "name": "count", "object": "collection", "arguments": { "filter": {} }, "error": true } ], "expectations": [ { "command_started_event": { "command": { "count": "coll" }, "database_name": "retryable-reads-tests" } }, { "command_started_event": { "command": { "count": "coll" }, "database_name": "retryable-reads-tests" } } ] }, { "description": "Count fails after NotWritablePrimary when retryReads is false", "clientOptions": { "retryReads": false }, "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "count" ], "errorCode": 10107 } }, "operations": [ { "name": "count", "object": "collection", "arguments": { "filter": {} }, "error": true } ], "expectations": [ { "command_started_event": { "command": { "count": "coll" }, "database_name": "retryable-reads-tests" } } ] } ] } mongodb-mongo-python-driver-509e9b7/test/retryable_reads/legacy/count.json000066400000000000000000000070141462766011000270540ustar00rootroot00000000000000{ "runOn": [ { "minServerVersion": "4.0", "topology": [ "single", "replicaset" ] }, { "minServerVersion": "4.1.7", "topology": [ "sharded", "load-balanced" ] } ], "database_name": "retryable-reads-tests", "collection_name": "coll", "data": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 22 } ], "tests": [ { "description": "Count succeeds on first attempt", "operations": [ { "name": "count", "object": "collection", "arguments": { "filter": {} }, "result": 2 } ], "expectations": [ { "command_started_event": { "command": { "count": "coll" }, "database_name": "retryable-reads-tests" } } ] }, { "description": "Count succeeds on second attempt", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "count" ], "closeConnection": true } }, "operations": [ { "name": "count", "object": "collection", "arguments": { "filter": {} }, "result": 2 } ], "expectations": [ { "command_started_event": { "command": { "count": "coll" }, "database_name": "retryable-reads-tests" } }, { "command_started_event": { "command": { "count": "coll" }, "database_name": "retryable-reads-tests" } } ] }, { "description": "Count fails on first attempt", "clientOptions": { "retryReads": false }, "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "count" ], "closeConnection": true } }, "operations": [ { "name": "count", "object": "collection", "arguments": { "filter": {} }, "error": true } ], "expectations": [ { "command_started_event": { "command": { "count": "coll" }, "database_name": "retryable-reads-tests" } } ] }, { "description": "Count fails on second attempt", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 2 }, "data": { "failCommands": [ "count" ], "closeConnection": true } }, "operations": [ { "name": "count", "object": "collection", "arguments": { "filter": {} }, "error": true } ], "expectations": [ { "command_started_event": { "command": { "count": "coll" }, "database_name": "retryable-reads-tests" } }, { "command_started_event": { "command": { "count": "coll" }, "database_name": "retryable-reads-tests" } } ] } ] } mongodb-mongo-python-driver-509e9b7/test/retryable_reads/legacy/countDocuments-serverErrors.json000066400000000000000000000502101462766011000334330ustar00rootroot00000000000000{ "runOn": [ { "minServerVersion": "4.0", "topology": [ "single", "replicaset" ] }, { "minServerVersion": "4.1.7", "topology": [ "sharded", "load-balanced" ] } ], "database_name": "retryable-reads-tests", "collection_name": "coll", "data": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 22 } ], "tests": [ { "description": "CountDocuments succeeds after InterruptedAtShutdown", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "aggregate" ], "errorCode": 11600 } }, "operations": [ { "name": "countDocuments", "object": "collection", "arguments": { "filter": {} }, "result": 2 } ], "expectations": [ { "command_started_event": { "command": { "aggregate": "coll", "pipeline": [ { "$match": {} }, { "$group": { "_id": 1, "n": { "$sum": 1 } } } ] }, "database_name": "retryable-reads-tests" } }, { "command_started_event": { "command": { "aggregate": "coll", "pipeline": [ { "$match": {} }, { "$group": { "_id": 1, "n": { "$sum": 1 } } } ] }, "database_name": "retryable-reads-tests" } } ] }, { "description": "CountDocuments succeeds after InterruptedDueToReplStateChange", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "aggregate" ], "errorCode": 11602 } }, "operations": [ { "name": "countDocuments", "object": "collection", "arguments": { "filter": {} }, "result": 2 } ], "expectations": [ { "command_started_event": { "command": { "aggregate": "coll", "pipeline": [ { "$match": {} }, { "$group": { "_id": 1, "n": { "$sum": 1 } } } ] }, "database_name": "retryable-reads-tests" } }, { "command_started_event": { "command": { "aggregate": "coll", "pipeline": [ { "$match": {} }, { "$group": { "_id": 1, "n": { "$sum": 1 } } } ] }, "database_name": "retryable-reads-tests" } } ] }, { "description": "CountDocuments succeeds after NotWritablePrimary", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "aggregate" ], "errorCode": 10107 } }, "operations": [ { "name": "countDocuments", "object": "collection", "arguments": { "filter": {} }, "result": 2 } ], "expectations": [ { "command_started_event": { "command": { "aggregate": "coll", "pipeline": [ { "$match": {} }, { "$group": { "_id": 1, "n": { "$sum": 1 } } } ] }, "database_name": "retryable-reads-tests" } }, { "command_started_event": { "command": { "aggregate": "coll", "pipeline": [ { "$match": {} }, { "$group": { "_id": 1, "n": { "$sum": 1 } } } ] }, "database_name": "retryable-reads-tests" } } ] }, { "description": "CountDocuments succeeds after NotPrimaryNoSecondaryOk", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "aggregate" ], "errorCode": 13435 } }, "operations": [ { "name": "countDocuments", "object": "collection", "arguments": { "filter": {} }, "result": 2 } ], "expectations": [ { "command_started_event": { "command": { "aggregate": "coll", "pipeline": [ { "$match": {} }, { "$group": { "_id": 1, "n": { "$sum": 1 } } } ] }, "database_name": "retryable-reads-tests" } }, { "command_started_event": { "command": { "aggregate": "coll", "pipeline": [ { "$match": {} }, { "$group": { "_id": 1, "n": { "$sum": 1 } } } ] }, "database_name": "retryable-reads-tests" } } ] }, { "description": "CountDocuments succeeds after NotPrimaryOrSecondary", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "aggregate" ], "errorCode": 13436 } }, "operations": [ { "name": "countDocuments", "object": "collection", "arguments": { "filter": {} }, "result": 2 } ], "expectations": [ { "command_started_event": { "command": { "aggregate": "coll", "pipeline": [ { "$match": {} }, { "$group": { "_id": 1, "n": { "$sum": 1 } } } ] }, "database_name": "retryable-reads-tests" } }, { "command_started_event": { "command": { "aggregate": "coll", "pipeline": [ { "$match": {} }, { "$group": { "_id": 1, "n": { "$sum": 1 } } } ] }, "database_name": "retryable-reads-tests" } } ] }, { "description": "CountDocuments succeeds after PrimarySteppedDown", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "aggregate" ], "errorCode": 189 } }, "operations": [ { "name": "countDocuments", "object": "collection", "arguments": { "filter": {} }, "result": 2 } ], "expectations": [ { "command_started_event": { "command": { "aggregate": "coll", "pipeline": [ { "$match": {} }, { "$group": { "_id": 1, "n": { "$sum": 1 } } } ] }, "database_name": "retryable-reads-tests" } }, { "command_started_event": { "command": { "aggregate": "coll", "pipeline": [ { "$match": {} }, { "$group": { "_id": 1, "n": { "$sum": 1 } } } ] }, "database_name": "retryable-reads-tests" } } ] }, { "description": "CountDocuments succeeds after ShutdownInProgress", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "aggregate" ], "errorCode": 91 } }, "operations": [ { "name": "countDocuments", "object": "collection", "arguments": { "filter": {} }, "result": 2 } ], "expectations": [ { "command_started_event": { "command": { "aggregate": "coll", "pipeline": [ { "$match": {} }, { "$group": { "_id": 1, "n": { "$sum": 1 } } } ] }, "database_name": "retryable-reads-tests" } }, { "command_started_event": { "command": { "aggregate": "coll", "pipeline": [ { "$match": {} }, { "$group": { "_id": 1, "n": { "$sum": 1 } } } ] }, "database_name": "retryable-reads-tests" } } ] }, { "description": "CountDocuments succeeds after HostNotFound", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "aggregate" ], "errorCode": 7 } }, "operations": [ { "name": "countDocuments", "object": "collection", "arguments": { "filter": {} }, "result": 2 } ], "expectations": [ { "command_started_event": { "command": { "aggregate": "coll", "pipeline": [ { "$match": {} }, { "$group": { "_id": 1, "n": { "$sum": 1 } } } ] }, "database_name": "retryable-reads-tests" } }, { "command_started_event": { "command": { "aggregate": "coll", "pipeline": [ { "$match": {} }, { "$group": { "_id": 1, "n": { "$sum": 1 } } } ] }, "database_name": "retryable-reads-tests" } } ] }, { "description": "CountDocuments succeeds after HostUnreachable", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "aggregate" ], "errorCode": 6 } }, "operations": [ { "name": "countDocuments", "object": "collection", "arguments": { "filter": {} }, "result": 2 } ], "expectations": [ { "command_started_event": { "command": { "aggregate": "coll", "pipeline": [ { "$match": {} }, { "$group": { "_id": 1, "n": { "$sum": 1 } } } ] }, "database_name": "retryable-reads-tests" } }, { "command_started_event": { "command": { "aggregate": "coll", "pipeline": [ { "$match": {} }, { "$group": { "_id": 1, "n": { "$sum": 1 } } } ] }, "database_name": "retryable-reads-tests" } } ] }, { "description": "CountDocuments succeeds after NetworkTimeout", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "aggregate" ], "errorCode": 89 } }, "operations": [ { "name": "countDocuments", "object": "collection", "arguments": { "filter": {} }, "result": 2 } ], "expectations": [ { "command_started_event": { "command": { "aggregate": "coll", "pipeline": [ { "$match": {} }, { "$group": { "_id": 1, "n": { "$sum": 1 } } } ] }, "database_name": "retryable-reads-tests" } }, { "command_started_event": { "command": { "aggregate": "coll", "pipeline": [ { "$match": {} }, { "$group": { "_id": 1, "n": { "$sum": 1 } } } ] }, "database_name": "retryable-reads-tests" } } ] }, { "description": "CountDocuments succeeds after SocketException", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "aggregate" ], "errorCode": 9001 } }, "operations": [ { "name": "countDocuments", "object": "collection", "arguments": { "filter": {} }, "result": 2 } ], "expectations": [ { "command_started_event": { "command": { "aggregate": "coll", "pipeline": [ { "$match": {} }, { "$group": { "_id": 1, "n": { "$sum": 1 } } } ] }, "database_name": "retryable-reads-tests" } }, { "command_started_event": { "command": { "aggregate": "coll", "pipeline": [ { "$match": {} }, { "$group": { "_id": 1, "n": { "$sum": 1 } } } ] }, "database_name": "retryable-reads-tests" } } ] }, { "description": "CountDocuments fails after two NotWritablePrimary errors", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 2 }, "data": { "failCommands": [ "aggregate" ], "errorCode": 10107 } }, "operations": [ { "name": "countDocuments", "object": "collection", "arguments": { "filter": {} }, "error": true } ], "expectations": [ { "command_started_event": { "command": { "aggregate": "coll", "pipeline": [ { "$match": {} }, { "$group": { "_id": 1, "n": { "$sum": 1 } } } ] }, "database_name": "retryable-reads-tests" } }, { "command_started_event": { "command": { "aggregate": "coll", "pipeline": [ { "$match": {} }, { "$group": { "_id": 1, "n": { "$sum": 1 } } } ] }, "database_name": "retryable-reads-tests" } } ] }, { "description": "CountDocuments fails after NotWritablePrimary when retryReads is false", "clientOptions": { "retryReads": false }, "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "aggregate" ], "errorCode": 10107 } }, "operations": [ { "name": "countDocuments", "object": "collection", "arguments": { "filter": {} }, "error": true } ], "expectations": [ { "command_started_event": { "command": { "aggregate": "coll", "pipeline": [ { "$match": {} }, { "$group": { "_id": 1, "n": { "$sum": 1 } } } ] }, "database_name": "retryable-reads-tests" } } ] } ] } mongodb-mongo-python-driver-509e9b7/test/retryable_reads/legacy/countDocuments.json000066400000000000000000000126741462766011000307460ustar00rootroot00000000000000{ "runOn": [ { "minServerVersion": "4.0", "topology": [ "single", "replicaset" ] }, { "minServerVersion": "4.1.7", "topology": [ "sharded", "load-balanced" ] } ], "database_name": "retryable-reads-tests", "collection_name": "coll", "data": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 22 } ], "tests": [ { "description": "CountDocuments succeeds on first attempt", "operations": [ { "name": "countDocuments", "object": "collection", "arguments": { "filter": {} }, "result": 2 } ], "expectations": [ { "command_started_event": { "command": { "aggregate": "coll", "pipeline": [ { "$match": {} }, { "$group": { "_id": 1, "n": { "$sum": 1 } } } ] }, "database_name": "retryable-reads-tests" } } ] }, { "description": "CountDocuments succeeds on second attempt", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "aggregate" ], "closeConnection": true } }, "operations": [ { "name": "countDocuments", "object": "collection", "arguments": { "filter": {} }, "result": 2 } ], "expectations": [ { "command_started_event": { "command": { "aggregate": "coll", "pipeline": [ { "$match": {} }, { "$group": { "_id": 1, "n": { "$sum": 1 } } } ] }, "database_name": "retryable-reads-tests" } }, { "command_started_event": { "command": { "aggregate": "coll", "pipeline": [ { "$match": {} }, { "$group": { "_id": 1, "n": { "$sum": 1 } } } ] }, "database_name": "retryable-reads-tests" } } ] }, { "description": "CountDocuments fails on first attempt", "clientOptions": { "retryReads": false }, "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "aggregate" ], "closeConnection": true } }, "operations": [ { "name": "countDocuments", "object": "collection", "arguments": { "filter": {} }, "error": true } ], "expectations": [ { "command_started_event": { "command": { "aggregate": "coll", "pipeline": [ { "$match": {} }, { "$group": { "_id": 1, "n": { "$sum": 1 } } } ] }, "database_name": "retryable-reads-tests" } } ] }, { "description": "CountDocuments fails on second attempt", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 2 }, "data": { "failCommands": [ "aggregate" ], "closeConnection": true } }, "operations": [ { "name": "countDocuments", "object": "collection", "arguments": { "filter": {} }, "error": true } ], "expectations": [ { "command_started_event": { "command": { "aggregate": "coll", "pipeline": [ { "$match": {} }, { "$group": { "_id": 1, "n": { "$sum": 1 } } } ] }, "database_name": "retryable-reads-tests" } }, { "command_started_event": { "command": { "aggregate": "coll", "pipeline": [ { "$match": {} }, { "$group": { "_id": 1, "n": { "$sum": 1 } } } ] }, "database_name": "retryable-reads-tests" } } ] } ] } mongodb-mongo-python-driver-509e9b7/test/retryable_reads/legacy/distinct-serverErrors.json000066400000000000000000000431551462766011000322540ustar00rootroot00000000000000{ "runOn": [ { "minServerVersion": "4.0", "topology": [ "single", "replicaset" ] }, { "minServerVersion": "4.1.7", "topology": [ "sharded", "load-balanced" ] } ], "database_name": "retryable-reads-tests", "collection_name": "coll", "data": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 22 }, { "_id": 3, "x": 33 } ], "tests": [ { "description": "Distinct succeeds after InterruptedAtShutdown", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "distinct" ], "errorCode": 11600 } }, "operations": [ { "name": "distinct", "object": "collection", "arguments": { "fieldName": "x", "filter": { "_id": { "$gt": 1 } } }, "result": [ 22, 33 ] } ], "expectations": [ { "command_started_event": { "command": { "distinct": "coll", "key": "x", "query": { "_id": { "$gt": 1 } } }, "database_name": "retryable-reads-tests" } }, { "command_started_event": { "command": { "distinct": "coll", "key": "x", "query": { "_id": { "$gt": 1 } } }, "database_name": "retryable-reads-tests" } } ] }, { "description": "Distinct succeeds after InterruptedDueToReplStateChange", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "distinct" ], "errorCode": 11602 } }, "operations": [ { "name": "distinct", "object": "collection", "arguments": { "fieldName": "x", "filter": { "_id": { "$gt": 1 } } }, "result": [ 22, 33 ] } ], "expectations": [ { "command_started_event": { "command": { "distinct": "coll", "key": "x", "query": { "_id": { "$gt": 1 } } }, "database_name": "retryable-reads-tests" } }, { "command_started_event": { "command": { "distinct": "coll", "key": "x", "query": { "_id": { "$gt": 1 } } }, "database_name": "retryable-reads-tests" } } ] }, { "description": "Distinct succeeds after NotWritablePrimary", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "distinct" ], "errorCode": 10107 } }, "operations": [ { "name": "distinct", "object": "collection", "arguments": { "fieldName": "x", "filter": { "_id": { "$gt": 1 } } }, "result": [ 22, 33 ] } ], "expectations": [ { "command_started_event": { "command": { "distinct": "coll", "key": "x", "query": { "_id": { "$gt": 1 } } }, "database_name": "retryable-reads-tests" } }, { "command_started_event": { "command": { "distinct": "coll", "key": "x", "query": { "_id": { "$gt": 1 } } }, "database_name": "retryable-reads-tests" } } ] }, { "description": "Distinct succeeds after NotPrimaryNoSecondaryOk", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "distinct" ], "errorCode": 13435 } }, "operations": [ { "name": "distinct", "object": "collection", "arguments": { "fieldName": "x", "filter": { "_id": { "$gt": 1 } } }, "result": [ 22, 33 ] } ], "expectations": [ { "command_started_event": { "command": { "distinct": "coll", "key": "x", "query": { "_id": { "$gt": 1 } } }, "database_name": "retryable-reads-tests" } }, { "command_started_event": { "command": { "distinct": "coll", "key": "x", "query": { "_id": { "$gt": 1 } } }, "database_name": "retryable-reads-tests" } } ] }, { "description": "Distinct succeeds after NotPrimaryOrSecondary", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "distinct" ], "errorCode": 13436 } }, "operations": [ { "name": "distinct", "object": "collection", "arguments": { "fieldName": "x", "filter": { "_id": { "$gt": 1 } } }, "result": [ 22, 33 ] } ], "expectations": [ { "command_started_event": { "command": { "distinct": "coll", "key": "x", "query": { "_id": { "$gt": 1 } } }, "database_name": "retryable-reads-tests" } }, { "command_started_event": { "command": { "distinct": "coll", "key": "x", "query": { "_id": { "$gt": 1 } } }, "database_name": "retryable-reads-tests" } } ] }, { "description": "Distinct succeeds after PrimarySteppedDown", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "distinct" ], "errorCode": 189 } }, "operations": [ { "name": "distinct", "object": "collection", "arguments": { "fieldName": "x", "filter": { "_id": { "$gt": 1 } } }, "result": [ 22, 33 ] } ], "expectations": [ { "command_started_event": { "command": { "distinct": "coll", "key": "x", "query": { "_id": { "$gt": 1 } } }, "database_name": "retryable-reads-tests" } }, { "command_started_event": { "command": { "distinct": "coll", "key": "x", "query": { "_id": { "$gt": 1 } } }, "database_name": "retryable-reads-tests" } } ] }, { "description": "Distinct succeeds after ShutdownInProgress", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "distinct" ], "errorCode": 91 } }, "operations": [ { "name": "distinct", "object": "collection", "arguments": { "fieldName": "x", "filter": { "_id": { "$gt": 1 } } }, "result": [ 22, 33 ] } ], "expectations": [ { "command_started_event": { "command": { "distinct": "coll", "key": "x", "query": { "_id": { "$gt": 1 } } }, "database_name": "retryable-reads-tests" } }, { "command_started_event": { "command": { "distinct": "coll", "key": "x", "query": { "_id": { "$gt": 1 } } }, "database_name": "retryable-reads-tests" } } ] }, { "description": "Distinct succeeds after HostNotFound", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "distinct" ], "errorCode": 7 } }, "operations": [ { "name": "distinct", "object": "collection", "arguments": { "fieldName": "x", "filter": { "_id": { "$gt": 1 } } }, "result": [ 22, 33 ] } ], "expectations": [ { "command_started_event": { "command": { "distinct": "coll", "key": "x", "query": { "_id": { "$gt": 1 } } }, "database_name": "retryable-reads-tests" } }, { "command_started_event": { "command": { "distinct": "coll", "key": "x", "query": { "_id": { "$gt": 1 } } }, "database_name": "retryable-reads-tests" } } ] }, { "description": "Distinct succeeds after HostUnreachable", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "distinct" ], "errorCode": 6 } }, "operations": [ { "name": "distinct", "object": "collection", "arguments": { "fieldName": "x", "filter": { "_id": { "$gt": 1 } } }, "result": [ 22, 33 ] } ], "expectations": [ { "command_started_event": { "command": { "distinct": "coll", "key": "x", "query": { "_id": { "$gt": 1 } } }, "database_name": "retryable-reads-tests" } }, { "command_started_event": { "command": { "distinct": "coll", "key": "x", "query": { "_id": { "$gt": 1 } } }, "database_name": "retryable-reads-tests" } } ] }, { "description": "Distinct succeeds after NetworkTimeout", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "distinct" ], "errorCode": 89 } }, "operations": [ { "name": "distinct", "object": "collection", "arguments": { "fieldName": "x", "filter": { "_id": { "$gt": 1 } } }, "result": [ 22, 33 ] } ], "expectations": [ { "command_started_event": { "command": { "distinct": "coll", "key": "x", "query": { "_id": { "$gt": 1 } } }, "database_name": "retryable-reads-tests" } }, { "command_started_event": { "command": { "distinct": "coll", "key": "x", "query": { "_id": { "$gt": 1 } } }, "database_name": "retryable-reads-tests" } } ] }, { "description": "Distinct succeeds after SocketException", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "distinct" ], "errorCode": 9001 } }, "operations": [ { "name": "distinct", "object": "collection", "arguments": { "fieldName": "x", "filter": { "_id": { "$gt": 1 } } }, "result": [ 22, 33 ] } ], "expectations": [ { "command_started_event": { "command": { "distinct": "coll", "key": "x", "query": { "_id": { "$gt": 1 } } }, "database_name": "retryable-reads-tests" } }, { "command_started_event": { "command": { "distinct": "coll", "key": "x", "query": { "_id": { "$gt": 1 } } }, "database_name": "retryable-reads-tests" } } ] }, { "description": "Distinct fails after two NotWritablePrimary errors", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 2 }, "data": { "failCommands": [ "distinct" ], "errorCode": 10107 } }, "operations": [ { "name": "distinct", "object": "collection", "arguments": { "fieldName": "x", "filter": { "_id": { "$gt": 1 } } }, "error": true } ], "expectations": [ { "command_started_event": { "command": { "distinct": "coll", "key": "x", "query": { "_id": { "$gt": 1 } } }, "database_name": "retryable-reads-tests" } }, { "command_started_event": { "command": { "distinct": "coll", "key": "x", "query": { "_id": { "$gt": 1 } } }, "database_name": "retryable-reads-tests" } } ] }, { "description": "Distinct fails after NotWritablePrimary when retryReads is false", "clientOptions": { "retryReads": false }, "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "distinct" ], "errorCode": 10107 } }, "operations": [ { "name": "distinct", "object": "collection", "arguments": { "fieldName": "x", "filter": { "_id": { "$gt": 1 } } }, "error": true } ], "expectations": [ { "command_started_event": { "command": { "distinct": "coll", "key": "x", "query": { "_id": { "$gt": 1 } } }, "database_name": "retryable-reads-tests" } } ] } ] } mongodb-mongo-python-driver-509e9b7/test/retryable_reads/legacy/distinct.json000066400000000000000000000116501462766011000275460ustar00rootroot00000000000000{ "runOn": [ { "minServerVersion": "4.0", "topology": [ "single", "replicaset" ] }, { "minServerVersion": "4.1.7", "topology": [ "sharded", "load-balanced" ] } ], "database_name": "retryable-reads-tests", "collection_name": "coll", "data": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 22 }, { "_id": 3, "x": 33 } ], "tests": [ { "description": "Distinct succeeds on first attempt", "operations": [ { "name": "distinct", "object": "collection", "arguments": { "fieldName": "x", "filter": { "_id": { "$gt": 1 } } }, "result": [ 22, 33 ] } ], "expectations": [ { "command_started_event": { "command": { "distinct": "coll", "key": "x", "query": { "_id": { "$gt": 1 } } }, "database_name": "retryable-reads-tests" } } ] }, { "description": "Distinct succeeds on second attempt", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "distinct" ], "closeConnection": true } }, "operations": [ { "name": "distinct", "object": "collection", "arguments": { "fieldName": "x", "filter": { "_id": { "$gt": 1 } } }, "result": [ 22, 33 ] } ], "expectations": [ { "command_started_event": { "command": { "distinct": "coll", "key": "x", "query": { "_id": { "$gt": 1 } } }, "database_name": "retryable-reads-tests" } }, { "command_started_event": { "command": { "distinct": "coll", "key": "x", "query": { "_id": { "$gt": 1 } } }, "database_name": "retryable-reads-tests" } } ] }, { "description": "Distinct fails on first attempt", "clientOptions": { "retryReads": false }, "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "distinct" ], "closeConnection": true } }, "operations": [ { "name": "distinct", "object": "collection", "arguments": { "fieldName": "x", "filter": { "_id": { "$gt": 1 } } }, "error": true } ], "expectations": [ { "command_started_event": { "command": { "distinct": "coll", "key": "x", "query": { "_id": { "$gt": 1 } } }, "database_name": "retryable-reads-tests" } } ] }, { "description": "Distinct fails on second attempt", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 2 }, "data": { "failCommands": [ "distinct" ], "closeConnection": true } }, "operations": [ { "name": "distinct", "object": "collection", "arguments": { "fieldName": "x", "filter": { "_id": { "$gt": 1 } } }, "error": true } ], "expectations": [ { "command_started_event": { "command": { "distinct": "coll", "key": "x", "query": { "_id": { "$gt": 1 } } }, "database_name": "retryable-reads-tests" } }, { "command_started_event": { "command": { "distinct": "coll", "key": "x", "query": { "_id": { "$gt": 1 } } }, "database_name": "retryable-reads-tests" } } ] } ] } estimatedDocumentCount-serverErrors.json000066400000000000000000000274561462766011000350510ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/retryable_reads/legacy{ "runOn": [ { "minServerVersion": "4.0", "topology": [ "single", "replicaset" ] }, { "minServerVersion": "4.1.7", "topology": [ "sharded" ] } ], "database_name": "retryable-reads-tests", "collection_name": "coll", "data": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 22 } ], "tests": [ { "description": "EstimatedDocumentCount succeeds after InterruptedAtShutdown", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "count" ], "errorCode": 11600 } }, "operations": [ { "name": "estimatedDocumentCount", "object": "collection", "result": 2 } ], "expectations": [ { "command_started_event": { "command": { "count": "coll" }, "database_name": "retryable-reads-tests" } }, { "command_started_event": { "command": { "count": "coll" }, "database_name": "retryable-reads-tests" } } ] }, { "description": "EstimatedDocumentCount succeeds after InterruptedDueToReplStateChange", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "count" ], "errorCode": 11602 } }, "operations": [ { "name": "estimatedDocumentCount", "object": "collection", "result": 2 } ], "expectations": [ { "command_started_event": { "command": { "count": "coll" }, "database_name": "retryable-reads-tests" } }, { "command_started_event": { "command": { "count": "coll" }, "database_name": "retryable-reads-tests" } } ] }, { "description": "EstimatedDocumentCount succeeds after NotWritablePrimary", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "count" ], "errorCode": 10107 } }, "operations": [ { "name": "estimatedDocumentCount", "object": "collection", "result": 2 } ], "expectations": [ { "command_started_event": { "command": { "count": "coll" }, "database_name": "retryable-reads-tests" } }, { "command_started_event": { "command": { "count": "coll" }, "database_name": "retryable-reads-tests" } } ] }, { "description": "EstimatedDocumentCount succeeds after NotPrimaryNoSecondaryOk", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "count" ], "errorCode": 13435 } }, "operations": [ { "name": "estimatedDocumentCount", "object": "collection", "result": 2 } ], "expectations": [ { "command_started_event": { "command": { "count": "coll" }, "database_name": "retryable-reads-tests" } }, { "command_started_event": { "command": { "count": "coll" }, "database_name": "retryable-reads-tests" } } ] }, { "description": "EstimatedDocumentCount succeeds after NotPrimaryOrSecondary", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "count" ], "errorCode": 13436 } }, "operations": [ { "name": "estimatedDocumentCount", "object": "collection", "result": 2 } ], "expectations": [ { "command_started_event": { "command": { "count": "coll" }, "database_name": "retryable-reads-tests" } }, { "command_started_event": { "command": { "count": "coll" }, "database_name": "retryable-reads-tests" } } ] }, { "description": "EstimatedDocumentCount succeeds after PrimarySteppedDown", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "count" ], "errorCode": 189 } }, "operations": [ { "name": "estimatedDocumentCount", "object": "collection", "result": 2 } ], "expectations": [ { "command_started_event": { "command": { "count": "coll" }, "database_name": "retryable-reads-tests" } }, { "command_started_event": { "command": { "count": "coll" }, "database_name": "retryable-reads-tests" } } ] }, { "description": "EstimatedDocumentCount succeeds after ShutdownInProgress", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "count" ], "errorCode": 91 } }, "operations": [ { "name": "estimatedDocumentCount", "object": "collection", "result": 2 } ], "expectations": [ { "command_started_event": { "command": { "count": "coll" }, "database_name": "retryable-reads-tests" } }, { "command_started_event": { "command": { "count": "coll" }, "database_name": "retryable-reads-tests" } } ] }, { "description": "EstimatedDocumentCount succeeds after HostNotFound", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "count" ], "errorCode": 7 } }, "operations": [ { "name": "estimatedDocumentCount", "object": "collection", "result": 2 } ], "expectations": [ { "command_started_event": { "command": { "count": "coll" }, "database_name": "retryable-reads-tests" } }, { "command_started_event": { "command": { "count": "coll" }, "database_name": "retryable-reads-tests" } } ] }, { "description": "EstimatedDocumentCount succeeds after HostUnreachable", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "count" ], "errorCode": 6 } }, "operations": [ { "name": "estimatedDocumentCount", "object": "collection", "result": 2 } ], "expectations": [ { "command_started_event": { "command": { "count": "coll" }, "database_name": "retryable-reads-tests" } }, { "command_started_event": { "command": { "count": "coll" }, "database_name": "retryable-reads-tests" } } ] }, { "description": "EstimatedDocumentCount succeeds after NetworkTimeout", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "count" ], "errorCode": 89 } }, "operations": [ { "name": "estimatedDocumentCount", "object": "collection", "result": 2 } ], "expectations": [ { "command_started_event": { "command": { "count": "coll" }, "database_name": "retryable-reads-tests" } }, { "command_started_event": { "command": { "count": "coll" }, "database_name": "retryable-reads-tests" } } ] }, { "description": "EstimatedDocumentCount succeeds after SocketException", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "count" ], "errorCode": 9001 } }, "operations": [ { "name": "estimatedDocumentCount", "object": "collection", "result": 2 } ], "expectations": [ { "command_started_event": { "command": { "count": "coll" }, "database_name": "retryable-reads-tests" } }, { "command_started_event": { "command": { "count": "coll" }, "database_name": "retryable-reads-tests" } } ] }, { "description": "EstimatedDocumentCount fails after two NotWritablePrimary errors", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 2 }, "data": { "failCommands": [ "count" ], "errorCode": 10107 } }, "operations": [ { "name": "estimatedDocumentCount", "object": "collection", "error": true } ], "expectations": [ { "command_started_event": { "command": { "count": "coll" }, "database_name": "retryable-reads-tests" } }, { "command_started_event": { "command": { "count": "coll" }, "database_name": "retryable-reads-tests" } } ] }, { "description": "EstimatedDocumentCount fails after NotWritablePrimary when retryReads is false", "clientOptions": { "retryReads": false }, "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "count" ], "errorCode": 10107 } }, "operations": [ { "name": "estimatedDocumentCount", "object": "collection", "error": true } ], "expectations": [ { "command_started_event": { "command": { "count": "coll" }, "database_name": "retryable-reads-tests" } } ] } ] } mongodb-mongo-python-driver-509e9b7/test/retryable_reads/legacy/estimatedDocumentCount.json000066400000000000000000000065771462766011000324300ustar00rootroot00000000000000{ "runOn": [ { "minServerVersion": "4.0", "topology": [ "single", "replicaset" ] }, { "minServerVersion": "4.1.7", "topology": [ "sharded" ] } ], "database_name": "retryable-reads-tests", "collection_name": "coll", "data": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 22 } ], "tests": [ { "description": "EstimatedDocumentCount succeeds on first attempt", "operations": [ { "name": "estimatedDocumentCount", "object": "collection", "result": 2 } ], "expectations": [ { "command_started_event": { "command": { "count": "coll" }, "database_name": "retryable-reads-tests" } } ] }, { "description": "EstimatedDocumentCount succeeds on second attempt", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "count" ], "closeConnection": true } }, "operations": [ { "name": "estimatedDocumentCount", "object": "collection", "result": 2 } ], "expectations": [ { "command_started_event": { "command": { "count": "coll" }, "database_name": "retryable-reads-tests" } }, { "command_started_event": { "command": { "count": "coll" }, "database_name": "retryable-reads-tests" } } ] }, { "description": "EstimatedDocumentCount fails on first attempt", "clientOptions": { "retryReads": false }, "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "count" ], "closeConnection": true } }, "operations": [ { "name": "estimatedDocumentCount", "object": "collection", "error": true } ], "expectations": [ { "command_started_event": { "command": { "count": "coll" }, "database_name": "retryable-reads-tests" } } ] }, { "description": "EstimatedDocumentCount fails on second attempt", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 2 }, "data": { "failCommands": [ "count" ], "closeConnection": true } }, "operations": [ { "name": "estimatedDocumentCount", "object": "collection", "error": true } ], "expectations": [ { "command_started_event": { "command": { "count": "coll" }, "database_name": "retryable-reads-tests" } }, { "command_started_event": { "command": { "count": "coll" }, "database_name": "retryable-reads-tests" } } ] } ] } mongodb-mongo-python-driver-509e9b7/test/retryable_reads/legacy/find-serverErrors.json000066400000000000000000000471321462766011000313520ustar00rootroot00000000000000{ "runOn": [ { "minServerVersion": "4.0", "topology": [ "single", "replicaset" ] }, { "minServerVersion": "4.1.7", "topology": [ "sharded", "load-balanced" ] } ], "database_name": "retryable-reads-tests", "collection_name": "coll", "data": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 22 }, { "_id": 3, "x": 33 }, { "_id": 4, "x": 44 }, { "_id": 5, "x": 55 } ], "tests": [ { "description": "Find succeeds after InterruptedAtShutdown", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "find" ], "errorCode": 11600 } }, "operations": [ { "name": "find", "object": "collection", "arguments": { "filter": {}, "sort": { "_id": 1 }, "limit": 4 }, "result": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 22 }, { "_id": 3, "x": 33 }, { "_id": 4, "x": 44 } ] } ], "expectations": [ { "command_started_event": { "command": { "find": "coll", "filter": {}, "sort": { "_id": 1 }, "limit": 4 }, "database_name": "retryable-reads-tests" } }, { "command_started_event": { "command": { "find": "coll", "filter": {}, "sort": { "_id": 1 }, "limit": 4 }, "database_name": "retryable-reads-tests" } } ] }, { "description": "Find succeeds after InterruptedDueToReplStateChange", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "find" ], "errorCode": 11602 } }, "operations": [ { "name": "find", "object": "collection", "arguments": { "filter": {}, "sort": { "_id": 1 }, "limit": 4 }, "result": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 22 }, { "_id": 3, "x": 33 }, { "_id": 4, "x": 44 } ] } ], "expectations": [ { "command_started_event": { "command": { "find": "coll", "filter": {}, "sort": { "_id": 1 }, "limit": 4 }, "database_name": "retryable-reads-tests" } }, { "command_started_event": { "command": { "find": "coll", "filter": {}, "sort": { "_id": 1 }, "limit": 4 }, "database_name": "retryable-reads-tests" } } ] }, { "description": "Find succeeds after NotWritablePrimary", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "find" ], "errorCode": 10107 } }, "operations": [ { "name": "find", "object": "collection", "arguments": { "filter": {}, "sort": { "_id": 1 }, "limit": 4 }, "result": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 22 }, { "_id": 3, "x": 33 }, { "_id": 4, "x": 44 } ] } ], "expectations": [ { "command_started_event": { "command": { "find": "coll", "filter": {}, "sort": { "_id": 1 }, "limit": 4 }, "database_name": "retryable-reads-tests" } }, { "command_started_event": { "command": { "find": "coll", "filter": {}, "sort": { "_id": 1 }, "limit": 4 }, "database_name": "retryable-reads-tests" } } ] }, { "description": "Find succeeds after NotPrimaryNoSecondaryOk", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "find" ], "errorCode": 13435 } }, "operations": [ { "name": "find", "object": "collection", "arguments": { "filter": {}, "sort": { "_id": 1 }, "limit": 4 }, "result": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 22 }, { "_id": 3, "x": 33 }, { "_id": 4, "x": 44 } ] } ], "expectations": [ { "command_started_event": { "command": { "find": "coll", "filter": {}, "sort": { "_id": 1 }, "limit": 4 }, "database_name": "retryable-reads-tests" } }, { "command_started_event": { "command": { "find": "coll", "filter": {}, "sort": { "_id": 1 }, "limit": 4 }, "database_name": "retryable-reads-tests" } } ] }, { "description": "Find succeeds after NotPrimaryOrSecondary", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "find" ], "errorCode": 13436 } }, "operations": [ { "name": "find", "object": "collection", "arguments": { "filter": {}, "sort": { "_id": 1 }, "limit": 4 }, "result": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 22 }, { "_id": 3, "x": 33 }, { "_id": 4, "x": 44 } ] } ], "expectations": [ { "command_started_event": { "command": { "find": "coll", "filter": {}, "sort": { "_id": 1 }, "limit": 4 }, "database_name": "retryable-reads-tests" } }, { "command_started_event": { "command": { "find": "coll", "filter": {}, "sort": { "_id": 1 }, "limit": 4 }, "database_name": "retryable-reads-tests" } } ] }, { "description": "Find succeeds after PrimarySteppedDown", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "find" ], "errorCode": 189 } }, "operations": [ { "name": "find", "object": "collection", "arguments": { "filter": {}, "sort": { "_id": 1 }, "limit": 4 }, "result": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 22 }, { "_id": 3, "x": 33 }, { "_id": 4, "x": 44 } ] } ], "expectations": [ { "command_started_event": { "command": { "find": "coll", "filter": {}, "sort": { "_id": 1 }, "limit": 4 }, "database_name": "retryable-reads-tests" } }, { "command_started_event": { "command": { "find": "coll", "filter": {}, "sort": { "_id": 1 }, "limit": 4 }, "database_name": "retryable-reads-tests" } } ] }, { "description": "Find succeeds after ShutdownInProgress", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "find" ], "errorCode": 91 } }, "operations": [ { "name": "find", "object": "collection", "arguments": { "filter": {}, "sort": { "_id": 1 }, "limit": 4 }, "result": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 22 }, { "_id": 3, "x": 33 }, { "_id": 4, "x": 44 } ] } ], "expectations": [ { "command_started_event": { "command": { "find": "coll", "filter": {}, "sort": { "_id": 1 }, "limit": 4 }, "database_name": "retryable-reads-tests" } }, { "command_started_event": { "command": { "find": "coll", "filter": {}, "sort": { "_id": 1 }, "limit": 4 }, "database_name": "retryable-reads-tests" } } ] }, { "description": "Find succeeds after HostNotFound", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "find" ], "errorCode": 7 } }, "operations": [ { "name": "find", "object": "collection", "arguments": { "filter": {}, "sort": { "_id": 1 }, "limit": 4 }, "result": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 22 }, { "_id": 3, "x": 33 }, { "_id": 4, "x": 44 } ] } ], "expectations": [ { "command_started_event": { "command": { "find": "coll", "filter": {}, "sort": { "_id": 1 }, "limit": 4 }, "database_name": "retryable-reads-tests" } }, { "command_started_event": { "command": { "find": "coll", "filter": {}, "sort": { "_id": 1 }, "limit": 4 }, "database_name": "retryable-reads-tests" } } ] }, { "description": "Find succeeds after HostUnreachable", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "find" ], "errorCode": 6 } }, "operations": [ { "name": "find", "object": "collection", "arguments": { "filter": {}, "sort": { "_id": 1 }, "limit": 4 }, "result": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 22 }, { "_id": 3, "x": 33 }, { "_id": 4, "x": 44 } ] } ], "expectations": [ { "command_started_event": { "command": { "find": "coll", "filter": {}, "sort": { "_id": 1 }, "limit": 4 }, "database_name": "retryable-reads-tests" } }, { "command_started_event": { "command": { "find": "coll", "filter": {}, "sort": { "_id": 1 }, "limit": 4 }, "database_name": "retryable-reads-tests" } } ] }, { "description": "Find succeeds after NetworkTimeout", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "find" ], "errorCode": 89 } }, "operations": [ { "name": "find", "object": "collection", "arguments": { "filter": {}, "sort": { "_id": 1 }, "limit": 4 }, "result": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 22 }, { "_id": 3, "x": 33 }, { "_id": 4, "x": 44 } ] } ], "expectations": [ { "command_started_event": { "command": { "find": "coll", "filter": {}, "sort": { "_id": 1 }, "limit": 4 }, "database_name": "retryable-reads-tests" } }, { "command_started_event": { "command": { "find": "coll", "filter": {}, "sort": { "_id": 1 }, "limit": 4 }, "database_name": "retryable-reads-tests" } } ] }, { "description": "Find succeeds after SocketException", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "find" ], "errorCode": 9001 } }, "operations": [ { "name": "find", "object": "collection", "arguments": { "filter": {}, "sort": { "_id": 1 }, "limit": 4 }, "result": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 22 }, { "_id": 3, "x": 33 }, { "_id": 4, "x": 44 } ] } ], "expectations": [ { "command_started_event": { "command": { "find": "coll", "filter": {}, "sort": { "_id": 1 }, "limit": 4 }, "database_name": "retryable-reads-tests" } }, { "command_started_event": { "command": { "find": "coll", "filter": {}, "sort": { "_id": 1 }, "limit": 4 }, "database_name": "retryable-reads-tests" } } ] }, { "description": "Find fails after two NotWritablePrimary errors", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 2 }, "data": { "failCommands": [ "find" ], "errorCode": 10107 } }, "operations": [ { "name": "find", "object": "collection", "arguments": { "filter": {}, "sort": { "_id": 1 }, "limit": 4 }, "error": true } ], "expectations": [ { "command_started_event": { "command": { "find": "coll", "filter": {}, "sort": { "_id": 1 }, "limit": 4 }, "database_name": "retryable-reads-tests" } }, { "command_started_event": { "command": { "find": "coll", "filter": {}, "sort": { "_id": 1 }, "limit": 4 }, "database_name": "retryable-reads-tests" } } ] }, { "description": "Find fails after NotWritablePrimary when retryReads is false", "clientOptions": { "retryReads": false }, "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "find" ], "errorCode": 10107 } }, "operations": [ { "name": "find", "object": "collection", "arguments": { "filter": {}, "sort": { "_id": 1 }, "limit": 4 }, "error": true } ], "expectations": [ { "command_started_event": { "command": { "find": "coll", "filter": {}, "sort": { "_id": 1 }, "limit": 4 }, "database_name": "retryable-reads-tests" } } ] } ] } mongodb-mongo-python-driver-509e9b7/test/retryable_reads/legacy/find.json000066400000000000000000000155751462766011000266570ustar00rootroot00000000000000{ "runOn": [ { "minServerVersion": "4.0", "topology": [ "single", "replicaset" ] }, { "minServerVersion": "4.1.7", "topology": [ "sharded", "load-balanced" ] } ], "database_name": "retryable-reads-tests", "collection_name": "coll", "data": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 22 }, { "_id": 3, "x": 33 }, { "_id": 4, "x": 44 }, { "_id": 5, "x": 55 } ], "tests": [ { "description": "Find succeeds on first attempt", "operations": [ { "name": "find", "object": "collection", "arguments": { "filter": {}, "sort": { "_id": 1 }, "limit": 4 }, "result": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 22 }, { "_id": 3, "x": 33 }, { "_id": 4, "x": 44 } ] } ], "expectations": [ { "command_started_event": { "command": { "find": "coll", "filter": {}, "sort": { "_id": 1 }, "limit": 4 }, "database_name": "retryable-reads-tests" } } ] }, { "description": "Find succeeds on second attempt with explicit clientOptions", "clientOptions": { "retryReads": true }, "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "find" ], "closeConnection": true } }, "operations": [ { "name": "find", "object": "collection", "arguments": { "filter": {}, "sort": { "_id": 1 }, "limit": 4 }, "result": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 22 }, { "_id": 3, "x": 33 }, { "_id": 4, "x": 44 } ] } ], "expectations": [ { "command_started_event": { "command": { "find": "coll", "filter": {}, "sort": { "_id": 1 }, "limit": 4 }, "database_name": "retryable-reads-tests" } }, { "command_started_event": { "command": { "find": "coll", "filter": {}, "sort": { "_id": 1 }, "limit": 4 }, "database_name": "retryable-reads-tests" } } ] }, { "description": "Find succeeds on second attempt", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "find" ], "closeConnection": true } }, "operations": [ { "name": "find", "object": "collection", "arguments": { "filter": {}, "sort": { "_id": 1 }, "limit": 4 }, "result": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 22 }, { "_id": 3, "x": 33 }, { "_id": 4, "x": 44 } ] } ], "expectations": [ { "command_started_event": { "command": { "find": "coll", "filter": {}, "sort": { "_id": 1 }, "limit": 4 }, "database_name": "retryable-reads-tests" } }, { "command_started_event": { "command": { "find": "coll", "filter": {}, "sort": { "_id": 1 }, "limit": 4 }, "database_name": "retryable-reads-tests" } } ] }, { "description": "Find fails on first attempt", "clientOptions": { "retryReads": false }, "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "find" ], "closeConnection": true } }, "operations": [ { "name": "find", "object": "collection", "arguments": { "filter": {}, "sort": { "_id": 1 }, "limit": 4 }, "error": true } ], "expectations": [ { "command_started_event": { "command": { "find": "coll", "filter": {}, "sort": { "_id": 1 }, "limit": 4 }, "database_name": "retryable-reads-tests" } } ] }, { "description": "Find fails on second attempt", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 2 }, "data": { "failCommands": [ "find" ], "closeConnection": true } }, "operations": [ { "name": "find", "object": "collection", "arguments": { "filter": {}, "sort": { "_id": 1 }, "limit": 4 }, "error": true } ], "expectations": [ { "command_started_event": { "command": { "find": "coll", "filter": {}, "sort": { "_id": 1 }, "limit": 4 }, "database_name": "retryable-reads-tests" } }, { "command_started_event": { "command": { "find": "coll", "filter": {}, "sort": { "_id": 1 }, "limit": 4 }, "database_name": "retryable-reads-tests" } } ] } ] } mongodb-mongo-python-driver-509e9b7/test/retryable_reads/legacy/findOne-serverErrors.json000066400000000000000000000360311462766011000320100ustar00rootroot00000000000000{ "runOn": [ { "minServerVersion": "4.0", "topology": [ "single", "replicaset" ] }, { "minServerVersion": "4.1.7", "topology": [ "sharded", "load-balanced" ] } ], "database_name": "retryable-reads-tests", "collection_name": "coll", "data": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 22 }, { "_id": 3, "x": 33 }, { "_id": 4, "x": 44 }, { "_id": 5, "x": 55 } ], "tests": [ { "description": "FindOne succeeds after InterruptedAtShutdown", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "find" ], "errorCode": 11600 } }, "operations": [ { "name": "findOne", "object": "collection", "arguments": { "filter": { "_id": 1 } }, "result": { "_id": 1, "x": 11 } } ], "expectations": [ { "command_started_event": { "command": { "find": "coll", "filter": { "_id": 1 } }, "database_name": "retryable-reads-tests" } }, { "command_started_event": { "command": { "find": "coll", "filter": { "_id": 1 } }, "database_name": "retryable-reads-tests" } } ] }, { "description": "FindOne succeeds after InterruptedDueToReplStateChange", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "find" ], "errorCode": 11602 } }, "operations": [ { "name": "findOne", "object": "collection", "arguments": { "filter": { "_id": 1 } }, "result": { "_id": 1, "x": 11 } } ], "expectations": [ { "command_started_event": { "command": { "find": "coll", "filter": { "_id": 1 } }, "database_name": "retryable-reads-tests" } }, { "command_started_event": { "command": { "find": "coll", "filter": { "_id": 1 } }, "database_name": "retryable-reads-tests" } } ] }, { "description": "FindOne succeeds after NotWritablePrimary", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "find" ], "errorCode": 10107 } }, "operations": [ { "name": "findOne", "object": "collection", "arguments": { "filter": { "_id": 1 } }, "result": { "_id": 1, "x": 11 } } ], "expectations": [ { "command_started_event": { "command": { "find": "coll", "filter": { "_id": 1 } }, "database_name": "retryable-reads-tests" } }, { "command_started_event": { "command": { "find": "coll", "filter": { "_id": 1 } }, "database_name": "retryable-reads-tests" } } ] }, { "description": "FindOne succeeds after NotPrimaryNoSecondaryOk", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "find" ], "errorCode": 13435 } }, "operations": [ { "name": "findOne", "object": "collection", "arguments": { "filter": { "_id": 1 } }, "result": { "_id": 1, "x": 11 } } ], "expectations": [ { "command_started_event": { "command": { "find": "coll", "filter": { "_id": 1 } }, "database_name": "retryable-reads-tests" } }, { "command_started_event": { "command": { "find": "coll", "filter": { "_id": 1 } }, "database_name": "retryable-reads-tests" } } ] }, { "description": "FindOne succeeds after NotPrimaryOrSecondary", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "find" ], "errorCode": 13436 } }, "operations": [ { "name": "findOne", "object": "collection", "arguments": { "filter": { "_id": 1 } }, "result": { "_id": 1, "x": 11 } } ], "expectations": [ { "command_started_event": { "command": { "find": "coll", "filter": { "_id": 1 } }, "database_name": "retryable-reads-tests" } }, { "command_started_event": { "command": { "find": "coll", "filter": { "_id": 1 } }, "database_name": "retryable-reads-tests" } } ] }, { "description": "FindOne succeeds after PrimarySteppedDown", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "find" ], "errorCode": 189 } }, "operations": [ { "name": "findOne", "object": "collection", "arguments": { "filter": { "_id": 1 } }, "result": { "_id": 1, "x": 11 } } ], "expectations": [ { "command_started_event": { "command": { "find": "coll", "filter": { "_id": 1 } }, "database_name": "retryable-reads-tests" } }, { "command_started_event": { "command": { "find": "coll", "filter": { "_id": 1 } }, "database_name": "retryable-reads-tests" } } ] }, { "description": "FindOne succeeds after ShutdownInProgress", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "find" ], "errorCode": 91 } }, "operations": [ { "name": "findOne", "object": "collection", "arguments": { "filter": { "_id": 1 } }, "result": { "_id": 1, "x": 11 } } ], "expectations": [ { "command_started_event": { "command": { "find": "coll", "filter": { "_id": 1 } }, "database_name": "retryable-reads-tests" } }, { "command_started_event": { "command": { "find": "coll", "filter": { "_id": 1 } }, "database_name": "retryable-reads-tests" } } ] }, { "description": "FindOne succeeds after HostNotFound", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "find" ], "errorCode": 7 } }, "operations": [ { "name": "findOne", "object": "collection", "arguments": { "filter": { "_id": 1 } }, "result": { "_id": 1, "x": 11 } } ], "expectations": [ { "command_started_event": { "command": { "find": "coll", "filter": { "_id": 1 } }, "database_name": "retryable-reads-tests" } }, { "command_started_event": { "command": { "find": "coll", "filter": { "_id": 1 } }, "database_name": "retryable-reads-tests" } } ] }, { "description": "FindOne succeeds after HostUnreachable", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "find" ], "errorCode": 6 } }, "operations": [ { "name": "findOne", "object": "collection", "arguments": { "filter": { "_id": 1 } }, "result": { "_id": 1, "x": 11 } } ], "expectations": [ { "command_started_event": { "command": { "find": "coll", "filter": { "_id": 1 } }, "database_name": "retryable-reads-tests" } }, { "command_started_event": { "command": { "find": "coll", "filter": { "_id": 1 } }, "database_name": "retryable-reads-tests" } } ] }, { "description": "FindOne succeeds after NetworkTimeout", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "find" ], "errorCode": 89 } }, "operations": [ { "name": "findOne", "object": "collection", "arguments": { "filter": { "_id": 1 } }, "result": { "_id": 1, "x": 11 } } ], "expectations": [ { "command_started_event": { "command": { "find": "coll", "filter": { "_id": 1 } }, "database_name": "retryable-reads-tests" } }, { "command_started_event": { "command": { "find": "coll", "filter": { "_id": 1 } }, "database_name": "retryable-reads-tests" } } ] }, { "description": "FindOne succeeds after SocketException", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "find" ], "errorCode": 9001 } }, "operations": [ { "name": "findOne", "object": "collection", "arguments": { "filter": { "_id": 1 } }, "result": { "_id": 1, "x": 11 } } ], "expectations": [ { "command_started_event": { "command": { "find": "coll", "filter": { "_id": 1 } }, "database_name": "retryable-reads-tests" } }, { "command_started_event": { "command": { "find": "coll", "filter": { "_id": 1 } }, "database_name": "retryable-reads-tests" } } ] }, { "description": "FindOne fails after two NotWritablePrimary errors", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 2 }, "data": { "failCommands": [ "find" ], "errorCode": 10107 } }, "operations": [ { "name": "findOne", "object": "collection", "arguments": { "filter": { "_id": 1 } }, "error": true } ], "expectations": [ { "command_started_event": { "command": { "find": "coll", "filter": { "_id": 1 } }, "database_name": "retryable-reads-tests" } }, { "command_started_event": { "command": { "find": "coll", "filter": { "_id": 1 } }, "database_name": "retryable-reads-tests" } } ] }, { "description": "FindOne fails after NotWritablePrimary when retryReads is false", "clientOptions": { "retryReads": false }, "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "find" ], "errorCode": 10107 } }, "operations": [ { "name": "findOne", "object": "collection", "arguments": { "filter": { "_id": 1 } }, "error": true } ], "expectations": [ { "command_started_event": { "command": { "find": "coll", "filter": { "_id": 1 } }, "database_name": "retryable-reads-tests" } } ] } ] } mongodb-mongo-python-driver-509e9b7/test/retryable_reads/legacy/findOne.json000066400000000000000000000104501462766011000273040ustar00rootroot00000000000000{ "runOn": [ { "minServerVersion": "4.0", "topology": [ "single", "replicaset" ] }, { "minServerVersion": "4.1.7", "topology": [ "sharded", "load-balanced" ] } ], "database_name": "retryable-reads-tests", "collection_name": "coll", "data": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 22 }, { "_id": 3, "x": 33 }, { "_id": 4, "x": 44 }, { "_id": 5, "x": 55 } ], "tests": [ { "description": "FindOne succeeds on first attempt", "operations": [ { "name": "findOne", "object": "collection", "arguments": { "filter": { "_id": 1 } }, "result": { "_id": 1, "x": 11 } } ], "expectations": [ { "command_started_event": { "command": { "find": "coll", "filter": { "_id": 1 } }, "database_name": "retryable-reads-tests" } } ] }, { "description": "FindOne succeeds on second attempt", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "find" ], "closeConnection": true } }, "operations": [ { "name": "findOne", "object": "collection", "arguments": { "filter": { "_id": 1 } }, "result": { "_id": 1, "x": 11 } } ], "expectations": [ { "command_started_event": { "command": { "find": "coll", "filter": { "_id": 1 } }, "database_name": "retryable-reads-tests" } }, { "command_started_event": { "command": { "find": "coll", "filter": { "_id": 1 } }, "database_name": "retryable-reads-tests" } } ] }, { "description": "FindOne fails on first attempt", "clientOptions": { "retryReads": false }, "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "find" ], "closeConnection": true } }, "operations": [ { "name": "findOne", "object": "collection", "arguments": { "filter": { "_id": 1 } }, "error": true } ], "expectations": [ { "command_started_event": { "command": { "find": "coll", "filter": { "_id": 1 } }, "database_name": "retryable-reads-tests" } } ] }, { "description": "FindOne fails on second attempt", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 2 }, "data": { "failCommands": [ "find" ], "closeConnection": true } }, "operations": [ { "name": "findOne", "object": "collection", "arguments": { "filter": { "_id": 1 } }, "error": true } ], "expectations": [ { "command_started_event": { "command": { "find": "coll", "filter": { "_id": 1 } }, "database_name": "retryable-reads-tests" } }, { "command_started_event": { "command": { "find": "coll", "filter": { "_id": 1 } }, "database_name": "retryable-reads-tests" } } ] } ] } mongodb-mongo-python-driver-509e9b7/test/retryable_reads/legacy/gridfs-download-serverErrors.json000066400000000000000000000521451462766011000335150ustar00rootroot00000000000000{ "runOn": [ { "minServerVersion": "4.0", "topology": [ "single", "replicaset" ] }, { "minServerVersion": "4.1.7", "topology": [ "sharded", "load-balanced" ] } ], "database_name": "retryable-reads-tests", "bucket_name": "fs", "data": { "fs.files": [ { "_id": { "$oid": "000000000000000000000001" }, "length": 1, "chunkSize": 4, "uploadDate": { "$date": "1970-01-01T00:00:00.000Z" }, "filename": "abc", "metadata": {} } ], "fs.chunks": [ { "_id": { "$oid": "000000000000000000000002" }, "files_id": { "$oid": "000000000000000000000001" }, "n": 0, "data": { "$binary": { "base64": "EQ==", "subType": "00" } } } ] }, "tests": [ { "description": "Download succeeds after InterruptedAtShutdown", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "find" ], "errorCode": 11600 } }, "operations": [ { "name": "download", "object": "gridfsbucket", "arguments": { "id": { "$oid": "000000000000000000000001" } } } ], "expectations": [ { "command_started_event": { "command": { "find": "fs.files", "filter": { "_id": { "$oid": "000000000000000000000001" } } }, "database_name": "retryable-reads-tests" } }, { "command_started_event": { "command": { "find": "fs.files", "filter": { "_id": { "$oid": "000000000000000000000001" } } }, "database_name": "retryable-reads-tests" } }, { "command_started_event": { "command": { "find": "fs.chunks", "filter": { "files_id": { "$oid": "000000000000000000000001" } }, "sort": { "n": 1 } }, "database_name": "retryable-reads-tests" } } ] }, { "description": "Download succeeds after InterruptedDueToReplStateChange", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "find" ], "errorCode": 11602 } }, "operations": [ { "name": "download", "object": "gridfsbucket", "arguments": { "id": { "$oid": "000000000000000000000001" } } } ], "expectations": [ { "command_started_event": { "command": { "find": "fs.files", "filter": { "_id": { "$oid": "000000000000000000000001" } } }, "database_name": "retryable-reads-tests" } }, { "command_started_event": { "command": { "find": "fs.files", "filter": { "_id": { "$oid": "000000000000000000000001" } } }, "database_name": "retryable-reads-tests" } }, { "command_started_event": { "command": { "find": "fs.chunks", "filter": { "files_id": { "$oid": "000000000000000000000001" } }, "sort": { "n": 1 } }, "database_name": "retryable-reads-tests" } } ] }, { "description": "Download succeeds after NotWritablePrimary", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "find" ], "errorCode": 10107 } }, "operations": [ { "name": "download", "object": "gridfsbucket", "arguments": { "id": { "$oid": "000000000000000000000001" } } } ], "expectations": [ { "command_started_event": { "command": { "find": "fs.files", "filter": { "_id": { "$oid": "000000000000000000000001" } } }, "database_name": "retryable-reads-tests" } }, { "command_started_event": { "command": { "find": "fs.files", "filter": { "_id": { "$oid": "000000000000000000000001" } } }, "database_name": "retryable-reads-tests" } }, { "command_started_event": { "command": { "find": "fs.chunks", "filter": { "files_id": { "$oid": "000000000000000000000001" } }, "sort": { "n": 1 } }, "database_name": "retryable-reads-tests" } } ] }, { "description": "Download succeeds after NotPrimaryNoSecondaryOk", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "find" ], "errorCode": 13435 } }, "operations": [ { "name": "download", "object": "gridfsbucket", "arguments": { "id": { "$oid": "000000000000000000000001" } } } ], "expectations": [ { "command_started_event": { "command": { "find": "fs.files", "filter": { "_id": { "$oid": "000000000000000000000001" } } }, "database_name": "retryable-reads-tests" } }, { "command_started_event": { "command": { "find": "fs.files", "filter": { "_id": { "$oid": "000000000000000000000001" } } }, "database_name": "retryable-reads-tests" } }, { "command_started_event": { "command": { "find": "fs.chunks", "filter": { "files_id": { "$oid": "000000000000000000000001" } }, "sort": { "n": 1 } }, "database_name": "retryable-reads-tests" } } ] }, { "description": "Download succeeds after NotPrimaryOrSecondary", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "find" ], "errorCode": 13436 } }, "operations": [ { "name": "download", "object": "gridfsbucket", "arguments": { "id": { "$oid": "000000000000000000000001" } } } ], "expectations": [ { "command_started_event": { "command": { "find": "fs.files", "filter": { "_id": { "$oid": "000000000000000000000001" } } }, "database_name": "retryable-reads-tests" } }, { "command_started_event": { "command": { "find": "fs.files", "filter": { "_id": { "$oid": "000000000000000000000001" } } }, "database_name": "retryable-reads-tests" } }, { "command_started_event": { "command": { "find": "fs.chunks", "filter": { "files_id": { "$oid": "000000000000000000000001" } }, "sort": { "n": 1 } }, "database_name": "retryable-reads-tests" } } ] }, { "description": "Download succeeds after PrimarySteppedDown", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "find" ], "errorCode": 189 } }, "operations": [ { "name": "download", "object": "gridfsbucket", "arguments": { "id": { "$oid": "000000000000000000000001" } } } ], "expectations": [ { "command_started_event": { "command": { "find": "fs.files", "filter": { "_id": { "$oid": "000000000000000000000001" } } }, "database_name": "retryable-reads-tests" } }, { "command_started_event": { "command": { "find": "fs.files", "filter": { "_id": { "$oid": "000000000000000000000001" } } }, "database_name": "retryable-reads-tests" } }, { "command_started_event": { "command": { "find": "fs.chunks", "filter": { "files_id": { "$oid": "000000000000000000000001" } }, "sort": { "n": 1 } }, "database_name": "retryable-reads-tests" } } ] }, { "description": "Download succeeds after ShutdownInProgress", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "find" ], "errorCode": 91 } }, "operations": [ { "name": "download", "object": "gridfsbucket", "arguments": { "id": { "$oid": "000000000000000000000001" } } } ], "expectations": [ { "command_started_event": { "command": { "find": "fs.files", "filter": { "_id": { "$oid": "000000000000000000000001" } } }, "database_name": "retryable-reads-tests" } }, { "command_started_event": { "command": { "find": "fs.files", "filter": { "_id": { "$oid": "000000000000000000000001" } } }, "database_name": "retryable-reads-tests" } }, { "command_started_event": { "command": { "find": "fs.chunks", "filter": { "files_id": { "$oid": "000000000000000000000001" } }, "sort": { "n": 1 } }, "database_name": "retryable-reads-tests" } } ] }, { "description": "Download succeeds after HostNotFound", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "find" ], "errorCode": 7 } }, "operations": [ { "name": "download", "object": "gridfsbucket", "arguments": { "id": { "$oid": "000000000000000000000001" } } } ], "expectations": [ { "command_started_event": { "command": { "find": "fs.files", "filter": { "_id": { "$oid": "000000000000000000000001" } } }, "database_name": "retryable-reads-tests" } }, { "command_started_event": { "command": { "find": "fs.files", "filter": { "_id": { "$oid": "000000000000000000000001" } } }, "database_name": "retryable-reads-tests" } }, { "command_started_event": { "command": { "find": "fs.chunks", "filter": { "files_id": { "$oid": "000000000000000000000001" } }, "sort": { "n": 1 } }, "database_name": "retryable-reads-tests" } } ] }, { "description": "Download succeeds after HostUnreachable", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "find" ], "errorCode": 6 } }, "operations": [ { "name": "download", "object": "gridfsbucket", "arguments": { "id": { "$oid": "000000000000000000000001" } } } ], "expectations": [ { "command_started_event": { "command": { "find": "fs.files", "filter": { "_id": { "$oid": "000000000000000000000001" } } }, "database_name": "retryable-reads-tests" } }, { "command_started_event": { "command": { "find": "fs.files", "filter": { "_id": { "$oid": "000000000000000000000001" } } }, "database_name": "retryable-reads-tests" } }, { "command_started_event": { "command": { "find": "fs.chunks", "filter": { "files_id": { "$oid": "000000000000000000000001" } }, "sort": { "n": 1 } }, "database_name": "retryable-reads-tests" } } ] }, { "description": "Download succeeds after NetworkTimeout", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "find" ], "errorCode": 89 } }, "operations": [ { "name": "download", "object": "gridfsbucket", "arguments": { "id": { "$oid": "000000000000000000000001" } } } ], "expectations": [ { "command_started_event": { "command": { "find": "fs.files", "filter": { "_id": { "$oid": "000000000000000000000001" } } }, "database_name": "retryable-reads-tests" } }, { "command_started_event": { "command": { "find": "fs.files", "filter": { "_id": { "$oid": "000000000000000000000001" } } }, "database_name": "retryable-reads-tests" } }, { "command_started_event": { "command": { "find": "fs.chunks", "filter": { "files_id": { "$oid": "000000000000000000000001" } }, "sort": { "n": 1 } }, "database_name": "retryable-reads-tests" } } ] }, { "description": "Download succeeds after SocketException", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "find" ], "errorCode": 9001 } }, "operations": [ { "name": "download", "object": "gridfsbucket", "arguments": { "id": { "$oid": "000000000000000000000001" } } } ], "expectations": [ { "command_started_event": { "command": { "find": "fs.files", "filter": { "_id": { "$oid": "000000000000000000000001" } } }, "database_name": "retryable-reads-tests" } }, { "command_started_event": { "command": { "find": "fs.files", "filter": { "_id": { "$oid": "000000000000000000000001" } } }, "database_name": "retryable-reads-tests" } }, { "command_started_event": { "command": { "find": "fs.chunks", "filter": { "files_id": { "$oid": "000000000000000000000001" } }, "sort": { "n": 1 } }, "database_name": "retryable-reads-tests" } } ] }, { "description": "Download fails after two NotWritablePrimary errors", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 2 }, "data": { "failCommands": [ "find" ], "errorCode": 10107 } }, "operations": [ { "name": "download", "object": "gridfsbucket", "arguments": { "id": { "$oid": "000000000000000000000001" } }, "error": true } ], "expectations": [ { "command_started_event": { "command": { "find": "fs.files", "filter": { "_id": { "$oid": "000000000000000000000001" } } }, "database_name": "retryable-reads-tests" } }, { "command_started_event": { "command": { "find": "fs.files", "filter": { "_id": { "$oid": "000000000000000000000001" } } }, "database_name": "retryable-reads-tests" } } ] }, { "description": "Download fails after NotWritablePrimary when retryReads is false", "clientOptions": { "retryReads": false }, "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "find" ], "errorCode": 10107 } }, "operations": [ { "name": "download", "object": "gridfsbucket", "arguments": { "id": { "$oid": "000000000000000000000001" } }, "error": true } ], "expectations": [ { "command_started_event": { "command": { "find": "fs.files", "filter": { "_id": { "$oid": "000000000000000000000001" } } }, "database_name": "retryable-reads-tests" } } ] } ] } mongodb-mongo-python-driver-509e9b7/test/retryable_reads/legacy/gridfs-download.json000066400000000000000000000135611462766011000310130ustar00rootroot00000000000000{ "runOn": [ { "minServerVersion": "4.0", "topology": [ "single", "replicaset" ] }, { "minServerVersion": "4.1.7", "topology": [ "sharded", "load-balanced" ] } ], "database_name": "retryable-reads-tests", "bucket_name": "fs", "data": { "fs.files": [ { "_id": { "$oid": "000000000000000000000001" }, "length": 1, "chunkSize": 4, "uploadDate": { "$date": "1970-01-01T00:00:00.000Z" }, "filename": "abc", "metadata": {} } ], "fs.chunks": [ { "_id": { "$oid": "000000000000000000000002" }, "files_id": { "$oid": "000000000000000000000001" }, "n": 0, "data": { "$binary": { "base64": "EQ==", "subType": "00" } } } ] }, "tests": [ { "description": "Download succeeds on first attempt", "operations": [ { "name": "download", "object": "gridfsbucket", "arguments": { "id": { "$oid": "000000000000000000000001" } } } ], "expectations": [ { "command_started_event": { "command": { "find": "fs.files", "filter": { "_id": { "$oid": "000000000000000000000001" } } }, "database_name": "retryable-reads-tests" } }, { "command_started_event": { "command": { "find": "fs.chunks", "filter": { "files_id": { "$oid": "000000000000000000000001" } }, "sort": { "n": 1 } }, "database_name": "retryable-reads-tests" } } ] }, { "description": "Download succeeds on second attempt", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "find" ], "closeConnection": true } }, "operations": [ { "name": "download", "object": "gridfsbucket", "arguments": { "id": { "$oid": "000000000000000000000001" } } } ], "expectations": [ { "command_started_event": { "command": { "find": "fs.files", "filter": { "_id": { "$oid": "000000000000000000000001" } } }, "database_name": "retryable-reads-tests" } }, { "command_started_event": { "command": { "find": "fs.files", "filter": { "_id": { "$oid": "000000000000000000000001" } } }, "database_name": "retryable-reads-tests" } }, { "command_started_event": { "command": { "find": "fs.chunks", "filter": { "files_id": { "$oid": "000000000000000000000001" } }, "sort": { "n": 1 } }, "database_name": "retryable-reads-tests" } } ] }, { "description": "Download fails on first attempt", "clientOptions": { "retryReads": false }, "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "find" ], "closeConnection": true } }, "operations": [ { "name": "download", "object": "gridfsbucket", "arguments": { "id": { "$oid": "000000000000000000000001" } }, "error": true } ], "expectations": [ { "command_started_event": { "command": { "find": "fs.files", "filter": { "_id": { "$oid": "000000000000000000000001" } } }, "database_name": "retryable-reads-tests" } } ] }, { "description": "Download fails on second attempt", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 2 }, "data": { "failCommands": [ "find" ], "closeConnection": true } }, "operations": [ { "name": "download", "object": "gridfsbucket", "arguments": { "id": { "$oid": "000000000000000000000001" } }, "error": true } ], "expectations": [ { "command_started_event": { "command": { "find": "fs.files", "filter": { "_id": { "$oid": "000000000000000000000001" } } }, "database_name": "retryable-reads-tests" } }, { "command_started_event": { "command": { "find": "fs.files", "filter": { "_id": { "$oid": "000000000000000000000001" } } }, "database_name": "retryable-reads-tests" } } ] } ] } gridfs-downloadByName-serverErrors.json000066400000000000000000000461341462766011000345330ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/retryable_reads/legacy{ "runOn": [ { "minServerVersion": "4.0", "topology": [ "single", "replicaset" ] }, { "minServerVersion": "4.1.7", "topology": [ "sharded", "load-balanced" ] } ], "database_name": "retryable-reads-tests", "bucket_name": "fs", "data": { "fs.files": [ { "_id": { "$oid": "000000000000000000000001" }, "length": 1, "chunkSize": 4, "uploadDate": { "$date": "1970-01-01T00:00:00.000Z" }, "filename": "abc", "metadata": {} } ], "fs.chunks": [ { "_id": { "$oid": "000000000000000000000002" }, "files_id": { "$oid": "000000000000000000000001" }, "n": 0, "data": { "$binary": { "base64": "EQ==", "subType": "00" } } } ] }, "tests": [ { "description": "DownloadByName succeeds after InterruptedAtShutdown", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "find" ], "errorCode": 11600 } }, "operations": [ { "name": "download_by_name", "object": "gridfsbucket", "arguments": { "filename": "abc" } } ], "expectations": [ { "command_started_event": { "command": { "find": "fs.files", "filter": { "filename": "abc" } }, "database_name": "retryable-reads-tests" } }, { "command_started_event": { "command": { "find": "fs.files", "filter": { "filename": "abc" } }, "database_name": "retryable-reads-tests" } }, { "command_started_event": { "command": { "find": "fs.chunks", "filter": { "files_id": { "$oid": "000000000000000000000001" } }, "sort": { "n": 1 } }, "database_name": "retryable-reads-tests" } } ] }, { "description": "DownloadByName succeeds after InterruptedDueToReplStateChange", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "find" ], "errorCode": 11602 } }, "operations": [ { "name": "download_by_name", "object": "gridfsbucket", "arguments": { "filename": "abc" } } ], "expectations": [ { "command_started_event": { "command": { "find": "fs.files", "filter": { "filename": "abc" } }, "database_name": "retryable-reads-tests" } }, { "command_started_event": { "command": { "find": "fs.files", "filter": { "filename": "abc" } }, "database_name": "retryable-reads-tests" } }, { "command_started_event": { "command": { "find": "fs.chunks", "filter": { "files_id": { "$oid": "000000000000000000000001" } }, "sort": { "n": 1 } }, "database_name": "retryable-reads-tests" } } ] }, { "description": "DownloadByName succeeds after NotWritablePrimary", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "find" ], "errorCode": 10107 } }, "operations": [ { "name": "download_by_name", "object": "gridfsbucket", "arguments": { "filename": "abc" } } ], "expectations": [ { "command_started_event": { "command": { "find": "fs.files", "filter": { "filename": "abc" } }, "database_name": "retryable-reads-tests" } }, { "command_started_event": { "command": { "find": "fs.files", "filter": { "filename": "abc" } }, "database_name": "retryable-reads-tests" } }, { "command_started_event": { "command": { "find": "fs.chunks", "filter": { "files_id": { "$oid": "000000000000000000000001" } }, "sort": { "n": 1 } }, "database_name": "retryable-reads-tests" } } ] }, { "description": "DownloadByName succeeds after NotPrimaryNoSecondaryOk", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "find" ], "errorCode": 13435 } }, "operations": [ { "name": "download_by_name", "object": "gridfsbucket", "arguments": { "filename": "abc" } } ], "expectations": [ { "command_started_event": { "command": { "find": "fs.files", "filter": { "filename": "abc" } }, "database_name": "retryable-reads-tests" } }, { "command_started_event": { "command": { "find": "fs.files", "filter": { "filename": "abc" } }, "database_name": "retryable-reads-tests" } }, { "command_started_event": { "command": { "find": "fs.chunks", "filter": { "files_id": { "$oid": "000000000000000000000001" } }, "sort": { "n": 1 } }, "database_name": "retryable-reads-tests" } } ] }, { "description": "DownloadByName succeeds after NotPrimaryOrSecondary", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "find" ], "errorCode": 13436 } }, "operations": [ { "name": "download_by_name", "object": "gridfsbucket", "arguments": { "filename": "abc" } } ], "expectations": [ { "command_started_event": { "command": { "find": "fs.files", "filter": { "filename": "abc" } }, "database_name": "retryable-reads-tests" } }, { "command_started_event": { "command": { "find": "fs.files", "filter": { "filename": "abc" } }, "database_name": "retryable-reads-tests" } }, { "command_started_event": { "command": { "find": "fs.chunks", "filter": { "files_id": { "$oid": "000000000000000000000001" } }, "sort": { "n": 1 } }, "database_name": "retryable-reads-tests" } } ] }, { "description": "DownloadByName succeeds after PrimarySteppedDown", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "find" ], "errorCode": 189 } }, "operations": [ { "name": "download_by_name", "object": "gridfsbucket", "arguments": { "filename": "abc" } } ], "expectations": [ { "command_started_event": { "command": { "find": "fs.files", "filter": { "filename": "abc" } }, "database_name": "retryable-reads-tests" } }, { "command_started_event": { "command": { "find": "fs.files", "filter": { "filename": "abc" } }, "database_name": "retryable-reads-tests" } }, { "command_started_event": { "command": { "find": "fs.chunks", "filter": { "files_id": { "$oid": "000000000000000000000001" } }, "sort": { "n": 1 } }, "database_name": "retryable-reads-tests" } } ] }, { "description": "DownloadByName succeeds after ShutdownInProgress", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "find" ], "errorCode": 91 } }, "operations": [ { "name": "download_by_name", "object": "gridfsbucket", "arguments": { "filename": "abc" } } ], "expectations": [ { "command_started_event": { "command": { "find": "fs.files", "filter": { "filename": "abc" } }, "database_name": "retryable-reads-tests" } }, { "command_started_event": { "command": { "find": "fs.files", "filter": { "filename": "abc" } }, "database_name": "retryable-reads-tests" } }, { "command_started_event": { "command": { "find": "fs.chunks", "filter": { "files_id": { "$oid": "000000000000000000000001" } }, "sort": { "n": 1 } }, "database_name": "retryable-reads-tests" } } ] }, { "description": "DownloadByName succeeds after HostNotFound", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "find" ], "errorCode": 7 } }, "operations": [ { "name": "download_by_name", "object": "gridfsbucket", "arguments": { "filename": "abc" } } ], "expectations": [ { "command_started_event": { "command": { "find": "fs.files", "filter": { "filename": "abc" } }, "database_name": "retryable-reads-tests" } }, { "command_started_event": { "command": { "find": "fs.files", "filter": { "filename": "abc" } }, "database_name": "retryable-reads-tests" } }, { "command_started_event": { "command": { "find": "fs.chunks", "filter": { "files_id": { "$oid": "000000000000000000000001" } }, "sort": { "n": 1 } }, "database_name": "retryable-reads-tests" } } ] }, { "description": "DownloadByName succeeds after HostUnreachable", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "find" ], "errorCode": 6 } }, "operations": [ { "name": "download_by_name", "object": "gridfsbucket", "arguments": { "filename": "abc" } } ], "expectations": [ { "command_started_event": { "command": { "find": "fs.files", "filter": { "filename": "abc" } }, "database_name": "retryable-reads-tests" } }, { "command_started_event": { "command": { "find": "fs.files", "filter": { "filename": "abc" } }, "database_name": "retryable-reads-tests" } }, { "command_started_event": { "command": { "find": "fs.chunks", "filter": { "files_id": { "$oid": "000000000000000000000001" } }, "sort": { "n": 1 } }, "database_name": "retryable-reads-tests" } } ] }, { "description": "DownloadByName succeeds after NetworkTimeout", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "find" ], "errorCode": 89 } }, "operations": [ { "name": "download_by_name", "object": "gridfsbucket", "arguments": { "filename": "abc" } } ], "expectations": [ { "command_started_event": { "command": { "find": "fs.files", "filter": { "filename": "abc" } }, "database_name": "retryable-reads-tests" } }, { "command_started_event": { "command": { "find": "fs.files", "filter": { "filename": "abc" } }, "database_name": "retryable-reads-tests" } }, { "command_started_event": { "command": { "find": "fs.chunks", "filter": { "files_id": { "$oid": "000000000000000000000001" } }, "sort": { "n": 1 } }, "database_name": "retryable-reads-tests" } } ] }, { "description": "DownloadByName succeeds after SocketException", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "find" ], "errorCode": 9001 } }, "operations": [ { "name": "download_by_name", "object": "gridfsbucket", "arguments": { "filename": "abc" } } ], "expectations": [ { "command_started_event": { "command": { "find": "fs.files", "filter": { "filename": "abc" } }, "database_name": "retryable-reads-tests" } }, { "command_started_event": { "command": { "find": "fs.files", "filter": { "filename": "abc" } }, "database_name": "retryable-reads-tests" } }, { "command_started_event": { "command": { "find": "fs.chunks", "filter": { "files_id": { "$oid": "000000000000000000000001" } }, "sort": { "n": 1 } }, "database_name": "retryable-reads-tests" } } ] }, { "description": "DownloadByName fails after two NotWritablePrimary errors", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 2 }, "data": { "failCommands": [ "find" ], "errorCode": 10107 } }, "operations": [ { "name": "download_by_name", "object": "gridfsbucket", "arguments": { "filename": "abc" }, "error": true } ], "expectations": [ { "command_started_event": { "command": { "find": "fs.files", "filter": { "filename": "abc" } }, "database_name": "retryable-reads-tests" } }, { "command_started_event": { "command": { "find": "fs.files", "filter": { "filename": "abc" } }, "database_name": "retryable-reads-tests" } } ] }, { "description": "DownloadByName fails after NotWritablePrimary when retryReads is false", "clientOptions": { "retryReads": false }, "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "find" ], "errorCode": 10107 } }, "operations": [ { "name": "download_by_name", "object": "gridfsbucket", "arguments": { "filename": "abc" }, "error": true } ], "expectations": [ { "command_started_event": { "command": { "find": "fs.files", "filter": { "filename": "abc" } }, "database_name": "retryable-reads-tests" } } ] } ] } mongodb-mongo-python-driver-509e9b7/test/retryable_reads/legacy/gridfs-downloadByName.json000066400000000000000000000125411462766011000321040ustar00rootroot00000000000000{ "runOn": [ { "minServerVersion": "4.0", "topology": [ "single", "replicaset" ] }, { "minServerVersion": "4.1.7", "topology": [ "sharded", "load-balanced" ] } ], "database_name": "retryable-reads-tests", "bucket_name": "fs", "data": { "fs.files": [ { "_id": { "$oid": "000000000000000000000001" }, "length": 1, "chunkSize": 4, "uploadDate": { "$date": "1970-01-01T00:00:00.000Z" }, "filename": "abc", "metadata": {} } ], "fs.chunks": [ { "_id": { "$oid": "000000000000000000000002" }, "files_id": { "$oid": "000000000000000000000001" }, "n": 0, "data": { "$binary": { "base64": "EQ==", "subType": "00" } } } ] }, "tests": [ { "description": "DownloadByName succeeds on first attempt", "operations": [ { "name": "download_by_name", "object": "gridfsbucket", "arguments": { "filename": "abc" } } ], "expectations": [ { "command_started_event": { "command": { "find": "fs.files", "filter": { "filename": "abc" } }, "database_name": "retryable-reads-tests" } }, { "command_started_event": { "command": { "find": "fs.chunks", "filter": { "files_id": { "$oid": "000000000000000000000001" } }, "sort": { "n": 1 } }, "database_name": "retryable-reads-tests" } } ] }, { "description": "DownloadByName succeeds on second attempt", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "find" ], "closeConnection": true } }, "operations": [ { "name": "download_by_name", "object": "gridfsbucket", "arguments": { "filename": "abc" } } ], "expectations": [ { "command_started_event": { "command": { "find": "fs.files", "filter": { "filename": "abc" } }, "database_name": "retryable-reads-tests" } }, { "command_started_event": { "command": { "find": "fs.files", "filter": { "filename": "abc" } }, "database_name": "retryable-reads-tests" } }, { "command_started_event": { "command": { "find": "fs.chunks", "filter": { "files_id": { "$oid": "000000000000000000000001" } }, "sort": { "n": 1 } }, "database_name": "retryable-reads-tests" } } ] }, { "description": "DownloadByName fails on first attempt", "clientOptions": { "retryReads": false }, "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "find" ], "closeConnection": true } }, "operations": [ { "name": "download_by_name", "object": "gridfsbucket", "arguments": { "filename": "abc" }, "error": true } ], "expectations": [ { "command_started_event": { "command": { "find": "fs.files", "filter": { "filename": "abc" } }, "database_name": "retryable-reads-tests" } } ] }, { "description": "DownloadByName fails on second attempt", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 2 }, "data": { "failCommands": [ "find" ], "closeConnection": true } }, "operations": [ { "name": "download_by_name", "object": "gridfsbucket", "arguments": { "filename": "abc" }, "error": true } ], "expectations": [ { "command_started_event": { "command": { "find": "fs.files", "filter": { "filename": "abc" } }, "database_name": "retryable-reads-tests" } }, { "command_started_event": { "command": { "find": "fs.files", "filter": { "filename": "abc" } }, "database_name": "retryable-reads-tests" } } ] } ] } listCollectionNames-serverErrors.json000066400000000000000000000245031462766011000343230ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/retryable_reads/legacy{ "runOn": [ { "minServerVersion": "4.0", "topology": [ "single", "replicaset" ] }, { "minServerVersion": "4.1.7", "topology": [ "sharded", "load-balanced" ] } ], "database_name": "retryable-reads-tests", "collection_name": "coll", "data": [], "tests": [ { "description": "ListCollectionNames succeeds after InterruptedAtShutdown", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "listCollections" ], "errorCode": 11600 } }, "operations": [ { "name": "listCollectionNames", "object": "database" } ], "expectations": [ { "command_started_event": { "command": { "listCollections": 1 } } }, { "command_started_event": { "command": { "listCollections": 1 } } } ] }, { "description": "ListCollectionNames succeeds after InterruptedDueToReplStateChange", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "listCollections" ], "errorCode": 11602 } }, "operations": [ { "name": "listCollectionNames", "object": "database" } ], "expectations": [ { "command_started_event": { "command": { "listCollections": 1 } } }, { "command_started_event": { "command": { "listCollections": 1 } } } ] }, { "description": "ListCollectionNames succeeds after NotWritablePrimary", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "listCollections" ], "errorCode": 10107 } }, "operations": [ { "name": "listCollectionNames", "object": "database" } ], "expectations": [ { "command_started_event": { "command": { "listCollections": 1 } } }, { "command_started_event": { "command": { "listCollections": 1 } } } ] }, { "description": "ListCollectionNames succeeds after NotPrimaryNoSecondaryOk", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "listCollections" ], "errorCode": 13435 } }, "operations": [ { "name": "listCollectionNames", "object": "database" } ], "expectations": [ { "command_started_event": { "command": { "listCollections": 1 } } }, { "command_started_event": { "command": { "listCollections": 1 } } } ] }, { "description": "ListCollectionNames succeeds after NotPrimaryOrSecondary", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "listCollections" ], "errorCode": 13436 } }, "operations": [ { "name": "listCollectionNames", "object": "database" } ], "expectations": [ { "command_started_event": { "command": { "listCollections": 1 } } }, { "command_started_event": { "command": { "listCollections": 1 } } } ] }, { "description": "ListCollectionNames succeeds after PrimarySteppedDown", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "listCollections" ], "errorCode": 189 } }, "operations": [ { "name": "listCollectionNames", "object": "database" } ], "expectations": [ { "command_started_event": { "command": { "listCollections": 1 } } }, { "command_started_event": { "command": { "listCollections": 1 } } } ] }, { "description": "ListCollectionNames succeeds after ShutdownInProgress", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "listCollections" ], "errorCode": 91 } }, "operations": [ { "name": "listCollectionNames", "object": "database" } ], "expectations": [ { "command_started_event": { "command": { "listCollections": 1 } } }, { "command_started_event": { "command": { "listCollections": 1 } } } ] }, { "description": "ListCollectionNames succeeds after HostNotFound", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "listCollections" ], "errorCode": 7 } }, "operations": [ { "name": "listCollectionNames", "object": "database" } ], "expectations": [ { "command_started_event": { "command": { "listCollections": 1 } } }, { "command_started_event": { "command": { "listCollections": 1 } } } ] }, { "description": "ListCollectionNames succeeds after HostUnreachable", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "listCollections" ], "errorCode": 6 } }, "operations": [ { "name": "listCollectionNames", "object": "database" } ], "expectations": [ { "command_started_event": { "command": { "listCollections": 1 } } }, { "command_started_event": { "command": { "listCollections": 1 } } } ] }, { "description": "ListCollectionNames succeeds after NetworkTimeout", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "listCollections" ], "errorCode": 89 } }, "operations": [ { "name": "listCollectionNames", "object": "database" } ], "expectations": [ { "command_started_event": { "command": { "listCollections": 1 } } }, { "command_started_event": { "command": { "listCollections": 1 } } } ] }, { "description": "ListCollectionNames succeeds after SocketException", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "listCollections" ], "errorCode": 9001 } }, "operations": [ { "name": "listCollectionNames", "object": "database" } ], "expectations": [ { "command_started_event": { "command": { "listCollections": 1 } } }, { "command_started_event": { "command": { "listCollections": 1 } } } ] }, { "description": "ListCollectionNames fails after two NotWritablePrimary errors", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 2 }, "data": { "failCommands": [ "listCollections" ], "errorCode": 10107 } }, "operations": [ { "name": "listCollectionNames", "object": "database", "error": true } ], "expectations": [ { "command_started_event": { "command": { "listCollections": 1 } } }, { "command_started_event": { "command": { "listCollections": 1 } } } ] }, { "description": "ListCollectionNames fails after NotWritablePrimary when retryReads is false", "clientOptions": { "retryReads": false }, "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "listCollections" ], "errorCode": 10107 } }, "operations": [ { "name": "listCollectionNames", "object": "database", "error": true } ], "expectations": [ { "command_started_event": { "command": { "listCollections": 1 } } } ] } ] } mongodb-mongo-python-driver-509e9b7/test/retryable_reads/legacy/listCollectionNames.json000066400000000000000000000057521462766011000317060ustar00rootroot00000000000000{ "runOn": [ { "minServerVersion": "4.0", "topology": [ "single", "replicaset" ] }, { "minServerVersion": "4.1.7", "topology": [ "sharded", "load-balanced" ] } ], "database_name": "retryable-reads-tests", "collection_name": "coll", "data": [], "tests": [ { "description": "ListCollectionNames succeeds on first attempt", "operations": [ { "name": "listCollectionNames", "object": "database" } ], "expectations": [ { "command_started_event": { "command": { "listCollections": 1 } } } ] }, { "description": "ListCollectionNames succeeds on second attempt", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "listCollections" ], "closeConnection": true } }, "operations": [ { "name": "listCollectionNames", "object": "database" } ], "expectations": [ { "command_started_event": { "command": { "listCollections": 1 } } }, { "command_started_event": { "command": { "listCollections": 1 } } } ] }, { "description": "ListCollectionNames fails on first attempt", "clientOptions": { "retryReads": false }, "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "listCollections" ], "closeConnection": true } }, "operations": [ { "name": "listCollectionNames", "object": "database", "error": true } ], "expectations": [ { "command_started_event": { "command": { "listCollections": 1 } } } ] }, { "description": "ListCollectionNames fails on second attempt", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 2 }, "data": { "failCommands": [ "listCollections" ], "closeConnection": true } }, "operations": [ { "name": "listCollectionNames", "object": "database", "error": true } ], "expectations": [ { "command_started_event": { "command": { "listCollections": 1 } } }, { "command_started_event": { "command": { "listCollections": 1 } } } ] } ] } listCollectionObjects-serverErrors.json000066400000000000000000000245671462766011000346630ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/retryable_reads/legacy{ "runOn": [ { "minServerVersion": "4.0", "topology": [ "single", "replicaset" ] }, { "minServerVersion": "4.1.7", "topology": [ "sharded", "load-balanced" ] } ], "database_name": "retryable-reads-tests", "collection_name": "coll", "data": [], "tests": [ { "description": "ListCollectionObjects succeeds after InterruptedAtShutdown", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "listCollections" ], "errorCode": 11600 } }, "operations": [ { "name": "listCollectionObjects", "object": "database" } ], "expectations": [ { "command_started_event": { "command": { "listCollections": 1 } } }, { "command_started_event": { "command": { "listCollections": 1 } } } ] }, { "description": "ListCollectionObjects succeeds after InterruptedDueToReplStateChange", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "listCollections" ], "errorCode": 11602 } }, "operations": [ { "name": "listCollectionObjects", "object": "database" } ], "expectations": [ { "command_started_event": { "command": { "listCollections": 1 } } }, { "command_started_event": { "command": { "listCollections": 1 } } } ] }, { "description": "ListCollectionObjects succeeds after NotWritablePrimary", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "listCollections" ], "errorCode": 10107 } }, "operations": [ { "name": "listCollectionObjects", "object": "database" } ], "expectations": [ { "command_started_event": { "command": { "listCollections": 1 } } }, { "command_started_event": { "command": { "listCollections": 1 } } } ] }, { "description": "ListCollectionObjects succeeds after NotPrimaryNoSecondaryOk", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "listCollections" ], "errorCode": 13435 } }, "operations": [ { "name": "listCollectionObjects", "object": "database" } ], "expectations": [ { "command_started_event": { "command": { "listCollections": 1 } } }, { "command_started_event": { "command": { "listCollections": 1 } } } ] }, { "description": "ListCollectionObjects succeeds after NotPrimaryOrSecondary", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "listCollections" ], "errorCode": 13436 } }, "operations": [ { "name": "listCollectionObjects", "object": "database" } ], "expectations": [ { "command_started_event": { "command": { "listCollections": 1 } } }, { "command_started_event": { "command": { "listCollections": 1 } } } ] }, { "description": "ListCollectionObjects succeeds after PrimarySteppedDown", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "listCollections" ], "errorCode": 189 } }, "operations": [ { "name": "listCollectionObjects", "object": "database" } ], "expectations": [ { "command_started_event": { "command": { "listCollections": 1 } } }, { "command_started_event": { "command": { "listCollections": 1 } } } ] }, { "description": "ListCollectionObjects succeeds after ShutdownInProgress", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "listCollections" ], "errorCode": 91 } }, "operations": [ { "name": "listCollectionObjects", "object": "database" } ], "expectations": [ { "command_started_event": { "command": { "listCollections": 1 } } }, { "command_started_event": { "command": { "listCollections": 1 } } } ] }, { "description": "ListCollectionObjects succeeds after HostNotFound", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "listCollections" ], "errorCode": 7 } }, "operations": [ { "name": "listCollectionObjects", "object": "database" } ], "expectations": [ { "command_started_event": { "command": { "listCollections": 1 } } }, { "command_started_event": { "command": { "listCollections": 1 } } } ] }, { "description": "ListCollectionObjects succeeds after HostUnreachable", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "listCollections" ], "errorCode": 6 } }, "operations": [ { "name": "listCollectionObjects", "object": "database" } ], "expectations": [ { "command_started_event": { "command": { "listCollections": 1 } } }, { "command_started_event": { "command": { "listCollections": 1 } } } ] }, { "description": "ListCollectionObjects succeeds after NetworkTimeout", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "listCollections" ], "errorCode": 89 } }, "operations": [ { "name": "listCollectionObjects", "object": "database" } ], "expectations": [ { "command_started_event": { "command": { "listCollections": 1 } } }, { "command_started_event": { "command": { "listCollections": 1 } } } ] }, { "description": "ListCollectionObjects succeeds after SocketException", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "listCollections" ], "errorCode": 9001 } }, "operations": [ { "name": "listCollectionObjects", "object": "database" } ], "expectations": [ { "command_started_event": { "command": { "listCollections": 1 } } }, { "command_started_event": { "command": { "listCollections": 1 } } } ] }, { "description": "ListCollectionObjects fails after two NotWritablePrimary errors", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 2 }, "data": { "failCommands": [ "listCollections" ], "errorCode": 10107 } }, "operations": [ { "name": "listCollectionObjects", "object": "database", "error": true } ], "expectations": [ { "command_started_event": { "command": { "listCollections": 1 } } }, { "command_started_event": { "command": { "listCollections": 1 } } } ] }, { "description": "ListCollectionObjects fails after NotWritablePrimary when retryReads is false", "clientOptions": { "retryReads": false }, "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "listCollections" ], "errorCode": 10107 } }, "operations": [ { "name": "listCollectionObjects", "object": "database", "error": true } ], "expectations": [ { "command_started_event": { "command": { "listCollections": 1 } } } ] } ] } mongodb-mongo-python-driver-509e9b7/test/retryable_reads/legacy/listCollectionObjects.json000066400000000000000000000057721462766011000322360ustar00rootroot00000000000000{ "runOn": [ { "minServerVersion": "4.0", "topology": [ "single", "replicaset" ] }, { "minServerVersion": "4.1.7", "topology": [ "sharded", "load-balanced" ] } ], "database_name": "retryable-reads-tests", "collection_name": "coll", "data": [], "tests": [ { "description": "ListCollectionObjects succeeds on first attempt", "operations": [ { "name": "listCollectionObjects", "object": "database" } ], "expectations": [ { "command_started_event": { "command": { "listCollections": 1 } } } ] }, { "description": "ListCollectionObjects succeeds on second attempt", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "listCollections" ], "closeConnection": true } }, "operations": [ { "name": "listCollectionObjects", "object": "database" } ], "expectations": [ { "command_started_event": { "command": { "listCollections": 1 } } }, { "command_started_event": { "command": { "listCollections": 1 } } } ] }, { "description": "ListCollectionObjects fails on first attempt", "clientOptions": { "retryReads": false }, "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "listCollections" ], "closeConnection": true } }, "operations": [ { "name": "listCollectionObjects", "object": "database", "error": true } ], "expectations": [ { "command_started_event": { "command": { "listCollections": 1 } } } ] }, { "description": "ListCollectionObjects fails on second attempt", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 2 }, "data": { "failCommands": [ "listCollections" ], "closeConnection": true } }, "operations": [ { "name": "listCollectionObjects", "object": "database", "error": true } ], "expectations": [ { "command_started_event": { "command": { "listCollections": 1 } } }, { "command_started_event": { "command": { "listCollections": 1 } } } ] } ] } mongodb-mongo-python-driver-509e9b7/test/retryable_reads/legacy/listCollections-serverErrors.json000066400000000000000000000243331462766011000336020ustar00rootroot00000000000000{ "runOn": [ { "minServerVersion": "4.0", "topology": [ "single", "replicaset" ] }, { "minServerVersion": "4.1.7", "topology": [ "sharded", "load-balanced" ] } ], "database_name": "retryable-reads-tests", "collection_name": "coll", "data": [], "tests": [ { "description": "ListCollections succeeds after InterruptedAtShutdown", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "listCollections" ], "errorCode": 11600 } }, "operations": [ { "name": "listCollections", "object": "database" } ], "expectations": [ { "command_started_event": { "command": { "listCollections": 1 } } }, { "command_started_event": { "command": { "listCollections": 1 } } } ] }, { "description": "ListCollections succeeds after InterruptedDueToReplStateChange", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "listCollections" ], "errorCode": 11602 } }, "operations": [ { "name": "listCollections", "object": "database" } ], "expectations": [ { "command_started_event": { "command": { "listCollections": 1 } } }, { "command_started_event": { "command": { "listCollections": 1 } } } ] }, { "description": "ListCollections succeeds after NotWritablePrimary", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "listCollections" ], "errorCode": 10107 } }, "operations": [ { "name": "listCollections", "object": "database" } ], "expectations": [ { "command_started_event": { "command": { "listCollections": 1 } } }, { "command_started_event": { "command": { "listCollections": 1 } } } ] }, { "description": "ListCollections succeeds after NotPrimaryNoSecondaryOk", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "listCollections" ], "errorCode": 13435 } }, "operations": [ { "name": "listCollections", "object": "database" } ], "expectations": [ { "command_started_event": { "command": { "listCollections": 1 } } }, { "command_started_event": { "command": { "listCollections": 1 } } } ] }, { "description": "ListCollections succeeds after NotPrimaryOrSecondary", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "listCollections" ], "errorCode": 13436 } }, "operations": [ { "name": "listCollections", "object": "database" } ], "expectations": [ { "command_started_event": { "command": { "listCollections": 1 } } }, { "command_started_event": { "command": { "listCollections": 1 } } } ] }, { "description": "ListCollections succeeds after PrimarySteppedDown", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "listCollections" ], "errorCode": 189 } }, "operations": [ { "name": "listCollections", "object": "database" } ], "expectations": [ { "command_started_event": { "command": { "listCollections": 1 } } }, { "command_started_event": { "command": { "listCollections": 1 } } } ] }, { "description": "ListCollections succeeds after ShutdownInProgress", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "listCollections" ], "errorCode": 91 } }, "operations": [ { "name": "listCollections", "object": "database" } ], "expectations": [ { "command_started_event": { "command": { "listCollections": 1 } } }, { "command_started_event": { "command": { "listCollections": 1 } } } ] }, { "description": "ListCollections succeeds after HostNotFound", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "listCollections" ], "errorCode": 7 } }, "operations": [ { "name": "listCollections", "object": "database" } ], "expectations": [ { "command_started_event": { "command": { "listCollections": 1 } } }, { "command_started_event": { "command": { "listCollections": 1 } } } ] }, { "description": "ListCollections succeeds after HostUnreachable", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "listCollections" ], "errorCode": 6 } }, "operations": [ { "name": "listCollections", "object": "database" } ], "expectations": [ { "command_started_event": { "command": { "listCollections": 1 } } }, { "command_started_event": { "command": { "listCollections": 1 } } } ] }, { "description": "ListCollections succeeds after NetworkTimeout", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "listCollections" ], "errorCode": 89 } }, "operations": [ { "name": "listCollections", "object": "database" } ], "expectations": [ { "command_started_event": { "command": { "listCollections": 1 } } }, { "command_started_event": { "command": { "listCollections": 1 } } } ] }, { "description": "ListCollections succeeds after SocketException", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "listCollections" ], "errorCode": 9001 } }, "operations": [ { "name": "listCollections", "object": "database" } ], "expectations": [ { "command_started_event": { "command": { "listCollections": 1 } } }, { "command_started_event": { "command": { "listCollections": 1 } } } ] }, { "description": "ListCollections fails after two NotWritablePrimary errors", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 2 }, "data": { "failCommands": [ "listCollections" ], "errorCode": 10107 } }, "operations": [ { "name": "listCollections", "object": "database", "error": true } ], "expectations": [ { "command_started_event": { "command": { "listCollections": 1 } } }, { "command_started_event": { "command": { "listCollections": 1 } } } ] }, { "description": "ListCollections fails after NotWritablePrimary when retryReads is false", "clientOptions": { "retryReads": false }, "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "listCollections" ], "errorCode": 10107 } }, "operations": [ { "name": "listCollections", "object": "database", "error": true } ], "expectations": [ { "command_started_event": { "command": { "listCollections": 1 } } } ] } ] } mongodb-mongo-python-driver-509e9b7/test/retryable_reads/legacy/listCollections.json000066400000000000000000000057121462766011000311010ustar00rootroot00000000000000{ "runOn": [ { "minServerVersion": "4.0", "topology": [ "single", "replicaset" ] }, { "minServerVersion": "4.1.7", "topology": [ "sharded", "load-balanced" ] } ], "database_name": "retryable-reads-tests", "collection_name": "coll", "data": [], "tests": [ { "description": "ListCollections succeeds on first attempt", "operations": [ { "name": "listCollections", "object": "database" } ], "expectations": [ { "command_started_event": { "command": { "listCollections": 1 } } } ] }, { "description": "ListCollections succeeds on second attempt", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "listCollections" ], "closeConnection": true } }, "operations": [ { "name": "listCollections", "object": "database" } ], "expectations": [ { "command_started_event": { "command": { "listCollections": 1 } } }, { "command_started_event": { "command": { "listCollections": 1 } } } ] }, { "description": "ListCollections fails on first attempt", "clientOptions": { "retryReads": false }, "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "listCollections" ], "closeConnection": true } }, "operations": [ { "name": "listCollections", "object": "database", "error": true } ], "expectations": [ { "command_started_event": { "command": { "listCollections": 1 } } } ] }, { "description": "ListCollections fails on second attempt", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 2 }, "data": { "failCommands": [ "listCollections" ], "closeConnection": true } }, "operations": [ { "name": "listCollections", "object": "database", "error": true } ], "expectations": [ { "command_started_event": { "command": { "listCollections": 1 } } }, { "command_started_event": { "command": { "listCollections": 1 } } } ] } ] } mongodb-mongo-python-driver-509e9b7/test/retryable_reads/legacy/listDatabaseNames-serverErrors.json000066400000000000000000000242511462766011000340130ustar00rootroot00000000000000{ "runOn": [ { "minServerVersion": "4.0", "topology": [ "single", "replicaset" ] }, { "minServerVersion": "4.1.7", "topology": [ "sharded", "load-balanced" ] } ], "database_name": "retryable-reads-tests", "collection_name": "coll", "data": [], "tests": [ { "description": "ListDatabaseNames succeeds after InterruptedAtShutdown", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "listDatabases" ], "errorCode": 11600 } }, "operations": [ { "name": "listDatabaseNames", "object": "client" } ], "expectations": [ { "command_started_event": { "command": { "listDatabases": 1 } } }, { "command_started_event": { "command": { "listDatabases": 1 } } } ] }, { "description": "ListDatabaseNames succeeds after InterruptedDueToReplStateChange", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "listDatabases" ], "errorCode": 11602 } }, "operations": [ { "name": "listDatabaseNames", "object": "client" } ], "expectations": [ { "command_started_event": { "command": { "listDatabases": 1 } } }, { "command_started_event": { "command": { "listDatabases": 1 } } } ] }, { "description": "ListDatabaseNames succeeds after NotWritablePrimary", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "listDatabases" ], "errorCode": 10107 } }, "operations": [ { "name": "listDatabaseNames", "object": "client" } ], "expectations": [ { "command_started_event": { "command": { "listDatabases": 1 } } }, { "command_started_event": { "command": { "listDatabases": 1 } } } ] }, { "description": "ListDatabaseNames succeeds after NotPrimaryNoSecondaryOk", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "listDatabases" ], "errorCode": 13435 } }, "operations": [ { "name": "listDatabaseNames", "object": "client" } ], "expectations": [ { "command_started_event": { "command": { "listDatabases": 1 } } }, { "command_started_event": { "command": { "listDatabases": 1 } } } ] }, { "description": "ListDatabaseNames succeeds after NotPrimaryOrSecondary", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "listDatabases" ], "errorCode": 13436 } }, "operations": [ { "name": "listDatabaseNames", "object": "client" } ], "expectations": [ { "command_started_event": { "command": { "listDatabases": 1 } } }, { "command_started_event": { "command": { "listDatabases": 1 } } } ] }, { "description": "ListDatabaseNames succeeds after PrimarySteppedDown", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "listDatabases" ], "errorCode": 189 } }, "operations": [ { "name": "listDatabaseNames", "object": "client" } ], "expectations": [ { "command_started_event": { "command": { "listDatabases": 1 } } }, { "command_started_event": { "command": { "listDatabases": 1 } } } ] }, { "description": "ListDatabaseNames succeeds after ShutdownInProgress", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "listDatabases" ], "errorCode": 91 } }, "operations": [ { "name": "listDatabaseNames", "object": "client" } ], "expectations": [ { "command_started_event": { "command": { "listDatabases": 1 } } }, { "command_started_event": { "command": { "listDatabases": 1 } } } ] }, { "description": "ListDatabaseNames succeeds after HostNotFound", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "listDatabases" ], "errorCode": 7 } }, "operations": [ { "name": "listDatabaseNames", "object": "client" } ], "expectations": [ { "command_started_event": { "command": { "listDatabases": 1 } } }, { "command_started_event": { "command": { "listDatabases": 1 } } } ] }, { "description": "ListDatabaseNames succeeds after HostUnreachable", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "listDatabases" ], "errorCode": 6 } }, "operations": [ { "name": "listDatabaseNames", "object": "client" } ], "expectations": [ { "command_started_event": { "command": { "listDatabases": 1 } } }, { "command_started_event": { "command": { "listDatabases": 1 } } } ] }, { "description": "ListDatabaseNames succeeds after NetworkTimeout", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "listDatabases" ], "errorCode": 89 } }, "operations": [ { "name": "listDatabaseNames", "object": "client" } ], "expectations": [ { "command_started_event": { "command": { "listDatabases": 1 } } }, { "command_started_event": { "command": { "listDatabases": 1 } } } ] }, { "description": "ListDatabaseNames succeeds after SocketException", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "listDatabases" ], "errorCode": 9001 } }, "operations": [ { "name": "listDatabaseNames", "object": "client" } ], "expectations": [ { "command_started_event": { "command": { "listDatabases": 1 } } }, { "command_started_event": { "command": { "listDatabases": 1 } } } ] }, { "description": "ListDatabaseNames fails after two NotWritablePrimary errors", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 2 }, "data": { "failCommands": [ "listDatabases" ], "errorCode": 10107 } }, "operations": [ { "name": "listDatabaseNames", "object": "client", "error": true } ], "expectations": [ { "command_started_event": { "command": { "listDatabases": 1 } } }, { "command_started_event": { "command": { "listDatabases": 1 } } } ] }, { "description": "ListDatabaseNames fails after NotWritablePrimary when retryReads is false", "clientOptions": { "retryReads": false }, "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "listDatabases" ], "errorCode": 10107 } }, "operations": [ { "name": "listDatabaseNames", "object": "client", "error": true } ], "expectations": [ { "command_started_event": { "command": { "listDatabases": 1 } } } ] } ] } mongodb-mongo-python-driver-509e9b7/test/retryable_reads/legacy/listDatabaseNames.json000066400000000000000000000057001462766011000313100ustar00rootroot00000000000000{ "runOn": [ { "minServerVersion": "4.0", "topology": [ "single", "replicaset" ] }, { "minServerVersion": "4.1.7", "topology": [ "sharded", "load-balanced" ] } ], "database_name": "retryable-reads-tests", "collection_name": "coll", "data": [], "tests": [ { "description": "ListDatabaseNames succeeds on first attempt", "operations": [ { "name": "listDatabaseNames", "object": "client" } ], "expectations": [ { "command_started_event": { "command": { "listDatabases": 1 } } } ] }, { "description": "ListDatabaseNames succeeds on second attempt", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "listDatabases" ], "closeConnection": true } }, "operations": [ { "name": "listDatabaseNames", "object": "client" } ], "expectations": [ { "command_started_event": { "command": { "listDatabases": 1 } } }, { "command_started_event": { "command": { "listDatabases": 1 } } } ] }, { "description": "ListDatabaseNames fails on first attempt", "clientOptions": { "retryReads": false }, "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "listDatabases" ], "closeConnection": true } }, "operations": [ { "name": "listDatabaseNames", "object": "client", "error": true } ], "expectations": [ { "command_started_event": { "command": { "listDatabases": 1 } } } ] }, { "description": "ListDatabaseNames fails on second attempt", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 2 }, "data": { "failCommands": [ "listDatabases" ], "closeConnection": true } }, "operations": [ { "name": "listDatabaseNames", "object": "client", "error": true } ], "expectations": [ { "command_started_event": { "command": { "listDatabases": 1 } } }, { "command_started_event": { "command": { "listDatabases": 1 } } } ] } ] } listDatabaseObjects-serverErrors.json000066400000000000000000000243351462766011000342650ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/retryable_reads/legacy{ "runOn": [ { "minServerVersion": "4.0", "topology": [ "single", "replicaset" ] }, { "minServerVersion": "4.1.7", "topology": [ "sharded", "load-balanced" ] } ], "database_name": "retryable-reads-tests", "collection_name": "coll", "data": [], "tests": [ { "description": "ListDatabaseObjects succeeds after InterruptedAtShutdown", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "listDatabases" ], "errorCode": 11600 } }, "operations": [ { "name": "listDatabaseObjects", "object": "client" } ], "expectations": [ { "command_started_event": { "command": { "listDatabases": 1 } } }, { "command_started_event": { "command": { "listDatabases": 1 } } } ] }, { "description": "ListDatabaseObjects succeeds after InterruptedDueToReplStateChange", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "listDatabases" ], "errorCode": 11602 } }, "operations": [ { "name": "listDatabaseObjects", "object": "client" } ], "expectations": [ { "command_started_event": { "command": { "listDatabases": 1 } } }, { "command_started_event": { "command": { "listDatabases": 1 } } } ] }, { "description": "ListDatabaseObjects succeeds after NotWritablePrimary", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "listDatabases" ], "errorCode": 10107 } }, "operations": [ { "name": "listDatabaseObjects", "object": "client" } ], "expectations": [ { "command_started_event": { "command": { "listDatabases": 1 } } }, { "command_started_event": { "command": { "listDatabases": 1 } } } ] }, { "description": "ListDatabaseObjects succeeds after NotPrimaryNoSecondaryOk", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "listDatabases" ], "errorCode": 13435 } }, "operations": [ { "name": "listDatabaseObjects", "object": "client" } ], "expectations": [ { "command_started_event": { "command": { "listDatabases": 1 } } }, { "command_started_event": { "command": { "listDatabases": 1 } } } ] }, { "description": "ListDatabaseObjects succeeds after NotPrimaryOrSecondary", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "listDatabases" ], "errorCode": 13436 } }, "operations": [ { "name": "listDatabaseObjects", "object": "client" } ], "expectations": [ { "command_started_event": { "command": { "listDatabases": 1 } } }, { "command_started_event": { "command": { "listDatabases": 1 } } } ] }, { "description": "ListDatabaseObjects succeeds after PrimarySteppedDown", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "listDatabases" ], "errorCode": 189 } }, "operations": [ { "name": "listDatabaseObjects", "object": "client" } ], "expectations": [ { "command_started_event": { "command": { "listDatabases": 1 } } }, { "command_started_event": { "command": { "listDatabases": 1 } } } ] }, { "description": "ListDatabaseObjects succeeds after ShutdownInProgress", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "listDatabases" ], "errorCode": 91 } }, "operations": [ { "name": "listDatabaseObjects", "object": "client" } ], "expectations": [ { "command_started_event": { "command": { "listDatabases": 1 } } }, { "command_started_event": { "command": { "listDatabases": 1 } } } ] }, { "description": "ListDatabaseObjects succeeds after HostNotFound", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "listDatabases" ], "errorCode": 7 } }, "operations": [ { "name": "listDatabaseObjects", "object": "client" } ], "expectations": [ { "command_started_event": { "command": { "listDatabases": 1 } } }, { "command_started_event": { "command": { "listDatabases": 1 } } } ] }, { "description": "ListDatabaseObjects succeeds after HostUnreachable", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "listDatabases" ], "errorCode": 6 } }, "operations": [ { "name": "listDatabaseObjects", "object": "client" } ], "expectations": [ { "command_started_event": { "command": { "listDatabases": 1 } } }, { "command_started_event": { "command": { "listDatabases": 1 } } } ] }, { "description": "ListDatabaseObjects succeeds after NetworkTimeout", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "listDatabases" ], "errorCode": 89 } }, "operations": [ { "name": "listDatabaseObjects", "object": "client" } ], "expectations": [ { "command_started_event": { "command": { "listDatabases": 1 } } }, { "command_started_event": { "command": { "listDatabases": 1 } } } ] }, { "description": "ListDatabaseObjects succeeds after SocketException", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "listDatabases" ], "errorCode": 9001 } }, "operations": [ { "name": "listDatabaseObjects", "object": "client" } ], "expectations": [ { "command_started_event": { "command": { "listDatabases": 1 } } }, { "command_started_event": { "command": { "listDatabases": 1 } } } ] }, { "description": "ListDatabaseObjects fails after two NotWritablePrimary errors", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 2 }, "data": { "failCommands": [ "listDatabases" ], "errorCode": 10107 } }, "operations": [ { "name": "listDatabaseObjects", "object": "client", "error": true } ], "expectations": [ { "command_started_event": { "command": { "listDatabases": 1 } } }, { "command_started_event": { "command": { "listDatabases": 1 } } } ] }, { "description": "ListDatabaseObjects fails after NotWritablePrimary when retryReads is false", "clientOptions": { "retryReads": false }, "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "listDatabases" ], "errorCode": 10107 } }, "operations": [ { "name": "listDatabaseObjects", "object": "client", "error": true } ], "expectations": [ { "command_started_event": { "command": { "listDatabases": 1 } } } ] } ] } mongodb-mongo-python-driver-509e9b7/test/retryable_reads/legacy/listDatabaseObjects.json000066400000000000000000000057201462766011000316400ustar00rootroot00000000000000{ "runOn": [ { "minServerVersion": "4.0", "topology": [ "single", "replicaset" ] }, { "minServerVersion": "4.1.7", "topology": [ "sharded", "load-balanced" ] } ], "database_name": "retryable-reads-tests", "collection_name": "coll", "data": [], "tests": [ { "description": "ListDatabaseObjects succeeds on first attempt", "operations": [ { "name": "listDatabaseObjects", "object": "client" } ], "expectations": [ { "command_started_event": { "command": { "listDatabases": 1 } } } ] }, { "description": "ListDatabaseObjects succeeds on second attempt", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "listDatabases" ], "closeConnection": true } }, "operations": [ { "name": "listDatabaseObjects", "object": "client" } ], "expectations": [ { "command_started_event": { "command": { "listDatabases": 1 } } }, { "command_started_event": { "command": { "listDatabases": 1 } } } ] }, { "description": "ListDatabaseObjects fails on first attempt", "clientOptions": { "retryReads": false }, "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "listDatabases" ], "closeConnection": true } }, "operations": [ { "name": "listDatabaseObjects", "object": "client", "error": true } ], "expectations": [ { "command_started_event": { "command": { "listDatabases": 1 } } } ] }, { "description": "ListDatabaseObjects fails on second attempt", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 2 }, "data": { "failCommands": [ "listDatabases" ], "closeConnection": true } }, "operations": [ { "name": "listDatabaseObjects", "object": "client", "error": true } ], "expectations": [ { "command_started_event": { "command": { "listDatabases": 1 } } }, { "command_started_event": { "command": { "listDatabases": 1 } } } ] } ] } mongodb-mongo-python-driver-509e9b7/test/retryable_reads/legacy/listDatabases-serverErrors.json000066400000000000000000000241011462766011000332040ustar00rootroot00000000000000{ "runOn": [ { "minServerVersion": "4.0", "topology": [ "single", "replicaset" ] }, { "minServerVersion": "4.1.7", "topology": [ "sharded", "load-balanced" ] } ], "database_name": "retryable-reads-tests", "collection_name": "coll", "data": [], "tests": [ { "description": "ListDatabases succeeds after InterruptedAtShutdown", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "listDatabases" ], "errorCode": 11600 } }, "operations": [ { "name": "listDatabases", "object": "client" } ], "expectations": [ { "command_started_event": { "command": { "listDatabases": 1 } } }, { "command_started_event": { "command": { "listDatabases": 1 } } } ] }, { "description": "ListDatabases succeeds after InterruptedDueToReplStateChange", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "listDatabases" ], "errorCode": 11602 } }, "operations": [ { "name": "listDatabases", "object": "client" } ], "expectations": [ { "command_started_event": { "command": { "listDatabases": 1 } } }, { "command_started_event": { "command": { "listDatabases": 1 } } } ] }, { "description": "ListDatabases succeeds after NotWritablePrimary", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "listDatabases" ], "errorCode": 10107 } }, "operations": [ { "name": "listDatabases", "object": "client" } ], "expectations": [ { "command_started_event": { "command": { "listDatabases": 1 } } }, { "command_started_event": { "command": { "listDatabases": 1 } } } ] }, { "description": "ListDatabases succeeds after NotPrimaryNoSecondaryOk", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "listDatabases" ], "errorCode": 13435 } }, "operations": [ { "name": "listDatabases", "object": "client" } ], "expectations": [ { "command_started_event": { "command": { "listDatabases": 1 } } }, { "command_started_event": { "command": { "listDatabases": 1 } } } ] }, { "description": "ListDatabases succeeds after NotPrimaryOrSecondary", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "listDatabases" ], "errorCode": 13436 } }, "operations": [ { "name": "listDatabases", "object": "client" } ], "expectations": [ { "command_started_event": { "command": { "listDatabases": 1 } } }, { "command_started_event": { "command": { "listDatabases": 1 } } } ] }, { "description": "ListDatabases succeeds after PrimarySteppedDown", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "listDatabases" ], "errorCode": 189 } }, "operations": [ { "name": "listDatabases", "object": "client" } ], "expectations": [ { "command_started_event": { "command": { "listDatabases": 1 } } }, { "command_started_event": { "command": { "listDatabases": 1 } } } ] }, { "description": "ListDatabases succeeds after ShutdownInProgress", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "listDatabases" ], "errorCode": 91 } }, "operations": [ { "name": "listDatabases", "object": "client" } ], "expectations": [ { "command_started_event": { "command": { "listDatabases": 1 } } }, { "command_started_event": { "command": { "listDatabases": 1 } } } ] }, { "description": "ListDatabases succeeds after HostNotFound", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "listDatabases" ], "errorCode": 7 } }, "operations": [ { "name": "listDatabases", "object": "client" } ], "expectations": [ { "command_started_event": { "command": { "listDatabases": 1 } } }, { "command_started_event": { "command": { "listDatabases": 1 } } } ] }, { "description": "ListDatabases succeeds after HostUnreachable", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "listDatabases" ], "errorCode": 6 } }, "operations": [ { "name": "listDatabases", "object": "client" } ], "expectations": [ { "command_started_event": { "command": { "listDatabases": 1 } } }, { "command_started_event": { "command": { "listDatabases": 1 } } } ] }, { "description": "ListDatabases succeeds after NetworkTimeout", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "listDatabases" ], "errorCode": 89 } }, "operations": [ { "name": "listDatabases", "object": "client" } ], "expectations": [ { "command_started_event": { "command": { "listDatabases": 1 } } }, { "command_started_event": { "command": { "listDatabases": 1 } } } ] }, { "description": "ListDatabases succeeds after SocketException", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "listDatabases" ], "errorCode": 9001 } }, "operations": [ { "name": "listDatabases", "object": "client" } ], "expectations": [ { "command_started_event": { "command": { "listDatabases": 1 } } }, { "command_started_event": { "command": { "listDatabases": 1 } } } ] }, { "description": "ListDatabases fails after two NotWritablePrimary errors", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 2 }, "data": { "failCommands": [ "listDatabases" ], "errorCode": 10107 } }, "operations": [ { "name": "listDatabases", "object": "client", "error": true } ], "expectations": [ { "command_started_event": { "command": { "listDatabases": 1 } } }, { "command_started_event": { "command": { "listDatabases": 1 } } } ] }, { "description": "ListDatabases fails after NotWritablePrimary when retryReads is false", "clientOptions": { "retryReads": false }, "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "listDatabases" ], "errorCode": 10107 } }, "operations": [ { "name": "listDatabases", "object": "client", "error": true } ], "expectations": [ { "command_started_event": { "command": { "listDatabases": 1 } } } ] } ] } mongodb-mongo-python-driver-509e9b7/test/retryable_reads/legacy/listDatabases.json000066400000000000000000000056401462766011000305120ustar00rootroot00000000000000{ "runOn": [ { "minServerVersion": "4.0", "topology": [ "single", "replicaset" ] }, { "minServerVersion": "4.1.7", "topology": [ "sharded", "load-balanced" ] } ], "database_name": "retryable-reads-tests", "collection_name": "coll", "data": [], "tests": [ { "description": "ListDatabases succeeds on first attempt", "operations": [ { "name": "listDatabases", "object": "client" } ], "expectations": [ { "command_started_event": { "command": { "listDatabases": 1 } } } ] }, { "description": "ListDatabases succeeds on second attempt", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "listDatabases" ], "closeConnection": true } }, "operations": [ { "name": "listDatabases", "object": "client" } ], "expectations": [ { "command_started_event": { "command": { "listDatabases": 1 } } }, { "command_started_event": { "command": { "listDatabases": 1 } } } ] }, { "description": "ListDatabases fails on first attempt", "clientOptions": { "retryReads": false }, "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "listDatabases" ], "closeConnection": true } }, "operations": [ { "name": "listDatabases", "object": "client", "error": true } ], "expectations": [ { "command_started_event": { "command": { "listDatabases": 1 } } } ] }, { "description": "ListDatabases fails on second attempt", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 2 }, "data": { "failCommands": [ "listDatabases" ], "closeConnection": true } }, "operations": [ { "name": "listDatabases", "object": "client", "error": true } ], "expectations": [ { "command_started_event": { "command": { "listDatabases": 1 } } }, { "command_started_event": { "command": { "listDatabases": 1 } } } ] } ] } mongodb-mongo-python-driver-509e9b7/test/retryable_reads/legacy/listIndexNames-serverErrors.json000066400000000000000000000270061462766011000333570ustar00rootroot00000000000000{ "runOn": [ { "minServerVersion": "4.0", "topology": [ "single", "replicaset" ] }, { "minServerVersion": "4.1.7", "topology": [ "sharded", "load-balanced" ] } ], "database_name": "retryable-reads-tests", "collection_name": "coll", "data": [], "tests": [ { "description": "ListIndexNames succeeds after InterruptedAtShutdown", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "listIndexes" ], "errorCode": 11600 } }, "operations": [ { "name": "listIndexNames", "object": "collection" } ], "expectations": [ { "command_started_event": { "command": { "listIndexes": "coll" }, "database_name": "retryable-reads-tests" } }, { "command_started_event": { "command": { "listIndexes": "coll" }, "database_name": "retryable-reads-tests" } } ] }, { "description": "ListIndexNames succeeds after InterruptedDueToReplStateChange", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "listIndexes" ], "errorCode": 11602 } }, "operations": [ { "name": "listIndexNames", "object": "collection" } ], "expectations": [ { "command_started_event": { "command": { "listIndexes": "coll" }, "database_name": "retryable-reads-tests" } }, { "command_started_event": { "command": { "listIndexes": "coll" }, "database_name": "retryable-reads-tests" } } ] }, { "description": "ListIndexNames succeeds after NotWritablePrimary", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "listIndexes" ], "errorCode": 10107 } }, "operations": [ { "name": "listIndexNames", "object": "collection" } ], "expectations": [ { "command_started_event": { "command": { "listIndexes": "coll" }, "database_name": "retryable-reads-tests" } }, { "command_started_event": { "command": { "listIndexes": "coll" }, "database_name": "retryable-reads-tests" } } ] }, { "description": "ListIndexNames succeeds after NotPrimaryNoSecondaryOk", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "listIndexes" ], "errorCode": 13435 } }, "operations": [ { "name": "listIndexNames", "object": "collection" } ], "expectations": [ { "command_started_event": { "command": { "listIndexes": "coll" }, "database_name": "retryable-reads-tests" } }, { "command_started_event": { "command": { "listIndexes": "coll" }, "database_name": "retryable-reads-tests" } } ] }, { "description": "ListIndexNames succeeds after NotPrimaryOrSecondary", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "listIndexes" ], "errorCode": 13436 } }, "operations": [ { "name": "listIndexNames", "object": "collection" } ], "expectations": [ { "command_started_event": { "command": { "listIndexes": "coll" }, "database_name": "retryable-reads-tests" } }, { "command_started_event": { "command": { "listIndexes": "coll" }, "database_name": "retryable-reads-tests" } } ] }, { "description": "ListIndexNames succeeds after PrimarySteppedDown", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "listIndexes" ], "errorCode": 189 } }, "operations": [ { "name": "listIndexNames", "object": "collection" } ], "expectations": [ { "command_started_event": { "command": { "listIndexes": "coll" }, "database_name": "retryable-reads-tests" } }, { "command_started_event": { "command": { "listIndexes": "coll" }, "database_name": "retryable-reads-tests" } } ] }, { "description": "ListIndexNames succeeds after ShutdownInProgress", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "listIndexes" ], "errorCode": 91 } }, "operations": [ { "name": "listIndexNames", "object": "collection" } ], "expectations": [ { "command_started_event": { "command": { "listIndexes": "coll" }, "database_name": "retryable-reads-tests" } }, { "command_started_event": { "command": { "listIndexes": "coll" }, "database_name": "retryable-reads-tests" } } ] }, { "description": "ListIndexNames succeeds after HostNotFound", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "listIndexes" ], "errorCode": 7 } }, "operations": [ { "name": "listIndexNames", "object": "collection" } ], "expectations": [ { "command_started_event": { "command": { "listIndexes": "coll" }, "database_name": "retryable-reads-tests" } }, { "command_started_event": { "command": { "listIndexes": "coll" }, "database_name": "retryable-reads-tests" } } ] }, { "description": "ListIndexNames succeeds after HostUnreachable", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "listIndexes" ], "errorCode": 6 } }, "operations": [ { "name": "listIndexNames", "object": "collection" } ], "expectations": [ { "command_started_event": { "command": { "listIndexes": "coll" }, "database_name": "retryable-reads-tests" } }, { "command_started_event": { "command": { "listIndexes": "coll" }, "database_name": "retryable-reads-tests" } } ] }, { "description": "ListIndexNames succeeds after NetworkTimeout", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "listIndexes" ], "errorCode": 89 } }, "operations": [ { "name": "listIndexNames", "object": "collection" } ], "expectations": [ { "command_started_event": { "command": { "listIndexes": "coll" }, "database_name": "retryable-reads-tests" } }, { "command_started_event": { "command": { "listIndexes": "coll" }, "database_name": "retryable-reads-tests" } } ] }, { "description": "ListIndexNames succeeds after SocketException", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "listIndexes" ], "errorCode": 9001 } }, "operations": [ { "name": "listIndexNames", "object": "collection" } ], "expectations": [ { "command_started_event": { "command": { "listIndexes": "coll" }, "database_name": "retryable-reads-tests" } }, { "command_started_event": { "command": { "listIndexes": "coll" }, "database_name": "retryable-reads-tests" } } ] }, { "description": "ListIndexNames fails after two NotWritablePrimary errors", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 2 }, "data": { "failCommands": [ "listIndexes" ], "errorCode": 10107 } }, "operations": [ { "name": "listIndexNames", "object": "collection", "error": true } ], "expectations": [ { "command_started_event": { "command": { "listIndexes": "coll" }, "database_name": "retryable-reads-tests" } }, { "command_started_event": { "command": { "listIndexes": "coll" }, "database_name": "retryable-reads-tests" } } ] }, { "description": "ListIndexNames fails after NotWritablePrimary when retryReads is false", "clientOptions": { "retryReads": false }, "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "listIndexes" ], "errorCode": 10107 } }, "operations": [ { "name": "listIndexNames", "object": "collection", "error": true } ], "expectations": [ { "command_started_event": { "command": { "listIndexes": "coll" }, "database_name": "retryable-reads-tests" } } ] } ] } mongodb-mongo-python-driver-509e9b7/test/retryable_reads/legacy/listIndexNames.json000066400000000000000000000064101462766011000306520ustar00rootroot00000000000000{ "runOn": [ { "minServerVersion": "4.0", "topology": [ "single", "replicaset" ] }, { "minServerVersion": "4.1.7", "topology": [ "sharded", "load-balanced" ] } ], "database_name": "retryable-reads-tests", "collection_name": "coll", "data": [], "tests": [ { "description": "ListIndexNames succeeds on first attempt", "operations": [ { "name": "listIndexNames", "object": "collection" } ], "expectations": [ { "command_started_event": { "command": { "listIndexes": "coll" }, "database_name": "retryable-reads-tests" } } ] }, { "description": "ListIndexNames succeeds on second attempt", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "listIndexes" ], "closeConnection": true } }, "operations": [ { "name": "listIndexNames", "object": "collection" } ], "expectations": [ { "command_started_event": { "command": { "listIndexes": "coll" }, "database_name": "retryable-reads-tests" } }, { "command_started_event": { "command": { "listIndexes": "coll" }, "database_name": "retryable-reads-tests" } } ] }, { "description": "ListIndexNames fails on first attempt", "clientOptions": { "retryReads": false }, "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "listIndexes" ], "closeConnection": true } }, "operations": [ { "name": "listIndexNames", "object": "collection", "error": true } ], "expectations": [ { "command_started_event": { "command": { "listIndexes": "coll" }, "database_name": "retryable-reads-tests" } } ] }, { "description": "ListIndexNames fails on second attempt", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 2 }, "data": { "failCommands": [ "listIndexes" ], "closeConnection": true } }, "operations": [ { "name": "listIndexNames", "object": "collection", "error": true } ], "expectations": [ { "command_started_event": { "command": { "listIndexes": "coll" }, "database_name": "retryable-reads-tests" } }, { "command_started_event": { "command": { "listIndexes": "coll" }, "database_name": "retryable-reads-tests" } } ] } ] } mongodb-mongo-python-driver-509e9b7/test/retryable_reads/legacy/listIndexes-serverErrors.json000066400000000000000000000266701462766011000327310ustar00rootroot00000000000000{ "runOn": [ { "minServerVersion": "4.0", "topology": [ "single", "replicaset" ] }, { "minServerVersion": "4.1.7", "topology": [ "sharded", "load-balanced" ] } ], "database_name": "retryable-reads-tests", "collection_name": "coll", "data": [], "tests": [ { "description": "ListIndexes succeeds after InterruptedAtShutdown", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "listIndexes" ], "errorCode": 11600 } }, "operations": [ { "name": "listIndexes", "object": "collection" } ], "expectations": [ { "command_started_event": { "command": { "listIndexes": "coll" }, "database_name": "retryable-reads-tests" } }, { "command_started_event": { "command": { "listIndexes": "coll" }, "database_name": "retryable-reads-tests" } } ] }, { "description": "ListIndexes succeeds after InterruptedDueToReplStateChange", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "listIndexes" ], "errorCode": 11602 } }, "operations": [ { "name": "listIndexes", "object": "collection" } ], "expectations": [ { "command_started_event": { "command": { "listIndexes": "coll" }, "database_name": "retryable-reads-tests" } }, { "command_started_event": { "command": { "listIndexes": "coll" }, "database_name": "retryable-reads-tests" } } ] }, { "description": "ListIndexes succeeds after NotWritablePrimary", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "listIndexes" ], "errorCode": 10107 } }, "operations": [ { "name": "listIndexes", "object": "collection" } ], "expectations": [ { "command_started_event": { "command": { "listIndexes": "coll" }, "database_name": "retryable-reads-tests" } }, { "command_started_event": { "command": { "listIndexes": "coll" }, "database_name": "retryable-reads-tests" } } ] }, { "description": "ListIndexes succeeds after NotPrimaryNoSecondaryOk", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "listIndexes" ], "errorCode": 13435 } }, "operations": [ { "name": "listIndexes", "object": "collection" } ], "expectations": [ { "command_started_event": { "command": { "listIndexes": "coll" }, "database_name": "retryable-reads-tests" } }, { "command_started_event": { "command": { "listIndexes": "coll" }, "database_name": "retryable-reads-tests" } } ] }, { "description": "ListIndexes succeeds after NotPrimaryOrSecondary", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "listIndexes" ], "errorCode": 13436 } }, "operations": [ { "name": "listIndexes", "object": "collection" } ], "expectations": [ { "command_started_event": { "command": { "listIndexes": "coll" }, "database_name": "retryable-reads-tests" } }, { "command_started_event": { "command": { "listIndexes": "coll" }, "database_name": "retryable-reads-tests" } } ] }, { "description": "ListIndexes succeeds after PrimarySteppedDown", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "listIndexes" ], "errorCode": 189 } }, "operations": [ { "name": "listIndexes", "object": "collection" } ], "expectations": [ { "command_started_event": { "command": { "listIndexes": "coll" }, "database_name": "retryable-reads-tests" } }, { "command_started_event": { "command": { "listIndexes": "coll" }, "database_name": "retryable-reads-tests" } } ] }, { "description": "ListIndexes succeeds after ShutdownInProgress", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "listIndexes" ], "errorCode": 91 } }, "operations": [ { "name": "listIndexes", "object": "collection" } ], "expectations": [ { "command_started_event": { "command": { "listIndexes": "coll" }, "database_name": "retryable-reads-tests" } }, { "command_started_event": { "command": { "listIndexes": "coll" }, "database_name": "retryable-reads-tests" } } ] }, { "description": "ListIndexes succeeds after HostNotFound", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "listIndexes" ], "errorCode": 7 } }, "operations": [ { "name": "listIndexes", "object": "collection" } ], "expectations": [ { "command_started_event": { "command": { "listIndexes": "coll" }, "database_name": "retryable-reads-tests" } }, { "command_started_event": { "command": { "listIndexes": "coll" }, "database_name": "retryable-reads-tests" } } ] }, { "description": "ListIndexes succeeds after HostUnreachable", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "listIndexes" ], "errorCode": 6 } }, "operations": [ { "name": "listIndexes", "object": "collection" } ], "expectations": [ { "command_started_event": { "command": { "listIndexes": "coll" }, "database_name": "retryable-reads-tests" } }, { "command_started_event": { "command": { "listIndexes": "coll" }, "database_name": "retryable-reads-tests" } } ] }, { "description": "ListIndexes succeeds after NetworkTimeout", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "listIndexes" ], "errorCode": 89 } }, "operations": [ { "name": "listIndexes", "object": "collection" } ], "expectations": [ { "command_started_event": { "command": { "listIndexes": "coll" }, "database_name": "retryable-reads-tests" } }, { "command_started_event": { "command": { "listIndexes": "coll" }, "database_name": "retryable-reads-tests" } } ] }, { "description": "ListIndexes succeeds after SocketException", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "listIndexes" ], "errorCode": 9001 } }, "operations": [ { "name": "listIndexes", "object": "collection" } ], "expectations": [ { "command_started_event": { "command": { "listIndexes": "coll" }, "database_name": "retryable-reads-tests" } }, { "command_started_event": { "command": { "listIndexes": "coll" }, "database_name": "retryable-reads-tests" } } ] }, { "description": "ListIndexes fails after two NotWritablePrimary errors", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 2 }, "data": { "failCommands": [ "listIndexes" ], "errorCode": 10107 } }, "operations": [ { "name": "listIndexes", "object": "collection", "error": true } ], "expectations": [ { "command_started_event": { "command": { "listIndexes": "coll" }, "database_name": "retryable-reads-tests" } }, { "command_started_event": { "command": { "listIndexes": "coll" }, "database_name": "retryable-reads-tests" } } ] }, { "description": "ListIndexes fails after NotWritablePrimary when retryReads is false", "clientOptions": { "retryReads": false }, "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "listIndexes" ], "errorCode": 10107 } }, "operations": [ { "name": "listIndexes", "object": "collection", "error": true } ], "expectations": [ { "command_started_event": { "command": { "listIndexes": "coll" }, "database_name": "retryable-reads-tests" } } ] } ] } mongodb-mongo-python-driver-509e9b7/test/retryable_reads/legacy/listIndexes.json000066400000000000000000000063601462766011000302220ustar00rootroot00000000000000{ "runOn": [ { "minServerVersion": "4.0", "topology": [ "single", "replicaset" ] }, { "minServerVersion": "4.1.7", "topology": [ "sharded", "load-balanced" ] } ], "database_name": "retryable-reads-tests", "collection_name": "coll", "data": [], "tests": [ { "description": "ListIndexes succeeds on first attempt", "operations": [ { "name": "listIndexes", "object": "collection" } ], "expectations": [ { "command_started_event": { "command": { "listIndexes": "coll" }, "database_name": "retryable-reads-tests" } } ] }, { "description": "ListIndexes succeeds on second attempt", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "listIndexes" ], "closeConnection": true } }, "operations": [ { "name": "listIndexes", "object": "collection" } ], "expectations": [ { "command_started_event": { "command": { "listIndexes": "coll" }, "database_name": "retryable-reads-tests" } }, { "command_started_event": { "command": { "listIndexes": "coll" }, "database_name": "retryable-reads-tests" } } ] }, { "description": "ListIndexes fails on first attempt", "clientOptions": { "retryReads": false }, "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "listIndexes" ], "closeConnection": true } }, "operations": [ { "name": "listIndexes", "object": "collection", "error": true } ], "expectations": [ { "command_started_event": { "command": { "listIndexes": "coll" }, "database_name": "retryable-reads-tests" } } ] }, { "description": "ListIndexes fails on second attempt", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 2 }, "data": { "failCommands": [ "listIndexes" ], "closeConnection": true } }, "operations": [ { "name": "listIndexes", "object": "collection", "error": true } ], "expectations": [ { "command_started_event": { "command": { "listIndexes": "coll" }, "database_name": "retryable-reads-tests" } }, { "command_started_event": { "command": { "listIndexes": "coll" }, "database_name": "retryable-reads-tests" } } ] } ] } mongodb-mongo-python-driver-509e9b7/test/retryable_reads/legacy/mapReduce.json000066400000000000000000000105751462766011000276370ustar00rootroot00000000000000{ "runOn": [ { "minServerVersion": "4.0", "topology": [ "single", "replicaset" ] }, { "minServerVersion": "4.1.7", "topology": [ "sharded", "load-balanced" ], "serverless": "forbid" } ], "database_name": "retryable-reads-tests", "collection_name": "coll", "data": [ { "_id": 1, "x": 0 }, { "_id": 2, "x": 1 }, { "_id": 3, "x": 2 } ], "tests": [ { "description": "MapReduce succeeds with retry on", "operations": [ { "name": "mapReduce", "object": "collection", "arguments": { "map": { "$code": "function inc() { return emit(0, this.x + 1) }" }, "reduce": { "$code": "function sum(key, values) { return values.reduce((acc, x) => acc + x); }" }, "out": { "inline": 1 } }, "result": [ { "_id": 0, "value": 6 } ] } ], "expectations": [ { "command_started_event": { "command": { "mapReduce": "coll", "map": { "$code": "function inc() { return emit(0, this.x + 1) }" }, "reduce": { "$code": "function sum(key, values) { return values.reduce((acc, x) => acc + x); }" }, "out": { "inline": 1 } }, "database_name": "retryable-reads-tests" } } ] }, { "description": "MapReduce fails with retry on", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "mapReduce" ], "closeConnection": true } }, "operations": [ { "name": "mapReduce", "object": "collection", "arguments": { "map": { "$code": "function inc() { return emit(0, this.x + 1) }" }, "reduce": { "$code": "function sum(key, values) { return values.reduce((acc, x) => acc + x); }" }, "out": { "inline": 1 } }, "error": true } ], "expectations": [ { "command_started_event": { "command": { "mapReduce": "coll", "map": { "$code": "function inc() { return emit(0, this.x + 1) }" }, "reduce": { "$code": "function sum(key, values) { return values.reduce((acc, x) => acc + x); }" }, "out": { "inline": 1 } }, "database_name": "retryable-reads-tests" } } ] }, { "description": "MapReduce fails with retry off", "clientOptions": { "retryReads": false }, "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "mapReduce" ], "closeConnection": true } }, "operations": [ { "name": "mapReduce", "object": "collection", "arguments": { "map": { "$code": "function inc() { return emit(0, this.x + 1) }" }, "reduce": { "$code": "function sum(key, values) { return values.reduce((acc, x) => acc + x); }" }, "out": { "inline": 1 } }, "error": true } ], "expectations": [ { "command_started_event": { "command": { "mapReduce": "coll", "map": { "$code": "function inc() { return emit(0, this.x + 1) }" }, "reduce": { "$code": "function sum(key, values) { return values.reduce((acc, x) => acc + x); }" }, "out": { "inline": 1 } }, "database_name": "retryable-reads-tests" } } ] } ] } mongodb-mongo-python-driver-509e9b7/test/retryable_reads/unified/000077500000000000000000000000001462766011000252065ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/retryable_reads/unified/exceededTimeLimit.json000066400000000000000000000061101462766011000314630ustar00rootroot00000000000000{ "description": "ExceededTimeLimit is a retryable read", "schemaVersion": "1.3", "runOnRequirements": [ { "minServerVersion": "4.0", "topologies": [ "single", "replicaset" ] }, { "minServerVersion": "4.1.7", "topologies": [ "sharded", "load-balanced" ] } ], "createEntities": [ { "client": { "id": "client0", "useMultipleMongoses": false, "observeEvents": [ "commandStartedEvent" ] } }, { "database": { "id": "database0", "client": "client0", "databaseName": "retryable-reads-tests" } }, { "collection": { "id": "collection0", "database": "database0", "collectionName": "exceededtimelimit-test" } } ], "initialData": [ { "collectionName": "exceededtimelimit-test", "databaseName": "retryable-reads-tests", "documents": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 22 }, { "_id": 3, "x": 33 } ] } ], "tests": [ { "description": "Find succeeds on second attempt after ExceededTimeLimit", "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "client0", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "find" ], "errorCode": 262 } } } }, { "name": "find", "arguments": { "filter": { "_id": { "$gt": 1 } } }, "object": "collection0", "expectResult": [ { "_id": 2, "x": 22 }, { "_id": 3, "x": 33 } ] } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "find": "exceededtimelimit-test", "filter": { "_id": { "$gt": 1 } } }, "commandName": "find", "databaseName": "retryable-reads-tests" } }, { "commandStartedEvent": { "command": { "find": "exceededtimelimit-test", "filter": { "_id": { "$gt": 1 } } }, "commandName": "find", "databaseName": "retryable-reads-tests" } } ] } ] } ] } mongodb-mongo-python-driver-509e9b7/test/retryable_reads/unified/handshakeError.json000066400000000000000000002206131462766011000310450ustar00rootroot00000000000000{ "description": "retryable reads handshake failures", "schemaVersion": "1.4", "runOnRequirements": [ { "minServerVersion": "4.2", "topologies": [ "replicaset", "sharded", "load-balanced" ], "auth": true } ], "createEntities": [ { "client": { "id": "client", "useMultipleMongoses": false, "observeEvents": [ "connectionCheckOutStartedEvent", "commandStartedEvent", "commandSucceededEvent", "commandFailedEvent" ] } }, { "database": { "id": "database", "client": "client", "databaseName": "retryable-reads-handshake-tests" } }, { "collection": { "id": "collection", "database": "database", "collectionName": "coll" } } ], "initialData": [ { "collectionName": "coll", "databaseName": "retryable-reads-handshake-tests", "documents": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 22 }, { "_id": 3, "x": 33 } ] } ], "tests": [ { "description": "client.listDatabases succeeds after retryable handshake network error", "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "client", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 2 }, "data": { "failCommands": [ "ping", "saslContinue" ], "closeConnection": true } } } }, { "name": "runCommand", "object": "database", "arguments": { "commandName": "ping", "command": { "ping": 1 } }, "expectError": { "isError": true } }, { "name": "listDatabases", "object": "client", "arguments": { "filter": {} } } ], "expectEvents": [ { "client": "client", "eventType": "cmap", "events": [ { "connectionCheckOutStartedEvent": {} }, { "connectionCheckOutStartedEvent": {} }, { "connectionCheckOutStartedEvent": {} }, { "connectionCheckOutStartedEvent": {} } ] }, { "client": "client", "events": [ { "commandStartedEvent": { "command": { "ping": 1 }, "databaseName": "retryable-reads-handshake-tests" } }, { "commandFailedEvent": { "commandName": "ping" } }, { "commandStartedEvent": { "commandName": "listDatabases" } }, { "commandSucceededEvent": { "commandName": "listDatabases" } } ] } ] }, { "description": "client.listDatabases succeeds after retryable handshake server error (ShutdownInProgress)", "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "client", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 2 }, "data": { "failCommands": [ "ping", "saslContinue" ], "closeConnection": true } } } }, { "name": "runCommand", "object": "database", "arguments": { "commandName": "ping", "command": { "ping": 1 } }, "expectError": { "isError": true } }, { "name": "listDatabases", "object": "client", "arguments": { "filter": {} } } ], "expectEvents": [ { "client": "client", "eventType": "cmap", "events": [ { "connectionCheckOutStartedEvent": {} }, { "connectionCheckOutStartedEvent": {} }, { "connectionCheckOutStartedEvent": {} }, { "connectionCheckOutStartedEvent": {} } ] }, { "client": "client", "events": [ { "commandStartedEvent": { "command": { "ping": 1 }, "databaseName": "retryable-reads-handshake-tests" } }, { "commandFailedEvent": { "commandName": "ping" } }, { "commandStartedEvent": { "commandName": "listDatabases" } }, { "commandSucceededEvent": { "commandName": "listDatabases" } } ] } ] }, { "description": "client.listDatabaseNames succeeds after retryable handshake network error", "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "client", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 2 }, "data": { "failCommands": [ "ping", "saslContinue" ], "closeConnection": true } } } }, { "name": "runCommand", "object": "database", "arguments": { "commandName": "ping", "command": { "ping": 1 } }, "expectError": { "isError": true } }, { "name": "listDatabaseNames", "object": "client" } ], "expectEvents": [ { "client": "client", "eventType": "cmap", "events": [ { "connectionCheckOutStartedEvent": {} }, { "connectionCheckOutStartedEvent": {} }, { "connectionCheckOutStartedEvent": {} }, { "connectionCheckOutStartedEvent": {} } ] }, { "client": "client", "events": [ { "commandStartedEvent": { "command": { "ping": 1 }, "databaseName": "retryable-reads-handshake-tests" } }, { "commandFailedEvent": { "commandName": "ping" } }, { "commandStartedEvent": { "commandName": "listDatabases" } }, { "commandSucceededEvent": { "commandName": "listDatabases" } } ] } ] }, { "description": "client.listDatabaseNames succeeds after retryable handshake server error (ShutdownInProgress)", "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "client", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 2 }, "data": { "failCommands": [ "ping", "saslContinue" ], "closeConnection": true } } } }, { "name": "runCommand", "object": "database", "arguments": { "commandName": "ping", "command": { "ping": 1 } }, "expectError": { "isError": true } }, { "name": "listDatabaseNames", "object": "client" } ], "expectEvents": [ { "client": "client", "eventType": "cmap", "events": [ { "connectionCheckOutStartedEvent": {} }, { "connectionCheckOutStartedEvent": {} }, { "connectionCheckOutStartedEvent": {} }, { "connectionCheckOutStartedEvent": {} } ] }, { "client": "client", "events": [ { "commandStartedEvent": { "command": { "ping": 1 }, "databaseName": "retryable-reads-handshake-tests" } }, { "commandFailedEvent": { "commandName": "ping" } }, { "commandStartedEvent": { "commandName": "listDatabases" } }, { "commandSucceededEvent": { "commandName": "listDatabases" } } ] } ] }, { "description": "client.createChangeStream succeeds after retryable handshake network error", "runOnRequirements": [ { "serverless": "forbid" } ], "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "client", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 2 }, "data": { "failCommands": [ "ping", "saslContinue" ], "closeConnection": true } } } }, { "name": "runCommand", "object": "database", "arguments": { "commandName": "ping", "command": { "ping": 1 } }, "expectError": { "isError": true } }, { "name": "createChangeStream", "object": "client", "arguments": { "pipeline": [] }, "saveResultAsEntity": "changeStream" } ], "expectEvents": [ { "client": "client", "eventType": "cmap", "events": [ { "connectionCheckOutStartedEvent": {} }, { "connectionCheckOutStartedEvent": {} }, { "connectionCheckOutStartedEvent": {} }, { "connectionCheckOutStartedEvent": {} } ] }, { "client": "client", "events": [ { "commandStartedEvent": { "command": { "ping": 1 }, "databaseName": "retryable-reads-handshake-tests" } }, { "commandFailedEvent": { "commandName": "ping" } }, { "commandStartedEvent": { "commandName": "aggregate" } }, { "commandSucceededEvent": { "commandName": "aggregate" } } ] } ] }, { "description": "client.createChangeStream succeeds after retryable handshake server error (ShutdownInProgress)", "runOnRequirements": [ { "serverless": "forbid" } ], "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "client", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 2 }, "data": { "failCommands": [ "ping", "saslContinue" ], "closeConnection": true } } } }, { "name": "runCommand", "object": "database", "arguments": { "commandName": "ping", "command": { "ping": 1 } }, "expectError": { "isError": true } }, { "name": "createChangeStream", "object": "client", "arguments": { "pipeline": [] }, "saveResultAsEntity": "changeStream" } ], "expectEvents": [ { "client": "client", "eventType": "cmap", "events": [ { "connectionCheckOutStartedEvent": {} }, { "connectionCheckOutStartedEvent": {} }, { "connectionCheckOutStartedEvent": {} }, { "connectionCheckOutStartedEvent": {} } ] }, { "client": "client", "events": [ { "commandStartedEvent": { "command": { "ping": 1 }, "databaseName": "retryable-reads-handshake-tests" } }, { "commandFailedEvent": { "commandName": "ping" } }, { "commandStartedEvent": { "commandName": "aggregate" } }, { "commandSucceededEvent": { "commandName": "aggregate" } } ] } ] }, { "description": "database.aggregate succeeds after retryable handshake network error", "runOnRequirements": [ { "serverless": "forbid" } ], "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "client", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 2 }, "data": { "failCommands": [ "ping", "saslContinue" ], "closeConnection": true } } } }, { "name": "runCommand", "object": "database", "arguments": { "commandName": "ping", "command": { "ping": 1 } }, "expectError": { "isError": true } }, { "name": "aggregate", "object": "database", "arguments": { "pipeline": [ { "$listLocalSessions": {} }, { "$limit": 1 } ] } } ], "expectEvents": [ { "client": "client", "eventType": "cmap", "events": [ { "connectionCheckOutStartedEvent": {} }, { "connectionCheckOutStartedEvent": {} }, { "connectionCheckOutStartedEvent": {} }, { "connectionCheckOutStartedEvent": {} } ] }, { "client": "client", "events": [ { "commandStartedEvent": { "command": { "ping": 1 }, "databaseName": "retryable-reads-handshake-tests" } }, { "commandFailedEvent": { "commandName": "ping" } }, { "commandStartedEvent": { "commandName": "aggregate" } }, { "commandSucceededEvent": { "commandName": "aggregate" } } ] } ] }, { "description": "database.aggregate succeeds after retryable handshake server error (ShutdownInProgress)", "runOnRequirements": [ { "serverless": "forbid" } ], "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "client", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 2 }, "data": { "failCommands": [ "ping", "saslContinue" ], "closeConnection": true } } } }, { "name": "runCommand", "object": "database", "arguments": { "commandName": "ping", "command": { "ping": 1 } }, "expectError": { "isError": true } }, { "name": "aggregate", "object": "database", "arguments": { "pipeline": [ { "$listLocalSessions": {} }, { "$limit": 1 } ] } } ], "expectEvents": [ { "client": "client", "eventType": "cmap", "events": [ { "connectionCheckOutStartedEvent": {} }, { "connectionCheckOutStartedEvent": {} }, { "connectionCheckOutStartedEvent": {} }, { "connectionCheckOutStartedEvent": {} } ] }, { "client": "client", "events": [ { "commandStartedEvent": { "command": { "ping": 1 }, "databaseName": "retryable-reads-handshake-tests" } }, { "commandFailedEvent": { "commandName": "ping" } }, { "commandStartedEvent": { "commandName": "aggregate" } }, { "commandSucceededEvent": { "commandName": "aggregate" } } ] } ] }, { "description": "database.listCollections succeeds after retryable handshake network error", "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "client", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 2 }, "data": { "failCommands": [ "ping", "saslContinue" ], "closeConnection": true } } } }, { "name": "runCommand", "object": "database", "arguments": { "commandName": "ping", "command": { "ping": 1 } }, "expectError": { "isError": true } }, { "name": "listCollections", "object": "database", "arguments": { "filter": {} } } ], "expectEvents": [ { "client": "client", "eventType": "cmap", "events": [ { "connectionCheckOutStartedEvent": {} }, { "connectionCheckOutStartedEvent": {} }, { "connectionCheckOutStartedEvent": {} }, { "connectionCheckOutStartedEvent": {} } ] }, { "client": "client", "events": [ { "commandStartedEvent": { "command": { "ping": 1 }, "databaseName": "retryable-reads-handshake-tests" } }, { "commandFailedEvent": { "commandName": "ping" } }, { "commandStartedEvent": { "commandName": "listCollections" } }, { "commandSucceededEvent": { "commandName": "listCollections" } } ] } ] }, { "description": "database.listCollections succeeds after retryable handshake server error (ShutdownInProgress)", "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "client", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 2 }, "data": { "failCommands": [ "ping", "saslContinue" ], "closeConnection": true } } } }, { "name": "runCommand", "object": "database", "arguments": { "commandName": "ping", "command": { "ping": 1 } }, "expectError": { "isError": true } }, { "name": "listCollections", "object": "database", "arguments": { "filter": {} } } ], "expectEvents": [ { "client": "client", "eventType": "cmap", "events": [ { "connectionCheckOutStartedEvent": {} }, { "connectionCheckOutStartedEvent": {} }, { "connectionCheckOutStartedEvent": {} }, { "connectionCheckOutStartedEvent": {} } ] }, { "client": "client", "events": [ { "commandStartedEvent": { "command": { "ping": 1 }, "databaseName": "retryable-reads-handshake-tests" } }, { "commandFailedEvent": { "commandName": "ping" } }, { "commandStartedEvent": { "commandName": "listCollections" } }, { "commandSucceededEvent": { "commandName": "listCollections" } } ] } ] }, { "description": "database.listCollectionNames succeeds after retryable handshake network error", "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "client", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 2 }, "data": { "failCommands": [ "ping", "saslContinue" ], "closeConnection": true } } } }, { "name": "runCommand", "object": "database", "arguments": { "commandName": "ping", "command": { "ping": 1 } }, "expectError": { "isError": true } }, { "name": "listCollectionNames", "object": "database", "arguments": { "filter": {} } } ], "expectEvents": [ { "client": "client", "eventType": "cmap", "events": [ { "connectionCheckOutStartedEvent": {} }, { "connectionCheckOutStartedEvent": {} }, { "connectionCheckOutStartedEvent": {} }, { "connectionCheckOutStartedEvent": {} } ] }, { "client": "client", "events": [ { "commandStartedEvent": { "command": { "ping": 1 }, "databaseName": "retryable-reads-handshake-tests" } }, { "commandFailedEvent": { "commandName": "ping" } }, { "commandStartedEvent": { "commandName": "listCollections" } }, { "commandSucceededEvent": { "commandName": "listCollections" } } ] } ] }, { "description": "database.listCollectionNames succeeds after retryable handshake server error (ShutdownInProgress)", "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "client", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 2 }, "data": { "failCommands": [ "ping", "saslContinue" ], "closeConnection": true } } } }, { "name": "runCommand", "object": "database", "arguments": { "commandName": "ping", "command": { "ping": 1 } }, "expectError": { "isError": true } }, { "name": "listCollectionNames", "object": "database", "arguments": { "filter": {} } } ], "expectEvents": [ { "client": "client", "eventType": "cmap", "events": [ { "connectionCheckOutStartedEvent": {} }, { "connectionCheckOutStartedEvent": {} }, { "connectionCheckOutStartedEvent": {} }, { "connectionCheckOutStartedEvent": {} } ] }, { "client": "client", "events": [ { "commandStartedEvent": { "command": { "ping": 1 }, "databaseName": "retryable-reads-handshake-tests" } }, { "commandFailedEvent": { "commandName": "ping" } }, { "commandStartedEvent": { "commandName": "listCollections" } }, { "commandSucceededEvent": { "commandName": "listCollections" } } ] } ] }, { "description": "database.createChangeStream succeeds after retryable handshake network error", "runOnRequirements": [ { "serverless": "forbid" } ], "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "client", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 2 }, "data": { "failCommands": [ "ping", "saslContinue" ], "closeConnection": true } } } }, { "name": "runCommand", "object": "database", "arguments": { "commandName": "ping", "command": { "ping": 1 } }, "expectError": { "isError": true } }, { "name": "createChangeStream", "object": "database", "arguments": { "pipeline": [] }, "saveResultAsEntity": "changeStream" } ], "expectEvents": [ { "client": "client", "eventType": "cmap", "events": [ { "connectionCheckOutStartedEvent": {} }, { "connectionCheckOutStartedEvent": {} }, { "connectionCheckOutStartedEvent": {} }, { "connectionCheckOutStartedEvent": {} } ] }, { "client": "client", "events": [ { "commandStartedEvent": { "command": { "ping": 1 }, "databaseName": "retryable-reads-handshake-tests" } }, { "commandFailedEvent": { "commandName": "ping" } }, { "commandStartedEvent": { "commandName": "aggregate" } }, { "commandSucceededEvent": { "commandName": "aggregate" } } ] } ] }, { "description": "database.createChangeStream succeeds after retryable handshake server error (ShutdownInProgress)", "runOnRequirements": [ { "serverless": "forbid" } ], "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "client", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 2 }, "data": { "failCommands": [ "ping", "saslContinue" ], "closeConnection": true } } } }, { "name": "runCommand", "object": "database", "arguments": { "commandName": "ping", "command": { "ping": 1 } }, "expectError": { "isError": true } }, { "name": "createChangeStream", "object": "database", "arguments": { "pipeline": [] }, "saveResultAsEntity": "changeStream" } ], "expectEvents": [ { "client": "client", "eventType": "cmap", "events": [ { "connectionCheckOutStartedEvent": {} }, { "connectionCheckOutStartedEvent": {} }, { "connectionCheckOutStartedEvent": {} }, { "connectionCheckOutStartedEvent": {} } ] }, { "client": "client", "events": [ { "commandStartedEvent": { "command": { "ping": 1 }, "databaseName": "retryable-reads-handshake-tests" } }, { "commandFailedEvent": { "commandName": "ping" } }, { "commandStartedEvent": { "commandName": "aggregate" } }, { "commandSucceededEvent": { "commandName": "aggregate" } } ] } ] }, { "description": "collection.aggregate succeeds after retryable handshake network error", "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "client", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 2 }, "data": { "failCommands": [ "ping", "saslContinue" ], "closeConnection": true } } } }, { "name": "runCommand", "object": "database", "arguments": { "commandName": "ping", "command": { "ping": 1 } }, "expectError": { "isError": true } }, { "name": "aggregate", "object": "collection", "arguments": { "pipeline": [] } } ], "expectEvents": [ { "client": "client", "eventType": "cmap", "events": [ { "connectionCheckOutStartedEvent": {} }, { "connectionCheckOutStartedEvent": {} }, { "connectionCheckOutStartedEvent": {} }, { "connectionCheckOutStartedEvent": {} } ] }, { "client": "client", "events": [ { "commandStartedEvent": { "command": { "ping": 1 }, "databaseName": "retryable-reads-handshake-tests" } }, { "commandFailedEvent": { "commandName": "ping" } }, { "commandStartedEvent": { "commandName": "aggregate" } }, { "commandSucceededEvent": { "commandName": "aggregate" } } ] } ] }, { "description": "collection.aggregate succeeds after retryable handshake server error (ShutdownInProgress)", "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "client", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 2 }, "data": { "failCommands": [ "ping", "saslContinue" ], "closeConnection": true } } } }, { "name": "runCommand", "object": "database", "arguments": { "commandName": "ping", "command": { "ping": 1 } }, "expectError": { "isError": true } }, { "name": "aggregate", "object": "collection", "arguments": { "pipeline": [] } } ], "expectEvents": [ { "client": "client", "eventType": "cmap", "events": [ { "connectionCheckOutStartedEvent": {} }, { "connectionCheckOutStartedEvent": {} }, { "connectionCheckOutStartedEvent": {} }, { "connectionCheckOutStartedEvent": {} } ] }, { "client": "client", "events": [ { "commandStartedEvent": { "command": { "ping": 1 }, "databaseName": "retryable-reads-handshake-tests" } }, { "commandFailedEvent": { "commandName": "ping" } }, { "commandStartedEvent": { "commandName": "aggregate" } }, { "commandSucceededEvent": { "commandName": "aggregate" } } ] } ] }, { "description": "collection.countDocuments succeeds after retryable handshake network error", "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "client", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 2 }, "data": { "failCommands": [ "ping", "saslContinue" ], "closeConnection": true } } } }, { "name": "runCommand", "object": "database", "arguments": { "commandName": "ping", "command": { "ping": 1 } }, "expectError": { "isError": true } }, { "name": "countDocuments", "object": "collection", "arguments": { "filter": {} } } ], "expectEvents": [ { "client": "client", "eventType": "cmap", "events": [ { "connectionCheckOutStartedEvent": {} }, { "connectionCheckOutStartedEvent": {} }, { "connectionCheckOutStartedEvent": {} }, { "connectionCheckOutStartedEvent": {} } ] }, { "client": "client", "events": [ { "commandStartedEvent": { "command": { "ping": 1 }, "databaseName": "retryable-reads-handshake-tests" } }, { "commandFailedEvent": { "commandName": "ping" } }, { "commandStartedEvent": { "commandName": "aggregate" } }, { "commandSucceededEvent": { "commandName": "aggregate" } } ] } ] }, { "description": "collection.countDocuments succeeds after retryable handshake server error (ShutdownInProgress)", "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "client", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 2 }, "data": { "failCommands": [ "ping", "saslContinue" ], "closeConnection": true } } } }, { "name": "runCommand", "object": "database", "arguments": { "commandName": "ping", "command": { "ping": 1 } }, "expectError": { "isError": true } }, { "name": "countDocuments", "object": "collection", "arguments": { "filter": {} } } ], "expectEvents": [ { "client": "client", "eventType": "cmap", "events": [ { "connectionCheckOutStartedEvent": {} }, { "connectionCheckOutStartedEvent": {} }, { "connectionCheckOutStartedEvent": {} }, { "connectionCheckOutStartedEvent": {} } ] }, { "client": "client", "events": [ { "commandStartedEvent": { "command": { "ping": 1 }, "databaseName": "retryable-reads-handshake-tests" } }, { "commandFailedEvent": { "commandName": "ping" } }, { "commandStartedEvent": { "commandName": "aggregate" } }, { "commandSucceededEvent": { "commandName": "aggregate" } } ] } ] }, { "description": "collection.estimatedDocumentCount succeeds after retryable handshake network error", "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "client", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 2 }, "data": { "failCommands": [ "ping", "saslContinue" ], "closeConnection": true } } } }, { "name": "runCommand", "object": "database", "arguments": { "commandName": "ping", "command": { "ping": 1 } }, "expectError": { "isError": true } }, { "name": "estimatedDocumentCount", "object": "collection" } ], "expectEvents": [ { "client": "client", "eventType": "cmap", "events": [ { "connectionCheckOutStartedEvent": {} }, { "connectionCheckOutStartedEvent": {} }, { "connectionCheckOutStartedEvent": {} }, { "connectionCheckOutStartedEvent": {} } ] }, { "client": "client", "events": [ { "commandStartedEvent": { "command": { "ping": 1 }, "databaseName": "retryable-reads-handshake-tests" } }, { "commandFailedEvent": { "commandName": "ping" } }, { "commandStartedEvent": { "commandName": "count" } }, { "commandSucceededEvent": { "commandName": "count" } } ] } ] }, { "description": "collection.estimatedDocumentCount succeeds after retryable handshake server error (ShutdownInProgress)", "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "client", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 2 }, "data": { "failCommands": [ "ping", "saslContinue" ], "closeConnection": true } } } }, { "name": "runCommand", "object": "database", "arguments": { "commandName": "ping", "command": { "ping": 1 } }, "expectError": { "isError": true } }, { "name": "estimatedDocumentCount", "object": "collection" } ], "expectEvents": [ { "client": "client", "eventType": "cmap", "events": [ { "connectionCheckOutStartedEvent": {} }, { "connectionCheckOutStartedEvent": {} }, { "connectionCheckOutStartedEvent": {} }, { "connectionCheckOutStartedEvent": {} } ] }, { "client": "client", "events": [ { "commandStartedEvent": { "command": { "ping": 1 }, "databaseName": "retryable-reads-handshake-tests" } }, { "commandFailedEvent": { "commandName": "ping" } }, { "commandStartedEvent": { "commandName": "count" } }, { "commandSucceededEvent": { "commandName": "count" } } ] } ] }, { "description": "collection.distinct succeeds after retryable handshake network error", "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "client", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 2 }, "data": { "failCommands": [ "ping", "saslContinue" ], "closeConnection": true } } } }, { "name": "runCommand", "object": "database", "arguments": { "commandName": "ping", "command": { "ping": 1 } }, "expectError": { "isError": true } }, { "name": "distinct", "object": "collection", "arguments": { "fieldName": "x", "filter": {} } } ], "expectEvents": [ { "client": "client", "eventType": "cmap", "events": [ { "connectionCheckOutStartedEvent": {} }, { "connectionCheckOutStartedEvent": {} }, { "connectionCheckOutStartedEvent": {} }, { "connectionCheckOutStartedEvent": {} } ] }, { "client": "client", "events": [ { "commandStartedEvent": { "command": { "ping": 1 }, "databaseName": "retryable-reads-handshake-tests" } }, { "commandFailedEvent": { "commandName": "ping" } }, { "commandStartedEvent": { "commandName": "distinct" } }, { "commandSucceededEvent": { "commandName": "distinct" } } ] } ] }, { "description": "collection.distinct succeeds after retryable handshake server error (ShutdownInProgress)", "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "client", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 2 }, "data": { "failCommands": [ "ping", "saslContinue" ], "closeConnection": true } } } }, { "name": "runCommand", "object": "database", "arguments": { "commandName": "ping", "command": { "ping": 1 } }, "expectError": { "isError": true } }, { "name": "distinct", "object": "collection", "arguments": { "fieldName": "x", "filter": {} } } ], "expectEvents": [ { "client": "client", "eventType": "cmap", "events": [ { "connectionCheckOutStartedEvent": {} }, { "connectionCheckOutStartedEvent": {} }, { "connectionCheckOutStartedEvent": {} }, { "connectionCheckOutStartedEvent": {} } ] }, { "client": "client", "events": [ { "commandStartedEvent": { "command": { "ping": 1 }, "databaseName": "retryable-reads-handshake-tests" } }, { "commandFailedEvent": { "commandName": "ping" } }, { "commandStartedEvent": { "commandName": "distinct" } }, { "commandSucceededEvent": { "commandName": "distinct" } } ] } ] }, { "description": "collection.find succeeds after retryable handshake network error", "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "client", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 2 }, "data": { "failCommands": [ "ping", "saslContinue" ], "closeConnection": true } } } }, { "name": "runCommand", "object": "database", "arguments": { "commandName": "ping", "command": { "ping": 1 } }, "expectError": { "isError": true } }, { "name": "find", "object": "collection", "arguments": { "filter": {} } } ], "expectEvents": [ { "client": "client", "eventType": "cmap", "events": [ { "connectionCheckOutStartedEvent": {} }, { "connectionCheckOutStartedEvent": {} }, { "connectionCheckOutStartedEvent": {} }, { "connectionCheckOutStartedEvent": {} } ] }, { "client": "client", "events": [ { "commandStartedEvent": { "command": { "ping": 1 }, "databaseName": "retryable-reads-handshake-tests" } }, { "commandFailedEvent": { "commandName": "ping" } }, { "commandStartedEvent": { "commandName": "find" } }, { "commandSucceededEvent": { "commandName": "find" } } ] } ] }, { "description": "collection.find succeeds after retryable handshake server error (ShutdownInProgress)", "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "client", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 2 }, "data": { "failCommands": [ "ping", "saslContinue" ], "closeConnection": true } } } }, { "name": "runCommand", "object": "database", "arguments": { "commandName": "ping", "command": { "ping": 1 } }, "expectError": { "isError": true } }, { "name": "find", "object": "collection", "arguments": { "filter": {} } } ], "expectEvents": [ { "client": "client", "eventType": "cmap", "events": [ { "connectionCheckOutStartedEvent": {} }, { "connectionCheckOutStartedEvent": {} }, { "connectionCheckOutStartedEvent": {} }, { "connectionCheckOutStartedEvent": {} } ] }, { "client": "client", "events": [ { "commandStartedEvent": { "command": { "ping": 1 }, "databaseName": "retryable-reads-handshake-tests" } }, { "commandFailedEvent": { "commandName": "ping" } }, { "commandStartedEvent": { "commandName": "find" } }, { "commandSucceededEvent": { "commandName": "find" } } ] } ] }, { "description": "collection.findOne succeeds after retryable handshake network error", "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "client", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 2 }, "data": { "failCommands": [ "ping", "saslContinue" ], "closeConnection": true } } } }, { "name": "runCommand", "object": "database", "arguments": { "commandName": "ping", "command": { "ping": 1 } }, "expectError": { "isError": true } }, { "name": "findOne", "object": "collection", "arguments": { "filter": {} } } ], "expectEvents": [ { "client": "client", "eventType": "cmap", "events": [ { "connectionCheckOutStartedEvent": {} }, { "connectionCheckOutStartedEvent": {} }, { "connectionCheckOutStartedEvent": {} }, { "connectionCheckOutStartedEvent": {} } ] }, { "client": "client", "events": [ { "commandStartedEvent": { "command": { "ping": 1 }, "databaseName": "retryable-reads-handshake-tests" } }, { "commandFailedEvent": { "commandName": "ping" } }, { "commandStartedEvent": { "commandName": "find" } }, { "commandSucceededEvent": { "commandName": "find" } } ] } ] }, { "description": "collection.findOne succeeds after retryable handshake server error (ShutdownInProgress)", "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "client", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 2 }, "data": { "failCommands": [ "ping", "saslContinue" ], "closeConnection": true } } } }, { "name": "runCommand", "object": "database", "arguments": { "commandName": "ping", "command": { "ping": 1 } }, "expectError": { "isError": true } }, { "name": "findOne", "object": "collection", "arguments": { "filter": {} } } ], "expectEvents": [ { "client": "client", "eventType": "cmap", "events": [ { "connectionCheckOutStartedEvent": {} }, { "connectionCheckOutStartedEvent": {} }, { "connectionCheckOutStartedEvent": {} }, { "connectionCheckOutStartedEvent": {} } ] }, { "client": "client", "events": [ { "commandStartedEvent": { "command": { "ping": 1 }, "databaseName": "retryable-reads-handshake-tests" } }, { "commandFailedEvent": { "commandName": "ping" } }, { "commandStartedEvent": { "commandName": "find" } }, { "commandSucceededEvent": { "commandName": "find" } } ] } ] }, { "description": "collection.listIndexes succeeds after retryable handshake network error", "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "client", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 2 }, "data": { "failCommands": [ "ping", "saslContinue" ], "closeConnection": true } } } }, { "name": "runCommand", "object": "database", "arguments": { "commandName": "ping", "command": { "ping": 1 } }, "expectError": { "isError": true } }, { "name": "listIndexes", "object": "collection" } ], "expectEvents": [ { "client": "client", "eventType": "cmap", "events": [ { "connectionCheckOutStartedEvent": {} }, { "connectionCheckOutStartedEvent": {} }, { "connectionCheckOutStartedEvent": {} }, { "connectionCheckOutStartedEvent": {} } ] }, { "client": "client", "events": [ { "commandStartedEvent": { "command": { "ping": 1 }, "databaseName": "retryable-reads-handshake-tests" } }, { "commandFailedEvent": { "commandName": "ping" } }, { "commandStartedEvent": { "commandName": "listIndexes" } }, { "commandSucceededEvent": { "commandName": "listIndexes" } } ] } ] }, { "description": "collection.listIndexes succeeds after retryable handshake server error (ShutdownInProgress)", "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "client", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 2 }, "data": { "failCommands": [ "ping", "saslContinue" ], "closeConnection": true } } } }, { "name": "runCommand", "object": "database", "arguments": { "commandName": "ping", "command": { "ping": 1 } }, "expectError": { "isError": true } }, { "name": "listIndexes", "object": "collection" } ], "expectEvents": [ { "client": "client", "eventType": "cmap", "events": [ { "connectionCheckOutStartedEvent": {} }, { "connectionCheckOutStartedEvent": {} }, { "connectionCheckOutStartedEvent": {} }, { "connectionCheckOutStartedEvent": {} } ] }, { "client": "client", "events": [ { "commandStartedEvent": { "command": { "ping": 1 }, "databaseName": "retryable-reads-handshake-tests" } }, { "commandFailedEvent": { "commandName": "ping" } }, { "commandStartedEvent": { "commandName": "listIndexes" } }, { "commandSucceededEvent": { "commandName": "listIndexes" } } ] } ] }, { "description": "collection.listIndexNames succeeds after retryable handshake network error", "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "client", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 2 }, "data": { "failCommands": [ "ping", "saslContinue" ], "closeConnection": true } } } }, { "name": "runCommand", "object": "database", "arguments": { "commandName": "ping", "command": { "ping": 1 } }, "expectError": { "isError": true } }, { "name": "listIndexNames", "object": "collection" } ], "expectEvents": [ { "client": "client", "eventType": "cmap", "events": [ { "connectionCheckOutStartedEvent": {} }, { "connectionCheckOutStartedEvent": {} }, { "connectionCheckOutStartedEvent": {} }, { "connectionCheckOutStartedEvent": {} } ] }, { "client": "client", "events": [ { "commandStartedEvent": { "command": { "ping": 1 }, "databaseName": "retryable-reads-handshake-tests" } }, { "commandFailedEvent": { "commandName": "ping" } }, { "commandStartedEvent": { "commandName": "listIndexes" } }, { "commandSucceededEvent": { "commandName": "listIndexes" } } ] } ] }, { "description": "collection.listIndexNames succeeds after retryable handshake server error (ShutdownInProgress)", "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "client", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 2 }, "data": { "failCommands": [ "ping", "saslContinue" ], "closeConnection": true } } } }, { "name": "runCommand", "object": "database", "arguments": { "commandName": "ping", "command": { "ping": 1 } }, "expectError": { "isError": true } }, { "name": "listIndexNames", "object": "collection" } ], "expectEvents": [ { "client": "client", "eventType": "cmap", "events": [ { "connectionCheckOutStartedEvent": {} }, { "connectionCheckOutStartedEvent": {} }, { "connectionCheckOutStartedEvent": {} }, { "connectionCheckOutStartedEvent": {} } ] }, { "client": "client", "events": [ { "commandStartedEvent": { "command": { "ping": 1 }, "databaseName": "retryable-reads-handshake-tests" } }, { "commandFailedEvent": { "commandName": "ping" } }, { "commandStartedEvent": { "commandName": "listIndexes" } }, { "commandSucceededEvent": { "commandName": "listIndexes" } } ] } ] }, { "description": "collection.createChangeStream succeeds after retryable handshake network error", "runOnRequirements": [ { "serverless": "forbid" } ], "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "client", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 2 }, "data": { "failCommands": [ "ping", "saslContinue" ], "closeConnection": true } } } }, { "name": "runCommand", "object": "database", "arguments": { "commandName": "ping", "command": { "ping": 1 } }, "expectError": { "isError": true } }, { "name": "createChangeStream", "object": "collection", "arguments": { "pipeline": [] }, "saveResultAsEntity": "changeStream" } ], "expectEvents": [ { "client": "client", "eventType": "cmap", "events": [ { "connectionCheckOutStartedEvent": {} }, { "connectionCheckOutStartedEvent": {} }, { "connectionCheckOutStartedEvent": {} }, { "connectionCheckOutStartedEvent": {} } ] }, { "client": "client", "events": [ { "commandStartedEvent": { "command": { "ping": 1 }, "databaseName": "retryable-reads-handshake-tests" } }, { "commandFailedEvent": { "commandName": "ping" } }, { "commandStartedEvent": { "commandName": "aggregate" } }, { "commandSucceededEvent": { "commandName": "aggregate" } } ] } ] }, { "description": "collection.createChangeStream succeeds after retryable handshake server error (ShutdownInProgress)", "runOnRequirements": [ { "serverless": "forbid" } ], "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "client", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 2 }, "data": { "failCommands": [ "ping", "saslContinue" ], "closeConnection": true } } } }, { "name": "runCommand", "object": "database", "arguments": { "commandName": "ping", "command": { "ping": 1 } }, "expectError": { "isError": true } }, { "name": "createChangeStream", "object": "collection", "arguments": { "pipeline": [] }, "saveResultAsEntity": "changeStream" } ], "expectEvents": [ { "client": "client", "eventType": "cmap", "events": [ { "connectionCheckOutStartedEvent": {} }, { "connectionCheckOutStartedEvent": {} }, { "connectionCheckOutStartedEvent": {} }, { "connectionCheckOutStartedEvent": {} } ] }, { "client": "client", "events": [ { "commandStartedEvent": { "command": { "ping": 1 }, "databaseName": "retryable-reads-handshake-tests" } }, { "commandFailedEvent": { "commandName": "ping" } }, { "commandStartedEvent": { "commandName": "aggregate" } }, { "commandSucceededEvent": { "commandName": "aggregate" } } ] } ] } ] } readConcernMajorityNotAvailableYet.json000066400000000000000000000062561462766011000347410ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/retryable_reads/unified{ "description": "ReadConcernMajorityNotAvailableYet is a retryable read", "schemaVersion": "1.3", "runOnRequirements": [ { "minServerVersion": "4.0", "topologies": [ "single", "replicaset" ] }, { "minServerVersion": "4.1.7", "topologies": [ "sharded", "load-balanced" ] } ], "createEntities": [ { "client": { "id": "client0", "useMultipleMongoses": false, "observeEvents": [ "commandStartedEvent" ] } }, { "database": { "id": "database0", "client": "client0", "databaseName": "retryable-reads-tests" } }, { "collection": { "id": "collection0", "database": "database0", "collectionName": "readconcernmajoritynotavailableyet_test" } } ], "initialData": [ { "collectionName": "readconcernmajoritynotavailableyet_test", "databaseName": "retryable-reads-tests", "documents": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 22 }, { "_id": 3, "x": 33 } ] } ], "tests": [ { "description": "Find succeeds on second attempt after ReadConcernMajorityNotAvailableYet", "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "client0", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "find" ], "errorCode": 134 } } } }, { "name": "find", "arguments": { "filter": { "_id": { "$gt": 1 } } }, "object": "collection0", "expectResult": [ { "_id": 2, "x": 22 }, { "_id": 3, "x": 33 } ] } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "find": "readconcernmajoritynotavailableyet_test", "filter": { "_id": { "$gt": 1 } } }, "commandName": "find", "databaseName": "retryable-reads-tests" } }, { "commandStartedEvent": { "command": { "find": "readconcernmajoritynotavailableyet_test", "filter": { "_id": { "$gt": 1 } } }, "commandName": "find", "databaseName": "retryable-reads-tests" } } ] } ] } ] } mongodb-mongo-python-driver-509e9b7/test/retryable_writes/000077500000000000000000000000001462766011000240025ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/retryable_writes/legacy/000077500000000000000000000000001462766011000252465ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/retryable_writes/legacy/bulkWrite-errorLabels.json000066400000000000000000000163731462766011000323750ustar00rootroot00000000000000{ "runOn": [ { "minServerVersion": "4.3.1", "topology": [ "replicaset", "sharded", "load-balanced" ] } ], "data": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 22 } ], "tests": [ { "description": "BulkWrite succeeds with RetryableWriteError from server", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "update" ], "errorCode": 112, "errorLabels": [ "RetryableWriteError" ] } }, "operation": { "name": "bulkWrite", "arguments": { "requests": [ { "name": "deleteOne", "arguments": { "filter": { "_id": 1 } } }, { "name": "insertOne", "arguments": { "document": { "_id": 3, "x": 33 } } }, { "name": "updateOne", "arguments": { "filter": { "_id": 2 }, "update": { "$inc": { "x": 1 } } } } ], "options": { "ordered": true } } }, "outcome": { "result": { "deletedCount": 1, "insertedCount": 1, "insertedIds": { "1": 3 }, "matchedCount": 1, "modifiedCount": 1, "upsertedCount": 0, "upsertedIds": {} }, "collection": { "data": [ { "_id": 2, "x": 23 }, { "_id": 3, "x": 33 } ] } } }, { "description": "BulkWrite fails if server does not return RetryableWriteError", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "update" ], "errorCode": 11600, "errorLabels": [] } }, "operation": { "name": "bulkWrite", "arguments": { "requests": [ { "name": "deleteOne", "arguments": { "filter": { "_id": 1 } } }, { "name": "insertOne", "arguments": { "document": { "_id": 3, "x": 33 } } }, { "name": "updateOne", "arguments": { "filter": { "_id": 2 }, "update": { "$inc": { "x": 1 } } } } ], "options": { "ordered": true } } }, "outcome": { "error": true, "result": { "errorLabelsOmit": [ "RetryableWriteError" ] }, "collection": { "data": [ { "_id": 2, "x": 22 }, { "_id": 3, "x": 33 } ] } } }, { "description": "BulkWrite succeeds after PrimarySteppedDown", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "update" ], "errorCode": 189, "errorLabels": [ "RetryableWriteError" ] } }, "operation": { "name": "bulkWrite", "arguments": { "requests": [ { "name": "deleteOne", "arguments": { "filter": { "_id": 1 } } }, { "name": "insertOne", "arguments": { "document": { "_id": 3, "x": 33 } } }, { "name": "updateOne", "arguments": { "filter": { "_id": 2 }, "update": { "$inc": { "x": 1 } } } } ], "options": { "ordered": true } } }, "outcome": { "result": { "deletedCount": 1, "insertedCount": 1, "insertedIds": { "1": 3 }, "matchedCount": 1, "modifiedCount": 1, "upsertedCount": 0, "upsertedIds": {} }, "collection": { "data": [ { "_id": 2, "x": 23 }, { "_id": 3, "x": 33 } ] } } }, { "description": "BulkWrite succeeds after WriteConcernError ShutdownInProgress", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "insert" ], "errorLabels": [ "RetryableWriteError" ], "writeConcernError": { "code": 91, "errmsg": "Replication is being shut down" } } }, "operation": { "name": "bulkWrite", "arguments": { "requests": [ { "name": "deleteOne", "arguments": { "filter": { "_id": 1 } } }, { "name": "insertOne", "arguments": { "document": { "_id": 3, "x": 33 } } }, { "name": "updateOne", "arguments": { "filter": { "_id": 2 }, "update": { "$inc": { "x": 1 } } } } ], "options": { "ordered": true } } }, "outcome": { "result": { "deletedCount": 1, "insertedCount": 1, "insertedIds": { "1": 3 }, "matchedCount": 1, "modifiedCount": 1, "upsertedCount": 0, "upsertedIds": {} }, "collection": { "data": [ { "_id": 2, "x": 23 }, { "_id": 3, "x": 33 } ] } } } ] } mongodb-mongo-python-driver-509e9b7/test/retryable_writes/legacy/bulkWrite-serverErrors.json000066400000000000000000000036761462766011000326260ustar00rootroot00000000000000{ "runOn": [ { "minServerVersion": "4.0", "topology": [ "replicaset" ] }, { "minServerVersion": "4.1.7", "topology": [ "sharded", "load-balanced" ] } ], "data": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 22 } ], "tests": [ { "description": "BulkWrite fails with a RetryableWriteError label after two connection failures", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 2 }, "data": { "failCommands": [ "update" ], "closeConnection": true } }, "operation": { "name": "bulkWrite", "arguments": { "requests": [ { "name": "deleteOne", "arguments": { "filter": { "_id": 1 } } }, { "name": "insertOne", "arguments": { "document": { "_id": 3, "x": 33 } } }, { "name": "updateOne", "arguments": { "filter": { "_id": 2 }, "update": { "$inc": { "x": 1 } } } } ], "options": { "ordered": true } } }, "outcome": { "error": true, "result": { "errorLabelsContain": [ "RetryableWriteError" ] }, "collection": { "data": [ { "_id": 2, "x": 22 }, { "_id": 3, "x": 33 } ] } } } ] } mongodb-mongo-python-driver-509e9b7/test/retryable_writes/legacy/bulkWrite.json000066400000000000000000000421551462766011000301200ustar00rootroot00000000000000{ "runOn": [ { "minServerVersion": "3.6", "topology": [ "replicaset" ] } ], "data": [ { "_id": 1, "x": 11 } ], "tests": [ { "description": "First command is retried", "failPoint": { "configureFailPoint": "onPrimaryTransactionalWrite", "mode": { "times": 1 } }, "operation": { "name": "bulkWrite", "arguments": { "requests": [ { "name": "insertOne", "arguments": { "document": { "_id": 2, "x": 22 } } }, { "name": "updateOne", "arguments": { "filter": { "_id": 2 }, "update": { "$inc": { "x": 1 } } } }, { "name": "deleteOne", "arguments": { "filter": { "_id": 1 } } } ], "options": { "ordered": true } } }, "outcome": { "result": { "deletedCount": 1, "insertedCount": 1, "insertedIds": { "0": 2 }, "matchedCount": 1, "modifiedCount": 1, "upsertedCount": 0, "upsertedIds": {} }, "collection": { "data": [ { "_id": 2, "x": 23 } ] } } }, { "description": "All commands are retried", "failPoint": { "configureFailPoint": "onPrimaryTransactionalWrite", "mode": { "times": 7 } }, "operation": { "name": "bulkWrite", "arguments": { "requests": [ { "name": "insertOne", "arguments": { "document": { "_id": 2, "x": 22 } } }, { "name": "updateOne", "arguments": { "filter": { "_id": 2 }, "update": { "$inc": { "x": 1 } } } }, { "name": "insertOne", "arguments": { "document": { "_id": 3, "x": 33 } } }, { "name": "updateOne", "arguments": { "filter": { "_id": 4, "x": 44 }, "update": { "$inc": { "x": 1 } }, "upsert": true } }, { "name": "insertOne", "arguments": { "document": { "_id": 5, "x": 55 } } }, { "name": "replaceOne", "arguments": { "filter": { "_id": 3 }, "replacement": { "_id": 3, "x": 333 } } }, { "name": "deleteOne", "arguments": { "filter": { "_id": 1 } } } ], "options": { "ordered": true } } }, "outcome": { "result": { "deletedCount": 1, "insertedCount": 3, "insertedIds": { "0": 2, "2": 3, "4": 5 }, "matchedCount": 2, "modifiedCount": 2, "upsertedCount": 1, "upsertedIds": { "3": 4 } }, "collection": { "data": [ { "_id": 2, "x": 23 }, { "_id": 3, "x": 333 }, { "_id": 4, "x": 45 }, { "_id": 5, "x": 55 } ] } } }, { "description": "Both commands are retried after their first statement fails", "failPoint": { "configureFailPoint": "onPrimaryTransactionalWrite", "mode": { "times": 2 } }, "operation": { "name": "bulkWrite", "arguments": { "requests": [ { "name": "insertOne", "arguments": { "document": { "_id": 2, "x": 22 } } }, { "name": "updateOne", "arguments": { "filter": { "_id": 1 }, "update": { "$inc": { "x": 1 } } } }, { "name": "updateOne", "arguments": { "filter": { "_id": 2 }, "update": { "$inc": { "x": 1 } } } } ], "options": { "ordered": true } } }, "outcome": { "result": { "deletedCount": 0, "insertedCount": 1, "insertedIds": { "0": 2 }, "matchedCount": 2, "modifiedCount": 2, "upsertedCount": 0, "upsertedIds": {} }, "collection": { "data": [ { "_id": 1, "x": 12 }, { "_id": 2, "x": 23 } ] } } }, { "description": "Second command is retried after its second statement fails", "failPoint": { "configureFailPoint": "onPrimaryTransactionalWrite", "mode": { "skip": 2 } }, "operation": { "name": "bulkWrite", "arguments": { "requests": [ { "name": "insertOne", "arguments": { "document": { "_id": 2, "x": 22 } } }, { "name": "updateOne", "arguments": { "filter": { "_id": 1 }, "update": { "$inc": { "x": 1 } } } }, { "name": "updateOne", "arguments": { "filter": { "_id": 2 }, "update": { "$inc": { "x": 1 } } } } ], "options": { "ordered": true } } }, "outcome": { "result": { "deletedCount": 0, "insertedCount": 1, "insertedIds": { "0": 2 }, "matchedCount": 2, "modifiedCount": 2, "upsertedCount": 0, "upsertedIds": {} }, "collection": { "data": [ { "_id": 1, "x": 12 }, { "_id": 2, "x": 23 } ] } } }, { "description": "BulkWrite with unordered execution", "failPoint": { "configureFailPoint": "onPrimaryTransactionalWrite", "mode": { "times": 1 } }, "operation": { "name": "bulkWrite", "arguments": { "requests": [ { "name": "insertOne", "arguments": { "document": { "_id": 2, "x": 22 } } }, { "name": "insertOne", "arguments": { "document": { "_id": 3, "x": 33 } } } ], "options": { "ordered": false } } }, "outcome": { "result": { "deletedCount": 0, "insertedCount": 2, "insertedIds": { "0": 2, "1": 3 }, "matchedCount": 0, "modifiedCount": 0, "upsertedCount": 0, "upsertedIds": {} }, "collection": { "data": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 22 }, { "_id": 3, "x": 33 } ] } } }, { "description": "First insertOne is never committed", "failPoint": { "configureFailPoint": "onPrimaryTransactionalWrite", "mode": { "times": 2 }, "data": { "failBeforeCommitExceptionCode": 1 } }, "operation": { "name": "bulkWrite", "arguments": { "requests": [ { "name": "insertOne", "arguments": { "document": { "_id": 2, "x": 22 } } }, { "name": "updateOne", "arguments": { "filter": { "_id": 2 }, "update": { "$inc": { "x": 1 } } } }, { "name": "deleteOne", "arguments": { "filter": { "_id": 1 } } } ], "options": { "ordered": true } } }, "outcome": { "error": true, "result": { "deletedCount": 0, "insertedCount": 0, "insertedIds": {}, "matchedCount": 0, "modifiedCount": 0, "upsertedCount": 0, "upsertedIds": {} }, "collection": { "data": [ { "_id": 1, "x": 11 } ] } } }, { "description": "Second updateOne is never committed", "failPoint": { "configureFailPoint": "onPrimaryTransactionalWrite", "mode": { "skip": 1 }, "data": { "failBeforeCommitExceptionCode": 1 } }, "operation": { "name": "bulkWrite", "arguments": { "requests": [ { "name": "insertOne", "arguments": { "document": { "_id": 2, "x": 22 } } }, { "name": "updateOne", "arguments": { "filter": { "_id": 2 }, "update": { "$inc": { "x": 1 } } } }, { "name": "deleteOne", "arguments": { "filter": { "_id": 1 } } } ], "options": { "ordered": true } } }, "outcome": { "error": true, "result": { "deletedCount": 0, "insertedCount": 1, "insertedIds": { "0": 2 }, "matchedCount": 0, "modifiedCount": 0, "upsertedCount": 0, "upsertedIds": {} }, "collection": { "data": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 22 } ] } } }, { "description": "Third updateOne is never committed", "failPoint": { "configureFailPoint": "onPrimaryTransactionalWrite", "mode": { "skip": 2 }, "data": { "failBeforeCommitExceptionCode": 1 } }, "operation": { "name": "bulkWrite", "arguments": { "requests": [ { "name": "updateOne", "arguments": { "filter": { "_id": 1 }, "update": { "$inc": { "x": 1 } } } }, { "name": "insertOne", "arguments": { "document": { "_id": 2, "x": 22 } } }, { "name": "updateOne", "arguments": { "filter": { "_id": 2 }, "update": { "$inc": { "x": 1 } } } } ], "options": { "ordered": true } } }, "outcome": { "error": true, "result": { "deletedCount": 0, "insertedCount": 1, "insertedIds": { "1": 2 }, "matchedCount": 1, "modifiedCount": 1, "upsertedCount": 0, "upsertedIds": {} }, "collection": { "data": [ { "_id": 1, "x": 12 }, { "_id": 2, "x": 22 } ] } } }, { "description": "Single-document write following deleteMany is retried", "failPoint": { "configureFailPoint": "onPrimaryTransactionalWrite", "mode": { "times": 1 }, "data": { "failBeforeCommitExceptionCode": 1 } }, "operation": { "name": "bulkWrite", "arguments": { "requests": [ { "name": "deleteMany", "arguments": { "filter": { "x": 11 } } }, { "name": "insertOne", "arguments": { "document": { "_id": 2, "x": 22 } } } ], "options": { "ordered": true } } }, "outcome": { "result": { "deletedCount": 1, "insertedCount": 1, "insertedIds": { "1": 2 }, "matchedCount": 0, "modifiedCount": 0, "upsertedCount": 0, "upsertedIds": {} }, "collection": { "data": [ { "_id": 2, "x": 22 } ] } } }, { "description": "Single-document write following updateMany is retried", "failPoint": { "configureFailPoint": "onPrimaryTransactionalWrite", "mode": { "times": 1 }, "data": { "failBeforeCommitExceptionCode": 1 } }, "operation": { "name": "bulkWrite", "arguments": { "requests": [ { "name": "updateMany", "arguments": { "filter": { "x": 11 }, "update": { "$inc": { "x": 1 } } } }, { "name": "insertOne", "arguments": { "document": { "_id": 2, "x": 22 } } } ], "options": { "ordered": true } } }, "outcome": { "result": { "deletedCount": 0, "insertedCount": 1, "insertedIds": { "1": 2 }, "matchedCount": 1, "modifiedCount": 1, "upsertedCount": 0, "upsertedIds": {} }, "collection": { "data": [ { "_id": 1, "x": 12 }, { "_id": 2, "x": 22 } ] } } } ] } mongodb-mongo-python-driver-509e9b7/test/retryable_writes/legacy/deleteMany.json000066400000000000000000000011761462766011000302350ustar00rootroot00000000000000{ "runOn": [ { "minServerVersion": "3.6", "topology": [ "replicaset", "sharded", "load-balanced" ] } ], "data": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 22 } ], "tests": [ { "description": "DeleteMany ignores retryWrites", "useMultipleMongoses": true, "operation": { "name": "deleteMany", "arguments": { "filter": {} } }, "outcome": { "result": { "deletedCount": 2 }, "collection": { "data": [] } } } ] } mongodb-mongo-python-driver-509e9b7/test/retryable_writes/legacy/deleteOne-errorLabels.json000066400000000000000000000070311462766011000323200ustar00rootroot00000000000000{ "runOn": [ { "minServerVersion": "4.3.1", "topology": [ "replicaset", "sharded", "load-balanced" ] } ], "data": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 22 } ], "tests": [ { "description": "DeleteOne succeeds with RetryableWriteError from server", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "delete" ], "errorCode": 112, "errorLabels": [ "RetryableWriteError" ] } }, "operation": { "name": "deleteOne", "arguments": { "filter": { "_id": 1 } } }, "outcome": { "result": { "deletedCount": 1 }, "collection": { "data": [ { "_id": 2, "x": 22 } ] } } }, { "description": "DeleteOne fails if server does not return RetryableWriteError", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "delete" ], "errorCode": 11600, "errorLabels": [] } }, "operation": { "name": "deleteOne", "arguments": { "filter": { "_id": 1 } } }, "outcome": { "error": true, "result": { "errorLabelsOmit": [ "RetryableWriteError" ] }, "collection": { "data": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 22 } ] } } }, { "description": "DeleteOne succeeds after PrimarySteppedDown", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "delete" ], "errorCode": 189, "errorLabels": [ "RetryableWriteError" ] } }, "operation": { "name": "deleteOne", "arguments": { "filter": { "_id": 1 } } }, "outcome": { "result": { "deletedCount": 1 }, "collection": { "data": [ { "_id": 2, "x": 22 } ] } } }, { "description": "DeleteOne succeeds after WriteConcernError ShutdownInProgress", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "delete" ], "errorLabels": [ "RetryableWriteError" ], "writeConcernError": { "code": 91, "errmsg": "Replication is being shut down" } } }, "operation": { "name": "deleteOne", "arguments": { "filter": { "_id": 1 } } }, "outcome": { "result": { "deletedCount": 1 }, "collection": { "data": [ { "_id": 2, "x": 22 } ] } } } ] } mongodb-mongo-python-driver-509e9b7/test/retryable_writes/legacy/deleteOne-serverErrors.json000066400000000000000000000023271462766011000325520ustar00rootroot00000000000000{ "runOn": [ { "minServerVersion": "4.0", "topology": [ "replicaset" ] }, { "minServerVersion": "4.1.7", "topology": [ "sharded", "load-balanced" ] } ], "data": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 22 } ], "tests": [ { "description": "DeleteOne fails with RetryableWriteError label after two connection failures", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 2 }, "data": { "failCommands": [ "delete" ], "closeConnection": true } }, "operation": { "name": "deleteOne", "arguments": { "filter": { "_id": 1 } } }, "outcome": { "error": true, "result": { "errorLabelsContain": [ "RetryableWriteError" ] }, "collection": { "data": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 22 } ] } } } ] } mongodb-mongo-python-driver-509e9b7/test/retryable_writes/legacy/deleteOne.json000066400000000000000000000042101462766011000300420ustar00rootroot00000000000000{ "runOn": [ { "minServerVersion": "3.6", "topology": [ "replicaset" ] } ], "data": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 22 } ], "tests": [ { "description": "DeleteOne is committed on first attempt", "failPoint": { "configureFailPoint": "onPrimaryTransactionalWrite", "mode": { "times": 1 } }, "operation": { "name": "deleteOne", "arguments": { "filter": { "_id": 1 } } }, "outcome": { "result": { "deletedCount": 1 }, "collection": { "data": [ { "_id": 2, "x": 22 } ] } } }, { "description": "DeleteOne is not committed on first attempt", "failPoint": { "configureFailPoint": "onPrimaryTransactionalWrite", "mode": { "times": 1 }, "data": { "failBeforeCommitExceptionCode": 1 } }, "operation": { "name": "deleteOne", "arguments": { "filter": { "_id": 1 } } }, "outcome": { "result": { "deletedCount": 1 }, "collection": { "data": [ { "_id": 2, "x": 22 } ] } } }, { "description": "DeleteOne is never committed", "failPoint": { "configureFailPoint": "onPrimaryTransactionalWrite", "mode": { "times": 2 }, "data": { "failBeforeCommitExceptionCode": 1 } }, "operation": { "name": "deleteOne", "arguments": { "filter": { "_id": 1 } } }, "outcome": { "error": true, "collection": { "data": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 22 } ] } } } ] } mongodb-mongo-python-driver-509e9b7/test/retryable_writes/legacy/findOneAndDelete-errorLabels.json000066400000000000000000000077571462766011000335630ustar00rootroot00000000000000{ "runOn": [ { "minServerVersion": "4.3.1", "topology": [ "replicaset", "sharded", "load-balanced" ] } ], "data": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 22 } ], "tests": [ { "description": "FindOneAndDelete succeeds with RetryableWriteError from server", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "findAndModify" ], "errorCode": 112, "errorLabels": [ "RetryableWriteError" ] } }, "operation": { "name": "findOneAndDelete", "arguments": { "filter": { "x": { "$gte": 11 } }, "sort": { "x": 1 } } }, "outcome": { "result": { "_id": 1, "x": 11 }, "collection": { "data": [ { "_id": 2, "x": 22 } ] } } }, { "description": "FindOneAndDelete fails if server does not return RetryableWriteError", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "findAndModify" ], "errorCode": 11600, "errorLabels": [] } }, "operation": { "name": "findOneAndDelete", "arguments": { "filter": { "x": { "$gte": 11 } }, "sort": { "x": 1 } } }, "outcome": { "error": true, "result": { "errorLabelsOmit": [ "RetryableWriteError" ] }, "collection": { "data": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 22 } ] } } }, { "description": "FindOneAndDelete succeeds after PrimarySteppedDown", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "findAndModify" ], "errorCode": 189, "errorLabels": [ "RetryableWriteError" ] } }, "operation": { "name": "findOneAndDelete", "arguments": { "filter": { "x": { "$gte": 11 } }, "sort": { "x": 1 } } }, "outcome": { "result": { "_id": 1, "x": 11 }, "collection": { "data": [ { "_id": 2, "x": 22 } ] } } }, { "description": "FindOneAndDelete succeeds after WriteConcernError ShutdownInProgress", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "findAndModify" ], "errorLabels": [ "RetryableWriteError" ], "writeConcernError": { "code": 91, "errmsg": "Replication is being shut down" } } }, "operation": { "name": "findOneAndDelete", "arguments": { "filter": { "x": { "$gte": 11 } }, "sort": { "x": 1 } } }, "outcome": { "result": { "_id": 1, "x": 11 }, "collection": { "data": [ { "_id": 2, "x": 22 } ] } } } ] } mongodb-mongo-python-driver-509e9b7/test/retryable_writes/legacy/findOneAndDelete-serverErrors.json000066400000000000000000000025071462766011000337760ustar00rootroot00000000000000{ "runOn": [ { "minServerVersion": "4.0", "topology": [ "replicaset" ] }, { "minServerVersion": "4.1.7", "topology": [ "sharded", "load-balanced" ] } ], "data": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 22 } ], "tests": [ { "description": "FindOneAndDelete fails with a RetryableWriteError label after two connection failures", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 2 }, "data": { "failCommands": [ "findAndModify" ], "closeConnection": true } }, "operation": { "name": "findOneAndDelete", "arguments": { "filter": { "x": { "$gte": 11 } }, "sort": { "x": 1 } } }, "outcome": { "error": true, "result": { "errorLabelsContain": [ "RetryableWriteError" ] }, "collection": { "data": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 22 } ] } } } ] } mongodb-mongo-python-driver-509e9b7/test/retryable_writes/legacy/findOneAndDelete.json000066400000000000000000000047211462766011000312750ustar00rootroot00000000000000{ "runOn": [ { "minServerVersion": "3.6", "topology": [ "replicaset" ] } ], "data": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 22 } ], "tests": [ { "description": "FindOneAndDelete is committed on first attempt", "failPoint": { "configureFailPoint": "onPrimaryTransactionalWrite", "mode": { "times": 1 } }, "operation": { "name": "findOneAndDelete", "arguments": { "filter": { "x": { "$gte": 11 } }, "sort": { "x": 1 } } }, "outcome": { "result": { "_id": 1, "x": 11 }, "collection": { "data": [ { "_id": 2, "x": 22 } ] } } }, { "description": "FindOneAndDelete is not committed on first attempt", "failPoint": { "configureFailPoint": "onPrimaryTransactionalWrite", "mode": { "times": 1 }, "data": { "failBeforeCommitExceptionCode": 1 } }, "operation": { "name": "findOneAndDelete", "arguments": { "filter": { "x": { "$gte": 11 } }, "sort": { "x": 1 } } }, "outcome": { "result": { "_id": 1, "x": 11 }, "collection": { "data": [ { "_id": 2, "x": 22 } ] } } }, { "description": "FindOneAndDelete is never committed", "failPoint": { "configureFailPoint": "onPrimaryTransactionalWrite", "mode": { "times": 2 }, "data": { "failBeforeCommitExceptionCode": 1 } }, "operation": { "name": "findOneAndDelete", "arguments": { "filter": { "x": { "$gte": 11 } }, "sort": { "x": 1 } } }, "outcome": { "error": true, "collection": { "data": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 22 } ] } } } ] } mongodb-mongo-python-driver-509e9b7/test/retryable_writes/legacy/findOneAndReplace-errorLabels.json000066400000000000000000000105331462766011000337160ustar00rootroot00000000000000{ "runOn": [ { "minServerVersion": "4.3.1", "topology": [ "replicaset", "sharded", "load-balanced" ] } ], "data": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 22 } ], "tests": [ { "description": "FindOneAndReplace succeeds with RetryableWriteError from server", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "findAndModify" ], "errorCode": 112, "errorLabels": [ "RetryableWriteError" ] } }, "operation": { "name": "findOneAndReplace", "arguments": { "filter": { "_id": 1 }, "replacement": { "_id": 1, "x": 111 }, "returnDocument": "Before" } }, "outcome": { "result": { "_id": 1, "x": 11 }, "collection": { "data": [ { "_id": 1, "x": 111 }, { "_id": 2, "x": 22 } ] } } }, { "description": "FindOneAndReplace fails if server does not return RetryableWriteError", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "findAndModify" ], "errorCode": 11600, "errorLabels": [] } }, "operation": { "name": "findOneAndReplace", "arguments": { "filter": { "_id": 1 }, "replacement": { "_id": 1, "x": 111 }, "returnDocument": "Before" } }, "outcome": { "error": true, "result": { "errorLabelsOmit": [ "RetryableWriteError" ] }, "collection": { "data": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 22 } ] } } }, { "description": "FindOneAndReplace succeeds after PrimarySteppedDown", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "findAndModify" ], "errorCode": 189, "errorLabels": [ "RetryableWriteError" ] } }, "operation": { "name": "findOneAndReplace", "arguments": { "filter": { "_id": 1 }, "replacement": { "_id": 1, "x": 111 }, "returnDocument": "Before" } }, "outcome": { "result": { "_id": 1, "x": 11 }, "collection": { "data": [ { "_id": 1, "x": 111 }, { "_id": 2, "x": 22 } ] } } }, { "description": "FindOneAndReplace succeeds after WriteConcernError ShutdownInProgress", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "findAndModify" ], "errorLabels": [ "RetryableWriteError" ], "writeConcernError": { "code": 91, "errmsg": "Replication is being shut down" } } }, "operation": { "name": "findOneAndReplace", "arguments": { "filter": { "_id": 1 }, "replacement": { "_id": 1, "x": 111 }, "returnDocument": "Before" } }, "outcome": { "result": { "_id": 1, "x": 11 }, "collection": { "data": [ { "_id": 1, "x": 111 }, { "_id": 2, "x": 22 } ] } } } ] } mongodb-mongo-python-driver-509e9b7/test/retryable_writes/legacy/findOneAndReplace-serverErrors.json000066400000000000000000000025511462766011000341460ustar00rootroot00000000000000{ "runOn": [ { "minServerVersion": "4.0", "topology": [ "replicaset" ] }, { "minServerVersion": "4.1.7", "topology": [ "sharded", "load-balanced" ] } ], "data": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 22 } ], "tests": [ { "description": "FindOneAndReplace fails with a RetryableWriteError label after two connection failures", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 2 }, "data": { "failCommands": [ "findAndModify" ], "closeConnection": true } }, "operation": { "name": "findOneAndReplace", "arguments": { "filter": { "_id": 1 }, "replacement": { "_id": 1, "x": 111 }, "returnDocument": "Before" } }, "outcome": { "error": true, "result": { "errorLabelsContain": [ "RetryableWriteError" ] }, "collection": { "data": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 22 } ] } } } ] } mongodb-mongo-python-driver-509e9b7/test/retryable_writes/legacy/findOneAndReplace.json000066400000000000000000000053171462766011000314500ustar00rootroot00000000000000{ "runOn": [ { "minServerVersion": "3.6", "topology": [ "replicaset" ] } ], "data": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 22 } ], "tests": [ { "description": "FindOneAndReplace is committed on first attempt", "failPoint": { "configureFailPoint": "onPrimaryTransactionalWrite", "mode": { "times": 1 } }, "operation": { "name": "findOneAndReplace", "arguments": { "filter": { "_id": 1 }, "replacement": { "_id": 1, "x": 111 }, "returnDocument": "Before" } }, "outcome": { "result": { "_id": 1, "x": 11 }, "collection": { "data": [ { "_id": 1, "x": 111 }, { "_id": 2, "x": 22 } ] } } }, { "description": "FindOneAndReplace is not committed on first attempt", "failPoint": { "configureFailPoint": "onPrimaryTransactionalWrite", "mode": { "times": 1 }, "data": { "failBeforeCommitExceptionCode": 1 } }, "operation": { "name": "findOneAndReplace", "arguments": { "filter": { "_id": 1 }, "replacement": { "_id": 1, "x": 111 }, "returnDocument": "Before" } }, "outcome": { "result": { "_id": 1, "x": 11 }, "collection": { "data": [ { "_id": 1, "x": 111 }, { "_id": 2, "x": 22 } ] } } }, { "description": "FindOneAndReplace is never committed", "failPoint": { "configureFailPoint": "onPrimaryTransactionalWrite", "mode": { "times": 2 }, "data": { "failBeforeCommitExceptionCode": 1 } }, "operation": { "name": "findOneAndReplace", "arguments": { "filter": { "_id": 1 }, "replacement": { "_id": 1, "x": 111 }, "returnDocument": "Before" } }, "outcome": { "error": true, "collection": { "data": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 22 } ] } } } ] } mongodb-mongo-python-driver-509e9b7/test/retryable_writes/legacy/findOneAndUpdate-errorLabels.json000066400000000000000000000105641462766011000335710ustar00rootroot00000000000000{ "runOn": [ { "minServerVersion": "4.3.1", "topology": [ "replicaset", "sharded", "load-balanced" ] } ], "data": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 22 } ], "tests": [ { "description": "FindOneAndUpdate succeeds with RetryableWriteError from server", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "findAndModify" ], "errorCode": 112, "errorLabels": [ "RetryableWriteError" ] } }, "operation": { "name": "findOneAndUpdate", "arguments": { "filter": { "_id": 1 }, "update": { "$inc": { "x": 1 } }, "returnDocument": "Before" } }, "outcome": { "result": { "_id": 1, "x": 11 }, "collection": { "data": [ { "_id": 1, "x": 12 }, { "_id": 2, "x": 22 } ] } } }, { "description": "FindOneAndUpdate fails if server does not return RetryableWriteError", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "findAndModify" ], "errorCode": 11600, "errorLabels": [] } }, "operation": { "name": "findOneAndUpdate", "arguments": { "filter": { "_id": 1 }, "update": { "$inc": { "x": 1 } }, "returnDocument": "Before" } }, "outcome": { "error": true, "result": { "errorLabelsOmit": [ "RetryableWriteError" ] }, "collection": { "data": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 22 } ] } } }, { "description": "FindOneAndUpdate succeeds after PrimarySteppedDown", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "findAndModify" ], "errorCode": 189, "errorLabels": [ "RetryableWriteError" ] } }, "operation": { "name": "findOneAndUpdate", "arguments": { "filter": { "_id": 1 }, "update": { "$inc": { "x": 1 } }, "returnDocument": "Before" } }, "outcome": { "result": { "_id": 1, "x": 11 }, "collection": { "data": [ { "_id": 1, "x": 12 }, { "_id": 2, "x": 22 } ] } } }, { "description": "FindOneAndUpdate succeeds after WriteConcernError ShutdownInProgress", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "findAndModify" ], "errorLabels": [ "RetryableWriteError" ], "writeConcernError": { "code": 91, "errmsg": "Replication is being shut down" } } }, "operation": { "name": "findOneAndUpdate", "arguments": { "filter": { "_id": 1 }, "update": { "$inc": { "x": 1 } }, "returnDocument": "Before" } }, "outcome": { "result": { "_id": 1, "x": 11 }, "collection": { "data": [ { "_id": 1, "x": 12 }, { "_id": 2, "x": 22 } ] } } } ] } mongodb-mongo-python-driver-509e9b7/test/retryable_writes/legacy/findOneAndUpdate-serverErrors.json000066400000000000000000000025601462766011000340150ustar00rootroot00000000000000{ "runOn": [ { "minServerVersion": "4.0", "topology": [ "replicaset" ] }, { "minServerVersion": "4.1.7", "topology": [ "sharded", "load-balanced" ] } ], "data": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 22 } ], "tests": [ { "description": "FindOneAndUpdate fails with a RetryableWriteError label after two connection failures", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 2 }, "data": { "failCommands": [ "findAndModify" ], "closeConnection": true } }, "operation": { "name": "findOneAndUpdate", "arguments": { "filter": { "_id": 1 }, "update": { "$inc": { "x": 1 } }, "returnDocument": "Before" } }, "outcome": { "error": true, "result": { "errorLabelsContain": [ "RetryableWriteError" ] }, "collection": { "data": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 22 } ] } } } ] } mongodb-mongo-python-driver-509e9b7/test/retryable_writes/legacy/findOneAndUpdate.json000066400000000000000000000052741462766011000313210ustar00rootroot00000000000000{ "runOn": [ { "minServerVersion": "3.6", "topology": [ "replicaset" ] } ], "data": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 22 } ], "tests": [ { "description": "FindOneAndUpdate is committed on first attempt", "failPoint": { "configureFailPoint": "onPrimaryTransactionalWrite", "mode": { "times": 1 } }, "operation": { "name": "findOneAndUpdate", "arguments": { "filter": { "_id": 1 }, "update": { "$inc": { "x": 1 } }, "returnDocument": "Before" } }, "outcome": { "result": { "_id": 1, "x": 11 }, "collection": { "data": [ { "_id": 1, "x": 12 }, { "_id": 2, "x": 22 } ] } } }, { "description": "FindOneAndUpdate is not committed on first attempt", "failPoint": { "configureFailPoint": "onPrimaryTransactionalWrite", "mode": { "times": 1 }, "data": { "failBeforeCommitExceptionCode": 1 } }, "operation": { "name": "findOneAndUpdate", "arguments": { "filter": { "_id": 1 }, "update": { "$inc": { "x": 1 } }, "returnDocument": "Before" } }, "outcome": { "result": { "_id": 1, "x": 11 }, "collection": { "data": [ { "_id": 1, "x": 12 }, { "_id": 2, "x": 22 } ] } } }, { "description": "FindOneAndUpdate is never committed", "failPoint": { "configureFailPoint": "onPrimaryTransactionalWrite", "mode": { "times": 2 }, "data": { "failBeforeCommitExceptionCode": 1 } }, "operation": { "name": "findOneAndUpdate", "arguments": { "filter": { "_id": 1 }, "update": { "$inc": { "x": 1 } } } }, "outcome": { "error": true, "collection": { "data": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 22 } ] } } } ] } mongodb-mongo-python-driver-509e9b7/test/retryable_writes/legacy/insertMany-errorLabels.json000066400000000000000000000114171462766011000325500ustar00rootroot00000000000000{ "runOn": [ { "minServerVersion": "4.3.1", "topology": [ "replicaset", "sharded", "load-balanced" ] } ], "data": [ { "_id": 1, "x": 11 } ], "tests": [ { "description": "InsertMany succeeds with RetryableWriteError from server", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "insert" ], "errorCode": 112, "errorLabels": [ "RetryableWriteError" ] } }, "operation": { "name": "insertMany", "arguments": { "documents": [ { "_id": 2, "x": 22 }, { "_id": 3, "x": 33 } ], "options": { "ordered": true } } }, "outcome": { "result": { "insertedIds": { "0": 2, "1": 3 } }, "collection": { "data": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 22 }, { "_id": 3, "x": 33 } ] } } }, { "description": "InsertMany fails if server does not return RetryableWriteError", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "insert" ], "errorCode": 11600, "errorLabels": [] } }, "operation": { "name": "insertMany", "arguments": { "documents": [ { "_id": 2, "x": 22 }, { "_id": 3, "x": 33 } ], "options": { "ordered": true } } }, "outcome": { "error": true, "result": { "errorLabelsOmit": [ "RetryableWriteError" ] }, "collection": { "data": [ { "_id": 1, "x": 11 } ] } } }, { "description": "InsertMany succeeds after PrimarySteppedDown", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "insert" ], "errorCode": 189, "errorLabels": [ "RetryableWriteError" ] } }, "operation": { "name": "insertMany", "arguments": { "documents": [ { "_id": 2, "x": 22 }, { "_id": 3, "x": 33 } ], "options": { "ordered": true } } }, "outcome": { "result": { "insertedIds": { "0": 2, "1": 3 } }, "collection": { "data": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 22 }, { "_id": 3, "x": 33 } ] } } }, { "description": "InsertMany succeeds after WriteConcernError ShutdownInProgress", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "insert" ], "errorLabels": [ "RetryableWriteError" ], "writeConcernError": { "code": 91, "errmsg": "Replication is being shut down" } } }, "operation": { "name": "insertMany", "arguments": { "documents": [ { "_id": 2, "x": 22 }, { "_id": 3, "x": 33 } ], "options": { "ordered": true } } }, "outcome": { "result": { "insertedIds": { "0": 2, "1": 3 } }, "collection": { "data": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 22 }, { "_id": 3, "x": 33 } ] } } } ] } mongodb-mongo-python-driver-509e9b7/test/retryable_writes/legacy/insertMany-serverErrors.json000066400000000000000000000024501462766011000327740ustar00rootroot00000000000000{ "runOn": [ { "minServerVersion": "4.0", "topology": [ "replicaset" ] }, { "minServerVersion": "4.1.7", "topology": [ "sharded", "load-balanced" ] } ], "data": [ { "_id": 1, "x": 11 } ], "tests": [ { "description": "InsertMany fails with a RetryableWriteError label after two connection failures", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 2 }, "data": { "failCommands": [ "insert" ], "closeConnection": true } }, "operation": { "name": "insertMany", "arguments": { "documents": [ { "_id": 2, "x": 22 }, { "_id": 3, "x": 33 } ], "options": { "ordered": true } } }, "outcome": { "error": true, "result": { "errorLabelsContain": [ "RetryableWriteError" ] }, "collection": { "data": [ { "_id": 1, "x": 11 } ] } } } ] } mongodb-mongo-python-driver-509e9b7/test/retryable_writes/legacy/insertMany.json000066400000000000000000000057501462766011000303010ustar00rootroot00000000000000{ "runOn": [ { "minServerVersion": "3.6", "topology": [ "replicaset" ] } ], "data": [ { "_id": 1, "x": 11 } ], "tests": [ { "description": "InsertMany succeeds after one network error", "failPoint": { "configureFailPoint": "onPrimaryTransactionalWrite", "mode": { "times": 1 } }, "operation": { "name": "insertMany", "arguments": { "documents": [ { "_id": 2, "x": 22 }, { "_id": 3, "x": 33 } ], "options": { "ordered": true } } }, "outcome": { "result": { "insertedIds": { "0": 2, "1": 3 } }, "collection": { "data": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 22 }, { "_id": 3, "x": 33 } ] } } }, { "description": "InsertMany with unordered execution", "failPoint": { "configureFailPoint": "onPrimaryTransactionalWrite", "mode": { "times": 1 } }, "operation": { "name": "insertMany", "arguments": { "documents": [ { "_id": 2, "x": 22 }, { "_id": 3, "x": 33 } ], "options": { "ordered": false } } }, "outcome": { "result": { "insertedIds": { "0": 2, "1": 3 } }, "collection": { "data": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 22 }, { "_id": 3, "x": 33 } ] } } }, { "description": "InsertMany fails after multiple network errors", "failPoint": { "configureFailPoint": "onPrimaryTransactionalWrite", "mode": "alwaysOn", "data": { "failBeforeCommitExceptionCode": 1 } }, "operation": { "name": "insertMany", "arguments": { "documents": [ { "_id": 2, "x": 22 }, { "_id": 3, "x": 33 }, { "_id": 4, "x": 44 } ], "options": { "ordered": true } } }, "outcome": { "error": true, "collection": { "data": [ { "_id": 1, "x": 11 } ] } } } ] } mongodb-mongo-python-driver-509e9b7/test/retryable_writes/legacy/insertOne-errorLabels.json000066400000000000000000000376721462766011000324000ustar00rootroot00000000000000{ "runOn": [ { "minServerVersion": "4.3.1", "topology": [ "replicaset", "sharded", "load-balanced" ] } ], "data": [], "tests": [ { "description": "InsertOne succeeds with RetryableWriteError from server", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "insert" ], "errorCode": 112, "errorLabels": [ "RetryableWriteError" ] } }, "operation": { "name": "insertOne", "arguments": { "document": { "_id": 1, "x": 11 } } }, "outcome": { "result": { "insertedId": 1 }, "collection": { "data": [ { "_id": 1, "x": 11 } ] } } }, { "description": "InsertOne fails if server does not return RetryableWriteError", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "insert" ], "errorCode": 11600, "errorLabels": [] } }, "operation": { "name": "insertOne", "arguments": { "document": { "_id": 1, "x": 11 } } }, "outcome": { "error": true, "result": { "errorLabelsOmit": [ "RetryableWriteError" ] }, "collection": { "data": [] } } }, { "description": "InsertOne succeeds after NotWritablePrimary", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "insert" ], "errorCode": 10107, "errorLabels": [ "RetryableWriteError" ], "closeConnection": false } }, "operation": { "name": "insertOne", "arguments": { "document": { "_id": 1, "x": 11 } } }, "outcome": { "result": { "insertedId": 1 }, "collection": { "data": [ { "_id": 1, "x": 11 } ] } } }, { "description": "InsertOne succeeds after NotPrimaryOrSecondary", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "insert" ], "errorCode": 13436, "errorLabels": [ "RetryableWriteError" ], "closeConnection": false } }, "operation": { "name": "insertOne", "arguments": { "document": { "_id": 1, "x": 11 } } }, "outcome": { "result": { "insertedId": 1 }, "collection": { "data": [ { "_id": 1, "x": 11 } ] } } }, { "description": "InsertOne succeeds after NotPrimaryNoSecondaryOk", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "insert" ], "errorCode": 13435, "errorLabels": [ "RetryableWriteError" ], "closeConnection": false } }, "operation": { "name": "insertOne", "arguments": { "document": { "_id": 1, "x": 11 } } }, "outcome": { "result": { "insertedId": 1 }, "collection": { "data": [ { "_id": 1, "x": 11 } ] } } }, { "description": "InsertOne succeeds after InterruptedDueToReplStateChange", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "insert" ], "errorCode": 11602, "errorLabels": [ "RetryableWriteError" ], "closeConnection": false } }, "operation": { "name": "insertOne", "arguments": { "document": { "_id": 1, "x": 11 } } }, "outcome": { "result": { "insertedId": 1 }, "collection": { "data": [ { "_id": 1, "x": 11 } ] } } }, { "description": "InsertOne succeeds after InterruptedAtShutdown", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "insert" ], "errorCode": 11600, "errorLabels": [ "RetryableWriteError" ], "closeConnection": false } }, "operation": { "name": "insertOne", "arguments": { "document": { "_id": 1, "x": 11 } } }, "outcome": { "result": { "insertedId": 1 }, "collection": { "data": [ { "_id": 1, "x": 11 } ] } } }, { "description": "InsertOne succeeds after PrimarySteppedDown", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "insert" ], "errorCode": 189, "errorLabels": [ "RetryableWriteError" ], "closeConnection": false } }, "operation": { "name": "insertOne", "arguments": { "document": { "_id": 1, "x": 11 } } }, "outcome": { "result": { "insertedId": 1 }, "collection": { "data": [ { "_id": 1, "x": 11 } ] } } }, { "description": "InsertOne succeeds after ShutdownInProgress", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "insert" ], "errorCode": 91, "errorLabels": [ "RetryableWriteError" ], "closeConnection": false } }, "operation": { "name": "insertOne", "arguments": { "document": { "_id": 1, "x": 11 } } }, "outcome": { "result": { "insertedId": 1 }, "collection": { "data": [ { "_id": 1, "x": 11 } ] } } }, { "description": "InsertOne succeeds after HostNotFound", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "insert" ], "errorCode": 7, "errorLabels": [ "RetryableWriteError" ], "closeConnection": false } }, "operation": { "name": "insertOne", "arguments": { "document": { "_id": 1, "x": 11 } } }, "outcome": { "result": { "insertedId": 1 }, "collection": { "data": [ { "_id": 1, "x": 11 } ] } } }, { "description": "InsertOne succeeds after HostUnreachable", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "insert" ], "errorCode": 6, "errorLabels": [ "RetryableWriteError" ], "closeConnection": false } }, "operation": { "name": "insertOne", "arguments": { "document": { "_id": 1, "x": 11 } } }, "outcome": { "result": { "insertedId": 1 }, "collection": { "data": [ { "_id": 1, "x": 11 } ] } } }, { "description": "InsertOne succeeds after SocketException", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "insert" ], "errorCode": 9001, "errorLabels": [ "RetryableWriteError" ], "closeConnection": false } }, "operation": { "name": "insertOne", "arguments": { "document": { "_id": 1, "x": 11 } } }, "outcome": { "result": { "insertedId": 1 }, "collection": { "data": [ { "_id": 1, "x": 11 } ] } } }, { "description": "InsertOne succeeds after NetworkTimeout", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "insert" ], "errorCode": 89, "errorLabels": [ "RetryableWriteError" ], "closeConnection": false } }, "operation": { "name": "insertOne", "arguments": { "document": { "_id": 1, "x": 11 } } }, "outcome": { "result": { "insertedId": 1 }, "collection": { "data": [ { "_id": 1, "x": 11 } ] } } }, { "description": "InsertOne succeeds after ExceededTimeLimit", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "insert" ], "errorCode": 262, "errorLabels": [ "RetryableWriteError" ], "closeConnection": false } }, "operation": { "name": "insertOne", "arguments": { "document": { "_id": 1, "x": 11 } } }, "outcome": { "result": { "insertedId": 1 }, "collection": { "data": [ { "_id": 1, "x": 11 } ] } } }, { "description": "InsertOne succeeds after WriteConcernError InterruptedAtShutdown", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "insert" ], "errorLabels": [ "RetryableWriteError" ], "writeConcernError": { "code": 11600, "errmsg": "Replication is being shut down" } } }, "operation": { "name": "insertOne", "arguments": { "document": { "_id": 1, "x": 11 } } }, "outcome": { "result": { "insertedId": 1 }, "collection": { "data": [ { "_id": 1, "x": 11 } ] } } }, { "description": "InsertOne succeeds after WriteConcernError InterruptedDueToReplStateChange", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "insert" ], "errorLabels": [ "RetryableWriteError" ], "writeConcernError": { "code": 11602, "errmsg": "Replication is being shut down" } } }, "operation": { "name": "insertOne", "arguments": { "document": { "_id": 1, "x": 11 } } }, "outcome": { "result": { "insertedId": 1 }, "collection": { "data": [ { "_id": 1, "x": 11 } ] } } }, { "description": "InsertOne succeeds after WriteConcernError PrimarySteppedDown", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "insert" ], "errorLabels": [ "RetryableWriteError" ], "writeConcernError": { "code": 189, "errmsg": "Replication is being shut down" } } }, "operation": { "name": "insertOne", "arguments": { "document": { "_id": 1, "x": 11 } } }, "outcome": { "result": { "insertedId": 1 }, "collection": { "data": [ { "_id": 1, "x": 11 } ] } } }, { "description": "InsertOne succeeds after WriteConcernError ShutdownInProgress", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "insert" ], "errorLabels": [ "RetryableWriteError" ], "writeConcernError": { "code": 91, "errmsg": "Replication is being shut down" } } }, "operation": { "name": "insertOne", "arguments": { "document": { "_id": 1, "x": 11 } } }, "outcome": { "result": { "insertedId": 1 }, "collection": { "data": [ { "_id": 1, "x": 11 } ] } } }, { "description": "InsertOne fails after multiple retryable writeConcernErrors", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 2 }, "data": { "failCommands": [ "insert" ], "errorLabels": [ "RetryableWriteError" ], "writeConcernError": { "code": 91, "errmsg": "Replication is being shut down" } } }, "operation": { "name": "insertOne", "arguments": { "document": { "_id": 1, "x": 11 } } }, "outcome": { "error": true, "result": { "errorLabelsContain": [ "RetryableWriteError" ] }, "collection": { "data": [ { "_id": 1, "x": 11 } ] } } } ] } mongodb-mongo-python-driver-509e9b7/test/retryable_writes/legacy/insertOne-serverErrors.json000066400000000000000000000141071462766011000326130ustar00rootroot00000000000000{ "runOn": [ { "minServerVersion": "4.0", "topology": [ "replicaset" ] }, { "minServerVersion": "4.1.7", "topology": [ "sharded", "load-balanced" ] } ], "data": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 22 } ], "tests": [ { "description": "InsertOne succeeds after connection failure", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "insert" ], "closeConnection": true } }, "operation": { "name": "insertOne", "arguments": { "document": { "_id": 3, "x": 33 } } }, "outcome": { "result": { "insertedId": 3 }, "collection": { "data": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 22 }, { "_id": 3, "x": 33 } ] } } }, { "description": "InsertOne fails after connection failure when retryWrites option is false", "clientOptions": { "retryWrites": false }, "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "insert" ], "closeConnection": true } }, "operation": { "name": "insertOne", "arguments": { "document": { "_id": 3, "x": 33 } } }, "outcome": { "error": true, "result": { "errorLabelsOmit": [ "RetryableWriteError" ] }, "collection": { "data": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 22 } ] } } }, { "description": "InsertOne fails after Interrupted", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "insert" ], "errorCode": 11601, "closeConnection": false } }, "operation": { "name": "insertOne", "arguments": { "document": { "_id": 3, "x": 33 } } }, "outcome": { "error": true, "result": { "errorLabelsOmit": [ "RetryableWriteError" ] }, "collection": { "data": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 22 } ] } } }, { "description": "InsertOne fails after WriteConcernError Interrupted", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "insert" ], "writeConcernError": { "code": 11601, "errmsg": "operation was interrupted" } } }, "operation": { "name": "insertOne", "arguments": { "document": { "_id": 3, "x": 33 } } }, "outcome": { "error": true, "result": { "errorLabelsOmit": [ "RetryableWriteError" ] }, "collection": { "data": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 22 }, { "_id": 3, "x": 33 } ] } } }, { "description": "InsertOne fails after WriteConcernError WriteConcernFailed", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "insert" ], "writeConcernError": { "code": 64, "codeName": "WriteConcernFailed", "errmsg": "waiting for replication timed out", "errInfo": { "wtimeout": true } } } }, "operation": { "name": "insertOne", "arguments": { "document": { "_id": 3, "x": 33 } } }, "outcome": { "error": true, "result": { "errorLabelsOmit": [ "RetryableWriteError" ] }, "collection": { "data": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 22 }, { "_id": 3, "x": 33 } ] } } }, { "description": "InsertOne fails with a RetryableWriteError label after two connection failures", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 2 }, "data": { "failCommands": [ "insert" ], "closeConnection": true } }, "operation": { "name": "insertOne", "arguments": { "document": { "_id": 3, "x": 33 } } }, "outcome": { "error": true, "result": { "errorLabelsContain": [ "RetryableWriteError" ] }, "collection": { "data": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 22 } ] } } } ] } mongodb-mongo-python-driver-509e9b7/test/retryable_writes/legacy/insertOne.json000066400000000000000000000047651462766011000301230ustar00rootroot00000000000000{ "runOn": [ { "minServerVersion": "3.6", "topology": [ "replicaset" ] } ], "data": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 22 } ], "tests": [ { "description": "InsertOne is committed on first attempt", "failPoint": { "configureFailPoint": "onPrimaryTransactionalWrite", "mode": { "times": 1 } }, "operation": { "name": "insertOne", "arguments": { "document": { "_id": 3, "x": 33 } } }, "outcome": { "result": { "insertedId": 3 }, "collection": { "data": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 22 }, { "_id": 3, "x": 33 } ] } } }, { "description": "InsertOne is not committed on first attempt", "failPoint": { "configureFailPoint": "onPrimaryTransactionalWrite", "mode": { "times": 1 }, "data": { "failBeforeCommitExceptionCode": 1 } }, "operation": { "name": "insertOne", "arguments": { "document": { "_id": 3, "x": 33 } } }, "outcome": { "result": { "insertedId": 3 }, "collection": { "data": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 22 }, { "_id": 3, "x": 33 } ] } } }, { "description": "InsertOne is never committed", "failPoint": { "configureFailPoint": "onPrimaryTransactionalWrite", "mode": { "times": 2 }, "data": { "failBeforeCommitExceptionCode": 1 } }, "operation": { "name": "insertOne", "arguments": { "document": { "_id": 3, "x": 33 } } }, "outcome": { "error": true, "collection": { "data": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 22 } ] } } } ] } mongodb-mongo-python-driver-509e9b7/test/retryable_writes/legacy/replaceOne-errorLabels.json000066400000000000000000000104051462766011000324700ustar00rootroot00000000000000{ "runOn": [ { "minServerVersion": "4.3.1", "topology": [ "replicaset", "sharded", "load-balanced" ] } ], "data": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 22 } ], "tests": [ { "description": "ReplaceOne succeeds with RetryableWriteError from server", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "update" ], "errorCode": 112, "errorLabels": [ "RetryableWriteError" ] } }, "operation": { "name": "replaceOne", "arguments": { "filter": { "_id": 1 }, "replacement": { "_id": 1, "x": 111 } } }, "outcome": { "result": { "matchedCount": 1, "modifiedCount": 1, "upsertedCount": 0 }, "collection": { "data": [ { "_id": 1, "x": 111 }, { "_id": 2, "x": 22 } ] } } }, { "description": "ReplaceOne fails if server does not return RetryableWriteError", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "update" ], "errorCode": 11600, "errorLabels": [] } }, "operation": { "name": "replaceOne", "arguments": { "filter": { "_id": 1 }, "replacement": { "_id": 1, "x": 111 } } }, "outcome": { "error": true, "result": { "errorLabelsOmit": [ "RetryableWriteError" ] }, "collection": { "data": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 22 } ] } } }, { "description": "ReplaceOne succeeds after PrimarySteppedDown", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "update" ], "errorCode": 189, "errorLabels": [ "RetryableWriteError" ] } }, "operation": { "name": "replaceOne", "arguments": { "filter": { "_id": 1 }, "replacement": { "_id": 1, "x": 111 } } }, "outcome": { "result": { "matchedCount": 1, "modifiedCount": 1, "upsertedCount": 0 }, "collection": { "data": [ { "_id": 1, "x": 111 }, { "_id": 2, "x": 22 } ] } } }, { "description": "ReplaceOne succeeds after WriteConcernError ShutdownInProgress", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "update" ], "errorLabels": [ "RetryableWriteError" ], "writeConcernError": { "code": 91, "errmsg": "Replication is being shut down" } } }, "operation": { "name": "replaceOne", "arguments": { "filter": { "_id": 1 }, "replacement": { "_id": 1, "x": 111 } } }, "outcome": { "result": { "matchedCount": 1, "modifiedCount": 1, "upsertedCount": 0 }, "collection": { "data": [ { "_id": 1, "x": 111 }, { "_id": 2, "x": 22 } ] } } } ] } mongodb-mongo-python-driver-509e9b7/test/retryable_writes/legacy/replaceOne-serverErrors.json000066400000000000000000000024561462766011000327260ustar00rootroot00000000000000{ "runOn": [ { "minServerVersion": "4.0", "topology": [ "replicaset" ] }, { "minServerVersion": "4.1.7", "topology": [ "sharded", "load-balanced" ] } ], "data": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 22 } ], "tests": [ { "description": "ReplaceOne fails with a RetryableWriteError label after two connection failures", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 2 }, "data": { "failCommands": [ "update" ], "closeConnection": true } }, "operation": { "name": "replaceOne", "arguments": { "filter": { "_id": 1 }, "replacement": { "_id": 1, "x": 111 } } }, "outcome": { "error": true, "result": { "errorLabelsContain": [ "RetryableWriteError" ] }, "collection": { "data": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 22 } ] } } } ] } mongodb-mongo-python-driver-509e9b7/test/retryable_writes/legacy/replaceOne.json000066400000000000000000000052271462766011000302240ustar00rootroot00000000000000{ "runOn": [ { "minServerVersion": "3.6", "topology": [ "replicaset" ] } ], "data": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 22 } ], "tests": [ { "description": "ReplaceOne is committed on first attempt", "failPoint": { "configureFailPoint": "onPrimaryTransactionalWrite", "mode": { "times": 1 } }, "operation": { "name": "replaceOne", "arguments": { "filter": { "_id": 1 }, "replacement": { "_id": 1, "x": 111 } } }, "outcome": { "result": { "matchedCount": 1, "modifiedCount": 1, "upsertedCount": 0 }, "collection": { "data": [ { "_id": 1, "x": 111 }, { "_id": 2, "x": 22 } ] } } }, { "description": "ReplaceOne is not committed on first attempt", "failPoint": { "configureFailPoint": "onPrimaryTransactionalWrite", "mode": { "times": 1 }, "data": { "failBeforeCommitExceptionCode": 1 } }, "operation": { "name": "replaceOne", "arguments": { "filter": { "_id": 1 }, "replacement": { "_id": 1, "x": 111 } } }, "outcome": { "result": { "matchedCount": 1, "modifiedCount": 1, "upsertedCount": 0 }, "collection": { "data": [ { "_id": 1, "x": 111 }, { "_id": 2, "x": 22 } ] } } }, { "description": "ReplaceOne is never committed", "failPoint": { "configureFailPoint": "onPrimaryTransactionalWrite", "mode": { "times": 2 }, "data": { "failBeforeCommitExceptionCode": 1 } }, "operation": { "name": "replaceOne", "arguments": { "filter": { "_id": 1 }, "replacement": { "_id": 1, "x": 111 } } }, "outcome": { "error": true, "collection": { "data": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 22 } ] } } } ] } mongodb-mongo-python-driver-509e9b7/test/retryable_writes/legacy/updateMany.json000066400000000000000000000016661462766011000302610ustar00rootroot00000000000000{ "runOn": [ { "minServerVersion": "3.6", "topology": [ "replicaset", "sharded", "load-balanced" ] } ], "data": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 22 } ], "tests": [ { "description": "UpdateMany ignores retryWrites", "useMultipleMongoses": true, "operation": { "name": "updateMany", "arguments": { "filter": {}, "update": { "$inc": { "x": 1 } } } }, "outcome": { "result": { "matchedCount": 2, "modifiedCount": 2, "upsertedCount": 0 }, "collection": { "data": [ { "_id": 1, "x": 12 }, { "_id": 2, "x": 23 } ] } } } ] } mongodb-mongo-python-driver-509e9b7/test/retryable_writes/legacy/updateOne-errorLabels.json000066400000000000000000000104361462766011000323430ustar00rootroot00000000000000{ "runOn": [ { "minServerVersion": "4.3.1", "topology": [ "replicaset", "sharded", "load-balanced" ] } ], "data": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 22 } ], "tests": [ { "description": "UpdateOne succeeds with RetryableWriteError from server", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "update" ], "errorCode": 112, "errorLabels": [ "RetryableWriteError" ] } }, "operation": { "name": "updateOne", "arguments": { "filter": { "_id": 1 }, "update": { "$inc": { "x": 1 } } } }, "outcome": { "result": { "matchedCount": 1, "modifiedCount": 1, "upsertedCount": 0 }, "collection": { "data": [ { "_id": 1, "x": 12 }, { "_id": 2, "x": 22 } ] } } }, { "description": "UpdateOne fails if server does not return RetryableWriteError", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "update" ], "errorCode": 11600, "errorLabels": [] } }, "operation": { "name": "updateOne", "arguments": { "filter": { "_id": 1 }, "update": { "$inc": { "x": 1 } } } }, "outcome": { "error": true, "result": { "errorLabelsOmit": [ "RetryableWriteError" ] }, "collection": { "data": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 22 } ] } } }, { "description": "UpdateOne succeeds after PrimarySteppedDown", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "update" ], "errorCode": 189, "errorLabels": [ "RetryableWriteError" ] } }, "operation": { "name": "updateOne", "arguments": { "filter": { "_id": 1 }, "update": { "$inc": { "x": 1 } } } }, "outcome": { "result": { "matchedCount": 1, "modifiedCount": 1, "upsertedCount": 0 }, "collection": { "data": [ { "_id": 1, "x": 12 }, { "_id": 2, "x": 22 } ] } } }, { "description": "UpdateOne succeeds after WriteConcernError ShutdownInProgress", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "update" ], "errorLabels": [ "RetryableWriteError" ], "writeConcernError": { "code": 91, "errmsg": "Replication is being shut down" } } }, "operation": { "name": "updateOne", "arguments": { "filter": { "_id": 1 }, "update": { "$inc": { "x": 1 } } } }, "outcome": { "result": { "matchedCount": 1, "modifiedCount": 1, "upsertedCount": 0 }, "collection": { "data": [ { "_id": 1, "x": 12 }, { "_id": 2, "x": 22 } ] } } } ] } mongodb-mongo-python-driver-509e9b7/test/retryable_writes/legacy/updateOne-serverErrors.json000066400000000000000000000024651462766011000325750ustar00rootroot00000000000000{ "runOn": [ { "minServerVersion": "4.0", "topology": [ "replicaset" ] }, { "minServerVersion": "4.1.7", "topology": [ "sharded", "load-balanced" ] } ], "data": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 22 } ], "tests": [ { "description": "UpdateOne fails with a RetryableWriteError label after two connection failures", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 2 }, "data": { "failCommands": [ "update" ], "closeConnection": true } }, "operation": { "name": "updateOne", "arguments": { "filter": { "_id": 1 }, "update": { "$inc": { "x": 1 } } } }, "outcome": { "error": true, "result": { "errorLabelsContain": [ "RetryableWriteError" ] }, "collection": { "data": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 22 } ] } } } ] } mongodb-mongo-python-driver-509e9b7/test/retryable_writes/legacy/updateOne.json000066400000000000000000000127471462766011000301000ustar00rootroot00000000000000{ "runOn": [ { "minServerVersion": "3.6", "topology": [ "replicaset" ] } ], "data": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 22 } ], "tests": [ { "description": "UpdateOne is committed on first attempt", "failPoint": { "configureFailPoint": "onPrimaryTransactionalWrite", "mode": { "times": 1 } }, "operation": { "name": "updateOne", "arguments": { "filter": { "_id": 1 }, "update": { "$inc": { "x": 1 } } } }, "outcome": { "result": { "matchedCount": 1, "modifiedCount": 1, "upsertedCount": 0 }, "collection": { "data": [ { "_id": 1, "x": 12 }, { "_id": 2, "x": 22 } ] } } }, { "description": "UpdateOne is not committed on first attempt", "failPoint": { "configureFailPoint": "onPrimaryTransactionalWrite", "mode": { "times": 1 }, "data": { "failBeforeCommitExceptionCode": 1 } }, "operation": { "name": "updateOne", "arguments": { "filter": { "_id": 1 }, "update": { "$inc": { "x": 1 } } } }, "outcome": { "result": { "matchedCount": 1, "modifiedCount": 1, "upsertedCount": 0 }, "collection": { "data": [ { "_id": 1, "x": 12 }, { "_id": 2, "x": 22 } ] } } }, { "description": "UpdateOne is never committed", "failPoint": { "configureFailPoint": "onPrimaryTransactionalWrite", "mode": { "times": 2 }, "data": { "failBeforeCommitExceptionCode": 1 } }, "operation": { "name": "updateOne", "arguments": { "filter": { "_id": 1 }, "update": { "$inc": { "x": 1 } } } }, "outcome": { "error": true, "collection": { "data": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 22 } ] } } }, { "description": "UpdateOne with upsert is committed on first attempt", "failPoint": { "configureFailPoint": "onPrimaryTransactionalWrite", "mode": { "times": 1 } }, "operation": { "name": "updateOne", "arguments": { "filter": { "_id": 3, "x": 33 }, "update": { "$inc": { "x": 1 } }, "upsert": true } }, "outcome": { "result": { "matchedCount": 0, "modifiedCount": 0, "upsertedCount": 1, "upsertedId": 3 }, "collection": { "data": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 22 }, { "_id": 3, "x": 34 } ] } } }, { "description": "UpdateOne with upsert is not committed on first attempt", "failPoint": { "configureFailPoint": "onPrimaryTransactionalWrite", "mode": { "times": 1 }, "data": { "failBeforeCommitExceptionCode": 1 } }, "operation": { "name": "updateOne", "arguments": { "filter": { "_id": 3, "x": 33 }, "update": { "$inc": { "x": 1 } }, "upsert": true } }, "outcome": { "result": { "matchedCount": 0, "modifiedCount": 0, "upsertedCount": 1, "upsertedId": 3 }, "collection": { "data": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 22 }, { "_id": 3, "x": 34 } ] } } }, { "description": "UpdateOne with upsert is never committed", "failPoint": { "configureFailPoint": "onPrimaryTransactionalWrite", "mode": { "times": 2 }, "data": { "failBeforeCommitExceptionCode": 1 } }, "operation": { "name": "updateOne", "arguments": { "filter": { "_id": 3, "x": 33 }, "update": { "$inc": { "x": 1 } }, "upsert": true } }, "outcome": { "error": true, "collection": { "data": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 22 } ] } } } ] } mongodb-mongo-python-driver-509e9b7/test/retryable_writes/unified/000077500000000000000000000000001462766011000254255ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/retryable_writes/unified/bulkWrite-serverErrors.json000066400000000000000000000110031462766011000327640ustar00rootroot00000000000000{ "description": "retryable-writes bulkWrite serverErrors", "schemaVersion": "1.0", "runOnRequirements": [ { "minServerVersion": "4.0", "topologies": [ "replicaset" ] }, { "minServerVersion": "4.1.7", "topologies": [ "sharded" ] } ], "createEntities": [ { "client": { "id": "client0", "useMultipleMongoses": false, "observeEvents": [ "commandStartedEvent" ] } }, { "database": { "id": "database0", "client": "client0", "databaseName": "retryable-writes-tests" } }, { "collection": { "id": "collection0", "database": "database0", "collectionName": "coll" } } ], "initialData": [ { "collectionName": "coll", "databaseName": "retryable-writes-tests", "documents": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 22 } ] } ], "tests": [ { "description": "BulkWrite succeeds after retryable writeConcernError in first batch", "runOnRequirements": [ { "minServerVersion": "4.3.1" } ], "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "client0", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "insert" ], "errorLabels": [ "RetryableWriteError" ], "writeConcernError": { "code": 91, "errmsg": "Replication is being shut down" } } } } }, { "name": "bulkWrite", "object": "collection0", "arguments": { "requests": [ { "insertOne": { "document": { "_id": 3, "x": 33 } } }, { "deleteOne": { "filter": { "_id": 2 } } } ] }, "expectResult": { "deletedCount": 1, "insertedCount": 1, "matchedCount": 0, "modifiedCount": 0, "upsertedCount": 0, "insertedIds": { "$$unsetOrMatches": { "0": 3 } }, "upsertedIds": {} } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "insert": "coll", "documents": [ { "_id": 3, "x": 33 } ] }, "commandName": "insert", "databaseName": "retryable-writes-tests" } }, { "commandStartedEvent": { "command": { "insert": "coll", "documents": [ { "_id": 3, "x": 33 } ] }, "commandName": "insert", "databaseName": "retryable-writes-tests" } }, { "commandStartedEvent": { "command": { "delete": "coll", "deletes": [ { "q": { "_id": 2 }, "limit": 1 } ] }, "commandName": "delete", "databaseName": "retryable-writes-tests" } } ] } ], "outcome": [ { "collectionName": "coll", "databaseName": "retryable-writes-tests", "documents": [ { "_id": 1, "x": 11 }, { "_id": 3, "x": 33 } ] } ] } ] } mongodb-mongo-python-driver-509e9b7/test/retryable_writes/unified/handshakeError.json000066400000000000000000001237341462766011000312720ustar00rootroot00000000000000{ "description": "retryable writes handshake failures", "schemaVersion": "1.3", "runOnRequirements": [ { "minServerVersion": "4.2", "topologies": [ "replicaset", "sharded", "load-balanced" ], "auth": true } ], "createEntities": [ { "client": { "id": "client", "useMultipleMongoses": false, "observeEvents": [ "connectionCheckOutStartedEvent", "commandStartedEvent", "commandSucceededEvent", "commandFailedEvent" ] } }, { "database": { "id": "database", "client": "client", "databaseName": "retryable-writes-handshake-tests" } }, { "collection": { "id": "collection", "database": "database", "collectionName": "coll" } } ], "initialData": [ { "collectionName": "coll", "databaseName": "retryable-writes-handshake-tests", "documents": [ { "_id": 1, "x": 11 } ] } ], "tests": [ { "description": "collection.insertOne succeeds after retryable handshake network error", "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "client", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 2 }, "data": { "failCommands": [ "ping", "saslContinue" ], "closeConnection": true } } } }, { "name": "runCommand", "object": "database", "arguments": { "commandName": "ping", "command": { "ping": 1 } }, "expectError": { "isError": true } }, { "name": "insertOne", "object": "collection", "arguments": { "document": { "_id": 2, "x": 22 } } } ], "expectEvents": [ { "client": "client", "eventType": "cmap", "events": [ { "connectionCheckOutStartedEvent": {} }, { "connectionCheckOutStartedEvent": {} }, { "connectionCheckOutStartedEvent": {} }, { "connectionCheckOutStartedEvent": {} } ] }, { "client": "client", "events": [ { "commandStartedEvent": { "command": { "ping": 1 }, "databaseName": "retryable-writes-handshake-tests" } }, { "commandFailedEvent": { "commandName": "ping" } }, { "commandStartedEvent": { "commandName": "insert" } }, { "commandSucceededEvent": { "commandName": "insert" } } ] } ] }, { "description": "collection.insertOne succeeds after retryable handshake server error (ShutdownInProgress)", "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "client", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 2 }, "data": { "failCommands": [ "ping", "saslContinue" ], "closeConnection": true } } } }, { "name": "runCommand", "object": "database", "arguments": { "commandName": "ping", "command": { "ping": 1 } }, "expectError": { "isError": true } }, { "name": "insertOne", "object": "collection", "arguments": { "document": { "_id": 2, "x": 22 } } } ], "expectEvents": [ { "client": "client", "eventType": "cmap", "events": [ { "connectionCheckOutStartedEvent": {} }, { "connectionCheckOutStartedEvent": {} }, { "connectionCheckOutStartedEvent": {} }, { "connectionCheckOutStartedEvent": {} } ] }, { "client": "client", "events": [ { "commandStartedEvent": { "command": { "ping": 1 }, "databaseName": "retryable-writes-handshake-tests" } }, { "commandFailedEvent": { "commandName": "ping" } }, { "commandStartedEvent": { "commandName": "insert" } }, { "commandSucceededEvent": { "commandName": "insert" } } ] } ] }, { "description": "collection.insertMany succeeds after retryable handshake network error", "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "client", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 2 }, "data": { "failCommands": [ "ping", "saslContinue" ], "closeConnection": true } } } }, { "name": "runCommand", "object": "database", "arguments": { "commandName": "ping", "command": { "ping": 1 } }, "expectError": { "isError": true } }, { "name": "insertMany", "object": "collection", "arguments": { "documents": [ { "_id": 2, "x": 22 } ] } } ], "expectEvents": [ { "client": "client", "eventType": "cmap", "events": [ { "connectionCheckOutStartedEvent": {} }, { "connectionCheckOutStartedEvent": {} }, { "connectionCheckOutStartedEvent": {} }, { "connectionCheckOutStartedEvent": {} } ] }, { "client": "client", "events": [ { "commandStartedEvent": { "command": { "ping": 1 }, "databaseName": "retryable-writes-handshake-tests" } }, { "commandFailedEvent": { "commandName": "ping" } }, { "commandStartedEvent": { "commandName": "insert" } }, { "commandSucceededEvent": { "commandName": "insert" } } ] } ] }, { "description": "collection.insertMany succeeds after retryable handshake server error (ShutdownInProgress)", "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "client", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 2 }, "data": { "failCommands": [ "ping", "saslContinue" ], "closeConnection": true } } } }, { "name": "runCommand", "object": "database", "arguments": { "commandName": "ping", "command": { "ping": 1 } }, "expectError": { "isError": true } }, { "name": "insertMany", "object": "collection", "arguments": { "documents": [ { "_id": 2, "x": 22 } ] } } ], "expectEvents": [ { "client": "client", "eventType": "cmap", "events": [ { "connectionCheckOutStartedEvent": {} }, { "connectionCheckOutStartedEvent": {} }, { "connectionCheckOutStartedEvent": {} }, { "connectionCheckOutStartedEvent": {} } ] }, { "client": "client", "events": [ { "commandStartedEvent": { "command": { "ping": 1 }, "databaseName": "retryable-writes-handshake-tests" } }, { "commandFailedEvent": { "commandName": "ping" } }, { "commandStartedEvent": { "commandName": "insert" } }, { "commandSucceededEvent": { "commandName": "insert" } } ] } ] }, { "description": "collection.deleteOne succeeds after retryable handshake network error", "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "client", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 2 }, "data": { "failCommands": [ "ping", "saslContinue" ], "closeConnection": true } } } }, { "name": "runCommand", "object": "database", "arguments": { "commandName": "ping", "command": { "ping": 1 } }, "expectError": { "isError": true } }, { "name": "deleteOne", "object": "collection", "arguments": { "filter": {} } } ], "expectEvents": [ { "client": "client", "eventType": "cmap", "events": [ { "connectionCheckOutStartedEvent": {} }, { "connectionCheckOutStartedEvent": {} }, { "connectionCheckOutStartedEvent": {} }, { "connectionCheckOutStartedEvent": {} } ] }, { "client": "client", "events": [ { "commandStartedEvent": { "command": { "ping": 1 }, "databaseName": "retryable-writes-handshake-tests" } }, { "commandFailedEvent": { "commandName": "ping" } }, { "commandStartedEvent": { "commandName": "delete" } }, { "commandSucceededEvent": { "commandName": "delete" } } ] } ] }, { "description": "collection.deleteOne succeeds after retryable handshake server error (ShutdownInProgress)", "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "client", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 2 }, "data": { "failCommands": [ "ping", "saslContinue" ], "closeConnection": true } } } }, { "name": "runCommand", "object": "database", "arguments": { "commandName": "ping", "command": { "ping": 1 } }, "expectError": { "isError": true } }, { "name": "deleteOne", "object": "collection", "arguments": { "filter": {} } } ], "expectEvents": [ { "client": "client", "eventType": "cmap", "events": [ { "connectionCheckOutStartedEvent": {} }, { "connectionCheckOutStartedEvent": {} }, { "connectionCheckOutStartedEvent": {} }, { "connectionCheckOutStartedEvent": {} } ] }, { "client": "client", "events": [ { "commandStartedEvent": { "command": { "ping": 1 }, "databaseName": "retryable-writes-handshake-tests" } }, { "commandFailedEvent": { "commandName": "ping" } }, { "commandStartedEvent": { "commandName": "delete" } }, { "commandSucceededEvent": { "commandName": "delete" } } ] } ] }, { "description": "collection.replaceOne succeeds after retryable handshake network error", "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "client", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 2 }, "data": { "failCommands": [ "ping", "saslContinue" ], "closeConnection": true } } } }, { "name": "runCommand", "object": "database", "arguments": { "commandName": "ping", "command": { "ping": 1 } }, "expectError": { "isError": true } }, { "name": "replaceOne", "object": "collection", "arguments": { "filter": {}, "replacement": { "x": 22 } } } ], "expectEvents": [ { "client": "client", "eventType": "cmap", "events": [ { "connectionCheckOutStartedEvent": {} }, { "connectionCheckOutStartedEvent": {} }, { "connectionCheckOutStartedEvent": {} }, { "connectionCheckOutStartedEvent": {} } ] }, { "client": "client", "events": [ { "commandStartedEvent": { "command": { "ping": 1 }, "databaseName": "retryable-writes-handshake-tests" } }, { "commandFailedEvent": { "commandName": "ping" } }, { "commandStartedEvent": { "commandName": "update" } }, { "commandSucceededEvent": { "commandName": "update" } } ] } ] }, { "description": "collection.replaceOne succeeds after retryable handshake server error (ShutdownInProgress)", "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "client", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 2 }, "data": { "failCommands": [ "ping", "saslContinue" ], "closeConnection": true } } } }, { "name": "runCommand", "object": "database", "arguments": { "commandName": "ping", "command": { "ping": 1 } }, "expectError": { "isError": true } }, { "name": "replaceOne", "object": "collection", "arguments": { "filter": {}, "replacement": { "x": 22 } } } ], "expectEvents": [ { "client": "client", "eventType": "cmap", "events": [ { "connectionCheckOutStartedEvent": {} }, { "connectionCheckOutStartedEvent": {} }, { "connectionCheckOutStartedEvent": {} }, { "connectionCheckOutStartedEvent": {} } ] }, { "client": "client", "events": [ { "commandStartedEvent": { "command": { "ping": 1 }, "databaseName": "retryable-writes-handshake-tests" } }, { "commandFailedEvent": { "commandName": "ping" } }, { "commandStartedEvent": { "commandName": "update" } }, { "commandSucceededEvent": { "commandName": "update" } } ] } ] }, { "description": "collection.updateOne succeeds after retryable handshake network error", "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "client", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 2 }, "data": { "failCommands": [ "ping", "saslContinue" ], "closeConnection": true } } } }, { "name": "runCommand", "object": "database", "arguments": { "commandName": "ping", "command": { "ping": 1 } }, "expectError": { "isError": true } }, { "name": "updateOne", "object": "collection", "arguments": { "filter": {}, "update": { "$set": { "x": 22 } } } } ], "expectEvents": [ { "client": "client", "eventType": "cmap", "events": [ { "connectionCheckOutStartedEvent": {} }, { "connectionCheckOutStartedEvent": {} }, { "connectionCheckOutStartedEvent": {} }, { "connectionCheckOutStartedEvent": {} } ] }, { "client": "client", "events": [ { "commandStartedEvent": { "command": { "ping": 1 }, "databaseName": "retryable-writes-handshake-tests" } }, { "commandFailedEvent": { "commandName": "ping" } }, { "commandStartedEvent": { "commandName": "update" } }, { "commandSucceededEvent": { "commandName": "update" } } ] } ] }, { "description": "collection.updateOne succeeds after retryable handshake server error (ShutdownInProgress)", "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "client", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 2 }, "data": { "failCommands": [ "ping", "saslContinue" ], "closeConnection": true } } } }, { "name": "runCommand", "object": "database", "arguments": { "commandName": "ping", "command": { "ping": 1 } }, "expectError": { "isError": true } }, { "name": "updateOne", "object": "collection", "arguments": { "filter": {}, "update": { "$set": { "x": 22 } } } } ], "expectEvents": [ { "client": "client", "eventType": "cmap", "events": [ { "connectionCheckOutStartedEvent": {} }, { "connectionCheckOutStartedEvent": {} }, { "connectionCheckOutStartedEvent": {} }, { "connectionCheckOutStartedEvent": {} } ] }, { "client": "client", "events": [ { "commandStartedEvent": { "command": { "ping": 1 }, "databaseName": "retryable-writes-handshake-tests" } }, { "commandFailedEvent": { "commandName": "ping" } }, { "commandStartedEvent": { "commandName": "update" } }, { "commandSucceededEvent": { "commandName": "update" } } ] } ] }, { "description": "collection.findOneAndDelete succeeds after retryable handshake network error", "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "client", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 2 }, "data": { "failCommands": [ "ping", "saslContinue" ], "closeConnection": true } } } }, { "name": "runCommand", "object": "database", "arguments": { "commandName": "ping", "command": { "ping": 1 } }, "expectError": { "isError": true } }, { "name": "findOneAndDelete", "object": "collection", "arguments": { "filter": {} } } ], "expectEvents": [ { "client": "client", "eventType": "cmap", "events": [ { "connectionCheckOutStartedEvent": {} }, { "connectionCheckOutStartedEvent": {} }, { "connectionCheckOutStartedEvent": {} }, { "connectionCheckOutStartedEvent": {} } ] }, { "client": "client", "events": [ { "commandStartedEvent": { "command": { "ping": 1 }, "databaseName": "retryable-writes-handshake-tests" } }, { "commandFailedEvent": { "commandName": "ping" } }, { "commandStartedEvent": { "commandName": "findAndModify" } }, { "commandSucceededEvent": { "commandName": "findAndModify" } } ] } ] }, { "description": "collection.findOneAndDelete succeeds after retryable handshake server error (ShutdownInProgress)", "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "client", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 2 }, "data": { "failCommands": [ "ping", "saslContinue" ], "closeConnection": true } } } }, { "name": "runCommand", "object": "database", "arguments": { "commandName": "ping", "command": { "ping": 1 } }, "expectError": { "isError": true } }, { "name": "findOneAndDelete", "object": "collection", "arguments": { "filter": {} } } ], "expectEvents": [ { "client": "client", "eventType": "cmap", "events": [ { "connectionCheckOutStartedEvent": {} }, { "connectionCheckOutStartedEvent": {} }, { "connectionCheckOutStartedEvent": {} }, { "connectionCheckOutStartedEvent": {} } ] }, { "client": "client", "events": [ { "commandStartedEvent": { "command": { "ping": 1 }, "databaseName": "retryable-writes-handshake-tests" } }, { "commandFailedEvent": { "commandName": "ping" } }, { "commandStartedEvent": { "commandName": "findAndModify" } }, { "commandSucceededEvent": { "commandName": "findAndModify" } } ] } ] }, { "description": "collection.findOneAndReplace succeeds after retryable handshake network error", "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "client", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 2 }, "data": { "failCommands": [ "ping", "saslContinue" ], "closeConnection": true } } } }, { "name": "runCommand", "object": "database", "arguments": { "commandName": "ping", "command": { "ping": 1 } }, "expectError": { "isError": true } }, { "name": "findOneAndReplace", "object": "collection", "arguments": { "filter": {}, "replacement": { "x": 22 } } } ], "expectEvents": [ { "client": "client", "eventType": "cmap", "events": [ { "connectionCheckOutStartedEvent": {} }, { "connectionCheckOutStartedEvent": {} }, { "connectionCheckOutStartedEvent": {} }, { "connectionCheckOutStartedEvent": {} } ] }, { "client": "client", "events": [ { "commandStartedEvent": { "command": { "ping": 1 }, "databaseName": "retryable-writes-handshake-tests" } }, { "commandFailedEvent": { "commandName": "ping" } }, { "commandStartedEvent": { "commandName": "findAndModify" } }, { "commandSucceededEvent": { "commandName": "findAndModify" } } ] } ] }, { "description": "collection.findOneAndReplace succeeds after retryable handshake server error (ShutdownInProgress)", "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "client", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 2 }, "data": { "failCommands": [ "ping", "saslContinue" ], "closeConnection": true } } } }, { "name": "runCommand", "object": "database", "arguments": { "commandName": "ping", "command": { "ping": 1 } }, "expectError": { "isError": true } }, { "name": "findOneAndReplace", "object": "collection", "arguments": { "filter": {}, "replacement": { "x": 22 } } } ], "expectEvents": [ { "client": "client", "eventType": "cmap", "events": [ { "connectionCheckOutStartedEvent": {} }, { "connectionCheckOutStartedEvent": {} }, { "connectionCheckOutStartedEvent": {} }, { "connectionCheckOutStartedEvent": {} } ] }, { "client": "client", "events": [ { "commandStartedEvent": { "command": { "ping": 1 }, "databaseName": "retryable-writes-handshake-tests" } }, { "commandFailedEvent": { "commandName": "ping" } }, { "commandStartedEvent": { "commandName": "findAndModify" } }, { "commandSucceededEvent": { "commandName": "findAndModify" } } ] } ] }, { "description": "collection.findOneAndUpdate succeeds after retryable handshake network error", "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "client", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 2 }, "data": { "failCommands": [ "ping", "saslContinue" ], "closeConnection": true } } } }, { "name": "runCommand", "object": "database", "arguments": { "commandName": "ping", "command": { "ping": 1 } }, "expectError": { "isError": true } }, { "name": "findOneAndUpdate", "object": "collection", "arguments": { "filter": {}, "update": { "$set": { "x": 22 } } } } ], "expectEvents": [ { "client": "client", "eventType": "cmap", "events": [ { "connectionCheckOutStartedEvent": {} }, { "connectionCheckOutStartedEvent": {} }, { "connectionCheckOutStartedEvent": {} }, { "connectionCheckOutStartedEvent": {} } ] }, { "client": "client", "events": [ { "commandStartedEvent": { "command": { "ping": 1 }, "databaseName": "retryable-writes-handshake-tests" } }, { "commandFailedEvent": { "commandName": "ping" } }, { "commandStartedEvent": { "commandName": "findAndModify" } }, { "commandSucceededEvent": { "commandName": "findAndModify" } } ] } ] }, { "description": "collection.findOneAndUpdate succeeds after retryable handshake server error (ShutdownInProgress)", "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "client", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 2 }, "data": { "failCommands": [ "ping", "saslContinue" ], "closeConnection": true } } } }, { "name": "runCommand", "object": "database", "arguments": { "commandName": "ping", "command": { "ping": 1 } }, "expectError": { "isError": true } }, { "name": "findOneAndUpdate", "object": "collection", "arguments": { "filter": {}, "update": { "$set": { "x": 22 } } } } ], "expectEvents": [ { "client": "client", "eventType": "cmap", "events": [ { "connectionCheckOutStartedEvent": {} }, { "connectionCheckOutStartedEvent": {} }, { "connectionCheckOutStartedEvent": {} }, { "connectionCheckOutStartedEvent": {} } ] }, { "client": "client", "events": [ { "commandStartedEvent": { "command": { "ping": 1 }, "databaseName": "retryable-writes-handshake-tests" } }, { "commandFailedEvent": { "commandName": "ping" } }, { "commandStartedEvent": { "commandName": "findAndModify" } }, { "commandSucceededEvent": { "commandName": "findAndModify" } } ] } ] }, { "description": "collection.bulkWrite succeeds after retryable handshake network error", "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "client", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 2 }, "data": { "failCommands": [ "ping", "saslContinue" ], "closeConnection": true } } } }, { "name": "runCommand", "object": "database", "arguments": { "commandName": "ping", "command": { "ping": 1 } }, "expectError": { "isError": true } }, { "name": "bulkWrite", "object": "collection", "arguments": { "requests": [ { "insertOne": { "document": { "_id": 2, "x": 22 } } } ] } } ], "expectEvents": [ { "client": "client", "eventType": "cmap", "events": [ { "connectionCheckOutStartedEvent": {} }, { "connectionCheckOutStartedEvent": {} }, { "connectionCheckOutStartedEvent": {} }, { "connectionCheckOutStartedEvent": {} } ] }, { "client": "client", "events": [ { "commandStartedEvent": { "command": { "ping": 1 }, "databaseName": "retryable-writes-handshake-tests" } }, { "commandFailedEvent": { "commandName": "ping" } }, { "commandStartedEvent": { "commandName": "insert" } }, { "commandSucceededEvent": { "commandName": "insert" } } ] } ] }, { "description": "collection.bulkWrite succeeds after retryable handshake server error (ShutdownInProgress)", "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "client", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 2 }, "data": { "failCommands": [ "ping", "saslContinue" ], "closeConnection": true } } } }, { "name": "runCommand", "object": "database", "arguments": { "commandName": "ping", "command": { "ping": 1 } }, "expectError": { "isError": true } }, { "name": "bulkWrite", "object": "collection", "arguments": { "requests": [ { "insertOne": { "document": { "_id": 2, "x": 22 } } } ] } } ], "expectEvents": [ { "client": "client", "eventType": "cmap", "events": [ { "connectionCheckOutStartedEvent": {} }, { "connectionCheckOutStartedEvent": {} }, { "connectionCheckOutStartedEvent": {} }, { "connectionCheckOutStartedEvent": {} } ] }, { "client": "client", "events": [ { "commandStartedEvent": { "command": { "ping": 1 }, "databaseName": "retryable-writes-handshake-tests" } }, { "commandFailedEvent": { "commandName": "ping" } }, { "commandStartedEvent": { "commandName": "insert" } }, { "commandSucceededEvent": { "commandName": "insert" } } ] } ] } ] } insertOne-noWritesPerformedError.json000066400000000000000000000037471462766011000347100ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/retryable_writes/unified{ "description": "retryable-writes insertOne noWritesPerformedErrors", "schemaVersion": "1.0", "runOnRequirements": [ { "minServerVersion": "6.0", "topologies": [ "replicaset" ] } ], "createEntities": [ { "client": { "id": "client0", "useMultipleMongoses": false, "observeEvents": [ "commandFailedEvent" ] } }, { "database": { "id": "database0", "client": "client0", "databaseName": "retryable-writes-tests" } }, { "collection": { "id": "collection0", "database": "database0", "collectionName": "no-writes-performed-collection" } } ], "tests": [ { "description": "InsertOne fails after NoWritesPerformed error", "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "client0", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 2 }, "data": { "failCommands": [ "insert" ], "errorCode": 64, "errorLabels": [ "NoWritesPerformed", "RetryableWriteError" ] } } } }, { "name": "insertOne", "object": "collection0", "arguments": { "document": { "x": 1 } }, "expectError": { "errorCode": 64, "errorLabelsContain": [ "NoWritesPerformed", "RetryableWriteError" ] } } ], "outcome": [ { "collectionName": "no-writes-performed-collection", "databaseName": "retryable-writes-tests", "documents": [] } ] } ] } mongodb-mongo-python-driver-509e9b7/test/retryable_writes/unified/insertOne-serverErrors.json000066400000000000000000000254171462766011000330000ustar00rootroot00000000000000{ "description": "retryable-writes insertOne serverErrors", "schemaVersion": "1.0", "runOnRequirements": [ { "minServerVersion": "4.0", "topologies": [ "replicaset" ] }, { "minServerVersion": "4.1.7", "topologies": [ "sharded" ] } ], "createEntities": [ { "client": { "id": "client0", "useMultipleMongoses": false, "observeEvents": [ "commandStartedEvent" ] } }, { "database": { "id": "database0", "client": "client0", "databaseName": "retryable-writes-tests" } }, { "collection": { "id": "collection0", "database": "database0", "collectionName": "coll" } } ], "initialData": [ { "collectionName": "coll", "databaseName": "retryable-writes-tests", "documents": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 22 } ] } ], "tests": [ { "description": "InsertOne succeeds after retryable writeConcernError", "runOnRequirements": [ { "minServerVersion": "4.3.1" } ], "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "client0", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "insert" ], "errorLabels": [ "RetryableWriteError" ], "writeConcernError": { "code": 91, "errmsg": "Replication is being shut down" } } } } }, { "name": "insertOne", "object": "collection0", "arguments": { "document": { "_id": 3, "x": 33 } }, "expectResult": { "$$unsetOrMatches": { "insertedId": { "$$unsetOrMatches": 3 } } } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "insert": "coll", "documents": [ { "_id": 3, "x": 33 } ] }, "commandName": "insert", "databaseName": "retryable-writes-tests" } }, { "commandStartedEvent": { "command": { "insert": "coll", "documents": [ { "_id": 3, "x": 33 } ] }, "commandName": "insert", "databaseName": "retryable-writes-tests" } } ] } ], "outcome": [ { "collectionName": "coll", "databaseName": "retryable-writes-tests", "documents": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 22 }, { "_id": 3, "x": 33 } ] } ] }, { "description": "RetryableWriteError label is added based on top-level code in pre-4.4 server response", "runOnRequirements": [ { "minServerVersion": "4.2", "maxServerVersion": "4.2.99", "topologies": [ "replicaset", "sharded" ] } ], "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "client0", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 2 }, "data": { "failCommands": [ "insert" ], "errorCode": 189 } } } }, { "name": "insertOne", "object": "collection0", "arguments": { "document": { "_id": 3, "x": 33 } }, "expectError": { "errorLabelsContain": [ "RetryableWriteError" ] } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "insert": "coll", "documents": [ { "_id": 3, "x": 33 } ] }, "commandName": "insert", "databaseName": "retryable-writes-tests" } }, { "commandStartedEvent": { "command": { "insert": "coll", "documents": [ { "_id": 3, "x": 33 } ] }, "commandName": "insert", "databaseName": "retryable-writes-tests" } } ] } ], "outcome": [ { "collectionName": "coll", "databaseName": "retryable-writes-tests", "documents": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 22 } ] } ] }, { "description": "RetryableWriteError label is added based on writeConcernError in pre-4.4 mongod response", "runOnRequirements": [ { "minServerVersion": "4.2", "maxServerVersion": "4.2.99", "topologies": [ "replicaset" ] } ], "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "client0", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 2 }, "data": { "failCommands": [ "insert" ], "writeConcernError": { "code": 91, "errmsg": "Replication is being shut down" } } } } }, { "name": "insertOne", "object": "collection0", "arguments": { "document": { "_id": 3, "x": 33 } }, "expectError": { "errorLabelsContain": [ "RetryableWriteError" ] } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "insert": "coll", "documents": [ { "_id": 3, "x": 33 } ] }, "commandName": "insert", "databaseName": "retryable-writes-tests" } }, { "commandStartedEvent": { "command": { "insert": "coll", "documents": [ { "_id": 3, "x": 33 } ] }, "commandName": "insert", "databaseName": "retryable-writes-tests" } } ] } ], "outcome": [ { "collectionName": "coll", "databaseName": "retryable-writes-tests", "documents": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 22 }, { "_id": 3, "x": 33 } ] } ] }, { "description": "RetryableWriteError label is not added based on writeConcernError in pre-4.4 mongos response", "runOnRequirements": [ { "minServerVersion": "4.2", "maxServerVersion": "4.2.99", "topologies": [ "sharded" ] } ], "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "client0", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "insert" ], "writeConcernError": { "code": 91, "errmsg": "Replication is being shut down" } } } } }, { "name": "insertOne", "object": "collection0", "arguments": { "document": { "_id": 3, "x": 33 } }, "expectError": { "errorLabelsOmit": [ "RetryableWriteError" ] } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "insert": "coll", "documents": [ { "_id": 3, "x": 33 } ] }, "commandName": "insert", "databaseName": "retryable-writes-tests" } } ] } ], "outcome": [ { "collectionName": "coll", "databaseName": "retryable-writes-tests", "documents": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 22 }, { "_id": 3, "x": 33 } ] } ] } ] } mongodb-mongo-python-driver-509e9b7/test/run_command/000077500000000000000000000000001462766011000227165ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/run_command/unified/000077500000000000000000000000001462766011000243415ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/run_command/unified/runCommand.json000066400000000000000000000345731462766011000273530ustar00rootroot00000000000000{ "description": "runCommand", "schemaVersion": "1.3", "createEntities": [ { "client": { "id": "client", "useMultipleMongoses": false, "observeEvents": [ "commandStartedEvent" ] } }, { "database": { "id": "db", "client": "client", "databaseName": "db" } }, { "collection": { "id": "collection", "database": "db", "collectionName": "collection" } }, { "database": { "id": "dbWithRC", "client": "client", "databaseName": "dbWithRC", "databaseOptions": { "readConcern": { "level": "local" } } } }, { "database": { "id": "dbWithWC", "client": "client", "databaseName": "dbWithWC", "databaseOptions": { "writeConcern": { "w": 0 } } } }, { "session": { "id": "session", "client": "client" } }, { "client": { "id": "clientWithStableApi", "observeEvents": [ "commandStartedEvent" ], "serverApi": { "version": "1", "strict": true } } }, { "database": { "id": "dbWithStableApi", "client": "clientWithStableApi", "databaseName": "dbWithStableApi" } } ], "initialData": [ { "collectionName": "collection", "databaseName": "db", "documents": [] } ], "tests": [ { "description": "always attaches $db and implicit lsid to given command and omits default readPreference", "operations": [ { "name": "runCommand", "object": "db", "arguments": { "commandName": "ping", "command": { "ping": 1 } }, "expectResult": { "ok": 1 } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "command": { "ping": 1, "$db": "db", "lsid": { "$$exists": true }, "$readPreference": { "$$exists": false } }, "commandName": "ping" } } ] } ] }, { "description": "always gossips the $clusterTime on the sent command", "runOnRequirements": [ { "topologies": [ "replicaset", "sharded" ] } ], "operations": [ { "name": "runCommand", "object": "db", "arguments": { "commandName": "ping", "command": { "ping": 1 } }, "expectResult": { "ok": 1 } }, { "name": "runCommand", "object": "db", "arguments": { "commandName": "ping", "command": { "ping": 1 } }, "expectResult": { "ok": 1 } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "commandName": "ping" } }, { "commandStartedEvent": { "command": { "ping": 1, "$clusterTime": { "$$exists": true } }, "commandName": "ping" } } ] } ] }, { "description": "attaches the provided session lsid to given command", "operations": [ { "name": "runCommand", "object": "db", "arguments": { "commandName": "ping", "command": { "ping": 1 }, "session": "session" }, "expectResult": { "ok": 1 } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "command": { "ping": 1, "lsid": { "$$sessionLsid": "session" }, "$db": "db" }, "commandName": "ping" } } ] } ] }, { "description": "attaches the provided $readPreference to given command", "runOnRequirements": [ { "topologies": [ "replicaset", "sharded-replicaset", "load-balanced", "sharded" ] } ], "operations": [ { "name": "runCommand", "object": "db", "arguments": { "commandName": "ping", "command": { "ping": 1 }, "readPreference": { "mode": "nearest" } }, "expectResult": { "ok": 1 } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "command": { "ping": 1, "$readPreference": { "mode": "nearest" }, "$db": "db" }, "commandName": "ping" } } ] } ] }, { "description": "does not attach $readPreference to given command on standalone", "runOnRequirements": [ { "topologies": [ "single" ] } ], "operations": [ { "name": "runCommand", "object": "db", "arguments": { "commandName": "ping", "command": { "ping": 1 }, "readPreference": { "mode": "nearest" } }, "expectResult": { "ok": 1 } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "command": { "ping": 1, "$readPreference": { "$$exists": false }, "$db": "db" }, "commandName": "ping" } } ] } ] }, { "description": "does not attach primary $readPreference to given command", "operations": [ { "name": "runCommand", "object": "db", "arguments": { "commandName": "ping", "command": { "ping": 1 }, "readPreference": { "mode": "primary" } }, "expectResult": { "ok": 1 } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "command": { "ping": 1, "$readPreference": { "$$exists": false }, "$db": "db" }, "commandName": "ping" } } ] } ] }, { "description": "does not inherit readConcern specified at the db level", "operations": [ { "name": "runCommand", "object": "dbWithRC", "arguments": { "commandName": "aggregate", "command": { "aggregate": "collection", "pipeline": [], "cursor": {} } } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "command": { "aggregate": "collection", "readConcern": { "$$exists": false }, "$db": "dbWithRC" }, "commandName": "aggregate" } } ] } ] }, { "description": "does not inherit writeConcern specified at the db level", "operations": [ { "name": "runCommand", "object": "dbWithWC", "arguments": { "commandName": "insert", "command": { "insert": "collection", "documents": [ { "foo": "bar" } ], "ordered": true } }, "expectResult": { "ok": 1 } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "command": { "insert": "collection", "writeConcern": { "$$exists": false }, "$db": "dbWithWC" }, "commandName": "insert" } } ] } ] }, { "description": "does not retry retryable errors on given command", "runOnRequirements": [ { "minServerVersion": "4.2" } ], "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "client", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "ping" ], "closeConnection": true } } } }, { "name": "runCommand", "object": "db", "arguments": { "commandName": "ping", "command": { "ping": 1 } }, "expectError": { "isClientError": true } } ] }, { "description": "attaches transaction fields to given command", "runOnRequirements": [ { "minServerVersion": "4.0", "topologies": [ "replicaset" ] }, { "minServerVersion": "4.2", "topologies": [ "sharded-replicaset", "load-balanced" ] } ], "operations": [ { "name": "withTransaction", "object": "session", "arguments": { "callback": [ { "name": "runCommand", "object": "db", "arguments": { "session": "session", "commandName": "insert", "command": { "insert": "collection", "documents": [ { "foo": "transaction" } ], "ordered": true } }, "expectResult": { "$$unsetOrMatches": { "insertedId": { "$$unsetOrMatches": 1 } } } } ] } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "command": { "insert": "collection", "documents": [ { "foo": "transaction" } ], "ordered": true, "lsid": { "$$sessionLsid": "session" }, "txnNumber": 1, "startTransaction": true, "autocommit": false, "readConcern": { "$$exists": false }, "writeConcern": { "$$exists": false } }, "commandName": "insert", "databaseName": "db" } }, { "commandStartedEvent": { "command": { "commitTransaction": 1, "lsid": { "$$sessionLsid": "session" }, "txnNumber": 1, "autocommit": false, "writeConcern": { "$$exists": false }, "readConcern": { "$$exists": false } }, "commandName": "commitTransaction", "databaseName": "admin" } } ] } ] }, { "description": "attaches apiVersion fields to given command when stableApi is configured on the client", "runOnRequirements": [ { "minServerVersion": "5.0" } ], "operations": [ { "name": "runCommand", "object": "dbWithStableApi", "arguments": { "commandName": "ping", "command": { "ping": 1 } }, "expectResult": { "ok": 1 } } ], "expectEvents": [ { "client": "clientWithStableApi", "events": [ { "commandStartedEvent": { "command": { "ping": 1, "$db": "dbWithStableApi", "apiVersion": "1", "apiStrict": true, "apiDeprecationErrors": { "$$unsetOrMatches": false } }, "commandName": "ping" } } ] } ] } ] } mongodb-mongo-python-driver-509e9b7/test/run_command/unified/runCursorCommand.json000066400000000000000000000505661462766011000305510ustar00rootroot00000000000000{ "description": "runCursorCommand", "schemaVersion": "1.9", "createEntities": [ { "client": { "id": "client", "useMultipleMongoses": false, "observeEvents": [ "commandStartedEvent", "connectionReadyEvent", "connectionCheckedOutEvent", "connectionCheckedInEvent" ] } }, { "session": { "id": "session", "client": "client" } }, { "database": { "id": "db", "client": "client", "databaseName": "db" } }, { "collection": { "id": "collection", "database": "db", "collectionName": "collection" } } ], "initialData": [ { "collectionName": "collection", "databaseName": "db", "documents": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 22 }, { "_id": 3, "x": 33 }, { "_id": 4, "x": 44 }, { "_id": 5, "x": 55 } ] } ], "tests": [ { "description": "successfully executes checkMetadataConsistency cursor creating command", "runOnRequirements": [ { "minServerVersion": "7.0", "topologies": [ "sharded" ] } ], "operations": [ { "name": "runCursorCommand", "object": "db", "arguments": { "commandName": "checkMetadataConsistency", "command": { "checkMetadataConsistency": 1 } } } ], "expectEvents": [ { "client": "client", "eventType": "command", "events": [ { "commandStartedEvent": { "command": { "checkMetadataConsistency": 1, "$db": "db", "lsid": { "$$exists": true } }, "commandName": "checkMetadataConsistency" } } ] } ] }, { "description": "errors if the command response is not a cursor", "operations": [ { "name": "createCommandCursor", "object": "db", "arguments": { "commandName": "ping", "command": { "ping": 1 } }, "expectError": { "isClientError": true } } ] }, { "description": "creates an implicit session that is reused across getMores", "operations": [ { "name": "runCursorCommand", "object": "db", "arguments": { "commandName": "find", "command": { "find": "collection", "batchSize": 2 } }, "expectResult": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 22 }, { "_id": 3, "x": 33 }, { "_id": 4, "x": 44 }, { "_id": 5, "x": 55 } ] }, { "name": "assertSameLsidOnLastTwoCommands", "object": "testRunner", "arguments": { "client": "client" } } ], "expectEvents": [ { "client": "client", "eventType": "command", "events": [ { "commandStartedEvent": { "command": { "find": "collection", "batchSize": 2, "$db": "db", "lsid": { "$$exists": true } }, "commandName": "find" } }, { "commandStartedEvent": { "command": { "getMore": { "$$type": [ "int", "long" ] }, "collection": "collection", "$db": "db", "lsid": { "$$exists": true } }, "commandName": "getMore" } } ] } ] }, { "description": "accepts an explicit session that is reused across getMores", "operations": [ { "name": "runCursorCommand", "object": "db", "arguments": { "commandName": "find", "session": "session", "command": { "find": "collection", "batchSize": 2 } }, "expectResult": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 22 }, { "_id": 3, "x": 33 }, { "_id": 4, "x": 44 }, { "_id": 5, "x": 55 } ] }, { "name": "assertSameLsidOnLastTwoCommands", "object": "testRunner", "arguments": { "client": "client" } } ], "expectEvents": [ { "client": "client", "eventType": "command", "events": [ { "commandStartedEvent": { "command": { "find": "collection", "batchSize": 2, "$db": "db", "lsid": { "$$sessionLsid": "session" } }, "commandName": "find" } }, { "commandStartedEvent": { "command": { "getMore": { "$$type": [ "int", "long" ] }, "collection": "collection", "$db": "db", "lsid": { "$$sessionLsid": "session" } }, "commandName": "getMore" } } ] } ] }, { "description": "returns pinned connections to the pool when the cursor is exhausted", "runOnRequirements": [ { "topologies": [ "load-balanced" ] } ], "operations": [ { "name": "createCommandCursor", "object": "db", "arguments": { "commandName": "find", "batchSize": 2, "session": "session", "command": { "find": "collection", "batchSize": 2 } }, "saveResultAsEntity": "cursor" }, { "name": "assertNumberConnectionsCheckedOut", "object": "testRunner", "arguments": { "client": "client", "connections": 1 } }, { "name": "iterateUntilDocumentOrError", "object": "cursor", "expectResult": { "_id": 1, "x": 11 } }, { "name": "iterateUntilDocumentOrError", "object": "cursor", "expectResult": { "_id": 2, "x": 22 } }, { "name": "iterateUntilDocumentOrError", "object": "cursor", "expectResult": { "_id": 3, "x": 33 } }, { "name": "iterateUntilDocumentOrError", "object": "cursor", "expectResult": { "_id": 4, "x": 44 } }, { "name": "iterateUntilDocumentOrError", "object": "cursor", "expectResult": { "_id": 5, "x": 55 } }, { "name": "assertNumberConnectionsCheckedOut", "object": "testRunner", "arguments": { "client": "client", "connections": 0 } } ], "expectEvents": [ { "client": "client", "eventType": "command", "events": [ { "commandStartedEvent": { "command": { "find": "collection", "batchSize": 2, "$db": "db", "lsid": { "$$sessionLsid": "session" } }, "commandName": "find" } }, { "commandStartedEvent": { "command": { "getMore": { "$$type": [ "int", "long" ] }, "collection": "collection", "$db": "db", "lsid": { "$$sessionLsid": "session" } }, "commandName": "getMore" } }, { "commandStartedEvent": { "command": { "getMore": { "$$type": [ "int", "long" ] }, "collection": "collection", "$db": "db", "lsid": { "$$sessionLsid": "session" } }, "commandName": "getMore" } } ] }, { "client": "client", "eventType": "cmap", "events": [ { "connectionReadyEvent": {} }, { "connectionCheckedOutEvent": {} }, { "connectionCheckedInEvent": {} } ] } ] }, { "description": "returns pinned connections to the pool when the cursor is closed", "runOnRequirements": [ { "topologies": [ "load-balanced" ] } ], "operations": [ { "name": "createCommandCursor", "object": "db", "arguments": { "commandName": "find", "command": { "find": "collection", "batchSize": 2 } }, "saveResultAsEntity": "cursor" }, { "name": "assertNumberConnectionsCheckedOut", "object": "testRunner", "arguments": { "client": "client", "connections": 1 } }, { "name": "close", "object": "cursor" }, { "name": "assertNumberConnectionsCheckedOut", "object": "testRunner", "arguments": { "client": "client", "connections": 0 } } ] }, { "description": "supports configuring getMore batchSize", "operations": [ { "name": "runCursorCommand", "object": "db", "arguments": { "commandName": "find", "batchSize": 5, "command": { "find": "collection", "batchSize": 1 } }, "expectResult": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 22 }, { "_id": 3, "x": 33 }, { "_id": 4, "x": 44 }, { "_id": 5, "x": 55 } ] } ], "expectEvents": [ { "client": "client", "eventType": "command", "events": [ { "commandStartedEvent": { "command": { "find": "collection", "batchSize": 1, "$db": "db", "lsid": { "$$exists": true } }, "commandName": "find" } }, { "commandStartedEvent": { "command": { "getMore": { "$$type": [ "int", "long" ] }, "collection": "collection", "batchSize": 5, "$db": "db", "lsid": { "$$exists": true } }, "commandName": "getMore" } } ] } ] }, { "description": "supports configuring getMore maxTimeMS", "operations": [ { "name": "runCursorCommand", "object": "db", "arguments": { "commandName": "find", "maxTimeMS": 300, "command": { "find": "collection", "maxTimeMS": 200, "batchSize": 1 } }, "ignoreResultAndError": true } ], "expectEvents": [ { "client": "client", "eventType": "command", "ignoreExtraEvents": true, "events": [ { "commandStartedEvent": { "command": { "find": "collection", "maxTimeMS": 200, "batchSize": 1, "$db": "db", "lsid": { "$$exists": true } }, "commandName": "find" } }, { "commandStartedEvent": { "command": { "getMore": { "$$type": [ "int", "long" ] }, "collection": "collection", "$db": "db", "maxTimeMS": 300, "lsid": { "$$exists": true } }, "commandName": "getMore" } } ] } ] }, { "description": "supports configuring getMore comment", "runOnRequirements": [ { "minServerVersion": "4.4" } ], "operations": [ { "name": "runCursorCommand", "object": "db", "arguments": { "commandName": "find", "comment": { "hello": "getMore" }, "command": { "find": "collection", "batchSize": 1, "comment": { "hello": "find" } } }, "expectResult": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 22 }, { "_id": 3, "x": 33 }, { "_id": 4, "x": 44 }, { "_id": 5, "x": 55 } ] } ], "expectEvents": [ { "client": "client", "eventType": "command", "events": [ { "commandStartedEvent": { "command": { "find": "collection", "batchSize": 1, "comment": { "hello": "find" }, "$db": "db", "lsid": { "$$exists": true } }, "commandName": "find" } }, { "commandStartedEvent": { "command": { "getMore": { "$$type": [ "int", "long" ] }, "collection": "collection", "comment": { "hello": "getMore" }, "$db": "db", "lsid": { "$$exists": true } }, "commandName": "getMore" } } ] } ] }, { "description": "does not close the cursor when receiving an empty batch", "runOnRequirements": [ { "serverless": "forbid" } ], "operations": [ { "name": "dropCollection", "object": "db", "arguments": { "collection": "cappedCollection" } }, { "name": "createCollection", "object": "db", "arguments": { "collection": "cappedCollection", "capped": true, "size": 4096, "max": 3 }, "saveResultAsEntity": "cappedCollection" }, { "name": "insertMany", "object": "cappedCollection", "arguments": { "documents": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 22 } ] } }, { "name": "createCommandCursor", "object": "db", "arguments": { "cursorType": "tailable", "commandName": "find", "batchSize": 2, "command": { "find": "cappedCollection", "tailable": true } }, "saveResultAsEntity": "cursor" }, { "name": "iterateOnce", "object": "cursor" }, { "name": "iterateOnce", "object": "cursor" }, { "name": "iterateOnce", "object": "cursor" }, { "name": "close", "object": "cursor" } ], "expectEvents": [ { "client": "client", "eventType": "command", "events": [ { "commandStartedEvent": { "command": { "drop": "cappedCollection" }, "commandName": "drop" } }, { "commandStartedEvent": { "command": { "create": "cappedCollection" }, "commandName": "create" } }, { "commandStartedEvent": { "command": { "insert": "cappedCollection" }, "commandName": "insert" } }, { "commandStartedEvent": { "command": { "find": "cappedCollection", "$db": "db", "lsid": { "$$exists": true } }, "commandName": "find" } }, { "commandStartedEvent": { "command": { "getMore": { "$$type": [ "int", "long" ] }, "collection": "cappedCollection", "$db": "db", "lsid": { "$$exists": true } }, "commandName": "getMore" } }, { "commandStartedEvent": { "command": { "killCursors": "cappedCollection", "cursors": { "$$type": "array" } }, "commandName": "killCursors" } } ] } ] } ] } mongodb-mongo-python-driver-509e9b7/test/sdam_monitoring/000077500000000000000000000000001462766011000236055ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/sdam_monitoring/discovered_standalone.json000066400000000000000000000053551462766011000310470ustar00rootroot00000000000000{ "description": "Monitoring a discovered standalone connection", "uri": "mongodb://a:27017/?directConnection=false", "phases": [ { "responses": [ [ "a:27017", { "ok": 1, "helloOk": true, "isWritablePrimary": true, "minWireVersion": 0, "maxWireVersion": 6 } ] ], "outcome": { "events": [ { "topology_opening_event": { "topologyId": "42" } }, { "topology_description_changed_event": { "topologyId": "42", "previousDescription": { "topologyType": "Unknown", "servers": [] }, "newDescription": { "topologyType": "Unknown", "servers": [ { "address": "a:27017", "arbiters": [], "hosts": [], "passives": [], "type": "Unknown" } ] } } }, { "server_opening_event": { "topologyId": "42", "address": "a:27017" } }, { "server_description_changed_event": { "topologyId": "42", "address": "a:27017", "previousDescription": { "address": "a:27017", "arbiters": [], "hosts": [], "passives": [], "type": "Unknown" }, "newDescription": { "address": "a:27017", "arbiters": [], "hosts": [], "passives": [], "type": "Standalone" } } }, { "topology_description_changed_event": { "topologyId": "42", "previousDescription": { "topologyType": "Unknown", "servers": [ { "address": "a:27017", "arbiters": [], "hosts": [], "passives": [], "type": "Unknown" } ] }, "newDescription": { "topologyType": "Single", "servers": [ { "address": "a:27017", "arbiters": [], "hosts": [], "passives": [], "type": "Standalone" } ] } } } ] } } ] } mongodb-mongo-python-driver-509e9b7/test/sdam_monitoring/load_balancer.json000066400000000000000000000047601462766011000272550ustar00rootroot00000000000000{ "description": "Monitoring a load balancer", "uri": "mongodb://a:27017/?loadBalanced=true", "phases": [ { "outcome": { "events": [ { "topology_opening_event": { "topologyId": "42" } }, { "topology_description_changed_event": { "topologyId": "42", "previousDescription": { "topologyType": "Unknown", "servers": [] }, "newDescription": { "topologyType": "LoadBalanced", "servers": [ { "address": "a:27017", "arbiters": [], "hosts": [], "passives": [], "type": "Unknown" } ] } } }, { "server_opening_event": { "topologyId": "42", "address": "a:27017" } }, { "server_description_changed_event": { "topologyId": "42", "address": "a:27017", "previousDescription": { "address": "a:27017", "arbiters": [], "hosts": [], "passives": [], "type": "Unknown" }, "newDescription": { "address": "a:27017", "arbiters": [], "hosts": [], "passives": [], "type": "LoadBalancer" } } }, { "topology_description_changed_event": { "topologyId": "42", "previousDescription": { "topologyType": "LoadBalanced", "servers": [ { "address": "a:27017", "arbiters": [], "hosts": [], "passives": [], "type": "Unknown" } ] }, "newDescription": { "topologyType": "LoadBalanced", "servers": [ { "address": "a:27017", "arbiters": [], "hosts": [], "passives": [], "type": "LoadBalancer" } ] } } } ] } } ] } mongodb-mongo-python-driver-509e9b7/test/sdam_monitoring/replica_set_with_no_primary.json000066400000000000000000000101421462766011000322620ustar00rootroot00000000000000{ "description": "Monitoring a topology that is a replica set with no primary connected", "uri": "mongodb://a,b", "phases": [ { "responses": [ [ "a:27017", { "ok": 1, "helloOk": true, "isWritablePrimary": false, "secondary": true, "setName": "rs", "setVersion": 1, "primary": "b:27017", "hosts": [ "a:27017", "b:27017" ], "minWireVersion": 0, "maxWireVersion": 6 } ] ], "outcome": { "events": [ { "topology_opening_event": { "topologyId": "42" } }, { "topology_description_changed_event": { "topologyId": "42", "previousDescription": { "topologyType": "Unknown", "servers": [] }, "newDescription": { "topologyType": "Unknown", "servers": [ { "address": "a:27017", "arbiters": [], "hosts": [], "passives": [], "type": "Unknown" }, { "address": "b:27017", "arbiters": [], "hosts": [], "passives": [], "type": "Unknown" } ] } } }, { "server_opening_event": { "topologyId": "42", "address": "a:27017" } }, { "server_opening_event": { "topologyId": "42", "address": "b:27017" } }, { "server_description_changed_event": { "topologyId": "42", "address": "a:27017", "previousDescription": { "address": "a:27017", "arbiters": [], "hosts": [], "passives": [], "type": "Unknown" }, "newDescription": { "address": "a:27017", "arbiters": [], "hosts": [ "a:27017", "b:27017" ], "passives": [], "primary": "b:27017", "setName": "rs", "type": "RSSecondary" } } }, { "topology_description_changed_event": { "topologyId": "42", "previousDescription": { "topologyType": "Unknown", "servers": [ { "address": "a:27017", "arbiters": [], "hosts": [], "passives": [], "type": "Unknown" }, { "address": "b:27017", "arbiters": [], "hosts": [], "passives": [], "type": "Unknown" } ] }, "newDescription": { "topologyType": "ReplicaSetNoPrimary", "setName": "rs", "servers": [ { "address": "a:27017", "arbiters": [], "hosts": [ "a:27017", "b:27017" ], "passives": [], "primary": "b:27017", "setName": "rs", "type": "RSSecondary" }, { "address": "b:27017", "arbiters": [], "hosts": [], "passives": [], "type": "PossiblePrimary" } ] } } } ] } } ] } mongodb-mongo-python-driver-509e9b7/test/sdam_monitoring/replica_set_with_primary.json000066400000000000000000000100671462766011000315740ustar00rootroot00000000000000{ "description": "Monitoring a topology that is a replica set with a primary connected", "uri": "mongodb://a,b", "phases": [ { "responses": [ [ "a:27017", { "ok": 1, "helloOk": true, "isWritablePrimary": true, "setName": "rs", "setVersion": 1, "primary": "a:27017", "hosts": [ "a:27017", "b:27017" ], "minWireVersion": 0, "maxWireVersion": 6 } ] ], "outcome": { "events": [ { "topology_opening_event": { "topologyId": "42" } }, { "topology_description_changed_event": { "topologyId": "42", "previousDescription": { "topologyType": "Unknown", "servers": [] }, "newDescription": { "topologyType": "Unknown", "servers": [ { "address": "a:27017", "arbiters": [], "hosts": [], "passives": [], "type": "Unknown" }, { "address": "b:27017", "arbiters": [], "hosts": [], "passives": [], "type": "Unknown" } ] } } }, { "server_opening_event": { "topologyId": "42", "address": "a:27017" } }, { "server_opening_event": { "topologyId": "42", "address": "b:27017" } }, { "server_description_changed_event": { "topologyId": "42", "address": "a:27017", "previousDescription": { "address": "a:27017", "arbiters": [], "hosts": [], "passives": [], "type": "Unknown" }, "newDescription": { "address": "a:27017", "arbiters": [], "hosts": [ "a:27017", "b:27017" ], "passives": [], "primary": "a:27017", "setName": "rs", "type": "RSPrimary" } } }, { "topology_description_changed_event": { "topologyId": "42", "previousDescription": { "topologyType": "Unknown", "servers": [ { "address": "a:27017", "arbiters": [], "hosts": [], "passives": [], "type": "Unknown" }, { "address": "b:27017", "arbiters": [], "hosts": [], "passives": [], "type": "Unknown" } ] }, "newDescription": { "topologyType": "ReplicaSetWithPrimary", "setName": "rs", "servers": [ { "address": "a:27017", "arbiters": [], "hosts": [ "a:27017", "b:27017" ], "passives": [], "primary": "a:27017", "setName": "rs", "type": "RSPrimary" }, { "address": "b:27017", "arbiters": [], "hosts": [], "passives": [], "type": "Unknown" } ] } } } ] } } ] } mongodb-mongo-python-driver-509e9b7/test/sdam_monitoring/replica_set_with_removal.json000066400000000000000000000101521462766011000315510ustar00rootroot00000000000000{ "description": "Monitoring a replica set with non member", "uri": "mongodb://a,b/", "phases": [ { "responses": [], "outcome": { "events": [ { "topology_opening_event": { "topologyId": "42" } }, { "topology_description_changed_event": { "topologyId": "42", "previousDescription": { "topologyType": "Unknown", "servers": [] }, "newDescription": { "topologyType": "Unknown", "servers": [ { "address": "a:27017", "arbiters": [], "hosts": [], "passives": [], "type": "Unknown" }, { "address": "b:27017", "arbiters": [], "hosts": [], "passives": [], "type": "Unknown" } ] } } }, { "server_opening_event": { "topologyId": "42", "address": "a:27017" } }, { "server_opening_event": { "topologyId": "42", "address": "b:27017" } } ] } }, { "responses": [ [ "a:27017", { "ok": 1, "helloOk": true, "isWritablePrimary": true, "setName": "rs", "setVersion": 1, "primary": "a:27017", "hosts": [ "a:27017" ], "minWireVersion": 0, "maxWireVersion": 6 } ], [ "b:27017", { "ok": 1, "helloOk": true, "isWritablePrimary": true } ] ], "outcome": { "events": [ { "server_description_changed_event": { "topologyId": "42", "address": "a:27017", "previousDescription": { "address": "a:27017", "arbiters": [], "hosts": [], "passives": [], "type": "Unknown" }, "newDescription": { "address": "a:27017", "arbiters": [], "hosts": [ "a:27017" ], "passives": [], "primary": "a:27017", "setName": "rs", "type": "RSPrimary" } } }, { "server_closed_event": { "topologyId": "42", "address": "b:27017" } }, { "topology_description_changed_event": { "topologyId": "42", "previousDescription": { "topologyType": "Unknown", "servers": [ { "address": "a:27017", "arbiters": [], "hosts": [], "passives": [], "type": "Unknown" }, { "address": "b:27017", "arbiters": [], "hosts": [], "passives": [], "type": "Unknown" } ] }, "newDescription": { "topologyType": "ReplicaSetWithPrimary", "setName": "rs", "servers": [ { "address": "a:27017", "arbiters": [], "hosts": [ "a:27017" ], "passives": [], "primary": "a:27017", "setName": "rs", "type": "RSPrimary" } ] } } } ] } } ] } mongodb-mongo-python-driver-509e9b7/test/sdam_monitoring/required_replica_set.json000066400000000000000000000102261462766011000306730ustar00rootroot00000000000000{ "description": "Monitoring a topology that is required to be a replica set", "uri": "mongodb://a,b/?replicaSet=rs", "phases": [ { "responses": [ [ "a:27017", { "ok": 1, "helloOk": true, "isWritablePrimary": true, "setName": "rs", "setVersion": 1, "primary": "a:27017", "hosts": [ "a:27017", "b:27017" ], "minWireVersion": 0, "maxWireVersion": 6 } ] ], "outcome": { "events": [ { "topology_opening_event": { "topologyId": "42" } }, { "topology_description_changed_event": { "topologyId": "42", "previousDescription": { "topologyType": "Unknown", "servers": [] }, "newDescription": { "topologyType": "ReplicaSetNoPrimary", "setName": "rs", "servers": [ { "address": "a:27017", "arbiters": [], "hosts": [], "passives": [], "type": "Unknown" }, { "address": "b:27017", "arbiters": [], "hosts": [], "passives": [], "type": "Unknown" } ] } } }, { "server_opening_event": { "topologyId": "42", "address": "a:27017" } }, { "server_opening_event": { "topologyId": "42", "address": "b:27017" } }, { "server_description_changed_event": { "topologyId": "42", "address": "a:27017", "previousDescription": { "address": "a:27017", "arbiters": [], "hosts": [], "passives": [], "type": "Unknown" }, "newDescription": { "address": "a:27017", "arbiters": [], "hosts": [ "a:27017", "b:27017" ], "passives": [], "primary": "a:27017", "setName": "rs", "type": "RSPrimary" } } }, { "topology_description_changed_event": { "topologyId": "42", "previousDescription": { "topologyType": "ReplicaSetNoPrimary", "setName": "rs", "servers": [ { "address": "a:27017", "arbiters": [], "hosts": [], "passives": [], "type": "Unknown" }, { "address": "b:27017", "arbiters": [], "hosts": [], "passives": [], "type": "Unknown" } ] }, "newDescription": { "topologyType": "ReplicaSetWithPrimary", "setName": "rs", "servers": [ { "address": "a:27017", "arbiters": [], "hosts": [ "a:27017", "b:27017" ], "passives": [], "primary": "a:27017", "setName": "rs", "type": "RSPrimary" }, { "address": "b:27017", "arbiters": [], "hosts": [], "passives": [], "type": "Unknown" } ] } } } ] } } ] } mongodb-mongo-python-driver-509e9b7/test/sdam_monitoring/standalone.json000066400000000000000000000053331462766011000266340ustar00rootroot00000000000000{ "description": "Monitoring a direct connection", "uri": "mongodb://a:27017/?directConnection=true", "phases": [ { "responses": [ [ "a:27017", { "ok": 1, "helloOk": true, "isWritablePrimary": true, "minWireVersion": 0, "maxWireVersion": 6 } ] ], "outcome": { "events": [ { "topology_opening_event": { "topologyId": "42" } }, { "topology_description_changed_event": { "topologyId": "42", "previousDescription": { "topologyType": "Unknown", "servers": [] }, "newDescription": { "topologyType": "Single", "servers": [ { "address": "a:27017", "arbiters": [], "hosts": [], "passives": [], "type": "Unknown" } ] } } }, { "server_opening_event": { "topologyId": "42", "address": "a:27017" } }, { "server_description_changed_event": { "topologyId": "42", "address": "a:27017", "previousDescription": { "address": "a:27017", "arbiters": [], "hosts": [], "passives": [], "type": "Unknown" }, "newDescription": { "address": "a:27017", "arbiters": [], "hosts": [], "passives": [], "type": "Standalone" } } }, { "topology_description_changed_event": { "topologyId": "42", "previousDescription": { "topologyType": "Single", "servers": [ { "address": "a:27017", "arbiters": [], "hosts": [], "passives": [], "type": "Unknown" } ] }, "newDescription": { "topologyType": "Single", "servers": [ { "address": "a:27017", "arbiters": [], "hosts": [], "passives": [], "type": "Standalone" } ] } } } ] } } ] } standalone_suppress_equal_description_changes.json000066400000000000000000000057561462766011000360140ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/sdam_monitoring{ "description": "Monitoring a direct connection - suppress update events for equal server descriptions", "uri": "mongodb://a:27017/?directConnection=true", "phases": [ { "responses": [ [ "a:27017", { "ok": 1, "helloOk": true, "isWritablePrimary": true, "minWireVersion": 0, "maxWireVersion": 6 } ], [ "a:27017", { "ok": 1, "helloOk": true, "isWritablePrimary": true, "minWireVersion": 0, "maxWireVersion": 6 } ] ], "outcome": { "events": [ { "topology_opening_event": { "topologyId": "42" } }, { "topology_description_changed_event": { "topologyId": "42", "previousDescription": { "topologyType": "Unknown", "servers": [] }, "newDescription": { "topologyType": "Single", "servers": [ { "address": "a:27017", "arbiters": [], "hosts": [], "passives": [], "type": "Unknown" } ] } } }, { "server_opening_event": { "topologyId": "42", "address": "a:27017" } }, { "server_description_changed_event": { "topologyId": "42", "address": "a:27017", "previousDescription": { "address": "a:27017", "arbiters": [], "hosts": [], "passives": [], "type": "Unknown" }, "newDescription": { "address": "a:27017", "arbiters": [], "hosts": [], "passives": [], "type": "Standalone" } } }, { "topology_description_changed_event": { "topologyId": "42", "previousDescription": { "topologyType": "Single", "servers": [ { "address": "a:27017", "arbiters": [], "hosts": [], "passives": [], "type": "Unknown" } ] }, "newDescription": { "topologyType": "Single", "servers": [ { "address": "a:27017", "arbiters": [], "hosts": [], "passives": [], "type": "Standalone" } ] } } } ] } } ] } mongodb-mongo-python-driver-509e9b7/test/server_selection/000077500000000000000000000000001462766011000237675ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/server_selection/in_window/000077500000000000000000000000001462766011000257645ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/server_selection/in_window/equilibrium.json000066400000000000000000000015251462766011000312110ustar00rootroot00000000000000{ "description": "When in equilibrium selection is evenly distributed", "topology_description": { "type": "Sharded", "servers": [ { "address": "a:27017", "avg_rtt_ms": 35, "type": "Mongos" }, { "address": "b:27017", "avg_rtt_ms": 35, "type": "Mongos" }, { "address": "c:27017", "avg_rtt_ms": 35, "type": "Mongos" } ] }, "mocked_topology_state": [ { "address": "a:27017", "operation_count": 5 }, { "address": "b:27017", "operation_count": 5 }, { "address": "c:27017", "operation_count": 5 } ], "iterations": 2000, "outcome": { "tolerance": 0.05, "expected_frequencies": { "a:27017": 0.33, "b:27017": 0.33, "c:27017": 0.33 } } } mongodb-mongo-python-driver-509e9b7/test/server_selection/in_window/many-choices.json000066400000000000000000000037231462766011000312430ustar00rootroot00000000000000{ "description": "Selections from many choices occur at correct frequencies", "topology_description": { "type": "Sharded", "servers": [ { "address": "a:27017", "avg_rtt_ms": 35, "type": "Mongos" }, { "address": "b:27017", "avg_rtt_ms": 35, "type": "Mongos" }, { "address": "c:27017", "avg_rtt_ms": 35, "type": "Mongos" }, { "address": "d:27017", "avg_rtt_ms": 35, "type": "Mongos" }, { "address": "e:27017", "avg_rtt_ms": 35, "type": "Mongos" }, { "address": "f:27017", "avg_rtt_ms": 35, "type": "Mongos" }, { "address": "g:27017", "avg_rtt_ms": 35, "type": "Mongos" }, { "address": "h:27017", "avg_rtt_ms": 35, "type": "Mongos" }, { "address": "i:27017", "avg_rtt_ms": 35, "type": "Mongos" } ] }, "mocked_topology_state": [ { "address": "a:27017", "operation_count": 0 }, { "address": "b:27017", "operation_count": 5 }, { "address": "c:27017", "operation_count": 5 }, { "address": "d:27017", "operation_count": 10 }, { "address": "e:27017", "operation_count": 10 }, { "address": "f:27017", "operation_count": 20 }, { "address": "g:27017", "operation_count": 20 }, { "address": "h:27017", "operation_count": 50 }, { "address": "i:27017", "operation_count": 60 } ], "iterations": 10000, "outcome": { "tolerance": 0.03, "expected_frequencies": { "a:27017": 0.22, "b:27017": 0.18, "c:27017": 0.18, "d:27017": 0.125, "e:27017": 0.125, "f:27017": 0.074, "g:27017": 0.074, "h:27017": 0.0277, "i:27017": 0 } } } mongodb-mongo-python-driver-509e9b7/test/server_selection/in_window/one-least-two-tied.json000066400000000000000000000015451462766011000323050ustar00rootroot00000000000000{ "description": "Least operations gets most selections, two tied share the rest", "topology_description": { "type": "Sharded", "servers": [ { "address": "a:27017", "avg_rtt_ms": 35, "type": "Mongos" }, { "address": "b:27017", "avg_rtt_ms": 35, "type": "Mongos" }, { "address": "c:27017", "avg_rtt_ms": 35, "type": "Mongos" } ] }, "mocked_topology_state": [ { "address": "a:27017", "operation_count": 16 }, { "address": "b:27017", "operation_count": 10 }, { "address": "c:27017", "operation_count": 16 } ], "iterations": 2000, "outcome": { "tolerance": 0.05, "expected_frequencies": { "a:27017": 0.165, "b:27017": 0.66, "c:27017": 0.165 } } } mongodb-mongo-python-driver-509e9b7/test/server_selection/in_window/rs-equilibrium.json000066400000000000000000000015761462766011000316410ustar00rootroot00000000000000{ "description": "When in equilibrium selection is evenly distributed (replica set)", "topology_description": { "type": "ReplicaSetWithPrimary", "servers": [ { "address": "a:27017", "avg_rtt_ms": 35, "type": "RSPrimary" }, { "address": "b:27017", "avg_rtt_ms": 35, "type": "RSSecondary" }, { "address": "c:27017", "avg_rtt_ms": 35, "type": "RSSecondary" } ] }, "mocked_topology_state": [ { "address": "a:27017", "operation_count": 6 }, { "address": "b:27017", "operation_count": 6 }, { "address": "c:27017", "operation_count": 6 } ], "iterations": 2000, "outcome": { "tolerance": 0.05, "expected_frequencies": { "a:27017": 0.33, "b:27017": 0.33, "c:27017": 0.33 } } } mongodb-mongo-python-driver-509e9b7/test/server_selection/in_window/rs-three-choices.json000066400000000000000000000016041462766011000320240ustar00rootroot00000000000000{ "description": "Selections from three servers occur at proper distributions (replica set)", "topology_description": { "type": "ReplicaSetWithPrimary", "servers": [ { "address": "a:27017", "avg_rtt_ms": 35, "type": "RSPrimary" }, { "address": "b:27017", "avg_rtt_ms": 35, "type": "RSSecondary" }, { "address": "c:27017", "avg_rtt_ms": 35, "type": "RSSecondary" } ] }, "mocked_topology_state": [ { "address": "a:27017", "operation_count": 3 }, { "address": "b:27017", "operation_count": 6 }, { "address": "c:27017", "operation_count": 20 } ], "iterations": 2000, "outcome": { "tolerance": 0.05, "expected_frequencies": { "a:27017": 0.66, "b:27017": 0.33, "c:27017": 0 } } } mongodb-mongo-python-driver-509e9b7/test/server_selection/in_window/three-choices.json000066400000000000000000000015331462766011000314030ustar00rootroot00000000000000{ "description": "Selections from three servers occur at proper distributions", "topology_description": { "type": "Sharded", "servers": [ { "address": "a:27017", "avg_rtt_ms": 35, "type": "Mongos" }, { "address": "b:27017", "avg_rtt_ms": 35, "type": "Mongos" }, { "address": "c:27017", "avg_rtt_ms": 35, "type": "Mongos" } ] }, "mocked_topology_state": [ { "address": "a:27017", "operation_count": 3 }, { "address": "b:27017", "operation_count": 6 }, { "address": "c:27017", "operation_count": 20 } ], "iterations": 2000, "outcome": { "tolerance": 0.05, "expected_frequencies": { "a:27017": 0.66, "b:27017": 0.33, "c:27017": 0 } } } mongodb-mongo-python-driver-509e9b7/test/server_selection/in_window/two-choices.json000066400000000000000000000012001462766011000310740ustar00rootroot00000000000000{ "description": "Better of two choices always selected", "topology_description": { "type": "Sharded", "servers": [ { "address": "a:27017", "avg_rtt_ms": 35, "type": "Mongos" }, { "address": "b:27017", "avg_rtt_ms": 35, "type": "Mongos" } ] }, "mocked_topology_state": [ { "address": "a:27017", "operation_count": 0 }, { "address": "b:27017", "operation_count": 5 } ], "iterations": 100, "outcome": { "tolerance": 0, "expected_frequencies": { "a:27017": 1, "b:27017": 0 } } } mongodb-mongo-python-driver-509e9b7/test/server_selection/in_window/two-least.json000066400000000000000000000015221462766011000305760ustar00rootroot00000000000000{ "description": "Two tied for least operations share all selections", "topology_description": { "type": "Sharded", "servers": [ { "address": "a:27017", "avg_rtt_ms": 35, "type": "Mongos" }, { "address": "b:27017", "avg_rtt_ms": 35, "type": "Mongos" }, { "address": "c:27017", "avg_rtt_ms": 35, "type": "Mongos" } ] }, "mocked_topology_state": [ { "address": "a:27017", "operation_count": 10 }, { "address": "b:27017", "operation_count": 10 }, { "address": "c:27017", "operation_count": 16 } ], "iterations": 2000, "outcome": { "tolerance": 0.05, "expected_frequencies": { "a:27017": 0.5, "b:27017": 0.5, "c:27017": 0 } } } mongodb-mongo-python-driver-509e9b7/test/server_selection/rtt/000077500000000000000000000000001462766011000246005ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/server_selection/rtt/first_value.json000066400000000000000000000001041462766011000300110ustar00rootroot00000000000000{ "avg_rtt_ms": "NULL", "new_rtt_ms": 10, "new_avg_rtt": 10 } mongodb-mongo-python-driver-509e9b7/test/server_selection/rtt/first_value_zero.json000066400000000000000000000001021462766011000310460ustar00rootroot00000000000000{ "avg_rtt_ms": "NULL", "new_rtt_ms": 0, "new_avg_rtt": 0 } mongodb-mongo-python-driver-509e9b7/test/server_selection/rtt/value_test_1.json000066400000000000000000000000751462766011000300700ustar00rootroot00000000000000{ "avg_rtt_ms": 0, "new_rtt_ms": 5, "new_avg_rtt": 1 } mongodb-mongo-python-driver-509e9b7/test/server_selection/rtt/value_test_2.json000066400000000000000000000001031462766011000300610ustar00rootroot00000000000000{ "avg_rtt_ms": 3.1, "new_rtt_ms": 36, "new_avg_rtt": 9.68 } mongodb-mongo-python-driver-509e9b7/test/server_selection/rtt/value_test_3.json000066400000000000000000000001061462766011000300650ustar00rootroot00000000000000{ "avg_rtt_ms": 9.12, "new_rtt_ms": 9.12, "new_avg_rtt": 9.12 } mongodb-mongo-python-driver-509e9b7/test/server_selection/rtt/value_test_4.json000066400000000000000000000001041462766011000300640ustar00rootroot00000000000000{ "avg_rtt_ms": 1, "new_rtt_ms": 1000, "new_avg_rtt": 200.8 } mongodb-mongo-python-driver-509e9b7/test/server_selection/rtt/value_test_5.json000066400000000000000000000001031462766011000300640ustar00rootroot00000000000000{ "avg_rtt_ms": 0, "new_rtt_ms": 0.25, "new_avg_rtt": 0.05 } mongodb-mongo-python-driver-509e9b7/test/server_selection/server_selection/000077500000000000000000000000001462766011000273425ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/server_selection/server_selection/LoadBalanced/000077500000000000000000000000001462766011000316335ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/server_selection/server_selection/LoadBalanced/read/000077500000000000000000000000001462766011000325465ustar00rootroot00000000000000Nearest.json000066400000000000000000000010771462766011000347700ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/server_selection/server_selection/LoadBalanced/read{ "topology_description": { "type": "LoadBalanced", "servers": [ { "address": "g:27017", "avg_rtt_ms": 0, "type": "LoadBalancer" } ] }, "operation": "read", "read_preference": { "mode": "Nearest", "tag_sets": [ { "data_center": "nyc" } ] }, "suitable_servers": [ { "address": "g:27017", "avg_rtt_ms": 0, "type": "LoadBalancer" } ], "in_latency_window": [ { "address": "g:27017", "avg_rtt_ms": 0, "type": "LoadBalancer" } ] } Primary.json000066400000000000000000000007711462766011000350120ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/server_selection/server_selection/LoadBalanced/read{ "topology_description": { "type": "LoadBalanced", "servers": [ { "address": "g:27017", "avg_rtt_ms": 0, "type": "LoadBalancer" } ] }, "operation": "read", "read_preference": { "mode": "Primary" }, "suitable_servers": [ { "address": "g:27017", "avg_rtt_ms": 0, "type": "LoadBalancer" } ], "in_latency_window": [ { "address": "g:27017", "avg_rtt_ms": 0, "type": "LoadBalancer" } ] } PrimaryPreferred.json000066400000000000000000000011101462766011000366350ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/server_selection/server_selection/LoadBalanced/read{ "topology_description": { "type": "LoadBalanced", "servers": [ { "address": "g:27017", "avg_rtt_ms": 0, "type": "LoadBalancer" } ] }, "operation": "read", "read_preference": { "mode": "PrimaryPreferred", "tag_sets": [ { "data_center": "nyc" } ] }, "suitable_servers": [ { "address": "g:27017", "avg_rtt_ms": 0, "type": "LoadBalancer" } ], "in_latency_window": [ { "address": "g:27017", "avg_rtt_ms": 0, "type": "LoadBalancer" } ] } Secondary.json000066400000000000000000000011011462766011000353020ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/server_selection/server_selection/LoadBalanced/read{ "topology_description": { "type": "LoadBalanced", "servers": [ { "address": "g:27017", "avg_rtt_ms": 0, "type": "LoadBalancer" } ] }, "operation": "read", "read_preference": { "mode": "Secondary", "tag_sets": [ { "data_center": "nyc" } ] }, "suitable_servers": [ { "address": "g:27017", "avg_rtt_ms": 0, "type": "LoadBalancer" } ], "in_latency_window": [ { "address": "g:27017", "avg_rtt_ms": 0, "type": "LoadBalancer" } ] } SecondaryPreferred.json000066400000000000000000000011121462766011000371430ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/server_selection/server_selection/LoadBalanced/read{ "topology_description": { "type": "LoadBalanced", "servers": [ { "address": "g:27017", "avg_rtt_ms": 0, "type": "LoadBalancer" } ] }, "operation": "read", "read_preference": { "mode": "SecondaryPreferred", "tag_sets": [ { "data_center": "nyc" } ] }, "suitable_servers": [ { "address": "g:27017", "avg_rtt_ms": 0, "type": "LoadBalancer" } ], "in_latency_window": [ { "address": "g:27017", "avg_rtt_ms": 0, "type": "LoadBalancer" } ] } mongodb-mongo-python-driver-509e9b7/test/server_selection/server_selection/LoadBalanced/write/000077500000000000000000000000001462766011000327655ustar00rootroot00000000000000Nearest.json000066400000000000000000000011001462766011000351720ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/server_selection/server_selection/LoadBalanced/write{ "topology_description": { "type": "LoadBalanced", "servers": [ { "address": "g:27017", "avg_rtt_ms": 0, "type": "LoadBalancer" } ] }, "operation": "write", "read_preference": { "mode": "Nearest", "tag_sets": [ { "data_center": "nyc" } ] }, "suitable_servers": [ { "address": "g:27017", "avg_rtt_ms": 0, "type": "LoadBalancer" } ], "in_latency_window": [ { "address": "g:27017", "avg_rtt_ms": 0, "type": "LoadBalancer" } ] } Primary.json000066400000000000000000000007721462766011000352320ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/server_selection/server_selection/LoadBalanced/write{ "topology_description": { "type": "LoadBalanced", "servers": [ { "address": "g:27017", "avg_rtt_ms": 0, "type": "LoadBalancer" } ] }, "operation": "write", "read_preference": { "mode": "Primary" }, "suitable_servers": [ { "address": "g:27017", "avg_rtt_ms": 0, "type": "LoadBalancer" } ], "in_latency_window": [ { "address": "g:27017", "avg_rtt_ms": 0, "type": "LoadBalancer" } ] } PrimaryPreferred.json000066400000000000000000000011111462766011000370550ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/server_selection/server_selection/LoadBalanced/write{ "topology_description": { "type": "LoadBalanced", "servers": [ { "address": "g:27017", "avg_rtt_ms": 0, "type": "LoadBalancer" } ] }, "operation": "write", "read_preference": { "mode": "PrimaryPreferred", "tag_sets": [ { "data_center": "nyc" } ] }, "suitable_servers": [ { "address": "g:27017", "avg_rtt_ms": 0, "type": "LoadBalancer" } ], "in_latency_window": [ { "address": "g:27017", "avg_rtt_ms": 0, "type": "LoadBalancer" } ] } Secondary.json000066400000000000000000000011021462766011000355220ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/server_selection/server_selection/LoadBalanced/write{ "topology_description": { "type": "LoadBalanced", "servers": [ { "address": "g:27017", "avg_rtt_ms": 0, "type": "LoadBalancer" } ] }, "operation": "write", "read_preference": { "mode": "Secondary", "tag_sets": [ { "data_center": "nyc" } ] }, "suitable_servers": [ { "address": "g:27017", "avg_rtt_ms": 0, "type": "LoadBalancer" } ], "in_latency_window": [ { "address": "g:27017", "avg_rtt_ms": 0, "type": "LoadBalancer" } ] } SecondaryPreferred.json000066400000000000000000000011131462766011000373630ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/server_selection/server_selection/LoadBalanced/write{ "topology_description": { "type": "LoadBalanced", "servers": [ { "address": "g:27017", "avg_rtt_ms": 0, "type": "LoadBalancer" } ] }, "operation": "write", "read_preference": { "mode": "SecondaryPreferred", "tag_sets": [ { "data_center": "nyc" } ] }, "suitable_servers": [ { "address": "g:27017", "avg_rtt_ms": 0, "type": "LoadBalancer" } ], "in_latency_window": [ { "address": "g:27017", "avg_rtt_ms": 0, "type": "LoadBalancer" } ] } mongodb-mongo-python-driver-509e9b7/test/server_selection/server_selection/ReplicaSetNoPrimary/000077500000000000000000000000001462766011000332365ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/server_selection/server_selection/ReplicaSetNoPrimary/read/000077500000000000000000000000001462766011000341515ustar00rootroot00000000000000Nearest.json000066400000000000000000000020431462766011000363650ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/server_selection/server_selection/ReplicaSetNoPrimary/read{ "topology_description": { "type": "ReplicaSetNoPrimary", "servers": [ { "address": "b:27017", "avg_rtt_ms": 5, "type": "RSSecondary", "tags": { "data_center": "nyc" } }, { "address": "c:27017", "avg_rtt_ms": 100, "type": "RSSecondary", "tags": { "data_center": "nyc" } } ] }, "operation": "read", "read_preference": { "mode": "Nearest", "tag_sets": [ { "data_center": "nyc" } ] }, "suitable_servers": [ { "address": "b:27017", "avg_rtt_ms": 5, "type": "RSSecondary", "tags": { "data_center": "nyc" } }, { "address": "c:27017", "avg_rtt_ms": 100, "type": "RSSecondary", "tags": { "data_center": "nyc" } } ], "in_latency_window": [ { "address": "b:27017", "avg_rtt_ms": 5, "type": "RSSecondary", "tags": { "data_center": "nyc" } } ] } Nearest_multiple.json000066400000000000000000000022671462766011000403100ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/server_selection/server_selection/ReplicaSetNoPrimary/read{ "topology_description": { "type": "ReplicaSetNoPrimary", "servers": [ { "address": "b:27017", "avg_rtt_ms": 10, "type": "RSSecondary", "tags": { "data_center": "nyc" } }, { "address": "c:27017", "avg_rtt_ms": 20, "type": "RSSecondary", "tags": { "data_center": "nyc" } } ] }, "operation": "read", "read_preference": { "mode": "Nearest", "tag_sets": [ { "data_center": "nyc" } ] }, "suitable_servers": [ { "address": "b:27017", "avg_rtt_ms": 10, "type": "RSSecondary", "tags": { "data_center": "nyc" } }, { "address": "c:27017", "avg_rtt_ms": 20, "type": "RSSecondary", "tags": { "data_center": "nyc" } } ], "in_latency_window": [ { "address": "b:27017", "avg_rtt_ms": 10, "type": "RSSecondary", "tags": { "data_center": "nyc" } }, { "address": "c:27017", "avg_rtt_ms": 20, "type": "RSSecondary", "tags": { "data_center": "nyc" } } ] } Nearest_non_matching.json000066400000000000000000000011461462766011000411140ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/server_selection/server_selection/ReplicaSetNoPrimary/read{ "topology_description": { "type": "ReplicaSetNoPrimary", "servers": [ { "address": "b:27017", "avg_rtt_ms": 5, "type": "RSSecondary", "tags": { "data_center": "nyc" } }, { "address": "c:27017", "avg_rtt_ms": 100, "type": "RSSecondary", "tags": { "data_center": "nyc" } } ] }, "operation": "read", "read_preference": { "mode": "Nearest", "tag_sets": [ { "data_center": "sf" } ] }, "suitable_servers": [], "in_latency_window": [] } PossiblePrimary.json000066400000000000000000000005471462766011000401170ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/server_selection/server_selection/ReplicaSetNoPrimary/read{ "topology_description": { "type": "ReplicaSetNoPrimary", "servers": [ { "address": "b:27017", "avg_rtt_ms": 5, "type": "PossiblePrimary" } ] }, "operation": "read", "read_preference": { "mode": "Primary", "tag_sets": [ {} ] }, "suitable_servers": [], "in_latency_window": [] } PossiblePrimaryNearest.json000066400000000000000000000005471462766011000414410ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/server_selection/server_selection/ReplicaSetNoPrimary/read{ "topology_description": { "type": "ReplicaSetNoPrimary", "servers": [ { "address": "b:27017", "avg_rtt_ms": 5, "type": "PossiblePrimary" } ] }, "operation": "read", "read_preference": { "mode": "Nearest", "tag_sets": [ {} ] }, "suitable_servers": [], "in_latency_window": [] } Primary.json000066400000000000000000000010411462766011000364040ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/server_selection/server_selection/ReplicaSetNoPrimary/read{ "topology_description": { "type": "ReplicaSetNoPrimary", "servers": [ { "address": "b:27017", "avg_rtt_ms": 5, "type": "RSSecondary", "tags": { "data_center": "nyc" } }, { "address": "c:27017", "avg_rtt_ms": 100, "type": "RSSecondary", "tags": { "data_center": "nyc" } } ] }, "operation": "read", "read_preference": { "mode": "Primary" }, "suitable_servers": [], "in_latency_window": [] } PrimaryPreferred.json000066400000000000000000000020101462766011000402400ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/server_selection/server_selection/ReplicaSetNoPrimary/read{ "topology_description": { "type": "ReplicaSetNoPrimary", "servers": [ { "address": "b:27017", "avg_rtt_ms": 5, "type": "RSSecondary", "tags": { "data_center": "nyc" } }, { "address": "c:27017", "avg_rtt_ms": 100, "type": "RSSecondary", "tags": { "data_center": "nyc" } } ] }, "operation": "read", "read_preference": { "mode": "PrimaryPreferred", "tag_sets": [ {} ] }, "suitable_servers": [ { "address": "b:27017", "avg_rtt_ms": 5, "type": "RSSecondary", "tags": { "data_center": "nyc" } }, { "address": "c:27017", "avg_rtt_ms": 100, "type": "RSSecondary", "tags": { "data_center": "nyc" } } ], "in_latency_window": [ { "address": "b:27017", "avg_rtt_ms": 5, "type": "RSSecondary", "tags": { "data_center": "nyc" } } ] } PrimaryPreferred_non_matching.json000066400000000000000000000011571462766011000427770ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/server_selection/server_selection/ReplicaSetNoPrimary/read{ "topology_description": { "type": "ReplicaSetNoPrimary", "servers": [ { "address": "b:27017", "avg_rtt_ms": 5, "type": "RSSecondary", "tags": { "data_center": "nyc" } }, { "address": "c:27017", "avg_rtt_ms": 100, "type": "RSSecondary", "tags": { "data_center": "nyc" } } ] }, "operation": "read", "read_preference": { "mode": "PrimaryPreferred", "tag_sets": [ { "data_center": "sf" } ] }, "suitable_servers": [], "in_latency_window": [] } Secondary.json000066400000000000000000000020451462766011000367150ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/server_selection/server_selection/ReplicaSetNoPrimary/read{ "topology_description": { "type": "ReplicaSetNoPrimary", "servers": [ { "address": "b:27017", "avg_rtt_ms": 5, "type": "RSSecondary", "tags": { "data_center": "nyc" } }, { "address": "c:27017", "avg_rtt_ms": 100, "type": "RSSecondary", "tags": { "data_center": "nyc" } } ] }, "operation": "read", "read_preference": { "mode": "Secondary", "tag_sets": [ { "data_center": "nyc" } ] }, "suitable_servers": [ { "address": "b:27017", "avg_rtt_ms": 5, "type": "RSSecondary", "tags": { "data_center": "nyc" } }, { "address": "c:27017", "avg_rtt_ms": 100, "type": "RSSecondary", "tags": { "data_center": "nyc" } } ], "in_latency_window": [ { "address": "b:27017", "avg_rtt_ms": 5, "type": "RSSecondary", "tags": { "data_center": "nyc" } } ] } SecondaryPreferred.json000066400000000000000000000020561462766011000405560ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/server_selection/server_selection/ReplicaSetNoPrimary/read{ "topology_description": { "type": "ReplicaSetNoPrimary", "servers": [ { "address": "b:27017", "avg_rtt_ms": 5, "type": "RSSecondary", "tags": { "data_center": "nyc" } }, { "address": "c:27017", "avg_rtt_ms": 100, "type": "RSSecondary", "tags": { "data_center": "nyc" } } ] }, "operation": "read", "read_preference": { "mode": "SecondaryPreferred", "tag_sets": [ { "data_center": "nyc" } ] }, "suitable_servers": [ { "address": "b:27017", "avg_rtt_ms": 5, "type": "RSSecondary", "tags": { "data_center": "nyc" } }, { "address": "c:27017", "avg_rtt_ms": 100, "type": "RSSecondary", "tags": { "data_center": "nyc" } } ], "in_latency_window": [ { "address": "b:27017", "avg_rtt_ms": 5, "type": "RSSecondary", "tags": { "data_center": "nyc" } } ] } SecondaryPreferred_non_matching.json000066400000000000000000000011611462766011000432760ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/server_selection/server_selection/ReplicaSetNoPrimary/read{ "topology_description": { "type": "ReplicaSetNoPrimary", "servers": [ { "address": "b:27017", "avg_rtt_ms": 5, "type": "RSSecondary", "tags": { "data_center": "nyc" } }, { "address": "c:27017", "avg_rtt_ms": 100, "type": "RSSecondary", "tags": { "data_center": "nyc" } } ] }, "operation": "read", "read_preference": { "mode": "SecondaryPreferred", "tag_sets": [ { "data_center": "sf" } ] }, "suitable_servers": [], "in_latency_window": [] } Secondary_multi_tags.json000066400000000000000000000020711462766011000411440ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/server_selection/server_selection/ReplicaSetNoPrimary/read{ "topology_description": { "type": "ReplicaSetNoPrimary", "servers": [ { "address": "b:27017", "avg_rtt_ms": 5, "type": "RSSecondary", "tags": { "rack": "one", "data_center": "nyc" } }, { "address": "c:27017", "avg_rtt_ms": 5, "type": "RSSecondary", "tags": { "rack": "two", "data_center": "sf" } } ] }, "operation": "read", "read_preference": { "mode": "Secondary", "tag_sets": [ { "data_center": "nyc", "rack": "one" }, { "other_tag": "doesntexist" } ] }, "suitable_servers": [ { "address": "b:27017", "avg_rtt_ms": 5, "type": "RSSecondary", "tags": { "rack": "one", "data_center": "nyc" } } ], "in_latency_window": [ { "address": "b:27017", "avg_rtt_ms": 5, "type": "RSSecondary", "tags": { "rack": "one", "data_center": "nyc" } } ] } Secondary_multi_tags2.json000066400000000000000000000020721462766011000412270ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/server_selection/server_selection/ReplicaSetNoPrimary/read{ "topology_description": { "type": "ReplicaSetNoPrimary", "servers": [ { "address": "b:27017", "avg_rtt_ms": 5, "type": "RSSecondary", "tags": { "rack": "one", "data_center": "nyc" } }, { "address": "c:27017", "avg_rtt_ms": 5, "type": "RSSecondary", "tags": { "rack": "two", "data_center": "nyc" } } ] }, "operation": "read", "read_preference": { "mode": "Secondary", "tag_sets": [ { "data_center": "nyc", "rack": "one" }, { "other_tag": "doesntexist" } ] }, "suitable_servers": [ { "address": "b:27017", "avg_rtt_ms": 5, "type": "RSSecondary", "tags": { "rack": "one", "data_center": "nyc" } } ], "in_latency_window": [ { "address": "b:27017", "avg_rtt_ms": 5, "type": "RSSecondary", "tags": { "rack": "one", "data_center": "nyc" } } ] } Secondary_non_matching.json000066400000000000000000000011501462766011000414350ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/server_selection/server_selection/ReplicaSetNoPrimary/read{ "topology_description": { "type": "ReplicaSetNoPrimary", "servers": [ { "address": "b:27017", "avg_rtt_ms": 5, "type": "RSSecondary", "tags": { "data_center": "nyc" } }, { "address": "c:27017", "avg_rtt_ms": 100, "type": "RSSecondary", "tags": { "data_center": "nyc" } } ] }, "operation": "read", "read_preference": { "mode": "Secondary", "tag_sets": [ { "data_center": "sf" } ] }, "suitable_servers": [], "in_latency_window": [] } write/000077500000000000000000000000001462766011000343115ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/server_selection/server_selection/ReplicaSetNoPrimarySecondaryPreferred.json000066400000000000000000000011631462766011000407730ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/server_selection/server_selection/ReplicaSetNoPrimary/write{ "topology_description": { "type": "ReplicaSetNoPrimary", "servers": [ { "address": "b:27017", "avg_rtt_ms": 5, "type": "RSSecondary", "tags": { "data_center": "nyc" } }, { "address": "c:27017", "avg_rtt_ms": 100, "type": "RSSecondary", "tags": { "data_center": "nyc" } } ] }, "operation": "write", "read_preference": { "mode": "SecondaryPreferred", "tag_sets": [ { "data_center": "nyc" } ] }, "suitable_servers": [], "in_latency_window": [] } mongodb-mongo-python-driver-509e9b7/test/server_selection/server_selection/ReplicaSetWithPrimary/000077500000000000000000000000001462766011000335755ustar00rootroot00000000000000read/000077500000000000000000000000001462766011000344315ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/server_selection/server_selection/ReplicaSetWithPrimaryNearest.json000066400000000000000000000025271462766011000367330ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/server_selection/server_selection/ReplicaSetWithPrimary/read{ "topology_description": { "type": "ReplicaSetWithPrimary", "servers": [ { "address": "b:27017", "avg_rtt_ms": 5, "type": "RSSecondary", "tags": { "data_center": "nyc" } }, { "address": "c:27017", "avg_rtt_ms": 100, "type": "RSSecondary", "tags": { "data_center": "nyc" } }, { "address": "a:27017", "avg_rtt_ms": 26, "type": "RSPrimary", "tags": { "data_center": "nyc" } } ] }, "operation": "read", "read_preference": { "mode": "Nearest", "tag_sets": [ { "data_center": "nyc" } ] }, "suitable_servers": [ { "address": "b:27017", "avg_rtt_ms": 5, "type": "RSSecondary", "tags": { "data_center": "nyc" } }, { "address": "a:27017", "avg_rtt_ms": 26, "type": "RSPrimary", "tags": { "data_center": "nyc" } }, { "address": "c:27017", "avg_rtt_ms": 100, "type": "RSSecondary", "tags": { "data_center": "nyc" } } ], "in_latency_window": [ { "address": "b:27017", "avg_rtt_ms": 5, "type": "RSSecondary", "tags": { "data_center": "nyc" } } ] } Nearest_multiple.json000066400000000000000000000027531462766011000406470ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/server_selection/server_selection/ReplicaSetWithPrimary/read{ "topology_description": { "type": "ReplicaSetWithPrimary", "servers": [ { "address": "b:27017", "avg_rtt_ms": 10, "type": "RSSecondary", "tags": { "data_center": "nyc" } }, { "address": "c:27017", "avg_rtt_ms": 100, "type": "RSSecondary", "tags": { "data_center": "nyc" } }, { "address": "a:27017", "avg_rtt_ms": 20, "type": "RSPrimary", "tags": { "data_center": "nyc" } } ] }, "operation": "read", "read_preference": { "mode": "Nearest", "tag_sets": [ { "data_center": "nyc" } ] }, "suitable_servers": [ { "address": "b:27017", "avg_rtt_ms": 10, "type": "RSSecondary", "tags": { "data_center": "nyc" } }, { "address": "a:27017", "avg_rtt_ms": 20, "type": "RSPrimary", "tags": { "data_center": "nyc" } }, { "address": "c:27017", "avg_rtt_ms": 100, "type": "RSSecondary", "tags": { "data_center": "nyc" } } ], "in_latency_window": [ { "address": "b:27017", "avg_rtt_ms": 10, "type": "RSSecondary", "tags": { "data_center": "nyc" } }, { "address": "a:27017", "avg_rtt_ms": 20, "type": "RSPrimary", "tags": { "data_center": "nyc" } } ] } Nearest_non_matching.json000066400000000000000000000014111462766011000414460ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/server_selection/server_selection/ReplicaSetWithPrimary/read{ "topology_description": { "type": "ReplicaSetWithPrimary", "servers": [ { "address": "b:27017", "avg_rtt_ms": 5, "type": "RSSecondary", "tags": { "data_center": "nyc" } }, { "address": "c:27017", "avg_rtt_ms": 100, "type": "RSSecondary", "tags": { "data_center": "nyc" } }, { "address": "a:27017", "avg_rtt_ms": 26, "type": "RSPrimary", "tags": { "data_center": "nyc" } } ] }, "operation": "read", "read_preference": { "mode": "Nearest", "tag_sets": [ { "data_center": "sf" } ] }, "suitable_servers": [], "in_latency_window": [] } Primary.json000066400000000000000000000017521462766011000367540ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/server_selection/server_selection/ReplicaSetWithPrimary/read{ "topology_description": { "type": "ReplicaSetWithPrimary", "servers": [ { "address": "b:27017", "avg_rtt_ms": 5, "type": "RSSecondary", "tags": { "data_center": "nyc" } }, { "address": "c:27017", "avg_rtt_ms": 100, "type": "RSSecondary", "tags": { "data_center": "nyc" } }, { "address": "a:27017", "avg_rtt_ms": 26, "type": "RSPrimary", "tags": { "data_center": "nyc" } } ] }, "operation": "read", "read_preference": { "mode": "Primary" }, "suitable_servers": [ { "address": "a:27017", "avg_rtt_ms": 26, "type": "RSPrimary", "tags": { "data_center": "nyc" } } ], "in_latency_window": [ { "address": "a:27017", "avg_rtt_ms": 26, "type": "RSPrimary", "tags": { "data_center": "nyc" } } ] } PrimaryPreferred.json000066400000000000000000000020251462766011000406050ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/server_selection/server_selection/ReplicaSetWithPrimary/read{ "topology_description": { "type": "ReplicaSetWithPrimary", "servers": [ { "address": "b:27017", "avg_rtt_ms": 5, "type": "RSSecondary", "tags": { "data_center": "nyc" } }, { "address": "c:27017", "avg_rtt_ms": 100, "type": "RSSecondary", "tags": { "data_center": "nyc" } }, { "address": "a:27017", "avg_rtt_ms": 26, "type": "RSPrimary", "tags": { "data_center": "nyc" } } ] }, "operation": "read", "read_preference": { "mode": "PrimaryPreferred", "tag_sets": [ {} ] }, "suitable_servers": [ { "address": "a:27017", "avg_rtt_ms": 26, "type": "RSPrimary", "tags": { "data_center": "nyc" } } ], "in_latency_window": [ { "address": "a:27017", "avg_rtt_ms": 26, "type": "RSPrimary", "tags": { "data_center": "nyc" } } ] } PrimaryPreferred_non_matching.json000066400000000000000000000020701462766011000433310ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/server_selection/server_selection/ReplicaSetWithPrimary/read{ "topology_description": { "type": "ReplicaSetWithPrimary", "servers": [ { "address": "b:27017", "avg_rtt_ms": 5, "type": "RSSecondary", "tags": { "data_center": "nyc" } }, { "address": "c:27017", "avg_rtt_ms": 100, "type": "RSSecondary", "tags": { "data_center": "nyc" } }, { "address": "a:27017", "avg_rtt_ms": 26, "type": "RSPrimary", "tags": { "data_center": "nyc" } } ] }, "operation": "read", "read_preference": { "mode": "PrimaryPreferred", "tag_sets": [ { "data_center": "sf" } ] }, "suitable_servers": [ { "address": "a:27017", "avg_rtt_ms": 26, "type": "RSPrimary", "tags": { "data_center": "nyc" } } ], "in_latency_window": [ { "address": "a:27017", "avg_rtt_ms": 26, "type": "RSPrimary", "tags": { "data_center": "nyc" } } ] } Secondary.json000066400000000000000000000023101462766011000372470ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/server_selection/server_selection/ReplicaSetWithPrimary/read{ "topology_description": { "type": "ReplicaSetWithPrimary", "servers": [ { "address": "b:27017", "avg_rtt_ms": 5, "type": "RSSecondary", "tags": { "data_center": "nyc" } }, { "address": "c:27017", "avg_rtt_ms": 100, "type": "RSSecondary", "tags": { "data_center": "nyc" } }, { "address": "a:27017", "avg_rtt_ms": 26, "type": "RSPrimary", "tags": { "data_center": "nyc" } } ] }, "operation": "read", "read_preference": { "mode": "Secondary", "tag_sets": [ { "data_center": "nyc" } ] }, "suitable_servers": [ { "address": "b:27017", "avg_rtt_ms": 5, "type": "RSSecondary", "tags": { "data_center": "nyc" } }, { "address": "c:27017", "avg_rtt_ms": 100, "type": "RSSecondary", "tags": { "data_center": "nyc" } } ], "in_latency_window": [ { "address": "b:27017", "avg_rtt_ms": 5, "type": "RSSecondary", "tags": { "data_center": "nyc" } } ] } SecondaryPreferred.json000066400000000000000000000023211462766011000411100ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/server_selection/server_selection/ReplicaSetWithPrimary/read{ "topology_description": { "type": "ReplicaSetWithPrimary", "servers": [ { "address": "b:27017", "avg_rtt_ms": 5, "type": "RSSecondary", "tags": { "data_center": "nyc" } }, { "address": "c:27017", "avg_rtt_ms": 100, "type": "RSSecondary", "tags": { "data_center": "nyc" } }, { "address": "a:27017", "avg_rtt_ms": 26, "type": "RSPrimary", "tags": { "data_center": "nyc" } } ] }, "operation": "read", "read_preference": { "mode": "SecondaryPreferred", "tag_sets": [ { "data_center": "nyc" } ] }, "suitable_servers": [ { "address": "b:27017", "avg_rtt_ms": 5, "type": "RSSecondary", "tags": { "data_center": "nyc" } }, { "address": "c:27017", "avg_rtt_ms": 100, "type": "RSSecondary", "tags": { "data_center": "nyc" } } ], "in_latency_window": [ { "address": "b:27017", "avg_rtt_ms": 5, "type": "RSSecondary", "tags": { "data_center": "nyc" } } ] } SecondaryPreferred_non_matching.json000066400000000000000000000020721462766011000436370ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/server_selection/server_selection/ReplicaSetWithPrimary/read{ "topology_description": { "type": "ReplicaSetWithPrimary", "servers": [ { "address": "b:27017", "avg_rtt_ms": 5, "type": "RSSecondary", "tags": { "data_center": "nyc" } }, { "address": "c:27017", "avg_rtt_ms": 100, "type": "RSSecondary", "tags": { "data_center": "nyc" } }, { "address": "a:27017", "avg_rtt_ms": 26, "type": "RSPrimary", "tags": { "data_center": "nyc" } } ] }, "operation": "read", "read_preference": { "mode": "SecondaryPreferred", "tag_sets": [ { "data_center": "sf" } ] }, "suitable_servers": [ { "address": "a:27017", "avg_rtt_ms": 26, "type": "RSPrimary", "tags": { "data_center": "nyc" } } ], "in_latency_window": [ { "address": "a:27017", "avg_rtt_ms": 26, "type": "RSPrimary", "tags": { "data_center": "nyc" } } ] } SecondaryPreferred_tags.json000066400000000000000000000016231462766011000421320ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/server_selection/server_selection/ReplicaSetWithPrimary/read{ "topology_description": { "type": "ReplicaSetWithPrimary", "servers": [ { "address": "a:27017", "avg_rtt_ms": 5, "type": "RSPrimary", "tags": { "data_center": "nyc" } }, { "address": "b:27017", "avg_rtt_ms": 5, "type": "RSSecondary", "tags": { "data_center": "sf" } } ] }, "operation": "read", "read_preference": { "mode": "SecondaryPreferred", "tag_sets": [ { "data_center": "nyc" } ] }, "suitable_servers": [ { "address": "a:27017", "avg_rtt_ms": 5, "type": "RSPrimary", "tags": { "data_center": "nyc" } } ], "in_latency_window": [ { "address": "a:27017", "avg_rtt_ms": 5, "type": "RSPrimary", "tags": { "data_center": "nyc" } } ] } Secondary_non_matching.json000066400000000000000000000014131462766011000417760ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/server_selection/server_selection/ReplicaSetWithPrimary/read{ "topology_description": { "type": "ReplicaSetWithPrimary", "servers": [ { "address": "b:27017", "avg_rtt_ms": 5, "type": "RSSecondary", "tags": { "data_center": "nyc" } }, { "address": "c:27017", "avg_rtt_ms": 100, "type": "RSSecondary", "tags": { "data_center": "nyc" } }, { "address": "a:27017", "avg_rtt_ms": 26, "type": "RSPrimary", "tags": { "data_center": "nyc" } } ] }, "operation": "read", "read_preference": { "mode": "Secondary", "tag_sets": [ { "data_center": "sf" } ] }, "suitable_servers": [], "in_latency_window": [] } write/000077500000000000000000000000001462766011000346505ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/server_selection/server_selection/ReplicaSetWithPrimarySecondaryPreferred.json000066400000000000000000000020741462766011000413340ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/server_selection/server_selection/ReplicaSetWithPrimary/write{ "topology_description": { "type": "ReplicaSetWithPrimary", "servers": [ { "address": "b:27017", "avg_rtt_ms": 5, "type": "RSSecondary", "tags": { "data_center": "nyc" } }, { "address": "c:27017", "avg_rtt_ms": 100, "type": "RSSecondary", "tags": { "data_center": "nyc" } }, { "address": "a:27017", "avg_rtt_ms": 26, "type": "RSPrimary", "tags": { "data_center": "nyc" } } ] }, "operation": "write", "read_preference": { "mode": "SecondaryPreferred", "tag_sets": [ { "data_center": "nyc" } ] }, "suitable_servers": [ { "address": "a:27017", "avg_rtt_ms": 26, "type": "RSPrimary", "tags": { "data_center": "nyc" } } ], "in_latency_window": [ { "address": "a:27017", "avg_rtt_ms": 26, "type": "RSPrimary", "tags": { "data_center": "nyc" } } ] } mongodb-mongo-python-driver-509e9b7/test/server_selection/server_selection/Sharded/000077500000000000000000000000001462766011000307145ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/server_selection/server_selection/Sharded/read/000077500000000000000000000000001462766011000316275ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/server_selection/server_selection/Sharded/read/Nearest.json000066400000000000000000000013421462766011000341230ustar00rootroot00000000000000{ "topology_description": { "type": "Sharded", "servers": [ { "address": "g:27017", "avg_rtt_ms": 5, "type": "Mongos" }, { "address": "h:27017", "avg_rtt_ms": 35, "type": "Mongos" } ] }, "operation": "read", "read_preference": { "mode": "Nearest", "tag_sets": [ { "data_center": "nyc" } ] }, "suitable_servers": [ { "address": "g:27017", "avg_rtt_ms": 5, "type": "Mongos" }, { "address": "h:27017", "avg_rtt_ms": 35, "type": "Mongos" } ], "in_latency_window": [ { "address": "g:27017", "avg_rtt_ms": 5, "type": "Mongos" } ] } mongodb-mongo-python-driver-509e9b7/test/server_selection/server_selection/Sharded/read/Primary.json000066400000000000000000000012341462766011000341450ustar00rootroot00000000000000{ "topology_description": { "type": "Sharded", "servers": [ { "address": "g:27017", "avg_rtt_ms": 5, "type": "Mongos" }, { "address": "h:27017", "avg_rtt_ms": 35, "type": "Mongos" } ] }, "operation": "read", "read_preference": { "mode": "Primary" }, "suitable_servers": [ { "address": "g:27017", "avg_rtt_ms": 5, "type": "Mongos" }, { "address": "h:27017", "avg_rtt_ms": 35, "type": "Mongos" } ], "in_latency_window": [ { "address": "g:27017", "avg_rtt_ms": 5, "type": "Mongos" } ] } PrimaryPreferred.json000066400000000000000000000013531462766011000357270ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/server_selection/server_selection/Sharded/read{ "topology_description": { "type": "Sharded", "servers": [ { "address": "g:27017", "avg_rtt_ms": 5, "type": "Mongos" }, { "address": "h:27017", "avg_rtt_ms": 35, "type": "Mongos" } ] }, "operation": "read", "read_preference": { "mode": "PrimaryPreferred", "tag_sets": [ { "data_center": "nyc" } ] }, "suitable_servers": [ { "address": "g:27017", "avg_rtt_ms": 5, "type": "Mongos" }, { "address": "h:27017", "avg_rtt_ms": 35, "type": "Mongos" } ], "in_latency_window": [ { "address": "g:27017", "avg_rtt_ms": 5, "type": "Mongos" } ] } Secondary.json000066400000000000000000000013441462766011000343740ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/server_selection/server_selection/Sharded/read{ "topology_description": { "type": "Sharded", "servers": [ { "address": "g:27017", "avg_rtt_ms": 5, "type": "Mongos" }, { "address": "h:27017", "avg_rtt_ms": 35, "type": "Mongos" } ] }, "operation": "read", "read_preference": { "mode": "Secondary", "tag_sets": [ { "data_center": "nyc" } ] }, "suitable_servers": [ { "address": "g:27017", "avg_rtt_ms": 5, "type": "Mongos" }, { "address": "h:27017", "avg_rtt_ms": 35, "type": "Mongos" } ], "in_latency_window": [ { "address": "g:27017", "avg_rtt_ms": 5, "type": "Mongos" } ] } SecondaryPreferred.json000066400000000000000000000013551462766011000362350ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/server_selection/server_selection/Sharded/read{ "topology_description": { "type": "Sharded", "servers": [ { "address": "g:27017", "avg_rtt_ms": 5, "type": "Mongos" }, { "address": "h:27017", "avg_rtt_ms": 35, "type": "Mongos" } ] }, "operation": "read", "read_preference": { "mode": "SecondaryPreferred", "tag_sets": [ { "data_center": "nyc" } ] }, "suitable_servers": [ { "address": "g:27017", "avg_rtt_ms": 5, "type": "Mongos" }, { "address": "h:27017", "avg_rtt_ms": 35, "type": "Mongos" } ], "in_latency_window": [ { "address": "g:27017", "avg_rtt_ms": 5, "type": "Mongos" } ] } mongodb-mongo-python-driver-509e9b7/test/server_selection/server_selection/Sharded/write/000077500000000000000000000000001462766011000320465ustar00rootroot00000000000000Nearest.json000066400000000000000000000013431462766011000342640ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/server_selection/server_selection/Sharded/write{ "topology_description": { "type": "Sharded", "servers": [ { "address": "g:27017", "avg_rtt_ms": 5, "type": "Mongos" }, { "address": "h:27017", "avg_rtt_ms": 35, "type": "Mongos" } ] }, "operation": "write", "read_preference": { "mode": "Nearest", "tag_sets": [ { "data_center": "nyc" } ] }, "suitable_servers": [ { "address": "g:27017", "avg_rtt_ms": 5, "type": "Mongos" }, { "address": "h:27017", "avg_rtt_ms": 35, "type": "Mongos" } ], "in_latency_window": [ { "address": "g:27017", "avg_rtt_ms": 5, "type": "Mongos" } ] } Primary.json000066400000000000000000000012351462766011000343060ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/server_selection/server_selection/Sharded/write{ "topology_description": { "type": "Sharded", "servers": [ { "address": "g:27017", "avg_rtt_ms": 5, "type": "Mongos" }, { "address": "h:27017", "avg_rtt_ms": 35, "type": "Mongos" } ] }, "operation": "write", "read_preference": { "mode": "Primary" }, "suitable_servers": [ { "address": "g:27017", "avg_rtt_ms": 5, "type": "Mongos" }, { "address": "h:27017", "avg_rtt_ms": 35, "type": "Mongos" } ], "in_latency_window": [ { "address": "g:27017", "avg_rtt_ms": 5, "type": "Mongos" } ] } PrimaryPreferred.json000066400000000000000000000013541462766011000361470ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/server_selection/server_selection/Sharded/write{ "topology_description": { "type": "Sharded", "servers": [ { "address": "g:27017", "avg_rtt_ms": 5, "type": "Mongos" }, { "address": "h:27017", "avg_rtt_ms": 35, "type": "Mongos" } ] }, "operation": "write", "read_preference": { "mode": "PrimaryPreferred", "tag_sets": [ { "data_center": "nyc" } ] }, "suitable_servers": [ { "address": "g:27017", "avg_rtt_ms": 5, "type": "Mongos" }, { "address": "h:27017", "avg_rtt_ms": 35, "type": "Mongos" } ], "in_latency_window": [ { "address": "g:27017", "avg_rtt_ms": 5, "type": "Mongos" } ] } Secondary.json000066400000000000000000000013451462766011000346140ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/server_selection/server_selection/Sharded/write{ "topology_description": { "type": "Sharded", "servers": [ { "address": "g:27017", "avg_rtt_ms": 5, "type": "Mongos" }, { "address": "h:27017", "avg_rtt_ms": 35, "type": "Mongos" } ] }, "operation": "write", "read_preference": { "mode": "Secondary", "tag_sets": [ { "data_center": "nyc" } ] }, "suitable_servers": [ { "address": "g:27017", "avg_rtt_ms": 5, "type": "Mongos" }, { "address": "h:27017", "avg_rtt_ms": 35, "type": "Mongos" } ], "in_latency_window": [ { "address": "g:27017", "avg_rtt_ms": 5, "type": "Mongos" } ] } SecondaryPreferred.json000066400000000000000000000013561462766011000364550ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/server_selection/server_selection/Sharded/write{ "topology_description": { "type": "Sharded", "servers": [ { "address": "g:27017", "avg_rtt_ms": 5, "type": "Mongos" }, { "address": "h:27017", "avg_rtt_ms": 35, "type": "Mongos" } ] }, "operation": "write", "read_preference": { "mode": "SecondaryPreferred", "tag_sets": [ { "data_center": "nyc" } ] }, "suitable_servers": [ { "address": "g:27017", "avg_rtt_ms": 5, "type": "Mongos" }, { "address": "h:27017", "avg_rtt_ms": 35, "type": "Mongos" } ], "in_latency_window": [ { "address": "g:27017", "avg_rtt_ms": 5, "type": "Mongos" } ] } mongodb-mongo-python-driver-509e9b7/test/server_selection/server_selection/Single/000077500000000000000000000000001462766011000305635ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/server_selection/server_selection/Single/read/000077500000000000000000000000001462766011000314765ustar00rootroot00000000000000SecondaryPreferred.json000066400000000000000000000013431462766011000361010ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/server_selection/server_selection/Single/read{ "topology_description": { "type": "Single", "servers": [ { "address": "a:27017", "avg_rtt_ms": 5, "type": "Standalone", "tags": { "data_center": "dc" } } ] }, "operation": "read", "read_preference": { "mode": "SecondaryPreferred", "tag_sets": [ { "data_center": "nyc" } ] }, "suitable_servers": [ { "address": "a:27017", "avg_rtt_ms": 5, "type": "Standalone", "tags": { "data_center": "dc" } } ], "in_latency_window": [ { "address": "a:27017", "avg_rtt_ms": 5, "type": "Standalone", "tags": { "data_center": "dc" } } ] } mongodb-mongo-python-driver-509e9b7/test/server_selection/server_selection/Single/write/000077500000000000000000000000001462766011000317155ustar00rootroot00000000000000SecondaryPreferred.json000066400000000000000000000013441462766011000363210ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/server_selection/server_selection/Single/write{ "topology_description": { "type": "Single", "servers": [ { "address": "a:27017", "avg_rtt_ms": 5, "type": "Standalone", "tags": { "data_center": "dc" } } ] }, "operation": "write", "read_preference": { "mode": "SecondaryPreferred", "tag_sets": [ { "data_center": "nyc" } ] }, "suitable_servers": [ { "address": "a:27017", "avg_rtt_ms": 5, "type": "Standalone", "tags": { "data_center": "dc" } } ], "in_latency_window": [ { "address": "a:27017", "avg_rtt_ms": 5, "type": "Standalone", "tags": { "data_center": "dc" } } ] } mongodb-mongo-python-driver-509e9b7/test/server_selection/server_selection/Unknown/000077500000000000000000000000001462766011000310015ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/server_selection/server_selection/Unknown/read/000077500000000000000000000000001462766011000317145ustar00rootroot00000000000000SecondaryPreferred.json000066400000000000000000000004341462766011000363170ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/server_selection/server_selection/Unknown/read{ "topology_description": { "type": "Unknown", "servers": [] }, "operation": "read", "read_preference": { "mode": "SecondaryPreferred", "tag_sets": [ { "data_center": "nyc" } ] }, "suitable_servers": [], "in_latency_window": [] } mongodb-mongo-python-driver-509e9b7/test/server_selection/server_selection/Unknown/read/ghost.json000066400000000000000000000004611462766011000337340ustar00rootroot00000000000000{ "topology_description": { "type": "Unknown", "servers": [ { "address": "a:27017", "avg_rtt_ms": 5, "type": "RSGhost" } ] }, "operation": "read", "read_preference": { "mode": "Nearest" }, "suitable_servers": [], "in_latency_window": [] } mongodb-mongo-python-driver-509e9b7/test/server_selection/server_selection/Unknown/write/000077500000000000000000000000001462766011000321335ustar00rootroot00000000000000SecondaryPreferred.json000066400000000000000000000004351462766011000365370ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/server_selection/server_selection/Unknown/write{ "topology_description": { "type": "Unknown", "servers": [] }, "operation": "write", "read_preference": { "mode": "SecondaryPreferred", "tag_sets": [ { "data_center": "nyc" } ] }, "suitable_servers": [], "in_latency_window": [] } mongodb-mongo-python-driver-509e9b7/test/server_selection/server_selection/Unknown/write/ghost.json000066400000000000000000000004621462766011000341540ustar00rootroot00000000000000{ "topology_description": { "type": "Unknown", "servers": [ { "address": "a:27017", "avg_rtt_ms": 5, "type": "RSGhost" } ] }, "operation": "write", "read_preference": { "mode": "Nearest" }, "suitable_servers": [], "in_latency_window": [] } mongodb-mongo-python-driver-509e9b7/test/server_selection_logging/000077500000000000000000000000001462766011000254755ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/server_selection_logging/load-balanced.json000066400000000000000000000045771462766011000310530ustar00rootroot00000000000000{ "description": "server-selection-logging", "schemaVersion": "1.13", "runOnRequirements": [ { "topologies": [ "load-balanced" ] } ], "createEntities": [ { "client": { "id": "client", "uriOptions": { "heartbeatFrequencyMS": 500 }, "observeLogMessages": { "serverSelection": "debug" }, "observeEvents": [ "serverDescriptionChangedEvent" ] } }, { "database": { "id": "database", "client": "client", "databaseName": "logging-tests" } }, { "collection": { "id": "collection", "database": "database", "collectionName": "server-selection" } } ], "tests": [ { "description": "A successful operation - load balanced cluster", "operations": [ { "name": "waitForEvent", "object": "testRunner", "arguments": { "client": "client", "event": { "serverDescriptionChangedEvent": { "newDescription": { "type": "LoadBalancer" } } }, "count": 1 } }, { "name": "insertOne", "object": "collection", "arguments": { "document": { "x": 1 } } } ], "expectLogMessages": [ { "client": "client", "messages": [ { "level": "debug", "component": "serverSelection", "data": { "message": "Server selection started", "selector": { "$$exists": true }, "operation": "insert", "topologyDescription": { "$$exists": true } } }, { "level": "debug", "component": "serverSelection", "data": { "message": "Server selection succeeded", "selector": { "$$exists": true }, "operation": "insert", "topologyDescription": { "$$exists": true } } } ] } ] } ] } mongodb-mongo-python-driver-509e9b7/test/server_selection_logging/operation-id.json000066400000000000000000000125611462766011000307670ustar00rootroot00000000000000{ "description": "operation-id", "schemaVersion": "1.14", "runOnRequirements": [ { "topologies": [ "single" ] } ], "createEntities": [ { "client": { "id": "client", "uriOptions": { "retryWrites": false, "heartbeatFrequencyMS": 500, "appName": "loggingClient", "serverSelectionTimeoutMS": 2000 }, "observeLogMessages": { "serverSelection": "debug" }, "observeEvents": [ "serverDescriptionChangedEvent", "topologyDescriptionChangedEvent" ] } }, { "database": { "id": "database", "client": "client", "databaseName": "logging-tests" } }, { "collection": { "id": "collection", "database": "database", "collectionName": "server-selection" } }, { "client": { "id": "failPointClient" } } ], "tests": [ { "description": "Successful bulkWrite operation: log messages have operationIds", "operations": [ { "name": "waitForEvent", "object": "testRunner", "arguments": { "client": "client", "event": { "topologyDescriptionChangedEvent": {} }, "count": 2 } }, { "name": "bulkWrite", "object": "collection", "arguments": { "requests": [ { "insertOne": { "document": { "x": 1 } } } ] } } ], "expectLogMessages": [ { "client": "client", "messages": [ { "level": "debug", "component": "serverSelection", "data": { "message": "Server selection started", "operationId": { "$$type": [ "int", "long" ] }, "operation": "insert" } }, { "level": "debug", "component": "serverSelection", "data": { "message": "Server selection succeeded", "operationId": { "$$type": [ "int", "long" ] }, "operation": "insert" } } ] } ] }, { "description": "Failed bulkWrite operation: log messages have operationIds", "runOnRequirements": [ { "minServerVersion": "4.4" } ], "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": "alwaysOn", "data": { "failCommands": [ "hello", "ismaster" ], "appName": "loggingClient", "closeConnection": true } } } }, { "name": "waitForEvent", "object": "testRunner", "arguments": { "client": "client", "event": { "serverDescriptionChangedEvent": { "newDescription": { "type": "Unknown" } } }, "count": 1 } }, { "name": "bulkWrite", "object": "collection", "arguments": { "requests": [ { "insertOne": { "document": { "x": 1 } } } ] }, "expectError": { "isClientError": true } } ], "expectLogMessages": [ { "client": "client", "messages": [ { "level": "debug", "component": "serverSelection", "data": { "message": "Server selection started", "operationId": { "$$type": [ "int", "long" ] }, "operation": "insert" } }, { "level": "debug", "component": "serverSelection", "data": { "message": "Waiting for suitable server to become available", "operationId": { "$$type": [ "int", "long" ] }, "operation": "insert" } }, { "level": "debug", "component": "serverSelection", "data": { "message": "Server selection failed", "operationId": { "$$type": [ "int", "long" ] }, "operation": "insert" } } ] } ] } ] } mongodb-mongo-python-driver-509e9b7/test/server_selection_logging/replica-set.json000066400000000000000000000125761462766011000306130ustar00rootroot00000000000000{ "description": "replica-set-logging", "schemaVersion": "1.14", "runOnRequirements": [ { "topologies": [ "replicaset" ] } ], "createEntities": [ { "client": { "id": "client", "uriOptions": { "retryWrites": false, "heartbeatFrequencyMS": 500, "serverSelectionTimeoutMS": 2000 }, "observeLogMessages": { "serverSelection": "debug" }, "observeEvents": [ "serverDescriptionChangedEvent", "topologyDescriptionChangedEvent" ] } }, { "database": { "id": "database", "client": "client", "databaseName": "logging-tests" } }, { "collection": { "id": "collection", "database": "database", "collectionName": "server-selection" } }, { "client": { "id": "failPointClient" } }, { "collection": { "id": "unsatisfiableRPColl", "database": "database", "collectionName": "unsatisfiableRPColl", "collectionOptions": { "readPreference": { "mode": "Secondary", "tagSets": [ { "nonexistenttag": "a" } ] } } } } ], "tests": [ { "description": "A successful operation", "operations": [ { "name": "waitForEvent", "object": "testRunner", "arguments": { "client": "client", "event": { "topologyDescriptionChangedEvent": {} }, "count": 4 } }, { "name": "insertOne", "object": "collection", "arguments": { "document": { "x": 1 } } } ], "expectLogMessages": [ { "client": "client", "messages": [ { "level": "debug", "component": "serverSelection", "data": { "message": "Server selection started", "selector": { "$$exists": true }, "operation": "insert", "topologyDescription": { "$$exists": true } } }, { "level": "debug", "component": "serverSelection", "data": { "message": "Server selection succeeded", "selector": { "$$exists": true }, "operation": "insert", "topologyDescription": { "$$exists": true }, "serverHost": { "$$type": "string" }, "serverPort": { "$$type": [ "int", "long" ] } } } ] } ] }, { "description": "Server selection fails due to unsatisfiable read preference", "runOnRequirements": [ { "minServerVersion": "4.0" } ], "operations": [ { "name": "waitForEvent", "object": "testRunner", "arguments": { "client": "client", "event": { "topologyDescriptionChangedEvent": {} }, "count": 4 } }, { "name": "find", "object": "unsatisfiableRPColl", "arguments": { "filter": { "x": 1 } }, "expectError": { "isClientError": true } } ], "expectLogMessages": [ { "client": "client", "messages": [ { "level": "debug", "component": "serverSelection", "data": { "message": "Server selection started", "selector": { "$$exists": true }, "operation": "find", "topologyDescription": { "$$exists": true } } }, { "level": "debug", "component": "serverSelection", "data": { "message": "Waiting for suitable server to become available", "selector": { "$$exists": true }, "operation": "find", "topologyDescription": { "$$exists": true }, "remainingTimeMS": { "$$type": [ "int", "long" ] } } }, { "level": "debug", "component": "serverSelection", "data": { "message": "Server selection failed", "selector": { "$$exists": true }, "operation": "find", "topologyDescription": { "$$exists": true }, "failure": { "$$exists": true } } } ] } ] } ] } mongodb-mongo-python-driver-509e9b7/test/server_selection_logging/sharded.json000066400000000000000000000133141462766011000300040ustar00rootroot00000000000000{ "description": "server-selection-logging", "schemaVersion": "1.14", "runOnRequirements": [ { "topologies": [ "sharded" ] } ], "createEntities": [ { "client": { "id": "client", "uriOptions": { "retryWrites": false, "heartbeatFrequencyMS": 500, "appName": "loggingClient", "serverSelectionTimeoutMS": 2000 }, "observeLogMessages": { "serverSelection": "debug" }, "observeEvents": [ "serverDescriptionChangedEvent", "topologyDescriptionChangedEvent" ], "useMultipleMongoses": false } }, { "database": { "id": "database", "client": "client", "databaseName": "logging-tests" } }, { "collection": { "id": "collection", "database": "database", "collectionName": "server-selection" } }, { "client": { "id": "failPointClient", "useMultipleMongoses": false } } ], "tests": [ { "description": "A successful operation", "operations": [ { "name": "waitForEvent", "object": "testRunner", "arguments": { "client": "client", "event": { "topologyDescriptionChangedEvent": {} }, "count": 2 } }, { "name": "insertOne", "object": "collection", "arguments": { "document": { "x": 1 } } } ], "expectLogMessages": [ { "client": "client", "messages": [ { "level": "debug", "component": "serverSelection", "data": { "message": "Server selection started", "selector": { "$$exists": true }, "operation": "insert", "topologyDescription": { "$$exists": true } } }, { "level": "debug", "component": "serverSelection", "data": { "message": "Server selection succeeded", "selector": { "$$exists": true }, "operation": "insert", "topologyDescription": { "$$exists": true }, "serverHost": { "$$type": "string" }, "serverPort": { "$$type": [ "int", "long" ] } } } ] } ] }, { "description": "Failure due to unreachable server", "runOnRequirements": [ { "minServerVersion": "4.4" } ], "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": "alwaysOn", "data": { "failCommands": [ "hello", "ismaster" ], "appName": "loggingClient", "closeConnection": true } } } }, { "name": "waitForEvent", "object": "testRunner", "arguments": { "client": "client", "event": { "serverDescriptionChangedEvent": { "newDescription": { "type": "Unknown" } } }, "count": 1 } }, { "name": "insertOne", "object": "collection", "arguments": { "document": { "x": 1 } }, "expectError": { "isClientError": true } } ], "expectLogMessages": [ { "client": "client", "messages": [ { "level": "debug", "component": "serverSelection", "data": { "message": "Server selection started", "selector": { "$$exists": true }, "operation": "insert", "topologyDescription": { "$$exists": true } } }, { "level": "debug", "component": "serverSelection", "data": { "message": "Waiting for suitable server to become available", "selector": { "$$exists": true }, "operation": "insert", "topologyDescription": { "$$exists": true }, "remainingTimeMS": { "$$type": [ "int", "long" ] } } }, { "level": "debug", "component": "serverSelection", "data": { "message": "Server selection failed", "selector": { "$$exists": true }, "operation": "insert", "topologyDescription": { "$$exists": true }, "failure": { "$$exists": true } } } ] } ] } ] } mongodb-mongo-python-driver-509e9b7/test/server_selection_logging/standalone.json000066400000000000000000000722621462766011000305310ustar00rootroot00000000000000{ "description": "standalone-logging", "schemaVersion": "1.14", "runOnRequirements": [ { "topologies": [ "single" ] } ], "createEntities": [ { "client": { "id": "client", "uriOptions": { "retryWrites": false, "heartbeatFrequencyMS": 500, "appName": "loggingClient", "serverSelectionTimeoutMS": 2000 }, "observeLogMessages": { "serverSelection": "debug" }, "observeEvents": [ "serverDescriptionChangedEvent", "topologyDescriptionChangedEvent" ] } }, { "database": { "id": "database", "client": "client", "databaseName": "logging-tests" } }, { "collection": { "id": "collection", "database": "database", "collectionName": "server-selection" } }, { "client": { "id": "failPointClient" } } ], "initialData": [ { "collectionName": "server-selection", "databaseName": "logging-tests", "documents": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 22 }, { "_id": 3, "x": 33 } ] } ], "tests": [ { "description": "A successful insert operation", "operations": [ { "name": "waitForEvent", "object": "testRunner", "arguments": { "client": "client", "event": { "topologyDescriptionChangedEvent": {} }, "count": 2 } }, { "name": "insertOne", "object": "collection", "arguments": { "document": { "x": 1 } } } ], "expectLogMessages": [ { "client": "client", "messages": [ { "level": "debug", "component": "serverSelection", "data": { "message": "Server selection started", "selector": { "$$exists": true }, "operation": "insert", "topologyDescription": { "$$exists": true } } }, { "level": "debug", "component": "serverSelection", "data": { "message": "Server selection succeeded", "selector": { "$$exists": true }, "operation": "insert", "topologyDescription": { "$$exists": true }, "serverHost": { "$$type": "string" }, "serverPort": { "$$type": [ "int", "long" ] } } } ] } ] }, { "description": "Failure due to unreachable server", "runOnRequirements": [ { "minServerVersion": "4.4" } ], "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "failPointClient", "failPoint": { "configureFailPoint": "failCommand", "mode": "alwaysOn", "data": { "failCommands": [ "hello", "ismaster" ], "appName": "loggingClient", "closeConnection": true } } } }, { "name": "waitForEvent", "object": "testRunner", "arguments": { "client": "client", "event": { "serverDescriptionChangedEvent": { "newDescription": { "type": "Unknown" } } }, "count": 1 } }, { "name": "insertOne", "object": "collection", "arguments": { "document": { "x": 1 } }, "expectError": { "isClientError": true } } ], "expectLogMessages": [ { "client": "client", "messages": [ { "level": "debug", "component": "serverSelection", "data": { "message": "Server selection started", "selector": { "$$exists": true }, "operation": "insert", "topologyDescription": { "$$exists": true } } }, { "level": "debug", "component": "serverSelection", "data": { "message": "Waiting for suitable server to become available", "selector": { "$$exists": true }, "operation": "insert", "topologyDescription": { "$$exists": true }, "remainingTimeMS": { "$$type": [ "int", "long" ] } } }, { "level": "debug", "component": "serverSelection", "data": { "message": "Server selection failed", "selector": { "$$exists": true }, "operation": "insert", "topologyDescription": { "$$exists": true }, "failure": { "$$exists": true } } } ] } ] }, { "description": "A successful find operation", "operations": [ { "name": "waitForEvent", "object": "testRunner", "arguments": { "client": "client", "event": { "topologyDescriptionChangedEvent": {} }, "count": 2 } }, { "name": "findOne", "object": "collection", "arguments": { "filter": { "x": 1 } } } ], "expectLogMessages": [ { "client": "client", "messages": [ { "level": "debug", "component": "serverSelection", "data": { "message": "Server selection started", "selector": { "$$exists": true }, "operation": "find", "topologyDescription": { "$$exists": true } } }, { "level": "debug", "component": "serverSelection", "data": { "message": "Server selection succeeded", "selector": { "$$exists": true }, "operation": "find", "topologyDescription": { "$$exists": true }, "serverHost": { "$$type": "string" }, "serverPort": { "$$type": [ "int", "long" ] } } } ] } ] }, { "description": "A successful findAndModify operation", "operations": [ { "name": "waitForEvent", "object": "testRunner", "arguments": { "client": "client", "event": { "topologyDescriptionChangedEvent": {} }, "count": 2 } }, { "name": "findOneAndReplace", "object": "collection", "arguments": { "filter": { "x": 1 }, "replacement": { "x": 11 } } } ], "expectLogMessages": [ { "client": "client", "messages": [ { "level": "debug", "component": "serverSelection", "data": { "message": "Server selection started", "selector": { "$$exists": true }, "operation": "findAndModify", "topologyDescription": { "$$exists": true } } }, { "level": "debug", "component": "serverSelection", "data": { "message": "Server selection succeeded", "selector": { "$$exists": true }, "operation": "findAndModify", "topologyDescription": { "$$exists": true }, "serverHost": { "$$type": "string" }, "serverPort": { "$$type": [ "int", "long" ] } } } ] } ] }, { "description": "A successful find and getMore operation", "operations": [ { "name": "waitForEvent", "object": "testRunner", "arguments": { "client": "client", "event": { "topologyDescriptionChangedEvent": {} }, "count": 2 } }, { "name": "find", "object": "collection", "arguments": { "batchSize": 3 } } ], "expectLogMessages": [ { "client": "client", "messages": [ { "level": "debug", "component": "serverSelection", "data": { "message": "Server selection started", "selector": { "$$exists": true }, "operation": "find", "topologyDescription": { "$$exists": true } } }, { "level": "debug", "component": "serverSelection", "data": { "message": "Server selection succeeded", "selector": { "$$exists": true }, "operation": "find", "topologyDescription": { "$$exists": true }, "serverHost": { "$$type": "string" }, "serverPort": { "$$type": [ "int", "long" ] } } }, { "level": "debug", "component": "serverSelection", "data": { "message": "Server selection started", "selector": { "$$exists": true }, "operation": "getMore", "topologyDescription": { "$$exists": true } } }, { "level": "debug", "component": "serverSelection", "data": { "message": "Server selection succeeded", "selector": { "$$exists": true }, "operation": "getMore", "topologyDescription": { "$$exists": true }, "serverHost": { "$$type": "string" }, "serverPort": { "$$type": [ "int", "long" ] } } } ] } ] }, { "description": "A successful aggregate operation", "operations": [ { "name": "waitForEvent", "object": "testRunner", "arguments": { "client": "client", "event": { "topologyDescriptionChangedEvent": {} }, "count": 2 } }, { "name": "aggregate", "object": "collection", "arguments": { "pipeline": [ { "$match": { "_id": { "$gt": 1 } } } ] } } ], "expectLogMessages": [ { "client": "client", "messages": [ { "level": "debug", "component": "serverSelection", "data": { "message": "Server selection started", "selector": { "$$exists": true }, "operation": "aggregate", "topologyDescription": { "$$exists": true } } }, { "level": "debug", "component": "serverSelection", "data": { "message": "Server selection succeeded", "selector": { "$$exists": true }, "operation": "aggregate", "topologyDescription": { "$$exists": true }, "serverHost": { "$$type": "string" }, "serverPort": { "$$type": [ "int", "long" ] } } } ] } ] }, { "description": "A successful count operation", "operations": [ { "name": "waitForEvent", "object": "testRunner", "arguments": { "client": "client", "event": { "topologyDescriptionChangedEvent": {} }, "count": 2 } }, { "name": "countDocuments", "object": "collection", "arguments": { "filter": {} } } ], "expectLogMessages": [ { "client": "client", "messages": [ { "level": "debug", "component": "serverSelection", "data": { "message": "Server selection started", "selector": { "$$exists": true }, "operation": "count", "topologyDescription": { "$$exists": true } } }, { "level": "debug", "component": "serverSelection", "data": { "message": "Server selection succeeded", "selector": { "$$exists": true }, "operation": "count", "topologyDescription": { "$$exists": true }, "serverHost": { "$$type": "string" }, "serverPort": { "$$type": [ "int", "long" ] } } } ] } ] }, { "description": "A successful distinct operation", "operations": [ { "name": "waitForEvent", "object": "testRunner", "arguments": { "client": "client", "event": { "topologyDescriptionChangedEvent": {} }, "count": 2 } }, { "name": "distinct", "object": "collection", "arguments": { "fieldName": "x", "filter": {} } } ], "expectLogMessages": [ { "client": "client", "messages": [ { "level": "debug", "component": "serverSelection", "data": { "message": "Server selection started", "selector": { "$$exists": true }, "operation": "distinct", "topologyDescription": { "$$exists": true } } }, { "level": "debug", "component": "serverSelection", "data": { "message": "Server selection succeeded", "selector": { "$$exists": true }, "operation": "distinct", "topologyDescription": { "$$exists": true }, "serverHost": { "$$type": "string" }, "serverPort": { "$$type": [ "int", "long" ] } } } ] } ] }, { "description": "Successful collection management operations", "operations": [ { "name": "waitForEvent", "object": "testRunner", "arguments": { "client": "client", "event": { "topologyDescriptionChangedEvent": {} }, "count": 2 } }, { "name": "createCollection", "object": "database", "arguments": { "collection": "foo" } }, { "name": "listCollections", "object": "database" }, { "name": "dropCollection", "object": "database", "arguments": { "collection": "foo" } } ], "expectLogMessages": [ { "client": "client", "messages": [ { "level": "debug", "component": "serverSelection", "data": { "message": "Server selection started", "selector": { "$$exists": true }, "operation": "create", "topologyDescription": { "$$exists": true } } }, { "level": "debug", "component": "serverSelection", "data": { "message": "Server selection succeeded", "selector": { "$$exists": true }, "operation": "create", "topologyDescription": { "$$exists": true }, "serverHost": { "$$type": "string" }, "serverPort": { "$$type": [ "int", "long" ] } } }, { "level": "debug", "component": "serverSelection", "data": { "message": "Server selection started", "selector": { "$$exists": true }, "operation": "listCollections", "topologyDescription": { "$$exists": true } } }, { "level": "debug", "component": "serverSelection", "data": { "message": "Server selection succeeded", "selector": { "$$exists": true }, "operation": "listCollections", "topologyDescription": { "$$exists": true }, "serverHost": { "$$type": "string" }, "serverPort": { "$$type": [ "int", "long" ] } } }, { "level": "debug", "component": "serverSelection", "data": { "message": "Server selection started", "selector": { "$$exists": true }, "operation": "drop", "topologyDescription": { "$$exists": true } } }, { "level": "debug", "component": "serverSelection", "data": { "message": "Server selection succeeded", "selector": { "$$exists": true }, "operation": "drop", "topologyDescription": { "$$exists": true }, "serverHost": { "$$type": "string" }, "serverPort": { "$$type": [ "int", "long" ] } } } ] } ] }, { "description": "Successful index operations", "operations": [ { "name": "waitForEvent", "object": "testRunner", "arguments": { "client": "client", "event": { "topologyDescriptionChangedEvent": {} }, "count": 2 } }, { "name": "createIndex", "object": "collection", "arguments": { "keys": { "x": 1 }, "name": "x_1" } }, { "name": "listIndexes", "object": "collection" }, { "name": "dropIndex", "object": "collection", "arguments": { "name": "x_1" } } ], "expectLogMessages": [ { "client": "client", "messages": [ { "level": "debug", "component": "serverSelection", "data": { "message": "Server selection started", "selector": { "$$exists": true }, "operation": "createIndexes", "topologyDescription": { "$$exists": true } } }, { "level": "debug", "component": "serverSelection", "data": { "message": "Server selection succeeded", "selector": { "$$exists": true }, "operation": "createIndexes", "topologyDescription": { "$$exists": true }, "serverHost": { "$$type": "string" }, "serverPort": { "$$type": [ "int", "long" ] } } }, { "level": "debug", "component": "serverSelection", "data": { "message": "Server selection started", "selector": { "$$exists": true }, "operation": "listIndexes", "topologyDescription": { "$$exists": true } } }, { "level": "debug", "component": "serverSelection", "data": { "message": "Server selection succeeded", "selector": { "$$exists": true }, "operation": "listIndexes", "topologyDescription": { "$$exists": true }, "serverHost": { "$$type": "string" }, "serverPort": { "$$type": [ "int", "long" ] } } }, { "level": "debug", "component": "serverSelection", "data": { "message": "Server selection started", "selector": { "$$exists": true }, "operation": "dropIndexes", "topologyDescription": { "$$exists": true } } }, { "level": "debug", "component": "serverSelection", "data": { "message": "Server selection succeeded", "selector": { "$$exists": true }, "operation": "dropIndexes", "topologyDescription": { "$$exists": true }, "serverHost": { "$$type": "string" }, "serverPort": { "$$type": [ "int", "long" ] } } } ] } ] }, { "description": "A successful update operation", "operations": [ { "name": "waitForEvent", "object": "testRunner", "arguments": { "client": "client", "event": { "topologyDescriptionChangedEvent": {} }, "count": 2 } }, { "name": "updateOne", "object": "collection", "arguments": { "filter": { "x": 1 }, "update": { "$inc": { "x": 1 } } } } ], "expectLogMessages": [ { "client": "client", "messages": [ { "level": "debug", "component": "serverSelection", "data": { "message": "Server selection started", "selector": { "$$exists": true }, "operation": "update", "topologyDescription": { "$$exists": true } } }, { "level": "debug", "component": "serverSelection", "data": { "message": "Server selection succeeded", "selector": { "$$exists": true }, "operation": "update", "topologyDescription": { "$$exists": true }, "serverHost": { "$$type": "string" }, "serverPort": { "$$type": [ "int", "long" ] } } } ] } ] }, { "description": "A successful delete operation", "operations": [ { "name": "waitForEvent", "object": "testRunner", "arguments": { "client": "client", "event": { "topologyDescriptionChangedEvent": {} }, "count": 2 } }, { "name": "deleteOne", "object": "collection", "arguments": { "filter": { "x": 1 } } } ], "expectLogMessages": [ { "client": "client", "messages": [ { "level": "debug", "component": "serverSelection", "data": { "message": "Server selection started", "selector": { "$$exists": true }, "operation": "delete", "topologyDescription": { "$$exists": true } } }, { "level": "debug", "component": "serverSelection", "data": { "message": "Server selection succeeded", "selector": { "$$exists": true }, "operation": "delete", "topologyDescription": { "$$exists": true }, "serverHost": { "$$type": "string" }, "serverPort": { "$$type": [ "int", "long" ] } } } ] } ] } ] } mongodb-mongo-python-driver-509e9b7/test/sessions/000077500000000000000000000000001462766011000222625ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/sessions/driver-sessions-dirty-session-errors.json000066400000000000000000000564211462766011000324500ustar00rootroot00000000000000{ "description": "driver-sessions-dirty-session-errors", "schemaVersion": "1.0", "runOnRequirements": [ { "minServerVersion": "4.0", "topologies": [ "replicaset" ] }, { "minServerVersion": "4.1.8", "topologies": [ "sharded-replicaset" ] } ], "createEntities": [ { "client": { "id": "client0", "useMultipleMongoses": false, "observeEvents": [ "commandStartedEvent" ] } }, { "database": { "id": "database0", "client": "client0", "databaseName": "session-tests" } }, { "collection": { "id": "collection0", "database": "database0", "collectionName": "test" } }, { "session": { "id": "session0", "client": "client0" } } ], "initialData": [ { "collectionName": "test", "databaseName": "session-tests", "documents": [ { "_id": 1 } ] } ], "tests": [ { "description": "Dirty explicit session is discarded (insert)", "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "client0", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "insert" ], "closeConnection": true } } } }, { "name": "assertSessionNotDirty", "object": "testRunner", "arguments": { "session": "session0" } }, { "name": "insertOne", "object": "collection0", "arguments": { "session": "session0", "document": { "_id": 2 } }, "expectResult": { "$$unsetOrMatches": { "insertedId": { "$$unsetOrMatches": 2 } } } }, { "name": "assertSessionDirty", "object": "testRunner", "arguments": { "session": "session0" } }, { "name": "insertOne", "object": "collection0", "arguments": { "session": "session0", "document": { "_id": 3 } }, "expectResult": { "$$unsetOrMatches": { "insertedId": { "$$unsetOrMatches": 3 } } } }, { "name": "assertSessionDirty", "object": "testRunner", "arguments": { "session": "session0" } }, { "name": "endSession", "object": "session0" }, { "name": "find", "object": "collection0", "arguments": { "filter": { "_id": -1 } }, "expectResult": [] }, { "name": "assertDifferentLsidOnLastTwoCommands", "object": "testRunner", "arguments": { "client": "client0" } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "insert": "test", "documents": [ { "_id": 2 } ], "ordered": true, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": 1 }, "commandName": "insert", "databaseName": "session-tests" } }, { "commandStartedEvent": { "command": { "insert": "test", "documents": [ { "_id": 2 } ], "ordered": true, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": 1 }, "commandName": "insert", "databaseName": "session-tests" } }, { "commandStartedEvent": { "command": { "insert": "test", "documents": [ { "_id": 3 } ], "ordered": true, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": 2 }, "commandName": "insert", "databaseName": "session-tests" } }, { "commandStartedEvent": { "command": { "find": "test", "filter": { "_id": -1 }, "lsid": { "$$type": "object" } }, "commandName": "find", "databaseName": "session-tests" } } ] } ], "outcome": [ { "collectionName": "test", "databaseName": "session-tests", "documents": [ { "_id": 1 }, { "_id": 2 }, { "_id": 3 } ] } ] }, { "description": "Dirty explicit session is discarded (findAndModify)", "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "client0", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "findAndModify" ], "closeConnection": true } } } }, { "name": "assertSessionNotDirty", "object": "testRunner", "arguments": { "session": "session0" } }, { "name": "findOneAndUpdate", "object": "collection0", "arguments": { "session": "session0", "filter": { "_id": 1 }, "update": { "$inc": { "x": 1 } }, "returnDocument": "Before" }, "expectResult": { "_id": 1 } }, { "name": "assertSessionDirty", "object": "testRunner", "arguments": { "session": "session0" } }, { "name": "endSession", "object": "session0" }, { "name": "find", "object": "collection0", "arguments": { "filter": { "_id": -1 } }, "expectResult": [] }, { "name": "assertDifferentLsidOnLastTwoCommands", "object": "testRunner", "arguments": { "client": "client0" } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "findAndModify": "test", "query": { "_id": 1 }, "update": { "$inc": { "x": 1 } }, "new": false, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": 1, "readConcern": { "$$exists": false }, "writeConcern": { "$$exists": false } }, "commandName": "findAndModify", "databaseName": "session-tests" } }, { "commandStartedEvent": { "command": { "findAndModify": "test", "query": { "_id": 1 }, "update": { "$inc": { "x": 1 } }, "new": false, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": 1, "readConcern": { "$$exists": false }, "writeConcern": { "$$exists": false } }, "commandName": "findAndModify", "databaseName": "session-tests" } }, { "commandStartedEvent": { "command": { "find": "test", "filter": { "_id": -1 }, "lsid": { "$$type": "object" } }, "commandName": "find", "databaseName": "session-tests" } } ] } ], "outcome": [ { "collectionName": "test", "databaseName": "session-tests", "documents": [ { "_id": 1, "x": 1 } ] } ] }, { "description": "Dirty implicit session is discarded (insert)", "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "client0", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "insert" ], "closeConnection": true } } } }, { "name": "insertOne", "object": "collection0", "arguments": { "document": { "_id": 2 } }, "expectResult": { "$$unsetOrMatches": { "insertedId": { "$$unsetOrMatches": 2 } } } }, { "name": "find", "object": "collection0", "arguments": { "filter": { "_id": -1 } }, "expectResult": [] }, { "name": "assertDifferentLsidOnLastTwoCommands", "object": "testRunner", "arguments": { "client": "client0" } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "insert": "test", "documents": [ { "_id": 2 } ], "ordered": true, "lsid": { "$$type": "object" }, "txnNumber": 1 }, "commandName": "insert", "databaseName": "session-tests" } }, { "commandStartedEvent": { "command": { "insert": "test", "documents": [ { "_id": 2 } ], "ordered": true, "lsid": { "$$type": "object" }, "txnNumber": 1 }, "commandName": "insert", "databaseName": "session-tests" } }, { "commandStartedEvent": { "command": { "find": "test", "filter": { "_id": -1 }, "lsid": { "$$type": "object" } }, "commandName": "find", "databaseName": "session-tests" } } ] } ], "outcome": [ { "collectionName": "test", "databaseName": "session-tests", "documents": [ { "_id": 1 }, { "_id": 2 } ] } ] }, { "description": "Dirty implicit session is discarded (findAndModify)", "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "client0", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "findAndModify" ], "closeConnection": true } } } }, { "name": "findOneAndUpdate", "object": "collection0", "arguments": { "filter": { "_id": 1 }, "update": { "$inc": { "x": 1 } }, "returnDocument": "Before" }, "expectResult": { "_id": 1 } }, { "name": "find", "object": "collection0", "arguments": { "filter": { "_id": -1 } }, "expectResult": [] }, { "name": "assertDifferentLsidOnLastTwoCommands", "object": "testRunner", "arguments": { "client": "client0" } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "findAndModify": "test", "query": { "_id": 1 }, "update": { "$inc": { "x": 1 } }, "new": false, "lsid": { "$$type": "object" }, "txnNumber": 1, "readConcern": { "$$exists": false }, "writeConcern": { "$$exists": false } }, "commandName": "findAndModify", "databaseName": "session-tests" } }, { "commandStartedEvent": { "command": { "findAndModify": "test", "query": { "_id": 1 }, "update": { "$inc": { "x": 1 } }, "new": false, "lsid": { "$$type": "object" }, "txnNumber": 1, "readConcern": { "$$exists": false }, "writeConcern": { "$$exists": false } }, "commandName": "findAndModify", "databaseName": "session-tests" } }, { "commandStartedEvent": { "command": { "find": "test", "filter": { "_id": -1 }, "lsid": { "$$type": "object" } }, "commandName": "find", "databaseName": "session-tests" } } ] } ], "outcome": [ { "collectionName": "test", "databaseName": "session-tests", "documents": [ { "_id": 1, "x": 1 } ] } ] }, { "description": "Dirty implicit session is discarded (read returning cursor)", "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "client0", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "aggregate" ], "closeConnection": true } } } }, { "name": "aggregate", "object": "collection0", "arguments": { "pipeline": [ { "$project": { "_id": 1 } } ] }, "expectResult": [ { "_id": 1 } ] }, { "name": "find", "object": "collection0", "arguments": { "filter": { "_id": -1 } }, "expectResult": [] }, { "name": "assertDifferentLsidOnLastTwoCommands", "object": "testRunner", "arguments": { "client": "client0" } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "aggregate": "test", "pipeline": [ { "$project": { "_id": 1 } } ], "lsid": { "$$type": "object" } }, "commandName": "aggregate", "databaseName": "session-tests" } }, { "commandStartedEvent": { "command": { "aggregate": "test", "pipeline": [ { "$project": { "_id": 1 } } ], "lsid": { "$$type": "object" } }, "commandName": "aggregate", "databaseName": "session-tests" } }, { "commandStartedEvent": { "command": { "find": "test", "filter": { "_id": -1 }, "lsid": { "$$type": "object" } }, "commandName": "find", "databaseName": "session-tests" } } ] } ], "outcome": [ { "collectionName": "test", "databaseName": "session-tests", "documents": [ { "_id": 1 } ] } ] }, { "description": "Dirty implicit session is discarded (read not returning cursor)", "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "client0", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "aggregate" ], "closeConnection": true } } } }, { "name": "countDocuments", "object": "collection0", "arguments": { "filter": {} }, "expectResult": 1 }, { "name": "find", "object": "collection0", "arguments": { "filter": { "_id": -1 } }, "expectResult": [] }, { "name": "assertDifferentLsidOnLastTwoCommands", "object": "testRunner", "arguments": { "client": "client0" } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "aggregate": "test", "pipeline": [ { "$match": {} }, { "$group": { "_id": 1, "n": { "$sum": 1 } } } ], "lsid": { "$$type": "object" } }, "commandName": "aggregate", "databaseName": "session-tests" } }, { "commandStartedEvent": { "command": { "aggregate": "test", "pipeline": [ { "$match": {} }, { "$group": { "_id": 1, "n": { "$sum": 1 } } } ], "lsid": { "$$type": "object" } }, "commandName": "aggregate", "databaseName": "session-tests" } }, { "commandStartedEvent": { "command": { "find": "test", "filter": { "_id": -1 }, "lsid": { "$$type": "object" } }, "commandName": "find", "databaseName": "session-tests" } } ] } ], "outcome": [ { "collectionName": "test", "databaseName": "session-tests", "documents": [ { "_id": 1 } ] } ] } ] } mongodb-mongo-python-driver-509e9b7/test/sessions/driver-sessions-server-support.json000066400000000000000000000131151462766011000313330ustar00rootroot00000000000000{ "description": "driver-sessions-server-support", "schemaVersion": "1.0", "runOnRequirements": [ { "minServerVersion": "3.6" } ], "createEntities": [ { "client": { "id": "client0", "useMultipleMongoses": false, "observeEvents": [ "commandStartedEvent" ] } }, { "database": { "id": "database0", "client": "client0", "databaseName": "session-tests" } }, { "collection": { "id": "collection0", "database": "database0", "collectionName": "test" } }, { "session": { "id": "session0", "client": "client0" } } ], "initialData": [ { "collectionName": "test", "databaseName": "session-tests", "documents": [ { "_id": 1 } ] } ], "tests": [ { "description": "Server supports explicit sessions", "operations": [ { "name": "assertSessionNotDirty", "object": "testRunner", "arguments": { "session": "session0" } }, { "name": "insertOne", "object": "collection0", "arguments": { "session": "session0", "document": { "_id": 2 } }, "expectResult": { "$$unsetOrMatches": { "insertedId": { "$$unsetOrMatches": 2 } } } }, { "name": "assertSessionNotDirty", "object": "testRunner", "arguments": { "session": "session0" } }, { "name": "endSession", "object": "session0" }, { "name": "find", "object": "collection0", "arguments": { "filter": { "_id": -1 } }, "expectResult": [] }, { "name": "assertSameLsidOnLastTwoCommands", "object": "testRunner", "arguments": { "client": "client0" } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "insert": "test", "documents": [ { "_id": 2 } ], "ordered": true, "lsid": { "$$sessionLsid": "session0" } }, "commandName": "insert", "databaseName": "session-tests" } }, { "commandStartedEvent": { "command": { "find": "test", "filter": { "_id": -1 }, "lsid": { "$$sessionLsid": "session0" } }, "commandName": "find", "databaseName": "session-tests" } } ] } ], "outcome": [ { "collectionName": "test", "databaseName": "session-tests", "documents": [ { "_id": 1 }, { "_id": 2 } ] } ] }, { "description": "Server supports implicit sessions", "operations": [ { "name": "insertOne", "object": "collection0", "arguments": { "document": { "_id": 2 } }, "expectResult": { "$$unsetOrMatches": { "insertedId": { "$$unsetOrMatches": 2 } } } }, { "name": "find", "object": "collection0", "arguments": { "filter": { "_id": -1 } }, "expectResult": [] }, { "name": "assertSameLsidOnLastTwoCommands", "object": "testRunner", "arguments": { "client": "client0" } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "insert": "test", "documents": [ { "_id": 2 } ], "ordered": true, "lsid": { "$$type": "object" } }, "commandName": "insert", "databaseName": "session-tests" } }, { "commandStartedEvent": { "command": { "find": "test", "filter": { "_id": -1 }, "lsid": { "$$type": "object" } }, "commandName": "find", "databaseName": "session-tests" } } ] } ], "outcome": [ { "collectionName": "test", "databaseName": "session-tests", "documents": [ { "_id": 1 }, { "_id": 2 } ] } ] } ] } mongodb-mongo-python-driver-509e9b7/test/sessions/implicit-sessions-default-causal-consistency.json000066400000000000000000000167521462766011000340750ustar00rootroot00000000000000{ "description": "implicit sessions default causal consistency", "schemaVersion": "1.3", "runOnRequirements": [ { "minServerVersion": "4.2", "topologies": [ "replicaset", "sharded", "load-balanced" ] } ], "createEntities": [ { "client": { "id": "client0", "useMultipleMongoses": false, "observeEvents": [ "commandStartedEvent" ] } }, { "database": { "id": "database0", "client": "client0", "databaseName": "implicit-cc-tests" } }, { "collection": { "id": "collectionDefault", "database": "database0", "collectionName": "coll-default" } }, { "collection": { "id": "collectionSnapshot", "database": "database0", "collectionName": "coll-snapshot", "collectionOptions": { "readConcern": { "level": "snapshot" } } } }, { "collection": { "id": "collectionlinearizable", "database": "database0", "collectionName": "coll-linearizable", "collectionOptions": { "readConcern": { "level": "linearizable" } } } } ], "initialData": [ { "collectionName": "coll-default", "databaseName": "implicit-cc-tests", "documents": [ { "_id": 1, "x": "default" } ] }, { "collectionName": "coll-snapshot", "databaseName": "implicit-cc-tests", "documents": [ { "_id": 1, "x": "snapshot" } ] }, { "collectionName": "coll-linearizable", "databaseName": "implicit-cc-tests", "documents": [ { "_id": 1, "x": "linearizable" } ] } ], "tests": [ { "description": "readConcern is not sent on retried read in implicit session when readConcern level is not specified", "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "client0", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "find" ], "errorCode": 11600 } } } }, { "name": "find", "object": "collectionDefault", "arguments": { "filter": {} }, "expectResult": [ { "_id": 1, "x": "default" } ] } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "find": "coll-default", "filter": {}, "readConcern": { "$$exists": false } }, "databaseName": "implicit-cc-tests" } }, { "commandStartedEvent": { "command": { "find": "coll-default", "filter": {}, "readConcern": { "$$exists": false } }, "databaseName": "implicit-cc-tests" } } ] } ] }, { "description": "afterClusterTime is not sent on retried read in implicit session when readConcern level is snapshot", "runOnRequirements": [ { "minServerVersion": "5.0" } ], "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "client0", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "find" ], "errorCode": 11600 } } } }, { "name": "find", "object": "collectionSnapshot", "arguments": { "filter": {} }, "expectResult": [ { "_id": 1, "x": "snapshot" } ] } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "find": "coll-snapshot", "filter": {}, "readConcern": { "level": "snapshot", "afterClusterTime": { "$$exists": false } } }, "databaseName": "implicit-cc-tests" } }, { "commandStartedEvent": { "command": { "find": "coll-snapshot", "filter": {}, "readConcern": { "level": "snapshot", "afterClusterTime": { "$$exists": false } } }, "databaseName": "implicit-cc-tests" } } ] } ] }, { "description": "afterClusterTime is not sent on retried read in implicit session when readConcern level is linearizable", "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "client0", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "find" ], "errorCode": 11600 } } } }, { "name": "find", "object": "collectionlinearizable", "arguments": { "filter": {} }, "expectResult": [ { "_id": 1, "x": "linearizable" } ] } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "find": "coll-linearizable", "filter": {}, "readConcern": { "level": "linearizable", "afterClusterTime": { "$$exists": false } } }, "databaseName": "implicit-cc-tests" } }, { "commandStartedEvent": { "command": { "find": "coll-linearizable", "filter": {}, "readConcern": { "level": "linearizable", "afterClusterTime": { "$$exists": false } } }, "databaseName": "implicit-cc-tests" } } ] } ] } ] } mongodb-mongo-python-driver-509e9b7/test/sessions/snapshot-sessions-not-supported-client-error.json000066400000000000000000000052241462766011000341070ustar00rootroot00000000000000{ "description": "snapshot-sessions-not-supported-client-error", "schemaVersion": "1.0", "runOnRequirements": [ { "minServerVersion": "3.6", "maxServerVersion": "4.4.99" } ], "createEntities": [ { "client": { "id": "client0", "observeEvents": [ "commandStartedEvent", "commandFailedEvent" ] } }, { "database": { "id": "database0", "client": "client0", "databaseName": "database0" } }, { "collection": { "id": "collection0", "database": "database0", "collectionName": "collection0" } }, { "session": { "id": "session0", "client": "client0", "sessionOptions": { "snapshot": true } } } ], "initialData": [ { "collectionName": "collection0", "databaseName": "database0", "documents": [ { "_id": 1, "x": 11 } ] } ], "tests": [ { "description": "Client error on find with snapshot", "operations": [ { "name": "find", "object": "collection0", "arguments": { "session": "session0", "filter": {} }, "expectError": { "isClientError": true, "errorContains": "Snapshot reads require MongoDB 5.0 or later" } } ], "expectEvents": [ { "client": "client0", "events": [] } ] }, { "description": "Client error on aggregate with snapshot", "operations": [ { "name": "aggregate", "object": "collection0", "arguments": { "session": "session0", "pipeline": [] }, "expectError": { "isClientError": true, "errorContains": "Snapshot reads require MongoDB 5.0 or later" } } ], "expectEvents": [ { "client": "client0", "events": [] } ] }, { "description": "Client error on distinct with snapshot", "operations": [ { "name": "distinct", "object": "collection0", "arguments": { "fieldName": "x", "filter": {}, "session": "session0" }, "expectError": { "isClientError": true, "errorContains": "Snapshot reads require MongoDB 5.0 or later" } } ], "expectEvents": [ { "client": "client0", "events": [] } ] } ] } mongodb-mongo-python-driver-509e9b7/test/sessions/snapshot-sessions-not-supported-server-error.json000066400000000000000000000100451462766011000341340ustar00rootroot00000000000000{ "description": "snapshot-sessions-not-supported-server-error", "schemaVersion": "1.0", "runOnRequirements": [ { "minServerVersion": "5.0", "topologies": [ "single" ] } ], "createEntities": [ { "client": { "id": "client0", "observeEvents": [ "commandStartedEvent", "commandFailedEvent" ] } }, { "database": { "id": "database0", "client": "client0", "databaseName": "database0" } }, { "collection": { "id": "collection0", "database": "database0", "collectionName": "collection0" } }, { "session": { "id": "session0", "client": "client0", "sessionOptions": { "snapshot": true } } } ], "initialData": [ { "collectionName": "collection0", "databaseName": "database0", "documents": [ { "_id": 1, "x": 11 } ] } ], "tests": [ { "description": "Server returns an error on find with snapshot", "operations": [ { "name": "find", "object": "collection0", "arguments": { "session": "session0", "filter": {} }, "expectError": { "isError": true, "isClientError": false } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "find": "collection0", "readConcern": { "level": "snapshot", "atClusterTime": { "$$exists": false } } } } }, { "commandFailedEvent": { "commandName": "find" } } ] } ] }, { "description": "Server returns an error on aggregate with snapshot", "operations": [ { "name": "aggregate", "object": "collection0", "arguments": { "session": "session0", "pipeline": [] }, "expectError": { "isError": true, "isClientError": false } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "aggregate": "collection0", "readConcern": { "level": "snapshot", "atClusterTime": { "$$exists": false } } } } }, { "commandFailedEvent": { "commandName": "aggregate" } } ] } ] }, { "description": "Server returns an error on distinct with snapshot", "operations": [ { "name": "distinct", "object": "collection0", "arguments": { "fieldName": "x", "filter": {}, "session": "session0" }, "expectError": { "isError": true, "isClientError": false } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "distinct": "collection0", "readConcern": { "level": "snapshot", "atClusterTime": { "$$exists": false } } } } }, { "commandFailedEvent": { "commandName": "distinct" } } ] } ] } ] } mongodb-mongo-python-driver-509e9b7/test/sessions/snapshot-sessions-unsupported-ops.json000066400000000000000000000260701462766011000320520ustar00rootroot00000000000000{ "description": "snapshot-sessions-unsupported-ops", "schemaVersion": "1.0", "runOnRequirements": [ { "minServerVersion": "5.0", "topologies": [ "replicaset", "sharded-replicaset" ] } ], "createEntities": [ { "client": { "id": "client0", "observeEvents": [ "commandStartedEvent", "commandFailedEvent" ] } }, { "database": { "id": "database0", "client": "client0", "databaseName": "database0" } }, { "collection": { "id": "collection0", "database": "database0", "collectionName": "collection0" } }, { "session": { "id": "session0", "client": "client0", "sessionOptions": { "snapshot": true } } } ], "initialData": [ { "collectionName": "collection0", "databaseName": "database0", "documents": [ { "_id": 1, "x": 11 } ] } ], "tests": [ { "description": "Server returns an error on insertOne with snapshot", "runOnRequirements": [ { "topologies": [ "replicaset" ] } ], "operations": [ { "name": "insertOne", "object": "collection0", "arguments": { "session": "session0", "document": { "_id": 22, "x": 22 } }, "expectError": { "isError": true, "isClientError": false } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "insert": "collection0", "readConcern": { "level": "snapshot", "atClusterTime": { "$$exists": false } } } } }, { "commandFailedEvent": { "commandName": "insert" } } ] } ] }, { "description": "Server returns an error on insertMany with snapshot", "runOnRequirements": [ { "topologies": [ "replicaset" ] } ], "operations": [ { "name": "insertMany", "object": "collection0", "arguments": { "session": "session0", "documents": [ { "_id": 22, "x": 22 }, { "_id": 33, "x": 33 } ] }, "expectError": { "isError": true, "isClientError": false } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "insert": "collection0", "readConcern": { "level": "snapshot", "atClusterTime": { "$$exists": false } } } } }, { "commandFailedEvent": { "commandName": "insert" } } ] } ] }, { "description": "Server returns an error on deleteOne with snapshot", "runOnRequirements": [ { "topologies": [ "replicaset" ] } ], "operations": [ { "name": "deleteOne", "object": "collection0", "arguments": { "session": "session0", "filter": {} }, "expectError": { "isError": true, "isClientError": false } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "delete": "collection0", "readConcern": { "level": "snapshot", "atClusterTime": { "$$exists": false } } } } }, { "commandFailedEvent": { "commandName": "delete" } } ] } ] }, { "description": "Server returns an error on updateOne with snapshot", "runOnRequirements": [ { "topologies": [ "replicaset" ] } ], "operations": [ { "name": "updateOne", "object": "collection0", "arguments": { "session": "session0", "filter": { "_id": 1 }, "update": { "$inc": { "x": 1 } } }, "expectError": { "isError": true, "isClientError": false } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "update": "collection0", "readConcern": { "level": "snapshot", "atClusterTime": { "$$exists": false } } } } }, { "commandFailedEvent": { "commandName": "update" } } ] } ] }, { "description": "Server returns an error on findOneAndUpdate with snapshot", "operations": [ { "name": "findOneAndUpdate", "object": "collection0", "arguments": { "session": "session0", "filter": { "_id": 1 }, "update": { "$inc": { "x": 1 } } }, "expectError": { "isError": true, "isClientError": false } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "findAndModify": "collection0", "readConcern": { "level": "snapshot", "atClusterTime": { "$$exists": false } } } } }, { "commandFailedEvent": { "commandName": "findAndModify" } } ] } ] }, { "description": "Server returns an error on listDatabases with snapshot", "operations": [ { "name": "listDatabases", "object": "client0", "arguments": { "session": "session0" }, "expectError": { "isError": true, "isClientError": false } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "listDatabases": 1, "readConcern": { "level": "snapshot", "atClusterTime": { "$$exists": false } } } } }, { "commandFailedEvent": { "commandName": "listDatabases" } } ] } ] }, { "description": "Server returns an error on listCollections with snapshot", "operations": [ { "name": "listCollections", "object": "database0", "arguments": { "session": "session0" }, "expectError": { "isError": true, "isClientError": false } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "listCollections": 1, "readConcern": { "level": "snapshot", "atClusterTime": { "$$exists": false } } } } }, { "commandFailedEvent": { "commandName": "listCollections" } } ] } ] }, { "description": "Server returns an error on listIndexes with snapshot", "operations": [ { "name": "listIndexes", "object": "collection0", "arguments": { "session": "session0" }, "expectError": { "isError": true, "isClientError": false } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "listIndexes": "collection0", "readConcern": { "level": "snapshot", "atClusterTime": { "$$exists": false } } } } }, { "commandFailedEvent": { "commandName": "listIndexes" } } ] } ] }, { "description": "Server returns an error on runCommand with snapshot", "operations": [ { "name": "runCommand", "object": "database0", "arguments": { "session": "session0", "commandName": "listCollections", "command": { "listCollections": 1 } }, "expectError": { "isError": true, "isClientError": false } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "listCollections": 1, "readConcern": { "level": "snapshot", "atClusterTime": { "$$exists": false } } } } }, { "commandFailedEvent": { "commandName": "listCollections" } } ] } ] } ] } mongodb-mongo-python-driver-509e9b7/test/sessions/snapshot-sessions.json000066400000000000000000000545471462766011000266770ustar00rootroot00000000000000{ "description": "snapshot-sessions", "schemaVersion": "1.0", "runOnRequirements": [ { "minServerVersion": "5.0", "topologies": [ "replicaset", "sharded-replicaset" ] } ], "createEntities": [ { "client": { "id": "client0", "observeEvents": [ "commandStartedEvent" ], "ignoreCommandMonitoringEvents": [ "findAndModify", "insert", "update" ] } }, { "database": { "id": "database0", "client": "client0", "databaseName": "database0" } }, { "collection": { "id": "collection0", "database": "database0", "collectionName": "collection0", "collectionOptions": { "writeConcern": { "w": "majority" } } } }, { "session": { "id": "session0", "client": "client0", "sessionOptions": { "snapshot": true } } }, { "session": { "id": "session1", "client": "client0", "sessionOptions": { "snapshot": true } } } ], "initialData": [ { "collectionName": "collection0", "databaseName": "database0", "documents": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 11 } ] } ], "tests": [ { "description": "Find operation with snapshot", "operations": [ { "name": "find", "object": "collection0", "arguments": { "session": "session0", "filter": { "_id": 1 } }, "expectResult": [ { "_id": 1, "x": 11 } ] }, { "name": "findOneAndUpdate", "object": "collection0", "arguments": { "filter": { "_id": 1 }, "update": { "$inc": { "x": 1 } }, "returnDocument": "After" }, "expectResult": { "_id": 1, "x": 12 } }, { "name": "find", "object": "collection0", "arguments": { "session": "session1", "filter": { "_id": 1 } }, "expectResult": [ { "_id": 1, "x": 12 } ] }, { "name": "findOneAndUpdate", "object": "collection0", "arguments": { "filter": { "_id": 1 }, "update": { "$inc": { "x": 1 } }, "returnDocument": "After" }, "expectResult": { "_id": 1, "x": 13 } }, { "name": "find", "object": "collection0", "arguments": { "filter": { "_id": 1 } }, "expectResult": [ { "_id": 1, "x": 13 } ] }, { "name": "find", "object": "collection0", "arguments": { "session": "session0", "filter": { "_id": 1 } }, "expectResult": [ { "_id": 1, "x": 11 } ] }, { "name": "find", "object": "collection0", "arguments": { "session": "session1", "filter": { "_id": 1 } }, "expectResult": [ { "_id": 1, "x": 12 } ] } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "find": "collection0", "readConcern": { "level": "snapshot", "atClusterTime": { "$$exists": false } } } } }, { "commandStartedEvent": { "command": { "find": "collection0", "readConcern": { "level": "snapshot", "atClusterTime": { "$$exists": false } } } } }, { "commandStartedEvent": { "command": { "find": "collection0", "readConcern": { "$$exists": false } } } }, { "commandStartedEvent": { "command": { "find": "collection0", "readConcern": { "level": "snapshot", "atClusterTime": { "$$exists": true } } } } }, { "commandStartedEvent": { "command": { "find": "collection0", "readConcern": { "level": "snapshot", "atClusterTime": { "$$exists": true } } } } } ] } ] }, { "description": "Distinct operation with snapshot", "operations": [ { "name": "distinct", "object": "collection0", "arguments": { "fieldName": "x", "filter": {}, "session": "session0" }, "expectResult": [ 11 ] }, { "name": "findOneAndUpdate", "object": "collection0", "arguments": { "filter": { "_id": 2 }, "update": { "$inc": { "x": 1 } }, "returnDocument": "After" }, "expectResult": { "_id": 2, "x": 12 } }, { "name": "distinct", "object": "collection0", "arguments": { "fieldName": "x", "filter": {}, "session": "session1" }, "expectResult": [ 11, 12 ] }, { "name": "findOneAndUpdate", "object": "collection0", "arguments": { "filter": { "_id": 2 }, "update": { "$inc": { "x": 1 } }, "returnDocument": "After" }, "expectResult": { "_id": 2, "x": 13 } }, { "name": "distinct", "object": "collection0", "arguments": { "fieldName": "x", "filter": {} }, "expectResult": [ 11, 13 ] }, { "name": "distinct", "object": "collection0", "arguments": { "fieldName": "x", "filter": {}, "session": "session0" }, "expectResult": [ 11 ] }, { "name": "distinct", "object": "collection0", "arguments": { "fieldName": "x", "filter": {}, "session": "session1" }, "expectResult": [ 11, 12 ] } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "distinct": "collection0", "readConcern": { "level": "snapshot", "atClusterTime": { "$$exists": false } } } } }, { "commandStartedEvent": { "command": { "distinct": "collection0", "readConcern": { "level": "snapshot", "atClusterTime": { "$$exists": false } } } } }, { "commandStartedEvent": { "command": { "distinct": "collection0", "readConcern": { "$$exists": false } } } }, { "commandStartedEvent": { "command": { "distinct": "collection0", "readConcern": { "level": "snapshot", "atClusterTime": { "$$exists": true } } } } }, { "commandStartedEvent": { "command": { "distinct": "collection0", "readConcern": { "level": "snapshot", "atClusterTime": { "$$exists": true } } } } } ] } ] }, { "description": "Aggregate operation with snapshot", "operations": [ { "name": "aggregate", "object": "collection0", "arguments": { "pipeline": [ { "$match": { "_id": 1 } } ], "session": "session0" }, "expectResult": [ { "_id": 1, "x": 11 } ] }, { "name": "findOneAndUpdate", "object": "collection0", "arguments": { "filter": { "_id": 1 }, "update": { "$inc": { "x": 1 } }, "returnDocument": "After" }, "expectResult": { "_id": 1, "x": 12 } }, { "name": "aggregate", "object": "collection0", "arguments": { "pipeline": [ { "$match": { "_id": 1 } } ], "session": "session1" }, "expectResult": [ { "_id": 1, "x": 12 } ] }, { "name": "findOneAndUpdate", "object": "collection0", "arguments": { "filter": { "_id": 1 }, "update": { "$inc": { "x": 1 } }, "returnDocument": "After" }, "expectResult": { "_id": 1, "x": 13 } }, { "name": "aggregate", "object": "collection0", "arguments": { "pipeline": [ { "$match": { "_id": 1 } } ] }, "expectResult": [ { "_id": 1, "x": 13 } ] }, { "name": "aggregate", "object": "collection0", "arguments": { "pipeline": [ { "$match": { "_id": 1 } } ], "session": "session0" }, "expectResult": [ { "_id": 1, "x": 11 } ] }, { "name": "aggregate", "object": "collection0", "arguments": { "pipeline": [ { "$match": { "_id": 1 } } ], "session": "session1" }, "expectResult": [ { "_id": 1, "x": 12 } ] } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "aggregate": "collection0", "readConcern": { "level": "snapshot", "atClusterTime": { "$$exists": false } } } } }, { "commandStartedEvent": { "command": { "aggregate": "collection0", "readConcern": { "level": "snapshot", "atClusterTime": { "$$exists": false } } } } }, { "commandStartedEvent": { "command": { "aggregate": "collection0", "readConcern": { "$$exists": false } } } }, { "commandStartedEvent": { "command": { "aggregate": "collection0", "readConcern": { "level": "snapshot", "atClusterTime": { "$$exists": true } } } } }, { "commandStartedEvent": { "command": { "aggregate": "collection0", "readConcern": { "level": "snapshot", "atClusterTime": { "$$exists": true } } } } } ] } ] }, { "description": "countDocuments operation with snapshot", "operations": [ { "name": "countDocuments", "object": "collection0", "arguments": { "filter": {}, "session": "session0" }, "expectResult": 2 }, { "name": "countDocuments", "object": "collection0", "arguments": { "filter": {}, "session": "session0" }, "expectResult": 2 } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "aggregate": "collection0", "readConcern": { "level": "snapshot", "atClusterTime": { "$$exists": false } } } } }, { "commandStartedEvent": { "command": { "aggregate": "collection0", "readConcern": { "level": "snapshot", "atClusterTime": { "$$exists": true } } } } } ] } ] }, { "description": "Mixed operation with snapshot", "operations": [ { "name": "find", "object": "collection0", "arguments": { "session": "session0", "filter": { "_id": 1 } }, "expectResult": [ { "_id": 1, "x": 11 } ] }, { "name": "findOneAndUpdate", "object": "collection0", "arguments": { "filter": { "_id": 1 }, "update": { "$inc": { "x": 1 } }, "returnDocument": "After" }, "expectResult": { "_id": 1, "x": 12 } }, { "name": "find", "object": "collection0", "arguments": { "filter": { "_id": 1 } }, "expectResult": [ { "_id": 1, "x": 12 } ] }, { "name": "aggregate", "object": "collection0", "arguments": { "pipeline": [ { "$match": { "_id": 1 } } ], "session": "session0" }, "expectResult": [ { "_id": 1, "x": 11 } ] }, { "name": "distinct", "object": "collection0", "arguments": { "fieldName": "x", "filter": {}, "session": "session0" }, "expectResult": [ 11 ] } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "find": "collection0", "readConcern": { "level": "snapshot", "atClusterTime": { "$$exists": false } } } } }, { "commandStartedEvent": { "command": { "find": "collection0", "readConcern": { "$$exists": false } } } }, { "commandStartedEvent": { "command": { "aggregate": "collection0", "readConcern": { "level": "snapshot", "atClusterTime": { "$$exists": true } } } } }, { "commandStartedEvent": { "command": { "distinct": "collection0", "readConcern": { "level": "snapshot", "atClusterTime": { "$$exists": true } } } } } ] } ] }, { "description": "Write commands with snapshot session do not affect snapshot reads", "operations": [ { "name": "find", "object": "collection0", "arguments": { "filter": {}, "session": "session0" } }, { "name": "insertOne", "object": "collection0", "arguments": { "document": { "_id": 22, "x": 33 } } }, { "name": "updateOne", "object": "collection0", "arguments": { "filter": { "_id": 1 }, "update": { "$inc": { "x": 1 } } } }, { "name": "find", "object": "collection0", "arguments": { "filter": { "_id": 1 }, "session": "session0" }, "expectResult": [ { "_id": 1, "x": 11 } ] } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "find": "collection0", "readConcern": { "level": "snapshot", "atClusterTime": { "$$exists": false } } } } }, { "commandStartedEvent": { "command": { "find": "collection0", "readConcern": { "level": "snapshot", "atClusterTime": { "$$exists": true } } } } } ] } ] }, { "description": "First snapshot read does not send atClusterTime", "operations": [ { "name": "find", "object": "collection0", "arguments": { "filter": {}, "session": "session0" } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "find": "collection0", "readConcern": { "level": "snapshot", "atClusterTime": { "$$exists": false } } }, "commandName": "find", "databaseName": "database0" } } ] } ] }, { "description": "StartTransaction fails in snapshot session", "operations": [ { "name": "startTransaction", "object": "session0", "expectError": { "isError": true, "isClientError": true, "errorContains": "Transactions are not supported in snapshot sessions" } } ] } ] } mongodb-mongo-python-driver-509e9b7/test/sigstop_sigcont.py000066400000000000000000000053741462766011000242150ustar00rootroot00000000000000# Copyright 2022-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. """Used by test_client.TestClient.test_sigstop_sigcont.""" from __future__ import annotations import logging import os import sys sys.path[0:0] = [""] from pymongo import monitoring from pymongo.mongo_client import MongoClient from pymongo.server_api import ServerApi SERVER_API = None MONGODB_API_VERSION = os.environ.get("MONGODB_API_VERSION") if MONGODB_API_VERSION: SERVER_API = ServerApi(MONGODB_API_VERSION) class HeartbeatLogger(monitoring.ServerHeartbeatListener): """Log events until the listener is closed.""" def __init__(self): self.closed = False def close(self): self.closed = True def started(self, event: monitoring.ServerHeartbeatStartedEvent) -> None: if self.closed: return logging.info("%s", event) def succeeded(self, event: monitoring.ServerHeartbeatSucceededEvent) -> None: if self.closed: return logging.info("%s", event) def failed(self, event: monitoring.ServerHeartbeatFailedEvent) -> None: if self.closed: return logging.warning("%s", event) def main(uri: str) -> None: heartbeat_logger = HeartbeatLogger() client = MongoClient( uri, event_listeners=[heartbeat_logger], heartbeatFrequencyMS=500, connectTimeoutMS=500, server_api=SERVER_API, ) client.admin.command("ping") logging.info("TEST STARTED") # test_sigstop_sigcont will SIGSTOP and SIGCONT this process in this loop. while True: try: data = input('Type "q" to quit: ') except EOFError: break if data == "q": break client.admin.command("ping") logging.info("TEST COMPLETED") heartbeat_logger.close() client.close() if __name__ == "__main__": if len(sys.argv) != 2: print("unknown or missing options") print(f"usage: python3 {sys.argv[0]} 'mongodb://localhost'") sys.exit(1) # Enable logs in this format: # 2022-03-30 12:40:55,582 INFO FORMAT = "%(asctime)s %(levelname)s %(message)s" logging.basicConfig(format=FORMAT, level=logging.INFO) main(sys.argv[1]) mongodb-mongo-python-driver-509e9b7/test/srv_seedlist/000077500000000000000000000000001462766011000231225ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/srv_seedlist/load-balanced/000077500000000000000000000000001462766011000255705ustar00rootroot00000000000000loadBalanced-directConnection.json000066400000000000000000000004631462766011000342300ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/srv_seedlist/load-balanced{ "uri": "mongodb+srv://test24.test.build.10gen.cc/?directConnection=false", "seeds": [ "localhost.test.build.10gen.cc:8000" ], "hosts": [ "localhost.test.build.10gen.cc:8000" ], "options": { "loadBalanced": true, "ssl": true, "directConnection": false }, "ping": true } mongodb-mongo-python-driver-509e9b7/test/srv_seedlist/load-balanced/loadBalanced-no-results.json000066400000000000000000000003061462766011000331240ustar00rootroot00000000000000{ "uri": "mongodb+srv://test4.test.build.10gen.cc/?loadBalanced=true", "seeds": [], "hosts": [], "error": true, "comment": "Should fail because no SRV records are present for this URI." } loadBalanced-replicaSet-errors.json000066400000000000000000000003211462766011000343340ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/srv_seedlist/load-balanced{ "uri": "mongodb+srv://test24.test.build.10gen.cc/?replicaSet=replset", "seeds": [], "hosts": [], "error": true, "comment": "Should fail because loadBalanced=true is incompatible with replicaSet" } loadBalanced-true-multiple-hosts.json000066400000000000000000000003401462766011000346760ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/srv_seedlist/load-balanced{ "uri": "mongodb+srv://test1.test.build.10gen.cc/?loadBalanced=true", "seeds": [], "hosts": [], "error": true, "comment": "Should fail because loadBalanced is true but the SRV record resolves to multiple hosts" } mongodb-mongo-python-driver-509e9b7/test/srv_seedlist/load-balanced/loadBalanced-true-txt.json000066400000000000000000000003751462766011000326130ustar00rootroot00000000000000{ "uri": "mongodb+srv://test24.test.build.10gen.cc/", "seeds": [ "localhost.test.build.10gen.cc:8000" ], "hosts": [ "localhost.test.build.10gen.cc:8000" ], "options": { "loadBalanced": true, "ssl": true }, "ping": true } srvMaxHosts-conflicts_with_loadBalanced-true-txt.json000066400000000000000000000003421462766011000401240ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/srv_seedlist/load-balanced{ "uri": "mongodb+srv://test24.test.build.10gen.cc/?srvMaxHosts=1", "seeds": [], "hosts": [], "error": true, "comment": "Should fail because positive integer for srvMaxHosts conflicts with loadBalanced=true (TXT)" } srvMaxHosts-conflicts_with_loadBalanced-true.json000066400000000000000000000003551462766011000373130ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/srv_seedlist/load-balanced{ "uri": "mongodb+srv://test3.test.build.10gen.cc/?loadBalanced=true&srvMaxHosts=1", "seeds": [], "hosts": [], "error": true, "comment": "Should fail because positive integer for srvMaxHosts conflicts with loadBalanced=true" } mongodb-mongo-python-driver-509e9b7/test/srv_seedlist/load-balanced/srvMaxHosts-zero-txt.json000066400000000000000000000004411462766011000325550ustar00rootroot00000000000000{ "uri": "mongodb+srv://test24.test.build.10gen.cc/?srvMaxHosts=0", "seeds": [ "localhost.test.build.10gen.cc:8000" ], "hosts": [ "localhost.test.build.10gen.cc:8000" ], "options": { "loadBalanced": true, "srvMaxHosts": 0, "ssl": true }, "ping": true } mongodb-mongo-python-driver-509e9b7/test/srv_seedlist/load-balanced/srvMaxHosts-zero.json000066400000000000000000000004631462766011000317440ustar00rootroot00000000000000{ "uri": "mongodb+srv://test23.test.build.10gen.cc/?loadBalanced=true&srvMaxHosts=0", "seeds": [ "localhost.test.build.10gen.cc:8000" ], "hosts": [ "localhost.test.build.10gen.cc:8000" ], "options": { "loadBalanced": true, "srvMaxHosts": 0, "ssl": true }, "ping": true } mongodb-mongo-python-driver-509e9b7/test/srv_seedlist/replica-set/000077500000000000000000000000001462766011000253325ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/srv_seedlist/replica-set/dbname-with-commas-escaped.json000066400000000000000000000006121462766011000333020ustar00rootroot00000000000000{ "uri": "mongodb+srv://test1.test.build.10gen.cc/some%2Cdb?replicaSet=repl0", "seeds": [ "localhost.test.build.10gen.cc:27017", "localhost.test.build.10gen.cc:27018" ], "hosts": [ "localhost:27017", "localhost:27018", "localhost:27019" ], "options": { "replicaSet": "repl0", "ssl": true }, "parsed_options": { "defaultDatabase": "some,db" } } mongodb-mongo-python-driver-509e9b7/test/srv_seedlist/replica-set/dbname-with-commas.json000066400000000000000000000006101462766011000316760ustar00rootroot00000000000000{ "uri": "mongodb+srv://test1.test.build.10gen.cc/some,db?replicaSet=repl0", "seeds": [ "localhost.test.build.10gen.cc:27017", "localhost.test.build.10gen.cc:27018" ], "hosts": [ "localhost:27017", "localhost:27018", "localhost:27019" ], "options": { "replicaSet": "repl0", "ssl": true }, "parsed_options": { "defaultDatabase": "some,db" } } mongodb-mongo-python-driver-509e9b7/test/srv_seedlist/replica-set/direct-connection-false.json000066400000000000000000000004641462766011000327300ustar00rootroot00000000000000{ "uri": "mongodb+srv://test3.test.build.10gen.cc/?directConnection=false", "seeds": [ "localhost.test.build.10gen.cc:27017" ], "hosts": [ "localhost:27017", "localhost:27018", "localhost:27019" ], "options": { "ssl": true, "directConnection": false }, "ping": true } mongodb-mongo-python-driver-509e9b7/test/srv_seedlist/replica-set/direct-connection-true.json000066400000000000000000000003261462766011000326120ustar00rootroot00000000000000{ "uri": "mongodb+srv://test3.test.build.10gen.cc/?directConnection=true", "seeds": [], "hosts": [], "error": true, "comment": "Should fail because directConnection=true is incompatible with SRV URIs." } mongodb-mongo-python-driver-509e9b7/test/srv_seedlist/replica-set/encoded-userinfo-and-db.json000066400000000000000000000007601462766011000326040ustar00rootroot00000000000000{ "uri": "mongodb+srv://b*b%40f3tt%3D:%244to%40L8%3DMC@test3.test.build.10gen.cc/mydb%3F?replicaSet=repl0", "seeds": [ "localhost.test.build.10gen.cc:27017" ], "hosts": [ "localhost:27017", "localhost:27018", "localhost:27019" ], "options": { "replicaSet": "repl0", "ssl": true }, "parsed_options": { "user": "b*b@f3tt=", "password": "$4to@L8=MC", "db": "mydb?" }, "ping": false, "comment": "Encoded user, pass, and DB parse correctly" } mongodb-mongo-python-driver-509e9b7/test/srv_seedlist/replica-set/loadBalanced-false-txt.json000066400000000000000000000004321462766011000324620ustar00rootroot00000000000000{ "uri": "mongodb+srv://test21.test.build.10gen.cc/", "seeds": [ "localhost.test.build.10gen.cc:27017" ], "hosts": [ "localhost:27017", "localhost:27018", "localhost:27019" ], "options": { "loadBalanced": false, "ssl": true }, "ping": true } mongodb-mongo-python-driver-509e9b7/test/srv_seedlist/replica-set/longer-parent-in-return.json000066400000000000000000000006161462766011000327260ustar00rootroot00000000000000{ "uri": "mongodb+srv://test18.test.build.10gen.cc/?replicaSet=repl0", "seeds": [ "localhost.sub.test.build.10gen.cc:27017" ], "hosts": [ "localhost:27017", "localhost:27018", "localhost:27019" ], "options": { "replicaSet": "repl0", "ssl": true }, "ping": true, "comment": "Is correct, as returned host name shared the URI root \"test.build.10gen.cc\"." } mongodb-mongo-python-driver-509e9b7/test/srv_seedlist/replica-set/misformatted-option.json000066400000000000000000000003231462766011000322270ustar00rootroot00000000000000{ "uri": "mongodb+srv://test8.test.build.10gen.cc/", "seeds": [], "hosts": [], "error": true, "comment": "Should fail because the options in the TXT record are incorrectly formatted (misses value)." } mongodb-mongo-python-driver-509e9b7/test/srv_seedlist/replica-set/no-results.json000066400000000000000000000002641462766011000303420ustar00rootroot00000000000000{ "uri": "mongodb+srv://test4.test.build.10gen.cc/", "seeds": [], "hosts": [], "error": true, "comment": "Should fail because no SRV records are present for this URI." } mongodb-mongo-python-driver-509e9b7/test/srv_seedlist/replica-set/not-enough-parts.json000066400000000000000000000002701462766011000314360ustar00rootroot00000000000000{ "uri": "mongodb+srv://10gen.cc/", "seeds": [], "hosts": [], "error": true, "comment": "Should fail because host in URI does not have {hostname}, {domainname} and {tld}." } mongodb-mongo-python-driver-509e9b7/test/srv_seedlist/replica-set/one-result-default-port.json000066400000000000000000000004521462766011000327270ustar00rootroot00000000000000{ "uri": "mongodb+srv://test3.test.build.10gen.cc/?replicaSet=repl0", "seeds": [ "localhost.test.build.10gen.cc:27017" ], "hosts": [ "localhost:27017", "localhost:27018", "localhost:27019" ], "options": { "replicaSet": "repl0", "ssl": true }, "ping": true } one-txt-record-multiple-strings.json000066400000000000000000000004321462766011000343370ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/srv_seedlist/replica-set{ "uri": "mongodb+srv://test11.test.build.10gen.cc/", "seeds": [ "localhost.test.build.10gen.cc:27017" ], "hosts": [ "localhost:27017", "localhost:27018", "localhost:27019" ], "options": { "replicaSet": "repl0", "ssl": true }, "ping": true } mongodb-mongo-python-driver-509e9b7/test/srv_seedlist/replica-set/one-txt-record.json000066400000000000000000000004651462766011000311040ustar00rootroot00000000000000{ "uri": "mongodb+srv://test5.test.build.10gen.cc/", "seeds": [ "localhost.test.build.10gen.cc:27017" ], "hosts": [ "localhost:27017", "localhost:27018", "localhost:27019" ], "options": { "replicaSet": "repl0", "authSource": "thisDB", "ssl": true }, "ping": true } mongodb-mongo-python-driver-509e9b7/test/srv_seedlist/replica-set/parent-part-mismatch1.json000066400000000000000000000003301462766011000323420ustar00rootroot00000000000000{ "uri": "mongodb+srv://test14.test.build.10gen.cc/", "seeds": [], "hosts": [], "error": true, "comment": "Should fail because returned host name's part \"not-test\" mismatches URI parent part \"test\"." } mongodb-mongo-python-driver-509e9b7/test/srv_seedlist/replica-set/parent-part-mismatch2.json000066400000000000000000000003321462766011000323450ustar00rootroot00000000000000{ "uri": "mongodb+srv://test15.test.build.10gen.cc/", "seeds": [], "hosts": [], "error": true, "comment": "Should fail because returned host name's part \"not-build\" mismatches URI parent part \"build\"." } mongodb-mongo-python-driver-509e9b7/test/srv_seedlist/replica-set/parent-part-mismatch3.json000066400000000000000000000003321462766011000323460ustar00rootroot00000000000000{ "uri": "mongodb+srv://test16.test.build.10gen.cc/", "seeds": [], "hosts": [], "error": true, "comment": "Should fail because returned host name's part \"not-10gen\" mismatches URI parent part \"10gen\"." } mongodb-mongo-python-driver-509e9b7/test/srv_seedlist/replica-set/parent-part-mismatch4.json000066400000000000000000000003131462766011000323460ustar00rootroot00000000000000{ "uri": "mongodb+srv://test17.test.build.10gen.cc/", "seeds": [], "hosts": [], "error": true, "comment": "Should fail because returned host name's TLD \"not-cc\" mismatches URI TLD \"cc\"." } mongodb-mongo-python-driver-509e9b7/test/srv_seedlist/replica-set/parent-part-mismatch5.json000066400000000000000000000003341462766011000323520ustar00rootroot00000000000000{ "uri": "mongodb+srv://test19.test.build.10gen.cc/", "seeds": [], "hosts": [], "error": true, "comment": "Should fail because one of the returned host names' domain name parts \"evil\" mismatches \"test\"." } mongodb-mongo-python-driver-509e9b7/test/srv_seedlist/replica-set/returned-parent-too-short.json000066400000000000000000000003121462766011000332740ustar00rootroot00000000000000{ "uri": "mongodb+srv://test13.test.build.10gen.cc/", "seeds": [], "hosts": [], "error": true, "comment": "Should fail because returned host name's parent (build.10gen.cc) misses \"test.\"" } mongodb-mongo-python-driver-509e9b7/test/srv_seedlist/replica-set/returned-parent-wrong.json000066400000000000000000000003051462766011000324740ustar00rootroot00000000000000{ "uri": "mongodb+srv://test12.test.build.10gen.cc/", "seeds": [], "hosts": [], "error": true, "comment": "Should fail because returned host name is too short and mismatches a parent." } mongodb-mongo-python-driver-509e9b7/test/srv_seedlist/replica-set/srv-service-name.json000066400000000000000000000005501462766011000314130ustar00rootroot00000000000000{ "uri": "mongodb+srv://test22.test.build.10gen.cc/?srvServiceName=customname", "seeds": [ "localhost.test.build.10gen.cc:27017", "localhost.test.build.10gen.cc:27018" ], "hosts": [ "localhost:27017", "localhost:27018", "localhost:27019" ], "options": { "ssl": true, "srvServiceName": "customname" }, "ping": true } srvMaxHosts-conflicts_with_replicaSet-txt.json000066400000000000000000000003411462766011000364520ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/srv_seedlist/replica-set{ "uri": "mongodb+srv://test5.test.build.10gen.cc/?srvMaxHosts=1", "seeds": [], "hosts": [], "error": true, "comment": "Should fail because positive integer for srvMaxHosts conflicts with replicaSet option (TXT)" } srvMaxHosts-conflicts_with_replicaSet.json000066400000000000000000000003541462766011000356410ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/srv_seedlist/replica-set{ "uri": "mongodb+srv://test1.test.build.10gen.cc/?replicaSet=repl0&srvMaxHosts=1", "seeds": [], "hosts": [], "error": true, "comment": "Should fail because positive integer for srvMaxHosts conflicts with replicaSet option" } srvMaxHosts-equal_to_srv_records.json000066400000000000000000000005361462766011000346750ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/srv_seedlist/replica-set{ "uri": "mongodb+srv://test1.test.build.10gen.cc/?srvMaxHosts=2", "numSeeds": 2, "seeds": [ "localhost.test.build.10gen.cc:27017", "localhost.test.build.10gen.cc:27018" ], "hosts": [ "localhost:27017", "localhost:27018", "localhost:27019" ], "options": { "srvMaxHosts": 2, "ssl": true }, "ping": true } srvMaxHosts-greater_than_srv_records.json000066400000000000000000000005151462766011000355240ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/srv_seedlist/replica-set{ "uri": "mongodb+srv://test1.test.build.10gen.cc/?srvMaxHosts=3", "seeds": [ "localhost.test.build.10gen.cc:27017", "localhost.test.build.10gen.cc:27018" ], "hosts": [ "localhost:27017", "localhost:27018", "localhost:27019" ], "options": { "srvMaxHosts": 3, "ssl": true }, "ping": true } srvMaxHosts-less_than_srv_records.json000066400000000000000000000003671462766011000350460ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/srv_seedlist/replica-set{ "uri": "mongodb+srv://test1.test.build.10gen.cc/?srvMaxHosts=1", "numSeeds": 1, "hosts": [ "localhost:27017", "localhost:27018", "localhost:27019" ], "options": { "srvMaxHosts": 1, "ssl": true }, "ping": true } mongodb-mongo-python-driver-509e9b7/test/srv_seedlist/replica-set/srvMaxHosts-zero-txt.json000066400000000000000000000005311462766011000323170ustar00rootroot00000000000000{ "uri": "mongodb+srv://test5.test.build.10gen.cc/?srvMaxHosts=0", "seeds": [ "localhost.test.build.10gen.cc:27017" ], "hosts": [ "localhost:27017", "localhost:27018", "localhost:27019" ], "options": { "authSource": "thisDB", "replicaSet": "repl0", "srvMaxHosts": 0, "ssl": true }, "ping": true } mongodb-mongo-python-driver-509e9b7/test/srv_seedlist/replica-set/srvMaxHosts-zero.json000066400000000000000000000005711462766011000315060ustar00rootroot00000000000000{ "uri": "mongodb+srv://test1.test.build.10gen.cc/?replicaSet=repl0&srvMaxHosts=0", "seeds": [ "localhost.test.build.10gen.cc:27017", "localhost.test.build.10gen.cc:27018" ], "hosts": [ "localhost:27017", "localhost:27018", "localhost:27019" ], "options": { "replicaSet": "repl0", "srvMaxHosts": 0, "ssl": true }, "ping": true } mongodb-mongo-python-driver-509e9b7/test/srv_seedlist/replica-set/two-results-default-port.json000066400000000000000000000005251462766011000331430ustar00rootroot00000000000000{ "uri": "mongodb+srv://test1.test.build.10gen.cc/?replicaSet=repl0", "seeds": [ "localhost.test.build.10gen.cc:27017", "localhost.test.build.10gen.cc:27018" ], "hosts": [ "localhost:27017", "localhost:27018", "localhost:27019" ], "options": { "replicaSet": "repl0", "ssl": true }, "ping": true } mongodb-mongo-python-driver-509e9b7/test/srv_seedlist/replica-set/two-results-nonstandard-port.json000066400000000000000000000005251462766011000340320ustar00rootroot00000000000000{ "uri": "mongodb+srv://test2.test.build.10gen.cc/?replicaSet=repl0", "seeds": [ "localhost.test.build.10gen.cc:27018", "localhost.test.build.10gen.cc:27019" ], "hosts": [ "localhost:27017", "localhost:27018", "localhost:27019" ], "options": { "replicaSet": "repl0", "ssl": true }, "ping": true } mongodb-mongo-python-driver-509e9b7/test/srv_seedlist/replica-set/two-txt-records.json000066400000000000000000000002461462766011000313140ustar00rootroot00000000000000{ "uri": "mongodb+srv://test6.test.build.10gen.cc/", "seeds": [], "hosts": [], "error": true, "comment": "Should fail because there are two TXT records." } mongodb-mongo-python-driver-509e9b7/test/srv_seedlist/replica-set/txt-record-not-allowed-option.json000066400000000000000000000003071462766011000340510ustar00rootroot00000000000000{ "uri": "mongodb+srv://test10.test.build.10gen.cc/?replicaSet=repl0", "seeds": [], "hosts": [], "error": true, "comment": "Should fail because socketTimeoutMS is not an allowed option." } txt-record-with-overridden-ssl-option.json000066400000000000000000000005001462766011000354510ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/srv_seedlist/replica-set{ "uri": "mongodb+srv://test5.test.build.10gen.cc/?ssl=false", "seeds": [ "localhost.test.build.10gen.cc:27017" ], "hosts": [ "localhost:27017", "localhost:27018", "localhost:27019" ], "options": { "replicaSet": "repl0", "authSource": "thisDB", "ssl": false }, "ping": true } txt-record-with-overridden-uri-option.json000066400000000000000000000005111462766011000354510ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/srv_seedlist/replica-set{ "uri": "mongodb+srv://test5.test.build.10gen.cc/?authSource=otherDB", "seeds": [ "localhost.test.build.10gen.cc:27017" ], "hosts": [ "localhost:27017", "localhost:27018", "localhost:27019" ], "options": { "replicaSet": "repl0", "authSource": "otherDB", "ssl": true }, "ping": true } txt-record-with-unallowed-option.json000066400000000000000000000002551462766011000345120ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/srv_seedlist/replica-set{ "uri": "mongodb+srv://test7.test.build.10gen.cc/", "seeds": [], "hosts": [], "error": true, "comment": "Should fail because \"ssl\" is not an allowed option." } mongodb-mongo-python-driver-509e9b7/test/srv_seedlist/replica-set/uri-with-admin-database.json000066400000000000000000000006261462766011000326310ustar00rootroot00000000000000{ "uri": "mongodb+srv://test1.test.build.10gen.cc/adminDB?replicaSet=repl0", "seeds": [ "localhost.test.build.10gen.cc:27017", "localhost.test.build.10gen.cc:27018" ], "hosts": [ "localhost:27017", "localhost:27018", "localhost:27019" ], "options": { "replicaSet": "repl0", "ssl": true }, "parsed_options": { "auth_database": "adminDB" }, "ping": true } mongodb-mongo-python-driver-509e9b7/test/srv_seedlist/replica-set/uri-with-auth.json000066400000000000000000000007331462766011000307370ustar00rootroot00000000000000{ "uri": "mongodb+srv://auser:apass@test1.test.build.10gen.cc/?replicaSet=repl0", "seeds": [ "localhost.test.build.10gen.cc:27017", "localhost.test.build.10gen.cc:27018" ], "hosts": [ "localhost:27017", "localhost:27018", "localhost:27019" ], "options": { "replicaSet": "repl0", "ssl": true }, "parsed_options": { "user": "auser", "password": "apass" }, "ping": false, "comment": "Should preserve auth credentials" } mongodb-mongo-python-driver-509e9b7/test/srv_seedlist/replica-set/uri-with-port.json000066400000000000000000000003061462766011000307560ustar00rootroot00000000000000{ "uri": "mongodb+srv://test5.test.build.10gen.cc:8123/?replicaSet=repl0", "seeds": [], "hosts": [], "error": true, "comment": "Should fail because the mongodb+srv URI includes a port." } mongodb-mongo-python-driver-509e9b7/test/srv_seedlist/replica-set/uri-with-two-hosts.json000066400000000000000000000003431462766011000317420ustar00rootroot00000000000000{ "uri": "mongodb+srv://test5.test.build.10gen.cc,test6.test.build.10gen.cc/?replicaSet=repl0", "seeds": [], "hosts": [], "error": true, "comment": "Should fail because the mongodb+srv URI includes two host names." } mongodb-mongo-python-driver-509e9b7/test/srv_seedlist/replica-set/uri-with-uppercase-hostname.json000066400000000000000000000004501462766011000335750ustar00rootroot00000000000000{ "uri": "mongodb+srv://TEST1.TEST.BUILD.10GEN.CC", "seeds": [ "localhost.test.build.10gen.cc:27017", "localhost.test.build.10gen.cc:27018" ], "hosts": [ "localhost:27017", "localhost:27018", "localhost:27019" ], "options": { "ssl": true }, "ping": true } mongodb-mongo-python-driver-509e9b7/test/srv_seedlist/sharded/000077500000000000000000000000001462766011000245345ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/srv_seedlist/sharded/srvMaxHosts-equal_to_srv_records.json000066400000000000000000000005571462766011000341610ustar00rootroot00000000000000{ "uri": "mongodb+srv://test1.test.build.10gen.cc/?srvMaxHosts=2", "numSeeds": 2, "seeds": [ "localhost.test.build.10gen.cc:27017", "localhost.test.build.10gen.cc:27018" ], "hosts": [ "localhost.test.build.10gen.cc:27017", "localhost.test.build.10gen.cc:27018" ], "options": { "srvMaxHosts": 2, "ssl": true }, "ping": true } srvMaxHosts-greater_than_srv_records.json000066400000000000000000000005361462766011000347310ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/srv_seedlist/sharded{ "uri": "mongodb+srv://test1.test.build.10gen.cc/?srvMaxHosts=3", "seeds": [ "localhost.test.build.10gen.cc:27017", "localhost.test.build.10gen.cc:27018" ], "hosts": [ "localhost.test.build.10gen.cc:27017", "localhost.test.build.10gen.cc:27018" ], "options": { "srvMaxHosts": 3, "ssl": true }, "ping": true } mongodb-mongo-python-driver-509e9b7/test/srv_seedlist/sharded/srvMaxHosts-less_than_srv_records.json000066400000000000000000000002621462766011000343210ustar00rootroot00000000000000{ "uri": "mongodb+srv://test1.test.build.10gen.cc/?srvMaxHosts=1", "numSeeds": 1, "numHosts": 1, "options": { "srvMaxHosts": 1, "ssl": true }, "ping": true } mongodb-mongo-python-driver-509e9b7/test/srv_seedlist/sharded/srvMaxHosts-zero.json000066400000000000000000000005361462766011000307110ustar00rootroot00000000000000{ "uri": "mongodb+srv://test1.test.build.10gen.cc/?srvMaxHosts=0", "seeds": [ "localhost.test.build.10gen.cc:27017", "localhost.test.build.10gen.cc:27018" ], "hosts": [ "localhost.test.build.10gen.cc:27017", "localhost.test.build.10gen.cc:27018" ], "options": { "srvMaxHosts": 0, "ssl": true }, "ping": true } mongodb-mongo-python-driver-509e9b7/test/test_auth.py000066400000000000000000000604701462766011000227750ustar00rootroot00000000000000# Copyright 2013-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. """Authentication Tests.""" from __future__ import annotations import os import sys import threading from urllib.parse import quote_plus sys.path[0:0] = [""] from test import IntegrationTest, SkipTest, client_context, unittest from test.utils import ( AllowListEventListener, delay, ignore_deprecations, rs_or_single_client, rs_or_single_client_noauth, single_client, single_client_noauth, ) from pymongo import MongoClient, monitoring from pymongo.auth import HAVE_KERBEROS, _build_credentials_tuple from pymongo.errors import OperationFailure from pymongo.hello import HelloCompat from pymongo.read_preferences import ReadPreference from pymongo.saslprep import HAVE_STRINGPREP # YOU MUST RUN KINIT BEFORE RUNNING GSSAPI TESTS ON UNIX. GSSAPI_HOST = os.environ.get("GSSAPI_HOST") GSSAPI_PORT = int(os.environ.get("GSSAPI_PORT", "27017")) GSSAPI_PRINCIPAL = os.environ.get("GSSAPI_PRINCIPAL") GSSAPI_SERVICE_NAME = os.environ.get("GSSAPI_SERVICE_NAME", "mongodb") GSSAPI_CANONICALIZE = os.environ.get("GSSAPI_CANONICALIZE", "false") GSSAPI_SERVICE_REALM = os.environ.get("GSSAPI_SERVICE_REALM") GSSAPI_PASS = os.environ.get("GSSAPI_PASS") GSSAPI_DB = os.environ.get("GSSAPI_DB", "test") SASL_HOST = os.environ.get("SASL_HOST") SASL_PORT = int(os.environ.get("SASL_PORT", "27017")) SASL_USER = os.environ.get("SASL_USER") SASL_PASS = os.environ.get("SASL_PASS") SASL_DB = os.environ.get("SASL_DB", "$external") class AutoAuthenticateThread(threading.Thread): """Used in testing threaded authentication. This does collection.find_one() with a 1-second delay to ensure it must check out and authenticate multiple connections from the pool concurrently. :Parameters: `collection`: An auth-protected collection containing one document. """ def __init__(self, collection): super().__init__() self.collection = collection self.success = False def run(self): assert self.collection.find_one({"$where": delay(1)}) is not None self.success = True class TestGSSAPI(unittest.TestCase): mech_properties: str service_realm_required: bool @classmethod def setUpClass(cls): if not HAVE_KERBEROS: raise SkipTest("Kerberos module not available.") if not GSSAPI_HOST or not GSSAPI_PRINCIPAL: raise SkipTest("Must set GSSAPI_HOST and GSSAPI_PRINCIPAL to test GSSAPI") cls.service_realm_required = ( GSSAPI_SERVICE_REALM is not None and GSSAPI_SERVICE_REALM not in GSSAPI_PRINCIPAL ) mech_properties = f"SERVICE_NAME:{GSSAPI_SERVICE_NAME}" mech_properties += f",CANONICALIZE_HOST_NAME:{GSSAPI_CANONICALIZE}" if GSSAPI_SERVICE_REALM is not None: mech_properties += f",SERVICE_REALM:{GSSAPI_SERVICE_REALM}" cls.mech_properties = mech_properties def test_credentials_hashing(self): # GSSAPI credentials are properly hashed. creds0 = _build_credentials_tuple("GSSAPI", None, "user", "pass", {}, None) creds1 = _build_credentials_tuple( "GSSAPI", None, "user", "pass", {"authmechanismproperties": {"SERVICE_NAME": "A"}}, None ) creds2 = _build_credentials_tuple( "GSSAPI", None, "user", "pass", {"authmechanismproperties": {"SERVICE_NAME": "A"}}, None ) creds3 = _build_credentials_tuple( "GSSAPI", None, "user", "pass", {"authmechanismproperties": {"SERVICE_NAME": "B"}}, None ) self.assertEqual(1, len({creds1, creds2})) self.assertEqual(3, len({creds0, creds1, creds2, creds3})) @ignore_deprecations def test_gssapi_simple(self): assert GSSAPI_PRINCIPAL is not None if GSSAPI_PASS is not None: uri = "mongodb://%s:%s@%s:%d/?authMechanism=GSSAPI" % ( quote_plus(GSSAPI_PRINCIPAL), GSSAPI_PASS, GSSAPI_HOST, GSSAPI_PORT, ) else: uri = "mongodb://%s@%s:%d/?authMechanism=GSSAPI" % ( quote_plus(GSSAPI_PRINCIPAL), GSSAPI_HOST, GSSAPI_PORT, ) if not self.service_realm_required: # Without authMechanismProperties. client = MongoClient( GSSAPI_HOST, GSSAPI_PORT, username=GSSAPI_PRINCIPAL, password=GSSAPI_PASS, authMechanism="GSSAPI", ) client[GSSAPI_DB].collection.find_one() # Log in using URI, without authMechanismProperties. client = MongoClient(uri) client[GSSAPI_DB].collection.find_one() # Authenticate with authMechanismProperties. client = MongoClient( GSSAPI_HOST, GSSAPI_PORT, username=GSSAPI_PRINCIPAL, password=GSSAPI_PASS, authMechanism="GSSAPI", authMechanismProperties=self.mech_properties, ) client[GSSAPI_DB].collection.find_one() # Log in using URI, with authMechanismProperties. mech_uri = uri + f"&authMechanismProperties={self.mech_properties}" client = MongoClient(mech_uri) client[GSSAPI_DB].collection.find_one() set_name = client.admin.command(HelloCompat.LEGACY_CMD).get("setName") if set_name: if not self.service_realm_required: # Without authMechanismProperties client = MongoClient( GSSAPI_HOST, GSSAPI_PORT, username=GSSAPI_PRINCIPAL, password=GSSAPI_PASS, authMechanism="GSSAPI", replicaSet=set_name, ) client[GSSAPI_DB].list_collection_names() uri = uri + f"&replicaSet={set_name!s}" client = MongoClient(uri) client[GSSAPI_DB].list_collection_names() # With authMechanismProperties client = MongoClient( GSSAPI_HOST, GSSAPI_PORT, username=GSSAPI_PRINCIPAL, password=GSSAPI_PASS, authMechanism="GSSAPI", authMechanismProperties=self.mech_properties, replicaSet=set_name, ) client[GSSAPI_DB].list_collection_names() mech_uri = mech_uri + f"&replicaSet={set_name!s}" client = MongoClient(mech_uri) client[GSSAPI_DB].list_collection_names() @ignore_deprecations def test_gssapi_threaded(self): client = MongoClient( GSSAPI_HOST, GSSAPI_PORT, username=GSSAPI_PRINCIPAL, password=GSSAPI_PASS, authMechanism="GSSAPI", authMechanismProperties=self.mech_properties, ) # Authentication succeeded? client.server_info() db = client[GSSAPI_DB] # Need one document in the collection. AutoAuthenticateThread does # collection.find_one with a 1-second delay, forcing it to check out # multiple connections from the pool concurrently, proving that # auto-authentication works with GSSAPI. collection = db.test if not collection.count_documents({}): try: collection.drop() collection.insert_one({"_id": 1}) except OperationFailure: raise SkipTest("User must be able to write.") threads = [] for _ in range(4): threads.append(AutoAuthenticateThread(collection)) for thread in threads: thread.start() for thread in threads: thread.join() self.assertTrue(thread.success) set_name = client.admin.command(HelloCompat.LEGACY_CMD).get("setName") if set_name: client = MongoClient( GSSAPI_HOST, GSSAPI_PORT, username=GSSAPI_PRINCIPAL, password=GSSAPI_PASS, authMechanism="GSSAPI", authMechanismProperties=self.mech_properties, replicaSet=set_name, ) # Succeeded? client.server_info() threads = [] for _ in range(4): threads.append(AutoAuthenticateThread(collection)) for thread in threads: thread.start() for thread in threads: thread.join() self.assertTrue(thread.success) class TestSASLPlain(unittest.TestCase): @classmethod def setUpClass(cls): if not SASL_HOST or not SASL_USER or not SASL_PASS: raise SkipTest("Must set SASL_HOST, SASL_USER, and SASL_PASS to test SASL") def test_sasl_plain(self): client = MongoClient( SASL_HOST, SASL_PORT, username=SASL_USER, password=SASL_PASS, authSource=SASL_DB, authMechanism="PLAIN", ) client.ldap.test.find_one() assert SASL_USER is not None assert SASL_PASS is not None uri = "mongodb://%s:%s@%s:%d/?authMechanism=PLAIN;authSource=%s" % ( quote_plus(SASL_USER), quote_plus(SASL_PASS), SASL_HOST, SASL_PORT, SASL_DB, ) client = MongoClient(uri) client.ldap.test.find_one() set_name = client.admin.command(HelloCompat.LEGACY_CMD).get("setName") if set_name: client = MongoClient( SASL_HOST, SASL_PORT, replicaSet=set_name, username=SASL_USER, password=SASL_PASS, authSource=SASL_DB, authMechanism="PLAIN", ) client.ldap.test.find_one() uri = "mongodb://%s:%s@%s:%d/?authMechanism=PLAIN;authSource=%s;replicaSet=%s" % ( quote_plus(SASL_USER), quote_plus(SASL_PASS), SASL_HOST, SASL_PORT, SASL_DB, str(set_name), ) client = MongoClient(uri) client.ldap.test.find_one() def test_sasl_plain_bad_credentials(self): def auth_string(user, password): uri = "mongodb://%s:%s@%s:%d/?authMechanism=PLAIN;authSource=%s" % ( quote_plus(user), quote_plus(password), SASL_HOST, SASL_PORT, SASL_DB, ) return uri bad_user = MongoClient(auth_string("not-user", SASL_PASS)) bad_pwd = MongoClient(auth_string(SASL_USER, "not-pwd")) # OperationFailure raised upon connecting. self.assertRaises(OperationFailure, bad_user.admin.command, "ping") self.assertRaises(OperationFailure, bad_pwd.admin.command, "ping") class TestSCRAMSHA1(IntegrationTest): @client_context.require_auth def setUp(self): super().setUp() client_context.create_user("pymongo_test", "user", "pass", roles=["userAdmin", "readWrite"]) def tearDown(self): client_context.drop_user("pymongo_test", "user") super().tearDown() def test_scram_sha1(self): host, port = client_context.host, client_context.port client = rs_or_single_client_noauth( "mongodb://user:pass@%s:%d/pymongo_test?authMechanism=SCRAM-SHA-1" % (host, port) ) client.pymongo_test.command("dbstats") if client_context.is_rs: uri = ( "mongodb://user:pass" "@%s:%d/pymongo_test?authMechanism=SCRAM-SHA-1" "&replicaSet=%s" % (host, port, client_context.replica_set_name) ) client = single_client_noauth(uri) client.pymongo_test.command("dbstats") db = client.get_database("pymongo_test", read_preference=ReadPreference.SECONDARY) db.command("dbstats") # https://github.com/mongodb/specifications/blob/master/source/auth/auth.rst#scram-sha-256-and-mechanism-negotiation class TestSCRAM(IntegrationTest): @client_context.require_auth @client_context.require_version_min(3, 7, 2) def setUp(self): super().setUp() self._SENSITIVE_COMMANDS = monitoring._SENSITIVE_COMMANDS monitoring._SENSITIVE_COMMANDS = set() self.listener = AllowListEventListener("saslStart") def tearDown(self): monitoring._SENSITIVE_COMMANDS = self._SENSITIVE_COMMANDS client_context.client.testscram.command("dropAllUsersFromDatabase") client_context.client.drop_database("testscram") super().tearDown() def test_scram_skip_empty_exchange(self): listener = AllowListEventListener("saslStart", "saslContinue") client_context.create_user( "testscram", "sha256", "pwd", roles=["dbOwner"], mechanisms=["SCRAM-SHA-256"] ) client = rs_or_single_client_noauth( username="sha256", password="pwd", authSource="testscram", event_listeners=[listener] ) client.testscram.command("dbstats") if client_context.version < (4, 4, -1): # Assert we sent the skipEmptyExchange option. first_event = listener.started_events[0] self.assertEqual(first_event.command_name, "saslStart") self.assertEqual(first_event.command["options"], {"skipEmptyExchange": True}) # Assert the third exchange was skipped on servers that support it. # Note that the first exchange occurs on the connection handshake. started = listener.started_command_names() if client_context.version.at_least(4, 4, -1): self.assertEqual(started, ["saslContinue"]) else: self.assertEqual(started, ["saslStart", "saslContinue", "saslContinue"]) def test_scram(self): # Step 1: create users client_context.create_user( "testscram", "sha1", "pwd", roles=["dbOwner"], mechanisms=["SCRAM-SHA-1"] ) client_context.create_user( "testscram", "sha256", "pwd", roles=["dbOwner"], mechanisms=["SCRAM-SHA-256"] ) client_context.create_user( "testscram", "both", "pwd", roles=["dbOwner"], mechanisms=["SCRAM-SHA-1", "SCRAM-SHA-256"], ) # Step 2: verify auth success cases client = rs_or_single_client_noauth(username="sha1", password="pwd", authSource="testscram") client.testscram.command("dbstats") client = rs_or_single_client_noauth( username="sha1", password="pwd", authSource="testscram", authMechanism="SCRAM-SHA-1" ) client.testscram.command("dbstats") client = rs_or_single_client_noauth( username="sha256", password="pwd", authSource="testscram" ) client.testscram.command("dbstats") client = rs_or_single_client_noauth( username="sha256", password="pwd", authSource="testscram", authMechanism="SCRAM-SHA-256" ) client.testscram.command("dbstats") # Step 2: SCRAM-SHA-1 and SCRAM-SHA-256 client = rs_or_single_client_noauth( username="both", password="pwd", authSource="testscram", authMechanism="SCRAM-SHA-1" ) client.testscram.command("dbstats") client = rs_or_single_client_noauth( username="both", password="pwd", authSource="testscram", authMechanism="SCRAM-SHA-256" ) client.testscram.command("dbstats") self.listener.reset() client = rs_or_single_client_noauth( username="both", password="pwd", authSource="testscram", event_listeners=[self.listener] ) client.testscram.command("dbstats") if client_context.version.at_least(4, 4, -1): # Speculative authentication in 4.4+ sends saslStart with the # handshake. self.assertEqual(self.listener.started_events, []) else: started = self.listener.started_events[0] self.assertEqual(started.command.get("mechanism"), "SCRAM-SHA-256") # Step 3: verify auth failure conditions client = rs_or_single_client_noauth( username="sha1", password="pwd", authSource="testscram", authMechanism="SCRAM-SHA-256" ) with self.assertRaises(OperationFailure): client.testscram.command("dbstats") client = rs_or_single_client_noauth( username="sha256", password="pwd", authSource="testscram", authMechanism="SCRAM-SHA-1" ) with self.assertRaises(OperationFailure): client.testscram.command("dbstats") client = rs_or_single_client_noauth( username="not-a-user", password="pwd", authSource="testscram" ) with self.assertRaises(OperationFailure): client.testscram.command("dbstats") if client_context.is_rs: host, port = client_context.host, client_context.port uri = "mongodb://both:pwd@%s:%d/testscram?replicaSet=%s" % ( host, port, client_context.replica_set_name, ) client = single_client_noauth(uri) client.testscram.command("dbstats") db = client.get_database("testscram", read_preference=ReadPreference.SECONDARY) db.command("dbstats") @unittest.skipUnless(HAVE_STRINGPREP, "Cannot test without stringprep") def test_scram_saslprep(self): # Step 4: test SASLprep host, port = client_context.host, client_context.port # Test the use of SASLprep on passwords. For example, # saslprep('\u2136') becomes 'IV' and saslprep('I\u00ADX') # becomes 'IX'. SASLprep is only supported when the standard # library provides stringprep. client_context.create_user( "testscram", "\u2168", "\u2163", roles=["dbOwner"], mechanisms=["SCRAM-SHA-256"] ) client_context.create_user( "testscram", "IX", "IX", roles=["dbOwner"], mechanisms=["SCRAM-SHA-256"] ) client = rs_or_single_client_noauth( username="\u2168", password="\u2163", authSource="testscram" ) client.testscram.command("dbstats") client = rs_or_single_client_noauth( username="\u2168", password="\u2163", authSource="testscram", authMechanism="SCRAM-SHA-256", ) client.testscram.command("dbstats") client = rs_or_single_client_noauth( username="\u2168", password="IV", authSource="testscram" ) client.testscram.command("dbstats") client = rs_or_single_client_noauth( username="IX", password="I\u00ADX", authSource="testscram" ) client.testscram.command("dbstats") client = rs_or_single_client_noauth( username="IX", password="I\u00ADX", authSource="testscram", authMechanism="SCRAM-SHA-256", ) client.testscram.command("dbstats") client = rs_or_single_client_noauth( username="IX", password="IX", authSource="testscram", authMechanism="SCRAM-SHA-256" ) client.testscram.command("dbstats") client = rs_or_single_client_noauth( "mongodb://\u2168:\u2163@%s:%d/testscram" % (host, port) ) client.testscram.command("dbstats") client = rs_or_single_client_noauth("mongodb://\u2168:IV@%s:%d/testscram" % (host, port)) client.testscram.command("dbstats") client = rs_or_single_client_noauth("mongodb://IX:I\u00ADX@%s:%d/testscram" % (host, port)) client.testscram.command("dbstats") client = rs_or_single_client_noauth("mongodb://IX:IX@%s:%d/testscram" % (host, port)) client.testscram.command("dbstats") def test_cache(self): client = single_client() credentials = client.options.pool_options._credentials cache = credentials.cache self.assertIsNotNone(cache) self.assertIsNone(cache.data) # Force authentication. client.admin.command("ping") cache = credentials.cache self.assertIsNotNone(cache) data = cache.data self.assertIsNotNone(data) self.assertEqual(len(data), 4) ckey, skey, salt, iterations = data self.assertIsInstance(ckey, bytes) self.assertIsInstance(skey, bytes) self.assertIsInstance(salt, bytes) self.assertIsInstance(iterations, int) def test_scram_threaded(self): coll = client_context.client.db.test coll.drop() coll.insert_one({"_id": 1}) # The first thread to call find() will authenticate client = rs_or_single_client() self.addCleanup(client.close) coll = client.db.test threads = [] for _ in range(4): threads.append(AutoAuthenticateThread(coll)) for thread in threads: thread.start() for thread in threads: thread.join() self.assertTrue(thread.success) class TestAuthURIOptions(IntegrationTest): @client_context.require_auth def setUp(self): super().setUp() client_context.create_user("admin", "admin", "pass") client_context.create_user("pymongo_test", "user", "pass", ["userAdmin", "readWrite"]) def tearDown(self): client_context.drop_user("pymongo_test", "user") client_context.drop_user("admin", "admin") super().tearDown() def test_uri_options(self): # Test default to admin host, port = client_context.host, client_context.port client = rs_or_single_client_noauth("mongodb://admin:pass@%s:%d" % (host, port)) self.assertTrue(client.admin.command("dbstats")) if client_context.is_rs: uri = "mongodb://admin:pass@%s:%d/?replicaSet=%s" % ( host, port, client_context.replica_set_name, ) client = single_client_noauth(uri) self.assertTrue(client.admin.command("dbstats")) db = client.get_database("admin", read_preference=ReadPreference.SECONDARY) self.assertTrue(db.command("dbstats")) # Test explicit database uri = "mongodb://user:pass@%s:%d/pymongo_test" % (host, port) client = rs_or_single_client_noauth(uri) self.assertRaises(OperationFailure, client.admin.command, "dbstats") self.assertTrue(client.pymongo_test.command("dbstats")) if client_context.is_rs: uri = "mongodb://user:pass@%s:%d/pymongo_test?replicaSet=%s" % ( host, port, client_context.replica_set_name, ) client = single_client_noauth(uri) self.assertRaises(OperationFailure, client.admin.command, "dbstats") self.assertTrue(client.pymongo_test.command("dbstats")) db = client.get_database("pymongo_test", read_preference=ReadPreference.SECONDARY) self.assertTrue(db.command("dbstats")) # Test authSource uri = "mongodb://user:pass@%s:%d/pymongo_test2?authSource=pymongo_test" % (host, port) client = rs_or_single_client_noauth(uri) self.assertRaises(OperationFailure, client.pymongo_test2.command, "dbstats") self.assertTrue(client.pymongo_test.command("dbstats")) if client_context.is_rs: uri = ( "mongodb://user:pass@%s:%d/pymongo_test2?replicaSet=" "%s;authSource=pymongo_test" % (host, port, client_context.replica_set_name) ) client = single_client_noauth(uri) self.assertRaises(OperationFailure, client.pymongo_test2.command, "dbstats") self.assertTrue(client.pymongo_test.command("dbstats")) db = client.get_database("pymongo_test", read_preference=ReadPreference.SECONDARY) self.assertTrue(db.command("dbstats")) if __name__ == "__main__": unittest.main() mongodb-mongo-python-driver-509e9b7/test/test_auth_spec.py000066400000000000000000000070401462766011000240010ustar00rootroot00000000000000# Copyright 2018-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. """Run the auth spec tests.""" from __future__ import annotations import glob import json import os import sys import warnings sys.path[0:0] = [""] from test import unittest from test.unified_format import generate_test_classes from pymongo import MongoClient from pymongo.auth_oidc import OIDCCallback _TEST_PATH = os.path.join(os.path.dirname(os.path.realpath(__file__)), "auth") class TestAuthSpec(unittest.TestCase): pass class SampleHumanCallback(OIDCCallback): def fetch(self, context): pass def create_test(test_case): def run_test(self): uri = test_case["uri"] valid = test_case["valid"] credential = test_case.get("credential") if not valid: with warnings.catch_warnings(): warnings.simplefilter("default") self.assertRaises(Exception, MongoClient, uri, connect=False) else: client = MongoClient(uri, connect=False) credentials = client.options.pool_options._credentials if credential is None: self.assertIsNone(credentials) else: self.assertIsNotNone(credentials) self.assertEqual(credentials.username, credential["username"]) self.assertEqual(credentials.password, credential["password"]) self.assertEqual(credentials.source, credential["source"]) if credential["mechanism"] is not None: self.assertEqual(credentials.mechanism, credential["mechanism"]) else: self.assertEqual(credentials.mechanism, "DEFAULT") expected = credential["mechanism_properties"] if expected is not None: actual = credentials.mechanism_properties for key, value in expected.items(): self.assertEqual(getattr(actual, key.lower()), value) else: if credential["mechanism"] == "MONGODB-AWS": self.assertIsNone(credentials.mechanism_properties.aws_session_token) else: self.assertIsNone(credentials.mechanism_properties) return run_test def create_tests(): for filename in glob.glob(os.path.join(_TEST_PATH, "legacy", "*.json")): test_suffix, _ = os.path.splitext(os.path.basename(filename)) with open(filename) as auth_tests: test_cases = json.load(auth_tests)["tests"] for test_case in test_cases: if test_case.get("optional", False): continue test_method = create_test(test_case) name = str(test_case["description"].lower().replace(" ", "_")) setattr(TestAuthSpec, f"test_{test_suffix}_{name}", test_method) create_tests() globals().update( generate_test_classes( os.path.join(_TEST_PATH, "unified"), module=__name__, ) ) if __name__ == "__main__": unittest.main() mongodb-mongo-python-driver-509e9b7/test/test_binary.py000066400000000000000000000517521462766011000233230ustar00rootroot00000000000000# Copyright 2009-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. """Tests for the Binary wrapper.""" from __future__ import annotations import array import base64 import copy import mmap import pickle import sys import uuid from typing import Any sys.path[0:0] = [""] from test import IntegrationTest, client_context, unittest import bson from bson import decode, encode from bson.binary import * from bson.codec_options import CodecOptions from bson.son import SON from pymongo.common import validate_uuid_representation from pymongo.mongo_client import MongoClient from pymongo.write_concern import WriteConcern class TestBinary(unittest.TestCase): csharp_data: bytes java_data: bytes @classmethod def setUpClass(cls): # Generated by the Java driver from_java = ( b"bAAAAAdfaWQAUCBQxkVm+XdxJ9tOBW5ld2d1aWQAEAAAAAMIQkfACFu" b"Z/0RustLOU/G6Am5ld2d1aWRzdHJpbmcAJQAAAGZmOTk1YjA4LWMwND" b"ctNDIwOC1iYWYxLTUzY2VkMmIyNmU0NAAAbAAAAAdfaWQAUCBQxkVm+" b"XdxJ9tPBW5ld2d1aWQAEAAAAANgS/xhRXXv8kfIec+dYdyCAm5ld2d1" b"aWRzdHJpbmcAJQAAAGYyZWY3NTQ1LTYxZmMtNGI2MC04MmRjLTYxOWR" b"jZjc5Yzg0NwAAbAAAAAdfaWQAUCBQxkVm+XdxJ9tQBW5ld2d1aWQAEA" b"AAAAPqREIbhZPUJOSdHCJIgaqNAm5ld2d1aWRzdHJpbmcAJQAAADI0Z" b"DQ5Mzg1LTFiNDItNDRlYS04ZGFhLTgxNDgyMjFjOWRlNAAAbAAAAAdf" b"aWQAUCBQxkVm+XdxJ9tRBW5ld2d1aWQAEAAAAANjQBn/aQuNfRyfNyx" b"29COkAm5ld2d1aWRzdHJpbmcAJQAAADdkOGQwYjY5LWZmMTktNDA2My" b"1hNDIzLWY0NzYyYzM3OWYxYwAAbAAAAAdfaWQAUCBQxkVm+XdxJ9tSB" b"W5ld2d1aWQAEAAAAAMtSv/Et1cAQUFHUYevqxaLAm5ld2d1aWRzdHJp" b"bmcAJQAAADQxMDA1N2I3LWM0ZmYtNGEyZC04YjE2LWFiYWY4NzUxNDc" b"0MQAA" ) cls.java_data = base64.b64decode(from_java) # Generated by the .net driver from_csharp = ( b"ZAAAABBfaWQAAAAAAAVuZXdndWlkABAAAAAD+MkoCd/Jy0iYJ7Vhl" b"iF3BAJuZXdndWlkc3RyaW5nACUAAAAwOTI4YzlmOC1jOWRmLTQ4Y2" b"ItOTgyNy1iNTYxOTYyMTc3MDQAAGQAAAAQX2lkAAEAAAAFbmV3Z3V" b"pZAAQAAAAA9MD0oXQe6VOp7mK4jkttWUCbmV3Z3VpZHN0cmluZwAl" b"AAAAODVkMjAzZDMtN2JkMC00ZWE1LWE3YjktOGFlMjM5MmRiNTY1A" b"ABkAAAAEF9pZAACAAAABW5ld2d1aWQAEAAAAAPRmIO2auc/Tprq1Z" b"oQ1oNYAm5ld2d1aWRzdHJpbmcAJQAAAGI2ODM5OGQxLWU3NmEtNGU" b"zZi05YWVhLWQ1OWExMGQ2ODM1OAAAZAAAABBfaWQAAwAAAAVuZXdn" b"dWlkABAAAAADISpriopuTEaXIa7arYOCFAJuZXdndWlkc3RyaW5nA" b"CUAAAA4YTZiMmEyMS02ZThhLTQ2NGMtOTcyMS1hZWRhYWQ4MzgyMT" b"QAAGQAAAAQX2lkAAQAAAAFbmV3Z3VpZAAQAAAAA98eg0CFpGlPihP" b"MwOmYGOMCbmV3Z3VpZHN0cmluZwAlAAAANDA4MzFlZGYtYTQ4NS00" b"ZjY5LThhMTMtY2NjMGU5OTgxOGUzAAA=" ) cls.csharp_data = base64.b64decode(from_csharp) def test_binary(self): a_string = "hello world" a_binary = Binary(b"hello world") self.assertTrue(a_binary.startswith(b"hello")) self.assertTrue(a_binary.endswith(b"world")) self.assertTrue(isinstance(a_binary, Binary)) self.assertFalse(isinstance(a_string, Binary)) def test_exceptions(self): self.assertRaises(TypeError, Binary, None) self.assertRaises(TypeError, Binary, 5) self.assertRaises(TypeError, Binary, 10.2) self.assertRaises(TypeError, Binary, b"hello", None) self.assertRaises(TypeError, Binary, b"hello", "100") self.assertRaises(ValueError, Binary, b"hello", -1) self.assertRaises(ValueError, Binary, b"hello", 256) self.assertTrue(Binary(b"hello", 0)) self.assertTrue(Binary(b"hello", 255)) self.assertRaises(TypeError, Binary, "hello") def test_subtype(self): one = Binary(b"hello") self.assertEqual(one.subtype, 0) two = Binary(b"hello", 2) self.assertEqual(two.subtype, 2) three = Binary(b"hello", 100) self.assertEqual(three.subtype, 100) def test_equality(self): two = Binary(b"hello") three = Binary(b"hello", 100) self.assertNotEqual(two, three) self.assertEqual(three, Binary(b"hello", 100)) self.assertEqual(two, Binary(b"hello")) self.assertNotEqual(two, Binary(b"hello ")) self.assertNotEqual(b"hello", Binary(b"hello")) # Explicitly test inequality self.assertFalse(three != Binary(b"hello", 100)) self.assertFalse(two != Binary(b"hello")) def test_repr(self): one = Binary(b"hello world") self.assertEqual(repr(one), "Binary({}, 0)".format(repr(b"hello world"))) two = Binary(b"hello world", 2) self.assertEqual(repr(two), "Binary({}, 2)".format(repr(b"hello world"))) three = Binary(b"\x08\xFF") self.assertEqual(repr(three), "Binary({}, 0)".format(repr(b"\x08\xFF"))) four = Binary(b"\x08\xFF", 2) self.assertEqual(repr(four), "Binary({}, 2)".format(repr(b"\x08\xFF"))) five = Binary(b"test", 100) self.assertEqual(repr(five), "Binary({}, 100)".format(repr(b"test"))) def test_hash(self): one = Binary(b"hello world") two = Binary(b"hello world", 42) self.assertEqual(hash(Binary(b"hello world")), hash(one)) self.assertNotEqual(hash(one), hash(two)) self.assertEqual(hash(Binary(b"hello world", 42)), hash(two)) def test_uuid_subtype_4(self): """Only STANDARD should decode subtype 4 as native uuid.""" expected_uuid = uuid.uuid4() expected_bin = Binary(expected_uuid.bytes, 4) doc = {"uuid": expected_bin} encoded = encode(doc) for uuid_rep in ( UuidRepresentation.PYTHON_LEGACY, UuidRepresentation.JAVA_LEGACY, UuidRepresentation.CSHARP_LEGACY, ): opts = CodecOptions(uuid_representation=uuid_rep) self.assertEqual(expected_bin, decode(encoded, opts)["uuid"]) opts = CodecOptions(uuid_representation=UuidRepresentation.STANDARD) self.assertEqual(expected_uuid, decode(encoded, opts)["uuid"]) def test_legacy_java_uuid(self): # Test decoding data = self.java_data docs = bson.decode_all(data, CodecOptions(SON[str, Any], False, PYTHON_LEGACY)) for d in docs: self.assertNotEqual(d["newguid"], uuid.UUID(d["newguidstring"])) docs = bson.decode_all(data, CodecOptions(SON[str, Any], False, STANDARD)) for d in docs: self.assertNotEqual(d["newguid"], uuid.UUID(d["newguidstring"])) docs = bson.decode_all(data, CodecOptions(SON[str, Any], False, CSHARP_LEGACY)) for d in docs: self.assertNotEqual(d["newguid"], uuid.UUID(d["newguidstring"])) docs = bson.decode_all(data, CodecOptions(SON[str, Any], False, JAVA_LEGACY)) for d in docs: self.assertEqual(d["newguid"], uuid.UUID(d["newguidstring"])) # Test encoding encoded = b"".join( [encode(doc, False, CodecOptions(uuid_representation=PYTHON_LEGACY)) for doc in docs] ) self.assertNotEqual(data, encoded) encoded = b"".join( [encode(doc, False, CodecOptions(uuid_representation=STANDARD)) for doc in docs] ) self.assertNotEqual(data, encoded) encoded = b"".join( [encode(doc, False, CodecOptions(uuid_representation=CSHARP_LEGACY)) for doc in docs] ) self.assertNotEqual(data, encoded) encoded = b"".join( [encode(doc, False, CodecOptions(uuid_representation=JAVA_LEGACY)) for doc in docs] ) self.assertEqual(data, encoded) @client_context.require_connection def test_legacy_java_uuid_roundtrip(self): data = self.java_data docs = bson.decode_all(data, CodecOptions(SON[str, Any], False, JAVA_LEGACY)) client_context.client.pymongo_test.drop_collection("java_uuid") db = client_context.client.pymongo_test coll = db.get_collection("java_uuid", CodecOptions(uuid_representation=JAVA_LEGACY)) coll.insert_many(docs) self.assertEqual(5, coll.count_documents({})) for d in coll.find(): self.assertEqual(d["newguid"], uuid.UUID(d["newguidstring"])) coll = db.get_collection("java_uuid", CodecOptions(uuid_representation=PYTHON_LEGACY)) for d in coll.find(): self.assertNotEqual(d["newguid"], d["newguidstring"]) client_context.client.pymongo_test.drop_collection("java_uuid") def test_legacy_csharp_uuid(self): data = self.csharp_data # Test decoding docs = bson.decode_all(data, CodecOptions(SON[str, Any], False, PYTHON_LEGACY)) for d in docs: self.assertNotEqual(d["newguid"], uuid.UUID(d["newguidstring"])) docs = bson.decode_all(data, CodecOptions(SON[str, Any], False, STANDARD)) for d in docs: self.assertNotEqual(d["newguid"], uuid.UUID(d["newguidstring"])) docs = bson.decode_all(data, CodecOptions(SON[str, Any], False, JAVA_LEGACY)) for d in docs: self.assertNotEqual(d["newguid"], uuid.UUID(d["newguidstring"])) docs = bson.decode_all(data, CodecOptions(SON[str, Any], False, CSHARP_LEGACY)) for d in docs: self.assertEqual(d["newguid"], uuid.UUID(d["newguidstring"])) # Test encoding encoded = b"".join( [encode(doc, False, CodecOptions(uuid_representation=PYTHON_LEGACY)) for doc in docs] ) self.assertNotEqual(data, encoded) encoded = b"".join( [encode(doc, False, CodecOptions(uuid_representation=STANDARD)) for doc in docs] ) self.assertNotEqual(data, encoded) encoded = b"".join( [encode(doc, False, CodecOptions(uuid_representation=JAVA_LEGACY)) for doc in docs] ) self.assertNotEqual(data, encoded) encoded = b"".join( [encode(doc, False, CodecOptions(uuid_representation=CSHARP_LEGACY)) for doc in docs] ) self.assertEqual(data, encoded) @client_context.require_connection def test_legacy_csharp_uuid_roundtrip(self): data = self.csharp_data docs = bson.decode_all(data, CodecOptions(SON[str, Any], False, CSHARP_LEGACY)) client_context.client.pymongo_test.drop_collection("csharp_uuid") db = client_context.client.pymongo_test coll = db.get_collection("csharp_uuid", CodecOptions(uuid_representation=CSHARP_LEGACY)) coll.insert_many(docs) self.assertEqual(5, coll.count_documents({})) for d in coll.find(): self.assertEqual(d["newguid"], uuid.UUID(d["newguidstring"])) coll = db.get_collection("csharp_uuid", CodecOptions(uuid_representation=PYTHON_LEGACY)) for d in coll.find(): self.assertNotEqual(d["newguid"], d["newguidstring"]) client_context.client.pymongo_test.drop_collection("csharp_uuid") def test_uri_to_uuid(self): uri = "mongodb://foo/?uuidrepresentation=csharpLegacy" client = MongoClient(uri, connect=False) self.assertEqual(client.pymongo_test.test.codec_options.uuid_representation, CSHARP_LEGACY) @client_context.require_connection def test_uuid_queries(self): db = client_context.client.pymongo_test coll = db.test coll.drop() uu = uuid.uuid4() coll.insert_one({"uuid": Binary(uu.bytes, 3)}) self.assertEqual(1, coll.count_documents({})) # Test regular UUID queries (using subtype 4). coll = db.get_collection( "test", CodecOptions(uuid_representation=UuidRepresentation.STANDARD) ) self.assertEqual(0, coll.count_documents({"uuid": uu})) coll.insert_one({"uuid": uu}) self.assertEqual(2, coll.count_documents({})) docs = list(coll.find({"uuid": uu})) self.assertEqual(1, len(docs)) self.assertEqual(uu, docs[0]["uuid"]) # Test both. uu_legacy = Binary.from_uuid(uu, UuidRepresentation.PYTHON_LEGACY) predicate = {"uuid": {"$in": [uu, uu_legacy]}} self.assertEqual(2, coll.count_documents(predicate)) docs = list(coll.find(predicate)) self.assertEqual(2, len(docs)) coll.drop() def test_pickle(self): b1 = Binary(b"123", 2) # For testing backwards compatibility with pre-2.4 pymongo p = ( b"\x80\x03cbson.binary\nBinary\nq\x00C\x03123q\x01\x85q" b"\x02\x81q\x03}q\x04X\x10\x00\x00\x00_Binary__subtypeq" b"\x05K\x02sb." ) if not sys.version.startswith("3.0"): self.assertEqual(b1, pickle.loads(p)) for proto in range(pickle.HIGHEST_PROTOCOL + 1): self.assertEqual(b1, pickle.loads(pickle.dumps(b1, proto))) uu = uuid.uuid4() uul = Binary.from_uuid(uu, UuidRepresentation.PYTHON_LEGACY) self.assertEqual(uul, copy.copy(uul)) self.assertEqual(uul, copy.deepcopy(uul)) for proto in range(pickle.HIGHEST_PROTOCOL + 1): self.assertEqual(uul, pickle.loads(pickle.dumps(uul, proto))) def test_buffer_protocol(self): b0 = Binary(b"123", 2) self.assertEqual(b0, Binary(memoryview(b"123"), 2)) self.assertEqual(b0, Binary(bytearray(b"123"), 2)) with mmap.mmap(-1, len(b"123")) as mm: mm.write(b"123") mm.seek(0) self.assertEqual(b0, Binary(mm, 2)) self.assertEqual(b0, Binary(array.array("B", b"123"), 2)) class TestUuidSpecExplicitCoding(unittest.TestCase): uuid: uuid.UUID @classmethod def setUpClass(cls): super().setUpClass() cls.uuid = uuid.UUID("00112233445566778899AABBCCDDEEFF") @staticmethod def _hex_to_bytes(hexstring): return bytes.fromhex(hexstring) # Explicit encoding prose test #1 def test_encoding_1(self): obj = Binary.from_uuid(self.uuid) expected_obj = Binary(self._hex_to_bytes("00112233445566778899AABBCCDDEEFF"), 4) self.assertEqual(obj, expected_obj) def _test_encoding_w_uuid_rep(self, uuid_rep, expected_hexstring, expected_subtype): obj = Binary.from_uuid(self.uuid, uuid_rep) expected_obj = Binary(self._hex_to_bytes(expected_hexstring), expected_subtype) self.assertEqual(obj, expected_obj) # Explicit encoding prose test #2 def test_encoding_2(self): self._test_encoding_w_uuid_rep( UuidRepresentation.STANDARD, "00112233445566778899AABBCCDDEEFF", 4 ) # Explicit encoding prose test #3 def test_encoding_3(self): self._test_encoding_w_uuid_rep( UuidRepresentation.JAVA_LEGACY, "7766554433221100FFEEDDCCBBAA9988", 3 ) # Explicit encoding prose test #4 def test_encoding_4(self): self._test_encoding_w_uuid_rep( UuidRepresentation.CSHARP_LEGACY, "33221100554477668899AABBCCDDEEFF", 3 ) # Explicit encoding prose test #5 def test_encoding_5(self): self._test_encoding_w_uuid_rep( UuidRepresentation.PYTHON_LEGACY, "00112233445566778899AABBCCDDEEFF", 3 ) # Explicit encoding prose test #6 def test_encoding_6(self): with self.assertRaises(ValueError): Binary.from_uuid(self.uuid, UuidRepresentation.UNSPECIFIED) # Explicit decoding prose test #1 def test_decoding_1(self): obj = Binary(self._hex_to_bytes("00112233445566778899AABBCCDDEEFF"), 4) # Case i: self.assertEqual(obj.as_uuid(), self.uuid) # Case ii: self.assertEqual(obj.as_uuid(UuidRepresentation.STANDARD), self.uuid) # Cases iii-vi: for uuid_rep in ( UuidRepresentation.JAVA_LEGACY, UuidRepresentation.CSHARP_LEGACY, UuidRepresentation.PYTHON_LEGACY, ): with self.assertRaises(ValueError): obj.as_uuid(uuid_rep) def _test_decoding_legacy(self, hexstring, uuid_rep): obj = Binary(self._hex_to_bytes(hexstring), 3) # Case i: with self.assertRaises(ValueError): obj.as_uuid() # Cases ii-iii: for rep in (UuidRepresentation.STANDARD, UuidRepresentation.UNSPECIFIED): with self.assertRaises(ValueError): obj.as_uuid(rep) # Case iv: self.assertEqual(obj.as_uuid(uuid_rep), self.uuid) # Explicit decoding prose test #2 def test_decoding_2(self): self._test_decoding_legacy( "7766554433221100FFEEDDCCBBAA9988", UuidRepresentation.JAVA_LEGACY ) # Explicit decoding prose test #3 def test_decoding_3(self): self._test_decoding_legacy( "33221100554477668899AABBCCDDEEFF", UuidRepresentation.CSHARP_LEGACY ) # Explicit decoding prose test #4 def test_decoding_4(self): self._test_decoding_legacy( "00112233445566778899AABBCCDDEEFF", UuidRepresentation.PYTHON_LEGACY ) class TestUuidSpecImplicitCoding(IntegrationTest): uuid: uuid.UUID @classmethod def setUpClass(cls): super().setUpClass() cls.uuid = uuid.UUID("00112233445566778899AABBCCDDEEFF") @staticmethod def _hex_to_bytes(hexstring): return bytes.fromhex(hexstring) def _get_coll_w_uuid_rep(self, uuid_rep): codec_options = self.client.codec_options.with_options( uuid_representation=validate_uuid_representation(None, uuid_rep) ) coll = self.db.get_collection( "pymongo_test", codec_options=codec_options, write_concern=WriteConcern("majority") ) return coll def _test_encoding(self, uuid_rep, expected_hexstring, expected_subtype): coll = self._get_coll_w_uuid_rep(uuid_rep) coll.delete_many({}) coll.insert_one({"_id": self.uuid}) self.assertTrue( coll.find_one({"_id": Binary(self._hex_to_bytes(expected_hexstring), expected_subtype)}) ) # Implicit encoding prose test #1 def test_encoding_1(self): self._test_encoding("javaLegacy", "7766554433221100FFEEDDCCBBAA9988", 3) # Implicit encoding prose test #2 def test_encoding_2(self): self._test_encoding("csharpLegacy", "33221100554477668899AABBCCDDEEFF", 3) # Implicit encoding prose test #3 def test_encoding_3(self): self._test_encoding("pythonLegacy", "00112233445566778899AABBCCDDEEFF", 3) # Implicit encoding prose test #4 def test_encoding_4(self): self._test_encoding("standard", "00112233445566778899AABBCCDDEEFF", 4) # Implicit encoding prose test #5 def test_encoding_5(self): with self.assertRaises(ValueError): self._test_encoding("unspecified", "dummy", -1) def _test_decoding( self, client_uuid_representation_string, legacy_field_uuid_representation, expected_standard_field_value, expected_legacy_field_value, ): coll = self._get_coll_w_uuid_rep(client_uuid_representation_string) coll.drop() standard_val = Binary.from_uuid(self.uuid, UuidRepresentation.STANDARD) legacy_val = Binary.from_uuid(self.uuid, legacy_field_uuid_representation) coll.insert_one({"standard": standard_val, "legacy": legacy_val}) doc = coll.find_one() self.assertEqual(doc["standard"], expected_standard_field_value) self.assertEqual(doc["legacy"], expected_legacy_field_value) # Implicit decoding prose test #1 def test_decoding_1(self): standard_binary = Binary.from_uuid(self.uuid, UuidRepresentation.STANDARD) self._test_decoding( "javaLegacy", UuidRepresentation.JAVA_LEGACY, standard_binary, self.uuid ) self._test_decoding( "csharpLegacy", UuidRepresentation.CSHARP_LEGACY, standard_binary, self.uuid ) self._test_decoding( "pythonLegacy", UuidRepresentation.PYTHON_LEGACY, standard_binary, self.uuid ) # Implicit decoding pose test #2 def test_decoding_2(self): legacy_binary = Binary.from_uuid(self.uuid, UuidRepresentation.PYTHON_LEGACY) self._test_decoding("standard", UuidRepresentation.PYTHON_LEGACY, self.uuid, legacy_binary) # Implicit decoding pose test #3 def test_decoding_3(self): expected_standard_value = Binary.from_uuid(self.uuid, UuidRepresentation.STANDARD) for legacy_uuid_rep in ( UuidRepresentation.PYTHON_LEGACY, UuidRepresentation.CSHARP_LEGACY, UuidRepresentation.JAVA_LEGACY, ): expected_legacy_value = Binary.from_uuid(self.uuid, legacy_uuid_rep) self._test_decoding( "unspecified", legacy_uuid_rep, expected_standard_value, expected_legacy_value ) if __name__ == "__main__": unittest.main() mongodb-mongo-python-driver-509e9b7/test/test_bson.py000066400000000000000000001505201462766011000227710ustar00rootroot00000000000000# # Copyright 2009-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. """Test the bson module.""" from __future__ import annotations import array import collections import datetime import mmap import os import pickle import re import sys import tempfile import uuid from collections import OrderedDict, abc from io import BytesIO sys.path[0:0] = [""] from test import qcheck, unittest from test.utils import ExceptionCatchingThread import bson from bson import ( BSON, EPOCH_AWARE, DatetimeMS, Regex, _datetime_to_millis, decode, decode_all, decode_file_iter, decode_iter, encode, is_valid, ) from bson.binary import USER_DEFINED_SUBTYPE, Binary, UuidRepresentation from bson.code import Code from bson.codec_options import CodecOptions, DatetimeConversion from bson.datetime_ms import _DATETIME_ERROR_SUGGESTION from bson.dbref import DBRef from bson.errors import InvalidBSON, InvalidDocument from bson.int64 import Int64 from bson.max_key import MaxKey from bson.min_key import MinKey from bson.objectid import ObjectId from bson.son import SON from bson.timestamp import Timestamp from bson.tz_util import FixedOffset, utc class NotADict(abc.MutableMapping): """Non-dict type that implements the mapping protocol.""" def __init__(self, initial=None): if not initial: self._dict = {} else: self._dict = initial def __iter__(self): return iter(self._dict) def __getitem__(self, item): return self._dict[item] def __delitem__(self, item): del self._dict[item] def __setitem__(self, item, value): self._dict[item] = value def __len__(self): return len(self._dict) def __eq__(self, other): if isinstance(other, abc.Mapping): return all(self.get(k) == other.get(k) for k in self) return NotImplemented def __repr__(self): return "NotADict(%s)" % repr(self._dict) class DSTAwareTimezone(datetime.tzinfo): def __init__(self, offset, name, dst_start_month, dst_end_month): self.__offset = offset self.__dst_start_month = dst_start_month self.__dst_end_month = dst_end_month self.__name = name def _is_dst(self, dt): return self.__dst_start_month <= dt.month <= self.__dst_end_month def utcoffset(self, dt): return datetime.timedelta(minutes=self.__offset) + self.dst(dt) def dst(self, dt): if self._is_dst(dt): return datetime.timedelta(hours=1) return datetime.timedelta(0) def tzname(self, dt): return self.__name class TestBSON(unittest.TestCase): def assertInvalid(self, data): self.assertRaises(InvalidBSON, decode, data) def check_encode_then_decode(self, doc_class=dict, decoder=decode, encoder=encode): # Work around http://bugs.jython.org/issue1728 if sys.platform.startswith("java"): doc_class = SON def helper(doc): self.assertEqual(doc, (decoder(encoder(doc_class(doc))))) self.assertEqual(doc, decoder(encoder(doc))) helper({}) helper({"test": "hello"}) self.assertTrue(isinstance(decoder(encoder({"hello": "world"}))["hello"], str)) helper({"mike": -10120}) helper({"long": Int64(10)}) helper({"really big long": 2147483648}) helper({"hello": 0.0013109}) helper({"something": True}) helper({"false": False}) helper({"an array": [1, True, 3.8, "world"]}) helper({"an object": doc_class({"test": "something"})}) helper({"a binary": Binary(b"test", 100)}) helper({"a binary": Binary(b"test", 128)}) helper({"a binary": Binary(b"test", 254)}) helper({"another binary": Binary(b"test", 2)}) helper(SON([("test dst", datetime.datetime(1993, 4, 4, 2))])) helper(SON([("test negative dst", datetime.datetime(1, 1, 1, 1, 1, 1))])) helper({"big float": float(10000000000)}) helper({"ref": DBRef("coll", 5)}) helper({"ref": DBRef("coll", 5, foo="bar", bar=4)}) helper({"ref": DBRef("coll", 5, "foo")}) helper({"ref": DBRef("coll", 5, "foo", foo="bar")}) helper({"ref": Timestamp(1, 2)}) helper({"foo": MinKey()}) helper({"foo": MaxKey()}) helper({"$field": Code("function(){ return true; }")}) helper({"$field": Code("return function(){ return x; }", scope={"x": False})}) def encode_then_decode(doc): return doc_class(doc) == decoder(encode(doc), CodecOptions(document_class=doc_class)) qcheck.check_unittest(self, encode_then_decode, qcheck.gen_mongo_dict(3)) def test_encode_then_decode(self): self.check_encode_then_decode() def test_encode_then_decode_any_mapping(self): self.check_encode_then_decode(doc_class=NotADict) def test_encode_then_decode_legacy(self): self.check_encode_then_decode( encoder=BSON.encode, decoder=lambda *args: BSON(args[0]).decode(*args[1:]) ) def test_encode_then_decode_any_mapping_legacy(self): self.check_encode_then_decode( doc_class=NotADict, encoder=BSON.encode, decoder=lambda *args: BSON(args[0]).decode(*args[1:]), ) def test_encoding_defaultdict(self): dct = collections.defaultdict(dict, [("foo", "bar")]) # type: ignore[arg-type] encode(dct) self.assertEqual(dct, collections.defaultdict(dict, [("foo", "bar")])) def test_basic_validation(self): self.assertRaises(TypeError, is_valid, 100) self.assertRaises(TypeError, is_valid, "test") self.assertRaises(TypeError, is_valid, 10.4) self.assertInvalid(b"test") # the simplest valid BSON document self.assertTrue(is_valid(b"\x05\x00\x00\x00\x00")) self.assertTrue(is_valid(BSON(b"\x05\x00\x00\x00\x00"))) # failure cases self.assertInvalid(b"\x04\x00\x00\x00\x00") self.assertInvalid(b"\x05\x00\x00\x00\x01") self.assertInvalid(b"\x05\x00\x00\x00") self.assertInvalid(b"\x05\x00\x00\x00\x00\x00") self.assertInvalid(b"\x07\x00\x00\x00\x02a\x00\x78\x56\x34\x12") self.assertInvalid(b"\x09\x00\x00\x00\x10a\x00\x05\x00") self.assertInvalid(b"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00") self.assertInvalid(b"\x13\x00\x00\x00\x02foo\x00\x04\x00\x00\x00bar\x00\x00") self.assertInvalid( b"\x18\x00\x00\x00\x03foo\x00\x0f\x00\x00\x00\x10bar\x00\xff\xff\xff\x7f\x00\x00" ) self.assertInvalid(b"\x15\x00\x00\x00\x03foo\x00\x0c\x00\x00\x00\x08bar\x00\x01\x00\x00") self.assertInvalid( b"\x1c\x00\x00\x00\x03foo\x00" b"\x12\x00\x00\x00\x02bar\x00" b"\x05\x00\x00\x00baz\x00\x00\x00" ) self.assertInvalid(b"\x10\x00\x00\x00\x02a\x00\x04\x00\x00\x00abc\xff\x00") def test_bad_string_lengths(self): self.assertInvalid(b"\x0c\x00\x00\x00\x02\x00\x00\x00\x00\x00\x00\x00") self.assertInvalid(b"\x12\x00\x00\x00\x02\x00\xff\xff\xff\xfffoobar\x00\x00") self.assertInvalid(b"\x0c\x00\x00\x00\x0e\x00\x00\x00\x00\x00\x00\x00") self.assertInvalid(b"\x12\x00\x00\x00\x0e\x00\xff\xff\xff\xfffoobar\x00\x00") self.assertInvalid( b"\x18\x00\x00\x00\x0c\x00\x00\x00\x00\x00\x00RY\xb5j\xfa[\xd8A\xd6X]\x99\x00" ) self.assertInvalid( b"\x1e\x00\x00\x00\x0c\x00" b"\xff\xff\xff\xfffoobar\x00" b"RY\xb5j\xfa[\xd8A\xd6X]\x99\x00" ) self.assertInvalid(b"\x0c\x00\x00\x00\r\x00\x00\x00\x00\x00\x00\x00") self.assertInvalid(b"\x0c\x00\x00\x00\r\x00\xff\xff\xff\xff\x00\x00") self.assertInvalid( b"\x1c\x00\x00\x00\x0f\x00" b"\x15\x00\x00\x00\x00\x00" b"\x00\x00\x00\x0c\x00\x00" b"\x00\x02\x00\x01\x00\x00" b"\x00\x00\x00\x00" ) self.assertInvalid( b"\x1c\x00\x00\x00\x0f\x00" b"\x15\x00\x00\x00\xff\xff" b"\xff\xff\x00\x0c\x00\x00" b"\x00\x02\x00\x01\x00\x00" b"\x00\x00\x00\x00" ) self.assertInvalid( b"\x1c\x00\x00\x00\x0f\x00" b"\x15\x00\x00\x00\x01\x00" b"\x00\x00\x00\x0c\x00\x00" b"\x00\x02\x00\x00\x00\x00" b"\x00\x00\x00\x00" ) self.assertInvalid( b"\x1c\x00\x00\x00\x0f\x00" b"\x15\x00\x00\x00\x01\x00" b"\x00\x00\x00\x0c\x00\x00" b"\x00\x02\x00\xff\xff\xff" b"\xff\x00\x00\x00" ) def test_random_data_is_not_bson(self): qcheck.check_unittest( self, qcheck.isnt(is_valid), qcheck.gen_string(qcheck.gen_range(0, 40)) ) def test_basic_decode(self): self.assertEqual( {"test": "hello world"}, decode( b"\x1B\x00\x00\x00\x0E\x74\x65\x73\x74\x00\x0C" b"\x00\x00\x00\x68\x65\x6C\x6C\x6F\x20\x77\x6F" b"\x72\x6C\x64\x00\x00" ), ) self.assertEqual( [{"test": "hello world"}, {}], decode_all( b"\x1B\x00\x00\x00\x0E\x74\x65\x73\x74" b"\x00\x0C\x00\x00\x00\x68\x65\x6C\x6C" b"\x6f\x20\x77\x6F\x72\x6C\x64\x00\x00" b"\x05\x00\x00\x00\x00" ), ) self.assertEqual( [{"test": "hello world"}, {}], list( decode_iter( b"\x1B\x00\x00\x00\x0E\x74\x65\x73\x74" b"\x00\x0C\x00\x00\x00\x68\x65\x6C\x6C" b"\x6f\x20\x77\x6F\x72\x6C\x64\x00\x00" b"\x05\x00\x00\x00\x00" ) ), ) self.assertEqual( [{"test": "hello world"}, {}], list( decode_file_iter( BytesIO( b"\x1B\x00\x00\x00\x0E\x74\x65\x73\x74" b"\x00\x0C\x00\x00\x00\x68\x65\x6C\x6C" b"\x6f\x20\x77\x6F\x72\x6C\x64\x00\x00" b"\x05\x00\x00\x00\x00" ) ) ), ) def test_decode_all_buffer_protocol(self): docs = [{"foo": "bar"}, {}] bs = b"".join(map(encode, docs)) # type: ignore[arg-type] self.assertEqual(docs, decode_all(bytearray(bs))) self.assertEqual(docs, decode_all(memoryview(bs))) self.assertEqual(docs, decode_all(memoryview(b"1" + bs + b"1")[1:-1])) self.assertEqual(docs, decode_all(array.array("B", bs))) with mmap.mmap(-1, len(bs)) as mm: mm.write(bs) mm.seek(0) self.assertEqual(docs, decode_all(mm)) def test_decode_buffer_protocol(self): doc = {"foo": "bar"} bs = encode(doc) self.assertEqual(doc, decode(bs)) self.assertEqual(doc, decode(bytearray(bs))) self.assertEqual(doc, decode(memoryview(bs))) self.assertEqual(doc, decode(memoryview(b"1" + bs + b"1")[1:-1])) self.assertEqual(doc, decode(array.array("B", bs))) with mmap.mmap(-1, len(bs)) as mm: mm.write(bs) mm.seek(0) self.assertEqual(doc, decode(mm)) def test_invalid_decodes(self): # Invalid object size (not enough bytes in document for even # an object size of first object. # NOTE: decode_all and decode_iter don't care, not sure if they should? self.assertRaises(InvalidBSON, list, decode_file_iter(BytesIO(b"\x1B"))) bad_bsons = [ # An object size that's too small to even include the object size, # but is correctly encoded, along with a correct EOO (and no data). b"\x01\x00\x00\x00\x00", # One object, but with object size listed smaller than it is in the # data. ( b"\x1A\x00\x00\x00\x0E\x74\x65\x73\x74" b"\x00\x0C\x00\x00\x00\x68\x65\x6C\x6C" b"\x6f\x20\x77\x6F\x72\x6C\x64\x00\x00" b"\x05\x00\x00\x00\x00" ), # One object, missing the EOO at the end. ( b"\x1B\x00\x00\x00\x0E\x74\x65\x73\x74" b"\x00\x0C\x00\x00\x00\x68\x65\x6C\x6C" b"\x6f\x20\x77\x6F\x72\x6C\x64\x00\x00" b"\x05\x00\x00\x00" ), # One object, sized correctly, with a spot for an EOO, but the EOO # isn't 0x00. ( b"\x1B\x00\x00\x00\x0E\x74\x65\x73\x74" b"\x00\x0C\x00\x00\x00\x68\x65\x6C\x6C" b"\x6f\x20\x77\x6F\x72\x6C\x64\x00\x00" b"\x05\x00\x00\x00\xFF" ), ] for i, data in enumerate(bad_bsons): msg = f"bad_bson[{i}]" with self.assertRaises(InvalidBSON, msg=msg): decode_all(data) with self.assertRaises(InvalidBSON, msg=msg): list(decode_iter(data)) with self.assertRaises(InvalidBSON, msg=msg): list(decode_file_iter(BytesIO(data))) with tempfile.TemporaryFile() as scratch: scratch.write(data) scratch.seek(0, os.SEEK_SET) with self.assertRaises(InvalidBSON, msg=msg): list(decode_file_iter(scratch)) def test_invalid_field_name(self): # Decode a truncated field with self.assertRaises(InvalidBSON) as ctx: decode(b"\x0b\x00\x00\x00\x02field\x00") # Assert that the InvalidBSON error message is not empty. self.assertTrue(str(ctx.exception)) def test_data_timestamp(self): self.assertEqual( {"test": Timestamp(4, 20)}, decode(b"\x13\x00\x00\x00\x11\x74\x65\x73\x74\x00\x14\x00\x00\x00\x04\x00\x00\x00\x00"), ) def test_basic_encode(self): self.assertRaises(TypeError, encode, 100) self.assertRaises(TypeError, encode, "hello") self.assertRaises(TypeError, encode, None) self.assertRaises(TypeError, encode, []) self.assertEqual(encode({}), BSON(b"\x05\x00\x00\x00\x00")) self.assertEqual(encode({}), b"\x05\x00\x00\x00\x00") self.assertEqual( encode({"test": "hello world"}), b"\x1B\x00\x00\x00\x02\x74\x65\x73\x74\x00\x0C\x00" b"\x00\x00\x68\x65\x6C\x6C\x6F\x20\x77\x6F\x72\x6C" b"\x64\x00\x00", ) self.assertEqual( encode({"mike": 100}), b"\x0F\x00\x00\x00\x10\x6D\x69\x6B\x65\x00\x64\x00\x00\x00\x00", ) self.assertEqual( encode({"hello": 1.5}), b"\x14\x00\x00\x00\x01\x68\x65\x6C\x6C\x6F\x00\x00\x00\x00\x00\x00\x00\xF8\x3F\x00", ) self.assertEqual( encode({"true": True}), b"\x0C\x00\x00\x00\x08\x74\x72\x75\x65\x00\x01\x00" ) self.assertEqual( encode({"false": False}), b"\x0D\x00\x00\x00\x08\x66\x61\x6C\x73\x65\x00\x00\x00" ) self.assertEqual( encode({"empty": []}), b"\x11\x00\x00\x00\x04\x65\x6D\x70\x74\x79\x00\x05\x00\x00\x00\x00\x00", ) self.assertEqual( encode({"none": {}}), b"\x10\x00\x00\x00\x03\x6E\x6F\x6E\x65\x00\x05\x00\x00\x00\x00\x00", ) self.assertEqual( encode({"test": Binary(b"test", 0)}), b"\x14\x00\x00\x00\x05\x74\x65\x73\x74\x00\x04\x00\x00\x00\x00\x74\x65\x73\x74\x00", ) self.assertEqual( encode({"test": Binary(b"test", 2)}), b"\x18\x00\x00\x00\x05\x74\x65\x73\x74\x00\x08\x00" b"\x00\x00\x02\x04\x00\x00\x00\x74\x65\x73\x74\x00", ) self.assertEqual( encode({"test": Binary(b"test", 128)}), b"\x14\x00\x00\x00\x05\x74\x65\x73\x74\x00\x04\x00\x00\x00\x80\x74\x65\x73\x74\x00", ) self.assertEqual(encode({"test": None}), b"\x0B\x00\x00\x00\x0A\x74\x65\x73\x74\x00\x00") self.assertEqual( encode({"date": datetime.datetime(2007, 1, 8, 0, 30, 11)}), b"\x13\x00\x00\x00\x09\x64\x61\x74\x65\x00\x38\xBE\x1C\xFF\x0F\x01\x00\x00\x00", ) self.assertEqual( encode({"regex": re.compile(b"a*b", re.IGNORECASE)}), b"\x12\x00\x00\x00\x0B\x72\x65\x67\x65\x78\x00\x61\x2A\x62\x00\x69\x00\x00", ) self.assertEqual( encode({"$where": Code("test")}), b"\x16\x00\x00\x00\r$where\x00\x05\x00\x00\x00test\x00\x00", ) self.assertEqual( encode({"$field": Code("function(){ return true;}", scope=None)}), b"+\x00\x00\x00\r$field\x00\x1a\x00\x00\x00function(){ return true;}\x00\x00", ) self.assertEqual( encode({"$field": Code("return function(){ return x; }", scope={"x": False})}), b"=\x00\x00\x00\x0f$field\x000\x00\x00\x00\x1f\x00" b"\x00\x00return function(){ return x; }\x00\t\x00" b"\x00\x00\x08x\x00\x00\x00\x00", ) unicode_empty_scope = Code("function(){ return 'héllo';}", {}) self.assertEqual( encode({"$field": unicode_empty_scope}), b"8\x00\x00\x00\x0f$field\x00+\x00\x00\x00\x1e\x00" b"\x00\x00function(){ return 'h\xc3\xa9llo';}\x00\x05" b"\x00\x00\x00\x00\x00", ) a = ObjectId(b"\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B") self.assertEqual( encode({"oid": a}), b"\x16\x00\x00\x00\x07\x6F\x69\x64\x00\x00\x01\x02" b"\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x00", ) self.assertEqual( encode({"ref": DBRef("coll", a)}), b"\x2F\x00\x00\x00\x03ref\x00\x25\x00\x00\x00\x02" b"$ref\x00\x05\x00\x00\x00coll\x00\x07$id\x00\x00" b"\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x00" b"\x00", ) def test_unknown_type(self): # Repr value differs with major python version part = "type {!r} for fieldname 'foo'".format(b"\x14") docs = [ b"\x0e\x00\x00\x00\x14foo\x00\x01\x00\x00\x00\x00", (b"\x16\x00\x00\x00\x04foo\x00\x0c\x00\x00\x00\x140\x00\x01\x00\x00\x00\x00\x00"), ( b" \x00\x00\x00\x04bar\x00\x16\x00\x00\x00\x030\x00\x0e\x00\x00" b"\x00\x14foo\x00\x01\x00\x00\x00\x00\x00\x00" ), ] for bs in docs: try: decode(bs) except Exception as exc: self.assertTrue(isinstance(exc, InvalidBSON)) self.assertTrue(part in str(exc)) else: self.fail("Failed to raise an exception.") def test_dbpointer(self): # *Note* - DBPointer and DBRef are *not* the same thing. DBPointer # is a deprecated BSON type. DBRef is a convention that does not # exist in the BSON spec, meant to replace DBPointer. PyMongo does # not support creation of the DBPointer type, but will decode # DBPointer to DBRef. bs = b"\x18\x00\x00\x00\x0c\x00\x01\x00\x00\x00\x00RY\xb5j\xfa[\xd8A\xd6X]\x99\x00" self.assertEqual({"": DBRef("", ObjectId("5259b56afa5bd841d6585d99"))}, decode(bs)) def test_bad_dbref(self): ref_only = {"ref": {"$ref": "collection"}} id_only = {"ref": {"$id": ObjectId()}} self.assertEqual(ref_only, decode(encode(ref_only))) self.assertEqual(id_only, decode(encode(id_only))) def test_bytes_as_keys(self): doc = {b"foo": "bar"} # Since `bytes` are stored as Binary you can't use them # as keys. Using binary data as a key makes no sense in BSON # anyway and little sense in python. self.assertRaises(InvalidDocument, encode, doc) def test_datetime_encode_decode(self): # Negative timestamps dt1 = datetime.datetime(1, 1, 1, 1, 1, 1, 111000) dt2 = decode(encode({"date": dt1}))["date"] self.assertEqual(dt1, dt2) dt1 = datetime.datetime(1959, 6, 25, 12, 16, 59, 999000) dt2 = decode(encode({"date": dt1}))["date"] self.assertEqual(dt1, dt2) # Positive timestamps dt1 = datetime.datetime(9999, 12, 31, 23, 59, 59, 999000) dt2 = decode(encode({"date": dt1}))["date"] self.assertEqual(dt1, dt2) dt1 = datetime.datetime(2011, 6, 14, 10, 47, 53, 444000) dt2 = decode(encode({"date": dt1}))["date"] self.assertEqual(dt1, dt2) def test_large_datetime_truncation(self): # Ensure that a large datetime is truncated correctly. dt1 = datetime.datetime(9999, 1, 1, 1, 1, 1, 999999) dt2 = decode(encode({"date": dt1}))["date"] self.assertEqual(dt2.microsecond, 999000) self.assertEqual(dt2.second, dt1.second) def test_aware_datetime(self): aware = datetime.datetime(1993, 4, 4, 2, tzinfo=FixedOffset(555, "SomeZone")) offset = aware.utcoffset() assert offset is not None as_utc = (aware - offset).replace(tzinfo=utc) self.assertEqual(datetime.datetime(1993, 4, 3, 16, 45, tzinfo=utc), as_utc) after = decode(encode({"date": aware}), CodecOptions(tz_aware=True))["date"] self.assertEqual(utc, after.tzinfo) self.assertEqual(as_utc, after) def test_local_datetime(self): # Timezone -60 minutes of UTC, with DST between April and July. tz = DSTAwareTimezone(60, "sixty-minutes", 4, 7) # It's not DST. local = datetime.datetime(year=2025, month=12, hour=2, day=1, tzinfo=tz) options = CodecOptions(tz_aware=True, tzinfo=tz) # Encode with this timezone, then decode to UTC. encoded = encode({"date": local}, codec_options=options) self.assertEqual(local.replace(hour=1, tzinfo=None), decode(encoded)["date"]) # It's DST. local = datetime.datetime(year=2025, month=4, hour=1, day=1, tzinfo=tz) encoded = encode({"date": local}, codec_options=options) self.assertEqual( local.replace(month=3, day=31, hour=23, tzinfo=None), decode(encoded)["date"] ) # Encode UTC, then decode in a different timezone. encoded = encode({"date": local.replace(tzinfo=utc)}) decoded = decode(encoded, options)["date"] self.assertEqual(local.replace(hour=3), decoded) self.assertEqual(tz, decoded.tzinfo) # Test round-tripping. self.assertEqual( local, decode(encode({"date": local}, codec_options=options), options)["date"] ) # Test around the Unix Epoch. epochs = ( EPOCH_AWARE, EPOCH_AWARE.astimezone(FixedOffset(120, "one twenty")), EPOCH_AWARE.astimezone(FixedOffset(-120, "minus one twenty")), ) utc_co = CodecOptions(tz_aware=True) for epoch in epochs: doc = {"epoch": epoch} # We always retrieve datetimes in UTC unless told to do otherwise. self.assertEqual(EPOCH_AWARE, decode(encode(doc), codec_options=utc_co)["epoch"]) # Round-trip the epoch. local_co = CodecOptions(tz_aware=True, tzinfo=epoch.tzinfo) self.assertEqual(epoch, decode(encode(doc), codec_options=local_co)["epoch"]) def test_naive_decode(self): aware = datetime.datetime(1993, 4, 4, 2, tzinfo=FixedOffset(555, "SomeZone")) offset = aware.utcoffset() assert offset is not None naive_utc = (aware - offset).replace(tzinfo=None) self.assertEqual(datetime.datetime(1993, 4, 3, 16, 45), naive_utc) after = decode(encode({"date": aware}))["date"] self.assertEqual(None, after.tzinfo) self.assertEqual(naive_utc, after) def test_dst(self): d = {"x": datetime.datetime(1993, 4, 4, 2)} self.assertEqual(d, decode(encode(d))) @unittest.skip("Disabled due to http://bugs.python.org/issue25222") def test_bad_encode(self): evil_list: dict = {"a": []} evil_list["a"].append(evil_list) evil_dict: dict = {} evil_dict["a"] = evil_dict for evil_data in [evil_dict, evil_list]: self.assertRaises(Exception, encode, evil_data) def test_overflow(self): self.assertTrue(encode({"x": 9223372036854775807})) self.assertRaises(OverflowError, encode, {"x": 9223372036854775808}) self.assertTrue(encode({"x": -9223372036854775808})) self.assertRaises(OverflowError, encode, {"x": -9223372036854775809}) def test_small_long_encode_decode(self): encoded1 = encode({"x": 256}) decoded1 = decode(encoded1)["x"] self.assertEqual(256, decoded1) self.assertEqual(int, type(decoded1)) encoded2 = encode({"x": Int64(256)}) decoded2 = decode(encoded2)["x"] expected = Int64(256) self.assertEqual(expected, decoded2) self.assertEqual(type(expected), type(decoded2)) self.assertNotEqual(type(decoded1), type(decoded2)) def test_tuple(self): self.assertEqual({"tuple": [1, 2]}, decode(encode({"tuple": (1, 2)}))) def test_uuid(self): id = uuid.uuid4() # The default uuid_representation is UNSPECIFIED with self.assertRaisesRegex(ValueError, "cannot encode native uuid"): bson.decode_all(encode({"uuid": id})) opts = CodecOptions(uuid_representation=UuidRepresentation.STANDARD) transformed_id = decode(encode({"id": id}, codec_options=opts), codec_options=opts)["id"] self.assertTrue(isinstance(transformed_id, uuid.UUID)) self.assertEqual(id, transformed_id) self.assertNotEqual(uuid.uuid4(), transformed_id) def test_uuid_legacy(self): id = uuid.uuid4() legacy = Binary.from_uuid(id, UuidRepresentation.PYTHON_LEGACY) self.assertEqual(3, legacy.subtype) bin = decode(encode({"uuid": legacy}))["uuid"] self.assertTrue(isinstance(bin, Binary)) transformed = bin.as_uuid(UuidRepresentation.PYTHON_LEGACY) self.assertEqual(id, transformed) # The C extension was segfaulting on unicode RegExs, so we have this test # that doesn't really test anything but the lack of a segfault. def test_unicode_regex(self): regex = re.compile("revisi\xf3n") decode(encode({"regex": regex})) def test_non_string_keys(self): self.assertRaises(InvalidDocument, encode, {8.9: "test"}) def test_utf8(self): w = {"aéã‚": "aéã‚"} self.assertEqual(w, decode(encode(w))) # b'a\xe9' == "aé".encode("iso-8859-1") iso8859_bytes = b"a\xe9" y = {"hello": iso8859_bytes} # Stored as BSON binary subtype 0. out = decode(encode(y)) self.assertTrue(isinstance(out["hello"], bytes)) self.assertEqual(out["hello"], iso8859_bytes) def test_null_character(self): doc = {"a": "\x00"} self.assertEqual(doc, decode(encode(doc))) doc = {"a": "\x00"} self.assertEqual(doc, decode(encode(doc))) self.assertRaises(InvalidDocument, encode, {b"\x00": "a"}) self.assertRaises(InvalidDocument, encode, {"\x00": "a"}) self.assertRaises(InvalidDocument, encode, {"a": re.compile(b"ab\x00c")}) self.assertRaises(InvalidDocument, encode, {"a": re.compile("ab\x00c")}) def test_move_id(self): self.assertEqual( b"\x19\x00\x00\x00\x02_id\x00\x02\x00\x00\x00a\x00" b"\x02a\x00\x02\x00\x00\x00a\x00\x00", encode(SON([("a", "a"), ("_id", "a")])), ) self.assertEqual( b"\x2c\x00\x00\x00" b"\x02_id\x00\x02\x00\x00\x00b\x00" b"\x03b\x00" b"\x19\x00\x00\x00\x02a\x00\x02\x00\x00\x00a\x00" b"\x02_id\x00\x02\x00\x00\x00a\x00\x00\x00", encode(SON([("b", SON([("a", "a"), ("_id", "a")])), ("_id", "b")])), ) def test_dates(self): doc = {"early": datetime.datetime(1686, 5, 5), "late": datetime.datetime(2086, 5, 5)} try: self.assertEqual(doc, decode(encode(doc))) except ValueError: # Ignore ValueError when no C ext, since it's probably # a problem w/ 32-bit Python - we work around this in the # C ext, though. if bson.has_c(): raise def test_custom_class(self): self.assertIsInstance(decode(encode({})), dict) self.assertNotIsInstance(decode(encode({})), SON) self.assertIsInstance(decode(encode({}), CodecOptions(document_class=SON)), SON) # type: ignore[type-var] self.assertEqual(1, decode(encode({"x": 1}), CodecOptions(document_class=SON))["x"]) # type: ignore[type-var] x = encode({"x": [{"y": 1}]}) self.assertIsInstance(decode(x, CodecOptions(document_class=SON))["x"][0], SON) # type: ignore[type-var] def test_subclasses(self): # make sure we can serialize subclasses of native Python types. class _myint(int): pass class _myfloat(float): pass class _myunicode(str): pass d = {"a": _myint(42), "b": _myfloat(63.9), "c": _myunicode("hello world")} d2 = decode(encode(d)) for key, value in d2.items(): orig_value = d[key] orig_type = orig_value.__class__.__bases__[0] self.assertEqual(type(value), orig_type) self.assertEqual(value, orig_type(value)) def test_encode_type_marker(self): # Assert that a custom subclass can be BSON encoded based on the _type_marker attribute. class MyMaxKey: _type_marker = 127 expected_bson = encode({"a": MaxKey()}) self.assertEqual(encode({"a": MyMaxKey()}), expected_bson) # Test a class that inherits from two built in types class MyBinary(Binary): pass expected_bson = encode({"a": Binary(b"bin", USER_DEFINED_SUBTYPE)}) self.assertEqual(encode({"a": MyBinary(b"bin", USER_DEFINED_SUBTYPE)}), expected_bson) def test_ordered_dict(self): d = OrderedDict([("one", 1), ("two", 2), ("three", 3), ("four", 4)]) self.assertEqual(d, decode(encode(d), CodecOptions(document_class=OrderedDict))) # type: ignore[type-var] def test_bson_regex(self): # Invalid Python regex, though valid PCRE. bson_re1 = Regex(r"[\w-\.]") self.assertEqual(r"[\w-\.]", bson_re1.pattern) self.assertEqual(0, bson_re1.flags) doc1 = {"r": bson_re1} doc1_bson = ( b"\x11\x00\x00\x00\x0br\x00[\\w-\\.]\x00\x00\x00" ) # document length # r: regex # document terminator self.assertEqual(doc1_bson, encode(doc1)) self.assertEqual(doc1, decode(doc1_bson)) # Valid Python regex, with flags. re2 = re.compile(".*", re.I | re.M | re.S | re.U | re.X) bson_re2 = Regex(".*", re.I | re.M | re.S | re.U | re.X) doc2_with_re = {"r": re2} doc2_with_bson_re = {"r": bson_re2} doc2_bson = ( b"\x11\x00\x00\x00\x0br\x00.*\x00imsux\x00\x00" ) # document length # r: regex # document terminator self.assertEqual(doc2_bson, encode(doc2_with_re)) self.assertEqual(doc2_bson, encode(doc2_with_bson_re)) self.assertEqual(re2.pattern, decode(doc2_bson)["r"].pattern) self.assertEqual(re2.flags, decode(doc2_bson)["r"].flags) def test_regex_from_native(self): self.assertEqual(".*", Regex.from_native(re.compile(".*")).pattern) self.assertEqual(0, Regex.from_native(re.compile(b"")).flags) regex = re.compile(b"", re.I | re.L | re.M | re.S | re.X) self.assertEqual(re.I | re.L | re.M | re.S | re.X, Regex.from_native(regex).flags) unicode_regex = re.compile("", re.U) self.assertEqual(re.U, Regex.from_native(unicode_regex).flags) def test_regex_hash(self): self.assertRaises(TypeError, hash, Regex("hello")) def test_regex_comparison(self): re1 = Regex("a") re2 = Regex("b") self.assertNotEqual(re1, re2) re1 = Regex("a", re.I) re2 = Regex("a", re.M) self.assertNotEqual(re1, re2) re1 = Regex("a", re.I) re2 = Regex("a", re.I) self.assertEqual(re1, re2) def test_exception_wrapping(self): # No matter what exception is raised while trying to decode BSON, # the final exception always matches InvalidBSON. # {'s': '\xff'}, will throw attempting to decode utf-8. bad_doc = b"\x0f\x00\x00\x00\x02s\x00\x03\x00\x00\x00\xff\x00\x00\x00" with self.assertRaises(InvalidBSON) as context: decode_all(bad_doc) self.assertIn("codec can't decode byte 0xff", str(context.exception)) def test_minkey_maxkey_comparison(self): # MinKey's <, <=, >, >=, !=, and ==. self.assertTrue(MinKey() < None) self.assertTrue(MinKey() < 1) self.assertTrue(MinKey() <= 1) self.assertTrue(MinKey() <= MinKey()) self.assertFalse(MinKey() > None) self.assertFalse(MinKey() > 1) self.assertFalse(MinKey() >= 1) self.assertTrue(MinKey() >= MinKey()) self.assertTrue(MinKey() != 1) self.assertFalse(MinKey() == 1) self.assertTrue(MinKey() == MinKey()) # MinKey compared to MaxKey. self.assertTrue(MinKey() < MaxKey()) self.assertTrue(MinKey() <= MaxKey()) self.assertFalse(MinKey() > MaxKey()) self.assertFalse(MinKey() >= MaxKey()) self.assertTrue(MinKey() != MaxKey()) self.assertFalse(MinKey() == MaxKey()) # MaxKey's <, <=, >, >=, !=, and ==. self.assertFalse(MaxKey() < None) self.assertFalse(MaxKey() < 1) self.assertFalse(MaxKey() <= 1) self.assertTrue(MaxKey() <= MaxKey()) self.assertTrue(MaxKey() > None) self.assertTrue(MaxKey() > 1) self.assertTrue(MaxKey() >= 1) self.assertTrue(MaxKey() >= MaxKey()) self.assertTrue(MaxKey() != 1) self.assertFalse(MaxKey() == 1) self.assertTrue(MaxKey() == MaxKey()) # MaxKey compared to MinKey. self.assertFalse(MaxKey() < MinKey()) self.assertFalse(MaxKey() <= MinKey()) self.assertTrue(MaxKey() > MinKey()) self.assertTrue(MaxKey() >= MinKey()) self.assertTrue(MaxKey() != MinKey()) self.assertFalse(MaxKey() == MinKey()) def test_minkey_maxkey_hash(self): self.assertEqual(hash(MaxKey()), hash(MaxKey())) self.assertEqual(hash(MinKey()), hash(MinKey())) self.assertNotEqual(hash(MaxKey()), hash(MinKey())) def test_timestamp_comparison(self): # Timestamp is initialized with time, inc. Time is the more # significant comparand. self.assertTrue(Timestamp(1, 0) < Timestamp(2, 17)) self.assertTrue(Timestamp(2, 0) > Timestamp(1, 0)) self.assertTrue(Timestamp(1, 7) <= Timestamp(2, 0)) self.assertTrue(Timestamp(2, 0) >= Timestamp(1, 1)) self.assertTrue(Timestamp(2, 0) <= Timestamp(2, 0)) self.assertTrue(Timestamp(2, 0) >= Timestamp(2, 0)) self.assertFalse(Timestamp(1, 0) > Timestamp(2, 0)) # Comparison by inc. self.assertTrue(Timestamp(1, 0) < Timestamp(1, 1)) self.assertTrue(Timestamp(1, 1) > Timestamp(1, 0)) self.assertTrue(Timestamp(1, 0) <= Timestamp(1, 0)) self.assertTrue(Timestamp(1, 0) <= Timestamp(1, 1)) self.assertFalse(Timestamp(1, 0) >= Timestamp(1, 1)) self.assertTrue(Timestamp(1, 0) >= Timestamp(1, 0)) self.assertTrue(Timestamp(1, 1) >= Timestamp(1, 0)) self.assertFalse(Timestamp(1, 1) <= Timestamp(1, 0)) self.assertTrue(Timestamp(1, 0) <= Timestamp(1, 0)) self.assertFalse(Timestamp(1, 0) > Timestamp(1, 0)) def test_timestamp_highorder_bits(self): doc = {"a": Timestamp(0xFFFFFFFF, 0xFFFFFFFF)} doc_bson = b"\x10\x00\x00\x00\x11a\x00\xff\xff\xff\xff\xff\xff\xff\xff\x00" self.assertEqual(doc_bson, encode(doc)) self.assertEqual(doc, decode(doc_bson)) def test_bad_id_keys(self): self.assertRaises(InvalidDocument, encode, {"_id": {"$bad": 123}}, True) self.assertRaises( InvalidDocument, encode, {"_id": {"$oid": "52d0b971b3ba219fdeb4170e"}}, True ) encode({"_id": {"$oid": "52d0b971b3ba219fdeb4170e"}}) def test_bson_encode_thread_safe(self): def target(i): for j in range(1000): my_int = type(f"MyInt_{i}_{j}", (int,), {}) bson.encode({"my_int": my_int()}) threads = [ExceptionCatchingThread(target=target, args=(i,)) for i in range(3)] for t in threads: t.start() for t in threads: t.join() for t in threads: self.assertIsNone(t.exc) def test_raise_invalid_document(self): class Wrapper: def __init__(self, val): self.val = val def __repr__(self): return repr(self.val) self.assertEqual("1", repr(Wrapper(1))) with self.assertRaisesRegex( InvalidDocument, "cannot encode object: 1, of type: " + repr(Wrapper) ): encode({"t": Wrapper(1)}) class TestCodecOptions(unittest.TestCase): def test_document_class(self): self.assertRaises(TypeError, CodecOptions, document_class=object) self.assertIs(SON, CodecOptions(document_class=SON).document_class) # type: ignore[type-var] def test_tz_aware(self): self.assertRaises(TypeError, CodecOptions, tz_aware=1) self.assertFalse(CodecOptions().tz_aware) self.assertTrue(CodecOptions(tz_aware=True).tz_aware) def test_uuid_representation(self): self.assertRaises(ValueError, CodecOptions, uuid_representation=7) self.assertRaises(ValueError, CodecOptions, uuid_representation=2) def test_tzinfo(self): self.assertRaises(TypeError, CodecOptions, tzinfo="pacific") tz = FixedOffset(42, "forty-two") self.assertRaises(ValueError, CodecOptions, tzinfo=tz) self.assertEqual(tz, CodecOptions(tz_aware=True, tzinfo=tz).tzinfo) def test_codec_options_repr(self): r = ( "CodecOptions(document_class=dict, tz_aware=False, " "uuid_representation=UuidRepresentation.UNSPECIFIED, " "unicode_decode_error_handler='strict', " "tzinfo=None, type_registry=TypeRegistry(type_codecs=[], " "fallback_encoder=None), " "datetime_conversion=DatetimeConversion.DATETIME)" ) self.assertEqual(r, repr(CodecOptions())) def test_decode_all_defaults(self): # Test decode_all()'s default document_class is dict and tz_aware is # False. doc = {"sub_document": {}, "dt": datetime.datetime.now(tz=datetime.timezone.utc)} decoded = bson.decode_all(bson.encode(doc))[0] self.assertIsInstance(decoded["sub_document"], dict) self.assertIsNone(decoded["dt"].tzinfo) # The default uuid_representation is UNSPECIFIED with self.assertRaisesRegex(ValueError, "cannot encode native uuid"): bson.decode_all(bson.encode({"uuid": uuid.uuid4()})) def test_decode_all_no_options(self): # Test decode_all()'s default document_class is dict and tz_aware is # False. doc = {"sub_document": {}, "dt": datetime.datetime.now(tz=datetime.timezone.utc)} decoded = bson.decode_all(bson.encode(doc), None)[0] self.assertIsInstance(decoded["sub_document"], dict) self.assertIsNone(decoded["dt"].tzinfo) doc2 = {"id": Binary.from_uuid(uuid.uuid4())} decoded = bson.decode_all(bson.encode(doc2), None)[0] self.assertIsInstance(decoded["id"], Binary) def test_decode_all_kwarg(self): doc = {"a": uuid.uuid4()} opts = CodecOptions(uuid_representation=UuidRepresentation.STANDARD) encoded = encode(doc, codec_options=opts) # Positional codec_options self.assertEqual([doc], decode_all(encoded, opts)) # Keyword codec_options self.assertEqual([doc], decode_all(encoded, codec_options=opts)) def test_unicode_decode_error_handler(self): enc = encode({"keystr": "foobar"}) # Test handling of bad key value, bad string value, and both. invalid_key = enc[:7] + b"\xe9" + enc[8:] invalid_val = enc[:18] + b"\xe9" + enc[19:] invalid_both = enc[:7] + b"\xe9" + enc[8:18] + b"\xe9" + enc[19:] # Ensure that strict mode raises an error. for invalid in [invalid_key, invalid_val, invalid_both]: self.assertRaises( InvalidBSON, decode, invalid, CodecOptions(unicode_decode_error_handler="strict"), ) self.assertRaises(InvalidBSON, decode, invalid, CodecOptions()) self.assertRaises(InvalidBSON, decode, invalid) # Test all other error handlers. for handler in ["replace", "backslashreplace", "surrogateescape", "ignore"]: expected_key = b"ke\xe9str".decode("utf-8", handler) expected_val = b"fo\xe9bar".decode("utf-8", handler) doc = decode(invalid_key, CodecOptions(unicode_decode_error_handler=handler)) self.assertEqual(doc, {expected_key: "foobar"}) doc = decode(invalid_val, CodecOptions(unicode_decode_error_handler=handler)) self.assertEqual(doc, {"keystr": expected_val}) doc = decode(invalid_both, CodecOptions(unicode_decode_error_handler=handler)) self.assertEqual(doc, {expected_key: expected_val}) # Test handling bad error mode. dec = decode(enc, CodecOptions(unicode_decode_error_handler="junk")) self.assertEqual(dec, {"keystr": "foobar"}) self.assertRaises( InvalidBSON, decode, invalid_both, CodecOptions(unicode_decode_error_handler="junk"), ) def round_trip_pickle(self, obj, pickled_with_older): pickled_with_older_obj = pickle.loads(pickled_with_older) for protocol in range(pickle.HIGHEST_PROTOCOL + 1): pkl = pickle.dumps(obj, protocol=protocol) obj2 = pickle.loads(pkl) self.assertEqual(obj, obj2) self.assertEqual(pickled_with_older_obj, obj2) def test_regex_pickling(self): reg = Regex(".?") pickled_with_3 = ( b"\x80\x04\x959\x00\x00\x00\x00\x00\x00\x00\x8c\n" b"bson.regex\x94\x8c\x05Regex\x94\x93\x94)\x81\x94}" b"\x94(\x8c\x07pattern\x94\x8c\x02.?\x94\x8c\x05flag" b"s\x94K\x00ub." ) self.round_trip_pickle(reg, pickled_with_3) def test_timestamp_pickling(self): ts = Timestamp(0, 1) pickled_with_3 = ( b"\x80\x04\x95Q\x00\x00\x00\x00\x00\x00\x00\x8c" b"\x0ebson.timestamp\x94\x8c\tTimestamp\x94\x93\x94)" b"\x81\x94}\x94(" b"\x8c\x10_Timestamp__time\x94K\x00\x8c" b"\x0f_Timestamp__inc\x94K\x01ub." ) self.round_trip_pickle(ts, pickled_with_3) def test_dbref_pickling(self): dbr = DBRef("foo", 5) pickled_with_3 = ( b"\x80\x04\x95q\x00\x00\x00\x00\x00\x00\x00\x8c\n" b"bson.dbref\x94\x8c\x05DBRef\x94\x93\x94)\x81\x94}" b"\x94(\x8c\x12_DBRef__collection\x94\x8c\x03foo\x94" b"\x8c\n_DBRef__id\x94K\x05\x8c\x10_DBRef__database" b"\x94N\x8c\x0e_DBRef__kwargs\x94}\x94ub." ) self.round_trip_pickle(dbr, pickled_with_3) dbr = DBRef("foo", 5, database="db", kwargs1=None) pickled_with_3 = ( b"\x80\x04\x95\x81\x00\x00\x00\x00\x00\x00\x00\x8c" b"\nbson.dbref\x94\x8c\x05DBRef\x94\x93\x94)\x81\x94}" b"\x94(\x8c\x12_DBRef__collection\x94\x8c\x03foo\x94" b"\x8c\n_DBRef__id\x94K\x05\x8c\x10_DBRef__database" b"\x94\x8c\x02db\x94\x8c\x0e_DBRef__kwargs\x94}\x94" b"\x8c\x07kwargs1\x94Nsub." ) self.round_trip_pickle(dbr, pickled_with_3) def test_minkey_pickling(self): mink = MinKey() pickled_with_3 = ( b"\x80\x04\x95\x1e\x00\x00\x00\x00\x00\x00\x00\x8c" b"\x0cbson.min_key\x94\x8c\x06MinKey\x94\x93\x94)" b"\x81\x94." ) self.round_trip_pickle(mink, pickled_with_3) def test_maxkey_pickling(self): maxk = MaxKey() pickled_with_3 = ( b"\x80\x04\x95\x1e\x00\x00\x00\x00\x00\x00\x00\x8c" b"\x0cbson.max_key\x94\x8c\x06MaxKey\x94\x93\x94)" b"\x81\x94." ) self.round_trip_pickle(maxk, pickled_with_3) def test_int64_pickling(self): i64 = Int64(9) pickled_with_3 = ( b"\x80\x04\x95\x1e\x00\x00\x00\x00\x00\x00\x00\x8c\n" b"bson.int64\x94\x8c\x05Int64\x94\x93\x94K\t\x85\x94" b"\x81\x94." ) self.round_trip_pickle(i64, pickled_with_3) def test_bson_encode_decode(self) -> None: doc = {"_id": ObjectId()} encoded = bson.encode(doc) decoded = bson.decode(encoded) encoded = bson.encode(decoded) decoded = bson.decode(encoded) # Documents returned from decode are mutable. decoded["new_field"] = 1 self.assertTrue(decoded["_id"].generation_time) class TestDatetimeConversion(unittest.TestCase): def test_comps(self): # Tests other timestamp formats. # Test each of the rich comparison methods. pairs = [ (DatetimeMS(-1), DatetimeMS(1)), (DatetimeMS(0), DatetimeMS(0)), (DatetimeMS(1), DatetimeMS(-1)), ] comp_ops = ["__lt__", "__le__", "__eq__", "__ne__", "__gt__", "__ge__"] for lh, rh in pairs: for op in comp_ops: self.assertEqual(getattr(lh, op)(rh), getattr(lh._value, op)(rh._value)) def test_class_conversions(self): # Test class conversions. dtr1 = DatetimeMS(1234) dt1 = dtr1.as_datetime() self.assertEqual(dtr1, DatetimeMS(dt1)) dt2 = datetime.datetime(1969, 1, 1) dtr2 = DatetimeMS(dt2) self.assertEqual(dtr2.as_datetime(), dt2) # Test encode and decode without codec options. Expect: DatetimeMS => datetime dtr1 = DatetimeMS(0) enc1 = encode({"x": dtr1}) dec1 = decode(enc1) self.assertEqual(dec1["x"], datetime.datetime(1970, 1, 1)) self.assertNotEqual(type(dtr1), type(dec1["x"])) # Test encode and decode with codec options. Expect: UTCDateimteRaw => DatetimeMS opts1 = CodecOptions(datetime_conversion=DatetimeConversion.DATETIME_MS) enc1 = encode({"x": dtr1}) dec1 = decode(enc1, opts1) self.assertEqual(type(dtr1), type(dec1["x"])) self.assertEqual(dtr1, dec1["x"]) # Expect: datetime => DatetimeMS opts1 = CodecOptions(datetime_conversion=DatetimeConversion.DATETIME_MS) dt1 = datetime.datetime(1970, 1, 1, tzinfo=datetime.timezone.utc) enc1 = encode({"x": dt1}) dec1 = decode(enc1, opts1) self.assertEqual(dec1["x"], DatetimeMS(0)) self.assertNotEqual(dt1, type(dec1["x"])) def test_clamping(self): # Test clamping from below and above. opts1 = CodecOptions( datetime_conversion=DatetimeConversion.DATETIME_CLAMP, tz_aware=True, tzinfo=datetime.timezone.utc, ) below = encode({"x": DatetimeMS(_datetime_to_millis(datetime.datetime.min) - 1)}) dec_below = decode(below, opts1) self.assertEqual( dec_below["x"], datetime.datetime.min.replace(tzinfo=datetime.timezone.utc) ) above = encode({"x": DatetimeMS(_datetime_to_millis(datetime.datetime.max) + 1)}) dec_above = decode(above, opts1) self.assertEqual( dec_above["x"], datetime.datetime.max.replace(tzinfo=datetime.timezone.utc, microsecond=999000), ) def test_tz_clamping(self): # Naive clamping to local tz. opts1 = CodecOptions(datetime_conversion=DatetimeConversion.DATETIME_CLAMP, tz_aware=False) below = encode({"x": DatetimeMS(_datetime_to_millis(datetime.datetime.min) - 24 * 60 * 60)}) dec_below = decode(below, opts1) self.assertEqual(dec_below["x"], datetime.datetime.min) above = encode({"x": DatetimeMS(_datetime_to_millis(datetime.datetime.max) + 24 * 60 * 60)}) dec_above = decode(above, opts1) self.assertEqual( dec_above["x"], datetime.datetime.max.replace(microsecond=999000), ) # Aware clamping. opts2 = CodecOptions(datetime_conversion=DatetimeConversion.DATETIME_CLAMP, tz_aware=True) below = encode({"x": DatetimeMS(_datetime_to_millis(datetime.datetime.min) - 24 * 60 * 60)}) dec_below = decode(below, opts2) self.assertEqual( dec_below["x"], datetime.datetime.min.replace(tzinfo=datetime.timezone.utc) ) above = encode({"x": DatetimeMS(_datetime_to_millis(datetime.datetime.max) + 24 * 60 * 60)}) dec_above = decode(above, opts2) self.assertEqual( dec_above["x"], datetime.datetime.max.replace(tzinfo=datetime.timezone.utc, microsecond=999000), ) def test_datetime_auto(self): # Naive auto, in range. opts1 = CodecOptions(datetime_conversion=DatetimeConversion.DATETIME_AUTO) inr = encode({"x": datetime.datetime(1970, 1, 1)}, codec_options=opts1) dec_inr = decode(inr) self.assertEqual(dec_inr["x"], datetime.datetime(1970, 1, 1)) # Naive auto, below range. below = encode({"x": DatetimeMS(_datetime_to_millis(datetime.datetime.min) - 24 * 60 * 60)}) dec_below = decode(below, opts1) self.assertEqual( dec_below["x"], DatetimeMS(_datetime_to_millis(datetime.datetime.min) - 24 * 60 * 60) ) # Naive auto, above range. above = encode({"x": DatetimeMS(_datetime_to_millis(datetime.datetime.max) + 24 * 60 * 60)}) dec_above = decode(above, opts1) self.assertEqual( dec_above["x"], DatetimeMS(_datetime_to_millis(datetime.datetime.max) + 24 * 60 * 60), ) # Aware auto, in range. opts2 = CodecOptions( datetime_conversion=DatetimeConversion.DATETIME_AUTO, tz_aware=True, tzinfo=datetime.timezone.utc, ) inr = encode({"x": datetime.datetime(1970, 1, 1)}, codec_options=opts2) dec_inr = decode(inr) self.assertEqual(dec_inr["x"], datetime.datetime(1970, 1, 1)) # Aware auto, below range. below = encode({"x": DatetimeMS(_datetime_to_millis(datetime.datetime.min) - 24 * 60 * 60)}) dec_below = decode(below, opts2) self.assertEqual( dec_below["x"], DatetimeMS(_datetime_to_millis(datetime.datetime.min) - 24 * 60 * 60) ) # Aware auto, above range. above = encode({"x": DatetimeMS(_datetime_to_millis(datetime.datetime.max) + 24 * 60 * 60)}) dec_above = decode(above, opts2) self.assertEqual( dec_above["x"], DatetimeMS(_datetime_to_millis(datetime.datetime.max) + 24 * 60 * 60), ) def test_millis_from_datetime_ms(self): # Test 65+ bit integer conversion, expect OverflowError. big_ms = 2**65 with self.assertRaises(OverflowError): encode({"x": DatetimeMS(big_ms)}) # Subclass of DatetimeMS w/ __int__ override, expect an Error. class DatetimeMSOverride(DatetimeMS): def __int__(self): return float(self._value) float_ms = DatetimeMSOverride(2) with self.assertRaises(TypeError): encode({"x": float_ms}) # Test InvalidBSON errors on conversion include _DATETIME_ERROR_SUGGESTION small_ms = -2 << 51 with self.assertRaisesRegex(InvalidBSON, re.compile(re.escape(_DATETIME_ERROR_SUGGESTION))): decode(encode({"a": DatetimeMS(small_ms)})) class TestLongLongToString(unittest.TestCase): def test_long_long_to_string(self): try: from bson import _cbson _cbson._test_long_long_to_str() except ImportError: print("_cbson was not imported. Check compilation logs.") if __name__ == "__main__": unittest.main() mongodb-mongo-python-driver-509e9b7/test/test_bson_corpus.py000066400000000000000000000231331462766011000243630ustar00rootroot00000000000000# Copyright 2016-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. """Run the BSON corpus specification tests.""" from __future__ import annotations import binascii import codecs import functools import glob import json import os import sys from decimal import DecimalException sys.path[0:0] = [""] from test import unittest from bson import decode, encode, json_util from bson.binary import STANDARD from bson.codec_options import CodecOptions from bson.dbref import DBRef from bson.decimal128 import Decimal128 from bson.errors import InvalidBSON, InvalidDocument, InvalidId from bson.json_util import JSONMode from bson.son import SON _TEST_PATH = os.path.join(os.path.dirname(os.path.realpath(__file__)), "bson_corpus") _TESTS_TO_SKIP = { # Python cannot decode dates after year 9999. "Y10K", } _NON_PARSE_ERRORS = { # {"$date": } is our legacy format which we still need to parse. "Bad $date (number, not string or hash)", # This variant of $numberLong may have been generated by an old version # of mongoexport. "Bad $numberLong (number, not string)", # Python's UUID constructor is very permissive. "$uuid invalid value--misplaced hyphens", # We parse Regex flags with extra characters, including nulls. "Null byte in $regularExpression options", } _IMPLCIT_LOSSY_TESTS = { # JSON decodes top-level $ref+$id as a DBRef but BSON doesn't. "Document with key names similar to those of a DBRef" } _DEPRECATED_BSON_TYPES = { # Symbol "0x0E": str, # Undefined "0x06": type(None), # DBPointer "0x0C": DBRef, } # Need to set tz_aware=True in order to use "strict" dates in extended JSON. codec_options: CodecOptions = CodecOptions(tz_aware=True, document_class=SON) codec_options_no_tzaware: CodecOptions = CodecOptions(document_class=SON) # We normally encode UUID as binary subtype 0x03, # but we'll need to encode to subtype 0x04 for one of the tests. codec_options_uuid_04 = codec_options._replace(uuid_representation=STANDARD) json_options_uuid_04 = json_util.JSONOptions( json_mode=JSONMode.CANONICAL, uuid_representation=STANDARD ) json_options_iso8601 = json_util.JSONOptions( datetime_representation=json_util.DatetimeRepresentation.ISO8601, json_mode=JSONMode.LEGACY ) to_extjson = functools.partial(json_util.dumps, json_options=json_util.CANONICAL_JSON_OPTIONS) to_extjson_uuid_04 = functools.partial(json_util.dumps, json_options=json_options_uuid_04) to_extjson_iso8601 = functools.partial(json_util.dumps, json_options=json_options_iso8601) to_relaxed_extjson = functools.partial(json_util.dumps, json_options=json_util.RELAXED_JSON_OPTIONS) to_bson_uuid_04 = functools.partial(encode, codec_options=codec_options_uuid_04) to_bson = functools.partial(encode, codec_options=codec_options) decode_bson = functools.partial(decode, codec_options=codec_options_no_tzaware) decode_extjson = functools.partial( json_util.loads, json_options=json_util.JSONOptions(json_mode=JSONMode.CANONICAL, document_class=SON), ) loads = functools.partial(json.loads, object_pairs_hook=SON) class TestBSONCorpus(unittest.TestCase): def assertJsonEqual(self, first, second, msg=None): """Fail if the two json strings are unequal. Normalize json by parsing it with the built-in json library. This accounts for discrepancies in spacing. """ self.assertEqual(loads(first), loads(second), msg=msg) def create_test(case_spec): bson_type = case_spec["bson_type"] # Test key is absent when testing top-level documents. test_key = case_spec.get("test_key") deprecated = case_spec.get("deprecated") def run_test(self): for valid_case in case_spec.get("valid", []): description = valid_case["description"] if description in _TESTS_TO_SKIP: continue # Special case for testing encoding UUID as binary subtype 0x04. if description.startswith("subtype 0x04"): encode_extjson = to_extjson_uuid_04 encode_bson = to_bson_uuid_04 else: encode_extjson = to_extjson encode_bson = to_bson cB = binascii.unhexlify(valid_case["canonical_bson"].encode("utf8")) cEJ = valid_case["canonical_extjson"] rEJ = valid_case.get("relaxed_extjson") dEJ = valid_case.get("degenerate_extjson") if description in _IMPLCIT_LOSSY_TESTS: valid_case.setdefault("lossy", True) lossy = valid_case.get("lossy") # BSON double, use lowercase 'e+' to match Python's encoding if bson_type == "0x01": cEJ = cEJ.replace("E+", "e+") decoded_bson = decode_bson(cB) if not lossy: # Make sure we can parse the legacy (default) JSON format. legacy_json = json_util.dumps( decoded_bson, json_options=json_util.LEGACY_JSON_OPTIONS ) self.assertEqual(decode_extjson(legacy_json), decoded_bson, description) if deprecated: if "converted_bson" in valid_case: converted_bson = binascii.unhexlify(valid_case["converted_bson"].encode("utf8")) self.assertEqual(encode_bson(decoded_bson), converted_bson) self.assertJsonEqual( encode_extjson(decode_bson(converted_bson)), valid_case["converted_extjson"] ) # Make sure we can decode the type. self.assertEqual(decoded_bson, decode_extjson(cEJ)) if test_key is not None: self.assertIsInstance(decoded_bson[test_key], _DEPRECATED_BSON_TYPES[bson_type]) continue # Jython can't handle NaN with a payload from # struct.(un)pack if endianness is specified in the format string. if not (sys.platform.startswith("java") and description == "NaN with payload"): # Test round-tripping canonical bson. self.assertEqual(encode_bson(decoded_bson), cB, description) self.assertJsonEqual(encode_extjson(decoded_bson), cEJ) # Test round-tripping canonical extended json. decoded_json = decode_extjson(cEJ) self.assertJsonEqual(encode_extjson(decoded_json), cEJ) if not lossy: self.assertEqual(encode_bson(decoded_json), cB) # Test round-tripping degenerate bson. if "degenerate_bson" in valid_case: dB = binascii.unhexlify(valid_case["degenerate_bson"].encode("utf8")) self.assertEqual(encode_bson(decode_bson(dB)), cB) # Test round-tripping degenerate extended json. if dEJ is not None: decoded_json = decode_extjson(dEJ) self.assertJsonEqual(encode_extjson(decoded_json), cEJ) if not lossy: self.assertEqual(encode_bson(decoded_json), cB) # Test round-tripping relaxed extended json. if rEJ is not None: self.assertJsonEqual(to_relaxed_extjson(decoded_bson), rEJ) decoded_json = decode_extjson(rEJ) self.assertJsonEqual(to_relaxed_extjson(decoded_json), rEJ) for decode_error_case in case_spec.get("decodeErrors", []): with self.assertRaises(InvalidBSON): decode_bson(binascii.unhexlify(decode_error_case["bson"].encode("utf8"))) for parse_error_case in case_spec.get("parseErrors", []): description = parse_error_case["description"] if description in _NON_PARSE_ERRORS: decode_extjson(parse_error_case["string"]) continue if bson_type == "0x13": self.assertRaises(DecimalException, Decimal128, parse_error_case["string"]) elif bson_type == "0x00": try: doc = decode_extjson(parse_error_case["string"]) # Null bytes are validated when encoding to BSON. if "Null" in description: to_bson(doc) raise AssertionError("exception not raised for test case: " + description) except (ValueError, KeyError, TypeError, InvalidId, InvalidDocument): pass elif bson_type == "0x05": try: decode_extjson(parse_error_case["string"]) raise AssertionError("exception not raised for test case: " + description) except (TypeError, ValueError): pass else: raise AssertionError("cannot test parseErrors for type " + bson_type) return run_test def create_tests(): for filename in glob.glob(os.path.join(_TEST_PATH, "*.json")): test_suffix, _ = os.path.splitext(os.path.basename(filename)) with codecs.open(filename, encoding="utf-8") as bson_test_file: test_method = create_test(json.load(bson_test_file)) setattr(TestBSONCorpus, "test_" + test_suffix, test_method) create_tests() if __name__ == "__main__": unittest.main() mongodb-mongo-python-driver-509e9b7/test/test_bulk.py000066400000000000000000001134421462766011000227670ustar00rootroot00000000000000# Copyright 2014-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. """Test the bulk API.""" from __future__ import annotations import sys import uuid from typing import Any, Optional from pymongo.mongo_client import MongoClient sys.path[0:0] = [""] from test import IntegrationTest, client_context, unittest from test.utils import ( remove_all_users, rs_or_single_client_noauth, single_client, wait_until, ) from bson.binary import Binary, UuidRepresentation from bson.codec_options import CodecOptions from bson.objectid import ObjectId from pymongo.collection import Collection from pymongo.common import partition_node from pymongo.errors import ( BulkWriteError, ConfigurationError, InvalidOperation, OperationFailure, ) from pymongo.operations import * from pymongo.write_concern import WriteConcern class BulkTestBase(IntegrationTest): coll: Collection coll_w0: Collection @classmethod def setUpClass(cls): super().setUpClass() cls.coll = cls.db.test cls.coll_w0 = cls.coll.with_options(write_concern=WriteConcern(w=0)) def setUp(self): super().setUp() self.coll.drop() def assertEqualResponse(self, expected, actual): """Compare response from bulk.execute() to expected response.""" for key, value in expected.items(): if key == "nModified": self.assertEqual(value, actual["nModified"]) elif key == "upserted": expected_upserts = value actual_upserts = actual["upserted"] self.assertEqual( len(expected_upserts), len(actual_upserts), 'Expected %d elements in "upserted", got %d' % (len(expected_upserts), len(actual_upserts)), ) for e, a in zip(expected_upserts, actual_upserts): self.assertEqualUpsert(e, a) elif key == "writeErrors": expected_errors = value actual_errors = actual["writeErrors"] self.assertEqual( len(expected_errors), len(actual_errors), 'Expected %d elements in "writeErrors", got %d' % (len(expected_errors), len(actual_errors)), ) for e, a in zip(expected_errors, actual_errors): self.assertEqualWriteError(e, a) else: self.assertEqual( actual.get(key), value, f"{key!r} value of {actual.get(key)!r} does not match expected {value!r}", ) def assertEqualUpsert(self, expected, actual): """Compare bulk.execute()['upserts'] to expected value. Like: {'index': 0, '_id': ObjectId()} """ self.assertEqual(expected["index"], actual["index"]) if expected["_id"] == "...": # Unspecified value. self.assertTrue("_id" in actual) else: self.assertEqual(expected["_id"], actual["_id"]) def assertEqualWriteError(self, expected, actual): """Compare bulk.execute()['writeErrors'] to expected value. Like: {'index': 0, 'code': 123, 'errmsg': '...', 'op': { ... }} """ self.assertEqual(expected["index"], actual["index"]) self.assertEqual(expected["code"], actual["code"]) if expected["errmsg"] == "...": # Unspecified value. self.assertTrue("errmsg" in actual) else: self.assertEqual(expected["errmsg"], actual["errmsg"]) expected_op = expected["op"].copy() actual_op = actual["op"].copy() if expected_op.get("_id") == "...": # Unspecified _id. self.assertTrue("_id" in actual_op) actual_op.pop("_id") expected_op.pop("_id") self.assertEqual(expected_op, actual_op) class TestBulk(BulkTestBase): def test_empty(self): self.assertRaises(InvalidOperation, self.coll.bulk_write, []) def test_insert(self): expected = { "nMatched": 0, "nModified": 0, "nUpserted": 0, "nInserted": 1, "nRemoved": 0, "upserted": [], "writeErrors": [], "writeConcernErrors": [], } result = self.coll.bulk_write([InsertOne({})]) self.assertEqualResponse(expected, result.bulk_api_result) self.assertEqual(1, result.inserted_count) self.assertEqual(1, self.coll.count_documents({})) def _test_update_many(self, update): expected = { "nMatched": 2, "nModified": 2, "nUpserted": 0, "nInserted": 0, "nRemoved": 0, "upserted": [], "writeErrors": [], "writeConcernErrors": [], } self.coll.insert_many([{}, {}]) result = self.coll.bulk_write([UpdateMany({}, update)]) self.assertEqualResponse(expected, result.bulk_api_result) self.assertEqual(2, result.matched_count) self.assertTrue(result.modified_count in (2, None)) def test_update_many(self): self._test_update_many({"$set": {"foo": "bar"}}) @client_context.require_version_min(4, 1, 11) def test_update_many_pipeline(self): self._test_update_many([{"$set": {"foo": "bar"}}]) def test_array_filters_validation(self): self.assertRaises(TypeError, UpdateMany, {}, {}, array_filters={}) self.assertRaises(TypeError, UpdateOne, {}, {}, array_filters={}) def test_array_filters_unacknowledged(self): coll = self.coll_w0 update_one = UpdateOne({}, {"$set": {"y.$[i].b": 5}}, array_filters=[{"i.b": 1}]) update_many = UpdateMany({}, {"$set": {"y.$[i].b": 5}}, array_filters=[{"i.b": 1}]) self.assertRaises(ConfigurationError, coll.bulk_write, [update_one]) self.assertRaises(ConfigurationError, coll.bulk_write, [update_many]) def _test_update_one(self, update): expected = { "nMatched": 1, "nModified": 1, "nUpserted": 0, "nInserted": 0, "nRemoved": 0, "upserted": [], "writeErrors": [], "writeConcernErrors": [], } self.coll.insert_many([{}, {}]) result = self.coll.bulk_write([UpdateOne({}, update)]) self.assertEqualResponse(expected, result.bulk_api_result) self.assertEqual(1, result.matched_count) self.assertTrue(result.modified_count in (1, None)) def test_update_one(self): self._test_update_one({"$set": {"foo": "bar"}}) @client_context.require_version_min(4, 1, 11) def test_update_one_pipeline(self): self._test_update_one([{"$set": {"foo": "bar"}}]) def test_replace_one(self): expected = { "nMatched": 1, "nModified": 1, "nUpserted": 0, "nInserted": 0, "nRemoved": 0, "upserted": [], "writeErrors": [], "writeConcernErrors": [], } self.coll.insert_many([{}, {}]) result = self.coll.bulk_write([ReplaceOne({}, {"foo": "bar"})]) self.assertEqualResponse(expected, result.bulk_api_result) self.assertEqual(1, result.matched_count) self.assertTrue(result.modified_count in (1, None)) def test_remove(self): # Test removing all documents, ordered. expected = { "nMatched": 0, "nModified": 0, "nUpserted": 0, "nInserted": 0, "nRemoved": 2, "upserted": [], "writeErrors": [], "writeConcernErrors": [], } self.coll.insert_many([{}, {}]) result = self.coll.bulk_write([DeleteMany({})]) self.assertEqualResponse(expected, result.bulk_api_result) self.assertEqual(2, result.deleted_count) def test_remove_one(self): # Test removing one document, empty selector. self.coll.insert_many([{}, {}]) expected = { "nMatched": 0, "nModified": 0, "nUpserted": 0, "nInserted": 0, "nRemoved": 1, "upserted": [], "writeErrors": [], "writeConcernErrors": [], } result = self.coll.bulk_write([DeleteOne({})]) self.assertEqualResponse(expected, result.bulk_api_result) self.assertEqual(1, result.deleted_count) self.assertEqual(self.coll.count_documents({}), 1) def test_upsert(self): expected = { "nMatched": 0, "nModified": 0, "nUpserted": 1, "nInserted": 0, "nRemoved": 0, "upserted": [{"index": 0, "_id": "..."}], } result = self.coll.bulk_write([ReplaceOne({}, {"foo": "bar"}, upsert=True)]) self.assertEqualResponse(expected, result.bulk_api_result) self.assertEqual(1, result.upserted_count) assert result.upserted_ids is not None self.assertEqual(1, len(result.upserted_ids)) self.assertTrue(isinstance(result.upserted_ids.get(0), ObjectId)) self.assertEqual(self.coll.count_documents({"foo": "bar"}), 1) def test_numerous_inserts(self): # Ensure we don't exceed server's maxWriteBatchSize size limit. n_docs = client_context.max_write_batch_size + 100 requests = [InsertOne[dict]({}) for _ in range(n_docs)] result = self.coll.bulk_write(requests, ordered=False) self.assertEqual(n_docs, result.inserted_count) self.assertEqual(n_docs, self.coll.count_documents({})) # Same with ordered bulk. self.coll.drop() result = self.coll.bulk_write(requests) self.assertEqual(n_docs, result.inserted_count) self.assertEqual(n_docs, self.coll.count_documents({})) def test_bulk_max_message_size(self): self.coll.delete_many({}) self.addCleanup(self.coll.delete_many, {}) _16_MB = 16 * 1000 * 1000 # Generate a list of documents such that the first batched OP_MSG is # as close as possible to the 48MB limit. docs = [ {"_id": 1, "l": "s" * _16_MB}, {"_id": 2, "l": "s" * _16_MB}, {"_id": 3, "l": "s" * (_16_MB - 10000)}, ] # Fill in the remaining ~10000 bytes with small documents. for i in range(4, 10000): docs.append({"_id": i}) result = self.coll.insert_many(docs) self.assertEqual(len(docs), len(result.inserted_ids)) def test_generator_insert(self): def gen(): yield {"a": 1, "b": 1} yield {"a": 1, "b": 2} yield {"a": 2, "b": 3} yield {"a": 3, "b": 5} yield {"a": 5, "b": 8} result = self.coll.insert_many(gen()) self.assertEqual(5, len(result.inserted_ids)) def test_bulk_write_no_results(self): result = self.coll_w0.bulk_write([InsertOne({})]) self.assertFalse(result.acknowledged) self.assertRaises(InvalidOperation, lambda: result.inserted_count) self.assertRaises(InvalidOperation, lambda: result.matched_count) self.assertRaises(InvalidOperation, lambda: result.modified_count) self.assertRaises(InvalidOperation, lambda: result.deleted_count) self.assertRaises(InvalidOperation, lambda: result.upserted_count) self.assertRaises(InvalidOperation, lambda: result.upserted_ids) def test_bulk_write_invalid_arguments(self): # The requests argument must be a list. generator = (InsertOne[dict]({}) for _ in range(10)) with self.assertRaises(TypeError): self.coll.bulk_write(generator) # type: ignore[arg-type] # Document is not wrapped in a bulk write operation. with self.assertRaises(TypeError): self.coll.bulk_write([{}]) # type: ignore[list-item] def test_upsert_large(self): big = "a" * (client_context.max_bson_size - 37) result = self.coll.bulk_write([UpdateOne({"x": 1}, {"$set": {"s": big}}, upsert=True)]) self.assertEqualResponse( { "nMatched": 0, "nModified": 0, "nUpserted": 1, "nInserted": 0, "nRemoved": 0, "upserted": [{"index": 0, "_id": "..."}], }, result.bulk_api_result, ) self.assertEqual(1, self.coll.count_documents({"x": 1})) def test_client_generated_upsert_id(self): result = self.coll.bulk_write( [ UpdateOne({"_id": 0}, {"$set": {"a": 0}}, upsert=True), ReplaceOne({"a": 1}, {"_id": 1}, upsert=True), # This is just here to make the counts right in all cases. ReplaceOne({"_id": 2}, {"_id": 2}, upsert=True), ] ) self.assertEqualResponse( { "nMatched": 0, "nModified": 0, "nUpserted": 3, "nInserted": 0, "nRemoved": 0, "upserted": [ {"index": 0, "_id": 0}, {"index": 1, "_id": 1}, {"index": 2, "_id": 2}, ], }, result.bulk_api_result, ) def test_upsert_uuid_standard(self): options = CodecOptions(uuid_representation=UuidRepresentation.STANDARD) coll = self.coll.with_options(codec_options=options) uuids = [uuid.uuid4() for _ in range(3)] result = coll.bulk_write( [ UpdateOne({"_id": uuids[0]}, {"$set": {"a": 0}}, upsert=True), ReplaceOne({"a": 1}, {"_id": uuids[1]}, upsert=True), # This is just here to make the counts right in all cases. ReplaceOne({"_id": uuids[2]}, {"_id": uuids[2]}, upsert=True), ] ) self.assertEqualResponse( { "nMatched": 0, "nModified": 0, "nUpserted": 3, "nInserted": 0, "nRemoved": 0, "upserted": [ {"index": 0, "_id": uuids[0]}, {"index": 1, "_id": uuids[1]}, {"index": 2, "_id": uuids[2]}, ], }, result.bulk_api_result, ) def test_upsert_uuid_unspecified(self): options = CodecOptions(uuid_representation=UuidRepresentation.UNSPECIFIED) coll = self.coll.with_options(codec_options=options) uuids = [Binary.from_uuid(uuid.uuid4()) for _ in range(3)] result = coll.bulk_write( [ UpdateOne({"_id": uuids[0]}, {"$set": {"a": 0}}, upsert=True), ReplaceOne({"a": 1}, {"_id": uuids[1]}, upsert=True), # This is just here to make the counts right in all cases. ReplaceOne({"_id": uuids[2]}, {"_id": uuids[2]}, upsert=True), ] ) self.assertEqualResponse( { "nMatched": 0, "nModified": 0, "nUpserted": 3, "nInserted": 0, "nRemoved": 0, "upserted": [ {"index": 0, "_id": uuids[0]}, {"index": 1, "_id": uuids[1]}, {"index": 2, "_id": uuids[2]}, ], }, result.bulk_api_result, ) def test_upsert_uuid_standard_subdocuments(self): options = CodecOptions(uuid_representation=UuidRepresentation.STANDARD) coll = self.coll.with_options(codec_options=options) ids: list = [{"f": Binary(bytes(i)), "f2": uuid.uuid4()} for i in range(3)] result = coll.bulk_write( [ UpdateOne({"_id": ids[0]}, {"$set": {"a": 0}}, upsert=True), ReplaceOne({"a": 1}, {"_id": ids[1]}, upsert=True), # This is just here to make the counts right in all cases. ReplaceOne({"_id": ids[2]}, {"_id": ids[2]}, upsert=True), ] ) # The `Binary` values are returned as `bytes` objects. for _id in ids: _id["f"] = bytes(_id["f"]) self.assertEqualResponse( { "nMatched": 0, "nModified": 0, "nUpserted": 3, "nInserted": 0, "nRemoved": 0, "upserted": [ {"index": 0, "_id": ids[0]}, {"index": 1, "_id": ids[1]}, {"index": 2, "_id": ids[2]}, ], }, result.bulk_api_result, ) def test_single_ordered_batch(self): result = self.coll.bulk_write( [ InsertOne({"a": 1}), UpdateOne({"a": 1}, {"$set": {"b": 1}}), UpdateOne({"a": 2}, {"$set": {"b": 2}}, upsert=True), InsertOne({"a": 3}), DeleteOne({"a": 3}), ] ) self.assertEqualResponse( { "nMatched": 1, "nModified": 1, "nUpserted": 1, "nInserted": 2, "nRemoved": 1, "upserted": [{"index": 2, "_id": "..."}], }, result.bulk_api_result, ) def test_single_error_ordered_batch(self): self.coll.create_index("a", unique=True) self.addCleanup(self.coll.drop_index, [("a", 1)]) requests: list = [ InsertOne({"b": 1, "a": 1}), UpdateOne({"b": 2}, {"$set": {"a": 1}}, upsert=True), InsertOne({"b": 3, "a": 2}), ] try: self.coll.bulk_write(requests) except BulkWriteError as exc: result = exc.details self.assertEqual(exc.code, 65) else: self.fail("Error not raised") self.assertEqualResponse( { "nMatched": 0, "nModified": 0, "nUpserted": 0, "nInserted": 1, "nRemoved": 0, "upserted": [], "writeConcernErrors": [], "writeErrors": [ { "index": 1, "code": 11000, "errmsg": "...", "op": { "q": {"b": 2}, "u": {"$set": {"a": 1}}, "multi": False, "upsert": True, }, } ], }, result, ) def test_multiple_error_ordered_batch(self): self.coll.create_index("a", unique=True) self.addCleanup(self.coll.drop_index, [("a", 1)]) requests: list = [ InsertOne({"b": 1, "a": 1}), UpdateOne({"b": 2}, {"$set": {"a": 1}}, upsert=True), UpdateOne({"b": 3}, {"$set": {"a": 2}}, upsert=True), UpdateOne({"b": 2}, {"$set": {"a": 1}}, upsert=True), InsertOne({"b": 4, "a": 3}), InsertOne({"b": 5, "a": 1}), ] try: self.coll.bulk_write(requests) except BulkWriteError as exc: result = exc.details self.assertEqual(exc.code, 65) else: self.fail("Error not raised") self.assertEqualResponse( { "nMatched": 0, "nModified": 0, "nUpserted": 0, "nInserted": 1, "nRemoved": 0, "upserted": [], "writeConcernErrors": [], "writeErrors": [ { "index": 1, "code": 11000, "errmsg": "...", "op": { "q": {"b": 2}, "u": {"$set": {"a": 1}}, "multi": False, "upsert": True, }, } ], }, result, ) def test_single_unordered_batch(self): requests: list = [ InsertOne({"a": 1}), UpdateOne({"a": 1}, {"$set": {"b": 1}}), UpdateOne({"a": 2}, {"$set": {"b": 2}}, upsert=True), InsertOne({"a": 3}), DeleteOne({"a": 3}), ] result = self.coll.bulk_write(requests, ordered=False) self.assertEqualResponse( { "nMatched": 1, "nModified": 1, "nUpserted": 1, "nInserted": 2, "nRemoved": 1, "upserted": [{"index": 2, "_id": "..."}], "writeErrors": [], "writeConcernErrors": [], }, result.bulk_api_result, ) def test_single_error_unordered_batch(self): self.coll.create_index("a", unique=True) self.addCleanup(self.coll.drop_index, [("a", 1)]) requests: list = [ InsertOne({"b": 1, "a": 1}), UpdateOne({"b": 2}, {"$set": {"a": 1}}, upsert=True), InsertOne({"b": 3, "a": 2}), ] try: self.coll.bulk_write(requests, ordered=False) except BulkWriteError as exc: result = exc.details self.assertEqual(exc.code, 65) else: self.fail("Error not raised") self.assertEqualResponse( { "nMatched": 0, "nModified": 0, "nUpserted": 0, "nInserted": 2, "nRemoved": 0, "upserted": [], "writeConcernErrors": [], "writeErrors": [ { "index": 1, "code": 11000, "errmsg": "...", "op": { "q": {"b": 2}, "u": {"$set": {"a": 1}}, "multi": False, "upsert": True, }, } ], }, result, ) def test_multiple_error_unordered_batch(self): self.coll.create_index("a", unique=True) self.addCleanup(self.coll.drop_index, [("a", 1)]) requests: list = [ InsertOne({"b": 1, "a": 1}), UpdateOne({"b": 2}, {"$set": {"a": 3}}, upsert=True), UpdateOne({"b": 3}, {"$set": {"a": 4}}, upsert=True), UpdateOne({"b": 4}, {"$set": {"a": 3}}, upsert=True), InsertOne({"b": 5, "a": 2}), InsertOne({"b": 6, "a": 1}), ] try: self.coll.bulk_write(requests, ordered=False) except BulkWriteError as exc: result = exc.details self.assertEqual(exc.code, 65) else: self.fail("Error not raised") # Assume the update at index 1 runs before the update at index 3, # although the spec does not require it. Same for inserts. self.assertEqualResponse( { "nMatched": 0, "nModified": 0, "nUpserted": 2, "nInserted": 2, "nRemoved": 0, "upserted": [{"index": 1, "_id": "..."}, {"index": 2, "_id": "..."}], "writeConcernErrors": [], "writeErrors": [ { "index": 3, "code": 11000, "errmsg": "...", "op": { "q": {"b": 4}, "u": {"$set": {"a": 3}}, "multi": False, "upsert": True, }, }, { "index": 5, "code": 11000, "errmsg": "...", "op": {"_id": "...", "b": 6, "a": 1}, }, ], }, result, ) def test_large_inserts_ordered(self): big = "x" * client_context.max_bson_size requests = [ InsertOne({"b": 1, "a": 1}), InsertOne({"big": big}), InsertOne({"b": 2, "a": 2}), ] try: self.coll.bulk_write(requests) except BulkWriteError as exc: result = exc.details self.assertEqual(exc.code, 65) else: self.fail("Error not raised") self.assertEqual(1, result["nInserted"]) self.coll.delete_many({}) big = "x" * (1024 * 1024 * 4) write_result = self.coll.bulk_write( [ InsertOne({"a": 1, "big": big}), InsertOne({"a": 2, "big": big}), InsertOne({"a": 3, "big": big}), InsertOne({"a": 4, "big": big}), InsertOne({"a": 5, "big": big}), InsertOne({"a": 6, "big": big}), ] ) self.assertEqual(6, write_result.inserted_count) self.assertEqual(6, self.coll.count_documents({})) def test_large_inserts_unordered(self): big = "x" * client_context.max_bson_size requests = [ InsertOne({"b": 1, "a": 1}), InsertOne({"big": big}), InsertOne({"b": 2, "a": 2}), ] try: self.coll.bulk_write(requests, ordered=False) except BulkWriteError as exc: details = exc.details self.assertEqual(exc.code, 65) else: self.fail("Error not raised") self.assertEqual(2, details["nInserted"]) self.coll.delete_many({}) big = "x" * (1024 * 1024 * 4) result = self.coll.bulk_write( [ InsertOne({"a": 1, "big": big}), InsertOne({"a": 2, "big": big}), InsertOne({"a": 3, "big": big}), InsertOne({"a": 4, "big": big}), InsertOne({"a": 5, "big": big}), InsertOne({"a": 6, "big": big}), ], ordered=False, ) self.assertEqual(6, result.inserted_count) self.assertEqual(6, self.coll.count_documents({})) class BulkAuthorizationTestBase(BulkTestBase): @classmethod @client_context.require_auth @client_context.require_no_api_version def setUpClass(cls): super().setUpClass() def setUp(self): super().setUp() client_context.create_user(self.db.name, "readonly", "pw", ["read"]) self.db.command( "createRole", "noremove", privileges=[ { "actions": ["insert", "update", "find"], "resource": {"db": "pymongo_test", "collection": "test"}, } ], roles=[], ) client_context.create_user(self.db.name, "noremove", "pw", ["noremove"]) def tearDown(self): self.db.command("dropRole", "noremove") remove_all_users(self.db) class TestBulkUnacknowledged(BulkTestBase): def tearDown(self): self.coll.delete_many({}) def test_no_results_ordered_success(self): requests: list = [ InsertOne({"a": 1}), UpdateOne({"a": 3}, {"$set": {"b": 1}}, upsert=True), InsertOne({"a": 2}), DeleteOne({"a": 1}), ] result = self.coll_w0.bulk_write(requests) self.assertFalse(result.acknowledged) wait_until(lambda: self.coll.count_documents({}) == 2, "insert 2 documents") wait_until(lambda: self.coll.find_one({"_id": 1}) is None, 'removed {"_id": 1}') def test_no_results_ordered_failure(self): requests: list = [ InsertOne({"_id": 1}), UpdateOne({"_id": 3}, {"$set": {"b": 1}}, upsert=True), InsertOne({"_id": 2}), # Fails with duplicate key error. InsertOne({"_id": 1}), # Should not be executed since the batch is ordered. DeleteOne({"_id": 1}), ] result = self.coll_w0.bulk_write(requests) self.assertFalse(result.acknowledged) wait_until(lambda: self.coll.count_documents({}) == 3, "insert 3 documents") self.assertEqual({"_id": 1}, self.coll.find_one({"_id": 1})) def test_no_results_unordered_success(self): requests: list = [ InsertOne({"a": 1}), UpdateOne({"a": 3}, {"$set": {"b": 1}}, upsert=True), InsertOne({"a": 2}), DeleteOne({"a": 1}), ] result = self.coll_w0.bulk_write(requests, ordered=False) self.assertFalse(result.acknowledged) wait_until(lambda: self.coll.count_documents({}) == 2, "insert 2 documents") wait_until(lambda: self.coll.find_one({"_id": 1}) is None, 'removed {"_id": 1}') def test_no_results_unordered_failure(self): requests: list = [ InsertOne({"_id": 1}), UpdateOne({"_id": 3}, {"$set": {"b": 1}}, upsert=True), InsertOne({"_id": 2}), # Fails with duplicate key error. InsertOne({"_id": 1}), # Should be executed since the batch is unordered. DeleteOne({"_id": 1}), ] result = self.coll_w0.bulk_write(requests, ordered=False) self.assertFalse(result.acknowledged) wait_until(lambda: self.coll.count_documents({}) == 2, "insert 2 documents") wait_until(lambda: self.coll.find_one({"_id": 1}) is None, 'removed {"_id": 1}') class TestBulkAuthorization(BulkAuthorizationTestBase): def test_readonly(self): # We test that an authorization failure aborts the batch and is raised # as OperationFailure. cli = rs_or_single_client_noauth( username="readonly", password="pw", authSource="pymongo_test" ) coll = cli.pymongo_test.test coll.find_one() self.assertRaises(OperationFailure, coll.bulk_write, [InsertOne({"x": 1})]) def test_no_remove(self): # We test that an authorization failure aborts the batch and is raised # as OperationFailure. cli = rs_or_single_client_noauth( username="noremove", password="pw", authSource="pymongo_test" ) coll = cli.pymongo_test.test coll.find_one() requests = [ InsertOne({"x": 1}), ReplaceOne({"x": 2}, {"x": 2}, upsert=True), DeleteMany({}), # Prohibited. InsertOne({"x": 3}), # Never attempted. ] self.assertRaises(OperationFailure, coll.bulk_write, requests) self.assertEqual({1, 2}, set(self.coll.distinct("x"))) class TestBulkWriteConcern(BulkTestBase): w: Optional[int] secondary: MongoClient @classmethod def setUpClass(cls): super().setUpClass() cls.w = client_context.w cls.secondary = None if cls.w is not None and cls.w > 1: for member in client_context.hello["hosts"]: if member != client_context.hello["primary"]: cls.secondary = single_client(*partition_node(member)) break @classmethod def tearDownClass(cls): if cls.secondary: cls.secondary.close() def cause_wtimeout(self, requests, ordered): if not client_context.test_commands_enabled: self.skipTest("Test commands must be enabled.") # Use the rsSyncApplyStop failpoint to pause replication on a # secondary which will cause a wtimeout error. self.secondary.admin.command("configureFailPoint", "rsSyncApplyStop", mode="alwaysOn") try: coll = self.coll.with_options(write_concern=WriteConcern(w=self.w, wtimeout=1)) return coll.bulk_write(requests, ordered=ordered) finally: self.secondary.admin.command("configureFailPoint", "rsSyncApplyStop", mode="off") @client_context.require_replica_set @client_context.require_secondaries_count(1) def test_write_concern_failure_ordered(self): # Ensure we don't raise on wnote. coll_ww = self.coll.with_options(write_concern=WriteConcern(w=self.w)) result = coll_ww.bulk_write([DeleteOne({"something": "that does no exist"})]) self.assertTrue(result.acknowledged) requests: list[Any] = [InsertOne({"a": 1}), InsertOne({"a": 2})] # Replication wtimeout is a 'soft' error. # It shouldn't stop batch processing. try: self.cause_wtimeout(requests, ordered=True) except BulkWriteError as exc: details = exc.details self.assertEqual(exc.code, 65) else: self.fail("Error not raised") self.assertEqualResponse( { "nMatched": 0, "nModified": 0, "nUpserted": 0, "nInserted": 2, "nRemoved": 0, "upserted": [], "writeErrors": [], }, details, ) # When talking to legacy servers there will be a # write concern error for each operation. self.assertTrue(len(details["writeConcernErrors"]) > 0) failed = details["writeConcernErrors"][0] self.assertEqual(64, failed["code"]) self.assertTrue(isinstance(failed["errmsg"], str)) self.coll.delete_many({}) self.coll.create_index("a", unique=True) self.addCleanup(self.coll.drop_index, [("a", 1)]) # Fail due to write concern support as well # as duplicate key error on ordered batch. requests = [ InsertOne({"a": 1}), ReplaceOne({"a": 3}, {"b": 1}, upsert=True), InsertOne({"a": 1}), InsertOne({"a": 2}), ] try: self.cause_wtimeout(requests, ordered=True) except BulkWriteError as exc: details = exc.details self.assertEqual(exc.code, 65) else: self.fail("Error not raised") self.assertEqualResponse( { "nMatched": 0, "nModified": 0, "nUpserted": 1, "nInserted": 1, "nRemoved": 0, "upserted": [{"index": 1, "_id": "..."}], "writeErrors": [ {"index": 2, "code": 11000, "errmsg": "...", "op": {"_id": "...", "a": 1}} ], }, details, ) self.assertTrue(len(details["writeConcernErrors"]) > 1) failed = details["writeErrors"][0] self.assertTrue("duplicate" in failed["errmsg"]) @client_context.require_replica_set @client_context.require_secondaries_count(1) def test_write_concern_failure_unordered(self): # Ensure we don't raise on wnote. coll_ww = self.coll.with_options(write_concern=WriteConcern(w=self.w)) result = coll_ww.bulk_write([DeleteOne({"something": "that does no exist"})], ordered=False) self.assertTrue(result.acknowledged) requests = [ InsertOne({"a": 1}), UpdateOne({"a": 3}, {"$set": {"a": 3, "b": 1}}, upsert=True), InsertOne({"a": 2}), ] # Replication wtimeout is a 'soft' error. # It shouldn't stop batch processing. try: self.cause_wtimeout(requests, ordered=False) except BulkWriteError as exc: details = exc.details self.assertEqual(exc.code, 65) else: self.fail("Error not raised") self.assertEqual(2, details["nInserted"]) self.assertEqual(1, details["nUpserted"]) self.assertEqual(0, len(details["writeErrors"])) # When talking to legacy servers there will be a # write concern error for each operation. self.assertTrue(len(details["writeConcernErrors"]) > 1) self.coll.delete_many({}) self.coll.create_index("a", unique=True) self.addCleanup(self.coll.drop_index, [("a", 1)]) # Fail due to write concern support as well # as duplicate key error on unordered batch. requests: list = [ InsertOne({"a": 1}), UpdateOne({"a": 3}, {"$set": {"a": 3, "b": 1}}, upsert=True), InsertOne({"a": 1}), InsertOne({"a": 2}), ] try: self.cause_wtimeout(requests, ordered=False) except BulkWriteError as exc: details = exc.details self.assertEqual(exc.code, 65) else: self.fail("Error not raised") self.assertEqual(2, details["nInserted"]) self.assertEqual(1, details["nUpserted"]) self.assertEqual(1, len(details["writeErrors"])) # When talking to legacy servers there will be a # write concern error for each operation. self.assertTrue(len(details["writeConcernErrors"]) > 1) failed = details["writeErrors"][0] self.assertEqual(2, failed["index"]) self.assertEqual(11000, failed["code"]) self.assertTrue(isinstance(failed["errmsg"], str)) self.assertEqual(1, failed["op"]["a"]) failed = details["writeConcernErrors"][0] self.assertEqual(64, failed["code"]) self.assertTrue(isinstance(failed["errmsg"], str)) upserts = details["upserted"] self.assertEqual(1, len(upserts)) self.assertEqual(1, upserts[0]["index"]) self.assertTrue(upserts[0].get("_id")) if __name__ == "__main__": unittest.main() mongodb-mongo-python-driver-509e9b7/test/test_change_stream.py000066400000000000000000001415571462766011000246420ustar00rootroot00000000000000# Copyright 2017 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. """Test the change_stream module.""" from __future__ import annotations import os import random import string import sys import threading import time import uuid from itertools import product from typing import no_type_check sys.path[0:0] = [""] from test import IntegrationTest, Version, client_context, unittest from test.unified_format import generate_test_classes from test.utils import ( AllowListEventListener, EventListener, rs_or_single_client, wait_until, ) from bson import SON, ObjectId, Timestamp, encode from bson.binary import ALL_UUID_REPRESENTATIONS, PYTHON_LEGACY, STANDARD, Binary from bson.raw_bson import DEFAULT_RAW_BSON_OPTIONS, RawBSONDocument from pymongo import MongoClient from pymongo.command_cursor import CommandCursor from pymongo.errors import ( InvalidOperation, OperationFailure, ServerSelectionTimeoutError, ) from pymongo.message import _CursorAddress from pymongo.read_concern import ReadConcern from pymongo.write_concern import WriteConcern class TestChangeStreamBase(IntegrationTest): RUN_ON_LOAD_BALANCER = True def change_stream_with_client(self, client, *args, **kwargs): """Create a change stream using the given client and return it.""" raise NotImplementedError def change_stream(self, *args, **kwargs): """Create a change stream using the default client and return it.""" return self.change_stream_with_client(self.client, *args, **kwargs) def client_with_listener(self, *commands): """Return a client with a AllowListEventListener.""" listener = AllowListEventListener(*commands) client = rs_or_single_client(event_listeners=[listener]) self.addCleanup(client.close) return client, listener def watched_collection(self, *args, **kwargs): """Return a collection that is watched by self.change_stream().""" # Construct a unique collection for each test. collname = ".".join(self.id().rsplit(".", 2)[1:]) return self.db.get_collection(collname, *args, **kwargs) def generate_invalidate_event(self, change_stream): """Cause a change stream invalidate event.""" raise NotImplementedError def generate_unique_collnames(self, numcolls): """Generate numcolls collection names unique to a test.""" collnames = [] for idx in range(1, numcolls + 1): collnames.append(self.id() + "_" + str(idx)) return collnames def get_resume_token(self, invalidate=False): """Get a resume token to use for starting a change stream.""" # Ensure targeted collection exists before starting. coll = self.watched_collection(write_concern=WriteConcern("majority")) coll.insert_one({}) if invalidate: with self.change_stream([{"$match": {"operationType": "invalidate"}}]) as cs: if isinstance(cs._target, MongoClient): self.skipTest("cluster-level change streams cannot be invalidated") self.generate_invalidate_event(cs) return cs.next()["_id"] else: with self.change_stream() as cs: coll.insert_one({"data": 1}) return cs.next()["_id"] def get_start_at_operation_time(self): """Get an operationTime. Advances the operation clock beyond the most recently returned timestamp. """ optime = self.client.admin.command("ping")["operationTime"] return Timestamp(optime.time, optime.inc + 1) def insert_one_and_check(self, change_stream, doc): """Insert a document and check that it shows up in the change stream.""" raise NotImplementedError def kill_change_stream_cursor(self, change_stream): """Cause a cursor not found error on the next getMore.""" cursor = change_stream._cursor address = _CursorAddress(cursor.address, cursor._CommandCursor__ns) client = self.watched_collection().database.client client._close_cursor_now(cursor.cursor_id, address) class APITestsMixin: @no_type_check def test_watch(self): with self.change_stream( [{"$project": {"foo": 0}}], full_document="updateLookup", max_await_time_ms=1000, batch_size=100, ) as change_stream: self.assertEqual([{"$project": {"foo": 0}}], change_stream._pipeline) self.assertEqual("updateLookup", change_stream._full_document) self.assertEqual(1000, change_stream._max_await_time_ms) self.assertEqual(100, change_stream._batch_size) self.assertIsInstance(change_stream._cursor, CommandCursor) self.assertEqual(1000, change_stream._cursor._CommandCursor__max_await_time_ms) self.watched_collection(write_concern=WriteConcern("majority")).insert_one({}) _ = change_stream.next() resume_token = change_stream.resume_token with self.assertRaises(TypeError): self.change_stream(pipeline={}) with self.assertRaises(TypeError): self.change_stream(full_document={}) # No Error. with self.change_stream(resume_after=resume_token): pass @no_type_check def test_try_next(self): # ChangeStreams only read majority committed data so use w:majority. coll = self.watched_collection().with_options(write_concern=WriteConcern("majority")) coll.drop() coll.insert_one({}) self.addCleanup(coll.drop) with self.change_stream(max_await_time_ms=250) as stream: self.assertIsNone(stream.try_next()) # No changes initially. coll.insert_one({}) # Generate a change. # On sharded clusters, even majority-committed changes only show # up once an event that sorts after it shows up on the other # shard. So, we wait on try_next to eventually return changes. wait_until(lambda: stream.try_next() is not None, "get change from try_next") @no_type_check def test_try_next_runs_one_getmore(self): listener = EventListener() client = rs_or_single_client(event_listeners=[listener]) # Connect to the cluster. client.admin.command("ping") listener.reset() # ChangeStreams only read majority committed data so use w:majority. coll = self.watched_collection().with_options(write_concern=WriteConcern("majority")) coll.drop() # Create the watched collection before starting the change stream to # skip any "create" events. coll.insert_one({"_id": 1}) self.addCleanup(coll.drop) with self.change_stream_with_client(client, max_await_time_ms=250) as stream: self.assertEqual(listener.started_command_names(), ["aggregate"]) listener.reset() # Confirm that only a single getMore is run even when no documents # are returned. self.assertIsNone(stream.try_next()) self.assertEqual(listener.started_command_names(), ["getMore"]) listener.reset() self.assertIsNone(stream.try_next()) self.assertEqual(listener.started_command_names(), ["getMore"]) listener.reset() # Get at least one change before resuming. coll.insert_one({"_id": 2}) wait_until(lambda: stream.try_next() is not None, "get change from try_next") listener.reset() # Cause the next request to initiate the resume process. self.kill_change_stream_cursor(stream) listener.reset() # The sequence should be: # - getMore, fail # - resume with aggregate command # - no results, return immediately without another getMore self.assertIsNone(stream.try_next()) self.assertEqual(listener.started_command_names(), ["getMore", "aggregate"]) listener.reset() # Stream still works after a resume. coll.insert_one({"_id": 3}) wait_until(lambda: stream.try_next() is not None, "get change from try_next") self.assertEqual(set(listener.started_command_names()), {"getMore"}) self.assertIsNone(stream.try_next()) @no_type_check def test_batch_size_is_honored(self): listener = EventListener() client = rs_or_single_client(event_listeners=[listener]) # Connect to the cluster. client.admin.command("ping") listener.reset() # ChangeStreams only read majority committed data so use w:majority. coll = self.watched_collection().with_options(write_concern=WriteConcern("majority")) coll.drop() # Create the watched collection before starting the change stream to # skip any "create" events. coll.insert_one({"_id": 1}) self.addCleanup(coll.drop) # Expected batchSize. expected = {"batchSize": 23} with self.change_stream_with_client(client, max_await_time_ms=250, batch_size=23) as stream: # Confirm that batchSize is honored for initial batch. cmd = listener.started_events[0].command self.assertEqual(cmd["cursor"], expected) listener.reset() # Confirm that batchSize is honored by getMores. self.assertIsNone(stream.try_next()) cmd = listener.started_events[0].command key = next(iter(expected)) self.assertEqual(expected[key], cmd[key]) # $changeStream.startAtOperationTime was added in 4.0.0. @no_type_check @client_context.require_version_min(4, 0, 0) def test_start_at_operation_time(self): optime = self.get_start_at_operation_time() coll = self.watched_collection(write_concern=WriteConcern("majority")) ndocs = 3 coll.insert_many([{"data": i} for i in range(ndocs)]) with self.change_stream(start_at_operation_time=optime) as cs: for _i in range(ndocs): cs.next() @no_type_check def _test_full_pipeline(self, expected_cs_stage): client, listener = self.client_with_listener("aggregate") with self.change_stream_with_client(client, [{"$project": {"foo": 0}}]) as _: pass self.assertEqual(1, len(listener.started_events)) command = listener.started_events[0] self.assertEqual("aggregate", command.command_name) self.assertEqual( [{"$changeStream": expected_cs_stage}, {"$project": {"foo": 0}}], command.command["pipeline"], ) @no_type_check def test_full_pipeline(self): """$changeStream must be the first stage in a change stream pipeline sent to the server. """ self._test_full_pipeline({}) @no_type_check def test_iteration(self): with self.change_stream(batch_size=2) as change_stream: num_inserted = 10 self.watched_collection().insert_many([{} for _ in range(num_inserted)]) inserts_received = 0 for change in change_stream: self.assertEqual(change["operationType"], "insert") inserts_received += 1 if inserts_received == num_inserted: break self._test_invalidate_stops_iteration(change_stream) @no_type_check def _test_next_blocks(self, change_stream): inserted_doc = {"_id": ObjectId()} changes = [] t = threading.Thread(target=lambda: changes.append(change_stream.next())) t.start() # Sleep for a bit to prove that the call to next() blocks. time.sleep(1) self.assertTrue(t.is_alive()) self.assertFalse(changes) self.watched_collection().insert_one(inserted_doc) # Join with large timeout to give the server time to return the change, # in particular for shard clusters. t.join(30) self.assertFalse(t.is_alive()) self.assertEqual(1, len(changes)) self.assertEqual(changes[0]["operationType"], "insert") self.assertEqual(changes[0]["fullDocument"], inserted_doc) @no_type_check def test_next_blocks(self): """Test that next blocks until a change is readable""" # Use a short await time to speed up the test. with self.change_stream(max_await_time_ms=250) as change_stream: self._test_next_blocks(change_stream) @no_type_check def test_aggregate_cursor_blocks(self): """Test that an aggregate cursor blocks until a change is readable.""" with self.watched_collection().aggregate( [{"$changeStream": {}}], maxAwaitTimeMS=250 ) as change_stream: self._test_next_blocks(change_stream) @no_type_check def test_concurrent_close(self): """Ensure a ChangeStream can be closed from another thread.""" # Use a short await time to speed up the test. with self.change_stream(max_await_time_ms=250) as change_stream: def iterate_cursor(): try: for _ in change_stream: pass except OperationFailure as e: if e.code != 237: # CursorKilled error code raise t = threading.Thread(target=iterate_cursor) t.start() self.watched_collection().insert_one({}) time.sleep(1) change_stream.close() t.join(3) self.assertFalse(t.is_alive()) @no_type_check def test_unknown_full_document(self): """Must rely on the server to raise an error on unknown fullDocument.""" try: with self.change_stream(full_document="notValidatedByPyMongo"): pass except OperationFailure: pass @no_type_check def test_change_operations(self): """Test each operation type.""" expected_ns = { "db": self.watched_collection().database.name, "coll": self.watched_collection().name, } with self.change_stream() as change_stream: # Insert. inserted_doc = {"_id": ObjectId(), "foo": "bar"} self.watched_collection().insert_one(inserted_doc) change = change_stream.next() self.assertTrue(change["_id"]) self.assertEqual(change["operationType"], "insert") self.assertEqual(change["ns"], expected_ns) self.assertEqual(change["fullDocument"], inserted_doc) # Update. update_spec = {"$set": {"new": 1}, "$unset": {"foo": 1}} self.watched_collection().update_one(inserted_doc, update_spec) change = change_stream.next() self.assertTrue(change["_id"]) self.assertEqual(change["operationType"], "update") self.assertEqual(change["ns"], expected_ns) self.assertNotIn("fullDocument", change) expected_update_description = {"updatedFields": {"new": 1}, "removedFields": ["foo"]} if client_context.version.at_least(4, 5, 0): expected_update_description["truncatedArrays"] = [] self.assertEqual(expected_update_description, change["updateDescription"]) # Replace. self.watched_collection().replace_one({"new": 1}, {"foo": "bar"}) change = change_stream.next() self.assertTrue(change["_id"]) self.assertEqual(change["operationType"], "replace") self.assertEqual(change["ns"], expected_ns) self.assertEqual(change["fullDocument"], inserted_doc) # Delete. self.watched_collection().delete_one({"foo": "bar"}) change = change_stream.next() self.assertTrue(change["_id"]) self.assertEqual(change["operationType"], "delete") self.assertEqual(change["ns"], expected_ns) self.assertNotIn("fullDocument", change) # Invalidate. self._test_get_invalidate_event(change_stream) @no_type_check @client_context.require_version_min(4, 1, 1) def test_start_after(self): resume_token = self.get_resume_token(invalidate=True) # resume_after cannot resume after invalidate. with self.assertRaises(OperationFailure): self.change_stream(resume_after=resume_token) # start_after can resume after invalidate. with self.change_stream(start_after=resume_token) as change_stream: self.watched_collection().insert_one({"_id": 2}) change = change_stream.next() self.assertEqual(change["operationType"], "insert") self.assertEqual(change["fullDocument"], {"_id": 2}) @no_type_check @client_context.require_version_min(4, 1, 1) def test_start_after_resume_process_with_changes(self): resume_token = self.get_resume_token(invalidate=True) with self.change_stream(start_after=resume_token, max_await_time_ms=250) as change_stream: self.watched_collection().insert_one({"_id": 2}) change = change_stream.next() self.assertEqual(change["operationType"], "insert") self.assertEqual(change["fullDocument"], {"_id": 2}) self.assertIsNone(change_stream.try_next()) self.kill_change_stream_cursor(change_stream) self.watched_collection().insert_one({"_id": 3}) change = change_stream.next() self.assertEqual(change["operationType"], "insert") self.assertEqual(change["fullDocument"], {"_id": 3}) @no_type_check @client_context.require_version_min(4, 2) def test_start_after_resume_process_without_changes(self): resume_token = self.get_resume_token(invalidate=True) with self.change_stream(start_after=resume_token, max_await_time_ms=250) as change_stream: self.assertIsNone(change_stream.try_next()) self.kill_change_stream_cursor(change_stream) self.watched_collection().insert_one({"_id": 2}) change = change_stream.next() self.assertEqual(change["operationType"], "insert") self.assertEqual(change["fullDocument"], {"_id": 2}) class ProseSpecTestsMixin: @no_type_check def _client_with_listener(self, *commands): listener = AllowListEventListener(*commands) client = rs_or_single_client(event_listeners=[listener]) self.addCleanup(client.close) return client, listener @no_type_check def _populate_and_exhaust_change_stream(self, change_stream, batch_size=3): self.watched_collection().insert_many([{"data": k} for k in range(batch_size)]) for _ in range(batch_size): change = next(change_stream) return change def _get_expected_resume_token_legacy(self, stream, listener, previous_change=None): """Predicts what the resume token should currently be for server versions that don't support postBatchResumeToken. Assumes the stream has never returned any changes if previous_change is None. """ if previous_change is None: agg_cmd = listener.started_events[0] stage = agg_cmd.command["pipeline"][0]["$changeStream"] return stage.get("resumeAfter") or stage.get("startAfter") return previous_change["_id"] def _get_expected_resume_token(self, stream, listener, previous_change=None): """Predicts what the resume token should currently be for server versions that support postBatchResumeToken. Assumes the stream has never returned any changes if previous_change is None. Assumes listener is a AllowListEventListener that listens for aggregate and getMore commands. """ if previous_change is None or stream._cursor._has_next(): token = self._get_expected_resume_token_legacy(stream, listener, previous_change) if token is not None: return token response = listener.succeeded_events[-1].reply return response["cursor"]["postBatchResumeToken"] @no_type_check def _test_raises_error_on_missing_id(self, expected_exception): """ChangeStream will raise an exception if the server response is missing the resume token. """ with self.change_stream([{"$project": {"_id": 0}}]) as change_stream: self.watched_collection().insert_one({}) with self.assertRaises(expected_exception): next(change_stream) # The cursor should now be closed. with self.assertRaises(StopIteration): next(change_stream) @no_type_check def _test_update_resume_token(self, expected_rt_getter): """ChangeStream must continuously track the last seen resumeToken.""" client, listener = self._client_with_listener("aggregate", "getMore") coll = self.watched_collection(write_concern=WriteConcern("majority")) with self.change_stream_with_client(client) as change_stream: self.assertEqual( change_stream.resume_token, expected_rt_getter(change_stream, listener) ) for _ in range(3): coll.insert_one({}) change = next(change_stream) self.assertEqual( change_stream.resume_token, expected_rt_getter(change_stream, listener, change) ) # Prose test no. 1 @client_context.require_version_min(4, 0, 7) def test_update_resume_token(self): self._test_update_resume_token(self._get_expected_resume_token) # Prose test no. 1 @client_context.require_version_max(4, 0, 7) def test_update_resume_token_legacy(self): self._test_update_resume_token(self._get_expected_resume_token_legacy) # Prose test no. 2 @client_context.require_version_min(4, 1, 8) def test_raises_error_on_missing_id_418plus(self): # Server returns an error on 4.1.8+ self._test_raises_error_on_missing_id(OperationFailure) # Prose test no. 2 @client_context.require_version_max(4, 1, 8) def test_raises_error_on_missing_id_418minus(self): # PyMongo raises an error self._test_raises_error_on_missing_id(InvalidOperation) # Prose test no. 3 @no_type_check def test_resume_on_error(self): with self.change_stream() as change_stream: self.insert_one_and_check(change_stream, {"_id": 1}) # Cause a cursor not found error on the next getMore. self.kill_change_stream_cursor(change_stream) self.insert_one_and_check(change_stream, {"_id": 2}) # Prose test no. 4 @no_type_check @client_context.require_failCommand_fail_point def test_no_resume_attempt_if_aggregate_command_fails(self): # Set non-retryable error on aggregate command. fail_point = {"mode": {"times": 1}, "data": {"errorCode": 2, "failCommands": ["aggregate"]}} client, listener = self._client_with_listener("aggregate", "getMore") with self.fail_point(fail_point): try: _ = self.change_stream_with_client(client) except OperationFailure: pass # Driver should have attempted aggregate command only once. self.assertEqual(len(listener.started_events), 1) self.assertEqual(listener.started_events[0].command_name, "aggregate") # Prose test no. 5 - REMOVED # Prose test no. 6 - SKIPPED # Reason: readPreference is not configurable using the watch() helpers # so we can skip this test. Also, PyMongo performs server selection for # each operation which ensure compliance with this prose test. # Prose test no. 7 @no_type_check def test_initial_empty_batch(self): with self.change_stream() as change_stream: # The first batch should be empty. self.assertFalse(change_stream._cursor._has_next()) cursor_id = change_stream._cursor.cursor_id self.assertTrue(cursor_id) self.insert_one_and_check(change_stream, {}) # Make sure we're still using the same cursor. self.assertEqual(cursor_id, change_stream._cursor.cursor_id) # Prose test no. 8 @no_type_check def test_kill_cursors(self): def raise_error(): raise ServerSelectionTimeoutError("mock error") with self.change_stream() as change_stream: self.insert_one_and_check(change_stream, {"_id": 1}) # Cause a cursor not found error on the next getMore. cursor = change_stream._cursor self.kill_change_stream_cursor(change_stream) cursor.close = raise_error self.insert_one_and_check(change_stream, {"_id": 2}) # Prose test no. 9 @no_type_check @client_context.require_version_min(4, 0, 0) @client_context.require_version_max(4, 0, 7) def test_start_at_operation_time_caching(self): # Case 1: change stream not started with startAtOperationTime client, listener = self.client_with_listener("aggregate") with self.change_stream_with_client(client) as cs: self.kill_change_stream_cursor(cs) cs.try_next() cmd = listener.started_events[-1].command self.assertIsNotNone(cmd["pipeline"][0]["$changeStream"].get("startAtOperationTime")) # Case 2: change stream started with startAtOperationTime listener.reset() optime = self.get_start_at_operation_time() with self.change_stream_with_client(client, start_at_operation_time=optime) as cs: self.kill_change_stream_cursor(cs) cs.try_next() cmd = listener.started_events[-1].command self.assertEqual( cmd["pipeline"][0]["$changeStream"].get("startAtOperationTime"), optime, str([k.command for k in listener.started_events]), ) # Prose test no. 10 - SKIPPED # This test is identical to prose test no. 3. # Prose test no. 11 @no_type_check @client_context.require_version_min(4, 0, 7) def test_resumetoken_empty_batch(self): client, listener = self._client_with_listener("getMore") with self.change_stream_with_client(client) as change_stream: self.assertIsNone(change_stream.try_next()) resume_token = change_stream.resume_token response = listener.succeeded_events[0].reply self.assertEqual(resume_token, response["cursor"]["postBatchResumeToken"]) # Prose test no. 11 @no_type_check @client_context.require_version_min(4, 0, 7) def test_resumetoken_exhausted_batch(self): client, listener = self._client_with_listener("getMore") with self.change_stream_with_client(client) as change_stream: self._populate_and_exhaust_change_stream(change_stream) resume_token = change_stream.resume_token response = listener.succeeded_events[-1].reply self.assertEqual(resume_token, response["cursor"]["postBatchResumeToken"]) # Prose test no. 12 @no_type_check @client_context.require_version_max(4, 0, 7) def test_resumetoken_empty_batch_legacy(self): resume_point = self.get_resume_token() # Empty resume token when neither resumeAfter or startAfter specified. with self.change_stream() as change_stream: change_stream.try_next() self.assertIsNone(change_stream.resume_token) # Resume token value is same as resumeAfter. with self.change_stream(resume_after=resume_point) as change_stream: change_stream.try_next() resume_token = change_stream.resume_token self.assertEqual(resume_token, resume_point) # Prose test no. 12 @no_type_check @client_context.require_version_max(4, 0, 7) def test_resumetoken_exhausted_batch_legacy(self): # Resume token is _id of last change. with self.change_stream() as change_stream: change = self._populate_and_exhaust_change_stream(change_stream) self.assertEqual(change_stream.resume_token, change["_id"]) resume_point = change["_id"] # Resume token is _id of last change even if resumeAfter is specified. with self.change_stream(resume_after=resume_point) as change_stream: change = self._populate_and_exhaust_change_stream(change_stream) self.assertEqual(change_stream.resume_token, change["_id"]) # Prose test no. 13 @no_type_check def test_resumetoken_partially_iterated_batch(self): # When batch has been iterated up to but not including the last element. # Resume token should be _id of previous change document. with self.change_stream() as change_stream: self.watched_collection(write_concern=WriteConcern("majority")).insert_many( [{"data": k} for k in range(3)] ) for _ in range(2): change = next(change_stream) resume_token = change_stream.resume_token self.assertEqual(resume_token, change["_id"]) @no_type_check def _test_resumetoken_uniterated_nonempty_batch(self, resume_option): # When the batch is not empty and hasn't been iterated at all. # Resume token should be same as the resume option used. resume_point = self.get_resume_token() # Insert some documents so that firstBatch isn't empty. self.watched_collection(write_concern=WriteConcern("majority")).insert_many( [{"a": 1}, {"b": 2}, {"c": 3}] ) # Resume token should be same as the resume option. with self.change_stream(**{resume_option: resume_point}) as change_stream: self.assertTrue(change_stream._cursor._has_next()) resume_token = change_stream.resume_token self.assertEqual(resume_token, resume_point) # Prose test no. 14 @no_type_check @client_context.require_no_mongos def test_resumetoken_uniterated_nonempty_batch_resumeafter(self): self._test_resumetoken_uniterated_nonempty_batch("resume_after") # Prose test no. 14 @no_type_check @client_context.require_no_mongos @client_context.require_version_min(4, 1, 1) def test_resumetoken_uniterated_nonempty_batch_startafter(self): self._test_resumetoken_uniterated_nonempty_batch("start_after") # Prose test no. 17 @no_type_check @client_context.require_version_min(4, 1, 1) def test_startafter_resume_uses_startafter_after_empty_getMore(self): # Resume should use startAfter after no changes have been returned. resume_point = self.get_resume_token() client, listener = self._client_with_listener("aggregate") with self.change_stream_with_client(client, start_after=resume_point) as change_stream: self.assertFalse(change_stream._cursor._has_next()) # No changes change_stream.try_next() # No changes self.kill_change_stream_cursor(change_stream) change_stream.try_next() # Resume attempt response = listener.started_events[-1] self.assertIsNone(response.command["pipeline"][0]["$changeStream"].get("resumeAfter")) self.assertIsNotNone(response.command["pipeline"][0]["$changeStream"].get("startAfter")) # Prose test no. 18 @no_type_check @client_context.require_version_min(4, 1, 1) def test_startafter_resume_uses_resumeafter_after_nonempty_getMore(self): # Resume should use resumeAfter after some changes have been returned. resume_point = self.get_resume_token() client, listener = self._client_with_listener("aggregate") with self.change_stream_with_client(client, start_after=resume_point) as change_stream: self.assertFalse(change_stream._cursor._has_next()) # No changes self.watched_collection().insert_one({}) next(change_stream) # Changes self.kill_change_stream_cursor(change_stream) change_stream.try_next() # Resume attempt response = listener.started_events[-1] self.assertIsNotNone(response.command["pipeline"][0]["$changeStream"].get("resumeAfter")) self.assertIsNone(response.command["pipeline"][0]["$changeStream"].get("startAfter")) # Prose test no. 19 @no_type_check def test_split_large_change(self): server_version = client_context.version if not server_version.at_least(6, 0, 9): self.skipTest("$changeStreamSplitLargeEvent requires MongoDB 6.0.9+") if server_version.at_least(6, 1, 0) and server_version < Version(7, 0, 0): self.skipTest("$changeStreamSplitLargeEvent is not available in 6.x rapid releases") self.db.drop_collection("test_split_large_change") coll = self.db.create_collection( "test_split_large_change", changeStreamPreAndPostImages={"enabled": True} ) coll.insert_one({"_id": 1, "value": "q" * 10 * 1024 * 1024}) with coll.watch( [{"$changeStreamSplitLargeEvent": {}}], full_document_before_change="required" ) as change_stream: coll.update_one({"_id": 1}, {"$set": {"value": "z" * 10 * 1024 * 1024}}) doc_1 = change_stream.next() self.assertIn("splitEvent", doc_1) self.assertEqual(doc_1["splitEvent"], {"fragment": 1, "of": 2}) doc_2 = change_stream.next() self.assertIn("splitEvent", doc_2) self.assertEqual(doc_2["splitEvent"], {"fragment": 2, "of": 2}) class TestClusterChangeStream(TestChangeStreamBase, APITestsMixin): dbs: list @classmethod @client_context.require_version_min(4, 0, 0, -1) @client_context.require_change_streams def setUpClass(cls): super().setUpClass() cls.dbs = [cls.db, cls.client.pymongo_test_2] @classmethod def tearDownClass(cls): for db in cls.dbs: cls.client.drop_database(db) super().tearDownClass() def change_stream_with_client(self, client, *args, **kwargs): return client.watch(*args, **kwargs) def generate_invalidate_event(self, change_stream): self.skipTest("cluster-level change streams cannot be invalidated") def _test_get_invalidate_event(self, change_stream): # Cluster-level change streams don't get invalidated. pass def _test_invalidate_stops_iteration(self, change_stream): # Cluster-level change streams don't get invalidated. pass def _insert_and_check(self, change_stream, db, collname, doc): coll = db[collname] coll.insert_one(doc) change = next(change_stream) self.assertEqual(change["operationType"], "insert") self.assertEqual(change["ns"], {"db": db.name, "coll": collname}) self.assertEqual(change["fullDocument"], doc) def insert_one_and_check(self, change_stream, doc): db = random.choice(self.dbs) collname = self.id() self._insert_and_check(change_stream, db, collname, doc) def test_simple(self): collnames = self.generate_unique_collnames(3) with self.change_stream() as change_stream: for db, collname in product(self.dbs, collnames): self._insert_and_check(change_stream, db, collname, {"_id": collname}) def test_aggregate_cursor_blocks(self): """Test that an aggregate cursor blocks until a change is readable.""" with self.client.admin.aggregate( [{"$changeStream": {"allChangesForCluster": True}}], maxAwaitTimeMS=250 ) as change_stream: self._test_next_blocks(change_stream) def test_full_pipeline(self): """$changeStream must be the first stage in a change stream pipeline sent to the server. """ self._test_full_pipeline({"allChangesForCluster": True}) class TestDatabaseChangeStream(TestChangeStreamBase, APITestsMixin): @classmethod @client_context.require_version_min(4, 0, 0, -1) @client_context.require_change_streams def setUpClass(cls): super().setUpClass() def change_stream_with_client(self, client, *args, **kwargs): return client[self.db.name].watch(*args, **kwargs) def generate_invalidate_event(self, change_stream): # Dropping the database invalidates the change stream. change_stream._client.drop_database(self.db.name) def _test_get_invalidate_event(self, change_stream): # Cache collection names. dropped_colls = self.db.list_collection_names() # Drop the watched database to get an invalidate event. self.generate_invalidate_event(change_stream) change = change_stream.next() # 4.1+ returns "drop" events for each collection in dropped database # and a "dropDatabase" event for the database itself. if change["operationType"] == "drop": self.assertTrue(change["_id"]) for _ in range(len(dropped_colls)): ns = change["ns"] self.assertEqual(ns["db"], change_stream._target.name) self.assertIn(ns["coll"], dropped_colls) change = change_stream.next() self.assertEqual(change["operationType"], "dropDatabase") self.assertTrue(change["_id"]) self.assertEqual(change["ns"], {"db": change_stream._target.name}) # Get next change. change = change_stream.next() self.assertTrue(change["_id"]) self.assertEqual(change["operationType"], "invalidate") self.assertNotIn("ns", change) self.assertNotIn("fullDocument", change) # The ChangeStream should be dead. with self.assertRaises(StopIteration): change_stream.next() def _test_invalidate_stops_iteration(self, change_stream): # Drop the watched database to get an invalidate event. change_stream._client.drop_database(self.db.name) # Check drop and dropDatabase events. for change in change_stream: self.assertIn(change["operationType"], ("drop", "dropDatabase", "invalidate")) # Last change must be invalidate. self.assertEqual(change["operationType"], "invalidate") # Change stream must not allow further iteration. with self.assertRaises(StopIteration): change_stream.next() with self.assertRaises(StopIteration): next(change_stream) def _insert_and_check(self, change_stream, collname, doc): coll = self.db[collname] coll.insert_one(doc) change = next(change_stream) self.assertEqual(change["operationType"], "insert") self.assertEqual(change["ns"], {"db": self.db.name, "coll": collname}) self.assertEqual(change["fullDocument"], doc) def insert_one_and_check(self, change_stream, doc): self._insert_and_check(change_stream, self.id(), doc) def test_simple(self): collnames = self.generate_unique_collnames(3) with self.change_stream() as change_stream: for collname in collnames: self._insert_and_check( change_stream, collname, {"_id": Binary.from_uuid(uuid.uuid4())} ) def test_isolation(self): # Ensure inserts to other dbs don't show up in our ChangeStream. other_db = self.client.pymongo_test_temp self.assertNotEqual(other_db, self.db, msg="Isolation must be tested on separate DBs") collname = self.id() with self.change_stream() as change_stream: other_db[collname].insert_one({"_id": Binary.from_uuid(uuid.uuid4())}) self._insert_and_check(change_stream, collname, {"_id": Binary.from_uuid(uuid.uuid4())}) self.client.drop_database(other_db) class TestCollectionChangeStream(TestChangeStreamBase, APITestsMixin, ProseSpecTestsMixin): @classmethod @client_context.require_change_streams def setUpClass(cls): super().setUpClass() def setUp(self): # Use a new collection for each test. self.watched_collection().drop() self.watched_collection().insert_one({}) def change_stream_with_client(self, client, *args, **kwargs): return ( client[self.db.name] .get_collection(self.watched_collection().name) .watch(*args, **kwargs) ) def generate_invalidate_event(self, change_stream): # Dropping the collection invalidates the change stream. change_stream._target.drop() def _test_invalidate_stops_iteration(self, change_stream): self.generate_invalidate_event(change_stream) # Check drop and dropDatabase events. for change in change_stream: self.assertIn(change["operationType"], ("drop", "invalidate")) # Last change must be invalidate. self.assertEqual(change["operationType"], "invalidate") # Change stream must not allow further iteration. with self.assertRaises(StopIteration): change_stream.next() with self.assertRaises(StopIteration): next(change_stream) def _test_get_invalidate_event(self, change_stream): # Drop the watched database to get an invalidate event. change_stream._target.drop() change = change_stream.next() # 4.1+ returns a "drop" change document. if change["operationType"] == "drop": self.assertTrue(change["_id"]) self.assertEqual( change["ns"], {"db": change_stream._target.database.name, "coll": change_stream._target.name}, ) # Last change should be invalidate. change = change_stream.next() self.assertTrue(change["_id"]) self.assertEqual(change["operationType"], "invalidate") self.assertNotIn("ns", change) self.assertNotIn("fullDocument", change) # The ChangeStream should be dead. with self.assertRaises(StopIteration): change_stream.next() def insert_one_and_check(self, change_stream, doc): self.watched_collection().insert_one(doc) change = next(change_stream) self.assertEqual(change["operationType"], "insert") self.assertEqual( change["ns"], {"db": self.watched_collection().database.name, "coll": self.watched_collection().name}, ) self.assertEqual(change["fullDocument"], doc) def test_raw(self): """Test with RawBSONDocument.""" raw_coll = self.watched_collection(codec_options=DEFAULT_RAW_BSON_OPTIONS) with raw_coll.watch() as change_stream: raw_doc = RawBSONDocument(encode({"_id": 1})) self.watched_collection().insert_one(raw_doc) change = next(change_stream) self.assertIsInstance(change, RawBSONDocument) self.assertEqual(change["operationType"], "insert") self.assertEqual(change["ns"]["db"], self.watched_collection().database.name) self.assertEqual(change["ns"]["coll"], self.watched_collection().name) self.assertEqual(change["fullDocument"], raw_doc) def test_uuid_representations(self): """Test with uuid document _ids and different uuid_representation.""" for uuid_representation in ALL_UUID_REPRESENTATIONS: for id_subtype in (STANDARD, PYTHON_LEGACY): options = self.watched_collection().codec_options.with_options( uuid_representation=uuid_representation ) coll = self.watched_collection(codec_options=options) with coll.watch() as change_stream: coll.insert_one({"_id": Binary(uuid.uuid4().bytes, id_subtype)}) _ = change_stream.next() resume_token = change_stream.resume_token # Should not error. coll.watch(resume_after=resume_token) def test_document_id_order(self): """Test with document _ids that need their order preserved.""" random_keys = random.sample(string.ascii_letters, len(string.ascii_letters)) random_doc = {"_id": SON([(key, key) for key in random_keys])} for document_class in (dict, SON, RawBSONDocument): options = self.watched_collection().codec_options.with_options( document_class=document_class ) coll = self.watched_collection(codec_options=options) with coll.watch() as change_stream: coll.insert_one(random_doc) _ = change_stream.next() resume_token = change_stream.resume_token # The resume token is always a document. self.assertIsInstance(resume_token, document_class) # Should not error. coll.watch(resume_after=resume_token) coll.delete_many({}) def test_read_concern(self): """Test readConcern is not validated by the driver.""" # Read concern 'local' is not allowed for $changeStream. coll = self.watched_collection(read_concern=ReadConcern("local")) with self.assertRaises(OperationFailure): coll.watch() # Does not error. coll = self.watched_collection(read_concern=ReadConcern("majority")) with coll.watch(): pass class TestAllLegacyScenarios(IntegrationTest): RUN_ON_LOAD_BALANCER = True listener: AllowListEventListener @classmethod @client_context.require_connection def setUpClass(cls): super().setUpClass() cls.listener = AllowListEventListener("aggregate", "getMore") cls.client = rs_or_single_client(event_listeners=[cls.listener]) @classmethod def tearDownClass(cls): cls.client.close() super().tearDownClass() def setUp(self): super().setUp() self.listener.reset() def setUpCluster(self, scenario_dict): assets = [ (scenario_dict["database_name"], scenario_dict["collection_name"]), ( scenario_dict.get("database2_name", "db2"), scenario_dict.get("collection2_name", "coll2"), ), ] for db, coll in assets: self.client.drop_database(db) self.client[db].create_collection(coll) def setFailPoint(self, scenario_dict): fail_point = scenario_dict.get("failPoint") if fail_point is None: return elif not client_context.test_commands_enabled: self.skipTest("Test commands must be enabled") fail_cmd = SON([("configureFailPoint", "failCommand")]) fail_cmd.update(fail_point) client_context.client.admin.command(fail_cmd) self.addCleanup( client_context.client.admin.command, "configureFailPoint", fail_cmd["configureFailPoint"], mode="off", ) def assert_list_contents_are_subset(self, superlist, sublist): """Check that each element in sublist is a subset of the corresponding element in superlist. """ self.assertEqual(len(superlist), len(sublist)) for sup, sub in zip(superlist, sublist): if isinstance(sub, dict): self.assert_dict_is_subset(sup, sub) continue if isinstance(sub, (list, tuple)): self.assert_list_contents_are_subset(sup, sub) continue self.assertEqual(sup, sub) def assert_dict_is_subset(self, superdict, subdict): """Check that subdict is a subset of superdict.""" exempt_fields = ["documentKey", "_id", "getMore"] for key, value in subdict.items(): if key not in superdict: self.fail(f"Key {key} not found in {superdict}") if isinstance(value, dict): self.assert_dict_is_subset(superdict[key], value) continue if isinstance(value, (list, tuple)): self.assert_list_contents_are_subset(superdict[key], value) continue if key in exempt_fields: # Only check for presence of these exempt fields, but not value. self.assertIn(key, superdict) else: self.assertEqual(superdict[key], value) def check_event(self, event, expectation_dict): if event is None: self.fail() for key, value in expectation_dict.items(): if isinstance(value, dict): self.assert_dict_is_subset(getattr(event, key), value) else: self.assertEqual(getattr(event, key), value) def tearDown(self): self.listener.reset() _TEST_PATH = os.path.join(os.path.dirname(os.path.realpath(__file__)), "change_streams") globals().update( generate_test_classes( os.path.join(_TEST_PATH, "unified"), module=__name__, ) ) if __name__ == "__main__": unittest.main() mongodb-mongo-python-driver-509e9b7/test/test_client.py000066400000000000000000002714701462766011000233160ustar00rootroot00000000000000# Copyright 2013-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. """Test the mongo_client module.""" from __future__ import annotations import _thread as thread import contextlib import copy import datetime import gc import logging import os import re import signal import socket import struct import subprocess import sys import threading import time from typing import Iterable, Type, no_type_check from unittest import mock from unittest.mock import patch import pytest from pymongo.operations import _Op sys.path[0:0] = [""] from test import ( HAVE_IPADDRESS, IntegrationTest, MockClientTest, SkipTest, client_context, client_knobs, db_pwd, db_user, unittest, ) from test.pymongo_mocks import MockClient from test.utils import ( NTHREADS, CMAPListener, FunctionCallRecorder, assertRaisesExactly, connected, delay, get_pool, gevent_monkey_patched, is_greenthread_patched, lazy_client_trial, one, remove_all_users, rs_client, rs_or_single_client, rs_or_single_client_noauth, single_client, wait_until, ) import pymongo from bson import encode from bson.codec_options import ( CodecOptions, DatetimeConversion, TypeEncoder, TypeRegistry, ) from bson.son import SON from bson.tz_util import utc from pymongo import event_loggers, message, monitoring from pymongo.client_options import ClientOptions from pymongo.command_cursor import CommandCursor from pymongo.common import _UUID_REPRESENTATIONS, CONNECT_TIMEOUT from pymongo.compression_support import _have_snappy, _have_zstd from pymongo.cursor import Cursor, CursorType from pymongo.database import Database from pymongo.driver_info import DriverInfo from pymongo.errors import ( AutoReconnect, ConfigurationError, ConnectionFailure, InvalidName, InvalidOperation, InvalidURI, NetworkTimeout, OperationFailure, ServerSelectionTimeoutError, WriteConcernError, ) from pymongo.mongo_client import MongoClient from pymongo.monitoring import ServerHeartbeatListener, ServerHeartbeatStartedEvent from pymongo.pool import _METADATA, ENV_VAR_K8S, Connection, PoolOptions from pymongo.read_preferences import ReadPreference from pymongo.server_description import ServerDescription from pymongo.server_selectors import readable_server_selector, writable_server_selector from pymongo.server_type import SERVER_TYPE from pymongo.settings import TOPOLOGY_TYPE from pymongo.topology import _ErrorContext from pymongo.topology_description import TopologyDescription from pymongo.write_concern import WriteConcern class ClientUnitTest(unittest.TestCase): """MongoClient tests that don't require a server.""" client: MongoClient @classmethod def setUpClass(cls): cls.client = rs_or_single_client(connect=False, serverSelectionTimeoutMS=100) @classmethod def tearDownClass(cls): cls.client.close() @pytest.fixture(autouse=True) def inject_fixtures(self, caplog): self._caplog = caplog def test_keyword_arg_defaults(self): client = MongoClient( socketTimeoutMS=None, connectTimeoutMS=20000, waitQueueTimeoutMS=None, replicaSet=None, read_preference=ReadPreference.PRIMARY, ssl=False, tlsCertificateKeyFile=None, tlsAllowInvalidCertificates=True, tlsCAFile=None, connect=False, serverSelectionTimeoutMS=12000, ) options = client._MongoClient__options pool_opts = options.pool_options self.assertEqual(None, pool_opts.socket_timeout) # socket.Socket.settimeout takes a float in seconds self.assertEqual(20.0, pool_opts.connect_timeout) self.assertEqual(None, pool_opts.wait_queue_timeout) self.assertEqual(None, pool_opts._ssl_context) self.assertEqual(None, options.replica_set_name) self.assertEqual(ReadPreference.PRIMARY, client.read_preference) self.assertAlmostEqual(12, client.options.server_selection_timeout) def test_connect_timeout(self): client = MongoClient(connect=False, connectTimeoutMS=None, socketTimeoutMS=None) pool_opts = client._MongoClient__options.pool_options self.assertEqual(None, pool_opts.socket_timeout) self.assertEqual(None, pool_opts.connect_timeout) client = MongoClient(connect=False, connectTimeoutMS=0, socketTimeoutMS=0) pool_opts = client._MongoClient__options.pool_options self.assertEqual(None, pool_opts.socket_timeout) self.assertEqual(None, pool_opts.connect_timeout) client = MongoClient( "mongodb://localhost/?connectTimeoutMS=0&socketTimeoutMS=0", connect=False ) pool_opts = client._MongoClient__options.pool_options self.assertEqual(None, pool_opts.socket_timeout) self.assertEqual(None, pool_opts.connect_timeout) def test_types(self): self.assertRaises(TypeError, MongoClient, 1) self.assertRaises(TypeError, MongoClient, 1.14) self.assertRaises(TypeError, MongoClient, "localhost", "27017") self.assertRaises(TypeError, MongoClient, "localhost", 1.14) self.assertRaises(TypeError, MongoClient, "localhost", []) self.assertRaises(ConfigurationError, MongoClient, []) def test_max_pool_size_zero(self): MongoClient(maxPoolSize=0) def test_uri_detection(self): self.assertRaises(ConfigurationError, MongoClient, "/foo") self.assertRaises(ConfigurationError, MongoClient, "://") self.assertRaises(ConfigurationError, MongoClient, "foo/") def test_get_db(self): def make_db(base, name): return base[name] self.assertRaises(InvalidName, make_db, self.client, "") self.assertRaises(InvalidName, make_db, self.client, "te$t") self.assertRaises(InvalidName, make_db, self.client, "te.t") self.assertRaises(InvalidName, make_db, self.client, "te\\t") self.assertRaises(InvalidName, make_db, self.client, "te/t") self.assertRaises(InvalidName, make_db, self.client, "te st") self.assertTrue(isinstance(self.client.test, Database)) self.assertEqual(self.client.test, self.client["test"]) self.assertEqual(self.client.test, Database(self.client, "test")) def test_get_database(self): codec_options = CodecOptions(tz_aware=True) write_concern = WriteConcern(w=2, j=True) db = self.client.get_database("foo", codec_options, ReadPreference.SECONDARY, write_concern) self.assertEqual("foo", db.name) self.assertEqual(codec_options, db.codec_options) self.assertEqual(ReadPreference.SECONDARY, db.read_preference) self.assertEqual(write_concern, db.write_concern) def test_getattr(self): self.assertTrue(isinstance(self.client["_does_not_exist"], Database)) with self.assertRaises(AttributeError) as context: self.client._does_not_exist # Message should be: # "AttributeError: MongoClient has no attribute '_does_not_exist'. To # access the _does_not_exist database, use client['_does_not_exist']". self.assertIn("has no attribute '_does_not_exist'", str(context.exception)) def test_iteration(self): client = self.client if "PyPy" in sys.version and sys.version_info < (3, 8, 15): msg = "'NoneType' object is not callable" else: msg = "'MongoClient' object is not iterable" # Iteration fails with self.assertRaisesRegex(TypeError, msg): for _ in client: # type: ignore[misc] # error: "None" not callable [misc] break # Index fails with self.assertRaises(TypeError): _ = client[0] # next fails with self.assertRaisesRegex(TypeError, "'MongoClient' object is not iterable"): _ = next(client) # .next() fails with self.assertRaisesRegex(TypeError, "'MongoClient' object is not iterable"): _ = client.next() # Do not implement typing.Iterable. self.assertNotIsInstance(client, Iterable) def test_get_default_database(self): c = rs_or_single_client( "mongodb://%s:%d/foo" % (client_context.host, client_context.port), connect=False ) self.assertEqual(Database(c, "foo"), c.get_default_database()) # Test that default doesn't override the URI value. self.assertEqual(Database(c, "foo"), c.get_default_database("bar")) codec_options = CodecOptions(tz_aware=True) write_concern = WriteConcern(w=2, j=True) db = c.get_default_database(None, codec_options, ReadPreference.SECONDARY, write_concern) self.assertEqual("foo", db.name) self.assertEqual(codec_options, db.codec_options) self.assertEqual(ReadPreference.SECONDARY, db.read_preference) self.assertEqual(write_concern, db.write_concern) c = rs_or_single_client( "mongodb://%s:%d/" % (client_context.host, client_context.port), connect=False ) self.assertEqual(Database(c, "foo"), c.get_default_database("foo")) def test_get_default_database_error(self): # URI with no database. c = rs_or_single_client( "mongodb://%s:%d/" % (client_context.host, client_context.port), connect=False ) self.assertRaises(ConfigurationError, c.get_default_database) def test_get_default_database_with_authsource(self): # Ensure we distinguish database name from authSource. uri = "mongodb://%s:%d/foo?authSource=src" % (client_context.host, client_context.port) c = rs_or_single_client(uri, connect=False) self.assertEqual(Database(c, "foo"), c.get_default_database()) def test_get_database_default(self): c = rs_or_single_client( "mongodb://%s:%d/foo" % (client_context.host, client_context.port), connect=False ) self.assertEqual(Database(c, "foo"), c.get_database()) def test_get_database_default_error(self): # URI with no database. c = rs_or_single_client( "mongodb://%s:%d/" % (client_context.host, client_context.port), connect=False ) self.assertRaises(ConfigurationError, c.get_database) def test_get_database_default_with_authsource(self): # Ensure we distinguish database name from authSource. uri = "mongodb://%s:%d/foo?authSource=src" % (client_context.host, client_context.port) c = rs_or_single_client(uri, connect=False) self.assertEqual(Database(c, "foo"), c.get_database()) def test_primary_read_pref_with_tags(self): # No tags allowed with "primary". with self.assertRaises(ConfigurationError): MongoClient("mongodb://host/?readpreferencetags=dc:east") with self.assertRaises(ConfigurationError): MongoClient("mongodb://host/?readpreference=primary&readpreferencetags=dc:east") def test_read_preference(self): c = rs_or_single_client( "mongodb://host", connect=False, readpreference=ReadPreference.NEAREST.mongos_mode ) self.assertEqual(c.read_preference, ReadPreference.NEAREST) def test_metadata(self): metadata = copy.deepcopy(_METADATA) metadata["application"] = {"name": "foobar"} client = MongoClient("mongodb://foo:27017/?appname=foobar&connect=false") options = client._MongoClient__options self.assertEqual(options.pool_options.metadata, metadata) client = MongoClient("foo", 27017, appname="foobar", connect=False) options = client._MongoClient__options self.assertEqual(options.pool_options.metadata, metadata) # No error MongoClient(appname="x" * 128) self.assertRaises(ValueError, MongoClient, appname="x" * 129) # Bad "driver" options. self.assertRaises(TypeError, DriverInfo, "Foo", 1, "a") self.assertRaises(TypeError, DriverInfo, version="1", platform="a") self.assertRaises(TypeError, DriverInfo) self.assertRaises(TypeError, MongoClient, driver=1) self.assertRaises(TypeError, MongoClient, driver="abc") self.assertRaises(TypeError, MongoClient, driver=("Foo", "1", "a")) # Test appending to driver info. metadata["driver"]["name"] = "PyMongo|FooDriver" metadata["driver"]["version"] = "{}|1.2.3".format(_METADATA["driver"]["version"]) client = MongoClient( "foo", 27017, appname="foobar", driver=DriverInfo("FooDriver", "1.2.3", None), connect=False, ) options = client._MongoClient__options self.assertEqual(options.pool_options.metadata, metadata) metadata["platform"] = "{}|FooPlatform".format(_METADATA["platform"]) client = MongoClient( "foo", 27017, appname="foobar", driver=DriverInfo("FooDriver", "1.2.3", "FooPlatform"), connect=False, ) options = client._MongoClient__options self.assertEqual(options.pool_options.metadata, metadata) @mock.patch.dict("os.environ", {ENV_VAR_K8S: "1"}) def test_container_metadata(self): metadata = copy.deepcopy(_METADATA) metadata["env"] = {} metadata["env"]["container"] = {"orchestrator": "kubernetes"} client = MongoClient("mongodb://foo:27017/?appname=foobar&connect=false") options = client._MongoClient__options self.assertEqual(options.pool_options.metadata["env"], metadata["env"]) def test_kwargs_codec_options(self): class MyFloatType: def __init__(self, x): self.__x = x @property def x(self): return self.__x class MyFloatAsIntEncoder(TypeEncoder): python_type = MyFloatType def transform_python(self, value): return int(value) # Ensure codec options are passed in correctly document_class: Type[SON] = SON type_registry = TypeRegistry([MyFloatAsIntEncoder()]) tz_aware = True uuid_representation_label = "javaLegacy" unicode_decode_error_handler = "ignore" tzinfo = utc c = MongoClient( document_class=document_class, type_registry=type_registry, tz_aware=tz_aware, uuidrepresentation=uuid_representation_label, unicode_decode_error_handler=unicode_decode_error_handler, tzinfo=tzinfo, connect=False, ) self.assertEqual(c.codec_options.document_class, document_class) self.assertEqual(c.codec_options.type_registry, type_registry) self.assertEqual(c.codec_options.tz_aware, tz_aware) self.assertEqual( c.codec_options.uuid_representation, _UUID_REPRESENTATIONS[uuid_representation_label] ) self.assertEqual(c.codec_options.unicode_decode_error_handler, unicode_decode_error_handler) self.assertEqual(c.codec_options.tzinfo, tzinfo) def test_uri_codec_options(self): # Ensure codec options are passed in correctly uuid_representation_label = "javaLegacy" unicode_decode_error_handler = "ignore" datetime_conversion = "DATETIME_CLAMP" uri = ( "mongodb://%s:%d/foo?tz_aware=true&uuidrepresentation=" "%s&unicode_decode_error_handler=%s" "&datetime_conversion=%s" % ( client_context.host, client_context.port, uuid_representation_label, unicode_decode_error_handler, datetime_conversion, ) ) c = MongoClient(uri, connect=False) self.assertEqual(c.codec_options.tz_aware, True) self.assertEqual( c.codec_options.uuid_representation, _UUID_REPRESENTATIONS[uuid_representation_label] ) self.assertEqual(c.codec_options.unicode_decode_error_handler, unicode_decode_error_handler) self.assertEqual( c.codec_options.datetime_conversion, DatetimeConversion[datetime_conversion] ) # Change the passed datetime_conversion to a number and re-assert. uri = uri.replace(datetime_conversion, f"{int(DatetimeConversion[datetime_conversion])}") c = MongoClient(uri, connect=False) self.assertEqual( c.codec_options.datetime_conversion, DatetimeConversion[datetime_conversion] ) def test_uri_option_precedence(self): # Ensure kwarg options override connection string options. uri = "mongodb://localhost/?ssl=true&replicaSet=name&readPreference=primary" c = MongoClient(uri, ssl=False, replicaSet="newname", readPreference="secondaryPreferred") clopts = c._MongoClient__options opts = clopts._options self.assertEqual(opts["tls"], False) self.assertEqual(clopts.replica_set_name, "newname") self.assertEqual(clopts.read_preference, ReadPreference.SECONDARY_PREFERRED) def test_connection_timeout_ms_propagates_to_DNS_resolver(self): # Patch the resolver. from pymongo.srv_resolver import _resolve patched_resolver = FunctionCallRecorder(_resolve) pymongo.srv_resolver._resolve = patched_resolver def reset_resolver(): pymongo.srv_resolver._resolve = _resolve self.addCleanup(reset_resolver) # Setup. base_uri = "mongodb+srv://test5.test.build.10gen.cc" connectTimeoutMS = 5000 expected_kw_value = 5.0 uri_with_timeout = base_uri + "/?connectTimeoutMS=6000" expected_uri_value = 6.0 def test_scenario(args, kwargs, expected_value): patched_resolver.reset() MongoClient(*args, **kwargs) for _, kw in patched_resolver.call_list(): self.assertAlmostEqual(kw["lifetime"], expected_value) # No timeout specified. test_scenario((base_uri,), {}, CONNECT_TIMEOUT) # Timeout only specified in connection string. test_scenario((uri_with_timeout,), {}, expected_uri_value) # Timeout only specified in keyword arguments. kwarg = {"connectTimeoutMS": connectTimeoutMS} test_scenario((base_uri,), kwarg, expected_kw_value) # Timeout specified in both kwargs and connection string. test_scenario((uri_with_timeout,), kwarg, expected_kw_value) def test_uri_security_options(self): # Ensure that we don't silently override security-related options. with self.assertRaises(InvalidURI): MongoClient("mongodb://localhost/?ssl=true", tls=False, connect=False) # Matching SSL and TLS options should not cause errors. c = MongoClient("mongodb://localhost/?ssl=false", tls=False, connect=False) self.assertEqual(c._MongoClient__options._options["tls"], False) # Conflicting tlsInsecure options should raise an error. with self.assertRaises(InvalidURI): MongoClient( "mongodb://localhost/?tlsInsecure=true", connect=False, tlsAllowInvalidHostnames=True, ) # Conflicting legacy tlsInsecure options should also raise an error. with self.assertRaises(InvalidURI): MongoClient( "mongodb://localhost/?tlsInsecure=true", connect=False, tlsAllowInvalidCertificates=False, ) # Conflicting kwargs should raise InvalidURI with self.assertRaises(InvalidURI): MongoClient(ssl=True, tls=False) def test_event_listeners(self): c = MongoClient(event_listeners=[], connect=False) self.assertEqual(c.options.event_listeners, []) listeners = [ event_loggers.CommandLogger(), event_loggers.HeartbeatLogger(), event_loggers.ServerLogger(), event_loggers.TopologyLogger(), event_loggers.ConnectionPoolLogger(), ] c = MongoClient(event_listeners=listeners, connect=False) self.assertEqual(c.options.event_listeners, listeners) def test_client_options(self): c = MongoClient(connect=False) self.assertIsInstance(c.options, ClientOptions) self.assertIsInstance(c.options.pool_options, PoolOptions) self.assertEqual(c.options.server_selection_timeout, 30) self.assertEqual(c.options.pool_options.max_idle_time_seconds, None) self.assertIsInstance(c.options.retry_writes, bool) self.assertIsInstance(c.options.retry_reads, bool) def test_validate_suggestion(self): """Validate kwargs in constructor.""" for typo in ["auth", "Auth", "AUTH"]: expected = f"Unknown option: {typo}. Did you mean one of (authsource, authmechanism, authoidcallowedhosts) or maybe a camelCase version of one? Refer to docstring." expected = re.escape(expected) with self.assertRaisesRegex(ConfigurationError, expected): MongoClient(**{typo: "standard"}) # type: ignore[arg-type] @patch("pymongo.srv_resolver._SrvResolver.get_hosts") def test_detected_environment_logging(self, mock_get_hosts): normal_hosts = [ "normal.host.com", "host.cosmos.azure.com", "host.docdb.amazonaws.com", "host.docdb-elastic.amazonaws.com", ] srv_hosts = ["mongodb+srv://:@" + s for s in normal_hosts] multi_host = ( "host.cosmos.azure.com,host.docdb.amazonaws.com,host.docdb-elastic.amazonaws.com" ) with self.assertLogs("pymongo", level="INFO") as cm: for host in normal_hosts: MongoClient(host) for host in srv_hosts: mock_get_hosts.return_value = [(host, 1)] MongoClient(host) MongoClient(multi_host) logs = [record.message for record in cm.records if record.name == "pymongo.client"] self.assertEqual(len(logs), 7) @patch("pymongo.srv_resolver._SrvResolver.get_hosts") def test_detected_environment_warning(self, mock_get_hosts): with self._caplog.at_level(logging.WARN): normal_hosts = [ "host.cosmos.azure.com", "host.docdb.amazonaws.com", "host.docdb-elastic.amazonaws.com", ] srv_hosts = ["mongodb+srv://:@" + s for s in normal_hosts] multi_host = ( "host.cosmos.azure.com,host.docdb.amazonaws.com,host.docdb-elastic.amazonaws.com" ) for host in normal_hosts: with self.assertWarns(UserWarning): MongoClient(host) for host in srv_hosts: mock_get_hosts.return_value = [(host, 1)] with self.assertWarns(UserWarning): MongoClient(host) with self.assertWarns(UserWarning): MongoClient(multi_host) class TestClient(IntegrationTest): def test_multiple_uris(self): with self.assertRaises(ConfigurationError): MongoClient( host=[ "mongodb+srv://cluster-a.abc12.mongodb.net", "mongodb+srv://cluster-b.abc12.mongodb.net", "mongodb+srv://cluster-c.abc12.mongodb.net", ] ) def test_max_idle_time_reaper_default(self): with client_knobs(kill_cursor_frequency=0.1): # Assert reaper doesn't remove connections when maxIdleTimeMS not set client = rs_or_single_client() server = client._get_topology().select_server(readable_server_selector, _Op.TEST) with server._pool.checkout() as conn: pass self.assertEqual(1, len(server._pool.conns)) self.assertTrue(conn in server._pool.conns) client.close() def test_max_idle_time_reaper_removes_stale_minPoolSize(self): with client_knobs(kill_cursor_frequency=0.1): # Assert reaper removes idle socket and replaces it with a new one client = rs_or_single_client(maxIdleTimeMS=500, minPoolSize=1) server = client._get_topology().select_server(readable_server_selector, _Op.TEST) with server._pool.checkout() as conn: pass # When the reaper runs at the same time as the get_socket, two # connections could be created and checked into the pool. self.assertGreaterEqual(len(server._pool.conns), 1) wait_until(lambda: conn not in server._pool.conns, "remove stale socket") wait_until(lambda: len(server._pool.conns) >= 1, "replace stale socket") client.close() def test_max_idle_time_reaper_does_not_exceed_maxPoolSize(self): with client_knobs(kill_cursor_frequency=0.1): # Assert reaper respects maxPoolSize when adding new connections. client = rs_or_single_client(maxIdleTimeMS=500, minPoolSize=1, maxPoolSize=1) server = client._get_topology().select_server(readable_server_selector, _Op.TEST) with server._pool.checkout() as conn: pass # When the reaper runs at the same time as the get_socket, # maxPoolSize=1 should prevent two connections from being created. self.assertEqual(1, len(server._pool.conns)) wait_until(lambda: conn not in server._pool.conns, "remove stale socket") wait_until(lambda: len(server._pool.conns) == 1, "replace stale socket") client.close() def test_max_idle_time_reaper_removes_stale(self): with client_knobs(kill_cursor_frequency=0.1): # Assert reaper has removed idle socket and NOT replaced it client = rs_or_single_client(maxIdleTimeMS=500) server = client._get_topology().select_server(readable_server_selector, _Op.TEST) with server._pool.checkout() as conn_one: pass # Assert that the pool does not close connections prematurely. time.sleep(0.300) with server._pool.checkout() as conn_two: pass self.assertIs(conn_one, conn_two) wait_until( lambda: len(server._pool.conns) == 0, "stale socket reaped and new one NOT added to the pool", ) client.close() def test_min_pool_size(self): with client_knobs(kill_cursor_frequency=0.1): client = rs_or_single_client() server = client._get_topology().select_server(readable_server_selector, _Op.TEST) self.assertEqual(0, len(server._pool.conns)) # Assert that pool started up at minPoolSize client = rs_or_single_client(minPoolSize=10) server = client._get_topology().select_server(readable_server_selector, _Op.TEST) wait_until( lambda: len(server._pool.conns) == 10, "pool initialized with 10 connections", ) # Assert that if a socket is closed, a new one takes its place with server._pool.checkout() as conn: conn.close_conn(None) wait_until( lambda: len(server._pool.conns) == 10, "a closed socket gets replaced from the pool", ) self.assertFalse(conn in server._pool.conns) def test_max_idle_time_checkout(self): # Use high frequency to test _get_socket_no_auth. with client_knobs(kill_cursor_frequency=99999999): client = rs_or_single_client(maxIdleTimeMS=500) server = client._get_topology().select_server(readable_server_selector, _Op.TEST) with server._pool.checkout() as conn: pass self.assertEqual(1, len(server._pool.conns)) time.sleep(1) # Sleep so that the socket becomes stale. with server._pool.checkout() as new_con: self.assertNotEqual(conn, new_con) self.assertEqual(1, len(server._pool.conns)) self.assertFalse(conn in server._pool.conns) self.assertTrue(new_con in server._pool.conns) # Test that connections are reused if maxIdleTimeMS is not set. client = rs_or_single_client() server = client._get_topology().select_server(readable_server_selector, _Op.TEST) with server._pool.checkout() as conn: pass self.assertEqual(1, len(server._pool.conns)) time.sleep(1) with server._pool.checkout() as new_con: self.assertEqual(conn, new_con) self.assertEqual(1, len(server._pool.conns)) def test_constants(self): """This test uses MongoClient explicitly to make sure that host and port are not overloaded. """ host, port = client_context.host, client_context.port kwargs: dict = client_context.default_client_options.copy() if client_context.auth_enabled: kwargs["username"] = db_user kwargs["password"] = db_pwd # Set bad defaults. MongoClient.HOST = "somedomainthatdoesntexist.org" MongoClient.PORT = 123456789 with self.assertRaises(AutoReconnect): connected(MongoClient(serverSelectionTimeoutMS=10, **kwargs)) # Override the defaults. No error. connected(MongoClient(host, port, **kwargs)) # Set good defaults. MongoClient.HOST = host MongoClient.PORT = port # No error. connected(MongoClient(**kwargs)) def test_init_disconnected(self): host, port = client_context.host, client_context.port c = rs_or_single_client(connect=False) # is_primary causes client to block until connected self.assertIsInstance(c.is_primary, bool) c = rs_or_single_client(connect=False) self.assertIsInstance(c.is_mongos, bool) c = rs_or_single_client(connect=False) self.assertIsInstance(c.options.pool_options.max_pool_size, int) self.assertIsInstance(c.nodes, frozenset) c = rs_or_single_client(connect=False) self.assertEqual(c.codec_options, CodecOptions()) c = rs_or_single_client(connect=False) self.assertFalse(c.primary) self.assertFalse(c.secondaries) c = rs_or_single_client(connect=False) self.assertIsInstance(c.topology_description, TopologyDescription) self.assertEqual(c.topology_description, c._topology._description) self.assertIsNone(c.address) # PYTHON-2981 c.admin.command("ping") # connect if client_context.is_rs: # The primary's host and port are from the replica set config. self.assertIsNotNone(c.address) else: self.assertEqual(c.address, (host, port)) bad_host = "somedomainthatdoesntexist.org" c = MongoClient(bad_host, port, connectTimeoutMS=1, serverSelectionTimeoutMS=10) self.assertRaises(ConnectionFailure, c.pymongo_test.test.find_one) def test_init_disconnected_with_auth(self): uri = "mongodb://user:pass@somedomainthatdoesntexist" c = MongoClient(uri, connectTimeoutMS=1, serverSelectionTimeoutMS=10) self.assertRaises(ConnectionFailure, c.pymongo_test.test.find_one) def test_equality(self): seed = "{}:{}".format(*list(self.client._topology_settings.seeds)[0]) c = rs_or_single_client(seed, connect=False) self.addCleanup(c.close) self.assertEqual(client_context.client, c) # Explicitly test inequality self.assertFalse(client_context.client != c) c = rs_or_single_client("invalid.com", connect=False) self.addCleanup(c.close) self.assertNotEqual(client_context.client, c) self.assertTrue(client_context.client != c) # Seeds differ: self.assertNotEqual(MongoClient("a", connect=False), MongoClient("b", connect=False)) # Same seeds but out of order still compares equal: self.assertEqual( MongoClient(["a", "b", "c"], connect=False), MongoClient(["c", "a", "b"], connect=False) ) def test_hashable(self): seed = "{}:{}".format(*list(self.client._topology_settings.seeds)[0]) c = rs_or_single_client(seed, connect=False) self.addCleanup(c.close) self.assertIn(c, {client_context.client}) c = rs_or_single_client("invalid.com", connect=False) self.addCleanup(c.close) self.assertNotIn(c, {client_context.client}) def test_host_w_port(self): with self.assertRaises(ValueError): connected( MongoClient( f"{client_context.host}:1234567", connectTimeoutMS=1, serverSelectionTimeoutMS=10, ) ) def test_repr(self): # Used to test 'eval' below. import bson client = MongoClient( # type: ignore[type-var] "mongodb://localhost:27017,localhost:27018/?replicaSet=replset" "&connectTimeoutMS=12345&w=1&wtimeoutms=100", connect=False, document_class=SON, ) the_repr = repr(client) self.assertIn("MongoClient(host=", the_repr) self.assertIn("document_class=bson.son.SON, tz_aware=False, connect=False, ", the_repr) self.assertIn("connecttimeoutms=12345", the_repr) self.assertIn("replicaset='replset'", the_repr) self.assertIn("w=1", the_repr) self.assertIn("wtimeoutms=100", the_repr) self.assertEqual(eval(the_repr), client) client = MongoClient( "localhost:27017,localhost:27018", replicaSet="replset", connectTimeoutMS=12345, socketTimeoutMS=None, w=1, wtimeoutms=100, connect=False, ) the_repr = repr(client) self.assertIn("MongoClient(host=", the_repr) self.assertIn("document_class=dict, tz_aware=False, connect=False, ", the_repr) self.assertIn("connecttimeoutms=12345", the_repr) self.assertIn("replicaset='replset'", the_repr) self.assertIn("sockettimeoutms=None", the_repr) self.assertIn("w=1", the_repr) self.assertIn("wtimeoutms=100", the_repr) self.assertEqual(eval(the_repr), client) def test_getters(self): wait_until(lambda: client_context.nodes == self.client.nodes, "find all nodes") def test_list_databases(self): cmd_docs = self.client.admin.command("listDatabases")["databases"] cursor = self.client.list_databases() self.assertIsInstance(cursor, CommandCursor) helper_docs = list(cursor) self.assertTrue(len(helper_docs) > 0) self.assertEqual(len(helper_docs), len(cmd_docs)) # PYTHON-3529 Some fields may change between calls, just compare names. for helper_doc, cmd_doc in zip(helper_docs, cmd_docs): self.assertIs(type(helper_doc), dict) self.assertEqual(helper_doc.keys(), cmd_doc.keys()) client = rs_or_single_client(document_class=SON) self.addCleanup(client.close) for doc in client.list_databases(): self.assertIs(type(doc), dict) self.client.pymongo_test.test.insert_one({}) cursor = self.client.list_databases(filter={"name": "admin"}) docs = list(cursor) self.assertEqual(1, len(docs)) self.assertEqual(docs[0]["name"], "admin") cursor = self.client.list_databases(nameOnly=True) for doc in cursor: self.assertEqual(["name"], list(doc)) def test_list_database_names(self): self.client.pymongo_test.test.insert_one({"dummy": "object"}) self.client.pymongo_test_mike.test.insert_one({"dummy": "object"}) cmd_docs = self.client.admin.command("listDatabases")["databases"] cmd_names = [doc["name"] for doc in cmd_docs] db_names = self.client.list_database_names() self.assertTrue("pymongo_test" in db_names) self.assertTrue("pymongo_test_mike" in db_names) self.assertEqual(db_names, cmd_names) def test_drop_database(self): self.assertRaises(TypeError, self.client.drop_database, 5) self.assertRaises(TypeError, self.client.drop_database, None) self.client.pymongo_test.test.insert_one({"dummy": "object"}) self.client.pymongo_test2.test.insert_one({"dummy": "object"}) dbs = self.client.list_database_names() self.assertIn("pymongo_test", dbs) self.assertIn("pymongo_test2", dbs) self.client.drop_database("pymongo_test") if client_context.is_rs: wc_client = rs_or_single_client(w=len(client_context.nodes) + 1) with self.assertRaises(WriteConcernError): wc_client.drop_database("pymongo_test2") self.client.drop_database(self.client.pymongo_test2) dbs = self.client.list_database_names() self.assertNotIn("pymongo_test", dbs) self.assertNotIn("pymongo_test2", dbs) def test_close(self): test_client = rs_or_single_client() coll = test_client.pymongo_test.bar test_client.close() self.assertRaises(InvalidOperation, coll.count_documents, {}) def test_close_kills_cursors(self): if sys.platform.startswith("java"): # We can't figure out how to make this test reliable with Jython. raise SkipTest("Can't test with Jython") test_client = rs_or_single_client() # Kill any cursors possibly queued up by previous tests. gc.collect() test_client._process_periodic_tasks() # Add some test data. coll = test_client.pymongo_test.test_close_kills_cursors docs_inserted = 1000 coll.insert_many([{"i": i} for i in range(docs_inserted)]) # Open a cursor and leave it open on the server. cursor = coll.find().batch_size(10) self.assertTrue(bool(next(cursor))) self.assertLess(cursor.retrieved, docs_inserted) # Open a command cursor and leave it open on the server. cursor = coll.aggregate([], batchSize=10) self.assertTrue(bool(next(cursor))) del cursor # Required for PyPy, Jython and other Python implementations that # don't use reference counting garbage collection. gc.collect() # Close the client and ensure the topology is closed. self.assertTrue(test_client._topology._opened) test_client.close() self.assertFalse(test_client._topology._opened) test_client = rs_or_single_client() # The killCursors task should not need to re-open the topology. test_client._process_periodic_tasks() self.assertTrue(test_client._topology._opened) def test_close_stops_kill_cursors_thread(self): client = rs_client() client.test.test.find_one() self.assertFalse(client._kill_cursors_executor._stopped) # Closing the client should stop the thread. client.close() self.assertTrue(client._kill_cursors_executor._stopped) # Reusing the closed client should raise an InvalidOperation error. self.assertRaises(InvalidOperation, client.admin.command, "ping") # Thread is still stopped. self.assertTrue(client._kill_cursors_executor._stopped) def test_uri_connect_option(self): # Ensure that topology is not opened if connect=False. client = rs_client(connect=False) self.assertFalse(client._topology._opened) # Ensure kill cursors thread has not been started. kc_thread = client._kill_cursors_executor._thread self.assertFalse(kc_thread and kc_thread.is_alive()) # Using the client should open topology and start the thread. client.admin.command("ping") self.assertTrue(client._topology._opened) kc_thread = client._kill_cursors_executor._thread self.assertTrue(kc_thread and kc_thread.is_alive()) # Tear down. client.close() def test_close_does_not_open_servers(self): client = rs_client(connect=False) topology = client._topology self.assertEqual(topology._servers, {}) client.close() self.assertEqual(topology._servers, {}) def test_close_closes_sockets(self): client = rs_client() self.addCleanup(client.close) client.test.test.find_one() topology = client._topology client.close() for server in topology._servers.values(): self.assertFalse(server._pool.conns) self.assertTrue(server._monitor._executor._stopped) self.assertTrue(server._monitor._rtt_monitor._executor._stopped) self.assertFalse(server._monitor._pool.conns) self.assertFalse(server._monitor._rtt_monitor._pool.conns) def test_bad_uri(self): with self.assertRaises(InvalidURI): MongoClient("http://localhost") @client_context.require_auth def test_auth_from_uri(self): host, port = client_context.host, client_context.port client_context.create_user("admin", "admin", "pass") self.addCleanup(client_context.drop_user, "admin", "admin") self.addCleanup(remove_all_users, self.client.pymongo_test) client_context.create_user("pymongo_test", "user", "pass", roles=["userAdmin", "readWrite"]) with self.assertRaises(OperationFailure): connected(rs_or_single_client_noauth("mongodb://a:b@%s:%d" % (host, port))) # No error. connected(rs_or_single_client_noauth("mongodb://admin:pass@%s:%d" % (host, port))) # Wrong database. uri = "mongodb://admin:pass@%s:%d/pymongo_test" % (host, port) with self.assertRaises(OperationFailure): connected(rs_or_single_client_noauth(uri)) # No error. connected( rs_or_single_client_noauth("mongodb://user:pass@%s:%d/pymongo_test" % (host, port)) ) # Auth with lazy connection. rs_or_single_client_noauth( "mongodb://user:pass@%s:%d/pymongo_test" % (host, port), connect=False ).pymongo_test.test.find_one() # Wrong password. bad_client = rs_or_single_client_noauth( "mongodb://user:wrong@%s:%d/pymongo_test" % (host, port), connect=False ) self.assertRaises(OperationFailure, bad_client.pymongo_test.test.find_one) @client_context.require_auth def test_username_and_password(self): client_context.create_user("admin", "ad min", "pa/ss") self.addCleanup(client_context.drop_user, "admin", "ad min") c = rs_or_single_client_noauth(username="ad min", password="pa/ss") # Username and password aren't in strings that will likely be logged. self.assertNotIn("ad min", repr(c)) self.assertNotIn("ad min", str(c)) self.assertNotIn("pa/ss", repr(c)) self.assertNotIn("pa/ss", str(c)) # Auth succeeds. c.server_info() with self.assertRaises(OperationFailure): rs_or_single_client_noauth(username="ad min", password="foo").server_info() @client_context.require_auth def test_lazy_auth_raises_operation_failure(self): lazy_client = rs_or_single_client_noauth( f"mongodb://user:wrong@{client_context.host}/pymongo_test", connect=False ) assertRaisesExactly(OperationFailure, lazy_client.test.collection.find_one) @client_context.require_no_tls def test_unix_socket(self): if not hasattr(socket, "AF_UNIX"): raise SkipTest("UNIX-sockets are not supported on this system") mongodb_socket = "/tmp/mongodb-%d.sock" % (client_context.port,) encoded_socket = "%2Ftmp%2F" + "mongodb-%d.sock" % (client_context.port,) if not os.access(mongodb_socket, os.R_OK): raise SkipTest("Socket file is not accessible") uri = "mongodb://%s" % encoded_socket # Confirm we can do operations via the socket. client = rs_or_single_client(uri) self.addCleanup(client.close) client.pymongo_test.test.insert_one({"dummy": "object"}) dbs = client.list_database_names() self.assertTrue("pymongo_test" in dbs) self.assertTrue(mongodb_socket in repr(client)) # Confirm it fails with a missing socket. self.assertRaises( ConnectionFailure, connected, MongoClient("mongodb://%2Ftmp%2Fnon-existent.sock", serverSelectionTimeoutMS=100), ) def test_document_class(self): c = self.client db = c.pymongo_test db.test.insert_one({"x": 1}) self.assertEqual(dict, c.codec_options.document_class) self.assertTrue(isinstance(db.test.find_one(), dict)) self.assertFalse(isinstance(db.test.find_one(), SON)) c = rs_or_single_client(document_class=SON) self.addCleanup(c.close) db = c.pymongo_test self.assertEqual(SON, c.codec_options.document_class) self.assertTrue(isinstance(db.test.find_one(), SON)) def test_timeouts(self): client = rs_or_single_client( connectTimeoutMS=10500, socketTimeoutMS=10500, maxIdleTimeMS=10500, serverSelectionTimeoutMS=10500, ) self.assertEqual(10.5, get_pool(client).opts.connect_timeout) self.assertEqual(10.5, get_pool(client).opts.socket_timeout) self.assertEqual(10.5, get_pool(client).opts.max_idle_time_seconds) self.assertEqual(10.5, client.options.pool_options.max_idle_time_seconds) self.assertEqual(10.5, client.options.server_selection_timeout) def test_socket_timeout_ms_validation(self): c = rs_or_single_client(socketTimeoutMS=10 * 1000) self.assertEqual(10, get_pool(c).opts.socket_timeout) c = connected(rs_or_single_client(socketTimeoutMS=None)) self.assertEqual(None, get_pool(c).opts.socket_timeout) c = connected(rs_or_single_client(socketTimeoutMS=0)) self.assertEqual(None, get_pool(c).opts.socket_timeout) self.assertRaises(ValueError, rs_or_single_client, socketTimeoutMS=-1) self.assertRaises(ValueError, rs_or_single_client, socketTimeoutMS=1e10) self.assertRaises(ValueError, rs_or_single_client, socketTimeoutMS="foo") def test_socket_timeout(self): no_timeout = self.client timeout_sec = 1 timeout = rs_or_single_client(socketTimeoutMS=1000 * timeout_sec) self.addCleanup(timeout.close) no_timeout.pymongo_test.drop_collection("test") no_timeout.pymongo_test.test.insert_one({"x": 1}) # A $where clause that takes a second longer than the timeout where_func = delay(timeout_sec + 1) def get_x(db): doc = next(db.test.find().where(where_func)) return doc["x"] self.assertEqual(1, get_x(no_timeout.pymongo_test)) self.assertRaises(NetworkTimeout, get_x, timeout.pymongo_test) def test_server_selection_timeout(self): client = MongoClient(serverSelectionTimeoutMS=100, connect=False) self.assertAlmostEqual(0.1, client.options.server_selection_timeout) client = MongoClient(serverSelectionTimeoutMS=0, connect=False) self.assertAlmostEqual(0, client.options.server_selection_timeout) self.assertRaises(ValueError, MongoClient, serverSelectionTimeoutMS="foo", connect=False) self.assertRaises(ValueError, MongoClient, serverSelectionTimeoutMS=-1, connect=False) self.assertRaises( ConfigurationError, MongoClient, serverSelectionTimeoutMS=None, connect=False ) client = MongoClient("mongodb://localhost/?serverSelectionTimeoutMS=100", connect=False) self.assertAlmostEqual(0.1, client.options.server_selection_timeout) client = MongoClient("mongodb://localhost/?serverSelectionTimeoutMS=0", connect=False) self.assertAlmostEqual(0, client.options.server_selection_timeout) # Test invalid timeout in URI ignored and set to default. client = MongoClient("mongodb://localhost/?serverSelectionTimeoutMS=-1", connect=False) self.assertAlmostEqual(30, client.options.server_selection_timeout) client = MongoClient("mongodb://localhost/?serverSelectionTimeoutMS=", connect=False) self.assertAlmostEqual(30, client.options.server_selection_timeout) def test_waitQueueTimeoutMS(self): client = rs_or_single_client(waitQueueTimeoutMS=2000) self.assertEqual(get_pool(client).opts.wait_queue_timeout, 2) def test_socketKeepAlive(self): pool = get_pool(self.client) with pool.checkout() as conn: keepalive = conn.conn.getsockopt(socket.SOL_SOCKET, socket.SO_KEEPALIVE) self.assertTrue(keepalive) @no_type_check def test_tz_aware(self): self.assertRaises(ValueError, MongoClient, tz_aware="foo") aware = rs_or_single_client(tz_aware=True) self.addCleanup(aware.close) naive = self.client aware.pymongo_test.drop_collection("test") now = datetime.datetime.now(tz=datetime.timezone.utc) aware.pymongo_test.test.insert_one({"x": now}) self.assertEqual(None, naive.pymongo_test.test.find_one()["x"].tzinfo) self.assertEqual(utc, aware.pymongo_test.test.find_one()["x"].tzinfo) self.assertEqual( aware.pymongo_test.test.find_one()["x"].replace(tzinfo=None), naive.pymongo_test.test.find_one()["x"], ) @client_context.require_ipv6 def test_ipv6(self): if client_context.tls: if not HAVE_IPADDRESS: raise SkipTest("Need the ipaddress module to test with SSL") if client_context.auth_enabled: auth_str = f"{db_user}:{db_pwd}@" else: auth_str = "" uri = "mongodb://%s[::1]:%d" % (auth_str, client_context.port) if client_context.is_rs: uri += "/?replicaSet=" + (client_context.replica_set_name or "") client = rs_or_single_client_noauth(uri) self.addCleanup(client.close) client.pymongo_test.test.insert_one({"dummy": "object"}) client.pymongo_test_bernie.test.insert_one({"dummy": "object"}) dbs = client.list_database_names() self.assertTrue("pymongo_test" in dbs) self.assertTrue("pymongo_test_bernie" in dbs) def test_contextlib(self): client = rs_or_single_client() client.pymongo_test.drop_collection("test") client.pymongo_test.test.insert_one({"foo": "bar"}) # The socket used for the previous commands has been returned to the # pool self.assertEqual(1, len(get_pool(client).conns)) with contextlib.closing(client): self.assertEqual("bar", client.pymongo_test.test.find_one()["foo"]) with self.assertRaises(InvalidOperation): client.pymongo_test.test.find_one() client = rs_or_single_client() with client as client: self.assertEqual("bar", client.pymongo_test.test.find_one()["foo"]) with self.assertRaises(InvalidOperation): client.pymongo_test.test.find_one() def test_interrupt_signal(self): if sys.platform.startswith("java"): # We can't figure out how to raise an exception on a thread that's # blocked on a socket, whether that's the main thread or a worker, # without simply killing the whole thread in Jython. This suggests # PYTHON-294 can't actually occur in Jython. raise SkipTest("Can't test interrupts in Jython") if is_greenthread_patched(): raise SkipTest("Can't reliably test interrupts with green threads") # Test fix for PYTHON-294 -- make sure MongoClient closes its # socket if it gets an interrupt while waiting to recv() from it. db = self.client.pymongo_test # A $where clause which takes 1.5 sec to execute where = delay(1.5) # Need exactly 1 document so find() will execute its $where clause once db.drop_collection("foo") db.foo.insert_one({"_id": 1}) old_signal_handler = None try: # Platform-specific hacks for raising a KeyboardInterrupt on the # main thread while find() is in-progress: On Windows, SIGALRM is # unavailable so we use a second thread. In our Evergreen setup on # Linux, the thread technique causes an error in the test at # conn.recv(): TypeError: 'int' object is not callable # We don't know what causes this, so we hack around it. if sys.platform == "win32": def interrupter(): # Raises KeyboardInterrupt in the main thread time.sleep(0.25) thread.interrupt_main() thread.start_new_thread(interrupter, ()) else: # Convert SIGALRM to SIGINT -- it's hard to schedule a SIGINT # for one second in the future, but easy to schedule SIGALRM. def sigalarm(num, frame): raise KeyboardInterrupt old_signal_handler = signal.signal(signal.SIGALRM, sigalarm) signal.alarm(1) raised = False try: # Will be interrupted by a KeyboardInterrupt. next(db.foo.find({"$where": where})) except KeyboardInterrupt: raised = True # Can't use self.assertRaises() because it doesn't catch system # exceptions self.assertTrue(raised, "Didn't raise expected KeyboardInterrupt") # Raises AssertionError due to PYTHON-294 -- Mongo's response to # the previous find() is still waiting to be read on the socket, # so the request id's don't match. self.assertEqual({"_id": 1}, next(db.foo.find())) finally: if old_signal_handler: signal.signal(signal.SIGALRM, old_signal_handler) def test_operation_failure(self): # Ensure MongoClient doesn't close socket after it gets an error # response to getLastError. PYTHON-395. We need a new client here # to avoid race conditions caused by replica set failover or idle # socket reaping. client = single_client() self.addCleanup(client.close) client.pymongo_test.test.find_one() pool = get_pool(client) socket_count = len(pool.conns) self.assertGreaterEqual(socket_count, 1) old_conn = next(iter(pool.conns)) client.pymongo_test.test.drop() client.pymongo_test.test.insert_one({"_id": "foo"}) self.assertRaises(OperationFailure, client.pymongo_test.test.insert_one, {"_id": "foo"}) self.assertEqual(socket_count, len(pool.conns)) new_con = next(iter(pool.conns)) self.assertEqual(old_conn, new_con) def test_lazy_connect_w0(self): # Ensure that connect-on-demand works when the first operation is # an unacknowledged write. This exercises _writable_max_wire_version(). # Use a separate collection to avoid races where we're still # completing an operation on a collection while the next test begins. client_context.client.drop_database("test_lazy_connect_w0") self.addCleanup(client_context.client.drop_database, "test_lazy_connect_w0") client = rs_or_single_client(connect=False, w=0) self.addCleanup(client.close) client.test_lazy_connect_w0.test.insert_one({}) wait_until( lambda: client.test_lazy_connect_w0.test.count_documents({}) == 1, "find one document" ) client = rs_or_single_client(connect=False, w=0) self.addCleanup(client.close) client.test_lazy_connect_w0.test.update_one({}, {"$set": {"x": 1}}) wait_until( lambda: client.test_lazy_connect_w0.test.find_one().get("x") == 1, "update one document" ) client = rs_or_single_client(connect=False, w=0) self.addCleanup(client.close) client.test_lazy_connect_w0.test.delete_one({}) wait_until( lambda: client.test_lazy_connect_w0.test.count_documents({}) == 0, "delete one document" ) @client_context.require_no_mongos def test_exhaust_network_error(self): # When doing an exhaust query, the socket stays checked out on success # but must be checked in on error to avoid semaphore leaks. client = rs_or_single_client(maxPoolSize=1, retryReads=False) self.addCleanup(client.close) collection = client.pymongo_test.test pool = get_pool(client) pool._check_interval_seconds = None # Never check. # Ensure a socket. connected(client) # Cause a network error. conn = one(pool.conns) conn.conn.close() cursor = collection.find(cursor_type=CursorType.EXHAUST) with self.assertRaises(ConnectionFailure): next(cursor) self.assertTrue(conn.closed) # The semaphore was decremented despite the error. self.assertEqual(0, pool.requests) @client_context.require_auth def test_auth_network_error(self): # Make sure there's no semaphore leak if we get a network error # when authenticating a new socket with cached credentials. # Get a client with one socket so we detect if it's leaked. c = connected(rs_or_single_client(maxPoolSize=1, waitQueueTimeoutMS=1, retryReads=False)) # Cause a network error on the actual socket. pool = get_pool(c) socket_info = one(pool.conns) socket_info.conn.close() # Connection.authenticate logs, but gets a socket.error. Should be # reraised as AutoReconnect. self.assertRaises(AutoReconnect, c.test.collection.find_one) # No semaphore leak, the pool is allowed to make a new socket. c.test.collection.find_one() @client_context.require_no_replica_set def test_connect_to_standalone_using_replica_set_name(self): client = single_client(replicaSet="anything", serverSelectionTimeoutMS=100) with self.assertRaises(AutoReconnect): client.test.test.find_one() @client_context.require_replica_set def test_stale_getmore(self): # A cursor is created, but its member goes down and is removed from # the topology before the getMore message is sent. Test that # MongoClient._run_operation_with_response handles the error. with self.assertRaises(AutoReconnect): client = rs_client(connect=False, serverSelectionTimeoutMS=100) client._run_operation( operation=message._GetMore( "pymongo_test", "collection", 101, 1234, client.codec_options, ReadPreference.PRIMARY, None, client, None, None, False, None, ), unpack_res=Cursor(client.pymongo_test.collection)._unpack_response, address=("not-a-member", 27017), ) def test_heartbeat_frequency_ms(self): class HeartbeatStartedListener(ServerHeartbeatListener): def __init__(self): self.results = [] def started(self, event): self.results.append(event) def succeeded(self, event): pass def failed(self, event): pass old_init = ServerHeartbeatStartedEvent.__init__ heartbeat_times = [] def init(self, *args): old_init(self, *args) heartbeat_times.append(time.time()) try: ServerHeartbeatStartedEvent.__init__ = init # type: ignore listener = HeartbeatStartedListener() uri = "mongodb://%s:%d/?heartbeatFrequencyMS=500" % ( client_context.host, client_context.port, ) client = single_client(uri, event_listeners=[listener]) wait_until( lambda: len(listener.results) >= 2, "record two ServerHeartbeatStartedEvents" ) # Default heartbeatFrequencyMS is 10 sec. Check the interval was # closer to 0.5 sec with heartbeatFrequencyMS configured. self.assertAlmostEqual(heartbeat_times[1] - heartbeat_times[0], 0.5, delta=2) client.close() finally: ServerHeartbeatStartedEvent.__init__ = old_init # type: ignore def test_small_heartbeat_frequency_ms(self): uri = "mongodb://example/?heartbeatFrequencyMS=499" with self.assertRaises(ConfigurationError) as context: MongoClient(uri) self.assertIn("heartbeatFrequencyMS", str(context.exception)) def test_compression(self): def compression_settings(client): pool_options = client._MongoClient__options.pool_options return pool_options._compression_settings uri = "mongodb://localhost:27017/?compressors=zlib" client = MongoClient(uri, connect=False) opts = compression_settings(client) self.assertEqual(opts.compressors, ["zlib"]) uri = "mongodb://localhost:27017/?compressors=zlib&zlibCompressionLevel=4" client = MongoClient(uri, connect=False) opts = compression_settings(client) self.assertEqual(opts.compressors, ["zlib"]) self.assertEqual(opts.zlib_compression_level, 4) uri = "mongodb://localhost:27017/?compressors=zlib&zlibCompressionLevel=-1" client = MongoClient(uri, connect=False) opts = compression_settings(client) self.assertEqual(opts.compressors, ["zlib"]) self.assertEqual(opts.zlib_compression_level, -1) uri = "mongodb://localhost:27017" client = MongoClient(uri, connect=False) opts = compression_settings(client) self.assertEqual(opts.compressors, []) self.assertEqual(opts.zlib_compression_level, -1) uri = "mongodb://localhost:27017/?compressors=foobar" client = MongoClient(uri, connect=False) opts = compression_settings(client) self.assertEqual(opts.compressors, []) self.assertEqual(opts.zlib_compression_level, -1) uri = "mongodb://localhost:27017/?compressors=foobar,zlib" client = MongoClient(uri, connect=False) opts = compression_settings(client) self.assertEqual(opts.compressors, ["zlib"]) self.assertEqual(opts.zlib_compression_level, -1) # According to the connection string spec, unsupported values # just raise a warning and are ignored. uri = "mongodb://localhost:27017/?compressors=zlib&zlibCompressionLevel=10" client = MongoClient(uri, connect=False) opts = compression_settings(client) self.assertEqual(opts.compressors, ["zlib"]) self.assertEqual(opts.zlib_compression_level, -1) uri = "mongodb://localhost:27017/?compressors=zlib&zlibCompressionLevel=-2" client = MongoClient(uri, connect=False) opts = compression_settings(client) self.assertEqual(opts.compressors, ["zlib"]) self.assertEqual(opts.zlib_compression_level, -1) if not _have_snappy(): uri = "mongodb://localhost:27017/?compressors=snappy" client = MongoClient(uri, connect=False) opts = compression_settings(client) self.assertEqual(opts.compressors, []) else: uri = "mongodb://localhost:27017/?compressors=snappy" client = MongoClient(uri, connect=False) opts = compression_settings(client) self.assertEqual(opts.compressors, ["snappy"]) uri = "mongodb://localhost:27017/?compressors=snappy,zlib" client = MongoClient(uri, connect=False) opts = compression_settings(client) self.assertEqual(opts.compressors, ["snappy", "zlib"]) if not _have_zstd(): uri = "mongodb://localhost:27017/?compressors=zstd" client = MongoClient(uri, connect=False) opts = compression_settings(client) self.assertEqual(opts.compressors, []) else: uri = "mongodb://localhost:27017/?compressors=zstd" client = MongoClient(uri, connect=False) opts = compression_settings(client) self.assertEqual(opts.compressors, ["zstd"]) uri = "mongodb://localhost:27017/?compressors=zstd,zlib" client = MongoClient(uri, connect=False) opts = compression_settings(client) self.assertEqual(opts.compressors, ["zstd", "zlib"]) options = client_context.default_client_options if "compressors" in options and "zlib" in options["compressors"]: for level in range(-1, 10): client = single_client(zlibcompressionlevel=level) # No error client.pymongo_test.test.find_one() def test_reset_during_update_pool(self): client = rs_or_single_client(minPoolSize=10) self.addCleanup(client.close) client.admin.command("ping") pool = get_pool(client) generation = pool.gen.get_overall() # Continuously reset the pool. class ResetPoolThread(threading.Thread): def __init__(self, pool): super().__init__() self.running = True self.pool = pool def stop(self): self.running = False def run(self): while self.running: exc = AutoReconnect("mock pool error") ctx = _ErrorContext(exc, 0, pool.gen.get_overall(), False, None) client._topology.handle_error(pool.address, ctx) time.sleep(0.001) t = ResetPoolThread(pool) t.start() # Ensure that update_pool completes without error even when the pool # is reset concurrently. try: while True: for _ in range(10): client._topology.update_pool() if generation != pool.gen.get_overall(): break finally: t.stop() t.join() client.admin.command("ping") def test_background_connections_do_not_hold_locks(self): min_pool_size = 10 client = rs_or_single_client( serverSelectionTimeoutMS=3000, minPoolSize=min_pool_size, connect=False ) self.addCleanup(client.close) # Create a single connection in the pool. client.admin.command("ping") # Cause new connections stall for a few seconds. pool = get_pool(client) original_connect = pool.connect def stall_connect(*args, **kwargs): time.sleep(2) return original_connect(*args, **kwargs) pool.connect = stall_connect # Un-patch Pool.connect to break the cyclic reference. self.addCleanup(delattr, pool, "connect") # Wait for the background thread to start creating connections wait_until(lambda: len(pool.conns) > 1, "start creating connections") # Assert that application operations do not block. for _ in range(10): start = time.monotonic() client.admin.command("ping") total = time.monotonic() - start # Each ping command should not take more than 2 seconds self.assertLess(total, 2) @client_context.require_replica_set def test_direct_connection(self): # direct_connection=True should result in Single topology. client = rs_or_single_client(directConnection=True) client.admin.command("ping") self.assertEqual(len(client.nodes), 1) self.assertEqual(client._topology_settings.get_topology_type(), TOPOLOGY_TYPE.Single) client.close() # direct_connection=False should result in RS topology. client = rs_or_single_client(directConnection=False) client.admin.command("ping") self.assertGreaterEqual(len(client.nodes), 1) self.assertIn( client._topology_settings.get_topology_type(), [TOPOLOGY_TYPE.ReplicaSetNoPrimary, TOPOLOGY_TYPE.ReplicaSetWithPrimary], ) client.close() # directConnection=True, should error with multiple hosts as a list. with self.assertRaises(ConfigurationError): MongoClient(["host1", "host2"], directConnection=True) @unittest.skipIf("PyPy" in sys.version, "PYTHON-2927 fails often on PyPy") def test_continuous_network_errors(self): def server_description_count(): i = 0 for obj in gc.get_objects(): try: if isinstance(obj, ServerDescription): i += 1 except ReferenceError: pass return i gc.collect() with client_knobs(min_heartbeat_interval=0.003): client = MongoClient( "invalid:27017", heartbeatFrequencyMS=3, serverSelectionTimeoutMS=150 ) initial_count = server_description_count() self.addCleanup(client.close) with self.assertRaises(ServerSelectionTimeoutError): client.test.test.find_one() gc.collect() final_count = server_description_count() # If a bug like PYTHON-2433 is reintroduced then too many # ServerDescriptions will be kept alive and this test will fail: # AssertionError: 19 != 46 within 15 delta (27 difference) # On Python 3.11 we seem to get more of a delta. self.assertAlmostEqual(initial_count, final_count, delta=20) @client_context.require_failCommand_fail_point def test_network_error_message(self): client = single_client(retryReads=False) self.addCleanup(client.close) client.admin.command("ping") # connect with self.fail_point( {"mode": {"times": 1}, "data": {"closeConnection": True, "failCommands": ["find"]}} ): assert client.address is not None expected = "{}:{}: ".format(*client.address) with self.assertRaisesRegex(AutoReconnect, expected): client.pymongo_test.test.find_one({}) @unittest.skipIf("PyPy" in sys.version, "PYTHON-2938 could fail on PyPy") def test_process_periodic_tasks(self): client = rs_or_single_client() coll = client.db.collection coll.insert_many([{} for _ in range(5)]) cursor = coll.find(batch_size=2) cursor.next() c_id = cursor.cursor_id self.assertIsNotNone(c_id) client.close() # Add cursor to kill cursors queue del cursor wait_until( lambda: client._MongoClient__kill_cursors_queue, "waited for cursor to be added to queue", ) client._process_periodic_tasks() # This must not raise or print any exceptions with self.assertRaises(InvalidOperation): coll.insert_many([{} for _ in range(5)]) def test_service_name_from_kwargs(self): client = MongoClient( "mongodb+srv://user:password@test22.test.build.10gen.cc", srvServiceName="customname", connect=False, ) self.assertEqual(client._topology_settings.srv_service_name, "customname") client = MongoClient( "mongodb+srv://user:password@test22.test.build.10gen.cc" "/?srvServiceName=shouldbeoverriden", srvServiceName="customname", connect=False, ) self.assertEqual(client._topology_settings.srv_service_name, "customname") client = MongoClient( "mongodb+srv://user:password@test22.test.build.10gen.cc/?srvServiceName=customname", connect=False, ) self.assertEqual(client._topology_settings.srv_service_name, "customname") def test_srv_max_hosts_kwarg(self): client = MongoClient("mongodb+srv://test1.test.build.10gen.cc/") self.assertGreater(len(client.topology_description.server_descriptions()), 1) client = MongoClient("mongodb+srv://test1.test.build.10gen.cc/", srvmaxhosts=1) self.assertEqual(len(client.topology_description.server_descriptions()), 1) client = MongoClient( "mongodb+srv://test1.test.build.10gen.cc/?srvMaxHosts=1", srvmaxhosts=2 ) self.assertEqual(len(client.topology_description.server_descriptions()), 2) @unittest.skipIf( client_context.load_balancer or client_context.serverless, "loadBalanced clients do not run SDAM", ) @unittest.skipIf(sys.platform == "win32", "Windows does not support SIGSTOP") def test_sigstop_sigcont(self): test_dir = os.path.dirname(os.path.realpath(__file__)) script = os.path.join(test_dir, "sigstop_sigcont.py") p = subprocess.Popen( [sys.executable, script, client_context.uri], stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, ) self.addCleanup(p.wait, timeout=1) self.addCleanup(p.kill) time.sleep(1) # Stop the child, sleep for twice the streaming timeout # (heartbeatFrequencyMS + connectTimeoutMS), and restart. os.kill(p.pid, signal.SIGSTOP) time.sleep(2) os.kill(p.pid, signal.SIGCONT) time.sleep(0.5) # Tell the script to exit gracefully. outs, _ = p.communicate(input=b"q\n", timeout=10) self.assertTrue(outs) log_output = outs.decode("utf-8") self.assertIn("TEST STARTED", log_output) self.assertIn("ServerHeartbeatStartedEvent", log_output) self.assertIn("ServerHeartbeatSucceededEvent", log_output) self.assertIn("TEST COMPLETED", log_output) self.assertNotIn("ServerHeartbeatFailedEvent", log_output) def _test_handshake(self, env_vars, expected_env): with patch.dict("os.environ", env_vars): metadata = copy.deepcopy(_METADATA) if expected_env is not None: metadata["env"] = expected_env if "AWS_REGION" not in env_vars: os.environ["AWS_REGION"] = "" with rs_or_single_client(serverSelectionTimeoutMS=10000) as client: client.admin.command("ping") options = client._MongoClient__options self.assertEqual(options.pool_options.metadata, metadata) def test_handshake_01_aws(self): self._test_handshake( { "AWS_EXECUTION_ENV": "AWS_Lambda_python3.9", "AWS_REGION": "us-east-2", "AWS_LAMBDA_FUNCTION_MEMORY_SIZE": "1024", }, {"name": "aws.lambda", "region": "us-east-2", "memory_mb": 1024}, ) def test_handshake_02_azure(self): self._test_handshake({"FUNCTIONS_WORKER_RUNTIME": "python"}, {"name": "azure.func"}) def test_handshake_03_gcp(self): self._test_handshake( { "K_SERVICE": "servicename", "FUNCTION_MEMORY_MB": "1024", "FUNCTION_TIMEOUT_SEC": "60", "FUNCTION_REGION": "us-central1", }, {"name": "gcp.func", "region": "us-central1", "memory_mb": 1024, "timeout_sec": 60}, ) # Extra case for FUNCTION_NAME. self._test_handshake( { "FUNCTION_NAME": "funcname", "FUNCTION_MEMORY_MB": "1024", "FUNCTION_TIMEOUT_SEC": "60", "FUNCTION_REGION": "us-central1", }, {"name": "gcp.func", "region": "us-central1", "memory_mb": 1024, "timeout_sec": 60}, ) def test_handshake_04_vercel(self): self._test_handshake( {"VERCEL": "1", "VERCEL_REGION": "cdg1"}, {"name": "vercel", "region": "cdg1"} ) def test_handshake_05_multiple(self): self._test_handshake( {"AWS_EXECUTION_ENV": "AWS_Lambda_python3.9", "FUNCTIONS_WORKER_RUNTIME": "python"}, None, ) # Extra cases for other combos. self._test_handshake( {"FUNCTIONS_WORKER_RUNTIME": "python", "K_SERVICE": "servicename"}, None, ) self._test_handshake({"K_SERVICE": "servicename", "VERCEL": "1"}, None) def test_handshake_06_region_too_long(self): self._test_handshake( {"AWS_EXECUTION_ENV": "AWS_Lambda_python3.9", "AWS_REGION": "a" * 512}, {"name": "aws.lambda"}, ) def test_handshake_07_memory_invalid_int(self): self._test_handshake( {"AWS_EXECUTION_ENV": "AWS_Lambda_python3.9", "AWS_LAMBDA_FUNCTION_MEMORY_SIZE": "big"}, {"name": "aws.lambda"}, ) def test_handshake_08_invalid_aws_ec2(self): # AWS_EXECUTION_ENV needs to start with "AWS_Lambda_". self._test_handshake( {"AWS_EXECUTION_ENV": "EC2"}, None, ) def test_dict_hints(self): self.db.t.find(hint={"x": 1}) def test_dict_hints_sort(self): result = self.db.t.find() result.sort({"x": 1}) self.db.t.find(sort={"x": 1}) def test_dict_hints_create_index(self): self.db.t.create_index({"x": pymongo.ASCENDING}) class TestExhaustCursor(IntegrationTest): """Test that clients properly handle errors from exhaust cursors.""" def setUp(self): super().setUp() if client_context.is_mongos: raise SkipTest("mongos doesn't support exhaust, SERVER-2627") def test_exhaust_query_server_error(self): # When doing an exhaust query, the socket stays checked out on success # but must be checked in on error to avoid semaphore leaks. client = connected(rs_or_single_client(maxPoolSize=1)) collection = client.pymongo_test.test pool = get_pool(client) conn = one(pool.conns) # This will cause OperationFailure in all mongo versions since # the value for $orderby must be a document. cursor = collection.find( SON([("$query", {}), ("$orderby", True)]), cursor_type=CursorType.EXHAUST ) self.assertRaises(OperationFailure, cursor.next) self.assertFalse(conn.closed) # The socket was checked in and the semaphore was decremented. self.assertIn(conn, pool.conns) self.assertEqual(0, pool.requests) def test_exhaust_getmore_server_error(self): # When doing a getmore on an exhaust cursor, the socket stays checked # out on success but it's checked in on error to avoid semaphore leaks. client = rs_or_single_client(maxPoolSize=1) collection = client.pymongo_test.test collection.drop() collection.insert_many([{} for _ in range(200)]) self.addCleanup(client_context.client.pymongo_test.test.drop) pool = get_pool(client) pool._check_interval_seconds = None # Never check. conn = one(pool.conns) cursor = collection.find(cursor_type=CursorType.EXHAUST) # Initial query succeeds. cursor.next() # Cause a server error on getmore. def receive_message(request_id): # Discard the actual server response. Connection.receive_message(conn, request_id) # responseFlags bit 1 is QueryFailure. msg = struct.pack("= results[1]["score"]) db.test.drop_indexes() def test_index_2dsphere(self): db = self.db db.test.drop_indexes() self.assertEqual("geo_2dsphere", db.test.create_index([("geo", GEOSPHERE)])) for dummy, info in db.test.index_information().items(): field, idx_type = info["key"][0] if field == "geo" and idx_type == "2dsphere": break else: self.fail("2dsphere index not found.") poly = {"type": "Polygon", "coordinates": [[[40, 5], [40, 6], [41, 6], [41, 5], [40, 5]]]} query = {"geo": {"$within": {"$geometry": poly}}} # This query will error without a 2dsphere index. db.test.find(query) db.test.drop_indexes() def test_index_hashed(self): db = self.db db.test.drop_indexes() self.assertEqual("a_hashed", db.test.create_index([("a", HASHED)])) for dummy, info in db.test.index_information().items(): field, idx_type = info["key"][0] if field == "a" and idx_type == "hashed": break else: self.fail("hashed index not found.") db.test.drop_indexes() def test_index_sparse(self): db = self.db db.test.drop_indexes() db.test.create_index([("key", ASCENDING)], sparse=True) self.assertTrue(db.test.index_information()["key_1"]["sparse"]) def test_index_background(self): db = self.db db.test.drop_indexes() db.test.create_index([("keya", ASCENDING)]) db.test.create_index([("keyb", ASCENDING)], background=False) db.test.create_index([("keyc", ASCENDING)], background=True) self.assertFalse("background" in db.test.index_information()["keya_1"]) self.assertFalse(db.test.index_information()["keyb_1"]["background"]) self.assertTrue(db.test.index_information()["keyc_1"]["background"]) def _drop_dups_setup(self, db): db.drop_collection("test") db.test.insert_one({"i": 1}) db.test.insert_one({"i": 2}) db.test.insert_one({"i": 2}) # duplicate db.test.insert_one({"i": 3}) def test_index_dont_drop_dups(self): # Try *not* dropping duplicates db = self.db self._drop_dups_setup(db) # There's a duplicate def test_create(): db.test.create_index([("i", ASCENDING)], unique=True, dropDups=False) self.assertRaises(DuplicateKeyError, test_create) # Duplicate wasn't dropped self.assertEqual(4, db.test.count_documents({})) # Index wasn't created, only the default index on _id self.assertEqual(1, len(db.test.index_information())) # Get the plan dynamically because the explain format will change. def get_plan_stage(self, root, stage): if root.get("stage") == stage: return root elif "inputStage" in root: return self.get_plan_stage(root["inputStage"], stage) elif "inputStages" in root: for i in root["inputStages"]: stage = self.get_plan_stage(i, stage) if stage: return stage elif "queryPlan" in root: # queryPlan (and slotBasedPlan) are new in 5.0. return self.get_plan_stage(root["queryPlan"], stage) elif "shards" in root: for i in root["shards"]: stage = self.get_plan_stage(i["winningPlan"], stage) if stage: return stage return {} def test_index_filter(self): db = self.db db.drop_collection("test") # Test bad filter spec on create. self.assertRaises(OperationFailure, db.test.create_index, "x", partialFilterExpression=5) self.assertRaises( OperationFailure, db.test.create_index, "x", partialFilterExpression={"x": {"$asdasd": 3}}, ) self.assertRaises( OperationFailure, db.test.create_index, "x", partialFilterExpression={"$and": 5} ) self.assertEqual( "x_1", db.test.create_index([("x", ASCENDING)], partialFilterExpression={"a": {"$lte": 1.5}}), ) db.test.insert_one({"x": 5, "a": 2}) db.test.insert_one({"x": 6, "a": 1}) # Operations that use the partial index. explain = db.test.find({"x": 6, "a": 1}).explain() stage = self.get_plan_stage(explain["queryPlanner"]["winningPlan"], "IXSCAN") self.assertEqual("x_1", stage.get("indexName")) self.assertTrue(stage.get("isPartial")) explain = db.test.find({"x": {"$gt": 1}, "a": 1}).explain() stage = self.get_plan_stage(explain["queryPlanner"]["winningPlan"], "IXSCAN") self.assertEqual("x_1", stage.get("indexName")) self.assertTrue(stage.get("isPartial")) explain = db.test.find({"x": 6, "a": {"$lte": 1}}).explain() stage = self.get_plan_stage(explain["queryPlanner"]["winningPlan"], "IXSCAN") self.assertEqual("x_1", stage.get("indexName")) self.assertTrue(stage.get("isPartial")) # Operations that do not use the partial index. explain = db.test.find({"x": 6, "a": {"$lte": 1.6}}).explain() stage = self.get_plan_stage(explain["queryPlanner"]["winningPlan"], "COLLSCAN") self.assertNotEqual({}, stage) explain = db.test.find({"x": 6}).explain() stage = self.get_plan_stage(explain["queryPlanner"]["winningPlan"], "COLLSCAN") self.assertNotEqual({}, stage) # Test drop_indexes. db.test.drop_index("x_1") explain = db.test.find({"x": 6, "a": 1}).explain() stage = self.get_plan_stage(explain["queryPlanner"]["winningPlan"], "COLLSCAN") self.assertNotEqual({}, stage) def test_field_selection(self): db = self.db db.drop_collection("test") doc = {"a": 1, "b": 5, "c": {"d": 5, "e": 10}} db.test.insert_one(doc) # Test field inclusion doc = next(db.test.find({}, ["_id"])) self.assertEqual(list(doc), ["_id"]) doc = next(db.test.find({}, ["a"])) l = list(doc) l.sort() self.assertEqual(l, ["_id", "a"]) doc = next(db.test.find({}, ["b"])) l = list(doc) l.sort() self.assertEqual(l, ["_id", "b"]) doc = next(db.test.find({}, ["c"])) l = list(doc) l.sort() self.assertEqual(l, ["_id", "c"]) doc = next(db.test.find({}, ["a"])) self.assertEqual(doc["a"], 1) doc = next(db.test.find({}, ["b"])) self.assertEqual(doc["b"], 5) doc = next(db.test.find({}, ["c"])) self.assertEqual(doc["c"], {"d": 5, "e": 10}) # Test inclusion of fields with dots doc = next(db.test.find({}, ["c.d"])) self.assertEqual(doc["c"], {"d": 5}) doc = next(db.test.find({}, ["c.e"])) self.assertEqual(doc["c"], {"e": 10}) doc = next(db.test.find({}, ["b", "c.e"])) self.assertEqual(doc["c"], {"e": 10}) doc = next(db.test.find({}, ["b", "c.e"])) l = list(doc) l.sort() self.assertEqual(l, ["_id", "b", "c"]) doc = next(db.test.find({}, ["b", "c.e"])) self.assertEqual(doc["b"], 5) # Test field exclusion doc = next(db.test.find({}, {"a": False, "b": 0})) l = list(doc) l.sort() self.assertEqual(l, ["_id", "c"]) doc = next(db.test.find({}, {"_id": False})) l = list(doc) self.assertFalse("_id" in l) def test_options(self): db = self.db db.drop_collection("test") db.create_collection("test", capped=True, size=4096) result = db.test.options() self.assertEqual(result, {"capped": True, "size": 4096}) db.drop_collection("test") def test_insert_one(self): db = self.db db.test.drop() document: dict[str, Any] = {"_id": 1000} result = db.test.insert_one(document) self.assertTrue(isinstance(result, InsertOneResult)) self.assertTrue(isinstance(result.inserted_id, int)) self.assertEqual(document["_id"], result.inserted_id) self.assertTrue(result.acknowledged) self.assertIsNotNone(db.test.find_one({"_id": document["_id"]})) self.assertEqual(1, db.test.count_documents({})) document = {"foo": "bar"} result = db.test.insert_one(document) self.assertTrue(isinstance(result, InsertOneResult)) self.assertTrue(isinstance(result.inserted_id, ObjectId)) self.assertEqual(document["_id"], result.inserted_id) self.assertTrue(result.acknowledged) self.assertIsNotNone(db.test.find_one({"_id": document["_id"]})) self.assertEqual(2, db.test.count_documents({})) db = db.client.get_database(db.name, write_concern=WriteConcern(w=0)) result = db.test.insert_one(document) self.assertTrue(isinstance(result, InsertOneResult)) self.assertTrue(isinstance(result.inserted_id, ObjectId)) self.assertEqual(document["_id"], result.inserted_id) self.assertFalse(result.acknowledged) # The insert failed duplicate key... wait_until(lambda: db.test.count_documents({}) == 2, "forcing duplicate key error") document = RawBSONDocument(encode({"_id": ObjectId(), "foo": "bar"})) result = db.test.insert_one(document) self.assertTrue(isinstance(result, InsertOneResult)) self.assertEqual(result.inserted_id, None) def test_insert_many(self): db = self.db db.test.drop() docs: list = [{} for _ in range(5)] result = db.test.insert_many(docs) self.assertTrue(isinstance(result, InsertManyResult)) self.assertTrue(isinstance(result.inserted_ids, list)) self.assertEqual(5, len(result.inserted_ids)) for doc in docs: _id = doc["_id"] self.assertTrue(isinstance(_id, ObjectId)) self.assertTrue(_id in result.inserted_ids) self.assertEqual(1, db.test.count_documents({"_id": _id})) self.assertTrue(result.acknowledged) docs = [{"_id": i} for i in range(5)] result = db.test.insert_many(docs) self.assertTrue(isinstance(result, InsertManyResult)) self.assertTrue(isinstance(result.inserted_ids, list)) self.assertEqual(5, len(result.inserted_ids)) for doc in docs: _id = doc["_id"] self.assertTrue(isinstance(_id, int)) self.assertTrue(_id in result.inserted_ids) self.assertEqual(1, db.test.count_documents({"_id": _id})) self.assertTrue(result.acknowledged) docs = [RawBSONDocument(encode({"_id": i + 5})) for i in range(5)] result = db.test.insert_many(docs) self.assertTrue(isinstance(result, InsertManyResult)) self.assertTrue(isinstance(result.inserted_ids, list)) self.assertEqual([], result.inserted_ids) db = db.client.get_database(db.name, write_concern=WriteConcern(w=0)) docs: list = [{} for _ in range(5)] result = db.test.insert_many(docs) self.assertTrue(isinstance(result, InsertManyResult)) self.assertFalse(result.acknowledged) self.assertEqual(20, db.test.count_documents({})) def test_insert_many_generator(self): coll = self.db.test coll.delete_many({}) def gen(): yield {"a": 1, "b": 1} yield {"a": 1, "b": 2} yield {"a": 2, "b": 3} yield {"a": 3, "b": 5} yield {"a": 5, "b": 8} result = coll.insert_many(gen()) self.assertEqual(5, len(result.inserted_ids)) def test_insert_many_invalid(self): db = self.db with self.assertRaisesRegex(TypeError, "documents must be a non-empty list"): db.test.insert_many({}) with self.assertRaisesRegex(TypeError, "documents must be a non-empty list"): db.test.insert_many([]) with self.assertRaisesRegex(TypeError, "documents must be a non-empty list"): db.test.insert_many(1) # type: ignore[arg-type] with self.assertRaisesRegex(TypeError, "documents must be a non-empty list"): db.test.insert_many(RawBSONDocument(encode({"_id": 2}))) def test_delete_one(self): self.db.test.drop() self.db.test.insert_one({"x": 1}) self.db.test.insert_one({"y": 1}) self.db.test.insert_one({"z": 1}) result = self.db.test.delete_one({"x": 1}) self.assertTrue(isinstance(result, DeleteResult)) self.assertEqual(1, result.deleted_count) self.assertTrue(result.acknowledged) self.assertEqual(2, self.db.test.count_documents({})) result = self.db.test.delete_one({"y": 1}) self.assertTrue(isinstance(result, DeleteResult)) self.assertEqual(1, result.deleted_count) self.assertTrue(result.acknowledged) self.assertEqual(1, self.db.test.count_documents({})) db = self.db.client.get_database(self.db.name, write_concern=WriteConcern(w=0)) result = db.test.delete_one({"z": 1}) self.assertTrue(isinstance(result, DeleteResult)) self.assertRaises(InvalidOperation, lambda: result.deleted_count) self.assertFalse(result.acknowledged) wait_until(lambda: db.test.count_documents({}) == 0, "delete 1 documents") def test_delete_many(self): self.db.test.drop() self.db.test.insert_one({"x": 1}) self.db.test.insert_one({"x": 1}) self.db.test.insert_one({"y": 1}) self.db.test.insert_one({"y": 1}) result = self.db.test.delete_many({"x": 1}) self.assertTrue(isinstance(result, DeleteResult)) self.assertEqual(2, result.deleted_count) self.assertTrue(result.acknowledged) self.assertEqual(0, self.db.test.count_documents({"x": 1})) db = self.db.client.get_database(self.db.name, write_concern=WriteConcern(w=0)) result = db.test.delete_many({"y": 1}) self.assertTrue(isinstance(result, DeleteResult)) self.assertRaises(InvalidOperation, lambda: result.deleted_count) self.assertFalse(result.acknowledged) wait_until(lambda: db.test.count_documents({}) == 0, "delete 2 documents") def test_command_document_too_large(self): large = "*" * (client_context.max_bson_size + _COMMAND_OVERHEAD) coll = self.db.test self.assertRaises(DocumentTooLarge, coll.insert_one, {"data": large}) # update_one and update_many are the same self.assertRaises(DocumentTooLarge, coll.replace_one, {}, {"data": large}) self.assertRaises(DocumentTooLarge, coll.delete_one, {"data": large}) def test_write_large_document(self): max_size = client_context.max_bson_size half_size = int(max_size / 2) max_str = "x" * max_size half_str = "x" * half_size self.assertEqual(max_size, 16777216) self.assertRaises(OperationFailure, self.db.test.insert_one, {"foo": max_str}) self.assertRaises( OperationFailure, self.db.test.replace_one, {}, {"foo": max_str}, upsert=True ) self.assertRaises(OperationFailure, self.db.test.insert_many, [{"x": 1}, {"foo": max_str}]) self.db.test.insert_many([{"foo": half_str}, {"foo": half_str}]) self.db.test.insert_one({"bar": "x"}) # Use w=0 here to test legacy doc size checking in all server versions unack_coll = self.db.test.with_options(write_concern=WriteConcern(w=0)) self.assertRaises( DocumentTooLarge, unack_coll.replace_one, {"bar": "x"}, {"bar": "x" * (max_size - 14)} ) self.db.test.replace_one({"bar": "x"}, {"bar": "x" * (max_size - 32)}) def test_insert_bypass_document_validation(self): db = self.db db.test.drop() db.create_collection("test", validator={"a": {"$exists": True}}) db_w0 = self.db.client.get_database(self.db.name, write_concern=WriteConcern(w=0)) # Test insert_one self.assertRaises(OperationFailure, db.test.insert_one, {"_id": 1, "x": 100}) result = db.test.insert_one({"_id": 1, "x": 100}, bypass_document_validation=True) self.assertTrue(isinstance(result, InsertOneResult)) self.assertEqual(1, result.inserted_id) result = db.test.insert_one({"_id": 2, "a": 0}) self.assertTrue(isinstance(result, InsertOneResult)) self.assertEqual(2, result.inserted_id) db_w0.test.insert_one({"y": 1}, bypass_document_validation=True) wait_until(lambda: db_w0.test.find_one({"y": 1}), "find w:0 inserted document") # Test insert_many docs = [{"_id": i, "x": 100 - i} for i in range(3, 100)] self.assertRaises(OperationFailure, db.test.insert_many, docs) result = db.test.insert_many(docs, bypass_document_validation=True) self.assertTrue(isinstance(result, InsertManyResult)) self.assertTrue(97, len(result.inserted_ids)) for doc in docs: _id = doc["_id"] self.assertTrue(isinstance(_id, int)) self.assertTrue(_id in result.inserted_ids) self.assertEqual(1, db.test.count_documents({"x": doc["x"]})) self.assertTrue(result.acknowledged) docs = [{"_id": i, "a": 200 - i} for i in range(100, 200)] result = db.test.insert_many(docs) self.assertTrue(isinstance(result, InsertManyResult)) self.assertTrue(97, len(result.inserted_ids)) for doc in docs: _id = doc["_id"] self.assertTrue(isinstance(_id, int)) self.assertTrue(_id in result.inserted_ids) self.assertEqual(1, db.test.count_documents({"a": doc["a"]})) self.assertTrue(result.acknowledged) self.assertRaises( OperationFailure, db_w0.test.insert_many, [{"x": 1}, {"x": 2}], bypass_document_validation=True, ) def test_replace_bypass_document_validation(self): db = self.db db.test.drop() db.create_collection("test", validator={"a": {"$exists": True}}) db_w0 = self.db.client.get_database(self.db.name, write_concern=WriteConcern(w=0)) # Test replace_one db.test.insert_one({"a": 101}) self.assertRaises(OperationFailure, db.test.replace_one, {"a": 101}, {"y": 1}) self.assertEqual(0, db.test.count_documents({"y": 1})) self.assertEqual(1, db.test.count_documents({"a": 101})) db.test.replace_one({"a": 101}, {"y": 1}, bypass_document_validation=True) self.assertEqual(0, db.test.count_documents({"a": 101})) self.assertEqual(1, db.test.count_documents({"y": 1})) db.test.replace_one({"y": 1}, {"a": 102}) self.assertEqual(0, db.test.count_documents({"y": 1})) self.assertEqual(0, db.test.count_documents({"a": 101})) self.assertEqual(1, db.test.count_documents({"a": 102})) db.test.insert_one({"y": 1}, bypass_document_validation=True) self.assertRaises(OperationFailure, db.test.replace_one, {"y": 1}, {"x": 101}) self.assertEqual(0, db.test.count_documents({"x": 101})) self.assertEqual(1, db.test.count_documents({"y": 1})) db.test.replace_one({"y": 1}, {"x": 101}, bypass_document_validation=True) self.assertEqual(0, db.test.count_documents({"y": 1})) self.assertEqual(1, db.test.count_documents({"x": 101})) db.test.replace_one({"x": 101}, {"a": 103}, bypass_document_validation=False) self.assertEqual(0, db.test.count_documents({"x": 101})) self.assertEqual(1, db.test.count_documents({"a": 103})) db.test.insert_one({"y": 1}, bypass_document_validation=True) db_w0.test.replace_one({"y": 1}, {"x": 1}, bypass_document_validation=True) wait_until(lambda: db_w0.test.find_one({"x": 1}), "find w:0 replaced document") def test_update_bypass_document_validation(self): db = self.db db.test.drop() db.test.insert_one({"z": 5}) db.command(SON([("collMod", "test"), ("validator", {"z": {"$gte": 0}})])) db_w0 = self.db.client.get_database(self.db.name, write_concern=WriteConcern(w=0)) # Test update_one self.assertRaises(OperationFailure, db.test.update_one, {"z": 5}, {"$inc": {"z": -10}}) self.assertEqual(0, db.test.count_documents({"z": -5})) self.assertEqual(1, db.test.count_documents({"z": 5})) db.test.update_one({"z": 5}, {"$inc": {"z": -10}}, bypass_document_validation=True) self.assertEqual(0, db.test.count_documents({"z": 5})) self.assertEqual(1, db.test.count_documents({"z": -5})) db.test.update_one({"z": -5}, {"$inc": {"z": 6}}, bypass_document_validation=False) self.assertEqual(1, db.test.count_documents({"z": 1})) self.assertEqual(0, db.test.count_documents({"z": -5})) db.test.insert_one({"z": -10}, bypass_document_validation=True) self.assertRaises(OperationFailure, db.test.update_one, {"z": -10}, {"$inc": {"z": 1}}) self.assertEqual(0, db.test.count_documents({"z": -9})) self.assertEqual(1, db.test.count_documents({"z": -10})) db.test.update_one({"z": -10}, {"$inc": {"z": 1}}, bypass_document_validation=True) self.assertEqual(1, db.test.count_documents({"z": -9})) self.assertEqual(0, db.test.count_documents({"z": -10})) db.test.update_one({"z": -9}, {"$inc": {"z": 9}}, bypass_document_validation=False) self.assertEqual(0, db.test.count_documents({"z": -9})) self.assertEqual(1, db.test.count_documents({"z": 0})) db.test.insert_one({"y": 1, "x": 0}, bypass_document_validation=True) db_w0.test.update_one({"y": 1}, {"$inc": {"x": 1}}, bypass_document_validation=True) wait_until(lambda: db_w0.test.find_one({"y": 1, "x": 1}), "find w:0 updated document") # Test update_many db.test.insert_many([{"z": i} for i in range(3, 101)]) db.test.insert_one({"y": 0}, bypass_document_validation=True) self.assertRaises(OperationFailure, db.test.update_many, {}, {"$inc": {"z": -100}}) self.assertEqual(100, db.test.count_documents({"z": {"$gte": 0}})) self.assertEqual(0, db.test.count_documents({"z": {"$lt": 0}})) self.assertEqual(0, db.test.count_documents({"y": 0, "z": -100})) db.test.update_many( {"z": {"$gte": 0}}, {"$inc": {"z": -100}}, bypass_document_validation=True ) self.assertEqual(0, db.test.count_documents({"z": {"$gt": 0}})) self.assertEqual(100, db.test.count_documents({"z": {"$lte": 0}})) db.test.update_many( {"z": {"$gt": -50}}, {"$inc": {"z": 100}}, bypass_document_validation=False ) self.assertEqual(50, db.test.count_documents({"z": {"$gt": 0}})) self.assertEqual(50, db.test.count_documents({"z": {"$lt": 0}})) db.test.insert_many([{"z": -i} for i in range(50)], bypass_document_validation=True) self.assertRaises(OperationFailure, db.test.update_many, {}, {"$inc": {"z": 1}}) self.assertEqual(100, db.test.count_documents({"z": {"$lte": 0}})) self.assertEqual(50, db.test.count_documents({"z": {"$gt": 1}})) db.test.update_many( {"z": {"$gte": 0}}, {"$inc": {"z": -100}}, bypass_document_validation=True ) self.assertEqual(0, db.test.count_documents({"z": {"$gt": 0}})) self.assertEqual(150, db.test.count_documents({"z": {"$lte": 0}})) db.test.update_many( {"z": {"$lte": 0}}, {"$inc": {"z": 100}}, bypass_document_validation=False ) self.assertEqual(150, db.test.count_documents({"z": {"$gte": 0}})) self.assertEqual(0, db.test.count_documents({"z": {"$lt": 0}})) db.test.insert_one({"m": 1, "x": 0}, bypass_document_validation=True) db.test.insert_one({"m": 1, "x": 0}, bypass_document_validation=True) db_w0.test.update_many({"m": 1}, {"$inc": {"x": 1}}, bypass_document_validation=True) wait_until( lambda: db_w0.test.count_documents({"m": 1, "x": 1}) == 2, "find w:0 updated documents" ) def test_bypass_document_validation_bulk_write(self): db = self.db db.test.drop() db.create_collection("test", validator={"a": {"$gte": 0}}) db_w0 = self.db.client.get_database(self.db.name, write_concern=WriteConcern(w=0)) ops: list = [ InsertOne({"a": -10}), InsertOne({"a": -11}), InsertOne({"a": -12}), UpdateOne({"a": {"$lte": -10}}, {"$inc": {"a": 1}}), UpdateMany({"a": {"$lte": -10}}, {"$inc": {"a": 1}}), ReplaceOne({"a": {"$lte": -10}}, {"a": -1}), ] db.test.bulk_write(ops, bypass_document_validation=True) self.assertEqual(3, db.test.count_documents({})) self.assertEqual(1, db.test.count_documents({"a": -11})) self.assertEqual(1, db.test.count_documents({"a": -1})) self.assertEqual(1, db.test.count_documents({"a": -9})) # Assert that the operations would fail without bypass_doc_val for op in ops: self.assertRaises(BulkWriteError, db.test.bulk_write, [op]) self.assertRaises( OperationFailure, db_w0.test.bulk_write, ops, bypass_document_validation=True ) def test_find_by_default_dct(self): db = self.db db.test.insert_one({"foo": "bar"}) dct = defaultdict(dict, [("foo", "bar")]) # type: ignore[arg-type] self.assertIsNotNone(db.test.find_one(dct)) self.assertEqual(dct, defaultdict(dict, [("foo", "bar")])) def test_find_w_fields(self): db = self.db db.test.delete_many({}) db.test.insert_one({"x": 1, "mike": "awesome", "extra thing": "abcdefghijklmnopqrstuvwxyz"}) self.assertEqual(1, db.test.count_documents({})) doc = next(db.test.find({})) self.assertTrue("x" in doc) doc = next(db.test.find({})) self.assertTrue("mike" in doc) doc = next(db.test.find({})) self.assertTrue("extra thing" in doc) doc = next(db.test.find({}, ["x", "mike"])) self.assertTrue("x" in doc) doc = next(db.test.find({}, ["x", "mike"])) self.assertTrue("mike" in doc) doc = next(db.test.find({}, ["x", "mike"])) self.assertFalse("extra thing" in doc) doc = next(db.test.find({}, ["mike"])) self.assertFalse("x" in doc) doc = next(db.test.find({}, ["mike"])) self.assertTrue("mike" in doc) doc = next(db.test.find({}, ["mike"])) self.assertFalse("extra thing" in doc) @no_type_check def test_fields_specifier_as_dict(self): db = self.db db.test.delete_many({}) db.test.insert_one({"x": [1, 2, 3], "mike": "awesome"}) self.assertEqual([1, 2, 3], db.test.find_one()["x"]) self.assertEqual([2, 3], db.test.find_one(projection={"x": {"$slice": -2}})["x"]) self.assertTrue("x" not in db.test.find_one(projection={"x": 0})) self.assertTrue("mike" in db.test.find_one(projection={"x": 0})) def test_find_w_regex(self): db = self.db db.test.delete_many({}) db.test.insert_one({"x": "hello_world"}) db.test.insert_one({"x": "hello_mike"}) db.test.insert_one({"x": "hello_mikey"}) db.test.insert_one({"x": "hello_test"}) self.assertEqual(len(list(db.test.find())), 4) self.assertEqual(len(list(db.test.find({"x": re.compile("^hello.*")}))), 4) self.assertEqual(len(list(db.test.find({"x": re.compile("ello")}))), 4) self.assertEqual(len(list(db.test.find({"x": re.compile("^hello$")}))), 0) self.assertEqual(len(list(db.test.find({"x": re.compile("^hello_mi.*$")}))), 2) def test_id_can_be_anything(self): db = self.db db.test.delete_many({}) auto_id = {"hello": "world"} db.test.insert_one(auto_id) self.assertTrue(isinstance(auto_id["_id"], ObjectId)) numeric = {"_id": 240, "hello": "world"} db.test.insert_one(numeric) self.assertEqual(numeric["_id"], 240) obj = {"_id": numeric, "hello": "world"} db.test.insert_one(obj) self.assertEqual(obj["_id"], numeric) for x in db.test.find(): self.assertEqual(x["hello"], "world") self.assertTrue("_id" in x) def test_unique_index(self): db = self.db db.drop_collection("test") db.test.create_index("hello") # No error. db.test.insert_one({"hello": "world"}) db.test.insert_one({"hello": "world"}) db.drop_collection("test") db.test.create_index("hello", unique=True) with self.assertRaises(DuplicateKeyError): db.test.insert_one({"hello": "world"}) db.test.insert_one({"hello": "world"}) def test_duplicate_key_error(self): db = self.db db.drop_collection("test") db.test.create_index("x", unique=True) db.test.insert_one({"_id": 1, "x": 1}) with self.assertRaises(DuplicateKeyError) as context: db.test.insert_one({"x": 1}) self.assertIsNotNone(context.exception.details) with self.assertRaises(DuplicateKeyError) as context: db.test.insert_one({"x": 1}) self.assertIsNotNone(context.exception.details) self.assertEqual(1, db.test.count_documents({})) def test_write_error_text_handling(self): db = self.db db.drop_collection("test") db.test.create_index("text", unique=True) # Test workaround for SERVER-24007 data = ( b"a\xe2\x98\x83\xe2\x98\x83\xe2\x98\x83\xe2\x98\x83" b"\xe2\x98\x83\xe2\x98\x83\xe2\x98\x83\xe2\x98\x83" b"\xe2\x98\x83\xe2\x98\x83\xe2\x98\x83\xe2\x98\x83" b"\xe2\x98\x83\xe2\x98\x83\xe2\x98\x83\xe2\x98\x83" b"\xe2\x98\x83\xe2\x98\x83\xe2\x98\x83\xe2\x98\x83" b"\xe2\x98\x83\xe2\x98\x83\xe2\x98\x83\xe2\x98\x83" b"\xe2\x98\x83\xe2\x98\x83\xe2\x98\x83\xe2\x98\x83" b"\xe2\x98\x83\xe2\x98\x83\xe2\x98\x83\xe2\x98\x83" b"\xe2\x98\x83\xe2\x98\x83\xe2\x98\x83\xe2\x98\x83" b"\xe2\x98\x83\xe2\x98\x83\xe2\x98\x83\xe2\x98\x83" b"\xe2\x98\x83\xe2\x98\x83\xe2\x98\x83\xe2\x98\x83" b"\xe2\x98\x83\xe2\x98\x83\xe2\x98\x83\xe2\x98\x83" b"\xe2\x98\x83\xe2\x98\x83\xe2\x98\x83\xe2\x98\x83" b"\xe2\x98\x83\xe2\x98\x83\xe2\x98\x83\xe2\x98\x83" b"\xe2\x98\x83\xe2\x98\x83\xe2\x98\x83\xe2\x98\x83" b"\xe2\x98\x83\xe2\x98\x83\xe2\x98\x83\xe2\x98\x83" b"\xe2\x98\x83\xe2\x98\x83\xe2\x98\x83\xe2\x98\x83" b"\xe2\x98\x83\xe2\x98\x83\xe2\x98\x83\xe2\x98\x83" b"\xe2\x98\x83\xe2\x98\x83\xe2\x98\x83\xe2\x98\x83" b"\xe2\x98\x83\xe2\x98\x83\xe2\x98\x83\xe2\x98\x83" b"\xe2\x98\x83\xe2\x98\x83\xe2\x98\x83\xe2\x98\x83" b"\xe2\x98\x83\xe2\x98\x83\xe2\x98\x83\xe2\x98\x83" b"\xe2\x98\x83\xe2\x98\x83\xe2\x98\x83\xe2\x98\x83" b"\xe2\x98\x83\xe2\x98\x83\xe2\x98\x83\xe2\x98\x83" b"\xe2\x98\x83\xe2\x98\x83\xe2\x98\x83\xe2\x98\x83" b"\xe2\x98\x83\xe2\x98\x83\xe2\x98\x83\xe2\x98\x83" b"\xe2\x98\x83\xe2\x98\x83\xe2\x98\x83\xe2\x98\x83" b"\xe2\x98\x83\xe2\x98\x83\xe2\x98\x83\xe2\x98\x83" ) text = utf_8_decode(data, None, True) db.test.insert_one({"text": text}) # Should raise DuplicateKeyError, not InvalidBSON self.assertRaises(DuplicateKeyError, db.test.insert_one, {"text": text}) self.assertRaises( DuplicateKeyError, db.test.replace_one, {"_id": ObjectId()}, {"text": text}, upsert=True ) # Should raise BulkWriteError, not InvalidBSON self.assertRaises(BulkWriteError, db.test.insert_many, [{"text": text}]) def test_write_error_unicode(self): coll = self.db.test self.addCleanup(coll.drop) coll.create_index("a", unique=True) coll.insert_one({"a": "unicode \U0001f40d"}) with self.assertRaisesRegex(DuplicateKeyError, "E11000 duplicate key error") as ctx: coll.insert_one({"a": "unicode \U0001f40d"}) # Once more for good measure. self.assertIn("E11000 duplicate key error", str(ctx.exception)) def test_wtimeout(self): # Ensure setting wtimeout doesn't disable write concern altogether. # See SERVER-12596. collection = self.db.test collection.drop() collection.insert_one({"_id": 1}) coll = collection.with_options(write_concern=WriteConcern(w=1, wtimeout=1000)) self.assertRaises(DuplicateKeyError, coll.insert_one, {"_id": 1}) coll = collection.with_options(write_concern=WriteConcern(wtimeout=1000)) self.assertRaises(DuplicateKeyError, coll.insert_one, {"_id": 1}) def test_error_code(self): try: self.db.test.update_many({}, {"$thismodifierdoesntexist": 1}) except OperationFailure as exc: self.assertTrue(exc.code in (9, 10147, 16840, 17009)) # Just check that we set the error document. Fields # vary by MongoDB version. self.assertTrue(exc.details is not None) else: self.fail("OperationFailure was not raised") def test_index_on_subfield(self): db = self.db db.drop_collection("test") db.test.insert_one({"hello": {"a": 4, "b": 5}}) db.test.insert_one({"hello": {"a": 7, "b": 2}}) db.test.insert_one({"hello": {"a": 4, "b": 10}}) db.drop_collection("test") db.test.create_index("hello.a", unique=True) db.test.insert_one({"hello": {"a": 4, "b": 5}}) db.test.insert_one({"hello": {"a": 7, "b": 2}}) self.assertRaises(DuplicateKeyError, db.test.insert_one, {"hello": {"a": 4, "b": 10}}) def test_replace_one(self): db = self.db db.drop_collection("test") self.assertRaises(ValueError, lambda: db.test.replace_one({}, {"$set": {"x": 1}})) id1 = db.test.insert_one({"x": 1}).inserted_id result = db.test.replace_one({"x": 1}, {"y": 1}) self.assertTrue(isinstance(result, UpdateResult)) self.assertEqual(1, result.matched_count) self.assertTrue(result.modified_count in (None, 1)) self.assertIsNone(result.upserted_id) self.assertTrue(result.acknowledged) self.assertEqual(1, db.test.count_documents({"y": 1})) self.assertEqual(0, db.test.count_documents({"x": 1})) self.assertEqual(db.test.find_one(id1)["y"], 1) # type: ignore replacement = RawBSONDocument(encode({"_id": id1, "z": 1})) result = db.test.replace_one({"y": 1}, replacement, True) self.assertTrue(isinstance(result, UpdateResult)) self.assertEqual(1, result.matched_count) self.assertTrue(result.modified_count in (None, 1)) self.assertIsNone(result.upserted_id) self.assertTrue(result.acknowledged) self.assertEqual(1, db.test.count_documents({"z": 1})) self.assertEqual(0, db.test.count_documents({"y": 1})) self.assertEqual(db.test.find_one(id1)["z"], 1) # type: ignore result = db.test.replace_one({"x": 2}, {"y": 2}, True) self.assertTrue(isinstance(result, UpdateResult)) self.assertEqual(0, result.matched_count) self.assertTrue(result.modified_count in (None, 0)) self.assertTrue(isinstance(result.upserted_id, ObjectId)) self.assertTrue(result.acknowledged) self.assertEqual(1, db.test.count_documents({"y": 2})) db = db.client.get_database(db.name, write_concern=WriteConcern(w=0)) result = db.test.replace_one({"x": 0}, {"y": 0}) self.assertTrue(isinstance(result, UpdateResult)) self.assertRaises(InvalidOperation, lambda: result.matched_count) self.assertRaises(InvalidOperation, lambda: result.modified_count) self.assertRaises(InvalidOperation, lambda: result.upserted_id) self.assertFalse(result.acknowledged) def test_update_one(self): db = self.db db.drop_collection("test") self.assertRaises(ValueError, lambda: db.test.update_one({}, {"x": 1})) id1 = db.test.insert_one({"x": 5}).inserted_id result = db.test.update_one({}, {"$inc": {"x": 1}}) self.assertTrue(isinstance(result, UpdateResult)) self.assertEqual(1, result.matched_count) self.assertTrue(result.modified_count in (None, 1)) self.assertIsNone(result.upserted_id) self.assertTrue(result.acknowledged) self.assertEqual(db.test.find_one(id1)["x"], 6) # type: ignore id2 = db.test.insert_one({"x": 1}).inserted_id result = db.test.update_one({"x": 6}, {"$inc": {"x": 1}}) self.assertTrue(isinstance(result, UpdateResult)) self.assertEqual(1, result.matched_count) self.assertTrue(result.modified_count in (None, 1)) self.assertIsNone(result.upserted_id) self.assertTrue(result.acknowledged) self.assertEqual(db.test.find_one(id1)["x"], 7) # type: ignore self.assertEqual(db.test.find_one(id2)["x"], 1) # type: ignore result = db.test.update_one({"x": 2}, {"$set": {"y": 1}}, True) self.assertTrue(isinstance(result, UpdateResult)) self.assertEqual(0, result.matched_count) self.assertTrue(result.modified_count in (None, 0)) self.assertTrue(isinstance(result.upserted_id, ObjectId)) self.assertTrue(result.acknowledged) db = db.client.get_database(db.name, write_concern=WriteConcern(w=0)) result = db.test.update_one({"x": 0}, {"$inc": {"x": 1}}) self.assertTrue(isinstance(result, UpdateResult)) self.assertRaises(InvalidOperation, lambda: result.matched_count) self.assertRaises(InvalidOperation, lambda: result.modified_count) self.assertRaises(InvalidOperation, lambda: result.upserted_id) self.assertFalse(result.acknowledged) def test_update_many(self): db = self.db db.drop_collection("test") self.assertRaises(ValueError, lambda: db.test.update_many({}, {"x": 1})) db.test.insert_one({"x": 4, "y": 3}) db.test.insert_one({"x": 5, "y": 5}) db.test.insert_one({"x": 4, "y": 4}) result = db.test.update_many({"x": 4}, {"$set": {"y": 5}}) self.assertTrue(isinstance(result, UpdateResult)) self.assertEqual(2, result.matched_count) self.assertTrue(result.modified_count in (None, 2)) self.assertIsNone(result.upserted_id) self.assertTrue(result.acknowledged) self.assertEqual(3, db.test.count_documents({"y": 5})) result = db.test.update_many({"x": 5}, {"$set": {"y": 6}}) self.assertTrue(isinstance(result, UpdateResult)) self.assertEqual(1, result.matched_count) self.assertTrue(result.modified_count in (None, 1)) self.assertIsNone(result.upserted_id) self.assertTrue(result.acknowledged) self.assertEqual(1, db.test.count_documents({"y": 6})) result = db.test.update_many({"x": 2}, {"$set": {"y": 1}}, True) self.assertTrue(isinstance(result, UpdateResult)) self.assertEqual(0, result.matched_count) self.assertTrue(result.modified_count in (None, 0)) self.assertTrue(isinstance(result.upserted_id, ObjectId)) self.assertTrue(result.acknowledged) db = db.client.get_database(db.name, write_concern=WriteConcern(w=0)) result = db.test.update_many({"x": 0}, {"$inc": {"x": 1}}) self.assertTrue(isinstance(result, UpdateResult)) self.assertRaises(InvalidOperation, lambda: result.matched_count) self.assertRaises(InvalidOperation, lambda: result.modified_count) self.assertRaises(InvalidOperation, lambda: result.upserted_id) self.assertFalse(result.acknowledged) def test_update_check_keys(self): self.db.drop_collection("test") self.assertTrue(self.db.test.insert_one({"hello": "world"})) # Modify shouldn't check keys... self.assertTrue( self.db.test.update_one({"hello": "world"}, {"$set": {"foo.bar": "baz"}}, upsert=True) ) # I know this seems like testing the server but I'd like to be notified # by CI if the server's behavior changes here. doc = SON([("$set", {"foo.bar": "bim"}), ("hello", "world")]) self.assertRaises( OperationFailure, self.db.test.update_one, {"hello": "world"}, doc, upsert=True ) # This is going to cause keys to be checked and raise InvalidDocument. # That's OK assuming the server's behavior in the previous assert # doesn't change. If the behavior changes checking the first key for # '$' in update won't be good enough anymore. doc = SON([("hello", "world"), ("$set", {"foo.bar": "bim"})]) self.assertRaises( OperationFailure, self.db.test.replace_one, {"hello": "world"}, doc, upsert=True ) # Replace with empty document self.assertNotEqual(0, self.db.test.replace_one({"hello": "world"}, {}).matched_count) def test_acknowledged_delete(self): db = self.db db.drop_collection("test") db.test.insert_many([{"x": 1}, {"x": 1}]) self.assertEqual(2, db.test.delete_many({}).deleted_count) self.assertEqual(0, db.test.delete_many({}).deleted_count) @client_context.require_version_max(4, 9) def test_manual_last_error(self): coll = self.db.get_collection("test", write_concern=WriteConcern(w=0)) coll.insert_one({"x": 1}) self.db.command("getlasterror", w=1, wtimeout=1) def test_count_documents(self): db = self.db db.drop_collection("test") self.addCleanup(db.drop_collection, "test") self.assertEqual(db.test.count_documents({}), 0) db.wrong.insert_many([{}, {}]) self.assertEqual(db.test.count_documents({}), 0) db.test.insert_many([{}, {}]) self.assertEqual(db.test.count_documents({}), 2) db.test.insert_many([{"foo": "bar"}, {"foo": "baz"}]) self.assertEqual(db.test.count_documents({"foo": "bar"}), 1) self.assertEqual(db.test.count_documents({"foo": re.compile(r"ba.*")}), 2) def test_estimated_document_count(self): db = self.db db.drop_collection("test") self.addCleanup(db.drop_collection, "test") self.assertEqual(db.test.estimated_document_count(), 0) db.wrong.insert_many([{}, {}]) self.assertEqual(db.test.estimated_document_count(), 0) db.test.insert_many([{}, {}]) self.assertEqual(db.test.estimated_document_count(), 2) def test_aggregate(self): db = self.db db.drop_collection("test") db.test.insert_one({"foo": [1, 2]}) self.assertRaises(TypeError, db.test.aggregate, "wow") pipeline = {"$project": {"_id": False, "foo": True}} result = db.test.aggregate([pipeline]) self.assertTrue(isinstance(result, CommandCursor)) self.assertEqual([{"foo": [1, 2]}], list(result)) # Test write concern. with self.write_concern_collection() as coll: coll.aggregate([{"$out": "output-collection"}]) def test_aggregate_raw_bson(self): db = self.db db.drop_collection("test") db.test.insert_one({"foo": [1, 2]}) self.assertRaises(TypeError, db.test.aggregate, "wow") pipeline = {"$project": {"_id": False, "foo": True}} coll = db.get_collection("test", codec_options=CodecOptions(document_class=RawBSONDocument)) result = coll.aggregate([pipeline]) self.assertTrue(isinstance(result, CommandCursor)) first_result = next(result) self.assertIsInstance(first_result, RawBSONDocument) self.assertEqual([1, 2], list(first_result["foo"])) def test_aggregation_cursor_validation(self): db = self.db projection = {"$project": {"_id": "$_id"}} cursor = db.test.aggregate([projection], cursor={}) self.assertTrue(isinstance(cursor, CommandCursor)) def test_aggregation_cursor(self): db = self.db if client_context.has_secondaries: # Test that getMore messages are sent to the right server. db = self.client.get_database( db.name, read_preference=ReadPreference.SECONDARY, write_concern=WriteConcern(w=self.w), ) for collection_size in (10, 1000): db.drop_collection("test") db.test.insert_many([{"_id": i} for i in range(collection_size)]) expected_sum = sum(range(collection_size)) # Use batchSize to ensure multiple getMore messages cursor = db.test.aggregate([{"$project": {"_id": "$_id"}}], batchSize=5) self.assertEqual(expected_sum, sum(doc["_id"] for doc in cursor)) # Test that batchSize is handled properly. cursor = db.test.aggregate([], batchSize=5) self.assertEqual(5, len(cursor._CommandCursor__data)) # type: ignore # Force a getMore cursor._CommandCursor__data.clear() # type: ignore next(cursor) # batchSize - 1 self.assertEqual(4, len(cursor._CommandCursor__data)) # type: ignore # Exhaust the cursor. There shouldn't be any errors. for _doc in cursor: pass def test_aggregation_cursor_alive(self): self.db.test.delete_many({}) self.db.test.insert_many([{} for _ in range(3)]) self.addCleanup(self.db.test.delete_many, {}) cursor = self.db.test.aggregate(pipeline=[], cursor={"batchSize": 2}) n = 0 while True: cursor.next() n += 1 if n == 3: self.assertFalse(cursor.alive) break self.assertTrue(cursor.alive) def test_invalid_session_parameter(self): def try_invalid_session(): with self.db.test.aggregate([], {}): # type:ignore pass self.assertRaisesRegex(ValueError, "must be a ClientSession", try_invalid_session) def test_large_limit(self): db = self.db db.drop_collection("test_large_limit") db.test_large_limit.create_index([("x", 1)]) my_str = "mongomongo" * 1000 db.test_large_limit.insert_many({"x": i, "y": my_str} for i in range(2000)) i = 0 y = 0 for doc in db.test_large_limit.find(limit=1900).sort([("x", 1)]): i += 1 y += doc["x"] self.assertEqual(1900, i) self.assertEqual((1900 * 1899) / 2, y) def test_find_kwargs(self): db = self.db db.drop_collection("test") db.test.insert_many({"x": i} for i in range(10)) self.assertEqual(10, db.test.count_documents({})) total = 0 for x in db.test.find({}, skip=4, limit=2): total += x["x"] self.assertEqual(9, total) def test_rename(self): db = self.db db.drop_collection("test") db.drop_collection("foo") self.assertRaises(TypeError, db.test.rename, 5) self.assertRaises(InvalidName, db.test.rename, "") self.assertRaises(InvalidName, db.test.rename, "te$t") self.assertRaises(InvalidName, db.test.rename, ".test") self.assertRaises(InvalidName, db.test.rename, "test.") self.assertRaises(InvalidName, db.test.rename, "tes..t") self.assertEqual(0, db.test.count_documents({})) self.assertEqual(0, db.foo.count_documents({})) db.test.insert_many({"x": i} for i in range(10)) self.assertEqual(10, db.test.count_documents({})) db.test.rename("foo") self.assertEqual(0, db.test.count_documents({})) self.assertEqual(10, db.foo.count_documents({})) x = 0 for doc in db.foo.find(): self.assertEqual(x, doc["x"]) x += 1 db.test.insert_one({}) self.assertRaises(OperationFailure, db.foo.rename, "test") db.foo.rename("test", dropTarget=True) with self.write_concern_collection() as coll: coll.rename("foo") @no_type_check def test_find_one(self): db = self.db db.drop_collection("test") _id = db.test.insert_one({"hello": "world", "foo": "bar"}).inserted_id self.assertEqual("world", db.test.find_one()["hello"]) self.assertEqual(db.test.find_one(_id), db.test.find_one()) self.assertEqual(db.test.find_one(None), db.test.find_one()) self.assertEqual(db.test.find_one({}), db.test.find_one()) self.assertEqual(db.test.find_one({"hello": "world"}), db.test.find_one()) self.assertTrue("hello" in db.test.find_one(projection=["hello"])) self.assertTrue("hello" not in db.test.find_one(projection=["foo"])) self.assertTrue("hello" in db.test.find_one(projection=("hello",))) self.assertTrue("hello" not in db.test.find_one(projection=("foo",))) self.assertTrue("hello" in db.test.find_one(projection={"hello"})) self.assertTrue("hello" not in db.test.find_one(projection={"foo"})) self.assertTrue("hello" in db.test.find_one(projection=frozenset(["hello"]))) self.assertTrue("hello" not in db.test.find_one(projection=frozenset(["foo"]))) self.assertEqual(["_id"], list(db.test.find_one(projection={"_id": True}))) self.assertTrue("hello" in list(db.test.find_one(projection={}))) self.assertTrue("hello" in list(db.test.find_one(projection=[]))) self.assertEqual(None, db.test.find_one({"hello": "foo"})) self.assertEqual(None, db.test.find_one(ObjectId())) def test_find_one_non_objectid(self): db = self.db db.drop_collection("test") db.test.insert_one({"_id": 5}) self.assertTrue(db.test.find_one(5)) self.assertFalse(db.test.find_one(6)) def test_find_one_with_find_args(self): db = self.db db.drop_collection("test") db.test.insert_many([{"x": i} for i in range(1, 4)]) self.assertEqual(1, db.test.find_one()["x"]) self.assertEqual(2, db.test.find_one(skip=1, limit=2)["x"]) def test_find_with_sort(self): db = self.db db.drop_collection("test") db.test.insert_many([{"x": 2}, {"x": 1}, {"x": 3}]) self.assertEqual(2, db.test.find_one()["x"]) self.assertEqual(1, db.test.find_one(sort=[("x", 1)])["x"]) self.assertEqual(3, db.test.find_one(sort=[("x", -1)])["x"]) def to_list(things): return [thing["x"] for thing in things] self.assertEqual([2, 1, 3], to_list(db.test.find())) self.assertEqual([1, 2, 3], to_list(db.test.find(sort=[("x", 1)]))) self.assertEqual([3, 2, 1], to_list(db.test.find(sort=[("x", -1)]))) self.assertRaises(TypeError, db.test.find, sort=5) self.assertRaises(TypeError, db.test.find, sort="hello") self.assertRaises(TypeError, db.test.find, sort=["hello", 1]) # TODO doesn't actually test functionality, just that it doesn't blow up def test_cursor_timeout(self): list(self.db.test.find(no_cursor_timeout=True)) list(self.db.test.find(no_cursor_timeout=False)) def test_exhaust(self): if is_mongos(self.db.client): self.assertRaises(InvalidOperation, self.db.test.find, cursor_type=CursorType.EXHAUST) return # Limit is incompatible with exhaust. self.assertRaises( InvalidOperation, self.db.test.find, cursor_type=CursorType.EXHAUST, limit=5 ) cur = self.db.test.find(cursor_type=CursorType.EXHAUST) self.assertRaises(InvalidOperation, cur.limit, 5) cur = self.db.test.find(limit=5) self.assertRaises(InvalidOperation, cur.add_option, 64) cur = self.db.test.find() cur.add_option(64) self.assertRaises(InvalidOperation, cur.limit, 5) self.db.drop_collection("test") # Insert enough documents to require more than one batch self.db.test.insert_many([{"i": i} for i in range(150)]) client = rs_or_single_client(maxPoolSize=1) self.addCleanup(client.close) pool = get_pool(client) # Make sure the socket is returned after exhaustion. cur = client[self.db.name].test.find(cursor_type=CursorType.EXHAUST) next(cur) self.assertEqual(0, len(pool.conns)) for _ in cur: pass self.assertEqual(1, len(pool.conns)) # Same as previous but don't call next() for _ in client[self.db.name].test.find(cursor_type=CursorType.EXHAUST): pass self.assertEqual(1, len(pool.conns)) # If the Cursor instance is discarded before being completely iterated # and the socket has pending data (more_to_come=True) we have to close # and discard the socket. cur = client[self.db.name].test.find(cursor_type=CursorType.EXHAUST, batch_size=2) if client_context.version.at_least(4, 2): # On 4.2+ we use OP_MSG which only sets more_to_come=True after the # first getMore. for _ in range(3): next(cur) else: next(cur) self.assertEqual(0, len(pool.conns)) if sys.platform.startswith("java") or "PyPy" in sys.version: # Don't wait for GC or use gc.collect(), it's unreliable. cur.close() cur = None # Wait until the background thread returns the socket. wait_until(lambda: pool.active_sockets == 0, "return socket") # The socket should be discarded. self.assertEqual(0, len(pool.conns)) def test_distinct(self): self.db.drop_collection("test") test = self.db.test test.insert_many([{"a": 1}, {"a": 2}, {"a": 2}, {"a": 2}, {"a": 3}]) distinct = test.distinct("a") distinct.sort() self.assertEqual([1, 2, 3], distinct) distinct = test.find({"a": {"$gt": 1}}).distinct("a") distinct.sort() self.assertEqual([2, 3], distinct) distinct = test.distinct("a", {"a": {"$gt": 1}}) distinct.sort() self.assertEqual([2, 3], distinct) self.db.drop_collection("test") test.insert_one({"a": {"b": "a"}, "c": 12}) test.insert_one({"a": {"b": "b"}, "c": 12}) test.insert_one({"a": {"b": "c"}, "c": 12}) test.insert_one({"a": {"b": "c"}, "c": 12}) distinct = test.distinct("a.b") distinct.sort() self.assertEqual(["a", "b", "c"], distinct) def test_query_on_query_field(self): self.db.drop_collection("test") self.db.test.insert_one({"query": "foo"}) self.db.test.insert_one({"bar": "foo"}) self.assertEqual(1, self.db.test.count_documents({"query": {"$ne": None}})) self.assertEqual(1, len(list(self.db.test.find({"query": {"$ne": None}})))) def test_min_query(self): self.db.drop_collection("test") self.db.test.insert_many([{"x": 1}, {"x": 2}]) self.db.test.create_index("x") cursor = self.db.test.find({"$min": {"x": 2}, "$query": {}}, hint="x_1") docs = list(cursor) self.assertEqual(1, len(docs)) self.assertEqual(2, docs[0]["x"]) def test_numerous_inserts(self): # Ensure we don't exceed server's maxWriteBatchSize size limit. self.db.test.drop() n_docs = client_context.max_write_batch_size + 100 self.db.test.insert_many([{} for _ in range(n_docs)]) self.assertEqual(n_docs, self.db.test.count_documents({})) self.db.test.drop() def test_insert_many_large_batch(self): # Tests legacy insert. db = self.client.test_insert_large_batch self.addCleanup(self.client.drop_database, "test_insert_large_batch") max_bson_size = client_context.max_bson_size # Write commands are limited to 16MB + 16k per batch big_string = "x" * int(max_bson_size / 2) # Batch insert that requires 2 batches. successful_insert = [ {"x": big_string}, {"x": big_string}, {"x": big_string}, {"x": big_string}, ] db.collection_0.insert_many(successful_insert) self.assertEqual(4, db.collection_0.count_documents({})) db.collection_0.drop() # Test that inserts fail after first error. insert_second_fails = [ {"_id": "id0", "x": big_string}, {"_id": "id0", "x": big_string}, {"_id": "id1", "x": big_string}, {"_id": "id2", "x": big_string}, ] with self.assertRaises(BulkWriteError): db.collection_1.insert_many(insert_second_fails) self.assertEqual(1, db.collection_1.count_documents({})) db.collection_1.drop() # 2 batches, 2nd insert fails, unacknowledged, ordered. unack_coll = db.collection_2.with_options(write_concern=WriteConcern(w=0)) unack_coll.insert_many(insert_second_fails) wait_until( lambda: db.collection_2.count_documents({}) == 1, "insert 1 document", timeout=60 ) db.collection_2.drop() # 2 batches, ids of docs 0 and 1 are dupes, ids of docs 2 and 3 are # dupes. Acknowledged, unordered. insert_two_failures = [ {"_id": "id0", "x": big_string}, {"_id": "id0", "x": big_string}, {"_id": "id1", "x": big_string}, {"_id": "id1", "x": big_string}, ] with self.assertRaises(OperationFailure) as context: db.collection_3.insert_many(insert_two_failures, ordered=False) self.assertIn("id1", str(context.exception)) # Only the first and third documents should be inserted. self.assertEqual(2, db.collection_3.count_documents({})) db.collection_3.drop() # 2 batches, 2 errors, unacknowledged, unordered. unack_coll = db.collection_4.with_options(write_concern=WriteConcern(w=0)) unack_coll.insert_many(insert_two_failures, ordered=False) # Only the first and third documents are inserted. wait_until( lambda: db.collection_4.count_documents({}) == 2, "insert 2 documents", timeout=60 ) db.collection_4.drop() def test_messages_with_unicode_collection_names(self): db = self.db db["Employés"].insert_one({"x": 1}) db["Employés"].replace_one({"x": 1}, {"x": 2}) db["Employés"].delete_many({}) db["Employés"].find_one() list(db["Employés"].find()) def test_drop_indexes_non_existent(self): self.db.drop_collection("test") self.db.test.drop_indexes() # This is really a bson test but easier to just reproduce it here... # (Shame on me) def test_bad_encode(self): c = self.db.test c.drop() self.assertRaises(InvalidDocument, c.insert_one, {"x": c}) class BadGetAttr(dict): def __getattr__(self, name): pass bad = BadGetAttr([("foo", "bar")]) c.insert_one({"bad": bad}) self.assertEqual("bar", c.find_one()["bad"]["foo"]) # type: ignore def test_array_filters_validation(self): # array_filters must be a list. c = self.db.test with self.assertRaises(TypeError): c.update_one({}, {"$set": {"a": 1}}, array_filters={}) # type: ignore[arg-type] with self.assertRaises(TypeError): c.update_many({}, {"$set": {"a": 1}}, array_filters={}) # type: ignore[arg-type] with self.assertRaises(TypeError): update = {"$set": {"a": 1}} c.find_one_and_update({}, update, array_filters={}) # type: ignore[arg-type] def test_array_filters_unacknowledged(self): c_w0 = self.db.test.with_options(write_concern=WriteConcern(w=0)) with self.assertRaises(ConfigurationError): c_w0.update_one({}, {"$set": {"y.$[i].b": 5}}, array_filters=[{"i.b": 1}]) with self.assertRaises(ConfigurationError): c_w0.update_many({}, {"$set": {"y.$[i].b": 5}}, array_filters=[{"i.b": 1}]) with self.assertRaises(ConfigurationError): c_w0.find_one_and_update({}, {"$set": {"y.$[i].b": 5}}, array_filters=[{"i.b": 1}]) def test_find_one_and(self): c = self.db.test c.drop() c.insert_one({"_id": 1, "i": 1}) self.assertEqual({"_id": 1, "i": 1}, c.find_one_and_update({"_id": 1}, {"$inc": {"i": 1}})) self.assertEqual( {"_id": 1, "i": 3}, c.find_one_and_update( {"_id": 1}, {"$inc": {"i": 1}}, return_document=ReturnDocument.AFTER ), ) self.assertEqual({"_id": 1, "i": 3}, c.find_one_and_delete({"_id": 1})) self.assertEqual(None, c.find_one({"_id": 1})) self.assertEqual(None, c.find_one_and_update({"_id": 1}, {"$inc": {"i": 1}})) self.assertEqual( {"_id": 1, "i": 1}, c.find_one_and_update( {"_id": 1}, {"$inc": {"i": 1}}, return_document=ReturnDocument.AFTER, upsert=True ), ) self.assertEqual( {"_id": 1, "i": 2}, c.find_one_and_update( {"_id": 1}, {"$inc": {"i": 1}}, return_document=ReturnDocument.AFTER ), ) self.assertEqual( {"_id": 1, "i": 3}, c.find_one_and_replace( {"_id": 1}, {"i": 3, "j": 1}, projection=["i"], return_document=ReturnDocument.AFTER ), ) self.assertEqual( {"i": 4}, c.find_one_and_update( {"_id": 1}, {"$inc": {"i": 1}}, projection={"i": 1, "_id": 0}, return_document=ReturnDocument.AFTER, ), ) c.drop() for j in range(5): c.insert_one({"j": j, "i": 0}) sort = [("j", DESCENDING)] self.assertEqual(4, c.find_one_and_update({}, {"$inc": {"i": 1}}, sort=sort)["j"]) def test_find_one_and_write_concern(self): listener = EventListener() db = single_client(event_listeners=[listener])[self.db.name] # non-default WriteConcern. c_w0 = db.get_collection("test", write_concern=WriteConcern(w=0)) # default WriteConcern. c_default = db.get_collection("test", write_concern=WriteConcern()) # Authenticate the client and throw out auth commands from the listener. db.command("ping") listener.reset() c_w0.find_one_and_update({"_id": 1}, {"$set": {"foo": "bar"}}) self.assertEqual({"w": 0}, listener.started_events[0].command["writeConcern"]) listener.reset() c_w0.find_one_and_replace({"_id": 1}, {"foo": "bar"}) self.assertEqual({"w": 0}, listener.started_events[0].command["writeConcern"]) listener.reset() c_w0.find_one_and_delete({"_id": 1}) self.assertEqual({"w": 0}, listener.started_events[0].command["writeConcern"]) listener.reset() # Test write concern errors. if client_context.is_rs: c_wc_error = db.get_collection( "test", write_concern=WriteConcern(w=len(client_context.nodes) + 1) ) self.assertRaises( WriteConcernError, c_wc_error.find_one_and_update, {"_id": 1}, {"$set": {"foo": "bar"}}, ) self.assertRaises( WriteConcernError, c_wc_error.find_one_and_replace, {"w": 0}, listener.started_events[0].command["writeConcern"], ) self.assertRaises( WriteConcernError, c_wc_error.find_one_and_delete, {"w": 0}, listener.started_events[0].command["writeConcern"], ) listener.reset() c_default.find_one_and_update({"_id": 1}, {"$set": {"foo": "bar"}}) self.assertNotIn("writeConcern", listener.started_events[0].command) listener.reset() c_default.find_one_and_replace({"_id": 1}, {"foo": "bar"}) self.assertNotIn("writeConcern", listener.started_events[0].command) listener.reset() c_default.find_one_and_delete({"_id": 1}) self.assertNotIn("writeConcern", listener.started_events[0].command) listener.reset() def test_find_with_nested(self): c = self.db.test c.drop() c.insert_many([{"i": i} for i in range(5)]) # [0, 1, 2, 3, 4] self.assertEqual( [2], [ i["i"] for i in c.find( { "$and": [ { # This clause gives us [1,2,4] "$or": [ {"i": {"$lte": 2}}, {"i": {"$gt": 3}}, ], }, { # This clause gives us [2,3] "$or": [ {"i": 2}, {"i": 3}, ] }, ] } ) ], ) self.assertEqual( [0, 1, 2], [ i["i"] for i in c.find( { "$or": [ { # This clause gives us [2] "$and": [ {"i": {"$gte": 2}}, {"i": {"$lt": 3}}, ], }, { # This clause gives us [0,1] "$and": [ {"i": {"$gt": -100}}, {"i": {"$lt": 2}}, ] }, ] } ) ], ) def test_find_regex(self): c = self.db.test c.drop() c.insert_one({"r": re.compile(".*")}) self.assertTrue(isinstance(c.find_one()["r"], Regex)) # type: ignore for doc in c.find(): self.assertTrue(isinstance(doc["r"], Regex)) def test_find_command_generation(self): cmd = _gen_find_command( "coll", {"$query": {"foo": 1}, "$dumb": 2}, None, 0, 0, 0, None, DEFAULT_READ_CONCERN, None, None, ) self.assertEqual(cmd, {"find": "coll", "$dumb": 2, "filter": {"foo": 1}}) def test_bool(self): with self.assertRaises(NotImplementedError): bool(Collection(self.db, "test")) @client_context.require_version_min(5, 0, 0) def test_helpers_with_let(self): c = self.db.test helpers = [ (c.delete_many, ({}, {})), (c.delete_one, ({}, {})), (c.find, ({})), (c.update_many, ({}, {"$inc": {"x": 3}})), (c.update_one, ({}, {"$inc": {"x": 3}})), (c.find_one_and_delete, ({}, {})), (c.find_one_and_replace, ({}, {})), (c.aggregate, ([],)), ] for let in [10, "str", [], False]: for helper, args in helpers: with self.assertRaisesRegex(TypeError, "let must be an instance of dict"): helper(*args, let=let) # type: ignore for helper, args in helpers: helper(*args, let={}) # type: ignore if __name__ == "__main__": unittest.main() mongodb-mongo-python-driver-509e9b7/test/test_collection_management.py000066400000000000000000000020661462766011000263600ustar00rootroot00000000000000# Copyright 2021-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. """Test the collection management unified spec tests.""" from __future__ import annotations import os import sys sys.path[0:0] = [""] from test import unittest from test.unified_format import generate_test_classes # Location of JSON test specifications. TEST_PATH = os.path.join(os.path.dirname(os.path.realpath(__file__)), "collection_management") # Generate unified tests. globals().update(generate_test_classes(TEST_PATH, module=__name__)) if __name__ == "__main__": unittest.main() mongodb-mongo-python-driver-509e9b7/test/test_command_logging.py000066400000000000000000000020701462766011000251500ustar00rootroot00000000000000# Copyright 2023-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. """Run the command monitoring unified format spec tests.""" from __future__ import annotations import os import sys sys.path[0:0] = [""] from test import unittest from test.unified_format import generate_test_classes # Location of JSON test specifications. _TEST_PATH = os.path.join(os.path.dirname(os.path.realpath(__file__)), "command_logging") globals().update( generate_test_classes( _TEST_PATH, module=__name__, ) ) if __name__ == "__main__": unittest.main() mongodb-mongo-python-driver-509e9b7/test/test_command_monitoring.py000066400000000000000000000020751462766011000257140ustar00rootroot00000000000000# Copyright 2015-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. """Run the command monitoring unified format spec tests.""" from __future__ import annotations import os import sys sys.path[0:0] = [""] from test import unittest from test.unified_format import generate_test_classes # Location of JSON test specifications. _TEST_PATH = os.path.join(os.path.dirname(os.path.realpath(__file__)), "command_monitoring") globals().update( generate_test_classes( _TEST_PATH, module=__name__, ) ) if __name__ == "__main__": unittest.main() mongodb-mongo-python-driver-509e9b7/test/test_comment.py000066400000000000000000000154511462766011000234750ustar00rootroot00000000000000# Copyright 2022-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. """Test the keyword argument 'comment' in various helpers.""" from __future__ import annotations import inspect import sys sys.path[0:0] = [""] from test import IntegrationTest, client_context, unittest from test.utils import EventListener, rs_or_single_client from bson.dbref import DBRef from pymongo.command_cursor import CommandCursor from pymongo.operations import IndexModel class Empty: def __getattr__(self, item): try: self.__dict__[item] except KeyError: return self.empty def empty(self, *args, **kwargs): return Empty() class TestComment(IntegrationTest): def _test_ops( self, helpers, already_supported, listener, db=Empty(), # noqa: B008 coll=Empty(), # noqa: B008 ): for h, args in helpers: c = "testing comment with " + h.__name__ with self.subTest("collection-" + h.__name__ + "-comment"): for cc in [c, {"key": c}, ["any", 1]]: listener.reset() kwargs = {"comment": cc} if h == coll.rename: _ = db.get_collection("temp_temp_temp").drop() destruct_coll = db.get_collection("test_temp") destruct_coll.insert_one({}) maybe_cursor = destruct_coll.rename(*args, **kwargs) destruct_coll.drop() elif h == db.validate_collection: coll = db.get_collection("test") coll.insert_one({}) maybe_cursor = db.validate_collection(*args, **kwargs) else: coll.create_index("a") maybe_cursor = h(*args, **kwargs) self.assertIn( "comment", inspect.signature(h).parameters, msg="Could not find 'comment' in the " "signature of function %s" % (h.__name__), ) self.assertEqual( inspect.signature(h).parameters["comment"].annotation, "Optional[Any]" ) if isinstance(maybe_cursor, CommandCursor): maybe_cursor.close() tested = False # For some reason collection.list_indexes creates two commands and the first # one doesn't contain 'comment'. for i in listener.started_events: if cc == i.command.get("comment", ""): self.assertEqual(cc, i.command["comment"]) tested = True self.assertTrue(tested) if h not in [coll.aggregate_raw_batches]: self.assertIn( ":param comment:", h.__doc__, ) if h not in already_supported: self.assertIn( "Added ``comment`` parameter", h.__doc__, ) else: self.assertNotIn( "Added ``comment`` parameter", h.__doc__, ) listener.reset() @client_context.require_version_min(4, 7, -1) @client_context.require_replica_set def test_database_helpers(self): listener = EventListener() db = rs_or_single_client(event_listeners=[listener]).db helpers = [ (db.watch, []), (db.command, ["hello"]), (db.list_collections, []), (db.list_collection_names, []), (db.drop_collection, ["hello"]), (db.validate_collection, ["test"]), (db.dereference, [DBRef("collection", 1)]), ] already_supported = [db.command, db.list_collections, db.list_collection_names] self._test_ops(helpers, already_supported, listener, db=db, coll=db.get_collection("test")) @client_context.require_version_min(4, 7, -1) @client_context.require_replica_set def test_client_helpers(self): listener = EventListener() cli = rs_or_single_client(event_listeners=[listener]) helpers = [ (cli.watch, []), (cli.list_databases, []), (cli.list_database_names, []), (cli.drop_database, ["test"]), ] already_supported = [ cli.list_databases, ] self._test_ops(helpers, already_supported, listener) @client_context.require_version_min(4, 7, -1) def test_collection_helpers(self): listener = EventListener() db = rs_or_single_client(event_listeners=[listener])[self.db.name] coll = db.get_collection("test") helpers = [ (coll.list_indexes, []), (coll.drop, []), (coll.index_information, []), (coll.options, []), (coll.aggregate, [[{"$set": {"x": 1}}]]), (coll.aggregate_raw_batches, [[{"$set": {"x": 1}}]]), (coll.rename, ["temp_temp_temp"]), (coll.distinct, ["_id"]), (coll.find_one_and_delete, [{}]), (coll.find_one_and_replace, [{}, {}]), (coll.find_one_and_update, [{}, {"$set": {"a": 1}}]), (coll.estimated_document_count, []), (coll.count_documents, [{}]), (coll.create_indexes, [[IndexModel("a")]]), (coll.create_index, ["a"]), (coll.drop_index, [[("a", 1)]]), (coll.drop_indexes, []), ] already_supported = [ coll.estimated_document_count, coll.count_documents, coll.create_indexes, coll.drop_indexes, coll.options, coll.find_one_and_replace, coll.drop_index, coll.rename, coll.distinct, coll.find_one_and_delete, coll.find_one_and_update, ] self._test_ops(helpers, already_supported, listener, coll=coll, db=db) if __name__ == "__main__": unittest.main() mongodb-mongo-python-driver-509e9b7/test/test_common.py000066400000000000000000000156111462766011000233210ustar00rootroot00000000000000# Copyright 2011-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. """Test the pymongo common module.""" from __future__ import annotations import sys import uuid sys.path[0:0] = [""] from test import IntegrationTest, client_context, unittest from test.utils import connected, rs_or_single_client, single_client from bson.binary import PYTHON_LEGACY, STANDARD, Binary, UuidRepresentation from bson.codec_options import CodecOptions from bson.objectid import ObjectId from pymongo.errors import OperationFailure from pymongo.write_concern import WriteConcern @client_context.require_connection def setUpModule(): pass class TestCommon(IntegrationTest): def test_uuid_representation(self): coll = self.db.uuid coll.drop() # Test property self.assertEqual(UuidRepresentation.UNSPECIFIED, coll.codec_options.uuid_representation) # Test basic query uu = uuid.uuid4() # Insert as binary subtype 3 coll = self.db.get_collection("uuid", CodecOptions(uuid_representation=PYTHON_LEGACY)) legacy_opts = coll.codec_options coll.insert_one({"uu": uu}) self.assertEqual(uu, coll.find_one({"uu": uu})["uu"]) # type: ignore coll = self.db.get_collection("uuid", CodecOptions(uuid_representation=STANDARD)) self.assertEqual(STANDARD, coll.codec_options.uuid_representation) self.assertEqual(None, coll.find_one({"uu": uu})) uul = Binary.from_uuid(uu, PYTHON_LEGACY) self.assertEqual(uul, coll.find_one({"uu": uul})["uu"]) # type: ignore # Test count_documents self.assertEqual(0, coll.count_documents({"uu": uu})) coll = self.db.get_collection("uuid", CodecOptions(uuid_representation=PYTHON_LEGACY)) self.assertEqual(1, coll.count_documents({"uu": uu})) # Test delete coll = self.db.get_collection("uuid", CodecOptions(uuid_representation=STANDARD)) coll.delete_one({"uu": uu}) self.assertEqual(1, coll.count_documents({})) coll = self.db.get_collection("uuid", CodecOptions(uuid_representation=PYTHON_LEGACY)) coll.delete_one({"uu": uu}) self.assertEqual(0, coll.count_documents({})) # Test update_one coll.insert_one({"_id": uu, "i": 1}) coll = self.db.get_collection("uuid", CodecOptions(uuid_representation=STANDARD)) coll.update_one({"_id": uu}, {"$set": {"i": 2}}) coll = self.db.get_collection("uuid", CodecOptions(uuid_representation=PYTHON_LEGACY)) self.assertEqual(1, coll.find_one({"_id": uu})["i"]) # type: ignore coll.update_one({"_id": uu}, {"$set": {"i": 2}}) self.assertEqual(2, coll.find_one({"_id": uu})["i"]) # type: ignore # Test Cursor.distinct self.assertEqual([2], coll.find({"_id": uu}).distinct("i")) coll = self.db.get_collection("uuid", CodecOptions(uuid_representation=STANDARD)) self.assertEqual([], coll.find({"_id": uu}).distinct("i")) # Test findAndModify self.assertEqual(None, coll.find_one_and_update({"_id": uu}, {"$set": {"i": 5}})) coll = self.db.get_collection("uuid", CodecOptions(uuid_representation=PYTHON_LEGACY)) self.assertEqual(2, coll.find_one_and_update({"_id": uu}, {"$set": {"i": 5}})["i"]) self.assertEqual(5, coll.find_one({"_id": uu})["i"]) # type: ignore # Test command self.assertEqual( 5, self.db.command( "findAndModify", "uuid", update={"$set": {"i": 6}}, query={"_id": uu}, codec_options=legacy_opts, )["value"]["i"], ) self.assertEqual( 6, self.db.command( "findAndModify", "uuid", update={"$set": {"i": 7}}, query={"_id": Binary.from_uuid(uu, PYTHON_LEGACY)}, )["value"]["i"], ) def test_write_concern(self): c = rs_or_single_client(connect=False) self.assertEqual(WriteConcern(), c.write_concern) c = rs_or_single_client(connect=False, w=2, wTimeoutMS=1000) wc = WriteConcern(w=2, wtimeout=1000) self.assertEqual(wc, c.write_concern) # Can we override back to the server default? db = c.get_database("pymongo_test", write_concern=WriteConcern()) self.assertEqual(db.write_concern, WriteConcern()) db = c.pymongo_test self.assertEqual(wc, db.write_concern) coll = db.test self.assertEqual(wc, coll.write_concern) cwc = WriteConcern(j=True) coll = db.get_collection("test", write_concern=cwc) self.assertEqual(cwc, coll.write_concern) self.assertEqual(wc, db.write_concern) def test_mongo_client(self): pair = client_context.pair m = rs_or_single_client(w=0) coll = m.pymongo_test.write_concern_test coll.drop() doc = {"_id": ObjectId()} coll.insert_one(doc) self.assertTrue(coll.insert_one(doc)) coll = coll.with_options(write_concern=WriteConcern(w=1)) self.assertRaises(OperationFailure, coll.insert_one, doc) m = rs_or_single_client() coll = m.pymongo_test.write_concern_test new_coll = coll.with_options(write_concern=WriteConcern(w=0)) self.assertTrue(new_coll.insert_one(doc)) self.assertRaises(OperationFailure, coll.insert_one, doc) m = rs_or_single_client(f"mongodb://{pair}/", replicaSet=client_context.replica_set_name) coll = m.pymongo_test.write_concern_test self.assertRaises(OperationFailure, coll.insert_one, doc) m = rs_or_single_client( f"mongodb://{pair}/?w=0", replicaSet=client_context.replica_set_name ) coll = m.pymongo_test.write_concern_test coll.insert_one(doc) # Equality tests direct = connected(single_client(w=0)) direct2 = connected(single_client(f"mongodb://{pair}/?w=0", **self.credentials)) self.assertEqual(direct, direct2) self.assertFalse(direct != direct2) def test_validate_boolean(self): self.db.test.update_one({}, {"$set": {"total": 1}}, upsert=True) with self.assertRaisesRegex( TypeError, "upsert must be True or False, was: upsert={'upsert': True}" ): self.db.test.update_one({}, {"$set": {"total": 1}}, {"upsert": True}) # type: ignore if __name__ == "__main__": unittest.main() mongodb-mongo-python-driver-509e9b7/test/test_connection_logging.py000066400000000000000000000020751462766011000256760ustar00rootroot00000000000000# Copyright 2023-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. """Run the connection logging unified format spec tests.""" from __future__ import annotations import os import sys sys.path[0:0] = [""] from test import unittest from test.unified_format import generate_test_classes # Location of JSON test specifications. _TEST_PATH = os.path.join(os.path.dirname(os.path.realpath(__file__)), "connection_logging") globals().update( generate_test_classes( _TEST_PATH, module=__name__, ) ) if __name__ == "__main__": unittest.main() mongodb-mongo-python-driver-509e9b7/test/test_connection_monitoring.py000066400000000000000000000425221462766011000264360ustar00rootroot00000000000000# Copyright 2019-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. """Execute Transactions Spec tests.""" from __future__ import annotations import os import sys import time sys.path[0:0] = [""] from test import IntegrationTest, client_knobs, unittest from test.pymongo_mocks import DummyMonitor from test.utils import ( CMAPListener, SpecTestCreator, camel_to_snake, client_context, get_pool, get_pools, rs_or_single_client, single_client, single_client_noauth, wait_until, ) from test.utils_spec_runner import SpecRunnerThread from bson.objectid import ObjectId from bson.son import SON from pymongo.errors import ( ConnectionFailure, OperationFailure, PyMongoError, WaitQueueTimeoutError, ) from pymongo.monitoring import ( ConnectionCheckedInEvent, ConnectionCheckedOutEvent, ConnectionCheckOutFailedEvent, ConnectionCheckOutFailedReason, ConnectionCheckOutStartedEvent, ConnectionClosedEvent, ConnectionClosedReason, ConnectionCreatedEvent, ConnectionReadyEvent, PoolClearedEvent, PoolClosedEvent, PoolCreatedEvent, PoolReadyEvent, ) from pymongo.pool import PoolState, _PoolClosedError from pymongo.read_preferences import ReadPreference from pymongo.topology_description import updated_topology_description OBJECT_TYPES = { # Event types. "ConnectionCheckedIn": ConnectionCheckedInEvent, "ConnectionCheckedOut": ConnectionCheckedOutEvent, "ConnectionCheckOutFailed": ConnectionCheckOutFailedEvent, "ConnectionClosed": ConnectionClosedEvent, "ConnectionCreated": ConnectionCreatedEvent, "ConnectionReady": ConnectionReadyEvent, "ConnectionCheckOutStarted": ConnectionCheckOutStartedEvent, "ConnectionPoolCreated": PoolCreatedEvent, "ConnectionPoolReady": PoolReadyEvent, "ConnectionPoolCleared": PoolClearedEvent, "ConnectionPoolClosed": PoolClosedEvent, # Error types. "PoolClosedError": _PoolClosedError, "WaitQueueTimeoutError": WaitQueueTimeoutError, } class TestCMAP(IntegrationTest): # Location of JSON test specifications. TEST_PATH = os.path.join(os.path.dirname(os.path.realpath(__file__)), "connection_monitoring") # Test operations: def start(self, op): """Run the 'start' thread operation.""" target = op["target"] thread = SpecRunnerThread(target) thread.start() self.targets[target] = thread def wait(self, op): """Run the 'wait' operation.""" time.sleep(op["ms"] / 1000.0) def wait_for_thread(self, op): """Run the 'waitForThread' operation.""" target = op["target"] thread = self.targets[target] thread.stop() thread.join() if thread.exc: raise thread.exc self.assertFalse(thread.ops) def wait_for_event(self, op): """Run the 'waitForEvent' operation.""" event = OBJECT_TYPES[op["event"]] count = op["count"] timeout = op.get("timeout", 10000) / 1000.0 wait_until( lambda: self.listener.event_count(event) >= count, f"find {count} {event} event(s)", timeout=timeout, ) def check_out(self, op): """Run the 'checkOut' operation.""" label = op["label"] with self.pool.checkout() as conn: # Call 'pin_cursor' so we can hold the socket. conn.pin_cursor() if label: self.labels[label] = conn else: self.addCleanup(conn.close_conn, None) def check_in(self, op): """Run the 'checkIn' operation.""" label = op["connection"] conn = self.labels[label] self.pool.checkin(conn) def ready(self, op): """Run the 'ready' operation.""" self.pool.ready() def clear(self, op): """Run the 'clear' operation.""" if "interruptInUseConnections" in op: self.pool.reset(interrupt_connections=op["interruptInUseConnections"]) else: self.pool.reset() def close(self, op): """Run the 'close' operation.""" self.pool.close() def run_operation(self, op): """Run a single operation in a test.""" op_name = camel_to_snake(op["name"]) thread = op["thread"] meth = getattr(self, op_name) if thread: self.targets[thread].schedule(lambda: meth(op)) else: meth(op) def run_operations(self, ops): """Run a test's operations.""" for op in ops: self._ops.append(op) self.run_operation(op) def check_object(self, actual, expected): """Assert that the actual object matches the expected object.""" self.assertEqual(type(actual), OBJECT_TYPES[expected["type"]]) for attr, expected_val in expected.items(): if attr == "type": continue c2s = camel_to_snake(attr) if c2s == "interrupt_in_use_connections": c2s = "interrupt_connections" actual_val = getattr(actual, c2s) if expected_val == 42: self.assertIsNotNone(actual_val) else: self.assertEqual(actual_val, expected_val) def check_event(self, actual, expected): """Assert that the actual event matches the expected event.""" self.check_object(actual, expected) def actual_events(self, ignore): """Return all the non-ignored events.""" ignore = tuple(OBJECT_TYPES[name] for name in ignore) return [event for event in self.listener.events if not isinstance(event, ignore)] def check_events(self, events, ignore): """Check the events of a test.""" actual_events = self.actual_events(ignore) for actual, expected in zip(actual_events, events): self.logs.append(f"Checking event actual: {actual!r} vs expected: {expected!r}") self.check_event(actual, expected) if len(events) > len(actual_events): self.fail(f"missing events: {events[len(actual_events) :]!r}") def check_error(self, actual, expected): message = expected.pop("message") self.check_object(actual, expected) self.assertIn(message, str(actual)) def _set_fail_point(self, client, command_args): cmd = SON([("configureFailPoint", "failCommand")]) cmd.update(command_args) client.admin.command(cmd) def set_fail_point(self, command_args): if not client_context.supports_failCommand_fail_point: self.skipTest("failCommand fail point must be supported") self._set_fail_point(self.client, command_args) def run_scenario(self, scenario_def, test): """Run a CMAP spec test.""" self.logs: list = [] self.assertEqual(scenario_def["version"], 1) self.assertIn(scenario_def["style"], ["unit", "integration"]) self.listener = CMAPListener() self._ops: list = [] # Configure the fail point before creating the client. if "failPoint" in test: fp = test["failPoint"] self.set_fail_point(fp) self.addCleanup( self.set_fail_point, {"configureFailPoint": fp["configureFailPoint"], "mode": "off"} ) opts = test["poolOptions"].copy() opts["event_listeners"] = [self.listener] opts["_monitor_class"] = DummyMonitor opts["connect"] = False # Support backgroundThreadIntervalMS, default to 50ms. interval = opts.pop("backgroundThreadIntervalMS", 50) if interval < 0: kill_cursor_frequency = 99999999 else: kill_cursor_frequency = interval / 1000.0 with client_knobs(kill_cursor_frequency=kill_cursor_frequency, min_heartbeat_interval=0.05): client = single_client(**opts) # Update the SD to a known type because the DummyMonitor will not. # Note we cannot simply call topology.on_change because that would # internally call pool.ready() which introduces unexpected # PoolReadyEvents. Instead, update the initial state before # opening the Topology. td = client_context.client._topology.description sd = td.server_descriptions()[(client_context.host, client_context.port)] client._topology._description = updated_topology_description( client._topology._description, sd ) # When backgroundThreadIntervalMS is negative we do not start the # background thread to ensure it never runs. if interval < 0: client._topology.open() else: client._get_topology() self.addCleanup(client.close) self.pool = list(client._topology._servers.values())[0].pool # Map of target names to Thread objects. self.targets: dict = {} # Map of label names to Connection objects self.labels: dict = {} def cleanup(): for t in self.targets.values(): t.stop() for t in self.targets.values(): t.join(5) for conn in self.labels.values(): conn.close_conn(None) self.addCleanup(cleanup) try: if test["error"]: with self.assertRaises(PyMongoError) as ctx: self.run_operations(test["operations"]) self.check_error(ctx.exception, test["error"]) else: self.run_operations(test["operations"]) self.check_events(test["events"], test["ignore"]) except Exception: # Print the events after a test failure. print("\nFailed test: {!r}".format(test["description"])) print("Operations:") for op in self._ops: print(op) print("Threads:") print(self.targets) print("Connections:") print(self.labels) print("Events:") for event in self.listener.events: print(event) print("Log:") for log in self.logs: print(log) raise POOL_OPTIONS = { "maxPoolSize": 50, "minPoolSize": 1, "maxIdleTimeMS": 10000, "waitQueueTimeoutMS": 10000, } # # Prose tests. Numbers correspond to the prose test number in the spec. # def test_1_client_connection_pool_options(self): client = rs_or_single_client(**self.POOL_OPTIONS) self.addCleanup(client.close) pool_opts = get_pool(client).opts self.assertEqual(pool_opts.non_default_options, self.POOL_OPTIONS) def test_2_all_client_pools_have_same_options(self): client = rs_or_single_client(**self.POOL_OPTIONS) self.addCleanup(client.close) client.admin.command("ping") # Discover at least one secondary. if client_context.has_secondaries: client.admin.command("ping", read_preference=ReadPreference.SECONDARY) pools = get_pools(client) pool_opts = pools[0].opts self.assertEqual(pool_opts.non_default_options, self.POOL_OPTIONS) for pool in pools[1:]: self.assertEqual(pool.opts, pool_opts) def test_3_uri_connection_pool_options(self): opts = "&".join([f"{k}={v}" for k, v in self.POOL_OPTIONS.items()]) uri = f"mongodb://{client_context.pair}/?{opts}" client = rs_or_single_client(uri) self.addCleanup(client.close) pool_opts = get_pool(client).opts self.assertEqual(pool_opts.non_default_options, self.POOL_OPTIONS) def test_4_subscribe_to_events(self): listener = CMAPListener() client = single_client(event_listeners=[listener]) self.addCleanup(client.close) self.assertEqual(listener.event_count(PoolCreatedEvent), 1) # Creates a new connection. client.admin.command("ping") self.assertEqual(listener.event_count(ConnectionCheckOutStartedEvent), 1) self.assertEqual(listener.event_count(ConnectionCreatedEvent), 1) self.assertEqual(listener.event_count(ConnectionReadyEvent), 1) self.assertEqual(listener.event_count(ConnectionCheckedOutEvent), 1) self.assertEqual(listener.event_count(ConnectionCheckedInEvent), 1) # Uses the existing connection. client.admin.command("ping") self.assertEqual(listener.event_count(ConnectionCheckOutStartedEvent), 2) self.assertEqual(listener.event_count(ConnectionCheckedOutEvent), 2) self.assertEqual(listener.event_count(ConnectionCheckedInEvent), 2) client.close() self.assertEqual(listener.event_count(PoolClosedEvent), 1) self.assertEqual(listener.event_count(ConnectionClosedEvent), 1) def test_5_check_out_fails_connection_error(self): listener = CMAPListener() client = single_client(event_listeners=[listener]) self.addCleanup(client.close) pool = get_pool(client) def mock_connect(*args, **kwargs): raise ConnectionFailure("connect failed") pool.connect = mock_connect # Un-patch Pool.connect to break the cyclic reference. self.addCleanup(delattr, pool, "connect") # Attempt to create a new connection. with self.assertRaisesRegex(ConnectionFailure, "connect failed"): client.admin.command("ping") self.assertIsInstance(listener.events[0], PoolCreatedEvent) self.assertIsInstance(listener.events[1], PoolReadyEvent) self.assertIsInstance(listener.events[2], ConnectionCheckOutStartedEvent) self.assertIsInstance(listener.events[3], ConnectionCheckOutFailedEvent) self.assertIsInstance(listener.events[4], PoolClearedEvent) failed_event = listener.events[3] self.assertEqual(failed_event.reason, ConnectionCheckOutFailedReason.CONN_ERROR) def test_5_check_out_fails_auth_error(self): listener = CMAPListener() client = single_client_noauth( username="notauser", password="fail", event_listeners=[listener] ) self.addCleanup(client.close) # Attempt to create a new connection. with self.assertRaisesRegex(OperationFailure, "failed"): client.admin.command("ping") self.assertIsInstance(listener.events[0], PoolCreatedEvent) self.assertIsInstance(listener.events[1], PoolReadyEvent) self.assertIsInstance(listener.events[2], ConnectionCheckOutStartedEvent) self.assertIsInstance(listener.events[3], ConnectionCreatedEvent) # Error happens here. self.assertIsInstance(listener.events[4], ConnectionClosedEvent) self.assertIsInstance(listener.events[5], ConnectionCheckOutFailedEvent) self.assertEqual(listener.events[5].reason, ConnectionCheckOutFailedReason.CONN_ERROR) # # Extra non-spec tests # def assertRepr(self, obj): new_obj = eval(repr(obj)) self.assertEqual(type(new_obj), type(obj)) self.assertEqual(repr(new_obj), repr(obj)) def test_events_repr(self): host = ("localhost", 27017) self.assertRepr(ConnectionCheckedInEvent(host, 1)) self.assertRepr(ConnectionCheckedOutEvent(host, 1, time.monotonic())) self.assertRepr( ConnectionCheckOutFailedEvent( host, ConnectionCheckOutFailedReason.POOL_CLOSED, time.monotonic() ) ) self.assertRepr(ConnectionClosedEvent(host, 1, ConnectionClosedReason.POOL_CLOSED)) self.assertRepr(ConnectionCreatedEvent(host, 1)) self.assertRepr(ConnectionReadyEvent(host, 1, time.monotonic())) self.assertRepr(ConnectionCheckOutStartedEvent(host)) self.assertRepr(PoolCreatedEvent(host, {})) self.assertRepr(PoolClearedEvent(host)) self.assertRepr(PoolClearedEvent(host, service_id=ObjectId())) self.assertRepr(PoolClosedEvent(host)) def test_close_leaves_pool_unpaused(self): listener = CMAPListener() client = single_client(event_listeners=[listener]) client.admin.command("ping") pool = get_pool(client) client.close() self.assertEqual(1, listener.event_count(PoolClosedEvent)) self.assertEqual(PoolState.CLOSED, pool.state) # Checking out a connection should fail with self.assertRaises(_PoolClosedError): with pool.checkout(): pass def create_test(scenario_def, test, name): def run_scenario(self): self.run_scenario(scenario_def, test) return run_scenario class CMAPSpecTestCreator(SpecTestCreator): def tests(self, scenario_def): """Extract the tests from a spec file. CMAP tests do not have a 'tests' field. The whole file represents a single test case. """ return [scenario_def] test_creator = CMAPSpecTestCreator(create_test, TestCMAP, TestCMAP.TEST_PATH) test_creator.create_tests() if __name__ == "__main__": unittest.main() mongodb-mongo-python-driver-509e9b7/test/test_connections_survive_primary_stepdown_spec.py000066400000000000000000000126101462766011000326320ustar00rootroot00000000000000# Copyright 2019-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. """Test compliance with the connections survive primary step down spec.""" from __future__ import annotations import sys sys.path[0:0] = [""] from test import IntegrationTest, client_context, unittest from test.utils import ( CMAPListener, ensure_all_connected, repl_set_step_down, rs_or_single_client, ) from bson import SON from pymongo import monitoring from pymongo.collection import Collection from pymongo.errors import NotPrimaryError from pymongo.write_concern import WriteConcern class TestConnectionsSurvivePrimaryStepDown(IntegrationTest): listener: CMAPListener coll: Collection @classmethod @client_context.require_replica_set def setUpClass(cls): super().setUpClass() cls.listener = CMAPListener() cls.client = rs_or_single_client( event_listeners=[cls.listener], retryWrites=False, heartbeatFrequencyMS=500 ) # Ensure connections to all servers in replica set. This is to test # that the is_writable flag is properly updated for connections that # survive a replica set election. ensure_all_connected(cls.client) cls.listener.reset() cls.db = cls.client.get_database("step-down", write_concern=WriteConcern("majority")) cls.coll = cls.db.get_collection("step-down", write_concern=WriteConcern("majority")) @classmethod def tearDownClass(cls): cls.client.close() def setUp(self): # Note that all ops use same write-concern as self.db (majority). self.db.drop_collection("step-down") self.db.create_collection("step-down") self.listener.reset() def set_fail_point(self, command_args): cmd = SON([("configureFailPoint", "failCommand")]) cmd.update(command_args) self.client.admin.command(cmd) def verify_pool_cleared(self): self.assertEqual(self.listener.event_count(monitoring.PoolClearedEvent), 1) def verify_pool_not_cleared(self): self.assertEqual(self.listener.event_count(monitoring.PoolClearedEvent), 0) @client_context.require_version_min(4, 2, -1) def test_get_more_iteration(self): # Insert 5 documents with WC majority. self.coll.insert_many([{"data": k} for k in range(5)]) # Start a find operation and retrieve first batch of results. batch_size = 2 cursor = self.coll.find(batch_size=batch_size) for _ in range(batch_size): cursor.next() # Force step-down the primary. repl_set_step_down(self.client, replSetStepDown=5, force=True) # Get next batch of results. for _ in range(batch_size): cursor.next() # Verify pool not cleared. self.verify_pool_not_cleared() # Attempt insertion to mark server description as stale and prevent a # NotPrimaryError on the subsequent operation. try: self.coll.insert_one({}) except NotPrimaryError: pass # Next insert should succeed on the new primary without clearing pool. self.coll.insert_one({}) self.verify_pool_not_cleared() def run_scenario(self, error_code, retry, pool_status_checker): # Set fail point. self.set_fail_point( {"mode": {"times": 1}, "data": {"failCommands": ["insert"], "errorCode": error_code}} ) self.addCleanup(self.set_fail_point, {"mode": "off"}) # Insert record and verify failure. with self.assertRaises(NotPrimaryError) as exc: self.coll.insert_one({"test": 1}) self.assertEqual(exc.exception.details["code"], error_code) # type: ignore[call-overload] # Retry before CMAPListener assertion if retry_before=True. if retry: self.coll.insert_one({"test": 1}) # Verify pool cleared/not cleared. pool_status_checker() # Always retry here to ensure discovery of new primary. self.coll.insert_one({"test": 1}) @client_context.require_version_min(4, 2, -1) @client_context.require_test_commands def test_not_primary_keep_connection_pool(self): self.run_scenario(10107, True, self.verify_pool_not_cleared) @client_context.require_version_min(4, 0, 0) @client_context.require_version_max(4, 1, 0, -1) @client_context.require_test_commands def test_not_primary_reset_connection_pool(self): self.run_scenario(10107, False, self.verify_pool_cleared) @client_context.require_version_min(4, 0, 0) @client_context.require_test_commands def test_shutdown_in_progress(self): self.run_scenario(91, False, self.verify_pool_cleared) @client_context.require_version_min(4, 0, 0) @client_context.require_test_commands def test_interrupted_at_shutdown(self): self.run_scenario(11600, False, self.verify_pool_cleared) if __name__ == "__main__": unittest.main() mongodb-mongo-python-driver-509e9b7/test/test_create_entities.py000066400000000000000000000114441462766011000252000ustar00rootroot00000000000000# Copyright 2021-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. from __future__ import annotations import sys import unittest sys.path[0:0] = [""] from test import IntegrationTest from test.unified_format import UnifiedSpecTestMixinV1 class TestCreateEntities(IntegrationTest): def test_store_events_as_entities(self): self.scenario_runner = UnifiedSpecTestMixinV1() spec = { "description": "blank", "schemaVersion": "1.2", "createEntities": [ { "client": { "id": "client0", "storeEventsAsEntities": [ { "id": "events1", "events": [ "PoolCreatedEvent", ], } ], } }, ], "tests": [{"description": "foo", "operations": []}], } self.scenario_runner.TEST_SPEC = spec self.scenario_runner.setUp() self.scenario_runner.run_scenario(spec["tests"][0]) self.scenario_runner.entity_map["client0"].close() final_entity_map = self.scenario_runner.entity_map self.assertIn("events1", final_entity_map) self.assertGreater(len(final_entity_map["events1"]), 0) for event in final_entity_map["events1"]: self.assertIn("PoolCreatedEvent", event["name"]) def test_store_all_others_as_entities(self): self.scenario_runner = UnifiedSpecTestMixinV1() spec = { "description": "Find", "schemaVersion": "1.2", "createEntities": [ { "client": { "id": "client0", "uriOptions": {"retryReads": True}, } }, {"database": {"id": "database0", "client": "client0", "databaseName": "dat"}}, { "collection": { "id": "collection0", "database": "database0", "collectionName": "dat", } }, ], "tests": [ { "description": "test loops", "operations": [ { "name": "loop", "object": "testRunner", "arguments": { "storeIterationsAsEntity": "iterations", "storeSuccessesAsEntity": "successes", "storeFailuresAsEntity": "failures", "storeErrorsAsEntity": "errors", "numIterations": 5, "operations": [ { "name": "insertOne", "object": "collection0", "arguments": {"document": {"_id": 1, "x": 44}}, }, { "name": "insertOne", "object": "collection0", "arguments": {"document": {"_id": 2, "x": 44}}, }, ], }, } ], } ], } self.client.dat.dat.delete_many({}) self.scenario_runner.TEST_SPEC = spec self.scenario_runner.setUp() self.scenario_runner.run_scenario(spec["tests"][0]) self.scenario_runner.entity_map["client0"].close() entity_map = self.scenario_runner.entity_map self.assertEqual(len(entity_map["errors"]), 4) for error in entity_map["errors"]: self.assertEqual(error["type"], "DuplicateKeyError") self.assertEqual(entity_map["failures"], []) self.assertEqual(entity_map["successes"], 2) self.assertEqual(entity_map["iterations"], 5) if __name__ == "__main__": unittest.main() mongodb-mongo-python-driver-509e9b7/test/test_crud_unified.py000066400000000000000000000020671462766011000244720ustar00rootroot00000000000000# Copyright 2021-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. """Test the CRUD unified spec tests.""" from __future__ import annotations import os import sys sys.path[0:0] = [""] from test import unittest from test.unified_format import generate_test_classes # Location of JSON test specifications. TEST_PATH = os.path.join(os.path.dirname(os.path.realpath(__file__)), "crud", "unified") # Generate unified tests. globals().update(generate_test_classes(TEST_PATH, module=__name__, RUN_ON_SERVERLESS=True)) if __name__ == "__main__": unittest.main() mongodb-mongo-python-driver-509e9b7/test/test_crud_v1.py000066400000000000000000000242021462766011000233700ustar00rootroot00000000000000# Copyright 2015-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. """Test the collection module.""" from __future__ import annotations import os import sys sys.path[0:0] = [""] from test import IntegrationTest, unittest from test.utils import ( SpecTestCreator, camel_to_snake, camel_to_snake_args, camel_to_upper_camel, drop_collections, ) from pymongo import WriteConcern, operations from pymongo.command_cursor import CommandCursor from pymongo.cursor import Cursor from pymongo.errors import PyMongoError from pymongo.operations import ( DeleteMany, DeleteOne, InsertOne, ReplaceOne, UpdateMany, UpdateOne, ) from pymongo.read_concern import ReadConcern from pymongo.results import BulkWriteResult, _WriteResult # Location of JSON test specifications. _TEST_PATH = os.path.join(os.path.dirname(os.path.realpath(__file__)), "crud", "v1") class TestAllScenarios(IntegrationTest): RUN_ON_SERVERLESS = True def check_result(self, expected_result, result): if isinstance(result, _WriteResult): for res in expected_result: prop = camel_to_snake(res) msg = f"{prop} : {expected_result!r} != {result!r}" # SPEC-869: Only BulkWriteResult has upserted_count. if prop == "upserted_count" and not isinstance(result, BulkWriteResult): if result.upserted_id is not None: # type: ignore upserted_count = 1 else: upserted_count = 0 self.assertEqual(upserted_count, expected_result[res], msg) elif prop == "inserted_ids": # BulkWriteResult does not have inserted_ids. if isinstance(result, BulkWriteResult): self.assertEqual(len(expected_result[res]), result.inserted_count) else: # InsertManyResult may be compared to [id1] from the # crud spec or {"0": id1} from the retryable write spec. ids = expected_result[res] if isinstance(ids, dict): ids = [ids[str(i)] for i in range(len(ids))] self.assertEqual(ids, result.inserted_ids, msg) # type: ignore elif prop == "upserted_ids": # Convert indexes from strings to integers. ids = expected_result[res] expected_ids = {} for str_index in ids: expected_ids[int(str_index)] = ids[str_index] self.assertEqual(expected_ids, result.upserted_ids, msg) # type: ignore else: self.assertEqual(getattr(result, prop), expected_result[res], msg) else: self.assertEqual(result, expected_result) def run_operation(collection, test): # Convert command from CamelCase to pymongo.collection method. operation = camel_to_snake(test["operation"]["name"]) cmd = getattr(collection, operation) # Convert arguments to snake_case and handle special cases. arguments = test["operation"]["arguments"] options = arguments.pop("options", {}) for option_name in options: arguments[camel_to_snake(option_name)] = options[option_name] if operation == "count": raise unittest.SkipTest("PyMongo does not support count") if operation == "bulk_write": # Parse each request into a bulk write model. requests = [] for request in arguments["requests"]: bulk_model = camel_to_upper_camel(request["name"]) bulk_class = getattr(operations, bulk_model) bulk_arguments = camel_to_snake_args(request["arguments"]) requests.append(bulk_class(**bulk_arguments)) arguments["requests"] = requests else: for arg_name in list(arguments): c2s = camel_to_snake(arg_name) # PyMongo accepts sort as list of tuples. if arg_name == "sort": sort_dict = arguments[arg_name] arguments[arg_name] = list(sort_dict.items()) # Named "key" instead not fieldName. if arg_name == "fieldName": arguments["key"] = arguments.pop(arg_name) # Aggregate uses "batchSize", while find uses batch_size. elif arg_name == "batchSize" and operation == "aggregate": continue # Requires boolean returnDocument. elif arg_name == "returnDocument": arguments[c2s] = arguments.pop(arg_name) == "After" else: arguments[c2s] = arguments.pop(arg_name) result = cmd(**arguments) if isinstance(result, Cursor) or isinstance(result, CommandCursor): return list(result) return result def create_test(scenario_def, test, name): def run_scenario(self): # Cleanup state and load data (if provided). drop_collections(self.db) data = scenario_def.get("data") if data: self.db.test.with_options(write_concern=WriteConcern(w="majority")).insert_many( scenario_def["data"] ) # Run operations and check results or errors. expected_result = test.get("outcome", {}).get("result") expected_error = test.get("outcome", {}).get("error") if expected_error is True: with self.assertRaises(PyMongoError): run_operation(self.db.test, test) else: result = run_operation(self.db.test, test) if expected_result is not None: check_result(self, expected_result, result) # Assert final state is expected. expected_c = test["outcome"].get("collection") if expected_c is not None: expected_name = expected_c.get("name") if expected_name is not None: db_coll = self.db[expected_name] else: db_coll = self.db.test db_coll = db_coll.with_options(read_concern=ReadConcern(level="local")) self.assertEqual(list(db_coll.find()), expected_c["data"]) return run_scenario test_creator = SpecTestCreator(create_test, TestAllScenarios, _TEST_PATH) test_creator.create_tests() class TestWriteOpsComparison(unittest.TestCase): def test_InsertOneEquals(self): self.assertEqual(InsertOne({"foo": 42}), InsertOne({"foo": 42})) def test_InsertOneNotEquals(self): self.assertNotEqual(InsertOne({"foo": 42}), InsertOne({"foo": 23})) def test_DeleteOneEquals(self): self.assertEqual(DeleteOne({"foo": 42}), DeleteOne({"foo": 42})) self.assertEqual( DeleteOne({"foo": 42}, {"locale": "en_US"}), DeleteOne({"foo": 42}, {"locale": "en_US"}) ) self.assertEqual( DeleteOne({"foo": 42}, {"locale": "en_US"}, {"hint": 1}), DeleteOne({"foo": 42}, {"locale": "en_US"}, {"hint": 1}), ) def test_DeleteOneNotEquals(self): self.assertNotEqual(DeleteOne({"foo": 42}), DeleteOne({"foo": 23})) self.assertNotEqual( DeleteOne({"foo": 42}, {"locale": "en_US"}), DeleteOne({"foo": 42}, {"locale": "en_GB"}) ) self.assertNotEqual( DeleteOne({"foo": 42}, {"locale": "en_US"}, {"hint": 1}), DeleteOne({"foo": 42}, {"locale": "en_US"}, {"hint": 2}), ) def test_DeleteManyEquals(self): self.assertEqual(DeleteMany({"foo": 42}), DeleteMany({"foo": 42})) self.assertEqual( DeleteMany({"foo": 42}, {"locale": "en_US"}), DeleteMany({"foo": 42}, {"locale": "en_US"}), ) self.assertEqual( DeleteMany({"foo": 42}, {"locale": "en_US"}, {"hint": 1}), DeleteMany({"foo": 42}, {"locale": "en_US"}, {"hint": 1}), ) def test_DeleteManyNotEquals(self): self.assertNotEqual(DeleteMany({"foo": 42}), DeleteMany({"foo": 23})) self.assertNotEqual( DeleteMany({"foo": 42}, {"locale": "en_US"}), DeleteMany({"foo": 42}, {"locale": "en_GB"}), ) self.assertNotEqual( DeleteMany({"foo": 42}, {"locale": "en_US"}, {"hint": 1}), DeleteMany({"foo": 42}, {"locale": "en_US"}, {"hint": 2}), ) def test_DeleteOneNotEqualsDeleteMany(self): self.assertNotEqual(DeleteOne({"foo": 42}), DeleteMany({"foo": 42})) def test_ReplaceOneEquals(self): self.assertEqual( ReplaceOne({"foo": 42}, {"bar": 42}, upsert=False), ReplaceOne({"foo": 42}, {"bar": 42}, upsert=False), ) def test_ReplaceOneNotEquals(self): self.assertNotEqual( ReplaceOne({"foo": 42}, {"bar": 42}, upsert=False), ReplaceOne({"foo": 42}, {"bar": 42}, upsert=True), ) def test_UpdateOneEquals(self): self.assertEqual( UpdateOne({"foo": 42}, {"$set": {"bar": 42}}), UpdateOne({"foo": 42}, {"$set": {"bar": 42}}), ) def test_UpdateOneNotEquals(self): self.assertNotEqual( UpdateOne({"foo": 42}, {"$set": {"bar": 42}}), UpdateOne({"foo": 42}, {"$set": {"bar": 23}}), ) def test_UpdateManyEquals(self): self.assertEqual( UpdateMany({"foo": 42}, {"$set": {"bar": 42}}), UpdateMany({"foo": 42}, {"$set": {"bar": 42}}), ) def test_UpdateManyNotEquals(self): self.assertNotEqual( UpdateMany({"foo": 42}, {"$set": {"bar": 42}}), UpdateMany({"foo": 42}, {"$set": {"bar": 23}}), ) def test_UpdateOneNotEqualsUpdateMany(self): self.assertNotEqual( UpdateOne({"foo": 42}, {"$set": {"bar": 42}}), UpdateMany({"foo": 42}, {"$set": {"bar": 42}}), ) if __name__ == "__main__": unittest.main() mongodb-mongo-python-driver-509e9b7/test/test_csot.py000066400000000000000000000076121462766011000230030ustar00rootroot00000000000000# Copyright 2022-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. """Test the CSOT unified spec tests.""" from __future__ import annotations import os import sys sys.path[0:0] = [""] from test import IntegrationTest, client_context, unittest from test.unified_format import generate_test_classes import pymongo from pymongo import _csot from pymongo.errors import PyMongoError # Location of JSON test specifications. TEST_PATH = os.path.join(os.path.dirname(os.path.realpath(__file__)), "csot") # Generate unified tests. globals().update(generate_test_classes(TEST_PATH, module=__name__)) class TestCSOT(IntegrationTest): RUN_ON_SERVERLESS = True RUN_ON_LOAD_BALANCER = True def test_timeout_nested(self): coll = self.db.coll self.assertEqual(_csot.get_timeout(), None) self.assertEqual(_csot.get_deadline(), float("inf")) self.assertEqual(_csot.get_rtt(), 0.0) with pymongo.timeout(10): coll.find_one() self.assertEqual(_csot.get_timeout(), 10) deadline_10 = _csot.get_deadline() # Capped at the original 10 deadline. with pymongo.timeout(15): coll.find_one() self.assertEqual(_csot.get_timeout(), 15) self.assertEqual(_csot.get_deadline(), deadline_10) # Should be reset to previous values self.assertEqual(_csot.get_timeout(), 10) self.assertEqual(_csot.get_deadline(), deadline_10) coll.find_one() with pymongo.timeout(5): coll.find_one() self.assertEqual(_csot.get_timeout(), 5) self.assertLess(_csot.get_deadline(), deadline_10) # Should be reset to previous values self.assertEqual(_csot.get_timeout(), 10) self.assertEqual(_csot.get_deadline(), deadline_10) coll.find_one() # Should be reset to previous values self.assertEqual(_csot.get_timeout(), None) self.assertEqual(_csot.get_deadline(), float("inf")) self.assertEqual(_csot.get_rtt(), 0.0) @client_context.require_change_streams def test_change_stream_can_resume_after_timeouts(self): coll = self.db.test with coll.watch() as stream: with pymongo.timeout(0.1): with self.assertRaises(PyMongoError) as ctx: stream.next() self.assertTrue(ctx.exception.timeout) self.assertTrue(stream.alive) with self.assertRaises(PyMongoError) as ctx: stream.try_next() self.assertTrue(ctx.exception.timeout) self.assertTrue(stream.alive) # Resume before the insert on 3.6 because 4.0 is required to avoid skipping documents if client_context.version < (4, 0): stream.try_next() coll.insert_one({}) with pymongo.timeout(10): self.assertTrue(stream.next()) self.assertTrue(stream.alive) # Timeout applies to entire next() call, not only individual commands. with pymongo.timeout(0.5): with self.assertRaises(PyMongoError) as ctx: stream.next() self.assertTrue(ctx.exception.timeout) self.assertTrue(stream.alive) self.assertFalse(stream.alive) if __name__ == "__main__": unittest.main() mongodb-mongo-python-driver-509e9b7/test/test_cursor.py000066400000000000000000001730321462766011000233500ustar00rootroot00000000000000# Copyright 2009-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. """Test the cursor module.""" from __future__ import annotations import copy import gc import itertools import random import re import sys import threading import time from typing import Any import pymongo sys.path[0:0] = [""] from test import IntegrationTest, client_context, unittest from test.utils import ( AllowListEventListener, EventListener, OvertCommandListener, ignore_deprecations, rs_or_single_client, wait_until, ) from bson import decode_all from bson.code import Code from bson.son import SON from pymongo import ASCENDING, DESCENDING from pymongo.collation import Collation from pymongo.cursor import Cursor, CursorType from pymongo.errors import ExecutionTimeout, InvalidOperation, OperationFailure from pymongo.operations import _IndexList from pymongo.read_concern import ReadConcern from pymongo.read_preferences import ReadPreference from pymongo.write_concern import WriteConcern class TestCursor(IntegrationTest): def test_deepcopy_cursor_littered_with_regexes(self): cursor = self.db.test.find( { "x": re.compile("^hmmm.*"), "y": [re.compile("^hmm.*")], "z": {"a": [re.compile("^hm.*")]}, re.compile("^key.*"): {"a": [re.compile("^hm.*")]}, } ) cursor2 = copy.deepcopy(cursor) self.assertEqual(cursor._Cursor__spec, cursor2._Cursor__spec) # type: ignore def test_add_remove_option(self): cursor = self.db.test.find() self.assertEqual(0, cursor._Cursor__query_flags) cursor.add_option(2) cursor2 = self.db.test.find(cursor_type=CursorType.TAILABLE) self.assertEqual(2, cursor2._Cursor__query_flags) self.assertEqual(cursor._Cursor__query_flags, cursor2._Cursor__query_flags) cursor.add_option(32) cursor2 = self.db.test.find(cursor_type=CursorType.TAILABLE_AWAIT) self.assertEqual(34, cursor2._Cursor__query_flags) self.assertEqual(cursor._Cursor__query_flags, cursor2._Cursor__query_flags) cursor.add_option(128) cursor2 = self.db.test.find(cursor_type=CursorType.TAILABLE_AWAIT).add_option(128) self.assertEqual(162, cursor2._Cursor__query_flags) self.assertEqual(cursor._Cursor__query_flags, cursor2._Cursor__query_flags) self.assertEqual(162, cursor._Cursor__query_flags) cursor.add_option(128) self.assertEqual(162, cursor._Cursor__query_flags) cursor.remove_option(128) cursor2 = self.db.test.find(cursor_type=CursorType.TAILABLE_AWAIT) self.assertEqual(34, cursor2._Cursor__query_flags) self.assertEqual(cursor._Cursor__query_flags, cursor2._Cursor__query_flags) cursor.remove_option(32) cursor2 = self.db.test.find(cursor_type=CursorType.TAILABLE) self.assertEqual(2, cursor2._Cursor__query_flags) self.assertEqual(cursor._Cursor__query_flags, cursor2._Cursor__query_flags) self.assertEqual(2, cursor._Cursor__query_flags) cursor.remove_option(32) self.assertEqual(2, cursor._Cursor__query_flags) # Timeout cursor = self.db.test.find(no_cursor_timeout=True) self.assertEqual(16, cursor._Cursor__query_flags) cursor2 = self.db.test.find().add_option(16) self.assertEqual(cursor._Cursor__query_flags, cursor2._Cursor__query_flags) cursor.remove_option(16) self.assertEqual(0, cursor._Cursor__query_flags) # Tailable / Await data cursor = self.db.test.find(cursor_type=CursorType.TAILABLE_AWAIT) self.assertEqual(34, cursor._Cursor__query_flags) cursor2 = self.db.test.find().add_option(34) self.assertEqual(cursor._Cursor__query_flags, cursor2._Cursor__query_flags) cursor.remove_option(32) self.assertEqual(2, cursor._Cursor__query_flags) # Partial cursor = self.db.test.find(allow_partial_results=True) self.assertEqual(128, cursor._Cursor__query_flags) cursor2 = self.db.test.find().add_option(128) self.assertEqual(cursor._Cursor__query_flags, cursor2._Cursor__query_flags) cursor.remove_option(128) self.assertEqual(0, cursor._Cursor__query_flags) def test_add_remove_option_exhaust(self): # Exhaust - which mongos doesn't support if client_context.is_mongos: with self.assertRaises(InvalidOperation): self.db.test.find(cursor_type=CursorType.EXHAUST) else: cursor = self.db.test.find(cursor_type=CursorType.EXHAUST) self.assertEqual(64, cursor._Cursor__query_flags) cursor2 = self.db.test.find().add_option(64) self.assertEqual(cursor._Cursor__query_flags, cursor2._Cursor__query_flags) self.assertTrue(cursor._Cursor__exhaust) cursor.remove_option(64) self.assertEqual(0, cursor._Cursor__query_flags) self.assertFalse(cursor._Cursor__exhaust) def test_allow_disk_use(self): db = self.db db.pymongo_test.drop() coll = db.pymongo_test self.assertRaises(TypeError, coll.find().allow_disk_use, "baz") cursor = coll.find().allow_disk_use(True) self.assertEqual(True, cursor._Cursor__allow_disk_use) # type: ignore cursor = coll.find().allow_disk_use(False) self.assertEqual(False, cursor._Cursor__allow_disk_use) # type: ignore def test_max_time_ms(self): db = self.db db.pymongo_test.drop() coll = db.pymongo_test self.assertRaises(TypeError, coll.find().max_time_ms, "foo") coll.insert_one({"amalia": 1}) coll.insert_one({"amalia": 2}) coll.find().max_time_ms(None) coll.find().max_time_ms(1) cursor = coll.find().max_time_ms(999) self.assertEqual(999, cursor._Cursor__max_time_ms) # type: ignore cursor = coll.find().max_time_ms(10).max_time_ms(1000) self.assertEqual(1000, cursor._Cursor__max_time_ms) # type: ignore cursor = coll.find().max_time_ms(999) c2 = cursor.clone() self.assertEqual(999, c2._Cursor__max_time_ms) # type: ignore self.assertTrue("$maxTimeMS" in cursor._Cursor__query_spec()) # type: ignore self.assertTrue("$maxTimeMS" in c2._Cursor__query_spec()) # type: ignore self.assertTrue(coll.find_one(max_time_ms=1000)) client = self.client if not client_context.is_mongos and client_context.test_commands_enabled: # Cursor parses server timeout error in response to initial query. client.admin.command("configureFailPoint", "maxTimeAlwaysTimeOut", mode="alwaysOn") try: cursor = coll.find().max_time_ms(1) try: next(cursor) except ExecutionTimeout: pass else: self.fail("ExecutionTimeout not raised") self.assertRaises(ExecutionTimeout, coll.find_one, max_time_ms=1) finally: client.admin.command("configureFailPoint", "maxTimeAlwaysTimeOut", mode="off") def test_max_await_time_ms(self): db = self.db db.pymongo_test.drop() coll = db.create_collection("pymongo_test", capped=True, size=4096) self.assertRaises(TypeError, coll.find().max_await_time_ms, "foo") coll.insert_one({"amalia": 1}) coll.insert_one({"amalia": 2}) coll.find().max_await_time_ms(None) coll.find().max_await_time_ms(1) # When cursor is not tailable_await cursor = coll.find() self.assertEqual(None, cursor._Cursor__max_await_time_ms) cursor = coll.find().max_await_time_ms(99) self.assertEqual(None, cursor._Cursor__max_await_time_ms) # If cursor is tailable_await and timeout is unset cursor = coll.find(cursor_type=CursorType.TAILABLE_AWAIT) self.assertEqual(None, cursor._Cursor__max_await_time_ms) # If cursor is tailable_await and timeout is set cursor = coll.find(cursor_type=CursorType.TAILABLE_AWAIT).max_await_time_ms(99) self.assertEqual(99, cursor._Cursor__max_await_time_ms) cursor = ( coll.find(cursor_type=CursorType.TAILABLE_AWAIT) .max_await_time_ms(10) .max_await_time_ms(90) ) self.assertEqual(90, cursor._Cursor__max_await_time_ms) listener = AllowListEventListener("find", "getMore") coll = rs_or_single_client(event_listeners=[listener])[self.db.name].pymongo_test # Tailable_await defaults. list(coll.find(cursor_type=CursorType.TAILABLE_AWAIT)) # find self.assertFalse("maxTimeMS" in listener.started_events[0].command) # getMore self.assertFalse("maxTimeMS" in listener.started_events[1].command) listener.reset() # Tailable_await with max_await_time_ms set. list(coll.find(cursor_type=CursorType.TAILABLE_AWAIT).max_await_time_ms(99)) # find self.assertEqual("find", listener.started_events[0].command_name) self.assertFalse("maxTimeMS" in listener.started_events[0].command) # getMore self.assertEqual("getMore", listener.started_events[1].command_name) self.assertTrue("maxTimeMS" in listener.started_events[1].command) self.assertEqual(99, listener.started_events[1].command["maxTimeMS"]) listener.reset() # Tailable_await with max_time_ms list(coll.find(cursor_type=CursorType.TAILABLE_AWAIT).max_time_ms(99)) # find self.assertEqual("find", listener.started_events[0].command_name) self.assertTrue("maxTimeMS" in listener.started_events[0].command) self.assertEqual(99, listener.started_events[0].command["maxTimeMS"]) # getMore self.assertEqual("getMore", listener.started_events[1].command_name) self.assertFalse("maxTimeMS" in listener.started_events[1].command) listener.reset() # Tailable_await with both max_time_ms and max_await_time_ms list(coll.find(cursor_type=CursorType.TAILABLE_AWAIT).max_time_ms(99).max_await_time_ms(99)) # find self.assertEqual("find", listener.started_events[0].command_name) self.assertTrue("maxTimeMS" in listener.started_events[0].command) self.assertEqual(99, listener.started_events[0].command["maxTimeMS"]) # getMore self.assertEqual("getMore", listener.started_events[1].command_name) self.assertTrue("maxTimeMS" in listener.started_events[1].command) self.assertEqual(99, listener.started_events[1].command["maxTimeMS"]) listener.reset() # Non tailable_await with max_await_time_ms list(coll.find(batch_size=1).max_await_time_ms(99)) # find self.assertEqual("find", listener.started_events[0].command_name) self.assertFalse("maxTimeMS" in listener.started_events[0].command) # getMore self.assertEqual("getMore", listener.started_events[1].command_name) self.assertFalse("maxTimeMS" in listener.started_events[1].command) listener.reset() # Non tailable_await with max_time_ms list(coll.find(batch_size=1).max_time_ms(99)) # find self.assertEqual("find", listener.started_events[0].command_name) self.assertTrue("maxTimeMS" in listener.started_events[0].command) self.assertEqual(99, listener.started_events[0].command["maxTimeMS"]) # getMore self.assertEqual("getMore", listener.started_events[1].command_name) self.assertFalse("maxTimeMS" in listener.started_events[1].command) # Non tailable_await with both max_time_ms and max_await_time_ms list(coll.find(batch_size=1).max_time_ms(99).max_await_time_ms(88)) # find self.assertEqual("find", listener.started_events[0].command_name) self.assertTrue("maxTimeMS" in listener.started_events[0].command) self.assertEqual(99, listener.started_events[0].command["maxTimeMS"]) # getMore self.assertEqual("getMore", listener.started_events[1].command_name) self.assertFalse("maxTimeMS" in listener.started_events[1].command) @client_context.require_test_commands @client_context.require_no_mongos def test_max_time_ms_getmore(self): # Test that Cursor handles server timeout error in response to getmore. coll = self.db.pymongo_test coll.insert_many([{} for _ in range(200)]) cursor = coll.find().max_time_ms(100) # Send initial query before turning on failpoint. next(cursor) self.client.admin.command("configureFailPoint", "maxTimeAlwaysTimeOut", mode="alwaysOn") try: try: # Iterate up to first getmore. list(cursor) except ExecutionTimeout: pass else: self.fail("ExecutionTimeout not raised") finally: self.client.admin.command("configureFailPoint", "maxTimeAlwaysTimeOut", mode="off") def test_explain(self): a = self.db.test.find() a.explain() for _ in a: break b = a.explain() self.assertIn("executionStats", b) def test_explain_with_read_concern(self): # Do not add readConcern level to explain. listener = AllowListEventListener("explain") client = rs_or_single_client(event_listeners=[listener]) self.addCleanup(client.close) coll = client.pymongo_test.test.with_options(read_concern=ReadConcern(level="local")) self.assertTrue(coll.find().explain()) started = listener.started_events self.assertEqual(len(started), 1) self.assertNotIn("readConcern", started[0].command) def test_hint(self): db = self.db self.assertRaises(TypeError, db.test.find().hint, 5.5) db.test.drop() db.test.insert_many([{"num": i, "foo": i} for i in range(100)]) self.assertRaises( OperationFailure, db.test.find({"num": 17, "foo": 17}).hint([("num", ASCENDING)]).explain, ) self.assertRaises( OperationFailure, db.test.find({"num": 17, "foo": 17}).hint([("foo", ASCENDING)]).explain, ) spec: list[Any] = [("num", DESCENDING)] _ = db.test.create_index(spec) first = next(db.test.find()) self.assertEqual(0, first.get("num")) first = next(db.test.find().hint(spec)) self.assertEqual(99, first.get("num")) self.assertRaises( OperationFailure, db.test.find({"num": 17, "foo": 17}).hint([("foo", ASCENDING)]).explain, ) a = db.test.find({"num": 17}) a.hint(spec) for _ in a: break self.assertRaises(InvalidOperation, a.hint, spec) db.test.drop() db.test.insert_many([{"num": i, "foo": i} for i in range(100)]) spec: _IndexList = ["num", ("foo", DESCENDING)] db.test.create_index(spec) first = next(db.test.find().hint(spec)) self.assertEqual(0, first.get("num")) self.assertEqual(0, first.get("foo")) db.test.drop() db.test.insert_many([{"num": i, "foo": i} for i in range(100)]) spec = ["num"] db.test.create_index(spec) first = next(db.test.find().hint(spec)) self.assertEqual(0, first.get("num")) def test_hint_by_name(self): db = self.db db.test.drop() db.test.insert_many([{"i": i} for i in range(100)]) db.test.create_index([("i", DESCENDING)], name="fooindex") first = next(db.test.find()) self.assertEqual(0, first.get("i")) first = next(db.test.find().hint("fooindex")) self.assertEqual(99, first.get("i")) def test_limit(self): db = self.db self.assertRaises(TypeError, db.test.find().limit, None) self.assertRaises(TypeError, db.test.find().limit, "hello") self.assertRaises(TypeError, db.test.find().limit, 5.5) self.assertTrue(db.test.find().limit(5)) db.test.drop() db.test.insert_many([{"x": i} for i in range(100)]) count = 0 for _ in db.test.find(): count += 1 self.assertEqual(count, 100) count = 0 for _ in db.test.find().limit(20): count += 1 self.assertEqual(count, 20) count = 0 for _ in db.test.find().limit(99): count += 1 self.assertEqual(count, 99) count = 0 for _ in db.test.find().limit(1): count += 1 self.assertEqual(count, 1) count = 0 for _ in db.test.find().limit(0): count += 1 self.assertEqual(count, 100) count = 0 for _ in db.test.find().limit(0).limit(50).limit(10): count += 1 self.assertEqual(count, 10) a = db.test.find() a.limit(10) for _ in a: break self.assertRaises(InvalidOperation, a.limit, 5) def test_max(self): db = self.db db.test.drop() j_index = [("j", ASCENDING)] db.test.create_index(j_index) db.test.insert_many([{"j": j, "k": j} for j in range(10)]) def find(max_spec, expected_index): return db.test.find().max(max_spec).hint(expected_index) cursor = find([("j", 3)], j_index) self.assertEqual(len(list(cursor)), 3) # Tuple. cursor = find((("j", 3),), j_index) self.assertEqual(len(list(cursor)), 3) # Compound index. index_keys = [("j", ASCENDING), ("k", ASCENDING)] db.test.create_index(index_keys) cursor = find([("j", 3), ("k", 3)], index_keys) self.assertEqual(len(list(cursor)), 3) # Wrong order. cursor = find([("k", 3), ("j", 3)], index_keys) self.assertRaises(OperationFailure, list, cursor) # No such index. cursor = find([("k", 3)], "k") self.assertRaises(OperationFailure, list, cursor) self.assertRaises(TypeError, db.test.find().max, 10) self.assertRaises(TypeError, db.test.find().max, {"j": 10}) def test_min(self): db = self.db db.test.drop() j_index = [("j", ASCENDING)] db.test.create_index(j_index) db.test.insert_many([{"j": j, "k": j} for j in range(10)]) def find(min_spec, expected_index): return db.test.find().min(min_spec).hint(expected_index) cursor = find([("j", 3)], j_index) self.assertEqual(len(list(cursor)), 7) # Tuple. cursor = find((("j", 3),), j_index) self.assertEqual(len(list(cursor)), 7) # Compound index. index_keys = [("j", ASCENDING), ("k", ASCENDING)] db.test.create_index(index_keys) cursor = find([("j", 3), ("k", 3)], index_keys) self.assertEqual(len(list(cursor)), 7) # Wrong order. cursor = find([("k", 3), ("j", 3)], index_keys) self.assertRaises(OperationFailure, list, cursor) # No such index. cursor = find([("k", 3)], "k") self.assertRaises(OperationFailure, list, cursor) self.assertRaises(TypeError, db.test.find().min, 10) self.assertRaises(TypeError, db.test.find().min, {"j": 10}) def test_min_max_without_hint(self): coll = self.db.test j_index = [("j", ASCENDING)] coll.create_index(j_index) with self.assertRaises(InvalidOperation): list(coll.find().min([("j", 3)])) with self.assertRaises(InvalidOperation): list(coll.find().max([("j", 3)])) def test_batch_size(self): db = self.db db.test.drop() db.test.insert_many([{"x": x} for x in range(200)]) self.assertRaises(TypeError, db.test.find().batch_size, None) self.assertRaises(TypeError, db.test.find().batch_size, "hello") self.assertRaises(TypeError, db.test.find().batch_size, 5.5) self.assertRaises(ValueError, db.test.find().batch_size, -1) self.assertTrue(db.test.find().batch_size(5)) a = db.test.find() for _ in a: break self.assertRaises(InvalidOperation, a.batch_size, 5) def cursor_count(cursor, expected_count): count = 0 for _ in cursor: count += 1 self.assertEqual(expected_count, count) cursor_count(db.test.find().batch_size(0), 200) cursor_count(db.test.find().batch_size(1), 200) cursor_count(db.test.find().batch_size(2), 200) cursor_count(db.test.find().batch_size(5), 200) cursor_count(db.test.find().batch_size(100), 200) cursor_count(db.test.find().batch_size(500), 200) cursor_count(db.test.find().batch_size(0).limit(1), 1) cursor_count(db.test.find().batch_size(1).limit(1), 1) cursor_count(db.test.find().batch_size(2).limit(1), 1) cursor_count(db.test.find().batch_size(5).limit(1), 1) cursor_count(db.test.find().batch_size(100).limit(1), 1) cursor_count(db.test.find().batch_size(500).limit(1), 1) cursor_count(db.test.find().batch_size(0).limit(10), 10) cursor_count(db.test.find().batch_size(1).limit(10), 10) cursor_count(db.test.find().batch_size(2).limit(10), 10) cursor_count(db.test.find().batch_size(5).limit(10), 10) cursor_count(db.test.find().batch_size(100).limit(10), 10) cursor_count(db.test.find().batch_size(500).limit(10), 10) cur = db.test.find().batch_size(1) next(cur) # find command batchSize should be 1 self.assertEqual(0, len(cur._Cursor__data)) next(cur) self.assertEqual(0, len(cur._Cursor__data)) next(cur) self.assertEqual(0, len(cur._Cursor__data)) next(cur) self.assertEqual(0, len(cur._Cursor__data)) def test_limit_and_batch_size(self): db = self.db db.test.drop() db.test.insert_many([{"x": x} for x in range(500)]) curs = db.test.find().limit(0).batch_size(10) next(curs) self.assertEqual(10, curs._Cursor__retrieved) curs = db.test.find(limit=0, batch_size=10) next(curs) self.assertEqual(10, curs._Cursor__retrieved) curs = db.test.find().limit(-2).batch_size(0) next(curs) self.assertEqual(2, curs._Cursor__retrieved) curs = db.test.find(limit=-2, batch_size=0) next(curs) self.assertEqual(2, curs._Cursor__retrieved) curs = db.test.find().limit(-4).batch_size(5) next(curs) self.assertEqual(4, curs._Cursor__retrieved) curs = db.test.find(limit=-4, batch_size=5) next(curs) self.assertEqual(4, curs._Cursor__retrieved) curs = db.test.find().limit(50).batch_size(500) next(curs) self.assertEqual(50, curs._Cursor__retrieved) curs = db.test.find(limit=50, batch_size=500) next(curs) self.assertEqual(50, curs._Cursor__retrieved) curs = db.test.find().batch_size(500) next(curs) self.assertEqual(500, curs._Cursor__retrieved) curs = db.test.find(batch_size=500) next(curs) self.assertEqual(500, curs._Cursor__retrieved) curs = db.test.find().limit(50) next(curs) self.assertEqual(50, curs._Cursor__retrieved) curs = db.test.find(limit=50) next(curs) self.assertEqual(50, curs._Cursor__retrieved) # these two might be shaky, as the default # is set by the server. as of 2.0.0-rc0, 101 # or 1MB (whichever is smaller) is default # for queries without ntoreturn curs = db.test.find() next(curs) self.assertEqual(101, curs._Cursor__retrieved) curs = db.test.find().limit(0).batch_size(0) next(curs) self.assertEqual(101, curs._Cursor__retrieved) curs = db.test.find(limit=0, batch_size=0) next(curs) self.assertEqual(101, curs._Cursor__retrieved) def test_skip(self): db = self.db self.assertRaises(TypeError, db.test.find().skip, None) self.assertRaises(TypeError, db.test.find().skip, "hello") self.assertRaises(TypeError, db.test.find().skip, 5.5) self.assertRaises(ValueError, db.test.find().skip, -5) self.assertTrue(db.test.find().skip(5)) db.drop_collection("test") db.test.insert_many([{"x": i} for i in range(100)]) for i in db.test.find(): self.assertEqual(i["x"], 0) break for i in db.test.find().skip(20): self.assertEqual(i["x"], 20) break for i in db.test.find().skip(99): self.assertEqual(i["x"], 99) break for i in db.test.find().skip(1): self.assertEqual(i["x"], 1) break for i in db.test.find().skip(0): self.assertEqual(i["x"], 0) break for i in db.test.find().skip(0).skip(50).skip(10): self.assertEqual(i["x"], 10) break for i in db.test.find().skip(1000): self.fail() a = db.test.find() a.skip(10) for _ in a: break self.assertRaises(InvalidOperation, a.skip, 5) def test_sort(self): db = self.db self.assertRaises(TypeError, db.test.find().sort, 5) self.assertRaises(ValueError, db.test.find().sort, []) self.assertRaises(TypeError, db.test.find().sort, [], ASCENDING) self.assertRaises(TypeError, db.test.find().sort, [("hello", DESCENDING)], DESCENDING) db.test.drop() unsort = list(range(10)) random.shuffle(unsort) db.test.insert_many([{"x": i} for i in unsort]) asc = [i["x"] for i in db.test.find().sort("x", ASCENDING)] self.assertEqual(asc, list(range(10))) asc = [i["x"] for i in db.test.find().sort("x")] self.assertEqual(asc, list(range(10))) asc = [i["x"] for i in db.test.find().sort([("x", ASCENDING)])] self.assertEqual(asc, list(range(10))) expect = list(reversed(range(10))) desc = [i["x"] for i in db.test.find().sort("x", DESCENDING)] self.assertEqual(desc, expect) desc = [i["x"] for i in db.test.find().sort([("x", DESCENDING)])] self.assertEqual(desc, expect) desc = [i["x"] for i in db.test.find().sort("x", ASCENDING).sort("x", DESCENDING)] self.assertEqual(desc, expect) expected = [(1, 5), (2, 5), (0, 3), (7, 3), (9, 2), (2, 1), (3, 1)] shuffled = list(expected) random.shuffle(shuffled) db.test.drop() for a, b in shuffled: db.test.insert_one({"a": a, "b": b}) result = [ (i["a"], i["b"]) for i in db.test.find().sort([("b", DESCENDING), ("a", ASCENDING)]) ] self.assertEqual(result, expected) result = [(i["a"], i["b"]) for i in db.test.find().sort([("b", DESCENDING), "a"])] self.assertEqual(result, expected) a = db.test.find() a.sort("x", ASCENDING) for _ in a: break self.assertRaises(InvalidOperation, a.sort, "x", ASCENDING) def test_where(self): db = self.db db.test.drop() a = db.test.find() self.assertRaises(TypeError, a.where, 5) self.assertRaises(TypeError, a.where, None) self.assertRaises(TypeError, a.where, {}) db.test.insert_many([{"x": i} for i in range(10)]) self.assertEqual(3, len(list(db.test.find().where("this.x < 3")))) self.assertEqual(3, len(list(db.test.find().where(Code("this.x < 3"))))) code_with_scope = Code("this.x < i", {"i": 3}) if client_context.version.at_least(4, 3, 3): # MongoDB 4.4 removed support for Code with scope. with self.assertRaises(OperationFailure): list(db.test.find().where(code_with_scope)) code_with_empty_scope = Code("this.x < 3", {}) with self.assertRaises(OperationFailure): list(db.test.find().where(code_with_empty_scope)) else: self.assertEqual(3, len(list(db.test.find().where(code_with_scope)))) self.assertEqual(10, len(list(db.test.find()))) self.assertEqual([0, 1, 2], [a["x"] for a in db.test.find().where("this.x < 3")]) self.assertEqual([], [a["x"] for a in db.test.find({"x": 5}).where("this.x < 3")]) self.assertEqual([5], [a["x"] for a in db.test.find({"x": 5}).where("this.x > 3")]) cursor = db.test.find().where("this.x < 3").where("this.x > 7") self.assertEqual([8, 9], [a["x"] for a in cursor]) a = db.test.find() _ = a.where("this.x > 3") for _ in a: break self.assertRaises(InvalidOperation, a.where, "this.x < 3") def test_rewind(self): self.db.test.insert_many([{"x": i} for i in range(1, 4)]) cursor = self.db.test.find().limit(2) count = 0 for _ in cursor: count += 1 self.assertEqual(2, count) count = 0 for _ in cursor: count += 1 self.assertEqual(0, count) cursor.rewind() count = 0 for _ in cursor: count += 1 self.assertEqual(2, count) cursor.rewind() count = 0 for _ in cursor: break cursor.rewind() for _ in cursor: count += 1 self.assertEqual(2, count) self.assertEqual(cursor, cursor.rewind()) # oplog_reply, and snapshot are all deprecated. @ignore_deprecations def test_clone(self): self.db.test.insert_many([{"x": i} for i in range(1, 4)]) cursor = self.db.test.find().limit(2) count = 0 for _ in cursor: count += 1 self.assertEqual(2, count) count = 0 for _ in cursor: count += 1 self.assertEqual(0, count) cursor = cursor.clone() cursor2 = cursor.clone() count = 0 for _ in cursor: count += 1 self.assertEqual(2, count) for _ in cursor2: count += 1 self.assertEqual(4, count) cursor.rewind() count = 0 for _ in cursor: break cursor = cursor.clone() for _ in cursor: count += 1 self.assertEqual(2, count) self.assertNotEqual(cursor, cursor.clone()) # Just test attributes cursor = self.db.test.find( {"x": re.compile("^hello.*")}, projection={"_id": False}, skip=1, no_cursor_timeout=True, cursor_type=CursorType.TAILABLE_AWAIT, sort=[("x", 1)], allow_partial_results=True, oplog_replay=True, batch_size=123, collation={"locale": "en_US"}, hint=[("_id", 1)], max_scan=100, max_time_ms=1000, return_key=True, show_record_id=True, snapshot=True, allow_disk_use=True, ).limit(2) cursor.min([("a", 1)]).max([("b", 3)]) cursor.add_option(128) cursor.comment("hi!") # Every attribute should be the same. cursor2 = cursor.clone() self.assertEqual(cursor.__dict__, cursor2.__dict__) # Shallow copies can so can mutate cursor2 = copy.copy(cursor) cursor2._Cursor__projection["cursor2"] = False self.assertTrue("cursor2" in cursor._Cursor__projection) # Deepcopies and shouldn't mutate cursor3 = copy.deepcopy(cursor) cursor3._Cursor__projection["cursor3"] = False self.assertFalse("cursor3" in cursor._Cursor__projection) cursor4 = cursor.clone() cursor4._Cursor__projection["cursor4"] = False self.assertFalse("cursor4" in cursor._Cursor__projection) # Test memo when deepcopying queries query = {"hello": "world"} query["reflexive"] = query cursor = self.db.test.find(query) cursor2 = copy.deepcopy(cursor) self.assertNotEqual(id(cursor._Cursor__spec), id(cursor2._Cursor__spec)) self.assertEqual(id(cursor2._Cursor__spec["reflexive"]), id(cursor2._Cursor__spec)) self.assertEqual(len(cursor2._Cursor__spec), 2) # Ensure hints are cloned as the correct type cursor = self.db.test.find().hint([("z", 1), ("a", 1)]) cursor2 = copy.deepcopy(cursor) # Internal types are now dict rather than SON by default self.assertTrue(isinstance(cursor2._Cursor__hint, dict)) self.assertEqual(cursor._Cursor__hint, cursor2._Cursor__hint) def test_clone_empty(self): self.db.test.delete_many({}) self.db.test.insert_many([{"x": i} for i in range(1, 4)]) cursor = self.db.test.find()[2:2] cursor2 = cursor.clone() self.assertRaises(StopIteration, cursor.next) self.assertRaises(StopIteration, cursor2.next) def test_bad_getitem(self): self.assertRaises(TypeError, lambda x: self.db.test.find()[x], "hello") self.assertRaises(TypeError, lambda x: self.db.test.find()[x], 5.5) self.assertRaises(TypeError, lambda x: self.db.test.find()[x], None) def test_getitem_slice_index(self): self.db.drop_collection("test") self.db.test.insert_many([{"i": i} for i in range(100)]) count = itertools.count self.assertRaises(IndexError, lambda: self.db.test.find()[-1:]) self.assertRaises(IndexError, lambda: self.db.test.find()[1:2:2]) for a, b in zip(count(0), self.db.test.find()): self.assertEqual(a, b["i"]) self.assertEqual(100, len(list(self.db.test.find()[0:]))) for a, b in zip(count(0), self.db.test.find()[0:]): self.assertEqual(a, b["i"]) self.assertEqual(80, len(list(self.db.test.find()[20:]))) for a, b in zip(count(20), self.db.test.find()[20:]): self.assertEqual(a, b["i"]) for a, b in zip(count(99), self.db.test.find()[99:]): self.assertEqual(a, b["i"]) for _i in self.db.test.find()[1000:]: self.fail() self.assertEqual(5, len(list(self.db.test.find()[20:25]))) self.assertEqual(5, len(list(self.db.test.find()[20:25]))) for a, b in zip(count(20), self.db.test.find()[20:25]): self.assertEqual(a, b["i"]) self.assertEqual(80, len(list(self.db.test.find()[40:45][20:]))) for a, b in zip(count(20), self.db.test.find()[40:45][20:]): self.assertEqual(a, b["i"]) self.assertEqual(80, len(list(self.db.test.find()[40:45].limit(0).skip(20)))) for a, b in zip(count(20), self.db.test.find()[40:45].limit(0).skip(20)): self.assertEqual(a, b["i"]) self.assertEqual(80, len(list(self.db.test.find().limit(10).skip(40)[20:]))) for a, b in zip(count(20), self.db.test.find().limit(10).skip(40)[20:]): self.assertEqual(a, b["i"]) self.assertEqual(1, len(list(self.db.test.find()[:1]))) self.assertEqual(5, len(list(self.db.test.find()[:5]))) self.assertEqual(1, len(list(self.db.test.find()[99:100]))) self.assertEqual(1, len(list(self.db.test.find()[99:1000]))) self.assertEqual(0, len(list(self.db.test.find()[10:10]))) self.assertEqual(0, len(list(self.db.test.find()[:0]))) self.assertEqual(80, len(list(self.db.test.find()[10:10].limit(0).skip(20)))) self.assertRaises(IndexError, lambda: self.db.test.find()[10:8]) def test_getitem_numeric_index(self): self.db.drop_collection("test") self.db.test.insert_many([{"i": i} for i in range(100)]) self.assertEqual(0, self.db.test.find()[0]["i"]) self.assertEqual(50, self.db.test.find()[50]["i"]) self.assertEqual(50, self.db.test.find().skip(50)[0]["i"]) self.assertEqual(50, self.db.test.find().skip(49)[1]["i"]) self.assertEqual(50, self.db.test.find()[50]["i"]) self.assertEqual(99, self.db.test.find()[99]["i"]) self.assertRaises(IndexError, lambda x: self.db.test.find()[x], -1) self.assertRaises(IndexError, lambda x: self.db.test.find()[x], 100) self.assertRaises(IndexError, lambda x: self.db.test.find().skip(50)[x], 50) def test_len(self): self.assertRaises(TypeError, len, self.db.test.find()) def test_properties(self): self.assertEqual(self.db.test, self.db.test.find().collection) def set_coll(): self.db.test.find().collection = "hello" # type: ignore self.assertRaises(AttributeError, set_coll) def test_get_more(self): db = self.db db.drop_collection("test") db.test.insert_many([{"i": i} for i in range(10)]) self.assertEqual(10, len(list(db.test.find().batch_size(5)))) def test_tailable(self): db = self.db db.drop_collection("test") db.create_collection("test", capped=True, size=1000, max=3) self.addCleanup(db.drop_collection, "test") cursor = db.test.find(cursor_type=CursorType.TAILABLE) db.test.insert_one({"x": 1}) count = 0 for doc in cursor: count += 1 self.assertEqual(1, doc["x"]) self.assertEqual(1, count) db.test.insert_one({"x": 2}) count = 0 for doc in cursor: count += 1 self.assertEqual(2, doc["x"]) self.assertEqual(1, count) db.test.insert_one({"x": 3}) count = 0 for doc in cursor: count += 1 self.assertEqual(3, doc["x"]) self.assertEqual(1, count) # Capped rollover - the collection can never # have more than 3 documents. Just make sure # this doesn't raise... db.test.insert_many([{"x": i} for i in range(4, 7)]) self.assertEqual(0, len(list(cursor))) # and that the cursor doesn't think it's still alive. self.assertFalse(cursor.alive) self.assertEqual(3, db.test.count_documents({})) # __getitem__(index) for cursor in ( db.test.find(cursor_type=CursorType.TAILABLE), db.test.find(cursor_type=CursorType.TAILABLE_AWAIT), ): self.assertEqual(4, cursor[0]["x"]) self.assertEqual(5, cursor[1]["x"]) self.assertEqual(6, cursor[2]["x"]) cursor.rewind() self.assertEqual([4], [doc["x"] for doc in cursor[0:1]]) cursor.rewind() self.assertEqual([5], [doc["x"] for doc in cursor[1:2]]) cursor.rewind() self.assertEqual([6], [doc["x"] for doc in cursor[2:3]]) cursor.rewind() self.assertEqual([4, 5], [doc["x"] for doc in cursor[0:2]]) cursor.rewind() self.assertEqual([5, 6], [doc["x"] for doc in cursor[1:3]]) cursor.rewind() self.assertEqual([4, 5, 6], [doc["x"] for doc in cursor[0:3]]) def test_concurrent_close(self): """Ensure a tailable can be closed from another thread.""" db = self.db db.drop_collection("test") db.create_collection("test", capped=True, size=1000, max=3) self.addCleanup(db.drop_collection, "test") cursor = db.test.find(cursor_type=CursorType.TAILABLE) def iterate_cursor(): while cursor.alive: try: for _doc in cursor: pass except OperationFailure as e: if e.code != 237: # CursorKilled error code raise t = threading.Thread(target=iterate_cursor) t.start() time.sleep(1) cursor.close() self.assertFalse(cursor.alive) t.join(3) self.assertFalse(t.is_alive()) def test_distinct(self): self.db.drop_collection("test") self.db.test.insert_many([{"a": 1}, {"a": 2}, {"a": 2}, {"a": 2}, {"a": 3}]) distinct = self.db.test.find({"a": {"$lt": 3}}).distinct("a") distinct.sort() self.assertEqual([1, 2], distinct) self.db.drop_collection("test") self.db.test.insert_one({"a": {"b": "a"}, "c": 12}) self.db.test.insert_one({"a": {"b": "b"}, "c": 8}) self.db.test.insert_one({"a": {"b": "c"}, "c": 12}) self.db.test.insert_one({"a": {"b": "c"}, "c": 8}) distinct = self.db.test.find({"c": 8}).distinct("a.b") distinct.sort() self.assertEqual(["b", "c"], distinct) @client_context.require_version_max(4, 1, 0, -1) def test_max_scan(self): self.db.drop_collection("test") self.db.test.insert_many([{} for _ in range(100)]) self.assertEqual(100, len(list(self.db.test.find()))) self.assertEqual(50, len(list(self.db.test.find().max_scan(50)))) self.assertEqual(50, len(list(self.db.test.find().max_scan(90).max_scan(50)))) def test_with_statement(self): self.db.drop_collection("test") self.db.test.insert_many([{} for _ in range(100)]) c1 = self.db.test.find() with self.db.test.find() as c2: self.assertTrue(c2.alive) self.assertFalse(c2.alive) with self.db.test.find() as c2: self.assertEqual(100, len(list(c2))) self.assertFalse(c2.alive) self.assertTrue(c1.alive) @client_context.require_no_mongos def test_comment(self): self.client.drop_database(self.db) self.db.command("profile", 2) # Profile ALL commands. try: list(self.db.test.find().comment("foo")) count = self.db.system.profile.count_documents( {"ns": "pymongo_test.test", "op": "query", "command.comment": "foo"} ) self.assertEqual(count, 1) self.db.test.find().comment("foo").distinct("type") count = self.db.system.profile.count_documents( { "ns": "pymongo_test.test", "op": "command", "command.distinct": "test", "command.comment": "foo", } ) self.assertEqual(count, 1) finally: self.db.command("profile", 0) # Turn off profiling. self.db.system.profile.drop() self.db.test.insert_many([{}, {}]) cursor = self.db.test.find() next(cursor) self.assertRaises(InvalidOperation, cursor.comment, "hello") def test_alive(self): self.db.test.delete_many({}) self.db.test.insert_many([{} for _ in range(3)]) self.addCleanup(self.db.test.delete_many, {}) cursor = self.db.test.find().batch_size(2) n = 0 while True: cursor.next() n += 1 if n == 3: self.assertFalse(cursor.alive) break self.assertTrue(cursor.alive) def test_close_kills_cursor_synchronously(self): # Kill any cursors possibly queued up by previous tests. gc.collect() self.client._process_periodic_tasks() listener = AllowListEventListener("killCursors") client = rs_or_single_client(event_listeners=[listener]) self.addCleanup(client.close) coll = client[self.db.name].test_close_kills_cursors # Add some test data. docs_inserted = 1000 coll.insert_many([{"i": i} for i in range(docs_inserted)]) listener.reset() # Close a cursor while it's still open on the server. cursor = coll.find().batch_size(10) self.assertTrue(bool(next(cursor))) self.assertLess(cursor.retrieved, docs_inserted) cursor.close() def assertCursorKilled(): self.assertEqual(1, len(listener.started_events)) self.assertEqual("killCursors", listener.started_events[0].command_name) self.assertEqual(1, len(listener.succeeded_events)) self.assertEqual("killCursors", listener.succeeded_events[0].command_name) assertCursorKilled() listener.reset() # Close a command cursor while it's still open on the server. cursor = coll.aggregate([], batchSize=10) self.assertTrue(bool(next(cursor))) cursor.close() # The cursor should be killed if it had a non-zero id. if cursor.cursor_id: assertCursorKilled() else: self.assertEqual(0, len(listener.started_events)) @client_context.require_failCommand_appName def test_timeout_kills_cursor_asynchronously(self): listener = AllowListEventListener("killCursors") client = rs_or_single_client(event_listeners=[listener]) self.addCleanup(client.close) coll = client[self.db.name].test_timeout_kills_cursor # Add some test data. docs_inserted = 10 coll.insert_many([{"i": i} for i in range(docs_inserted)]) listener.reset() cursor = coll.find({}, batch_size=1) cursor.next() # Mock getMore commands timing out. mock_timeout_errors = { "configureFailPoint": "failCommand", "mode": "alwaysOn", "data": { "errorCode": 50, "failCommands": ["getMore"], }, } with self.fail_point(mock_timeout_errors): with self.assertRaises(ExecutionTimeout): cursor.next() def assertCursorKilled(): wait_until( lambda: len(listener.succeeded_events), "find successful killCursors command", ) self.assertEqual(1, len(listener.started_events)) self.assertEqual("killCursors", listener.started_events[0].command_name) self.assertEqual(1, len(listener.succeeded_events)) self.assertEqual("killCursors", listener.succeeded_events[0].command_name) assertCursorKilled() listener.reset() cursor = coll.aggregate([], batchSize=1) cursor.next() with self.fail_point(mock_timeout_errors): with self.assertRaises(ExecutionTimeout): cursor.next() assertCursorKilled() def test_delete_not_initialized(self): # Creating a cursor with invalid arguments will not run __init__ # but will still call __del__, eg test.find(invalidKwarg=1). cursor = Cursor.__new__(Cursor) # Skip calling __init__ cursor.__del__() # no error def test_getMore_does_not_send_readPreference(self): listener = AllowListEventListener("find", "getMore") client = rs_or_single_client(event_listeners=[listener]) self.addCleanup(client.close) # We never send primary read preference so override the default. coll = client[self.db.name].get_collection( "test", read_preference=ReadPreference.PRIMARY_PREFERRED ) coll.delete_many({}) coll.insert_many([{} for _ in range(5)]) self.addCleanup(coll.drop) list(coll.find(batch_size=3)) started = listener.started_events self.assertEqual(2, len(started)) self.assertEqual("find", started[0].command_name) if client_context.is_rs or client_context.is_mongos: self.assertIn("$readPreference", started[0].command) else: self.assertNotIn("$readPreference", started[0].command) self.assertEqual("getMore", started[1].command_name) self.assertNotIn("$readPreference", started[1].command) class TestRawBatchCursor(IntegrationTest): def test_find_raw(self): c = self.db.test c.drop() docs = [{"_id": i, "x": 3.0 * i} for i in range(10)] c.insert_many(docs) batches = list(c.find_raw_batches().sort("_id")) self.assertEqual(1, len(batches)) self.assertEqual(docs, decode_all(batches[0])) @client_context.require_transactions def test_find_raw_transaction(self): c = self.db.test c.drop() docs = [{"_id": i, "x": 3.0 * i} for i in range(10)] c.insert_many(docs) listener = OvertCommandListener() client = rs_or_single_client(event_listeners=[listener]) with client.start_session() as session: with session.start_transaction(): batches = list( client[self.db.name].test.find_raw_batches(session=session).sort("_id") ) cmd = listener.started_events[0] self.assertEqual(cmd.command_name, "find") self.assertIn("$clusterTime", cmd.command) self.assertEqual(cmd.command["startTransaction"], True) self.assertEqual(cmd.command["txnNumber"], 1) # Ensure we update $clusterTime from the command response. last_cmd = listener.succeeded_events[-1] self.assertEqual( last_cmd.reply["$clusterTime"]["clusterTime"], session.cluster_time["clusterTime"], ) self.assertEqual(1, len(batches)) self.assertEqual(docs, decode_all(batches[0])) @client_context.require_sessions @client_context.require_failCommand_fail_point def test_find_raw_retryable_reads(self): c = self.db.test c.drop() docs = [{"_id": i, "x": 3.0 * i} for i in range(10)] c.insert_many(docs) listener = OvertCommandListener() client = rs_or_single_client(event_listeners=[listener], retryReads=True) with self.fail_point( {"mode": {"times": 1}, "data": {"failCommands": ["find"], "closeConnection": True}} ): batches = list(client[self.db.name].test.find_raw_batches().sort("_id")) self.assertEqual(1, len(batches)) self.assertEqual(docs, decode_all(batches[0])) self.assertEqual(len(listener.started_events), 2) for cmd in listener.started_events: self.assertEqual(cmd.command_name, "find") @client_context.require_version_min(5, 0, 0) @client_context.require_no_standalone def test_find_raw_snapshot_reads(self): c = self.db.get_collection("test", write_concern=WriteConcern(w="majority")) c.drop() docs = [{"_id": i, "x": 3.0 * i} for i in range(10)] c.insert_many(docs) listener = OvertCommandListener() client = rs_or_single_client(event_listeners=[listener], retryReads=True) db = client[self.db.name] with client.start_session(snapshot=True) as session: db.test.distinct("x", {}, session=session) batches = list(db.test.find_raw_batches(session=session).sort("_id")) self.assertEqual(1, len(batches)) self.assertEqual(docs, decode_all(batches[0])) find_cmd = listener.started_events[1].command self.assertEqual(find_cmd["readConcern"]["level"], "snapshot") self.assertIsNotNone(find_cmd["readConcern"]["atClusterTime"]) def test_explain(self): c = self.db.test c.insert_one({}) explanation = c.find_raw_batches().explain() self.assertIsInstance(explanation, dict) def test_empty(self): self.db.test.drop() cursor = self.db.test.find_raw_batches() with self.assertRaises(StopIteration): next(cursor) def test_clone(self): self.db.test.insert_one({}) cursor = self.db.test.find_raw_batches() # Copy of a RawBatchCursor is also a RawBatchCursor, not a Cursor. self.assertIsInstance(next(cursor.clone()), bytes) self.assertIsInstance(next(copy.copy(cursor)), bytes) @client_context.require_no_mongos def test_exhaust(self): c = self.db.test c.drop() c.insert_many({"_id": i} for i in range(200)) result = b"".join(c.find_raw_batches(cursor_type=CursorType.EXHAUST)) self.assertEqual([{"_id": i} for i in range(200)], decode_all(result)) def test_server_error(self): with self.assertRaises(OperationFailure) as exc: next(self.db.test.find_raw_batches({"x": {"$bad": 1}})) # The server response was decoded, not left raw. self.assertIsInstance(exc.exception.details, dict) def test_get_item(self): with self.assertRaises(InvalidOperation): self.db.test.find_raw_batches()[0] def test_collation(self): next(self.db.test.find_raw_batches(collation=Collation("en_US"))) @client_context.require_no_mmap # MMAPv1 does not support read concern def test_read_concern(self): self.db.get_collection("test", write_concern=WriteConcern(w="majority")).insert_one({}) c = self.db.get_collection("test", read_concern=ReadConcern("majority")) next(c.find_raw_batches()) def test_monitoring(self): listener = EventListener() client = rs_or_single_client(event_listeners=[listener]) c = client.pymongo_test.test c.drop() c.insert_many([{"_id": i} for i in range(10)]) listener.reset() cursor = c.find_raw_batches(batch_size=4) # First raw batch of 4 documents. next(cursor) started = listener.started_events[0] succeeded = listener.succeeded_events[0] self.assertEqual(0, len(listener.failed_events)) self.assertEqual("find", started.command_name) self.assertEqual("pymongo_test", started.database_name) self.assertEqual("find", succeeded.command_name) csr = succeeded.reply["cursor"] self.assertEqual(csr["ns"], "pymongo_test.test") # The batch is a list of one raw bytes object. self.assertEqual(len(csr["firstBatch"]), 1) self.assertEqual(decode_all(csr["firstBatch"][0]), [{"_id": i} for i in range(4)]) listener.reset() # Next raw batch of 4 documents. next(cursor) try: started = listener.started_events[0] succeeded = listener.succeeded_events[0] self.assertEqual(0, len(listener.failed_events)) self.assertEqual("getMore", started.command_name) self.assertEqual("pymongo_test", started.database_name) self.assertEqual("getMore", succeeded.command_name) csr = succeeded.reply["cursor"] self.assertEqual(csr["ns"], "pymongo_test.test") self.assertEqual(len(csr["nextBatch"]), 1) self.assertEqual(decode_all(csr["nextBatch"][0]), [{"_id": i} for i in range(4, 8)]) finally: # Finish the cursor. tuple(cursor) class TestRawBatchCommandCursor(IntegrationTest): @classmethod def setUpClass(cls): super().setUpClass() def test_aggregate_raw(self): c = self.db.test c.drop() docs = [{"_id": i, "x": 3.0 * i} for i in range(10)] c.insert_many(docs) batches = list(c.aggregate_raw_batches([{"$sort": {"_id": 1}}])) self.assertEqual(1, len(batches)) self.assertEqual(docs, decode_all(batches[0])) @client_context.require_transactions def test_aggregate_raw_transaction(self): c = self.db.test c.drop() docs = [{"_id": i, "x": 3.0 * i} for i in range(10)] c.insert_many(docs) listener = OvertCommandListener() client = rs_or_single_client(event_listeners=[listener]) with client.start_session() as session: with session.start_transaction(): batches = list( client[self.db.name].test.aggregate_raw_batches( [{"$sort": {"_id": 1}}], session=session ) ) cmd = listener.started_events[0] self.assertEqual(cmd.command_name, "aggregate") self.assertIn("$clusterTime", cmd.command) self.assertEqual(cmd.command["startTransaction"], True) self.assertEqual(cmd.command["txnNumber"], 1) # Ensure we update $clusterTime from the command response. last_cmd = listener.succeeded_events[-1] self.assertEqual( last_cmd.reply["$clusterTime"]["clusterTime"], session.cluster_time["clusterTime"], ) self.assertEqual(1, len(batches)) self.assertEqual(docs, decode_all(batches[0])) @client_context.require_sessions @client_context.require_failCommand_fail_point def test_aggregate_raw_retryable_reads(self): c = self.db.test c.drop() docs = [{"_id": i, "x": 3.0 * i} for i in range(10)] c.insert_many(docs) listener = OvertCommandListener() client = rs_or_single_client(event_listeners=[listener], retryReads=True) with self.fail_point( {"mode": {"times": 1}, "data": {"failCommands": ["aggregate"], "closeConnection": True}} ): batches = list(client[self.db.name].test.aggregate_raw_batches([{"$sort": {"_id": 1}}])) self.assertEqual(1, len(batches)) self.assertEqual(docs, decode_all(batches[0])) self.assertEqual(len(listener.started_events), 3) cmds = listener.started_events self.assertEqual(cmds[0].command_name, "aggregate") self.assertEqual(cmds[1].command_name, "aggregate") @client_context.require_version_min(5, 0, -1) @client_context.require_no_standalone def test_aggregate_raw_snapshot_reads(self): c = self.db.get_collection("test", write_concern=WriteConcern(w="majority")) c.drop() docs = [{"_id": i, "x": 3.0 * i} for i in range(10)] c.insert_many(docs) listener = OvertCommandListener() client = rs_or_single_client(event_listeners=[listener], retryReads=True) db = client[self.db.name] with client.start_session(snapshot=True) as session: db.test.distinct("x", {}, session=session) batches = list(db.test.aggregate_raw_batches([{"$sort": {"_id": 1}}], session=session)) self.assertEqual(1, len(batches)) self.assertEqual(docs, decode_all(batches[0])) find_cmd = listener.started_events[1].command self.assertEqual(find_cmd["readConcern"]["level"], "snapshot") self.assertIsNotNone(find_cmd["readConcern"]["atClusterTime"]) def test_server_error(self): c = self.db.test c.drop() docs = [{"_id": i, "x": 3.0 * i} for i in range(10)] c.insert_many(docs) c.insert_one({"_id": 10, "x": "not a number"}) with self.assertRaises(OperationFailure) as exc: list( self.db.test.aggregate_raw_batches( [ { "$sort": {"_id": 1}, }, {"$project": {"x": {"$multiply": [2, "$x"]}}}, ], batchSize=4, ) ) # The server response was decoded, not left raw. self.assertIsInstance(exc.exception.details, dict) def test_get_item(self): with self.assertRaises(InvalidOperation): self.db.test.aggregate_raw_batches([])[0] def test_collation(self): next(self.db.test.aggregate_raw_batches([], collation=Collation("en_US"))) def test_monitoring(self): listener = EventListener() client = rs_or_single_client(event_listeners=[listener]) c = client.pymongo_test.test c.drop() c.insert_many([{"_id": i} for i in range(10)]) listener.reset() cursor = c.aggregate_raw_batches([{"$sort": {"_id": 1}}], batchSize=4) # Start cursor, no initial batch. started = listener.started_events[0] succeeded = listener.succeeded_events[0] self.assertEqual(0, len(listener.failed_events)) self.assertEqual("aggregate", started.command_name) self.assertEqual("pymongo_test", started.database_name) self.assertEqual("aggregate", succeeded.command_name) csr = succeeded.reply["cursor"] self.assertEqual(csr["ns"], "pymongo_test.test") # First batch is empty. self.assertEqual(len(csr["firstBatch"]), 0) listener.reset() # Batches of 4 documents. n = 0 for batch in cursor: started = listener.started_events[0] succeeded = listener.succeeded_events[0] self.assertEqual(0, len(listener.failed_events)) self.assertEqual("getMore", started.command_name) self.assertEqual("pymongo_test", started.database_name) self.assertEqual("getMore", succeeded.command_name) csr = succeeded.reply["cursor"] self.assertEqual(csr["ns"], "pymongo_test.test") self.assertEqual(len(csr["nextBatch"]), 1) self.assertEqual(csr["nextBatch"][0], batch) self.assertEqual(decode_all(batch), [{"_id": i} for i in range(n, min(n + 4, 10))]) n += 4 listener.reset() @client_context.require_version_min(5, 0, -1) @client_context.require_no_mongos def test_exhaust_cursor_db_set(self): listener = OvertCommandListener() client = rs_or_single_client(event_listeners=[listener]) self.addCleanup(client.close) c = client.pymongo_test.test c.delete_many({}) c.insert_many([{"_id": i} for i in range(3)]) listener.reset() result = list(c.find({}, cursor_type=pymongo.CursorType.EXHAUST, batch_size=1)) self.assertEqual(len(result), 3) self.assertEqual( listener.started_command_names(), ["find", "getMore", "getMore", "getMore"] ) for cmd in listener.started_events: self.assertEqual(cmd.command["$db"], "pymongo_test") if __name__ == "__main__": unittest.main() mongodb-mongo-python-driver-509e9b7/test/test_custom_types.py000066400000000000000000001014361462766011000245700ustar00rootroot00000000000000# Copyright 2019-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. """Test support for callbacks to encode/decode custom types.""" from __future__ import annotations import datetime import sys import tempfile from collections import OrderedDict from decimal import Decimal from random import random from typing import Any, Tuple, Type, no_type_check sys.path[0:0] = [""] from test import client_context, unittest from test.test_client import IntegrationTest from test.utils import rs_client from bson import ( _BUILT_IN_TYPES, RE_TYPE, Decimal128, _bson_to_dict, _dict_to_bson, decode, decode_all, decode_file_iter, decode_iter, encode, ) from bson.codec_options import ( CodecOptions, TypeCodec, TypeDecoder, TypeEncoder, TypeRegistry, ) from bson.errors import InvalidDocument from bson.int64 import Int64 from bson.raw_bson import RawBSONDocument from gridfs import GridIn, GridOut from pymongo.collection import ReturnDocument from pymongo.errors import DuplicateKeyError from pymongo.message import _CursorAddress class DecimalEncoder(TypeEncoder): @property def python_type(self): return Decimal def transform_python(self, value): return Decimal128(value) class DecimalDecoder(TypeDecoder): @property def bson_type(self): return Decimal128 def transform_bson(self, value): return value.to_decimal() class DecimalCodec(DecimalDecoder, DecimalEncoder): pass DECIMAL_CODECOPTS = CodecOptions(type_registry=TypeRegistry([DecimalCodec()])) class UndecipherableInt64Type: def __init__(self, value): self.value = value def __eq__(self, other): if isinstance(other, type(self)): return self.value == other.value # Does not compare equal to integers. return False class UndecipherableIntDecoder(TypeDecoder): bson_type = Int64 def transform_bson(self, value): return UndecipherableInt64Type(value) class UndecipherableIntEncoder(TypeEncoder): python_type = UndecipherableInt64Type def transform_python(self, value): return Int64(value.value) UNINT_DECODER_CODECOPTS = CodecOptions( type_registry=TypeRegistry( [ UndecipherableIntDecoder(), ] ) ) UNINT_CODECOPTS = CodecOptions( type_registry=TypeRegistry([UndecipherableIntDecoder(), UndecipherableIntEncoder()]) ) class UppercaseTextDecoder(TypeDecoder): bson_type = str def transform_bson(self, value): return value.upper() UPPERSTR_DECODER_CODECOPTS = CodecOptions( type_registry=TypeRegistry( [ UppercaseTextDecoder(), ] ) ) def type_obfuscating_decoder_factory(rt_type): class ResumeTokenToNanDecoder(TypeDecoder): bson_type = rt_type def transform_bson(self, value): return "NaN" return ResumeTokenToNanDecoder class CustomBSONTypeTests: @no_type_check def roundtrip(self, doc): bsonbytes = encode(doc, codec_options=self.codecopts) rt_document = decode(bsonbytes, codec_options=self.codecopts) self.assertEqual(doc, rt_document) def test_encode_decode_roundtrip(self): self.roundtrip({"average": Decimal("56.47")}) self.roundtrip({"average": {"b": Decimal("56.47")}}) self.roundtrip({"average": [Decimal("56.47")]}) self.roundtrip({"average": [[Decimal("56.47")]]}) self.roundtrip({"average": [{"b": Decimal("56.47")}]}) @no_type_check def test_decode_all(self): documents = [] for dec in range(3): documents.append({"average": Decimal(f"56.4{dec}")}) bsonstream = b"" for doc in documents: bsonstream += encode(doc, codec_options=self.codecopts) self.assertEqual(decode_all(bsonstream, self.codecopts), documents) @no_type_check def test__bson_to_dict(self): document = {"average": Decimal("56.47")} rawbytes = encode(document, codec_options=self.codecopts) decoded_document = _bson_to_dict(rawbytes, self.codecopts) self.assertEqual(document, decoded_document) @no_type_check def test__dict_to_bson(self): document = {"average": Decimal("56.47")} rawbytes = encode(document, codec_options=self.codecopts) encoded_document = _dict_to_bson(document, False, self.codecopts) self.assertEqual(encoded_document, rawbytes) def _generate_multidocument_bson_stream(self): inp_num = [str(random() * 100)[:4] for _ in range(10)] docs = [{"n": Decimal128(dec)} for dec in inp_num] edocs = [{"n": Decimal(dec)} for dec in inp_num] bsonstream = b"" for doc in docs: bsonstream += encode(doc) return edocs, bsonstream @no_type_check def test_decode_iter(self): expected, bson_data = self._generate_multidocument_bson_stream() for expected_doc, decoded_doc in zip(expected, decode_iter(bson_data, self.codecopts)): self.assertEqual(expected_doc, decoded_doc) @no_type_check def test_decode_file_iter(self): expected, bson_data = self._generate_multidocument_bson_stream() fileobj = tempfile.TemporaryFile() fileobj.write(bson_data) fileobj.seek(0) for expected_doc, decoded_doc in zip(expected, decode_file_iter(fileobj, self.codecopts)): self.assertEqual(expected_doc, decoded_doc) fileobj.close() class TestCustomPythonBSONTypeToBSONMonolithicCodec(CustomBSONTypeTests, unittest.TestCase): @classmethod def setUpClass(cls): cls.codecopts = DECIMAL_CODECOPTS class TestCustomPythonBSONTypeToBSONMultiplexedCodec(CustomBSONTypeTests, unittest.TestCase): @classmethod def setUpClass(cls): codec_options = CodecOptions( type_registry=TypeRegistry((DecimalEncoder(), DecimalDecoder())) ) cls.codecopts = codec_options class TestBSONFallbackEncoder(unittest.TestCase): def _get_codec_options(self, fallback_encoder): type_registry = TypeRegistry(fallback_encoder=fallback_encoder) return CodecOptions(type_registry=type_registry) def test_simple(self): codecopts = self._get_codec_options(lambda x: Decimal128(x)) document = {"average": Decimal("56.47")} bsonbytes = encode(document, codec_options=codecopts) exp_document = {"average": Decimal128("56.47")} exp_bsonbytes = encode(exp_document) self.assertEqual(bsonbytes, exp_bsonbytes) def test_erroring_fallback_encoder(self): codecopts = self._get_codec_options(lambda _: 1 / 0) # fallback converter should not be invoked when encoding known types. encode( {"a": 1, "b": Decimal128("1.01"), "c": {"arr": ["abc", 3.678]}}, codec_options=codecopts ) # expect an error when encoding a custom type. document = {"average": Decimal("56.47")} with self.assertRaises(ZeroDivisionError): encode(document, codec_options=codecopts) def test_noop_fallback_encoder(self): codecopts = self._get_codec_options(lambda x: x) document = {"average": Decimal("56.47")} with self.assertRaises(InvalidDocument): encode(document, codec_options=codecopts) def test_type_unencodable_by_fallback_encoder(self): def fallback_encoder(value): try: return Decimal128(value) except: raise TypeError("cannot encode type %s" % (type(value))) codecopts = self._get_codec_options(fallback_encoder) document = {"average": Decimal} with self.assertRaises(TypeError): encode(document, codec_options=codecopts) def test_call_only_once_for_not_handled_big_integers(self): called_with = [] def fallback_encoder(value): called_with.append(value) return value codecopts = self._get_codec_options(fallback_encoder) document = {"a": {"b": {"c": 2 << 65}}} msg = "MongoDB can only handle up to 8-byte ints" with self.assertRaises(OverflowError, msg=msg): encode(document, codec_options=codecopts) self.assertEqual(called_with, [2 << 65]) class TestBSONTypeEnDeCodecs(unittest.TestCase): def test_instantiation(self): msg = "Can't instantiate abstract class" def run_test(base, attrs, fail): codec = type("testcodec", (base,), attrs) if fail: with self.assertRaisesRegex(TypeError, msg): codec() else: codec() class MyType: pass run_test( TypeEncoder, { "python_type": MyType, }, fail=True, ) run_test(TypeEncoder, {"transform_python": lambda s, x: x}, fail=True) run_test( TypeEncoder, {"transform_python": lambda s, x: x, "python_type": MyType}, fail=False ) run_test( TypeDecoder, { "bson_type": Decimal128, }, fail=True, ) run_test(TypeDecoder, {"transform_bson": lambda s, x: x}, fail=True) run_test( TypeDecoder, {"transform_bson": lambda s, x: x, "bson_type": Decimal128}, fail=False ) run_test(TypeCodec, {"bson_type": Decimal128, "python_type": MyType}, fail=True) run_test( TypeCodec, {"transform_bson": lambda s, x: x, "transform_python": lambda s, x: x}, fail=True, ) run_test( TypeCodec, { "python_type": MyType, "transform_python": lambda s, x: x, "transform_bson": lambda s, x: x, "bson_type": Decimal128, }, fail=False, ) def test_type_checks(self): self.assertTrue(issubclass(TypeCodec, TypeEncoder)) self.assertTrue(issubclass(TypeCodec, TypeDecoder)) self.assertFalse(issubclass(TypeDecoder, TypeEncoder)) self.assertFalse(issubclass(TypeEncoder, TypeDecoder)) class TestBSONCustomTypeEncoderAndFallbackEncoderTandem(unittest.TestCase): TypeA: Any TypeB: Any fallback_encoder_A2B: Any fallback_encoder_A2BSON: Any B2BSON: Type[TypeEncoder] B2A: Type[TypeEncoder] A2B: Type[TypeEncoder] @classmethod def setUpClass(cls): class TypeA: def __init__(self, x): self.value = x class TypeB: def __init__(self, x): self.value = x # transforms A, and only A into B def fallback_encoder_A2B(value): assert isinstance(value, TypeA) return TypeB(value.value) # transforms A, and only A into something encodable def fallback_encoder_A2BSON(value): assert isinstance(value, TypeA) return value.value # transforms B into something encodable class B2BSON(TypeEncoder): python_type = TypeB def transform_python(self, value): return value.value # transforms A into B # technically, this isn't a proper type encoder as the output is not # BSON-encodable. class A2B(TypeEncoder): python_type = TypeA def transform_python(self, value): return TypeB(value.value) # transforms B into A # technically, this isn't a proper type encoder as the output is not # BSON-encodable. class B2A(TypeEncoder): python_type = TypeB def transform_python(self, value): return TypeA(value.value) cls.TypeA = TypeA cls.TypeB = TypeB cls.fallback_encoder_A2B = staticmethod(fallback_encoder_A2B) cls.fallback_encoder_A2BSON = staticmethod(fallback_encoder_A2BSON) cls.B2BSON = B2BSON cls.B2A = B2A cls.A2B = A2B def test_encode_fallback_then_custom(self): codecopts = CodecOptions( type_registry=TypeRegistry([self.B2BSON()], fallback_encoder=self.fallback_encoder_A2B) ) testdoc = {"x": self.TypeA(123)} expected_bytes = encode({"x": 123}) self.assertEqual(encode(testdoc, codec_options=codecopts), expected_bytes) def test_encode_custom_then_fallback(self): codecopts = CodecOptions( type_registry=TypeRegistry([self.B2A()], fallback_encoder=self.fallback_encoder_A2BSON) ) testdoc = {"x": self.TypeB(123)} expected_bytes = encode({"x": 123}) self.assertEqual(encode(testdoc, codec_options=codecopts), expected_bytes) def test_chaining_encoders_fails(self): codecopts = CodecOptions(type_registry=TypeRegistry([self.A2B(), self.B2BSON()])) with self.assertRaises(InvalidDocument): encode({"x": self.TypeA(123)}, codec_options=codecopts) def test_infinite_loop_exceeds_max_recursion_depth(self): codecopts = CodecOptions( type_registry=TypeRegistry([self.B2A()], fallback_encoder=self.fallback_encoder_A2B) ) # Raises max recursion depth exceeded error with self.assertRaises(RuntimeError): encode({"x": self.TypeA(100)}, codec_options=codecopts) class TestTypeRegistry(unittest.TestCase): types: Tuple[object, object] codecs: Tuple[Type[TypeCodec], Type[TypeCodec]] fallback_encoder: Any @classmethod def setUpClass(cls): class MyIntType: def __init__(self, x): assert isinstance(x, int) self.x = x class MyStrType: def __init__(self, x): assert isinstance(x, str) self.x = x class MyIntCodec(TypeCodec): @property def python_type(self): return MyIntType @property def bson_type(self): return int def transform_python(self, value): return value.x def transform_bson(self, value): return MyIntType(value) class MyStrCodec(TypeCodec): @property def python_type(self): return MyStrType @property def bson_type(self): return str def transform_python(self, value): return value.x def transform_bson(self, value): return MyStrType(value) def fallback_encoder(value): return value cls.types = (MyIntType, MyStrType) cls.codecs = (MyIntCodec, MyStrCodec) cls.fallback_encoder = fallback_encoder def test_simple(self): codec_instances = [codec() for codec in self.codecs] def assert_proper_initialization(type_registry, codec_instances): self.assertEqual( type_registry._encoder_map, { self.types[0]: codec_instances[0].transform_python, self.types[1]: codec_instances[1].transform_python, }, ) self.assertEqual( type_registry._decoder_map, {int: codec_instances[0].transform_bson, str: codec_instances[1].transform_bson}, ) self.assertEqual(type_registry._fallback_encoder, self.fallback_encoder) type_registry = TypeRegistry(codec_instances, self.fallback_encoder) assert_proper_initialization(type_registry, codec_instances) type_registry = TypeRegistry( fallback_encoder=self.fallback_encoder, type_codecs=codec_instances ) assert_proper_initialization(type_registry, codec_instances) # Ensure codec list held by the type registry doesn't change if we # mutate the initial list. codec_instances_copy = list(codec_instances) codec_instances.pop(0) self.assertListEqual(type_registry._TypeRegistry__type_codecs, codec_instances_copy) def test_simple_separate_codecs(self): class MyIntEncoder(TypeEncoder): python_type = self.types[0] def transform_python(self, value): return value.x class MyIntDecoder(TypeDecoder): bson_type = int def transform_bson(self, value): return self.types[0](value) codec_instances: list = [MyIntDecoder(), MyIntEncoder()] type_registry = TypeRegistry(codec_instances) self.assertEqual( type_registry._encoder_map, {MyIntEncoder.python_type: codec_instances[1].transform_python}, ) self.assertEqual( type_registry._decoder_map, {MyIntDecoder.bson_type: codec_instances[0].transform_bson}, ) def test_initialize_fail(self): err_msg = "Expected an instance of TypeEncoder, TypeDecoder, or TypeCodec, got .* instead" with self.assertRaisesRegex(TypeError, err_msg): TypeRegistry(self.codecs) # type: ignore[arg-type] with self.assertRaisesRegex(TypeError, err_msg): TypeRegistry([type("AnyType", (object,), {})()]) err_msg = f"fallback_encoder {True!r} is not a callable" with self.assertRaisesRegex(TypeError, err_msg): TypeRegistry([], True) # type: ignore[arg-type] err_msg = "fallback_encoder {!r} is not a callable".format("hello") with self.assertRaisesRegex(TypeError, err_msg): TypeRegistry(fallback_encoder="hello") # type: ignore[arg-type] def test_type_registry_repr(self): codec_instances = [codec() for codec in self.codecs] type_registry = TypeRegistry(codec_instances) r = f"TypeRegistry(type_codecs={codec_instances!r}, fallback_encoder={None!r})" self.assertEqual(r, repr(type_registry)) def test_type_registry_eq(self): codec_instances = [codec() for codec in self.codecs] self.assertEqual(TypeRegistry(codec_instances), TypeRegistry(codec_instances)) codec_instances_2 = [codec() for codec in self.codecs] self.assertNotEqual(TypeRegistry(codec_instances), TypeRegistry(codec_instances_2)) def test_builtin_types_override_fails(self): def run_test(base, attrs): msg = ( r"TypeEncoders cannot change how built-in types " r"are encoded \(encoder .* transforms type .*\)" ) for pytype in _BUILT_IN_TYPES: attrs.update({"python_type": pytype, "transform_python": lambda x: x}) codec = type("testcodec", (base,), attrs) codec_instance = codec() with self.assertRaisesRegex(TypeError, msg): TypeRegistry( [ codec_instance, ] ) # Test only some subtypes as not all can be subclassed. if pytype in [ bool, type(None), RE_TYPE, ]: continue class MyType(pytype): # type: ignore pass attrs.update({"python_type": MyType, "transform_python": lambda x: x}) codec = type("testcodec", (base,), attrs) codec_instance = codec() with self.assertRaisesRegex(TypeError, msg): TypeRegistry( [ codec_instance, ] ) run_test(TypeEncoder, {}) run_test(TypeCodec, {"bson_type": Decimal128, "transform_bson": lambda x: x}) class TestCollectionWCustomType(IntegrationTest): def setUp(self): self.db.test.drop() def tearDown(self): self.db.test.drop() def test_overflow_int_w_custom_decoder(self): type_registry = TypeRegistry(fallback_encoder=lambda val: str(val)) codec_options = CodecOptions(type_registry=type_registry) collection = self.db.get_collection("test", codec_options=codec_options) collection.insert_one({"_id": 1, "data": 2**520}) ret = collection.find_one() self.assertEqual(ret["data"], str(2**520)) def test_command_errors_w_custom_type_decoder(self): db = self.db test_doc = {"_id": 1, "data": "a"} test = db.get_collection("test", codec_options=UNINT_DECODER_CODECOPTS) result = test.insert_one(test_doc) self.assertEqual(result.inserted_id, test_doc["_id"]) with self.assertRaises(DuplicateKeyError): test.insert_one(test_doc) def test_find_w_custom_type_decoder(self): db = self.db input_docs = [{"x": Int64(k)} for k in [1, 2, 3]] for doc in input_docs: db.test.insert_one(doc) test = db.get_collection("test", codec_options=UNINT_DECODER_CODECOPTS) for doc in test.find({}, batch_size=1): self.assertIsInstance(doc["x"], UndecipherableInt64Type) def test_find_w_custom_type_decoder_and_document_class(self): def run_test(doc_cls): db = self.db input_docs = [{"x": Int64(k)} for k in [1, 2, 3]] for doc in input_docs: db.test.insert_one(doc) test = db.get_collection( "test", codec_options=CodecOptions( type_registry=TypeRegistry([UndecipherableIntDecoder()]), document_class=doc_cls ), ) for doc in test.find({}, batch_size=1): self.assertIsInstance(doc, doc_cls) self.assertIsInstance(doc["x"], UndecipherableInt64Type) for doc_cls in [RawBSONDocument, OrderedDict]: run_test(doc_cls) def test_aggregate_w_custom_type_decoder(self): db = self.db db.test.insert_many( [ {"status": "in progress", "qty": Int64(1)}, {"status": "complete", "qty": Int64(10)}, {"status": "in progress", "qty": Int64(1)}, {"status": "complete", "qty": Int64(10)}, {"status": "in progress", "qty": Int64(1)}, ] ) test = db.get_collection("test", codec_options=UNINT_DECODER_CODECOPTS) pipeline: list = [ {"$match": {"status": "complete"}}, {"$group": {"_id": "$status", "total_qty": {"$sum": "$qty"}}}, ] result = test.aggregate(pipeline) res = list(result)[0] self.assertEqual(res["_id"], "complete") self.assertIsInstance(res["total_qty"], UndecipherableInt64Type) self.assertEqual(res["total_qty"].value, 20) def test_distinct_w_custom_type(self): self.db.drop_collection("test") test = self.db.get_collection("test", codec_options=UNINT_CODECOPTS) values = [ UndecipherableInt64Type(1), UndecipherableInt64Type(2), UndecipherableInt64Type(3), {"b": UndecipherableInt64Type(3)}, ] test.insert_many({"a": val} for val in values) self.assertEqual(values, test.distinct("a")) def test_find_one_and__w_custom_type_decoder(self): db = self.db c = db.get_collection("test", codec_options=UNINT_DECODER_CODECOPTS) c.insert_one({"_id": 1, "x": Int64(1)}) doc = c.find_one_and_update( {"_id": 1}, {"$inc": {"x": 1}}, return_document=ReturnDocument.AFTER ) self.assertEqual(doc["_id"], 1) self.assertIsInstance(doc["x"], UndecipherableInt64Type) self.assertEqual(doc["x"].value, 2) doc = c.find_one_and_replace( {"_id": 1}, {"x": Int64(3), "y": True}, return_document=ReturnDocument.AFTER ) self.assertEqual(doc["_id"], 1) self.assertIsInstance(doc["x"], UndecipherableInt64Type) self.assertEqual(doc["x"].value, 3) self.assertEqual(doc["y"], True) doc = c.find_one_and_delete({"y": True}) self.assertEqual(doc["_id"], 1) self.assertIsInstance(doc["x"], UndecipherableInt64Type) self.assertEqual(doc["x"].value, 3) self.assertIsNone(c.find_one()) class TestGridFileCustomType(IntegrationTest): def setUp(self): self.db.drop_collection("fs.files") self.db.drop_collection("fs.chunks") def test_grid_out_custom_opts(self): db = self.db.with_options(codec_options=UPPERSTR_DECODER_CODECOPTS) one = GridIn( db.fs, _id=5, filename="my_file", contentType="text/html", chunkSize=1000, aliases=["foo"], metadata={"foo": "red", "bar": "blue"}, bar=3, baz="hello", ) one.write(b"hello world") one.close() two = GridOut(db.fs, 5) self.assertEqual("my_file", two.name) self.assertEqual("my_file", two.filename) self.assertEqual(5, two._id) self.assertEqual(11, two.length) self.assertEqual("text/html", two.content_type) self.assertEqual(1000, two.chunk_size) self.assertTrue(isinstance(two.upload_date, datetime.datetime)) self.assertEqual(["foo"], two.aliases) self.assertEqual({"foo": "red", "bar": "blue"}, two.metadata) self.assertEqual(3, two.bar) self.assertEqual(None, two.md5) for attr in [ "_id", "name", "content_type", "length", "chunk_size", "upload_date", "aliases", "metadata", "md5", ]: self.assertRaises(AttributeError, setattr, two, attr, 5) class ChangeStreamsWCustomTypesTestMixin: @no_type_check def change_stream(self, *args, **kwargs): return self.watched_target.watch(*args, **kwargs) @no_type_check def insert_and_check(self, change_stream, insert_doc, expected_doc): self.input_target.insert_one(insert_doc) change = next(change_stream) self.assertEqual(change["fullDocument"], expected_doc) @no_type_check def kill_change_stream_cursor(self, change_stream): # Cause a cursor not found error on the next getMore. cursor = change_stream._cursor address = _CursorAddress(cursor.address, cursor._CommandCursor__ns) client = self.input_target.database.client client._close_cursor_now(cursor.cursor_id, address) @no_type_check def test_simple(self): codecopts = CodecOptions( type_registry=TypeRegistry([UndecipherableIntEncoder(), UppercaseTextDecoder()]) ) self.create_targets(codec_options=codecopts) input_docs = [ {"_id": UndecipherableInt64Type(1), "data": "hello"}, {"_id": 2, "data": "world"}, {"_id": UndecipherableInt64Type(3), "data": "!"}, ] expected_docs = [ {"_id": 1, "data": "HELLO"}, {"_id": 2, "data": "WORLD"}, {"_id": 3, "data": "!"}, ] change_stream = self.change_stream() self.insert_and_check(change_stream, input_docs[0], expected_docs[0]) self.kill_change_stream_cursor(change_stream) self.insert_and_check(change_stream, input_docs[1], expected_docs[1]) self.kill_change_stream_cursor(change_stream) self.insert_and_check(change_stream, input_docs[2], expected_docs[2]) @no_type_check def test_custom_type_in_pipeline(self): codecopts = CodecOptions( type_registry=TypeRegistry([UndecipherableIntEncoder(), UppercaseTextDecoder()]) ) self.create_targets(codec_options=codecopts) input_docs = [ {"_id": UndecipherableInt64Type(1), "data": "hello"}, {"_id": 2, "data": "world"}, {"_id": UndecipherableInt64Type(3), "data": "!"}, ] expected_docs = [{"_id": 2, "data": "WORLD"}, {"_id": 3, "data": "!"}] # UndecipherableInt64Type should be encoded with the TypeRegistry. change_stream = self.change_stream( [{"$match": {"documentKey._id": {"$gte": UndecipherableInt64Type(2)}}}] ) self.input_target.insert_one(input_docs[0]) self.insert_and_check(change_stream, input_docs[1], expected_docs[0]) self.kill_change_stream_cursor(change_stream) self.insert_and_check(change_stream, input_docs[2], expected_docs[1]) @no_type_check def test_break_resume_token(self): # Get one document from a change stream to determine resumeToken type. self.create_targets() change_stream = self.change_stream() self.input_target.insert_one({"data": "test"}) change = next(change_stream) resume_token_decoder = type_obfuscating_decoder_factory(type(change["_id"]["_data"])) # Custom-decoding the resumeToken type breaks resume tokens. codecopts = CodecOptions( type_registry=TypeRegistry([resume_token_decoder(), UndecipherableIntEncoder()]) ) # Re-create targets, change stream and proceed. self.create_targets(codec_options=codecopts) docs = [{"_id": 1}, {"_id": 2}, {"_id": 3}] change_stream = self.change_stream() self.insert_and_check(change_stream, docs[0], docs[0]) self.kill_change_stream_cursor(change_stream) self.insert_and_check(change_stream, docs[1], docs[1]) self.kill_change_stream_cursor(change_stream) self.insert_and_check(change_stream, docs[2], docs[2]) @no_type_check def test_document_class(self): def run_test(doc_cls): codecopts = CodecOptions( type_registry=TypeRegistry([UppercaseTextDecoder(), UndecipherableIntEncoder()]), document_class=doc_cls, ) self.create_targets(codec_options=codecopts) change_stream = self.change_stream() doc = {"a": UndecipherableInt64Type(101), "b": "xyz"} self.input_target.insert_one(doc) change = next(change_stream) self.assertIsInstance(change, doc_cls) self.assertEqual(change["fullDocument"]["a"], 101) self.assertEqual(change["fullDocument"]["b"], "XYZ") for doc_cls in [OrderedDict, RawBSONDocument]: run_test(doc_cls) class TestCollectionChangeStreamsWCustomTypes(IntegrationTest, ChangeStreamsWCustomTypesTestMixin): @classmethod @client_context.require_change_streams def setUpClass(cls): super().setUpClass() cls.db.test.delete_many({}) def tearDown(self): self.input_target.drop() def create_targets(self, *args, **kwargs): self.watched_target = self.db.get_collection("test", *args, **kwargs) self.input_target = self.watched_target # Ensure the collection exists and is empty. self.input_target.insert_one({}) self.input_target.delete_many({}) class TestDatabaseChangeStreamsWCustomTypes(IntegrationTest, ChangeStreamsWCustomTypesTestMixin): @classmethod @client_context.require_version_min(4, 0, 0) @client_context.require_change_streams def setUpClass(cls): super().setUpClass() cls.db.test.delete_many({}) def tearDown(self): self.input_target.drop() self.client.drop_database(self.watched_target) def create_targets(self, *args, **kwargs): self.watched_target = self.client.get_database(self.db.name, *args, **kwargs) self.input_target = self.watched_target.test # Insert a record to ensure db, coll are created. self.input_target.insert_one({"data": "dummy"}) class TestClusterChangeStreamsWCustomTypes(IntegrationTest, ChangeStreamsWCustomTypesTestMixin): @classmethod @client_context.require_version_min(4, 0, 0) @client_context.require_change_streams def setUpClass(cls): super().setUpClass() cls.db.test.delete_many({}) def tearDown(self): self.input_target.drop() self.client.drop_database(self.db) def create_targets(self, *args, **kwargs): codec_options = kwargs.pop("codec_options", None) if codec_options: kwargs["type_registry"] = codec_options.type_registry kwargs["document_class"] = codec_options.document_class self.watched_target = rs_client(*args, **kwargs) self.addCleanup(self.watched_target.close) self.input_target = self.watched_target[self.db.name].test # Insert a record to ensure db, coll are created. self.input_target.insert_one({"data": "dummy"}) if __name__ == "__main__": unittest.main() mongodb-mongo-python-driver-509e9b7/test/test_data_lake.py000066400000000000000000000074611462766011000237420ustar00rootroot00000000000000# Copyright 2020-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. """Test Atlas Data Lake.""" from __future__ import annotations import os import sys sys.path[0:0] = [""] from test import IntegrationTest, client_context, unittest from test.crud_v2_format import TestCrudV2 from test.utils import ( OvertCommandListener, SpecTestCreator, rs_client_noauth, rs_or_single_client, ) # Location of JSON test specifications. _TEST_PATH = os.path.join(os.path.dirname(os.path.realpath(__file__)), "data_lake") class TestDataLakeMustConnect(unittest.TestCase): def test_connected_to_data_lake(self): data_lake = os.environ.get("TEST_DATA_LAKE") if not data_lake: self.skipTest("TEST_DATA_LAKE is not set") self.assertTrue( client_context.is_data_lake and client_context.connected, "client context must be connected to data lake when DATA_LAKE is set. Failed attempts:\n{}".format( client_context.connection_attempt_info() ), ) class TestDataLakeProse(IntegrationTest): # Default test database and collection names. TEST_DB = "test" TEST_COLLECTION = "driverdata" @classmethod @client_context.require_data_lake def setUpClass(cls): super().setUpClass() # Test killCursors def test_1(self): listener = OvertCommandListener() client = rs_or_single_client(event_listeners=[listener]) cursor = client[self.TEST_DB][self.TEST_COLLECTION].find({}, batch_size=2) next(cursor) # find command assertions find_cmd = listener.succeeded_events[-1] self.assertEqual(find_cmd.command_name, "find") cursor_id = find_cmd.reply["cursor"]["id"] cursor_ns = find_cmd.reply["cursor"]["ns"] # killCursors command assertions cursor.close() started = listener.started_events[-1] self.assertEqual(started.command_name, "killCursors") succeeded = listener.succeeded_events[-1] self.assertEqual(succeeded.command_name, "killCursors") self.assertIn(cursor_id, started.command["cursors"]) target_ns = ".".join([started.command["$db"], started.command["killCursors"]]) self.assertEqual(cursor_ns, target_ns) self.assertIn(cursor_id, succeeded.reply["cursorsKilled"]) # Test no auth def test_2(self): client = rs_client_noauth() client.admin.command("ping") # Test with auth def test_3(self): for mechanism in ["SCRAM-SHA-1", "SCRAM-SHA-256"]: client = rs_or_single_client(authMechanism=mechanism) client[self.TEST_DB][self.TEST_COLLECTION].find_one() class DataLakeTestSpec(TestCrudV2): # Default test database and collection names. TEST_DB = "test" TEST_COLLECTION = "driverdata" @classmethod @client_context.require_data_lake def setUpClass(cls): super().setUpClass() def setup_scenario(self, scenario_def): # Spec tests MUST NOT insert data/drop collection for # data lake testing. pass def create_test(scenario_def, test, name): def run_scenario(self): self.run_scenario(scenario_def, test) return run_scenario SpecTestCreator(create_test, DataLakeTestSpec, _TEST_PATH).create_tests() if __name__ == "__main__": unittest.main() mongodb-mongo-python-driver-509e9b7/test/test_database.py000066400000000000000000000670221462766011000236000ustar00rootroot00000000000000# Copyright 2009-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. """Test the database module.""" from __future__ import annotations import re import sys from typing import Any, Iterable, List, Mapping, Union from pymongo.command_cursor import CommandCursor sys.path[0:0] = [""] from test import IntegrationTest, client_context, unittest from test.test_custom_types import DECIMAL_CODECOPTS from test.utils import ( IMPOSSIBLE_WRITE_CONCERN, OvertCommandListener, rs_or_single_client, wait_until, ) from bson.codec_options import CodecOptions from bson.dbref import DBRef from bson.int64 import Int64 from bson.objectid import ObjectId from bson.regex import Regex from bson.son import SON from pymongo import auth, helpers from pymongo.collection import Collection from pymongo.database import Database from pymongo.errors import ( CollectionInvalid, ExecutionTimeout, InvalidName, InvalidOperation, OperationFailure, WriteConcernError, ) from pymongo.mongo_client import MongoClient from pymongo.read_concern import ReadConcern from pymongo.read_preferences import ReadPreference from pymongo.write_concern import WriteConcern class TestDatabaseNoConnect(unittest.TestCase): """Test Database features on a client that does not connect.""" client: MongoClient @classmethod def setUpClass(cls): cls.client = MongoClient(connect=False) def test_name(self): self.assertRaises(TypeError, Database, self.client, 4) self.assertRaises(InvalidName, Database, self.client, "my db") self.assertRaises(InvalidName, Database, self.client, 'my"db') self.assertRaises(InvalidName, Database, self.client, "my\x00db") self.assertRaises(InvalidName, Database, self.client, "my\u0000db") self.assertEqual("name", Database(self.client, "name").name) def test_get_collection(self): codec_options = CodecOptions(tz_aware=True) write_concern = WriteConcern(w=2, j=True) read_concern = ReadConcern("majority") coll = self.client.pymongo_test.get_collection( "foo", codec_options, ReadPreference.SECONDARY, write_concern, read_concern ) self.assertEqual("foo", coll.name) self.assertEqual(codec_options, coll.codec_options) self.assertEqual(ReadPreference.SECONDARY, coll.read_preference) self.assertEqual(write_concern, coll.write_concern) self.assertEqual(read_concern, coll.read_concern) def test_getattr(self): db = self.client.pymongo_test self.assertTrue(isinstance(db["_does_not_exist"], Collection)) with self.assertRaises(AttributeError) as context: db._does_not_exist # Message should be: "AttributeError: Database has no attribute # '_does_not_exist'. To access the _does_not_exist collection, # use database['_does_not_exist']". self.assertIn("has no attribute '_does_not_exist'", str(context.exception)) def test_iteration(self): db = self.client.pymongo_test if "PyPy" in sys.version and sys.version_info < (3, 8, 15): msg = "'NoneType' object is not callable" else: msg = "'Database' object is not iterable" # Iteration fails with self.assertRaisesRegex(TypeError, msg): for _ in db: # type: ignore[misc] # error: "None" not callable [misc] break # Index fails with self.assertRaises(TypeError): _ = db[0] # next fails with self.assertRaisesRegex(TypeError, "'Database' object is not iterable"): _ = next(db) # .next() fails with self.assertRaisesRegex(TypeError, "'Database' object is not iterable"): _ = db.next() # Do not implement typing.Iterable. self.assertNotIsInstance(db, Iterable) class TestDatabase(IntegrationTest): def test_equality(self): self.assertNotEqual(Database(self.client, "test"), Database(self.client, "mike")) self.assertEqual(Database(self.client, "test"), Database(self.client, "test")) # Explicitly test inequality self.assertFalse(Database(self.client, "test") != Database(self.client, "test")) def test_hashable(self): self.assertIn(self.client.test, {Database(self.client, "test")}) def test_get_coll(self): db = Database(self.client, "pymongo_test") self.assertEqual(db.test, db["test"]) self.assertEqual(db.test, Collection(db, "test")) self.assertNotEqual(db.test, Collection(db, "mike")) self.assertEqual(db.test.mike, db["test.mike"]) def test_repr(self): self.assertEqual( repr(Database(self.client, "pymongo_test")), "Database({!r}, {})".format(self.client, repr("pymongo_test")), ) def test_create_collection(self): db = Database(self.client, "pymongo_test") db.test.insert_one({"hello": "world"}) self.assertRaises(CollectionInvalid, db.create_collection, "test") db.drop_collection("test") self.assertRaises(TypeError, db.create_collection, 5) self.assertRaises(TypeError, db.create_collection, None) self.assertRaises(InvalidName, db.create_collection, "coll..ection") test = db.create_collection("test") self.assertTrue("test" in db.list_collection_names()) test.insert_one({"hello": "world"}) self.assertEqual(db.test.find_one()["hello"], "world") # type: ignore db.drop_collection("test.foo") db.create_collection("test.foo") self.assertTrue("test.foo" in db.list_collection_names()) self.assertRaises(CollectionInvalid, db.create_collection, "test.foo") def test_list_collection_names(self): db = Database(self.client, "pymongo_test") db.test.insert_one({"dummy": "object"}) db.test.mike.insert_one({"dummy": "object"}) colls = db.list_collection_names() self.assertTrue("test" in colls) self.assertTrue("test.mike" in colls) for coll in colls: self.assertTrue("$" not in coll) db.systemcoll.test.insert_one({}) no_system_collections = db.list_collection_names( filter={"name": {"$regex": r"^(?!system\.)"}} ) for coll in no_system_collections: self.assertTrue(not coll.startswith("system.")) self.assertIn("systemcoll.test", no_system_collections) # Force more than one batch. db = self.client.many_collections for i in range(101): db["coll" + str(i)].insert_one({}) # No Error try: db.list_collection_names() finally: self.client.drop_database("many_collections") def test_list_collection_names_filter(self): listener = OvertCommandListener() client = rs_or_single_client(event_listeners=[listener]) db = client[self.db.name] db.capped.drop() db.create_collection("capped", capped=True, size=4096) db.capped.insert_one({}) db.non_capped.insert_one({}) self.addCleanup(client.drop_database, db.name) filter: Union[None, Mapping[str, Any]] # Should not send nameOnly. for filter in ({"options.capped": True}, {"options.capped": True, "name": "capped"}): listener.reset() names = db.list_collection_names(filter=filter) self.assertEqual(names, ["capped"]) self.assertNotIn("nameOnly", listener.started_events[0].command) # Should send nameOnly (except on 2.6). for filter in (None, {}, {"name": {"$in": ["capped", "non_capped"]}}): listener.reset() names = db.list_collection_names(filter=filter) self.assertIn("capped", names) self.assertIn("non_capped", names) command = listener.started_events[0].command self.assertIn("nameOnly", command) self.assertTrue(command["nameOnly"]) def test_check_exists(self): listener = OvertCommandListener() client = rs_or_single_client(event_listeners=[listener]) self.addCleanup(client.close) db = client[self.db.name] db.drop_collection("unique") db.create_collection("unique", check_exists=True) self.assertIn("listCollections", listener.started_command_names()) listener.reset() db.drop_collection("unique") db.create_collection("unique", check_exists=False) self.assertTrue(len(listener.started_events) > 0) self.assertNotIn("listCollections", listener.started_command_names()) def test_list_collections(self): self.client.drop_database("pymongo_test") db = Database(self.client, "pymongo_test") db.test.insert_one({"dummy": "object"}) db.test.mike.insert_one({"dummy": "object"}) results = db.list_collections() colls = [result["name"] for result in results] # All the collections present. self.assertTrue("test" in colls) self.assertTrue("test.mike" in colls) # No collection containing a '$'. for coll in colls: self.assertTrue("$" not in coll) # Duplicate check. coll_cnt: dict = {} for coll in colls: try: # Found duplicate. coll_cnt[coll] += 1 self.assertTrue(False) except KeyError: coll_cnt[coll] = 1 coll_cnt: dict = {} # Checking if is there any collection which don't exists. if ( len(set(colls) - {"test", "test.mike"}) == 0 or len(set(colls) - {"test", "test.mike", "system.indexes"}) == 0 ): self.assertTrue(True) else: self.assertTrue(False) colls = db.list_collections(filter={"name": {"$regex": "^test$"}}) self.assertEqual(1, len(list(colls))) colls = db.list_collections(filter={"name": {"$regex": "^test.mike$"}}) self.assertEqual(1, len(list(colls))) db.drop_collection("test") db.create_collection("test", capped=True, size=4096) results = db.list_collections(filter={"options.capped": True}) colls = [result["name"] for result in results] # Checking only capped collections are present self.assertTrue("test" in colls) self.assertFalse("test.mike" in colls) # No collection containing a '$'. for coll in colls: self.assertTrue("$" not in coll) # Duplicate check. coll_cnt = {} for coll in colls: try: # Found duplicate. coll_cnt[coll] += 1 self.assertTrue(False) except KeyError: coll_cnt[coll] = 1 coll_cnt = {} # Checking if is there any collection which don't exists. if len(set(colls) - {"test"}) == 0 or len(set(colls) - {"test", "system.indexes"}) == 0: self.assertTrue(True) else: self.assertTrue(False) self.client.drop_database("pymongo_test") def test_list_collection_names_single_socket(self): client = rs_or_single_client(maxPoolSize=1) client.drop_database("test_collection_names_single_socket") db = client.test_collection_names_single_socket for i in range(200): db.create_collection(str(i)) db.list_collection_names() # Must not hang. client.drop_database("test_collection_names_single_socket") def test_drop_collection(self): db = Database(self.client, "pymongo_test") self.assertRaises(TypeError, db.drop_collection, 5) self.assertRaises(TypeError, db.drop_collection, None) db.test.insert_one({"dummy": "object"}) self.assertTrue("test" in db.list_collection_names()) db.drop_collection("test") self.assertFalse("test" in db.list_collection_names()) db.test.insert_one({"dummy": "object"}) self.assertTrue("test" in db.list_collection_names()) db.drop_collection("test") self.assertFalse("test" in db.list_collection_names()) db.test.insert_one({"dummy": "object"}) self.assertTrue("test" in db.list_collection_names()) db.drop_collection(db.test) self.assertFalse("test" in db.list_collection_names()) db.test.insert_one({"dummy": "object"}) self.assertTrue("test" in db.list_collection_names()) db.test.drop() self.assertFalse("test" in db.list_collection_names()) db.test.drop() db.drop_collection(db.test.doesnotexist) if client_context.is_rs: db_wc = Database(self.client, "pymongo_test", write_concern=IMPOSSIBLE_WRITE_CONCERN) with self.assertRaises(WriteConcernError): db_wc.drop_collection("test") def test_validate_collection(self): db = self.client.pymongo_test self.assertRaises(TypeError, db.validate_collection, 5) self.assertRaises(TypeError, db.validate_collection, None) db.test.insert_one({"dummy": "object"}) self.assertRaises(OperationFailure, db.validate_collection, "test.doesnotexist") self.assertRaises(OperationFailure, db.validate_collection, db.test.doesnotexist) self.assertTrue(db.validate_collection("test")) self.assertTrue(db.validate_collection(db.test)) self.assertTrue(db.validate_collection(db.test, full=True)) self.assertTrue(db.validate_collection(db.test, scandata=True)) self.assertTrue(db.validate_collection(db.test, scandata=True, full=True)) self.assertTrue(db.validate_collection(db.test, True, True)) @client_context.require_version_min(4, 3, 3) @client_context.require_no_standalone def test_validate_collection_background(self): db = self.client.pymongo_test.with_options(write_concern=WriteConcern(w="majority")) db.test.insert_one({"dummy": "object"}) coll = db.test self.assertTrue(db.validate_collection(coll, background=False)) # The inMemory storage engine does not support background=True. if client_context.storage_engine != "inMemory": # background=True requires the collection exist in a checkpoint. self.client.admin.command("fsync") self.assertTrue(db.validate_collection(coll, background=True)) self.assertTrue(db.validate_collection(coll, scandata=True, background=True)) # The server does not support background=True with full=True. # Assert that we actually send the background option by checking # that this combination fails. with self.assertRaises(OperationFailure): db.validate_collection(coll, full=True, background=True) def test_command(self): self.maxDiff = None db = self.client.admin first = db.command("buildinfo") second = db.command({"buildinfo": 1}) third = db.command("buildinfo", 1) self.assertEqualReply(first, second) self.assertEqualReply(second, third) # We use 'aggregate' as our example command, since it's an easy way to # retrieve a BSON regex from a collection using a command. def test_command_with_regex(self): db = self.client.pymongo_test db.test.drop() db.test.insert_one({"r": re.compile(".*")}) db.test.insert_one({"r": Regex(".*")}) result = db.command("aggregate", "test", pipeline=[], cursor={}) for doc in result["cursor"]["firstBatch"]: self.assertTrue(isinstance(doc["r"], Regex)) def test_cursor_command(self): db = self.client.pymongo_test db.test.drop() docs = [{"_id": i, "doc": i} for i in range(3)] db.test.insert_many(docs) cursor = db.cursor_command("find", "test") self.assertIsInstance(cursor, CommandCursor) result_docs = list(cursor) self.assertEqual(docs, result_docs) def test_cursor_command_invalid(self): self.assertRaises(InvalidOperation, self.db.cursor_command, "usersInfo", "test") def test_password_digest(self): self.assertRaises(TypeError, auth._password_digest, 5) self.assertRaises(TypeError, auth._password_digest, True) self.assertRaises(TypeError, auth._password_digest, None) self.assertTrue(isinstance(auth._password_digest("mike", "password"), str)) self.assertEqual( auth._password_digest("mike", "password"), "cd7e45b3b2767dc2fa9b6b548457ed00" ) self.assertEqual( auth._password_digest("Gustave", "Dor\xe9"), "81e0e2364499209f466e75926a162d73" ) def test_id_ordering(self): # PyMongo attempts to have _id show up first # when you iterate key/value pairs in a document. # This isn't reliable since python dicts don't # guarantee any particular order. This will never # work right in Jython or any Python or environment # with hash randomization enabled (e.g. tox). db = self.client.pymongo_test db.test.drop() db.test.insert_one(SON([("hello", "world"), ("_id", 5)])) db = self.client.get_database( "pymongo_test", codec_options=CodecOptions(document_class=SON[str, Any]) ) cursor = db.test.find() for x in cursor: for k, _v in x.items(): self.assertEqual(k, "_id") break def test_deref(self): db = self.client.pymongo_test db.test.drop() self.assertRaises(TypeError, db.dereference, 5) self.assertRaises(TypeError, db.dereference, "hello") self.assertRaises(TypeError, db.dereference, None) self.assertEqual(None, db.dereference(DBRef("test", ObjectId()))) obj: dict[str, Any] = {"x": True} key = db.test.insert_one(obj).inserted_id self.assertEqual(obj, db.dereference(DBRef("test", key))) self.assertEqual(obj, db.dereference(DBRef("test", key, "pymongo_test"))) self.assertRaises(ValueError, db.dereference, DBRef("test", key, "foo")) self.assertEqual(None, db.dereference(DBRef("test", 4))) obj = {"_id": 4} db.test.insert_one(obj) self.assertEqual(obj, db.dereference(DBRef("test", 4))) def test_deref_kwargs(self): db = self.client.pymongo_test db.test.drop() db.test.insert_one({"_id": 4, "foo": "bar"}) db = self.client.get_database( "pymongo_test", codec_options=CodecOptions(document_class=SON[str, Any]) ) self.assertEqual( SON([("foo", "bar")]), db.dereference(DBRef("test", 4), projection={"_id": False}) ) # TODO some of these tests belong in the collection level testing. def test_insert_find_one(self): db = self.client.pymongo_test db.test.drop() a_doc = SON({"hello": "world"}) a_key = db.test.insert_one(a_doc).inserted_id self.assertTrue(isinstance(a_doc["_id"], ObjectId)) self.assertEqual(a_doc["_id"], a_key) self.assertEqual(a_doc, db.test.find_one({"_id": a_doc["_id"]})) self.assertEqual(a_doc, db.test.find_one(a_key)) self.assertEqual(None, db.test.find_one(ObjectId())) self.assertEqual(a_doc, db.test.find_one({"hello": "world"})) self.assertEqual(None, db.test.find_one({"hello": "test"})) b = db.test.find_one() assert b is not None b["hello"] = "mike" db.test.replace_one({"_id": b["_id"]}, b) self.assertNotEqual(a_doc, db.test.find_one(a_key)) self.assertEqual(b, db.test.find_one(a_key)) self.assertEqual(b, db.test.find_one()) count = 0 for _ in db.test.find(): count += 1 self.assertEqual(count, 1) def test_long(self): db = self.client.pymongo_test db.test.drop() db.test.insert_one({"x": 9223372036854775807}) retrieved = db.test.find_one()["x"] # type: ignore self.assertEqual(Int64(9223372036854775807), retrieved) self.assertIsInstance(retrieved, Int64) db.test.delete_many({}) db.test.insert_one({"x": Int64(1)}) retrieved = db.test.find_one()["x"] # type: ignore self.assertEqual(Int64(1), retrieved) self.assertIsInstance(retrieved, Int64) def test_delete(self): db = self.client.pymongo_test db.test.drop() db.test.insert_one({"x": 1}) db.test.insert_one({"x": 2}) db.test.insert_one({"x": 3}) length = 0 for _ in db.test.find(): length += 1 self.assertEqual(length, 3) db.test.delete_one({"x": 1}) length = 0 for _ in db.test.find(): length += 1 self.assertEqual(length, 2) db.test.delete_one(db.test.find_one()) # type: ignore[arg-type] db.test.delete_one(db.test.find_one()) # type: ignore[arg-type] self.assertEqual(db.test.find_one(), None) db.test.insert_one({"x": 1}) db.test.insert_one({"x": 2}) db.test.insert_one({"x": 3}) self.assertTrue(db.test.find_one({"x": 2})) db.test.delete_one({"x": 2}) self.assertFalse(db.test.find_one({"x": 2})) self.assertTrue(db.test.find_one()) db.test.delete_many({}) self.assertFalse(db.test.find_one()) def test_command_response_without_ok(self): # Sometimes (SERVER-10891) the server's response to a badly-formatted # command document will have no 'ok' field. We should raise # OperationFailure instead of KeyError. self.assertRaises(OperationFailure, helpers._check_command_response, {}, None) try: helpers._check_command_response({"$err": "foo"}, None) except OperationFailure as e: self.assertEqual(e.args[0], "foo, full error: {'$err': 'foo'}") else: self.fail("_check_command_response didn't raise OperationFailure") def test_mongos_response(self): error_document = { "ok": 0, "errmsg": "outer", "raw": {"shard0/host0,host1": {"ok": 0, "errmsg": "inner"}}, } with self.assertRaises(OperationFailure) as context: helpers._check_command_response(error_document, None) self.assertIn("inner", str(context.exception)) # If a shard has no primary and you run a command like dbstats, which # cannot be run on a secondary, mongos's response includes empty "raw" # errors. See SERVER-15428. error_document = {"ok": 0, "errmsg": "outer", "raw": {"shard0/host0,host1": {}}} with self.assertRaises(OperationFailure) as context: helpers._check_command_response(error_document, None) self.assertIn("outer", str(context.exception)) # Raw error has ok: 0 but no errmsg. Not a known case, but test it. error_document = {"ok": 0, "errmsg": "outer", "raw": {"shard0/host0,host1": {"ok": 0}}} with self.assertRaises(OperationFailure) as context: helpers._check_command_response(error_document, None) self.assertIn("outer", str(context.exception)) @client_context.require_test_commands @client_context.require_no_mongos def test_command_max_time_ms(self): self.client.admin.command("configureFailPoint", "maxTimeAlwaysTimeOut", mode="alwaysOn") try: db = self.client.pymongo_test db.command("count", "test") self.assertRaises(ExecutionTimeout, db.command, "count", "test", maxTimeMS=1) pipeline = [{"$project": {"name": 1, "count": 1}}] # Database command helper. db.command("aggregate", "test", pipeline=pipeline, cursor={}) self.assertRaises( ExecutionTimeout, db.command, "aggregate", "test", pipeline=pipeline, cursor={}, maxTimeMS=1, ) # Collection helper. db.test.aggregate(pipeline=pipeline) self.assertRaises(ExecutionTimeout, db.test.aggregate, pipeline, maxTimeMS=1) finally: self.client.admin.command("configureFailPoint", "maxTimeAlwaysTimeOut", mode="off") def test_with_options(self): codec_options = DECIMAL_CODECOPTS read_preference = ReadPreference.SECONDARY_PREFERRED write_concern = WriteConcern(j=True) read_concern = ReadConcern(level="majority") # List of all options to compare. allopts = [ "name", "client", "codec_options", "read_preference", "write_concern", "read_concern", ] db1 = self.client.get_database( "with_options_test", codec_options=codec_options, read_preference=read_preference, write_concern=write_concern, read_concern=read_concern, ) # Case 1: swap no options db2 = db1.with_options() for opt in allopts: self.assertEqual(getattr(db1, opt), getattr(db2, opt)) # Case 2: swap all options newopts = { "codec_options": CodecOptions(), "read_preference": ReadPreference.PRIMARY, "write_concern": WriteConcern(w=1), "read_concern": ReadConcern(level="local"), } db2 = db1.with_options(**newopts) # type: ignore[arg-type] for opt in newopts: self.assertEqual(getattr(db2, opt), newopts.get(opt, getattr(db1, opt))) class TestDatabaseAggregation(IntegrationTest): def setUp(self): self.pipeline: List[Mapping[str, Any]] = [ {"$listLocalSessions": {}}, {"$limit": 1}, {"$addFields": {"dummy": "dummy field"}}, {"$project": {"_id": 0, "dummy": 1}}, ] self.result = {"dummy": "dummy field"} self.admin = self.client.admin def test_database_aggregation(self): with self.admin.aggregate(self.pipeline) as cursor: result = next(cursor) self.assertEqual(result, self.result) @client_context.require_no_mongos def test_database_aggregation_fake_cursor(self): coll_name = "test_output" write_stage: dict if client_context.version < (4, 3): db_name = "admin" write_stage = {"$out": coll_name} else: # SERVER-43287 disallows writing with $out to the admin db, use # $merge instead. db_name = "pymongo_test" write_stage = {"$merge": {"into": {"db": db_name, "coll": coll_name}}} output_coll = self.client[db_name][coll_name] output_coll.drop() self.addCleanup(output_coll.drop) admin = self.admin.with_options(write_concern=WriteConcern(w=0)) pipeline = self.pipeline[:] pipeline.append(write_stage) with admin.aggregate(pipeline) as cursor: with self.assertRaises(StopIteration): next(cursor) result = wait_until(output_coll.find_one, "read unacknowledged write") self.assertEqual(result["dummy"], self.result["dummy"]) def test_bool(self): with self.assertRaises(NotImplementedError): bool(Database(self.client, "test")) if __name__ == "__main__": unittest.main() mongodb-mongo-python-driver-509e9b7/test/test_dbref.py000066400000000000000000000233321462766011000231120ustar00rootroot00000000000000# Copyright 2009-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. """Tests for the dbref module.""" from __future__ import annotations import pickle import sys from typing import Any sys.path[0:0] = [""] from copy import deepcopy from test import unittest from bson import decode, encode from bson.dbref import DBRef from bson.objectid import ObjectId class TestDBRef(unittest.TestCase): def test_creation(self): a = ObjectId() self.assertRaises(TypeError, DBRef) self.assertRaises(TypeError, DBRef, "coll") self.assertRaises(TypeError, DBRef, 4, a) self.assertRaises(TypeError, DBRef, 1.5, a) self.assertRaises(TypeError, DBRef, a, a) self.assertRaises(TypeError, DBRef, None, a) self.assertRaises(TypeError, DBRef, "coll", a, 5) self.assertTrue(DBRef("coll", a)) self.assertTrue(DBRef("coll", 5)) self.assertTrue(DBRef("coll", 5, "database")) def test_read_only(self): a = DBRef("coll", ObjectId()) def foo(): a.collection = "blah" # type: ignore[misc] def bar(): a.id = "aoeu" # type: ignore[misc] self.assertEqual("coll", a.collection) a.id self.assertEqual(None, a.database) self.assertRaises(AttributeError, foo) self.assertRaises(AttributeError, bar) def test_repr(self): self.assertEqual( repr(DBRef("coll", ObjectId("1234567890abcdef12345678"))), "DBRef('coll', ObjectId('1234567890abcdef12345678'))", ) self.assertEqual( repr(DBRef("coll", ObjectId("1234567890abcdef12345678"))), "DBRef({}, ObjectId('1234567890abcdef12345678'))".format(repr("coll")), ) self.assertEqual(repr(DBRef("coll", 5, foo="bar")), "DBRef('coll', 5, foo='bar')") self.assertEqual( repr(DBRef("coll", ObjectId("1234567890abcdef12345678"), "foo")), "DBRef('coll', ObjectId('1234567890abcdef12345678'), 'foo')", ) def test_equality(self): obj_id = ObjectId("1234567890abcdef12345678") self.assertEqual(DBRef("foo", 5), DBRef("foo", 5)) self.assertEqual(DBRef("coll", obj_id), DBRef("coll", obj_id)) self.assertNotEqual(DBRef("coll", obj_id), DBRef("coll", obj_id, "foo")) self.assertNotEqual(DBRef("coll", obj_id), DBRef("col", obj_id)) self.assertNotEqual(DBRef("coll", obj_id), DBRef("coll", ObjectId(b"123456789011"))) self.assertNotEqual(DBRef("coll", obj_id), 4) self.assertNotEqual(DBRef("coll", obj_id, "foo"), DBRef("coll", obj_id, "bar")) # Explicitly test inequality self.assertFalse(DBRef("foo", 5) != DBRef("foo", 5)) self.assertFalse(DBRef("coll", obj_id) != DBRef("coll", obj_id)) self.assertFalse(DBRef("coll", obj_id, "foo") != DBRef("coll", obj_id, "foo")) def test_kwargs(self): self.assertEqual(DBRef("coll", 5, foo="bar"), DBRef("coll", 5, foo="bar")) self.assertNotEqual(DBRef("coll", 5, foo="bar"), DBRef("coll", 5)) self.assertNotEqual(DBRef("coll", 5, foo="bar"), DBRef("coll", 5, foo="baz")) self.assertEqual("bar", DBRef("coll", 5, foo="bar").foo) self.assertRaises(AttributeError, getattr, DBRef("coll", 5, foo="bar"), "bar") def test_deepcopy(self): a = DBRef("coll", "asdf", "db", x=[1]) b = deepcopy(a) self.assertEqual(a, b) self.assertNotEqual(id(a), id(b.x)) self.assertEqual(a.x, b.x) self.assertNotEqual(id(a.x), id(b.x)) b.x[0] = 2 self.assertEqual(a.x, [1]) self.assertEqual(b.x, [2]) def test_pickling(self): dbr = DBRef("coll", 5, foo="bar") for protocol in [0, 1, 2, -1]: pkl = pickle.dumps(dbr, protocol=protocol) dbr2 = pickle.loads(pkl) self.assertEqual(dbr, dbr2) def test_dbref_hash(self): dbref_1a = DBRef("collection", "id", "database") dbref_1b = DBRef("collection", "id", "database") self.assertEqual(hash(dbref_1a), hash(dbref_1b)) dbref_2a = DBRef("collection", "id", "database", custom="custom") dbref_2b = DBRef("collection", "id", "database", custom="custom") self.assertEqual(hash(dbref_2a), hash(dbref_2b)) self.assertNotEqual(hash(dbref_1a), hash(dbref_2a)) # https://github.com/mongodb/specifications/blob/master/source/dbref.rst#test-plan class TestDBRefSpec(unittest.TestCase): def test_decoding_1_2_3(self): doc: Any for doc in [ # 1, Valid documents MUST be decoded to a DBRef: {"$ref": "coll0", "$id": ObjectId("60a6fe9a54f4180c86309efa")}, {"$ref": "coll0", "$id": 1}, {"$ref": "coll0", "$id": None}, {"$ref": "coll0", "$id": 1, "$db": "db0"}, # 2, Valid documents with extra fields: {"$ref": "coll0", "$id": 1, "$db": "db0", "foo": "bar"}, {"$ref": "coll0", "$id": 1, "foo": True, "bar": False}, {"$ref": "coll0", "$id": 1, "meta": {"foo": 1, "bar": 2}}, {"$ref": "coll0", "$id": 1, "$foo": "bar"}, {"$ref": "coll0", "$id": 1, "foo.bar": 0}, # 3, Valid documents with out of order fields: {"$id": 1, "$ref": "coll0"}, {"$db": "db0", "$ref": "coll0", "$id": 1}, {"foo": 1, "$id": 1, "$ref": "coll0"}, {"foo": 1, "$ref": "coll0", "$id": 1, "$db": "db0"}, {"foo": 1, "$ref": "coll0", "$id": 1, "$db": "db0", "bar": 1}, ]: with self.subTest(doc=doc): decoded = decode(encode({"dbref": doc})) dbref = decoded["dbref"] self.assertIsInstance(dbref, DBRef) self.assertEqual(dbref.collection, doc["$ref"]) self.assertEqual(dbref.id, doc["$id"]) self.assertEqual(dbref.database, doc.get("$db")) for extra in set(doc.keys()) - {"$ref", "$id", "$db"}: self.assertEqual(getattr(dbref, extra), doc[extra]) def test_decoding_4_5(self): for doc in [ # 4, Documents missing required fields MUST NOT be decoded to a # DBRef: {"$ref": "coll0"}, {"$id": ObjectId("60a6fe9a54f4180c86309efa")}, {"$db": "db0"}, # 5, Documents with invalid types for $ref or $db MUST NOT be # decoded to a DBRef {"$ref": True, "$id": 1}, {"$ref": "coll0", "$id": 1, "$db": 1}, ]: with self.subTest(doc=doc): decoded = decode(encode({"dbref": doc})) dbref = decoded["dbref"] self.assertIsInstance(dbref, dict) def test_encoding_1_2(self): doc: Any for doc in [ # 1, Encoding DBRefs with basic fields: {"$ref": "coll0", "$id": ObjectId("60a6fe9a54f4180c86309efa")}, {"$ref": "coll0", "$id": 1}, {"$ref": "coll0", "$id": None}, {"$ref": "coll0", "$id": 1, "$db": "db0"}, # 2, Encoding DBRefs with extra, optional fields: {"$ref": "coll0", "$id": 1, "$db": "db0", "foo": "bar"}, {"$ref": "coll0", "$id": 1, "foo": True, "bar": False}, {"$ref": "coll0", "$id": 1, "meta": {"foo": 1, "bar": 2}}, {"$ref": "coll0", "$id": 1, "$foo": "bar"}, {"$ref": "coll0", "$id": 1, "foo.bar": 0}, ]: with self.subTest(doc=doc): # Decode the test input to a DBRef via a BSON roundtrip. encoded_doc = encode({"dbref": doc}) decoded = decode(encoded_doc) dbref = decoded["dbref"] self.assertIsInstance(dbref, DBRef) # Encode the DBRef. encoded_dbref = encode(decoded) self.assertEqual(encoded_dbref, encoded_doc) # Ensure extra fields are present. for extra in set(doc.keys()) - {"$ref", "$id", "$db"}: self.assertEqual(getattr(dbref, extra), doc[extra]) def test_encoding_3(self): for doc in [ # 3, Encoding DBRefs re-orders any out of order fields during # decoding: {"$id": 1, "$ref": "coll0"}, {"$db": "db0", "$ref": "coll0", "$id": 1}, {"foo": 1, "$id": 1, "$ref": "coll0"}, {"foo": 1, "$ref": "coll0", "$id": 1, "$db": "db0"}, {"foo": 1, "$ref": "coll0", "$id": 1, "$db": "db0", "bar": 1}, ]: with self.subTest(doc=doc): # Decode the test input to a DBRef via a BSON roundtrip. encoded_doc = encode({"dbref": doc}) decoded = decode(encoded_doc) dbref = decoded["dbref"] self.assertIsInstance(dbref, DBRef) # Encode the DBRef. encoded_dbref = encode(decoded) # BSON does not match because DBRef fields are reordered. self.assertNotEqual(encoded_dbref, encoded_doc) self.assertEqual(decode(encoded_dbref), decode(encoded_doc)) # Ensure extra fields are present. for extra in set(doc.keys()) - {"$ref", "$id", "$db"}: self.assertEqual(getattr(dbref, extra), doc[extra]) if __name__ == "__main__": unittest.main() mongodb-mongo-python-driver-509e9b7/test/test_decimal128.py000066400000000000000000000051171462766011000236620ustar00rootroot00000000000000# Copyright 2016-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. """Tests for Decimal128.""" from __future__ import annotations import pickle import sys from decimal import Decimal sys.path[0:0] = [""] from test import client_context, unittest from bson.decimal128 import Decimal128, create_decimal128_context class TestDecimal128(unittest.TestCase): @client_context.require_connection def test_round_trip(self): coll = client_context.client.pymongo_test.test coll.drop() dec128 = Decimal128.from_bid(b"\x00@cR\xbf\xc6\x01\x00\x00\x00\x00\x00\x00\x00\x1c0") coll.insert_one({"dec128": dec128}) doc = coll.find_one({"dec128": dec128}) assert doc is not None self.assertIsNotNone(doc) self.assertEqual(doc["dec128"], dec128) def test_pickle(self): dec128 = Decimal128.from_bid(b"\x00@cR\xbf\xc6\x01\x00\x00\x00\x00\x00\x00\x00\x1c0") for protocol in range(pickle.HIGHEST_PROTOCOL + 1): pkl = pickle.dumps(dec128, protocol=protocol) self.assertEqual(dec128, pickle.loads(pkl)) def test_special(self): dnan = Decimal("NaN") dnnan = Decimal("-NaN") dsnan = Decimal("sNaN") dnsnan = Decimal("-sNaN") dnan128 = Decimal128(dnan) dnnan128 = Decimal128(dnnan) dsnan128 = Decimal128(dsnan) dnsnan128 = Decimal128(dnsnan) # Due to the comparison rules for decimal.Decimal we have to # compare strings. self.assertEqual(str(dnan), str(dnan128.to_decimal())) self.assertEqual(str(dnnan), str(dnnan128.to_decimal())) self.assertEqual(str(dsnan), str(dsnan128.to_decimal())) self.assertEqual(str(dnsnan), str(dnsnan128.to_decimal())) def test_decimal128_context(self): ctx = create_decimal128_context() self.assertEqual("NaN", str(ctx.copy().create_decimal(".13.1"))) self.assertEqual("Infinity", str(ctx.copy().create_decimal("1E6145"))) self.assertEqual("0E-6176", str(ctx.copy().create_decimal("1E-6177"))) if __name__ == "__main__": unittest.main() mongodb-mongo-python-driver-509e9b7/test/test_default_exports.py000066400000000000000000000041251462766011000252370ustar00rootroot00000000000000# Copyright 2022-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. """Test the default exports of the top level packages.""" from __future__ import annotations import inspect import unittest import bson import gridfs import pymongo BSON_IGNORE = [] GRIDFS_IGNORE = [ "ASCENDING", "DESCENDING", "ClientSession", "Collection", "ObjectId", "validate_string", "Database", "ConfigurationError", "WriteConcern", ] PYMONGO_IGNORE = [] GLOBAL_INGORE = ["TYPE_CHECKING", "annotations"] class TestDefaultExports(unittest.TestCase): def check_module(self, mod, ignores): names = dir(mod) names.remove("__all__") for name in mod.__all__: if name not in names and name not in ignores: self.fail(f"{name} was included in {mod}.__all__ but is not a valid symbol") for name in names: if name not in mod.__all__ and name not in ignores: if name in GLOBAL_INGORE: continue value = getattr(mod, name) if inspect.ismodule(value): continue if getattr(value, "__module__", None) == "typing": continue if not name.startswith("_"): self.fail(f"{name} was not included in {mod}.__all__") def test_pymongo(self): self.check_module(pymongo, PYMONGO_IGNORE) def test_gridfs(self): self.check_module(gridfs, GRIDFS_IGNORE) def test_bson(self): self.check_module(bson, BSON_IGNORE) if __name__ == "__main__": unittest.main() mongodb-mongo-python-driver-509e9b7/test/test_discovery_and_monitoring.py000066400000000000000000000373411462766011000271330ustar00rootroot00000000000000# Copyright 2014-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. """Test the topology module.""" from __future__ import annotations import os import socketserver import sys import threading sys.path[0:0] = [""] from test import IntegrationTest, unittest from test.pymongo_mocks import DummyMonitor from test.unified_format import generate_test_classes from test.utils import ( CMAPListener, HeartbeatEventListener, HeartbeatEventsListListener, assertion_context, client_context, get_pool, rs_or_single_client, server_name_to_type, single_client, wait_until, ) from unittest.mock import patch from bson import Timestamp, json_util from pymongo import MongoClient, common, monitoring from pymongo.errors import ( AutoReconnect, ConfigurationError, NetworkTimeout, NotPrimaryError, OperationFailure, ) from pymongo.hello import Hello, HelloCompat from pymongo.helpers import _check_command_response, _check_write_command_response from pymongo.monitoring import ServerHeartbeatFailedEvent, ServerHeartbeatStartedEvent from pymongo.server_description import SERVER_TYPE, ServerDescription from pymongo.settings import TopologySettings from pymongo.topology import Topology, _ErrorContext from pymongo.topology_description import TOPOLOGY_TYPE from pymongo.uri_parser import parse_uri # Location of JSON test specifications. SDAM_PATH = os.path.join(os.path.dirname(os.path.realpath(__file__)), "discovery_and_monitoring") def create_mock_topology(uri, monitor_class=DummyMonitor): parsed_uri = parse_uri(uri) replica_set_name = None direct_connection = None load_balanced = None if "replicaset" in parsed_uri["options"]: replica_set_name = parsed_uri["options"]["replicaset"] if "directConnection" in parsed_uri["options"]: direct_connection = parsed_uri["options"]["directConnection"] if "loadBalanced" in parsed_uri["options"]: load_balanced = parsed_uri["options"]["loadBalanced"] topology_settings = TopologySettings( parsed_uri["nodelist"], replica_set_name=replica_set_name, monitor_class=monitor_class, direct_connection=direct_connection, load_balanced=load_balanced, ) c = Topology(topology_settings) c.open() return c def got_hello(topology, server_address, hello_response): server_description = ServerDescription(server_address, Hello(hello_response), 0) topology.on_change(server_description) def got_app_error(topology, app_error): server_address = common.partition_node(app_error["address"]) server = topology.get_server_by_address(server_address) error_type = app_error["type"] generation = app_error.get("generation", server.pool.gen.get_overall()) when = app_error["when"] max_wire_version = app_error["maxWireVersion"] # XXX: We could get better test coverage by mocking the errors on the # Pool/Connection. try: if error_type == "command": _check_command_response(app_error["response"], max_wire_version) _check_write_command_response(app_error["response"]) elif error_type == "network": raise AutoReconnect("mock non-timeout network error") elif error_type == "timeout": raise NetworkTimeout("mock network timeout error") else: raise AssertionError(f"unknown error type: {error_type}") raise AssertionError except (AutoReconnect, NotPrimaryError, OperationFailure) as e: if when == "beforeHandshakeCompletes": completed_handshake = False elif when == "afterHandshakeCompletes": completed_handshake = True else: raise AssertionError(f"Unknown when field {when}") topology.handle_error( server_address, _ErrorContext(e, max_wire_version, generation, completed_handshake, None), ) def get_type(topology, hostname): description = topology.get_server_by_address((hostname, 27017)).description return description.server_type class TestAllScenarios(unittest.TestCase): pass def topology_type_name(topology_type): return TOPOLOGY_TYPE._fields[topology_type] def server_type_name(server_type): return SERVER_TYPE._fields[server_type] def check_outcome(self, topology, outcome): expected_servers = outcome["servers"] # Check weak equality before proceeding. self.assertEqual(len(topology.description.server_descriptions()), len(expected_servers)) if outcome.get("compatible") is False: with self.assertRaises(ConfigurationError): topology.description.check_compatible() else: # No error. topology.description.check_compatible() # Since lengths are equal, every actual server must have a corresponding # expected server. for expected_server_address, expected_server in expected_servers.items(): node = common.partition_node(expected_server_address) self.assertTrue(topology.has_server(node)) actual_server = topology.get_server_by_address(node) actual_server_description = actual_server.description expected_server_type = server_name_to_type(expected_server["type"]) self.assertEqual( server_type_name(expected_server_type), server_type_name(actual_server_description.server_type), ) self.assertEqual(expected_server.get("setName"), actual_server_description.replica_set_name) self.assertEqual(expected_server.get("setVersion"), actual_server_description.set_version) self.assertEqual(expected_server.get("electionId"), actual_server_description.election_id) self.assertEqual( expected_server.get("topologyVersion"), actual_server_description.topology_version ) expected_pool = expected_server.get("pool") if expected_pool: self.assertEqual(expected_pool.get("generation"), actual_server.pool.gen.get_overall()) self.assertEqual(outcome["setName"], topology.description.replica_set_name) self.assertEqual( outcome.get("logicalSessionTimeoutMinutes"), topology.description.logical_session_timeout_minutes, ) expected_topology_type = getattr(TOPOLOGY_TYPE, outcome["topologyType"]) self.assertEqual( topology_type_name(expected_topology_type), topology_type_name(topology.description.topology_type), ) self.assertEqual(outcome.get("maxSetVersion"), topology.description.max_set_version) self.assertEqual(outcome.get("maxElectionId"), topology.description.max_election_id) def create_test(scenario_def): def run_scenario(self): c = create_mock_topology(scenario_def["uri"]) for i, phase in enumerate(scenario_def["phases"]): # Including the phase description makes failures easier to debug. description = phase.get("description", str(i)) with assertion_context(f"phase: {description}"): for response in phase.get("responses", []): got_hello(c, common.partition_node(response[0]), response[1]) for app_error in phase.get("applicationErrors", []): got_app_error(c, app_error) check_outcome(self, c, phase["outcome"]) return run_scenario def create_tests(): for dirpath, _, filenames in os.walk(SDAM_PATH): dirname = os.path.split(dirpath)[-1] # SDAM unified tests are handled separately. if dirname == "unified": continue for filename in filenames: if os.path.splitext(filename)[1] != ".json": continue with open(os.path.join(dirpath, filename)) as scenario_stream: scenario_def = json_util.loads(scenario_stream.read()) # Construct test from scenario. new_test = create_test(scenario_def) test_name = f"test_{dirname}_{os.path.splitext(filename)[0]}" new_test.__name__ = test_name setattr(TestAllScenarios, new_test.__name__, new_test) create_tests() class TestClusterTimeComparison(unittest.TestCase): def test_cluster_time_comparison(self): t = create_mock_topology("mongodb://host") def send_cluster_time(time, inc, should_update): old = t.max_cluster_time() new = {"clusterTime": Timestamp(time, inc)} got_hello( t, ("host", 27017), {"ok": 1, "minWireVersion": 0, "maxWireVersion": 6, "$clusterTime": new}, ) actual = t.max_cluster_time() if should_update: self.assertEqual(actual, new) else: self.assertEqual(actual, old) send_cluster_time(0, 1, True) send_cluster_time(2, 2, True) send_cluster_time(2, 1, False) send_cluster_time(1, 3, False) send_cluster_time(2, 3, True) class TestIgnoreStaleErrors(IntegrationTest): def test_ignore_stale_connection_errors(self): N_THREADS = 5 barrier = threading.Barrier(N_THREADS, timeout=30) client = rs_or_single_client(minPoolSize=N_THREADS) self.addCleanup(client.close) # Wait for initial discovery. client.admin.command("ping") pool = get_pool(client) starting_generation = pool.gen.get_overall() wait_until(lambda: len(pool.conns) == N_THREADS, "created conns") def mock_command(*args, **kwargs): # Synchronize all threads to ensure they use the same generation. barrier.wait() raise AutoReconnect("mock Connection.command error") for sock in pool.conns: sock.command = mock_command def insert_command(i): try: client.test.command("insert", "test", documents=[{"i": i}]) except AutoReconnect: pass threads = [] for i in range(N_THREADS): threads.append(threading.Thread(target=insert_command, args=(i,))) for t in threads: t.start() for t in threads: t.join() # Expect a single pool reset for the network error self.assertEqual(starting_generation + 1, pool.gen.get_overall()) # Server should be selectable. client.admin.command("ping") class CMAPHeartbeatListener(HeartbeatEventListener, CMAPListener): pass class TestPoolManagement(IntegrationTest): @client_context.require_failCommand_appName def test_pool_unpause(self): # This test implements the prose test "Connection Pool Management" listener = CMAPHeartbeatListener() client = single_client( appName="SDAMPoolManagementTest", heartbeatFrequencyMS=500, event_listeners=[listener] ) self.addCleanup(client.close) # Assert that ConnectionPoolReadyEvent occurs after the first # ServerHeartbeatSucceededEvent. listener.wait_for_event(monitoring.PoolReadyEvent, 1) pool_ready = listener.events_by_type(monitoring.PoolReadyEvent)[0] hb_succeeded = listener.events_by_type(monitoring.ServerHeartbeatSucceededEvent)[0] self.assertGreater(listener.events.index(pool_ready), listener.events.index(hb_succeeded)) listener.reset() fail_hello = { "mode": {"times": 2}, "data": { "failCommands": [HelloCompat.LEGACY_CMD, "hello"], "errorCode": 1234, "appName": "SDAMPoolManagementTest", }, } with self.fail_point(fail_hello): listener.wait_for_event(monitoring.ServerHeartbeatFailedEvent, 1) listener.wait_for_event(monitoring.PoolClearedEvent, 1) listener.wait_for_event(monitoring.ServerHeartbeatSucceededEvent, 1) listener.wait_for_event(monitoring.PoolReadyEvent, 1) class TestServerMonitoringMode(IntegrationTest): @client_context.require_no_serverless @client_context.require_no_load_balancer def setUp(self): super().setUp() def test_rtt_connection_is_enabled_stream(self): client = rs_or_single_client(serverMonitoringMode="stream") self.addCleanup(client.close) client.admin.command("ping") def predicate(): for _, server in client._topology._servers.items(): monitor = server._monitor if not monitor._stream: return False if client_context.version >= (4, 4): if monitor._rtt_monitor._executor._thread is None: return False else: if monitor._rtt_monitor._executor._thread is not None: return False return True wait_until(predicate, "find all RTT monitors") def test_rtt_connection_is_disabled_poll(self): client = rs_or_single_client(serverMonitoringMode="poll") self.addCleanup(client.close) self.assert_rtt_connection_is_disabled(client) def test_rtt_connection_is_disabled_auto(self): envs = [ {"AWS_EXECUTION_ENV": "AWS_Lambda_python3.9"}, {"FUNCTIONS_WORKER_RUNTIME": "python"}, {"K_SERVICE": "gcpservicename"}, {"FUNCTION_NAME": "gcpfunctionname"}, {"VERCEL": "1"}, ] for env in envs: with patch.dict("os.environ", env): client = rs_or_single_client(serverMonitoringMode="auto") self.addCleanup(client.close) self.assert_rtt_connection_is_disabled(client) def assert_rtt_connection_is_disabled(self, client): client.admin.command("ping") for _, server in client._topology._servers.items(): monitor = server._monitor self.assertFalse(monitor._stream) self.assertIsNone(monitor._rtt_monitor._executor._thread) class MockTCPHandler(socketserver.BaseRequestHandler): def handle(self): self.server.events.append("client connected") if self.request.recv(1024).strip(): self.server.events.append("client hello received") self.request.close() class TCPServer(socketserver.TCPServer): allow_reuse_address = True def handle_request_and_shutdown(self): self.handle_request() self.server_close() class TestHeartbeatStartOrdering(unittest.TestCase): def test_heartbeat_start_ordering(self): events = [] listener = HeartbeatEventsListListener(events) server = TCPServer(("localhost", 9999), MockTCPHandler) server.events = events server_thread = threading.Thread(target=server.handle_request_and_shutdown) server_thread.start() _c = MongoClient( "mongodb://localhost:9999", serverSelectionTimeoutMS=500, event_listeners=(listener,) ) server_thread.join() listener.wait_for_event(ServerHeartbeatStartedEvent, 1) listener.wait_for_event(ServerHeartbeatFailedEvent, 1) self.assertEqual( events, [ "serverHeartbeatStartedEvent", "client connected", "client hello received", "serverHeartbeatFailedEvent", ], ) # Generate unified tests. globals().update(generate_test_classes(os.path.join(SDAM_PATH, "unified"), module=__name__)) if __name__ == "__main__": unittest.main() mongodb-mongo-python-driver-509e9b7/test/test_dns.py000066400000000000000000000156301462766011000226160ustar00rootroot00000000000000# Copyright 2017 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. """Run the SRV support tests.""" from __future__ import annotations import glob import json import os import sys sys.path[0:0] = [""] from test import IntegrationTest, client_context, unittest from test.utils import wait_until from pymongo.common import validate_read_preference_tags from pymongo.errors import ConfigurationError from pymongo.mongo_client import MongoClient from pymongo.uri_parser import parse_uri, split_hosts class TestDNSRepl(unittest.TestCase): TEST_PATH = os.path.join( os.path.dirname(os.path.realpath(__file__)), "srv_seedlist", "replica-set" ) load_balanced = False @client_context.require_replica_set def setUp(self): pass class TestDNSLoadBalanced(unittest.TestCase): TEST_PATH = os.path.join( os.path.dirname(os.path.realpath(__file__)), "srv_seedlist", "load-balanced" ) load_balanced = True @client_context.require_load_balancer def setUp(self): pass class TestDNSSharded(unittest.TestCase): TEST_PATH = os.path.join(os.path.dirname(os.path.realpath(__file__)), "srv_seedlist", "sharded") load_balanced = False @client_context.require_mongos def setUp(self): pass def create_test(test_case): def run_test(self): uri = test_case["uri"] seeds = test_case.get("seeds") num_seeds = test_case.get("numSeeds", len(seeds or [])) hosts = test_case.get("hosts") num_hosts = test_case.get("numHosts", len(hosts or [])) options = test_case.get("options", {}) if "ssl" in options: options["tls"] = options.pop("ssl") parsed_options = test_case.get("parsed_options") # See DRIVERS-1324, unless tls is explicitly set to False we need TLS. needs_tls = not (options and (options.get("ssl") is False or options.get("tls") is False)) if needs_tls and not client_context.tls: self.skipTest("this test requires a TLS cluster") if not needs_tls and client_context.tls: self.skipTest("this test requires a non-TLS cluster") if seeds: seeds = split_hosts(",".join(seeds)) if hosts: hosts = frozenset(split_hosts(",".join(hosts))) if seeds or num_seeds: result = parse_uri(uri, validate=True) if seeds is not None: self.assertEqual(sorted(result["nodelist"]), sorted(seeds)) if num_seeds is not None: self.assertEqual(len(result["nodelist"]), num_seeds) if options: opts = result["options"] if "readpreferencetags" in opts: rpts = validate_read_preference_tags( "readPreferenceTags", opts.pop("readpreferencetags") ) opts["readPreferenceTags"] = rpts self.assertEqual(result["options"], options) if parsed_options: for opt, expected in parsed_options.items(): if opt == "user": self.assertEqual(result["username"], expected) elif opt == "password": self.assertEqual(result["password"], expected) elif opt == "auth_database" or opt == "db": self.assertEqual(result["database"], expected) hostname = next(iter(client_context.client.nodes))[0] # The replica set members must be configured as 'localhost'. if hostname == "localhost": copts = client_context.default_client_options.copy() # Remove tls since SRV parsing should add it automatically. copts.pop("tls", None) if client_context.tls: # Our test certs don't support the SRV hosts used in these # tests. copts["tlsAllowInvalidHostnames"] = True client = MongoClient(uri, **copts) if num_seeds is not None: self.assertEqual(len(client._topology_settings.seeds), num_seeds) if hosts is not None: wait_until(lambda: hosts == client.nodes, "match test hosts to client nodes") if num_hosts is not None: wait_until( lambda: num_hosts == len(client.nodes), "wait to connect to num_hosts" ) if test_case.get("ping", True): client.admin.command("ping") # XXX: we should block until SRV poller runs at least once # and re-run these assertions. else: try: parse_uri(uri) except (ConfigurationError, ValueError): pass else: self.fail("failed to raise an exception") return run_test def create_tests(cls): for filename in glob.glob(os.path.join(cls.TEST_PATH, "*.json")): test_suffix, _ = os.path.splitext(os.path.basename(filename)) with open(filename) as dns_test_file: test_method = create_test(json.load(dns_test_file)) setattr(cls, "test_" + test_suffix, test_method) create_tests(TestDNSRepl) create_tests(TestDNSLoadBalanced) create_tests(TestDNSSharded) class TestParsingErrors(unittest.TestCase): def test_invalid_host(self): self.assertRaisesRegex( ConfigurationError, "Invalid URI host: mongodb is not", MongoClient, "mongodb+srv://mongodb", ) self.assertRaisesRegex( ConfigurationError, "Invalid URI host: mongodb.com is not", MongoClient, "mongodb+srv://mongodb.com", ) self.assertRaisesRegex( ConfigurationError, "Invalid URI host: an IP address is not", MongoClient, "mongodb+srv://127.0.0.1", ) self.assertRaisesRegex( ConfigurationError, "Invalid URI host: an IP address is not", MongoClient, "mongodb+srv://[::1]", ) class TestCaseInsensitive(IntegrationTest): def test_connect_case_insensitive(self): client = MongoClient("mongodb+srv://TEST1.TEST.BUILD.10GEN.cc/") self.addCleanup(client.close) self.assertGreater(len(client.topology_description.server_descriptions()), 1) if __name__ == "__main__": unittest.main() mongodb-mongo-python-driver-509e9b7/test/test_encryption.py000066400000000000000000003702121462766011000242240ustar00rootroot00000000000000# Copyright 2019-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. """Test client side encryption spec.""" from __future__ import annotations import base64 import copy import os import re import socket import socketserver import ssl import sys import textwrap import traceback import uuid import warnings from threading import Thread from typing import Any, Dict, Mapping from pymongo.collection import Collection from pymongo.daemon import _spawn_daemon sys.path[0:0] = [""] from test import ( AWS_CREDS, AZURE_CREDS, CA_PEM, CLIENT_PEM, GCP_CREDS, KMIP_CREDS, LOCAL_MASTER_KEY, IntegrationTest, PyMongoTestCase, client_context, unittest, ) from test.test_bulk import BulkTestBase from test.unified_format import generate_test_classes from test.utils import ( AllowListEventListener, OvertCommandListener, SpecTestCreator, TopologyEventListener, camel_to_snake_args, is_greenthread_patched, rs_or_single_client, wait_until, ) from test.utils_spec_runner import SpecRunner from bson import DatetimeMS, Decimal128, encode, json_util from bson.binary import UUID_SUBTYPE, Binary, UuidRepresentation from bson.codec_options import CodecOptions from bson.errors import BSONError from bson.json_util import JSONOptions from bson.son import SON from pymongo import ReadPreference, encryption from pymongo.cursor import CursorType from pymongo.encryption import Algorithm, ClientEncryption, QueryType from pymongo.encryption_options import _HAVE_PYMONGOCRYPT, AutoEncryptionOpts, RangeOpts from pymongo.errors import ( AutoReconnect, BulkWriteError, ConfigurationError, DuplicateKeyError, EncryptedCollectionError, EncryptionError, InvalidOperation, OperationFailure, ServerSelectionTimeoutError, WriteError, ) from pymongo.mongo_client import MongoClient from pymongo.operations import InsertOne, ReplaceOne, UpdateOne from pymongo.write_concern import WriteConcern KMS_PROVIDERS = {"local": {"key": b"\x00" * 96}} def get_client_opts(client): return client._MongoClient__options class TestAutoEncryptionOpts(PyMongoTestCase): @unittest.skipUnless(_HAVE_PYMONGOCRYPT, "pymongocrypt is not installed") @unittest.skipUnless(os.environ.get("TEST_CRYPT_SHARED"), "crypt_shared lib is not installed") def test_crypt_shared(self): # Test that we can pick up crypt_shared lib automatically client = MongoClient( auto_encryption_opts=AutoEncryptionOpts( KMS_PROVIDERS, "keyvault.datakeys", crypt_shared_lib_required=True ), connect=False, ) self.addCleanup(client.close) @unittest.skipIf(_HAVE_PYMONGOCRYPT, "pymongocrypt is installed") def test_init_requires_pymongocrypt(self): with self.assertRaises(ConfigurationError): AutoEncryptionOpts({}, "keyvault.datakeys") @unittest.skipUnless(_HAVE_PYMONGOCRYPT, "pymongocrypt is not installed") def test_init(self): opts = AutoEncryptionOpts({}, "keyvault.datakeys") self.assertEqual(opts._kms_providers, {}) self.assertEqual(opts._key_vault_namespace, "keyvault.datakeys") self.assertEqual(opts._key_vault_client, None) self.assertEqual(opts._schema_map, None) self.assertEqual(opts._bypass_auto_encryption, False) self.assertEqual(opts._mongocryptd_uri, "mongodb://localhost:27020") self.assertEqual(opts._mongocryptd_bypass_spawn, False) self.assertEqual(opts._mongocryptd_spawn_path, "mongocryptd") self.assertEqual(opts._mongocryptd_spawn_args, ["--idleShutdownTimeoutSecs=60"]) self.assertEqual(opts._kms_ssl_contexts, {}) @unittest.skipUnless(_HAVE_PYMONGOCRYPT, "pymongocrypt is not installed") def test_init_spawn_args(self): # User can override idleShutdownTimeoutSecs opts = AutoEncryptionOpts( {}, "keyvault.datakeys", mongocryptd_spawn_args=["--idleShutdownTimeoutSecs=88"] ) self.assertEqual(opts._mongocryptd_spawn_args, ["--idleShutdownTimeoutSecs=88"]) # idleShutdownTimeoutSecs is added by default opts = AutoEncryptionOpts({}, "keyvault.datakeys", mongocryptd_spawn_args=[]) self.assertEqual(opts._mongocryptd_spawn_args, ["--idleShutdownTimeoutSecs=60"]) # Also added when other options are given opts = AutoEncryptionOpts( {}, "keyvault.datakeys", mongocryptd_spawn_args=["--quiet", "--port=27020"] ) self.assertEqual( opts._mongocryptd_spawn_args, ["--quiet", "--port=27020", "--idleShutdownTimeoutSecs=60"], ) @unittest.skipUnless(_HAVE_PYMONGOCRYPT, "pymongocrypt is not installed") def test_init_kms_tls_options(self): # Error cases: with self.assertRaisesRegex(TypeError, r'kms_tls_options\["kmip"\] must be a dict'): AutoEncryptionOpts({}, "k.d", kms_tls_options={"kmip": 1}) tls_opts: Any for tls_opts in [ {"kmip": {"tls": True, "tlsInsecure": True}}, {"kmip": {"tls": True, "tlsAllowInvalidCertificates": True}}, {"kmip": {"tls": True, "tlsAllowInvalidHostnames": True}}, ]: with self.assertRaisesRegex(ConfigurationError, "Insecure TLS options prohibited"): opts = AutoEncryptionOpts({}, "k.d", kms_tls_options=tls_opts) with self.assertRaises(FileNotFoundError): AutoEncryptionOpts({}, "k.d", kms_tls_options={"kmip": {"tlsCAFile": "does-not-exist"}}) # Success cases: tls_opts: Any for tls_opts in [None, {}]: opts = AutoEncryptionOpts({}, "k.d", kms_tls_options=tls_opts) self.assertEqual(opts._kms_ssl_contexts, {}) opts = AutoEncryptionOpts({}, "k.d", kms_tls_options={"kmip": {"tls": True}, "aws": {}}) ctx = opts._kms_ssl_contexts["kmip"] self.assertEqual(ctx.check_hostname, True) self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED) ctx = opts._kms_ssl_contexts["aws"] self.assertEqual(ctx.check_hostname, True) self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED) opts = AutoEncryptionOpts( {}, "k.d", kms_tls_options={"kmip": {"tlsCAFile": CA_PEM, "tlsCertificateKeyFile": CLIENT_PEM}}, ) ctx = opts._kms_ssl_contexts["kmip"] self.assertEqual(ctx.check_hostname, True) self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED) class TestClientOptions(PyMongoTestCase): def test_default(self): client = MongoClient(connect=False) self.addCleanup(client.close) self.assertEqual(get_client_opts(client).auto_encryption_opts, None) client = MongoClient(auto_encryption_opts=None, connect=False) self.addCleanup(client.close) self.assertEqual(get_client_opts(client).auto_encryption_opts, None) @unittest.skipUnless(_HAVE_PYMONGOCRYPT, "pymongocrypt is not installed") def test_kwargs(self): opts = AutoEncryptionOpts(KMS_PROVIDERS, "keyvault.datakeys") client = MongoClient(auto_encryption_opts=opts, connect=False) self.addCleanup(client.close) self.assertEqual(get_client_opts(client).auto_encryption_opts, opts) class EncryptionIntegrationTest(IntegrationTest): """Base class for encryption integration tests.""" @classmethod @unittest.skipUnless(_HAVE_PYMONGOCRYPT, "pymongocrypt is not installed") @client_context.require_version_min(4, 2, -1) def setUpClass(cls): super().setUpClass() def assertEncrypted(self, val): self.assertIsInstance(val, Binary) self.assertEqual(val.subtype, 6) def assertBinaryUUID(self, val): self.assertIsInstance(val, Binary) self.assertEqual(val.subtype, UUID_SUBTYPE) # Location of JSON test files. BASE = os.path.join(os.path.dirname(os.path.realpath(__file__)), "client-side-encryption") SPEC_PATH = os.path.join(BASE, "spec") OPTS = CodecOptions() # Use SON to preserve the order of fields while parsing json. Use tz_aware # =False to match how CodecOptions decodes dates. JSON_OPTS = JSONOptions(document_class=SON, tz_aware=False) def read(*paths): with open(os.path.join(BASE, *paths)) as fp: return fp.read() def json_data(*paths): return json_util.loads(read(*paths), json_options=JSON_OPTS) def bson_data(*paths): return encode(json_data(*paths), codec_options=OPTS) class TestClientSimple(EncryptionIntegrationTest): def _test_auto_encrypt(self, opts): client = rs_or_single_client(auto_encryption_opts=opts) self.addCleanup(client.close) # Create the encrypted field's data key. key_vault = create_key_vault( self.client.keyvault.datakeys, json_data("custom", "key-document-local.json") ) self.addCleanup(key_vault.drop) # Collection.insert_one/insert_many auto encrypts. docs = [ {"_id": 0, "ssn": "000"}, {"_id": 1, "ssn": "111"}, {"_id": 2, "ssn": "222"}, {"_id": 3, "ssn": "333"}, {"_id": 4, "ssn": "444"}, {"_id": 5, "ssn": "555"}, ] encrypted_coll = client.pymongo_test.test encrypted_coll.insert_one(docs[0]) encrypted_coll.insert_many(docs[1:3]) unack = encrypted_coll.with_options(write_concern=WriteConcern(w=0)) unack.insert_one(docs[3]) unack.insert_many(docs[4:], ordered=False) wait_until( lambda: self.db.test.count_documents({}) == len(docs), "insert documents with w=0" ) # Database.command auto decrypts. res = client.pymongo_test.command("find", "test", filter={"ssn": "000"}) decrypted_docs = res["cursor"]["firstBatch"] self.assertEqual(decrypted_docs, [{"_id": 0, "ssn": "000"}]) # Collection.find auto decrypts. decrypted_docs = list(encrypted_coll.find()) self.assertEqual(decrypted_docs, docs) # Collection.find auto decrypts getMores. decrypted_docs = list(encrypted_coll.find(batch_size=1)) self.assertEqual(decrypted_docs, docs) # Collection.aggregate auto decrypts. decrypted_docs = list(encrypted_coll.aggregate([])) self.assertEqual(decrypted_docs, docs) # Collection.aggregate auto decrypts getMores. decrypted_docs = list(encrypted_coll.aggregate([], batchSize=1)) self.assertEqual(decrypted_docs, docs) # Collection.distinct auto decrypts. decrypted_ssns = encrypted_coll.distinct("ssn") self.assertEqual(set(decrypted_ssns), {d["ssn"] for d in docs}) # Make sure the field is actually encrypted. for encrypted_doc in self.db.test.find(): self.assertIsInstance(encrypted_doc["_id"], int) self.assertEncrypted(encrypted_doc["ssn"]) # Attempt to encrypt an unencodable object. with self.assertRaises(BSONError): encrypted_coll.insert_one({"unencodeable": object()}) def test_auto_encrypt(self): # Configure the encrypted field via jsonSchema. json_schema = json_data("custom", "schema.json") create_with_schema(self.db.test, json_schema) self.addCleanup(self.db.test.drop) opts = AutoEncryptionOpts(KMS_PROVIDERS, "keyvault.datakeys") self._test_auto_encrypt(opts) def test_auto_encrypt_local_schema_map(self): # Configure the encrypted field via the local schema_map option. schemas = {"pymongo_test.test": json_data("custom", "schema.json")} opts = AutoEncryptionOpts(KMS_PROVIDERS, "keyvault.datakeys", schema_map=schemas) self._test_auto_encrypt(opts) def test_use_after_close(self): opts = AutoEncryptionOpts(KMS_PROVIDERS, "keyvault.datakeys") client = rs_or_single_client(auto_encryption_opts=opts) self.addCleanup(client.close) client.admin.command("ping") client.close() with self.assertRaisesRegex(InvalidOperation, "Cannot use MongoClient after close"): client.admin.command("ping") @unittest.skipIf( not hasattr(os, "register_at_fork"), "register_at_fork not available in this version of Python", ) @unittest.skipIf( is_greenthread_patched(), "gevent and eventlet do not support POSIX-style forking.", ) def test_fork(self): opts = AutoEncryptionOpts(KMS_PROVIDERS, "keyvault.datakeys") client = rs_or_single_client(auto_encryption_opts=opts) self.addCleanup(client.close) def target(): with warnings.catch_warnings(): warnings.simplefilter("ignore") client.admin.command("ping") with self.fork(target): target() class TestEncryptedBulkWrite(BulkTestBase, EncryptionIntegrationTest): def test_upsert_uuid_standard_encrypt(self): opts = AutoEncryptionOpts(KMS_PROVIDERS, "keyvault.datakeys") client = rs_or_single_client(auto_encryption_opts=opts) self.addCleanup(client.close) options = CodecOptions(uuid_representation=UuidRepresentation.STANDARD) encrypted_coll = client.pymongo_test.test coll = encrypted_coll.with_options(codec_options=options) uuids = [uuid.uuid4() for _ in range(3)] result = coll.bulk_write( [ UpdateOne({"_id": uuids[0]}, {"$set": {"a": 0}}, upsert=True), ReplaceOne({"a": 1}, {"_id": uuids[1]}, upsert=True), # This is just here to make the counts right in all cases. ReplaceOne({"_id": uuids[2]}, {"_id": uuids[2]}, upsert=True), ] ) self.assertEqualResponse( { "nMatched": 0, "nModified": 0, "nUpserted": 3, "nInserted": 0, "nRemoved": 0, "upserted": [ {"index": 0, "_id": uuids[0]}, {"index": 1, "_id": uuids[1]}, {"index": 2, "_id": uuids[2]}, ], }, result.bulk_api_result, ) class TestClientMaxWireVersion(IntegrationTest): @classmethod @unittest.skipUnless(_HAVE_PYMONGOCRYPT, "pymongocrypt is not installed") def setUpClass(cls): super().setUpClass() @client_context.require_version_max(4, 0, 99) def test_raise_max_wire_version_error(self): opts = AutoEncryptionOpts(KMS_PROVIDERS, "keyvault.datakeys") client = rs_or_single_client(auto_encryption_opts=opts) self.addCleanup(client.close) msg = "Auto-encryption requires a minimum MongoDB version of 4.2" with self.assertRaisesRegex(ConfigurationError, msg): client.test.test.insert_one({}) with self.assertRaisesRegex(ConfigurationError, msg): client.admin.command("ping") with self.assertRaisesRegex(ConfigurationError, msg): client.test.test.find_one({}) with self.assertRaisesRegex(ConfigurationError, msg): client.test.test.bulk_write([InsertOne({})]) def test_raise_unsupported_error(self): opts = AutoEncryptionOpts(KMS_PROVIDERS, "keyvault.datakeys") client = rs_or_single_client(auto_encryption_opts=opts) self.addCleanup(client.close) msg = "find_raw_batches does not support auto encryption" with self.assertRaisesRegex(InvalidOperation, msg): client.test.test.find_raw_batches({}) msg = "aggregate_raw_batches does not support auto encryption" with self.assertRaisesRegex(InvalidOperation, msg): client.test.test.aggregate_raw_batches([]) if client_context.is_mongos: msg = "Exhaust cursors are not supported by mongos" else: msg = "exhaust cursors do not support auto encryption" with self.assertRaisesRegex(InvalidOperation, msg): next(client.test.test.find(cursor_type=CursorType.EXHAUST)) class TestExplicitSimple(EncryptionIntegrationTest): def test_encrypt_decrypt(self): client_encryption = ClientEncryption( KMS_PROVIDERS, "keyvault.datakeys", client_context.client, OPTS ) self.addCleanup(client_encryption.close) # Use standard UUID representation. key_vault = client_context.client.keyvault.get_collection("datakeys", codec_options=OPTS) self.addCleanup(key_vault.drop) # Create the encrypted field's data key. key_id = client_encryption.create_data_key("local", key_alt_names=["name"]) self.assertBinaryUUID(key_id) self.assertTrue(key_vault.find_one({"_id": key_id})) # Create an unused data key to make sure filtering works. unused_key_id = client_encryption.create_data_key("local", key_alt_names=["unused"]) self.assertBinaryUUID(unused_key_id) self.assertTrue(key_vault.find_one({"_id": unused_key_id})) doc = {"_id": 0, "ssn": "000"} encrypted_ssn = client_encryption.encrypt( doc["ssn"], Algorithm.AEAD_AES_256_CBC_HMAC_SHA_512_Deterministic, key_id=key_id ) # Ensure encryption via key_alt_name for the same key produces the # same output. encrypted_ssn2 = client_encryption.encrypt( doc["ssn"], Algorithm.AEAD_AES_256_CBC_HMAC_SHA_512_Deterministic, key_alt_name="name" ) self.assertEqual(encrypted_ssn, encrypted_ssn2) # Test encryption via UUID encrypted_ssn3 = client_encryption.encrypt( doc["ssn"], Algorithm.AEAD_AES_256_CBC_HMAC_SHA_512_Deterministic, key_id=key_id.as_uuid(), ) self.assertEqual(encrypted_ssn, encrypted_ssn3) # Test decryption. decrypted_ssn = client_encryption.decrypt(encrypted_ssn) self.assertEqual(decrypted_ssn, doc["ssn"]) def test_validation(self): client_encryption = ClientEncryption( KMS_PROVIDERS, "keyvault.datakeys", client_context.client, OPTS ) self.addCleanup(client_encryption.close) msg = "value to decrypt must be a bson.binary.Binary with subtype 6" with self.assertRaisesRegex(TypeError, msg): client_encryption.decrypt("str") # type: ignore[arg-type] with self.assertRaisesRegex(TypeError, msg): client_encryption.decrypt(Binary(b"123")) msg = "key_id must be a bson.binary.Binary with subtype 4" algo = Algorithm.AEAD_AES_256_CBC_HMAC_SHA_512_Deterministic with self.assertRaisesRegex(TypeError, msg): client_encryption.encrypt("str", algo, key_id=Binary(b"123")) def test_bson_errors(self): client_encryption = ClientEncryption( KMS_PROVIDERS, "keyvault.datakeys", client_context.client, OPTS ) self.addCleanup(client_encryption.close) # Attempt to encrypt an unencodable object. unencodable_value = object() with self.assertRaises(BSONError): client_encryption.encrypt( unencodable_value, Algorithm.AEAD_AES_256_CBC_HMAC_SHA_512_Deterministic, key_id=Binary.from_uuid(uuid.uuid4()), ) def test_codec_options(self): with self.assertRaisesRegex(TypeError, "codec_options must be"): ClientEncryption( KMS_PROVIDERS, "keyvault.datakeys", client_context.client, None, # type: ignore[arg-type] ) opts = CodecOptions(uuid_representation=UuidRepresentation.JAVA_LEGACY) client_encryption_legacy = ClientEncryption( KMS_PROVIDERS, "keyvault.datakeys", client_context.client, opts ) self.addCleanup(client_encryption_legacy.close) # Create the encrypted field's data key. key_id = client_encryption_legacy.create_data_key("local") # Encrypt a UUID with JAVA_LEGACY codec options. value = uuid.uuid4() encrypted_legacy = client_encryption_legacy.encrypt( value, Algorithm.AEAD_AES_256_CBC_HMAC_SHA_512_Deterministic, key_id=key_id ) decrypted_value_legacy = client_encryption_legacy.decrypt(encrypted_legacy) self.assertEqual(decrypted_value_legacy, value) # Encrypt the same UUID with STANDARD codec options. opts = CodecOptions(uuid_representation=UuidRepresentation.STANDARD) client_encryption = ClientEncryption( KMS_PROVIDERS, "keyvault.datakeys", client_context.client, opts ) self.addCleanup(client_encryption.close) encrypted_standard = client_encryption.encrypt( value, Algorithm.AEAD_AES_256_CBC_HMAC_SHA_512_Deterministic, key_id=key_id ) decrypted_standard = client_encryption.decrypt(encrypted_standard) self.assertEqual(decrypted_standard, value) # Test that codec_options is applied during encryption. self.assertNotEqual(encrypted_standard, encrypted_legacy) # Test that codec_options is applied during decryption. self.assertEqual( client_encryption_legacy.decrypt(encrypted_standard), Binary.from_uuid(value) ) self.assertNotEqual(client_encryption.decrypt(encrypted_legacy), value) def test_close(self): client_encryption = ClientEncryption( KMS_PROVIDERS, "keyvault.datakeys", client_context.client, OPTS ) client_encryption.close() # Close can be called multiple times. client_encryption.close() algo = Algorithm.AEAD_AES_256_CBC_HMAC_SHA_512_Deterministic msg = "Cannot use closed ClientEncryption" with self.assertRaisesRegex(InvalidOperation, msg): client_encryption.create_data_key("local") with self.assertRaisesRegex(InvalidOperation, msg): client_encryption.encrypt("val", algo, key_alt_name="name") with self.assertRaisesRegex(InvalidOperation, msg): client_encryption.decrypt(Binary(b"", 6)) def test_with_statement(self): with ClientEncryption( KMS_PROVIDERS, "keyvault.datakeys", client_context.client, OPTS ) as client_encryption: pass with self.assertRaisesRegex(InvalidOperation, "Cannot use closed ClientEncryption"): client_encryption.create_data_key("local") # Spec tests AWS_TEMP_CREDS = { "accessKeyId": os.environ.get("CSFLE_AWS_TEMP_ACCESS_KEY_ID", ""), "secretAccessKey": os.environ.get("CSFLE_AWS_TEMP_SECRET_ACCESS_KEY", ""), "sessionToken": os.environ.get("CSFLE_AWS_TEMP_SESSION_TOKEN", ""), } AWS_TEMP_NO_SESSION_CREDS = { "accessKeyId": os.environ.get("CSFLE_AWS_TEMP_ACCESS_KEY_ID", ""), "secretAccessKey": os.environ.get("CSFLE_AWS_TEMP_SECRET_ACCESS_KEY", ""), } KMS_TLS_OPTS = {"kmip": {"tlsCAFile": CA_PEM, "tlsCertificateKeyFile": CLIENT_PEM}} class TestSpec(SpecRunner): @classmethod @unittest.skipUnless(_HAVE_PYMONGOCRYPT, "pymongocrypt is not installed") def setUpClass(cls): super().setUpClass() def parse_auto_encrypt_opts(self, opts): """Parse clientOptions.autoEncryptOpts.""" opts = camel_to_snake_args(opts) kms_providers = opts["kms_providers"] if "aws" in kms_providers: kms_providers["aws"] = AWS_CREDS if not any(AWS_CREDS.values()): self.skipTest("AWS environment credentials are not set") if "awsTemporary" in kms_providers: kms_providers["aws"] = AWS_TEMP_CREDS del kms_providers["awsTemporary"] if not any(AWS_TEMP_CREDS.values()): self.skipTest("AWS Temp environment credentials are not set") if "awsTemporaryNoSessionToken" in kms_providers: kms_providers["aws"] = AWS_TEMP_NO_SESSION_CREDS del kms_providers["awsTemporaryNoSessionToken"] if not any(AWS_TEMP_NO_SESSION_CREDS.values()): self.skipTest("AWS Temp environment credentials are not set") if "azure" in kms_providers: kms_providers["azure"] = AZURE_CREDS if not any(AZURE_CREDS.values()): self.skipTest("Azure environment credentials are not set") if "gcp" in kms_providers: kms_providers["gcp"] = GCP_CREDS if not any(AZURE_CREDS.values()): self.skipTest("GCP environment credentials are not set") if "kmip" in kms_providers: kms_providers["kmip"] = KMIP_CREDS opts["kms_tls_options"] = KMS_TLS_OPTS if "key_vault_namespace" not in opts: opts["key_vault_namespace"] = "keyvault.datakeys" if "extra_options" in opts: opts.update(camel_to_snake_args(opts.pop("extra_options"))) opts = dict(opts) return AutoEncryptionOpts(**opts) def parse_client_options(self, opts): """Override clientOptions parsing to support autoEncryptOpts.""" encrypt_opts = opts.pop("autoEncryptOpts", None) if encrypt_opts: opts["auto_encryption_opts"] = self.parse_auto_encrypt_opts(encrypt_opts) return super().parse_client_options(opts) def get_object_name(self, op): """Default object is collection.""" return op.get("object", "collection") def maybe_skip_scenario(self, test): super().maybe_skip_scenario(test) desc = test["description"].lower() if ( "timeoutms applied to listcollections to get collection schema" in desc and sys.platform in ("win32", "darwin") ): self.skipTest("PYTHON-3706 flaky test on Windows/macOS") if "type=symbol" in desc: self.skipTest("PyMongo does not support the symbol type") def setup_scenario(self, scenario_def): """Override a test's setup.""" key_vault_data = scenario_def["key_vault_data"] encrypted_fields = scenario_def["encrypted_fields"] json_schema = scenario_def["json_schema"] data = scenario_def["data"] coll = client_context.client.get_database("keyvault", codec_options=OPTS)["datakeys"] coll.delete_many({}) if key_vault_data: coll.insert_many(key_vault_data) db_name = self.get_scenario_db_name(scenario_def) coll_name = self.get_scenario_coll_name(scenario_def) db = client_context.client.get_database(db_name, codec_options=OPTS) coll = db.drop_collection(coll_name, encrypted_fields=encrypted_fields) wc = WriteConcern(w="majority") kwargs: Dict[str, Any] = {} if json_schema: kwargs["validator"] = {"$jsonSchema": json_schema} kwargs["codec_options"] = OPTS if not data: kwargs["write_concern"] = wc if encrypted_fields: kwargs["encryptedFields"] = encrypted_fields db.create_collection(coll_name, **kwargs) coll = db[coll_name] if data: # Load data. coll.with_options(write_concern=wc).insert_many(scenario_def["data"]) def allowable_errors(self, op): """Override expected error classes.""" errors = super().allowable_errors(op) # An updateOne test expects encryption to error when no $ operator # appears but pymongo raises a client side ValueError in this case. if op["name"] == "updateOne": errors += (ValueError,) return errors def create_test(scenario_def, test, name): @client_context.require_test_commands def run_scenario(self): self.run_scenario(scenario_def, test) return run_scenario test_creator = SpecTestCreator(create_test, TestSpec, os.path.join(SPEC_PATH, "legacy")) test_creator.create_tests() if _HAVE_PYMONGOCRYPT: globals().update( generate_test_classes( os.path.join(SPEC_PATH, "unified"), module=__name__, ) ) # Prose Tests ALL_KMS_PROVIDERS = { "aws": AWS_CREDS, "azure": AZURE_CREDS, "gcp": GCP_CREDS, "kmip": KMIP_CREDS, "local": {"key": LOCAL_MASTER_KEY}, } LOCAL_KEY_ID = Binary(base64.b64decode(b"LOCALAAAAAAAAAAAAAAAAA=="), UUID_SUBTYPE) AWS_KEY_ID = Binary(base64.b64decode(b"AWSAAAAAAAAAAAAAAAAAAA=="), UUID_SUBTYPE) AZURE_KEY_ID = Binary(base64.b64decode(b"AZUREAAAAAAAAAAAAAAAAA=="), UUID_SUBTYPE) GCP_KEY_ID = Binary(base64.b64decode(b"GCPAAAAAAAAAAAAAAAAAAA=="), UUID_SUBTYPE) KMIP_KEY_ID = Binary(base64.b64decode(b"KMIPAAAAAAAAAAAAAAAAAA=="), UUID_SUBTYPE) def create_with_schema(coll, json_schema): """Create and return a Collection with a jsonSchema.""" coll.with_options(write_concern=WriteConcern(w="majority")).drop() return coll.database.create_collection( coll.name, validator={"$jsonSchema": json_schema}, codec_options=OPTS ) def create_key_vault(vault, *data_keys): """Create the key vault collection with optional data keys.""" vault = vault.with_options(write_concern=WriteConcern(w="majority"), codec_options=OPTS) vault.drop() if data_keys: vault.insert_many(data_keys) vault.create_index( "keyAltNames", unique=True, partialFilterExpression={"keyAltNames": {"$exists": True}}, ) return vault class TestDataKeyDoubleEncryption(EncryptionIntegrationTest): client_encrypted: MongoClient client_encryption: ClientEncryption listener: OvertCommandListener vault: Any KMS_PROVIDERS = ALL_KMS_PROVIDERS MASTER_KEYS = { "aws": { "region": "us-east-1", "key": "arn:aws:kms:us-east-1:579766882180:key/89fcc2c4-08b0-4bd9-9f25-e30687b580d0", }, "azure": { "keyVaultEndpoint": "key-vault-csfle.vault.azure.net", "keyName": "key-name-csfle", }, "gcp": { "projectId": "devprod-drivers", "location": "global", "keyRing": "key-ring-csfle", "keyName": "key-name-csfle", }, "kmip": {}, "local": None, } @classmethod @unittest.skipUnless( any([all(AWS_CREDS.values()), all(AZURE_CREDS.values()), all(GCP_CREDS.values())]), "No environment credentials are set", ) def setUpClass(cls): super().setUpClass() cls.listener = OvertCommandListener() cls.client = rs_or_single_client(event_listeners=[cls.listener]) cls.client.db.coll.drop() cls.vault = create_key_vault(cls.client.keyvault.datakeys) # Configure the encrypted field via the local schema_map option. schemas = { "db.coll": { "bsonType": "object", "properties": { "encrypted_placeholder": { "encrypt": { "keyId": "/placeholder", "bsonType": "string", "algorithm": "AEAD_AES_256_CBC_HMAC_SHA_512-Random", } } }, } } opts = AutoEncryptionOpts( cls.KMS_PROVIDERS, "keyvault.datakeys", schema_map=schemas, kms_tls_options=KMS_TLS_OPTS ) cls.client_encrypted = rs_or_single_client( auto_encryption_opts=opts, uuidRepresentation="standard" ) cls.client_encryption = ClientEncryption( cls.KMS_PROVIDERS, "keyvault.datakeys", cls.client, OPTS, kms_tls_options=KMS_TLS_OPTS ) @classmethod def tearDownClass(cls): cls.vault.drop() cls.client.close() cls.client_encrypted.close() cls.client_encryption.close() def setUp(self): self.listener.reset() def run_test(self, provider_name): # Create data key. master_key: Any = self.MASTER_KEYS[provider_name] datakey_id = self.client_encryption.create_data_key( provider_name, master_key=master_key, key_alt_names=[f"{provider_name}_altname"] ) self.assertBinaryUUID(datakey_id) cmd = self.listener.started_events[-1] self.assertEqual("insert", cmd.command_name) self.assertEqual({"w": "majority"}, cmd.command.get("writeConcern")) docs = list(self.vault.find({"_id": datakey_id})) self.assertEqual(len(docs), 1) self.assertEqual(docs[0]["masterKey"]["provider"], provider_name) # Encrypt by key_id. encrypted = self.client_encryption.encrypt( f"hello {provider_name}", Algorithm.AEAD_AES_256_CBC_HMAC_SHA_512_Deterministic, key_id=datakey_id, ) self.assertEncrypted(encrypted) self.client_encrypted.db.coll.insert_one({"_id": provider_name, "value": encrypted}) doc_decrypted = self.client_encrypted.db.coll.find_one({"_id": provider_name}) self.assertEqual(doc_decrypted["value"], f"hello {provider_name}") # type: ignore # Encrypt by key_alt_name. encrypted_altname = self.client_encryption.encrypt( f"hello {provider_name}", Algorithm.AEAD_AES_256_CBC_HMAC_SHA_512_Deterministic, key_alt_name=f"{provider_name}_altname", ) self.assertEqual(encrypted_altname, encrypted) # Explicitly encrypting an auto encrypted field. with self.assertRaisesRegex(EncryptionError, r"encrypt element of type"): self.client_encrypted.db.coll.insert_one({"encrypted_placeholder": encrypted}) def test_data_key_local(self): self.run_test("local") @unittest.skipUnless(any(AWS_CREDS.values()), "AWS environment credentials are not set") def test_data_key_aws(self): self.run_test("aws") @unittest.skipUnless(any(AZURE_CREDS.values()), "Azure environment credentials are not set") def test_data_key_azure(self): self.run_test("azure") @unittest.skipUnless(any(GCP_CREDS.values()), "GCP environment credentials are not set") def test_data_key_gcp(self): self.run_test("gcp") def test_data_key_kmip(self): self.run_test("kmip") class TestExternalKeyVault(EncryptionIntegrationTest): @staticmethod def kms_providers(): return {"local": {"key": LOCAL_MASTER_KEY}} def _test_external_key_vault(self, with_external_key_vault): self.client.db.coll.drop() vault = create_key_vault( self.client.keyvault.datakeys, json_data("corpus", "corpus-key-local.json"), json_data("corpus", "corpus-key-aws.json"), ) self.addCleanup(vault.drop) # Configure the encrypted field via the local schema_map option. schemas = {"db.coll": json_data("external", "external-schema.json")} if with_external_key_vault: key_vault_client = rs_or_single_client(username="fake-user", password="fake-pwd") self.addCleanup(key_vault_client.close) else: key_vault_client = client_context.client opts = AutoEncryptionOpts( self.kms_providers(), "keyvault.datakeys", schema_map=schemas, key_vault_client=key_vault_client, ) client_encrypted = rs_or_single_client( auto_encryption_opts=opts, uuidRepresentation="standard" ) self.addCleanup(client_encrypted.close) client_encryption = ClientEncryption( self.kms_providers(), "keyvault.datakeys", key_vault_client, OPTS ) self.addCleanup(client_encryption.close) if with_external_key_vault: # Authentication error. with self.assertRaises(EncryptionError) as ctx: client_encrypted.db.coll.insert_one({"encrypted": "test"}) # AuthenticationFailed error. self.assertIsInstance(ctx.exception.cause, OperationFailure) self.assertEqual(ctx.exception.cause.code, 18) else: client_encrypted.db.coll.insert_one({"encrypted": "test"}) if with_external_key_vault: # Authentication error. with self.assertRaises(EncryptionError) as ctx: client_encryption.encrypt( "test", Algorithm.AEAD_AES_256_CBC_HMAC_SHA_512_Deterministic, key_id=LOCAL_KEY_ID, ) # AuthenticationFailed error. self.assertIsInstance(ctx.exception.cause, OperationFailure) self.assertEqual(ctx.exception.cause.code, 18) else: client_encryption.encrypt( "test", Algorithm.AEAD_AES_256_CBC_HMAC_SHA_512_Deterministic, key_id=LOCAL_KEY_ID ) def test_external_key_vault_1(self): self._test_external_key_vault(True) def test_external_key_vault_2(self): self._test_external_key_vault(False) class TestViews(EncryptionIntegrationTest): @staticmethod def kms_providers(): return {"local": {"key": LOCAL_MASTER_KEY}} def test_views_are_prohibited(self): self.client.db.view.drop() self.client.db.create_collection("view", viewOn="coll") self.addCleanup(self.client.db.view.drop) opts = AutoEncryptionOpts(self.kms_providers(), "keyvault.datakeys") client_encrypted = rs_or_single_client( auto_encryption_opts=opts, uuidRepresentation="standard" ) self.addCleanup(client_encrypted.close) with self.assertRaisesRegex(EncryptionError, "cannot auto encrypt a view"): client_encrypted.db.view.insert_one({}) class TestCorpus(EncryptionIntegrationTest): @classmethod @unittest.skipUnless(any(AWS_CREDS.values()), "AWS environment credentials are not set") def setUpClass(cls): super().setUpClass() @staticmethod def kms_providers(): return ALL_KMS_PROVIDERS @staticmethod def fix_up_schema(json_schema): """Remove deprecated symbol/dbPointer types from json schema.""" for key in list(json_schema["properties"]): if "_symbol_" in key or "_dbPointer_" in key: del json_schema["properties"][key] return json_schema @staticmethod def fix_up_curpus(corpus): """Disallow deprecated symbol/dbPointer types from corpus test.""" for key in corpus: if "_symbol_" in key or "_dbPointer_" in key: corpus[key]["allowed"] = False return corpus @staticmethod def fix_up_curpus_encrypted(corpus_encrypted, corpus): """Fix the expected values for deprecated symbol/dbPointer types.""" for key in corpus_encrypted: if "_symbol_" in key or "_dbPointer_" in key: corpus_encrypted[key] = copy.deepcopy(corpus[key]) return corpus_encrypted def _test_corpus(self, opts): # Drop and create the collection 'db.coll' with jsonSchema. coll = create_with_schema( self.client.db.coll, self.fix_up_schema(json_data("corpus", "corpus-schema.json")) ) self.addCleanup(coll.drop) vault = create_key_vault( self.client.keyvault.datakeys, json_data("corpus", "corpus-key-local.json"), json_data("corpus", "corpus-key-aws.json"), json_data("corpus", "corpus-key-azure.json"), json_data("corpus", "corpus-key-gcp.json"), json_data("corpus", "corpus-key-kmip.json"), ) self.addCleanup(vault.drop) client_encrypted = rs_or_single_client(auto_encryption_opts=opts) self.addCleanup(client_encrypted.close) client_encryption = ClientEncryption( self.kms_providers(), "keyvault.datakeys", client_context.client, OPTS, kms_tls_options=KMS_TLS_OPTS, ) self.addCleanup(client_encryption.close) corpus = self.fix_up_curpus(json_data("corpus", "corpus.json")) corpus_copied: SON = SON() for key, value in corpus.items(): corpus_copied[key] = copy.deepcopy(value) if key in ( "_id", "altname_aws", "altname_azure", "altname_gcp", "altname_local", "altname_kmip", ): continue if value["method"] == "auto": continue if value["method"] == "explicit": identifier = value["identifier"] self.assertIn(identifier, ("id", "altname")) kms = value["kms"] self.assertIn(kms, ("local", "aws", "azure", "gcp", "kmip")) if identifier == "id": if kms == "local": kwargs = {"key_id": LOCAL_KEY_ID} elif kms == "aws": kwargs = {"key_id": AWS_KEY_ID} elif kms == "azure": kwargs = {"key_id": AZURE_KEY_ID} elif kms == "gcp": kwargs = {"key_id": GCP_KEY_ID} else: kwargs = {"key_id": KMIP_KEY_ID} else: kwargs = {"key_alt_name": kms} self.assertIn(value["algo"], ("det", "rand")) if value["algo"] == "det": algo = Algorithm.AEAD_AES_256_CBC_HMAC_SHA_512_Deterministic else: algo = Algorithm.AEAD_AES_256_CBC_HMAC_SHA_512_Random try: encrypted_val = client_encryption.encrypt( value["value"], algo, **kwargs, # type: ignore[arg-type] ) if not value["allowed"]: self.fail(f"encrypt should have failed: {key!r}: {value!r}") corpus_copied[key]["value"] = encrypted_val except Exception: if value["allowed"]: tb = traceback.format_exc() self.fail(f"encrypt failed: {key!r}: {value!r}, traceback: {tb}") client_encrypted.db.coll.insert_one(corpus_copied) corpus_decrypted = client_encrypted.db.coll.find_one() self.assertEqual(corpus_decrypted, corpus) corpus_encrypted_expected = self.fix_up_curpus_encrypted( json_data("corpus", "corpus-encrypted.json"), corpus ) corpus_encrypted_actual = coll.find_one() for key, value in corpus_encrypted_actual.items(): if key in ( "_id", "altname_aws", "altname_azure", "altname_gcp", "altname_local", "altname_kmip", ): continue if value["algo"] == "det": self.assertEqual(value["value"], corpus_encrypted_expected[key]["value"], key) elif value["algo"] == "rand" and value["allowed"]: self.assertNotEqual(value["value"], corpus_encrypted_expected[key]["value"], key) if value["allowed"]: decrypt_actual = client_encryption.decrypt(value["value"]) decrypt_expected = client_encryption.decrypt( corpus_encrypted_expected[key]["value"] ) self.assertEqual(decrypt_actual, decrypt_expected, key) else: self.assertEqual(value["value"], corpus[key]["value"], key) def test_corpus(self): opts = AutoEncryptionOpts( self.kms_providers(), "keyvault.datakeys", kms_tls_options=KMS_TLS_OPTS ) self._test_corpus(opts) def test_corpus_local_schema(self): # Configure the encrypted field via the local schema_map option. schemas = {"db.coll": self.fix_up_schema(json_data("corpus", "corpus-schema.json"))} opts = AutoEncryptionOpts( self.kms_providers(), "keyvault.datakeys", schema_map=schemas, kms_tls_options=KMS_TLS_OPTS, ) self._test_corpus(opts) _2_MiB = 2097152 _16_MiB = 16777216 class TestBsonSizeBatches(EncryptionIntegrationTest): """Prose tests for BSON size limits and batch splitting.""" coll: Collection coll_encrypted: Collection client_encrypted: MongoClient listener: OvertCommandListener @classmethod def setUpClass(cls): super().setUpClass() db = client_context.client.db cls.coll = db.coll cls.coll.drop() # Configure the encrypted 'db.coll' collection via jsonSchema. json_schema = json_data("limits", "limits-schema.json") db.create_collection( "coll", validator={"$jsonSchema": json_schema}, codec_options=OPTS, write_concern=WriteConcern(w="majority"), ) # Create the key vault. coll = client_context.client.get_database( "keyvault", write_concern=WriteConcern(w="majority"), codec_options=OPTS )["datakeys"] coll.drop() coll.insert_one(json_data("limits", "limits-key.json")) opts = AutoEncryptionOpts({"local": {"key": LOCAL_MASTER_KEY}}, "keyvault.datakeys") cls.listener = OvertCommandListener() cls.client_encrypted = rs_or_single_client( auto_encryption_opts=opts, event_listeners=[cls.listener] ) cls.coll_encrypted = cls.client_encrypted.db.coll @classmethod def tearDownClass(cls): cls.coll_encrypted.drop() cls.client_encrypted.close() super().tearDownClass() def test_01_insert_succeeds_under_2MiB(self): doc = {"_id": "over_2mib_under_16mib", "unencrypted": "a" * _2_MiB} self.coll_encrypted.insert_one(doc) # Same with bulk_write. doc["_id"] = "over_2mib_under_16mib_bulk" self.coll_encrypted.bulk_write([InsertOne(doc)]) def test_02_insert_succeeds_over_2MiB_post_encryption(self): doc = {"_id": "encryption_exceeds_2mib", "unencrypted": "a" * ((2**21) - 2000)} doc.update(json_data("limits", "limits-doc.json")) self.coll_encrypted.insert_one(doc) # Same with bulk_write. doc["_id"] = "encryption_exceeds_2mib_bulk" self.coll_encrypted.bulk_write([InsertOne(doc)]) def test_03_bulk_batch_split(self): doc1 = {"_id": "over_2mib_1", "unencrypted": "a" * _2_MiB} doc2 = {"_id": "over_2mib_2", "unencrypted": "a" * _2_MiB} self.listener.reset() self.coll_encrypted.bulk_write([InsertOne(doc1), InsertOne(doc2)]) self.assertEqual(self.listener.started_command_names(), ["insert", "insert"]) def test_04_bulk_batch_split(self): limits_doc = json_data("limits", "limits-doc.json") doc1 = {"_id": "encryption_exceeds_2mib_1", "unencrypted": "a" * (_2_MiB - 2000)} doc1.update(limits_doc) doc2 = {"_id": "encryption_exceeds_2mib_2", "unencrypted": "a" * (_2_MiB - 2000)} doc2.update(limits_doc) self.listener.reset() self.coll_encrypted.bulk_write([InsertOne(doc1), InsertOne(doc2)]) self.assertEqual(self.listener.started_command_names(), ["insert", "insert"]) def test_05_insert_succeeds_just_under_16MiB(self): doc = {"_id": "under_16mib", "unencrypted": "a" * (_16_MiB - 2000)} self.coll_encrypted.insert_one(doc) # Same with bulk_write. doc["_id"] = "under_16mib_bulk" self.coll_encrypted.bulk_write([InsertOne(doc)]) def test_06_insert_fails_over_16MiB(self): limits_doc = json_data("limits", "limits-doc.json") doc = {"_id": "encryption_exceeds_16mib", "unencrypted": "a" * (_16_MiB - 2000)} doc.update(limits_doc) with self.assertRaisesRegex(WriteError, "object to insert too large"): self.coll_encrypted.insert_one(doc) # Same with bulk_write. doc["_id"] = "encryption_exceeds_16mib_bulk" with self.assertRaises(BulkWriteError) as ctx: self.coll_encrypted.bulk_write([InsertOne(doc)]) err = ctx.exception.details["writeErrors"][0] self.assertEqual(2, err["code"]) self.assertIn("object to insert too large", err["errmsg"]) class TestCustomEndpoint(EncryptionIntegrationTest): """Prose tests for creating data keys with a custom endpoint.""" @classmethod @unittest.skipUnless( any([all(AWS_CREDS.values()), all(AZURE_CREDS.values()), all(GCP_CREDS.values())]), "No environment credentials are set", ) def setUpClass(cls): super().setUpClass() def setUp(self): kms_providers = { "aws": AWS_CREDS, "azure": AZURE_CREDS, "gcp": GCP_CREDS, "kmip": KMIP_CREDS, } self.client_encryption = ClientEncryption( kms_providers=kms_providers, key_vault_namespace="keyvault.datakeys", key_vault_client=client_context.client, codec_options=OPTS, kms_tls_options=KMS_TLS_OPTS, ) kms_providers_invalid = copy.deepcopy(kms_providers) kms_providers_invalid["azure"]["identityPlatformEndpoint"] = "doesnotexist.invalid:443" kms_providers_invalid["gcp"]["endpoint"] = "doesnotexist.invalid:443" kms_providers_invalid["kmip"]["endpoint"] = "doesnotexist.local:5698" self.client_encryption_invalid = ClientEncryption( kms_providers=kms_providers_invalid, key_vault_namespace="keyvault.datakeys", key_vault_client=client_context.client, codec_options=OPTS, kms_tls_options=KMS_TLS_OPTS, ) self._kmip_host_error = None self._invalid_host_error = None def tearDown(self): self.client_encryption.close() self.client_encryption_invalid.close() def run_test_expected_success(self, provider_name, master_key): data_key_id = self.client_encryption.create_data_key(provider_name, master_key=master_key) encrypted = self.client_encryption.encrypt( "test", Algorithm.AEAD_AES_256_CBC_HMAC_SHA_512_Deterministic, key_id=data_key_id ) self.assertEqual("test", self.client_encryption.decrypt(encrypted)) @unittest.skipUnless(any(AWS_CREDS.values()), "AWS environment credentials are not set") def test_01_aws_region_key(self): self.run_test_expected_success( "aws", { "region": "us-east-1", "key": ( "arn:aws:kms:us-east-1:579766882180:key/89fcc2c4-08b0-4bd9-9f25-e30687b580d0" ), }, ) @unittest.skipUnless(any(AWS_CREDS.values()), "AWS environment credentials are not set") def test_02_aws_region_key_endpoint(self): self.run_test_expected_success( "aws", { "region": "us-east-1", "key": ( "arn:aws:kms:us-east-1:579766882180:key/89fcc2c4-08b0-4bd9-9f25-e30687b580d0" ), "endpoint": "kms.us-east-1.amazonaws.com", }, ) @unittest.skipUnless(any(AWS_CREDS.values()), "AWS environment credentials are not set") def test_03_aws_region_key_endpoint_port(self): self.run_test_expected_success( "aws", { "region": "us-east-1", "key": ( "arn:aws:kms:us-east-1:579766882180:key/89fcc2c4-08b0-4bd9-9f25-e30687b580d0" ), "endpoint": "kms.us-east-1.amazonaws.com:443", }, ) @unittest.skipUnless(any(AWS_CREDS.values()), "AWS environment credentials are not set") def test_04_aws_endpoint_invalid_port(self): master_key = { "region": "us-east-1", "key": ("arn:aws:kms:us-east-1:579766882180:key/89fcc2c4-08b0-4bd9-9f25-e30687b580d0"), "endpoint": "kms.us-east-1.amazonaws.com:12345", } with self.assertRaisesRegex(EncryptionError, "kms.us-east-1.amazonaws.com:12345") as ctx: self.client_encryption.create_data_key("aws", master_key=master_key) self.assertIsInstance(ctx.exception.cause, AutoReconnect) @unittest.skipUnless(any(AWS_CREDS.values()), "AWS environment credentials are not set") def test_05_aws_endpoint_wrong_region(self): master_key = { "region": "us-east-1", "key": ("arn:aws:kms:us-east-1:579766882180:key/89fcc2c4-08b0-4bd9-9f25-e30687b580d0"), "endpoint": "kms.us-east-2.amazonaws.com", } # The full error should be something like: # "Credential should be scoped to a valid region, not 'us-east-1'" # but we only check for EncryptionError to avoid breaking on slight # changes to AWS' error message. with self.assertRaises(EncryptionError): self.client_encryption.create_data_key("aws", master_key=master_key) @unittest.skipUnless(any(AWS_CREDS.values()), "AWS environment credentials are not set") def test_06_aws_endpoint_invalid_host(self): master_key = { "region": "us-east-1", "key": ("arn:aws:kms:us-east-1:579766882180:key/89fcc2c4-08b0-4bd9-9f25-e30687b580d0"), "endpoint": "doesnotexist.invalid", } with self.assertRaisesRegex(EncryptionError, self.invalid_host_error): self.client_encryption.create_data_key("aws", master_key=master_key) @unittest.skipUnless(any(AZURE_CREDS.values()), "Azure environment credentials are not set") def test_07_azure(self): master_key = { "keyVaultEndpoint": "key-vault-csfle.vault.azure.net", "keyName": "key-name-csfle", } self.run_test_expected_success("azure", master_key) # The full error should be something like: # "[Errno 8] nodename nor servname provided, or not known" with self.assertRaisesRegex(EncryptionError, self.invalid_host_error): self.client_encryption_invalid.create_data_key("azure", master_key=master_key) @unittest.skipUnless(any(GCP_CREDS.values()), "GCP environment credentials are not set") def test_08_gcp_valid_endpoint(self): master_key = { "projectId": "devprod-drivers", "location": "global", "keyRing": "key-ring-csfle", "keyName": "key-name-csfle", "endpoint": "cloudkms.googleapis.com:443", } self.run_test_expected_success("gcp", master_key) # The full error should be something like: # "[Errno 8] nodename nor servname provided, or not known" with self.assertRaisesRegex(EncryptionError, self.invalid_host_error): self.client_encryption_invalid.create_data_key("gcp", master_key=master_key) @unittest.skipUnless(any(GCP_CREDS.values()), "GCP environment credentials are not set") def test_09_gcp_invalid_endpoint(self): master_key = { "projectId": "devprod-drivers", "location": "global", "keyRing": "key-ring-csfle", "keyName": "key-name-csfle", "endpoint": "doesnotexist.invalid:443", } # The full error should be something like: # "Invalid KMS response, no access_token returned. HTTP status=200" with self.assertRaisesRegex(EncryptionError, "Invalid KMS response"): self.client_encryption.create_data_key("gcp", master_key=master_key) def dns_error(self, host, port): # The full error should be something like: # "[Errno 8] nodename nor servname provided, or not known" with self.assertRaises(Exception) as ctx: socket.getaddrinfo(host, port, socket.AF_INET, socket.SOCK_STREAM) return re.escape(str(ctx.exception)) @property def invalid_host_error(self): if self._invalid_host_error is None: self._invalid_host_error = self.dns_error("doesnotexist.invalid", 443) return self._invalid_host_error @property def kmip_host_error(self): if self._kmip_host_error is None: self._kmip_host_error = self.dns_error("doesnotexist.local", 5698) return self._kmip_host_error def test_10_kmip_invalid_endpoint(self): key = {"keyId": "1"} self.run_test_expected_success("kmip", key) with self.assertRaisesRegex(EncryptionError, self.kmip_host_error): self.client_encryption_invalid.create_data_key("kmip", key) def test_11_kmip_master_key_endpoint(self): key = {"keyId": "1", "endpoint": KMIP_CREDS["endpoint"]} self.run_test_expected_success("kmip", key) # Override invalid endpoint: data_key_id = self.client_encryption_invalid.create_data_key("kmip", master_key=key) encrypted = self.client_encryption_invalid.encrypt( "test", Algorithm.AEAD_AES_256_CBC_HMAC_SHA_512_Deterministic, key_id=data_key_id ) self.assertEqual("test", self.client_encryption_invalid.decrypt(encrypted)) def test_12_kmip_master_key_invalid_endpoint(self): key = {"keyId": "1", "endpoint": "doesnotexist.local:5698"} with self.assertRaisesRegex(EncryptionError, self.kmip_host_error): self.client_encryption.create_data_key("kmip", key) class AzureGCPEncryptionTestMixin: DEK = None KMS_PROVIDER_MAP = None KEYVAULT_DB = "keyvault" KEYVAULT_COLL = "datakeys" client: MongoClient def setUp(self): keyvault = self.client.get_database(self.KEYVAULT_DB).get_collection(self.KEYVAULT_COLL) create_key_vault(keyvault, self.DEK) def _test_explicit(self, expectation): client_encryption = ClientEncryption( self.KMS_PROVIDER_MAP, # type: ignore[arg-type] ".".join([self.KEYVAULT_DB, self.KEYVAULT_COLL]), client_context.client, OPTS, ) self.addCleanup(client_encryption.close) ciphertext = client_encryption.encrypt( "string0", algorithm=Algorithm.AEAD_AES_256_CBC_HMAC_SHA_512_Deterministic, key_id=self.DEK["_id"], ) self.assertEqual(bytes(ciphertext), base64.b64decode(expectation)) self.assertEqual(client_encryption.decrypt(ciphertext), "string0") def _test_automatic(self, expectation_extjson, payload): encrypted_db = "db" encrypted_coll = "coll" keyvault_namespace = ".".join([self.KEYVAULT_DB, self.KEYVAULT_COLL]) encryption_opts = AutoEncryptionOpts( self.KMS_PROVIDER_MAP, # type: ignore[arg-type] keyvault_namespace, schema_map=self.SCHEMA_MAP, ) insert_listener = AllowListEventListener("insert") client = rs_or_single_client( auto_encryption_opts=encryption_opts, event_listeners=[insert_listener] ) self.addCleanup(client.close) coll = client.get_database(encrypted_db).get_collection( encrypted_coll, codec_options=OPTS, write_concern=WriteConcern("majority") ) coll.drop() expected_document = json_util.loads(expectation_extjson, json_options=JSON_OPTS) coll.insert_one(payload) event = insert_listener.started_events[0] inserted_doc = event.command["documents"][0] for key, value in expected_document.items(): self.assertEqual(value, inserted_doc[key]) output_doc = coll.find_one({}) for key, value in payload.items(): self.assertEqual(output_doc[key], value) class TestAzureEncryption(AzureGCPEncryptionTestMixin, EncryptionIntegrationTest): @classmethod @unittest.skipUnless(any(AZURE_CREDS.values()), "Azure environment credentials are not set") def setUpClass(cls): cls.KMS_PROVIDER_MAP = {"azure": AZURE_CREDS} cls.DEK = json_data(BASE, "custom", "azure-dek.json") cls.SCHEMA_MAP = json_data(BASE, "custom", "azure-gcp-schema.json") super().setUpClass() def test_explicit(self): return self._test_explicit( "AQGVERPgAAAAAAAAAAAAAAAC5DbBSwPwfSlBrDtRuglvNvCXD1KzDuCKY2P+4bRFtHDjpTOE2XuytPAUaAbXf1orsPq59PVZmsbTZbt2CB8qaQ==" ) def test_automatic(self): expected_document_extjson = textwrap.dedent( """ {"secret_azure": { "$binary": { "base64": "AQGVERPgAAAAAAAAAAAAAAAC5DbBSwPwfSlBrDtRuglvNvCXD1KzDuCKY2P+4bRFtHDjpTOE2XuytPAUaAbXf1orsPq59PVZmsbTZbt2CB8qaQ==", "subType": "06"} }}""" ) return self._test_automatic(expected_document_extjson, {"secret_azure": "string0"}) class TestGCPEncryption(AzureGCPEncryptionTestMixin, EncryptionIntegrationTest): @classmethod @unittest.skipUnless(any(GCP_CREDS.values()), "GCP environment credentials are not set") def setUpClass(cls): cls.KMS_PROVIDER_MAP = {"gcp": GCP_CREDS} cls.DEK = json_data(BASE, "custom", "gcp-dek.json") cls.SCHEMA_MAP = json_data(BASE, "custom", "azure-gcp-schema.json") super().setUpClass() def test_explicit(self): return self._test_explicit( "ARgj/gAAAAAAAAAAAAAAAAACwFd+Y5Ojw45GUXNvbcIpN9YkRdoHDHkR4kssdn0tIMKlDQOLFkWFY9X07IRlXsxPD8DcTiKnl6XINK28vhcGlg==" ) def test_automatic(self): expected_document_extjson = textwrap.dedent( """ {"secret_gcp": { "$binary": { "base64": "ARgj/gAAAAAAAAAAAAAAAAACwFd+Y5Ojw45GUXNvbcIpN9YkRdoHDHkR4kssdn0tIMKlDQOLFkWFY9X07IRlXsxPD8DcTiKnl6XINK28vhcGlg==", "subType": "06"} }}""" ) return self._test_automatic(expected_document_extjson, {"secret_gcp": "string0"}) # https://github.com/mongodb/specifications/blob/master/source/client-side-encryption/tests/README.rst#deadlock-tests class TestDeadlockProse(EncryptionIntegrationTest): def setUp(self): self.client_test = rs_or_single_client( maxPoolSize=1, readConcernLevel="majority", w="majority", uuidRepresentation="standard" ) self.addCleanup(self.client_test.close) self.client_keyvault_listener = OvertCommandListener() self.client_keyvault = rs_or_single_client( maxPoolSize=1, readConcernLevel="majority", w="majority", event_listeners=[self.client_keyvault_listener], ) self.addCleanup(self.client_keyvault.close) self.client_test.keyvault.datakeys.drop() self.client_test.db.coll.drop() self.client_test.keyvault.datakeys.insert_one(json_data("external", "external-key.json")) _ = self.client_test.db.create_collection( "coll", validator={"$jsonSchema": json_data("external", "external-schema.json")}, codec_options=OPTS, ) client_encryption = ClientEncryption( kms_providers={"local": {"key": LOCAL_MASTER_KEY}}, key_vault_namespace="keyvault.datakeys", key_vault_client=self.client_test, codec_options=OPTS, ) self.ciphertext = client_encryption.encrypt( "string0", Algorithm.AEAD_AES_256_CBC_HMAC_SHA_512_Deterministic, key_alt_name="local" ) client_encryption.close() self.client_listener = OvertCommandListener() self.topology_listener = TopologyEventListener() self.optargs = ({"local": {"key": LOCAL_MASTER_KEY}}, "keyvault.datakeys") def _run_test(self, max_pool_size, auto_encryption_opts): client_encrypted = rs_or_single_client( readConcernLevel="majority", w="majority", maxPoolSize=max_pool_size, auto_encryption_opts=auto_encryption_opts, event_listeners=[self.client_listener, self.topology_listener], ) if auto_encryption_opts._bypass_auto_encryption is True: self.client_test.db.coll.insert_one({"_id": 0, "encrypted": self.ciphertext}) elif auto_encryption_opts._bypass_auto_encryption is False: client_encrypted.db.coll.insert_one({"_id": 0, "encrypted": "string0"}) else: raise RuntimeError("bypass_auto_encryption must be a bool") result = client_encrypted.db.coll.find_one({"_id": 0}) self.assertEqual(result, {"_id": 0, "encrypted": "string0"}) self.addCleanup(client_encrypted.close) def test_case_1(self): self._run_test( max_pool_size=1, auto_encryption_opts=AutoEncryptionOpts( *self.optargs, bypass_auto_encryption=False, key_vault_client=None ), ) cev = self.client_listener.started_events self.assertEqual(len(cev), 4) self.assertEqual(cev[0].command_name, "listCollections") self.assertEqual(cev[0].database_name, "db") self.assertEqual(cev[1].command_name, "find") self.assertEqual(cev[1].database_name, "keyvault") self.assertEqual(cev[2].command_name, "insert") self.assertEqual(cev[2].database_name, "db") self.assertEqual(cev[3].command_name, "find") self.assertEqual(cev[3].database_name, "db") self.assertEqual(len(self.topology_listener.results["opened"]), 2) def test_case_2(self): self._run_test( max_pool_size=1, auto_encryption_opts=AutoEncryptionOpts( *self.optargs, bypass_auto_encryption=False, key_vault_client=self.client_keyvault ), ) cev = self.client_listener.started_events self.assertEqual(len(cev), 3) self.assertEqual(cev[0].command_name, "listCollections") self.assertEqual(cev[0].database_name, "db") self.assertEqual(cev[1].command_name, "insert") self.assertEqual(cev[1].database_name, "db") self.assertEqual(cev[2].command_name, "find") self.assertEqual(cev[2].database_name, "db") cev = self.client_keyvault_listener.started_events self.assertEqual(len(cev), 1) self.assertEqual(cev[0].command_name, "find") self.assertEqual(cev[0].database_name, "keyvault") self.assertEqual(len(self.topology_listener.results["opened"]), 2) def test_case_3(self): self._run_test( max_pool_size=1, auto_encryption_opts=AutoEncryptionOpts( *self.optargs, bypass_auto_encryption=True, key_vault_client=None ), ) cev = self.client_listener.started_events self.assertEqual(len(cev), 2) self.assertEqual(cev[0].command_name, "find") self.assertEqual(cev[0].database_name, "db") self.assertEqual(cev[1].command_name, "find") self.assertEqual(cev[1].database_name, "keyvault") self.assertEqual(len(self.topology_listener.results["opened"]), 2) def test_case_4(self): self._run_test( max_pool_size=1, auto_encryption_opts=AutoEncryptionOpts( *self.optargs, bypass_auto_encryption=True, key_vault_client=self.client_keyvault ), ) cev = self.client_listener.started_events self.assertEqual(len(cev), 1) self.assertEqual(cev[0].command_name, "find") self.assertEqual(cev[0].database_name, "db") cev = self.client_keyvault_listener.started_events self.assertEqual(len(cev), 1) self.assertEqual(cev[0].command_name, "find") self.assertEqual(cev[0].database_name, "keyvault") self.assertEqual(len(self.topology_listener.results["opened"]), 1) def test_case_5(self): self._run_test( max_pool_size=None, auto_encryption_opts=AutoEncryptionOpts( *self.optargs, bypass_auto_encryption=False, key_vault_client=None ), ) cev = self.client_listener.started_events self.assertEqual(len(cev), 5) self.assertEqual(cev[0].command_name, "listCollections") self.assertEqual(cev[0].database_name, "db") self.assertEqual(cev[1].command_name, "listCollections") self.assertEqual(cev[1].database_name, "keyvault") self.assertEqual(cev[2].command_name, "find") self.assertEqual(cev[2].database_name, "keyvault") self.assertEqual(cev[3].command_name, "insert") self.assertEqual(cev[3].database_name, "db") self.assertEqual(cev[4].command_name, "find") self.assertEqual(cev[4].database_name, "db") self.assertEqual(len(self.topology_listener.results["opened"]), 1) def test_case_6(self): self._run_test( max_pool_size=None, auto_encryption_opts=AutoEncryptionOpts( *self.optargs, bypass_auto_encryption=False, key_vault_client=self.client_keyvault ), ) cev = self.client_listener.started_events self.assertEqual(len(cev), 3) self.assertEqual(cev[0].command_name, "listCollections") self.assertEqual(cev[0].database_name, "db") self.assertEqual(cev[1].command_name, "insert") self.assertEqual(cev[1].database_name, "db") self.assertEqual(cev[2].command_name, "find") self.assertEqual(cev[2].database_name, "db") cev = self.client_keyvault_listener.started_events self.assertEqual(len(cev), 1) self.assertEqual(cev[0].command_name, "find") self.assertEqual(cev[0].database_name, "keyvault") self.assertEqual(len(self.topology_listener.results["opened"]), 1) def test_case_7(self): self._run_test( max_pool_size=None, auto_encryption_opts=AutoEncryptionOpts( *self.optargs, bypass_auto_encryption=True, key_vault_client=None ), ) cev = self.client_listener.started_events self.assertEqual(len(cev), 2) self.assertEqual(cev[0].command_name, "find") self.assertEqual(cev[0].database_name, "db") self.assertEqual(cev[1].command_name, "find") self.assertEqual(cev[1].database_name, "keyvault") self.assertEqual(len(self.topology_listener.results["opened"]), 1) def test_case_8(self): self._run_test( max_pool_size=None, auto_encryption_opts=AutoEncryptionOpts( *self.optargs, bypass_auto_encryption=True, key_vault_client=self.client_keyvault ), ) cev = self.client_listener.started_events self.assertEqual(len(cev), 1) self.assertEqual(cev[0].command_name, "find") self.assertEqual(cev[0].database_name, "db") cev = self.client_keyvault_listener.started_events self.assertEqual(len(cev), 1) self.assertEqual(cev[0].command_name, "find") self.assertEqual(cev[0].database_name, "keyvault") self.assertEqual(len(self.topology_listener.results["opened"]), 1) # https://github.com/mongodb/specifications/blob/master/source/client-side-encryption/tests/README.rst#14-decryption-events class TestDecryptProse(EncryptionIntegrationTest): def setUp(self): self.client = client_context.client self.client.db.drop_collection("decryption_events") create_key_vault(self.client.keyvault.datakeys) kms_providers_map = {"local": {"key": LOCAL_MASTER_KEY}} self.client_encryption = ClientEncryption( kms_providers_map, "keyvault.datakeys", self.client, CodecOptions() ) keyID = self.client_encryption.create_data_key("local") self.cipher_text = self.client_encryption.encrypt( "hello", key_id=keyID, algorithm=Algorithm.AEAD_AES_256_CBC_HMAC_SHA_512_Deterministic ) self.malformed_cipher_text = self.cipher_text[:-1] + (self.cipher_text[-1] ^ 1).to_bytes( 1, "big" ) self.malformed_cipher_text = Binary(self.malformed_cipher_text, 6) opts = AutoEncryptionOpts( key_vault_namespace="keyvault.datakeys", kms_providers=kms_providers_map ) self.listener = AllowListEventListener("aggregate") self.encrypted_client = rs_or_single_client( auto_encryption_opts=opts, retryReads=False, event_listeners=[self.listener] ) self.addCleanup(self.encrypted_client.close) def test_01_command_error(self): with self.fail_point( { "mode": {"times": 1}, "data": {"errorCode": 123, "failCommands": ["aggregate"]}, } ): with self.assertRaises(OperationFailure): self.encrypted_client.db.decryption_events.aggregate([]) self.assertEqual(len(self.listener.failed_events), 1) for event in self.listener.failed_events: self.assertEqual(event.failure["code"], 123) def test_02_network_error(self): with self.fail_point( { "mode": {"times": 1}, "data": {"errorCode": 123, "closeConnection": True, "failCommands": ["aggregate"]}, } ): with self.assertRaises(AutoReconnect): self.encrypted_client.db.decryption_events.aggregate([]) self.assertEqual(len(self.listener.failed_events), 1) self.assertEqual(self.listener.failed_events[0].command_name, "aggregate") def test_03_decrypt_error(self): self.encrypted_client.db.decryption_events.insert_one( {"encrypted": self.malformed_cipher_text} ) with self.assertRaises(EncryptionError): next(self.encrypted_client.db.decryption_events.aggregate([])) event = self.listener.succeeded_events[0] self.assertEqual(len(self.listener.failed_events), 0) self.assertEqual( event.reply["cursor"]["firstBatch"][0]["encrypted"], self.malformed_cipher_text ) def test_04_decrypt_success(self): self.encrypted_client.db.decryption_events.insert_one({"encrypted": self.cipher_text}) next(self.encrypted_client.db.decryption_events.aggregate([])) event = self.listener.succeeded_events[0] self.assertEqual(len(self.listener.failed_events), 0) self.assertEqual(event.reply["cursor"]["firstBatch"][0]["encrypted"], self.cipher_text) # https://github.com/mongodb/specifications/blob/master/source/client-side-encryption/tests/README.rst#bypass-spawning-mongocryptd class TestBypassSpawningMongocryptdProse(EncryptionIntegrationTest): @unittest.skipIf( os.environ.get("TEST_CRYPT_SHARED"), "this prose test does not work when crypt_shared is on a system dynamic " "library search path.", ) def test_mongocryptd_bypass_spawn(self): # Lower the mongocryptd timeout to reduce the test run time. self._original_timeout = encryption._MONGOCRYPTD_TIMEOUT_MS encryption._MONGOCRYPTD_TIMEOUT_MS = 500 def reset_timeout(): encryption._MONGOCRYPTD_TIMEOUT_MS = self._original_timeout self.addCleanup(reset_timeout) # Configure the encrypted field via the local schema_map option. schemas = {"db.coll": json_data("external", "external-schema.json")} opts = AutoEncryptionOpts( {"local": {"key": LOCAL_MASTER_KEY}}, "keyvault.datakeys", schema_map=schemas, mongocryptd_bypass_spawn=True, mongocryptd_uri="mongodb://localhost:27027/", mongocryptd_spawn_args=[ "--pidfilepath=bypass-spawning-mongocryptd.pid", "--port=27027", ], ) client_encrypted = rs_or_single_client(auto_encryption_opts=opts) self.addCleanup(client_encrypted.close) with self.assertRaisesRegex(EncryptionError, "Timeout"): client_encrypted.db.coll.insert_one({"encrypted": "test"}) def test_bypassAutoEncryption(self): opts = AutoEncryptionOpts( {"local": {"key": LOCAL_MASTER_KEY}}, "keyvault.datakeys", bypass_auto_encryption=True, mongocryptd_spawn_args=[ "--pidfilepath=bypass-spawning-mongocryptd.pid", "--port=27027", ], ) client_encrypted = rs_or_single_client(auto_encryption_opts=opts) self.addCleanup(client_encrypted.close) client_encrypted.db.coll.insert_one({"unencrypted": "test"}) # Validate that mongocryptd was not spawned: mongocryptd_client = MongoClient("mongodb://localhost:27027/?serverSelectionTimeoutMS=500") with self.assertRaises(ServerSelectionTimeoutError): mongocryptd_client.admin.command("ping") @unittest.skipUnless(os.environ.get("TEST_CRYPT_SHARED"), "crypt_shared lib is not installed") def test_via_loading_shared_library(self): create_key_vault( client_context.client.keyvault.datakeys, json_data("external", "external-key.json") ) schemas = {"db.coll": json_data("external", "external-schema.json")} opts = AutoEncryptionOpts( kms_providers={"local": {"key": LOCAL_MASTER_KEY}}, key_vault_namespace="keyvault.datakeys", schema_map=schemas, mongocryptd_uri="mongodb://localhost:47021/db?serverSelectionTimeoutMS=1000", mongocryptd_spawn_args=[ "--pidfilepath=bypass-spawning-mongocryptd.pid", "--port=47021", ], crypt_shared_lib_required=True, ) client_encrypted = rs_or_single_client(auto_encryption_opts=opts) self.addCleanup(client_encrypted.close) client_encrypted.db.coll.drop() client_encrypted.db.coll.insert_one({"encrypted": "test"}) self.assertEncrypted(client_context.client.db.coll.find_one({})["encrypted"]) no_mongocryptd_client = MongoClient( host="mongodb://localhost:47021/db?serverSelectionTimeoutMS=1000" ) self.addCleanup(no_mongocryptd_client.close) with self.assertRaises(ServerSelectionTimeoutError): no_mongocryptd_client.db.command("ping") # https://github.com/mongodb/specifications/blob/master/source/client-side-encryption/tests/README.rst#20-bypass-creating-mongocryptd-client-when-shared-library-is-loaded @unittest.skipUnless(os.environ.get("TEST_CRYPT_SHARED"), "crypt_shared lib is not installed") def test_client_via_loading_shared_library(self): connection_established = False class Handler(socketserver.BaseRequestHandler): def handle(self): nonlocal connection_established connection_established = True server = socketserver.TCPServer(("localhost", 47021), Handler) def listener(): with server: server.serve_forever(poll_interval=0.05) # Short poll timeout to speed up the test listener_t = Thread(target=listener) listener_t.start() create_key_vault( client_context.client.keyvault.datakeys, json_data("external", "external-key.json") ) schemas = {"db.coll": json_data("external", "external-schema.json")} opts = AutoEncryptionOpts( kms_providers={"local": {"key": LOCAL_MASTER_KEY}}, key_vault_namespace="keyvault.datakeys", schema_map=schemas, mongocryptd_uri="mongodb://localhost:47021", crypt_shared_lib_required=False, ) client_encrypted = rs_or_single_client(auto_encryption_opts=opts) self.addCleanup(client_encrypted.close) client_encrypted.db.coll.drop() client_encrypted.db.coll.insert_one({"encrypted": "test"}) server.shutdown() listener_t.join() self.assertFalse(connection_established, "a connection was established on port 47021") # https://github.com/mongodb/specifications/tree/master/source/client-side-encryption/tests#kms-tls-tests class TestKmsTLSProse(EncryptionIntegrationTest): @unittest.skipUnless(any(AWS_CREDS.values()), "AWS environment credentials are not set") def setUp(self): super().setUp() self.patch_system_certs(CA_PEM) self.client_encrypted = ClientEncryption( {"aws": AWS_CREDS}, "keyvault.datakeys", self.client, OPTS ) self.addCleanup(self.client_encrypted.close) def test_invalid_kms_certificate_expired(self): key = { "region": "us-east-1", "key": "arn:aws:kms:us-east-1:579766882180:key/89fcc2c4-08b0-4bd9-9f25-e30687b580d0", "endpoint": "mongodb://127.0.0.1:9000", } # Some examples: # certificate verify failed: certificate has expired (_ssl.c:1129) # amazon1-2018 Python 3.6: certificate verify failed (_ssl.c:852) with self.assertRaisesRegex(EncryptionError, "expired|certificate verify failed"): self.client_encrypted.create_data_key("aws", master_key=key) def test_invalid_hostname_in_kms_certificate(self): key = { "region": "us-east-1", "key": "arn:aws:kms:us-east-1:579766882180:key/89fcc2c4-08b0-4bd9-9f25-e30687b580d0", "endpoint": "mongodb://127.0.0.1:9001", } # Some examples: # certificate verify failed: IP address mismatch, certificate is not valid for '127.0.0.1'. (_ssl.c:1129)" # hostname '127.0.0.1' doesn't match 'wronghost.com' # 127.0.0.1:9001: ('Certificate does not contain any `subjectAltName`s.',) with self.assertRaisesRegex( EncryptionError, "IP address mismatch|wronghost|IPAddressMismatch|Certificate" ): self.client_encrypted.create_data_key("aws", master_key=key) # https://github.com/mongodb/specifications/blob/master/source/client-side-encryption/tests/README.rst#kms-tls-options-tests class TestKmsTLSOptions(EncryptionIntegrationTest): @unittest.skipUnless(any(AWS_CREDS.values()), "AWS environment credentials are not set") def setUp(self): super().setUp() # 1, create client with only tlsCAFile. providers: dict = copy.deepcopy(ALL_KMS_PROVIDERS) providers["azure"]["identityPlatformEndpoint"] = "127.0.0.1:9002" providers["gcp"]["endpoint"] = "127.0.0.1:9002" kms_tls_opts_ca_only = { "aws": {"tlsCAFile": CA_PEM}, "azure": {"tlsCAFile": CA_PEM}, "gcp": {"tlsCAFile": CA_PEM}, "kmip": {"tlsCAFile": CA_PEM}, } self.client_encryption_no_client_cert = ClientEncryption( providers, "keyvault.datakeys", self.client, OPTS, kms_tls_options=kms_tls_opts_ca_only ) self.addCleanup(self.client_encryption_no_client_cert.close) # 2, same providers as above but with tlsCertificateKeyFile. kms_tls_opts = copy.deepcopy(kms_tls_opts_ca_only) for p in kms_tls_opts: kms_tls_opts[p]["tlsCertificateKeyFile"] = CLIENT_PEM self.client_encryption_with_tls = ClientEncryption( providers, "keyvault.datakeys", self.client, OPTS, kms_tls_options=kms_tls_opts ) self.addCleanup(self.client_encryption_with_tls.close) # 3, update endpoints to expired host. providers: dict = copy.deepcopy(providers) providers["azure"]["identityPlatformEndpoint"] = "127.0.0.1:9000" providers["gcp"]["endpoint"] = "127.0.0.1:9000" providers["kmip"]["endpoint"] = "127.0.0.1:9000" self.client_encryption_expired = ClientEncryption( providers, "keyvault.datakeys", self.client, OPTS, kms_tls_options=kms_tls_opts_ca_only ) self.addCleanup(self.client_encryption_expired.close) # 3, update endpoints to invalid host. providers: dict = copy.deepcopy(providers) providers["azure"]["identityPlatformEndpoint"] = "127.0.0.1:9001" providers["gcp"]["endpoint"] = "127.0.0.1:9001" providers["kmip"]["endpoint"] = "127.0.0.1:9001" self.client_encryption_invalid_hostname = ClientEncryption( providers, "keyvault.datakeys", self.client, OPTS, kms_tls_options=kms_tls_opts_ca_only ) self.addCleanup(self.client_encryption_invalid_hostname.close) # Errors when client has no cert, some examples: # [SSL: TLSV13_ALERT_CERTIFICATE_REQUIRED] tlsv13 alert certificate required (_ssl.c:2623) self.cert_error = ( "certificate required|SSL handshake failed|" "KMS connection closed|Connection reset by peer|ECONNRESET|EPIPE" ) # On Python 3.10+ this error might be: # EOF occurred in violation of protocol (_ssl.c:2384) if sys.version_info[:2] >= (3, 10): self.cert_error += "|EOF" # On Windows this error might be: # [WinError 10054] An existing connection was forcibly closed by the remote host if sys.platform == "win32": self.cert_error += "|forcibly closed" # 4, Test named KMS providers. providers = { "aws:no_client_cert": AWS_CREDS, "azure:no_client_cert": {"identityPlatformEndpoint": "127.0.0.1:9002", **AZURE_CREDS}, "gcp:no_client_cert": {"endpoint": "127.0.0.1:9002", **GCP_CREDS}, "kmip:no_client_cert": KMIP_CREDS, "aws:with_tls": AWS_CREDS, "azure:with_tls": {"identityPlatformEndpoint": "127.0.0.1:9002", **AZURE_CREDS}, "gcp:with_tls": {"endpoint": "127.0.0.1:9002", **GCP_CREDS}, "kmip:with_tls": KMIP_CREDS, } no_cert = {"tlsCAFile": CA_PEM} with_cert = {"tlsCAFile": CA_PEM, "tlsCertificateKeyFile": CLIENT_PEM} kms_tls_opts_4 = { "aws:no_client_cert": no_cert, "azure:no_client_cert": no_cert, "gcp:no_client_cert": no_cert, "kmip:no_client_cert": no_cert, "aws:with_tls": with_cert, "azure:with_tls": with_cert, "gcp:with_tls": with_cert, "kmip:with_tls": with_cert, } self.client_encryption_with_names = ClientEncryption( providers, "keyvault.datakeys", self.client, OPTS, kms_tls_options=kms_tls_opts_4 ) def test_01_aws(self): key = { "region": "us-east-1", "key": "arn:aws:kms:us-east-1:579766882180:key/89fcc2c4-08b0-4bd9-9f25-e30687b580d0", "endpoint": "127.0.0.1:9002", } with self.assertRaisesRegex(EncryptionError, self.cert_error): self.client_encryption_no_client_cert.create_data_key("aws", key) # "parse error" here means that the TLS handshake succeeded. with self.assertRaisesRegex(EncryptionError, "parse error"): self.client_encryption_with_tls.create_data_key("aws", key) # Some examples: # certificate verify failed: certificate has expired (_ssl.c:1129) # amazon1-2018 Python 3.6: certificate verify failed (_ssl.c:852) key["endpoint"] = "127.0.0.1:9000" with self.assertRaisesRegex(EncryptionError, "expired|certificate verify failed"): self.client_encryption_expired.create_data_key("aws", key) # Some examples: # certificate verify failed: IP address mismatch, certificate is not valid for '127.0.0.1'. (_ssl.c:1129)" # hostname '127.0.0.1' doesn't match 'wronghost.com' # 127.0.0.1:9001: ('Certificate does not contain any `subjectAltName`s.',) key["endpoint"] = "127.0.0.1:9001" with self.assertRaisesRegex( EncryptionError, "IP address mismatch|wronghost|IPAddressMismatch|Certificate" ): self.client_encryption_invalid_hostname.create_data_key("aws", key) def test_02_azure(self): key = {"keyVaultEndpoint": "doesnotexist.local", "keyName": "foo"} # Missing client cert error. with self.assertRaisesRegex(EncryptionError, self.cert_error): self.client_encryption_no_client_cert.create_data_key("azure", key) # "HTTP status=404" here means that the TLS handshake succeeded. with self.assertRaisesRegex(EncryptionError, "HTTP status=404"): self.client_encryption_with_tls.create_data_key("azure", key) # Expired cert error. with self.assertRaisesRegex(EncryptionError, "expired|certificate verify failed"): self.client_encryption_expired.create_data_key("azure", key) # Invalid cert hostname error. with self.assertRaisesRegex( EncryptionError, "IP address mismatch|wronghost|IPAddressMismatch|Certificate" ): self.client_encryption_invalid_hostname.create_data_key("azure", key) def test_03_gcp(self): key = {"projectId": "foo", "location": "bar", "keyRing": "baz", "keyName": "foo"} # Missing client cert error. with self.assertRaisesRegex(EncryptionError, self.cert_error): self.client_encryption_no_client_cert.create_data_key("gcp", key) # "HTTP status=404" here means that the TLS handshake succeeded. with self.assertRaisesRegex(EncryptionError, "HTTP status=404"): self.client_encryption_with_tls.create_data_key("gcp", key) # Expired cert error. with self.assertRaisesRegex(EncryptionError, "expired|certificate verify failed"): self.client_encryption_expired.create_data_key("gcp", key) # Invalid cert hostname error. with self.assertRaisesRegex( EncryptionError, "IP address mismatch|wronghost|IPAddressMismatch|Certificate" ): self.client_encryption_invalid_hostname.create_data_key("gcp", key) def test_04_kmip(self): # Missing client cert error. with self.assertRaisesRegex(EncryptionError, self.cert_error): self.client_encryption_no_client_cert.create_data_key("kmip") self.client_encryption_with_tls.create_data_key("kmip") # Expired cert error. with self.assertRaisesRegex(EncryptionError, "expired|certificate verify failed"): self.client_encryption_expired.create_data_key("kmip") # Invalid cert hostname error. with self.assertRaisesRegex( EncryptionError, "IP address mismatch|wronghost|IPAddressMismatch|Certificate" ): self.client_encryption_invalid_hostname.create_data_key("kmip") def test_05_tlsDisableOCSPEndpointCheck_is_permitted(self): providers = {"aws": {"accessKeyId": "foo", "secretAccessKey": "bar"}} options = {"aws": {"tlsDisableOCSPEndpointCheck": True}} encryption = ClientEncryption( providers, "keyvault.datakeys", self.client, OPTS, kms_tls_options=options ) self.addCleanup(encryption.close) ctx = encryption._io_callbacks.opts._kms_ssl_contexts["aws"] if not hasattr(ctx, "check_ocsp_endpoint"): raise self.skipTest("OCSP not enabled") self.assertFalse(ctx.check_ocsp_endpoint) def test_06_named_kms_providers_apply_tls_options_aws(self): key = { "region": "us-east-1", "key": "arn:aws:kms:us-east-1:579766882180:key/89fcc2c4-08b0-4bd9-9f25-e30687b580d0", "endpoint": "127.0.0.1:9002", } # Missing client cert error. with self.assertRaisesRegex(EncryptionError, self.cert_error): self.client_encryption_with_names.create_data_key("aws:no_client_cert", key) # "parse error" here means that the TLS handshake succeeded. with self.assertRaisesRegex(EncryptionError, "parse error"): self.client_encryption_with_names.create_data_key("aws:with_tls", key) def test_06_named_kms_providers_apply_tls_options_azure(self): key = {"keyVaultEndpoint": "doesnotexist.local", "keyName": "foo"} # Missing client cert error. with self.assertRaisesRegex(EncryptionError, self.cert_error): self.client_encryption_with_names.create_data_key("azure:no_client_cert", key) # "HTTP status=404" here means that the TLS handshake succeeded. with self.assertRaisesRegex(EncryptionError, "HTTP status=404"): self.client_encryption_with_names.create_data_key("azure:with_tls", key) def test_06_named_kms_providers_apply_tls_options_gcp(self): key = {"projectId": "foo", "location": "bar", "keyRing": "baz", "keyName": "foo"} # Missing client cert error. with self.assertRaisesRegex(EncryptionError, self.cert_error): self.client_encryption_with_names.create_data_key("gcp:no_client_cert", key) # "HTTP status=404" here means that the TLS handshake succeeded. with self.assertRaisesRegex(EncryptionError, "HTTP status=404"): self.client_encryption_with_names.create_data_key("gcp:with_tls", key) def test_06_named_kms_providers_apply_tls_options_kmip(self): # Missing client cert error. with self.assertRaisesRegex(EncryptionError, self.cert_error): self.client_encryption_with_names.create_data_key("kmip:no_client_cert") self.client_encryption_with_names.create_data_key("kmip:with_tls") # https://github.com/mongodb/specifications/blob/50e26fe/source/client-side-encryption/tests/README.rst#unique-index-on-keyaltnames class TestUniqueIndexOnKeyAltNamesProse(EncryptionIntegrationTest): def setUp(self): self.client = client_context.client create_key_vault(self.client.keyvault.datakeys) kms_providers_map = {"local": {"key": LOCAL_MASTER_KEY}} self.client_encryption = ClientEncryption( kms_providers_map, "keyvault.datakeys", self.client, CodecOptions() ) self.def_key_id = self.client_encryption.create_data_key("local", key_alt_names=["def"]) def test_01_create_key(self): self.client_encryption.create_data_key("local", key_alt_names=["abc"]) with self.assertRaisesRegex(EncryptionError, "E11000 duplicate key error collection"): self.client_encryption.create_data_key("local", key_alt_names=["abc"]) with self.assertRaisesRegex(EncryptionError, "E11000 duplicate key error collection"): self.client_encryption.create_data_key("local", key_alt_names=["def"]) def test_02_add_key_alt_name(self): key_id = self.client_encryption.create_data_key("local") self.client_encryption.add_key_alt_name(key_id, "abc") key_doc = self.client_encryption.add_key_alt_name(key_id, "abc") assert key_doc["keyAltNames"] == ["abc"] with self.assertRaisesRegex(DuplicateKeyError, "E11000 duplicate key error collection"): self.client_encryption.add_key_alt_name(key_id, "def") key_doc = self.client_encryption.add_key_alt_name(self.def_key_id, "def") assert key_doc["keyAltNames"] == ["def"] # https://github.com/mongodb/specifications/blob/d4c9432/source/client-side-encryption/tests/README.rst#explicit-encryption class TestExplicitQueryableEncryption(EncryptionIntegrationTest): @client_context.require_no_standalone @client_context.require_version_min(7, 0, -1) def setUp(self): super().setUp() self.encrypted_fields = json_data("etc", "data", "encryptedFields.json") self.key1_document = json_data("etc", "data", "keys", "key1-document.json") self.key1_id = self.key1_document["_id"] self.db = self.client.test_queryable_encryption self.client.drop_database(self.db) self.db.command("create", "explicit_encryption", encryptedFields=self.encrypted_fields) key_vault = create_key_vault(self.client.keyvault.datakeys, self.key1_document) self.addCleanup(key_vault.drop) self.key_vault_client = self.client self.client_encryption = ClientEncryption( {"local": {"key": LOCAL_MASTER_KEY}}, key_vault.full_name, self.key_vault_client, OPTS ) self.addCleanup(self.client_encryption.close) opts = AutoEncryptionOpts( {"local": {"key": LOCAL_MASTER_KEY}}, key_vault.full_name, bypass_query_analysis=True, ) self.encrypted_client = rs_or_single_client(auto_encryption_opts=opts) self.addCleanup(self.encrypted_client.close) def test_01_insert_encrypted_indexed_and_find(self): val = "encrypted indexed value" insert_payload = self.client_encryption.encrypt( val, Algorithm.INDEXED, self.key1_id, contention_factor=0 ) self.encrypted_client[self.db.name].explicit_encryption.insert_one( {"encryptedIndexed": insert_payload} ) find_payload = self.client_encryption.encrypt( val, Algorithm.INDEXED, self.key1_id, query_type=QueryType.EQUALITY, contention_factor=0 ) docs = list( self.encrypted_client[self.db.name].explicit_encryption.find( {"encryptedIndexed": find_payload} ) ) self.assertEqual(len(docs), 1) self.assertEqual(docs[0]["encryptedIndexed"], val) def test_02_insert_encrypted_indexed_and_find_contention(self): val = "encrypted indexed value" contention = 10 for _ in range(contention): insert_payload = self.client_encryption.encrypt( val, Algorithm.INDEXED, self.key1_id, contention_factor=contention ) self.encrypted_client[self.db.name].explicit_encryption.insert_one( {"encryptedIndexed": insert_payload} ) find_payload = self.client_encryption.encrypt( val, Algorithm.INDEXED, self.key1_id, query_type=QueryType.EQUALITY, contention_factor=0 ) docs = list( self.encrypted_client[self.db.name].explicit_encryption.find( {"encryptedIndexed": find_payload} ) ) self.assertLessEqual(len(docs), 10) for doc in docs: self.assertEqual(doc["encryptedIndexed"], val) # Find with contention_factor will return all 10 documents. find_payload = self.client_encryption.encrypt( val, Algorithm.INDEXED, self.key1_id, query_type=QueryType.EQUALITY, contention_factor=contention, ) docs = list( self.encrypted_client[self.db.name].explicit_encryption.find( {"encryptedIndexed": find_payload} ) ) self.assertEqual(len(docs), 10) for doc in docs: self.assertEqual(doc["encryptedIndexed"], val) def test_03_insert_encrypted_unindexed(self): val = "encrypted unindexed value" insert_payload = self.client_encryption.encrypt(val, Algorithm.UNINDEXED, self.key1_id) self.encrypted_client[self.db.name].explicit_encryption.insert_one( {"_id": 1, "encryptedUnindexed": insert_payload} ) docs = list(self.encrypted_client[self.db.name].explicit_encryption.find({"_id": 1})) self.assertEqual(len(docs), 1) self.assertEqual(docs[0]["encryptedUnindexed"], val) def test_04_roundtrip_encrypted_indexed(self): val = "encrypted indexed value" payload = self.client_encryption.encrypt( val, Algorithm.INDEXED, self.key1_id, contention_factor=0 ) decrypted = self.client_encryption.decrypt(payload) self.assertEqual(decrypted, val) def test_05_roundtrip_encrypted_unindexed(self): val = "encrypted indexed value" payload = self.client_encryption.encrypt(val, Algorithm.UNINDEXED, self.key1_id) decrypted = self.client_encryption.decrypt(payload) self.assertEqual(decrypted, val) # https://github.com/mongodb/specifications/blob/072601/source/client-side-encryption/tests/README.rst#rewrap class TestRewrapWithSeparateClientEncryption(EncryptionIntegrationTest): MASTER_KEYS: Mapping[str, Mapping[str, Any]] = { "aws": { "region": "us-east-1", "key": "arn:aws:kms:us-east-1:579766882180:key/89fcc2c4-08b0-4bd9-9f25-e30687b580d0", }, "azure": { "keyVaultEndpoint": "key-vault-csfle.vault.azure.net", "keyName": "key-name-csfle", }, "gcp": { "projectId": "devprod-drivers", "location": "global", "keyRing": "key-ring-csfle", "keyName": "key-name-csfle", }, "kmip": {}, "local": {}, } def test_rewrap(self): for src_provider in self.MASTER_KEYS: for dst_provider in self.MASTER_KEYS: with self.subTest(src_provider=src_provider, dst_provider=dst_provider): self.run_test(src_provider, dst_provider) def run_test(self, src_provider, dst_provider): # Step 1. Drop the collection ``keyvault.datakeys``. self.client.keyvault.drop_collection("datakeys") # Step 2. Create a ``ClientEncryption`` object named ``client_encryption1`` client_encryption1 = ClientEncryption( key_vault_client=self.client, key_vault_namespace="keyvault.datakeys", kms_providers=ALL_KMS_PROVIDERS, kms_tls_options=KMS_TLS_OPTS, codec_options=OPTS, ) self.addCleanup(client_encryption1.close) # Step 3. Call ``client_encryption1.create_data_key`` with ``src_provider``. key_id = client_encryption1.create_data_key( master_key=self.MASTER_KEYS[src_provider], kms_provider=src_provider ) # Step 4. Call ``client_encryption1.encrypt`` with the value "test" cipher_text = client_encryption1.encrypt( "test", key_id=key_id, algorithm=Algorithm.AEAD_AES_256_CBC_HMAC_SHA_512_Deterministic ) # Step 5. Create a ``ClientEncryption`` object named ``client_encryption2`` client2 = rs_or_single_client() self.addCleanup(client2.close) client_encryption2 = ClientEncryption( key_vault_client=client2, key_vault_namespace="keyvault.datakeys", kms_providers=ALL_KMS_PROVIDERS, kms_tls_options=KMS_TLS_OPTS, codec_options=OPTS, ) self.addCleanup(client_encryption1.close) # Step 6. Call ``client_encryption2.rewrap_many_data_key`` with an empty ``filter``. rewrap_many_data_key_result = client_encryption2.rewrap_many_data_key( {}, provider=dst_provider, master_key=self.MASTER_KEYS[dst_provider] ) self.assertEqual(rewrap_many_data_key_result.bulk_write_result.modified_count, 1) # 7. Call ``client_encryption1.decrypt`` with the ``cipher_text``. Assert the return value is "test". decrypt_result1 = client_encryption1.decrypt(cipher_text) self.assertEqual(decrypt_result1, "test") # 8. Call ``client_encryption2.decrypt`` with the ``cipher_text``. Assert the return value is "test". decrypt_result2 = client_encryption2.decrypt(cipher_text) self.assertEqual(decrypt_result2, "test") # 8. Case 2. Provider is not optional when master_key is given. with self.assertRaises(ConfigurationError): rewrap_many_data_key_result = client_encryption2.rewrap_many_data_key( {}, master_key=self.MASTER_KEYS[dst_provider] ) # https://github.com/mongodb/specifications/blob/5cf3ed/source/client-side-encryption/tests/README.rst#on-demand-aws-credentials class TestOnDemandAWSCredentials(EncryptionIntegrationTest): def setUp(self): super().setUp() self.master_key = { "region": "us-east-1", "key": ("arn:aws:kms:us-east-1:579766882180:key/89fcc2c4-08b0-4bd9-9f25-e30687b580d0"), } @unittest.skipIf(any(AWS_CREDS.values()), "AWS environment credentials are set") def test_01_failure(self): self.client_encryption = ClientEncryption( kms_providers={"aws": {}}, key_vault_namespace="keyvault.datakeys", key_vault_client=client_context.client, codec_options=OPTS, ) with self.assertRaises(EncryptionError): self.client_encryption.create_data_key("aws", self.master_key) @unittest.skipUnless(any(AWS_CREDS.values()), "AWS environment credentials are not set") def test_02_success(self): self.client_encryption = ClientEncryption( kms_providers={"aws": {}}, key_vault_namespace="keyvault.datakeys", key_vault_client=client_context.client, codec_options=OPTS, ) self.client_encryption.create_data_key("aws", self.master_key) class TestQueryableEncryptionDocsExample(EncryptionIntegrationTest): # Queryable Encryption is not supported on Standalone topology. @client_context.require_no_standalone @client_context.require_version_min(7, 0, -1) def setUp(self): super().setUp() def test_queryable_encryption(self): # MongoClient to use in testing that handles auth/tls/etc, # and cleanup. def MongoClient(**kwargs): c = rs_or_single_client(**kwargs) self.addCleanup(c.close) return c # Drop data from prior test runs. self.client.keyvault.datakeys.drop() self.client.drop_database("docs_examples") kms_providers_map = {"local": {"key": LOCAL_MASTER_KEY}} # Create two data keys. key_vault_client = MongoClient() client_encryption = ClientEncryption( kms_providers_map, "keyvault.datakeys", key_vault_client, CodecOptions() ) key1_id = client_encryption.create_data_key("local") key2_id = client_encryption.create_data_key("local") # Create an encryptedFieldsMap. encrypted_fields_map = { "docs_examples.encrypted": { "fields": [ { "path": "encrypted_indexed", "bsonType": "string", "keyId": key1_id, "queries": [ { "queryType": "equality", }, ], }, { "path": "encrypted_unindexed", "bsonType": "string", "keyId": key2_id, }, ], }, } # Create an Queryable Encryption collection. opts = AutoEncryptionOpts( kms_providers_map, "keyvault.datakeys", encrypted_fields_map=encrypted_fields_map ) encrypted_client = MongoClient(auto_encryption_opts=opts) # Create a Queryable Encryption collection "docs_examples.encrypted". # Because docs_examples.encrypted is in encrypted_fields_map, it is # created with Queryable Encryption support. db = encrypted_client.docs_examples encrypted_coll = db.create_collection("encrypted") # Auto encrypt an insert and find. # Encrypt an insert. encrypted_coll.insert_one( { "_id": 1, "encrypted_indexed": "indexed_value", "encrypted_unindexed": "unindexed_value", } ) # Encrypt a find. res = encrypted_coll.find_one({"encrypted_indexed": "indexed_value"}) assert res is not None assert res["encrypted_indexed"] == "indexed_value" assert res["encrypted_unindexed"] == "unindexed_value" # Find documents without decryption. unencrypted_client = MongoClient() unencrypted_coll = unencrypted_client.docs_examples.encrypted res = unencrypted_coll.find_one({"_id": 1}) assert res is not None assert isinstance(res["encrypted_indexed"], Binary) assert isinstance(res["encrypted_unindexed"], Binary) client_encryption.close() # https://github.com/mongodb/specifications/blob/master/source/client-side-encryption/tests/README.rst#range-explicit-encryption class TestRangeQueryProse(EncryptionIntegrationTest): @client_context.require_no_standalone @client_context.require_version_min(7, 0, -1) def setUp(self): super().setUp() self.key1_document = json_data("etc", "data", "keys", "key1-document.json") self.key1_id = self.key1_document["_id"] self.client.drop_database(self.db) key_vault = create_key_vault(self.client.keyvault.datakeys, self.key1_document) self.addCleanup(key_vault.drop) self.key_vault_client = self.client self.client_encryption = ClientEncryption( {"local": {"key": LOCAL_MASTER_KEY}}, key_vault.full_name, self.key_vault_client, OPTS ) self.addCleanup(self.client_encryption.close) opts = AutoEncryptionOpts( {"local": {"key": LOCAL_MASTER_KEY}}, key_vault.full_name, bypass_query_analysis=True, ) self.encrypted_client = rs_or_single_client(auto_encryption_opts=opts) self.db = self.encrypted_client.db self.addCleanup(self.encrypted_client.close) def run_expression_find( self, name, expression, expected_elems, range_opts, use_expr=False, key_id=None ): find_payload = self.client_encryption.encrypt_expression( expression=expression, key_id=key_id or self.key1_id, algorithm=Algorithm.RANGEPREVIEW, query_type=QueryType.RANGEPREVIEW, contention_factor=0, range_opts=range_opts, ) if use_expr: find_payload = {"$expr": find_payload} sorted_find = sorted( self.encrypted_client.db.explicit_encryption.find(find_payload), key=lambda x: x["_id"] ) for elem, expected in zip(sorted_find, expected_elems): self.assertEqual(elem[f"encrypted{name}"], expected) def run_test_cases(self, name, range_opts, cast_func): encrypted_fields = json_data("etc", "data", f"range-encryptedFields-{name}.json") self.db.drop_collection("explicit_encryption", encrypted_fields=encrypted_fields) self.db.create_collection("explicit_encryption", encryptedFields=encrypted_fields) def encrypt_and_cast(i): return self.client_encryption.encrypt( cast_func(i), key_id=self.key1_id, algorithm=Algorithm.RANGEPREVIEW, contention_factor=0, range_opts=range_opts, ) for elem in [{f"encrypted{name}": encrypt_and_cast(i)} for i in [0, 6, 30, 200]]: self.encrypted_client.db.explicit_encryption.insert_one(elem) # Case 1. insert_payload = self.client_encryption.encrypt( cast_func(6), key_id=self.key1_id, algorithm=Algorithm.RANGEPREVIEW, contention_factor=0, range_opts=range_opts, ) self.assertEqual(self.client_encryption.decrypt(insert_payload), cast_func(6)) # Case 2. expression = { "$and": [ {f"encrypted{name}": {"$gte": cast_func(6)}}, {f"encrypted{name}": {"$lte": cast_func(200)}}, ] } self.run_expression_find(name, expression, [cast_func(i) for i in [6, 30, 200]], range_opts) # Case 2, with UUID key_id self.run_expression_find( name, expression, [cast_func(i) for i in [6, 30, 200]], range_opts, key_id=self.key1_id.as_uuid(), ) # Case 3. self.run_expression_find( name, { "$and": [ {f"encrypted{name}": {"$gte": cast_func(0)}}, {f"encrypted{name}": {"$lte": cast_func(6)}}, ] }, [cast_func(i) for i in [0, 6]], range_opts, ) # Case 4. self.run_expression_find( name, { "$and": [ {f"encrypted{name}": {"$gt": cast_func(30)}}, ] }, [cast_func(i) for i in [200]], range_opts, ) # Case 5. self.run_expression_find( name, {"$and": [{"$lt": [f"$encrypted{name}", cast_func(30)]}]}, [cast_func(i) for i in [0, 6]], range_opts, use_expr=True, ) # The spec says to skip the following tests for no precision decimal or double types. if name not in ("DoubleNoPrecision", "DecimalNoPrecision"): # Case 6. with self.assertRaisesRegex( EncryptionError, "greater than or equal to the minimum value and less than or equal to the maximum value", ): self.client_encryption.encrypt( cast_func(201), key_id=self.key1_id, algorithm=Algorithm.RANGEPREVIEW, contention_factor=0, range_opts=range_opts, ) # Case 7. with self.assertRaisesRegex( EncryptionError, "expected matching 'min' and value type. Got range option" ): self.client_encryption.encrypt( 6 if cast_func != int else float(6), key_id=self.key1_id, algorithm=Algorithm.RANGEPREVIEW, contention_factor=0, range_opts=range_opts, ) # Case 8. # The spec says we must additionally not run this case with any precision type, not just the ones above. if "Precision" not in name: with self.assertRaisesRegex( EncryptionError, "expected 'precision' to be set with double or decimal128 index, but got:", ): self.client_encryption.encrypt( cast_func(6), key_id=self.key1_id, algorithm=Algorithm.RANGEPREVIEW, contention_factor=0, range_opts=RangeOpts( min=cast_func(0), max=cast_func(200), sparsity=1, precision=2 ), ) def test_double_no_precision(self): self.run_test_cases("DoubleNoPrecision", RangeOpts(sparsity=1), float) def test_double_precision(self): self.run_test_cases( "DoublePrecision", RangeOpts(min=0.0, max=200.0, sparsity=1, precision=2), float, ) def test_decimal_no_precision(self): self.run_test_cases( "DecimalNoPrecision", RangeOpts(sparsity=1), lambda x: Decimal128(str(x)) ) def test_decimal_precision(self): self.run_test_cases( "DecimalPrecision", RangeOpts(min=Decimal128("0.0"), max=Decimal128("200.0"), sparsity=1, precision=2), lambda x: Decimal128(str(x)), ) def test_datetime(self): self.run_test_cases( "Date", RangeOpts(min=DatetimeMS(0), max=DatetimeMS(200), sparsity=1), lambda x: DatetimeMS(x).as_datetime(), ) def test_int(self): self.run_test_cases("Int", RangeOpts(min=0, max=200, sparsity=1), int) # https://github.com/mongodb/specifications/blob/master/source/client-side-encryption/tests/README.rst#automatic-data-encryption-keys class TestAutomaticDecryptionKeys(EncryptionIntegrationTest): @client_context.require_no_standalone @client_context.require_version_min(7, 0, -1) def setUp(self): super().setUp() self.key1_document = json_data("etc", "data", "keys", "key1-document.json") self.key1_id = self.key1_document["_id"] self.client.drop_database(self.db) self.key_vault = create_key_vault(self.client.keyvault.datakeys, self.key1_document) self.addCleanup(self.key_vault.drop) self.client_encryption = ClientEncryption( {"local": {"key": LOCAL_MASTER_KEY}}, self.key_vault.full_name, self.client, OPTS, ) self.addCleanup(self.client_encryption.close) def test_01_simple_create(self): coll, _ = self.client_encryption.create_encrypted_collection( database=self.db, name="testing1", encrypted_fields={"fields": [{"path": "ssn", "bsonType": "string", "keyId": None}]}, kms_provider="local", ) with self.assertRaises(WriteError) as exc: coll.insert_one({"ssn": "123-45-6789"}) self.assertEqual(exc.exception.code, 121) def test_02_no_fields(self): with self.assertRaisesRegex( TypeError, "create_encrypted_collection.* missing 1 required positional argument: 'encrypted_fields'", ): self.client_encryption.create_encrypted_collection( # type:ignore[call-arg] database=self.db, name="testing1", ) def test_03_invalid_keyid(self): with self.assertRaisesRegex( EncryptedCollectionError, "create.encryptedFields.fields.keyId' is the wrong type 'bool', expected type 'binData", ): self.client_encryption.create_encrypted_collection( database=self.db, name="testing1", encrypted_fields={ "fields": [{"path": "ssn", "bsonType": "string", "keyId": False}] }, kms_provider="local", ) def test_04_insert_encrypted(self): coll, ef = self.client_encryption.create_encrypted_collection( database=self.db, name="testing1", encrypted_fields={"fields": [{"path": "ssn", "bsonType": "string", "keyId": None}]}, kms_provider="local", ) key1_id = ef["fields"][0]["keyId"] encrypted_value = self.client_encryption.encrypt( "123-45-6789", key_id=key1_id, algorithm=Algorithm.UNINDEXED, ) coll.insert_one({"ssn": encrypted_value}) def test_copy_encrypted_fields(self): encrypted_fields = { "fields": [ { "path": "ssn", "bsonType": "string", "keyId": None, } ] } _, ef = self.client_encryption.create_encrypted_collection( database=self.db, name="testing1", kms_provider="local", encrypted_fields=encrypted_fields, ) self.assertIsNotNone(ef["fields"][0]["keyId"]) self.assertIsNone(encrypted_fields["fields"][0]["keyId"]) def test_options_forward(self): coll, ef = self.client_encryption.create_encrypted_collection( database=self.db, name="testing1", kms_provider="local", encrypted_fields={"fields": [{"path": "ssn", "bsonType": "string", "keyId": None}]}, read_preference=ReadPreference.NEAREST, ) self.assertEqual(coll.read_preference, ReadPreference.NEAREST) self.assertEqual(coll.name, "testing1") def test_mixed_null_keyids(self): key = self.client_encryption.create_data_key(kms_provider="local") coll, ef = self.client_encryption.create_encrypted_collection( database=self.db, name="testing1", encrypted_fields={ "fields": [ {"path": "ssn", "bsonType": "string", "keyId": None}, {"path": "dob", "bsonType": "string", "keyId": key}, {"path": "secrets", "bsonType": "string"}, {"path": "address", "bsonType": "string", "keyId": None}, ] }, kms_provider="local", ) encrypted_values = [ self.client_encryption.encrypt( val, key_id=key, algorithm=Algorithm.UNINDEXED, ) for val, key in zip( ["123-45-6789", "11/22/1963", "My secret", "New Mexico, 87104"], [field["keyId"] for field in ef["fields"]], ) ] coll.insert_one( { "ssn": encrypted_values[0], "dob": encrypted_values[1], "secrets": encrypted_values[2], "address": encrypted_values[3], } ) def test_create_datakey_fails(self): key = self.client_encryption.create_data_key(kms_provider="local") encrypted_fields = { "fields": [ {"path": "address", "bsonType": "string", "keyId": key}, {"path": "dob", "bsonType": "string", "keyId": None}, ] } # Make sure the exception's encrypted_fields object includes the previous keys in the error message even when # generating keys fails. with self.assertRaises( EncryptedCollectionError, ) as exc: self.client_encryption.create_encrypted_collection( database=self.db, name="testing1", encrypted_fields=encrypted_fields, kms_provider="does not exist", ) self.assertEqual(exc.exception.encrypted_fields, encrypted_fields) def test_create_failure(self): key = self.client_encryption.create_data_key(kms_provider="local") # Make sure the exception's encrypted_fields object includes the previous keys in the error message even when # it is the creation of the collection that fails. with self.assertRaises( EncryptedCollectionError, ) as exc: self.client_encryption.create_encrypted_collection( database=self.db, name=1, # type:ignore[arg-type] encrypted_fields={ "fields": [ {"path": "address", "bsonType": "string", "keyId": key}, {"path": "dob", "bsonType": "string", "keyId": None}, ] }, kms_provider="local", ) for field in exc.exception.encrypted_fields["fields"]: self.assertIsInstance(field["keyId"], Binary) def test_collection_name_collision(self): encrypted_fields = { "fields": [ {"path": "address", "bsonType": "string", "keyId": None}, ] } self.db.create_collection("testing1") with self.assertRaises( EncryptedCollectionError, ) as exc: self.client_encryption.create_encrypted_collection( database=self.db, name="testing1", encrypted_fields=encrypted_fields, kms_provider="local", ) self.assertIsInstance(exc.exception.encrypted_fields["fields"][0]["keyId"], Binary) self.db.drop_collection("testing1", encrypted_fields=encrypted_fields) self.client_encryption.create_encrypted_collection( database=self.db, name="testing1", encrypted_fields=encrypted_fields, kms_provider="local", ) with self.assertRaises( EncryptedCollectionError, ) as exc: self.client_encryption.create_encrypted_collection( database=self.db, name="testing1", encrypted_fields=encrypted_fields, kms_provider="local", ) self.assertIsInstance(exc.exception.encrypted_fields["fields"][0]["keyId"], Binary) def start_mongocryptd(port) -> None: args = ["mongocryptd", f"--port={port}", "--idleShutdownTimeoutSecs=60"] _spawn_daemon(args) class TestNoSessionsSupport(EncryptionIntegrationTest): mongocryptd_client: MongoClient MONGOCRYPTD_PORT = 27020 @classmethod @unittest.skipIf(os.environ.get("TEST_CRYPT_SHARED"), "crypt_shared lib is installed") def setUpClass(cls): super().setUpClass() start_mongocryptd(cls.MONGOCRYPTD_PORT) @classmethod def tearDownClass(cls): super().tearDownClass() def setUp(self) -> None: self.listener = OvertCommandListener() self.mongocryptd_client = MongoClient( f"mongodb://localhost:{self.MONGOCRYPTD_PORT}", event_listeners=[self.listener] ) self.addCleanup(self.mongocryptd_client.close) hello = self.mongocryptd_client.db.command("hello") self.assertNotIn("logicalSessionTimeoutMinutes", hello) def test_implicit_session_ignored_when_unsupported(self): self.listener.reset() with self.assertRaises(OperationFailure): self.mongocryptd_client.db.test.find_one() self.assertNotIn("lsid", self.listener.started_events[0].command) with self.assertRaises(OperationFailure): self.mongocryptd_client.db.test.insert_one({"x": 1}) self.assertNotIn("lsid", self.listener.started_events[1].command) def test_explicit_session_errors_when_unsupported(self): self.listener.reset() with self.mongocryptd_client.start_session() as s: with self.assertRaisesRegex( ConfigurationError, r"Sessions are not supported by this MongoDB deployment" ): self.mongocryptd_client.db.test.find_one(session=s) with self.assertRaisesRegex( ConfigurationError, r"Sessions are not supported by this MongoDB deployment" ): self.mongocryptd_client.db.test.insert_one({"x": 1}, session=s) if __name__ == "__main__": unittest.main() mongodb-mongo-python-driver-509e9b7/test/test_errors.py000066400000000000000000000075511462766011000233510ustar00rootroot00000000000000# Copyright 2020-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. from __future__ import annotations import pickle import sys import traceback sys.path[0:0] = [""] from test import PyMongoTestCase, unittest from pymongo.errors import ( BulkWriteError, EncryptionError, NotPrimaryError, OperationFailure, ) class TestErrors(PyMongoTestCase): def test_not_primary_error(self): exc = NotPrimaryError("not primary test", {"errmsg": "error"}) self.assertIn("full error", str(exc)) try: raise exc except NotPrimaryError: self.assertIn("full error", traceback.format_exc()) def test_operation_failure(self): exc = OperationFailure("operation failure test", 10, {"errmsg": "error"}) self.assertIn("full error", str(exc)) try: raise exc except OperationFailure: self.assertIn("full error", traceback.format_exc()) def _test_unicode_strs(self, exc): if sys.implementation.name == "pypy" and sys.implementation.version < (7, 3, 7): # PyPy used to display unicode in repr differently. self.assertEqual( "unicode \U0001f40d, full error: {'errmsg': 'unicode \\U0001f40d'}", str(exc) ) else: self.assertEqual( "unicode \U0001f40d, full error: {'errmsg': 'unicode \U0001f40d'}", str(exc) ) try: raise exc except Exception: self.assertIn("full error", traceback.format_exc()) def test_unicode_strs_operation_failure(self): exc = OperationFailure("unicode \U0001f40d", 10, {"errmsg": "unicode \U0001f40d"}) self._test_unicode_strs(exc) def test_unicode_strs_not_primary_error(self): exc = NotPrimaryError("unicode \U0001f40d", {"errmsg": "unicode \U0001f40d"}) self._test_unicode_strs(exc) def assertPyMongoErrorEqual(self, exc1, exc2): self.assertEqual(exc1._message, exc2._message) self.assertEqual(exc1._error_labels, exc2._error_labels) self.assertEqual(exc1.args, exc2.args) self.assertEqual(str(exc1), str(exc2)) def assertOperationFailureEqual(self, exc1, exc2): self.assertPyMongoErrorEqual(exc1, exc2) self.assertEqual(exc1.code, exc2.code) self.assertEqual(exc1.details, exc2.details) self.assertEqual(exc1._max_wire_version, exc2._max_wire_version) def test_pickle_NotPrimaryError(self): exc = NotPrimaryError("not primary test", {"errmsg": "error"}) self.assertPyMongoErrorEqual(exc, pickle.loads(pickle.dumps(exc))) def test_pickle_OperationFailure(self): exc = OperationFailure("error", code=5, details={}, max_wire_version=7) self.assertOperationFailureEqual(exc, pickle.loads(pickle.dumps(exc))) def test_pickle_BulkWriteError(self): exc = BulkWriteError({}) self.assertOperationFailureEqual(exc, pickle.loads(pickle.dumps(exc))) self.assertIn("batch op errors occurred", str(exc)) def test_pickle_EncryptionError(self): cause = OperationFailure("error", code=5, details={}, max_wire_version=7) exc = EncryptionError(cause) exc2 = pickle.loads(pickle.dumps(exc)) self.assertPyMongoErrorEqual(exc, exc2) self.assertOperationFailureEqual(cause, exc2.cause) if __name__ == "__main__": unittest.main() mongodb-mongo-python-driver-509e9b7/test/test_examples.py000066400000000000000000001360241462766011000236510ustar00rootroot00000000000000# Copyright 2017 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. """MongoDB documentation examples in Python.""" from __future__ import annotations import datetime import sys import threading sys.path[0:0] = [""] from test import IntegrationTest, client_context, unittest from test.utils import rs_client, wait_until import pymongo from pymongo.errors import ConnectionFailure, OperationFailure from pymongo.read_concern import ReadConcern from pymongo.read_preferences import ReadPreference from pymongo.server_api import ServerApi from pymongo.write_concern import WriteConcern class TestSampleShellCommands(IntegrationTest): @classmethod def setUpClass(cls): super().setUpClass() # Run once before any tests run. cls.db.inventory.drop() @classmethod def tearDownClass(cls): cls.client.drop_database("pymongo_test") def tearDown(self): # Run after every test. self.db.inventory.drop() def test_first_three_examples(self): db = self.db # Start Example 1 db.inventory.insert_one( { "item": "canvas", "qty": 100, "tags": ["cotton"], "size": {"h": 28, "w": 35.5, "uom": "cm"}, } ) # End Example 1 self.assertEqual(db.inventory.count_documents({}), 1) # Start Example 2 cursor = db.inventory.find({"item": "canvas"}) # End Example 2 self.assertEqual(len(list(cursor)), 1) # Start Example 3 db.inventory.insert_many( [ { "item": "journal", "qty": 25, "tags": ["blank", "red"], "size": {"h": 14, "w": 21, "uom": "cm"}, }, { "item": "mat", "qty": 85, "tags": ["gray"], "size": {"h": 27.9, "w": 35.5, "uom": "cm"}, }, { "item": "mousepad", "qty": 25, "tags": ["gel", "blue"], "size": {"h": 19, "w": 22.85, "uom": "cm"}, }, ] ) # End Example 3 self.assertEqual(db.inventory.count_documents({}), 4) def test_query_top_level_fields(self): db = self.db # Start Example 6 db.inventory.insert_many( [ { "item": "journal", "qty": 25, "size": {"h": 14, "w": 21, "uom": "cm"}, "status": "A", }, { "item": "notebook", "qty": 50, "size": {"h": 8.5, "w": 11, "uom": "in"}, "status": "A", }, { "item": "paper", "qty": 100, "size": {"h": 8.5, "w": 11, "uom": "in"}, "status": "D", }, { "item": "planner", "qty": 75, "size": {"h": 22.85, "w": 30, "uom": "cm"}, "status": "D", }, { "item": "postcard", "qty": 45, "size": {"h": 10, "w": 15.25, "uom": "cm"}, "status": "A", }, ] ) # End Example 6 self.assertEqual(db.inventory.count_documents({}), 5) # Start Example 7 cursor = db.inventory.find({}) # End Example 7 self.assertEqual(len(list(cursor)), 5) # Start Example 9 cursor = db.inventory.find({"status": "D"}) # End Example 9 self.assertEqual(len(list(cursor)), 2) # Start Example 10 cursor = db.inventory.find({"status": {"$in": ["A", "D"]}}) # End Example 10 self.assertEqual(len(list(cursor)), 5) # Start Example 11 cursor = db.inventory.find({"status": "A", "qty": {"$lt": 30}}) # End Example 11 self.assertEqual(len(list(cursor)), 1) # Start Example 12 cursor = db.inventory.find({"$or": [{"status": "A"}, {"qty": {"$lt": 30}}]}) # End Example 12 self.assertEqual(len(list(cursor)), 3) # Start Example 13 cursor = db.inventory.find( {"status": "A", "$or": [{"qty": {"$lt": 30}}, {"item": {"$regex": "^p"}}]} ) # End Example 13 self.assertEqual(len(list(cursor)), 2) def test_query_embedded_documents(self): db = self.db # Start Example 14 # Subdocument key order matters in a few of these examples so we have # to use bson.son.SON instead of a Python dict. from bson.son import SON db.inventory.insert_many( [ { "item": "journal", "qty": 25, "size": SON([("h", 14), ("w", 21), ("uom", "cm")]), "status": "A", }, { "item": "notebook", "qty": 50, "size": SON([("h", 8.5), ("w", 11), ("uom", "in")]), "status": "A", }, { "item": "paper", "qty": 100, "size": SON([("h", 8.5), ("w", 11), ("uom", "in")]), "status": "D", }, { "item": "planner", "qty": 75, "size": SON([("h", 22.85), ("w", 30), ("uom", "cm")]), "status": "D", }, { "item": "postcard", "qty": 45, "size": SON([("h", 10), ("w", 15.25), ("uom", "cm")]), "status": "A", }, ] ) # End Example 14 # Start Example 15 cursor = db.inventory.find({"size": SON([("h", 14), ("w", 21), ("uom", "cm")])}) # End Example 15 self.assertEqual(len(list(cursor)), 1) # Start Example 16 cursor = db.inventory.find({"size": SON([("w", 21), ("h", 14), ("uom", "cm")])}) # End Example 16 self.assertEqual(len(list(cursor)), 0) # Start Example 17 cursor = db.inventory.find({"size.uom": "in"}) # End Example 17 self.assertEqual(len(list(cursor)), 2) # Start Example 18 cursor = db.inventory.find({"size.h": {"$lt": 15}}) # End Example 18 self.assertEqual(len(list(cursor)), 4) # Start Example 19 cursor = db.inventory.find({"size.h": {"$lt": 15}, "size.uom": "in", "status": "D"}) # End Example 19 self.assertEqual(len(list(cursor)), 1) def test_query_arrays(self): db = self.db # Start Example 20 db.inventory.insert_many( [ {"item": "journal", "qty": 25, "tags": ["blank", "red"], "dim_cm": [14, 21]}, {"item": "notebook", "qty": 50, "tags": ["red", "blank"], "dim_cm": [14, 21]}, { "item": "paper", "qty": 100, "tags": ["red", "blank", "plain"], "dim_cm": [14, 21], }, {"item": "planner", "qty": 75, "tags": ["blank", "red"], "dim_cm": [22.85, 30]}, {"item": "postcard", "qty": 45, "tags": ["blue"], "dim_cm": [10, 15.25]}, ] ) # End Example 20 # Start Example 21 cursor = db.inventory.find({"tags": ["red", "blank"]}) # End Example 21 self.assertEqual(len(list(cursor)), 1) # Start Example 22 cursor = db.inventory.find({"tags": {"$all": ["red", "blank"]}}) # End Example 22 self.assertEqual(len(list(cursor)), 4) # Start Example 23 cursor = db.inventory.find({"tags": "red"}) # End Example 23 self.assertEqual(len(list(cursor)), 4) # Start Example 24 cursor = db.inventory.find({"dim_cm": {"$gt": 25}}) # End Example 24 self.assertEqual(len(list(cursor)), 1) # Start Example 25 cursor = db.inventory.find({"dim_cm": {"$gt": 15, "$lt": 20}}) # End Example 25 self.assertEqual(len(list(cursor)), 4) # Start Example 26 cursor = db.inventory.find({"dim_cm": {"$elemMatch": {"$gt": 22, "$lt": 30}}}) # End Example 26 self.assertEqual(len(list(cursor)), 1) # Start Example 27 cursor = db.inventory.find({"dim_cm.1": {"$gt": 25}}) # End Example 27 self.assertEqual(len(list(cursor)), 1) # Start Example 28 cursor = db.inventory.find({"tags": {"$size": 3}}) # End Example 28 self.assertEqual(len(list(cursor)), 1) def test_query_array_of_documents(self): db = self.db # Start Example 29 # Subdocument key order matters in a few of these examples so we have # to use bson.son.SON instead of a Python dict. from bson.son import SON db.inventory.insert_many( [ { "item": "journal", "instock": [ SON([("warehouse", "A"), ("qty", 5)]), SON([("warehouse", "C"), ("qty", 15)]), ], }, {"item": "notebook", "instock": [SON([("warehouse", "C"), ("qty", 5)])]}, { "item": "paper", "instock": [ SON([("warehouse", "A"), ("qty", 60)]), SON([("warehouse", "B"), ("qty", 15)]), ], }, { "item": "planner", "instock": [ SON([("warehouse", "A"), ("qty", 40)]), SON([("warehouse", "B"), ("qty", 5)]), ], }, { "item": "postcard", "instock": [ SON([("warehouse", "B"), ("qty", 15)]), SON([("warehouse", "C"), ("qty", 35)]), ], }, ] ) # End Example 29 # Start Example 30 cursor = db.inventory.find({"instock": SON([("warehouse", "A"), ("qty", 5)])}) # End Example 30 self.assertEqual(len(list(cursor)), 1) # Start Example 31 cursor = db.inventory.find({"instock": SON([("qty", 5), ("warehouse", "A")])}) # End Example 31 self.assertEqual(len(list(cursor)), 0) # Start Example 32 cursor = db.inventory.find({"instock.0.qty": {"$lte": 20}}) # End Example 32 self.assertEqual(len(list(cursor)), 3) # Start Example 33 cursor = db.inventory.find({"instock.qty": {"$lte": 20}}) # End Example 33 self.assertEqual(len(list(cursor)), 5) # Start Example 34 cursor = db.inventory.find({"instock": {"$elemMatch": {"qty": 5, "warehouse": "A"}}}) # End Example 34 self.assertEqual(len(list(cursor)), 1) # Start Example 35 cursor = db.inventory.find({"instock": {"$elemMatch": {"qty": {"$gt": 10, "$lte": 20}}}}) # End Example 35 self.assertEqual(len(list(cursor)), 3) # Start Example 36 cursor = db.inventory.find({"instock.qty": {"$gt": 10, "$lte": 20}}) # End Example 36 self.assertEqual(len(list(cursor)), 4) # Start Example 37 cursor = db.inventory.find({"instock.qty": 5, "instock.warehouse": "A"}) # End Example 37 self.assertEqual(len(list(cursor)), 2) def test_query_null(self): db = self.db # Start Example 38 db.inventory.insert_many([{"_id": 1, "item": None}, {"_id": 2}]) # End Example 38 # Start Example 39 cursor = db.inventory.find({"item": None}) # End Example 39 self.assertEqual(len(list(cursor)), 2) # Start Example 40 cursor = db.inventory.find({"item": {"$type": 10}}) # End Example 40 self.assertEqual(len(list(cursor)), 1) # Start Example 41 cursor = db.inventory.find({"item": {"$exists": False}}) # End Example 41 self.assertEqual(len(list(cursor)), 1) def test_projection(self): db = self.db # Start Example 42 db.inventory.insert_many( [ { "item": "journal", "status": "A", "size": {"h": 14, "w": 21, "uom": "cm"}, "instock": [{"warehouse": "A", "qty": 5}], }, { "item": "notebook", "status": "A", "size": {"h": 8.5, "w": 11, "uom": "in"}, "instock": [{"warehouse": "C", "qty": 5}], }, { "item": "paper", "status": "D", "size": {"h": 8.5, "w": 11, "uom": "in"}, "instock": [{"warehouse": "A", "qty": 60}], }, { "item": "planner", "status": "D", "size": {"h": 22.85, "w": 30, "uom": "cm"}, "instock": [{"warehouse": "A", "qty": 40}], }, { "item": "postcard", "status": "A", "size": {"h": 10, "w": 15.25, "uom": "cm"}, "instock": [{"warehouse": "B", "qty": 15}, {"warehouse": "C", "qty": 35}], }, ] ) # End Example 42 # Start Example 43 cursor = db.inventory.find({"status": "A"}) # End Example 43 self.assertEqual(len(list(cursor)), 3) # Start Example 44 cursor = db.inventory.find({"status": "A"}, {"item": 1, "status": 1}) # End Example 44 for doc in cursor: self.assertTrue("_id" in doc) self.assertTrue("item" in doc) self.assertTrue("status" in doc) self.assertFalse("size" in doc) self.assertFalse("instock" in doc) # Start Example 45 cursor = db.inventory.find({"status": "A"}, {"item": 1, "status": 1, "_id": 0}) # End Example 45 for doc in cursor: self.assertFalse("_id" in doc) self.assertTrue("item" in doc) self.assertTrue("status" in doc) self.assertFalse("size" in doc) self.assertFalse("instock" in doc) # Start Example 46 cursor = db.inventory.find({"status": "A"}, {"status": 0, "instock": 0}) # End Example 46 for doc in cursor: self.assertTrue("_id" in doc) self.assertTrue("item" in doc) self.assertFalse("status" in doc) self.assertTrue("size" in doc) self.assertFalse("instock" in doc) # Start Example 47 cursor = db.inventory.find({"status": "A"}, {"item": 1, "status": 1, "size.uom": 1}) # End Example 47 for doc in cursor: self.assertTrue("_id" in doc) self.assertTrue("item" in doc) self.assertTrue("status" in doc) self.assertTrue("size" in doc) self.assertFalse("instock" in doc) size = doc["size"] self.assertTrue("uom" in size) self.assertFalse("h" in size) self.assertFalse("w" in size) # Start Example 48 cursor = db.inventory.find({"status": "A"}, {"size.uom": 0}) # End Example 48 for doc in cursor: self.assertTrue("_id" in doc) self.assertTrue("item" in doc) self.assertTrue("status" in doc) self.assertTrue("size" in doc) self.assertTrue("instock" in doc) size = doc["size"] self.assertFalse("uom" in size) self.assertTrue("h" in size) self.assertTrue("w" in size) # Start Example 49 cursor = db.inventory.find({"status": "A"}, {"item": 1, "status": 1, "instock.qty": 1}) # End Example 49 for doc in cursor: self.assertTrue("_id" in doc) self.assertTrue("item" in doc) self.assertTrue("status" in doc) self.assertFalse("size" in doc) self.assertTrue("instock" in doc) for subdoc in doc["instock"]: self.assertFalse("warehouse" in subdoc) self.assertTrue("qty" in subdoc) # Start Example 50 cursor = db.inventory.find( {"status": "A"}, {"item": 1, "status": 1, "instock": {"$slice": -1}} ) # End Example 50 for doc in cursor: self.assertTrue("_id" in doc) self.assertTrue("item" in doc) self.assertTrue("status" in doc) self.assertFalse("size" in doc) self.assertTrue("instock" in doc) self.assertEqual(len(doc["instock"]), 1) def test_update_and_replace(self): db = self.db # Start Example 51 db.inventory.insert_many( [ { "item": "canvas", "qty": 100, "size": {"h": 28, "w": 35.5, "uom": "cm"}, "status": "A", }, { "item": "journal", "qty": 25, "size": {"h": 14, "w": 21, "uom": "cm"}, "status": "A", }, { "item": "mat", "qty": 85, "size": {"h": 27.9, "w": 35.5, "uom": "cm"}, "status": "A", }, { "item": "mousepad", "qty": 25, "size": {"h": 19, "w": 22.85, "uom": "cm"}, "status": "P", }, { "item": "notebook", "qty": 50, "size": {"h": 8.5, "w": 11, "uom": "in"}, "status": "P", }, { "item": "paper", "qty": 100, "size": {"h": 8.5, "w": 11, "uom": "in"}, "status": "D", }, { "item": "planner", "qty": 75, "size": {"h": 22.85, "w": 30, "uom": "cm"}, "status": "D", }, { "item": "postcard", "qty": 45, "size": {"h": 10, "w": 15.25, "uom": "cm"}, "status": "A", }, { "item": "sketchbook", "qty": 80, "size": {"h": 14, "w": 21, "uom": "cm"}, "status": "A", }, { "item": "sketch pad", "qty": 95, "size": {"h": 22.85, "w": 30.5, "uom": "cm"}, "status": "A", }, ] ) # End Example 51 # Start Example 52 db.inventory.update_one( {"item": "paper"}, {"$set": {"size.uom": "cm", "status": "P"}, "$currentDate": {"lastModified": True}}, ) # End Example 52 for doc in db.inventory.find({"item": "paper"}): self.assertEqual(doc["size"]["uom"], "cm") self.assertEqual(doc["status"], "P") self.assertTrue("lastModified" in doc) # Start Example 53 db.inventory.update_many( {"qty": {"$lt": 50}}, {"$set": {"size.uom": "in", "status": "P"}, "$currentDate": {"lastModified": True}}, ) # End Example 53 for doc in db.inventory.find({"qty": {"$lt": 50}}): self.assertEqual(doc["size"]["uom"], "in") self.assertEqual(doc["status"], "P") self.assertTrue("lastModified" in doc) # Start Example 54 db.inventory.replace_one( {"item": "paper"}, { "item": "paper", "instock": [{"warehouse": "A", "qty": 60}, {"warehouse": "B", "qty": 40}], }, ) # End Example 54 for doc in db.inventory.find({"item": "paper"}, {"_id": 0}): self.assertEqual(len(doc.keys()), 2) self.assertTrue("item" in doc) self.assertTrue("instock" in doc) self.assertEqual(len(doc["instock"]), 2) def test_delete(self): db = self.db # Start Example 55 db.inventory.insert_many( [ { "item": "journal", "qty": 25, "size": {"h": 14, "w": 21, "uom": "cm"}, "status": "A", }, { "item": "notebook", "qty": 50, "size": {"h": 8.5, "w": 11, "uom": "in"}, "status": "P", }, { "item": "paper", "qty": 100, "size": {"h": 8.5, "w": 11, "uom": "in"}, "status": "D", }, { "item": "planner", "qty": 75, "size": {"h": 22.85, "w": 30, "uom": "cm"}, "status": "D", }, { "item": "postcard", "qty": 45, "size": {"h": 10, "w": 15.25, "uom": "cm"}, "status": "A", }, ] ) # End Example 55 self.assertEqual(db.inventory.count_documents({}), 5) # Start Example 57 db.inventory.delete_many({"status": "A"}) # End Example 57 self.assertEqual(db.inventory.count_documents({}), 3) # Start Example 58 db.inventory.delete_one({"status": "D"}) # End Example 58 self.assertEqual(db.inventory.count_documents({}), 2) # Start Example 56 db.inventory.delete_many({}) # End Example 56 self.assertEqual(db.inventory.count_documents({}), 0) @client_context.require_change_streams def test_change_streams(self): db = self.db done = False def insert_docs(): while not done: db.inventory.insert_one({"username": "alice"}) db.inventory.delete_one({"username": "alice"}) t = threading.Thread(target=insert_docs) t.start() try: # 1. The database for reactive, real-time applications # Start Changestream Example 1 cursor = db.inventory.watch() next(cursor) # End Changestream Example 1 # Start Changestream Example 2 cursor = db.inventory.watch(full_document="updateLookup") next(cursor) # End Changestream Example 2 # Start Changestream Example 3 resume_token = cursor.resume_token cursor = db.inventory.watch(resume_after=resume_token) next(cursor) # End Changestream Example 3 # Start Changestream Example 4 pipeline = [ {"$match": {"fullDocument.username": "alice"}}, {"$addFields": {"newField": "this is an added field!"}}, ] cursor = db.inventory.watch(pipeline=pipeline) next(cursor) # End Changestream Example 4 finally: done = True t.join() def test_aggregate_examples(self): db = self.db # Start Aggregation Example 1 db.sales.aggregate([{"$match": {"items.fruit": "banana"}}, {"$sort": {"date": 1}}]) # End Aggregation Example 1 # Start Aggregation Example 2 db.sales.aggregate( [ {"$unwind": "$items"}, {"$match": {"items.fruit": "banana"}}, { "$group": { "_id": {"day": {"$dayOfWeek": "$date"}}, "count": {"$sum": "$items.quantity"}, } }, {"$project": {"dayOfWeek": "$_id.day", "numberSold": "$count", "_id": 0}}, {"$sort": {"numberSold": 1}}, ] ) # End Aggregation Example 2 # Start Aggregation Example 3 db.sales.aggregate( [ {"$unwind": "$items"}, { "$group": { "_id": {"day": {"$dayOfWeek": "$date"}}, "items_sold": {"$sum": "$items.quantity"}, "revenue": {"$sum": {"$multiply": ["$items.quantity", "$items.price"]}}, } }, { "$project": { "day": "$_id.day", "revenue": 1, "items_sold": 1, "discount": { "$cond": {"if": {"$lte": ["$revenue", 250]}, "then": 25, "else": 0} }, } }, ] ) # End Aggregation Example 3 # Start Aggregation Example 4 db.air_alliances.aggregate( [ { "$lookup": { "from": "air_airlines", "let": {"constituents": "$airlines"}, "pipeline": [{"$match": {"$expr": {"$in": ["$name", "$$constituents"]}}}], "as": "airlines", } }, { "$project": { "_id": 0, "name": 1, "airlines": { "$filter": { "input": "$airlines", "as": "airline", "cond": {"$eq": ["$$airline.country", "Canada"]}, } }, } }, ] ) # End Aggregation Example 4 def test_commands(self): db = self.db db.restaurants.insert_one({}) # Start runCommand Example 1 db.command("buildInfo") # End runCommand Example 1 # Start runCommand Example 2 db.command("count", "restaurants") # End runCommand Example 2 def test_index_management(self): db = self.db # Start Index Example 1 db.records.create_index("score") # End Index Example 1 # Start Index Example 1 db.restaurants.create_index( [("cuisine", pymongo.ASCENDING), ("name", pymongo.ASCENDING)], partialFilterExpression={"rating": {"$gt": 5}}, ) # End Index Example 1 @client_context.require_replica_set def test_misc(self): # Marketing examples client = self.client self.addCleanup(client.drop_database, "test") self.addCleanup(client.drop_database, "my_database") # 2. Tunable consistency controls collection = client.my_database.my_collection with client.start_session() as session: collection.insert_one({"_id": 1}, session=session) collection.update_one({"_id": 1}, {"$set": {"a": 1}}, session=session) for _doc in collection.find({}, session=session): pass # 3. Exploiting the power of arrays collection = client.test.array_updates_test collection.update_one({"_id": 1}, {"$set": {"a.$[i].b": 2}}, array_filters=[{"i.b": 0}]) class TestTransactionExamples(IntegrationTest): @client_context.require_transactions def test_transactions(self): # Transaction examples client = self.client self.addCleanup(client.drop_database, "hr") self.addCleanup(client.drop_database, "reporting") employees = client.hr.employees events = client.reporting.events employees.insert_one({"employee": 3, "status": "Active"}) events.insert_one({"employee": 3, "status": {"new": "Active", "old": None}}) # Start Transactions Intro Example 1 def update_employee_info(session): employees_coll = session.client.hr.employees events_coll = session.client.reporting.events with session.start_transaction( read_concern=ReadConcern("snapshot"), write_concern=WriteConcern(w="majority") ): employees_coll.update_one( {"employee": 3}, {"$set": {"status": "Inactive"}}, session=session ) events_coll.insert_one( {"employee": 3, "status": {"new": "Inactive", "old": "Active"}}, session=session ) while True: try: # Commit uses write concern set at transaction start. session.commit_transaction() print("Transaction committed.") break except (ConnectionFailure, OperationFailure) as exc: # Can retry commit if exc.has_error_label("UnknownTransactionCommitResult"): print("UnknownTransactionCommitResult, retrying commit operation ...") continue else: print("Error during commit ...") raise # End Transactions Intro Example 1 with client.start_session() as session: update_employee_info(session) employee = employees.find_one({"employee": 3}) assert employee is not None self.assertIsNotNone(employee) self.assertEqual(employee["status"], "Inactive") # Start Transactions Retry Example 1 def run_transaction_with_retry(txn_func, session): while True: try: txn_func(session) # performs transaction break except (ConnectionFailure, OperationFailure) as exc: print("Transaction aborted. Caught exception during transaction.") # If transient error, retry the whole transaction if exc.has_error_label("TransientTransactionError"): print("TransientTransactionError, retrying transaction ...") continue else: raise # End Transactions Retry Example 1 with client.start_session() as session: run_transaction_with_retry(update_employee_info, session) employee = employees.find_one({"employee": 3}) assert employee is not None self.assertIsNotNone(employee) self.assertEqual(employee["status"], "Inactive") # Start Transactions Retry Example 2 def commit_with_retry(session): while True: try: # Commit uses write concern set at transaction start. session.commit_transaction() print("Transaction committed.") break except (ConnectionFailure, OperationFailure) as exc: # Can retry commit if exc.has_error_label("UnknownTransactionCommitResult"): print("UnknownTransactionCommitResult, retrying commit operation ...") continue else: print("Error during commit ...") raise # End Transactions Retry Example 2 # Test commit_with_retry from the previous examples def _insert_employee_retry_commit(session): with session.start_transaction(): employees.insert_one({"employee": 4, "status": "Active"}, session=session) events.insert_one( {"employee": 4, "status": {"new": "Active", "old": None}}, session=session ) commit_with_retry(session) with client.start_session() as session: run_transaction_with_retry(_insert_employee_retry_commit, session) employee = employees.find_one({"employee": 4}) assert employee is not None self.assertIsNotNone(employee) self.assertEqual(employee["status"], "Active") # Start Transactions Retry Example 3 def run_transaction_with_retry(txn_func, session): while True: try: txn_func(session) # performs transaction break except (ConnectionFailure, OperationFailure) as exc: # If transient error, retry the whole transaction if exc.has_error_label("TransientTransactionError"): print("TransientTransactionError, retrying transaction ...") continue else: raise def commit_with_retry(session): while True: try: # Commit uses write concern set at transaction start. session.commit_transaction() print("Transaction committed.") break except (ConnectionFailure, OperationFailure) as exc: # Can retry commit if exc.has_error_label("UnknownTransactionCommitResult"): print("UnknownTransactionCommitResult, retrying commit operation ...") continue else: print("Error during commit ...") raise # Updates two collections in a transactions def update_employee_info(session): employees_coll = session.client.hr.employees events_coll = session.client.reporting.events with session.start_transaction( read_concern=ReadConcern("snapshot"), write_concern=WriteConcern(w="majority"), read_preference=ReadPreference.PRIMARY, ): employees_coll.update_one( {"employee": 3}, {"$set": {"status": "Inactive"}}, session=session ) events_coll.insert_one( {"employee": 3, "status": {"new": "Inactive", "old": "Active"}}, session=session ) commit_with_retry(session) # Start a session. with client.start_session() as session: try: run_transaction_with_retry(update_employee_info, session) except Exception: # Do something with error. raise # End Transactions Retry Example 3 employee = employees.find_one({"employee": 3}) assert employee is not None self.assertIsNotNone(employee) self.assertEqual(employee["status"], "Inactive") def MongoClient(_): return rs_client() uriString = None # Start Transactions withTxn API Example 1 # For a replica set, include the replica set name and a seedlist of the members in the URI string; e.g. # uriString = 'mongodb://mongodb0.example.com:27017,mongodb1.example.com:27017/?replicaSet=myRepl' # For a sharded cluster, connect to the mongos instances; e.g. # uriString = 'mongodb://mongos0.example.com:27017,mongos1.example.com:27017/' client = MongoClient(uriString) wc_majority = WriteConcern("majority", wtimeout=1000) # Prereq: Create collections. client.get_database("mydb1", write_concern=wc_majority).foo.insert_one({"abc": 0}) client.get_database("mydb2", write_concern=wc_majority).bar.insert_one({"xyz": 0}) # Step 1: Define the callback that specifies the sequence of operations to perform inside the transactions. def callback(session): collection_one = session.client.mydb1.foo collection_two = session.client.mydb2.bar # Important:: You must pass the session to the operations. collection_one.insert_one({"abc": 1}, session=session) collection_two.insert_one({"xyz": 999}, session=session) # Step 2: Start a client session. with client.start_session() as session: # Step 3: Use with_transaction to start a transaction, execute the callback, and commit (or abort on error). session.with_transaction( callback, read_concern=ReadConcern("local"), write_concern=wc_majority, read_preference=ReadPreference.PRIMARY, ) # End Transactions withTxn API Example 1 class TestCausalConsistencyExamples(IntegrationTest): @client_context.require_secondaries_count(1) @client_context.require_no_mmap def test_causal_consistency(self): # Causal consistency examples client = self.client self.addCleanup(client.drop_database, "test") client.test.drop_collection("items") client.test.items.insert_one( {"sku": "111", "name": "Peanuts", "start": datetime.datetime.today()} ) # Start Causal Consistency Example 1 with client.start_session(causal_consistency=True) as s1: current_date = datetime.datetime.today() items = client.get_database( "test", read_concern=ReadConcern("majority"), write_concern=WriteConcern("majority", wtimeout=1000), ).items items.update_one( {"sku": "111", "end": None}, {"$set": {"end": current_date}}, session=s1 ) items.insert_one( {"sku": "nuts-111", "name": "Pecans", "start": current_date}, session=s1 ) # End Causal Consistency Example 1 assert s1.cluster_time is not None assert s1.operation_time is not None # Start Causal Consistency Example 2 with client.start_session(causal_consistency=True) as s2: s2.advance_cluster_time(s1.cluster_time) s2.advance_operation_time(s1.operation_time) items = client.get_database( "test", read_preference=ReadPreference.SECONDARY, read_concern=ReadConcern("majority"), write_concern=WriteConcern("majority", wtimeout=1000), ).items for item in items.find({"end": None}, session=s2): print(item) # End Causal Consistency Example 2 class TestVersionedApiExamples(IntegrationTest): @client_context.require_version_min(4, 7) def test_versioned_api(self): # Versioned API examples def MongoClient(_, server_api): return rs_client(server_api=server_api, connect=False) uri = None # Start Versioned API Example 1 from pymongo.server_api import ServerApi MongoClient(uri, server_api=ServerApi("1")) # End Versioned API Example 1 # Start Versioned API Example 2 MongoClient(uri, server_api=ServerApi("1", strict=True)) # End Versioned API Example 2 # Start Versioned API Example 3 MongoClient(uri, server_api=ServerApi("1", strict=False)) # End Versioned API Example 3 # Start Versioned API Example 4 MongoClient(uri, server_api=ServerApi("1", deprecation_errors=True)) # End Versioned API Example 4 @unittest.skip("PYTHON-3167 count has been added to API version 1") @client_context.require_version_min(4, 7) def test_versioned_api_migration(self): # SERVER-58785 if client_context.is_topology_type(["sharded"]) and not client_context.version.at_least( 5, 0, 2 ): self.skipTest("This test needs MongoDB 5.0.2 or newer") client = rs_client(server_api=ServerApi("1", strict=True)) client.db.sales.drop() # Start Versioned API Example 5 def strptime(s): return datetime.datetime.strptime(s, "%Y-%m-%dT%H:%M:%SZ") client.db.sales.insert_many( [ { "_id": 1, "item": "abc", "price": 10, "quantity": 2, "date": strptime("2021-01-01T08:00:00Z"), }, { "_id": 2, "item": "jkl", "price": 20, "quantity": 1, "date": strptime("2021-02-03T09:00:00Z"), }, { "_id": 3, "item": "xyz", "price": 5, "quantity": 5, "date": strptime("2021-02-03T09:05:00Z"), }, { "_id": 4, "item": "abc", "price": 10, "quantity": 10, "date": strptime("2021-02-15T08:00:00Z"), }, { "_id": 5, "item": "xyz", "price": 5, "quantity": 10, "date": strptime("2021-02-15T09:05:00Z"), }, { "_id": 6, "item": "xyz", "price": 5, "quantity": 5, "date": strptime("2021-02-15T12:05:10Z"), }, { "_id": 7, "item": "xyz", "price": 5, "quantity": 10, "date": strptime("2021-02-15T14:12:12Z"), }, { "_id": 8, "item": "abc", "price": 10, "quantity": 5, "date": strptime("2021-03-16T20:20:13Z"), }, ] ) # End Versioned API Example 5 with self.assertRaisesRegex( OperationFailure, "Provided apiStrict:true, but the command count is not in API Version 1", ): client.db.command("count", "sales", query={}) # Start Versioned API Example 6 # pymongo.errors.OperationFailure: Provided apiStrict:true, but the command count is not in API Version 1, full error: {'ok': 0.0, 'errmsg': 'Provided apiStrict:true, but the command count is not in API Version 1', 'code': 323, 'codeName': 'APIStrictError'} # End Versioned API Example 6 # Start Versioned API Example 7 client.db.sales.count_documents({}) # End Versioned API Example 7 # Start Versioned API Example 8 # 8 # End Versioned API Example 8 class TestSnapshotQueryExamples(IntegrationTest): @client_context.require_version_min(5, 0) def test_snapshot_query(self): client = self.client if not client_context.is_topology_type(["replicaset", "sharded"]): self.skipTest("Must be a sharded or replicaset") self.addCleanup(client.drop_database, "pets") db = client.pets db.drop_collection("cats") db.drop_collection("dogs") db.cats.insert_one({"name": "Whiskers", "color": "white", "age": 10, "adoptable": True}) db.dogs.insert_one({"name": "Pebbles", "color": "Brown", "age": 10, "adoptable": True}) wait_until(lambda: self.check_for_snapshot(db.cats), "success") wait_until(lambda: self.check_for_snapshot(db.dogs), "success") # Start Snapshot Query Example 1 db = client.pets with client.start_session(snapshot=True) as s: adoptablePetsCount = db.cats.aggregate( [{"$match": {"adoptable": True}}, {"$count": "adoptableCatsCount"}], session=s ).next()["adoptableCatsCount"] adoptablePetsCount += db.dogs.aggregate( [{"$match": {"adoptable": True}}, {"$count": "adoptableDogsCount"}], session=s ).next()["adoptableDogsCount"] print(adoptablePetsCount) # End Snapshot Query Example 1 db = client.retail self.addCleanup(client.drop_database, "retail") db.drop_collection("sales") saleDate = datetime.datetime.now() db.sales.insert_one({"shoeType": "boot", "price": 30, "saleDate": saleDate}) wait_until(lambda: self.check_for_snapshot(db.sales), "success") # Start Snapshot Query Example 2 db = client.retail with client.start_session(snapshot=True) as s: db.sales.aggregate( [ { "$match": { "$expr": { "$gt": [ "$saleDate", { "$dateSubtract": { "startDate": "$$NOW", "unit": "day", "amount": 1, } }, ] } } }, {"$count": "totalDailySales"}, ], session=s, ).next()["totalDailySales"] # End Snapshot Query Example 2 def check_for_snapshot(self, collection): """Wait for snapshot reads to become available to prevent this error: [246:SnapshotUnavailable]: Unable to read from a snapshot due to pending collection catalog changes; please retry the operation. Snapshot timestamp is Timestamp(1646666892, 4). Collection minimum is Timestamp(1646666892, 5) (on localhost:27017, modern retry, attempt 1) From https://github.com/mongodb/mongo-ruby-driver/commit/7c4117b58e3d12e237f7536f7521e18fc15f79ac """ with self.client.start_session(snapshot=True) as s: try: if collection.find_one(session=s): return True return False except OperationFailure as e: # Retry them as the server demands... if e.code == 246: # SnapshotUnavailable return False raise if __name__ == "__main__": unittest.main() mongodb-mongo-python-driver-509e9b7/test/test_fork.py000066400000000000000000000070041462766011000227670ustar00rootroot00000000000000# Copyright 2022-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. """Test that pymongo resets its own locks after a fork.""" from __future__ import annotations import os import sys import unittest import warnings from multiprocessing import Pipe sys.path[0:0] = [""] from test import IntegrationTest from test.utils import is_greenthread_patched from bson.objectid import ObjectId @unittest.skipIf( not hasattr(os, "register_at_fork"), "register_at_fork not available in this version of Python" ) @unittest.skipIf( is_greenthread_patched(), "gevent and eventlet do not support POSIX-style forking.", ) class TestFork(IntegrationTest): def test_lock_client(self): # Forks the client with some items locked. # Parent => All locks should be as before the fork. # Child => All locks should be reset. with self.client._MongoClient__lock: def target(): with warnings.catch_warnings(): warnings.simplefilter("ignore") self.client.admin.command("ping") with self.fork(target): pass self.client.admin.command("ping") def test_lock_object_id(self): # Forks the client with ObjectId's _inc_lock locked. # Parent => _inc_lock should remain locked. # Child => _inc_lock should be unlocked. with ObjectId._inc_lock: def target(): self.assertFalse(ObjectId._inc_lock.locked()) self.assertTrue(ObjectId()) with self.fork(target): pass def test_topology_reset(self): # Tests that topologies are different from each other. # Cannot use ID because virtual memory addresses may be the same. # Cannot reinstantiate ObjectId in the topology settings. # Relies on difference in PID when opened again. parent_conn, child_conn = Pipe() init_id = self.client._topology._pid parent_cursor_exc = self.client._kill_cursors_executor def target(): # Catch the fork warning and send to the parent for assertion. with warnings.catch_warnings(record=True) as ctx: warnings.simplefilter("always") self.client.admin.command("ping") child_conn.send(str(ctx[0])) child_conn.send(self.client._topology._pid) child_conn.send( ( parent_cursor_exc != self.client._kill_cursors_executor, "client._kill_cursors_executor was not reinitialized", ) ) with self.fork(target): self.assertEqual(self.client._topology._pid, init_id) fork_warning = parent_conn.recv() self.assertIn("MongoClient opened before fork", fork_warning) child_id = parent_conn.recv() self.assertNotEqual(child_id, init_id) passed, msg = parent_conn.recv() self.assertTrue(passed, msg) if __name__ == "__main__": unittest.main() mongodb-mongo-python-driver-509e9b7/test/test_grid_file.py000066400000000000000000000633431462766011000237620ustar00rootroot00000000000000# # Copyright 2009-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. """Tests for the grid_file module.""" from __future__ import annotations import datetime import io import sys import zipfile from io import BytesIO from pymongo.database import Database sys.path[0:0] = [""] from test import IntegrationTest, qcheck, unittest from test.utils import EventListener, rs_or_single_client from bson.objectid import ObjectId from gridfs import GridFS from gridfs.errors import NoFile from gridfs.grid_file import ( _SEEK_CUR, _SEEK_END, DEFAULT_CHUNK_SIZE, GridIn, GridOut, GridOutCursor, ) from pymongo import MongoClient from pymongo.errors import ConfigurationError, ServerSelectionTimeoutError from pymongo.message import _CursorAddress class TestGridFileNoConnect(unittest.TestCase): """Test GridFile features on a client that does not connect.""" db: Database @classmethod def setUpClass(cls): cls.db = MongoClient(connect=False).pymongo_test def test_grid_in_custom_opts(self): self.assertRaises(TypeError, GridIn, "foo") a = GridIn( self.db.fs, _id=5, filename="my_file", contentType="text/html", chunkSize=1000, aliases=["foo"], metadata={"foo": 1, "bar": 2}, bar=3, baz="hello", ) self.assertEqual(5, a._id) self.assertEqual("my_file", a.filename) self.assertEqual("my_file", a.name) self.assertEqual("text/html", a.content_type) self.assertEqual(1000, a.chunk_size) self.assertEqual(["foo"], a.aliases) self.assertEqual({"foo": 1, "bar": 2}, a.metadata) self.assertEqual(3, a.bar) self.assertEqual("hello", a.baz) self.assertRaises(AttributeError, getattr, a, "mike") b = GridIn(self.db.fs, content_type="text/html", chunk_size=1000, baz=100) self.assertEqual("text/html", b.content_type) self.assertEqual(1000, b.chunk_size) self.assertEqual(100, b.baz) class TestGridFile(IntegrationTest): def setUp(self): self.cleanup_colls(self.db.fs.files, self.db.fs.chunks) def test_basic(self): f = GridIn(self.db.fs, filename="test") f.write(b"hello world") f.close() self.assertEqual(1, self.db.fs.files.count_documents({})) self.assertEqual(1, self.db.fs.chunks.count_documents({})) g = GridOut(self.db.fs, f._id) self.assertEqual(b"hello world", g.read()) # make sure it's still there... g = GridOut(self.db.fs, f._id) self.assertEqual(b"hello world", g.read()) f = GridIn(self.db.fs, filename="test") f.close() self.assertEqual(2, self.db.fs.files.count_documents({})) self.assertEqual(1, self.db.fs.chunks.count_documents({})) g = GridOut(self.db.fs, f._id) self.assertEqual(b"", g.read()) # test that reading 0 returns proper type self.assertEqual(b"", g.read(0)) def test_md5(self): f = GridIn(self.db.fs) f.write(b"hello world\n") f.close() self.assertEqual(None, f.md5) def test_alternate_collection(self): self.db.alt.files.delete_many({}) self.db.alt.chunks.delete_many({}) f = GridIn(self.db.alt) f.write(b"hello world") f.close() self.assertEqual(1, self.db.alt.files.count_documents({})) self.assertEqual(1, self.db.alt.chunks.count_documents({})) g = GridOut(self.db.alt, f._id) self.assertEqual(b"hello world", g.read()) def test_grid_in_default_opts(self): self.assertRaises(TypeError, GridIn, "foo") a = GridIn(self.db.fs) self.assertTrue(isinstance(a._id, ObjectId)) self.assertRaises(AttributeError, setattr, a, "_id", 5) self.assertEqual(None, a.filename) self.assertEqual(None, a.name) a.filename = "my_file" self.assertEqual("my_file", a.filename) self.assertEqual("my_file", a.name) self.assertEqual(None, a.content_type) a.content_type = "text/html" self.assertEqual("text/html", a.content_type) self.assertRaises(AttributeError, getattr, a, "length") self.assertRaises(AttributeError, setattr, a, "length", 5) self.assertEqual(255 * 1024, a.chunk_size) self.assertRaises(AttributeError, setattr, a, "chunk_size", 5) self.assertRaises(AttributeError, getattr, a, "upload_date") self.assertRaises(AttributeError, setattr, a, "upload_date", 5) self.assertRaises(AttributeError, getattr, a, "aliases") a.aliases = ["foo"] self.assertEqual(["foo"], a.aliases) self.assertRaises(AttributeError, getattr, a, "metadata") a.metadata = {"foo": 1} self.assertEqual({"foo": 1}, a.metadata) self.assertRaises(AttributeError, setattr, a, "md5", 5) a.close() a.forty_two = 42 self.assertEqual(42, a.forty_two) self.assertTrue(isinstance(a._id, ObjectId)) self.assertRaises(AttributeError, setattr, a, "_id", 5) self.assertEqual("my_file", a.filename) self.assertEqual("my_file", a.name) self.assertEqual("text/html", a.content_type) self.assertEqual(0, a.length) self.assertRaises(AttributeError, setattr, a, "length", 5) self.assertEqual(255 * 1024, a.chunk_size) self.assertRaises(AttributeError, setattr, a, "chunk_size", 5) self.assertTrue(isinstance(a.upload_date, datetime.datetime)) self.assertRaises(AttributeError, setattr, a, "upload_date", 5) self.assertEqual(["foo"], a.aliases) self.assertEqual({"foo": 1}, a.metadata) self.assertEqual(None, a.md5) self.assertRaises(AttributeError, setattr, a, "md5", 5) # Make sure custom attributes that were set both before and after # a.close() are reflected in b. PYTHON-411. b = GridFS(self.db).get_last_version(filename=a.filename) self.assertEqual(a.metadata, b.metadata) self.assertEqual(a.aliases, b.aliases) self.assertEqual(a.forty_two, b.forty_two) def test_grid_out_default_opts(self): self.assertRaises(TypeError, GridOut, "foo") gout = GridOut(self.db.fs, 5) with self.assertRaises(NoFile): gout.name a = GridIn(self.db.fs) a.close() b = GridOut(self.db.fs, a._id) self.assertEqual(a._id, b._id) self.assertEqual(0, b.length) self.assertEqual(None, b.content_type) self.assertEqual(None, b.name) self.assertEqual(None, b.filename) self.assertEqual(255 * 1024, b.chunk_size) self.assertTrue(isinstance(b.upload_date, datetime.datetime)) self.assertEqual(None, b.aliases) self.assertEqual(None, b.metadata) self.assertEqual(None, b.md5) for attr in [ "_id", "name", "content_type", "length", "chunk_size", "upload_date", "aliases", "metadata", "md5", ]: self.assertRaises(AttributeError, setattr, b, attr, 5) def test_grid_out_cursor_options(self): self.assertRaises( TypeError, GridOutCursor.__init__, self.db.fs, {}, projection={"filename": 1} ) cursor = GridOutCursor(self.db.fs, {}) cursor_clone = cursor.clone() cursor_dict = cursor.__dict__.copy() cursor_dict.pop("_Cursor__session") cursor_clone_dict = cursor_clone.__dict__.copy() cursor_clone_dict.pop("_Cursor__session") self.assertDictEqual(cursor_dict, cursor_clone_dict) self.assertRaises(NotImplementedError, cursor.add_option, 0) self.assertRaises(NotImplementedError, cursor.remove_option, 0) def test_grid_out_custom_opts(self): one = GridIn( self.db.fs, _id=5, filename="my_file", contentType="text/html", chunkSize=1000, aliases=["foo"], metadata={"foo": 1, "bar": 2}, bar=3, baz="hello", ) one.write(b"hello world") one.close() two = GridOut(self.db.fs, 5) self.assertEqual("my_file", two.name) self.assertEqual("my_file", two.filename) self.assertEqual(5, two._id) self.assertEqual(11, two.length) self.assertEqual("text/html", two.content_type) self.assertEqual(1000, two.chunk_size) self.assertTrue(isinstance(two.upload_date, datetime.datetime)) self.assertEqual(["foo"], two.aliases) self.assertEqual({"foo": 1, "bar": 2}, two.metadata) self.assertEqual(3, two.bar) self.assertEqual(None, two.md5) for attr in [ "_id", "name", "content_type", "length", "chunk_size", "upload_date", "aliases", "metadata", "md5", ]: self.assertRaises(AttributeError, setattr, two, attr, 5) def test_grid_out_file_document(self): one = GridIn(self.db.fs) one.write(b"foo bar") one.close() two = GridOut(self.db.fs, file_document=self.db.fs.files.find_one()) self.assertEqual(b"foo bar", two.read()) three = GridOut(self.db.fs, 5, file_document=self.db.fs.files.find_one()) self.assertEqual(b"foo bar", three.read()) four = GridOut(self.db.fs, file_document={}) with self.assertRaises(NoFile): four.name def test_write_file_like(self): one = GridIn(self.db.fs) one.write(b"hello world") one.close() two = GridOut(self.db.fs, one._id) three = GridIn(self.db.fs) three.write(two) three.close() four = GridOut(self.db.fs, three._id) self.assertEqual(b"hello world", four.read()) five = GridIn(self.db.fs, chunk_size=2) five.write(b"hello") buffer = BytesIO(b" world") five.write(buffer) five.write(b" and mongodb") five.close() self.assertEqual(b"hello world and mongodb", GridOut(self.db.fs, five._id).read()) def test_write_lines(self): a = GridIn(self.db.fs) a.writelines([b"hello ", b"world"]) a.close() self.assertEqual(b"hello world", GridOut(self.db.fs, a._id).read()) def test_close(self): f = GridIn(self.db.fs) f.close() self.assertRaises(ValueError, f.write, "test") f.close() def test_closed(self): f = GridIn(self.db.fs, chunkSize=5) f.write(b"Hello world.\nHow are you?") f.close() g = GridOut(self.db.fs, f._id) self.assertFalse(g.closed) g.read(1) self.assertFalse(g.closed) g.read(100) self.assertFalse(g.closed) g.close() self.assertTrue(g.closed) def test_multi_chunk_file(self): random_string = b"a" * (DEFAULT_CHUNK_SIZE + 1000) f = GridIn(self.db.fs) f.write(random_string) f.close() self.assertEqual(1, self.db.fs.files.count_documents({})) self.assertEqual(2, self.db.fs.chunks.count_documents({})) g = GridOut(self.db.fs, f._id) self.assertEqual(random_string, g.read()) def test_small_chunks(self): self.files = 0 self.chunks = 0 def helper(data): f = GridIn(self.db.fs, chunkSize=1) f.write(data) f.close() self.files += 1 self.chunks += len(data) self.assertEqual(self.files, self.db.fs.files.count_documents({})) self.assertEqual(self.chunks, self.db.fs.chunks.count_documents({})) g = GridOut(self.db.fs, f._id) self.assertEqual(data, g.read()) g = GridOut(self.db.fs, f._id) self.assertEqual(data, g.read(10) + g.read(10)) return True qcheck.check_unittest(self, helper, qcheck.gen_string(qcheck.gen_range(0, 20))) def test_seek(self): f = GridIn(self.db.fs, chunkSize=3) f.write(b"hello world") f.close() g = GridOut(self.db.fs, f._id) self.assertEqual(b"hello world", g.read()) g.seek(0) self.assertEqual(b"hello world", g.read()) g.seek(1) self.assertEqual(b"ello world", g.read()) self.assertRaises(IOError, g.seek, -1) g.seek(-3, _SEEK_END) self.assertEqual(b"rld", g.read()) g.seek(0, _SEEK_END) self.assertEqual(b"", g.read()) self.assertRaises(IOError, g.seek, -100, _SEEK_END) g.seek(3) g.seek(3, _SEEK_CUR) self.assertEqual(b"world", g.read()) self.assertRaises(IOError, g.seek, -100, _SEEK_CUR) def test_tell(self): f = GridIn(self.db.fs, chunkSize=3) f.write(b"hello world") f.close() g = GridOut(self.db.fs, f._id) self.assertEqual(0, g.tell()) g.read(0) self.assertEqual(0, g.tell()) g.read(1) self.assertEqual(1, g.tell()) g.read(2) self.assertEqual(3, g.tell()) g.read() self.assertEqual(g.length, g.tell()) def test_multiple_reads(self): f = GridIn(self.db.fs, chunkSize=3) f.write(b"hello world") f.close() g = GridOut(self.db.fs, f._id) self.assertEqual(b"he", g.read(2)) self.assertEqual(b"ll", g.read(2)) self.assertEqual(b"o ", g.read(2)) self.assertEqual(b"wo", g.read(2)) self.assertEqual(b"rl", g.read(2)) self.assertEqual(b"d", g.read(2)) self.assertEqual(b"", g.read(2)) def test_readline(self): f = GridIn(self.db.fs, chunkSize=5) f.write( b"""Hello world, How are you? Hope all is well. Bye""" ) f.close() # Try read(), then readline(). g = GridOut(self.db.fs, f._id) self.assertEqual(b"H", g.read(1)) self.assertEqual(b"ello world,\n", g.readline()) self.assertEqual(b"How a", g.readline(5)) self.assertEqual(b"", g.readline(0)) self.assertEqual(b"re you?\n", g.readline()) self.assertEqual(b"Hope all is well.\n", g.readline(1000)) self.assertEqual(b"Bye", g.readline()) self.assertEqual(b"", g.readline()) # Try readline() first, then read(). g = GridOut(self.db.fs, f._id) self.assertEqual(b"He", g.readline(2)) self.assertEqual(b"l", g.read(1)) self.assertEqual(b"lo", g.readline(2)) self.assertEqual(b" world,\n", g.readline()) # Only readline(). g = GridOut(self.db.fs, f._id) self.assertEqual(b"H", g.readline(1)) self.assertEqual(b"e", g.readline(1)) self.assertEqual(b"llo world,\n", g.readline()) def test_readlines(self): f = GridIn(self.db.fs, chunkSize=5) f.write( b"""Hello world, How are you? Hope all is well. Bye""" ) f.close() # Try read(), then readlines(). g = GridOut(self.db.fs, f._id) self.assertEqual(b"He", g.read(2)) self.assertEqual([b"llo world,\n", b"How are you?\n"], g.readlines(11)) self.assertEqual([b"Hope all is well.\n", b"Bye"], g.readlines()) self.assertEqual([], g.readlines()) # Try readline(), then readlines(). g = GridOut(self.db.fs, f._id) self.assertEqual(b"Hello world,\n", g.readline()) self.assertEqual([b"How are you?\n", b"Hope all is well.\n"], g.readlines(13)) self.assertEqual(b"Bye", g.readline()) self.assertEqual([], g.readlines()) # Only readlines(). g = GridOut(self.db.fs, f._id) self.assertEqual( [b"Hello world,\n", b"How are you?\n", b"Hope all is well.\n", b"Bye"], g.readlines() ) g = GridOut(self.db.fs, f._id) self.assertEqual( [b"Hello world,\n", b"How are you?\n", b"Hope all is well.\n", b"Bye"], g.readlines(0) ) g = GridOut(self.db.fs, f._id) self.assertEqual([b"Hello world,\n"], g.readlines(1)) self.assertEqual([b"How are you?\n"], g.readlines(12)) self.assertEqual([b"Hope all is well.\n", b"Bye"], g.readlines(18)) # Try readlines() first, then read(). g = GridOut(self.db.fs, f._id) self.assertEqual([b"Hello world,\n"], g.readlines(1)) self.assertEqual(b"H", g.read(1)) self.assertEqual([b"ow are you?\n", b"Hope all is well.\n"], g.readlines(29)) self.assertEqual([b"Bye"], g.readlines(1)) # Try readlines() first, then readline(). g = GridOut(self.db.fs, f._id) self.assertEqual([b"Hello world,\n"], g.readlines(1)) self.assertEqual(b"How are you?\n", g.readline()) self.assertEqual([b"Hope all is well.\n"], g.readlines(17)) self.assertEqual(b"Bye", g.readline()) def test_iterator(self): f = GridIn(self.db.fs) f.close() g = GridOut(self.db.fs, f._id) self.assertEqual([], list(g)) f = GridIn(self.db.fs) f.write(b"hello world\nhere are\nsome lines.") f.close() g = GridOut(self.db.fs, f._id) self.assertEqual([b"hello world\n", b"here are\n", b"some lines."], list(g)) self.assertEqual(b"", g.read(5)) self.assertEqual([], list(g)) g = GridOut(self.db.fs, f._id) self.assertEqual(b"hello world\n", next(iter(g))) self.assertEqual(b"here", g.read(4)) self.assertEqual(b" are\n", next(iter(g))) self.assertEqual(b"some lines", g.read(10)) self.assertEqual(b".", next(iter(g))) self.assertRaises(StopIteration, iter(g).__next__) f = GridIn(self.db.fs, chunk_size=2) f.write(b"hello world") f.close() g = GridOut(self.db.fs, f._id) self.assertEqual([b"hello world"], list(g)) def test_read_unaligned_buffer_size(self): in_data = b"This is a text that doesn't quite fit in a single 16-byte chunk." f = GridIn(self.db.fs, chunkSize=16) f.write(in_data) f.close() g = GridOut(self.db.fs, f._id) out_data = b"" while 1: s = g.read(13) if not s: break out_data += s self.assertEqual(in_data, out_data) def test_readchunk(self): in_data = b"a" * 10 f = GridIn(self.db.fs, chunkSize=3) f.write(in_data) f.close() g = GridOut(self.db.fs, f._id) self.assertEqual(3, len(g.readchunk())) self.assertEqual(2, len(g.read(2))) self.assertEqual(1, len(g.readchunk())) self.assertEqual(3, len(g.read(3))) self.assertEqual(1, len(g.readchunk())) self.assertEqual(0, len(g.readchunk())) def test_write_unicode(self): f = GridIn(self.db.fs) self.assertRaises(TypeError, f.write, "foo") f = GridIn(self.db.fs, encoding="utf-8") f.write("foo") f.close() g = GridOut(self.db.fs, f._id) self.assertEqual(b"foo", g.read()) f = GridIn(self.db.fs, encoding="iso-8859-1") f.write("aé") f.close() g = GridOut(self.db.fs, f._id) self.assertEqual("aé".encode("iso-8859-1"), g.read()) def test_set_after_close(self): f = GridIn(self.db.fs, _id="foo", bar="baz") self.assertEqual("foo", f._id) self.assertEqual("baz", f.bar) self.assertRaises(AttributeError, getattr, f, "baz") self.assertRaises(AttributeError, getattr, f, "uploadDate") self.assertRaises(AttributeError, setattr, f, "_id", 5) f.bar = "foo" f.baz = 5 self.assertEqual("foo", f._id) self.assertEqual("foo", f.bar) self.assertEqual(5, f.baz) self.assertRaises(AttributeError, getattr, f, "uploadDate") f.close() self.assertEqual("foo", f._id) self.assertEqual("foo", f.bar) self.assertEqual(5, f.baz) self.assertTrue(f.uploadDate) self.assertRaises(AttributeError, setattr, f, "_id", 5) f.bar = "a" f.baz = "b" self.assertRaises(AttributeError, setattr, f, "upload_date", 5) g = GridOut(self.db.fs, f._id) self.assertEqual("a", g.bar) self.assertEqual("b", g.baz) # Versions 2.0.1 and older saved a _closed field for some reason. self.assertRaises(AttributeError, getattr, g, "_closed") def test_context_manager(self): contents = b"Imagine this is some important data..." with GridIn(self.db.fs, filename="important") as infile: infile.write(contents) with GridOut(self.db.fs, infile._id) as outfile: self.assertEqual(contents, outfile.read()) def test_exception_file_non_existence(self): contents = b"Imagine this is some important data..." with self.assertRaises(ConnectionError): with GridIn(self.db.fs, filename="important") as infile: infile.write(contents) raise ConnectionError("Test exception") # Expectation: File chunks are written, entry in files doesn't appear. self.assertEqual( self.db.fs.chunks.count_documents({"files_id": infile._id}), infile._chunk_number ) self.assertIsNone(self.db.fs.files.find_one({"_id": infile._id})) self.assertTrue(infile.closed) def test_prechunked_string(self): def write_me(s, chunk_size): buf = BytesIO(s) infile = GridIn(self.db.fs) while True: to_write = buf.read(chunk_size) if to_write == b"": break infile.write(to_write) infile.close() buf.close() outfile = GridOut(self.db.fs, infile._id) data = outfile.read() self.assertEqual(s, data) s = b"x" * DEFAULT_CHUNK_SIZE * 4 # Test with default chunk size write_me(s, DEFAULT_CHUNK_SIZE) # Multiple write_me(s, DEFAULT_CHUNK_SIZE * 3) # Custom write_me(s, 262300) def test_grid_out_lazy_connect(self): fs = self.db.fs outfile = GridOut(fs, file_id=-1) self.assertRaises(NoFile, outfile.read) self.assertRaises(NoFile, getattr, outfile, "filename") infile = GridIn(fs, filename=1) infile.close() outfile = GridOut(fs, infile._id) outfile.read() outfile.filename outfile = GridOut(fs, infile._id) outfile.readchunk() def test_grid_in_lazy_connect(self): client = MongoClient("badhost", connect=False, serverSelectionTimeoutMS=10) fs = client.db.fs infile = GridIn(fs, file_id=-1, chunk_size=1) self.assertRaises(ServerSelectionTimeoutError, infile.write, b"data") self.assertRaises(ServerSelectionTimeoutError, infile.close) def test_unacknowledged(self): # w=0 is prohibited. with self.assertRaises(ConfigurationError): GridIn(rs_or_single_client(w=0).pymongo_test.fs) def test_survive_cursor_not_found(self): # By default the find command returns 101 documents in the first batch. # Use 102 batches to cause a single getMore. chunk_size = 1024 data = b"d" * (102 * chunk_size) listener = EventListener() client = rs_or_single_client(event_listeners=[listener]) db = client.pymongo_test with GridIn(db.fs, chunk_size=chunk_size) as infile: infile.write(data) with GridOut(db.fs, infile._id) as outfile: self.assertEqual(len(outfile.readchunk()), chunk_size) # Kill the cursor to simulate the cursor timing out on the server # when an application spends a long time between two calls to # readchunk(). assert client.address is not None client._close_cursor_now( outfile._GridOut__chunk_iter._cursor.cursor_id, _CursorAddress(client.address, db.fs.chunks.full_name), ) # Read the rest of the file without error. self.assertEqual(len(outfile.read()), len(data) - chunk_size) # Paranoid, ensure that a getMore was actually sent. self.assertIn("getMore", listener.started_command_names()) def test_zip(self): zf = BytesIO() z = zipfile.ZipFile(zf, "w") z.writestr("test.txt", b"hello world") z.close() zf.seek(0) f = GridIn(self.db.fs, filename="test.zip") f.write(zf) f.close() self.assertEqual(1, self.db.fs.files.count_documents({})) self.assertEqual(1, self.db.fs.chunks.count_documents({})) g = GridOut(self.db.fs, f._id) z = zipfile.ZipFile(g) self.assertSequenceEqual(z.namelist(), ["test.txt"]) self.assertEqual(z.read("test.txt"), b"hello world") def test_grid_out_unsupported_operations(self): f = GridIn(self.db.fs, chunkSize=3) f.write(b"hello world") f.close() g = GridOut(self.db.fs, f._id) self.assertRaises(io.UnsupportedOperation, g.writelines, [b"some", b"lines"]) self.assertRaises(io.UnsupportedOperation, g.write, b"some text") self.assertRaises(io.UnsupportedOperation, g.fileno) self.assertRaises(io.UnsupportedOperation, g.truncate) self.assertFalse(g.writable()) self.assertFalse(g.isatty()) if __name__ == "__main__": unittest.main() mongodb-mongo-python-driver-509e9b7/test/test_gridfs.py000066400000000000000000000477531462766011000233230ustar00rootroot00000000000000# # Copyright 2009-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. """Tests for the gridfs package.""" from __future__ import annotations import datetime import sys import threading import time from io import BytesIO from unittest.mock import patch sys.path[0:0] = [""] from test import IntegrationTest, client_context, unittest from test.utils import joinall, one, rs_client, rs_or_single_client, single_client import gridfs from bson.binary import Binary from gridfs.errors import CorruptGridFile, FileExists, NoFile from gridfs.grid_file import DEFAULT_CHUNK_SIZE, GridOutCursor from pymongo.database import Database from pymongo.errors import ( ConfigurationError, NotPrimaryError, ServerSelectionTimeoutError, ) from pymongo.mongo_client import MongoClient from pymongo.read_preferences import ReadPreference class JustWrite(threading.Thread): def __init__(self, fs, n): threading.Thread.__init__(self) self.fs = fs self.n = n self.daemon = True def run(self): for _ in range(self.n): file = self.fs.new_file(filename="test") file.write(b"hello") file.close() class JustRead(threading.Thread): def __init__(self, fs, n, results): threading.Thread.__init__(self) self.fs = fs self.n = n self.results = results self.daemon = True def run(self): for _ in range(self.n): file = self.fs.get("test") data = file.read() self.results.append(data) assert data == b"hello" class TestGridfsNoConnect(unittest.TestCase): db: Database @classmethod def setUpClass(cls): cls.db = MongoClient(connect=False).pymongo_test def test_gridfs(self): self.assertRaises(TypeError, gridfs.GridFS, "foo") self.assertRaises(TypeError, gridfs.GridFS, self.db, 5) class TestGridfs(IntegrationTest): fs: gridfs.GridFS alt: gridfs.GridFS @classmethod def setUpClass(cls): super().setUpClass() cls.fs = gridfs.GridFS(cls.db) cls.alt = gridfs.GridFS(cls.db, "alt") def setUp(self): self.cleanup_colls( self.db.fs.files, self.db.fs.chunks, self.db.alt.files, self.db.alt.chunks ) def test_basic(self): oid = self.fs.put(b"hello world") self.assertEqual(b"hello world", self.fs.get(oid).read()) self.assertEqual(1, self.db.fs.files.count_documents({})) self.assertEqual(1, self.db.fs.chunks.count_documents({})) self.fs.delete(oid) self.assertRaises(NoFile, self.fs.get, oid) self.assertEqual(0, self.db.fs.files.count_documents({})) self.assertEqual(0, self.db.fs.chunks.count_documents({})) self.assertRaises(NoFile, self.fs.get, "foo") oid = self.fs.put(b"hello world", _id="foo") self.assertEqual("foo", oid) self.assertEqual(b"hello world", self.fs.get("foo").read()) def test_multi_chunk_delete(self): self.db.fs.drop() self.assertEqual(0, self.db.fs.files.count_documents({})) self.assertEqual(0, self.db.fs.chunks.count_documents({})) gfs = gridfs.GridFS(self.db) oid = gfs.put(b"hello", chunkSize=1) self.assertEqual(1, self.db.fs.files.count_documents({})) self.assertEqual(5, self.db.fs.chunks.count_documents({})) gfs.delete(oid) self.assertEqual(0, self.db.fs.files.count_documents({})) self.assertEqual(0, self.db.fs.chunks.count_documents({})) def test_list(self): self.assertEqual([], self.fs.list()) self.fs.put(b"hello world") self.assertEqual([], self.fs.list()) # PYTHON-598: in server versions before 2.5.x, creating an index on # filename, uploadDate causes list() to include None. self.fs.get_last_version() self.assertEqual([], self.fs.list()) self.fs.put(b"", filename="mike") self.fs.put(b"foo", filename="test") self.fs.put(b"", filename="hello world") self.assertEqual({"mike", "test", "hello world"}, set(self.fs.list())) def test_empty_file(self): oid = self.fs.put(b"") self.assertEqual(b"", self.fs.get(oid).read()) self.assertEqual(1, self.db.fs.files.count_documents({})) self.assertEqual(0, self.db.fs.chunks.count_documents({})) raw = self.db.fs.files.find_one() assert raw is not None self.assertEqual(0, raw["length"]) self.assertEqual(oid, raw["_id"]) self.assertTrue(isinstance(raw["uploadDate"], datetime.datetime)) self.assertEqual(255 * 1024, raw["chunkSize"]) self.assertNotIn("md5", raw) def test_corrupt_chunk(self): files_id = self.fs.put(b"foobar") self.db.fs.chunks.update_one({"files_id": files_id}, {"$set": {"data": Binary(b"foo", 0)}}) try: out = self.fs.get(files_id) self.assertRaises(CorruptGridFile, out.read) out = self.fs.get(files_id) self.assertRaises(CorruptGridFile, out.readline) finally: self.fs.delete(files_id) def test_put_ensures_index(self): chunks = self.db.fs.chunks files = self.db.fs.files # Ensure the collections are removed. chunks.drop() files.drop() self.fs.put(b"junk") self.assertTrue( any( info.get("key") == [("files_id", 1), ("n", 1)] for info in chunks.index_information().values() ) ) self.assertTrue( any( info.get("key") == [("filename", 1), ("uploadDate", 1)] for info in files.index_information().values() ) ) def test_alt_collection(self): oid = self.alt.put(b"hello world") self.assertEqual(b"hello world", self.alt.get(oid).read()) self.assertEqual(1, self.db.alt.files.count_documents({})) self.assertEqual(1, self.db.alt.chunks.count_documents({})) self.alt.delete(oid) self.assertRaises(NoFile, self.alt.get, oid) self.assertEqual(0, self.db.alt.files.count_documents({})) self.assertEqual(0, self.db.alt.chunks.count_documents({})) self.assertRaises(NoFile, self.alt.get, "foo") oid = self.alt.put(b"hello world", _id="foo") self.assertEqual("foo", oid) self.assertEqual(b"hello world", self.alt.get("foo").read()) self.alt.put(b"", filename="mike") self.alt.put(b"foo", filename="test") self.alt.put(b"", filename="hello world") self.assertEqual({"mike", "test", "hello world"}, set(self.alt.list())) def test_threaded_reads(self): self.fs.put(b"hello", _id="test") threads = [] results: list = [] for i in range(10): threads.append(JustRead(self.fs, 10, results)) threads[i].start() joinall(threads) self.assertEqual(100 * [b"hello"], results) def test_threaded_writes(self): threads = [] for i in range(10): threads.append(JustWrite(self.fs, 10)) threads[i].start() joinall(threads) f = self.fs.get_last_version("test") self.assertEqual(f.read(), b"hello") # Should have created 100 versions of 'test' file self.assertEqual(100, self.db.fs.files.count_documents({"filename": "test"})) def test_get_last_version(self): one = self.fs.put(b"foo", filename="test") time.sleep(0.01) two = self.fs.new_file(filename="test") two.write(b"bar") two.close() time.sleep(0.01) two = two._id three = self.fs.put(b"baz", filename="test") self.assertEqual(b"baz", self.fs.get_last_version("test").read()) self.fs.delete(three) self.assertEqual(b"bar", self.fs.get_last_version("test").read()) self.fs.delete(two) self.assertEqual(b"foo", self.fs.get_last_version("test").read()) self.fs.delete(one) self.assertRaises(NoFile, self.fs.get_last_version, "test") def test_get_last_version_with_metadata(self): one = self.fs.put(b"foo", filename="test", author="author") time.sleep(0.01) two = self.fs.put(b"bar", filename="test", author="author") self.assertEqual(b"bar", self.fs.get_last_version(author="author").read()) self.fs.delete(two) self.assertEqual(b"foo", self.fs.get_last_version(author="author").read()) self.fs.delete(one) one = self.fs.put(b"foo", filename="test", author="author1") time.sleep(0.01) two = self.fs.put(b"bar", filename="test", author="author2") self.assertEqual(b"foo", self.fs.get_last_version(author="author1").read()) self.assertEqual(b"bar", self.fs.get_last_version(author="author2").read()) self.assertEqual(b"bar", self.fs.get_last_version(filename="test").read()) self.assertRaises(NoFile, self.fs.get_last_version, author="author3") self.assertRaises(NoFile, self.fs.get_last_version, filename="nottest", author="author1") self.fs.delete(one) self.fs.delete(two) def test_get_version(self): self.fs.put(b"foo", filename="test") time.sleep(0.01) self.fs.put(b"bar", filename="test") time.sleep(0.01) self.fs.put(b"baz", filename="test") time.sleep(0.01) self.assertEqual(b"foo", self.fs.get_version("test", 0).read()) self.assertEqual(b"bar", self.fs.get_version("test", 1).read()) self.assertEqual(b"baz", self.fs.get_version("test", 2).read()) self.assertEqual(b"baz", self.fs.get_version("test", -1).read()) self.assertEqual(b"bar", self.fs.get_version("test", -2).read()) self.assertEqual(b"foo", self.fs.get_version("test", -3).read()) self.assertRaises(NoFile, self.fs.get_version, "test", 3) self.assertRaises(NoFile, self.fs.get_version, "test", -4) def test_get_version_with_metadata(self): one = self.fs.put(b"foo", filename="test", author="author1") time.sleep(0.01) two = self.fs.put(b"bar", filename="test", author="author1") time.sleep(0.01) three = self.fs.put(b"baz", filename="test", author="author2") self.assertEqual( b"foo", self.fs.get_version(filename="test", author="author1", version=-2).read() ) self.assertEqual( b"bar", self.fs.get_version(filename="test", author="author1", version=-1).read() ) self.assertEqual( b"foo", self.fs.get_version(filename="test", author="author1", version=0).read() ) self.assertEqual( b"bar", self.fs.get_version(filename="test", author="author1", version=1).read() ) self.assertEqual( b"baz", self.fs.get_version(filename="test", author="author2", version=0).read() ) self.assertEqual(b"baz", self.fs.get_version(filename="test", version=-1).read()) self.assertEqual(b"baz", self.fs.get_version(filename="test", version=2).read()) self.assertRaises(NoFile, self.fs.get_version, filename="test", author="author3") self.assertRaises(NoFile, self.fs.get_version, filename="test", author="author1", version=2) self.fs.delete(one) self.fs.delete(two) self.fs.delete(three) def test_put_filelike(self): oid = self.fs.put(BytesIO(b"hello world"), chunk_size=1) self.assertEqual(11, self.db.fs.chunks.count_documents({})) self.assertEqual(b"hello world", self.fs.get(oid).read()) def test_file_exists(self): oid = self.fs.put(b"hello") self.assertRaises(FileExists, self.fs.put, b"world", _id=oid) one = self.fs.new_file(_id=123) one.write(b"some content") one.close() # Attempt to upload a file with more chunks to the same _id. with patch("gridfs.grid_file._UPLOAD_BUFFER_SIZE", DEFAULT_CHUNK_SIZE): two = self.fs.new_file(_id=123) self.assertRaises(FileExists, two.write, b"x" * DEFAULT_CHUNK_SIZE * 3) # Original file is still readable (no extra chunks were uploaded). self.assertEqual(self.fs.get(123).read(), b"some content") two = self.fs.new_file(_id=123) two.write(b"some content") self.assertRaises(FileExists, two.close) # Original file is still readable. self.assertEqual(self.fs.get(123).read(), b"some content") def test_exists(self): oid = self.fs.put(b"hello") self.assertTrue(self.fs.exists(oid)) self.assertTrue(self.fs.exists({"_id": oid})) self.assertTrue(self.fs.exists(_id=oid)) self.assertFalse(self.fs.exists(filename="mike")) self.assertFalse(self.fs.exists("mike")) oid = self.fs.put(b"hello", filename="mike", foo=12) self.assertTrue(self.fs.exists(oid)) self.assertTrue(self.fs.exists({"_id": oid})) self.assertTrue(self.fs.exists(_id=oid)) self.assertTrue(self.fs.exists(filename="mike")) self.assertTrue(self.fs.exists({"filename": "mike"})) self.assertTrue(self.fs.exists(foo=12)) self.assertTrue(self.fs.exists({"foo": 12})) self.assertTrue(self.fs.exists(foo={"$gt": 11})) self.assertTrue(self.fs.exists({"foo": {"$gt": 11}})) self.assertFalse(self.fs.exists(foo=13)) self.assertFalse(self.fs.exists({"foo": 13})) self.assertFalse(self.fs.exists(foo={"$gt": 12})) self.assertFalse(self.fs.exists({"foo": {"$gt": 12}})) def test_put_unicode(self): self.assertRaises(TypeError, self.fs.put, "hello") oid = self.fs.put("hello", encoding="utf-8") self.assertEqual(b"hello", self.fs.get(oid).read()) self.assertEqual("utf-8", self.fs.get(oid).encoding) oid = self.fs.put("aé", encoding="iso-8859-1") self.assertEqual("aé".encode("iso-8859-1"), self.fs.get(oid).read()) self.assertEqual("iso-8859-1", self.fs.get(oid).encoding) def test_missing_length_iter(self): # Test fix that guards against PHP-237 self.fs.put(b"", filename="empty") doc = self.db.fs.files.find_one({"filename": "empty"}) assert doc is not None doc.pop("length") self.db.fs.files.replace_one({"_id": doc["_id"]}, doc) f = self.fs.get_last_version(filename="empty") def iterate_file(grid_file): for _chunk in grid_file: pass return True self.assertTrue(iterate_file(f)) def test_gridfs_lazy_connect(self): client = MongoClient("badhost", connect=False, serverSelectionTimeoutMS=10) db = client.db gfs = gridfs.GridFS(db) self.assertRaises(ServerSelectionTimeoutError, gfs.list) fs = gridfs.GridFS(db) f = fs.new_file() self.assertRaises(ServerSelectionTimeoutError, f.close) def test_gridfs_find(self): self.fs.put(b"test2", filename="two") time.sleep(0.01) self.fs.put(b"test2+", filename="two") time.sleep(0.01) self.fs.put(b"test1", filename="one") time.sleep(0.01) self.fs.put(b"test2++", filename="two") files = self.db.fs.files self.assertEqual(3, files.count_documents({"filename": "two"})) self.assertEqual(4, files.count_documents({})) cursor = self.fs.find(no_cursor_timeout=False).sort("uploadDate", -1).skip(1).limit(2) gout = next(cursor) self.assertEqual(b"test1", gout.read()) cursor.rewind() gout = next(cursor) self.assertEqual(b"test1", gout.read()) gout = next(cursor) self.assertEqual(b"test2+", gout.read()) self.assertRaises(StopIteration, cursor.__next__) cursor.close() self.assertRaises(TypeError, self.fs.find, {}, {"_id": True}) def test_delete_not_initialized(self): # Creating a cursor with invalid arguments will not run __init__ # but will still call __del__. cursor = GridOutCursor.__new__(GridOutCursor) # Skip calling __init__ with self.assertRaises(TypeError): cursor.__init__(self.db.fs.files, {}, {"_id": True}) # type: ignore cursor.__del__() # no error def test_gridfs_find_one(self): self.assertEqual(None, self.fs.find_one()) id1 = self.fs.put(b"test1", filename="file1") res = self.fs.find_one() assert res is not None self.assertEqual(b"test1", res.read()) id2 = self.fs.put(b"test2", filename="file2", meta="data") res1 = self.fs.find_one(id1) assert res1 is not None self.assertEqual(b"test1", res1.read()) res2 = self.fs.find_one(id2) assert res2 is not None self.assertEqual(b"test2", res2.read()) res3 = self.fs.find_one({"filename": "file1"}) assert res3 is not None self.assertEqual(b"test1", res3.read()) res4 = self.fs.find_one(id2) assert res4 is not None self.assertEqual("data", res4.meta) def test_grid_in_non_int_chunksize(self): # Lua, and perhaps other buggy GridFS clients, store size as a float. data = b"data" self.fs.put(data, filename="f") self.db.fs.files.update_one({"filename": "f"}, {"$set": {"chunkSize": 100.0}}) self.assertEqual(data, self.fs.get_version("f").read()) def test_unacknowledged(self): # w=0 is prohibited. with self.assertRaises(ConfigurationError): gridfs.GridFS(rs_or_single_client(w=0).pymongo_test) def test_md5(self): gin = self.fs.new_file() gin.write(b"no md5 sum") gin.close() self.assertIsNone(gin.md5) gout = self.fs.get(gin._id) self.assertIsNone(gout.md5) _id = self.fs.put(b"still no md5 sum") gout = self.fs.get(_id) self.assertIsNone(gout.md5) class TestGridfsReplicaSet(IntegrationTest): @classmethod @client_context.require_secondaries_count(1) def setUpClass(cls): super().setUpClass() @classmethod def tearDownClass(cls): client_context.client.drop_database("gfsreplica") def test_gridfs_replica_set(self): rsc = rs_client(w=client_context.w, read_preference=ReadPreference.SECONDARY) fs = gridfs.GridFS(rsc.gfsreplica, "gfsreplicatest") gin = fs.new_file() self.assertEqual(gin._coll.read_preference, ReadPreference.PRIMARY) oid = fs.put(b"foo") content = fs.get(oid).read() self.assertEqual(b"foo", content) def test_gridfs_secondary(self): secondary_host, secondary_port = one(self.client.secondaries) secondary_connection = single_client( secondary_host, secondary_port, read_preference=ReadPreference.SECONDARY ) # Should detect it's connected to secondary and not attempt to # create index fs = gridfs.GridFS(secondary_connection.gfsreplica, "gfssecondarytest") # This won't detect secondary, raises error self.assertRaises(NotPrimaryError, fs.put, b"foo") def test_gridfs_secondary_lazy(self): # Should detect it's connected to secondary and not attempt to # create index. secondary_host, secondary_port = one(self.client.secondaries) client = single_client( secondary_host, secondary_port, read_preference=ReadPreference.SECONDARY, connect=False ) # Still no connection. fs = gridfs.GridFS(client.gfsreplica, "gfssecondarylazytest") # Connects, doesn't create index. self.assertRaises(NoFile, fs.get_last_version) self.assertRaises(NotPrimaryError, fs.put, "data", encoding="utf-8") if __name__ == "__main__": unittest.main() mongodb-mongo-python-driver-509e9b7/test/test_gridfs_bucket.py000066400000000000000000000500661462766011000246470ustar00rootroot00000000000000# # Copyright 2015-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. """Tests for the gridfs package.""" from __future__ import annotations import datetime import itertools import sys import threading import time from io import BytesIO from unittest.mock import patch sys.path[0:0] = [""] from test import IntegrationTest, client_context, unittest from test.utils import joinall, one, rs_client, rs_or_single_client, single_client import gridfs from bson.binary import Binary from bson.int64 import Int64 from bson.objectid import ObjectId from bson.son import SON from gridfs.errors import CorruptGridFile, NoFile from pymongo.errors import ( ConfigurationError, NotPrimaryError, ServerSelectionTimeoutError, WriteConcernError, ) from pymongo.mongo_client import MongoClient from pymongo.read_preferences import ReadPreference class JustWrite(threading.Thread): def __init__(self, gfs, num): threading.Thread.__init__(self) self.gfs = gfs self.num = num self.daemon = True def run(self): for _ in range(self.num): file = self.gfs.open_upload_stream("test") file.write(b"hello") file.close() class JustRead(threading.Thread): def __init__(self, gfs, num, results): threading.Thread.__init__(self) self.gfs = gfs self.num = num self.results = results self.daemon = True def run(self): for _ in range(self.num): file = self.gfs.open_download_stream_by_name("test") data = file.read() self.results.append(data) assert data == b"hello" class TestGridfs(IntegrationTest): fs: gridfs.GridFSBucket alt: gridfs.GridFSBucket @classmethod def setUpClass(cls): super().setUpClass() cls.fs = gridfs.GridFSBucket(cls.db) cls.alt = gridfs.GridFSBucket(cls.db, bucket_name="alt") def setUp(self): self.cleanup_colls( self.db.fs.files, self.db.fs.chunks, self.db.alt.files, self.db.alt.chunks ) def test_basic(self): oid = self.fs.upload_from_stream("test_filename", b"hello world") self.assertEqual(b"hello world", self.fs.open_download_stream(oid).read()) self.assertEqual(1, self.db.fs.files.count_documents({})) self.assertEqual(1, self.db.fs.chunks.count_documents({})) self.fs.delete(oid) self.assertRaises(NoFile, self.fs.open_download_stream, oid) self.assertEqual(0, self.db.fs.files.count_documents({})) self.assertEqual(0, self.db.fs.chunks.count_documents({})) def test_multi_chunk_delete(self): self.assertEqual(0, self.db.fs.files.count_documents({})) self.assertEqual(0, self.db.fs.chunks.count_documents({})) gfs = gridfs.GridFSBucket(self.db) oid = gfs.upload_from_stream("test_filename", b"hello", chunk_size_bytes=1) self.assertEqual(1, self.db.fs.files.count_documents({})) self.assertEqual(5, self.db.fs.chunks.count_documents({})) gfs.delete(oid) self.assertEqual(0, self.db.fs.files.count_documents({})) self.assertEqual(0, self.db.fs.chunks.count_documents({})) def test_empty_file(self): oid = self.fs.upload_from_stream("test_filename", b"") self.assertEqual(b"", self.fs.open_download_stream(oid).read()) self.assertEqual(1, self.db.fs.files.count_documents({})) self.assertEqual(0, self.db.fs.chunks.count_documents({})) raw = self.db.fs.files.find_one() assert raw is not None self.assertEqual(0, raw["length"]) self.assertEqual(oid, raw["_id"]) self.assertTrue(isinstance(raw["uploadDate"], datetime.datetime)) self.assertEqual(255 * 1024, raw["chunkSize"]) self.assertNotIn("md5", raw) def test_corrupt_chunk(self): files_id = self.fs.upload_from_stream("test_filename", b"foobar") self.db.fs.chunks.update_one({"files_id": files_id}, {"$set": {"data": Binary(b"foo", 0)}}) try: out = self.fs.open_download_stream(files_id) self.assertRaises(CorruptGridFile, out.read) out = self.fs.open_download_stream(files_id) self.assertRaises(CorruptGridFile, out.readline) finally: self.fs.delete(files_id) def test_upload_ensures_index(self): chunks = self.db.fs.chunks files = self.db.fs.files # Ensure the collections are removed. chunks.drop() files.drop() self.fs.upload_from_stream("filename", b"junk") self.assertTrue( any( info.get("key") == [("files_id", 1), ("n", 1)] for info in chunks.index_information().values() ) ) self.assertTrue( any( info.get("key") == [("filename", 1), ("uploadDate", 1)] for info in files.index_information().values() ) ) def test_ensure_index_shell_compat(self): files = self.db.fs.files for i, j in itertools.combinations_with_replacement([1, 1.0, Int64(1)], 2): # Create the index with different numeric types (as might be done # from the mongo shell). shell_index = [("filename", i), ("uploadDate", j)] self.db.command( "createIndexes", files.name, indexes=[{"key": SON(shell_index), "name": "filename_1.0_uploadDate_1.0"}], ) # No error. self.fs.upload_from_stream("filename", b"data") self.assertTrue( any( info.get("key") == [("filename", 1), ("uploadDate", 1)] for info in files.index_information().values() ) ) files.drop() def test_alt_collection(self): oid = self.alt.upload_from_stream("test_filename", b"hello world") self.assertEqual(b"hello world", self.alt.open_download_stream(oid).read()) self.assertEqual(1, self.db.alt.files.count_documents({})) self.assertEqual(1, self.db.alt.chunks.count_documents({})) self.alt.delete(oid) self.assertRaises(NoFile, self.alt.open_download_stream, oid) self.assertEqual(0, self.db.alt.files.count_documents({})) self.assertEqual(0, self.db.alt.chunks.count_documents({})) self.assertRaises(NoFile, self.alt.open_download_stream, "foo") self.alt.upload_from_stream("foo", b"hello world") self.assertEqual(b"hello world", self.alt.open_download_stream_by_name("foo").read()) self.alt.upload_from_stream("mike", b"") self.alt.upload_from_stream("test", b"foo") self.alt.upload_from_stream("hello world", b"") self.assertEqual( {"mike", "test", "hello world", "foo"}, {k["filename"] for k in list(self.db.alt.files.find())}, ) def test_threaded_reads(self): self.fs.upload_from_stream("test", b"hello") threads = [] results: list = [] for i in range(10): threads.append(JustRead(self.fs, 10, results)) threads[i].start() joinall(threads) self.assertEqual(100 * [b"hello"], results) def test_threaded_writes(self): threads = [] for i in range(10): threads.append(JustWrite(self.fs, 10)) threads[i].start() joinall(threads) fstr = self.fs.open_download_stream_by_name("test") self.assertEqual(fstr.read(), b"hello") # Should have created 100 versions of 'test' file self.assertEqual(100, self.db.fs.files.count_documents({"filename": "test"})) def test_get_last_version(self): one = self.fs.upload_from_stream("test", b"foo") time.sleep(0.01) two = self.fs.open_upload_stream("test") two.write(b"bar") two.close() time.sleep(0.01) two = two._id three = self.fs.upload_from_stream("test", b"baz") self.assertEqual(b"baz", self.fs.open_download_stream_by_name("test").read()) self.fs.delete(three) self.assertEqual(b"bar", self.fs.open_download_stream_by_name("test").read()) self.fs.delete(two) self.assertEqual(b"foo", self.fs.open_download_stream_by_name("test").read()) self.fs.delete(one) self.assertRaises(NoFile, self.fs.open_download_stream_by_name, "test") def test_get_version(self): self.fs.upload_from_stream("test", b"foo") time.sleep(0.01) self.fs.upload_from_stream("test", b"bar") time.sleep(0.01) self.fs.upload_from_stream("test", b"baz") time.sleep(0.01) self.assertEqual(b"foo", self.fs.open_download_stream_by_name("test", revision=0).read()) self.assertEqual(b"bar", self.fs.open_download_stream_by_name("test", revision=1).read()) self.assertEqual(b"baz", self.fs.open_download_stream_by_name("test", revision=2).read()) self.assertEqual(b"baz", self.fs.open_download_stream_by_name("test", revision=-1).read()) self.assertEqual(b"bar", self.fs.open_download_stream_by_name("test", revision=-2).read()) self.assertEqual(b"foo", self.fs.open_download_stream_by_name("test", revision=-3).read()) self.assertRaises(NoFile, self.fs.open_download_stream_by_name, "test", revision=3) self.assertRaises(NoFile, self.fs.open_download_stream_by_name, "test", revision=-4) def test_upload_from_stream(self): oid = self.fs.upload_from_stream("test_file", BytesIO(b"hello world"), chunk_size_bytes=1) self.assertEqual(11, self.db.fs.chunks.count_documents({})) self.assertEqual(b"hello world", self.fs.open_download_stream(oid).read()) def test_upload_from_stream_with_id(self): oid = ObjectId() self.fs.upload_from_stream_with_id( oid, "test_file_custom_id", BytesIO(b"custom id"), chunk_size_bytes=1 ) self.assertEqual(b"custom id", self.fs.open_download_stream(oid).read()) @patch("gridfs.grid_file._UPLOAD_BUFFER_CHUNKS", 3) @client_context.require_failCommand_fail_point def test_upload_bulk_write_error(self): # Test BulkWriteError from insert_many is converted to an insert_one style error. expected_wce = { "code": 100, "codeName": "UnsatisfiableWriteConcern", "errmsg": "Not enough data-bearing nodes", } cause_wce = { "configureFailPoint": "failCommand", "mode": {"times": 2}, "data": {"failCommands": ["insert"], "writeConcernError": expected_wce}, } gin = self.fs.open_upload_stream("test_file", chunk_size_bytes=1) with self.fail_point(cause_wce): # Assert we raise WriteConcernError, not BulkWriteError. with self.assertRaises(WriteConcernError): gin.write(b"hello world") # 3 chunks were uploaded. self.assertEqual(3, self.db.fs.chunks.count_documents({"files_id": gin._id})) gin.abort() @patch("gridfs.grid_file._UPLOAD_BUFFER_CHUNKS", 10) def test_upload_batching(self): with self.fs.open_upload_stream("test_file", chunk_size_bytes=1) as gin: gin.write(b"s" * (10 - 1)) # No chunks were uploaded yet. self.assertEqual(0, self.db.fs.chunks.count_documents({"files_id": gin._id})) gin.write(b"s") # All chunks were uploaded since we hit the _UPLOAD_BUFFER_CHUNKS limit. self.assertEqual(10, self.db.fs.chunks.count_documents({"files_id": gin._id})) def test_open_upload_stream(self): gin = self.fs.open_upload_stream("from_stream") gin.write(b"from stream") gin.close() self.assertEqual(b"from stream", self.fs.open_download_stream(gin._id).read()) def test_open_upload_stream_with_id(self): oid = ObjectId() gin = self.fs.open_upload_stream_with_id(oid, "from_stream_custom_id") gin.write(b"from stream with custom id") gin.close() self.assertEqual(b"from stream with custom id", self.fs.open_download_stream(oid).read()) def test_missing_length_iter(self): # Test fix that guards against PHP-237 self.fs.upload_from_stream("empty", b"") doc = self.db.fs.files.find_one({"filename": "empty"}) assert doc is not None doc.pop("length") self.db.fs.files.replace_one({"_id": doc["_id"]}, doc) fstr = self.fs.open_download_stream_by_name("empty") def iterate_file(grid_file): for _ in grid_file: pass return True self.assertTrue(iterate_file(fstr)) def test_gridfs_lazy_connect(self): client = MongoClient("badhost", connect=False, serverSelectionTimeoutMS=0) cdb = client.db gfs = gridfs.GridFSBucket(cdb) self.assertRaises(ServerSelectionTimeoutError, gfs.delete, 0) gfs = gridfs.GridFSBucket(cdb) self.assertRaises( ServerSelectionTimeoutError, gfs.upload_from_stream, "test", b"" ) # Still no connection. def test_gridfs_find(self): self.fs.upload_from_stream("two", b"test2") time.sleep(0.01) self.fs.upload_from_stream("two", b"test2+") time.sleep(0.01) self.fs.upload_from_stream("one", b"test1") time.sleep(0.01) self.fs.upload_from_stream("two", b"test2++") files = self.db.fs.files self.assertEqual(3, files.count_documents({"filename": "two"})) self.assertEqual(4, files.count_documents({})) cursor = self.fs.find( {}, no_cursor_timeout=False, sort=[("uploadDate", -1)], skip=1, limit=2 ) gout = next(cursor) self.assertEqual(b"test1", gout.read()) cursor.rewind() gout = next(cursor) self.assertEqual(b"test1", gout.read()) gout = next(cursor) self.assertEqual(b"test2+", gout.read()) self.assertRaises(StopIteration, cursor.__next__) cursor.close() self.assertRaises(TypeError, self.fs.find, {}, {"_id": True}) def test_grid_in_non_int_chunksize(self): # Lua, and perhaps other buggy GridFS clients, store size as a float. data = b"data" self.fs.upload_from_stream("f", data) self.db.fs.files.update_one({"filename": "f"}, {"$set": {"chunkSize": 100.0}}) self.assertEqual(data, self.fs.open_download_stream_by_name("f").read()) def test_unacknowledged(self): # w=0 is prohibited. with self.assertRaises(ConfigurationError): gridfs.GridFSBucket(rs_or_single_client(w=0).pymongo_test) def test_rename(self): _id = self.fs.upload_from_stream("first_name", b"testing") self.assertEqual(b"testing", self.fs.open_download_stream_by_name("first_name").read()) self.fs.rename(_id, "second_name") self.assertRaises(NoFile, self.fs.open_download_stream_by_name, "first_name") self.assertEqual(b"testing", self.fs.open_download_stream_by_name("second_name").read()) @patch("gridfs.grid_file._UPLOAD_BUFFER_SIZE", 5) def test_abort(self): gin = self.fs.open_upload_stream("test_filename", chunk_size_bytes=5) gin.write(b"test1") gin.write(b"test2") gin.write(b"test3") self.assertEqual(3, self.db.fs.chunks.count_documents({"files_id": gin._id})) gin.abort() self.assertTrue(gin.closed) self.assertRaises(ValueError, gin.write, b"test4") self.assertEqual(0, self.db.fs.chunks.count_documents({"files_id": gin._id})) def test_download_to_stream(self): file1 = BytesIO(b"hello world") # Test with one chunk. oid = self.fs.upload_from_stream("one_chunk", file1) self.assertEqual(1, self.db.fs.chunks.count_documents({})) file2 = BytesIO() self.fs.download_to_stream(oid, file2) file1.seek(0) file2.seek(0) self.assertEqual(file1.read(), file2.read()) # Test with many chunks. self.db.drop_collection("fs.files") self.db.drop_collection("fs.chunks") file1.seek(0) oid = self.fs.upload_from_stream("many_chunks", file1, chunk_size_bytes=1) self.assertEqual(11, self.db.fs.chunks.count_documents({})) file2 = BytesIO() self.fs.download_to_stream(oid, file2) file1.seek(0) file2.seek(0) self.assertEqual(file1.read(), file2.read()) def test_download_to_stream_by_name(self): file1 = BytesIO(b"hello world") # Test with one chunk. _ = self.fs.upload_from_stream("one_chunk", file1) self.assertEqual(1, self.db.fs.chunks.count_documents({})) file2 = BytesIO() self.fs.download_to_stream_by_name("one_chunk", file2) file1.seek(0) file2.seek(0) self.assertEqual(file1.read(), file2.read()) # Test with many chunks. self.db.drop_collection("fs.files") self.db.drop_collection("fs.chunks") file1.seek(0) self.fs.upload_from_stream("many_chunks", file1, chunk_size_bytes=1) self.assertEqual(11, self.db.fs.chunks.count_documents({})) file2 = BytesIO() self.fs.download_to_stream_by_name("many_chunks", file2) file1.seek(0) file2.seek(0) self.assertEqual(file1.read(), file2.read()) def test_md5(self): gin = self.fs.open_upload_stream("no md5") gin.write(b"no md5 sum") gin.close() self.assertIsNone(gin.md5) gout = self.fs.open_download_stream(gin._id) self.assertIsNone(gout.md5) gin = self.fs.open_upload_stream_with_id(ObjectId(), "also no md5") gin.write(b"also no md5 sum") gin.close() self.assertIsNone(gin.md5) gout = self.fs.open_download_stream(gin._id) self.assertIsNone(gout.md5) class TestGridfsBucketReplicaSet(IntegrationTest): @classmethod @client_context.require_secondaries_count(1) def setUpClass(cls): super().setUpClass() @classmethod def tearDownClass(cls): client_context.client.drop_database("gfsbucketreplica") def test_gridfs_replica_set(self): rsc = rs_client(w=client_context.w, read_preference=ReadPreference.SECONDARY) gfs = gridfs.GridFSBucket(rsc.gfsbucketreplica, "gfsbucketreplicatest") oid = gfs.upload_from_stream("test_filename", b"foo") content = gfs.open_download_stream(oid).read() self.assertEqual(b"foo", content) def test_gridfs_secondary(self): secondary_host, secondary_port = one(self.client.secondaries) secondary_connection = single_client( secondary_host, secondary_port, read_preference=ReadPreference.SECONDARY ) # Should detect it's connected to secondary and not attempt to # create index gfs = gridfs.GridFSBucket(secondary_connection.gfsbucketreplica, "gfsbucketsecondarytest") # This won't detect secondary, raises error self.assertRaises(NotPrimaryError, gfs.upload_from_stream, "test_filename", b"foo") def test_gridfs_secondary_lazy(self): # Should detect it's connected to secondary and not attempt to # create index. secondary_host, secondary_port = one(self.client.secondaries) client = single_client( secondary_host, secondary_port, read_preference=ReadPreference.SECONDARY, connect=False ) # Still no connection. gfs = gridfs.GridFSBucket(client.gfsbucketreplica, "gfsbucketsecondarylazytest") # Connects, doesn't create index. self.assertRaises(NoFile, gfs.open_download_stream_by_name, "test_filename") self.assertRaises(NotPrimaryError, gfs.upload_from_stream, "test_filename", b"data") if __name__ == "__main__": unittest.main() mongodb-mongo-python-driver-509e9b7/test/test_gridfs_spec.py000066400000000000000000000020301462766011000243100ustar00rootroot00000000000000# Copyright 2015-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. """Test the GridFS unified spec tests.""" from __future__ import annotations import os import sys sys.path[0:0] = [""] from test import unittest from test.unified_format import generate_test_classes # Location of JSON test specifications. TEST_PATH = os.path.join(os.path.dirname(os.path.realpath(__file__)), "gridfs") # Generate unified tests. globals().update(generate_test_classes(TEST_PATH, module=__name__)) if __name__ == "__main__": unittest.main() mongodb-mongo-python-driver-509e9b7/test/test_heartbeat_monitoring.py000066400000000000000000000067631462766011000262450ustar00rootroot00000000000000# Copyright 2016-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. """Test the monitoring of the server heartbeats.""" from __future__ import annotations import sys sys.path[0:0] = [""] from test import IntegrationTest, client_knobs, unittest from test.utils import HeartbeatEventListener, MockPool, single_client, wait_until from pymongo.errors import ConnectionFailure from pymongo.hello import Hello, HelloCompat from pymongo.monitor import Monitor class TestHeartbeatMonitoring(IntegrationTest): def create_mock_monitor(self, responses, uri, expected_results): listener = HeartbeatEventListener() with client_knobs( heartbeat_frequency=0.1, min_heartbeat_interval=0.1, events_queue_frequency=0.1 ): class MockMonitor(Monitor): def _check_with_socket(self, *args, **kwargs): if isinstance(responses[1], Exception): raise responses[1] return Hello(responses[1]), 99 m = single_client( h=uri, event_listeners=(listener,), _monitor_class=MockMonitor, _pool_class=MockPool ) expected_len = len(expected_results) # Wait for *at least* expected_len number of results. The # monitor thread may run multiple times during the execution # of this test. wait_until(lambda: len(listener.events) >= expected_len, "publish all events") try: # zip gives us len(expected_results) pairs. for expected, actual in zip(expected_results, listener.events): self.assertEqual(expected, actual.__class__.__name__) self.assertEqual(actual.connection_id, responses[0]) if expected != "ServerHeartbeatStartedEvent": if isinstance(actual.reply, Hello): self.assertEqual(actual.duration, 99) self.assertEqual(actual.reply._doc, responses[1]) else: self.assertEqual(actual.reply, responses[1]) finally: m.close() def test_standalone(self): responses = ( ("a", 27017), {HelloCompat.LEGACY_CMD: True, "maxWireVersion": 4, "minWireVersion": 0, "ok": 1}, ) uri = "mongodb://a:27017" expected_results = ["ServerHeartbeatStartedEvent", "ServerHeartbeatSucceededEvent"] self.create_mock_monitor(responses, uri, expected_results) def test_standalone_error(self): responses = (("a", 27017), ConnectionFailure("SPECIAL MESSAGE")) uri = "mongodb://a:27017" # _check_with_socket failing results in a second attempt. expected_results = [ "ServerHeartbeatStartedEvent", "ServerHeartbeatFailedEvent", "ServerHeartbeatStartedEvent", "ServerHeartbeatFailedEvent", ] self.create_mock_monitor(responses, uri, expected_results) if __name__ == "__main__": unittest.main() mongodb-mongo-python-driver-509e9b7/test/test_index_management.py000066400000000000000000000405111462766011000253310ustar00rootroot00000000000000# Copyright 2023-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. """Run the auth spec tests.""" from __future__ import annotations import os import sys import time import uuid from typing import Any, Mapping sys.path[0:0] = [""] from test import IntegrationTest, unittest from test.unified_format import generate_test_classes from test.utils import AllowListEventListener, EventListener from pymongo import MongoClient from pymongo.errors import OperationFailure from pymongo.operations import SearchIndexModel from pymongo.read_concern import ReadConcern from pymongo.write_concern import WriteConcern _TEST_PATH = os.path.join(os.path.dirname(os.path.realpath(__file__)), "index_management") _NAME = "test-search-index" class TestCreateSearchIndex(IntegrationTest): def test_inputs(self): if not os.environ.get("TEST_INDEX_MANAGEMENT"): raise unittest.SkipTest("Skipping index management tests") listener = AllowListEventListener("createSearchIndexes") client = MongoClient(event_listeners=[listener]) self.addCleanup(client.close) coll = client.test.test coll.drop() definition = dict(mappings=dict(dynamic=True)) model_kwarg_list: list[Mapping[str, Any]] = [ dict(definition=definition, name=None), dict(definition=definition, name="test"), ] for model_kwargs in model_kwarg_list: model = SearchIndexModel(**model_kwargs) with self.assertRaises(OperationFailure): coll.create_search_index(model) with self.assertRaises(OperationFailure): coll.create_search_index(model_kwargs) listener.reset() with self.assertRaises(OperationFailure): coll.create_search_index({"definition": definition, "arbitraryOption": 1}) self.assertEqual( {"definition": definition, "arbitraryOption": 1}, listener.events[0].command["indexes"][0], ) listener.reset() with self.assertRaises(OperationFailure): coll.create_search_index({"definition": definition, "type": "search"}) self.assertEqual( {"definition": definition, "type": "search"}, listener.events[0].command["indexes"][0] ) class SearchIndexIntegrationBase(unittest.TestCase): db_name = "test_search_index_base" @classmethod def setUpClass(cls) -> None: super().setUpClass() if not os.environ.get("TEST_INDEX_MANAGEMENT"): raise unittest.SkipTest("Skipping index management tests") url = os.environ.get("MONGODB_URI") username = os.environ["DB_USER"] password = os.environ["DB_PASSWORD"] cls.listener = listener = EventListener() cls.client = MongoClient( url, username=username, password=password, event_listeners=[listener] ) cls.client.drop_database(_NAME) cls.db = cls.client[cls.db_name] @classmethod def tearDownClass(cls): cls.client.drop_database(_NAME) cls.client.close() def wait_for_ready(self, coll, name=_NAME, predicate=None): """Wait for a search index to be ready.""" indices: list[Mapping[str, Any]] = [] if predicate is None: predicate = lambda index: index.get("queryable") is True while True: indices = list(coll.list_search_indexes(name)) if len(indices) and predicate(indices[0]): return indices[0] break time.sleep(5) class TestSearchIndexIntegration(SearchIndexIntegrationBase): db_name = "test_search_index" def test_comment_field(self): # Create a collection with the "create" command using a randomly generated name (referred to as ``coll0``). coll0 = self.db[f"col{uuid.uuid4()}"] coll0.insert_one({}) # Create a new search index on ``coll0`` that implicitly passes its type. search_definition = {"mappings": {"dynamic": False}} self.listener.reset() implicit_search_resp = coll0.create_search_index( model={"name": _NAME + "-implicit", "definition": search_definition}, comment="foo" ) event = self.listener.events[0] self.assertEqual(event.command["comment"], "foo") # Get the index definition. self.listener.reset() coll0.list_search_indexes(name=implicit_search_resp, comment="foo").next() event = self.listener.events[0] self.assertEqual(event.command["comment"], "foo") class TestSearchIndexProse(SearchIndexIntegrationBase): db_name = "test_search_index_prose" def test_case_1(self): """Driver can successfully create and list search indexes.""" # Create a collection with the "create" command using a randomly generated name (referred to as ``coll0``). coll0 = self.db[f"col{uuid.uuid4()}"] # Create a new search index on ``coll0`` with the ``createSearchIndex`` helper. Use the following definition: model = {"name": _NAME, "definition": {"mappings": {"dynamic": False}}} coll0.insert_one({}) resp = coll0.create_search_index(model) # Assert that the command returns the name of the index: ``"test-search-index"``. self.assertEqual(resp, _NAME) # Run ``coll0.listSearchIndexes()`` repeatedly every 5 seconds until the following condition is satisfied and store the value in a variable ``index``: # An index with the ``name`` of ``test-search-index`` is present and the index has a field ``queryable`` with a value of ``true``. index = self.wait_for_ready(coll0) # . Assert that ``index`` has a property ``latestDefinition`` whose value is ``{ 'mappings': { 'dynamic': false } }`` self.assertIn("latestDefinition", index) self.assertEqual(index["latestDefinition"], model["definition"]) def test_case_2(self): """Driver can successfully create multiple indexes in batch.""" # Create a collection with the "create" command using a randomly generated name (referred to as ``coll0``). coll0 = self.db[f"col{uuid.uuid4()}"] coll0.insert_one({}) # Create two new search indexes on ``coll0`` with the ``createSearchIndexes`` helper. name1 = "test-search-index-1" name2 = "test-search-index-2" definition = {"mappings": {"dynamic": False}} index_definitions: list[dict[str, Any]] = [ {"name": name1, "definition": definition}, {"name": name2, "definition": definition}, ] coll0.create_search_indexes( [SearchIndexModel(i["definition"], i["name"]) for i in index_definitions] ) # .Assert that the command returns an array containing the new indexes' names: ``["test-search-index-1", "test-search-index-2"]``. indices = list(coll0.list_search_indexes()) names = [i["name"] for i in indices] self.assertIn(name1, names) self.assertIn(name2, names) # Run ``coll0.listSearchIndexes()`` repeatedly every 5 seconds until the following condition is satisfied. # An index with the ``name`` of ``test-search-index-1`` is present and index has a field ``queryable`` with the value of ``true``. Store result in ``index1``. # An index with the ``name`` of ``test-search-index-2`` is present and index has a field ``queryable`` with the value of ``true``. Store result in ``index2``. index1 = self.wait_for_ready(coll0, name1) index2 = self.wait_for_ready(coll0, name2) # Assert that ``index1`` and ``index2`` have the property ``latestDefinition`` whose value is ``{ "mappings" : { "dynamic" : false } }`` for index in [index1, index2]: self.assertIn("latestDefinition", index) self.assertEqual(index["latestDefinition"], definition) def test_case_3(self): """Driver can successfully drop search indexes.""" # Create a collection with the "create" command using a randomly generated name (referred to as ``coll0``). coll0 = self.db[f"col{uuid.uuid4()}"] coll0.insert_one({}) # Create a new search index on ``coll0``. model = {"name": _NAME, "definition": {"mappings": {"dynamic": False}}} resp = coll0.create_search_index(model) # Assert that the command returns the name of the index: ``"test-search-index"``. self.assertEqual(resp, "test-search-index") # Run ``coll0.listSearchIndexes()`` repeatedly every 5 seconds until the following condition is satisfied: # An index with the ``name`` of ``test-search-index`` is present and index has a field ``queryable`` with the value of ``true``. self.wait_for_ready(coll0) # Run a ``dropSearchIndex`` on ``coll0``, using ``test-search-index`` for the name. coll0.drop_search_index(_NAME) # Run ``coll0.listSearchIndexes()`` repeatedly every 5 seconds until ``listSearchIndexes`` returns an empty array. t0 = time.time() while True: indices = list(coll0.list_search_indexes()) if indices: break if (time.time() - t0) / 60 > 5: raise TimeoutError("Timed out waiting for index deletion") time.sleep(5) def test_case_4(self): """Driver can update a search index.""" # Create a collection with the "create" command using a randomly generated name (referred to as ``coll0``). coll0 = self.db[f"col{uuid.uuid4()}"] coll0.insert_one({}) # Create a new search index on ``coll0``. model = {"name": _NAME, "definition": {"mappings": {"dynamic": False}}} resp = coll0.create_search_index(model) # Assert that the command returns the name of the index: ``"test-search-index"``. self.assertEqual(resp, _NAME) # Run ``coll0.listSearchIndexes()`` repeatedly every 5 seconds until the following condition is satisfied: # An index with the ``name`` of ``test-search-index`` is present and index has a field ``queryable`` with the value of ``true``. self.wait_for_ready(coll0) # Run a ``updateSearchIndex`` on ``coll0``. # Assert that the command does not error and the server responds with a success. model2: dict[str, Any] = {"name": _NAME, "definition": {"mappings": {"dynamic": True}}} coll0.update_search_index(_NAME, model2["definition"]) # Run ``coll0.listSearchIndexes()`` repeatedly every 5 seconds until the following condition is satisfied: # An index with the ``name`` of ``test-search-index`` is present. This index is referred to as ``index``. # The index has a field ``queryable`` with a value of ``true`` and has a field ``status`` with the value of ``READY``. predicate = lambda index: index.get("queryable") is True and index.get("status") == "READY" self.wait_for_ready(coll0, predicate=predicate) # Assert that an index is present with the name ``test-search-index`` and the definition has a property ``latestDefinition`` whose value is ``{ 'mappings': { 'dynamic': true } }``. index = list(coll0.list_search_indexes(_NAME))[0] self.assertIn("latestDefinition", index) self.assertEqual(index["latestDefinition"], model2["definition"]) def test_case_5(self): """``dropSearchIndex`` suppresses namespace not found errors.""" # Create a driver-side collection object for a randomly generated collection name. Do not create this collection on the server. coll0 = self.db[f"col{uuid.uuid4()}"] # Run a ``dropSearchIndex`` command and assert that no error is thrown. coll0.drop_search_index("foo") def test_case_6(self): """Driver can successfully create and list search indexes with non-default readConcern and writeConcern.""" # Create a collection with the "create" command using a randomly generated name (referred to as ``coll0``). coll0 = self.db[f"col{uuid.uuid4()}"] coll0.insert_one({}) # Apply a write concern ``WriteConcern(w=1)`` and a read concern with ``ReadConcern(level="majority")`` to ``coll0``. coll0 = coll0.with_options( write_concern=WriteConcern(w="1"), read_concern=ReadConcern(level="majority") ) # Create a new search index on ``coll0`` with the ``createSearchIndex`` helper. name = "test-search-index-case6" model = {"name": name, "definition": {"mappings": {"dynamic": False}}} resp = coll0.create_search_index(model) # Assert that the command returns the name of the index: ``"test-search-index-case6"``. self.assertEqual(resp, name) # Run ``coll0.listSearchIndexes()`` repeatedly every 5 seconds until the following condition is satisfied and store the value in a variable ``index``: # - An index with the ``name`` of ``test-search-index-case6`` is present and the index has a field ``queryable`` with a value of ``true``. index = self.wait_for_ready(coll0, name) # Assert that ``index`` has a property ``latestDefinition`` whose value is ``{ 'mappings': { 'dynamic': false } }`` self.assertIn("latestDefinition", index) self.assertEqual(index["latestDefinition"], model["definition"]) def test_case_7(self): """Driver handles index types.""" # Create a collection with the "create" command using a randomly generated name (referred to as ``coll0``). coll0 = self.db[f"col{uuid.uuid4()}"] coll0.insert_one({}) # Use these search and vector search definitions for indexes. search_definition = {"mappings": {"dynamic": False}} vector_search_definition = { "fields": [ { "type": "vector", "path": "plot_embedding", "numDimensions": 1536, "similarity": "euclidean", }, ] } # Create a new search index on ``coll0`` that implicitly passes its type. implicit_search_resp = coll0.create_search_index( model={"name": _NAME + "-implicit", "definition": search_definition} ) # Get the index definition. resp = coll0.list_search_indexes(name=implicit_search_resp).next() # Assert that the index model contains the correct index type: ``"search"``. self.assertEqual(resp["type"], "search") # Create a new search index on ``coll0`` that explicitly passes its type. explicit_search_resp = coll0.create_search_index( model={"name": _NAME + "-explicit", "type": "search", "definition": search_definition} ) # Get the index definition. resp = coll0.list_search_indexes(name=explicit_search_resp).next() # Assert that the index model contains the correct index type: ``"search"``. self.assertEqual(resp["type"], "search") # Create a new vector search index on ``coll0`` that explicitly passes its type. explicit_vector_resp = coll0.create_search_index( model={ "name": _NAME + "-vector", "type": "vectorSearch", "definition": vector_search_definition, } ) # Get the index definition. resp = coll0.list_search_indexes(name=explicit_vector_resp).next() # Assert that the index model contains the correct index type: ``"vectorSearch"``. self.assertEqual(resp["type"], "vectorSearch") # Catch the error raised when trying to create a vector search index without specifying the type with self.assertRaises(OperationFailure) as e: coll0.create_search_index( model={"name": _NAME + "-error", "definition": vector_search_definition} ) self.assertIn("Attribute mappings missing.", e.exception.details["errmsg"]) globals().update( generate_test_classes( _TEST_PATH, module=__name__, ) ) if __name__ == "__main__": unittest.main() mongodb-mongo-python-driver-509e9b7/test/test_json_util.py000066400000000000000000000625711462766011000240460ustar00rootroot00000000000000# Copyright 2009-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. """Test some utilities for working with JSON and PyMongo.""" from __future__ import annotations import datetime import json import re import sys import uuid from collections import OrderedDict from typing import Any, List, MutableMapping, Tuple, Type from bson.codec_options import CodecOptions, DatetimeConversion sys.path[0:0] = [""] from test import IntegrationTest, unittest from bson import EPOCH_AWARE, EPOCH_NAIVE, SON, DatetimeMS, json_util from bson.binary import ( ALL_UUID_REPRESENTATIONS, MD5_SUBTYPE, STANDARD, USER_DEFINED_SUBTYPE, Binary, UuidRepresentation, ) from bson.code import Code from bson.datetime_ms import _max_datetime_ms from bson.dbref import DBRef from bson.decimal128 import Decimal128 from bson.int64 import Int64 from bson.json_util import ( CANONICAL_JSON_OPTIONS, LEGACY_JSON_OPTIONS, RELAXED_JSON_OPTIONS, DatetimeRepresentation, JSONMode, JSONOptions, ) from bson.max_key import MaxKey from bson.min_key import MinKey from bson.objectid import ObjectId from bson.regex import Regex from bson.timestamp import Timestamp from bson.tz_util import FixedOffset, utc STRICT_JSON_OPTIONS = JSONOptions( strict_number_long=True, datetime_representation=DatetimeRepresentation.ISO8601, strict_uuid=True, json_mode=JSONMode.LEGACY, ) class TestJsonUtil(unittest.TestCase): def round_tripped(self, doc, **kwargs): return json_util.loads(json_util.dumps(doc, **kwargs), **kwargs) def round_trip(self, doc, **kwargs): self.assertEqual(doc, self.round_tripped(doc, **kwargs)) def test_basic(self): self.round_trip({"hello": "world"}) def test_loads_bytes(self): string = b'{"hello": "world"}' self.assertEqual(json_util.loads(bytes(string)), {"hello": "world"}) self.assertEqual(json_util.loads(bytearray(string)), {"hello": "world"}) def test_json_options_with_options(self): opts = JSONOptions( datetime_representation=DatetimeRepresentation.NUMBERLONG, json_mode=JSONMode.LEGACY ) self.assertEqual(opts.datetime_representation, DatetimeRepresentation.NUMBERLONG) opts2 = opts.with_options( datetime_representation=DatetimeRepresentation.ISO8601, json_mode=JSONMode.LEGACY ) self.assertEqual(opts2.datetime_representation, DatetimeRepresentation.ISO8601) opts = JSONOptions(strict_number_long=True, json_mode=JSONMode.LEGACY) self.assertEqual(opts.strict_number_long, True) opts2 = opts.with_options(strict_number_long=False) self.assertEqual(opts2.strict_number_long, False) opts = json_util.CANONICAL_JSON_OPTIONS self.assertNotEqual(opts.uuid_representation, UuidRepresentation.JAVA_LEGACY) opts2 = opts.with_options(uuid_representation=UuidRepresentation.JAVA_LEGACY) self.assertEqual(opts2.uuid_representation, UuidRepresentation.JAVA_LEGACY) self.assertEqual(opts2.document_class, dict) opts3 = opts2.with_options(document_class=SON) self.assertEqual(opts3.uuid_representation, UuidRepresentation.JAVA_LEGACY) self.assertEqual(opts3.document_class, SON) def test_objectid(self): self.round_trip({"id": ObjectId()}) def test_dbref(self): self.round_trip({"ref": DBRef("foo", 5)}) self.round_trip({"ref": DBRef("foo", 5, "db")}) self.round_trip({"ref": DBRef("foo", ObjectId())}) # Check order. self.assertEqual( '{"$ref": "collection", "$id": 1, "$db": "db"}', json_util.dumps(DBRef("collection", 1, "db")), ) def test_datetime(self): tz_aware_opts = json_util.DEFAULT_JSON_OPTIONS.with_options(tz_aware=True) # only millis, not micros self.round_trip( {"date": datetime.datetime(2009, 12, 9, 15, 49, 45, 191000, utc)}, json_options=tz_aware_opts, ) self.round_trip({"date": datetime.datetime(2009, 12, 9, 15, 49, 45, 191000)}) for jsn in [ '{"dt": { "$date" : "1970-01-01T00:00:00.000+0000"}}', '{"dt": { "$date" : "1970-01-01T00:00:00.000000+0000"}}', '{"dt": { "$date" : "1970-01-01T00:00:00.000+00:00"}}', '{"dt": { "$date" : "1970-01-01T00:00:00.000000+00:00"}}', '{"dt": { "$date" : "1970-01-01T00:00:00.000000+00"}}', '{"dt": { "$date" : "1970-01-01T00:00:00.000Z"}}', '{"dt": { "$date" : "1970-01-01T00:00:00.000000Z"}}', '{"dt": { "$date" : "1970-01-01T00:00:00Z"}}', '{"dt": {"$date": "1970-01-01T00:00:00.000"}}', '{"dt": { "$date" : "1970-01-01T00:00:00"}}', '{"dt": { "$date" : "1970-01-01T00:00:00.000000"}}', '{"dt": { "$date" : "1969-12-31T16:00:00.000-0800"}}', '{"dt": { "$date" : "1969-12-31T16:00:00.000000-0800"}}', '{"dt": { "$date" : "1969-12-31T16:00:00.000-08:00"}}', '{"dt": { "$date" : "1969-12-31T16:00:00.000000-08:00"}}', '{"dt": { "$date" : "1969-12-31T16:00:00.000000-08"}}', '{"dt": { "$date" : "1970-01-01T01:00:00.000+0100"}}', '{"dt": { "$date" : "1970-01-01T01:00:00.000000+0100"}}', '{"dt": { "$date" : "1970-01-01T01:00:00.000+01:00"}}', '{"dt": { "$date" : "1970-01-01T01:00:00.000000+01:00"}}', '{"dt": { "$date" : "1970-01-01T01:00:00.000000+01"}}', ]: self.assertEqual(EPOCH_AWARE, json_util.loads(jsn, json_options=tz_aware_opts)["dt"]) self.assertEqual(EPOCH_NAIVE, json_util.loads(jsn)["dt"]) dtm = datetime.datetime(1, 1, 1, 1, 1, 1, 0, utc) jsn = '{"dt": {"$date": -62135593139000}}' self.assertEqual(dtm, json_util.loads(jsn, json_options=tz_aware_opts)["dt"]) jsn = '{"dt": {"$date": {"$numberLong": "-62135593139000"}}}' self.assertEqual(dtm, json_util.loads(jsn, json_options=tz_aware_opts)["dt"]) # Test dumps format pre_epoch = {"dt": datetime.datetime(1, 1, 1, 1, 1, 1, 10000, utc)} post_epoch = {"dt": datetime.datetime(1972, 1, 1, 1, 1, 1, 10000, utc)} self.assertEqual( '{"dt": {"$date": {"$numberLong": "-62135593138990"}}}', json_util.dumps(pre_epoch) ) self.assertEqual( '{"dt": {"$date": "1972-01-01T01:01:01.010Z"}}', json_util.dumps(post_epoch) ) self.assertEqual( '{"dt": {"$date": -62135593138990}}', json_util.dumps(pre_epoch, json_options=LEGACY_JSON_OPTIONS), ) self.assertEqual( '{"dt": {"$date": 63075661010}}', json_util.dumps(post_epoch, json_options=LEGACY_JSON_OPTIONS), ) self.assertEqual( '{"dt": {"$date": {"$numberLong": "-62135593138990"}}}', json_util.dumps(pre_epoch, json_options=STRICT_JSON_OPTIONS), ) self.assertEqual( '{"dt": {"$date": "1972-01-01T01:01:01.010Z"}}', json_util.dumps(post_epoch, json_options=STRICT_JSON_OPTIONS), ) number_long_options = JSONOptions( datetime_representation=DatetimeRepresentation.NUMBERLONG, json_mode=JSONMode.LEGACY ) self.assertEqual( '{"dt": {"$date": {"$numberLong": "63075661010"}}}', json_util.dumps(post_epoch, json_options=number_long_options), ) self.assertEqual( '{"dt": {"$date": {"$numberLong": "-62135593138990"}}}', json_util.dumps(pre_epoch, json_options=number_long_options), ) # ISO8601 mode assumes naive datetimes are UTC pre_epoch_naive = {"dt": datetime.datetime(1, 1, 1, 1, 1, 1, 10000)} post_epoch_naive = {"dt": datetime.datetime(1972, 1, 1, 1, 1, 1, 10000)} self.assertEqual( '{"dt": {"$date": {"$numberLong": "-62135593138990"}}}', json_util.dumps(pre_epoch_naive, json_options=STRICT_JSON_OPTIONS), ) self.assertEqual( '{"dt": {"$date": "1972-01-01T01:01:01.010Z"}}', json_util.dumps(post_epoch_naive, json_options=STRICT_JSON_OPTIONS), ) # Test tz_aware and tzinfo options self.assertEqual( datetime.datetime(1972, 1, 1, 1, 1, 1, 10000, utc), json_util.loads( '{"dt": {"$date": "1972-01-01T01:01:01.010+0000"}}', json_options=tz_aware_opts )["dt"], ) self.assertEqual( datetime.datetime(1972, 1, 1, 1, 1, 1, 10000, utc), json_util.loads( '{"dt": {"$date": "1972-01-01T01:01:01.010+0000"}}', json_options=JSONOptions(tz_aware=True, tzinfo=utc), )["dt"], ) self.assertEqual( datetime.datetime(1972, 1, 1, 1, 1, 1, 10000), json_util.loads( '{"dt": {"$date": "1972-01-01T01:01:01.010+0000"}}', json_options=JSONOptions(tz_aware=False), )["dt"], ) self.round_trip(pre_epoch_naive, json_options=JSONOptions(tz_aware=False)) # Test a non-utc timezone pacific = FixedOffset(-8 * 60, "US/Pacific") aware_datetime = {"dt": datetime.datetime(2002, 10, 27, 6, 0, 0, 10000, pacific)} self.assertEqual( '{"dt": {"$date": "2002-10-27T06:00:00.010-0800"}}', json_util.dumps(aware_datetime, json_options=STRICT_JSON_OPTIONS), ) self.round_trip( aware_datetime, json_options=JSONOptions(json_mode=JSONMode.LEGACY, tz_aware=True, tzinfo=pacific), ) self.round_trip( aware_datetime, json_options=JSONOptions( datetime_representation=DatetimeRepresentation.ISO8601, json_mode=JSONMode.LEGACY, tz_aware=True, tzinfo=pacific, ), ) def test_datetime_ms(self): # Test ISO8601 in-range dat_min: dict[str, Any] = {"x": DatetimeMS(0)} dat_max: dict[str, Any] = {"x": DatetimeMS(_max_datetime_ms())} opts = JSONOptions(datetime_representation=DatetimeRepresentation.ISO8601) self.assertEqual( dat_min["x"].as_datetime(CodecOptions(tz_aware=False)), json_util.loads(json_util.dumps(dat_min))["x"], ) self.assertEqual( dat_max["x"].as_datetime(CodecOptions(tz_aware=False)), json_util.loads(json_util.dumps(dat_max))["x"], ) # Test ISO8601 out-of-range dat_min = {"x": DatetimeMS(-1)} dat_max = {"x": DatetimeMS(_max_datetime_ms() + 1)} self.assertEqual('{"x": {"$date": {"$numberLong": "-1"}}}', json_util.dumps(dat_min)) self.assertEqual( '{"x": {"$date": {"$numberLong": "' + str(int(dat_max["x"])) + '"}}}', json_util.dumps(dat_max), ) # Test legacy. opts = JSONOptions( datetime_representation=DatetimeRepresentation.LEGACY, json_mode=JSONMode.LEGACY ) self.assertEqual('{"x": {"$date": "-1"}}', json_util.dumps(dat_min, json_options=opts)) self.assertEqual( '{"x": {"$date": "' + str(int(dat_max["x"])) + '"}}', json_util.dumps(dat_max, json_options=opts), ) # Test regular. opts = JSONOptions( datetime_representation=DatetimeRepresentation.NUMBERLONG, json_mode=JSONMode.LEGACY ) self.assertEqual( '{"x": {"$date": {"$numberLong": "-1"}}}', json_util.dumps(dat_min, json_options=opts) ) self.assertEqual( '{"x": {"$date": {"$numberLong": "' + str(int(dat_max["x"])) + '"}}}', json_util.dumps(dat_max, json_options=opts), ) # Test decode from datetime.datetime to DatetimeMS dat_min = {"x": datetime.datetime.min} dat_max = {"x": DatetimeMS(_max_datetime_ms()).as_datetime(CodecOptions(tz_aware=False))} opts = JSONOptions( datetime_representation=DatetimeRepresentation.ISO8601, datetime_conversion=DatetimeConversion.DATETIME_MS, ) self.assertEqual( DatetimeMS(dat_min["x"]), json_util.loads(json_util.dumps(dat_min), json_options=opts)["x"], ) self.assertEqual( DatetimeMS(dat_max["x"]), json_util.loads(json_util.dumps(dat_max), json_options=opts)["x"], ) def test_regex_object_hook(self): # Extended JSON format regular expression. pat = "a*b" json_re = '{"$regex": "%s", "$options": "u"}' % pat loaded = json_util.object_hook(json.loads(json_re)) self.assertTrue(isinstance(loaded, Regex)) self.assertEqual(pat, loaded.pattern) self.assertEqual(re.U, loaded.flags) def test_regex(self): for regex_instance in (re.compile("a*b", re.IGNORECASE), Regex("a*b", re.IGNORECASE)): res = self.round_tripped({"r": regex_instance})["r"] self.assertEqual("a*b", res.pattern) res = self.round_tripped({"r": Regex("a*b", re.IGNORECASE)})["r"] self.assertEqual("a*b", res.pattern) self.assertEqual(re.IGNORECASE, res.flags) unicode_options = re.I | re.M | re.S | re.U | re.X regex = re.compile("a*b", unicode_options) res = self.round_tripped({"r": regex})["r"] self.assertEqual(unicode_options, res.flags) # Some tools may not add $options if no flags are set. res = json_util.loads('{"r": {"$regex": "a*b"}}')["r"] self.assertEqual(0, res.flags) self.assertEqual( Regex(".*", "ilm"), json_util.loads('{"r": {"$regex": ".*", "$options": "ilm"}}')["r"] ) # Check order. self.assertEqual( '{"$regularExpression": {"pattern": ".*", "options": "mx"}}', json_util.dumps(Regex(".*", re.M | re.X)), ) self.assertEqual( '{"$regularExpression": {"pattern": ".*", "options": "mx"}}', json_util.dumps(re.compile(b".*", re.M | re.X)), ) self.assertEqual( '{"$regex": ".*", "$options": "mx"}', json_util.dumps(Regex(".*", re.M | re.X), json_options=LEGACY_JSON_OPTIONS), ) def test_regex_validation(self): non_str_types = [10, {}, []] docs = [{"$regex": i} for i in non_str_types] for doc in docs: self.assertEqual(doc, json_util.loads(json.dumps(doc))) doc = {"$regex": ""} self.assertIsInstance(json_util.loads(json.dumps(doc)), Regex) def test_minkey(self): self.round_trip({"m": MinKey()}) def test_maxkey(self): self.round_trip({"m": MaxKey()}) def test_timestamp(self): dct = {"ts": Timestamp(4, 13)} res = json_util.dumps(dct, default=json_util.default) rtdct = json_util.loads(res) self.assertEqual(dct, rtdct) self.assertEqual('{"ts": {"$timestamp": {"t": 4, "i": 13}}}', res) def test_uuid_default(self): # Cannot directly encode native UUIDs with the default # uuid_representation. doc = {"uuid": uuid.UUID("f47ac10b-58cc-4372-a567-0e02b2c3d479")} with self.assertRaisesRegex(ValueError, "cannot encode native uuid"): json_util.dumps(doc) legacy_jsn = '{"uuid": {"$uuid": "f47ac10b58cc4372a5670e02b2c3d479"}}' expected = {"uuid": Binary(b"\xf4z\xc1\x0bX\xccCr\xa5g\x0e\x02\xb2\xc3\xd4y", 4)} self.assertEqual(json_util.loads(legacy_jsn), expected) def test_uuid(self): doc = {"uuid": uuid.UUID("f47ac10b-58cc-4372-a567-0e02b2c3d479")} uuid_legacy_opts = LEGACY_JSON_OPTIONS.with_options( uuid_representation=UuidRepresentation.PYTHON_LEGACY ) self.round_trip(doc, json_options=uuid_legacy_opts) self.assertEqual( '{"uuid": {"$uuid": "f47ac10b58cc4372a5670e02b2c3d479"}}', json_util.dumps(doc, json_options=LEGACY_JSON_OPTIONS), ) self.assertEqual( '{"uuid": {"$binary": "9HrBC1jMQ3KlZw4CssPUeQ==", "$type": "03"}}', json_util.dumps( doc, json_options=STRICT_JSON_OPTIONS.with_options( uuid_representation=UuidRepresentation.PYTHON_LEGACY ), ), ) self.assertEqual( '{"uuid": {"$binary": "9HrBC1jMQ3KlZw4CssPUeQ==", "$type": "04"}}', json_util.dumps( doc, json_options=JSONOptions( strict_uuid=True, json_mode=JSONMode.LEGACY, uuid_representation=STANDARD ), ), ) self.assertEqual( doc, json_util.loads( '{"uuid": {"$binary": "9HrBC1jMQ3KlZw4CssPUeQ==", "$type": "03"}}', json_options=uuid_legacy_opts, ), ) for uuid_representation in set(ALL_UUID_REPRESENTATIONS) - {UuidRepresentation.UNSPECIFIED}: options = JSONOptions( strict_uuid=True, json_mode=JSONMode.LEGACY, uuid_representation=uuid_representation ) self.round_trip(doc, json_options=options) # Ignore UUID representation when decoding BSON binary subtype 4. self.assertEqual( doc, json_util.loads( '{"uuid": {"$binary": "9HrBC1jMQ3KlZw4CssPUeQ==", "$type": "04"}}', json_options=options, ), ) def test_uuid_uuid_rep_unspecified(self): _uuid = uuid.uuid4() options = JSONOptions( strict_uuid=True, json_mode=JSONMode.LEGACY, uuid_representation=UuidRepresentation.UNSPECIFIED, ) # Cannot directly encode native UUIDs with UNSPECIFIED. doc: dict[str, Any] = {"uuid": _uuid} with self.assertRaises(ValueError): json_util.dumps(doc, json_options=options) # All UUID subtypes are decoded as Binary with UNSPECIFIED. # subtype 3 doc = {"uuid": Binary(_uuid.bytes, subtype=3)} ext_json_str = json_util.dumps(doc) self.assertEqual(doc, json_util.loads(ext_json_str, json_options=options)) # subtype 4 doc = {"uuid": Binary(_uuid.bytes, subtype=4)} ext_json_str = json_util.dumps(doc) self.assertEqual(doc, json_util.loads(ext_json_str, json_options=options)) # $uuid-encoded fields doc = {"uuid": Binary(_uuid.bytes, subtype=4)} ext_json_str = json_util.dumps({"uuid": _uuid}, json_options=LEGACY_JSON_OPTIONS) self.assertEqual(doc, json_util.loads(ext_json_str, json_options=options)) def test_binary(self): bin_type_dict = {"bin": b"\x00\x01\x02\x03\x04"} md5_type_dict = { "md5": Binary(b" n7\x18\xaf\t/\xd1\xd1/\x80\xca\xe7q\xcc\xac", MD5_SUBTYPE) } custom_type_dict = {"custom": Binary(b"hello", USER_DEFINED_SUBTYPE)} self.round_trip(bin_type_dict) self.round_trip(md5_type_dict) self.round_trip(custom_type_dict) # Binary with subtype 0 is decoded into bytes in Python 3. bin = json_util.loads('{"bin": {"$binary": "AAECAwQ=", "$type": "00"}}')["bin"] self.assertEqual(type(bin), bytes) # PYTHON-443 ensure old type formats are supported json_bin_dump = json_util.dumps(bin_type_dict, json_options=LEGACY_JSON_OPTIONS) self.assertIn('"$type": "00"', json_bin_dump) self.assertEqual( bin_type_dict, json_util.loads('{"bin": {"$type": 0, "$binary": "AAECAwQ="}}') ) json_bin_dump = json_util.dumps(md5_type_dict, json_options=LEGACY_JSON_OPTIONS) # Check order. self.assertEqual( '{"md5": {"$binary": "IG43GK8JL9HRL4DK53HMrA==", "$type": "05"}}', json_bin_dump ) self.assertEqual( md5_type_dict, json_util.loads('{"md5": {"$type": 5, "$binary": "IG43GK8JL9HRL4DK53HMrA=="}}'), ) json_bin_dump = json_util.dumps(custom_type_dict, json_options=LEGACY_JSON_OPTIONS) self.assertIn('"$type": "80"', json_bin_dump) self.assertEqual( custom_type_dict, json_util.loads('{"custom": {"$type": 128, "$binary": "aGVsbG8="}}'), ) # Handle mongoexport where subtype >= 128 self.assertEqual( 128, json_util.loads('{"custom": {"$type": "ffffff80", "$binary": "aGVsbG8="}}')[ "custom" ].subtype, ) self.assertEqual( 255, json_util.loads('{"custom": {"$type": "ffffffff", "$binary": "aGVsbG8="}}')[ "custom" ].subtype, ) def test_code(self): self.round_trip({"code": Code("function x() { return 1; }")}) code = Code("return z", z=2) res = json_util.dumps(code) self.assertEqual(code, json_util.loads(res)) # Check order. self.assertEqual('{"$code": "return z", "$scope": {"z": 2}}', res) no_scope = Code("function() {}") self.assertEqual('{"$code": "function() {}"}', json_util.dumps(no_scope)) def test_undefined(self): jsn = '{"name": {"$undefined": true}}' self.assertIsNone(json_util.loads(jsn)["name"]) def test_numberlong(self): jsn = '{"weight": {"$numberLong": "65535"}}' self.assertEqual(json_util.loads(jsn)["weight"], Int64(65535)) self.assertEqual(json_util.dumps({"weight": Int64(65535)}), '{"weight": 65535}') json_options = JSONOptions(strict_number_long=True, json_mode=JSONMode.LEGACY) self.assertEqual(json_util.dumps({"weight": Int64(65535)}, json_options=json_options), jsn) # Ensure json_util.default converts Int64 to int in non-strict mode. converted = json_util.default(Int64(65535)) self.assertEqual(converted, 65535) self.assertNotIsInstance(converted, Int64) self.assertEqual( json_util.default(Int64(65535), json_options=json_options), {"$numberLong": "65535"} ) def test_loads_document_class(self): json_doc = '{"foo": "bar", "b": 1, "d": {"a": 1}}' expected_doc = {"foo": "bar", "b": 1, "d": {"a": 1}} for cls in (dict, SON, OrderedDict): doc = json_util.loads(json_doc, json_options=JSONOptions(document_class=cls)) self.assertEqual(doc, expected_doc) self.assertIsInstance(doc, cls) self.assertIsInstance(doc["d"], cls) def test_encode_subclass(self): cases: list[Tuple[Type, Any]] = [ (int, (1,)), (int, (2 << 60,)), (float, (1.1,)), (Int64, (64,)), (Int64, (2 << 60,)), (str, ("str",)), (bytes, (b"bytes",)), (datetime.datetime, (2024, 1, 16)), (DatetimeMS, (1,)), (uuid.UUID, ("f47ac10b-58cc-4372-a567-0e02b2c3d479",)), (Binary, (b"1", USER_DEFINED_SUBTYPE)), (Code, ("code",)), (DBRef, ("coll", ObjectId())), (ObjectId, ("65a6dab5f98bc03906ee3597",)), (MaxKey, ()), (MinKey, ()), (Regex, ("pat",)), (Timestamp, (1, 1)), (Decimal128, ("0.5",)), ] allopts = [ CANONICAL_JSON_OPTIONS.with_options(uuid_representation=STANDARD), RELAXED_JSON_OPTIONS.with_options(uuid_representation=STANDARD), LEGACY_JSON_OPTIONS.with_options(uuid_representation=STANDARD), ] for cls, args in cases: basic_obj = cls(*args) my_cls = type(f"My{cls.__name__}", (cls,), {}) my_obj = my_cls(*args) for opts in allopts: expected_json = json_util.dumps(basic_obj, json_options=opts) self.assertEqual(json_util.dumps(my_obj, json_options=opts), expected_json) def test_encode_type_marker(self): # Assert that a custom subclass can be JSON encoded based on the _type_marker attribute. class MyMaxKey: _type_marker = 127 expected_json = json_util.dumps(MaxKey()) self.assertEqual(json_util.dumps(MyMaxKey()), expected_json) # Test a class that inherits from two built in types class MyBinary(Binary): pass expected_json = json_util.dumps(Binary(b"bin", USER_DEFINED_SUBTYPE)) self.assertEqual(json_util.dumps(MyBinary(b"bin", USER_DEFINED_SUBTYPE)), expected_json) class TestJsonUtilRoundtrip(IntegrationTest): def test_cursor(self): db = self.db db.drop_collection("test") docs: List[MutableMapping[str, Any]] = [ {"foo": [1, 2]}, {"bar": {"hello": "world"}}, {"code": Code("function x() { return 1; }")}, {"bin": Binary(b"\x00\x01\x02\x03\x04", USER_DEFINED_SUBTYPE)}, {"dbref": {"_ref": DBRef("simple", ObjectId("509b8db456c02c5ab7e63c34"))}}, ] db.test.insert_many(docs) reloaded_docs = json_util.loads(json_util.dumps(db.test.find())) for doc in docs: self.assertTrue(doc in reloaded_docs) if __name__ == "__main__": unittest.main() mongodb-mongo-python-driver-509e9b7/test/test_load_balancer.py000066400000000000000000000141531462766011000245770ustar00rootroot00000000000000# Copyright 2021-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. """Test the Load Balancer unified spec tests.""" from __future__ import annotations import gc import os import sys import threading 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 # Location of JSON test specifications. TEST_PATH = os.path.join(os.path.dirname(os.path.realpath(__file__)), "load_balancer") # Generate unified tests. globals().update(generate_test_classes(TEST_PATH, module=__name__)) class TestLB(IntegrationTest): RUN_ON_LOAD_BALANCER = True RUN_ON_SERVERLESS = True def test_connections_are_only_returned_once(self): if "PyPy" in sys.version: # Tracked in PYTHON-3011 self.skipTest("Test is flaky on PyPy") pool = get_pool(self.client) n_conns = len(pool.conns) self.db.test.find_one({}) self.assertEqual(len(pool.conns), n_conns) list(self.db.test.aggregate([{"$limit": 1}])) self.assertEqual(len(pool.conns), n_conns) @client_context.require_load_balancer def test_unpin_committed_transaction(self): client = rs_client() self.addCleanup(client.close) pool = get_pool(client) coll = client[self.db.name].test with client.start_session() as session: with session.start_transaction(): self.assertEqual(pool.active_sockets, 0) coll.insert_one({}, session=session) self.assertEqual(pool.active_sockets, 1) # Pinned. self.assertEqual(pool.active_sockets, 1) # Still pinned. self.assertEqual(pool.active_sockets, 0) # Unpinned. @client_context.require_failCommand_fail_point def test_cursor_gc(self): def create_resource(coll): cursor = coll.find({}, batch_size=3) next(cursor) return cursor self._test_no_gc_deadlock(create_resource) @client_context.require_failCommand_fail_point def test_command_cursor_gc(self): def create_resource(coll): cursor = coll.aggregate([], batchSize=3) next(cursor) return cursor self._test_no_gc_deadlock(create_resource) def _test_no_gc_deadlock(self, create_resource): client = rs_client() self.addCleanup(client.close) pool = get_pool(client) coll = client[self.db.name].test coll.insert_many([{} for _ in range(10)]) self.assertEqual(pool.active_sockets, 0) # Cause the initial find attempt to fail to induce a reference cycle. args = { "mode": {"times": 1}, "data": { "failCommands": ["find", "aggregate"], "closeConnection": True, }, } with self.fail_point(args): resource = create_resource(coll) if client_context.load_balancer: self.assertEqual(pool.active_sockets, 1) # Pinned. thread = PoolLocker(pool) thread.start() self.assertTrue(thread.locked.wait(5), "timed out") # Garbage collect the resource while the pool is locked to ensure we # don't deadlock. del resource # On PyPy it can take a few rounds to collect the cursor. for _ in range(3): gc.collect() thread.unlock.set() thread.join(5) self.assertFalse(thread.is_alive()) self.assertIsNone(thread.exc) wait_until(lambda: pool.active_sockets == 0, "return socket") # Run another operation to ensure the socket still works. coll.delete_many({}) @client_context.require_transactions def test_session_gc(self): client = rs_client() self.addCleanup(client.close) pool = get_pool(client) session = client.start_session() session.start_transaction() client.test_session_gc.test.find_one({}, session=session) # Cleanup the transaction left open on the server unless we're # testing serverless which does not support killSessions. if not client_context.serverless: self.addCleanup(self.client.admin.command, "killSessions", [session.session_id]) if client_context.load_balancer: self.assertEqual(pool.active_sockets, 1) # Pinned. thread = PoolLocker(pool) thread.start() self.assertTrue(thread.locked.wait(5), "timed out") # Garbage collect the session while the pool is locked to ensure we # don't deadlock. del session # On PyPy it can take a few rounds to collect the session. for _ in range(3): gc.collect() thread.unlock.set() thread.join(5) self.assertFalse(thread.is_alive()) self.assertIsNone(thread.exc) wait_until(lambda: pool.active_sockets == 0, "return socket") # Run another operation to ensure the socket still works. client[self.db.name].test.delete_many({}) class PoolLocker(ExceptionCatchingThread): def __init__(self, pool): super().__init__(target=self.lock_pool) self.pool = pool self.daemon = True self.locked = threading.Event() self.unlock = threading.Event() def lock_pool(self): with self.pool.lock: self.locked.set() # Wait for the unlock flag. unlock_pool = self.unlock.wait(10) if not unlock_pool: raise Exception("timed out waiting for unlock signal: deadlock?") if __name__ == "__main__": unittest.main() mongodb-mongo-python-driver-509e9b7/test/test_logger.py000066400000000000000000000072421462766011000233110ustar00rootroot00000000000000# Copyright 2023-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. from __future__ import annotations import os from test import unittest from test.test_client import IntegrationTest from unittest.mock import patch from bson import json_util from pymongo.errors import OperationFailure from pymongo.logger import _DEFAULT_DOCUMENT_LENGTH # https://github.com/mongodb/specifications/tree/master/source/command-logging-and-monitoring/tests#prose-tests class TestLogger(IntegrationTest): def test_default_truncation_limit(self): docs = [{"x": "y"} for _ in range(100)] db = self.db with patch.dict("os.environ"): os.environ.pop("MONGOB_LOG_MAX_DOCUMENT_LENGTH", None) with self.assertLogs("pymongo.command", level="DEBUG") as cm: db.test.insert_many(docs) cmd_started_log = json_util.loads(cm.records[0].message) self.assertEqual(len(cmd_started_log["command"]), _DEFAULT_DOCUMENT_LENGTH + 3) cmd_succeeded_log = json_util.loads(cm.records[1].message) self.assertLessEqual(len(cmd_succeeded_log["reply"]), _DEFAULT_DOCUMENT_LENGTH + 3) with self.assertLogs("pymongo.command", level="DEBUG") as cm: list(db.test.find({})) cmd_succeeded_log = json_util.loads(cm.records[1].message) self.assertEqual(len(cmd_succeeded_log["reply"]), _DEFAULT_DOCUMENT_LENGTH + 3) def test_configured_truncation_limit(self): cmd = {"hello": True} db = self.db with patch.dict("os.environ", {"MONGOB_LOG_MAX_DOCUMENT_LENGTH": "5"}): with self.assertLogs("pymongo.command", level="DEBUG") as cm: db.command(cmd) cmd_started_log = json_util.loads(cm.records[0].message) self.assertEqual(len(cmd_started_log["command"]), 5 + 3) cmd_succeeded_log = json_util.loads(cm.records[1].message) self.assertLessEqual(len(cmd_succeeded_log["reply"]), 5 + 3) with self.assertRaises(OperationFailure): db.command({"notARealCommand": True}) cmd_failed_log = json_util.loads(cm.records[-1].message) self.assertEqual(len(cmd_failed_log["failure"]), 5 + 3) def test_truncation_multi_byte_codepoints(self): document_lengths = ["20000", "20001", "20002"] multi_byte_char_str_len = 50_000 str_to_repeat = "界" multi_byte_char_str = "" for i in range(multi_byte_char_str_len): multi_byte_char_str += str_to_repeat for length in document_lengths: with patch.dict("os.environ", {"MONGOB_LOG_MAX_DOCUMENT_LENGTH": length}): with self.assertLogs("pymongo.command", level="DEBUG") as cm: self.db.test.insert_one({"x": multi_byte_char_str}) cmd_started_log = json_util.loads(cm.records[0].message)["command"] cmd_started_log = cmd_started_log[:-3] last_3_bytes = cmd_started_log.encode()[-3:].decode() self.assertEqual(last_3_bytes, str_to_repeat) if __name__ == "__main__": unittest.main() mongodb-mongo-python-driver-509e9b7/test/test_max_staleness.py000066400000000000000000000126231462766011000246770ustar00rootroot00000000000000# Copyright 2016 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. """Test maxStalenessSeconds support.""" from __future__ import annotations import os import sys import time import warnings from pymongo.operations import _Op sys.path[0:0] = [""] from test import client_context, unittest from test.utils import rs_or_single_client from test.utils_selection_tests import create_selection_tests from pymongo import MongoClient from pymongo.errors import ConfigurationError from pymongo.server_selectors import writable_server_selector # Location of JSON test specifications. _TEST_PATH = os.path.join(os.path.dirname(os.path.realpath(__file__)), "max_staleness") class TestAllScenarios(create_selection_tests(_TEST_PATH)): # type: ignore pass class TestMaxStaleness(unittest.TestCase): def test_max_staleness(self): client = MongoClient() self.assertEqual(-1, client.read_preference.max_staleness) client = MongoClient("mongodb://a/?readPreference=secondary") self.assertEqual(-1, client.read_preference.max_staleness) # These tests are specified in max-staleness-tests.rst. with self.assertRaises(ConfigurationError): # Default read pref "primary" can't be used with max staleness. MongoClient("mongodb://a/?maxStalenessSeconds=120") with self.assertRaises(ConfigurationError): # Read pref "primary" can't be used with max staleness. MongoClient("mongodb://a/?readPreference=primary&maxStalenessSeconds=120") client = MongoClient("mongodb://host/?maxStalenessSeconds=-1") self.assertEqual(-1, client.read_preference.max_staleness) client = MongoClient("mongodb://host/?readPreference=primary&maxStalenessSeconds=-1") self.assertEqual(-1, client.read_preference.max_staleness) client = MongoClient("mongodb://host/?readPreference=secondary&maxStalenessSeconds=120") self.assertEqual(120, client.read_preference.max_staleness) client = MongoClient("mongodb://a/?readPreference=secondary&maxStalenessSeconds=1") self.assertEqual(1, client.read_preference.max_staleness) client = MongoClient("mongodb://a/?readPreference=secondary&maxStalenessSeconds=-1") self.assertEqual(-1, client.read_preference.max_staleness) client = MongoClient(maxStalenessSeconds=-1, readPreference="nearest") self.assertEqual(-1, client.read_preference.max_staleness) with self.assertRaises(TypeError): # Prohibit None. MongoClient(maxStalenessSeconds=None, readPreference="nearest") def test_max_staleness_float(self): with self.assertRaises(TypeError) as ctx: rs_or_single_client(maxStalenessSeconds=1.5, readPreference="nearest") self.assertIn("must be an integer", str(ctx.exception)) with warnings.catch_warnings(record=True) as ctx: warnings.simplefilter("always") client = MongoClient("mongodb://host/?maxStalenessSeconds=1.5&readPreference=nearest") # Option was ignored. self.assertEqual(-1, client.read_preference.max_staleness) self.assertIn("must be an integer", str(ctx[0])) def test_max_staleness_zero(self): # Zero is too small. with self.assertRaises(ValueError) as ctx: rs_or_single_client(maxStalenessSeconds=0, readPreference="nearest") self.assertIn("must be a positive integer", str(ctx.exception)) with warnings.catch_warnings(record=True) as ctx: warnings.simplefilter("always") client = MongoClient("mongodb://host/?maxStalenessSeconds=0&readPreference=nearest") # Option was ignored. self.assertEqual(-1, client.read_preference.max_staleness) self.assertIn("must be a positive integer", str(ctx[0])) @client_context.require_replica_set def test_last_write_date(self): # From max-staleness-tests.rst, "Parse lastWriteDate". client = rs_or_single_client(heartbeatFrequencyMS=500) client.pymongo_test.test.insert_one({}) # Wait for the server description to be updated. time.sleep(1) server = client._topology.select_server(writable_server_selector, _Op.TEST) first = server.description.last_write_date self.assertTrue(first) # The first last_write_date may correspond to a internal server write, # sleep so that the next write does not occur within the same second. time.sleep(1) client.pymongo_test.test.insert_one({}) # Wait for the server description to be updated. time.sleep(1) server = client._topology.select_server(writable_server_selector, _Op.TEST) second = server.description.last_write_date assert first is not None assert second is not None self.assertGreater(second, first) self.assertLess(second, first + 10) if __name__ == "__main__": unittest.main() mongodb-mongo-python-driver-509e9b7/test/test_mongos_load_balancing.py000066400000000000000000000137251462766011000263340ustar00rootroot00000000000000# Copyright 2015-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. """Test MongoClient's mongos load balancing using a mock.""" from __future__ import annotations import sys import threading from pymongo.operations import _Op sys.path[0:0] = [""] from test import MockClientTest, client_context, unittest from test.pymongo_mocks import MockClient from test.utils import connected, wait_until from pymongo.errors import AutoReconnect, InvalidOperation from pymongo.server_selectors import writable_server_selector from pymongo.topology_description import TOPOLOGY_TYPE @client_context.require_connection @client_context.require_no_load_balancer def setUpModule(): pass class SimpleOp(threading.Thread): def __init__(self, client): super().__init__() self.client = client self.passed = False def run(self): self.client.db.command("ping") self.passed = True # No exception raised. def do_simple_op(client, nthreads): threads = [SimpleOp(client) for _ in range(nthreads)] for t in threads: t.start() for t in threads: t.join() for t in threads: assert t.passed def writable_addresses(topology): return { server.description.address for server in topology.select_servers(writable_server_selector, _Op.TEST) } class TestMongosLoadBalancing(MockClientTest): def mock_client(self, **kwargs): mock_client = MockClient( standalones=[], members=[], mongoses=["a:1", "b:2", "c:3"], host="a:1,b:2,c:3", connect=False, **kwargs, ) self.addCleanup(mock_client.close) # Latencies in seconds. mock_client.mock_rtts["a:1"] = 0.020 mock_client.mock_rtts["b:2"] = 0.025 mock_client.mock_rtts["c:3"] = 0.045 return mock_client def test_lazy_connect(self): # While connected() ensures we can trigger connection from the main # thread and wait for the monitors, this test triggers connection from # several threads at once to check for data races. nthreads = 10 client = self.mock_client() self.assertEqual(0, len(client.nodes)) # Trigger initial connection. do_simple_op(client, nthreads) wait_until(lambda: len(client.nodes) == 3, "connect to all mongoses") def test_failover(self): nthreads = 10 client = connected(self.mock_client(localThresholdMS=0.001)) wait_until(lambda: len(client.nodes) == 3, "connect to all mongoses") # Our chosen mongos goes down. client.kill_host("a:1") # Trigger failover to higher-latency nodes. AutoReconnect should be # raised at most once in each thread. passed = [] def f(): try: client.db.command("ping") except AutoReconnect: # Second attempt succeeds. client.db.command("ping") passed.append(True) threads = [threading.Thread(target=f) for _ in range(nthreads)] for t in threads: t.start() for t in threads: t.join() self.assertEqual(nthreads, len(passed)) # Down host removed from list. self.assertEqual(2, len(client.nodes)) def test_local_threshold(self): client = connected(self.mock_client(localThresholdMS=30)) self.assertEqual(30, client.options.local_threshold_ms) wait_until(lambda: len(client.nodes) == 3, "connect to all mongoses") topology = client._topology # All are within a 30-ms latency window, see self.mock_client(). self.assertEqual({("a", 1), ("b", 2), ("c", 3)}, writable_addresses(topology)) # No error client.admin.command("ping") client = connected(self.mock_client(localThresholdMS=0)) self.assertEqual(0, client.options.local_threshold_ms) # No error client.db.command("ping") # Our chosen mongos goes down. client.kill_host("{}:{}".format(*next(iter(client.nodes)))) try: client.db.command("ping") except: pass # We eventually connect to a new mongos. def connect_to_new_mongos(): try: return client.db.command("ping") except AutoReconnect: pass wait_until(connect_to_new_mongos, "connect to a new mongos") def test_load_balancing(self): # Although the server selection JSON tests already prove that # select_servers works for sharded topologies, here we do an end-to-end # test of discovering servers' round trip times and configuring # localThresholdMS. client = connected(self.mock_client()) wait_until(lambda: len(client.nodes) == 3, "connect to all mongoses") # Prohibited for topology type Sharded. with self.assertRaises(InvalidOperation): client.address topology = client._topology self.assertEqual(TOPOLOGY_TYPE.Sharded, topology.description.topology_type) # a and b are within the 15-ms latency window, see self.mock_client(). self.assertEqual({("a", 1), ("b", 2)}, writable_addresses(topology)) client.mock_rtts["a:1"] = 0.045 # Discover only b is within latency window. wait_until( lambda: {("b", 2)} == writable_addresses(topology), 'discover server "a" is too far', ) if __name__ == "__main__": unittest.main() mongodb-mongo-python-driver-509e9b7/test/test_monitor.py000066400000000000000000000057011462766011000235170ustar00rootroot00000000000000# Copyright 2014-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. """Test the monitor module.""" from __future__ import annotations import gc import subprocess import sys from functools import partial sys.path[0:0] = [""] from test import IntegrationTest, unittest from test.utils import ( ServerAndTopologyEventListener, connected, single_client, wait_until, ) from pymongo.periodic_executor import _EXECUTORS def unregistered(ref): gc.collect() return ref not in _EXECUTORS def get_executors(client): executors = [] for server in client._topology._servers.values(): executors.append(server._monitor._executor) executors.append(server._monitor._rtt_monitor._executor) executors.append(client._kill_cursors_executor) executors.append(client._topology._Topology__events_executor) return [e for e in executors if e is not None] def create_client(): listener = ServerAndTopologyEventListener() client = single_client(event_listeners=[listener]) connected(client) return client class TestMonitor(IntegrationTest): def test_cleanup_executors_on_client_del(self): client = create_client() executors = get_executors(client) self.assertEqual(len(executors), 4) # Each executor stores a weakref to itself in _EXECUTORS. executor_refs = [(r, r()._name) for r in _EXECUTORS.copy() if r() in executors] del executors del client for ref, name in executor_refs: wait_until(partial(unregistered, ref), f"unregister executor: {name}", timeout=5) def test_cleanup_executors_on_client_close(self): client = create_client() executors = get_executors(client) self.assertEqual(len(executors), 4) client.close() for executor in executors: wait_until(lambda: executor._stopped, f"closed executor: {executor._name}", timeout=5) def test_no_thread_start_runtime_err_on_shutdown(self): """Test we silence noisy runtime errors fired when the MongoClient spawns a new thread on process shutdown.""" command = [sys.executable, "-c", "from pymongo import MongoClient; c = MongoClient()"] completed_process: subprocess.CompletedProcess = subprocess.run( command, capture_output=True ) self.assertFalse(completed_process.stderr) self.assertFalse(completed_process.stdout) if __name__ == "__main__": unittest.main() mongodb-mongo-python-driver-509e9b7/test/test_monitoring.py000066400000000000000000001561741462766011000242300ustar00rootroot00000000000000# Copyright 2015-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. from __future__ import annotations import copy import datetime import sys import time from typing import Any sys.path[0:0] = [""] from test import IntegrationTest, client_context, client_knobs, sanitize_cmd, unittest from test.utils import EventListener, rs_or_single_client, single_client, wait_until from bson.int64 import Int64 from bson.objectid import ObjectId from bson.son import SON from pymongo import CursorType, DeleteOne, InsertOne, UpdateOne, monitoring from pymongo.command_cursor import CommandCursor from pymongo.errors import AutoReconnect, NotPrimaryError, OperationFailure from pymongo.read_preferences import ReadPreference from pymongo.write_concern import WriteConcern class TestCommandMonitoring(IntegrationTest): listener: EventListener @classmethod @client_context.require_connection def setUpClass(cls): super().setUpClass() cls.listener = EventListener() cls.client = rs_or_single_client(event_listeners=[cls.listener], retryWrites=False) @classmethod def tearDownClass(cls): cls.client.close() super().tearDownClass() def tearDown(self): self.listener.reset() super().tearDown() def test_started_simple(self): self.client.pymongo_test.command("ping") started = self.listener.started_events[0] succeeded = self.listener.succeeded_events[0] self.assertEqual(0, len(self.listener.failed_events)) self.assertTrue(isinstance(succeeded, monitoring.CommandSucceededEvent)) self.assertTrue(isinstance(started, monitoring.CommandStartedEvent)) self.assertEqualCommand(SON([("ping", 1)]), started.command) self.assertEqual("ping", started.command_name) self.assertEqual(self.client.address, started.connection_id) self.assertEqual("pymongo_test", started.database_name) self.assertTrue(isinstance(started.request_id, int)) def test_succeeded_simple(self): self.client.pymongo_test.command("ping") started = self.listener.started_events[0] succeeded = self.listener.succeeded_events[0] self.assertEqual(0, len(self.listener.failed_events)) self.assertTrue(isinstance(started, monitoring.CommandStartedEvent)) self.assertTrue(isinstance(succeeded, monitoring.CommandSucceededEvent)) self.assertEqual("ping", succeeded.command_name) self.assertEqual(self.client.address, succeeded.connection_id) self.assertEqual(1, succeeded.reply.get("ok")) self.assertTrue(isinstance(succeeded.request_id, int)) self.assertTrue(isinstance(succeeded.duration_micros, int)) def test_failed_simple(self): try: self.client.pymongo_test.command("oops!") except OperationFailure: pass started = self.listener.started_events[0] failed = self.listener.failed_events[0] self.assertEqual(0, len(self.listener.succeeded_events)) self.assertTrue(isinstance(started, monitoring.CommandStartedEvent)) self.assertTrue(isinstance(failed, monitoring.CommandFailedEvent)) self.assertEqual("oops!", failed.command_name) self.assertEqual(self.client.address, failed.connection_id) self.assertEqual(0, failed.failure.get("ok")) self.assertTrue(isinstance(failed.request_id, int)) self.assertTrue(isinstance(failed.duration_micros, int)) def test_find_one(self): self.client.pymongo_test.test.find_one() started = self.listener.started_events[0] succeeded = self.listener.succeeded_events[0] self.assertEqual(0, len(self.listener.failed_events)) self.assertTrue(isinstance(succeeded, monitoring.CommandSucceededEvent)) self.assertTrue(isinstance(started, monitoring.CommandStartedEvent)) self.assertEqualCommand( SON([("find", "test"), ("filter", {}), ("limit", 1), ("singleBatch", True)]), started.command, ) self.assertEqual("find", started.command_name) self.assertEqual(self.client.address, started.connection_id) self.assertEqual("pymongo_test", started.database_name) self.assertTrue(isinstance(started.request_id, int)) def test_find_and_get_more(self): self.client.pymongo_test.test.drop() self.client.pymongo_test.test.insert_many([{} for _ in range(10)]) self.listener.reset() cursor = self.client.pymongo_test.test.find(projection={"_id": False}, batch_size=4) for _ in range(4): next(cursor) cursor_id = cursor.cursor_id started = self.listener.started_events[0] succeeded = self.listener.succeeded_events[0] self.assertEqual(0, len(self.listener.failed_events)) self.assertTrue(isinstance(started, monitoring.CommandStartedEvent)) self.assertEqualCommand( SON( [("find", "test"), ("filter", {}), ("projection", {"_id": False}), ("batchSize", 4)] ), started.command, ) self.assertEqual("find", started.command_name) self.assertEqual(self.client.address, started.connection_id) self.assertEqual("pymongo_test", started.database_name) self.assertTrue(isinstance(started.request_id, int)) self.assertTrue(isinstance(succeeded, monitoring.CommandSucceededEvent)) self.assertTrue(isinstance(succeeded.duration_micros, int)) self.assertEqual("find", succeeded.command_name) self.assertTrue(isinstance(succeeded.request_id, int)) self.assertEqual(cursor.address, succeeded.connection_id) csr = succeeded.reply["cursor"] self.assertEqual(csr["id"], cursor_id) self.assertEqual(csr["ns"], "pymongo_test.test") self.assertEqual(csr["firstBatch"], [{} for _ in range(4)]) self.listener.reset() # Next batch. Exhausting the cursor could cause a getMore # that returns id of 0 and no results. next(cursor) try: started = self.listener.started_events[0] succeeded = self.listener.succeeded_events[0] self.assertEqual(0, len(self.listener.failed_events)) self.assertTrue(isinstance(started, monitoring.CommandStartedEvent)) self.assertEqualCommand( SON([("getMore", cursor_id), ("collection", "test"), ("batchSize", 4)]), started.command, ) self.assertEqual("getMore", started.command_name) self.assertEqual(self.client.address, started.connection_id) self.assertEqual("pymongo_test", started.database_name) self.assertTrue(isinstance(started.request_id, int)) self.assertTrue(isinstance(succeeded, monitoring.CommandSucceededEvent)) self.assertTrue(isinstance(succeeded.duration_micros, int)) self.assertEqual("getMore", succeeded.command_name) self.assertTrue(isinstance(succeeded.request_id, int)) self.assertEqual(cursor.address, succeeded.connection_id) csr = succeeded.reply["cursor"] self.assertEqual(csr["id"], cursor_id) self.assertEqual(csr["ns"], "pymongo_test.test") self.assertEqual(csr["nextBatch"], [{} for _ in range(4)]) finally: # Exhaust the cursor to avoid kill cursors. tuple(cursor) def test_find_with_explain(self): cmd = SON([("explain", SON([("find", "test"), ("filter", {})]))]) self.client.pymongo_test.test.drop() self.client.pymongo_test.test.insert_one({}) self.listener.reset() coll = self.client.pymongo_test.test # Test that we publish the unwrapped command. if self.client.is_mongos: coll = coll.with_options(read_preference=ReadPreference.PRIMARY_PREFERRED) res = coll.find().explain() started = self.listener.started_events[0] succeeded = self.listener.succeeded_events[0] self.assertEqual(0, len(self.listener.failed_events)) self.assertTrue(isinstance(started, monitoring.CommandStartedEvent)) self.assertEqualCommand(cmd, started.command) self.assertEqual("explain", started.command_name) self.assertEqual(self.client.address, started.connection_id) self.assertEqual("pymongo_test", started.database_name) self.assertTrue(isinstance(started.request_id, int)) self.assertTrue(isinstance(succeeded, monitoring.CommandSucceededEvent)) self.assertTrue(isinstance(succeeded.duration_micros, int)) self.assertEqual("explain", succeeded.command_name) self.assertTrue(isinstance(succeeded.request_id, int)) self.assertEqual(self.client.address, succeeded.connection_id) self.assertEqual(res, succeeded.reply) def _test_find_options(self, query, expected_cmd): coll = self.client.pymongo_test.test coll.drop() coll.create_index("x") coll.insert_many([{"x": i} for i in range(5)]) # Test that we publish the unwrapped command. self.listener.reset() if self.client.is_mongos: coll = coll.with_options(read_preference=ReadPreference.PRIMARY_PREFERRED) cursor = coll.find(**query) next(cursor) try: started = self.listener.started_events[0] succeeded = self.listener.succeeded_events[0] self.assertEqual(0, len(self.listener.failed_events)) self.assertTrue(isinstance(started, monitoring.CommandStartedEvent)) self.assertEqualCommand(expected_cmd, started.command) self.assertEqual("find", started.command_name) self.assertEqual(self.client.address, started.connection_id) self.assertEqual("pymongo_test", started.database_name) self.assertTrue(isinstance(started.request_id, int)) self.assertTrue(isinstance(succeeded, monitoring.CommandSucceededEvent)) self.assertTrue(isinstance(succeeded.duration_micros, int)) self.assertEqual("find", succeeded.command_name) self.assertTrue(isinstance(succeeded.request_id, int)) self.assertEqual(self.client.address, succeeded.connection_id) finally: # Exhaust the cursor to avoid kill cursors. tuple(cursor) def test_find_options(self): query = { "filter": {}, "hint": [("x", 1)], "max_time_ms": 10000, "max": {"x": 10}, "min": {"x": -10}, "return_key": True, "show_record_id": True, "projection": {"x": False}, "skip": 1, "no_cursor_timeout": True, "sort": [("_id", 1)], "allow_partial_results": True, "comment": "this is a test", "batch_size": 2, } cmd = { "find": "test", "filter": {}, "hint": SON([("x", 1)]), "comment": "this is a test", "maxTimeMS": 10000, "max": {"x": 10}, "min": {"x": -10}, "returnKey": True, "showRecordId": True, "sort": SON([("_id", 1)]), "projection": {"x": False}, "skip": 1, "batchSize": 2, "noCursorTimeout": True, "allowPartialResults": True, } if client_context.version < (4, 1, 0, -1): query["max_scan"] = 10 cmd["maxScan"] = 10 self._test_find_options(query, cmd) @client_context.require_version_max(3, 7, 2) def test_find_snapshot(self): # Test "snapshot" parameter separately, can't combine with "sort". query = {"filter": {}, "snapshot": True} cmd = {"find": "test", "filter": {}, "snapshot": True} self._test_find_options(query, cmd) def test_command_and_get_more(self): self.client.pymongo_test.test.drop() self.client.pymongo_test.test.insert_many([{"x": 1} for _ in range(10)]) self.listener.reset() coll = self.client.pymongo_test.test # Test that we publish the unwrapped command. if self.client.is_mongos: coll = coll.with_options(read_preference=ReadPreference.PRIMARY_PREFERRED) cursor = coll.aggregate([{"$project": {"_id": False, "x": 1}}], batchSize=4) for _ in range(4): next(cursor) cursor_id = cursor.cursor_id started = self.listener.started_events[0] succeeded = self.listener.succeeded_events[0] self.assertEqual(0, len(self.listener.failed_events)) self.assertTrue(isinstance(started, monitoring.CommandStartedEvent)) self.assertEqualCommand( SON( [ ("aggregate", "test"), ("pipeline", [{"$project": {"_id": False, "x": 1}}]), ("cursor", {"batchSize": 4}), ] ), started.command, ) self.assertEqual("aggregate", started.command_name) self.assertEqual(self.client.address, started.connection_id) self.assertEqual("pymongo_test", started.database_name) self.assertTrue(isinstance(started.request_id, int)) self.assertTrue(isinstance(succeeded, monitoring.CommandSucceededEvent)) self.assertTrue(isinstance(succeeded.duration_micros, int)) self.assertEqual("aggregate", succeeded.command_name) self.assertTrue(isinstance(succeeded.request_id, int)) self.assertEqual(cursor.address, succeeded.connection_id) expected_cursor = { "id": cursor_id, "ns": "pymongo_test.test", "firstBatch": [{"x": 1} for _ in range(4)], } self.assertEqualCommand(expected_cursor, succeeded.reply.get("cursor")) self.listener.reset() next(cursor) try: started = self.listener.started_events[0] succeeded = self.listener.succeeded_events[0] self.assertEqual(0, len(self.listener.failed_events)) self.assertTrue(isinstance(started, monitoring.CommandStartedEvent)) self.assertEqualCommand( SON([("getMore", cursor_id), ("collection", "test"), ("batchSize", 4)]), started.command, ) self.assertEqual("getMore", started.command_name) self.assertEqual(self.client.address, started.connection_id) self.assertEqual("pymongo_test", started.database_name) self.assertTrue(isinstance(started.request_id, int)) self.assertTrue(isinstance(succeeded, monitoring.CommandSucceededEvent)) self.assertTrue(isinstance(succeeded.duration_micros, int)) self.assertEqual("getMore", succeeded.command_name) self.assertTrue(isinstance(succeeded.request_id, int)) self.assertEqual(cursor.address, succeeded.connection_id) expected_result = { "cursor": { "id": cursor_id, "ns": "pymongo_test.test", "nextBatch": [{"x": 1} for _ in range(4)], }, "ok": 1.0, } self.assertEqualReply(expected_result, succeeded.reply) finally: # Exhaust the cursor to avoid kill cursors. tuple(cursor) def test_get_more_failure(self): address = self.client.address coll = self.client.pymongo_test.test cursor_id = Int64(12345) cursor_doc = {"id": cursor_id, "firstBatch": [], "ns": coll.full_name} cursor = CommandCursor(coll, cursor_doc, address) try: next(cursor) except Exception: pass started = self.listener.started_events[0] self.assertEqual(0, len(self.listener.succeeded_events)) failed = self.listener.failed_events[0] self.assertTrue(isinstance(started, monitoring.CommandStartedEvent)) self.assertEqualCommand( SON([("getMore", cursor_id), ("collection", "test")]), started.command ) self.assertEqual("getMore", started.command_name) self.assertEqual(self.client.address, started.connection_id) self.assertEqual("pymongo_test", started.database_name) self.assertTrue(isinstance(started.request_id, int)) self.assertTrue(isinstance(failed, monitoring.CommandFailedEvent)) self.assertTrue(isinstance(failed.duration_micros, int)) self.assertEqual("getMore", failed.command_name) self.assertTrue(isinstance(failed.request_id, int)) self.assertEqual(cursor.address, failed.connection_id) self.assertEqual(0, failed.failure.get("ok")) @client_context.require_replica_set @client_context.require_secondaries_count(1) def test_not_primary_error(self): address = next(iter(client_context.client.secondaries)) client = single_client(*address, event_listeners=[self.listener]) # Clear authentication command results from the listener. client.admin.command("ping") self.listener.reset() error = None try: client.pymongo_test.test.find_one_and_delete({}) except NotPrimaryError as exc: error = exc.errors started = self.listener.started_events[0] failed = self.listener.failed_events[0] self.assertEqual(0, len(self.listener.succeeded_events)) self.assertTrue(isinstance(started, monitoring.CommandStartedEvent)) self.assertTrue(isinstance(failed, monitoring.CommandFailedEvent)) self.assertEqual("findAndModify", failed.command_name) self.assertEqual(address, failed.connection_id) self.assertEqual(0, failed.failure.get("ok")) self.assertTrue(isinstance(failed.request_id, int)) self.assertTrue(isinstance(failed.duration_micros, int)) self.assertEqual(error, failed.failure) @client_context.require_no_mongos def test_exhaust(self): self.client.pymongo_test.test.drop() self.client.pymongo_test.test.insert_many([{} for _ in range(11)]) self.listener.reset() cursor = self.client.pymongo_test.test.find( projection={"_id": False}, batch_size=5, cursor_type=CursorType.EXHAUST ) next(cursor) cursor_id = cursor.cursor_id started = self.listener.started_events[0] succeeded = self.listener.succeeded_events[0] self.assertEqual(0, len(self.listener.failed_events)) self.assertTrue(isinstance(started, monitoring.CommandStartedEvent)) self.assertEqualCommand( SON( [("find", "test"), ("filter", {}), ("projection", {"_id": False}), ("batchSize", 5)] ), started.command, ) self.assertEqual("find", started.command_name) self.assertEqual(cursor.address, started.connection_id) self.assertEqual("pymongo_test", started.database_name) self.assertTrue(isinstance(started.request_id, int)) self.assertTrue(isinstance(succeeded, monitoring.CommandSucceededEvent)) self.assertTrue(isinstance(succeeded.duration_micros, int)) self.assertEqual("find", succeeded.command_name) self.assertTrue(isinstance(succeeded.request_id, int)) self.assertEqual(cursor.address, succeeded.connection_id) expected_result = { "cursor": { "id": cursor_id, "ns": "pymongo_test.test", "firstBatch": [{} for _ in range(5)], }, "ok": 1, } self.assertEqualReply(expected_result, succeeded.reply) self.listener.reset() tuple(cursor) self.assertEqual(0, len(self.listener.failed_events)) for event in self.listener.started_events: self.assertTrue(isinstance(event, monitoring.CommandStartedEvent)) self.assertEqualCommand( SON([("getMore", cursor_id), ("collection", "test"), ("batchSize", 5)]), event.command, ) self.assertEqual("getMore", event.command_name) self.assertEqual(cursor.address, event.connection_id) self.assertEqual("pymongo_test", event.database_name) self.assertTrue(isinstance(event.request_id, int)) for event in self.listener.succeeded_events: self.assertTrue(isinstance(event, monitoring.CommandSucceededEvent)) self.assertTrue(isinstance(event.duration_micros, int)) self.assertEqual("getMore", event.command_name) self.assertTrue(isinstance(event.request_id, int)) self.assertEqual(cursor.address, event.connection_id) # Last getMore receives a response with cursor id 0. self.assertEqual(0, self.listener.succeeded_events[-1].reply["cursor"]["id"]) def test_kill_cursors(self): with client_knobs(kill_cursor_frequency=0.01): self.client.pymongo_test.test.drop() self.client.pymongo_test.test.insert_many([{} for _ in range(10)]) cursor = self.client.pymongo_test.test.find().batch_size(5) next(cursor) cursor_id = cursor.cursor_id self.listener.reset() cursor.close() time.sleep(2) started = self.listener.started_events[0] succeeded = self.listener.succeeded_events[0] self.assertEqual(0, len(self.listener.failed_events)) self.assertTrue(isinstance(started, monitoring.CommandStartedEvent)) # There could be more than one cursor_id here depending on # when the thread last ran. self.assertIn(cursor_id, started.command["cursors"]) self.assertEqual("killCursors", started.command_name) self.assertIs(type(started.connection_id), tuple) self.assertEqual(cursor.address, started.connection_id) self.assertEqual("pymongo_test", started.database_name) self.assertTrue(isinstance(started.request_id, int)) self.assertTrue(isinstance(succeeded, monitoring.CommandSucceededEvent)) self.assertTrue(isinstance(succeeded.duration_micros, int)) self.assertEqual("killCursors", succeeded.command_name) self.assertTrue(isinstance(succeeded.request_id, int)) self.assertIs(type(succeeded.connection_id), tuple) self.assertEqual(cursor.address, succeeded.connection_id) # There could be more than one cursor_id here depending on # when the thread last ran. self.assertTrue( cursor_id in succeeded.reply["cursorsUnknown"] or cursor_id in succeeded.reply["cursorsKilled"] ) def test_non_bulk_writes(self): coll = self.client.pymongo_test.test coll.drop() self.listener.reset() # Implied write concern insert_one res = coll.insert_one({"x": 1}) started = self.listener.started_events[0] succeeded = self.listener.succeeded_events[0] self.assertEqual(0, len(self.listener.failed_events)) self.assertIsInstance(started, monitoring.CommandStartedEvent) expected = SON( [ ("insert", coll.name), ("ordered", True), ("documents", [{"_id": res.inserted_id, "x": 1}]), ] ) self.assertEqualCommand(expected, started.command) self.assertEqual("pymongo_test", started.database_name) self.assertEqual("insert", started.command_name) self.assertIsInstance(started.request_id, int) self.assertEqual(self.client.address, started.connection_id) self.assertIsInstance(succeeded, monitoring.CommandSucceededEvent) self.assertIsInstance(succeeded.duration_micros, int) self.assertEqual(started.command_name, succeeded.command_name) self.assertEqual(started.request_id, succeeded.request_id) self.assertEqual(started.connection_id, succeeded.connection_id) reply = succeeded.reply self.assertEqual(1, reply.get("ok")) self.assertEqual(1, reply.get("n")) # Unacknowledged insert_one self.listener.reset() coll = coll.with_options(write_concern=WriteConcern(w=0)) res = coll.insert_one({"x": 1}) started = self.listener.started_events[0] succeeded = self.listener.succeeded_events[0] self.assertEqual(0, len(self.listener.failed_events)) self.assertIsInstance(started, monitoring.CommandStartedEvent) expected = SON( [ ("insert", coll.name), ("ordered", True), ("documents", [{"_id": res.inserted_id, "x": 1}]), ("writeConcern", {"w": 0}), ] ) self.assertEqualCommand(expected, started.command) self.assertEqual("pymongo_test", started.database_name) self.assertEqual("insert", started.command_name) self.assertIsInstance(started.request_id, int) self.assertEqual(self.client.address, started.connection_id) self.assertIsInstance(succeeded, monitoring.CommandSucceededEvent) self.assertIsInstance(succeeded.duration_micros, int) self.assertEqual(started.command_name, succeeded.command_name) self.assertEqual(started.request_id, succeeded.request_id) self.assertEqual(started.connection_id, succeeded.connection_id) self.assertEqualReply(succeeded.reply, {"ok": 1}) # Explicit write concern insert_one self.listener.reset() coll = coll.with_options(write_concern=WriteConcern(w=1)) res = coll.insert_one({"x": 1}) started = self.listener.started_events[0] succeeded = self.listener.succeeded_events[0] self.assertEqual(0, len(self.listener.failed_events)) self.assertIsInstance(started, monitoring.CommandStartedEvent) expected = SON( [ ("insert", coll.name), ("ordered", True), ("documents", [{"_id": res.inserted_id, "x": 1}]), ("writeConcern", {"w": 1}), ] ) self.assertEqualCommand(expected, started.command) self.assertEqual("pymongo_test", started.database_name) self.assertEqual("insert", started.command_name) self.assertIsInstance(started.request_id, int) self.assertEqual(self.client.address, started.connection_id) self.assertIsInstance(succeeded, monitoring.CommandSucceededEvent) self.assertIsInstance(succeeded.duration_micros, int) self.assertEqual(started.command_name, succeeded.command_name) self.assertEqual(started.request_id, succeeded.request_id) self.assertEqual(started.connection_id, succeeded.connection_id) reply = succeeded.reply self.assertEqual(1, reply.get("ok")) self.assertEqual(1, reply.get("n")) # delete_many self.listener.reset() res = coll.delete_many({"x": 1}) started = self.listener.started_events[0] succeeded = self.listener.succeeded_events[0] self.assertEqual(0, len(self.listener.failed_events)) self.assertIsInstance(started, monitoring.CommandStartedEvent) expected = SON( [ ("delete", coll.name), ("ordered", True), ("deletes", [SON([("q", {"x": 1}), ("limit", 0)])]), ("writeConcern", {"w": 1}), ] ) self.assertEqualCommand(expected, started.command) self.assertEqual("pymongo_test", started.database_name) self.assertEqual("delete", started.command_name) self.assertIsInstance(started.request_id, int) self.assertEqual(self.client.address, started.connection_id) self.assertIsInstance(succeeded, monitoring.CommandSucceededEvent) self.assertIsInstance(succeeded.duration_micros, int) self.assertEqual(started.command_name, succeeded.command_name) self.assertEqual(started.request_id, succeeded.request_id) self.assertEqual(started.connection_id, succeeded.connection_id) reply = succeeded.reply self.assertEqual(1, reply.get("ok")) self.assertEqual(res.deleted_count, reply.get("n")) # replace_one self.listener.reset() oid = ObjectId() res = coll.replace_one({"_id": oid}, {"_id": oid, "x": 1}, upsert=True) started = self.listener.started_events[0] succeeded = self.listener.succeeded_events[0] self.assertEqual(0, len(self.listener.failed_events)) self.assertIsInstance(started, monitoring.CommandStartedEvent) expected = SON( [ ("update", coll.name), ("ordered", True), ( "updates", [ SON( [ ("q", {"_id": oid}), ("u", {"_id": oid, "x": 1}), ("multi", False), ("upsert", True), ] ) ], ), ("writeConcern", {"w": 1}), ] ) self.assertEqualCommand(expected, started.command) self.assertEqual("pymongo_test", started.database_name) self.assertEqual("update", started.command_name) self.assertIsInstance(started.request_id, int) self.assertEqual(self.client.address, started.connection_id) self.assertIsInstance(succeeded, monitoring.CommandSucceededEvent) self.assertIsInstance(succeeded.duration_micros, int) self.assertEqual(started.command_name, succeeded.command_name) self.assertEqual(started.request_id, succeeded.request_id) self.assertEqual(started.connection_id, succeeded.connection_id) reply = succeeded.reply self.assertEqual(1, reply.get("ok")) self.assertEqual(1, reply.get("n")) self.assertEqual([{"index": 0, "_id": oid}], reply.get("upserted")) # update_one self.listener.reset() res = coll.update_one({"x": 1}, {"$inc": {"x": 1}}) started = self.listener.started_events[0] succeeded = self.listener.succeeded_events[0] self.assertEqual(0, len(self.listener.failed_events)) self.assertIsInstance(started, monitoring.CommandStartedEvent) expected = SON( [ ("update", coll.name), ("ordered", True), ( "updates", [ SON( [ ("q", {"x": 1}), ("u", {"$inc": {"x": 1}}), ("multi", False), ("upsert", False), ] ) ], ), ("writeConcern", {"w": 1}), ] ) self.assertEqualCommand(expected, started.command) self.assertEqual("pymongo_test", started.database_name) self.assertEqual("update", started.command_name) self.assertIsInstance(started.request_id, int) self.assertEqual(self.client.address, started.connection_id) self.assertIsInstance(succeeded, monitoring.CommandSucceededEvent) self.assertIsInstance(succeeded.duration_micros, int) self.assertEqual(started.command_name, succeeded.command_name) self.assertEqual(started.request_id, succeeded.request_id) self.assertEqual(started.connection_id, succeeded.connection_id) reply = succeeded.reply self.assertEqual(1, reply.get("ok")) self.assertEqual(1, reply.get("n")) # update_many self.listener.reset() res = coll.update_many({"x": 2}, {"$inc": {"x": 1}}) started = self.listener.started_events[0] succeeded = self.listener.succeeded_events[0] self.assertEqual(0, len(self.listener.failed_events)) self.assertIsInstance(started, monitoring.CommandStartedEvent) expected = SON( [ ("update", coll.name), ("ordered", True), ( "updates", [ SON( [ ("q", {"x": 2}), ("u", {"$inc": {"x": 1}}), ("multi", True), ("upsert", False), ] ) ], ), ("writeConcern", {"w": 1}), ] ) self.assertEqualCommand(expected, started.command) self.assertEqual("pymongo_test", started.database_name) self.assertEqual("update", started.command_name) self.assertIsInstance(started.request_id, int) self.assertEqual(self.client.address, started.connection_id) self.assertIsInstance(succeeded, monitoring.CommandSucceededEvent) self.assertIsInstance(succeeded.duration_micros, int) self.assertEqual(started.command_name, succeeded.command_name) self.assertEqual(started.request_id, succeeded.request_id) self.assertEqual(started.connection_id, succeeded.connection_id) reply = succeeded.reply self.assertEqual(1, reply.get("ok")) self.assertEqual(1, reply.get("n")) # delete_one self.listener.reset() _ = coll.delete_one({"x": 3}) started = self.listener.started_events[0] succeeded = self.listener.succeeded_events[0] self.assertEqual(0, len(self.listener.failed_events)) self.assertIsInstance(started, monitoring.CommandStartedEvent) expected = SON( [ ("delete", coll.name), ("ordered", True), ("deletes", [SON([("q", {"x": 3}), ("limit", 1)])]), ("writeConcern", {"w": 1}), ] ) self.assertEqualCommand(expected, started.command) self.assertEqual("pymongo_test", started.database_name) self.assertEqual("delete", started.command_name) self.assertIsInstance(started.request_id, int) self.assertEqual(self.client.address, started.connection_id) self.assertIsInstance(succeeded, monitoring.CommandSucceededEvent) self.assertIsInstance(succeeded.duration_micros, int) self.assertEqual(started.command_name, succeeded.command_name) self.assertEqual(started.request_id, succeeded.request_id) self.assertEqual(started.connection_id, succeeded.connection_id) reply = succeeded.reply self.assertEqual(1, reply.get("ok")) self.assertEqual(1, reply.get("n")) self.assertEqual(0, coll.count_documents({})) # write errors coll.insert_one({"_id": 1}) try: self.listener.reset() coll.insert_one({"_id": 1}) except OperationFailure: pass started = self.listener.started_events[0] succeeded = self.listener.succeeded_events[0] self.assertEqual(0, len(self.listener.failed_events)) self.assertIsInstance(started, monitoring.CommandStartedEvent) expected = SON( [ ("insert", coll.name), ("ordered", True), ("documents", [{"_id": 1}]), ("writeConcern", {"w": 1}), ] ) self.assertEqualCommand(expected, started.command) self.assertEqual("pymongo_test", started.database_name) self.assertEqual("insert", started.command_name) self.assertIsInstance(started.request_id, int) self.assertEqual(self.client.address, started.connection_id) self.assertIsInstance(succeeded, monitoring.CommandSucceededEvent) self.assertIsInstance(succeeded.duration_micros, int) self.assertEqual(started.command_name, succeeded.command_name) self.assertEqual(started.request_id, succeeded.request_id) self.assertEqual(started.connection_id, succeeded.connection_id) reply = succeeded.reply self.assertEqual(1, reply.get("ok")) self.assertEqual(0, reply.get("n")) errors = reply.get("writeErrors") self.assertIsInstance(errors, list) error = errors[0] self.assertEqual(0, error.get("index")) self.assertIsInstance(error.get("code"), int) self.assertIsInstance(error.get("errmsg"), str) def test_insert_many(self): # This always uses the bulk API. coll = self.client.pymongo_test.test coll.drop() self.listener.reset() big = "x" * (1024 * 1024 * 4) docs = [{"_id": i, "big": big} for i in range(6)] coll.insert_many(docs) started = self.listener.started_events succeeded = self.listener.succeeded_events self.assertEqual(0, len(self.listener.failed_events)) documents = [] count = 0 operation_id = started[0].operation_id self.assertIsInstance(operation_id, int) for start, succeed in zip(started, succeeded): self.assertIsInstance(start, monitoring.CommandStartedEvent) cmd = sanitize_cmd(start.command) self.assertEqual(["insert", "ordered", "documents"], list(cmd.keys())) self.assertEqual(coll.name, cmd["insert"]) self.assertIs(True, cmd["ordered"]) documents.extend(cmd["documents"]) self.assertEqual("pymongo_test", start.database_name) self.assertEqual("insert", start.command_name) self.assertIsInstance(start.request_id, int) self.assertEqual(self.client.address, start.connection_id) self.assertIsInstance(succeed, monitoring.CommandSucceededEvent) self.assertIsInstance(succeed.duration_micros, int) self.assertEqual(start.command_name, succeed.command_name) self.assertEqual(start.request_id, succeed.request_id) self.assertEqual(start.connection_id, succeed.connection_id) self.assertEqual(start.operation_id, operation_id) self.assertEqual(succeed.operation_id, operation_id) reply = succeed.reply self.assertEqual(1, reply.get("ok")) count += reply.get("n", 0) self.assertEqual(documents, docs) self.assertEqual(6, count) def test_insert_many_unacknowledged(self): coll = self.client.pymongo_test.test coll.drop() unack_coll = coll.with_options(write_concern=WriteConcern(w=0)) self.listener.reset() # Force two batches on legacy servers. big = "x" * (1024 * 1024 * 12) docs = [{"_id": i, "big": big} for i in range(6)] unack_coll.insert_many(docs) started = self.listener.started_events succeeded = self.listener.succeeded_events self.assertEqual(0, len(self.listener.failed_events)) documents = [] operation_id = started[0].operation_id self.assertIsInstance(operation_id, int) for start, succeed in zip(started, succeeded): self.assertIsInstance(start, monitoring.CommandStartedEvent) cmd = sanitize_cmd(start.command) cmd.pop("writeConcern", None) self.assertEqual(["insert", "ordered", "documents"], list(cmd.keys())) self.assertEqual(coll.name, cmd["insert"]) self.assertIs(True, cmd["ordered"]) documents.extend(cmd["documents"]) self.assertEqual("pymongo_test", start.database_name) self.assertEqual("insert", start.command_name) self.assertIsInstance(start.request_id, int) self.assertEqual(self.client.address, start.connection_id) self.assertIsInstance(succeed, monitoring.CommandSucceededEvent) self.assertIsInstance(succeed.duration_micros, int) self.assertEqual(start.command_name, succeed.command_name) self.assertEqual(start.request_id, succeed.request_id) self.assertEqual(start.connection_id, succeed.connection_id) self.assertEqual(start.operation_id, operation_id) self.assertEqual(succeed.operation_id, operation_id) self.assertEqual(1, succeed.reply.get("ok")) self.assertEqual(documents, docs) wait_until(lambda: coll.count_documents({}) == 6, "insert documents with w=0") def test_bulk_write(self): coll = self.client.pymongo_test.test coll.drop() self.listener.reset() coll.bulk_write( [ InsertOne({"_id": 1}), UpdateOne({"_id": 1}, {"$set": {"x": 1}}), DeleteOne({"_id": 1}), ] ) started = self.listener.started_events succeeded = self.listener.succeeded_events self.assertEqual(0, len(self.listener.failed_events)) operation_id = started[0].operation_id pairs = list(zip(started, succeeded)) self.assertEqual(3, len(pairs)) for start, succeed in pairs: self.assertIsInstance(start, monitoring.CommandStartedEvent) self.assertEqual("pymongo_test", start.database_name) self.assertIsInstance(start.request_id, int) self.assertEqual(self.client.address, start.connection_id) self.assertIsInstance(succeed, monitoring.CommandSucceededEvent) self.assertIsInstance(succeed.duration_micros, int) self.assertEqual(start.command_name, succeed.command_name) self.assertEqual(start.request_id, succeed.request_id) self.assertEqual(start.connection_id, succeed.connection_id) self.assertEqual(start.operation_id, operation_id) self.assertEqual(succeed.operation_id, operation_id) expected = SON([("insert", coll.name), ("ordered", True), ("documents", [{"_id": 1}])]) self.assertEqualCommand(expected, started[0].command) expected = SON( [ ("update", coll.name), ("ordered", True), ( "updates", [ SON( [ ("q", {"_id": 1}), ("u", {"$set": {"x": 1}}), ("multi", False), ("upsert", False), ] ) ], ), ] ) self.assertEqualCommand(expected, started[1].command) expected = SON( [ ("delete", coll.name), ("ordered", True), ("deletes", [SON([("q", {"_id": 1}), ("limit", 1)])]), ] ) self.assertEqualCommand(expected, started[2].command) @client_context.require_failCommand_fail_point def test_bulk_write_command_network_error(self): coll = self.client.pymongo_test.test self.listener.reset() insert_network_error = { "configureFailPoint": "failCommand", "mode": {"times": 1}, "data": { "failCommands": ["insert"], "closeConnection": True, }, } with self.fail_point(insert_network_error): with self.assertRaises(AutoReconnect): coll.bulk_write([InsertOne({"_id": 1})]) failed = self.listener.failed_events self.assertEqual(1, len(failed)) event = failed[0] self.assertEqual(event.command_name, "insert") self.assertIsInstance(event.failure, dict) self.assertEqual(event.failure["errtype"], "AutoReconnect") self.assertTrue(event.failure["errmsg"]) @client_context.require_failCommand_fail_point def test_bulk_write_command_error(self): coll = self.client.pymongo_test.test self.listener.reset() insert_command_error = { "configureFailPoint": "failCommand", "mode": {"times": 1}, "data": { "failCommands": ["insert"], "closeConnection": False, "errorCode": 10107, # Not primary }, } with self.fail_point(insert_command_error): with self.assertRaises(NotPrimaryError): coll.bulk_write([InsertOne({"_id": 1})]) failed = self.listener.failed_events self.assertEqual(1, len(failed)) event = failed[0] self.assertEqual(event.command_name, "insert") self.assertIsInstance(event.failure, dict) self.assertEqual(event.failure["code"], 10107) self.assertTrue(event.failure["errmsg"]) def test_write_errors(self): coll = self.client.pymongo_test.test coll.drop() self.listener.reset() try: coll.bulk_write( [ InsertOne({"_id": 1}), InsertOne({"_id": 1}), InsertOne({"_id": 1}), DeleteOne({"_id": 1}), ], ordered=False, ) except OperationFailure: pass started = self.listener.started_events succeeded = self.listener.succeeded_events self.assertEqual(0, len(self.listener.failed_events)) operation_id = started[0].operation_id pairs = list(zip(started, succeeded)) errors = [] for start, succeed in pairs: self.assertIsInstance(start, monitoring.CommandStartedEvent) self.assertEqual("pymongo_test", start.database_name) self.assertIsInstance(start.request_id, int) self.assertEqual(self.client.address, start.connection_id) self.assertIsInstance(succeed, monitoring.CommandSucceededEvent) self.assertIsInstance(succeed.duration_micros, int) self.assertEqual(start.command_name, succeed.command_name) self.assertEqual(start.request_id, succeed.request_id) self.assertEqual(start.connection_id, succeed.connection_id) self.assertEqual(start.operation_id, operation_id) self.assertEqual(succeed.operation_id, operation_id) if "writeErrors" in succeed.reply: errors.extend(succeed.reply["writeErrors"]) self.assertEqual(2, len(errors)) fields = {"index", "code", "errmsg"} for error in errors: self.assertTrue(fields.issubset(set(error))) def test_first_batch_helper(self): # Regardless of server version and use of helpers._first_batch # this test should still pass. self.listener.reset() tuple(self.client.pymongo_test.test.list_indexes()) started = self.listener.started_events[0] succeeded = self.listener.succeeded_events[0] self.assertEqual(0, len(self.listener.failed_events)) self.assertIsInstance(started, monitoring.CommandStartedEvent) expected = SON([("listIndexes", "test"), ("cursor", {})]) self.assertEqualCommand(expected, started.command) self.assertEqual("pymongo_test", started.database_name) self.assertEqual("listIndexes", started.command_name) self.assertIsInstance(started.request_id, int) self.assertEqual(self.client.address, started.connection_id) self.assertIsInstance(succeeded, monitoring.CommandSucceededEvent) self.assertIsInstance(succeeded.duration_micros, int) self.assertEqual(started.command_name, succeeded.command_name) self.assertEqual(started.request_id, succeeded.request_id) self.assertEqual(started.connection_id, succeeded.connection_id) self.assertTrue("cursor" in succeeded.reply) self.assertTrue("ok" in succeeded.reply) self.listener.reset() @client_context.require_version_max(6, 1, 99) def test_sensitive_commands(self): listeners = self.client._event_listeners self.listener.reset() cmd = SON([("getnonce", 1)]) listeners.publish_command_start(cmd, "pymongo_test", 12345, self.client.address, None) # type: ignore[arg-type] delta = datetime.timedelta(milliseconds=100) listeners.publish_command_success( delta, {"nonce": "e474f4561c5eb40b", "ok": 1.0}, "getnonce", 12345, self.client.address, # type: ignore[arg-type] None, database_name="pymongo_test", ) started = self.listener.started_events[0] succeeded = self.listener.succeeded_events[0] self.assertEqual(0, len(self.listener.failed_events)) self.assertIsInstance(started, monitoring.CommandStartedEvent) self.assertEqual({}, started.command) self.assertEqual("pymongo_test", started.database_name) self.assertEqual("getnonce", started.command_name) self.assertIsInstance(started.request_id, int) self.assertEqual(self.client.address, started.connection_id) self.assertIsInstance(succeeded, monitoring.CommandSucceededEvent) self.assertEqual(succeeded.duration_micros, 100000) self.assertEqual(started.command_name, succeeded.command_name) self.assertEqual(started.request_id, succeeded.request_id) self.assertEqual(started.connection_id, succeeded.connection_id) self.assertEqual({}, succeeded.reply) class TestGlobalListener(IntegrationTest): listener: EventListener saved_listeners: Any @classmethod @client_context.require_connection def setUpClass(cls): super().setUpClass() cls.listener = EventListener() # We plan to call register(), which internally modifies _LISTENERS. cls.saved_listeners = copy.deepcopy(monitoring._LISTENERS) monitoring.register(cls.listener) cls.client = single_client() # Get one (authenticated) socket in the pool. cls.client.pymongo_test.command("ping") @classmethod def tearDownClass(cls): monitoring._LISTENERS = cls.saved_listeners cls.client.close() super().tearDownClass() def setUp(self): super().setUp() self.listener.reset() def test_simple(self): self.client.pymongo_test.command("ping") started = self.listener.started_events[0] succeeded = self.listener.succeeded_events[0] self.assertEqual(0, len(self.listener.failed_events)) self.assertTrue(isinstance(succeeded, monitoring.CommandSucceededEvent)) self.assertTrue(isinstance(started, monitoring.CommandStartedEvent)) self.assertEqualCommand(SON([("ping", 1)]), started.command) self.assertEqual("ping", started.command_name) self.assertEqual(self.client.address, started.connection_id) self.assertEqual("pymongo_test", started.database_name) self.assertTrue(isinstance(started.request_id, int)) class TestEventClasses(unittest.TestCase): def test_command_event_repr(self): request_id, connection_id, operation_id, db_name = 1, ("localhost", 27017), 2, "admin" event = monitoring.CommandStartedEvent( {"ping": 1}, db_name, request_id, connection_id, operation_id ) self.assertEqual( repr(event), "", ) delta = datetime.timedelta(milliseconds=100) event = monitoring.CommandSucceededEvent( delta, {"ok": 1}, "ping", request_id, connection_id, operation_id, database_name=db_name ) self.assertEqual( repr(event), "", ) event = monitoring.CommandFailedEvent( delta, {"ok": 0}, "ping", request_id, connection_id, operation_id, database_name=db_name ) self.assertEqual( repr(event), "", ) def test_server_heartbeat_event_repr(self): connection_id = ("localhost", 27017) event = monitoring.ServerHeartbeatStartedEvent(connection_id) self.assertEqual( repr(event), "" ) delta = 0.1 event = monitoring.ServerHeartbeatSucceededEvent( delta, {"ok": 1}, # type: ignore[arg-type] connection_id, ) self.assertEqual( repr(event), "", ) event = monitoring.ServerHeartbeatFailedEvent( delta, "ERROR", # type: ignore[arg-type] connection_id, ) self.assertEqual( repr(event), "", ) def test_server_event_repr(self): server_address = ("localhost", 27017) topology_id = ObjectId("000000000000000000000001") event = monitoring.ServerOpeningEvent(server_address, topology_id) self.assertEqual( repr(event), "", ) event = monitoring.ServerDescriptionChangedEvent( "PREV", # type: ignore[arg-type] "NEW", # type: ignore[arg-type] server_address, topology_id, ) self.assertEqual( repr(event), "", ) event = monitoring.ServerClosedEvent(server_address, topology_id) self.assertEqual( repr(event), "", ) def test_topology_event_repr(self): topology_id = ObjectId("000000000000000000000001") event = monitoring.TopologyOpenedEvent(topology_id) self.assertEqual(repr(event), "") event = monitoring.TopologyDescriptionChangedEvent( "PREV", # type: ignore[arg-type] "NEW", # type: ignore[arg-type] topology_id, ) self.assertEqual( repr(event), "", ) event = monitoring.TopologyClosedEvent(topology_id) self.assertEqual(repr(event), "") if __name__ == "__main__": unittest.main() mongodb-mongo-python-driver-509e9b7/test/test_objectid.py000066400000000000000000000174631462766011000236230ustar00rootroot00000000000000# Copyright 2009-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. """Tests for the objectid module.""" from __future__ import annotations import datetime import pickle import struct import sys sys.path[0:0] = [""] from test import SkipTest, unittest from test.utils import oid_generated_on_process from bson.errors import InvalidId from bson.objectid import _MAX_COUNTER_VALUE, ObjectId from bson.tz_util import FixedOffset, utc def oid(x): return ObjectId() class TestObjectId(unittest.TestCase): def test_creation(self): self.assertRaises(TypeError, ObjectId, 4) self.assertRaises(TypeError, ObjectId, 175.0) self.assertRaises(TypeError, ObjectId, {"test": 4}) self.assertRaises(TypeError, ObjectId, ["something"]) self.assertRaises(InvalidId, ObjectId, "") self.assertRaises(InvalidId, ObjectId, "12345678901") self.assertRaises(InvalidId, ObjectId, "1234567890123") self.assertTrue(ObjectId()) self.assertTrue(ObjectId(b"123456789012")) a = ObjectId() self.assertTrue(ObjectId(a)) def test_unicode(self): a = ObjectId() self.assertEqual(a, ObjectId(a)) self.assertRaises(InvalidId, ObjectId, "hello") def test_from_hex(self): ObjectId("123456789012123456789012") self.assertRaises(InvalidId, ObjectId, "123456789012123456789G12") def test_repr_str(self): self.assertEqual( repr(ObjectId("1234567890abcdef12345678")), "ObjectId('1234567890abcdef12345678')" ) self.assertEqual(str(ObjectId("1234567890abcdef12345678")), "1234567890abcdef12345678") self.assertEqual(str(ObjectId(b"123456789012")), "313233343536373839303132") self.assertEqual( ObjectId("1234567890abcdef12345678").binary, b"\x124Vx\x90\xab\xcd\xef\x124Vx" ) self.assertEqual( str(ObjectId(b"\x124Vx\x90\xab\xcd\xef\x124Vx")), "1234567890abcdef12345678" ) def test_equality(self): a = ObjectId() self.assertEqual(a, ObjectId(a)) self.assertEqual(ObjectId(b"123456789012"), ObjectId(b"123456789012")) self.assertNotEqual(ObjectId(), ObjectId()) self.assertNotEqual(ObjectId(b"123456789012"), b"123456789012") # Explicitly test inequality self.assertFalse(a != ObjectId(a)) self.assertFalse(ObjectId(b"123456789012") != ObjectId(b"123456789012")) def test_binary_str_equivalence(self): a = ObjectId() self.assertEqual(a, ObjectId(a.binary)) self.assertEqual(a, ObjectId(str(a))) def test_generation_time(self): d1 = datetime.datetime.now(tz=datetime.timezone.utc).replace(tzinfo=None) d2 = ObjectId().generation_time self.assertEqual(utc, d2.tzinfo) d2 = d2.replace(tzinfo=None) self.assertTrue(d2 - d1 < datetime.timedelta(seconds=2)) def test_from_datetime(self): if "PyPy 1.8.0" in sys.version: # See https://bugs.pypy.org/issue1092 raise SkipTest("datetime.timedelta is broken in pypy 1.8.0") d = datetime.datetime.now(tz=datetime.timezone.utc).replace(tzinfo=None) d = d - datetime.timedelta(microseconds=d.microsecond) oid = ObjectId.from_datetime(d) self.assertEqual(d, oid.generation_time.replace(tzinfo=None)) self.assertEqual("0" * 16, str(oid)[8:]) aware = datetime.datetime(1993, 4, 4, 2, tzinfo=FixedOffset(555, "SomeZone")) offset = aware.utcoffset() assert offset is not None as_utc = (aware - offset).replace(tzinfo=utc) oid = ObjectId.from_datetime(aware) self.assertEqual(as_utc, oid.generation_time) def test_pickling(self): orig = ObjectId() for protocol in [0, 1, 2, -1]: pkl = pickle.dumps(orig, protocol=protocol) self.assertEqual(orig, pickle.loads(pkl)) def test_pickle_backwards_compatability(self): # This string was generated by pickling an ObjectId in pymongo # version 1.9 pickled_with_1_9 = ( b"ccopy_reg\n_reconstructor\np0\n" b"(cbson.objectid\nObjectId\np1\nc__builtin__\n" b"object\np2\nNtp3\nRp4\n" b"(dp5\nS'_ObjectId__id'\np6\n" b"S'M\\x9afV\\x13v\\xc0\\x0b\\x88\\x00\\x00\\x00'\np7\nsb." ) # We also test against a hardcoded "New" pickle format so that we # make sure we're backward compatible with the current version in # the future as well. pickled_with_1_10 = ( b"ccopy_reg\n_reconstructor\np0\n" b"(cbson.objectid\nObjectId\np1\nc__builtin__\n" b"object\np2\nNtp3\nRp4\n" b"S'M\\x9afV\\x13v\\xc0\\x0b\\x88\\x00\\x00\\x00'\np5\nb." ) # Have to load using 'latin-1' since these were pickled in python2.x. oid_1_9 = pickle.loads(pickled_with_1_9, encoding="latin-1") oid_1_10 = pickle.loads(pickled_with_1_10, encoding="latin-1") self.assertEqual(oid_1_9, ObjectId("4d9a66561376c00b88000000")) self.assertEqual(oid_1_9, oid_1_10) def test_random_bytes(self): self.assertTrue(oid_generated_on_process(ObjectId())) def test_is_valid(self): self.assertFalse(ObjectId.is_valid(None)) self.assertFalse(ObjectId.is_valid(4)) self.assertFalse(ObjectId.is_valid(175.0)) self.assertFalse(ObjectId.is_valid({"test": 4})) self.assertFalse(ObjectId.is_valid(["something"])) self.assertFalse(ObjectId.is_valid("")) self.assertFalse(ObjectId.is_valid("12345678901")) self.assertFalse(ObjectId.is_valid("1234567890123")) self.assertTrue(ObjectId.is_valid(b"123456789012")) self.assertTrue(ObjectId.is_valid("123456789012123456789012")) def test_counter_overflow(self): # Spec-test to check counter overflows from max value to 0. ObjectId._inc = _MAX_COUNTER_VALUE ObjectId() self.assertEqual(ObjectId._inc, 0) def test_timestamp_values(self): # Spec-test to check timestamp field is interpreted correctly. TEST_DATA = { 0x00000000: (1970, 1, 1, 0, 0, 0), 0x7FFFFFFF: (2038, 1, 19, 3, 14, 7), 0x80000000: (2038, 1, 19, 3, 14, 8), 0xFFFFFFFF: (2106, 2, 7, 6, 28, 15), } def generate_objectid_with_timestamp(timestamp): oid = ObjectId() _, trailing_bytes = struct.unpack(">IQ", oid.binary) new_oid = struct.pack(">IQ", timestamp, trailing_bytes) return ObjectId(new_oid) for tstamp, exp_datetime_args in TEST_DATA.items(): oid = generate_objectid_with_timestamp(tstamp) # 32-bit platforms may overflow in datetime.fromtimestamp. if tstamp > 0x7FFFFFFF and sys.maxsize < 2**32: try: oid.generation_time except (OverflowError, ValueError): continue self.assertEqual(oid.generation_time, datetime.datetime(*exp_datetime_args, tzinfo=utc)) def test_random_regenerated_on_pid_change(self): # Test that change of pid triggers new random number generation. random_original = ObjectId._random() ObjectId._pid += 1 random_new = ObjectId._random() self.assertNotEqual(random_original, random_new) if __name__ == "__main__": unittest.main() mongodb-mongo-python-driver-509e9b7/test/test_ocsp_cache.py000066400000000000000000000120311462766011000241110ustar00rootroot00000000000000# Copyright 2020-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. """Test the pymongo ocsp_support module.""" from __future__ import annotations import random import sys from collections import namedtuple from datetime import datetime, timedelta, timezone from os import urandom from time import sleep from typing import Any sys.path[0:0] = [""] from test import unittest from pymongo.ocsp_cache import _OCSPCache class TestOcspCache(unittest.TestCase): MockHashAlgorithm: Any MockOcspRequest: Any MockOcspResponse: Any @classmethod def setUpClass(cls): cls.MockHashAlgorithm = namedtuple("MockHashAlgorithm", ["name"]) # type: ignore cls.MockOcspRequest = namedtuple( # type: ignore "MockOcspRequest", ["hash_algorithm", "issuer_name_hash", "issuer_key_hash", "serial_number"], ) cls.MockOcspResponse = namedtuple( # type: ignore "MockOcspResponse", ["this_update", "next_update"] ) def setUp(self): self.cache = _OCSPCache() def _create_mock_request(self): hash_algorithm = self.MockHashAlgorithm(random.choice(["sha1", "md5", "sha256"])) issuer_name_hash = urandom(8) issuer_key_hash = urandom(8) serial_number = random.randint(0, 10**10) return self.MockOcspRequest( hash_algorithm=hash_algorithm, issuer_name_hash=issuer_name_hash, issuer_key_hash=issuer_key_hash, serial_number=serial_number, ) def _create_mock_response(self, this_update_delta_seconds, next_update_delta_seconds): now = datetime.now(tz=timezone.utc).replace(tzinfo=None) this_update = now + timedelta(seconds=this_update_delta_seconds) if next_update_delta_seconds is not None: next_update = now + timedelta(seconds=next_update_delta_seconds) else: next_update = None return self.MockOcspResponse(this_update=this_update, next_update=next_update) def _add_mock_cache_entry(self, mock_request, mock_response): key = self.cache._get_cache_key(mock_request) self.cache._data[key] = mock_response def test_simple(self): # Start with 1 valid entry in the cache. request = self._create_mock_request() response = self._create_mock_response(-10, +3600) self._add_mock_cache_entry(request, response) # Ensure entry can be retrieved. self.assertEqual(self.cache[request], response) # Valid entries with an earlier next_update have no effect. response_1 = self._create_mock_response(-20, +1800) self.cache[request] = response_1 self.assertEqual(self.cache[request], response) # Invalid entries with a later this_update have no effect. response_2 = self._create_mock_response(+20, +1800) self.cache[request] = response_2 self.assertEqual(self.cache[request], response) # Invalid entries with passed next_update have no effect. response_3 = self._create_mock_response(-10, -5) self.cache[request] = response_3 self.assertEqual(self.cache[request], response) # Valid entries with a later next_update update the cache. response_new = self._create_mock_response(-5, +7200) self.cache[request] = response_new self.assertEqual(self.cache[request], response_new) # Entries with an unset next_update purge the cache. response_notset = self._create_mock_response(-5, None) self.cache[request] = response_notset with self.assertRaises(KeyError): _ = self.cache[request] def test_invalidate(self): # Start with 1 valid entry in the cache. request = self._create_mock_request() response = self._create_mock_response(-10, +0.25) self._add_mock_cache_entry(request, response) # Ensure entry can be retrieved. self.assertEqual(self.cache[request], response) # Wait for entry to become invalid and ensure KeyError is raised. sleep(0.5) with self.assertRaises(KeyError): _ = self.cache[request] def test_non_existent(self): # Start with 1 valid entry in the cache. request = self._create_mock_request() response = self._create_mock_response(-10, +10) self._add_mock_cache_entry(request, response) # Attempt to retrieve non-existent entry must raise KeyError. with self.assertRaises(KeyError): _ = self.cache[self._create_mock_request()] if __name__ == "__main__": unittest.main() mongodb-mongo-python-driver-509e9b7/test/test_on_demand_csfle.py000066400000000000000000000101321462766011000251220ustar00rootroot00000000000000# Copyright 2022-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. """Test client side encryption with on demand credentials.""" from __future__ import annotations import os import sys import unittest sys.path[0:0] = [""] from test import IntegrationTest, client_context from bson.codec_options import CodecOptions from pymongo.encryption import _HAVE_PYMONGOCRYPT, ClientEncryption, EncryptionError class TestonDemandGCPCredentials(IntegrationTest): @classmethod @unittest.skipUnless(_HAVE_PYMONGOCRYPT, "pymongocrypt is not installed") @client_context.require_version_min(4, 2, -1) def setUpClass(cls): super().setUpClass() def setUp(self): super().setUp() self.master_key = { "projectId": "devprod-drivers", "location": "global", "keyRing": "key-ring-csfle", "keyName": "key-name-csfle", } @unittest.skipIf(not os.getenv("TEST_FLE_GCP_AUTO"), "Not testing FLE GCP auto") def test_01_failure(self): if os.environ["SUCCESS"].lower() == "true": self.skipTest("Expecting success") self.client_encryption = ClientEncryption( kms_providers={"gcp": {}}, key_vault_namespace="keyvault.datakeys", key_vault_client=client_context.client, codec_options=CodecOptions(), ) with self.assertRaises(EncryptionError): self.client_encryption.create_data_key("gcp", self.master_key) @unittest.skipIf(not os.getenv("TEST_FLE_GCP_AUTO"), "Not testing FLE GCP auto") def test_02_success(self): if os.environ["SUCCESS"].lower() == "false": self.skipTest("Expecting failure") self.client_encryption = ClientEncryption( kms_providers={"gcp": {}}, key_vault_namespace="keyvault.datakeys", key_vault_client=client_context.client, codec_options=CodecOptions(), ) self.client_encryption.create_data_key("gcp", self.master_key) class TestonDemandAzureCredentials(IntegrationTest): @classmethod @unittest.skipUnless(_HAVE_PYMONGOCRYPT, "pymongocrypt is not installed") @client_context.require_version_min(4, 2, -1) def setUpClass(cls): super().setUpClass() def setUp(self): super().setUp() self.master_key = { "keyVaultEndpoint": os.environ["KEY_VAULT_ENDPOINT"], "keyName": os.environ["KEY_NAME"], } @unittest.skipIf(not os.getenv("TEST_FLE_AZURE_AUTO"), "Not testing FLE Azure auto") def test_01_failure(self): if os.environ["SUCCESS"].lower() == "true": self.skipTest("Expecting success") self.client_encryption = ClientEncryption( kms_providers={"azure": {}}, key_vault_namespace="keyvault.datakeys", key_vault_client=client_context.client, codec_options=CodecOptions(), ) with self.assertRaises(EncryptionError): self.client_encryption.create_data_key("azure", self.master_key) @unittest.skipIf(not os.getenv("TEST_FLE_AZURE_AUTO"), "Not testing FLE Azure auto") def test_02_success(self): if os.environ["SUCCESS"].lower() == "false": self.skipTest("Expecting failure") self.client_encryption = ClientEncryption( kms_providers={"azure": {}}, key_vault_namespace="keyvault.datakeys", key_vault_client=client_context.client, codec_options=CodecOptions(), ) self.client_encryption.create_data_key("azure", self.master_key) if __name__ == "__main__": unittest.main(verbosity=2) mongodb-mongo-python-driver-509e9b7/test/test_pooling.py000066400000000000000000000477231462766011000235110ustar00rootroot00000000000000# Copyright 2009-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. """Test built in connection-pooling with threads.""" from __future__ import annotations import gc import random import socket import sys import threading import time from bson.codec_options import DEFAULT_CODEC_OPTIONS from bson.son import SON from pymongo import MongoClient, message, timeout from pymongo.errors import AutoReconnect, ConnectionFailure, DuplicateKeyError from pymongo.hello import HelloCompat sys.path[0:0] = [""] from test import IntegrationTest, client_context, unittest from test.utils import delay, get_pool, joinall, rs_or_single_client from pymongo.pool import Pool, PoolOptions from pymongo.socket_checker import SocketChecker @client_context.require_connection def setUpModule(): pass N = 10 DB = "pymongo-pooling-tests" def gc_collect_until_done(threads, timeout=60): start = time.time() running = list(threads) while running: assert (time.time() - start) < timeout, "Threads timed out" for t in running: t.join(0.1) if not t.is_alive(): running.remove(t) gc.collect() class MongoThread(threading.Thread): """A thread that uses a MongoClient.""" def __init__(self, client): super().__init__() self.daemon = True # Don't hang whole test if thread hangs. self.client = client self.db = self.client[DB] self.passed = False def run(self): self.run_mongo_thread() self.passed = True def run_mongo_thread(self): raise NotImplementedError class InsertOneAndFind(MongoThread): def run_mongo_thread(self): for _ in range(N): rand = random.randint(0, N) _id = self.db.sf.insert_one({"x": rand}).inserted_id assert rand == self.db.sf.find_one(_id)["x"] class Unique(MongoThread): def run_mongo_thread(self): for _ in range(N): self.db.unique.insert_one({}) # no error class NonUnique(MongoThread): def run_mongo_thread(self): for _ in range(N): try: self.db.unique.insert_one({"_id": "jesse"}) except DuplicateKeyError: pass else: raise AssertionError("Should have raised DuplicateKeyError") class SocketGetter(MongoThread): """Utility for TestPooling. Checks out a socket and holds it forever. Used in test_no_wait_queue_timeout. """ def __init__(self, client, pool): super().__init__(client) self.state = "init" self.pool = pool self.sock = None def run_mongo_thread(self): self.state = "get_socket" # Call 'pin_cursor' so we can hold the socket. with self.pool.checkout() as sock: sock.pin_cursor() self.sock = sock self.state = "connection" def __del__(self): if self.sock: self.sock.close_conn(None) def run_cases(client, cases): threads = [] n_runs = 5 for case in cases: for _i in range(n_runs): t = case(client) t.start() threads.append(t) for t in threads: t.join() for t in threads: assert t.passed, "%s.run() threw an exception" % repr(t) class _TestPoolingBase(IntegrationTest): """Base class for all connection-pool tests.""" def setUp(self): super().setUp() self.c = rs_or_single_client() db = self.c[DB] db.unique.drop() db.test.drop() db.unique.insert_one({"_id": "jesse"}) db.test.insert_many([{} for _ in range(10)]) def tearDown(self): self.c.close() super().tearDown() def create_pool(self, pair=(client_context.host, client_context.port), *args, **kwargs): # Start the pool with the correct ssl options. pool_options = client_context.client._topology_settings.pool_options kwargs["ssl_context"] = pool_options._ssl_context kwargs["tls_allow_invalid_hostnames"] = pool_options.tls_allow_invalid_hostnames kwargs["server_api"] = pool_options.server_api pool = Pool(pair, PoolOptions(*args, **kwargs)) pool.ready() return pool class TestPooling(_TestPoolingBase): def test_max_pool_size_validation(self): host, port = client_context.host, client_context.port self.assertRaises(ValueError, MongoClient, host=host, port=port, maxPoolSize=-1) self.assertRaises(ValueError, MongoClient, host=host, port=port, maxPoolSize="foo") c = MongoClient(host=host, port=port, maxPoolSize=100, connect=False) self.assertEqual(c.options.pool_options.max_pool_size, 100) def test_no_disconnect(self): run_cases(self.c, [NonUnique, Unique, InsertOneAndFind]) def test_pool_reuses_open_socket(self): # Test Pool's _check_closed() method doesn't close a healthy socket. cx_pool = self.create_pool(max_pool_size=10) cx_pool._check_interval_seconds = 0 # Always check. with cx_pool.checkout() as conn: pass with cx_pool.checkout() as new_connection: self.assertEqual(conn, new_connection) self.assertEqual(1, len(cx_pool.conns)) def test_get_socket_and_exception(self): # get_socket() returns socket after a non-network error. cx_pool = self.create_pool(max_pool_size=1, wait_queue_timeout=1) with self.assertRaises(ZeroDivisionError): with cx_pool.checkout() as conn: 1 / 0 # Socket was returned, not closed. with cx_pool.checkout() as new_connection: self.assertEqual(conn, new_connection) self.assertEqual(1, len(cx_pool.conns)) def test_pool_removes_closed_socket(self): # Test that Pool removes explicitly closed socket. cx_pool = self.create_pool() with cx_pool.checkout() as conn: # Use Connection's API to close the socket. conn.close_conn(None) self.assertEqual(0, len(cx_pool.conns)) def test_pool_removes_dead_socket(self): # Test that Pool removes dead socket and the socket doesn't return # itself PYTHON-344 cx_pool = self.create_pool(max_pool_size=1, wait_queue_timeout=1) cx_pool._check_interval_seconds = 0 # Always check. with cx_pool.checkout() as conn: # Simulate a closed socket without telling the Connection it's # closed. conn.conn.close() self.assertTrue(conn.conn_closed()) with cx_pool.checkout() as new_connection: self.assertEqual(0, len(cx_pool.conns)) self.assertNotEqual(conn, new_connection) self.assertEqual(1, len(cx_pool.conns)) # Semaphore was released. with cx_pool.checkout(): pass def test_socket_closed(self): s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.connect((client_context.host, client_context.port)) socket_checker = SocketChecker() self.assertFalse(socket_checker.socket_closed(s)) s.close() self.assertTrue(socket_checker.socket_closed(s)) def test_socket_checker(self): s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.connect((client_context.host, client_context.port)) socket_checker = SocketChecker() # Socket has nothing to read. self.assertFalse(socket_checker.select(s, read=True)) self.assertFalse(socket_checker.select(s, read=True, timeout=0)) self.assertFalse(socket_checker.select(s, read=True, timeout=0.05)) # Socket is writable. self.assertTrue(socket_checker.select(s, write=True, timeout=None)) self.assertTrue(socket_checker.select(s, write=True)) self.assertTrue(socket_checker.select(s, write=True, timeout=0)) self.assertTrue(socket_checker.select(s, write=True, timeout=0.05)) # Make the socket readable _, msg, _ = message._query( 0, "admin.$cmd", 0, -1, SON([("ping", 1)]), None, DEFAULT_CODEC_OPTIONS ) s.sendall(msg) # Block until the socket is readable. self.assertTrue(socket_checker.select(s, read=True, timeout=None)) self.assertTrue(socket_checker.select(s, read=True)) self.assertTrue(socket_checker.select(s, read=True, timeout=0)) self.assertTrue(socket_checker.select(s, read=True, timeout=0.05)) # Socket is still writable. self.assertTrue(socket_checker.select(s, write=True, timeout=None)) self.assertTrue(socket_checker.select(s, write=True)) self.assertTrue(socket_checker.select(s, write=True, timeout=0)) self.assertTrue(socket_checker.select(s, write=True, timeout=0.05)) s.close() self.assertTrue(socket_checker.socket_closed(s)) def test_return_socket_after_reset(self): pool = self.create_pool() with pool.checkout() as sock: self.assertEqual(pool.active_sockets, 1) self.assertEqual(pool.operation_count, 1) pool.reset() self.assertTrue(sock.closed) self.assertEqual(0, len(pool.conns)) self.assertEqual(pool.active_sockets, 0) self.assertEqual(pool.operation_count, 0) def test_pool_check(self): # Test that Pool recovers from two connection failures in a row. # This exercises code at the end of Pool._check(). cx_pool = self.create_pool(max_pool_size=1, connect_timeout=1, wait_queue_timeout=1) cx_pool._check_interval_seconds = 0 # Always check. self.addCleanup(cx_pool.close) with cx_pool.checkout() as conn: # Simulate a closed socket without telling the Connection it's # closed. conn.conn.close() # Swap pool's address with a bad one. address, cx_pool.address = cx_pool.address, ("foo.com", 1234) with self.assertRaises(AutoReconnect): with cx_pool.checkout(): pass # Back to normal, semaphore was correctly released. cx_pool.address = address with cx_pool.checkout(): pass def test_wait_queue_timeout(self): wait_queue_timeout = 2 # Seconds pool = self.create_pool(max_pool_size=1, wait_queue_timeout=wait_queue_timeout) self.addCleanup(pool.close) with pool.checkout(): start = time.time() with self.assertRaises(ConnectionFailure): with pool.checkout(): pass duration = time.time() - start self.assertTrue( abs(wait_queue_timeout - duration) < 1, f"Waited {duration:.2f} seconds for a socket, expected {wait_queue_timeout:f}", ) def test_no_wait_queue_timeout(self): # Verify get_socket() with no wait_queue_timeout blocks forever. pool = self.create_pool(max_pool_size=1) self.addCleanup(pool.close) # Reach max_size. with pool.checkout() as s1: t = SocketGetter(self.c, pool) t.start() while t.state != "get_socket": time.sleep(0.1) time.sleep(1) self.assertEqual(t.state, "get_socket") while t.state != "connection": time.sleep(0.1) self.assertEqual(t.state, "connection") self.assertEqual(t.sock, s1) def test_checkout_more_than_max_pool_size(self): pool = self.create_pool(max_pool_size=2) socks = [] for _ in range(2): # Call 'pin_cursor' so we can hold the socket. with pool.checkout() as sock: sock.pin_cursor() socks.append(sock) threads = [] for _ in range(30): t = SocketGetter(self.c, pool) t.start() threads.append(t) time.sleep(1) for t in threads: self.assertEqual(t.state, "get_socket") for socket_info in socks: socket_info.close_conn(None) def test_maxConnecting(self): client = rs_or_single_client() self.addCleanup(client.close) self.client.test.test.insert_one({}) self.addCleanup(self.client.test.test.delete_many, {}) pool = get_pool(client) docs = [] # Run 50 short running operations def find_one(): docs.append(client.test.test.find_one({})) threads = [threading.Thread(target=find_one) for _ in range(50)] for thread in threads: thread.start() for thread in threads: thread.join(10) self.assertEqual(len(docs), 50) self.assertLessEqual(len(pool.conns), 50) # TLS and auth make connection establishment more expensive than # the query which leads to more threads hitting maxConnecting. # The end result is fewer total connections and better latency. if client_context.tls and client_context.auth_enabled: self.assertLessEqual(len(pool.conns), 30) else: self.assertLessEqual(len(pool.conns), 50) # MongoDB 4.4.1 with auth + ssl: # maxConnecting = 2: 6 connections in ~0.231+ seconds # maxConnecting = unbounded: 50 connections in ~0.642+ seconds # # MongoDB 4.4.1 with no-auth no-ssl Python 3.8: # maxConnecting = 2: 15-22 connections in ~0.108+ seconds # maxConnecting = unbounded: 30+ connections in ~0.140+ seconds print(len(pool.conns)) @client_context.require_failCommand_fail_point def test_csot_timeout_message(self): client = rs_or_single_client(appName="connectionTimeoutApp") # Mock a connection failing due to timeout. mock_connection_timeout = { "configureFailPoint": "failCommand", "mode": "alwaysOn", "data": { "blockConnection": True, "blockTimeMS": 1000, "failCommands": ["find"], "appName": "connectionTimeoutApp", }, } client.db.t.insert_one({"x": 1}) with self.fail_point(mock_connection_timeout): with self.assertRaises(Exception) as error: with timeout(0.5): client.db.t.find_one({"$where": delay(2)}) self.assertTrue("(configured timeouts: timeoutMS: 500.0ms" in str(error.exception)) @client_context.require_failCommand_fail_point def test_socket_timeout_message(self): client = rs_or_single_client(socketTimeoutMS=500, appName="connectionTimeoutApp") # Mock a connection failing due to timeout. mock_connection_timeout = { "configureFailPoint": "failCommand", "mode": "alwaysOn", "data": { "blockConnection": True, "blockTimeMS": 1000, "failCommands": ["find"], "appName": "connectionTimeoutApp", }, } client.db.t.insert_one({"x": 1}) with self.fail_point(mock_connection_timeout): with self.assertRaises(Exception) as error: client.db.t.find_one({"$where": delay(2)}) self.assertTrue( "(configured timeouts: socketTimeoutMS: 500.0ms, connectTimeoutMS: 20000.0ms)" in str(error.exception) ) @client_context.require_failCommand_fail_point @client_context.require_version_min( 4, 9, 0 ) # configureFailPoint does not allow failure on handshake before 4.9, fixed in SERVER-49336 def test_connection_timeout_message(self): # Mock a connection failing due to timeout. mock_connection_timeout = { "configureFailPoint": "failCommand", "mode": "alwaysOn", "data": { "blockConnection": True, "blockTimeMS": 1000, "failCommands": [HelloCompat.LEGACY_CMD, "hello"], "appName": "connectionTimeoutApp", }, } with self.fail_point(mock_connection_timeout): with self.assertRaises(Exception) as error: client = rs_or_single_client(connectTimeoutMS=500, appName="connectionTimeoutApp") client.admin.command("ping") self.assertTrue( "(configured timeouts: socketTimeoutMS: 500.0ms, connectTimeoutMS: 500.0ms)" in str(error.exception) ) class TestPoolMaxSize(_TestPoolingBase): def test_max_pool_size(self): max_pool_size = 4 c = rs_or_single_client(maxPoolSize=max_pool_size) self.addCleanup(c.close) collection = c[DB].test # Need one document. collection.drop() collection.insert_one({}) # nthreads had better be much larger than max_pool_size to ensure that # max_pool_size connections are actually required at some point in this # test's execution. cx_pool = get_pool(c) nthreads = 10 threads = [] lock = threading.Lock() self.n_passed = 0 def f(): for _ in range(5): collection.find_one({"$where": delay(0.1)}) assert len(cx_pool.conns) <= max_pool_size with lock: self.n_passed += 1 for _i in range(nthreads): t = threading.Thread(target=f) threads.append(t) t.start() joinall(threads) self.assertEqual(nthreads, self.n_passed) self.assertTrue(len(cx_pool.conns) > 1) self.assertEqual(0, cx_pool.requests) def test_max_pool_size_none(self): c = rs_or_single_client(maxPoolSize=None) self.addCleanup(c.close) collection = c[DB].test # Need one document. collection.drop() collection.insert_one({}) cx_pool = get_pool(c) nthreads = 10 threads = [] lock = threading.Lock() self.n_passed = 0 def f(): for _ in range(5): collection.find_one({"$where": delay(0.1)}) with lock: self.n_passed += 1 for _i in range(nthreads): t = threading.Thread(target=f) threads.append(t) t.start() joinall(threads) self.assertEqual(nthreads, self.n_passed) self.assertTrue(len(cx_pool.conns) > 1) self.assertEqual(cx_pool.max_pool_size, float("inf")) def test_max_pool_size_zero(self): c = rs_or_single_client(maxPoolSize=0) self.addCleanup(c.close) pool = get_pool(c) self.assertEqual(pool.max_pool_size, float("inf")) def test_max_pool_size_with_connection_failure(self): # The pool acquires its semaphore before attempting to connect; ensure # it releases the semaphore on connection failure. test_pool = Pool( ("somedomainthatdoesntexist.org", 27017), PoolOptions(max_pool_size=1, connect_timeout=1, socket_timeout=1, wait_queue_timeout=1), ) test_pool.ready() # First call to get_socket fails; if pool doesn't release its semaphore # then the second call raises "ConnectionFailure: Timed out waiting for # socket from pool" instead of AutoReconnect. for _i in range(2): with self.assertRaises(AutoReconnect) as context: with test_pool.checkout(): pass # Testing for AutoReconnect instead of ConnectionFailure, above, # is sufficient right *now* to catch a semaphore leak. But that # seems error-prone, so check the message too. self.assertNotIn("waiting for socket from pool", str(context.exception)) if __name__ == "__main__": unittest.main() mongodb-mongo-python-driver-509e9b7/test/test_pymongo.py000066400000000000000000000017601462766011000235210ustar00rootroot00000000000000# Copyright 2009-2015 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. """Test the pymongo module itself.""" from __future__ import annotations import sys sys.path[0:0] = [""] from test import unittest import pymongo class TestPyMongo(unittest.TestCase): def test_mongo_client_alias(self): # Testing that pymongo module imports mongo_client.MongoClient self.assertEqual(pymongo.MongoClient, pymongo.mongo_client.MongoClient) if __name__ == "__main__": unittest.main() mongodb-mongo-python-driver-509e9b7/test/test_raw_bson.py000066400000000000000000000203651462766011000236450ustar00rootroot00000000000000# Copyright 2015-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. from __future__ import annotations import datetime import sys import uuid sys.path[0:0] = [""] from test import client_context, unittest from test.test_client import IntegrationTest from bson import Code, DBRef, decode, encode from bson.binary import JAVA_LEGACY, Binary, UuidRepresentation from bson.codec_options import CodecOptions from bson.errors import InvalidBSON from bson.raw_bson import DEFAULT_RAW_BSON_OPTIONS, RawBSONDocument from bson.son import SON class TestRawBSONDocument(IntegrationTest): # {'_id': ObjectId('556df68b6e32ab21a95e0785'), # 'name': 'Sherlock', # 'addresses': [{'street': 'Baker Street'}]} bson_string = ( b"Z\x00\x00\x00\x07_id\x00Um\xf6\x8bn2\xab!\xa9^\x07\x85\x02name\x00\t" b"\x00\x00\x00Sherlock\x00\x04addresses\x00&\x00\x00\x00\x030\x00\x1e" b"\x00\x00\x00\x02street\x00\r\x00\x00\x00Baker Street\x00\x00\x00\x00" ) document = RawBSONDocument(bson_string) def tearDown(self): if client_context.connected: self.client.pymongo_test.test_raw.drop() def test_decode(self): self.assertEqual("Sherlock", self.document["name"]) first_address = self.document["addresses"][0] self.assertIsInstance(first_address, RawBSONDocument) self.assertEqual("Baker Street", first_address["street"]) def test_raw(self): self.assertEqual(self.bson_string, self.document.raw) def test_empty_doc(self): doc = RawBSONDocument(encode({})) with self.assertRaises(KeyError): doc["does-not-exist"] def test_invalid_bson_sequence(self): bson_byte_sequence = encode({"a": 1}) + encode({}) with self.assertRaisesRegex(InvalidBSON, "invalid object length"): RawBSONDocument(bson_byte_sequence) def test_invalid_bson_eoo(self): invalid_bson_eoo = encode({"a": 1})[:-1] + b"\x01" with self.assertRaisesRegex(InvalidBSON, "bad eoo"): RawBSONDocument(invalid_bson_eoo) @client_context.require_connection def test_round_trip(self): db = self.client.get_database( "pymongo_test", codec_options=CodecOptions(document_class=RawBSONDocument) ) db.test_raw.insert_one(self.document) result = db.test_raw.find_one(self.document["_id"]) assert result is not None self.assertIsInstance(result, RawBSONDocument) self.assertEqual(dict(self.document.items()), dict(result.items())) @client_context.require_connection def test_round_trip_raw_uuid(self): coll = self.client.get_database("pymongo_test").test_raw uid = uuid.uuid4() doc = {"_id": 1, "bin4": Binary(uid.bytes, 4), "bin3": Binary(uid.bytes, 3)} raw = RawBSONDocument(encode(doc)) coll.insert_one(raw) self.assertEqual(coll.find_one(), doc) uuid_coll = coll.with_options( codec_options=coll.codec_options.with_options( uuid_representation=UuidRepresentation.STANDARD ) ) self.assertEqual( uuid_coll.find_one(), {"_id": 1, "bin4": uid, "bin3": Binary(uid.bytes, 3)} ) # Test that the raw bytes haven't changed. raw_coll = coll.with_options(codec_options=DEFAULT_RAW_BSON_OPTIONS) self.assertEqual(raw_coll.find_one(), raw) def test_with_codec_options(self): # {'date': datetime.datetime(2015, 6, 3, 18, 40, 50, 826000), # '_id': UUID('026fab8f-975f-4965-9fbf-85ad874c60ff')} # encoded with JAVA_LEGACY uuid representation. bson_string = ( b"-\x00\x00\x00\x05_id\x00\x10\x00\x00\x00\x03eI_\x97\x8f\xabo\x02" b"\xff`L\x87\xad\x85\xbf\x9f\tdate\x00\x8a\xd6\xb9\xbaM" b"\x01\x00\x00\x00" ) document = RawBSONDocument( bson_string, codec_options=CodecOptions( uuid_representation=JAVA_LEGACY, document_class=RawBSONDocument ), ) self.assertEqual(uuid.UUID("026fab8f-975f-4965-9fbf-85ad874c60ff"), document["_id"]) @client_context.require_connection def test_round_trip_codec_options(self): doc = { "date": datetime.datetime(2015, 6, 3, 18, 40, 50, 826000), "_id": uuid.UUID("026fab8f-975f-4965-9fbf-85ad874c60ff"), } db = self.client.pymongo_test coll = db.get_collection( "test_raw", codec_options=CodecOptions(uuid_representation=JAVA_LEGACY) ) coll.insert_one(doc) raw_java_legacy = CodecOptions( uuid_representation=JAVA_LEGACY, document_class=RawBSONDocument ) coll = db.get_collection("test_raw", codec_options=raw_java_legacy) self.assertEqual( RawBSONDocument(encode(doc, codec_options=raw_java_legacy)), coll.find_one() ) @client_context.require_connection def test_raw_bson_document_embedded(self): doc = {"embedded": self.document} db = self.client.pymongo_test db.test_raw.insert_one(doc) result = db.test_raw.find_one() assert result is not None self.assertEqual(decode(self.document.raw), result["embedded"]) # Make sure that CodecOptions are preserved. # {'embedded': [ # {'date': datetime.datetime(2015, 6, 3, 18, 40, 50, 826000), # '_id': UUID('026fab8f-975f-4965-9fbf-85ad874c60ff')} # ]} # encoded with JAVA_LEGACY uuid representation. bson_string = ( b"D\x00\x00\x00\x04embedded\x005\x00\x00\x00\x030\x00-\x00\x00\x00" b"\tdate\x00\x8a\xd6\xb9\xbaM\x01\x00\x00\x05_id\x00\x10\x00\x00" b"\x00\x03eI_\x97\x8f\xabo\x02\xff`L\x87\xad\x85\xbf\x9f\x00\x00" b"\x00" ) rbd = RawBSONDocument( bson_string, codec_options=CodecOptions( uuid_representation=JAVA_LEGACY, document_class=RawBSONDocument ), ) db.test_raw.drop() db.test_raw.insert_one(rbd) result = db.get_collection( "test_raw", codec_options=CodecOptions(uuid_representation=JAVA_LEGACY) ).find_one() assert result is not None self.assertEqual(rbd["embedded"][0]["_id"], result["embedded"][0]["_id"]) @client_context.require_connection def test_write_response_raw_bson(self): coll = self.client.get_database( "pymongo_test", codec_options=CodecOptions(document_class=RawBSONDocument) ).test_raw # No Exceptions raised while handling write response. coll.insert_one(self.document) coll.delete_one(self.document) coll.insert_many([self.document]) coll.delete_many(self.document) coll.update_one(self.document, {"$set": {"a": "b"}}, upsert=True) coll.update_many(self.document, {"$set": {"b": "c"}}) def test_preserve_key_ordering(self): keyvaluepairs = [ ("a", 1), ("b", 2), ("c", 3), ] rawdoc = RawBSONDocument(encode(SON(keyvaluepairs))) for rkey, elt in zip(rawdoc, keyvaluepairs): self.assertEqual(rkey, elt[0]) def test_contains_code_with_scope(self): doc = RawBSONDocument(encode({"value": Code("x=1", scope={})})) self.assertEqual(decode(encode(doc)), {"value": Code("x=1", {})}) self.assertEqual(doc["value"].scope, RawBSONDocument(encode({}))) def test_contains_dbref(self): doc = RawBSONDocument(encode({"value": DBRef("test", "id")})) raw = {"$ref": "test", "$id": "id"} raw_encoded = encode(decode(encode(raw))) self.assertEqual(decode(encode(doc)), {"value": DBRef("test", "id")}) self.assertEqual(doc["value"].raw, raw_encoded) if __name__ == "__main__": unittest.main() mongodb-mongo-python-driver-509e9b7/test/test_read_concern.py000066400000000000000000000105671462766011000244600ustar00rootroot00000000000000# Copyright 2015-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. """Test the read_concern module.""" from __future__ import annotations import sys import unittest sys.path[0:0] = [""] from test import IntegrationTest, client_context from test.utils import OvertCommandListener, rs_or_single_client from bson.son import SON from pymongo.errors import OperationFailure from pymongo.read_concern import ReadConcern class TestReadConcern(IntegrationTest): listener: OvertCommandListener @classmethod @client_context.require_connection def setUpClass(cls): super().setUpClass() cls.listener = OvertCommandListener() cls.client = rs_or_single_client(event_listeners=[cls.listener]) cls.db = cls.client.pymongo_test client_context.client.pymongo_test.create_collection("coll") @classmethod def tearDownClass(cls): cls.client.close() client_context.client.pymongo_test.drop_collection("coll") super().tearDownClass() def tearDown(self): self.listener.reset() super().tearDown() def test_read_concern(self): rc = ReadConcern() self.assertIsNone(rc.level) self.assertTrue(rc.ok_for_legacy) rc = ReadConcern("majority") self.assertEqual("majority", rc.level) self.assertFalse(rc.ok_for_legacy) rc = ReadConcern("local") self.assertEqual("local", rc.level) self.assertTrue(rc.ok_for_legacy) self.assertRaises(TypeError, ReadConcern, 42) def test_read_concern_uri(self): uri = f"mongodb://{client_context.pair}/?readConcernLevel=majority" client = rs_or_single_client(uri, connect=False) self.assertEqual(ReadConcern("majority"), client.read_concern) def test_invalid_read_concern(self): coll = self.db.get_collection("coll", read_concern=ReadConcern("unknown")) # We rely on the server to validate read concern. with self.assertRaises(OperationFailure): coll.find_one() def test_find_command(self): # readConcern not sent in command if not specified. coll = self.db.coll tuple(coll.find({"field": "value"})) self.assertNotIn("readConcern", self.listener.started_events[0].command) self.listener.reset() # Explicitly set readConcern to 'local'. coll = self.db.get_collection("coll", read_concern=ReadConcern("local")) tuple(coll.find({"field": "value"})) self.assertEqualCommand( SON( [ ("find", "coll"), ("filter", {"field": "value"}), ("readConcern", {"level": "local"}), ] ), self.listener.started_events[0].command, ) def test_command_cursor(self): # readConcern not sent in command if not specified. coll = self.db.coll tuple(coll.aggregate([{"$match": {"field": "value"}}])) self.assertNotIn("readConcern", self.listener.started_events[0].command) self.listener.reset() # Explicitly set readConcern to 'local'. coll = self.db.get_collection("coll", read_concern=ReadConcern("local")) tuple(coll.aggregate([{"$match": {"field": "value"}}])) self.assertEqual({"level": "local"}, self.listener.started_events[0].command["readConcern"]) def test_aggregate_out(self): coll = self.db.get_collection("coll", read_concern=ReadConcern("local")) tuple(coll.aggregate([{"$match": {"field": "value"}}, {"$out": "output_collection"}])) # Aggregate with $out supports readConcern MongoDB 4.2 onwards. if client_context.version >= (4, 1): self.assertIn("readConcern", self.listener.started_events[0].command) else: self.assertNotIn("readConcern", self.listener.started_events[0].command) if __name__ == "__main__": unittest.main() mongodb-mongo-python-driver-509e9b7/test/test_read_preferences.py000066400000000000000000000631331462766011000253270ustar00rootroot00000000000000# Copyright 2011-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. """Test the replica_set_connection module.""" from __future__ import annotations import contextlib import copy import pickle import random import sys from typing import Any from pymongo.operations import _Op sys.path[0:0] = [""] from test import IntegrationTest, SkipTest, client_context, unittest from test.utils import ( OvertCommandListener, connected, one, rs_client, single_client, wait_until, ) from test.version import Version from bson.son import SON from pymongo.errors import ConfigurationError, OperationFailure from pymongo.message import _maybe_add_read_preference from pymongo.mongo_client import MongoClient from pymongo.read_preferences import ( MovingAverage, Nearest, Primary, PrimaryPreferred, ReadPreference, Secondary, SecondaryPreferred, ) from pymongo.server_description import ServerDescription from pymongo.server_selectors import Selection, readable_server_selector from pymongo.server_type import SERVER_TYPE from pymongo.write_concern import WriteConcern class TestSelections(IntegrationTest): @client_context.require_connection def test_bool(self): client = single_client() wait_until(lambda: client.address, "discover primary") selection = Selection.from_topology_description(client._topology.description) self.assertTrue(selection) self.assertFalse(selection.with_server_descriptions([])) class TestReadPreferenceObjects(unittest.TestCase): prefs = [ Primary(), PrimaryPreferred(), Secondary(), Nearest(tag_sets=[{"a": 1}, {"b": 2}]), SecondaryPreferred(max_staleness=30), ] def test_pickle(self): for pref in self.prefs: self.assertEqual(pref, pickle.loads(pickle.dumps(pref))) def test_copy(self): for pref in self.prefs: self.assertEqual(pref, copy.copy(pref)) def test_deepcopy(self): for pref in self.prefs: self.assertEqual(pref, copy.deepcopy(pref)) class TestReadPreferencesBase(IntegrationTest): @classmethod @client_context.require_secondaries_count(1) def setUpClass(cls): super().setUpClass() def setUp(self): super().setUp() # Insert some data so we can use cursors in read_from_which_host self.client.pymongo_test.test.drop() self.client.get_database( "pymongo_test", write_concern=WriteConcern(w=client_context.w) ).test.insert_many([{"_id": i} for i in range(10)]) self.addCleanup(self.client.pymongo_test.test.drop) def read_from_which_host(self, client): """Do a find() on the client and return which host was used""" cursor = client.pymongo_test.test.find() next(cursor) return cursor.address def read_from_which_kind(self, client): """Do a find() on the client and return 'primary' or 'secondary' depending on which the client used. """ address = self.read_from_which_host(client) if address == client.primary: return "primary" elif address in client.secondaries: return "secondary" else: self.fail( f"Cursor used address {address}, expected either primary " f"{client.primary} or secondaries {client.secondaries}" ) return None def assertReadsFrom(self, expected, **kwargs): c = rs_client(**kwargs) wait_until(lambda: len(c.nodes - c.arbiters) == client_context.w, "discovered all nodes") used = self.read_from_which_kind(c) self.assertEqual(expected, used, f"Cursor used {used}, expected {expected}") class TestSingleSecondaryOk(TestReadPreferencesBase): def test_reads_from_secondary(self): host, port = next(iter(self.client.secondaries)) # Direct connection to a secondary. client = single_client(host, port) self.assertFalse(client.is_primary) # Regardless of read preference, we should be able to do # "reads" with a direct connection to a secondary. # See server-selection.rst#topology-type-single. self.assertEqual(client.read_preference, ReadPreference.PRIMARY) db = client.pymongo_test coll = db.test # Test find and find_one. self.assertIsNotNone(coll.find_one()) self.assertEqual(10, len(list(coll.find()))) # Test some database helpers. self.assertIsNotNone(db.list_collection_names()) self.assertIsNotNone(db.validate_collection("test")) self.assertIsNotNone(db.command("ping")) # Test some collection helpers. self.assertEqual(10, coll.count_documents({})) self.assertEqual(10, len(coll.distinct("_id"))) self.assertIsNotNone(coll.aggregate([])) self.assertIsNotNone(coll.index_information()) class TestReadPreferences(TestReadPreferencesBase): def test_mode_validation(self): for mode in ( ReadPreference.PRIMARY, ReadPreference.PRIMARY_PREFERRED, ReadPreference.SECONDARY, ReadPreference.SECONDARY_PREFERRED, ReadPreference.NEAREST, ): self.assertEqual(mode, rs_client(read_preference=mode).read_preference) self.assertRaises(TypeError, rs_client, read_preference="foo") def test_tag_sets_validation(self): S = Secondary(tag_sets=[{}]) self.assertEqual([{}], rs_client(read_preference=S).read_preference.tag_sets) S = Secondary(tag_sets=[{"k": "v"}]) self.assertEqual([{"k": "v"}], rs_client(read_preference=S).read_preference.tag_sets) S = Secondary(tag_sets=[{"k": "v"}, {}]) self.assertEqual([{"k": "v"}, {}], rs_client(read_preference=S).read_preference.tag_sets) self.assertRaises(ValueError, Secondary, tag_sets=[]) # One dict not ok, must be a list of dicts self.assertRaises(TypeError, Secondary, tag_sets={"k": "v"}) self.assertRaises(TypeError, Secondary, tag_sets="foo") self.assertRaises(TypeError, Secondary, tag_sets=["foo"]) def test_threshold_validation(self): self.assertEqual( 17, rs_client(localThresholdMS=17, connect=False).options.local_threshold_ms ) self.assertEqual( 42, rs_client(localThresholdMS=42, connect=False).options.local_threshold_ms ) self.assertEqual( 666, rs_client(localThresholdMS=666, connect=False).options.local_threshold_ms ) self.assertEqual(0, rs_client(localThresholdMS=0, connect=False).options.local_threshold_ms) self.assertRaises(ValueError, rs_client, localthresholdms=-1) def test_zero_latency(self): ping_times: set = set() # Generate unique ping times. while len(ping_times) < len(self.client.nodes): ping_times.add(random.random()) for ping_time, host in zip(ping_times, self.client.nodes): ServerDescription._host_to_round_trip_time[host] = ping_time try: client = connected(rs_client(readPreference="nearest", localThresholdMS=0)) wait_until(lambda: client.nodes == self.client.nodes, "discovered all nodes") host = self.read_from_which_host(client) for _ in range(5): self.assertEqual(host, self.read_from_which_host(client)) finally: ServerDescription._host_to_round_trip_time.clear() def test_primary(self): self.assertReadsFrom("primary", read_preference=ReadPreference.PRIMARY) def test_primary_with_tags(self): # Tags not allowed with PRIMARY self.assertRaises(ConfigurationError, rs_client, tag_sets=[{"dc": "ny"}]) def test_primary_preferred(self): self.assertReadsFrom("primary", read_preference=ReadPreference.PRIMARY_PREFERRED) def test_secondary(self): self.assertReadsFrom("secondary", read_preference=ReadPreference.SECONDARY) def test_secondary_preferred(self): self.assertReadsFrom("secondary", read_preference=ReadPreference.SECONDARY_PREFERRED) def test_nearest(self): # With high localThresholdMS, expect to read from any # member c = rs_client(read_preference=ReadPreference.NEAREST, localThresholdMS=10000) # 10 seconds data_members = {self.client.primary} | self.client.secondaries # This is a probabilistic test; track which members we've read from so # far, and keep reading until we've used all the members or give up. # Chance of using only 2 of 3 members 10k times if there's no bug = # 3 * (2/3)**10000, very low. used: set = set() i = 0 while data_members.difference(used) and i < 10000: address = self.read_from_which_host(c) used.add(address) i += 1 not_used = data_members.difference(used) latencies = ", ".join( "%s: %sms" % (server.description.address, server.description.round_trip_time) for server in c._get_topology().select_servers(readable_server_selector, _Op.TEST) ) self.assertFalse( not_used, "Expected to use primary and all secondaries for mode NEAREST," f" but didn't use {not_used}\nlatencies: {latencies}", ) class ReadPrefTester(MongoClient): def __init__(self, *args, **kwargs): self.has_read_from = set() client_options = client_context.client_options client_options.update(kwargs) super().__init__(*args, **client_options) @contextlib.contextmanager def _conn_for_reads(self, read_preference, session, operation): context = super()._conn_for_reads(read_preference, session, operation) with context as (conn, read_preference): self.record_a_read(conn.address) yield conn, read_preference @contextlib.contextmanager def _conn_from_server(self, read_preference, server, session): context = super()._conn_from_server(read_preference, server, session) with context as (conn, read_preference): self.record_a_read(conn.address) yield conn, read_preference def record_a_read(self, address): server = self._get_topology().select_server_by_address(address, _Op.TEST, 0) self.has_read_from.add(server) _PREF_MAP = [ (Primary, SERVER_TYPE.RSPrimary), (PrimaryPreferred, SERVER_TYPE.RSPrimary), (Secondary, SERVER_TYPE.RSSecondary), (SecondaryPreferred, SERVER_TYPE.RSSecondary), (Nearest, "any"), ] class TestCommandAndReadPreference(IntegrationTest): c: ReadPrefTester client_version: Version @classmethod @client_context.require_secondaries_count(1) def setUpClass(cls): super().setUpClass() cls.c = ReadPrefTester( # Ignore round trip times, to test ReadPreference modes only. localThresholdMS=1000 * 1000, ) cls.client_version = Version.from_client(cls.c) # mapReduce fails if the collection does not exist. coll = cls.c.pymongo_test.get_collection( "test", write_concern=WriteConcern(w=client_context.w) ) coll.insert_one({}) @classmethod def tearDownClass(cls): cls.c.drop_database("pymongo_test") cls.c.close() def executed_on_which_server(self, client, fn, *args, **kwargs): """Execute fn(*args, **kwargs) and return the Server instance used.""" client.has_read_from.clear() fn(*args, **kwargs) self.assertEqual(1, len(client.has_read_from)) return one(client.has_read_from) def assertExecutedOn(self, server_type, client, fn, *args, **kwargs): server = self.executed_on_which_server(client, fn, *args, **kwargs) self.assertEqual( SERVER_TYPE._fields[server_type], SERVER_TYPE._fields[server.description.server_type] ) def _test_fn(self, server_type, fn): for _ in range(10): if server_type == "any": used = set() for _ in range(1000): server = self.executed_on_which_server(self.c, fn) used.add(server.description.address) if len(used) == len(self.c.secondaries) + 1: # Success break assert self.c.primary is not None unused = self.c.secondaries.union({self.c.primary}).difference(used) if unused: self.fail("Some members not used for NEAREST: %s" % (unused)) else: self.assertExecutedOn(server_type, self.c, fn) def _test_primary_helper(self, func): # Helpers that ignore read preference. self._test_fn(SERVER_TYPE.RSPrimary, func) def _test_coll_helper(self, secondary_ok, coll, meth, *args, **kwargs): for mode, server_type in _PREF_MAP: new_coll = coll.with_options(read_preference=mode()) def func(): return getattr(new_coll, meth)(*args, **kwargs) if secondary_ok: self._test_fn(server_type, func) else: self._test_fn(SERVER_TYPE.RSPrimary, func) def test_command(self): # Test that the generic command helper obeys the read preference # passed to it. for mode, server_type in _PREF_MAP: def func(): return self.c.pymongo_test.command("dbStats", read_preference=mode()) self._test_fn(server_type, func) def test_create_collection(self): # create_collection runs listCollections on the primary to check if # the collection already exists. self._test_primary_helper( lambda: self.c.pymongo_test.create_collection( "some_collection%s" % random.randint(0, sys.maxsize) ) ) def test_count_documents(self): self._test_coll_helper(True, self.c.pymongo_test.test, "count_documents", {}) def test_estimated_document_count(self): self._test_coll_helper(True, self.c.pymongo_test.test, "estimated_document_count") def test_distinct(self): self._test_coll_helper(True, self.c.pymongo_test.test, "distinct", "a") def test_aggregate(self): self._test_coll_helper( True, self.c.pymongo_test.test, "aggregate", [{"$project": {"_id": 1}}] ) def test_aggregate_write(self): # 5.0 servers support $out on secondaries. secondary_ok = client_context.version.at_least(5, 0) self._test_coll_helper( secondary_ok, self.c.pymongo_test.test, "aggregate", [{"$project": {"_id": 1}}, {"$out": "agg_write_test"}], ) class TestMovingAverage(unittest.TestCase): def test_moving_average(self): avg = MovingAverage() self.assertIsNone(avg.get()) avg.add_sample(10) self.assertAlmostEqual(10, avg.get()) # type: ignore avg.add_sample(20) self.assertAlmostEqual(12, avg.get()) # type: ignore avg.add_sample(30) self.assertAlmostEqual(15.6, avg.get()) # type: ignore class TestMongosAndReadPreference(IntegrationTest): def test_read_preference_document(self): pref = Primary() self.assertEqual(pref.document, {"mode": "primary"}) pref = PrimaryPreferred() self.assertEqual(pref.document, {"mode": "primaryPreferred"}) pref = PrimaryPreferred(tag_sets=[{"dc": "sf"}]) self.assertEqual(pref.document, {"mode": "primaryPreferred", "tags": [{"dc": "sf"}]}) pref = PrimaryPreferred(tag_sets=[{"dc": "sf"}], max_staleness=30) self.assertEqual( pref.document, {"mode": "primaryPreferred", "tags": [{"dc": "sf"}], "maxStalenessSeconds": 30}, ) pref = Secondary() self.assertEqual(pref.document, {"mode": "secondary"}) pref = Secondary(tag_sets=[{"dc": "sf"}]) self.assertEqual(pref.document, {"mode": "secondary", "tags": [{"dc": "sf"}]}) pref = Secondary(tag_sets=[{"dc": "sf"}], max_staleness=30) self.assertEqual( pref.document, {"mode": "secondary", "tags": [{"dc": "sf"}], "maxStalenessSeconds": 30} ) pref = SecondaryPreferred() self.assertEqual(pref.document, {"mode": "secondaryPreferred"}) pref = SecondaryPreferred(tag_sets=[{"dc": "sf"}]) self.assertEqual(pref.document, {"mode": "secondaryPreferred", "tags": [{"dc": "sf"}]}) pref = SecondaryPreferred(tag_sets=[{"dc": "sf"}], max_staleness=30) self.assertEqual( pref.document, {"mode": "secondaryPreferred", "tags": [{"dc": "sf"}], "maxStalenessSeconds": 30}, ) pref = Nearest() self.assertEqual(pref.document, {"mode": "nearest"}) pref = Nearest(tag_sets=[{"dc": "sf"}]) self.assertEqual(pref.document, {"mode": "nearest", "tags": [{"dc": "sf"}]}) pref = Nearest(tag_sets=[{"dc": "sf"}], max_staleness=30) self.assertEqual( pref.document, {"mode": "nearest", "tags": [{"dc": "sf"}], "maxStalenessSeconds": 30} ) with self.assertRaises(TypeError): # Float is prohibited. Nearest(max_staleness=1.5) # type: ignore with self.assertRaises(ValueError): Nearest(max_staleness=0) with self.assertRaises(ValueError): Nearest(max_staleness=-2) def test_read_preference_document_hedge(self): cases = { "primaryPreferred": PrimaryPreferred, "secondary": Secondary, "secondaryPreferred": SecondaryPreferred, "nearest": Nearest, } for mode, cls in cases.items(): with self.assertRaises(TypeError): cls(hedge=[]) # type: ignore pref = cls(hedge={}) self.assertEqual(pref.document, {"mode": mode}) out = _maybe_add_read_preference({}, pref) if cls == SecondaryPreferred: # SecondaryPreferred without hedge doesn't add $readPreference. self.assertEqual(out, {}) else: self.assertEqual(out, SON([("$query", {}), ("$readPreference", pref.document)])) hedge: dict[str, Any] = {"enabled": True} pref = cls(hedge=hedge) self.assertEqual(pref.document, {"mode": mode, "hedge": hedge}) out = _maybe_add_read_preference({}, pref) self.assertEqual(out, SON([("$query", {}), ("$readPreference", pref.document)])) hedge = {"enabled": False} pref = cls(hedge=hedge) self.assertEqual(pref.document, {"mode": mode, "hedge": hedge}) out = _maybe_add_read_preference({}, pref) self.assertEqual(out, SON([("$query", {}), ("$readPreference", pref.document)])) hedge = {"enabled": False, "extra": "option"} pref = cls(hedge=hedge) self.assertEqual(pref.document, {"mode": mode, "hedge": hedge}) out = _maybe_add_read_preference({}, pref) self.assertEqual(out, SON([("$query", {}), ("$readPreference", pref.document)])) def test_send_hedge(self): cases = { "primaryPreferred": PrimaryPreferred, "secondaryPreferred": SecondaryPreferred, "nearest": Nearest, } if client_context.supports_secondary_read_pref: cases["secondary"] = Secondary listener = OvertCommandListener() client = rs_client(event_listeners=[listener]) self.addCleanup(client.close) client.admin.command("ping") for _mode, cls in cases.items(): pref = cls(hedge={"enabled": True}) coll = client.test.get_collection("test", read_preference=pref) listener.reset() coll.find_one() started = listener.started_events self.assertEqual(len(started), 1, started) cmd = started[0].command if client_context.is_rs or client_context.is_mongos: self.assertIn("$readPreference", cmd) self.assertEqual(cmd["$readPreference"], pref.document) else: self.assertNotIn("$readPreference", cmd) def test_maybe_add_read_preference(self): # Primary doesn't add $readPreference out = _maybe_add_read_preference({}, Primary()) self.assertEqual(out, {}) pref = PrimaryPreferred() out = _maybe_add_read_preference({}, pref) self.assertEqual(out, SON([("$query", {}), ("$readPreference", pref.document)])) pref = PrimaryPreferred(tag_sets=[{"dc": "nyc"}]) out = _maybe_add_read_preference({}, pref) self.assertEqual(out, SON([("$query", {}), ("$readPreference", pref.document)])) pref = Secondary() out = _maybe_add_read_preference({}, pref) self.assertEqual(out, SON([("$query", {}), ("$readPreference", pref.document)])) pref = Secondary(tag_sets=[{"dc": "nyc"}]) out = _maybe_add_read_preference({}, pref) self.assertEqual(out, SON([("$query", {}), ("$readPreference", pref.document)])) # SecondaryPreferred without tag_sets or max_staleness doesn't add # $readPreference pref = SecondaryPreferred() out = _maybe_add_read_preference({}, pref) self.assertEqual(out, {}) pref = SecondaryPreferred(tag_sets=[{"dc": "nyc"}]) out = _maybe_add_read_preference({}, pref) self.assertEqual(out, SON([("$query", {}), ("$readPreference", pref.document)])) pref = SecondaryPreferred(max_staleness=120) out = _maybe_add_read_preference({}, pref) self.assertEqual(out, SON([("$query", {}), ("$readPreference", pref.document)])) pref = Nearest() out = _maybe_add_read_preference({}, pref) self.assertEqual(out, SON([("$query", {}), ("$readPreference", pref.document)])) pref = Nearest(tag_sets=[{"dc": "nyc"}]) out = _maybe_add_read_preference({}, pref) self.assertEqual(out, SON([("$query", {}), ("$readPreference", pref.document)])) criteria = SON([("$query", {}), ("$orderby", SON([("_id", 1)]))]) pref = Nearest() out = _maybe_add_read_preference(criteria, pref) self.assertEqual( out, SON( [ ("$query", {}), ("$orderby", SON([("_id", 1)])), ("$readPreference", pref.document), ] ), ) pref = Nearest(tag_sets=[{"dc": "nyc"}]) out = _maybe_add_read_preference(criteria, pref) self.assertEqual( out, SON( [ ("$query", {}), ("$orderby", SON([("_id", 1)])), ("$readPreference", pref.document), ] ), ) @client_context.require_mongos def test_mongos(self): res = client_context.client.config.shards.find_one() assert res is not None shard = res["host"] num_members = shard.count(",") + 1 if num_members == 1: raise SkipTest("Need a replica set shard to test.") coll = client_context.client.pymongo_test.get_collection( "test", write_concern=WriteConcern(w=num_members) ) coll.drop() res = coll.insert_many([{} for _ in range(5)]) first_id = res.inserted_ids[0] last_id = res.inserted_ids[-1] # Note - this isn't a perfect test since there's no way to # tell what shard member a query ran on. for pref in (Primary(), PrimaryPreferred(), Secondary(), SecondaryPreferred(), Nearest()): qcoll = coll.with_options(read_preference=pref) results = list(qcoll.find().sort([("_id", 1)])) self.assertEqual(first_id, results[0]["_id"]) self.assertEqual(last_id, results[-1]["_id"]) results = list(qcoll.find().sort([("_id", -1)])) self.assertEqual(first_id, results[-1]["_id"]) self.assertEqual(last_id, results[0]["_id"]) @client_context.require_mongos def test_mongos_max_staleness(self): # Sanity check that we're sending maxStalenessSeconds coll = client_context.client.pymongo_test.get_collection( "test", read_preference=SecondaryPreferred(max_staleness=120) ) # No error coll.find_one() coll = client_context.client.pymongo_test.get_collection( "test", read_preference=SecondaryPreferred(max_staleness=10) ) try: coll.find_one() except OperationFailure as exc: self.assertEqual(160, exc.code) else: self.fail("mongos accepted invalid staleness") coll = single_client( readPreference="secondaryPreferred", maxStalenessSeconds=120 ).pymongo_test.test # No error coll.find_one() coll = single_client( readPreference="secondaryPreferred", maxStalenessSeconds=10 ).pymongo_test.test try: coll.find_one() except OperationFailure as exc: self.assertEqual(160, exc.code) else: self.fail("mongos accepted invalid staleness") if __name__ == "__main__": unittest.main() mongodb-mongo-python-driver-509e9b7/test/test_read_write_concern_spec.py000066400000000000000000000326221462766011000267000ustar00rootroot00000000000000# Copyright 2018-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. """Run the read and write concern tests.""" from __future__ import annotations import json import os import sys import warnings sys.path[0:0] = [""] from test import IntegrationTest, client_context, unittest from test.utils import ( EventListener, SpecTestCreator, disable_replication, enable_replication, rs_or_single_client, ) from test.utils_spec_runner import SpecRunner from pymongo import DESCENDING from pymongo.errors import ( BulkWriteError, ConfigurationError, WriteConcernError, WriteError, WTimeoutError, ) from pymongo.mongo_client import MongoClient from pymongo.operations import IndexModel, InsertOne from pymongo.read_concern import ReadConcern from pymongo.write_concern import WriteConcern _TEST_PATH = os.path.join(os.path.dirname(os.path.realpath(__file__)), "read_write_concern") class TestReadWriteConcernSpec(IntegrationTest): def test_omit_default_read_write_concern(self): listener = EventListener() # Client with default readConcern and writeConcern client = rs_or_single_client(event_listeners=[listener]) self.addCleanup(client.close) collection = client.pymongo_test.collection # Prepare for tests of find() and aggregate(). collection.insert_many([{} for _ in range(10)]) self.addCleanup(collection.drop) self.addCleanup(client.pymongo_test.collection2.drop) # Commands MUST NOT send the default read/write concern to the server. def rename_and_drop(): # Ensure collection exists. collection.insert_one({}) collection.rename("collection2") client.pymongo_test.collection2.drop() def insert_command_default_write_concern(): collection.database.command( "insert", "collection", documents=[{}], write_concern=WriteConcern() ) ops = [ ("aggregate", lambda: list(collection.aggregate([]))), ("find", lambda: list(collection.find())), ("insert_one", lambda: collection.insert_one({})), ("update_one", lambda: collection.update_one({}, {"$set": {"x": 1}})), ("update_many", lambda: collection.update_many({}, {"$set": {"x": 1}})), ("delete_one", lambda: collection.delete_one({})), ("delete_many", lambda: collection.delete_many({})), ("bulk_write", lambda: collection.bulk_write([InsertOne({})])), ("rename_and_drop", rename_and_drop), ("command", insert_command_default_write_concern), ] for name, f in ops: listener.reset() f() self.assertGreaterEqual(len(listener.started_events), 1) for _i, event in enumerate(listener.started_events): self.assertNotIn( "readConcern", event.command, f"{name} sent default readConcern with {event.command_name}", ) self.assertNotIn( "writeConcern", event.command, f"{name} sent default writeConcern with {event.command_name}", ) def assertWriteOpsRaise(self, write_concern, expected_exception): wc = write_concern.document # Set socket timeout to avoid indefinite stalls client = rs_or_single_client(w=wc["w"], wTimeoutMS=wc["wtimeout"], socketTimeoutMS=30000) db = client.get_database("pymongo_test") coll = db.test def insert_command(): coll.database.command( "insert", "new_collection", documents=[{}], writeConcern=write_concern.document, parse_write_concern_error=True, ) ops = [ ("insert_one", lambda: coll.insert_one({})), ("insert_many", lambda: coll.insert_many([{}, {}])), ("update_one", lambda: coll.update_one({}, {"$set": {"x": 1}})), ("update_many", lambda: coll.update_many({}, {"$set": {"x": 1}})), ("delete_one", lambda: coll.delete_one({})), ("delete_many", lambda: coll.delete_many({})), ("bulk_write", lambda: coll.bulk_write([InsertOne({})])), ("command", insert_command), ("aggregate", lambda: coll.aggregate([{"$out": "out"}])), # SERVER-46668 Delete all the documents in the collection to # workaround a hang in createIndexes. ("delete_many", lambda: coll.delete_many({})), ("create_index", lambda: coll.create_index([("a", DESCENDING)])), ("create_indexes", lambda: coll.create_indexes([IndexModel("b")])), ("drop_index", lambda: coll.drop_index([("a", DESCENDING)])), ("create", lambda: db.create_collection("new")), ("rename", lambda: coll.rename("new")), ("drop", lambda: db.new.drop()), ] # SERVER-47194: dropDatabase does not respect wtimeout in 3.6. if client_context.version[:2] != (3, 6): ops.append(("drop_database", lambda: client.drop_database(db))) for name, f in ops: # Ensure insert_many and bulk_write still raise BulkWriteError. if name in ("insert_many", "bulk_write"): expected = BulkWriteError else: expected = expected_exception with self.assertRaises(expected, msg=name) as cm: f() if expected == BulkWriteError: bulk_result = cm.exception.details assert bulk_result is not None wc_errors = bulk_result["writeConcernErrors"] self.assertTrue(wc_errors) @client_context.require_replica_set def test_raise_write_concern_error(self): self.addCleanup(client_context.client.drop_database, "pymongo_test") assert client_context.w is not None self.assertWriteOpsRaise( WriteConcern(w=client_context.w + 1, wtimeout=1), WriteConcernError ) @client_context.require_secondaries_count(1) @client_context.require_test_commands def test_raise_wtimeout(self): self.addCleanup(client_context.client.drop_database, "pymongo_test") self.addCleanup(enable_replication, client_context.client) # Disable replication to guarantee a wtimeout error. disable_replication(client_context.client) self.assertWriteOpsRaise(WriteConcern(w=client_context.w, wtimeout=1), WTimeoutError) @client_context.require_failCommand_fail_point def test_error_includes_errInfo(self): expected_wce = { "code": 100, "codeName": "UnsatisfiableWriteConcern", "errmsg": "Not enough data-bearing nodes", "errInfo": {"writeConcern": {"w": 2, "wtimeout": 0, "provenance": "clientSupplied"}}, } cause_wce = { "configureFailPoint": "failCommand", "mode": {"times": 2}, "data": {"failCommands": ["insert"], "writeConcernError": expected_wce}, } with self.fail_point(cause_wce): # Write concern error on insert includes errInfo. with self.assertRaises(WriteConcernError) as ctx: self.db.test.insert_one({}) self.assertEqual(ctx.exception.details, expected_wce) # Test bulk_write as well. with self.assertRaises(BulkWriteError) as ctx: self.db.test.bulk_write([InsertOne({})]) expected_details = { "writeErrors": [], "writeConcernErrors": [expected_wce], "nInserted": 1, "nUpserted": 0, "nMatched": 0, "nModified": 0, "nRemoved": 0, "upserted": [], } self.assertEqual(ctx.exception.details, expected_details) @client_context.require_version_min(4, 9) def test_write_error_details_exposes_errinfo(self): listener = EventListener() client = rs_or_single_client(event_listeners=[listener]) self.addCleanup(client.close) db = client.errinfotest self.addCleanup(client.drop_database, "errinfotest") validator = {"x": {"$type": "string"}} db.create_collection("test", validator=validator) with self.assertRaises(WriteError) as ctx: db.test.insert_one({"x": 1}) self.assertEqual(ctx.exception.code, 121) self.assertIsNotNone(ctx.exception.details) assert ctx.exception.details is not None self.assertIsNotNone(ctx.exception.details.get("errInfo")) for event in listener.succeeded_events: if event.command_name == "insert": self.assertEqual(event.reply["writeErrors"][0], ctx.exception.details) break else: self.fail("Couldn't find insert event.") def normalize_write_concern(concern): result = {} for key in concern: if key.lower() == "wtimeoutms": result["wtimeout"] = concern[key] elif key == "journal": result["j"] = concern[key] else: result[key] = concern[key] return result def create_connection_string_test(test_case): def run_test(self): uri = test_case["uri"] valid = test_case["valid"] warning = test_case["warning"] if not valid: if warning is False: self.assertRaises((ConfigurationError, ValueError), MongoClient, uri, connect=False) else: with warnings.catch_warnings(): warnings.simplefilter("error", UserWarning) self.assertRaises(UserWarning, MongoClient, uri, connect=False) else: client = MongoClient(uri, connect=False) if "writeConcern" in test_case: document = client.write_concern.document self.assertEqual(document, normalize_write_concern(test_case["writeConcern"])) if "readConcern" in test_case: document = client.read_concern.document self.assertEqual(document, test_case["readConcern"]) return run_test def create_document_test(test_case): def run_test(self): valid = test_case["valid"] if "writeConcern" in test_case: normalized = normalize_write_concern(test_case["writeConcern"]) if not valid: self.assertRaises((ConfigurationError, ValueError), WriteConcern, **normalized) else: write_concern = WriteConcern(**normalized) self.assertEqual(write_concern.document, test_case["writeConcernDocument"]) self.assertEqual(write_concern.acknowledged, test_case["isAcknowledged"]) self.assertEqual(write_concern.is_server_default, test_case["isServerDefault"]) if "readConcern" in test_case: # Any string for 'level' is equally valid read_concern = ReadConcern(**test_case["readConcern"]) self.assertEqual(read_concern.document, test_case["readConcernDocument"]) self.assertEqual(not bool(read_concern.level), test_case["isServerDefault"]) return run_test def create_tests(): for dirpath, _, filenames in os.walk(_TEST_PATH): dirname = os.path.split(dirpath)[-1] if dirname == "operation": # This directory is tested by TestOperations. continue elif dirname == "connection-string": create_test = create_connection_string_test else: create_test = create_document_test for filename in filenames: with open(os.path.join(dirpath, filename)) as test_stream: test_cases = json.load(test_stream)["tests"] fname = os.path.splitext(filename)[0] for test_case in test_cases: new_test = create_test(test_case) test_name = "test_{}_{}_{}".format( dirname.replace("-", "_"), fname.replace("-", "_"), str(test_case["description"].lower().replace(" ", "_")), ) new_test.__name__ = test_name setattr(TestReadWriteConcernSpec, new_test.__name__, new_test) create_tests() class TestOperation(SpecRunner): # Location of JSON test specifications. TEST_PATH = os.path.join(_TEST_PATH, "operation") def get_outcome_coll_name(self, outcome, collection): """Spec says outcome has an optional 'collection.name'.""" return outcome["collection"].get("name", collection.name) def create_operation_test(scenario_def, test, name): @client_context.require_test_commands def run_scenario(self): self.run_scenario(scenario_def, test) return run_scenario test_creator = SpecTestCreator(create_operation_test, TestOperation, TestOperation.TEST_PATH) test_creator.create_tests() if __name__ == "__main__": unittest.main() mongodb-mongo-python-driver-509e9b7/test/test_replica_set_reconfig.py000066400000000000000000000134121462766011000261740ustar00rootroot00000000000000# Copyright 2013-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. """Test clients and replica set configuration changes, using mocks.""" from __future__ import annotations import sys sys.path[0:0] = [""] from test import MockClientTest, client_context, client_knobs, unittest from test.pymongo_mocks import MockClient from test.utils import wait_until from pymongo import ReadPreference from pymongo.errors import ConnectionFailure, ServerSelectionTimeoutError @client_context.require_connection @client_context.require_no_load_balancer def setUpModule(): pass class TestSecondaryBecomesStandalone(MockClientTest): # An administrator removes a secondary from a 3-node set and # brings it back up as standalone, without updating the other # members' config. Verify we don't continue using it. def test_client(self): c = MockClient( standalones=[], members=["a:1", "b:2", "c:3"], mongoses=[], host="a:1,b:2,c:3", replicaSet="rs", serverSelectionTimeoutMS=100, connect=False, ) self.addCleanup(c.close) # C is brought up as a standalone. c.mock_members.remove("c:3") c.mock_standalones.append("c:3") # Fail over. c.kill_host("a:1") c.kill_host("b:2") with self.assertRaises(ServerSelectionTimeoutError): c.db.command("ping") self.assertEqual(c.address, None) # Client can still discover the primary node c.revive_host("a:1") wait_until(lambda: c.address is not None, "connect to primary") self.assertEqual(c.address, ("a", 1)) def test_replica_set_client(self): c = MockClient( standalones=[], members=["a:1", "b:2", "c:3"], mongoses=[], host="a:1,b:2,c:3", replicaSet="rs", ) self.addCleanup(c.close) wait_until(lambda: ("b", 2) in c.secondaries, 'discover host "b"') wait_until(lambda: ("c", 3) in c.secondaries, 'discover host "c"') # C is brought up as a standalone. c.mock_members.remove("c:3") c.mock_standalones.append("c:3") wait_until(lambda: {("b", 2)} == c.secondaries, "update the list of secondaries") self.assertEqual(("a", 1), c.primary) class TestSecondaryRemoved(MockClientTest): # An administrator removes a secondary from a 3-node set *without* # restarting it as standalone. def test_replica_set_client(self): c = MockClient( standalones=[], members=["a:1", "b:2", "c:3"], mongoses=[], host="a:1,b:2,c:3", replicaSet="rs", ) self.addCleanup(c.close) wait_until(lambda: ("b", 2) in c.secondaries, 'discover host "b"') wait_until(lambda: ("c", 3) in c.secondaries, 'discover host "c"') # C is removed. c.mock_hello_hosts.remove("c:3") wait_until(lambda: {("b", 2)} == c.secondaries, "update list of secondaries") self.assertEqual(("a", 1), c.primary) class TestSocketError(MockClientTest): def test_socket_error_marks_member_down(self): # Disable background refresh. with client_knobs(heartbeat_frequency=999999): c = MockClient( standalones=[], members=["a:1", "b:2"], mongoses=[], host="a:1", replicaSet="rs", serverSelectionTimeoutMS=100, ) self.addCleanup(c.close) wait_until(lambda: len(c.nodes) == 2, "discover both nodes") # b now raises socket.error. c.mock_down_hosts.append("b:2") self.assertRaises( ConnectionFailure, c.db.collection.with_options(read_preference=ReadPreference.SECONDARY).find_one, ) self.assertEqual(1, len(c.nodes)) class TestSecondaryAdded(MockClientTest): def test_client(self): c = MockClient( standalones=[], members=["a:1", "b:2"], mongoses=[], host="a:1", replicaSet="rs" ) self.addCleanup(c.close) wait_until(lambda: len(c.nodes) == 2, "discover both nodes") # MongoClient connects to primary by default. self.assertEqual(c.address, ("a", 1)) self.assertEqual({("a", 1), ("b", 2)}, c.nodes) # C is added. c.mock_members.append("c:3") c.mock_hello_hosts.append("c:3") c.db.command("ping") self.assertEqual(c.address, ("a", 1)) wait_until( lambda: {("a", 1), ("b", 2), ("c", 3)} == c.nodes, "reconnect to both secondaries" ) def test_replica_set_client(self): c = MockClient( standalones=[], members=["a:1", "b:2"], mongoses=[], host="a:1", replicaSet="rs" ) self.addCleanup(c.close) wait_until(lambda: c.primary == ("a", 1), "discover the primary") wait_until(lambda: {("b", 2)} == c.secondaries, "discover the secondary") # C is added. c.mock_members.append("c:3") c.mock_hello_hosts.append("c:3") wait_until(lambda: {("b", 2), ("c", 3)} == c.secondaries, "discover the new secondary") self.assertEqual(("a", 1), c.primary) if __name__ == "__main__": unittest.main() mongodb-mongo-python-driver-509e9b7/test/test_results.py000066400000000000000000000120071462766011000235260ustar00rootroot00000000000000# Copyright 2023-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. """Test results module.""" from __future__ import annotations import sys sys.path[0:0] = [""] from test import unittest from pymongo.errors import InvalidOperation from pymongo.results import ( BulkWriteResult, DeleteResult, InsertManyResult, InsertOneResult, UpdateResult, ) class TestResults(unittest.TestCase): def repr_test(self, cls, result_arg): for acknowledged in (True, False): result = cls(result_arg, acknowledged) expected_repr = "%s(%r, acknowledged=%r)" % (cls.__name__, result_arg, acknowledged) self.assertEqual(acknowledged, result.acknowledged) self.assertEqual(expected_repr, repr(result)) def test_bulk_write_result(self): raw_result = { "writeErrors": [], "writeConcernErrors": [], "nInserted": 1, "nUpserted": 2, "nMatched": 2, "nModified": 2, "nRemoved": 2, "upserted": [ {"index": 5, "_id": 1}, {"index": 9, "_id": 2}, ], } self.repr_test(BulkWriteResult, raw_result) result = BulkWriteResult(raw_result, True) self.assertEqual(raw_result, result.bulk_api_result) self.assertEqual(raw_result["nInserted"], result.inserted_count) self.assertEqual(raw_result["nMatched"], result.matched_count) self.assertEqual(raw_result["nModified"], result.modified_count) self.assertEqual(raw_result["nRemoved"], result.deleted_count) self.assertEqual(raw_result["nUpserted"], result.upserted_count) self.assertEqual({5: 1, 9: 2}, result.upserted_ids) result = BulkWriteResult(raw_result, False) self.assertEqual(raw_result, result.bulk_api_result) error_msg = "A value for .* is not available when" with self.assertRaisesRegex(InvalidOperation, error_msg): result.inserted_count with self.assertRaisesRegex(InvalidOperation, error_msg): result.matched_count with self.assertRaisesRegex(InvalidOperation, error_msg): result.modified_count with self.assertRaisesRegex(InvalidOperation, error_msg): result.deleted_count with self.assertRaisesRegex(InvalidOperation, error_msg): result.upserted_count with self.assertRaisesRegex(InvalidOperation, error_msg): result.upserted_ids def test_delete_result(self): raw_result = {"n": 5} self.repr_test(DeleteResult, {"n": 0}) result = DeleteResult(raw_result, True) self.assertEqual(raw_result, result.raw_result) self.assertEqual(raw_result["n"], result.deleted_count) result = DeleteResult(raw_result, False) self.assertEqual(raw_result, result.raw_result) error_msg = "A value for .* is not available when" with self.assertRaisesRegex(InvalidOperation, error_msg): result.deleted_count def test_insert_many_result(self): inserted_ids = [1, 2, 3] self.repr_test(InsertManyResult, inserted_ids) for acknowledged in (True, False): result = InsertManyResult(inserted_ids, acknowledged) self.assertEqual(inserted_ids, result.inserted_ids) def test_insert_one_result(self): self.repr_test(InsertOneResult, 0) for acknowledged in (True, False): result = InsertOneResult(0, acknowledged) self.assertEqual(0, result.inserted_id) def test_update_result(self): raw_result = { "n": 1, "nModified": 1, "upserted": None, } self.repr_test(UpdateResult, raw_result) result = UpdateResult(raw_result, True) self.assertEqual(raw_result, result.raw_result) self.assertEqual(raw_result["n"], result.matched_count) self.assertEqual(raw_result["nModified"], result.modified_count) self.assertEqual(raw_result["upserted"], result.upserted_id) result = UpdateResult(raw_result, False) self.assertEqual(raw_result, result.raw_result) error_msg = "A value for .* is not available when" with self.assertRaisesRegex(InvalidOperation, error_msg): result.matched_count with self.assertRaisesRegex(InvalidOperation, error_msg): result.modified_count with self.assertRaisesRegex(InvalidOperation, error_msg): result.upserted_id if __name__ == "__main__": unittest.main() mongodb-mongo-python-driver-509e9b7/test/test_retryable_reads.py000066400000000000000000000235421462766011000252020ustar00rootroot00000000000000# Copyright 2019-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. """Test retryable reads spec.""" from __future__ import annotations import os import pprint import sys import threading from bson import SON from pymongo.errors import AutoReconnect sys.path[0:0] = [""] from test import ( IntegrationTest, PyMongoTestCase, client_context, client_knobs, unittest, ) from test.utils import ( CMAPListener, EventListener, OvertCommandListener, SpecTestCreator, rs_client, rs_or_single_client, set_fail_point, ) from test.utils_spec_runner import SpecRunner from pymongo.mongo_client import MongoClient from pymongo.monitoring import ( ConnectionCheckedOutEvent, ConnectionCheckOutFailedEvent, ConnectionCheckOutFailedReason, PoolClearedEvent, ) from pymongo.write_concern import WriteConcern # Location of JSON test specifications. _TEST_PATH = os.path.join(os.path.dirname(os.path.realpath(__file__)), "retryable_reads", "legacy") class TestClientOptions(PyMongoTestCase): def test_default(self): client = MongoClient(connect=False) self.assertEqual(client.options.retry_reads, True) def test_kwargs(self): client = MongoClient(retryReads=True, connect=False) self.assertEqual(client.options.retry_reads, True) client = MongoClient(retryReads=False, connect=False) self.assertEqual(client.options.retry_reads, False) def test_uri(self): client = MongoClient("mongodb://h/?retryReads=true", connect=False) self.assertEqual(client.options.retry_reads, True) client = MongoClient("mongodb://h/?retryReads=false", connect=False) self.assertEqual(client.options.retry_reads, False) class TestSpec(SpecRunner): RUN_ON_LOAD_BALANCER = True RUN_ON_SERVERLESS = True @classmethod @client_context.require_failCommand_fail_point # TODO: remove this once PYTHON-1948 is done. @client_context.require_no_mmap def setUpClass(cls): super().setUpClass() def maybe_skip_scenario(self, test): super().maybe_skip_scenario(test) skip_names = ["listCollectionObjects", "listIndexNames", "listDatabaseObjects"] for name in skip_names: if name.lower() in test["description"].lower(): self.skipTest(f"PyMongo does not support {name}") # Serverless does not support $out and collation. if client_context.serverless: for operation in test["operations"]: if operation["name"] == "aggregate": for stage in operation["arguments"]["pipeline"]: if "$out" in stage: self.skipTest("MongoDB Serverless does not support $out") if "collation" in operation["arguments"]: self.skipTest("MongoDB Serverless does not support collations") # Skip changeStream related tests on MMAPv1 and serverless. test_name = self.id().rsplit(".")[-1] if "changestream" in test_name.lower(): if client_context.storage_engine == "mmapv1": self.skipTest("MMAPv1 does not support change streams.") if client_context.serverless: self.skipTest("Serverless does not support change streams.") def get_scenario_coll_name(self, scenario_def): """Override a test's collection name to support GridFS tests.""" if "bucket_name" in scenario_def: return scenario_def["bucket_name"] return super().get_scenario_coll_name(scenario_def) def setup_scenario(self, scenario_def): """Override a test's setup to support GridFS tests.""" if "bucket_name" in scenario_def: data = scenario_def["data"] db_name = self.get_scenario_db_name(scenario_def) db = client_context.client[db_name] # Create a bucket for the retryable reads GridFS tests with as few # majority writes as possible. wc = WriteConcern(w="majority") if data: db["fs.chunks"].drop() db["fs.files"].drop() db["fs.chunks"].insert_many(data["fs.chunks"]) db.get_collection("fs.files", write_concern=wc).insert_many(data["fs.files"]) else: db.get_collection("fs.chunks").drop() db.get_collection("fs.files", write_concern=wc).drop() else: super().setup_scenario(scenario_def) def create_test(scenario_def, test, name): @client_context.require_test_commands def run_scenario(self): self.run_scenario(scenario_def, test) return run_scenario test_creator = SpecTestCreator(create_test, TestSpec, _TEST_PATH) test_creator.create_tests() class FindThread(threading.Thread): def __init__(self, collection): super().__init__() self.daemon = True self.collection = collection self.passed = False def run(self): self.collection.find_one({}) self.passed = True class TestPoolPausedError(IntegrationTest): # Pools don't get paused in load balanced mode. RUN_ON_LOAD_BALANCER = False RUN_ON_SERVERLESS = False @client_context.require_failCommand_blockConnection @client_knobs(heartbeat_frequency=0.05, min_heartbeat_interval=0.05) def test_pool_paused_error_is_retryable(self): if "PyPy" in sys.version: # Tracked in PYTHON-3519 self.skipTest("Test is flakey on PyPy") cmap_listener = CMAPListener() cmd_listener = OvertCommandListener() client = rs_or_single_client(maxPoolSize=1, event_listeners=[cmap_listener, cmd_listener]) self.addCleanup(client.close) for _ in range(10): cmap_listener.reset() cmd_listener.reset() threads = [FindThread(client.pymongo_test.test) for _ in range(2)] fail_command = { "mode": {"times": 1}, "data": { "failCommands": ["find"], "blockConnection": True, "blockTimeMS": 1000, "errorCode": 91, }, } with self.fail_point(fail_command): for thread in threads: thread.start() for thread in threads: thread.join() for thread in threads: self.assertTrue(thread.passed) # It's possible that SDAM can rediscover the server and mark the # pool ready before the thread in the wait queue has a chance # to run. Repeat the test until the thread actually encounters # a PoolClearedError. if cmap_listener.event_count(ConnectionCheckOutFailedEvent): break # Via CMAP monitoring, assert that the first check out succeeds. cmap_events = cmap_listener.events_by_type( (ConnectionCheckedOutEvent, ConnectionCheckOutFailedEvent, PoolClearedEvent) ) msg = pprint.pformat(cmap_listener.events) self.assertIsInstance(cmap_events[0], ConnectionCheckedOutEvent, msg) self.assertIsInstance(cmap_events[1], PoolClearedEvent, msg) self.assertIsInstance(cmap_events[2], ConnectionCheckOutFailedEvent, msg) self.assertEqual(cmap_events[2].reason, ConnectionCheckOutFailedReason.CONN_ERROR, msg) self.assertIsInstance(cmap_events[3], ConnectionCheckedOutEvent, msg) # Connection check out failures are not reflected in command # monitoring because we only publish command events _after_ checking # out a connection. started = cmd_listener.started_events msg = pprint.pformat(cmd_listener.results) self.assertEqual(3, len(started), msg) succeeded = cmd_listener.succeeded_events self.assertEqual(2, len(succeeded), msg) failed = cmd_listener.failed_events self.assertEqual(1, len(failed), msg) class TestRetryableReads(IntegrationTest): @client_context.require_multiple_mongoses @client_context.require_failCommand_fail_point def test_retryable_reads_in_sharded_cluster_multiple_available(self): fail_command = { "configureFailPoint": "failCommand", "mode": {"times": 1}, "data": { "failCommands": ["find"], "closeConnection": True, "appName": "retryableReadTest", }, } mongos_clients = [] for mongos in client_context.mongos_seeds().split(","): client = rs_or_single_client(mongos) set_fail_point(client, fail_command) self.addCleanup(client.close) mongos_clients.append(client) listener = OvertCommandListener() client = rs_or_single_client( client_context.mongos_seeds(), appName="retryableReadTest", event_listeners=[listener], retryReads=True, ) with self.fail_point(fail_command): with self.assertRaises(AutoReconnect): client.t.t.find_one({}) # Disable failpoints on each mongos for client in mongos_clients: fail_command["mode"] = "off" set_fail_point(client, fail_command) self.assertEqual(len(listener.failed_events), 2) self.assertEqual(len(listener.succeeded_events), 0) if __name__ == "__main__": unittest.main() mongodb-mongo-python-driver-509e9b7/test/test_retryable_reads_unified.py000066400000000000000000000020361462766011000267000ustar00rootroot00000000000000# Copyright 2022-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. """Test the Retryable Reads unified spec tests.""" from __future__ import annotations import sys from pathlib import Path sys.path[0:0] = [""] from test import unittest from test.unified_format import generate_test_classes # Location of JSON test specifications. TEST_PATH = Path(__file__).parent / "retryable_reads/unified" # Generate unified tests. globals().update(generate_test_classes(TEST_PATH, module=__name__)) if __name__ == "__main__": unittest.main() mongodb-mongo-python-driver-509e9b7/test/test_retryable_writes.py000066400000000000000000000671241462766011000254250ustar00rootroot00000000000000# Copyright 2017 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. """Test retryable writes.""" from __future__ import annotations import copy import os import pprint import sys import threading sys.path[0:0] = [""] from test import IntegrationTest, SkipTest, client_context, client_knobs, unittest from test.utils import ( CMAPListener, DeprecationFilter, EventListener, OvertCommandListener, SpecTestCreator, rs_or_single_client, set_fail_point, ) from test.utils_spec_runner import SpecRunner from test.version import Version from bson.codec_options import DEFAULT_CODEC_OPTIONS from bson.int64 import Int64 from bson.raw_bson import RawBSONDocument from bson.son import SON from pymongo.errors import ( AutoReconnect, ConnectionFailure, OperationFailure, ServerSelectionTimeoutError, WriteConcernError, ) from pymongo.mongo_client import MongoClient from pymongo.monitoring import ( CommandSucceededEvent, ConnectionCheckedOutEvent, ConnectionCheckOutFailedEvent, ConnectionCheckOutFailedReason, PoolClearedEvent, ) from pymongo.operations import ( DeleteMany, DeleteOne, InsertOne, ReplaceOne, UpdateMany, UpdateOne, ) from pymongo.write_concern import WriteConcern # Location of JSON test specifications. _TEST_PATH = os.path.join(os.path.dirname(os.path.realpath(__file__)), "retryable_writes", "legacy") class InsertEventListener(EventListener): def succeeded(self, event: CommandSucceededEvent) -> None: super().succeeded(event) if ( event.command_name == "insert" and event.reply.get("writeConcernError", {}).get("code", None) == 91 ): client_context.client.admin.command( { "configureFailPoint": "failCommand", "mode": {"times": 1}, "data": { "errorCode": 10107, "errorLabels": ["RetryableWriteError", "NoWritesPerformed"], "failCommands": ["insert"], }, } ) class TestAllScenarios(SpecRunner): RUN_ON_LOAD_BALANCER = True RUN_ON_SERVERLESS = True def get_object_name(self, op): return op.get("object", "collection") def get_scenario_db_name(self, scenario_def): return scenario_def.get("database_name", "pymongo_test") def get_scenario_coll_name(self, scenario_def): return scenario_def.get("collection_name", "test") def run_test_ops(self, sessions, collection, test): # Transform retryable writes spec format into transactions. operation = test["operation"] outcome = test["outcome"] if "error" in outcome: operation["error"] = outcome["error"] if "result" in outcome: operation["result"] = outcome["result"] test["operations"] = [operation] super().run_test_ops(sessions, collection, test) def create_test(scenario_def, test, name): @client_context.require_test_commands @client_context.require_no_mmap def run_scenario(self): self.run_scenario(scenario_def, test) return run_scenario test_creator = SpecTestCreator(create_test, TestAllScenarios, _TEST_PATH) test_creator.create_tests() def retryable_single_statement_ops(coll): return [ (coll.bulk_write, [[InsertOne({}), InsertOne({})]], {}), (coll.bulk_write, [[InsertOne({}), InsertOne({})]], {"ordered": False}), (coll.bulk_write, [[ReplaceOne({}, {"a1": 1})]], {}), (coll.bulk_write, [[ReplaceOne({}, {"a2": 1}), ReplaceOne({}, {"a3": 1})]], {}), ( coll.bulk_write, [[UpdateOne({}, {"$set": {"a4": 1}}), UpdateOne({}, {"$set": {"a5": 1}})]], {}, ), (coll.bulk_write, [[DeleteOne({})]], {}), (coll.bulk_write, [[DeleteOne({}), DeleteOne({})]], {}), (coll.insert_one, [{}], {}), (coll.insert_many, [[{}, {}]], {}), (coll.replace_one, [{}, {"a6": 1}], {}), (coll.update_one, [{}, {"$set": {"a7": 1}}], {}), (coll.delete_one, [{}], {}), (coll.find_one_and_replace, [{}, {"a8": 1}], {}), (coll.find_one_and_update, [{}, {"$set": {"a9": 1}}], {}), (coll.find_one_and_delete, [{}, {"a10": 1}], {}), ] def non_retryable_single_statement_ops(coll): return [ ( coll.bulk_write, [[UpdateOne({}, {"$set": {"a": 1}}), UpdateMany({}, {"$set": {"a": 1}})]], {}, ), (coll.bulk_write, [[DeleteOne({}), DeleteMany({})]], {}), (coll.update_many, [{}, {"$set": {"a": 1}}], {}), (coll.delete_many, [{}], {}), ] class IgnoreDeprecationsTest(IntegrationTest): RUN_ON_LOAD_BALANCER = True RUN_ON_SERVERLESS = True deprecation_filter: DeprecationFilter @classmethod def setUpClass(cls): super().setUpClass() cls.deprecation_filter = DeprecationFilter() @classmethod def tearDownClass(cls): cls.deprecation_filter.stop() super().tearDownClass() class TestRetryableWritesMMAPv1(IgnoreDeprecationsTest): knobs: client_knobs @classmethod def setUpClass(cls): super().setUpClass() # Speed up the tests by decreasing the heartbeat frequency. cls.knobs = client_knobs(heartbeat_frequency=0.1, min_heartbeat_interval=0.1) cls.knobs.enable() cls.client = rs_or_single_client(retryWrites=True) cls.db = cls.client.pymongo_test @classmethod def tearDownClass(cls): cls.knobs.disable() cls.client.close() super().tearDownClass() @client_context.require_no_standalone def test_actionable_error_message(self): if client_context.storage_engine != "mmapv1": raise SkipTest("This cluster is not running MMAPv1") expected_msg = ( "This MongoDB deployment does not support retryable " "writes. Please add retryWrites=false to your " "connection string." ) for method, args, kwargs in retryable_single_statement_ops(self.db.retryable_write_test): with self.assertRaisesRegex(OperationFailure, expected_msg): method(*args, **kwargs) class TestRetryableWrites(IgnoreDeprecationsTest): listener: OvertCommandListener knobs: client_knobs @classmethod @client_context.require_no_mmap def setUpClass(cls): super().setUpClass() # Speed up the tests by decreasing the heartbeat frequency. cls.knobs = client_knobs(heartbeat_frequency=0.1, min_heartbeat_interval=0.1) cls.knobs.enable() cls.listener = OvertCommandListener() cls.client = rs_or_single_client(retryWrites=True, event_listeners=[cls.listener]) cls.db = cls.client.pymongo_test @classmethod def tearDownClass(cls): cls.knobs.disable() cls.client.close() super().tearDownClass() def setUp(self): if client_context.is_rs and client_context.test_commands_enabled: self.client.admin.command( SON([("configureFailPoint", "onPrimaryTransactionalWrite"), ("mode", "alwaysOn")]) ) def tearDown(self): if client_context.is_rs and client_context.test_commands_enabled: self.client.admin.command( SON([("configureFailPoint", "onPrimaryTransactionalWrite"), ("mode", "off")]) ) def test_supported_single_statement_no_retry(self): listener = OvertCommandListener() client = rs_or_single_client(retryWrites=False, event_listeners=[listener]) self.addCleanup(client.close) for method, args, kwargs in retryable_single_statement_ops(client.db.retryable_write_test): msg = f"{method.__name__}(*{args!r}, **{kwargs!r})" listener.reset() method(*args, **kwargs) for event in listener.started_events: self.assertNotIn( "txnNumber", event.command, f"{msg} sent txnNumber with {event.command_name}", ) @client_context.require_no_standalone def test_supported_single_statement_supported_cluster(self): for method, args, kwargs in retryable_single_statement_ops(self.db.retryable_write_test): msg = f"{method.__name__}(*{args!r}, **{kwargs!r})" self.listener.reset() method(*args, **kwargs) commands_started = self.listener.started_events self.assertEqual(len(self.listener.succeeded_events), 1, msg) first_attempt = commands_started[0] self.assertIn( "lsid", first_attempt.command, f"{msg} sent no lsid with {first_attempt.command_name}", ) initial_session_id = first_attempt.command["lsid"] self.assertIn( "txnNumber", first_attempt.command, f"{msg} sent no txnNumber with {first_attempt.command_name}", ) # There should be no retry when the failpoint is not active. if client_context.is_mongos or not client_context.test_commands_enabled: self.assertEqual(len(commands_started), 1) continue initial_transaction_id = first_attempt.command["txnNumber"] retry_attempt = commands_started[1] self.assertIn( "lsid", retry_attempt.command, f"{msg} sent no lsid with {first_attempt.command_name}", ) self.assertEqual(retry_attempt.command["lsid"], initial_session_id, msg) self.assertIn( "txnNumber", retry_attempt.command, f"{msg} sent no txnNumber with {first_attempt.command_name}", ) self.assertEqual(retry_attempt.command["txnNumber"], initial_transaction_id, msg) def test_supported_single_statement_unsupported_cluster(self): if client_context.is_rs or client_context.is_mongos: raise SkipTest("This cluster supports retryable writes") for method, args, kwargs in retryable_single_statement_ops(self.db.retryable_write_test): msg = f"{method.__name__}(*{args!r}, **{kwargs!r})" self.listener.reset() method(*args, **kwargs) for event in self.listener.started_events: self.assertNotIn( "txnNumber", event.command, f"{msg} sent txnNumber with {event.command_name}", ) def test_unsupported_single_statement(self): coll = self.db.retryable_write_test coll.insert_many([{}, {}]) coll_w0 = coll.with_options(write_concern=WriteConcern(w=0)) for method, args, kwargs in non_retryable_single_statement_ops( coll ) + retryable_single_statement_ops(coll_w0): msg = f"{method.__name__}(*{args!r}, **{kwargs!r})" self.listener.reset() method(*args, **kwargs) started_events = self.listener.started_events self.assertEqual(len(self.listener.succeeded_events), len(started_events), msg) self.assertEqual(len(self.listener.failed_events), 0, msg) for event in started_events: self.assertNotIn( "txnNumber", event.command, f"{msg} sent txnNumber with {event.command_name}", ) def test_server_selection_timeout_not_retried(self): """A ServerSelectionTimeoutError is not retried.""" listener = OvertCommandListener() client = MongoClient( "somedomainthatdoesntexist.org", serverSelectionTimeoutMS=1, retryWrites=True, event_listeners=[listener], ) for method, args, kwargs in retryable_single_statement_ops(client.db.retryable_write_test): msg = f"{method.__name__}(*{args!r}, **{kwargs!r})" listener.reset() with self.assertRaises(ServerSelectionTimeoutError, msg=msg): method(*args, **kwargs) self.assertEqual(len(listener.started_events), 0, msg) @client_context.require_replica_set @client_context.require_test_commands def test_retry_timeout_raises_original_error(self): """A ServerSelectionTimeoutError on the retry attempt raises the original error. """ listener = OvertCommandListener() client = rs_or_single_client(retryWrites=True, event_listeners=[listener]) self.addCleanup(client.close) topology = client._topology select_server = topology.select_server def mock_select_server(*args, **kwargs): server = select_server(*args, **kwargs) def raise_error(*args, **kwargs): raise ServerSelectionTimeoutError("No primary available for writes") # Raise ServerSelectionTimeout on the retry attempt. topology.select_server = raise_error return server for method, args, kwargs in retryable_single_statement_ops(client.db.retryable_write_test): msg = f"{method.__name__}(*{args!r}, **{kwargs!r})" listener.reset() topology.select_server = mock_select_server with self.assertRaises(ConnectionFailure, msg=msg): method(*args, **kwargs) self.assertEqual(len(listener.started_events), 1, msg) @client_context.require_replica_set @client_context.require_test_commands def test_batch_splitting(self): """Test retry succeeds after failures during batch splitting.""" large = "s" * 1024 * 1024 * 15 coll = self.db.retryable_write_test coll.delete_many({}) self.listener.reset() bulk_result = coll.bulk_write( [ InsertOne({"_id": 1, "l": large}), InsertOne({"_id": 2, "l": large}), InsertOne({"_id": 3, "l": large}), UpdateOne({"_id": 1, "l": large}, {"$unset": {"l": 1}, "$inc": {"count": 1}}), UpdateOne({"_id": 2, "l": large}, {"$set": {"foo": "bar"}}), DeleteOne({"l": large}), DeleteOne({"l": large}), ] ) # Each command should fail and be retried. # With OP_MSG 3 inserts are one batch. 2 updates another. # 2 deletes a third. self.assertEqual(len(self.listener.started_events), 6) self.assertEqual(coll.find_one(), {"_id": 1, "count": 1}) # Assert the final result expected_result = { "writeErrors": [], "writeConcernErrors": [], "nInserted": 3, "nUpserted": 0, "nMatched": 2, "nModified": 2, "nRemoved": 2, "upserted": [], } self.assertEqual(bulk_result.bulk_api_result, expected_result) @client_context.require_replica_set @client_context.require_test_commands def test_batch_splitting_retry_fails(self): """Test retry fails during batch splitting.""" large = "s" * 1024 * 1024 * 15 coll = self.db.retryable_write_test coll.delete_many({}) self.client.admin.command( SON( [ ("configureFailPoint", "onPrimaryTransactionalWrite"), ("mode", {"skip": 3}), # The number of _documents_ to skip. ("data", {"failBeforeCommitExceptionCode": 1}), ] ) ) self.listener.reset() with self.client.start_session() as session: initial_txn = session._transaction_id try: coll.bulk_write( [ InsertOne({"_id": 1, "l": large}), InsertOne({"_id": 2, "l": large}), InsertOne({"_id": 3, "l": large}), InsertOne({"_id": 4, "l": large}), ], session=session, ) except ConnectionFailure: pass else: self.fail("bulk_write should have failed") started = self.listener.started_events self.assertEqual(len(started), 3) self.assertEqual(len(self.listener.succeeded_events), 1) expected_txn = Int64(initial_txn + 1) self.assertEqual(started[0].command["txnNumber"], expected_txn) self.assertEqual(started[0].command["lsid"], session.session_id) expected_txn = Int64(initial_txn + 2) self.assertEqual(started[1].command["txnNumber"], expected_txn) self.assertEqual(started[1].command["lsid"], session.session_id) started[1].command.pop("$clusterTime") started[2].command.pop("$clusterTime") self.assertEqual(started[1].command, started[2].command) final_txn = session._transaction_id self.assertEqual(final_txn, expected_txn) self.assertEqual(coll.find_one(projection={"_id": True}), {"_id": 1}) @client_context.require_multiple_mongoses @client_context.require_failCommand_fail_point def test_retryable_writes_in_sharded_cluster_multiple_available(self): fail_command = { "configureFailPoint": "failCommand", "mode": {"times": 1}, "data": { "failCommands": ["insert"], "closeConnection": True, "appName": "retryableWriteTest", }, } mongos_clients = [] for mongos in client_context.mongos_seeds().split(","): client = rs_or_single_client(mongos) set_fail_point(client, fail_command) self.addCleanup(client.close) mongos_clients.append(client) listener = OvertCommandListener() client = rs_or_single_client( client_context.mongos_seeds(), appName="retryableWriteTest", event_listeners=[listener], retryWrites=True, ) with self.assertRaises(AutoReconnect): client.t.t.insert_one({"x": 1}) # Disable failpoints on each mongos for client in mongos_clients: fail_command["mode"] = "off" set_fail_point(client, fail_command) self.assertEqual(len(listener.failed_events), 2) self.assertEqual(len(listener.succeeded_events), 0) class TestWriteConcernError(IntegrationTest): RUN_ON_LOAD_BALANCER = True RUN_ON_SERVERLESS = True fail_insert: dict @classmethod @client_context.require_replica_set @client_context.require_no_mmap @client_context.require_failCommand_fail_point def setUpClass(cls): super().setUpClass() cls.fail_insert = { "configureFailPoint": "failCommand", "mode": {"times": 2}, "data": { "failCommands": ["insert"], "writeConcernError": {"code": 91, "errmsg": "Replication is being shut down"}, }, } @client_context.require_version_min(4, 0) @client_knobs(heartbeat_frequency=0.05, min_heartbeat_interval=0.05) def test_RetryableWriteError_error_label(self): listener = OvertCommandListener() client = rs_or_single_client(retryWrites=True, event_listeners=[listener]) self.addCleanup(client.close) # Ensure collection exists. client.pymongo_test.testcoll.insert_one({}) with self.fail_point(self.fail_insert): with self.assertRaises(WriteConcernError) as cm: client.pymongo_test.testcoll.insert_one({}) self.assertTrue(cm.exception.has_error_label("RetryableWriteError")) if client_context.version >= Version(4, 4): # In MongoDB 4.4+ we rely on the server returning the error label. self.assertIn("RetryableWriteError", listener.succeeded_events[-1].reply["errorLabels"]) @client_context.require_version_min(4, 4) def test_RetryableWriteError_error_label_RawBSONDocument(self): # using RawBSONDocument should not cause errorLabel parsing to fail with self.fail_point(self.fail_insert): with self.client.start_session() as s: s._start_retryable_write() result = self.client.pymongo_test.command( "insert", "testcoll", documents=[{"_id": 1}], txnNumber=s._transaction_id, session=s, codec_options=DEFAULT_CODEC_OPTIONS.with_options( document_class=RawBSONDocument ), ) self.assertIn("writeConcernError", result) self.assertIn("RetryableWriteError", result["errorLabels"]) class InsertThread(threading.Thread): def __init__(self, collection): super().__init__() self.daemon = True self.collection = collection self.passed = False def run(self): self.collection.insert_one({}) self.passed = True class TestPoolPausedError(IntegrationTest): # Pools don't get paused in load balanced mode. RUN_ON_LOAD_BALANCER = False RUN_ON_SERVERLESS = False @client_context.require_failCommand_blockConnection @client_context.require_retryable_writes @client_knobs(heartbeat_frequency=0.05, min_heartbeat_interval=0.05) def test_pool_paused_error_is_retryable(self): cmap_listener = CMAPListener() cmd_listener = OvertCommandListener() client = rs_or_single_client(maxPoolSize=1, event_listeners=[cmap_listener, cmd_listener]) self.addCleanup(client.close) for _ in range(10): cmap_listener.reset() cmd_listener.reset() threads = [InsertThread(client.pymongo_test.test) for _ in range(2)] fail_command = { "mode": {"times": 1}, "data": { "failCommands": ["insert"], "blockConnection": True, "blockTimeMS": 1000, "errorCode": 91, "errorLabels": ["RetryableWriteError"], }, } with self.fail_point(fail_command): for thread in threads: thread.start() for thread in threads: thread.join() for thread in threads: self.assertTrue(thread.passed) # It's possible that SDAM can rediscover the server and mark the # pool ready before the thread in the wait queue has a chance # to run. Repeat the test until the thread actually encounters # a PoolClearedError. if cmap_listener.event_count(ConnectionCheckOutFailedEvent): break # Via CMAP monitoring, assert that the first check out succeeds. cmap_events = cmap_listener.events_by_type( (ConnectionCheckedOutEvent, ConnectionCheckOutFailedEvent, PoolClearedEvent) ) msg = pprint.pformat(cmap_listener.events) self.assertIsInstance(cmap_events[0], ConnectionCheckedOutEvent, msg) self.assertIsInstance(cmap_events[1], PoolClearedEvent, msg) self.assertIsInstance(cmap_events[2], ConnectionCheckOutFailedEvent, msg) self.assertEqual(cmap_events[2].reason, ConnectionCheckOutFailedReason.CONN_ERROR, msg) self.assertIsInstance(cmap_events[3], ConnectionCheckedOutEvent, msg) # Connection check out failures are not reflected in command # monitoring because we only publish command events _after_ checking # out a connection. started = cmd_listener.started_events msg = pprint.pformat(cmd_listener.results) self.assertEqual(3, len(started), msg) succeeded = cmd_listener.succeeded_events self.assertEqual(2, len(succeeded), msg) failed = cmd_listener.failed_events self.assertEqual(1, len(failed), msg) @client_context.require_failCommand_fail_point @client_context.require_replica_set @client_context.require_version_min( 6, 0, 0 ) # the spec requires that this prose test only be run on 6.0+ @client_knobs(heartbeat_frequency=0.05, min_heartbeat_interval=0.05) def test_returns_original_error_code( self, ): cmd_listener = InsertEventListener() client = rs_or_single_client(retryWrites=True, event_listeners=[cmd_listener]) client.test.test.drop() self.addCleanup(client.close) cmd_listener.reset() client.admin.command( { "configureFailPoint": "failCommand", "mode": {"times": 1}, "data": { "writeConcernError": { "code": 91, "errorLabels": ["RetryableWriteError"], }, "failCommands": ["insert"], }, } ) with self.assertRaises(WriteConcernError) as exc: client.test.test.insert_one({"_id": 1}) self.assertEqual(exc.exception.code, 91) client.admin.command( { "configureFailPoint": "failCommand", "mode": "off", } ) # TODO: Make this a real integration test where we stepdown the primary. class TestRetryableWritesTxnNumber(IgnoreDeprecationsTest): @client_context.require_replica_set @client_context.require_no_mmap def test_increment_transaction_id_without_sending_command(self): """Test that the txnNumber field is properly incremented, even when the first attempt fails before sending the command. """ listener = OvertCommandListener() client = rs_or_single_client(retryWrites=True, event_listeners=[listener]) self.addCleanup(client.close) topology = client._topology select_server = topology.select_server def raise_connection_err_select_server(*args, **kwargs): # Raise ConnectionFailure on the first attempt and perform # normal selection on the retry attempt. topology.select_server = select_server raise ConnectionFailure("Connection refused") for method, args, kwargs in retryable_single_statement_ops(client.db.retryable_write_test): listener.reset() topology.select_server = raise_connection_err_select_server with client.start_session() as session: kwargs = copy.deepcopy(kwargs) kwargs["session"] = session msg = f"{method.__name__}(*{args!r}, **{kwargs!r})" initial_txn_id = session._transaction_id # Each operation should fail on the first attempt and succeed # on the second. method(*args, **kwargs) self.assertEqual(len(listener.started_events), 1, msg) retry_cmd = listener.started_events[0].command sent_txn_id = retry_cmd["txnNumber"] final_txn_id = session._transaction_id self.assertEqual(Int64(initial_txn_id + 1), sent_txn_id, msg) self.assertEqual(sent_txn_id, final_txn_id, msg) if __name__ == "__main__": unittest.main() mongodb-mongo-python-driver-509e9b7/test/test_retryable_writes_unified.py000066400000000000000000000020671462766011000271230ustar00rootroot00000000000000# Copyright 2021-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. """Test the Retryable Writes unified spec tests.""" from __future__ import annotations import os import sys sys.path[0:0] = [""] from test import unittest from test.unified_format import generate_test_classes # Location of JSON test specifications. TEST_PATH = os.path.join(os.path.dirname(os.path.realpath(__file__)), "retryable_writes", "unified") # Generate unified tests. globals().update(generate_test_classes(TEST_PATH, module=__name__)) if __name__ == "__main__": unittest.main() mongodb-mongo-python-driver-509e9b7/test/test_run_command.py000066400000000000000000000005711462766011000243320ustar00rootroot00000000000000from __future__ import annotations import os import unittest from test.unified_format import generate_test_classes _TEST_PATH = os.path.join(os.path.dirname(os.path.realpath(__file__)), "run_command") globals().update( generate_test_classes( os.path.join(_TEST_PATH, "unified"), module=__name__, ) ) if __name__ == "__main__": unittest.main() mongodb-mongo-python-driver-509e9b7/test/test_saslprep.py000066400000000000000000000030641462766011000236610ustar00rootroot00000000000000# Copyright 2016-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. from __future__ import annotations import sys sys.path[0:0] = [""] from test import unittest from pymongo.saslprep import saslprep class TestSASLprep(unittest.TestCase): def test_saslprep(self): try: import stringprep except ImportError: self.assertRaises(TypeError, saslprep, "anything...") # Bytes strings are ignored. self.assertEqual(saslprep(b"user"), b"user") else: # Examples from RFC4013, Section 3. self.assertEqual(saslprep("I\u00ADX"), "IX") self.assertEqual(saslprep("user"), "user") self.assertEqual(saslprep("USER"), "USER") self.assertEqual(saslprep("\u00AA"), "a") self.assertEqual(saslprep("\u2168"), "IX") self.assertRaises(ValueError, saslprep, "\u0007") self.assertRaises(ValueError, saslprep, "\u0627\u0031") # Bytes strings are ignored. self.assertEqual(saslprep(b"user"), b"user") mongodb-mongo-python-driver-509e9b7/test/test_sdam_monitoring_spec.py000066400000000000000000000324671462766011000262440ustar00rootroot00000000000000# Copyright 2016 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. """Run the sdam monitoring spec tests.""" from __future__ import annotations import json import os import sys import time sys.path[0:0] = [""] from test import IntegrationTest, client_context, client_knobs, unittest from test.utils import ( ServerAndTopologyEventListener, rs_or_single_client, server_name_to_type, wait_until, ) from bson.json_util import object_hook from pymongo import MongoClient, monitoring from pymongo.collection import Collection from pymongo.common import clean_node from pymongo.errors import ConnectionFailure, NotPrimaryError from pymongo.hello import Hello from pymongo.monitor import Monitor from pymongo.server_description import ServerDescription from pymongo.topology_description import TOPOLOGY_TYPE # Location of JSON test specifications. _TEST_PATH = os.path.join(os.path.dirname(os.path.realpath(__file__)), "sdam_monitoring") def compare_server_descriptions(expected, actual): if (expected["address"] != "{}:{}".format(*actual.address)) or ( server_name_to_type(expected["type"]) != actual.server_type ): return False expected_hosts = set(expected["arbiters"] + expected["passives"] + expected["hosts"]) return expected_hosts == {"{}:{}".format(*s) for s in actual.all_hosts} def compare_topology_descriptions(expected, actual): if TOPOLOGY_TYPE.__getattribute__(expected["topologyType"]) != actual.topology_type: return False expected = expected["servers"] actual = actual.server_descriptions() if len(expected) != len(actual): return False for exp_server in expected: for _address, actual_server in actual.items(): if compare_server_descriptions(exp_server, actual_server): break else: return False return True def compare_events(expected_dict, actual): if not expected_dict: return False, "Error: Bad expected value in YAML test" if not actual: return False, "Error: Event published was None" expected_type, expected = list(expected_dict.items())[0] if expected_type == "server_opening_event": if not isinstance(actual, monitoring.ServerOpeningEvent): return False, "Expected ServerOpeningEvent, got %s" % (actual.__class__) if expected["address"] != "{}:{}".format(*actual.server_address): return ( False, "ServerOpeningEvent published with wrong address (expected" " {}, got {}".format( expected["address"], actual.server_address ), ) elif expected_type == "server_description_changed_event": if not isinstance(actual, monitoring.ServerDescriptionChangedEvent): return (False, "Expected ServerDescriptionChangedEvent, got %s" % (actual.__class__)) if expected["address"] != "{}:{}".format(*actual.server_address): return ( False, "ServerDescriptionChangedEvent has wrong address" " (expected {}, got {}".format( expected["address"], actual.server_address ), ) if not compare_server_descriptions(expected["newDescription"], actual.new_description): return (False, "New ServerDescription incorrect in ServerDescriptionChangedEvent") if not compare_server_descriptions( expected["previousDescription"], actual.previous_description ): return ( False, "Previous ServerDescription incorrect in ServerDescriptionChangedEvent", ) elif expected_type == "server_closed_event": if not isinstance(actual, monitoring.ServerClosedEvent): return False, "Expected ServerClosedEvent, got %s" % (actual.__class__) if expected["address"] != "{}:{}".format(*actual.server_address): return ( False, "ServerClosedEvent published with wrong address" " (expected {}, got {}".format( expected["address"], actual.server_address ), ) elif expected_type == "topology_opening_event": if not isinstance(actual, monitoring.TopologyOpenedEvent): return False, "Expected TopologyOpeningEvent, got %s" % (actual.__class__) elif expected_type == "topology_description_changed_event": if not isinstance(actual, monitoring.TopologyDescriptionChangedEvent): return ( False, "Expected TopologyDescriptionChangedEvent, got %s" % (actual.__class__), ) if not compare_topology_descriptions(expected["newDescription"], actual.new_description): return ( False, "New TopologyDescription incorrect in TopologyDescriptionChangedEvent", ) if not compare_topology_descriptions( expected["previousDescription"], actual.previous_description ): return ( False, "Previous TopologyDescription incorrect in TopologyDescriptionChangedEvent", ) elif expected_type == "topology_closed_event": if not isinstance(actual, monitoring.TopologyClosedEvent): return False, "Expected TopologyClosedEvent, got %s" % (actual.__class__) else: return False, f"Incorrect event: expected {expected_type}, actual {actual}" return True, "" def compare_multiple_events(i, expected_results, actual_results): events_in_a_row = [] j = i while j < len(expected_results) and isinstance(actual_results[j], actual_results[i].__class__): events_in_a_row.append(actual_results[j]) j += 1 message = "" for event in events_in_a_row: for k in range(i, j): passed, message = compare_events(expected_results[k], event) if passed: expected_results[k] = None break else: return i, False, message return j, True, "" class TestAllScenarios(IntegrationTest): def setUp(self): super().setUp() self.all_listener = ServerAndTopologyEventListener() def create_test(scenario_def): def run_scenario(self): with client_knobs(events_queue_frequency=0.1): _run_scenario(self) def _run_scenario(self): class NoopMonitor(Monitor): """Override the _run method to do nothing.""" def _run(self): time.sleep(0.05) m = MongoClient( host=scenario_def["uri"], port=27017, event_listeners=[self.all_listener], _monitor_class=NoopMonitor, ) topology = m._get_topology() try: for phase in scenario_def["phases"]: for source, response in phase.get("responses", []): source_address = clean_node(source) topology.on_change( ServerDescription( address=source_address, hello=Hello(response), round_trip_time=0 ) ) expected_results = phase["outcome"]["events"] expected_len = len(expected_results) wait_until( lambda: len(self.all_listener.results) >= expected_len, "publish all events", timeout=15, ) # Wait some time to catch possible lagging extra events. time.sleep(0.5) i = 0 while i < expected_len: result = ( self.all_listener.results[i] if len(self.all_listener.results) > i else None ) # The order of ServerOpening/ClosedEvents doesn't matter if isinstance( result, (monitoring.ServerOpeningEvent, monitoring.ServerClosedEvent) ): i, passed, message = compare_multiple_events( i, expected_results, self.all_listener.results ) self.assertTrue(passed, message) else: self.assertTrue(*compare_events(expected_results[i], result)) i += 1 # Assert no extra events. extra_events = self.all_listener.results[expected_len:] if extra_events: self.fail(f"Extra events {extra_events!r}") self.all_listener.reset() finally: m.close() return run_scenario def create_tests(): for dirpath, _, filenames in os.walk(_TEST_PATH): for filename in filenames: with open(os.path.join(dirpath, filename)) as scenario_stream: scenario_def = json.load(scenario_stream, object_hook=object_hook) # Construct test from scenario. new_test = create_test(scenario_def) test_name = f"test_{os.path.splitext(filename)[0]}" new_test.__name__ = test_name setattr(TestAllScenarios, new_test.__name__, new_test) create_tests() class TestSdamMonitoring(IntegrationTest): knobs: client_knobs listener: ServerAndTopologyEventListener test_client: MongoClient coll: Collection @classmethod @client_context.require_failCommand_fail_point def setUpClass(cls): super().setUpClass() # Speed up the tests by decreasing the event publish frequency. cls.knobs = client_knobs(events_queue_frequency=0.1) cls.knobs.enable() cls.listener = ServerAndTopologyEventListener() retry_writes = client_context.supports_transactions() cls.test_client = rs_or_single_client( event_listeners=[cls.listener], retryWrites=retry_writes ) cls.coll = cls.test_client[cls.client.db.name].test cls.coll.insert_one({}) @classmethod def tearDownClass(cls): cls.test_client.close() cls.knobs.disable() super().tearDownClass() def setUp(self): self.listener.reset() def _test_app_error(self, fail_command_opts, expected_error): address = self.test_client.address # Test that an application error causes a ServerDescriptionChangedEvent # to be published. data = {"failCommands": ["insert"]} data.update(fail_command_opts) fail_insert = { "configureFailPoint": "failCommand", "mode": {"times": 1}, "data": data, } with self.fail_point(fail_insert): if self.test_client.options.retry_writes: self.coll.insert_one({}) else: with self.assertRaises(expected_error): self.coll.insert_one({}) self.coll.insert_one({}) def marked_unknown(event): return ( isinstance(event, monitoring.ServerDescriptionChangedEvent) and event.server_address == address and not event.new_description.is_server_type_known ) def discovered_node(event): return ( isinstance(event, monitoring.ServerDescriptionChangedEvent) and event.server_address == address and not event.previous_description.is_server_type_known and event.new_description.is_server_type_known ) def marked_unknown_and_rediscovered(): return ( len(self.listener.matching(marked_unknown)) >= 1 and len(self.listener.matching(discovered_node)) >= 1 ) # Topology events are published asynchronously wait_until(marked_unknown_and_rediscovered, "rediscover node") # Expect a single ServerDescriptionChangedEvent for the network error. marked_unknown_events = self.listener.matching(marked_unknown) self.assertEqual(len(marked_unknown_events), 1, marked_unknown_events) self.assertIsInstance(marked_unknown_events[0].new_description.error, expected_error) def test_network_error_publishes_events(self): self._test_app_error({"closeConnection": True}, ConnectionFailure) # In 4.4+, not primary errors from failCommand don't cause SDAM state # changes because topologyVersion is not incremented. @client_context.require_version_max(4, 3) def test_not_primary_error_publishes_events(self): self._test_app_error( {"errorCode": 10107, "closeConnection": False, "errorLabels": ["RetryableWriteError"]}, NotPrimaryError, ) def test_shutdown_error_publishes_events(self): self._test_app_error( {"errorCode": 91, "closeConnection": False, "errorLabels": ["RetryableWriteError"]}, NotPrimaryError, ) if __name__ == "__main__": unittest.main() mongodb-mongo-python-driver-509e9b7/test/test_server.py000066400000000000000000000022271462766011000233360ustar00rootroot00000000000000# Copyright 2014-2015 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. """Test the server module.""" from __future__ import annotations import sys sys.path[0:0] = [""] from test import unittest from pymongo.hello import Hello from pymongo.server import Server from pymongo.server_description import ServerDescription class TestServer(unittest.TestCase): def test_repr(self): hello = Hello({"ok": 1}) sd = ServerDescription(("localhost", 27017), hello) server = Server(sd, pool=object(), monitor=object()) # type: ignore[arg-type] self.assertTrue("Standalone" in str(server)) if __name__ == "__main__": unittest.main() mongodb-mongo-python-driver-509e9b7/test/test_server_description.py000066400000000000000000000160131462766011000257370ustar00rootroot00000000000000# Copyright 2014-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. """Test the server_description module.""" from __future__ import annotations import sys sys.path[0:0] = [""] from test import unittest from bson.int64 import Int64 from bson.objectid import ObjectId from pymongo.hello import Hello, HelloCompat from pymongo.server_description import ServerDescription from pymongo.server_type import SERVER_TYPE address = ("localhost", 27017) def parse_hello_response(doc): hello_response = Hello(doc) return ServerDescription(address, hello_response) class TestServerDescription(unittest.TestCase): def test_unknown(self): # Default, no hello_response. s = ServerDescription(address) self.assertEqual(SERVER_TYPE.Unknown, s.server_type) self.assertFalse(s.is_writable) self.assertFalse(s.is_readable) def test_mongos(self): s = parse_hello_response({"ok": 1, "msg": "isdbgrid"}) self.assertEqual(SERVER_TYPE.Mongos, s.server_type) self.assertEqual("Mongos", s.server_type_name) self.assertTrue(s.is_writable) self.assertTrue(s.is_readable) def test_primary(self): s = parse_hello_response({"ok": 1, HelloCompat.LEGACY_CMD: True, "setName": "rs"}) self.assertEqual(SERVER_TYPE.RSPrimary, s.server_type) self.assertEqual("RSPrimary", s.server_type_name) self.assertTrue(s.is_writable) self.assertTrue(s.is_readable) def test_secondary(self): s = parse_hello_response( {"ok": 1, HelloCompat.LEGACY_CMD: False, "secondary": True, "setName": "rs"} ) self.assertEqual(SERVER_TYPE.RSSecondary, s.server_type) self.assertEqual("RSSecondary", s.server_type_name) self.assertFalse(s.is_writable) self.assertTrue(s.is_readable) def test_arbiter(self): s = parse_hello_response( {"ok": 1, HelloCompat.LEGACY_CMD: False, "arbiterOnly": True, "setName": "rs"} ) self.assertEqual(SERVER_TYPE.RSArbiter, s.server_type) self.assertEqual("RSArbiter", s.server_type_name) self.assertFalse(s.is_writable) self.assertFalse(s.is_readable) def test_other(self): s = parse_hello_response({"ok": 1, HelloCompat.LEGACY_CMD: False, "setName": "rs"}) self.assertEqual(SERVER_TYPE.RSOther, s.server_type) self.assertEqual("RSOther", s.server_type_name) s = parse_hello_response( { "ok": 1, HelloCompat.LEGACY_CMD: False, "secondary": True, "hidden": True, "setName": "rs", } ) self.assertEqual(SERVER_TYPE.RSOther, s.server_type) self.assertFalse(s.is_writable) self.assertFalse(s.is_readable) def test_ghost(self): s = parse_hello_response({"ok": 1, "isreplicaset": True}) self.assertEqual(SERVER_TYPE.RSGhost, s.server_type) self.assertEqual("RSGhost", s.server_type_name) self.assertFalse(s.is_writable) self.assertFalse(s.is_readable) def test_fields(self): s = parse_hello_response( { "ok": 1, HelloCompat.LEGACY_CMD: False, "secondary": True, "primary": "a:27017", "tags": {"a": "foo", "b": "baz"}, "maxMessageSizeBytes": 1, "maxBsonObjectSize": 2, "maxWriteBatchSize": 3, "minWireVersion": 4, "maxWireVersion": 5, "setName": "rs", } ) self.assertEqual(SERVER_TYPE.RSSecondary, s.server_type) self.assertEqual(("a", 27017), s.primary) self.assertEqual({"a": "foo", "b": "baz"}, s.tags) self.assertEqual(1, s.max_message_size) self.assertEqual(2, s.max_bson_size) self.assertEqual(3, s.max_write_batch_size) self.assertEqual(4, s.min_wire_version) self.assertEqual(5, s.max_wire_version) def test_default_max_message_size(self): s = parse_hello_response({"ok": 1, HelloCompat.LEGACY_CMD: True, "maxBsonObjectSize": 2}) # Twice max_bson_size. self.assertEqual(4, s.max_message_size) def test_standalone(self): s = parse_hello_response({"ok": 1, HelloCompat.LEGACY_CMD: True}) self.assertEqual(SERVER_TYPE.Standalone, s.server_type) # Mongod started with --slave. # master-slave replication was removed in MongoDB 4.0. s = parse_hello_response({"ok": 1, HelloCompat.LEGACY_CMD: False}) self.assertEqual(SERVER_TYPE.Standalone, s.server_type) self.assertTrue(s.is_writable) self.assertTrue(s.is_readable) def test_ok_false(self): s = parse_hello_response({"ok": 0, HelloCompat.LEGACY_CMD: True}) self.assertEqual(SERVER_TYPE.Unknown, s.server_type) self.assertFalse(s.is_writable) self.assertFalse(s.is_readable) def test_all_hosts(self): s = parse_hello_response( { "ok": 1, HelloCompat.LEGACY_CMD: True, "hosts": ["a"], "passives": ["b:27018"], "arbiters": ["c"], } ) self.assertEqual([("a", 27017), ("b", 27018), ("c", 27017)], sorted(s.all_hosts)) def test_repr(self): s = parse_hello_response({"ok": 1, "msg": "isdbgrid"}) self.assertEqual( repr(s), "" ) def test_topology_version(self): topology_version = {"processId": ObjectId(), "counter": Int64("0")} s = parse_hello_response( { "ok": 1, HelloCompat.LEGACY_CMD: True, "setName": "rs", "topologyVersion": topology_version, } ) self.assertEqual(SERVER_TYPE.RSPrimary, s.server_type) self.assertEqual(topology_version, s.topology_version) # Resetting a server to unknown preserves topology_version. s_unknown = s.to_unknown() self.assertEqual(SERVER_TYPE.Unknown, s_unknown.server_type) self.assertEqual(topology_version, s_unknown.topology_version) def test_topology_version_not_present(self): # No topologyVersion field. s = parse_hello_response({"ok": 1, HelloCompat.LEGACY_CMD: True, "setName": "rs"}) self.assertEqual(SERVER_TYPE.RSPrimary, s.server_type) self.assertEqual(None, s.topology_version) if __name__ == "__main__": unittest.main() mongodb-mongo-python-driver-509e9b7/test/test_server_selection.py000066400000000000000000000200711462766011000254000ustar00rootroot00000000000000# Copyright 2015-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. """Test the topology module's Server Selection Spec implementation.""" from __future__ import annotations import os import sys from pymongo import MongoClient, ReadPreference from pymongo.errors import ServerSelectionTimeoutError from pymongo.hello import HelloCompat from pymongo.operations import _Op from pymongo.server_selectors import writable_server_selector from pymongo.settings import TopologySettings from pymongo.topology import Topology from pymongo.typings import strip_optional sys.path[0:0] = [""] from test import IntegrationTest, client_context, unittest from test.utils import ( EventListener, FunctionCallRecorder, rs_or_single_client, wait_until, ) from test.utils_selection_tests import ( create_selection_tests, get_addresses, get_topology_settings_dict, make_server_description, ) # Location of JSON test specifications. _TEST_PATH = os.path.join( os.path.dirname(os.path.realpath(__file__)), os.path.join("server_selection", "server_selection"), ) class SelectionStoreSelector: """No-op selector that keeps track of what was passed to it.""" def __init__(self): self.selection = None def __call__(self, selection): self.selection = selection return selection class TestAllScenarios(create_selection_tests(_TEST_PATH)): # type: ignore pass class TestCustomServerSelectorFunction(IntegrationTest): @client_context.require_replica_set def test_functional_select_max_port_number_host(self): # Selector that returns server with highest port number. def custom_selector(servers): ports = [s.address[1] for s in servers] idx = ports.index(max(ports)) return [servers[idx]] # Initialize client with appropriate listeners. listener = EventListener() client = rs_or_single_client(server_selector=custom_selector, event_listeners=[listener]) self.addCleanup(client.close) coll = client.get_database("testdb", read_preference=ReadPreference.NEAREST).coll self.addCleanup(client.drop_database, "testdb") # Wait the node list to be fully populated. def all_hosts_started(): return len(client.admin.command(HelloCompat.LEGACY_CMD)["hosts"]) == len( client._topology._description.readable_servers ) wait_until(all_hosts_started, "receive heartbeat from all hosts") expected_port = max( [strip_optional(n.address[1]) for n in client._topology._description.readable_servers] ) # Insert 1 record and access it 10 times. coll.insert_one({"name": "John Doe"}) for _ in range(10): coll.find_one({"name": "John Doe"}) # Confirm all find commands are run against appropriate host. for command in listener.started_events: if command.command_name == "find": self.assertEqual(command.connection_id[1], expected_port) def test_invalid_server_selector(self): # Client initialization must fail if server_selector is not callable. for selector_candidate in [[], 10, "string", {}]: with self.assertRaisesRegex(ValueError, "must be a callable"): MongoClient(connect=False, server_selector=selector_candidate) # None value for server_selector is OK. MongoClient(connect=False, server_selector=None) @client_context.require_replica_set def test_selector_called(self): selector = FunctionCallRecorder(lambda x: x) # Client setup. mongo_client = rs_or_single_client(server_selector=selector) test_collection = mongo_client.testdb.test_collection self.addCleanup(mongo_client.close) self.addCleanup(mongo_client.drop_database, "testdb") # Do N operations and test selector is called at least N times. test_collection.insert_one({"age": 20, "name": "John"}) test_collection.insert_one({"age": 31, "name": "Jane"}) test_collection.update_one({"name": "Jane"}, {"$set": {"age": 21}}) test_collection.find_one({"name": "Roe"}) self.assertGreaterEqual(selector.call_count, 4) @client_context.require_replica_set def test_latency_threshold_application(self): selector = SelectionStoreSelector() scenario_def: dict = { "topology_description": { "type": "ReplicaSetWithPrimary", "servers": [ {"address": "b:27017", "avg_rtt_ms": 10000, "type": "RSSecondary", "tag": {}}, {"address": "c:27017", "avg_rtt_ms": 20000, "type": "RSSecondary", "tag": {}}, {"address": "a:27017", "avg_rtt_ms": 30000, "type": "RSPrimary", "tag": {}}, ], } } # Create & populate Topology such that all but one server is too slow. rtt_times = [srv["avg_rtt_ms"] for srv in scenario_def["topology_description"]["servers"]] min_rtt_idx = rtt_times.index(min(rtt_times)) seeds, hosts = get_addresses(scenario_def["topology_description"]["servers"]) settings = get_topology_settings_dict( heartbeat_frequency=1, local_threshold_ms=1, seeds=seeds, server_selector=selector ) topology = Topology(TopologySettings(**settings)) topology.open() for server in scenario_def["topology_description"]["servers"]: server_description = make_server_description(server, hosts) topology.on_change(server_description) # Invoke server selection and assert no filtering based on latency # prior to custom server selection logic kicking in. server = topology.select_server(ReadPreference.NEAREST, _Op.TEST) assert selector.selection is not None self.assertEqual(len(selector.selection), len(topology.description.server_descriptions())) # Ensure proper filtering based on latency after custom selection. self.assertEqual(server.description.address, seeds[min_rtt_idx]) @client_context.require_replica_set def test_server_selector_bypassed(self): selector = FunctionCallRecorder(lambda x: x) scenario_def = { "topology_description": { "type": "ReplicaSetNoPrimary", "servers": [ {"address": "b:27017", "avg_rtt_ms": 10000, "type": "RSSecondary", "tag": {}}, {"address": "c:27017", "avg_rtt_ms": 20000, "type": "RSSecondary", "tag": {}}, {"address": "a:27017", "avg_rtt_ms": 30000, "type": "RSSecondary", "tag": {}}, ], } } # Create & populate Topology such that no server is writeable. seeds, hosts = get_addresses(scenario_def["topology_description"]["servers"]) settings = get_topology_settings_dict( heartbeat_frequency=1, local_threshold_ms=1, seeds=seeds, server_selector=selector ) topology = Topology(TopologySettings(**settings)) topology.open() for server in scenario_def["topology_description"]["servers"]: server_description = make_server_description(server, hosts) topology.on_change(server_description) # Invoke server selection and assert no calls to our custom selector. with self.assertRaisesRegex(ServerSelectionTimeoutError, "No primary available for writes"): topology.select_server(writable_server_selector, _Op.TEST, server_selection_timeout=0.1) self.assertEqual(selector.call_count, 0) if __name__ == "__main__": unittest.main() mongodb-mongo-python-driver-509e9b7/test/test_server_selection_in_window.py000066400000000000000000000134661462766011000274670ustar00rootroot00000000000000# Copyright 2020-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. """Test the topology module's Server Selection Spec implementation.""" from __future__ import annotations import os import threading from test import IntegrationTest, client_context, unittest from test.utils import ( OvertCommandListener, SpecTestCreator, get_pool, rs_client, wait_until, ) from test.utils_selection_tests import create_topology from pymongo.common import clean_node from pymongo.operations import _Op from pymongo.read_preferences import ReadPreference # Location of JSON test specifications. TEST_PATH = os.path.join( os.path.dirname(os.path.realpath(__file__)), os.path.join("server_selection", "in_window") ) class TestAllScenarios(unittest.TestCase): def run_scenario(self, scenario_def): topology = create_topology(scenario_def) # Update mock operation_count state: for mock in scenario_def["mocked_topology_state"]: address = clean_node(mock["address"]) server = topology.get_server_by_address(address) server.pool.operation_count = mock["operation_count"] pref = ReadPreference.NEAREST counts = {address: 0 for address in topology._description.server_descriptions()} # Number of times to repeat server selection iterations = scenario_def["iterations"] for _ in range(iterations): server = topology.select_server(pref, _Op.TEST, server_selection_timeout=0) counts[server.description.address] += 1 # Verify expected_frequencies outcome = scenario_def["outcome"] tolerance = outcome["tolerance"] expected_frequencies = outcome["expected_frequencies"] for host_str, freq in expected_frequencies.items(): address = clean_node(host_str) actual_freq = float(counts[address]) / iterations if freq == 0: # Should be exactly 0. self.assertEqual(actual_freq, 0) else: # Should be within 'tolerance'. self.assertAlmostEqual(actual_freq, freq, delta=tolerance) def create_test(scenario_def, test, name): def run_scenario(self): self.run_scenario(scenario_def) return run_scenario class CustomSpecTestCreator(SpecTestCreator): def tests(self, scenario_def): """Extract the tests from a spec file. Server selection in_window tests do not have a 'tests' field. The whole file represents a single test case. """ return [scenario_def] CustomSpecTestCreator(create_test, TestAllScenarios, TEST_PATH).create_tests() class FinderThread(threading.Thread): def __init__(self, collection, iterations): super().__init__() self.daemon = True self.collection = collection self.iterations = iterations self.passed = False def run(self): for _ in range(self.iterations): self.collection.find_one({}) self.passed = True class TestProse(IntegrationTest): def frequencies(self, client, listener, n_finds=10): coll = client.test.test N_THREADS = 10 threads = [FinderThread(coll, n_finds) for _ in range(N_THREADS)] for thread in threads: thread.start() for thread in threads: thread.join() for thread in threads: self.assertTrue(thread.passed) events = listener.started_events self.assertEqual(len(events), n_finds * N_THREADS) nodes = client.nodes self.assertEqual(len(nodes), 2) freqs = {address: 0.0 for address in nodes} for event in events: freqs[event.connection_id] += 1 for address in freqs: freqs[address] = freqs[address] / float(len(events)) return freqs @client_context.require_failCommand_appName @client_context.require_multiple_mongoses def test_load_balancing(self): listener = OvertCommandListener() # PYTHON-2584: Use a large localThresholdMS to avoid the impact of # varying RTTs. client = rs_client( client_context.mongos_seeds(), appName="loadBalancingTest", event_listeners=[listener], localThresholdMS=30000, minPoolSize=10, ) self.addCleanup(client.close) wait_until(lambda: len(client.nodes) == 2, "discover both nodes") wait_until(lambda: len(get_pool(client).conns) >= 10, "create 10 connections") # Delay find commands on delay_finds = { "configureFailPoint": "failCommand", "mode": {"times": 10000}, "data": { "failCommands": ["find"], "blockConnection": True, "blockTimeMS": 500, "appName": "loadBalancingTest", }, } with self.fail_point(delay_finds): nodes = client_context.client.nodes self.assertEqual(len(nodes), 1) delayed_server = next(iter(nodes)) freqs = self.frequencies(client, listener) self.assertLessEqual(freqs[delayed_server], 0.25) listener.reset() freqs = self.frequencies(client, listener, n_finds=100) self.assertAlmostEqual(freqs[delayed_server], 0.50, delta=0.15) if __name__ == "__main__": unittest.main() mongodb-mongo-python-driver-509e9b7/test/test_server_selection_logging.py000066400000000000000000000021111462766011000271010ustar00rootroot00000000000000# Copyright 2024-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. """Run the server selection logging unified format spec tests.""" from __future__ import annotations import os import sys sys.path[0:0] = [""] from test import unittest from test.unified_format import generate_test_classes # Location of JSON test specifications. _TEST_PATH = os.path.join(os.path.dirname(os.path.realpath(__file__)), "server_selection_logging") globals().update( generate_test_classes( _TEST_PATH, module=__name__, ) ) if __name__ == "__main__": unittest.main() mongodb-mongo-python-driver-509e9b7/test/test_server_selection_rtt.py000066400000000000000000000037711462766011000263010ustar00rootroot00000000000000# Copyright 2015 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. """Test the topology module.""" from __future__ import annotations import json import os import sys sys.path[0:0] = [""] from test import unittest from pymongo.read_preferences import MovingAverage # Location of JSON test specifications. _TEST_PATH = os.path.join(os.path.dirname(os.path.realpath(__file__)), "server_selection/rtt") class TestAllScenarios(unittest.TestCase): pass def create_test(scenario_def): def run_scenario(self): moving_average = MovingAverage() if scenario_def["avg_rtt_ms"] != "NULL": moving_average.add_sample(scenario_def["avg_rtt_ms"]) if scenario_def["new_rtt_ms"] != "NULL": moving_average.add_sample(scenario_def["new_rtt_ms"]) self.assertAlmostEqual(moving_average.get(), scenario_def["new_avg_rtt"]) return run_scenario def create_tests(): for dirpath, _, filenames in os.walk(_TEST_PATH): dirname = os.path.split(dirpath)[-1] for filename in filenames: with open(os.path.join(dirpath, filename)) as scenario_stream: scenario_def = json.load(scenario_stream) # Construct test from scenario. new_test = create_test(scenario_def) test_name = f"test_{dirname}_{os.path.splitext(filename)[0]}" new_test.__name__ = test_name setattr(TestAllScenarios, new_test.__name__, new_test) create_tests() if __name__ == "__main__": unittest.main() mongodb-mongo-python-driver-509e9b7/test/test_session.py000066400000000000000000001303451462766011000235160ustar00rootroot00000000000000# Copyright 2017 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. """Test the client_session module.""" from __future__ import annotations import copy import sys import time from io import BytesIO from typing import Any, Callable, List, Set, Tuple from pymongo.mongo_client import MongoClient sys.path[0:0] = [""] from test import IntegrationTest, SkipTest, client_context, unittest from test.utils import ( EventListener, ExceptionCatchingThread, rs_or_single_client, wait_until, ) from bson import DBRef from gridfs import GridFS, GridFSBucket from pymongo import ASCENDING, IndexModel, InsertOne, monitoring from pymongo.command_cursor import CommandCursor from pymongo.common import _MAX_END_SESSIONS from pymongo.cursor import Cursor from pymongo.errors import ConfigurationError, InvalidOperation, OperationFailure from pymongo.operations import UpdateOne from pymongo.read_concern import ReadConcern # Ignore auth commands like saslStart, so we can assert lsid is in all commands. class SessionTestListener(EventListener): def started(self, event): if not event.command_name.startswith("sasl"): super().started(event) def succeeded(self, event): if not event.command_name.startswith("sasl"): super().succeeded(event) def failed(self, event): if not event.command_name.startswith("sasl"): super().failed(event) def first_command_started(self): assert len(self.started_events) >= 1, "No command-started events" return self.started_events[0] def session_ids(client): return [s.session_id for s in copy.copy(client._topology._session_pool)] class TestSession(IntegrationTest): client2: MongoClient sensitive_commands: Set[str] @classmethod @client_context.require_sessions def setUpClass(cls): super().setUpClass() # Create a second client so we can make sure clients cannot share # sessions. cls.client2 = rs_or_single_client() # Redact no commands, so we can test user-admin commands have "lsid". cls.sensitive_commands = monitoring._SENSITIVE_COMMANDS.copy() monitoring._SENSITIVE_COMMANDS.clear() @classmethod def tearDownClass(cls): monitoring._SENSITIVE_COMMANDS.update(cls.sensitive_commands) cls.client2.close() super().tearDownClass() def setUp(self): self.listener = SessionTestListener() self.session_checker_listener = SessionTestListener() self.client = rs_or_single_client( event_listeners=[self.listener, self.session_checker_listener] ) self.addCleanup(self.client.close) self.db = self.client.pymongo_test self.initial_lsids = {s["id"] for s in session_ids(self.client)} def tearDown(self): """All sessions used in the test must be returned to the pool.""" self.client.drop_database("pymongo_test") used_lsids = self.initial_lsids.copy() for event in self.session_checker_listener.started_events: if "lsid" in event.command: used_lsids.add(event.command["lsid"]["id"]) current_lsids = {s["id"] for s in session_ids(self.client)} self.assertLessEqual(used_lsids, current_lsids) def _test_ops(self, client, *ops): listener = client.options.event_listeners[0] for f, args, kw in ops: with client.start_session() as s: listener.reset() s._materialize() last_use = s._server_session.last_use start = time.monotonic() self.assertLessEqual(last_use, start) # In case "f" modifies its inputs. args = copy.copy(args) kw = copy.copy(kw) kw["session"] = s f(*args, **kw) self.assertGreaterEqual(len(listener.started_events), 1) for event in listener.started_events: self.assertTrue( "lsid" in event.command, f"{f.__name__} sent no lsid with {event.command_name}", ) self.assertEqual( s.session_id, event.command["lsid"], f"{f.__name__} sent wrong lsid with {event.command_name}", ) self.assertFalse(s.has_ended) self.assertTrue(s.has_ended) with self.assertRaisesRegex(InvalidOperation, "ended session"): f(*args, **kw) # Test a session cannot be used on another client. with self.client2.start_session() as s: # In case "f" modifies its inputs. args = copy.copy(args) kw = copy.copy(kw) kw["session"] = s with self.assertRaisesRegex( InvalidOperation, "Can only use session with the MongoClient that started it" ): f(*args, **kw) # No explicit session. for f, args, kw in ops: listener.reset() f(*args, **kw) self.assertGreaterEqual(len(listener.started_events), 1) lsids = [] for event in listener.started_events: self.assertTrue( "lsid" in event.command, f"{f.__name__} sent no lsid with {event.command_name}", ) lsids.append(event.command["lsid"]) if not (sys.platform.startswith("java") or "PyPy" in sys.version): # Server session was returned to pool. Ignore interpreters with # non-deterministic GC. for lsid in lsids: self.assertIn( lsid, session_ids(client), f"{f.__name__} did not return implicit session to pool", ) def test_implicit_sessions_checkout(self): # "To confirm that implicit sessions only allocate their server session after a # successful connection checkout" test from Driver Sessions Spec. succeeded = False lsid_set = set() failures = 0 for _ in range(5): listener = EventListener() client = rs_or_single_client(event_listeners=[listener], maxPoolSize=1) cursor = client.db.test.find({}) ops: List[Tuple[Callable, List[Any]]] = [ (client.db.test.find_one, [{"_id": 1}]), (client.db.test.delete_one, [{}]), (client.db.test.update_one, [{}, {"$set": {"x": 2}}]), (client.db.test.bulk_write, [[UpdateOne({}, {"$set": {"x": 2}})]]), (client.db.test.find_one_and_delete, [{}]), (client.db.test.find_one_and_update, [{}, {"$set": {"x": 1}}]), (client.db.test.find_one_and_replace, [{}, {}]), (client.db.test.aggregate, [[{"$limit": 1}]]), (client.db.test.find, []), (client.server_info, []), (client.db.aggregate, [[{"$listLocalSessions": {}}, {"$limit": 1}]]), (cursor.distinct, ["_id"]), (client.db.list_collections, []), ] threads = [] listener.reset() def thread_target(op, *args): res = op(*args) if isinstance(res, (Cursor, CommandCursor)): list(res) for op, args in ops: threads.append( ExceptionCatchingThread( target=thread_target, args=[op, *args], name=op.__name__ ) ) threads[-1].start() self.assertEqual(len(threads), len(ops)) for thread in threads: thread.join() self.assertIsNone(thread.exc) client.close() lsid_set.clear() for i in listener.started_events: if i.command.get("lsid"): lsid_set.add(i.command.get("lsid")["id"]) if len(lsid_set) == 1: succeeded = True else: failures += 1 self.assertTrue(succeeded, lsid_set) def test_pool_lifo(self): # "Pool is LIFO" test from Driver Sessions Spec. a = self.client.start_session() b = self.client.start_session() a_id = a.session_id b_id = b.session_id a.end_session() b.end_session() s = self.client.start_session() self.assertEqual(b_id, s.session_id) self.assertNotEqual(a_id, s.session_id) s2 = self.client.start_session() self.assertEqual(a_id, s2.session_id) self.assertNotEqual(b_id, s2.session_id) s.end_session() s2.end_session() def test_end_session(self): # We test elsewhere that using an ended session throws InvalidOperation. client = self.client s = client.start_session() self.assertFalse(s.has_ended) self.assertIsNotNone(s.session_id) s.end_session() self.assertTrue(s.has_ended) with self.assertRaisesRegex(InvalidOperation, "ended session"): s.session_id def test_end_sessions(self): # Use a new client so that the tearDown hook does not error. listener = SessionTestListener() client = rs_or_single_client(event_listeners=[listener]) # Start many sessions. sessions = [client.start_session() for _ in range(_MAX_END_SESSIONS + 1)] for s in sessions: s._materialize() for s in sessions: s.end_session() # Closing the client should end all sessions and clear the pool. self.assertEqual(len(client._topology._session_pool), _MAX_END_SESSIONS + 1) client.close() self.assertEqual(len(client._topology._session_pool), 0) end_sessions = [e for e in listener.started_events if e.command_name == "endSessions"] self.assertEqual(len(end_sessions), 2) # Closing again should not send any commands. listener.reset() client.close() self.assertEqual(len(listener.started_events), 0) def test_client(self): client = self.client ops: list = [ (client.server_info, [], {}), (client.list_database_names, [], {}), (client.drop_database, ["pymongo_test"], {}), ] self._test_ops(client, *ops) def test_database(self): client = self.client db = client.pymongo_test ops: list = [ (db.command, ["ping"], {}), (db.create_collection, ["collection"], {}), (db.list_collection_names, [], {}), (db.validate_collection, ["collection"], {}), (db.drop_collection, ["collection"], {}), (db.dereference, [DBRef("collection", 1)], {}), ] self._test_ops(client, *ops) @staticmethod def collection_write_ops(coll): """Generate database write ops for tests.""" return [ (coll.drop, [], {}), (coll.bulk_write, [[InsertOne({})]], {}), (coll.insert_one, [{}], {}), (coll.insert_many, [[{}, {}]], {}), (coll.replace_one, [{}, {}], {}), (coll.update_one, [{}, {"$set": {"a": 1}}], {}), (coll.update_many, [{}, {"$set": {"a": 1}}], {}), (coll.delete_one, [{}], {}), (coll.delete_many, [{}], {}), (coll.find_one_and_replace, [{}, {}], {}), (coll.find_one_and_update, [{}, {"$set": {"a": 1}}], {}), (coll.find_one_and_delete, [{}, {}], {}), (coll.rename, ["collection2"], {}), # Drop collection2 between tests of "rename", above. (coll.database.drop_collection, ["collection2"], {}), (coll.create_indexes, [[IndexModel("a")]], {}), (coll.create_index, ["a"], {}), (coll.drop_index, ["a_1"], {}), (coll.drop_indexes, [], {}), (coll.aggregate, [[{"$out": "aggout"}]], {}), ] def test_collection(self): client = self.client coll = client.pymongo_test.collection # Test some collection methods - the rest are in test_cursor. ops = self.collection_write_ops(coll) ops.extend( [ (coll.distinct, ["a"], {}), (coll.find_one, [], {}), (coll.count_documents, [{}], {}), (coll.list_indexes, [], {}), (coll.index_information, [], {}), (coll.options, [], {}), (coll.aggregate, [[]], {}), ] ) self._test_ops(client, *ops) def test_cursor_clone(self): coll = self.client.pymongo_test.collection # Ensure some batches. coll.insert_many({} for _ in range(10)) self.addCleanup(coll.drop) with self.client.start_session() as s: cursor = coll.find(session=s) self.assertTrue(cursor.session is s) clone = cursor.clone() self.assertTrue(clone.session is s) # No explicit session. cursor = coll.find(batch_size=2) next(cursor) # Session is "owned" by cursor. self.assertIsNone(cursor.session) self.assertIsNotNone(cursor._Cursor__session) clone = cursor.clone() next(clone) self.assertIsNone(clone.session) self.assertIsNotNone(clone._Cursor__session) self.assertFalse(cursor._Cursor__session is clone._Cursor__session) cursor.close() clone.close() def test_cursor(self): listener = self.listener client = self.client coll = client.pymongo_test.collection coll.insert_many([{} for _ in range(1000)]) # Test all cursor methods. ops = [ ("find", lambda session: list(coll.find(session=session))), ("getitem", lambda session: coll.find(session=session)[0]), ("distinct", lambda session: coll.find(session=session).distinct("a")), ("explain", lambda session: coll.find(session=session).explain()), ] for name, f in ops: with client.start_session() as s: listener.reset() f(session=s) self.assertGreaterEqual(len(listener.started_events), 1) for event in listener.started_events: self.assertTrue( "lsid" in event.command, f"{name} sent no lsid with {event.command_name}", ) self.assertEqual( s.session_id, event.command["lsid"], f"{name} sent wrong lsid with {event.command_name}", ) with self.assertRaisesRegex(InvalidOperation, "ended session"): f(session=s) # No explicit session. for name, f in ops: listener.reset() f(session=None) event0 = listener.first_command_started() self.assertTrue( "lsid" in event0.command, f"{name} sent no lsid with {event0.command_name}" ) lsid = event0.command["lsid"] for event in listener.started_events[1:]: self.assertTrue( "lsid" in event.command, f"{name} sent no lsid with {event.command_name}" ) self.assertEqual( lsid, event.command["lsid"], f"{name} sent wrong lsid with {event.command_name}", ) def test_gridfs(self): client = self.client fs = GridFS(client.pymongo_test) def new_file(session=None): grid_file = fs.new_file(_id=1, filename="f", session=session) # 1 MB, 5 chunks, to test that each chunk is fetched with same lsid. grid_file.write(b"a" * 1048576) grid_file.close() def find(session=None): files = list(fs.find({"_id": 1}, session=session)) for f in files: f.read() self._test_ops( client, (new_file, [], {}), (fs.put, [b"data"], {}), (lambda session=None: fs.get(1, session=session).read(), [], {}), (lambda session=None: fs.get_version("f", session=session).read(), [], {}), (lambda session=None: fs.get_last_version("f", session=session).read(), [], {}), (fs.list, [], {}), (fs.find_one, [1], {}), (lambda session=None: list(fs.find(session=session)), [], {}), (fs.exists, [1], {}), (find, [], {}), (fs.delete, [1], {}), ) def test_gridfs_bucket(self): client = self.client bucket = GridFSBucket(client.pymongo_test) def upload(session=None): stream = bucket.open_upload_stream("f", session=session) stream.write(b"a" * 1048576) stream.close() def upload_with_id(session=None): stream = bucket.open_upload_stream_with_id(1, "f1", session=session) stream.write(b"a" * 1048576) stream.close() def open_download_stream(session=None): stream = bucket.open_download_stream(1, session=session) stream.read() def open_download_stream_by_name(session=None): stream = bucket.open_download_stream_by_name("f", session=session) stream.read() def find(session=None): files = list(bucket.find({"_id": 1}, session=session)) for f in files: f.read() sio = BytesIO() self._test_ops( client, (upload, [], {}), (upload_with_id, [], {}), (bucket.upload_from_stream, ["f", b"data"], {}), (bucket.upload_from_stream_with_id, [2, "f", b"data"], {}), (open_download_stream, [], {}), (open_download_stream_by_name, [], {}), (bucket.download_to_stream, [1, sio], {}), (bucket.download_to_stream_by_name, ["f", sio], {}), (find, [], {}), (bucket.rename, [1, "f2"], {}), # Delete both files so _test_ops can run these operations twice. (bucket.delete, [1], {}), (bucket.delete, [2], {}), ) def test_gridfsbucket_cursor(self): client = self.client bucket = GridFSBucket(client.pymongo_test) for file_id in 1, 2: stream = bucket.open_upload_stream_with_id(file_id, str(file_id)) stream.write(b"a" * 1048576) stream.close() with client.start_session() as s: cursor = bucket.find(session=s) for f in cursor: f.read() self.assertFalse(s.has_ended) self.assertTrue(s.has_ended) # No explicit session. cursor = bucket.find(batch_size=1) files = [cursor.next()] s = cursor._Cursor__session self.assertFalse(s.has_ended) cursor.__del__() self.assertTrue(s.has_ended) self.assertIsNone(cursor._Cursor__session) # Files are still valid, they use their own sessions. for f in files: f.read() # Explicit session. with client.start_session() as s: cursor = bucket.find(session=s) assert cursor.session is not None s = cursor.session files = list(cursor) cursor.__del__() self.assertFalse(s.has_ended) for f in files: f.read() for f in files: # Attempt to read the file again. f.seek(0) with self.assertRaisesRegex(InvalidOperation, "ended session"): f.read() def test_aggregate(self): client = self.client coll = client.pymongo_test.collection def agg(session=None): list(coll.aggregate([], batchSize=2, session=session)) # With empty collection. self._test_ops(client, (agg, [], {})) # Now with documents. coll.insert_many([{} for _ in range(10)]) self.addCleanup(coll.drop) self._test_ops(client, (agg, [], {})) def test_killcursors(self): client = self.client coll = client.pymongo_test.collection coll.insert_many([{} for _ in range(10)]) def explicit_close(session=None): cursor = coll.find(batch_size=2, session=session) next(cursor) cursor.close() self._test_ops(client, (explicit_close, [], {})) def test_aggregate_error(self): listener = self.listener client = self.client coll = client.pymongo_test.collection # 3.6.0 mongos only validates the aggregate pipeline when the # database exists. coll.insert_one({}) listener.reset() with self.assertRaises(OperationFailure): coll.aggregate([{"$badOperation": {"bar": 1}}]) event = listener.first_command_started() self.assertEqual(event.command_name, "aggregate") lsid = event.command["lsid"] # Session was returned to pool despite error. self.assertIn(lsid, session_ids(client)) def _test_cursor_helper(self, create_cursor, close_cursor): coll = self.client.pymongo_test.collection coll.insert_many([{} for _ in range(1000)]) cursor = create_cursor(coll, None) next(cursor) # Session is "owned" by cursor. session = getattr(cursor, "_%s__session" % cursor.__class__.__name__) self.assertIsNotNone(session) lsid = session.session_id next(cursor) # Cursor owns its session unto death. self.assertNotIn(lsid, session_ids(self.client)) close_cursor(cursor) self.assertIn(lsid, session_ids(self.client)) # An explicit session is not ended by cursor.close() or list(cursor). with self.client.start_session() as s: cursor = create_cursor(coll, s) next(cursor) close_cursor(cursor) self.assertFalse(s.has_ended) lsid = s.session_id self.assertTrue(s.has_ended) self.assertIn(lsid, session_ids(self.client)) def test_cursor_close(self): self._test_cursor_helper( lambda coll, session: coll.find(session=session), lambda cursor: cursor.close() ) def test_command_cursor_close(self): self._test_cursor_helper( lambda coll, session: coll.aggregate([], session=session), lambda cursor: cursor.close() ) def test_cursor_del(self): self._test_cursor_helper( lambda coll, session: coll.find(session=session), lambda cursor: cursor.__del__() ) def test_command_cursor_del(self): self._test_cursor_helper( lambda coll, session: coll.aggregate([], session=session), lambda cursor: cursor.__del__(), ) def test_cursor_exhaust(self): self._test_cursor_helper( lambda coll, session: coll.find(session=session), lambda cursor: list(cursor) ) def test_command_cursor_exhaust(self): self._test_cursor_helper( lambda coll, session: coll.aggregate([], session=session), lambda cursor: list(cursor) ) def test_cursor_limit_reached(self): self._test_cursor_helper( lambda coll, session: coll.find(limit=4, batch_size=2, session=session), lambda cursor: list(cursor), ) def test_command_cursor_limit_reached(self): self._test_cursor_helper( lambda coll, session: coll.aggregate([], batchSize=900, session=session), lambda cursor: list(cursor), ) def _test_unacknowledged_ops(self, client, *ops): listener = client.options.event_listeners[0] for f, args, kw in ops: with client.start_session() as s: listener.reset() # In case "f" modifies its inputs. args = copy.copy(args) kw = copy.copy(kw) kw["session"] = s with self.assertRaises( ConfigurationError, msg=f"{f.__name__} did not raise ConfigurationError" ): f(*args, **kw) if f.__name__ == "create_collection": # create_collection runs listCollections first. event = listener.started_events.pop(0) self.assertEqual("listCollections", event.command_name) self.assertIn( "lsid", event.command, f"{f.__name__} sent no lsid with {event.command_name}", ) # Should not run any command before raising an error. self.assertFalse(listener.started_events, f"{f.__name__} sent command") self.assertTrue(s.has_ended) # Unacknowledged write without a session does not send an lsid. for f, args, kw in ops: listener.reset() f(*args, **kw) self.assertGreaterEqual(len(listener.started_events), 1) if f.__name__ == "create_collection": # create_collection runs listCollections first. event = listener.started_events.pop(0) self.assertEqual("listCollections", event.command_name) self.assertIn( "lsid", event.command, f"{f.__name__} sent no lsid with {event.command_name}", ) for event in listener.started_events: self.assertNotIn( "lsid", event.command, f"{f.__name__} sent lsid with {event.command_name}" ) def test_unacknowledged_writes(self): # Ensure the collection exists. self.client.pymongo_test.test_unacked_writes.insert_one({}) client = rs_or_single_client(w=0, event_listeners=[self.listener]) self.addCleanup(client.close) db = client.pymongo_test coll = db.test_unacked_writes ops: list = [ (client.drop_database, [db.name], {}), (db.create_collection, ["collection"], {}), (db.drop_collection, ["collection"], {}), ] ops.extend(self.collection_write_ops(coll)) self._test_unacknowledged_ops(client, *ops) def drop_db(): try: self.client.drop_database(db.name) return True except OperationFailure as exc: # Try again on BackgroundOperationInProgressForDatabase and # BackgroundOperationInProgressForNamespace. if exc.code in (12586, 12587): return False raise wait_until(drop_db, "dropped database after w=0 writes") def test_snapshot_incompatible_with_causal_consistency(self): with self.client.start_session(causal_consistency=False, snapshot=False): pass with self.client.start_session(causal_consistency=False, snapshot=True): pass with self.client.start_session(causal_consistency=True, snapshot=False): pass with self.assertRaises(ConfigurationError): with self.client.start_session(causal_consistency=True, snapshot=True): pass def test_session_not_copyable(self): client = self.client with client.start_session() as s: self.assertRaises(TypeError, lambda: copy.copy(s)) class TestCausalConsistency(unittest.TestCase): listener: SessionTestListener client: MongoClient @classmethod def setUpClass(cls): cls.listener = SessionTestListener() cls.client = rs_or_single_client(event_listeners=[cls.listener]) @classmethod def tearDownClass(cls): cls.client.close() @client_context.require_sessions def setUp(self): super().setUp() @client_context.require_no_standalone def test_core(self): with self.client.start_session() as sess: self.assertIsNone(sess.cluster_time) self.assertIsNone(sess.operation_time) self.listener.reset() self.client.pymongo_test.test.find_one(session=sess) started = self.listener.started_events[0] cmd = started.command self.assertIsNone(cmd.get("readConcern")) op_time = sess.operation_time self.assertIsNotNone(op_time) succeeded = self.listener.succeeded_events[0] reply = succeeded.reply self.assertEqual(op_time, reply.get("operationTime")) # No explicit session self.client.pymongo_test.test.insert_one({}) self.assertEqual(sess.operation_time, op_time) self.listener.reset() try: self.client.pymongo_test.command("doesntexist", session=sess) except: pass failed = self.listener.failed_events[0] failed_op_time = failed.failure.get("operationTime") # Some older builds of MongoDB 3.5 / 3.6 return None for # operationTime when a command fails. Make sure we don't # change operation_time to None. if failed_op_time is None: self.assertIsNotNone(sess.operation_time) else: self.assertEqual(sess.operation_time, failed_op_time) with self.client.start_session() as sess2: self.assertIsNone(sess2.cluster_time) self.assertIsNone(sess2.operation_time) self.assertRaises(TypeError, sess2.advance_cluster_time, 1) self.assertRaises(ValueError, sess2.advance_cluster_time, {}) self.assertRaises(TypeError, sess2.advance_operation_time, 1) # No error assert sess.cluster_time is not None assert sess.operation_time is not None sess2.advance_cluster_time(sess.cluster_time) sess2.advance_operation_time(sess.operation_time) self.assertEqual(sess.cluster_time, sess2.cluster_time) self.assertEqual(sess.operation_time, sess2.operation_time) def _test_reads(self, op, exception=None): coll = self.client.pymongo_test.test with self.client.start_session() as sess: coll.find_one({}, session=sess) operation_time = sess.operation_time self.assertIsNotNone(operation_time) self.listener.reset() if exception: with self.assertRaises(exception): op(coll, sess) else: op(coll, sess) act = ( self.listener.started_events[0] .command.get("readConcern", {}) .get("afterClusterTime") ) self.assertEqual(operation_time, act) @client_context.require_no_standalone def test_reads(self): # Make sure the collection exists. self.client.pymongo_test.test.insert_one({}) self._test_reads(lambda coll, session: list(coll.aggregate([], session=session))) self._test_reads(lambda coll, session: list(coll.find({}, session=session))) self._test_reads(lambda coll, session: coll.find_one({}, session=session)) self._test_reads(lambda coll, session: coll.count_documents({}, session=session)) self._test_reads(lambda coll, session: coll.distinct("foo", session=session)) self._test_reads( lambda coll, session: list(coll.aggregate_raw_batches([], session=session)) ) self._test_reads(lambda coll, session: list(coll.find_raw_batches({}, session=session))) self.assertRaises( ConfigurationError, self._test_reads, lambda coll, session: coll.estimated_document_count(session=session), ) def _test_writes(self, op): coll = self.client.pymongo_test.test with self.client.start_session() as sess: op(coll, sess) operation_time = sess.operation_time self.assertIsNotNone(operation_time) self.listener.reset() coll.find_one({}, session=sess) act = ( self.listener.started_events[0] .command.get("readConcern", {}) .get("afterClusterTime") ) self.assertEqual(operation_time, act) @client_context.require_no_standalone def test_writes(self): self._test_writes( lambda coll, session: coll.bulk_write([InsertOne[dict]({})], session=session) ) self._test_writes(lambda coll, session: coll.insert_one({}, session=session)) self._test_writes(lambda coll, session: coll.insert_many([{}], session=session)) self._test_writes( lambda coll, session: coll.replace_one({"_id": 1}, {"x": 1}, session=session) ) self._test_writes( lambda coll, session: coll.update_one({}, {"$set": {"X": 1}}, session=session) ) self._test_writes( lambda coll, session: coll.update_many({}, {"$set": {"x": 1}}, session=session) ) self._test_writes(lambda coll, session: coll.delete_one({}, session=session)) self._test_writes(lambda coll, session: coll.delete_many({}, session=session)) self._test_writes( lambda coll, session: coll.find_one_and_replace({"x": 1}, {"y": 1}, session=session) ) self._test_writes( lambda coll, session: coll.find_one_and_update( {"y": 1}, {"$set": {"x": 1}}, session=session ) ) self._test_writes(lambda coll, session: coll.find_one_and_delete({"x": 1}, session=session)) self._test_writes(lambda coll, session: coll.create_index("foo", session=session)) self._test_writes( lambda coll, session: coll.create_indexes( [IndexModel([("bar", ASCENDING)])], session=session ) ) self._test_writes(lambda coll, session: coll.drop_index("foo_1", session=session)) self._test_writes(lambda coll, session: coll.drop_indexes(session=session)) def _test_no_read_concern(self, op): coll = self.client.pymongo_test.test with self.client.start_session() as sess: coll.find_one({}, session=sess) operation_time = sess.operation_time self.assertIsNotNone(operation_time) self.listener.reset() op(coll, sess) rc = self.listener.started_events[0].command.get("readConcern") self.assertIsNone(rc) @client_context.require_no_standalone def test_writes_do_not_include_read_concern(self): self._test_no_read_concern( lambda coll, session: coll.bulk_write([InsertOne[dict]({})], session=session) ) self._test_no_read_concern(lambda coll, session: coll.insert_one({}, session=session)) self._test_no_read_concern(lambda coll, session: coll.insert_many([{}], session=session)) self._test_no_read_concern( lambda coll, session: coll.replace_one({"_id": 1}, {"x": 1}, session=session) ) self._test_no_read_concern( lambda coll, session: coll.update_one({}, {"$set": {"X": 1}}, session=session) ) self._test_no_read_concern( lambda coll, session: coll.update_many({}, {"$set": {"x": 1}}, session=session) ) self._test_no_read_concern(lambda coll, session: coll.delete_one({}, session=session)) self._test_no_read_concern(lambda coll, session: coll.delete_many({}, session=session)) self._test_no_read_concern( lambda coll, session: coll.find_one_and_replace({"x": 1}, {"y": 1}, session=session) ) self._test_no_read_concern( lambda coll, session: coll.find_one_and_update( {"y": 1}, {"$set": {"x": 1}}, session=session ) ) self._test_no_read_concern( lambda coll, session: coll.find_one_and_delete({"x": 1}, session=session) ) self._test_no_read_concern(lambda coll, session: coll.create_index("foo", session=session)) self._test_no_read_concern( lambda coll, session: coll.create_indexes( [IndexModel([("bar", ASCENDING)])], session=session ) ) self._test_no_read_concern(lambda coll, session: coll.drop_index("foo_1", session=session)) self._test_no_read_concern(lambda coll, session: coll.drop_indexes(session=session)) # Not a write, but explain also doesn't support readConcern. self._test_no_read_concern(lambda coll, session: coll.find({}, session=session).explain()) @client_context.require_no_standalone @client_context.require_version_max(4, 1, 0) def test_aggregate_out_does_not_include_read_concern(self): self._test_no_read_concern( lambda coll, session: list(coll.aggregate([{"$out": "aggout"}], session=session)) ) @client_context.require_no_standalone def test_get_more_does_not_include_read_concern(self): coll = self.client.pymongo_test.test with self.client.start_session() as sess: coll.find_one({}, session=sess) operation_time = sess.operation_time self.assertIsNotNone(operation_time) coll.insert_many([{}, {}]) cursor = coll.find({}).batch_size(1) next(cursor) self.listener.reset() list(cursor) started = self.listener.started_events[0] self.assertEqual(started.command_name, "getMore") self.assertIsNone(started.command.get("readConcern")) def test_session_not_causal(self): with self.client.start_session(causal_consistency=False) as s: self.client.pymongo_test.test.insert_one({}, session=s) self.listener.reset() self.client.pymongo_test.test.find_one({}, session=s) act = ( self.listener.started_events[0] .command.get("readConcern", {}) .get("afterClusterTime") ) self.assertIsNone(act) @client_context.require_standalone def test_server_not_causal(self): with self.client.start_session(causal_consistency=True) as s: self.client.pymongo_test.test.insert_one({}, session=s) self.listener.reset() self.client.pymongo_test.test.find_one({}, session=s) act = ( self.listener.started_events[0] .command.get("readConcern", {}) .get("afterClusterTime") ) self.assertIsNone(act) @client_context.require_no_standalone @client_context.require_no_mmap def test_read_concern(self): with self.client.start_session(causal_consistency=True) as s: coll = self.client.pymongo_test.test coll.insert_one({}, session=s) self.listener.reset() coll.find_one({}, session=s) read_concern = self.listener.started_events[0].command.get("readConcern") self.assertIsNotNone(read_concern) self.assertIsNone(read_concern.get("level")) self.assertIsNotNone(read_concern.get("afterClusterTime")) coll = coll.with_options(read_concern=ReadConcern("majority")) self.listener.reset() coll.find_one({}, session=s) read_concern = self.listener.started_events[0].command.get("readConcern") self.assertIsNotNone(read_concern) self.assertEqual(read_concern.get("level"), "majority") self.assertIsNotNone(read_concern.get("afterClusterTime")) @client_context.require_no_standalone def test_cluster_time_with_server_support(self): self.client.pymongo_test.test.insert_one({}) self.listener.reset() self.client.pymongo_test.test.find_one({}) after_cluster_time = self.listener.started_events[0].command.get("$clusterTime") self.assertIsNotNone(after_cluster_time) @client_context.require_standalone def test_cluster_time_no_server_support(self): self.client.pymongo_test.test.insert_one({}) self.listener.reset() self.client.pymongo_test.test.find_one({}) after_cluster_time = self.listener.started_events[0].command.get("$clusterTime") self.assertIsNone(after_cluster_time) class TestClusterTime(IntegrationTest): def setUp(self): super().setUp() if "$clusterTime" not in client_context.hello: raise SkipTest("$clusterTime not supported") def test_cluster_time(self): listener = SessionTestListener() # Prevent heartbeats from updating $clusterTime between operations. client = rs_or_single_client(event_listeners=[listener], heartbeatFrequencyMS=999999) self.addCleanup(client.close) collection = client.pymongo_test.collection # Prepare for tests of find() and aggregate(). collection.insert_many([{} for _ in range(10)]) self.addCleanup(collection.drop) self.addCleanup(client.pymongo_test.collection2.drop) def rename_and_drop(): # Ensure collection exists. collection.insert_one({}) collection.rename("collection2") client.pymongo_test.collection2.drop() def insert_and_find(): cursor = collection.find().batch_size(1) for _ in range(10): # Advance the cluster time. collection.insert_one({}) next(cursor) cursor.close() def insert_and_aggregate(): cursor = collection.aggregate([], batchSize=1).batch_size(1) for _ in range(5): # Advance the cluster time. collection.insert_one({}) next(cursor) cursor.close() ops = [ # Tests from Driver Sessions Spec. ("ping", lambda: client.admin.command("ping")), ("aggregate", lambda: list(collection.aggregate([]))), ("find", lambda: list(collection.find())), ("insert_one", lambda: collection.insert_one({})), # Additional PyMongo tests. ("insert_and_find", insert_and_find), ("insert_and_aggregate", insert_and_aggregate), ("update_one", lambda: collection.update_one({}, {"$set": {"x": 1}})), ("update_many", lambda: collection.update_many({}, {"$set": {"x": 1}})), ("delete_one", lambda: collection.delete_one({})), ("delete_many", lambda: collection.delete_many({})), ("bulk_write", lambda: collection.bulk_write([InsertOne({})])), ("rename_and_drop", rename_and_drop), ] for _name, f in ops: listener.reset() # Call f() twice, insert to advance clusterTime, call f() again. f() f() collection.insert_one({}) f() self.assertGreaterEqual(len(listener.started_events), 1) for i, event in enumerate(listener.started_events): self.assertTrue( "$clusterTime" in event.command, f"{f.__name__} sent no $clusterTime with {event.command_name}", ) if i > 0: succeeded = listener.succeeded_events[i - 1] self.assertTrue( "$clusterTime" in succeeded.reply, f"{f.__name__} received no $clusterTime with {succeeded.command_name}", ) self.assertTrue( event.command["$clusterTime"]["clusterTime"] >= succeeded.reply["$clusterTime"]["clusterTime"], f"{f.__name__} sent wrong $clusterTime with {event.command_name}", ) if __name__ == "__main__": unittest.main() mongodb-mongo-python-driver-509e9b7/test/test_sessions_unified.py000066400000000000000000000020341462766011000253750ustar00rootroot00000000000000# Copyright 2021-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. """Test the Sessions unified spec tests.""" from __future__ import annotations import os import sys sys.path[0:0] = [""] from test import unittest from test.unified_format import generate_test_classes # Location of JSON test specifications. TEST_PATH = os.path.join(os.path.dirname(os.path.realpath(__file__)), "sessions") # Generate unified tests. globals().update(generate_test_classes(TEST_PATH, module=__name__)) if __name__ == "__main__": unittest.main() mongodb-mongo-python-driver-509e9b7/test/test_son.py000066400000000000000000000160471462766011000226340ustar00rootroot00000000000000# Copyright 2009-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. """Tests for the son module.""" from __future__ import annotations import copy import pickle import re import sys sys.path[0:0] = [""] from collections import OrderedDict from test import unittest from bson.son import SON class TestSON(unittest.TestCase): def test_ordered_dict(self): a1 = SON() a1["hello"] = "world" a1["mike"] = "awesome" a1["hello_"] = "mike" self.assertEqual( list(a1.items()), [("hello", "world"), ("mike", "awesome"), ("hello_", "mike")] ) b2 = SON({"hello": "world"}) self.assertEqual(b2["hello"], "world") self.assertRaises(KeyError, lambda: b2["goodbye"]) def test_equality(self): a1 = SON({"hello": "world"}) b2 = SON((("hello", "world"), ("mike", "awesome"), ("hello_", "mike"))) self.assertEqual(a1, SON({"hello": "world"})) self.assertEqual(b2, SON((("hello", "world"), ("mike", "awesome"), ("hello_", "mike")))) self.assertEqual(b2, {"hello_": "mike", "mike": "awesome", "hello": "world"}) self.assertNotEqual(a1, b2) self.assertNotEqual(b2, SON((("hello_", "mike"), ("mike", "awesome"), ("hello", "world")))) # Explicitly test inequality self.assertFalse(a1 != SON({"hello": "world"})) self.assertFalse(b2 != SON((("hello", "world"), ("mike", "awesome"), ("hello_", "mike")))) self.assertFalse(b2 != {"hello_": "mike", "mike": "awesome", "hello": "world"}) # Embedded SON. d4 = SON([("blah", {"foo": SON()})]) self.assertEqual(d4, {"blah": {"foo": {}}}) self.assertEqual(d4, {"blah": {"foo": SON()}}) self.assertNotEqual(d4, {"blah": {"foo": []}}) # Original data unaffected. self.assertEqual(SON, d4["blah"]["foo"].__class__) def test_to_dict(self): a1 = SON() b2 = SON([("blah", SON())]) c3 = SON([("blah", [SON()])]) d4 = SON([("blah", {"foo": SON()})]) self.assertEqual({}, a1.to_dict()) self.assertEqual({"blah": {}}, b2.to_dict()) self.assertEqual({"blah": [{}]}, c3.to_dict()) self.assertEqual({"blah": {"foo": {}}}, d4.to_dict()) self.assertEqual(dict, a1.to_dict().__class__) self.assertEqual(dict, b2.to_dict()["blah"].__class__) self.assertEqual(dict, c3.to_dict()["blah"][0].__class__) self.assertEqual(dict, d4.to_dict()["blah"]["foo"].__class__) # Original data unaffected. self.assertEqual(SON, d4["blah"]["foo"].__class__) def test_pickle(self): simple_son = SON([]) complex_son = SON([("son", simple_son), ("list", [simple_son, simple_son])]) for protocol in range(pickle.HIGHEST_PROTOCOL + 1): pickled = pickle.loads(pickle.dumps(complex_son, protocol=protocol)) self.assertEqual(pickled["son"], pickled["list"][0]) self.assertEqual(pickled["son"], pickled["list"][1]) def test_pickle_backwards_compatability(self): # This string was generated by pickling a SON object in pymongo # version 2.1.1 pickled_with_2_1_1 = ( b"ccopy_reg\n_reconstructor\np0\n(cbson.son\nSON\np1\n" b"c__builtin__\ndict\np2\n(dp3\ntp4\nRp5\n(dp6\n" b"S'_SON__keys'\np7\n(lp8\nsb." ) son_2_1_1 = pickle.loads(pickled_with_2_1_1) self.assertEqual(son_2_1_1, SON([])) def test_copying(self): simple_son = SON([]) complex_son = SON([("son", simple_son), ("list", [simple_son, simple_son])]) regex_son = SON([("x", re.compile("^hello.*"))]) reflexive_son = SON([("son", simple_son)]) reflexive_son["reflexive"] = reflexive_son simple_son1 = copy.copy(simple_son) self.assertEqual(simple_son, simple_son1) complex_son1 = copy.copy(complex_son) self.assertEqual(complex_son, complex_son1) regex_son1 = copy.copy(regex_son) self.assertEqual(regex_son, regex_son1) reflexive_son1 = copy.copy(reflexive_son) self.assertEqual(reflexive_son, reflexive_son1) # Test deepcopying simple_son1 = copy.deepcopy(simple_son) self.assertEqual(simple_son, simple_son1) regex_son1 = copy.deepcopy(regex_son) self.assertEqual(regex_son, regex_son1) complex_son1 = copy.deepcopy(complex_son) self.assertEqual(complex_son, complex_son1) reflexive_son1 = copy.deepcopy(reflexive_son) self.assertEqual(list(reflexive_son), list(reflexive_son1)) self.assertEqual(id(reflexive_son1), id(reflexive_son1["reflexive"])) def test_iteration(self): """Test __iter__""" # test success case test_son = SON([(1, 100), (2, 200), (3, 300)]) for ele in test_son: self.assertEqual(ele * 100, test_son[ele]) def test_contains_has(self): """has_key and __contains__""" test_son = SON([(1, 100), (2, 200), (3, 300)]) self.assertIn(1, test_son) self.assertTrue(2 in test_son, "in failed") self.assertFalse(22 in test_son, "in succeeded when it shouldn't") self.assertTrue(test_son.has_key(2), "has_key failed") self.assertFalse(test_son.has_key(22), "has_key succeeded when it shouldn't") def test_clears(self): """Test clear()""" test_son = SON([(1, 100), (2, 200), (3, 300)]) test_son.clear() self.assertNotIn(1, test_son) self.assertEqual(0, len(test_son)) self.assertEqual(0, len(test_son.keys())) self.assertEqual({}, test_son.to_dict()) def test_len(self): """Test len""" test_son = SON() self.assertEqual(0, len(test_son)) test_son = SON([(1, 100), (2, 200), (3, 300)]) self.assertEqual(3, len(test_son)) test_son.popitem() self.assertEqual(2, len(test_son)) def test_keys(self): # Test to make sure that set operations do not throw an error d = SON().keys() for i in [OrderedDict, dict]: try: d - i().keys() except TypeError: self.fail( "SON().keys() is not returning an object compatible " "with %s objects" % (str(i)) ) # Test to verify correctness d = SON({"k": "v"}).keys() for i in [OrderedDict, dict]: self.assertEqual(d | i({"k1": 0}).keys(), {"k", "k1"}) for i in [OrderedDict, dict]: self.assertEqual(d - i({"k": 0}).keys(), set()) if __name__ == "__main__": unittest.main() mongodb-mongo-python-driver-509e9b7/test/test_srv_polling.py000066400000000000000000000315021462766011000243640ustar00rootroot00000000000000# Copyright 2019-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. """Run the SRV support tests.""" from __future__ import annotations import sys from time import sleep from typing import Any sys.path[0:0] = [""] from test import client_knobs, unittest from test.utils import FunctionCallRecorder, wait_until import pymongo from pymongo import common from pymongo.errors import ConfigurationError from pymongo.mongo_client import MongoClient from pymongo.srv_resolver import _have_dnspython WAIT_TIME = 0.1 class SrvPollingKnobs: def __init__( self, ttl_time=None, min_srv_rescan_interval=None, nodelist_callback=None, count_resolver_calls=False, ): self.ttl_time = ttl_time self.min_srv_rescan_interval = min_srv_rescan_interval self.nodelist_callback = nodelist_callback self.count_resolver_calls = count_resolver_calls self.old_min_srv_rescan_interval = None self.old_dns_resolver_response = None def enable(self): self.old_min_srv_rescan_interval = common.MIN_SRV_RESCAN_INTERVAL self.old_dns_resolver_response = pymongo.srv_resolver._SrvResolver.get_hosts_and_min_ttl if self.min_srv_rescan_interval is not None: common.MIN_SRV_RESCAN_INTERVAL = self.min_srv_rescan_interval def mock_get_hosts_and_min_ttl(resolver, *args): assert self.old_dns_resolver_response is not None nodes, ttl = self.old_dns_resolver_response(resolver) if self.nodelist_callback is not None: nodes = self.nodelist_callback() if self.ttl_time is not None: ttl = self.ttl_time return nodes, ttl patch_func: Any if self.count_resolver_calls: patch_func = FunctionCallRecorder(mock_get_hosts_and_min_ttl) else: patch_func = mock_get_hosts_and_min_ttl pymongo.srv_resolver._SrvResolver.get_hosts_and_min_ttl = patch_func # type: ignore def __enter__(self): self.enable() def disable(self): common.MIN_SRV_RESCAN_INTERVAL = self.old_min_srv_rescan_interval # type: ignore pymongo.srv_resolver._SrvResolver.get_hosts_and_min_ttl = ( # type: ignore self.old_dns_resolver_response # type: ignore ) def __exit__(self, exc_type, exc_val, exc_tb): self.disable() class TestSrvPolling(unittest.TestCase): BASE_SRV_RESPONSE = [ ("localhost.test.build.10gen.cc", 27017), ("localhost.test.build.10gen.cc", 27018), ] CONNECTION_STRING = "mongodb+srv://test1.test.build.10gen.cc" def setUp(self): # Patch timeouts to ensure short rescan SRV interval. self.client_knobs = client_knobs( heartbeat_frequency=WAIT_TIME, min_heartbeat_interval=WAIT_TIME, events_queue_frequency=WAIT_TIME, ) self.client_knobs.enable() def tearDown(self): self.client_knobs.disable() def get_nodelist(self, client): return client._topology.description.server_descriptions().keys() def assert_nodelist_change(self, expected_nodelist, client, timeout=(100 * WAIT_TIME)): """Check if the client._topology eventually sees all nodes in the expected_nodelist. """ def predicate(): nodelist = self.get_nodelist(client) if set(expected_nodelist) == set(nodelist): return True return False wait_until(predicate, "see expected nodelist", timeout=timeout) def assert_nodelist_nochange(self, expected_nodelist, client, timeout=(100 * WAIT_TIME)): """Check if the client._topology ever deviates from seeing all nodes in the expected_nodelist. Consistency is checked after sleeping for (WAIT_TIME * 10) seconds. Also check that the resolver is called at least once. """ def predicate(): if set(expected_nodelist) == set(self.get_nodelist(client)): return pymongo.srv_resolver._SrvResolver.get_hosts_and_min_ttl.call_count >= 1 return False wait_until(predicate, "Node list equals expected nodelist", timeout=timeout) nodelist = self.get_nodelist(client) if set(expected_nodelist) != set(nodelist): msg = "Client nodelist %s changed unexpectedly (expected %s)" raise self.fail(msg % (nodelist, expected_nodelist)) self.assertGreaterEqual( pymongo.srv_resolver._SrvResolver.get_hosts_and_min_ttl.call_count, # type: ignore 1, "resolver was never called", ) return True def run_scenario(self, dns_response, expect_change): self.assertEqual(_have_dnspython(), True) if callable(dns_response): dns_resolver_response = dns_response else: def dns_resolver_response(): return dns_response if expect_change: assertion_method = self.assert_nodelist_change count_resolver_calls = False expected_response = dns_response else: assertion_method = self.assert_nodelist_nochange count_resolver_calls = True expected_response = self.BASE_SRV_RESPONSE # Patch timeouts to ensure short test running times. with SrvPollingKnobs(ttl_time=WAIT_TIME, min_srv_rescan_interval=WAIT_TIME): client = MongoClient(self.CONNECTION_STRING) self.assert_nodelist_change(self.BASE_SRV_RESPONSE, client) # Patch list of hosts returned by DNS query. with SrvPollingKnobs( nodelist_callback=dns_resolver_response, count_resolver_calls=count_resolver_calls ): assertion_method(expected_response, client) def test_addition(self): response = self.BASE_SRV_RESPONSE[:] response.append(("localhost.test.build.10gen.cc", 27019)) self.run_scenario(response, True) def test_removal(self): response = self.BASE_SRV_RESPONSE[:] response.remove(("localhost.test.build.10gen.cc", 27018)) self.run_scenario(response, True) def test_replace_one(self): response = self.BASE_SRV_RESPONSE[:] response.remove(("localhost.test.build.10gen.cc", 27018)) response.append(("localhost.test.build.10gen.cc", 27019)) self.run_scenario(response, True) def test_replace_both_with_one(self): response = [("localhost.test.build.10gen.cc", 27019)] self.run_scenario(response, True) def test_replace_both_with_two(self): response = [ ("localhost.test.build.10gen.cc", 27019), ("localhost.test.build.10gen.cc", 27020), ] self.run_scenario(response, True) def test_dns_failures(self): from dns import exception for exc in (exception.FormError, exception.TooBig, exception.Timeout): def response_callback(*args): raise exc("DNS Failure!") self.run_scenario(response_callback, False) def test_dns_record_lookup_empty(self): response: list = [] self.run_scenario(response, False) def _test_recover_from_initial(self, initial_callback): # Construct a valid final response callback distinct from base. response_final = self.BASE_SRV_RESPONSE[:] response_final.pop() def final_callback(): return response_final with SrvPollingKnobs( ttl_time=WAIT_TIME, min_srv_rescan_interval=WAIT_TIME, nodelist_callback=initial_callback, count_resolver_calls=True, ): # Client uses unpatched method to get initial nodelist client = MongoClient(self.CONNECTION_STRING) # Invalid DNS resolver response should not change nodelist. self.assert_nodelist_nochange(self.BASE_SRV_RESPONSE, client) with SrvPollingKnobs( ttl_time=WAIT_TIME, min_srv_rescan_interval=WAIT_TIME, nodelist_callback=final_callback ): # Nodelist should reflect new valid DNS resolver response. self.assert_nodelist_change(response_final, client) def test_recover_from_initially_empty_seedlist(self): def empty_seedlist(): return [] self._test_recover_from_initial(empty_seedlist) def test_recover_from_initially_erroring_seedlist(self): def erroring_seedlist(): raise ConfigurationError self._test_recover_from_initial(erroring_seedlist) def test_10_all_dns_selected(self): response = [ ("localhost.test.build.10gen.cc", 27017), ("localhost.test.build.10gen.cc", 27019), ("localhost.test.build.10gen.cc", 27020), ] def nodelist_callback(): return response with SrvPollingKnobs(ttl_time=WAIT_TIME, min_srv_rescan_interval=WAIT_TIME): client = MongoClient(self.CONNECTION_STRING, srvMaxHosts=0) self.addCleanup(client.close) with SrvPollingKnobs(nodelist_callback=nodelist_callback): self.assert_nodelist_change(response, client) def test_11_all_dns_selected(self): response = [ ("localhost.test.build.10gen.cc", 27019), ("localhost.test.build.10gen.cc", 27020), ] def nodelist_callback(): return response with SrvPollingKnobs(ttl_time=WAIT_TIME, min_srv_rescan_interval=WAIT_TIME): client = MongoClient(self.CONNECTION_STRING, srvMaxHosts=2) self.addCleanup(client.close) with SrvPollingKnobs(nodelist_callback=nodelist_callback): self.assert_nodelist_change(response, client) def test_12_new_dns_randomly_selected(self): response = [ ("localhost.test.build.10gen.cc", 27020), ("localhost.test.build.10gen.cc", 27019), ("localhost.test.build.10gen.cc", 27017), ] def nodelist_callback(): return response with SrvPollingKnobs(ttl_time=WAIT_TIME, min_srv_rescan_interval=WAIT_TIME): client = MongoClient(self.CONNECTION_STRING, srvMaxHosts=2) self.addCleanup(client.close) with SrvPollingKnobs(nodelist_callback=nodelist_callback): sleep(2 * common.MIN_SRV_RESCAN_INTERVAL) final_topology = set(client.topology_description.server_descriptions()) self.assertIn(("localhost.test.build.10gen.cc", 27017), final_topology) self.assertEqual(len(final_topology), 2) def test_does_not_flipflop(self): with SrvPollingKnobs(ttl_time=WAIT_TIME, min_srv_rescan_interval=WAIT_TIME): client = MongoClient(self.CONNECTION_STRING, srvMaxHosts=1) self.addCleanup(client.close) old = set(client.topology_description.server_descriptions()) sleep(4 * WAIT_TIME) new = set(client.topology_description.server_descriptions()) self.assertSetEqual(old, new) def test_srv_service_name(self): # Construct a valid final response callback distinct from base. response = [ ("localhost.test.build.10gen.cc.", 27019), ("localhost.test.build.10gen.cc.", 27020), ] def nodelist_callback(): return response with SrvPollingKnobs(ttl_time=WAIT_TIME, min_srv_rescan_interval=WAIT_TIME): client = MongoClient( "mongodb+srv://test22.test.build.10gen.cc/?srvServiceName=customname" ) with SrvPollingKnobs(nodelist_callback=nodelist_callback): self.assert_nodelist_change(response, client) def test_srv_waits_to_poll(self): modified = [("localhost.test.build.10gen.cc", 27019)] def resolver_response(): return modified with SrvPollingKnobs( ttl_time=WAIT_TIME, min_srv_rescan_interval=WAIT_TIME, nodelist_callback=resolver_response, ): client = MongoClient(self.CONNECTION_STRING) self.assertRaises( AssertionError, self.assert_nodelist_change, modified, client, timeout=WAIT_TIME / 2 ) def test_import_dns_resolver(self): # Regression test for PYTHON-4407 import dns.resolver self.assertTrue(hasattr(dns.resolver, "resolve")) if __name__ == "__main__": unittest.main() mongodb-mongo-python-driver-509e9b7/test/test_ssl.py000066400000000000000000000601061462766011000226310ustar00rootroot00000000000000# Copyright 2011-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. """Tests for SSL support.""" from __future__ import annotations import os import socket import sys sys.path[0:0] = [""] from test import HAVE_IPADDRESS, IntegrationTest, SkipTest, client_context, unittest from test.utils import ( EventListener, cat_files, connected, ignore_deprecations, remove_all_users, ) from urllib.parse import quote_plus from pymongo import MongoClient, ssl_support from pymongo.errors import ConfigurationError, ConnectionFailure, OperationFailure from pymongo.hello import HelloCompat from pymongo.ssl_support import HAVE_SSL, _ssl, get_ssl_context from pymongo.write_concern import WriteConcern _HAVE_PYOPENSSL = False try: # All of these must be available to use PyOpenSSL import OpenSSL import requests import service_identity # Ensure service_identity>=18.1 is installed from service_identity.pyopenssl import verify_ip_address from pymongo.ocsp_support import _load_trusted_ca_certs _HAVE_PYOPENSSL = True except ImportError: _load_trusted_ca_certs = None # type: ignore if HAVE_SSL: import ssl CERT_PATH = os.path.join(os.path.dirname(os.path.realpath(__file__)), "certificates") CLIENT_PEM = os.path.join(CERT_PATH, "client.pem") CLIENT_ENCRYPTED_PEM = os.path.join(CERT_PATH, "password_protected.pem") CA_PEM = os.path.join(CERT_PATH, "ca.pem") CA_BUNDLE_PEM = os.path.join(CERT_PATH, "trusted-ca.pem") CRL_PEM = os.path.join(CERT_PATH, "crl.pem") MONGODB_X509_USERNAME = "C=US,ST=New York,L=New York City,O=MDB,OU=Drivers,CN=client" # To fully test this start a mongod instance (built with SSL support) like so: # mongod --dbpath /path/to/data/directory --sslOnNormalPorts \ # --sslPEMKeyFile /path/to/pymongo/test/certificates/server.pem \ # --sslCAFile /path/to/pymongo/test/certificates/ca.pem \ # --sslWeakCertificateValidation # Also, make sure you have 'server' as an alias for localhost in /etc/hosts # # Note: For all replica set tests to pass, the replica set configuration must # use 'localhost' for the hostname of all hosts. class TestClientSSL(unittest.TestCase): @unittest.skipIf(HAVE_SSL, "The ssl module is available, can't test what happens without it.") def test_no_ssl_module(self): # Explicit self.assertRaises(ConfigurationError, MongoClient, ssl=True) # Implied self.assertRaises(ConfigurationError, MongoClient, tlsCertificateKeyFile=CLIENT_PEM) @unittest.skipUnless(HAVE_SSL, "The ssl module is not available.") @ignore_deprecations def test_config_ssl(self): # Tests various ssl configurations self.assertRaises(ValueError, MongoClient, ssl="foo") self.assertRaises( ConfigurationError, MongoClient, tls=False, tlsCertificateKeyFile=CLIENT_PEM ) self.assertRaises(TypeError, MongoClient, ssl=0) self.assertRaises(TypeError, MongoClient, ssl=5.5) self.assertRaises(TypeError, MongoClient, ssl=[]) self.assertRaises(IOError, MongoClient, tlsCertificateKeyFile="NoSuchFile") self.assertRaises(TypeError, MongoClient, tlsCertificateKeyFile=True) self.assertRaises(TypeError, MongoClient, tlsCertificateKeyFile=[]) # Test invalid combinations self.assertRaises( ConfigurationError, MongoClient, tls=False, tlsCertificateKeyFile=CLIENT_PEM ) self.assertRaises(ConfigurationError, MongoClient, tls=False, tlsCAFile=CA_PEM) self.assertRaises(ConfigurationError, MongoClient, tls=False, tlsCRLFile=CRL_PEM) self.assertRaises( ConfigurationError, MongoClient, tls=False, tlsAllowInvalidCertificates=False ) self.assertRaises( ConfigurationError, MongoClient, tls=False, tlsAllowInvalidHostnames=False ) self.assertRaises( ConfigurationError, MongoClient, tls=False, tlsDisableOCSPEndpointCheck=False ) @unittest.skipUnless(_HAVE_PYOPENSSL, "PyOpenSSL is not available.") def test_use_pyopenssl_when_available(self): self.assertTrue(_ssl.IS_PYOPENSSL) @unittest.skipUnless(_HAVE_PYOPENSSL, "Cannot test without PyOpenSSL") def test_load_trusted_ca_certs(self): trusted_ca_certs = _load_trusted_ca_certs(CA_BUNDLE_PEM) self.assertEqual(2, len(trusted_ca_certs)) class TestSSL(IntegrationTest): saved_port: int def assertClientWorks(self, client): coll = client.pymongo_test.ssl_test.with_options( write_concern=WriteConcern(w=client_context.w) ) coll.drop() coll.insert_one({"ssl": True}) self.assertTrue(coll.find_one()["ssl"]) coll.drop() @classmethod @unittest.skipUnless(HAVE_SSL, "The ssl module is not available.") def setUpClass(cls): super().setUpClass() # MongoClient should connect to the primary by default. cls.saved_port = MongoClient.PORT MongoClient.PORT = client_context.port @classmethod def tearDownClass(cls): MongoClient.PORT = cls.saved_port super().tearDownClass() @client_context.require_tls def test_simple_ssl(self): # Expects the server to be running with ssl and with # no --sslPEMKeyFile or with --sslWeakCertificateValidation self.assertClientWorks(self.client) @client_context.require_tlsCertificateKeyFile @ignore_deprecations def test_tlsCertificateKeyFilePassword(self): # Expects the server to be running with server.pem and ca.pem # # --sslPEMKeyFile=/path/to/pymongo/test/certificates/server.pem # --sslCAFile=/path/to/pymongo/test/certificates/ca.pem if not hasattr(ssl, "SSLContext") and not _ssl.IS_PYOPENSSL: self.assertRaises( ConfigurationError, MongoClient, "localhost", ssl=True, tlsCertificateKeyFile=CLIENT_ENCRYPTED_PEM, tlsCertificateKeyFilePassword="qwerty", tlsCAFile=CA_PEM, serverSelectionTimeoutMS=1000, ) else: connected( MongoClient( "localhost", ssl=True, tlsCertificateKeyFile=CLIENT_ENCRYPTED_PEM, tlsCertificateKeyFilePassword="qwerty", tlsCAFile=CA_PEM, serverSelectionTimeoutMS=5000, **self.credentials, # type: ignore[arg-type] ) ) uri_fmt = ( "mongodb://localhost/?ssl=true" "&tlsCertificateKeyFile=%s&tlsCertificateKeyFilePassword=qwerty" "&tlsCAFile=%s&serverSelectionTimeoutMS=5000" ) connected( MongoClient(uri_fmt % (CLIENT_ENCRYPTED_PEM, CA_PEM), **self.credentials) # type: ignore[arg-type] ) @client_context.require_tlsCertificateKeyFile @client_context.require_no_auth @ignore_deprecations def test_cert_ssl_implicitly_set(self): # Expects the server to be running with server.pem and ca.pem # # --sslPEMKeyFile=/path/to/pymongo/test/certificates/server.pem # --sslCAFile=/path/to/pymongo/test/certificates/ca.pem # # test that setting tlsCertificateKeyFile causes ssl to be set to True client = MongoClient( client_context.host, client_context.port, tlsAllowInvalidCertificates=True, tlsCertificateKeyFile=CLIENT_PEM, ) response = client.admin.command(HelloCompat.LEGACY_CMD) if "setName" in response: client = MongoClient( client_context.pair, replicaSet=response["setName"], w=len(response["hosts"]), tlsAllowInvalidCertificates=True, tlsCertificateKeyFile=CLIENT_PEM, ) self.assertClientWorks(client) @client_context.require_tlsCertificateKeyFile @client_context.require_no_auth @ignore_deprecations def test_cert_ssl_validation(self): # Expects the server to be running with server.pem and ca.pem # # --sslPEMKeyFile=/path/to/pymongo/test/certificates/server.pem # --sslCAFile=/path/to/pymongo/test/certificates/ca.pem # client = MongoClient( "localhost", ssl=True, tlsCertificateKeyFile=CLIENT_PEM, tlsAllowInvalidCertificates=False, tlsCAFile=CA_PEM, ) response = client.admin.command(HelloCompat.LEGACY_CMD) if "setName" in response: if response["primary"].split(":")[0] != "localhost": raise SkipTest( "No hosts in the replicaset for 'localhost'. " "Cannot validate hostname in the certificate" ) client = MongoClient( "localhost", replicaSet=response["setName"], w=len(response["hosts"]), ssl=True, tlsCertificateKeyFile=CLIENT_PEM, tlsAllowInvalidCertificates=False, tlsCAFile=CA_PEM, ) self.assertClientWorks(client) if HAVE_IPADDRESS: client = MongoClient( "127.0.0.1", ssl=True, tlsCertificateKeyFile=CLIENT_PEM, tlsAllowInvalidCertificates=False, tlsCAFile=CA_PEM, ) self.assertClientWorks(client) @client_context.require_tlsCertificateKeyFile @client_context.require_no_auth @ignore_deprecations def test_cert_ssl_uri_support(self): # Expects the server to be running with server.pem and ca.pem # # --sslPEMKeyFile=/path/to/pymongo/test/certificates/server.pem # --sslCAFile=/path/to/pymongo/test/certificates/ca.pem # uri_fmt = ( "mongodb://localhost/?ssl=true&tlsCertificateKeyFile=%s&tlsAllowInvalidCertificates" "=%s&tlsCAFile=%s&tlsAllowInvalidHostnames=false" ) client = MongoClient(uri_fmt % (CLIENT_PEM, "true", CA_PEM)) self.assertClientWorks(client) @client_context.require_tlsCertificateKeyFile @client_context.require_server_resolvable @ignore_deprecations def test_cert_ssl_validation_hostname_matching(self): # Expects the server to be running with server.pem and ca.pem # # --sslPEMKeyFile=/path/to/pymongo/test/certificates/server.pem # --sslCAFile=/path/to/pymongo/test/certificates/ca.pem ctx = get_ssl_context(None, None, None, None, True, True, False) self.assertFalse(ctx.check_hostname) ctx = get_ssl_context(None, None, None, None, True, False, False) self.assertFalse(ctx.check_hostname) ctx = get_ssl_context(None, None, None, None, False, True, False) self.assertFalse(ctx.check_hostname) ctx = get_ssl_context(None, None, None, None, False, False, False) self.assertTrue(ctx.check_hostname) response = self.client.admin.command(HelloCompat.LEGACY_CMD) with self.assertRaises(ConnectionFailure): connected( MongoClient( "server", ssl=True, tlsCertificateKeyFile=CLIENT_PEM, tlsAllowInvalidCertificates=False, tlsCAFile=CA_PEM, serverSelectionTimeoutMS=500, **self.credentials, # type: ignore[arg-type] ) ) connected( MongoClient( "server", ssl=True, tlsCertificateKeyFile=CLIENT_PEM, tlsAllowInvalidCertificates=False, tlsCAFile=CA_PEM, tlsAllowInvalidHostnames=True, serverSelectionTimeoutMS=500, **self.credentials, # type: ignore[arg-type] ) ) if "setName" in response: with self.assertRaises(ConnectionFailure): connected( MongoClient( "server", replicaSet=response["setName"], ssl=True, tlsCertificateKeyFile=CLIENT_PEM, tlsAllowInvalidCertificates=False, tlsCAFile=CA_PEM, serverSelectionTimeoutMS=500, **self.credentials, # type: ignore[arg-type] ) ) connected( MongoClient( "server", replicaSet=response["setName"], ssl=True, tlsCertificateKeyFile=CLIENT_PEM, tlsAllowInvalidCertificates=False, tlsCAFile=CA_PEM, tlsAllowInvalidHostnames=True, serverSelectionTimeoutMS=500, **self.credentials, # type: ignore[arg-type] ) ) @client_context.require_tlsCertificateKeyFile @ignore_deprecations def test_tlsCRLFile_support(self): if not hasattr(ssl, "VERIFY_CRL_CHECK_LEAF") or _ssl.IS_PYOPENSSL: self.assertRaises( ConfigurationError, MongoClient, "localhost", ssl=True, tlsCAFile=CA_PEM, tlsCRLFile=CRL_PEM, serverSelectionTimeoutMS=1000, ) else: connected( MongoClient( "localhost", ssl=True, tlsCAFile=CA_PEM, serverSelectionTimeoutMS=1000, **self.credentials, # type: ignore[arg-type] ) ) with self.assertRaises(ConnectionFailure): connected( MongoClient( "localhost", ssl=True, tlsCAFile=CA_PEM, tlsCRLFile=CRL_PEM, serverSelectionTimeoutMS=1000, **self.credentials, # type: ignore[arg-type] ) ) uri_fmt = "mongodb://localhost/?ssl=true&tlsCAFile=%s&serverSelectionTimeoutMS=1000" connected(MongoClient(uri_fmt % (CA_PEM,), **self.credentials)) # type: ignore uri_fmt = ( "mongodb://localhost/?ssl=true&tlsCRLFile=%s" "&tlsCAFile=%s&serverSelectionTimeoutMS=1000" ) with self.assertRaises(ConnectionFailure): connected( MongoClient(uri_fmt % (CRL_PEM, CA_PEM), **self.credentials) # type: ignore[arg-type] ) @client_context.require_tlsCertificateKeyFile @client_context.require_server_resolvable @ignore_deprecations def test_validation_with_system_ca_certs(self): # Expects the server to be running with server.pem and ca.pem. # # --sslPEMKeyFile=/path/to/pymongo/test/certificates/server.pem # --sslCAFile=/path/to/pymongo/test/certificates/ca.pem # --sslWeakCertificateValidation # self.patch_system_certs(CA_PEM) with self.assertRaises(ConnectionFailure): # Server cert is verified but hostname matching fails connected( MongoClient("server", ssl=True, serverSelectionTimeoutMS=1000, **self.credentials) # type: ignore[arg-type] ) # Server cert is verified. Disable hostname matching. connected( MongoClient( "server", ssl=True, tlsAllowInvalidHostnames=True, serverSelectionTimeoutMS=1000, **self.credentials, # type: ignore[arg-type] ) ) # Server cert and hostname are verified. connected( MongoClient("localhost", ssl=True, serverSelectionTimeoutMS=1000, **self.credentials) # type: ignore[arg-type] ) # Server cert and hostname are verified. connected( MongoClient( "mongodb://localhost/?ssl=true&serverSelectionTimeoutMS=1000", **self.credentials, # type: ignore[arg-type] ) ) def test_system_certs_config_error(self): ctx = get_ssl_context(None, None, None, None, True, True, False) if (sys.platform != "win32" and hasattr(ctx, "set_default_verify_paths")) or hasattr( ctx, "load_default_certs" ): raise SkipTest("Can't test when system CA certificates are loadable.") have_certifi = ssl_support.HAVE_CERTIFI have_wincertstore = ssl_support.HAVE_WINCERTSTORE # Force the test regardless of environment. ssl_support.HAVE_CERTIFI = False ssl_support.HAVE_WINCERTSTORE = False try: with self.assertRaises(ConfigurationError): MongoClient("mongodb://localhost/?ssl=true") finally: ssl_support.HAVE_CERTIFI = have_certifi ssl_support.HAVE_WINCERTSTORE = have_wincertstore def test_certifi_support(self): if hasattr(ssl, "SSLContext"): # SSLSocket doesn't provide ca_certs attribute on pythons # with SSLContext and SSLContext provides no information # about ca_certs. raise SkipTest("Can't test when SSLContext available.") if not ssl_support.HAVE_CERTIFI: raise SkipTest("Need certifi to test certifi support.") have_wincertstore = ssl_support.HAVE_WINCERTSTORE # Force the test on Windows, regardless of environment. ssl_support.HAVE_WINCERTSTORE = False try: ctx = get_ssl_context(None, None, CA_PEM, None, False, False, False) ssl_sock = ctx.wrap_socket(socket.socket()) self.assertEqual(ssl_sock.ca_certs, CA_PEM) ctx = get_ssl_context(None, None, None, None, False, False, False) ssl_sock = ctx.wrap_socket(socket.socket()) self.assertEqual(ssl_sock.ca_certs, ssl_support.certifi.where()) finally: ssl_support.HAVE_WINCERTSTORE = have_wincertstore def test_wincertstore(self): if sys.platform != "win32": raise SkipTest("Only valid on Windows.") if hasattr(ssl, "SSLContext"): # SSLSocket doesn't provide ca_certs attribute on pythons # with SSLContext and SSLContext provides no information # about ca_certs. raise SkipTest("Can't test when SSLContext available.") if not ssl_support.HAVE_WINCERTSTORE: raise SkipTest("Need wincertstore to test wincertstore.") ctx = get_ssl_context(None, None, CA_PEM, None, False, False, False) ssl_sock = ctx.wrap_socket(socket.socket()) self.assertEqual(ssl_sock.ca_certs, CA_PEM) ctx = get_ssl_context(None, None, None, None, False, False, False) ssl_sock = ctx.wrap_socket(socket.socket()) self.assertEqual(ssl_sock.ca_certs, ssl_support._WINCERTS.name) @client_context.require_auth @client_context.require_tlsCertificateKeyFile @ignore_deprecations def test_mongodb_x509_auth(self): host, port = client_context.host, client_context.port self.addCleanup(remove_all_users, client_context.client["$external"]) # Give x509 user all necessary privileges. client_context.create_user( "$external", MONGODB_X509_USERNAME, roles=[ {"role": "readWriteAnyDatabase", "db": "admin"}, {"role": "userAdminAnyDatabase", "db": "admin"}, ], ) noauth = MongoClient( client_context.pair, ssl=True, tlsAllowInvalidCertificates=True, tlsCertificateKeyFile=CLIENT_PEM, ) self.addCleanup(noauth.close) with self.assertRaises(OperationFailure): noauth.pymongo_test.test.find_one() listener = EventListener() auth = MongoClient( client_context.pair, authMechanism="MONGODB-X509", ssl=True, tlsAllowInvalidCertificates=True, tlsCertificateKeyFile=CLIENT_PEM, event_listeners=[listener], ) self.addCleanup(auth.close) # No error auth.pymongo_test.test.find_one() names = listener.started_command_names() if client_context.version.at_least(4, 4, -1): # Speculative auth skips the authenticate command. self.assertEqual(names, ["find"]) else: self.assertEqual(names, ["authenticate", "find"]) uri = "mongodb://%s@%s:%d/?authMechanism=MONGODB-X509" % ( quote_plus(MONGODB_X509_USERNAME), host, port, ) client = MongoClient( uri, ssl=True, tlsAllowInvalidCertificates=True, tlsCertificateKeyFile=CLIENT_PEM ) self.addCleanup(client.close) # No error client.pymongo_test.test.find_one() uri = "mongodb://%s:%d/?authMechanism=MONGODB-X509" % (host, port) client = MongoClient( uri, ssl=True, tlsAllowInvalidCertificates=True, tlsCertificateKeyFile=CLIENT_PEM ) self.addCleanup(client.close) # No error client.pymongo_test.test.find_one() # Auth should fail if username and certificate do not match uri = "mongodb://%s@%s:%d/?authMechanism=MONGODB-X509" % ( quote_plus("not the username"), host, port, ) bad_client = MongoClient( uri, ssl=True, tlsAllowInvalidCertificates=True, tlsCertificateKeyFile=CLIENT_PEM ) self.addCleanup(bad_client.close) with self.assertRaises(OperationFailure): bad_client.pymongo_test.test.find_one() bad_client = MongoClient( client_context.pair, username="not the username", authMechanism="MONGODB-X509", ssl=True, tlsAllowInvalidCertificates=True, tlsCertificateKeyFile=CLIENT_PEM, ) self.addCleanup(bad_client.close) with self.assertRaises(OperationFailure): bad_client.pymongo_test.test.find_one() # Invalid certificate (using CA certificate as client certificate) uri = "mongodb://%s@%s:%d/?authMechanism=MONGODB-X509" % ( quote_plus(MONGODB_X509_USERNAME), host, port, ) try: connected( MongoClient( uri, ssl=True, tlsAllowInvalidCertificates=True, tlsCertificateKeyFile=CA_PEM, serverSelectionTimeoutMS=1000, ) ) except (ConnectionFailure, ConfigurationError): pass else: self.fail("Invalid certificate accepted.") @client_context.require_tlsCertificateKeyFile @ignore_deprecations def test_connect_with_ca_bundle(self): def remove(path): try: os.remove(path) except OSError: pass temp_ca_bundle = os.path.join(CERT_PATH, "trusted-ca-bundle.pem") self.addCleanup(remove, temp_ca_bundle) # Add the CA cert file to the bundle. cat_files(temp_ca_bundle, CA_BUNDLE_PEM, CA_PEM) with MongoClient( "localhost", tls=True, tlsCertificateKeyFile=CLIENT_PEM, tlsCAFile=temp_ca_bundle ) as client: self.assertTrue(client.admin.command("ping")) if __name__ == "__main__": unittest.main() mongodb-mongo-python-driver-509e9b7/test/test_streaming_protocol.py000066400000000000000000000210071462766011000257370ustar00rootroot00000000000000# Copyright 2020-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. """Test the database module.""" from __future__ import annotations import sys import time sys.path[0:0] = [""] from test import IntegrationTest, client_context, unittest from test.utils import ( HeartbeatEventListener, ServerEventListener, rs_or_single_client, single_client, wait_until, ) from pymongo import monitoring from pymongo.hello import HelloCompat class TestStreamingProtocol(IntegrationTest): @client_context.require_failCommand_appName def test_failCommand_streaming(self): listener = ServerEventListener() hb_listener = HeartbeatEventListener() client = rs_or_single_client( event_listeners=[listener, hb_listener], heartbeatFrequencyMS=500, appName="failingHeartbeatTest", ) self.addCleanup(client.close) # Force a connection. client.admin.command("ping") address = client.address listener.reset() fail_hello = { "configureFailPoint": "failCommand", "mode": {"times": 4}, "data": { "failCommands": [HelloCompat.LEGACY_CMD, "hello"], "closeConnection": False, "errorCode": 10107, "appName": "failingHeartbeatTest", }, } with self.fail_point(fail_hello): def _marked_unknown(event): return ( event.server_address == address and not event.new_description.is_server_type_known ) def _discovered_node(event): return ( event.server_address == address and not event.previous_description.is_server_type_known and event.new_description.is_server_type_known ) def marked_unknown(): return len(listener.matching(_marked_unknown)) >= 1 def rediscovered(): return len(listener.matching(_discovered_node)) >= 1 # Topology events are published asynchronously wait_until(marked_unknown, "mark node unknown") wait_until(rediscovered, "rediscover node") # Server should be selectable. client.admin.command("ping") @client_context.require_failCommand_appName def test_streaming_rtt(self): listener = ServerEventListener() hb_listener = HeartbeatEventListener() # On Windows, RTT can actually be 0.0 because time.time() only has # 1-15 millisecond resolution. We need to delay the initial hello # to ensure that RTT is never zero. name = "streamingRttTest" delay_hello: dict = { "configureFailPoint": "failCommand", "mode": {"times": 1000}, "data": { "failCommands": [HelloCompat.LEGACY_CMD, "hello"], "blockConnection": True, "blockTimeMS": 20, # This can be uncommented after SERVER-49220 is fixed. # 'appName': name, }, } with self.fail_point(delay_hello): client = rs_or_single_client( event_listeners=[listener, hb_listener], heartbeatFrequencyMS=500, appName=name ) self.addCleanup(client.close) # Force a connection. client.admin.command("ping") address = client.address delay_hello["data"]["blockTimeMS"] = 500 delay_hello["data"]["appName"] = name with self.fail_point(delay_hello): def rtt_exceeds_250_ms(): # XXX: Add a public TopologyDescription getter to MongoClient? topology = client._topology sd = topology.description.server_descriptions()[address] assert sd.round_trip_time is not None return sd.round_trip_time > 0.250 wait_until(rtt_exceeds_250_ms, "exceed 250ms RTT") # Server should be selectable. client.admin.command("ping") def changed_event(event): return event.server_address == address and isinstance( event, monitoring.ServerDescriptionChangedEvent ) # There should only be one event published, for the initial discovery. events = listener.matching(changed_event) self.assertEqual(1, len(events)) self.assertGreater(events[0].new_description.round_trip_time, 0) @client_context.require_version_min(4, 9, -1) @client_context.require_failCommand_appName def test_monitor_waits_after_server_check_error(self): # This test implements: # https://github.com/mongodb/specifications/blob/6c5b2ac/source/server-discovery-and-monitoring/server-discovery-and-monitoring-tests.rst#monitors-sleep-at-least-minheartbeatfreqencyms-between-checks fail_hello = { "mode": {"times": 5}, "data": { "failCommands": [HelloCompat.LEGACY_CMD, "hello"], "errorCode": 1234, "appName": "SDAMMinHeartbeatFrequencyTest", }, } with self.fail_point(fail_hello): start = time.time() client = single_client( appName="SDAMMinHeartbeatFrequencyTest", serverSelectionTimeoutMS=5000 ) self.addCleanup(client.close) # Force a connection. client.admin.command("ping") duration = time.time() - start # Explanation of the expected events: # 0ms: run configureFailPoint # 1ms: create MongoClient # 2ms: failed monitor handshake, 1 # 502ms: failed monitor handshake, 2 # 1002ms: failed monitor handshake, 3 # 1502ms: failed monitor handshake, 4 # 2002ms: failed monitor handshake, 5 # 2502ms: monitor handshake succeeds # 2503ms: run awaitable hello # 2504ms: application handshake succeeds # 2505ms: ping command succeeds self.assertGreaterEqual(duration, 2) self.assertLessEqual(duration, 3.5) @client_context.require_failCommand_appName def test_heartbeat_awaited_flag(self): hb_listener = HeartbeatEventListener() client = single_client( event_listeners=[hb_listener], heartbeatFrequencyMS=500, appName="heartbeatEventAwaitedFlag", ) self.addCleanup(client.close) # Force a connection. client.admin.command("ping") def hb_succeeded(event): return isinstance(event, monitoring.ServerHeartbeatSucceededEvent) def hb_failed(event): return isinstance(event, monitoring.ServerHeartbeatFailedEvent) fail_heartbeat = { "mode": {"times": 2}, "data": { "failCommands": [HelloCompat.LEGACY_CMD, "hello"], "closeConnection": True, "appName": "heartbeatEventAwaitedFlag", }, } with self.fail_point(fail_heartbeat): wait_until(lambda: hb_listener.matching(hb_failed), "published failed event") # Reconnect. client.admin.command("ping") hb_succeeded_events = hb_listener.matching(hb_succeeded) hb_failed_events = hb_listener.matching(hb_failed) self.assertFalse(hb_succeeded_events[0].awaited) self.assertTrue(hb_failed_events[0].awaited) # Depending on thread scheduling, the failed heartbeat could occur on # the second or third check. events = [type(e) for e in hb_listener.events[:4]] if events == [ monitoring.ServerHeartbeatStartedEvent, monitoring.ServerHeartbeatSucceededEvent, monitoring.ServerHeartbeatStartedEvent, monitoring.ServerHeartbeatFailedEvent, ]: self.assertFalse(hb_succeeded_events[1].awaited) else: self.assertTrue(hb_succeeded_events[1].awaited) if __name__ == "__main__": unittest.main() mongodb-mongo-python-driver-509e9b7/test/test_threads.py000066400000000000000000000105641462766011000234650ustar00rootroot00000000000000# Copyright 2009-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. """Test that pymongo is thread safe.""" from __future__ import annotations import threading from test import IntegrationTest, client_context, unittest from test.utils import joinall @client_context.require_connection def setUpModule(): pass class AutoAuthenticateThreads(threading.Thread): def __init__(self, collection, num): threading.Thread.__init__(self) self.coll = collection self.num = num self.success = False self.daemon = True def run(self): for i in range(self.num): self.coll.insert_one({"num": i}) self.coll.find_one({"num": i}) self.success = True class SaveAndFind(threading.Thread): def __init__(self, collection): threading.Thread.__init__(self) self.collection = collection self.daemon = True self.passed = False def run(self): sum = 0 for document in self.collection.find(): sum += document["x"] assert sum == 499500, "sum was %d not 499500" % sum self.passed = True class Insert(threading.Thread): def __init__(self, collection, n, expect_exception): threading.Thread.__init__(self) self.collection = collection self.n = n self.expect_exception = expect_exception self.daemon = True def run(self): for _ in range(self.n): error = True try: self.collection.insert_one({"test": "insert"}) error = False except: if not self.expect_exception: raise if self.expect_exception: assert error class Update(threading.Thread): def __init__(self, collection, n, expect_exception): threading.Thread.__init__(self) self.collection = collection self.n = n self.expect_exception = expect_exception self.daemon = True def run(self): for _ in range(self.n): error = True try: self.collection.update_one({"test": "unique"}, {"$set": {"test": "update"}}) error = False except: if not self.expect_exception: raise if self.expect_exception: assert error class TestThreads(IntegrationTest): def setUp(self): self.db = self.client.pymongo_test def test_threading(self): self.db.drop_collection("test") self.db.test.insert_many([{"x": i} for i in range(1000)]) threads = [] for _i in range(10): t = SaveAndFind(self.db.test) t.start() threads.append(t) joinall(threads) def test_safe_insert(self): self.db.drop_collection("test1") self.db.test1.insert_one({"test": "insert"}) self.db.drop_collection("test2") self.db.test2.insert_one({"test": "insert"}) self.db.test2.create_index("test", unique=True) self.db.test2.find_one() okay = Insert(self.db.test1, 2000, False) error = Insert(self.db.test2, 2000, True) error.start() okay.start() error.join() okay.join() def test_safe_update(self): self.db.drop_collection("test1") self.db.test1.insert_one({"test": "update"}) self.db.test1.insert_one({"test": "unique"}) self.db.drop_collection("test2") self.db.test2.insert_one({"test": "update"}) self.db.test2.insert_one({"test": "unique"}) self.db.test2.create_index("test", unique=True) self.db.test2.find_one() okay = Update(self.db.test1, 2000, False) error = Update(self.db.test2, 2000, True) error.start() okay.start() error.join() okay.join() if __name__ == "__main__": unittest.main() mongodb-mongo-python-driver-509e9b7/test/test_timestamp.py000066400000000000000000000053371462766011000240400ustar00rootroot00000000000000# Copyright 2009-2015 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. """Tests for the Timestamp class.""" from __future__ import annotations import copy import datetime import pickle import sys sys.path[0:0] = [""] from test import unittest from bson.timestamp import Timestamp from bson.tz_util import utc class TestTimestamp(unittest.TestCase): def test_timestamp(self): t = Timestamp(123, 456) self.assertEqual(t.time, 123) self.assertEqual(t.inc, 456) self.assertTrue(isinstance(t, Timestamp)) def test_datetime(self): d = datetime.datetime(2010, 5, 5, tzinfo=utc) t = Timestamp(d, 0) self.assertEqual(1273017600, t.time) self.assertEqual(d, t.as_datetime()) def test_datetime_copy_pickle(self): d = datetime.datetime(2010, 5, 5, tzinfo=utc) t = Timestamp(d, 0) dc = copy.deepcopy(d) self.assertEqual(dc, t.as_datetime()) for protocol in [0, 1, 2, -1]: pkl = pickle.dumps(d, protocol=protocol) dp = pickle.loads(pkl) self.assertEqual(dp, t.as_datetime()) def test_exceptions(self): self.assertRaises(TypeError, Timestamp) self.assertRaises(TypeError, Timestamp, None, 123) self.assertRaises(TypeError, Timestamp, 1.2, 123) self.assertRaises(TypeError, Timestamp, 123, None) self.assertRaises(TypeError, Timestamp, 123, 1.2) self.assertRaises(ValueError, Timestamp, 0, -1) self.assertRaises(ValueError, Timestamp, -1, 0) self.assertTrue(Timestamp(0, 0)) def test_equality(self): t = Timestamp(1, 1) self.assertNotEqual(t, Timestamp(0, 1)) self.assertNotEqual(t, Timestamp(1, 0)) self.assertEqual(t, Timestamp(1, 1)) # Explicitly test inequality self.assertFalse(t != Timestamp(1, 1)) def test_hash(self): self.assertEqual(hash(Timestamp(1, 2)), hash(Timestamp(1, 2))) self.assertNotEqual(hash(Timestamp(1, 2)), hash(Timestamp(1, 3))) self.assertNotEqual(hash(Timestamp(1, 2)), hash(Timestamp(2, 2))) def test_repr(self): t = Timestamp(0, 0) self.assertEqual(repr(t), "Timestamp(0, 0)") if __name__ == "__main__": unittest.main() mongodb-mongo-python-driver-509e9b7/test/test_topology.py000066400000000000000000000755411462766011000237150ustar00rootroot00000000000000# Copyright 2014-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. """Test the topology module.""" from __future__ import annotations import sys from pymongo.operations import _Op sys.path[0:0] = [""] from test import client_knobs, unittest from test.pymongo_mocks import DummyMonitor from test.utils import MockPool, wait_until from bson.objectid import ObjectId from pymongo import common from pymongo.errors import AutoReconnect, ConfigurationError, ConnectionFailure from pymongo.hello import Hello, HelloCompat from pymongo.monitor import Monitor from pymongo.pool import PoolOptions from pymongo.read_preferences import ReadPreference, Secondary from pymongo.server import Server from pymongo.server_description import ServerDescription from pymongo.server_selectors import any_server_selector, writable_server_selector from pymongo.server_type import SERVER_TYPE from pymongo.settings import TopologySettings from pymongo.topology import Topology, _ErrorContext, _filter_servers from pymongo.topology_description import TOPOLOGY_TYPE class SetNameDiscoverySettings(TopologySettings): def get_topology_type(self): return TOPOLOGY_TYPE.ReplicaSetNoPrimary address = ("a", 27017) def create_mock_topology( seeds=None, replica_set_name=None, monitor_class=DummyMonitor, direct_connection=False ): partitioned_seeds = list(map(common.partition_node, seeds or ["a"])) topology_settings = TopologySettings( partitioned_seeds, replica_set_name=replica_set_name, pool_class=MockPool, # type: ignore[arg-type] monitor_class=monitor_class, direct_connection=direct_connection, ) t = Topology(topology_settings) t.open() return t def got_hello(topology, server_address, hello_response): server_description = ServerDescription(server_address, Hello(hello_response), 0) topology.on_change(server_description) def disconnected(topology, server_address): # Create new description of server type Unknown. topology.on_change(ServerDescription(server_address)) def get_server(topology, hostname): return topology.get_server_by_address((hostname, 27017)) def get_type(topology, hostname): return get_server(topology, hostname).description.server_type def get_monitor(topology, hostname): return get_server(topology, hostname)._monitor class TopologyTest(unittest.TestCase): """Disables periodic monitoring, to make tests deterministic.""" def setUp(self): super().setUp() self.client_knobs = client_knobs(heartbeat_frequency=999999) self.client_knobs.enable() self.addCleanup(self.client_knobs.disable) class TestTopologyConfiguration(TopologyTest): def test_timeout_configuration(self): pool_options = PoolOptions(connect_timeout=1, socket_timeout=2) topology_settings = TopologySettings(pool_options=pool_options) t = Topology(topology_settings=topology_settings) t.open() # Get the default server. server = t.get_server_by_address(("localhost", 27017)) # The pool for application operations obeys our settings. self.assertEqual(1, server._pool.opts.connect_timeout) self.assertEqual(2, server._pool.opts.socket_timeout) # The pool for monitoring operations uses our connect_timeout as both # its connect_timeout and its socket_timeout. monitor = server._monitor self.assertEqual(1, monitor._pool.opts.connect_timeout) self.assertEqual(1, monitor._pool.opts.socket_timeout) # The monitor, not its pool, is responsible for calling hello. self.assertFalse(monitor._pool.handshake) class TestSingleServerTopology(TopologyTest): def test_direct_connection(self): for server_type, hello_response in [ ( SERVER_TYPE.RSPrimary, { "ok": 1, HelloCompat.LEGACY_CMD: True, "hosts": ["a"], "setName": "rs", "maxWireVersion": 6, }, ), ( SERVER_TYPE.RSSecondary, { "ok": 1, HelloCompat.LEGACY_CMD: False, "secondary": True, "hosts": ["a"], "setName": "rs", "maxWireVersion": 6, }, ), ( SERVER_TYPE.Mongos, {"ok": 1, HelloCompat.LEGACY_CMD: True, "msg": "isdbgrid", "maxWireVersion": 6}, ), ( SERVER_TYPE.RSArbiter, { "ok": 1, HelloCompat.LEGACY_CMD: False, "arbiterOnly": True, "hosts": ["a"], "setName": "rs", "maxWireVersion": 6, }, ), (SERVER_TYPE.Standalone, {"ok": 1, HelloCompat.LEGACY_CMD: True, "maxWireVersion": 6}), # A "slave" in a master-slave deployment. # This replication type was removed in MongoDB # 4.0. (SERVER_TYPE.Standalone, {"ok": 1, HelloCompat.LEGACY_CMD: False, "maxWireVersion": 6}), ]: t = create_mock_topology(direct_connection=True) # Can't select a server while the only server is of type Unknown. with self.assertRaisesRegex(ConnectionFailure, "No servers found yet"): t.select_servers(any_server_selector, _Op.TEST, server_selection_timeout=0) got_hello(t, address, hello_response) # Topology type never changes. self.assertEqual(TOPOLOGY_TYPE.Single, t.description.topology_type) # No matter whether the server is writable, # select_servers() returns it. s = t.select_server(writable_server_selector, _Op.TEST) self.assertEqual(server_type, s.description.server_type) # Topology type single is always readable and writable regardless # of server type or state. self.assertEqual(t.description.topology_type_name, "Single") self.assertTrue(t.description.has_writable_server()) self.assertTrue(t.description.has_readable_server()) self.assertTrue(t.description.has_readable_server(Secondary())) self.assertTrue( t.description.has_readable_server(Secondary(tag_sets=[{"tag": "does-not-exist"}])) ) def test_reopen(self): t = create_mock_topology() # Additional calls are permitted. t.open() t.open() def test_unavailable_seed(self): t = create_mock_topology() disconnected(t, address) self.assertEqual(SERVER_TYPE.Unknown, get_type(t, "a")) def test_round_trip_time(self): round_trip_time = 125 available = True class TestMonitor(Monitor): def _check_with_socket(self, *args, **kwargs): if available: return (Hello({"ok": 1, "maxWireVersion": 6}), round_trip_time) else: raise AutoReconnect("mock monitor error") t = create_mock_topology(monitor_class=TestMonitor) self.addCleanup(t.close) s = t.select_server(writable_server_selector, _Op.TEST) self.assertEqual(125, s.description.round_trip_time) round_trip_time = 25 t.request_check_all() # Exponential weighted average: .8 * 125 + .2 * 25 = 105. self.assertAlmostEqual(105, s.description.round_trip_time) # The server is temporarily down. available = False t.request_check_all() def raises_err(): try: t.select_server(writable_server_selector, _Op.TEST, server_selection_timeout=0.1) except ConnectionFailure: return True else: return False wait_until(raises_err, "discover server is down") self.assertIsNone(s.description.round_trip_time) # Bring it back, RTT is now 20 milliseconds. available = True round_trip_time = 20 def new_average(): # We reset the average to the most recent measurement. description = s.description return ( description.round_trip_time is not None and round(abs(20 - description.round_trip_time), 7) == 0 ) tries = 0 while not new_average(): t.request_check_all() tries += 1 if tries > 10: self.fail("Didn't ever calculate correct new average") class TestMultiServerTopology(TopologyTest): def test_readable_writable(self): t = create_mock_topology(replica_set_name="rs") got_hello( t, ("a", 27017), {"ok": 1, HelloCompat.LEGACY_CMD: True, "setName": "rs", "hosts": ["a", "b"]}, ) got_hello( t, ("b", 27017), { "ok": 1, HelloCompat.LEGACY_CMD: False, "secondary": True, "setName": "rs", "hosts": ["a", "b"], }, ) self.assertEqual(t.description.topology_type_name, "ReplicaSetWithPrimary") self.assertTrue(t.description.has_writable_server()) self.assertTrue(t.description.has_readable_server()) self.assertTrue(t.description.has_readable_server(Secondary())) self.assertFalse(t.description.has_readable_server(Secondary(tag_sets=[{"tag": "exists"}]))) t = create_mock_topology(replica_set_name="rs") got_hello( t, ("a", 27017), { "ok": 1, HelloCompat.LEGACY_CMD: False, "secondary": False, "setName": "rs", "hosts": ["a", "b"], }, ) got_hello( t, ("b", 27017), { "ok": 1, HelloCompat.LEGACY_CMD: False, "secondary": True, "setName": "rs", "hosts": ["a", "b"], }, ) self.assertEqual(t.description.topology_type_name, "ReplicaSetNoPrimary") self.assertFalse(t.description.has_writable_server()) self.assertFalse(t.description.has_readable_server()) self.assertTrue(t.description.has_readable_server(Secondary())) self.assertFalse(t.description.has_readable_server(Secondary(tag_sets=[{"tag": "exists"}]))) t = create_mock_topology(replica_set_name="rs") got_hello( t, ("a", 27017), {"ok": 1, HelloCompat.LEGACY_CMD: True, "setName": "rs", "hosts": ["a", "b"]}, ) got_hello( t, ("b", 27017), { "ok": 1, HelloCompat.LEGACY_CMD: False, "secondary": True, "setName": "rs", "hosts": ["a", "b"], "tags": {"tag": "exists"}, }, ) self.assertEqual(t.description.topology_type_name, "ReplicaSetWithPrimary") self.assertTrue(t.description.has_writable_server()) self.assertTrue(t.description.has_readable_server()) self.assertTrue(t.description.has_readable_server(Secondary())) self.assertTrue(t.description.has_readable_server(Secondary(tag_sets=[{"tag": "exists"}]))) def test_close(self): t = create_mock_topology(replica_set_name="rs") got_hello( t, ("a", 27017), {"ok": 1, HelloCompat.LEGACY_CMD: True, "setName": "rs", "hosts": ["a", "b"]}, ) got_hello( t, ("b", 27017), { "ok": 1, HelloCompat.LEGACY_CMD: False, "secondary": True, "setName": "rs", "hosts": ["a", "b"], }, ) self.assertEqual(SERVER_TYPE.RSPrimary, get_type(t, "a")) self.assertEqual(SERVER_TYPE.RSSecondary, get_type(t, "b")) self.assertTrue(get_monitor(t, "a").opened) self.assertTrue(get_monitor(t, "b").opened) self.assertEqual(TOPOLOGY_TYPE.ReplicaSetWithPrimary, t.description.topology_type) t.close() self.assertEqual(2, len(t.description.server_descriptions())) self.assertEqual(SERVER_TYPE.Unknown, get_type(t, "a")) self.assertEqual(SERVER_TYPE.Unknown, get_type(t, "b")) self.assertFalse(get_monitor(t, "a").opened) self.assertFalse(get_monitor(t, "b").opened) self.assertEqual("rs", t.description.replica_set_name) self.assertEqual(TOPOLOGY_TYPE.ReplicaSetNoPrimary, t.description.topology_type) # A closed topology should not be updated when receiving a hello. got_hello( t, ("a", 27017), {"ok": 1, HelloCompat.LEGACY_CMD: True, "setName": "rs", "hosts": ["a", "b", "c"]}, ) self.assertEqual(2, len(t.description.server_descriptions())) self.assertEqual(SERVER_TYPE.Unknown, get_type(t, "a")) self.assertEqual(SERVER_TYPE.Unknown, get_type(t, "b")) self.assertFalse(get_monitor(t, "a").opened) self.assertFalse(get_monitor(t, "b").opened) # Server c should not have been added. self.assertEqual(None, get_server(t, "c")) self.assertEqual("rs", t.description.replica_set_name) self.assertEqual(TOPOLOGY_TYPE.ReplicaSetNoPrimary, t.description.topology_type) def test_handle_error(self): t = create_mock_topology(replica_set_name="rs") got_hello( t, ("a", 27017), {"ok": 1, HelloCompat.LEGACY_CMD: True, "setName": "rs", "hosts": ["a", "b"]}, ) got_hello( t, ("b", 27017), { "ok": 1, HelloCompat.LEGACY_CMD: False, "secondary": True, "setName": "rs", "hosts": ["a", "b"], }, ) errctx = _ErrorContext(AutoReconnect("mock"), 0, 0, True, None) t.handle_error(("a", 27017), errctx) self.assertEqual(SERVER_TYPE.Unknown, get_type(t, "a")) self.assertEqual(SERVER_TYPE.RSSecondary, get_type(t, "b")) self.assertEqual("rs", t.description.replica_set_name) self.assertEqual(TOPOLOGY_TYPE.ReplicaSetNoPrimary, t.description.topology_type) got_hello( t, ("a", 27017), {"ok": 1, HelloCompat.LEGACY_CMD: True, "setName": "rs", "hosts": ["a", "b"]}, ) self.assertEqual(SERVER_TYPE.RSPrimary, get_type(t, "a")) self.assertEqual(TOPOLOGY_TYPE.ReplicaSetWithPrimary, t.description.topology_type) t.handle_error(("b", 27017), errctx) self.assertEqual(SERVER_TYPE.RSPrimary, get_type(t, "a")) self.assertEqual(SERVER_TYPE.Unknown, get_type(t, "b")) self.assertEqual("rs", t.description.replica_set_name) self.assertEqual(TOPOLOGY_TYPE.ReplicaSetWithPrimary, t.description.topology_type) def test_handle_error_removed_server(self): t = create_mock_topology(replica_set_name="rs") # No error resetting a server not in the TopologyDescription. errctx = _ErrorContext(AutoReconnect("mock"), 0, 0, True, None) t.handle_error(("b", 27017), errctx) # Server was *not* added as type Unknown. self.assertFalse(t.has_server(("b", 27017))) def test_discover_set_name_from_primary(self): # Discovering a replica set without the setName supplied by the user # is not yet supported by MongoClient, but Topology can do it. topology_settings = SetNameDiscoverySettings( seeds=[address], pool_class=MockPool, # type: ignore[arg-type] monitor_class=DummyMonitor, # type: ignore[arg-type] ) t = Topology(topology_settings) self.assertEqual(t.description.replica_set_name, None) self.assertEqual(t.description.topology_type, TOPOLOGY_TYPE.ReplicaSetNoPrimary) t.open() got_hello( t, address, {"ok": 1, HelloCompat.LEGACY_CMD: True, "setName": "rs", "hosts": ["a"]} ) self.assertEqual(t.description.replica_set_name, "rs") self.assertEqual(t.description.topology_type, TOPOLOGY_TYPE.ReplicaSetWithPrimary) # Another response from the primary. Tests the code that processes # primary response when topology type is already ReplicaSetWithPrimary. got_hello( t, address, {"ok": 1, HelloCompat.LEGACY_CMD: True, "setName": "rs", "hosts": ["a"]} ) # No change. self.assertEqual(t.description.replica_set_name, "rs") self.assertEqual(t.description.topology_type, TOPOLOGY_TYPE.ReplicaSetWithPrimary) def test_discover_set_name_from_secondary(self): # Discovering a replica set without the setName supplied by the user # is not yet supported by MongoClient, but Topology can do it. topology_settings = SetNameDiscoverySettings( seeds=[address], pool_class=MockPool, # type: ignore[arg-type] monitor_class=DummyMonitor, # type: ignore[arg-type] ) t = Topology(topology_settings) self.assertEqual(t.description.replica_set_name, None) self.assertEqual(t.description.topology_type, TOPOLOGY_TYPE.ReplicaSetNoPrimary) t.open() got_hello( t, address, { "ok": 1, HelloCompat.LEGACY_CMD: False, "secondary": True, "setName": "rs", "hosts": ["a"], }, ) self.assertEqual(t.description.replica_set_name, "rs") self.assertEqual(t.description.topology_type, TOPOLOGY_TYPE.ReplicaSetNoPrimary) def test_wire_version(self): t = create_mock_topology(replica_set_name="rs") t.description.check_compatible() # No error. got_hello( t, address, {"ok": 1, HelloCompat.LEGACY_CMD: True, "setName": "rs", "hosts": ["a"]} ) # Use defaults. server = t.get_server_by_address(address) self.assertEqual(server.description.min_wire_version, 0) self.assertEqual(server.description.max_wire_version, 0) got_hello( t, address, { "ok": 1, HelloCompat.LEGACY_CMD: True, "setName": "rs", "hosts": ["a"], "minWireVersion": 1, "maxWireVersion": 6, }, ) self.assertEqual(server.description.min_wire_version, 1) self.assertEqual(server.description.max_wire_version, 6) t.select_servers(any_server_selector, _Op.TEST) # Incompatible. got_hello( t, address, { "ok": 1, HelloCompat.LEGACY_CMD: True, "setName": "rs", "hosts": ["a"], "minWireVersion": 22, "maxWireVersion": 24, }, ) try: t.select_servers(any_server_selector, _Op.TEST) except ConfigurationError as e: # Error message should say which server failed and why. self.assertEqual( str(e), "Server at a:27017 requires wire version 22, but this version " "of PyMongo only supports up to %d." % (common.MAX_SUPPORTED_WIRE_VERSION,), ) else: self.fail("No error with incompatible wire version") # Incompatible. got_hello( t, address, { "ok": 1, HelloCompat.LEGACY_CMD: True, "setName": "rs", "hosts": ["a"], "minWireVersion": 0, "maxWireVersion": 0, }, ) try: t.select_servers(any_server_selector, _Op.TEST) except ConfigurationError as e: # Error message should say which server failed and why. self.assertEqual( str(e), "Server at a:27017 reports wire version 0, but this version " "of PyMongo requires at least %d (MongoDB %s)." % (common.MIN_SUPPORTED_WIRE_VERSION, common.MIN_SUPPORTED_SERVER_VERSION), ) else: self.fail("No error with incompatible wire version") def test_max_write_batch_size(self): t = create_mock_topology(seeds=["a", "b"], replica_set_name="rs") def write_batch_size(): s = t.select_server(writable_server_selector, _Op.TEST) return s.description.max_write_batch_size got_hello( t, ("a", 27017), { "ok": 1, HelloCompat.LEGACY_CMD: True, "setName": "rs", "hosts": ["a", "b"], "maxWireVersion": 6, "maxWriteBatchSize": 1, }, ) got_hello( t, ("b", 27017), { "ok": 1, HelloCompat.LEGACY_CMD: False, "secondary": True, "setName": "rs", "hosts": ["a", "b"], "maxWireVersion": 6, "maxWriteBatchSize": 2, }, ) # Uses primary's max batch size. self.assertEqual(1, write_batch_size()) # b becomes primary. got_hello( t, ("b", 27017), { "ok": 1, HelloCompat.LEGACY_CMD: True, "setName": "rs", "hosts": ["a", "b"], "maxWireVersion": 6, "maxWriteBatchSize": 2, }, ) self.assertEqual(2, write_batch_size()) def test_topology_repr(self): t = create_mock_topology(replica_set_name="rs") self.addCleanup(t.close) got_hello( t, ("a", 27017), {"ok": 1, HelloCompat.LEGACY_CMD: True, "setName": "rs", "hosts": ["a", "c", "b"]}, ) self.assertEqual( repr(t.description), f", " ", " "]>", ) def test_unexpected_load_balancer(self): # Note: This behavior should not be reachable in practice but we # should handle it gracefully nonetheless. See PYTHON-2791. # Load balancers are included in topology with a single seed. t = create_mock_topology(seeds=["a"]) mock_lb_response = { "ok": 1, "msg": "isdbgrid", "serviceId": ObjectId(), "maxWireVersion": 13, } got_hello(t, ("a", 27017), mock_lb_response) sds = t.description.server_descriptions() self.assertIn(("a", 27017), sds) self.assertEqual(sds[("a", 27017)].server_type_name, "LoadBalancer") self.assertEqual(t.description.topology_type_name, "Single") self.assertTrue(t.description.has_writable_server()) # Load balancers are removed from a topology with multiple seeds. t = create_mock_topology(seeds=["a", "b"]) got_hello(t, ("a", 27017), mock_lb_response) self.assertNotIn(("a", 27017), t.description.server_descriptions()) self.assertEqual(t.description.topology_type_name, "Unknown") def test_filtered_server_selection(self): s1 = Server(ServerDescription(("localhost", 27017)), pool=object(), monitor=object()) # type: ignore[arg-type] s2 = Server(ServerDescription(("localhost2", 27017)), pool=object(), monitor=object()) # type: ignore[arg-type] servers = [s1, s2] result = _filter_servers(servers, deprioritized_servers=[s2]) self.assertEqual(result, [s1]) result = _filter_servers(servers, deprioritized_servers=[s1, s2]) self.assertEqual(result, servers) result = _filter_servers(servers, deprioritized_servers=[]) self.assertEqual(result, servers) result = _filter_servers(servers) self.assertEqual(result, servers) def wait_for_primary(topology): """Wait for a Topology to discover a writable server. If the monitor is currently calling hello, a blocking call to select_server from this thread can trigger a spurious wake of the monitor thread. In applications this is harmless but it would break some tests, so we pass server_selection_timeout=0 and poll instead. """ def get_primary(): try: return topology.select_server(writable_server_selector, _Op.TEST, 0) except ConnectionFailure: return None return wait_until(get_primary, "find primary") class TestTopologyErrors(TopologyTest): # Errors when calling hello. def test_pool_reset(self): # hello succeeds at first, then always raises socket error. hello_count = [0] class TestMonitor(Monitor): def _check_with_socket(self, *args, **kwargs): hello_count[0] += 1 if hello_count[0] == 1: return Hello({"ok": 1, "maxWireVersion": 6}), 0 else: raise AutoReconnect("mock monitor error") t = create_mock_topology(monitor_class=TestMonitor) self.addCleanup(t.close) server = wait_for_primary(t) self.assertEqual(1, hello_count[0]) generation = server.pool.gen.get_overall() # Pool is reset by hello failure. t.request_check_all() self.assertNotEqual(generation, server.pool.gen.get_overall()) def test_hello_retry(self): # hello succeeds at first, then raises socket error, then succeeds. hello_count = [0] class TestMonitor(Monitor): def _check_with_socket(self, *args, **kwargs): hello_count[0] += 1 if hello_count[0] in (1, 3): return Hello({"ok": 1, "maxWireVersion": 6}), 0 else: raise AutoReconnect(f"mock monitor error #{hello_count[0]}") t = create_mock_topology(monitor_class=TestMonitor) self.addCleanup(t.close) server = wait_for_primary(t) self.assertEqual(1, hello_count[0]) self.assertEqual(SERVER_TYPE.Standalone, server.description.server_type) # Second hello call, server is marked Unknown, then the monitor # immediately runs a retry (third hello). t.request_check_all() # The third hello call (the immediate retry) happens sometime soon # after the failed check triggered by request_check_all. Wait until # the server becomes known again. server = t.select_server(writable_server_selector, _Op.TEST, 0.250) self.assertEqual(SERVER_TYPE.Standalone, server.description.server_type) self.assertEqual(3, hello_count[0]) def test_internal_monitor_error(self): exception = AssertionError("internal error") class TestMonitor(Monitor): def _check_with_socket(self, *args, **kwargs): raise exception t = create_mock_topology(monitor_class=TestMonitor) self.addCleanup(t.close) with self.assertRaisesRegex(ConnectionFailure, "internal error"): t.select_server(any_server_selector, _Op.TEST, server_selection_timeout=0.5) class TestServerSelectionErrors(TopologyTest): def assertMessage(self, message, topology, selector=any_server_selector): with self.assertRaises(ConnectionFailure) as context: topology.select_server(selector, _Op.TEST, server_selection_timeout=0) self.assertIn(message, str(context.exception)) def test_no_primary(self): t = create_mock_topology(replica_set_name="rs") got_hello( t, address, { "ok": 1, HelloCompat.LEGACY_CMD: False, "secondary": True, "setName": "rs", "hosts": ["a"], }, ) self.assertMessage( 'No replica set members match selector "Primary()"', t, ReadPreference.PRIMARY ) self.assertMessage("No primary available for writes", t, writable_server_selector) def test_no_secondary(self): t = create_mock_topology(replica_set_name="rs") got_hello( t, address, {"ok": 1, HelloCompat.LEGACY_CMD: True, "setName": "rs", "hosts": ["a"]} ) self.assertMessage( "No replica set members match selector" ' "Secondary(tag_sets=None, max_staleness=-1, hedge=None)"', t, ReadPreference.SECONDARY, ) self.assertMessage( "No replica set members match selector" " \"Secondary(tag_sets=[{'dc': 'ny'}], max_staleness=-1, " 'hedge=None)"', t, Secondary(tag_sets=[{"dc": "ny"}]), ) def test_bad_replica_set_name(self): t = create_mock_topology(replica_set_name="rs") got_hello( t, address, { "ok": 1, HelloCompat.LEGACY_CMD: False, "secondary": True, "setName": "wrong", "hosts": ["a"], }, ) self.assertMessage('No replica set members available for replica set name "rs"', t) def test_multiple_standalones(self): # Standalones are removed from a topology with multiple seeds. t = create_mock_topology(seeds=["a", "b"]) got_hello(t, ("a", 27017), {"ok": 1}) got_hello(t, ("b", 27017), {"ok": 1}) self.assertMessage("No servers available", t) def test_no_mongoses(self): # Standalones are removed from a topology with multiple seeds. t = create_mock_topology(seeds=["a", "b"]) # Discover a mongos and change topology type to Sharded. got_hello(t, ("a", 27017), {"ok": 1, "msg": "isdbgrid"}) # Oops, both servers are standalone now. Remove them. got_hello(t, ("a", 27017), {"ok": 1}) got_hello(t, ("b", 27017), {"ok": 1}) self.assertMessage("No mongoses available", t) if __name__ == "__main__": unittest.main() mongodb-mongo-python-driver-509e9b7/test/test_transactions.py000066400000000000000000000524651462766011000245510ustar00rootroot00000000000000# Copyright 2018-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. """Execute Transactions Spec tests.""" from __future__ import annotations import os import sys from io import BytesIO sys.path[0:0] = [""] from test import client_context, unittest from test.utils import ( OvertCommandListener, SpecTestCreator, rs_client, single_client, wait_until, ) from test.utils_spec_runner import SpecRunner from typing import List from bson import encode from bson.raw_bson import RawBSONDocument from gridfs import GridFS, GridFSBucket from pymongo import WriteConcern, client_session from pymongo.client_session import TransactionOptions from pymongo.command_cursor import CommandCursor from pymongo.cursor import Cursor from pymongo.errors import ( CollectionInvalid, ConfigurationError, ConnectionFailure, InvalidOperation, OperationFailure, ) from pymongo.operations import IndexModel, InsertOne from pymongo.read_concern import ReadConcern from pymongo.read_preferences import ReadPreference _TXN_TESTS_DEBUG = os.environ.get("TRANSACTION_TESTS_DEBUG") # Max number of operations to perform after a transaction to prove unpinning # occurs. Chosen so that there's a low false positive rate. With 2 mongoses, # 50 attempts yields a one in a quadrillion chance of a false positive # (1/(0.5^50)). UNPIN_TEST_MAX_ATTEMPTS = 50 class TransactionsBase(SpecRunner): @classmethod def setUpClass(cls): super().setUpClass() if client_context.supports_transactions(): for address in client_context.mongoses: cls.mongos_clients.append(single_client("{}:{}".format(*address))) @classmethod def tearDownClass(cls): for client in cls.mongos_clients: client.close() super().tearDownClass() def maybe_skip_scenario(self, test): super().maybe_skip_scenario(test) if ( "secondary" in self.id() and not client_context.is_mongos and not client_context.has_secondaries ): raise unittest.SkipTest("No secondaries") class TestTransactions(TransactionsBase): RUN_ON_SERVERLESS = True @client_context.require_transactions def test_transaction_options_validation(self): default_options = TransactionOptions() self.assertIsNone(default_options.read_concern) self.assertIsNone(default_options.write_concern) self.assertIsNone(default_options.read_preference) self.assertIsNone(default_options.max_commit_time_ms) # No error when valid options are provided. TransactionOptions( read_concern=ReadConcern(), write_concern=WriteConcern(), read_preference=ReadPreference.PRIMARY, max_commit_time_ms=10000, ) with self.assertRaisesRegex(TypeError, "read_concern must be "): TransactionOptions(read_concern={}) # type: ignore with self.assertRaisesRegex(TypeError, "write_concern must be "): TransactionOptions(write_concern={}) # type: ignore with self.assertRaisesRegex( ConfigurationError, "transactions do not support unacknowledged write concern" ): TransactionOptions(write_concern=WriteConcern(w=0)) with self.assertRaisesRegex(TypeError, "is not valid for read_preference"): TransactionOptions(read_preference={}) # type: ignore with self.assertRaisesRegex(TypeError, "max_commit_time_ms must be an integer or None"): TransactionOptions(max_commit_time_ms="10000") # type: ignore @client_context.require_transactions def test_transaction_write_concern_override(self): """Test txn overrides Client/Database/Collection write_concern.""" client = rs_client(w=0) self.addCleanup(client.close) db = client.test coll = db.test coll.insert_one({}) with client.start_session() as s: with s.start_transaction(write_concern=WriteConcern(w=1)): self.assertTrue(coll.insert_one({}, session=s).acknowledged) self.assertTrue(coll.insert_many([{}, {}], session=s).acknowledged) self.assertTrue(coll.bulk_write([InsertOne({})], session=s).acknowledged) self.assertTrue(coll.replace_one({}, {}, session=s).acknowledged) self.assertTrue(coll.update_one({}, {"$set": {"a": 1}}, session=s).acknowledged) self.assertTrue(coll.update_many({}, {"$set": {"a": 1}}, session=s).acknowledged) self.assertTrue(coll.delete_one({}, session=s).acknowledged) self.assertTrue(coll.delete_many({}, session=s).acknowledged) coll.find_one_and_delete({}, session=s) coll.find_one_and_replace({}, {}, session=s) coll.find_one_and_update({}, {"$set": {"a": 1}}, session=s) unsupported_txn_writes: list = [ (client.drop_database, [db.name], {}), (db.drop_collection, ["collection"], {}), (coll.drop, [], {}), (coll.rename, ["collection2"], {}), # Drop collection2 between tests of "rename", above. (coll.database.drop_collection, ["collection2"], {}), (coll.create_indexes, [[IndexModel("a")]], {}), (coll.create_index, ["a"], {}), (coll.drop_index, ["a_1"], {}), (coll.drop_indexes, [], {}), (coll.aggregate, [[{"$out": "aggout"}]], {}), ] # Creating a collection in a transaction requires MongoDB 4.4+. if client_context.version < (4, 3, 4): unsupported_txn_writes.extend( [ (db.create_collection, ["collection"], {}), ] ) for op in unsupported_txn_writes: op, args, kwargs = op with client.start_session() as s: kwargs["session"] = s s.start_transaction(write_concern=WriteConcern(w=1)) with self.assertRaises(OperationFailure): op(*args, **kwargs) s.abort_transaction() @client_context.require_transactions @client_context.require_multiple_mongoses def test_unpin_for_next_transaction(self): # Increase localThresholdMS and wait until both nodes are discovered # to avoid false positives. client = rs_client(client_context.mongos_seeds(), localThresholdMS=1000) wait_until(lambda: len(client.nodes) > 1, "discover both mongoses") coll = client.test.test # Create the collection. coll.insert_one({}) self.addCleanup(client.close) with client.start_session() as s: # Session is pinned to Mongos. with s.start_transaction(): coll.insert_one({}, session=s) addresses = set() for _ in range(UNPIN_TEST_MAX_ATTEMPTS): with s.start_transaction(): cursor = coll.find({}, session=s) self.assertTrue(next(cursor)) addresses.add(cursor.address) # Break early if we can. if len(addresses) > 1: break self.assertGreater(len(addresses), 1) @client_context.require_transactions @client_context.require_multiple_mongoses def test_unpin_for_non_transaction_operation(self): # Increase localThresholdMS and wait until both nodes are discovered # to avoid false positives. client = rs_client(client_context.mongos_seeds(), localThresholdMS=1000) wait_until(lambda: len(client.nodes) > 1, "discover both mongoses") coll = client.test.test # Create the collection. coll.insert_one({}) self.addCleanup(client.close) with client.start_session() as s: # Session is pinned to Mongos. with s.start_transaction(): coll.insert_one({}, session=s) addresses = set() for _ in range(UNPIN_TEST_MAX_ATTEMPTS): cursor = coll.find({}, session=s) self.assertTrue(next(cursor)) addresses.add(cursor.address) # Break early if we can. if len(addresses) > 1: break self.assertGreater(len(addresses), 1) @client_context.require_transactions @client_context.require_version_min(4, 3, 4) def test_create_collection(self): client = client_context.client db = client.pymongo_test coll = db.test_create_collection self.addCleanup(coll.drop) # Use with_transaction to avoid StaleConfig errors on sharded clusters. def create_and_insert(session): coll2 = db.create_collection(coll.name, session=session) self.assertEqual(coll, coll2) coll.insert_one({}, session=session) with client.start_session() as s: s.with_transaction(create_and_insert) # Outside a transaction we raise CollectionInvalid on existing colls. with self.assertRaises(CollectionInvalid): db.create_collection(coll.name) # Inside a transaction we raise the OperationFailure from create. with client.start_session() as s: s.start_transaction() with self.assertRaises(OperationFailure) as ctx: db.create_collection(coll.name, session=s) self.assertEqual(ctx.exception.code, 48) # NamespaceExists @client_context.require_transactions def test_gridfs_does_not_support_transactions(self): client = client_context.client db = client.pymongo_test gfs = GridFS(db) bucket = GridFSBucket(db) def gridfs_find(*args, **kwargs): return gfs.find(*args, **kwargs).next() def gridfs_open_upload_stream(*args, **kwargs): bucket.open_upload_stream(*args, **kwargs).write(b"1") gridfs_ops = [ (gfs.put, (b"123",)), (gfs.get, (1,)), (gfs.get_version, ("name",)), (gfs.get_last_version, ("name",)), (gfs.delete, (1,)), (gfs.list, ()), (gfs.find_one, ()), (gridfs_find, ()), (gfs.exists, ()), (gridfs_open_upload_stream, ("name",)), ( bucket.upload_from_stream, ( "name", b"data", ), ), ( bucket.download_to_stream, ( 1, BytesIO(), ), ), ( bucket.download_to_stream_by_name, ( "name", BytesIO(), ), ), (bucket.delete, (1,)), (bucket.find, ()), (bucket.open_download_stream, (1,)), (bucket.open_download_stream_by_name, ("name",)), ( bucket.rename, ( 1, "new-name", ), ), ] with client.start_session() as s, s.start_transaction(): for op, args in gridfs_ops: with self.assertRaisesRegex( InvalidOperation, "GridFS does not support multi-document transactions", ): op(*args, session=s) # type: ignore # Require 4.2+ for large (16MB+) transactions. @client_context.require_version_min(4, 2) @client_context.require_transactions @unittest.skipIf(sys.platform == "win32", "Our Windows machines are too slow to pass this test") def test_transaction_starts_with_batched_write(self): if "PyPy" in sys.version and client_context.tls: self.skipTest( "PYTHON-2937 PyPy is so slow sending large " "messages over TLS that this test fails" ) # Start a transaction with a batch of operations that needs to be # split. listener = OvertCommandListener() client = rs_client(event_listeners=[listener]) coll = client[self.db.name].test coll.delete_many({}) listener.reset() self.addCleanup(client.close) self.addCleanup(coll.drop) large_str = "\0" * (1 * 1024 * 1024) ops: List[InsertOne[RawBSONDocument]] = [ InsertOne(RawBSONDocument(encode({"a": large_str}))) for _ in range(48) ] with client.start_session() as session: with session.start_transaction(): coll.bulk_write(ops, session=session) # type: ignore[arg-type] # Assert commands were constructed properly. self.assertEqual( ["insert", "insert", "commitTransaction"], listener.started_command_names() ) first_cmd = listener.started_events[0].command self.assertTrue(first_cmd["startTransaction"]) lsid = first_cmd["lsid"] txn_number = first_cmd["txnNumber"] for event in listener.started_events[1:]: self.assertNotIn("startTransaction", event.command) self.assertEqual(lsid, event.command["lsid"]) self.assertEqual(txn_number, event.command["txnNumber"]) self.assertEqual(48, coll.count_documents({})) @client_context.require_transactions def test_transaction_direct_connection(self): client = single_client() self.addCleanup(client.close) coll = client.pymongo_test.test # Make sure the collection exists. coll.insert_one({}) self.assertEqual(client.topology_description.topology_type_name, "Single") ops = [ (coll.bulk_write, [[InsertOne[dict]({})]]), (coll.insert_one, [{}]), (coll.insert_many, [[{}, {}]]), (coll.replace_one, [{}, {}]), (coll.update_one, [{}, {"$set": {"a": 1}}]), (coll.update_many, [{}, {"$set": {"a": 1}}]), (coll.delete_one, [{}]), (coll.delete_many, [{}]), (coll.find_one_and_replace, [{}, {}]), (coll.find_one_and_update, [{}, {"$set": {"a": 1}}]), (coll.find_one_and_delete, [{}, {}]), (coll.find_one, [{}]), (coll.count_documents, [{}]), (coll.distinct, ["foo"]), (coll.aggregate, [[]]), (coll.find, [{}]), (coll.aggregate_raw_batches, [[]]), (coll.find_raw_batches, [{}]), (coll.database.command, ["find", coll.name]), ] for f, args in ops: with client.start_session() as s, s.start_transaction(): res = f(*args, session=s) # type:ignore[operator] if isinstance(res, (CommandCursor, Cursor)): list(res) class PatchSessionTimeout: """Patches the client_session's with_transaction timeout for testing.""" def __init__(self, mock_timeout): self.real_timeout = client_session._WITH_TRANSACTION_RETRY_TIME_LIMIT self.mock_timeout = mock_timeout def __enter__(self): client_session._WITH_TRANSACTION_RETRY_TIME_LIMIT = self.mock_timeout return self def __exit__(self, exc_type, exc_val, exc_tb): client_session._WITH_TRANSACTION_RETRY_TIME_LIMIT = self.real_timeout class TestTransactionsConvenientAPI(TransactionsBase): @client_context.require_transactions def test_callback_raises_custom_error(self): class _MyException(Exception): pass def raise_error(_): raise _MyException with self.client.start_session() as s: with self.assertRaises(_MyException): s.with_transaction(raise_error) @client_context.require_transactions def test_callback_returns_value(self): def callback(_): return "Foo" with self.client.start_session() as s: self.assertEqual(s.with_transaction(callback), "Foo") self.db.test.insert_one({}) def callback2(session): self.db.test.insert_one({}, session=session) return "Foo" with self.client.start_session() as s: self.assertEqual(s.with_transaction(callback2), "Foo") @client_context.require_transactions def test_callback_not_retried_after_timeout(self): listener = OvertCommandListener() client = rs_client(event_listeners=[listener]) self.addCleanup(client.close) coll = client[self.db.name].test def callback(session): coll.insert_one({}, session=session) err: dict = { "ok": 0, "errmsg": "Transaction 7819 has been aborted.", "code": 251, "codeName": "NoSuchTransaction", "errorLabels": ["TransientTransactionError"], } raise OperationFailure(err["errmsg"], err["code"], err) # Create the collection. coll.insert_one({}) listener.reset() with client.start_session() as s: with PatchSessionTimeout(0): with self.assertRaises(OperationFailure): s.with_transaction(callback) self.assertEqual(listener.started_command_names(), ["insert", "abortTransaction"]) @client_context.require_test_commands @client_context.require_transactions def test_callback_not_retried_after_commit_timeout(self): listener = OvertCommandListener() client = rs_client(event_listeners=[listener]) self.addCleanup(client.close) coll = client[self.db.name].test def callback(session): coll.insert_one({}, session=session) # Create the collection. coll.insert_one({}) self.set_fail_point( { "configureFailPoint": "failCommand", "mode": {"times": 1}, "data": { "failCommands": ["commitTransaction"], "errorCode": 251, # NoSuchTransaction }, } ) self.addCleanup(self.set_fail_point, {"configureFailPoint": "failCommand", "mode": "off"}) listener.reset() with client.start_session() as s: with PatchSessionTimeout(0): with self.assertRaises(OperationFailure): s.with_transaction(callback) self.assertEqual(listener.started_command_names(), ["insert", "commitTransaction"]) @client_context.require_test_commands @client_context.require_transactions def test_commit_not_retried_after_timeout(self): listener = OvertCommandListener() client = rs_client(event_listeners=[listener]) self.addCleanup(client.close) coll = client[self.db.name].test def callback(session): coll.insert_one({}, session=session) # Create the collection. coll.insert_one({}) self.set_fail_point( { "configureFailPoint": "failCommand", "mode": {"times": 2}, "data": {"failCommands": ["commitTransaction"], "closeConnection": True}, } ) self.addCleanup(self.set_fail_point, {"configureFailPoint": "failCommand", "mode": "off"}) listener.reset() with client.start_session() as s: with PatchSessionTimeout(0): with self.assertRaises(ConnectionFailure): s.with_transaction(callback) # One insert for the callback and two commits (includes the automatic # retry). self.assertEqual( listener.started_command_names(), ["insert", "commitTransaction", "commitTransaction"] ) # Tested here because this supports Motor's convenient transactions API. @client_context.require_transactions def test_in_transaction_property(self): client = client_context.client coll = client.test.testcollection coll.insert_one({}) self.addCleanup(coll.drop) with client.start_session() as s: self.assertFalse(s.in_transaction) s.start_transaction() self.assertTrue(s.in_transaction) coll.insert_one({}, session=s) self.assertTrue(s.in_transaction) s.commit_transaction() self.assertFalse(s.in_transaction) with client.start_session() as s: s.start_transaction() # commit empty transaction s.commit_transaction() self.assertFalse(s.in_transaction) with client.start_session() as s: s.start_transaction() s.abort_transaction() self.assertFalse(s.in_transaction) # Using a callback def callback(session): self.assertTrue(session.in_transaction) with client.start_session() as s: self.assertFalse(s.in_transaction) s.with_transaction(callback) self.assertFalse(s.in_transaction) if __name__ == "__main__": unittest.main() mongodb-mongo-python-driver-509e9b7/test/test_transactions_unified.py000066400000000000000000000026341462766011000262450ustar00rootroot00000000000000# Copyright 2021-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. """Test the Transactions unified spec tests.""" from __future__ import annotations import os import sys sys.path[0:0] = [""] from test import client_context, unittest from test.unified_format import generate_test_classes @client_context.require_no_mmap def setUpModule(): pass # Location of JSON test specifications. TEST_PATH = os.path.join(os.path.dirname(os.path.realpath(__file__)), "transactions", "unified") # Generate unified tests. globals().update(generate_test_classes(TEST_PATH, module=__name__)) # Location of JSON test specifications for transactions-convenient-api. TEST_PATH = os.path.join( os.path.dirname(os.path.realpath(__file__)), "transactions-convenient-api", "unified" ) # Generate unified tests. globals().update(generate_test_classes(TEST_PATH, module=__name__)) if __name__ == "__main__": unittest.main() mongodb-mongo-python-driver-509e9b7/test/test_typing.py000066400000000000000000000514571462766011000233530ustar00rootroot00000000000000# Copyright 2020-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. """Test that each file in mypy_fails/ actually fails mypy, and test some sample client code that uses PyMongo typings. """ from __future__ import annotations import os import sys import tempfile import unittest from typing import ( TYPE_CHECKING, Any, Callable, Dict, Iterable, Iterator, List, TypeVar, Union, cast, ) try: from typing_extensions import NotRequired, TypedDict from bson import ObjectId class Movie(TypedDict): name: str year: int class MovieWithId(TypedDict): _id: ObjectId name: str year: int class ImplicitMovie(TypedDict): _id: NotRequired[ObjectId] # pyright: ignore[reportGeneralTypeIssues] name: str year: int except ImportError: Movie = dict # type:ignore[misc,assignment] ImplicitMovie = dict # type: ignore[assignment,misc] MovieWithId = dict # type: ignore[assignment,misc] TypedDict = None NotRequired = None # type: ignore[assignment] try: from mypy import api except ImportError: api = None # type: ignore[assignment] sys.path[0:0] = [""] from test import IntegrationTest, client_context from test.utils import rs_or_single_client from bson import CodecOptions, decode, decode_all, decode_file_iter, decode_iter, encode from bson.raw_bson import RawBSONDocument from bson.son import SON from pymongo import ASCENDING, MongoClient from pymongo.collection import Collection from pymongo.operations import DeleteOne, InsertOne, ReplaceOne from pymongo.read_preferences import ReadPreference TEST_PATH = os.path.join(os.path.dirname(os.path.realpath(__file__)), "mypy_fails") def get_tests() -> Iterable[str]: for dirpath, _, filenames in os.walk(TEST_PATH): for filename in filenames: yield os.path.join(dirpath, filename) FuncT = TypeVar("FuncT", bound=Callable[..., None]) def only_type_check(func: FuncT) -> FuncT: def inner(*args, **kwargs): if not TYPE_CHECKING: raise unittest.SkipTest("Used for Type Checking Only") func(*args, **kwargs) return cast(FuncT, inner) class TestMypyFails(unittest.TestCase): def ensure_mypy_fails(self, filename: str) -> None: if api is None: raise unittest.SkipTest("Mypy is not installed") stdout, stderr, exit_status = api.run([filename]) self.assertTrue(exit_status, msg=stdout) def test_mypy_failures(self) -> None: for filename in get_tests(): if filename == "typeddict_client.py" and TypedDict is None: continue with self.subTest(filename=filename): self.ensure_mypy_fails(filename) class TestPymongo(IntegrationTest): coll: Collection @classmethod def setUpClass(cls): super().setUpClass() cls.coll = cls.client.test.test def test_insert_find(self) -> None: doc = {"my": "doc"} coll2 = self.client.test.test2 result = self.coll.insert_one(doc) self.assertEqual(result.inserted_id, doc["_id"]) retrieved = self.coll.find_one({"_id": doc["_id"]}) if retrieved: # Documents returned from find are mutable. retrieved["new_field"] = 1 result2 = coll2.insert_one(retrieved) self.assertEqual(result2.inserted_id, result.inserted_id) def test_cursor_iterable(self) -> None: def to_list(iterable: Iterable[Dict[str, Any]]) -> List[Dict[str, Any]]: return list(iterable) self.coll.insert_one({}) cursor = self.coll.find() docs = to_list(cursor) self.assertTrue(docs) @only_type_check def test_bulk_write(self) -> None: self.coll.insert_one({}) coll: Collection[Movie] = self.coll requests: List[InsertOne[Movie]] = [InsertOne(Movie(name="American Graffiti", year=1973))] self.assertTrue(coll.bulk_write(requests).acknowledged) new_requests: List[Union[InsertOne[Movie], ReplaceOne[Movie]]] = [] input_list: List[Union[InsertOne[Movie], ReplaceOne[Movie]]] = [ InsertOne(Movie(name="American Graffiti", year=1973)), ReplaceOne({}, Movie(name="American Graffiti", year=1973)), ] for i in input_list: new_requests.append(i) self.assertTrue(coll.bulk_write(new_requests).acknowledged) # Because ReplaceOne is not generic, type checking is not enforced for ReplaceOne in the first example. @only_type_check def test_bulk_write_heterogeneous(self): coll: Collection[Movie] = self.coll requests: List[Union[InsertOne[Movie], ReplaceOne, DeleteOne]] = [ InsertOne(Movie(name="American Graffiti", year=1973)), ReplaceOne({}, {"name": "American Graffiti", "year": "WRONG_TYPE"}), DeleteOne({}), ] self.assertTrue(coll.bulk_write(requests).acknowledged) requests_two: List[Union[InsertOne[Movie], ReplaceOne[Movie], DeleteOne]] = [ InsertOne(Movie(name="American Graffiti", year=1973)), ReplaceOne( {}, {"name": "American Graffiti", "year": "WRONG_TYPE"}, # type:ignore[typeddict-item] ), DeleteOne({}), ] self.assertTrue(coll.bulk_write(requests_two).acknowledged) def test_command(self) -> None: result: Dict = self.client.admin.command("ping") result.items() def test_list_collections(self) -> None: cursor = self.client.test.list_collections() value = cursor.next() value.items() def test_list_databases(self) -> None: cursor = self.client.list_databases() value = cursor.next() value.items() def test_default_document_type(self) -> None: client = rs_or_single_client() self.addCleanup(client.close) coll = client.test.test doc = {"my": "doc"} coll.insert_one(doc) retrieved = coll.find_one({"_id": doc["_id"]}) assert retrieved is not None retrieved["a"] = 1 def test_aggregate_pipeline(self) -> None: coll3 = self.client.test.test3 coll3.insert_many( [ {"x": 1, "tags": ["dog", "cat"]}, {"x": 2, "tags": ["cat"]}, {"x": 2, "tags": ["mouse", "cat", "dog"]}, {"x": 3, "tags": []}, ] ) class mydict(Dict[str, Any]): pass result = coll3.aggregate( [ mydict({"$unwind": "$tags"}), {"$group": {"_id": "$tags", "count": {"$sum": 1}}}, {"$sort": SON([("count", -1), ("_id", -1)])}, ] ) self.assertTrue(len(list(result))) def test_with_transaction(self) -> None: def execute_transaction(session): pass with self.client.start_session() as session: return session.with_transaction( execute_transaction, read_preference=ReadPreference.PRIMARY ) class TestDecode(unittest.TestCase): def test_bson_decode(self) -> None: doc = {"_id": 1} bsonbytes = encode(doc) rt_document: Dict[str, Any] = decode(bsonbytes) assert rt_document["_id"] == 1 rt_document["foo"] = "bar" class MyDict(Dict[str, Any]): def foo(self): return "bar" codec_options = CodecOptions(document_class=MyDict) bsonbytes2 = encode(doc, codec_options=codec_options) rt_document2 = decode(bsonbytes2, codec_options=codec_options) assert rt_document2.foo() == "bar" codec_options2 = CodecOptions(document_class=RawBSONDocument) encode(doc, codec_options=codec_options2) rt_document3 = decode(bsonbytes2, codec_options=codec_options2) assert rt_document3.raw def test_bson_decode_no_codec_option(self) -> None: doc = decode_all(encode({"a": 1})) assert doc doc[0]["a"] = 2 def test_bson_decode_all(self) -> None: doc = {"_id": 1} bsonbytes = encode(doc) bsonbytes += encode(doc) rt_documents: List[Dict[str, Any]] = decode_all(bsonbytes) assert rt_documents[0]["_id"] == 1 rt_documents[0]["foo"] = "bar" class MyDict(Dict[str, Any]): def foo(self): return "bar" codec_options2 = CodecOptions(MyDict) bsonbytes2 = encode(doc, codec_options=codec_options2) bsonbytes2 += encode(doc, codec_options=codec_options2) rt_documents2 = decode_all(bsonbytes2, codec_options2) assert rt_documents2[0].foo() == "bar" codec_options3 = CodecOptions(RawBSONDocument) bsonbytes3 = encode(doc, codec_options=codec_options3) bsonbytes3 += encode(doc, codec_options=codec_options3) rt_documents3 = decode_all(bsonbytes3, codec_options3) assert rt_documents3[0].raw def test_bson_decode_all_no_codec_option(self) -> None: docs = decode_all(b"") docs.append({"new": 1}) docs = decode_all(encode({"a": 1})) assert docs docs[0]["a"] = 2 docs.append({"new": 1}) def test_bson_decode_iter(self) -> None: doc = {"_id": 1} bsonbytes = encode(doc) bsonbytes += encode(doc) rt_documents: Iterator[Dict[str, Any]] = decode_iter(bsonbytes) assert next(rt_documents)["_id"] == 1 next(rt_documents)["foo"] = "bar" class MyDict(Dict[str, Any]): def foo(self): return "bar" codec_options2 = CodecOptions(MyDict) bsonbytes2 = encode(doc, codec_options=codec_options2) bsonbytes2 += encode(doc, codec_options=codec_options2) rt_documents2 = decode_iter(bsonbytes2, codec_options2) assert next(rt_documents2).foo() == "bar" codec_options3 = CodecOptions(RawBSONDocument) bsonbytes3 = encode(doc, codec_options=codec_options3) bsonbytes3 += encode(doc, codec_options=codec_options3) rt_documents3 = decode_iter(bsonbytes3, codec_options3) assert next(rt_documents3).raw def test_bson_decode_iter_no_codec_option(self) -> None: doc = next(decode_iter(encode({"a": 1}))) assert doc doc["a"] = 2 def make_tempfile(self, content: bytes) -> Any: fileobj = tempfile.TemporaryFile() fileobj.write(content) fileobj.seek(0) self.addCleanup(fileobj.close) return fileobj def test_bson_decode_file_iter(self) -> None: doc = {"_id": 1} bsonbytes = encode(doc) bsonbytes += encode(doc) fileobj = self.make_tempfile(bsonbytes) rt_documents: Iterator[Dict[str, Any]] = decode_file_iter(fileobj) assert next(rt_documents)["_id"] == 1 next(rt_documents)["foo"] = "bar" class MyDict(Dict[str, Any]): def foo(self): return "bar" codec_options2 = CodecOptions(MyDict) bsonbytes2 = encode(doc, codec_options=codec_options2) bsonbytes2 += encode(doc, codec_options=codec_options2) fileobj2 = self.make_tempfile(bsonbytes2) rt_documents2 = decode_file_iter(fileobj2, codec_options2) assert next(rt_documents2).foo() == "bar" codec_options3 = CodecOptions(RawBSONDocument) bsonbytes3 = encode(doc, codec_options=codec_options3) bsonbytes3 += encode(doc, codec_options=codec_options3) fileobj3 = self.make_tempfile(bsonbytes3) rt_documents3 = decode_file_iter(fileobj3, codec_options3) assert next(rt_documents3).raw def test_bson_decode_file_iter_none_codec_option(self) -> None: fileobj = self.make_tempfile(encode({"new": 1})) doc = next(decode_file_iter(fileobj)) assert doc doc["a"] = 2 class TestDocumentType(unittest.TestCase): @only_type_check def test_default(self) -> None: client: MongoClient = MongoClient() coll = client.test.test retrieved = coll.find_one({"_id": "foo"}) assert retrieved is not None retrieved["a"] = 1 @only_type_check def test_explicit_document_type(self) -> None: client: MongoClient[Dict[str, Any]] = MongoClient() coll = client.test.test retrieved = coll.find_one({"_id": "foo"}) assert retrieved is not None retrieved["a"] = 1 @only_type_check def test_typeddict_document_type(self) -> None: client: MongoClient[Movie] = MongoClient() coll = client.test.test retrieved = coll.find_one({"_id": "foo"}) assert retrieved is not None assert retrieved["year"] == 1 assert retrieved["name"] == "a" @only_type_check def test_typeddict_document_type_insertion(self) -> None: client: MongoClient[Movie] = MongoClient() coll = client.test.test mov = {"name": "THX-1138", "year": 1971} movie = Movie(name="THX-1138", year=1971) coll.insert_one(mov) # type: ignore[arg-type] coll.insert_one({"name": "THX-1138", "year": 1971}) # This will work because it is in-line. coll.insert_one(movie) coll.insert_many([mov]) # type: ignore[list-item] coll.insert_many([movie]) bad_mov = {"name": "THX-1138", "year": "WRONG TYPE"} bad_movie = Movie(name="THX-1138", year="WRONG TYPE") # type: ignore[typeddict-item] coll.insert_one(bad_mov) # type:ignore[arg-type] coll.insert_one({"name": "THX-1138", "year": "WRONG TYPE"}) # type: ignore[typeddict-item] coll.insert_one(bad_movie) coll.insert_many([bad_mov]) # type: ignore[list-item] coll.insert_many( [{"name": "THX-1138", "year": "WRONG TYPE"}] # type: ignore[typeddict-item] ) coll.insert_many([bad_movie]) @only_type_check def test_bulk_write_document_type_insertion(self): client: MongoClient[MovieWithId] = MongoClient() coll: Collection[MovieWithId] = client.test.test coll.bulk_write( [InsertOne(Movie({"name": "THX-1138", "year": 1971}))] # type:ignore[arg-type] ) mov_dict = {"_id": ObjectId(), "name": "THX-1138", "year": 1971} coll.bulk_write( [InsertOne(mov_dict)] # type:ignore[arg-type] ) coll.bulk_write( [ InsertOne({"_id": ObjectId(), "name": "THX-1138", "year": 1971}) ] # No error because it is in-line. ) @only_type_check def test_bulk_write_document_type_replacement(self): client: MongoClient[MovieWithId] = MongoClient() coll: Collection[MovieWithId] = client.test.test coll.bulk_write( [ReplaceOne({}, Movie({"name": "THX-1138", "year": 1971}))] # type:ignore[arg-type] ) mov_dict = {"_id": ObjectId(), "name": "THX-1138", "year": 1971} coll.bulk_write( [ReplaceOne({}, mov_dict)] # type:ignore[arg-type] ) coll.bulk_write( [ ReplaceOne({}, {"_id": ObjectId(), "name": "THX-1138", "year": 1971}) ] # No error because it is in-line. ) @only_type_check def test_typeddict_explicit_document_type(self) -> None: out = MovieWithId(_id=ObjectId(), name="THX-1138", year=1971) assert out is not None # This should fail because the output is a Movie. assert out["foo"] # type:ignore[typeddict-item] assert out["_id"] # This should work the same as the test above, but this time using NotRequired to allow # automatic insertion of the _id field by insert_one. @only_type_check def test_typeddict_not_required_document_type(self) -> None: out = ImplicitMovie(name="THX-1138", year=1971) assert out is not None # This should fail because the output is a Movie. assert out["foo"] # type:ignore[typeddict-item] # pyright gives reportTypedDictNotRequiredAccess for the following: assert out["_id"] # type:ignore @only_type_check def test_typeddict_empty_document_type(self) -> None: out = Movie(name="THX-1138", year=1971) assert out is not None # This should fail because the output is a Movie. assert out["foo"] # type:ignore[typeddict-item] # This should fail because _id is not included in our TypedDict definition. assert out["_id"] # type:ignore[typeddict-item] @client_context.require_connection def test_typeddict_find_notrequired(self): if NotRequired is None or ImplicitMovie is None: raise unittest.SkipTest("Python 3.11+ is required to use NotRequired.") client: MongoClient[ImplicitMovie] = rs_or_single_client() coll = client.test.test coll.insert_one(ImplicitMovie(name="THX-1138", year=1971)) out = coll.find_one({}) assert out is not None # pyright gives reportTypedDictNotRequiredAccess for the following: assert out["_id"] # type:ignore @only_type_check def test_raw_bson_document_type(self) -> None: client = MongoClient(document_class=RawBSONDocument) coll = client.test.test retrieved = coll.find_one({"_id": "foo"}) assert retrieved is not None assert len(retrieved.raw) > 0 @only_type_check def test_son_document_type(self) -> None: client = MongoClient(document_class=SON[str, Any]) coll = client.test.test retrieved = coll.find_one({"_id": "foo"}) assert retrieved is not None retrieved["a"] = 1 def test_son_document_type_runtime(self) -> None: MongoClient(document_class=SON[str, Any], connect=False) @only_type_check def test_create_index(self) -> None: client: MongoClient[Dict[str, str]] = MongoClient("test") db = client.test with client.start_session() as session: index = db.test.create_index([("user_id", ASCENDING)], unique=True, session=session) assert isinstance(index, str) class TestCommandDocumentType(unittest.TestCase): @only_type_check def test_default(self) -> None: client: MongoClient = MongoClient() result: Dict = client.admin.command("ping") result["a"] = 1 @only_type_check def test_explicit_document_type(self) -> None: client: MongoClient = MongoClient() codec_options: CodecOptions[Dict[str, Any]] = CodecOptions() result = client.admin.command("ping", codec_options=codec_options) result["a"] = 1 @only_type_check def test_typeddict_document_type(self) -> None: client: MongoClient = MongoClient() codec_options: CodecOptions[Movie] = CodecOptions() result = client.admin.command("ping", codec_options=codec_options) assert result["year"] == 1 assert result["name"] == "a" @only_type_check def test_raw_bson_document_type(self) -> None: client: MongoClient = MongoClient() codec_options = CodecOptions(RawBSONDocument) result = client.admin.command("ping", codec_options=codec_options) assert len(result.raw) > 0 @only_type_check def test_son_document_type(self) -> None: client = MongoClient(document_class=SON[str, Any]) codec_options = CodecOptions(SON[str, Any]) result = client.admin.command("ping", codec_options=codec_options) result["a"] = 1 class TestCodecOptionsDocumentType(unittest.TestCase): def test_default(self) -> None: options: CodecOptions = CodecOptions() obj = options.document_class() obj["a"] = 1 def test_explicit_document_type(self) -> None: options: CodecOptions[Dict[str, Any]] = CodecOptions() obj = options.document_class() obj["a"] = 1 def test_typeddict_document_type(self) -> None: options: CodecOptions[Movie] = CodecOptions() # Suppress: Cannot instantiate type "Type[Movie]". obj = options.document_class(name="a", year=1) # type: ignore[misc] assert obj["year"] == 1 assert obj["name"] == "a" def test_raw_bson_document_type(self) -> None: options = CodecOptions(RawBSONDocument) doc_bson = b"\x10\x00\x00\x00\x11a\x00\xff\xff\xff\xff\xff\xff\xff\xff\x00" obj = options.document_class(doc_bson) assert len(obj.raw) > 0 def test_son_document_type(self) -> None: options = CodecOptions(SON[str, Any]) obj = options.document_class() obj["a"] = 1 if __name__ == "__main__": unittest.main() mongodb-mongo-python-driver-509e9b7/test/test_typing_strict.py000066400000000000000000000026441462766011000247350ustar00rootroot00000000000000# Copyright 2023-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. """Test typings in strict mode.""" from __future__ import annotations import unittest from typing import TYPE_CHECKING, Any, Dict import pymongo from pymongo.collection import Collection from pymongo.database import Database def test_generic_arguments() -> None: """Ensure known usages of generic arguments pass strict typing""" if not TYPE_CHECKING: raise unittest.SkipTest("Used for Type Checking Only") mongo_client: pymongo.MongoClient[Dict[str, Any]] = pymongo.MongoClient() mongo_client.drop_database("foo") mongo_client.get_default_database() db = mongo_client.get_database("test_db") db = Database(mongo_client, "test_db") db.with_options() db.validate_collection("py_test") col = db.get_collection("py_test") col.insert_one({"abc": 123}) col = Collection(db, "py_test") col.with_options() mongodb-mongo-python-driver-509e9b7/test/test_unified_format.py000066400000000000000000000056411462766011000250260ustar00rootroot00000000000000# Copyright 2020-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. from __future__ import annotations import os import sys from typing import Any sys.path[0:0] = [""] from test import unittest from test.unified_format import MatchEvaluatorUtil, generate_test_classes from bson import ObjectId _TEST_PATH = os.path.join(os.path.dirname(os.path.realpath(__file__)), "unified-test-format") globals().update( generate_test_classes( os.path.join(_TEST_PATH, "valid-pass"), module=__name__, class_name_prefix="UnifiedTestFormat", expected_failures=[ "Client side error in command starting transaction", # PYTHON-1894 ], RUN_ON_SERVERLESS=False, ) ) globals().update( generate_test_classes( os.path.join(_TEST_PATH, "valid-fail"), module=__name__, class_name_prefix="UnifiedTestFormat", bypass_test_generation_errors=True, expected_failures=[ ".*", # All tests expected to fail ], RUN_ON_SERVERLESS=False, ) ) class TestMatchEvaluatorUtil(unittest.TestCase): def setUp(self): self.match_evaluator = MatchEvaluatorUtil(self) def test_unsetOrMatches(self): spec: dict[str, Any] = {"$$unsetOrMatches": {"y": {"$$unsetOrMatches": 2}}} for actual in [{}, {"y": 2}, None]: self.match_evaluator.match_result(spec, actual) spec = {"x": {"$$unsetOrMatches": {"y": {"$$unsetOrMatches": 2}}}} for actual in [{}, {"x": {}}, {"x": {"y": 2}}]: self.match_evaluator.match_result(spec, actual) spec = {"y": {"$$unsetOrMatches": {"$$exists": True}}} self.match_evaluator.match_result(spec, {}) self.match_evaluator.match_result(spec, {"y": 2}) self.match_evaluator.match_result(spec, {"x": 1}) self.match_evaluator.match_result(spec, {"y": {}}) def test_type(self): self.match_evaluator.match_result( { "operationType": "insert", "ns": {"db": "change-stream-tests", "coll": "test"}, "fullDocument": {"_id": {"$$type": "objectId"}, "x": 1}, }, { "operationType": "insert", "fullDocument": {"_id": ObjectId("5fc93511ac93941052098f0c"), "x": 1}, "ns": {"db": "change-stream-tests", "coll": "test"}, }, ) if __name__ == "__main__": unittest.main() mongodb-mongo-python-driver-509e9b7/test/test_uri_parser.py000066400000000000000000000546651462766011000242200ustar00rootroot00000000000000# Copyright 2011-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. """Test the pymongo uri_parser module.""" from __future__ import annotations import copy import sys import warnings from typing import Any from urllib.parse import quote_plus sys.path[0:0] = [""] from test import unittest from bson.binary import JAVA_LEGACY from pymongo import ReadPreference from pymongo.errors import ConfigurationError, InvalidURI from pymongo.uri_parser import ( parse_uri, parse_userinfo, split_hosts, split_options, ) class TestURI(unittest.TestCase): def test_validate_userinfo(self): self.assertRaises(InvalidURI, parse_userinfo, "foo@") self.assertRaises(InvalidURI, parse_userinfo, ":password") self.assertRaises(InvalidURI, parse_userinfo, "fo::o:p@ssword") self.assertRaises(InvalidURI, parse_userinfo, ":") self.assertTrue(parse_userinfo("user:password")) self.assertEqual(("us:r", "p@ssword"), parse_userinfo("us%3Ar:p%40ssword")) self.assertEqual(("us er", "p ssword"), parse_userinfo("us+er:p+ssword")) self.assertEqual(("us er", "p ssword"), parse_userinfo("us%20er:p%20ssword")) self.assertEqual(("us+er", "p+ssword"), parse_userinfo("us%2Ber:p%2Bssword")) self.assertEqual(("dev1@FOO.COM", ""), parse_userinfo("dev1%40FOO.COM")) self.assertEqual(("dev1@FOO.COM", ""), parse_userinfo("dev1%40FOO.COM:")) def test_split_hosts(self): self.assertRaises(ConfigurationError, split_hosts, "localhost:27017,") self.assertRaises(ConfigurationError, split_hosts, ",localhost:27017") self.assertRaises(ConfigurationError, split_hosts, "localhost:27017,,localhost:27018") self.assertEqual( [("localhost", 27017), ("example.com", 27017)], split_hosts("localhost,example.com") ) self.assertEqual( [("localhost", 27018), ("example.com", 27019)], split_hosts("localhost:27018,example.com:27019"), ) self.assertEqual( [("/tmp/mongodb-27017.sock", None)], split_hosts("/tmp/mongodb-27017.sock") ) self.assertEqual( [("/tmp/mongodb-27017.sock", None), ("example.com", 27017)], split_hosts("/tmp/mongodb-27017.sock,example.com:27017"), ) self.assertEqual( [("example.com", 27017), ("/tmp/mongodb-27017.sock", None)], split_hosts("example.com:27017,/tmp/mongodb-27017.sock"), ) self.assertRaises(ValueError, split_hosts, "::1", 27017) self.assertRaises(ValueError, split_hosts, "[::1:27017") self.assertRaises(ValueError, split_hosts, "::1") self.assertRaises(ValueError, split_hosts, "::1]:27017") self.assertEqual([("::1", 27017)], split_hosts("[::1]:27017")) self.assertEqual([("::1", 27017)], split_hosts("[::1]")) def test_split_options(self): self.assertRaises(ConfigurationError, split_options, "foo") self.assertRaises(ConfigurationError, split_options, "foo=bar;foo") self.assertTrue(split_options("ssl=true")) self.assertTrue(split_options("connect=true")) self.assertTrue(split_options("tlsAllowInvalidHostnames=false")) # Test Invalid URI options that should throw warnings. with warnings.catch_warnings(): warnings.filterwarnings("error") self.assertRaises(Warning, split_options, "foo=bar", warn=True) self.assertRaises(Warning, split_options, "socketTimeoutMS=foo", warn=True) self.assertRaises(Warning, split_options, "socketTimeoutMS=0.0", warn=True) self.assertRaises(Warning, split_options, "connectTimeoutMS=foo", warn=True) self.assertRaises(Warning, split_options, "connectTimeoutMS=0.0", warn=True) self.assertRaises(Warning, split_options, "connectTimeoutMS=1e100000", warn=True) self.assertRaises(Warning, split_options, "connectTimeoutMS=-1e100000", warn=True) self.assertRaises(Warning, split_options, "ssl=foo", warn=True) self.assertRaises(Warning, split_options, "connect=foo", warn=True) self.assertRaises(Warning, split_options, "tlsAllowInvalidHostnames=foo", warn=True) self.assertRaises(Warning, split_options, "connectTimeoutMS=inf", warn=True) self.assertRaises(Warning, split_options, "connectTimeoutMS=-inf", warn=True) self.assertRaises(Warning, split_options, "wtimeoutms=foo", warn=True) self.assertRaises(Warning, split_options, "wtimeoutms=5.5", warn=True) self.assertRaises(Warning, split_options, "fsync=foo", warn=True) self.assertRaises(Warning, split_options, "fsync=5.5", warn=True) self.assertRaises(Warning, split_options, "authMechanism=foo", warn=True) # Test invalid options with warn=False. self.assertRaises(ConfigurationError, split_options, "foo=bar") self.assertRaises(ValueError, split_options, "socketTimeoutMS=foo") self.assertRaises(ValueError, split_options, "socketTimeoutMS=0.0") self.assertRaises(ValueError, split_options, "connectTimeoutMS=foo") self.assertRaises(ValueError, split_options, "connectTimeoutMS=0.0") self.assertRaises(ValueError, split_options, "connectTimeoutMS=1e100000") self.assertRaises(ValueError, split_options, "connectTimeoutMS=-1e100000") self.assertRaises(ValueError, split_options, "ssl=foo") self.assertRaises(ValueError, split_options, "connect=foo") self.assertRaises(ValueError, split_options, "tlsAllowInvalidHostnames=foo") self.assertRaises(ValueError, split_options, "connectTimeoutMS=inf") self.assertRaises(ValueError, split_options, "connectTimeoutMS=-inf") self.assertRaises(ValueError, split_options, "wtimeoutms=foo") self.assertRaises(ValueError, split_options, "wtimeoutms=5.5") self.assertRaises(ValueError, split_options, "fsync=foo") self.assertRaises(ValueError, split_options, "fsync=5.5") self.assertRaises(ValueError, split_options, "authMechanism=foo") # Test splitting options works when valid. self.assertTrue(split_options("socketTimeoutMS=300")) self.assertTrue(split_options("connectTimeoutMS=300")) self.assertEqual({"sockettimeoutms": 0.3}, split_options("socketTimeoutMS=300")) self.assertEqual({"sockettimeoutms": 0.0001}, split_options("socketTimeoutMS=0.1")) self.assertEqual({"connecttimeoutms": 0.3}, split_options("connectTimeoutMS=300")) self.assertEqual({"connecttimeoutms": 0.0001}, split_options("connectTimeoutMS=0.1")) self.assertTrue(split_options("connectTimeoutMS=300")) self.assertTrue(isinstance(split_options("w=5")["w"], int)) self.assertTrue(isinstance(split_options("w=5.5")["w"], str)) self.assertTrue(split_options("w=foo")) self.assertTrue(split_options("w=majority")) self.assertTrue(split_options("wtimeoutms=500")) self.assertEqual({"fsync": True}, split_options("fsync=true")) self.assertEqual({"fsync": False}, split_options("fsync=false")) self.assertEqual({"authmechanism": "GSSAPI"}, split_options("authMechanism=GSSAPI")) self.assertEqual({"authmechanism": "MONGODB-CR"}, split_options("authMechanism=MONGODB-CR")) self.assertEqual( {"authmechanism": "SCRAM-SHA-1"}, split_options("authMechanism=SCRAM-SHA-1") ) self.assertEqual({"authsource": "foobar"}, split_options("authSource=foobar")) self.assertEqual({"maxpoolsize": 50}, split_options("maxpoolsize=50")) # Test suggestions given when invalid kwarg passed expected = r"Unknown option: auth. Did you mean one of \(authsource, authmechanism, timeoutms\) or maybe a camelCase version of one\? Refer to docstring." with self.assertRaisesRegex(ConfigurationError, expected): split_options("auth=GSSAPI") def test_parse_uri(self): self.assertRaises(InvalidURI, parse_uri, "http://foobar.com") self.assertRaises(InvalidURI, parse_uri, "http://foo@foobar.com") self.assertRaises(ValueError, parse_uri, "mongodb://::1", 27017) # Extra whitespace should be visible in error message. with self.assertRaisesRegex(ValueError, "'27017 '"): parse_uri("mongodb://localhost:27017 ") orig: dict = { "nodelist": [("localhost", 27017)], "username": None, "password": None, "database": None, "collection": None, "options": {}, "fqdn": None, } res: dict = copy.deepcopy(orig) self.assertEqual(res, parse_uri("mongodb://localhost")) res.update({"username": "fred", "password": "foobar"}) self.assertEqual(res, parse_uri("mongodb://fred:foobar@localhost")) res.update({"database": "baz"}) self.assertEqual(res, parse_uri("mongodb://fred:foobar@localhost/baz")) res = copy.deepcopy(orig) res["nodelist"] = [("example1.com", 27017), ("example2.com", 27017)] self.assertEqual(res, parse_uri("mongodb://example1.com:27017,example2.com:27017")) res = copy.deepcopy(orig) res["nodelist"] = [("localhost", 27017), ("localhost", 27018), ("localhost", 27019)] self.assertEqual(res, parse_uri("mongodb://localhost,localhost:27018,localhost:27019")) res = copy.deepcopy(orig) res["database"] = "foo" self.assertEqual(res, parse_uri("mongodb://localhost/foo")) res = copy.deepcopy(orig) self.assertEqual(res, parse_uri("mongodb://localhost/")) res.update({"database": "test", "collection": "yield_historical.in"}) self.assertEqual(res, parse_uri("mongodb://localhost/test.yield_historical.in")) res.update({"username": "fred", "password": "foobar"}) self.assertEqual(res, parse_uri("mongodb://fred:foobar@localhost/test.yield_historical.in")) res = copy.deepcopy(orig) res["nodelist"] = [("example1.com", 27017), ("example2.com", 27017)] res.update({"database": "test", "collection": "yield_historical.in"}) self.assertEqual( res, parse_uri("mongodb://example1.com:27017,example2.com:27017/test.yield_historical.in"), ) # Test socket path without escaped characters. self.assertRaises(InvalidURI, parse_uri, "mongodb:///tmp/mongodb-27017.sock") # Test with escaped characters. res = copy.deepcopy(orig) res["nodelist"] = [("example2.com", 27017), ("/tmp/mongodb-27017.sock", None)] self.assertEqual(res, parse_uri("mongodb://example2.com,%2Ftmp%2Fmongodb-27017.sock")) res = copy.deepcopy(orig) res["nodelist"] = [("shoe.sock.pants.co.uk", 27017), ("/tmp/mongodb-27017.sock", None)] res["database"] = "nethers_db" self.assertEqual( res, parse_uri("mongodb://shoe.sock.pants.co.uk,%2Ftmp%2Fmongodb-27017.sock/nethers_db"), ) res = copy.deepcopy(orig) res["nodelist"] = [("/tmp/mongodb-27017.sock", None), ("example2.com", 27017)] res.update({"database": "test", "collection": "yield_historical.in"}) self.assertEqual( res, parse_uri( "mongodb://%2Ftmp%2Fmongodb-27017.sock," "example2.com:27017" "/test.yield_historical.in" ), ) res = copy.deepcopy(orig) res["nodelist"] = [("/tmp/mongodb-27017.sock", None), ("example2.com", 27017)] res.update({"database": "test", "collection": "yield_historical.sock"}) self.assertEqual( res, parse_uri( "mongodb://%2Ftmp%2Fmongodb-27017.sock," "example2.com:27017/test.yield_historical" ".sock" ), ) res = copy.deepcopy(orig) res["nodelist"] = [("example2.com", 27017)] res.update({"database": "test", "collection": "yield_historical.sock"}) self.assertEqual(res, parse_uri("mongodb://example2.com:27017/test.yield_historical.sock")) res = copy.deepcopy(orig) res["nodelist"] = [("/tmp/mongodb-27017.sock", None)] res.update({"database": "test", "collection": "mongodb-27017.sock"}) self.assertEqual( res, parse_uri("mongodb://%2Ftmp%2Fmongodb-27017.sock/test.mongodb-27017.sock") ) res = copy.deepcopy(orig) res["nodelist"] = [ ("/tmp/mongodb-27020.sock", None), ("::1", 27017), ("2001:0db8:85a3:0000:0000:8a2e:0370:7334", 27018), ("192.168.0.212", 27019), ("localhost", 27018), ] self.assertEqual( res, parse_uri( "mongodb://%2Ftmp%2Fmongodb-27020.sock" ",[::1]:27017,[2001:0db8:" "85a3:0000:0000:8a2e:0370:7334]," "192.168.0.212:27019,localhost", 27018, ), ) res = copy.deepcopy(orig) res.update({"username": "fred", "password": "foobar"}) res.update({"database": "test", "collection": "yield_historical.in"}) self.assertEqual(res, parse_uri("mongodb://fred:foobar@localhost/test.yield_historical.in")) res = copy.deepcopy(orig) res["database"] = "test" res["collection"] = 'name/with "delimiters' self.assertEqual(res, parse_uri('mongodb://localhost/test.name/with "delimiters')) res = copy.deepcopy(orig) res["options"] = {"readpreference": ReadPreference.SECONDARY.mongos_mode} self.assertEqual(res, parse_uri("mongodb://localhost/?readPreference=secondary")) # Various authentication tests res = copy.deepcopy(orig) res["options"] = {"authmechanism": "MONGODB-CR"} res["username"] = "user" res["password"] = "password" self.assertEqual( res, parse_uri("mongodb://user:password@localhost/?authMechanism=MONGODB-CR") ) res = copy.deepcopy(orig) res["options"] = {"authmechanism": "MONGODB-CR", "authsource": "bar"} res["username"] = "user" res["password"] = "password" res["database"] = "foo" self.assertEqual( res, parse_uri( "mongodb://user:password@localhost/foo?authSource=bar;authMechanism=MONGODB-CR" ), ) res = copy.deepcopy(orig) res["options"] = {"authmechanism": "MONGODB-CR"} res["username"] = "user" res["password"] = "" self.assertEqual(res, parse_uri("mongodb://user:@localhost/?authMechanism=MONGODB-CR")) res = copy.deepcopy(orig) res["username"] = "user@domain.com" res["password"] = "password" res["database"] = "foo" self.assertEqual(res, parse_uri("mongodb://user%40domain.com:password@localhost/foo")) res = copy.deepcopy(orig) res["options"] = {"authmechanism": "GSSAPI"} res["username"] = "user@domain.com" res["password"] = "password" res["database"] = "foo" self.assertEqual( res, parse_uri("mongodb://user%40domain.com:password@localhost/foo?authMechanism=GSSAPI"), ) res = copy.deepcopy(orig) res["options"] = {"authmechanism": "GSSAPI"} res["username"] = "user@domain.com" res["password"] = "" res["database"] = "foo" self.assertEqual( res, parse_uri("mongodb://user%40domain.com@localhost/foo?authMechanism=GSSAPI") ) res = copy.deepcopy(orig) res["options"] = { "readpreference": ReadPreference.SECONDARY.mongos_mode, "readpreferencetags": [ {"dc": "west", "use": "website"}, {"dc": "east", "use": "website"}, ], } res["username"] = "user@domain.com" res["password"] = "password" res["database"] = "foo" self.assertEqual( res, parse_uri( "mongodb://user%40domain.com:password" "@localhost/foo?readpreference=secondary&" "readpreferencetags=dc:west,use:website&" "readpreferencetags=dc:east,use:website" ), ) res = copy.deepcopy(orig) res["options"] = { "readpreference": ReadPreference.SECONDARY.mongos_mode, "readpreferencetags": [ {"dc": "west", "use": "website"}, {"dc": "east", "use": "website"}, {}, ], } res["username"] = "user@domain.com" res["password"] = "password" res["database"] = "foo" self.assertEqual( res, parse_uri( "mongodb://user%40domain.com:password" "@localhost/foo?readpreference=secondary&" "readpreferencetags=dc:west,use:website&" "readpreferencetags=dc:east,use:website&" "readpreferencetags=" ), ) res = copy.deepcopy(orig) res["options"] = {"uuidrepresentation": JAVA_LEGACY} res["username"] = "user@domain.com" res["password"] = "password" res["database"] = "foo" self.assertEqual( res, parse_uri( "mongodb://user%40domain.com:password" "@localhost/foo?uuidrepresentation=" "javaLegacy" ), ) with warnings.catch_warnings(): warnings.filterwarnings("error") self.assertRaises( Warning, parse_uri, "mongodb://user%40domain.com:password" "@localhost/foo?uuidrepresentation=notAnOption", warn=True, ) self.assertRaises( ValueError, parse_uri, "mongodb://user%40domain.com:password@localhost/foo?uuidrepresentation=notAnOption", ) def test_parse_ssl_paths(self): # Turn off "validate" since these paths don't exist on filesystem. self.assertEqual( { "collection": None, "database": None, "nodelist": [("/MongoDB.sock", None)], "options": {"tlsCertificateKeyFile": "/a/b"}, "password": "foo/bar", "username": "jesse", "fqdn": None, }, parse_uri( "mongodb://jesse:foo%2Fbar@%2FMongoDB.sock/?tlsCertificateKeyFile=/a/b", validate=False, ), ) self.assertEqual( { "collection": None, "database": None, "nodelist": [("/MongoDB.sock", None)], "options": {"tlsCertificateKeyFile": "a/b"}, "password": "foo/bar", "username": "jesse", "fqdn": None, }, parse_uri( "mongodb://jesse:foo%2Fbar@%2FMongoDB.sock/?tlsCertificateKeyFile=a/b", validate=False, ), ) def test_tlsinsecure_simple(self): # check that tlsInsecure is expanded correctly. self.maxDiff = None uri = "mongodb://example.com/?tlsInsecure=true" res = { "tlsAllowInvalidHostnames": True, "tlsAllowInvalidCertificates": True, "tlsInsecure": True, "tlsDisableOCSPEndpointCheck": True, } self.assertEqual(res, parse_uri(uri)["options"]) def test_normalize_options(self): # check that options are converted to their internal names correctly. uri = "mongodb://example.com/?ssl=true&appname=myapp" res = {"tls": True, "appname": "myapp"} self.assertEqual(res, parse_uri(uri)["options"]) def test_unquote_after_parsing(self): quoted_val = "val%21%40%23%24%25%5E%26%2A%28%29_%2B%2C%3A+etc" unquoted_val = "val!@#$%^&*()_+,: etc" uri = ( "mongodb://user:password@localhost/?authMechanism=MONGODB-AWS" "&authMechanismProperties=AWS_SESSION_TOKEN:" + quoted_val ) res = parse_uri(uri) options: dict[str, Any] = { "authmechanism": "MONGODB-AWS", "authmechanismproperties": {"AWS_SESSION_TOKEN": unquoted_val}, } self.assertEqual(options, res["options"]) uri = ( "mongodb://localhost/foo?readpreference=secondary&" "readpreferencetags=dc:west," + quoted_val + ":" + quoted_val + "&" "readpreferencetags=dc:east,use:" + quoted_val ) res = parse_uri(uri) options = { "readpreference": ReadPreference.SECONDARY.mongos_mode, "readpreferencetags": [ {"dc": "west", unquoted_val: unquoted_val}, {"dc": "east", "use": unquoted_val}, ], } self.assertEqual(options, res["options"]) def test_redact_AWS_SESSION_TOKEN(self): token = "token" uri = ( "mongodb://user:password@localhost/?authMechanism=MONGODB-AWS" "&authMechanismProperties=AWS_SESSION_TOKEN-" + token ) with self.assertRaisesRegex( ValueError, "auth mechanism properties must be key:value pairs like AWS_SESSION_TOKEN:", ): parse_uri(uri) def test_handle_colon(self): token = "token:foo" uri = ( "mongodb://user:password@localhost/?authMechanism=MONGODB-AWS" "&authMechanismProperties=AWS_SESSION_TOKEN:" + token ) res = parse_uri(uri) options = { "authmechanism": "MONGODB-AWS", "authMechanismProperties": {"AWS_SESSION_TOKEN": token}, } self.assertEqual(options, res["options"]) def test_special_chars(self): user = "user@ /9+:?~!$&'()*+,;=" pwd = "pwd@ /9+:?~!$&'()*+,;=" uri = f"mongodb://{quote_plus(user)}:{quote_plus(pwd)}@localhost" res = parse_uri(uri) self.assertEqual(user, res["username"]) self.assertEqual(pwd, res["password"]) if __name__ == "__main__": unittest.main() mongodb-mongo-python-driver-509e9b7/test/test_uri_spec.py000066400000000000000000000234721462766011000236460ustar00rootroot00000000000000# Copyright 2011-2015 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. """Test that the pymongo.uri_parser module is compliant with the connection string and uri options specifications. """ from __future__ import annotations import json import os import sys import warnings sys.path[0:0] = [""] from test import clear_warning_registry, unittest from pymongo.common import INTERNAL_URI_OPTION_NAME_MAP, validate from pymongo.compression_support import _have_snappy from pymongo.uri_parser import SRV_SCHEME, parse_uri CONN_STRING_TEST_PATH = os.path.join( os.path.dirname(os.path.realpath(__file__)), os.path.join("connection_string", "test") ) URI_OPTIONS_TEST_PATH = os.path.join(os.path.dirname(os.path.realpath(__file__)), "uri_options") TEST_DESC_SKIP_LIST = [ "Valid options specific to single-threaded drivers are parsed correctly", "Invalid serverSelectionTryOnce causes a warning", "tlsDisableCertificateRevocationCheck can be set to true", "tlsDisableCertificateRevocationCheck can be set to false", "tlsAllowInvalidCertificates and tlsDisableCertificateRevocationCheck both present (and true) raises an error", "tlsAllowInvalidCertificates=true and tlsDisableCertificateRevocationCheck=false raises an error", "tlsAllowInvalidCertificates=false and tlsDisableCertificateRevocationCheck=true raises an error", "tlsAllowInvalidCertificates and tlsDisableCertificateRevocationCheck both present (and false) raises an error", "tlsDisableCertificateRevocationCheck and tlsAllowInvalidCertificates both present (and true) raises an error", "tlsDisableCertificateRevocationCheck=true and tlsAllowInvalidCertificates=false raises an error", "tlsDisableCertificateRevocationCheck=false and tlsAllowInvalidCertificates=true raises an error", "tlsDisableCertificateRevocationCheck and tlsAllowInvalidCertificates both present (and false) raises an error", "tlsInsecure and tlsDisableCertificateRevocationCheck both present (and true) raises an error", "tlsInsecure=true and tlsDisableCertificateRevocationCheck=false raises an error", "tlsInsecure=false and tlsDisableCertificateRevocationCheck=true raises an error", "tlsInsecure and tlsDisableCertificateRevocationCheck both present (and false) raises an error", "tlsDisableCertificateRevocationCheck and tlsInsecure both present (and true) raises an error", "tlsDisableCertificateRevocationCheck=true and tlsInsecure=false raises an error", "tlsDisableCertificateRevocationCheck=false and tlsInsecure=true raises an error", "tlsDisableCertificateRevocationCheck and tlsInsecure both present (and false) raises an error", "tlsDisableCertificateRevocationCheck and tlsDisableOCSPEndpointCheck both present (and true) raises an error", "tlsDisableCertificateRevocationCheck=true and tlsDisableOCSPEndpointCheck=false raises an error", "tlsDisableCertificateRevocationCheck=false and tlsDisableOCSPEndpointCheck=true raises an error", "tlsDisableCertificateRevocationCheck and tlsDisableOCSPEndpointCheck both present (and false) raises an error", "tlsDisableOCSPEndpointCheck and tlsDisableCertificateRevocationCheck both present (and true) raises an error", "tlsDisableOCSPEndpointCheck=true and tlsDisableCertificateRevocationCheck=false raises an error", "tlsDisableOCSPEndpointCheck=false and tlsDisableCertificateRevocationCheck=true raises an error", "tlsDisableOCSPEndpointCheck and tlsDisableCertificateRevocationCheck both present (and false) raises an error", ] class TestAllScenarios(unittest.TestCase): def setUp(self): clear_warning_registry() def get_error_message_template(expected, artifact): return "{} {} for test '{}'".format("Expected" if expected else "Unexpected", artifact, "%s") def run_scenario_in_dir(target_workdir): def workdir_context_decorator(func): def modified_test_scenario(*args, **kwargs): original_workdir = os.getcwd() os.chdir(target_workdir) with warnings.catch_warnings(): warnings.simplefilter("default") func(*args, **kwargs) os.chdir(original_workdir) return modified_test_scenario return workdir_context_decorator def create_test(test, test_workdir): def run_scenario(self): compressors = (test.get("options") or {}).get("compressors", []) if "snappy" in compressors and not _have_snappy(): self.skipTest("This test needs the snappy module.") valid = True warning = False expected_warning = test.get("warning", False) expected_valid = test.get("valid", True) with warnings.catch_warnings(record=True) as ctx: warnings.simplefilter("ignore", category=ResourceWarning) try: options = parse_uri(test["uri"], warn=True) except Exception: valid = False else: warning = len(ctx) > 0 if expected_valid and warning and not expected_warning: raise ValueError("Got unexpected warning(s): ", [str(i) for i in ctx]) self.assertEqual( valid, expected_valid, get_error_message_template(not expected_valid, "error") % test["description"], ) if expected_valid: self.assertEqual( warning, expected_warning, get_error_message_template(expected_warning, "warning") % test["description"], ) # Compare hosts and port. if test["hosts"] is not None: self.assertEqual( len(test["hosts"]), len(options["nodelist"]), "Incorrect number of hosts parsed from URI", ) for exp, actual in zip(test["hosts"], options["nodelist"]): self.assertEqual( exp["host"], actual[0], "Expected host {} but got {}".format(exp["host"], actual[0]), ) if exp["port"] is not None: self.assertEqual( exp["port"], actual[1], "Expected port {} but got {}".format(exp["port"], actual), ) # Compare auth options. auth = test["auth"] if auth is not None: auth["database"] = auth.pop("db") # db == database # Special case for PyMongo's collection parsing. if options.get("collection") is not None: options["database"] += "." + options["collection"] for elm in auth: if auth[elm] is not None: # We have to do this because while the spec requires # "+"->"+", unquote_plus does "+"->" " options[elm] = options[elm].replace(" ", "+") self.assertEqual( auth[elm], options[elm], f"Expected {auth[elm]} but got {options[elm]}", ) # Compare URI options. err_msg = "For option %s expected %s but got %s" if test["options"]: opts = options["options"] for opt in test["options"]: lopt = opt.lower() optname = INTERNAL_URI_OPTION_NAME_MAP.get(lopt, lopt) if opts.get(optname) is not None: if opts[optname] == test["options"][opt]: expected_value = test["options"][opt] else: expected_value = validate(lopt, test["options"][opt])[1] self.assertEqual( opts[optname], expected_value, err_msg % ( opt, expected_value, opts[optname], ), ) else: self.fail(f"Missing expected option {opt}") return run_scenario_in_dir(test_workdir)(run_scenario) def create_tests(test_path): for dirpath, _, filenames in os.walk(test_path): dirname = os.path.split(dirpath) dirname = os.path.split(dirname[-2])[-1] + "_" + dirname[-1] for filename in filenames: if not filename.endswith(".json"): # skip everything that is not a test specification continue json_path = os.path.join(dirpath, filename) with open(json_path, encoding="utf-8") as scenario_stream: scenario_def = json.load(scenario_stream) for testcase in scenario_def["tests"]: dsc = testcase["description"] if dsc in TEST_DESC_SKIP_LIST: print("Skipping test '%s'" % dsc) continue testmethod = create_test(testcase, dirpath) testname = "test_{}_{}_{}".format( dirname, os.path.splitext(filename)[0], str(dsc).replace(" ", "_"), ) testmethod.__name__ = testname setattr(TestAllScenarios, testmethod.__name__, testmethod) for test_path in [CONN_STRING_TEST_PATH, URI_OPTIONS_TEST_PATH]: create_tests(test_path) if __name__ == "__main__": unittest.main() mongodb-mongo-python-driver-509e9b7/test/test_versioned_api.py000066400000000000000000000077741462766011000246730ustar00rootroot00000000000000# Copyright 2020-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. from __future__ import annotations import os import sys sys.path[0:0] = [""] from test import IntegrationTest, client_context, unittest from test.unified_format import generate_test_classes from test.utils import OvertCommandListener, rs_or_single_client from pymongo.mongo_client import MongoClient from pymongo.server_api import ServerApi, ServerApiVersion TEST_PATH = os.path.join(os.path.dirname(os.path.realpath(__file__)), "versioned-api") # Generate unified tests. globals().update(generate_test_classes(TEST_PATH, module=__name__)) class TestServerApi(IntegrationTest): RUN_ON_LOAD_BALANCER = True RUN_ON_SERVERLESS = True def test_server_api_defaults(self): api = ServerApi(ServerApiVersion.V1) self.assertEqual(api.version, "1") self.assertIsNone(api.strict) self.assertIsNone(api.deprecation_errors) def test_server_api_explicit_false(self): api = ServerApi("1", strict=False, deprecation_errors=False) self.assertEqual(api.version, "1") self.assertFalse(api.strict) self.assertFalse(api.deprecation_errors) def test_server_api_strict(self): api = ServerApi("1", strict=True, deprecation_errors=True) self.assertEqual(api.version, "1") self.assertTrue(api.strict) self.assertTrue(api.deprecation_errors) def test_server_api_validation(self): with self.assertRaises(ValueError): ServerApi("2") with self.assertRaises(TypeError): ServerApi("1", strict="not-a-bool") # type: ignore[arg-type] with self.assertRaises(TypeError): ServerApi("1", deprecation_errors="not-a-bool") # type: ignore[arg-type] with self.assertRaises(TypeError): MongoClient(server_api="not-a-ServerApi") def assertServerApi(self, event): self.assertIn("apiVersion", event.command) self.assertEqual(event.command["apiVersion"], "1") def assertNoServerApi(self, event): self.assertNotIn("apiVersion", event.command) def assertServerApiInAllCommands(self, events): for event in events: self.assertServerApi(event) @client_context.require_version_min(4, 7) def test_command_options(self): listener = OvertCommandListener() client = rs_or_single_client(server_api=ServerApi("1"), event_listeners=[listener]) self.addCleanup(client.close) coll = client.test.test coll.insert_many([{} for _ in range(100)]) self.addCleanup(coll.delete_many, {}) list(coll.find(batch_size=25)) client.admin.command("ping") self.assertServerApiInAllCommands(listener.started_events) @client_context.require_version_min(4, 7) @client_context.require_transactions def test_command_options_txn(self): listener = OvertCommandListener() client = rs_or_single_client(server_api=ServerApi("1"), event_listeners=[listener]) self.addCleanup(client.close) coll = client.test.test coll.insert_many([{} for _ in range(100)]) self.addCleanup(coll.delete_many, {}) listener.reset() with client.start_session() as s, s.start_transaction(): coll.insert_many([{} for _ in range(100)], session=s) list(coll.find(batch_size=25, session=s)) client.test.command("find", "test", session=s) self.assertServerApiInAllCommands(listener.started_events) if __name__ == "__main__": unittest.main() mongodb-mongo-python-driver-509e9b7/test/test_write_concern.py000066400000000000000000000053031462766011000246670ustar00rootroot00000000000000# Copyright 2018-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. """Run the unit tests for WriteConcern.""" from __future__ import annotations import collections import unittest from pymongo.errors import ConfigurationError from pymongo.write_concern import WriteConcern class TestWriteConcern(unittest.TestCase): def test_invalid(self): # Can't use fsync and j options together self.assertRaises(ConfigurationError, WriteConcern, j=True, fsync=True) # Can't use w=0 and j options together self.assertRaises(ConfigurationError, WriteConcern, w=0, j=True) def test_equality(self): concern = WriteConcern(j=True, wtimeout=3000) self.assertEqual(concern, WriteConcern(j=True, wtimeout=3000)) self.assertNotEqual(concern, WriteConcern()) def test_equality_to_none(self): concern = WriteConcern() self.assertNotEqual(concern, None) # Explicitly use the != operator. self.assertTrue(concern != None) # noqa: E711 def test_equality_compatible_type(self): class _FakeWriteConcern: def __init__(self, **document): self.document = document def __eq__(self, other): try: return self.document == other.document except AttributeError: return NotImplemented def __ne__(self, other): try: return self.document != other.document except AttributeError: return NotImplemented self.assertEqual(WriteConcern(j=True), _FakeWriteConcern(j=True)) self.assertEqual(_FakeWriteConcern(j=True), WriteConcern(j=True)) self.assertEqual(WriteConcern(j=True), _FakeWriteConcern(j=True)) self.assertEqual(WriteConcern(wtimeout=42), _FakeWriteConcern(wtimeout=42)) self.assertNotEqual(WriteConcern(wtimeout=42), _FakeWriteConcern(wtimeout=2000)) def test_equality_incompatible_type(self): _fake_type = collections.namedtuple("NotAWriteConcern", ["document"]) # type: ignore self.assertNotEqual(WriteConcern(j=True), _fake_type({"j": True})) if __name__ == "__main__": unittest.main() mongodb-mongo-python-driver-509e9b7/test/transactions-convenient-api/000077500000000000000000000000001462766011000260415ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/transactions-convenient-api/unified/000077500000000000000000000000001462766011000274645ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/transactions-convenient-api/unified/callback-aborts.json000066400000000000000000000212441462766011000334060ustar00rootroot00000000000000{ "description": "callback-aborts", "schemaVersion": "1.3", "runOnRequirements": [ { "minServerVersion": "4.0", "topologies": [ "replicaset" ] }, { "minServerVersion": "4.1.8", "topologies": [ "sharded", "load-balanced" ] } ], "createEntities": [ { "client": { "id": "client0", "useMultipleMongoses": true, "observeEvents": [ "commandStartedEvent" ] } }, { "database": { "id": "database0", "client": "client0", "databaseName": "withTransaction-tests" } }, { "collection": { "id": "collection0", "database": "database0", "collectionName": "test" } }, { "session": { "id": "session0", "client": "client0" } } ], "initialData": [ { "collectionName": "test", "databaseName": "withTransaction-tests", "documents": [] } ], "tests": [ { "description": "withTransaction succeeds if callback aborts", "operations": [ { "name": "withTransaction", "object": "session0", "arguments": { "callback": [ { "name": "insertOne", "object": "collection0", "arguments": { "session": "session0", "document": { "_id": 1 } }, "expectResult": { "$$unsetOrMatches": { "insertedId": { "$$unsetOrMatches": 1 } } } }, { "name": "abortTransaction", "object": "session0" } ] } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "insert": "test", "documents": [ { "_id": 1 } ], "ordered": true, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": true, "autocommit": false, "readConcern": { "$$exists": false }, "writeConcern": { "$$exists": false } }, "commandName": "insert", "databaseName": "withTransaction-tests" } }, { "commandStartedEvent": { "command": { "abortTransaction": 1, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "autocommit": false, "readConcern": { "$$exists": false }, "startTransaction": { "$$exists": false }, "writeConcern": { "$$exists": false } }, "commandName": "abortTransaction", "databaseName": "admin" } } ] } ], "outcome": [ { "collectionName": "test", "databaseName": "withTransaction-tests", "documents": [] } ] }, { "description": "withTransaction succeeds if callback aborts with no ops", "operations": [ { "name": "withTransaction", "object": "session0", "arguments": { "callback": [ { "name": "abortTransaction", "object": "session0" } ] } } ], "expectEvents": [ { "client": "client0", "events": [] } ], "outcome": [ { "collectionName": "test", "databaseName": "withTransaction-tests", "documents": [] } ] }, { "description": "withTransaction still succeeds if callback aborts and runs extra op", "operations": [ { "name": "withTransaction", "object": "session0", "arguments": { "callback": [ { "name": "insertOne", "object": "collection0", "arguments": { "session": "session0", "document": { "_id": 1 } }, "expectResult": { "$$unsetOrMatches": { "insertedId": { "$$unsetOrMatches": 1 } } } }, { "name": "abortTransaction", "object": "session0" }, { "name": "insertOne", "object": "collection0", "arguments": { "session": "session0", "document": { "_id": 2 } }, "expectResult": { "$$unsetOrMatches": { "insertedId": { "$$unsetOrMatches": 2 } } } } ] } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "insert": "test", "documents": [ { "_id": 1 } ], "ordered": true, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": true, "autocommit": false, "readConcern": { "$$exists": false }, "writeConcern": { "$$exists": false } }, "commandName": "insert", "databaseName": "withTransaction-tests" } }, { "commandStartedEvent": { "command": { "abortTransaction": 1, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "autocommit": false, "readConcern": { "$$exists": false }, "startTransaction": { "$$exists": false }, "writeConcern": { "$$exists": false } }, "commandName": "abortTransaction", "databaseName": "admin" } }, { "commandStartedEvent": { "command": { "insert": "test", "documents": [ { "_id": 2 } ], "ordered": true, "lsid": { "$$sessionLsid": "session0" }, "autocommit": { "$$exists": false }, "readConcern": { "$$exists": false }, "startTransaction": { "$$exists": false }, "writeConcern": { "$$exists": false } }, "commandName": "insert", "databaseName": "withTransaction-tests" } } ] } ], "outcome": [ { "collectionName": "test", "databaseName": "withTransaction-tests", "documents": [ { "_id": 2 } ] } ] } ] } mongodb-mongo-python-driver-509e9b7/test/transactions-convenient-api/unified/callback-commits.json000066400000000000000000000260551462766011000335740ustar00rootroot00000000000000{ "description": "callback-commits", "schemaVersion": "1.3", "runOnRequirements": [ { "minServerVersion": "4.0", "topologies": [ "replicaset" ] }, { "minServerVersion": "4.1.8", "topologies": [ "sharded", "load-balanced" ] } ], "createEntities": [ { "client": { "id": "client0", "useMultipleMongoses": true, "observeEvents": [ "commandStartedEvent" ] } }, { "database": { "id": "database0", "client": "client0", "databaseName": "withTransaction-tests" } }, { "collection": { "id": "collection0", "database": "database0", "collectionName": "test" } }, { "session": { "id": "session0", "client": "client0" } } ], "initialData": [ { "collectionName": "test", "databaseName": "withTransaction-tests", "documents": [] } ], "tests": [ { "description": "withTransaction succeeds if callback commits", "operations": [ { "name": "withTransaction", "object": "session0", "arguments": { "callback": [ { "name": "insertOne", "object": "collection0", "arguments": { "session": "session0", "document": { "_id": 1 } }, "expectResult": { "$$unsetOrMatches": { "insertedId": { "$$unsetOrMatches": 1 } } } }, { "name": "insertOne", "object": "collection0", "arguments": { "session": "session0", "document": { "_id": 2 } }, "expectResult": { "$$unsetOrMatches": { "insertedId": { "$$unsetOrMatches": 2 } } } }, { "name": "commitTransaction", "object": "session0" } ] } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "insert": "test", "documents": [ { "_id": 1 } ], "ordered": true, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": true, "autocommit": false, "readConcern": { "$$exists": false }, "writeConcern": { "$$exists": false } }, "commandName": "insert", "databaseName": "withTransaction-tests" } }, { "commandStartedEvent": { "command": { "insert": "test", "documents": [ { "_id": 2 } ], "ordered": true, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "autocommit": false, "readConcern": { "$$exists": false }, "startTransaction": { "$$exists": false }, "writeConcern": { "$$exists": false } }, "commandName": "insert", "databaseName": "withTransaction-tests" } }, { "commandStartedEvent": { "command": { "commitTransaction": 1, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "autocommit": false, "readConcern": { "$$exists": false }, "startTransaction": { "$$exists": false }, "writeConcern": { "$$exists": false } }, "commandName": "commitTransaction", "databaseName": "admin" } } ] } ], "outcome": [ { "collectionName": "test", "databaseName": "withTransaction-tests", "documents": [ { "_id": 1 }, { "_id": 2 } ] } ] }, { "description": "withTransaction still succeeds if callback commits and runs extra op", "operations": [ { "name": "withTransaction", "object": "session0", "arguments": { "callback": [ { "name": "insertOne", "object": "collection0", "arguments": { "session": "session0", "document": { "_id": 1 } }, "expectResult": { "$$unsetOrMatches": { "insertedId": { "$$unsetOrMatches": 1 } } } }, { "name": "insertOne", "object": "collection0", "arguments": { "session": "session0", "document": { "_id": 2 } }, "expectResult": { "$$unsetOrMatches": { "insertedId": { "$$unsetOrMatches": 2 } } } }, { "name": "commitTransaction", "object": "session0" }, { "name": "insertOne", "object": "collection0", "arguments": { "session": "session0", "document": { "_id": 3 } }, "expectResult": { "$$unsetOrMatches": { "insertedId": { "$$unsetOrMatches": 3 } } } } ] } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "insert": "test", "documents": [ { "_id": 1 } ], "ordered": true, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": true, "autocommit": false, "readConcern": { "$$exists": false }, "writeConcern": { "$$exists": false } }, "commandName": "insert", "databaseName": "withTransaction-tests" } }, { "commandStartedEvent": { "command": { "insert": "test", "documents": [ { "_id": 2 } ], "ordered": true, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "autocommit": false, "readConcern": { "$$exists": false }, "startTransaction": { "$$exists": false }, "writeConcern": { "$$exists": false } }, "commandName": "insert", "databaseName": "withTransaction-tests" } }, { "commandStartedEvent": { "command": { "commitTransaction": 1, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "autocommit": false, "readConcern": { "$$exists": false }, "startTransaction": { "$$exists": false }, "writeConcern": { "$$exists": false } }, "commandName": "commitTransaction", "databaseName": "admin" } }, { "commandStartedEvent": { "command": { "insert": "test", "documents": [ { "_id": 3 } ], "ordered": true, "lsid": { "$$sessionLsid": "session0" }, "autocommit": { "$$exists": false }, "readConcern": { "$$exists": false }, "startTransaction": { "$$exists": false }, "writeConcern": { "$$exists": false } }, "commandName": "insert", "databaseName": "withTransaction-tests" } } ] } ], "outcome": [ { "collectionName": "test", "databaseName": "withTransaction-tests", "documents": [ { "_id": 1 }, { "_id": 2 }, { "_id": 3 } ] } ] } ] } mongodb-mongo-python-driver-509e9b7/test/transactions-convenient-api/unified/callback-retry.json000066400000000000000000000305511462766011000332620ustar00rootroot00000000000000{ "description": "callback-retry", "schemaVersion": "1.4", "runOnRequirements": [ { "minServerVersion": "4.0", "topologies": [ "replicaset" ] }, { "minServerVersion": "4.1.8", "topologies": [ "sharded", "load-balanced" ] } ], "createEntities": [ { "client": { "id": "client0", "useMultipleMongoses": false, "observeEvents": [ "commandStartedEvent" ] } }, { "database": { "id": "database0", "client": "client0", "databaseName": "withTransaction-tests" } }, { "collection": { "id": "collection0", "database": "database0", "collectionName": "test" } }, { "session": { "id": "session0", "client": "client0" } }, { "client": { "id": "client1", "useMultipleMongoses": true, "observeEvents": [ "commandStartedEvent" ] } }, { "database": { "id": "database1", "client": "client1", "databaseName": "withTransaction-tests" } }, { "collection": { "id": "collection1", "database": "database1", "collectionName": "test" } }, { "session": { "id": "session1", "client": "client1" } } ], "initialData": [ { "collectionName": "test", "databaseName": "withTransaction-tests", "documents": [] } ], "tests": [ { "description": "callback succeeds after multiple connection errors", "runOnRequirements": [ { "serverless": "forbid" } ], "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "client0", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 2 }, "data": { "failCommands": [ "insert" ], "closeConnection": true } } } }, { "name": "withTransaction", "object": "session0", "arguments": { "callback": [ { "name": "insertOne", "object": "collection0", "arguments": { "session": "session0", "document": { "_id": 1 } }, "ignoreResultAndError": true } ] } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "insert": "test", "documents": [ { "_id": 1 } ], "ordered": true, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": true, "autocommit": false, "readConcern": { "$$exists": false }, "writeConcern": { "$$exists": false } }, "commandName": "insert", "databaseName": "withTransaction-tests" } }, { "commandStartedEvent": { "command": { "abortTransaction": 1, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "autocommit": false, "readConcern": { "$$exists": false }, "startTransaction": { "$$exists": false }, "writeConcern": { "$$exists": false } }, "commandName": "abortTransaction", "databaseName": "admin" } }, { "commandStartedEvent": { "command": { "insert": "test", "documents": [ { "_id": 1 } ], "ordered": true, "lsid": { "$$sessionLsid": "session0" }, "readConcern": { "afterClusterTime": { "$$exists": true } }, "txnNumber": { "$numberLong": "2" }, "startTransaction": true, "autocommit": false, "writeConcern": { "$$exists": false } }, "commandName": "insert", "databaseName": "withTransaction-tests" } }, { "commandStartedEvent": { "command": { "abortTransaction": 1, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "2" }, "autocommit": false, "readConcern": { "$$exists": false }, "startTransaction": { "$$exists": false }, "writeConcern": { "$$exists": false } }, "commandName": "abortTransaction", "databaseName": "admin" } }, { "commandStartedEvent": { "command": { "insert": "test", "documents": [ { "_id": 1 } ], "ordered": true, "lsid": { "$$sessionLsid": "session0" }, "readConcern": { "afterClusterTime": { "$$exists": true } }, "txnNumber": { "$numberLong": "3" }, "startTransaction": true, "autocommit": false, "writeConcern": { "$$exists": false } }, "commandName": "insert", "databaseName": "withTransaction-tests" } }, { "commandStartedEvent": { "command": { "commitTransaction": 1, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "3" }, "autocommit": false, "readConcern": { "$$exists": false }, "startTransaction": { "$$exists": false }, "writeConcern": { "$$exists": false } }, "commandName": "commitTransaction", "databaseName": "admin" } } ] } ], "outcome": [ { "collectionName": "test", "databaseName": "withTransaction-tests", "documents": [ { "_id": 1 } ] } ] }, { "description": "callback is not retried after non-transient error (DuplicateKeyError)", "operations": [ { "name": "withTransaction", "object": "session1", "arguments": { "callback": [ { "name": "insertOne", "object": "collection1", "arguments": { "session": "session1", "document": { "_id": 1 } }, "expectResult": { "$$unsetOrMatches": { "insertedId": { "$$unsetOrMatches": 1 } } } }, { "name": "insertOne", "object": "collection1", "arguments": { "session": "session1", "document": { "_id": 1 } }, "expectError": { "errorLabelsOmit": [ "TransientTransactionError", "UnknownTransactionCommitResult" ] } } ] }, "expectError": { "errorLabelsOmit": [ "TransientTransactionError", "UnknownTransactionCommitResult" ], "errorContains": "E11000" } } ], "expectEvents": [ { "client": "client1", "events": [ { "commandStartedEvent": { "command": { "insert": "test", "documents": [ { "_id": 1 } ], "ordered": true, "lsid": { "$$sessionLsid": "session1" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": true, "autocommit": false, "readConcern": { "$$exists": false }, "writeConcern": { "$$exists": false } }, "commandName": "insert", "databaseName": "withTransaction-tests" } }, { "commandStartedEvent": { "command": { "insert": "test", "documents": [ { "_id": 1 } ], "ordered": true, "lsid": { "$$sessionLsid": "session1" }, "txnNumber": { "$numberLong": "1" }, "autocommit": false, "readConcern": { "$$exists": false }, "startTransaction": { "$$exists": false }, "writeConcern": { "$$exists": false } }, "commandName": "insert", "databaseName": "withTransaction-tests" } }, { "commandStartedEvent": { "command": { "abortTransaction": 1, "lsid": { "$$sessionLsid": "session1" }, "txnNumber": { "$numberLong": "1" }, "autocommit": false, "readConcern": { "$$exists": false }, "startTransaction": { "$$exists": false }, "writeConcern": { "$$exists": false } }, "commandName": "abortTransaction", "databaseName": "admin" } } ] } ], "outcome": [ { "collectionName": "test", "databaseName": "withTransaction-tests", "documents": [] } ] } ] } commit-retry-errorLabels.json000066400000000000000000000136571462766011000352210ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/transactions-convenient-api/unified{ "description": "commit-retry-errorLabels", "schemaVersion": "1.3", "runOnRequirements": [ { "minServerVersion": "4.3.1", "topologies": [ "replicaset", "sharded", "load-balanced" ] } ], "createEntities": [ { "client": { "id": "client0", "useMultipleMongoses": false, "observeEvents": [ "commandStartedEvent" ] } }, { "database": { "id": "database0", "client": "client0", "databaseName": "withTransaction-tests" } }, { "collection": { "id": "collection0", "database": "database0", "collectionName": "test" } }, { "session": { "id": "session0", "client": "client0" } } ], "initialData": [ { "collectionName": "test", "databaseName": "withTransaction-tests", "documents": [] } ], "tests": [ { "description": "commit is retried after commitTransaction UnknownTransactionCommitResult (NotWritablePrimary)", "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "client0", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 2 }, "data": { "failCommands": [ "commitTransaction" ], "errorCode": 10107, "errorLabels": [ "RetryableWriteError" ], "closeConnection": false } } } }, { "name": "withTransaction", "object": "session0", "arguments": { "callback": [ { "name": "insertOne", "object": "collection0", "arguments": { "session": "session0", "document": { "_id": 1 } }, "expectResult": { "$$unsetOrMatches": { "insertedId": { "$$unsetOrMatches": 1 } } } } ] } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "insert": "test", "documents": [ { "_id": 1 } ], "ordered": true, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": true, "autocommit": false, "readConcern": { "$$exists": false }, "writeConcern": { "$$exists": false } }, "commandName": "insert", "databaseName": "withTransaction-tests" } }, { "commandStartedEvent": { "command": { "commitTransaction": 1, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "autocommit": false, "readConcern": { "$$exists": false }, "startTransaction": { "$$exists": false }, "writeConcern": { "$$exists": false } }, "commandName": "commitTransaction", "databaseName": "admin" } }, { "commandStartedEvent": { "command": { "commitTransaction": 1, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "autocommit": false, "writeConcern": { "w": "majority", "wtimeout": 10000 }, "readConcern": { "$$exists": false }, "startTransaction": { "$$exists": false } }, "commandName": "commitTransaction", "databaseName": "admin" } }, { "commandStartedEvent": { "command": { "commitTransaction": 1, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "autocommit": false, "writeConcern": { "w": "majority", "wtimeout": 10000 }, "readConcern": { "$$exists": false }, "startTransaction": { "$$exists": false } }, "commandName": "commitTransaction", "databaseName": "admin" } } ] } ], "outcome": [ { "collectionName": "test", "databaseName": "withTransaction-tests", "documents": [ { "_id": 1 } ] } ] } ] } mongodb-mongo-python-driver-509e9b7/test/transactions-convenient-api/unified/commit-retry.json000066400000000000000000000350441462766011000330200ustar00rootroot00000000000000{ "description": "commit-retry", "schemaVersion": "1.4", "runOnRequirements": [ { "minServerVersion": "4.0", "topologies": [ "replicaset" ] }, { "minServerVersion": "4.1.8", "topologies": [ "sharded", "load-balanced" ] } ], "createEntities": [ { "client": { "id": "client0", "useMultipleMongoses": false, "observeEvents": [ "commandStartedEvent" ] } }, { "database": { "id": "database0", "client": "client0", "databaseName": "withTransaction-tests" } }, { "collection": { "id": "collection0", "database": "database0", "collectionName": "test" } }, { "session": { "id": "session0", "client": "client0" } } ], "initialData": [ { "collectionName": "test", "databaseName": "withTransaction-tests", "documents": [] } ], "tests": [ { "description": "commitTransaction succeeds after multiple connection errors", "runOnRequirements": [ { "serverless": "forbid" } ], "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "client0", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 2 }, "data": { "failCommands": [ "commitTransaction" ], "closeConnection": true } } } }, { "name": "withTransaction", "object": "session0", "arguments": { "callback": [ { "name": "insertOne", "object": "collection0", "arguments": { "session": "session0", "document": { "_id": 1 } }, "expectResult": { "$$unsetOrMatches": { "insertedId": { "$$unsetOrMatches": 1 } } } } ] } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "insert": "test", "documents": [ { "_id": 1 } ], "ordered": true, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": true, "autocommit": false, "readConcern": { "$$exists": false }, "writeConcern": { "$$exists": false } }, "commandName": "insert", "databaseName": "withTransaction-tests" } }, { "commandStartedEvent": { "command": { "commitTransaction": 1, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "autocommit": false, "readConcern": { "$$exists": false }, "startTransaction": { "$$exists": false }, "writeConcern": { "$$exists": false } }, "commandName": "commitTransaction", "databaseName": "admin" } }, { "commandStartedEvent": { "command": { "commitTransaction": 1, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "autocommit": false, "writeConcern": { "w": "majority", "wtimeout": 10000 }, "readConcern": { "$$exists": false }, "startTransaction": { "$$exists": false } }, "commandName": "commitTransaction", "databaseName": "admin" } }, { "commandStartedEvent": { "command": { "commitTransaction": 1, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "autocommit": false, "writeConcern": { "w": "majority", "wtimeout": 10000 }, "readConcern": { "$$exists": false }, "startTransaction": { "$$exists": false } }, "commandName": "commitTransaction", "databaseName": "admin" } } ] } ], "outcome": [ { "collectionName": "test", "databaseName": "withTransaction-tests", "documents": [ { "_id": 1 } ] } ] }, { "description": "commitTransaction retry only overwrites write concern w option", "runOnRequirements": [ { "serverless": "forbid" } ], "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "client0", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 2 }, "data": { "failCommands": [ "commitTransaction" ], "closeConnection": true } } } }, { "name": "withTransaction", "object": "session0", "arguments": { "callback": [ { "name": "insertOne", "object": "collection0", "arguments": { "session": "session0", "document": { "_id": 1 } }, "expectResult": { "$$unsetOrMatches": { "insertedId": { "$$unsetOrMatches": 1 } } } } ], "writeConcern": { "w": 2, "journal": true, "wtimeoutMS": 5000 } } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "insert": "test", "documents": [ { "_id": 1 } ], "ordered": true, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": true, "autocommit": false, "readConcern": { "$$exists": false }, "writeConcern": { "$$exists": false } }, "commandName": "insert", "databaseName": "withTransaction-tests" } }, { "commandStartedEvent": { "command": { "commitTransaction": 1, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "autocommit": false, "writeConcern": { "w": 2, "j": true, "wtimeout": 5000 }, "readConcern": { "$$exists": false }, "startTransaction": { "$$exists": false } }, "commandName": "commitTransaction", "databaseName": "admin" } }, { "commandStartedEvent": { "command": { "commitTransaction": 1, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "autocommit": false, "writeConcern": { "w": "majority", "j": true, "wtimeout": 5000 }, "readConcern": { "$$exists": false }, "startTransaction": { "$$exists": false } }, "commandName": "commitTransaction", "databaseName": "admin" } }, { "commandStartedEvent": { "command": { "commitTransaction": 1, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "autocommit": false, "writeConcern": { "w": "majority", "j": true, "wtimeout": 5000 }, "readConcern": { "$$exists": false }, "startTransaction": { "$$exists": false } }, "commandName": "commitTransaction", "databaseName": "admin" } } ] } ], "outcome": [ { "collectionName": "test", "databaseName": "withTransaction-tests", "documents": [ { "_id": 1 } ] } ] }, { "description": "commit is not retried after MaxTimeMSExpired error", "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "client0", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "commitTransaction" ], "errorCode": 50 } } } }, { "name": "withTransaction", "object": "session0", "arguments": { "callback": [ { "name": "insertOne", "object": "collection0", "arguments": { "session": "session0", "document": { "_id": 1 } }, "expectResult": { "$$unsetOrMatches": { "insertedId": { "$$unsetOrMatches": 1 } } } } ], "maxCommitTimeMS": 60000 }, "expectError": { "errorCodeName": "MaxTimeMSExpired", "errorLabelsContain": [ "UnknownTransactionCommitResult" ], "errorLabelsOmit": [ "TransientTransactionError" ] } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "insert": "test", "documents": [ { "_id": 1 } ], "ordered": true, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": true, "autocommit": false, "readConcern": { "$$exists": false }, "writeConcern": { "$$exists": false } }, "commandName": "insert", "databaseName": "withTransaction-tests" } }, { "commandStartedEvent": { "command": { "commitTransaction": 1, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "autocommit": false, "maxTimeMS": 60000, "readConcern": { "$$exists": false }, "startTransaction": { "$$exists": false }, "writeConcern": { "$$exists": false } }, "commandName": "commitTransaction", "databaseName": "admin" } } ] } ], "outcome": [ { "collectionName": "test", "databaseName": "withTransaction-tests", "documents": [] } ] } ] } commit-transienttransactionerror-4.2.json000066400000000000000000000173771462766011000374350ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/transactions-convenient-api/unified{ "description": "commit-transienttransactionerror-4.2", "schemaVersion": "1.4", "runOnRequirements": [ { "minServerVersion": "4.1.6", "topologies": [ "replicaset" ] }, { "minServerVersion": "4.1.8", "topologies": [ "sharded", "load-balanced" ], "serverless": "forbid" } ], "createEntities": [ { "client": { "id": "client0", "useMultipleMongoses": false, "observeEvents": [ "commandStartedEvent" ] } }, { "database": { "id": "database0", "client": "client0", "databaseName": "withTransaction-tests" } }, { "collection": { "id": "collection0", "database": "database0", "collectionName": "test" } }, { "session": { "id": "session0", "client": "client0" } } ], "initialData": [ { "collectionName": "test", "databaseName": "withTransaction-tests", "documents": [] } ], "tests": [ { "description": "transaction is retried after commitTransaction TransientTransactionError (PreparedTransactionInProgress)", "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "client0", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 2 }, "data": { "failCommands": [ "commitTransaction" ], "errorCode": 267, "closeConnection": false } } } }, { "name": "withTransaction", "object": "session0", "arguments": { "callback": [ { "name": "insertOne", "object": "collection0", "arguments": { "session": "session0", "document": { "_id": 1 } }, "expectResult": { "$$unsetOrMatches": { "insertedId": { "$$unsetOrMatches": 1 } } } } ] } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "insert": "test", "documents": [ { "_id": 1 } ], "ordered": true, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": true, "autocommit": false, "readConcern": { "$$exists": false }, "writeConcern": { "$$exists": false } }, "commandName": "insert", "databaseName": "withTransaction-tests" } }, { "commandStartedEvent": { "command": { "commitTransaction": 1, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "autocommit": false, "readConcern": { "$$exists": false }, "startTransaction": { "$$exists": false }, "writeConcern": { "$$exists": false } }, "commandName": "commitTransaction", "databaseName": "admin" } }, { "commandStartedEvent": { "command": { "insert": "test", "documents": [ { "_id": 1 } ], "ordered": true, "lsid": { "$$sessionLsid": "session0" }, "readConcern": { "afterClusterTime": { "$$exists": true } }, "txnNumber": { "$numberLong": "2" }, "startTransaction": true, "autocommit": false, "writeConcern": { "$$exists": false } }, "commandName": "insert", "databaseName": "withTransaction-tests" } }, { "commandStartedEvent": { "command": { "commitTransaction": 1, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "2" }, "autocommit": false, "readConcern": { "$$exists": false }, "startTransaction": { "$$exists": false }, "writeConcern": { "$$exists": false } }, "commandName": "commitTransaction", "databaseName": "admin" } }, { "commandStartedEvent": { "command": { "insert": "test", "documents": [ { "_id": 1 } ], "ordered": true, "lsid": { "$$sessionLsid": "session0" }, "readConcern": { "afterClusterTime": { "$$exists": true } }, "txnNumber": { "$numberLong": "3" }, "startTransaction": true, "autocommit": false, "writeConcern": { "$$exists": false } }, "commandName": "insert", "databaseName": "withTransaction-tests" } }, { "commandStartedEvent": { "command": { "commitTransaction": 1, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "3" }, "autocommit": false, "readConcern": { "$$exists": false }, "startTransaction": { "$$exists": false }, "writeConcern": { "$$exists": false } }, "commandName": "commitTransaction", "databaseName": "admin" } } ] } ], "outcome": [ { "collectionName": "test", "databaseName": "withTransaction-tests", "documents": [ { "_id": 1 } ] } ] } ] } commit-transienttransactionerror.json000066400000000000000000000673561462766011000371360ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/transactions-convenient-api/unified{ "description": "commit-transienttransactionerror", "schemaVersion": "1.4", "runOnRequirements": [ { "minServerVersion": "4.0", "topologies": [ "replicaset" ] }, { "minServerVersion": "4.1.8", "topologies": [ "sharded", "load-balanced" ], "serverless": "forbid" } ], "createEntities": [ { "client": { "id": "client0", "useMultipleMongoses": false, "observeEvents": [ "commandStartedEvent" ] } }, { "database": { "id": "database0", "client": "client0", "databaseName": "withTransaction-tests" } }, { "collection": { "id": "collection0", "database": "database0", "collectionName": "test" } }, { "session": { "id": "session0", "client": "client0" } } ], "initialData": [ { "collectionName": "test", "databaseName": "withTransaction-tests", "documents": [] } ], "tests": [ { "description": "transaction is retried after commitTransaction TransientTransactionError (LockTimeout)", "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "client0", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 2 }, "data": { "failCommands": [ "commitTransaction" ], "errorCode": 24, "closeConnection": false } } } }, { "name": "withTransaction", "object": "session0", "arguments": { "callback": [ { "name": "insertOne", "object": "collection0", "arguments": { "session": "session0", "document": { "_id": 1 } }, "expectResult": { "$$unsetOrMatches": { "insertedId": { "$$unsetOrMatches": 1 } } } } ] } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "insert": "test", "documents": [ { "_id": 1 } ], "ordered": true, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": true, "autocommit": false, "readConcern": { "$$exists": false }, "writeConcern": { "$$exists": false } }, "commandName": "insert", "databaseName": "withTransaction-tests" } }, { "commandStartedEvent": { "command": { "commitTransaction": 1, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "autocommit": false, "readConcern": { "$$exists": false }, "startTransaction": { "$$exists": false }, "writeConcern": { "$$exists": false } }, "commandName": "commitTransaction", "databaseName": "admin" } }, { "commandStartedEvent": { "command": { "insert": "test", "documents": [ { "_id": 1 } ], "ordered": true, "lsid": { "$$sessionLsid": "session0" }, "readConcern": { "afterClusterTime": { "$$exists": true } }, "txnNumber": { "$numberLong": "2" }, "startTransaction": true, "autocommit": false, "writeConcern": { "$$exists": false } }, "commandName": "insert", "databaseName": "withTransaction-tests" } }, { "commandStartedEvent": { "command": { "commitTransaction": 1, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "2" }, "autocommit": false, "readConcern": { "$$exists": false }, "startTransaction": { "$$exists": false }, "writeConcern": { "$$exists": false } }, "commandName": "commitTransaction", "databaseName": "admin" } }, { "commandStartedEvent": { "command": { "insert": "test", "documents": [ { "_id": 1 } ], "ordered": true, "lsid": { "$$sessionLsid": "session0" }, "readConcern": { "afterClusterTime": { "$$exists": true } }, "txnNumber": { "$numberLong": "3" }, "startTransaction": true, "autocommit": false, "writeConcern": { "$$exists": false } }, "commandName": "insert", "databaseName": "withTransaction-tests" } }, { "commandStartedEvent": { "command": { "commitTransaction": 1, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "3" }, "autocommit": false, "readConcern": { "$$exists": false }, "startTransaction": { "$$exists": false }, "writeConcern": { "$$exists": false } }, "commandName": "commitTransaction", "databaseName": "admin" } } ] } ], "outcome": [ { "collectionName": "test", "databaseName": "withTransaction-tests", "documents": [ { "_id": 1 } ] } ] }, { "description": "transaction is retried after commitTransaction TransientTransactionError (WriteConflict)", "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "client0", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 2 }, "data": { "failCommands": [ "commitTransaction" ], "errorCode": 112, "closeConnection": false } } } }, { "name": "withTransaction", "object": "session0", "arguments": { "callback": [ { "name": "insertOne", "object": "collection0", "arguments": { "session": "session0", "document": { "_id": 1 } }, "expectResult": { "$$unsetOrMatches": { "insertedId": { "$$unsetOrMatches": 1 } } } } ] } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "insert": "test", "documents": [ { "_id": 1 } ], "ordered": true, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": true, "autocommit": false, "readConcern": { "$$exists": false }, "writeConcern": { "$$exists": false } }, "commandName": "insert", "databaseName": "withTransaction-tests" } }, { "commandStartedEvent": { "command": { "commitTransaction": 1, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "autocommit": false, "readConcern": { "$$exists": false }, "startTransaction": { "$$exists": false }, "writeConcern": { "$$exists": false } }, "commandName": "commitTransaction", "databaseName": "admin" } }, { "commandStartedEvent": { "command": { "insert": "test", "documents": [ { "_id": 1 } ], "ordered": true, "lsid": { "$$sessionLsid": "session0" }, "readConcern": { "afterClusterTime": { "$$exists": true } }, "txnNumber": { "$numberLong": "2" }, "startTransaction": true, "autocommit": false, "writeConcern": { "$$exists": false } }, "commandName": "insert", "databaseName": "withTransaction-tests" } }, { "commandStartedEvent": { "command": { "commitTransaction": 1, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "2" }, "autocommit": false, "readConcern": { "$$exists": false }, "startTransaction": { "$$exists": false }, "writeConcern": { "$$exists": false } }, "commandName": "commitTransaction", "databaseName": "admin" } }, { "commandStartedEvent": { "command": { "insert": "test", "documents": [ { "_id": 1 } ], "ordered": true, "lsid": { "$$sessionLsid": "session0" }, "readConcern": { "afterClusterTime": { "$$exists": true } }, "txnNumber": { "$numberLong": "3" }, "startTransaction": true, "autocommit": false, "writeConcern": { "$$exists": false } }, "commandName": "insert", "databaseName": "withTransaction-tests" } }, { "commandStartedEvent": { "command": { "commitTransaction": 1, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "3" }, "autocommit": false, "readConcern": { "$$exists": false }, "startTransaction": { "$$exists": false }, "writeConcern": { "$$exists": false } }, "commandName": "commitTransaction", "databaseName": "admin" } } ] } ], "outcome": [ { "collectionName": "test", "databaseName": "withTransaction-tests", "documents": [ { "_id": 1 } ] } ] }, { "description": "transaction is retried after commitTransaction TransientTransactionError (SnapshotUnavailable)", "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "client0", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 2 }, "data": { "failCommands": [ "commitTransaction" ], "errorCode": 246, "closeConnection": false } } } }, { "name": "withTransaction", "object": "session0", "arguments": { "callback": [ { "name": "insertOne", "object": "collection0", "arguments": { "session": "session0", "document": { "_id": 1 } }, "expectResult": { "$$unsetOrMatches": { "insertedId": { "$$unsetOrMatches": 1 } } } } ] } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "insert": "test", "documents": [ { "_id": 1 } ], "ordered": true, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": true, "autocommit": false, "readConcern": { "$$exists": false }, "writeConcern": { "$$exists": false } }, "commandName": "insert", "databaseName": "withTransaction-tests" } }, { "commandStartedEvent": { "command": { "commitTransaction": 1, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "autocommit": false, "readConcern": { "$$exists": false }, "startTransaction": { "$$exists": false }, "writeConcern": { "$$exists": false } }, "commandName": "commitTransaction", "databaseName": "admin" } }, { "commandStartedEvent": { "command": { "insert": "test", "documents": [ { "_id": 1 } ], "ordered": true, "lsid": { "$$sessionLsid": "session0" }, "readConcern": { "afterClusterTime": { "$$exists": true } }, "txnNumber": { "$numberLong": "2" }, "startTransaction": true, "autocommit": false, "writeConcern": { "$$exists": false } }, "commandName": "insert", "databaseName": "withTransaction-tests" } }, { "commandStartedEvent": { "command": { "commitTransaction": 1, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "2" }, "autocommit": false, "readConcern": { "$$exists": false }, "startTransaction": { "$$exists": false }, "writeConcern": { "$$exists": false } }, "commandName": "commitTransaction", "databaseName": "admin" } }, { "commandStartedEvent": { "command": { "insert": "test", "documents": [ { "_id": 1 } ], "ordered": true, "lsid": { "$$sessionLsid": "session0" }, "readConcern": { "afterClusterTime": { "$$exists": true } }, "txnNumber": { "$numberLong": "3" }, "startTransaction": true, "autocommit": false, "writeConcern": { "$$exists": false } }, "commandName": "insert", "databaseName": "withTransaction-tests" } }, { "commandStartedEvent": { "command": { "commitTransaction": 1, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "3" }, "autocommit": false, "readConcern": { "$$exists": false }, "startTransaction": { "$$exists": false }, "writeConcern": { "$$exists": false } }, "commandName": "commitTransaction", "databaseName": "admin" } } ] } ], "outcome": [ { "collectionName": "test", "databaseName": "withTransaction-tests", "documents": [ { "_id": 1 } ] } ] }, { "description": "transaction is retried after commitTransaction TransientTransactionError (NoSuchTransaction)", "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "client0", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 2 }, "data": { "failCommands": [ "commitTransaction" ], "errorCode": 251, "closeConnection": false } } } }, { "name": "withTransaction", "object": "session0", "arguments": { "callback": [ { "name": "insertOne", "object": "collection0", "arguments": { "session": "session0", "document": { "_id": 1 } }, "expectResult": { "$$unsetOrMatches": { "insertedId": { "$$unsetOrMatches": 1 } } } } ] } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "insert": "test", "documents": [ { "_id": 1 } ], "ordered": true, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": true, "autocommit": false, "readConcern": { "$$exists": false }, "writeConcern": { "$$exists": false } }, "commandName": "insert", "databaseName": "withTransaction-tests" } }, { "commandStartedEvent": { "command": { "commitTransaction": 1, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "autocommit": false, "readConcern": { "$$exists": false }, "startTransaction": { "$$exists": false }, "writeConcern": { "$$exists": false } }, "commandName": "commitTransaction", "databaseName": "admin" } }, { "commandStartedEvent": { "command": { "insert": "test", "documents": [ { "_id": 1 } ], "ordered": true, "lsid": { "$$sessionLsid": "session0" }, "readConcern": { "afterClusterTime": { "$$exists": true } }, "txnNumber": { "$numberLong": "2" }, "startTransaction": true, "autocommit": false, "writeConcern": { "$$exists": false } }, "commandName": "insert", "databaseName": "withTransaction-tests" } }, { "commandStartedEvent": { "command": { "commitTransaction": 1, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "2" }, "autocommit": false, "readConcern": { "$$exists": false }, "startTransaction": { "$$exists": false }, "writeConcern": { "$$exists": false } }, "commandName": "commitTransaction", "databaseName": "admin" } }, { "commandStartedEvent": { "command": { "insert": "test", "documents": [ { "_id": 1 } ], "ordered": true, "lsid": { "$$sessionLsid": "session0" }, "readConcern": { "afterClusterTime": { "$$exists": true } }, "txnNumber": { "$numberLong": "3" }, "startTransaction": true, "autocommit": false, "writeConcern": { "$$exists": false } }, "commandName": "insert", "databaseName": "withTransaction-tests" } }, { "commandStartedEvent": { "command": { "commitTransaction": 1, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "3" }, "autocommit": false, "readConcern": { "$$exists": false }, "startTransaction": { "$$exists": false }, "writeConcern": { "$$exists": false } }, "commandName": "commitTransaction", "databaseName": "admin" } } ] } ], "outcome": [ { "collectionName": "test", "databaseName": "withTransaction-tests", "documents": [ { "_id": 1 } ] } ] } ] } commit-writeconcernerror.json000066400000000000000000000537241462766011000353550ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/transactions-convenient-api/unified{ "description": "commit-writeconcernerror", "schemaVersion": "1.3", "runOnRequirements": [ { "minServerVersion": "4.0", "topologies": [ "replicaset" ] }, { "minServerVersion": "4.1.8", "topologies": [ "sharded", "load-balanced" ] } ], "createEntities": [ { "client": { "id": "client0", "useMultipleMongoses": false, "observeEvents": [ "commandStartedEvent" ] } }, { "database": { "id": "database0", "client": "client0", "databaseName": "withTransaction-tests" } }, { "collection": { "id": "collection0", "database": "database0", "collectionName": "test" } }, { "session": { "id": "session0", "client": "client0" } } ], "initialData": [ { "collectionName": "test", "databaseName": "withTransaction-tests", "documents": [] } ], "tests": [ { "description": "commitTransaction is retried after WriteConcernFailed timeout error", "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "client0", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 2 }, "data": { "failCommands": [ "commitTransaction" ], "writeConcernError": { "code": 64, "codeName": "WriteConcernFailed", "errmsg": "waiting for replication timed out", "errInfo": { "wtimeout": true } } } } } }, { "name": "withTransaction", "object": "session0", "arguments": { "callback": [ { "name": "insertOne", "object": "collection0", "arguments": { "session": "session0", "document": { "_id": 1 } }, "expectResult": { "$$unsetOrMatches": { "insertedId": { "$$unsetOrMatches": 1 } } } } ] } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "insert": "test", "documents": [ { "_id": 1 } ], "ordered": true, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": true, "autocommit": false, "readConcern": { "$$exists": false }, "writeConcern": { "$$exists": false } }, "commandName": "insert", "databaseName": "withTransaction-tests" } }, { "commandStartedEvent": { "command": { "commitTransaction": 1, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "autocommit": false, "readConcern": { "$$exists": false }, "startTransaction": { "$$exists": false }, "writeConcern": { "$$exists": false } }, "commandName": "commitTransaction", "databaseName": "admin" } }, { "commandStartedEvent": { "command": { "commitTransaction": 1, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "autocommit": false, "writeConcern": { "w": "majority", "wtimeout": 10000 }, "readConcern": { "$$exists": false }, "startTransaction": { "$$exists": false } }, "commandName": "commitTransaction", "databaseName": "admin" } }, { "commandStartedEvent": { "command": { "commitTransaction": 1, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "autocommit": false, "writeConcern": { "w": "majority", "wtimeout": 10000 }, "readConcern": { "$$exists": false }, "startTransaction": { "$$exists": false } }, "commandName": "commitTransaction", "databaseName": "admin" } } ] } ], "outcome": [ { "collectionName": "test", "databaseName": "withTransaction-tests", "documents": [ { "_id": 1 } ] } ] }, { "description": "commitTransaction is retried after WriteConcernFailed non-timeout error", "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "client0", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 2 }, "data": { "failCommands": [ "commitTransaction" ], "writeConcernError": { "code": 64, "codeName": "WriteConcernFailed", "errmsg": "multiple errors reported" } } } } }, { "name": "withTransaction", "object": "session0", "arguments": { "callback": [ { "name": "insertOne", "object": "collection0", "arguments": { "session": "session0", "document": { "_id": 1 } }, "expectResult": { "$$unsetOrMatches": { "insertedId": { "$$unsetOrMatches": 1 } } } } ] } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "insert": "test", "documents": [ { "_id": 1 } ], "ordered": true, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": true, "autocommit": false, "readConcern": { "$$exists": false }, "writeConcern": { "$$exists": false } }, "commandName": "insert", "databaseName": "withTransaction-tests" } }, { "commandStartedEvent": { "command": { "commitTransaction": 1, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "autocommit": false, "readConcern": { "$$exists": false }, "startTransaction": { "$$exists": false }, "writeConcern": { "$$exists": false } }, "commandName": "commitTransaction", "databaseName": "admin" } }, { "commandStartedEvent": { "command": { "commitTransaction": 1, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "autocommit": false, "writeConcern": { "w": "majority", "wtimeout": 10000 }, "readConcern": { "$$exists": false }, "startTransaction": { "$$exists": false } }, "commandName": "commitTransaction", "databaseName": "admin" } }, { "commandStartedEvent": { "command": { "commitTransaction": 1, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "autocommit": false, "writeConcern": { "w": "majority", "wtimeout": 10000 }, "readConcern": { "$$exists": false }, "startTransaction": { "$$exists": false } }, "commandName": "commitTransaction", "databaseName": "admin" } } ] } ], "outcome": [ { "collectionName": "test", "databaseName": "withTransaction-tests", "documents": [ { "_id": 1 } ] } ] }, { "description": "commitTransaction is not retried after UnknownReplWriteConcern error", "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "client0", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "commitTransaction" ], "writeConcernError": { "code": 79, "codeName": "UnknownReplWriteConcern", "errmsg": "No write concern mode named 'foo' found in replica set configuration" } } } } }, { "name": "withTransaction", "object": "session0", "arguments": { "callback": [ { "name": "insertOne", "object": "collection0", "arguments": { "session": "session0", "document": { "_id": 1 } }, "expectResult": { "$$unsetOrMatches": { "insertedId": { "$$unsetOrMatches": 1 } } } } ] }, "expectError": { "errorCodeName": "UnknownReplWriteConcern", "errorLabelsOmit": [ "TransientTransactionError", "UnknownTransactionCommitResult" ] } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "insert": "test", "documents": [ { "_id": 1 } ], "ordered": true, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": true, "autocommit": false, "readConcern": { "$$exists": false }, "writeConcern": { "$$exists": false } }, "commandName": "insert", "databaseName": "withTransaction-tests" } }, { "commandStartedEvent": { "command": { "commitTransaction": 1, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "autocommit": false, "readConcern": { "$$exists": false }, "startTransaction": { "$$exists": false }, "writeConcern": { "$$exists": false } }, "commandName": "commitTransaction", "databaseName": "admin" } } ] } ], "outcome": [ { "collectionName": "test", "databaseName": "withTransaction-tests", "documents": [ { "_id": 1 } ] } ] }, { "description": "commitTransaction is not retried after UnsatisfiableWriteConcern error", "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "client0", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "commitTransaction" ], "writeConcernError": { "code": 100, "codeName": "UnsatisfiableWriteConcern", "errmsg": "Not enough data-bearing nodes" } } } } }, { "name": "withTransaction", "object": "session0", "arguments": { "callback": [ { "name": "insertOne", "object": "collection0", "arguments": { "session": "session0", "document": { "_id": 1 } }, "expectResult": { "$$unsetOrMatches": { "insertedId": { "$$unsetOrMatches": 1 } } } } ] }, "expectError": { "errorCodeName": "UnsatisfiableWriteConcern", "errorLabelsOmit": [ "TransientTransactionError", "UnknownTransactionCommitResult" ] } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "insert": "test", "documents": [ { "_id": 1 } ], "ordered": true, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": true, "autocommit": false, "readConcern": { "$$exists": false }, "writeConcern": { "$$exists": false } }, "commandName": "insert", "databaseName": "withTransaction-tests" } }, { "commandStartedEvent": { "command": { "commitTransaction": 1, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "autocommit": false, "readConcern": { "$$exists": false }, "startTransaction": { "$$exists": false }, "writeConcern": { "$$exists": false } }, "commandName": "commitTransaction", "databaseName": "admin" } } ] } ], "outcome": [ { "collectionName": "test", "databaseName": "withTransaction-tests", "documents": [ { "_id": 1 } ] } ] }, { "description": "commitTransaction is not retried after MaxTimeMSExpired error", "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "client0", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "commitTransaction" ], "writeConcernError": { "code": 50, "codeName": "MaxTimeMSExpired", "errmsg": "operation exceeded time limit" } } } } }, { "name": "withTransaction", "object": "session0", "arguments": { "callback": [ { "name": "insertOne", "object": "collection0", "arguments": { "session": "session0", "document": { "_id": 1 } }, "expectResult": { "$$unsetOrMatches": { "insertedId": { "$$unsetOrMatches": 1 } } } } ] }, "expectError": { "errorCodeName": "MaxTimeMSExpired", "errorLabelsContain": [ "UnknownTransactionCommitResult" ], "errorLabelsOmit": [ "TransientTransactionError" ] } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "insert": "test", "documents": [ { "_id": 1 } ], "ordered": true, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": true, "autocommit": false, "readConcern": { "$$exists": false }, "writeConcern": { "$$exists": false } }, "commandName": "insert", "databaseName": "withTransaction-tests" } }, { "commandStartedEvent": { "command": { "commitTransaction": 1, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "autocommit": false, "readConcern": { "$$exists": false }, "startTransaction": { "$$exists": false }, "writeConcern": { "$$exists": false } }, "commandName": "commitTransaction", "databaseName": "admin" } } ] } ], "outcome": [ { "collectionName": "test", "databaseName": "withTransaction-tests", "documents": [ { "_id": 1 } ] } ] } ] } mongodb-mongo-python-driver-509e9b7/test/transactions-convenient-api/unified/commit.json000066400000000000000000000246141462766011000316560ustar00rootroot00000000000000{ "description": "commit", "schemaVersion": "1.3", "runOnRequirements": [ { "minServerVersion": "4.0", "topologies": [ "replicaset" ] }, { "minServerVersion": "4.1.8", "topologies": [ "sharded", "load-balanced" ] } ], "createEntities": [ { "client": { "id": "client0", "useMultipleMongoses": true, "observeEvents": [ "commandStartedEvent" ] } }, { "database": { "id": "database0", "client": "client0", "databaseName": "withTransaction-tests" } }, { "collection": { "id": "collection0", "database": "database0", "collectionName": "test" } }, { "session": { "id": "session0", "client": "client0" } } ], "initialData": [ { "collectionName": "test", "databaseName": "withTransaction-tests", "documents": [] } ], "tests": [ { "description": "withTransaction commits after callback returns", "operations": [ { "name": "withTransaction", "object": "session0", "arguments": { "callback": [ { "name": "insertOne", "object": "collection0", "arguments": { "session": "session0", "document": { "_id": 1 } }, "expectResult": { "$$unsetOrMatches": { "insertedId": { "$$unsetOrMatches": 1 } } } }, { "name": "insertOne", "object": "collection0", "arguments": { "session": "session0", "document": { "_id": 2 } }, "expectResult": { "$$unsetOrMatches": { "insertedId": { "$$unsetOrMatches": 2 } } } } ] } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "insert": "test", "documents": [ { "_id": 1 } ], "ordered": true, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": true, "autocommit": false, "readConcern": { "$$exists": false }, "writeConcern": { "$$exists": false } }, "commandName": "insert", "databaseName": "withTransaction-tests" } }, { "commandStartedEvent": { "command": { "insert": "test", "documents": [ { "_id": 2 } ], "ordered": true, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "autocommit": false, "readConcern": { "$$exists": false }, "startTransaction": { "$$exists": false }, "writeConcern": { "$$exists": false } }, "commandName": "insert", "databaseName": "withTransaction-tests" } }, { "commandStartedEvent": { "command": { "commitTransaction": 1, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "autocommit": false, "readConcern": { "$$exists": false }, "startTransaction": { "$$exists": false }, "writeConcern": { "$$exists": false } }, "commandName": "commitTransaction", "databaseName": "admin" } } ] } ], "outcome": [ { "collectionName": "test", "databaseName": "withTransaction-tests", "documents": [ { "_id": 1 }, { "_id": 2 } ] } ] }, { "description": "withTransaction commits after callback returns (second transaction)", "operations": [ { "name": "withTransaction", "object": "session0", "arguments": { "callback": [ { "name": "insertOne", "object": "collection0", "arguments": { "session": "session0", "document": { "_id": 1 } }, "expectResult": { "$$unsetOrMatches": { "insertedId": { "$$unsetOrMatches": 1 } } } }, { "name": "commitTransaction", "object": "session0" }, { "name": "startTransaction", "object": "session0" }, { "name": "insertOne", "object": "collection0", "arguments": { "session": "session0", "document": { "_id": 2 } }, "expectResult": { "$$unsetOrMatches": { "insertedId": { "$$unsetOrMatches": 2 } } } } ] } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "insert": "test", "documents": [ { "_id": 1 } ], "ordered": true, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": true, "autocommit": false, "readConcern": { "$$exists": false }, "writeConcern": { "$$exists": false } }, "commandName": "insert", "databaseName": "withTransaction-tests" } }, { "commandStartedEvent": { "command": { "commitTransaction": 1, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "autocommit": false, "readConcern": { "$$exists": false }, "startTransaction": { "$$exists": false }, "writeConcern": { "$$exists": false } }, "commandName": "commitTransaction", "databaseName": "admin" } }, { "commandStartedEvent": { "command": { "insert": "test", "documents": [ { "_id": 2 } ], "ordered": true, "lsid": { "$$sessionLsid": "session0" }, "readConcern": { "afterClusterTime": { "$$exists": true } }, "txnNumber": { "$numberLong": "2" }, "startTransaction": true, "autocommit": false, "writeConcern": { "$$exists": false } }, "commandName": "insert", "databaseName": "withTransaction-tests" } }, { "commandStartedEvent": { "command": { "commitTransaction": 1, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "2" }, "autocommit": false, "readConcern": { "$$exists": false }, "startTransaction": { "$$exists": false }, "writeConcern": { "$$exists": false } }, "commandName": "commitTransaction", "databaseName": "admin" } } ] } ], "outcome": [ { "collectionName": "test", "databaseName": "withTransaction-tests", "documents": [ { "_id": 1 }, { "_id": 2 } ] } ] } ] } transaction-options.json000066400000000000000000000525271462766011000343310ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/transactions-convenient-api/unified{ "description": "transaction-options", "schemaVersion": "1.9", "runOnRequirements": [ { "minServerVersion": "4.0", "topologies": [ "replicaset" ] }, { "minServerVersion": "4.1.8", "topologies": [ "sharded", "load-balanced" ] } ], "createEntities": [ { "client": { "id": "client0", "useMultipleMongoses": true, "observeEvents": [ "commandStartedEvent" ] } }, { "database": { "id": "database0", "client": "client0", "databaseName": "withTransaction-tests" } }, { "collection": { "id": "collection0", "database": "database0", "collectionName": "test" } }, { "session": { "id": "session0", "client": "client0" } } ], "initialData": [ { "collectionName": "test", "databaseName": "withTransaction-tests", "documents": [] } ], "tests": [ { "description": "withTransaction and no transaction options set", "operations": [ { "name": "withTransaction", "object": "session0", "arguments": { "callback": [ { "name": "insertOne", "object": "collection0", "arguments": { "session": "session0", "document": { "_id": 1 } }, "expectResult": { "$$unsetOrMatches": { "insertedId": { "$$unsetOrMatches": 1 } } } } ] } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "insert": "test", "documents": [ { "_id": 1 } ], "ordered": true, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": true, "autocommit": false, "readConcern": { "$$exists": false }, "writeConcern": { "$$exists": false } }, "commandName": "insert", "databaseName": "withTransaction-tests" } }, { "commandStartedEvent": { "command": { "commitTransaction": 1, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "autocommit": false, "readConcern": { "$$exists": false }, "startTransaction": { "$$exists": false }, "writeConcern": { "$$exists": false } }, "commandName": "commitTransaction", "databaseName": "admin" } } ] } ], "outcome": [ { "collectionName": "test", "databaseName": "withTransaction-tests", "documents": [ { "_id": 1 } ] } ] }, { "description": "withTransaction inherits transaction options from client", "operations": [ { "object": "testRunner", "name": "createEntities", "arguments": { "entities": [ { "client": { "id": "client1", "useMultipleMongoses": true, "uriOptions": { "readConcernLevel": "local", "w": 1 }, "observeEvents": [ "commandStartedEvent" ] } }, { "database": { "id": "database1", "client": "client1", "databaseName": "withTransaction-tests" } }, { "collection": { "id": "collection1", "database": "database1", "collectionName": "test" } }, { "session": { "id": "session1", "client": "client1" } } ] } }, { "name": "withTransaction", "object": "session1", "arguments": { "callback": [ { "name": "insertOne", "object": "collection1", "arguments": { "session": "session1", "document": { "_id": 1 } }, "expectResult": { "$$unsetOrMatches": { "insertedId": { "$$unsetOrMatches": 1 } } } } ] } } ], "expectEvents": [ { "client": "client1", "events": [ { "commandStartedEvent": { "command": { "insert": "test", "documents": [ { "_id": 1 } ], "ordered": true, "lsid": { "$$sessionLsid": "session1" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": true, "autocommit": false, "readConcern": { "level": "local" }, "writeConcern": { "$$exists": false } }, "commandName": "insert", "databaseName": "withTransaction-tests" } }, { "commandStartedEvent": { "command": { "commitTransaction": 1, "lsid": { "$$sessionLsid": "session1" }, "txnNumber": { "$numberLong": "1" }, "autocommit": false, "writeConcern": { "w": 1 }, "readConcern": { "$$exists": false }, "startTransaction": { "$$exists": false } }, "commandName": "commitTransaction", "databaseName": "admin" } } ] } ], "outcome": [ { "collectionName": "test", "databaseName": "withTransaction-tests", "documents": [ { "_id": 1 } ] } ] }, { "description": "withTransaction inherits transaction options from defaultTransactionOptions", "operations": [ { "object": "testRunner", "name": "createEntities", "arguments": { "entities": [ { "session": { "id": "session1", "client": "client0", "sessionOptions": { "defaultTransactionOptions": { "readConcern": { "level": "majority" }, "writeConcern": { "w": 1 } } } } } ] } }, { "name": "withTransaction", "object": "session1", "arguments": { "callback": [ { "name": "insertOne", "object": "collection0", "arguments": { "session": "session1", "document": { "_id": 1 } }, "expectResult": { "$$unsetOrMatches": { "insertedId": { "$$unsetOrMatches": 1 } } } } ] } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "insert": "test", "documents": [ { "_id": 1 } ], "ordered": true, "lsid": { "$$sessionLsid": "session1" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": true, "autocommit": false, "readConcern": { "level": "majority" }, "writeConcern": { "$$exists": false } }, "commandName": "insert", "databaseName": "withTransaction-tests" } }, { "commandStartedEvent": { "command": { "commitTransaction": 1, "lsid": { "$$sessionLsid": "session1" }, "txnNumber": { "$numberLong": "1" }, "autocommit": false, "writeConcern": { "w": 1 }, "readConcern": { "$$exists": false }, "startTransaction": { "$$exists": false } }, "commandName": "commitTransaction", "databaseName": "admin" } } ] } ], "outcome": [ { "collectionName": "test", "databaseName": "withTransaction-tests", "documents": [ { "_id": 1 } ] } ] }, { "description": "withTransaction explicit transaction options", "operations": [ { "name": "withTransaction", "object": "session0", "arguments": { "callback": [ { "name": "insertOne", "object": "collection0", "arguments": { "session": "session0", "document": { "_id": 1 } }, "expectResult": { "$$unsetOrMatches": { "insertedId": { "$$unsetOrMatches": 1 } } } } ], "readConcern": { "level": "majority" }, "writeConcern": { "w": 1 } } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "insert": "test", "documents": [ { "_id": 1 } ], "ordered": true, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": true, "autocommit": false, "readConcern": { "level": "majority" }, "writeConcern": { "$$exists": false } }, "commandName": "insert", "databaseName": "withTransaction-tests" } }, { "commandStartedEvent": { "command": { "commitTransaction": 1, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "autocommit": false, "writeConcern": { "w": 1 }, "readConcern": { "$$exists": false }, "startTransaction": { "$$exists": false } }, "commandName": "commitTransaction", "databaseName": "admin" } } ] } ], "outcome": [ { "collectionName": "test", "databaseName": "withTransaction-tests", "documents": [ { "_id": 1 } ] } ] }, { "description": "withTransaction explicit transaction options override defaultTransactionOptions", "operations": [ { "object": "testRunner", "name": "createEntities", "arguments": { "entities": [ { "session": { "id": "session1", "client": "client0", "sessionOptions": { "defaultTransactionOptions": { "readConcern": { "level": "snapshot" }, "writeConcern": { "w": "majority" } } } } } ] } }, { "name": "withTransaction", "object": "session1", "arguments": { "callback": [ { "name": "insertOne", "object": "collection0", "arguments": { "session": "session1", "document": { "_id": 1 } }, "expectResult": { "$$unsetOrMatches": { "insertedId": { "$$unsetOrMatches": 1 } } } } ], "readConcern": { "level": "majority" }, "writeConcern": { "w": 1 } } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "insert": "test", "documents": [ { "_id": 1 } ], "ordered": true, "lsid": { "$$sessionLsid": "session1" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": true, "autocommit": false, "readConcern": { "level": "majority" }, "writeConcern": { "$$exists": false } }, "commandName": "insert", "databaseName": "withTransaction-tests" } }, { "commandStartedEvent": { "command": { "commitTransaction": 1, "lsid": { "$$sessionLsid": "session1" }, "txnNumber": { "$numberLong": "1" }, "autocommit": false, "writeConcern": { "w": 1 }, "readConcern": { "$$exists": false }, "startTransaction": { "$$exists": false } }, "commandName": "commitTransaction", "databaseName": "admin" } } ] } ], "outcome": [ { "collectionName": "test", "databaseName": "withTransaction-tests", "documents": [ { "_id": 1 } ] } ] }, { "description": "withTransaction explicit transaction options override client options", "operations": [ { "object": "testRunner", "name": "createEntities", "arguments": { "entities": [ { "client": { "id": "client1", "useMultipleMongoses": true, "uriOptions": { "readConcernLevel": "local", "w": "majority" }, "observeEvents": [ "commandStartedEvent" ] } }, { "database": { "id": "database1", "client": "client1", "databaseName": "withTransaction-tests" } }, { "collection": { "id": "collection1", "database": "database1", "collectionName": "test" } }, { "session": { "id": "session1", "client": "client1" } } ] } }, { "name": "withTransaction", "object": "session1", "arguments": { "callback": [ { "name": "insertOne", "object": "collection1", "arguments": { "session": "session1", "document": { "_id": 1 } }, "expectResult": { "$$unsetOrMatches": { "insertedId": { "$$unsetOrMatches": 1 } } } } ], "readConcern": { "level": "majority" }, "writeConcern": { "w": 1 } } } ], "expectEvents": [ { "client": "client1", "events": [ { "commandStartedEvent": { "command": { "insert": "test", "documents": [ { "_id": 1 } ], "ordered": true, "lsid": { "$$sessionLsid": "session1" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": true, "autocommit": false, "readConcern": { "level": "majority" }, "writeConcern": { "$$exists": false } }, "commandName": "insert", "databaseName": "withTransaction-tests" } }, { "commandStartedEvent": { "command": { "commitTransaction": 1, "lsid": { "$$sessionLsid": "session1" }, "txnNumber": { "$numberLong": "1" }, "autocommit": false, "writeConcern": { "w": 1 }, "readConcern": { "$$exists": false }, "startTransaction": { "$$exists": false } }, "commandName": "commitTransaction", "databaseName": "admin" } } ] } ], "outcome": [ { "collectionName": "test", "databaseName": "withTransaction-tests", "documents": [ { "_id": 1 } ] } ] } ] } mongodb-mongo-python-driver-509e9b7/test/transactions/000077500000000000000000000000001462766011000231245ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/transactions/unified/000077500000000000000000000000001462766011000245475ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/transactions/unified/abort.json000066400000000000000000000514571462766011000265650ustar00rootroot00000000000000{ "description": "abort", "schemaVersion": "1.3", "runOnRequirements": [ { "minServerVersion": "4.0", "topologies": [ "replicaset" ] }, { "minServerVersion": "4.1.8", "topologies": [ "sharded", "load-balanced" ] } ], "createEntities": [ { "client": { "id": "client0", "useMultipleMongoses": false, "observeEvents": [ "commandStartedEvent" ] } }, { "database": { "id": "database0", "client": "client0", "databaseName": "transaction-tests" } }, { "collection": { "id": "collection0", "database": "database0", "collectionName": "test" } }, { "session": { "id": "session0", "client": "client0" } } ], "initialData": [ { "collectionName": "test", "databaseName": "transaction-tests", "documents": [] } ], "tests": [ { "description": "abort", "operations": [ { "object": "session0", "name": "startTransaction" }, { "object": "collection0", "name": "insertOne", "arguments": { "session": "session0", "document": { "_id": 1 } }, "expectResult": { "$$unsetOrMatches": { "insertedId": { "$$unsetOrMatches": 1 } } } }, { "object": "session0", "name": "abortTransaction" }, { "object": "session0", "name": "startTransaction" }, { "object": "collection0", "name": "insertOne", "arguments": { "session": "session0", "document": { "_id": 1 } }, "expectResult": { "$$unsetOrMatches": { "insertedId": { "$$unsetOrMatches": 1 } } } }, { "object": "session0", "name": "abortTransaction" } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "insert": "test", "documents": [ { "_id": 1 } ], "ordered": true, "readConcern": { "$$exists": false }, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": true, "autocommit": false, "writeConcern": { "$$exists": false } }, "commandName": "insert", "databaseName": "transaction-tests" } }, { "commandStartedEvent": { "command": { "abortTransaction": 1, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": { "$$exists": false }, "autocommit": false, "writeConcern": { "$$exists": false } }, "commandName": "abortTransaction", "databaseName": "admin" } }, { "commandStartedEvent": { "command": { "insert": "test", "documents": [ { "_id": 1 } ], "ordered": true, "readConcern": { "afterClusterTime": { "$$exists": true } }, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "2" }, "startTransaction": true, "autocommit": false, "writeConcern": { "$$exists": false } }, "commandName": "insert", "databaseName": "transaction-tests" } }, { "commandStartedEvent": { "command": { "abortTransaction": 1, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "2" }, "startTransaction": { "$$exists": false }, "autocommit": false, "writeConcern": { "$$exists": false } }, "commandName": "abortTransaction", "databaseName": "admin" } } ] } ], "outcome": [ { "collectionName": "test", "databaseName": "transaction-tests", "documents": [] } ] }, { "description": "implicit abort", "operations": [ { "object": "session0", "name": "startTransaction" }, { "object": "collection0", "name": "insertOne", "arguments": { "session": "session0", "document": { "_id": 1 } }, "expectResult": { "$$unsetOrMatches": { "insertedId": { "$$unsetOrMatches": 1 } } } }, { "object": "session0", "name": "endSession" } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "insert": "test", "documents": [ { "_id": 1 } ], "ordered": true, "readConcern": { "$$exists": false }, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": true, "autocommit": false, "writeConcern": { "$$exists": false } }, "commandName": "insert", "databaseName": "transaction-tests" } }, { "commandStartedEvent": { "command": { "abortTransaction": 1, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": { "$$exists": false }, "autocommit": false, "writeConcern": { "$$exists": false } }, "commandName": "abortTransaction", "databaseName": "admin" } } ] } ], "outcome": [ { "collectionName": "test", "databaseName": "transaction-tests", "documents": [] } ] }, { "description": "two aborts", "operations": [ { "object": "session0", "name": "startTransaction" }, { "object": "collection0", "name": "insertOne", "arguments": { "session": "session0", "document": { "_id": 1 } }, "expectResult": { "$$unsetOrMatches": { "insertedId": { "$$unsetOrMatches": 1 } } } }, { "object": "session0", "name": "abortTransaction" }, { "object": "session0", "name": "abortTransaction", "expectError": { "errorContains": "cannot call abortTransaction twice" } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "insert": "test", "documents": [ { "_id": 1 } ], "ordered": true, "readConcern": { "$$exists": false }, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": true, "autocommit": false, "writeConcern": { "$$exists": false } }, "commandName": "insert", "databaseName": "transaction-tests" } }, { "commandStartedEvent": { "command": { "abortTransaction": 1, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": { "$$exists": false }, "autocommit": false, "writeConcern": { "$$exists": false } }, "commandName": "abortTransaction", "databaseName": "admin" } } ] } ], "outcome": [ { "collectionName": "test", "databaseName": "transaction-tests", "documents": [] } ] }, { "description": "abort without start", "operations": [ { "object": "session0", "name": "abortTransaction", "expectError": { "errorContains": "no transaction started" } } ], "expectEvents": [ { "client": "client0", "events": [] } ], "outcome": [ { "collectionName": "test", "databaseName": "transaction-tests", "documents": [] } ] }, { "description": "abort directly after no-op commit", "operations": [ { "object": "session0", "name": "startTransaction" }, { "object": "session0", "name": "commitTransaction" }, { "object": "session0", "name": "abortTransaction", "expectError": { "errorContains": "Cannot call abortTransaction after calling commitTransaction" } } ], "expectEvents": [ { "client": "client0", "events": [] } ], "outcome": [ { "collectionName": "test", "databaseName": "transaction-tests", "documents": [] } ] }, { "description": "abort directly after commit", "operations": [ { "object": "session0", "name": "startTransaction" }, { "object": "collection0", "name": "insertOne", "arguments": { "session": "session0", "document": { "_id": 1 } }, "expectResult": { "$$unsetOrMatches": { "insertedId": { "$$unsetOrMatches": 1 } } } }, { "object": "session0", "name": "commitTransaction" }, { "object": "session0", "name": "abortTransaction", "expectError": { "errorContains": "Cannot call abortTransaction after calling commitTransaction" } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "insert": "test", "documents": [ { "_id": 1 } ], "ordered": true, "readConcern": { "$$exists": false }, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": true, "autocommit": false, "writeConcern": { "$$exists": false } }, "commandName": "insert", "databaseName": "transaction-tests" } }, { "commandStartedEvent": { "command": { "commitTransaction": 1, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": { "$$exists": false }, "autocommit": false, "writeConcern": { "$$exists": false } }, "commandName": "commitTransaction", "databaseName": "admin" } } ] } ], "outcome": [ { "collectionName": "test", "databaseName": "transaction-tests", "documents": [ { "_id": 1 } ] } ] }, { "description": "abort ignores TransactionAborted", "operations": [ { "object": "session0", "name": "startTransaction" }, { "object": "collection0", "name": "insertOne", "arguments": { "session": "session0", "document": { "_id": 1 } }, "expectResult": { "$$unsetOrMatches": { "insertedId": { "$$unsetOrMatches": 1 } } } }, { "object": "collection0", "name": "insertOne", "arguments": { "session": "session0", "document": { "_id": 1 } }, "expectError": { "errorLabelsOmit": [ "TransientTransactionError", "UnknownTransactionCommitResult" ], "errorContains": "E11000" } }, { "object": "collection0", "name": "insertOne", "arguments": { "session": "session0", "document": { "_id": 1 } }, "expectError": { "errorCodeName": "NoSuchTransaction", "errorLabelsContain": [ "TransientTransactionError" ], "errorLabelsOmit": [ "UnknownTransactionCommitResult" ] } }, { "object": "session0", "name": "abortTransaction" } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "insert": "test", "documents": [ { "_id": 1 } ], "ordered": true, "readConcern": { "$$exists": false }, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": true, "autocommit": false, "writeConcern": { "$$exists": false } }, "commandName": "insert", "databaseName": "transaction-tests" } }, { "commandStartedEvent": { "command": { "insert": "test", "documents": [ { "_id": 1 } ], "ordered": true, "readConcern": { "$$exists": false }, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": { "$$exists": false }, "autocommit": false, "writeConcern": { "$$exists": false } }, "commandName": "insert", "databaseName": "transaction-tests" } }, { "commandStartedEvent": { "command": { "insert": "test", "documents": [ { "_id": 1 } ], "ordered": true, "readConcern": { "$$exists": false }, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": { "$$exists": false }, "autocommit": false, "writeConcern": { "$$exists": false } }, "commandName": "insert", "databaseName": "transaction-tests" } }, { "commandStartedEvent": { "command": { "abortTransaction": 1, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": { "$$exists": false }, "autocommit": false, "writeConcern": { "$$exists": false } }, "commandName": "abortTransaction", "databaseName": "admin" } } ] } ], "outcome": [ { "collectionName": "test", "databaseName": "transaction-tests", "documents": [] } ] }, { "description": "abort does not apply writeConcern", "operations": [ { "object": "session0", "name": "startTransaction", "arguments": { "writeConcern": { "w": 10 } } }, { "object": "collection0", "name": "insertOne", "arguments": { "session": "session0", "document": { "_id": 1 } }, "expectResult": { "$$unsetOrMatches": { "insertedId": { "$$unsetOrMatches": 1 } } } }, { "object": "session0", "name": "abortTransaction" } ], "outcome": [ { "collectionName": "test", "databaseName": "transaction-tests", "documents": [] } ] } ] } mongodb-mongo-python-driver-509e9b7/test/transactions/unified/bulk.json000066400000000000000000000416741462766011000264130ustar00rootroot00000000000000{ "description": "bulk", "schemaVersion": "1.3", "runOnRequirements": [ { "minServerVersion": "4.0", "topologies": [ "replicaset" ] }, { "minServerVersion": "4.1.8", "topologies": [ "sharded", "load-balanced" ] } ], "createEntities": [ { "client": { "id": "client0", "useMultipleMongoses": false, "observeEvents": [ "commandStartedEvent" ] } }, { "database": { "id": "database0", "client": "client0", "databaseName": "transaction-tests" } }, { "collection": { "id": "collection0", "database": "database0", "collectionName": "test" } }, { "session": { "id": "session0", "client": "client0" } } ], "initialData": [ { "collectionName": "test", "databaseName": "transaction-tests", "documents": [] } ], "tests": [ { "description": "bulk", "operations": [ { "object": "session0", "name": "startTransaction" }, { "object": "collection0", "name": "insertOne", "arguments": { "session": "session0", "document": { "_id": 1 } }, "expectResult": { "$$unsetOrMatches": { "insertedId": { "$$unsetOrMatches": 1 } } } }, { "object": "collection0", "name": "deleteOne", "arguments": { "session": "session0", "filter": { "_id": 1 } }, "expectResult": { "deletedCount": 1 } }, { "object": "collection0", "name": "bulkWrite", "arguments": { "session": "session0", "requests": [ { "insertOne": { "document": { "_id": 1 } } }, { "updateOne": { "filter": { "_id": 1 }, "update": { "$set": { "x": 1 } } } }, { "updateOne": { "filter": { "_id": 2 }, "update": { "$set": { "x": 2 } }, "upsert": true } }, { "insertOne": { "document": { "_id": 3 } } }, { "insertOne": { "document": { "_id": 4 } } }, { "insertOne": { "document": { "_id": 5 } } }, { "insertOne": { "document": { "_id": 6 } } }, { "insertOne": { "document": { "_id": 7 } } }, { "replaceOne": { "filter": { "_id": 1 }, "replacement": { "y": 1 } } }, { "replaceOne": { "filter": { "_id": 2 }, "replacement": { "y": 2 } } }, { "deleteOne": { "filter": { "_id": 3 } } }, { "deleteOne": { "filter": { "_id": 4 } } }, { "updateMany": { "filter": { "_id": { "$gte": 2 } }, "update": { "$set": { "z": 1 } } } }, { "deleteMany": { "filter": { "_id": { "$gte": 6 } } } } ] }, "expectResult": { "deletedCount": 4, "insertedCount": 6, "insertedIds": { "$$unsetOrMatches": { "0": 1, "3": 3, "4": 4, "5": 5, "6": 6, "7": 7 } }, "matchedCount": 7, "modifiedCount": 7, "upsertedCount": 1, "upsertedIds": { "2": 2 } } }, { "object": "session0", "name": "commitTransaction" } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "insert": "test", "documents": [ { "_id": 1 } ], "ordered": true, "readConcern": { "$$exists": false }, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": true, "autocommit": false, "writeConcern": { "$$exists": false } }, "commandName": "insert", "databaseName": "transaction-tests" } }, { "commandStartedEvent": { "command": { "delete": "test", "deletes": [ { "q": { "_id": 1 }, "limit": 1 } ], "ordered": true, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": { "$$exists": false }, "autocommit": false, "writeConcern": { "$$exists": false } }, "commandName": "delete", "databaseName": "transaction-tests" } }, { "commandStartedEvent": { "command": { "insert": "test", "documents": [ { "_id": 1 } ], "ordered": true, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": { "$$exists": false }, "autocommit": false, "writeConcern": { "$$exists": false } }, "commandName": "insert", "databaseName": "transaction-tests" } }, { "commandStartedEvent": { "command": { "update": "test", "updates": [ { "q": { "_id": 1 }, "u": { "$set": { "x": 1 } }, "multi": { "$$unsetOrMatches": false }, "upsert": { "$$unsetOrMatches": false } }, { "q": { "_id": 2 }, "u": { "$set": { "x": 2 } }, "upsert": true, "multi": { "$$unsetOrMatches": false } } ], "ordered": true, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": { "$$exists": false }, "autocommit": false, "writeConcern": { "$$exists": false } }, "commandName": "update", "databaseName": "transaction-tests" } }, { "commandStartedEvent": { "command": { "insert": "test", "documents": [ { "_id": 3 }, { "_id": 4 }, { "_id": 5 }, { "_id": 6 }, { "_id": 7 } ], "ordered": true, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": { "$$exists": false }, "autocommit": false, "writeConcern": { "$$exists": false } }, "commandName": "insert", "databaseName": "transaction-tests" } }, { "commandStartedEvent": { "command": { "update": "test", "updates": [ { "q": { "_id": 1 }, "u": { "y": 1 }, "multi": { "$$unsetOrMatches": false }, "upsert": { "$$unsetOrMatches": false } }, { "q": { "_id": 2 }, "u": { "y": 2 }, "multi": { "$$unsetOrMatches": false }, "upsert": { "$$unsetOrMatches": false } } ], "ordered": true, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": { "$$exists": false }, "autocommit": false, "writeConcern": { "$$exists": false } }, "commandName": "update", "databaseName": "transaction-tests" } }, { "commandStartedEvent": { "command": { "delete": "test", "deletes": [ { "q": { "_id": 3 }, "limit": 1 }, { "q": { "_id": 4 }, "limit": 1 } ], "ordered": true, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": { "$$exists": false }, "autocommit": false, "writeConcern": { "$$exists": false } }, "commandName": "delete", "databaseName": "transaction-tests" } }, { "commandStartedEvent": { "command": { "update": "test", "updates": [ { "q": { "_id": { "$gte": 2 } }, "u": { "$set": { "z": 1 } }, "multi": true, "upsert": { "$$unsetOrMatches": false } } ], "ordered": true, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": { "$$exists": false }, "autocommit": false, "writeConcern": { "$$exists": false } }, "commandName": "update", "databaseName": "transaction-tests" } }, { "commandStartedEvent": { "command": { "delete": "test", "deletes": [ { "q": { "_id": { "$gte": 6 } }, "limit": 0 } ], "ordered": true, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": { "$$exists": false }, "autocommit": false, "writeConcern": { "$$exists": false } }, "commandName": "delete", "databaseName": "transaction-tests" } }, { "commandStartedEvent": { "command": { "commitTransaction": 1, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": { "$$exists": false }, "autocommit": false, "writeConcern": { "$$exists": false } }, "commandName": "commitTransaction", "databaseName": "admin" } } ] } ], "outcome": [ { "collectionName": "test", "databaseName": "transaction-tests", "documents": [ { "_id": 1, "y": 1 }, { "_id": 2, "y": 2, "z": 1 }, { "_id": 5, "z": 1 } ] } ] } ] } mongodb-mongo-python-driver-509e9b7/test/transactions/unified/causal-consistency.json000066400000000000000000000251271462766011000312600ustar00rootroot00000000000000{ "description": "causal-consistency", "schemaVersion": "1.3", "runOnRequirements": [ { "minServerVersion": "4.0", "topologies": [ "replicaset" ] }, { "minServerVersion": "4.1.8", "topologies": [ "sharded", "load-balanced" ] } ], "createEntities": [ { "client": { "id": "client0", "useMultipleMongoses": false, "uriOptions": { "retryWrites": false }, "observeEvents": [ "commandStartedEvent" ] } }, { "database": { "id": "database0", "client": "client0", "databaseName": "transaction-tests" } }, { "collection": { "id": "collection0", "database": "database0", "collectionName": "test" } }, { "session": { "id": "session0", "client": "client0" } }, { "session": { "id": "session_no_cc", "client": "client0", "sessionOptions": { "causalConsistency": false } } } ], "initialData": [ { "collectionName": "test", "databaseName": "transaction-tests", "documents": [ { "_id": 1, "count": 0 } ] } ], "tests": [ { "description": "causal consistency", "operations": [ { "object": "collection0", "name": "updateOne", "arguments": { "session": "session0", "filter": { "_id": 1 }, "update": { "$inc": { "count": 1 } } }, "expectResult": { "matchedCount": 1, "modifiedCount": 1, "upsertedCount": 0 } }, { "object": "session0", "name": "startTransaction" }, { "object": "collection0", "name": "updateOne", "arguments": { "session": "session0", "filter": { "_id": 1 }, "update": { "$inc": { "count": 1 } } }, "expectResult": { "matchedCount": 1, "modifiedCount": 1, "upsertedCount": 0 } }, { "object": "session0", "name": "commitTransaction" } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "update": "test", "updates": [ { "q": { "_id": 1 }, "u": { "$inc": { "count": 1 } }, "multi": { "$$unsetOrMatches": false }, "upsert": { "$$unsetOrMatches": false } } ], "ordered": true, "lsid": { "$$sessionLsid": "session0" }, "readConcern": { "$$exists": false }, "txnNumber": { "$$exists": false }, "startTransaction": { "$$exists": false }, "autocommit": { "$$exists": false }, "writeConcern": { "$$exists": false } }, "commandName": "update", "databaseName": "transaction-tests" } }, { "commandStartedEvent": { "command": { "update": "test", "updates": [ { "q": { "_id": 1 }, "u": { "$inc": { "count": 1 } }, "multi": { "$$unsetOrMatches": false }, "upsert": { "$$unsetOrMatches": false } } ], "ordered": true, "readConcern": { "afterClusterTime": { "$$exists": true } }, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": true, "autocommit": false, "writeConcern": { "$$exists": false } }, "commandName": "update", "databaseName": "transaction-tests" } }, { "commandStartedEvent": { "command": { "commitTransaction": 1, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": { "$$exists": false }, "autocommit": false, "writeConcern": { "$$exists": false } }, "commandName": "commitTransaction", "databaseName": "admin" } } ] } ], "outcome": [ { "collectionName": "test", "databaseName": "transaction-tests", "documents": [ { "_id": 1, "count": 2 } ] } ] }, { "description": "causal consistency disabled", "operations": [ { "object": "collection0", "name": "insertOne", "arguments": { "session": "session_no_cc", "document": { "_id": 2 } }, "expectResult": { "$$unsetOrMatches": { "insertedId": { "$$unsetOrMatches": 2 } } } }, { "object": "session_no_cc", "name": "startTransaction" }, { "object": "collection0", "name": "updateOne", "arguments": { "session": "session_no_cc", "filter": { "_id": 1 }, "update": { "$inc": { "count": 1 } } }, "expectResult": { "matchedCount": 1, "modifiedCount": 1, "upsertedCount": 0 } }, { "object": "session_no_cc", "name": "commitTransaction" } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "insert": "test", "documents": [ { "_id": 2 } ], "ordered": true, "readConcern": { "$$exists": false }, "lsid": { "$$sessionLsid": "session_no_cc" }, "txnNumber": { "$$exists": false }, "autocommit": { "$$exists": false }, "writeConcern": { "$$exists": false } }, "commandName": "insert", "databaseName": "transaction-tests" } }, { "commandStartedEvent": { "command": { "update": "test", "updates": [ { "q": { "_id": 1 }, "u": { "$inc": { "count": 1 } }, "multi": { "$$unsetOrMatches": false }, "upsert": { "$$unsetOrMatches": false } } ], "ordered": true, "readConcern": { "$$exists": false }, "lsid": { "$$sessionLsid": "session_no_cc" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": true, "autocommit": false, "writeConcern": { "$$exists": false } }, "commandName": "update", "databaseName": "transaction-tests" } }, { "commandStartedEvent": { "command": { "commitTransaction": 1, "lsid": { "$$sessionLsid": "session_no_cc" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": { "$$exists": false }, "autocommit": false, "writeConcern": { "$$exists": false } }, "commandName": "commitTransaction", "databaseName": "admin" } } ] } ], "outcome": [ { "collectionName": "test", "databaseName": "transaction-tests", "documents": [ { "_id": 1, "count": 1 }, { "_id": 2 } ] } ] } ] } mongodb-mongo-python-driver-509e9b7/test/transactions/unified/commit.json000066400000000000000000000757771462766011000267610ustar00rootroot00000000000000{ "description": "commit", "schemaVersion": "1.3", "runOnRequirements": [ { "minServerVersion": "4.0", "topologies": [ "replicaset" ] }, { "minServerVersion": "4.1.8", "topologies": [ "sharded", "load-balanced" ] } ], "createEntities": [ { "client": { "id": "client0", "useMultipleMongoses": false, "observeEvents": [ "commandStartedEvent" ] } }, { "database": { "id": "database0", "client": "client0", "databaseName": "transaction-tests" } }, { "collection": { "id": "collection0", "database": "database0", "collectionName": "test" } }, { "session": { "id": "session0", "client": "client0" } }, { "client": { "id": "client1", "useMultipleMongoses": false, "uriOptions": { "retryWrites": false }, "observeEvents": [ "commandStartedEvent" ] } }, { "database": { "id": "database1", "client": "client1", "databaseName": "transaction-tests" } }, { "collection": { "id": "collection1", "database": "database1", "collectionName": "test" } }, { "session": { "id": "session1", "client": "client1" } } ], "initialData": [ { "collectionName": "test", "databaseName": "transaction-tests", "documents": [] } ], "tests": [ { "description": "commit", "operations": [ { "object": "session0", "name": "startTransaction" }, { "object": "collection0", "name": "insertOne", "arguments": { "session": "session0", "document": { "_id": 1 } }, "expectResult": { "$$unsetOrMatches": { "insertedId": { "$$unsetOrMatches": 1 } } } }, { "object": "session0", "name": "commitTransaction" }, { "object": "session0", "name": "startTransaction" }, { "object": "collection0", "name": "insertOne", "arguments": { "session": "session0", "document": { "_id": 2 } }, "expectResult": { "$$unsetOrMatches": { "insertedId": { "$$unsetOrMatches": 2 } } } }, { "object": "session0", "name": "commitTransaction" } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "insert": "test", "documents": [ { "_id": 1 } ], "ordered": true, "readConcern": { "$$exists": false }, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": true, "autocommit": false, "writeConcern": { "$$exists": false } }, "commandName": "insert", "databaseName": "transaction-tests" } }, { "commandStartedEvent": { "command": { "commitTransaction": 1, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": { "$$exists": false }, "autocommit": false, "writeConcern": { "$$exists": false } }, "commandName": "commitTransaction", "databaseName": "admin" } }, { "commandStartedEvent": { "command": { "insert": "test", "documents": [ { "_id": 2 } ], "ordered": true, "readConcern": { "afterClusterTime": { "$$exists": true } }, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "2" }, "startTransaction": true, "autocommit": false, "writeConcern": { "$$exists": false } }, "commandName": "insert", "databaseName": "transaction-tests" } }, { "commandStartedEvent": { "command": { "commitTransaction": 1, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "2" }, "startTransaction": { "$$exists": false }, "autocommit": false, "writeConcern": { "$$exists": false } }, "commandName": "commitTransaction", "databaseName": "admin" } } ] } ], "outcome": [ { "collectionName": "test", "databaseName": "transaction-tests", "documents": [ { "_id": 1 }, { "_id": 2 } ] } ] }, { "description": "rerun commit after empty transaction", "operations": [ { "object": "session0", "name": "startTransaction" }, { "object": "session0", "name": "commitTransaction" }, { "object": "session0", "name": "commitTransaction" }, { "object": "session0", "name": "startTransaction" }, { "object": "collection0", "name": "insertOne", "arguments": { "session": "session0", "document": { "_id": 1 } }, "expectResult": { "$$unsetOrMatches": { "insertedId": { "$$unsetOrMatches": 1 } } } }, { "object": "session0", "name": "commitTransaction" } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "insert": "test", "documents": [ { "_id": 1 } ], "ordered": true, "readConcern": { "$$exists": false }, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "2" }, "startTransaction": true, "autocommit": false, "writeConcern": { "$$exists": false } }, "commandName": "insert", "databaseName": "transaction-tests" } }, { "commandStartedEvent": { "command": { "commitTransaction": 1, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "2" }, "startTransaction": { "$$exists": false }, "autocommit": false, "writeConcern": { "$$exists": false } }, "commandName": "commitTransaction", "databaseName": "admin" } } ] } ], "outcome": [ { "collectionName": "test", "databaseName": "transaction-tests", "documents": [ { "_id": 1 } ] } ] }, { "description": "multiple commits in a row", "operations": [ { "object": "session0", "name": "startTransaction" }, { "object": "collection0", "name": "insertOne", "arguments": { "session": "session0", "document": { "_id": 1 } }, "expectResult": { "$$unsetOrMatches": { "insertedId": { "$$unsetOrMatches": 1 } } } }, { "object": "session0", "name": "commitTransaction" }, { "object": "session0", "name": "commitTransaction" }, { "object": "session0", "name": "commitTransaction" } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "insert": "test", "documents": [ { "_id": 1 } ], "ordered": true, "readConcern": { "$$exists": false }, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": true, "autocommit": false, "writeConcern": { "$$exists": false } }, "commandName": "insert", "databaseName": "transaction-tests" } }, { "commandStartedEvent": { "command": { "commitTransaction": 1, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": { "$$exists": false }, "autocommit": false, "writeConcern": { "$$exists": false } }, "commandName": "commitTransaction", "databaseName": "admin" } }, { "commandStartedEvent": { "command": { "commitTransaction": 1, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": { "$$exists": false }, "autocommit": false, "writeConcern": { "w": "majority", "wtimeout": 10000 } }, "commandName": "commitTransaction", "databaseName": "admin" } }, { "commandStartedEvent": { "command": { "commitTransaction": 1, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": { "$$exists": false }, "autocommit": false, "writeConcern": { "w": "majority", "wtimeout": 10000 } }, "commandName": "commitTransaction", "databaseName": "admin" } } ] } ], "outcome": [ { "collectionName": "test", "databaseName": "transaction-tests", "documents": [ { "_id": 1 } ] } ] }, { "description": "write concern error on commit", "operations": [ { "object": "session0", "name": "startTransaction", "arguments": { "writeConcern": { "w": 10 } } }, { "object": "collection0", "name": "insertOne", "arguments": { "session": "session0", "document": { "_id": 1 } }, "expectResult": { "$$unsetOrMatches": { "insertedId": { "$$unsetOrMatches": 1 } } } }, { "object": "session0", "name": "commitTransaction", "expectError": { "errorLabelsOmit": [ "TransientTransactionError", "UnknownTransactionCommitResult" ] } } ], "outcome": [ { "collectionName": "test", "databaseName": "transaction-tests", "documents": [ { "_id": 1 } ] } ] }, { "description": "commit without start", "operations": [ { "object": "session0", "name": "commitTransaction", "expectError": { "errorContains": "no transaction started" } } ], "expectEvents": [ { "client": "client0", "events": [] } ], "outcome": [ { "collectionName": "test", "databaseName": "transaction-tests", "documents": [] } ] }, { "description": "commit after no-op abort", "operations": [ { "object": "session0", "name": "startTransaction" }, { "object": "session0", "name": "abortTransaction" }, { "object": "session0", "name": "commitTransaction", "expectError": { "errorContains": "Cannot call commitTransaction after calling abortTransaction" } } ], "expectEvents": [ { "client": "client0", "events": [] } ], "outcome": [ { "collectionName": "test", "databaseName": "transaction-tests", "documents": [] } ] }, { "description": "commit after abort", "operations": [ { "object": "session0", "name": "startTransaction" }, { "object": "collection0", "name": "insertOne", "arguments": { "session": "session0", "document": { "_id": 1 } }, "expectResult": { "$$unsetOrMatches": { "insertedId": { "$$unsetOrMatches": 1 } } } }, { "object": "session0", "name": "abortTransaction" }, { "object": "session0", "name": "commitTransaction", "expectError": { "errorContains": "Cannot call commitTransaction after calling abortTransaction" } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "insert": "test", "documents": [ { "_id": 1 } ], "ordered": true, "readConcern": { "$$exists": false }, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": true, "autocommit": false, "writeConcern": { "$$exists": false } }, "commandName": "insert", "databaseName": "transaction-tests" } }, { "commandStartedEvent": { "command": { "abortTransaction": 1, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": { "$$exists": false }, "autocommit": false, "writeConcern": { "$$exists": false } }, "commandName": "abortTransaction", "databaseName": "admin" } } ] } ] }, { "description": "multiple commits after empty transaction", "operations": [ { "object": "session0", "name": "startTransaction" }, { "object": "collection0", "name": "insertOne", "arguments": { "session": "session0", "document": { "_id": 1 } }, "expectResult": { "$$unsetOrMatches": { "insertedId": { "$$unsetOrMatches": 1 } } } }, { "object": "session0", "name": "abortTransaction" }, { "object": "session0", "name": "startTransaction" }, { "object": "session0", "name": "commitTransaction" }, { "object": "session0", "name": "commitTransaction" }, { "object": "session0", "name": "startTransaction" }, { "object": "collection0", "name": "insertOne", "arguments": { "session": "session0", "document": { "_id": 1 } }, "expectResult": { "$$unsetOrMatches": { "insertedId": { "$$unsetOrMatches": 1 } } } }, { "object": "session0", "name": "abortTransaction" } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "insert": "test", "documents": [ { "_id": 1 } ], "ordered": true, "readConcern": { "$$exists": false }, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": true, "autocommit": false, "writeConcern": { "$$exists": false } }, "commandName": "insert", "databaseName": "transaction-tests" } }, { "commandStartedEvent": { "command": { "abortTransaction": 1, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": { "$$exists": false }, "autocommit": false, "writeConcern": { "$$exists": false } }, "commandName": "abortTransaction", "databaseName": "admin" } }, { "commandStartedEvent": { "command": { "insert": "test", "documents": [ { "_id": 1 } ], "ordered": true, "readConcern": { "afterClusterTime": { "$$exists": true } }, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "3" }, "startTransaction": true, "autocommit": false, "writeConcern": { "$$exists": false } }, "commandName": "insert", "databaseName": "transaction-tests" } }, { "commandStartedEvent": { "command": { "abortTransaction": 1, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "3" }, "startTransaction": { "$$exists": false }, "autocommit": false, "writeConcern": { "$$exists": false } }, "commandName": "abortTransaction", "databaseName": "admin" } } ] } ], "outcome": [ { "collectionName": "test", "databaseName": "transaction-tests", "documents": [] } ] }, { "description": "reset session state commit", "operations": [ { "object": "session1", "name": "startTransaction" }, { "object": "collection1", "name": "insertOne", "arguments": { "session": "session1", "document": { "_id": 1 } }, "expectResult": { "$$unsetOrMatches": { "insertedId": { "$$unsetOrMatches": 1 } } } }, { "object": "session1", "name": "commitTransaction" }, { "object": "collection1", "name": "insertOne", "arguments": { "session": "session1", "document": { "_id": 2 } }, "expectResult": { "$$unsetOrMatches": { "insertedId": { "$$unsetOrMatches": 2 } } } }, { "object": "session1", "name": "commitTransaction", "expectError": { "errorContains": "no transaction started" } } ], "expectEvents": [ { "client": "client1", "events": [ { "commandStartedEvent": { "command": { "insert": "test", "documents": [ { "_id": 1 } ], "ordered": true, "readConcern": { "$$exists": false }, "lsid": { "$$sessionLsid": "session1" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": true, "autocommit": false, "writeConcern": { "$$exists": false } }, "commandName": "insert", "databaseName": "transaction-tests" } }, { "commandStartedEvent": { "command": { "commitTransaction": 1, "lsid": { "$$sessionLsid": "session1" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": { "$$exists": false }, "autocommit": false, "writeConcern": { "$$exists": false } }, "commandName": "commitTransaction", "databaseName": "admin" } }, { "commandStartedEvent": { "command": { "insert": "test", "documents": [ { "_id": 2 } ], "ordered": true, "readConcern": { "$$exists": false }, "lsid": { "$$sessionLsid": "session1" }, "txnNumber": { "$$exists": false }, "startTransaction": { "$$exists": false }, "autocommit": { "$$exists": false } }, "commandName": "insert", "databaseName": "transaction-tests" } } ] } ], "outcome": [ { "collectionName": "test", "databaseName": "transaction-tests", "documents": [ { "_id": 1 }, { "_id": 2 } ] } ] }, { "description": "reset session state abort", "operations": [ { "object": "session1", "name": "startTransaction" }, { "object": "collection1", "name": "insertOne", "arguments": { "session": "session1", "document": { "_id": 1 } }, "expectResult": { "$$unsetOrMatches": { "insertedId": { "$$unsetOrMatches": 1 } } } }, { "object": "session1", "name": "abortTransaction" }, { "object": "collection1", "name": "insertOne", "arguments": { "session": "session1", "document": { "_id": 2 } }, "expectResult": { "$$unsetOrMatches": { "insertedId": { "$$unsetOrMatches": 2 } } } }, { "object": "session1", "name": "abortTransaction", "expectError": { "errorContains": "no transaction started" } } ], "expectEvents": [ { "client": "client1", "events": [ { "commandStartedEvent": { "command": { "insert": "test", "documents": [ { "_id": 1 } ], "ordered": true, "readConcern": { "$$exists": false }, "lsid": { "$$sessionLsid": "session1" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": true, "autocommit": false, "writeConcern": { "$$exists": false } }, "commandName": "insert", "databaseName": "transaction-tests" } }, { "commandStartedEvent": { "command": { "abortTransaction": 1, "lsid": { "$$sessionLsid": "session1" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": { "$$exists": false }, "autocommit": false, "writeConcern": { "$$exists": false } }, "commandName": "abortTransaction", "databaseName": "admin" } }, { "commandStartedEvent": { "command": { "insert": "test", "documents": [ { "_id": 2 } ], "ordered": true, "readConcern": { "$$exists": false }, "lsid": { "$$sessionLsid": "session1" }, "txnNumber": { "$$exists": false }, "startTransaction": { "$$exists": false }, "autocommit": { "$$exists": false } }, "commandName": "insert", "databaseName": "transaction-tests" } } ] } ], "outcome": [ { "collectionName": "test", "databaseName": "transaction-tests", "documents": [ { "_id": 2 } ] } ] } ] } mongodb-mongo-python-driver-509e9b7/test/transactions/unified/count.json000066400000000000000000000074471462766011000266060ustar00rootroot00000000000000{ "description": "count", "schemaVersion": "1.3", "runOnRequirements": [ { "minServerVersion": "4.0.2", "topologies": [ "replicaset" ] }, { "minServerVersion": "4.1.8", "topologies": [ "sharded", "load-balanced" ] } ], "createEntities": [ { "client": { "id": "client0", "useMultipleMongoses": false, "observeEvents": [ "commandStartedEvent" ] } }, { "database": { "id": "database0", "client": "client0", "databaseName": "transaction-tests" } }, { "collection": { "id": "collection0", "database": "database0", "collectionName": "test" } }, { "session": { "id": "session0", "client": "client0" } } ], "initialData": [ { "collectionName": "test", "databaseName": "transaction-tests", "documents": [ { "_id": 1 }, { "_id": 2 }, { "_id": 3 }, { "_id": 4 } ] } ], "tests": [ { "description": "count", "operations": [ { "object": "session0", "name": "startTransaction" }, { "object": "collection0", "name": "count", "arguments": { "session": "session0", "filter": { "_id": 1 } }, "expectError": { "errorCodeName": "OperationNotSupportedInTransaction", "errorLabelsOmit": [ "TransientTransactionError", "UnknownTransactionCommitResult" ] } }, { "object": "session0", "name": "abortTransaction" } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "count": "test", "query": { "_id": 1 }, "readConcern": { "$$exists": false }, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": true, "autocommit": false, "writeConcern": { "$$exists": false } }, "commandName": "count", "databaseName": "transaction-tests" } }, { "commandStartedEvent": { "command": { "abortTransaction": 1, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": { "$$exists": false }, "autocommit": false, "writeConcern": { "$$exists": false } }, "commandName": "abortTransaction", "databaseName": "admin" } } ] } ], "outcome": [ { "collectionName": "test", "databaseName": "transaction-tests", "documents": [ { "_id": 1 }, { "_id": 2 }, { "_id": 3 }, { "_id": 4 } ] } ] } ] } mongodb-mongo-python-driver-509e9b7/test/transactions/unified/create-collection.json000066400000000000000000000160111462766011000310350ustar00rootroot00000000000000{ "description": "create-collection", "schemaVersion": "1.3", "runOnRequirements": [ { "minServerVersion": "4.3.4", "topologies": [ "replicaset", "sharded", "load-balanced" ] } ], "createEntities": [ { "client": { "id": "client0", "useMultipleMongoses": false, "observeEvents": [ "commandStartedEvent" ] } }, { "database": { "id": "database0", "client": "client0", "databaseName": "transaction-tests" } }, { "collection": { "id": "collection0", "database": "database0", "collectionName": "test" } }, { "session": { "id": "session0", "client": "client0" } } ], "initialData": [ { "collectionName": "test", "databaseName": "transaction-tests", "documents": [] } ], "tests": [ { "description": "explicitly create collection using create command", "operations": [ { "object": "database0", "name": "dropCollection", "arguments": { "collection": "test" } }, { "object": "session0", "name": "startTransaction" }, { "object": "database0", "name": "createCollection", "arguments": { "session": "session0", "collection": "test" } }, { "object": "testRunner", "name": "assertCollectionNotExists", "arguments": { "databaseName": "transaction-tests", "collectionName": "test" } }, { "object": "session0", "name": "commitTransaction" }, { "object": "testRunner", "name": "assertCollectionExists", "arguments": { "databaseName": "transaction-tests", "collectionName": "test" } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "drop": "test", "writeConcern": { "$$exists": false } }, "commandName": "drop", "databaseName": "transaction-tests" } }, { "commandStartedEvent": { "command": { "create": "test", "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": true, "autocommit": false, "writeConcern": { "$$exists": false } }, "commandName": "create", "databaseName": "transaction-tests" } }, { "commandStartedEvent": { "command": { "commitTransaction": 1, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": { "$$exists": false }, "autocommit": false, "writeConcern": { "$$exists": false } }, "commandName": "commitTransaction", "databaseName": "admin" } } ] } ] }, { "description": "implicitly create collection using insert", "operations": [ { "object": "database0", "name": "dropCollection", "arguments": { "collection": "test" } }, { "object": "session0", "name": "startTransaction" }, { "object": "collection0", "name": "insertOne", "arguments": { "session": "session0", "document": { "_id": 1 } }, "expectResult": { "$$unsetOrMatches": { "insertedId": { "$$unsetOrMatches": 1 } } } }, { "object": "testRunner", "name": "assertCollectionNotExists", "arguments": { "databaseName": "transaction-tests", "collectionName": "test" } }, { "object": "session0", "name": "commitTransaction" }, { "object": "testRunner", "name": "assertCollectionExists", "arguments": { "databaseName": "transaction-tests", "collectionName": "test" } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "drop": "test", "writeConcern": { "$$exists": false } }, "commandName": "drop", "databaseName": "transaction-tests" } }, { "commandStartedEvent": { "command": { "insert": "test", "documents": [ { "_id": 1 } ], "ordered": true, "readConcern": { "$$exists": false }, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": true, "autocommit": false, "writeConcern": { "$$exists": false } }, "commandName": "insert", "databaseName": "transaction-tests" } }, { "commandStartedEvent": { "command": { "commitTransaction": 1, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": { "$$exists": false }, "autocommit": false, "writeConcern": { "$$exists": false } }, "commandName": "commitTransaction", "databaseName": "admin" } } ] } ] } ] } mongodb-mongo-python-driver-509e9b7/test/transactions/unified/create-index.json000066400000000000000000000175621462766011000300250ustar00rootroot00000000000000{ "description": "create-index", "schemaVersion": "1.3", "runOnRequirements": [ { "minServerVersion": "4.3.4", "topologies": [ "replicaset", "sharded", "load-balanced" ] } ], "createEntities": [ { "client": { "id": "client0", "useMultipleMongoses": false, "observeEvents": [ "commandStartedEvent" ] } }, { "database": { "id": "database0", "client": "client0", "databaseName": "transaction-tests" } }, { "collection": { "id": "collection0", "database": "database0", "collectionName": "test" } }, { "session": { "id": "session0", "client": "client0" } } ], "initialData": [ { "collectionName": "test", "databaseName": "transaction-tests", "documents": [] } ], "tests": [ { "description": "create index on a non-existing collection", "operations": [ { "object": "database0", "name": "dropCollection", "arguments": { "collection": "test" } }, { "object": "session0", "name": "startTransaction" }, { "object": "collection0", "name": "createIndex", "arguments": { "session": "session0", "name": "t_1", "keys": { "x": 1 } } }, { "object": "testRunner", "name": "assertIndexNotExists", "arguments": { "databaseName": "transaction-tests", "collectionName": "test", "indexName": "t_1" } }, { "object": "session0", "name": "commitTransaction" }, { "object": "testRunner", "name": "assertIndexExists", "arguments": { "databaseName": "transaction-tests", "collectionName": "test", "indexName": "t_1" } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "drop": "test", "writeConcern": { "$$exists": false } }, "commandName": "drop", "databaseName": "transaction-tests" } }, { "commandStartedEvent": { "command": { "createIndexes": "test", "indexes": [ { "name": "t_1", "key": { "x": 1 } } ], "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": true, "autocommit": false, "writeConcern": { "$$exists": false } }, "commandName": "createIndexes", "databaseName": "transaction-tests" } }, { "commandStartedEvent": { "command": { "commitTransaction": 1, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": { "$$exists": false }, "autocommit": false, "writeConcern": { "$$exists": false } }, "commandName": "commitTransaction", "databaseName": "admin" } } ] } ] }, { "description": "create index on a collection created within the same transaction", "operations": [ { "object": "database0", "name": "dropCollection", "arguments": { "collection": "test" } }, { "object": "session0", "name": "startTransaction" }, { "object": "database0", "name": "createCollection", "arguments": { "session": "session0", "collection": "test" } }, { "object": "collection0", "name": "createIndex", "arguments": { "session": "session0", "name": "t_1", "keys": { "x": 1 } } }, { "object": "testRunner", "name": "assertIndexNotExists", "arguments": { "databaseName": "transaction-tests", "collectionName": "test", "indexName": "t_1" } }, { "object": "session0", "name": "commitTransaction" }, { "object": "testRunner", "name": "assertIndexExists", "arguments": { "databaseName": "transaction-tests", "collectionName": "test", "indexName": "t_1" } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "drop": "test", "writeConcern": { "$$exists": false } }, "commandName": "drop", "databaseName": "transaction-tests" } }, { "commandStartedEvent": { "command": { "create": "test", "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": true, "autocommit": false, "writeConcern": { "$$exists": false } }, "commandName": "create", "databaseName": "transaction-tests" } }, { "commandStartedEvent": { "command": { "createIndexes": "test", "indexes": [ { "name": "t_1", "key": { "x": 1 } } ], "lsid": { "$$sessionLsid": "session0" }, "writeConcern": { "$$exists": false } }, "commandName": "createIndexes", "databaseName": "transaction-tests" } }, { "commandStartedEvent": { "command": { "commitTransaction": 1, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": { "$$exists": false }, "autocommit": false, "writeConcern": { "$$exists": false } }, "commandName": "commitTransaction", "databaseName": "admin" } } ] } ] } ] } mongodb-mongo-python-driver-509e9b7/test/transactions/unified/delete.json000066400000000000000000000247051462766011000267140ustar00rootroot00000000000000{ "description": "delete", "schemaVersion": "1.9", "runOnRequirements": [ { "minServerVersion": "4.0", "topologies": [ "replicaset" ] }, { "minServerVersion": "4.1.8", "topologies": [ "sharded", "load-balanced" ] } ], "createEntities": [ { "client": { "id": "client0", "useMultipleMongoses": false, "observeEvents": [ "commandStartedEvent" ] } }, { "database": { "id": "database0", "client": "client0", "databaseName": "transaction-tests" } }, { "collection": { "id": "collection0", "database": "database0", "collectionName": "test" } }, { "session": { "id": "session0", "client": "client0" } } ], "initialData": [ { "collectionName": "test", "databaseName": "transaction-tests", "documents": [ { "_id": 1 }, { "_id": 2 }, { "_id": 3 }, { "_id": 4 }, { "_id": 5 } ] } ], "tests": [ { "description": "delete", "operations": [ { "object": "session0", "name": "startTransaction" }, { "object": "collection0", "name": "deleteOne", "arguments": { "session": "session0", "filter": { "_id": 1 } }, "expectResult": { "deletedCount": 1 } }, { "object": "collection0", "name": "deleteMany", "arguments": { "session": "session0", "filter": { "_id": { "$lte": 3 } } }, "expectResult": { "deletedCount": 2 } }, { "object": "collection0", "name": "deleteOne", "arguments": { "session": "session0", "filter": { "_id": 4 } }, "expectResult": { "deletedCount": 1 } }, { "object": "session0", "name": "commitTransaction" } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "delete": "test", "deletes": [ { "q": { "_id": 1 }, "limit": 1 } ], "ordered": true, "readConcern": { "$$exists": false }, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": true, "autocommit": false, "writeConcern": { "$$exists": false } }, "commandName": "delete", "databaseName": "transaction-tests" } }, { "commandStartedEvent": { "command": { "delete": "test", "deletes": [ { "q": { "_id": { "$lte": 3 } }, "limit": 0 } ], "ordered": true, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": { "$$exists": false }, "autocommit": false, "writeConcern": { "$$exists": false } }, "commandName": "delete", "databaseName": "transaction-tests" } }, { "commandStartedEvent": { "command": { "delete": "test", "deletes": [ { "q": { "_id": 4 }, "limit": 1 } ], "ordered": true, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": { "$$exists": false }, "autocommit": false, "writeConcern": { "$$exists": false } }, "commandName": "delete", "databaseName": "transaction-tests" } }, { "commandStartedEvent": { "command": { "commitTransaction": 1, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": { "$$exists": false }, "autocommit": false, "writeConcern": { "$$exists": false } }, "commandName": "commitTransaction", "databaseName": "admin" } } ] } ], "outcome": [ { "collectionName": "test", "databaseName": "transaction-tests", "documents": [ { "_id": 5 } ] } ] }, { "description": "collection writeConcern ignored for delete", "operations": [ { "object": "testRunner", "name": "createEntities", "arguments": { "entities": [ { "collection": { "id": "collection_wc_majority", "database": "database0", "collectionName": "test", "collectionOptions": { "writeConcern": { "w": "majority" } } } } ] } }, { "object": "session0", "name": "startTransaction", "arguments": { "writeConcern": { "w": "majority" } } }, { "object": "collection_wc_majority", "name": "deleteOne", "arguments": { "session": "session0", "filter": { "_id": 1 } }, "expectResult": { "deletedCount": 1 } }, { "object": "collection_wc_majority", "name": "deleteMany", "arguments": { "session": "session0", "filter": { "_id": { "$lte": 3 } } }, "expectResult": { "deletedCount": 2 } }, { "object": "session0", "name": "commitTransaction" } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "delete": "test", "deletes": [ { "q": { "_id": 1 }, "limit": 1 } ], "ordered": true, "readConcern": { "$$exists": false }, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": true, "autocommit": false, "writeConcern": { "$$exists": false } }, "commandName": "delete", "databaseName": "transaction-tests" } }, { "commandStartedEvent": { "command": { "delete": "test", "deletes": [ { "q": { "_id": { "$lte": 3 } }, "limit": 0 } ], "ordered": true, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": { "$$exists": false }, "autocommit": false, "writeConcern": { "$$exists": false } }, "commandName": "delete", "databaseName": "transaction-tests" } }, { "commandStartedEvent": { "command": { "commitTransaction": 1, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": { "$$exists": false }, "autocommit": false, "writeConcern": { "w": "majority" } }, "commandName": "commitTransaction", "databaseName": "admin" } } ] } ] } ] } mongodb-mongo-python-driver-509e9b7/test/transactions/unified/do-not-retry-read-in-transaction.json000066400000000000000000000046521462766011000336540ustar00rootroot00000000000000{ "description": "do not retry read in a transaction", "schemaVersion": "1.4", "runOnRequirements": [ { "minServerVersion": "4.0.0", "topologies": [ "replicaset" ] }, { "minServerVersion": "4.2.0", "topologies": [ "sharded", "load-balanced" ] } ], "createEntities": [ { "client": { "id": "client0", "useMultipleMongoses": false, "observeEvents": [ "commandStartedEvent" ], "uriOptions": { "retryReads": true } } }, { "database": { "id": "database0", "client": "client0", "databaseName": "retryable-read-in-transaction-test" } }, { "collection": { "id": "collection0", "database": "database0", "collectionName": "coll" } }, { "session": { "id": "session0", "client": "client0" } } ], "tests": [ { "description": "find does not retry in a transaction", "operations": [ { "name": "startTransaction", "object": "session0" }, { "name": "failPoint", "object": "testRunner", "arguments": { "client": "client0", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "find" ], "closeConnection": true } } } }, { "name": "find", "object": "collection0", "arguments": { "filter": {}, "session": "session0" }, "expectError": { "isError": true, "errorLabelsContain": [ "TransientTransactionError" ] } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "find": "coll", "filter": {}, "startTransaction": true }, "commandName": "find", "databaseName": "retryable-read-in-transaction-test" } } ] } ] } ] } mongodb-mongo-python-driver-509e9b7/test/transactions/unified/error-labels-blockConnection.json000066400000000000000000000135631462766011000331530ustar00rootroot00000000000000{ "description": "error-labels-blockConnection", "schemaVersion": "1.3", "runOnRequirements": [ { "minServerVersion": "4.2", "topologies": [ "replicaset", "sharded", "load-balanced" ] } ], "createEntities": [ { "client": { "id": "client0", "useMultipleMongoses": false, "uriOptions": { "socketTimeoutMS": 100 }, "observeEvents": [ "commandStartedEvent" ] } }, { "database": { "id": "database0", "client": "client0", "databaseName": "transaction-tests" } }, { "collection": { "id": "collection0", "database": "database0", "collectionName": "test" } }, { "session": { "id": "session0", "client": "client0" } } ], "initialData": [ { "collectionName": "test", "databaseName": "transaction-tests", "documents": [] } ], "tests": [ { "description": "add RetryableWriteError and UnknownTransactionCommitResult labels to connection errors", "operations": [ { "object": "testRunner", "name": "failPoint", "arguments": { "client": "client0", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 2 }, "data": { "failCommands": [ "commitTransaction" ], "blockConnection": true, "blockTimeMS": 150 } } } }, { "object": "session0", "name": "startTransaction" }, { "object": "collection0", "name": "insertOne", "arguments": { "session": "session0", "document": { "_id": 1 } }, "expectResult": { "$$unsetOrMatches": { "insertedId": { "$$unsetOrMatches": 1 } } } }, { "object": "session0", "name": "commitTransaction", "expectError": { "errorLabelsContain": [ "RetryableWriteError", "UnknownTransactionCommitResult" ], "errorLabelsOmit": [ "TransientTransactionError" ] } }, { "object": "session0", "name": "commitTransaction" } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "insert": "test", "documents": [ { "_id": 1 } ], "ordered": true, "readConcern": { "$$exists": false }, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": true, "autocommit": false, "writeConcern": { "$$exists": false } }, "commandName": "insert", "databaseName": "transaction-tests" } }, { "commandStartedEvent": { "command": { "commitTransaction": 1, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": { "$$exists": false }, "autocommit": false, "writeConcern": { "$$exists": false } }, "commandName": "commitTransaction", "databaseName": "admin" } }, { "commandStartedEvent": { "command": { "commitTransaction": 1, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": { "$$exists": false }, "autocommit": false, "writeConcern": { "w": "majority", "wtimeout": 10000 } }, "commandName": "commitTransaction", "databaseName": "admin" } }, { "commandStartedEvent": { "command": { "commitTransaction": 1, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": { "$$exists": false }, "autocommit": false, "writeConcern": { "w": "majority", "wtimeout": 10000 } }, "commandName": "commitTransaction", "databaseName": "admin" } } ] } ], "outcome": [ { "collectionName": "test", "databaseName": "transaction-tests", "documents": [ { "_id": 1 } ] } ] } ] } mongodb-mongo-python-driver-509e9b7/test/transactions/unified/error-labels-errorLabels.json000066400000000000000000000260201462766011000323050ustar00rootroot00000000000000{ "description": "error-labels-errorLabels", "schemaVersion": "1.4", "runOnRequirements": [ { "minServerVersion": "4.3.1", "serverless": "forbid", "topologies": [ "replicaset", "sharded", "load-balanced" ] } ], "createEntities": [ { "client": { "id": "client0", "useMultipleMongoses": false, "observeEvents": [ "commandStartedEvent" ] } }, { "database": { "id": "database0", "client": "client0", "databaseName": "transaction-tests" } }, { "collection": { "id": "collection0", "database": "database0", "collectionName": "test" } }, { "session": { "id": "session0", "client": "client0" } } ], "initialData": [ { "collectionName": "test", "databaseName": "transaction-tests", "documents": [] } ], "tests": [ { "description": "add RetryableWriteError and UnknownTransactionCommitResult labels to retryable commit errors", "operations": [ { "object": "testRunner", "name": "failPoint", "arguments": { "client": "client0", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 2 }, "data": { "failCommands": [ "commitTransaction" ], "errorCode": 11602, "errorLabels": [ "RetryableWriteError" ] } } } }, { "object": "session0", "name": "startTransaction" }, { "object": "collection0", "name": "insertOne", "arguments": { "session": "session0", "document": { "_id": 1 } }, "expectResult": { "$$unsetOrMatches": { "insertedId": { "$$unsetOrMatches": 1 } } } }, { "object": "session0", "name": "commitTransaction", "expectError": { "errorLabelsContain": [ "RetryableWriteError", "UnknownTransactionCommitResult" ], "errorLabelsOmit": [ "TransientTransactionError" ] } }, { "object": "session0", "name": "commitTransaction" } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "insert": "test", "documents": [ { "_id": 1 } ], "ordered": true, "readConcern": { "$$exists": false }, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": true, "autocommit": false, "writeConcern": { "$$exists": false } }, "commandName": "insert", "databaseName": "transaction-tests" } }, { "commandStartedEvent": { "command": { "commitTransaction": 1, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": { "$$exists": false }, "autocommit": false, "writeConcern": { "$$exists": false } }, "commandName": "commitTransaction", "databaseName": "admin" } }, { "commandStartedEvent": { "command": { "commitTransaction": 1, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": { "$$exists": false }, "autocommit": false, "writeConcern": { "w": "majority", "wtimeout": 10000 } }, "commandName": "commitTransaction", "databaseName": "admin" } }, { "commandStartedEvent": { "command": { "commitTransaction": 1, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": { "$$exists": false }, "autocommit": false, "writeConcern": { "w": "majority", "wtimeout": 10000 } }, "commandName": "commitTransaction", "databaseName": "admin" } } ] } ], "outcome": [ { "collectionName": "test", "databaseName": "transaction-tests", "documents": [ { "_id": 1 } ] } ] }, { "description": "add RetryableWriteError and UnknownTransactionCommitResult labels to writeConcernError ShutdownInProgress", "operations": [ { "object": "testRunner", "name": "failPoint", "arguments": { "client": "client0", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 2 }, "data": { "failCommands": [ "commitTransaction" ], "errorLabels": [ "RetryableWriteError" ], "writeConcernError": { "code": 91, "errmsg": "Replication is being shut down" } } } } }, { "object": "session0", "name": "startTransaction", "arguments": { "writeConcern": { "w": "majority" } } }, { "object": "collection0", "name": "insertOne", "arguments": { "session": "session0", "document": { "_id": 1 } }, "expectResult": { "$$unsetOrMatches": { "insertedId": { "$$unsetOrMatches": 1 } } } }, { "object": "session0", "name": "commitTransaction", "expectError": { "errorLabelsContain": [ "RetryableWriteError", "UnknownTransactionCommitResult" ], "errorLabelsOmit": [ "TransientTransactionError" ] } }, { "object": "session0", "name": "commitTransaction" } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "insert": "test", "documents": [ { "_id": 1 } ], "ordered": true, "readConcern": { "$$exists": false }, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": true, "autocommit": false, "writeConcern": { "$$exists": false } }, "commandName": "insert", "databaseName": "transaction-tests" } }, { "commandStartedEvent": { "command": { "commitTransaction": 1, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": { "$$exists": false }, "autocommit": false, "writeConcern": { "w": "majority" } }, "commandName": "commitTransaction", "databaseName": "admin" } }, { "commandStartedEvent": { "command": { "commitTransaction": 1, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": { "$$exists": false }, "autocommit": false, "writeConcern": { "w": "majority", "wtimeout": 10000 } }, "commandName": "commitTransaction", "databaseName": "admin" } }, { "commandStartedEvent": { "command": { "commitTransaction": 1, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": { "$$exists": false }, "autocommit": false, "writeConcern": { "w": "majority", "wtimeout": 10000 } }, "commandName": "commitTransaction", "databaseName": "admin" } } ] } ], "outcome": [ { "collectionName": "test", "databaseName": "transaction-tests", "documents": [ { "_id": 1 } ] } ] } ] } mongodb-mongo-python-driver-509e9b7/test/transactions/unified/error-labels.json000066400000000000000000001671401462766011000300440ustar00rootroot00000000000000{ "description": "error-labels", "schemaVersion": "1.4", "runOnRequirements": [ { "minServerVersion": "4.0", "topologies": [ "replicaset" ] }, { "minServerVersion": "4.1.8", "serverless": "forbid", "topologies": [ "sharded", "load-balanced" ] } ], "createEntities": [ { "client": { "id": "client0", "useMultipleMongoses": false, "observeEvents": [ "commandStartedEvent" ] } }, { "database": { "id": "database0", "client": "client0", "databaseName": "transaction-tests" } }, { "collection": { "id": "collection0", "database": "database0", "collectionName": "test" } }, { "session": { "id": "session0", "client": "client0" } } ], "initialData": [ { "collectionName": "test", "databaseName": "transaction-tests", "documents": [] } ], "tests": [ { "description": "DuplicateKey errors do not contain transient label", "operations": [ { "object": "session0", "name": "startTransaction" }, { "object": "collection0", "name": "insertMany", "arguments": { "session": "session0", "documents": [ { "_id": 1 }, { "_id": 1 } ] }, "expectError": { "errorLabelsOmit": [ "TransientTransactionError", "UnknownTransactionCommitResult" ], "errorContains": "E11000" } }, { "object": "session0", "name": "abortTransaction" } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "insert": "test", "documents": [ { "_id": 1 }, { "_id": 1 } ], "ordered": true, "readConcern": { "$$exists": false }, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": true, "autocommit": false, "writeConcern": { "$$exists": false } }, "commandName": "insert", "databaseName": "transaction-tests" } }, { "commandStartedEvent": { "command": { "abortTransaction": 1, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": { "$$exists": false }, "autocommit": false, "writeConcern": { "$$exists": false } }, "commandName": "abortTransaction", "databaseName": "admin" } } ] } ], "outcome": [ { "collectionName": "test", "databaseName": "transaction-tests", "documents": [] } ] }, { "description": "NotWritablePrimary errors contain transient label", "operations": [ { "object": "testRunner", "name": "failPoint", "arguments": { "client": "client0", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "insert" ], "errorCode": 10107 } } } }, { "object": "session0", "name": "startTransaction" }, { "object": "collection0", "name": "insertOne", "arguments": { "session": "session0", "document": { "_id": 1 } }, "expectError": { "errorLabelsContain": [ "TransientTransactionError" ], "errorLabelsOmit": [ "RetryableWriteError", "UnknownTransactionCommitResult" ] } }, { "object": "session0", "name": "abortTransaction" } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "insert": "test", "documents": [ { "_id": 1 } ], "ordered": true, "readConcern": { "$$exists": false }, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": true, "autocommit": false, "writeConcern": { "$$exists": false } }, "commandName": "insert", "databaseName": "transaction-tests" } }, { "commandStartedEvent": { "command": { "abortTransaction": 1, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": { "$$exists": false }, "autocommit": false, "writeConcern": { "$$exists": false } }, "commandName": "abortTransaction", "databaseName": "admin" } } ] } ], "outcome": [ { "collectionName": "test", "databaseName": "transaction-tests", "documents": [] } ] }, { "description": "WriteConflict errors contain transient label", "operations": [ { "object": "testRunner", "name": "failPoint", "arguments": { "client": "client0", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "insert" ], "errorCode": 112 } } } }, { "object": "session0", "name": "startTransaction" }, { "object": "collection0", "name": "insertOne", "arguments": { "session": "session0", "document": { "_id": 1 } }, "expectError": { "errorLabelsContain": [ "TransientTransactionError" ], "errorLabelsOmit": [ "RetryableWriteError", "UnknownTransactionCommitResult" ] } }, { "object": "session0", "name": "abortTransaction" } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "insert": "test", "documents": [ { "_id": 1 } ], "ordered": true, "readConcern": { "$$exists": false }, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": true, "autocommit": false, "writeConcern": { "$$exists": false } }, "commandName": "insert", "databaseName": "transaction-tests" } }, { "commandStartedEvent": { "command": { "abortTransaction": 1, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": { "$$exists": false }, "autocommit": false, "writeConcern": { "$$exists": false } }, "commandName": "abortTransaction", "databaseName": "admin" } } ] } ], "outcome": [ { "collectionName": "test", "databaseName": "transaction-tests", "documents": [] } ] }, { "description": "NoSuchTransaction errors contain transient label", "operations": [ { "object": "testRunner", "name": "failPoint", "arguments": { "client": "client0", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "insert" ], "errorCode": 251 } } } }, { "object": "session0", "name": "startTransaction" }, { "object": "collection0", "name": "insertOne", "arguments": { "session": "session0", "document": { "_id": 1 } }, "expectError": { "errorLabelsContain": [ "TransientTransactionError" ], "errorLabelsOmit": [ "RetryableWriteError", "UnknownTransactionCommitResult" ] } }, { "object": "session0", "name": "abortTransaction" } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "insert": "test", "documents": [ { "_id": 1 } ], "ordered": true, "readConcern": { "$$exists": false }, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": true, "autocommit": false, "writeConcern": { "$$exists": false } }, "commandName": "insert", "databaseName": "transaction-tests" } }, { "commandStartedEvent": { "command": { "abortTransaction": 1, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": { "$$exists": false }, "autocommit": false, "writeConcern": { "$$exists": false } }, "commandName": "abortTransaction", "databaseName": "admin" } } ] } ], "outcome": [ { "collectionName": "test", "databaseName": "transaction-tests", "documents": [] } ] }, { "description": "NoSuchTransaction errors on commit contain transient label", "operations": [ { "object": "testRunner", "name": "failPoint", "arguments": { "client": "client0", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "commitTransaction" ], "errorCode": 251 } } } }, { "object": "session0", "name": "startTransaction" }, { "object": "collection0", "name": "insertOne", "arguments": { "session": "session0", "document": { "_id": 1 } }, "expectResult": { "$$unsetOrMatches": { "insertedId": { "$$unsetOrMatches": 1 } } } }, { "object": "session0", "name": "commitTransaction", "expectError": { "errorLabelsContain": [ "TransientTransactionError" ], "errorLabelsOmit": [ "RetryableWriteError", "UnknownTransactionCommitResult" ] } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "insert": "test", "documents": [ { "_id": 1 } ], "ordered": true, "readConcern": { "$$exists": false }, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": true, "autocommit": false, "writeConcern": { "$$exists": false } }, "commandName": "insert", "databaseName": "transaction-tests" } }, { "commandStartedEvent": { "command": { "commitTransaction": 1, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": { "$$exists": false }, "autocommit": false, "writeConcern": { "$$exists": false } }, "commandName": "commitTransaction", "databaseName": "admin" } } ] } ], "outcome": [ { "collectionName": "test", "databaseName": "transaction-tests", "documents": [] } ] }, { "description": "add TransientTransactionError label to connection errors, but do not add RetryableWriteError label", "operations": [ { "object": "testRunner", "name": "failPoint", "arguments": { "client": "client0", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 4 }, "data": { "failCommands": [ "insert", "find", "aggregate", "distinct" ], "closeConnection": true } } } }, { "object": "session0", "name": "startTransaction" }, { "object": "collection0", "name": "insertOne", "arguments": { "session": "session0", "document": { "_id": 1 } }, "expectError": { "errorLabelsContain": [ "TransientTransactionError" ], "errorLabelsOmit": [ "RetryableWriteError", "UnknownTransactionCommitResult" ] } }, { "object": "collection0", "name": "find", "arguments": { "filter": {}, "session": "session0" }, "expectError": { "errorLabelsContain": [ "TransientTransactionError" ], "errorLabelsOmit": [ "RetryableWriteError", "UnknownTransactionCommitResult" ] } }, { "object": "collection0", "name": "aggregate", "arguments": { "pipeline": [ { "$project": { "_id": 1 } } ], "session": "session0" }, "expectError": { "errorLabelsContain": [ "TransientTransactionError" ], "errorLabelsOmit": [ "RetryableWriteError", "UnknownTransactionCommitResult" ] } }, { "object": "collection0", "name": "distinct", "arguments": { "fieldName": "_id", "filter": {}, "session": "session0" }, "expectError": { "errorLabelsContain": [ "TransientTransactionError" ], "errorLabelsOmit": [ "RetryableWriteError", "UnknownTransactionCommitResult" ] } }, { "object": "session0", "name": "abortTransaction" } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "insert": "test", "documents": [ { "_id": 1 } ], "ordered": true, "readConcern": { "$$exists": false }, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": true, "autocommit": false, "writeConcern": { "$$exists": false } }, "commandName": "insert", "databaseName": "transaction-tests" } }, { "commandStartedEvent": { "command": { "find": "test", "readConcern": { "$$exists": false }, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": { "$$exists": false }, "autocommit": false }, "commandName": "find", "databaseName": "transaction-tests" } }, { "commandStartedEvent": { "command": { "aggregate": "test", "pipeline": [ { "$project": { "_id": 1 } } ], "cursor": {}, "readConcern": { "$$exists": false }, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": { "$$exists": false }, "autocommit": false }, "commandName": "aggregate", "databaseName": "transaction-tests" } }, { "commandStartedEvent": { "command": { "distinct": "test", "key": "_id", "lsid": { "$$sessionLsid": "session0" }, "readConcern": { "$$exists": false }, "txnNumber": { "$numberLong": "1" }, "startTransaction": { "$$exists": false }, "autocommit": false }, "commandName": "distinct", "databaseName": "transaction-tests" } }, { "commandStartedEvent": { "command": { "abortTransaction": 1, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": { "$$exists": false }, "autocommit": false, "writeConcern": { "$$exists": false } }, "commandName": "abortTransaction", "databaseName": "admin" } } ] } ], "outcome": [ { "collectionName": "test", "databaseName": "transaction-tests", "documents": [] } ] }, { "description": "add RetryableWriteError and UnknownTransactionCommitResult labels to connection errors", "operations": [ { "object": "testRunner", "name": "failPoint", "arguments": { "client": "client0", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 2 }, "data": { "failCommands": [ "commitTransaction" ], "closeConnection": true } } } }, { "object": "session0", "name": "startTransaction" }, { "object": "collection0", "name": "insertOne", "arguments": { "session": "session0", "document": { "_id": 1 } }, "expectResult": { "$$unsetOrMatches": { "insertedId": { "$$unsetOrMatches": 1 } } } }, { "object": "session0", "name": "commitTransaction", "expectError": { "errorLabelsContain": [ "RetryableWriteError", "UnknownTransactionCommitResult" ], "errorLabelsOmit": [ "TransientTransactionError" ] } }, { "object": "session0", "name": "commitTransaction" } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "insert": "test", "documents": [ { "_id": 1 } ], "ordered": true, "readConcern": { "$$exists": false }, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": true, "autocommit": false, "writeConcern": { "$$exists": false } }, "commandName": "insert", "databaseName": "transaction-tests" } }, { "commandStartedEvent": { "command": { "commitTransaction": 1, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": { "$$exists": false }, "autocommit": false, "writeConcern": { "$$exists": false } }, "commandName": "commitTransaction", "databaseName": "admin" } }, { "commandStartedEvent": { "command": { "commitTransaction": 1, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": { "$$exists": false }, "autocommit": false, "writeConcern": { "w": "majority", "wtimeout": 10000 } }, "commandName": "commitTransaction", "databaseName": "admin" } }, { "commandStartedEvent": { "command": { "commitTransaction": 1, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": { "$$exists": false }, "autocommit": false, "writeConcern": { "w": "majority", "wtimeout": 10000 } }, "commandName": "commitTransaction", "databaseName": "admin" } } ] } ], "outcome": [ { "collectionName": "test", "databaseName": "transaction-tests", "documents": [ { "_id": 1 } ] } ] }, { "description": "do not add RetryableWriteError label to writeConcernError ShutdownInProgress that occurs within transaction", "operations": [ { "object": "testRunner", "name": "failPoint", "arguments": { "client": "client0", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "insert" ], "writeConcernError": { "code": 91, "errmsg": "Replication is being shut down" } } } } }, { "object": "session0", "name": "startTransaction", "arguments": { "writeConcern": { "w": "majority" } } }, { "object": "collection0", "name": "insertOne", "arguments": { "session": "session0", "document": { "_id": 1 } }, "expectError": { "errorLabelsOmit": [ "RetryableWriteError", "TransientTransactionError", "UnknownTransactionCommitResult" ] } }, { "object": "session0", "name": "abortTransaction" } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "insert": "test", "documents": [ { "_id": 1 } ], "ordered": true, "readConcern": { "$$exists": false }, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": true, "autocommit": false }, "commandName": "insert", "databaseName": "transaction-tests" } }, { "commandStartedEvent": { "command": { "abortTransaction": 1, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": { "$$exists": false }, "autocommit": false }, "commandName": "abortTransaction", "databaseName": "admin" } } ] } ], "outcome": [ { "collectionName": "test", "databaseName": "transaction-tests", "documents": [] } ] }, { "description": "add UnknownTransactionCommitResult label to writeConcernError WriteConcernFailed", "operations": [ { "object": "testRunner", "name": "failPoint", "arguments": { "client": "client0", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "commitTransaction" ], "writeConcernError": { "code": 64, "errmsg": "multiple errors reported" } } } } }, { "object": "session0", "name": "startTransaction", "arguments": { "writeConcern": { "w": "majority" } } }, { "object": "collection0", "name": "insertOne", "arguments": { "session": "session0", "document": { "_id": 1 } }, "expectResult": { "$$unsetOrMatches": { "insertedId": { "$$unsetOrMatches": 1 } } } }, { "object": "session0", "name": "commitTransaction", "expectError": { "errorLabelsContain": [ "UnknownTransactionCommitResult" ], "errorLabelsOmit": [ "RetryableWriteError", "TransientTransactionError" ] } }, { "object": "session0", "name": "commitTransaction" } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "insert": "test", "documents": [ { "_id": 1 } ], "ordered": true, "readConcern": { "$$exists": false }, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": true, "autocommit": false, "writeConcern": { "$$exists": false } }, "commandName": "insert", "databaseName": "transaction-tests" } }, { "commandStartedEvent": { "command": { "commitTransaction": 1, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": { "$$exists": false }, "autocommit": false, "writeConcern": { "w": "majority" } }, "commandName": "commitTransaction", "databaseName": "admin" } }, { "commandStartedEvent": { "command": { "commitTransaction": 1, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": { "$$exists": false }, "autocommit": false, "writeConcern": { "w": "majority", "wtimeout": 10000 } }, "commandName": "commitTransaction", "databaseName": "admin" } } ] } ], "outcome": [ { "collectionName": "test", "databaseName": "transaction-tests", "documents": [ { "_id": 1 } ] } ] }, { "description": "add UnknownTransactionCommitResult label to writeConcernError WriteConcernFailed with wtimeout", "operations": [ { "object": "testRunner", "name": "failPoint", "arguments": { "client": "client0", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "commitTransaction" ], "writeConcernError": { "code": 64, "codeName": "WriteConcernFailed", "errmsg": "waiting for replication timed out", "errInfo": { "wtimeout": true } } } } } }, { "object": "session0", "name": "startTransaction", "arguments": { "writeConcern": { "w": "majority" } } }, { "object": "collection0", "name": "insertOne", "arguments": { "session": "session0", "document": { "_id": 1 } }, "expectResult": { "$$unsetOrMatches": { "insertedId": { "$$unsetOrMatches": 1 } } } }, { "object": "session0", "name": "commitTransaction", "expectError": { "errorLabelsContain": [ "UnknownTransactionCommitResult" ], "errorLabelsOmit": [ "RetryableWriteError", "TransientTransactionError" ] } }, { "object": "session0", "name": "commitTransaction" } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "insert": "test", "documents": [ { "_id": 1 } ], "ordered": true, "readConcern": { "$$exists": false }, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": true, "autocommit": false, "writeConcern": { "$$exists": false } }, "commandName": "insert", "databaseName": "transaction-tests" } }, { "commandStartedEvent": { "command": { "commitTransaction": 1, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": { "$$exists": false }, "autocommit": false, "writeConcern": { "w": "majority" } }, "commandName": "commitTransaction", "databaseName": "admin" } }, { "commandStartedEvent": { "command": { "commitTransaction": 1, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": { "$$exists": false }, "autocommit": false, "writeConcern": { "w": "majority", "wtimeout": 10000 } }, "commandName": "commitTransaction", "databaseName": "admin" } } ] } ], "outcome": [ { "collectionName": "test", "databaseName": "transaction-tests", "documents": [ { "_id": 1 } ] } ] }, { "description": "omit UnknownTransactionCommitResult label from writeConcernError UnsatisfiableWriteConcern", "operations": [ { "object": "testRunner", "name": "failPoint", "arguments": { "client": "client0", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "commitTransaction" ], "writeConcernError": { "code": 100, "errmsg": "Not enough data-bearing nodes" } } } } }, { "object": "session0", "name": "startTransaction", "arguments": { "writeConcern": { "w": "majority" } } }, { "object": "collection0", "name": "insertOne", "arguments": { "session": "session0", "document": { "_id": 1 } }, "expectResult": { "$$unsetOrMatches": { "insertedId": { "$$unsetOrMatches": 1 } } } }, { "object": "session0", "name": "commitTransaction", "expectError": { "errorLabelsOmit": [ "RetryableWriteError", "TransientTransactionError", "UnknownTransactionCommitResult" ] } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "insert": "test", "documents": [ { "_id": 1 } ], "ordered": true, "readConcern": { "$$exists": false }, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": true, "autocommit": false, "writeConcern": { "$$exists": false } }, "commandName": "insert", "databaseName": "transaction-tests" } }, { "commandStartedEvent": { "command": { "commitTransaction": 1, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": { "$$exists": false }, "autocommit": false, "writeConcern": { "w": "majority" } }, "commandName": "commitTransaction", "databaseName": "admin" } } ] } ], "outcome": [ { "collectionName": "test", "databaseName": "transaction-tests", "documents": [ { "_id": 1 } ] } ] }, { "description": "omit UnknownTransactionCommitResult label from writeConcernError UnknownReplWriteConcern", "operations": [ { "object": "testRunner", "name": "failPoint", "arguments": { "client": "client0", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "commitTransaction" ], "writeConcernError": { "code": 79, "errmsg": "No write concern mode named 'blah' found in replica set configuration" } } } } }, { "object": "session0", "name": "startTransaction", "arguments": { "writeConcern": { "w": "majority" } } }, { "object": "collection0", "name": "insertOne", "arguments": { "session": "session0", "document": { "_id": 1 } }, "expectResult": { "$$unsetOrMatches": { "insertedId": { "$$unsetOrMatches": 1 } } } }, { "object": "session0", "name": "commitTransaction", "expectError": { "errorLabelsOmit": [ "RetryableWriteConcern", "TransientTransactionError", "UnknownTransactionCommitResult" ] } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "insert": "test", "documents": [ { "_id": 1 } ], "ordered": true, "readConcern": { "$$exists": false }, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": true, "autocommit": false, "writeConcern": { "$$exists": false } }, "commandName": "insert", "databaseName": "transaction-tests" } }, { "commandStartedEvent": { "command": { "commitTransaction": 1, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": { "$$exists": false }, "autocommit": false, "writeConcern": { "w": "majority" } }, "commandName": "commitTransaction", "databaseName": "admin" } } ] } ], "outcome": [ { "collectionName": "test", "databaseName": "transaction-tests", "documents": [ { "_id": 1 } ] } ] }, { "description": "do not add UnknownTransactionCommitResult label to MaxTimeMSExpired inside transactions", "operations": [ { "object": "testRunner", "name": "failPoint", "arguments": { "client": "client0", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "aggregate" ], "errorCode": 50 } } } }, { "object": "session0", "name": "startTransaction" }, { "object": "collection0", "name": "insertOne", "arguments": { "session": "session0", "document": { "_id": 1 } }, "expectResult": { "$$unsetOrMatches": { "insertedId": { "$$unsetOrMatches": 1 } } } }, { "object": "collection0", "name": "aggregate", "arguments": { "pipeline": [ { "$project": { "_id": 1 } } ], "maxTimeMS": 60000, "session": "session0" }, "expectError": { "errorLabelsOmit": [ "RetryableWriteError", "UnknownTransactionCommitResult", "TransientTransactionError" ] } }, { "object": "session0", "name": "abortTransaction" } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "insert": "test", "documents": [ { "_id": 1 } ], "ordered": true, "readConcern": { "$$exists": false }, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": true, "autocommit": false, "writeConcern": { "$$exists": false } }, "commandName": "insert", "databaseName": "transaction-tests" } }, { "commandStartedEvent": { "command": { "aggregate": "test", "pipeline": [ { "$project": { "_id": 1 } } ], "cursor": {}, "readConcern": { "$$exists": false }, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "autocommit": false, "maxTimeMS": 60000 }, "commandName": "aggregate", "databaseName": "transaction-tests" } }, { "commandStartedEvent": { "command": { "abortTransaction": 1, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": { "$$exists": false }, "autocommit": false, "writeConcern": { "$$exists": false } }, "commandName": "abortTransaction", "databaseName": "admin" } } ] } ], "outcome": [ { "collectionName": "test", "databaseName": "transaction-tests", "documents": [] } ] }, { "description": "add UnknownTransactionCommitResult label to MaxTimeMSExpired", "operations": [ { "object": "testRunner", "name": "failPoint", "arguments": { "client": "client0", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "commitTransaction" ], "errorCode": 50 } } } }, { "object": "session0", "name": "startTransaction", "arguments": { "writeConcern": { "w": "majority" }, "maxCommitTimeMS": 60000 } }, { "object": "collection0", "name": "insertOne", "arguments": { "session": "session0", "document": { "_id": 1 } }, "expectResult": { "$$unsetOrMatches": { "insertedId": { "$$unsetOrMatches": 1 } } } }, { "object": "session0", "name": "commitTransaction", "expectError": { "errorLabelsContain": [ "UnknownTransactionCommitResult" ], "errorLabelsOmit": [ "RetryableWriteError", "TransientTransactionError" ] } }, { "object": "session0", "name": "commitTransaction" } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "insert": "test", "documents": [ { "_id": 1 } ], "ordered": true, "readConcern": { "$$exists": false }, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": true, "autocommit": false, "writeConcern": { "$$exists": false } }, "commandName": "insert", "databaseName": "transaction-tests" } }, { "commandStartedEvent": { "command": { "commitTransaction": 1, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": { "$$exists": false }, "autocommit": false, "writeConcern": { "w": "majority" }, "maxTimeMS": 60000 }, "commandName": "commitTransaction", "databaseName": "admin" } }, { "commandStartedEvent": { "command": { "commitTransaction": 1, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": { "$$exists": false }, "autocommit": false, "writeConcern": { "w": "majority", "wtimeout": 10000 }, "maxTimeMS": 60000 }, "commandName": "commitTransaction", "databaseName": "admin" } } ] } ], "outcome": [ { "collectionName": "test", "databaseName": "transaction-tests", "documents": [ { "_id": 1 } ] } ] }, { "description": "add UnknownTransactionCommitResult label to writeConcernError MaxTimeMSExpired", "operations": [ { "object": "testRunner", "name": "failPoint", "arguments": { "client": "client0", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "commitTransaction" ], "writeConcernError": { "code": 50, "errmsg": "operation exceeded time limit" } } } } }, { "object": "session0", "name": "startTransaction", "arguments": { "writeConcern": { "w": "majority" }, "maxCommitTimeMS": 60000 } }, { "object": "collection0", "name": "insertOne", "arguments": { "session": "session0", "document": { "_id": 1 } }, "expectResult": { "$$unsetOrMatches": { "insertedId": { "$$unsetOrMatches": 1 } } } }, { "object": "session0", "name": "commitTransaction", "expectError": { "errorLabelsContain": [ "UnknownTransactionCommitResult" ], "errorLabelsOmit": [ "RetryableWriteError", "TransientTransactionError" ] } }, { "object": "session0", "name": "commitTransaction" } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "insert": "test", "documents": [ { "_id": 1 } ], "ordered": true, "readConcern": { "$$exists": false }, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": true, "autocommit": false, "writeConcern": { "$$exists": false } }, "commandName": "insert", "databaseName": "transaction-tests" } }, { "commandStartedEvent": { "command": { "commitTransaction": 1, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": { "$$exists": false }, "autocommit": false, "writeConcern": { "w": "majority" }, "maxTimeMS": 60000 }, "commandName": "commitTransaction", "databaseName": "admin" } }, { "commandStartedEvent": { "command": { "commitTransaction": 1, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": { "$$exists": false }, "autocommit": false, "writeConcern": { "w": "majority", "wtimeout": 10000 }, "maxTimeMS": 60000 }, "commandName": "commitTransaction", "databaseName": "admin" } } ] } ], "outcome": [ { "collectionName": "test", "databaseName": "transaction-tests", "documents": [ { "_id": 1 } ] } ] } ] } mongodb-mongo-python-driver-509e9b7/test/transactions/unified/errors-client.json000066400000000000000000000056141462766011000302400ustar00rootroot00000000000000{ "description": "errors-client", "schemaVersion": "1.3", "runOnRequirements": [ { "minServerVersion": "4.0", "topologies": [ "replicaset" ] }, { "minServerVersion": "4.1.8", "topologies": [ "sharded", "load-balanced" ] } ], "createEntities": [ { "client": { "id": "client0", "useMultipleMongoses": false, "observeEvents": [ "commandStartedEvent" ] } }, { "database": { "id": "database0", "client": "client0", "databaseName": "transaction-tests" } }, { "collection": { "id": "collection0", "database": "database0", "collectionName": "test" } }, { "session": { "id": "session0", "client": "client0" } } ], "initialData": [ { "collectionName": "test", "databaseName": "transaction-tests", "documents": [] } ], "tests": [ { "description": "Client side error in command starting transaction", "operations": [ { "object": "session0", "name": "startTransaction" }, { "object": "collection0", "name": "updateOne", "arguments": { "session": "session0", "filter": { "_id": 1 }, "update": { "x": 1 } }, "expectError": { "isError": true } }, { "object": "testRunner", "name": "assertSessionTransactionState", "arguments": { "session": "session0", "state": "starting" } } ] }, { "description": "Client side error when transaction is in progress", "operations": [ { "object": "session0", "name": "startTransaction" }, { "object": "collection0", "name": "insertOne", "arguments": { "session": "session0", "document": { "_id": 1 } }, "expectResult": { "$$unsetOrMatches": { "insertedId": { "$$unsetOrMatches": 1 } } } }, { "object": "collection0", "name": "updateOne", "arguments": { "session": "session0", "filter": { "_id": 1 }, "update": { "x": 1 } }, "expectError": { "isError": true } }, { "object": "testRunner", "name": "assertSessionTransactionState", "arguments": { "session": "session0", "state": "in_progress" } } ] } ] } mongodb-mongo-python-driver-509e9b7/test/transactions/unified/errors.json000066400000000000000000000143041462766011000267600ustar00rootroot00000000000000{ "description": "errors", "schemaVersion": "1.3", "runOnRequirements": [ { "minServerVersion": "4.0", "topologies": [ "replicaset" ] }, { "minServerVersion": "4.1.8", "topologies": [ "sharded", "load-balanced" ] } ], "createEntities": [ { "client": { "id": "client0", "useMultipleMongoses": false, "observeEvents": [ "commandStartedEvent" ] } }, { "database": { "id": "database0", "client": "client0", "databaseName": "transaction-tests" } }, { "collection": { "id": "collection0", "database": "database0", "collectionName": "test" } }, { "session": { "id": "session0", "client": "client0" } }, { "session": { "id": "session1", "client": "client0" } } ], "initialData": [ { "collectionName": "test", "databaseName": "transaction-tests", "documents": [] } ], "tests": [ { "description": "start insert start", "operations": [ { "object": "session0", "name": "startTransaction" }, { "object": "collection0", "name": "insertOne", "arguments": { "session": "session0", "document": { "_id": 1 } }, "expectResult": { "$$unsetOrMatches": { "insertedId": { "$$unsetOrMatches": 1 } } } }, { "object": "session0", "name": "startTransaction", "expectError": { "isClientError": true, "errorContains": "transaction already in progress" } }, { "object": "session0", "name": "commitTransaction" } ] }, { "description": "start twice", "operations": [ { "object": "session0", "name": "startTransaction" }, { "object": "session0", "name": "startTransaction", "expectError": { "isClientError": true, "errorContains": "transaction already in progress" } } ] }, { "description": "commit and start twice", "operations": [ { "object": "session0", "name": "startTransaction" }, { "object": "collection0", "name": "insertOne", "arguments": { "session": "session0", "document": { "_id": 1 } }, "expectResult": { "$$unsetOrMatches": { "insertedId": { "$$unsetOrMatches": 1 } } } }, { "object": "session0", "name": "commitTransaction" }, { "object": "session0", "name": "startTransaction" }, { "object": "session0", "name": "startTransaction", "expectError": { "isClientError": true, "errorContains": "transaction already in progress" } } ] }, { "description": "write conflict commit", "operations": [ { "object": "session0", "name": "startTransaction" }, { "object": "collection0", "name": "insertOne", "arguments": { "session": "session0", "document": { "_id": 1 } }, "expectResult": { "$$unsetOrMatches": { "insertedId": { "$$unsetOrMatches": 1 } } } }, { "object": "session1", "name": "startTransaction" }, { "object": "collection0", "name": "insertOne", "arguments": { "session": "session1", "document": { "_id": 1 } }, "expectError": { "errorCodeName": "WriteConflict", "errorLabelsContain": [ "TransientTransactionError" ], "errorLabelsOmit": [ "UnknownTransactionCommitResult" ] } }, { "object": "session0", "name": "commitTransaction" }, { "object": "session1", "name": "commitTransaction", "expectError": { "errorCodeName": "NoSuchTransaction", "errorLabelsContain": [ "TransientTransactionError" ], "errorLabelsOmit": [ "UnknownTransactionCommitResult" ] } } ] }, { "description": "write conflict abort", "operations": [ { "object": "session0", "name": "startTransaction" }, { "object": "collection0", "name": "insertOne", "arguments": { "session": "session0", "document": { "_id": 1 } }, "expectResult": { "$$unsetOrMatches": { "insertedId": { "$$unsetOrMatches": 1 } } } }, { "object": "session1", "name": "startTransaction" }, { "object": "collection0", "name": "insertOne", "arguments": { "session": "session1", "document": { "_id": 1 } }, "expectError": { "errorCodeName": "WriteConflict", "errorLabelsContain": [ "TransientTransactionError" ], "errorLabelsOmit": [ "UnknownTransactionCommitResult" ] } }, { "object": "session0", "name": "commitTransaction" }, { "object": "session1", "name": "abortTransaction" } ] } ] } mongodb-mongo-python-driver-509e9b7/test/transactions/unified/findOneAndDelete.json000066400000000000000000000172721462766011000306030ustar00rootroot00000000000000{ "description": "findOneAndDelete", "schemaVersion": "1.9", "runOnRequirements": [ { "minServerVersion": "4.0", "topologies": [ "replicaset" ] }, { "minServerVersion": "4.1.8", "topologies": [ "sharded", "load-balanced" ] } ], "createEntities": [ { "client": { "id": "client0", "useMultipleMongoses": false, "observeEvents": [ "commandStartedEvent" ] } }, { "database": { "id": "database0", "client": "client0", "databaseName": "transaction-tests" } }, { "collection": { "id": "collection0", "database": "database0", "collectionName": "test" } }, { "session": { "id": "session0", "client": "client0" } } ], "initialData": [ { "collectionName": "test", "databaseName": "transaction-tests", "documents": [ { "_id": 1 }, { "_id": 2 }, { "_id": 3 } ] } ], "tests": [ { "description": "findOneAndDelete", "operations": [ { "object": "session0", "name": "startTransaction" }, { "object": "collection0", "name": "findOneAndDelete", "arguments": { "session": "session0", "filter": { "_id": 3 } }, "expectResult": { "_id": 3 } }, { "object": "collection0", "name": "findOneAndDelete", "arguments": { "session": "session0", "filter": { "_id": 4 } } }, { "object": "session0", "name": "commitTransaction" } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "findAndModify": "test", "query": { "_id": 3 }, "remove": true, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": true, "autocommit": false, "readConcern": { "$$exists": false }, "writeConcern": { "$$exists": false } }, "commandName": "findAndModify", "databaseName": "transaction-tests" } }, { "commandStartedEvent": { "command": { "findAndModify": "test", "query": { "_id": 4 }, "remove": true, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": { "$$exists": false }, "autocommit": false, "readConcern": { "$$exists": false }, "writeConcern": { "$$exists": false } }, "commandName": "findAndModify", "databaseName": "transaction-tests" } }, { "commandStartedEvent": { "command": { "commitTransaction": 1, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": { "$$exists": false }, "autocommit": false, "readConcern": { "$$exists": false }, "writeConcern": { "$$exists": false } }, "commandName": "commitTransaction", "databaseName": "admin" } } ] } ], "outcome": [ { "collectionName": "test", "databaseName": "transaction-tests", "documents": [ { "_id": 1 }, { "_id": 2 } ] } ] }, { "description": "collection writeConcern ignored for findOneAndDelete", "operations": [ { "object": "testRunner", "name": "createEntities", "arguments": { "entities": [ { "collection": { "id": "collection_wc_majority", "database": "database0", "collectionName": "test", "collectionOptions": { "writeConcern": { "w": "majority" } } } } ] } }, { "object": "session0", "name": "startTransaction", "arguments": { "writeConcern": { "w": "majority" } } }, { "object": "collection_wc_majority", "name": "findOneAndDelete", "arguments": { "session": "session0", "filter": { "_id": 3 } }, "expectResult": { "_id": 3 } }, { "object": "session0", "name": "commitTransaction" } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "findAndModify": "test", "query": { "_id": 3 }, "remove": true, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": true, "autocommit": false, "readConcern": { "$$exists": false }, "writeConcern": { "$$exists": false } }, "commandName": "findAndModify", "databaseName": "transaction-tests" } }, { "commandStartedEvent": { "command": { "commitTransaction": 1, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": { "$$exists": false }, "autocommit": false, "readConcern": { "$$exists": false }, "writeConcern": { "w": "majority" } }, "commandName": "commitTransaction", "databaseName": "admin" } } ] } ] } ] } mongodb-mongo-python-driver-509e9b7/test/transactions/unified/findOneAndReplace.json000066400000000000000000000210011462766011000307350ustar00rootroot00000000000000{ "description": "findOneAndReplace", "schemaVersion": "1.9", "runOnRequirements": [ { "minServerVersion": "4.0", "topologies": [ "replicaset" ] }, { "minServerVersion": "4.1.8", "topologies": [ "sharded", "load-balanced" ] } ], "createEntities": [ { "client": { "id": "client0", "useMultipleMongoses": false, "observeEvents": [ "commandStartedEvent" ] } }, { "database": { "id": "database0", "client": "client0", "databaseName": "transaction-tests" } }, { "collection": { "id": "collection0", "database": "database0", "collectionName": "test" } }, { "session": { "id": "session0", "client": "client0" } } ], "initialData": [ { "collectionName": "test", "databaseName": "transaction-tests", "documents": [ { "_id": 1 }, { "_id": 2 }, { "_id": 3 } ] } ], "tests": [ { "description": "findOneAndReplace", "operations": [ { "object": "session0", "name": "startTransaction" }, { "object": "collection0", "name": "findOneAndReplace", "arguments": { "session": "session0", "filter": { "_id": 3 }, "replacement": { "x": 1 }, "returnDocument": "Before" }, "expectResult": { "_id": 3 } }, { "object": "collection0", "name": "findOneAndReplace", "arguments": { "session": "session0", "filter": { "_id": 4 }, "replacement": { "x": 1 }, "upsert": true, "returnDocument": "After" }, "expectResult": { "_id": 4, "x": 1 } }, { "object": "session0", "name": "commitTransaction" } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "findAndModify": "test", "query": { "_id": 3 }, "update": { "x": 1 }, "new": false, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": true, "autocommit": false, "readConcern": { "$$exists": false }, "writeConcern": { "$$exists": false } }, "commandName": "findAndModify", "databaseName": "transaction-tests" } }, { "commandStartedEvent": { "command": { "findAndModify": "test", "query": { "_id": 4 }, "update": { "x": 1 }, "new": true, "upsert": true, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": { "$$exists": false }, "autocommit": false, "readConcern": { "$$exists": false }, "writeConcern": { "$$exists": false } }, "commandName": "findAndModify", "databaseName": "transaction-tests" } }, { "commandStartedEvent": { "command": { "commitTransaction": 1, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": { "$$exists": false }, "autocommit": false, "readConcern": { "$$exists": false }, "writeConcern": { "$$exists": false } }, "commandName": "commitTransaction", "databaseName": "admin" } } ] } ], "outcome": [ { "collectionName": "test", "databaseName": "transaction-tests", "documents": [ { "_id": 1 }, { "_id": 2 }, { "_id": 3, "x": 1 }, { "_id": 4, "x": 1 } ] } ] }, { "description": "collection writeConcern ignored for findOneAndReplace", "operations": [ { "object": "testRunner", "name": "createEntities", "arguments": { "entities": [ { "collection": { "id": "collection_wc_majority", "database": "database0", "collectionName": "test", "collectionOptions": { "writeConcern": { "w": "majority" } } } } ] } }, { "object": "session0", "name": "startTransaction", "arguments": { "writeConcern": { "w": "majority" } } }, { "object": "collection_wc_majority", "name": "findOneAndReplace", "arguments": { "session": "session0", "filter": { "_id": 3 }, "replacement": { "x": 1 }, "returnDocument": "Before" }, "expectResult": { "_id": 3 } }, { "object": "session0", "name": "commitTransaction" } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "findAndModify": "test", "query": { "_id": 3 }, "update": { "x": 1 }, "new": false, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": true, "autocommit": false, "readConcern": { "$$exists": false }, "writeConcern": { "$$exists": false } }, "commandName": "findAndModify", "databaseName": "transaction-tests" } }, { "commandStartedEvent": { "command": { "commitTransaction": 1, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": { "$$exists": false }, "autocommit": false, "readConcern": { "$$exists": false }, "writeConcern": { "w": "majority" } }, "commandName": "commitTransaction", "databaseName": "admin" } } ] } ] } ] } mongodb-mongo-python-driver-509e9b7/test/transactions/unified/findOneAndUpdate.json000066400000000000000000000330751462766011000306220ustar00rootroot00000000000000{ "description": "findOneAndUpdate", "schemaVersion": "1.9", "runOnRequirements": [ { "minServerVersion": "4.0", "topologies": [ "replicaset" ] }, { "minServerVersion": "4.1.8", "topologies": [ "sharded", "load-balanced" ] } ], "createEntities": [ { "client": { "id": "client0", "useMultipleMongoses": false, "observeEvents": [ "commandStartedEvent" ] } }, { "database": { "id": "database0", "client": "client0", "databaseName": "transaction-tests" } }, { "collection": { "id": "collection0", "database": "database0", "collectionName": "test" } }, { "session": { "id": "session0", "client": "client0" } } ], "initialData": [ { "collectionName": "test", "databaseName": "transaction-tests", "documents": [ { "_id": 1 }, { "_id": 2 }, { "_id": 3 } ] } ], "tests": [ { "description": "findOneAndUpdate", "operations": [ { "object": "session0", "name": "startTransaction" }, { "object": "collection0", "name": "findOneAndUpdate", "arguments": { "session": "session0", "filter": { "_id": 3 }, "update": { "$inc": { "x": 1 } }, "returnDocument": "Before" }, "expectResult": { "_id": 3 } }, { "object": "collection0", "name": "findOneAndUpdate", "arguments": { "session": "session0", "filter": { "_id": 4 }, "update": { "$inc": { "x": 1 } }, "upsert": true, "returnDocument": "After" }, "expectResult": { "_id": 4, "x": 1 } }, { "object": "session0", "name": "commitTransaction" }, { "object": "session0", "name": "startTransaction" }, { "object": "collection0", "name": "findOneAndUpdate", "arguments": { "session": "session0", "filter": { "_id": 3 }, "update": { "$inc": { "x": 1 } }, "returnDocument": "Before" }, "expectResult": { "_id": 3, "x": 1 } }, { "object": "session0", "name": "commitTransaction" }, { "object": "session0", "name": "startTransaction" }, { "object": "collection0", "name": "findOneAndUpdate", "arguments": { "session": "session0", "filter": { "_id": 3 }, "update": { "$inc": { "x": 1 } }, "returnDocument": "Before" }, "expectResult": { "_id": 3, "x": 2 } }, { "object": "session0", "name": "abortTransaction" } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "findAndModify": "test", "query": { "_id": 3 }, "update": { "$inc": { "x": 1 } }, "new": false, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": true, "autocommit": false, "readConcern": { "$$exists": false }, "writeConcern": { "$$exists": false } }, "commandName": "findAndModify", "databaseName": "transaction-tests" } }, { "commandStartedEvent": { "command": { "findAndModify": "test", "query": { "_id": 4 }, "update": { "$inc": { "x": 1 } }, "new": true, "upsert": true, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": { "$$exists": false }, "autocommit": false, "readConcern": { "$$exists": false }, "writeConcern": { "$$exists": false } }, "commandName": "findAndModify", "databaseName": "transaction-tests" } }, { "commandStartedEvent": { "command": { "commitTransaction": 1, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": { "$$exists": false }, "autocommit": false, "readConcern": { "$$exists": false }, "writeConcern": { "$$exists": false } }, "commandName": "commitTransaction", "databaseName": "admin" } }, { "commandStartedEvent": { "command": { "findAndModify": "test", "query": { "_id": 3 }, "update": { "$inc": { "x": 1 } }, "new": false, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "2" }, "startTransaction": true, "autocommit": false, "readConcern": { "afterClusterTime": { "$$exists": true } }, "writeConcern": { "$$exists": false } }, "commandName": "findAndModify", "databaseName": "transaction-tests" } }, { "commandStartedEvent": { "command": { "commitTransaction": 1, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "2" }, "startTransaction": { "$$exists": false }, "autocommit": false, "readConcern": { "$$exists": false }, "writeConcern": { "$$exists": false } }, "commandName": "commitTransaction", "databaseName": "admin" } }, { "commandStartedEvent": { "command": { "findAndModify": "test", "query": { "_id": 3 }, "update": { "$inc": { "x": 1 } }, "new": false, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "3" }, "startTransaction": true, "autocommit": false, "readConcern": { "afterClusterTime": { "$$exists": true } }, "writeConcern": { "$$exists": false } }, "commandName": "findAndModify", "databaseName": "transaction-tests" } }, { "commandStartedEvent": { "command": { "abortTransaction": 1, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "3" }, "startTransaction": { "$$exists": false }, "autocommit": false, "readConcern": { "$$exists": false }, "writeConcern": { "$$exists": false } }, "commandName": "abortTransaction", "databaseName": "admin" } } ] } ], "outcome": [ { "collectionName": "test", "databaseName": "transaction-tests", "documents": [ { "_id": 1 }, { "_id": 2 }, { "_id": 3, "x": 2 }, { "_id": 4, "x": 1 } ] } ] }, { "description": "collection writeConcern ignored for findOneAndUpdate", "operations": [ { "object": "testRunner", "name": "createEntities", "arguments": { "entities": [ { "collection": { "id": "collection_wc_majority", "database": "database0", "collectionName": "test", "collectionOptions": { "writeConcern": { "w": "majority" } } } } ] } }, { "object": "session0", "name": "startTransaction", "arguments": { "writeConcern": { "w": "majority" } } }, { "object": "collection_wc_majority", "name": "findOneAndUpdate", "arguments": { "session": "session0", "filter": { "_id": 3 }, "update": { "$inc": { "x": 1 } }, "returnDocument": "Before" }, "expectResult": { "_id": 3 } }, { "object": "session0", "name": "commitTransaction" } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "findAndModify": "test", "query": { "_id": 3 }, "update": { "$inc": { "x": 1 } }, "new": false, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": true, "autocommit": false, "readConcern": { "$$exists": false }, "writeConcern": { "$$exists": false } }, "commandName": "findAndModify", "databaseName": "transaction-tests" } }, { "commandStartedEvent": { "command": { "commitTransaction": 1, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": { "$$exists": false }, "autocommit": false, "readConcern": { "$$exists": false }, "writeConcern": { "w": "majority" } }, "commandName": "commitTransaction", "databaseName": "admin" } } ] } ] } ] } mongodb-mongo-python-driver-509e9b7/test/transactions/unified/insert.json000066400000000000000000000550321462766011000267530ustar00rootroot00000000000000{ "description": "insert", "schemaVersion": "1.9", "runOnRequirements": [ { "minServerVersion": "4.0", "topologies": [ "replicaset" ] }, { "minServerVersion": "4.1.8", "topologies": [ "sharded", "load-balanced" ] } ], "createEntities": [ { "client": { "id": "client0", "useMultipleMongoses": false, "observeEvents": [ "commandStartedEvent" ] } }, { "database": { "id": "database0", "client": "client0", "databaseName": "transaction-tests" } }, { "collection": { "id": "collection0", "database": "database0", "collectionName": "test" } }, { "session": { "id": "session0", "client": "client0" } }, { "session": { "id": "session1", "client": "client0" } } ], "initialData": [ { "collectionName": "test", "databaseName": "transaction-tests", "documents": [] } ], "tests": [ { "description": "insert", "operations": [ { "object": "session0", "name": "startTransaction" }, { "object": "collection0", "name": "insertOne", "arguments": { "session": "session0", "document": { "_id": 1 } }, "expectResult": { "$$unsetOrMatches": { "insertedId": { "$$unsetOrMatches": 1 } } } }, { "object": "collection0", "name": "insertMany", "arguments": { "documents": [ { "_id": 2 }, { "_id": 3 } ], "session": "session0" }, "expectResult": { "$$unsetOrMatches": { "insertedIds": { "$$unsetOrMatches": { "0": 2, "1": 3 } } } } }, { "object": "collection0", "name": "insertOne", "arguments": { "session": "session0", "document": { "_id": 4 } }, "expectResult": { "$$unsetOrMatches": { "insertedId": { "$$unsetOrMatches": 4 } } } }, { "object": "session0", "name": "commitTransaction" }, { "object": "session0", "name": "startTransaction" }, { "object": "collection0", "name": "insertOne", "arguments": { "session": "session0", "document": { "_id": 5 } }, "expectResult": { "$$unsetOrMatches": { "insertedId": { "$$unsetOrMatches": 5 } } } }, { "object": "session0", "name": "commitTransaction" } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "insert": "test", "documents": [ { "_id": 1 } ], "ordered": true, "readConcern": { "$$exists": false }, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": true, "autocommit": false, "writeConcern": { "$$exists": false } }, "commandName": "insert", "databaseName": "transaction-tests" } }, { "commandStartedEvent": { "command": { "insert": "test", "documents": [ { "_id": 2 }, { "_id": 3 } ], "ordered": true, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": { "$$exists": false }, "autocommit": false, "writeConcern": { "$$exists": false } }, "commandName": "insert", "databaseName": "transaction-tests" } }, { "commandStartedEvent": { "command": { "insert": "test", "documents": [ { "_id": 4 } ], "ordered": true, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "autocommit": false, "writeConcern": { "$$exists": false } }, "commandName": "insert", "databaseName": "transaction-tests" } }, { "commandStartedEvent": { "command": { "commitTransaction": 1, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": { "$$exists": false }, "autocommit": false, "writeConcern": { "$$exists": false } }, "commandName": "commitTransaction", "databaseName": "admin" } }, { "commandStartedEvent": { "command": { "insert": "test", "documents": [ { "_id": 5 } ], "ordered": true, "readConcern": { "afterClusterTime": { "$$exists": true } }, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "2" }, "startTransaction": true, "autocommit": false, "writeConcern": { "$$exists": false } }, "commandName": "insert", "databaseName": "transaction-tests" } }, { "commandStartedEvent": { "command": { "commitTransaction": 1, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "2" }, "startTransaction": { "$$exists": false }, "autocommit": false, "writeConcern": { "$$exists": false } }, "commandName": "commitTransaction", "databaseName": "admin" } } ] } ], "outcome": [ { "collectionName": "test", "databaseName": "transaction-tests", "documents": [ { "_id": 1 }, { "_id": 2 }, { "_id": 3 }, { "_id": 4 }, { "_id": 5 } ] } ] }, { "description": "insert with session1", "operations": [ { "object": "session1", "name": "startTransaction" }, { "object": "collection0", "name": "insertOne", "arguments": { "session": "session1", "document": { "_id": 1 } }, "expectResult": { "$$unsetOrMatches": { "insertedId": { "$$unsetOrMatches": 1 } } } }, { "object": "collection0", "name": "insertMany", "arguments": { "documents": [ { "_id": 2 }, { "_id": 3 } ], "session": "session1" }, "expectResult": { "$$unsetOrMatches": { "insertedIds": { "$$unsetOrMatches": { "0": 2, "1": 3 } } } } }, { "object": "session1", "name": "commitTransaction" }, { "object": "session1", "name": "startTransaction" }, { "object": "collection0", "name": "insertOne", "arguments": { "session": "session1", "document": { "_id": 4 } }, "expectResult": { "$$unsetOrMatches": { "insertedId": { "$$unsetOrMatches": 4 } } } }, { "object": "session1", "name": "abortTransaction" } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "insert": "test", "documents": [ { "_id": 1 } ], "ordered": true, "readConcern": { "$$exists": false }, "lsid": { "$$sessionLsid": "session1" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": true, "autocommit": false, "writeConcern": { "$$exists": false } }, "commandName": "insert", "databaseName": "transaction-tests" } }, { "commandStartedEvent": { "command": { "insert": "test", "documents": [ { "_id": 2 }, { "_id": 3 } ], "ordered": true, "lsid": { "$$sessionLsid": "session1" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": { "$$exists": false }, "autocommit": false, "writeConcern": { "$$exists": false } }, "commandName": "insert", "databaseName": "transaction-tests" } }, { "commandStartedEvent": { "command": { "commitTransaction": 1, "lsid": { "$$sessionLsid": "session1" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": { "$$exists": false }, "autocommit": false, "writeConcern": { "$$exists": false } }, "commandName": "commitTransaction", "databaseName": "admin" } }, { "commandStartedEvent": { "command": { "insert": "test", "documents": [ { "_id": 4 } ], "ordered": true, "readConcern": { "afterClusterTime": { "$$exists": true } }, "lsid": { "$$sessionLsid": "session1" }, "txnNumber": { "$numberLong": "2" }, "startTransaction": true, "autocommit": false, "writeConcern": { "$$exists": false } }, "commandName": "insert", "databaseName": "transaction-tests" } }, { "commandStartedEvent": { "command": { "abortTransaction": 1, "lsid": { "$$sessionLsid": "session1" }, "txnNumber": { "$numberLong": "2" }, "startTransaction": { "$$exists": false }, "autocommit": false, "writeConcern": { "$$exists": false } }, "commandName": "abortTransaction", "databaseName": "admin" } } ] } ], "outcome": [ { "collectionName": "test", "databaseName": "transaction-tests", "documents": [ { "_id": 1 }, { "_id": 2 }, { "_id": 3 } ] } ] }, { "description": "collection writeConcern without transaction", "operations": [ { "object": "testRunner", "name": "createEntities", "arguments": { "entities": [ { "client": { "id": "client1", "useMultipleMongoses": false, "uriOptions": { "retryWrites": false }, "observeEvents": [ "commandStartedEvent" ] } }, { "database": { "id": "database1", "client": "client1", "databaseName": "transaction-tests" } }, { "collection": { "id": "collection_wc_majority", "database": "database1", "collectionName": "test", "collectionOptions": { "writeConcern": { "w": "majority" } } } }, { "session": { "id": "session2", "client": "client1" } } ] } }, { "object": "collection_wc_majority", "name": "insertOne", "arguments": { "session": "session2", "document": { "_id": 1 } }, "expectResult": { "$$unsetOrMatches": { "insertedId": { "$$unsetOrMatches": 1 } } } } ], "expectEvents": [ { "client": "client1", "events": [ { "commandStartedEvent": { "command": { "insert": "test", "documents": [ { "_id": 1 } ], "ordered": true, "readConcern": { "$$exists": false }, "lsid": { "$$sessionLsid": "session2" }, "txnNumber": { "$$exists": false }, "startTransaction": { "$$exists": false }, "autocommit": { "$$exists": false }, "writeConcern": { "w": "majority" } }, "commandName": "insert", "databaseName": "transaction-tests" } } ] } ], "outcome": [ { "collectionName": "test", "databaseName": "transaction-tests", "documents": [ { "_id": 1 } ] } ] }, { "description": "collection writeConcern ignored for insert", "operations": [ { "object": "testRunner", "name": "createEntities", "arguments": { "entities": [ { "collection": { "id": "collection_wc_majority", "database": "database0", "collectionName": "test", "collectionOptions": { "writeConcern": { "w": "majority" } } } } ] } }, { "object": "session0", "name": "startTransaction", "arguments": { "writeConcern": { "w": "majority" } } }, { "object": "collection_wc_majority", "name": "insertOne", "arguments": { "session": "session0", "document": { "_id": 1 } }, "expectResult": { "$$unsetOrMatches": { "insertedId": { "$$unsetOrMatches": 1 } } } }, { "object": "collection_wc_majority", "name": "insertMany", "arguments": { "documents": [ { "_id": 2 }, { "_id": 3 } ], "session": "session0" }, "expectResult": { "$$unsetOrMatches": { "insertedIds": { "$$unsetOrMatches": { "0": 2, "1": 3 } } } } }, { "object": "session0", "name": "commitTransaction" } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "insert": "test", "documents": [ { "_id": 1 } ], "ordered": true, "readConcern": { "$$exists": false }, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": true, "autocommit": false, "writeConcern": { "$$exists": false } }, "commandName": "insert", "databaseName": "transaction-tests" } }, { "commandStartedEvent": { "command": { "insert": "test", "documents": [ { "_id": 2 }, { "_id": 3 } ], "ordered": true, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": { "$$exists": false }, "autocommit": false, "writeConcern": { "$$exists": false } }, "commandName": "insert", "databaseName": "transaction-tests" } }, { "commandStartedEvent": { "command": { "commitTransaction": 1, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": { "$$exists": false }, "autocommit": false, "writeConcern": { "w": "majority" } }, "commandName": "commitTransaction", "databaseName": "admin" } } ] } ], "outcome": [ { "collectionName": "test", "databaseName": "transaction-tests", "documents": [ { "_id": 1 }, { "_id": 2 }, { "_id": 3 } ] } ] } ] } mongodb-mongo-python-driver-509e9b7/test/transactions/unified/isolation.json000066400000000000000000000130541462766011000274460ustar00rootroot00000000000000{ "description": "isolation", "schemaVersion": "1.3", "runOnRequirements": [ { "minServerVersion": "4.0", "topologies": [ "replicaset" ] }, { "minServerVersion": "4.1.8", "topologies": [ "sharded", "load-balanced" ] } ], "createEntities": [ { "client": { "id": "client0", "useMultipleMongoses": false, "observeEvents": [ "commandStartedEvent" ] } }, { "database": { "id": "database0", "client": "client0", "databaseName": "transaction-tests" } }, { "collection": { "id": "collection0", "database": "database0", "collectionName": "test" } }, { "session": { "id": "session0", "client": "client0" } }, { "session": { "id": "session1", "client": "client0" } } ], "initialData": [ { "collectionName": "test", "databaseName": "transaction-tests", "documents": [] } ], "tests": [ { "description": "one transaction", "operations": [ { "object": "session0", "name": "startTransaction" }, { "object": "collection0", "name": "insertOne", "arguments": { "session": "session0", "document": { "_id": 1 } }, "expectResult": { "$$unsetOrMatches": { "insertedId": { "$$unsetOrMatches": 1 } } } }, { "object": "collection0", "name": "find", "arguments": { "session": "session0", "filter": { "_id": 1 } }, "expectResult": [ { "_id": 1 } ] }, { "object": "collection0", "name": "find", "arguments": { "session": "session1", "filter": { "_id": 1 } }, "expectResult": [] }, { "object": "collection0", "name": "find", "arguments": { "filter": { "_id": 1 } }, "expectResult": [] }, { "object": "session0", "name": "commitTransaction" }, { "object": "collection0", "name": "find", "arguments": { "session": "session1", "filter": { "_id": 1 } }, "expectResult": [ { "_id": 1 } ] }, { "object": "collection0", "name": "find", "arguments": { "filter": { "_id": 1 } }, "expectResult": [ { "_id": 1 } ] } ], "outcome": [ { "collectionName": "test", "databaseName": "transaction-tests", "documents": [ { "_id": 1 } ] } ] }, { "description": "two transactions", "operations": [ { "object": "session0", "name": "startTransaction" }, { "object": "session1", "name": "startTransaction" }, { "object": "collection0", "name": "insertOne", "arguments": { "session": "session0", "document": { "_id": 1 } }, "expectResult": { "$$unsetOrMatches": { "insertedId": { "$$unsetOrMatches": 1 } } } }, { "object": "collection0", "name": "find", "arguments": { "session": "session0", "filter": { "_id": 1 } }, "expectResult": [ { "_id": 1 } ] }, { "object": "collection0", "name": "find", "arguments": { "session": "session1", "filter": { "_id": 1 } }, "expectResult": [] }, { "object": "collection0", "name": "find", "arguments": { "filter": { "_id": 1 } }, "expectResult": [] }, { "object": "session0", "name": "commitTransaction" }, { "object": "collection0", "name": "find", "arguments": { "session": "session1", "filter": { "_id": 1 } }, "expectResult": [] }, { "object": "collection0", "name": "find", "arguments": { "filter": { "_id": 1 } }, "expectResult": [ { "_id": 1 } ] }, { "object": "session1", "name": "commitTransaction" } ], "outcome": [ { "collectionName": "test", "databaseName": "transaction-tests", "documents": [ { "_id": 1 } ] } ] } ] } mongodb-mongo-python-driver-509e9b7/test/transactions/unified/mongos-pin-auto.json000066400000000000000000003557441462766011000305200ustar00rootroot00000000000000{ "description": "mongos-pin-auto", "schemaVersion": "1.4", "runOnRequirements": [ { "minServerVersion": "4.1.8", "topologies": [ "sharded" ], "serverless": "forbid" } ], "createEntities": [ { "client": { "id": "client0", "useMultipleMongoses": true, "observeEvents": [ "commandStartedEvent" ] } }, { "database": { "id": "database0", "client": "client0", "databaseName": "transaction-tests" } }, { "collection": { "id": "collection0", "database": "database0", "collectionName": "test" } }, { "session": { "id": "session0", "client": "client0" } } ], "initialData": [ { "collectionName": "test", "databaseName": "transaction-tests", "documents": [ { "_id": 1 }, { "_id": 2 } ] } ], "tests": [ { "description": "remain pinned after non-transient Interrupted error on insertOne", "operations": [ { "object": "session0", "name": "startTransaction" }, { "object": "collection0", "name": "insertOne", "arguments": { "session": "session0", "document": { "_id": 3 } }, "expectResult": { "$$unsetOrMatches": { "insertedId": { "$$unsetOrMatches": 3 } } } }, { "object": "testRunner", "name": "targetedFailPoint", "arguments": { "session": "session0", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "insert" ], "errorCode": 11601 } } } }, { "object": "collection0", "name": "insertOne", "arguments": { "session": "session0", "document": { "_id": 4 } }, "expectError": { "errorLabelsOmit": [ "TransientTransactionError", "UnknownTransactionCommitResult" ], "errorCodeName": "Interrupted" } }, { "object": "testRunner", "name": "assertSessionPinned", "arguments": { "session": "session0" } }, { "object": "session0", "name": "commitTransaction" } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "insert": "test", "documents": [ { "_id": 3 } ], "ordered": true, "readConcern": { "$$exists": false }, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": true, "autocommit": false, "writeConcern": { "$$exists": false } }, "commandName": "insert", "databaseName": "transaction-tests" } }, { "commandStartedEvent": { "command": { "insert": "test", "documents": [ { "_id": 4 } ], "ordered": true, "readConcern": { "$$exists": false }, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": { "$$exists": false }, "autocommit": false, "writeConcern": { "$$exists": false } }, "commandName": "insert", "databaseName": "transaction-tests" } }, { "commandStartedEvent": { "command": { "commitTransaction": 1, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": { "$$exists": false }, "autocommit": false, "writeConcern": { "$$exists": false }, "recoveryToken": { "$$exists": true } }, "commandName": "commitTransaction", "databaseName": "admin" } } ] } ], "outcome": [ { "collectionName": "test", "databaseName": "transaction-tests", "documents": [ { "_id": 1 }, { "_id": 2 }, { "_id": 3 } ] } ] }, { "description": "unpin after transient error within a transaction", "operations": [ { "object": "session0", "name": "startTransaction" }, { "object": "collection0", "name": "insertOne", "arguments": { "session": "session0", "document": { "_id": 3 } }, "expectResult": { "$$unsetOrMatches": { "insertedId": { "$$unsetOrMatches": 3 } } } }, { "object": "testRunner", "name": "targetedFailPoint", "arguments": { "session": "session0", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "insert" ], "closeConnection": true } } } }, { "object": "collection0", "name": "insertOne", "arguments": { "session": "session0", "document": { "_id": 4 } }, "expectError": { "errorLabelsContain": [ "TransientTransactionError" ], "errorLabelsOmit": [ "UnknownTransactionCommitResult" ] } }, { "object": "testRunner", "name": "assertSessionUnpinned", "arguments": { "session": "session0" } }, { "object": "session0", "name": "abortTransaction" } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "insert": "test", "documents": [ { "_id": 3 } ], "ordered": true, "readConcern": { "$$exists": false }, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": true, "autocommit": false, "writeConcern": { "$$exists": false } }, "commandName": "insert", "databaseName": "transaction-tests" } }, { "commandStartedEvent": { "command": { "insert": "test", "documents": [ { "_id": 4 } ], "ordered": true, "readConcern": { "$$exists": false }, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": { "$$exists": false }, "autocommit": false, "writeConcern": { "$$exists": false } }, "commandName": "insert", "databaseName": "transaction-tests" } }, { "commandStartedEvent": { "command": { "abortTransaction": 1, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": { "$$exists": false }, "autocommit": false, "writeConcern": { "$$exists": false }, "recoveryToken": { "$$exists": true } }, "commandName": "abortTransaction", "databaseName": "admin" } } ] } ], "outcome": [ { "collectionName": "test", "databaseName": "transaction-tests", "documents": [ { "_id": 1 }, { "_id": 2 } ] } ] }, { "description": "remain pinned after non-transient Interrupted error on insertOne insert", "operations": [ { "object": "session0", "name": "startTransaction" }, { "object": "collection0", "name": "insertOne", "arguments": { "session": "session0", "document": { "_id": 3 } }, "expectResult": { "$$unsetOrMatches": { "insertedId": { "$$unsetOrMatches": 3 } } } }, { "name": "targetedFailPoint", "object": "testRunner", "arguments": { "session": "session0", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "insert" ], "errorCode": 11601 } } } }, { "name": "insertOne", "object": "collection0", "arguments": { "session": "session0", "document": { "_id": 4 } }, "expectError": { "errorLabelsOmit": [ "TransientTransactionError" ] } }, { "object": "testRunner", "name": "assertSessionPinned", "arguments": { "session": "session0" } }, { "object": "session0", "name": "abortTransaction" } ], "outcome": [ { "collectionName": "test", "databaseName": "transaction-tests", "documents": [ { "_id": 1 }, { "_id": 2 } ] } ] }, { "description": "remain pinned after non-transient Interrupted error on insertMany insert", "operations": [ { "object": "session0", "name": "startTransaction" }, { "object": "collection0", "name": "insertOne", "arguments": { "session": "session0", "document": { "_id": 3 } }, "expectResult": { "$$unsetOrMatches": { "insertedId": { "$$unsetOrMatches": 3 } } } }, { "name": "targetedFailPoint", "object": "testRunner", "arguments": { "session": "session0", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "insert" ], "errorCode": 11601 } } } }, { "name": "insertMany", "object": "collection0", "arguments": { "session": "session0", "documents": [ { "_id": 4 }, { "_id": 5 } ] }, "expectError": { "errorLabelsOmit": [ "TransientTransactionError" ] } }, { "object": "testRunner", "name": "assertSessionPinned", "arguments": { "session": "session0" } }, { "object": "session0", "name": "abortTransaction" } ], "outcome": [ { "collectionName": "test", "databaseName": "transaction-tests", "documents": [ { "_id": 1 }, { "_id": 2 } ] } ] }, { "description": "remain pinned after non-transient Interrupted error on updateOne update", "operations": [ { "object": "session0", "name": "startTransaction" }, { "object": "collection0", "name": "insertOne", "arguments": { "session": "session0", "document": { "_id": 3 } }, "expectResult": { "$$unsetOrMatches": { "insertedId": { "$$unsetOrMatches": 3 } } } }, { "name": "targetedFailPoint", "object": "testRunner", "arguments": { "session": "session0", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "update" ], "errorCode": 11601 } } } }, { "name": "updateOne", "object": "collection0", "arguments": { "session": "session0", "filter": { "_id": 1 }, "update": { "$inc": { "x": 1 } } }, "expectError": { "errorLabelsOmit": [ "TransientTransactionError" ] } }, { "object": "testRunner", "name": "assertSessionPinned", "arguments": { "session": "session0" } }, { "object": "session0", "name": "abortTransaction" } ], "outcome": [ { "collectionName": "test", "databaseName": "transaction-tests", "documents": [ { "_id": 1 }, { "_id": 2 } ] } ] }, { "description": "remain pinned after non-transient Interrupted error on replaceOne update", "operations": [ { "object": "session0", "name": "startTransaction" }, { "object": "collection0", "name": "insertOne", "arguments": { "session": "session0", "document": { "_id": 3 } }, "expectResult": { "$$unsetOrMatches": { "insertedId": { "$$unsetOrMatches": 3 } } } }, { "name": "targetedFailPoint", "object": "testRunner", "arguments": { "session": "session0", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "update" ], "errorCode": 11601 } } } }, { "name": "replaceOne", "object": "collection0", "arguments": { "session": "session0", "filter": { "_id": 1 }, "replacement": { "y": 1 } }, "expectError": { "errorLabelsOmit": [ "TransientTransactionError" ] } }, { "object": "testRunner", "name": "assertSessionPinned", "arguments": { "session": "session0" } }, { "object": "session0", "name": "abortTransaction" } ], "outcome": [ { "collectionName": "test", "databaseName": "transaction-tests", "documents": [ { "_id": 1 }, { "_id": 2 } ] } ] }, { "description": "remain pinned after non-transient Interrupted error on updateMany update", "operations": [ { "object": "session0", "name": "startTransaction" }, { "object": "collection0", "name": "insertOne", "arguments": { "session": "session0", "document": { "_id": 3 } }, "expectResult": { "$$unsetOrMatches": { "insertedId": { "$$unsetOrMatches": 3 } } } }, { "name": "targetedFailPoint", "object": "testRunner", "arguments": { "session": "session0", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "update" ], "errorCode": 11601 } } } }, { "name": "updateMany", "object": "collection0", "arguments": { "session": "session0", "filter": { "_id": { "$gte": 1 } }, "update": { "$set": { "z": 1 } } }, "expectError": { "errorLabelsOmit": [ "TransientTransactionError" ] } }, { "object": "testRunner", "name": "assertSessionPinned", "arguments": { "session": "session0" } }, { "object": "session0", "name": "abortTransaction" } ], "outcome": [ { "collectionName": "test", "databaseName": "transaction-tests", "documents": [ { "_id": 1 }, { "_id": 2 } ] } ] }, { "description": "remain pinned after non-transient Interrupted error on deleteOne delete", "operations": [ { "object": "session0", "name": "startTransaction" }, { "object": "collection0", "name": "insertOne", "arguments": { "session": "session0", "document": { "_id": 3 } }, "expectResult": { "$$unsetOrMatches": { "insertedId": { "$$unsetOrMatches": 3 } } } }, { "name": "targetedFailPoint", "object": "testRunner", "arguments": { "session": "session0", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "delete" ], "errorCode": 11601 } } } }, { "name": "deleteOne", "object": "collection0", "arguments": { "session": "session0", "filter": { "_id": 1 } }, "expectError": { "errorLabelsOmit": [ "TransientTransactionError" ] } }, { "object": "testRunner", "name": "assertSessionPinned", "arguments": { "session": "session0" } }, { "object": "session0", "name": "abortTransaction" } ], "outcome": [ { "collectionName": "test", "databaseName": "transaction-tests", "documents": [ { "_id": 1 }, { "_id": 2 } ] } ] }, { "description": "remain pinned after non-transient Interrupted error on deleteMany delete", "operations": [ { "object": "session0", "name": "startTransaction" }, { "object": "collection0", "name": "insertOne", "arguments": { "session": "session0", "document": { "_id": 3 } }, "expectResult": { "$$unsetOrMatches": { "insertedId": { "$$unsetOrMatches": 3 } } } }, { "name": "targetedFailPoint", "object": "testRunner", "arguments": { "session": "session0", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "delete" ], "errorCode": 11601 } } } }, { "name": "deleteMany", "object": "collection0", "arguments": { "session": "session0", "filter": { "_id": { "$gte": 1 } } }, "expectError": { "errorLabelsOmit": [ "TransientTransactionError" ] } }, { "object": "testRunner", "name": "assertSessionPinned", "arguments": { "session": "session0" } }, { "object": "session0", "name": "abortTransaction" } ], "outcome": [ { "collectionName": "test", "databaseName": "transaction-tests", "documents": [ { "_id": 1 }, { "_id": 2 } ] } ] }, { "description": "remain pinned after non-transient Interrupted error on findOneAndDelete findAndModify", "operations": [ { "object": "session0", "name": "startTransaction" }, { "object": "collection0", "name": "insertOne", "arguments": { "session": "session0", "document": { "_id": 3 } }, "expectResult": { "$$unsetOrMatches": { "insertedId": { "$$unsetOrMatches": 3 } } } }, { "name": "targetedFailPoint", "object": "testRunner", "arguments": { "session": "session0", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "findAndModify" ], "errorCode": 11601 } } } }, { "name": "findOneAndDelete", "object": "collection0", "arguments": { "session": "session0", "filter": { "_id": 1 } }, "expectError": { "errorLabelsOmit": [ "TransientTransactionError" ] } }, { "object": "testRunner", "name": "assertSessionPinned", "arguments": { "session": "session0" } }, { "object": "session0", "name": "abortTransaction" } ], "outcome": [ { "collectionName": "test", "databaseName": "transaction-tests", "documents": [ { "_id": 1 }, { "_id": 2 } ] } ] }, { "description": "remain pinned after non-transient Interrupted error on findOneAndUpdate findAndModify", "operations": [ { "object": "session0", "name": "startTransaction" }, { "object": "collection0", "name": "insertOne", "arguments": { "session": "session0", "document": { "_id": 3 } }, "expectResult": { "$$unsetOrMatches": { "insertedId": { "$$unsetOrMatches": 3 } } } }, { "name": "targetedFailPoint", "object": "testRunner", "arguments": { "session": "session0", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "findAndModify" ], "errorCode": 11601 } } } }, { "name": "findOneAndUpdate", "object": "collection0", "arguments": { "session": "session0", "filter": { "_id": 1 }, "update": { "$inc": { "x": 1 } }, "returnDocument": "Before" }, "expectError": { "errorLabelsOmit": [ "TransientTransactionError" ] } }, { "object": "testRunner", "name": "assertSessionPinned", "arguments": { "session": "session0" } }, { "object": "session0", "name": "abortTransaction" } ], "outcome": [ { "collectionName": "test", "databaseName": "transaction-tests", "documents": [ { "_id": 1 }, { "_id": 2 } ] } ] }, { "description": "remain pinned after non-transient Interrupted error on findOneAndReplace findAndModify", "operations": [ { "object": "session0", "name": "startTransaction" }, { "object": "collection0", "name": "insertOne", "arguments": { "session": "session0", "document": { "_id": 3 } }, "expectResult": { "$$unsetOrMatches": { "insertedId": { "$$unsetOrMatches": 3 } } } }, { "name": "targetedFailPoint", "object": "testRunner", "arguments": { "session": "session0", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "findAndModify" ], "errorCode": 11601 } } } }, { "name": "findOneAndReplace", "object": "collection0", "arguments": { "session": "session0", "filter": { "_id": 1 }, "replacement": { "y": 1 }, "returnDocument": "Before" }, "expectError": { "errorLabelsOmit": [ "TransientTransactionError" ] } }, { "object": "testRunner", "name": "assertSessionPinned", "arguments": { "session": "session0" } }, { "object": "session0", "name": "abortTransaction" } ], "outcome": [ { "collectionName": "test", "databaseName": "transaction-tests", "documents": [ { "_id": 1 }, { "_id": 2 } ] } ] }, { "description": "remain pinned after non-transient Interrupted error on bulkWrite insert", "operations": [ { "object": "session0", "name": "startTransaction" }, { "object": "collection0", "name": "insertOne", "arguments": { "session": "session0", "document": { "_id": 3 } }, "expectResult": { "$$unsetOrMatches": { "insertedId": { "$$unsetOrMatches": 3 } } } }, { "name": "targetedFailPoint", "object": "testRunner", "arguments": { "session": "session0", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "insert" ], "errorCode": 11601 } } } }, { "name": "bulkWrite", "object": "collection0", "arguments": { "session": "session0", "requests": [ { "insertOne": { "document": { "_id": 1 } } } ] }, "expectError": { "errorLabelsOmit": [ "TransientTransactionError" ] } }, { "object": "testRunner", "name": "assertSessionPinned", "arguments": { "session": "session0" } }, { "object": "session0", "name": "abortTransaction" } ], "outcome": [ { "collectionName": "test", "databaseName": "transaction-tests", "documents": [ { "_id": 1 }, { "_id": 2 } ] } ] }, { "description": "remain pinned after non-transient Interrupted error on bulkWrite update", "operations": [ { "object": "session0", "name": "startTransaction" }, { "object": "collection0", "name": "insertOne", "arguments": { "session": "session0", "document": { "_id": 3 } }, "expectResult": { "$$unsetOrMatches": { "insertedId": { "$$unsetOrMatches": 3 } } } }, { "name": "targetedFailPoint", "object": "testRunner", "arguments": { "session": "session0", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "update" ], "errorCode": 11601 } } } }, { "name": "bulkWrite", "object": "collection0", "arguments": { "session": "session0", "requests": [ { "updateOne": { "filter": { "_id": 1 }, "update": { "$set": { "x": 1 } } } } ] }, "expectError": { "errorLabelsOmit": [ "TransientTransactionError" ] } }, { "object": "testRunner", "name": "assertSessionPinned", "arguments": { "session": "session0" } }, { "object": "session0", "name": "abortTransaction" } ], "outcome": [ { "collectionName": "test", "databaseName": "transaction-tests", "documents": [ { "_id": 1 }, { "_id": 2 } ] } ] }, { "description": "remain pinned after non-transient Interrupted error on bulkWrite delete", "operations": [ { "object": "session0", "name": "startTransaction" }, { "object": "collection0", "name": "insertOne", "arguments": { "session": "session0", "document": { "_id": 3 } }, "expectResult": { "$$unsetOrMatches": { "insertedId": { "$$unsetOrMatches": 3 } } } }, { "name": "targetedFailPoint", "object": "testRunner", "arguments": { "session": "session0", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "delete" ], "errorCode": 11601 } } } }, { "name": "bulkWrite", "object": "collection0", "arguments": { "session": "session0", "requests": [ { "deleteOne": { "filter": { "_id": 1 } } } ] }, "expectError": { "errorLabelsOmit": [ "TransientTransactionError" ] } }, { "object": "testRunner", "name": "assertSessionPinned", "arguments": { "session": "session0" } }, { "object": "session0", "name": "abortTransaction" } ], "outcome": [ { "collectionName": "test", "databaseName": "transaction-tests", "documents": [ { "_id": 1 }, { "_id": 2 } ] } ] }, { "description": "remain pinned after non-transient Interrupted error on find find", "operations": [ { "object": "session0", "name": "startTransaction" }, { "object": "collection0", "name": "insertOne", "arguments": { "session": "session0", "document": { "_id": 3 } }, "expectResult": { "$$unsetOrMatches": { "insertedId": { "$$unsetOrMatches": 3 } } } }, { "name": "targetedFailPoint", "object": "testRunner", "arguments": { "session": "session0", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "find" ], "errorCode": 11601 } } } }, { "name": "find", "object": "collection0", "arguments": { "session": "session0", "filter": { "_id": 1 } }, "expectError": { "errorLabelsOmit": [ "TransientTransactionError" ] } }, { "object": "testRunner", "name": "assertSessionPinned", "arguments": { "session": "session0" } }, { "object": "session0", "name": "abortTransaction" } ], "outcome": [ { "collectionName": "test", "databaseName": "transaction-tests", "documents": [ { "_id": 1 }, { "_id": 2 } ] } ] }, { "description": "remain pinned after non-transient Interrupted error on countDocuments aggregate", "operations": [ { "object": "session0", "name": "startTransaction" }, { "object": "collection0", "name": "insertOne", "arguments": { "session": "session0", "document": { "_id": 3 } }, "expectResult": { "$$unsetOrMatches": { "insertedId": { "$$unsetOrMatches": 3 } } } }, { "name": "targetedFailPoint", "object": "testRunner", "arguments": { "session": "session0", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "aggregate" ], "errorCode": 11601 } } } }, { "name": "countDocuments", "object": "collection0", "arguments": { "session": "session0", "filter": {} }, "expectError": { "errorLabelsOmit": [ "TransientTransactionError" ] } }, { "object": "testRunner", "name": "assertSessionPinned", "arguments": { "session": "session0" } }, { "object": "session0", "name": "abortTransaction" } ], "outcome": [ { "collectionName": "test", "databaseName": "transaction-tests", "documents": [ { "_id": 1 }, { "_id": 2 } ] } ] }, { "description": "remain pinned after non-transient Interrupted error on aggregate aggregate", "operations": [ { "object": "session0", "name": "startTransaction" }, { "object": "collection0", "name": "insertOne", "arguments": { "session": "session0", "document": { "_id": 3 } }, "expectResult": { "$$unsetOrMatches": { "insertedId": { "$$unsetOrMatches": 3 } } } }, { "name": "targetedFailPoint", "object": "testRunner", "arguments": { "session": "session0", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "aggregate" ], "errorCode": 11601 } } } }, { "name": "aggregate", "object": "collection0", "arguments": { "session": "session0", "pipeline": [] }, "expectError": { "errorLabelsOmit": [ "TransientTransactionError" ] } }, { "object": "testRunner", "name": "assertSessionPinned", "arguments": { "session": "session0" } }, { "object": "session0", "name": "abortTransaction" } ], "outcome": [ { "collectionName": "test", "databaseName": "transaction-tests", "documents": [ { "_id": 1 }, { "_id": 2 } ] } ] }, { "description": "remain pinned after non-transient Interrupted error on distinct distinct", "operations": [ { "object": "session0", "name": "startTransaction" }, { "object": "collection0", "name": "insertOne", "arguments": { "session": "session0", "document": { "_id": 3 } }, "expectResult": { "$$unsetOrMatches": { "insertedId": { "$$unsetOrMatches": 3 } } } }, { "name": "targetedFailPoint", "object": "testRunner", "arguments": { "session": "session0", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "distinct" ], "errorCode": 11601 } } } }, { "name": "distinct", "object": "collection0", "arguments": { "session": "session0", "fieldName": "_id", "filter": {} }, "expectError": { "errorLabelsOmit": [ "TransientTransactionError" ] } }, { "object": "testRunner", "name": "assertSessionPinned", "arguments": { "session": "session0" } }, { "object": "session0", "name": "abortTransaction" } ], "outcome": [ { "collectionName": "test", "databaseName": "transaction-tests", "documents": [ { "_id": 1 }, { "_id": 2 } ] } ] }, { "description": "remain pinned after non-transient Interrupted error on runCommand insert", "operations": [ { "object": "session0", "name": "startTransaction" }, { "object": "collection0", "name": "insertOne", "arguments": { "session": "session0", "document": { "_id": 3 } }, "expectResult": { "$$unsetOrMatches": { "insertedId": { "$$unsetOrMatches": 3 } } } }, { "name": "targetedFailPoint", "object": "testRunner", "arguments": { "session": "session0", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "insert" ], "errorCode": 11601 } } } }, { "name": "runCommand", "object": "database0", "arguments": { "session": "session0", "commandName": "insert", "command": { "insert": "test", "documents": [ { "_id": 1 } ] } }, "expectError": { "errorLabelsOmit": [ "TransientTransactionError" ] } }, { "object": "testRunner", "name": "assertSessionPinned", "arguments": { "session": "session0" } }, { "object": "session0", "name": "abortTransaction" } ], "outcome": [ { "collectionName": "test", "databaseName": "transaction-tests", "documents": [ { "_id": 1 }, { "_id": 2 } ] } ] }, { "description": "unpin after transient connection error on insertOne insert", "operations": [ { "object": "session0", "name": "startTransaction" }, { "object": "collection0", "name": "insertOne", "arguments": { "session": "session0", "document": { "_id": 3 } }, "expectResult": { "$$unsetOrMatches": { "insertedId": { "$$unsetOrMatches": 3 } } } }, { "name": "targetedFailPoint", "object": "testRunner", "arguments": { "session": "session0", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "insert" ], "closeConnection": true } } } }, { "name": "insertOne", "object": "collection0", "arguments": { "session": "session0", "document": { "_id": 4 } }, "expectError": { "errorLabelsContain": [ "TransientTransactionError" ] } }, { "object": "testRunner", "name": "assertSessionUnpinned", "arguments": { "session": "session0" } }, { "object": "session0", "name": "abortTransaction" } ], "outcome": [ { "collectionName": "test", "databaseName": "transaction-tests", "documents": [ { "_id": 1 }, { "_id": 2 } ] } ] }, { "description": "unpin after transient ShutdownInProgress error on insertOne insert", "operations": [ { "object": "session0", "name": "startTransaction" }, { "object": "collection0", "name": "insertOne", "arguments": { "session": "session0", "document": { "_id": 3 } }, "expectResult": { "$$unsetOrMatches": { "insertedId": { "$$unsetOrMatches": 3 } } } }, { "name": "targetedFailPoint", "object": "testRunner", "arguments": { "session": "session0", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "insert" ], "errorCode": 91 } } } }, { "name": "insertOne", "object": "collection0", "arguments": { "session": "session0", "document": { "_id": 4 } }, "expectError": { "errorLabelsContain": [ "TransientTransactionError" ] } }, { "object": "testRunner", "name": "assertSessionUnpinned", "arguments": { "session": "session0" } }, { "object": "session0", "name": "abortTransaction" } ], "outcome": [ { "collectionName": "test", "databaseName": "transaction-tests", "documents": [ { "_id": 1 }, { "_id": 2 } ] } ] }, { "description": "unpin after transient connection error on insertMany insert", "operations": [ { "object": "session0", "name": "startTransaction" }, { "object": "collection0", "name": "insertOne", "arguments": { "session": "session0", "document": { "_id": 3 } }, "expectResult": { "$$unsetOrMatches": { "insertedId": { "$$unsetOrMatches": 3 } } } }, { "name": "targetedFailPoint", "object": "testRunner", "arguments": { "session": "session0", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "insert" ], "closeConnection": true } } } }, { "name": "insertMany", "object": "collection0", "arguments": { "session": "session0", "documents": [ { "_id": 4 }, { "_id": 5 } ] }, "expectError": { "errorLabelsContain": [ "TransientTransactionError" ] } }, { "object": "testRunner", "name": "assertSessionUnpinned", "arguments": { "session": "session0" } }, { "object": "session0", "name": "abortTransaction" } ], "outcome": [ { "collectionName": "test", "databaseName": "transaction-tests", "documents": [ { "_id": 1 }, { "_id": 2 } ] } ] }, { "description": "unpin after transient ShutdownInProgress error on insertMany insert", "operations": [ { "object": "session0", "name": "startTransaction" }, { "object": "collection0", "name": "insertOne", "arguments": { "session": "session0", "document": { "_id": 3 } }, "expectResult": { "$$unsetOrMatches": { "insertedId": { "$$unsetOrMatches": 3 } } } }, { "name": "targetedFailPoint", "object": "testRunner", "arguments": { "session": "session0", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "insert" ], "errorCode": 91 } } } }, { "name": "insertMany", "object": "collection0", "arguments": { "session": "session0", "documents": [ { "_id": 4 }, { "_id": 5 } ] }, "expectError": { "errorLabelsContain": [ "TransientTransactionError" ] } }, { "object": "testRunner", "name": "assertSessionUnpinned", "arguments": { "session": "session0" } }, { "object": "session0", "name": "abortTransaction" } ], "outcome": [ { "collectionName": "test", "databaseName": "transaction-tests", "documents": [ { "_id": 1 }, { "_id": 2 } ] } ] }, { "description": "unpin after transient connection error on updateOne update", "operations": [ { "object": "session0", "name": "startTransaction" }, { "object": "collection0", "name": "insertOne", "arguments": { "session": "session0", "document": { "_id": 3 } }, "expectResult": { "$$unsetOrMatches": { "insertedId": { "$$unsetOrMatches": 3 } } } }, { "name": "targetedFailPoint", "object": "testRunner", "arguments": { "session": "session0", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "update" ], "closeConnection": true } } } }, { "name": "updateOne", "object": "collection0", "arguments": { "session": "session0", "filter": { "_id": 1 }, "update": { "$inc": { "x": 1 } } }, "expectError": { "errorLabelsContain": [ "TransientTransactionError" ] } }, { "object": "testRunner", "name": "assertSessionUnpinned", "arguments": { "session": "session0" } }, { "object": "session0", "name": "abortTransaction" } ], "outcome": [ { "collectionName": "test", "databaseName": "transaction-tests", "documents": [ { "_id": 1 }, { "_id": 2 } ] } ] }, { "description": "unpin after transient ShutdownInProgress error on updateOne update", "operations": [ { "object": "session0", "name": "startTransaction" }, { "object": "collection0", "name": "insertOne", "arguments": { "session": "session0", "document": { "_id": 3 } }, "expectResult": { "$$unsetOrMatches": { "insertedId": { "$$unsetOrMatches": 3 } } } }, { "name": "targetedFailPoint", "object": "testRunner", "arguments": { "session": "session0", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "update" ], "errorCode": 91 } } } }, { "name": "updateOne", "object": "collection0", "arguments": { "session": "session0", "filter": { "_id": 1 }, "update": { "$inc": { "x": 1 } } }, "expectError": { "errorLabelsContain": [ "TransientTransactionError" ] } }, { "object": "testRunner", "name": "assertSessionUnpinned", "arguments": { "session": "session0" } }, { "object": "session0", "name": "abortTransaction" } ], "outcome": [ { "collectionName": "test", "databaseName": "transaction-tests", "documents": [ { "_id": 1 }, { "_id": 2 } ] } ] }, { "description": "unpin after transient connection error on replaceOne update", "operations": [ { "object": "session0", "name": "startTransaction" }, { "object": "collection0", "name": "insertOne", "arguments": { "session": "session0", "document": { "_id": 3 } }, "expectResult": { "$$unsetOrMatches": { "insertedId": { "$$unsetOrMatches": 3 } } } }, { "name": "targetedFailPoint", "object": "testRunner", "arguments": { "session": "session0", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "update" ], "closeConnection": true } } } }, { "name": "replaceOne", "object": "collection0", "arguments": { "session": "session0", "filter": { "_id": 1 }, "replacement": { "y": 1 } }, "expectError": { "errorLabelsContain": [ "TransientTransactionError" ] } }, { "object": "testRunner", "name": "assertSessionUnpinned", "arguments": { "session": "session0" } }, { "object": "session0", "name": "abortTransaction" } ], "outcome": [ { "collectionName": "test", "databaseName": "transaction-tests", "documents": [ { "_id": 1 }, { "_id": 2 } ] } ] }, { "description": "unpin after transient ShutdownInProgress error on replaceOne update", "operations": [ { "object": "session0", "name": "startTransaction" }, { "object": "collection0", "name": "insertOne", "arguments": { "session": "session0", "document": { "_id": 3 } }, "expectResult": { "$$unsetOrMatches": { "insertedId": { "$$unsetOrMatches": 3 } } } }, { "name": "targetedFailPoint", "object": "testRunner", "arguments": { "session": "session0", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "update" ], "errorCode": 91 } } } }, { "name": "replaceOne", "object": "collection0", "arguments": { "session": "session0", "filter": { "_id": 1 }, "replacement": { "y": 1 } }, "expectError": { "errorLabelsContain": [ "TransientTransactionError" ] } }, { "object": "testRunner", "name": "assertSessionUnpinned", "arguments": { "session": "session0" } }, { "object": "session0", "name": "abortTransaction" } ], "outcome": [ { "collectionName": "test", "databaseName": "transaction-tests", "documents": [ { "_id": 1 }, { "_id": 2 } ] } ] }, { "description": "unpin after transient connection error on updateMany update", "operations": [ { "object": "session0", "name": "startTransaction" }, { "object": "collection0", "name": "insertOne", "arguments": { "session": "session0", "document": { "_id": 3 } }, "expectResult": { "$$unsetOrMatches": { "insertedId": { "$$unsetOrMatches": 3 } } } }, { "name": "targetedFailPoint", "object": "testRunner", "arguments": { "session": "session0", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "update" ], "closeConnection": true } } } }, { "name": "updateMany", "object": "collection0", "arguments": { "session": "session0", "filter": { "_id": { "$gte": 1 } }, "update": { "$set": { "z": 1 } } }, "expectError": { "errorLabelsContain": [ "TransientTransactionError" ] } }, { "object": "testRunner", "name": "assertSessionUnpinned", "arguments": { "session": "session0" } }, { "object": "session0", "name": "abortTransaction" } ], "outcome": [ { "collectionName": "test", "databaseName": "transaction-tests", "documents": [ { "_id": 1 }, { "_id": 2 } ] } ] }, { "description": "unpin after transient ShutdownInProgress error on updateMany update", "operations": [ { "object": "session0", "name": "startTransaction" }, { "object": "collection0", "name": "insertOne", "arguments": { "session": "session0", "document": { "_id": 3 } }, "expectResult": { "$$unsetOrMatches": { "insertedId": { "$$unsetOrMatches": 3 } } } }, { "name": "targetedFailPoint", "object": "testRunner", "arguments": { "session": "session0", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "update" ], "errorCode": 91 } } } }, { "name": "updateMany", "object": "collection0", "arguments": { "session": "session0", "filter": { "_id": { "$gte": 1 } }, "update": { "$set": { "z": 1 } } }, "expectError": { "errorLabelsContain": [ "TransientTransactionError" ] } }, { "object": "testRunner", "name": "assertSessionUnpinned", "arguments": { "session": "session0" } }, { "object": "session0", "name": "abortTransaction" } ], "outcome": [ { "collectionName": "test", "databaseName": "transaction-tests", "documents": [ { "_id": 1 }, { "_id": 2 } ] } ] }, { "description": "unpin after transient connection error on deleteOne delete", "operations": [ { "object": "session0", "name": "startTransaction" }, { "object": "collection0", "name": "insertOne", "arguments": { "session": "session0", "document": { "_id": 3 } }, "expectResult": { "$$unsetOrMatches": { "insertedId": { "$$unsetOrMatches": 3 } } } }, { "name": "targetedFailPoint", "object": "testRunner", "arguments": { "session": "session0", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "delete" ], "closeConnection": true } } } }, { "name": "deleteOne", "object": "collection0", "arguments": { "session": "session0", "filter": { "_id": 1 } }, "expectError": { "errorLabelsContain": [ "TransientTransactionError" ] } }, { "object": "testRunner", "name": "assertSessionUnpinned", "arguments": { "session": "session0" } }, { "object": "session0", "name": "abortTransaction" } ], "outcome": [ { "collectionName": "test", "databaseName": "transaction-tests", "documents": [ { "_id": 1 }, { "_id": 2 } ] } ] }, { "description": "unpin after transient ShutdownInProgress error on deleteOne delete", "operations": [ { "object": "session0", "name": "startTransaction" }, { "object": "collection0", "name": "insertOne", "arguments": { "session": "session0", "document": { "_id": 3 } }, "expectResult": { "$$unsetOrMatches": { "insertedId": { "$$unsetOrMatches": 3 } } } }, { "name": "targetedFailPoint", "object": "testRunner", "arguments": { "session": "session0", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "delete" ], "errorCode": 91 } } } }, { "name": "deleteOne", "object": "collection0", "arguments": { "session": "session0", "filter": { "_id": 1 } }, "expectError": { "errorLabelsContain": [ "TransientTransactionError" ] } }, { "object": "testRunner", "name": "assertSessionUnpinned", "arguments": { "session": "session0" } }, { "object": "session0", "name": "abortTransaction" } ], "outcome": [ { "collectionName": "test", "databaseName": "transaction-tests", "documents": [ { "_id": 1 }, { "_id": 2 } ] } ] }, { "description": "unpin after transient connection error on deleteMany delete", "operations": [ { "object": "session0", "name": "startTransaction" }, { "object": "collection0", "name": "insertOne", "arguments": { "session": "session0", "document": { "_id": 3 } }, "expectResult": { "$$unsetOrMatches": { "insertedId": { "$$unsetOrMatches": 3 } } } }, { "name": "targetedFailPoint", "object": "testRunner", "arguments": { "session": "session0", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "delete" ], "closeConnection": true } } } }, { "name": "deleteMany", "object": "collection0", "arguments": { "session": "session0", "filter": { "_id": { "$gte": 1 } } }, "expectError": { "errorLabelsContain": [ "TransientTransactionError" ] } }, { "object": "testRunner", "name": "assertSessionUnpinned", "arguments": { "session": "session0" } }, { "object": "session0", "name": "abortTransaction" } ], "outcome": [ { "collectionName": "test", "databaseName": "transaction-tests", "documents": [ { "_id": 1 }, { "_id": 2 } ] } ] }, { "description": "unpin after transient ShutdownInProgress error on deleteMany delete", "operations": [ { "object": "session0", "name": "startTransaction" }, { "object": "collection0", "name": "insertOne", "arguments": { "session": "session0", "document": { "_id": 3 } }, "expectResult": { "$$unsetOrMatches": { "insertedId": { "$$unsetOrMatches": 3 } } } }, { "name": "targetedFailPoint", "object": "testRunner", "arguments": { "session": "session0", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "delete" ], "errorCode": 91 } } } }, { "name": "deleteMany", "object": "collection0", "arguments": { "session": "session0", "filter": { "_id": { "$gte": 1 } } }, "expectError": { "errorLabelsContain": [ "TransientTransactionError" ] } }, { "object": "testRunner", "name": "assertSessionUnpinned", "arguments": { "session": "session0" } }, { "object": "session0", "name": "abortTransaction" } ], "outcome": [ { "collectionName": "test", "databaseName": "transaction-tests", "documents": [ { "_id": 1 }, { "_id": 2 } ] } ] }, { "description": "unpin after transient connection error on findOneAndDelete findAndModify", "operations": [ { "object": "session0", "name": "startTransaction" }, { "object": "collection0", "name": "insertOne", "arguments": { "session": "session0", "document": { "_id": 3 } }, "expectResult": { "$$unsetOrMatches": { "insertedId": { "$$unsetOrMatches": 3 } } } }, { "name": "targetedFailPoint", "object": "testRunner", "arguments": { "session": "session0", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "findAndModify" ], "closeConnection": true } } } }, { "name": "findOneAndDelete", "object": "collection0", "arguments": { "session": "session0", "filter": { "_id": 1 } }, "expectError": { "errorLabelsContain": [ "TransientTransactionError" ] } }, { "object": "testRunner", "name": "assertSessionUnpinned", "arguments": { "session": "session0" } }, { "object": "session0", "name": "abortTransaction" } ], "outcome": [ { "collectionName": "test", "databaseName": "transaction-tests", "documents": [ { "_id": 1 }, { "_id": 2 } ] } ] }, { "description": "unpin after transient ShutdownInProgress error on findOneAndDelete findAndModify", "operations": [ { "object": "session0", "name": "startTransaction" }, { "object": "collection0", "name": "insertOne", "arguments": { "session": "session0", "document": { "_id": 3 } }, "expectResult": { "$$unsetOrMatches": { "insertedId": { "$$unsetOrMatches": 3 } } } }, { "name": "targetedFailPoint", "object": "testRunner", "arguments": { "session": "session0", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "findAndModify" ], "errorCode": 91 } } } }, { "name": "findOneAndDelete", "object": "collection0", "arguments": { "session": "session0", "filter": { "_id": 1 } }, "expectError": { "errorLabelsContain": [ "TransientTransactionError" ] } }, { "object": "testRunner", "name": "assertSessionUnpinned", "arguments": { "session": "session0" } }, { "object": "session0", "name": "abortTransaction" } ], "outcome": [ { "collectionName": "test", "databaseName": "transaction-tests", "documents": [ { "_id": 1 }, { "_id": 2 } ] } ] }, { "description": "unpin after transient connection error on findOneAndUpdate findAndModify", "operations": [ { "object": "session0", "name": "startTransaction" }, { "object": "collection0", "name": "insertOne", "arguments": { "session": "session0", "document": { "_id": 3 } }, "expectResult": { "$$unsetOrMatches": { "insertedId": { "$$unsetOrMatches": 3 } } } }, { "name": "targetedFailPoint", "object": "testRunner", "arguments": { "session": "session0", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "findAndModify" ], "closeConnection": true } } } }, { "name": "findOneAndUpdate", "object": "collection0", "arguments": { "session": "session0", "filter": { "_id": 1 }, "update": { "$inc": { "x": 1 } }, "returnDocument": "Before" }, "expectError": { "errorLabelsContain": [ "TransientTransactionError" ] } }, { "object": "testRunner", "name": "assertSessionUnpinned", "arguments": { "session": "session0" } }, { "object": "session0", "name": "abortTransaction" } ], "outcome": [ { "collectionName": "test", "databaseName": "transaction-tests", "documents": [ { "_id": 1 }, { "_id": 2 } ] } ] }, { "description": "unpin after transient ShutdownInProgress error on findOneAndUpdate findAndModify", "operations": [ { "object": "session0", "name": "startTransaction" }, { "object": "collection0", "name": "insertOne", "arguments": { "session": "session0", "document": { "_id": 3 } }, "expectResult": { "$$unsetOrMatches": { "insertedId": { "$$unsetOrMatches": 3 } } } }, { "name": "targetedFailPoint", "object": "testRunner", "arguments": { "session": "session0", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "findAndModify" ], "errorCode": 91 } } } }, { "name": "findOneAndUpdate", "object": "collection0", "arguments": { "session": "session0", "filter": { "_id": 1 }, "update": { "$inc": { "x": 1 } }, "returnDocument": "Before" }, "expectError": { "errorLabelsContain": [ "TransientTransactionError" ] } }, { "object": "testRunner", "name": "assertSessionUnpinned", "arguments": { "session": "session0" } }, { "object": "session0", "name": "abortTransaction" } ], "outcome": [ { "collectionName": "test", "databaseName": "transaction-tests", "documents": [ { "_id": 1 }, { "_id": 2 } ] } ] }, { "description": "unpin after transient connection error on findOneAndReplace findAndModify", "operations": [ { "object": "session0", "name": "startTransaction" }, { "object": "collection0", "name": "insertOne", "arguments": { "session": "session0", "document": { "_id": 3 } }, "expectResult": { "$$unsetOrMatches": { "insertedId": { "$$unsetOrMatches": 3 } } } }, { "name": "targetedFailPoint", "object": "testRunner", "arguments": { "session": "session0", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "findAndModify" ], "closeConnection": true } } } }, { "name": "findOneAndReplace", "object": "collection0", "arguments": { "session": "session0", "filter": { "_id": 1 }, "replacement": { "y": 1 }, "returnDocument": "Before" }, "expectError": { "errorLabelsContain": [ "TransientTransactionError" ] } }, { "object": "testRunner", "name": "assertSessionUnpinned", "arguments": { "session": "session0" } }, { "object": "session0", "name": "abortTransaction" } ], "outcome": [ { "collectionName": "test", "databaseName": "transaction-tests", "documents": [ { "_id": 1 }, { "_id": 2 } ] } ] }, { "description": "unpin after transient ShutdownInProgress error on findOneAndReplace findAndModify", "operations": [ { "object": "session0", "name": "startTransaction" }, { "object": "collection0", "name": "insertOne", "arguments": { "session": "session0", "document": { "_id": 3 } }, "expectResult": { "$$unsetOrMatches": { "insertedId": { "$$unsetOrMatches": 3 } } } }, { "name": "targetedFailPoint", "object": "testRunner", "arguments": { "session": "session0", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "findAndModify" ], "errorCode": 91 } } } }, { "name": "findOneAndReplace", "object": "collection0", "arguments": { "session": "session0", "filter": { "_id": 1 }, "replacement": { "y": 1 }, "returnDocument": "Before" }, "expectError": { "errorLabelsContain": [ "TransientTransactionError" ] } }, { "object": "testRunner", "name": "assertSessionUnpinned", "arguments": { "session": "session0" } }, { "object": "session0", "name": "abortTransaction" } ], "outcome": [ { "collectionName": "test", "databaseName": "transaction-tests", "documents": [ { "_id": 1 }, { "_id": 2 } ] } ] }, { "description": "unpin after transient connection error on bulkWrite insert", "operations": [ { "object": "session0", "name": "startTransaction" }, { "object": "collection0", "name": "insertOne", "arguments": { "session": "session0", "document": { "_id": 3 } }, "expectResult": { "$$unsetOrMatches": { "insertedId": { "$$unsetOrMatches": 3 } } } }, { "name": "targetedFailPoint", "object": "testRunner", "arguments": { "session": "session0", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "insert" ], "closeConnection": true } } } }, { "name": "bulkWrite", "object": "collection0", "arguments": { "session": "session0", "requests": [ { "insertOne": { "document": { "_id": 1 } } } ] }, "expectError": { "errorLabelsContain": [ "TransientTransactionError" ] } }, { "object": "testRunner", "name": "assertSessionUnpinned", "arguments": { "session": "session0" } }, { "object": "session0", "name": "abortTransaction" } ], "outcome": [ { "collectionName": "test", "databaseName": "transaction-tests", "documents": [ { "_id": 1 }, { "_id": 2 } ] } ] }, { "description": "unpin after transient ShutdownInProgress error on bulkWrite insert", "operations": [ { "object": "session0", "name": "startTransaction" }, { "object": "collection0", "name": "insertOne", "arguments": { "session": "session0", "document": { "_id": 3 } }, "expectResult": { "$$unsetOrMatches": { "insertedId": { "$$unsetOrMatches": 3 } } } }, { "name": "targetedFailPoint", "object": "testRunner", "arguments": { "session": "session0", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "insert" ], "errorCode": 91 } } } }, { "name": "bulkWrite", "object": "collection0", "arguments": { "session": "session0", "requests": [ { "insertOne": { "document": { "_id": 1 } } } ] }, "expectError": { "errorLabelsContain": [ "TransientTransactionError" ] } }, { "object": "testRunner", "name": "assertSessionUnpinned", "arguments": { "session": "session0" } }, { "object": "session0", "name": "abortTransaction" } ], "outcome": [ { "collectionName": "test", "databaseName": "transaction-tests", "documents": [ { "_id": 1 }, { "_id": 2 } ] } ] }, { "description": "unpin after transient connection error on bulkWrite update", "operations": [ { "object": "session0", "name": "startTransaction" }, { "object": "collection0", "name": "insertOne", "arguments": { "session": "session0", "document": { "_id": 3 } }, "expectResult": { "$$unsetOrMatches": { "insertedId": { "$$unsetOrMatches": 3 } } } }, { "name": "targetedFailPoint", "object": "testRunner", "arguments": { "session": "session0", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "update" ], "closeConnection": true } } } }, { "name": "bulkWrite", "object": "collection0", "arguments": { "session": "session0", "requests": [ { "updateOne": { "filter": { "_id": 1 }, "update": { "$set": { "x": 1 } } } } ] }, "expectError": { "errorLabelsContain": [ "TransientTransactionError" ] } }, { "object": "testRunner", "name": "assertSessionUnpinned", "arguments": { "session": "session0" } }, { "object": "session0", "name": "abortTransaction" } ], "outcome": [ { "collectionName": "test", "databaseName": "transaction-tests", "documents": [ { "_id": 1 }, { "_id": 2 } ] } ] }, { "description": "unpin after transient ShutdownInProgress error on bulkWrite update", "operations": [ { "object": "session0", "name": "startTransaction" }, { "object": "collection0", "name": "insertOne", "arguments": { "session": "session0", "document": { "_id": 3 } }, "expectResult": { "$$unsetOrMatches": { "insertedId": { "$$unsetOrMatches": 3 } } } }, { "name": "targetedFailPoint", "object": "testRunner", "arguments": { "session": "session0", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "update" ], "errorCode": 91 } } } }, { "name": "bulkWrite", "object": "collection0", "arguments": { "session": "session0", "requests": [ { "updateOne": { "filter": { "_id": 1 }, "update": { "$set": { "x": 1 } } } } ] }, "expectError": { "errorLabelsContain": [ "TransientTransactionError" ] } }, { "object": "testRunner", "name": "assertSessionUnpinned", "arguments": { "session": "session0" } }, { "object": "session0", "name": "abortTransaction" } ], "outcome": [ { "collectionName": "test", "databaseName": "transaction-tests", "documents": [ { "_id": 1 }, { "_id": 2 } ] } ] }, { "description": "unpin after transient connection error on bulkWrite delete", "operations": [ { "object": "session0", "name": "startTransaction" }, { "object": "collection0", "name": "insertOne", "arguments": { "session": "session0", "document": { "_id": 3 } }, "expectResult": { "$$unsetOrMatches": { "insertedId": { "$$unsetOrMatches": 3 } } } }, { "name": "targetedFailPoint", "object": "testRunner", "arguments": { "session": "session0", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "delete" ], "closeConnection": true } } } }, { "name": "bulkWrite", "object": "collection0", "arguments": { "session": "session0", "requests": [ { "deleteOne": { "filter": { "_id": 1 } } } ] }, "expectError": { "errorLabelsContain": [ "TransientTransactionError" ] } }, { "object": "testRunner", "name": "assertSessionUnpinned", "arguments": { "session": "session0" } }, { "object": "session0", "name": "abortTransaction" } ], "outcome": [ { "collectionName": "test", "databaseName": "transaction-tests", "documents": [ { "_id": 1 }, { "_id": 2 } ] } ] }, { "description": "unpin after transient ShutdownInProgress error on bulkWrite delete", "operations": [ { "object": "session0", "name": "startTransaction" }, { "object": "collection0", "name": "insertOne", "arguments": { "session": "session0", "document": { "_id": 3 } }, "expectResult": { "$$unsetOrMatches": { "insertedId": { "$$unsetOrMatches": 3 } } } }, { "name": "targetedFailPoint", "object": "testRunner", "arguments": { "session": "session0", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "delete" ], "errorCode": 91 } } } }, { "name": "bulkWrite", "object": "collection0", "arguments": { "session": "session0", "requests": [ { "deleteOne": { "filter": { "_id": 1 } } } ] }, "expectError": { "errorLabelsContain": [ "TransientTransactionError" ] } }, { "object": "testRunner", "name": "assertSessionUnpinned", "arguments": { "session": "session0" } }, { "object": "session0", "name": "abortTransaction" } ], "outcome": [ { "collectionName": "test", "databaseName": "transaction-tests", "documents": [ { "_id": 1 }, { "_id": 2 } ] } ] }, { "description": "unpin after transient connection error on find find", "operations": [ { "object": "session0", "name": "startTransaction" }, { "object": "collection0", "name": "insertOne", "arguments": { "session": "session0", "document": { "_id": 3 } }, "expectResult": { "$$unsetOrMatches": { "insertedId": { "$$unsetOrMatches": 3 } } } }, { "name": "targetedFailPoint", "object": "testRunner", "arguments": { "session": "session0", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "find" ], "closeConnection": true } } } }, { "name": "find", "object": "collection0", "arguments": { "session": "session0", "filter": { "_id": 1 } }, "expectError": { "errorLabelsContain": [ "TransientTransactionError" ] } }, { "object": "testRunner", "name": "assertSessionUnpinned", "arguments": { "session": "session0" } }, { "object": "session0", "name": "abortTransaction" } ], "outcome": [ { "collectionName": "test", "databaseName": "transaction-tests", "documents": [ { "_id": 1 }, { "_id": 2 } ] } ] }, { "description": "unpin after transient ShutdownInProgress error on find find", "operations": [ { "object": "session0", "name": "startTransaction" }, { "object": "collection0", "name": "insertOne", "arguments": { "session": "session0", "document": { "_id": 3 } }, "expectResult": { "$$unsetOrMatches": { "insertedId": { "$$unsetOrMatches": 3 } } } }, { "name": "targetedFailPoint", "object": "testRunner", "arguments": { "session": "session0", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "find" ], "errorCode": 91 } } } }, { "name": "find", "object": "collection0", "arguments": { "session": "session0", "filter": { "_id": 1 } }, "expectError": { "errorLabelsContain": [ "TransientTransactionError" ] } }, { "object": "testRunner", "name": "assertSessionUnpinned", "arguments": { "session": "session0" } }, { "object": "session0", "name": "abortTransaction" } ], "outcome": [ { "collectionName": "test", "databaseName": "transaction-tests", "documents": [ { "_id": 1 }, { "_id": 2 } ] } ] }, { "description": "unpin after transient connection error on countDocuments aggregate", "operations": [ { "object": "session0", "name": "startTransaction" }, { "object": "collection0", "name": "insertOne", "arguments": { "session": "session0", "document": { "_id": 3 } }, "expectResult": { "$$unsetOrMatches": { "insertedId": { "$$unsetOrMatches": 3 } } } }, { "name": "targetedFailPoint", "object": "testRunner", "arguments": { "session": "session0", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "aggregate" ], "closeConnection": true } } } }, { "name": "countDocuments", "object": "collection0", "arguments": { "session": "session0", "filter": {} }, "expectError": { "errorLabelsContain": [ "TransientTransactionError" ] } }, { "object": "testRunner", "name": "assertSessionUnpinned", "arguments": { "session": "session0" } }, { "object": "session0", "name": "abortTransaction" } ], "outcome": [ { "collectionName": "test", "databaseName": "transaction-tests", "documents": [ { "_id": 1 }, { "_id": 2 } ] } ] }, { "description": "unpin after transient ShutdownInProgress error on countDocuments aggregate", "operations": [ { "object": "session0", "name": "startTransaction" }, { "object": "collection0", "name": "insertOne", "arguments": { "session": "session0", "document": { "_id": 3 } }, "expectResult": { "$$unsetOrMatches": { "insertedId": { "$$unsetOrMatches": 3 } } } }, { "name": "targetedFailPoint", "object": "testRunner", "arguments": { "session": "session0", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "aggregate" ], "errorCode": 91 } } } }, { "name": "countDocuments", "object": "collection0", "arguments": { "session": "session0", "filter": {} }, "expectError": { "errorLabelsContain": [ "TransientTransactionError" ] } }, { "object": "testRunner", "name": "assertSessionUnpinned", "arguments": { "session": "session0" } }, { "object": "session0", "name": "abortTransaction" } ], "outcome": [ { "collectionName": "test", "databaseName": "transaction-tests", "documents": [ { "_id": 1 }, { "_id": 2 } ] } ] }, { "description": "unpin after transient connection error on aggregate aggregate", "operations": [ { "object": "session0", "name": "startTransaction" }, { "object": "collection0", "name": "insertOne", "arguments": { "session": "session0", "document": { "_id": 3 } }, "expectResult": { "$$unsetOrMatches": { "insertedId": { "$$unsetOrMatches": 3 } } } }, { "name": "targetedFailPoint", "object": "testRunner", "arguments": { "session": "session0", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "aggregate" ], "closeConnection": true } } } }, { "name": "aggregate", "object": "collection0", "arguments": { "session": "session0", "pipeline": [] }, "expectError": { "errorLabelsContain": [ "TransientTransactionError" ] } }, { "object": "testRunner", "name": "assertSessionUnpinned", "arguments": { "session": "session0" } }, { "object": "session0", "name": "abortTransaction" } ], "outcome": [ { "collectionName": "test", "databaseName": "transaction-tests", "documents": [ { "_id": 1 }, { "_id": 2 } ] } ] }, { "description": "unpin after transient ShutdownInProgress error on aggregate aggregate", "operations": [ { "object": "session0", "name": "startTransaction" }, { "object": "collection0", "name": "insertOne", "arguments": { "session": "session0", "document": { "_id": 3 } }, "expectResult": { "$$unsetOrMatches": { "insertedId": { "$$unsetOrMatches": 3 } } } }, { "name": "targetedFailPoint", "object": "testRunner", "arguments": { "session": "session0", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "aggregate" ], "errorCode": 91 } } } }, { "name": "aggregate", "object": "collection0", "arguments": { "session": "session0", "pipeline": [] }, "expectError": { "errorLabelsContain": [ "TransientTransactionError" ] } }, { "object": "testRunner", "name": "assertSessionUnpinned", "arguments": { "session": "session0" } }, { "object": "session0", "name": "abortTransaction" } ], "outcome": [ { "collectionName": "test", "databaseName": "transaction-tests", "documents": [ { "_id": 1 }, { "_id": 2 } ] } ] }, { "description": "unpin after transient connection error on distinct distinct", "operations": [ { "object": "session0", "name": "startTransaction" }, { "object": "collection0", "name": "insertOne", "arguments": { "session": "session0", "document": { "_id": 3 } }, "expectResult": { "$$unsetOrMatches": { "insertedId": { "$$unsetOrMatches": 3 } } } }, { "name": "targetedFailPoint", "object": "testRunner", "arguments": { "session": "session0", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "distinct" ], "closeConnection": true } } } }, { "name": "distinct", "object": "collection0", "arguments": { "session": "session0", "fieldName": "_id", "filter": {} }, "expectError": { "errorLabelsContain": [ "TransientTransactionError" ] } }, { "object": "testRunner", "name": "assertSessionUnpinned", "arguments": { "session": "session0" } }, { "object": "session0", "name": "abortTransaction" } ], "outcome": [ { "collectionName": "test", "databaseName": "transaction-tests", "documents": [ { "_id": 1 }, { "_id": 2 } ] } ] }, { "description": "unpin after transient ShutdownInProgress error on distinct distinct", "operations": [ { "object": "session0", "name": "startTransaction" }, { "object": "collection0", "name": "insertOne", "arguments": { "session": "session0", "document": { "_id": 3 } }, "expectResult": { "$$unsetOrMatches": { "insertedId": { "$$unsetOrMatches": 3 } } } }, { "name": "targetedFailPoint", "object": "testRunner", "arguments": { "session": "session0", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "distinct" ], "errorCode": 91 } } } }, { "name": "distinct", "object": "collection0", "arguments": { "session": "session0", "fieldName": "_id", "filter": {} }, "expectError": { "errorLabelsContain": [ "TransientTransactionError" ] } }, { "object": "testRunner", "name": "assertSessionUnpinned", "arguments": { "session": "session0" } }, { "object": "session0", "name": "abortTransaction" } ], "outcome": [ { "collectionName": "test", "databaseName": "transaction-tests", "documents": [ { "_id": 1 }, { "_id": 2 } ] } ] }, { "description": "unpin after transient connection error on runCommand insert", "operations": [ { "object": "session0", "name": "startTransaction" }, { "object": "collection0", "name": "insertOne", "arguments": { "session": "session0", "document": { "_id": 3 } }, "expectResult": { "$$unsetOrMatches": { "insertedId": { "$$unsetOrMatches": 3 } } } }, { "name": "targetedFailPoint", "object": "testRunner", "arguments": { "session": "session0", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "insert" ], "closeConnection": true } } } }, { "name": "runCommand", "object": "database0", "arguments": { "session": "session0", "commandName": "insert", "command": { "insert": "test", "documents": [ { "_id": 1 } ] } }, "expectError": { "errorLabelsContain": [ "TransientTransactionError" ] } }, { "object": "testRunner", "name": "assertSessionUnpinned", "arguments": { "session": "session0" } }, { "object": "session0", "name": "abortTransaction" } ], "outcome": [ { "collectionName": "test", "databaseName": "transaction-tests", "documents": [ { "_id": 1 }, { "_id": 2 } ] } ] }, { "description": "unpin after transient ShutdownInProgress error on runCommand insert", "operations": [ { "object": "session0", "name": "startTransaction" }, { "object": "collection0", "name": "insertOne", "arguments": { "session": "session0", "document": { "_id": 3 } }, "expectResult": { "$$unsetOrMatches": { "insertedId": { "$$unsetOrMatches": 3 } } } }, { "name": "targetedFailPoint", "object": "testRunner", "arguments": { "session": "session0", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "insert" ], "errorCode": 91 } } } }, { "name": "runCommand", "object": "database0", "arguments": { "session": "session0", "commandName": "insert", "command": { "insert": "test", "documents": [ { "_id": 1 } ] } }, "expectError": { "errorLabelsContain": [ "TransientTransactionError" ] } }, { "object": "testRunner", "name": "assertSessionUnpinned", "arguments": { "session": "session0" } }, { "object": "session0", "name": "abortTransaction" } ], "outcome": [ { "collectionName": "test", "databaseName": "transaction-tests", "documents": [ { "_id": 1 }, { "_id": 2 } ] } ] } ] } mongodb-mongo-python-driver-509e9b7/test/transactions/unified/mongos-recovery-token-errorLabels.json000066400000000000000000000122361462766011000341740ustar00rootroot00000000000000{ "description": "mongos-recovery-token-errorLabels", "schemaVersion": "1.4", "runOnRequirements": [ { "minServerVersion": "4.3.1", "serverless": "forbid", "topologies": [ "sharded" ] } ], "createEntities": [ { "client": { "id": "client0", "useMultipleMongoses": true, "observeEvents": [ "commandStartedEvent" ] } }, { "database": { "id": "database0", "client": "client0", "databaseName": "transaction-tests" } }, { "collection": { "id": "collection0", "database": "database0", "collectionName": "test" } }, { "session": { "id": "session0", "client": "client0" } } ], "initialData": [ { "collectionName": "test", "databaseName": "transaction-tests", "documents": [] } ], "tests": [ { "description": "commitTransaction retry succeeds on new mongos", "operations": [ { "object": "session0", "name": "startTransaction", "arguments": { "writeConcern": { "w": "majority" } } }, { "object": "collection0", "name": "insertOne", "arguments": { "session": "session0", "document": { "_id": 1 } }, "expectResult": { "$$unsetOrMatches": { "insertedId": { "$$unsetOrMatches": 1 } } } }, { "object": "testRunner", "name": "targetedFailPoint", "arguments": { "session": "session0", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "commitTransaction" ], "errorLabels": [ "RetryableWriteError" ], "writeConcernError": { "code": 91, "errmsg": "Replication is being shut down" } } } } }, { "object": "session0", "name": "commitTransaction" } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "insert": "test", "documents": [ { "_id": 1 } ], "ordered": true, "readConcern": { "$$exists": false }, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": true, "autocommit": false, "writeConcern": { "$$exists": false } }, "commandName": "insert", "databaseName": "transaction-tests" } }, { "commandStartedEvent": { "command": { "commitTransaction": 1, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": { "$$exists": false }, "autocommit": false, "writeConcern": { "w": "majority" }, "recoveryToken": { "$$exists": true } }, "commandName": "commitTransaction", "databaseName": "admin" } }, { "commandStartedEvent": { "command": { "commitTransaction": 1, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": { "$$exists": false }, "autocommit": false, "writeConcern": { "w": "majority", "wtimeout": 10000 }, "recoveryToken": { "$$exists": true } }, "commandName": "commitTransaction", "databaseName": "admin" } } ] } ], "outcome": [ { "collectionName": "test", "databaseName": "transaction-tests", "documents": [ { "_id": 1 } ] } ] } ] } mongodb-mongo-python-driver-509e9b7/test/transactions/unified/mongos-recovery-token.json000066400000000000000000000352451462766011000317270ustar00rootroot00000000000000{ "description": "mongos-recovery-token", "schemaVersion": "1.9", "runOnRequirements": [ { "minServerVersion": "4.1.8", "serverless": "forbid", "topologies": [ "sharded", "load-balanced" ] } ], "createEntities": [ { "client": { "id": "client0", "useMultipleMongoses": true, "observeEvents": [ "commandStartedEvent" ] } }, { "database": { "id": "database0", "client": "client0", "databaseName": "transaction-tests" } }, { "collection": { "id": "collection0", "database": "database0", "collectionName": "test" } }, { "session": { "id": "session0", "client": "client0" } } ], "initialData": [ { "collectionName": "test", "databaseName": "transaction-tests", "documents": [] } ], "tests": [ { "description": "commitTransaction explicit retries include recoveryToken", "operations": [ { "object": "session0", "name": "startTransaction" }, { "object": "collection0", "name": "insertOne", "arguments": { "session": "session0", "document": { "_id": 1 } }, "expectResult": { "$$unsetOrMatches": { "insertedId": { "$$unsetOrMatches": 1 } } } }, { "object": "session0", "name": "commitTransaction" }, { "object": "session0", "name": "commitTransaction" }, { "object": "session0", "name": "commitTransaction" } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "insert": "test", "documents": [ { "_id": 1 } ], "ordered": true, "readConcern": { "$$exists": false }, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": true, "autocommit": false, "writeConcern": { "$$exists": false } }, "commandName": "insert", "databaseName": "transaction-tests" } }, { "commandStartedEvent": { "command": { "commitTransaction": 1, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": { "$$exists": false }, "autocommit": false, "writeConcern": { "$$exists": false }, "recoveryToken": { "$$exists": true } }, "commandName": "commitTransaction", "databaseName": "admin" } }, { "commandStartedEvent": { "command": { "commitTransaction": 1, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": { "$$exists": false }, "autocommit": false, "writeConcern": { "w": "majority", "wtimeout": 10000 }, "recoveryToken": { "$$exists": true } }, "commandName": "commitTransaction", "databaseName": "admin" } }, { "commandStartedEvent": { "command": { "commitTransaction": 1, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": { "$$exists": false }, "autocommit": false, "writeConcern": { "w": "majority", "wtimeout": 10000 }, "recoveryToken": { "$$exists": true } }, "commandName": "commitTransaction", "databaseName": "admin" } } ] } ], "outcome": [ { "collectionName": "test", "databaseName": "transaction-tests", "documents": [ { "_id": 1 } ] } ] }, { "description": "commitTransaction retry fails on new mongos", "runOnRequirements": [ { "topologies": [ "sharded" ] } ], "operations": [ { "object": "testRunner", "name": "createEntities", "arguments": { "entities": [ { "client": { "id": "client1", "useMultipleMongoses": true, "uriOptions": { "heartbeatFrequencyMS": 30000 }, "observeEvents": [ "commandStartedEvent" ] } }, { "database": { "id": "database1", "client": "client1", "databaseName": "transaction-tests" } }, { "collection": { "id": "collection1", "database": "database1", "collectionName": "test" } }, { "session": { "id": "session1", "client": "client1" } } ] } }, { "object": "session1", "name": "startTransaction" }, { "object": "collection1", "name": "insertOne", "arguments": { "session": "session1", "document": { "_id": 1 } }, "expectResult": { "$$unsetOrMatches": { "insertedId": { "$$unsetOrMatches": 1 } } } }, { "object": "testRunner", "name": "targetedFailPoint", "arguments": { "session": "session1", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 7 }, "data": { "failCommands": [ "commitTransaction", "isMaster", "hello" ], "closeConnection": true } } } }, { "object": "session1", "name": "commitTransaction", "expectError": { "errorLabelsContain": [ "TransientTransactionError" ], "errorLabelsOmit": [ "UnknownTransactionCommitResult" ], "errorCodeName": "NoSuchTransaction" } } ], "expectEvents": [ { "client": "client1", "events": [ { "commandStartedEvent": { "command": { "insert": "test", "documents": [ { "_id": 1 } ], "ordered": true, "readConcern": { "$$exists": false }, "lsid": { "$$sessionLsid": "session1" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": true, "autocommit": false, "writeConcern": { "$$exists": false } }, "commandName": "insert", "databaseName": "transaction-tests" } }, { "commandStartedEvent": { "command": { "commitTransaction": 1, "lsid": { "$$sessionLsid": "session1" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": { "$$exists": false }, "autocommit": false, "writeConcern": { "$$exists": false }, "recoveryToken": { "$$exists": true } }, "commandName": "commitTransaction", "databaseName": "admin" } }, { "commandStartedEvent": { "command": { "commitTransaction": 1, "lsid": { "$$sessionLsid": "session1" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": { "$$exists": false }, "autocommit": false, "writeConcern": { "w": "majority", "wtimeout": 10000 }, "recoveryToken": { "$$exists": true } }, "commandName": "commitTransaction", "databaseName": "admin" } } ] } ], "outcome": [ { "collectionName": "test", "databaseName": "transaction-tests", "documents": [] } ] }, { "description": "abortTransaction sends recoveryToken", "runOnRequirements": [ { "topologies": [ "sharded" ] } ], "operations": [ { "object": "session0", "name": "startTransaction" }, { "object": "collection0", "name": "insertOne", "arguments": { "session": "session0", "document": { "_id": 1 } }, "expectResult": { "$$unsetOrMatches": { "insertedId": { "$$unsetOrMatches": 1 } } } }, { "object": "testRunner", "name": "targetedFailPoint", "arguments": { "session": "session0", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "abortTransaction" ], "closeConnection": true } } } }, { "object": "session0", "name": "abortTransaction" } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "insert": "test", "documents": [ { "_id": 1 } ], "ordered": true, "readConcern": { "$$exists": false }, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": true, "autocommit": false, "writeConcern": { "$$exists": false } }, "commandName": "insert", "databaseName": "transaction-tests" } }, { "commandStartedEvent": { "command": { "abortTransaction": 1, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": { "$$exists": false }, "autocommit": false, "writeConcern": { "$$exists": false }, "recoveryToken": { "$$exists": true } }, "commandName": "abortTransaction", "databaseName": "admin" } }, { "commandStartedEvent": { "command": { "abortTransaction": 1, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": { "$$exists": false }, "autocommit": false, "writeConcern": { "$$exists": false }, "recoveryToken": { "$$exists": true } }, "commandName": "abortTransaction", "databaseName": "admin" } } ] } ], "outcome": [ { "collectionName": "test", "databaseName": "transaction-tests", "documents": [] } ] } ] } mongodb-mongo-python-driver-509e9b7/test/transactions/unified/mongos-unpin.json000066400000000000000000000234461462766011000301040ustar00rootroot00000000000000{ "description": "mongos-unpin", "schemaVersion": "1.4", "runOnRequirements": [ { "minServerVersion": "4.2", "topologies": [ "sharded" ] } ], "createEntities": [ { "client": { "id": "client0", "useMultipleMongoses": true } }, { "database": { "id": "database0", "client": "client0", "databaseName": "mongos-unpin-db" } }, { "collection": { "id": "collection0", "database": "database0", "collectionName": "test" } }, { "session": { "id": "session0", "client": "client0" } } ], "initialData": [ { "collectionName": "test", "databaseName": "mongos-unpin-db", "documents": [] } ], "_yamlAnchors": { "anchors": 24 }, "tests": [ { "description": "unpin after TransientTransactionError error on commit", "runOnRequirements": [ { "serverless": "forbid", "topologies": [ "sharded" ] } ], "operations": [ { "name": "startTransaction", "object": "session0" }, { "name": "insertOne", "object": "collection0", "arguments": { "document": { "x": 1 }, "session": "session0" } }, { "name": "targetedFailPoint", "object": "testRunner", "arguments": { "session": "session0", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "commitTransaction" ], "errorCode": 24 } } } }, { "name": "commitTransaction", "object": "session0", "expectError": { "errorCode": 24, "errorLabelsContain": [ "TransientTransactionError" ], "errorLabelsOmit": [ "UnknownTransactionCommitResult" ] } }, { "name": "assertSessionUnpinned", "object": "testRunner", "arguments": { "session": "session0" } }, { "name": "startTransaction", "object": "session0" }, { "name": "insertOne", "object": "collection0", "arguments": { "document": { "x": 1 }, "session": "session0" } }, { "name": "abortTransaction", "object": "session0" } ] }, { "description": "unpin on successful abort", "operations": [ { "name": "startTransaction", "object": "session0" }, { "name": "insertOne", "object": "collection0", "arguments": { "document": { "x": 1 }, "session": "session0" } }, { "name": "abortTransaction", "object": "session0" }, { "name": "assertSessionUnpinned", "object": "testRunner", "arguments": { "session": "session0" } } ] }, { "description": "unpin after non-transient error on abort", "runOnRequirements": [ { "serverless": "forbid", "topologies": [ "sharded" ] } ], "operations": [ { "name": "startTransaction", "object": "session0" }, { "name": "insertOne", "object": "collection0", "arguments": { "document": { "x": 1 }, "session": "session0" } }, { "name": "targetedFailPoint", "object": "testRunner", "arguments": { "session": "session0", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "abortTransaction" ], "errorCode": 24 } } } }, { "name": "abortTransaction", "object": "session0" }, { "name": "assertSessionUnpinned", "object": "testRunner", "arguments": { "session": "session0" } }, { "name": "startTransaction", "object": "session0" }, { "name": "insertOne", "object": "collection0", "arguments": { "document": { "x": 1 }, "session": "session0" } }, { "name": "abortTransaction", "object": "session0" } ] }, { "description": "unpin after TransientTransactionError error on abort", "runOnRequirements": [ { "topologies": [ "sharded" ] } ], "operations": [ { "name": "startTransaction", "object": "session0" }, { "name": "insertOne", "object": "collection0", "arguments": { "document": { "x": 1 }, "session": "session0" } }, { "name": "targetedFailPoint", "object": "testRunner", "arguments": { "session": "session0", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "abortTransaction" ], "errorCode": 91 } } } }, { "name": "abortTransaction", "object": "session0" }, { "name": "assertSessionUnpinned", "object": "testRunner", "arguments": { "session": "session0" } }, { "name": "startTransaction", "object": "session0" }, { "name": "insertOne", "object": "collection0", "arguments": { "document": { "x": 1 }, "session": "session0" } }, { "name": "abortTransaction", "object": "session0" } ] }, { "description": "unpin when a new transaction is started", "operations": [ { "name": "startTransaction", "object": "session0" }, { "name": "insertOne", "object": "collection0", "arguments": { "document": { "x": 1 }, "session": "session0" } }, { "name": "commitTransaction", "object": "session0" }, { "name": "assertSessionPinned", "object": "testRunner", "arguments": { "session": "session0" } }, { "name": "startTransaction", "object": "session0" }, { "name": "assertSessionUnpinned", "object": "testRunner", "arguments": { "session": "session0" } } ] }, { "description": "unpin when a non-transaction write operation uses a session", "operations": [ { "name": "startTransaction", "object": "session0" }, { "name": "insertOne", "object": "collection0", "arguments": { "document": { "x": 1 }, "session": "session0" } }, { "name": "commitTransaction", "object": "session0" }, { "name": "assertSessionPinned", "object": "testRunner", "arguments": { "session": "session0" } }, { "name": "insertOne", "object": "collection0", "arguments": { "document": { "x": 1 }, "session": "session0" } }, { "name": "assertSessionUnpinned", "object": "testRunner", "arguments": { "session": "session0" } } ] }, { "description": "unpin when a non-transaction read operation uses a session", "operations": [ { "name": "startTransaction", "object": "session0" }, { "name": "insertOne", "object": "collection0", "arguments": { "document": { "x": 1 }, "session": "session0" } }, { "name": "commitTransaction", "object": "session0" }, { "name": "assertSessionPinned", "object": "testRunner", "arguments": { "session": "session0" } }, { "name": "find", "object": "collection0", "arguments": { "filter": { "x": 1 }, "session": "session0" } }, { "name": "assertSessionUnpinned", "object": "testRunner", "arguments": { "session": "session0" } } ] } ] } mongodb-mongo-python-driver-509e9b7/test/transactions/unified/pin-mongos.json000066400000000000000000001014671462766011000275410ustar00rootroot00000000000000{ "description": "pin-mongos", "schemaVersion": "1.9", "runOnRequirements": [ { "minServerVersion": "4.1.8", "serverless": "forbid", "topologies": [ "sharded", "load-balanced" ] } ], "createEntities": [ { "client": { "id": "client0", "useMultipleMongoses": true, "observeEvents": [ "commandStartedEvent" ] } }, { "database": { "id": "database0", "client": "client0", "databaseName": "transaction-tests" } }, { "collection": { "id": "collection0", "database": "database0", "collectionName": "test" } }, { "session": { "id": "session0", "client": "client0" } } ], "initialData": [ { "collectionName": "test", "databaseName": "transaction-tests", "documents": [ { "_id": 1 }, { "_id": 2 } ] } ], "tests": [ { "description": "countDocuments", "operations": [ { "object": "session0", "name": "startTransaction" }, { "object": "collection0", "name": "countDocuments", "arguments": { "filter": { "_id": 2 }, "session": "session0" }, "expectResult": 1 }, { "object": "collection0", "name": "countDocuments", "arguments": { "filter": { "_id": 2 }, "session": "session0" }, "expectResult": 1 }, { "object": "collection0", "name": "countDocuments", "arguments": { "filter": { "_id": 2 }, "session": "session0" }, "expectResult": 1 }, { "object": "collection0", "name": "countDocuments", "arguments": { "filter": { "_id": 2 }, "session": "session0" }, "expectResult": 1 }, { "object": "collection0", "name": "countDocuments", "arguments": { "filter": { "_id": 2 }, "session": "session0" }, "expectResult": 1 }, { "object": "collection0", "name": "countDocuments", "arguments": { "filter": { "_id": 2 }, "session": "session0" }, "expectResult": 1 }, { "object": "collection0", "name": "countDocuments", "arguments": { "filter": { "_id": 2 }, "session": "session0" }, "expectResult": 1 }, { "object": "collection0", "name": "countDocuments", "arguments": { "filter": { "_id": 2 }, "session": "session0" }, "expectResult": 1 }, { "object": "session0", "name": "commitTransaction" } ], "outcome": [ { "collectionName": "test", "databaseName": "transaction-tests", "documents": [ { "_id": 1 }, { "_id": 2 } ] } ] }, { "description": "distinct", "operations": [ { "object": "session0", "name": "startTransaction" }, { "object": "collection0", "name": "distinct", "arguments": { "fieldName": "_id", "filter": {}, "session": "session0" }, "expectResult": [ 1, 2 ] }, { "object": "collection0", "name": "distinct", "arguments": { "fieldName": "_id", "filter": {}, "session": "session0" }, "expectResult": [ 1, 2 ] }, { "object": "collection0", "name": "distinct", "arguments": { "fieldName": "_id", "filter": {}, "session": "session0" }, "expectResult": [ 1, 2 ] }, { "object": "collection0", "name": "distinct", "arguments": { "fieldName": "_id", "filter": {}, "session": "session0" }, "expectResult": [ 1, 2 ] }, { "object": "collection0", "name": "distinct", "arguments": { "fieldName": "_id", "filter": {}, "session": "session0" }, "expectResult": [ 1, 2 ] }, { "object": "collection0", "name": "distinct", "arguments": { "fieldName": "_id", "filter": {}, "session": "session0" }, "expectResult": [ 1, 2 ] }, { "object": "collection0", "name": "distinct", "arguments": { "fieldName": "_id", "filter": {}, "session": "session0" }, "expectResult": [ 1, 2 ] }, { "object": "collection0", "name": "distinct", "arguments": { "fieldName": "_id", "filter": {}, "session": "session0" }, "expectResult": [ 1, 2 ] }, { "object": "session0", "name": "commitTransaction" } ], "outcome": [ { "collectionName": "test", "databaseName": "transaction-tests", "documents": [ { "_id": 1 }, { "_id": 2 } ] } ] }, { "description": "find", "operations": [ { "object": "session0", "name": "startTransaction" }, { "object": "collection0", "name": "find", "arguments": { "filter": { "_id": 2 }, "session": "session0" }, "expectResult": [ { "_id": 2 } ] }, { "object": "collection0", "name": "find", "arguments": { "filter": { "_id": 2 }, "session": "session0" }, "expectResult": [ { "_id": 2 } ] }, { "object": "collection0", "name": "find", "arguments": { "filter": { "_id": 2 }, "session": "session0" }, "expectResult": [ { "_id": 2 } ] }, { "object": "collection0", "name": "find", "arguments": { "filter": { "_id": 2 }, "session": "session0" }, "expectResult": [ { "_id": 2 } ] }, { "object": "collection0", "name": "find", "arguments": { "filter": { "_id": 2 }, "session": "session0" }, "expectResult": [ { "_id": 2 } ] }, { "object": "collection0", "name": "find", "arguments": { "filter": { "_id": 2 }, "session": "session0" }, "expectResult": [ { "_id": 2 } ] }, { "object": "collection0", "name": "find", "arguments": { "filter": { "_id": 2 }, "session": "session0" }, "expectResult": [ { "_id": 2 } ] }, { "object": "collection0", "name": "find", "arguments": { "filter": { "_id": 2 }, "session": "session0" }, "expectResult": [ { "_id": 2 } ] }, { "object": "session0", "name": "commitTransaction" } ], "outcome": [ { "collectionName": "test", "databaseName": "transaction-tests", "documents": [ { "_id": 1 }, { "_id": 2 } ] } ] }, { "description": "insertOne", "operations": [ { "object": "session0", "name": "startTransaction" }, { "object": "collection0", "name": "insertOne", "arguments": { "document": { "_id": 3 }, "session": "session0" }, "expectResult": { "$$unsetOrMatches": { "insertedId": { "$$unsetOrMatches": 3 } } } }, { "object": "collection0", "name": "insertOne", "arguments": { "document": { "_id": 4 }, "session": "session0" }, "expectResult": { "$$unsetOrMatches": { "insertedId": { "$$unsetOrMatches": 4 } } } }, { "object": "collection0", "name": "insertOne", "arguments": { "document": { "_id": 5 }, "session": "session0" }, "expectResult": { "$$unsetOrMatches": { "insertedId": { "$$unsetOrMatches": 5 } } } }, { "object": "collection0", "name": "insertOne", "arguments": { "document": { "_id": 6 }, "session": "session0" }, "expectResult": { "$$unsetOrMatches": { "insertedId": { "$$unsetOrMatches": 6 } } } }, { "object": "collection0", "name": "insertOne", "arguments": { "document": { "_id": 7 }, "session": "session0" }, "expectResult": { "$$unsetOrMatches": { "insertedId": { "$$unsetOrMatches": 7 } } } }, { "object": "collection0", "name": "insertOne", "arguments": { "document": { "_id": 8 }, "session": "session0" }, "expectResult": { "$$unsetOrMatches": { "insertedId": { "$$unsetOrMatches": 8 } } } }, { "object": "collection0", "name": "insertOne", "arguments": { "document": { "_id": 9 }, "session": "session0" }, "expectResult": { "$$unsetOrMatches": { "insertedId": { "$$unsetOrMatches": 9 } } } }, { "object": "collection0", "name": "insertOne", "arguments": { "document": { "_id": 10 }, "session": "session0" }, "expectResult": { "$$unsetOrMatches": { "insertedId": { "$$unsetOrMatches": 10 } } } }, { "object": "session0", "name": "commitTransaction" } ], "outcome": [ { "collectionName": "test", "databaseName": "transaction-tests", "documents": [ { "_id": 1 }, { "_id": 2 }, { "_id": 3 }, { "_id": 4 }, { "_id": 5 }, { "_id": 6 }, { "_id": 7 }, { "_id": 8 }, { "_id": 9 }, { "_id": 10 } ] } ] }, { "description": "mixed read write operations", "operations": [ { "object": "session0", "name": "startTransaction" }, { "object": "collection0", "name": "insertOne", "arguments": { "document": { "_id": 3 }, "session": "session0" }, "expectResult": { "$$unsetOrMatches": { "insertedId": { "$$unsetOrMatches": 3 } } } }, { "object": "collection0", "name": "countDocuments", "arguments": { "filter": { "_id": 3 }, "session": "session0" }, "expectResult": 1 }, { "object": "collection0", "name": "countDocuments", "arguments": { "filter": { "_id": 3 }, "session": "session0" }, "expectResult": 1 }, { "object": "collection0", "name": "countDocuments", "arguments": { "filter": { "_id": 3 }, "session": "session0" }, "expectResult": 1 }, { "object": "collection0", "name": "countDocuments", "arguments": { "filter": { "_id": 3 }, "session": "session0" }, "expectResult": 1 }, { "object": "collection0", "name": "countDocuments", "arguments": { "filter": { "_id": 3 }, "session": "session0" }, "expectResult": 1 }, { "object": "collection0", "name": "insertOne", "arguments": { "document": { "_id": 4 }, "session": "session0" }, "expectResult": { "$$unsetOrMatches": { "insertedId": { "$$unsetOrMatches": 4 } } } }, { "object": "collection0", "name": "insertOne", "arguments": { "document": { "_id": 5 }, "session": "session0" }, "expectResult": { "$$unsetOrMatches": { "insertedId": { "$$unsetOrMatches": 5 } } } }, { "object": "collection0", "name": "insertOne", "arguments": { "document": { "_id": 6 }, "session": "session0" }, "expectResult": { "$$unsetOrMatches": { "insertedId": { "$$unsetOrMatches": 6 } } } }, { "object": "collection0", "name": "insertOne", "arguments": { "document": { "_id": 7 }, "session": "session0" }, "expectResult": { "$$unsetOrMatches": { "insertedId": { "$$unsetOrMatches": 7 } } } }, { "object": "session0", "name": "commitTransaction" } ], "outcome": [ { "collectionName": "test", "databaseName": "transaction-tests", "documents": [ { "_id": 1 }, { "_id": 2 }, { "_id": 3 }, { "_id": 4 }, { "_id": 5 }, { "_id": 6 }, { "_id": 7 } ] } ] }, { "description": "multiple commits", "operations": [ { "object": "session0", "name": "startTransaction" }, { "object": "collection0", "name": "insertMany", "arguments": { "documents": [ { "_id": 3 }, { "_id": 4 } ], "session": "session0" }, "expectResult": { "$$unsetOrMatches": { "insertedIds": { "$$unsetOrMatches": { "0": 3, "1": 4 } } } } }, { "object": "testRunner", "name": "assertSessionPinned", "arguments": { "session": "session0" } }, { "object": "session0", "name": "commitTransaction" }, { "object": "testRunner", "name": "assertSessionPinned", "arguments": { "session": "session0" } }, { "object": "session0", "name": "commitTransaction" }, { "object": "session0", "name": "commitTransaction" }, { "object": "session0", "name": "commitTransaction" }, { "object": "session0", "name": "commitTransaction" }, { "object": "session0", "name": "commitTransaction" }, { "object": "session0", "name": "commitTransaction" }, { "object": "session0", "name": "commitTransaction" }, { "object": "session0", "name": "commitTransaction" }, { "object": "session0", "name": "commitTransaction" }, { "object": "testRunner", "name": "assertSessionPinned", "arguments": { "session": "session0" } } ], "outcome": [ { "collectionName": "test", "databaseName": "transaction-tests", "documents": [ { "_id": 1 }, { "_id": 2 }, { "_id": 3 }, { "_id": 4 } ] } ] }, { "description": "remain pinned after non-transient error on commit", "runOnRequirements": [ { "topologies": [ "sharded" ] } ], "operations": [ { "object": "session0", "name": "startTransaction" }, { "object": "collection0", "name": "insertMany", "arguments": { "documents": [ { "_id": 3 }, { "_id": 4 } ], "session": "session0" }, "expectResult": { "$$unsetOrMatches": { "insertedIds": { "$$unsetOrMatches": { "0": 3, "1": 4 } } } } }, { "object": "testRunner", "name": "assertSessionPinned", "arguments": { "session": "session0" } }, { "object": "testRunner", "name": "targetedFailPoint", "arguments": { "session": "session0", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "commitTransaction" ], "errorCode": 51 } } } }, { "object": "session0", "name": "commitTransaction", "expectError": { "errorLabelsOmit": [ "TransientTransactionError" ], "errorCode": 51 } }, { "object": "testRunner", "name": "assertSessionPinned", "arguments": { "session": "session0" } }, { "object": "session0", "name": "commitTransaction" }, { "object": "testRunner", "name": "assertSessionPinned", "arguments": { "session": "session0" } } ], "outcome": [ { "collectionName": "test", "databaseName": "transaction-tests", "documents": [ { "_id": 1 }, { "_id": 2 }, { "_id": 3 }, { "_id": 4 } ] } ] }, { "description": "unpin after transient error within a transaction", "runOnRequirements": [ { "topologies": [ "sharded" ] } ], "operations": [ { "object": "session0", "name": "startTransaction" }, { "object": "collection0", "name": "insertOne", "arguments": { "session": "session0", "document": { "_id": 3 } }, "expectResult": { "$$unsetOrMatches": { "insertedId": { "$$unsetOrMatches": 3 } } } }, { "object": "testRunner", "name": "targetedFailPoint", "arguments": { "session": "session0", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "insert" ], "closeConnection": true } } } }, { "object": "collection0", "name": "insertOne", "arguments": { "session": "session0", "document": { "_id": 4 } }, "expectError": { "errorLabelsContain": [ "TransientTransactionError" ], "errorLabelsOmit": [ "UnknownTransactionCommitResult" ] } }, { "object": "session0", "name": "abortTransaction" } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "insert": "test", "documents": [ { "_id": 3 } ], "ordered": true, "readConcern": { "$$exists": false }, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": true, "autocommit": false, "writeConcern": { "$$exists": false } }, "commandName": "insert", "databaseName": "transaction-tests" } }, { "commandStartedEvent": { "command": { "insert": "test", "documents": [ { "_id": 4 } ], "ordered": true, "readConcern": { "$$exists": false }, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": { "$$exists": false }, "autocommit": false, "writeConcern": { "$$exists": false } }, "commandName": "insert", "databaseName": "transaction-tests" } }, { "commandStartedEvent": { "command": { "abortTransaction": 1, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": { "$$exists": false }, "autocommit": false, "writeConcern": { "$$exists": false }, "recoveryToken": { "$$exists": true } }, "commandName": "abortTransaction", "databaseName": "admin" } } ] } ], "outcome": [ { "collectionName": "test", "databaseName": "transaction-tests", "documents": [ { "_id": 1 }, { "_id": 2 } ] } ] }, { "description": "unpin after transient error within a transaction and commit", "runOnRequirements": [ { "topologies": [ "sharded" ] } ], "operations": [ { "object": "testRunner", "name": "createEntities", "arguments": { "entities": [ { "client": { "id": "client1", "useMultipleMongoses": true, "uriOptions": { "heartbeatFrequencyMS": 30000 }, "observeEvents": [ "commandStartedEvent" ] } }, { "database": { "id": "database1", "client": "client1", "databaseName": "transaction-tests" } }, { "collection": { "id": "collection1", "database": "database1", "collectionName": "test" } }, { "session": { "id": "session1", "client": "client1" } } ] } }, { "object": "session1", "name": "startTransaction" }, { "object": "collection1", "name": "insertOne", "arguments": { "session": "session1", "document": { "_id": 3 } }, "expectResult": { "$$unsetOrMatches": { "insertedId": { "$$unsetOrMatches": 3 } } } }, { "object": "testRunner", "name": "targetedFailPoint", "arguments": { "session": "session1", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 7 }, "data": { "failCommands": [ "insert", "isMaster", "hello" ], "closeConnection": true } } } }, { "object": "collection1", "name": "insertOne", "arguments": { "session": "session1", "document": { "_id": 4 } }, "expectError": { "errorLabelsContain": [ "TransientTransactionError" ], "errorLabelsOmit": [ "UnknownTransactionCommitResult" ] } }, { "object": "session1", "name": "commitTransaction", "expectError": { "errorLabelsContain": [ "TransientTransactionError" ], "errorLabelsOmit": [ "UnknownTransactionCommitResult" ], "errorCodeName": "NoSuchTransaction" } } ], "expectEvents": [ { "client": "client1", "events": [ { "commandStartedEvent": { "command": { "insert": "test", "documents": [ { "_id": 3 } ], "ordered": true, "readConcern": { "$$exists": false }, "lsid": { "$$sessionLsid": "session1" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": true, "autocommit": false, "writeConcern": { "$$exists": false } }, "commandName": "insert", "databaseName": "transaction-tests" } }, { "commandStartedEvent": { "command": { "insert": "test", "documents": [ { "_id": 4 } ], "ordered": true, "readConcern": { "$$exists": false }, "lsid": { "$$sessionLsid": "session1" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": { "$$exists": false }, "autocommit": false, "writeConcern": { "$$exists": false } }, "commandName": "insert", "databaseName": "transaction-tests" } }, { "commandStartedEvent": { "command": { "commitTransaction": 1, "lsid": { "$$sessionLsid": "session1" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": { "$$exists": false }, "autocommit": false, "writeConcern": { "$$exists": false }, "recoveryToken": { "$$exists": true } }, "commandName": "commitTransaction", "databaseName": "admin" } } ] } ], "outcome": [ { "collectionName": "test", "databaseName": "transaction-tests", "documents": [ { "_id": 1 }, { "_id": 2 } ] } ] } ] } mongodb-mongo-python-driver-509e9b7/test/transactions/unified/read-concern.json000066400000000000000000001415071462766011000300120ustar00rootroot00000000000000{ "description": "read-concern", "schemaVersion": "1.3", "runOnRequirements": [ { "minServerVersion": "4.0", "topologies": [ "replicaset" ] }, { "minServerVersion": "4.1.8", "topologies": [ "sharded", "load-balanced" ] } ], "createEntities": [ { "client": { "id": "client0", "useMultipleMongoses": false, "observeEvents": [ "commandStartedEvent" ] } }, { "database": { "id": "database0", "client": "client0", "databaseName": "transaction-tests" } }, { "database": { "id": "database_rc_majority", "client": "client0", "databaseName": "transaction-tests", "databaseOptions": { "readConcern": { "level": "majority" } } } }, { "collection": { "id": "collection_rc_majority", "database": "database0", "collectionName": "test", "collectionOptions": { "readConcern": { "level": "majority" } } } }, { "session": { "id": "session0", "client": "client0" } } ], "initialData": [ { "collectionName": "test", "databaseName": "transaction-tests", "documents": [ { "_id": 1 }, { "_id": 2 }, { "_id": 3 }, { "_id": 4 } ] } ], "tests": [ { "description": "only first countDocuments includes readConcern", "operations": [ { "object": "session0", "name": "startTransaction", "arguments": { "readConcern": { "level": "majority" } } }, { "object": "collection_rc_majority", "name": "countDocuments", "arguments": { "filter": { "_id": { "$gte": 2 } }, "session": "session0" }, "expectResult": 3 }, { "object": "collection_rc_majority", "name": "countDocuments", "arguments": { "filter": { "_id": { "$gte": 2 } }, "session": "session0" }, "expectResult": 3 }, { "object": "session0", "name": "commitTransaction" } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "aggregate": "test", "pipeline": [ { "$match": { "_id": { "$gte": 2 } } }, { "$group": { "_id": 1, "n": { "$sum": 1 } } } ], "cursor": {}, "lsid": { "$$sessionLsid": "session0" }, "readConcern": { "level": "majority" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": true, "autocommit": false }, "commandName": "aggregate", "databaseName": "transaction-tests" } }, { "commandStartedEvent": { "command": { "aggregate": "test", "pipeline": [ { "$match": { "_id": { "$gte": 2 } } }, { "$group": { "_id": 1, "n": { "$sum": 1 } } } ], "cursor": {}, "lsid": { "$$sessionLsid": "session0" }, "readConcern": { "$$exists": false }, "txnNumber": { "$numberLong": "1" }, "startTransaction": { "$$exists": false }, "autocommit": false }, "commandName": "aggregate", "databaseName": "transaction-tests" } }, { "commandStartedEvent": { "command": { "commitTransaction": 1, "lsid": { "$$sessionLsid": "session0" }, "readConcern": { "$$exists": false }, "txnNumber": { "$numberLong": "1" }, "startTransaction": { "$$exists": false }, "autocommit": false, "writeConcern": { "$$exists": false } }, "commandName": "commitTransaction", "databaseName": "admin" } } ] } ], "outcome": [ { "collectionName": "test", "databaseName": "transaction-tests", "documents": [ { "_id": 1 }, { "_id": 2 }, { "_id": 3 }, { "_id": 4 } ] } ] }, { "description": "only first find includes readConcern", "operations": [ { "object": "session0", "name": "startTransaction", "arguments": { "readConcern": { "level": "majority" } } }, { "object": "collection_rc_majority", "name": "find", "arguments": { "batchSize": 3, "filter": {}, "session": "session0" }, "expectResult": [ { "_id": 1 }, { "_id": 2 }, { "_id": 3 }, { "_id": 4 } ] }, { "object": "collection_rc_majority", "name": "find", "arguments": { "batchSize": 3, "filter": {}, "session": "session0" }, "expectResult": [ { "_id": 1 }, { "_id": 2 }, { "_id": 3 }, { "_id": 4 } ] }, { "object": "session0", "name": "commitTransaction" } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "find": "test", "batchSize": 3, "lsid": { "$$sessionLsid": "session0" }, "readConcern": { "level": "majority" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": true, "autocommit": false }, "commandName": "find", "databaseName": "transaction-tests" } }, { "commandStartedEvent": { "command": { "getMore": { "$$type": [ "int", "long" ] }, "collection": "test", "batchSize": 3, "lsid": { "$$sessionLsid": "session0" }, "readConcern": { "$$exists": false }, "txnNumber": { "$numberLong": "1" }, "startTransaction": { "$$exists": false }, "autocommit": false }, "commandName": "getMore", "databaseName": "transaction-tests" } }, { "commandStartedEvent": { "command": { "find": "test", "batchSize": 3, "lsid": { "$$sessionLsid": "session0" }, "readConcern": { "$$exists": false }, "txnNumber": { "$numberLong": "1" }, "startTransaction": { "$$exists": false }, "autocommit": false }, "commandName": "find", "databaseName": "transaction-tests" } }, { "commandStartedEvent": { "command": { "getMore": { "$$type": [ "int", "long" ] }, "collection": "test", "batchSize": 3, "lsid": { "$$sessionLsid": "session0" }, "readConcern": { "$$exists": false }, "txnNumber": { "$numberLong": "1" }, "startTransaction": { "$$exists": false }, "autocommit": false }, "commandName": "getMore", "databaseName": "transaction-tests" } }, { "commandStartedEvent": { "command": { "commitTransaction": 1, "lsid": { "$$sessionLsid": "session0" }, "readConcern": { "$$exists": false }, "txnNumber": { "$numberLong": "1" }, "startTransaction": { "$$exists": false }, "autocommit": false, "writeConcern": { "$$exists": false } }, "commandName": "commitTransaction", "databaseName": "admin" } } ] } ], "outcome": [ { "collectionName": "test", "databaseName": "transaction-tests", "documents": [ { "_id": 1 }, { "_id": 2 }, { "_id": 3 }, { "_id": 4 } ] } ] }, { "description": "only first aggregate includes readConcern", "operations": [ { "object": "session0", "name": "startTransaction", "arguments": { "readConcern": { "level": "majority" } } }, { "object": "collection_rc_majority", "name": "aggregate", "arguments": { "pipeline": [ { "$project": { "_id": 1 } } ], "batchSize": 3, "session": "session0" }, "expectResult": [ { "_id": 1 }, { "_id": 2 }, { "_id": 3 }, { "_id": 4 } ] }, { "object": "collection_rc_majority", "name": "aggregate", "arguments": { "pipeline": [ { "$project": { "_id": 1 } } ], "batchSize": 3, "session": "session0" }, "expectResult": [ { "_id": 1 }, { "_id": 2 }, { "_id": 3 }, { "_id": 4 } ] }, { "object": "session0", "name": "commitTransaction" } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "aggregate": "test", "pipeline": [ { "$project": { "_id": 1 } } ], "cursor": { "batchSize": 3 }, "lsid": { "$$sessionLsid": "session0" }, "readConcern": { "level": "majority" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": true, "autocommit": false }, "commandName": "aggregate", "databaseName": "transaction-tests" } }, { "commandStartedEvent": { "command": { "getMore": { "$$type": [ "int", "long" ] }, "collection": "test", "batchSize": 3, "lsid": { "$$sessionLsid": "session0" }, "readConcern": { "$$exists": false }, "txnNumber": { "$numberLong": "1" }, "startTransaction": { "$$exists": false }, "autocommit": false }, "commandName": "getMore", "databaseName": "transaction-tests" } }, { "commandStartedEvent": { "command": { "aggregate": "test", "pipeline": [ { "$project": { "_id": 1 } } ], "cursor": { "batchSize": 3 }, "lsid": { "$$sessionLsid": "session0" }, "readConcern": { "$$exists": false }, "txnNumber": { "$numberLong": "1" }, "startTransaction": { "$$exists": false }, "autocommit": false }, "commandName": "aggregate", "databaseName": "transaction-tests" } }, { "commandStartedEvent": { "command": { "getMore": { "$$type": [ "int", "long" ] }, "collection": "test", "batchSize": 3, "lsid": { "$$sessionLsid": "session0" }, "readConcern": { "$$exists": false }, "txnNumber": { "$numberLong": "1" }, "startTransaction": { "$$exists": false }, "autocommit": false }, "commandName": "getMore", "databaseName": "transaction-tests" } }, { "commandStartedEvent": { "command": { "commitTransaction": 1, "lsid": { "$$sessionLsid": "session0" }, "readConcern": { "$$exists": false }, "txnNumber": { "$numberLong": "1" }, "startTransaction": { "$$exists": false }, "autocommit": false, "writeConcern": { "$$exists": false } }, "commandName": "commitTransaction", "databaseName": "admin" } } ] } ], "outcome": [ { "collectionName": "test", "databaseName": "transaction-tests", "documents": [ { "_id": 1 }, { "_id": 2 }, { "_id": 3 }, { "_id": 4 } ] } ] }, { "description": "only first distinct includes readConcern", "operations": [ { "object": "session0", "name": "startTransaction", "arguments": { "readConcern": { "level": "majority" } } }, { "object": "collection_rc_majority", "name": "distinct", "arguments": { "fieldName": "_id", "filter": {}, "session": "session0" }, "expectResult": [ 1, 2, 3, 4 ] }, { "object": "collection_rc_majority", "name": "distinct", "arguments": { "fieldName": "_id", "filter": {}, "session": "session0" }, "expectResult": [ 1, 2, 3, 4 ] }, { "object": "session0", "name": "commitTransaction" } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "distinct": "test", "key": "_id", "lsid": { "$$sessionLsid": "session0" }, "readConcern": { "level": "majority" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": true, "autocommit": false, "writeConcern": { "$$exists": false } }, "commandName": "distinct", "databaseName": "transaction-tests" } }, { "commandStartedEvent": { "command": { "distinct": "test", "key": "_id", "lsid": { "$$sessionLsid": "session0" }, "readConcern": { "$$exists": false }, "txnNumber": { "$numberLong": "1" }, "startTransaction": { "$$exists": false }, "autocommit": false, "writeConcern": { "$$exists": false } }, "commandName": "distinct", "databaseName": "transaction-tests" } }, { "commandStartedEvent": { "command": { "commitTransaction": 1, "lsid": { "$$sessionLsid": "session0" }, "readConcern": { "$$exists": false }, "txnNumber": { "$numberLong": "1" }, "startTransaction": { "$$exists": false }, "autocommit": false, "writeConcern": { "$$exists": false } }, "commandName": "commitTransaction", "databaseName": "admin" } } ] } ], "outcome": [ { "collectionName": "test", "databaseName": "transaction-tests", "documents": [ { "_id": 1 }, { "_id": 2 }, { "_id": 3 }, { "_id": 4 } ] } ] }, { "description": "only first runCommand includes readConcern", "operations": [ { "object": "session0", "name": "startTransaction", "arguments": { "readConcern": { "level": "majority" } } }, { "object": "database0", "name": "runCommand", "arguments": { "session": "session0", "command": { "find": "test" }, "commandName": "find" } }, { "object": "database0", "name": "runCommand", "arguments": { "session": "session0", "command": { "find": "test" }, "commandName": "find" } }, { "object": "session0", "name": "commitTransaction" } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "find": "test", "lsid": { "$$sessionLsid": "session0" }, "readConcern": { "level": "majority" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": true, "autocommit": false, "writeConcern": { "$$exists": false } }, "commandName": "find", "databaseName": "transaction-tests" } }, { "commandStartedEvent": { "command": { "find": "test", "lsid": { "$$sessionLsid": "session0" }, "readConcern": { "$$exists": false }, "txnNumber": { "$numberLong": "1" }, "startTransaction": { "$$exists": false }, "autocommit": false, "writeConcern": { "$$exists": false } }, "commandName": "find", "databaseName": "transaction-tests" } }, { "commandStartedEvent": { "command": { "commitTransaction": 1, "lsid": { "$$sessionLsid": "session0" }, "readConcern": { "$$exists": false }, "txnNumber": { "$numberLong": "1" }, "startTransaction": { "$$exists": false }, "autocommit": false, "writeConcern": { "$$exists": false } }, "commandName": "commitTransaction", "databaseName": "admin" } } ] } ], "outcome": [ { "collectionName": "test", "databaseName": "transaction-tests", "documents": [ { "_id": 1 }, { "_id": 2 }, { "_id": 3 }, { "_id": 4 } ] } ] }, { "description": "countDocuments ignores collection readConcern", "operations": [ { "object": "session0", "name": "startTransaction" }, { "object": "collection_rc_majority", "name": "countDocuments", "arguments": { "filter": { "_id": { "$gte": 2 } }, "session": "session0" }, "expectResult": 3 }, { "object": "collection_rc_majority", "name": "countDocuments", "arguments": { "filter": { "_id": { "$gte": 2 } }, "session": "session0" }, "expectResult": 3 }, { "object": "session0", "name": "commitTransaction" } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "aggregate": "test", "pipeline": [ { "$match": { "_id": { "$gte": 2 } } }, { "$group": { "_id": 1, "n": { "$sum": 1 } } } ], "cursor": {}, "lsid": { "$$sessionLsid": "session0" }, "readConcern": { "$$exists": false }, "txnNumber": { "$numberLong": "1" }, "startTransaction": true, "autocommit": false }, "commandName": "aggregate", "databaseName": "transaction-tests" } }, { "commandStartedEvent": { "command": { "aggregate": "test", "pipeline": [ { "$match": { "_id": { "$gte": 2 } } }, { "$group": { "_id": 1, "n": { "$sum": 1 } } } ], "cursor": {}, "lsid": { "$$sessionLsid": "session0" }, "readConcern": { "$$exists": false }, "txnNumber": { "$numberLong": "1" }, "startTransaction": { "$$exists": false }, "autocommit": false }, "commandName": "aggregate", "databaseName": "transaction-tests" } }, { "commandStartedEvent": { "command": { "commitTransaction": 1, "lsid": { "$$sessionLsid": "session0" }, "readConcern": { "$$exists": false }, "txnNumber": { "$numberLong": "1" }, "startTransaction": { "$$exists": false }, "autocommit": false, "writeConcern": { "$$exists": false } }, "commandName": "commitTransaction", "databaseName": "admin" } } ] } ], "outcome": [ { "collectionName": "test", "databaseName": "transaction-tests", "documents": [ { "_id": 1 }, { "_id": 2 }, { "_id": 3 }, { "_id": 4 } ] } ] }, { "description": "find ignores collection readConcern", "operations": [ { "object": "session0", "name": "startTransaction" }, { "object": "collection_rc_majority", "name": "find", "arguments": { "batchSize": 3, "filter": {}, "session": "session0" }, "expectResult": [ { "_id": 1 }, { "_id": 2 }, { "_id": 3 }, { "_id": 4 } ] }, { "object": "collection_rc_majority", "name": "find", "arguments": { "batchSize": 3, "filter": {}, "session": "session0" }, "expectResult": [ { "_id": 1 }, { "_id": 2 }, { "_id": 3 }, { "_id": 4 } ] }, { "object": "session0", "name": "commitTransaction" } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "find": "test", "batchSize": 3, "lsid": { "$$sessionLsid": "session0" }, "readConcern": { "$$exists": false }, "txnNumber": { "$numberLong": "1" }, "startTransaction": true, "autocommit": false }, "commandName": "find", "databaseName": "transaction-tests" } }, { "commandStartedEvent": { "command": { "getMore": { "$$type": [ "int", "long" ] }, "collection": "test", "batchSize": 3, "lsid": { "$$sessionLsid": "session0" }, "readConcern": { "$$exists": false }, "txnNumber": { "$numberLong": "1" }, "startTransaction": { "$$exists": false }, "autocommit": false }, "commandName": "getMore", "databaseName": "transaction-tests" } }, { "commandStartedEvent": { "command": { "find": "test", "batchSize": 3, "lsid": { "$$sessionLsid": "session0" }, "readConcern": { "$$exists": false }, "txnNumber": { "$numberLong": "1" }, "startTransaction": { "$$exists": false }, "autocommit": false }, "commandName": "find", "databaseName": "transaction-tests" } }, { "commandStartedEvent": { "command": { "getMore": { "$$type": [ "int", "long" ] }, "collection": "test", "batchSize": 3, "lsid": { "$$sessionLsid": "session0" }, "readConcern": { "$$exists": false }, "txnNumber": { "$numberLong": "1" }, "startTransaction": { "$$exists": false }, "autocommit": false }, "commandName": "getMore", "databaseName": "transaction-tests" } }, { "commandStartedEvent": { "command": { "commitTransaction": 1, "lsid": { "$$sessionLsid": "session0" }, "readConcern": { "$$exists": false }, "txnNumber": { "$numberLong": "1" }, "startTransaction": { "$$exists": false }, "autocommit": false, "writeConcern": { "$$exists": false } }, "commandName": "commitTransaction", "databaseName": "admin" } } ] } ], "outcome": [ { "collectionName": "test", "databaseName": "transaction-tests", "documents": [ { "_id": 1 }, { "_id": 2 }, { "_id": 3 }, { "_id": 4 } ] } ] }, { "description": "aggregate ignores collection readConcern", "operations": [ { "object": "session0", "name": "startTransaction" }, { "object": "collection_rc_majority", "name": "aggregate", "arguments": { "pipeline": [ { "$project": { "_id": 1 } } ], "batchSize": 3, "session": "session0" }, "expectResult": [ { "_id": 1 }, { "_id": 2 }, { "_id": 3 }, { "_id": 4 } ] }, { "object": "collection_rc_majority", "name": "aggregate", "arguments": { "pipeline": [ { "$project": { "_id": 1 } } ], "batchSize": 3, "session": "session0" }, "expectResult": [ { "_id": 1 }, { "_id": 2 }, { "_id": 3 }, { "_id": 4 } ] }, { "object": "session0", "name": "commitTransaction" } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "aggregate": "test", "pipeline": [ { "$project": { "_id": 1 } } ], "cursor": { "batchSize": 3 }, "lsid": { "$$sessionLsid": "session0" }, "readConcern": { "$$exists": false }, "txnNumber": { "$numberLong": "1" }, "startTransaction": true, "autocommit": false }, "commandName": "aggregate", "databaseName": "transaction-tests" } }, { "commandStartedEvent": { "command": { "getMore": { "$$type": [ "int", "long" ] }, "collection": "test", "batchSize": 3, "lsid": { "$$sessionLsid": "session0" }, "readConcern": { "$$exists": false }, "txnNumber": { "$numberLong": "1" }, "startTransaction": { "$$exists": false }, "autocommit": false }, "commandName": "getMore", "databaseName": "transaction-tests" } }, { "commandStartedEvent": { "command": { "aggregate": "test", "pipeline": [ { "$project": { "_id": 1 } } ], "cursor": { "batchSize": 3 }, "lsid": { "$$sessionLsid": "session0" }, "readConcern": { "$$exists": false }, "txnNumber": { "$numberLong": "1" }, "startTransaction": { "$$exists": false }, "autocommit": false }, "commandName": "aggregate", "databaseName": "transaction-tests" } }, { "commandStartedEvent": { "command": { "getMore": { "$$type": [ "int", "long" ] }, "collection": "test", "batchSize": 3, "lsid": { "$$sessionLsid": "session0" }, "readConcern": { "$$exists": false }, "txnNumber": { "$numberLong": "1" }, "startTransaction": { "$$exists": false }, "autocommit": false }, "commandName": "getMore", "databaseName": "transaction-tests" } }, { "commandStartedEvent": { "command": { "commitTransaction": 1, "lsid": { "$$sessionLsid": "session0" }, "readConcern": { "$$exists": false }, "txnNumber": { "$numberLong": "1" }, "startTransaction": { "$$exists": false }, "autocommit": false, "writeConcern": { "$$exists": false } }, "commandName": "commitTransaction", "databaseName": "admin" } } ] } ], "outcome": [ { "collectionName": "test", "databaseName": "transaction-tests", "documents": [ { "_id": 1 }, { "_id": 2 }, { "_id": 3 }, { "_id": 4 } ] } ] }, { "description": "distinct ignores collection readConcern", "operations": [ { "object": "session0", "name": "startTransaction" }, { "object": "collection_rc_majority", "name": "distinct", "arguments": { "fieldName": "_id", "filter": {}, "session": "session0" }, "expectResult": [ 1, 2, 3, 4 ] }, { "object": "collection_rc_majority", "name": "distinct", "arguments": { "fieldName": "_id", "filter": {}, "session": "session0" }, "expectResult": [ 1, 2, 3, 4 ] }, { "object": "session0", "name": "commitTransaction" } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "distinct": "test", "key": "_id", "lsid": { "$$sessionLsid": "session0" }, "readConcern": { "$$exists": false }, "txnNumber": { "$numberLong": "1" }, "startTransaction": true, "autocommit": false, "writeConcern": { "$$exists": false } }, "commandName": "distinct", "databaseName": "transaction-tests" } }, { "commandStartedEvent": { "command": { "distinct": "test", "key": "_id", "lsid": { "$$sessionLsid": "session0" }, "readConcern": { "$$exists": false }, "txnNumber": { "$numberLong": "1" }, "startTransaction": { "$$exists": false }, "autocommit": false, "writeConcern": { "$$exists": false } }, "commandName": "distinct", "databaseName": "transaction-tests" } }, { "commandStartedEvent": { "command": { "commitTransaction": 1, "lsid": { "$$sessionLsid": "session0" }, "readConcern": { "$$exists": false }, "txnNumber": { "$numberLong": "1" }, "startTransaction": { "$$exists": false }, "autocommit": false, "writeConcern": { "$$exists": false } }, "commandName": "commitTransaction", "databaseName": "admin" } } ] } ], "outcome": [ { "collectionName": "test", "databaseName": "transaction-tests", "documents": [ { "_id": 1 }, { "_id": 2 }, { "_id": 3 }, { "_id": 4 } ] } ] }, { "description": "runCommand ignores database readConcern", "operations": [ { "object": "session0", "name": "startTransaction" }, { "object": "database_rc_majority", "name": "runCommand", "arguments": { "session": "session0", "command": { "find": "test" }, "commandName": "find" } }, { "object": "database0", "name": "runCommand", "arguments": { "session": "session0", "command": { "find": "test" }, "commandName": "find" } }, { "object": "session0", "name": "commitTransaction" } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "find": "test", "lsid": { "$$sessionLsid": "session0" }, "readConcern": { "$$exists": false }, "txnNumber": { "$numberLong": "1" }, "startTransaction": true, "autocommit": false, "writeConcern": { "$$exists": false } }, "commandName": "find", "databaseName": "transaction-tests" } }, { "commandStartedEvent": { "command": { "find": "test", "lsid": { "$$sessionLsid": "session0" }, "readConcern": { "$$exists": false }, "txnNumber": { "$numberLong": "1" }, "startTransaction": { "$$exists": false }, "autocommit": false, "writeConcern": { "$$exists": false } }, "commandName": "find", "databaseName": "transaction-tests" } }, { "commandStartedEvent": { "command": { "commitTransaction": 1, "lsid": { "$$sessionLsid": "session0" }, "readConcern": { "$$exists": false }, "txnNumber": { "$numberLong": "1" }, "startTransaction": { "$$exists": false }, "autocommit": false, "writeConcern": { "$$exists": false } }, "commandName": "commitTransaction", "databaseName": "admin" } } ] } ], "outcome": [ { "collectionName": "test", "databaseName": "transaction-tests", "documents": [ { "_id": 1 }, { "_id": 2 }, { "_id": 3 }, { "_id": 4 } ] } ] } ] } mongodb-mongo-python-driver-509e9b7/test/transactions/unified/read-pref.json000066400000000000000000000371731462766011000273220ustar00rootroot00000000000000{ "description": "read-pref", "schemaVersion": "1.3", "runOnRequirements": [ { "minServerVersion": "4.0", "topologies": [ "replicaset" ] }, { "minServerVersion": "4.1.8", "topologies": [ "sharded", "load-balanced" ] } ], "createEntities": [ { "client": { "id": "client0", "useMultipleMongoses": false, "observeEvents": [ "commandStartedEvent" ] } }, { "database": { "id": "database0", "client": "client0", "databaseName": "transaction-tests" } }, { "collection": { "id": "collection0", "database": "database0", "collectionName": "test" } }, { "collection": { "id": "collection_rp_primary", "database": "database0", "collectionName": "test" } }, { "collection": { "id": "collection_rp_secondary", "database": "database0", "collectionName": "test" } }, { "session": { "id": "session0", "client": "client0" } } ], "initialData": [ { "collectionName": "test", "databaseName": "transaction-tests", "documents": [] } ], "tests": [ { "description": "default readPreference", "operations": [ { "object": "session0", "name": "startTransaction" }, { "object": "collection0", "name": "insertMany", "arguments": { "documents": [ { "_id": 1 }, { "_id": 2 }, { "_id": 3 }, { "_id": 4 } ], "session": "session0" }, "expectResult": { "$$unsetOrMatches": { "insertedIds": { "$$unsetOrMatches": { "0": 1, "1": 2, "2": 3, "3": 4 } } } } }, { "object": "collection_rp_secondary", "name": "aggregate", "arguments": { "session": "session0", "pipeline": [ { "$match": { "_id": 1 } }, { "$count": "count" } ] }, "expectResult": [ { "count": 1 } ] }, { "object": "collection_rp_secondary", "name": "find", "arguments": { "batchSize": 3, "filter": {}, "session": "session0" }, "expectResult": [ { "_id": 1 }, { "_id": 2 }, { "_id": 3 }, { "_id": 4 } ] }, { "object": "collection_rp_secondary", "name": "aggregate", "arguments": { "pipeline": [ { "$project": { "_id": 1 } } ], "batchSize": 3, "session": "session0" }, "expectResult": [ { "_id": 1 }, { "_id": 2 }, { "_id": 3 }, { "_id": 4 } ] }, { "object": "session0", "name": "commitTransaction" } ], "outcome": [ { "collectionName": "test", "databaseName": "transaction-tests", "documents": [ { "_id": 1 }, { "_id": 2 }, { "_id": 3 }, { "_id": 4 } ] } ] }, { "description": "primary readPreference", "operations": [ { "object": "session0", "name": "startTransaction", "arguments": { "readPreference": { "mode": "primary" } } }, { "object": "collection0", "name": "insertMany", "arguments": { "documents": [ { "_id": 1 }, { "_id": 2 }, { "_id": 3 }, { "_id": 4 } ], "session": "session0" }, "expectResult": { "$$unsetOrMatches": { "insertedIds": { "$$unsetOrMatches": { "0": 1, "1": 2, "2": 3, "3": 4 } } } } }, { "object": "collection_rp_secondary", "name": "aggregate", "arguments": { "session": "session0", "pipeline": [ { "$match": { "_id": 1 } }, { "$count": "count" } ] }, "expectResult": [ { "count": 1 } ] }, { "object": "collection_rp_secondary", "name": "find", "arguments": { "batchSize": 3, "filter": {}, "session": "session0" }, "expectResult": [ { "_id": 1 }, { "_id": 2 }, { "_id": 3 }, { "_id": 4 } ] }, { "object": "collection_rp_secondary", "name": "aggregate", "arguments": { "pipeline": [ { "$project": { "_id": 1 } } ], "batchSize": 3, "session": "session0" }, "expectResult": [ { "_id": 1 }, { "_id": 2 }, { "_id": 3 }, { "_id": 4 } ] }, { "object": "session0", "name": "commitTransaction" } ], "outcome": [ { "collectionName": "test", "databaseName": "transaction-tests", "documents": [ { "_id": 1 }, { "_id": 2 }, { "_id": 3 }, { "_id": 4 } ] } ] }, { "description": "secondary readPreference", "operations": [ { "object": "session0", "name": "startTransaction", "arguments": { "readPreference": { "mode": "secondary" } } }, { "object": "collection0", "name": "insertMany", "arguments": { "documents": [ { "_id": 1 }, { "_id": 2 }, { "_id": 3 }, { "_id": 4 } ], "session": "session0" }, "expectResult": { "$$unsetOrMatches": { "insertedIds": { "$$unsetOrMatches": { "0": 1, "1": 2, "2": 3, "3": 4 } } } } }, { "object": "collection_rp_primary", "name": "aggregate", "arguments": { "session": "session0", "pipeline": [ { "$match": { "_id": 1 } }, { "$count": "count" } ] }, "expectError": { "errorContains": "read preference in a transaction must be primary" } }, { "object": "collection_rp_primary", "name": "find", "arguments": { "batchSize": 3, "filter": {}, "session": "session0" }, "expectError": { "errorContains": "read preference in a transaction must be primary" } }, { "object": "collection_rp_primary", "name": "aggregate", "arguments": { "pipeline": [ { "$project": { "_id": 1 } } ], "batchSize": 3, "session": "session0" }, "expectError": { "errorContains": "read preference in a transaction must be primary" } }, { "object": "session0", "name": "abortTransaction" } ], "outcome": [ { "collectionName": "test", "databaseName": "transaction-tests", "documents": [] } ] }, { "description": "primaryPreferred readPreference", "operations": [ { "object": "session0", "name": "startTransaction", "arguments": { "readPreference": { "mode": "primaryPreferred" } } }, { "object": "collection0", "name": "insertMany", "arguments": { "documents": [ { "_id": 1 }, { "_id": 2 }, { "_id": 3 }, { "_id": 4 } ], "session": "session0" }, "expectResult": { "$$unsetOrMatches": { "insertedIds": { "$$unsetOrMatches": { "0": 1, "1": 2, "2": 3, "3": 4 } } } } }, { "object": "collection_rp_primary", "name": "aggregate", "arguments": { "session": "session0", "pipeline": [ { "$match": { "_id": 1 } }, { "$count": "count" } ] }, "expectError": { "errorContains": "read preference in a transaction must be primary" } }, { "object": "collection_rp_primary", "name": "find", "arguments": { "batchSize": 3, "filter": {}, "session": "session0" }, "expectError": { "errorContains": "read preference in a transaction must be primary" } }, { "object": "collection_rp_primary", "name": "aggregate", "arguments": { "pipeline": [ { "$project": { "_id": 1 } } ], "batchSize": 3, "session": "session0" }, "expectError": { "errorContains": "read preference in a transaction must be primary" } }, { "object": "session0", "name": "abortTransaction" } ], "outcome": [ { "collectionName": "test", "databaseName": "transaction-tests", "documents": [] } ] }, { "description": "nearest readPreference", "operations": [ { "object": "session0", "name": "startTransaction", "arguments": { "readPreference": { "mode": "nearest" } } }, { "object": "collection0", "name": "insertMany", "arguments": { "documents": [ { "_id": 1 }, { "_id": 2 }, { "_id": 3 }, { "_id": 4 } ], "session": "session0" }, "expectResult": { "$$unsetOrMatches": { "insertedIds": { "$$unsetOrMatches": { "0": 1, "1": 2, "2": 3, "3": 4 } } } } }, { "object": "collection_rp_primary", "name": "aggregate", "arguments": { "session": "session0", "pipeline": [ { "$match": { "_id": 1 } }, { "$count": "count" } ] }, "expectError": { "errorContains": "read preference in a transaction must be primary" } }, { "object": "collection_rp_primary", "name": "find", "arguments": { "batchSize": 3, "filter": {}, "session": "session0" }, "expectError": { "errorContains": "read preference in a transaction must be primary" } }, { "object": "collection_rp_primary", "name": "aggregate", "arguments": { "pipeline": [ { "$project": { "_id": 1 } } ], "batchSize": 3, "session": "session0" }, "expectError": { "errorContains": "read preference in a transaction must be primary" } }, { "object": "session0", "name": "abortTransaction" } ], "outcome": [ { "collectionName": "test", "databaseName": "transaction-tests", "documents": [] } ] }, { "description": "secondary write only", "operations": [ { "object": "session0", "name": "startTransaction", "arguments": { "readPreference": { "mode": "secondary" } } }, { "object": "collection0", "name": "insertOne", "arguments": { "session": "session0", "document": { "_id": 1 } }, "expectResult": { "$$unsetOrMatches": { "insertedId": { "$$unsetOrMatches": 1 } } } }, { "object": "session0", "name": "commitTransaction" } ], "outcome": [ { "collectionName": "test", "databaseName": "transaction-tests", "documents": [ { "_id": 1 } ] } ] } ] } mongodb-mongo-python-driver-509e9b7/test/transactions/unified/reads.json000066400000000000000000000415431462766011000265470ustar00rootroot00000000000000{ "description": "reads", "schemaVersion": "1.9", "runOnRequirements": [ { "minServerVersion": "4.0", "topologies": [ "replicaset" ] }, { "minServerVersion": "4.1.8", "topologies": [ "sharded", "load-balanced" ] } ], "createEntities": [ { "client": { "id": "client0", "useMultipleMongoses": false, "observeEvents": [ "commandStartedEvent" ] } }, { "database": { "id": "database0", "client": "client0", "databaseName": "transaction-tests" } }, { "collection": { "id": "collection0", "database": "database0", "collectionName": "test" } }, { "session": { "id": "session0", "client": "client0" } } ], "initialData": [ { "collectionName": "test", "databaseName": "transaction-tests", "documents": [ { "_id": 1 }, { "_id": 2 }, { "_id": 3 }, { "_id": 4 } ] } ], "tests": [ { "description": "collection readConcern without transaction", "operations": [ { "object": "testRunner", "name": "createEntities", "arguments": { "entities": [ { "collection": { "id": "collection1", "database": "database0", "collectionName": "test", "collectionOptions": { "readConcern": { "level": "majority" } } } } ] } }, { "object": "collection1", "name": "find", "arguments": { "filter": {}, "session": "session0" }, "expectResult": [ { "_id": 1 }, { "_id": 2 }, { "_id": 3 }, { "_id": 4 } ] } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "find": "test", "readConcern": { "level": "majority" }, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$$exists": false }, "startTransaction": { "$$exists": false }, "autocommit": { "$$exists": false } }, "commandName": "find", "databaseName": "transaction-tests" } } ] } ], "outcome": [ { "collectionName": "test", "databaseName": "transaction-tests", "documents": [ { "_id": 1 }, { "_id": 2 }, { "_id": 3 }, { "_id": 4 } ] } ] }, { "description": "find", "operations": [ { "object": "session0", "name": "startTransaction" }, { "object": "collection0", "name": "find", "arguments": { "batchSize": 3, "filter": {}, "session": "session0" }, "expectResult": [ { "_id": 1 }, { "_id": 2 }, { "_id": 3 }, { "_id": 4 } ] }, { "object": "collection0", "name": "find", "arguments": { "batchSize": 3, "filter": {}, "session": "session0" }, "expectResult": [ { "_id": 1 }, { "_id": 2 }, { "_id": 3 }, { "_id": 4 } ] }, { "object": "session0", "name": "commitTransaction" } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "find": "test", "batchSize": 3, "readConcern": { "$$exists": false }, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": true, "autocommit": false }, "commandName": "find", "databaseName": "transaction-tests" } }, { "commandStartedEvent": { "command": { "getMore": { "$$type": [ "int", "long" ] }, "collection": "test", "batchSize": 3, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": { "$$exists": false }, "autocommit": false }, "commandName": "getMore", "databaseName": "transaction-tests" } }, { "commandStartedEvent": { "command": { "find": "test", "batchSize": 3, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": { "$$exists": false }, "autocommit": false }, "commandName": "find", "databaseName": "transaction-tests" } }, { "commandStartedEvent": { "command": { "getMore": { "$$type": [ "int", "long" ] }, "collection": "test", "batchSize": 3, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": { "$$exists": false }, "autocommit": false }, "commandName": "getMore", "databaseName": "transaction-tests" } }, { "commandStartedEvent": { "command": { "commitTransaction": 1, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": { "$$exists": false }, "autocommit": false, "writeConcern": { "$$exists": false } }, "commandName": "commitTransaction", "databaseName": "admin" } } ] } ], "outcome": [ { "collectionName": "test", "databaseName": "transaction-tests", "documents": [ { "_id": 1 }, { "_id": 2 }, { "_id": 3 }, { "_id": 4 } ] } ] }, { "description": "aggregate", "operations": [ { "object": "session0", "name": "startTransaction" }, { "object": "collection0", "name": "aggregate", "arguments": { "pipeline": [ { "$project": { "_id": 1 } } ], "batchSize": 3, "session": "session0" }, "expectResult": [ { "_id": 1 }, { "_id": 2 }, { "_id": 3 }, { "_id": 4 } ] }, { "object": "collection0", "name": "aggregate", "arguments": { "pipeline": [ { "$project": { "_id": 1 } } ], "batchSize": 3, "session": "session0" }, "expectResult": [ { "_id": 1 }, { "_id": 2 }, { "_id": 3 }, { "_id": 4 } ] }, { "object": "session0", "name": "commitTransaction" } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "aggregate": "test", "pipeline": [ { "$project": { "_id": 1 } } ], "cursor": { "batchSize": 3 }, "readConcern": { "$$exists": false }, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": true, "autocommit": false }, "commandName": "aggregate", "databaseName": "transaction-tests" } }, { "commandStartedEvent": { "command": { "getMore": { "$$type": [ "int", "long" ] }, "collection": "test", "batchSize": 3, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": { "$$exists": false }, "autocommit": false }, "commandName": "getMore", "databaseName": "transaction-tests" } }, { "commandStartedEvent": { "command": { "aggregate": "test", "pipeline": [ { "$project": { "_id": 1 } } ], "cursor": { "batchSize": 3 }, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": { "$$exists": false }, "autocommit": false }, "commandName": "aggregate", "databaseName": "transaction-tests" } }, { "commandStartedEvent": { "command": { "getMore": { "$$type": [ "int", "long" ] }, "collection": "test", "batchSize": 3, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": { "$$exists": false }, "autocommit": false }, "commandName": "getMore", "databaseName": "transaction-tests" } }, { "commandStartedEvent": { "command": { "commitTransaction": 1, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": { "$$exists": false }, "autocommit": false, "writeConcern": { "$$exists": false } }, "commandName": "commitTransaction", "databaseName": "admin" } } ] } ], "outcome": [ { "collectionName": "test", "databaseName": "transaction-tests", "documents": [ { "_id": 1 }, { "_id": 2 }, { "_id": 3 }, { "_id": 4 } ] } ] }, { "description": "distinct", "operations": [ { "object": "session0", "name": "startTransaction" }, { "object": "collection0", "name": "distinct", "arguments": { "fieldName": "_id", "filter": {}, "session": "session0" }, "expectResult": [ 1, 2, 3, 4 ] }, { "object": "session0", "name": "commitTransaction" } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "distinct": "test", "key": "_id", "lsid": { "$$sessionLsid": "session0" }, "readConcern": { "$$exists": false }, "txnNumber": { "$numberLong": "1" }, "startTransaction": true, "autocommit": false, "writeConcern": { "$$exists": false } }, "commandName": "distinct", "databaseName": "transaction-tests" } }, { "commandStartedEvent": { "command": { "commitTransaction": 1, "lsid": { "$$sessionLsid": "session0" }, "readConcern": { "$$exists": false }, "txnNumber": { "$numberLong": "1" }, "startTransaction": { "$$exists": false }, "autocommit": false, "writeConcern": { "$$exists": false } }, "commandName": "commitTransaction", "databaseName": "admin" } } ] } ], "outcome": [ { "collectionName": "test", "databaseName": "transaction-tests", "documents": [ { "_id": 1 }, { "_id": 2 }, { "_id": 3 }, { "_id": 4 } ] } ] } ] } mongodb-mongo-python-driver-509e9b7/test/transactions/unified/retryable-abort-errorLabels.json000066400000000000000000002013011462766011000330070ustar00rootroot00000000000000{ "description": "retryable-abort-errorLabels", "schemaVersion": "1.3", "runOnRequirements": [ { "minServerVersion": "4.3.1", "topologies": [ "replicaset", "sharded", "load-balanced" ] } ], "createEntities": [ { "client": { "id": "client0", "useMultipleMongoses": false, "observeEvents": [ "commandStartedEvent" ] } }, { "database": { "id": "database0", "client": "client0", "databaseName": "transaction-tests" } }, { "collection": { "id": "collection0", "database": "database0", "collectionName": "test" } }, { "session": { "id": "session0", "client": "client0" } } ], "initialData": [ { "collectionName": "test", "databaseName": "transaction-tests", "documents": [] } ], "tests": [ { "description": "abortTransaction only retries once with RetryableWriteError from server", "operations": [ { "object": "testRunner", "name": "failPoint", "arguments": { "client": "client0", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 2 }, "data": { "failCommands": [ "abortTransaction" ], "errorCode": 112, "errorLabels": [ "RetryableWriteError" ] } } } }, { "object": "session0", "name": "startTransaction" }, { "object": "collection0", "name": "insertOne", "arguments": { "session": "session0", "document": { "_id": 1 } }, "expectResult": { "$$unsetOrMatches": { "insertedId": { "$$unsetOrMatches": 1 } } } }, { "object": "session0", "name": "abortTransaction" } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "insert": "test", "documents": [ { "_id": 1 } ], "ordered": true, "readConcern": { "$$exists": false }, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": true, "autocommit": false, "writeConcern": { "$$exists": false } }, "commandName": "insert", "databaseName": "transaction-tests" } }, { "commandStartedEvent": { "command": { "abortTransaction": 1, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": { "$$exists": false }, "autocommit": false, "writeConcern": { "$$exists": false } }, "commandName": "abortTransaction", "databaseName": "admin" } }, { "commandStartedEvent": { "command": { "abortTransaction": 1, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": { "$$exists": false }, "autocommit": false, "writeConcern": { "$$exists": false } }, "commandName": "abortTransaction", "databaseName": "admin" } } ] } ], "outcome": [ { "collectionName": "test", "databaseName": "transaction-tests", "documents": [] } ] }, { "description": "abortTransaction does not retry without RetryableWriteError label", "operations": [ { "object": "testRunner", "name": "failPoint", "arguments": { "client": "client0", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "abortTransaction" ], "errorCode": 11600, "errorLabels": [] } } } }, { "object": "session0", "name": "startTransaction" }, { "object": "collection0", "name": "insertOne", "arguments": { "session": "session0", "document": { "_id": 1 } }, "expectResult": { "$$unsetOrMatches": { "insertedId": { "$$unsetOrMatches": 1 } } } }, { "object": "session0", "name": "abortTransaction" } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "insert": "test", "documents": [ { "_id": 1 } ], "ordered": true, "readConcern": { "$$exists": false }, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": true, "autocommit": false, "writeConcern": { "$$exists": false } }, "commandName": "insert", "databaseName": "transaction-tests" } }, { "commandStartedEvent": { "command": { "abortTransaction": 1, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": { "$$exists": false }, "autocommit": false, "writeConcern": { "$$exists": false } }, "commandName": "abortTransaction", "databaseName": "admin" } } ] } ], "outcome": [ { "collectionName": "test", "databaseName": "transaction-tests", "documents": [] } ] }, { "description": "abortTransaction succeeds after NotWritablePrimary", "operations": [ { "object": "testRunner", "name": "failPoint", "arguments": { "client": "client0", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "abortTransaction" ], "errorCode": 10107, "errorLabels": [ "RetryableWriteError" ], "closeConnection": false } } } }, { "object": "session0", "name": "startTransaction" }, { "object": "collection0", "name": "insertOne", "arguments": { "session": "session0", "document": { "_id": 1 } }, "expectResult": { "$$unsetOrMatches": { "insertedId": { "$$unsetOrMatches": 1 } } } }, { "object": "session0", "name": "abortTransaction" } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "insert": "test", "documents": [ { "_id": 1 } ], "ordered": true, "readConcern": { "$$exists": false }, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": true, "autocommit": false, "writeConcern": { "$$exists": false } }, "commandName": "insert", "databaseName": "transaction-tests" } }, { "commandStartedEvent": { "command": { "abortTransaction": 1, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": { "$$exists": false }, "autocommit": false, "writeConcern": { "$$exists": false } }, "commandName": "abortTransaction", "databaseName": "admin" } }, { "commandStartedEvent": { "command": { "abortTransaction": 1, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": { "$$exists": false }, "autocommit": false, "writeConcern": { "$$exists": false } }, "commandName": "abortTransaction", "databaseName": "admin" } } ] } ], "outcome": [ { "collectionName": "test", "databaseName": "transaction-tests", "documents": [] } ] }, { "description": "abortTransaction succeeds after NotPrimaryOrSecondary", "operations": [ { "object": "testRunner", "name": "failPoint", "arguments": { "client": "client0", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "abortTransaction" ], "errorCode": 13436, "errorLabels": [ "RetryableWriteError" ], "closeConnection": false } } } }, { "object": "session0", "name": "startTransaction" }, { "object": "collection0", "name": "insertOne", "arguments": { "session": "session0", "document": { "_id": 1 } }, "expectResult": { "$$unsetOrMatches": { "insertedId": { "$$unsetOrMatches": 1 } } } }, { "object": "session0", "name": "abortTransaction" } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "insert": "test", "documents": [ { "_id": 1 } ], "ordered": true, "readConcern": { "$$exists": false }, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": true, "autocommit": false, "writeConcern": { "$$exists": false } }, "commandName": "insert", "databaseName": "transaction-tests" } }, { "commandStartedEvent": { "command": { "abortTransaction": 1, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": { "$$exists": false }, "autocommit": false, "writeConcern": { "$$exists": false } }, "commandName": "abortTransaction", "databaseName": "admin" } }, { "commandStartedEvent": { "command": { "abortTransaction": 1, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": { "$$exists": false }, "autocommit": false, "writeConcern": { "$$exists": false } }, "commandName": "abortTransaction", "databaseName": "admin" } } ] } ], "outcome": [ { "collectionName": "test", "databaseName": "transaction-tests", "documents": [] } ] }, { "description": "abortTransaction succeeds after NotPrimaryNoSecondaryOk", "operations": [ { "object": "testRunner", "name": "failPoint", "arguments": { "client": "client0", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "abortTransaction" ], "errorCode": 13435, "errorLabels": [ "RetryableWriteError" ], "closeConnection": false } } } }, { "object": "session0", "name": "startTransaction" }, { "object": "collection0", "name": "insertOne", "arguments": { "session": "session0", "document": { "_id": 1 } }, "expectResult": { "$$unsetOrMatches": { "insertedId": { "$$unsetOrMatches": 1 } } } }, { "object": "session0", "name": "abortTransaction" } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "insert": "test", "documents": [ { "_id": 1 } ], "ordered": true, "readConcern": { "$$exists": false }, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": true, "autocommit": false, "writeConcern": { "$$exists": false } }, "commandName": "insert", "databaseName": "transaction-tests" } }, { "commandStartedEvent": { "command": { "abortTransaction": 1, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": { "$$exists": false }, "autocommit": false, "writeConcern": { "$$exists": false } }, "commandName": "abortTransaction", "databaseName": "admin" } }, { "commandStartedEvent": { "command": { "abortTransaction": 1, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": { "$$exists": false }, "autocommit": false, "writeConcern": { "$$exists": false } }, "commandName": "abortTransaction", "databaseName": "admin" } } ] } ], "outcome": [ { "collectionName": "test", "databaseName": "transaction-tests", "documents": [] } ] }, { "description": "abortTransaction succeeds after InterruptedDueToReplStateChange", "operations": [ { "object": "testRunner", "name": "failPoint", "arguments": { "client": "client0", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "abortTransaction" ], "errorCode": 11602, "errorLabels": [ "RetryableWriteError" ], "closeConnection": false } } } }, { "object": "session0", "name": "startTransaction" }, { "object": "collection0", "name": "insertOne", "arguments": { "session": "session0", "document": { "_id": 1 } }, "expectResult": { "$$unsetOrMatches": { "insertedId": { "$$unsetOrMatches": 1 } } } }, { "object": "session0", "name": "abortTransaction" } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "insert": "test", "documents": [ { "_id": 1 } ], "ordered": true, "readConcern": { "$$exists": false }, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": true, "autocommit": false, "writeConcern": { "$$exists": false } }, "commandName": "insert", "databaseName": "transaction-tests" } }, { "commandStartedEvent": { "command": { "abortTransaction": 1, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": { "$$exists": false }, "autocommit": false, "writeConcern": { "$$exists": false } }, "commandName": "abortTransaction", "databaseName": "admin" } }, { "commandStartedEvent": { "command": { "abortTransaction": 1, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": { "$$exists": false }, "autocommit": false, "writeConcern": { "$$exists": false } }, "commandName": "abortTransaction", "databaseName": "admin" } } ] } ], "outcome": [ { "collectionName": "test", "databaseName": "transaction-tests", "documents": [] } ] }, { "description": "abortTransaction succeeds after InterruptedAtShutdown", "operations": [ { "object": "testRunner", "name": "failPoint", "arguments": { "client": "client0", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "abortTransaction" ], "errorCode": 11600, "errorLabels": [ "RetryableWriteError" ], "closeConnection": false } } } }, { "object": "session0", "name": "startTransaction" }, { "object": "collection0", "name": "insertOne", "arguments": { "session": "session0", "document": { "_id": 1 } }, "expectResult": { "$$unsetOrMatches": { "insertedId": { "$$unsetOrMatches": 1 } } } }, { "object": "session0", "name": "abortTransaction" } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "insert": "test", "documents": [ { "_id": 1 } ], "ordered": true, "readConcern": { "$$exists": false }, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": true, "autocommit": false, "writeConcern": { "$$exists": false } }, "commandName": "insert", "databaseName": "transaction-tests" } }, { "commandStartedEvent": { "command": { "abortTransaction": 1, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": { "$$exists": false }, "autocommit": false, "writeConcern": { "$$exists": false } }, "commandName": "abortTransaction", "databaseName": "admin" } }, { "commandStartedEvent": { "command": { "abortTransaction": 1, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": { "$$exists": false }, "autocommit": false, "writeConcern": { "$$exists": false } }, "commandName": "abortTransaction", "databaseName": "admin" } } ] } ], "outcome": [ { "collectionName": "test", "databaseName": "transaction-tests", "documents": [] } ] }, { "description": "abortTransaction succeeds after PrimarySteppedDown", "operations": [ { "object": "testRunner", "name": "failPoint", "arguments": { "client": "client0", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "abortTransaction" ], "errorCode": 189, "errorLabels": [ "RetryableWriteError" ], "closeConnection": false } } } }, { "object": "session0", "name": "startTransaction" }, { "object": "collection0", "name": "insertOne", "arguments": { "session": "session0", "document": { "_id": 1 } }, "expectResult": { "$$unsetOrMatches": { "insertedId": { "$$unsetOrMatches": 1 } } } }, { "object": "session0", "name": "abortTransaction" } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "insert": "test", "documents": [ { "_id": 1 } ], "ordered": true, "readConcern": { "$$exists": false }, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": true, "autocommit": false, "writeConcern": { "$$exists": false } }, "commandName": "insert", "databaseName": "transaction-tests" } }, { "commandStartedEvent": { "command": { "abortTransaction": 1, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": { "$$exists": false }, "autocommit": false, "writeConcern": { "$$exists": false } }, "commandName": "abortTransaction", "databaseName": "admin" } }, { "commandStartedEvent": { "command": { "abortTransaction": 1, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": { "$$exists": false }, "autocommit": false, "writeConcern": { "$$exists": false } }, "commandName": "abortTransaction", "databaseName": "admin" } } ] } ], "outcome": [ { "collectionName": "test", "databaseName": "transaction-tests", "documents": [] } ] }, { "description": "abortTransaction succeeds after ShutdownInProgress", "operations": [ { "object": "testRunner", "name": "failPoint", "arguments": { "client": "client0", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "abortTransaction" ], "errorCode": 91, "errorLabels": [ "RetryableWriteError" ], "closeConnection": false } } } }, { "object": "session0", "name": "startTransaction" }, { "object": "collection0", "name": "insertOne", "arguments": { "session": "session0", "document": { "_id": 1 } }, "expectResult": { "$$unsetOrMatches": { "insertedId": { "$$unsetOrMatches": 1 } } } }, { "object": "session0", "name": "abortTransaction" } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "insert": "test", "documents": [ { "_id": 1 } ], "ordered": true, "readConcern": { "$$exists": false }, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": true, "autocommit": false, "writeConcern": { "$$exists": false } }, "commandName": "insert", "databaseName": "transaction-tests" } }, { "commandStartedEvent": { "command": { "abortTransaction": 1, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": { "$$exists": false }, "autocommit": false, "writeConcern": { "$$exists": false } }, "commandName": "abortTransaction", "databaseName": "admin" } }, { "commandStartedEvent": { "command": { "abortTransaction": 1, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": { "$$exists": false }, "autocommit": false, "writeConcern": { "$$exists": false } }, "commandName": "abortTransaction", "databaseName": "admin" } } ] } ], "outcome": [ { "collectionName": "test", "databaseName": "transaction-tests", "documents": [] } ] }, { "description": "abortTransaction succeeds after HostNotFound", "operations": [ { "object": "testRunner", "name": "failPoint", "arguments": { "client": "client0", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "abortTransaction" ], "errorCode": 7, "errorLabels": [ "RetryableWriteError" ], "closeConnection": false } } } }, { "object": "session0", "name": "startTransaction" }, { "object": "collection0", "name": "insertOne", "arguments": { "session": "session0", "document": { "_id": 1 } }, "expectResult": { "$$unsetOrMatches": { "insertedId": { "$$unsetOrMatches": 1 } } } }, { "object": "session0", "name": "abortTransaction" } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "insert": "test", "documents": [ { "_id": 1 } ], "ordered": true, "readConcern": { "$$exists": false }, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": true, "autocommit": false, "writeConcern": { "$$exists": false } }, "commandName": "insert", "databaseName": "transaction-tests" } }, { "commandStartedEvent": { "command": { "abortTransaction": 1, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": { "$$exists": false }, "autocommit": false, "writeConcern": { "$$exists": false } }, "commandName": "abortTransaction", "databaseName": "admin" } }, { "commandStartedEvent": { "command": { "abortTransaction": 1, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": { "$$exists": false }, "autocommit": false, "writeConcern": { "$$exists": false } }, "commandName": "abortTransaction", "databaseName": "admin" } } ] } ], "outcome": [ { "collectionName": "test", "databaseName": "transaction-tests", "documents": [] } ] }, { "description": "abortTransaction succeeds after HostUnreachable", "operations": [ { "object": "testRunner", "name": "failPoint", "arguments": { "client": "client0", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "abortTransaction" ], "errorCode": 6, "errorLabels": [ "RetryableWriteError" ], "closeConnection": false } } } }, { "object": "session0", "name": "startTransaction" }, { "object": "collection0", "name": "insertOne", "arguments": { "session": "session0", "document": { "_id": 1 } }, "expectResult": { "$$unsetOrMatches": { "insertedId": { "$$unsetOrMatches": 1 } } } }, { "object": "session0", "name": "abortTransaction" } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "insert": "test", "documents": [ { "_id": 1 } ], "ordered": true, "readConcern": { "$$exists": false }, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": true, "autocommit": false, "writeConcern": { "$$exists": false } }, "commandName": "insert", "databaseName": "transaction-tests" } }, { "commandStartedEvent": { "command": { "abortTransaction": 1, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": { "$$exists": false }, "autocommit": false, "writeConcern": { "$$exists": false } }, "commandName": "abortTransaction", "databaseName": "admin" } }, { "commandStartedEvent": { "command": { "abortTransaction": 1, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": { "$$exists": false }, "autocommit": false, "writeConcern": { "$$exists": false } }, "commandName": "abortTransaction", "databaseName": "admin" } } ] } ], "outcome": [ { "collectionName": "test", "databaseName": "transaction-tests", "documents": [] } ] }, { "description": "abortTransaction succeeds after SocketException", "operations": [ { "object": "testRunner", "name": "failPoint", "arguments": { "client": "client0", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "abortTransaction" ], "errorCode": 9001, "errorLabels": [ "RetryableWriteError" ], "closeConnection": false } } } }, { "object": "session0", "name": "startTransaction" }, { "object": "collection0", "name": "insertOne", "arguments": { "session": "session0", "document": { "_id": 1 } }, "expectResult": { "$$unsetOrMatches": { "insertedId": { "$$unsetOrMatches": 1 } } } }, { "object": "session0", "name": "abortTransaction" } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "insert": "test", "documents": [ { "_id": 1 } ], "ordered": true, "readConcern": { "$$exists": false }, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": true, "autocommit": false, "writeConcern": { "$$exists": false } }, "commandName": "insert", "databaseName": "transaction-tests" } }, { "commandStartedEvent": { "command": { "abortTransaction": 1, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": { "$$exists": false }, "autocommit": false, "writeConcern": { "$$exists": false } }, "commandName": "abortTransaction", "databaseName": "admin" } }, { "commandStartedEvent": { "command": { "abortTransaction": 1, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": { "$$exists": false }, "autocommit": false, "writeConcern": { "$$exists": false } }, "commandName": "abortTransaction", "databaseName": "admin" } } ] } ], "outcome": [ { "collectionName": "test", "databaseName": "transaction-tests", "documents": [] } ] }, { "description": "abortTransaction succeeds after NetworkTimeout", "operations": [ { "object": "testRunner", "name": "failPoint", "arguments": { "client": "client0", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "abortTransaction" ], "errorCode": 89, "errorLabels": [ "RetryableWriteError" ], "closeConnection": false } } } }, { "object": "session0", "name": "startTransaction" }, { "object": "collection0", "name": "insertOne", "arguments": { "session": "session0", "document": { "_id": 1 } }, "expectResult": { "$$unsetOrMatches": { "insertedId": { "$$unsetOrMatches": 1 } } } }, { "object": "session0", "name": "abortTransaction" } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "insert": "test", "documents": [ { "_id": 1 } ], "ordered": true, "readConcern": { "$$exists": false }, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": true, "autocommit": false, "writeConcern": { "$$exists": false } }, "commandName": "insert", "databaseName": "transaction-tests" } }, { "commandStartedEvent": { "command": { "abortTransaction": 1, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": { "$$exists": false }, "autocommit": false, "writeConcern": { "$$exists": false } }, "commandName": "abortTransaction", "databaseName": "admin" } }, { "commandStartedEvent": { "command": { "abortTransaction": 1, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": { "$$exists": false }, "autocommit": false, "writeConcern": { "$$exists": false } }, "commandName": "abortTransaction", "databaseName": "admin" } } ] } ], "outcome": [ { "collectionName": "test", "databaseName": "transaction-tests", "documents": [] } ] }, { "description": "abortTransaction succeeds after WriteConcernError InterruptedAtShutdown", "operations": [ { "object": "testRunner", "name": "failPoint", "arguments": { "client": "client0", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "abortTransaction" ], "errorLabels": [ "RetryableWriteError" ], "writeConcernError": { "code": 11600, "errmsg": "Replication is being shut down" } } } } }, { "object": "session0", "name": "startTransaction", "arguments": { "writeConcern": { "w": "majority" } } }, { "object": "collection0", "name": "insertOne", "arguments": { "session": "session0", "document": { "_id": 1 } }, "expectResult": { "$$unsetOrMatches": { "insertedId": { "$$unsetOrMatches": 1 } } } }, { "object": "session0", "name": "abortTransaction" } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "insert": "test", "documents": [ { "_id": 1 } ], "ordered": true, "readConcern": { "$$exists": false }, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": true, "autocommit": false, "writeConcern": { "$$exists": false } }, "commandName": "insert", "databaseName": "transaction-tests" } }, { "commandStartedEvent": { "command": { "abortTransaction": 1, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": { "$$exists": false }, "autocommit": false, "writeConcern": { "w": "majority" } }, "commandName": "abortTransaction", "databaseName": "admin" } }, { "commandStartedEvent": { "command": { "abortTransaction": 1, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": { "$$exists": false }, "autocommit": false, "writeConcern": { "w": "majority" } }, "commandName": "abortTransaction", "databaseName": "admin" } } ] } ], "outcome": [ { "collectionName": "test", "databaseName": "transaction-tests", "documents": [] } ] }, { "description": "abortTransaction succeeds after WriteConcernError InterruptedDueToReplStateChange", "operations": [ { "object": "testRunner", "name": "failPoint", "arguments": { "client": "client0", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "abortTransaction" ], "errorLabels": [ "RetryableWriteError" ], "writeConcernError": { "code": 11602, "errmsg": "Replication is being shut down" } } } } }, { "object": "session0", "name": "startTransaction", "arguments": { "writeConcern": { "w": "majority" } } }, { "object": "collection0", "name": "insertOne", "arguments": { "session": "session0", "document": { "_id": 1 } }, "expectResult": { "$$unsetOrMatches": { "insertedId": { "$$unsetOrMatches": 1 } } } }, { "object": "session0", "name": "abortTransaction" } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "insert": "test", "documents": [ { "_id": 1 } ], "ordered": true, "readConcern": { "$$exists": false }, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": true, "autocommit": false, "writeConcern": { "$$exists": false } }, "commandName": "insert", "databaseName": "transaction-tests" } }, { "commandStartedEvent": { "command": { "abortTransaction": 1, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": { "$$exists": false }, "autocommit": false, "writeConcern": { "w": "majority" } }, "commandName": "abortTransaction", "databaseName": "admin" } }, { "commandStartedEvent": { "command": { "abortTransaction": 1, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": { "$$exists": false }, "autocommit": false, "writeConcern": { "w": "majority" } }, "commandName": "abortTransaction", "databaseName": "admin" } } ] } ], "outcome": [ { "collectionName": "test", "databaseName": "transaction-tests", "documents": [] } ] }, { "description": "abortTransaction succeeds after WriteConcernError PrimarySteppedDown", "operations": [ { "object": "testRunner", "name": "failPoint", "arguments": { "client": "client0", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "abortTransaction" ], "errorLabels": [ "RetryableWriteError" ], "writeConcernError": { "code": 189, "errmsg": "Replication is being shut down" } } } } }, { "object": "session0", "name": "startTransaction", "arguments": { "writeConcern": { "w": "majority" } } }, { "object": "collection0", "name": "insertOne", "arguments": { "session": "session0", "document": { "_id": 1 } }, "expectResult": { "$$unsetOrMatches": { "insertedId": { "$$unsetOrMatches": 1 } } } }, { "object": "session0", "name": "abortTransaction" } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "insert": "test", "documents": [ { "_id": 1 } ], "ordered": true, "readConcern": { "$$exists": false }, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": true, "autocommit": false, "writeConcern": { "$$exists": false } }, "commandName": "insert", "databaseName": "transaction-tests" } }, { "commandStartedEvent": { "command": { "abortTransaction": 1, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": { "$$exists": false }, "autocommit": false, "writeConcern": { "w": "majority" } }, "commandName": "abortTransaction", "databaseName": "admin" } }, { "commandStartedEvent": { "command": { "abortTransaction": 1, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": { "$$exists": false }, "autocommit": false, "writeConcern": { "w": "majority" } }, "commandName": "abortTransaction", "databaseName": "admin" } } ] } ], "outcome": [ { "collectionName": "test", "databaseName": "transaction-tests", "documents": [] } ] }, { "description": "abortTransaction succeeds after WriteConcernError ShutdownInProgress", "operations": [ { "object": "testRunner", "name": "failPoint", "arguments": { "client": "client0", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "abortTransaction" ], "errorLabels": [ "RetryableWriteError" ], "writeConcernError": { "code": 91, "errmsg": "Replication is being shut down" } } } } }, { "object": "session0", "name": "startTransaction", "arguments": { "writeConcern": { "w": "majority" } } }, { "object": "collection0", "name": "insertOne", "arguments": { "session": "session0", "document": { "_id": 1 } }, "expectResult": { "$$unsetOrMatches": { "insertedId": { "$$unsetOrMatches": 1 } } } }, { "object": "session0", "name": "abortTransaction" } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "insert": "test", "documents": [ { "_id": 1 } ], "ordered": true, "readConcern": { "$$exists": false }, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": true, "autocommit": false, "writeConcern": { "$$exists": false } }, "commandName": "insert", "databaseName": "transaction-tests" } }, { "commandStartedEvent": { "command": { "abortTransaction": 1, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": { "$$exists": false }, "autocommit": false, "writeConcern": { "w": "majority" } }, "commandName": "abortTransaction", "databaseName": "admin" } }, { "commandStartedEvent": { "command": { "abortTransaction": 1, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": { "$$exists": false }, "autocommit": false, "writeConcern": { "w": "majority" } }, "commandName": "abortTransaction", "databaseName": "admin" } } ] } ], "outcome": [ { "collectionName": "test", "databaseName": "transaction-tests", "documents": [] } ] } ] } mongodb-mongo-python-driver-509e9b7/test/transactions/unified/retryable-abort-handshake.json000066400000000000000000000111401462766011000324610ustar00rootroot00000000000000{ "description": "retryable abortTransaction on handshake errors", "schemaVersion": "1.4", "runOnRequirements": [ { "minServerVersion": "4.2", "topologies": [ "replicaset", "sharded", "load-balanced" ], "serverless": "forbid", "auth": true } ], "createEntities": [ { "client": { "id": "client0", "useMultipleMongoses": false, "observeEvents": [ "commandStartedEvent", "connectionCheckOutStartedEvent" ] } }, { "database": { "id": "database0", "client": "client0", "databaseName": "retryable-handshake-tests" } }, { "collection": { "id": "collection0", "database": "database0", "collectionName": "coll" } }, { "session": { "id": "session0", "client": "client0" } }, { "session": { "id": "session1", "client": "client0" } } ], "initialData": [ { "collectionName": "coll", "databaseName": "retryable-handshake-tests", "documents": [ { "_id": 1, "x": 11 } ] } ], "tests": [ { "description": "AbortTransaction succeeds after handshake network error", "skipReason": "DRIVERS-2032: Pinned servers need to be checked if they are still selectable", "operations": [ { "name": "startTransaction", "object": "session0" }, { "name": "insertOne", "object": "collection0", "arguments": { "session": "session0", "document": { "_id": 2, "x": 22 } } }, { "name": "failPoint", "object": "testRunner", "arguments": { "client": "client0", "session": "session1", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 2 }, "data": { "failCommands": [ "saslContinue", "ping" ], "closeConnection": true } } } }, { "name": "runCommand", "object": "database0", "arguments": { "commandName": "ping", "command": { "ping": 1 }, "session": "session1" }, "expectError": { "isError": true } }, { "name": "abortTransaction", "object": "session0" } ], "expectEvents": [ { "client": "client0", "eventType": "cmap", "events": [ { "connectionCheckOutStartedEvent": {} }, { "connectionCheckOutStartedEvent": {} }, { "connectionCheckOutStartedEvent": {} }, { "connectionCheckOutStartedEvent": {} }, { "connectionCheckOutStartedEvent": {} } ] }, { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "insert": "coll", "documents": [ { "_id": 2, "x": 22 } ], "startTransaction": true }, "commandName": "insert", "databaseName": "retryable-handshake-tests" } }, { "commandStartedEvent": { "command": { "ping": 1 }, "databaseName": "retryable-handshake-tests" } }, { "commandStartedEvent": { "command": { "abortTransaction": 1, "lsid": { "$$sessionLsid": "session0" } }, "commandName": "abortTransaction", "databaseName": "admin" } } ] } ], "outcome": [ { "collectionName": "coll", "databaseName": "retryable-handshake-tests", "documents": [ { "_id": 1, "x": 11 } ] } ] } ] } mongodb-mongo-python-driver-509e9b7/test/transactions/unified/retryable-abort.json000066400000000000000000000360141462766011000305440ustar00rootroot00000000000000{ "description": "retryable-abort", "schemaVersion": "1.3", "runOnRequirements": [ { "minServerVersion": "4.0", "topologies": [ "replicaset" ] }, { "minServerVersion": "4.1.8", "topologies": [ "sharded", "load-balanced" ] } ], "createEntities": [ { "client": { "id": "client0", "useMultipleMongoses": false, "observeEvents": [ "commandStartedEvent" ] } }, { "database": { "id": "database0", "client": "client0", "databaseName": "transaction-tests" } }, { "collection": { "id": "collection0", "database": "database0", "collectionName": "test" } }, { "session": { "id": "session0", "client": "client0" } }, { "client": { "id": "client1", "useMultipleMongoses": false, "uriOptions": { "retryWrites": false }, "observeEvents": [ "commandStartedEvent" ] } }, { "database": { "id": "database1", "client": "client1", "databaseName": "transaction-tests" } }, { "collection": { "id": "collection1", "database": "database1", "collectionName": "test" } }, { "session": { "id": "session1", "client": "client1" } } ], "initialData": [ { "collectionName": "test", "databaseName": "transaction-tests", "documents": [] } ], "tests": [ { "description": "abortTransaction only performs a single retry", "operations": [ { "object": "testRunner", "name": "failPoint", "arguments": { "client": "client1", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 2 }, "data": { "failCommands": [ "abortTransaction" ], "closeConnection": true } } } }, { "object": "session1", "name": "startTransaction" }, { "object": "collection1", "name": "insertOne", "arguments": { "session": "session1", "document": { "_id": 1 } }, "expectResult": { "$$unsetOrMatches": { "insertedId": { "$$unsetOrMatches": 1 } } } }, { "object": "session1", "name": "abortTransaction" } ], "expectEvents": [ { "client": "client1", "events": [ { "commandStartedEvent": { "command": { "insert": "test", "documents": [ { "_id": 1 } ], "ordered": true, "readConcern": { "$$exists": false }, "lsid": { "$$sessionLsid": "session1" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": true, "autocommit": false, "writeConcern": { "$$exists": false } }, "commandName": "insert", "databaseName": "transaction-tests" } }, { "commandStartedEvent": { "command": { "abortTransaction": 1, "lsid": { "$$sessionLsid": "session1" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": { "$$exists": false }, "autocommit": false, "writeConcern": { "$$exists": false } }, "commandName": "abortTransaction", "databaseName": "admin" } }, { "commandStartedEvent": { "command": { "abortTransaction": 1, "lsid": { "$$sessionLsid": "session1" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": { "$$exists": false }, "autocommit": false, "writeConcern": { "$$exists": false } }, "commandName": "abortTransaction", "databaseName": "admin" } } ] } ], "outcome": [ { "collectionName": "test", "databaseName": "transaction-tests", "documents": [] } ] }, { "description": "abortTransaction does not retry after Interrupted", "operations": [ { "object": "testRunner", "name": "failPoint", "arguments": { "client": "client0", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "abortTransaction" ], "errorCode": 11601, "closeConnection": false } } } }, { "object": "session0", "name": "startTransaction" }, { "object": "collection0", "name": "insertOne", "arguments": { "session": "session0", "document": { "_id": 1 } }, "expectResult": { "$$unsetOrMatches": { "insertedId": { "$$unsetOrMatches": 1 } } } }, { "object": "session0", "name": "abortTransaction" } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "insert": "test", "documents": [ { "_id": 1 } ], "ordered": true, "readConcern": { "$$exists": false }, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": true, "autocommit": false, "writeConcern": { "$$exists": false } }, "commandName": "insert", "databaseName": "transaction-tests" } }, { "commandStartedEvent": { "command": { "abortTransaction": 1, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": { "$$exists": false }, "autocommit": false, "writeConcern": { "$$exists": false } }, "commandName": "abortTransaction", "databaseName": "admin" } } ] } ], "outcome": [ { "collectionName": "test", "databaseName": "transaction-tests", "documents": [] } ] }, { "description": "abortTransaction does not retry after WriteConcernError Interrupted", "operations": [ { "object": "testRunner", "name": "failPoint", "arguments": { "client": "client0", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "abortTransaction" ], "writeConcernError": { "code": 11601, "errmsg": "operation was interrupted" } } } } }, { "object": "session0", "name": "startTransaction", "arguments": { "writeConcern": { "w": "majority" } } }, { "object": "collection0", "name": "insertOne", "arguments": { "session": "session0", "document": { "_id": 1 } }, "expectResult": { "$$unsetOrMatches": { "insertedId": { "$$unsetOrMatches": 1 } } } }, { "object": "session0", "name": "abortTransaction" } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "insert": "test", "documents": [ { "_id": 1 } ], "ordered": true, "readConcern": { "$$exists": false }, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": true, "autocommit": false, "writeConcern": { "$$exists": false } }, "commandName": "insert", "databaseName": "transaction-tests" } }, { "commandStartedEvent": { "command": { "abortTransaction": 1, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": { "$$exists": false }, "autocommit": false, "writeConcern": { "w": "majority" } }, "commandName": "abortTransaction", "databaseName": "admin" } } ] } ], "outcome": [ { "collectionName": "test", "databaseName": "transaction-tests", "documents": [] } ] }, { "description": "abortTransaction succeeds after connection error", "operations": [ { "object": "testRunner", "name": "failPoint", "arguments": { "client": "client0", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "abortTransaction" ], "closeConnection": true } } } }, { "object": "session0", "name": "startTransaction" }, { "object": "collection0", "name": "insertOne", "arguments": { "session": "session0", "document": { "_id": 1 } }, "expectResult": { "$$unsetOrMatches": { "insertedId": { "$$unsetOrMatches": 1 } } } }, { "object": "session0", "name": "abortTransaction" } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "insert": "test", "documents": [ { "_id": 1 } ], "ordered": true, "readConcern": { "$$exists": false }, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": true, "autocommit": false, "writeConcern": { "$$exists": false } }, "commandName": "insert", "databaseName": "transaction-tests" } }, { "commandStartedEvent": { "command": { "abortTransaction": 1, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": { "$$exists": false }, "autocommit": false, "writeConcern": { "$$exists": false } }, "commandName": "abortTransaction", "databaseName": "admin" } }, { "commandStartedEvent": { "command": { "abortTransaction": 1, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": { "$$exists": false }, "autocommit": false, "writeConcern": { "$$exists": false } }, "commandName": "abortTransaction", "databaseName": "admin" } } ] } ], "outcome": [ { "collectionName": "test", "databaseName": "transaction-tests", "documents": [] } ] } ] } mongodb-mongo-python-driver-509e9b7/test/transactions/unified/retryable-commit-errorLabels.json000066400000000000000000002064561462766011000332100ustar00rootroot00000000000000{ "description": "retryable-commit-errorLabels", "schemaVersion": "1.4", "runOnRequirements": [ { "minServerVersion": "4.3.1", "topologies": [ "replicaset", "sharded", "load-balanced" ] } ], "createEntities": [ { "client": { "id": "client0", "useMultipleMongoses": false, "observeEvents": [ "commandStartedEvent" ] } }, { "database": { "id": "database0", "client": "client0", "databaseName": "transaction-tests" } }, { "collection": { "id": "collection0", "database": "database0", "collectionName": "test" } }, { "session": { "id": "session0", "client": "client0" } }, { "client": { "id": "client1", "useMultipleMongoses": false, "uriOptions": { "retryWrites": false }, "observeEvents": [ "commandStartedEvent" ] } }, { "database": { "id": "database1", "client": "client1", "databaseName": "transaction-tests" } }, { "collection": { "id": "collection1", "database": "database1", "collectionName": "test" } }, { "session": { "id": "session1", "client": "client1" } } ], "initialData": [ { "collectionName": "test", "databaseName": "transaction-tests", "documents": [] } ], "tests": [ { "description": "commitTransaction does not retry error without RetryableWriteError label", "operations": [ { "object": "testRunner", "name": "failPoint", "arguments": { "client": "client1", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "commitTransaction" ], "errorCode": 11600, "errorLabels": [] } } } }, { "object": "session1", "name": "startTransaction" }, { "object": "collection1", "name": "insertOne", "arguments": { "session": "session1", "document": { "_id": 1 } }, "expectResult": { "$$unsetOrMatches": { "insertedId": { "$$unsetOrMatches": 1 } } } }, { "object": "session1", "name": "commitTransaction", "expectError": { "errorLabelsOmit": [ "RetryableWriteError", "TransientTransactionError" ] } } ], "expectEvents": [ { "client": "client1", "events": [ { "commandStartedEvent": { "command": { "insert": "test", "documents": [ { "_id": 1 } ], "ordered": true, "readConcern": { "$$exists": false }, "lsid": { "$$sessionLsid": "session1" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": true, "autocommit": false, "writeConcern": { "$$exists": false } }, "commandName": "insert", "databaseName": "transaction-tests" } }, { "commandStartedEvent": { "command": { "commitTransaction": 1, "lsid": { "$$sessionLsid": "session1" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": { "$$exists": false }, "autocommit": false, "writeConcern": { "$$exists": false } }, "commandName": "commitTransaction", "databaseName": "admin" } } ] } ], "outcome": [ { "collectionName": "test", "databaseName": "transaction-tests", "documents": [] } ] }, { "description": "commitTransaction retries once with RetryableWriteError from server", "operations": [ { "object": "testRunner", "name": "failPoint", "arguments": { "client": "client1", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "commitTransaction" ], "errorCode": 112, "errorLabels": [ "RetryableWriteError" ] } } } }, { "object": "session1", "name": "startTransaction" }, { "object": "collection1", "name": "insertOne", "arguments": { "session": "session1", "document": { "_id": 1 } }, "expectResult": { "$$unsetOrMatches": { "insertedId": { "$$unsetOrMatches": 1 } } } }, { "object": "session1", "name": "commitTransaction" } ], "expectEvents": [ { "client": "client1", "events": [ { "commandStartedEvent": { "command": { "insert": "test", "documents": [ { "_id": 1 } ], "ordered": true, "readConcern": { "$$exists": false }, "lsid": { "$$sessionLsid": "session1" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": true, "autocommit": false, "writeConcern": { "$$exists": false } }, "commandName": "insert", "databaseName": "transaction-tests" } }, { "commandStartedEvent": { "command": { "commitTransaction": 1, "lsid": { "$$sessionLsid": "session1" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": { "$$exists": false }, "autocommit": false, "writeConcern": { "$$exists": false } }, "commandName": "commitTransaction", "databaseName": "admin" } }, { "commandStartedEvent": { "command": { "commitTransaction": 1, "lsid": { "$$sessionLsid": "session1" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": { "$$exists": false }, "autocommit": false, "writeConcern": { "w": "majority", "wtimeout": 10000 } }, "commandName": "commitTransaction", "databaseName": "admin" } } ] } ], "outcome": [ { "collectionName": "test", "databaseName": "transaction-tests", "documents": [ { "_id": 1 } ] } ] }, { "description": "commitTransaction succeeds after NotWritablePrimary", "operations": [ { "object": "testRunner", "name": "failPoint", "arguments": { "client": "client0", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "commitTransaction" ], "errorCode": 10107, "errorLabels": [ "RetryableWriteError" ], "closeConnection": false } } } }, { "object": "session0", "name": "startTransaction" }, { "object": "collection0", "name": "insertOne", "arguments": { "session": "session0", "document": { "_id": 1 } }, "expectResult": { "$$unsetOrMatches": { "insertedId": { "$$unsetOrMatches": 1 } } } }, { "object": "session0", "name": "commitTransaction" } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "insert": "test", "documents": [ { "_id": 1 } ], "ordered": true, "readConcern": { "$$exists": false }, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": true, "autocommit": false, "writeConcern": { "$$exists": false } }, "commandName": "insert", "databaseName": "transaction-tests" } }, { "commandStartedEvent": { "command": { "commitTransaction": 1, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": { "$$exists": false }, "autocommit": false, "writeConcern": { "$$exists": false } }, "commandName": "commitTransaction", "databaseName": "admin" } }, { "commandStartedEvent": { "command": { "commitTransaction": 1, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": { "$$exists": false }, "autocommit": false, "writeConcern": { "w": "majority", "wtimeout": 10000 } }, "commandName": "commitTransaction", "databaseName": "admin" } } ] } ], "outcome": [ { "collectionName": "test", "databaseName": "transaction-tests", "documents": [ { "_id": 1 } ] } ] }, { "description": "commitTransaction succeeds after NotPrimaryOrSecondary", "operations": [ { "object": "testRunner", "name": "failPoint", "arguments": { "client": "client0", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "commitTransaction" ], "errorCode": 13436, "errorLabels": [ "RetryableWriteError" ], "closeConnection": false } } } }, { "object": "session0", "name": "startTransaction" }, { "object": "collection0", "name": "insertOne", "arguments": { "session": "session0", "document": { "_id": 1 } }, "expectResult": { "$$unsetOrMatches": { "insertedId": { "$$unsetOrMatches": 1 } } } }, { "object": "session0", "name": "commitTransaction" } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "insert": "test", "documents": [ { "_id": 1 } ], "ordered": true, "readConcern": { "$$exists": false }, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": true, "autocommit": false, "writeConcern": { "$$exists": false } }, "commandName": "insert", "databaseName": "transaction-tests" } }, { "commandStartedEvent": { "command": { "commitTransaction": 1, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": { "$$exists": false }, "autocommit": false, "writeConcern": { "$$exists": false } }, "commandName": "commitTransaction", "databaseName": "admin" } }, { "commandStartedEvent": { "command": { "commitTransaction": 1, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": { "$$exists": false }, "autocommit": false, "writeConcern": { "w": "majority", "wtimeout": 10000 } }, "commandName": "commitTransaction", "databaseName": "admin" } } ] } ], "outcome": [ { "collectionName": "test", "databaseName": "transaction-tests", "documents": [ { "_id": 1 } ] } ] }, { "description": "commitTransaction succeeds after NotPrimaryNoSecondaryOk", "operations": [ { "object": "testRunner", "name": "failPoint", "arguments": { "client": "client0", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "commitTransaction" ], "errorCode": 13435, "errorLabels": [ "RetryableWriteError" ], "closeConnection": false } } } }, { "object": "session0", "name": "startTransaction" }, { "object": "collection0", "name": "insertOne", "arguments": { "session": "session0", "document": { "_id": 1 } }, "expectResult": { "$$unsetOrMatches": { "insertedId": { "$$unsetOrMatches": 1 } } } }, { "object": "session0", "name": "commitTransaction" } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "insert": "test", "documents": [ { "_id": 1 } ], "ordered": true, "readConcern": { "$$exists": false }, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": true, "autocommit": false, "writeConcern": { "$$exists": false } }, "commandName": "insert", "databaseName": "transaction-tests" } }, { "commandStartedEvent": { "command": { "commitTransaction": 1, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": { "$$exists": false }, "autocommit": false, "writeConcern": { "$$exists": false } }, "commandName": "commitTransaction", "databaseName": "admin" } }, { "commandStartedEvent": { "command": { "commitTransaction": 1, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": { "$$exists": false }, "autocommit": false, "writeConcern": { "w": "majority", "wtimeout": 10000 } }, "commandName": "commitTransaction", "databaseName": "admin" } } ] } ], "outcome": [ { "collectionName": "test", "databaseName": "transaction-tests", "documents": [ { "_id": 1 } ] } ] }, { "description": "commitTransaction succeeds after InterruptedDueToReplStateChange", "operations": [ { "object": "testRunner", "name": "failPoint", "arguments": { "client": "client0", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "commitTransaction" ], "errorCode": 11602, "errorLabels": [ "RetryableWriteError" ], "closeConnection": false } } } }, { "object": "session0", "name": "startTransaction" }, { "object": "collection0", "name": "insertOne", "arguments": { "session": "session0", "document": { "_id": 1 } }, "expectResult": { "$$unsetOrMatches": { "insertedId": { "$$unsetOrMatches": 1 } } } }, { "object": "session0", "name": "commitTransaction" } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "insert": "test", "documents": [ { "_id": 1 } ], "ordered": true, "readConcern": { "$$exists": false }, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": true, "autocommit": false, "writeConcern": { "$$exists": false } }, "commandName": "insert", "databaseName": "transaction-tests" } }, { "commandStartedEvent": { "command": { "commitTransaction": 1, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": { "$$exists": false }, "autocommit": false, "writeConcern": { "$$exists": false } }, "commandName": "commitTransaction", "databaseName": "admin" } }, { "commandStartedEvent": { "command": { "commitTransaction": 1, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": { "$$exists": false }, "autocommit": false, "writeConcern": { "w": "majority", "wtimeout": 10000 } }, "commandName": "commitTransaction", "databaseName": "admin" } } ] } ], "outcome": [ { "collectionName": "test", "databaseName": "transaction-tests", "documents": [ { "_id": 1 } ] } ] }, { "description": "commitTransaction succeeds after PrimarySteppedDown", "operations": [ { "object": "testRunner", "name": "failPoint", "arguments": { "client": "client0", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "commitTransaction" ], "errorCode": 189, "errorLabels": [ "RetryableWriteError" ], "closeConnection": false } } } }, { "object": "session0", "name": "startTransaction" }, { "object": "collection0", "name": "insertOne", "arguments": { "session": "session0", "document": { "_id": 1 } }, "expectResult": { "$$unsetOrMatches": { "insertedId": { "$$unsetOrMatches": 1 } } } }, { "object": "session0", "name": "commitTransaction" } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "insert": "test", "documents": [ { "_id": 1 } ], "ordered": true, "readConcern": { "$$exists": false }, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": true, "autocommit": false, "writeConcern": { "$$exists": false } }, "commandName": "insert", "databaseName": "transaction-tests" } }, { "commandStartedEvent": { "command": { "commitTransaction": 1, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": { "$$exists": false }, "autocommit": false, "writeConcern": { "$$exists": false } }, "commandName": "commitTransaction", "databaseName": "admin" } }, { "commandStartedEvent": { "command": { "commitTransaction": 1, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": { "$$exists": false }, "autocommit": false, "writeConcern": { "w": "majority", "wtimeout": 10000 } }, "commandName": "commitTransaction", "databaseName": "admin" } } ] } ], "outcome": [ { "collectionName": "test", "databaseName": "transaction-tests", "documents": [ { "_id": 1 } ] } ] }, { "description": "commitTransaction succeeds after HostNotFound", "operations": [ { "object": "testRunner", "name": "failPoint", "arguments": { "client": "client0", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "commitTransaction" ], "errorCode": 7, "errorLabels": [ "RetryableWriteError" ], "closeConnection": false } } } }, { "object": "session0", "name": "startTransaction" }, { "object": "collection0", "name": "insertOne", "arguments": { "session": "session0", "document": { "_id": 1 } }, "expectResult": { "$$unsetOrMatches": { "insertedId": { "$$unsetOrMatches": 1 } } } }, { "object": "session0", "name": "commitTransaction" } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "insert": "test", "documents": [ { "_id": 1 } ], "ordered": true, "readConcern": { "$$exists": false }, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": true, "autocommit": false, "writeConcern": { "$$exists": false } }, "commandName": "insert", "databaseName": "transaction-tests" } }, { "commandStartedEvent": { "command": { "commitTransaction": 1, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": { "$$exists": false }, "autocommit": false, "writeConcern": { "$$exists": false } }, "commandName": "commitTransaction", "databaseName": "admin" } }, { "commandStartedEvent": { "command": { "commitTransaction": 1, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": { "$$exists": false }, "autocommit": false, "writeConcern": { "w": "majority", "wtimeout": 10000 } }, "commandName": "commitTransaction", "databaseName": "admin" } } ] } ], "outcome": [ { "collectionName": "test", "databaseName": "transaction-tests", "documents": [ { "_id": 1 } ] } ] }, { "description": "commitTransaction succeeds after HostUnreachable", "operations": [ { "object": "testRunner", "name": "failPoint", "arguments": { "client": "client0", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "commitTransaction" ], "errorCode": 6, "errorLabels": [ "RetryableWriteError" ], "closeConnection": false } } } }, { "object": "session0", "name": "startTransaction" }, { "object": "collection0", "name": "insertOne", "arguments": { "session": "session0", "document": { "_id": 1 } }, "expectResult": { "$$unsetOrMatches": { "insertedId": { "$$unsetOrMatches": 1 } } } }, { "object": "session0", "name": "commitTransaction" } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "insert": "test", "documents": [ { "_id": 1 } ], "ordered": true, "readConcern": { "$$exists": false }, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": true, "autocommit": false, "writeConcern": { "$$exists": false } }, "commandName": "insert", "databaseName": "transaction-tests" } }, { "commandStartedEvent": { "command": { "commitTransaction": 1, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": { "$$exists": false }, "autocommit": false, "writeConcern": { "$$exists": false } }, "commandName": "commitTransaction", "databaseName": "admin" } }, { "commandStartedEvent": { "command": { "commitTransaction": 1, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": { "$$exists": false }, "autocommit": false, "writeConcern": { "w": "majority", "wtimeout": 10000 } }, "commandName": "commitTransaction", "databaseName": "admin" } } ] } ], "outcome": [ { "collectionName": "test", "databaseName": "transaction-tests", "documents": [ { "_id": 1 } ] } ] }, { "description": "commitTransaction succeeds after SocketException", "operations": [ { "object": "testRunner", "name": "failPoint", "arguments": { "client": "client0", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "commitTransaction" ], "errorCode": 9001, "errorLabels": [ "RetryableWriteError" ], "closeConnection": false } } } }, { "object": "session0", "name": "startTransaction" }, { "object": "collection0", "name": "insertOne", "arguments": { "session": "session0", "document": { "_id": 1 } }, "expectResult": { "$$unsetOrMatches": { "insertedId": { "$$unsetOrMatches": 1 } } } }, { "object": "session0", "name": "commitTransaction" } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "insert": "test", "documents": [ { "_id": 1 } ], "ordered": true, "readConcern": { "$$exists": false }, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": true, "autocommit": false, "writeConcern": { "$$exists": false } }, "commandName": "insert", "databaseName": "transaction-tests" } }, { "commandStartedEvent": { "command": { "commitTransaction": 1, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": { "$$exists": false }, "autocommit": false, "writeConcern": { "$$exists": false } }, "commandName": "commitTransaction", "databaseName": "admin" } }, { "commandStartedEvent": { "command": { "commitTransaction": 1, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": { "$$exists": false }, "autocommit": false, "writeConcern": { "w": "majority", "wtimeout": 10000 } }, "commandName": "commitTransaction", "databaseName": "admin" } } ] } ], "outcome": [ { "collectionName": "test", "databaseName": "transaction-tests", "documents": [ { "_id": 1 } ] } ] }, { "description": "commitTransaction succeeds after NetworkTimeout", "operations": [ { "object": "testRunner", "name": "failPoint", "arguments": { "client": "client0", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "commitTransaction" ], "errorCode": 89, "errorLabels": [ "RetryableWriteError" ], "closeConnection": false } } } }, { "object": "session0", "name": "startTransaction" }, { "object": "collection0", "name": "insertOne", "arguments": { "session": "session0", "document": { "_id": 1 } }, "expectResult": { "$$unsetOrMatches": { "insertedId": { "$$unsetOrMatches": 1 } } } }, { "object": "session0", "name": "commitTransaction" } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "insert": "test", "documents": [ { "_id": 1 } ], "ordered": true, "readConcern": { "$$exists": false }, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": true, "autocommit": false, "writeConcern": { "$$exists": false } }, "commandName": "insert", "databaseName": "transaction-tests" } }, { "commandStartedEvent": { "command": { "commitTransaction": 1, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": { "$$exists": false }, "autocommit": false, "writeConcern": { "$$exists": false } }, "commandName": "commitTransaction", "databaseName": "admin" } }, { "commandStartedEvent": { "command": { "commitTransaction": 1, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": { "$$exists": false }, "autocommit": false, "writeConcern": { "w": "majority", "wtimeout": 10000 } }, "commandName": "commitTransaction", "databaseName": "admin" } } ] } ], "outcome": [ { "collectionName": "test", "databaseName": "transaction-tests", "documents": [ { "_id": 1 } ] } ] }, { "description": "commitTransaction succeeds after WriteConcernError InterruptedAtShutdown", "operations": [ { "object": "testRunner", "name": "failPoint", "arguments": { "client": "client0", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "commitTransaction" ], "errorLabels": [ "RetryableWriteError" ], "writeConcernError": { "code": 11600, "errmsg": "Replication is being shut down" } } } } }, { "object": "session0", "name": "startTransaction", "arguments": { "writeConcern": { "w": "majority" } } }, { "object": "collection0", "name": "insertOne", "arguments": { "session": "session0", "document": { "_id": 1 } }, "expectResult": { "$$unsetOrMatches": { "insertedId": { "$$unsetOrMatches": 1 } } } }, { "object": "session0", "name": "commitTransaction" } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "insert": "test", "documents": [ { "_id": 1 } ], "ordered": true, "readConcern": { "$$exists": false }, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": true, "autocommit": false, "writeConcern": { "$$exists": false } }, "commandName": "insert", "databaseName": "transaction-tests" } }, { "commandStartedEvent": { "command": { "commitTransaction": 1, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": { "$$exists": false }, "autocommit": false, "writeConcern": { "w": "majority" } }, "commandName": "commitTransaction", "databaseName": "admin" } }, { "commandStartedEvent": { "command": { "commitTransaction": 1, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": { "$$exists": false }, "autocommit": false, "writeConcern": { "w": "majority", "wtimeout": 10000 } }, "commandName": "commitTransaction", "databaseName": "admin" } } ] } ], "outcome": [ { "collectionName": "test", "databaseName": "transaction-tests", "documents": [ { "_id": 1 } ] } ] }, { "description": "commitTransaction succeeds after WriteConcernError InterruptedDueToReplStateChange", "operations": [ { "object": "testRunner", "name": "failPoint", "arguments": { "client": "client0", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "commitTransaction" ], "errorLabels": [ "RetryableWriteError" ], "writeConcernError": { "code": 11602, "errmsg": "Replication is being shut down" } } } } }, { "object": "session0", "name": "startTransaction", "arguments": { "writeConcern": { "w": "majority" } } }, { "object": "collection0", "name": "insertOne", "arguments": { "session": "session0", "document": { "_id": 1 } }, "expectResult": { "$$unsetOrMatches": { "insertedId": { "$$unsetOrMatches": 1 } } } }, { "object": "session0", "name": "commitTransaction" } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "insert": "test", "documents": [ { "_id": 1 } ], "ordered": true, "readConcern": { "$$exists": false }, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": true, "autocommit": false, "writeConcern": { "$$exists": false } }, "commandName": "insert", "databaseName": "transaction-tests" } }, { "commandStartedEvent": { "command": { "commitTransaction": 1, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": { "$$exists": false }, "autocommit": false, "writeConcern": { "w": "majority" } }, "commandName": "commitTransaction", "databaseName": "admin" } }, { "commandStartedEvent": { "command": { "commitTransaction": 1, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": { "$$exists": false }, "autocommit": false, "writeConcern": { "w": "majority", "wtimeout": 10000 } }, "commandName": "commitTransaction", "databaseName": "admin" } } ] } ], "outcome": [ { "collectionName": "test", "databaseName": "transaction-tests", "documents": [ { "_id": 1 } ] } ] }, { "description": "commitTransaction succeeds after WriteConcernError PrimarySteppedDown", "operations": [ { "object": "testRunner", "name": "failPoint", "arguments": { "client": "client0", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "commitTransaction" ], "errorLabels": [ "RetryableWriteError" ], "writeConcernError": { "code": 189, "errmsg": "Replication is being shut down" } } } } }, { "object": "session0", "name": "startTransaction", "arguments": { "writeConcern": { "w": "majority" } } }, { "object": "collection0", "name": "insertOne", "arguments": { "session": "session0", "document": { "_id": 1 } }, "expectResult": { "$$unsetOrMatches": { "insertedId": { "$$unsetOrMatches": 1 } } } }, { "object": "session0", "name": "commitTransaction" } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "insert": "test", "documents": [ { "_id": 1 } ], "ordered": true, "readConcern": { "$$exists": false }, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": true, "autocommit": false, "writeConcern": { "$$exists": false } }, "commandName": "insert", "databaseName": "transaction-tests" } }, { "commandStartedEvent": { "command": { "commitTransaction": 1, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": { "$$exists": false }, "autocommit": false, "writeConcern": { "w": "majority" } }, "commandName": "commitTransaction", "databaseName": "admin" } }, { "commandStartedEvent": { "command": { "commitTransaction": 1, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": { "$$exists": false }, "autocommit": false, "writeConcern": { "w": "majority", "wtimeout": 10000 } }, "commandName": "commitTransaction", "databaseName": "admin" } } ] } ], "outcome": [ { "collectionName": "test", "databaseName": "transaction-tests", "documents": [ { "_id": 1 } ] } ] }, { "description": "commitTransaction succeeds after WriteConcernError ShutdownInProgress", "operations": [ { "object": "testRunner", "name": "failPoint", "arguments": { "client": "client0", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "commitTransaction" ], "errorLabels": [ "RetryableWriteError" ], "writeConcernError": { "code": 91, "errmsg": "Replication is being shut down" } } } } }, { "object": "session0", "name": "startTransaction", "arguments": { "writeConcern": { "w": "majority" } } }, { "object": "collection0", "name": "insertOne", "arguments": { "session": "session0", "document": { "_id": 1 } }, "expectResult": { "$$unsetOrMatches": { "insertedId": { "$$unsetOrMatches": 1 } } } }, { "object": "session0", "name": "commitTransaction" } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "insert": "test", "documents": [ { "_id": 1 } ], "ordered": true, "readConcern": { "$$exists": false }, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": true, "autocommit": false, "writeConcern": { "$$exists": false } }, "commandName": "insert", "databaseName": "transaction-tests" } }, { "commandStartedEvent": { "command": { "commitTransaction": 1, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": { "$$exists": false }, "autocommit": false, "writeConcern": { "w": "majority" } }, "commandName": "commitTransaction", "databaseName": "admin" } }, { "commandStartedEvent": { "command": { "commitTransaction": 1, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": { "$$exists": false }, "autocommit": false, "writeConcern": { "w": "majority", "wtimeout": 10000 } }, "commandName": "commitTransaction", "databaseName": "admin" } } ] } ], "outcome": [ { "collectionName": "test", "databaseName": "transaction-tests", "documents": [ { "_id": 1 } ] } ] }, { "description": "commitTransaction succeeds after InterruptedAtShutdown", "runOnRequirements": [ { "serverless": "forbid" } ], "operations": [ { "object": "testRunner", "name": "failPoint", "arguments": { "client": "client0", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "commitTransaction" ], "errorCode": 11600, "errorLabels": [ "RetryableWriteError" ], "closeConnection": false } } } }, { "object": "session0", "name": "startTransaction" }, { "object": "collection0", "name": "insertOne", "arguments": { "session": "session0", "document": { "_id": 1 } }, "expectResult": { "$$unsetOrMatches": { "insertedId": { "$$unsetOrMatches": 1 } } } }, { "object": "session0", "name": "commitTransaction" } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "insert": "test", "documents": [ { "_id": 1 } ], "ordered": true, "readConcern": { "$$exists": false }, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": true, "autocommit": false, "writeConcern": { "$$exists": false } }, "commandName": "insert", "databaseName": "transaction-tests" } }, { "commandStartedEvent": { "command": { "commitTransaction": 1, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": { "$$exists": false }, "autocommit": false, "writeConcern": { "$$exists": false } }, "commandName": "commitTransaction", "databaseName": "admin" } }, { "commandStartedEvent": { "command": { "commitTransaction": 1, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": { "$$exists": false }, "autocommit": false, "writeConcern": { "w": "majority", "wtimeout": 10000 } }, "commandName": "commitTransaction", "databaseName": "admin" } } ] } ], "outcome": [ { "collectionName": "test", "databaseName": "transaction-tests", "documents": [ { "_id": 1 } ] } ] }, { "description": "commitTransaction succeeds after ShutdownInProgress", "runOnRequirements": [ { "serverless": "forbid" } ], "operations": [ { "object": "testRunner", "name": "failPoint", "arguments": { "client": "client0", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "commitTransaction" ], "errorCode": 91, "errorLabels": [ "RetryableWriteError" ], "closeConnection": false } } } }, { "object": "session0", "name": "startTransaction" }, { "object": "collection0", "name": "insertOne", "arguments": { "session": "session0", "document": { "_id": 1 } }, "expectResult": { "$$unsetOrMatches": { "insertedId": { "$$unsetOrMatches": 1 } } } }, { "object": "session0", "name": "commitTransaction" } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "insert": "test", "documents": [ { "_id": 1 } ], "ordered": true, "readConcern": { "$$exists": false }, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": true, "autocommit": false, "writeConcern": { "$$exists": false } }, "commandName": "insert", "databaseName": "transaction-tests" } }, { "commandStartedEvent": { "command": { "commitTransaction": 1, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": { "$$exists": false }, "autocommit": false, "writeConcern": { "$$exists": false } }, "commandName": "commitTransaction", "databaseName": "admin" } }, { "commandStartedEvent": { "command": { "commitTransaction": 1, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": { "$$exists": false }, "autocommit": false, "writeConcern": { "w": "majority", "wtimeout": 10000 } }, "commandName": "commitTransaction", "databaseName": "admin" } } ] } ], "outcome": [ { "collectionName": "test", "databaseName": "transaction-tests", "documents": [ { "_id": 1 } ] } ] } ] } mongodb-mongo-python-driver-509e9b7/test/transactions/unified/retryable-commit-handshake.json000066400000000000000000000113621462766011000326500ustar00rootroot00000000000000{ "description": "retryable commitTransaction on handshake errors", "schemaVersion": "1.4", "runOnRequirements": [ { "minServerVersion": "4.2", "topologies": [ "replicaset", "sharded", "load-balanced" ], "serverless": "forbid", "auth": true } ], "createEntities": [ { "client": { "id": "client0", "useMultipleMongoses": false, "observeEvents": [ "commandStartedEvent", "connectionCheckOutStartedEvent" ], "uriOptions": { "retryWrites": false } } }, { "database": { "id": "database0", "client": "client0", "databaseName": "retryable-handshake-tests" } }, { "collection": { "id": "collection0", "database": "database0", "collectionName": "coll" } }, { "session": { "id": "session0", "client": "client0" } }, { "session": { "id": "session1", "client": "client0" } } ], "initialData": [ { "collectionName": "coll", "databaseName": "retryable-handshake-tests", "documents": [ { "_id": 1, "x": 11 } ] } ], "tests": [ { "description": "CommitTransaction succeeds after handshake network error", "skipReason": "DRIVERS-2032: Pinned servers need to be checked if they are still selectable", "operations": [ { "name": "startTransaction", "object": "session0" }, { "name": "insertOne", "object": "collection0", "arguments": { "session": "session0", "document": { "_id": 2, "x": 22 } } }, { "name": "failPoint", "object": "testRunner", "arguments": { "client": "client0", "session": "session1", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 2 }, "data": { "failCommands": [ "saslContinue", "ping" ], "closeConnection": true } } } }, { "name": "runCommand", "object": "database0", "arguments": { "commandName": "ping", "command": { "ping": 1 }, "session": "session1" }, "expectError": { "isError": true } }, { "name": "commitTransaction", "object": "session0" } ], "expectEvents": [ { "client": "client0", "eventType": "cmap", "events": [ { "connectionCheckOutStartedEvent": {} }, { "connectionCheckOutStartedEvent": {} }, { "connectionCheckOutStartedEvent": {} }, { "connectionCheckOutStartedEvent": {} }, { "connectionCheckOutStartedEvent": {} } ] }, { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "insert": "coll", "documents": [ { "_id": 2, "x": 22 } ], "startTransaction": true }, "commandName": "insert", "databaseName": "retryable-handshake-tests" } }, { "commandStartedEvent": { "command": { "ping": 1 }, "databaseName": "retryable-handshake-tests" } }, { "commandStartedEvent": { "command": { "commitTransaction": 1, "lsid": { "$$sessionLsid": "session0" } }, "commandName": "commitTransaction", "databaseName": "admin" } } ] } ], "outcome": [ { "collectionName": "coll", "databaseName": "retryable-handshake-tests", "documents": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 22 } ] } ] } ] } mongodb-mongo-python-driver-509e9b7/test/transactions/unified/retryable-commit.json000066400000000000000000000542051462766011000307270ustar00rootroot00000000000000{ "description": "retryable-commit", "schemaVersion": "1.4", "runOnRequirements": [ { "minServerVersion": "4.0", "topologies": [ "replicaset" ] }, { "minServerVersion": "4.1.8", "topologies": [ "sharded", "load-balanced" ] } ], "createEntities": [ { "client": { "id": "client0", "useMultipleMongoses": false, "observeEvents": [ "commandStartedEvent" ] } }, { "database": { "id": "database0", "client": "client0", "databaseName": "transaction-tests" } }, { "collection": { "id": "collection0", "database": "database0", "collectionName": "test" } }, { "session": { "id": "session0", "client": "client0" } }, { "client": { "id": "client1", "useMultipleMongoses": false, "uriOptions": { "retryWrites": false }, "observeEvents": [ "commandStartedEvent" ] } }, { "database": { "id": "database1", "client": "client1", "databaseName": "transaction-tests" } }, { "collection": { "id": "collection1", "database": "database1", "collectionName": "test" } }, { "session": { "id": "session1", "client": "client1" } } ], "initialData": [ { "collectionName": "test", "databaseName": "transaction-tests", "documents": [] } ], "tests": [ { "description": "commitTransaction fails after Interrupted", "operations": [ { "object": "testRunner", "name": "failPoint", "arguments": { "client": "client0", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "commitTransaction" ], "errorCode": 11601, "closeConnection": false } } } }, { "object": "session0", "name": "startTransaction" }, { "object": "collection0", "name": "insertOne", "arguments": { "session": "session0", "document": { "_id": 1 } }, "expectResult": { "$$unsetOrMatches": { "insertedId": { "$$unsetOrMatches": 1 } } } }, { "object": "session0", "name": "commitTransaction", "expectError": { "errorCodeName": "Interrupted", "errorLabelsOmit": [ "RetryableWriteError", "TransientTransactionError", "UnknownTransactionCommitResult" ] } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "insert": "test", "documents": [ { "_id": 1 } ], "ordered": true, "readConcern": { "$$exists": false }, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": true, "autocommit": false, "writeConcern": { "$$exists": false } }, "commandName": "insert", "databaseName": "transaction-tests" } }, { "commandStartedEvent": { "command": { "commitTransaction": 1, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": { "$$exists": false }, "autocommit": false, "writeConcern": { "$$exists": false } }, "commandName": "commitTransaction", "databaseName": "admin" } } ] } ], "outcome": [ { "collectionName": "test", "databaseName": "transaction-tests", "documents": [] } ] }, { "description": "commitTransaction is not retried after UnsatisfiableWriteConcern error", "operations": [ { "object": "testRunner", "name": "failPoint", "arguments": { "client": "client0", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "commitTransaction" ], "writeConcernError": { "code": 100, "errmsg": "Not enough data-bearing nodes" } } } } }, { "object": "session0", "name": "startTransaction", "arguments": { "writeConcern": { "w": "majority" } } }, { "object": "collection0", "name": "insertOne", "arguments": { "session": "session0", "document": { "_id": 1 } }, "expectResult": { "$$unsetOrMatches": { "insertedId": { "$$unsetOrMatches": 1 } } } }, { "object": "session0", "name": "commitTransaction", "expectError": { "errorLabelsOmit": [ "RetryableWriteError", "TransientTransactionError", "UnknownTransactionCommitResult" ] } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "insert": "test", "documents": [ { "_id": 1 } ], "ordered": true, "readConcern": { "$$exists": false }, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": true, "autocommit": false, "writeConcern": { "$$exists": false } }, "commandName": "insert", "databaseName": "transaction-tests" } }, { "commandStartedEvent": { "command": { "commitTransaction": 1, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": { "$$exists": false }, "autocommit": false, "writeConcern": { "w": "majority" } }, "commandName": "commitTransaction", "databaseName": "admin" } } ] } ], "outcome": [ { "collectionName": "test", "databaseName": "transaction-tests", "documents": [ { "_id": 1 } ] } ] }, { "description": "commitTransaction fails after two errors", "runOnRequirements": [ { "serverless": "forbid" } ], "operations": [ { "object": "testRunner", "name": "failPoint", "arguments": { "client": "client1", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 2 }, "data": { "failCommands": [ "commitTransaction" ], "closeConnection": true } } } }, { "object": "session1", "name": "startTransaction" }, { "object": "collection1", "name": "insertOne", "arguments": { "session": "session1", "document": { "_id": 1 } }, "expectResult": { "$$unsetOrMatches": { "insertedId": { "$$unsetOrMatches": 1 } } } }, { "object": "session1", "name": "commitTransaction", "expectError": { "errorLabelsContain": [ "RetryableWriteError", "UnknownTransactionCommitResult" ], "errorLabelsOmit": [ "TransientTransactionError" ] } }, { "object": "session1", "name": "commitTransaction" } ], "expectEvents": [ { "client": "client1", "events": [ { "commandStartedEvent": { "command": { "insert": "test", "documents": [ { "_id": 1 } ], "ordered": true, "readConcern": { "$$exists": false }, "lsid": { "$$sessionLsid": "session1" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": true, "autocommit": false, "writeConcern": { "$$exists": false } }, "commandName": "insert", "databaseName": "transaction-tests" } }, { "commandStartedEvent": { "command": { "commitTransaction": 1, "lsid": { "$$sessionLsid": "session1" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": { "$$exists": false }, "autocommit": false, "writeConcern": { "$$exists": false } }, "commandName": "commitTransaction", "databaseName": "admin" } }, { "commandStartedEvent": { "command": { "commitTransaction": 1, "lsid": { "$$sessionLsid": "session1" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": { "$$exists": false }, "autocommit": false, "writeConcern": { "w": "majority", "wtimeout": 10000 } }, "commandName": "commitTransaction", "databaseName": "admin" } }, { "commandStartedEvent": { "command": { "commitTransaction": 1, "lsid": { "$$sessionLsid": "session1" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": { "$$exists": false }, "autocommit": false, "writeConcern": { "w": "majority", "wtimeout": 10000 } }, "commandName": "commitTransaction", "databaseName": "admin" } } ] } ], "outcome": [ { "collectionName": "test", "databaseName": "transaction-tests", "documents": [ { "_id": 1 } ] } ] }, { "description": "commitTransaction applies majority write concern on retries", "runOnRequirements": [ { "serverless": "forbid" } ], "operations": [ { "object": "testRunner", "name": "failPoint", "arguments": { "client": "client1", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 2 }, "data": { "failCommands": [ "commitTransaction" ], "closeConnection": true } } } }, { "object": "session1", "name": "startTransaction", "arguments": { "writeConcern": { "w": 2, "journal": true, "wtimeoutMS": 5000 } } }, { "object": "collection1", "name": "insertOne", "arguments": { "session": "session1", "document": { "_id": 1 } }, "expectResult": { "$$unsetOrMatches": { "insertedId": { "$$unsetOrMatches": 1 } } } }, { "object": "session1", "name": "commitTransaction", "expectError": { "errorLabelsContain": [ "RetryableWriteError", "UnknownTransactionCommitResult" ], "errorLabelsOmit": [ "TransientTransactionError" ] } }, { "object": "session1", "name": "commitTransaction" } ], "expectEvents": [ { "client": "client1", "events": [ { "commandStartedEvent": { "command": { "insert": "test", "documents": [ { "_id": 1 } ], "ordered": true, "readConcern": { "$$exists": false }, "lsid": { "$$sessionLsid": "session1" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": true, "autocommit": false, "writeConcern": { "$$exists": false } }, "commandName": "insert", "databaseName": "transaction-tests" } }, { "commandStartedEvent": { "command": { "commitTransaction": 1, "lsid": { "$$sessionLsid": "session1" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": { "$$exists": false }, "autocommit": false, "writeConcern": { "w": 2, "j": true, "wtimeout": 5000 } }, "commandName": "commitTransaction", "databaseName": "admin" } }, { "commandStartedEvent": { "command": { "commitTransaction": 1, "lsid": { "$$sessionLsid": "session1" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": { "$$exists": false }, "autocommit": false, "writeConcern": { "w": "majority", "j": true, "wtimeout": 5000 } }, "commandName": "commitTransaction", "databaseName": "admin" } }, { "commandStartedEvent": { "command": { "commitTransaction": 1, "lsid": { "$$sessionLsid": "session1" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": { "$$exists": false }, "autocommit": false, "writeConcern": { "w": "majority", "j": true, "wtimeout": 5000 } }, "commandName": "commitTransaction", "databaseName": "admin" } } ] } ], "outcome": [ { "collectionName": "test", "databaseName": "transaction-tests", "documents": [ { "_id": 1 } ] } ] }, { "description": "commitTransaction succeeds after connection error", "runOnRequirements": [ { "serverless": "forbid" } ], "operations": [ { "object": "testRunner", "name": "failPoint", "arguments": { "client": "client0", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "commitTransaction" ], "closeConnection": true } } } }, { "object": "session0", "name": "startTransaction" }, { "object": "collection0", "name": "insertOne", "arguments": { "session": "session0", "document": { "_id": 1 } }, "expectResult": { "$$unsetOrMatches": { "insertedId": { "$$unsetOrMatches": 1 } } } }, { "object": "session0", "name": "commitTransaction" } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "insert": "test", "documents": [ { "_id": 1 } ], "ordered": true, "readConcern": { "$$exists": false }, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": true, "autocommit": false, "writeConcern": { "$$exists": false } }, "commandName": "insert", "databaseName": "transaction-tests" } }, { "commandStartedEvent": { "command": { "commitTransaction": 1, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": { "$$exists": false }, "autocommit": false, "writeConcern": { "$$exists": false } }, "commandName": "commitTransaction", "databaseName": "admin" } }, { "commandStartedEvent": { "command": { "commitTransaction": 1, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": { "$$exists": false }, "autocommit": false, "writeConcern": { "w": "majority", "wtimeout": 10000 } }, "commandName": "commitTransaction", "databaseName": "admin" } } ] } ], "outcome": [ { "collectionName": "test", "databaseName": "transaction-tests", "documents": [ { "_id": 1 } ] } ] } ] } mongodb-mongo-python-driver-509e9b7/test/transactions/unified/retryable-writes.json000066400000000000000000000272421462766011000307550ustar00rootroot00000000000000{ "description": "retryable-writes", "schemaVersion": "1.3", "runOnRequirements": [ { "minServerVersion": "4.0", "topologies": [ "replicaset" ] }, { "minServerVersion": "4.1.8", "topologies": [ "sharded", "load-balanced" ] } ], "createEntities": [ { "client": { "id": "client0", "useMultipleMongoses": false, "observeEvents": [ "commandStartedEvent" ] } }, { "database": { "id": "database0", "client": "client0", "databaseName": "transaction-tests" } }, { "collection": { "id": "collection0", "database": "database0", "collectionName": "test" } }, { "session": { "id": "session0", "client": "client0" } } ], "initialData": [ { "collectionName": "test", "databaseName": "transaction-tests", "documents": [] } ], "tests": [ { "description": "increment txnNumber", "operations": [ { "object": "session0", "name": "startTransaction" }, { "object": "collection0", "name": "insertOne", "arguments": { "session": "session0", "document": { "_id": 1 } }, "expectResult": { "$$unsetOrMatches": { "insertedId": { "$$unsetOrMatches": 1 } } } }, { "object": "session0", "name": "commitTransaction" }, { "object": "collection0", "name": "insertOne", "arguments": { "session": "session0", "document": { "_id": 2 } }, "expectResult": { "$$unsetOrMatches": { "insertedId": { "$$unsetOrMatches": 2 } } } }, { "object": "session0", "name": "startTransaction" }, { "object": "collection0", "name": "insertOne", "arguments": { "session": "session0", "document": { "_id": 3 } }, "expectResult": { "$$unsetOrMatches": { "insertedId": { "$$unsetOrMatches": 3 } } } }, { "object": "session0", "name": "abortTransaction" }, { "object": "collection0", "name": "insertMany", "arguments": { "documents": [ { "_id": 4 }, { "_id": 5 } ], "session": "session0" }, "expectResult": { "$$unsetOrMatches": { "insertedIds": { "$$unsetOrMatches": { "0": 4, "1": 5 } } } } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "insert": "test", "documents": [ { "_id": 1 } ], "ordered": true, "readConcern": { "$$exists": false }, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": true, "autocommit": false, "writeConcern": { "$$exists": false } }, "commandName": "insert", "databaseName": "transaction-tests" } }, { "commandStartedEvent": { "command": { "commitTransaction": 1, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": { "$$exists": false }, "autocommit": false, "writeConcern": { "$$exists": false } }, "commandName": "commitTransaction", "databaseName": "admin" } }, { "commandStartedEvent": { "command": { "insert": "test", "documents": [ { "_id": 2 } ], "ordered": true, "readConcern": { "$$exists": false }, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "2" }, "startTransaction": { "$$exists": false }, "autocommit": { "$$exists": false }, "writeConcern": { "$$exists": false } }, "commandName": "insert", "databaseName": "transaction-tests" } }, { "commandStartedEvent": { "command": { "insert": "test", "documents": [ { "_id": 3 } ], "ordered": true, "readConcern": { "afterClusterTime": { "$$exists": true } }, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "3" }, "startTransaction": true, "autocommit": false, "writeConcern": { "$$exists": false } }, "commandName": "insert", "databaseName": "transaction-tests" } }, { "commandStartedEvent": { "command": { "abortTransaction": 1, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "3" }, "startTransaction": { "$$exists": false }, "autocommit": false, "writeConcern": { "$$exists": false } }, "commandName": "abortTransaction", "databaseName": "admin" } }, { "commandStartedEvent": { "command": { "insert": "test", "documents": [ { "_id": 4 }, { "_id": 5 } ], "ordered": true, "readConcern": { "$$exists": false }, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "4" }, "startTransaction": { "$$exists": false }, "autocommit": { "$$exists": false }, "writeConcern": { "$$exists": false } }, "commandName": "insert", "databaseName": "transaction-tests" } } ] } ], "outcome": [ { "collectionName": "test", "databaseName": "transaction-tests", "documents": [ { "_id": 1 }, { "_id": 2 }, { "_id": 4 }, { "_id": 5 } ] } ] }, { "description": "writes are not retried", "operations": [ { "object": "testRunner", "name": "failPoint", "arguments": { "client": "client0", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "insert" ], "closeConnection": true } } } }, { "object": "session0", "name": "startTransaction" }, { "object": "collection0", "name": "insertOne", "arguments": { "session": "session0", "document": { "_id": 1 } }, "expectError": { "errorLabelsContain": [ "TransientTransactionError" ] } }, { "object": "session0", "name": "abortTransaction" } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "insert": "test", "documents": [ { "_id": 1 } ], "ordered": true, "readConcern": { "$$exists": false }, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": true, "autocommit": false, "writeConcern": { "$$exists": false } }, "commandName": "insert", "databaseName": "transaction-tests" } }, { "commandStartedEvent": { "command": { "abortTransaction": 1, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": { "$$exists": false }, "autocommit": false, "writeConcern": { "$$exists": false } }, "commandName": "abortTransaction", "databaseName": "admin" } } ] } ], "outcome": [ { "collectionName": "test", "databaseName": "transaction-tests", "documents": [] } ] } ] } mongodb-mongo-python-driver-509e9b7/test/transactions/unified/run-command.json000066400000000000000000000247631462766011000276760ustar00rootroot00000000000000{ "description": "run-command", "schemaVersion": "1.9", "runOnRequirements": [ { "minServerVersion": "4.0", "topologies": [ "replicaset" ] }, { "minServerVersion": "4.1.8", "topologies": [ "sharded", "load-balanced" ] } ], "createEntities": [ { "client": { "id": "client0", "useMultipleMongoses": false, "observeEvents": [ "commandStartedEvent" ] } }, { "database": { "id": "database0", "client": "client0", "databaseName": "transaction-tests" } }, { "collection": { "id": "collection0", "database": "database0", "collectionName": "test" } }, { "session": { "id": "session0", "client": "client0" } } ], "initialData": [ { "collectionName": "test", "databaseName": "transaction-tests", "documents": [] } ], "tests": [ { "description": "run command with default read preference", "operations": [ { "object": "session0", "name": "startTransaction" }, { "object": "database0", "name": "runCommand", "arguments": { "session": "session0", "command": { "insert": "test", "documents": [ { "_id": 1 } ] }, "commandName": "insert" }, "expectResult": { "n": 1 } }, { "object": "session0", "name": "commitTransaction" } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "insert": "test", "documents": [ { "_id": 1 } ], "readConcern": { "$$exists": false }, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": true, "autocommit": false, "writeConcern": { "$$exists": false } }, "commandName": "insert", "databaseName": "transaction-tests" } }, { "commandStartedEvent": { "command": { "commitTransaction": 1, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": { "$$exists": false }, "autocommit": false, "writeConcern": { "$$exists": false } }, "commandName": "commitTransaction", "databaseName": "admin" } } ] } ] }, { "description": "run command with secondary read preference in client option and primary read preference in transaction options", "operations": [ { "object": "testRunner", "name": "createEntities", "arguments": { "entities": [ { "client": { "id": "client1", "useMultipleMongoses": false, "uriOptions": { "readPreference": "secondary" }, "observeEvents": [ "commandStartedEvent" ] } }, { "database": { "id": "database1", "client": "client1", "databaseName": "transaction-tests" } }, { "session": { "id": "session1", "client": "client1" } } ] } }, { "object": "session1", "name": "startTransaction", "arguments": { "readPreference": { "mode": "primary" } } }, { "object": "database1", "name": "runCommand", "arguments": { "session": "session1", "command": { "insert": "test", "documents": [ { "_id": 1 } ] }, "commandName": "insert" }, "expectResult": { "n": 1 } }, { "object": "session1", "name": "commitTransaction" } ], "expectEvents": [ { "client": "client1", "events": [ { "commandStartedEvent": { "command": { "insert": "test", "documents": [ { "_id": 1 } ], "readConcern": { "$$exists": false }, "lsid": { "$$sessionLsid": "session1" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": true, "autocommit": false, "writeConcern": { "$$exists": false } }, "commandName": "insert", "databaseName": "transaction-tests" } }, { "commandStartedEvent": { "command": { "commitTransaction": 1, "lsid": { "$$sessionLsid": "session1" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": { "$$exists": false }, "autocommit": false, "writeConcern": { "$$exists": false } }, "commandName": "commitTransaction", "databaseName": "admin" } } ] } ] }, { "description": "run command with explicit primary read preference", "operations": [ { "object": "session0", "name": "startTransaction" }, { "object": "database0", "name": "runCommand", "arguments": { "session": "session0", "command": { "insert": "test", "documents": [ { "_id": 1 } ] }, "readPreference": { "mode": "primary" }, "commandName": "insert" }, "expectResult": { "n": 1 } }, { "object": "session0", "name": "commitTransaction" } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "insert": "test", "documents": [ { "_id": 1 } ], "readConcern": { "$$exists": false }, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": true, "autocommit": false, "writeConcern": { "$$exists": false } }, "commandName": "insert", "databaseName": "transaction-tests" } }, { "commandStartedEvent": { "command": { "commitTransaction": 1, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": { "$$exists": false }, "autocommit": false, "writeConcern": { "$$exists": false } }, "commandName": "commitTransaction", "databaseName": "admin" } } ] } ] }, { "description": "run command fails with explicit secondary read preference", "operations": [ { "object": "session0", "name": "startTransaction" }, { "object": "database0", "name": "runCommand", "arguments": { "session": "session0", "command": { "find": "test" }, "readPreference": { "mode": "secondary" }, "commandName": "find" }, "expectError": { "errorContains": "read preference in a transaction must be primary" } } ] }, { "description": "run command fails with secondary read preference from transaction options", "operations": [ { "object": "session0", "name": "startTransaction", "arguments": { "readPreference": { "mode": "secondary" } } }, { "object": "database0", "name": "runCommand", "arguments": { "session": "session0", "command": { "find": "test" }, "commandName": "find" }, "expectError": { "errorContains": "read preference in a transaction must be primary" } } ] } ] } mongodb-mongo-python-driver-509e9b7/test/transactions/unified/transaction-options-repl.json000066400000000000000000000151421462766011000324230ustar00rootroot00000000000000{ "description": "transaction-options-repl", "schemaVersion": "1.9", "runOnRequirements": [ { "minServerVersion": "4.0", "topologies": [ "replicaset" ] } ], "createEntities": [ { "client": { "id": "client0", "useMultipleMongoses": false, "observeEvents": [ "commandStartedEvent" ] } }, { "database": { "id": "database0", "client": "client0", "databaseName": "transaction-tests" } }, { "collection": { "id": "collection0", "database": "database0", "collectionName": "test" } }, { "session": { "id": "session0", "client": "client0" } } ], "initialData": [ { "collectionName": "test", "databaseName": "transaction-tests", "documents": [] } ], "tests": [ { "description": "readConcern snapshot in startTransaction options", "operations": [ { "object": "testRunner", "name": "createEntities", "arguments": { "entities": [ { "session": { "id": "session1", "client": "client0", "sessionOptions": { "defaultTransactionOptions": { "readConcern": { "level": "majority" } } } } } ] } }, { "object": "session1", "name": "startTransaction", "arguments": { "readConcern": { "level": "snapshot" } } }, { "object": "collection0", "name": "insertOne", "arguments": { "session": "session1", "document": { "_id": 1 } }, "expectResult": { "$$unsetOrMatches": { "insertedId": { "$$unsetOrMatches": 1 } } } }, { "object": "session1", "name": "commitTransaction" }, { "object": "session1", "name": "startTransaction", "arguments": { "readConcern": { "level": "snapshot" } } }, { "object": "collection0", "name": "insertOne", "arguments": { "session": "session1", "document": { "_id": 2 } }, "expectResult": { "$$unsetOrMatches": { "insertedId": { "$$unsetOrMatches": 2 } } } }, { "object": "session1", "name": "abortTransaction" } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "insert": "test", "documents": [ { "_id": 1 } ], "ordered": true, "lsid": { "$$sessionLsid": "session1" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": true, "autocommit": false, "readConcern": { "level": "snapshot" }, "writeConcern": { "$$exists": false } }, "commandName": "insert", "databaseName": "transaction-tests" } }, { "commandStartedEvent": { "command": { "commitTransaction": 1, "lsid": { "$$sessionLsid": "session1" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": { "$$exists": false }, "autocommit": false, "readConcern": { "$$exists": false }, "writeConcern": { "$$exists": false } }, "commandName": "commitTransaction", "databaseName": "admin" } }, { "commandStartedEvent": { "command": { "insert": "test", "documents": [ { "_id": 2 } ], "ordered": true, "lsid": { "$$sessionLsid": "session1" }, "txnNumber": { "$numberLong": "2" }, "startTransaction": true, "autocommit": false, "readConcern": { "level": "snapshot", "afterClusterTime": { "$$exists": true } }, "writeConcern": { "$$exists": false } }, "commandName": "insert", "databaseName": "transaction-tests" } }, { "commandStartedEvent": { "command": { "abortTransaction": 1, "lsid": { "$$sessionLsid": "session1" }, "txnNumber": { "$numberLong": "2" }, "startTransaction": { "$$exists": false }, "autocommit": false, "readConcern": { "$$exists": false }, "writeConcern": { "$$exists": false } }, "commandName": "abortTransaction", "databaseName": "admin" } } ] } ], "outcome": [ { "collectionName": "test", "databaseName": "transaction-tests", "documents": [ { "_id": 1 } ] } ] } ] } mongodb-mongo-python-driver-509e9b7/test/transactions/unified/transaction-options.json000066400000000000000000001556601462766011000314750ustar00rootroot00000000000000{ "description": "transaction-options", "schemaVersion": "1.9", "runOnRequirements": [ { "minServerVersion": "4.0", "topologies": [ "replicaset" ] }, { "minServerVersion": "4.1.8", "topologies": [ "sharded", "load-balanced" ] } ], "createEntities": [ { "client": { "id": "client0", "useMultipleMongoses": false, "observeEvents": [ "commandStartedEvent" ] } }, { "database": { "id": "database0", "client": "client0", "databaseName": "transaction-tests" } }, { "collection": { "id": "collection0", "database": "database0", "collectionName": "test" } }, { "session": { "id": "session0", "client": "client0" } } ], "initialData": [ { "collectionName": "test", "databaseName": "transaction-tests", "documents": [] } ], "tests": [ { "description": "no transaction options set", "operations": [ { "object": "session0", "name": "startTransaction" }, { "object": "collection0", "name": "insertOne", "arguments": { "session": "session0", "document": { "_id": 1 } }, "expectResult": { "$$unsetOrMatches": { "insertedId": { "$$unsetOrMatches": 1 } } } }, { "object": "session0", "name": "commitTransaction" }, { "object": "session0", "name": "startTransaction" }, { "object": "collection0", "name": "insertOne", "arguments": { "session": "session0", "document": { "_id": 2 } }, "expectResult": { "$$unsetOrMatches": { "insertedId": { "$$unsetOrMatches": 2 } } } }, { "object": "session0", "name": "abortTransaction" } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "insert": "test", "documents": [ { "_id": 1 } ], "ordered": true, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": true, "autocommit": false, "readConcern": { "$$exists": false }, "writeConcern": { "$$exists": false }, "maxTimeMS": { "$$exists": false } }, "commandName": "insert", "databaseName": "transaction-tests" } }, { "commandStartedEvent": { "command": { "commitTransaction": 1, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": { "$$exists": false }, "autocommit": false, "readConcern": { "$$exists": false }, "writeConcern": { "$$exists": false }, "maxTimeMS": { "$$exists": false } }, "commandName": "commitTransaction", "databaseName": "admin" } }, { "commandStartedEvent": { "command": { "insert": "test", "documents": [ { "_id": 2 } ], "ordered": true, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "2" }, "startTransaction": true, "autocommit": false, "readConcern": { "afterClusterTime": { "$$exists": true } }, "writeConcern": { "$$exists": false }, "maxTimeMS": { "$$exists": false } }, "commandName": "insert", "databaseName": "transaction-tests" } }, { "commandStartedEvent": { "command": { "abortTransaction": 1, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "2" }, "startTransaction": { "$$exists": false }, "autocommit": false, "readConcern": { "$$exists": false }, "writeConcern": { "$$exists": false }, "maxTimeMS": { "$$exists": false } }, "commandName": "abortTransaction", "databaseName": "admin" } } ] } ], "outcome": [ { "collectionName": "test", "databaseName": "transaction-tests", "documents": [ { "_id": 1 } ] } ] }, { "description": "transaction options inherited from client", "operations": [ { "object": "testRunner", "name": "createEntities", "arguments": { "entities": [ { "client": { "id": "client1", "useMultipleMongoses": false, "uriOptions": { "readConcernLevel": "local", "w": 1 }, "observeEvents": [ "commandStartedEvent" ] } }, { "database": { "id": "database1", "client": "client1", "databaseName": "transaction-tests" } }, { "collection": { "id": "collection1", "database": "database1", "collectionName": "test" } }, { "session": { "id": "session1", "client": "client1" } } ] } }, { "object": "session1", "name": "startTransaction" }, { "object": "collection1", "name": "insertOne", "arguments": { "session": "session1", "document": { "_id": 1 } }, "expectResult": { "$$unsetOrMatches": { "insertedId": { "$$unsetOrMatches": 1 } } } }, { "object": "session1", "name": "commitTransaction" }, { "object": "session1", "name": "startTransaction" }, { "object": "collection1", "name": "insertOne", "arguments": { "session": "session1", "document": { "_id": 2 } }, "expectResult": { "$$unsetOrMatches": { "insertedId": { "$$unsetOrMatches": 2 } } } }, { "object": "session1", "name": "abortTransaction" } ], "expectEvents": [ { "client": "client1", "events": [ { "commandStartedEvent": { "command": { "insert": "test", "documents": [ { "_id": 1 } ], "ordered": true, "lsid": { "$$sessionLsid": "session1" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": true, "autocommit": false, "readConcern": { "level": "local" }, "writeConcern": { "$$exists": false }, "maxTimeMS": { "$$exists": false } }, "commandName": "insert", "databaseName": "transaction-tests" } }, { "commandStartedEvent": { "command": { "commitTransaction": 1, "lsid": { "$$sessionLsid": "session1" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": { "$$exists": false }, "autocommit": false, "readConcern": { "$$exists": false }, "writeConcern": { "w": 1 }, "maxTimeMS": { "$$exists": false } }, "commandName": "commitTransaction", "databaseName": "admin" } }, { "commandStartedEvent": { "command": { "insert": "test", "documents": [ { "_id": 2 } ], "ordered": true, "lsid": { "$$sessionLsid": "session1" }, "txnNumber": { "$numberLong": "2" }, "startTransaction": true, "autocommit": false, "readConcern": { "level": "local", "afterClusterTime": { "$$exists": true } }, "writeConcern": { "$$exists": false }, "maxTimeMS": { "$$exists": false } }, "commandName": "insert", "databaseName": "transaction-tests" } }, { "commandStartedEvent": { "command": { "abortTransaction": 1, "lsid": { "$$sessionLsid": "session1" }, "txnNumber": { "$numberLong": "2" }, "startTransaction": { "$$exists": false }, "autocommit": false, "readConcern": { "$$exists": false }, "writeConcern": { "w": 1 }, "maxTimeMS": { "$$exists": false } }, "commandName": "abortTransaction", "databaseName": "admin" } } ] } ], "outcome": [ { "collectionName": "test", "databaseName": "transaction-tests", "documents": [ { "_id": 1 } ] } ] }, { "description": "transaction options inherited from defaultTransactionOptions", "operations": [ { "object": "testRunner", "name": "createEntities", "arguments": { "entities": [ { "session": { "id": "session1", "client": "client0", "sessionOptions": { "defaultTransactionOptions": { "readConcern": { "level": "majority" }, "writeConcern": { "w": 1 }, "maxCommitTimeMS": 60000 } } } } ] } }, { "object": "session1", "name": "startTransaction" }, { "object": "collection0", "name": "insertOne", "arguments": { "session": "session1", "document": { "_id": 1 } }, "expectResult": { "$$unsetOrMatches": { "insertedId": { "$$unsetOrMatches": 1 } } } }, { "object": "session1", "name": "commitTransaction" }, { "object": "session1", "name": "startTransaction" }, { "object": "collection0", "name": "insertOne", "arguments": { "session": "session1", "document": { "_id": 2 } }, "expectResult": { "$$unsetOrMatches": { "insertedId": { "$$unsetOrMatches": 2 } } } }, { "object": "session1", "name": "abortTransaction" } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "insert": "test", "documents": [ { "_id": 1 } ], "ordered": true, "lsid": { "$$sessionLsid": "session1" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": true, "autocommit": false, "readConcern": { "level": "majority" }, "writeConcern": { "$$exists": false } }, "commandName": "insert", "databaseName": "transaction-tests" } }, { "commandStartedEvent": { "command": { "commitTransaction": 1, "lsid": { "$$sessionLsid": "session1" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": { "$$exists": false }, "autocommit": false, "readConcern": { "$$exists": false }, "writeConcern": { "w": 1 }, "maxTimeMS": 60000 }, "commandName": "commitTransaction", "databaseName": "admin" } }, { "commandStartedEvent": { "command": { "insert": "test", "documents": [ { "_id": 2 } ], "ordered": true, "lsid": { "$$sessionLsid": "session1" }, "txnNumber": { "$numberLong": "2" }, "startTransaction": true, "autocommit": false, "readConcern": { "level": "majority", "afterClusterTime": { "$$exists": true } }, "writeConcern": { "$$exists": false } }, "commandName": "insert", "databaseName": "transaction-tests" } }, { "commandStartedEvent": { "command": { "abortTransaction": 1, "lsid": { "$$sessionLsid": "session1" }, "txnNumber": { "$numberLong": "2" }, "startTransaction": { "$$exists": false }, "autocommit": false, "readConcern": { "$$exists": false }, "writeConcern": { "w": 1 } }, "commandName": "abortTransaction", "databaseName": "admin" } } ] } ], "outcome": [ { "collectionName": "test", "databaseName": "transaction-tests", "documents": [ { "_id": 1 } ] } ] }, { "description": "startTransaction options override defaults", "operations": [ { "object": "testRunner", "name": "createEntities", "arguments": { "entities": [ { "client": { "id": "client1", "useMultipleMongoses": false, "uriOptions": { "readConcernLevel": "local", "w": 1 }, "observeEvents": [ "commandStartedEvent" ] } }, { "database": { "id": "database1", "client": "client1", "databaseName": "transaction-tests" } }, { "collection": { "id": "collection1", "database": "database1", "collectionName": "test" } }, { "session": { "id": "session1", "client": "client1", "sessionOptions": { "defaultTransactionOptions": { "readConcern": { "level": "snapshot" }, "writeConcern": { "w": 1 }, "maxCommitTimeMS": 30000 } } } } ] } }, { "object": "session1", "name": "startTransaction", "arguments": { "readConcern": { "level": "majority" }, "writeConcern": { "w": "majority" }, "maxCommitTimeMS": 60000 } }, { "object": "collection1", "name": "insertOne", "arguments": { "session": "session1", "document": { "_id": 1 } }, "expectResult": { "$$unsetOrMatches": { "insertedId": { "$$unsetOrMatches": 1 } } } }, { "object": "session1", "name": "commitTransaction" }, { "object": "session1", "name": "startTransaction", "arguments": { "readConcern": { "level": "majority" }, "writeConcern": { "w": "majority" } } }, { "object": "collection1", "name": "insertOne", "arguments": { "session": "session1", "document": { "_id": 2 } }, "expectResult": { "$$unsetOrMatches": { "insertedId": { "$$unsetOrMatches": 2 } } } }, { "object": "session1", "name": "abortTransaction" } ], "expectEvents": [ { "client": "client1", "events": [ { "commandStartedEvent": { "command": { "insert": "test", "documents": [ { "_id": 1 } ], "ordered": true, "lsid": { "$$sessionLsid": "session1" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": true, "autocommit": false, "readConcern": { "level": "majority" }, "writeConcern": { "$$exists": false }, "maxTimeMS": { "$$exists": false } }, "commandName": "insert", "databaseName": "transaction-tests" } }, { "commandStartedEvent": { "command": { "commitTransaction": 1, "lsid": { "$$sessionLsid": "session1" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": { "$$exists": false }, "autocommit": false, "readConcern": { "$$exists": false }, "writeConcern": { "w": "majority" }, "maxTimeMS": 60000 }, "commandName": "commitTransaction", "databaseName": "admin" } }, { "commandStartedEvent": { "command": { "insert": "test", "documents": [ { "_id": 2 } ], "ordered": true, "lsid": { "$$sessionLsid": "session1" }, "txnNumber": { "$numberLong": "2" }, "startTransaction": true, "autocommit": false, "readConcern": { "level": "majority", "afterClusterTime": { "$$exists": true } }, "writeConcern": { "$$exists": false }, "maxTimeMS": { "$$exists": false } }, "commandName": "insert", "databaseName": "transaction-tests" } }, { "commandStartedEvent": { "command": { "abortTransaction": 1, "lsid": { "$$sessionLsid": "session1" }, "txnNumber": { "$numberLong": "2" }, "startTransaction": { "$$exists": false }, "autocommit": false, "readConcern": { "$$exists": false }, "writeConcern": { "w": "majority" }, "maxTimeMS": { "$$exists": false } }, "commandName": "abortTransaction", "databaseName": "admin" } } ] } ], "outcome": [ { "collectionName": "test", "databaseName": "transaction-tests", "documents": [ { "_id": 1 } ] } ] }, { "description": "defaultTransactionOptions override client options", "operations": [ { "object": "testRunner", "name": "createEntities", "arguments": { "entities": [ { "client": { "id": "client1", "useMultipleMongoses": false, "uriOptions": { "readConcernLevel": "local", "w": 1 }, "observeEvents": [ "commandStartedEvent" ] } }, { "database": { "id": "database1", "client": "client1", "databaseName": "transaction-tests" } }, { "collection": { "id": "collection1", "database": "database1", "collectionName": "test" } }, { "session": { "id": "session1", "client": "client1", "sessionOptions": { "defaultTransactionOptions": { "readConcern": { "level": "majority" }, "writeConcern": { "w": "majority" }, "maxCommitTimeMS": 60000 } } } } ] } }, { "object": "session1", "name": "startTransaction" }, { "object": "collection1", "name": "insertOne", "arguments": { "session": "session1", "document": { "_id": 1 } }, "expectResult": { "$$unsetOrMatches": { "insertedId": { "$$unsetOrMatches": 1 } } } }, { "object": "session1", "name": "commitTransaction" }, { "object": "session1", "name": "startTransaction" }, { "object": "collection1", "name": "insertOne", "arguments": { "session": "session1", "document": { "_id": 2 } }, "expectResult": { "$$unsetOrMatches": { "insertedId": { "$$unsetOrMatches": 2 } } } }, { "object": "session1", "name": "abortTransaction" } ], "expectEvents": [ { "client": "client1", "events": [ { "commandStartedEvent": { "command": { "insert": "test", "documents": [ { "_id": 1 } ], "ordered": true, "lsid": { "$$sessionLsid": "session1" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": true, "autocommit": false, "readConcern": { "level": "majority" }, "writeConcern": { "$$exists": false }, "maxTimeMS": { "$$exists": false } }, "commandName": "insert", "databaseName": "transaction-tests" } }, { "commandStartedEvent": { "command": { "commitTransaction": 1, "lsid": { "$$sessionLsid": "session1" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": { "$$exists": false }, "autocommit": false, "readConcern": { "$$exists": false }, "writeConcern": { "w": "majority" }, "maxTimeMS": 60000 }, "commandName": "commitTransaction", "databaseName": "admin" } }, { "commandStartedEvent": { "command": { "insert": "test", "documents": [ { "_id": 2 } ], "ordered": true, "lsid": { "$$sessionLsid": "session1" }, "txnNumber": { "$numberLong": "2" }, "startTransaction": true, "autocommit": false, "readConcern": { "level": "majority", "afterClusterTime": { "$$exists": true } }, "writeConcern": { "$$exists": false }, "maxTimeMS": { "$$exists": false } }, "commandName": "insert", "databaseName": "transaction-tests" } }, { "commandStartedEvent": { "command": { "abortTransaction": 1, "lsid": { "$$sessionLsid": "session1" }, "txnNumber": { "$numberLong": "2" }, "startTransaction": { "$$exists": false }, "autocommit": false, "readConcern": { "$$exists": false }, "writeConcern": { "w": "majority" }, "maxTimeMS": { "$$exists": false } }, "commandName": "abortTransaction", "databaseName": "admin" } } ] } ], "outcome": [ { "collectionName": "test", "databaseName": "transaction-tests", "documents": [ { "_id": 1 } ] } ] }, { "description": "readConcern local in defaultTransactionOptions", "operations": [ { "object": "testRunner", "name": "createEntities", "arguments": { "entities": [ { "client": { "id": "client1", "useMultipleMongoses": false, "uriOptions": { "w": 1 }, "observeEvents": [ "commandStartedEvent" ] } }, { "database": { "id": "database1", "client": "client1", "databaseName": "transaction-tests" } }, { "collection": { "id": "collection1", "database": "database1", "collectionName": "test" } }, { "session": { "id": "session1", "client": "client1", "sessionOptions": { "defaultTransactionOptions": { "readConcern": { "level": "local" } } } } } ] } }, { "object": "session1", "name": "startTransaction" }, { "object": "collection1", "name": "insertOne", "arguments": { "session": "session1", "document": { "_id": 1 } }, "expectResult": { "$$unsetOrMatches": { "insertedId": { "$$unsetOrMatches": 1 } } } }, { "object": "session1", "name": "commitTransaction" }, { "object": "session1", "name": "startTransaction" }, { "object": "collection1", "name": "insertOne", "arguments": { "session": "session1", "document": { "_id": 2 } }, "expectResult": { "$$unsetOrMatches": { "insertedId": { "$$unsetOrMatches": 2 } } } }, { "object": "session1", "name": "abortTransaction" } ], "expectEvents": [ { "client": "client1", "events": [ { "commandStartedEvent": { "command": { "insert": "test", "documents": [ { "_id": 1 } ], "ordered": true, "lsid": { "$$sessionLsid": "session1" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": true, "autocommit": false, "readConcern": { "level": "local" }, "writeConcern": { "$$exists": false } }, "commandName": "insert", "databaseName": "transaction-tests" } }, { "commandStartedEvent": { "command": { "commitTransaction": 1, "lsid": { "$$sessionLsid": "session1" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": { "$$exists": false }, "autocommit": false, "readConcern": { "$$exists": false }, "writeConcern": { "w": 1 } }, "commandName": "commitTransaction", "databaseName": "admin" } }, { "commandStartedEvent": { "command": { "insert": "test", "documents": [ { "_id": 2 } ], "ordered": true, "lsid": { "$$sessionLsid": "session1" }, "txnNumber": { "$numberLong": "2" }, "startTransaction": true, "autocommit": false, "readConcern": { "level": "local", "afterClusterTime": { "$$exists": true } }, "writeConcern": { "$$exists": false } }, "commandName": "insert", "databaseName": "transaction-tests" } }, { "commandStartedEvent": { "command": { "abortTransaction": 1, "lsid": { "$$sessionLsid": "session1" }, "txnNumber": { "$numberLong": "2" }, "startTransaction": { "$$exists": false }, "autocommit": false, "readConcern": { "$$exists": false }, "writeConcern": { "w": 1 } }, "commandName": "abortTransaction", "databaseName": "admin" } } ] } ], "outcome": [ { "collectionName": "test", "databaseName": "transaction-tests", "documents": [ { "_id": 1 } ] } ] }, { "description": "client writeConcern ignored for bulk", "operations": [ { "object": "testRunner", "name": "createEntities", "arguments": { "entities": [ { "client": { "id": "client1", "useMultipleMongoses": false, "uriOptions": { "w": "majority" }, "observeEvents": [ "commandStartedEvent" ] } }, { "database": { "id": "database1", "client": "client1", "databaseName": "transaction-tests" } }, { "collection": { "id": "collection1", "database": "database1", "collectionName": "test" } }, { "session": { "id": "session1", "client": "client1" } } ] } }, { "object": "session1", "name": "startTransaction", "arguments": { "writeConcern": { "w": 1 } } }, { "object": "collection1", "name": "bulkWrite", "arguments": { "requests": [ { "insertOne": { "document": { "_id": 1 } } } ], "session": "session1" }, "expectResult": { "deletedCount": 0, "insertedCount": 1, "insertedIds": { "$$unsetOrMatches": { "0": 1 } }, "matchedCount": 0, "modifiedCount": 0, "upsertedCount": 0, "upsertedIds": {} } }, { "object": "session1", "name": "commitTransaction" } ], "expectEvents": [ { "client": "client1", "events": [ { "commandStartedEvent": { "command": { "insert": "test", "documents": [ { "_id": 1 } ], "ordered": true, "readConcern": { "$$exists": false }, "lsid": { "$$sessionLsid": "session1" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": true, "autocommit": false, "writeConcern": { "$$exists": false } }, "commandName": "insert", "databaseName": "transaction-tests" } }, { "commandStartedEvent": { "command": { "commitTransaction": 1, "lsid": { "$$sessionLsid": "session1" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": { "$$exists": false }, "autocommit": false, "writeConcern": { "w": 1 } }, "commandName": "commitTransaction", "databaseName": "admin" } } ] } ], "outcome": [ { "collectionName": "test", "databaseName": "transaction-tests", "documents": [ { "_id": 1 } ] } ] }, { "description": "readPreference inherited from client", "operations": [ { "object": "testRunner", "name": "createEntities", "arguments": { "entities": [ { "client": { "id": "client1", "useMultipleMongoses": false, "uriOptions": { "readPreference": "secondary" }, "observeEvents": [ "commandStartedEvent" ] } }, { "database": { "id": "database1", "client": "client1", "databaseName": "transaction-tests" } }, { "collection": { "id": "collection1", "database": "database1", "collectionName": "test" } }, { "session": { "id": "session1", "client": "client1" } } ] } }, { "object": "session1", "name": "startTransaction" }, { "object": "collection1", "name": "insertOne", "arguments": { "session": "session1", "document": { "_id": 1 } }, "expectResult": { "$$unsetOrMatches": { "insertedId": { "$$unsetOrMatches": 1 } } } }, { "object": "collection1", "name": "find", "arguments": { "session": "session1", "filter": { "_id": 1 } }, "expectError": { "errorContains": "read preference in a transaction must be primary" } }, { "object": "session1", "name": "commitTransaction" } ], "expectEvents": [ { "client": "client1", "events": [ { "commandStartedEvent": { "command": { "insert": "test", "documents": [ { "_id": 1 } ], "ordered": true, "lsid": { "$$sessionLsid": "session1" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": true, "autocommit": false, "readConcern": { "$$exists": false }, "writeConcern": { "$$exists": false } }, "commandName": "insert", "databaseName": "transaction-tests" } }, { "commandStartedEvent": { "command": { "commitTransaction": 1, "lsid": { "$$sessionLsid": "session1" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": { "$$exists": false }, "autocommit": false, "readConcern": { "$$exists": false }, "writeConcern": { "$$exists": false } }, "commandName": "commitTransaction", "databaseName": "admin" } } ] } ], "outcome": [ { "collectionName": "test", "databaseName": "transaction-tests", "documents": [ { "_id": 1 } ] } ] }, { "description": "readPreference inherited from defaultTransactionOptions", "operations": [ { "object": "testRunner", "name": "createEntities", "arguments": { "entities": [ { "client": { "id": "client1", "useMultipleMongoses": false, "uriOptions": { "readPreference": "primary" }, "observeEvents": [ "commandStartedEvent" ] } }, { "database": { "id": "database1", "client": "client1", "databaseName": "transaction-tests" } }, { "collection": { "id": "collection1", "database": "database1", "collectionName": "test" } }, { "session": { "id": "session1", "client": "client1", "sessionOptions": { "defaultTransactionOptions": { "readPreference": { "mode": "secondary" } } } } } ] } }, { "object": "session1", "name": "startTransaction" }, { "object": "collection1", "name": "insertOne", "arguments": { "session": "session1", "document": { "_id": 1 } }, "expectResult": { "$$unsetOrMatches": { "insertedId": { "$$unsetOrMatches": 1 } } } }, { "object": "collection1", "name": "find", "arguments": { "session": "session1", "filter": { "_id": 1 } }, "expectError": { "errorContains": "read preference in a transaction must be primary" } }, { "object": "session1", "name": "commitTransaction" } ], "expectEvents": [ { "client": "client1", "events": [ { "commandStartedEvent": { "command": { "insert": "test", "documents": [ { "_id": 1 } ], "ordered": true, "lsid": { "$$sessionLsid": "session1" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": true, "autocommit": false, "readConcern": { "$$exists": false }, "writeConcern": { "$$exists": false } }, "commandName": "insert", "databaseName": "transaction-tests" } }, { "commandStartedEvent": { "command": { "commitTransaction": 1, "lsid": { "$$sessionLsid": "session1" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": { "$$exists": false }, "autocommit": false, "readConcern": { "$$exists": false }, "writeConcern": { "$$exists": false } }, "commandName": "commitTransaction", "databaseName": "admin" } } ] } ], "outcome": [ { "collectionName": "test", "databaseName": "transaction-tests", "documents": [ { "_id": 1 } ] } ] }, { "description": "startTransaction overrides readPreference", "operations": [ { "object": "testRunner", "name": "createEntities", "arguments": { "entities": [ { "client": { "id": "client1", "useMultipleMongoses": false, "uriOptions": { "readPreference": "primary" }, "observeEvents": [ "commandStartedEvent" ] } }, { "database": { "id": "database1", "client": "client1", "databaseName": "transaction-tests" } }, { "collection": { "id": "collection1", "database": "database1", "collectionName": "test" } }, { "session": { "id": "session1", "client": "client1", "sessionOptions": { "defaultTransactionOptions": { "readPreference": { "mode": "primary" } } } } } ] } }, { "object": "session1", "name": "startTransaction", "arguments": { "readPreference": { "mode": "secondary" } } }, { "object": "collection1", "name": "insertOne", "arguments": { "session": "session1", "document": { "_id": 1 } }, "expectResult": { "$$unsetOrMatches": { "insertedId": { "$$unsetOrMatches": 1 } } } }, { "object": "collection1", "name": "find", "arguments": { "session": "session1", "filter": { "_id": 1 } }, "expectError": { "errorContains": "read preference in a transaction must be primary" } }, { "object": "session1", "name": "commitTransaction" } ], "expectEvents": [ { "client": "client1", "events": [ { "commandStartedEvent": { "command": { "insert": "test", "documents": [ { "_id": 1 } ], "ordered": true, "lsid": { "$$sessionLsid": "session1" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": true, "autocommit": false, "readConcern": { "$$exists": false }, "writeConcern": { "$$exists": false } }, "commandName": "insert", "databaseName": "transaction-tests" } }, { "commandStartedEvent": { "command": { "commitTransaction": 1, "lsid": { "$$sessionLsid": "session1" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": { "$$exists": false }, "autocommit": false, "readConcern": { "$$exists": false }, "writeConcern": { "$$exists": false } }, "commandName": "commitTransaction", "databaseName": "admin" } } ] } ], "outcome": [ { "collectionName": "test", "databaseName": "transaction-tests", "documents": [ { "_id": 1 } ] } ] } ] } mongodb-mongo-python-driver-509e9b7/test/transactions/unified/update.json000066400000000000000000000344461462766011000267370ustar00rootroot00000000000000{ "description": "update", "schemaVersion": "1.9", "runOnRequirements": [ { "minServerVersion": "4.0", "topologies": [ "replicaset" ] }, { "minServerVersion": "4.1.8", "topologies": [ "sharded", "load-balanced" ] } ], "createEntities": [ { "client": { "id": "client0", "useMultipleMongoses": false, "observeEvents": [ "commandStartedEvent" ] } }, { "database": { "id": "database0", "client": "client0", "databaseName": "transaction-tests" } }, { "collection": { "id": "collection0", "database": "database0", "collectionName": "test" } }, { "session": { "id": "session0", "client": "client0" } } ], "initialData": [ { "collectionName": "test", "databaseName": "transaction-tests", "documents": [ { "_id": 1 }, { "_id": 2 }, { "_id": 3 } ] } ], "tests": [ { "description": "update", "operations": [ { "object": "session0", "name": "startTransaction" }, { "object": "collection0", "name": "updateOne", "arguments": { "session": "session0", "filter": { "_id": 4 }, "update": { "$inc": { "x": 1 } }, "upsert": true }, "expectResult": { "matchedCount": 0, "modifiedCount": 0, "upsertedCount": 1, "upsertedId": 4 } }, { "object": "collection0", "name": "replaceOne", "arguments": { "session": "session0", "filter": { "x": 1 }, "replacement": { "y": 1 } }, "expectResult": { "matchedCount": 1, "modifiedCount": 1, "upsertedCount": 0 } }, { "object": "collection0", "name": "updateMany", "arguments": { "session": "session0", "filter": { "_id": { "$gte": 3 } }, "update": { "$set": { "z": 1 } } }, "expectResult": { "matchedCount": 2, "modifiedCount": 2, "upsertedCount": 0 } }, { "object": "session0", "name": "commitTransaction" } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "update": "test", "updates": [ { "q": { "_id": 4 }, "u": { "$inc": { "x": 1 } }, "upsert": true, "multi": { "$$unsetOrMatches": false } } ], "ordered": true, "readConcern": { "$$exists": false }, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": true, "autocommit": false, "writeConcern": { "$$exists": false } }, "commandName": "update", "databaseName": "transaction-tests" } }, { "commandStartedEvent": { "command": { "update": "test", "updates": [ { "q": { "x": 1 }, "u": { "y": 1 }, "multi": { "$$unsetOrMatches": false }, "upsert": { "$$unsetOrMatches": false } } ], "ordered": true, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": { "$$exists": false }, "autocommit": false, "writeConcern": { "$$exists": false } }, "commandName": "update", "databaseName": "transaction-tests" } }, { "commandStartedEvent": { "command": { "update": "test", "updates": [ { "q": { "_id": { "$gte": 3 } }, "u": { "$set": { "z": 1 } }, "multi": true, "upsert": { "$$unsetOrMatches": false } } ], "ordered": true, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": { "$$exists": false }, "autocommit": false, "writeConcern": { "$$exists": false } }, "commandName": "update", "databaseName": "transaction-tests" } }, { "commandStartedEvent": { "command": { "commitTransaction": 1, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": { "$$exists": false }, "autocommit": false, "writeConcern": { "$$exists": false } }, "commandName": "commitTransaction", "databaseName": "admin" } } ] } ], "outcome": [ { "collectionName": "test", "databaseName": "transaction-tests", "documents": [ { "_id": 1 }, { "_id": 2 }, { "_id": 3, "z": 1 }, { "_id": 4, "y": 1, "z": 1 } ] } ] }, { "description": "collections writeConcern ignored for update", "operations": [ { "object": "testRunner", "name": "createEntities", "arguments": { "entities": [ { "collection": { "id": "collection1", "database": "database0", "collectionName": "test", "collectionOptions": { "writeConcern": { "w": "majority" } } } } ] } }, { "object": "session0", "name": "startTransaction", "arguments": { "writeConcern": { "w": "majority" } } }, { "object": "collection1", "name": "updateOne", "arguments": { "session": "session0", "filter": { "_id": 4 }, "update": { "$inc": { "x": 1 } }, "upsert": true }, "expectResult": { "matchedCount": 0, "modifiedCount": 0, "upsertedCount": 1, "upsertedId": 4 } }, { "object": "collection1", "name": "replaceOne", "arguments": { "session": "session0", "filter": { "x": 1 }, "replacement": { "y": 1 } }, "expectResult": { "matchedCount": 1, "modifiedCount": 1, "upsertedCount": 0 } }, { "object": "collection1", "name": "updateMany", "arguments": { "session": "session0", "filter": { "_id": { "$gte": 3 } }, "update": { "$set": { "z": 1 } } }, "expectResult": { "matchedCount": 2, "modifiedCount": 2, "upsertedCount": 0 } }, { "object": "session0", "name": "commitTransaction" } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "update": "test", "updates": [ { "q": { "_id": 4 }, "u": { "$inc": { "x": 1 } }, "upsert": true, "multi": { "$$unsetOrMatches": false } } ], "ordered": true, "readConcern": { "$$exists": false }, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": true, "autocommit": false, "writeConcern": { "$$exists": false } }, "commandName": "update", "databaseName": "transaction-tests" } }, { "commandStartedEvent": { "command": { "update": "test", "updates": [ { "q": { "x": 1 }, "u": { "y": 1 }, "multi": { "$$unsetOrMatches": false }, "upsert": { "$$unsetOrMatches": false } } ], "ordered": true, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": { "$$exists": false }, "autocommit": false, "writeConcern": { "$$exists": false } }, "commandName": "update", "databaseName": "transaction-tests" } }, { "commandStartedEvent": { "command": { "update": "test", "updates": [ { "q": { "_id": { "$gte": 3 } }, "u": { "$set": { "z": 1 } }, "multi": true, "upsert": { "$$unsetOrMatches": false } } ], "ordered": true, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": { "$$exists": false }, "autocommit": false, "writeConcern": { "$$exists": false } }, "commandName": "update", "databaseName": "transaction-tests" } }, { "commandStartedEvent": { "command": { "commitTransaction": 1, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": { "$$exists": false }, "autocommit": false, "writeConcern": { "w": "majority" } }, "commandName": "commitTransaction", "databaseName": "admin" } } ] } ] } ] } mongodb-mongo-python-driver-509e9b7/test/transactions/unified/write-concern.json000066400000000000000000001175141462766011000302320ustar00rootroot00000000000000{ "description": "write-concern", "schemaVersion": "1.9", "runOnRequirements": [ { "minServerVersion": "4.0", "topologies": [ "replicaset" ] }, { "minServerVersion": "4.1.8", "topologies": [ "sharded", "load-balanced" ] } ], "createEntities": [ { "client": { "id": "client0", "useMultipleMongoses": false, "observeEvents": [ "commandStartedEvent" ] } }, { "database": { "id": "database0", "client": "client0", "databaseName": "transaction-tests" } }, { "collection": { "id": "collection0", "database": "database0", "collectionName": "test" } }, { "collection": { "id": "collection_w0", "database": "database0", "collectionName": "test", "collectionOptions": { "writeConcern": { "w": 0 } } } }, { "session": { "id": "session0", "client": "client0" } } ], "initialData": [ { "collectionName": "test", "databaseName": "transaction-tests", "documents": [ { "_id": 0 } ] } ], "tests": [ { "description": "commit with majority", "operations": [ { "object": "session0", "name": "startTransaction", "arguments": { "writeConcern": { "w": "majority" } } }, { "object": "collection0", "name": "insertOne", "arguments": { "session": "session0", "document": { "_id": 1 } }, "expectResult": { "$$unsetOrMatches": { "insertedId": { "$$unsetOrMatches": 1 } } } }, { "object": "session0", "name": "commitTransaction" } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "insert": "test", "documents": [ { "_id": 1 } ], "ordered": true, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": true, "autocommit": false, "readConcern": { "$$exists": false }, "writeConcern": { "$$exists": false } }, "commandName": "insert", "databaseName": "transaction-tests" } }, { "commandStartedEvent": { "command": { "commitTransaction": 1, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": { "$$exists": false }, "autocommit": false, "writeConcern": { "w": "majority" } }, "commandName": "commitTransaction", "databaseName": "admin" } } ] } ], "outcome": [ { "collectionName": "test", "databaseName": "transaction-tests", "documents": [ { "_id": 0 }, { "_id": 1 } ] } ] }, { "description": "commit with default", "operations": [ { "object": "session0", "name": "startTransaction" }, { "object": "collection0", "name": "insertOne", "arguments": { "session": "session0", "document": { "_id": 1 } }, "expectResult": { "$$unsetOrMatches": { "insertedId": { "$$unsetOrMatches": 1 } } } }, { "object": "session0", "name": "commitTransaction" } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "insert": "test", "documents": [ { "_id": 1 } ], "ordered": true, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": true, "autocommit": false, "readConcern": { "$$exists": false }, "writeConcern": { "$$exists": false } }, "commandName": "insert", "databaseName": "transaction-tests" } }, { "commandStartedEvent": { "command": { "commitTransaction": 1, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": { "$$exists": false }, "autocommit": false, "writeConcern": { "$$exists": false } }, "commandName": "commitTransaction", "databaseName": "admin" } } ] } ], "outcome": [ { "collectionName": "test", "databaseName": "transaction-tests", "documents": [ { "_id": 0 }, { "_id": 1 } ] } ] }, { "description": "abort with majority", "operations": [ { "object": "session0", "name": "startTransaction", "arguments": { "writeConcern": { "w": "majority" } } }, { "object": "collection0", "name": "insertOne", "arguments": { "session": "session0", "document": { "_id": 1 } }, "expectResult": { "$$unsetOrMatches": { "insertedId": { "$$unsetOrMatches": 1 } } } }, { "object": "session0", "name": "abortTransaction" } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "insert": "test", "documents": [ { "_id": 1 } ], "ordered": true, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": true, "autocommit": false, "readConcern": { "$$exists": false }, "writeConcern": { "$$exists": false } }, "commandName": "insert", "databaseName": "transaction-tests" } }, { "commandStartedEvent": { "command": { "abortTransaction": 1, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": { "$$exists": false }, "autocommit": false, "writeConcern": { "w": "majority" } }, "commandName": "abortTransaction", "databaseName": "admin" } } ] } ], "outcome": [ { "collectionName": "test", "databaseName": "transaction-tests", "documents": [ { "_id": 0 } ] } ] }, { "description": "abort with default", "operations": [ { "object": "session0", "name": "startTransaction" }, { "object": "collection0", "name": "insertOne", "arguments": { "session": "session0", "document": { "_id": 1 } }, "expectResult": { "$$unsetOrMatches": { "insertedId": { "$$unsetOrMatches": 1 } } } }, { "object": "session0", "name": "abortTransaction" } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "insert": "test", "documents": [ { "_id": 1 } ], "ordered": true, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": true, "autocommit": false, "readConcern": { "$$exists": false }, "writeConcern": { "$$exists": false } }, "commandName": "insert", "databaseName": "transaction-tests" } }, { "commandStartedEvent": { "command": { "abortTransaction": 1, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": { "$$exists": false }, "autocommit": false, "writeConcern": { "$$exists": false } }, "commandName": "abortTransaction", "databaseName": "admin" } } ] } ], "outcome": [ { "collectionName": "test", "databaseName": "transaction-tests", "documents": [ { "_id": 0 } ] } ] }, { "description": "start with unacknowledged write concern", "operations": [ { "object": "session0", "name": "startTransaction", "arguments": { "writeConcern": { "w": 0 } }, "expectError": { "isClientError": true, "errorContains": "transactions do not support unacknowledged write concern" } } ] }, { "description": "start with implicit unacknowledged write concern", "operations": [ { "object": "testRunner", "name": "createEntities", "arguments": { "entities": [ { "client": { "id": "client1", "useMultipleMongoses": false, "uriOptions": { "w": 0 } } }, { "session": { "id": "session1", "client": "client1" } } ] } }, { "object": "session1", "name": "startTransaction", "expectError": { "isClientError": true, "errorContains": "transactions do not support unacknowledged write concern" } } ] }, { "description": "unacknowledged write concern coll insertOne", "operations": [ { "object": "session0", "name": "startTransaction" }, { "object": "collection_w0", "name": "insertOne", "arguments": { "session": "session0", "document": { "_id": 1 } }, "expectResult": { "$$unsetOrMatches": { "insertedId": { "$$unsetOrMatches": 1 } } } }, { "object": "session0", "name": "commitTransaction" } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "insert": "test", "documents": [ { "_id": 1 } ], "ordered": true, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": true, "autocommit": false, "readConcern": { "$$exists": false }, "writeConcern": { "$$exists": false } }, "commandName": "insert", "databaseName": "transaction-tests" } }, { "commandStartedEvent": { "command": { "commitTransaction": 1, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": { "$$exists": false }, "autocommit": false, "writeConcern": { "$$exists": false } }, "commandName": "commitTransaction", "databaseName": "admin" } } ] } ], "outcome": [ { "collectionName": "test", "databaseName": "transaction-tests", "documents": [ { "_id": 0 }, { "_id": 1 } ] } ] }, { "description": "unacknowledged write concern coll insertMany", "operations": [ { "object": "session0", "name": "startTransaction" }, { "object": "collection_w0", "name": "insertMany", "arguments": { "session": "session0", "documents": [ { "_id": 1 }, { "_id": 2 } ] }, "expectResult": { "$$unsetOrMatches": { "insertedIds": { "$$unsetOrMatches": { "0": 1, "1": 2 } } } } }, { "object": "session0", "name": "commitTransaction" } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "insert": "test", "documents": [ { "_id": 1 }, { "_id": 2 } ], "ordered": true, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": true, "autocommit": false, "readConcern": { "$$exists": false }, "writeConcern": { "$$exists": false } }, "commandName": "insert", "databaseName": "transaction-tests" } }, { "commandStartedEvent": { "command": { "commitTransaction": 1, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": { "$$exists": false }, "autocommit": false, "writeConcern": { "$$exists": false } }, "commandName": "commitTransaction", "databaseName": "admin" } } ] } ], "outcome": [ { "collectionName": "test", "databaseName": "transaction-tests", "documents": [ { "_id": 0 }, { "_id": 1 }, { "_id": 2 } ] } ] }, { "description": "unacknowledged write concern coll bulkWrite", "operations": [ { "object": "session0", "name": "startTransaction" }, { "object": "collection_w0", "name": "bulkWrite", "arguments": { "session": "session0", "requests": [ { "insertOne": { "document": { "_id": 1 } } } ] }, "expectResult": { "deletedCount": 0, "insertedCount": 1, "insertedIds": { "$$unsetOrMatches": { "0": 1 } }, "matchedCount": 0, "modifiedCount": 0, "upsertedCount": 0, "upsertedIds": {} } }, { "object": "session0", "name": "commitTransaction" } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "insert": "test", "documents": [ { "_id": 1 } ], "ordered": true, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": true, "autocommit": false, "readConcern": { "$$exists": false }, "writeConcern": { "$$exists": false } }, "commandName": "insert", "databaseName": "transaction-tests" } }, { "commandStartedEvent": { "command": { "commitTransaction": 1, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": { "$$exists": false }, "autocommit": false, "writeConcern": { "$$exists": false } }, "commandName": "commitTransaction", "databaseName": "admin" } } ] } ], "outcome": [ { "collectionName": "test", "databaseName": "transaction-tests", "documents": [ { "_id": 0 }, { "_id": 1 } ] } ] }, { "description": "unacknowledged write concern coll deleteOne", "operations": [ { "object": "session0", "name": "startTransaction" }, { "object": "collection_w0", "name": "deleteOne", "arguments": { "session": "session0", "filter": { "_id": 0 } }, "expectResult": { "deletedCount": 1 } }, { "object": "session0", "name": "commitTransaction" } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "delete": "test", "deletes": [ { "q": { "_id": 0 }, "limit": 1 } ], "ordered": true, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": true, "autocommit": false, "readConcern": { "$$exists": false }, "writeConcern": { "$$exists": false } }, "commandName": "delete", "databaseName": "transaction-tests" } }, { "commandStartedEvent": { "command": { "commitTransaction": 1, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": { "$$exists": false }, "autocommit": false, "writeConcern": { "$$exists": false } }, "commandName": "commitTransaction", "databaseName": "admin" } } ] } ], "outcome": [ { "collectionName": "test", "databaseName": "transaction-tests", "documents": [] } ] }, { "description": "unacknowledged write concern coll deleteMany", "operations": [ { "object": "session0", "name": "startTransaction" }, { "object": "collection_w0", "name": "deleteMany", "arguments": { "session": "session0", "filter": { "_id": 0 } }, "expectResult": { "deletedCount": 1 } }, { "object": "session0", "name": "commitTransaction" } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "delete": "test", "deletes": [ { "q": { "_id": 0 }, "limit": 0 } ], "ordered": true, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": true, "autocommit": false, "readConcern": { "$$exists": false }, "writeConcern": { "$$exists": false } }, "commandName": "delete", "databaseName": "transaction-tests" } }, { "commandStartedEvent": { "command": { "commitTransaction": 1, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": { "$$exists": false }, "autocommit": false, "writeConcern": { "$$exists": false } }, "commandName": "commitTransaction", "databaseName": "admin" } } ] } ], "outcome": [ { "collectionName": "test", "databaseName": "transaction-tests", "documents": [] } ] }, { "description": "unacknowledged write concern coll updateOne", "operations": [ { "object": "session0", "name": "startTransaction" }, { "object": "collection_w0", "name": "updateOne", "arguments": { "session": "session0", "filter": { "_id": 0 }, "update": { "$inc": { "x": 1 } }, "upsert": true }, "expectResult": { "matchedCount": 1, "modifiedCount": 1, "upsertedCount": 0 } }, { "object": "session0", "name": "commitTransaction" } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "update": "test", "updates": [ { "q": { "_id": 0 }, "u": { "$inc": { "x": 1 } }, "upsert": true, "multi": { "$$unsetOrMatches": false } } ], "ordered": true, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": true, "autocommit": false, "readConcern": { "$$exists": false }, "writeConcern": { "$$exists": false } }, "commandName": "update", "databaseName": "transaction-tests" } }, { "commandStartedEvent": { "command": { "commitTransaction": 1, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": { "$$exists": false }, "autocommit": false, "writeConcern": { "$$exists": false } }, "commandName": "commitTransaction", "databaseName": "admin" } } ] } ], "outcome": [ { "collectionName": "test", "databaseName": "transaction-tests", "documents": [ { "_id": 0, "x": 1 } ] } ] }, { "description": "unacknowledged write concern coll updateMany", "operations": [ { "object": "session0", "name": "startTransaction" }, { "object": "collection_w0", "name": "updateMany", "arguments": { "session": "session0", "filter": { "_id": 0 }, "update": { "$inc": { "x": 1 } }, "upsert": true }, "expectResult": { "matchedCount": 1, "modifiedCount": 1, "upsertedCount": 0 } }, { "object": "session0", "name": "commitTransaction" } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "update": "test", "updates": [ { "q": { "_id": 0 }, "u": { "$inc": { "x": 1 } }, "multi": true, "upsert": true } ], "ordered": true, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": true, "autocommit": false, "readConcern": { "$$exists": false }, "writeConcern": { "$$exists": false } }, "commandName": "update", "databaseName": "transaction-tests" } }, { "commandStartedEvent": { "command": { "commitTransaction": 1, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": { "$$exists": false }, "autocommit": false, "writeConcern": { "$$exists": false } }, "commandName": "commitTransaction", "databaseName": "admin" } } ] } ], "outcome": [ { "collectionName": "test", "databaseName": "transaction-tests", "documents": [ { "_id": 0, "x": 1 } ] } ] }, { "description": "unacknowledged write concern coll findOneAndDelete", "operations": [ { "object": "session0", "name": "startTransaction" }, { "object": "collection_w0", "name": "findOneAndDelete", "arguments": { "session": "session0", "filter": { "_id": 0 } }, "expectResult": { "_id": 0 } }, { "object": "session0", "name": "commitTransaction" } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "findAndModify": "test", "query": { "_id": 0 }, "remove": true, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": true, "autocommit": false, "readConcern": { "$$exists": false }, "writeConcern": { "$$exists": false } }, "commandName": "findAndModify", "databaseName": "transaction-tests" } }, { "commandStartedEvent": { "command": { "commitTransaction": 1, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": { "$$exists": false }, "autocommit": false, "writeConcern": { "$$exists": false } }, "commandName": "commitTransaction", "databaseName": "admin" } } ] } ], "outcome": [ { "collectionName": "test", "databaseName": "transaction-tests", "documents": [] } ] }, { "description": "unacknowledged write concern coll findOneAndReplace", "operations": [ { "object": "session0", "name": "startTransaction" }, { "object": "collection_w0", "name": "findOneAndReplace", "arguments": { "session": "session0", "filter": { "_id": 0 }, "replacement": { "x": 1 }, "returnDocument": "Before" }, "expectResult": { "_id": 0 } }, { "object": "session0", "name": "commitTransaction" } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "findAndModify": "test", "query": { "_id": 0 }, "update": { "x": 1 }, "new": false, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": true, "autocommit": false, "readConcern": { "$$exists": false }, "writeConcern": { "$$exists": false } }, "commandName": "findAndModify", "databaseName": "transaction-tests" } }, { "commandStartedEvent": { "command": { "commitTransaction": 1, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": { "$$exists": false }, "autocommit": false, "writeConcern": { "$$exists": false } }, "commandName": "commitTransaction", "databaseName": "admin" } } ] } ], "outcome": [ { "collectionName": "test", "databaseName": "transaction-tests", "documents": [ { "_id": 0, "x": 1 } ] } ] }, { "description": "unacknowledged write concern coll findOneAndUpdate", "operations": [ { "object": "session0", "name": "startTransaction" }, { "object": "collection_w0", "name": "findOneAndUpdate", "arguments": { "session": "session0", "filter": { "_id": 0 }, "update": { "$inc": { "x": 1 } }, "returnDocument": "Before" }, "expectResult": { "_id": 0 } }, { "object": "session0", "name": "commitTransaction" } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "findAndModify": "test", "query": { "_id": 0 }, "update": { "$inc": { "x": 1 } }, "new": false, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": true, "autocommit": false, "readConcern": { "$$exists": false }, "writeConcern": { "$$exists": false } }, "commandName": "findAndModify", "databaseName": "transaction-tests" } }, { "commandStartedEvent": { "command": { "commitTransaction": 1, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": { "$numberLong": "1" }, "startTransaction": { "$$exists": false }, "autocommit": false, "writeConcern": { "$$exists": false } }, "commandName": "commitTransaction", "databaseName": "admin" } } ] } ], "outcome": [ { "collectionName": "test", "databaseName": "transaction-tests", "documents": [ { "_id": 0, "x": 1 } ] } ] } ] } mongodb-mongo-python-driver-509e9b7/test/unicode/000077500000000000000000000000001462766011000220425ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/unicode/test_utf8.py000066400000000000000000000013751462766011000243470ustar00rootroot00000000000000from __future__ import annotations import sys sys.path[0:0] = [""] from test import unittest from bson import encode from bson.errors import InvalidStringData class TestUTF8(unittest.TestCase): # Verify that python and bson have the same understanding of # legal utf-8 if the first byte is 0xf4 (244) def _assert_same_utf8_validation(self, data): try: data.decode("utf-8") py_is_legal = True except UnicodeDecodeError: py_is_legal = False try: encode({"x": data}) bson_is_legal = True except InvalidStringData: bson_is_legal = False self.assertEqual(py_is_legal, bson_is_legal, data) if __name__ == "__main__": unittest.main() mongodb-mongo-python-driver-509e9b7/test/unified-test-format/000077500000000000000000000000001462766011000243025ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/unified-test-format/invalid/000077500000000000000000000000001462766011000257305ustar00rootroot00000000000000clientEncryptionOpts-additionalProperties.json000066400000000000000000000010641462766011000371270ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/unified-test-format/invalid{ "description": "clientEncryptionOpts-additionalProperties", "schemaVersion": "1.8", "createEntities": [ { "client": { "id": "client0" } }, { "clientEncryption": { "id": "clientEncryption0", "clientEncryptionOpts": { "keyVaultClient": "client0", "keyVaultNamespace": "keyvault.datakeys", "kmsProviders": { "aws": {} }, "invalid": {} } } } ], "tests": [ { "description": "", "operations": [] } ] } clientEncryptionOpts-keyVaultClient-required.json000066400000000000000000000006701462766011000375250ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/unified-test-format/invalid{ "description": "clientEncryptionOpts-keyVaultClient-required", "schemaVersion": "1.8", "createEntities": [ { "clientEncryption": { "id": "clientEncryption0", "clientEncryptionOpts": { "keyVaultNamespace": "keyvault.datakeys", "kmsProviders": { "aws": {} } } } } ], "tests": [ { "description": "", "operations": [] } ] } clientEncryptionOpts-keyVaultClient-type.json000066400000000000000000000010221462766011000366560ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/unified-test-format/invalid{ "description": "clientEncryptionOpts-keyVaultClient-type", "schemaVersion": "1.8", "createEntities": [ { "client": { "id": "client0" } }, { "clientEncryption": { "id": "clientEncryption0", "clientEncryptionOpts": { "keyVaultClient": 0, "keyVaultNamespace": "keyvault.datakeys", "kmsProviders": { "aws": {} } } } } ], "tests": [ { "description": "", "operations": [] } ] } clientEncryptionOpts-keyVaultNamespace-required.json000066400000000000000000000007551462766011000402070ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/unified-test-format/invalid{ "description": "clientEncryptionOpts-keyVaultNamespace-required", "schemaVersion": "1.8", "createEntities": [ { "client": { "id": "client0" } }, { "clientEncryption": { "id": "clientEncryption0", "clientEncryptionOpts": { "keyVaultClient": "client0", "kmsProviders": { "aws": {} } } } } ], "tests": [ { "description": "", "operations": [] } ] } clientEncryptionOpts-keyVaultNamespace-type.json000066400000000000000000000010131462766011000373340ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/unified-test-format/invalid{ "description": "clientEncryptionOpts-keyVaultNamespace-type", "schemaVersion": "1.8", "createEntities": [ { "client": { "id": "client0" } }, { "clientEncryption": { "id": "clientEncryption0", "clientEncryptionOpts": { "keyVaultClient": "client0", "keyVaultNamespace": 0, "kmsProviders": { "aws": {} } } } } ], "tests": [ { "description": "", "operations": [] } ] } clientEncryptionOpts-kmsProviders-additionalProperties.json000066400000000000000000000010541462766011000416140ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/unified-test-format/invalid{ "description": "clientEncryptionOpts-kmsProviders-additionalProperties", "schemaVersion": "1.8", "createEntities": [ { "client": { "id": "client0" } }, { "clientEncryption": { "id": "clientEncryption0", "clientEncryptionOpts": { "keyVaultClient": "client0", "keyVaultNamespace": "keyvault.datakeys", "kmsProviders": { "invalid": {} } } } } ], "tests": [ { "description": "", "operations": [] } ] } clientEncryptionOpts-kmsProviders-aws-additionalProperties.json000066400000000000000000000011251462766011000424030ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/unified-test-format/invalid{ "description": "clientEncryptionOpts-kmsProviders-aws-additionalProperties", "schemaVersion": "1.8", "createEntities": [ { "client": { "id": "client0" } }, { "clientEncryption": { "id": "clientEncryption0", "clientEncryptionOpts": { "keyVaultClient": "client0", "keyVaultNamespace": "keyvault.datakeys", "kmsProviders": { "aws": { "invalid": {} } } } } } ], "tests": [ { "description": "", "operations": [] } ] } clientEncryptionOpts-kmsProviders-aws-type.json000066400000000000000000000010331462766011000371750ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/unified-test-format/invalid{ "description": "clientEncryptionOpts-kmsProviders-aws-type", "schemaVersion": "1.8", "createEntities": [ { "client": { "id": "client0" } }, { "clientEncryption": { "id": "clientEncryption0", "clientEncryptionOpts": { "keyVaultClient": "client0", "keyVaultNamespace": "keyvault.datakeys", "kmsProviders": { "aws": 0 } } } } ], "tests": [ { "description": "", "operations": [] } ] } clientEncryptionOpts-kmsProviders-azure-additionalProperties.json000066400000000000000000000011311462766011000427340ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/unified-test-format/invalid{ "description": "clientEncryptionOpts-kmsProviders-azure-additionalProperties", "schemaVersion": "1.8", "createEntities": [ { "client": { "id": "client0" } }, { "clientEncryption": { "id": "clientEncryption0", "clientEncryptionOpts": { "keyVaultClient": "client0", "keyVaultNamespace": "keyvault.datakeys", "kmsProviders": { "azure": { "invalid": {} } } } } } ], "tests": [ { "description": "", "operations": [] } ] } clientEncryptionOpts-kmsProviders-azure-type.json000066400000000000000000000010371462766011000375350ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/unified-test-format/invalid{ "description": "clientEncryptionOpts-kmsProviders-azure-type", "schemaVersion": "1.8", "createEntities": [ { "client": { "id": "client0" } }, { "clientEncryption": { "id": "clientEncryption0", "clientEncryptionOpts": { "keyVaultClient": "client0", "keyVaultNamespace": "keyvault.datakeys", "kmsProviders": { "azure": 0 } } } } ], "tests": [ { "description": "", "operations": [] } ] } clientEncryptionOpts-kmsProviders-gcp-additionalProperties.json000066400000000000000000000011251462766011000423620ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/unified-test-format/invalid{ "description": "clientEncryptionOpts-kmsProviders-gcp-additionalProperties", "schemaVersion": "1.8", "createEntities": [ { "client": { "id": "client0" } }, { "clientEncryption": { "id": "clientEncryption0", "clientEncryptionOpts": { "keyVaultClient": "client0", "keyVaultNamespace": "keyvault.datakeys", "kmsProviders": { "gcp": { "invalid": {} } } } } } ], "tests": [ { "description": "", "operations": [] } ] } clientEncryptionOpts-kmsProviders-gcp-type.json000066400000000000000000000010331462766011000371540ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/unified-test-format/invalid{ "description": "clientEncryptionOpts-kmsProviders-gcp-type", "schemaVersion": "1.8", "createEntities": [ { "client": { "id": "client0" } }, { "clientEncryption": { "id": "clientEncryption0", "clientEncryptionOpts": { "keyVaultClient": "client0", "keyVaultNamespace": "keyvault.datakeys", "kmsProviders": { "gcp": 0 } } } } ], "tests": [ { "description": "", "operations": [] } ] } clientEncryptionOpts-kmsProviders-invalidName.json000066400000000000000000000010751462766011000376610ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/unified-test-format/invalid{ "description": "clientEncryptionOpts-kmsProviders-invalidName", "schemaVersion": "1.18", "createEntities": [ { "client": { "id": "client0" } }, { "clientEncryption": { "id": "clientEncryption0", "clientEncryptionOpts": { "keyVaultClient": "client0", "keyVaultNamespace": "keyvault.datakeys", "kmsProviders": { "aws:name_with_invalid_character*": {} } } } } ], "tests": [ { "description": "", "operations": [] } ] } clientEncryptionOpts-kmsProviders-kmip-additionalProperties.json000066400000000000000000000011271462766011000425530ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/unified-test-format/invalid{ "description": "clientEncryptionOpts-kmsProviders-kmip-additionalProperties", "schemaVersion": "1.8", "createEntities": [ { "client": { "id": "client0" } }, { "clientEncryption": { "id": "clientEncryption0", "clientEncryptionOpts": { "keyVaultClient": "client0", "keyVaultNamespace": "keyvault.datakeys", "kmsProviders": { "kmip": { "invalid": {} } } } } } ], "tests": [ { "description": "", "operations": [] } ] } clientEncryptionOpts-kmsProviders-kmip-type.json000066400000000000000000000010351462766011000373450ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/unified-test-format/invalid{ "description": "clientEncryptionOpts-kmsProviders-kmip-type", "schemaVersion": "1.8", "createEntities": [ { "client": { "id": "client0" } }, { "clientEncryption": { "id": "clientEncryption0", "clientEncryptionOpts": { "keyVaultClient": "client0", "keyVaultNamespace": "keyvault.datakeys", "kmsProviders": { "kmip": 0 } } } } ], "tests": [ { "description": "", "operations": [] } ] } clientEncryptionOpts-kmsProviders-local-additionalProperties.json000066400000000000000000000011311462766011000427000ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/unified-test-format/invalid{ "description": "clientEncryptionOpts-kmsProviders-local-additionalProperties", "schemaVersion": "1.8", "createEntities": [ { "client": { "id": "client0" } }, { "clientEncryption": { "id": "clientEncryption0", "clientEncryptionOpts": { "keyVaultClient": "client0", "keyVaultNamespace": "keyvault.datakeys", "kmsProviders": { "local": { "invalid": {} } } } } } ], "tests": [ { "description": "", "operations": [] } ] } clientEncryptionOpts-kmsProviders-local-type.json000066400000000000000000000010371462766011000375010ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/unified-test-format/invalid{ "description": "clientEncryptionOpts-kmsProviders-local-type", "schemaVersion": "1.8", "createEntities": [ { "client": { "id": "client0" } }, { "clientEncryption": { "id": "clientEncryption0", "clientEncryptionOpts": { "keyVaultClient": "client0", "keyVaultNamespace": "keyvault.datakeys", "kmsProviders": { "local": 0 } } } } ], "tests": [ { "description": "", "operations": [] } ] } clientEncryptionOpts-kmsProviders-required.json000066400000000000000000000007351462766011000372540ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/unified-test-format/invalid{ "description": "clientEncryptionOpts-kmsProviders-required", "schemaVersion": "1.8", "createEntities": [ { "client": { "id": "client0" } }, { "clientEncryption": { "id": "clientEncryption0", "clientEncryptionOpts": { "keyVaultClient": "client0", "keyVaultNamespace": "keyvault.datakeys" } } } ], "tests": [ { "description": "", "operations": [] } ] } clientEncryptionOpts-kmsProviders-type.json000066400000000000000000000007661462766011000364210ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/unified-test-format/invalid{ "description": "clientEncryptionOpts-kmsProviders-type", "schemaVersion": "1.8", "createEntities": [ { "client": { "id": "client0" } }, { "clientEncryption": { "id": "clientEncryption0", "clientEncryptionOpts": { "keyVaultClient": "client0", "keyVaultNamespace": "keyvault.datakeys", "kmsProviders": 0 } } } ], "tests": [ { "description": "", "operations": [] } ] } clientEncryptionOpts-tlsOptions_not_supported.json000066400000000000000000000010731462766011000401050ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/unified-test-format/invalid{ "description": "clientEncryptionOpts-tlsOptions_not_supported", "schemaVersion": "1.8", "createEntities": [ { "client": { "id": "client0" } }, { "clientEncryption": { "id": "clientEncryption0", "clientEncryptionOpts": { "keyVaultClient": "client0", "keyVaultNamespace": "keyvault.datakeys", "kmsProviders": { "aws": {} }, "tlsOptions": {} } } } ], "tests": [ { "description": "", "operations": [] } ] } collectionData-additionalProperties.json000066400000000000000000000012151462766011000356530ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/unified-test-format/invalid{ "description": "collectionData-additionalProperties", "schemaVersion": "1.0", "createEntities": [ { "client": { "id": "client0" } }, { "database": { "id": "database0", "client": "client0", "databaseName": "foo" } }, { "collection": { "id": "collection0", "database": "database0", "collectionName": "foo" } } ], "initialData": [ { "collectionName": "foo", "databaseName": "foo", "documents": [], "foo": 0 } ], "tests": [ { "description": "foo", "operations": [] } ] } collectionData-collectionName-required.json000066400000000000000000000011411462766011000362360ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/unified-test-format/invalid{ "description": "collectionData-collectionName-required", "schemaVersion": "1.0", "createEntities": [ { "client": { "id": "client0" } }, { "database": { "id": "database0", "client": "client0", "databaseName": "foo" } }, { "collection": { "id": "collection0", "database": "database0", "collectionName": "foo" } } ], "initialData": [ { "databaseName": "foo", "documents": [] } ], "tests": [ { "description": "foo", "operations": [] } ] } collectionData-collectionName-type.json000066400000000000000000000011701462766011000354010ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/unified-test-format/invalid{ "description": "collectionData-collectionName-type", "schemaVersion": "1.0", "createEntities": [ { "client": { "id": "client0" } }, { "database": { "id": "database0", "client": "client0", "databaseName": "foo" } }, { "collection": { "id": "collection0", "database": "database0", "collectionName": "foo" } } ], "initialData": [ { "collectionName": 0, "databaseName": "foo", "documents": [] } ], "tests": [ { "description": "foo", "operations": [] } ] } collectionData-createOptions-type.json000066400000000000000000000012251462766011000352650ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/unified-test-format/invalid{ "description": "collectionData-createOptions-type", "schemaVersion": "1.9", "createEntities": [ { "client": { "id": "client0" } }, { "database": { "id": "database0", "client": "client0", "databaseName": "foo" } }, { "collection": { "id": "collection0", "database": "database0", "collectionName": "foo" } } ], "initialData": [ { "collectionName": "foo", "databaseName": "foo", "createOptions": 0, "documents": [] } ], "tests": [ { "description": "foo", "operations": [] } ] } collectionData-databaseName-required.json000066400000000000000000000011411462766011000356470ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/unified-test-format/invalid{ "description": "collectionData-databaseName-required", "schemaVersion": "1.0", "createEntities": [ { "client": { "id": "client0" } }, { "database": { "id": "database0", "client": "client0", "databaseName": "foo" } }, { "collection": { "id": "collection0", "database": "database0", "collectionName": "foo" } } ], "initialData": [ { "collectionName": "foo", "documents": [] } ], "tests": [ { "description": "foo", "operations": [] } ] } collectionData-databaseName-type.json000066400000000000000000000011661462766011000350170ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/unified-test-format/invalid{ "description": "collectionData-databaseName-type", "schemaVersion": "1.0", "createEntities": [ { "client": { "id": "client0" } }, { "database": { "id": "database0", "client": "client0", "databaseName": "foo" } }, { "collection": { "id": "collection0", "database": "database0", "collectionName": "foo" } } ], "initialData": [ { "collectionName": "foo", "databaseName": 0, "documents": [] } ], "tests": [ { "description": "foo", "operations": [] } ] } collectionData-documents-items.json000066400000000000000000000012111462766011000346020ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/unified-test-format/invalid{ "description": "collectionData-documents-items", "schemaVersion": "1.0", "createEntities": [ { "client": { "id": "client0" } }, { "database": { "id": "database0", "client": "client0", "databaseName": "foo" } }, { "collection": { "id": "collection0", "database": "database0", "collectionName": "foo" } } ], "initialData": [ { "collectionName": "foo", "databaseName": "foo", "documents": [ 0 ] } ], "tests": [ { "description": "foo", "operations": [] } ] } collectionData-documents-required.json000066400000000000000000000011441462766011000353060ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/unified-test-format/invalid{ "description": "collectionData-documents-required", "schemaVersion": "1.0", "createEntities": [ { "client": { "id": "client0" } }, { "database": { "id": "database0", "client": "client0", "databaseName": "foo" } }, { "collection": { "id": "collection0", "database": "database0", "collectionName": "foo" } } ], "initialData": [ { "collectionName": "foo", "databaseName": "foo" } ], "tests": [ { "description": "foo", "operations": [] } ] } collectionData-documents-type.json000066400000000000000000000011661462766011000344530ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/unified-test-format/invalid{ "description": "collectionData-documents-type", "schemaVersion": "1.0", "createEntities": [ { "client": { "id": "client0" } }, { "database": { "id": "database0", "client": "client0", "databaseName": "foo" } }, { "collection": { "id": "collection0", "database": "database0", "collectionName": "foo" } } ], "initialData": [ { "collectionName": "foo", "databaseName": "foo", "documents": 0 } ], "tests": [ { "description": "foo", "operations": [] } ] } collectionOrDatabaseOptions-additionalProperties.json000066400000000000000000000007061462766011000403670ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/unified-test-format/invalid{ "description": "collectionOrDatabaseOptions-additionalProperties", "schemaVersion": "1.0", "createEntities": [ { "client": { "id": "client0" } }, { "database": { "id": "database0", "client": "client0", "databaseName": "foo", "databaseOptions": { "foo": 0 } } } ], "tests": [ { "description": "foo", "operations": [] } ] } collectionOrDatabaseOptions-readConcern-type.json000066400000000000000000000007121462766011000374010ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/unified-test-format/invalid{ "description": "collectionOrDatabaseOptions-readConcern-type", "schemaVersion": "1.0", "createEntities": [ { "client": { "id": "client0" } }, { "database": { "id": "database0", "client": "client0", "databaseName": "foo", "databaseOptions": { "readConcern": 0 } } } ], "tests": [ { "description": "foo", "operations": [] } ] } collectionOrDatabaseOptions-readPreference-type.json000066400000000000000000000007201462766011000400670ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/unified-test-format/invalid{ "description": "collectionOrDatabaseOptions-readPreference-type", "schemaVersion": "1.0", "createEntities": [ { "client": { "id": "client0" } }, { "database": { "id": "database0", "client": "client0", "databaseName": "foo", "databaseOptions": { "readPreference": 0 } } } ], "tests": [ { "description": "foo", "operations": [] } ] } collectionOrDatabaseOptions-timeoutMS-type.json000066400000000000000000000007101462766011000371020ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/unified-test-format/invalid{ "description": "collectionOrDatabaseOptions-timeoutMS-type", "schemaVersion": "1.9", "createEntities": [ { "client": { "id": "client0" } }, { "database": { "id": "database0", "client": "client0", "databaseName": "foo", "databaseOptions": { "timeoutMS": 4.5 } } } ], "tests": [ { "description": "foo", "operations": [] } ] } collectionOrDatabaseOptions-writeConcern-type.json000066400000000000000000000007141462766011000376220ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/unified-test-format/invalid{ "description": "collectionOrDatabaseOptions-writeConcern-type", "schemaVersion": "1.0", "createEntities": [ { "client": { "id": "client0" } }, { "database": { "id": "database0", "client": "client0", "databaseName": "foo", "databaseOptions": { "writeConcern": 0 } } } ], "tests": [ { "description": "foo", "operations": [] } ] } mongodb-mongo-python-driver-509e9b7/test/unified-test-format/invalid/createEntities-items.json000066400000000000000000000002701462766011000327110ustar00rootroot00000000000000{ "description": "createEntities-items", "schemaVersion": "1.0", "createEntities": [ 0 ], "tests": [ { "description": "foo", "operations": [] } ] } mongodb-mongo-python-driver-509e9b7/test/unified-test-format/invalid/createEntities-minItems.json000066400000000000000000000002621462766011000333560ustar00rootroot00000000000000{ "description": "createEntities-minItems", "schemaVersion": "1.0", "createEntities": [], "tests": [ { "description": "foo", "operations": [] } ] } mongodb-mongo-python-driver-509e9b7/test/unified-test-format/invalid/createEntities-type.json000066400000000000000000000002551462766011000325540ustar00rootroot00000000000000{ "description": "createEntities-type", "schemaVersion": "1.0", "createEntities": 0, "tests": [ { "description": "foo", "operations": [] } ] } mongodb-mongo-python-driver-509e9b7/test/unified-test-format/invalid/description-required.json000066400000000000000000000001561462766011000327660ustar00rootroot00000000000000{ "schemaVersion": "1.0", "tests": [ { "description": "foo", "operations": [] } ] } entity-additionalProperties.json000066400000000000000000000003241462766011000342420ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/unified-test-format/invalid{ "description": "entity-additionalProperties", "schemaVersion": "1.0", "createEntities": [ { "foo": 0 } ], "tests": [ { "description": "foo", "operations": [] } ] } entity-bucket-additionalProperties.json000066400000000000000000000007571462766011000355270ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/unified-test-format/invalid{ "description": "entity-bucket-additionalProperties", "schemaVersion": "1.0", "createEntities": [ { "client": { "id": "client0" } }, { "database": { "id": "database0", "client": "client0", "databaseName": "foo" } }, { "bucket": { "id": "bucket0", "database": "database0", "foo": 0 } } ], "tests": [ { "description": "foo", "operations": [] } ] } entity-bucket-bucketOptions-type.json000066400000000000000000000007671462766011000351530ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/unified-test-format/invalid{ "description": "entity-bucket-bucketOptions-type", "schemaVersion": "1.0", "createEntities": [ { "client": { "id": "client0" } }, { "database": { "id": "database0", "client": "client0", "databaseName": "foo" } }, { "bucket": { "id": "bucket0", "database": "database0", "bucketOptions": 0 } } ], "tests": [ { "description": "foo", "operations": [] } ] } entity-bucket-database-required.json000066400000000000000000000006711462766011000347170ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/unified-test-format/invalid{ "description": "entity-bucket-database-required", "schemaVersion": "1.0", "createEntities": [ { "client": { "id": "client0" } }, { "database": { "id": "database0", "client": "client0", "databaseName": "foo" } }, { "bucket": { "id": "bucket0" } } ], "tests": [ { "description": "foo", "operations": [] } ] } entity-bucket-database-type.json000066400000000000000000000007141462766011000340560ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/unified-test-format/invalid{ "description": "entity-bucket-database-type", "schemaVersion": "1.0", "createEntities": [ { "client": { "id": "client0" } }, { "database": { "id": "database0", "client": "client0", "databaseName": "foo" } }, { "bucket": { "id": "bucket0", "database": 0 } } ], "tests": [ { "description": "foo", "operations": [] } ] } mongodb-mongo-python-driver-509e9b7/test/unified-test-format/invalid/entity-bucket-id-required.json000066400000000000000000000006731462766011000336300ustar00rootroot00000000000000{ "description": "entity-bucket-id-required", "schemaVersion": "1.0", "createEntities": [ { "client": { "id": "client0" } }, { "database": { "id": "database0", "client": "client0", "databaseName": "foo" } }, { "bucket": { "database": "database0" } } ], "tests": [ { "description": "foo", "operations": [] } ] } mongodb-mongo-python-driver-509e9b7/test/unified-test-format/invalid/entity-bucket-id-type.json000066400000000000000000000007101462766011000327610ustar00rootroot00000000000000{ "description": "entity-bucket-id-type", "schemaVersion": "1.0", "createEntities": [ { "client": { "id": "client0" } }, { "database": { "id": "database0", "client": "client0", "databaseName": "foo" } }, { "bucket": { "id": 0, "database": "database0" } } ], "tests": [ { "description": "foo", "operations": [] } ] } entity-client-additionalProperties.json000066400000000000000000000004201462766011000355130ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/unified-test-format/invalid{ "description": "entity-client-additionalProperties", "schemaVersion": "1.0", "createEntities": [ { "client": { "id": "client0", "foo": 0 } } ], "tests": [ { "description": "foo", "operations": [] } ] } mongodb-mongo-python-driver-509e9b7/test/unified-test-format/invalid/entity-client-id-required.json000066400000000000000000000003261462766011000336240ustar00rootroot00000000000000{ "description": "entity-client-id-required", "schemaVersion": "1.0", "createEntities": [ { "client": {} } ], "tests": [ { "description": "foo", "operations": [] } ] } mongodb-mongo-python-driver-509e9b7/test/unified-test-format/invalid/entity-client-id-type.json000066400000000000000000000003511462766011000327630ustar00rootroot00000000000000{ "description": "entity-client-id-type", "schemaVersion": "1.0", "createEntities": [ { "client": { "id": 0 } } ], "tests": [ { "description": "foo", "operations": [] } ] } entity-client-ignoreCommandMonitoringEvents-items.json000066400000000000000000000005171462766011000404710ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/unified-test-format/invalid{ "description": "entity-client-ignoreCommandMonitoringEvents-items", "schemaVersion": "1.0", "createEntities": [ { "client": { "id": "client0", "ignoreCommandMonitoringEvents": [ 0 ] } } ], "tests": [ { "description": "foo", "operations": [] } ] } entity-client-ignoreCommandMonitoringEvents-minItems.json000066400000000000000000000004751462766011000411400ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/unified-test-format/invalid{ "description": "entity-client-ignoreCommandMonitoringEvents-minItems", "schemaVersion": "1.0", "createEntities": [ { "client": { "id": "client0", "ignoreCommandMonitoringEvents": [] } } ], "tests": [ { "description": "foo", "operations": [] } ] } entity-client-ignoreCommandMonitoringEvents-type.json000066400000000000000000000004701462766011000403270ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/unified-test-format/invalid{ "description": "entity-client-ignoreCommandMonitoringEvents-type", "schemaVersion": "1.0", "createEntities": [ { "client": { "id": "client0", "ignoreCommandMonitoringEvents": 0 } } ], "tests": [ { "description": "foo", "operations": [] } ] } entity-client-observeEvents-enum.json000066400000000000000000000004621462766011000351300ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/unified-test-format/invalid{ "description": "entity-client-observeEvents-enum", "schemaVersion": "1.0", "createEntities": [ { "client": { "id": "client0", "observeEvents": [ "foo" ] } } ], "tests": [ { "description": "foo", "operations": [] } ] } entity-client-observeEvents-items.json000066400000000000000000000004571462766011000353110ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/unified-test-format/invalid{ "description": "entity-client-observeEvents-items", "schemaVersion": "1.0", "createEntities": [ { "client": { "id": "client0", "observeEvents": [ 0 ] } } ], "tests": [ { "description": "foo", "operations": [] } ] } entity-client-observeEvents-minItems.json000066400000000000000000000004351462766011000357510ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/unified-test-format/invalid{ "description": "entity-client-observeEvents-minItems", "schemaVersion": "1.0", "createEntities": [ { "client": { "id": "client0", "observeEvents": [] } } ], "tests": [ { "description": "foo", "operations": [] } ] } entity-client-observeEvents-type.json000066400000000000000000000004301462766011000351400ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/unified-test-format/invalid{ "description": "entity-client-observeEvents-type", "schemaVersion": "1.0", "createEntities": [ { "client": { "id": "client0", "observeEvents": 0 } } ], "tests": [ { "description": "foo", "operations": [] } ] } entity-client-observeLogMessages-minProperties.json000066400000000000000000000004551462766011000377730ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/unified-test-format/invalid{ "description": "entity-client-observeLogMessages-minProperties", "schemaVersion": "1.13", "createEntities": [ { "client": { "id": "client0", "observeLogMessages": {} } } ], "tests": [ { "description": "foo", "operations": [] } ] } entity-client-observeLogMessages-property-type.json000066400000000000000000000005161462766011000377740ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/unified-test-format/invalid{ "description": "entity-client-observeLogMessages-property-type", "schemaVersion": "1.13", "createEntities": [ { "client": { "id": "client0", "observeLogMessages": { "command": {} } } } ], "tests": [ { "description": "foo", "operations": [] } ] } entity-client-observeLogMessages-property-value.json000066400000000000000000000005321462766011000401250ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/unified-test-format/invalid{ "description": "entity-client-observeLogMessages-property-type", "schemaVersion": "1.13", "createEntities": [ { "client": { "id": "client0", "observeLogMessages": { "command": "notALogLevel" } } } ], "tests": [ { "description": "foo", "operations": [] } ] } entity-client-observeLogMessages-type.json000066400000000000000000000004431462766011000361110ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/unified-test-format/invalid{ "description": "entity-client-observeLogMessages-type", "schemaVersion": "1.13", "createEntities": [ { "client": { "id": "client0", "observeLogMessages": 0 } } ], "tests": [ { "description": "foo", "operations": [] } ] } entity-client-observeSensitiveCommands-type.json000066400000000000000000000004561462766011000373370ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/unified-test-format/invalid{ "description": "entity-client-observeSensitiveCommands-type", "schemaVersion": "1.5", "createEntities": [ { "client": { "id": "client0", "observeSensitiveCommands": 0 } } ], "tests": [ { "description": "foo", "operations": [] } ] } entity-client-serverApi-deprecationErrors-type.json000066400000000000000000000005351462766011000377440ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/unified-test-format/invalid{ "description": "entity-client-serverApi-version-type", "schemaVersion": "1.1", "createEntities": [ { "client": { "id": "client0", "serverApi": { "version": "1", "deprecationErrors": 0 } } } ], "tests": [ { "description": "foo", "operations": [] } ] } entity-client-serverApi-strict-type.json000066400000000000000000000005221462766011000355560ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/unified-test-format/invalid{ "description": "entity-client-serverApi-version-type", "schemaVersion": "1.1", "createEntities": [ { "client": { "id": "client0", "serverApi": { "version": "1", "strict": 0 } } } ], "tests": [ { "description": "foo", "operations": [] } ] } entity-client-serverApi-type.json000066400000000000000000000004201462766011000342450ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/unified-test-format/invalid{ "description": "entity-client-serverApi-type", "schemaVersion": "1.1", "createEntities": [ { "client": { "id": "client0", "serverApi": 0 } } ], "tests": [ { "description": "foo", "operations": [] } ] } entity-client-serverApi-version-required.json000066400000000000000000000004351462766011000365750ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/unified-test-format/invalid{ "description": "entity-client-serverApi-version-required", "schemaVersion": "1.1", "createEntities": [ { "client": { "id": "client0", "serverApi": {} } } ], "tests": [ { "description": "foo", "operations": [] } ] } entity-client-serverApi-version-type.json000066400000000000000000000004711462766011000357360ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/unified-test-format/invalid{ "description": "entity-client-serverApi-version-type", "schemaVersion": "1.1", "createEntities": [ { "client": { "id": "client0", "serverApi": { "version": 0 } } } ], "tests": [ { "description": "foo", "operations": [] } ] } entity-client-storeEventsAsEntities-minItems.json000066400000000000000000000004551462766011000374330ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/unified-test-format/invalid{ "description": "entity-client-storeEventsAsEntities-minItems", "schemaVersion": "1.2", "createEntities": [ { "client": { "id": "client0", "storeEventsAsEntities": [] } } ], "tests": [ { "description": "foo", "operations": [] } ] } entity-client-storeEventsAsEntities-type.json000066400000000000000000000004501462766011000366220ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/unified-test-format/invalid{ "description": "entity-client-storeEventsAsEntities-type", "schemaVersion": "1.2", "createEntities": [ { "client": { "id": "client0", "storeEventsAsEntities": 0 } } ], "tests": [ { "description": "foo", "operations": [] } ] } entity-client-uriOptions-type.json000066400000000000000000000004221462766011000344620ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/unified-test-format/invalid{ "description": "entity-client-uriOptions-type", "schemaVersion": "1.0", "createEntities": [ { "client": { "id": "client0", "uriOptions": 0 } } ], "tests": [ { "description": "foo", "operations": [] } ] } entity-client-useMultipleMongoses-type.json000066400000000000000000000004441462766011000363360ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/unified-test-format/invalid{ "description": "entity-client-useMultipleMongoses-type", "schemaVersion": "1.0", "createEntities": [ { "client": { "id": "client0", "useMultipleMongoses": 0 } } ], "tests": [ { "description": "foo", "operations": [] } ] } entity-clientEncryption-additionalProperties.json000066400000000000000000000010651462766011000375740ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/unified-test-format/invalid{ "description": "entity-clientEncryption-additionalProperties", "schemaVersion": "1.8", "createEntities": [ { "client": { "id": "client0" } }, { "clientEncryption": { "id": "clientEncryption0", "clientEncryptionOpts": { "keyVaultClient": "client0", "keyVaultNamespace": "keyvault.datakeys", "kmsProviders": { "aws": {} } }, "invalid": {} } } ], "tests": [ { "description": "", "operations": [] } ] } entity-clientEncryption-clientEncryptionOpts-required.json000066400000000000000000000004421462766011000414220ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/unified-test-format/invalid{ "description": "entity-clientEncryption-clientEncryptionOpts-required", "schemaVersion": "1.8", "createEntities": [ { "clientEncryption": { "id": "clientEncryption0" } } ], "tests": [ { "description": "", "operations": [] } ] } entity-clientEncryption-clientEncryptionOpts-type.json000066400000000000000000000005011462766011000405570ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/unified-test-format/invalid{ "description": "entity-clientEncryption-clientEncryptionOpts-type", "schemaVersion": "1.8", "createEntities": [ { "clientEncryption": { "id": "clientEncryption0", "clientEncryptionOpts": 0 } } ], "tests": [ { "description": "", "operations": [] } ] } entity-clientEncryption-id-required.json000066400000000000000000000007621462766011000356240ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/unified-test-format/invalid{ "description": "entity-clientEncryption-id-required", "schemaVersion": "1.8", "createEntities": [ { "client": { "id": "client0" } }, { "clientEncryption": { "clientEncryptionOpts": { "keyVaultClient": "client0", "keyVaultNamespace": "keyvault.datakeys", "kmsProviders": { "aws": {} } } } } ], "tests": [ { "description": "", "operations": [] } ] } entity-clientEncryption-id-type.json000066400000000000000000000007771462766011000347730ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/unified-test-format/invalid{ "description": "entity-clientEncryption-id-type", "schemaVersion": "1.8", "createEntities": [ { "client": { "id": "client0" } }, { "clientEncryption": { "id": 0, "clientEncryptionOpts": { "keyVaultClient": "client0", "keyVaultNamespace": "keyvault.datakeys", "kmsProviders": { "aws": {} } } } } ], "tests": [ { "description": "", "operations": [] } ] } entity-collection-additionalProperties.json000066400000000000000000000010341462766011000363720ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/unified-test-format/invalid{ "description": "entity-collection-additionalProperties", "schemaVersion": "1.0", "createEntities": [ { "client": { "id": "client0" } }, { "database": { "id": "database0", "client": "client0", "databaseName": "foo" } }, { "collection": { "id": "collection0", "database": "database0", "collectionName": "foo", "foo": 0 } } ], "tests": [ { "description": "foo", "operations": [] } ] } entity-collection-collectionName-required.json000066400000000000000000000007541462766011000367670ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/unified-test-format/invalid{ "description": "entity-collection-collectionName-required", "schemaVersion": "1.0", "createEntities": [ { "client": { "id": "client0" } }, { "database": { "id": "database0", "client": "client0", "databaseName": "foo" } }, { "collection": { "id": "collection0", "database": "database0" } } ], "tests": [ { "description": "foo", "operations": [] } ] } entity-collection-collectionName-type.json000066400000000000000000000010051462766011000361160ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/unified-test-format/invalid{ "description": "entity-collection-collectionName-type", "schemaVersion": "1.0", "createEntities": [ { "client": { "id": "client0" } }, { "database": { "id": "database0", "client": "client0", "databaseName": "foo" } }, { "collection": { "id": "collection0", "database": "database0", "collectionName": 0 } } ], "tests": [ { "description": "foo", "operations": [] } ] } entity-collection-collectionOptions-type.json000066400000000000000000000010541462766011000366750ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/unified-test-format/invalid{ "description": "entity-collection-collectionOptions-type", "schemaVersion": "1.0", "createEntities": [ { "client": { "id": "client0" } }, { "database": { "id": "database0", "client": "client0", "databaseName": "foo" } }, { "collection": { "id": "collection0", "database": "database0", "collectionName": "foo", "collectionOptions": 0 } } ], "tests": [ { "description": "foo", "operations": [] } ] } entity-collection-database-required.json000066400000000000000000000007461462766011000356000ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/unified-test-format/invalid{ "description": "entity-collection-database-required", "schemaVersion": "1.0", "createEntities": [ { "client": { "id": "client0" } }, { "database": { "id": "database0", "client": "client0", "databaseName": "foo" } }, { "collection": { "id": "collection0", "collectionName": "foo" } } ], "tests": [ { "description": "foo", "operations": [] } ] } entity-collection-database-type.json000066400000000000000000000007711462766011000347370ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/unified-test-format/invalid{ "description": "entity-collection-database-type", "schemaVersion": "1.0", "createEntities": [ { "client": { "id": "client0" } }, { "database": { "id": "database0", "client": "client0", "databaseName": "foo" } }, { "collection": { "id": "collection0", "database": 0, "collectionName": "foo" } } ], "tests": [ { "description": "foo", "operations": [] } ] } entity-collection-id-required.json000066400000000000000000000007441462766011000344260ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/unified-test-format/invalid{ "description": "entity-collection-id-required", "schemaVersion": "1.0", "createEntities": [ { "client": { "id": "client0" } }, { "database": { "id": "database0", "client": "client0", "databaseName": "foo" } }, { "collection": { "database": "database0", "collectionName": "foo" } } ], "tests": [ { "description": "foo", "operations": [] } ] } mongodb-mongo-python-driver-509e9b7/test/unified-test-format/invalid/entity-collection-id-type.json000066400000000000000000000007611462766011000336450ustar00rootroot00000000000000{ "description": "entity-collection-id-type", "schemaVersion": "1.0", "createEntities": [ { "client": { "id": "client0" } }, { "database": { "id": "database0", "client": "client0", "databaseName": "foo" } }, { "collection": { "id": 0, "database": "database0", "collectionName": "foo" } } ], "tests": [ { "description": "foo", "operations": [] } ] } entity-database-additionalProperties.json000066400000000000000000000006211462766011000360040ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/unified-test-format/invalid{ "description": "entity-database-additionalProperties", "schemaVersion": "1.0", "createEntities": [ { "client": { "id": "client0" } }, { "database": { "id": "database0", "client": "client0", "databaseName": "foo", "foo": 0 } } ], "tests": [ { "description": "foo", "operations": [] } ] } entity-database-client-required.json000066400000000000000000000005351462766011000347170ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/unified-test-format/invalid{ "description": "entity-database-client-required", "schemaVersion": "1.0", "createEntities": [ { "client": { "id": "client0" } }, { "database": { "id": "database0", "databaseName": "foo" } } ], "tests": [ { "description": "foo", "operations": [] } ] } entity-database-client-type.json000066400000000000000000000005561462766011000340630ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/unified-test-format/invalid{ "description": "entity-database-client-type", "schemaVersion": "1.0", "createEntities": [ { "client": { "id": "client0" } }, { "database": { "id": "database0", "client": 0, "databaseName": "foo" } } ], "tests": [ { "description": "foo", "operations": [] } ] } entity-database-databaseName-required.json000066400000000000000000000005411462766011000360030ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/unified-test-format/invalid{ "description": "entity-database-databaseName-required", "schemaVersion": "1.0", "createEntities": [ { "client": { "id": "client0" } }, { "database": { "id": "database0", "client": "client0" } } ], "tests": [ { "description": "foo", "operations": [] } ] } entity-database-databaseName-type.json000066400000000000000000000005701462766011000351460ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/unified-test-format/invalid{ "description": "entity-database-databaseName-type", "schemaVersion": "1.0", "createEntities": [ { "client": { "id": "client0" } }, { "database": { "id": "database0", "client": "client0", "databaseName": 0 } } ], "tests": [ { "description": "foo", "operations": [] } ] } entity-database-databaseOptions-type.json000066400000000000000000000006351462766011000357230ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/unified-test-format/invalid{ "description": "entity-database-databaseOptions-type", "schemaVersion": "1.0", "createEntities": [ { "client": { "id": "client0" } }, { "database": { "id": "database0", "client": "client0", "databaseName": "foo", "databaseOptions": 0 } } ], "tests": [ { "description": "foo", "operations": [] } ] } entity-database-id-required.json000066400000000000000000000005331462766011000340330ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/unified-test-format/invalid{ "description": "entity-database-id-required", "schemaVersion": "1.0", "createEntities": [ { "client": { "id": "client0" } }, { "database": { "client": "client0", "databaseName": "foo" } } ], "tests": [ { "description": "foo", "operations": [] } ] } mongodb-mongo-python-driver-509e9b7/test/unified-test-format/invalid/entity-database-id-type.json000066400000000000000000000005501462766011000332520ustar00rootroot00000000000000{ "description": "entity-database-id-type", "schemaVersion": "1.0", "createEntities": [ { "client": { "id": "client0" } }, { "database": { "id": 0, "client": "client0", "databaseName": "foo" } } ], "tests": [ { "description": "foo", "operations": [] } ] } mongodb-mongo-python-driver-509e9b7/test/unified-test-format/invalid/entity-maxProperties.json000066400000000000000000000005431462766011000330010ustar00rootroot00000000000000{ "description": "entity-maxProperties", "schemaVersion": "1.0", "createEntities": [ { "client": { "id": "client0" }, "database": { "id": "database0", "client": "client0", "databaseName": "foo" } } ], "tests": [ { "description": "foo", "operations": [] } ] } mongodb-mongo-python-driver-509e9b7/test/unified-test-format/invalid/entity-minProperties.json000066400000000000000000000002711462766011000327750ustar00rootroot00000000000000{ "description": "entity-minProperties", "schemaVersion": "1.0", "createEntities": [ {} ], "tests": [ { "description": "foo", "operations": [] } ] } entity-session-additionalProperties.json000066400000000000000000000005571462766011000357330ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/unified-test-format/invalid{ "description": "entity-session-additionalProperties", "schemaVersion": "1.0", "createEntities": [ { "client": { "id": "client0" } }, { "session": { "id": "session0", "client": "client0", "foo": 0 } } ], "tests": [ { "description": "foo", "operations": [] } ] } entity-session-client-required.json000066400000000000000000000004731462766011000346370ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/unified-test-format/invalid{ "description": "entity-session-client-required", "schemaVersion": "1.0", "createEntities": [ { "client": { "id": "client0" } }, { "session": { "id": "session0" } } ], "tests": [ { "description": "foo", "operations": [] } ] } mongodb-mongo-python-driver-509e9b7/test/unified-test-format/invalid/entity-session-client-type.json000066400000000000000000000005141462766011000340530ustar00rootroot00000000000000{ "description": "entity-session-client-type", "schemaVersion": "1.0", "createEntities": [ { "client": { "id": "client0" } }, { "session": { "id": "session0", "client": 0 } } ], "tests": [ { "description": "foo", "operations": [] } ] } mongodb-mongo-python-driver-509e9b7/test/unified-test-format/invalid/entity-session-id-required.json000066400000000000000000000004721462766011000340330ustar00rootroot00000000000000{ "description": "entity-session-id-required", "schemaVersion": "1.0", "createEntities": [ { "client": { "id": "client0" } }, { "session": { "client": "client0" } } ], "tests": [ { "description": "foo", "operations": [] } ] } mongodb-mongo-python-driver-509e9b7/test/unified-test-format/invalid/entity-session-id-type.json000066400000000000000000000005071462766011000331730ustar00rootroot00000000000000{ "description": "entity-session-id-type", "schemaVersion": "1.0", "createEntities": [ { "client": { "id": "client0" } }, { "session": { "id": 0, "client": "client0" } } ], "tests": [ { "description": "foo", "operations": [] } ] } entity-session-sessionOptions-type.json000066400000000000000000000005711462766011000355600ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/unified-test-format/invalid{ "description": "entity-session-sessionOptions-type", "schemaVersion": "1.0", "createEntities": [ { "client": { "id": "client0" } }, { "session": { "id": "session0", "client": "client0", "sessionOptions": 0 } } ], "tests": [ { "description": "foo", "operations": [] } ] } entity-stream-additionalProperties.json000066400000000000000000000004521462766011000355350ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/unified-test-format/invalid{ "description": "entity-stream-additionalProperties", "schemaVersion": "1.0", "createEntities": [ { "stream": { "id": "stream0", "hexBytes": "FF", "foo": 0 } } ], "tests": [ { "description": "foo", "operations": [] } ] } entity-stream-hexBytes-pattern.json000066400000000000000000000004251462766011000346160ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/unified-test-format/invalid{ "description": "entity-stream-hexBytes-pattern", "schemaVersion": "1.0", "createEntities": [ { "stream": { "id": "stream0", "hexBytes": "FFF" } } ], "tests": [ { "description": "foo", "operations": [] } ] } entity-stream-hexBytes-required.json000066400000000000000000000003731462766011000347630ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/unified-test-format/invalid{ "description": "entity-stream-hexBytes-required", "schemaVersion": "1.0", "createEntities": [ { "stream": { "id": "stream0" } } ], "tests": [ { "description": "foo", "operations": [] } ] } entity-stream-hexBytes-type.json000066400000000000000000000004161462766011000341220ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/unified-test-format/invalid{ "description": "entity-stream-hexBytes-type", "schemaVersion": "1.0", "createEntities": [ { "stream": { "id": "stream0", "hexBytes": 0 } } ], "tests": [ { "description": "foo", "operations": [] } ] } mongodb-mongo-python-driver-509e9b7/test/unified-test-format/invalid/entity-stream-id-required.json000066400000000000000000000003661462766011000336450ustar00rootroot00000000000000{ "description": "entity-stream-id-required", "schemaVersion": "1.0", "createEntities": [ { "stream": { "hexBytes": "FF" } } ], "tests": [ { "description": "foo", "operations": [] } ] } mongodb-mongo-python-driver-509e9b7/test/unified-test-format/invalid/entity-stream-id-type.json000066400000000000000000000004031462766011000327760ustar00rootroot00000000000000{ "description": "entity-stream-id-type", "schemaVersion": "1.0", "createEntities": [ { "stream": { "id": 0, "hexBytes": "FF" } } ], "tests": [ { "description": "foo", "operations": [] } ] } entity-thread-additionalProperties.json000066400000000000000000000004251462766011000355110ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/unified-test-format/invalid{ "description": "entity-thread-additionalProperties", "schemaVersion": "1.10", "createEntities": [ { "thread": { "id": "thread0", "foo": "bar" } } ], "tests": [ { "description": "foo", "operations": [] } ] } mongodb-mongo-python-driver-509e9b7/test/unified-test-format/invalid/entity-thread-id-required.json000066400000000000000000000003271462766011000336160ustar00rootroot00000000000000{ "description": "entity-thread-id-required", "schemaVersion": "1.10", "createEntities": [ { "thread": {} } ], "tests": [ { "description": "foo", "operations": [] } ] } mongodb-mongo-python-driver-509e9b7/test/unified-test-format/invalid/entity-thread-id-type.json000066400000000000000000000003521462766011000327550ustar00rootroot00000000000000{ "description": "entity-thread-id-type", "schemaVersion": "1.10", "createEntities": [ { "thread": { "id": 0 } } ], "tests": [ { "description": "foo", "operations": [] } ] } expectedCmapEvent-connectionCheckOutFailedEvent-reason-type.json000066400000000000000000000007151462766011000423110ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/unified-test-format/invalid{ "description": "expectedCmapEvent-connectionCheckOutFailedEvent-reason-type", "schemaVersion": "1.3", "tests": [ { "description": "foo", "operations": [], "expectEvents": [ { "client": "client0", "eventType": "cmap", "events": [ { "connectionCheckOutFailedEvent": { "reason": 10 } } ] } ] } ] } expectedCmapEvent-connectionCheckOutStartedEvent-additionalProperties.json000066400000000000000000000007301462766011000444470ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/unified-test-format/invalid{ "description": "expectedCmapEvent-connectionCheckOutStartedEvent-additionalProperties", "schemaVersion": "1.3", "tests": [ { "description": "foo", "operations": [], "expectEvents": [ { "client": "client0", "eventType": "cmap", "events": [ { "connectionCheckOutStartedEvent": { "foo": "bar" } } ] } ] } ] } expectedCmapEvent-connectionCheckedInEvent-additionalProperties.json000066400000000000000000000007141462766011000432320ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/unified-test-format/invalid{ "description": "expectedCmapEvent-connectionCheckedInEvent-additionalProperties", "schemaVersion": "1.3", "tests": [ { "description": "foo", "operations": [], "expectEvents": [ { "client": "client0", "eventType": "cmap", "events": [ { "connectionCheckedInEvent": { "foo": "bar" } } ] } ] } ] } expectedCmapEvent-connectionCheckedOutEvent-additionalProperties.json000066400000000000000000000007161462766011000434350ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/unified-test-format/invalid{ "description": "expectedCmapEvent-connectionCheckedOutEvent-additionalProperties", "schemaVersion": "1.3", "tests": [ { "description": "foo", "operations": [], "expectEvents": [ { "client": "client0", "eventType": "cmap", "events": [ { "connectionCheckedOutEvent": { "foo": "bar" } } ] } ] } ] } expectedCmapEvent-connectionClosedEvent-reason-type.json000066400000000000000000000006751462766011000407150ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/unified-test-format/invalid{ "description": "expectedCmapEvent-connectionClosedEvent-reason-type", "schemaVersion": "1.3", "tests": [ { "description": "foo", "operations": [], "expectEvents": [ { "client": "client0", "eventType": "cmap", "events": [ { "connectionClosedEvent": { "reason": 10 } } ] } ] } ] } expectedCmapEvent-connectionCreatedEvent-additionalProperties.json000066400000000000000000000007101462766011000427600ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/unified-test-format/invalid{ "description": "expectedCmapEvent-connectionCreatedEvent-additionalProperties", "schemaVersion": "1.3", "tests": [ { "description": "foo", "operations": [], "expectEvents": [ { "client": "client0", "eventType": "cmap", "events": [ { "connectionCreatedEvent": { "foo": "bar" } } ] } ] } ] } expectedCmapEvent-connectionReadyEvent-additionalProperties.json000066400000000000000000000007041462766011000424600ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/unified-test-format/invalid{ "description": "expectedCmapEvent-connectionReadyEvent-additionalProperties", "schemaVersion": "1.3", "tests": [ { "description": "foo", "operations": [], "expectEvents": [ { "client": "client0", "eventType": "cmap", "events": [ { "connectionReadyEvent": { "foo": "bar" } } ] } ] } ] } expectedCmapEvent-poolClearedEvent-hasServiceId-type.json000066400000000000000000000007021462766011000407260ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/unified-test-format/invalid{ "description": "expectedCmapEvent-poolClearedEvent-hasServiceId-type", "schemaVersion": "1.3", "tests": [ { "description": "foo", "operations": [], "expectEvents": [ { "client": "client0", "eventType": "cmap", "events": [ { "poolClearedEvent": { "hasServiceId": "foo" } } ] } ] } ] } expectedCmapEvent-poolClearedEvent-interruptInUseConnections-type.json000066400000000000000000000007351462766011000435660ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/unified-test-format/invalid{ "description": "expectedCmapEvent-poolClearedEvent-interruptInUseConnections-type", "schemaVersion": "1.11", "tests": [ { "description": "foo", "operations": [], "expectEvents": [ { "client": "client0", "eventType": "cmap", "events": [ { "poolClearedEvent": { "interruptInUseConnections": "foo" } } ] } ] } ] } expectedCmapEvent-poolClosedEvent-additionalProperties.json000066400000000000000000000006721462766011000414430ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/unified-test-format/invalid{ "description": "expectedCmapEvent-poolClosedEvent-additionalProperties", "schemaVersion": "1.3", "tests": [ { "description": "foo", "operations": [], "expectEvents": [ { "client": "client0", "eventType": "cmap", "events": [ { "poolClosedEvent": { "foo": "bar" } } ] } ] } ] } expectedCmapEvent-poolCreatedEvent-additionalProperties.json000066400000000000000000000006741462766011000416030ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/unified-test-format/invalid{ "description": "expectedCmapEvent-poolCreatedEvent-additionalProperties", "schemaVersion": "1.3", "tests": [ { "description": "foo", "operations": [], "expectEvents": [ { "client": "client0", "eventType": "cmap", "events": [ { "poolCreatedEvent": { "foo": "bar" } } ] } ] } ] } expectedCmapEvent-poolReadyEvent-additionalProperties.json000066400000000000000000000006701462766011000412740ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/unified-test-format/invalid{ "description": "expectedCmapEvent-poolReadyEvent-additionalProperties", "schemaVersion": "1.3", "tests": [ { "description": "foo", "operations": [], "expectEvents": [ { "client": "client0", "eventType": "cmap", "events": [ { "poolReadyEvent": { "foo": "bar" } } ] } ] } ] } expectedCommandEvent-additionalProperties.json000066400000000000000000000006561462766011000370400ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/unified-test-format/invalid{ "description": "expectedCommandEvent-additionalProperties", "schemaVersion": "1.0", "createEntities": [ { "client": { "id": "client0" } } ], "tests": [ { "description": "foo", "operations": [], "expectEvents": [ { "client": "client0", "events": [ { "foo": 0 } ] } ] } ] } expectedCommandEvent-commandFailedEvent-commandName-type.json000066400000000000000000000007751462766011000415760ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/unified-test-format/invalid{ "description": "expectedCommandEvent-commandFailedEvent-commandName-type", "schemaVersion": "1.0", "createEntities": [ { "client": { "id": "client0" } } ], "tests": [ { "description": "foo", "operations": [], "expectEvents": [ { "client": "client0", "events": [ { "commandFailedEvent": { "commandName": 0 } } ] } ] } ] } expectedCommandEvent-commandFailedEvent-databaseName-type.json000066400000000000000000000010001462766011000417020ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/unified-test-format/invalid{ "description": "expectedCommandEvent-commandFailedEvent-databaseName-type", "schemaVersion": "1.15", "createEntities": [ { "client": { "id": "client0" } } ], "tests": [ { "description": "foo", "operations": [], "expectEvents": [ { "client": "client0", "events": [ { "commandFailedEvent": { "databaseName": 0 } } ] } ] } ] } expectedCommandEvent-commandFailedEvent-hasServerConnectionId-type.json000066400000000000000000000010251462766011000436030ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/unified-test-format/invalid{ "description": "expectedCommandEvent-commandFailedEvent-hasServerConnectionId-type", "schemaVersion": "1.6", "createEntities": [ { "client": { "id": "client0" } } ], "tests": [ { "description": "foo", "operations": [], "expectEvents": [ { "client": "client0", "events": [ { "commandFailedEvent": { "hasServerConnectionId": "foo" } } ] } ] } ] } expectedCommandEvent-commandFailedEvent-hasServiceId-type.json000066400000000000000000000010031462766011000417110ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/unified-test-format/invalid{ "description": "expectedCommandEvent-commandFailedEvent-hasServiceId-type", "schemaVersion": "1.3", "createEntities": [ { "client": { "id": "client0" } } ], "tests": [ { "description": "foo", "operations": [], "expectEvents": [ { "client": "client0", "events": [ { "commandFailedEvent": { "hasServiceId": "foo" } } ] } ] } ] } expectedCommandEvent-commandStartedEvent-additionalProperties.json000066400000000000000000000007731462766011000430050ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/unified-test-format/invalid{ "description": "expectedCommandEvent-commandStartedEvent-additionalProperties", "schemaVersion": "1.0", "createEntities": [ { "client": { "id": "client0" } } ], "tests": [ { "description": "foo", "operations": [], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "foo": 0 } } ] } ] } ] } expectedCommandEvent-commandStartedEvent-command-type.json000066400000000000000000000007671462766011000412200ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/unified-test-format/invalid{ "description": "expectedCommandEvent-commandStartedEvent-command-type", "schemaVersion": "1.0", "createEntities": [ { "client": { "id": "client0" } } ], "tests": [ { "description": "foo", "operations": [], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": 0 } } ] } ] } ] } expectedCommandEvent-commandStartedEvent-commandName-type.json000066400000000000000000000007771462766011000420220ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/unified-test-format/invalid{ "description": "expectedCommandEvent-commandStartedEvent-commandName-type", "schemaVersion": "1.0", "createEntities": [ { "client": { "id": "client0" } } ], "tests": [ { "description": "foo", "operations": [], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "commandName": 0 } } ] } ] } ] } expectedCommandEvent-commandStartedEvent-databaseName-type.json000066400000000000000000000010011462766011000421250ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/unified-test-format/invalid{ "description": "expectedCommandEvent-commandStartedEvent-databaseName-type", "schemaVersion": "1.0", "createEntities": [ { "client": { "id": "client0" } } ], "tests": [ { "description": "foo", "operations": [], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "databaseName": 0 } } ] } ] } ] } expectedCommandEvent-commandStartedEvent-hasServerConnectionId-type.json000066400000000000000000000010271462766011000440270ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/unified-test-format/invalid{ "description": "expectedCommandEvent-commandStartedEvent-hasServerConnectionId-type", "schemaVersion": "1.6", "createEntities": [ { "client": { "id": "client0" } } ], "tests": [ { "description": "foo", "operations": [], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "hasServerConnectionId": "foo" } } ] } ] } ] } expectedCommandEvent-commandStartedEvent-hasServiceId-type.json000066400000000000000000000010051462766011000421350ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/unified-test-format/invalid{ "description": "expectedCommandEvent-commandStartedEvent-hasServiceId-type", "schemaVersion": "1.3", "createEntities": [ { "client": { "id": "client0" } } ], "tests": [ { "description": "foo", "operations": [], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "hasServiceId": "foo" } } ] } ] } ] } expectedCommandEvent-commandSucceededEvent-commandName-type.json000066400000000000000000000010031462766011000422570ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/unified-test-format/invalid{ "description": "expectedCommandEvent-commandSucceededEvent-commandName-type", "schemaVersion": "1.0", "createEntities": [ { "client": { "id": "client0" } } ], "tests": [ { "description": "foo", "operations": [], "expectEvents": [ { "client": "client0", "events": [ { "commandSucceededEvent": { "commandName": 0 } } ] } ] } ] } expectedCommandEvent-commandSucceededEvent-databaseName-type.json000066400000000000000000000010061462766011000424100ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/unified-test-format/invalid{ "description": "expectedCommandEvent-commandSucceededEvent-databaseName-type", "schemaVersion": "1.15", "createEntities": [ { "client": { "id": "client0" } } ], "tests": [ { "description": "foo", "operations": [], "expectEvents": [ { "client": "client0", "events": [ { "commandSucceededEvent": { "databaseName": 0 } } ] } ] } ] } expectedCommandEvent-commandSucceededEvent-hasServerConnectionId-type.json000066400000000000000000000010331462766011000443020ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/unified-test-format/invalid{ "description": "expectedCommandEvent-commandSucceededEvent-hasServerConnectionId-type", "schemaVersion": "1.6", "createEntities": [ { "client": { "id": "client0" } } ], "tests": [ { "description": "foo", "operations": [], "expectEvents": [ { "client": "client0", "events": [ { "commandSucceededEvent": { "hasServerConnectionId": "foo" } } ] } ] } ] } expectedCommandEvent-commandSucceededEvent-hasServiceId-type.json000066400000000000000000000010111462766011000424100ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/unified-test-format/invalid{ "description": "expectedCommandEvent-commandSucceededEvent-hasServiceId-type", "schemaVersion": "1.3", "createEntities": [ { "client": { "id": "client0" } } ], "tests": [ { "description": "foo", "operations": [], "expectEvents": [ { "client": "client0", "events": [ { "commandSucceededEvent": { "hasServiceId": "foo" } } ] } ] } ] } expectedCommandEvent-commandSucceededEvent-reply-type.json000066400000000000000000000007671462766011000412130ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/unified-test-format/invalid{ "description": "expectedCommandEvent-commandSucceededEvent-reply-type", "schemaVersion": "1.0", "createEntities": [ { "client": { "id": "client0" } } ], "tests": [ { "description": "foo", "operations": [], "expectEvents": [ { "client": "client0", "events": [ { "commandSucceededEvent": { "reply": 0 } } ] } ] } ] } expectedCommandEvent-maxProperties.json000066400000000000000000000007431462766011000355120ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/unified-test-format/invalid{ "description": "expectedCommandEvent-maxProperties", "schemaVersion": "1.0", "createEntities": [ { "client": { "id": "client0" } } ], "tests": [ { "description": "foo", "operations": [], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": {}, "commandSucceededEvent": {} } ] } ] } ] } expectedCommandEvent-minProperties.json000066400000000000000000000006031462766011000355030ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/unified-test-format/invalid{ "description": "expectedCommandEvent-minProperties", "schemaVersion": "1.0", "createEntities": [ { "client": { "id": "client0" } } ], "tests": [ { "description": "foo", "operations": [], "expectEvents": [ { "client": "client0", "events": [ {} ] } ] } ] } expectedError-additionalProperties.json000066400000000000000000000006151462766011000355440ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/unified-test-format/invalid{ "description": "expectedError-additionalProperties", "schemaVersion": "1.0", "createEntities": [ { "client": { "id": "client0" } } ], "tests": [ { "description": "foo", "operations": [ { "name": "foo", "object": "client0", "expectError": { "foo": 0 } } ] } ] } expectedError-errorCode-type.json000066400000000000000000000006211462766011000342570ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/unified-test-format/invalid{ "description": "expectedError-errorCode-type", "schemaVersion": "1.0", "createEntities": [ { "client": { "id": "client0" } } ], "tests": [ { "description": "foo", "operations": [ { "name": "foo", "object": "client0", "expectError": { "errorCode": "foo" } } ] } ] } expectedError-errorCodeName-type.json000066400000000000000000000006251462766011000350640ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/unified-test-format/invalid{ "description": "expectedError-errorCodeName-type", "schemaVersion": "1.0", "createEntities": [ { "client": { "id": "client0" } } ], "tests": [ { "description": "foo", "operations": [ { "name": "foo", "object": "client0", "expectError": { "errorCodeName": 0 } } ] } ] } expectedError-errorContains-type.json000066400000000000000000000006251462766011000351670ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/unified-test-format/invalid{ "description": "expectedError-errorContains-type", "schemaVersion": "1.0", "createEntities": [ { "client": { "id": "client0" } } ], "tests": [ { "description": "foo", "operations": [ { "name": "foo", "object": "client0", "expectError": { "errorContains": 0 } } ] } ] } expectedError-errorLabelsContain-items.json000066400000000000000000000006761462766011000362750ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/unified-test-format/invalid{ "description": "expectedError-errorLabelsContain-items", "schemaVersion": "1.0", "createEntities": [ { "client": { "id": "client0" } } ], "tests": [ { "description": "foo", "operations": [ { "name": "foo", "object": "client0", "expectError": { "errorLabelsContain": [ 0 ] } } ] } ] } expectedError-errorLabelsContain-minItems.json000066400000000000000000000006441462766011000367340ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/unified-test-format/invalid{ "description": "expectedError-errorLabelsContain-minItems", "schemaVersion": "1.0", "createEntities": [ { "client": { "id": "client0" } } ], "tests": [ { "description": "foo", "operations": [ { "name": "foo", "object": "client0", "expectError": { "errorLabelsContain": [] } } ] } ] } expectedError-errorLabelsContain-type.json000066400000000000000000000006371462766011000361320ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/unified-test-format/invalid{ "description": "expectedError-errorLabelsContain-type", "schemaVersion": "1.0", "createEntities": [ { "client": { "id": "client0" } } ], "tests": [ { "description": "foo", "operations": [ { "name": "foo", "object": "client0", "expectError": { "errorLabelsContain": 0 } } ] } ] } expectedError-errorLabelsOmit-items.json000066400000000000000000000006701462766011000356040ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/unified-test-format/invalid{ "description": "expectedError-errorLabelsOmit-items", "schemaVersion": "1.0", "createEntities": [ { "client": { "id": "client0" } } ], "tests": [ { "description": "foo", "operations": [ { "name": "foo", "object": "client0", "expectError": { "errorLabelsOmit": [ 0 ] } } ] } ] } expectedError-errorLabelsOmit-minItems.json000066400000000000000000000006361462766011000362520ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/unified-test-format/invalid{ "description": "expectedError-errorLabelsOmit-minItems", "schemaVersion": "1.0", "createEntities": [ { "client": { "id": "client0" } } ], "tests": [ { "description": "foo", "operations": [ { "name": "foo", "object": "client0", "expectError": { "errorLabelsOmit": [] } } ] } ] } expectedError-errorLabelsOmit-type.json000066400000000000000000000006311462766011000354410ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/unified-test-format/invalid{ "description": "expectedError-errorLabelsOmit-type", "schemaVersion": "1.0", "createEntities": [ { "client": { "id": "client0" } } ], "tests": [ { "description": "foo", "operations": [ { "name": "foo", "object": "client0", "expectError": { "errorLabelsOmit": 0 } } ] } ] } expectedError-errorResponse-type.json000066400000000000000000000006261462766011000352100ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/unified-test-format/invalid{ "description": "expectedError-errorResponse-type", "schemaVersion": "1.12", "createEntities": [ { "client": { "id": "client0" } } ], "tests": [ { "description": "foo", "operations": [ { "name": "foo", "object": "client0", "expectError": { "errorResponse": 0 } } ] } ] } expectedError-isClientError-type.json000066400000000000000000000006251462766011000351230ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/unified-test-format/invalid{ "description": "expectedError-isClientError-type", "schemaVersion": "1.0", "createEntities": [ { "client": { "id": "client0" } } ], "tests": [ { "description": "foo", "operations": [ { "name": "foo", "object": "client0", "expectError": { "isClientError": 0 } } ] } ] } expectedError-isError-const.json000066400000000000000000000006161462766011000341310ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/unified-test-format/invalid{ "description": "expectedError-isError-const", "schemaVersion": "1.0", "createEntities": [ { "client": { "id": "client0" } } ], "tests": [ { "description": "foo", "operations": [ { "name": "foo", "object": "client0", "expectError": { "isError": false } } ] } ] } mongodb-mongo-python-driver-509e9b7/test/unified-test-format/invalid/expectedError-isError-type.json000066400000000000000000000006111462766011000340360ustar00rootroot00000000000000{ "description": "expectedError-isError-type", "schemaVersion": "1.0", "createEntities": [ { "client": { "id": "client0" } } ], "tests": [ { "description": "foo", "operations": [ { "name": "foo", "object": "client0", "expectError": { "isError": 0 } } ] } ] } expectedError-isTimeoutError-type.json000066400000000000000000000006271462766011000353350ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/unified-test-format/invalid{ "description": "expectedError-isTimeoutError-type", "schemaVersion": "1.9", "createEntities": [ { "client": { "id": "client0" } } ], "tests": [ { "description": "foo", "operations": [ { "name": "foo", "object": "client0", "expectError": { "isTimeoutError": 0 } } ] } ] } expectedError-minProperties.json000066400000000000000000000005461462766011000342220ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/unified-test-format/invalid{ "description": "expectedError-minProperties", "schemaVersion": "1.0", "createEntities": [ { "client": { "id": "client0" } } ], "tests": [ { "description": "foo", "operations": [ { "name": "foo", "object": "client0", "expectError": {} } ] } ] } expectedEventsForClient-additionalProperties.json000066400000000000000000000006071462766011000375260ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/unified-test-format/invalid{ "description": "expectedEventsForClient-additionalProperties", "schemaVersion": "1.0", "createEntities": [ { "client": { "id": "client0" } } ], "tests": [ { "description": "foo", "operations": [], "expectEvents": [ { "client": "client0", "events": [], "foo": 0 } ] } ] } expectedEventsForClient-client-required.json000066400000000000000000000005171462766011000364350ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/unified-test-format/invalid{ "description": "expectedEventsForClient-client-required", "schemaVersion": "1.0", "createEntities": [ { "client": { "id": "client0" } } ], "tests": [ { "description": "foo", "operations": [], "expectEvents": [ { "events": [] } ] } ] } expectedEventsForClient-client-type.json000066400000000000000000000005421462766011000355740ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/unified-test-format/invalid{ "description": "expectedEventsForClient-client-type", "schemaVersion": "1.0", "createEntities": [ { "client": { "id": "client0" } } ], "tests": [ { "description": "foo", "operations": [], "expectEvents": [ { "client": 0, "events": [] } ] } ] } expectedEventsForClient-eventType-enum.json000066400000000000000000000006371462766011000362710ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/unified-test-format/invalid{ "description": "expectedEventsForClient-eventType-enum", "schemaVersion": "1.3", "createEntities": [ { "client": { "id": "client0" } } ], "tests": [ { "description": "invalid eventType value", "operations": [], "expectEvents": [ { "client": "client0", "eventType": "foo", "events": [] } ] } ] } expectedEventsForClient-eventType-type.json000066400000000000000000000006331462766011000363020ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/unified-test-format/invalid{ "description": "expectedEventsForClient-eventType-type", "schemaVersion": "1.3", "createEntities": [ { "client": { "id": "client0" } } ], "tests": [ { "description": "invalid eventType type", "operations": [], "expectEvents": [ { "client": "client0", "eventType": 10, "events": [] } ] } ] } expectedEventsForClient-events-items.json000066400000000000000000000006041462766011000357610ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/unified-test-format/invalid{ "description": "expectedEventsForClient-events-items", "schemaVersion": "1.0", "createEntities": [ { "client": { "id": "client0" } } ], "tests": [ { "description": "foo", "operations": [], "expectEvents": [ { "client": "client0", "events": [ 0 ] } ] } ] } expectedEventsForClient-events-required.json000066400000000000000000000005261462766011000364630ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/unified-test-format/invalid{ "description": "expectedEventsForClient-events-required", "schemaVersion": "1.0", "createEntities": [ { "client": { "id": "client0" } } ], "tests": [ { "description": "foo", "operations": [], "expectEvents": [ { "client": "client0" } ] } ] } expectedEventsForClient-events-type.json000066400000000000000000000005511462766011000356220ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/unified-test-format/invalid{ "description": "expectedEventsForClient-events-type", "schemaVersion": "1.0", "createEntities": [ { "client": { "id": "client0" } } ], "tests": [ { "description": "foo", "operations": [], "expectEvents": [ { "client": "client0", "events": 0 } ] } ] } expectedEventsForClient-events_conflicts_with_cmap_eventType.json000066400000000000000000000010221462766011000427770ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/unified-test-format/invalid{ "description": "expectedEventsForClient-events_conflicts_with_cmap_eventType", "schemaVersion": "1.3", "createEntities": [ { "client": { "id": "client0" } } ], "tests": [ { "description": "invalid event when eventType is cmap", "operations": [], "expectEvents": [ { "client": "client0", "eventType": "cmap", "events": [ { "commandStartedEvent": {} } ] } ] } ] } expectedEventsForClient-events_conflicts_with_command_eventType.json000066400000000000000000000010301462766011000434740ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/unified-test-format/invalid{ "description": "expectedEventsForClient-events_conflicts_with_command_eventType", "schemaVersion": "1.3", "createEntities": [ { "client": { "id": "client0" } } ], "tests": [ { "description": "invalid event when eventType is command", "operations": [], "expectEvents": [ { "client": "client0", "eventType": "command", "events": [ { "poolCreatedEvent": {} } ] } ] } ] } expectedEventsForClient-events_conflicts_with_default_eventType.json000066400000000000000000000007641462766011000435170ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/unified-test-format/invalid{ "description": "expectedEventsForClient-events_conflicts_with_default_eventType", "schemaVersion": "1.3", "createEntities": [ { "client": { "id": "client0" } } ], "tests": [ { "description": "invalid event when eventType is unset", "operations": [], "expectEvents": [ { "client": "client0", "events": [ { "poolCreatedEvent": {} } ] } ] } ] } expectedEventsForClient-ignoreExtraEvents-type.json000066400000000000000000000006271462766011000377760ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/unified-test-format/invalid{ "description": "expectedEventsForClient-ignoreExtraEvents-type", "schemaVersion": "1.7", "createEntities": [ { "client": { "id": "client0" } } ], "tests": [ { "description": "foo", "operations": [], "expectEvents": [ { "client": "client0", "events": [], "ignoreExtraEvents": 0 } ] } ] } expectedLogMessage-additionalProperties.json000066400000000000000000000006121462766011000364760ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/unified-test-format/invalid{ "description": "expectedLogMessage-additionalProperties", "schemaVersion": "1.13", "createEntities": [ { "client": { "id": "client0" } } ], "tests": [ { "description": "foo", "operations": [], "expectLogMessages": [ { "client": "client0", "messages": [], "foo": 0 } ] } ] } expectedLogMessage-component-enum.json000066400000000000000000000007621462766011000352630ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/unified-test-format/invalid{ "description": "expectedLogMessage-component-enum", "schemaVersion": "1.13", "createEntities": [ { "client": { "id": "client0" } } ], "tests": [ { "description": "foo", "operations": [], "expectLogMessages": [ { "client": "client0", "messages": [ { "level": "debug", "component": "foo", "data": {} } ] } ] } ] } expectedLogMessage-component-required.json000066400000000000000000000007201462766011000361310ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/unified-test-format/invalid{ "description": "expectedLogMessage-component-type", "schemaVersion": "1.13", "createEntities": [ { "client": { "id": "client0" } } ], "tests": [ { "description": "foo", "operations": [], "expectLogMessages": [ { "client": "client0", "messages": [ { "level": "debug", "data": {} } ] } ] } ] } expectedLogMessage-component-type.json000066400000000000000000000007561462766011000353030ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/unified-test-format/invalid{ "description": "expectedLogMessage-component-type", "schemaVersion": "1.13", "createEntities": [ { "client": { "id": "client0" } } ], "tests": [ { "description": "foo", "operations": [], "expectLogMessages": [ { "client": "client0", "messages": [ { "level": "debug", "component": 0, "data": {} } ] } ] } ] } expectedLogMessage-data-required.json000066400000000000000000000007331462766011000350440ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/unified-test-format/invalid{ "description": "expectedLogMessage-data-required", "schemaVersion": "1.13", "createEntities": [ { "client": { "id": "client0" } } ], "tests": [ { "description": "foo", "operations": [], "expectLogMessages": [ { "client": "client0", "messages": [ { "level": "debug", "component": "command" } ] } ] } ] } expectedLogMessage-data-type.json000066400000000000000000000007601462766011000342050ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/unified-test-format/invalid{ "description": "expectedLogMessage-data-type", "schemaVersion": "1.13", "createEntities": [ { "client": { "id": "client0" } } ], "tests": [ { "description": "foo", "operations": [], "expectLogMessages": [ { "client": "client0", "messages": [ { "level": "debug", "component": "command", "data": 0 } ] } ] } ] } expectedLogMessage-failureIsRedacted-type.json000066400000000000000000000010441462766011000366470ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/unified-test-format/invalid{ "description": "expectedLogMessage-failureIsRedacted-type", "schemaVersion": "1.13", "createEntities": [ { "client": { "id": "client0" } } ], "tests": [ { "description": "foo", "operations": [], "expectLogMessages": [ { "client": "client0", "messages": [ { "level": "debug", "component": "command", "failureIsRedacted": 0, "data": {} } ] } ] } ] } expectedLogMessage-level-enum.json000066400000000000000000000007601462766011000343660ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/unified-test-format/invalid{ "description": "expectedLogMessage-level-enum", "schemaVersion": "1.13", "createEntities": [ { "client": { "id": "client0" } } ], "tests": [ { "description": "foo", "operations": [], "expectLogMessages": [ { "client": "client0", "messages": [ { "level": "foo", "component": "command", "data": {} } ] } ] } ] } expectedLogMessage-level-required.json000066400000000000000000000007261462766011000352440ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/unified-test-format/invalid{ "description": "expectedLogMessage-level-required", "schemaVersion": "1.13", "createEntities": [ { "client": { "id": "client0" } } ], "tests": [ { "description": "foo", "operations": [], "expectLogMessages": [ { "client": "client0", "messages": [ { "component": "command", "data": {} } ] } ] } ] } expectedLogMessage-level-type.json000066400000000000000000000007541462766011000344060ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/unified-test-format/invalid{ "description": "expectedLogMessage-level-type", "schemaVersion": "1.13", "createEntities": [ { "client": { "id": "client0" } } ], "tests": [ { "description": "foo", "operations": [], "expectLogMessages": [ { "client": "client0", "messages": [ { "level": 0, "component": "command", "data": {} } ] } ] } ] } expectedLogMessagesForClient-additionalProperties.json000066400000000000000000000006241462766011000404720ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/unified-test-format/invalid{ "description": "expectedLogMessagesForClient-additionalProperties", "schemaVersion": "1.13", "createEntities": [ { "client": { "id": "client0" } } ], "tests": [ { "description": "foo", "operations": [], "expectLogMessages": [ { "client": "client0", "messages": [], "foo": 0 } ] } ] } expectedLogMessagesForClient-client-required.json000066400000000000000000000005341462766011000374010ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/unified-test-format/invalid{ "description": "expectedLogMessagesForClient-client-required", "schemaVersion": "1.13", "createEntities": [ { "client": { "id": "client0" } } ], "tests": [ { "description": "foo", "operations": [], "expectLogMessages": [ { "messages": [] } ] } ] } expectedLogMessagesForClient-client-type.json000066400000000000000000000005521462766011000365420ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/unified-test-format/invalid{ "description": "expectedEventsForClient-client-type", "schemaVersion": "1.13", "createEntities": [ { "client": { "id": "client0" } } ], "tests": [ { "description": "foo", "operations": [], "expectLogMessages": [ { "client": 0, "messages": [] } ] } ] } expectedLogMessagesForClient-ignoreExtraMessages-type.json000066400000000000000000000006551462766011000412470ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/unified-test-format/invalid{ "description": "expectedLogMessagesForClient-ignoreExtraMessages-type", "schemaVersion": "1.16", "createEntities": [ { "client": { "id": "client0" } } ], "tests": [ { "description": "foo", "operations": [], "expectLogMessages": [ { "client": "client0", "ignoreExtraMessages": "true", "messages": [] } ] } ] } expectedLogMessagesForClient-ignoreMessages-items.json000066400000000000000000000006711462766011000404010ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/unified-test-format/invalid{ "description": "expectedLogMessagesForClient-ignoreMessages-items", "schemaVersion": "1.16", "createEntities": [ { "client": { "id": "client0" } } ], "tests": [ { "description": "foo", "operations": [], "expectLogMessages": [ { "client": "client0", "messages": [], "ignoreMessages": [ 0 ] } ] } ] } expectedLogMessagesForClient-ignoreMessages-type.json000066400000000000000000000006361462766011000402420ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/unified-test-format/invalid{ "description": "expectedLogMessagesForClient-ignoreMessages-type", "schemaVersion": "1.16", "createEntities": [ { "client": { "id": "client0" } } ], "tests": [ { "description": "foo", "operations": [], "expectLogMessages": [ { "client": "client0", "messages": [], "ignoreMessages": 0 } ] } ] } expectedLogMessagesForClient-messages-items.json000066400000000000000000000006231462766011000372320ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/unified-test-format/invalid{ "description": "expectedLogMessagesForClient-messages-items", "schemaVersion": "1.13", "createEntities": [ { "client": { "id": "client0" } } ], "tests": [ { "description": "foo", "operations": [], "expectLogMessages": [ { "client": "client0", "messages": [ 0 ] } ] } ] } expectedLogMessagesForClient-messages-required.json000066400000000000000000000005431462766011000377320ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/unified-test-format/invalid{ "description": "expectedLogMessagesForClient-messages-required", "schemaVersion": "1.13", "createEntities": [ { "client": { "id": "client0" } } ], "tests": [ { "description": "foo", "operations": [], "expectLogMessages": [ { "client": "client0" } ] } ] } expectedLogMessagesForClient-messages-type.json000066400000000000000000000005701462766011000370730ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/unified-test-format/invalid{ "description": "expectedLogMessagesForClient-messages-type", "schemaVersion": "1.13", "createEntities": [ { "client": { "id": "client0" } } ], "tests": [ { "description": "foo", "operations": [], "expectLogMessages": [ { "client": "client0", "messages": 0 } ] } ] } expectedSdamEvent-serverDescriptionChangedEvent-additionalProperties.json000066400000000000000000000007271462766011000443310ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/unified-test-format/invalid{ "description": "expectedSdamEvent-serverDescriptionChangedEvent-additionalProperties", "schemaVersion": "1.10", "tests": [ { "description": "foo", "operations": [], "expectEvents": [ { "client": "client0", "eventType": "sdam", "events": [ { "serverDescriptionChangedEvent": { "foo": "bar" } } ] } ] } ] } expectedSdamEvent-serverDescriptionChangedEvent-serverDescription-additionalProperties.json000066400000000000000000000010461462766011000500340ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/unified-test-format/invalid{ "description": "expectedSdamEvent-serverDescriptionChangedEvent-serverDescription-additionalProperties", "schemaVersion": "1.10", "tests": [ { "description": "foo", "operations": [], "expectEvents": [ { "client": "client0", "eventType": "sdam", "events": [ { "serverDescriptionChangedEvent": { "previousDescription": { "foo": "bar" } } } ] } ] } ] } expectedSdamEvent-serverDescriptionChangedEvent-serverDescription-type-enum.json000066400000000000000000000010521462766011000455670ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/unified-test-format/invalid{ "description": "expectedSdamEvent-serverDescriptionChangedEvent-serverDescription-type-enum", "schemaVersion": "1.10", "tests": [ { "description": "foo", "operations": [], "expectEvents": [ { "client": "client0", "eventType": "sdam", "events": [ { "serverDescriptionChangedEvent": { "previousDescription": { "type": "not a server type" } } } ] } ] } ] } expectedSdamEvent-serverDescriptionChangedEvent-serverDescription-type-type.json000066400000000000000000000010311462766011000456010ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/unified-test-format/invalid{ "description": "expectedSdamEvent-serverDescriptionChangedEvent-serverDescription-type-type", "schemaVersion": "1.10", "tests": [ { "description": "foo", "operations": [], "expectEvents": [ { "client": "client0", "eventType": "sdam", "events": [ { "serverDescriptionChangedEvent": { "previousDescription": { "type": 12 } } } ] } ] } ] } expectedSdamEvent-topologyDescriptionChangedEvent-additionalProperties.json000066400000000000000000000007331462766011000446740ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/unified-test-format/invalid{ "description": "expectedSdamEvent-topologyDescriptionChangedEvent-additionalProperties", "schemaVersion": "1.14", "tests": [ { "description": "foo", "operations": [], "expectEvents": [ { "client": "client0", "eventType": "sdam", "events": [ { "topologyDescriptionChangedEvent": { "foo": "bar" } } ] } ] } ] } mongodb-mongo-python-driver-509e9b7/test/unified-test-format/invalid/initialData-items.json000066400000000000000000000002621462766011000321650ustar00rootroot00000000000000{ "description": "initialData-items", "schemaVersion": "1.0", "initialData": [ 0 ], "tests": [ { "description": "foo", "operations": [] } ] } mongodb-mongo-python-driver-509e9b7/test/unified-test-format/invalid/initialData-minItems.json000066400000000000000000000002541462766011000326320ustar00rootroot00000000000000{ "description": "initialData-minItems", "schemaVersion": "1.0", "initialData": [], "tests": [ { "description": "foo", "operations": [] } ] } mongodb-mongo-python-driver-509e9b7/test/unified-test-format/invalid/initialData-type.json000066400000000000000000000002471462766011000320300ustar00rootroot00000000000000{ "description": "initialData-type", "schemaVersion": "1.0", "initialData": 0, "tests": [ { "description": "foo", "operations": [] } ] } operation-additionalProperties.json000066400000000000000000000005401462766011000347260ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/unified-test-format/invalid{ "description": "operation-additionalProperties", "schemaVersion": "1.0", "createEntities": [ { "client": { "id": "client0" } } ], "tests": [ { "description": "foo", "operations": [ { "name": "foo", "object": "client0", "foo": 0 } ] } ] } mongodb-mongo-python-driver-509e9b7/test/unified-test-format/invalid/operation-arguments-type.json000066400000000000000000000005401462766011000336040ustar00rootroot00000000000000{ "description": "operation-arguments-type", "schemaVersion": "1.0", "createEntities": [ { "client": { "id": "client0" } } ], "tests": [ { "description": "foo", "operations": [ { "name": "foo", "object": "client0", "arguments": 0 } ] } ] } operation-expectError-conflicts_with_expectResult.json000066400000000000000000000007011462766011000406260ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/unified-test-format/invalid{ "description": "operation-expectError-conflicts_with_expectResult", "schemaVersion": "1.0", "createEntities": [ { "client": { "id": "client0" } } ], "tests": [ { "description": "foo", "operations": [ { "name": "foo", "object": "client0", "expectError": { "isError": true }, "expectResult": {} } ] } ] } operation-expectError-conflicts_with_saveResultAsEntity.json000066400000000000000000000007201462766011000417560ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/unified-test-format/invalid{ "description": "operation-expectError-conflicts_with_saveResultAsEntity", "schemaVersion": "1.0", "createEntities": [ { "client": { "id": "client0" } } ], "tests": [ { "description": "foo", "operations": [ { "name": "foo", "object": "client0", "expectError": { "isError": true }, "saveResultAsEntity": "foo" } ] } ] } mongodb-mongo-python-driver-509e9b7/test/unified-test-format/invalid/operation-expectError-type.json000066400000000000000000000005441462766011000341050ustar00rootroot00000000000000{ "description": "operation-expectError-type", "schemaVersion": "1.0", "createEntities": [ { "client": { "id": "client0" } } ], "tests": [ { "description": "foo", "operations": [ { "name": "foo", "object": "client0", "expectError": 0 } ] } ] } operation-expectEvents-type.json000066400000000000000000000005461462766011000342030ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/unified-test-format/invalid{ "description": "operation-expectEvents-type", "schemaVersion": "1.0", "createEntities": [ { "client": { "id": "client0" } } ], "tests": [ { "description": "foo", "operations": [ { "name": "foo", "object": "client0", "expectEvents": 0 } ] } ] } operation-ignoreResultAndError-conflicts_with_expectError.json000066400000000000000000000006351462766011000422640ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/unified-test-format/invalid{ "description": "operation-ignoreResultAndError-conflicts_with_expectError", "schemaVersion": "1.3", "tests": [ { "description": "ignoreResultAndError used with expectError", "operations": [ { "name": "foo", "object": "bar", "ignoreResultAndError": true, "expectError": { "isError": true } } ] } ] } operation-ignoreResultAndError-conflicts_with_expectResult.json000066400000000000000000000005701462766011000424470ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/unified-test-format/invalid{ "description": "operation-ignoreResultAndError-conflicts_with_expectResult", "schemaVersion": "1.3", "tests": [ { "description": "ignoreResultAndError used with expectResult", "operations": [ { "name": "foo", "object": "bar", "ignoreResultAndError": true, "expectResult": 1 } ] } ] } operation-ignoreResultAndError-conflicts_with_saveResultAsEntity.json000066400000000000000000000006221462766011000435740ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/unified-test-format/invalid{ "description": "operation-ignoreResultAndError-conflicts_with_saveResultAsEntity", "schemaVersion": "1.3", "tests": [ { "description": "ignoreResultAndError used with saveResultAsEntity", "operations": [ { "name": "foo", "object": "bar", "ignoreResultAndError": true, "saveResultAsEntity": "entity0" } ] } ] } mongodb-mongo-python-driver-509e9b7/test/unified-test-format/invalid/operation-name-required.json000066400000000000000000000004541462766011000333620ustar00rootroot00000000000000{ "description": "operation-name-required", "schemaVersion": "1.0", "createEntities": [ { "client": { "id": "client0" } } ], "tests": [ { "description": "foo", "operations": [ { "object": "client0" } ] } ] } mongodb-mongo-python-driver-509e9b7/test/unified-test-format/invalid/operation-name-type.json000066400000000000000000000004751462766011000325260ustar00rootroot00000000000000{ "description": "operation-name-type", "schemaVersion": "1.0", "createEntities": [ { "client": { "id": "client0" } } ], "tests": [ { "description": "foo", "operations": [ { "name": 0, "object": "client0" } ] } ] } mongodb-mongo-python-driver-509e9b7/test/unified-test-format/invalid/operation-object-required.json000066400000000000000000000004501462766011000337040ustar00rootroot00000000000000{ "description": "operation-object-required", "schemaVersion": "1.0", "createEntities": [ { "client": { "id": "client0" } } ], "tests": [ { "description": "foo", "operations": [ { "name": "foo" } ] } ] } mongodb-mongo-python-driver-509e9b7/test/unified-test-format/invalid/operation-object-type.json000066400000000000000000000004731462766011000330520ustar00rootroot00000000000000{ "description": "operation-object-type", "schemaVersion": "1.0", "createEntities": [ { "client": { "id": "client0" } } ], "tests": [ { "description": "foo", "operations": [ { "name": "foo", "object": 0 } ] } ] } operation-saveResultAsEntity-type.json000066400000000000000000000005621462766011000353420ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/unified-test-format/invalid{ "description": "operation-saveResultAsEntity-type", "schemaVersion": "1.0", "createEntities": [ { "client": { "id": "client0" } } ], "tests": [ { "description": "foo", "operations": [ { "name": "foo", "object": "client0", "saveResultAsEntity": 0 } ] } ] } runOnRequirement-additionalProperties.json000066400000000000000000000004021462766011000362450ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/unified-test-format/invalid{ "description": "runOnRequirement-additionalProperties", "schemaVersion": "1.0", "runOnRequirements": [ { "minServerVersion": "4.0", "foo": 0 } ], "tests": [ { "description": "foo", "operations": [] } ] } mongodb-mongo-python-driver-509e9b7/test/unified-test-format/invalid/runOnRequirement-auth-type.json000066400000000000000000000003331462766011000340620ustar00rootroot00000000000000{ "description": "runOnRequirement-auth-type", "schemaVersion": "1.3", "runOnRequirements": [ { "auth": "foo" } ], "tests": [ { "description": "foo", "operations": [] } ] } runOnRequirement-authMechanism-type.json000066400000000000000000000003621462766011000356320ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/unified-test-format/invalid{ "description": "runOnRequirement-authMechanism-type", "schemaVersion": "1.19", "runOnRequirements": [ { "authMechanism": 0 } ], "tests": [ { "description": "foo", "operations": [ ] } ] } runOnRequirement-csfle-type.json000066400000000000000000000003351462766011000341400ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/unified-test-format/invalid{ "description": "runOnRequirement-csfle-type", "schemaVersion": "1.8", "runOnRequirements": [ { "csfle": "foo" } ], "tests": [ { "description": "foo", "operations": [] } ] } runOnRequirement-maxServerVersion-pattern.json000066400000000000000000000003721462766011000370630ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/unified-test-format/invalid{ "description": "runOnRequirement-maxServerVersion-pattern", "schemaVersion": "1.0", "runOnRequirements": [ { "maxServerVersion": "1.2.3.4" } ], "tests": [ { "description": "foo", "operations": [] } ] } runOnRequirement-maxServerVersion-type.json000066400000000000000000000003571462766011000363720ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/unified-test-format/invalid{ "description": "runOnRequirement-maxServerVersion-type", "schemaVersion": "1.0", "runOnRequirements": [ { "maxServerVersion": 0 } ], "tests": [ { "description": "foo", "operations": [] } ] } runOnRequirement-minProperties.json000066400000000000000000000003061462766011000347230ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/unified-test-format/invalid{ "description": "runOnRequirement-minProperties", "schemaVersion": "1.0", "runOnRequirements": [ {} ], "tests": [ { "description": "foo", "operations": [] } ] } runOnRequirement-minServerVersion-pattern.json000066400000000000000000000003721462766011000370610ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/unified-test-format/invalid{ "description": "runOnRequirement-minServerVersion-pattern", "schemaVersion": "1.0", "runOnRequirements": [ { "minServerVersion": "1.2.3.4" } ], "tests": [ { "description": "foo", "operations": [] } ] } runOnRequirement-minServerVersion-type.json000066400000000000000000000003571462766011000363700ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/unified-test-format/invalid{ "description": "runOnRequirement-minServerVersion-type", "schemaVersion": "1.0", "runOnRequirements": [ { "minServerVersion": 0 } ], "tests": [ { "description": "foo", "operations": [] } ] } runOnRequirement-serverless-enum.json000066400000000000000000000003471462766011000352270ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/unified-test-format/invalid{ "description": "runOnRequirement-serverless-enum", "schemaVersion": "1.4", "runOnRequirements": [ { "serverless": "foo" } ], "tests": [ { "description": "foo", "operations": [] } ] } runOnRequirement-serverless-type.json000066400000000000000000000003461462766011000352430ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/unified-test-format/invalid{ "description": "runOnRequirement-serverless-type", "schemaVersion": "1.4", "runOnRequirements": [ { "serverless": 1234 } ], "tests": [ { "description": "foo", "operations": [] } ] } runOnRequirement-topologies-enum.json000066400000000000000000000003711462766011000352130ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/unified-test-format/invalid{ "description": "runOnRequirement-topologies-enum", "schemaVersion": "1.0", "runOnRequirements": [ { "topologies": [ "foo" ] } ], "tests": [ { "description": "foo", "operations": [] } ] } runOnRequirement-topologies-items.json000066400000000000000000000003661462766011000353740ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/unified-test-format/invalid{ "description": "runOnRequirement-topologies-items", "schemaVersion": "1.0", "runOnRequirements": [ { "topologies": [ 0 ] } ], "tests": [ { "description": "foo", "operations": [] } ] } runOnRequirement-topologies-minItems.json000066400000000000000000000003501462766011000360310ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/unified-test-format/invalid{ "description": "runOnRequirement-topologies-minItems", "schemaVersion": "1.0", "runOnRequirements": [ { "topologies": [] } ], "tests": [ { "description": "foo", "operations": [] } ] } runOnRequirement-topologies-type.json000066400000000000000000000003431462766011000352270ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/unified-test-format/invalid{ "description": "runOnRequirement-topologies-type", "schemaVersion": "1.0", "runOnRequirements": [ { "topologies": 0 } ], "tests": [ { "description": "foo", "operations": [] } ] } mongodb-mongo-python-driver-509e9b7/test/unified-test-format/invalid/runOnRequirements-items.json000066400000000000000000000002761462766011000334540ustar00rootroot00000000000000{ "description": "runOnRequirements-items", "schemaVersion": "1.0", "runOnRequirements": [ 0 ], "tests": [ { "description": "foo", "operations": [] } ] } mongodb-mongo-python-driver-509e9b7/test/unified-test-format/invalid/runOnRequirements-minItems.json000066400000000000000000000002701462766011000341120ustar00rootroot00000000000000{ "description": "runOnRequirements-minItems", "schemaVersion": "1.0", "runOnRequirements": [], "tests": [ { "description": "foo", "operations": [] } ] } mongodb-mongo-python-driver-509e9b7/test/unified-test-format/invalid/runOnRequirements-type.json000066400000000000000000000002631462766011000333100ustar00rootroot00000000000000{ "description": "runOnRequirements-type", "schemaVersion": "1.0", "runOnRequirements": 0, "tests": [ { "description": "foo", "operations": [] } ] } mongodb-mongo-python-driver-509e9b7/test/unified-test-format/invalid/schemaVersion-pattern.json000066400000000000000000000002341462766011000331030ustar00rootroot00000000000000{ "description": "schemaVersion-pattern", "schemaVersion": "1.2.3.4", "tests": [ { "description": "foo", "operations": [] } ] } mongodb-mongo-python-driver-509e9b7/test/unified-test-format/invalid/schemaVersion-required.json000066400000000000000000000001771462766011000332540ustar00rootroot00000000000000{ "description": "schemaVersion-required", "tests": [ { "description": "foo", "operations": [] } ] } mongodb-mongo-python-driver-509e9b7/test/unified-test-format/invalid/schemaVersion-type.json000066400000000000000000000002211462766011000324030ustar00rootroot00000000000000{ "description": "schemaVersion-type", "schemaVersion": 0, "tests": [ { "description": "foo", "operations": [] } ] } storeEventsAsEntity-additionalProperties.json000066400000000000000000000007161462766011000367350ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/unified-test-format/invalid{ "description": "storeEventsAsEntity-additionalProperties", "schemaVersion": "1.2", "createEntities": [ { "client": { "id": "client0", "storeEventsAsEntities": [ { "id": "client0_events", "events": [ "CommandStartedEvent" ], "foo": 0 } ] } } ], "tests": [ { "description": "foo", "operations": [] } ] } storeEventsAsEntity-events-enum.json000066400000000000000000000006371462766011000350200ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/unified-test-format/invalid{ "description": "storeEventsAsEntity-events-enum", "schemaVersion": "1.2", "createEntities": [ { "client": { "id": "client0", "storeEventsAsEntities": [ { "id": "client0_events", "events": [ "foo" ] } ] } } ], "tests": [ { "description": "foo", "operations": [] } ] } storeEventsAsEntity-events-minItems.json000066400000000000000000000006021462766011000356310ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/unified-test-format/invalid{ "description": "storeEventsAsEntity-events-minItems", "schemaVersion": "1.2", "createEntities": [ { "client": { "id": "client0", "storeEventsAsEntities": [ { "id": "client0_events", "events": [] } ] } } ], "tests": [ { "description": "foo", "operations": [] } ] } storeEventsAsEntity-events-required.json000066400000000000000000000005501462766011000356660ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/unified-test-format/invalid{ "description": "storeEventsAsEntity-events-required", "schemaVersion": "1.2", "createEntities": [ { "client": { "id": "client0", "storeEventsAsEntities": [ { "id": "client0_events" } ] } } ], "tests": [ { "description": "foo", "operations": [] } ] } storeEventsAsEntity-events-type.json000066400000000000000000000005751462766011000350360ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/unified-test-format/invalid{ "description": "storeEventsAsEntity-events-type", "schemaVersion": "1.2", "createEntities": [ { "client": { "id": "client0", "storeEventsAsEntities": [ { "id": "client0_events", "events": 0 } ] } } ], "tests": [ { "description": "foo", "operations": [] } ] } storeEventsAsEntity-id-required.json000066400000000000000000000006131462766011000347560ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/unified-test-format/invalid{ "description": "storeEventsAsEntity-id-required", "schemaVersion": "1.2", "createEntities": [ { "client": { "id": "client0", "storeEventsAsEntities": [ { "events": [ "CommandStartedEvent" ] } ] } } ], "tests": [ { "description": "foo", "operations": [] } ] } storeEventsAsEntity-id-type.json000066400000000000000000000006341462766011000341220ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/unified-test-format/invalid{ "description": "storeEventsAsEntity-id-type", "schemaVersion": "1.2", "createEntities": [ { "client": { "id": "client0", "storeEventsAsEntities": [ { "id": 0, "events": [ "CommandStartedEvent" ] } ] } } ], "tests": [ { "description": "foo", "operations": [] } ] } mongodb-mongo-python-driver-509e9b7/test/unified-test-format/invalid/test-additionalProperties.json000066400000000000000000000002541462766011000337660ustar00rootroot00000000000000{ "description": "test-additionalProperties", "schemaVersion": "1.0", "tests": [ { "description": "foo", "operations": [], "foo": 0 } ] } mongodb-mongo-python-driver-509e9b7/test/unified-test-format/invalid/test-description-required.json000066400000000000000000000001771462766011000337460ustar00rootroot00000000000000{ "description": "test-description-required", "schemaVersion": "1.0", "tests": [ { "operation": [] } ] } mongodb-mongo-python-driver-509e9b7/test/unified-test-format/invalid/test-description-type.json000066400000000000000000000002231462766011000330770ustar00rootroot00000000000000{ "description": "test-description-type", "schemaVersion": "1.0", "tests": [ { "description": 0, "operation": [] } ] } mongodb-mongo-python-driver-509e9b7/test/unified-test-format/invalid/test-expectEvents-items.json000066400000000000000000000003051462766011000333720ustar00rootroot00000000000000{ "description": "test-expectEvents-items", "schemaVersion": "1.0", "tests": [ { "description": "foo", "operations": [], "expectEvents": [ 0 ] } ] } mongodb-mongo-python-driver-509e9b7/test/unified-test-format/invalid/test-expectEvents-minItems.json000066400000000000000000000002671462766011000340450ustar00rootroot00000000000000{ "description": "test-expectEvents-minItems", "schemaVersion": "1.0", "tests": [ { "description": "foo", "operations": [], "expectEvents": [] } ] } mongodb-mongo-python-driver-509e9b7/test/unified-test-format/invalid/test-expectEvents-type.json000066400000000000000000000002621462766011000332340ustar00rootroot00000000000000{ "description": "test-expectEvents-type", "schemaVersion": "1.0", "tests": [ { "description": "foo", "operations": [], "expectEvents": 0 } ] } test-expectLogMessages-items.json000066400000000000000000000003201462766011000342550ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/unified-test-format/invalid{ "description": "test-expectLogMessages-items", "schemaVersion": "1.13", "tests": [ { "description": "foo", "operations": [], "expectLogMessages": [ 0 ] } ] } test-expectLogMessages-minItems.json000066400000000000000000000003021462766011000347210ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/unified-test-format/invalid{ "description": "test-expectLogMessages-minItems", "schemaVersion": "1.11", "tests": [ { "description": "foo", "operations": [], "expectLogMessages": [] } ] } test-expectLogMessages-type.json000066400000000000000000000002751462766011000341260ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/unified-test-format/invalid{ "description": "test-expectLogMessages-type", "schemaVersion": "1.13", "tests": [ { "description": "foo", "operations": [], "expectLogMessages": 0 } ] } mongodb-mongo-python-driver-509e9b7/test/unified-test-format/invalid/test-operations-items.json000066400000000000000000000002511462766011000331000ustar00rootroot00000000000000{ "description": "test-operations-items", "schemaVersion": "1.0", "tests": [ { "description": "foo", "operations": [ 0 ] } ] } mongodb-mongo-python-driver-509e9b7/test/unified-test-format/invalid/test-operations-required.json000066400000000000000000000002031462766011000335740ustar00rootroot00000000000000{ "description": "test-operations-required", "schemaVersion": "1.0", "tests": [ { "description": "foo" } ] } mongodb-mongo-python-driver-509e9b7/test/unified-test-format/invalid/test-operations-type.json000066400000000000000000000002261462766011000327420ustar00rootroot00000000000000{ "description": "test-operations-type", "schemaVersion": "1.0", "tests": [ { "description": "foo", "operations": 0 } ] } mongodb-mongo-python-driver-509e9b7/test/unified-test-format/invalid/test-outcome-items.json000066400000000000000000000002731462766011000323740ustar00rootroot00000000000000{ "description": "test-outcome-items", "schemaVersion": "1.0", "tests": [ { "description": "foo", "operations": [], "outcome": [ 0 ] } ] } mongodb-mongo-python-driver-509e9b7/test/unified-test-format/invalid/test-outcome-minItems.json000066400000000000000000000002551462766011000330400ustar00rootroot00000000000000{ "description": "test-outcome-minItems", "schemaVersion": "1.0", "tests": [ { "description": "foo", "operations": [], "outcome": [] } ] } mongodb-mongo-python-driver-509e9b7/test/unified-test-format/invalid/test-outcome-type.json000066400000000000000000000002501462766011000322270ustar00rootroot00000000000000{ "description": "test-outcome-type", "schemaVersion": "1.0", "tests": [ { "description": "foo", "operations": [], "outcome": 0 } ] } test-runOnRequirements-items.json000066400000000000000000000003171462766011000343460ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/unified-test-format/invalid{ "description": "test-runOnRequirements-items", "schemaVersion": "1.0", "tests": [ { "description": "foo", "operations": [], "runOnRequirements": [ 0 ] } ] } test-runOnRequirements-minItems.json000066400000000000000000000003011462766011000350030ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/unified-test-format/invalid{ "description": "test-runOnRequirements-minItems", "schemaVersion": "1.0", "tests": [ { "description": "foo", "operations": [], "runOnRequirements": [] } ] } test-runOnRequirements-type.json000066400000000000000000000002741462766011000342100ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/unified-test-format/invalid{ "description": "test-runOnRequirements-type", "schemaVersion": "1.0", "tests": [ { "description": "foo", "operations": [], "runOnRequirements": 0 } ] } mongodb-mongo-python-driver-509e9b7/test/unified-test-format/invalid/test-skipReason-type.json000066400000000000000000000002561462766011000327000ustar00rootroot00000000000000{ "description": "test-skipReason-type", "schemaVersion": "1.0", "tests": [ { "description": "foo", "operations": [], "skipReason": 0 } ] } mongodb-mongo-python-driver-509e9b7/test/unified-test-format/invalid/tests-items.json000066400000000000000000000001251462766011000311020ustar00rootroot00000000000000{ "description": "tests-items", "schemaVersion": "1.0", "tests": [ 0 ] } mongodb-mongo-python-driver-509e9b7/test/unified-test-format/invalid/tests-minItems.json000066400000000000000000000001171462766011000315470ustar00rootroot00000000000000{ "description": "tests-minItems", "schemaVersion": "1.0", "tests": [] } mongodb-mongo-python-driver-509e9b7/test/unified-test-format/invalid/tests-required.json000066400000000000000000000001001462766011000315720ustar00rootroot00000000000000{ "description": "tests-required", "schemaVersion": "1.0" } mongodb-mongo-python-driver-509e9b7/test/unified-test-format/invalid/tests-type.json000066400000000000000000000001121462766011000307360ustar00rootroot00000000000000{ "description": "tests-type", "schemaVersion": "1.0", "tests": 0 } mongodb-mongo-python-driver-509e9b7/test/unified-test-format/valid-fail/000077500000000000000000000000001462766011000263125ustar00rootroot00000000000000assertNumberConnectionsCheckedOut.json000066400000000000000000000026361462766011000357510ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/unified-test-format/valid-fail{ "description": "assertNumberConnectionsCheckedOut", "schemaVersion": "1.3", "createEntities": [ { "client": { "id": "client0", "useMultipleMongoses": true } } ], "tests": [ { "description": "operation fails if client field is not specified", "operations": [ { "name": "assertNumberConnectionsCheckedOut", "object": "testRunner", "arguments": { "connections": 1 } } ] }, { "description": "operation fails if connections field is not specified", "operations": [ { "name": "assertNumberConnectionsCheckedOut", "object": "testRunner", "arguments": { "client": "client0" } } ] }, { "description": "operation fails if client entity does not exist", "operations": [ { "name": "assertNumberConnectionsCheckedOut", "object": "testRunner", "arguments": { "client": "client1" } } ] }, { "description": "operation fails if number of connections is incorrect", "operations": [ { "name": "assertNumberConnectionsCheckedOut", "object": "testRunner", "arguments": { "client": "client0", "connections": 1 } } ] } ] } entity-bucket-database-undefined.json000066400000000000000000000004271462766011000354210ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/unified-test-format/valid-fail{ "description": "entity-bucket-database-undefined", "schemaVersion": "1.0", "createEntities": [ { "bucket": { "id": "bucket0", "database": "foo" } } ], "tests": [ { "description": "foo", "operations": [] } ] } entity-client-apiVersion-unsupported.json000066400000000000000000000005441462766011000364240ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/unified-test-format/valid-fail{ "description": "entity-client-apiVersion-unsupported", "schemaVersion": "1.1", "createEntities": [ { "client": { "id": "client0", "serverApi": { "version": "server_will_never_support_this_api_version" } } } ], "tests": [ { "description": "foo", "operations": [] } ] } entity-client-storeEventsAsEntities-conflict_with_client_id.json000066400000000000000000000010441462766011000430710ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/unified-test-format/valid-fail{ "description": "entity-client-storeEventsAsEntities-conflict_with_client_id", "schemaVersion": "1.2", "createEntities": [ { "client": { "id": "client0", "storeEventsAsEntities": [ { "id": "client0", "events": [ "PoolCreatedEvent", "PoolReadyEvent", "PoolClearedEvent", "PoolClosedEvent" ] } ] } } ], "tests": [ { "description": "foo", "operations": [] } ] } entity-client-storeEventsAsEntities-conflict_within_different_array.json000066400000000000000000000015411462766011000446340ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/unified-test-format/valid-fail{ "description": "entity-client-storeEventsAsEntities-conflict_within_different_array", "schemaVersion": "1.2", "createEntities": [ { "client": { "id": "client0", "storeEventsAsEntities": [ { "id": "events", "events": [ "PoolCreatedEvent", "PoolReadyEvent", "PoolClearedEvent", "PoolClosedEvent" ] } ] } }, { "client": { "id": "client1", "storeEventsAsEntities": [ { "id": "events", "events": [ "CommandStartedEvent", "CommandSucceededEvent", "CommandFailedEvent" ] } ] } } ], "tests": [ { "description": "foo", "operations": [] } ] } entity-client-storeEventsAsEntities-conflict_within_same_array.json000066400000000000000000000013601462766011000436120ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/unified-test-format/valid-fail{ "description": "entity-client-storeEventsAsEntities-conflict_within_same_array", "schemaVersion": "1.2", "createEntities": [ { "client": { "id": "client0", "storeEventsAsEntities": [ { "id": "events", "events": [ "PoolCreatedEvent", "PoolReadyEvent", "PoolClearedEvent", "PoolClosedEvent" ] }, { "id": "events", "events": [ "CommandStartedEvent", "CommandSucceededEvent", "CommandFailedEvent" ] } ] } } ], "tests": [ { "description": "foo", "operations": [] } ] } entity-collection-database-undefined.json000066400000000000000000000005041462766011000362730ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/unified-test-format/valid-fail{ "description": "entity-collection-database-undefined", "schemaVersion": "1.0", "createEntities": [ { "collection": { "id": "collection0", "database": "foo", "collectionName": "foo" } } ], "tests": [ { "description": "foo", "operations": [] } ] } entity-database-client-undefined.json000066400000000000000000000004701462766011000354200ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/unified-test-format/valid-fail{ "description": "entity-database-client-undefined", "schemaVersion": "1.0", "createEntities": [ { "database": { "id": "database0", "client": "foo", "databaseName": "foo" } } ], "tests": [ { "description": "foo", "operations": [] } ] } entity-findCursor-malformed.json000066400000000000000000000015111462766011000345200ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/unified-test-format/valid-fail{ "description": "entity-findCursor-malformed", "schemaVersion": "1.3", "createEntities": [ { "client": { "id": "client0" } }, { "database": { "id": "database0", "client": "client0", "databaseName": "database0Name" } }, { "collection": { "id": "collection0", "database": "database0", "collectionName": "coll0" } } ], "initialData": [ { "databaseName": "database0Name", "collectionName": "coll0", "documents": [] } ], "tests": [ { "description": "createFindCursor fails if filter is not specified", "operations": [ { "name": "createFindCursor", "object": "collection0", "saveResultAsEntity": "cursor0" } ] } ] } mongodb-mongo-python-driver-509e9b7/test/unified-test-format/valid-fail/entity-findCursor.json000066400000000000000000000017631462766011000326440ustar00rootroot00000000000000{ "description": "entity-findCursor", "schemaVersion": "1.3", "createEntities": [ { "client": { "id": "client0" } }, { "database": { "id": "database0", "client": "client0", "databaseName": "database0Name" } }, { "collection": { "id": "collection0", "database": "database0", "collectionName": "coll0" } } ], "initialData": [ { "databaseName": "database0Name", "collectionName": "coll0", "documents": [] } ], "tests": [ { "description": "iterateUntilDocumentOrError fails if it references a nonexistent entity", "operations": [ { "name": "iterateUntilDocumentOrError", "object": "cursor0" } ] }, { "description": "close fails if it references a nonexistent entity", "operations": [ { "name": "close", "object": "cursor0" } ] } ] } entity-session-client-undefined.json000066400000000000000000000004261462766011000353400ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/unified-test-format/valid-fail{ "description": "entity-session-client-undefined", "schemaVersion": "1.0", "createEntities": [ { "session": { "id": "session0", "client": "foo" } } ], "tests": [ { "description": "foo", "operations": [] } ] } ignoreResultAndError-malformed.json000066400000000000000000000016561462766011000352210ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/unified-test-format/valid-fail{ "description": "ignoreResultAndError-malformed", "schemaVersion": "1.3", "createEntities": [ { "client": { "id": "client0", "useMultipleMongoses": true } }, { "database": { "id": "database0", "client": "client0", "databaseName": "database0Name" } }, { "collection": { "id": "collection0", "database": "database0", "collectionName": "coll0" } } ], "initialData": [ { "collectionName": "coll0", "databaseName": "database0Name", "documents": [] } ], "tests": [ { "description": "malformed operation fails if ignoreResultAndError is true", "operations": [ { "name": "insertOne", "object": "collection0", "arguments": { "foo": "bar" }, "ignoreResultAndError": true } ] } ] } mongodb-mongo-python-driver-509e9b7/test/unified-test-format/valid-fail/ignoreResultAndError.json000066400000000000000000000022161462766011000333250ustar00rootroot00000000000000{ "description": "ignoreResultAndError", "schemaVersion": "1.3", "createEntities": [ { "client": { "id": "client0", "useMultipleMongoses": true } }, { "database": { "id": "database0", "client": "client0", "databaseName": "database0Name" } }, { "collection": { "id": "collection0", "database": "database0", "collectionName": "coll0" } } ], "initialData": [ { "collectionName": "coll0", "databaseName": "database0Name", "documents": [] } ], "tests": [ { "description": "operation errors are not ignored if ignoreResultAndError is false", "operations": [ { "name": "insertOne", "object": "collection0", "arguments": { "document": { "_id": 1 } } }, { "name": "insertOne", "object": "collection0", "arguments": { "document": { "_id": 1 } }, "ignoreResultAndError": false } ] } ] } kmsProviders-missing_aws_kms_credentials.json000066400000000000000000000012201462766011000373610ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/unified-test-format/valid-fail{ "description": "kmsProviders-missing_aws_kms_credentials", "schemaVersion": "1.8", "runOnRequirements": [ { "csfle": true } ], "createEntities": [ { "client": { "id": "client0" } }, { "clientEncryption": { "id": "clientEncryption0", "clientEncryptionOpts": { "keyVaultClient": "client0", "keyVaultNamespace": "keyvault.datakeys", "kmsProviders": { "aws": { "accessKeyId": "accessKeyId" } } } } } ], "tests": [ { "description": "", "operations": [] } ] } kmsProviders-missing_azure_kms_credentials.json000066400000000000000000000012161462766011000377220ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/unified-test-format/valid-fail{ "description": "kmsProviders-missing_azure_kms_credentials", "schemaVersion": "1.8", "runOnRequirements": [ { "csfle": true } ], "createEntities": [ { "client": { "id": "client0" } }, { "clientEncryption": { "id": "clientEncryption0", "clientEncryptionOpts": { "keyVaultClient": "client0", "keyVaultNamespace": "keyvault.datakeys", "kmsProviders": { "azure": { "tenantId": "tenantId" } } } } } ], "tests": [ { "description": "", "operations": [] } ] } kmsProviders-missing_gcp_kms_credentials.json000066400000000000000000000012041462766011000373420ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/unified-test-format/valid-fail{ "description": "kmsProviders-missing_gcp_kms_credentials", "schemaVersion": "1.8", "runOnRequirements": [ { "csfle": true } ], "createEntities": [ { "client": { "id": "client0" } }, { "clientEncryption": { "id": "clientEncryption0", "clientEncryptionOpts": { "keyVaultClient": "client0", "keyVaultNamespace": "keyvault.datakeys", "kmsProviders": { "gcp": { "email": "email" } } } } } ], "tests": [ { "description": "", "operations": [] } ] } mongodb-mongo-python-driver-509e9b7/test/unified-test-format/valid-fail/kmsProviders-no_kms.json000066400000000000000000000010521462766011000331570ustar00rootroot00000000000000{ "description": "clientEncryptionOpts-no_kms", "schemaVersion": "1.8", "runOnRequirements": [ { "csfle": true } ], "createEntities": [ { "client": { "id": "client0" } }, { "clientEncryption": { "id": "clientEncryption0", "clientEncryptionOpts": { "keyVaultClient": "client0", "keyVaultNamespace": "keyvault.datakeys", "kmsProviders": {} } } } ], "tests": [ { "description": "", "operations": [] } ] } mongodb-mongo-python-driver-509e9b7/test/unified-test-format/valid-fail/operation-failure.json000066400000000000000000000020731462766011000326340ustar00rootroot00000000000000{ "description": "operation-failure", "schemaVersion": "1.0", "createEntities": [ { "client": { "id": "client0" } }, { "database": { "id": "database0", "client": "client0", "databaseName": "operation-failure" } }, { "collection": { "id": "collection0", "database": "database0", "collectionName": "coll0" } } ], "tests": [ { "description": "Unsupported command", "operations": [ { "name": "runCommand", "object": "database0", "arguments": { "commandName": "unsupportedCommand", "command": { "unsupportedCommand": 1 } } } ] }, { "description": "Unsupported query operator", "operations": [ { "name": "find", "object": "collection0", "arguments": { "filter": { "$unsupportedQueryOperator": 1 } } } ] } ] } mongodb-mongo-python-driver-509e9b7/test/unified-test-format/valid-fail/operation-unsupported.json000066400000000000000000000005461462766011000336000ustar00rootroot00000000000000{ "description": "operation-unsupported", "schemaVersion": "1.0", "createEntities": [ { "client": { "id": "client0" } } ], "tests": [ { "description": "Unsupported operation", "operations": [ { "name": "unsupportedOperation", "object": "client0" } ] } ] } returnDocument-enum-invalid.json000066400000000000000000000025001462766011000345270ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/unified-test-format/valid-fail{ "description": "returnDocument-enum-invalid", "schemaVersion": "1.0", "createEntities": [ { "client": { "id": "client0" } }, { "database": { "id": "database0", "client": "client0", "databaseName": "test" } }, { "collection": { "id": "collection0", "database": "database0", "collectionName": "coll" } } ], "tests": [ { "description": "FindOneAndReplace returnDocument invalid enum value", "operations": [ { "name": "findOneAndReplace", "object": "collection0", "arguments": { "filter": { "_id": 1 }, "replacement": { "_id": 1, "x": 111 }, "returnDocument": "invalid" } } ] }, { "description": "FindOneAndUpdate returnDocument invalid enum value", "operations": [ { "name": "findOneAndUpdate", "object": "collection0", "arguments": { "filter": { "_id": 1 }, "update": { "$inc": { "x": 1 } }, "returnDocument": "invalid" } } ] } ] } schemaVersion-unsupported.json000066400000000000000000000002341462766011000343210ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/unified-test-format/valid-fail{ "description": "schemaVersion-unsupported", "schemaVersion": "0.1", "tests": [ { "description": "foo", "operations": [] } ] } mongodb-mongo-python-driver-509e9b7/test/unified-test-format/valid-pass/000077500000000000000000000000001462766011000263455ustar00rootroot00000000000000assertNumberConnectionsCheckedOut.json000066400000000000000000000010161462766011000357730ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/unified-test-format/valid-pass{ "description": "assertNumberConnectionsCheckedOut", "schemaVersion": "1.3", "createEntities": [ { "client": { "id": "client0", "useMultipleMongoses": true } } ], "tests": [ { "description": "basic assertion succeeds", "operations": [ { "name": "assertNumberConnectionsCheckedOut", "object": "testRunner", "arguments": { "client": "client0", "connections": 0 } } ] } ] } collectionData-createOptions.json000066400000000000000000000030051462766011000347210ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/unified-test-format/valid-pass{ "description": "collectionData-createOptions", "schemaVersion": "1.9", "runOnRequirements": [ { "minServerVersion": "3.6", "serverless": "forbid" } ], "createEntities": [ { "client": { "id": "client0" } }, { "database": { "id": "database0", "client": "client0", "databaseName": "database0" } }, { "collection": { "id": "collection0", "database": "database0", "collectionName": "coll0" } } ], "initialData": [ { "collectionName": "coll0", "databaseName": "database0", "createOptions": { "capped": true, "size": 4096 }, "documents": [ { "_id": 1, "x": 11 } ] } ], "tests": [ { "description": "collection is created with the correct options", "operations": [ { "object": "collection0", "name": "aggregate", "arguments": { "pipeline": [ { "$collStats": { "storageStats": {} } }, { "$project": { "capped": "$storageStats.capped", "maxSize": "$storageStats.maxSize" } } ] }, "expectResult": [ { "capped": true, "maxSize": 4096 } ] } ] } ] } createEntities-operation.json000066400000000000000000000033211462766011000341260ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/unified-test-format/valid-pass{ "description": "createEntities-operation", "schemaVersion": "1.9", "tests": [ { "description": "createEntities operation", "operations": [ { "name": "createEntities", "object": "testRunner", "arguments": { "entities": [ { "client": { "id": "client1", "observeEvents": [ "commandStartedEvent" ] } }, { "database": { "id": "database1", "client": "client1", "databaseName": "database1" } }, { "collection": { "id": "collection1", "database": "database1", "collectionName": "coll1" } } ] } }, { "name": "deleteOne", "object": "collection1", "arguments": { "filter": { "_id": 1 } } } ], "expectEvents": [ { "client": "client1", "events": [ { "commandStartedEvent": { "command": { "delete": "coll1", "deletes": [ { "q": { "_id": 1 }, "limit": 1 } ] }, "commandName": "delete", "databaseName": "database1" } } ] } ] } ] } entity-client-cmap-events.json000066400000000000000000000026261462766011000341770ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/unified-test-format/valid-pass{ "description": "entity-client-cmap-events", "schemaVersion": "1.3", "createEntities": [ { "client": { "id": "client0", "useMultipleMongoses": true, "observeEvents": [ "connectionReadyEvent", "connectionCheckedOutEvent", "connectionCheckedInEvent" ] } }, { "database": { "id": "database0", "client": "client0", "databaseName": "database0Name" } }, { "collection": { "id": "collection0", "database": "database0", "collectionName": "coll0" } } ], "initialData": [ { "collectionName": "coll0", "databaseName": "database0Name", "documents": [] } ], "tests": [ { "description": "events are captured during an operation", "operations": [ { "name": "insertOne", "object": "collection0", "arguments": { "document": { "x": 1 } } } ], "expectEvents": [ { "client": "client0", "eventType": "cmap", "events": [ { "connectionReadyEvent": {} }, { "connectionCheckedOutEvent": {} }, { "connectionCheckedInEvent": {} } ] } ] } ] } entity-client-storeEventsAsEntities.json000066400000000000000000000023561462766011000362670ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/unified-test-format/valid-pass{ "description": "entity-client-storeEventsAsEntities", "schemaVersion": "1.2", "createEntities": [ { "client": { "id": "client0", "storeEventsAsEntities": [ { "id": "client0_events", "events": [ "CommandStartedEvent", "CommandSucceededEvent", "CommandFailedEvent" ] } ] } }, { "database": { "id": "database0", "client": "client0", "databaseName": "test" } }, { "collection": { "id": "collection0", "database": "database0", "collectionName": "coll0" } } ], "initialData": [ { "collectionName": "coll0", "databaseName": "test", "documents": [ { "_id": 1, "x": 11 } ] } ], "tests": [ { "description": "storeEventsAsEntities captures events", "operations": [ { "name": "find", "object": "collection0", "arguments": { "filter": {} }, "expectResult": [ { "_id": 1, "x": 11 } ] } ] } ] } mongodb-mongo-python-driver-509e9b7/test/unified-test-format/valid-pass/entity-commandCursor.json000066400000000000000000000145151462766011000333740ustar00rootroot00000000000000{ "description": "entity-commandCursor", "schemaVersion": "1.3", "createEntities": [ { "client": { "id": "client", "useMultipleMongoses": false, "observeEvents": [ "commandStartedEvent" ] } }, { "database": { "id": "db", "client": "client", "databaseName": "db" } }, { "collection": { "id": "collection", "database": "db", "collectionName": "collection" } } ], "initialData": [ { "collectionName": "collection", "databaseName": "db", "documents": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 22 }, { "_id": 3, "x": 33 }, { "_id": 4, "x": 44 }, { "_id": 5, "x": 55 } ] } ], "tests": [ { "description": "runCursorCommand creates and exhausts cursor by running getMores", "operations": [ { "name": "runCursorCommand", "object": "db", "arguments": { "commandName": "find", "batchSize": 2, "command": { "find": "collection", "filter": {}, "batchSize": 2 } }, "expectResult": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 22 }, { "_id": 3, "x": 33 }, { "_id": 4, "x": 44 }, { "_id": 5, "x": 55 } ] } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "command": { "find": "collection", "filter": {}, "batchSize": 2, "$db": "db", "lsid": { "$$exists": true } }, "commandName": "find" } }, { "commandStartedEvent": { "command": { "getMore": { "$$type": [ "int", "long" ] }, "collection": "collection", "$db": "db", "lsid": { "$$exists": true } }, "commandName": "getMore" } }, { "commandStartedEvent": { "command": { "getMore": { "$$type": [ "int", "long" ] }, "collection": "collection", "$db": "db", "lsid": { "$$exists": true } }, "commandName": "getMore" } } ] } ] }, { "description": "createCommandCursor creates a cursor and stores it as an entity that can be iterated one document at a time", "operations": [ { "name": "createCommandCursor", "object": "db", "arguments": { "commandName": "find", "batchSize": 2, "command": { "find": "collection", "filter": {}, "batchSize": 2 } }, "saveResultAsEntity": "myRunCommandCursor" }, { "name": "iterateUntilDocumentOrError", "object": "myRunCommandCursor", "expectResult": { "_id": 1, "x": 11 } }, { "name": "iterateUntilDocumentOrError", "object": "myRunCommandCursor", "expectResult": { "_id": 2, "x": 22 } }, { "name": "iterateUntilDocumentOrError", "object": "myRunCommandCursor", "expectResult": { "_id": 3, "x": 33 } }, { "name": "iterateUntilDocumentOrError", "object": "myRunCommandCursor", "expectResult": { "_id": 4, "x": 44 } }, { "name": "iterateUntilDocumentOrError", "object": "myRunCommandCursor", "expectResult": { "_id": 5, "x": 55 } } ] }, { "description": "createCommandCursor's cursor can be closed and will perform a killCursors operation", "operations": [ { "name": "createCommandCursor", "object": "db", "arguments": { "commandName": "find", "batchSize": 2, "command": { "find": "collection", "filter": {}, "batchSize": 2 } }, "saveResultAsEntity": "myRunCommandCursor" }, { "name": "iterateUntilDocumentOrError", "object": "myRunCommandCursor", "expectResult": { "_id": 1, "x": 11 } }, { "name": "close", "object": "myRunCommandCursor" } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "command": { "find": "collection", "filter": {}, "batchSize": 2, "$db": "db", "lsid": { "$$exists": true } }, "commandName": "find" } }, { "commandStartedEvent": { "command": { "killCursors": "collection", "cursors": { "$$type": "array" } }, "commandName": "killCursors" } } ] } ] } ] } entity-cursor-iterateOnce.json000066400000000000000000000043711462766011000342550ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/unified-test-format/valid-pass{ "description": "entity-cursor-iterateOnce", "schemaVersion": "1.9", "createEntities": [ { "client": { "id": "client0", "observeEvents": [ "commandStartedEvent" ] } }, { "database": { "id": "database0", "client": "client0", "databaseName": "database0" } }, { "collection": { "id": "collection0", "database": "database0", "collectionName": "coll0" } } ], "initialData": [ { "databaseName": "database0", "collectionName": "coll0", "documents": [ { "_id": 1 }, { "_id": 2 }, { "_id": 3 } ] } ], "tests": [ { "description": "iterateOnce", "operations": [ { "name": "createFindCursor", "object": "collection0", "arguments": { "filter": {}, "batchSize": 2 }, "saveResultAsEntity": "cursor0" }, { "name": "iterateUntilDocumentOrError", "object": "cursor0", "expectResult": { "_id": 1 } }, { "name": "iterateUntilDocumentOrError", "object": "cursor0", "expectResult": { "_id": 2 } }, { "name": "iterateOnce", "object": "cursor0" } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "find": "coll0", "filter": {}, "batchSize": 2 }, "commandName": "find", "databaseName": "database0" } }, { "commandStartedEvent": { "command": { "getMore": { "$$type": [ "int", "long" ] }, "collection": "coll0" }, "commandName": "getMore" } } ] } ] } ] } mongodb-mongo-python-driver-509e9b7/test/unified-test-format/valid-pass/entity-find-cursor.json000066400000000000000000000105401462766011000330050ustar00rootroot00000000000000{ "description": "entity-find-cursor", "schemaVersion": "1.3", "createEntities": [ { "client": { "id": "client0", "observeEvents": [ "commandStartedEvent", "commandSucceededEvent", "commandFailedEvent" ] } }, { "database": { "id": "database0", "client": "client0", "databaseName": "database0Name" } }, { "collection": { "id": "collection0", "database": "database0", "collectionName": "coll0" } } ], "initialData": [ { "databaseName": "database0Name", "collectionName": "coll0", "documents": [ { "_id": 1 }, { "_id": 2 }, { "_id": 3 }, { "_id": 4 }, { "_id": 5 } ] } ], "tests": [ { "description": "cursors can be created, iterated, and closed", "operations": [ { "name": "createFindCursor", "object": "collection0", "arguments": { "filter": {}, "batchSize": 2 }, "saveResultAsEntity": "cursor0" }, { "name": "iterateUntilDocumentOrError", "object": "cursor0", "expectResult": { "_id": 1 } }, { "name": "iterateUntilDocumentOrError", "object": "cursor0", "expectResult": { "_id": 2 } }, { "name": "iterateUntilDocumentOrError", "object": "cursor0", "expectResult": { "_id": 3 } }, { "name": "close", "object": "cursor0" } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "find": "coll0", "filter": {}, "batchSize": 2 }, "commandName": "find", "databaseName": "database0Name" } }, { "commandSucceededEvent": { "reply": { "cursor": { "id": { "$$type": [ "int", "long" ] }, "ns": { "$$type": "string" }, "firstBatch": { "$$type": "array" } } }, "commandName": "find" } }, { "commandStartedEvent": { "command": { "getMore": { "$$type": [ "int", "long" ] }, "collection": "coll0" }, "commandName": "getMore" } }, { "commandSucceededEvent": { "reply": { "cursor": { "id": { "$$type": [ "int", "long" ] }, "ns": { "$$type": "string" }, "nextBatch": { "$$type": "array" } } }, "commandName": "getMore" } }, { "commandStartedEvent": { "command": { "killCursors": "coll0", "cursors": { "$$type": "array" } }, "commandName": "killCursors" } }, { "commandSucceededEvent": { "reply": { "cursorsKilled": { "$$unsetOrMatches": { "$$type": "array" } } }, "commandName": "killCursors" } } ] } ] } ] } expectedError-errorResponse.json000066400000000000000000000025751462766011000346530ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/unified-test-format/valid-pass{ "description": "expectedError-errorResponse", "schemaVersion": "1.12", "createEntities": [ { "client": { "id": "client0" } }, { "database": { "id": "database0", "client": "client0", "databaseName": "test" } }, { "collection": { "id": "collection0", "database": "database0", "collectionName": "coll0" } } ], "tests": [ { "description": "Unsupported command", "operations": [ { "name": "runCommand", "object": "database0", "arguments": { "commandName": "unsupportedCommand", "command": { "unsupportedCommand": 1 } }, "expectError": { "errorResponse": { "errmsg": { "$$type": "string" } } } } ] }, { "description": "Unsupported query operator", "operations": [ { "name": "find", "object": "collection0", "arguments": { "filter": { "$unsupportedQueryOperator": 1 } }, "expectError": { "errorResponse": { "errmsg": { "$$type": "string" } } } } ] } ] } expectedEventsForClient-eventType.json000066400000000000000000000051141462766011000357370ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/unified-test-format/valid-pass{ "description": "expectedEventsForClient-eventType", "schemaVersion": "1.3", "createEntities": [ { "client": { "id": "client0", "useMultipleMongoses": true, "observeEvents": [ "commandStartedEvent", "connectionReadyEvent" ] } }, { "database": { "id": "database0", "client": "client0", "databaseName": "database0Name" } }, { "collection": { "id": "collection0", "database": "database0", "collectionName": "coll0" } } ], "initialData": [ { "collectionName": "coll0", "databaseName": "database0Name", "documents": [] } ], "tests": [ { "description": "eventType can be set to command and cmap", "operations": [ { "name": "insertOne", "object": "collection0", "arguments": { "document": { "_id": 1 } } } ], "expectEvents": [ { "client": "client0", "eventType": "command", "events": [ { "commandStartedEvent": { "command": { "insert": "coll0", "documents": [ { "_id": 1 } ] }, "commandName": "insert" } } ] }, { "client": "client0", "eventType": "cmap", "events": [ { "connectionReadyEvent": {} } ] } ] }, { "description": "eventType defaults to command if unset", "operations": [ { "name": "insertOne", "object": "collection0", "arguments": { "document": { "_id": 1 } } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "insert": "coll0", "documents": [ { "_id": 1 } ] }, "commandName": "insert" } } ] }, { "client": "client0", "eventType": "cmap", "events": [ { "connectionReadyEvent": {} } ] } ] } ] } expectedEventsForClient-ignoreExtraEvents.json000066400000000000000000000062151462766011000374330ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/unified-test-format/valid-pass{ "description": "expectedEventsForClient-ignoreExtraEvents", "schemaVersion": "1.7", "createEntities": [ { "client": { "id": "client0", "useMultipleMongoses": true, "observeEvents": [ "commandStartedEvent" ] } }, { "database": { "id": "database0", "client": "client0", "databaseName": "database0Name" } }, { "collection": { "id": "collection0", "database": "database0", "collectionName": "coll0" } } ], "initialData": [ { "collectionName": "coll0", "databaseName": "database0Name", "documents": [] } ], "tests": [ { "description": "ignoreExtraEvents can be set to false", "operations": [ { "name": "insertOne", "object": "collection0", "arguments": { "document": { "_id": 1 } } } ], "expectEvents": [ { "client": "client0", "ignoreExtraEvents": false, "events": [ { "commandStartedEvent": { "command": { "insert": "coll0", "documents": [ { "_id": 1 } ] }, "commandName": "insert" } } ] } ] }, { "description": "ignoreExtraEvents can be set to true", "operations": [ { "name": "insertOne", "object": "collection0", "arguments": { "document": { "_id": 2 } } }, { "name": "insertOne", "object": "collection0", "arguments": { "document": { "_id": 3 } } } ], "expectEvents": [ { "client": "client0", "ignoreExtraEvents": true, "events": [ { "commandStartedEvent": { "command": { "insert": "coll0", "documents": [ { "_id": 2 } ] }, "commandName": "insert" } } ] } ] }, { "description": "ignoreExtraEvents defaults to false if unset", "operations": [ { "name": "insertOne", "object": "collection0", "arguments": { "document": { "_id": 4 } } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "insert": "coll0", "documents": [ { "_id": 4 } ] }, "commandName": "insert" } } ] } ] } ] } expectedEventsForClient-topologyDescriptionChangedEvent.json000066400000000000000000000031141462766011000423060ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/unified-test-format/valid-pass{ "description": "expectedEventsForClient-topologyDescriptionChangedEvent", "schemaVersion": "1.20", "runOnRequirements": [ { "topologies": [ "replicaset" ], "minServerVersion": "4.4" } ], "tests": [ { "description": "can assert on values of newDescription and previousDescription fields", "operations": [ { "name": "createEntities", "object": "testRunner", "arguments": { "entities": [ { "client": { "id": "client", "uriOptions": { "directConnection": true }, "observeEvents": [ "topologyDescriptionChangedEvent" ] } } ] } }, { "name": "waitForEvent", "object": "testRunner", "arguments": { "client": "client", "event": { "topologyDescriptionChangedEvent": {} }, "count": 1 } } ], "expectEvents": [ { "client": "client", "eventType": "sdam", "ignoreExtraEvents": true, "events": [ { "topologyDescriptionChangedEvent": { "previousDescription": { "type": "Unknown" }, "newDescription": { "type": "Single" } } } ] } ] } ] } mongodb-mongo-python-driver-509e9b7/test/unified-test-format/valid-pass/ignoreResultAndError.json000066400000000000000000000022101462766011000333520ustar00rootroot00000000000000{ "description": "ignoreResultAndError", "schemaVersion": "1.3", "createEntities": [ { "client": { "id": "client0", "useMultipleMongoses": true } }, { "database": { "id": "database0", "client": "client0", "databaseName": "database0Name" } }, { "collection": { "id": "collection0", "database": "database0", "collectionName": "coll0" } } ], "initialData": [ { "collectionName": "coll0", "databaseName": "database0Name", "documents": [] } ], "tests": [ { "description": "operation errors are ignored if ignoreResultAndError is true", "operations": [ { "name": "insertOne", "object": "collection0", "arguments": { "document": { "_id": 1 } } }, { "name": "insertOne", "object": "collection0", "arguments": { "document": { "_id": 1 } }, "ignoreResultAndError": true } ] } ] } kmsProviders-explicit_kms_credentials.json000066400000000000000000000023331462766011000367200ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/unified-test-format/valid-pass{ "description": "kmsProviders-explicit_kms_credentials", "schemaVersion": "1.8", "runOnRequirements": [ { "csfle": true } ], "createEntities": [ { "client": { "id": "client0" } }, { "clientEncryption": { "id": "clientEncryption0", "clientEncryptionOpts": { "keyVaultClient": "client0", "keyVaultNamespace": "keyvault.datakeys", "kmsProviders": { "aws": { "accessKeyId": "accessKeyId", "secretAccessKey": "secretAccessKey" }, "azure": { "tenantId": "tenantId", "clientId": "clientId", "clientSecret": "clientSecret" }, "gcp": { "email": "email", "privateKey": "cHJpdmF0ZUtleQo=" }, "kmip": { "endpoint": "endpoint" }, "local": { "key": "a2V5a2V5a2V5a2V5a2V5a2V5a2V5a2V5a2V5a2V5a2V5a2V5a2V5a2V5a2V5a2V5a2V5a2V5a2V5a2V5a2V5a2V5a2V5a2V5a2V5a2V5a2V5a2V5a2V5a2V5a2V5a2V5" } } } } } ], "tests": [ { "description": "", "operations": [] } ] } kmsProviders-mixed_kms_credential_fields.json000066400000000000000000000021531462766011000373500ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/unified-test-format/valid-pass{ "description": "kmsProviders-mixed_kms_credential_fields", "schemaVersion": "1.8", "runOnRequirements": [ { "csfle": true } ], "createEntities": [ { "client": { "id": "client0" } }, { "clientEncryption": { "id": "clientEncryption0", "clientEncryptionOpts": { "keyVaultClient": "client0", "keyVaultNamespace": "keyvault.datakeys", "kmsProviders": { "aws": { "accessKeyId": "accessKeyId", "secretAccessKey": { "$$placeholder": 1 } }, "azure": { "tenantId": "tenantId", "clientId": { "$$placeholder": 1 }, "clientSecret": { "$$placeholder": 1 } }, "gcp": { "email": "email", "privateKey": { "$$placeholder": 1 } } } } } } ], "tests": [ { "description": "", "operations": [] } ] } kmsProviders-placeholder_kms_credentials.json000066400000000000000000000027151462766011000373650ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/unified-test-format/valid-pass{ "description": "kmsProviders-placeholder_kms_credentials", "schemaVersion": "1.8", "runOnRequirements": [ { "csfle": true } ], "createEntities": [ { "client": { "id": "client0" } }, { "clientEncryption": { "id": "clientEncryption0", "clientEncryptionOpts": { "keyVaultClient": "client0", "keyVaultNamespace": "keyvault.datakeys", "kmsProviders": { "aws": { "accessKeyId": { "$$placeholder": 1 }, "secretAccessKey": { "$$placeholder": 1 } }, "azure": { "tenantId": { "$$placeholder": 1 }, "clientId": { "$$placeholder": 1 }, "clientSecret": { "$$placeholder": 1 } }, "gcp": { "email": { "$$placeholder": 1 }, "privateKey": { "$$placeholder": 1 } }, "kmip": { "endpoint": { "$$placeholder": 1 } }, "local": { "key": { "$$placeholder": 1 } } } } } } ], "tests": [ { "description": "", "operations": [] } ] } kmsProviders-unconfigured_kms.json000066400000000000000000000014071462766011000352130ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/unified-test-format/valid-pass{ "description": "kmsProviders-unconfigured_kms", "schemaVersion": "1.8", "runOnRequirements": [ { "csfle": true } ], "createEntities": [ { "client": { "id": "client0" } }, { "clientEncryption": { "id": "clientEncryption0", "clientEncryptionOpts": { "keyVaultClient": "client0", "keyVaultNamespace": "keyvault.datakeys", "kmsProviders": { "aws": {}, "azure": {}, "gcp": {}, "kmip": {}, "local": {} } } } } ], "tests": [ { "description": "", "skipReason": "DRIVERS-2280: waiting on driver support for on-demand credentials", "operations": [] } ] } mongodb-mongo-python-driver-509e9b7/test/unified-test-format/valid-pass/matches-lte-operator.json000066400000000000000000000031101462766011000332720ustar00rootroot00000000000000{ "description": "matches-lte-operator", "schemaVersion": "1.9", "createEntities": [ { "client": { "id": "client0", "observeEvents": [ "commandStartedEvent" ] } }, { "database": { "id": "database0", "client": "client0", "databaseName": "database0Name" } }, { "collection": { "id": "collection0", "database": "database0", "collectionName": "coll0" } } ], "initialData": [ { "collectionName": "coll0", "databaseName": "database0Name", "documents": [] } ], "tests": [ { "description": "special lte matching operator", "operations": [ { "name": "insertOne", "object": "collection0", "arguments": { "document": { "_id": 1, "y": 1 } } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "insert": "coll0", "documents": [ { "_id": { "$$lte": 1 }, "y": { "$$lte": 2 } } ] }, "commandName": "insert", "databaseName": "database0Name" } } ] } ] } ] } observeSensitiveCommands.json000066400000000000000000000403121462766011000342020ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/unified-test-format/valid-pass{ "description": "observeSensitiveCommands", "schemaVersion": "1.5", "runOnRequirements": [ { "auth": false } ], "createEntities": [ { "client": { "id": "client0", "observeEvents": [ "commandStartedEvent", "commandSucceededEvent" ], "observeSensitiveCommands": true } }, { "client": { "id": "client1", "observeEvents": [ "commandStartedEvent", "commandSucceededEvent" ], "observeSensitiveCommands": false } }, { "client": { "id": "client2", "observeEvents": [ "commandStartedEvent", "commandSucceededEvent" ] } }, { "database": { "id": "database0", "client": "client0", "databaseName": "observeSensitiveCommands" } }, { "database": { "id": "database1", "client": "client1", "databaseName": "observeSensitiveCommands" } }, { "database": { "id": "database2", "client": "client2", "databaseName": "observeSensitiveCommands" } } ], "tests": [ { "description": "getnonce is observed with observeSensitiveCommands=true", "runOnRequirements": [ { "maxServerVersion": "6.1.99" } ], "operations": [ { "name": "runCommand", "object": "database0", "arguments": { "commandName": "getnonce", "command": { "getnonce": 1 } } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "commandName": "getnonce", "command": { "getnonce": { "$$exists": false } } } }, { "commandSucceededEvent": { "commandName": "getnonce", "reply": { "ok": { "$$exists": false }, "nonce": { "$$exists": false } } } } ] } ] }, { "description": "getnonce is not observed with observeSensitiveCommands=false", "runOnRequirements": [ { "maxServerVersion": "6.1.99" } ], "operations": [ { "name": "runCommand", "object": "database1", "arguments": { "commandName": "getnonce", "command": { "getnonce": 1 } } } ], "expectEvents": [ { "client": "client1", "events": [] } ] }, { "description": "getnonce is not observed by default", "runOnRequirements": [ { "maxServerVersion": "6.1.99" } ], "operations": [ { "name": "runCommand", "object": "database2", "arguments": { "commandName": "getnonce", "command": { "getnonce": 1 } } } ], "expectEvents": [ { "client": "client2", "events": [] } ] }, { "description": "hello with speculativeAuthenticate", "runOnRequirements": [ { "minServerVersion": "4.9" } ], "operations": [ { "name": "runCommand", "object": "database0", "arguments": { "commandName": "hello", "command": { "hello": 1, "speculativeAuthenticate": { "saslStart": 1 } } } }, { "name": "runCommand", "object": "database1", "arguments": { "commandName": "hello", "command": { "hello": 1, "speculativeAuthenticate": { "saslStart": 1 } } } }, { "name": "runCommand", "object": "database2", "arguments": { "commandName": "hello", "command": { "hello": 1, "speculativeAuthenticate": { "saslStart": 1 } } } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "commandName": "hello", "command": { "hello": { "$$exists": false }, "speculativeAuthenticate": { "$$exists": false } } } }, { "commandSucceededEvent": { "commandName": "hello", "reply": { "isWritablePrimary": { "$$exists": false }, "speculativeAuthenticate": { "$$exists": false } } } } ] }, { "client": "client1", "events": [] }, { "client": "client2", "events": [] } ] }, { "description": "hello without speculativeAuthenticate is always observed", "runOnRequirements": [ { "minServerVersion": "4.9" } ], "operations": [ { "name": "runCommand", "object": "database0", "arguments": { "commandName": "hello", "command": { "hello": 1 } } }, { "name": "runCommand", "object": "database1", "arguments": { "commandName": "hello", "command": { "hello": 1 } } }, { "name": "runCommand", "object": "database2", "arguments": { "commandName": "hello", "command": { "hello": 1 } } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "commandName": "hello", "command": { "hello": 1 } } }, { "commandSucceededEvent": { "commandName": "hello", "reply": { "isWritablePrimary": { "$$exists": true } } } } ] }, { "client": "client1", "events": [ { "commandStartedEvent": { "commandName": "hello", "command": { "hello": 1 } } }, { "commandSucceededEvent": { "commandName": "hello", "reply": { "isWritablePrimary": { "$$exists": true } } } } ] }, { "client": "client2", "events": [ { "commandStartedEvent": { "commandName": "hello", "command": { "hello": 1 } } }, { "commandSucceededEvent": { "commandName": "hello", "reply": { "isWritablePrimary": { "$$exists": true } } } } ] } ] }, { "description": "legacy hello with speculativeAuthenticate", "operations": [ { "name": "runCommand", "object": "database0", "arguments": { "commandName": "ismaster", "command": { "ismaster": 1, "speculativeAuthenticate": { "saslStart": 1 } } } }, { "name": "runCommand", "object": "database0", "arguments": { "commandName": "isMaster", "command": { "isMaster": 1, "speculativeAuthenticate": { "saslStart": 1 } } } }, { "name": "runCommand", "object": "database1", "arguments": { "commandName": "ismaster", "command": { "ismaster": 1, "speculativeAuthenticate": { "saslStart": 1 } } } }, { "name": "runCommand", "object": "database1", "arguments": { "commandName": "isMaster", "command": { "isMaster": 1, "speculativeAuthenticate": { "saslStart": 1 } } } }, { "name": "runCommand", "object": "database2", "arguments": { "commandName": "ismaster", "command": { "ismaster": 1, "speculativeAuthenticate": { "saslStart": 1 } } } }, { "name": "runCommand", "object": "database2", "arguments": { "commandName": "isMaster", "command": { "isMaster": 1, "speculativeAuthenticate": { "saslStart": 1 } } } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "commandName": "ismaster", "command": { "ismaster": { "$$exists": false }, "speculativeAuthenticate": { "$$exists": false } } } }, { "commandSucceededEvent": { "commandName": "ismaster", "reply": { "ismaster": { "$$exists": false }, "speculativeAuthenticate": { "$$exists": false } } } }, { "commandStartedEvent": { "commandName": "isMaster", "command": { "isMaster": { "$$exists": false }, "speculativeAuthenticate": { "$$exists": false } } } }, { "commandSucceededEvent": { "commandName": "isMaster", "reply": { "ismaster": { "$$exists": false }, "speculativeAuthenticate": { "$$exists": false } } } } ] }, { "client": "client1", "events": [] }, { "client": "client2", "events": [] } ] }, { "description": "legacy hello without speculativeAuthenticate is always observed", "operations": [ { "name": "runCommand", "object": "database0", "arguments": { "commandName": "ismaster", "command": { "ismaster": 1 } } }, { "name": "runCommand", "object": "database0", "arguments": { "commandName": "isMaster", "command": { "isMaster": 1 } } }, { "name": "runCommand", "object": "database1", "arguments": { "commandName": "ismaster", "command": { "ismaster": 1 } } }, { "name": "runCommand", "object": "database1", "arguments": { "commandName": "isMaster", "command": { "isMaster": 1 } } }, { "name": "runCommand", "object": "database2", "arguments": { "commandName": "ismaster", "command": { "ismaster": 1 } } }, { "name": "runCommand", "object": "database2", "arguments": { "commandName": "isMaster", "command": { "isMaster": 1 } } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "commandName": "ismaster", "command": { "ismaster": 1 } } }, { "commandSucceededEvent": { "commandName": "ismaster", "reply": { "ismaster": { "$$exists": true } } } }, { "commandStartedEvent": { "commandName": "isMaster", "command": { "isMaster": 1 } } }, { "commandSucceededEvent": { "commandName": "isMaster", "reply": { "ismaster": { "$$exists": true } } } } ] }, { "client": "client1", "events": [ { "commandStartedEvent": { "commandName": "ismaster", "command": { "ismaster": 1 } } }, { "commandSucceededEvent": { "commandName": "ismaster", "reply": { "ismaster": { "$$exists": true } } } }, { "commandStartedEvent": { "commandName": "isMaster", "command": { "isMaster": 1 } } }, { "commandSucceededEvent": { "commandName": "isMaster", "reply": { "ismaster": { "$$exists": true } } } } ] }, { "client": "client2", "events": [ { "commandStartedEvent": { "commandName": "ismaster", "command": { "ismaster": 1 } } }, { "commandSucceededEvent": { "commandName": "ismaster", "reply": { "ismaster": { "$$exists": true } } } }, { "commandStartedEvent": { "commandName": "isMaster", "command": { "isMaster": 1 } } }, { "commandSucceededEvent": { "commandName": "isMaster", "reply": { "ismaster": { "$$exists": true } } } } ] } ] } ] } mongodb-mongo-python-driver-509e9b7/test/unified-test-format/valid-pass/poc-change-streams.json000066400000000000000000000253031462766011000327230ustar00rootroot00000000000000{ "description": "poc-change-streams", "schemaVersion": "1.4", "runOnRequirements": [ { "serverless": "forbid" } ], "createEntities": [ { "client": { "id": "client0", "useMultipleMongoses": false, "observeEvents": [ "commandStartedEvent" ], "ignoreCommandMonitoringEvents": [ "getMore", "killCursors" ] } }, { "database": { "id": "database0", "client": "client0", "databaseName": "change-stream-tests" } }, { "collection": { "id": "collection0", "database": "database0", "collectionName": "test" } }, { "client": { "id": "client1", "useMultipleMongoses": false } }, { "database": { "id": "database1", "client": "client1", "databaseName": "change-stream-tests" } }, { "database": { "id": "database2", "client": "client1", "databaseName": "change-stream-tests-2" } }, { "collection": { "id": "collection1", "database": "database1", "collectionName": "test" } }, { "collection": { "id": "collection2", "database": "database1", "collectionName": "test2" } }, { "collection": { "id": "collection3", "database": "database2", "collectionName": "test" } } ], "initialData": [ { "collectionName": "test", "databaseName": "change-stream-tests", "documents": [] }, { "collectionName": "test2", "databaseName": "change-stream-tests", "documents": [] }, { "collectionName": "test", "databaseName": "change-stream-tests-2", "documents": [] } ], "tests": [ { "description": "saveResultAsEntity is optional for createChangeStream", "runOnRequirements": [ { "minServerVersion": "3.8.0", "topologies": [ "replicaset" ] } ], "operations": [ { "name": "createChangeStream", "object": "client0", "arguments": { "pipeline": [] } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "aggregate": 1 }, "commandName": "aggregate", "databaseName": "admin" } } ] } ] }, { "description": "Executing a watch helper on a MongoClient results in notifications for changes to all collections in all databases in the cluster.", "runOnRequirements": [ { "minServerVersion": "3.8.0", "topologies": [ "replicaset" ] } ], "operations": [ { "name": "createChangeStream", "object": "client0", "arguments": { "pipeline": [] }, "saveResultAsEntity": "changeStream0" }, { "name": "insertOne", "object": "collection2", "arguments": { "document": { "x": 1 } } }, { "name": "insertOne", "object": "collection3", "arguments": { "document": { "y": 1 } } }, { "name": "insertOne", "object": "collection1", "arguments": { "document": { "z": 1 } } }, { "name": "iterateUntilDocumentOrError", "object": "changeStream0", "expectResult": { "operationType": "insert", "ns": { "db": "change-stream-tests", "coll": "test2" }, "fullDocument": { "_id": { "$$type": "objectId" }, "x": 1 } } }, { "name": "iterateUntilDocumentOrError", "object": "changeStream0", "expectResult": { "operationType": "insert", "ns": { "db": "change-stream-tests-2", "coll": "test" }, "fullDocument": { "_id": { "$$type": "objectId" }, "y": 1 } } }, { "name": "iterateUntilDocumentOrError", "object": "changeStream0", "expectResult": { "operationType": "insert", "ns": { "db": "change-stream-tests", "coll": "test" }, "fullDocument": { "_id": { "$$type": "objectId" }, "z": 1 } } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "aggregate": 1, "cursor": {}, "pipeline": [ { "$changeStream": { "allChangesForCluster": true, "fullDocument": { "$$unsetOrMatches": "default" } } } ] }, "commandName": "aggregate", "databaseName": "admin" } } ] } ] }, { "description": "Test consecutive resume", "runOnRequirements": [ { "minServerVersion": "4.1.7", "topologies": [ "replicaset" ] } ], "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "client0", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 2 }, "data": { "failCommands": [ "getMore" ], "closeConnection": true } } } }, { "name": "createChangeStream", "object": "collection0", "arguments": { "batchSize": 1, "pipeline": [] }, "saveResultAsEntity": "changeStream0" }, { "name": "insertOne", "object": "collection1", "arguments": { "document": { "x": 1 } } }, { "name": "insertOne", "object": "collection1", "arguments": { "document": { "x": 2 } } }, { "name": "insertOne", "object": "collection1", "arguments": { "document": { "x": 3 } } }, { "name": "iterateUntilDocumentOrError", "object": "changeStream0", "expectResult": { "operationType": "insert", "ns": { "db": "change-stream-tests", "coll": "test" }, "fullDocument": { "_id": { "$$type": "objectId" }, "x": 1 } } }, { "name": "iterateUntilDocumentOrError", "object": "changeStream0", "expectResult": { "operationType": "insert", "ns": { "db": "change-stream-tests", "coll": "test" }, "fullDocument": { "_id": { "$$type": "objectId" }, "x": 2 } } }, { "name": "iterateUntilDocumentOrError", "object": "changeStream0", "expectResult": { "operationType": "insert", "ns": { "db": "change-stream-tests", "coll": "test" }, "fullDocument": { "_id": { "$$type": "objectId" }, "x": 3 } } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "aggregate": "test", "cursor": { "batchSize": 1 }, "pipeline": [ { "$changeStream": { "fullDocument": { "$$unsetOrMatches": "default" } } } ] }, "commandName": "aggregate", "databaseName": "change-stream-tests" } }, { "commandStartedEvent": { "command": { "aggregate": "test", "cursor": { "batchSize": 1 }, "pipeline": [ { "$changeStream": { "fullDocument": { "$$unsetOrMatches": "default" }, "resumeAfter": { "$$exists": true } } } ] }, "commandName": "aggregate", "databaseName": "change-stream-tests" } }, { "commandStartedEvent": { "command": { "aggregate": "test", "cursor": { "batchSize": 1 }, "pipeline": [ { "$changeStream": { "fullDocument": { "$$unsetOrMatches": "default" }, "resumeAfter": { "$$exists": true } } } ] }, "commandName": "aggregate", "databaseName": "change-stream-tests" } } ] } ] } ] } mongodb-mongo-python-driver-509e9b7/test/unified-test-format/valid-pass/poc-command-monitoring.json000066400000000000000000000120711462766011000336210ustar00rootroot00000000000000{ "description": "poc-command-monitoring", "schemaVersion": "1.0", "createEntities": [ { "client": { "id": "client0", "observeEvents": [ "commandStartedEvent", "commandSucceededEvent", "commandFailedEvent" ] } }, { "database": { "id": "database0", "client": "client0", "databaseName": "command-monitoring-tests" } }, { "collection": { "id": "collection0", "database": "database0", "collectionName": "test" } } ], "initialData": [ { "collectionName": "test", "databaseName": "command-monitoring-tests", "documents": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 22 }, { "_id": 3, "x": 33 }, { "_id": 4, "x": 44 }, { "_id": 5, "x": 55 } ] } ], "tests": [ { "description": "A successful find event with a getmore and the server kills the cursor (<= 4.4)", "runOnRequirements": [ { "minServerVersion": "3.1", "maxServerVersion": "4.4.99", "topologies": [ "single", "replicaset" ] } ], "operations": [ { "name": "find", "object": "collection0", "arguments": { "filter": { "_id": { "$gte": 1 } }, "sort": { "_id": 1 }, "batchSize": 3, "limit": 4 } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "find": "test", "filter": { "_id": { "$gte": 1 } }, "sort": { "_id": 1 }, "batchSize": 3, "limit": 4 }, "commandName": "find", "databaseName": "command-monitoring-tests" } }, { "commandSucceededEvent": { "reply": { "ok": 1, "cursor": { "id": { "$$type": [ "int", "long" ] }, "ns": "command-monitoring-tests.test", "firstBatch": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 22 }, { "_id": 3, "x": 33 } ] } }, "commandName": "find" } }, { "commandStartedEvent": { "command": { "getMore": { "$$type": [ "int", "long" ] }, "collection": "test", "batchSize": 1 }, "commandName": "getMore", "databaseName": "command-monitoring-tests" } }, { "commandSucceededEvent": { "reply": { "ok": 1, "cursor": { "id": 0, "ns": "command-monitoring-tests.test", "nextBatch": [ { "_id": 4, "x": 44 } ] } }, "commandName": "getMore" } } ] } ] }, { "description": "A failed find event", "operations": [ { "name": "find", "object": "collection0", "arguments": { "filter": { "$or": true } }, "expectError": { "isError": true } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "find": "test", "filter": { "$or": true } }, "commandName": "find", "databaseName": "command-monitoring-tests" } }, { "commandFailedEvent": { "commandName": "find" } } ] } ] } ] } mongodb-mongo-python-driver-509e9b7/test/unified-test-format/valid-pass/poc-crud.json000066400000000000000000000227131462766011000307610ustar00rootroot00000000000000{ "description": "poc-crud", "schemaVersion": "1.4", "createEntities": [ { "client": { "id": "client0", "observeEvents": [ "commandStartedEvent" ] } }, { "database": { "id": "database0", "client": "client0", "databaseName": "crud-tests" } }, { "database": { "id": "database1", "client": "client0", "databaseName": "admin" } }, { "collection": { "id": "collection0", "database": "database0", "collectionName": "coll0" } }, { "collection": { "id": "collection1", "database": "database0", "collectionName": "coll1" } }, { "collection": { "id": "collection2", "database": "database0", "collectionName": "coll2", "collectionOptions": { "readConcern": { "level": "majority" } } } } ], "initialData": [ { "collectionName": "coll0", "databaseName": "crud-tests", "documents": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 22 } ] }, { "collectionName": "coll1", "databaseName": "crud-tests", "documents": [ { "_id": 1, "x": 11 } ] }, { "collectionName": "coll2", "databaseName": "crud-tests", "documents": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 22 }, { "_id": 3, "x": 33 } ] }, { "collectionName": "aggregate_out", "databaseName": "crud-tests", "documents": [] } ], "tests": [ { "description": "BulkWrite with mixed ordered operations", "operations": [ { "name": "bulkWrite", "object": "collection0", "arguments": { "requests": [ { "insertOne": { "document": { "_id": 3, "x": 33 } } }, { "updateOne": { "filter": { "_id": 2 }, "update": { "$inc": { "x": 1 } } } }, { "updateMany": { "filter": { "_id": { "$gt": 1 } }, "update": { "$inc": { "x": 1 } } } }, { "insertOne": { "document": { "_id": 4, "x": 44 } } }, { "deleteMany": { "filter": { "x": { "$nin": [ 24, 34 ] } } } }, { "replaceOne": { "filter": { "_id": 4 }, "replacement": { "_id": 4, "x": 44 }, "upsert": true } } ], "ordered": true }, "expectResult": { "deletedCount": 2, "insertedCount": 2, "insertedIds": { "$$unsetOrMatches": { "0": 3, "3": 4 } }, "matchedCount": 3, "modifiedCount": 3, "upsertedCount": 1, "upsertedIds": { "5": 4 } } } ], "outcome": [ { "collectionName": "coll0", "databaseName": "crud-tests", "documents": [ { "_id": 2, "x": 24 }, { "_id": 3, "x": 34 }, { "_id": 4, "x": 44 } ] } ] }, { "description": "InsertMany continue-on-error behavior with unordered (duplicate key in requests)", "operations": [ { "name": "insertMany", "object": "collection1", "arguments": { "documents": [ { "_id": 2, "x": 22 }, { "_id": 2, "x": 22 }, { "_id": 3, "x": 33 } ], "ordered": false }, "expectError": { "expectResult": { "$$unsetOrMatches": { "deletedCount": 0, "insertedCount": 2, "matchedCount": 0, "modifiedCount": 0, "upsertedCount": 0, "upsertedIds": {} } } } } ], "outcome": [ { "collectionName": "coll1", "databaseName": "crud-tests", "documents": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 22 }, { "_id": 3, "x": 33 } ] } ] }, { "description": "ReplaceOne prohibits atomic modifiers", "operations": [ { "name": "replaceOne", "object": "collection1", "arguments": { "filter": { "_id": 1 }, "replacement": { "$set": { "x": 22 } } }, "expectError": { "isClientError": true } } ], "expectEvents": [ { "client": "client0", "events": [] } ], "outcome": [ { "collectionName": "coll1", "databaseName": "crud-tests", "documents": [ { "_id": 1, "x": 11 } ] } ] }, { "description": "readConcern majority with out stage", "runOnRequirements": [ { "minServerVersion": "4.1.0", "topologies": [ "replicaset", "sharded" ], "serverless": "forbid" } ], "operations": [ { "name": "aggregate", "object": "collection2", "arguments": { "pipeline": [ { "$sort": { "x": 1 } }, { "$match": { "_id": { "$gt": 1 } } }, { "$out": "aggregate_out" } ] } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "aggregate": "coll2", "pipeline": [ { "$sort": { "x": 1 } }, { "$match": { "_id": { "$gt": 1 } } }, { "$out": "aggregate_out" } ], "readConcern": { "level": "majority" } }, "commandName": "aggregate", "databaseName": "crud-tests" } } ] } ], "outcome": [ { "collectionName": "aggregate_out", "databaseName": "crud-tests", "documents": [ { "_id": 2, "x": 22 }, { "_id": 3, "x": 33 } ] } ] }, { "description": "Aggregate with $listLocalSessions", "runOnRequirements": [ { "minServerVersion": "3.6.0", "serverless": "forbid" } ], "operations": [ { "name": "aggregate", "object": "database1", "arguments": { "pipeline": [ { "$listLocalSessions": {} }, { "$limit": 1 }, { "$addFields": { "dummy": "dummy field" } }, { "$project": { "_id": 0, "dummy": 1 } } ] }, "expectResult": [ { "dummy": "dummy field" } ] } ] } ] } mongodb-mongo-python-driver-509e9b7/test/unified-test-format/valid-pass/poc-gridfs.json000066400000000000000000000152361462766011000313040ustar00rootroot00000000000000{ "description": "poc-gridfs", "schemaVersion": "1.0", "createEntities": [ { "client": { "id": "client0" } }, { "database": { "id": "database0", "client": "client0", "databaseName": "gridfs-tests" } }, { "bucket": { "id": "bucket0", "database": "database0" } }, { "collection": { "id": "bucket0_files_collection", "database": "database0", "collectionName": "fs.files" } }, { "collection": { "id": "bucket0_chunks_collection", "database": "database0", "collectionName": "fs.chunks" } } ], "initialData": [ { "collectionName": "fs.files", "databaseName": "gridfs-tests", "documents": [ { "_id": { "$oid": "000000000000000000000005" }, "length": 10, "chunkSize": 4, "uploadDate": { "$date": "1970-01-01T00:00:00.000Z" }, "md5": "57d83cd477bfb1ccd975ab33d827a92b", "filename": "length-10", "contentType": "application/octet-stream", "aliases": [], "metadata": {} } ] }, { "collectionName": "fs.chunks", "databaseName": "gridfs-tests", "documents": [ { "_id": { "$oid": "000000000000000000000005" }, "files_id": { "$oid": "000000000000000000000005" }, "n": 0, "data": { "$binary": { "base64": "ESIzRA==", "subType": "00" } } }, { "_id": { "$oid": "000000000000000000000006" }, "files_id": { "$oid": "000000000000000000000005" }, "n": 1, "data": { "$binary": { "base64": "VWZ3iA==", "subType": "00" } } }, { "_id": { "$oid": "000000000000000000000007" }, "files_id": { "$oid": "000000000000000000000005" }, "n": 2, "data": { "$binary": { "base64": "mao=", "subType": "00" } } } ] } ], "tests": [ { "description": "Delete when length is 10", "operations": [ { "name": "delete", "object": "bucket0", "arguments": { "id": { "$oid": "000000000000000000000005" } } } ], "outcome": [ { "collectionName": "fs.files", "databaseName": "gridfs-tests", "documents": [] }, { "collectionName": "fs.chunks", "databaseName": "gridfs-tests", "documents": [] } ] }, { "description": "Download when there are three chunks", "operations": [ { "name": "download", "object": "bucket0", "arguments": { "id": { "$oid": "000000000000000000000005" } }, "expectResult": { "$$matchesHexBytes": "112233445566778899aa" } } ] }, { "description": "Download when files entry does not exist", "operations": [ { "name": "download", "object": "bucket0", "arguments": { "id": { "$oid": "000000000000000000000000" } }, "expectError": { "isError": true } } ] }, { "description": "Download when an intermediate chunk is missing", "operations": [ { "name": "deleteOne", "object": "bucket0_chunks_collection", "arguments": { "filter": { "files_id": { "$oid": "000000000000000000000005" }, "n": 1 } }, "expectResult": { "deletedCount": 1 } }, { "name": "download", "object": "bucket0", "arguments": { "id": { "$oid": "000000000000000000000005" } }, "expectError": { "isError": true } } ] }, { "description": "Upload when length is 5", "operations": [ { "name": "upload", "object": "bucket0", "arguments": { "filename": "filename", "source": { "$$hexBytes": "1122334455" }, "chunkSizeBytes": 4 }, "expectResult": { "$$type": "objectId" }, "saveResultAsEntity": "oid0" }, { "name": "find", "object": "bucket0_files_collection", "arguments": { "filter": {}, "sort": { "uploadDate": -1 }, "limit": 1 }, "expectResult": [ { "_id": { "$$matchesEntity": "oid0" }, "length": 5, "chunkSize": 4, "uploadDate": { "$$type": "date" }, "md5": { "$$unsetOrMatches": "283d4fea5dded59cf837d3047328f5af" }, "filename": "filename" } ] }, { "name": "find", "object": "bucket0_chunks_collection", "arguments": { "filter": { "_id": { "$gt": { "$oid": "000000000000000000000007" } } }, "sort": { "n": 1 } }, "expectResult": [ { "_id": { "$$type": "objectId" }, "files_id": { "$$matchesEntity": "oid0" }, "n": 0, "data": { "$binary": { "base64": "ESIzRA==", "subType": "00" } } }, { "_id": { "$$type": "objectId" }, "files_id": { "$$matchesEntity": "oid0" }, "n": 1, "data": { "$binary": { "base64": "VQ==", "subType": "00" } } } ] } ] } ] } mongodb-mongo-python-driver-509e9b7/test/unified-test-format/valid-pass/poc-retryable-reads.json000066400000000000000000000227301462766011000331100ustar00rootroot00000000000000{ "description": "poc-retryable-reads", "schemaVersion": "1.0", "runOnRequirements": [ { "minServerVersion": "4.0", "topologies": [ "single", "replicaset" ] }, { "minServerVersion": "4.1.7", "topologies": [ "sharded" ] } ], "createEntities": [ { "client": { "id": "client0", "useMultipleMongoses": false, "observeEvents": [ "commandStartedEvent" ] } }, { "client": { "id": "client1", "uriOptions": { "retryReads": false }, "useMultipleMongoses": false, "observeEvents": [ "commandStartedEvent" ] } }, { "database": { "id": "database0", "client": "client0", "databaseName": "retryable-reads-tests" } }, { "database": { "id": "database1", "client": "client1", "databaseName": "retryable-reads-tests" } }, { "collection": { "id": "collection0", "database": "database0", "collectionName": "coll" } }, { "collection": { "id": "collection1", "database": "database1", "collectionName": "coll" } } ], "initialData": [ { "collectionName": "coll", "databaseName": "retryable-reads-tests", "documents": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 22 }, { "_id": 3, "x": 33 } ] } ], "tests": [ { "description": "Aggregate succeeds after InterruptedAtShutdown", "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "client0", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "aggregate" ], "errorCode": 11600 } } } }, { "name": "aggregate", "object": "collection0", "arguments": { "pipeline": [ { "$match": { "_id": { "$gt": 1 } } }, { "$sort": { "x": 1 } } ] }, "expectResult": [ { "_id": 2, "x": 22 }, { "_id": 3, "x": 33 } ] } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "aggregate": "coll", "pipeline": [ { "$match": { "_id": { "$gt": 1 } } }, { "$sort": { "x": 1 } } ] }, "databaseName": "retryable-reads-tests" } }, { "commandStartedEvent": { "command": { "aggregate": "coll", "pipeline": [ { "$match": { "_id": { "$gt": 1 } } }, { "$sort": { "x": 1 } } ] }, "databaseName": "retryable-reads-tests" } } ] } ] }, { "description": "Find succeeds on second attempt", "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "client0", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "find" ], "closeConnection": true } } } }, { "name": "find", "object": "collection0", "arguments": { "filter": {}, "sort": { "_id": 1 }, "limit": 2 }, "expectResult": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 22 } ] } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "find": "coll", "filter": {}, "sort": { "_id": 1 }, "limit": 2 }, "databaseName": "retryable-reads-tests" } }, { "commandStartedEvent": { "command": { "find": "coll", "filter": {}, "sort": { "_id": 1 }, "limit": 2 }, "databaseName": "retryable-reads-tests" } } ] } ] }, { "description": "Find fails on first attempt", "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "client0", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "find" ], "closeConnection": true } } } }, { "name": "find", "object": "collection1", "arguments": { "filter": {} }, "expectError": { "isError": true } } ], "expectEvents": [ { "client": "client1", "events": [ { "commandStartedEvent": { "command": { "find": "coll", "filter": {} }, "databaseName": "retryable-reads-tests" } } ] } ] }, { "description": "Find fails on second attempt", "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "client0", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 2 }, "data": { "failCommands": [ "find" ], "closeConnection": true } } } }, { "name": "find", "object": "collection0", "arguments": { "filter": {} }, "expectError": { "isError": true } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "find": "coll", "filter": {} }, "databaseName": "retryable-reads-tests" } }, { "commandStartedEvent": { "command": { "find": "coll", "filter": {} }, "databaseName": "retryable-reads-tests" } } ] } ] }, { "description": "ListDatabases succeeds on second attempt", "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "client0", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "listDatabases" ], "closeConnection": true } } } }, { "name": "listDatabases", "object": "client0" } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "listDatabases": 1 } } }, { "commandStartedEvent": { "command": { "listDatabases": 1 } } } ] } ] } ] } mongodb-mongo-python-driver-509e9b7/test/unified-test-format/valid-pass/poc-retryable-writes.json000066400000000000000000000247551462766011000333400ustar00rootroot00000000000000{ "description": "poc-retryable-writes", "schemaVersion": "1.0", "createEntities": [ { "client": { "id": "client0", "useMultipleMongoses": false, "observeEvents": [ "commandStartedEvent" ] } }, { "client": { "id": "client1", "uriOptions": { "retryWrites": false }, "useMultipleMongoses": false, "observeEvents": [ "commandStartedEvent" ] } }, { "database": { "id": "database0", "client": "client0", "databaseName": "retryable-writes-tests" } }, { "database": { "id": "database1", "client": "client1", "databaseName": "retryable-writes-tests" } }, { "collection": { "id": "collection0", "database": "database0", "collectionName": "coll" } }, { "collection": { "id": "collection1", "database": "database1", "collectionName": "coll" } } ], "initialData": [ { "collectionName": "coll", "databaseName": "retryable-writes-tests", "documents": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 22 } ] } ], "tests": [ { "description": "FindOneAndUpdate is committed on first attempt", "runOnRequirements": [ { "minServerVersion": "3.6", "topologies": [ "replicaset" ] } ], "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "client0", "failPoint": { "configureFailPoint": "onPrimaryTransactionalWrite", "mode": { "times": 1 } } } }, { "name": "findOneAndUpdate", "object": "collection0", "arguments": { "filter": { "_id": 1 }, "update": { "$inc": { "x": 1 } }, "returnDocument": "Before" }, "expectResult": { "_id": 1, "x": 11 } } ], "outcome": [ { "collectionName": "coll", "databaseName": "retryable-writes-tests", "documents": [ { "_id": 1, "x": 12 }, { "_id": 2, "x": 22 } ] } ] }, { "description": "FindOneAndUpdate is not committed on first attempt", "runOnRequirements": [ { "minServerVersion": "3.6", "topologies": [ "replicaset" ] } ], "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "client0", "failPoint": { "configureFailPoint": "onPrimaryTransactionalWrite", "mode": { "times": 1 }, "data": { "failBeforeCommitExceptionCode": 1 } } } }, { "name": "findOneAndUpdate", "object": "collection0", "arguments": { "filter": { "_id": 1 }, "update": { "$inc": { "x": 1 } }, "returnDocument": "Before" }, "expectResult": { "_id": 1, "x": 11 } } ], "outcome": [ { "collectionName": "coll", "databaseName": "retryable-writes-tests", "documents": [ { "_id": 1, "x": 12 }, { "_id": 2, "x": 22 } ] } ] }, { "description": "FindOneAndUpdate is never committed", "runOnRequirements": [ { "minServerVersion": "3.6", "topologies": [ "replicaset" ] } ], "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "client0", "failPoint": { "configureFailPoint": "onPrimaryTransactionalWrite", "mode": { "times": 2 }, "data": { "failBeforeCommitExceptionCode": 1 } } } }, { "name": "findOneAndUpdate", "object": "collection0", "arguments": { "filter": { "_id": 1 }, "update": { "$inc": { "x": 1 } }, "returnDocument": "Before" }, "expectError": { "isError": true } } ], "outcome": [ { "collectionName": "coll", "databaseName": "retryable-writes-tests", "documents": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 22 } ] } ] }, { "description": "InsertMany succeeds after PrimarySteppedDown", "runOnRequirements": [ { "minServerVersion": "4.3.1", "topologies": [ "replicaset", "sharded" ] } ], "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "client0", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "insert" ], "errorCode": 189, "errorLabels": [ "RetryableWriteError" ] } } } }, { "name": "insertMany", "object": "collection0", "arguments": { "documents": [ { "_id": 3, "x": 33 }, { "_id": 4, "x": 44 } ], "ordered": true }, "expectResult": { "$$unsetOrMatches": { "insertedIds": { "$$unsetOrMatches": { "0": 3, "1": 4 } } } } } ], "outcome": [ { "collectionName": "coll", "databaseName": "retryable-writes-tests", "documents": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 22 }, { "_id": 3, "x": 33 }, { "_id": 4, "x": 44 } ] } ] }, { "description": "InsertOne fails after connection failure when retryWrites option is false", "runOnRequirements": [ { "minServerVersion": "4.0", "topologies": [ "replicaset" ] }, { "minServerVersion": "4.1.7", "topologies": [ "sharded" ] } ], "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "client1", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "insert" ], "closeConnection": true } } } }, { "name": "insertOne", "object": "collection1", "arguments": { "document": { "_id": 3, "x": 33 } }, "expectError": { "errorLabelsOmit": [ "RetryableWriteError" ] } } ], "outcome": [ { "collectionName": "coll", "databaseName": "retryable-writes-tests", "documents": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 22 } ] } ] }, { "description": "InsertOne fails after multiple retryable writeConcernErrors", "runOnRequirements": [ { "minServerVersion": "4.3.1", "topologies": [ "replicaset", "sharded" ] } ], "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "client0", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 2 }, "data": { "failCommands": [ "insert" ], "errorLabels": [ "RetryableWriteError" ], "writeConcernError": { "code": 91, "errmsg": "Replication is being shut down" } } } } }, { "name": "insertOne", "object": "collection0", "arguments": { "document": { "_id": 3, "x": 33 } }, "expectError": { "errorLabelsContain": [ "RetryableWriteError" ] } } ], "outcome": [ { "collectionName": "coll", "databaseName": "retryable-writes-tests", "documents": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 22 }, { "_id": 3, "x": 33 } ] } ] } ] } mongodb-mongo-python-driver-509e9b7/test/unified-test-format/valid-pass/poc-sessions.json000066400000000000000000000251131462766011000316670ustar00rootroot00000000000000{ "description": "poc-sessions", "schemaVersion": "1.0", "runOnRequirements": [ { "minServerVersion": "3.6.0" } ], "createEntities": [ { "client": { "id": "client0", "useMultipleMongoses": false, "observeEvents": [ "commandStartedEvent" ] } }, { "database": { "id": "database0", "client": "client0", "databaseName": "session-tests" } }, { "collection": { "id": "collection0", "database": "database0", "collectionName": "test" } }, { "session": { "id": "session0", "client": "client0" } } ], "initialData": [ { "collectionName": "test", "databaseName": "session-tests", "documents": [ { "_id": 1 } ] } ], "tests": [ { "description": "Server supports explicit sessions", "operations": [ { "name": "assertSessionNotDirty", "object": "testRunner", "arguments": { "session": "session0" } }, { "name": "insertOne", "object": "collection0", "arguments": { "session": "session0", "document": { "_id": 2 } }, "expectResult": { "$$unsetOrMatches": { "insertedId": { "$$unsetOrMatches": 2 } } } }, { "name": "assertSessionNotDirty", "object": "testRunner", "arguments": { "session": "session0" } }, { "name": "endSession", "object": "session0" }, { "name": "find", "object": "collection0", "arguments": { "filter": { "_id": -1 } }, "expectResult": [] }, { "name": "assertSameLsidOnLastTwoCommands", "object": "testRunner", "arguments": { "client": "client0" } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "insert": "test", "documents": [ { "_id": 2 } ], "ordered": true, "lsid": { "$$sessionLsid": "session0" } }, "commandName": "insert", "databaseName": "session-tests" } }, { "commandStartedEvent": { "command": { "find": "test", "filter": { "_id": -1 }, "lsid": { "$$sessionLsid": "session0" } }, "commandName": "find", "databaseName": "session-tests" } } ] } ], "outcome": [ { "collectionName": "test", "databaseName": "session-tests", "documents": [ { "_id": 1 }, { "_id": 2 } ] } ] }, { "description": "Server supports implicit sessions", "operations": [ { "name": "insertOne", "object": "collection0", "arguments": { "document": { "_id": 2 } }, "expectResult": { "$$unsetOrMatches": { "insertedId": { "$$unsetOrMatches": 2 } } } }, { "name": "find", "object": "collection0", "arguments": { "filter": { "_id": -1 } }, "expectResult": [] }, { "name": "assertSameLsidOnLastTwoCommands", "object": "testRunner", "arguments": { "client": "client0" } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "insert": "test", "documents": [ { "_id": 2 } ], "ordered": true, "lsid": { "$$type": "object" } }, "commandName": "insert", "databaseName": "session-tests" } }, { "commandStartedEvent": { "command": { "find": "test", "filter": { "_id": -1 }, "lsid": { "$$type": "object" } }, "commandName": "find", "databaseName": "session-tests" } } ] } ], "outcome": [ { "collectionName": "test", "databaseName": "session-tests", "documents": [ { "_id": 1 }, { "_id": 2 } ] } ] }, { "description": "Dirty explicit session is discarded", "runOnRequirements": [ { "minServerVersion": "4.0", "topologies": [ "replicaset" ] }, { "minServerVersion": "4.1.8", "topologies": [ "sharded" ] } ], "operations": [ { "name": "failPoint", "object": "testRunner", "arguments": { "client": "client0", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "insert" ], "closeConnection": true } } } }, { "name": "assertSessionNotDirty", "object": "testRunner", "arguments": { "session": "session0" } }, { "name": "insertOne", "object": "collection0", "arguments": { "session": "session0", "document": { "_id": 2 } }, "expectResult": { "$$unsetOrMatches": { "insertedId": { "$$unsetOrMatches": 2 } } } }, { "name": "assertSessionDirty", "object": "testRunner", "arguments": { "session": "session0" } }, { "name": "insertOne", "object": "collection0", "arguments": { "session": "session0", "document": { "_id": 3 } }, "expectResult": { "$$unsetOrMatches": { "insertedId": { "$$unsetOrMatches": 3 } } } }, { "name": "assertSessionDirty", "object": "testRunner", "arguments": { "session": "session0" } }, { "name": "endSession", "object": "session0" }, { "name": "find", "object": "collection0", "arguments": { "filter": { "_id": -1 } }, "expectResult": [] }, { "name": "assertDifferentLsidOnLastTwoCommands", "object": "testRunner", "arguments": { "client": "client0" } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "insert": "test", "documents": [ { "_id": 2 } ], "ordered": true, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": 1 }, "commandName": "insert", "databaseName": "session-tests" } }, { "commandStartedEvent": { "command": { "insert": "test", "documents": [ { "_id": 2 } ], "ordered": true, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": 1 }, "commandName": "insert", "databaseName": "session-tests" } }, { "commandStartedEvent": { "command": { "insert": "test", "documents": [ { "_id": 3 } ], "ordered": true, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": 2 }, "commandName": "insert", "databaseName": "session-tests" } }, { "commandStartedEvent": { "command": { "find": "test", "filter": { "_id": -1 }, "lsid": { "$$type": "object" } }, "commandName": "find", "databaseName": "session-tests" } } ] } ], "outcome": [ { "collectionName": "test", "databaseName": "session-tests", "documents": [ { "_id": 1 }, { "_id": 2 }, { "_id": 3 } ] } ] } ] } poc-transactions-convenient-api.json000066400000000000000000000307601462766011000353730ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/unified-test-format/valid-pass{ "description": "poc-transactions-convenient-api", "schemaVersion": "1.0", "runOnRequirements": [ { "minServerVersion": "4.0", "topologies": [ "replicaset" ] }, { "minServerVersion": "4.1.8", "topologies": [ "sharded" ] } ], "createEntities": [ { "client": { "id": "client0", "useMultipleMongoses": true, "observeEvents": [ "commandStartedEvent" ] } }, { "client": { "id": "client1", "uriOptions": { "readConcernLevel": "local", "w": 1 }, "useMultipleMongoses": true, "observeEvents": [ "commandStartedEvent" ] } }, { "database": { "id": "database0", "client": "client0", "databaseName": "transaction-tests" } }, { "database": { "id": "database1", "client": "client1", "databaseName": "transaction-tests" } }, { "collection": { "id": "collection0", "database": "database0", "collectionName": "test" } }, { "collection": { "id": "collection1", "database": "database1", "collectionName": "test" } }, { "session": { "id": "session0", "client": "client0" } }, { "session": { "id": "session1", "client": "client1" } }, { "session": { "id": "session2", "client": "client0", "sessionOptions": { "defaultTransactionOptions": { "readConcern": { "level": "majority" }, "writeConcern": { "w": 1 } } } } } ], "initialData": [ { "collectionName": "test", "databaseName": "transaction-tests", "documents": [] } ], "tests": [ { "description": "withTransaction and no transaction options set", "operations": [ { "name": "withTransaction", "object": "session0", "arguments": { "callback": [ { "name": "insertOne", "object": "collection0", "arguments": { "session": "session0", "document": { "_id": 1 } }, "expectResult": { "$$unsetOrMatches": { "insertedId": { "$$unsetOrMatches": 1 } } } } ] } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "insert": "test", "documents": [ { "_id": 1 } ], "ordered": true, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": 1, "startTransaction": true, "autocommit": false, "readConcern": { "$$exists": false }, "writeConcern": { "$$exists": false } }, "commandName": "insert", "databaseName": "transaction-tests" } }, { "commandStartedEvent": { "command": { "commitTransaction": 1, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": 1, "autocommit": false, "readConcern": { "$$exists": false }, "startTransaction": { "$$exists": false }, "writeConcern": { "$$exists": false } }, "commandName": "commitTransaction", "databaseName": "admin" } } ] } ], "outcome": [ { "collectionName": "test", "databaseName": "transaction-tests", "documents": [ { "_id": 1 } ] } ] }, { "description": "withTransaction inherits transaction options from client", "operations": [ { "name": "withTransaction", "object": "session1", "arguments": { "callback": [ { "name": "insertOne", "object": "collection1", "arguments": { "session": "session1", "document": { "_id": 1 } }, "expectResult": { "$$unsetOrMatches": { "insertedId": { "$$unsetOrMatches": 1 } } } } ] } } ], "expectEvents": [ { "client": "client1", "events": [ { "commandStartedEvent": { "command": { "insert": "test", "documents": [ { "_id": 1 } ], "ordered": true, "lsid": { "$$sessionLsid": "session1" }, "txnNumber": 1, "startTransaction": true, "autocommit": false, "readConcern": { "level": "local" }, "writeConcern": { "$$exists": false } }, "commandName": "insert", "databaseName": "transaction-tests" } }, { "commandStartedEvent": { "command": { "commitTransaction": 1, "lsid": { "$$sessionLsid": "session1" }, "txnNumber": 1, "autocommit": false, "writeConcern": { "w": 1 }, "readConcern": { "$$exists": false }, "startTransaction": { "$$exists": false } }, "commandName": "commitTransaction", "databaseName": "admin" } } ] } ], "outcome": [ { "collectionName": "test", "databaseName": "transaction-tests", "documents": [ { "_id": 1 } ] } ] }, { "description": "withTransaction inherits transaction options from defaultTransactionOptions", "operations": [ { "name": "withTransaction", "object": "session2", "arguments": { "callback": [ { "name": "insertOne", "object": "collection0", "arguments": { "session": "session2", "document": { "_id": 1 } }, "expectResult": { "$$unsetOrMatches": { "insertedId": { "$$unsetOrMatches": 1 } } } } ] } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "insert": "test", "documents": [ { "_id": 1 } ], "ordered": true, "lsid": { "$$sessionLsid": "session2" }, "txnNumber": 1, "startTransaction": true, "autocommit": false, "readConcern": { "level": "majority" }, "writeConcern": { "$$exists": false } }, "commandName": "insert", "databaseName": "transaction-tests" } }, { "commandStartedEvent": { "command": { "commitTransaction": 1, "lsid": { "$$sessionLsid": "session2" }, "txnNumber": 1, "autocommit": false, "writeConcern": { "w": 1 }, "readConcern": { "$$exists": false }, "startTransaction": { "$$exists": false } }, "commandName": "commitTransaction", "databaseName": "admin" } } ] } ], "outcome": [ { "collectionName": "test", "databaseName": "transaction-tests", "documents": [ { "_id": 1 } ] } ] }, { "description": "withTransaction explicit transaction options", "operations": [ { "name": "withTransaction", "object": "session0", "arguments": { "callback": [ { "name": "insertOne", "object": "collection0", "arguments": { "session": "session0", "document": { "_id": 1 } }, "expectResult": { "$$unsetOrMatches": { "insertedId": { "$$unsetOrMatches": 1 } } } } ], "readConcern": { "level": "majority" }, "writeConcern": { "w": 1 } } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "insert": "test", "documents": [ { "_id": 1 } ], "ordered": true, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": 1, "startTransaction": true, "autocommit": false, "readConcern": { "level": "majority" }, "writeConcern": { "$$exists": false } }, "commandName": "insert", "databaseName": "transaction-tests" } }, { "commandStartedEvent": { "command": { "commitTransaction": 1, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": 1, "autocommit": false, "writeConcern": { "w": 1 }, "readConcern": { "$$exists": false }, "startTransaction": { "$$exists": false } }, "commandName": "commitTransaction", "databaseName": "admin" } } ] } ], "outcome": [ { "collectionName": "test", "databaseName": "transaction-tests", "documents": [ { "_id": 1 } ] } ] } ] } poc-transactions-mongos-pin-auto.json000066400000000000000000000240741462766011000355110ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/unified-test-format/valid-pass{ "description": "poc-transactions-mongos-pin-auto", "schemaVersion": "1.0", "runOnRequirements": [ { "minServerVersion": "4.1.8", "topologies": [ "sharded" ] } ], "createEntities": [ { "client": { "id": "client0", "useMultipleMongoses": true, "observeEvents": [ "commandStartedEvent" ] } }, { "database": { "id": "database0", "client": "client0", "databaseName": "transaction-tests" } }, { "collection": { "id": "collection0", "database": "database0", "collectionName": "test" } }, { "session": { "id": "session0", "client": "client0" } } ], "initialData": [ { "collectionName": "test", "databaseName": "transaction-tests", "documents": [ { "_id": 1 }, { "_id": 2 } ] } ], "tests": [ { "description": "remain pinned after non-transient Interrupted error on insertOne", "operations": [ { "name": "startTransaction", "object": "session0" }, { "name": "insertOne", "object": "collection0", "arguments": { "session": "session0", "document": { "_id": 3 } }, "expectResult": { "$$unsetOrMatches": { "insertedId": { "$$unsetOrMatches": 3 } } } }, { "name": "targetedFailPoint", "object": "testRunner", "arguments": { "session": "session0", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "insert" ], "errorCode": 11601 } } } }, { "name": "insertOne", "object": "collection0", "arguments": { "session": "session0", "document": { "_id": 4 } }, "expectError": { "errorLabelsOmit": [ "TransientTransactionError", "UnknownTransactionCommitResult" ], "errorCodeName": "Interrupted" } }, { "name": "assertSessionPinned", "object": "testRunner", "arguments": { "session": "session0" } }, { "name": "commitTransaction", "object": "session0" } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "insert": "test", "documents": [ { "_id": 3 } ], "ordered": true, "readConcern": { "$$exists": false }, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": 1, "startTransaction": true, "autocommit": false, "writeConcern": { "$$exists": false } }, "commandName": "insert", "databaseName": "transaction-tests" } }, { "commandStartedEvent": { "command": { "insert": "test", "documents": [ { "_id": 4 } ], "ordered": true, "readConcern": { "$$exists": false }, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": 1, "startTransaction": { "$$exists": false }, "autocommit": false, "writeConcern": { "$$exists": false } }, "commandName": "insert", "databaseName": "transaction-tests" } }, { "commandStartedEvent": { "command": { "commitTransaction": 1, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": 1, "startTransaction": { "$$exists": false }, "autocommit": false, "writeConcern": { "$$exists": false }, "recoveryToken": { "$$type": "object" } }, "commandName": "commitTransaction", "databaseName": "admin" } } ] } ], "outcome": [ { "collectionName": "test", "databaseName": "transaction-tests", "documents": [ { "_id": 1 }, { "_id": 2 }, { "_id": 3 } ] } ] }, { "description": "unpin after transient error within a transaction", "operations": [ { "name": "startTransaction", "object": "session0" }, { "name": "insertOne", "object": "collection0", "arguments": { "session": "session0", "document": { "_id": 3 } }, "expectResult": { "$$unsetOrMatches": { "insertedId": { "$$unsetOrMatches": 3 } } } }, { "name": "targetedFailPoint", "object": "testRunner", "arguments": { "session": "session0", "failPoint": { "configureFailPoint": "failCommand", "mode": { "times": 1 }, "data": { "failCommands": [ "insert" ], "closeConnection": true } } } }, { "name": "insertOne", "object": "collection0", "arguments": { "session": "session0", "document": { "_id": 4 } }, "expectError": { "errorLabelsContain": [ "TransientTransactionError" ], "errorLabelsOmit": [ "UnknownTransactionCommitResult" ] } }, { "name": "assertSessionUnpinned", "object": "testRunner", "arguments": { "session": "session0" } }, { "name": "abortTransaction", "object": "session0" } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "insert": "test", "documents": [ { "_id": 3 } ], "ordered": true, "readConcern": { "$$exists": false }, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": 1, "startTransaction": true, "autocommit": false, "writeConcern": { "$$exists": false } }, "commandName": "insert", "databaseName": "transaction-tests" } }, { "commandStartedEvent": { "command": { "insert": "test", "documents": [ { "_id": 4 } ], "ordered": true, "readConcern": { "$$exists": false }, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": 1, "startTransaction": { "$$exists": false }, "autocommit": false, "writeConcern": { "$$exists": false } }, "commandName": "insert", "databaseName": "transaction-tests" } }, { "commandStartedEvent": { "command": { "abortTransaction": 1, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": 1, "startTransaction": { "$$exists": false }, "autocommit": false, "writeConcern": { "$$exists": false }, "recoveryToken": { "$$type": "object" } }, "commandName": "abortTransaction", "databaseName": "admin" } } ] } ], "outcome": [ { "collectionName": "test", "databaseName": "transaction-tests", "documents": [ { "_id": 1 }, { "_id": 2 } ] } ] } ] } mongodb-mongo-python-driver-509e9b7/test/unified-test-format/valid-pass/poc-transactions.json000066400000000000000000000174371462766011000325430ustar00rootroot00000000000000{ "description": "poc-transactions", "schemaVersion": "1.0", "runOnRequirements": [ { "minServerVersion": "4.0", "topologies": [ "replicaset" ] }, { "minServerVersion": "4.1.8", "topologies": [ "sharded" ] } ], "createEntities": [ { "client": { "id": "client0", "observeEvents": [ "commandStartedEvent" ] } }, { "database": { "id": "database0", "client": "client0", "databaseName": "transaction-tests" } }, { "collection": { "id": "collection0", "database": "database0", "collectionName": "test" } }, { "session": { "id": "session0", "client": "client0" } } ], "initialData": [ { "collectionName": "test", "databaseName": "transaction-tests", "documents": [] } ], "tests": [ { "description": "Client side error in command starting transaction", "operations": [ { "name": "startTransaction", "object": "session0" }, { "name": "updateOne", "object": "collection0", "arguments": { "session": "session0", "filter": { "_id": 1 }, "update": { "x": 1 } }, "expectError": { "isClientError": true } }, { "name": "assertSessionTransactionState", "object": "testRunner", "arguments": { "session": "session0", "state": "starting" } } ] }, { "description": "explicitly create collection using create command", "runOnRequirements": [ { "minServerVersion": "4.3.4", "topologies": [ "replicaset", "sharded" ] } ], "operations": [ { "name": "dropCollection", "object": "database0", "arguments": { "collection": "test" } }, { "name": "startTransaction", "object": "session0" }, { "name": "createCollection", "object": "database0", "arguments": { "session": "session0", "collection": "test" } }, { "name": "assertCollectionNotExists", "object": "testRunner", "arguments": { "databaseName": "transaction-tests", "collectionName": "test" } }, { "name": "commitTransaction", "object": "session0" }, { "name": "assertCollectionExists", "object": "testRunner", "arguments": { "databaseName": "transaction-tests", "collectionName": "test" } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "drop": "test", "writeConcern": { "$$exists": false } }, "commandName": "drop", "databaseName": "transaction-tests" } }, { "commandStartedEvent": { "command": { "create": "test", "lsid": { "$$sessionLsid": "session0" }, "txnNumber": 1, "startTransaction": true, "autocommit": false, "writeConcern": { "$$exists": false } }, "commandName": "create", "databaseName": "transaction-tests" } }, { "commandStartedEvent": { "command": { "commitTransaction": 1, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": 1, "startTransaction": { "$$exists": false }, "autocommit": false, "writeConcern": { "$$exists": false } }, "commandName": "commitTransaction", "databaseName": "admin" } } ] } ] }, { "description": "create index on a non-existing collection", "runOnRequirements": [ { "minServerVersion": "4.3.4", "topologies": [ "replicaset", "sharded" ] } ], "operations": [ { "name": "dropCollection", "object": "database0", "arguments": { "collection": "test" } }, { "name": "startTransaction", "object": "session0" }, { "name": "createIndex", "object": "collection0", "arguments": { "session": "session0", "name": "x_1", "keys": { "x": 1 } } }, { "name": "assertIndexNotExists", "object": "testRunner", "arguments": { "databaseName": "transaction-tests", "collectionName": "test", "indexName": "x_1" } }, { "name": "commitTransaction", "object": "session0" }, { "name": "assertIndexExists", "object": "testRunner", "arguments": { "databaseName": "transaction-tests", "collectionName": "test", "indexName": "x_1" } } ], "expectEvents": [ { "client": "client0", "events": [ { "commandStartedEvent": { "command": { "drop": "test", "writeConcern": { "$$exists": false } }, "commandName": "drop", "databaseName": "transaction-tests" } }, { "commandStartedEvent": { "command": { "createIndexes": "test", "indexes": [ { "name": "x_1", "key": { "x": 1 } } ], "lsid": { "$$sessionLsid": "session0" }, "txnNumber": 1, "startTransaction": true, "autocommit": false, "writeConcern": { "$$exists": false } }, "commandName": "createIndexes", "databaseName": "transaction-tests" } }, { "commandStartedEvent": { "command": { "commitTransaction": 1, "lsid": { "$$sessionLsid": "session0" }, "txnNumber": 1, "startTransaction": { "$$exists": false }, "autocommit": false, "writeConcern": { "$$exists": false } }, "commandName": "commitTransaction", "databaseName": "admin" } } ] } ] } ] } mongodb-mongo-python-driver-509e9b7/test/unified_format.py000066400000000000000000002403411462766011000237650ustar00rootroot00000000000000# Copyright 2020-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. """Unified test format runner. https://github.com/mongodb/specifications/blob/master/source/unified-test-format/unified-test-format.rst """ from __future__ import annotations import binascii import collections import copy import datetime import functools import os import re import sys import time import traceback import types from collections import abc, defaultdict from test import ( AWS_CREDS, AWS_CREDS_2, AZURE_CREDS, CA_PEM, CLIENT_PEM, GCP_CREDS, KMIP_CREDS, LOCAL_MASTER_KEY, IntegrationTest, client_context, unittest, ) from test.utils import ( CMAPListener, camel_to_snake, camel_to_snake_args, get_pool, parse_collection_options, parse_spec_options, prepare_spec_arguments, rs_or_single_client, single_client, snake_to_camel, wait_until, ) from test.utils_spec_runner import SpecRunnerThread from test.version import Version from typing import Any, Dict, List, Mapping, Optional, Union import pymongo from bson import SON, Code, DBRef, Decimal128, Int64, MaxKey, MinKey, json_util from bson.binary import Binary from bson.codec_options import DEFAULT_CODEC_OPTIONS from bson.objectid import ObjectId from bson.regex import RE_TYPE, Regex from gridfs import GridFSBucket, GridOut from pymongo import ASCENDING, CursorType, MongoClient, _csot from pymongo.change_stream import ChangeStream from pymongo.client_session import ClientSession, TransactionOptions, _TxnState from pymongo.collection import Collection from pymongo.command_cursor import CommandCursor from pymongo.database import Database from pymongo.encryption import ClientEncryption from pymongo.encryption_options import _HAVE_PYMONGOCRYPT from pymongo.errors import ( BulkWriteError, ConfigurationError, ConnectionFailure, EncryptionError, InvalidOperation, NotPrimaryError, OperationFailure, PyMongoError, ) from pymongo.monitoring import ( _SENSITIVE_COMMANDS, CommandFailedEvent, CommandListener, CommandStartedEvent, CommandSucceededEvent, ConnectionCheckedInEvent, ConnectionCheckedOutEvent, ConnectionCheckOutFailedEvent, ConnectionCheckOutStartedEvent, ConnectionClosedEvent, ConnectionCreatedEvent, ConnectionReadyEvent, PoolClearedEvent, PoolClosedEvent, PoolCreatedEvent, PoolReadyEvent, ServerClosedEvent, ServerDescriptionChangedEvent, ServerHeartbeatFailedEvent, ServerHeartbeatListener, ServerHeartbeatStartedEvent, ServerHeartbeatSucceededEvent, ServerListener, ServerOpeningEvent, TopologyClosedEvent, TopologyDescriptionChangedEvent, TopologyEvent, TopologyListener, TopologyOpenedEvent, _CommandEvent, _ConnectionEvent, _PoolEvent, _ServerEvent, _ServerHeartbeatEvent, ) from pymongo.operations import SearchIndexModel from pymongo.read_concern import ReadConcern from pymongo.read_preferences import ReadPreference from pymongo.results import BulkWriteResult from pymongo.server_api import ServerApi from pymongo.server_description import ServerDescription from pymongo.server_selectors import Selection, writable_server_selector from pymongo.server_type import SERVER_TYPE from pymongo.topology_description import TopologyDescription from pymongo.typings import _Address from pymongo.write_concern import WriteConcern JSON_OPTS = json_util.JSONOptions(tz_aware=False) IS_INTERRUPTED = False KMS_TLS_OPTS = { "kmip": { "tlsCAFile": CA_PEM, "tlsCertificateKeyFile": CLIENT_PEM, } } # Build up a placeholder maps. PLACEHOLDER_MAP = {} for provider_name, provider_data in [ ("local", {"key": LOCAL_MASTER_KEY}), ("local:name1", {"key": LOCAL_MASTER_KEY}), ("aws", AWS_CREDS), ("aws:name1", AWS_CREDS), ("aws:name2", AWS_CREDS_2), ("azure", AZURE_CREDS), ("azure:name1", AZURE_CREDS), ("gcp", GCP_CREDS), ("gcp:name1", GCP_CREDS), ("kmip", KMIP_CREDS), ("kmip:name1", KMIP_CREDS), ]: for key, value in provider_data.items(): placeholder = f"/clientEncryptionOpts/kmsProviders/{provider_name}/{key}" PLACEHOLDER_MAP[placeholder] = value OIDC_ENV = os.environ.get("OIDC_ENV", "test") if OIDC_ENV == "test": PLACEHOLDER_MAP["/uriOptions/authMechanismProperties"] = {"ENVIRONMENT": "test"} elif OIDC_ENV == "azure": PLACEHOLDER_MAP["/uriOptions/authMechanismProperties"] = { "ENVIRONMENT": "azure", "TOKEN_RESOURCE": os.environ["AZUREOIDC_RESOURCE"], } elif OIDC_ENV == "gcp": PLACEHOLDER_MAP["/uriOptions/authMechanismProperties"] = { "ENVIRONMENT": "gcp", "TOKEN_RESOURCE": os.environ["GCPOIDC_AUDIENCE"], } def interrupt_loop(): global IS_INTERRUPTED IS_INTERRUPTED = True def with_metaclass(meta, *bases): """Create a base class with a metaclass. Vendored from six: https://github.com/benjaminp/six/blob/master/six.py """ # This requires a bit of explanation: the basic idea is to make a dummy # metaclass for one level of class instantiation that replaces itself with # the actual metaclass. class metaclass(type): def __new__(cls, name, this_bases, d): if sys.version_info[:2] >= (3, 7): # noqa: UP036 # This version introduced PEP 560 that requires a bit # of extra care (we mimic what is done by __build_class__). resolved_bases = types.resolve_bases(bases) if resolved_bases is not bases: d["__orig_bases__"] = bases else: resolved_bases = bases return meta(name, resolved_bases, d) @classmethod def __prepare__(cls, name, this_bases): return meta.__prepare__(name, bases) return type.__new__(metaclass, "temporary_class", (), {}) def is_run_on_requirement_satisfied(requirement): topology_satisfied = True req_topologies = requirement.get("topologies") if req_topologies: topology_satisfied = client_context.is_topology_type(req_topologies) server_version = Version(*client_context.version[:3]) min_version_satisfied = True req_min_server_version = requirement.get("minServerVersion") if req_min_server_version: min_version_satisfied = Version.from_string(req_min_server_version) <= server_version max_version_satisfied = True req_max_server_version = requirement.get("maxServerVersion") if req_max_server_version: max_version_satisfied = Version.from_string(req_max_server_version) >= server_version serverless = requirement.get("serverless") if serverless == "require": serverless_satisfied = client_context.serverless elif serverless == "forbid": serverless_satisfied = not client_context.serverless else: # unset or "allow" serverless_satisfied = True params_satisfied = True params = requirement.get("serverParameters") if params: for param, val in params.items(): if param not in client_context.server_parameters: params_satisfied = False elif client_context.server_parameters[param] != val: params_satisfied = False auth_satisfied = True req_auth = requirement.get("auth") if req_auth is not None: if req_auth: auth_satisfied = client_context.auth_enabled if auth_satisfied and "authMechanism" in requirement: auth_satisfied = client_context.check_auth_type(requirement["authMechanism"]) else: auth_satisfied = not client_context.auth_enabled csfle_satisfied = True req_csfle = requirement.get("csfle") if req_csfle is True: min_version_satisfied = Version.from_string("4.2") <= server_version csfle_satisfied = _HAVE_PYMONGOCRYPT and min_version_satisfied return ( topology_satisfied and min_version_satisfied and max_version_satisfied and serverless_satisfied and params_satisfied and auth_satisfied and csfle_satisfied ) def parse_collection_or_database_options(options): return parse_collection_options(options) def parse_bulk_write_result(result): upserted_ids = {str(int_idx): result.upserted_ids[int_idx] for int_idx in result.upserted_ids} return { "deletedCount": result.deleted_count, "insertedCount": result.inserted_count, "matchedCount": result.matched_count, "modifiedCount": result.modified_count, "upsertedCount": result.upserted_count, "upsertedIds": upserted_ids, } def parse_bulk_write_error_result(error): write_result = BulkWriteResult(error.details, True) return parse_bulk_write_result(write_result) class NonLazyCursor: """A find cursor proxy that creates the remote cursor when initialized.""" def __init__(self, find_cursor, client): self.client = client self.find_cursor = find_cursor # Create the server side cursor. self.first_result = next(find_cursor, None) @property def alive(self): return self.first_result is not None or self.find_cursor.alive def __next__(self): if self.first_result is not None: first = self.first_result self.first_result = None return first return next(self.find_cursor) # Added to support the iterateOnce operation. try_next = __next__ def close(self): self.find_cursor.close() self.client = None class EventListenerUtil( CMAPListener, CommandListener, ServerListener, ServerHeartbeatListener, TopologyListener ): def __init__( self, observe_events, ignore_commands, observe_sensitive_commands, store_events, entity_map ): self._event_types = {name.lower() for name in observe_events} if observe_sensitive_commands: self._observe_sensitive_commands = True self._ignore_commands = set(ignore_commands) else: self._observe_sensitive_commands = False self._ignore_commands = _SENSITIVE_COMMANDS | set(ignore_commands) self._ignore_commands.add("configurefailpoint") self._event_mapping = collections.defaultdict(list) self.entity_map = entity_map if store_events: for i in store_events: id = i["id"] events = (i.lower() for i in i["events"]) for i in events: self._event_mapping[i].append(id) self.entity_map[id] = [] super().__init__() def get_events(self, event_type): assert event_type in ("command", "cmap", "sdam", "all"), event_type if event_type == "all": return list(self.events) if event_type == "command": return [e for e in self.events if isinstance(e, _CommandEvent)] if event_type == "cmap": return [e for e in self.events if isinstance(e, (_ConnectionEvent, _PoolEvent))] return [ e for e in self.events if isinstance(e, (_ServerEvent, TopologyEvent, _ServerHeartbeatEvent)) ] def add_event(self, event): event_name = type(event).__name__.lower() if event_name in self._event_types: super().add_event(event) for id in self._event_mapping[event_name]: self.entity_map[id].append( { "name": type(event).__name__, "observedAt": time.time(), "description": repr(event), } ) def _command_event(self, event): if event.command_name.lower() not in self._ignore_commands: self.add_event(event) def started(self, event): if isinstance(event, CommandStartedEvent): if event.command == {}: # Command is redacted. Observe only if flag is set. if self._observe_sensitive_commands: self._command_event(event) else: self._command_event(event) else: self.add_event(event) def succeeded(self, event): if isinstance(event, CommandSucceededEvent): if event.reply == {}: # Command is redacted. Observe only if flag is set. if self._observe_sensitive_commands: self._command_event(event) else: self._command_event(event) else: self.add_event(event) def failed(self, event): if isinstance(event, CommandFailedEvent): self._command_event(event) else: self.add_event(event) def opened(self, event: Union[ServerOpeningEvent, TopologyOpenedEvent]) -> None: self.add_event(event) def description_changed( self, event: Union[ServerDescriptionChangedEvent, TopologyDescriptionChangedEvent] ) -> None: self.add_event(event) def topology_changed(self, event: TopologyDescriptionChangedEvent) -> None: self.add_event(event) def closed(self, event: Union[ServerClosedEvent, TopologyClosedEvent]) -> None: self.add_event(event) class EntityMapUtil: """Utility class that implements an entity map as per the unified test format specification. """ def __init__(self, test_class): self._entities: Dict[str, Any] = {} self._listeners: Dict[str, EventListenerUtil] = {} self._session_lsids: Dict[str, Mapping[str, Any]] = {} self.test: UnifiedSpecTestMixinV1 = test_class self._cluster_time: Mapping[str, Any] = {} def __contains__(self, item): return item in self._entities def __len__(self): return len(self._entities) def __getitem__(self, item): try: return self._entities[item] except KeyError: self.test.fail(f"Could not find entity named {item} in map") def __setitem__(self, key, value): if not isinstance(key, str): self.test.fail("Expected entity name of type str, got %s" % (type(key))) if key in self._entities: self.test.fail(f"Entity named {key} already in map") self._entities[key] = value def _handle_placeholders(self, spec: dict, current: dict, path: str) -> Any: if "$$placeholder" in current: if path not in PLACEHOLDER_MAP: raise ValueError(f"Could not find a placeholder value for {path}") return PLACEHOLDER_MAP[path] for key in list(current): value = current[key] if isinstance(value, dict): subpath = f"{path}/{key}" current[key] = self._handle_placeholders(spec, value, subpath) return current def _create_entity(self, entity_spec, uri=None): if len(entity_spec) != 1: self.test.fail(f"Entity spec {entity_spec} did not contain exactly one top-level key") entity_type, spec = next(iter(entity_spec.items())) spec = self._handle_placeholders(spec, spec, "") if entity_type == "client": kwargs: dict = {} observe_events = spec.get("observeEvents", []) ignore_commands = spec.get("ignoreCommandMonitoringEvents", []) observe_sensitive_commands = spec.get("observeSensitiveCommands", False) ignore_commands = [cmd.lower() for cmd in ignore_commands] listener = EventListenerUtil( observe_events, ignore_commands, observe_sensitive_commands, spec.get("storeEventsAsEntities"), self, ) self._listeners[spec["id"]] = listener kwargs["event_listeners"] = [listener] if spec.get("useMultipleMongoses"): if client_context.load_balancer or client_context.serverless: kwargs["h"] = client_context.MULTI_MONGOS_LB_URI elif client_context.is_mongos: kwargs["h"] = client_context.mongos_seeds() kwargs.update(spec.get("uriOptions", {})) server_api = spec.get("serverApi") if "waitQueueSize" in kwargs: raise unittest.SkipTest("PyMongo does not support waitQueueSize") if "waitQueueMultiple" in kwargs: raise unittest.SkipTest("PyMongo does not support waitQueueMultiple") if server_api: kwargs["server_api"] = ServerApi( server_api["version"], strict=server_api.get("strict"), deprecation_errors=server_api.get("deprecationErrors"), ) if uri: kwargs["h"] = uri client = rs_or_single_client(**kwargs) self[spec["id"]] = client self.test.addCleanup(client.close) return elif entity_type == "database": client = self[spec["client"]] if not isinstance(client, MongoClient): self.test.fail( "Expected entity {} to be of type MongoClient, got {}".format( spec["client"], type(client) ) ) options = parse_collection_or_database_options(spec.get("databaseOptions", {})) self[spec["id"]] = client.get_database(spec["databaseName"], **options) return elif entity_type == "collection": database = self[spec["database"]] if not isinstance(database, Database): self.test.fail( "Expected entity {} to be of type Database, got {}".format( spec["database"], type(database) ) ) options = parse_collection_or_database_options(spec.get("collectionOptions", {})) self[spec["id"]] = database.get_collection(spec["collectionName"], **options) return elif entity_type == "session": client = self[spec["client"]] if not isinstance(client, MongoClient): self.test.fail( "Expected entity {} to be of type MongoClient, got {}".format( spec["client"], type(client) ) ) opts = camel_to_snake_args(spec.get("sessionOptions", {})) if "default_transaction_options" in opts: txn_opts = parse_spec_options(opts["default_transaction_options"]) txn_opts = TransactionOptions(**txn_opts) opts = copy.deepcopy(opts) opts["default_transaction_options"] = txn_opts session = client.start_session(**dict(opts)) self[spec["id"]] = session self._session_lsids[spec["id"]] = copy.deepcopy(session.session_id) self.test.addCleanup(session.end_session) return elif entity_type == "bucket": db = self[spec["database"]] kwargs = parse_spec_options(spec.get("bucketOptions", {}).copy()) bucket = GridFSBucket(db, **kwargs) # PyMongo does not support GridFSBucket.drop(), emulate it. @_csot.apply def drop(self: GridFSBucket, *args: Any, **kwargs: Any) -> None: self._files.drop(*args, **kwargs) self._chunks.drop(*args, **kwargs) if not hasattr(bucket, "drop"): bucket.drop = drop.__get__(bucket) self[spec["id"]] = bucket return elif entity_type == "clientEncryption": opts = camel_to_snake_args(spec["clientEncryptionOpts"].copy()) if isinstance(opts["key_vault_client"], str): opts["key_vault_client"] = self[opts["key_vault_client"]] # Set TLS options for providers like "kmip:name1". kms_tls_options = {} for provider in opts["kms_providers"]: provider_type = provider.split(":")[0] if provider_type in KMS_TLS_OPTS: kms_tls_options[provider] = KMS_TLS_OPTS[provider_type] self[spec["id"]] = ClientEncryption( opts["kms_providers"], opts["key_vault_namespace"], opts["key_vault_client"], DEFAULT_CODEC_OPTIONS, opts.get("kms_tls_options", kms_tls_options), ) return elif entity_type == "thread": name = spec["id"] thread = SpecRunnerThread(name) thread.start() self[name] = thread return self.test.fail(f"Unable to create entity of unknown type {entity_type}") def create_entities_from_spec(self, entity_spec, uri=None): for spec in entity_spec: self._create_entity(spec, uri=uri) def get_listener_for_client(self, client_name: str) -> EventListenerUtil: client = self[client_name] if not isinstance(client, MongoClient): self.test.fail( f"Expected entity {client_name} to be of type MongoClient, got {type(client)}" ) listener = self._listeners.get(client_name) if not listener: self.test.fail(f"No listeners configured for client {client_name}") return listener def get_lsid_for_session(self, session_name): session = self[session_name] if not isinstance(session, ClientSession): self.test.fail( f"Expected entity {session_name} to be of type ClientSession, got {type(session)}" ) try: return session.session_id except InvalidOperation: # session has been closed. return self._session_lsids[session_name] def advance_cluster_times(self) -> None: """Manually synchronize entities when desired""" if not self._cluster_time: self._cluster_time = self.test.client.admin.command("ping").get("$clusterTime") for entity in self._entities.values(): if isinstance(entity, ClientSession) and self._cluster_time: entity.advance_cluster_time(self._cluster_time) binary_types = (Binary, bytes) long_types = (Int64,) unicode_type = str BSON_TYPE_ALIAS_MAP = { # https://mongodb.com/docs/manual/reference/operator/query/type/ # https://pymongo.readthedocs.io/en/stable/api/bson/index.html "double": (float,), "string": (str,), "object": (abc.Mapping,), "array": (abc.MutableSequence,), "binData": binary_types, "undefined": (type(None),), "objectId": (ObjectId,), "bool": (bool,), "date": (datetime.datetime,), "null": (type(None),), "regex": (Regex, RE_TYPE), "dbPointer": (DBRef,), "javascript": (unicode_type, Code), "symbol": (unicode_type,), "javascriptWithScope": (unicode_type, Code), "int": (int,), "long": (Int64,), "decimal": (Decimal128,), "maxKey": (MaxKey,), "minKey": (MinKey,), } class MatchEvaluatorUtil: """Utility class that implements methods for evaluating matches as per the unified test format specification. """ def __init__(self, test_class): self.test = test_class def _operation_exists(self, spec, actual, key_to_compare): if spec is True: if key_to_compare is None: assert actual is not None else: self.test.assertIn(key_to_compare, actual) elif spec is False: if key_to_compare is None: assert actual is None else: self.test.assertNotIn(key_to_compare, actual) else: self.test.fail(f"Expected boolean value for $$exists operator, got {spec}") def __type_alias_to_type(self, alias): if alias not in BSON_TYPE_ALIAS_MAP: self.test.fail(f"Unrecognized BSON type alias {alias}") return BSON_TYPE_ALIAS_MAP[alias] def _operation_type(self, spec, actual, key_to_compare): if isinstance(spec, abc.MutableSequence): permissible_types = tuple( [t for alias in spec for t in self.__type_alias_to_type(alias)] ) else: permissible_types = self.__type_alias_to_type(spec) value = actual[key_to_compare] if key_to_compare else actual self.test.assertIsInstance(value, permissible_types) def _operation_matchesEntity(self, spec, actual, key_to_compare): expected_entity = self.test.entity_map[spec] self.test.assertEqual(expected_entity, actual[key_to_compare]) def _operation_matchesHexBytes(self, spec, actual, key_to_compare): expected = binascii.unhexlify(spec) value = actual[key_to_compare] if key_to_compare else actual self.test.assertEqual(value, expected) def _operation_unsetOrMatches(self, spec, actual, key_to_compare): if key_to_compare is None and not actual: # top-level document can be None when unset return if key_to_compare not in actual: # we add a dummy value for the compared key to pass map size check actual[key_to_compare] = "dummyValue" return self.match_result(spec, actual[key_to_compare], in_recursive_call=True) def _operation_sessionLsid(self, spec, actual, key_to_compare): expected_lsid = self.test.entity_map.get_lsid_for_session(spec) self.test.assertEqual(expected_lsid, actual[key_to_compare]) def _operation_lte(self, spec, actual, key_to_compare): if key_to_compare not in actual: self.test.fail(f"Actual command is missing the {key_to_compare} field: {spec}") self.test.assertLessEqual(actual[key_to_compare], spec) def _operation_matchAsDocument(self, spec, actual, key_to_compare): self._match_document(spec, json_util.loads(actual[key_to_compare]), False) def _operation_matchAsRoot(self, spec, actual, key_to_compare): self._match_document(spec, actual, True) def _evaluate_special_operation(self, opname, spec, actual, key_to_compare): method_name = "_operation_{}".format(opname.strip("$")) try: method = getattr(self, method_name) except AttributeError: self.test.fail(f"Unsupported special matching operator {opname}") else: method(spec, actual, key_to_compare) def _evaluate_if_special_operation(self, expectation, actual, key_to_compare=None): """Returns True if a special operation is evaluated, False otherwise. If the ``expectation`` map contains a single key, value pair we check it for a special operation. If given, ``key_to_compare`` is assumed to be the key in ``expectation`` whose corresponding value needs to be evaluated for a possible special operation. ``key_to_compare`` is ignored when ``expectation`` has only one key. """ if not isinstance(expectation, abc.Mapping): return False is_special_op, opname, spec = False, False, False if key_to_compare is not None: if key_to_compare.startswith("$$"): is_special_op = True opname = key_to_compare spec = expectation[key_to_compare] key_to_compare = None else: nested = expectation[key_to_compare] if isinstance(nested, abc.Mapping) and len(nested) == 1: opname, spec = next(iter(nested.items())) if opname.startswith("$$"): is_special_op = True elif len(expectation) == 1: opname, spec = next(iter(expectation.items())) if opname.startswith("$$"): is_special_op = True key_to_compare = None if is_special_op: self._evaluate_special_operation( opname=opname, spec=spec, actual=actual, key_to_compare=key_to_compare ) return True return False def _match_document(self, expectation, actual, is_root): if self._evaluate_if_special_operation(expectation, actual): return self.test.assertIsInstance(actual, abc.Mapping) for key, value in expectation.items(): if self._evaluate_if_special_operation(expectation, actual, key): continue self.test.assertIn(key, actual) self.match_result(value, actual[key], in_recursive_call=True) if not is_root: expected_keys = set(expectation.keys()) for key, value in expectation.items(): if value == {"$$exists": False}: expected_keys.remove(key) self.test.assertEqual(expected_keys, set(actual.keys())) def match_result(self, expectation, actual, in_recursive_call=False): if isinstance(expectation, abc.Mapping): return self._match_document(expectation, actual, is_root=not in_recursive_call) if isinstance(expectation, abc.MutableSequence): self.test.assertIsInstance(actual, abc.MutableSequence) for e, a in zip(expectation, actual): if isinstance(e, abc.Mapping): self._match_document(e, a, is_root=not in_recursive_call) else: self.match_result(e, a, in_recursive_call=True) return None # account for flexible numerics in element-wise comparison if isinstance(expectation, int) or isinstance(expectation, float): self.test.assertEqual(expectation, actual) return None else: self.test.assertIsInstance(actual, type(expectation)) self.test.assertEqual(expectation, actual) return None def match_server_description(self, actual: ServerDescription, spec: dict) -> None: for field, expected in spec.items(): field = camel_to_snake(field) if field == "type": field = "server_type_name" self.test.assertEqual(getattr(actual, field), expected) def match_topology_description(self, actual: TopologyDescription, spec: dict) -> None: for field, expected in spec.items(): field = camel_to_snake(field) if field == "type": field = "topology_type_name" self.test.assertEqual(getattr(actual, field), expected) def match_event_fields(self, actual: Any, spec: dict) -> None: for field, expected in spec.items(): if field == "command" and isinstance(actual, CommandStartedEvent): command = spec["command"] if command: self.match_result(command, actual.command) continue if field == "reply" and isinstance(actual, CommandSucceededEvent): reply = spec["reply"] if reply: self.match_result(reply, actual.reply) continue if field == "hasServiceId": if spec["hasServiceId"]: self.test.assertIsNotNone(actual.service_id) self.test.assertIsInstance(actual.service_id, ObjectId) else: self.test.assertIsNone(actual.service_id) continue if field == "hasServerConnectionId": if spec["hasServerConnectionId"]: self.test.assertIsNotNone(actual.server_connection_id) self.test.assertIsInstance(actual.server_connection_id, int) else: self.test.assertIsNone(actual.server_connection_id) continue if field in ("previousDescription", "newDescription"): if isinstance(actual, ServerDescriptionChangedEvent): self.match_server_description( getattr(actual, camel_to_snake(field)), spec[field] ) continue if isinstance(actual, TopologyDescriptionChangedEvent): self.match_topology_description( getattr(actual, camel_to_snake(field)), spec[field] ) continue if field == "interruptInUseConnections": field = "interrupt_connections" else: field = camel_to_snake(field) self.test.assertEqual(getattr(actual, field), expected) def match_event(self, expectation, actual): name, spec = next(iter(expectation.items())) if name == "commandStartedEvent": self.test.assertIsInstance(actual, CommandStartedEvent) elif name == "commandSucceededEvent": self.test.assertIsInstance(actual, CommandSucceededEvent) elif name == "commandFailedEvent": self.test.assertIsInstance(actual, CommandFailedEvent) elif name == "poolCreatedEvent": self.test.assertIsInstance(actual, PoolCreatedEvent) elif name == "poolReadyEvent": self.test.assertIsInstance(actual, PoolReadyEvent) elif name == "poolClearedEvent": self.test.assertIsInstance(actual, PoolClearedEvent) self.test.assertIsInstance(actual.interrupt_connections, bool) elif name == "poolClosedEvent": self.test.assertIsInstance(actual, PoolClosedEvent) elif name == "connectionCreatedEvent": self.test.assertIsInstance(actual, ConnectionCreatedEvent) elif name == "connectionReadyEvent": self.test.assertIsInstance(actual, ConnectionReadyEvent) elif name == "connectionClosedEvent": self.test.assertIsInstance(actual, ConnectionClosedEvent) elif name == "connectionCheckOutStartedEvent": self.test.assertIsInstance(actual, ConnectionCheckOutStartedEvent) elif name == "connectionCheckOutFailedEvent": self.test.assertIsInstance(actual, ConnectionCheckOutFailedEvent) elif name == "connectionCheckedOutEvent": self.test.assertIsInstance(actual, ConnectionCheckedOutEvent) elif name == "connectionCheckedInEvent": self.test.assertIsInstance(actual, ConnectionCheckedInEvent) elif name == "serverDescriptionChangedEvent": self.test.assertIsInstance(actual, ServerDescriptionChangedEvent) elif name == "serverHeartbeatStartedEvent": self.test.assertIsInstance(actual, ServerHeartbeatStartedEvent) elif name == "serverHeartbeatSucceededEvent": self.test.assertIsInstance(actual, ServerHeartbeatSucceededEvent) elif name == "serverHeartbeatFailedEvent": self.test.assertIsInstance(actual, ServerHeartbeatFailedEvent) elif name == "topologyDescriptionChangedEvent": self.test.assertIsInstance(actual, TopologyDescriptionChangedEvent) else: raise Exception(f"Unsupported event type {name}") self.match_event_fields(actual, spec) def coerce_result(opname, result): """Convert a pymongo result into the spec's result format.""" if hasattr(result, "acknowledged") and not result.acknowledged: return {"acknowledged": False} if opname == "bulkWrite": return parse_bulk_write_result(result) if opname == "insertOne": return {"insertedId": result.inserted_id} if opname == "insertMany": return dict(enumerate(result.inserted_ids)) if opname in ("deleteOne", "deleteMany"): return {"deletedCount": result.deleted_count} if opname in ("updateOne", "updateMany", "replaceOne"): value = { "matchedCount": result.matched_count, "modifiedCount": result.modified_count, "upsertedCount": 0 if result.upserted_id is None else 1, } if result.upserted_id is not None: value["upsertedId"] = result.upserted_id return value return result class UnifiedSpecTestMixinV1(IntegrationTest): """Mixin class to run test cases from test specification files. Assumes that tests conform to the `unified test format `_. Specification of the test suite being currently run is available as a class attribute ``TEST_SPEC``. """ SCHEMA_VERSION = Version.from_string("1.20") RUN_ON_LOAD_BALANCER = True RUN_ON_SERVERLESS = True TEST_SPEC: Any mongos_clients: list[MongoClient] = [] @staticmethod def should_run_on(run_on_spec): if not run_on_spec: # Always run these tests. return True for req in run_on_spec: if is_run_on_requirement_satisfied(req): return True return False def insert_initial_data(self, initial_data): for i, collection_data in enumerate(initial_data): coll_name = collection_data["collectionName"] db_name = collection_data["databaseName"] opts = collection_data.get("createOptions", {}) documents = collection_data["documents"] # Setup the collection with as few majority writes as possible. db = self.client[db_name] db.drop_collection(coll_name) # Only use majority wc only on the final write. if i == len(initial_data) - 1: wc = WriteConcern(w="majority") else: wc = WriteConcern(w=1) if documents: if opts: db.create_collection(coll_name, **opts) db.get_collection(coll_name, write_concern=wc).insert_many(documents) else: # Ensure collection exists db.create_collection(coll_name, write_concern=wc, **opts) @classmethod def setUpClass(cls): # super call creates internal client cls.client super().setUpClass() # process file-level runOnRequirements run_on_spec = cls.TEST_SPEC.get("runOnRequirements", []) if not cls.should_run_on(run_on_spec): raise unittest.SkipTest(f"{cls.__name__} runOnRequirements not satisfied") # Handle mongos_clients for transactions tests. cls.mongos_clients = [] if ( client_context.supports_transactions() and not client_context.load_balancer and not client_context.serverless ): for address in client_context.mongoses: cls.mongos_clients.append(single_client("{}:{}".format(*address))) # add any special-casing for skipping tests here if client_context.storage_engine == "mmapv1": if "retryable-writes" in cls.TEST_SPEC["description"]: raise unittest.SkipTest("MMAPv1 does not support retryWrites=True") def setUp(self): super().setUp() # process schemaVersion # note: we check major schema version during class generation # note: we do this here because we cannot run assertions in setUpClass version = Version.from_string(self.TEST_SPEC["schemaVersion"]) self.assertLessEqual( version, self.SCHEMA_VERSION, f"expected schema version {self.SCHEMA_VERSION} or lower, got {version}", ) # initialize internals self.match_evaluator = MatchEvaluatorUtil(self) self.IS_SERVERLESS_PROXY = os.environ.get("IS_SERVERLESS_PROXY") def maybe_skip_test(self, spec): # add any special-casing for skipping tests here if client_context.storage_engine == "mmapv1": if ( "Dirty explicit session is discarded" in spec["description"] or "Dirty implicit session is discarded" in spec["description"] or "Cancel server check" in spec["description"] ): self.skipTest("MMAPv1 does not support retryWrites=True") if "Client side error in command starting transaction" in spec["description"]: self.skipTest("Implement PYTHON-1894") if "timeoutMS applied to entire download" in spec["description"]: self.skipTest("PyMongo's open_download_stream does not cap the stream's lifetime") if "unpin after non-transient error on abort" in spec["description"]: if client_context.version[0] == 8: self.skipTest("Skipping TransientTransactionError pending PYTHON-4182") if self.IS_SERVERLESS_PROXY is not None and ( "errors during the initial connection hello are ignored" in spec["description"] or "pinned connection is released after a transient network commit error" in spec["description"] ): self.skipTest("waiting on CLOUDP-202309") class_name = self.__class__.__name__.lower() description = spec["description"].lower() if "csot" in class_name: if "gridfs" in class_name and sys.platform == "win32": self.skipTest("PYTHON-3522 CSOT GridFS tests are flaky on Windows") if client_context.storage_engine == "mmapv1": self.skipTest( "MMAPv1 does not support retryable writes which is required for CSOT tests" ) if "change" in description or "change" in class_name: self.skipTest("CSOT not implemented for watch()") if "cursors" in class_name: self.skipTest("CSOT not implemented for cursors") if "tailable" in class_name: self.skipTest("CSOT not implemented for tailable cursors") if "sessions" in class_name: self.skipTest("CSOT not implemented for sessions") if "withtransaction" in description: self.skipTest("CSOT not implemented for with_transaction") if "transaction" in class_name or "transaction" in description: self.skipTest("CSOT not implemented for transactions") # Some tests need to be skipped based on the operations they try to run. for op in spec["operations"]: name = op["name"] if name == "count": self.skipTest("PyMongo does not support count()") if name == "listIndexNames": self.skipTest("PyMongo does not support list_index_names()") if client_context.storage_engine == "mmapv1": if name == "createChangeStream": self.skipTest("MMAPv1 does not support change streams") if name == "withTransaction" or name == "startTransaction": self.skipTest("MMAPv1 does not support document-level locking") if not client_context.test_commands_enabled: if name == "failPoint" or name == "targetedFailPoint": self.skipTest("Test commands must be enabled to use fail points") if name == "modifyCollection": self.skipTest("PyMongo does not support modifyCollection") if "timeoutMode" in op.get("arguments", {}): self.skipTest("PyMongo does not support timeoutMode") def process_error(self, exception, spec): is_error = spec.get("isError") is_client_error = spec.get("isClientError") is_timeout_error = spec.get("isTimeoutError") error_contains = spec.get("errorContains") error_code = spec.get("errorCode") error_code_name = spec.get("errorCodeName") error_labels_contain = spec.get("errorLabelsContain") error_labels_omit = spec.get("errorLabelsOmit") expect_result = spec.get("expectResult") error_response = spec.get("errorResponse") if error_response: self.match_evaluator.match_result(error_response, exception.details) if is_error: # already satisfied because exception was raised pass if is_client_error: # Connection errors are considered client errors. if isinstance(exception, ConnectionFailure): self.assertNotIsInstance(exception, NotPrimaryError) elif isinstance(exception, (InvalidOperation, ConfigurationError, EncryptionError)): pass else: self.assertNotIsInstance(exception, PyMongoError) if is_timeout_error: self.assertIsInstance(exception, PyMongoError) if not exception.timeout: # Re-raise the exception for better diagnostics. raise exception if error_contains: if isinstance(exception, BulkWriteError): errmsg = str(exception.details).lower() else: errmsg = str(exception).lower() self.assertIn(error_contains.lower(), errmsg) if error_code: self.assertEqual(error_code, exception.details.get("code")) if error_code_name: self.assertEqual(error_code_name, exception.details.get("codeName")) if error_labels_contain: labels = [ err_label for err_label in error_labels_contain if exception.has_error_label(err_label) ] self.assertEqual(labels, error_labels_contain) if error_labels_omit: for err_label in error_labels_omit: if exception.has_error_label(err_label): self.fail(f"Exception '{exception}' unexpectedly had label '{err_label}'") if expect_result: if isinstance(exception, BulkWriteError): result = parse_bulk_write_error_result(exception) self.match_evaluator.match_result(expect_result, result) else: self.fail(f"expectResult can only be specified with {BulkWriteError} exceptions") return exception def __raise_if_unsupported(self, opname, target, *target_types): if not isinstance(target, target_types): self.fail(f"Operation {opname} not supported for entity of type {type(target)}") def __entityOperation_createChangeStream(self, target, *args, **kwargs): if client_context.storage_engine == "mmapv1": self.skipTest("MMAPv1 does not support change streams") self.__raise_if_unsupported("createChangeStream", target, MongoClient, Database, Collection) stream = target.watch(*args, **kwargs) self.addCleanup(stream.close) return stream def _clientOperation_createChangeStream(self, target, *args, **kwargs): return self.__entityOperation_createChangeStream(target, *args, **kwargs) def _databaseOperation_createChangeStream(self, target, *args, **kwargs): return self.__entityOperation_createChangeStream(target, *args, **kwargs) def _collectionOperation_createChangeStream(self, target, *args, **kwargs): return self.__entityOperation_createChangeStream(target, *args, **kwargs) def _databaseOperation_runCommand(self, target, **kwargs): self.__raise_if_unsupported("runCommand", target, Database) # Ensure the first key is the command name. ordered_command = SON([(kwargs.pop("command_name"), 1)]) ordered_command.update(kwargs["command"]) kwargs["command"] = ordered_command return target.command(**kwargs) def _databaseOperation_runCursorCommand(self, target, **kwargs): return list(self._databaseOperation_createCommandCursor(target, **kwargs)) def _databaseOperation_createCommandCursor(self, target, **kwargs): self.__raise_if_unsupported("createCommandCursor", target, Database) # Ensure the first key is the command name. ordered_command = SON([(kwargs.pop("command_name"), 1)]) ordered_command.update(kwargs["command"]) kwargs["command"] = ordered_command batch_size = 0 cursor_type = kwargs.pop("cursor_type", "nonTailable") if cursor_type == CursorType.TAILABLE: ordered_command["tailable"] = True elif cursor_type == CursorType.TAILABLE_AWAIT: ordered_command["tailable"] = True ordered_command["awaitData"] = True elif cursor_type != "nonTailable": self.fail(f"unknown cursorType: {cursor_type}") if "maxTimeMS" in kwargs: kwargs["max_await_time_ms"] = kwargs.pop("maxTimeMS") if "batch_size" in kwargs: batch_size = kwargs.pop("batch_size") cursor = target.cursor_command(**kwargs) if batch_size > 0: cursor.batch_size(batch_size) return cursor def kill_all_sessions(self): if getattr(self, "client", None) is None: return clients = self.mongos_clients if self.mongos_clients else [self.client] for client in clients: try: client.admin.command("killAllSessions", []) except OperationFailure: # "operation was interrupted" by killing the command's # own session. pass def _databaseOperation_listCollections(self, target, *args, **kwargs): if "batch_size" in kwargs: kwargs["cursor"] = {"batchSize": kwargs.pop("batch_size")} cursor = target.list_collections(*args, **kwargs) return list(cursor) def _databaseOperation_createCollection(self, target, *args, **kwargs): # PYTHON-1936 Ignore the listCollections event from create_collection. kwargs["check_exists"] = False ret = target.create_collection(*args, **kwargs) return ret def __entityOperation_aggregate(self, target, *args, **kwargs): self.__raise_if_unsupported("aggregate", target, Database, Collection) return list(target.aggregate(*args, **kwargs)) def _databaseOperation_aggregate(self, target, *args, **kwargs): return self.__entityOperation_aggregate(target, *args, **kwargs) def _collectionOperation_aggregate(self, target, *args, **kwargs): return self.__entityOperation_aggregate(target, *args, **kwargs) def _collectionOperation_find(self, target, *args, **kwargs): self.__raise_if_unsupported("find", target, Collection) find_cursor = target.find(*args, **kwargs) return list(find_cursor) def _collectionOperation_createFindCursor(self, target, *args, **kwargs): self.__raise_if_unsupported("find", target, Collection) if "filter" not in kwargs: self.fail('createFindCursor requires a "filter" argument') cursor = NonLazyCursor(target.find(*args, **kwargs), target.database.client) self.addCleanup(cursor.close) return cursor def _collectionOperation_count(self, target, *args, **kwargs): self.skipTest("PyMongo does not support collection.count()") def _collectionOperation_listIndexes(self, target, *args, **kwargs): if "batch_size" in kwargs: self.skipTest("PyMongo does not support batch_size for list_indexes") return list(target.list_indexes(*args, **kwargs)) def _collectionOperation_listIndexNames(self, target, *args, **kwargs): self.skipTest("PyMongo does not support list_index_names") def _collectionOperation_createSearchIndexes(self, target, *args, **kwargs): models = [SearchIndexModel(**i) for i in kwargs["models"]] return target.create_search_indexes(models) def _collectionOperation_listSearchIndexes(self, target, *args, **kwargs): name = kwargs.get("name") agg_kwargs = kwargs.get("aggregation_options", dict()) return list(target.list_search_indexes(name, **agg_kwargs)) def _sessionOperation_withTransaction(self, target, *args, **kwargs): if client_context.storage_engine == "mmapv1": self.skipTest("MMAPv1 does not support document-level locking") self.__raise_if_unsupported("withTransaction", target, ClientSession) return target.with_transaction(*args, **kwargs) def _sessionOperation_startTransaction(self, target, *args, **kwargs): if client_context.storage_engine == "mmapv1": self.skipTest("MMAPv1 does not support document-level locking") self.__raise_if_unsupported("startTransaction", target, ClientSession) return target.start_transaction(*args, **kwargs) def _changeStreamOperation_iterateUntilDocumentOrError(self, target, *args, **kwargs): self.__raise_if_unsupported("iterateUntilDocumentOrError", target, ChangeStream) return next(target) def _cursor_iterateUntilDocumentOrError(self, target, *args, **kwargs): self.__raise_if_unsupported( "iterateUntilDocumentOrError", target, NonLazyCursor, CommandCursor ) while target.alive: try: return next(target) except StopIteration: pass return None def _cursor_close(self, target, *args, **kwargs): self.__raise_if_unsupported("close", target, NonLazyCursor, CommandCursor) return target.close() def _clientEncryptionOperation_createDataKey(self, target, *args, **kwargs): if "opts" in kwargs: kwargs.update(camel_to_snake_args(kwargs.pop("opts"))) return target.create_data_key(*args, **kwargs) def _clientEncryptionOperation_getKeys(self, target, *args, **kwargs): return list(target.get_keys(*args, **kwargs)) def _clientEncryptionOperation_deleteKey(self, target, *args, **kwargs): result = target.delete_key(*args, **kwargs) response = result.raw_result response["deletedCount"] = result.deleted_count return response def _clientEncryptionOperation_rewrapManyDataKey(self, target, *args, **kwargs): if "opts" in kwargs: kwargs.update(camel_to_snake_args(kwargs.pop("opts"))) data = target.rewrap_many_data_key(*args, **kwargs) if data.bulk_write_result: return {"bulkWriteResult": parse_bulk_write_result(data.bulk_write_result)} return {} def _clientEncryptionOperation_encrypt(self, target, *args, **kwargs): if "opts" in kwargs: kwargs.update(camel_to_snake_args(kwargs.pop("opts"))) return target.encrypt(*args, **kwargs) def _bucketOperation_download(self, target: GridFSBucket, *args: Any, **kwargs: Any) -> bytes: with target.open_download_stream(*args, **kwargs) as gout: return gout.read() def _bucketOperation_downloadByName( self, target: GridFSBucket, *args: Any, **kwargs: Any ) -> bytes: with target.open_download_stream_by_name(*args, **kwargs) as gout: return gout.read() def _bucketOperation_upload(self, target: GridFSBucket, *args: Any, **kwargs: Any) -> ObjectId: kwargs["source"] = binascii.unhexlify(kwargs.pop("source")["$$hexBytes"]) if "content_type" in kwargs: kwargs.setdefault("metadata", {})["contentType"] = kwargs.pop("content_type") return target.upload_from_stream(*args, **kwargs) def _bucketOperation_uploadWithId(self, target: GridFSBucket, *args: Any, **kwargs: Any) -> Any: kwargs["source"] = binascii.unhexlify(kwargs.pop("source")["$$hexBytes"]) if "content_type" in kwargs: kwargs.setdefault("metadata", {})["contentType"] = kwargs.pop("content_type") return target.upload_from_stream_with_id(*args, **kwargs) def _bucketOperation_find( self, target: GridFSBucket, *args: Any, **kwargs: Any ) -> List[GridOut]: return list(target.find(*args, **kwargs)) def run_entity_operation(self, spec): target = self.entity_map[spec["object"]] opname = spec["name"] opargs = spec.get("arguments") expect_error = spec.get("expectError") save_as_entity = spec.get("saveResultAsEntity") expect_result = spec.get("expectResult") ignore = spec.get("ignoreResultAndError") if ignore and (expect_error or save_as_entity or expect_result): raise ValueError( "ignoreResultAndError is incompatible with saveResultAsEntity" ", expectError, and expectResult" ) if opargs: arguments = parse_spec_options(copy.deepcopy(opargs)) prepare_spec_arguments( spec, arguments, camel_to_snake(opname), self.entity_map, self.run_operations_and_throw, ) else: arguments = {} if isinstance(target, MongoClient): method_name = f"_clientOperation_{opname}" elif isinstance(target, Database): method_name = f"_databaseOperation_{opname}" elif isinstance(target, Collection): method_name = f"_collectionOperation_{opname}" # contentType is always stored in metadata in pymongo. if target.name.endswith(".files") and opname == "find": for doc in spec.get("expectResult", []): if "contentType" in doc: doc.setdefault("metadata", {})["contentType"] = doc.pop("contentType") elif isinstance(target, ChangeStream): method_name = f"_changeStreamOperation_{opname}" elif isinstance(target, (NonLazyCursor, CommandCursor)): method_name = f"_cursor_{opname}" elif isinstance(target, ClientSession): method_name = f"_sessionOperation_{opname}" elif isinstance(target, GridFSBucket): method_name = f"_bucketOperation_{opname}" if "id" in arguments: arguments["file_id"] = arguments.pop("id") # MD5 is always disabled in pymongo. arguments.pop("disable_md5", None) elif isinstance(target, ClientEncryption): method_name = f"_clientEncryptionOperation_{opname}" else: method_name = "doesNotExist" try: method = getattr(self, method_name) except AttributeError: target_opname = camel_to_snake(opname) if target_opname == "iterate_once": target_opname = "try_next" try: cmd = getattr(target, target_opname) except AttributeError: self.fail(f"Unsupported operation {opname} on entity {target}") else: cmd = functools.partial(method, target) try: # CSOT: Translate the spec test "timeout" arg into pymongo's context timeout API. if "timeout" in arguments: timeout = arguments.pop("timeout") with pymongo.timeout(timeout): result = cmd(**dict(arguments)) else: result = cmd(**dict(arguments)) except Exception as exc: # Ignore all operation errors but to avoid masking bugs don't # ignore things like TypeError and ValueError. if ignore and isinstance(exc, (PyMongoError,)): return exc if expect_error: return self.process_error(exc, expect_error) raise else: if expect_error: self.fail(f'Excepted error {expect_error} but "{opname}" succeeded: {result}') if expect_result: actual = coerce_result(opname, result) self.match_evaluator.match_result(expect_result, actual) if save_as_entity: self.entity_map[save_as_entity] = result return None return None def __set_fail_point(self, client, command_args): if not client_context.test_commands_enabled: self.skipTest("Test commands must be enabled") cmd_on = SON([("configureFailPoint", "failCommand")]) cmd_on.update(command_args) client.admin.command(cmd_on) self.addCleanup( client.admin.command, "configureFailPoint", cmd_on["configureFailPoint"], mode="off" ) def _testOperation_failPoint(self, spec): self.__set_fail_point( client=self.entity_map[spec["client"]], command_args=spec["failPoint"] ) def _testOperation_targetedFailPoint(self, spec): session = self.entity_map[spec["session"]] if not session._pinned_address: self.fail( "Cannot use targetedFailPoint operation with unpinned " "session {}".format( spec["session"] ) ) client = single_client("{}:{}".format(*session._pinned_address)) self.addCleanup(client.close) self.__set_fail_point(client=client, command_args=spec["failPoint"]) def _testOperation_createEntities(self, spec): self.entity_map.create_entities_from_spec(spec["entities"], uri=self._uri) self.entity_map.advance_cluster_times() def _testOperation_assertSessionTransactionState(self, spec): session = self.entity_map[spec["session"]] expected_state = getattr(_TxnState, spec["state"].upper()) self.assertEqual(expected_state, session._transaction.state) def _testOperation_assertSessionPinned(self, spec): session = self.entity_map[spec["session"]] self.assertIsNotNone(session._transaction.pinned_address) def _testOperation_assertSessionUnpinned(self, spec): session = self.entity_map[spec["session"]] self.assertIsNone(session._pinned_address) self.assertIsNone(session._transaction.pinned_address) def __get_last_two_command_lsids(self, listener): cmd_started_events = [] for event in reversed(listener.events): if isinstance(event, CommandStartedEvent): cmd_started_events.append(event) if len(cmd_started_events) < 2: self.fail( "Needed 2 CommandStartedEvents to compare lsids, " "got %s" % (len(cmd_started_events)) ) return tuple([e.command["lsid"] for e in cmd_started_events][:2]) def _testOperation_assertDifferentLsidOnLastTwoCommands(self, spec): listener = self.entity_map.get_listener_for_client(spec["client"]) self.assertNotEqual(*self.__get_last_two_command_lsids(listener)) def _testOperation_assertSameLsidOnLastTwoCommands(self, spec): listener = self.entity_map.get_listener_for_client(spec["client"]) self.assertEqual(*self.__get_last_two_command_lsids(listener)) def _testOperation_assertSessionDirty(self, spec): session = self.entity_map[spec["session"]] self.assertTrue(session._server_session.dirty) def _testOperation_assertSessionNotDirty(self, spec): session = self.entity_map[spec["session"]] return self.assertFalse(session._server_session.dirty) def _testOperation_assertCollectionExists(self, spec): database_name = spec["databaseName"] collection_name = spec["collectionName"] collection_name_list = list(self.client.get_database(database_name).list_collection_names()) self.assertIn(collection_name, collection_name_list) def _testOperation_assertCollectionNotExists(self, spec): database_name = spec["databaseName"] collection_name = spec["collectionName"] collection_name_list = list(self.client.get_database(database_name).list_collection_names()) self.assertNotIn(collection_name, collection_name_list) def _testOperation_assertIndexExists(self, spec): collection = self.client[spec["databaseName"]][spec["collectionName"]] index_names = [idx["name"] for idx in collection.list_indexes()] self.assertIn(spec["indexName"], index_names) def _testOperation_assertIndexNotExists(self, spec): collection = self.client[spec["databaseName"]][spec["collectionName"]] for index in collection.list_indexes(): self.assertNotEqual(spec["indexName"], index["name"]) def _testOperation_assertNumberConnectionsCheckedOut(self, spec): client = self.entity_map[spec["client"]] pool = get_pool(client) self.assertEqual(spec["connections"], pool.active_sockets) def _event_count(self, client_name, event): listener = self.entity_map.get_listener_for_client(client_name) actual_events = listener.get_events("all") count = 0 for actual in actual_events: try: self.match_evaluator.match_event(event, actual) except AssertionError: continue else: count += 1 return count def _testOperation_assertEventCount(self, spec): """Run the assertEventCount test operation. Assert the given event was published exactly `count` times. """ client, event, count = spec["client"], spec["event"], spec["count"] self.assertEqual(self._event_count(client, event), count, f"expected {count} not {event!r}") def _testOperation_waitForEvent(self, spec): """Run the waitForEvent test operation. Wait for a number of events to be published, or fail. """ client, event, count = spec["client"], spec["event"], spec["count"] wait_until( lambda: self._event_count(client, event) >= count, f"find {count} {event} event(s)", ) def _testOperation_wait(self, spec): """Run the "wait" test operation.""" time.sleep(spec["ms"] / 1000.0) def _testOperation_recordTopologyDescription(self, spec): """Run the recordTopologyDescription test operation.""" self.entity_map[spec["id"]] = self.entity_map[spec["client"]].topology_description def _testOperation_assertTopologyType(self, spec): """Run the assertTopologyType test operation.""" description = self.entity_map[spec["topologyDescription"]] self.assertIsInstance(description, TopologyDescription) self.assertEqual(description.topology_type_name, spec["topologyType"]) def _testOperation_waitForPrimaryChange(self, spec: dict) -> None: """Run the waitForPrimaryChange test operation.""" client = self.entity_map[spec["client"]] old_description: TopologyDescription = self.entity_map[spec["priorTopologyDescription"]] timeout = spec["timeoutMS"] / 1000.0 def get_primary(td: TopologyDescription) -> Optional[_Address]: servers = writable_server_selector(Selection.from_topology_description(td)) if servers and servers[0].server_type == SERVER_TYPE.RSPrimary: return servers[0].address return None old_primary = get_primary(old_description) def primary_changed() -> bool: primary = client.primary if primary is None: return False return primary != old_primary wait_until(primary_changed, "change primary", timeout=timeout) def _testOperation_runOnThread(self, spec): """Run the 'runOnThread' operation.""" thread = self.entity_map[spec["thread"]] thread.schedule(lambda: self.run_entity_operation(spec["operation"])) def _testOperation_waitForThread(self, spec): """Run the 'waitForThread' operation.""" thread = self.entity_map[spec["thread"]] thread.stop() thread.join(10) if thread.exc: raise thread.exc self.assertFalse(thread.is_alive(), "Thread {} is still running".format(spec["thread"])) def _testOperation_loop(self, spec): failure_key = spec.get("storeFailuresAsEntity") error_key = spec.get("storeErrorsAsEntity") successes_key = spec.get("storeSuccessesAsEntity") iteration_key = spec.get("storeIterationsAsEntity") iteration_limiter_key = spec.get("numIterations") for i in [failure_key, error_key]: if i: self.entity_map[i] = [] for i in [successes_key, iteration_key]: if i: self.entity_map[i] = 0 i = 0 global IS_INTERRUPTED while True: if iteration_limiter_key and i >= iteration_limiter_key: break i += 1 if IS_INTERRUPTED: break try: if iteration_key: self.entity_map._entities[iteration_key] += 1 for op in spec["operations"]: self.run_entity_operation(op) if successes_key: self.entity_map._entities[successes_key] += 1 except Exception as exc: if isinstance(exc, AssertionError): key = failure_key or error_key else: key = error_key or failure_key if not key: raise self.entity_map[key].append( {"error": str(exc), "time": time.time(), "type": type(exc).__name__} ) def run_special_operation(self, spec): opname = spec["name"] method_name = f"_testOperation_{opname}" try: method = getattr(self, method_name) except AttributeError: self.fail(f"Unsupported special test operation {opname}") else: method(spec["arguments"]) def run_operations(self, spec): for op in spec: if op["object"] == "testRunner": self.run_special_operation(op) else: self.run_entity_operation(op) def run_operations_and_throw(self, spec): for op in spec: if op["object"] == "testRunner": self.run_special_operation(op) else: result = self.run_entity_operation(op) if isinstance(result, Exception): raise result def check_events(self, spec): for event_spec in spec: client_name = event_spec["client"] events = event_spec["events"] event_type = event_spec.get("eventType", "command") ignore_extra_events = event_spec.get("ignoreExtraEvents", False) server_connection_id = event_spec.get("serverConnectionId") has_server_connection_id = event_spec.get("hasServerConnectionId", False) listener = self.entity_map.get_listener_for_client(client_name) actual_events = listener.get_events(event_type) if ignore_extra_events: actual_events = actual_events[: len(events)] if len(events) == 0: self.assertEqual(actual_events, []) continue if len(actual_events) != len(events): expected = "\n".join(str(e) for e in events) actual = "\n".join(str(a) for a in actual_events) self.assertEqual( len(actual_events), len(events), f"expected events:\n{expected}\nactual events:\n{actual}", ) for idx, expected_event in enumerate(events): self.match_evaluator.match_event(expected_event, actual_events[idx]) if has_server_connection_id: assert server_connection_id is not None assert server_connection_id >= 0 else: assert server_connection_id is None def check_log_messages(self, operations, spec): def format_logs(log_list): client_to_log = defaultdict(list) for log in log_list: if log.module == "ocsp_support": continue data = json_util.loads(log.message) client = data.pop("clientId") client_to_log[client].append( { "level": log.levelname.lower(), "component": log.name.replace("pymongo.", "", 1), "data": data, } ) return client_to_log with self.assertLogs("pymongo", level="DEBUG") as cm: self.run_operations(operations) formatted_logs = format_logs(cm.records) for client in spec: components = set() for message in client["messages"]: components.add(message["component"]) clientid = self.entity_map[client["client"]]._topology_settings._topology_id actual_logs = formatted_logs[clientid] actual_logs = [log for log in actual_logs if log["component"] in components] if client.get("ignoreExtraMessages", False): actual_logs = actual_logs[: len(client["messages"])] self.assertEqual(len(client["messages"]), len(actual_logs)) for expected_msg, actual_msg in zip(client["messages"], actual_logs): expected_data, actual_data = expected_msg.pop("data"), actual_msg.pop("data") if "failureIsRedacted" in expected_msg: self.assertIn("failure", actual_data) should_redact = expected_msg.pop("failureIsRedacted") if should_redact: actual_fields = set(json_util.loads(actual_data["failure"]).keys()) self.assertTrue( {"code", "codeName", "errorLabels"}.issuperset(actual_fields) ) self.match_evaluator.match_result(expected_data, actual_data) self.match_evaluator.match_result(expected_msg, actual_msg) def verify_outcome(self, spec): for collection_data in spec: coll_name = collection_data["collectionName"] db_name = collection_data["databaseName"] expected_documents = collection_data["documents"] coll = self.client.get_database(db_name).get_collection( coll_name, read_preference=ReadPreference.PRIMARY, read_concern=ReadConcern(level="local"), ) if expected_documents: sorted_expected_documents = sorted(expected_documents, key=lambda doc: doc["_id"]) actual_documents = list(coll.find({}, sort=[("_id", ASCENDING)])) self.assertListEqual(sorted_expected_documents, actual_documents) def run_scenario(self, spec, uri=None): # Kill all sessions before and after each test to prevent an open # transaction (from a test failure) from blocking collection/database # operations during test set up and tear down. self.kill_all_sessions() self.addCleanup(self.kill_all_sessions) if "csot" in self.id().lower(): # Retry CSOT tests up to 2 times to deal with flakey tests. attempts = 3 for i in range(attempts): try: return self._run_scenario(spec, uri) except AssertionError: if i < attempts - 1: print( f"Retrying after attempt {i+1} of {self.id()} failed with:\n" f"{traceback.format_exc()}", file=sys.stderr, ) self.setUp() continue raise return None else: self._run_scenario(spec, uri) return None def _run_scenario(self, spec, uri=None): # maybe skip test manually self.maybe_skip_test(spec) # process test-level runOnRequirements run_on_spec = spec.get("runOnRequirements", []) if not self.should_run_on(run_on_spec): raise unittest.SkipTest("runOnRequirements not satisfied") # process skipReason skip_reason = spec.get("skipReason", None) if skip_reason is not None: raise unittest.SkipTest(f"{skip_reason}") # process createEntities self._uri = uri self.entity_map = EntityMapUtil(self) self.entity_map.create_entities_from_spec(self.TEST_SPEC.get("createEntities", []), uri=uri) # process initialData if "initialData" in self.TEST_SPEC: self.insert_initial_data(self.TEST_SPEC["initialData"]) self._cluster_time = self.client.admin.command("ping").get("$clusterTime") self.entity_map.advance_cluster_times() if "expectLogMessages" in spec: expect_log_messages = spec["expectLogMessages"] self.assertTrue(expect_log_messages, "expectEvents must be non-empty") self.check_log_messages(spec["operations"], expect_log_messages) else: # process operations self.run_operations(spec["operations"]) # process expectEvents if "expectEvents" in spec: expect_events = spec["expectEvents"] self.assertTrue(expect_events, "expectEvents must be non-empty") self.check_events(expect_events) # process outcome self.verify_outcome(spec.get("outcome", [])) class UnifiedSpecTestMeta(type): """Metaclass for generating test classes.""" TEST_SPEC: Any EXPECTED_FAILURES: Any def __init__(cls, *args, **kwargs): super().__init__(*args, **kwargs) def create_test(spec): def test_case(self): self.run_scenario(spec) return test_case for test_spec in cls.TEST_SPEC["tests"]: description = test_spec["description"] test_name = "test_{}".format( description.strip(". ").replace(" ", "_").replace(".", "_") ) test_method = create_test(copy.deepcopy(test_spec)) test_method.__name__ = str(test_name) for fail_pattern in cls.EXPECTED_FAILURES: if re.search(fail_pattern, description): test_method = unittest.expectedFailure(test_method) break setattr(cls, test_name, test_method) _ALL_MIXIN_CLASSES = [ UnifiedSpecTestMixinV1, # add mixin classes for new schema major versions here ] _SCHEMA_VERSION_MAJOR_TO_MIXIN_CLASS = { KLASS.SCHEMA_VERSION[0]: KLASS for KLASS in _ALL_MIXIN_CLASSES } def generate_test_classes( test_path, module=__name__, class_name_prefix="", expected_failures=[], # noqa: B006 bypass_test_generation_errors=False, **kwargs, ): """Method for generating test classes. Returns a dictionary where keys are the names of test classes and values are the test class objects. """ test_klasses = {} def test_base_class_factory(test_spec): """Utility that creates the base class to use for test generation. This is needed to ensure that cls.TEST_SPEC is appropriately set when the metaclass __init__ is invoked. """ class SpecTestBase(with_metaclass(UnifiedSpecTestMeta)): # type: ignore TEST_SPEC = test_spec EXPECTED_FAILURES = expected_failures return SpecTestBase for dirpath, _, filenames in os.walk(test_path): dirname = os.path.split(dirpath)[-1] for filename in filenames: fpath = os.path.join(dirpath, filename) with open(fpath) as scenario_stream: # Use tz_aware=False to match how CodecOptions decodes # dates. opts = json_util.JSONOptions(tz_aware=False) scenario_def = json_util.loads(scenario_stream.read(), json_options=opts) test_type = os.path.splitext(filename)[0] snake_class_name = "Test{}_{}_{}".format( class_name_prefix, dirname.replace("-", "_"), test_type.replace("-", "_").replace(".", "_"), ) class_name = snake_to_camel(snake_class_name) try: schema_version = Version.from_string(scenario_def["schemaVersion"]) mixin_class = _SCHEMA_VERSION_MAJOR_TO_MIXIN_CLASS.get(schema_version[0]) if mixin_class is None: raise ValueError( f"test file '{fpath}' has unsupported schemaVersion '{schema_version}'" ) module_dict = {"__module__": module} module_dict.update(kwargs) test_klasses[class_name] = type( class_name, ( mixin_class, test_base_class_factory(scenario_def), ), module_dict, ) except Exception: if bypass_test_generation_errors: continue raise return test_klasses mongodb-mongo-python-driver-509e9b7/test/uri_options/000077500000000000000000000000001462766011000227665ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/uri_options/auth-options.json000066400000000000000000000016661462766011000263240ustar00rootroot00000000000000{ "tests": [ { "description": "Valid auth options are parsed correctly (GSSAPI)", "uri": "mongodb://foo:bar@example.com/?authMechanism=GSSAPI&authMechanismProperties=SERVICE_NAME:other,CANONICALIZE_HOST_NAME:true&authSource=$external", "valid": true, "warning": false, "hosts": null, "auth": null, "options": { "authMechanism": "GSSAPI", "authMechanismProperties": { "SERVICE_NAME": "other", "CANONICALIZE_HOST_NAME": true }, "authSource": "$external" } }, { "description": "Valid auth options are parsed correctly (SCRAM-SHA-1)", "uri": "mongodb://foo:bar@example.com/?authMechanism=SCRAM-SHA-1&authSource=authSourceDB", "valid": true, "warning": false, "hosts": null, "auth": null, "options": { "authMechanism": "SCRAM-SHA-1", "authSource": "authSourceDB" } } ] } mongodb-mongo-python-driver-509e9b7/test/uri_options/ca.pem000066400000000000000000000002251462766011000240530ustar00rootroot00000000000000# This file exists solely for the purpose of facilitating drivers which check for the existence of files specified in the URI options at parse time. mongodb-mongo-python-driver-509e9b7/test/uri_options/cert.pem000066400000000000000000000002251462766011000244250ustar00rootroot00000000000000# This file exists solely for the purpose of facilitating drivers which check for the existence of files specified in the URI options at parse time. mongodb-mongo-python-driver-509e9b7/test/uri_options/client.pem000066400000000000000000000002251462766011000247460ustar00rootroot00000000000000# This file exists solely for the purpose of facilitating drivers which check for the existence of files specified in the URI options at parse time. mongodb-mongo-python-driver-509e9b7/test/uri_options/compression-options.json000066400000000000000000000027641462766011000277240ustar00rootroot00000000000000{ "tests": [ { "description": "Valid compression options are parsed correctly", "uri": "mongodb://example.com/?compressors=zlib&zlibCompressionLevel=9", "valid": true, "warning": false, "hosts": null, "auth": null, "options": { "compressors": [ "zlib" ], "zlibCompressionLevel": 9 } }, { "description": "Multiple compressors are parsed correctly", "uri": "mongodb://example.com/?compressors=snappy,zlib", "valid": true, "warning": false, "hosts": null, "auth": null, "options": { "compressors": [ "snappy", "zlib" ] } }, { "description": "Non-numeric zlibCompressionLevel causes a warning", "uri": "mongodb://example.com/?compressors=zlib&zlibCompressionLevel=invalid", "valid": true, "warning": true, "hosts": null, "auth": null, "options": {} }, { "description": "Too low zlibCompressionLevel causes a warning", "uri": "mongodb://example.com/?compressors=zlib&zlibCompressionLevel=-2", "valid": true, "warning": true, "hosts": null, "auth": null, "options": {} }, { "description": "Too high zlibCompressionLevel causes a warning", "uri": "mongodb://example.com/?compressors=zlib&zlibCompressionLevel=10", "valid": true, "warning": true, "hosts": null, "auth": null, "options": {} } ] } mongodb-mongo-python-driver-509e9b7/test/uri_options/concern-options.json000066400000000000000000000033471462766011000270100ustar00rootroot00000000000000{ "tests": [ { "description": "Valid read and write concern are parsed correctly", "uri": "mongodb://example.com/?readConcernLevel=majority&w=5&wTimeoutMS=30000&journal=false", "valid": true, "warning": false, "hosts": null, "auth": null, "options": { "readConcernLevel": "majority", "w": 5, "wTimeoutMS": 30000, "journal": false } }, { "description": "Arbitrary string readConcernLevel does not cause a warning", "uri": "mongodb://example.com/?readConcernLevel=arbitraryButStillValid", "valid": true, "warning": false, "hosts": null, "auth": null, "options": { "readConcernLevel": "arbitraryButStillValid" } }, { "description": "Arbitrary string w doesn't cause a warning", "uri": "mongodb://example.com/?w=arbitraryButStillValid", "valid": true, "warning": false, "hosts": null, "auth": null, "options": { "w": "arbitraryButStillValid" } }, { "description": "Non-numeric wTimeoutMS causes a warning", "uri": "mongodb://example.com/?wTimeoutMS=invalid", "valid": true, "warning": true, "hosts": null, "auth": null, "options": {} }, { "description": "Too low wTimeoutMS causes a warning", "uri": "mongodb://example.com/?wTimeoutMS=-2", "valid": true, "warning": true, "hosts": null, "auth": null, "options": {} }, { "description": "Invalid journal causes a warning", "uri": "mongodb://example.com/?journal=invalid", "valid": true, "warning": true, "hosts": null, "auth": null, "options": {} } ] } mongodb-mongo-python-driver-509e9b7/test/uri_options/connection-options.json000066400000000000000000000165631462766011000275240ustar00rootroot00000000000000{ "tests": [ { "description": "Valid connection and timeout options are parsed correctly", "uri": "mongodb://example.com/?appname=URI-OPTIONS-SPEC-TEST&connectTimeoutMS=20000&heartbeatFrequencyMS=5000&localThresholdMS=3000&maxIdleTimeMS=50000&replicaSet=uri-options-spec&retryWrites=true&serverSelectionTimeoutMS=15000&socketTimeoutMS=7500&timeoutMS=100", "valid": true, "warning": false, "hosts": null, "auth": null, "options": { "appname": "URI-OPTIONS-SPEC-TEST", "connectTimeoutMS": 20000, "heartbeatFrequencyMS": 5000, "localThresholdMS": 3000, "maxIdleTimeMS": 50000, "replicaSet": "uri-options-spec", "retryWrites": true, "serverSelectionTimeoutMS": 15000, "socketTimeoutMS": 7500, "timeoutMS": 100 } }, { "description": "Non-numeric connectTimeoutMS causes a warning", "uri": "mongodb://example.com/?connectTimeoutMS=invalid", "valid": true, "warning": true, "hosts": null, "auth": null, "options": {} }, { "description": "Too low connectTimeoutMS causes a warning", "uri": "mongodb://example.com/?connectTimeoutMS=-2", "valid": true, "warning": true, "hosts": null, "auth": null, "options": {} }, { "description": "Non-numeric heartbeatFrequencyMS causes a warning", "uri": "mongodb://example.com/?heartbeatFrequencyMS=invalid", "valid": true, "warning": true, "hosts": null, "auth": null, "options": {} }, { "description": "Too low heartbeatFrequencyMS causes a warning", "uri": "mongodb://example.com/?heartbeatFrequencyMS=-2", "valid": true, "warning": true, "hosts": null, "auth": null, "options": {} }, { "description": "Non-numeric localThresholdMS causes a warning", "uri": "mongodb://example.com/?localThresholdMS=invalid", "valid": true, "warning": true, "hosts": null, "auth": null, "options": {} }, { "description": "Too low localThresholdMS causes a warning", "uri": "mongodb://example.com/?localThresholdMS=-2", "valid": true, "warning": true, "hosts": null, "auth": null, "options": {} }, { "description": "Invalid retryWrites causes a warning", "uri": "mongodb://example.com/?retryWrites=invalid", "valid": true, "warning": true, "hosts": null, "auth": null, "options": {} }, { "description": "Non-numeric serverSelectionTimeoutMS causes a warning", "uri": "mongodb://example.com/?serverSelectionTimeoutMS=invalid", "valid": true, "warning": true, "hosts": null, "auth": null, "options": {} }, { "description": "Too low serverSelectionTimeoutMS causes a warning", "uri": "mongodb://example.com/?serverSelectionTimeoutMS=-2", "valid": true, "warning": true, "hosts": null, "auth": null, "options": {} }, { "description": "Non-numeric socketTimeoutMS causes a warning", "uri": "mongodb://example.com/?socketTimeoutMS=invalid", "valid": true, "warning": true, "hosts": null, "auth": null, "options": {} }, { "description": "Too low socketTimeoutMS causes a warning", "uri": "mongodb://example.com/?socketTimeoutMS=-2", "valid": true, "warning": true, "hosts": null, "auth": null, "options": {} }, { "description": "directConnection=true", "uri": "mongodb://example.com/?directConnection=true", "valid": true, "warning": false, "hosts": null, "auth": null, "options": { "directConnection": true } }, { "description": "directConnection=true with multiple seeds", "uri": "mongodb://example1.com,example2.com/?directConnection=true", "valid": false, "warning": false, "hosts": null, "auth": null, "options": {} }, { "description": "directConnection=false", "uri": "mongodb://example.com/?directConnection=false", "valid": true, "warning": false, "hosts": null, "auth": null, "options": { "directConnection": false } }, { "description": "directConnection=false with multiple seeds", "uri": "mongodb://example1.com,example2.com/?directConnection=false", "valid": true, "warning": false, "hosts": null, "auth": null, "options": { "directConnection": false } }, { "description": "Invalid directConnection value", "uri": "mongodb://example.com/?directConnection=invalid", "valid": true, "warning": true, "hosts": null, "auth": null, "options": {} }, { "description": "loadBalanced=true", "uri": "mongodb://example.com/?loadBalanced=true", "valid": true, "warning": false, "hosts": null, "auth": null, "options": { "loadBalanced": true } }, { "description": "loadBalanced=true with directConnection=false", "uri": "mongodb://example.com/?loadBalanced=true&directConnection=false", "valid": true, "warning": false, "hosts": null, "auth": null, "options": { "loadBalanced": true, "directConnection": false } }, { "description": "loadBalanced=false", "uri": "mongodb://example.com/?loadBalanced=false", "valid": true, "warning": false, "hosts": null, "auth": null, "options": { "loadBalanced": false } }, { "description": "Invalid loadBalanced value", "uri": "mongodb://example.com/?loadBalanced=1", "valid": true, "warning": true, "hosts": null, "auth": null, "options": {} }, { "description": "loadBalanced=true with multiple hosts causes an error", "uri": "mongodb://example1,example2/?loadBalanced=true", "valid": false, "warning": false, "hosts": null, "auth": null, "options": {} }, { "description": "loadBalanced=true with directConnection=true causes an error", "uri": "mongodb://example.com/?loadBalanced=true&directConnection=true", "valid": false, "warning": false, "hosts": null, "auth": null, "options": {} }, { "description": "loadBalanced=true with replicaSet causes an error", "uri": "mongodb://example.com/?loadBalanced=true&replicaSet=replset", "valid": false, "warning": false, "hosts": null, "auth": null, "options": {} }, { "description": "timeoutMS=0", "uri": "mongodb://example.com/?timeoutMS=0", "valid": true, "warning": false, "hosts": null, "auth": null, "options": { "timeoutMS": 0 } }, { "description": "Non-numeric timeoutMS causes a warning", "uri": "mongodb://example.com/?timeoutMS=invalid", "valid": true, "warning": true, "hosts": null, "auth": null, "options": {} }, { "description": "Too low timeoutMS causes a warning", "uri": "mongodb://example.com/?timeoutMS=-2", "valid": true, "warning": true, "hosts": null, "auth": null, "options": {} } ] } mongodb-mongo-python-driver-509e9b7/test/uri_options/connection-pool-options.json000066400000000000000000000035451462766011000304670ustar00rootroot00000000000000{ "tests": [ { "description": "Valid connection pool options are parsed correctly", "uri": "mongodb://example.com/?maxIdleTimeMS=50000&maxPoolSize=5&minPoolSize=3&maxConnecting=1", "valid": true, "warning": false, "hosts": null, "auth": null, "options": { "maxIdleTimeMS": 50000, "maxPoolSize": 5, "minPoolSize": 3, "maxConnecting": 1 } }, { "description": "Non-numeric maxIdleTimeMS causes a warning", "uri": "mongodb://example.com/?maxIdleTimeMS=invalid", "valid": true, "warning": true, "hosts": null, "auth": null, "options": {} }, { "description": "Too low maxIdleTimeMS causes a warning", "uri": "mongodb://example.com/?maxIdleTimeMS=-2", "valid": true, "warning": true, "hosts": null, "auth": null, "options": {} }, { "description": "maxPoolSize=0 does not error", "uri": "mongodb://example.com/?maxPoolSize=0", "valid": true, "warning": false, "hosts": null, "auth": null, "options": { "maxPoolSize": 0 } }, { "description": "minPoolSize=0 does not error", "uri": "mongodb://example.com/?minPoolSize=0", "valid": true, "warning": false, "hosts": null, "auth": null, "options": { "minPoolSize": 0 } }, { "description": "maxConnecting=0 causes a warning", "uri": "mongodb://example.com/?maxConnecting=0", "valid": true, "warning": true, "hosts": null, "auth": null, "options": {} }, { "description": "maxConnecting<0 causes a warning", "uri": "mongodb://example.com/?maxConnecting=-1", "valid": true, "warning": true, "hosts": null, "auth": null, "options": {} } ] } mongodb-mongo-python-driver-509e9b7/test/uri_options/read-preference-options.json000066400000000000000000000033411462766011000304020ustar00rootroot00000000000000{ "tests": [ { "description": "Valid read preference options are parsed correctly", "uri": "mongodb://example.com/?readPreference=primaryPreferred&readPreferenceTags=dc:ny,rack:1&maxStalenessSeconds=120&readPreferenceTags=dc:ny", "valid": true, "warning": false, "hosts": null, "auth": null, "options": { "readPreference": "primaryPreferred", "readPreferenceTags": [ { "dc": "ny", "rack": "1" }, { "dc": "ny" } ], "maxStalenessSeconds": 120 } }, { "description": "Single readPreferenceTags is parsed as array of size one", "uri": "mongodb://example.com/?readPreference=secondary&readPreferenceTags=dc:ny", "valid": true, "warning": false, "hosts": null, "auth": null, "options": { "readPreferenceTags": [ { "dc": "ny" } ] } }, { "description": "Invalid readPreferenceTags causes a warning", "uri": "mongodb://example.com/?readPreferenceTags=invalid", "valid": true, "warning": true, "hosts": null, "auth": null, "options": {} }, { "description": "Non-numeric maxStalenessSeconds causes a warning", "uri": "mongodb://example.com/?maxStalenessSeconds=invalid", "valid": true, "warning": true, "hosts": null, "auth": null, "options": {} }, { "description": "Too low maxStalenessSeconds causes a warning", "uri": "mongodb://example.com/?maxStalenessSeconds=-2", "valid": true, "warning": true, "hosts": null, "auth": null, "options": {} } ] } mongodb-mongo-python-driver-509e9b7/test/uri_options/sdam-options.json000066400000000000000000000021211462766011000262720ustar00rootroot00000000000000{ "tests": [ { "description": "serverMonitoringMode=auto", "uri": "mongodb://example.com/?serverMonitoringMode=auto", "valid": true, "warning": false, "hosts": null, "auth": null, "options": { "serverMonitoringMode": "auto" } }, { "description": "serverMonitoringMode=stream", "uri": "mongodb://example.com/?serverMonitoringMode=stream", "valid": true, "warning": false, "hosts": null, "auth": null, "options": { "serverMonitoringMode": "stream" } }, { "description": "serverMonitoringMode=poll", "uri": "mongodb://example.com/?serverMonitoringMode=poll", "valid": true, "warning": false, "hosts": null, "auth": null, "options": { "serverMonitoringMode": "poll" } }, { "description": "invalid serverMonitoringMode", "uri": "mongodb://example.com/?serverMonitoringMode=invalid", "valid": true, "warning": true, "hosts": null, "auth": null, "options": {} } ] } mongodb-mongo-python-driver-509e9b7/test/uri_options/single-threaded-options.json000066400000000000000000000011411462766011000304060ustar00rootroot00000000000000{ "tests": [ { "description": "Valid options specific to single-threaded drivers are parsed correctly", "uri": "mongodb://example.com/?serverSelectionTryOnce=false", "valid": true, "warning": false, "hosts": null, "auth": null, "options": { "serverSelectionTryOnce": false } }, { "description": "Invalid serverSelectionTryOnce causes a warning", "uri": "mongodb://example.com/?serverSelectionTryOnce=invalid", "valid": true, "warning": true, "hosts": null, "auth": null, "options": {} } ] } mongodb-mongo-python-driver-509e9b7/test/uri_options/srv-options.json000066400000000000000000000061621462766011000261710ustar00rootroot00000000000000{ "tests": [ { "description": "SRV URI with custom srvServiceName", "uri": "mongodb+srv://test22.test.build.10gen.cc/?srvServiceName=customname", "valid": true, "warning": false, "hosts": null, "auth": null, "options": { "srvServiceName": "customname" } }, { "description": "Non-SRV URI with custom srvServiceName", "uri": "mongodb://example.com/?srvServiceName=customname", "valid": false, "warning": false, "hosts": null, "auth": null, "options": {} }, { "description": "SRV URI with srvMaxHosts", "uri": "mongodb+srv://test1.test.build.10gen.cc/?srvMaxHosts=2", "valid": true, "warning": false, "hosts": null, "auth": null, "options": { "srvMaxHosts": 2 } }, { "description": "SRV URI with negative integer for srvMaxHosts", "uri": "mongodb+srv://test1.test.build.10gen.cc/?srvMaxHosts=-1", "valid": true, "warning": true, "hosts": null, "auth": null, "options": {} }, { "description": "SRV URI with invalid type for srvMaxHosts", "uri": "mongodb+srv://test1.test.build.10gen.cc/?srvMaxHosts=foo", "valid": true, "warning": true, "hosts": null, "auth": null, "options": {} }, { "description": "Non-SRV URI with srvMaxHosts", "uri": "mongodb://example.com/?srvMaxHosts=2", "valid": false, "warning": false, "hosts": null, "auth": null, "options": {} }, { "description": "SRV URI with positive srvMaxHosts and replicaSet", "uri": "mongodb+srv://test1.test.build.10gen.cc/?srvMaxHosts=2&replicaSet=foo", "valid": false, "warning": false, "hosts": null, "auth": null, "options": {} }, { "description": "SRV URI with positive srvMaxHosts and loadBalanced=true", "uri": "mongodb+srv://test1.test.build.10gen.cc/?srvMaxHosts=2&loadBalanced=true", "valid": false, "warning": false, "hosts": null, "auth": null, "options": {} }, { "description": "SRV URI with positive srvMaxHosts and loadBalanced=false", "uri": "mongodb+srv://test1.test.build.10gen.cc/?srvMaxHosts=2&loadBalanced=false", "valid": true, "warning": false, "hosts": null, "auth": null, "options": { "loadBalanced": false, "srvMaxHosts": 2 } }, { "description": "SRV URI with srvMaxHosts=0 and replicaSet", "uri": "mongodb+srv://test1.test.build.10gen.cc/?srvMaxHosts=0&replicaSet=foo", "valid": true, "warning": false, "hosts": null, "auth": null, "options": { "replicaSet": "foo", "srvMaxHosts": 0 } }, { "description": "SRV URI with srvMaxHosts=0 and loadBalanced=true", "uri": "mongodb+srv://test3.test.build.10gen.cc/?srvMaxHosts=0&loadBalanced=true", "valid": true, "warning": false, "hosts": null, "auth": null, "options": { "loadBalanced": true, "srvMaxHosts": 0 } } ] } mongodb-mongo-python-driver-509e9b7/test/uri_options/tls-options.json000066400000000000000000000526471462766011000261720ustar00rootroot00000000000000{ "tests": [ { "description": "Valid required tls options are parsed correctly", "uri": "mongodb://example.com/?tls=true&tlsCAFile=ca.pem&tlsCertificateKeyFile=cert.pem", "valid": true, "warning": false, "hosts": null, "auth": null, "options": { "tls": true, "tlsCAFile": "ca.pem", "tlsCertificateKeyFile": "cert.pem" } }, { "description": "Valid tlsCertificateKeyFilePassword is parsed correctly", "uri": "mongodb://example.com/?tlsCertificateKeyFilePassword=hunter2", "valid": true, "warning": false, "hosts": null, "auth": null, "options": { "tlsCertificateKeyFilePassword": "hunter2" } }, { "description": "Invalid tlsAllowInvalidCertificates causes a warning", "uri": "mongodb://example.com/?tlsAllowInvalidCertificates=invalid", "valid": true, "warning": true, "hosts": null, "auth": null, "options": {} }, { "description": "tlsAllowInvalidCertificates is parsed correctly", "uri": "mongodb://example.com/?tlsAllowInvalidCertificates=true", "valid": true, "warning": false, "hosts": null, "auth": null, "options": { "tlsAllowInvalidCertificates": true } }, { "description": "tlsAllowInvalidHostnames is parsed correctly", "uri": "mongodb://example.com/?tlsAllowInvalidHostnames=true", "valid": true, "warning": false, "hosts": null, "auth": null, "options": { "tlsAllowInvalidHostnames": true } }, { "description": "Invalid tlsAllowInvalidHostnames causes a warning", "uri": "mongodb://example.com/?tlsAllowInvalidHostnames=invalid", "valid": true, "warning": true, "hosts": null, "auth": null, "options": {} }, { "description": "tlsInsecure is parsed correctly", "uri": "mongodb://example.com/?tlsInsecure=true", "valid": true, "warning": false, "hosts": null, "auth": null, "options": { "tlsInsecure": true } }, { "description": "Invalid tlsInsecure causes a warning", "uri": "mongodb://example.com/?tlsInsecure=invalid", "valid": true, "warning": true, "hosts": null, "auth": null, "options": {} }, { "description": "tlsInsecure and tlsAllowInvalidCertificates both present (and true) raises an error", "uri": "mongodb://example.com/?tlsInsecure=true&tlsAllowInvalidCertificates=true", "valid": false, "warning": false, "hosts": null, "auth": null, "options": {} }, { "description": "tlsInsecure and tlsAllowInvalidCertificates both present (and false) raises an error", "uri": "mongodb://example.com/?tlsInsecure=false&tlsAllowInvalidCertificates=false", "valid": false, "warning": false, "hosts": null, "auth": null, "options": {} }, { "description": "tlsAllowInvalidCertificates and tlsInsecure both present (and true) raises an error", "uri": "mongodb://example.com/?tlsAllowInvalidCertificates=true&tlsInsecure=true", "valid": false, "warning": false, "hosts": null, "auth": null, "options": {} }, { "description": "tlsAllowInvalidCertificates and tlsInsecure both present (and false) raises an error", "uri": "mongodb://example.com/?tlsAllowInvalidCertificates=false&tlsInsecure=false", "valid": false, "warning": false, "hosts": null, "auth": null, "options": {} }, { "description": "tlsInsecure and tlsAllowInvalidHostnames both present (and true) raises an error", "uri": "mongodb://example.com/?tlsInsecure=true&tlsAllowInvalidHostnames=true", "valid": false, "warning": false, "hosts": null, "auth": null, "options": {} }, { "description": "tlsInsecure and tlsAllowInvalidHostnames both present (and false) raises an error", "uri": "mongodb://example.com/?tlsInsecure=false&tlsAllowInvalidHostnames=false", "valid": false, "warning": false, "hosts": null, "auth": null, "options": {} }, { "description": "tlsAllowInvalidHostnames and tlsInsecure both present (and true) raises an error", "uri": "mongodb://example.com/?tlsAllowInvalidHostnames=true&tlsInsecure=true", "valid": false, "warning": false, "hosts": null, "auth": null, "options": {} }, { "description": "tlsAllowInvalidHostnames and tlsInsecure both present (and false) raises an error", "uri": "mongodb://example.com/?tlsAllowInvalidHostnames=false&tlsInsecure=false", "valid": false, "warning": false, "hosts": null, "auth": null, "options": {} }, { "description": "tls=true and ssl=true doesn't warn", "uri": "mongodb://example.com/?tls=true&ssl=true", "valid": true, "warning": false, "hosts": null, "auth": null, "options": {} }, { "description": "tls=false and ssl=false doesn't warn", "uri": "mongodb://example.com/?tls=false&ssl=false", "valid": true, "warning": false, "hosts": null, "auth": null, "options": {} }, { "description": "ssl=true and tls=true doesn't warn", "uri": "mongodb://example.com/?ssl=true&tls=true", "valid": true, "warning": false, "hosts": null, "auth": null, "options": {} }, { "description": "ssl=false and tls=false doesn't warn", "uri": "mongodb://example.com/?ssl=false&tls=false", "valid": true, "warning": false, "hosts": null, "auth": null, "options": {} }, { "description": "tls=false and ssl=true raises error", "uri": "mongodb://example.com/?tls=false&ssl=true", "valid": false, "warning": false, "hosts": null, "auth": null, "options": {} }, { "description": "tls=true and ssl=false raises error", "uri": "mongodb://example.com/?tls=true&ssl=false", "valid": false, "warning": false, "hosts": null, "auth": null, "options": {} }, { "description": "ssl=false and tls=true raises error", "uri": "mongodb://example.com/?ssl=false&tls=true", "valid": false, "warning": false, "hosts": null, "auth": null, "options": {} }, { "description": "ssl=true and tls=false raises error", "uri": "mongodb://example.com/?ssl=true&tls=false", "valid": false, "warning": false, "hosts": null, "auth": null, "options": {} }, { "description": "tlsDisableCertificateRevocationCheck can be set to true", "uri": "mongodb://example.com/?tls=true&tlsDisableCertificateRevocationCheck=true", "valid": true, "warning": false, "hosts": null, "auth": null, "options": { "tls": true, "tlsDisableCertificateRevocationCheck": true } }, { "description": "tlsDisableCertificateRevocationCheck can be set to false", "uri": "mongodb://example.com/?tls=true&tlsDisableCertificateRevocationCheck=false", "valid": true, "warning": false, "hosts": null, "auth": null, "options": { "tls": true, "tlsDisableCertificateRevocationCheck": false } }, { "description": "tlsAllowInvalidCertificates and tlsDisableCertificateRevocationCheck both present (and true) raises an error", "uri": "mongodb://example.com/?tlsAllowInvalidCertificates=true&tlsDisableCertificateRevocationCheck=true", "valid": false, "warning": false, "hosts": null, "auth": null, "options": {} }, { "description": "tlsAllowInvalidCertificates=true and tlsDisableCertificateRevocationCheck=false raises an error", "uri": "mongodb://example.com/?tlsAllowInvalidCertificates=true&tlsDisableCertificateRevocationCheck=false", "valid": false, "warning": false, "hosts": null, "auth": null, "options": {} }, { "description": "tlsAllowInvalidCertificates=false and tlsDisableCertificateRevocationCheck=true raises an error", "uri": "mongodb://example.com/?tlsAllowInvalidCertificates=false&tlsDisableCertificateRevocationCheck=true", "valid": false, "warning": false, "hosts": null, "auth": null, "options": {} }, { "description": "tlsAllowInvalidCertificates and tlsDisableCertificateRevocationCheck both present (and false) raises an error", "uri": "mongodb://example.com/?tlsAllowInvalidCertificates=false&tlsDisableCertificateRevocationCheck=false", "valid": false, "warning": false, "hosts": null, "auth": null, "options": {} }, { "description": "tlsDisableCertificateRevocationCheck and tlsAllowInvalidCertificates both present (and true) raises an error", "uri": "mongodb://example.com/?tlsDisableCertificateRevocationCheck=true&tlsAllowInvalidCertificates=true", "valid": false, "warning": false, "hosts": null, "auth": null, "options": {} }, { "description": "tlsDisableCertificateRevocationCheck=true and tlsAllowInvalidCertificates=false raises an error", "uri": "mongodb://example.com/?tlsDisableCertificateRevocationCheck=true&tlsAllowInvalidCertificates=false", "valid": false, "warning": false, "hosts": null, "auth": null, "options": {} }, { "description": "tlsDisableCertificateRevocationCheck=false and tlsAllowInvalidCertificates=true raises an error", "uri": "mongodb://example.com/?tlsDisableCertificateRevocationCheck=false&tlsAllowInvalidCertificates=true", "valid": false, "warning": false, "hosts": null, "auth": null, "options": {} }, { "description": "tlsDisableCertificateRevocationCheck and tlsAllowInvalidCertificates both present (and false) raises an error", "uri": "mongodb://example.com/?tlsDisableCertificateRevocationCheck=false&tlsAllowInvalidCertificates=false", "valid": false, "warning": false, "hosts": null, "auth": null, "options": {} }, { "description": "tlsInsecure and tlsDisableCertificateRevocationCheck both present (and true) raises an error", "uri": "mongodb://example.com/?tlsInsecure=true&tlsDisableCertificateRevocationCheck=true", "valid": false, "warning": false, "hosts": null, "auth": null, "options": {} }, { "description": "tlsInsecure=true and tlsDisableCertificateRevocationCheck=false raises an error", "uri": "mongodb://example.com/?tlsInsecure=true&tlsDisableCertificateRevocationCheck=false", "valid": false, "warning": false, "hosts": null, "auth": null, "options": {} }, { "description": "tlsInsecure=false and tlsDisableCertificateRevocationCheck=true raises an error", "uri": "mongodb://example.com/?tlsInsecure=false&tlsDisableCertificateRevocationCheck=true", "valid": false, "warning": false, "hosts": null, "auth": null, "options": {} }, { "description": "tlsInsecure and tlsDisableCertificateRevocationCheck both present (and false) raises an error", "uri": "mongodb://example.com/?tlsInsecure=false&tlsDisableCertificateRevocationCheck=false", "valid": false, "warning": false, "hosts": null, "auth": null, "options": {} }, { "description": "tlsDisableCertificateRevocationCheck and tlsInsecure both present (and true) raises an error", "uri": "mongodb://example.com/?tlsDisableCertificateRevocationCheck=true&tlsInsecure=true", "valid": false, "warning": false, "hosts": null, "auth": null, "options": {} }, { "description": "tlsDisableCertificateRevocationCheck=true and tlsInsecure=false raises an error", "uri": "mongodb://example.com/?tlsDisableCertificateRevocationCheck=true&tlsInsecure=false", "valid": false, "warning": false, "hosts": null, "auth": null, "options": {} }, { "description": "tlsDisableCertificateRevocationCheck=false and tlsInsecure=true raises an error", "uri": "mongodb://example.com/?tlsDisableCertificateRevocationCheck=false&tlsInsecure=true", "valid": false, "warning": false, "hosts": null, "auth": null, "options": {} }, { "description": "tlsDisableCertificateRevocationCheck and tlsInsecure both present (and false) raises an error", "uri": "mongodb://example.com/?tlsDisableCertificateRevocationCheck=false&tlsInsecure=false", "valid": false, "warning": false, "hosts": null, "auth": null, "options": {} }, { "description": "tlsDisableCertificateRevocationCheck and tlsDisableOCSPEndpointCheck both present (and true) raises an error", "uri": "mongodb://example.com/?tlsDisableCertificateRevocationCheck=true&tlsDisableOCSPEndpointCheck=true", "valid": false, "warning": false, "hosts": null, "auth": null, "options": {} }, { "description": "tlsDisableCertificateRevocationCheck=true and tlsDisableOCSPEndpointCheck=false raises an error", "uri": "mongodb://example.com/?tlsDisableCertificateRevocationCheck=true&tlsDisableOCSPEndpointCheck=false", "valid": false, "warning": false, "hosts": null, "auth": null, "options": {} }, { "description": "tlsDisableCertificateRevocationCheck=false and tlsDisableOCSPEndpointCheck=true raises an error", "uri": "mongodb://example.com/?tlsDisableCertificateRevocationCheck=false&tlsDisableOCSPEndpointCheck=true", "valid": false, "warning": false, "hosts": null, "auth": null, "options": {} }, { "description": "tlsDisableCertificateRevocationCheck and tlsDisableOCSPEndpointCheck both present (and false) raises an error", "uri": "mongodb://example.com/?tlsDisableCertificateRevocationCheck=false&tlsDisableOCSPEndpointCheck=false", "valid": false, "warning": false, "hosts": null, "auth": null, "options": {} }, { "description": "tlsDisableOCSPEndpointCheck and tlsDisableCertificateRevocationCheck both present (and true) raises an error", "uri": "mongodb://example.com/?tlsDisableOCSPEndpointCheck=true&tlsDisableCertificateRevocationCheck=true", "valid": false, "warning": false, "hosts": null, "auth": null, "options": {} }, { "description": "tlsDisableOCSPEndpointCheck=true and tlsDisableCertificateRevocationCheck=false raises an error", "uri": "mongodb://example.com/?tlsDisableOCSPEndpointCheck=true&tlsDisableCertificateRevocationCheck=false", "valid": false, "warning": false, "hosts": null, "auth": null, "options": {} }, { "description": "tlsDisableOCSPEndpointCheck=false and tlsDisableCertificateRevocationCheck=true raises an error", "uri": "mongodb://example.com/?tlsDisableOCSPEndpointCheck=false&tlsDisableCertificateRevocationCheck=true", "valid": false, "warning": false, "hosts": null, "auth": null, "options": {} }, { "description": "tlsDisableOCSPEndpointCheck and tlsDisableCertificateRevocationCheck both present (and false) raises an error", "uri": "mongodb://example.com/?tlsDisableOCSPEndpointCheck=false&tlsDisableCertificateRevocationCheck=false", "valid": false, "warning": false, "hosts": null, "auth": null, "options": {} }, { "description": "tlsDisableOCSPEndpointCheck can be set to true", "uri": "mongodb://example.com/?tls=true&tlsDisableOCSPEndpointCheck=true", "valid": true, "warning": false, "hosts": null, "auth": null, "options": { "tls": true, "tlsDisableOCSPEndpointCheck": true } }, { "description": "tlsDisableOCSPEndpointCheck can be set to false", "uri": "mongodb://example.com/?tls=true&tlsDisableOCSPEndpointCheck=false", "valid": true, "warning": false, "hosts": null, "auth": null, "options": { "tls": true, "tlsDisableOCSPEndpointCheck": false } }, { "description": "tlsInsecure and tlsDisableOCSPEndpointCheck both present (and true) raises an error", "uri": "mongodb://example.com/?tlsInsecure=true&tlsDisableOCSPEndpointCheck=true", "valid": false, "warning": false, "hosts": null, "auth": null, "options": {} }, { "description": "tlsInsecure=true and tlsDisableOCSPEndpointCheck=false raises an error", "uri": "mongodb://example.com/?tlsInsecure=true&tlsDisableOCSPEndpointCheck=false", "valid": false, "warning": false, "hosts": null, "auth": null, "options": {} }, { "description": "tlsInsecure=false and tlsDisableOCSPEndpointCheck=true raises an error", "uri": "mongodb://example.com/?tlsInsecure=false&tlsDisableOCSPEndpointCheck=true", "valid": false, "warning": false, "hosts": null, "auth": null, "options": {} }, { "description": "tlsInsecure and tlsDisableOCSPEndpointCheck both present (and false) raises an error", "uri": "mongodb://example.com/?tlsInsecure=false&tlsDisableOCSPEndpointCheck=false", "valid": false, "warning": false, "hosts": null, "auth": null, "options": {} }, { "description": "tlsDisableOCSPEndpointCheck and tlsInsecure both present (and true) raises an error", "uri": "mongodb://example.com/?tlsDisableOCSPEndpointCheck=true&tlsInsecure=true", "valid": false, "warning": false, "hosts": null, "auth": null, "options": {} }, { "description": "tlsDisableOCSPEndpointCheck=true and tlsInsecure=false raises an error", "uri": "mongodb://example.com/?tlsDisableOCSPEndpointCheck=true&tlsInsecure=false", "valid": false, "warning": false, "hosts": null, "auth": null, "options": {} }, { "description": "tlsDisableOCSPEndpointCheck=false and tlsInsecure=true raises an error", "uri": "mongodb://example.com/?tlsDisableOCSPEndpointCheck=false&tlsInsecure=true", "valid": false, "warning": false, "hosts": null, "auth": null, "options": {} }, { "description": "tlsDisableOCSPEndpointCheck and tlsInsecure both present (and false) raises an error", "uri": "mongodb://example.com/?tlsDisableOCSPEndpointCheck=false&tlsInsecure=false", "valid": false, "warning": false, "hosts": null, "auth": null, "options": {} }, { "description": "tlsAllowInvalidCertificates and tlsDisableOCSPEndpointCheck both present (and true) raises an error", "uri": "mongodb://example.com/?tlsAllowInvalidCertificates=true&tlsDisableOCSPEndpointCheck=true", "valid": false, "warning": false, "hosts": null, "auth": null, "options": {} }, { "description": "tlsAllowInvalidCertificates=true and tlsDisableOCSPEndpointCheck=false raises an error", "uri": "mongodb://example.com/?tlsAllowInvalidCertificates=true&tlsDisableOCSPEndpointCheck=false", "valid": false, "warning": false, "hosts": null, "auth": null, "options": {} }, { "description": "tlsAllowInvalidCertificates=false and tlsDisableOCSPEndpointCheck=true raises an error", "uri": "mongodb://example.com/?tlsAllowInvalidCertificates=false&tlsDisableOCSPEndpointCheck=true", "valid": false, "warning": false, "hosts": null, "auth": null, "options": {} }, { "description": "tlsAllowInvalidCertificates and tlsDisableOCSPEndpointCheck both present (and false) raises an error", "uri": "mongodb://example.com/?tlsAllowInvalidCertificates=false&tlsDisableOCSPEndpointCheck=false", "valid": false, "warning": false, "hosts": null, "auth": null, "options": {} }, { "description": "tlsDisableOCSPEndpointCheck and tlsAllowInvalidCertificates both present (and true) raises an error", "uri": "mongodb://example.com/?tlsDisableOCSPEndpointCheck=true&tlsAllowInvalidCertificates=true", "valid": false, "warning": false, "hosts": null, "auth": null, "options": {} }, { "description": "tlsDisableOCSPEndpointCheck=true and tlsAllowInvalidCertificates=false raises an error", "uri": "mongodb://example.com/?tlsDisableOCSPEndpointCheck=true&tlsAllowInvalidCertificates=false", "valid": false, "warning": false, "hosts": null, "auth": null, "options": {} }, { "description": "tlsDisableOCSPEndpointCheck=false and tlsAllowInvalidCertificates=true raises an error", "uri": "mongodb://example.com/?tlsDisableOCSPEndpointCheck=false&tlsAllowInvalidCertificates=true", "valid": false, "warning": false, "hosts": null, "auth": null, "options": {} }, { "description": "tlsDisableOCSPEndpointCheck and tlsAllowInvalidCertificates both present (and false) raises an error", "uri": "mongodb://example.com/?tlsDisableOCSPEndpointCheck=false&tlsAllowInvalidCertificates=false", "valid": false, "warning": false, "hosts": null, "auth": null, "options": {} } ] } mongodb-mongo-python-driver-509e9b7/test/utils.py000066400000000000000000001150331462766011000221310ustar00rootroot00000000000000# Copyright 2012-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. """Utilities for testing pymongo""" from __future__ import annotations import contextlib import copy import functools import os import re import shutil import sys import threading import time import unittest import warnings from collections import abc, defaultdict from functools import partial from test import client_context, db_pwd, db_user from typing import Any, List from bson import json_util from bson.objectid import ObjectId from bson.son import SON from pymongo import MongoClient, monitoring, operations, read_preferences from pymongo.collection import ReturnDocument from pymongo.cursor import CursorType from pymongo.errors import ConfigurationError, OperationFailure from pymongo.hello import HelloCompat from pymongo.helpers import _SENSITIVE_COMMANDS from pymongo.lock import _create_lock from pymongo.monitoring import ( ConnectionCheckedInEvent, ConnectionCheckedOutEvent, ConnectionCheckOutFailedEvent, ConnectionCheckOutStartedEvent, ConnectionClosedEvent, ConnectionCreatedEvent, ConnectionReadyEvent, PoolClearedEvent, PoolClosedEvent, PoolCreatedEvent, PoolReadyEvent, ) from pymongo.operations import _Op from pymongo.pool import _CancellationContext, _PoolGeneration from pymongo.read_concern import ReadConcern from pymongo.read_preferences import ReadPreference from pymongo.server_selectors import any_server_selector, writable_server_selector from pymongo.server_type import SERVER_TYPE from pymongo.uri_parser import parse_uri from pymongo.write_concern import WriteConcern IMPOSSIBLE_WRITE_CONCERN = WriteConcern(w=50) class BaseListener: def __init__(self): self.events = [] def reset(self): self.events = [] def add_event(self, event): self.events.append(event) def event_count(self, event_type): return len(self.events_by_type(event_type)) def events_by_type(self, event_type): """Return the matching events by event class. event_type can be a single class or a tuple of classes. """ return self.matching(lambda e: isinstance(e, event_type)) def matching(self, matcher): """Return the matching events.""" return [event for event in self.events[:] if matcher(event)] def wait_for_event(self, event, count): """Wait for a number of events to be published, or fail.""" wait_until(lambda: self.event_count(event) >= count, f"find {count} {event} event(s)") class CMAPListener(BaseListener, monitoring.ConnectionPoolListener): def connection_created(self, event): assert isinstance(event, ConnectionCreatedEvent) self.add_event(event) def connection_ready(self, event): assert isinstance(event, ConnectionReadyEvent) self.add_event(event) def connection_closed(self, event): assert isinstance(event, ConnectionClosedEvent) self.add_event(event) def connection_check_out_started(self, event): assert isinstance(event, ConnectionCheckOutStartedEvent) self.add_event(event) def connection_check_out_failed(self, event): assert isinstance(event, ConnectionCheckOutFailedEvent) self.add_event(event) def connection_checked_out(self, event): assert isinstance(event, ConnectionCheckedOutEvent) self.add_event(event) def connection_checked_in(self, event): assert isinstance(event, ConnectionCheckedInEvent) self.add_event(event) def pool_created(self, event): assert isinstance(event, PoolCreatedEvent) self.add_event(event) def pool_ready(self, event): assert isinstance(event, PoolReadyEvent) self.add_event(event) def pool_cleared(self, event): assert isinstance(event, PoolClearedEvent) self.add_event(event) def pool_closed(self, event): assert isinstance(event, PoolClosedEvent) self.add_event(event) class EventListener(BaseListener, monitoring.CommandListener): def __init__(self): super().__init__() self.results = defaultdict(list) @property def started_events(self) -> List[monitoring.CommandStartedEvent]: return self.results["started"] @property def succeeded_events(self) -> List[monitoring.CommandSucceededEvent]: return self.results["succeeded"] @property def failed_events(self) -> List[monitoring.CommandFailedEvent]: return self.results["failed"] def started(self, event: monitoring.CommandStartedEvent) -> None: self.started_events.append(event) self.add_event(event) def succeeded(self, event: monitoring.CommandSucceededEvent) -> None: self.succeeded_events.append(event) self.add_event(event) def failed(self, event: monitoring.CommandFailedEvent) -> None: self.failed_events.append(event) self.add_event(event) def started_command_names(self) -> List[str]: """Return list of command names started.""" return [event.command_name for event in self.started_events] def reset(self) -> None: """Reset the state of this listener.""" self.results.clear() super().reset() class TopologyEventListener(monitoring.TopologyListener): def __init__(self): self.results = defaultdict(list) def closed(self, event): self.results["closed"].append(event) def description_changed(self, event): self.results["description_changed"].append(event) def opened(self, event): self.results["opened"].append(event) def reset(self): """Reset the state of this listener.""" self.results.clear() class AllowListEventListener(EventListener): def __init__(self, *commands): self.commands = set(commands) super().__init__() def started(self, event): if event.command_name in self.commands: super().started(event) def succeeded(self, event): if event.command_name in self.commands: super().succeeded(event) def failed(self, event): if event.command_name in self.commands: super().failed(event) class OvertCommandListener(EventListener): """A CommandListener that ignores sensitive commands.""" ignore_list_collections = False def started(self, event): if event.command_name.lower() not in _SENSITIVE_COMMANDS: super().started(event) def succeeded(self, event): if event.command_name.lower() not in _SENSITIVE_COMMANDS: super().succeeded(event) def failed(self, event): if event.command_name.lower() not in _SENSITIVE_COMMANDS: super().failed(event) class _ServerEventListener: """Listens to all events.""" def __init__(self): self.results = [] def opened(self, event): self.results.append(event) def description_changed(self, event): self.results.append(event) def closed(self, event): self.results.append(event) def matching(self, matcher): """Return the matching events.""" results = self.results[:] return [event for event in results if matcher(event)] def reset(self): self.results = [] class ServerEventListener(_ServerEventListener, monitoring.ServerListener): """Listens to Server events.""" class ServerAndTopologyEventListener( # type: ignore[misc] ServerEventListener, monitoring.TopologyListener ): """Listens to Server and Topology events.""" class HeartbeatEventListener(BaseListener, monitoring.ServerHeartbeatListener): """Listens to only server heartbeat events.""" def started(self, event): self.add_event(event) def succeeded(self, event): self.add_event(event) def failed(self, event): self.add_event(event) class HeartbeatEventsListListener(HeartbeatEventListener): """Listens to only server heartbeat events and publishes them to a provided list.""" def __init__(self, events): super().__init__() self.event_list = events def started(self, event): self.add_event(event) self.event_list.append("serverHeartbeatStartedEvent") def succeeded(self, event): self.add_event(event) self.event_list.append("serverHeartbeatSucceededEvent") def failed(self, event): self.add_event(event) self.event_list.append("serverHeartbeatFailedEvent") class MockConnection: def __init__(self): self.cancel_context = _CancellationContext() self.more_to_come = False def close_conn(self, reason): pass def __enter__(self): return self def __exit__(self, exc_type, exc_val, exc_tb): pass class MockPool: def __init__(self, address, options, handshake=True, client_id=None): self.gen = _PoolGeneration() self._lock = _create_lock() self.opts = options self.operation_count = 0 self.conns = [] def stale_generation(self, gen, service_id): return self.gen.stale(gen, service_id) def checkout(self, handler=None): return MockConnection() def checkin(self, *args, **kwargs): pass def _reset(self, service_id=None): with self._lock: self.gen.inc(service_id) def ready(self): pass def reset(self, service_id=None, interrupt_connections=False): self._reset() def reset_without_pause(self): self._reset() def close(self): self._reset() def update_is_writable(self, is_writable): pass def remove_stale_sockets(self, *args, **kwargs): pass class ScenarioDict(dict): """Dict that returns {} for any unknown key, recursively.""" def __init__(self, data): def convert(v): if isinstance(v, abc.Mapping): return ScenarioDict(v) if isinstance(v, (str, bytes)): return v if isinstance(v, abc.Sequence): return [convert(item) for item in v] return v dict.__init__(self, [(k, convert(v)) for k, v in data.items()]) def __getitem__(self, item): try: return dict.__getitem__(self, item) except KeyError: # Unlike a defaultdict, don't set the key, just return a dict. return ScenarioDict({}) class CompareType: """Class that compares equal to any object of the given type(s).""" def __init__(self, types): self.types = types def __eq__(self, other): return isinstance(other, self.types) class FunctionCallRecorder: """Utility class to wrap a callable and record its invocations.""" def __init__(self, function): self._function = function self._call_list = [] def __call__(self, *args, **kwargs): self._call_list.append((args, kwargs)) return self._function(*args, **kwargs) def reset(self): """Wipes the call list.""" self._call_list = [] def call_list(self): """Returns a copy of the call list.""" return self._call_list[:] @property def call_count(self): """Returns the number of times the function has been called.""" return len(self._call_list) class SpecTestCreator: """Class to create test cases from specifications.""" def __init__(self, create_test, test_class, test_path): """Create a TestCreator object. :Parameters: - `create_test`: callback that returns a test case. The callback must accept the following arguments - a dictionary containing the entire test specification (the `scenario_def`), a dictionary containing the specification for which the test case will be generated (the `test_def`). - `test_class`: the unittest.TestCase class in which to create the test case. - `test_path`: path to the directory containing the JSON files with the test specifications. """ self._create_test = create_test self._test_class = test_class self.test_path = test_path def _ensure_min_max_server_version(self, scenario_def, method): """Test modifier that enforces a version range for the server on a test case. """ if "minServerVersion" in scenario_def: min_ver = tuple(int(elt) for elt in scenario_def["minServerVersion"].split(".")) if min_ver is not None: method = client_context.require_version_min(*min_ver)(method) if "maxServerVersion" in scenario_def: max_ver = tuple(int(elt) for elt in scenario_def["maxServerVersion"].split(".")) if max_ver is not None: method = client_context.require_version_max(*max_ver)(method) if "serverless" in scenario_def: serverless = scenario_def["serverless"] if serverless == "require": serverless_satisfied = client_context.serverless elif serverless == "forbid": serverless_satisfied = not client_context.serverless else: # unset or "allow" serverless_satisfied = True method = unittest.skipUnless( serverless_satisfied, "Serverless requirement not satisfied" )(method) return method @staticmethod def valid_topology(run_on_req): return client_context.is_topology_type( run_on_req.get("topology", ["single", "replicaset", "sharded", "load-balanced"]) ) @staticmethod def min_server_version(run_on_req): version = run_on_req.get("minServerVersion") if version: min_ver = tuple(int(elt) for elt in version.split(".")) return client_context.version >= min_ver return True @staticmethod def max_server_version(run_on_req): version = run_on_req.get("maxServerVersion") if version: max_ver = tuple(int(elt) for elt in version.split(".")) return client_context.version <= max_ver return True @staticmethod def valid_auth_enabled(run_on_req): if "authEnabled" in run_on_req: if run_on_req["authEnabled"]: return client_context.auth_enabled return not client_context.auth_enabled return True @staticmethod def serverless_ok(run_on_req): serverless = run_on_req["serverless"] if serverless == "require": return client_context.serverless elif serverless == "forbid": return not client_context.serverless else: # unset or "allow" return True def should_run_on(self, scenario_def): run_on = scenario_def.get("runOn", []) if not run_on: # Always run these tests. return True for req in run_on: if ( self.valid_topology(req) and self.min_server_version(req) and self.max_server_version(req) and self.valid_auth_enabled(req) and self.serverless_ok(req) ): return True return False def ensure_run_on(self, scenario_def, method): """Test modifier that enforces a 'runOn' on a test case.""" return client_context._require( lambda: self.should_run_on(scenario_def), "runOn not satisfied", method ) def tests(self, scenario_def): """Allow CMAP spec test to override the location of test.""" return scenario_def["tests"] def create_tests(self): for dirpath, _, filenames in os.walk(self.test_path): dirname = os.path.split(dirpath)[-1] for filename in filenames: with open(os.path.join(dirpath, filename)) as scenario_stream: # Use tz_aware=False to match how CodecOptions decodes # dates. opts = json_util.JSONOptions(tz_aware=False) scenario_def = ScenarioDict( json_util.loads(scenario_stream.read(), json_options=opts) ) test_type = os.path.splitext(filename)[0] # Construct test from scenario. for test_def in self.tests(scenario_def): test_name = "test_{}_{}_{}".format( dirname, test_type.replace("-", "_").replace(".", "_"), str(test_def["description"].replace(" ", "_").replace(".", "_")), ) new_test = self._create_test(scenario_def, test_def, test_name) new_test = self._ensure_min_max_server_version(scenario_def, new_test) new_test = self.ensure_run_on(scenario_def, new_test) new_test.__name__ = test_name setattr(self._test_class, new_test.__name__, new_test) def _connection_string(h): if h.startswith(("mongodb://", "mongodb+srv://")): return h return f"mongodb://{h!s}" def _mongo_client(host, port, authenticate=True, directConnection=None, **kwargs): """Create a new client over SSL/TLS if necessary.""" host = host or client_context.host port = port or client_context.port client_options: dict = client_context.default_client_options.copy() if client_context.replica_set_name and not directConnection: client_options["replicaSet"] = client_context.replica_set_name if directConnection is not None: client_options["directConnection"] = directConnection client_options.update(kwargs) uri = _connection_string(host) auth_mech = kwargs.get("authMechanism", "") if client_context.auth_enabled and authenticate and auth_mech != "MONGODB-OIDC": # Only add the default username or password if one is not provided. res = parse_uri(uri) if ( not res["username"] and not res["password"] and "username" not in client_options and "password" not in client_options ): client_options["username"] = db_user client_options["password"] = db_pwd return MongoClient(uri, port, **client_options) def single_client_noauth(h: Any = None, p: Any = None, **kwargs: Any) -> MongoClient[dict]: """Make a direct connection. Don't authenticate.""" return _mongo_client(h, p, authenticate=False, directConnection=True, **kwargs) def single_client(h: Any = None, p: Any = None, **kwargs: Any) -> MongoClient[dict]: """Make a direct connection, and authenticate if necessary.""" return _mongo_client(h, p, directConnection=True, **kwargs) def rs_client_noauth(h: Any = None, p: Any = None, **kwargs: Any) -> MongoClient[dict]: """Connect to the replica set. Don't authenticate.""" return _mongo_client(h, p, authenticate=False, **kwargs) def rs_client(h: Any = None, p: Any = None, **kwargs: Any) -> MongoClient[dict]: """Connect to the replica set and authenticate if necessary.""" return _mongo_client(h, p, **kwargs) def rs_or_single_client_noauth(h: Any = None, p: Any = None, **kwargs: Any) -> MongoClient[dict]: """Connect to the replica set if there is one, otherwise the standalone. Like rs_or_single_client, but does not authenticate. """ return _mongo_client(h, p, authenticate=False, **kwargs) def rs_or_single_client(h: Any = None, p: Any = None, **kwargs: Any) -> MongoClient[Any]: """Connect to the replica set if there is one, otherwise the standalone. Authenticates if necessary. """ return _mongo_client(h, p, **kwargs) def ensure_all_connected(client: MongoClient) -> None: """Ensure that the client's connection pool has socket connections to all members of a replica set. Raises ConfigurationError when called with a non-replica set client. Depending on the use-case, the caller may need to clear any event listeners that are configured on the client. """ hello: dict = client.admin.command(HelloCompat.LEGACY_CMD) if "setName" not in hello: raise ConfigurationError("cluster is not a replica set") target_host_list = set(hello["hosts"] + hello.get("passives", [])) connected_host_list = {hello["me"]} # Run hello until we have connected to each host at least once. def discover(): i = 0 while i < 100 and connected_host_list != target_host_list: hello: dict = client.admin.command( HelloCompat.LEGACY_CMD, read_preference=ReadPreference.SECONDARY ) connected_host_list.update([hello["me"]]) i += 1 return connected_host_list try: wait_until(lambda: target_host_list == discover(), "connected to all hosts") except AssertionError as exc: raise AssertionError( f"{exc}, {connected_host_list} != {target_host_list}, {client.topology_description}" ) def one(s): """Get one element of a set""" return next(iter(s)) def oid_generated_on_process(oid): """Makes a determination as to whether the given ObjectId was generated by the current process, based on the 5-byte random number in the ObjectId. """ return ObjectId._random() == oid.binary[4:9] def delay(sec): return """function() { sleep(%f * 1000); return true; }""" % sec def get_command_line(client): command_line = client.admin.command("getCmdLineOpts") assert command_line["ok"] == 1, "getCmdLineOpts() failed" return command_line def camel_to_snake(camel): # Regex to convert CamelCase to snake_case. snake = re.sub("(.)([A-Z][a-z]+)", r"\1_\2", camel) return re.sub("([a-z0-9])([A-Z])", r"\1_\2", snake).lower() def camel_to_upper_camel(camel): return camel[0].upper() + camel[1:] def camel_to_snake_args(arguments): for arg_name in list(arguments): c2s = camel_to_snake(arg_name) arguments[c2s] = arguments.pop(arg_name) return arguments def snake_to_camel(snake): # Regex to convert snake_case to lowerCamelCase. return re.sub(r"_([a-z])", lambda m: m.group(1).upper(), snake) def parse_collection_options(opts): if "readPreference" in opts: opts["read_preference"] = parse_read_preference(opts.pop("readPreference")) if "writeConcern" in opts: opts["write_concern"] = WriteConcern(**dict(opts.pop("writeConcern"))) if "readConcern" in opts: opts["read_concern"] = ReadConcern(**dict(opts.pop("readConcern"))) if "timeoutMS" in opts: opts["timeout"] = int(opts.pop("timeoutMS")) / 1000.0 return opts def server_started_with_option(client, cmdline_opt, config_opt): """Check if the server was started with a particular option. :Parameters: - `cmdline_opt`: The command line option (i.e. --nojournal) - `config_opt`: The config file option (i.e. nojournal) """ command_line = get_command_line(client) if "parsed" in command_line: parsed = command_line["parsed"] if config_opt in parsed: return parsed[config_opt] argv = command_line["argv"] return cmdline_opt in argv def server_started_with_auth(client): try: command_line = get_command_line(client) except OperationFailure as e: assert e.details is not None msg = e.details.get("errmsg", "") if e.code == 13 or "unauthorized" in msg or "login" in msg: # Unauthorized. return True raise # MongoDB >= 2.0 if "parsed" in command_line: parsed = command_line["parsed"] # MongoDB >= 2.6 if "security" in parsed: security = parsed["security"] # >= rc3 if "authorization" in security: return security["authorization"] == "enabled" # < rc3 return security.get("auth", False) or bool(security.get("keyFile")) return parsed.get("auth", False) or bool(parsed.get("keyFile")) # Legacy argv = command_line["argv"] return "--auth" in argv or "--keyFile" in argv def drop_collections(db): # Drop all non-system collections in this database. for coll in db.list_collection_names(filter={"name": {"$regex": r"^(?!system\.)"}}): db.drop_collection(coll) def remove_all_users(db): db.command("dropAllUsersFromDatabase", 1, writeConcern={"w": client_context.w}) def joinall(threads): """Join threads with a 5-minute timeout, assert joins succeeded""" for t in threads: t.join(300) assert not t.is_alive(), "Thread %s hung" % t def connected(client): """Convenience to wait for a newly-constructed client to connect.""" with warnings.catch_warnings(): # Ignore warning that ping is always routed to primary even # if client's read preference isn't PRIMARY. warnings.simplefilter("ignore", UserWarning) client.admin.command("ping") # Force connection. return client def wait_until(predicate, success_description, timeout=10): """Wait up to 10 seconds (by default) for predicate to be true. E.g.: wait_until(lambda: client.primary == ('a', 1), 'connect to the primary') If the lambda-expression isn't true after 10 seconds, we raise AssertionError("Didn't ever connect to the primary"). Returns the predicate's first true value. """ start = time.time() interval = min(float(timeout) / 100, 0.1) while True: retval = predicate() if retval: return retval if time.time() - start > timeout: raise AssertionError("Didn't ever %s" % success_description) time.sleep(interval) def repl_set_step_down(client, **kwargs): """Run replSetStepDown, first unfreezing a secondary with replSetFreeze.""" cmd = SON([("replSetStepDown", 1)]) cmd.update(kwargs) # Unfreeze a secondary to ensure a speedy election. client.admin.command("replSetFreeze", 0, read_preference=ReadPreference.SECONDARY) client.admin.command(cmd) def is_mongos(client): res = client.admin.command(HelloCompat.LEGACY_CMD) return res.get("msg", "") == "isdbgrid" def assertRaisesExactly(cls, fn, *args, **kwargs): """ Unlike the standard assertRaises, this checks that a function raises a specific class of exception, and not a subclass. E.g., check that MongoClient() raises ConnectionFailure but not its subclass, AutoReconnect. """ try: fn(*args, **kwargs) except Exception as e: assert e.__class__ == cls, f"got {e.__class__.__name__}, expected {cls.__name__}" else: raise AssertionError("%s not raised" % cls) @contextlib.contextmanager def _ignore_deprecations(): with warnings.catch_warnings(): warnings.simplefilter("ignore", DeprecationWarning) yield def ignore_deprecations(wrapped=None): """A context manager or a decorator.""" if wrapped: @functools.wraps(wrapped) def wrapper(*args, **kwargs): with _ignore_deprecations(): return wrapped(*args, **kwargs) return wrapper else: return _ignore_deprecations() class DeprecationFilter: def __init__(self, action="ignore"): """Start filtering deprecations.""" self.warn_context = warnings.catch_warnings() self.warn_context.__enter__() warnings.simplefilter(action, DeprecationWarning) def stop(self): """Stop filtering deprecations.""" self.warn_context.__exit__() # type: ignore self.warn_context = None # type: ignore def get_pool(client): """Get the standalone, primary, or mongos pool.""" topology = client._get_topology() server = topology.select_server(writable_server_selector, _Op.TEST) return server.pool def get_pools(client): """Get all pools.""" return [ server.pool for server in client._get_topology().select_servers(any_server_selector, _Op.TEST) ] # Constants for run_threads and lazy_client_trial. NTRIALS = 5 NTHREADS = 10 def run_threads(collection, target): """Run a target function in many threads. target is a function taking a Collection and an integer. """ threads = [] for i in range(NTHREADS): bound_target = partial(target, collection, i) threads.append(threading.Thread(target=bound_target)) for t in threads: t.start() for t in threads: t.join(60) assert not t.is_alive() @contextlib.contextmanager def frequent_thread_switches(): """Make concurrency bugs more likely to manifest.""" interval = sys.getswitchinterval() sys.setswitchinterval(1e-6) try: yield finally: sys.setswitchinterval(interval) def lazy_client_trial(reset, target, test, get_client): """Test concurrent operations on a lazily-connecting client. `reset` takes a collection and resets it for the next trial. `target` takes a lazily-connecting collection and an index from 0 to NTHREADS, and performs some operation, e.g. an insert. `test` takes the lazily-connecting collection and asserts a post-condition to prove `target` succeeded. """ collection = client_context.client.pymongo_test.test with frequent_thread_switches(): for _i in range(NTRIALS): reset(collection) lazy_client = get_client() lazy_collection = lazy_client.pymongo_test.test run_threads(lazy_collection, target) test(lazy_collection) def gevent_monkey_patched(): """Check if gevent's monkey patching is active.""" try: import socket import gevent.socket # type:ignore[import] return socket.socket is gevent.socket.socket except ImportError: return False def eventlet_monkey_patched(): """Check if eventlet's monkey patching is active.""" import threading return threading.current_thread.__module__ == "eventlet.green.threading" def is_greenthread_patched(): return gevent_monkey_patched() or eventlet_monkey_patched() def disable_replication(client): """Disable replication on all secondaries.""" for host, port in client.secondaries: secondary = single_client(host, port) secondary.admin.command("configureFailPoint", "stopReplProducer", mode="alwaysOn") def enable_replication(client): """Enable replication on all secondaries.""" for host, port in client.secondaries: secondary = single_client(host, port) secondary.admin.command("configureFailPoint", "stopReplProducer", mode="off") class ExceptionCatchingThread(threading.Thread): """A thread that stores any exception encountered from run().""" def __init__(self, *args, **kwargs): self.exc = None super().__init__(*args, **kwargs) def run(self): try: super().run() except BaseException as exc: self.exc = exc raise def parse_read_preference(pref): # Make first letter lowercase to match read_pref's modes. mode_string = pref.get("mode", "primary") mode_string = mode_string[:1].lower() + mode_string[1:] mode = read_preferences.read_pref_mode_from_name(mode_string) max_staleness = pref.get("maxStalenessSeconds", -1) tag_sets = pref.get("tagSets") or pref.get("tag_sets") return read_preferences.make_read_preference( mode, tag_sets=tag_sets, max_staleness=max_staleness ) def server_name_to_type(name): """Convert a ServerType name to the corresponding value. For SDAM tests.""" # Special case, some tests in the spec include the PossiblePrimary # type, but only single-threaded drivers need that type. We call # possible primaries Unknown. if name == "PossiblePrimary": return SERVER_TYPE.Unknown return getattr(SERVER_TYPE, name) def cat_files(dest, *sources): """Cat multiple files into dest.""" with open(dest, "wb") as fdst: for src in sources: with open(src, "rb") as fsrc: shutil.copyfileobj(fsrc, fdst) @contextlib.contextmanager def assertion_context(msg): """A context manager that adds info to an assertion failure.""" try: yield except AssertionError as exc: raise AssertionError(f"{msg}: {exc}") def parse_spec_options(opts): if "readPreference" in opts: opts["read_preference"] = parse_read_preference(opts.pop("readPreference")) if "writeConcern" in opts: w_opts = opts.pop("writeConcern") if "journal" in w_opts: w_opts["j"] = w_opts.pop("journal") if "wtimeoutMS" in w_opts: w_opts["wtimeout"] = w_opts.pop("wtimeoutMS") opts["write_concern"] = WriteConcern(**dict(w_opts)) if "readConcern" in opts: opts["read_concern"] = ReadConcern(**dict(opts.pop("readConcern"))) if "timeoutMS" in opts: assert isinstance(opts["timeoutMS"], int) opts["timeout"] = int(opts.pop("timeoutMS")) / 1000.0 if "maxTimeMS" in opts: opts["max_time_ms"] = opts.pop("maxTimeMS") if "maxCommitTimeMS" in opts: opts["max_commit_time_ms"] = opts.pop("maxCommitTimeMS") if "hint" in opts: hint = opts.pop("hint") if not isinstance(hint, str): hint = list(hint.items()) opts["hint"] = hint # Properly format 'hint' arguments for the Bulk API tests. if "requests" in opts: reqs = opts.pop("requests") for req in reqs: if "name" in req: # CRUD v2 format args = req.pop("arguments", {}) if "hint" in args: hint = args.pop("hint") if not isinstance(hint, str): hint = list(hint.items()) args["hint"] = hint req["arguments"] = args else: # Unified test format bulk_model, spec = next(iter(req.items())) if "hint" in spec: hint = spec.pop("hint") if not isinstance(hint, str): hint = list(hint.items()) spec["hint"] = hint opts["requests"] = reqs return dict(opts) def prepare_spec_arguments(spec, arguments, opname, entity_map, with_txn_callback): for arg_name in list(arguments): c2s = camel_to_snake(arg_name) # PyMongo accepts sort as list of tuples. if arg_name == "sort": sort_dict = arguments[arg_name] arguments[arg_name] = list(sort_dict.items()) # Named "key" instead not fieldName. if arg_name == "fieldName": arguments["key"] = arguments.pop(arg_name) # Aggregate uses "batchSize", while find uses batch_size. elif (arg_name == "batchSize" or arg_name == "allowDiskUse") and opname == "aggregate": continue elif arg_name == "timeoutMode": raise unittest.SkipTest("PyMongo does not support timeoutMode") # Requires boolean returnDocument. elif arg_name == "returnDocument": arguments[c2s] = getattr(ReturnDocument, arguments.pop(arg_name).upper()) elif c2s == "requests": # Parse each request into a bulk write model. requests = [] for request in arguments["requests"]: if "name" in request: # CRUD v2 format bulk_model = camel_to_upper_camel(request["name"]) bulk_class = getattr(operations, bulk_model) bulk_arguments = camel_to_snake_args(request["arguments"]) else: # Unified test format bulk_model, spec = next(iter(request.items())) bulk_class = getattr(operations, camel_to_upper_camel(bulk_model)) bulk_arguments = camel_to_snake_args(spec) requests.append(bulk_class(**dict(bulk_arguments))) arguments["requests"] = requests elif arg_name == "session": arguments["session"] = entity_map[arguments["session"]] elif opname == "open_download_stream" and arg_name == "id": arguments["file_id"] = arguments.pop(arg_name) elif opname not in ("find", "find_one") and c2s == "max_time_ms": # find is the only method that accepts snake_case max_time_ms. # All other methods take kwargs which must use the server's # camelCase maxTimeMS. See PYTHON-1855. arguments["maxTimeMS"] = arguments.pop("max_time_ms") elif opname == "with_transaction" and arg_name == "callback": if "operations" in arguments[arg_name]: # CRUD v2 format callback_ops = arguments[arg_name]["operations"] else: # Unified test format callback_ops = arguments[arg_name] arguments["callback"] = lambda _: with_txn_callback(copy.deepcopy(callback_ops)) elif opname == "drop_collection" and arg_name == "collection": arguments["name_or_collection"] = arguments.pop(arg_name) elif opname == "create_collection": if arg_name == "collection": arguments["name"] = arguments.pop(arg_name) arguments["check_exists"] = False # Any other arguments to create_collection are passed through # **kwargs. elif opname == "create_index" and arg_name == "keys": arguments["keys"] = list(arguments.pop(arg_name).items()) elif opname == "drop_index" and arg_name == "name": arguments["index_or_name"] = arguments.pop(arg_name) elif opname == "rename" and arg_name == "to": arguments["new_name"] = arguments.pop(arg_name) elif opname == "rename" and arg_name == "dropTarget": arguments["dropTarget"] = arguments.pop(arg_name) elif arg_name == "cursorType": cursor_type = arguments.pop(arg_name) if cursor_type == "tailable": arguments["cursor_type"] = CursorType.TAILABLE elif cursor_type == "tailableAwait": arguments["cursor_type"] = CursorType.TAILABLE else: raise AssertionError(f"Unsupported cursorType: {cursor_type}") else: arguments[c2s] = arguments.pop(arg_name) def set_fail_point(client, command_args): cmd = SON([("configureFailPoint", "failCommand")]) cmd.update(command_args) client.admin.command(cmd) mongodb-mongo-python-driver-509e9b7/test/utils_selection_tests.py000066400000000000000000000236451462766011000254270ustar00rootroot00000000000000# Copyright 2015-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. """Utilities for testing Server Selection and Max Staleness.""" from __future__ import annotations import datetime import os import sys from pymongo.operations import _Op sys.path[0:0] = [""] from test import unittest from test.pymongo_mocks import DummyMonitor from test.utils import MockPool, parse_read_preference from bson import json_util from pymongo.common import HEARTBEAT_FREQUENCY, clean_node from pymongo.errors import AutoReconnect, ConfigurationError from pymongo.hello import Hello, HelloCompat from pymongo.server_description import ServerDescription from pymongo.server_selectors import writable_server_selector from pymongo.settings import TopologySettings from pymongo.topology import Topology def get_addresses(server_list): seeds = [] hosts = [] for server in server_list: seeds.append(clean_node(server["address"])) hosts.append(server["address"]) return seeds, hosts def make_last_write_date(server): epoch = datetime.datetime.fromtimestamp(0, tz=datetime.timezone.utc).replace(tzinfo=None) millis = server.get("lastWrite", {}).get("lastWriteDate") if millis: diff = ((millis % 1000) + 1000) % 1000 seconds = (millis - diff) / 1000 micros = diff * 1000 return epoch + datetime.timedelta(seconds=seconds, microseconds=micros) else: # "Unknown" server. return epoch def make_server_description(server, hosts): """Make a ServerDescription from server info in a JSON test.""" server_type = server["type"] if server_type in ("Unknown", "PossiblePrimary"): return ServerDescription(clean_node(server["address"]), Hello({})) hello_response = {"ok": True, "hosts": hosts} if server_type not in ("Standalone", "Mongos", "RSGhost"): hello_response["setName"] = "rs" if server_type == "RSPrimary": hello_response[HelloCompat.LEGACY_CMD] = True elif server_type == "RSSecondary": hello_response["secondary"] = True elif server_type == "Mongos": hello_response["msg"] = "isdbgrid" elif server_type == "RSGhost": hello_response["isreplicaset"] = True elif server_type == "RSArbiter": hello_response["arbiterOnly"] = True hello_response["lastWrite"] = {"lastWriteDate": make_last_write_date(server)} for field in "maxWireVersion", "tags", "idleWritePeriodMillis": if field in server: hello_response[field] = server[field] hello_response.setdefault("maxWireVersion", 6) # Sets _last_update_time to now. sd = ServerDescription( clean_node(server["address"]), Hello(hello_response), round_trip_time=server["avg_rtt_ms"] / 1000.0, ) if "lastUpdateTime" in server: sd._last_update_time = server["lastUpdateTime"] / 1000.0 # ms to sec. return sd def get_topology_type_name(scenario_def): td = scenario_def["topology_description"] name = td["type"] if name == "Unknown": # PyMongo never starts a topology in type Unknown. return "Sharded" if len(td["servers"]) > 1 else "Single" else: return name def get_topology_settings_dict(**kwargs): settings = { "monitor_class": DummyMonitor, "heartbeat_frequency": HEARTBEAT_FREQUENCY, "pool_class": MockPool, } settings.update(kwargs) return settings def create_topology(scenario_def, **kwargs): # Initialize topologies. if "heartbeatFrequencyMS" in scenario_def: frequency = int(scenario_def["heartbeatFrequencyMS"]) / 1000.0 else: frequency = HEARTBEAT_FREQUENCY seeds, hosts = get_addresses(scenario_def["topology_description"]["servers"]) topology_type = get_topology_type_name(scenario_def) if topology_type == "LoadBalanced": kwargs.setdefault("load_balanced", True) # Force topology description to ReplicaSet elif topology_type in ["ReplicaSetNoPrimary", "ReplicaSetWithPrimary"]: kwargs.setdefault("replica_set_name", "rs") settings = get_topology_settings_dict(heartbeat_frequency=frequency, seeds=seeds, **kwargs) # "Eligible servers" is defined in the server selection spec as # the set of servers matching both the ReadPreference's mode # and tag sets. topology = Topology(TopologySettings(**settings)) topology.open() # Update topologies with server descriptions. for server in scenario_def["topology_description"]["servers"]: server_description = make_server_description(server, hosts) topology.on_change(server_description) # Assert that descriptions match assert ( scenario_def["topology_description"]["type"] == topology.description.topology_type_name ), topology.description.topology_type_name return topology def create_test(scenario_def): def run_scenario(self): _, hosts = get_addresses(scenario_def["topology_description"]["servers"]) # "Eligible servers" is defined in the server selection spec as # the set of servers matching both the ReadPreference's mode # and tag sets. top_latency = create_topology(scenario_def) # "In latency window" is defined in the server selection # spec as the subset of suitable_servers that falls within the # allowable latency window. top_suitable = create_topology(scenario_def, local_threshold_ms=1000000) # Create server selector. if scenario_def.get("operation") == "write": pref = writable_server_selector else: # Make first letter lowercase to match read_pref's modes. pref_def = scenario_def["read_preference"] if scenario_def.get("error"): with self.assertRaises((ConfigurationError, ValueError)): # Error can be raised when making Read Pref or selecting. pref = parse_read_preference(pref_def) top_latency.select_server(pref, _Op.TEST) return pref = parse_read_preference(pref_def) # Select servers. if not scenario_def.get("suitable_servers"): with self.assertRaises(AutoReconnect): top_suitable.select_server(pref, _Op.TEST, server_selection_timeout=0) return if not scenario_def["in_latency_window"]: with self.assertRaises(AutoReconnect): top_latency.select_server(pref, _Op.TEST, server_selection_timeout=0) return actual_suitable_s = top_suitable.select_servers(pref, _Op.TEST, server_selection_timeout=0) actual_latency_s = top_latency.select_servers(pref, _Op.TEST, server_selection_timeout=0) expected_suitable_servers = {} for server in scenario_def["suitable_servers"]: server_description = make_server_description(server, hosts) expected_suitable_servers[server["address"]] = server_description actual_suitable_servers = {} for s in actual_suitable_s: actual_suitable_servers[ "%s:%d" % (s.description.address[0], s.description.address[1]) ] = s.description self.assertEqual(len(actual_suitable_servers), len(expected_suitable_servers)) for k, actual in actual_suitable_servers.items(): expected = expected_suitable_servers[k] self.assertEqual(expected.address, actual.address) self.assertEqual(expected.server_type, actual.server_type) self.assertEqual(expected.round_trip_time, actual.round_trip_time) self.assertEqual(expected.tags, actual.tags) self.assertEqual(expected.all_hosts, actual.all_hosts) expected_latency_servers = {} for server in scenario_def["in_latency_window"]: server_description = make_server_description(server, hosts) expected_latency_servers[server["address"]] = server_description actual_latency_servers = {} for s in actual_latency_s: actual_latency_servers[ "%s:%d" % (s.description.address[0], s.description.address[1]) ] = s.description self.assertEqual(len(actual_latency_servers), len(expected_latency_servers)) for k, actual in actual_latency_servers.items(): expected = expected_latency_servers[k] self.assertEqual(expected.address, actual.address) self.assertEqual(expected.server_type, actual.server_type) self.assertEqual(expected.round_trip_time, actual.round_trip_time) self.assertEqual(expected.tags, actual.tags) self.assertEqual(expected.all_hosts, actual.all_hosts) return run_scenario def create_selection_tests(test_dir): class TestAllScenarios(unittest.TestCase): pass for dirpath, _, filenames in os.walk(test_dir): dirname = os.path.split(dirpath) dirname = os.path.split(dirname[-2])[-1] + "_" + dirname[-1] for filename in filenames: if os.path.splitext(filename)[1] != ".json": continue with open(os.path.join(dirpath, filename)) as scenario_stream: scenario_def = json_util.loads(scenario_stream.read()) # Construct test from scenario. new_test = create_test(scenario_def) test_name = f"test_{dirname}_{os.path.splitext(filename)[0]}" new_test.__name__ = test_name setattr(TestAllScenarios, new_test.__name__, new_test) return TestAllScenarios mongodb-mongo-python-driver-509e9b7/test/utils_spec_runner.py000066400000000000000000000631061462766011000245370ustar00rootroot00000000000000# Copyright 2019-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. """Utilities for testing driver specs.""" from __future__ import annotations import functools import threading from collections import abc from test import IntegrationTest, client_context, client_knobs from test.utils import ( CMAPListener, CompareType, EventListener, OvertCommandListener, ServerAndTopologyEventListener, camel_to_snake, camel_to_snake_args, parse_spec_options, prepare_spec_arguments, rs_client, ) from typing import List from bson import ObjectId, decode, encode from bson.binary import Binary from bson.int64 import Int64 from bson.son import SON from gridfs import GridFSBucket from pymongo import client_session from pymongo.command_cursor import CommandCursor from pymongo.cursor import Cursor from pymongo.errors import BulkWriteError, OperationFailure, PyMongoError from pymongo.read_concern import ReadConcern from pymongo.read_preferences import ReadPreference from pymongo.results import BulkWriteResult, _WriteResult from pymongo.write_concern import WriteConcern class SpecRunnerThread(threading.Thread): def __init__(self, name): super().__init__() self.name = name self.exc = None self.daemon = True self.cond = threading.Condition() self.ops = [] self.stopped = False def schedule(self, work): self.ops.append(work) with self.cond: self.cond.notify() def stop(self): self.stopped = True with self.cond: self.cond.notify() def run(self): while not self.stopped or self.ops: if not self.ops: with self.cond: self.cond.wait(10) if self.ops: try: work = self.ops.pop(0) work() except Exception as exc: self.exc = exc self.stop() class SpecRunner(IntegrationTest): mongos_clients: List knobs: client_knobs listener: EventListener @classmethod def setUpClass(cls): super().setUpClass() cls.mongos_clients = [] # Speed up the tests by decreasing the heartbeat frequency. cls.knobs = client_knobs(heartbeat_frequency=0.1, min_heartbeat_interval=0.1) cls.knobs.enable() @classmethod def tearDownClass(cls): cls.knobs.disable() super().tearDownClass() def setUp(self): super().setUp() self.targets = {} self.listener = None # type: ignore self.pool_listener = None self.server_listener = None self.maxDiff = None def _set_fail_point(self, client, command_args): cmd = SON([("configureFailPoint", "failCommand")]) cmd.update(command_args) client.admin.command(cmd) def set_fail_point(self, command_args): clients = self.mongos_clients if self.mongos_clients else [self.client] for client in clients: self._set_fail_point(client, command_args) def targeted_fail_point(self, session, fail_point): """Run the targetedFailPoint test operation. Enable the fail point on the session's pinned mongos. """ clients = {c.address: c for c in self.mongos_clients} client = clients[session._pinned_address] self._set_fail_point(client, fail_point) self.addCleanup(self.set_fail_point, {"mode": "off"}) def assert_session_pinned(self, session): """Run the assertSessionPinned test operation. Assert that the given session is pinned. """ self.assertIsNotNone(session._transaction.pinned_address) def assert_session_unpinned(self, session): """Run the assertSessionUnpinned test operation. Assert that the given session is not pinned. """ self.assertIsNone(session._pinned_address) self.assertIsNone(session._transaction.pinned_address) def assert_collection_exists(self, database, collection): """Run the assertCollectionExists test operation.""" db = self.client[database] self.assertIn(collection, db.list_collection_names()) def assert_collection_not_exists(self, database, collection): """Run the assertCollectionNotExists test operation.""" db = self.client[database] self.assertNotIn(collection, db.list_collection_names()) def assert_index_exists(self, database, collection, index): """Run the assertIndexExists test operation.""" coll = self.client[database][collection] self.assertIn(index, [doc["name"] for doc in coll.list_indexes()]) def assert_index_not_exists(self, database, collection, index): """Run the assertIndexNotExists test operation.""" coll = self.client[database][collection] self.assertNotIn(index, [doc["name"] for doc in coll.list_indexes()]) def assertErrorLabelsContain(self, exc, expected_labels): labels = [l for l in expected_labels if exc.has_error_label(l)] self.assertEqual(labels, expected_labels) def assertErrorLabelsOmit(self, exc, omit_labels): for label in omit_labels: self.assertFalse( exc.has_error_label(label), msg=f"error labels should not contain {label}" ) def kill_all_sessions(self): clients = self.mongos_clients if self.mongos_clients else [self.client] for client in clients: try: client.admin.command("killAllSessions", []) except OperationFailure: # "operation was interrupted" by killing the command's # own session. pass def check_command_result(self, expected_result, result): # Only compare the keys in the expected result. filtered_result = {} for key in expected_result: try: filtered_result[key] = result[key] except KeyError: pass self.assertEqual(filtered_result, expected_result) # TODO: factor the following function with test_crud.py. def check_result(self, expected_result, result): if isinstance(result, _WriteResult): for res in expected_result: prop = camel_to_snake(res) # SPEC-869: Only BulkWriteResult has upserted_count. if prop == "upserted_count" and not isinstance(result, BulkWriteResult): if result.upserted_id is not None: upserted_count = 1 else: upserted_count = 0 self.assertEqual(upserted_count, expected_result[res], prop) elif prop == "inserted_ids": # BulkWriteResult does not have inserted_ids. if isinstance(result, BulkWriteResult): self.assertEqual(len(expected_result[res]), result.inserted_count) else: # InsertManyResult may be compared to [id1] from the # crud spec or {"0": id1} from the retryable write spec. ids = expected_result[res] if isinstance(ids, dict): ids = [ids[str(i)] for i in range(len(ids))] self.assertEqual(ids, result.inserted_ids, prop) elif prop == "upserted_ids": # Convert indexes from strings to integers. ids = expected_result[res] expected_ids = {} for str_index in ids: expected_ids[int(str_index)] = ids[str_index] self.assertEqual(expected_ids, result.upserted_ids, prop) else: self.assertEqual(getattr(result, prop), expected_result[res], prop) return True else: def _helper(expected_result, result): if isinstance(expected_result, abc.Mapping): for i in expected_result.keys(): self.assertEqual(expected_result[i], result[i]) elif isinstance(expected_result, list): for i, k in zip(expected_result, result): _helper(i, k) else: self.assertEqual(expected_result, result) _helper(expected_result, result) return None def get_object_name(self, op): """Allow subclasses to override handling of 'object' Transaction spec says 'object' is required. """ return op["object"] @staticmethod def parse_options(opts): return parse_spec_options(opts) def run_operation(self, sessions, collection, operation): original_collection = collection name = camel_to_snake(operation["name"]) if name == "run_command": name = "command" elif name == "download_by_name": name = "open_download_stream_by_name" elif name == "download": name = "open_download_stream" elif name == "map_reduce": self.skipTest("PyMongo does not support mapReduce") elif name == "count": self.skipTest("PyMongo does not support count") database = collection.database collection = database.get_collection(collection.name) if "collectionOptions" in operation: collection = collection.with_options( **self.parse_options(operation["collectionOptions"]) ) object_name = self.get_object_name(operation) if object_name == "gridfsbucket": # Only create the GridFSBucket when we need it (for the gridfs # retryable reads tests). obj = GridFSBucket(database, bucket_name=collection.name) else: objects = { "client": database.client, "database": database, "collection": collection, "testRunner": self, } objects.update(sessions) obj = objects[object_name] # Combine arguments with options and handle special cases. arguments = operation.get("arguments", {}) arguments.update(arguments.pop("options", {})) self.parse_options(arguments) cmd = getattr(obj, name) with_txn_callback = functools.partial( self.run_operations, sessions, original_collection, in_with_transaction=True ) prepare_spec_arguments(operation, arguments, name, sessions, with_txn_callback) if name == "run_on_thread": args = {"sessions": sessions, "collection": collection} args.update(arguments) arguments = args result = cmd(**dict(arguments)) # Cleanup open change stream cursors. if name == "watch": self.addCleanup(result.close) if name == "aggregate": if arguments["pipeline"] and "$out" in arguments["pipeline"][-1]: # Read from the primary to ensure causal consistency. out = collection.database.get_collection( arguments["pipeline"][-1]["$out"], read_preference=ReadPreference.PRIMARY ) return out.find() if "download" in name: result = Binary(result.read()) if isinstance(result, Cursor) or isinstance(result, CommandCursor): return list(result) return result def allowable_errors(self, op): """Allow encryption spec to override expected error classes.""" return (PyMongoError,) def _run_op(self, sessions, collection, op, in_with_transaction): expected_result = op.get("result") if expect_error(op): with self.assertRaises(self.allowable_errors(op), msg=op["name"]) as context: self.run_operation(sessions, collection, op.copy()) exc = context.exception if expect_error_message(expected_result): if isinstance(exc, BulkWriteError): errmsg = str(exc.details).lower() else: errmsg = str(exc).lower() self.assertIn(expected_result["errorContains"].lower(), errmsg) if expect_error_code(expected_result): self.assertEqual(expected_result["errorCodeName"], exc.details.get("codeName")) if expect_error_labels_contain(expected_result): self.assertErrorLabelsContain(exc, expected_result["errorLabelsContain"]) if expect_error_labels_omit(expected_result): self.assertErrorLabelsOmit(exc, expected_result["errorLabelsOmit"]) if expect_timeout_error(expected_result): self.assertIsInstance(exc, PyMongoError) if not exc.timeout: # Re-raise the exception for better diagnostics. raise exc # Reraise the exception if we're in the with_transaction # callback. if in_with_transaction: raise context.exception else: result = self.run_operation(sessions, collection, op.copy()) if "result" in op: if op["name"] == "runCommand": self.check_command_result(expected_result, result) else: self.check_result(expected_result, result) def run_operations(self, sessions, collection, ops, in_with_transaction=False): for op in ops: self._run_op(sessions, collection, op, in_with_transaction) # TODO: factor with test_command_monitoring.py def check_events(self, test, listener, session_ids): events = listener.started_events if not len(test["expectations"]): return # Give a nicer message when there are missing or extra events cmds = decode_raw([event.command for event in events]) self.assertEqual(len(events), len(test["expectations"]), cmds) for i, expectation in enumerate(test["expectations"]): event_type = next(iter(expectation)) event = events[i] # The tests substitute 42 for any number other than 0. if event.command_name == "getMore" and event.command["getMore"]: event.command["getMore"] = Int64(42) elif event.command_name == "killCursors": event.command["cursors"] = [Int64(42)] elif event.command_name == "update": # TODO: remove this once PYTHON-1744 is done. # Add upsert and multi fields back into expectations. updates = expectation[event_type]["command"]["updates"] for update in updates: update.setdefault("upsert", False) update.setdefault("multi", False) # Replace afterClusterTime: 42 with actual afterClusterTime. expected_cmd = expectation[event_type]["command"] expected_read_concern = expected_cmd.get("readConcern") if expected_read_concern is not None: time = expected_read_concern.get("afterClusterTime") if time == 42: actual_time = event.command.get("readConcern", {}).get("afterClusterTime") if actual_time is not None: expected_read_concern["afterClusterTime"] = actual_time recovery_token = expected_cmd.get("recoveryToken") if recovery_token == 42: expected_cmd["recoveryToken"] = CompareType(dict) # Replace lsid with a name like "session0" to match test. if "lsid" in event.command: for name, lsid in session_ids.items(): if event.command["lsid"] == lsid: event.command["lsid"] = name break for attr, expected in expectation[event_type].items(): actual = getattr(event, attr) expected = wrap_types(expected) if isinstance(expected, dict): for key, val in expected.items(): if val is None: if key in actual: self.fail(f"Unexpected key [{key}] in {actual!r}") elif key not in actual: self.fail(f"Expected key [{key}] in {actual!r}") else: self.assertEqual( val, decode_raw(actual[key]), f"Key [{key}] in {actual}" ) else: self.assertEqual(actual, expected) def maybe_skip_scenario(self, test): if test.get("skipReason"): self.skipTest(test.get("skipReason")) def get_scenario_db_name(self, scenario_def): """Allow subclasses to override a test's database name.""" return scenario_def["database_name"] def get_scenario_coll_name(self, scenario_def): """Allow subclasses to override a test's collection name.""" return scenario_def["collection_name"] def get_outcome_coll_name(self, outcome, collection): """Allow subclasses to override outcome collection.""" return collection.name def run_test_ops(self, sessions, collection, test): """Added to allow retryable writes spec to override a test's operation. """ self.run_operations(sessions, collection, test["operations"]) def parse_client_options(self, opts): """Allow encryption spec to override a clientOptions parsing.""" # Convert test['clientOptions'] to dict to avoid a Jython bug using # "**" with ScenarioDict. return dict(opts) def setup_scenario(self, scenario_def): """Allow specs to override a test's setup.""" db_name = self.get_scenario_db_name(scenario_def) coll_name = self.get_scenario_coll_name(scenario_def) documents = scenario_def["data"] # Setup the collection with as few majority writes as possible. db = client_context.client.get_database(db_name) coll_exists = bool(db.list_collection_names(filter={"name": coll_name})) if coll_exists: db[coll_name].delete_many({}) # Only use majority wc only on the final write. wc = WriteConcern(w="majority") if documents: db.get_collection(coll_name, write_concern=wc).insert_many(documents) elif not coll_exists: # Ensure collection exists. db.create_collection(coll_name, write_concern=wc) def run_scenario(self, scenario_def, test): self.maybe_skip_scenario(test) # Kill all sessions before and after each test to prevent an open # transaction (from a test failure) from blocking collection/database # operations during test set up and tear down. self.kill_all_sessions() self.addCleanup(self.kill_all_sessions) self.setup_scenario(scenario_def) database_name = self.get_scenario_db_name(scenario_def) collection_name = self.get_scenario_coll_name(scenario_def) # SPEC-1245 workaround StaleDbVersion on distinct for c in self.mongos_clients: c[database_name][collection_name].distinct("x") # Configure the fail point before creating the client. if "failPoint" in test: fp = test["failPoint"] self.set_fail_point(fp) self.addCleanup( self.set_fail_point, {"configureFailPoint": fp["configureFailPoint"], "mode": "off"} ) listener = OvertCommandListener() pool_listener = CMAPListener() server_listener = ServerAndTopologyEventListener() # Create a new client, to avoid interference from pooled sessions. client_options = self.parse_client_options(test["clientOptions"]) # MMAPv1 does not support retryable writes. if client_options.get("retryWrites") is True and client_context.storage_engine == "mmapv1": self.skipTest("MMAPv1 does not support retryWrites=True") use_multi_mongos = test["useMultipleMongoses"] host = None if use_multi_mongos: if client_context.load_balancer or client_context.serverless: host = client_context.MULTI_MONGOS_LB_URI elif client_context.is_mongos: host = client_context.mongos_seeds() client = rs_client( h=host, event_listeners=[listener, pool_listener, server_listener], **client_options ) self.scenario_client = client self.listener = listener self.pool_listener = pool_listener self.server_listener = server_listener # Close the client explicitly to avoid having too many threads open. self.addCleanup(client.close) # Create session0 and session1. sessions = {} session_ids = {} for i in range(2): # Don't attempt to create sessions if they are not supported by # the running server version. if not client_context.sessions_enabled: break session_name = "session%d" % i opts = camel_to_snake_args(test["sessionOptions"][session_name]) if "default_transaction_options" in opts: txn_opts = self.parse_options(opts["default_transaction_options"]) txn_opts = client_session.TransactionOptions(**txn_opts) opts["default_transaction_options"] = txn_opts s = client.start_session(**dict(opts)) sessions[session_name] = s # Store lsid so we can access it after end_session, in check_events. session_ids[session_name] = s.session_id self.addCleanup(end_sessions, sessions) collection = client[database_name][collection_name] self.run_test_ops(sessions, collection, test) end_sessions(sessions) self.check_events(test, listener, session_ids) # Disable fail points. if "failPoint" in test: fp = test["failPoint"] self.set_fail_point({"configureFailPoint": fp["configureFailPoint"], "mode": "off"}) # Assert final state is expected. outcome = test["outcome"] expected_c = outcome.get("collection") if expected_c is not None: outcome_coll_name = self.get_outcome_coll_name(outcome, collection) # Read from the primary with local read concern to ensure causal # consistency. outcome_coll = client_context.client[collection.database.name].get_collection( outcome_coll_name, read_preference=ReadPreference.PRIMARY, read_concern=ReadConcern("local"), ) actual_data = list(outcome_coll.find(sort=[("_id", 1)])) # The expected data needs to be the left hand side here otherwise # CompareType(Binary) doesn't work. self.assertEqual(wrap_types(expected_c["data"]), actual_data) def expect_any_error(op): if isinstance(op, dict): return op.get("error") return False def expect_error_message(expected_result): if isinstance(expected_result, dict): return isinstance(expected_result["errorContains"], str) return False def expect_error_code(expected_result): if isinstance(expected_result, dict): return expected_result["errorCodeName"] return False def expect_error_labels_contain(expected_result): if isinstance(expected_result, dict): return expected_result["errorLabelsContain"] return False def expect_error_labels_omit(expected_result): if isinstance(expected_result, dict): return expected_result["errorLabelsOmit"] return False def expect_timeout_error(expected_result): if isinstance(expected_result, dict): return expected_result["isTimeoutError"] return False def expect_error(op): expected_result = op.get("result") return ( expect_any_error(op) or expect_error_message(expected_result) or expect_error_code(expected_result) or expect_error_labels_contain(expected_result) or expect_error_labels_omit(expected_result) or expect_timeout_error(expected_result) ) def end_sessions(sessions): for s in sessions.values(): # Aborts the transaction if it's open. s.end_session() def decode_raw(val): """Decode RawBSONDocuments in the given container.""" if isinstance(val, (list, abc.Mapping)): return decode(encode({"v": val}))["v"] return val TYPES = { "binData": Binary, "long": Int64, "int": int, "string": str, "objectId": ObjectId, "object": dict, "array": list, } def wrap_types(val): """Support $$type assertion in command results.""" if isinstance(val, list): return [wrap_types(v) for v in val] if isinstance(val, abc.Mapping): typ = val.get("$$type") if typ: if isinstance(typ, str): types = TYPES[typ] else: types = tuple(TYPES[t] for t in typ) return CompareType(types) d = {} for key in val: d[key] = wrap_types(val[key]) return d return val mongodb-mongo-python-driver-509e9b7/test/version.py000066400000000000000000000057131462766011000224610ustar00rootroot00000000000000# Copyright 2009-2015 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. """Some tools for running tests based on MongoDB server version.""" from __future__ import annotations class Version(tuple): def __new__(cls, *version): padded_version = cls._padded(version, 4) return super().__new__(cls, tuple(padded_version)) @classmethod def _padded(cls, iter, length, padding=0): l = list(iter) if len(l) < length: for _ in range(length - len(l)): l.append(padding) return l @classmethod def from_string(cls, version_string): mod = 0 bump_patch_level = False if version_string.endswith("+"): version_string = version_string[0:-1] mod = 1 elif version_string.endswith("-pre-"): version_string = version_string[0:-5] mod = -1 elif version_string.endswith("-"): version_string = version_string[0:-1] mod = -1 # Deal with '-rcX' substrings if "-rc" in version_string: version_string = version_string[0 : version_string.find("-rc")] mod = -1 # Deal with git describe generated substrings elif "-" in version_string: version_string = version_string[0 : version_string.find("-")] mod = -1 bump_patch_level = True version = [int(part) for part in version_string.split(".")] version = cls._padded(version, 3) # Make from_string and from_version_array agree. For example: # MongoDB Enterprise > db.runCommand('buildInfo').versionArray # [ 3, 2, 1, -100 ] # MongoDB Enterprise > db.runCommand('buildInfo').version # 3.2.0-97-g1ef94fe if bump_patch_level: version[-1] += 1 version.append(mod) return Version(*version) @classmethod def from_version_array(cls, version_array): version = list(version_array) if version[-1] < 0: version[-1] = -1 version = cls._padded(version, 3) return Version(*version) @classmethod def from_client(cls, client): info = client.server_info() if "versionArray" in info: return cls.from_version_array(info["versionArray"]) return cls.from_string(info["version"]) def at_least(self, *other_version): return self >= Version(*other_version) def __str__(self): return ".".join(map(str, self)) mongodb-mongo-python-driver-509e9b7/test/versioned-api/000077500000000000000000000000001462766011000231615ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/versioned-api/crud-api-version-1-strict.json000066400000000000000000000643071462766011000307210ustar00rootroot00000000000000{ "description": "CRUD Api Version 1 (strict)", "schemaVersion": "1.4", "runOnRequirements": [ { "minServerVersion": "4.9" } ], "createEntities": [ { "client": { "id": "client", "observeEvents": [ "commandStartedEvent" ], "serverApi": { "version": "1", "strict": true } } }, { "database": { "id": "database", "client": "client", "databaseName": "versioned-api-tests" } }, { "database": { "id": "adminDatabase", "client": "client", "databaseName": "admin" } }, { "collection": { "id": "collection", "database": "database", "collectionName": "test" } } ], "_yamlAnchors": { "versions": [ { "apiVersion": "1", "apiStrict": true, "apiDeprecationErrors": { "$$unsetOrMatches": false } } ] }, "initialData": [ { "collectionName": "test", "databaseName": "versioned-api-tests", "documents": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 22 }, { "_id": 3, "x": 33 }, { "_id": 4, "x": 44 }, { "_id": 5, "x": 55 } ] } ], "tests": [ { "description": "aggregate on collection appends declared API version", "operations": [ { "name": "aggregate", "object": "collection", "arguments": { "pipeline": [ { "$sort": { "x": 1 } }, { "$match": { "_id": { "$gt": 1 } } } ] } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "command": { "aggregate": "test", "pipeline": [ { "$sort": { "x": 1 } }, { "$match": { "_id": { "$gt": 1 } } } ], "apiVersion": "1", "apiStrict": true, "apiDeprecationErrors": { "$$unsetOrMatches": false } } } } ] } ] }, { "description": "aggregate on database appends declared API version", "runOnRequirements": [ { "serverless": "forbid" } ], "operations": [ { "name": "aggregate", "object": "adminDatabase", "arguments": { "pipeline": [ { "$listLocalSessions": {} }, { "$limit": 1 } ] }, "expectError": { "errorCodeName": "APIStrictError" } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "command": { "aggregate": 1, "pipeline": [ { "$listLocalSessions": {} }, { "$limit": 1 } ], "apiVersion": "1", "apiStrict": true, "apiDeprecationErrors": { "$$unsetOrMatches": false } } } } ] } ] }, { "description": "bulkWrite appends declared API version", "operations": [ { "name": "bulkWrite", "object": "collection", "arguments": { "requests": [ { "insertOne": { "document": { "_id": 6, "x": 66 } } }, { "updateOne": { "filter": { "_id": 2 }, "update": { "$inc": { "x": 1 } } } }, { "deleteMany": { "filter": { "x": { "$nin": [ 24, 34 ] } } } }, { "updateMany": { "filter": { "_id": { "$gt": 1 } }, "update": { "$inc": { "x": 1 } } } }, { "deleteOne": { "filter": { "_id": 7 } } }, { "replaceOne": { "filter": { "_id": 4 }, "replacement": { "_id": 4, "x": 44 }, "upsert": true } } ], "ordered": true } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "command": { "insert": "test", "documents": [ { "_id": 6, "x": 66 } ], "apiVersion": "1", "apiStrict": true, "apiDeprecationErrors": { "$$unsetOrMatches": false } } } }, { "commandStartedEvent": { "command": { "update": "test", "updates": [ { "q": { "_id": 2 }, "u": { "$inc": { "x": 1 } }, "multi": { "$$unsetOrMatches": false }, "upsert": { "$$unsetOrMatches": false } } ], "apiVersion": "1", "apiStrict": true, "apiDeprecationErrors": { "$$unsetOrMatches": false } } } }, { "commandStartedEvent": { "command": { "delete": "test", "deletes": [ { "q": { "x": { "$nin": [ 24, 34 ] } }, "limit": 0 } ], "apiVersion": "1", "apiStrict": true, "apiDeprecationErrors": { "$$unsetOrMatches": false } } } }, { "commandStartedEvent": { "command": { "update": "test", "updates": [ { "q": { "_id": { "$gt": 1 } }, "u": { "$inc": { "x": 1 } }, "multi": true, "upsert": { "$$unsetOrMatches": false } } ], "apiVersion": "1", "apiStrict": true, "apiDeprecationErrors": { "$$unsetOrMatches": false } } } }, { "commandStartedEvent": { "command": { "delete": "test", "deletes": [ { "q": { "_id": 7 }, "limit": 1 } ], "apiVersion": "1", "apiStrict": true, "apiDeprecationErrors": { "$$unsetOrMatches": false } } } }, { "commandStartedEvent": { "command": { "update": "test", "updates": [ { "q": { "_id": 4 }, "u": { "_id": 4, "x": 44 }, "multi": { "$$unsetOrMatches": false }, "upsert": true } ], "apiVersion": "1", "apiStrict": true, "apiDeprecationErrors": { "$$unsetOrMatches": false } } } } ] } ] }, { "description": "countDocuments appends declared API version", "operations": [ { "name": "countDocuments", "object": "collection", "arguments": { "filter": { "x": { "$gt": 11 } } } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "command": { "aggregate": "test", "pipeline": [ { "$match": { "x": { "$gt": 11 } } }, { "$group": { "_id": 1, "n": { "$sum": 1 } } } ], "apiVersion": "1", "apiStrict": true, "apiDeprecationErrors": { "$$unsetOrMatches": false } } } } ] } ] }, { "description": "deleteMany appends declared API version", "operations": [ { "name": "deleteMany", "object": "collection", "arguments": { "filter": { "x": { "$nin": [ 24, 34 ] } } } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "command": { "delete": "test", "deletes": [ { "q": { "x": { "$nin": [ 24, 34 ] } }, "limit": 0 } ], "apiVersion": "1", "apiStrict": true, "apiDeprecationErrors": { "$$unsetOrMatches": false } } } } ] } ] }, { "description": "deleteOne appends declared API version", "operations": [ { "name": "deleteOne", "object": "collection", "arguments": { "filter": { "_id": 7 } } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "command": { "delete": "test", "deletes": [ { "q": { "_id": 7 }, "limit": 1 } ], "apiVersion": "1", "apiStrict": true, "apiDeprecationErrors": { "$$unsetOrMatches": false } } } } ] } ] }, { "description": "distinct appends declared API version", "operations": [ { "name": "distinct", "object": "collection", "arguments": { "fieldName": "x", "filter": {} }, "expectError": { "isError": true, "errorContains": "command distinct is not in API Version 1", "errorCodeName": "APIStrictError" } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "command": { "distinct": "test", "key": "x", "apiVersion": "1", "apiStrict": true, "apiDeprecationErrors": { "$$unsetOrMatches": false } } } } ] } ] }, { "description": "estimatedDocumentCount appends declared API version", "runOnRequirements": [ { "minServerVersion": "5.0.9", "maxServerVersion": "5.0.99" }, { "minServerVersion": "5.3.2" } ], "operations": [ { "name": "estimatedDocumentCount", "object": "collection", "arguments": {} } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "command": { "count": "test", "apiVersion": "1", "apiStrict": true, "apiDeprecationErrors": { "$$unsetOrMatches": false } } } } ] } ] }, { "description": "find and getMore append API version", "operations": [ { "name": "find", "object": "collection", "arguments": { "filter": {}, "sort": { "_id": 1 }, "batchSize": 3 }, "expectResult": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 22 }, { "_id": 3, "x": 33 }, { "_id": 4, "x": 44 }, { "_id": 5, "x": 55 } ] } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "command": { "find": "test", "apiVersion": "1", "apiStrict": true, "apiDeprecationErrors": { "$$unsetOrMatches": false } } } }, { "commandStartedEvent": { "command": { "getMore": { "$$type": [ "int", "long" ] }, "apiVersion": "1", "apiStrict": true, "apiDeprecationErrors": { "$$unsetOrMatches": false } } } } ] } ] }, { "description": "findOneAndDelete appends declared API version", "operations": [ { "name": "findOneAndDelete", "object": "collection", "arguments": { "filter": { "_id": 1 } } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "command": { "findAndModify": "test", "query": { "_id": 1 }, "remove": true, "apiVersion": "1", "apiStrict": true, "apiDeprecationErrors": { "$$unsetOrMatches": false } } } } ] } ] }, { "description": "findOneAndReplace appends declared API version", "operations": [ { "name": "findOneAndReplace", "object": "collection", "arguments": { "filter": { "_id": 1 }, "replacement": { "x": 33 } } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "command": { "findAndModify": "test", "query": { "_id": 1 }, "update": { "x": 33 }, "apiVersion": "1", "apiStrict": true, "apiDeprecationErrors": { "$$unsetOrMatches": false } } } } ] } ] }, { "description": "findOneAndUpdate appends declared API version", "operations": [ { "name": "findOneAndUpdate", "object": "collection", "arguments": { "filter": { "_id": 1 }, "update": { "$inc": { "x": 1 } } } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "command": { "findAndModify": "test", "query": { "_id": 1 }, "update": { "$inc": { "x": 1 } }, "apiVersion": "1", "apiStrict": true, "apiDeprecationErrors": { "$$unsetOrMatches": false } } } } ] } ] }, { "description": "insertMany appends declared API version", "operations": [ { "name": "insertMany", "object": "collection", "arguments": { "documents": [ { "_id": 6, "x": 66 }, { "_id": 7, "x": 77 } ] } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "command": { "insert": "test", "documents": [ { "_id": 6, "x": 66 }, { "_id": 7, "x": 77 } ], "apiVersion": "1", "apiStrict": true, "apiDeprecationErrors": { "$$unsetOrMatches": false } } } } ] } ] }, { "description": "insertOne appends declared API version", "operations": [ { "name": "insertOne", "object": "collection", "arguments": { "document": { "_id": 6, "x": 66 } } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "command": { "insert": "test", "documents": [ { "_id": 6, "x": 66 } ], "apiVersion": "1", "apiStrict": true, "apiDeprecationErrors": { "$$unsetOrMatches": false } } } } ] } ] }, { "description": "replaceOne appends declared API version", "operations": [ { "name": "replaceOne", "object": "collection", "arguments": { "filter": { "_id": 4 }, "replacement": { "_id": 4, "x": 44 }, "upsert": true } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "command": { "update": "test", "updates": [ { "q": { "_id": 4 }, "u": { "_id": 4, "x": 44 }, "multi": { "$$unsetOrMatches": false }, "upsert": true } ], "apiVersion": "1", "apiStrict": true, "apiDeprecationErrors": { "$$unsetOrMatches": false } } } } ] } ] }, { "description": "updateMany appends declared API version", "operations": [ { "name": "updateMany", "object": "collection", "arguments": { "filter": { "_id": { "$gt": 1 } }, "update": { "$inc": { "x": 1 } } } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "command": { "update": "test", "updates": [ { "q": { "_id": { "$gt": 1 } }, "u": { "$inc": { "x": 1 } }, "multi": true, "upsert": { "$$unsetOrMatches": false } } ], "apiVersion": "1", "apiStrict": true, "apiDeprecationErrors": { "$$unsetOrMatches": false } } } } ] } ] }, { "description": "updateOne appends declared API version", "operations": [ { "name": "updateOne", "object": "collection", "arguments": { "filter": { "_id": 2 }, "update": { "$inc": { "x": 1 } } } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "command": { "update": "test", "updates": [ { "q": { "_id": 2 }, "u": { "$inc": { "x": 1 } }, "multi": { "$$unsetOrMatches": false }, "upsert": { "$$unsetOrMatches": false } } ], "apiVersion": "1", "apiStrict": true, "apiDeprecationErrors": { "$$unsetOrMatches": false } } } } ] } ] } ] } mongodb-mongo-python-driver-509e9b7/test/versioned-api/crud-api-version-1.json000066400000000000000000000636671462766011000274230ustar00rootroot00000000000000{ "description": "CRUD Api Version 1", "schemaVersion": "1.4", "runOnRequirements": [ { "minServerVersion": "4.9" } ], "createEntities": [ { "client": { "id": "client", "observeEvents": [ "commandStartedEvent" ], "serverApi": { "version": "1", "deprecationErrors": true } } }, { "database": { "id": "database", "client": "client", "databaseName": "versioned-api-tests" } }, { "database": { "id": "adminDatabase", "client": "client", "databaseName": "admin" } }, { "collection": { "id": "collection", "database": "database", "collectionName": "test" } } ], "_yamlAnchors": { "versions": [ { "apiVersion": "1", "apiStrict": { "$$unsetOrMatches": false }, "apiDeprecationErrors": true } ] }, "initialData": [ { "collectionName": "test", "databaseName": "versioned-api-tests", "documents": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 22 }, { "_id": 3, "x": 33 }, { "_id": 4, "x": 44 }, { "_id": 5, "x": 55 } ] } ], "tests": [ { "description": "aggregate on collection appends declared API version", "operations": [ { "name": "aggregate", "object": "collection", "arguments": { "pipeline": [ { "$sort": { "x": 1 } }, { "$match": { "_id": { "$gt": 1 } } } ] } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "command": { "aggregate": "test", "pipeline": [ { "$sort": { "x": 1 } }, { "$match": { "_id": { "$gt": 1 } } } ], "apiVersion": "1", "apiStrict": { "$$unsetOrMatches": false }, "apiDeprecationErrors": true } } } ] } ] }, { "description": "aggregate on database appends declared API version", "runOnRequirements": [ { "serverless": "forbid" } ], "operations": [ { "name": "aggregate", "object": "adminDatabase", "arguments": { "pipeline": [ { "$listLocalSessions": {} }, { "$limit": 1 } ] } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "command": { "aggregate": 1, "pipeline": [ { "$listLocalSessions": {} }, { "$limit": 1 } ], "apiVersion": "1", "apiStrict": { "$$unsetOrMatches": false }, "apiDeprecationErrors": true } } } ] } ] }, { "description": "bulkWrite appends declared API version", "operations": [ { "name": "bulkWrite", "object": "collection", "arguments": { "requests": [ { "insertOne": { "document": { "_id": 6, "x": 66 } } }, { "updateOne": { "filter": { "_id": 2 }, "update": { "$inc": { "x": 1 } } } }, { "deleteMany": { "filter": { "x": { "$nin": [ 24, 34 ] } } } }, { "updateMany": { "filter": { "_id": { "$gt": 1 } }, "update": { "$inc": { "x": 1 } } } }, { "deleteOne": { "filter": { "_id": 7 } } }, { "replaceOne": { "filter": { "_id": 4 }, "replacement": { "_id": 4, "x": 44 }, "upsert": true } } ], "ordered": true } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "command": { "insert": "test", "documents": [ { "_id": 6, "x": 66 } ], "apiVersion": "1", "apiStrict": { "$$unsetOrMatches": false }, "apiDeprecationErrors": true } } }, { "commandStartedEvent": { "command": { "update": "test", "updates": [ { "q": { "_id": 2 }, "u": { "$inc": { "x": 1 } }, "multi": { "$$unsetOrMatches": false }, "upsert": { "$$unsetOrMatches": false } } ], "apiVersion": "1", "apiStrict": { "$$unsetOrMatches": false }, "apiDeprecationErrors": true } } }, { "commandStartedEvent": { "command": { "delete": "test", "deletes": [ { "q": { "x": { "$nin": [ 24, 34 ] } }, "limit": 0 } ], "apiVersion": "1", "apiStrict": { "$$unsetOrMatches": false }, "apiDeprecationErrors": true } } }, { "commandStartedEvent": { "command": { "update": "test", "updates": [ { "q": { "_id": { "$gt": 1 } }, "u": { "$inc": { "x": 1 } }, "multi": true, "upsert": { "$$unsetOrMatches": false } } ], "apiVersion": "1", "apiStrict": { "$$unsetOrMatches": false }, "apiDeprecationErrors": true } } }, { "commandStartedEvent": { "command": { "delete": "test", "deletes": [ { "q": { "_id": 7 }, "limit": 1 } ], "apiVersion": "1", "apiStrict": { "$$unsetOrMatches": false }, "apiDeprecationErrors": true } } }, { "commandStartedEvent": { "command": { "update": "test", "updates": [ { "q": { "_id": 4 }, "u": { "_id": 4, "x": 44 }, "multi": { "$$unsetOrMatches": false }, "upsert": true } ], "apiVersion": "1", "apiStrict": { "$$unsetOrMatches": false }, "apiDeprecationErrors": true } } } ] } ] }, { "description": "countDocuments appends declared API version", "operations": [ { "name": "countDocuments", "object": "collection", "arguments": { "filter": { "x": { "$gt": 11 } } } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "command": { "aggregate": "test", "pipeline": [ { "$match": { "x": { "$gt": 11 } } }, { "$group": { "_id": 1, "n": { "$sum": 1 } } } ], "apiVersion": "1", "apiStrict": { "$$unsetOrMatches": false }, "apiDeprecationErrors": true } } } ] } ] }, { "description": "deleteMany appends declared API version", "operations": [ { "name": "deleteMany", "object": "collection", "arguments": { "filter": { "x": { "$nin": [ 24, 34 ] } } } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "command": { "delete": "test", "deletes": [ { "q": { "x": { "$nin": [ 24, 34 ] } }, "limit": 0 } ], "apiVersion": "1", "apiStrict": { "$$unsetOrMatches": false }, "apiDeprecationErrors": true } } } ] } ] }, { "description": "deleteOne appends declared API version", "operations": [ { "name": "deleteOne", "object": "collection", "arguments": { "filter": { "_id": 7 } } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "command": { "delete": "test", "deletes": [ { "q": { "_id": 7 }, "limit": 1 } ], "apiVersion": "1", "apiStrict": { "$$unsetOrMatches": false }, "apiDeprecationErrors": true } } } ] } ] }, { "description": "distinct appends declared API version", "operations": [ { "name": "distinct", "object": "collection", "arguments": { "fieldName": "x", "filter": {} } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "command": { "distinct": "test", "key": "x", "apiVersion": "1", "apiStrict": { "$$unsetOrMatches": false }, "apiDeprecationErrors": true } } } ] } ] }, { "description": "estimatedDocumentCount appends declared API version", "runOnRequirements": [ { "minServerVersion": "5.0.9", "maxServerVersion": "5.0.99" }, { "minServerVersion": "5.3.2" } ], "operations": [ { "name": "estimatedDocumentCount", "object": "collection", "arguments": {} } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "command": { "count": "test", "apiVersion": "1", "apiStrict": { "$$unsetOrMatches": false }, "apiDeprecationErrors": true } } } ] } ] }, { "description": "find and getMore append API version", "operations": [ { "name": "find", "object": "collection", "arguments": { "filter": {}, "sort": { "_id": 1 }, "batchSize": 3 }, "expectResult": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 22 }, { "_id": 3, "x": 33 }, { "_id": 4, "x": 44 }, { "_id": 5, "x": 55 } ] } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "command": { "find": "test", "apiVersion": "1", "apiStrict": { "$$unsetOrMatches": false }, "apiDeprecationErrors": true } } }, { "commandStartedEvent": { "command": { "getMore": { "$$type": [ "int", "long" ] }, "apiVersion": "1", "apiStrict": { "$$unsetOrMatches": false }, "apiDeprecationErrors": true } } } ] } ] }, { "description": "findOneAndDelete appends declared API version", "operations": [ { "name": "findOneAndDelete", "object": "collection", "arguments": { "filter": { "_id": 1 } } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "command": { "findAndModify": "test", "query": { "_id": 1 }, "remove": true, "apiVersion": "1", "apiStrict": { "$$unsetOrMatches": false }, "apiDeprecationErrors": true } } } ] } ] }, { "description": "findOneAndReplace appends declared API version", "operations": [ { "name": "findOneAndReplace", "object": "collection", "arguments": { "filter": { "_id": 1 }, "replacement": { "x": 33 } } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "command": { "findAndModify": "test", "query": { "_id": 1 }, "update": { "x": 33 }, "apiVersion": "1", "apiStrict": { "$$unsetOrMatches": false }, "apiDeprecationErrors": true } } } ] } ] }, { "description": "findOneAndUpdate appends declared API version", "operations": [ { "name": "findOneAndUpdate", "object": "collection", "arguments": { "filter": { "_id": 1 }, "update": { "$inc": { "x": 1 } } } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "command": { "findAndModify": "test", "query": { "_id": 1 }, "update": { "$inc": { "x": 1 } }, "apiVersion": "1", "apiStrict": { "$$unsetOrMatches": false }, "apiDeprecationErrors": true } } } ] } ] }, { "description": "insertMany appends declared API version", "operations": [ { "name": "insertMany", "object": "collection", "arguments": { "documents": [ { "_id": 6, "x": 66 }, { "_id": 7, "x": 77 } ] } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "command": { "insert": "test", "documents": [ { "_id": 6, "x": 66 }, { "_id": 7, "x": 77 } ], "apiVersion": "1", "apiStrict": { "$$unsetOrMatches": false }, "apiDeprecationErrors": true } } } ] } ] }, { "description": "insertOne appends declared API version", "operations": [ { "name": "insertOne", "object": "collection", "arguments": { "document": { "_id": 6, "x": 66 } } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "command": { "insert": "test", "documents": [ { "_id": 6, "x": 66 } ], "apiVersion": "1", "apiStrict": { "$$unsetOrMatches": false }, "apiDeprecationErrors": true } } } ] } ] }, { "description": "replaceOne appends declared API version", "operations": [ { "name": "replaceOne", "object": "collection", "arguments": { "filter": { "_id": 4 }, "replacement": { "_id": 4, "x": 44 }, "upsert": true } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "command": { "update": "test", "updates": [ { "q": { "_id": 4 }, "u": { "_id": 4, "x": 44 }, "multi": { "$$unsetOrMatches": false }, "upsert": true } ], "apiVersion": "1", "apiStrict": { "$$unsetOrMatches": false }, "apiDeprecationErrors": true } } } ] } ] }, { "description": "updateMany appends declared API version", "operations": [ { "name": "updateMany", "object": "collection", "arguments": { "filter": { "_id": { "$gt": 1 } }, "update": { "$inc": { "x": 1 } } } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "command": { "update": "test", "updates": [ { "q": { "_id": { "$gt": 1 } }, "u": { "$inc": { "x": 1 } }, "multi": true, "upsert": { "$$unsetOrMatches": false } } ], "apiVersion": "1", "apiStrict": { "$$unsetOrMatches": false }, "apiDeprecationErrors": true } } } ] } ] }, { "description": "updateOne appends declared API version", "operations": [ { "name": "updateOne", "object": "collection", "arguments": { "filter": { "_id": 2 }, "update": { "$inc": { "x": 1 } } } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "command": { "update": "test", "updates": [ { "q": { "_id": 2 }, "u": { "$inc": { "x": 1 } }, "multi": { "$$unsetOrMatches": false }, "upsert": { "$$unsetOrMatches": false } } ], "apiVersion": "1", "apiStrict": { "$$unsetOrMatches": false }, "apiDeprecationErrors": true } } } ] } ] } ] } runcommand-helper-no-api-version-declared.json000066400000000000000000000056631462766011000340340ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/test/versioned-api{ "description": "RunCommand helper: No API version declared", "schemaVersion": "1.4", "runOnRequirements": [ { "minServerVersion": "4.9", "serverParameters": { "requireApiVersion": false } } ], "createEntities": [ { "client": { "id": "client", "observeEvents": [ "commandStartedEvent" ] } }, { "database": { "id": "database", "client": "client", "databaseName": "versioned-api-tests" } } ], "tests": [ { "description": "runCommand does not inspect or change the command document", "runOnRequirements": [ { "serverless": "forbid" } ], "operations": [ { "name": "runCommand", "object": "database", "arguments": { "commandName": "ping", "command": { "ping": 1, "apiVersion": "server_will_never_support_this_api_version" } }, "expectError": { "isError": true, "isClientError": false } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "command": { "ping": 1, "apiVersion": "server_will_never_support_this_api_version", "apiStrict": { "$$exists": false }, "apiDeprecationErrors": { "$$exists": false } }, "commandName": "ping", "databaseName": "versioned-api-tests" } } ] } ] }, { "description": "runCommand does not prevent sending invalid API version declarations", "runOnRequirements": [ { "serverless": "forbid" } ], "operations": [ { "name": "runCommand", "object": "database", "arguments": { "commandName": "ping", "command": { "ping": 1, "apiStrict": true } }, "expectError": { "isError": true, "isClientError": false } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "command": { "ping": 1, "apiVersion": { "$$exists": false }, "apiStrict": true, "apiDeprecationErrors": { "$$exists": false } }, "commandName": "ping", "databaseName": "versioned-api-tests" } } ] } ] } ] } mongodb-mongo-python-driver-509e9b7/test/versioned-api/test-commands-deprecation-errors.json000066400000000000000000000033571462766011000324470ustar00rootroot00000000000000{ "description": "Test commands: deprecation errors", "schemaVersion": "1.1", "runOnRequirements": [ { "minServerVersion": "4.9", "serverParameters": { "enableTestCommands": true, "acceptApiVersion2": true, "requireApiVersion": false } } ], "createEntities": [ { "client": { "id": "client", "observeEvents": [ "commandStartedEvent" ] } }, { "database": { "id": "database", "client": "client", "databaseName": "versioned-api-tests" } } ], "tests": [ { "description": "Running a command that is deprecated raises a deprecation error", "operations": [ { "name": "runCommand", "object": "database", "arguments": { "commandName": "testDeprecationInVersion2", "command": { "testDeprecationInVersion2": 1, "apiVersion": "2", "apiDeprecationErrors": true } }, "expectError": { "isError": true, "errorContains": "command testDeprecationInVersion2 is deprecated in API Version 2", "errorCodeName": "APIDeprecationError" } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "command": { "testDeprecationInVersion2": 1, "apiVersion": "2", "apiStrict": { "$$exists": false }, "apiDeprecationErrors": true } } } ] } ] } ] } mongodb-mongo-python-driver-509e9b7/test/versioned-api/test-commands-strict-mode.json000066400000000000000000000032331462766011000310630ustar00rootroot00000000000000{ "description": "Test commands: strict mode", "schemaVersion": "1.4", "runOnRequirements": [ { "minServerVersion": "4.9", "serverParameters": { "enableTestCommands": true }, "serverless": "forbid" } ], "createEntities": [ { "client": { "id": "client", "observeEvents": [ "commandStartedEvent" ], "serverApi": { "version": "1", "strict": true } } }, { "database": { "id": "database", "client": "client", "databaseName": "versioned-api-tests" } } ], "tests": [ { "description": "Running a command that is not part of the versioned API results in an error", "operations": [ { "name": "runCommand", "object": "database", "arguments": { "commandName": "testVersion2", "command": { "testVersion2": 1 } }, "expectError": { "isError": true, "errorContains": "command testVersion2 is not in API Version 1", "errorCodeName": "APIStrictError" } } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "command": { "testVersion2": 1, "apiVersion": "1", "apiStrict": true, "apiDeprecationErrors": { "$$unsetOrMatches": false } } } } ] } ] } ] } mongodb-mongo-python-driver-509e9b7/test/versioned-api/transaction-handling.json000066400000000000000000000177621462766011000302000ustar00rootroot00000000000000{ "description": "Transaction handling", "schemaVersion": "1.3", "runOnRequirements": [ { "minServerVersion": "4.9", "topologies": [ "replicaset", "sharded-replicaset", "load-balanced" ] } ], "createEntities": [ { "client": { "id": "client", "observeEvents": [ "commandStartedEvent" ], "serverApi": { "version": "1" } } }, { "database": { "id": "database", "client": "client", "databaseName": "versioned-api-tests" } }, { "collection": { "id": "collection", "database": "database", "collectionName": "test" } }, { "session": { "id": "session", "client": "client" } } ], "_yamlAnchors": { "versions": [ { "apiVersion": "1", "apiStrict": { "$$unsetOrMatches": false }, "apiDeprecationErrors": { "$$unsetOrMatches": false } } ] }, "initialData": [ { "collectionName": "test", "databaseName": "versioned-api-tests", "documents": [ { "_id": 1, "x": 11 }, { "_id": 2, "x": 22 }, { "_id": 3, "x": 33 }, { "_id": 4, "x": 44 }, { "_id": 5, "x": 55 } ] } ], "tests": [ { "description": "All commands in a transaction declare an API version", "runOnRequirements": [ { "topologies": [ "replicaset", "sharded-replicaset", "load-balanced" ] } ], "operations": [ { "name": "startTransaction", "object": "session" }, { "name": "insertOne", "object": "collection", "arguments": { "session": "session", "document": { "_id": 6, "x": 66 } }, "expectResult": { "$$unsetOrMatches": { "insertedId": { "$$unsetOrMatches": 6 } } } }, { "name": "insertOne", "object": "collection", "arguments": { "session": "session", "document": { "_id": 7, "x": 77 } }, "expectResult": { "$$unsetOrMatches": { "insertedId": { "$$unsetOrMatches": 7 } } } }, { "name": "commitTransaction", "object": "session" } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "command": { "insert": "test", "documents": [ { "_id": 6, "x": 66 } ], "lsid": { "$$sessionLsid": "session" }, "startTransaction": true, "apiVersion": "1", "apiStrict": { "$$unsetOrMatches": false }, "apiDeprecationErrors": { "$$unsetOrMatches": false } } } }, { "commandStartedEvent": { "command": { "insert": "test", "documents": [ { "_id": 7, "x": 77 } ], "lsid": { "$$sessionLsid": "session" }, "apiVersion": "1", "apiStrict": { "$$unsetOrMatches": false }, "apiDeprecationErrors": { "$$unsetOrMatches": false } } } }, { "commandStartedEvent": { "command": { "commitTransaction": 1, "lsid": { "$$sessionLsid": "session" }, "apiVersion": "1", "apiStrict": { "$$unsetOrMatches": false }, "apiDeprecationErrors": { "$$unsetOrMatches": false } } } } ] } ] }, { "description": "abortTransaction includes an API version", "runOnRequirements": [ { "topologies": [ "replicaset", "sharded-replicaset", "load-balanced" ] } ], "operations": [ { "name": "startTransaction", "object": "session" }, { "name": "insertOne", "object": "collection", "arguments": { "session": "session", "document": { "_id": 6, "x": 66 } }, "expectResult": { "$$unsetOrMatches": { "insertedId": { "$$unsetOrMatches": 6 } } } }, { "name": "insertOne", "object": "collection", "arguments": { "session": "session", "document": { "_id": 7, "x": 77 } }, "expectResult": { "$$unsetOrMatches": { "insertedId": { "$$unsetOrMatches": 7 } } } }, { "name": "abortTransaction", "object": "session" } ], "expectEvents": [ { "client": "client", "events": [ { "commandStartedEvent": { "command": { "insert": "test", "documents": [ { "_id": 6, "x": 66 } ], "lsid": { "$$sessionLsid": "session" }, "startTransaction": true, "apiVersion": "1", "apiStrict": { "$$unsetOrMatches": false }, "apiDeprecationErrors": { "$$unsetOrMatches": false } } } }, { "commandStartedEvent": { "command": { "insert": "test", "documents": [ { "_id": 7, "x": 77 } ], "lsid": { "$$sessionLsid": "session" }, "apiVersion": "1", "apiStrict": { "$$unsetOrMatches": false }, "apiDeprecationErrors": { "$$unsetOrMatches": false } } } }, { "commandStartedEvent": { "command": { "abortTransaction": 1, "lsid": { "$$sessionLsid": "session" }, "apiVersion": "1", "apiStrict": { "$$unsetOrMatches": false }, "apiDeprecationErrors": { "$$unsetOrMatches": false } } } } ] } ] } ] } mongodb-mongo-python-driver-509e9b7/tools/000077500000000000000000000000001462766011000205755ustar00rootroot00000000000000mongodb-mongo-python-driver-509e9b7/tools/README.rst000066400000000000000000000001171462766011000222630ustar00rootroot00000000000000Tools ===== This directory contains tools for use with the ``pymongo`` module. mongodb-mongo-python-driver-509e9b7/tools/clean.py000066400000000000000000000024531462766011000222350ustar00rootroot00000000000000# Copyright 2009-2015 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. """Clean up script for build artifacts. Only really intended to be used by internal build scripts. """ from __future__ import annotations import sys from pathlib import Path try: Path("pymongo/_cmessage.so").unlink() Path("bson/_cbson.so").unlink() except BaseException: # noqa: S110 pass try: Path("pymongo/_cmessage.pyd").unlink() Path("bson/_cbson.pyd").unlink() except BaseException: # noqa: S110 pass try: from pymongo import _cmessage # type: ignore[attr-defined] # noqa: F401 sys.exit("could still import _cmessage") except ImportError: pass try: from bson import _cbson # type: ignore[attr-defined] # noqa: F401 sys.exit("could still import _cbson") except ImportError: pass mongodb-mongo-python-driver-509e9b7/tools/compare_import_time.py000066400000000000000000000021731462766011000252100ustar00rootroot00000000000000# Copyright 2024-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. from __future__ import annotations import sys base_sha = sys.argv[-1] head_sha = sys.argv[-2] def get_total_time(sha: str) -> int: with open(f"pymongo-{sha}.log") as fid: last_line = fid.readlines()[-1] return int(last_line.split()[4]) base_time = get_total_time(base_sha) curr_time = get_total_time(head_sha) # Check if we got 20% or more slower. change = int((curr_time - base_time) / base_time * 100) if change > 20: print(f"PyMongo import got {change} percent worse") sys.exit(1) print(f"Import time changed by {change} percent") mongodb-mongo-python-driver-509e9b7/tools/ensure_future_annotations_import.py000066400000000000000000000024771462766011000300630ustar00rootroot00000000000000# Copyright 2023-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. """Ensure that 'from __future__ import annotations' is used in all package files """ from __future__ import annotations import sys from pathlib import Path pattern = "from __future__ import annotations" missing = [] for dirname in ["pymongo", "bson", "gridfs"]: for path in Path(dirname).glob("*.py"): if Path(path).name in ["_version.py", "errors.py"]: continue found = False with open(path) as fid: for line in fid.readlines(): if line.strip() == pattern: found = True break if not found: missing.append(path) if missing: print(f"Missing '{pattern}' import in:") for item in missing: print(item) sys.exit(1) mongodb-mongo-python-driver-509e9b7/tools/fail_if_no_c.py000066400000000000000000000030711462766011000235370ustar00rootroot00000000000000# Copyright 2009-2015 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. """Fail if the C extension module doesn't exist. Only really intended to be used by internal build scripts. """ from __future__ import annotations import os import subprocess import sys from pathlib import Path sys.path[0:0] = [""] import bson # noqa: E402 import pymongo # noqa: E402 if not pymongo.has_c() or not bson.has_c(): sys.exit("could not load C extensions") if os.environ.get("ENSURE_UNIVERSAL2") == "1": parent_dir = Path(pymongo.__path__[0]).parent for pkg in ["pymongo", "bson", "grifs"]: for so_file in Path(f"{parent_dir}/{pkg}").glob("*.so"): print(f"Checking universal2 compatibility in {so_file}...") output = subprocess.check_output(["file", so_file]) # noqa: S603, S607 if "arm64" not in output.decode("utf-8"): sys.exit("Universal wheel was not compiled with arm64 support") if "x86_64" not in output.decode("utf-8"): sys.exit("Universal wheel was not compiled with x86_64 support") mongodb-mongo-python-driver-509e9b7/tools/ocsptest.py000066400000000000000000000037741462766011000230260ustar00rootroot00000000000000# Copyright 2020-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. from __future__ import annotations import argparse import logging import socket from pymongo.pyopenssl_context import SSLContext from pymongo.ssl_support import get_ssl_context # Enable logs in this format: # 2020-06-08 23:49:35,982 DEBUG ocsp_support Peer did not staple an OCSP response FORMAT = "%(asctime)s %(levelname)s %(module)s %(message)s" logging.basicConfig(format=FORMAT, level=logging.DEBUG) def check_ocsp(host: str, port: int, capath: str) -> None: ctx = get_ssl_context( None, # certfile None, # passphrase capath, # ca_certs None, # crlfile False, # allow_invalid_certificates False, # allow_invalid_hostnames False, ) # disable_ocsp_endpoint_check # Ensure we're using pyOpenSSL. assert isinstance(ctx, SSLContext) s = socket.socket() s.connect((host, port)) try: s = ctx.wrap_socket(s, server_hostname=host) # type: ignore[assignment] finally: s.close() def main() -> None: parser = argparse.ArgumentParser(description="Debug OCSP") parser.add_argument("--host", type=str, required=True, help="Host to connect to") parser.add_argument("-p", "--port", type=int, default=443, help="Port to connect to") parser.add_argument("--ca_file", type=str, default=None, help="CA file for host") args = parser.parse_args() check_ocsp(args.host, args.port, args.ca_file) if __name__ == "__main__": main() mongodb-mongo-python-driver-509e9b7/tox.ini000066400000000000000000000124541462766011000207560ustar00rootroot00000000000000[tox] requires = tox>=4 envlist = # Test using the system Python. test, # Test using the run-tests Evergreen script. test-eg, # Set up encryption files and services. setup-encryption, # Tear down encryption files and services. teardown-encryption, # Run pre-commit on all files. lint, # Run pre-commit on all files, including stages that require manual fixes. lint-manual, # Typecheck using mypy. typecheck-mypy, # Typecheck using pyright. typecheck-pyright, # Typecheck using pyright strict. typecheck-pyright-strict, # Typecheck all files. typecheck, # Build sphinx docs doc, # Server live sphinx docs doc-serve, # Test sphinx docs doc-test, # Linkcheck sphinx docs linkcheck # Check the sdist integrity. manifest labels = # Use labels and -m instead of -e so that tox -m