From ea176bf4ce4ac01bd4ed604bc1cb17ece45fec2f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Botond=20D=C3=A9nes?= Date: Wed, 6 Dec 2023 05:10:30 -0500 Subject: [PATCH] test/boost/sstable_compaction_test: use scrub_test_framework in sstable_scrub_skip_mode_test The test becomes a lot shorter and it now uses random schema and random data. The test is also split in two: one test for abort mode and one for skip mode. Indentation is left broken, to be fixed in a future patch. (cherry picked from commit 5237e8133b3f4da45eafcf60661ee01ca817ab9c) --- test/boost/sstable_compaction_test.cc | 116 +++++++++++--------------- 1 file changed, 50 insertions(+), 66 deletions(-) diff --git a/test/boost/sstable_compaction_test.cc b/test/boost/sstable_compaction_test.cc index 3ce34f834a..acf4eac942 100644 --- a/test/boost/sstable_compaction_test.cc +++ b/test/boost/sstable_compaction_test.cc @@ -2322,93 +2322,77 @@ SEASTAR_TEST_CASE(sstable_validate_test) { }); } -SEASTAR_TEST_CASE(sstable_scrub_skip_mode_test) { - cql_test_config test_cfg; +SEASTAR_THREAD_TEST_CASE(sstable_scrub_abort_mode_test) { + scrub_test_framework test; - auto& db_cfg = *test_cfg.db_config; + auto schema = test.schema(); - // Disable cache to filter out its possible "corrections" to the corrupt sstable. - db_cfg.enable_cache(false); - db_cfg.enable_commitlog(false); + auto muts = tests::generate_random_mutations(test.random_schema(), 3).get(); + std::swap(*muts.begin(), *(muts.begin() + 1)); - return do_with_cql_env([] (cql_test_env& cql_env) -> future<> { - return test_env::do_with_async([] (test_env& env) { - auto schema = schema_builder("ks", get_name()) - .with_column("pk", utf8_type, column_kind::partition_key) - .with_column("ck", int32_type, column_kind::clustering_key) - .with_column("s", int32_type, column_kind::static_column) - .with_column("v", int32_type).build(); - auto permit = env.make_reader_permit(); - std::vector scrubbed_fragments; - auto sst = env.make_sstable(schema); - - const auto corrupt_fragments = write_corrupt_sstable(env, *sst, permit, [&] (mutation_fragment_v2&& mf, bool is_corrupt) { - if (!is_corrupt) { - scrubbed_fragments.emplace_back(std::move(mf)); - } - }); - - testlog.info("Writing sstable {}", sst->get_filename()); - - sst->load(sst->get_schema()->get_sharder()).get(); - - testlog.info("Loaded sstable {}", sst->get_filename()); - - auto table = env.make_table_for_tests(schema); - auto close_cf = deferred_stop(table); - table->start(); - auto& compaction_manager = table.get_compaction_manager(); - - table->add_sstable_and_update_cache(sst).get(); - - bool found_sstable = false; - foreach_table_state_with_thread(table, [&] (compaction::table_state& ts) { - auto sstables = in_strategy_sstables(ts); - if (sstables.empty()) { - return; - } + test.run(schema, muts, [] (table_for_tests& table, compaction::table_state& ts, std::vector sstables) { BOOST_REQUIRE(sstables.size() == 1); - BOOST_REQUIRE(sstables.front() == sst); - found_sstable = true; - - auto verify_fragments = [&] (sstables::shared_sstable sst, const std::vector& mfs) { - auto r = assert_that(sst->as_mutation_source().make_reader_v2(schema, permit)); - for (const auto& mf : mfs) { - testlog.trace("Expecting {}", mutation_fragment_v2::printer(*schema, mf)); - r.produces(*schema, mf); - } - r.produces_end_of_stream(); - }; - - testlog.info("Verifying written data..."); - - // Make sure we wrote what we though we wrote. - verify_fragments(sst, corrupt_fragments); + auto sst = sstables.front(); testlog.info("Scrub in abort mode"); // We expect the scrub with mode=srub::mode::abort to stop on the first invalid fragment. sstables::compaction_type_options::scrub opts = {}; opts.operation_mode = sstables::compaction_type_options::scrub::mode::abort; - BOOST_REQUIRE_THROW(compaction_manager.perform_sstable_scrub(ts, opts).get(), sstables::compaction_aborted_exception); + BOOST_REQUIRE_THROW(table->get_compaction_manager().perform_sstable_scrub(ts, opts).get(), sstables::compaction_aborted_exception); BOOST_REQUIRE(in_strategy_sstables(ts).size() == 1); - verify_fragments(sst, corrupt_fragments); + BOOST_REQUIRE(in_strategy_sstables(ts).front() == sst); + }); +} + +SEASTAR_THREAD_TEST_CASE(sstable_scrub_skip_mode_test) { + scrub_test_framework test; + + auto schema = test.schema(); + + auto corrupt_muts = tests::generate_random_mutations( + test.random_schema(), + tests::uncompactible_timestamp_generator(test.seed()), + tests::no_expiry_expiry_generator(), + std::uniform_int_distribution(10, 10), + std::uniform_int_distribution(10, 20), + std::uniform_int_distribution(0, 0)).get(); + + // prepare a corrupt fragment list, with both an ooo partition and an ooo row + std::swap(corrupt_muts.at(0), corrupt_muts.at(1)); + auto corrupt_fragments = explode(test.env().make_reader_permit(), corrupt_muts); + auto first_cr_index = corrupt_fragments.at(1).is_static_row() ? 2 : 1; + auto& cr1 = corrupt_fragments.at(first_cr_index); + auto& cr2 = corrupt_fragments.at(first_cr_index + 1); + BOOST_REQUIRE_EQUAL(cr1.mutation_fragment_kind(), mutation_fragment_v2::kind::clustering_row); + BOOST_REQUIRE_EQUAL(cr2.mutation_fragment_kind(), mutation_fragment_v2::kind::clustering_row); + std::swap(cr1, cr2); + + // prepare the expected post-scrub version of "corrupt_fragments" + std::vector scrubbed_muts; + scrubbed_muts.push_back(corrupt_muts.front()); + std::copy(corrupt_muts.begin() + 2, corrupt_muts.end(), std::back_inserter(scrubbed_muts)); + auto scrubbed_fragments = explode(test.env().make_reader_permit(), std::move(scrubbed_muts)); + scrubbed_fragments.erase(scrubbed_fragments.begin() + first_cr_index); + + test.run(schema, std::move(corrupt_fragments), [&] (table_for_tests& table, compaction::table_state& ts, std::vector sstables) { + BOOST_REQUIRE(sstables.size() == 1); + auto sst = sstables.front(); testlog.info("Scrub in skip mode"); // We expect the scrub with mode=srub::mode::skip to get rid of all invalid data. + sstables::compaction_type_options::scrub opts = {}; opts.operation_mode = sstables::compaction_type_options::scrub::mode::skip; - compaction_manager.perform_sstable_scrub(ts, opts).get(); + table->get_compaction_manager().perform_sstable_scrub(ts, opts).get(); BOOST_REQUIRE(in_strategy_sstables(ts).size() == 1); BOOST_REQUIRE(in_strategy_sstables(ts).front() != sst); - verify_fragments(in_strategy_sstables(ts).front(), scrubbed_fragments); - }).get(); - assert(found_sstable); - }); - }, test_cfg); + + verify_fragments(in_strategy_sstables(ts), test.env().make_reader_permit(), scrubbed_fragments); + }); } SEASTAR_TEST_CASE(sstable_scrub_segregate_mode_test) {