PYTHON-2547 Change estimated_document_count() to use $collStats instead of count on 4.9+ (#606)

Fix CRUD v1 aggregate $out change for
3f3a3c225d
PYTHON-2301 ValueError is an acceptable error for CRUD v2 error:true tests
This commit is contained in:
Shane Harvey 2021-04-28 15:02:06 -07:00 committed by GitHub
parent 61c6876872
commit 14ac9a3fde
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
21 changed files with 2477 additions and 132 deletions

View File

@ -1498,38 +1498,49 @@ class Collection(common.BaseObject):
return RawBatchCursor(self, *args, **kwargs)
def _count_cmd(self, session, sock_info, slave_ok, cmd, collation):
"""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(
sock_info,
cmd,
slave_ok,
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 _count(self, cmd, collation=None, session=None):
"""Internal count helper."""
# XXX: "ns missing" checks can be removed when we drop support for
# MongoDB 3.0, see SERVER-17051.
def _cmd(session, server, sock_info, slave_ok):
res = self._command(
sock_info,
cmd,
slave_ok,
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"])
return self._count_cmd(
session, sock_info, slave_ok, cmd, collation)
return self.__database.client._retryable_read(
_cmd, self._read_preference_for(session), session)
def _aggregate_one_result(
self, sock_info, slave_ok, cmd, collation=None, session=None):
self, sock_info, slave_ok, cmd, collation, session):
"""Internal helper to run an aggregate that returns a single result."""
result = self._command(
sock_info,
cmd,
slave_ok,
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
@ -1554,9 +1565,31 @@ class Collection(common.BaseObject):
if 'session' in kwargs:
raise ConfigurationError(
'estimated_document_count does not support sessions')
cmd = SON([('count', self.__name)])
cmd.update(kwargs)
return self._count(cmd)
def _cmd(session, server, sock_info, slave_ok):
if sock_info.max_wire_version >= 12:
# MongoDB 4.9+
pipeline = [
{'$collStats': {'count': {}}},
{'$group': {'_id': 1, 'n': {'$sum': '$count'}}},
]
cmd = SON([('aggregate', self.__name),
('pipeline', pipeline),
('cursor', {})])
cmd.update(kwargs)
result = self._aggregate_one_result(
sock_info, slave_ok, cmd, collation=None, session=session)
if not result:
return 0
return int(result['n'])
else:
# MongoDB < 4.9
cmd = SON([('count', self.__name)])
cmd.update(kwargs)
return self._count_cmd(None, sock_info, slave_ok, cmd, None)
return self.__database.client._retryable_read(
_cmd, self.read_preference, None)
def count_documents(self, filter, session=None, **kwargs):
"""Count the number of documents in this collection.

View File

@ -0,0 +1,562 @@
{
"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"
}
}
],
"initialData": [
{
"collectionName": "coll0",
"databaseName": "edc-tests",
"documents": [
{
"_id": 1,
"x": 11
},
{
"_id": 2,
"x": 22
},
{
"_id": 3,
"x": 33
}
]
}
],
"tests": [
{
"description": "estimatedDocumentCount uses $collStats on 4.9.0 or greater",
"runOnRequirements": [
{
"minServerVersion": "4.9.0"
}
],
"operations": [
{
"name": "estimatedDocumentCount",
"object": "collection0",
"expectResult": 3
}
],
"expectEvents": [
{
"client": "client0",
"events": [
{
"commandStartedEvent": {
"command": {
"aggregate": "coll0",
"pipeline": [
{
"$collStats": {
"count": {}
}
},
{
"$group": {
"_id": 1,
"n": {
"$sum": "$count"
}
}
}
]
},
"commandName": "aggregate",
"databaseName": "edc-tests"
}
}
]
}
]
},
{
"description": "estimatedDocumentCount with maxTimeMS on 4.9.0 or greater",
"runOnRequirements": [
{
"minServerVersion": "4.9.0"
}
],
"operations": [
{
"name": "estimatedDocumentCount",
"object": "collection0",
"arguments": {
"maxTimeMS": 6000
},
"expectResult": 3
}
],
"expectEvents": [
{
"client": "client0",
"events": [
{
"commandStartedEvent": {
"command": {
"aggregate": "coll0",
"pipeline": [
{
"$collStats": {
"count": {}
}
},
{
"$group": {
"_id": 1,
"n": {
"$sum": "$count"
}
}
}
],
"maxTimeMS": 6000
},
"commandName": "aggregate",
"databaseName": "edc-tests"
}
}
]
}
]
},
{
"description": "estimatedDocumentCount on non-existent collection on 4.9.0 or greater",
"runOnRequirements": [
{
"minServerVersion": "4.9.0"
}
],
"operations": [
{
"name": "estimatedDocumentCount",
"object": "collection1",
"expectResult": 0
}
],
"expectEvents": [
{
"client": "client0",
"events": [
{
"commandStartedEvent": {
"command": {
"aggregate": "coll1",
"pipeline": [
{
"$collStats": {
"count": {}
}
},
{
"$group": {
"_id": 1,
"n": {
"$sum": "$count"
}
}
}
]
},
"commandName": "aggregate",
"databaseName": "edc-tests"
}
}
]
}
]
},
{
"description": "estimatedDocumentCount errors correctly on 4.9.0 or greater--command error",
"runOnRequirements": [
{
"minServerVersion": "4.9.0"
}
],
"operations": [
{
"name": "failPoint",
"object": "testRunner",
"arguments": {
"client": "client0",
"failPoint": {
"configureFailPoint": "failCommand",
"mode": {
"times": 1
},
"data": {
"failCommands": [
"aggregate"
],
"errorCode": 8
}
}
}
},
{
"name": "estimatedDocumentCount",
"object": "collection0",
"expectError": {
"errorCode": 8
}
}
],
"expectEvents": [
{
"client": "client0",
"events": [
{
"commandStartedEvent": {
"command": {
"aggregate": "coll0",
"pipeline": [
{
"$collStats": {
"count": {}
}
},
{
"$group": {
"_id": 1,
"n": {
"$sum": "$count"
}
}
}
]
},
"commandName": "aggregate",
"databaseName": "edc-tests"
}
}
]
}
]
},
{
"description": "estimatedDocumentCount errors correctly on 4.9.0 or greater--socket error",
"runOnRequirements": [
{
"minServerVersion": "4.9.0"
}
],
"operations": [
{
"name": "failPoint",
"object": "testRunner",
"arguments": {
"client": "client0",
"failPoint": {
"configureFailPoint": "failCommand",
"mode": {
"times": 1
},
"data": {
"failCommands": [
"aggregate"
],
"closeConnection": true
}
}
}
},
{
"name": "estimatedDocumentCount",
"object": "collection0",
"expectError": {
"isError": true
}
}
],
"expectEvents": [
{
"client": "client0",
"events": [
{
"commandStartedEvent": {
"command": {
"aggregate": "coll0",
"pipeline": [
{
"$collStats": {
"count": {}
}
},
{
"$group": {
"_id": 1,
"n": {
"$sum": "$count"
}
}
}
]
},
"commandName": "aggregate",
"databaseName": "edc-tests"
}
}
]
}
]
},
{
"description": "estimatedDocumentCount uses count on less than 4.9.0",
"runOnRequirements": [
{
"maxServerVersion": "4.8.99"
}
],
"operations": [
{
"name": "estimatedDocumentCount",
"object": "collection0",
"expectResult": 3
}
],
"expectEvents": [
{
"client": "client0",
"events": [
{
"commandStartedEvent": {
"command": {
"count": "coll0"
},
"commandName": "count",
"databaseName": "edc-tests"
}
}
]
}
]
},
{
"description": "estimatedDocumentCount with maxTimeMS on less than 4.9.0",
"runOnRequirements": [
{
"maxServerVersion": "4.8.99"
}
],
"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 on less than 4.9.0",
"runOnRequirements": [
{
"maxServerVersion": "4.8.99"
}
],
"operations": [
{
"name": "estimatedDocumentCount",
"object": "collection1",
"expectResult": 0
}
],
"expectEvents": [
{
"client": "client0",
"events": [
{
"commandStartedEvent": {
"command": {
"count": "coll1"
},
"commandName": "count",
"databaseName": "edc-tests"
}
}
]
}
]
},
{
"description": "estimatedDocumentCount errors correctly on less than 4.9.0--command error",
"runOnRequirements": [
{
"minServerVersion": "4.0.0",
"maxServerVersion": "4.8.99",
"topologies": [
"single",
"replicaset"
]
},
{
"minServerVersion": "4.2.0",
"maxServerVersion": "4.8.99",
"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 on less than 4.9.0--socket error",
"runOnRequirements": [
{
"minServerVersion": "4.0.0",
"maxServerVersion": "4.8.99",
"topologies": [
"single",
"replicaset"
]
},
{
"minServerVersion": "4.2.0",
"maxServerVersion": "4.8.99",
"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"
}
}
]
}
]
}
]
}

