Browse Source

test: adjust RawCode test suites

master
Dnomd343 2 months ago
parent
commit
7531662364
  1. 1
      src/core_test/CMakeLists.txt
  2. 17
      src/core_test/codec/common_code.cc
  3. 24
      src/core_test/codec/helper/codec.cc
  4. 7
      src/core_test/codec/helper/codec.h
  5. 22
      src/core_test/codec/helper/sample.h
  6. 94
      src/core_test/codec/mirror.cc
  7. 80
      src/core_test/codec/raw_code.cc

1
src/core_test/CMakeLists.txt

@ -42,7 +42,6 @@ add_test(NAME klotski_ffi COMMAND test_klotski_ffi)
# ------------------------------------------------------------------------------------ # # ------------------------------------------------------------------------------------ #
set(KLSK_TEST_CODEC_SRC set(KLSK_TEST_CODEC_SRC
codec/mirror.cc
codec/raw_code.cc codec/raw_code.cc
codec/short_code.cc codec/short_code.cc
codec/common_code.cc codec/common_code.cc

17
src/core_test/codec/common_code.cc

@ -22,19 +22,18 @@ TEST(CommonCode, basic) {
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
EXPECT_NE(CommonCode::check(0x1'A0'BF'0C'01), true); // low bits not fill zero EXPECT_NE(CommonCode::check(0x1'A0'BF'0C'01), true); // low bits not fill zero
EXPECT_FALSE(CommonCode::create(0x123456789).has_value()); // invalid code
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_FALSE(CommonCode::unsafe_create(TEST_MIRROR_1).is_vertical_mirror()); EXPECT_FALSE(CommonCode::unsafe_create(TEST_MIRROR_C1).is_vertical_mirror());
EXPECT_TRUE(CommonCode::unsafe_create(TEST_MIRROR_1).is_horizontal_mirror()); EXPECT_TRUE(CommonCode::unsafe_create(TEST_MIRROR_C1).is_horizontal_mirror());
EXPECT_EQ(CommonCode::unsafe_create(TEST_MIRROR_1).to_vertical_mirror(), TEST_MIRROR_1_VM); EXPECT_EQ(CommonCode::unsafe_create(TEST_MIRROR_C1).to_vertical_mirror(), TEST_MIRROR_C1_VM);
EXPECT_EQ(CommonCode::unsafe_create(TEST_MIRROR_1).to_horizontal_mirror(), TEST_MIRROR_1_HM); EXPECT_EQ(CommonCode::unsafe_create(TEST_MIRROR_C1).to_horizontal_mirror(), TEST_MIRROR_C1_HM);
EXPECT_FALSE(CommonCode::unsafe_create(TEST_MIRROR_2).is_vertical_mirror()); EXPECT_FALSE(CommonCode::unsafe_create(TEST_MIRROR_C2).is_vertical_mirror());
EXPECT_FALSE(CommonCode::unsafe_create(TEST_MIRROR_2).is_horizontal_mirror()); EXPECT_FALSE(CommonCode::unsafe_create(TEST_MIRROR_C2).is_horizontal_mirror());
EXPECT_EQ(CommonCode::unsafe_create(TEST_MIRROR_2).to_vertical_mirror(), TEST_MIRROR_2_VM); EXPECT_EQ(CommonCode::unsafe_create(TEST_MIRROR_C2).to_vertical_mirror(), TEST_MIRROR_C2_VM);
EXPECT_EQ(CommonCode::unsafe_create(TEST_MIRROR_2).to_horizontal_mirror(), TEST_MIRROR_2_HM); EXPECT_EQ(CommonCode::unsafe_create(TEST_MIRROR_C2).to_horizontal_mirror(), TEST_MIRROR_C2_HM);
#ifndef KLSK_NDEBUG #ifndef KLSK_NDEBUG
std::ostringstream out; std::ostringstream out;

24
src/core_test/codec/helper/codec.cc

@ -44,3 +44,27 @@ void common_code_parallel(std::function<void(std::span<CommonCode>)> &&func) {
pool.wait(); pool.wait();
} }
static std::vector<RawCode> convert(const std::vector<CommonCode> &codes) {
std::vector<RawCode> result;
result.reserve(29334498);
for (auto code : codes) {
result.emplace_back(RawCode::from_common_code(code));
}
return result;
}
void raw_code_parallel(std::function<void(std::span<RawCode>)> &&func) {
static auto codes = convert(AllCases::instance().fetch().codes());
BS::thread_pool pool;
pool.detach_blocks((uint64_t)0, codes.size(), [func = std::move(func)](auto start, auto end) {
func(std::span<RawCode> {codes.data() + start, end - start});
}, 16);
pool.wait();
}

7
src/core_test/codec/helper/codec.h

@ -3,14 +3,17 @@
#include <span> #include <span>
#include <functional> #include <functional>
#include "raw_code/raw_code.h"
#include "all_cases/all_cases.h" #include "all_cases/all_cases.h"
#include "short_code/short_code.h" #include "short_code/short_code.h"
#include "common_code/common_code.h" #include "common_code/common_code.h"
using klotski::cases::AllCases; using klotski::cases::AllCases;
using klotski::cases::ALL_CASES_NUM_;
using klotski::codec::RawCode;
using klotski::codec::ShortCode; using klotski::codec::ShortCode;
using klotski::codec::CommonCode; using klotski::codec::CommonCode;
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();
@ -18,6 +21,8 @@ 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)> &&func); void head_parallel(std::function<void(uint64_t)> &&func);
void raw_code_parallel(std::function<void(std::span<RawCode>)> &&func);
void short_code_parallel(std::function<void(std::span<ShortCode>)> &&func); void short_code_parallel(std::function<void(std::span<ShortCode>)> &&func);
void common_code_parallel(std::function<void(std::span<CommonCode>)> &&func); void common_code_parallel(std::function<void(std::span<CommonCode>)> &&func);

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

