This document describes the tests that drivers MUST run to validate the behavior of the timeoutMS option. These tests are broken up into automated YAML/JSON tests and additional prose tests.
This directory contains a set of YAML and JSON spec tests. Drivers MUST run these as described in the "Unified Test
Runner" specification. Because the tests introduced in this specification are timing-based, there is a risk that some of
them may intermittently fail without any bugs being present in the driver. As a mitigation, drivers MAY execute these
tests in two new Evergreen tasks that use single-node replica sets: one with only authentication enabled and another
with both authentication and TLS enabled. Drivers that choose to do so SHOULD use the single-node-auth.json
and
single-node-auth-ssl.json
files in the drivers-evergreen-tools
repository to create these clusters.
There are some tests that cannot be expressed in the unified YAML/JSON format. For each of these tests, drivers MUST
create a MongoClient without the timeoutMS
option set (referred to as internalClient
). Any fail points set during a
test MUST be unset using internalClient
after the test has been executed. All MongoClient instances created for tests
MUST be configured with read/write concern majority
, read preference primary
, and command monitoring enabled to
listen for command_started
events.
This test MUST only run against standalones on server versions 4.4 and higher. The insertMany
call takes an
exceedingly long time on replicasets and sharded clusters. Drivers MAY adjust the timeouts used in this test to allow
for differing bulk encoding performance.
-
Using
internalClient
, drop thedb.coll
collection. -
Using
internalClient
, set the following fail point:{ configureFailPoint: "failCommand", mode: { times: 2 }, data: { failCommands: ["insert"], blockConnection: true, blockTimeMS: 1010 } }
-
Create a new MongoClient (referred to as
client
) withtimeoutMS=2000
. -
Using
client
, insert 50 1-megabyte documents in a singleinsertMany
call.- Expect this to fail with a timeout error.
-
Verify that two
insert
commands were executed againstdb.coll
as part of theinsertMany
call.
This test MUST only be run against enterprise server versions 4.2 and higher.
- Launch a mongocryptd process on 23000.
- Create a MongoClient (referred to as
client
) using the URImongodb://localhost:23000/?timeoutMS=1000
. - Using
client
, execute the{ ping: 1 }
command against theadmin
database. - Verify via command monitoring that the
ping
command sent did not contain amaxTimeMS
field.
Each test under this category MUST only be run against server versions 4.4 and higher. In these tests, LOCAL_MASTERKEY
refers to the following base64:
Mng0NCt4ZHVUYUJCa1kxNkVyNUR1QURhZ2h2UzR2d2RrZzh0cFBwM3R6NmdWMDFBMUN3YkQ5aXRRMkhGRGdQV09wOGVNYUMxT2k3NjZKelhaQmRCZGJkTXVyZG9uSjFk
For each test, perform the following setup:
-
Using
internalClient
, drop and create thekeyvault.datakeys
collection. -
Create a MongoClient (referred to as
keyVaultClient
) withtimeoutMS=10
. -
Create a
ClientEncryption
object that wrapskeyVaultClient
(referred to asclientEncryption
). Configure this object withkeyVaultNamespace
set tokeyvault.datakeys
and the following KMS providers map:{ "local": { "key": <base64 decoding of LOCAL_MASTERKEY> } }
-
Using
internalClient
, set the following fail point:{ configureFailPoint: "failCommand", mode: { times: 1 }, data: { failCommands: ["insert"], blockConnection: true, blockTimeMS: 15 } }
-
Call
clientEncryption.createDataKey()
with thelocal
KMS provider.- Expect this to fail with a timeout error.
-
Verify that an
insert
command was executed against tokeyvault.datakeys
as part of thecreateDataKey
call.
-
Call
client_encryption.createDataKey()
with thelocal
KMS provider.- Expect a BSON binary with subtype 4 to be returned, referred to as
datakeyId
.
- Expect a BSON binary with subtype 4 to be returned, referred to as
-
Using
internalClient
, set the following fail point:{ configureFailPoint: "failCommand", mode: { times: 1 }, data: { failCommands: ["find"], blockConnection: true, blockTimeMS: 15 } }
-
Call
clientEncryption.encrypt()
with the valuehello
, the algorithmAEAD_AES_256_CBC_HMAC_SHA_512-Deterministic
, and the keyIddatakeyId
.- Expect this to fail with a timeout error.
-
Verify that a
find
command was executed against thekeyvault.datakeys
collection as part of theencrypt
call.
-
Call
clientEncryption.createDataKey()
with thelocal
KMS provider.- Expect this to return a BSON binary with subtype 4, referred to as
dataKeyId
.
- Expect this to return a BSON binary with subtype 4, referred to as
-
Call
clientEncryption.encrypt()
with the valuehello
, the algorithmAEAD_AES_256_CBC_HMAC_SHA_512-Deterministic
, and the keyIddataKeyId
.- Expect this to return a BSON binary with subtype 6, referred to as
encrypted
.
- Expect this to return a BSON binary with subtype 6, referred to as
-
Close and re-create the
keyVaultClient
andclientEncryption
objects. -
Using
internalClient
, set the following fail point:{ configureFailPoint: "failCommand", mode: { times: 1 }, data: { failCommands: ["find"], blockConnection: true, blockTimeMS: 15 } }
-
Call
clientEncryption.decrypt()
with the valueencrypted
.- Expect this to fail with a timeout error.
-
Verify that a
find
command was executed against thekeyvault.datakeys
collection as part of thedecrypt
call.
The tests in this section MUST only be run if the server version is 4.4 or higher and the URI has authentication fields (i.e. a username and password). Each test in this section requires drivers to create a MongoClient and then wait for some CMAP events to be published. Drivers MUST wait for up to 10 seconds and fail the test if the specified events are not published within that time.
-
Using
internalClient
, set the following fail point:{ configureFailPoint: "failCommand", mode: { times: 1 }, data: { failCommands: ["saslContinue"], blockConnection: true, blockTimeMS: 15, appName: "timeoutBackgroundPoolTest" } }
-
Create a MongoClient (referred to as
client
) configured with the following:minPoolSize
of 1timeoutMS
of 10appName
oftimeoutBackgroundPoolTest
- CMAP monitor configured to listen for
ConnectionCreatedEvent
andConnectionClosedEvent
events.
-
Wait for a
ConnectionCreatedEvent
and aConnectionClosedEvent
to be published.
-
Using
internalClient
, set the following fail point:{ configureFailPoint: "failCommand", mode: "alwaysOn", data: { failCommands: ["hello", "isMaster", "saslContinue"], blockConnection: true, blockTimeMS: 15, appName: "refreshTimeoutBackgroundPoolTest" } }
-
Create a MongoClient (referred to as
client
) configured with the following:minPoolSize
of 1timeoutMS
of 20appName
ofrefreshTimeoutBackgroundPoolTest
- CMAP monitor configured to listen for
ConnectionCreatedEvent
andConnectionReady
events.
-
Wait for a
ConnectionCreatedEvent
and aConnectionReady
to be published.
Tests in this section MUST only be run against server versions 4.4 and higher and only apply to drivers that have a
blocking method for cursor iteration that executes getMore
commands in a loop until a document is available or an
error occurs.
-
Using
internalClient
, drop thedb.coll
collection. -
Using
internalClient
, insert the document{ x: 1 }
intodb.coll
. -
Using
internalClient
, set the following fail point:{ configureFailPoint: "failCommand", mode: "alwaysOn", data: { failCommands: ["getMore"], blockConnection: true, blockTimeMS: 15 } }
-
Create a new MongoClient (referred to as
client
) withtimeoutMS=20
. -
Using
client
, create a tailable cursor ondb.coll
withcursorType=tailable
.- Expect this to succeed and return a cursor with a non-zero ID.
-
Call either a blocking or non-blocking iteration method on the cursor.
- Expect this to succeed and return the document
{ x: 1 }
without sending agetMore
command.
- Expect this to succeed and return the document
-
Call the blocking iteration method on the resulting cursor.
- Expect this to fail with a timeout error.
-
Verify that a
find
command and twogetMore
commands were executed against thedb.coll
collection during the test.
-
Using
internalClient
, drop thedb.coll
collection. -
Using
internalClient
, set the following fail point:{ configureFailPoint: "failCommand", mode: "alwaysOn", data: { failCommands: ["getMore"], blockConnection: true, blockTimeMS: 15 } }
-
Create a new MongoClient (referred to as
client
) withtimeoutMS=20
. -
Using
client
, use thewatch
helper to create a change stream againstdb.coll
.- Expect this to succeed and return a change stream with a non-zero ID.
-
Call the blocking iteration method on the resulting change stream.
- Expect this to fail with a timeout error.
-
Verify that an
aggregate
command and twogetMore
commands were executed against thedb.coll
collection during the test.
Tests in this section MUST only be run against server versions 4.4 and higher. Drivers SHOULD apply useMultipleMongoses=false as described in the unified test format when testing on sharded clusters to ensure failpoint are hit by only using one mongos.
-
Using
internalClient
, drop and re-create thedb.fs.files
anddb.fs.chunks
collections. -
Using
internalClient
, set the following fail point:{ configureFailPoint: "failCommand", mode: { times: 1 }, data: { failCommands: ["insert"], blockConnection: true, blockTimeMS: 200 } }
-
Create a new MongoClient (referred to as
client
) withtimeoutMS=150
. -
Using
client
, create a GridFS bucket (referred to asbucket
) that wraps thedb
database. -
Call
bucket.open_upload_stream()
with the filenamefilename
to create an upload stream (referred to asuploadStream
).- Expect this to succeed and return a non-null stream.
-
Using
uploadStream
, upload a single0x12
byte. -
Call
uploadStream.close()
to flush the stream and insert chunks.- Expect this to fail with a timeout error.
This test only applies to drivers that provide an API to abort a GridFS upload stream.
-
Using
internalClient
, drop and re-create thedb.fs.files
anddb.fs.chunks
collections. -
Using
internalClient
, set the following fail point:{ configureFailPoint: "failCommand", mode: { times: 1 }, data: { failCommands: ["delete"], blockConnection: true, blockTimeMS: 200 } }
-
Create a new MongoClient (referred to as
client
) withtimeoutMS=150
. -
Using
client
, create a GridFS bucket (referred to asbucket
) that wraps thedb
database withchunkSizeBytes=2
. -
Call
bucket.open_upload_stream()
with the filenamefilename
to create an upload stream (referred to asuploadStream
).- Expect this to succeed and return a non-null stream.
-
Using
uploadStream
, upload the bytes[0x01, 0x02, 0x03, 0x04]
. -
Call
uploadStream.abort()
.- Expect this to fail with a timeout error.
This test MUST only be run against server versions 4.4 and higher. Drivers SHOULD apply useMultipleMongoses=false as described in the unified test format when testing on sharded clusters to ensure failpoint are hit by only using one mongos.
-
Using
internalClient
, drop and re-create thedb.fs.files
anddb.fs.chunks
collections. -
Using
internalClient
, insert the following document into thedb.fs.files
collection:{ "_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": {} }
-
Create a new MongoClient (referred to as
client
) withtimeoutMS=150
. -
Using
client
, create a GridFS bucket (referred to asbucket
) that wraps thedb
database. -
Call
bucket.open_download_stream
with the id{ "$oid": "000000000000000000000005" }
to create a download stream (referred to asdownloadStream
).- Expect this to succeed and return a non-null stream.
-
Using
internalClient
, set the following fail point:{ configureFailPoint: "failCommand", mode: { times: 1 }, data: { failCommands: ["find"], blockConnection: true, blockTimeMS: 200 } }
-
Read from the
downloadStream
.- Expect this to fail with a timeout error.
-
Verify that two
find
commands were executed during the read: one againstdb.fs.files
and another againstdb.fs.chunks
.
- Create a MongoClient (referred to as
client
) with URImongodb://invalid/?serverSelectionTimeoutMS=10
. - Using
client
, execute the command{ ping: 1 }
against theadmin
database.- Expect this to fail with a server selection timeout error after no more than 15ms.
- Create a MongoClient (referred to as
client
) with URImongodb://invalid/?timeoutMS=10&serverSelectionTimeoutMS=20
. - Using
client
, run the command{ ping: 1 }
against theadmin
database.- Expect this to fail with a server selection timeout error after no more than 15ms.
- Create a MongoClient (referred to as
client
) with URImongodb://invalid/?timeoutMS=20&serverSelectionTimeoutMS=10
. - Using
client
, run the command{ ping: 1 }
against theadmin
database.- Expect this to fail with a server selection timeout error after no more than 15ms.
- Create a MongoClient (referred to as
client
) with URImongodb://invalid/?timeoutMS=0&serverSelectionTimeoutMS=10
. - Using
client
, run the command{ ping: 1 }
against theadmin
database.- Expect this to fail with a server selection timeout error after no more than 15ms.
This test MUST only be run if the server version is 4.4 or higher and the URI has authentication fields (i.e. a username and password).
-
Using
internalClient
, set the following fail point:{ configureFailPoint: failCommand, mode: { times: 1 }, data: { failCommands: ["saslContinue"], blockConnection: true, blockTimeMS: 15 } }
-
Create a new MongoClient (referred to as
client
) withtimeoutMS=10
andserverSelectionTimeoutMS=20
. -
Using
client
, insert the document{ x: 1 }
into collectiondb.coll
.- Expect this to fail with a timeout error after no more than 15ms.
This test MUST only be run if the server version is 4.4 or higher and the URI has authentication fields (i.e. a username and password).
-
Using
internalClient
, set the following fail point:{ configureFailPoint: failCommand, mode: { times: 1 }, data: { failCommands: ["saslContinue"], blockConnection: true, blockTimeMS: 15 } }
-
Create a new MongoClient (referred to as
client
) withtimeoutMS=20
andserverSelectionTimeoutMS=10
. -
Using
client
, insert the document{ x: 1 }
into collectiondb.coll
.- Expect this to fail with a timeout error after no more than 15ms.
This test MUST only be run against replica sets and sharded clusters with server version 4.4 or higher. It MUST be run
three times: once with the timeout specified via the MongoClient timeoutMS
option, once with the timeout specified via
the ClientSession defaultTimeoutMS
option, and once more with the timeout specified via the timeoutMS
option for the
endSession
operation. In all cases, the timeout MUST be set to 150 milliseconds.
-
Using
internalClient
, drop thedb.coll
collection. -
Using
internalClient
, set the following fail point:{ configureFailPoint: failCommand, mode: { times: 1 }, data: { failCommands: ["abortTransaction"], blockConnection: true, blockTimeMS: 200 } }
-
Create a new MongoClient (referred to as
client
) and an explicit ClientSession derived from that MongoClient (referred to assession
). -
Execute the following code:
coll = client.database("db").collection("coll") session.start_transaction() coll.insert_one({x: 1}, session=session)
-
Using
session
, executesession.end_session
- Expect this to fail with a timeout error after no more than 150ms.
Tests in this section MUST only run against replica sets and sharded clusters with server versions 4.4 or higher.
-
Using
internalClient
, drop thedb.coll
collection. -
Using
internalClient
, set the following fail point:{ configureFailPoint: failCommand, mode: { times: 2 }, data: { failCommands: ["insert", "abortTransaction"], blockConnection: true, blockTimeMS: 200 } }
-
Create a new MongoClient (referred to as
client
) configured withtimeoutMS=150
and an explicit ClientSession derived from that MongoClient (referred to assession
). -
Using
session
, execute awithTransaction
operation with the following callback:def callback() { coll = client.database("db").collection("coll") coll.insert_one({ _id: 1 }, session=session) }
-
Expect the previous
withTransaction
call to fail with a timeout error. -
Verify that the following events were published during the
withTransaction
call:command_started
andcommand_failed
events for aninsert
command.command_started
andcommand_failed
events for anabortTransaction
command.
This test MUST only run against server versions 8.0+. This test must be skipped on Atlas Serverless.
This test MUST only run against standalones. The bulkWrite call takes an exceedingly long time on replicasets and sharded clusters. Drivers MAY adjust the timeouts used in this test to allow for differing bulk encoding performance.
-
Using
internalClient
, drop thedb.coll
collection. -
Using
internalClient
, set the following fail point:{ configureFailPoint: "failCommand", mode: { times: 2 }, data: { failCommands: ["bulkWrite"], blockConnection: true, blockTimeMS: 1010 } }
-
Using
internalClient
, perform ahello
command and record themaxBsonObjectSize
andmaxMessageSizeBytes
values in the response. -
Create a new MongoClient (referred to as
client
) withtimeoutMS=2000
. -
Create a list of write models (referred to as
models
) with the following write model repeated (maxMessageSizeBytes / maxBsonObjectSize + 1
) times:InsertOne { "namespace": "db.coll", "document": { "a": "b".repeat(maxBsonObjectSize - 500) } }
-
Call
bulkWrite
onclient
withmodels
.- Expect this to fail with a timeout error.
-
Verify that two
bulkWrite
commands were executed as part of theMongoClient.bulkWrite
call.
The tests enumerated in this section could not be expressed in either spec or prose format. Drivers SHOULD implement these if it is possible to do so using the driver's existing test infrastructure.
- Operations should ignore
waitQueueTimeoutMS
iftimeoutMS
is also set. - If
timeoutMS
is set for an operation, the remainingtimeoutMS
value should apply to connection checkout after a server has been selected. - If
timeoutMS
is not set for an operation,waitQueueTimeoutMS
should apply to connection checkout after a server has been selected. - If a new connection is required to execute an operation,
min(remaining computedServerSelectionTimeout, connectTimeoutMS)
should apply to socket establishment. - For drivers that have control over OCSP behavior,
min(remaining computedServerSelectionTimeout, 5 seconds)
should apply to HTTP requests against OCSP responders. - The remaining
timeoutMS
value should apply to HTTP requests against KMS servers for CSFLE. - The remaining
timeoutMS
value should apply to commands sent to mongocryptd as part of automatic encryption. - When doing
minPoolSize
maintenance,connectTimeoutMS
is used as the timeout for socket establishment.