View File

@ -41,16 +41,6 @@
}
},
"outcome": {
"result": [
{
"_id": 2,
"x": 22
},
{
"_id": 3,
"x": 33
}
],
"collection": {
"name": "other_test_collection",
"data": [
@ -92,16 +82,6 @@
}
},
"outcome": {
"result": [
{
"_id": 2,
"x": 22
},
{
"_id": 3,
"x": 33
}
],
"collection": {
"name": "other_test_collection",
"data": [

View File

@ -0,0 +1,110 @@
{
"runOn": [
{
"maxServerVersion": "3.5.5"
}
],
"data": [
{
"_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": [
{
"name": "bulkWrite",
"arguments": {
"requests": [
{
"name": "updateOne",
"arguments": {
"filter": {},
"update": {
"$set": {
"y.0.b": 2
}
},
"arrayFilters": [
{
"i.b": 1
}
]
}
}
],
"options": {
"ordered": true
}
},
"error": true
}
],
"expectations": []
},
{
"description": "BulkWrite on server that doesn't support arrayFilters with arrayFilters on second op",
"operations": [
{
"name": "bulkWrite",
"arguments": {
"requests": [
{
"name": "updateOne",
"arguments": {
"filter": {},
"update": {
"$set": {
"y.0.b": 2
}
}
}
},
{
"name": "updateMany",
"arguments": {
"filter": {},
"update": {
"$set": {
"y.$[i].b": 2
}
},
"arrayFilters": [
{
"i.b": 1
}
]
}
}
],
"options": {
"ordered": true
}
},
"error": true
}
],
"expectations": []
}
]
}

View File

@ -0,0 +1,151 @@
{
"data": [
{
"_id": 1,
"x": 11
},
{
"_id": 2,
"x": 22
},
{
"_id": 3,
"x": 33
}
],
"tests": [
{
"description": "BulkWrite replaceOne prohibits atomic modifiers",
"operations": [
{
"name": "bulkWrite",
"arguments": {
"requests": [
{
"name": "replaceOne",
"arguments": {
"filter": {
"_id": 1
},
"replacement": {
"$set": {
"x": 22
}
}
}
}
]
},
"error": true
}
],
"expectations": [],
"outcome": {
"collection": {
"data": [
{
"_id": 1,
"x": 11
},
{
"_id": 2,
"x": 22
},
{
"_id": 3,
"x": 33
}
]
}
}
},
{
"description": "BulkWrite updateOne requires atomic modifiers",
"operations": [
{
"name": "bulkWrite",
"arguments": {
"requests": [
{
"name": "updateOne",
"arguments": {
"filter": {
"_id": 1
},
"update": {
"x": 22
}
}
}
]
},
"error": true
}
],
"expectations": [],
"outcome": {
"collection": {
"data": [
{
"_id": 1,
"x": 11
},
{
"_id": 2,
"x": 22
},
{
"_id": 3,
"x": 33
}
]
}
}
},
{
"description": "BulkWrite updateMany requires atomic modifiers",
"operations": [
{
"name": "bulkWrite",
"arguments": {
"requests": [
{
"name": "updateMany",
"arguments": {
"filter": {
"_id": {
"$gt": 1
}
},
"update": {
"x": 44
}
}
}
]
},
"error": true
}
],
"expectations": [],
"outcome": {
"collection": {
"data": [
{
"_id": 1,
"x": 11
},
{
"_id": 2,
"x": 22
},
{
"_id": 3,
"x": 33
}
]
}
}
}
]
}

View File

@ -1,78 +1,78 @@
{
"runOn": [
"runOn": [
{
"minServerVersion": "4.3.1"
}
],
"collection_name": "test_find_allowdiskuse",
"tests": [
{
"description": "Find does not send allowDiskuse when value is not specified",
"operations": [
{
"minServerVersion": "4.3.1"
"object": "collection",
"name": "find",
"arguments": {
"filter": {}
}
}
],
"collection_name": "test_find_allowdiskuse",
"tests": [
],
"expectations": [
{
"description": "Find does not send allowDiskuse when value is not specified",
"operations": [
{
"object": "collection",
"name": "find",
"arguments": {
"filter": {}
}
}
],
"expectations": [
{
"command_started_event": {
"command": {
"find": "test_find_allowdiskuse",
"allowDiskUse": null
}
}
}
]
},
{
"description": "Find sends allowDiskuse false when false is specified",
"operations": [
{
"object": "collection",
"name": "find",
"arguments": {
"filter": {},
"allowDiskUse": false
}
}
],
"expectations": [
{
"command_started_event": {
"command": {
"find": "test_find_allowdiskuse",
"allowDiskUse": false
}
}
}
]
},
{
"description": "Find sends allowDiskUse true when true is specified",
"operations": [
{
"object": "collection",
"name": "find",
"arguments": {
"filter": {},
"allowDiskUse": true
}
}
],
"expectations": [
{
"command_started_event": {
"command": {
"find": "test_find_allowdiskuse",
"allowDiskUse": true
}
}
}
]
"command_started_event": {
"command": {
"find": "test_find_allowdiskuse",
"allowDiskUse": null
}
}
}
]
}
]
},
{
"description": "Find sends allowDiskuse false when false is specified",
"operations": [
{
"object": "collection",
"name": "find",
"arguments": {
"filter": {},
"allowDiskUse": false
}
}
],
"expectations": [
{
"command_started_event": {
"command": {
"find": "test_find_allowdiskuse",
"allowDiskUse": false
}
}
}
]
},
{
"description": "Find sends allowDiskUse true when true is specified",
"operations": [
{
"object": "collection",
"name": "find",
"arguments": {
"filter": {},
"allowDiskUse": true
}
}
],
"expectations": [
{
"command_started_event": {
"command": {
"find": "test_find_allowdiskuse",
"allowDiskUse": true
}
}
}
]
}
]
}

View File

@ -62,7 +62,7 @@
}
},
{
"description": "FindOneAndDelete with hint document",
"description": "FindOneAndDelete with hint document unsupported (server-side error)",
"operations": [
{
"object": "collection",

View File

@ -0,0 +1,41 @@
{
"data": [
{
"_id": 1,
"x": 11
}
],
"tests": [
{
"description": "ReplaceOne prohibits atomic modifiers",
"operations": [
{
"object": "collection",
"name": "replaceOne",
"arguments": {
"filter": {
"_id": 1
},
"replacement": {
"$set": {
"x": 22
}
}
},
"error": true
}
],
"expectations": [],
"outcome": {
"collection": {
"data": [
{
"_id": 1,
"x": 11
}
]
}
}
}
]
}

View File

@ -0,0 +1,57 @@
{
"data": [
{
"_id": 1,
"x": 11
},
{
"_id": 2,
"x": 22
},
{
"_id": 3,
"x": 33
}
],
"tests": [
{
"description": "UpdateOne requires atomic modifiers",
"operations": [
{
"object": "collection",
"name": "updateMany",
"arguments": {
"filter": {
"_id": {
"$gt": 1
}
},
"update": {
"x": 44
}
},
"error": true
}
],
"expectations": [],
"outcome": {
"collection": {
"data": [
{
"_id": 1,
"x": 11
},
{
"_id": 2,
"x": 22
},
{
"_id": 3,
"x": 33
}
]
}
}
}
]
}

View File

@ -0,0 +1,39 @@
{
"data": [
{
"_id": 1,
"x": 11
}
],
"tests": [
{
"description": "UpdateOne requires atomic modifiers",
"operations": [
{
"object": "collection",
"name": "updateOne",
"arguments": {
"filter": {
"_id": 1
},
"update": {
"x": 22
}
},
"error": true
}
],
"expectations": [],
"outcome": {
"collection": {
"data": [
{
"_id": 1,
"x": 11
}
]
}
}
}
]
}

View File

@ -25,6 +25,12 @@ class TestCrudV2(SpecRunner):
TEST_DB = None
TEST_COLLECTION = None
def allowable_errors(self, op):
"""Override expected error classes."""
errors = super(TestCrudV2, self).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)

View File

@ -0,0 +1,98 @@
{
"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"
}
}
]
}
]
}