@ -32,13 +32,23 @@ constexpr std::string_view TEST_C_CODE_STR_ERR = "0123456789";
// ----------------------------------------------------------------------------------------- // // ----------------------------------------------------------------------------------------- //
/// CommonCode with horizontal symmetry. /// CommonCode with horizontal symmetry.
constexpr uint64_t TEST_MIRROR_1 = 0x1A9BF0C00; constexpr uint64_t TEST_MIRROR_C1 = 0x1A9BF0C00;
constexpr uint64_t TEST_MIRROR_1_VM = 0xDC3BE6800; // vertical mirror constexpr uint64_t TEST_MIRROR_C1_VM = 0xDC3BE6800; // vertical mirror
constexpr uint64_t TEST_MIRROR_1_HM = 0x1A9BF0C00; // horizontal mirror constexpr uint64_t TEST_MIRROR_C1_HM = 0x1A9BF0C00; // horizontal mirror
/// RawCode with horizontal symmetry.
constexpr uint64_t TEST_MIRROR_R1 = 0x0603EDF5'CAFFF5E2;
constexpr uint64_t TEST_MIRROR_R1_VM = 0x0FFF5E2F'CF4DA603; // vertical mirror
constexpr uint64_t TEST_MIRROR_R1_HM = 0x0603EDF5'CAFFF5E2; // horizontal mirror
/// CommonCode without vertical or horizontal symmetry. /// CommonCode without vertical or horizontal symmetry.
constexpr uint64_t TEST_MIRROR_2 = 0x4FEA13400; constexpr uint64_t TEST_MIRROR_C2 = 0x4FEA13400;
constexpr uint64_t TEST_MIRROR_2_VM = 0x8346AFC00; // vertical mirror constexpr uint64_t TEST_MIRROR_C2_VM = 0x8346AFC00; // vertical mirror
constexpr uint64_t TEST_MIRROR_2_HM = 0x6BFA47000; // horizontal mirror constexpr uint64_t TEST_MIRROR_C2_HM = 0x6BFA47000; // horizontal mirror
/// RawCode without vertical or horizontal symmetry.
constexpr uint64_t TEST_MIRROR_R2 = 0x0E58FC85'FFEBC4DB;
constexpr uint64_t TEST_MIRROR_R2_VM = 0x0EDB5FFE'BC5C8E58; // vertical mirror
constexpr uint64_t TEST_MIRROR_R2_HM = 0x00F91CFF'FAF176DA; // horizontal mirror
// ----------------------------------------------------------------------------------------- // // ----------------------------------------------------------------------------------------- //

