Browse Source

test: add RawCode test suite

master
Dnomd343 9 months ago
parent
commit
2dbca4b898
  1. 2
      src/core/raw_code/sundry.cc
  2. 2
      src/core_test/CMakeLists.txt
  3. 16
      src/core_test/cases/all_cases.cc
  4. 10
      src/core_test/codec/common_code.cc
  5. 99
      src/core_test/codec/mirror.cc
  6. 137
      src/core_test/codec/raw_code.cc
  7. 17
      src/core_test/codec/sample.h
  8. 15
      src/core_test/codec/short_code.cc

2
src/core/raw_code/sundry.cc

@ -29,7 +29,7 @@ std::optional<RawCode> RawCode::from_common_code(uint64_t common_code) noexcept
}
std::optional<RawCode> 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();
});
}

2
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
)

16
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<int> callback_num(0);

10
src/core_test/codec/common_code.cc

@ -167,14 +167,6 @@ TEST(CommonCode, code_string) {
}
TEST(CommonCode, DISABLED_global_verify) {
std::vector<uint64_t> 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<uint64_t> 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());
}

99
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();
}

137
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<uint64_t> 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<uint64_t> 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());
}

17
src/core_test/codec/sample.h

@ -2,6 +2,7 @@
#include <string>
#include <cstdint>
#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<uint64_t> all_common_codes() {
std::vector<uint64_t> 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;
}
// ----------------------------------------------------------------------------------------- //

15
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<uint64_t> 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());
}

Loading…
Cancel
Save