The YAML and JSON files in this directory are platform-independent tests meant to exercise a driver's implementation of the CRUD specification. These tests utilize the Unified Test Format.
Several prose tests, which are not easily expressed in YAML, are also presented in this file. Those tests will need to be manually implemented by each driver.
Test that writeConcernError.errInfo
in a command response is propagated as WriteConcernError.details
(or equivalent)
in the driver.
Using a 4.0+ server, set the following failpoint:
{
"configureFailPoint": "failCommand",
"data": {
"failCommands": ["insert"],
"writeConcernError": {
"code": 100,
"codeName": "UnsatisfiableWriteConcern",
"errmsg": "Not enough data-bearing nodes",
"errInfo": {
"writeConcern": {
"w": 2,
"wtimeout": 0,
"provenance": "clientSupplied"
}
}
}
},
"mode": { "times": 1 }
}
Then, perform an insert operation and assert that a WriteConcernError occurs and that its details
property is both
accessible and matches the errInfo
object from the failpoint.
Test that writeErrors[].errInfo
in a command response is propagated as WriteError.details
(or equivalent) in the
driver.
Using a 5.0+ server, create a collection with document validation like so:
{
"create": "test",
"validator": {
"x": { $type: "string" }
}
}
Enable command monitoring to observe
CommandSucceededEvents. Then, insert an invalid document (e.g. {x: 1}
) and assert that a WriteError occurs, that its
code is 121
(i.e. DocumentValidationFailure), and that its details
property is accessible. Additionally, assert that
a CommandSucceededEvent was observed and that the writeErrors[0].errInfo
field in the response document matches the
WriteError's details
property.
3. MongoClient.bulkWrite
batch splits a writeModels
input with greater than maxWriteBatchSize
operations
Test that MongoClient.bulkWrite
properly handles writeModels
inputs containing a number of writes greater than
maxWriteBatchSize
.
This test must only be run on 8.0+ servers. This test must be skipped on Atlas Serverless.
Construct a MongoClient
(referred to as client
) with
command monitoring enabled to observe
CommandStartedEvents. Perform a hello
command using client
and record the maxWriteBatchSize
value contained in the
response. Then, construct the following write model (referred to as model
):
InsertOne: {
"namespace": "db.coll",
"document": { "a": "b" }
}
Construct a list of write models (referred to as models
) with model
repeated maxWriteBatchSize + 1
times. Execute
bulkWrite
on client
with models
. Assert that the bulk write succeeds and returns a BulkWriteResult
with an
insertedCount
value of maxWriteBatchSize + 1
.
Assert that two CommandStartedEvents (referred to as firstEvent
and secondEvent
) were observed for the bulkWrite
command. Assert that the length of firstEvent.command.ops
is maxWriteBatchSize
. Assert that the length of
secondEvent.command.ops
is 1. If the driver exposes operationId
s in its CommandStartedEvents, assert that
firstEvent.operationId
is equal to secondEvent.operationId
.
Test that MongoClient.bulkWrite
properly handles a writeModels
input which constructs an ops
array larger than
maxMessageSizeBytes
.
This test must only be run on 8.0+ servers. This test must be skipped on Atlas Serverless.
Construct a MongoClient
(referred to as client
) with
command monitoring enabled to observe
CommandStartedEvents. Perform a hello
command using client
and record the following values from the response:
maxBsonObjectSize
and maxMessageSizeBytes
. Then, construct the following document (referred to as document
):
{
"a": "b".repeat(maxBsonObjectSize - 500)
}
Construct the following write model (referred to as model
):
InsertOne: {
"namespace": "db.coll",
"document": document
}
Use the following calculation to determine the number of inserts that should be provided to MongoClient.bulkWrite
:
maxMessageSizeBytes / maxBsonObjectSize + 1
(referred to as numModels
). This number ensures that the inserts
provided to MongoClient.bulkWrite
will require multiple bulkWrite
commands to be sent to the server.
Construct as list of write models (referred to as models
) with model
repeated numModels
times. Then execute
bulkWrite
on client
with models
. Assert that the bulk write succeeds and returns a BulkWriteResult
with an
insertedCount
value of numModels
.
Assert that two CommandStartedEvents (referred to as firstEvent
and secondEvent
) were observed. Assert that the
length of firstEvent.command.ops
is numModels - 1
. Assert that the length of secondEvent.command.ops
is 1. If the
driver exposes operationId
s in its CommandStartedEvents, assert that firstEvent.operationId
is equal to
secondEvent.operationId
.
Test that MongoClient.bulkWrite
properly collects and reports writeConcernError
s returned in separate batches.
This test must only be run on 8.0+ servers. This test must be skipped on Atlas Serverless.
Construct a MongoClient
(referred to as client
) with retryWrites: false
configured and
command monitoring enabled to observe
CommandStartedEvents. Perform a hello
command using client
and record the maxWriteBatchSize
value contained in the
response. Then, configure the following fail point with client
:
{
"configureFailPoint": "failCommand",
"mode": { "times": 2 },
"data": {
"failCommands": ["bulkWrite"],
"writeConcernError": {
"code": 91,
"errmsg": "Replication is being shut down"
}
}
}
Construct the following write model (referred to as model
):
InsertOne: {
"namespace": "db.coll",
"document": { "a": "b" }
}
Construct a list of write models (referred to as models
) with model
repeated maxWriteBatchSize + 1
times. Execute
bulkWrite
on client
with models
. Assert that the bulk write fails and returns a BulkWriteError
(referred to as
error
).
Assert that error.writeConcernErrors
has a length of 2.
Assert that error.partialResult
is populated. Assert that error.partialResult.insertedCount
is equal to
maxWriteBatchSize + 1
.
Assert that two CommandStartedEvents were observed for the bulkWrite
command.
Test that MongoClient.bulkWrite
handles individual write errors across batches for ordered and unordered bulk writes.
This test must only be run on 8.0+ servers. This test must be skipped on Atlas Serverless.
Construct a MongoClient
(referred to as client
) with
command monitoring enabled to observe
CommandStartedEvents. Perform a hello
command using client
and record the maxWriteBatchSize
value contained in the
response.
Construct a MongoCollection
(referred to as collection
) with the namespace "db.coll" (referred to as namespace
).
Drop collection
. Then, construct the following document (referred to as document
):
{
"_id": 1
}
Insert document
into collection
.
Create the following write model (referred to as model
):
InsertOne {
"namespace": namespace,
"document": document
}
Construct a list of write models (referred to as models
) with model
repeated maxWriteBatchSize + 1
times.
Test that an unordered bulk write collects WriteError
s across batches.
Execute bulkWrite
on client
with models
and ordered
set to false. Assert that the bulk write fails and returns a
BulkWriteError
(referred to as unorderedError
).
Assert that unorderedError.writeErrors
has a length of maxWriteBatchSize + 1
.
Assert that two CommandStartedEvents were observed for the bulkWrite
command.
Test that an ordered bulk write does not execute further batches when a WriteError
occurs.
Execute bulkWrite
on client
with models
and ordered
set to true. Assert that the bulk write fails and returns a
BulkWriteError
(referred to as orderedError
).
Assert that orderedError.writeErrors
has a length of 1.
Assert that one CommandStartedEvent was observed for the bulkWrite
command.
Test that MongoClient.bulkWrite
properly iterates the results cursor when getMore
is required.
This test must only be run on 8.0+ servers. This test must be skipped on Atlas Serverless.
Construct a MongoClient
(referred to as client
) with
command monitoring enabled to observe
CommandStartedEvents. Perform a hello
command using client
and record the maxBsonObjectSize
value from the
response.
Construct a MongoCollection
(referred to as collection
) with the namespace "db.coll" (referred to as namespace
).
Drop collection
. Then create the following list of write models (referred to as models
):
UpdateOne {
"namespace": namespace,
"filter": { "_id": "a".repeat(maxBsonObjectSize / 2) },
"update": { "$set": { "x": 1 } },
"upsert": true
},
UpdateOne {
"namespace": namespace,
"filter": { "_id": "b".repeat(maxBsonObjectSize / 2) },
"update": { "$set": { "x": 1 } },
"upsert": true
},
Execute bulkWrite
on client
with models
and verboseResults
set to true. Assert that the bulk write succeeds and
returns a BulkWriteResult
(referred to as result
).
Assert that result.upsertedCount
is equal to 2.
Assert that the length of result.updateResults
is equal to 2.
Assert that a CommandStartedEvent was observed for the getMore
command.
Test that MongoClient.bulkWrite
executed within a transaction properly iterates the results cursor when getMore
is
required.
This test must only be run on 8.0+ servers. This test must be skipped on Atlas Serverless. This test must not be run against standalone servers.
Construct a MongoClient
(referred to as client
) with
command monitoring enabled to observe
CommandStartedEvents. Perform a hello
command using client
and record the maxBsonObjectSize
value from the
response.
Construct a MongoCollection
(referred to as collection
) with the namespace "db.coll" (referred to as namespace
).
Drop collection
.
Start a session on client
(referred to as session
). Start a transaction on session
.
Create the following list of write models (referred to as models
):
UpdateOne {
"namespace": namespace,
"filter": { "_id": "a".repeat(maxBsonObjectSize / 2) },
"update": { "$set": { "x": 1 } },
"upsert": true
},
UpdateOne {
"namespace": namespace,
"filter": { "_id": "b".repeat(maxBsonObjectSize / 2) },
"update": { "$set": { "x": 1 } },
"upsert": true
},
Execute bulkWrite
on client
with models
, session
, and verboseResults
set to true. Assert that the bulk write
succeeds and returns a BulkWriteResult
(referred to as result
).
Assert that result.upsertedCount
is equal to 2.
Assert that the length of result.updateResults
is equal to 2.
Assert that a CommandStartedEvent was observed for the getMore
command.
Test that MongoClient.bulkWrite
properly handles a failure that occurs when attempting a getMore
.
This test must only be run on 8.0+ servers. This test must be skipped on Atlas Serverless.
Construct a MongoClient
(referred to as client
) with
command monitoring enabled to observe
CommandStartedEvents. Perform a hello
command using client
and record the maxBsonObjectSize
value from the
response. Then, configure the following fail point with client
:
{
"configureFailPoint": "failCommand",
"mode": { "times": 1 },
"data": {
"failCommands": ["getMore"],
"errorCode": 8
}
}
Construct a MongoCollection
(referred to as collection
) with the namespace "db.coll" (referred to as namespace
).
Drop collection
. Then create the following list of write models (referred to as models
):
UpdateOne {
"namespace": namespace,
"filter": { "_id": "a".repeat(maxBsonObjectSize / 2) },
"update": { "$set": { "x": 1 } },
"upsert": true
},
UpdateOne {
"namespace": namespace,
"filter": { "_id": "b".repeat(maxBsonObjectSize / 2) },
"update": { "$set": { "x": 1 } },
"upsert": true
},
Execute bulkWrite
on client
with models
and verboseResults
set to true. Assert that the bulk write fails and
returns a BulkWriteError
(referred to as bulkWriteError
).
Assert that bulkWriteError.error
is populated with an error (referred to as topLevelError
). Assert that
topLevelError.errorCode
is equal to 8.
Assert that bulkWriteError.partialResult
is populated with a result (referred to as partialResult
). Assert that
partialResult.upsertedCount
is equal to 2. Assert that the length of partialResult.updateResults
is equal to 1.
Assert that a CommandStartedEvent was observed for the getMore
command.
Assert that a CommandStartedEvent was observed for the killCursors
command.
Removed.
Removed.
Removed.
11. MongoClient.bulkWrite
batch splits when the addition of a new namespace exceeds the maximum message size
Test that MongoClient.bulkWrite
batch splits a bulk write when the addition of a new namespace to nsInfo
causes the
size of the message to exceed maxMessageSizeBytes - 1000
.
This test must only be run on 8.0+ servers. This test must be skipped on Atlas Serverless.
Repeat the following setup for each test case:
Construct a MongoClient
(referred to as client
) with
command monitoring enabled to observe
CommandStartedEvents. Perform a hello
command using client
and record the following values from the response:
maxBsonObjectSize
and maxMessageSizeBytes
.
Calculate the following values:
opsBytes = maxMessageSizeBytes - 1122
numModels = opsBytes / maxBsonObjectSize
remainderBytes = opsBytes % maxBsonObjectSize
Construct the following write model (referred to as firstModel
):
InsertOne {
"namespace": "db.coll",
"document": { "a": "b".repeat(maxBsonObjectSize - 57) }
}
Create a list of write models (referred to as models
) with firstModel
repeated numModels
times.
If remainderBytes
is greater than or equal to 217, add 1 to numModels
and append the following write model to
models
:
InsertOne {
"namespace": "db.coll",
"document": { "a": "b".repeat(remainderBytes - 57) }
}
Then perform the following two tests:
Create the following write model (referred to as sameNamespaceModel
):
InsertOne {
"namespace": "db.coll",
"document": { "a": "b" }
}
Append sameNamespaceModel
to models
.
Execute bulkWrite
on client
with models
. Assert that the bulk write succeeds and returns a BulkWriteResult
(referred to as result
).
Assert that result.insertedCount
is equal to numModels + 1
.
Assert that one CommandStartedEvent was observed for the bulkWrite
command (referred to as event
).
Assert that the length of event.command.ops
is numModels + 1
. Assert that the length of event.command.nsInfo
is 1.
Assert that the namespace contained in event.command.nsInfo
is "db.coll".
Construct the following namespace (referred to as namespace
):
"db." + "c".repeat(200)
Create the following write model (referred to as newNamespaceModel
):
InsertOne {
"namespace": namespace,
"document": { "a": "b" }
}
Append newNamespaceModel
to models
.
Execute bulkWrite
on client
with models
. Assert that the bulk write succeeds and returns a BulkWriteResult
(referred to as result
).
Assert that result.insertedCount
is equal to numModels + 1
.
Assert that two CommandStartedEvents were observed for the bulkWrite
command (referred to as firstEvent
and
secondEvent
).
Assert that the length of firstEvent.command.ops
is equal to numModels
. Assert that the length of
firstEvent.command.nsInfo
is equal to 1. Assert that the namespace contained in firstEvent.command.nsInfo
is
"db.coll".
Assert that the length of secondEvent.command.ops
is equal to 1. Assert that the length of
secondEvent.command.nsInfo
is equal to 1. Assert that the namespace contained in secondEvent.command.nsInfo
is
namespace
.
This information is not needed to implement this prose test, but is documented for future reference. This test is
designed to work if maxBsonObjectSize
or maxMessageSizeBytes
changes, but will need to be updated if a required
field is added to the bulkWrite
command or the insert
operation document, or if the overhead OP_MSG
allowance is
changed in the bulk write specification.
The command document for the bulkWrite
has the following structure and size:
{
"bulkWrite": 1,
"errorsOnly": true,
"ordered": true
}
// Size: 43 bytes
Each write model will create an ops
document with the following structure and size:
{
"insert": <0 | 1>,
"document": {
"_id": <object ID>,
"a": <string>
}
}
// Size: 57 bytes + <number of characters in string>
The ops
document for both newNamespaceModel
and sameNamespaceModel
has a string with one character, so it is a
total of 58 bytes.
The models using the "db.coll" namespace will create one nsInfo
document with the following structure and size:
{
"ns": "db.coll"
}
// Size: 21 bytes
newNamespaceModel
will create an nsInfo
document with the following structure and size:
{
"ns": "db.<c repeated 200 times>"
}
// Size: 217 bytes
We need to fill up the rest of the message with bytes such that another ops
document will fit, but another nsInfo
entry will not. The following calculations are used:
# 1000 is the OP_MSG overhead required in the spec
maxBulkWriteBytes = maxMessageSizeBytes - 1000
# bulkWrite command + first namespace entry
existingMessageBytes = 43 + 21
# Space to fit the last model's ops entry
lastModelBytes = 58
remainingBulkWriteBytes = maxBulkWriteBytes - existingMessageBytes - lastModelBytes
# With the actual numbers plugged in
remainingBulkWriteBytes = maxMessageSizeBytes - 1122
Test that MongoClient.bulkWrite
returns an error if an operation provided exceeds maxMessageSizeBytes
such that an
empty ops
payload would be sent.
This test must only be run on 8.0+ servers. This test must be skipped on Atlas Serverless. This test may be skipped by drivers that are not able to construct arbitrarily large documents.
Construct a MongoClient
(referred to as client
). Perform a hello
command using client
and record the
maxMessageSizeBytes
value contained in the response.
Construct the following write model (referred to as largeDocumentModel
):
InsertOne {
"namespace": "db.coll",
"document": { "a": "b".repeat(maxMessageSizeBytes) }
}
Execute bulkWrite
on client
with largeDocumentModel
. Assert that an error (referred to as error
) is returned.
Assert that error
is a client error.
Construct the following namespace (referred to as namespace
):
"db." + "c".repeat(maxMessageSizeBytes)
Construct the following write model (referred to as largeNamespaceModel
):
InsertOne {
"namespace": namespace,
"document": { "a": "b" }
}
Execute bulkWrite
on client
with largeNamespaceModel
. Assert that an error (referred to as error
) is returned.
Assert that error
is a client error.
This test is expected to be removed when DRIVERS-2888 is resolved.
Test that MongoClient.bulkWrite
returns an error if the client has auto-encryption configured.
This test must only be run on 8.0+ servers. This test must be skipped on Atlas Serverless.
Construct a MongoClient
(referred to as client
) configured with the following AutoEncryptionOpts
:
AutoEncryptionOpts {
"keyVaultNamespace": "db.coll",
"kmsProviders": {
"aws": {
"accessKeyId": "foo",
"secretAccessKey": "bar"
}
}
}
Construct the following write model (referred to as model
):
InsertOne {
"namespace": "db.coll",
"document": { "a": "b" }
}
Execute bulkWrite
on client
with model
. Assert that an error (referred to as error
) is returned. Assert that
error
is a client error containing the message: "bulkWrite does not currently support automatic encryption".
Drivers that provide multiple APIs to specify explain should ensure this test is run at least once with each distinct
API. For example, the Node driver runs this test with option API (collection.find({}, { explain: ... })
) and the
fluent API (collection.find({}).explain(...)
).
Create a MongoClient with command monitoring enabled (referred to as client
).
Create a collection, referred to as collection
, with the namespace explain-test.collection
.
Run an explained find on collection
. The find will have the query predicate { name: 'john doe' }
. Specify a
maxTimeMS value of 2000ms for the explain
.
Obtain the command started event for the explain. Confirm that the top-level explain command should has a maxTimeMS
value of 2000
.
This test must only be run on 8.0+ servers. This test must be skipped on Atlas Serverless.
If testing with a sharded cluster, only connect to one mongos. This is intended to ensure the countDocuments
operation
uses the same connection as the bulkWrite
to get the correct connection count. (See
DRIVERS-2921).
Construct a MongoClient
(referred to as client
) with
command monitoring enabled to observe
CommandStartedEvents. Perform a hello
command using client
and record the maxBsonObjectSize
and
maxMessageSizeBytes
values in the response.
Construct a MongoCollection
(referred to as coll
) for the collection "db.coll". Drop coll
.
Use the create
command to create "db.coll" to workaround SERVER-95537.
Construct the following write model (referred to as model
):
InsertOne: {
"namespace": "db.coll",
"document": { "a": "b".repeat(maxBsonObjectSize - 500) }
}
Construct a list of write models (referred to as models
) with model
repeated
maxMessageSizeBytes / maxBsonObjectSize + 1
times.
Call client.bulkWrite
with models
. Pass BulkWriteOptions
with ordered
set to false
and writeConcern
set to
an unacknowledged write concern. Assert no error occurred. Assert the result indicates the write was unacknowledged.
Assert that two CommandStartedEvents (referred to as firstEvent
and secondEvent
) were observed for the bulkWrite
command. Assert that the length of firstEvent.command.ops
is maxMessageSizeBytes / maxBsonObjectSize
. Assert that
the length of secondEvent.command.ops
is 1. If the driver exposes operationId
s in its CommandStartedEvents, assert
that firstEvent.operationId
is equal to secondEvent.operationId
. Assert both commands include
writeConcern: {w: 0}
.
To force completion of the w:0
writes, execute coll.countDocuments
and expect the returned count is
maxMessageSizeBytes / maxBsonObjectSize + 1
. This is intended to avoid incomplete writes interfering with other tests
that may use this collection.
Construct a MongoClient
(referred to as client
) with
command monitoring enabled to observe
CommandStartedEvents. For each of insertOne
, client bulkWrite
, and collection bulkWrite
, do the following:
- Execute the command with a document that does not contain an
_id
field. - If possible, capture the wire protocol message (referred to as
request
) of the command and assert that the first field ofrequest.documents[0]
is_id
. - Otherwise, capture the CommandStartedEvent (referred to as
event
) emitted by the command and assert that the first field ofevent.command.documents[0]
is_id
.