diff options
5 files changed, 200 insertions, 7 deletions
diff --git a/buildscripts/idl/idl_compatibility_errors.py b/buildscripts/idl/idl_compatibility_errors.py index 9369f964d8b..2058b29a9f9 100644 --- a/buildscripts/idl/idl_compatibility_errors.py +++ b/buildscripts/idl/idl_compatibility_errors.py @@ -680,13 +680,13 @@ class IDLCompatibilityContext(object): def add_reply_field_bson_any_not_allowed_error(self, command_name: str, field_name: str, type_name: str, file: str) -> None: """ - Add an error about the old and new reply field bson serialization_type being 'any'. + Add an error about the reply field bson serialization_type being 'any'. - Add an error about the old and new reply field type's bson serialization type being of + Add an error about the reply field type's bson serialization type being of type 'any' when it is not explicitly allowed. """ self._add_error(ERROR_ID_REPLY_FIELD_BSON_SERIALIZATION_TYPE_ANY_NOT_ALLOWED, command_name, - ("'%s' has an old and new reply field or sub-field '%s' of type '%s' " + ("'%s' has a reply field or sub-field '%s' of type '%s' " "that has a bson serialization type 'any' when it " "is not explicitly allowed.") % (command_name, field_name, type_name), file) @@ -830,22 +830,22 @@ class IDLCompatibilityContext(object): is_command_parameter: bool) -> None: # pylint: disable=too-many-arguments,invalid-name """ - Add an error about the old and new command or param type bson serialization_type being 'any'. + Add an error about the command or param type bson serialization_type being 'any'. - Add an error about the old and new command or parameter type's bson serialization type + Add an error about the command or parameter type's bson serialization type being of type 'any' when it is not explicitly allowed. """ if is_command_parameter: self._add_error(ERROR_ID_COMMAND_PARAMETER_BSON_SERIALIZATION_TYPE_ANY_NOT_ALLOWED, command_name, - ("'%s' has an old and new field or sub-field '%s' of type " + ("'%s' has a field or sub-field '%s' of type " "'%s' that has a bson " "serialization type 'any' when it is not explicitly allowed.") % (command_name, field_name, type_name), file) else: self._add_error( ERROR_ID_COMMAND_TYPE_BSON_SERIALIZATION_TYPE_ANY_NOT_ALLOWED, command_name, - ("'%s' or its sub-struct has an old and new type '%s' that has a bson " + ("'%s' or its sub-struct has a type '%s' that has a bson " "serialization type 'any' when it is not explicitly allowed.") % (command_name, type_name), file) diff --git a/buildscripts/idl/tests/compatibility_test_fail/newly_added_commands/newly_added_commands.idl b/buildscripts/idl/tests/compatibility_test_fail/newly_added_commands/newly_added_commands.idl new file mode 100644 index 00000000000..c07063ec61d --- /dev/null +++ b/buildscripts/idl/tests/compatibility_test_fail/newly_added_commands/newly_added_commands.idl @@ -0,0 +1,124 @@ +# Copyright (C) 2022-present MongoDB, Inc. +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the Server Side Public License, version 1, +# as published by MongoDB, Inc. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# Server Side Public License for more details. +# +# You should have received a copy of the Server Side Public License +# along with this program. If not, see +# <http://www.mongodb.com/licensing/server-side-public-license>. +# +# As a special exception, the copyright holders give permission to link the +# code of portions of this program with the OpenSSL library under certain +# conditions as described in each individual source file and distribute +# linked combinations including the program with the OpenSSL library. You +# must comply with the Server Side Public License in all respects for +# all of the code used other than as permitted herein. If you modify file(s) +# with this exception, you may extend this exception to your version of the +# file(s), but you are not obligated to do so. If you do not wish to do so, +# delete this exception statement from your version. If you delete this +# exception statement from all source files in the program, then also delete +# it in the license file. +# + +global: + cpp_namespace: "mongo" + +imports: + - "mongo/idl/basic_types.idl" + - "../buildscripts/idl/tests/compatibility_test_fail/new/imports.idl" + +types: + bsonSerializationTypeAny: + bson_serialization_type: + - int + - any + description: "The bson_serialization_type contains 'any'" + cpp_type: "std::int32_t" + +structs: + NewStructFieldNoUnstableField: + description: "new struct field has no unstable field specified" + fields: + newStructFieldNoUnstableField: + type: bool + + NewStructFieldTypeContainsAny: + description: "new struct field type has bson_serialization_type with 'any'" + fields: + newStructFieldTypeContainsAny: + type: bsonSerializationTypeAny + unstable: false + +commands: + newCommandParameterNoUnstableField: + description: "newly added command has a parameter without the unstable field specified" + command_name: newCommandParameterNoUnstableField + namespace: ignored + cpp_name: newCommandParameterNoUnstableField + strict: true + api_version: "1" + fields: + flag1: + type: bool + reply_type: OkReply + + newCommandReplyNoUnstableField: + description: "newly added command has a reply field without the unstable field specified" + command_name: newCommandReplyNoUnstableField + namespace: ignored + cpp_name: newCommandReplyNoUnstableField + strict: true + api_version: "1" + reply_type: NewStructFieldNoUnstableField + + newCommandTypeStructFieldNoUnstableField: + description: "newly added command has a command type struct field without the unstable + field specified" + command_name: newCommandTypeStructFieldNoUnstableField + namespace: type + type: NewStructFieldNoUnstableField + cpp_name: newCommandTypeStructFieldNoUnstableField + strict: true + api_version: "1" + reply_type: OkReply + + newCommandParameterBsonSerializationTypeAny: + description: "newly added command has a parameter type that has bson_serialization_type + with 'any'" + command_name: newCommandParameterBsonSerializationTypeAny + namespace: ignored + cpp_name: newCommandParameterBsonSerializationTypeAny + strict: true + api_version: "1" + fields: + flag1: + type: bsonSerializationTypeAny + unstable: false + reply_type: OkReply + + newCommandReplyBsonSerializationTypeAny: + description: "newly added command has a reply field type that has bson_serialization_type + with 'any'" + command_name: newCommandReplyBsonSerializationTypeAny + namespace: ignored + cpp_name: newCommandReplyBsonSerializationTypeAny + strict: true + api_version: "1" + reply_type: NewStructFieldTypeContainsAny + + newCommandTypeStructFieldBsonSerializationTypeAny: + description: "newly added command has a command struct field type that has + bson_serialization_type with 'any'" + command_name: newCommandTypeStructFieldBsonSerializationTypeAny + namespace: type + type: NewStructFieldTypeContainsAny + cpp_name: newCommandTypeStructFieldBsonSerializationTypeAny + strict: true + api_version: "1" + reply_type: OkReply diff --git a/buildscripts/idl/tests/test_compatibility.py b/buildscripts/idl/tests/test_compatibility.py index 21c6492de46..7bd80713869 100644 --- a/buildscripts/idl/tests/test_compatibility.py +++ b/buildscripts/idl/tests/test_compatibility.py @@ -81,6 +81,65 @@ class TestIDLCompatibilityChecker(unittest.TestCase): path.join(dir_path, "compatibility_test_fail/abort/invalid_command_parameter_type"), ["src"], ["src"]) + # pylint: disable=invalid-name + def test_newly_added_commands_should_fail(self): + """Tests that incompatible newly added commands should fail.""" + dir_path = path.dirname(path.realpath(__file__)) + error_collection = idl_check_compatibility.check_compatibility( + path.join(dir_path, "compatibility_test_fail/newly_added_commands"), + path.join(dir_path, "compatibility_test_fail/newly_added_commands"), ["src"], ["src"]) + + self.assertTrue(error_collection.has_errors()) + self.assertEqual(error_collection.count(), 6) + + new_parameter_no_unstable_field_error = error_collection.get_error_by_command_name( + "newCommandParameterNoUnstableField") + self.assertTrue(new_parameter_no_unstable_field_error.error_id == + idl_compatibility_errors.ERROR_ID_NEW_PARAMETER_REQUIRES_UNSTABLE) + self.assertRegex( + str(new_parameter_no_unstable_field_error), "newCommandParameterNoUnstableField") + + new_reply_no_unstable_field_error = error_collection.get_error_by_command_name( + "newCommandReplyNoUnstableField") + self.assertTrue(new_reply_no_unstable_field_error.error_id == + idl_compatibility_errors.ERROR_ID_NEW_REPLY_FIELD_REQUIRES_UNSTABLE) + self.assertRegex(str(new_reply_no_unstable_field_error), "newCommandReplyNoUnstableField") + + new_command_type_struct_no_unstable_field_error = error_collection.get_error_by_command_name( + "newCommandTypeStructFieldNoUnstableField") + self.assertTrue(new_command_type_struct_no_unstable_field_error.error_id == + idl_compatibility_errors.ERROR_ID_NEW_COMMAND_TYPE_FIELD_REQUIRES_UNSTABLE) + self.assertRegex( + str(new_command_type_struct_no_unstable_field_error), + "newCommandTypeStructFieldNoUnstableField") + + new_parameter_bson_serialization_type_any_error = error_collection.get_error_by_command_name( + "newCommandParameterBsonSerializationTypeAny") + self.assertTrue( + new_parameter_bson_serialization_type_any_error.error_id == idl_compatibility_errors. + ERROR_ID_COMMAND_PARAMETER_BSON_SERIALIZATION_TYPE_ANY_NOT_ALLOWED) + self.assertRegex( + str(new_parameter_bson_serialization_type_any_error), + "newCommandParameterBsonSerializationTypeAny") + + new_reply_bson_serialization_type_any_error = error_collection.get_error_by_command_name( + "newCommandReplyBsonSerializationTypeAny") + self.assertTrue( + new_reply_bson_serialization_type_any_error.error_id == + idl_compatibility_errors.ERROR_ID_REPLY_FIELD_BSON_SERIALIZATION_TYPE_ANY_NOT_ALLOWED) + self.assertRegex( + str(new_reply_bson_serialization_type_any_error), + "newCommandReplyBsonSerializationTypeAny") + + new_command_type_struct_bson_serialization_type_any_error = error_collection.get_error_by_command_name( + "newCommandTypeStructFieldBsonSerializationTypeAny") + self.assertTrue( + new_command_type_struct_bson_serialization_type_any_error.error_id == + idl_compatibility_errors.ERROR_ID_COMMAND_TYPE_BSON_SERIALIZATION_TYPE_ANY_NOT_ALLOWED) + self.assertRegex( + str(new_command_type_struct_bson_serialization_type_any_error), + "newCommandTypeStructFieldBsonSerializationTypeAny") + # pylint: disable=too-many-locals,too-many-statements,invalid-name def test_should_fail(self): """Tests that incompatible old and new IDL commands should fail.""" diff --git a/evergreen/check_idl_compat.sh b/evergreen/check_idl_compat.sh index 9868c9d700b..4498641cd89 100755 --- a/evergreen/check_idl_compat.sh +++ b/evergreen/check_idl_compat.sh @@ -13,3 +13,9 @@ find idls -maxdepth 1 -mindepth 1 -type d | while read dir; do echo "Performing idl check compatibility with release: $dir:" $python buildscripts/idl/idl_check_compatibility.py -v --old-include "$dir/src" --old-include "$dir/src/mongo/db/modules/enterprise/src" --new-include src --new-include src/mongo/db/modules/enterprise/src "$dir/src" src done + +# Run the idl compatibility checker script with the current src directory as both the "old" and +# "new" versions. This is so that we can check that commands that were newly added since the last +# release adhere to compatibility requirements. +echo "Performing idl check compatibility for newly added commands since the last release:" +$python buildscripts/idl/idl_check_compatibility.py -v --old-include src --old-include src/mongo/db/modules/enterprise/src --new-include src --new-include src/mongo/db/modules/enterprise/src src src diff --git a/src/mongo/db/commands/change_stream_options.idl b/src/mongo/db/commands/change_stream_options.idl index 4f34f561b08..56146ad9049 100644 --- a/src/mongo/db/commands/change_stream_options.idl +++ b/src/mongo/db/commands/change_stream_options.idl @@ -45,6 +45,7 @@ structs: description: "The number of seconds after which a pre-image is eligible for deletion. A string value 'off' enables the default expiration policy." optional: true + unstable: false type: variant: [string, safeInt64] ChangeStreamOptions: @@ -53,6 +54,7 @@ structs: preAndPostImages: type: PreAndPostImagesOptions optional: true + unstable: false GetChangeStreamOptionsResponse: description: "A response for the get change streams options command." chained_structs: @@ -77,10 +79,12 @@ commands: description: "The pre- and post-images options to set." type: PreAndPostImagesOptions optional: true + unstable: false writeConcern: description: "The level of write concern for the command." type: WriteConcern optional: true + unstable: false reply_type: OkReply getChangeStreamOptions: description: "A command to get the change streams options." |