Files
scylladb/test/boost/dynamic_bitset_test.cc
Kefu Chai f9091066b7 treewide: replace boost::irange with std::views::iota where possible
when building scylla with the standard library from GCC-14.2, shipped by
fedora 41, we have following build failure:

```
/home/kefu/.local/bin/clang++ -DDEBUG -DDEBUG_LSA_SANITIZER -DFMT_SHARED -DSANITIZE -DSCYLLA_BUILD_MODE=debug -DSCYLLA_ENABLE_ERROR_INJECTION -DSEASTAR_API_LEVEL=7 -DSEASTAR_DEBUG -DSEASTAR_DEBUG_PROMISE -DSEASTAR_DEBUG_SHARED_PTR -DSEASTAR_DEFAULT_ALLOCATOR -DSEASTAR_LOGGER_COMPILE_TIME_FMT -DSEASTAR_LOGGER_TYPE_STDOUT -DSEASTAR_SCHEDULING_GROUPS_COUNT=16 -DSEASTAR_SHUFFLE_TASK_QUEUE -DSEASTAR_SSTRING -DSEASTAR_TYPE_ERASE_MORE -DXXH_PRIVATE_API -DCMAKE_INTDIR=\"Debug\" -I/home/kefu/dev/scylladb -I/home/kefu/dev/scylladb/build/gen -I/home/kefu/dev/scylladb/seastar/include -I/home/kefu/dev/scylladb/build/seastar/gen/include -I/home/kefu/dev/scylladb/build/seastar/gen/src -isystem /home/kefu/dev/scylladb/abseil -g -Og -g -gz -std=gnu++23 -fvisibility=hidden -Wall -Werror -Wextra -Wno-error=deprecated-declarations -Wimplicit-fallthrough -Wno-c++11-narrowing -Wno-deprecated-copy -Wno-mismatched-tags -Wno-missing-field-initializers -Wno-overloaded-virtual -Wno-unsupported-friend -Wno-unused-parameter -ffile-prefix-map=/home/kefu/dev/scylladb/build=. -march=x86-64-v3 -mpclmul -Xclang -fexperimental-assignment-tracking=disabled -Werror=unused-result -fstack-clash-protection -fsanitize=address -fsanitize=undefined -MD -MT CMakeFiles/scylla-main.dir/Debug/init.cc.o -MF CMakeFiles/scylla-main.dir/Debug/init.cc.o.d -o CMakeFiles/scylla-main.dir/Debug/init.cc.o -c /home/kefu/dev/scylladb/init.cc
In file included from /home/kefu/dev/scylladb/init.cc:12:
In file included from /home/kefu/dev/scylladb/db/config.hh:20:
In file included from /home/kefu/dev/scylladb/locator/abstract_replication_strategy.hh:26:
/home/kefu/dev/scylladb/locator/tablets.hh:410:30: error: unexpected type name 'size_t': expected expression
  410 |         return boost::irange<size_t>(0, tablet_count()) | boost::adaptors::transformed([] (size_t i) {
      |                              ^
/home/kefu/dev/scylladb/locator/tablets.hh:410:23: error: no member named 'irange' in namespace 'boost'
  410 |         return boost::irange<size_t>(0, tablet_count()) | boost::adaptors::transformed([] (size_t i) {
      |                ~~~~~~~^
/home/kefu/dev/scylladb/locator/tablets.hh:410:38: error: left operand of comma operator has no effect [-Werror,-Wunused-value]
  410 |         return boost::irange<size_t>(0, tablet_count()) | boost::adaptors::transformed([] (size_t i) {
      |                                      ^
3 errors generated.
[16/782] Building CXX object CMakeFiles/scylla-main.dir/Debug/keys.cc.o
[17/782] Building CXX object CMakeFiles/scylla-main.dir/Debug/counters.cc.o
[18/782] Building CXX object CMakeFiles/scylla-main.dir/Debug/partition_slice_builder.cc.o
[19/782] Building CXX object CMakeFiles/scylla-main.dir/Debug/mutation_query.cc.o
FAILED: CMakeFiles/scylla-main.dir/Debug/mutation_query.cc.o
/home/kefu/.local/bin/clang++ -DDEBUG -DDEBUG_LSA_SANITIZER -DFMT_SHARED -DSANITIZE -DSCYLLA_BUILD_MODE=debug -DSCYLLA_ENABLE_ERROR_INJECTION -DSEASTAR_API_LEVEL=7 -DSEASTAR_DEBUG -DSEASTAR_DEBUG_PROMISE -DSEASTAR_DEBUG_SHARED_PTR -DSEASTAR_DEFAULT_ALLOCATOR -DSEASTAR_LOGGER_COMPILE_TIME_FMT -DSEASTAR_LOGGER_TYPE_STDOUT -DSEASTAR_SCHEDULING_GROUPS_COUNT=16 -DSEASTAR_SHUFFLE_TASK_QUEUE -DSEASTAR_SSTRING -DSEASTAR_TYPE_ERASE_MORE -DXXH_PRIVATE_API -DCMAKE_INTDIR=\"Debug\" -I/home/kefu/dev/scylladb -I/home/kefu/dev/scylladb/build/gen -I/home/kefu/dev/scylladb/seastar/include -I/home/kefu/dev/scylladb/build/seastar/gen/include -I/home/kefu/dev/scylladb/build/seastar/gen/src -isystem /home/kefu/dev/scylladb/abseil -g -Og -g -gz -std=gnu++23 -fvisibility=hidden -Wall -Werror -Wextra -Wno-error=deprecated-declarations -Wimplicit-fallthrough -Wno-c++11-narrowing -Wno-deprecated-copy -Wno-mismatched-tags -Wno-missing-field-initializers -Wno-overloaded-virtual -Wno-unsupported-friend -Wno-unused-parameter -ffile-prefix-map=/home/kefu/dev/scylladb/build=. -march=x86-64-v3 -mpclmul -Xclang -fexperimental-assignment-tracking=disabled -Werror=unused-result -fstack-clash-protection -fsanitize=address -fsanitize=undefined -MD -MT CMakeFiles/scylla-main.dir/Debug/mutation_query.cc.o -MF CMakeFiles/scylla-main.dir/Debug/mutation_query.cc.o.d -o CMakeFiles/scylla-main.dir/Debug/mutation_query.cc.o -c /home/kefu/dev/scylladb/mutation_query.cc
In file included from /home/kefu/dev/scylladb/mutation_query.cc:12:
In file included from /home/kefu/dev/scylladb/schema/schema_registry.hh:17:
In file included from /home/kefu/dev/scylladb/replica/database.hh:11:
In file included from /home/kefu/dev/scylladb/locator/abstract_replication_strategy.hh:26:
/home/kefu/dev/scylladb/locator/tablets.hh:410:30: error: unexpected type name 'size_t': expected expression
  410 |         return boost::irange<size_t>(0, tablet_count()) | boost::adaptors::transformed([] (size_t i) {
      |                              ^
/home/kefu/dev/scylladb/locator/tablets.hh:410:23: error: no member named 'irange' in namespace 'boost'
  410 |         return boost::irange<size_t>(0, tablet_count()) | boost::adaptors::transformed([] (size_t i) {
      |                ~~~~~~~^
/home/kefu/dev/scylladb/locator/tablets.hh:410:38: error: left operand of comma operator has no effect [-Werror,-Wunused-value]
  410 |         return boost::irange<size_t>(0, tablet_count()) | boost::adaptors::transformed([] (size_t i) {
      |                                      ^
In file included from /home/kefu/dev/scylladb/mutation_query.cc:12:
In file included from /home/kefu/dev/scylladb/schema/schema_registry.hh:17:
In file included from /home/kefu/dev/scylladb/replica/database.hh:37:
In file included from /home/kefu/dev/scylladb/db/snapshot-ctl.hh:20:
/home/kefu/dev/scylladb/tasks/task_manager.hh:403:54: error: no member named 'irange' in namespace 'boost'
  403 |         co_await coroutine::parallel_for_each(boost::irange(0u, smp::count), [&tm, id, &res, &func] (unsigned shard) -> future<> {
      |                                               ~~~~~~~^
4 errors generated.
```