View File

@ -0,0 +1,246 @@
{
"runOn": [
{
"minServerVersion": "4.9.0"
}
],
"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": {
"aggregate": "coll",
"pipeline": [
{
"$collStats": {
"count": {}
}
},
{
"$group": {
"_id": 1,
"n": {
"$sum": "$count"
}
}
}
]
},
"database_name": "retryable-reads-tests"
}
}
]
},
{
"description": "EstimatedDocumentCount succeeds on second attempt",
"failPoint": {
"configureFailPoint": "failCommand",
"mode": {
"times": 1
},
"data": {
"failCommands": [
"aggregate"
],
"closeConnection": true
}
},
"operations": [
{
"name": "estimatedDocumentCount",
"object": "collection",
"result": 2
}
],
"expectations": [
{
"command_started_event": {
"command": {
"aggregate": "coll",
"pipeline": [
{
"$collStats": {
"count": {}
}
},
{
"$group": {
"_id": 1,
"n": {
"$sum": "$count"
}
}
}
]
},
"database_name": "retryable-reads-tests"
}
},
{
"command_started_event": {
"command": {
"aggregate": "coll",
"pipeline": [
{
"$collStats": {
"count": {}
}
},
{
"$group": {
"_id": 1,
"n": {
"$sum": "$count"
}
}
}
]
},
"database_name": "retryable-reads-tests"
}
}
]
},
{
"description": "EstimatedDocumentCount fails on first attempt",
"clientOptions": {
"retryReads": false
},
"failPoint": {
"configureFailPoint": "failCommand",
"mode": {
"times": 1
},
"data": {
"failCommands": [
"aggregate"
],
"closeConnection": true
}
},
"operations": [
{
"name": "estimatedDocumentCount",
"object": "collection",
"error": true
}
],
"expectations": [
{
"command_started_event": {
"command": {
"aggregate": "coll",
"pipeline": [
{
"$collStats": {
"count": {}
}
},
{
"$group": {
"_id": 1,
"n": {
"$sum": "$count"
}
}
}
]
},
"database_name": "retryable-reads-tests"
}
}
]
},
{
"description": "EstimatedDocumentCount fails on second attempt",
"failPoint": {
"configureFailPoint": "failCommand",
"mode": {
"times": 2
},
"data": {
"failCommands": [
"aggregate"
],
"closeConnection": true
}
},
"operations": [
{
"name": "estimatedDocumentCount",
"object": "collection",
"error": true
}
],
"expectations": [
{
"command_started_event": {
"command": {
"aggregate": "coll",
"pipeline": [
{
"$collStats": {
"count": {}
}
},
{
"$group": {
"_id": 1,
"n": {
"$sum": "$count"
}
}
}
]
},
"database_name": "retryable-reads-tests"
}
},
{
"command_started_event": {
"command": {
"aggregate": "coll",
"pipeline": [
{
"$collStats": {
"count": {}
}
},
{
"$group": {
"_id": 1,
"n": {
"$sum": "$count"
}
}
}
]
},
"database_name": "retryable-reads-tests"
}
}
]
}
]
}

