Browse Source

test: enhance test suites of ranges

legacy
Dnomd343 1 month ago
parent
commit
af47e6a5c5
  1. 6
      src/core/ranges/ranges.h
  2. 73
      src/core_test/cases/ranges.cc
  3. 22
      src/core_test/helper/internal/parallel.cc
  4. 12
      src/core_test/helper/parallel.h

6
src/core/ranges/ranges.h

@ -90,12 +90,16 @@ public:
// ------------------------------------------------------------------------------------- //
private:
static constexpr auto Heads = std::to_array<uint64_t>({
0x0, 0x1, 0x2, 0x4, 0x5, 0x6, 0x8, 0x9, 0xA, 0xC, 0xD, 0xE
});
// ------------------------------------------------------------------------------------- //
};
static_assert(sizeof(Ranges) == sizeof(std::vector<uint32_t>));
static_assert(sizeof(Ranges) * 16 == sizeof(RangesUnion));
} // namespace klotski::cases
#include "internal/ranges.inl"

73
src/core_test/cases/ranges.cc

@ -1,51 +1,64 @@
#include <gtest/gtest.h>
#include "helper/cases.h"
#include "group/group.h"
#include "ranges/ranges.h"
#include "helper/expect.h"
#include "helper/parallel.h"
#include "helper/block_num.h"
#include "group/group.h"
#include "ranges/ranges.h"
using klotski::cases::Ranges;
using klotski::cases::AllCases;
using klotski::codec::CommonCode;
using klotski::cases::BasicRanges;
using klotski::cases::RangesUnion;
using klotski::range_reverse;
using klotski::group::BLOCK_NUM;
using klotski::cases::ALL_CASES_NUM;
using klotski::cases::BASIC_RANGES_NUM_;
constexpr auto Heads = RangesUnion::Heads;
static_assert(std::is_base_of_v<std::vector<uint32_t>, Ranges>);
TEST(Ranges, check) {
RangesUnion all_cases;
for (const auto head : Heads) {
for (auto range : BasicRanges::instance().fetch()) {
if (Ranges::check(head, range_reverse(range)) == 0) {
all_cases.ranges(head).emplace_back(range); // found valid cases
HEAD_PARALLEL({
Ranges cases;
cases.reserve(ALL_CASES_NUM[head]);
for (const auto range : BasicRanges::instance().fetch()) {
if (Ranges::check(static_cast<int>(head), range_reverse(range)) == 0) {
cases.emplace_back(range); // found valid cases
}
}
}
EXPECT_EQ(all_cases, AllCases::instance().fetch());
EXPECT_EQ(cases, AllCases::instance().fetch().ranges(head));
});
}
TEST(Ranges, spawn) {
for (auto [n, n_2x1, n_1x1] : BLOCK_NUM) {
BLOCK_NUM_PARALLEL({
Ranges ranges;
ranges.spawn(n, n_2x1, n_1x1);
EXPECT_SORTED_AND_UNIQUE(ranges); // sorted and unique
for (const auto range : ranges) {
const auto [val_1x1, val_1x2, val_2x1] = helper::cal_block_num(range);
EXPECT_EQ(val_1x1, n_1x1);
EXPECT_EQ(val_2x1, n_2x1);
EXPECT_EQ(val_1x2 + val_2x1, n); // verify block nums
}
const auto val = helper::cal_block_num(range);
EXPECT_EQ(n_1x1, val.n_1x1);
EXPECT_EQ(n_2x1, val.n_2x1);
EXPECT_EQ(n, val.n_1x2 + val.n_2x1); // verify block nums
}
});
}
TEST(Ranges, derive) {
for (auto [n, n_2x1, n_1x1] : BLOCK_NUM) {
BLOCK_NUM_PARALLEL({
Ranges ranges;
ranges.spawn(n, n_2x1, n_1x1);
ranges.reverse(); // reverse ranges for derive
RangesUnion cases;
for (const auto head : Heads) {
ranges.derive(head, cases.ranges(head));
ranges.derive(static_cast<int>(head), cases.ranges(head));
EXPECT_SORTED_AND_UNIQUE(cases.ranges(head)); // sorted and unique
EXPECT_COMMON_CODES(head, cases.ranges(head)); // verify common codes
}
@ -54,7 +67,7 @@ TEST(Ranges, derive) {
for (const auto head : Heads) {
EXPECT_SUBSET(ranges, cases.ranges(head)); // derive ranges is subset
}
}
});
}
TEST(Ranges, append) {
@ -65,13 +78,15 @@ TEST(Ranges, append) {
auto &tmp = ranges += r;
EXPECT_EQ(tmp, ranges); // reference of ranges
}
std::stable_sort(ranges.begin(), ranges.end());
std::ranges::stable_sort(ranges.begin(), ranges.end());
EXPECT_EQ(ranges, BasicRanges::instance().fetch());
}
TEST(Ranges, reverse) {
auto ranges = BasicRanges::instance().fetch();
auto reverse = ranges | std::views::transform(range_reverse) | std::ranges::to<std::vector>();
const auto reverse = ranges
| std::views::transform(range_reverse)
| std::ranges::to<std::vector>();
ranges.reverse();
EXPECT_EQ(ranges, reverse);
ranges.reverse();
@ -91,8 +106,8 @@ TEST(Ranges, combine) {
ranges.spawn(n, n_2x1, n_1x1);
all_ranges += ranges;
ranges.reverse(); // reverse ranges for derive
for (const auto head : Heads) {
ranges.derive(head, all_cases.ranges(head)); // derive from sub ranges
for (const auto head : Heads) { // derive from sub ranges
ranges.derive(static_cast<int>(head), all_cases.ranges(head));
}
}
@ -104,9 +119,17 @@ TEST(Ranges, combine) {
EXPECT_EQ(all_cases, AllCases::instance().fetch()); // verify all cases
all_ranges.reverse(); // reverse ranges for derive
for (const auto head : Heads) {
for (const auto head : Heads) { // derive from all ranges
all_cases.ranges(head).clear();
all_ranges.derive(head, all_cases.ranges(head)); // derive from all ranges
all_ranges.derive(static_cast<int>(head), all_cases.ranges(head));
}
EXPECT_EQ(all_cases, AllCases::instance().fetch()); // verify content
}
TEST(Ranges, constexpr) {
static_assert(Ranges::check(1, 0x0030FE6A) == 0);
static_assert(Ranges::check(4, 0x001C4ABF) == 0);
static_assert(Ranges::check(1, 0xA9BF0C00) == 14);
static_assert(Ranges::check(4, 0xFEA13400) == 6);
}

22
src/core_test/helper/internal/parallel.cc

@ -9,6 +9,28 @@ using klotski::cases::AllCases;
using klotski::group::TYPE_ID_LIMIT;
using klotski::cases::ALL_CASES_NUM_;
using klotski::cases::RangesUnion;
void helper::head_parallel(std::function<void(uint64_t head)> &&func) {
BS::thread_pool pool;
for (auto head : RangesUnion::Heads) {
pool.detach_task([head, &func] {
func(head);
});
}
pool.wait();
}
void helper::block_num_parallel(std::function<void(int n, int n_2x1, int n_1x1)> &&func) {
BS::thread_pool pool;
for (auto [n, n_2x1, n_1x1] : klotski::group::BLOCK_NUM) {
pool.detach_task([n, n_2x1, n_1x1, &func] {
func(n, n_2x1, n_1x1);
});
}
pool.wait();
}
void helper::group_parallel(std::function<void(Group)> &&func) {
// TODO: spawn all Groups
}

12
src/core_test/helper/parallel.h

@ -20,6 +20,18 @@ namespace helper {
// ----------------------------------------------------------------------------------------- //
void head_parallel(std::function<void(uint64_t head)> &&func);
void block_num_parallel(std::function<void(int n, int n_2x1, int n_1x1)> &&func);
#define HEAD_PARALLEL(impl) \
::helper::head_parallel([](uint64_t head) {impl})
#define BLOCK_NUM_PARALLEL(impl) \
::helper::block_num_parallel([](int n, int n_2x1, int n_1x1) {impl})
// ----------------------------------------------------------------------------------------- //
/// Spawn all valid Groups in parallel.
void group_parallel(std::function<void(Group group)> &&func);

Loading…
Cancel
Save