Browse Source

test: adjust CommonCode test suites

master
Dnomd343 2 months ago
parent
commit
1d333a53ba
  1. 138
      src/core_test/codec/common_code.cc
  2. 33
      src/core_test/codec/helper/codec.cc
  3. 11
      src/core_test/codec/helper/codec.h
  4. 36
      src/core_test/codec/helper/sample.h

138
src/core_test/codec/common_code.cc

@ -16,7 +16,7 @@ using klotski::codec::CommonCode;
using klotski::cases::AllCases; using klotski::cases::AllCases;
using klotski::cases::ALL_CASES_NUM_; using klotski::cases::ALL_CASES_NUM_;
TEST(CommonCode, validity) { TEST(CommonCode, basic) {
EXPECT_NE(CommonCode::check(0x3'A9'BF'0C'00), true); // invalid 2x2 block EXPECT_NE(CommonCode::check(0x3'A9'BF'0C'00), true); // invalid 2x2 block
EXPECT_NE(CommonCode::check(0x1'D9'BF'0C'00), true); // invalid block range EXPECT_NE(CommonCode::check(0x1'D9'BF'0C'00), true); // invalid block range
EXPECT_NE(CommonCode::check(0x1'A9'BF'FC'00), true); // less than 2 space EXPECT_NE(CommonCode::check(0x1'A9'BF'FC'00), true); // less than 2 space
@ -26,15 +26,15 @@ TEST(CommonCode, validity) {
EXPECT_FALSE(CommonCode::from_string("0123456789").has_value()); // length > 9 EXPECT_FALSE(CommonCode::from_string("0123456789").has_value()); // length > 9
EXPECT_FALSE(CommonCode::from_string("123J432A9").has_value()); // with invalid `J` EXPECT_FALSE(CommonCode::from_string("123J432A9").has_value()); // with invalid `J`
EXPECT_TRUE(CommonCode::unsafe_create(0x1'A9BF0C00).is_horizontal_mirror()); EXPECT_FALSE(CommonCode::unsafe_create(TEST_MIRROR_1).is_vertical_mirror());
EXPECT_FALSE(CommonCode::unsafe_create(0x4'FEA13400).is_horizontal_mirror()); EXPECT_TRUE(CommonCode::unsafe_create(TEST_MIRROR_1).is_horizontal_mirror());
EXPECT_FALSE(CommonCode::unsafe_create(0x1'A9BF0C00).is_vertical_mirror()); EXPECT_EQ(CommonCode::unsafe_create(TEST_MIRROR_1).to_vertical_mirror(), TEST_MIRROR_1_VM);
EXPECT_FALSE(CommonCode::unsafe_create(0x4'FEA13400).is_vertical_mirror()); EXPECT_EQ(CommonCode::unsafe_create(TEST_MIRROR_1).to_horizontal_mirror(), TEST_MIRROR_1_HM);
EXPECT_EQ(CommonCode::unsafe_create(0x1'A9BF0C00).to_horizontal_mirror(), 0x1'A9BF0C00); EXPECT_FALSE(CommonCode::unsafe_create(TEST_MIRROR_2).is_vertical_mirror());
EXPECT_EQ(CommonCode::unsafe_create(0x4'FEA13400).to_horizontal_mirror(), 0x6'BFA47000); EXPECT_FALSE(CommonCode::unsafe_create(TEST_MIRROR_2).is_horizontal_mirror());
EXPECT_EQ(CommonCode::unsafe_create(0x1'A9BF0C00).to_vertical_mirror(), 0xD'C3BE6800); EXPECT_EQ(CommonCode::unsafe_create(TEST_MIRROR_2).to_vertical_mirror(), TEST_MIRROR_2_VM);
EXPECT_EQ(CommonCode::unsafe_create(0x4'FEA13400).to_vertical_mirror(), 0x8'346AFC00); EXPECT_EQ(CommonCode::unsafe_create(TEST_MIRROR_2).to_horizontal_mirror(), TEST_MIRROR_2_HM);
#ifndef KLSK_NDEBUG #ifndef KLSK_NDEBUG
std::ostringstream out; std::ostringstream out;
@ -43,6 +43,20 @@ TEST(CommonCode, validity) {
#endif #endif
} }
TEST(CommonCode, exporter) {
auto common_code = CommonCode::unsafe_create(TEST_C_CODE);
EXPECT_EQ(common_code.unwrap(), TEST_C_CODE);
EXPECT_EQ(common_code.to_string(), TEST_C_CODE_STR);
EXPECT_EQ(common_code.to_raw_code(), TEST_R_CODE);
EXPECT_EQ(common_code.to_short_code(), TEST_S_CODE);
auto code_shorten = common_code.to_string(true);
EXPECT_EQ(CommonCode::from_string(code_shorten), common_code);
auto code_normal = common_code.to_string(false);
EXPECT_EQ(CommonCode::from_string(code_normal), common_code);
}
TEST(CommonCode, operators) { TEST(CommonCode, operators) {
auto common_code = CommonCode::unsafe_create(TEST_C_CODE); auto common_code = CommonCode::unsafe_create(TEST_C_CODE);
EXPECT_EQ(static_cast<uint64_t>(common_code), TEST_C_CODE); // uint64_t cast EXPECT_EQ(static_cast<uint64_t>(common_code), TEST_C_CODE); // uint64_t cast
@ -80,21 +94,7 @@ TEST(CommonCode, operators) {
EXPECT_GT(CommonCode::unsafe_create(TEST_C_CODE + 1), common_code); // CommonCode > CommonCode EXPECT_GT(CommonCode::unsafe_create(TEST_C_CODE + 1), common_code); // CommonCode > CommonCode
} }
TEST(CommonCode, exporter) { TEST(CommonCode, initialize) {
auto common_code = CommonCode::unsafe_create(TEST_C_CODE);
EXPECT_EQ(common_code.unwrap(), TEST_C_CODE);
EXPECT_EQ(common_code.to_string(), TEST_C_CODE_STR);
EXPECT_EQ(common_code.to_raw_code(), TEST_R_CODE);
EXPECT_EQ(common_code.to_short_code(), TEST_S_CODE);
auto code_shorten = common_code.to_string(true);
EXPECT_EQ(CommonCode::from_string(code_shorten), common_code);
auto code_normal = common_code.to_string(false);
EXPECT_EQ(CommonCode::from_string(code_normal), common_code);
}
TEST(CommonCode, initializate) {
auto raw_code = RawCode::unsafe_create(TEST_R_CODE); auto raw_code = RawCode::unsafe_create(TEST_R_CODE);
auto short_code = ShortCode::unsafe_create(TEST_S_CODE); auto short_code = ShortCode::unsafe_create(TEST_S_CODE);
auto common_code = CommonCode::unsafe_create(TEST_C_CODE); auto common_code = CommonCode::unsafe_create(TEST_C_CODE);
@ -147,65 +147,73 @@ TEST(CommonCode, initializate) {
EXPECT_EQ(CommonCode::from_short_code(TEST_S_CODE_STR), TEST_C_CODE); EXPECT_EQ(CommonCode::from_short_code(TEST_S_CODE_STR), TEST_C_CODE);
} }
// TODO: global test function
// -> check
// -> string_decode / string_encode / string_encode_shorten
// -> check_mirror / get_vertical_mirror / get_horizontal_mirror
TEST(CommonCode, code_verify) { TEST(CommonCode, code_verify) {
BS::thread_pool pool; common_code_parallel([](std::span<CommonCode> codes) {
pool.detach_sequence(0, 16, [](const uint64_t head) { for (auto code : codes) {
for (auto range : AllCases::instance().fetch()[head]) { EXPECT_TRUE(CommonCode::check(code.unwrap())); // verify all cases
auto code = head << 32 | range;
EXPECT_TRUE(CommonCode::check(code)); // verify all cases
} }
}); });
pool.wait();
} }
TEST(CommonCode, code_string) { TEST(CommonCode, code_mirror) {
auto test_func = [](CommonCode code) { common_code_parallel([](std::span<CommonCode> codes) {
auto code_shorten = code.to_string(true); // with shorten for (auto code : codes) {
auto code_normal = code.to_string(false); // without shorten const auto mirror_v = code.to_vertical_mirror();
EXPECT_TRUE(code_normal.starts_with(code_shorten)); EXPECT_TRUE(CommonCode::check(mirror_v.unwrap()));
EXPECT_EQ(mirror_v.to_vertical_mirror(), code);
EXPECT_LE(code_shorten.size(), 9); // length -> (0, 9] EXPECT_FALSE(mirror_v.is_vertical_mirror()); // not exist
EXPECT_NE(code_shorten.size(), 0); EXPECT_NE(mirror_v, code);
if (code != 0) { // skip special code string `0`
EXPECT_NE(code_shorten.back(), '0'); const auto mirror_h = code.to_horizontal_mirror();
EXPECT_TRUE(CommonCode::check(mirror_h.unwrap()));
EXPECT_EQ(mirror_h.to_horizontal_mirror(), code);
if (mirror_h.is_horizontal_mirror()) {
EXPECT_EQ(mirror_h, code);
} else {
EXPECT_NE(mirror_h, code);
}
} }
EXPECT_EQ(CommonCode::from_string(code_shorten), code); // test upper cases });
std::transform(code_shorten.begin(), code_shorten.end(), code_shorten.begin(), ::tolower); }
EXPECT_EQ(CommonCode::from_string(code_shorten), code); // test lower cases
EXPECT_EQ(code_normal.size(), 9); // length = 9 TEST(CommonCode, code_string) {
for (auto c : code_normal) { common_code_parallel([](std::span<CommonCode> codes) {
EXPECT_TRUE((c >= '0' && c <= '9') || (c >= 'A' && c <= 'F')); for (auto code : codes) {
} auto code_shorten = code.to_string(true); // with shorten
EXPECT_EQ(CommonCode::from_string(code_normal), code); // test upper cases auto code_normal = code.to_string(false); // without shorten
std::transform(code_normal.begin(), code_normal.end(), code_normal.begin(), ::tolower); EXPECT_TRUE(code_normal.starts_with(code_shorten));
EXPECT_EQ(CommonCode::from_string(code_normal), code); // test lower cases EXPECT_EQ(std::format("{:09X}", code.unwrap()), code_normal);
};
EXPECT_LE(code_shorten.size(), 9); // length -> (0, 9]
EXPECT_NE(code_shorten.size(), 0);
if (code != 0) { // skip special code string `0`
EXPECT_NE(code_shorten.back(), '0');
}
EXPECT_EQ(CommonCode::from_string(code_shorten), code); // test upper cases
std::transform(code_shorten.begin(), code_shorten.end(), code_shorten.begin(), ::tolower);
EXPECT_EQ(CommonCode::from_string(code_shorten), code); // test lower cases
BS::thread_pool pool; EXPECT_EQ(code_normal.size(), 9); // length = 9
pool.detach_sequence(0, 16, [&test_func](const uint64_t head) { for (auto c : code_normal) {
for (auto range : AllCases::instance().fetch()[head]) { EXPECT_TRUE((c >= '0' && c <= '9') || (c >= 'A' && c <= 'F'));
test_func(CommonCode::unsafe_create(head << 32 | range)); }
EXPECT_EQ(CommonCode::from_string(code_normal), code); // test upper cases
std::transform(code_normal.begin(), code_normal.end(), code_normal.begin(), ::tolower);
EXPECT_EQ(CommonCode::from_string(code_normal), code); // test lower cases
} }
}); });
pool.wait();
} }
TEST(CommonCode, DISABLED_global_verify) { TEST(CommonCode, DISABLED_global_verify) {
BS::thread_pool pool; BS::thread_pool pool;
auto futures = pool.submit_blocks(0ULL, 0x10'0000'0000ULL, [](uint64_t start, uint64_t end) { auto futures = pool.submit_blocks(0ULL, 0x10'0000'0000ULL, [](auto start, auto end) {
std::vector<uint64_t> archive; std::vector<uint64_t> codes;
for (uint64_t common_code = start; common_code < end; ++common_code) { // brute-force search for (uint64_t common_code = start; common_code < end; ++common_code) { // brute-force search
if (CommonCode::check(common_code)) { if (CommonCode::check(common_code)) {
archive.emplace_back(common_code); // found valid common code codes.emplace_back(common_code); // found valid common code
} }
} }
return archive; return codes;
}, 0x1000); // split as 4096 pieces }, 0x1000); // split as 4096 pieces
std::vector<uint64_t> result; std::vector<uint64_t> result;

33
src/core_test/codec/helper/codec.cc

@ -3,14 +3,15 @@
#include "codec.h" #include "codec.h"
void head_parallel(std::function<void(uint64_t head)> &&func) { void head_parallel(std::function<void(uint64_t head)> &&func) {
BS::thread_pool pool; constexpr auto heads = std::to_array({
// TODO: skip invalid head 0, 1, 2, 4, 5, 6, 8, 9, 10, 12, 13, 14
pool.detach_sequence(0, 16, [func = std::move(func)](const uint64_t head) {
if (head == 3 || head == 7 || head == 11 || head == 15) {
return;
}
func(head);
}); });
BS::thread_pool pool;
for (auto head : heads) {
pool.detach_task([head, &func] {
func(head);
});
}
pool.wait(); pool.wait();
} }
@ -25,3 +26,21 @@ std::vector<uint64_t> all_common_codes() {
} }
return common_codes; return common_codes;
} }
void common_code_parallel(std::function<void(std::span<CommonCode>)> &&func) {
static auto codes = AllCases::instance().fetch().codes();
BS::thread_pool pool;
// TODO: enhance performance
pool.detach_blocks((uint64_t)0, codes.size(), [func = std::move(func)](auto start, auto end) {
func(std::span<CommonCode> {codes.data() + start, end - start});
}, 16);
pool.wait();
}

11
src/core_test/codec/helper/codec.h

@ -1,14 +1,23 @@
#pragma once #pragma once
#include <span>
#include <functional> #include <functional>
#include "all_cases/all_cases.h" #include "all_cases/all_cases.h"
#include "short_code/short_code.h"
#include "common_code/common_code.h"
using klotski::cases::AllCases; using klotski::cases::AllCases;
using klotski::codec::ShortCode;
using klotski::codec::CommonCode;
using klotski::cases::ALL_CASES_NUM_; using klotski::cases::ALL_CASES_NUM_;
/// Build all valid CommonCodes. /// Build all valid CommonCodes.
std::vector<uint64_t> all_common_codes(); std::vector<uint64_t> all_common_codes();
/// Spawn all valid klotski headers in parallel. /// Spawn all valid klotski headers in parallel.
void head_parallel(std::function<void(uint64_t head)> &&func); void head_parallel(std::function<void(uint64_t)> &&func);
void short_code_parallel(std::function<void(std::span<ShortCode>)> &&func);
void common_code_parallel(std::function<void(std::span<CommonCode>)> &&func);

36
src/core_test/codec/helper/sample.h

@ -5,32 +5,40 @@
// ----------------------------------------------------------------------------------------- // // ----------------------------------------------------------------------------------------- //
/// Valid klotski RawCode /// Valid klotski RawCode sample.
constexpr uint64_t TEST_R_CODE = 0x0603'EDF5'CAFF'F5E2; constexpr uint64_t TEST_R_CODE = 0x0603'EDF5'CAFF'F5E2;
/// Valid klotski ShortCode /// Valid klotski ShortCode sample.
constexpr uint32_t TEST_S_CODE = 4091296; constexpr uint32_t TEST_S_CODE = 4091296;
const std::string TEST_S_CODE_STR = "4WVE1"; // TODO: using `std::string_view` constexpr std::string_view TEST_S_CODE_STR = "4WVE1";
#define TEST_S_CODE_STR_RV std::string(TEST_S_CODE_STR) // TODO: remove r-value
/// Valid klotski CommonCode /// Valid klotski CommonCode sample.
constexpr uint64_t TEST_C_CODE = 0x1'A9BF'0C00; constexpr uint64_t TEST_C_CODE = 0x1'A9BF'0C00;
const std::string TEST_C_CODE_STR = "1A9BF0C00"; constexpr std::string_view TEST_C_CODE_STR = "1A9BF0C00";
#define TEST_C_CODE_STR_RV std::string(TEST_C_CODE_STR) // TODO: remove r-value
// ----------------------------------------------------------------------------------------- // // ----------------------------------------------------------------------------------------- //
/// Invalid klotski RawCode /// Invalid klotski RawCode sample.
constexpr uint64_t TEST_R_CODE_ERR = 0x1603'ED00'CAFF'F5E2; constexpr uint64_t TEST_R_CODE_ERR = 0x1603'ED00'CAFF'F5E2;
/// Invalid klotski ShortCode /// Invalid klotski ShortCode sample.
constexpr uint32_t TEST_S_CODE_ERR = 1234564323; constexpr uint32_t TEST_S_CODE_ERR = 1234564323;
const std::string TEST_S_CODE_STR_ERR = "ZZZZZZ"; constexpr std::string_view TEST_S_CODE_STR_ERR = "ZZZZZZ";
#define TEST_S_CODE_STR_ERR_RV std::string(TEST_S_CODE_STR_ERR) // TODO: remove r-value
/// Invalid klotski CommonCode /// Invalid klotski CommonCode sample.
constexpr uint64_t TEST_C_CODE_ERR = 0x3'A9BF'0C00; constexpr uint64_t TEST_C_CODE_ERR = 0x3'A9BF'0C00;
const static std::string TEST_C_CODE_STR_ERR = "0123456789"; constexpr std::string_view TEST_C_CODE_STR_ERR = "0123456789";
#define TEST_C_CODE_STR_ERR_RV std::string(TEST_C_CODE_STR_ERR) // TODO: remove r-value
// ----------------------------------------------------------------------------------------- //
/// CommonCode with horizontal symmetry.
constexpr uint64_t TEST_MIRROR_1 = 0x1A9BF0C00;
constexpr uint64_t TEST_MIRROR_1_VM = 0xDC3BE6800; // vertical mirror
constexpr uint64_t TEST_MIRROR_1_HM = 0x1A9BF0C00; // horizontal mirror
/// CommonCode without vertical or horizontal symmetry.
constexpr uint64_t TEST_MIRROR_2 = 0x4FEA13400;
constexpr uint64_t TEST_MIRROR_2_VM = 0x8346AFC00; // vertical mirror
constexpr uint64_t TEST_MIRROR_2_HM = 0x6BFA47000; // horizontal mirror
// ----------------------------------------------------------------------------------------- // // ----------------------------------------------------------------------------------------- //

Loading…
Cancel
Save