From f259759537903a20eec5eb5b3c331b12747cd68b Mon Sep 17 00:00:00 2001 From: Nikola Dancejic Date: Sat, 25 May 2024 01:32:24 +0000 Subject: [PATCH] [mux_rollback_ut.cpp] fixing mux_rollback_ut tests for bulk switchover bulk switchover feature chages the sai_api calls in switchover flow. Because of this mux_rollback_ut tests fail. This PR adds bulk operations to mock_sai_neighbor and mock_sai_api, and adjusts the expected function calls in mux_rollback_ut. Signed-off-by: Nikola Dancejic --- orchagent/muxorch.cpp | 3 +- orchagent/p4orch/tests/mock_sai_neighbor.h | 18 ++ .../p4orch/tests/neighbor_manager_test.cpp | 2 + tests/mock_tests/mock_sai_api.h | 54 +++- tests/mock_tests/mux_rollback_ut.cpp | 243 ++++++++++-------- 5 files changed, 193 insertions(+), 127 deletions(-) diff --git a/orchagent/muxorch.cpp b/orchagent/muxorch.cpp index 5c529a309d..3a64c20416 100644 --- a/orchagent/muxorch.cpp +++ b/orchagent/muxorch.cpp @@ -978,7 +978,7 @@ bool MuxNbrHandler::createBulkRouteEntries(std::list& bulk_ count++; } - SWSS_LOG_INFO("Successfully created %d bulk neighbor entries", count); + SWSS_LOG_INFO("Successfully created %d bulk route entries", count); return true; } @@ -1043,7 +1043,6 @@ bool MuxNbrHandler::processBulkRouteEntries(std::list& bulk } SWSS_LOG_NOTICE("Removed tunnel route to %s ", ctx->pfx.to_string().c_str()); - return status; } } return true; diff --git a/orchagent/p4orch/tests/mock_sai_neighbor.h b/orchagent/p4orch/tests/mock_sai_neighbor.h index cd8f2aa0a9..4355831d36 100644 --- a/orchagent/p4orch/tests/mock_sai_neighbor.h +++ b/orchagent/p4orch/tests/mock_sai_neighbor.h @@ -16,6 +16,12 @@ class MockSaiNeighbor MOCK_METHOD1(remove_neighbor_entry, sai_status_t(_In_ const sai_neighbor_entry_t *neighbor_entry)); + MOCK_METHOD6(create_neighbor_entries, sai_status_t(_In_ uint32_t object_count, _In_ const sai_neighbor_entry_t *neighbor_entry, _In_ const uint32_t *attr_count, + _In_ const sai_attribute_t **attr_list, _In_ sai_bulk_op_error_mode_t mode, _Out_ sai_status_t *object_statuses)); + + MOCK_METHOD4(remove_neighbor_entries, sai_status_t(_In_ uint32_t object_count, _In_ const sai_neighbor_entry_t *neighbor_entry, _In_ sai_bulk_op_error_mode_t mode, + _Out_ sai_status_t *object_statuses)); + MOCK_METHOD2(set_neighbor_entry_attribute, sai_status_t(_In_ const sai_neighbor_entry_t *neighbor_entry, _In_ const sai_attribute_t *attr)); @@ -37,6 +43,18 @@ sai_status_t mock_remove_neighbor_entry(_In_ const sai_neighbor_entry_t *neighbo return mock_sai_neighbor->remove_neighbor_entry(neighbor_entry); } +sai_status_t mock_create_neighbor_entries(_In_ uint32_t object_count, _In_ const sai_neighbor_entry_t *neighbor_entry, _In_ const uint32_t *attr_count, + _In_ const sai_attribute_t **attr_list, _In_ sai_bulk_op_error_mode_t mode, _Out_ sai_status_t *object_statuses) +{ + return mock_sai_neighbor->create_neighbor_entries(object_count, neighbor_entry, attr_count, attr_list, mode, object_statuses); +} + +sai_status_t mock_remove_neighbor_entries(_In_ uint32_t object_count, _In_ const sai_neighbor_entry_t *neighbor_entry, _In_ sai_bulk_op_error_mode_t mode, + _Out_ sai_status_t *object_statuses) +{ + return mock_sai_neighbor->remove_neighbor_entries(object_count, neighbor_entry, mode, object_statuses); +} + sai_status_t mock_set_neighbor_entry_attribute(_In_ const sai_neighbor_entry_t *neighbor_entry, _In_ const sai_attribute_t *attr) { diff --git a/orchagent/p4orch/tests/neighbor_manager_test.cpp b/orchagent/p4orch/tests/neighbor_manager_test.cpp index 4db1db873e..7523701cb7 100644 --- a/orchagent/p4orch/tests/neighbor_manager_test.cpp +++ b/orchagent/p4orch/tests/neighbor_manager_test.cpp @@ -124,6 +124,8 @@ class NeighborManagerTest : public ::testing::Test mock_sai_neighbor = &mock_sai_neighbor_; sai_neighbor_api->create_neighbor_entry = mock_create_neighbor_entry; sai_neighbor_api->remove_neighbor_entry = mock_remove_neighbor_entry; + sai_neighbor_api->create_neighbor_entries = mock_create_neighbor_entries; + sai_neighbor_api->remove_neighbor_entries = mock_remove_neighbor_entries; sai_neighbor_api->set_neighbor_entry_attribute = mock_set_neighbor_entry_attribute; sai_neighbor_api->get_neighbor_entry_attribute = mock_get_neighbor_entry_attribute; } diff --git a/tests/mock_tests/mock_sai_api.h b/tests/mock_tests/mock_sai_api.h index 7819b5b126..58e3c9da23 100644 --- a/tests/mock_tests/mock_sai_api.h +++ b/tests/mock_tests/mock_sai_api.h @@ -24,8 +24,12 @@ EXTERN_MOCK_FNS #define CREATE_PARAMS(sai_object_type) _In_ const sai_##sai_object_type##_entry_t *sai_object_type##_entry, _In_ uint32_t attr_count, _In_ const sai_attribute_t *attr_list #define REMOVE_PARAMS(sai_object_type) _In_ const sai_##sai_object_type##_entry_t *sai_object_type##_entry +#define CREATE_BULK_PARAMS(sai_object_type) _In_ uint32_t object_count, _In_ const sai_##sai_object_type##_entry_t *sai_object_type##_entry, _In_ const uint32_t *attr_count, _In_ const sai_attribute_t **attr_list, _In_ sai_bulk_op_error_mode_t mode, _Out_ sai_status_t *object_statuses +#define REMOVE_BULK_PARAMS(sai_object_type) _In_ uint32_t object_count, _In_ const sai_##sai_object_type##_entry_t *sai_object_type##_entry, _In_ sai_bulk_op_error_mode_t mode, _In_ sai_status_t *object_statuses #define CREATE_ARGS(sai_object_type) sai_object_type##_entry, attr_count, attr_list #define REMOVE_ARGS(sai_object_type) sai_object_type##_entry +#define CREATE_BULK_ARGS(sai_object_type) object_count, sai_object_type##_entry, attr_count, attr_list, mode, object_statuses +#define REMOVE_BULK_ARGS(sai_object_type) object_count, sai_object_type##_entry, mode, object_statuses #define GENERIC_CREATE_PARAMS(sai_object_type) _Out_ sai_object_id_t *sai_object_type##_id, _In_ sai_object_id_t switch_id, _In_ uint32_t attr_count, _In_ const sai_attribute_t *attr_list #define GENERIC_REMOVE_PARAMS(sai_object_type) _In_ sai_object_id_t sai_object_type##_id #define GENERIC_CREATE_ARGS(sai_object_type) sai_object_type##_id, switch_id, attr_count, attr_list @@ -42,8 +46,8 @@ The macro DEFINE_SAI_API_MOCK will perform the steps to mock the SAI API for the 7. Define a method to remove the mock */ #define DEFINE_SAI_API_MOCK(sai_object_type) \ - static sai_##sai_object_type##_api_t *old_sai_##sai_object_type##_api; \ - static sai_##sai_object_type##_api_t ut_sai_##sai_object_type##_api; \ + static sai_##sai_object_type##_api_t *old_sai_##sai_object_type##_api; \ + static sai_##sai_object_type##_api_t ut_sai_##sai_object_type##_api; \ class mock_sai_##sai_object_type##_api_t \ { \ public: \ @@ -59,20 +63,40 @@ The macro DEFINE_SAI_API_MOCK will perform the steps to mock the SAI API for the [this](REMOVE_PARAMS(sai_object_type)) { \ return old_sai_##sai_object_type##_api->remove_##sai_object_type##_entry(REMOVE_ARGS(sai_object_type)); \ }); \ + ON_CALL(*this, create_##sai_object_type##_entries) \ + .WillByDefault( \ + [this](CREATE_BULK_PARAMS(sai_object_type)) { \ + return old_sai_##sai_object_type##_api->create_##sai_object_type##_entries(CREATE_BULK_ARGS(sai_object_type)); \ + }); \ + ON_CALL(*this, remove_##sai_object_type##_entries) \ + .WillByDefault( \ + [this](REMOVE_BULK_PARAMS(sai_object_type)) { \ + return old_sai_##sai_object_type##_api->remove_##sai_object_type##_entries(REMOVE_BULK_ARGS(sai_object_type)); \ + }); \ } \ MOCK_METHOD3(create_##sai_object_type##_entry, sai_status_t(CREATE_PARAMS(sai_object_type))); \ MOCK_METHOD1(remove_##sai_object_type##_entry, sai_status_t(REMOVE_PARAMS(sai_object_type))); \ + MOCK_METHOD6(create_##sai_object_type##_entries, sai_status_t(CREATE_BULK_PARAMS(sai_object_type))); \ + MOCK_METHOD4(remove_##sai_object_type##_entries, sai_status_t(REMOVE_BULK_PARAMS(sai_object_type))); \ }; \ - static mock_sai_##sai_object_type##_api_t *mock_sai_##sai_object_type##_api; \ - inline sai_status_t mock_create_##sai_object_type##_entry(CREATE_PARAMS(sai_object_type)) \ + static mock_sai_##sai_object_type##_api_t *mock_sai_##sai_object_type##_api; \ + inline sai_status_t mock_create_##sai_object_type##_entry(CREATE_PARAMS(sai_object_type)) \ { \ return mock_sai_##sai_object_type##_api->create_##sai_object_type##_entry(CREATE_ARGS(sai_object_type)); \ } \ - inline sai_status_t mock_remove_##sai_object_type##_entry(REMOVE_PARAMS(sai_object_type)) \ + inline sai_status_t mock_remove_##sai_object_type##_entry(REMOVE_PARAMS(sai_object_type)) \ { \ return mock_sai_##sai_object_type##_api->remove_##sai_object_type##_entry(REMOVE_ARGS(sai_object_type)); \ } \ - inline void apply_sai_##sai_object_type##_api_mock() \ + inline sai_status_t mock_create_##sai_object_type##_entries(CREATE_BULK_PARAMS(sai_object_type)) \ + { \ + return mock_sai_##sai_object_type##_api->create_##sai_object_type##_entries(CREATE_BULK_ARGS(sai_object_type)); \ + } \ + inline sai_status_t mock_remove_##sai_object_type##_entries(REMOVE_BULK_PARAMS(sai_object_type)) \ + { \ + return mock_sai_##sai_object_type##_api->remove_##sai_object_type##_entries(REMOVE_BULK_ARGS(sai_object_type)); \ + } \ + inline void apply_sai_##sai_object_type##_api_mock() \ { \ mock_sai_##sai_object_type##_api = new NiceMock(); \ \ @@ -82,16 +106,18 @@ The macro DEFINE_SAI_API_MOCK will perform the steps to mock the SAI API for the \ sai_##sai_object_type##_api->create_##sai_object_type##_entry = mock_create_##sai_object_type##_entry; \ sai_##sai_object_type##_api->remove_##sai_object_type##_entry = mock_remove_##sai_object_type##_entry; \ + sai_##sai_object_type##_api->create_##sai_object_type##_entries = mock_create_##sai_object_type##_entries; \ + sai_##sai_object_type##_api->remove_##sai_object_type##_entries = mock_remove_##sai_object_type##_entries; \ } \ - inline void remove_sai_##sai_object_type##_api_mock() \ + inline void remove_sai_##sai_object_type##_api_mock() \ { \ sai_##sai_object_type##_api = old_sai_##sai_object_type##_api; \ delete mock_sai_##sai_object_type##_api; \ } #define DEFINE_SAI_GENERIC_API_MOCK(sai_api_name, sai_object_type) \ - static sai_##sai_api_name##_api_t *old_sai_##sai_api_name##_api; \ - static sai_##sai_api_name##_api_t ut_sai_##sai_api_name##_api; \ + static sai_##sai_api_name##_api_t *old_sai_##sai_api_name##_api; \ + static sai_##sai_api_name##_api_t ut_sai_##sai_api_name##_api; \ class mock_sai_##sai_api_name##_api_t \ { \ public: \ @@ -111,16 +137,16 @@ The macro DEFINE_SAI_API_MOCK will perform the steps to mock the SAI API for the MOCK_METHOD4(create_##sai_object_type, sai_status_t(GENERIC_CREATE_PARAMS(sai_object_type))); \ MOCK_METHOD1(remove_##sai_object_type, sai_status_t(GENERIC_REMOVE_PARAMS(sai_object_type))); \ }; \ - static mock_sai_##sai_api_name##_api_t *mock_sai_##sai_api_name##_api; \ - inline sai_status_t mock_create_##sai_object_type(GENERIC_CREATE_PARAMS(sai_object_type)) \ + static mock_sai_##sai_api_name##_api_t *mock_sai_##sai_api_name##_api; \ + inline sai_status_t mock_create_##sai_object_type(GENERIC_CREATE_PARAMS(sai_object_type)) \ { \ return mock_sai_##sai_api_name##_api->create_##sai_object_type(GENERIC_CREATE_ARGS(sai_object_type)); \ } \ - inline sai_status_t mock_remove_##sai_object_type(GENERIC_REMOVE_PARAMS(sai_object_type)) \ + inline sai_status_t mock_remove_##sai_object_type(GENERIC_REMOVE_PARAMS(sai_object_type)) \ { \ return mock_sai_##sai_api_name##_api->remove_##sai_object_type(GENERIC_REMOVE_ARGS(sai_object_type)); \ } \ - inline void apply_sai_##sai_api_name##_api_mock() \ + inline void apply_sai_##sai_api_name##_api_mock() \ { \ mock_sai_##sai_api_name##_api = new NiceMock(); \ \ @@ -131,7 +157,7 @@ The macro DEFINE_SAI_API_MOCK will perform the steps to mock the SAI API for the sai_##sai_api_name##_api->create_##sai_object_type = mock_create_##sai_object_type; \ sai_##sai_api_name##_api->remove_##sai_object_type = mock_remove_##sai_object_type; \ } \ - inline void remove_sai_##sai_api_name##_api_mock() \ + inline void remove_sai_##sai_api_name##_api_mock() \ { \ sai_##sai_api_name##_api = old_sai_##sai_api_name##_api; \ delete mock_sai_##sai_api_name##_api; \ diff --git a/tests/mock_tests/mux_rollback_ut.cpp b/tests/mock_tests/mux_rollback_ut.cpp index a5441fe4f7..1d9855a5c4 100644 --- a/tests/mock_tests/mux_rollback_ut.cpp +++ b/tests/mock_tests/mux_rollback_ut.cpp @@ -5,6 +5,10 @@ #include "orch.h" #undef protected #include "ut_helper.h" +#define private public +#include "neighorch.h" +#include "muxorch.h" +#undef private #include "mock_orchagent_main.h" #include "mock_sai_api.h" #include "mock_orch_test.h" @@ -19,6 +23,7 @@ namespace mux_rollback_test DEFINE_SAI_API_MOCK(route); DEFINE_SAI_GENERIC_API_MOCK(acl, acl_entry); DEFINE_SAI_GENERIC_API_MOCK(next_hop, next_hop); + using ::testing::_; using namespace std; using namespace mock_orch_test; using ::testing::Return; @@ -26,6 +31,11 @@ namespace mux_rollback_test static const string TEST_INTERFACE = "Ethernet4"; + sai_bulk_create_neighbor_entry_fn old_create_neighbor_entries; + sai_bulk_remove_neighbor_entry_fn old_remove_neighbor_entries; + sai_bulk_create_route_entry_fn old_create_route_entries; + sai_bulk_remove_route_entry_fn old_remove_route_entries; + class MuxRollbackTest : public MockOrchTest { protected: @@ -125,123 +135,134 @@ namespace mux_rollback_test INIT_SAI_API_MOCK(acl); INIT_SAI_API_MOCK(next_hop); MockSaiApis(); + old_create_neighbor_entries = gNeighOrch->gNeighBulker.create_entries; + old_remove_neighbor_entries = gNeighOrch->gNeighBulker.remove_entries; + old_create_route_entries = m_MuxCable->nbr_handler_->gRouteBulker.create_entries; + old_remove_route_entries = m_MuxCable->nbr_handler_->gRouteBulker.remove_entries; + gNeighOrch->gNeighBulker.create_entries = mock_create_neighbor_entries; + gNeighOrch->gNeighBulker.remove_entries = mock_remove_neighbor_entries; + m_MuxCable->nbr_handler_->gRouteBulker.create_entries = mock_create_route_entries; + m_MuxCable->nbr_handler_->gRouteBulker.remove_entries = mock_remove_route_entries; } void PreTearDown() override { RestoreSaiApis(); + gNeighOrch->gNeighBulker.create_entries = old_create_neighbor_entries; + gNeighOrch->gNeighBulker.remove_entries = old_remove_neighbor_entries; + m_MuxCable->nbr_handler_->gRouteBulker.create_entries = old_create_route_entries; + m_MuxCable->nbr_handler_->gRouteBulker.remove_entries = old_remove_route_entries; } }; - /* TODO: change expected api call to be create_neighbor_entries */ - // TEST_F(MuxRollbackTest, StandbyToActiveNeighborAlreadyExists) - // { - // EXPECT_CALL(*mock_sai_neighbor_api, create_neighbor_entry) - // .WillOnce(Return(SAI_STATUS_ITEM_ALREADY_EXISTS)); - // SetAndAssertMuxState(ACTIVE_STATE); - // } - - // TEST_F(MuxRollbackTest, ActiveToStandbyNeighborNotFound) - // { - // SetAndAssertMuxState(ACTIVE_STATE); - // EXPECT_CALL(*mock_sai_neighbor_api, remove_neighbor_entry) - // .WillOnce(Return(SAI_STATUS_ITEM_NOT_FOUND)); - // SetAndAssertMuxState(STANDBY_STATE); - // } - - // TEST_F(MuxRollbackTest, StandbyToActiveRouteNotFound) - // { - // EXPECT_CALL(*mock_sai_route_api, remove_route_entry) - // .WillOnce(Return(SAI_STATUS_ITEM_NOT_FOUND)); - // SetAndAssertMuxState(ACTIVE_STATE); - // } - - // TEST_F(MuxRollbackTest, ActiveToStandbyRouteAlreadyExists) - // { - // SetAndAssertMuxState(ACTIVE_STATE); - // EXPECT_CALL(*mock_sai_route_api, create_route_entry) - // .WillOnce(Return(SAI_STATUS_ITEM_ALREADY_EXISTS)); - // SetAndAssertMuxState(STANDBY_STATE); - // } - - // TEST_F(MuxRollbackTest, StandbyToActiveAclNotFound) - // { - // EXPECT_CALL(*mock_sai_acl_api, remove_acl_entry) - // .WillOnce(Return(SAI_STATUS_ITEM_NOT_FOUND)); - // SetAndAssertMuxState(ACTIVE_STATE); - // } - - // TEST_F(MuxRollbackTest, ActiveToStandbyAclAlreadyExists) - // { - // SetAndAssertMuxState(ACTIVE_STATE); - // EXPECT_CALL(*mock_sai_acl_api, create_acl_entry) - // .WillOnce(Return(SAI_STATUS_ITEM_ALREADY_EXISTS)); - // SetAndAssertMuxState(STANDBY_STATE); - // } - - // TEST_F(MuxRollbackTest, StandbyToActiveNextHopAlreadyExists) - // { - // EXPECT_CALL(*mock_sai_next_hop_api, create_next_hop) - // .WillOnce(Return(SAI_STATUS_ITEM_ALREADY_EXISTS)); - // SetAndAssertMuxState(ACTIVE_STATE); - // } - - // TEST_F(MuxRollbackTest, ActiveToStandbyNextHopNotFound) - // { - // SetAndAssertMuxState(ACTIVE_STATE); - // EXPECT_CALL(*mock_sai_next_hop_api, remove_next_hop) - // .WillOnce(Return(SAI_STATUS_ITEM_NOT_FOUND)); - // SetAndAssertMuxState(STANDBY_STATE); - // } - - // TEST_F(MuxRollbackTest, StandbyToActiveRuntimeErrorRollbackToStandby) - // { - // EXPECT_CALL(*mock_sai_route_api, remove_route_entry) - // .WillOnce(Throw(runtime_error("Mock runtime error"))); - // SetMuxStateFromAppDb(ACTIVE_STATE); - // EXPECT_EQ(STANDBY_STATE, m_MuxCable->getState()); - // } - - // TEST_F(MuxRollbackTest, ActiveToStandbyRuntimeErrorRollbackToActive) - // { - // SetAndAssertMuxState(ACTIVE_STATE); - // EXPECT_CALL(*mock_sai_route_api, create_route_entry) - // .WillOnce(Throw(runtime_error("Mock runtime error"))); - // SetMuxStateFromAppDb(STANDBY_STATE); - // EXPECT_EQ(ACTIVE_STATE, m_MuxCable->getState()); - // } - - // TEST_F(MuxRollbackTest, StandbyToActiveLogicErrorRollbackToStandby) - // { - // EXPECT_CALL(*mock_sai_neighbor_api, create_neighbor_entry) - // .WillOnce(Throw(logic_error("Mock logic error"))); - // SetMuxStateFromAppDb(ACTIVE_STATE); - // EXPECT_EQ(STANDBY_STATE, m_MuxCable->getState()); - // } - - // TEST_F(MuxRollbackTest, ActiveToStandbyLogicErrorRollbackToActive) - // { - // SetAndAssertMuxState(ACTIVE_STATE); - // EXPECT_CALL(*mock_sai_neighbor_api, remove_neighbor_entry) - // .WillOnce(Throw(logic_error("Mock logic error"))); - // SetMuxStateFromAppDb(STANDBY_STATE); - // EXPECT_EQ(ACTIVE_STATE, m_MuxCable->getState()); - // } - - // TEST_F(MuxRollbackTest, StandbyToActiveExceptionRollbackToStandby) - // { - // EXPECT_CALL(*mock_sai_next_hop_api, create_next_hop) - // .WillOnce(Throw(exception())); - // SetMuxStateFromAppDb(ACTIVE_STATE); - // EXPECT_EQ(STANDBY_STATE, m_MuxCable->getState()); - // } - - // TEST_F(MuxRollbackTest, ActiveToStandbyExceptionRollbackToActive) - // { - // SetAndAssertMuxState(ACTIVE_STATE); - // EXPECT_CALL(*mock_sai_next_hop_api, remove_next_hop) - // .WillOnce(Throw(exception())); - // SetMuxStateFromAppDb(STANDBY_STATE); - // EXPECT_EQ(ACTIVE_STATE, m_MuxCable->getState()); - // } + TEST_F(MuxRollbackTest, StandbyToActiveNeighborAlreadyExists) + { + EXPECT_CALL(*mock_sai_neighbor_api, create_neighbor_entries) + .WillOnce(Return(SAI_STATUS_ITEM_ALREADY_EXISTS)); + SetAndAssertMuxState(ACTIVE_STATE); + } + + TEST_F(MuxRollbackTest, ActiveToStandbyNeighborNotFound) + { + SetAndAssertMuxState(ACTIVE_STATE); + EXPECT_CALL(*mock_sai_neighbor_api, remove_neighbor_entries) + .WillOnce(Return(SAI_STATUS_ITEM_NOT_FOUND)); + SetAndAssertMuxState(STANDBY_STATE); + } + + TEST_F(MuxRollbackTest, StandbyToActiveRouteNotFound) + { + EXPECT_CALL(*mock_sai_route_api, remove_route_entries) + .WillOnce(Return(SAI_STATUS_ITEM_NOT_FOUND)); + SetAndAssertMuxState(ACTIVE_STATE); + } + + TEST_F(MuxRollbackTest, ActiveToStandbyRouteAlreadyExists) + { + SetAndAssertMuxState(ACTIVE_STATE); + EXPECT_CALL(*mock_sai_route_api, create_route_entries) + .WillOnce(Return(SAI_STATUS_ITEM_ALREADY_EXISTS)); + SetAndAssertMuxState(STANDBY_STATE); + } + + TEST_F(MuxRollbackTest, StandbyToActiveAclNotFound) + { + EXPECT_CALL(*mock_sai_acl_api, remove_acl_entry) + .WillOnce(Return(SAI_STATUS_ITEM_NOT_FOUND)); + SetAndAssertMuxState(ACTIVE_STATE); + } + + TEST_F(MuxRollbackTest, ActiveToStandbyAclAlreadyExists) + { + SetAndAssertMuxState(ACTIVE_STATE); + EXPECT_CALL(*mock_sai_acl_api, create_acl_entry) + .WillOnce(Return(SAI_STATUS_ITEM_ALREADY_EXISTS)); + SetAndAssertMuxState(STANDBY_STATE); + } + + TEST_F(MuxRollbackTest, StandbyToActiveNextHopAlreadyExists) + { + EXPECT_CALL(*mock_sai_next_hop_api, create_next_hop) + .WillOnce(Return(SAI_STATUS_ITEM_ALREADY_EXISTS)); + SetAndAssertMuxState(ACTIVE_STATE); + } + + TEST_F(MuxRollbackTest, ActiveToStandbyNextHopNotFound) + { + SetAndAssertMuxState(ACTIVE_STATE); + EXPECT_CALL(*mock_sai_next_hop_api, remove_next_hop) + .WillOnce(Return(SAI_STATUS_ITEM_NOT_FOUND)); + SetAndAssertMuxState(STANDBY_STATE); + } + + TEST_F(MuxRollbackTest, StandbyToActiveRuntimeErrorRollbackToStandby) + { + EXPECT_CALL(*mock_sai_route_api, remove_route_entries) + .WillOnce(Throw(runtime_error("Mock runtime error"))); + SetMuxStateFromAppDb(ACTIVE_STATE); + EXPECT_EQ(STANDBY_STATE, m_MuxCable->getState()); + } + + TEST_F(MuxRollbackTest, ActiveToStandbyRuntimeErrorRollbackToActive) + { + SetAndAssertMuxState(ACTIVE_STATE); + EXPECT_CALL(*mock_sai_route_api, create_route_entries) + .WillOnce(Throw(runtime_error("Mock runtime error"))); + SetMuxStateFromAppDb(STANDBY_STATE); + EXPECT_EQ(ACTIVE_STATE, m_MuxCable->getState()); + } + + TEST_F(MuxRollbackTest, StandbyToActiveLogicErrorRollbackToStandby) + { + EXPECT_CALL(*mock_sai_neighbor_api, create_neighbor_entries) + .WillOnce(Throw(logic_error("Mock logic error"))); + SetMuxStateFromAppDb(ACTIVE_STATE); + EXPECT_EQ(STANDBY_STATE, m_MuxCable->getState()); + } + + TEST_F(MuxRollbackTest, ActiveToStandbyLogicErrorRollbackToActive) + { + SetAndAssertMuxState(ACTIVE_STATE); + EXPECT_CALL(*mock_sai_neighbor_api, remove_neighbor_entries) + .WillOnce(Throw(logic_error("Mock logic error"))); + SetMuxStateFromAppDb(STANDBY_STATE); + EXPECT_EQ(ACTIVE_STATE, m_MuxCable->getState()); + } + + TEST_F(MuxRollbackTest, StandbyToActiveExceptionRollbackToStandby) + { + EXPECT_CALL(*mock_sai_next_hop_api, create_next_hop) + .WillOnce(Throw(exception())); + SetMuxStateFromAppDb(ACTIVE_STATE); + EXPECT_EQ(STANDBY_STATE, m_MuxCable->getState()); + } + + TEST_F(MuxRollbackTest, ActiveToStandbyExceptionRollbackToActive) + { + SetAndAssertMuxState(ACTIVE_STATE); + EXPECT_CALL(*mock_sai_next_hop_api, remove_next_hop) + .WillOnce(Throw(exception())); + SetMuxStateFromAppDb(STANDBY_STATE); + EXPECT_EQ(ACTIVE_STATE, m_MuxCable->getState()); + } }