summaryrefslogtreecommitdiff
path: root/buildscripts/idl
diff options
context:
space:
mode:
authorAli Mir <ali.mir@mongodb.com>2021-03-02 16:47:22 +0000
committerEvergreen Agent <no-reply@evergreen.mongodb.com>2021-03-09 18:59:51 +0000
commitd515a228ed01ffff0b9e808805a6957b31540211 (patch)
treee404e6c44ac759c3abbecdb93e3e2d43cd6ec652 /buildscripts/idl
parent7db8fdb7ff39b14a0a09996e67968a5a715f754b (diff)
downloadmongo-d515a228ed01ffff0b9e808805a6957b31540211.tar.gz
SERVER-53204 Recursively type check parameters in IDL compatibility checker script
Diffstat (limited to 'buildscripts/idl')
-rw-r--r--buildscripts/idl/idl_compatibility_errors.py154
-rw-r--r--buildscripts/idl/tests/compatibility_test_fail/new/compatibility_test_fail_new.idl41
-rw-r--r--buildscripts/idl/tests/compatibility_test_fail/old/compatibility_test_fail_old.idl40
-rw-r--r--buildscripts/idl/tests/compatibility_test_pass/new/compatibility_test_pass_new.idl41
-rw-r--r--buildscripts/idl/tests/compatibility_test_pass/old/compatibility_test_pass_old.idl41
-rw-r--r--buildscripts/idl/tests/test_compatibility.py18
6 files changed, 264 insertions, 71 deletions
diff --git a/buildscripts/idl/idl_compatibility_errors.py b/buildscripts/idl/idl_compatibility_errors.py
index 3d0d6bc35c7..4b51e989047 100644
--- a/buildscripts/idl/idl_compatibility_errors.py
+++ b/buildscripts/idl/idl_compatibility_errors.py
@@ -259,33 +259,35 @@ class IDLCompatibilityContext(object):
"of this command." % (command_name, field_name, type_name), file)
def add_command_or_param_type_invalid_error(self, command_name: str, file: str,
- param_name: Optional[str],
+ field_name: Optional[str],
is_command_parameter: bool) -> None:
"""Add an error about the command parameter or type being invalid."""
if is_command_parameter:
- self._add_error(ERROR_ID_COMMAND_PARAMETER_TYPE_INVALID, command_name,
- ("The '%s' command has a parameter '%s' that has an invalid type") %
- (command_name, param_name), file)
+ self._add_error(
+ ERROR_ID_COMMAND_PARAMETER_TYPE_INVALID, command_name,
+ "The '%s' command has a field or sub-field '%s' that has an invalid type" %
+ (command_name, field_name), file)
else:
- self._add_error(ERROR_ID_COMMAND_TYPE_INVALID, command_name,
- ("'%s' has an invalid type") % (command_name), file)
+ self._add_error(
+ ERROR_ID_COMMAND_TYPE_INVALID, command_name,
+ "'%s' has an invalid type or has a sub-struct with an invalid type" %
+ (command_name), file)
def add_command_or_param_type_not_superset_error(self, command_name: str, type_name: str,
- file: str, param_name: Optional[str],
+ file: str, field_name: Optional[str],
is_command_parameter: bool) -> None:
# pylint: disable=too-many-arguments
"""Add an error about the command or parameter type not being a superset."""
if is_command_parameter:
self._add_error(
ERROR_ID_COMMAND_PARAMETER_TYPE_NOT_SUPERSET, command_name,
- "The command '%s' has parameter '%s' with type '%s' that is not a superset of the"
- " older version of this command parameter type." % (command_name, param_name,
- type_name), file)
+ "The command '%s' has field or sub-field '%s' with type '%s' that is not a superset of the "
+ "older version of this field type." % (command_name, field_name, type_name), file)
else:
self._add_error(
ERROR_ID_COMMAND_TYPE_NOT_SUPERSET, command_name,
- "'%s' has type '%s' that is not a superset of the other version of this command." %
- (command_name, type_name), file)
+ "The command '%s' or its sub-struct has type '%s' that is not a superset of "
+ "the older version of this struct type." % (command_name, type_name), file)
def add_command_or_param_type_contains_validator_error(self, command_name: str, field_name: str,
file: str, type_name: Optional[str],
@@ -300,13 +302,14 @@ class IDLCompatibilityContext(object):
if is_command_parameter:
self._add_error(
ERROR_ID_COMMAND_PARAMETER_CONTAINS_VALIDATOR, command_name,
- "Parameter '%s' for new command '%s' contains a validator while old command "
- "parameter does not." % (field_name, command_name), file)
+ "Field or sub-field '%s' for new command '%s' contains a validator "
+ "while the old field does not." % (field_name, command_name), file)
else:
self._add_error(
ERROR_ID_COMMAND_TYPE_CONTAINS_VALIDATOR, command_name,
- ("Type '%s' for new command '%s' has a field '%s' that contains a validator while"
- " the old command type does not.") % (type_name, field_name, command_name), file)
+ "The command '%s' or its sub-struct has type '%s' with field '%s' that "
+ "contains a validator while "
+ "the old struct type does not." % (command_name, type_name, field_name), file)
def add_command_or_param_type_validators_not_equal_error(
self, command_name: str, field_name: str, file: str, type_name: Optional[str],
@@ -316,14 +319,15 @@ class IDLCompatibilityContext(object):
if is_command_parameter:
self._add_error(
ERROR_ID_COMMAND_PARAMETER_VALIDATORS_NOT_EQUAL, command_name,
- "Validator for parameter '%s' in old command '%s' is not equal to the validator in"
- "the new version of the command parameter" % (field_name, command_name), file)
+ "Validator for field or sub-field '%s' in old command '%s' is not equal "
+ "to the validator in the new version of the field" % (field_name, command_name),
+ file)
else:
self._add_error(
ERROR_ID_COMMAND_TYPE_VALIDATORS_NOT_EQUAL, command_name,
- ("Validator for field '%s' in type '%s' in old command '%s' is not equal to the"
- "validator in the new command type.") % (field_name, type_name, command_name),
- file)
+ "Validator for field '%s' in type '%s' in old command '%s' or its "
+ "sub-struct is not equal to the validator in the new struct type." %
+ (field_name, type_name, command_name), file)
def add_missing_error_reply_struct_error(self, file: str) -> None:
"""Add an error about the file missing the ErrorReply struct."""
@@ -331,7 +335,7 @@ class IDLCompatibilityContext(object):
("'%s' is missing the ErrorReply struct") % (file), file)
def add_new_command_or_param_type_bson_any_error(self, command_name: str, new_type: str,
- file: str, param_name: Optional[str],
+ file: str, field_name: Optional[str],
is_command_parameter: bool) -> None:
# pylint: disable=too-many-arguments
"""
@@ -344,17 +348,18 @@ class IDLCompatibilityContext(object):
if is_command_parameter:
self._add_error(
ERROR_ID_NEW_COMMAND_PARAMETER_TYPE_BSON_SERIALIZATION_TYPE_ANY, command_name,
- ("The '%s' command has new parameter '%s' that has type '%s' "
- "that has a bson serialization type 'any'") % (command_name, param_name, new_type),
+ "The '%s' command has field or sub-field '%s' that has type '%s' "
+ "that has a bson serialization type 'any'" % (command_name, field_name, new_type),
file)
else:
- self._add_error(ERROR_ID_NEW_COMMAND_TYPE_BSON_SERIALIZATION_TYPE_ANY, command_name,
- ("'%s' has new type '%s' that has a bson serialization type 'any'") %
- (command_name, new_type), file)
+ self._add_error(
+ ERROR_ID_NEW_COMMAND_TYPE_BSON_SERIALIZATION_TYPE_ANY, command_name,
+ "The '%s' command or its sub-struct has type '%s' that "
+ "has a bson serialization type 'any'" % (command_name, new_type), file)
def add_new_command_or_param_type_enum_or_struct_error(
self, command_name: str, new_type: str, old_type: str, file: str,
- param_name: Optional[str], is_command_parameter: bool) -> None:
+ field_name: Optional[str], is_command_parameter: bool) -> None:
# pylint: disable=too-many-arguments
"""
Add an error about a type that is an enum or struct.
@@ -365,14 +370,16 @@ class IDLCompatibilityContext(object):
if is_command_parameter:
self._add_error(
ERROR_ID_NEW_COMMAND_PARAMETER_TYPE_ENUM_OR_STRUCT, command_name,
- ("The command '%s' has parameter '%s' of type '%s' that is an enum or struct "
- "while the corresponding old parameter type is a non-enum or "
- "non-struct of type '%s'.") % (command_name, param_name, new_type, old_type), file)
+ "The command '%s' has field or sub-field '%s' of type '%s' that is an enum or "
+ "struct while the corresponding old field type is a non-enum or "
+ "non-struct of type '%s'." % (command_name, field_name, new_type, old_type), file)
else:
- self._add_error(ERROR_ID_NEW_COMMAND_TYPE_ENUM_OR_STRUCT, command_name,
- ("'%s' has type '%s' that is an enum or struct while the corresponding"
- " old type was a non-enum or struct of type '%s'.") %
- (command_name, new_type, old_type), file)
+ self._add_error(
+ ERROR_ID_NEW_COMMAND_TYPE_ENUM_OR_STRUCT, command_name,
+ "The command '%s' or its sub-struct has type '%s' that is an enum "
+ "or struct while the corresponding"
+ "old type was a non-enum or struct of type '%s'." % (command_name, new_type,
+ old_type), file)
def add_new_param_or_command_type_field_added_required_error(
self, command_name: str, field_name: str, file: str, type_name: str,
@@ -388,13 +395,14 @@ class IDLCompatibilityContext(object):
if is_command_parameter:
self._add_error(
ERROR_ID_ADDED_REQUIRED_COMMAND_PARAMETER, command_name,
- "New command parameter '%s' for command '%s' is required when it should "
+ "New field or sub-field '%s' for command '%s' is required when it should "
"be optional." % (field_name, command_name), file)
else:
self._add_error(
ERROR_ID_NEW_COMMAND_TYPE_FIELD_ADDED_REQUIRED, command_name,
- ("'%s' has type '%s' with an added and required type field '%s' that did not exist"
- " in the old command type.") % (command_name, type_name, field_name), file)
+ "The command '%s' or its sub-struct has type '%s' with an added and "
+ "required type field '%s' that did not exist "
+ "in the old struct type." % (command_name, type_name, field_name), file)
def add_new_param_or_command_type_field_missing_error(self, command_name: str, field_name: str,
file: str, type_name: str,
@@ -404,13 +412,14 @@ class IDLCompatibilityContext(object):
if is_command_parameter:
self._add_error(
ERROR_ID_REMOVED_COMMAND_PARAMETER, command_name,
- "Parameter '%s' for old command '%s' was removed from the corresponding new"
- "command." % (field_name, command_name), file)
+ "Field or sub-field '%s' for old command '%s' was removed from the corresponding new"
+ "struct." % (field_name, command_name), file)
else:
self._add_error(
ERROR_ID_NEW_COMMAND_TYPE_FIELD_MISSING, command_name,
- "'%s' has type '%s' that is missing a field '%s' that exists in the old command"
- " type." % (command_name, type_name, field_name), file)
+ "The command '%s' or its sub-struct has type '%s' that is missing a "
+ "field '%s' that exists in the old struct type." % (command_name, type_name,
+ field_name), file)
def add_new_param_or_command_type_field_required_error(self, command_name: str, field_name: str,
file: str, type_name: Optional[str],
@@ -425,13 +434,14 @@ class IDLCompatibilityContext(object):
if is_command_parameter:
self._add_error(
ERROR_ID_COMMAND_PARAMETER_REQUIRED, command_name,
- "'%s' has a required command parameter '%s' that was optional in the old command." %
+ "'%s' has a required field or sub-field '%s' that was optional in the old struct." %
(command_name, field_name), file)
else:
self._add_error(
ERROR_ID_NEW_COMMAND_TYPE_FIELD_REQUIRED, command_name,
- "'%s' has type '%s' with a required type field '%s' that was optional in the old"
- " command type." % (command_name, type_name, field_name), file)
+ "'%s' or its sub-struct has type '%s' with a required type field '%s' "
+ "that was optional in the old struct type." % (command_name, type_name, field_name),
+ file)
def add_new_param_or_command_type_field_stable_required_error(
self, command_name: str, field_name: str, file: str, type_name: Optional[str],
@@ -447,14 +457,15 @@ class IDLCompatibilityContext(object):
if is_command_parameter:
self._add_error(
ERROR_ID_COMMAND_PARAMETER_STABLE_REQUIRED, command_name,
- "'%s' has a stable required command parameter '%s' that was unstable in the"
- " old command."
- "The new parameter should be optional." % (command_name, field_name), file)
+ "'%s' has a stable required field or sub-field '%s' that "
+ "was unstable in the old struct. "
+ "The new field should be optional." % (command_name, field_name), file)
else:
self._add_error(
ERROR_ID_NEW_COMMAND_TYPE_FIELD_STABLE_REQUIRED, command_name,
- ("'%s' has type '%s' with a stable and required type field '%s' that was unstable "
- "in the old command type.") % (command_name, type_name, field_name), file)
+ "'%s' or its sub-struct has type '%s' with a stable and required "
+ "type field '%s' that was unstable "
+ "in the old struct type." % (command_name, type_name, field_name), file)
def add_new_param_or_command_type_field_unstable_error(self, command_name: str, field_name: str,
file: str, type_name: Optional[str],
@@ -469,17 +480,18 @@ class IDLCompatibilityContext(object):
if is_command_parameter:
self._add_error(
ERROR_ID_COMMAND_PARAMETER_UNSTABLE, command_name,
- "'%s' has an unstable command parameter '%s' that was stable in the old command." %
+ "'%s' has an unstable field or sub-field '%s' that was stable in the old struct." %
(command_name, field_name), file)
else:
self._add_error(
ERROR_ID_NEW_COMMAND_TYPE_FIELD_UNSTABLE, command_name,
- "'%s' has type '%s' with an unstable field '%s' that was stable in the old "
- "command type." % (command_name, type_name, field_name), file)
+ "'%s' or its sub-struct has type '%s' with an unstable "
+ "field '%s' that was stable in the old "
+ "struct type." % (command_name, type_name, field_name), file)
def add_new_command_or_param_type_not_enum_error(
self, command_name: str, new_type: str, old_type: str, file: str,
- param_name: Optional[str], is_command_parameter: bool) -> None:
+ field_name: Optional[str], is_command_parameter: bool) -> None:
# pylint: disable=too-many-arguments
"""
Add an not enum parameter or command type field error.
@@ -490,31 +502,33 @@ class IDLCompatibilityContext(object):
if is_command_parameter:
self._add_error(
ERROR_ID_NEW_COMMAND_PARAMETER_TYPE_NOT_ENUM, command_name,
- ("The '%s' command has parameter '%s' of type '%s' that is not an enum while the "
- "corresponding old parameter type was an enum of type '%s'.") %
- (command_name, param_name, new_type, old_type), file)
+ "The '%s' command has field or sub-field '%s' of type '%s' that is "
+ "not an enum while the corresponding old field type was an enum of type '%s'." %
+ (command_name, field_name, new_type, old_type), file)
else:
self._add_error(
ERROR_ID_NEW_COMMAND_TYPE_NOT_ENUM, command_name,
- ("'%s' has type '%s' that is not an enum while the corresponding "
- "old type was an enum of type '%s'.") % (command_name, new_type, old_type), file)
+ "'%s' or its sub-struct has type '%s' that is not an enum while the corresponding "
+ "old type was an enum of type '%s'." % (command_name, new_type, old_type), file)
def add_new_command_or_param_type_not_struct_error(
self, command_name: str, new_type: str, old_type: str, file: str,
- param_name: Optional[str], is_command_parameter: bool) -> None:
+ field_name: Optional[str], is_command_parameter: bool) -> None:
# pylint: disable=too-many-arguments
"""Add an error about the new command or parameter type not being a struct when the old one is."""
if is_command_parameter:
self._add_error(
ERROR_ID_NEW_COMMAND_PARAMETER_TYPE_NOT_STRUCT, command_name,
- ("The '%s' command has parameter '%s' of type '%s' that is not a struct while the"
- " corresponding old parameter type was a struct of type '%s'.") %
- (command_name, param_name, new_type, old_type), file)
+ "The '%s' command has field or sub-field '%s' of type '%s' that is "
+ "not a struct while the corresponding old "
+ "field type was a struct of type '%s'." % (command_name, field_name, new_type,
+ old_type), file)
else:
self._add_error(
ERROR_ID_NEW_COMMAND_TYPE_NOT_STRUCT, command_name,
- ("'%s' has type '%s' that is not a struct while the corresponding "
- "old type was a struct of type '%s'.") % (command_name, new_type, old_type), file)
+ "'%s' or its sub-struct has type '%s' that is not a "
+ "struct while the corresponding old type was a struct of type '%s'." %
+ (command_name, new_type, old_type), file)
def add_new_command_or_param_type_not_variant_type_error(self, command_name: str, new_type: str,
file: str, param_name: Optional[str],
@@ -679,7 +693,7 @@ class IDLCompatibilityContext(object):
(command_name, field_name, variant_type_name), file)
def add_old_command_or_param_type_bson_any_error(self, command_name: str, old_type: str,
- file: str, param_name: Optional[str],
+ file: str, field_name: Optional[str],
is_command_parameter: bool) -> None:
# pylint: disable=too-many-arguments
"""
@@ -692,13 +706,13 @@ class IDLCompatibilityContext(object):
if is_command_parameter:
self._add_error(
ERROR_ID_OLD_COMMAND_PARAMETER_TYPE_BSON_SERIALIZATION_TYPE_ANY, command_name,
- ("The '%s'' command has old parameter '%s' that has type '%s' "
- "that has a bson serialization type 'any'") % (command_name, param_name, old_type),
+ "The '%s'' command has field or sub-field '%s' that has type '%s' "
+ "that has a bson serialization type 'any'" % (command_name, field_name, old_type),
file)
else:
self._add_error(ERROR_ID_OLD_COMMAND_TYPE_BSON_SERIALIZATION_TYPE_ANY, command_name,
- ("'%s' has old type '%s' that has a bson serialization type 'any'") %
- (command_name, old_type), file)
+ ("'%s' or its sub-struct has type '%s' that has a "
+ "bson serialization type 'any'") % (command_name, old_type), file)
def add_command_or_param_type_bson_any_not_allowed_error(
self, command_name: str, type_name: str, file: str, param_name: Optional[str],
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 8b2a3b1f49a..0865850efca 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
@@ -290,6 +290,21 @@ structs:
type:
variant: [int, StructFieldTypeRecursiveReplyTwo]
+ CommandParamStructRecursiveOne:
+ description: "This command parameter struct type contains an unstable field while the
+ old struct field is stable"
+ fields:
+ stableToUnstableField:
+ type: string
+ unstable: true
+
+ CommandParamStructRecursiveTwo:
+ description: "This command parameter struct type contains a field that
+ is not a superset of the old struct field"
+ fields:
+ notSupersetField:
+ type: intStringToInt
+
NewCommandTypeValidatorStruct:
description: "This struct contains a field where the new version contains a validator while
the old version does not"
@@ -643,6 +658,32 @@ commands:
newParamBsonNotSuperset:
type: intStringToInt
+ newCommandParameterTypeStructRecursiveOne:
+ description: "new command fails because its parameter type is a struct that is
+ not compatible with the old command parameter type struct"
+ command_name: newCommandParameterTypeStructRecursiveOne
+ namespace: ignored
+ cpp_name: newCommandParameterTypeStructRecursiveOne
+ strict: true
+ api_version: "1"
+ reply_type: OkReply
+ fields:
+ stableToUnstableStructParameter:
+ type: CommandParamStructRecursiveOne
+
+ newCommandParameterTypeStructRecursiveTwo:
+ description: "new command fails because its parameter type is a struct that is
+ not compatible with the old command parameter type struct"
+ command_name: newCommandParameterTypeStructRecursiveTwo
+ namespace: ignored
+ cpp_name: newCommandParameterTypeStructRecursiveTwo
+ strict: true
+ api_version: "1"
+ reply_type: OkReply
+ fields:
+ notSupersetStructParameter:
+ type: CommandParamStructRecursiveTwo
+
newCommandParameterValidator:
description: "new command fails because it contains a parameter that contains a validator
that is not present in the old parameter"
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 827aef7a5e7..57a3622b4b2 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
@@ -293,6 +293,20 @@ structs:
type:
variant: [int, StructFieldTypeRecursiveReplyTwo]
+ CommandParamStructRecursiveOne:
+ description: "This command parameter struct type contains a stable field while the
+ new struct field is unstable"
+ fields:
+ stableToUnstableField:
+ type: string
+
+ CommandParamStructRecursiveTwo:
+ description: "This command parameter struct type contains a field that
+ is not a subset of the new struct field"
+ fields:
+ notSupersetField:
+ type: intStringToInt
+
NewCommandTypeValidatorStruct:
description: "This struct contains a field where the new version contains a validator while
the old version does not"
@@ -633,6 +647,32 @@ commands:
newParamBsonNotSuperset:
type: intStringToInt
+ newCommandParameterTypeStructRecursiveOne:
+ description: "new command fails because its parameter type is a struct that is
+ not compatible with the old command parameter type struct."
+ command_name: newCommandParameterTypeStructRecursiveOne
+ namespace: ignored
+ cpp_name: newCommandParameterTypeStructRecursiveOne
+ strict: true
+ api_version: "1"
+ reply_type: OkReply
+ fields:
+ stableToUnstableStructParameter:
+ type: CommandParamStructRecursiveOne
+
+ newCommandParameterTypeStructRecursiveTwo:
+ description: "new command fails because its parameter type is a struct that is
+ not compatible with the old command parameter type struct"
+ command_name: newCommandParameterTypeStructRecursiveTwo
+ namespace: ignored
+ cpp_name: newCommandParameterTypeStructRecursiveTwo
+ strict: true
+ api_version: "1"
+ reply_type: OkReply
+ fields:
+ notSupersetStructParameter:
+ type: CommandParamStructRecursiveTwo
+
newCommandParameterValidator:
description: "new command fails because it contains a parameter that contains a validator
that is not present in the old parameter"
diff --git a/buildscripts/idl/tests/compatibility_test_pass/new/compatibility_test_pass_new.idl b/buildscripts/idl/tests/compatibility_test_pass/new/compatibility_test_pass_new.idl
index bd8e3277881..4cd2c50b05d 100644
--- a/buildscripts/idl/tests/compatibility_test_pass/new/compatibility_test_pass_new.idl
+++ b/buildscripts/idl/tests/compatibility_test_pass/new/compatibility_test_pass_new.idl
@@ -218,6 +218,21 @@ structs:
type:
variant: [int, StructFieldTypeRecursiveReplyTwo]
+ CommandParamStructRecursiveOne:
+ description: "This command parameter struct type contains a stable and optional
+ field while the old struct field is unstable"
+ fields:
+ unstableToStableOptionalField:
+ type: string
+ optional: true
+
+ CommandParamStructRecursiveTwo:
+ description: "This command parameter struct type contains a field whose new type is
+ a superset of the old field type"
+ fields:
+ supersetField:
+ type: intToIntString
+
OldCommandTypeValidatorStruct:
description: "This struct contains a field where the old version contains a validator while
the new version does not"
@@ -495,6 +510,32 @@ commands:
bsonSupersetParam:
type: intToIntString
+ newCommandParameterTypeStructRecursiveOne:
+ description: "new command passes because its parameter type is a struct that is
+ compatible with the old parameter type struct"
+ command_name: newCommandParameterTypeStructRecursiveOne
+ namespace: ignored
+ cpp_name: newCommandParameterTypeStructRecursiveOne
+ strict: true
+ api_version: "1"
+ reply_type: OkReply
+ fields:
+ unstableToStableOptionalStructParameter:
+ type: CommandParamStructRecursiveOne
+
+ newCommandParameterTypeStructRecursiveTwo:
+ description: "new command passes because its parameter type is a struct that is
+ compatible with the old parameter type struct"
+ command_name: newCommandParameterTypeStructRecursiveTwo
+ namespace: ignored
+ cpp_name: newCommandParameterTypeStructRecursiveTwo
+ strict: true
+ api_version: "1"
+ reply_type: OkReply
+ fields:
+ supersetStructParameter:
+ type: CommandParamStructRecursiveTwo
+
oldCommandParameterValidator:
description: "new command passes when it contains a parameter that does not contain a validator
that is present in the old parameter"
diff --git a/buildscripts/idl/tests/compatibility_test_pass/old/compatibility_test_pass_old.idl b/buildscripts/idl/tests/compatibility_test_pass/old/compatibility_test_pass_old.idl
index eca3c5ba85c..2ed7c0b2494 100644
--- a/buildscripts/idl/tests/compatibility_test_pass/old/compatibility_test_pass_old.idl
+++ b/buildscripts/idl/tests/compatibility_test_pass/old/compatibility_test_pass_old.idl
@@ -221,6 +221,21 @@ structs:
description: "The new command parameter's type and the
old command parameter's type are both structs"
+ CommandParamStructRecursiveOne:
+ description: "This command parameter struct type contains a unstable field while the
+ new struct field is stable and optional"
+ fields:
+ unstableToStableOptionalField:
+ type: string
+ unstable: true
+
+ CommandParamStructRecursiveTwo:
+ description: "This command parameter struct type contains a field whose new type is
+ a superset of the old field type"
+ fields:
+ supersetField:
+ type: intToIntString
+
OldCommandTypeValidatorStruct:
description: "This struct contains a field where the old version contains a validator while
the new version does not"
@@ -486,6 +501,32 @@ commands:
bsonSupersetParam:
type: intToIntString
+ newCommandParameterTypeStructRecursiveOne:
+ description: "new command passes because its parameter type is a struct that is
+ compatible with the old parameter type struct"
+ command_name: newCommandParameterTypeStructRecursiveOne
+ namespace: ignored
+ cpp_name: newCommandParameterTypeStructRecursiveOne
+ strict: true
+ api_version: "1"
+ reply_type: OkReply
+ fields:
+ unstableToStableOptionalStructParameter:
+ type: CommandParamStructRecursiveOne
+
+ newCommandParameterTypeStructRecursiveTwo:
+ description: "new command passes because its parameter type is a struct that is
+ compatible with the old parameter type struct"
+ command_name: newCommandParameterTypeStructRecursiveTwo
+ namespace: ignored
+ cpp_name: newCommandParameterTypeStructRecursiveTwo
+ strict: true
+ api_version: "1"
+ reply_type: OkReply
+ fields:
+ supersetStructParameter:
+ type: CommandParamStructRecursiveTwo
+
oldCommandParameterValidator:
description: "new command passes when it contains a parameter that does not contain a validator
that is present in the old parameter"
diff --git a/buildscripts/idl/tests/test_compatibility.py b/buildscripts/idl/tests/test_compatibility.py
index b73147d2272..779dcd10c81 100644
--- a/buildscripts/idl/tests/test_compatibility.py
+++ b/buildscripts/idl/tests/test_compatibility.py
@@ -106,7 +106,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() == 88)
+ self.assertTrue(error_collection.count() == 90)
invalid_api_version_new_error = error_collection.get_error_by_command_name(
"invalidAPIVersionNew")
@@ -263,6 +263,22 @@ class TestIDLCompatibilityChecker(unittest.TestCase):
str(new_command_parameter_type_bson_not_superset),
"newCommandParameterTypeBsonNotSuperset")
+ new_command_parameter_type_recursive_one_error = error_collection.get_error_by_command_name(
+ "newCommandParameterTypeStructRecursiveOne")
+ self.assertTrue(new_command_parameter_type_recursive_one_error.error_id ==
+ idl_compatibility_errors.ERROR_ID_COMMAND_PARAMETER_UNSTABLE)
+ self.assertRegex(
+ str(new_command_parameter_type_recursive_one_error),
+ "newCommandParameterTypeStructRecursiveOne")
+
+ new_command_parameter_type_recursive_two_error = error_collection.get_error_by_command_name(
+ "newCommandParameterTypeStructRecursiveTwo")
+ self.assertTrue(new_command_parameter_type_recursive_two_error.error_id ==
+ idl_compatibility_errors.ERROR_ID_COMMAND_PARAMETER_TYPE_NOT_SUPERSET)
+ self.assertRegex(
+ str(new_command_parameter_type_recursive_two_error),
+ "newCommandParameterTypeStructRecursiveTwo")
+
new_reply_field_unstable_error = error_collection.get_error_by_command_name(
"newReplyFieldUnstable")
self.assertTrue(new_reply_field_unstable_error.error_id ==