View File

@ -2,6 +2,7 @@
"runOn": [
{
"minServerVersion": "4.0",
"maxServerVersion": "4.8.99",
"topology": [
"single",
"replicaset"
@ -9,6 +10,7 @@
},
{
"minServerVersion": "4.1.7",
"maxServerVersion": "4.8.99",
"topology": [
"sharded"
]

View File

@ -0,0 +1,911 @@
{
"runOn": [
{
"minServerVersion": "4.9.0"
}
],
"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": [
"aggregate"
],
"errorCode": 11600
}
},
"operations": [
{
"name": "estimatedDocumentCount",
"object": "collection",
"result": 2
}
],
"expectations": [
{
"command_started_event": {
"command": {
"aggregate": "coll",
"pipeline": [
{
"$collStats": {
"count": {}
}
},
{
"$group": {
"_id": 1,
"n": {
"$sum": "$count"
}
}
}
]
},
"database_name": "retryable-reads-tests"
}
},
{
"command_started_event": {
"command": {
"aggregate": "coll",
"pipeline": [
{
"$collStats": {
"count": {}
}
},
{
"$group": {
"_id": 1,
"n": {
"$sum": "$count"
}
}
}
]
},
"database_name": "retryable-reads-tests"
}
}
]
},
{
"description": "EstimatedDocumentCount succeeds after InterruptedDueToReplStateChange",
"failPoint": {
"configureFailPoint": "failCommand",
"mode": {
"times": 1
},
"data": {
"failCommands": [
"aggregate"
],
"errorCode": 11602
}
},
"operations": [
{
"name": "estimatedDocumentCount",
"object": "collection",
"result": 2
}
],
"expectations": [
{
"command_started_event": {
"command": {
"aggregate": "coll",
"pipeline": [
{
"$collStats": {
"count": {}
}
},
{
"$group": {
"_id": 1,
"n": {
"$sum": "$count"
}
}
}
]
},
"database_name": "retryable-reads-tests"
}
},
{
"command_started_event": {
"command": {
"aggregate": "coll",
"pipeline": [
{
"$collStats": {
"count": {}
}
},
{
"$group": {
"_id": 1,
"n": {
"$sum": "$count"
}
}
}
]
},
"database_name": "retryable-reads-tests"
}
}
]
},
{
"description": "EstimatedDocumentCount succeeds after NotMaster",
"failPoint": {
"configureFailPoint": "failCommand",
"mode": {
"times": 1
},
"data": {
"failCommands": [
"aggregate"
],
"errorCode": 10107
}
},
"operations": [
{
"name": "estimatedDocumentCount",
"object": "collection",
"result": 2
}
],
"expectations": [
{
"command_started_event": {
"command": {
"aggregate": "coll",
"pipeline": [
{
"$collStats": {
"count": {}
}
},
{
"$group": {
"_id": 1,
"n": {
"$sum": "$count"
}
}
}
]
},
"database_name": "retryable-reads-tests"
}
},
{
"command_started_event": {
"command": {
"aggregate": "coll",
"pipeline": [
{
"$collStats": {
"count": {}
}
},
{
"$group": {
"_id": 1,
"n": {
"$sum": "$count"
}
}
}
]
},
"database_name": "retryable-reads-tests"
}
}
]
},
{
"description": "EstimatedDocumentCount succeeds after NotMasterNoSlaveOk",
"failPoint": {
"configureFailPoint": "failCommand",
"mode": {
"times": 1
},
"data": {
"failCommands": [
"aggregate"
],
"errorCode": 13435
}
},
"operations": [
{
"name": "estimatedDocumentCount",
"object": "collection",
"result": 2
}
],
"expectations": [
{
"command_started_event": {
"command": {
"aggregate": "coll",
"pipeline": [
{
"$collStats": {
"count": {}
}
},
{
"$group": {
"_id": 1,
"n": {
"$sum": "$count"
}
}
}
]
},
"database_name": "retryable-reads-tests"
}
},
{
"command_started_event": {
"command": {
"aggregate": "coll",
"pipeline": [
{
"$collStats": {
"count": {}
}
},
{
"$group": {
"_id": 1,
"n": {
"$sum": "$count"
}
}
}
]
},
"database_name": "retryable-reads-tests"
}
}
]
},
{
"description": "EstimatedDocumentCount succeeds after NotMasterOrSecondary",
"failPoint": {
"configureFailPoint": "failCommand",
"mode": {
"times": 1
},
"data": {
"failCommands": [
"aggregate"
],
"errorCode": 13436
}
},
"operations": [
{
"name": "estimatedDocumentCount",
"object": "collection",
"result": 2
}
],
"expectations": [
{
"command_started_event": {
"command": {
"aggregate": "coll",
"pipeline": [
{
"$collStats": {
"count": {}
}
},
{
"$group": {
"_id": 1,
"n": {
"$sum": "$count"
}
}
}
]
},
"database_name": "retryable-reads-tests"
}
},
{
"command_started_event": {
"command": {
"aggregate": "coll",
"pipeline": [
{
"$collStats": {
"count": {}
}
},
{
"$group": {
"_id": 1,
"n": {
"$sum": "$count"
}
}
}
]
},
"database_name": "retryable-reads-tests"
}
}
]
},
{
"description": "EstimatedDocumentCount succeeds after PrimarySteppedDown",
"failPoint": {
"configureFailPoint": "failCommand",
"mode": {
"times": 1
},
"data": {
"failCommands": [
"aggregate"
],
"errorCode": 189
}
},
"operations": [
{
"name": "estimatedDocumentCount",
"object": "collection",
"result": 2
}
],
"expectations": [
{
"command_started_event": {
"command": {
"aggregate": "coll",
"pipeline": [
{
"$collStats": {
"count": {}
}
},
{
"$group": {
"_id": 1,
"n": {
"$sum": "$count"
}
}
}
]
},
"database_name": "retryable-reads-tests"
}
},
{
"command_started_event": {
"command": {
"aggregate": "coll",
"pipeline": [
{
"$collStats": {
"count": {}
}
},
{
"$group": {
"_id": 1,
"n": {
"$sum": "$count"
}
}
}
]
},
"database_name": "retryable-reads-tests"
}
}
]
},
{
"description": "EstimatedDocumentCount succeeds after ShutdownInProgress",
"failPoint": {
"configureFailPoint": "failCommand",
"mode": {
"times": 1
},
"data": {
"failCommands": [
"aggregate"
],
"errorCode": 91
}
},
"operations": [
{
"name": "estimatedDocumentCount",
"object": "collection",
"result": 2
}
],
"expectations": [
{
"command_started_event": {
"command": {
"aggregate": "coll",
"pipeline": [
{
"$collStats": {
"count": {}
}
},
{
"$group": {
"_id": 1,
"n": {
"$sum": "$count"
}
}
}
]
},
"database_name": "retryable-reads-tests"
}
},
{
"command_started_event": {
"command": {
"aggregate": "coll",
"pipeline": [
{
"$collStats": {
"count": {}
}
},
{
"$group": {
"_id": 1,
"n": {
"$sum": "$count"
}
}
}
]
},
"database_name": "retryable-reads-tests"
}
}
]
},
{
"description": "EstimatedDocumentCount succeeds after HostNotFound",
"failPoint": {
"configureFailPoint": "failCommand",
"mode": {
"times": 1
},
"data": {
"failCommands": [
"aggregate"
],
"errorCode": 7
}
},
"operations": [
{
"name": "estimatedDocumentCount",
"object": "collection",
"result": 2
}
],
"expectations": [
{
"command_started_event": {
"command": {
"aggregate": "coll",
"pipeline": [
{
"$collStats": {
"count": {}
}
},
{
"$group": {
"_id": 1,
"n": {
"$sum": "$count"
}
}
}
]
},
"database_name": "retryable-reads-tests"
}
},
{
"command_started_event": {
"command": {
"aggregate": "coll",
"pipeline": [
{
"$collStats": {
"count": {}
}
},
{
"$group": {
"_id": 1,
"n": {
"$sum": "$count"
}
}
}
]
},
"database_name": "retryable-reads-tests"
}
}
]
},
{
"description": "EstimatedDocumentCount succeeds after HostUnreachable",
"failPoint": {
"configureFailPoint": "failCommand",
"mode": {
"times": 1
},
"data": {
"failCommands": [
"aggregate"
],
"errorCode": 6
}
},
"operations": [
{
"name": "estimatedDocumentCount",
"object": "collection",
"result": 2
}
],
"expectations": [
{
"command_started_event": {
"command": {
"aggregate": "coll",
"pipeline": [
{
"$collStats": {
"count": {}
}
},
{
"$group": {
"_id": 1,
"n": {
"$sum": "$count"
}
}
}
]
},
"database_name": "retryable-reads-tests"
}
},
{
"command_started_event": {
"command": {
"aggregate": "coll",
"pipeline": [
{
"$collStats": {
"count": {}
}
},
{
"$group": {
"_id": 1,
"n": {
"$sum": "$count"
}
}
}
]
},
"database_name": "retryable-reads-tests"
}
}
]
},
{
"description": "EstimatedDocumentCount succeeds after NetworkTimeout",
"failPoint": {
"configureFailPoint": "failCommand",
"mode": {
"times": 1
},
"data": {
"failCommands": [
"aggregate"
],
"errorCode": 89
}
},
"operations": [
{
"name": "estimatedDocumentCount",
"object": "collection",
"result": 2
}
],
"expectations": [
{
"command_started_event": {
"command": {
"aggregate": "coll",
"pipeline": [
{
"$collStats": {
"count": {}
}
},
{
"$group": {
"_id": 1,
"n": {
"$sum": "$count"
}
}
}
]
},
"database_name": "retryable-reads-tests"
}
},
{
"command_started_event": {
"command": {
"aggregate": "coll",
"pipeline": [
{
"$collStats": {
"count": {}
}
},
{
"$group": {
"_id": 1,
"n": {
"$sum": "$count"
}
}
}
]
},
"database_name": "retryable-reads-tests"
}
}
]
},
{
"description": "EstimatedDocumentCount succeeds after SocketException",
"failPoint": {
"configureFailPoint": "failCommand",
"mode": {
"times": 1
},
"data": {
"failCommands": [
"aggregate"
],
"errorCode": 9001
}
},
"operations": [
{
"name": "estimatedDocumentCount",
"object": "collection",
"result": 2
}
],
"expectations": [
{
"command_started_event": {
"command": {
"aggregate": "coll",
"pipeline": [
{
"$collStats": {
"count": {}
}
},
{
"$group": {
"_id": 1,
"n": {
"$sum": "$count"
}
}
}
]
},
"database_name": "retryable-reads-tests"
}
},
{
"command_started_event": {
"command": {
"aggregate": "coll",
"pipeline": [
{
"$collStats": {
"count": {}
}
},
{
"$group": {
"_id": 1,
"n": {
"$sum": "$count"
}
}
}
]
},
"database_name": "retryable-reads-tests"
}
}
]
},
{
"description": "EstimatedDocumentCount fails after two NotMaster errors",
"failPoint": {
"configureFailPoint": "failCommand",
"mode": {
"times": 2
},
"data": {
"failCommands": [
"aggregate"
],
"errorCode": 10107
}
},
"operations": [
{
"name": "estimatedDocumentCount",
"object": "collection",
"error": true
}
],
"expectations": [
{
"command_started_event": {
"command": {
"aggregate": "coll",
"pipeline": [
{
"$collStats": {
"count": {}
}
},
{
"$group": {
"_id": 1,
"n": {
"$sum": "$count"
}
}
}
]
},
"database_name": "retryable-reads-tests"
}
},
{
"command_started_event": {
"command": {
"aggregate": "coll",
"pipeline": [
{
"$collStats": {
"count": {}
}
},
{
"$group": {
"_id": 1,
"n": {
"$sum": "$count"
}
}
}
]
},
"database_name": "retryable-reads-tests"
}
}
]
},
{
"description": "EstimatedDocumentCount fails after NotMaster when retryReads is false",
"clientOptions": {
"retryReads": false
},
"failPoint": {
"configureFailPoint": "failCommand",
"mode": {
"times": 1
},
"data": {
"failCommands": [
"aggregate"
],
"errorCode": 10107
}
},
"operations": [
{
"name": "estimatedDocumentCount",
"object": "collection",
"error": true
}
],
"expectations": [
{
"command_started_event": {
"command": {
"aggregate": "coll",
"pipeline": [
{
"$collStats": {
"count": {}
}
},
{
"$group": {
"_id": 1,
"n": {
"$sum": "$count"
}
}
}
]
},
"database_name": "retryable-reads-tests"
}
}
]
}
]
}