so let's take the opportunity to switch from `boost::irange` to
`std::views::iota`.

in this change, we:

- switch from boost::irange to std::views::iota for better standard library compatibility
- retain boost::irange where step parameter is used, as std::views::iota doesn't support it
- this change partially modernizes our range usage while maintaining
- existing functionality

Signed-off-by: Kefu Chai <kefu.chai@scylladb.com>

Closes scylladb/scylladb#20924
2024-10-03 10:33:33 +03:00

211 lines
5.9 KiB
C++

/*
* Copyright 2015-present ScyllaDB
*/
/*
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
#define BOOST_TEST_MODULE core
#include <boost/test/unit_test.hpp>
#include <boost/algorithm/cxx11/any_of.hpp>
#include <boost/range/irange.hpp>
#include <vector>
#include <random>
#include <ranges>
#include "utils/dynamic_bitset.hh"
BOOST_AUTO_TEST_CASE(test_set_clear_test) {
utils::dynamic_bitset bits(178);
for (size_t i = 0; i < 178; i++) {
BOOST_REQUIRE(!bits.test(i));
}
for (size_t i = 0; i < 178; i += 2) {
bits.set(i);
}
for (size_t i = 0; i < 178; i++) {
if (i % 2) {
BOOST_REQUIRE(!bits.test(i));
} else {
BOOST_REQUIRE(bits.test(i));
}
}
for (size_t i = 0; i < 178; i += 4) {
bits.clear(i);
}
for (size_t i = 0; i < 178; i++) {
if (i % 2 || i % 4 == 0) {
BOOST_REQUIRE(!bits.test(i));
} else {
BOOST_REQUIRE(bits.test(i));
}
}
}
BOOST_AUTO_TEST_CASE(test_find_first_next) {
utils::dynamic_bitset bits(178);
for (size_t i = 0; i < 178; i++) {
BOOST_REQUIRE(!bits.test(i));
}
BOOST_REQUIRE_EQUAL(bits.find_first_set(), utils::dynamic_bitset::npos);
for (size_t i = 0; i < 178; i += 2) {
bits.set(i);
}
size_t i = bits.find_first_set();
BOOST_REQUIRE_EQUAL(i, 0);
do {
auto j = bits.find_next_set(i);
BOOST_REQUIRE_EQUAL(i + 2, j);
i = j;
} while (i < 176);
BOOST_REQUIRE_EQUAL(bits.find_next_set(i), utils::dynamic_bitset::npos);
for (size_t i = 0; i < 178; i += 4) {
bits.clear(i);
}
i = bits.find_first_set();
BOOST_REQUIRE_EQUAL(i, 2);
do {
auto j = bits.find_next_set(i);
BOOST_REQUIRE_EQUAL(i + 4, j);
i = j;
} while (i < 174);
BOOST_REQUIRE_EQUAL(bits.find_next_set(i), utils::dynamic_bitset::npos);
}
BOOST_AUTO_TEST_CASE(test_find_last_prev) {
utils::dynamic_bitset bits(178);
for (size_t i = 0; i < 178; i++) {
BOOST_REQUIRE(!bits.test(i));
}
BOOST_REQUIRE_EQUAL(bits.find_last_set(), utils::dynamic_bitset::npos);
for (size_t i = 0; i < 178; i += 2) {
bits.set(i);
}
size_t i = bits.find_last_set();
BOOST_REQUIRE_EQUAL(i, 176);
for (size_t i = 0; i < 178; i += 4) {
bits.clear(i);
}
i = bits.find_last_set();
BOOST_REQUIRE_EQUAL(i, 174);
}
static void test_random_ops(size_t size, std::default_random_engine& re ) {
// BOOST_REQUIRE and friends are very slow, just use regular throws instead.
auto require = [] (bool b) {
if (!b) {
throw 0;
}
};
auto require_equal = [&] (const auto& a, const auto& b) {
require(a == b);
};
utils::dynamic_bitset db{size};
std::vector<bool> bv(size, false);
std::uniform_int_distribution<size_t> global_op_dist(0, size-1);
std::uniform_int_distribution<size_t> bit_dist(0, size-1);
std::uniform_int_distribution<int> global_op_selection_dist(0, 1);
std::uniform_int_distribution<int> single_op_selection_dist(0, 5);
auto is_set = [&] (size_t i) -> bool {
return bv[i];
};
size_t limit = std::log(size) * 1000;
for (size_t i = 0; i != limit; ++i) {
if (global_op_dist(re) == 0) {
// perform a global operation
switch (global_op_selection_dist(re)) {
case 0:
for (size_t j = 0; j != size; ++j) {
db.clear(j);
bv[j] = false;
}
break;
case 1:
for (size_t j = 0; j != size; ++j) {
db.set(j);
bv[j] = true;
}
break;
}
} else {
// perform a single-bit operation
switch (single_op_selection_dist(re)) {
case 0: {
auto bit = bit_dist(re);
db.set(bit);
bv[bit] = true;
break;
}
case 1: {
auto bit = bit_dist(re);
db.clear(bit);
bv[bit] = false;
break;
}
case 2: {
auto bit = bit_dist(re);
bool dbb = db.test(bit);
bool bvb = bv[bit];
require_equal(dbb, bvb);
break;
}
case 3: {
auto bit = bit_dist(re);
auto next = db.find_next_set(bit);
if (next == db.npos) {
require(!std::ranges::any_of(std::views::iota(bit+1, size), is_set));
} else {
require(!std::ranges::any_of(std::views::iota(bit+1, next), is_set));
require(is_set(next));
}
break; }
case 4: {
auto next = db.find_first_set();
if (next == db.npos) {
require(!std::ranges::any_of(std::views::iota(0u, size), is_set));
} else {
require(!std::ranges::any_of(std::views::iota(0u, next), is_set));
require(is_set(next));
}
break;
}
case 5: {
auto next = db.find_last_set();
if (next == db.npos) {
require(!std::ranges::any_of(std::views::iota(0u, size), is_set));
} else {
require(!std::ranges::any_of(std::views::iota(next + 1, size), is_set));
require(is_set(next));
}
break;
}
}
}
}
}
BOOST_AUTO_TEST_CASE(test_random_operations) {
std::random_device rd;
std::default_random_engine re(rd());
for (auto size : { 1, 63, 64, 65, 2000, 4096-65, 4096-64, 4096-63, 4096-1, 4096, 4096+1, 262144-1, 262144, 262144+1}) {
BOOST_CHECK_NO_THROW(test_random_ops(size, re));
}
}