diff options
author | Jacob Keeler <jacob.keeler@livioradio.com> | 2020-06-10 17:12:55 -0400 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-06-10 17:12:55 -0400 |
commit | ef2b88520b4224390ffd332f737fdf5573def60e (patch) | |
tree | 15533d732dcccd1682975c9f141c718c4720f314 | |
parent | 6ebc91a2db98493ac002c56f3555b33a301eee1b (diff) | |
download | sdl_core-ef2b88520b4224390ffd332f737fdf5573def60e.tar.gz |
Filter unknown enums when removing unknown parameters (#3385)
* Add enum filtering step to applySchema
This step is triggered when `remove_unknown_parameters` is enabled
* Add unit tests
* Pass warning info to message response after processing
38 files changed, 696 insertions, 138 deletions
diff --git a/src/components/application_manager/include/application_manager/commands/command.h b/src/components/application_manager/include/application_manager/commands/command.h index 0536c7aee1..a7241ce16d 100644 --- a/src/components/application_manager/include/application_manager/commands/command.h +++ b/src/components/application_manager/include/application_manager/commands/command.h @@ -98,6 +98,18 @@ class Command { */ virtual WindowID window_id() const = 0; + /** + * @brief Set warning info string, to be sent on a successful response + * @param info Warning info string + */ + virtual void set_warning_info(const std::string info) = 0; + + /** + * @brief Returns warning info string + * @return Warning info string + */ + virtual std::string warning_info() const = 0; + /* * @brief Function is called by RequestController when request execution time * has exceed it's limit diff --git a/src/components/application_manager/include/application_manager/commands/command_impl.h b/src/components/application_manager/include/application_manager/commands/command_impl.h index 0d8013b639..151c4d7874 100644 --- a/src/components/application_manager/include/application_manager/commands/command_impl.h +++ b/src/components/application_manager/include/application_manager/commands/command_impl.h @@ -122,6 +122,10 @@ class CommandImpl : public Command { */ WindowID window_id() const OVERRIDE; + void set_warning_info(const std::string info) OVERRIDE; + + std::string warning_info() const OVERRIDE; + /* * @brief Function is called by RequestController when request execution time * has exceed it's limit @@ -205,6 +209,12 @@ class CommandImpl : public Command { HMICapabilities& hmi_capabilities_; policy::PolicyHandlerInterface& policy_handler_; + /** + * @brief warning_info_ Defines a warning message to send in the case of a + * successful response + */ + std::string warning_info_; + CommandParametersPermissions parameters_permissions_; CommandParametersPermissions removed_parameters_permissions_; diff --git a/src/components/application_manager/include/application_manager/commands/command_request_impl.h b/src/components/application_manager/include/application_manager/commands/command_request_impl.h index 87008d9439..87c19ca1d1 100644 --- a/src/components/application_manager/include/application_manager/commands/command_request_impl.h +++ b/src/components/application_manager/include/application_manager/commands/command_request_impl.h @@ -380,7 +380,7 @@ class CommandRequestImpl : public CommandImpl, * @param info string with disallowed params enumeration * @param param disallowed param */ - void AddDissalowedParameterToInfoString(std::string& info, + void AddDisallowedParameterToInfoString(std::string& info, const std::string& param) const; /** diff --git a/src/components/application_manager/include/application_manager/rpc_handler_impl.h b/src/components/application_manager/include/application_manager/rpc_handler_impl.h index 11ac1745ee..ab140dbd8a 100644 --- a/src/components/application_manager/include/application_manager/rpc_handler_impl.h +++ b/src/components/application_manager/include/application_manager/rpc_handler_impl.h @@ -176,6 +176,7 @@ class RPCHandlerImpl : public RPCHandler, bool ConvertMessageToSO(const Message& message, smart_objects::SmartObject& output, + std::string& out_warning_info, const bool allow_unknown_parameters = false, const bool validate_params = true); std::shared_ptr<Message> ConvertRawMsgToMessage( diff --git a/src/components/application_manager/include/application_manager/rpc_service_impl.h b/src/components/application_manager/include/application_manager/rpc_service_impl.h index 3e3d83a519..289a0bcb66 100644 --- a/src/components/application_manager/include/application_manager/rpc_service_impl.h +++ b/src/components/application_manager/include/application_manager/rpc_service_impl.h @@ -122,6 +122,9 @@ class RPCServiceImpl : public RPCService, bool ManageMobileCommand(const commands::MessageSharedPtr message, commands::Command::CommandSource source) OVERRIDE; + bool ManageMobileCommand(const commands::MessageSharedPtr message, + commands::Command::CommandSource source, + const std::string warning_info) OVERRIDE; bool ManageHMICommand(const commands::MessageSharedPtr message, commands::Command::CommandSource source = commands::Command::SOURCE_HMI) OVERRIDE; diff --git a/src/components/application_manager/rpc_plugins/sdl_rpc_plugin/src/commands/mobile/subscribe_button_request.cc b/src/components/application_manager/rpc_plugins/sdl_rpc_plugin/src/commands/mobile/subscribe_button_request.cc index 1acb2a7438..3797913f5b 100644 --- a/src/components/application_manager/rpc_plugins/sdl_rpc_plugin/src/commands/mobile/subscribe_button_request.cc +++ b/src/components/application_manager/rpc_plugins/sdl_rpc_plugin/src/commands/mobile/subscribe_button_request.cc @@ -107,8 +107,8 @@ void SubscribeButtonRequest::Run() { app->SubscribeToButton(static_cast<mobile_apis::ButtonName::eType>(btn_id)); SendSubscribeButtonNotification(); - const bool is_succedeed = true; - SendResponse(is_succedeed, mobile_apis::Result::SUCCESS); + const bool is_succeeded = true; + SendResponse(is_succeeded, mobile_apis::Result::SUCCESS); } bool SubscribeButtonRequest::Init() { diff --git a/src/components/application_manager/src/commands/command_impl.cc b/src/components/application_manager/src/commands/command_impl.cc index 23b14184ad..3872ae45ab 100644 --- a/src/components/application_manager/src/commands/command_impl.cc +++ b/src/components/application_manager/src/commands/command_impl.cc @@ -111,6 +111,14 @@ uint32_t CommandImpl::connection_key() const { return (*message_)[strings::params][strings::connection_key].asUInt(); } +void CommandImpl::set_warning_info(const std::string info) { + warning_info_ = info; +} + +std::string CommandImpl::warning_info() const { + return warning_info_; +} + void CommandImpl::onTimeOut() {} bool CommandImpl::AllowedToTerminate() { diff --git a/src/components/application_manager/src/commands/command_request_impl.cc b/src/components/application_manager/src/commands/command_request_impl.cc index e5914e1376..3f279679a3 100644 --- a/src/components/application_manager/src/commands/command_request_impl.cc +++ b/src/components/application_manager/src/commands/command_request_impl.cc @@ -298,7 +298,7 @@ void CommandRequestImpl::SendResponse( response[strings::msg_params] = *response_params; } - if (info) { + if (info && *info != '\0') { response[strings::msg_params][strings::info] = std::string(info); } @@ -318,7 +318,17 @@ void CommandRequestImpl::SendResponse( } response[strings::msg_params][strings::success] = success; - response[strings::msg_params][strings::result_code] = result_code; + if ((result_code == mobile_apis::Result::SUCCESS || + result_code == mobile_apis::Result::WARNINGS) && + !warning_info().empty()) { + response[strings::msg_params][strings::info] = + (info && *info != '\0') ? std::string(info) + "\n" + warning_info() + : warning_info(); + response[strings::msg_params][strings::result_code] = + mobile_apis::Result::WARNINGS; + } else { + response[strings::msg_params][strings::result_code] = result_code; + } is_success_result_ = success; @@ -719,7 +729,7 @@ bool CommandRequestImpl::CheckHMICapabilities( return false; } -void CommandRequestImpl::AddDissalowedParameterToInfoString( +void CommandRequestImpl::AddDisallowedParameterToInfoString( std::string& info, const std::string& param) const { // prepare disallowed params enumeration for response info string if (info.empty()) { @@ -736,12 +746,12 @@ void CommandRequestImpl::AddDisallowedParametersToInfo( RPCParams::const_iterator it = removed_parameters_permissions_.disallowed_params.begin(); for (; it != removed_parameters_permissions_.disallowed_params.end(); ++it) { - AddDissalowedParameterToInfoString(info, (*it)); + AddDisallowedParameterToInfoString(info, (*it)); } it = removed_parameters_permissions_.undefined_params.begin(); for (; it != removed_parameters_permissions_.undefined_params.end(); ++it) { - AddDissalowedParameterToInfoString(info, (*it)); + AddDisallowedParameterToInfoString(info, (*it)); } if (!info.empty()) { diff --git a/src/components/application_manager/src/rpc_handler_impl.cc b/src/components/application_manager/src/rpc_handler_impl.cc index 0a62bc8498..bb8e4fc1fb 100644 --- a/src/components/application_manager/src/rpc_handler_impl.cc +++ b/src/components/application_manager/src/rpc_handler_impl.cc @@ -108,8 +108,12 @@ void RPCHandlerImpl::ProcessMessageFromMobile( allow_unknown_parameters = true; } - if (!ConvertMessageToSO( - *message, *so_from_mobile, allow_unknown_parameters, !rpc_passing)) { + std::string warning_info; + if (!ConvertMessageToSO(*message, + *so_from_mobile, + warning_info, + allow_unknown_parameters, + !rpc_passing)) { LOG4CXX_ERROR(logger_, "Cannot create smart object from message"); return; } @@ -131,7 +135,7 @@ void RPCHandlerImpl::ProcessMessageFromMobile( commands::Command::SOURCE_MOBILE, message_type)) { // Since PassThrough failed, refiltering the message - if (!ConvertMessageToSO(*message, *so_from_mobile)) { + if (!ConvertMessageToSO(*message, *so_from_mobile, warning_info)) { LOG4CXX_ERROR(logger_, "Cannot create smart object from message"); return; } @@ -143,7 +147,7 @@ void RPCHandlerImpl::ProcessMessageFromMobile( #endif // TELEMETRY_MONITOR if (!app_manager_.GetRPCService().ManageMobileCommand( - so_from_mobile, commands::Command::SOURCE_MOBILE)) { + so_from_mobile, commands::Command::SOURCE_MOBILE, warning_info)) { LOG4CXX_ERROR(logger_, "Received command didn't run successfully"); } #ifdef TELEMETRY_MONITOR @@ -176,7 +180,9 @@ void RPCHandlerImpl::ProcessMessageFromHMI( allow_unknown_parameters = true; } - if (!ConvertMessageToSO(*message, *smart_object, allow_unknown_parameters)) { + std::string warning_info; + if (!ConvertMessageToSO( + *message, *smart_object, warning_info, allow_unknown_parameters)) { if (application_manager::MessageType::kResponse == (*smart_object)[strings::params][strings::message_type].asInt()) { (*smart_object).erase(strings::msg_params); @@ -190,6 +196,11 @@ void RPCHandlerImpl::ProcessMessageFromHMI( } } + if (!warning_info.empty()) { + LOG4CXX_WARN(logger_, + "Warning while parsing HMI message: " << warning_info); + } + LOG4CXX_DEBUG(logger_, "Converted message, trying to create hmi command"); if (!app_manager_.GetRPCService().ManageHMICommand(smart_object)) { LOG4CXX_ERROR(logger_, "Received command didn't run successfully"); @@ -320,6 +331,7 @@ void RPCHandlerImpl::GetMessageVersion( bool RPCHandlerImpl::ConvertMessageToSO( const Message& message, ns_smart_device_link::ns_smart_objects::SmartObject& output, + std::string& out_warning_info, const bool allow_unknown_parameters, const bool validate_params) { LOG4CXX_AUTO_TRACE(logger_); @@ -382,6 +394,9 @@ bool RPCHandlerImpl::ConvertMessageToSO( "Convertion result for sdl object is true function_id " << output[jhs::S_PARAMS][jhs::S_FUNCTION_ID].asInt()); + // Populate any warning info generated during the validation process + out_warning_info = rpc::PrettyFormat(report); + output[strings::params][strings::connection_key] = message.connection_key(); output[strings::params][strings::protocol_version] = @@ -534,7 +549,7 @@ bool RPCHandlerImpl::ValidateRpcSO(smart_objects::SmartObject& message, rpc::ValidationReport& report_out, bool allow_unknown_parameters) { if (!mobile_so_factory().attachSchema( - message, !allow_unknown_parameters, msg_version) || + message, !allow_unknown_parameters, msg_version, &report_out) || message.validate(&report_out, msg_version, allow_unknown_parameters) != smart_objects::errors::OK) { LOG4CXX_WARN(logger_, "Failed to parse string to smart object"); diff --git a/src/components/application_manager/src/rpc_service_impl.cc b/src/components/application_manager/src/rpc_service_impl.cc index 0dc48385b2..d544c3b445 100644 --- a/src/components/application_manager/src/rpc_service_impl.cc +++ b/src/components/application_manager/src/rpc_service_impl.cc @@ -112,10 +112,16 @@ EncryptionFlagCheckResult RPCServiceImpl::IsEncryptionRequired( ? EncryptionFlagCheckResult::kSuccess_Protected : EncryptionFlagCheckResult::kSuccess_NotProtected; } - bool RPCServiceImpl::ManageMobileCommand( const commands::MessageSharedPtr message, commands::Command::CommandSource source) { + return ManageMobileCommand(message, source, std::string()); +} + +bool RPCServiceImpl::ManageMobileCommand( + const commands::MessageSharedPtr message, + commands::Command::CommandSource source, + const std::string warning_info) { LOG4CXX_AUTO_TRACE(logger_); if (!message) { @@ -237,7 +243,6 @@ bool RPCServiceImpl::ManageMobileCommand( if (message_type == mobile_apis::messageType::request && source == commands::Command::CommandSource::SOURCE_MOBILE) { - // commands will be launched from requesr_ctrl mobile_apis::HMILevel::eType app_hmi_level = mobile_apis::HMILevel::INVALID_ENUM; if (app) { @@ -245,8 +250,9 @@ bool RPCServiceImpl::ManageMobileCommand( app->hmi_level(mobile_apis::PredefinedWindows::DEFAULT_WINDOW); } - // commands will be launched from request_ctrl + command->set_warning_info(warning_info); + // commands will be launched from request_ctrl const request_controller::RequestController::TResult result = request_ctrl_.addMobileRequest(command, app_hmi_level); diff --git a/src/components/application_manager/test/commands/command_request_impl_test.cc b/src/components/application_manager/test/commands/command_request_impl_test.cc index 83b5d7eeb4..9034bf442f 100644 --- a/src/components/application_manager/test/commands/command_request_impl_test.cc +++ b/src/components/application_manager/test/commands/command_request_impl_test.cc @@ -543,8 +543,8 @@ TEST_F(CommandRequestImplTest, HashUpdateAllowed_UpdateExpected) { EXPECT_CALL(mock_rpc_service_, ManageMobileCommand(_, _)) .WillOnce(DoAll(SaveArg<0>(&result), Return(true))); - const bool is_succedeed = true; - command->SendResponse(is_succedeed, kMobResultSuccess, NULL, NULL); + const bool is_succeeded = true; + command->SendResponse(is_succeeded, kMobResultSuccess, NULL, NULL); MockAppPtr mock_app = CreateMockApp(); EXPECT_CALL(app_mngr_, application(_)).WillOnce(Return(mock_app)); @@ -564,8 +564,8 @@ TEST_F(CommandRequestImplTest, HashUpdateDisallowed_HashUpdateNotExpected) { EXPECT_CALL(mock_rpc_service_, ManageMobileCommand(_, _)) .WillOnce(DoAll(SaveArg<0>(&result), Return(true))); - const bool is_succedeed = true; - command->SendResponse(is_succedeed, kMobResultSuccess, NULL, NULL); + const bool is_succeeded = true; + command->SendResponse(is_succeeded, kMobResultSuccess, NULL, NULL); MockAppPtr mock_app = CreateMockApp(); EXPECT_CALL(*mock_app, UpdateHash()).Times(0); @@ -583,8 +583,8 @@ TEST_F(CommandRequestImplTest, RequestFailed_HashUpdateNotExpected) { EXPECT_CALL(mock_rpc_service_, ManageMobileCommand(_, _)) .WillOnce(DoAll(SaveArg<0>(&result), Return(true))); - const bool is_succedeed = false; - command->SendResponse(is_succedeed, kMobResultSuccess, NULL, NULL); + const bool is_succeeded = false; + command->SendResponse(is_succeeded, kMobResultSuccess, NULL, NULL); MockAppPtr mock_app = CreateMockApp(); EXPECT_CALL(*mock_app, UpdateHash()).Times(0); @@ -602,8 +602,8 @@ TEST_F(CommandRequestImplTest, AppNotFound_HashUpdateNotExpected) { EXPECT_CALL(mock_rpc_service_, ManageMobileCommand(_, _)) .WillOnce(DoAll(SaveArg<0>(&result), Return(true))); - const bool is_succedeed = true; - command->SendResponse(is_succedeed, kMobResultSuccess, NULL, NULL); + const bool is_succeeded = true; + command->SendResponse(is_succeeded, kMobResultSuccess, NULL, NULL); MockAppPtr mock_app = CreateMockApp(); EXPECT_CALL(app_mngr_, application(_)).WillOnce(Return(MockAppPtr())); diff --git a/src/components/application_manager/test/include/application_manager/mock_request.h b/src/components/application_manager/test/include/application_manager/mock_request.h index 77b5bb7c38..c1cc7f601f 100644 --- a/src/components/application_manager/test/include/application_manager/mock_request.h +++ b/src/components/application_manager/test/include/application_manager/mock_request.h @@ -56,6 +56,8 @@ class MockRequest : public application_manager::commands::Command { MOCK_CONST_METHOD0(default_timeout, uint32_t()); MOCK_CONST_METHOD0(function_id, int32_t()); MOCK_CONST_METHOD0(window_id, application_manager::WindowID()); + MOCK_METHOD1(set_warning_info, void(const std::string info)); + MOCK_CONST_METHOD0(warning_info, std::string()); MOCK_METHOD0(onTimeOut, void()); MOCK_METHOD0(AllowedToTerminate, bool()); MOCK_METHOD1(SetAllowedToTerminate, void(bool is_allowed)); diff --git a/src/components/formatters/include/formatters/CSmartFactory.h b/src/components/formatters/include/formatters/CSmartFactory.h index c384dbf01d..83bcbb770e 100644 --- a/src/components/formatters/include/formatters/CSmartFactory.h +++ b/src/components/formatters/include/formatters/CSmartFactory.h @@ -147,16 +147,18 @@ class CSmartFactory { * @brief Attach schema to the function SmartObject. * * @param object SmartObject to attach schema for. - * * @param remove_unknown_parameters contains true if need * to remove fake parameters from smart object otherwise contains false. + * @param MessageVersion the version of the schema to be applied + * @param report__ object for reporting warnings during schema application * * @return True if operation was successful or false otherwise. */ bool attachSchema( ns_smart_device_link::ns_smart_objects::SmartObject& object, const bool remove_unknown_parameters, - const utils::SemanticVersion& MessageVersion = utils::SemanticVersion()); + const utils::SemanticVersion& MessageVersion = utils::SemanticVersion(), + rpc::ValidationReport* report__ = nullptr); /** * @brief Attach schema to the struct SmartObject. @@ -277,7 +279,8 @@ template <class FunctionIdEnum, class MessageTypeEnum, class StructIdEnum> bool CSmartFactory<FunctionIdEnum, MessageTypeEnum, StructIdEnum>::attachSchema( ns_smart_device_link::ns_smart_objects::SmartObject& object, const bool remove_unknown_parameters, - const utils::SemanticVersion& MessageVersion) { + const utils::SemanticVersion& MessageVersion, + rpc::ValidationReport* report__) { if (false == object.keyExists(strings::S_PARAMS)) return false; if (false == object[strings::S_PARAMS].keyExists(strings::S_MESSAGE_TYPE)) @@ -305,7 +308,7 @@ bool CSmartFactory<FunctionIdEnum, MessageTypeEnum, StructIdEnum>::attachSchema( object.setSchema(schemaIterator->second); schemaIterator->second.applySchema( - object, remove_unknown_parameters, MessageVersion); + object, remove_unknown_parameters, MessageVersion, report__); return true; } diff --git a/src/components/include/application_manager/rpc_service.h b/src/components/include/application_manager/rpc_service.h index 4a80733ee7..f98cd826f9 100644 --- a/src/components/include/application_manager/rpc_service.h +++ b/src/components/include/application_manager/rpc_service.h @@ -54,10 +54,16 @@ class RPCService { * @brief ManageMobileCommand convert message to mobile command and execute it * @param message pointer to received message * @param origin origin of command + * @param warning_info warning message to send on a successful response. Only + * applies to requests from mobile. * @return true if command is executed, otherwise return false */ virtual bool ManageMobileCommand(const commands::MessageSharedPtr message, commands::Command::CommandSource source) = 0; + virtual bool ManageMobileCommand(const commands::MessageSharedPtr message, + commands::Command::CommandSource source, + const std::string warning_info) = 0; + /** * @brief ManageHMICommand convert message to HMI command and execute it * @param message pointer to received message diff --git a/src/components/include/test/application_manager/mock_rpc_service.h b/src/components/include/test/application_manager/mock_rpc_service.h index ed06b930d8..66de650ab6 100644 --- a/src/components/include/test/application_manager/mock_rpc_service.h +++ b/src/components/include/test/application_manager/mock_rpc_service.h @@ -21,6 +21,11 @@ class MockRPCService : public application_manager::rpc_service::RPCService { ManageMobileCommand, bool(const application_manager::commands::MessageSharedPtr message, application_manager::commands::Command::CommandSource origin)); + MOCK_METHOD3( + ManageMobileCommand, + bool(const application_manager::commands::MessageSharedPtr message, + application_manager::commands::Command::CommandSource origin, + const std::string warning_info)); MOCK_METHOD2(SendMessageToMobile, void(application_manager::commands::MessageSharedPtr, bool)); MOCK_METHOD1( diff --git a/src/components/smart_objects/include/smart_objects/always_false_schema_item.h b/src/components/smart_objects/include/smart_objects/always_false_schema_item.h index 05c53ec582..7b92bc9748 100644 --- a/src/components/smart_objects/include/smart_objects/always_false_schema_item.h +++ b/src/components/smart_objects/include/smart_objects/always_false_schema_item.h @@ -51,7 +51,7 @@ class CAlwaysFalseSchemaItem : public ISchemaItem { /** * @brief Validate smart object. * @param Object Object to validate. - * @param report__ object for reporting errors during validation + * @param report object for reporting errors during validation * @param MessageVersion to check mobile RPC version against RPC Spec History * @param allow_unknown_enums * false - unknown enum values (left as string values after applySchema) @@ -61,7 +61,7 @@ class CAlwaysFalseSchemaItem : public ISchemaItem { **/ errors::eType validate( const SmartObject& Object, - rpc::ValidationReport* report__, + rpc::ValidationReport* report, const utils::SemanticVersion& MessageVersion = utils::SemanticVersion(), const bool allow_unknown_enums = false) OVERRIDE; diff --git a/src/components/smart_objects/include/smart_objects/always_true_schema_item.h b/src/components/smart_objects/include/smart_objects/always_true_schema_item.h index a2d305d0f9..b0bb3f2fa6 100644 --- a/src/components/smart_objects/include/smart_objects/always_true_schema_item.h +++ b/src/components/smart_objects/include/smart_objects/always_true_schema_item.h @@ -51,7 +51,7 @@ class CAlwaysTrueSchemaItem : public ISchemaItem { /** * @brief Validate smart object. * @param Object Object to validate. - * @param report__ object for reporting errors during validation + * @param report object for reporting errors during validation * @param MessageVersion to check mobile RPC version against RPC Spec History * @param allow_unknown_enums * false - unknown enum values (left as string values after applySchema) @@ -61,7 +61,7 @@ class CAlwaysTrueSchemaItem : public ISchemaItem { **/ errors::eType validate( const SmartObject& Object, - rpc::ValidationReport* report__, + rpc::ValidationReport* report, const utils::SemanticVersion& MessageVersion = utils::SemanticVersion(), const bool allow_unknown_enums = false) OVERRIDE; diff --git a/src/components/smart_objects/include/smart_objects/array_schema_item.h b/src/components/smart_objects/include/smart_objects/array_schema_item.h index 0e19d2237e..8f9a179fff 100644 --- a/src/components/smart_objects/include/smart_objects/array_schema_item.h +++ b/src/components/smart_objects/include/smart_objects/array_schema_item.h @@ -66,7 +66,7 @@ class CArraySchemaItem : public ISchemaItem { /** * @brief Validate smart object. * @param Object Object to validate. - * @param report__ object for reporting errors during validation + * @param report object for reporting errors during validation * @param MessageVersion to check mobile RPC version against RPC Spec History * @param allow_unknown_enums * false - unknown enum values (left as string values after applySchema) @@ -76,17 +76,21 @@ class CArraySchemaItem : public ISchemaItem { **/ errors::eType validate( const SmartObject& Object, - rpc::ValidationReport* report__, + rpc::ValidationReport* report, const utils::SemanticVersion& MessageVersion = utils::SemanticVersion(), const bool allow_unknown_enums = false) OVERRIDE; + bool filterInvalidEnums(SmartObject& Object, + const utils::SemanticVersion& MessageVersion, + rpc::ValidationReport* report) OVERRIDE; + /** * @brief Apply schema. * * @param Object Object to apply schema. * @param remove_unknown_parameters contains true if need to remove unknown - *parameters - * from smart object otherwise contains false. + * parameters from smart object, otherwise contains false. + * @param MessageVersion the version of the schema to be applied **/ void applySchema(SmartObject& Object, const bool remove_unknown_parameters, @@ -113,6 +117,8 @@ class CArraySchemaItem : public ISchemaItem { void BuildObjectBySchema(const SmartObject& pattern_object, SmartObject& result_object) OVERRIDE; + TypeID GetType() OVERRIDE; + private: /** * @brief Constructor. @@ -124,6 +130,7 @@ class CArraySchemaItem : public ISchemaItem { CArraySchemaItem(const ISchemaItemPtr ElementSchemaItem, const TSchemaItemParameter<size_t>& MinSize, const TSchemaItemParameter<size_t>& MaxSize); + /** * @brief SchemaItem for array elements. **/ diff --git a/src/components/smart_objects/include/smart_objects/bool_schema_item.h b/src/components/smart_objects/include/smart_objects/bool_schema_item.h index 3a9f6c929d..b652799a27 100644 --- a/src/components/smart_objects/include/smart_objects/bool_schema_item.h +++ b/src/components/smart_objects/include/smart_objects/bool_schema_item.h @@ -51,6 +51,8 @@ class CBoolSchemaItem : public CDefaultSchemaItem<bool> { const TSchemaItemParameter<bool>& DefaultValue = TSchemaItemParameter<bool>()); + TypeID GetType() OVERRIDE; + private: explicit CBoolSchemaItem(const TSchemaItemParameter<bool>& DefaultValue); SmartType getSmartType() const OVERRIDE; diff --git a/src/components/smart_objects/include/smart_objects/default_shema_item.h b/src/components/smart_objects/include/smart_objects/default_shema_item.h index 16dbad4426..bcb610cb33 100644 --- a/src/components/smart_objects/include/smart_objects/default_shema_item.h +++ b/src/components/smart_objects/include/smart_objects/default_shema_item.h @@ -51,7 +51,7 @@ class CDefaultSchemaItem : public ISchemaItem { /** * @brief Validate smart object. * @param Object Object to validate. - * @param report__ object for reporting errors during validation + * @param report object for reporting errors during validation * @param MessageVersion to check mobile RPC version against RPC Spec History * @param allow_unknown_enums * false - unknown enum values (left as string values after applySchema) @@ -61,7 +61,7 @@ class CDefaultSchemaItem : public ISchemaItem { **/ errors::eType validate( const SmartObject& Object, - rpc::ValidationReport* report__, + rpc::ValidationReport* report, const utils::SemanticVersion& MessageVersion = utils::SemanticVersion(), const bool allow_unknown_enums = false) OVERRIDE; @@ -109,7 +109,7 @@ CDefaultSchemaItem<Type>::CDefaultSchemaItem(const ParameterType& DefaultValue) template <typename Type> errors::eType CDefaultSchemaItem<Type>::validate( const SmartObject& Object, - rpc::ValidationReport* report__, + rpc::ValidationReport* report, const utils::SemanticVersion& MessageVersion, const bool allow_unknown_enums) { if (getSmartType() != Object.getType()) { @@ -117,7 +117,7 @@ errors::eType CDefaultSchemaItem<Type>::validate( "Incorrect type, expected: " + SmartObject::typeToString(getSmartType()) + ", got: " + SmartObject::typeToString(Object.getType()); - report__->set_validation_info(validation_info); + report->set_validation_info(validation_info); return errors::INVALID_VALUE; } else { return errors::OK; diff --git a/src/components/smart_objects/include/smart_objects/enum_schema_item.h b/src/components/smart_objects/include/smart_objects/enum_schema_item.h index 7fa5a65b35..836a3faec1 100644 --- a/src/components/smart_objects/include/smart_objects/enum_schema_item.h +++ b/src/components/smart_objects/include/smart_objects/enum_schema_item.h @@ -106,7 +106,7 @@ class TEnumSchemaItem : public CDefaultSchemaItem<EnumType> { /** * @brief Validate smart object. * @param Object Object to validate. - * @param report__ object for reporting errors during validation + * @param report object for reporting errors during validation * @param MessageVersion to check mobile RPC version against RPC Spec History * @param allow_unknown_enums * false - unknown enum values (left as string values after applySchema) @@ -116,7 +116,7 @@ class TEnumSchemaItem : public CDefaultSchemaItem<EnumType> { **/ errors::eType validate( const SmartObject& Object, - rpc::ValidationReport* report__, + rpc::ValidationReport* report, const utils::SemanticVersion& MessageVersion = utils::SemanticVersion(), const bool allow_unknown_enums = false) OVERRIDE; /** @@ -128,15 +128,17 @@ class TEnumSchemaItem : public CDefaultSchemaItem<EnumType> { const std::vector<ElementSignature>& signatures, const utils::SemanticVersion& MessageVersion); + bool filterInvalidEnums(SmartObject& Object, + const utils::SemanticVersion& MessageVersion, + rpc::ValidationReport* report) OVERRIDE; + /** * @brief Apply schema. - * This implementation checks if enumeration is represented as string - * and tries to convert it to integer according to element-to-string - * map. + * * @param Object Object to apply schema. * @param remove_unknown_parameters contains true if need to remove unknown - *parameters - * from smart object otherwise contains false. + * parameters from smart object, otherwise contains false. + * @param MessageVersion the version of the schema to be applied **/ void applySchema(SmartObject& Object, const bool remove_unknown_parameters, @@ -166,6 +168,7 @@ class TEnumSchemaItem : public CDefaultSchemaItem<EnumType> { ElementSignatures); SmartType getSmartType() const OVERRIDE; EnumType getDefaultValue() const OVERRIDE; + TypeID GetType() OVERRIDE; /** * @brief Set of allowed enumeration elements. **/ @@ -315,9 +318,24 @@ const ElementSignature TEnumSchemaItem<EnumType>::getSignature( } template <typename EnumType> +bool TEnumSchemaItem<EnumType>::filterInvalidEnums( + SmartObject& Object, + const utils::SemanticVersion& MessageVersion, + rpc::ValidationReport* report) { + rpc::ValidationReport dummy_report(""); + if (validate(Object, &dummy_report, MessageVersion) != errors::OK) { + std::string validation_info = + "Ignored invalid value - " + Object.asString(); + report->set_validation_info(validation_info); + return true; + } + return false; +} + +template <typename EnumType> errors::eType TEnumSchemaItem<EnumType>::validate( const SmartObject& Object, - rpc::ValidationReport* report__, + rpc::ValidationReport* report, const utils::SemanticVersion& MessageVersion, const bool allow_unknown_enums) { if (SmartType_Integer != Object.getType()) { @@ -333,7 +351,7 @@ errors::eType TEnumSchemaItem<EnumType>::validate( SmartObject::typeToString(SmartType_Integer) + " (enum), got: " + SmartObject::typeToString(Object.getType()); } - report__->set_validation_info(validation_info); + report->set_validation_info(validation_info); return errors::INVALID_VALUE; } @@ -344,7 +362,7 @@ errors::eType TEnumSchemaItem<EnumType>::validate( std::stringstream stream; stream << "Invalid enum value: " << Object.asInt(); std::string validation_info = stream.str(); - report__->set_validation_info(validation_info); + report->set_validation_info(validation_info); return errors::OUT_OF_RANGE; } @@ -361,7 +379,7 @@ errors::eType TEnumSchemaItem<EnumType>::validate( std::string validation_info = "Enum value : " + Object.asString() + " removed for SyncMsgVersion " + MessageVersion.toString(); - report__->set_validation_info(validation_info); + report->set_validation_info(validation_info); return errors::INVALID_VALUE; } else if (signature.mSince == boost::none && signature.mUntil == boost::none) { @@ -369,7 +387,7 @@ errors::eType TEnumSchemaItem<EnumType>::validate( std::string validation_info = "Enum value : " + Object.asString() + " does not exist for SyncMsgVersion " + MessageVersion.toString(); - report__->set_validation_info(validation_info); + report->set_validation_info(validation_info); return errors::INVALID_VALUE; } } @@ -413,6 +431,11 @@ EnumType TEnumSchemaItem<EnumType>::getDefaultValue() const { } template <typename EnumType> +TypeID TEnumSchemaItem<EnumType>::GetType() { + return TYPE_ENUM; +} + +template <typename EnumType> TEnumSchemaItem<EnumType>::TEnumSchemaItem( const std::set<EnumType>& AllowedElements, const TSchemaItemParameter<EnumType>& DefaultValue) diff --git a/src/components/smart_objects/include/smart_objects/number_schema_item.h b/src/components/smart_objects/include/smart_objects/number_schema_item.h index c3767e8e48..25b7684829 100644 --- a/src/components/smart_objects/include/smart_objects/number_schema_item.h +++ b/src/components/smart_objects/include/smart_objects/number_schema_item.h @@ -68,7 +68,7 @@ class TNumberSchemaItem : public CDefaultSchemaItem<NumberType> { /** * @brief Validate smart object. * @param Object Object to validate. - * @param report__ object for reporting errors during validation + * @param report object for reporting errors during validation * @param MessageVersion to check mobile RPC version against RPC Spec History * @param allow_unknown_enums * false - unknown enum values (left as string values after applySchema) @@ -78,10 +78,12 @@ class TNumberSchemaItem : public CDefaultSchemaItem<NumberType> { **/ errors::eType validate( const SmartObject& Object, - rpc::ValidationReport* report__, + rpc::ValidationReport* report, const utils::SemanticVersion& MessageVersion = utils::SemanticVersion(), const bool allow_unknown_enums = false) OVERRIDE; + TypeID GetType() OVERRIDE; + private: /** * @brief Get smart type for this NumberType. @@ -142,7 +144,7 @@ bool TNumberSchemaItem<NumberType>::isValidNumberType(SmartType type) { template <typename NumberType> errors::eType TNumberSchemaItem<NumberType>::validate( const SmartObject& Object, - rpc::ValidationReport* report__, + rpc::ValidationReport* report, const utils::SemanticVersion& MessageVersion, const bool allow_unknown_enums) { if (!isValidNumberType(Object.getType())) { @@ -152,7 +154,7 @@ errors::eType TNumberSchemaItem<NumberType>::validate( std::string validation_info = "Incorrect type, expected: " + SmartObject::typeToString(expectedType) + ", got: " + SmartObject::typeToString(Object.getType()); - report__->set_validation_info(validation_info); + report->set_validation_info(validation_info); return errors::INVALID_VALUE; } NumberType value(0); @@ -176,7 +178,7 @@ errors::eType TNumberSchemaItem<NumberType>::validate( stream << "Value too small, got: " << value << ", minimum allowed: " << rangeLimit; std::string validation_info = stream.str(); - report__->set_validation_info(validation_info); + report->set_validation_info(validation_info); return errors::OUT_OF_RANGE; } @@ -185,13 +187,18 @@ errors::eType TNumberSchemaItem<NumberType>::validate( stream << "Value too large, got: " << value << ", maximum allowed: " << rangeLimit; std::string validation_info = stream.str(); - report__->set_validation_info(validation_info); + report->set_validation_info(validation_info); return errors::OUT_OF_RANGE; } return errors::OK; } template <typename NumberType> +TypeID TNumberSchemaItem<NumberType>::GetType() { + return TYPE_NUMBER; +} + +template <typename NumberType> TNumberSchemaItem<NumberType>::TNumberSchemaItem( const TSchemaItemParameter<NumberType>& MinValue, const TSchemaItemParameter<NumberType>& MaxValue, diff --git a/src/components/smart_objects/include/smart_objects/object_schema_item.h b/src/components/smart_objects/include/smart_objects/object_schema_item.h index 58e13106d4..d5c8a7f3e9 100644 --- a/src/components/smart_objects/include/smart_objects/object_schema_item.h +++ b/src/components/smart_objects/include/smart_objects/object_schema_item.h @@ -110,7 +110,7 @@ class CObjectSchemaItem : public ISchemaItem { /** * @brief Validate smart object. * @param Object Object to validate. - * @param report__ object for reporting errors during validation + * @param report object for reporting errors during validation * @param MessageVersion to check mobile RPC version against RPC Spec History * @param allow_unknown_enums * false - unknown enum values (left as string values after applySchema) @@ -120,15 +120,21 @@ class CObjectSchemaItem : public ISchemaItem { **/ errors::eType validate( const SmartObject& Object, - rpc::ValidationReport* report__, + rpc::ValidationReport* report, const utils::SemanticVersion& MessageVersion = utils::SemanticVersion(), const bool allow_unknown_enums = false) OVERRIDE; + + bool filterInvalidEnums(SmartObject& Object, + const utils::SemanticVersion& MessageVersion, + rpc::ValidationReport* report) OVERRIDE; + /** * @brief Apply schema. + * * @param Object Object to apply schema. * @param remove_unknown_parameters contains true if need to remove unknown - *parameters - * from smart object otherwise contains false. + * parameters from smart object, otherwise contains false. + * @param MessageVersion the version of the schema to be applied **/ void applySchema(SmartObject& Object, const bool remove_unknown_parameters, @@ -138,7 +144,7 @@ class CObjectSchemaItem : public ISchemaItem { * @brief Unapply schema. * @param Object Object to unapply schema. * @param remove_unknown_parameters contains true if need to remove unknown - *parameters + * parameters **/ void unapplySchema(SmartObject& Object, const bool remove_unknown_parameters) OVERRIDE; @@ -156,6 +162,8 @@ class CObjectSchemaItem : public ISchemaItem { */ size_t GetMemberSize() OVERRIDE; + TypeID GetType() OVERRIDE; + boost::optional<SMember&> GetMemberSchemaItem( const std::string& member_key) OVERRIDE; @@ -171,25 +179,27 @@ class CObjectSchemaItem : public ISchemaItem { CObjectSchemaItem(const Members& Members); /** - * @brief Removes fake parameters from object. - * @param Object Object to remove fake parameters. + * @brief Removes unknown parameters from object. + * @param Object Object to remove unknown parameters. + * @param MessageVersion The version to check against for which parameters are + * unknown. **/ - void RemoveFakeParams(SmartObject& Object, - const utils::SemanticVersion& MessageVersion); + void RemoveUnknownParams(SmartObject& Object, + const utils::SemanticVersion& MessageVersion); /** * @brief Returns the correct schema item based on message version. * @param member Schema member * @param MessageVersion Semantic Version of mobile message. * @return Pointer to correct schema item if item found or nullptr, if item - *was not found. + * was not found. **/ const SMember* GetCorrectMember(const SMember& member, const utils::SemanticVersion& messageVersion); /** * @brief Map of member name to SMember structure describing the object - *member. + * member. **/ Members mMembers; DISALLOW_COPY_AND_ASSIGN(CObjectSchemaItem); diff --git a/src/components/smart_objects/include/smart_objects/schema_item.h b/src/components/smart_objects/include/smart_objects/schema_item.h index 9c29e66f36..1b1395739b 100644 --- a/src/components/smart_objects/include/smart_objects/schema_item.h +++ b/src/components/smart_objects/include/smart_objects/schema_item.h @@ -49,6 +49,16 @@ namespace ns_smart_objects { class SmartObject; class SMember; +enum TypeID { + TYPE_NONE, + TYPE_OBJECT, + TYPE_ARRAY, + TYPE_STRING, + TYPE_NUMBER, + TYPE_ENUM, + TYPE_BOOLEAN +}; + /** * @brief Base schema item. **/ @@ -58,7 +68,7 @@ class ISchemaItem { * @brief Validate smart object. * * @param Object Object to validate. - * @param report__ object for reporting errors during validation + * @param report object for reporting errors during validation * message if an error occurs * @param MessageVersion to check mobile RPC version against RPC Spec History * @param allow_unknown_enums @@ -69,7 +79,7 @@ class ISchemaItem { **/ virtual errors::eType validate( const SmartObject& Object, - rpc::ValidationReport* report__, + rpc::ValidationReport* report, const utils::SemanticVersion& MessageVersion = utils::SemanticVersion(), const bool allow_unknown_enums = false); @@ -92,12 +102,26 @@ class ISchemaItem { virtual bool hasDefaultValue(SmartObject& Object); /** + * @brief Filter invalid enum values + * + * @param Object Object to check for invalid enum values + * @param MessageVersion the version of the schema to use for validation + * @param report object for reporting enums which were removed during the + * process + * + * @return true if the value being checked should be filtered, false otherwise + **/ + virtual bool filterInvalidEnums(SmartObject& Object, + const utils::SemanticVersion& MessageVersion, + rpc::ValidationReport* report); + + /** * @brief Apply schema. * * @param Object Object to apply schema. * @param remove_unknown_parameters contains true if need to remove unknown - *parameters - * from smart object otherwise contains false. + * parameters from smart object, otherwise contains false. + * @param MessageVersion the version of the schema to be applied **/ virtual void applySchema( ns_smart_device_link::ns_smart_objects::SmartObject& Object, @@ -143,6 +167,13 @@ class ISchemaItem { */ virtual size_t GetMemberSize(); + /** + * @brief Get type ID of schema + * + * @return The type ID of this schema + */ + virtual TypeID GetType(); + virtual ~ISchemaItem() {} }; typedef std::shared_ptr<ISchemaItem> ISchemaItemPtr; diff --git a/src/components/smart_objects/include/smart_objects/smart_object.h b/src/components/smart_objects/include/smart_objects/smart_object.h index f3aab0fc1e..6ce9f96d8b 100644 --- a/src/components/smart_objects/include/smart_objects/smart_object.h +++ b/src/components/smart_objects/include/smart_objects/smart_object.h @@ -674,7 +674,7 @@ class SmartObject FINAL { /** * @brief Validates object according to attached schema. * - * @param report__ object for reporting errors during validation + * @param report object for reporting errors during validation * @param messageVersion of the mobile app to check against RPC Spec Schema * @param allow_unknown_enums * false - unknown enum values (left as string values after applySchema) @@ -683,7 +683,7 @@ class SmartObject FINAL { * @return Result of validation. */ errors::eType validate( - rpc::ValidationReport* report__, + rpc::ValidationReport* report, const utils::SemanticVersion& MessageVersion = utils::SemanticVersion(), const bool allow_unknown_enums = false); diff --git a/src/components/smart_objects/include/smart_objects/smart_schema.h b/src/components/smart_objects/include/smart_objects/smart_schema.h index 8cbafa53b2..b44ac98afd 100644 --- a/src/components/smart_objects/include/smart_objects/smart_schema.h +++ b/src/components/smart_objects/include/smart_objects/smart_schema.h @@ -64,7 +64,7 @@ class CSmartSchema FINAL { * @brief Validate smart object. * * @param Object Object to validate. - * @param report__ object for reporting errors during validation + * @param report object for reporting errors during validation * @param MessageVersion to check mobile RPC version against RPC Spec History * @param allow_unknown_enums * false - unknown enum values (left as string values after applySchema) @@ -74,7 +74,7 @@ class CSmartSchema FINAL { **/ errors::eType validate( const SmartObject& Object, - rpc::ValidationReport* report__, + rpc::ValidationReport* report, const utils::SemanticVersion& messageVersion = utils::SemanticVersion(), const bool allow_unknown_enums = false) const; @@ -96,22 +96,23 @@ class CSmartSchema FINAL { * @brief Apply schema. * * @param Object Object to apply schema. - * * @param remove_unknown_parameters contains true if need to remove unknown - *parameters - * from smart object otherwise contains false. + * parameters from smart object, otherwise contains false. + * @param MessageVersion the version of the schema to be applied + * @param report object for reporting warnings during schema application **/ void applySchema( SmartObject& Object, const bool remove_unknown_parameters, - const utils::SemanticVersion& MessageVersion = utils::SemanticVersion()); + const utils::SemanticVersion& MessageVersion = utils::SemanticVersion(), + rpc::ValidationReport* report = nullptr); /** * @brief The reverse SmartObject conversion using schema. * * @param object Object to convert. * @param remove_unknown_parameters contains true if need to remove unknown - *parameters + * parameters */ // TODO(cpplint): Is this a non-const reference? // If so, make const or use a pointer. diff --git a/src/components/smart_objects/include/smart_objects/string_schema_item.h b/src/components/smart_objects/include/smart_objects/string_schema_item.h index 7104ff47a9..8f8f516e38 100644 --- a/src/components/smart_objects/include/smart_objects/string_schema_item.h +++ b/src/components/smart_objects/include/smart_objects/string_schema_item.h @@ -63,7 +63,7 @@ class CStringSchemaItem : public CDefaultSchemaItem<std::string> { /** * @brief Validate smart object. * @param Object Object to validate. - * @param report__ object for reporting errors during validation + * @param report object for reporting errors during validation * @param MessageVersion to check mobile RPC version against RPC Spec History * @param allow_unknown_enums * false - unknown enum values (left as string values after applySchema) @@ -73,10 +73,12 @@ class CStringSchemaItem : public CDefaultSchemaItem<std::string> { **/ errors::eType validate( const SmartObject& Object, - rpc::ValidationReport* report__, + rpc::ValidationReport* report, const utils::SemanticVersion& MessageVersion = utils::SemanticVersion(), const bool allow_unknown_enums = false) OVERRIDE; + TypeID GetType() OVERRIDE; + private: /** * @brief Constructor. diff --git a/src/components/smart_objects/src/always_false_schema_item.cc b/src/components/smart_objects/src/always_false_schema_item.cc index 4f8f4584af..45955c79da 100644 --- a/src/components/smart_objects/src/always_false_schema_item.cc +++ b/src/components/smart_objects/src/always_false_schema_item.cc @@ -43,10 +43,10 @@ std::shared_ptr<CAlwaysFalseSchemaItem> CAlwaysFalseSchemaItem::create() { errors::eType CAlwaysFalseSchemaItem::validate( const SmartObject& Object, - rpc::ValidationReport* report__, + rpc::ValidationReport* report, const utils::SemanticVersion& MessageVersion, const bool allow_unknown_enums) { - report__->set_validation_info("Generic error"); + report->set_validation_info("Generic error"); return errors::ERROR; } diff --git a/src/components/smart_objects/src/always_true_schema_item.cc b/src/components/smart_objects/src/always_true_schema_item.cc index 855bfef2a0..6df8b3a63d 100644 --- a/src/components/smart_objects/src/always_true_schema_item.cc +++ b/src/components/smart_objects/src/always_true_schema_item.cc @@ -41,7 +41,7 @@ std::shared_ptr<CAlwaysTrueSchemaItem> CAlwaysTrueSchemaItem::create() { errors::eType CAlwaysTrueSchemaItem::validate( const SmartObject& Object, - rpc::ValidationReport* report__, + rpc::ValidationReport* report, const utils::SemanticVersion& MessageVersion, const bool allow_unknown_enums) { return errors::OK; diff --git a/src/components/smart_objects/src/array_schema_item.cc b/src/components/smart_objects/src/array_schema_item.cc index 9420fe020f..3c28396213 100644 --- a/src/components/smart_objects/src/array_schema_item.cc +++ b/src/components/smart_objects/src/array_schema_item.cc @@ -29,6 +29,8 @@ // POSSIBILITY OF SUCH DAMAGE. #include "smart_objects/array_schema_item.h" + +#include "smart_objects/enum_schema_item.h" #include "smart_objects/smart_object.h" namespace ns_smart_device_link { @@ -44,7 +46,7 @@ std::shared_ptr<CArraySchemaItem> CArraySchemaItem::create( errors::eType CArraySchemaItem::validate( const SmartObject& Object, - rpc::ValidationReport* report__, + rpc::ValidationReport* report, const utils::SemanticVersion& MessageVersion, const bool allow_unknown_enums) { if (SmartType_Array != Object.getType()) { @@ -52,7 +54,7 @@ errors::eType CArraySchemaItem::validate( "Incorrect type, expected: " + SmartObject::typeToString(SmartType_Array) + ", got: " + SmartObject::typeToString(Object.getType()); - report__->set_validation_info(validation_info); + report->set_validation_info(validation_info); return errors::INVALID_VALUE; } size_t sizeLimit; @@ -63,7 +65,7 @@ errors::eType CArraySchemaItem::validate( stream << "Got array of size: " << array_len << ", minimum allowed: " << sizeLimit; std::string validation_info = stream.str(); - report__->set_validation_info(validation_info); + report->set_validation_info(validation_info); return errors::OUT_OF_RANGE; } if (mMaxSize.getValue(sizeLimit) && (array_len > sizeLimit)) { @@ -71,18 +73,16 @@ errors::eType CArraySchemaItem::validate( stream << "Got array of size: " << array_len << ", maximum allowed: " << sizeLimit; std::string validation_info = stream.str(); - report__->set_validation_info(validation_info); + report->set_validation_info(validation_info); return errors::OUT_OF_RANGE; } for (size_t i = 0u; i < array_len; ++i) { - std::stringstream strVal; - strVal << i; - const errors::eType result = - mElementSchemaItem->validate(Object.getElement(i), - &report__->ReportSubobject(strVal.str()), - MessageVersion, - allow_unknown_enums); + const errors::eType result = mElementSchemaItem->validate( + Object.getElement(i), + &report->ReportSubobject(std::to_string(i)), + MessageVersion, + allow_unknown_enums); if (errors::OK != result) { return result; } @@ -90,6 +90,36 @@ errors::eType CArraySchemaItem::validate( return errors::OK; } +bool CArraySchemaItem::filterInvalidEnums( + SmartObject& Object, + const utils::SemanticVersion& MessageVersion, + rpc::ValidationReport* report) { + if (SmartType_Array != Object.getType()) { + return false; + } + + int index = 0; + auto array = Object.asArray(); + size_t initial_size = array->size(); + auto should_erase = + [this, MessageVersion, report, &index](SmartObject& element) { + // If filterInvalidEnums returns true, the checked element + // is now invalid and should be filtered + return mElementSchemaItem->filterInvalidEnums( + element, + MessageVersion, + &report->ReportSubobject(std::to_string(index++))); + }; + array->erase(std::remove_if(array->begin(), array->end(), should_erase), + array->end()); + + // Mark this container as invalid if it is below the minimum size after + // filtering one or more elements + size_t min_size; + return array->size() < initial_size && mMinSize.getValue(min_size) && + array->size() < min_size; +} + void CArraySchemaItem::applySchema( SmartObject& Object, const bool remove_unknown_parameters, @@ -127,6 +157,10 @@ void CArraySchemaItem::BuildObjectBySchema(const SmartObject& pattern_object, result_object = SmartObject(SmartType_Array); } +TypeID CArraySchemaItem::GetType() { + return TYPE_ARRAY; +} + CArraySchemaItem::CArraySchemaItem(const ISchemaItemPtr ElementSchemaItem, const TSchemaItemParameter<size_t>& MinSize, const TSchemaItemParameter<size_t>& MaxSize) diff --git a/src/components/smart_objects/src/bool_schema_item.cc b/src/components/smart_objects/src/bool_schema_item.cc index a4875a1b24..f24d14acc3 100644 --- a/src/components/smart_objects/src/bool_schema_item.cc +++ b/src/components/smart_objects/src/bool_schema_item.cc @@ -51,5 +51,9 @@ bool CBoolSchemaItem::getDefaultValue() const { return false; } +TypeID CBoolSchemaItem::GetType() { + return TYPE_BOOLEAN; +} + } // namespace ns_smart_objects } // namespace ns_smart_device_link diff --git a/src/components/smart_objects/src/object_schema_item.cc b/src/components/smart_objects/src/object_schema_item.cc index 27c64de7e2..c8eab82e8a 100644 --- a/src/components/smart_objects/src/object_schema_item.cc +++ b/src/components/smart_objects/src/object_schema_item.cc @@ -35,6 +35,7 @@ #include "generated_msg_version.h" #include "smart_objects/always_false_schema_item.h" +#include "smart_objects/enum_schema_item.h" #include "smart_objects/smart_object.h" namespace { @@ -104,7 +105,7 @@ std::shared_ptr<CObjectSchemaItem> CObjectSchemaItem::create( errors::eType CObjectSchemaItem::validate( const SmartObject& object, - rpc::ValidationReport* report__, + rpc::ValidationReport* report, const utils::SemanticVersion& MessageVersion, const bool allow_unknown_enums) { if (SmartType_Map != object.getType()) { @@ -112,7 +113,7 @@ errors::eType CObjectSchemaItem::validate( "Incorrect type, expected: " + SmartObject::typeToString(SmartType_Map) + ", got: " + SmartObject::typeToString(object.getType()); - report__->set_validation_info(validation_info); + report->set_validation_info(validation_info); return errors::INVALID_VALUE; } @@ -129,7 +130,7 @@ errors::eType CObjectSchemaItem::validate( if (correct_member && correct_member->mIsMandatory == true && correct_member->mIsRemoved == false) { std::string validation_info = "Missing mandatory parameter: " + key; - report__->set_validation_info(validation_info); + report->set_validation_info(validation_info); return errors::MISSING_MANDATORY_PARAMETER; } continue; @@ -141,7 +142,7 @@ errors::eType CObjectSchemaItem::validate( if (correct_member) { result = correct_member->mSchemaItem->validate(field, - &report__->ReportSubobject(key), + &report->ReportSubobject(key), MessageVersion, allow_unknown_enums); } else { @@ -157,6 +158,40 @@ errors::eType CObjectSchemaItem::validate( return errors::OK; } +bool CObjectSchemaItem::filterInvalidEnums( + SmartObject& Object, + const utils::SemanticVersion& MessageVersion, + rpc::ValidationReport* report) { + bool valid = true; + for (const auto& key : Object.enumerate()) { + auto members_it = mMembers.find(key); + if (mMembers.end() == members_it) { + // No members found for this key, skipping over + continue; + } + + const SMember* member = + GetCorrectMember(members_it->second, MessageVersion); + // Perform filtering recursively on this field + if (member->mSchemaItem->filterInvalidEnums( + Object[key], MessageVersion, &report->ReportSubobject(key))) { + // Object is no longer valid if the member is mandatory. + if (member->mIsMandatory) { + valid = false; + } + + // The member is safe to filter if it is non-mandatory, only leaf nodes + // (individual enum values) should be filtered otherwise. + bool should_erase = (member->mSchemaItem->GetType() == TYPE_ENUM || + !member->mIsMandatory); + if (should_erase) { + Object.erase(key); + } + } + } + return !valid; +} + void CObjectSchemaItem::applySchema( SmartObject& Object, const bool remove_unknown_parameters, @@ -165,10 +200,6 @@ void CObjectSchemaItem::applySchema( return; } - if (remove_unknown_parameters) { - RemoveFakeParams(Object, MessageVersion); - } - SmartObject default_value; for (const auto& item : mMembers) { @@ -185,6 +216,10 @@ void CObjectSchemaItem::applySchema( Object[key], remove_unknown_parameters, MessageVersion); } } + + if (remove_unknown_parameters) { + RemoveUnknownParams(Object, MessageVersion); + } } void CObjectSchemaItem::unapplySchema(SmartObject& Object, @@ -232,6 +267,10 @@ size_t CObjectSchemaItem::GetMemberSize() { return mMembers.size(); } +TypeID CObjectSchemaItem::GetType() { + return TYPE_OBJECT; +} + boost::optional<SMember&> CObjectSchemaItem::GetMemberSchemaItem( const std::string& member_key) { auto it = mMembers.find(member_key); @@ -250,7 +289,7 @@ void CObjectSchemaItem::AddMemberSchemaItem(const std::string& member_key, CObjectSchemaItem::CObjectSchemaItem(const Members& members) : mMembers(members) {} -void CObjectSchemaItem::RemoveFakeParams( +void CObjectSchemaItem::RemoveUnknownParams( SmartObject& Object, const utils::SemanticVersion& MessageVersion) { for (const auto& key : Object.enumerate()) { std::map<std::string, SMember>::const_iterator members_it = diff --git a/src/components/smart_objects/src/schema_item.cc b/src/components/smart_objects/src/schema_item.cc index 8c40e2c7bd..c05b99f19e 100644 --- a/src/components/smart_objects/src/schema_item.cc +++ b/src/components/smart_objects/src/schema_item.cc @@ -37,7 +37,7 @@ namespace ns_smart_objects { errors::eType ISchemaItem::validate( const SmartObject& object, - rpc::ValidationReport* report__, + rpc::ValidationReport* report, const utils::SemanticVersion& MessageVersion, const bool allow_unknown_enums) { return errors::ERROR; @@ -51,6 +51,13 @@ bool ISchemaItem::hasDefaultValue(SmartObject& Object) { return false; } +bool ISchemaItem::filterInvalidEnums( + SmartObject& Object, + const utils::SemanticVersion& MessageVersion, + rpc::ValidationReport* report) { + return false; +} + void ISchemaItem::applySchema(SmartObject& Object, const bool remove_unknown_parameters, const utils::SemanticVersion& MessageVersion) {} @@ -65,5 +72,9 @@ size_t ISchemaItem::GetMemberSize() { return 0; } +TypeID ISchemaItem::GetType() { + return TYPE_NONE; +} + } // namespace ns_smart_objects } // namespace ns_smart_device_link diff --git a/src/components/smart_objects/src/smart_object.cc b/src/components/smart_objects/src/smart_object.cc index d13ca87848..a8fc267615 100644 --- a/src/components/smart_objects/src/smart_object.cc +++ b/src/components/smart_objects/src/smart_object.cc @@ -892,11 +892,10 @@ bool SmartObject::isValid() const { } errors::eType SmartObject::validate( - rpc::ValidationReport* report__, + rpc::ValidationReport* report, const utils::SemanticVersion& MessageVersion, const bool allow_unknown_enums) { - return m_schema.validate( - *this, report__, MessageVersion, allow_unknown_enums); + return m_schema.validate(*this, report, MessageVersion, allow_unknown_enums); } void SmartObject::setSchema(const CSmartSchema& schema) { diff --git a/src/components/smart_objects/src/smart_schema.cc b/src/components/smart_objects/src/smart_schema.cc index 6107d19266..6deb08da3b 100644 --- a/src/components/smart_objects/src/smart_schema.cc +++ b/src/components/smart_objects/src/smart_schema.cc @@ -42,11 +42,11 @@ CSmartSchema::CSmartSchema(const ISchemaItemPtr SchemaItem) errors::eType CSmartSchema::validate( const SmartObject& object, - rpc::ValidationReport* report__, + rpc::ValidationReport* report, const utils::SemanticVersion& MessageVersion, const bool allow_unknown_enums) const { return mSchemaItem->validate( - object, report__, MessageVersion, allow_unknown_enums); + object, report, MessageVersion, allow_unknown_enums); } void CSmartSchema::setSchemaItem(const ISchemaItemPtr schemaItem) { @@ -59,8 +59,16 @@ ISchemaItemPtr CSmartSchema::getSchemaItem() { void CSmartSchema::applySchema(SmartObject& Object, const bool remove_unknown_parameters, - const utils::SemanticVersion& MessageVersion) { + const utils::SemanticVersion& MessageVersion, + rpc::ValidationReport* report) { mSchemaItem->applySchema(Object, remove_unknown_parameters, MessageVersion); + if (remove_unknown_parameters) { + rpc::ValidationReport dummy_report(""); + if (!report) { + report = &dummy_report; + } + mSchemaItem->filterInvalidEnums(Object, MessageVersion, report); + } } void CSmartSchema::unapplySchema(SmartObject& Object, diff --git a/src/components/smart_objects/src/string_schema_item.cc b/src/components/smart_objects/src/string_schema_item.cc index c4382174d0..907f698545 100644 --- a/src/components/smart_objects/src/string_schema_item.cc +++ b/src/components/smart_objects/src/string_schema_item.cc @@ -48,7 +48,7 @@ std::shared_ptr<CStringSchemaItem> CStringSchemaItem::create( errors::eType CStringSchemaItem::validate( const SmartObject& Object, - rpc::ValidationReport* report__, + rpc::ValidationReport* report, const utils::SemanticVersion& MessageVersion, const bool allow_unknown_enums) { if (SmartType_String != Object.getType()) { @@ -56,7 +56,7 @@ errors::eType CStringSchemaItem::validate( "Incorrect type, expected: " + SmartObject::typeToString(SmartType_String) + ", got: " + SmartObject::typeToString(Object.getType()); - report__->set_validation_info(validation_info); + report->set_validation_info(validation_info); return errors::INVALID_VALUE; } @@ -68,7 +68,7 @@ errors::eType CStringSchemaItem::validate( stream << "Got string of size: " << value.size() << ", minimum allowed: " << length; std::string validation_info = stream.str(); - report__->set_validation_info(validation_info); + report->set_validation_info(validation_info); return errors::OUT_OF_RANGE; } if (mMaxLength.getValue(length) && (value.size() > length)) { @@ -76,7 +76,7 @@ errors::eType CStringSchemaItem::validate( stream << "Got string of size: " << value.size() << ", maximum allowed: " << length; std::string validation_info = stream.str(); - report__->set_validation_info(validation_info); + report->set_validation_info(validation_info); return errors::OUT_OF_RANGE; } return errors::OK; @@ -90,6 +90,10 @@ std::string CStringSchemaItem::getDefaultValue() const { return std::string(""); } +TypeID CStringSchemaItem::GetType() { + return TYPE_STRING; +} + CStringSchemaItem::CStringSchemaItem( const TSchemaItemParameter<size_t>& MinLength, const TSchemaItemParameter<size_t>& MaxLength, diff --git a/src/components/smart_objects/test/ArraySchemaItem_test.cc b/src/components/smart_objects/test/ArraySchemaItem_test.cc index a22a27399d..b5ba73ea91 100644 --- a/src/components/smart_objects/test/ArraySchemaItem_test.cc +++ b/src/components/smart_objects/test/ArraySchemaItem_test.cc @@ -33,8 +33,9 @@ #include <string> #include "gmock/gmock.h" - #include "smart_objects/array_schema_item.h" +#include "smart_objects/enum_schema_item.h" +#include "smart_objects/object_schema_item.h" #include "smart_objects/smart_object.h" #include "smart_objects/string_schema_item.h" @@ -42,6 +43,15 @@ namespace test { namespace components { namespace smart_object_test { +namespace ExampleEnum { +enum eType { INVALID_ENUM = -1, Value0 = 0, Value1, Value2 }; +} // namespace ExampleEnum + +namespace Keys { +const char OPTIONAL_PARAM[] = "optionalParam"; +const char MANDATORY_PARAM[] = "mandatoryParam"; +} // namespace Keys + /** * Test ArraySchemaItem no schema item, no min and max size **/ @@ -345,6 +355,189 @@ TEST(test_map_validate, test_ArraySchemaItemTest) { EXPECT_EQ(std::string("Out of array"), obj["array"][4].asString()); } +TEST(test_array_with_unknown_enum, test_ArraySchemaItemTest) { + using namespace ns_smart_device_link::ns_smart_objects; + SmartObject obj; + std::set<ExampleEnum::eType> enum_values; + enum_values.insert(ExampleEnum::Value0); + enum_values.insert(ExampleEnum::Value1); + enum_values.insert(ExampleEnum::Value2); + + ISchemaItemPtr item = CArraySchemaItem::create( + TEnumSchemaItem<ExampleEnum::eType>::create(enum_values), + TSchemaItemParameter<size_t>(1)); + + obj[0] = "Value0"; + obj[1] = "Value10"; + obj[2] = "Value1"; + + item->applySchema(obj, true); + + rpc::ValidationReport report("RPC"); + EXPECT_FALSE( + item->filterInvalidEnums(obj, utils::SemanticVersion(), &report)); + EXPECT_NE(std::string(""), rpc::PrettyFormat(report)); + + EXPECT_EQ((size_t)2, obj.length()); + EXPECT_EQ(0, obj[0].asInt()); + EXPECT_EQ(1, obj[1].asInt()); + + report = rpc::ValidationReport("RPC"); + EXPECT_EQ(errors::OK, item->validate(obj, &report)); + EXPECT_EQ(std::string(""), rpc::PrettyFormat(report)); +} + +TEST(test_array_with_unknown_enums, test_ArraySchemaItemTest) { + using namespace ns_smart_device_link::ns_smart_objects; + SmartObject obj; + std::set<ExampleEnum::eType> enum_values; + enum_values.insert(ExampleEnum::Value0); + enum_values.insert(ExampleEnum::Value1); + enum_values.insert(ExampleEnum::Value2); + + ISchemaItemPtr item = CArraySchemaItem::create( + TEnumSchemaItem<ExampleEnum::eType>::create(enum_values), + TSchemaItemParameter<size_t>(1)); + + obj[0] = "Value10"; + obj[1] = "Value11"; + obj[2] = "Value12"; + + item->applySchema(obj, true); + + rpc::ValidationReport report("RPC"); + EXPECT_TRUE(item->filterInvalidEnums(obj, utils::SemanticVersion(), &report)); + EXPECT_NE(std::string(""), rpc::PrettyFormat(report)); + + EXPECT_EQ((size_t)0, obj.length()); + + report = rpc::ValidationReport("RPC"); + EXPECT_EQ(errors::OUT_OF_RANGE, item->validate(obj, &report)); + EXPECT_NE(std::string(""), rpc::PrettyFormat(report)); +} + +TEST(test_array_of_objects_with_unknown_enum, test_ArraySchemaItemTest) { + using namespace ns_smart_device_link::ns_smart_objects; + SmartObject obj; + std::set<ExampleEnum::eType> enum_values; + enum_values.insert(ExampleEnum::Value0); + enum_values.insert(ExampleEnum::Value1); + enum_values.insert(ExampleEnum::Value2); + + Members structMembersMap; + structMembersMap[Keys::OPTIONAL_PARAM] = + SMember(TEnumSchemaItem<ExampleEnum::eType>::create(enum_values), false); + structMembersMap[Keys::MANDATORY_PARAM] = + SMember(TEnumSchemaItem<ExampleEnum::eType>::create(enum_values), true); + + ISchemaItemPtr item = + CArraySchemaItem::create(CObjectSchemaItem::create(structMembersMap), + TSchemaItemParameter<size_t>(1)); + + SmartObject struct1; + struct1[Keys::MANDATORY_PARAM] = "Value0"; + SmartObject struct2; + struct2[Keys::MANDATORY_PARAM] = "Value11"; + SmartObject struct3; + struct3[Keys::MANDATORY_PARAM] = "Value2"; + obj[0] = struct1; + obj[1] = struct2; + obj[2] = struct3; + + item->applySchema(obj, true); + + rpc::ValidationReport report("RPC"); + EXPECT_FALSE( + item->filterInvalidEnums(obj, utils::SemanticVersion(), &report)); + EXPECT_NE(std::string(""), rpc::PrettyFormat(report)); + + EXPECT_EQ((size_t)2, obj.length()); + EXPECT_EQ(0, obj[0][Keys::MANDATORY_PARAM].asInt()); + EXPECT_EQ(2, obj[1][Keys::MANDATORY_PARAM].asInt()); + + report = rpc::ValidationReport("RPC"); + EXPECT_EQ(errors::OK, item->validate(obj, &report)); + EXPECT_EQ(std::string(""), rpc::PrettyFormat(report)); +} + +TEST(test_array_of_objects_with_unknown_optional_enums, + test_ArraySchemaItemTest) { + using namespace ns_smart_device_link::ns_smart_objects; + SmartObject obj; + std::set<ExampleEnum::eType> enum_values; + enum_values.insert(ExampleEnum::Value0); + enum_values.insert(ExampleEnum::Value1); + enum_values.insert(ExampleEnum::Value2); + + Members structMembersMap; + structMembersMap[Keys::OPTIONAL_PARAM] = + SMember(TEnumSchemaItem<ExampleEnum::eType>::create(enum_values), false); + structMembersMap[Keys::MANDATORY_PARAM] = + SMember(TEnumSchemaItem<ExampleEnum::eType>::create(enum_values), true); + + ISchemaItemPtr item = + CArraySchemaItem::create(CObjectSchemaItem::create(structMembersMap), + TSchemaItemParameter<size_t>(1)); + + SmartObject struct1; + struct1[Keys::OPTIONAL_PARAM] = "Value10"; + struct1[Keys::MANDATORY_PARAM] = "Value0"; + SmartObject struct2; + struct2[Keys::OPTIONAL_PARAM] = "Value0"; + struct2[Keys::MANDATORY_PARAM] = "Value1"; + SmartObject struct3; + struct3[Keys::OPTIONAL_PARAM] = "Value12"; + struct3[Keys::MANDATORY_PARAM] = "Value2"; + obj[0] = struct1; + obj[1] = struct2; + obj[2] = struct3; + + item->applySchema(obj, true); + + rpc::ValidationReport report("RPC"); + EXPECT_FALSE( + item->filterInvalidEnums(obj, utils::SemanticVersion(), &report)); + EXPECT_NE(std::string(""), rpc::PrettyFormat(report)); + + // Unknown sub-parameter values should be filtered, but not array elements + EXPECT_EQ((size_t)3, obj.length()); + EXPECT_EQ(0, obj[0][Keys::MANDATORY_PARAM].asInt()); + EXPECT_FALSE(obj[0].keyExists(Keys::OPTIONAL_PARAM)); + EXPECT_EQ(1, obj[1][Keys::MANDATORY_PARAM].asInt()); + EXPECT_EQ(0, obj[1][Keys::OPTIONAL_PARAM].asInt()); + EXPECT_EQ(2, obj[2][Keys::MANDATORY_PARAM].asInt()); + EXPECT_FALSE(obj[2].keyExists(Keys::OPTIONAL_PARAM)); + + report = rpc::ValidationReport("RPC"); + EXPECT_EQ(errors::OK, item->validate(obj, &report)); + EXPECT_EQ(std::string(""), rpc::PrettyFormat(report)); +} + } // namespace smart_object_test } // namespace components } // namespace test + +namespace ns_smart_device_link { +namespace ns_smart_objects { + +namespace ExampleEnum = test::components::smart_object_test::ExampleEnum; +typedef EnumConversionHelper<ExampleEnum::eType> EnumConverter; + +template <> +const EnumConverter::EnumToCStringMap EnumConverter::enum_to_cstring_map_ = + EnumConverter::InitEnumToCStringMap(); + +template <> +const EnumConverter::CStringToEnumMap EnumConverter::cstring_to_enum_map_ = + EnumConverter::InitCStringToEnumMap(); + +template <> +const char* const EnumConverter::cstring_values_[] = { + "Value0", "Value1", "Value2"}; + +template <> +const ExampleEnum::eType EnumConverter::enum_values_[] = { + ExampleEnum::Value0, ExampleEnum::Value1, ExampleEnum::Value2}; + +} // namespace ns_smart_objects +} // namespace ns_smart_device_link diff --git a/src/components/smart_objects/test/CObjectSchemaItem_test.cc b/src/components/smart_objects/test/CObjectSchemaItem_test.cc index 8a7d09f31e..477d950257 100644 --- a/src/components/smart_objects/test/CObjectSchemaItem_test.cc +++ b/src/components/smart_objects/test/CObjectSchemaItem_test.cc @@ -89,6 +89,9 @@ namespace Keys { const char RESULT_CODE[] = "resultCode"; const char INFO[] = "info"; const char SUCCESS[] = "success"; +const char STRUCT[] = "struct"; +const char OPTIONAL_PARAM[] = "optionalParam"; +const char MANDATORY_PARAM[] = "mandatoryParam"; } // namespace Keys class ObjectSchemaItemTest : public ::testing::Test { @@ -127,6 +130,12 @@ class ObjectSchemaItemTest : public ::testing::Test { TSchemaItemParameter<int>(2)), true); + Members structMembersMap; + structMembersMap[Keys::OPTIONAL_PARAM] = SMember( + TEnumSchemaItem<FunctionID::eType>::create(function_values), false); + structMembersMap[Keys::MANDATORY_PARAM] = SMember( + TEnumSchemaItem<FunctionID::eType>::create(function_values), true); + Members schemaMembersMap; schemaMembersMap[Keys::RESULT_CODE] = SMember( TEnumSchemaItem<ResultType::eType>::create(resultCode_values), false); @@ -135,6 +144,8 @@ class ObjectSchemaItemTest : public ::testing::Test { TSchemaItemParameter<size_t>(10)), false); schemaMembersMap[Keys::SUCCESS] = SMember(CBoolSchemaItem::create(), false); + schemaMembersMap[Keys::STRUCT] = + SMember(CObjectSchemaItem::create(structMembersMap), false); // Create fake param that has breaking history changes std::vector<SMember> fake_param_history_vector; @@ -521,6 +532,97 @@ TEST_F(ObjectSchemaItemTest, test_strings_to_enum_conversion) { } } +TEST_F(ObjectSchemaItemTest, filter_unknown_enums_non_mandatory_param) { + SmartObject obj; + obj[S_PARAMS][S_FUNCTION_ID] = 1; + obj[S_PARAMS][S_CORRELATION_ID] = 0xFF; + obj[S_PARAMS][S_PROTOCOL_VERSION] = 2; + obj[S_MSG_PARAMS][Keys::RESULT_CODE] = "FUTURE"; + obj[S_MSG_PARAMS][Keys::INFO] = "0123456789"; + + schema_item->applySchema(obj, false); + rpc::ValidationReport report("RPC"); + EXPECT_FALSE( + schema_item->filterInvalidEnums(obj, utils::SemanticVersion(), &report)); + EXPECT_NE(std::string(""), rpc::PrettyFormat(report)); + + // The unknown enum value was filtered. Validation should pass in this case. + EXPECT_FALSE(obj[S_MSG_PARAMS].keyExists(Keys::RESULT_CODE)); + report = rpc::ValidationReport("RPC"); + EXPECT_EQ(errors::OK, schema_item->validate(obj, &report)); + EXPECT_EQ(std::string(""), rpc::PrettyFormat(report)); +} + +TEST_F(ObjectSchemaItemTest, filter_unknown_enums_mandatory) { + SmartObject obj; + obj[S_PARAMS][S_FUNCTION_ID] = "FUTURE"; + obj[S_PARAMS][S_CORRELATION_ID] = 0xFF; + obj[S_PARAMS][S_PROTOCOL_VERSION] = 2; + obj[S_MSG_PARAMS][Keys::RESULT_CODE] = 2; + obj[S_MSG_PARAMS][Keys::INFO] = "0123456789"; + + schema_item->applySchema(obj, false); + rpc::ValidationReport report("RPC"); + EXPECT_TRUE( + schema_item->filterInvalidEnums(obj, utils::SemanticVersion(), &report)); + EXPECT_NE(std::string(""), rpc::PrettyFormat(report)); + + EXPECT_FALSE(obj[S_PARAMS].keyExists(S_FUNCTION_ID)); + report = rpc::ValidationReport("RPC"); + EXPECT_EQ(errors::MISSING_MANDATORY_PARAMETER, + schema_item->validate(obj, &report)); + EXPECT_NE(std::string(""), rpc::PrettyFormat(report)); +} + +TEST_F(ObjectSchemaItemTest, filter_unknown_enums_non_mandatory_subparam) { + SmartObject obj; + obj[S_PARAMS][S_FUNCTION_ID] = 1; + obj[S_PARAMS][S_CORRELATION_ID] = 0xFF; + obj[S_PARAMS][S_PROTOCOL_VERSION] = 2; + obj[S_MSG_PARAMS][Keys::STRUCT][Keys::OPTIONAL_PARAM] = "FUTURE"; + obj[S_MSG_PARAMS][Keys::STRUCT][Keys::MANDATORY_PARAM] = 1; + obj[S_MSG_PARAMS][Keys::RESULT_CODE] = 2; + obj[S_MSG_PARAMS][Keys::INFO] = "0123456789"; + + schema_item->applySchema(obj, false); + rpc::ValidationReport report("RPC"); + EXPECT_FALSE( + schema_item->filterInvalidEnums(obj, utils::SemanticVersion(), &report)); + EXPECT_NE(std::string(""), rpc::PrettyFormat(report)); + + // The unknown enum value was filtered. + // Validation should pass in this case. + ASSERT_TRUE(obj[S_MSG_PARAMS].keyExists(Keys::STRUCT)); + EXPECT_FALSE(obj[S_MSG_PARAMS][Keys::STRUCT].keyExists(Keys::OPTIONAL_PARAM)); + EXPECT_TRUE(obj[S_MSG_PARAMS][Keys::STRUCT].keyExists(Keys::MANDATORY_PARAM)); + report = rpc::ValidationReport("RPC"); + EXPECT_EQ(errors::OK, schema_item->validate(obj, &report)); + EXPECT_EQ(std::string(""), rpc::PrettyFormat(report)); +} + +TEST_F(ObjectSchemaItemTest, filter_unknown_enums_mandatory_subparam) { + SmartObject obj; + obj[S_PARAMS][S_FUNCTION_ID] = 1; + obj[S_PARAMS][S_CORRELATION_ID] = 0xFF; + obj[S_PARAMS][S_PROTOCOL_VERSION] = 2; + obj[S_MSG_PARAMS][Keys::STRUCT][Keys::MANDATORY_PARAM] = "FUTURE"; + obj[S_MSG_PARAMS][Keys::RESULT_CODE] = 2; + obj[S_MSG_PARAMS][Keys::INFO] = "0123456789"; + + schema_item->applySchema(obj, false); + rpc::ValidationReport report("RPC"); + EXPECT_FALSE( + schema_item->filterInvalidEnums(obj, utils::SemanticVersion(), &report)); + EXPECT_NE(std::string(""), rpc::PrettyFormat(report)); + + // The struct containing the unknown enum value was filtered. + // Validation should pass in this case. + EXPECT_FALSE(obj[S_MSG_PARAMS].keyExists(Keys::STRUCT)); + report = rpc::ValidationReport("RPC"); + EXPECT_EQ(errors::OK, schema_item->validate(obj, &report)); + EXPECT_EQ(std::string(""), rpc::PrettyFormat(report)); +} + } // namespace smart_object_test } // namespace components } // namespace test @@ -529,20 +631,20 @@ namespace ns_smart_device_link { namespace ns_smart_objects { namespace FunctionID = test::components::smart_object_test::FunctionID; -typedef EnumConversionHelper<FunctionID::eType> FunctionConvertor; +typedef EnumConversionHelper<FunctionID::eType> FunctionConverter; template <> -const FunctionConvertor::EnumToCStringMap - FunctionConvertor::enum_to_cstring_map_ = - FunctionConvertor::InitEnumToCStringMap(); +const FunctionConverter::EnumToCStringMap + FunctionConverter::enum_to_cstring_map_ = + FunctionConverter::InitEnumToCStringMap(); template <> -const FunctionConvertor::CStringToEnumMap - FunctionConvertor::cstring_to_enum_map_ = - FunctionConvertor::InitCStringToEnumMap(); +const FunctionConverter::CStringToEnumMap + FunctionConverter::cstring_to_enum_map_ = + FunctionConverter::InitCStringToEnumMap(); template <> -const char* const FunctionConvertor::cstring_values_[] = {"Function0", +const char* const FunctionConverter::cstring_values_[] = {"Function0", "Function1", "Function2", "Function3", @@ -551,7 +653,7 @@ const char* const FunctionConvertor::cstring_values_[] = {"Function0", "Function6"}; template <> -const FunctionID::eType FunctionConvertor::enum_values_[] = { +const FunctionID::eType FunctionConverter::enum_values_[] = { FunctionID::Function0, FunctionID::Function1, FunctionID::Function2, @@ -563,20 +665,20 @@ const FunctionID::eType FunctionConvertor::enum_values_[] = { // ---------------------------------------------------------------------------- namespace ResultType = test::components::smart_object_test::ResultType; -typedef EnumConversionHelper<ResultType::eType> ResultTypeConvertor; +typedef EnumConversionHelper<ResultType::eType> ResultTypeConverter; template <> -const ResultTypeConvertor::EnumToCStringMap - ResultTypeConvertor::enum_to_cstring_map_ = - ResultTypeConvertor::InitEnumToCStringMap(); +const ResultTypeConverter::EnumToCStringMap + ResultTypeConverter::enum_to_cstring_map_ = + ResultTypeConverter::InitEnumToCStringMap(); template <> -const ResultTypeConvertor::CStringToEnumMap - ResultTypeConvertor::cstring_to_enum_map_ = - ResultTypeConvertor::InitCStringToEnumMap(); +const ResultTypeConverter::CStringToEnumMap + ResultTypeConverter::cstring_to_enum_map_ = + ResultTypeConverter::InitCStringToEnumMap(); template <> -const char* const ResultTypeConvertor::cstring_values_[] = { +const char* const ResultTypeConverter::cstring_values_[] = { "APPLICATION_NOT_REGISTERED", "SUCCESS", "TOO_MANY_PENDING_REQUESTS", @@ -589,7 +691,7 @@ const char* const ResultTypeConvertor::cstring_values_[] = { "DISALLOWED"}; template <> -const ResultType::eType ResultTypeConvertor::enum_values_[] = { +const ResultType::eType ResultTypeConverter::enum_values_[] = { ResultType::APPLICATION_NOT_REGISTERED, ResultType::SUCCESS, ResultType::TOO_MANY_PENDING_REQUESTS, |