View File

@ -2,6 +2,7 @@
"runOn": [
{
"minServerVersion": "4.0",
"maxServerVersion": "4.8.99",
"topology": [
"single",
"replicaset"
@ -9,6 +10,7 @@
},
{
"minServerVersion": "4.1.7",
"maxServerVersion": "4.8.99",
"topology": [
"sharded"
]

View File

@ -30,7 +30,7 @@
{
"command_started_event": {
"command": {
"listIndexNames": "coll"
"listIndexes": "coll"
},
"database_name": "retryable-reads-tests"
}
@ -61,7 +61,7 @@
{
"command_started_event": {
"command": {
"listIndexNames": "coll"
"listIndexes": "coll"
},
"database_name": "retryable-reads-tests"
}
@ -69,7 +69,7 @@
{
"command_started_event": {
"command": {
"listIndexNames": "coll"
"listIndexes": "coll"
},
"database_name": "retryable-reads-tests"
}
@ -104,7 +104,7 @@
{
"command_started_event": {
"command": {
"listIndexNames": "coll"
"listIndexes": "coll"
},
"database_name": "retryable-reads-tests"
}
@ -136,7 +136,7 @@
{
"command_started_event": {
"command": {
"listIndexNames": "coll"
"listIndexes": "coll"
},
"database_name": "retryable-reads-tests"
}
@ -144,7 +144,7 @@
{
"command_started_event": {
"command": {
"listIndexNames": "coll"
"listIndexes": "coll"
},
"database_name": "retryable-reads-tests"
}

34
test/test_crud_unified.py Normal file
View File

@ -0,0 +1,34 @@
# 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."""
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__))
if __name__ == "__main__":
unittest.main()

View File

@ -125,11 +125,6 @@ def run_operation(collection, test):
result = cmd(**arguments)
if operation == "aggregate":
if arguments["pipeline"] and "$out" in arguments["pipeline"][-1]:
out = collection.database[arguments["pipeline"][-1]["$out"]]
result = out.find()
if isinstance(result, Cursor) or isinstance(result, CommandCursor):
return list(result)
@ -154,7 +149,8 @@ def create_test(scenario_def, test, name):
run_operation(self.db.test, test)
else:
result = run_operation(self.db.test, test)
check_result(self, expected_result, result)
if expected_result is not None:
check_result(self, expected_result, result)
# Assert final state is expected.
expected_c = test['outcome'].get('collection')

View File

@ -3,7 +3,7 @@
"schemaVersion": "1.1",
"runOnRequirements": [
{
"minServerVersion": "4.7"
"minServerVersion": "4.9"
}
],
"createEntities": [
@ -301,6 +301,12 @@
"$inc": {
"x": 1
}
},
"multi": {
"$$unsetOrMatches": false
},
"upsert": {
"$$unsetOrMatches": false
}
}
],
@ -353,7 +359,10 @@
"x": 1
}
},
"multi": true
"multi": true,
"upsert": {
"$$unsetOrMatches": false
}
}
],
"apiVersion": "1",
@ -397,6 +406,9 @@
"_id": 4,
"x": 44
},
"multi": {
"$$unsetOrMatches": false
},
"upsert": true
}
],
@ -596,7 +608,6 @@
},
{
"description": "estimatedDocumentCount appends declared API version",
"skipReason": "DRIVERS-1437 count was removed from API version 1",
"operations": [
{
"name": "estimatedDocumentCount",
@ -611,7 +622,22 @@
{
"commandStartedEvent": {
"command": {
"count": "test",
"aggregate": "test",
"pipeline": [
{
"$collStats": {
"count": {}
}
},
{
"$group": {
"_id": 1,
"n": {
"$sum": "$count"
}
}
}
],
"apiVersion": "1",
"apiStrict": true,
"apiDeprecationErrors": {
@ -952,6 +978,9 @@
"_id": 4,
"x": 44
},
"multi": {
"$$unsetOrMatches": false
},
"upsert": true
}
],
@ -1007,7 +1036,10 @@
"x": 1
}
},
"multi": true
"multi": true,
"upsert": {
"$$unsetOrMatches": false
}
}
],
"apiVersion": "1",
@ -1057,6 +1089,12 @@
"$inc": {
"x": 1
}
},
"multi": {
"$$unsetOrMatches": false
},
"upsert": {
"$$unsetOrMatches": false
}
}
],

