diff --git a/fboss/agent/DsfSubscription.h b/fboss/agent/DsfSubscription.h index f9e8aafdaff8a..5e37a9f33d9fe 100644 --- a/fboss/agent/DsfSubscription.h +++ b/fboss/agent/DsfSubscription.h @@ -115,6 +115,8 @@ class DsfSubscription { template FRIEND_TEST(DsfSubscriptionTest, updateWithRollbackProtection); template + FRIEND_TEST(DsfSubscriptionTest, updateFailed); + template FRIEND_TEST(DsfSubscriptionTest, setupNeighbors); }; diff --git a/fboss/agent/test/DsfSubscriptionTests.cpp b/fboss/agent/test/DsfSubscriptionTests.cpp index 054b3d96d4e71..634b64d535936 100644 --- a/fboss/agent/test/DsfSubscriptionTests.cpp +++ b/fboss/agent/test/DsfSubscriptionTests.cpp @@ -4,6 +4,7 @@ #include "fboss/agent/AgentFsdbSyncManager.h" #include "fboss/agent/DsfSubscription.h" #include "fboss/agent/SwitchStats.h" +#include "fboss/agent/hw/mock/MockPlatform.h" #include "fboss/agent/test/CounterCache.h" #include "fboss/agent/test/HwTestHandle.h" #include "fboss/agent/test/TestUtils.h" @@ -15,6 +16,8 @@ #include #include "fboss/agent/GtestDefs.h" +using ::testing::_; +using ::testing::Return; namespace facebook::fboss { namespace { constexpr auto kRemoteSwitchIdBegin = 4; @@ -361,6 +364,44 @@ TYPED_TEST(DsfSubscriptionTest, DataUpdate) { this->getRemoteSystemPorts()->size(), this->kNumRemoteSwitchAsics + 1)); } +TYPED_TEST(DsfSubscriptionTest, updateFailed) { + CounterCache counters(this->sw_); + this->createPublisher(); + auto state = this->makeSwitchState(); + this->publishSwitchState(state); + + std::optional>> + recvSysPorts; + std::optional>> recvIntfs; + this->subscription_ = this->createSubscription(); + + WITH_RETRIES({ + ASSERT_EVENTUALLY_EQ( + this->getRemoteSystemPorts()->size(), this->kNumRemoteSwitchAsics); + ASSERT_EVENTUALLY_EQ( + this->getRemoteInterfaces()->size(), this->kNumRemoteSwitchAsics); + EXPECT_EQ(this->dsfSessionState(), DsfSessionState::WAIT_FOR_REMOTE); + }); + waitForStateUpdates(this->sw_); + + // Fail HW update by returning current state + EXPECT_HW_CALL(this->sw_, stateChangedImpl(_)) + .Times(::testing::AtLeast(1)) + .WillOnce(Return(this->sw_->getState())); + auto sysPort2 = makeSysPort( + std::nullopt, SystemPortID(kSysPortRangeMin + 2), kRemoteSwitchIdBegin); + auto portMap = state->getSystemPorts()->modify(&state); + portMap->addNode(sysPort2, this->matcher()); + this->publishSwitchState(state); + auto dsfUpdateFailedCounter = + SwitchStats::kCounterPrefix + "dsf_update_failed.sum.60"; + WITH_RETRIES({ + counters.update(); + ASSERT_EVENTUALLY_TRUE(counters.checkExist(dsfUpdateFailedCounter)); + ASSERT_EVENTUALLY_EQ(counters.value(dsfUpdateFailedCounter), 1); + }); +} + TYPED_TEST(DsfSubscriptionTest, updateWithRollbackProtection) { auto sysPorts = makeSysPortsForSwitchIds( std::set({SwitchID(kRemoteSwitchIdBegin)}), 2);