bson/testdata/change-streams/change-streams.yml
2025-03-17 20:58:26 +01:00

928 lines
28 KiB
YAML

description: "change-streams"
schemaVersion: "1.7"
runOnRequirements:
- minServerVersion: "3.6"
# TODO(DRIVERS-2323): Run all possible tests against sharded clusters once we know the
# cause of unexpected command monitoring events.
topologies: [ replicaset ]
serverless: forbid
createEntities:
- client:
id: &client0 client0
observeEvents: [ commandStartedEvent ]
ignoreCommandMonitoringEvents: [ killCursors ]
useMultipleMongoses: false
- client:
id: &globalClient globalClient
useMultipleMongoses: false
- database:
id: &database0 database0
client: *client0
databaseName: *database0
- collection:
id: &collection0 collection0
database: *database0
collectionName: *collection0
- database:
id: &database1 database1
client: *client0
databaseName: *database1
- collection:
id: &collection1 collection1
database: *database1
collectionName: *collection1
- database:
id: &globalDatabase0 globalDatabase0
client: *globalClient
databaseName: *database0
- collection:
id: &globalCollection0 globalCollection0
database: *globalDatabase0
collectionName: *collection0
- database:
id: &globalDatabase1 globalDatabase1
client: *globalClient
databaseName: *database1
- collection:
id: &globalCollection1 globalCollection1
database: *globalDatabase1
collectionName: *collection1
# Some tests run operations against db1.coll0 or db0.coll1
- collection:
id: &globalDb1Collection0 globalDb1Collection0
database: *globalDatabase1
collectionName: *collection0
- collection:
id: &globalDb0Collection1 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 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"
},
# It is up to the MongoDB server to decide how to report a change.
# This expectation is based on the current MongoDB server behavior.
# Alternatively, we could have used a set of possible expectations of which only one
# must be satisfied, but the unified test format does not support this.
"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: &comment0 { name: "test1" }
saveResultAsEntity: &changeStream0 changeStream0
expectEvents:
- client: *client0
events:
- commandStartedEvent:
command:
aggregate: *collection0
pipeline:
- $changeStream: {}
comment: *comment0
- description: "Test with document comment - pre 4.4"
runOnRequirements:
- maxServerVersion: "4.2.99"
operations:
- name: createChangeStream
object: *collection0
arguments:
pipeline: []
comment: &comment0 { name: "test1" }
expectError:
isClientError: false
expectEvents:
- client: *client0
events:
- commandStartedEvent:
command:
aggregate: *collection0
pipeline:
- $changeStream: {}
comment: *comment0
- description: "Test with string comment"
operations:
- name: createChangeStream
object: *collection0
arguments:
pipeline: []
comment: "comment"
saveResultAsEntity: &changeStream0 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: &commentDoc
key: "value"
saveResultAsEntity: &changeStream0 changeStream0
- name: insertOne
object: *collection0
arguments:
document: &new_document
_id: 1
a: 1
- name: iterateUntilDocumentOrError
object: *changeStream0
expectEvents:
- client: *client0
events:
- commandStartedEvent:
command:
aggregate: *collection0
pipeline:
- $changeStream: {}
comment: *commentDoc
- commandStartedEvent:
command:
insert: *collection0
documents:
- *new_document
- commandStartedEvent:
command:
getMore: { $$type: [ int, long ] }
collection: *collection0
comment: *commentDoc
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 changeStream0
- name: insertOne
object: *collection0
arguments:
document: &new_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:
- *new_document
- 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 changeStream0
- name: dropCollection
object: *database0
arguments:
collection: &collection1 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:
# using $project to simulate future changes to ChangeStreamDocument structure
pipeline: [ { $project: { operationType: "addedInFutureMongoDBVersion", ns: 1 } } ]
saveResultAsEntity: &changeStream0 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:
# using $project to simulate future changes to ChangeStreamDocument structure
pipeline: [ { $project: { operationType: 1, ns: 1, newField: "newFieldValue" } } ]
saveResultAsEntity: &changeStream0 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:
# using $project to simulate future changes to ChangeStreamDocument structure
pipeline: [ { $project: { operationType: "insert", "ns.viewOn": "db.coll" } } ]
saveResultAsEntity: &changeStream0 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:
# using $project to simulate future changes to ChangeStreamDocument structure
pipeline: [ { $project: { operationType: "insert", ns: { db: "$ns.db", coll: "$ns.coll", viewOn: "db.coll" } } } ]
saveResultAsEntity: &changeStream0 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"
# Server returns an error if _id is modified on versions 4.2 and higher
operations:
- name: createChangeStream
object: *collection0
arguments:
pipeline: [ { $project: { _id: 0 } } ]
saveResultAsEntity: &changeStream0 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 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 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 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 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 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 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 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 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 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 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
# Test that resume logic works correctly even after consecutive retryable failures of a getMore command,
# with no intervening events. This is ensured by setting the batch size of the change stream to 1,
- 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 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 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 }