View File

@ -3,7 +3,7 @@
"schemaVersion": "1.1",
"runOnRequirements": [
{
"minServerVersion": "4.7"
"minServerVersion": "4.9"
}
],
"createEntities": [
@ -298,6 +298,12 @@
"$inc": {
"x": 1
}
},
"multi": {
"$$unsetOrMatches": false
},
"upsert": {
"$$unsetOrMatches": false
}
}
],
@ -350,7 +356,10 @@
"x": 1
}
},
"multi": true
"multi": true,
"upsert": {
"$$unsetOrMatches": false
}
}
],
"apiVersion": "1",
@ -394,6 +403,9 @@
"_id": 4,
"x": 44
},
"multi": {
"$$unsetOrMatches": false
},
"upsert": true
}
],
@ -587,7 +599,7 @@
]
},
{
"description": "estimatedDocumentCount appends declared API version",
"description": "estimatedDocumentCount appends declared API version on 4.9.0 or greater",
"operations": [
{
"name": "estimatedDocumentCount",
@ -602,7 +614,22 @@
{
"commandStartedEvent": {
"command": {
"count": "test",
"aggregate": "test",
"pipeline": [
{
"$collStats": {
"count": {}
}
},
{
"$group": {
"_id": 1,
"n": {
"$sum": "$count"
}
}
}
],
"apiVersion": "1",
"apiStrict": {
"$$unsetOrMatches": false
@ -943,6 +970,9 @@
"_id": 4,
"x": 44
},
"multi": {
"$$unsetOrMatches": false
},
"upsert": true
}
],
@ -998,7 +1028,10 @@
"x": 1
}
},
"multi": true
"multi": true,
"upsert": {
"$$unsetOrMatches": false
}
}
],
"apiVersion": "1",
@ -1048,6 +1081,12 @@
"$inc": {
"x": 1
}
},
"multi": {
"$$unsetOrMatches": false
},
"upsert": {
"$$unsetOrMatches": false
}
}
],