From ccae5abce2c7a1aa3792f3225b32dc26d77322c6 Mon Sep 17 00:00:00 2001 From: Dnomd343 Date: Sat, 15 Jun 2024 12:03:05 +0800 Subject: [PATCH] test: perf test suites of Ranges --- src/core_test/CMakeLists.txt | 5 +- src/core_test/cases/helper/cases.h | 49 ++++++++++ src/core_test/cases/helper/impl.cc | 23 +++++ src/core_test/cases/ranges.cc | 150 +++++++++++++---------------- 4 files changed, 144 insertions(+), 83 deletions(-) create mode 100644 src/core_test/cases/helper/cases.h create mode 100644 src/core_test/cases/helper/impl.cc diff --git a/src/core_test/CMakeLists.txt b/src/core_test/CMakeLists.txt index f9b5d5e..0128044 100644 --- a/src/core_test/CMakeLists.txt +++ b/src/core_test/CMakeLists.txt @@ -20,10 +20,11 @@ include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../core/common_code) # ------------------------------------------------------------------------------------ # set(KLSK_TEST_CASES_SRC - cases/all_cases.cc + cases/ranges.cc cases/basic_ranges.cc + cases/all_cases.cc cases/group_union.cc - cases/ranges.cc + cases/helper/impl.cc ) add_executable(test_klotski_cases ${KLSK_TEST_CASES_SRC}) diff --git a/src/core_test/cases/helper/cases.h b/src/core_test/cases/helper/cases.h new file mode 100644 index 0000000..8708f2a --- /dev/null +++ b/src/core_test/cases/helper/cases.h @@ -0,0 +1,49 @@ +#pragma once + +#include +#include + +#include "group/group.h" +#include "all_cases/all_cases.h" + +using klotski::cases::Ranges; +using klotski::cases::AllCases; +using klotski::codec::CommonCode; +using klotski::cases::BasicRanges; +using klotski::cases::RangesUnion; + +using klotski::array_sum; +using klotski::range_reverse; + +using klotski::cases::BLOCK_NUM; +using klotski::cases::ALL_CASES_NUM; +using klotski::cases::ALL_CASES_NUM; +using klotski::cases::BASIC_RANGES_NUM; +using klotski::cases::BASIC_RANGES_NUM_; + +/// All valid klotski heads. +constexpr auto Heads = std::to_array({ + 0, 1, 2, 4, 5, 6, 8, 9, 10, 12, 13, 14 +}); + +/// Assert that Ranges are sorted and unique. +#define EXPECT_SORTED_AND_UNIQUE(R) \ + EXPECT_TRUE(std::ranges::is_sorted(R.begin(), R.end())); \ + EXPECT_EQ(std::ranges::adjacent_find(R.begin(), R.end()), R.end()) // no duplicates + +/// Assert that two ordered arrays are in a containment relationship. +#define EXPECT_SUBSET(R1, R2) \ + EXPECT_TRUE(std::ranges::includes(R1.begin(), R1.end(), R2.begin(), R2.end())) + +/// Assert that all CommonCodes generated from head and Ranges are valid. +#define EXPECT_COMMON_CODES(head, ranges) \ + for (const auto range : ranges) \ + EXPECT_TRUE(CommonCode::check(static_cast(head) << 32 | range)) + +struct block_num_t { + int n_1x1; + int n_1x2; + int n_2x1; +}; + +block_num_t get_block_num(uint32_t range); diff --git a/src/core_test/cases/helper/impl.cc b/src/core_test/cases/helper/impl.cc new file mode 100644 index 0000000..34582ae --- /dev/null +++ b/src/core_test/cases/helper/impl.cc @@ -0,0 +1,23 @@ +#include + +#include "cases.h" +#include "utils/utility.h" + +block_num_t get_block_num(uint32_t range) { + block_num_t result {}; + range = klotski::range_reverse(range); + for (; range; range >>= 2) { + switch (range & 0b11) { + case 0b01: // 1x2 block + ++result.n_1x2; + continue; + case 0b10: // 2x1 block + ++result.n_2x1; + continue; + case 0b11: // 1x1 block + ++result.n_1x1; + continue; + } + } + return result; +} diff --git a/src/core_test/cases/ranges.cc b/src/core_test/cases/ranges.cc index 9284613..df72229 100644 --- a/src/core_test/cases/ranges.cc +++ b/src/core_test/cases/ranges.cc @@ -1,120 +1,108 @@ #include +#include "group/group.h" +#include "helper/cases.h" #include "ranges/ranges.h" -#include -#include - -using klotski::cases::Ranges; - static_assert(std::is_base_of_v, Ranges>); -static_assert(std::is_base_of_v, klotski::cases::RangesUnion>); - -TEST(Ranges, demo) { - - for (int type_id = 0; type_id < klotski::cases::TYPE_ID_LIMIT; ++type_id) { - auto [n, n_2x1, n_1x1] = klotski::cases::BLOCK_NUM[type_id]; - - Ranges ranges; - ranges.spawn(n, n_2x1, n_1x1); - - EXPECT_TRUE(std::ranges::is_sorted(ranges.begin(), ranges.end())); - - const auto match = std::ranges::adjacent_find(ranges.begin(), ranges.end()); - - EXPECT_EQ(match, ranges.end()); - - } - -} - -TEST(Ranges, combine) { - - Ranges ranges; +static_assert(std::is_base_of_v, RangesUnion>); - for (int type_id = 0; type_id < klotski::cases::TYPE_ID_LIMIT; ++type_id) { - auto [n, n_2x1, n_1x1] = klotski::cases::BLOCK_NUM[type_id]; - - ranges.spawn(n, n_2x1, n_1x1); +TEST(Ranges, check) { + RangesUnion all_cases; + const auto ranges = BasicRanges::instance().fetch(); + for (const auto head : Heads) { + for (auto range : ranges) { + if (Ranges::check(head, range_reverse(range)) == 0) { + all_cases[head].emplace_back(range); // valid cases + } + } } - - std::ranges::stable_sort(ranges.begin(), ranges.end()); - - EXPECT_EQ(ranges, klotski::cases::BasicRanges::instance().fetch()); - + EXPECT_EQ(all_cases, AllCases::instance().fetch()); } -TEST(Ranges, reverse) { - - for (int type_id = 0; type_id < klotski::cases::TYPE_ID_LIMIT; ++type_id) { - auto [n, n_2x1, n_1x1] = klotski::cases::BLOCK_NUM[type_id]; - +TEST(Ranges, spawn) { + for (auto [n, n_2x1, n_1x1] : BLOCK_NUM) { Ranges ranges; ranges.spawn(n, n_2x1, n_1x1); + EXPECT_SORTED_AND_UNIQUE(ranges); - Ranges reverse {ranges}; - for (auto &x : reverse) { - x = klotski::range_reverse(x); + for (const auto range : ranges) { + const auto [val_1x1, val_1x2, val_2x1] = get_block_num(range); + EXPECT_EQ(val_1x1, n_1x1); + EXPECT_EQ(val_2x1, n_2x1); + EXPECT_EQ(val_1x2 + val_2x1, n); } - ranges.reverse(); - - EXPECT_EQ(ranges, reverse); - } - - } TEST(Ranges, derive) { - - for (int type_id = 0; type_id < klotski::cases::TYPE_ID_LIMIT; ++type_id) { - auto [n, n_2x1, n_1x1] = klotski::cases::BLOCK_NUM[type_id]; - + for (auto [n, n_2x1, n_1x1] : BLOCK_NUM) { Ranges ranges; ranges.spawn(n, n_2x1, n_1x1); - ranges.reverse(); - auto kk = klotski::cases::GroupUnion::unsafe_create(type_id); - - klotski::cases::RangesUnion result; - - for (int head = 0; head < 16; ++head) { - - if (head % 4 == 3) { - continue; - } + RangesUnion cases; + for (const auto head : Heads) { + ranges.derive(head, cases[head]); + EXPECT_SORTED_AND_UNIQUE(cases[head]); + EXPECT_COMMON_CODES(head, cases[head]); + } - ranges.derive(head, result[head]); + ranges.reverse(); + for (const auto head : Heads) { + EXPECT_SUBSET(ranges, cases[head]); // subset verify } + } +} - EXPECT_EQ(result, kk.cases()); +TEST(Ranges, reverse) { + auto ranges = BasicRanges::instance().fetch(); + Ranges reverse {ranges}; + for (auto &x : reverse) { + x = range_reverse(x); // manual reverse } + ranges.reverse(); + EXPECT_EQ(ranges, reverse); - + ranges.reverse(); + EXPECT_EQ(ranges, BasicRanges::instance().fetch()); } -TEST(Ranges, check) { - auto ranges = klotski::cases::BasicRanges::instance().fetch(); - - klotski::cases::RangesUnion all_cases; +TEST(Ranges, combine) { + Ranges all_ranges; + RangesUnion all_cases; - for (int head = 0; head < 16; ++head) { - if (head % 4 == 3) { - continue; - } + all_ranges.reserve(BASIC_RANGES_NUM_); // pre reserve + for (const auto head : Heads) { + all_cases[head].reserve(ALL_CASES_NUM[head]); // pre reserve + } - for (auto range : ranges) { - if (Ranges::check(head, klotski::range_reverse(range)) == 0) { - all_cases[head].emplace_back(range); - } + for (auto [n, n_2x1, n_1x1] : BLOCK_NUM) { + Ranges ranges; + ranges.spawn(n, n_2x1, n_1x1); + // TODO: add += interface + all_ranges.insert(all_ranges.end(), ranges.begin(), ranges.end()); + ranges.reverse(); + for (const auto head : Heads) { + ranges.derive(head, all_cases[head]); // derive from sub ranges } } - EXPECT_EQ(klotski::cases::AllCases::instance().fetch(), all_cases); + std::ranges::stable_sort(all_ranges.begin(), all_ranges.end()); + for (const auto head : Heads) { + std::ranges::stable_sort(all_cases[head].begin(), all_cases[head].end()); + } + EXPECT_EQ(all_ranges, BasicRanges::instance().fetch()); // verify content + EXPECT_EQ(all_cases, AllCases::instance().fetch()); // verify content + all_ranges.reverse(); + for (const auto head : Heads) { + all_cases[head].clear(); + all_ranges.derive(head, all_cases[head]); // derive from all ranges + } + EXPECT_EQ(all_cases, AllCases::instance().fetch()); // verify content } // TODO: export CommonCode