summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrii Kalinich (GitHub) <AKalinich@luxoft.com>2021-08-10 10:15:25 -0400
committerGitHub <noreply@github.com>2021-08-10 10:15:25 -0400
commitf51f4fd4c7475b30cbf2c2dbc4507ac13583b7bf (patch)
treee84aaa1c56abadd921813fda863217fd98857020
parent595d76585bdcc110ae4093a62f7ff77445aa88e2 (diff)
downloadsdl_core-f51f4fd4c7475b30cbf2c2dbc4507ac13583b7bf.tar.gz
Fix sub menues deletion wrong order (#3748)
* Fix wrong requests order for recursive deletion The issue which was observed is that SDL sends `DeleteSubMenu` request to HMI for a "parent node" submenu and then sends subsequent `DeleteSubMenu` requests recursively for all child nodes starting from the bottom one. Such order confuses HMI because deletion of parent node may automatically trigger deletion of all its child nodes on HMI side so subsequent requests from SDL for a child nodes might be rejected. To make sure that HMI removes all the hierarchy properly, SDL should start deletion sequence from the bottom nodes and delete the parent node in the end. To resolve that issue, DeleteSubMenu request logic was updated. Currently, SDL recursively iterates through the submenu and command nodes and collects them in a queue. Once queue is ready, SDL sends requests one by one, waiting for a HMI response for each sent request before sending the subsequent. Once the responses to all requests are received, SDL sends the final response to mobile app and finalizes the command. * Updated DeleteSubMenu unit tests to cover new logic
-rw-r--r--src/components/application_manager/rpc_plugins/sdl_rpc_plugin/include/sdl_rpc_plugin/commands/mobile/delete_sub_menu_request.h31
-rw-r--r--src/components/application_manager/rpc_plugins/sdl_rpc_plugin/src/commands/mobile/delete_sub_menu_request.cc192
-rw-r--r--src/components/application_manager/rpc_plugins/sdl_rpc_plugin/test/commands/mobile/delete_sub_menu_test.cc498
3 files changed, 523 insertions, 198 deletions
diff --git a/src/components/application_manager/rpc_plugins/sdl_rpc_plugin/include/sdl_rpc_plugin/commands/mobile/delete_sub_menu_request.h b/src/components/application_manager/rpc_plugins/sdl_rpc_plugin/include/sdl_rpc_plugin/commands/mobile/delete_sub_menu_request.h
index af2ba4a1ea..20fff456d5 100644
--- a/src/components/application_manager/rpc_plugins/sdl_rpc_plugin/include/sdl_rpc_plugin/commands/mobile/delete_sub_menu_request.h
+++ b/src/components/application_manager/rpc_plugins/sdl_rpc_plugin/include/sdl_rpc_plugin/commands/mobile/delete_sub_menu_request.h
@@ -82,34 +82,45 @@ class DeleteSubMenuRequest : public app_mngr::commands::CommandRequestImpl {
bool Init() FINAL;
private:
- /*
- * @brief Deletes submenus that have a parentID that matches the parentID
- * parameter
+ /**
+ * @brief Creates and queues up delete requests for a submenus that have a
+ * parent ID which matches the parentID parameter
*
* @param app_id Application ID
* @param parentID Parent ID of a nested submenu
*/
void DeleteNestedSubMenus(app_mngr::ApplicationSharedPtr const app,
- uint32_t parentID,
+ const uint32_t parentID,
const app_mngr::SubMenuMap& subMenus);
- /*
- * @brief Deletes VR commands from SDL for corresponding submenu ID
+ /**
+ * @brief Creates and queues up delete requests for each VR command tied to
+ * the given submenu ID
*
* @param app_id Application ID
* @param parentID Parent ID of a nested submenu
*/
void DeleteSubMenuVRCommands(app_mngr::ApplicationConstSharedPtr app,
- uint32_t parentID);
+ const uint32_t parentID);
- /*
- * @brief Deletes UI commands from SDL for corresponding submenu ID
+ /**
+ * @brief Creates and queues up delete requests for each UI command tied to
+ * the given submenu ID
*
* @param app_id Application ID
* @param parentID Parent ID of a nested submenu
*/
void DeleteSubMenuUICommands(app_mngr::ApplicationSharedPtr const app,
- uint32_t parentID);
+ const uint32_t parentID);
+
+ /**
+ * @brief Takes the next request in the queue and sends it to HMI
+ */
+ void SendNextRequest();
+
+ typedef std::list<smart_objects::SmartObject> RequestsList;
+ RequestsList requests_list_;
+ uint32_t pending_request_corr_id_;
DISALLOW_COPY_AND_ASSIGN(DeleteSubMenuRequest);
};
diff --git a/src/components/application_manager/rpc_plugins/sdl_rpc_plugin/src/commands/mobile/delete_sub_menu_request.cc b/src/components/application_manager/rpc_plugins/sdl_rpc_plugin/src/commands/mobile/delete_sub_menu_request.cc
index 19ec2dfb27..49e76ae327 100644
--- a/src/components/application_manager/rpc_plugins/sdl_rpc_plugin/src/commands/mobile/delete_sub_menu_request.cc
+++ b/src/components/application_manager/rpc_plugins/sdl_rpc_plugin/src/commands/mobile/delete_sub_menu_request.cc
@@ -56,7 +56,9 @@ DeleteSubMenuRequest::DeleteSubMenuRequest(
application_manager,
rpc_service,
hmi_capabilities,
- policy_handler) {}
+ policy_handler)
+ , requests_list_()
+ , pending_request_corr_id_(0) {}
DeleteSubMenuRequest::~DeleteSubMenuRequest() {}
@@ -82,19 +84,42 @@ void DeleteSubMenuRequest::Run() {
return;
}
+ {
+ const DataAccessor<SubMenuMap> accessor = app->sub_menu_map();
+ const SubMenuMap& sub_menus = accessor.GetData();
+ DeleteNestedSubMenus(app, menu_id, sub_menus);
+ }
+
smart_objects::SmartObject msg_params =
smart_objects::SmartObject(smart_objects::SmartType_Map);
-
msg_params[strings::menu_id] =
(*message_)[strings::msg_params][strings::menu_id];
msg_params[strings::app_id] = app->app_id();
+ requests_list_.push_back(msg_params);
+
StartAwaitForInterface(HmiInterfaces::HMI_INTERFACE_UI);
+ SendNextRequest();
+}
- SendHMIRequest(hmi_apis::FunctionID::UI_DeleteSubMenu, &msg_params, true);
+void DeleteSubMenuRequest::SendNextRequest() {
+ SDL_LOG_AUTO_TRACE();
+
+ const auto request_params = requests_list_.front();
+ auto function_id = hmi_apis::FunctionID::UI_DeleteSubMenu;
+
+ if (request_params.keyExists(strings::cmd_id)) {
+ function_id = request_params.keyExists(strings::grammar_id)
+ ? hmi_apis::FunctionID::VR_DeleteCommand
+ : hmi_apis::FunctionID::UI_DeleteCommand;
+ }
+
+ pending_request_corr_id_ = SendHMIRequest(function_id, &request_params, true);
+ SDL_LOG_DEBUG(
+ "Waiting for response for corr_id = " << pending_request_corr_id_);
}
void DeleteSubMenuRequest::DeleteNestedSubMenus(ApplicationSharedPtr const app,
- uint32_t parentID,
+ const uint32_t parentID,
const SubMenuMap& subMenus) {
SDL_LOG_AUTO_TRACE();
@@ -108,26 +133,26 @@ void DeleteSubMenuRequest::DeleteNestedSubMenus(ApplicationSharedPtr const app,
}
if (parentID == (*it->second)[strings::parent_id].asUInt()) {
- uint32_t menuID = (*it->second)[strings::menu_id].asUInt();
+ const uint32_t menuID = (*it->second)[strings::menu_id].asUInt();
DeleteNestedSubMenus(app, menuID, subMenus);
- DeleteSubMenuVRCommands(app, menuID);
- DeleteSubMenuUICommands(app, menuID);
+
smart_objects::SmartObject msg_params =
smart_objects::SmartObject(smart_objects::SmartType_Map);
msg_params[strings::menu_id] = menuID;
msg_params[strings::app_id] = app->app_id();
- SendHMIRequest(hmi_apis::FunctionID::UI_DeleteSubMenu, &msg_params);
- ++it;
- SDL_LOG_DEBUG("Removing submenuID: " << menuID);
- app->RemoveSubMenu(menuID);
- } else {
- ++it;
+ requests_list_.push_back(msg_params);
}
+
+ ++it;
}
+
+ SDL_LOG_DEBUG("Delete commands with Parent ID: " << parentID);
+ DeleteSubMenuVRCommands(app, parentID);
+ DeleteSubMenuUICommands(app, parentID);
}
void DeleteSubMenuRequest::DeleteSubMenuVRCommands(
- ApplicationConstSharedPtr app, uint32_t parentID) {
+ ApplicationConstSharedPtr app, const uint32_t parentID) {
SDL_LOG_AUTO_TRACE();
const DataAccessor<CommandsMap> accessor = app->commands_map();
@@ -148,7 +173,7 @@ void DeleteSubMenuRequest::DeleteSubMenuVRCommands(
msg_params[strings::grammar_id] = app->get_grammar_id();
msg_params[strings::type] = hmi_apis::Common_VRCommandType::Command;
- SendHMIRequest(hmi_apis::FunctionID::VR_DeleteCommand, &msg_params);
+ requests_list_.push_back(msg_params);
}
}
}
@@ -175,16 +200,11 @@ void DeleteSubMenuRequest::DeleteSubMenuUICommands(
const uint32_t cmd_id = (*it->second)[strings::cmd_id].asUInt();
msg_params[strings::app_id] = app->app_id();
msg_params[strings::cmd_id] = cmd_id;
- SDL_LOG_DEBUG("Removing UI Command: " << cmd_id);
- app->RemoveCommand(cmd_id);
- app->help_prompt_manager().OnVrCommandDeleted(cmd_id, false);
- it = commands.begin(); // Can not relay on
- // iterators after erase was called
-
- SendHMIRequest(hmi_apis::FunctionID::UI_DeleteCommand, &msg_params);
- } else {
- ++it;
+
+ requests_list_.push_back(msg_params);
}
+
+ ++it;
}
}
@@ -193,48 +213,110 @@ void DeleteSubMenuRequest::on_event(const event_engine::Event& event) {
const smart_objects::SmartObject& message = event.smart_object();
switch (event.id()) {
- case hmi_apis::FunctionID::UI_DeleteSubMenu: {
- EndAwaitForInterface(HmiInterfaces::HMI_INTERFACE_UI);
- hmi_apis::Common_Result::eType result_code =
- static_cast<hmi_apis::Common_Result::eType>(
- message[strings::params][hmi_response::code].asInt());
- std::string response_info;
- GetInfo(message, response_info);
- const bool result = PrepareResultForMobileResponse(
- result_code, HmiInterfaces::HMI_INTERFACE_UI);
-
- ApplicationSharedPtr application =
- application_manager_.application(connection_key());
-
- if (!application) {
- SDL_LOG_ERROR("NULL pointer");
- return;
+ case hmi_apis::FunctionID::UI_DeleteCommand: {
+ SDL_LOG_DEBUG("Received UI_DeleteCommand response");
+
+ const auto corr_id =
+ message[strings::params][strings::correlation_id].asUInt();
+ if (pending_request_corr_id_ == corr_id) {
+ auto msg_params = requests_list_.front();
+
+ const auto result_code = static_cast<hmi_apis::Common_Result::eType>(
+ message[strings::params][hmi_response::code].asInt());
+
+ auto app = application_manager_.application(connection_key());
+ if (!app) {
+ SDL_LOG_ERROR("Application not found");
+ return;
+ }
+
+ if (IsHMIResultSuccess(result_code)) {
+ const auto cmd_id = msg_params[strings::cmd_id].asUInt();
+ SDL_LOG_DEBUG("Removing UI Command: " << cmd_id);
+ app->RemoveCommand(cmd_id);
+ app->help_prompt_manager().OnVrCommandDeleted(cmd_id, false);
+ }
+
+ requests_list_.pop_front();
}
- if (result) {
- // delete sub menu items from SDL and HMI
- uint32_t parentID =
- (*message_)[strings::msg_params][strings::menu_id].asUInt();
- const DataAccessor<SubMenuMap> accessor = application->sub_menu_map();
- const SubMenuMap& subMenus = accessor.GetData();
- DeleteNestedSubMenus(application, parentID, subMenus);
- DeleteSubMenuVRCommands(application, parentID);
- DeleteSubMenuUICommands(application, parentID);
- application->RemoveSubMenu(
- (*message_)[strings::msg_params][strings::menu_id].asInt());
+ break;
+ }
+
+ case hmi_apis::FunctionID::VR_DeleteCommand: {
+ SDL_LOG_DEBUG("Received VR_DeleteCommand response");
+
+ const auto corr_id =
+ message[strings::params][strings::correlation_id].asUInt();
+
+ if (corr_id == pending_request_corr_id_) {
+ auto app = application_manager_.application(connection_key());
+ if (!app) {
+ SDL_LOG_ERROR("Application not found");
+ return;
+ }
+
+ requests_list_.pop_front();
}
- SendResponse(result,
- MessageHelper::HMIToMobileResult(result_code),
- response_info.empty() ? NULL : response_info.c_str(),
- &(message[strings::msg_params]));
break;
}
+
+ case hmi_apis::FunctionID::UI_DeleteSubMenu: {
+ SDL_LOG_DEBUG("Received UI_DeleteSubMenu response");
+
+ const auto corr_id =
+ message[strings::params][strings::correlation_id].asUInt();
+ if (corr_id == pending_request_corr_id_) {
+ auto msg_params = requests_list_.front();
+
+ const auto result_code = static_cast<hmi_apis::Common_Result::eType>(
+ message[strings::params][hmi_response::code].asInt());
+
+ auto app = application_manager_.application(connection_key());
+ if (!app) {
+ SDL_LOG_ERROR("Application not found");
+ return;
+ }
+
+ if (IsHMIResultSuccess(result_code)) {
+ const auto menu_id = msg_params[strings::menu_id].asUInt();
+ SDL_LOG_DEBUG("Removing submenuID: " << menu_id);
+ app->RemoveSubMenu(menu_id);
+ }
+
+ requests_list_.pop_front();
+ }
+
+ break;
+ }
+
default: {
SDL_LOG_ERROR("Received unknown event" << event.id());
return;
}
}
+
+ if (!requests_list_.empty()) {
+ SDL_LOG_DEBUG("Still waiting for another requests");
+ SendNextRequest();
+ return;
+ }
+
+ EndAwaitForInterface(HmiInterfaces::HMI_INTERFACE_UI);
+
+ hmi_apis::Common_Result::eType result_code =
+ static_cast<hmi_apis::Common_Result::eType>(
+ message[strings::params][hmi_response::code].asInt());
+ std::string response_info;
+ GetInfo(message, response_info);
+ const bool result = PrepareResultForMobileResponse(
+ result_code, HmiInterfaces::HMI_INTERFACE_UI);
+
+ SendResponse(result,
+ MessageHelper::HMIToMobileResult(result_code),
+ response_info.empty() ? NULL : response_info.c_str(),
+ &(message[strings::msg_params]));
}
bool DeleteSubMenuRequest::Init() {
diff --git a/src/components/application_manager/rpc_plugins/sdl_rpc_plugin/test/commands/mobile/delete_sub_menu_test.cc b/src/components/application_manager/rpc_plugins/sdl_rpc_plugin/test/commands/mobile/delete_sub_menu_test.cc
index f5856a8eda..975cba89a1 100644
--- a/src/components/application_manager/rpc_plugins/sdl_rpc_plugin/test/commands/mobile/delete_sub_menu_test.cc
+++ b/src/components/application_manager/rpc_plugins/sdl_rpc_plugin/test/commands/mobile/delete_sub_menu_test.cc
@@ -67,6 +67,7 @@ using sdl_rpc_plugin::commands::DeleteSubMenuResponse;
typedef std::shared_ptr<DeleteSubMenuRequest> DeleteSubMenuRequestPtr;
typedef std::shared_ptr<DeleteSubMenuResponse> DeleteSubMenuResponsePtr;
+typedef std::shared_ptr<Event> EventPtr;
MATCHER_P(CheckMessageResultCode, result_code, "") {
return (*arg)[am::strings::msg_params][am::strings::result_code].asInt() ==
@@ -89,8 +90,9 @@ namespace {
const uint32_t kConnectionKey = 2u;
const uint32_t kCorrelationId = 10u;
const uint32_t kMenuId = 100u;
+const uint32_t kMenuIdChild = 101u;
const uint32_t kGrammarId = 101u;
-const int32_t kCmdId = 102;
+const int32_t kCmdId = 102u;
} // namespace
class DeleteSubMenuRequestTest
@@ -107,6 +109,224 @@ class DeleteSubMenuRequestTest
std::make_shared<am_test::MockHelpPromptManager>())
, app_(CreateMockApp()) {}
+ /**
+ * @brief Generates submenu smart object with specified params
+ * @param menu_id id of the menu
+ * @param parent_id id of parent menu
+ * @return generated smart object
+ */
+ smart_objects::SmartObjectSPtr GenerateSubMenuMap(const uint32_t menu_id,
+ const uint32_t parent_id) {
+ smart_objects::SmartObjectSPtr smartObjectPtr =
+ std::make_shared<smart_objects::SmartObject>();
+
+ smart_objects::SmartObject& object = *smartObjectPtr;
+
+ object[am::strings::position] = 1;
+ object[am::strings::menu_name] = "SubMenu " + std::to_string(menu_id);
+ object[am::strings::menu_id] = menu_id;
+ object[am::strings::parent_id] = parent_id;
+
+ return smartObjectPtr;
+ }
+
+ /**
+ * @brief Generates UI & VR commands smart object with specified params
+ * @param cmd_id id of the command
+ * @param parent_id id of parent command
+ * @return generated smart object
+ */
+ smart_objects::SmartObjectSPtr GenerateUiVrCommandMapChild(
+ const uint32_t cmd_id, const uint32_t parent_id) {
+ smart_objects::SmartObjectSPtr smartObjectPtr =
+ std::make_shared<smart_objects::SmartObject>();
+
+ smart_objects::SmartObject& object = *smartObjectPtr;
+
+ object[am::strings::cmd_id] = cmd_id;
+ object[am::strings::grammar_id] = kGrammarId;
+ object[am::strings::vr_commands] = "VR commands";
+ object[am::strings::type] = hmi_apis::Common_VRCommandType::Command;
+ object[am::strings::menu_params][am::hmi_request::parent_id] = parent_id;
+
+ return smartObjectPtr;
+ }
+
+ /**
+ * @brief Sets up expectations for a successful execution of submenu request
+ * @param next_function_id function id of the next request
+ */
+ void SetUpSubMenuRequestExpectations(
+ const hmi_apis::FunctionID::eType next_function_id) {
+ (*message_)[am::strings::msg_params][am::strings::menu_id] = kMenuId;
+ (*message_)[am::strings::params][am::strings::connection_key] =
+ kConnectionKey;
+ (*message_)[am::strings::params][am::strings::function_id] =
+ next_function_id;
+
+ smart_objects::SmartObject sub_menu =
+ (*message_)[am::strings::msg_params][am::strings::menu_id];
+ EXPECT_CALL(app_mngr_, application(kConnectionKey)).WillOnce(Return(app_));
+ EXPECT_CALL(*app_, FindSubMenu(kMenuId)).WillOnce(Return(sub_menu));
+
+ ON_CALL(*app_, sub_menu_map()).WillByDefault(Return(sub_menu_accessor_));
+ ON_CALL(*app_, commands_map()).WillByDefault(Return(accessor_));
+
+ EXPECT_CALL(*app_, app_id()).WillRepeatedly(Return(kConnectionKey));
+ EXPECT_CALL(app_mngr_, GetNextHMICorrelationID())
+ .WillOnce(Return(kCorrelationId));
+
+ EXPECT_CALL(mock_rpc_service_,
+ ManageHMICommand(HMIResultCodeIs(next_function_id), _))
+ .WillOnce(Return(true));
+ }
+
+ /**
+ * @brief Prepares submenu response event with the specified params
+ * @param correlation_id correlation id
+ * @param menu_id id of the menu
+ * @return pointer to prepared event
+ */
+ EventPtr PrepareSubMenuResponseEvent(const uint32_t correlation_id,
+ const uint32_t menu_id) {
+ EventPtr menu_event =
+ std::make_shared<Event>(hmi_apis::FunctionID::UI_DeleteSubMenu);
+ (*message_)[am::strings::params][am::hmi_response::code] =
+ hmi_apis::Common_Result::SUCCESS;
+ (*message_)[am::strings::msg_params][am::strings::app_id] = kConnectionKey;
+ (*message_)[am::strings::params][am::strings::correlation_id] =
+ correlation_id;
+ (*message_)[am::strings::msg_params][am::strings::menu_id] = menu_id;
+ menu_event->set_smart_object(*message_);
+
+ return menu_event;
+ }
+
+ /**
+ * @brief Sets up expectations for a successful execution of submenu
+ * subsequent response
+ * @param event pointer to event representing the response message
+ * @param next_function_id function id of the next request
+ */
+ void SetUpSubMenuSubsequentResponseExpectations(
+ EventPtr event, hmi_apis::FunctionID::eType next_function_id) {
+ const auto& event_so_ref = event->smart_object();
+ const auto correlation_id = event->smart_object_correlation_id();
+ const auto menu_id =
+ event_so_ref[am::strings::msg_params][am::strings::menu_id].asUInt();
+
+ EXPECT_CALL(app_mngr_, application(kConnectionKey)).WillOnce(Return(app_));
+ EXPECT_CALL(*app_, RemoveSubMenu(menu_id));
+
+ EXPECT_CALL(app_mngr_, GetNextHMICorrelationID())
+ .WillOnce(Return(correlation_id + 1));
+ EXPECT_CALL(mock_rpc_service_,
+ ManageHMICommand(HMIResultCodeIs(next_function_id), _))
+ .WillOnce(Return(true));
+ }
+
+ /**
+ * @brief Prepares VR command response event with the specified params
+ * @param correlation_id correlation id
+ * @return pointer to prepared event
+ */
+ EventPtr PrepareVrCommandResponseEvent(const uint32_t correlation_id) {
+ EventPtr vr_event =
+ std::make_shared<Event>(hmi_apis::FunctionID::VR_DeleteCommand);
+ (*message_)[am::strings::msg_params][am::strings::app_id] = kConnectionKey;
+ (*message_)[am::strings::params][am::hmi_response::code] =
+ hmi_apis::Common_Result::SUCCESS;
+ (*message_)[am::strings::params][am::strings::correlation_id] =
+ correlation_id;
+ vr_event->set_smart_object(*message_);
+
+ return vr_event;
+ }
+
+ /**
+ * @brief Sets up expectations for a successful execution of VR command
+ * subsequent response
+ * @param event pointer to event representing the response message
+ * @param next_function_id function id of the next request
+ */
+ void SetUpVrCommandSubsequentResponseExpectations(
+ EventPtr event, hmi_apis::FunctionID::eType next_function_id) {
+ const auto correlation_id = event->smart_object_correlation_id();
+
+ EXPECT_CALL(app_mngr_, application(kConnectionKey)).WillOnce(Return(app_));
+ EXPECT_CALL(app_mngr_, GetNextHMICorrelationID())
+ .WillOnce(Return(correlation_id + 1));
+ EXPECT_CALL(mock_rpc_service_,
+ ManageHMICommand(HMIResultCodeIs(next_function_id), _))
+ .WillOnce(Return(true));
+ }
+
+ /**
+ * @brief Prepares UI command response event with the specified params
+ * @param correlation_id correlation id
+ * @param cmd_id id of the command
+ * @return pointer to prepared event
+ */
+ EventPtr PrepareUiCommandResponseEvent(const uint32_t correlation_id,
+ const uint32_t cmd_id) {
+ EventPtr ui_event =
+ std::make_shared<Event>(hmi_apis::FunctionID::UI_DeleteCommand);
+ (*message_)[am::strings::params][am::strings::correlation_id] =
+ correlation_id;
+ (*message_)[am::strings::params][am::hmi_response::code] =
+ hmi_apis::Common_Result::SUCCESS;
+ (*message_)[am::strings::msg_params][am::strings::app_id] = kConnectionKey;
+ (*message_)[am::strings::msg_params][am::strings::cmd_id] = cmd_id;
+ ui_event->set_smart_object(*message_);
+
+ return ui_event;
+ }
+
+ /**
+ * @brief Sets up expectations for a successful execution of UI command
+ * subsequent response
+ * @param event pointer to event representing the response message
+ * @param next_function_id function id of the next request
+ */
+ void SetUpUiCommandSubsequentResponseExpectations(
+ EventPtr event, hmi_apis::FunctionID::eType next_function_id) {
+ const auto correlation_id = event->smart_object_correlation_id();
+ const auto& event_so_ref = event->smart_object();
+ const auto cmd_id =
+ event_so_ref[am::strings::msg_params][am::strings::cmd_id].asUInt();
+
+ EXPECT_CALL(app_mngr_, application(kConnectionKey)).WillOnce(Return(app_));
+ EXPECT_CALL(*app_, RemoveCommand(cmd_id))
+ .WillOnce(DeleteCommand(&commands_map_));
+ EXPECT_CALL(*app_, help_prompt_manager())
+ .WillOnce(ReturnRef(*mock_help_prompt_manager_));
+ EXPECT_CALL(*mock_help_prompt_manager_, OnVrCommandDeleted(cmd_id, false));
+
+ EXPECT_CALL(app_mngr_, GetNextHMICorrelationID())
+ .WillOnce(Return(correlation_id + 1));
+ EXPECT_CALL(mock_rpc_service_,
+ ManageHMICommand(HMIResultCodeIs(next_function_id), _))
+ .WillOnce(Return(true));
+ }
+
+ /**
+ * @brief Sets up expectations for a successful execution of submenu final
+ * response
+ * @param event pointer to event representing the response message
+ */
+ void SetUpSubMenuFinalResponseExpectations(EventPtr event) {
+ const auto& event_so_ref = event->smart_object();
+ const auto menu_id =
+ event_so_ref[am::strings::msg_params][am::strings::menu_id].asUInt();
+
+ EXPECT_CALL(app_mngr_, application(kConnectionKey)).WillOnce(Return(app_));
+ EXPECT_CALL(*app_, RemoveSubMenu(menu_id));
+ EXPECT_CALL(
+ mock_rpc_service_,
+ ManageMobileCommand(MobileResultCodeIs(mobile_apis::Result::SUCCESS),
+ am::commands::Command::SOURCE_SDL));
+ }
+
am::CommandsMap commands_map_;
am::SubMenuMap sub_menu_map_;
mutable std::shared_ptr<sync_primitives::Lock> commands_lock_;
@@ -215,175 +435,187 @@ TEST_F(DeleteSubMenuRequestTest, Run_FindSubMenuFalse_UNSUCCESS) {
command_->Run();
}
-TEST_F(DeleteSubMenuRequestTest, Run_SendHMIRequest_SUCCESS) {
- (*message_)[am::strings::msg_params][am::strings::menu_id] = kMenuId;
- (*message_)[am::strings::params][am::strings::connection_key] =
- kConnectionKey;
-
- smart_objects::SmartObject sub_menu =
- (*message_)[am::strings::msg_params][am::strings::menu_id];
- EXPECT_CALL(app_mngr_, application(kConnectionKey)).WillOnce(Return(app_));
- EXPECT_CALL(*app_, FindSubMenu(kMenuId)).WillOnce(Return(sub_menu));
-
- EXPECT_CALL(*app_, app_id()).WillOnce(Return(kConnectionKey));
- EXPECT_CALL(app_mngr_, GetNextHMICorrelationID())
- .WillOnce(Return(kCorrelationId));
-
- EXPECT_CALL(mock_rpc_service_,
- ManageHMICommand(
- HMIResultCodeIs(hmi_apis::FunctionID::UI_DeleteSubMenu), _))
- .WillOnce(Return(true));
- command_->Run();
-}
-
TEST_F(DeleteSubMenuRequestTest, OnEvent_UnknownEventId_UNSUCCESS) {
Event event(hmi_apis::FunctionID::INVALID_ENUM);
- EXPECT_CALL(app_mngr_, application(_)).Times(0);
+ EXPECT_CALL(mock_rpc_service_,
+ ManageMobileCommand(_, am::commands::Command::SOURCE_SDL))
+ .Times(0);
command_->on_event(event);
}
TEST_F(DeleteSubMenuRequestTest, OnEvent_InvalidApp_UNSUCCESS) {
- Event event(hmi_apis::FunctionID::UI_DeleteSubMenu);
- (*message_)[am::strings::params][am::hmi_response::code] =
- hmi_apis::Common_Result::eType::SUCCESS;
- event.set_smart_object(*message_);
+ auto sub_menu_ptr = GenerateSubMenuMap(kMenuId, 0);
+ sub_menu_map_.insert(std::pair<uint32_t, smart_objects::SmartObject*>(
+ kMenuId, sub_menu_ptr.get()));
+
+ SetUpSubMenuRequestExpectations(hmi_apis::FunctionID::UI_DeleteSubMenu);
+ command_->Run();
+
MockAppPtr invalid_app;
+ EventPtr event = PrepareSubMenuResponseEvent(kCorrelationId, kMenuId);
+
EXPECT_CALL(app_mngr_, application(_)).WillOnce(Return(invalid_app));
EXPECT_CALL(*app_, RemoveSubMenu(_)).Times(0);
- command_->on_event(event);
+ EXPECT_CALL(mock_rpc_service_,
+ ManageMobileCommand(_, am::commands::Command::SOURCE_SDL))
+ .Times(0);
+
+ command_->on_event(*event);
}
-TEST_F(DeleteSubMenuRequestTest, OnEvent_DeleteSubmenu_SUCCESS) {
- Event event(hmi_apis::FunctionID::UI_DeleteSubMenu);
- (*message_)[am::strings::msg_params][am::strings::menu_id] = kMenuId;
- (*message_)[am::strings::params][am::strings::connection_key] =
- kConnectionKey;
- (*message_)[am::strings::msg_params][am::strings::vr_commands] =
- "vr_commands";
- (*message_)[am::strings::msg_params][am::strings::cmd_id] = kCmdId;
- (*message_)[am::strings::msg_params][am::strings::menu_params]
- [am::hmi_request::parent_id] = kMenuId;
- const hmi_apis::Common_Result::eType result_code =
- hmi_apis::Common_Result::SUCCESS;
- (*message_)[am::strings::params][am::hmi_response::code] = result_code;
- event.set_smart_object(*message_);
+TEST_F(DeleteSubMenuRequestTest, OnEvent_DeleteSubmenuOnly_SUCCESS) {
+ auto sub_menu_ptr = GenerateSubMenuMap(kMenuId, 0);
+ sub_menu_map_.insert(std::pair<uint32_t, smart_objects::SmartObject*>(
+ kMenuId, sub_menu_ptr.get()));
- commands_map_.insert(
- std::make_pair(0, &((*message_)[am::strings::msg_params])));
+ SetUpSubMenuRequestExpectations(hmi_apis::FunctionID::UI_DeleteSubMenu);
+ command_->Run();
- smart_objects::SmartObjectSPtr smartObjectPtr =
- std::make_shared<smart_objects::SmartObject>();
+ EventPtr event = PrepareSubMenuResponseEvent(kCorrelationId, kMenuId);
+ SetUpSubMenuFinalResponseExpectations(event);
+ command_->on_event(*event);
+}
- smart_objects::SmartObject& object = *smartObjectPtr;
+TEST_F(DeleteSubMenuRequestTest, OnEvent_DeleteSubmenuWithChildMenu_SUCCESS) {
+ auto sub_menu_ptr = GenerateSubMenuMap(kMenuId, 0);
+ sub_menu_map_.insert(std::pair<uint32_t, smart_objects::SmartObject*>(
+ kMenuId, sub_menu_ptr.get()));
- object[am::strings::position] = 1;
- object[am::strings::menu_name] = "SubMenu";
+ auto sub_menu_child_ptr = GenerateSubMenuMap(kMenuIdChild, kMenuId);
+ sub_menu_map_.insert(std::pair<uint32_t, smart_objects::SmartObject*>(
+ kMenuIdChild, sub_menu_child_ptr.get()));
- sub_menu_map_.insert(
- std::pair<uint32_t, smart_objects::SmartObject*>(5, &object));
- EXPECT_CALL(*app_, sub_menu_map()).WillRepeatedly(Return(sub_menu_accessor_));
- EXPECT_CALL(app_mngr_, application(_)).WillRepeatedly(Return(app_));
+ SetUpSubMenuRequestExpectations(hmi_apis::FunctionID::UI_DeleteSubMenu);
+ command_->Run();
- InSequence seq;
- EXPECT_CALL(*app_, commands_map()).WillOnce(Return(accessor_));
- EXPECT_CALL(*app_, app_id()).WillOnce(Return(kConnectionKey));
- EXPECT_CALL(*app_, get_grammar_id()).WillOnce(Return(kGrammarId));
+ EventPtr event = PrepareSubMenuResponseEvent(kCorrelationId, kMenuIdChild);
+ SetUpSubMenuSubsequentResponseExpectations(
+ event, hmi_apis::FunctionID::UI_DeleteSubMenu);
+ command_->on_event(*event);
- EXPECT_CALL(mock_rpc_service_,
- ManageHMICommand(
- HMIResultCodeIs(hmi_apis::FunctionID::VR_DeleteCommand), _))
- .WillOnce(Return(true));
-
- EXPECT_CALL(*app_, commands_map()).WillOnce(Return(accessor_));
- EXPECT_CALL(*app_, app_id()).WillOnce(Return(kConnectionKey));
- EXPECT_CALL(*app_, RemoveCommand(_)).WillOnce(DeleteCommand(&commands_map_));
- EXPECT_CALL(*app_, help_prompt_manager())
- .WillOnce(ReturnRef(*mock_help_prompt_manager_));
- EXPECT_CALL(*mock_help_prompt_manager_, OnVrCommandDeleted(kCmdId, false));
- EXPECT_CALL(mock_rpc_service_,
- ManageHMICommand(
- HMIResultCodeIs(hmi_apis::FunctionID::UI_DeleteCommand), _))
- .WillOnce(Return(true));
+ EventPtr event_final =
+ PrepareSubMenuResponseEvent(kCorrelationId + 1, kMenuId);
+ SetUpSubMenuFinalResponseExpectations(event_final);
+ command_->on_event(*event_final);
+}
- EXPECT_CALL(*app_, RemoveSubMenu(_));
- EXPECT_CALL(
- mock_rpc_service_,
- ManageMobileCommand(MobileResultCodeIs(mobile_apis::Result::SUCCESS),
- am::commands::Command::SOURCE_SDL));
- EXPECT_CALL(*app_, UpdateHash());
+TEST_F(DeleteSubMenuRequestTest, OnEvent_DeleteSubmenuWithVrAndUi_SUCCESS) {
+ auto sub_menu_ptr = GenerateSubMenuMap(kMenuId, 0);
+ sub_menu_map_.insert(std::pair<uint32_t, smart_objects::SmartObject*>(
+ kMenuId, sub_menu_ptr.get()));
- DeleteSubMenuRequestPtr command =
- CreateCommand<DeleteSubMenuRequest>(message_);
+ auto command_ptr = GenerateUiVrCommandMapChild(kCmdId, kMenuId);
+ commands_map_.insert(std::pair<uint32_t, smart_objects::SmartObject*>(
+ kCmdId, command_ptr.get()));
- command->Init();
- command->on_event(event);
-}
+ SetUpSubMenuRequestExpectations(hmi_apis::FunctionID::VR_DeleteCommand);
+ command_->Run();
-TEST_F(DeleteSubMenuResponseTest, Run_SUCCESS) {
- MessageSharedPtr message(CreateMessage());
- (*message)[am::strings::msg_params][am::strings::connection_key] =
- kConnectionKey;
- DeleteSubMenuResponsePtr command(
- CreateCommand<DeleteSubMenuResponse>(message));
+ EventPtr event_vr = PrepareVrCommandResponseEvent(kCorrelationId);
+ SetUpVrCommandSubsequentResponseExpectations(
+ event_vr, hmi_apis::FunctionID::UI_DeleteCommand);
+ command_->on_event(*event_vr);
- EXPECT_CALL(
- mock_rpc_service_,
- SendMessageToMobile(CheckMessageConnectionKey(kConnectionKey), _));
- command->Run();
+ EventPtr event_ui = PrepareUiCommandResponseEvent(kCorrelationId + 1, kCmdId);
+ SetUpUiCommandSubsequentResponseExpectations(
+ event_ui, hmi_apis::FunctionID::UI_DeleteSubMenu);
+ command_->on_event(*event_ui);
+
+ EventPtr event_final =
+ PrepareSubMenuResponseEvent(kCorrelationId + 2, kMenuId);
+ SetUpSubMenuFinalResponseExpectations(event_final);
+ command_->on_event(*event_final);
}
TEST_F(DeleteSubMenuRequestTest,
- DeleteSubmenu_CommandhaventVrCommadsAndMenuParams_DontSendHMIRequest) {
- Event event(hmi_apis::FunctionID::UI_DeleteSubMenu);
- (*message_)[am::strings::msg_params][am::strings::menu_id] = kMenuId;
- (*message_)[am::strings::params][am::strings::connection_key] =
- kConnectionKey;
- (*message_)[am::strings::params][am::hmi_response::code] =
- am::mobile_api::Result::SUCCESS;
- event.set_smart_object(*message_);
+ OnEvent_DeleteSubmenuWithChildVrAndUi_SUCCESS) {
+ auto sub_menu_ptr = GenerateSubMenuMap(kMenuId, 0);
+ sub_menu_map_.insert(std::pair<uint32_t, smart_objects::SmartObject*>(
+ kMenuId, sub_menu_ptr.get()));
- commands_map_.insert(
- std::make_pair(0, &((*message_)[am::strings::msg_params])));
+ auto sub_menu_child_ptr = GenerateSubMenuMap(kMenuIdChild, kMenuId);
+ sub_menu_map_.insert(std::pair<uint32_t, smart_objects::SmartObject*>(
+ kMenuIdChild, sub_menu_child_ptr.get()));
- EXPECT_CALL(app_mngr_, application(_)).WillRepeatedly(Return(app_));
- EXPECT_CALL(*app_, sub_menu_map()).WillRepeatedly(Return(sub_menu_accessor_));
- EXPECT_CALL(mock_rpc_service_, ManageHMICommand(_, _)).Times(0);
- EXPECT_CALL(*app_, commands_map()).Times(2).WillRepeatedly(Return(accessor_));
- EXPECT_CALL(*app_, RemoveCommand(_)).Times(0);
+ auto command_ptr = GenerateUiVrCommandMapChild(kCmdId, kMenuIdChild);
+ commands_map_.insert(std::pair<uint32_t, smart_objects::SmartObject*>(
+ kCmdId, command_ptr.get()));
- EXPECT_CALL(
- mock_rpc_service_,
- ManageMobileCommand(MobileResultCodeIs(mobile_apis::Result::SUCCESS),
- am::commands::Command::SOURCE_SDL));
- command_->on_event(event);
+ SetUpSubMenuRequestExpectations(hmi_apis::FunctionID::VR_DeleteCommand);
+ command_->Run();
+
+ EventPtr event_vr = PrepareVrCommandResponseEvent(kCorrelationId);
+ SetUpVrCommandSubsequentResponseExpectations(
+ event_vr, hmi_apis::FunctionID::UI_DeleteCommand);
+ command_->on_event(*event_vr);
+
+ EventPtr event_ui = PrepareUiCommandResponseEvent(kCorrelationId + 1, kCmdId);
+ SetUpUiCommandSubsequentResponseExpectations(
+ event_ui, hmi_apis::FunctionID::UI_DeleteSubMenu);
+ command_->on_event(*event_ui);
+
+ EventPtr event_submenu =
+ PrepareSubMenuResponseEvent(kCorrelationId + 2, kMenuIdChild);
+ SetUpSubMenuSubsequentResponseExpectations(
+ event_submenu, hmi_apis::FunctionID::UI_DeleteSubMenu);
+ command_->on_event(*event_submenu);
+
+ EventPtr event_final =
+ PrepareSubMenuResponseEvent(kCorrelationId + 3, kMenuId);
+ SetUpSubMenuFinalResponseExpectations(event_final);
+ command_->on_event(*event_final);
}
TEST_F(DeleteSubMenuRequestTest,
- DeleteSubmenu_NotAChildOfMenupartam_DontSendHMIRequest) {
- Event event(hmi_apis::FunctionID::UI_DeleteSubMenu);
- (*message_)[am::strings::msg_params][am::strings::menu_id] = kMenuId;
- (*message_)[am::strings::msg_params][am::strings::menu_params]
- [am::hmi_request::parent_id] = kMenuId + 1;
- (*message_)[am::strings::params][am::strings::connection_key] =
- kConnectionKey;
- (*message_)[am::strings::params][am::hmi_response::code] =
- am::mobile_api::Result::SUCCESS;
- event.set_smart_object(*message_);
+ OnEvent_DeleteSubmenuVrAndUiWithChild_SUCCESS) {
+ auto sub_menu_ptr = GenerateSubMenuMap(kMenuId, 0);
+ sub_menu_map_.insert(std::pair<uint32_t, smart_objects::SmartObject*>(
+ kMenuId, sub_menu_ptr.get()));
- commands_map_.insert(
- std::make_pair(0, &((*message_)[am::strings::msg_params])));
+ auto command_ptr = GenerateUiVrCommandMapChild(kCmdId, kMenuId);
+ commands_map_.insert(std::pair<uint32_t, smart_objects::SmartObject*>(
+ kCmdId, command_ptr.get()));
- EXPECT_CALL(app_mngr_, application(_)).WillRepeatedly(Return(app_));
- EXPECT_CALL(*app_, sub_menu_map()).WillRepeatedly(Return(sub_menu_accessor_));
- EXPECT_CALL(mock_rpc_service_, ManageHMICommand(_, _)).Times(0);
- EXPECT_CALL(*app_, commands_map()).Times(2).WillRepeatedly(Return(accessor_));
- EXPECT_CALL(*app_, RemoveCommand(_)).Times(0);
+ auto sub_menu_child_ptr = GenerateSubMenuMap(kMenuIdChild, kMenuId);
+ sub_menu_map_.insert(std::pair<uint32_t, smart_objects::SmartObject*>(
+ kMenuIdChild, sub_menu_child_ptr.get()));
+
+ SetUpSubMenuRequestExpectations(hmi_apis::FunctionID::UI_DeleteSubMenu);
+ command_->Run();
+
+ EventPtr event_submenu =
+ PrepareSubMenuResponseEvent(kCorrelationId, kMenuIdChild);
+ SetUpSubMenuSubsequentResponseExpectations(
+ event_submenu, hmi_apis::FunctionID::VR_DeleteCommand);
+ command_->on_event(*event_submenu);
+
+ EventPtr event_vr = PrepareVrCommandResponseEvent(kCorrelationId + 1);
+ SetUpVrCommandSubsequentResponseExpectations(
+ event_vr, hmi_apis::FunctionID::UI_DeleteCommand);
+ command_->on_event(*event_vr);
+
+ EventPtr event_ui = PrepareUiCommandResponseEvent(kCorrelationId + 2, kCmdId);
+ SetUpUiCommandSubsequentResponseExpectations(
+ event_ui, hmi_apis::FunctionID::UI_DeleteSubMenu);
+ command_->on_event(*event_ui);
+
+ EventPtr event_final =
+ PrepareSubMenuResponseEvent(kCorrelationId + 3, kMenuId);
+ SetUpSubMenuFinalResponseExpectations(event_final);
+ command_->on_event(*event_final);
+}
+
+TEST_F(DeleteSubMenuResponseTest, Run_SUCCESS) {
+ MessageSharedPtr message(CreateMessage());
+ (*message)[am::strings::msg_params][am::strings::connection_key] =
+ kConnectionKey;
+ DeleteSubMenuResponsePtr command(
+ CreateCommand<DeleteSubMenuResponse>(message));
EXPECT_CALL(
mock_rpc_service_,
- ManageMobileCommand(MobileResultCodeIs(mobile_apis::Result::SUCCESS),
- am::commands::Command::SOURCE_SDL));
- command_->on_event(event);
+ SendMessageToMobile(CheckMessageConnectionKey(kConnectionKey), _));
+ command->Run();
}
} // namespace delete_sub_menu_request