94
src/core_test/codec/mirror.cc

@ -1,94 +0,0 @@
#include <gtest/gtest.h>
#include <BS_thread_pool.hpp>
#include "raw_code/raw_code.h"
#include "all_cases/all_cases.h"
#include "common_code/common_code.h"
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;
pool.detach_sequence(0, 16, [&test_func](const uint64_t head) {
for (const auto range : AllCases::instance().fetch()[head]) {
test_func(RawCode::from_common_code(head << 32 | range).value());
}
});
pool.wait();
}
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;
pool.detach_sequence(0, 16, [&test_func](const uint64_t head) {
for (const auto range : AllCases::instance().fetch()[head]) {
test_func(RawCode::from_common_code(head << 32 | range).value());
}
});
pool.wait();
}

80
src/core_test/codec/raw_code.cc

@ -16,21 +16,33 @@ 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(RawCode, validity) { TEST(RawCode, basic) {
EXPECT_FALSE(RawCode::check(0x0A34'182B'3810'2D21)); // invalid code 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::check(0x8603'EDF5'CAFF'F5E2)); // high 4-bits not zero
EXPECT_FALSE(RawCode::create(0x0000'0000'0000'0000).has_value()); // invalid code EXPECT_FALSE(RawCode::unsafe_create(TEST_MIRROR_R1).is_vertical_mirror());
EXPECT_TRUE(RawCode::unsafe_create(TEST_MIRROR_R1).is_horizontal_mirror());
EXPECT_EQ(RawCode::unsafe_create(TEST_MIRROR_R1).to_vertical_mirror(), TEST_MIRROR_R1_VM);
EXPECT_EQ(RawCode::unsafe_create(TEST_MIRROR_R1).to_horizontal_mirror(), TEST_MIRROR_R1_HM);
// TODO: add mirror test EXPECT_FALSE(RawCode::unsafe_create(TEST_MIRROR_R2).is_vertical_mirror());
EXPECT_FALSE(RawCode::unsafe_create(TEST_MIRROR_R2).is_horizontal_mirror());
EXPECT_EQ(RawCode::unsafe_create(TEST_MIRROR_R2).to_vertical_mirror(), TEST_MIRROR_R2_VM);
EXPECT_EQ(RawCode::unsafe_create(TEST_MIRROR_R2).to_horizontal_mirror(), TEST_MIRROR_R2_HM);
#ifndef KLSK_NDEBUG #ifndef KLSK_NDEBUG
std::ostringstream out; std::ostringstream out;
out << RawCode::unsafe_create(TEST_R_CODE); // ostream capture out << RawCode::unsafe_create(TEST_R_CODE); // ostream capture
EXPECT_TRUE(out.str().starts_with("603EDF5CAFFF5E2\n")); // TODO: using full string EXPECT_EQ(out.str(), "603EDF5CAFFF5E2\n| @ + | \n+ + + + \n| ~ + | \n+ * * + \n* . . * \n");
#endif #endif
} }
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, operators) { TEST(RawCode, operators) {
auto raw_code = RawCode::unsafe_create(TEST_R_CODE); auto raw_code = RawCode::unsafe_create(TEST_R_CODE);
EXPECT_EQ((uint64_t)raw_code, TEST_R_CODE); // uint64_t cast EXPECT_EQ((uint64_t)raw_code, TEST_R_CODE); // uint64_t cast
@ -68,13 +80,7 @@ TEST(RawCode, operators) {
EXPECT_GT(RawCode::unsafe_create(TEST_R_CODE + 1), raw_code); // RawCode > RawCode EXPECT_GT(RawCode::unsafe_create(TEST_R_CODE + 1), raw_code); // RawCode > RawCode
} }
TEST(RawCode, exporter) { TEST(RawCode, initialize) {
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 raw_code = RawCode::unsafe_create(TEST_R_CODE);
auto common_code = CommonCode::unsafe_create(TEST_C_CODE); auto common_code = CommonCode::unsafe_create(TEST_C_CODE);
@ -112,27 +118,41 @@ TEST(RawCode, initializate) {
EXPECT_EQ(RawCode::from_common_code(TEST_C_CODE_STR), TEST_R_CODE); EXPECT_EQ(RawCode::from_common_code(TEST_C_CODE_STR), TEST_R_CODE);
} }
// TODO: global check function:
// -> check
// -> compact / extract
// -> check_mirror / get_vertical_mirror / get_horizontal_mirror
TEST(RawCode, code_verify) { TEST(RawCode, code_verify) {
BS::thread_pool pool; raw_code_parallel([](std::span<RawCode> codes) {
pool.detach_sequence(0, 16, [](const uint64_t head) { for (auto code : codes) {
for (const auto range : AllCases::instance().fetch()[head]) { EXPECT_TRUE(RawCode::check(code.unwrap()));
const auto code = RawCode::from_common_code(head << 32 | range); const auto common_code = code.to_common_code(); // RawCode::compact
EXPECT_TRUE(code.has_value()); EXPECT_EQ(RawCode::from_common_code(common_code), code); // RawCode::extract
EXPECT_TRUE(RawCode::check(code->unwrap())); }
EXPECT_EQ(code->to_common_code(), head << 32 | range); });
}
TEST(RawCode, code_mirror) {
raw_code_parallel([](std::span<RawCode> codes) {
for (auto code : codes) {
const auto mirror_v = code.to_vertical_mirror();
EXPECT_TRUE(RawCode::check(mirror_v.unwrap()));
EXPECT_EQ(mirror_v.to_vertical_mirror(), code);
EXPECT_FALSE(mirror_v.is_vertical_mirror()); // not exist
EXPECT_NE(mirror_v, code);
const auto mirror_h = code.to_horizontal_mirror();
EXPECT_TRUE(RawCode::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);
}
} }
}); });
pool.wait();
} }
TEST(RawCode, DISABLED_global_verify) { TEST(RawCode, DISABLED_global_verify) {
auto force_convert = [](uint64_t common_code) -> uint64_t { // convert to RawCode and ignore errors
auto range = range_reverse((uint32_t)common_code); static auto force_convert = +[](uint64_t common_code) -> uint64_t {
auto range = range_reverse(static_cast<uint32_t>(common_code));
auto raw_code = K_MASK_2x2 << (common_code >> 32) * 3; auto raw_code = K_MASK_2x2 << (common_code >> 32) * 3;
for (int addr = 0; range; range >>= 2) { for (int addr = 0; range; range >>= 2) {
while ((raw_code >> addr) & 0b111 && addr < 60) // found next space while ((raw_code >> addr) & 0b111 && addr < 60) // found next space
@ -150,14 +170,14 @@ TEST(RawCode, DISABLED_global_verify) {
}; };
BS::thread_pool pool; BS::thread_pool pool;
auto futures = pool.submit_blocks(0ULL, 0x10'0000'0000ULL, [&force_convert](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) { for (uint64_t common_code = start; common_code < end; ++common_code) {
if (RawCode::check(force_convert(common_code))) { if (RawCode::check(force_convert(common_code))) {
archive.emplace_back(common_code); // store valid raw code codes.emplace_back(common_code); // store valid raw 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;

Loading…
Cancel
Save