0, // pool
""s}; // nspace
+hobject_t ec_hobj_ms1{object_t{"ec_hobj_ms1"},
+ "keykey", // key
+ CEPH_NOSNAP, // snap_id
+ 0, // hash
+ 0, // pool
+ ""s}; // nspace
+
SnapsetMockData::CookedCloneSnaps ms1_fn()
{
std::map<snapid_t, uint64_t> clnsz;
return {clnsz, clnsn, overlaps};
}
+SnapsetMockData::CookedCloneSnaps ms2_fn() { return {{}, {}, {}}; }
+
static SnapsetMockData hobj_ms1_snapset{/* seq */ 0x40,
/* clones */ {0x20, 0x30},
ms1_fn};
+static SnapsetMockData empty_snapset{/* seq */ 0x0,
+ /* clones */ {}, ms2_fn};
+
hobject_t hobj_ms1_snp30{object_t{"hobj_ms1"},
"keykey", // key
0x30, // snap_id
};
+ScrubGenerator::RealObj erasure_code_obj{
+ ghobject_t{ec_hobj_ms1, 1, shard_id_t{0}},
+ RealData{100, 0xf8346009, 0, 0, {}, {}}, &crpt_funcs_set0, &empty_snapset};
+
} // namespace ScrubDatasets
#include "osd/scrubber/pg_scrubber.h"
#include "osd/scrubber/scrub_backend.h"
+#include "erasure-code/ErasureCodePlugin.h"
+
/// \file testing isolated parts of the Scrubber backend
using namespace std::string_literals;
bl.rebuild();
encode_map.insert(i, bl);
}
+
for (shard_id_t i; i < get_ec_sinfo().get_k(); ++i) {
for (int j = 0; j < get_ec_sinfo().get_chunk_size(); j++) {
encode_map.at(i).c_str()[j] =
EXPECT_EQ(incons.size(), 1); // one inconsistency
}
+class TestTScrubberBeECCorruptShards : public TestTScrubberBe {
+ private:
+ int seed;
+
+ protected:
+ std::mt19937 rng;
+ int8_t k;
+ int8_t m;
+ int m_chunk_size = 4;
+
+ public:
+ TestTScrubberBeECCorruptShards()
+ : TestTScrubberBe(),
+ seed(time(0)),
+ rng(seed),
+ k((rng() % 10) + 2),
+ m((rng() % std::min(k - 1, 4)) + 1) {
+ std::cout << "Using seed " << seed << std::endl;
+ }
+
+ std::size_t m_expected_inconsistencies = 0;
+ std::size_t m_expected_error_count = 0;
+
+ // basic test configuration - 3 OSDs, all involved in the pool
+ erasure_code_profile_conf_t ec_profile{
+ "scrub_ec_profile",
+ {{"k", fmt::format("{}", k)},
+ {"m", fmt::format("{}", m)},
+ {"plugin", "isa"},
+ {"technique", "reed_sol_van"},
+ {"stripe_unit", fmt::format("{}", m_chunk_size)}}};
+
+ pool_conf_t pl{3, 3, k + m, k + 1, "ec_pool", pg_pool_t::TYPE_ERASURE,
+ ec_profile};
+
+ TestTScrubberBeParams inject_params() override {
+ std::cout << fmt::format(
+ "{}: injecting params (minimal-snaps + size change)",
+ __func__)
+ << std::endl;
+ TestTScrubberBeParams params{
+ /* pool_conf */ pl,
+ /* real_objs_conf */
+ ScrubGenerator::make_erasure_code_configuration(k, m),
+ /*num_osds */ k + m};
+
+ return params;
+ }
+};
+
+class TestTScrubberBeECNoCorruptShards : public TestTScrubberBeECCorruptShards {
+ public:
+ TestTScrubberBeECNoCorruptShards() : TestTScrubberBeECCorruptShards() {}
+};
+
+TEST_F(TestTScrubberBeECNoCorruptShards, ec_parity_inconsistency) {
+ test_pg->set_stripe_info(k, m, k * m_chunk_size, &test_pg->m_pool->info);
+
+ ASSERT_TRUE(sbe); // Assert we have a scrubber backend
+ logger.set_expected_err_count(
+ 0); // Set the number of errors we expect to see
+
+ auto [incons, fix_list] = sbe->scrub_compare_maps(true, *test_scrubber);
+
+ EXPECT_EQ(incons.size(), 0);
+}
+
+class TestTScrubberBeECSingleCorruptDataShard
+ : public TestTScrubberBeECCorruptShards {
+ public:
+ TestTScrubberBeECSingleCorruptDataShard()
+ : TestTScrubberBeECCorruptShards() {}
+
+ TestTScrubberBeParams inject_params() override {
+ TestTScrubberBeParams params =
+ TestTScrubberBeECCorruptShards::inject_params();
+ corrupt_funcs = make_erasure_code_hash_corruption_functions(k + m);
+ params.objs_conf.objs[(rng() % k)].corrupt_funcs = &corrupt_funcs;
+ return params;
+ }
+
+ private:
+ CorruptFuncList corrupt_funcs;
+};
+
+TEST_F(TestTScrubberBeECSingleCorruptDataShard, ec_parity_inconsistency) {
+ test_pg->set_stripe_info(k, m, k * m_chunk_size, &test_pg->m_pool->info);
+
+ ASSERT_TRUE(sbe); // Assert we have a scrubber backend
+ logger.set_expected_err_count(
+ 1); // Set the number of errors we expect to see
+
+ auto [incons, fix_list] = sbe->scrub_compare_maps(true, *test_scrubber);
+
+ EXPECT_EQ(incons.size(), 1);
+}
+
+class TestTScrubberBeECCorruptParityShard
+ : public TestTScrubberBeECCorruptShards {
+ public:
+ TestTScrubberBeECCorruptParityShard() : TestTScrubberBeECCorruptShards() {}
+
+ TestTScrubberBeParams inject_params() override {
+ TestTScrubberBeParams params =
+ TestTScrubberBeECCorruptShards::inject_params();
+ corrupt_funcs = make_erasure_code_hash_corruption_functions(k + m);
+ params.objs_conf.objs[k].corrupt_funcs = &corrupt_funcs;
+ return params;
+ }
+
+ private:
+ CorruptFuncList corrupt_funcs;
+};
+
+TEST_F(TestTScrubberBeECCorruptParityShard, ec_parity_inconsistency) {
+ test_pg->set_stripe_info(k, m, k * m_chunk_size, &test_pg->m_pool->info);
+
+ ASSERT_TRUE(sbe); // Assert we have a scrubber backend
+ logger.set_expected_err_count(
+ 1); // Set the number of errors we expect to see
+
+ auto [incons, fix_list] = sbe->scrub_compare_maps(true, *test_scrubber);
+
+ EXPECT_EQ(incons.size(), 1);
+}
+
// Local Variables:
// compile-command: "cd ../.. ; make unittest_osdscrub ; ./unittest_osdscrub
// --log-to-stderr=true --debug-osd=20 # --gtest_filter=*.* " End: