From: stzuraski898 Date: Wed, 28 Jan 2026 21:49:06 +0000 (+0000) Subject: test/mgr: Add ClusterState unit tests X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=3dcf1e7a7655b95c829aad6bd575f9bb0fa05815;p=ceph-ci.git test/mgr: Add ClusterState unit tests Fixes: https://tracker.ceph.com/issues/72938 Signed-off-by: stzuraski898 --- diff --git a/src/test/mgr/test_clusterstate.cc b/src/test/mgr/test_clusterstate.cc new file mode 100644 index 00000000000..43300aa47d1 --- /dev/null +++ b/src/test/mgr/test_clusterstate.cc @@ -0,0 +1,217 @@ +// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- +// vim: ts=8 sw=2 smarttab + +#include + +#include "global/global_init.h" +#include "gtest/gtest.h" +#include "messages/MMgrDigest.h" +#include "messages/MPGStats.h" +#include "mgr/ClusterState.h" +#include "mon/PGMap.h" +#include "osd/osd_types.h" +#include "test/mgr/TestMgr.h" + +TEST_F(TestMgr, ClusterState_Construct) +{ + cs->with_mgrmap([&](const MgrMap& m) { ASSERT_EQ(m.epoch, mgr_map.epoch); }); + + cs->with_osdmap([&](const OSDMap& o) { ASSERT_EQ(o.get_epoch(), 0); }); + + cs->with_fsmap([&](const FSMap& f) { ASSERT_EQ(f.get_epoch(), 0); }); + + cs->with_servicemap([&](const ServiceMap& sm) { ASSERT_EQ(sm.epoch, 0); }); + + cs->with_pgmap([&](const PGMap& pm) { ASSERT_EQ(pm.version, 0); }); +} + +TEST_F(TestMgr, ClusterState_Setters) +{ + Objecter new_objecter(cct.get(), messenger.get(), mc.get(), *icp); + cs->set_objecter(&new_objecter); + ASSERT_EQ(cs->test_get_objecter(), &new_objecter); + ASSERT_NE(cs->test_get_objecter(), objecter.get()); + + cs->with_osdmap_and_pgmap([&](const OSDMap& old_map, const PGMap& pg_map) { + cs->notify_osdmap(osd_map); + }); + cs->with_osdmap([&](const OSDMap& o) { + ASSERT_EQ(o.get_epoch(), osd_map.get_epoch()); + }); + + ASSERT_FALSE(cs->have_fsmap()); + const FSMap fs_map = [] { + FSMap f; + f.inc_epoch(); + f.inc_epoch(); + return f; + }(); + cs->set_fsmap(fs_map); + ASSERT_TRUE(cs->have_fsmap()); + cs->with_fsmap([&](const FSMap& f) { + ASSERT_EQ(f.get_epoch(), fs_map.get_epoch()); + }); + + const MgrMap new_mgr_map = [] { + MgrMap m; + m.epoch = 456; + return m; + }(); + cs->set_mgr_map(new_mgr_map); + cs->with_mgrmap([&](const MgrMap& m) { + ASSERT_EQ(m.epoch, new_mgr_map.epoch); + }); + + const ServiceMap s_map = [] { + ServiceMap s; + s.epoch = 777; + return s; + }(); + cs->set_service_map(s_map); + cs->with_servicemap([&](const ServiceMap& sm) { + ASSERT_EQ(sm.epoch, s_map.epoch); + }); + + //After notify_osdmap, pgmap version should be incremented from 0 + cs->with_pgmap([&](const PGMap& pm) { ASSERT_EQ(pm.version, 1); }); +} + +TEST_F(TestMgr, ClusterState_LoadDigest) +{ + const bufferlist mon_status_bl = [] { + bufferlist bl; + bl.append("{\"monmap\":{\"epoch\":1}}"); + return bl; + }(); + + const bufferlist health_bl = [] { + bufferlist bl; + bl.append("{\"status\":\"HEALTH_OK\"}"); + return bl; + }(); + + auto digest = ceph::make_message(); + digest->mon_status_json = mon_status_bl; + digest->health_json = health_bl; + + cs->load_digest(digest.get()); + + cs->with_mon_status([&](const bufferlist& monstat) { + ASSERT_EQ(monstat.length(), mon_status_bl.length()); + ASSERT_EQ(monstat.to_str(), mon_status_bl.to_str()); + }); + + cs->with_health([&](const bufferlist& health) { + ASSERT_EQ(health.length(), health_bl.length()); + ASSERT_EQ(health.to_str(), health_bl.to_str()); + }); +} + +TEST_F(ClusterStateTest, IngestPGStats_Valid) +{ + // Test 1: OSD is in the map, PG pool exists, in range, new version + pg_t pgid(0, 1); + stats->pg_stat[pgid] = pgstat; + ingest_and_pginc(); + + ASSERT_TRUE(p_inc.pg_stat_updates.contains(pgid)); +} + +TEST_F(ClusterStateTest, IngestPGStats_PoolDNE) +{ + //Test 2: OSD is in the map, PG pool does not exist + pg_t pgid(0, 2); + stats->pg_stat[pgid] = pgstat; + ingest_and_pginc(); + + ASSERT_FALSE(p_inc.pg_stat_updates.contains(pgid)); +} + +TEST_F(ClusterStateTest, IngestPGStats_OOR) +{ + //Test 3: OSD is in the map, PG pool exists, out of range + pg_t pgid_out_of_range(2, 1); + stats->pg_stat[pgid_out_of_range] = pgstat; + ingest_and_pginc(); + + ASSERT_FALSE(p_inc.pg_stat_updates.contains(pgid_out_of_range)); +} + +TEST_F(ClusterStateTest, IngestPGStats_oldReportedSeq) +{ + pg_t pgid_valid(0, 1); + + stats->set_src(entity_name_t::OSD(0)); + stats->pg_stat[pgid_valid] = pgstat; + + cs->ingest_pgstats(stats); + cs->update_delta_stats(); + + //Test 4: OSD is in the map, PG pool exists, shard in range, old version + pgstat.reported_epoch = 1; + pgstat.reported_seq = 1; + stats->osd_stat.seq = 1; + pg_t pgid_old_version(0, 1); + stats->pg_stat[pgid_old_version] = pgstat; + ingest_and_pginc(); + + ASSERT_FALSE(p_inc.pg_stat_updates.contains(pgid_old_version)); +} + +TEST_F(ClusterStateTest, UpdateDeltaStats) +{ + pg_t pgid(0, 1); + + pgstat.reported_seq = 1; + stats->pg_stat[pgid] = pgstat; + + cs->ingest_pgstats(stats); + cs->update_delta_stats(); + + p_inc = cs->test_get_pending_inc(); + PGMap pg_map = cs->test_get_pg_map(); + + ASSERT_TRUE(p_inc.pg_stat_updates.empty()); + ASSERT_TRUE(pg_map.pg_stat.contains(pgid)); + ASSERT_EQ(pg_map.pg_stat[pgid].reported_seq, pgstat.reported_seq); +} + +TEST_F(ClusterStateTest, NotifyOSDMap) +{ + const pg_pool_t pool1 = [] { + pg_pool_t p; + p.set_pg_num(2); + return p; + }(); + + const pg_pool_t pool2 = [] { + pg_pool_t p; + p.set_pg_num(4); + return p; + }(); + + OSDMap::Incremental notify_inc(osd_map.get_epoch() + 1); + notify_inc.new_pool_max = 2; + notify_inc.new_pools[1] = pool1; + notify_inc.new_pools[2] = pool2; + osd_map.apply_incremental(notify_inc); + + cs->with_osdmap_and_pgmap([&](const OSDMap& old_map, const PGMap& pg_map) { + cs->notify_osdmap(osd_map); + }); + + const auto& existing_pools = cs->test_get_existing_pools(); + + ASSERT_TRUE(existing_pools.contains(1)); + ASSERT_TRUE(existing_pools.contains(2)); + ASSERT_EQ(existing_pools.at(1), pool1.get_pg_num()); + ASSERT_EQ(existing_pools.at(2), pool2.get_pg_num()); +} + +int +main(int argc, char* argv[]) +{ + ::testing::InitGoogleTest(&argc, argv); + + return RUN_ALL_TESTS(); +}