From 72cb835c1ef17334cf1dfd2ca47d3c000856cc18 Mon Sep 17 00:00:00 2001 From: Pavel Emelyanov Date: Fri, 6 Sep 2024 16:27:11 +0300 Subject: [PATCH] test: Move b+tree stress test from unit to boost Just move the code. And hard-code the "scale" (i.e. -- number of keys and iterations) from default arguments of the unit test. Signed-off-by: Pavel Emelyanov --- configure.py | 2 - test/boost/bptree_test.cc | 122 ++++++++++++++++++++++++ test/unit/CMakeLists.txt | 2 - test/unit/bptree_stress_test.cc | 160 -------------------------------- 4 files changed, 122 insertions(+), 164 deletions(-) delete mode 100644 test/unit/bptree_stress_test.cc diff --git a/configure.py b/configure.py index 4e9a535244..afd7bebe18 100755 --- a/configure.py +++ b/configure.py @@ -630,7 +630,6 @@ scylla_tests = set([ 'test/unit/lsa_sync_eviction_test', 'test/unit/row_cache_alloc_stress_test', 'test/unit/row_cache_stress_test', - 'test/unit/bptree_stress_test', 'test/unit/btree_stress_test', 'test/unit/bptree_compaction_test', 'test/unit/btree_compaction_test', @@ -1420,7 +1419,6 @@ tests_not_using_seastar_test_framework = set([ 'test/unit/lsa_async_eviction_test', 'test/unit/lsa_sync_eviction_test', 'test/unit/row_cache_alloc_stress_test', - 'test/unit/bptree_stress_test', 'test/unit/btree_stress_test', 'test/unit/bptree_compaction_test', 'test/unit/btree_compaction_test', diff --git a/test/boost/bptree_test.cc b/test/boost/bptree_test.cc index 5dbb966ac7..b4f5290298 100644 --- a/test/boost/bptree_test.cc +++ b/test/boost/bptree_test.cc @@ -14,6 +14,8 @@ #include "utils/assert.hh" #include "utils/bptree.hh" +#include "test/unit/collection_stress.hh" +#include "test/unit/bptree_validation.hh" #include "test/unit/tree_test_key.hh" struct int_compare { @@ -356,3 +358,123 @@ BOOST_AUTO_TEST_CASE(test_avx_search) { t.clear(); check_conversions(); } + +using test_key = tree_test_key_base; + +class test_data { + int _value; +public: + test_data() : _value(0) {} + test_data(test_key& k) : _value((int)k + 10) {} + + operator unsigned long() const { return _value; } + bool match_key(const test_key& k) const { return _value == (int)k + 10; } +}; + +template <> struct fmt::formatter : fmt::formatter { + auto format(test_data d, fmt::format_context& ctx) const { + return fmt::format_to(ctx.out(), "{}", static_cast(d)); + } +}; + +BOOST_AUTO_TEST_CASE(stress_test) { + constexpr int TEST_NODE_SIZE = 16; + using test_tree = tree; + using test_validator = validator; + using test_iterator_checker = iterator_checker; + + auto t = std::make_unique(test_key_compare{}); + std::map oracle; + test_validator tv; + auto* itc = new test_iterator_checker(tv, *t); + + stress_config cfg; + cfg.count = 4132; + cfg.iters = 9; + cfg.keys = "rand"; + cfg.verb = false; + auto rep = 0, itv = 0; + + stress_collection(cfg, + /* insert */ [&] (int key) { + test_key k(key); + + if (rep % 2 != 1) { + auto ir = t->emplace(copy_key(k), k); + SCYLLA_ASSERT(ir.second); + } else { + auto ir = t->lower_bound(k); + ir.emplace_before(copy_key(k), test_key_compare{}, k); + } + oracle[key] = key + 10; + + if (itv++ % 7 == 0) { + if (!itc->step()) { + delete itc; + itc = new test_iterator_checker(tv, *t); + } + } + }, + /* erase */ [&] (int key) { + test_key k(key); + + if (itc->here(k)) { + delete itc; + itc = nullptr; + } + + if (rep % 3 != 2) { + t->erase(k); + } else { + auto ri = t->find(k); + auto ni = ri; + ni++; + auto eni = ri.erase(test_key_compare{}); + SCYLLA_ASSERT(ni == eni); + } + oracle.erase(key); + + if (itc == nullptr) { + itc = new test_iterator_checker(tv, *t); + } + + if (itv++ % 5 == 0) { + if (!itc->step()) { + delete itc; + itc = new test_iterator_checker(tv, *t); + } + } + }, + /* validate */ [&] { + if (cfg.verb) { + fmt::print("Validating\n"); + tv.print_tree(*t, '|'); + } + tv.validate(*t); + }, + /* step */ [&] (stress_step step) { + if (step == stress_step::iteration_finished) { + rep++; + } + + if (step == stress_step::before_erase) { + auto sz = t->size_slow(); + if (sz != (size_t)cfg.count) { + fmt::print("Size {} != count {}\n", sz, cfg.count); + throw "size"; + } + + auto ti = t->begin(); + for (auto oe : oracle) { + if ((unsigned long)*ti != oe.second) { + fmt::print("Data mismatch {} vs {}\n", oe.second, *ti); + throw "oracle"; + } + ti++; + } + } + }, + false); + + delete itc; +} diff --git a/test/unit/CMakeLists.txt b/test/unit/CMakeLists.txt index 211f6eb399..b12bf79105 100644 --- a/test/unit/CMakeLists.txt +++ b/test/unit/CMakeLists.txt @@ -1,7 +1,5 @@ add_scylla_test(bptree_compaction_test KIND UNIT) -add_scylla_test(bptree_stress_test - KIND UNIT) add_scylla_test(btree_compaction_test KIND UNIT) add_scylla_test(btree_stress_test diff --git a/test/unit/bptree_stress_test.cc b/test/unit/bptree_stress_test.cc deleted file mode 100644 index 36c3c6e17a..0000000000 --- a/test/unit/bptree_stress_test.cc +++ /dev/null @@ -1,160 +0,0 @@ -/* - * Copyright (C) 2020-present ScyllaDB - */ - -/* - * SPDX-License-Identifier: AGPL-3.0-or-later - */ - -#include -#include -#include -#include - -constexpr int TEST_NODE_SIZE = 16; - -#include "tree_test_key.hh" -#include "utils/assert.hh" -#include "utils/bptree.hh" -#include "bptree_validation.hh" -#include "collection_stress.hh" - -using namespace bplus; -using namespace seastar; - -using test_key = tree_test_key_base; - -class test_data { - int _value; -public: - test_data() : _value(0) {} - test_data(test_key& k) : _value((int)k + 10) {} - - operator unsigned long() const { return _value; } - bool match_key(const test_key& k) const { return _value == (int)k + 10; } -}; - -template <> struct fmt::formatter : fmt::formatter { - auto format(test_data d, fmt::format_context& ctx) const { - return fmt::format_to(ctx.out(), "{}", static_cast(d)); - } -}; - -using test_tree = tree; -using test_node = typename test_tree::node; -using test_validator = validator; -using test_iterator_checker = iterator_checker; - -int main(int argc, char **argv) { - namespace bpo = boost::program_options; - app_template app; - app.add_options() - ("count", bpo::value()->default_value(4132), "number of keys to fill the tree with") - ("iters", bpo::value()->default_value(9), "number of iterations") - ("keys", bpo::value()->default_value("rand"), "how to generate keys (rand, asc, desc)") - ("verb", bpo::value()->default_value(false), "be verbose"); - - return app.run(argc, argv, [&app] { - auto count = app.configuration()["count"].as(); - auto iters = app.configuration()["iters"].as(); - auto ks = app.configuration()["keys"].as(); - auto verb = app.configuration()["verb"].as(); - - return seastar::async([count, iters, ks, verb] { - auto t = std::make_unique(test_key_compare{}); - std::map oracle; - test_validator tv; - auto* itc = new test_iterator_checker(tv, *t); - - stress_config cfg; - cfg.count = count; - cfg.iters = iters; - cfg.keys = ks; - cfg.verb = verb; - auto rep = 0, itv = 0; - - stress_collection(cfg, - /* insert */ [&] (int key) { - test_key k(key); - - if (rep % 2 != 1) { - auto ir = t->emplace(copy_key(k), k); - SCYLLA_ASSERT(ir.second); - } else { - auto ir = t->lower_bound(k); - ir.emplace_before(copy_key(k), test_key_compare{}, k); - } - oracle[key] = key + 10; - - if (itv++ % 7 == 0) { - if (!itc->step()) { - delete itc; - itc = new test_iterator_checker(tv, *t); - } - } - }, - /* erase */ [&] (int key) { - test_key k(key); - - if (itc->here(k)) { - delete itc; - itc = nullptr; - } - - if (rep % 3 != 2) { - t->erase(k); - } else { - auto ri = t->find(k); - auto ni = ri; - ni++; - auto eni = ri.erase(test_key_compare{}); - SCYLLA_ASSERT(ni == eni); - } - oracle.erase(key); - - if (itc == nullptr) { - itc = new test_iterator_checker(tv, *t); - } - - if (itv++ % 5 == 0) { - if (!itc->step()) { - delete itc; - itc = new test_iterator_checker(tv, *t); - } - } - }, - /* validate */ [&] { - if (verb) { - fmt::print("Validating\n"); - tv.print_tree(*t, '|'); - } - tv.validate(*t); - }, - /* step */ [&] (stress_step step) { - if (step == stress_step::iteration_finished) { - rep++; - } - - if (step == stress_step::before_erase) { - auto sz = t->size_slow(); - if (sz != (size_t)count) { - fmt::print("Size {} != count {}\n", sz, count); - throw "size"; - } - - auto ti = t->begin(); - for (auto oe : oracle) { - if ((unsigned long)*ti != oe.second) { - fmt::print("Data mismatch {} vs {}\n", oe.second, *ti); - throw "oracle"; - } - ti++; - } - } - } - ); - - delete itc; - }); - }); -}