summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMohammad Dashti <mdashti@gmail.com>2021-04-10 19:29:51 +0000
committerEvergreen Agent <no-reply@evergreen.mongodb.com>2021-04-10 20:05:27 +0000
commit2ff1849ef0c5b8d9ea59853e9e205d3e7b4581e1 (patch)
treebc60f74ec87a5d4f1fe51e03f80b64caa3b1ca62
parentccca10b25ab33f15a90c7c60996a054b9f8cc458 (diff)
downloadmongo-2ff1849ef0c5b8d9ea59853e9e205d3e7b4581e1.tar.gz
SERVER-54925 Move away from using Bson_serialization_type “any”
-rw-r--r--buildscripts/idl/idl_check_compatibility.py48
-rw-r--r--buildscripts/idl/idl_compatibility_errors.py54
-rw-r--r--buildscripts/idl/tests/compatibility_test_fail/new/compatibility_test_fail_new.idl342
-rw-r--r--buildscripts/idl/tests/compatibility_test_fail/old/compatibility_test_fail_old.idl372
-rw-r--r--buildscripts/idl/tests/test_compatibility.py43
-rw-r--r--src/mongo/db/ops/write_ops.cpp16
-rw-r--r--src/mongo/db/ops/write_ops_parsers.h14
-rw-r--r--src/mongo/db/pipeline/aggregation_request_helper.cpp16
-rw-r--r--src/mongo/db/pipeline/aggregation_request_helper.h19
-rw-r--r--src/mongo/db/pipeline/aggregation_request_test.cpp17
-rw-r--r--src/mongo/db/query/hint_parser.cpp8
-rw-r--r--src/mongo/db/query/max_time_ms_parser.cpp4
-rw-r--r--src/mongo/db/query/max_time_ms_parser.h4
-rw-r--r--src/mongo/db/query/query_request_test.cpp58
-rw-r--r--src/mongo/idl/basic_types.h26
-rw-r--r--src/mongo/idl/idl_parser.cpp16
-rw-r--r--src/mongo/idl/idl_parser.h16
17 files changed, 920 insertions, 153 deletions
diff --git a/buildscripts/idl/idl_check_compatibility.py b/buildscripts/idl/idl_check_compatibility.py
index 120a42d5a4f..77a187857ae 100644
--- a/buildscripts/idl/idl_check_compatibility.py
+++ b/buildscripts/idl/idl_check_compatibility.py
@@ -50,6 +50,7 @@ from idl.compiler import CompilerImportResolver
from idl_compatibility_errors import IDLCompatibilityContext, IDLCompatibilityErrorCollection, dump_errors
ALLOW_ANY_TYPE_LIST: List[str] = [
+ # This list if only used in unit-tests.
"commandAllowedAnyTypes",
"commandAllowedAnyTypes-param-anyTypeParam",
"commandAllowedAnyTypes-reply-anyTypeField",
@@ -69,6 +70,12 @@ ALLOW_ANY_TYPE_LIST: List[str] = [
"replyFieldCppTypeNotEqual-reply-cppTypeNotEqualReplyField",
"commandCppTypeNotEqual",
"commandParameterCppTypeNotEqual-param-cppTypeNotEqualParam",
+ "replyFieldSerializerNotEqual-reply-serializerNotEqualReplyField",
+ "commandSerializerNotEqual",
+ "commandParameterSerializerNotEqual-param-serializerNotEqualParam",
+ "replyFieldDeserializerNotEqual-reply-deserializerNotEqualReplyField",
+ "commandDeserializerNotEqual",
+ "commandParameterDeserializerNotEqual-param-deserializerNotEqualParam",
"newlyAddedReplyFieldTypeBsonAnyAllowed-reply-newlyAddedBsonSerializationTypeAnyReplyField",
"replyFieldTypeBsonAnyWithVariantUnstable-reply-bsonSerializationTypeWithVariantAnyUnstableReplyField",
"newlyAddedParamBsonAnyAllowList-param-newlyAddedBsonAnyAllowListParam",
@@ -78,6 +85,12 @@ ALLOW_ANY_TYPE_LIST: List[str] = [
"commandParameterCppTypeNotEqualUnstable-param-cppTypeNotEqualParam",
"replyFieldCppTypeNotEqualUnstable-reply-cppTypeNotEqualReplyUnstableField",
"commandCppTypeNotEqualUnstable",
+ "commandParameterSerializerNotEqualUnstable-param-serializerNotEqualParam",
+ "replyFieldSerializerNotEqualUnstable-reply-serializerNotEqualReplyUnstableField",
+ "commandSerializerNotEqualUnstable",
+ "commandParameterDeserializerNotEqualUnstable-param-deserializerNotEqualParam",
+ "replyFieldDeserializerNotEqualUnstable-reply-deserializerNotEqualReplyUnstableField",
+ "commandDeserializerNotEqualUnstable",
# TODO (SERVER-54956): Decide what to do with commands: (create, createIndexes).
'create-param-backwards',
@@ -93,8 +106,17 @@ ALLOW_ANY_TYPE_LIST: List[str] = [
'saslContinue-param-payload',
'saslContinue-reply-payload',
- # TODO (SERVER-54925): Decide what to do with commands:
- # (aggregate, find, update, delete, findAndModify, explain).
+ # These commands (aggregate, find, update, delete, findAndModify, explain) might contain some
+ # fields with type `any`. Currently, it's not possible to avoid the `any` type in those cases.
+ # Instead, here are the preventive measures in-place to catch unintentional breaking changes:
+ # 1- Added comments on top of custom serializers/deserializers (related to these fields) to
+ # let the future developers know that their modifications to these methods might lead to
+ # a breaking change in the API.
+ # 2- Added proper unit-tests to catch accidental changes to the custom serializers/deserializers
+ # by over-fitting on the current implementation of these custom serializers/deserializers.
+ # 3- Added further checks to the current script (idl_check_compatibility.py) to check for
+ # changing a custom serializer/deserializer and considering it as a potential breaking
+ # change.
'aggregate-param-pipeline',
'aggregate-param-explain',
'aggregate-param-allowDiskUse',
@@ -289,10 +311,21 @@ def check_reply_field_type_recursive(ctxt: IDLCompatibilityContext,
cmd_name, field_name, old_field_type.name, old_field.idl_file_path)
return
+ # If cpp_type is changed, it's a potential breaking change.
if old_field_type.cpp_type != new_field_type.cpp_type:
ctxt.add_reply_field_cpp_type_not_equal_error(cmd_name, field_name, new_field_type.name,
new_field.idl_file_path)
+ # If serializer is changed, it's a potential breaking change.
+ if (not old_field.unstable) and old_field_type.serializer != new_field_type.serializer:
+ ctxt.add_reply_field_serializer_not_equal_error(
+ cmd_name, field_name, new_field_type.name, new_field.idl_file_path)
+
+ # If deserializer is changed, it's a potential breaking change.
+ if (not old_field.unstable) and old_field_type.deserializer != new_field_type.deserializer:
+ ctxt.add_reply_field_deserializer_not_equal_error(
+ cmd_name, field_name, new_field_type.name, new_field.idl_file_path)
+
if isinstance(old_field_type, syntax.VariantType):
# If the new type is not variant just check the single type.
new_variant_types = new_field_type.variant_types if isinstance(
@@ -542,10 +575,21 @@ def check_param_or_command_type_recursive(ctxt: IDLCompatibilityContext,
cmd_name, old_type.name, old_field.idl_file_path, param_name, is_command_parameter)
return
+ # If cpp_type is changed, it's a potential breaking change.
if old_type.cpp_type != new_type.cpp_type:
ctxt.add_command_or_param_cpp_type_not_equal_error(
cmd_name, new_type.name, new_field.idl_file_path, param_name, is_command_parameter)
+ # If serializer is changed, it's a potential breaking change.
+ if (not old_field.unstable) and old_type.serializer != new_type.serializer:
+ ctxt.add_command_or_param_serializer_not_equal_error(
+ cmd_name, new_type.name, new_field.idl_file_path, param_name, is_command_parameter)
+
+ # If deserializer is changed, it's a potential breaking change.
+ if (not old_field.unstable) and old_type.deserializer != new_type.deserializer:
+ ctxt.add_command_or_param_deserializer_not_equal_error(
+ cmd_name, new_type.name, new_field.idl_file_path, param_name, is_command_parameter)
+
if isinstance(old_type, syntax.VariantType):
if not isinstance(new_type, syntax.VariantType):
if not old_field.unstable:
diff --git a/buildscripts/idl/idl_compatibility_errors.py b/buildscripts/idl/idl_compatibility_errors.py
index dc5c30a2105..02961c50ccf 100644
--- a/buildscripts/idl/idl_compatibility_errors.py
+++ b/buildscripts/idl/idl_compatibility_errors.py
@@ -112,6 +112,12 @@ ERROR_ID_ADDED_ACCESS_CHECK_FIELD = "ID0067"
ERROR_ID_COMMAND_STRICT_TRUE_ERROR = "ID0068"
ERROR_ID_GENERIC_ARGUMENT_REMOVED = "ID0069"
ERROR_ID_GENERIC_ARGUMENT_REMOVED_REPLY_FIELD = "ID0070"
+ERROR_ID_COMMAND_PARAMETER_SERIALIZER_NOT_EQUAL = "ID0071"
+ERROR_ID_COMMAND_SERIALIZER_NOT_EQUAL = "ID0072"
+ERROR_ID_REPLY_FIELD_SERIALIZER_NOT_EQUAL = "ID0073"
+ERROR_ID_COMMAND_DESERIALIZER_NOT_EQUAL = "ID0074"
+ERROR_ID_COMMAND_PARAMETER_DESERIALIZER_NOT_EQUAL = "ID0075"
+ERROR_ID_REPLY_FIELD_DESERIALIZER_NOT_EQUAL = "ID0076"
# TODO (SERVER-55203): Remove SKIPPED_COMMANDS logic.
# Any breaking changes added to API V1 before releasing 5.0 should be added to SKIPPED_COMMANDS to
@@ -730,6 +736,22 @@ class IDLCompatibilityContext(object):
"that is not equal in the old and new versions.") %
(command_name, field_name, type_name), file)
+ def add_reply_field_serializer_not_equal_error(self, command_name: str, field_name: str,
+ type_name: str, file: str) -> None:
+ """Add an error about the old and new reply field serializer not being equal."""
+ self._add_error(ERROR_ID_REPLY_FIELD_SERIALIZER_NOT_EQUAL, command_name,
+ ("'%s' has a reply field or sub-field '%s' of type '%s' that has "
+ "serializer that is not equal in the old and new versions.") %
+ (command_name, field_name, type_name), file)
+
+ def add_reply_field_deserializer_not_equal_error(self, command_name: str, field_name: str,
+ type_name: str, file: str) -> None:
+ """Add an error about the old and new reply field deserializer not being equal."""
+ self._add_error(ERROR_ID_REPLY_FIELD_DESERIALIZER_NOT_EQUAL, command_name,
+ ("'%s' has a reply field or sub-field '%s' of type '%s' that has "
+ "deserializer that is not equal in the old and new versions.") %
+ (command_name, field_name, type_name), file)
+
def add_new_reply_field_type_not_enum_error(self, command_name: str, field_name: str,
new_field_type: str, old_field_type: str,
file: str) -> None:
@@ -864,6 +886,38 @@ class IDLCompatibilityContext(object):
("'%s' or its sub-struct has command type '%s' that has cpp_type "
"that is not equal in the old and new versions") % (command_name, type_name), file)
+ def add_command_or_param_serializer_not_equal_error(self, command_name: str, type_name: str,
+ file: str, field_name: Optional[str],
+ is_command_parameter: bool) -> None:
+ # pylint: disable=too-many-arguments,invalid-name
+ """Add an error about the old and new command or param serializer not being equal."""
+ if is_command_parameter:
+ self._add_error(ERROR_ID_COMMAND_PARAMETER_SERIALIZER_NOT_EQUAL, command_name,
+ ("'%s' has field or sub-field '%s' of type '%s' that has "
+ "serializer that is not equal in the old and new versions") %
+ (command_name, field_name, type_name), file)
+ else:
+ self._add_error(
+ ERROR_ID_COMMAND_SERIALIZER_NOT_EQUAL, command_name,
+ ("'%s' or its sub-struct has command type '%s' that has serializer "
+ "that is not equal in the old and new versions") % (command_name, type_name), file)
+
+ def add_command_or_param_deserializer_not_equal_error(self, command_name: str, type_name: str,
+ file: str, field_name: Optional[str],
+ is_command_parameter: bool) -> None:
+ # pylint: disable=too-many-arguments,invalid-name
+ """Add an error about the old and new command or param deserializer not being equal."""
+ if is_command_parameter:
+ self._add_error(ERROR_ID_COMMAND_PARAMETER_DESERIALIZER_NOT_EQUAL, command_name,
+ ("'%s' has field or sub-field '%s' of type '%s' that has "
+ "deserializer that is not equal in the old and new versions") %
+ (command_name, field_name, type_name), file)
+ else:
+ self._add_error(
+ ERROR_ID_COMMAND_DESERIALIZER_NOT_EQUAL, command_name,
+ ("'%s' or its sub-struct has command type '%s' that has deserializer "
+ "that is not equal in the old and new versions") % (command_name, type_name), file)
+
def add_old_reply_field_bson_any_error(self, command_name: str, field_name: str,
old_field_type: str, file: str) -> None:
"""
diff --git a/buildscripts/idl/tests/compatibility_test_fail/new/compatibility_test_fail_new.idl b/buildscripts/idl/tests/compatibility_test_fail/new/compatibility_test_fail_new.idl
index b92612556a8..01da70b3e8c 100644
--- a/buildscripts/idl/tests/compatibility_test_fail/new/compatibility_test_fail_new.idl
+++ b/buildscripts/idl/tests/compatibility_test_fail/new/compatibility_test_fail_new.idl
@@ -41,7 +41,7 @@ types:
description: "The bson_serialization_type changes from int in the old command's reply
field type to [int, string] in the new command's reply field type"
cpp_type: "std::int32_t"
-
+
intStringToIntStringBool:
bson_serialization_type:
- int
@@ -57,7 +57,7 @@ types:
- int
description: "The old bson_serialization_type contains 'any'"
cpp_type: "std::int32_t"
-
+
newBsonSerializationTypeAny:
bson_serialization_type:
- int
@@ -79,6 +79,24 @@ types:
description: "The old and new bson_serialization_type contains 'any'"
cpp_type: "std::int32_t"
+ bsonSerializationTypeAnySerializerNotEqual:
+ bson_serialization_type:
+ - int
+ - any
+ description: "The old and new bson_serialization_type contains 'any'. The 'serializer'
+ field value here is different from the one defined in old."
+ cpp_type: "std::int64_t"
+ serializer: ::mongo::newSerializer
+
+ bsonSerializationTypeAnyDeserializerNotEqual:
+ bson_serialization_type:
+ - int
+ - any
+ description: "The old and new bson_serialization_type contains 'any' The 'deserializer'
+ field value here is different from the one defined in old."
+ cpp_type: "std::int64_t"
+ deserializer: ::mongo::newDeserializer
+
intStringBoolToIntString:
bson_serialization_type:
- int
@@ -97,7 +115,7 @@ types:
enums:
NewReplyFieldEnumNotSubset:
- description: "The new reply type is an enum that is not a subset of the old reply type's
+ description: "The new reply type is an enum that is not a subset of the old reply type's
enum values"
type: string
values:
@@ -123,7 +141,7 @@ structs:
unstableNewField:
type: string
unstable: true
-
+
OptionalNewFieldReply:
description: "This reply contains a field that is required in the old command but is
optional in the new command."
@@ -131,11 +149,11 @@ structs:
optionalNewField:
type: string
optional: true
-
+
MissingNewFieldReply:
description: "This reply contains a field that exists in the old command but is
missing in the new command."
-
+
RequiredNewField:
description: "This struct contains a field that is optional in the old command but is
required in the new command."
@@ -223,12 +241,28 @@ structs:
variant: [array<oldBsonSerializationTypeAny>, array<newBsonSerializationTypeAny>]
CppTypeNotEqualReply:
- description: "This reply contains a field whose old and new type have a bson_serialization_type
- that contains 'any' and the cpp_types are not equal"
+ description: "This reply contains a field whose old and new type have a
+ bson_serialization_type that contains 'any' and the cpp_types are not equal"
fields:
cppTypeNotEqualReplyField:
type: bsonSerializationTypeAnyCppTypeNotEqual
+ SerializerNotEqualReply:
+ description: "This reply contains a field whose old and new type
+ have a bson_serialization_type that contains 'any'
+ and the serializers are not equal"
+ fields:
+ serializerNotEqualReplyField:
+ type: bsonSerializationTypeAnySerializerNotEqual
+
+ DeserializerNotEqualReply:
+ description: "This reply contains a field whose old and new type have
+ a bson_serialization_type that contains 'any' and the
+ deserializers are not equal"
+ fields:
+ deserializerNotEqualReplyField:
+ type: bsonSerializationTypeAnyDeserializerNotEqual
+
NewlyAddedBsonSerializationTypeAnyReply:
description: "This reply contains a newly added field whose type has a bson_serialization_type
that contains 'any' that is not explicitly allowed"
@@ -270,13 +304,29 @@ structs:
variant: [oldBsonSerializationTypeAny, newBsonSerializationTypeAny]
CppTypeNotEqualUnstableReply:
- description: "This reply contains a field whose old and new type have a bson_serialization_type
- that contains 'any' and the cpp_types are not equal and where the old field
- is unstable"
+ description: "This reply contains a field whose old and new type have a
+ bson_serialization_type that contains 'any' and the cpp_types are
+ not equal and where the old field is unstable"
fields:
cppTypeNotEqualReplyUnstableField:
type: bsonSerializationTypeAnyCppTypeNotEqual
+ SerializerNotEqualUnstableReply:
+ description: "This reply contains a field whose old and new type have a
+ bson_serialization_type that contains 'any' and the serializers are
+ not equal and where the old field is unstable"
+ fields:
+ serializerNotEqualReplyUnstableField:
+ type: bsonSerializationTypeAnySerializerNotEqual
+
+ DeserializerNotEqualUnstableReply:
+ description: "This reply contains a field whose old and new type have a
+ bson_serialization_type that contains 'any' and the deserializers are
+ not equal and where the old field is unstable"
+ fields:
+ deserializerNotEqualReplyUnstableField:
+ type: bsonSerializationTypeAnyDeserializerNotEqual
+
NewlyAddedBsonSerializationTypeAnyStruct:
description: "This struct contains a newly added field whose type has a bson_serialization_type
that contains 'any' that is not explicitly allowed"
@@ -323,41 +373,59 @@ structs:
variant: [oldBsonSerializationTypeAny, newBsonSerializationTypeAny]
CppTypeNotEqualUnstableStruct:
- description: "This struct contains a field whose old and new type have a bson_serialization_type
- that contains 'any' and the cpp_types are not equal and where the old field
- is unstable"
+ description: "This struct contains a field whose old and new type have a
+ bson_serialization_type that contains 'any' and the cpp_types are
+ not equal and where the old field is unstable"
fields:
cppTypeNotEqualStructUnstableField:
optional: true
type: bsonSerializationTypeAnyCppTypeNotEqual
+ SerializerNotEqualUnstableStruct:
+ description: "This struct contains a field whose old and new type have a
+ bson_serialization_type that contains 'any' and the serializers are
+ not equal and where the old field is unstable"
+ fields:
+ serializerNotEqualStructUnstableField:
+ optional: true
+ type: bsonSerializationTypeAnySerializerNotEqual
+
+ DeserializerNotEqualUnstableStruct:
+ description: "This struct contains a field whose old and new type have a
+ bson_serialization_type that contains 'any' and the deserializers are
+ not equal and where the old field is unstable"
+ fields:
+ deserializerNotEqualStructUnstableField:
+ optional: true
+ type: bsonSerializationTypeAnyDeserializerNotEqual
+
StructFieldTypeRecursiveReplyOne:
- description: "This reply contains a field whose new type is a struct that is not
+ description: "This reply contains a field whose new type is a struct that is not
compatible with the old field type"
fields:
structReplyField:
type: UnstableNewFieldReply
-
+
StructFieldTypeRecursiveReplyTwo:
- description: "This reply contains a field whose new type is a struct that is not
+ description: "This reply contains a field whose new type is a struct that is not
compatible with the old field type"
fields:
structReplyField:
type: StructType
StructType:
- description: "This struct contains a field whose new type is incompatible with the
+ description: "This struct contains a field whose new type is incompatible with the
old field type"
fields:
fieldOne:
type: BsonNotSubsetReply
-
+
NewVariantTypeReply:
description: "This reply contains a new field that has a variant type while the old field
is not a variant type"
fields:
newVariantTypeReplyField:
- type:
+ type:
variant: [int, string]
NewVariantNotSubsetReply:
@@ -365,7 +433,7 @@ structs:
of the old variant types"
fields:
variantNotSubsetReplyField:
- type:
+ type:
variant: [int, bool, string]
NewVariantNotSubsetReplyWithArray:
@@ -373,7 +441,7 @@ structs:
of the old variant types"
fields:
variantNotSubsetReplyField:
- type:
+ type:
variant: [array<int>, array<bool>, array<string>]
NewVariantNotSubsetReplyTwo:
@@ -381,7 +449,7 @@ structs:
of the old variant types"
fields:
variantNotSubsetReplyFieldTwo:
- type:
+ type:
variant: [int, bool, string, double]
NewVariantNotSubsetReplyTwoWithArray:
@@ -389,15 +457,15 @@ structs:
of the old variant types"
fields:
variantNotSubsetReplyFieldTwo:
- type:
+ type:
variant: [array<int>, array<bool>, array<string>, array<double>]
-
+
VariantRecursiveReply:
description: "This reply contains a field that has a new variant type that is not
compatible with the old variant type"
fields:
variantRecursiveReplyField:
- type:
+ type:
variant: [int, intStringToIntStringBool]
VariantRecursiveReplyWithArray:
@@ -405,15 +473,15 @@ structs:
compatible with the old variant type"
fields:
variantRecursiveReplyField:
- type:
+ type:
variant: [array<int>, array<intStringToIntStringBool>]
-
+
NewVariantStructNotSubsetReply:
description: "This reply contains a field whose new variant types are not a subset
of the old variant types"
fields:
variantStructNotSubsetReplyField:
- type:
+ type:
variant: [int, string, StructType]
NewVariantStructNotSubsetReplyWithArray:
@@ -421,23 +489,23 @@ structs:
of the old variant types"
fields:
variantStructNotSubsetReplyField:
- type:
+ type:
variant: [array<int>, array<string>, array<StructType>]
-
+
VariantStructRecursiveReply:
description: "This reply contains a field that has a new variant struct type that is not
compatible with the old variant struct type"
fields:
variantStructRecursiveReplyField:
- type:
+ type:
variant: [int, StructFieldTypeRecursiveReplyTwo]
-
+
VariantStructRecursiveReplyWithArray:
description: "This reply contains a field that has a new variant struct type that is not
compatible with the old variant struct type"
fields:
variantStructRecursiveReplyField:
- type:
+ type:
variant: [array<int>, array<StructFieldTypeRecursiveReplyTwo>]
CommandParamStructRecursiveOne:
@@ -507,7 +575,7 @@ structs:
of the old variant types"
fields:
variantNotSupersetField:
- type:
+ type:
variant: [int, bool]
VariantNotSupersetStructWithArray:
@@ -515,7 +583,7 @@ structs:
of the old variant types"
fields:
variantNotSupersetField:
- type:
+ type:
variant: [array<int>, array<bool>]
VariantNotSupersetStructTwo:
@@ -523,7 +591,7 @@ structs:
of the old variant types"
fields:
variantNotSupersetFieldTwo:
- type:
+ type:
variant: [int, bool]
VariantNotSupersetStructTwoWithArray:
@@ -531,7 +599,7 @@ structs:
of the old variant types"
fields:
variantNotSupersetFieldTwo:
- type:
+ type:
variant: [array<int>, array<bool>]
NewTypeNotVariantStruct:
@@ -546,7 +614,7 @@ structs:
compatible with the old variant types"
fields:
variantRecursiveField:
- type:
+ type:
variant: [int, intStringBoolToIntString]
VariantRecursiveStructWithArray:
@@ -554,7 +622,7 @@ structs:
compatible with the old variant types"
fields:
variantRecursiveField:
- type:
+ type:
variant: [array<int>, array<intStringBoolToIntString>]
VariantStructNotSupersetStruct:
@@ -562,7 +630,7 @@ structs:
while the new one does not"
fields:
variantStructNotSupersetField:
- type:
+ type:
variant: [int, string]
VariantStructNotSupersetStructWithArray:
@@ -570,7 +638,7 @@ structs:
while the new one does not"
fields:
variantStructNotSupersetField:
- type:
+ type:
variant: [array<int>, array<string>]
VariantStructRecursiveStruct:
@@ -637,7 +705,7 @@ commands:
strict: true
api_version: "1"
reply_type: OkReply
-
+
removedCommandParameter:
description: "parameter will be removed from command in compatibility_test_fail/new
which results in an error"
@@ -784,6 +852,34 @@ commands:
cppTypeNotEqualParam:
type: bsonSerializationTypeAnyCppTypeNotEqual
+ commandParameterSerializerNotEqual:
+ description: "command fails because it has a parameter type that has a
+ bson_serialization_type that contains 'any' and where the serializers
+ are not equal"
+ command_name: commandParameterSerializerNotEqual
+ namespace: ignored
+ cpp_name: commandParameterSerializerNotEqual
+ strict: true
+ api_version: "1"
+ reply_type: OkReply
+ fields:
+ serializerNotEqualParam:
+ type: bsonSerializationTypeAnySerializerNotEqual
+
+ commandParameterDeserializerNotEqual:
+ description: "command fails because it has a parameter type that has a
+ bson_serialization_type that contains 'any' and where the deserializers
+ are not equal"
+ command_name: commandParameterDeserializerNotEqual
+ namespace: ignored
+ cpp_name: commandParameterDeserializerNotEqual
+ strict: true
+ api_version: "1"
+ reply_type: OkReply
+ fields:
+ deserializerNotEqualParam:
+ type: bsonSerializationTypeAnyDeserializerNotEqual
+
oldCommandParamTypeBsonAnyUnstable:
description: "old command fails because it has a parameter type that has a
bson_serialization_type that contains 'any' and the old param is unstable"
@@ -842,6 +938,36 @@ commands:
type: bsonSerializationTypeAnyCppTypeNotEqual
optional: true
+ commandParameterSerializerNotEqualUnstable:
+ description: "command fails because it has a parameter type that has a
+ bson_serialization_type that contains 'any' and where the serializers
+ are not equal"
+ command_name: commandParameterSerializerNotEqualUnstable
+ namespace: ignored
+ cpp_name: commandParameterSerializerNotEqualUnstable
+ strict: true
+ api_version: "1"
+ reply_type: OkReply
+ fields:
+ serializerNotEqualParam:
+ type: bsonSerializationTypeAnySerializerNotEqual
+ optional: true
+
+ commandParameterDeserializerNotEqualUnstable:
+ description: "command fails because it has a parameter type that has a
+ bson_serialization_type that contains 'any' and where the deserializers
+ are not equal"
+ command_name: commandParameterDeserializerNotEqualUnstable
+ namespace: ignored
+ cpp_name: commandParameterDeserializerNotEqualUnstable
+ strict: true
+ api_version: "1"
+ reply_type: OkReply
+ fields:
+ deserializerNotEqualParam:
+ type: bsonSerializationTypeAnyDeserializerNotEqual
+ optional: true
+
parameterFieldTypeBsonAnyWithVariantUnstable:
description: "command fails when its paramter field variant types have bson_serialization_type
'any' that is not compatible with each other"
@@ -1040,7 +1166,7 @@ commands:
strict: true
api_version: "1"
reply_type: UnstableNewFieldReply
-
+
newReplyFieldOptional:
description: "new command fails because it contains an optional reply field that is
required in the corresponding old command"
@@ -1211,8 +1337,8 @@ commands:
strict: true
api_version: "1"
reply_type: OkReply
- fields:
- variantAnyField:
+ fields:
+ variantAnyField:
type: BsonSerializationTypeWithVariantAnyStruct
parameterFieldTypeBsonAnyWithVariantWithArray:
@@ -1224,8 +1350,8 @@ commands:
strict: true
api_version: "1"
reply_type: OkReply
- fields:
- variantAnyField:
+ fields:
+ variantAnyField:
type: BsonSerializationTypeWithVariantAnyStructWithArray
commandTypeBsonAnyWithVariant:
@@ -1260,6 +1386,26 @@ commands:
api_version: "1"
reply_type: CppTypeNotEqualReply
+ replyFieldSerializerNotEqual:
+ description: "command fails because its reply field type has a bson_serialization_type
+ that contains 'any', and the serializers are not equal"
+ command_name: replyFieldSerializerNotEqual
+ namespace: ignored
+ cpp_name: replyFieldSerializerNotEqual
+ strict: true
+ api_version: "1"
+ reply_type: SerializerNotEqualReply
+
+ replyFieldDeserializerNotEqual:
+ description: "command fails because its reply field type has a bson_serialization_type
+ that contains 'any', and the deserializers are not equal"
+ command_name: replyFieldDeserializerNotEqual
+ namespace: ignored
+ cpp_name: replyFieldDeserializerNotEqual
+ strict: true
+ api_version: "1"
+ reply_type: DeserializerNotEqualReply
+
newReplyFieldTypeStructRecursiveOne:
description: "new command fails because its reply field type is a struct that is
incompatible with the old reply field type struct"
@@ -1385,6 +1531,28 @@ commands:
api_version: "1"
reply_type: OkReply
+ commandSerializerNotEqual:
+ description: "command fails because its type has a bson_serialization_type
+ that contains 'any' and the serializers are not equal"
+ command_name: commandSerializerNotEqual
+ namespace: type
+ type: bsonSerializationTypeAnySerializerNotEqual
+ cpp_name: commandSerializerNotEqual
+ strict: true
+ api_version: "1"
+ reply_type: OkReply
+
+ commandDeserializerNotEqual:
+ description: "command fails because its type has a bson_serialization_type
+ that contains 'any' and the deserializers are not equal"
+ command_name: commandDeserializerNotEqual
+ namespace: type
+ type: bsonSerializationTypeAnyDeserializerNotEqual
+ cpp_name: commandDeserializerNotEqual
+ strict: true
+ api_version: "1"
+ reply_type: OkReply
+
oldTypeBsonAnyUnstable:
description: "old command fails because its type has a bson_serialization_type
that contains 'any' and the old type field is unstable"
@@ -1420,7 +1588,8 @@ commands:
commandCppTypeNotEqualUnstable:
description: "command fails because its type has a bson_serialization_type
- that contains 'any' and the cpp_types are not equal and the old type field is unstable"
+ that contains 'any' and the cpp_types are not equal and the
+ old type field is unstable"
command_name: commandCppTypeNotEqualUnstable
namespace: type
type: CppTypeNotEqualUnstableStruct
@@ -1429,6 +1598,30 @@ commands:
api_version: "1"
reply_type: OkReply
+ commandSerializerNotEqualUnstable:
+ description: "command fails because its type has a bson_serialization_type
+ that contains 'any' and the serializers are not equal and the
+ old type field is unstable"
+ command_name: commandSerializerNotEqualUnstable
+ namespace: type
+ type: SerializerNotEqualUnstableStruct
+ cpp_name: commandSerializerNotEqualUnstable
+ strict: true
+ api_version: "1"
+ reply_type: OkReply
+
+ commandDeserializerNotEqualUnstable:
+ description: "command fails because its type has a bson_serialization_type
+ that contains 'any' and the deserializers are not equal and the
+ old type field is unstable"
+ command_name: commandDeserializerNotEqualUnstable
+ namespace: type
+ type: DeserializerNotEqualUnstableStruct
+ cpp_name: commandDeserializerNotEqualUnstable
+ strict: true
+ api_version: "1"
+ reply_type: OkReply
+
commandTypeBsonAnyWithVariantUnstable:
description: "command fails when its variant types have bson_serialization_type
'any' that is not compatible with each other and the old type field is unstable"
@@ -1581,7 +1774,7 @@ commands:
strict: true
api_version: "1"
reply_type: NewVariantTypeReply
-
+
newReplyFieldVariantNotSubset:
description: "new command fails because its reply field type is a variant type that is not
a subset of the old reply field variant types"
@@ -1661,7 +1854,7 @@ commands:
strict: true
api_version: "1"
reply_type: NewVariantStructNotSubsetReplyWithArray
-
+
replyFieldVariantStructRecursive:
description: "new command fails because its reply field type has a variant
struct type that is not compatible with the old reply field variant
@@ -1672,7 +1865,7 @@ commands:
strict: true
api_version: "1"
reply_type: VariantStructRecursiveReply
-
+
replyFieldVariantStructRecursiveWithArray:
description: "new command fails because its reply field type has a variant
struct type that is not compatible with the old reply field variant
@@ -1695,7 +1888,7 @@ commands:
reply_type: OkReply
fields:
variantNotSupersetParam:
- type:
+ type:
variant: [int, bool]
newParamVariantNotSupersetWithArray:
@@ -1709,7 +1902,7 @@ commands:
reply_type: OkReply
fields:
variantNotSupersetParam:
- type:
+ type:
variant: [array<int>, array<bool>]
newParamVariantNotSupersetTwo:
@@ -1723,7 +1916,7 @@ commands:
reply_type: OkReply
fields:
variantNotSupersetParamTwo:
- type:
+ type:
variant: [int, string]
newParamVariantNotSupersetTwoWithArray:
@@ -1737,7 +1930,7 @@ commands:
reply_type: OkReply
fields:
variantNotSupersetParamTwo:
- type:
+ type:
variant: [array<int>, array<string>]
newParamTypeNotVariant:
@@ -1764,7 +1957,7 @@ commands:
reply_type: OkReply
fields:
variantRecursiveParam:
- type:
+ type:
variant: [int, intStringBoolToIntString]
newParamVariantRecursiveWithArray:
@@ -1778,7 +1971,7 @@ commands:
reply_type: OkReply
fields:
variantRecursiveParam:
- type:
+ type:
variant: [array<int>, array<intStringBoolToIntString>]
newParamVariantStructNotSuperset:
@@ -1792,7 +1985,7 @@ commands:
reply_type: OkReply
fields:
variantStructNotSupersetParam:
- type:
+ type:
variant: [int, string]
newParamVariantStructNotSupersetWithArray:
@@ -1806,7 +1999,7 @@ commands:
reply_type: OkReply
fields:
variantStructNotSupersetParam:
- type:
+ type:
variant: [array<int>, array<string>]
newParamVariantStructRecursive:
@@ -2120,7 +2313,7 @@ commands:
none: true
complexChecksNotSubset:
- description: "new command fails because the complex checks are not a subset of the
+ description: "new command fails because the complex checks are not a subset of the
old complex checks"
command_name: complexChecksNotSubset
namespace: ignored
@@ -2134,7 +2327,7 @@ commands:
- check: checkOne
complexChecksNotSubsetTwo:
- description: "new command fails because the complex checks are not a subset of the
+ description: "new command fails because the complex checks are not a subset of the
old complex checks"
command_name: complexChecksNotSubsetTwo
namespace: ignored
@@ -2289,7 +2482,8 @@ commands:
replyFieldCppTypeNotEqualUnstable:
description: "command fails because its reply field type has a bson_serialization_type
- that contains 'any', and the cpp_types are not equal and the old reply field is unstable"
+ that contains 'any', and the cpp_types are not equal and
+ the old reply field is unstable"
command_name: replyFieldCppTypeNotEqualUnstable
namespace: ignored
cpp_name: replyFieldCppTypeNotEqualUnstable
@@ -2297,6 +2491,28 @@ commands:
api_version: "1"
reply_type: CppTypeNotEqualUnstableReply
+ replyFieldSerializerNotEqualUnstable:
+ description: "command fails because its reply field type has a bson_serialization_type
+ that contains 'any', and the serializers are not equal and
+ the old reply field is unstable"
+ command_name: replyFieldSerializerNotEqualUnstable
+ namespace: ignored
+ cpp_name: replyFieldSerializerNotEqualUnstable
+ strict: true
+ api_version: "1"
+ reply_type: SerializerNotEqualUnstableReply
+
+ replyFieldDeserializerNotEqualUnstable:
+ description: "command fails because its reply field type has a bson_serialization_type
+ that contains 'any', and the deserializers are not equal and
+ the old reply field is unstable"
+ command_name: replyFieldDeserializerNotEqualUnstable
+ namespace: ignored
+ cpp_name: replyFieldDeserializerNotEqualUnstable
+ strict: true
+ api_version: "1"
+ reply_type: DeserializerNotEqualUnstableReply
+
newlyAddedReplyFieldTypeBsonAnyNotAllowed:
description: "command fails because it has a newly added reply field type has a bson_serialization_type
that contains 'any' that is not explicitly allowed"
diff --git a/buildscripts/idl/tests/compatibility_test_fail/old/compatibility_test_fail_old.idl b/buildscripts/idl/tests/compatibility_test_fail/old/compatibility_test_fail_old.idl
index 4d29cdfe451..dabaeccbddc 100644
--- a/buildscripts/idl/tests/compatibility_test_fail/old/compatibility_test_fail_old.idl
+++ b/buildscripts/idl/tests/compatibility_test_fail/old/compatibility_test_fail_old.idl
@@ -61,7 +61,7 @@ types:
- int
description: "The new bson_serialization_type contains 'any'"
cpp_type: "std::int32_t"
-
+
bsonSerializationTypeAny:
bson_serialization_type:
- int
@@ -76,6 +76,24 @@ types:
description: "The old and new bson_serialization_type contains 'any'"
cpp_type: "std::int64_t"
+ bsonSerializationTypeAnySerializerNotEqual:
+ bson_serialization_type:
+ - int
+ - any
+ description: "The old and new bson_serialization_type contains 'any'. The 'serializer'
+ field value here is different from the one defined in new."
+ cpp_type: "std::int64_t"
+ serializer: ::mongo::oldSerializer
+
+ bsonSerializationTypeAnyDeserializerNotEqual:
+ bson_serialization_type:
+ - int
+ - any
+ description: "The old and new bson_serialization_type contains 'any'. The 'deserializer'
+ field value here is different from the one defined in new."
+ cpp_type: "std::int64_t"
+ deserializer: ::mongo::oldDeserializer
+
intStringBoolToIntString:
bson_serialization_type:
- int
@@ -96,13 +114,13 @@ types:
enums:
NewReplyFieldEnumNotSubset:
- description: "The new reply type is an enum that is not a subset of the old reply type's
+ description: "The new reply type is an enum that is not a subset of the old reply type's
enum values"
type: string
values:
valueOne: "one"
valueTwo: "two"
-
+
EnumNotSuperset:
description: "The new enum is not a superset of the old enum values"
type: string
@@ -128,7 +146,7 @@ structs:
fields:
optionalNewField:
type: string
-
+
RequiredNewField:
description: "This struct contains a field that is optional in the old command but is
required in the new command."
@@ -136,7 +154,7 @@ structs:
requiredNewField:
type: string
optional: true
-
+
MissingNewFieldReply:
description: "This reply contains a field that exists in the old command but is
missing in the new command."
@@ -204,15 +222,15 @@ structs:
type: newBsonSerializationTypeAny
BsonSerializationTypeAnyReply:
- description: "This reply contains a field whose old and new type have a bson_serialization_type
- that contains 'any' that is not explicitly allowed"
+ description: "This reply contains a field whose old and new type have a
+ bson_serialization_type that contains 'any' that is not explicitly allowed"
fields:
bsonSerializationTypeAnyReplyField:
type: bsonSerializationTypeAny
NewlyAddedBsonSerializationTypeAnyReply:
- description: "This reply contains a newly added field whose type has a bson_serialization_type
- that contains 'any' that is not explicitly allowed"
+ description: "This reply contains a newly added field whose type has a
+ bson_serialization_type that contains 'any' that is not explicitly allowed"
OldBsonSerializationTypeAnyUnstableReply:
description: "This reply contains a field that is unstable in the old version
@@ -242,8 +260,9 @@ structs:
unstable: true
BsonSerializationTypeWithVariantAnyUnstableReply:
- description: "This reply contains a field whose old and new variant types have a bson_serialization_type
- that contains 'any' that is not compatible and where the old field is unstable"
+ description: "This reply contains a field whose old and new variant types have a
+ bson_serialization_type that contains 'any' that is not compatible
+ and where the old field is unstable"
fields:
bsonSerializationTypeWithVariantAnyUnstableReplyField:
type:
@@ -251,17 +270,35 @@ structs:
unstable: true
CppTypeNotEqualUnstableReply:
- description: "This reply contains a field whose old and new type have a bson_serialization_type
- that contains 'any' and the cpp_types are not equal and where the old field
- is unstable"
+ description: "This reply contains a field whose old and new type have a
+ bson_serialization_type that contains 'any' and the cpp_types are
+ not equal and where the old field is unstable"
fields:
cppTypeNotEqualReplyUnstableField:
type: bsonSerializationTypeAnyCppTypeNotEqual
unstable: true
+ SerializerNotEqualUnstableReply:
+ description: "This reply contains a field whose old and new type have a
+ bson_serialization_type that contains 'any' and the serializers are
+ not equal and where the old field is unstable"
+ fields:
+ serializerNotEqualReplyUnstableField:
+ type: bsonSerializationTypeAnySerializerNotEqual
+ unstable: true
+
+ DeserializerNotEqualUnstableReply:
+ description: "This reply contains a field whose old and new type have a
+ bson_serialization_type that contains 'any' and the deserializers are
+ not equal and where the old field is unstable"
+ fields:
+ deserializerNotEqualReplyUnstableField:
+ type: bsonSerializationTypeAnyDeserializerNotEqual
+ unstable: true
+
NewlyAddedBsonSerializationTypeAnyStruct:
- description: "This struct contains a newly added field whose type has a bson_serialization_type
- that contains 'any' that is not explicitly allowed"
+ description: "This struct contains a newly added field whose type has a
+ bson_serialization_type that contains 'any' that is not explicitly allowed"
fields:
newlyAddedBsonSerializationTypeAnyStructField:
unstable: true
@@ -305,17 +342,35 @@ structs:
variant: [oldBsonSerializationTypeAny, newBsonSerializationTypeAny]
CppTypeNotEqualUnstableStruct:
- description: "This struct contains a field whose old and new type have a bson_serialization_type
- that contains 'any' and the cpp_types are not equal and where the old field
- is unstable"
+ description: "This struct contains a field whose old and new type have a
+ bson_serialization_type that contains 'any' and the cpp_types are
+ not equal and where the old field is unstable"
fields:
cppTypeNotEqualStructUnstableField:
unstable: true
type: bsonSerializationTypeAnyCppTypeNotEqual
+ SerializerNotEqualUnstableStruct:
+ description: "This struct contains a field whose old and new type have a
+ bson_serialization_type that contains 'any' and the serializers are
+ not equal and where the old field is unstable"
+ fields:
+ serializerNotEqualStructUnstableField:
+ unstable: true
+ type: bsonSerializationTypeAnySerializerNotEqual
+
+ DeserializerNotEqualUnstableStruct:
+ description: "This struct contains a field whose old and new type have a
+ bson_serialization_type that contains 'any' and the deserializers are
+ not equal and where the old field is unstable"
+ fields:
+ deserializerNotEqualStructUnstableField:
+ unstable: true
+ type: bsonSerializationTypeAnyDeserializerNotEqual
+
BsonSerializationTypeWithVariantAnyStruct:
- description: "This struct contains a field whose old and new variant types have a bson_serialization_type
- that contains 'any' that is not compatible"
+ description: "This struct contains a field whose old and new variant types have a
+ bson_serialization_type that contains 'any' that is not compatible"
fields:
bsonSerializationTypeAnyStructField:
type:
@@ -331,28 +386,44 @@ structs:
array<newBsonSerializationTypeAny>]
CppTypeNotEqualReply:
- description: "This reply contains a field whose old and new type have a bson_serialization_type
- that contains 'any' and the cpp_types are not equal"
+ description: "This reply contains a field whose old and new type have a
+ bson_serialization_type that contains 'any' and the cpp_types are not equal"
fields:
cppTypeNotEqualReplyField:
type: bsonSerializationTypeAnyCppTypeNotEqual
+ SerializerNotEqualReply:
+ description: "This reply contains a field whose old and new type have a
+ bson_serialization_type that contains 'any' and
+ the serializers are not equal"
+ fields:
+ serializerNotEqualReplyField:
+ type: bsonSerializationTypeAnySerializerNotEqual
+
+ DeserializerNotEqualReply:
+ description: "This reply contains a field whose old and new type have a
+ bson_serialization_type that contains 'any' and
+ the deserializers are not equal"
+ fields:
+ deserializerNotEqualReplyField:
+ type: bsonSerializationTypeAnyDeserializerNotEqual
+
StructFieldTypeRecursiveReplyOne:
- description: "This reply contains a field whose new type is a struct that is not
+ description: "This reply contains a field whose new type is a struct that is not
compatible with the old field type"
fields:
structReplyField:
type: UnstableNewFieldReply
-
+
StructFieldTypeRecursiveReplyTwo:
- description: "This reply contains a field whose new type is a struct that is not
+ description: "This reply contains a field whose new type is a struct that is not
compatible with the old field type"
fields:
structReplyField:
type: StructType
StructType:
- description: "This struct contains a field whose new type is incompatible with the
+ description: "This struct contains a field whose new type is incompatible with the
old field type"
fields:
fieldOne:
@@ -370,23 +441,23 @@ structs:
of the old variant types"
fields:
variantNotSubsetReplyField:
- type:
+ type:
variant: [int, string]
-
+
NewVariantNotSubsetReplyWithArray:
description: "This reply contains a field whose new variant types are not a subset
of the old variant types"
fields:
variantNotSubsetReplyField:
- type:
+ type:
variant: [array<int>, array<string>]
-
+
NewVariantNotSubsetReplyTwo:
description: "This reply contains a field whose new variant types are not a subset
of the old variant types"
fields:
variantNotSubsetReplyFieldTwo:
- type:
+ type:
variant: [int, string]
NewVariantNotSubsetReplyTwoWithArray:
@@ -394,7 +465,7 @@ structs:
of the old variant types"
fields:
variantNotSubsetReplyFieldTwo:
- type:
+ type:
variant: [array<int>, array<string>]
VariantRecursiveReply:
@@ -402,15 +473,15 @@ structs:
compatible with the old variant type"
fields:
variantRecursiveReplyField:
- type:
+ type:
variant: [int, intStringToIntStringBool]
-
+
VariantRecursiveReplyWithArray:
description: "This reply contains a field that has a new variant type that is not
compatible with the old variant type"
fields:
variantRecursiveReplyField:
- type:
+ type:
variant: [array<int>, array<intStringToIntStringBool>]
NewVariantStructNotSubsetReply:
@@ -418,7 +489,7 @@ structs:
of the old variant types"
fields:
variantStructNotSubsetReplyField:
- type:
+ type:
variant: [int, string]
NewVariantStructNotSubsetReplyWithArray:
@@ -426,7 +497,7 @@ structs:
of the old variant types"
fields:
variantStructNotSubsetReplyField:
- type:
+ type:
variant: [array<int>, array<string>]
VariantStructRecursiveReply:
@@ -434,7 +505,7 @@ structs:
compatible with the old variant struct type"
fields:
variantStructRecursiveReplyField:
- type:
+ type:
variant: [int, StructFieldTypeRecursiveReplyTwo]
VariantStructRecursiveReplyWithArray:
@@ -442,7 +513,7 @@ structs:
compatible with the old variant struct type"
fields:
variantStructRecursiveReplyField:
- type:
+ type:
variant: [array<int>, array<StructFieldTypeRecursiveReplyTwo>]
CommandParamStructRecursiveOne:
@@ -501,7 +572,7 @@ structs:
of the old variant types"
fields:
variantNotSupersetField:
- type:
+ type:
variant: [int, bool, string]
VariantNotSupersetStructWithArray:
@@ -509,7 +580,7 @@ structs:
of the old variant types"
fields:
variantNotSupersetField:
- type:
+ type:
variant: [array<int>, array<bool>, array<string>]
VariantNotSupersetStructTwo:
@@ -517,7 +588,7 @@ structs:
of the old variant types"
fields:
variantNotSupersetFieldTwo:
- type:
+ type:
variant: [int, bool, string, double]
VariantNotSupersetStructTwoWithArray:
@@ -525,7 +596,7 @@ structs:
of the old variant types"
fields:
variantNotSupersetFieldTwo:
- type:
+ type:
variant: [array<int>, array<bool>, array<string>, array<double>]
NewTypeNotVariantStruct:
@@ -533,7 +604,7 @@ structs:
old one is"
fields:
variantField:
- type:
+ type:
variant: [int, bool]
VariantRecursiveStruct:
@@ -541,7 +612,7 @@ structs:
compatible with the old variant types"
fields:
variantRecursiveField:
- type:
+ type:
variant: [int, intStringBoolToIntString]
VariantRecursiveStructWithArray:
@@ -549,7 +620,7 @@ structs:
compatible with the old variant types"
fields:
variantRecursiveField:
- type:
+ type:
variant: [array<int>, array<intStringBoolToIntString>]
VariantStructNotSupersetStruct:
@@ -557,7 +628,7 @@ structs:
while the new one does not"
fields:
variantStructNotSupersetField:
- type:
+ type:
variant: [int, string, StructCommandParameterType]
VariantStructNotSupersetStructWithArray:
@@ -565,7 +636,7 @@ structs:
while the new one does not"
fields:
variantStructNotSupersetField:
- type:
+ type:
variant: [array<int>, array<string>, array<StructCommandParameterType>]
VariantStructRecursiveStruct:
@@ -611,7 +682,7 @@ commands:
reply_type: OkReply
removedCommand:
- description: "command will be removed from compatibility_test_fail/new which results
+ description: "command will be removed from compatibility_test_fail/new which results
in an error"
command_name: removedCommand
namespace: ignored
@@ -775,6 +846,34 @@ commands:
cppTypeNotEqualParam:
type: bsonSerializationTypeAnyCppTypeNotEqual
+ commandParameterSerializerNotEqual:
+ description: "command fails because it has a parameter type that has a
+ bson_serialization_type that contains 'any' and where the serializers
+ are not equal"
+ command_name: commandParameterSerializerNotEqual
+ namespace: ignored
+ cpp_name: commandParameterSerializerNotEqual
+ strict: true
+ api_version: "1"
+ reply_type: OkReply
+ fields:
+ serializerNotEqualParam:
+ type: bsonSerializationTypeAnySerializerNotEqual
+
+ commandParameterDeserializerNotEqual:
+ description: "command fails because it has a parameter type that has a
+ bson_serialization_type that contains 'any' and where the deserializers
+ are not equal"
+ command_name: commandParameterDeserializerNotEqual
+ namespace: ignored
+ cpp_name: commandParameterDeserializerNotEqual
+ strict: true
+ api_version: "1"
+ reply_type: OkReply
+ fields:
+ deserializerNotEqualParam:
+ type: bsonSerializationTypeAnyDeserializerNotEqual
+
oldCommandParamTypeBsonAnyUnstable:
description: "old command fails because it has a parameter type that has a
bson_serialization_type that contains 'any' and the old param is unstable"
@@ -833,6 +932,36 @@ commands:
type: bsonSerializationTypeAnyCppTypeNotEqual
unstable: true
+ commandParameterSerializerNotEqualUnstable:
+ description: "command fails because it has a parameter type that has a
+ bson_serialization_type that contains 'any' and where the serializers
+ are not equal"
+ command_name: commandParameterSerializerNotEqualUnstable
+ namespace: ignored
+ cpp_name: commandParameterSerializerNotEqualUnstable
+ strict: true
+ api_version: "1"
+ reply_type: OkReply
+ fields:
+ serializerNotEqualParam:
+ type: bsonSerializationTypeAnySerializerNotEqual
+ unstable: true
+
+ commandParameterDeserializerNotEqualUnstable:
+ description: "command fails because it has a parameter type that has a
+ bson_serialization_type that contains 'any' and where the deserializers
+ are not equal"
+ command_name: commandParameterDeserializerNotEqualUnstable
+ namespace: ignored
+ cpp_name: commandParameterDeserializerNotEqualUnstable
+ strict: true
+ api_version: "1"
+ reply_type: OkReply
+ fields:
+ deserializerNotEqualParam:
+ type: bsonSerializationTypeAnyDeserializerNotEqual
+ unstable: true
+
parameterFieldTypeBsonAnyWithVariantUnstable:
description: "command fails when its paramter field variant types have bson_serialization_type
'any' that is not compatible with each other"
@@ -895,7 +1024,7 @@ commands:
fields:
newParamNotStruct:
type: StructCommandParameterType
-
+
newCommandParameterTypeEnumOrStructOne:
description: "new command fails because its parameter type is an enum while the
parameter type in the old command is an non-enum or non-struct"
@@ -1025,7 +1154,7 @@ commands:
strict: true
api_version: "1"
reply_type: UnstableNewFieldReply
-
+
newReplyFieldOptional:
description: "new command fails because it contains an optional reply field that is
required in the corresponding old command"
@@ -1045,7 +1174,7 @@ commands:
strict: true
api_version: "1"
reply_type: MissingNewFieldReply
-
+
importedReplyCommand:
description: "reply is imported and should fail"
command_name: importedReplyCommand
@@ -1196,8 +1325,8 @@ commands:
strict: true
api_version: "1"
reply_type: OkReply
- fields:
- variantAnyField:
+ fields:
+ variantAnyField:
type: BsonSerializationTypeWithVariantAnyStruct
parameterFieldTypeBsonAnyWithVariantWithArray:
@@ -1209,8 +1338,8 @@ commands:
strict: true
api_version: "1"
reply_type: OkReply
- fields:
- variantAnyField:
+ fields:
+ variantAnyField:
type: BsonSerializationTypeWithVariantAnyStructWithArray
commandTypeBsonAnyWithVariant:
@@ -1234,7 +1363,7 @@ commands:
strict: true
api_version: "1"
reply_type: OkReply
-
+
replyFieldCppTypeNotEqual:
description: "command fails because its reply field type has a bson_serialization_type
that contains 'any', and the cpp_types are not equal"
@@ -1245,6 +1374,26 @@ commands:
api_version: "1"
reply_type: CppTypeNotEqualReply
+ replyFieldSerializerNotEqual:
+ description: "command fails because its reply field type has a bson_serialization_type
+ that contains 'any', and the serializers are not equal"
+ command_name: replyFieldSerializerNotEqual
+ namespace: ignored
+ cpp_name: replyFieldSerializerNotEqual
+ strict: true
+ api_version: "1"
+ reply_type: SerializerNotEqualReply
+
+ replyFieldDeserializerNotEqual:
+ description: "command fails because its reply field type has a bson_serialization_type
+ that contains 'any', and the deserializers are not equal"
+ command_name: replyFieldDeserializerNotEqual
+ namespace: ignored
+ cpp_name: replyFieldDeserializerNotEqual
+ strict: true
+ api_version: "1"
+ reply_type: DeserializerNotEqualReply
+
oldReplyFieldTypeBsonAnyUnstable:
description: "old command fails when its reply field type has a bson_serialization_type
that contains 'any' and the old reply field is unstable"
@@ -1287,7 +1436,8 @@ commands:
replyFieldCppTypeNotEqualUnstable:
description: "command fails because its reply field type has a bson_serialization_type
- that contains 'any', and the cpp_types are not equal and the old reply field is unstable"
+ that contains 'any', and the cpp_types are not equal and
+ the old reply field is unstable"
command_name: replyFieldCppTypeNotEqualUnstable
namespace: ignored
cpp_name: replyFieldCppTypeNotEqualUnstable
@@ -1295,9 +1445,31 @@ commands:
api_version: "1"
reply_type: CppTypeNotEqualUnstableReply
+ replyFieldSerializerNotEqualUnstable:
+ description: "command fails because its reply field type has a bson_serialization_type
+ that contains 'any', and the serializers are not equal and
+ the old reply field is unstable"
+ command_name: replyFieldSerializerNotEqualUnstable
+ namespace: ignored
+ cpp_name: replyFieldSerializerNotEqualUnstable
+ strict: true
+ api_version: "1"
+ reply_type: SerializerNotEqualUnstableReply
+
+ replyFieldDeserializerNotEqualUnstable:
+ description: "command fails because its reply field type has a bson_serialization_type
+ that contains 'any', and the deserializers are not equal and
+ the old reply field is unstable"
+ command_name: replyFieldDeserializerNotEqualUnstable
+ namespace: ignored
+ cpp_name: replyFieldDeserializerNotEqualUnstable
+ strict: true
+ api_version: "1"
+ reply_type: DeserializerNotEqualUnstableReply
+
newlyAddedReplyFieldTypeBsonAnyNotAllowed:
- description: "command fails because it has a newly added reply field type has a bson_serialization_type
- that contains 'any' that is not explicitly allowed"
+ description: "command fails because it has a newly added reply field type has a
+ bson_serialization_type that contains 'any' that is not explicitly allowed"
command_name: newlyAddedReplyFieldTypeBsonAnyNotAllowed
namespace: ignored
cpp_name: newlyAddedReplyFieldTypeBsonAnyNotAllowed
@@ -1430,6 +1602,28 @@ commands:
api_version: "1"
reply_type: OkReply
+ commandSerializerNotEqual:
+ description: "command fails because its type has a bson_serialization_type
+ that contains 'any' and the serializers are not equal"
+ command_name: commandSerializerNotEqual
+ namespace: type
+ type: bsonSerializationTypeAnySerializerNotEqual
+ cpp_name: commandSerializerNotEqual
+ strict: true
+ api_version: "1"
+ reply_type: OkReply
+
+ commandDeserializerNotEqual:
+ description: "command fails because its type has a bson_serialization_type
+ that contains 'any' and the deserializers are not equal"
+ command_name: commandDeserializerNotEqual
+ namespace: type
+ type: bsonSerializationTypeAnyDeserializerNotEqual
+ cpp_name: commandDeserializerNotEqual
+ strict: true
+ api_version: "1"
+ reply_type: OkReply
+
oldTypeBsonAnyUnstable:
description: "old command fails because its type has a bson_serialization_type
that contains 'any' and the old type field is unstable"
@@ -1465,7 +1659,8 @@ commands:
commandCppTypeNotEqualUnstable:
description: "command fails because its type has a bson_serialization_type
- that contains 'any' and the cpp_types are not equal and the old type field is unstable"
+ that contains 'any' and the cpp_types are not equal and
+ the old type field is unstable"
command_name: commandCppTypeNotEqualUnstable
namespace: type
type: CppTypeNotEqualUnstableStruct
@@ -1474,9 +1669,34 @@ commands:
api_version: "1"
reply_type: OkReply
+ commandSerializerNotEqualUnstable:
+ description: "command fails because its type has a bson_serialization_type
+ that contains 'any' and the serializers are not equal and
+ the old type field is unstable"
+ command_name: commandSerializerNotEqualUnstable
+ namespace: type
+ type: SerializerNotEqualUnstableStruct
+ cpp_name: commandSerializerNotEqualUnstable
+ strict: true
+ api_version: "1"
+ reply_type: OkReply
+
+ commandDeserializerNotEqualUnstable:
+ description: "command fails because its type has a bson_serialization_type
+ that contains 'any' and the deserializers are not equal and
+ the old type field is unstable"
+ command_name: commandDeserializerNotEqualUnstable
+ namespace: type
+ type: DeserializerNotEqualUnstableStruct
+ cpp_name: commandDeserializerNotEqualUnstable
+ strict: true
+ api_version: "1"
+ reply_type: OkReply
+
commandTypeBsonAnyWithVariantUnstable:
description: "command fails when its variant types have bson_serialization_type
- 'any' that is not compatible with each other and the old type field is unstable"
+ 'any' that is not compatible with each other and
+ the old type field is unstable"
command_name: commandTypeBsonAnyWithVariantUnstable
namespace: type
type: BsonSerializationTypeWithVariantAnyUnstableStruct
@@ -1594,7 +1814,7 @@ commands:
strict: true
api_version: "1"
reply_type: OkReply
-
+
newTypeFieldAddedRequired:
description: "new command fails because it has an added type field that is required
when it should be optional"
@@ -1626,7 +1846,7 @@ commands:
strict: true
api_version: "1"
reply_type: NewVariantTypeReply
-
+
newReplyFieldVariantNotSubset:
description: "new command fails because its reply field type is a variant type that is not
a subset of the old reply field variant types"
@@ -1740,7 +1960,7 @@ commands:
reply_type: OkReply
fields:
variantNotSupersetParam:
- type:
+ type:
variant: [int, bool, string]
newParamVariantNotSupersetWithArray:
@@ -1754,7 +1974,7 @@ commands:
reply_type: OkReply
fields:
variantNotSupersetParam:
- type:
+ type:
variant: [array<int>, array<bool>, array<string>]
newParamVariantNotSupersetTwo:
@@ -1768,7 +1988,7 @@ commands:
reply_type: OkReply
fields:
variantNotSupersetParamTwo:
- type:
+ type:
variant: [int, bool, string, double]
newParamVariantNotSupersetTwoWithArray:
@@ -1782,7 +2002,7 @@ commands:
reply_type: OkReply
fields:
variantNotSupersetParamTwo:
- type:
+ type:
variant: [array<int>, array<bool>, array<string>, array<double>]
newParamTypeNotVariant:
@@ -1796,7 +2016,7 @@ commands:
reply_type: OkReply
fields:
variantParam:
- type:
+ type:
variant: [int, bool]
newParamVariantRecursive:
@@ -1810,7 +2030,7 @@ commands:
reply_type: OkReply
fields:
variantRecursiveParam:
- type:
+ type:
variant: [int, intStringBoolToIntString]
newParamVariantRecursiveWithArray:
@@ -1824,7 +2044,7 @@ commands:
reply_type: OkReply
fields:
variantRecursiveParam:
- type:
+ type:
variant: [array<int>, array<intStringBoolToIntString>]
newParamVariantStructNotSuperset:
@@ -1838,7 +2058,7 @@ commands:
reply_type: OkReply
fields:
variantStructNotSupersetParam:
- type:
+ type:
variant: [int, string, StructCommandParameterType]
newParamVariantStructNotSupersetWithArray:
@@ -1852,7 +2072,7 @@ commands:
reply_type: OkReply
fields:
variantStructNotSupersetParam:
- type:
+ type:
variant: [array<int>, array<string>, array<StructCommandParameterType>]
newParamVariantStructRecursive:
@@ -2167,7 +2387,7 @@ commands:
- check: checkOne
complexChecksNotSubset:
- description: "new command fails because the complex checks are not a subset of the
+ description: "new command fails because the complex checks are not a subset of the
old complex checks"
command_name: complexChecksNotSubset
namespace: ignored
@@ -2181,7 +2401,7 @@ commands:
- check: checkTwo
complexChecksNotSubsetTwo:
- description: "new command fails because the complex checks are not a subset of the
+ description: "new command fails because the complex checks are not a subset of the
old complex checks"
command_name: complexChecksNotSubsetTwo
namespace: ignored
diff --git a/buildscripts/idl/tests/test_compatibility.py b/buildscripts/idl/tests/test_compatibility.py
index 89a4e6130c6..56cf3e68408 100644
--- a/buildscripts/idl/tests/test_compatibility.py
+++ b/buildscripts/idl/tests/test_compatibility.py
@@ -92,7 +92,7 @@ class TestIDLCompatibilityChecker(unittest.TestCase):
path.join(dir_path, "compatibility_test_fail/new"), ["src"])
self.assertTrue(error_collection.has_errors())
- self.assertTrue(error_collection.count() == 164)
+ self.assertEqual(error_collection.count(), 170)
invalid_api_version_new_error = error_collection.get_error_by_command_name(
"invalidAPIVersionNew")
@@ -212,6 +212,21 @@ class TestIDLCompatibilityChecker(unittest.TestCase):
self.assertRegex(
str(command_parameter_cpp_type_not_equal_error), "commandParameterCppTypeNotEqual")
+ command_parameter_serializer_not_equal_error = error_collection.get_error_by_command_name(
+ "commandParameterSerializerNotEqual")
+ self.assertEqual(command_parameter_serializer_not_equal_error.error_id,
+ idl_compatibility_errors.ERROR_ID_COMMAND_PARAMETER_SERIALIZER_NOT_EQUAL)
+ self.assertRegex(
+ str(command_parameter_serializer_not_equal_error), "commandParameterSerializerNotEqual")
+
+ command_parameter_deserializer_not_equal_error = error_collection.get_error_by_command_name(
+ "commandParameterDeserializerNotEqual")
+ self.assertTrue(command_parameter_deserializer_not_equal_error.error_id ==
+ idl_compatibility_errors.ERROR_ID_COMMAND_PARAMETER_DESERIALIZER_NOT_EQUAL)
+ self.assertRegex(
+ str(command_parameter_deserializer_not_equal_error),
+ "commandParameterDeserializerNotEqual")
+
old_command_parameter_type_bson_any_unstable_error = error_collection.get_error_by_command_name(
"oldCommandParamTypeBsonAnyUnstable")
self.assertTrue(
@@ -612,6 +627,20 @@ class TestIDLCompatibilityChecker(unittest.TestCase):
idl_compatibility_errors.ERROR_ID_REPLY_FIELD_CPP_TYPE_NOT_EQUAL)
self.assertRegex(str(reply_field_cpp_type_not_equal_error), "replyFieldCppTypeNotEqual")
+ reply_field_serializer_not_equal_error = error_collection.get_error_by_command_name(
+ "replyFieldSerializerNotEqual")
+ self.assertTrue(reply_field_serializer_not_equal_error.error_id ==
+ idl_compatibility_errors.ERROR_ID_REPLY_FIELD_SERIALIZER_NOT_EQUAL)
+ self.assertRegex(
+ str(reply_field_serializer_not_equal_error), "replyFieldSerializerNotEqual")
+
+ reply_field_deserializer_not_equal_error = error_collection.get_error_by_command_name(
+ "replyFieldDeserializerNotEqual")
+ self.assertTrue(reply_field_deserializer_not_equal_error.error_id ==
+ idl_compatibility_errors.ERROR_ID_REPLY_FIELD_DESERIALIZER_NOT_EQUAL)
+ self.assertRegex(
+ str(reply_field_deserializer_not_equal_error), "replyFieldDeserializerNotEqual")
+
new_reply_field_type_struct_one_error = error_collection.get_error_by_command_name(
"newReplyFieldTypeStructRecursiveOne")
self.assertTrue(new_reply_field_type_struct_one_error.error_id ==
@@ -687,6 +716,18 @@ class TestIDLCompatibilityChecker(unittest.TestCase):
idl_compatibility_errors.ERROR_ID_COMMAND_CPP_TYPE_NOT_EQUAL)
self.assertRegex(str(command_cpp_type_not_equal_error), "commandCppTypeNotEqual")
+ command_serializer_not_equal_error = error_collection.get_error_by_command_name(
+ "commandSerializerNotEqual")
+ self.assertTrue(command_serializer_not_equal_error.error_id ==
+ idl_compatibility_errors.ERROR_ID_COMMAND_SERIALIZER_NOT_EQUAL)
+ self.assertRegex(str(command_serializer_not_equal_error), "commandSerializerNotEqual")
+
+ command_deserializer_not_equal_error = error_collection.get_error_by_command_name(
+ "commandDeserializerNotEqual")
+ self.assertTrue(command_deserializer_not_equal_error.error_id ==
+ idl_compatibility_errors.ERROR_ID_COMMAND_DESERIALIZER_NOT_EQUAL)
+ self.assertRegex(str(command_deserializer_not_equal_error), "commandDeserializerNotEqual")
+
old_type_bson_any_unstable_error = error_collection.get_error_by_command_name(
"oldTypeBsonAnyUnstable")
self.assertTrue(old_type_bson_any_unstable_error.error_id == idl_compatibility_errors.
diff --git a/src/mongo/db/ops/write_ops.cpp b/src/mongo/db/ops/write_ops.cpp
index 8e00f19713a..f69ad8844bb 100644
--- a/src/mongo/db/ops/write_ops.cpp
+++ b/src/mongo/db/ops/write_ops.cpp
@@ -79,6 +79,10 @@ void checkOpCountForCommand(const T& op, size_t numOps) {
namespace write_ops {
+/**
+ * IMPORTANT: The method should not be modified, as API version input/output guarantees could
+ * break because of it.
+ */
bool readMultiDeleteProperty(const BSONElement& limitElement) {
// Using a double to avoid throwing away illegal fractional portion. Don't want to accept 0.5
// here
@@ -90,6 +94,10 @@ bool readMultiDeleteProperty(const BSONElement& limitElement) {
return limit == 0;
}
+/**
+ * IMPORTANT: The method should not be modified, as API version input/output guarantees could
+ * break because of it.
+ */
void writeMultiDeleteProperty(bool isMulti, StringData fieldName, BSONObjBuilder* builder) {
builder->append(fieldName, isMulti ? 0 : 1);
}
@@ -328,6 +336,10 @@ write_ops::UpdateModification::UpdateModification(const BSONObj& update, Classic
write_ops::UpdateModification::UpdateModification(std::vector<BSONObj> pipeline)
: _update{PipelineUpdate{std::move(pipeline)}} {}
+/**
+ * IMPORTANT: The method should not be modified, as API version input/output guarantees could
+ * break because of it.
+ */
write_ops::UpdateModification write_ops::UpdateModification::parseFromBSON(BSONElement elem) {
return UpdateModification(elem);
}
@@ -363,6 +375,10 @@ write_ops::UpdateModification::Type write_ops::UpdateModification::type() const
_update);
}
+/**
+ * IMPORTANT: The method should not be modified, as API version input/output guarantees could
+ * break because of it.
+ */
void write_ops::UpdateModification::serializeToBSON(StringData fieldName,
BSONObjBuilder* bob) const {
diff --git a/src/mongo/db/ops/write_ops_parsers.h b/src/mongo/db/ops/write_ops_parsers.h
index 20b9f543bc7..900740b271b 100644
--- a/src/mongo/db/ops/write_ops_parsers.h
+++ b/src/mongo/db/ops/write_ops_parsers.h
@@ -51,11 +51,17 @@ constexpr int kRetryableAndTxnBatchWriteBSONSizeOverhead =
/**
* Parses the 'limit' property of a delete entry, which has inverted meaning from the 'multi'
* property of an update.
+ *
+ * IMPORTANT: The method should not be modified, as API version input/output guarantees could
+ * break because of it.
*/
bool readMultiDeleteProperty(const BSONElement& limitElement);
/**
* Writes the 'isMulti' value as a limit property.
+ *
+ * IMPORTANT: The method should not be modified, as API version input/output guarantees could
+ * break because of it.
*/
void writeMultiDeleteProperty(bool isMulti, StringData fieldName, BSONObjBuilder* builder);
@@ -100,8 +106,16 @@ public:
/**
* These methods support IDL parsing of the "u" field from the update command and OP_UPDATE.
+ *
+ * IMPORTANT: The method should not be modified, as API version input/output guarantees could
+ * break because of it.
*/
static UpdateModification parseFromBSON(BSONElement elem);
+
+ /**
+ * IMPORTANT: The method should not be modified, as API version input/output guarantees could
+ * break because of it.
+ */
void serializeToBSON(StringData fieldName, BSONObjBuilder* bob) const;
// When parsing from legacy OP_UPDATE messages, we receive the "u" field as an object. When an
diff --git a/src/mongo/db/pipeline/aggregation_request_helper.cpp b/src/mongo/db/pipeline/aggregation_request_helper.cpp
index 133e151dae6..5bfa4b7c2a3 100644
--- a/src/mongo/db/pipeline/aggregation_request_helper.cpp
+++ b/src/mongo/db/pipeline/aggregation_request_helper.cpp
@@ -241,6 +241,10 @@ PlanExecutorPipeline::ResumableScanType getResumableScanType(const AggregateComm
// Custom serializers/deserializers for AggregateCommandRequest.
+/**
+ * IMPORTANT: The method should not be modified, as API version input/output guarantees could
+ * break because of it.
+ */
boost::optional<mongo::ExplainOptions::Verbosity> parseExplainModeFromBSON(
const BSONElement& explainElem) {
uassert(ErrorCodes::TypeMismatch,
@@ -254,6 +258,10 @@ boost::optional<mongo::ExplainOptions::Verbosity> parseExplainModeFromBSON(
return boost::none;
}
+/**
+ * IMPORTANT: The method should not be modified, as API version input/output guarantees could
+ * break because of it.
+ */
void serializeExplainToBSON(const mongo::ExplainOptions::Verbosity& explain,
StringData fieldName,
BSONObjBuilder* builder) {
@@ -264,6 +272,10 @@ void serializeExplainToBSON(const mongo::ExplainOptions::Verbosity& explain,
return;
}
+/**
+ * IMPORTANT: The method should not be modified, as API version input/output guarantees could
+ * break because of it.
+ */
mongo::SimpleCursorOptions parseAggregateCursorFromBSON(const BSONElement& cursorElem) {
if (cursorElem.eoo()) {
SimpleCursorOptions cursor;
@@ -284,6 +296,10 @@ mongo::SimpleCursorOptions parseAggregateCursorFromBSON(const BSONElement& curso
return cursor;
}
+/**
+ * IMPORTANT: The method should not be modified, as API version input/output guarantees could
+ * break because of it.
+ */
void serializeAggregateCursorToBSON(const mongo::SimpleCursorOptions& cursor,
StringData fieldName,
BSONObjBuilder* builder) {
diff --git a/src/mongo/db/pipeline/aggregation_request_helper.h b/src/mongo/db/pipeline/aggregation_request_helper.h
index 631fd87a278..bb447712f7f 100644
--- a/src/mongo/db/pipeline/aggregation_request_helper.h
+++ b/src/mongo/db/pipeline/aggregation_request_helper.h
@@ -131,23 +131,40 @@ PlanExecutorPipeline::ResumableScanType getResumableScanType(const AggregateComm
/**
* Custom serializers/deserializers for AggregateCommandRequest.
+ *
+ * IMPORTANT: The method should not be modified, as API version input/output guarantees could
+ * break because of it.
*/
-
boost::optional<mongo::ExplainOptions::Verbosity> parseExplainModeFromBSON(
const BSONElement& explainElem);
+/**
+ * IMPORTANT: The method should not be modified, as API version input/output guarantees could
+ * break because of it.
+ */
void serializeExplainToBSON(const mongo::ExplainOptions::Verbosity& explain,
StringData fieldName,
BSONObjBuilder* builder);
+/**
+ * IMPORTANT: The method should not be modified, as API version input/output guarantees could
+ * break because of it.
+ */
mongo::SimpleCursorOptions parseAggregateCursorFromBSON(const BSONElement& cursorElem);
+/**
+ * IMPORTANT: The method should not be modified, as API version input/output guarantees could
+ * break because of it.
+ */
void serializeAggregateCursorToBSON(const SimpleCursorOptions& cursor,
StringData fieldName,
BSONObjBuilder* builder);
/**
* Parse an aggregation pipeline definition from 'pipelineElem'.
+ *
+ * IMPORTANT: The method should not be modified, as API version input/output guarantees could
+ * break because of it.
*/
static std::vector<BSONObj> parsePipelineFromBSON(const BSONElement& pipelineElem) {
std::vector<BSONObj> pipeline;
diff --git a/src/mongo/db/pipeline/aggregation_request_test.cpp b/src/mongo/db/pipeline/aggregation_request_test.cpp
index 66bac44423c..947764892b7 100644
--- a/src/mongo/db/pipeline/aggregation_request_test.cpp
+++ b/src/mongo/db/pipeline/aggregation_request_test.cpp
@@ -554,6 +554,23 @@ TEST(AggregationRequestTest, ShouldRejectNoCursorNoExplain) {
aggregation_request_helper::parseFromBSONForTests(nss, cursorRequest.done()).getStatus());
}
+TEST(AggregationRequestTest, ShouldRejectNonObjectCursor) {
+ NamespaceString nss("a.collection");
+ const BSONObj validRequest = fromjson(
+ "{aggregate: 'collection',"
+ "pipeline: [{$match: {a: 'abc'}}],"
+ "cursor: {},"
+ "isMapReduceCommand: true,"
+ "$db: 'a'}");
+ const BSONObj nonObjCursorCommand = fromjson("{cursor: 1}");
+ aggregationRequestParseFailureHelper(
+ nss, validRequest, nonObjCursorCommand, ErrorCodes::TypeMismatch);
+
+ const BSONObj arrayCursorCommand = fromjson("{cursor: []}");
+ aggregationRequestParseFailureHelper(
+ nss, validRequest, arrayCursorCommand, ErrorCodes::TypeMismatch);
+}
+
TEST(AggregationRequestTest, ShouldRejectExplainTrueWithSeparateExplainArg) {
NamespaceString nss("a.collection");
const BSONObj validRequest = fromjson(
diff --git a/src/mongo/db/query/hint_parser.cpp b/src/mongo/db/query/hint_parser.cpp
index d1372d86f55..1de75b84f82 100644
--- a/src/mongo/db/query/hint_parser.cpp
+++ b/src/mongo/db/query/hint_parser.cpp
@@ -33,6 +33,10 @@
namespace mongo {
+/**
+ * IMPORTANT: The method should not be modified, as API version input/output guarantees could
+ * break because of it.
+ */
BSONObj parseHint(const BSONElement& element) {
if (element.type() == BSONType::String) {
return BSON("$hint" << element.valueStringData());
@@ -44,6 +48,10 @@ BSONObj parseHint(const BSONElement& element) {
MONGO_UNREACHABLE;
}
+/**
+ * IMPORTANT: The method should not be modified, as API version input/output guarantees could
+ * break because of it.
+ */
void serializeHintToBSON(const BSONObj& hint, StringData fieldName, BSONObjBuilder* builder) {
if (hint.isEmpty())
return;
diff --git a/src/mongo/db/query/max_time_ms_parser.cpp b/src/mongo/db/query/max_time_ms_parser.cpp
index 7f2c84f07ad..054b2b76ead 100644
--- a/src/mongo/db/query/max_time_ms_parser.cpp
+++ b/src/mongo/db/query/max_time_ms_parser.cpp
@@ -62,6 +62,10 @@ StatusWith<int> parseMaxTimeMS(BSONElement maxTimeMSElt) {
return StatusWith<int>(static_cast<int>(maxTimeMSLongLong));
}
+/**
+ * IMPORTANT: The method should not be modified, as API version input/output guarantees could
+ * break because of it.
+ */
int32_t parseMaxTimeMSForIDL(BSONElement maxTimeMSElt) {
return static_cast<int32_t>(uassertStatusOK(parseMaxTimeMS(maxTimeMSElt)));
}
diff --git a/src/mongo/db/query/max_time_ms_parser.h b/src/mongo/db/query/max_time_ms_parser.h
index 1e5ec985c77..d111b480599 100644
--- a/src/mongo/db/query/max_time_ms_parser.h
+++ b/src/mongo/db/query/max_time_ms_parser.h
@@ -56,6 +56,10 @@ static constexpr auto kMaxTimeMSOpOnlyMaxPadding = 100LL;
*/
StatusWith<int> parseMaxTimeMS(BSONElement maxTimeMSElt);
+/**
+ * IMPORTANT: The method should not be modified, as API version input/output guarantees could
+ * break because of it.
+ */
int32_t parseMaxTimeMSForIDL(BSONElement maxTimeMSElt);
} // namespace mongo
diff --git a/src/mongo/db/query/query_request_test.cpp b/src/mongo/db/query/query_request_test.cpp
index e60a04ff79e..8518c0e4661 100644
--- a/src/mongo/db/query/query_request_test.cpp
+++ b/src/mongo/db/query/query_request_test.cpp
@@ -1194,36 +1194,74 @@ TEST(QueryRequestTest, ParseFromCommandForbidExtraOption) {
TEST(QueryRequestTest, ParseMaxTimeMSStringValueFails) {
BSONObj maxTimeObj = BSON(query_request_helper::cmdOptionMaxTimeMS << "foo");
- ASSERT_NOT_OK(parseMaxTimeMS(maxTimeObj[query_request_helper::cmdOptionMaxTimeMS]));
+ ASSERT_THROWS_CODE(parseMaxTimeMSForIDL(maxTimeObj[query_request_helper::cmdOptionMaxTimeMS]),
+ DBException,
+ ErrorCodes::BadValue);
+}
+
+TEST(QueryRequestTest, ParseMaxTimeMSBoolValueFails) {
+ BSONObj maxTimeObj = BSON(query_request_helper::cmdOptionMaxTimeMS << true);
+ ASSERT_THROWS_CODE(parseMaxTimeMSForIDL(maxTimeObj[query_request_helper::cmdOptionMaxTimeMS]),
+ DBException,
+ ErrorCodes::BadValue);
+}
+
+TEST(QueryRequestTest, ParseMaxTimeMSNullValueFails) {
+ BSONObj maxTimeObj = BSON(query_request_helper::cmdOptionMaxTimeMS << BSONNULL);
+ ASSERT_THROWS_CODE(parseMaxTimeMSForIDL(maxTimeObj[query_request_helper::cmdOptionMaxTimeMS]),
+ DBException,
+ ErrorCodes::BadValue);
+}
+
+TEST(QueryRequestTest, ParseMaxTimeMSUndefinedValueFails) {
+ BSONObj maxTimeObj = BSON(query_request_helper::cmdOptionMaxTimeMS << BSONUndefined);
+ ASSERT_THROWS_CODE(parseMaxTimeMSForIDL(maxTimeObj[query_request_helper::cmdOptionMaxTimeMS]),
+ DBException,
+ ErrorCodes::BadValue);
+}
+
+TEST(QueryRequestTest, ParseMaxTimeMSEmptyObjectValueFails) {
+ const auto emptyObj = BSONObjBuilder().obj();
+ BSONObj maxTimeObj = BSON(query_request_helper::cmdOptionMaxTimeMS << emptyObj);
+ ASSERT_THROWS_CODE(parseMaxTimeMSForIDL(maxTimeObj[query_request_helper::cmdOptionMaxTimeMS]),
+ DBException,
+ ErrorCodes::BadValue);
}
TEST(QueryRequestTest, ParseMaxTimeMSNonIntegralValueFails) {
BSONObj maxTimeObj = BSON(query_request_helper::cmdOptionMaxTimeMS << 100.3);
- ASSERT_NOT_OK(parseMaxTimeMS(maxTimeObj[query_request_helper::cmdOptionMaxTimeMS]));
+ ASSERT_THROWS_CODE(parseMaxTimeMSForIDL(maxTimeObj[query_request_helper::cmdOptionMaxTimeMS]),
+ DBException,
+ ErrorCodes::BadValue);
}
TEST(QueryRequestTest, ParseMaxTimeMSOutOfRangeDoubleFails) {
BSONObj maxTimeObj = BSON(query_request_helper::cmdOptionMaxTimeMS << 1e200);
- ASSERT_NOT_OK(parseMaxTimeMS(maxTimeObj[query_request_helper::cmdOptionMaxTimeMS]));
+ ASSERT_THROWS_CODE(parseMaxTimeMSForIDL(maxTimeObj[query_request_helper::cmdOptionMaxTimeMS]),
+ DBException,
+ ErrorCodes::BadValue);
}
TEST(QueryRequestTest, ParseMaxTimeMSNegativeValueFails) {
BSONObj maxTimeObj = BSON(query_request_helper::cmdOptionMaxTimeMS << -400);
- ASSERT_NOT_OK(parseMaxTimeMS(maxTimeObj[query_request_helper::cmdOptionMaxTimeMS]));
+ ASSERT_THROWS_CODE(parseMaxTimeMSForIDL(maxTimeObj[query_request_helper::cmdOptionMaxTimeMS]),
+ DBException,
+ ErrorCodes::BadValue);
}
TEST(QueryRequestTest, ParseMaxTimeMSZeroSucceeds) {
BSONObj maxTimeObj = BSON(query_request_helper::cmdOptionMaxTimeMS << 0);
- auto maxTime = parseMaxTimeMS(maxTimeObj[query_request_helper::cmdOptionMaxTimeMS]);
- ASSERT_OK(maxTime);
- ASSERT_EQ(maxTime.getValue(), 0);
+ ASSERT_EQ(parseMaxTimeMSForIDL(maxTimeObj[query_request_helper::cmdOptionMaxTimeMS]), 0);
+}
+
+TEST(QueryRequestTest, ParseMaxTimeMSEmptyElementSucceeds) {
+ const auto emptyElem = BSONElement();
+ ASSERT_EQ(parseMaxTimeMSForIDL(emptyElem), 0);
}
TEST(QueryRequestTest, ParseMaxTimeMSPositiveInRangeSucceeds) {
BSONObj maxTimeObj = BSON(query_request_helper::cmdOptionMaxTimeMS << 300);
- auto maxTime = parseMaxTimeMS(maxTimeObj[query_request_helper::cmdOptionMaxTimeMS]);
- ASSERT_OK(maxTime);
- ASSERT_EQ(maxTime.getValue(), 300);
+ ASSERT_EQ(parseMaxTimeMSForIDL(maxTimeObj[query_request_helper::cmdOptionMaxTimeMS]), 300);
}
TEST(QueryRequestTest, ConvertToAggregationSucceeds) {
diff --git a/src/mongo/idl/basic_types.h b/src/mongo/idl/basic_types.h
index c02366d3c5f..62e191a9bf5 100644
--- a/src/mongo/idl/basic_types.h
+++ b/src/mongo/idl/basic_types.h
@@ -47,6 +47,10 @@ namespace mongo {
*/
class OptionalBool {
public:
+ /**
+ * IMPORTANT: The method should not be modified, as API version input/output guarantees could
+ * break because of it.
+ */
static OptionalBool parseFromBSON(BSONElement element) {
uassert(ErrorCodes::TypeMismatch,
str::stream() << "Field '" << element.fieldNameStringData()
@@ -76,6 +80,9 @@ public:
/**
* Serialize this object as a field in a document. If _value is empty, omit the field.
+ *
+ * IMPORTANT: The method should not be modified, as API version input/output guarantees could
+ * break because of it.
*/
void serializeToBSON(StringData fieldName, BSONObjBuilder* builder) const {
if (_value) {
@@ -85,6 +92,9 @@ public:
/**
* Serialize this object as an element of a BSON array. If _value is empty, omit the entry.
+ *
+ * IMPORTANT: The method should not be modified, as API version input/output guarantees could
+ * break because of it.
*/
void serializeToBSON(BSONArrayBuilder* builder) const {
if (_value) {
@@ -112,6 +122,10 @@ private:
*/
class IDLAnyType {
public:
+ /**
+ * IMPORTANT: The method should not be modified, as API version input/output guarantees could
+ * break because of it.
+ */
static IDLAnyType parseFromBSON(const BSONElement& element) {
return IDLAnyType(element);
}
@@ -119,10 +133,18 @@ public:
IDLAnyType() = default;
IDLAnyType(const BSONElement& element) : _element(element) {}
+ /**
+ * IMPORTANT: The method should not be modified, as API version input/output guarantees could
+ * break because of it.
+ */
void serializeToBSON(StringData fieldName, BSONObjBuilder* builder) const {
builder->appendAs(_element, fieldName);
}
+ /**
+ * IMPORTANT: The method should not be modified, as API version input/output guarantees could
+ * break because of it.
+ */
void serializeToBSON(BSONArrayBuilder* builder) const {
builder->append(_element);
}
@@ -141,6 +163,10 @@ protected:
*/
class IDLAnyTypeOwned : public IDLAnyType {
public:
+ /**
+ * IMPORTANT: The method should not be modified, as API version input/output guarantees could
+ * break because of it.
+ */
static IDLAnyTypeOwned parseFromBSON(const BSONElement& element) {
return IDLAnyTypeOwned(element);
}
diff --git a/src/mongo/idl/idl_parser.cpp b/src/mongo/idl/idl_parser.cpp
index 9cad14bffca..de0ffd40852 100644
--- a/src/mongo/idl/idl_parser.cpp
+++ b/src/mongo/idl/idl_parser.cpp
@@ -341,14 +341,26 @@ std::vector<std::vector<std::uint8_t>> transformVector(const std::vector<ConstDa
return output;
}
+/**
+ * IMPORTANT: The method should not be modified, as API version input/output guarantees could
+ * break because of it.
+ */
void noOpSerializer(bool, StringData fieldName, BSONObjBuilder* bob) {}
+/**
+ * IMPORTANT: The method should not be modified, as API version input/output guarantees could
+ * break because of it.
+ */
void serializeBSONWhenNotEmpty(BSONObj obj, StringData fieldName, BSONObjBuilder* bob) {
if (!obj.isEmpty()) {
bob->append(fieldName, obj);
}
}
+/**
+ * IMPORTANT: The method should not be modified, as API version input/output guarantees could
+ * break because of it.
+ */
BSONObj parseOwnedBSON(BSONElement element) {
uassert(ErrorCodes::TypeMismatch,
str::stream() << "Expected field " << element.fieldNameStringData()
@@ -357,6 +369,10 @@ BSONObj parseOwnedBSON(BSONElement element) {
return element.Obj().getOwned();
}
+/**
+ * IMPORTANT: The method should not be modified, as API version input/output guarantees could
+ * break because of it.
+ */
bool parseBoolean(BSONElement element) {
uassert(ErrorCodes::TypeMismatch,
str::stream() << "Expected field " << element.fieldNameStringData()
diff --git a/src/mongo/idl/idl_parser.h b/src/mongo/idl/idl_parser.h
index 47096c0d117..316ccd06c7e 100644
--- a/src/mongo/idl/idl_parser.h
+++ b/src/mongo/idl/idl_parser.h
@@ -289,12 +289,28 @@ std::vector<std::string> transformVector(const std::vector<StringData>& input);
std::vector<ConstDataRange> transformVector(const std::vector<std::vector<std::uint8_t>>& input);
std::vector<std::vector<std::uint8_t>> transformVector(const std::vector<ConstDataRange>& input);
+/**
+ * IMPORTANT: The method should not be modified, as API version input/output guarantees could
+ * break because of it.
+ */
void noOpSerializer(bool, StringData fieldName, BSONObjBuilder* bob);
+/**
+ * IMPORTANT: The method should not be modified, as API version input/output guarantees could
+ * break because of it.
+ */
void serializeBSONWhenNotEmpty(BSONObj obj, StringData fieldName, BSONObjBuilder* bob);
+/**
+ * IMPORTANT: The method should not be modified, as API version input/output guarantees could
+ * break because of it.
+ */
BSONObj parseOwnedBSON(BSONElement element);
+/**
+ * IMPORTANT: The method should not be modified, as API version input/output guarantees could
+ * break because of it.
+ */
bool parseBoolean(BSONElement element);
} // namespace mongo