From 30258bc14d44dc221eb88dda4fba03d1dc476305 Mon Sep 17 00:00:00 2001 From: Radoslaw Zarzynski Date: Thu, 30 Jul 2020 16:46:17 +0200 Subject: [PATCH] crimson/tests: implement randomized testing for backfill. Signed-off-by: Radoslaw Zarzynski --- src/test/crimson/test_backfill.cc | 96 ++++++++++++++++++++++++++++++- 1 file changed, 95 insertions(+), 1 deletion(-) diff --git a/src/test/crimson/test_backfill.cc b/src/test/crimson/test_backfill.cc index bfd95ae3c1768..0409d47253d24 100644 --- a/src/test/crimson/test_backfill.cc +++ b/src/test/crimson/test_backfill.cc @@ -1,5 +1,7 @@ #include +#include #include +#include #include #include #include @@ -44,6 +46,13 @@ struct FakeStore { objs[obj] = version; } + void drop(const hobject_t& obj, const eversion_t version) { + auto it = objs.find(obj); + ceph_assert(it != std::end(objs)); + ceph_assert(it->second == version); + objs.erase(it); + } + template hobject_t list(const hobject_t& start, Func&& per_entry) const { auto it = objs.lower_bound(start); @@ -141,6 +150,12 @@ public: } } + void next_till_done() { + while (!events_to_dispatch.empty()) { + next_round(); + } + } + bool all_stores_look_like(const FakeStore& reference) const { const bool all_replica_match = std::all_of( std::begin(backfill_targets), std::end(backfill_targets), @@ -279,7 +294,7 @@ void BackfillFixture::enqueue_drop( const hobject_t& obj, const eversion_t& v) { - std::cout << __func__ << std::endl; + backfill_targets.at(target).store.drop(obj, v); } void BackfillFixture::update_peers_last_backfill( @@ -360,3 +375,82 @@ TEST(backfill, single_empty_replica) cluster_fixture.next_round(); EXPECT_TRUE(cluster_fixture.all_stores_look_like(reference_store)); } + +namespace StoreRandomizer { + // FIXME: copied & pasted from test/test_snap_mapper.cc. We need to + // find a way to avoid code duplication in test. A static library? + std::string random_string(std::size_t size) { + std::string name; + for (size_t j = 0; j < size; ++j) { + name.push_back('a' + (std::rand() % 26)); + } + return name; + } + + hobject_t random_hobject() { + uint32_t mask{0}; + uint32_t bits{0}; + return hobject_t( + random_string(1+(std::rand() % 16)), + random_string(1+(std::rand() % 16)), + snapid_t(std::rand() % 1000), + (std::rand() & ((~0)< 0; --i) { + store.push(random_hobject(), random_eversion()); + } + return store; + } + + template + void execute_random(Args&&... args) { + std::array, sizeof...(Args)> funcs = { + std::forward(args)... + }; + return std::move(funcs[std::rand() % std::size(funcs)])(); + } + + FakeStore mutate(const FakeStore& source_store) { + FakeStore mutated_store; + source_store.list(hobject_t{}, [&] (const auto& kv) { + const auto& [ oid, version ] = kv; + execute_random( + [] { /* just drop the entry */ }, + [&] { mutated_store.push(oid, version); }, + [&] { mutated_store.push(oid, random_eversion()); }, + [&] { mutated_store.push(random_hobject(), version); }, + [&] { + for (auto how_many = std::rand() % 8; how_many > 0; --how_many) { + mutated_store.push(random_hobject(), random_eversion()); + } + } + ); + }); + return mutated_store; + } +} + +// The name might suggest randomness is involved here. Well, that's true +// but till we know the seed the test still is repeatable. +TEST(backfill, one_pseudorandomized_replica) +{ + const auto reference_store = StoreRandomizer::create(); + auto cluster_fixture = BackfillFixtureBuilder::add_source( + reference_store.objs + ).add_target( + StoreRandomizer::mutate(reference_store).objs + ).get_result(); + + EXPECT_CALL(cluster_fixture, backfilled); + cluster_fixture.next_till_done(); + + EXPECT_TRUE(cluster_fixture.all_stores_look_like(reference_store)); +} -- 2.39.5