From 2dbca4b898fcd5e25b53692379d4d1936fe4986e Mon Sep 17 00:00:00 2001 From: Dnomd343 Date: Thu, 5 Oct 2023 18:31:51 +0800 Subject: [PATCH] test: add RawCode test suite --- src/core/raw_code/sundry.cc | 2 +- src/core_test/CMakeLists.txt | 2 + src/core_test/cases/all_cases.cc | 16 ++-- src/core_test/codec/common_code.cc | 10 +-- src/core_test/codec/mirror.cc | 99 +++++++++++++++++++++ src/core_test/codec/raw_code.cc | 137 +++++++++++++++++++++++++++++ src/core_test/codec/sample.h | 17 ++++ src/core_test/codec/short_code.cc | 15 +--- 8 files changed, 269 insertions(+), 29 deletions(-) create mode 100644 src/core_test/codec/mirror.cc create mode 100644 src/core_test/codec/raw_code.cc diff --git a/src/core/raw_code/sundry.cc b/src/core/raw_code/sundry.cc index 224cedf..ddabc76 100644 --- a/src/core/raw_code/sundry.cc +++ b/src/core/raw_code/sundry.cc @@ -29,7 +29,7 @@ std::optional RawCode::from_common_code(uint64_t common_code) noexcept } std::optional RawCode::from_common_code(std::string &&common_code) noexcept { - return CommonCode::from_short_code(std::move(common_code)).transform([](auto common_code) { + return CommonCode::from_string(std::move(common_code)).transform([](auto common_code) { return common_code.to_raw_code(); }); } diff --git a/src/core_test/CMakeLists.txt b/src/core_test/CMakeLists.txt index 8188cf2..2cd3943 100644 --- a/src/core_test/CMakeLists.txt +++ b/src/core_test/CMakeLists.txt @@ -39,6 +39,8 @@ add_test(NAME klotski_ffi COMMAND test_klotski_ffi) ############################################################################################### set(KLOTSKI_TEST_CODEC_SRC + codec/mirror.cc + codec/raw_code.cc codec/short_code.cc codec/common_code.cc ) diff --git a/src/core_test/cases/all_cases.cc b/src/core_test/cases/all_cases.cc index 16fec11..0a3a829 100644 --- a/src/core_test/cases/all_cases.cc +++ b/src/core_test/cases/all_cases.cc @@ -62,7 +62,7 @@ void all_cases_verify() { EXPECT_EQ(xxhsum(all_cases_xxh), ALL_CASES_XXHASH); // verify all cases checksum } -TEST(Cases, basic_ranges) { +TEST(AllCases, basic_ranges) { basic_ranges_reset(); EXPECT_FALSE(BasicRanges::instance().is_available()); BasicRanges::instance().build(); @@ -72,7 +72,7 @@ TEST(Cases, basic_ranges) { basic_ranges_verify(); } -TEST(Cases, basic_ranges_mutex) { +TEST(AllCases, basic_ranges_mutex) { basic_ranges_reset(); BS::thread_pool pool(TEST_THREAD_NUM); @@ -85,7 +85,7 @@ TEST(Cases, basic_ranges_mutex) { basic_ranges_verify(); } -TEST(Cases, all_cases) { +TEST(AllCases, all_cases) { all_cases_reset(); EXPECT_FALSE(AllCases::instance().is_available()); AllCases::instance().build(); @@ -95,7 +95,7 @@ TEST(Cases, all_cases) { all_cases_verify(); } -TEST(Cases, all_cases_mutex) { +TEST(AllCases, all_cases_mutex) { all_cases_reset(); BS::thread_pool pool(TEST_THREAD_NUM); @@ -108,7 +108,7 @@ TEST(Cases, all_cases_mutex) { all_cases_verify(); } -TEST(Cases, all_cases_parallel) { +TEST(AllCases, all_cases_parallel) { all_cases_reset(); BS::thread_pool executor; EXPECT_FALSE(AllCases::instance().is_available()); @@ -123,7 +123,7 @@ TEST(Cases, all_cases_parallel) { all_cases_verify(); } -TEST(Cases, all_cases_parallel_mutex) { +TEST(AllCases, all_cases_parallel_mutex) { all_cases_reset(); BS::thread_pool executor; BS::thread_pool pool(TEST_THREAD_NUM); @@ -140,7 +140,7 @@ TEST(Cases, all_cases_parallel_mutex) { all_cases_verify(); } -TEST(Cases, all_cases_async) { +TEST(AllCases, all_cases_async) { all_cases_reset(); std::atomic_flag flag; BS::thread_pool executor; @@ -169,7 +169,7 @@ TEST(Cases, all_cases_async) { all_cases_verify(); } -TEST(Cases, all_cases_async_mutex) { +TEST(AllCases, all_cases_async_mutex) { all_cases_reset(); BS::thread_pool executor; std::atomic callback_num(0); diff --git a/src/core_test/codec/common_code.cc b/src/core_test/codec/common_code.cc index d5cb8fe..4ced993 100644 --- a/src/core_test/codec/common_code.cc +++ b/src/core_test/codec/common_code.cc @@ -167,14 +167,6 @@ TEST(CommonCode, code_string) { } TEST(CommonCode, DISABLED_global_verify) { - std::vector common_codes; - common_codes.reserve(ALL_CASES_NUM_); - for (uint64_t head = 0; head < 16; ++head) { - for (auto range : AllCases::instance().fetch()[head]) { - common_codes.emplace_back(head << 32 | range); - } - } - BS::thread_pool pool; auto futures = pool.parallelize_loop(0x10'0000'0000, [](uint64_t start, uint64_t end) { std::vector archive; @@ -193,5 +185,5 @@ TEST(CommonCode, DISABLED_global_verify) { result.insert(result.end(), data.begin(), data.end()); // combine sections } pool.wait_for_tasks(); - EXPECT_EQ(result, common_codes); + EXPECT_EQ(result, all_common_codes()); } diff --git a/src/core_test/codec/mirror.cc b/src/core_test/codec/mirror.cc new file mode 100644 index 0000000..ad0e7ea --- /dev/null +++ b/src/core_test/codec/mirror.cc @@ -0,0 +1,99 @@ +#include "raw_code.h" +#include "all_cases.h" +#include "common_code.h" +#include "gtest/gtest.h" +#include "BS_thread_pool.hpp" + +using klotski::codec::RawCode; +using klotski::cases::AllCases; + +TEST(RawCode, vertical_mirror) { + auto raw_code_a = RawCode::unsafe_create(0x0'FC0'480'6DB'FC0'480); // invalid case for test + auto raw_code_b1 = RawCode::from_common_code(0x4FEA13400).value(); + auto raw_code_b2 = RawCode::from_common_code(0x8346AFC00).value(); + + EXPECT_TRUE(raw_code_a.is_vertical_mirror()); + EXPECT_TRUE(raw_code_a.is_vertical_mirror(raw_code_a)); + EXPECT_EQ(raw_code_a.to_vertical_mirror(), raw_code_a); + + EXPECT_FALSE(raw_code_b1.is_vertical_mirror()); + EXPECT_FALSE(raw_code_b2.is_vertical_mirror()); + EXPECT_TRUE(raw_code_b1.is_vertical_mirror(raw_code_b2)); + EXPECT_TRUE(raw_code_b2.is_vertical_mirror(raw_code_b1)); + EXPECT_EQ(raw_code_b1.to_vertical_mirror(), raw_code_b2); + EXPECT_EQ(raw_code_b2.to_vertical_mirror(), raw_code_b1); + + EXPECT_FALSE(raw_code_a.is_vertical_mirror(raw_code_b1)); + EXPECT_FALSE(raw_code_a.is_vertical_mirror(raw_code_b2)); + EXPECT_FALSE(raw_code_b1.is_vertical_mirror(raw_code_a)); + EXPECT_FALSE(raw_code_b2.is_vertical_mirror(raw_code_a)); +} + +TEST(RawCode, horizontal_mirror) { + auto raw_code_a = RawCode::from_common_code(0x1A9BF0C00).value(); + auto raw_code_b1 = RawCode::from_common_code(0x4FEA13400).value(); + auto raw_code_b2 = RawCode::from_common_code(0x6BFA47000).value(); + + EXPECT_TRUE(raw_code_a.is_horizontal_mirror()); + EXPECT_TRUE(raw_code_a.is_horizontal_mirror(raw_code_a)); + EXPECT_EQ(raw_code_a.to_horizontal_mirror(), raw_code_a); + + EXPECT_FALSE(raw_code_b1.is_horizontal_mirror()); + EXPECT_FALSE(raw_code_b2.is_horizontal_mirror()); + EXPECT_TRUE(raw_code_b1.is_horizontal_mirror(raw_code_b2)); + EXPECT_TRUE(raw_code_b2.is_horizontal_mirror(raw_code_b1)); + EXPECT_EQ(raw_code_b1.to_horizontal_mirror(), raw_code_b2); + EXPECT_EQ(raw_code_b2.to_horizontal_mirror(), raw_code_b1); + + EXPECT_FALSE(raw_code_a.is_horizontal_mirror(raw_code_b1)); + EXPECT_FALSE(raw_code_a.is_horizontal_mirror(raw_code_b2)); + EXPECT_FALSE(raw_code_b1.is_horizontal_mirror(raw_code_a)); + EXPECT_FALSE(raw_code_b2.is_horizontal_mirror(raw_code_a)); +} + +TEST(RawCode, code_vertical_mirror) { + auto test_func = [](RawCode code) { + auto mirror = code.to_vertical_mirror(); + EXPECT_TRUE(RawCode::check(mirror.unwrap())); + EXPECT_EQ(mirror.to_common_code().to_raw_code(), mirror); + EXPECT_EQ(mirror.to_vertical_mirror(), code); + EXPECT_FALSE(mirror.is_vertical_mirror()); + EXPECT_NE(code, mirror); + }; + + BS::thread_pool pool; + for (int head = 0; head < 16; ++head) { + pool.push_task([&test_func](uint64_t head) { + for (auto range : AllCases::instance().fetch()[head]) { + test_func(RawCode::from_common_code(head << 32 | range).value()); + } + }, head); + } + pool.wait_for_tasks(); +} + +TEST(RawCode, code_horizontal_mirror) { + auto test_func = [](RawCode code) { + auto mirror = code.to_horizontal_mirror(); + EXPECT_TRUE(RawCode::check(mirror.unwrap())); + EXPECT_EQ(mirror.to_common_code().to_raw_code(), mirror); + EXPECT_EQ(mirror.to_horizontal_mirror(), code); + if (mirror.is_horizontal_mirror()) { + EXPECT_EQ(code, mirror); + } else { + EXPECT_NE(code, mirror); + } + }; + + BS::thread_pool pool; + for (int head = 0; head < 16; ++head) { + pool.push_task([&test_func](uint64_t head) { + for (auto range : AllCases::instance().fetch()[head]) { + + test_func(RawCode::from_common_code(head << 32 | range).value()); + + } + }, head); + } + pool.wait_for_tasks(); +} diff --git a/src/core_test/codec/raw_code.cc b/src/core_test/codec/raw_code.cc new file mode 100644 index 0000000..b2fe733 --- /dev/null +++ b/src/core_test/codec/raw_code.cc @@ -0,0 +1,137 @@ +#include "common.h" +#include "sample.h" +#include "raw_code.h" +#include "all_cases.h" +#include "common_code.h" +#include "gtest/gtest.h" +#include "BS_thread_pool.hpp" + +using klotski::range_reverse; + +using klotski::codec::RawCode; +using klotski::codec::CommonCode; + +using klotski::cases::AllCases; +using klotski::cases::ALL_CASES_NUM_; + +TEST(RawCode, validity) { + EXPECT_FALSE(RawCode::check(0x0A34'182B'3810'2D21)); // invalid code + EXPECT_FALSE(RawCode::check(0x8603'EDF5'CAFF'F5E2)); // high 4-bits not zero + + EXPECT_FALSE(RawCode::create(0x0000'0000'0000'0000).has_value()); // invalid code +} + +TEST(RawCode, operators) { + auto raw_code = RawCode::unsafe_create(TEST_R_CODE); + + std::ostringstream tmp; + tmp << raw_code; // ostream capture + EXPECT_TRUE(tmp.str().starts_with("603EDF5CAFFF5E2\n")); + EXPECT_EQ((uint64_t)raw_code, TEST_R_CODE); // convert as uint64_t + + EXPECT_EQ(TEST_R_CODE, raw_code); // uint64_t == RawCode + EXPECT_EQ(raw_code, TEST_R_CODE); // RawCode == uint64_t + EXPECT_EQ(raw_code, raw_code); // RawCode == RawCode + + EXPECT_NE(TEST_R_CODE + 1, raw_code); // uint64_t != RawCode + EXPECT_NE(raw_code, TEST_R_CODE + 1); // RawCode != uint64_t + EXPECT_NE(raw_code, RawCode::unsafe_create(TEST_R_CODE + 1)); // RawCode != RawCode +} + +TEST(RawCode, exporter) { + auto raw_code = RawCode::unsafe_create(TEST_R_CODE); + EXPECT_EQ(raw_code.unwrap(), TEST_R_CODE); + EXPECT_EQ(raw_code.to_common_code(), TEST_C_CODE); +} + +TEST(RawCode, initializate) { + auto raw_code = RawCode::unsafe_create(TEST_R_CODE); + auto common_code = CommonCode::unsafe_create(TEST_C_CODE); + + // RawCode(...) + EXPECT_EQ(RawCode(common_code), TEST_R_CODE); + EXPECT_EQ(RawCode(raw_code), TEST_R_CODE); // l-value + EXPECT_EQ(RawCode(RawCode(raw_code)), TEST_R_CODE); // r-value + + // RawCode::create(uint64_t) + EXPECT_TRUE(RawCode::create(TEST_R_CODE).has_value()); + EXPECT_FALSE(RawCode::create(TEST_R_CODE_ERR).has_value()); + EXPECT_EQ(RawCode::create(TEST_R_CODE), TEST_R_CODE); + + // RawCode::unsafe_create(uint64_t) + EXPECT_EQ(RawCode::unsafe_create(TEST_R_CODE), TEST_R_CODE); + + // RawCode::from_common_code(CommonCode) + EXPECT_EQ(RawCode::from_common_code(common_code), TEST_R_CODE); + + // RawCode::from_common_code(uint64_t) + EXPECT_TRUE(RawCode::from_common_code(TEST_C_CODE).has_value()); + EXPECT_FALSE(RawCode::from_common_code(TEST_C_CODE_ERR).has_value()); + EXPECT_EQ(RawCode::from_common_code(TEST_C_CODE), TEST_R_CODE); + + // RawCode::from_common_code(const std::string &) + EXPECT_TRUE(RawCode::from_common_code(TEST_C_CODE_STR).has_value()); + EXPECT_FALSE(RawCode::from_common_code(TEST_C_CODE_STR_ERR).has_value()); + EXPECT_EQ(RawCode::from_common_code(TEST_C_CODE_STR), TEST_R_CODE); + + // RawCode::from_common_code(std::string &&) + EXPECT_TRUE(RawCode::from_common_code(TEST_C_CODE_STR_RV).has_value()); + EXPECT_FALSE(RawCode::from_common_code(TEST_C_CODE_STR_ERR_RV).has_value()); + EXPECT_EQ(RawCode::from_common_code(TEST_C_CODE_STR_RV), TEST_R_CODE); +} + +TEST(RawCode, code_verify) { + BS::thread_pool pool; + for (int head = 0; head < 16; ++head) { + pool.push_task([](uint64_t head) { + for (auto range : AllCases::instance().fetch()[head]) { + auto code = RawCode::from_common_code(head << 32 | range); + EXPECT_TRUE(code.has_value()); + EXPECT_TRUE(RawCode::check(code->unwrap())); + EXPECT_EQ(code->to_common_code(), head << 32 | range); + } + }, head); + } + pool.wait_for_tasks(); +} + +TEST(RawCode, DISABLED_global_verify) { + auto force_convert = [](uint64_t common_code) -> uint64_t { + auto range = range_reverse((uint32_t)common_code); + auto raw_code = K_MASK_2x2 << (common_code >> 32) * 3; + for (int addr = 0; range; range >>= 2) { + while ((raw_code >> addr) & 0b111 && addr < 60) // found next space + addr += 3; + if (addr >= 60) // invalid address + return 0; + switch (range & 0b11) { + case 0b01: raw_code |= K_MASK_1x2 << addr; break; + case 0b10: raw_code |= K_MASK_2x1 << addr; break; + case 0b11: raw_code |= K_MASK_1x1 << addr; break; + case 0b00: addr += 3; + } + } + return raw_code; + }; + + BS::thread_pool pool; + auto futures = pool.parallelize_loop(0x10'0000'0000, [&force_convert](uint64_t start, uint64_t end) { + std::vector archive; + for (uint64_t common_code = start; common_code < end; ++common_code) { + if (RawCode::check(force_convert(common_code))) { + archive.emplace_back(common_code); // store valid raw code + } + } + return archive; + }, 0x1000); // split as 4096 pieces + + std::vector result; + result.reserve(ALL_CASES_NUM_); + for (size_t i = 0; i < futures.size(); ++i) { + auto data = futures[i].get(); + std::cout << i << std::endl; + result.insert(result.end(), data.begin(), data.end()); // combine sections + } + pool.wait_for_tasks(); + EXPECT_EQ(result, all_common_codes()); +} diff --git a/src/core_test/codec/sample.h b/src/core_test/codec/sample.h index 0178501..65294f2 100644 --- a/src/core_test/codec/sample.h +++ b/src/core_test/codec/sample.h @@ -2,6 +2,7 @@ #include #include +#include "all_cases.h" // ----------------------------------------------------------------------------------------- // @@ -34,3 +35,19 @@ const static std::string TEST_C_CODE_STR_ERR = "0123456789"; #define TEST_C_CODE_STR_ERR_RV std::string(TEST_C_CODE_STR_ERR) // r-value // ----------------------------------------------------------------------------------------- // + +using klotski::cases::AllCases; +using klotski::cases::ALL_CASES_NUM_; + +inline std::vector all_common_codes() { + std::vector common_codes; + common_codes.reserve(ALL_CASES_NUM_); + for (uint64_t head = 0; head < 16; ++head) { + for (auto range : AllCases::instance().fetch()[head]) { + common_codes.emplace_back(head << 32 | range); + } + } + return common_codes; +} + +// ----------------------------------------------------------------------------------------- // diff --git a/src/core_test/codec/short_code.cc b/src/core_test/codec/short_code.cc index c4c5f85..5f761a9 100644 --- a/src/core_test/codec/short_code.cc +++ b/src/core_test/codec/short_code.cc @@ -98,7 +98,7 @@ TEST(ShortCode, initializate) { EXPECT_FALSE(ShortCode::from_string(TEST_S_CODE_STR_ERR).has_value()); EXPECT_EQ(ShortCode::from_string(TEST_S_CODE_STR), TEST_S_CODE); - // ShortCode::from_string(std::string&&) + // ShortCode::from_string(std::string &&) EXPECT_TRUE(ShortCode::from_string(TEST_S_CODE_STR_RV).has_value()); EXPECT_FALSE(ShortCode::from_string(TEST_S_CODE_STR_ERR_RV).has_value()); EXPECT_EQ(ShortCode::from_string(TEST_S_CODE_STR_RV), TEST_S_CODE); @@ -116,7 +116,7 @@ TEST(ShortCode, initializate) { EXPECT_FALSE(ShortCode::from_common_code(TEST_C_CODE_STR_ERR).has_value()); EXPECT_EQ(ShortCode::from_common_code(TEST_C_CODE_STR), TEST_S_CODE); - // ShortCode::from_common_code(std::string&&) + // ShortCode::from_common_code(std::string &&) EXPECT_TRUE(ShortCode::from_common_code(TEST_C_CODE_STR_RV).has_value()); EXPECT_FALSE(ShortCode::from_common_code(TEST_C_CODE_STR_ERR_RV).has_value()); EXPECT_EQ(ShortCode::from_common_code(TEST_C_CODE_STR_RV), TEST_S_CODE); @@ -156,6 +156,7 @@ TEST(ShortCode, code_verify) { auto code = ShortCode::from_common_code(head << 32 | range); EXPECT_TRUE(code.has_value()); EXPECT_TRUE(ShortCode::check(code->unwrap())); + EXPECT_EQ(code->to_common_code(), head << 32 | range); archive.emplace_back(code->unwrap()); } if (!archive.empty()) { @@ -191,14 +192,6 @@ TEST(ShortCode, code_string) { } TEST(ShortCode, DISABLED_global_verify) { - std::vector common_codes; - common_codes.reserve(ALL_CASES_NUM_); - for (uint64_t head = 0; head < 16; ++head) { - for (auto range : AllCases::instance().fetch()[head]) { - common_codes.emplace_back(head << 32 | range); - } - } - all_cases_reset(); BS::thread_pool pool; auto futures = pool.parallelize_loop(SHORT_CODE_LIMIT, [](uint32_t start, uint32_t end) { @@ -220,5 +213,5 @@ TEST(ShortCode, DISABLED_global_verify) { result.insert(result.end(), data.begin(), data.end()); // combine sections } pool.wait_for_tasks(); - EXPECT_EQ(result, common_codes); + EXPECT_EQ(result, all_common_codes()); }