From f4d00e1dfd4f318bbc027213e12afe366a338f0b Mon Sep 17 00:00:00 2001 From: Nischal Sheth Date: Thu, 13 Aug 2015 15:39:51 -0700 Subject: [PATCH] Support pagination of output for multicast manager introspect Limit the maximum number of entries displayed on a single page. A next_batch link is generated if there are more entries to be displayed. Also limit maximum number of entries examined in one invocation of the callback routine. This comes into play when there is a search string specified and many entries don't match it. A partial page is saved in user-allocated data and the next invocation of callback appends to it. This is repeated till there's a full page or there are no more entries in the table. Following changes are implemented: - Move code from bgp_sandesh.cc to bgp_show_multicast_manager.cc - Use class template BgpShowHandler to avoid code duplication - Implement iteration limit to avoid hogging CPU from introspect - Reuse type parameterized tests to also cover multicast manager - Remove older unit test which was limited in scope - Sprinkle const as required Change-Id: I190cfbaaa58ac52ce63fb6bd916c040ab100e742 Closes-Bug: 1479428 --- src/bgp/SConscript | 1 + src/bgp/bgp_multicast.cc | 14 ++ src/bgp/bgp_multicast.h | 13 +- src/bgp/bgp_peer.sandesh | 4 + src/bgp/bgp_peer_internal.sandesh | 4 + src/bgp/bgp_sandesh.cc | 143 +---------------- src/bgp/bgp_show_multicast_manager.cc | 147 ++++++++++++++++++ src/bgp/ermvpn/ermvpn_table.cc | 4 + src/bgp/ermvpn/ermvpn_table.h | 1 + src/bgp/test/SConscript | 6 + .../test/bgp_show_multicast_manager_test.cc | 70 +++++++++ src/bgp/test/bgp_xmpp_mcast_test.cc | 95 ----------- 12 files changed, 262 insertions(+), 240 deletions(-) create mode 100644 src/bgp/bgp_show_multicast_manager.cc create mode 100644 src/bgp/test/bgp_show_multicast_manager_test.cc diff --git a/src/bgp/SConscript b/src/bgp/SConscript index 0bbcb8d0051..7915a4d6e8d 100644 --- a/src/bgp/SConscript +++ b/src/bgp/SConscript @@ -60,6 +60,7 @@ libbgp = env.Library('bgp', 'bgp_session.cc', 'bgp_show_config.cc', 'bgp_show_evpn_table.cc', + 'bgp_show_multicast_manager.cc', 'bgp_show_neighbor.cc', 'bgp_show_route_summary.cc', 'bgp_show_routing_instance.cc', diff --git a/src/bgp/bgp_multicast.cc b/src/bgp/bgp_multicast.cc index 45f7feb2c4c..c64c6740a87 100644 --- a/src/bgp/bgp_multicast.cc +++ b/src/bgp/bgp_multicast.cc @@ -1013,3 +1013,17 @@ LifetimeActor *McastTreeManager::deleter() { return deleter_.get(); } +// +// Return the LifetimeActor for the McastTreeManager. +// Const version. +// +const LifetimeActor *McastTreeManager::deleter() const { + return deleter_.get(); +} + +// +// Return true if the McastTreeManager is deleted. +// +bool McastTreeManager::deleted() const { + return deleter_->IsDeleted(); +} diff --git a/src/bgp/bgp_multicast.h b/src/bgp/bgp_multicast.h index a3f070236c7..6e22acd69ef 100644 --- a/src/bgp/bgp_multicast.h +++ b/src/bgp/bgp_multicast.h @@ -312,8 +312,8 @@ class McastManagerPartition { BgpServer *server(); McastTreeManager *tree_manager() const { return tree_manager_; } - bool empty() { return sg_list_.empty(); } - size_t size() { return sg_list_.size(); } + bool empty() const { return sg_list_.empty(); } + size_t size() const { return sg_list_.size(); } private: friend class BgpMulticastTest; @@ -370,6 +370,9 @@ class McastTreeManager { public: static const int kDegree = 4; + typedef std::vector PartitionList; + typedef PartitionList::const_iterator const_iterator; + enum NodeLevel { LevelFirst = 0, LevelNative = 0, @@ -380,6 +383,9 @@ class McastTreeManager { explicit McastTreeManager(ErmVpnTable *table); virtual ~McastTreeManager(); + const_iterator begin() const { return partitions_.begin(); } + const_iterator end() const { return partitions_.end(); } + virtual void Initialize(); virtual void Terminate(); @@ -395,13 +401,14 @@ class McastTreeManager { void RetryDelete(); LifetimeActor *deleter(); + const LifetimeActor *deleter() const; + bool deleted() const; private: friend class BgpMulticastTest; friend class ShowMulticastManagerDetailHandler; class DeleteActor; - typedef std::vector PartitionList; void AllocPartitions(); void FreePartitions(); diff --git a/src/bgp/bgp_peer.sandesh b/src/bgp/bgp_peer.sandesh index fe472327f51..188586fffbe 100644 --- a/src/bgp/bgp_peer.sandesh +++ b/src/bgp/bgp_peer.sandesh @@ -294,10 +294,14 @@ request sandesh ShowEvpnTableSummaryReq { struct ShowMulticastManager { 1: string name (link="ShowMulticastManagerDetailReq"); 2: u32 total_trees; + 3: bool deleted; + 4: string deleted_at; } response sandesh ShowMulticastManagerResp { 1: list managers; + 2: optional string next_batch (link="ShowMulticastManagerReqIterate", + link_title="next_batch"); } request sandesh ShowMulticastManagerReq { diff --git a/src/bgp/bgp_peer_internal.sandesh b/src/bgp/bgp_peer_internal.sandesh index f190a588ebb..58773473b30 100644 --- a/src/bgp/bgp_peer_internal.sandesh +++ b/src/bgp/bgp_peer_internal.sandesh @@ -58,6 +58,10 @@ request sandesh ShowEvpnTableSummaryReqIterate { 1: string iterate_info; } +request sandesh ShowMulticastManagerReqIterate { + 1: string iterate_info; +} + response sandesh ShowMulticastManagerDetailResp { 1: list trees; } diff --git a/src/bgp/bgp_sandesh.cc b/src/bgp/bgp_sandesh.cc index c40a4b5543e..ce3e611932d 100644 --- a/src/bgp/bgp_sandesh.cc +++ b/src/bgp/bgp_sandesh.cc @@ -763,147 +763,6 @@ void ClearBgpNeighborReq::HandleRequest() const { RequestPipeline rp(ps); } -class ShowMulticastManagerHandler { -public: - struct MulticastManagerDataKey { - string routing_table; - bool operator<(const MulticastManagerDataKey &rhs) const { - return (routing_table < rhs.routing_table); - } - }; - - struct MulticastManagerData : public RequestPipeline::InstData { - typedef map Map; - Map table_map; - }; - - static RequestPipeline::InstData *CreateData(int stage) { - return (new MulticastManagerData); - } - - static void FillMulticastManagerStats(MulticastManagerData *data, - ErmVpnTable *table, int inst_id) { - MulticastManagerDataKey key; - key.routing_table = table->name(); - McastTreeManager *tm = table->GetTreeManager(); - McastManagerPartition *partition = tm->GetPartition(inst_id); - data->table_map[key] = partition->size(); - } - - static bool CallbackS1(const Sandesh *sr, - const RequestPipeline::PipeSpec ps, - int stage, int instNum, - RequestPipeline::InstData *data) { - int inst_id = ps.stages_[stage].instances_[instNum]; - - MulticastManagerData *mydata = - static_cast(data); - const ShowMulticastManagerReq *req = - static_cast(ps.snhRequest_.get()); - const string &search_string = req->get_search_string(); - BgpSandeshContext *bsc = - static_cast(req->client_context()); - RoutingInstanceMgr *rim = bsc->bgp_server->routing_instance_mgr(); - for (RoutingInstanceMgr::name_iterator it = rim->name_begin(); - it != rim->name_end(); it++) { - RoutingInstance *ri = it->second; - if (ri->IsDefaultRoutingInstance()) - continue; - ErmVpnTable *table = - static_cast(ri->GetTable(Address::ERMVPN)); - if (!table) - continue; - if (!search_string.empty() && - table->name().find(search_string) == string::npos) { - continue; - } - FillMulticastManagerStats(mydata, table, inst_id); - } - - return true; - } - - static void FillMulticastManagerInfo(const RequestPipeline::StageData *sd, - vector &mgr_list, ErmVpnTable *table) { - ShowMulticastManager mgr; - MulticastManagerDataKey key; - key.routing_table = table->name(); - for (size_t idx = 0; idx < sd->size(); idx++) { - const MulticastManagerData &data = - static_cast(sd->at(idx)); - MulticastManagerData::Map::const_iterator dit = - data.table_map.find(key); - if (dit != data.table_map.end()) { - mgr.total_trees += dit->second; - } - } - - mgr.set_name(table->name()); - mgr_list.push_back(mgr); - } - - static bool CallbackS2(const Sandesh *sr, - const RequestPipeline::PipeSpec ps, - int stage, int instNum, - RequestPipeline::InstData *data) { - const ShowMulticastManagerReq *req = - static_cast(ps.snhRequest_.get()); - const string &search_string = req->get_search_string(); - BgpSandeshContext *bsc = - static_cast(req->client_context()); - RoutingInstanceMgr *rim = bsc->bgp_server->routing_instance_mgr(); - vector mgr_list; - const RequestPipeline::StageData *sd = ps.GetStageData(0); - for (RoutingInstanceMgr::name_iterator it = rim->name_begin(); - it != rim->name_end(); it++) { - RoutingInstance *ri = it->second; - if (ri->IsDefaultRoutingInstance()) - continue; - ErmVpnTable *table = - static_cast(ri->GetTable(Address::ERMVPN)); - if (!table) - continue; - if (!search_string.empty() && - table->name().find(search_string) == string::npos) { - continue; - } - FillMulticastManagerInfo(sd, mgr_list, table); - } - - - ShowMulticastManagerResp *resp = new ShowMulticastManagerResp; - resp->set_managers(mgr_list); - resp->set_context(req->context()); - resp->Response(); - return true; - } -}; - -void ShowMulticastManagerReq::HandleRequest() const { - RequestPipeline::PipeSpec ps(this); - BgpSandeshContext *bsc = static_cast(client_context()); - - // Request pipeline has 2 stages. - // First stage to collect multicast manager stats. - // Second stage to fill stats from stage 1 and respond to the request. - RequestPipeline::StageSpec s1, s2; - TaskScheduler *scheduler = TaskScheduler::GetInstance(); - - s1.taskId_ = scheduler->GetTaskId("db::DBTable"); - s1.allocFn_ = ShowMulticastManagerHandler::CreateData; - s1.cbFn_ = ShowMulticastManagerHandler::CallbackS1; - for (int i = 0; i < bsc->bgp_server->database()->PartitionCount(); i++) { - s1.instances_.push_back(i); - } - - s2.taskId_ = scheduler->GetTaskId("bgp::ShowCommand"); - s2.cbFn_ = ShowMulticastManagerHandler::CallbackS2; - s2.instances_.push_back(0); - - ps.stages_ = list_of(s1)(s2); - RequestPipeline rp(ps); -} - class ShowMulticastManagerDetailHandler { public: struct MulticastManagerDetailData : public RequestPipeline::InstData { @@ -973,7 +832,7 @@ class ShowMulticastManagerDetailHandler { static_cast(req->client_context()); DBTableBase *table = bsc->bgp_server->database()->FindTable(req->get_name()); ErmVpnTable *mcast_table = dynamic_cast(table); - if (mcast_table) + if (mcast_table && !mcast_table->IsVpnTable()) FillMulticastPartitionInfo(mydata, mcast_table, inst_id); return true; diff --git a/src/bgp/bgp_show_multicast_manager.cc b/src/bgp/bgp_show_multicast_manager.cc new file mode 100644 index 00000000000..0d217377503 --- /dev/null +++ b/src/bgp/bgp_show_multicast_manager.cc @@ -0,0 +1,147 @@ +/* + * Copyright (c) 2013 Juniper Networks, Inc. All rights reserved. + */ + +#include "bgp/bgp_show_handler.h" + +#include +#include + +#include "base/time_util.h" +#include "bgp/bgp_peer_internal_types.h" +#include "bgp/bgp_server.h" +#include "bgp/bgp_table.h" +#include "bgp/bgp_multicast.h" +#include "bgp/ermvpn/ermvpn_table.h" +#include "bgp/routing-instance/routing_instance.h" + +using std::string; +using std::vector; + +// +// Fill in information for an ermvpn table. +// +static void FillMulticastManagerInfo(ShowMulticastManager *smm, + const BgpSandeshContext *bsc, const ErmVpnTable *table) { + smm->set_name(table->name()); + const McastTreeManager *manager = table->GetTreeManager(); + if (!manager) + return; + + smm->set_deleted(manager->deleted()); + smm->set_deleted_at( + UTCUsecToString(manager->deleter()->delete_time_stamp_usecs())); + + uint32_t total_trees = 0; + for (McastTreeManager::const_iterator it = manager->begin(); + it != manager->end(); ++it) { + const McastManagerPartition *partition = *it; + total_trees += partition->size(); + } + smm->set_total_trees(total_trees); +} + +// +// Specialization of BgpShowHandler<>::CallbackCommon. +// +template <> +bool BgpShowHandler::CallbackCommon( + const BgpSandeshContext *bsc, Data *data) { + uint32_t page_limit = bsc->page_limit() ? bsc->page_limit() : kPageLimit; + uint32_t iter_limit = bsc->iter_limit() ? bsc->iter_limit() : kIterLimit; + RoutingInstanceMgr *rim = bsc->bgp_server->routing_instance_mgr(); + + RoutingInstanceMgr::const_name_iterator it = + rim->name_clower_bound(data->next_entry); + for (uint32_t iter_count = 0; it != rim->name_cend(); ++it, ++iter_count) { + const RoutingInstance *rtinstance = it->second; + const ErmVpnTable *table = static_cast( + rtinstance->GetTable(Address::ERMVPN)); + if (!table) + continue; + if (!data->search_string.empty() && + (table->name().find(data->search_string) == string::npos) && + (data->search_string != "deleted" || !table->IsDeleted())) { + continue; + } + ShowMulticastManager smm; + FillMulticastManagerInfo(&smm, bsc, table); + data->show_list.push_back(smm); + if (data->show_list.size() >= page_limit) + break; + if (iter_count >= iter_limit) + break; + } + + // All done if we've looked at all instances. + if (it == rim->name_cend() || ++it == rim->name_cend()) + return true; + + // Return true if we've reached the page limit, false if we've reached the + // iteration limit. + bool done = data->show_list.size() >= page_limit; + SaveContextToData(it->second->name(), done, data); + return done; + + return done; +} + +// +// Specialization of BgpShowHandler<>::FillShowList. +// +template <> +void BgpShowHandler::FillShowList( + ShowMulticastManagerResp *resp, + const vector &show_list) { + resp->set_managers(show_list); +} + +// +// Handler for ShowMulticastManagerReq. +// +void ShowMulticastManagerReq::HandleRequest() const { + RequestPipeline::PipeSpec ps(this); + RequestPipeline::StageSpec s1; + TaskScheduler *scheduler = TaskScheduler::GetInstance(); + + s1.taskId_ = scheduler->GetTaskId("bgp::ShowCommand"); + s1.cbFn_ = boost::bind(&BgpShowHandler< + ShowMulticastManagerReq, + ShowMulticastManagerReqIterate, + ShowMulticastManagerResp, + ShowMulticastManager>::Callback, _1, _2, _3, _4, _5); + s1.allocFn_ = BgpShowHandler< + ShowMulticastManagerReq, + ShowMulticastManagerReqIterate, + ShowMulticastManagerResp, + ShowMulticastManager>::CreateData; + s1.instances_.push_back(0); + ps.stages_.push_back(s1); + RequestPipeline rp(ps); +} + +// +// Handler for ShowMulticastManagerReqIterate. +// +void ShowMulticastManagerReqIterate::HandleRequest() const { + RequestPipeline::PipeSpec ps(this); + RequestPipeline::StageSpec s1; + TaskScheduler *scheduler = TaskScheduler::GetInstance(); + + s1.taskId_ = scheduler->GetTaskId("bgp::ShowCommand"); + s1.cbFn_ = boost::bind(&BgpShowHandler< + ShowMulticastManagerReq, + ShowMulticastManagerReqIterate, + ShowMulticastManagerResp, + ShowMulticastManager>::CallbackIterate, _1, _2, _3, _4, _5); + s1.allocFn_ = BgpShowHandler< + ShowMulticastManagerReq, + ShowMulticastManagerReqIterate, + ShowMulticastManagerResp, + ShowMulticastManager>::CreateData; + s1.instances_.push_back(0); + ps.stages_.push_back(s1); + RequestPipeline rp(ps); +} diff --git a/src/bgp/ermvpn/ermvpn_table.cc b/src/bgp/ermvpn/ermvpn_table.cc index 13410c8cc57..29331cf0f96 100644 --- a/src/bgp/ermvpn/ermvpn_table.cc +++ b/src/bgp/ermvpn/ermvpn_table.cc @@ -201,6 +201,10 @@ McastTreeManager *ErmVpnTable::GetTreeManager() { return tree_manager_; } +const McastTreeManager *ErmVpnTable::GetTreeManager() const { + return tree_manager_; +} + void ErmVpnTable::set_routing_instance(RoutingInstance *rtinstance) { BgpTable::set_routing_instance(rtinstance); CreateTreeManager(); diff --git a/src/bgp/ermvpn/ermvpn_table.h b/src/bgp/ermvpn/ermvpn_table.h index 50cea6a124e..bb851c6406e 100644 --- a/src/bgp/ermvpn/ermvpn_table.h +++ b/src/bgp/ermvpn/ermvpn_table.h @@ -51,6 +51,7 @@ class ErmVpnTable : public BgpTable { void CreateTreeManager(); void DestroyTreeManager(); McastTreeManager *GetTreeManager(); + const McastTreeManager *GetTreeManager() const; virtual void set_routing_instance(RoutingInstance *rtinstance); private: diff --git a/src/bgp/test/SConscript b/src/bgp/test/SConscript index 70e4d87dd1b..0387210c098 100644 --- a/src/bgp/test/SConscript +++ b/src/bgp/test/SConscript @@ -230,6 +230,11 @@ bgp_show_instance_config_test = env.UnitTest('bgp_show_instance_config_test', env.Alias('src/bgp:bgp_show_instance_config_test', bgp_show_instance_config_test) +bgp_show_multicast_manager_test = env.UnitTest( + 'bgp_show_multicast_manager_test', ['bgp_show_multicast_manager_test.cc']) +env.Alias('src/bgp:bgp_show_multicast_manager_test', + bgp_show_multicast_manager_test) + bgp_show_neighbor_test = env.UnitTest('bgp_show_neighbor_test', ['bgp_show_neighbor_test.cc']) env.Alias('src/bgp:bgp_show_neighbor_test', @@ -408,6 +413,7 @@ test_suite = [ bgp_sg_test, bgp_show_evpn_table_test, bgp_show_instance_config_test, + bgp_show_multicast_manager_test, bgp_show_neighbor_test, bgp_show_route_summary_test, bgp_show_routing_instance_test, diff --git a/src/bgp/test/bgp_show_multicast_manager_test.cc b/src/bgp/test/bgp_show_multicast_manager_test.cc new file mode 100644 index 00000000000..a1833a443e7 --- /dev/null +++ b/src/bgp/test/bgp_show_multicast_manager_test.cc @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2013 Juniper Networks, Inc. All rights reserved. + */ + +#include "bgp/test/bgp_show_instance_or_table_test.h" + +typedef TypeDefinition< + ShowMulticastManagerReq, + ShowMulticastManagerReqIterate, + ShowMulticastManagerResp> MulticastReq; + +// Specialization of AddInstanceOrTableName. +template<> +void BgpShowInstanceOrTableTest::AddInstanceOrTableName( + vector *names, const string &name) { + string table_name; + if (name == BgpConfigManager::kMasterInstance) { + table_name = "bgp.ermvpn.0"; + } else { + table_name = name + ".ermvpn.0"; + } + names->push_back(table_name); +} + +// Specialization of ValidateResponse. +template<> +void BgpShowInstanceOrTableTest::ValidateResponse( + Sandesh *sandesh, vector &result, const string &next_batch) { + MulticastReq::RespT *resp = dynamic_cast(sandesh); + TASK_UTIL_EXPECT_TRUE(resp != NULL); + TASK_UTIL_EXPECT_EQ(result.size(), resp->get_managers().size()); + TASK_UTIL_EXPECT_EQ(next_batch, resp->get_next_batch()); + for (size_t i = 0; i < resp->get_managers().size(); ++i) { + TASK_UTIL_EXPECT_EQ(result[i], resp->get_managers()[i].get_name()); + cout << resp->get_managers()[i].log() << endl; + } + validate_done_ = true; +} + +// Instantiate all test patterns for ShowMulticastManagerReq. +INSTANTIATE_TYPED_TEST_CASE_P(Config, BgpShowInstanceOrTableTest, MulticastReq); + +class TestEnvironment : public ::testing::Environment { + virtual ~TestEnvironment() { } +}; + +static void SetUp() { + ControlNode::SetDefaultSchedulingPolicy(); + BgpServerTest::GlobalSetUp(); + XmppObjectFactory::Register( + boost::factory()); + BgpObjectFactory::Register( + boost::factory()); +} + +static void TearDown() { + task_util::WaitForIdle(); + TaskScheduler *scheduler = TaskScheduler::GetInstance(); + scheduler->Terminate(); +} + +int main(int argc, char **argv) { + bgp_log_test::init(); + ::testing::InitGoogleTest(&argc, argv); + ::testing::AddGlobalTestEnvironment(new TestEnvironment()); + SetUp(); + int result = RUN_ALL_TESTS(); + TearDown(); + return result; +} diff --git a/src/bgp/test/bgp_xmpp_mcast_test.cc b/src/bgp/test/bgp_xmpp_mcast_test.cc index 9774a975c06..e3e60409ed3 100644 --- a/src/bgp/test/bgp_xmpp_mcast_test.cc +++ b/src/bgp/test/bgp_xmpp_mcast_test.cc @@ -54,29 +54,6 @@ class BgpXmppMcastTest : public ::testing::Test { validate_done_ = 1; } - static void ValidateShowManagerMulticastResponse(Sandesh *sandesh, - vector &result) { - ShowMulticastManagerResp *resp = - dynamic_cast(sandesh); - EXPECT_NE((ShowMulticastManagerResp *)NULL, resp); - - TASK_UTIL_EXPECT_EQ(result.size(), resp->get_managers().size()); - cout << "*******************************************************"<get_managers().size(); ++i) { - cout << resp->get_managers()[i].log() << endl; - bool found = false; - BOOST_FOREACH(const string &manager_name, result) { - if (resp->get_managers()[i].get_name() == manager_name) { - found = true; - break; - } - } - EXPECT_TRUE(found); - } - cout << "*******************************************************"< &result) { ShowMulticastManagerDetailResp *resp = @@ -780,78 +757,6 @@ TEST_F(BgpXmppMcastMultiAgentTest, ValidateShowRoute) { TASK_UTIL_EXPECT_EQ(1, validate_done_); }; -TEST_F(BgpXmppMcastMultiAgentTest, ValidateShowMulticastManager) { - Subscribe("pink", 2); - - const char *mroute = "225.0.0.1,90.1.1.1"; - const char *networks[] = { "blue", "pink" }; - - // Add mcast routes for all agents. - BOOST_FOREACH(const char *net, networks) { - agent_xa_->AddMcastRoute(net, mroute, "10.1.1.1", "10000-19999"); - agent_xb_->AddMcastRoute(net, mroute, "10.1.1.2", "20000-29999"); - agent_xc_->AddMcastRoute(net, mroute, "10.1.1.3", "30000-39999"); - task_util::WaitForIdle(); - } - - // Verify that all agents have the routes. - TASK_UTIL_EXPECT_EQ(2, agent_xa_->McastRouteCount()); - TASK_UTIL_EXPECT_EQ(2, agent_xb_->McastRouteCount()); - TASK_UTIL_EXPECT_EQ(2, agent_xc_->McastRouteCount()); - - // Verify multicast manager via sandesh. - BgpSandeshContext sandesh_context; - RegisterSandeshShowXmppExtensions(&sandesh_context); - sandesh_context.bgp_server = bs_x_.get(); - sandesh_context.xmpp_peer_manager = bcm_x_.get(); - Sandesh::set_client_context(&sandesh_context); - vector result = list_of("blue.ermvpn.0")("pink.ermvpn.0"); - Sandesh::set_response_callback( - boost::bind(ValidateShowManagerMulticastResponse, _1, result)); - ShowMulticastManagerReq *show_req = new ShowMulticastManagerReq; - validate_done_ = 0; - show_req->HandleRequest(); - show_req->Release(); - task_util::WaitForIdle(); - TASK_UTIL_EXPECT_EQ(1, validate_done_); - - // Match "". - result = list_of("blue.ermvpn.0")("pink.ermvpn.0"); - Sandesh::set_response_callback( - boost::bind(ValidateShowManagerMulticastResponse, _1, result)); - show_req = new ShowMulticastManagerReq; - validate_done_ = 0; - show_req->set_search_string(""); - show_req->HandleRequest(); - show_req->Release(); - task_util::WaitForIdle(); - TASK_UTIL_EXPECT_EQ(1, validate_done_); - - // Match "ermvpn.0". - result = list_of("blue.ermvpn.0")("pink.ermvpn.0"); - Sandesh::set_response_callback( - boost::bind(ValidateShowManagerMulticastResponse, _1, result)); - show_req = new ShowMulticastManagerReq; - validate_done_ = 0; - show_req->set_search_string("ermvpn.0"); - show_req->HandleRequest(); - show_req->Release(); - task_util::WaitForIdle(); - TASK_UTIL_EXPECT_EQ(1, validate_done_); - - // Match "pink". - result = list_of("pink.ermvpn.0"); - Sandesh::set_response_callback( - boost::bind(ValidateShowManagerMulticastResponse, _1, result)); - show_req = new ShowMulticastManagerReq; - validate_done_ = 0; - show_req->set_search_string("pink"); - show_req->HandleRequest(); - show_req->Release(); - task_util::WaitForIdle(); - TASK_UTIL_EXPECT_EQ(1, validate_done_); -}; - TEST_F(BgpXmppMcastMultiAgentTest, ValidateShowMulticastManagerDetail) { const char *mroutes[] = { "225.0.0.1,90.1.1.1", "225.0.0.2,90.1.1.1" };