Browse Source

test: refactor group build cases test

legacy
Dnomd343 2 years ago
parent
commit
b035d2a13f
  1. 12
      src/klotski_core/group/build_cases.cc
  2. 6
      src/klotski_core/group/group.h
  3. 155
      test/group/build_cases.cc

12
src/klotski_core/group/build_cases.cc

@ -12,6 +12,18 @@ namespace klotski {
using Common::check_range; using Common::check_range;
using Common::range_reverse; using Common::range_reverse;
uint32_t Group::group_size(const GroupId &group_id) {
return group_cases(group_seed(group_id)).size();
}
uint32_t Group::group_size(const RawCode &raw_code) {
return group_cases(raw_code).size();
}
uint32_t Group::group_size(const CommonCode &common_code) {
return group_size(common_code.to_raw_code());
}
std::vector<RawCode> Group::group_cases(const CommonCode &common_code) { std::vector<RawCode> Group::group_cases(const CommonCode &common_code) {
return group_cases(common_code.to_raw_code()); return group_cases(common_code.to_raw_code());
} }

6
src/klotski_core/group/group.h

@ -7,6 +7,7 @@
namespace klotski { namespace klotski {
const uint32_t TYPE_ID_LIMIT = 203; const uint32_t TYPE_ID_LIMIT = 203;
const uint32_t ALL_GROUP_NUM = 25422;
/// ----------------------------------------- Type ID ----------------------------------------- /// ----------------------------------------- Type ID -----------------------------------------
@ -84,6 +85,11 @@ class Group {
public: public:
/// ----------------------------------- group seeds ----------------------------------- /// ----------------------------------- group seeds -----------------------------------
/// Get the size of the specified group.
static uint32_t group_size(const GroupId &group_id);
static uint32_t group_size(const RawCode &raw_code);
static uint32_t group_size(const CommonCode &common_code);
/// Get the minimum CommonCode of the specified group. /// Get the minimum CommonCode of the specified group.
static CommonCode group_seed(const GroupId &group_id); static CommonCode group_seed(const GroupId &group_id);
static CommonCode group_seed(const RawCode &raw_code); static CommonCode group_seed(const RawCode &raw_code);

155
test/group/build_cases.cc

@ -1,16 +1,15 @@
#include <algorithm> #include <algorithm>
#include "md5.h" #include "md5.h"
#include "group.h" #include "group.h"
#include "type_id.h"
#include "tiny_pool.h"
#include "common_code.h" #include "common_code.h"
#include "group_seeds.h"
#include "gtest/gtest.h" #include "gtest/gtest.h"
#include "tiny_pool.h"
#include "group/type_id.h"
#include "group/group_seeds.h"
using klotski::Group; using klotski::Group;
using klotski::TypeId; using klotski::TypeId;
using klotski::GroupId;
using klotski::AllCases; using klotski::AllCases;
using klotski::RawCode; using klotski::RawCode;
@ -19,44 +18,53 @@ using klotski::CommonCode;
using klotski::GROUP_SEEDS; using klotski::GROUP_SEEDS;
using klotski::TYPE_ID_SIZE; using klotski::TYPE_ID_SIZE;
using klotski::ALL_GROUP_NUM;
using klotski::TYPE_ID_LIMIT; using klotski::TYPE_ID_LIMIT;
using klotski::SHORT_CODE_LIMIT; using klotski::SHORT_CODE_LIMIT;
using klotski::TYPE_ID_GROUP_NUM;
using klotski::ALL_CASES_SIZE_SUM; using klotski::ALL_CASES_SIZE_SUM;
const char GROUP_INFO_MD5[] = "976bf22530085210e68a6a4e67053506"; const char GROUP_INFO_MD5[] = "976bf22530085210e68a6a4e67053506";
TEST(Group, all_cases) { TEST(Group, all_cases) {
std::vector<std::vector<CommonCode>> all_cases; std::array<std::vector<CommonCode>, TYPE_ID_LIMIT> all_cases;
auto build = [&all_cases](TypeId type_id) {
auto cases = Group::all_cases(type_id); // build test data
EXPECT_EQ(cases.size(), TYPE_ID_SIZE[type_id.unwrap()]); // verify cases number
for (auto &&common_code : cases) {
EXPECT_EQ(TypeId(common_code), type_id); // verify type id
}
EXPECT_EQ(std::is_sorted(cases.begin(), cases.end()), true); // verify data order
all_cases[type_id.unwrap()] = cases;
};
auto pool = TinyPool();
for (uint32_t type_id = 0; type_id < TYPE_ID_LIMIT; ++type_id) { for (uint32_t type_id = 0; type_id < TYPE_ID_LIMIT; ++type_id) {
all_cases.emplace_back(Group::all_cases(TypeId(type_id))); // build test data pool.submit(build, TypeId(type_id));
} }
pool.boot();
pool.join(); // wait data build complete
std::vector<uint64_t> combine; std::vector<CommonCode> combine;
combine.reserve(ALL_CASES_SIZE_SUM); combine.reserve(ALL_CASES_SIZE_SUM);
for (uint32_t id = 0; id < TYPE_ID_LIMIT; ++id) { for (auto &&cases : all_cases) {
EXPECT_EQ(all_cases[id].size(), TYPE_ID_SIZE[id]); // verify cases number combine.insert(combine.end(), cases.begin(), cases.end());
for (auto &&common_code : all_cases[id]) {
EXPECT_EQ(TypeId(common_code).unwrap(), id); // verify type id
combine.emplace_back(common_code.unwrap());
}
std::is_sorted(all_cases[id].begin(), all_cases[id].end()); // verify data order
} }
EXPECT_EQ(combine.size(), ALL_CASES_SIZE_SUM); // verify sum EXPECT_EQ(combine.size(), ALL_CASES_SIZE_SUM); // verify sum
auto all_cases_release = AllCases::release(); auto all_cases_release = AllCases::release();
std::stable_sort(combine.begin(), combine.end()); std::stable_sort(combine.begin(), combine.end());
for (uint32_t i = 0; i < combine.size(); ++i) { EXPECT_EQ(combine, all_cases_release); // verify combined cases
EXPECT_EQ(combine[i], all_cases_release[i]); // verify after combined
}
} }
TEST(Group, group_cases) { TEST(Group, group_cases) {
auto test = [](CommonCode seed) -> std::vector<CommonCode> { auto build = [](CommonCode seed) -> std::vector<CommonCode> {
auto group_raw = Group::group_cases(RawCode::from_common_code(seed)); auto group_raw = Group::group_cases(seed);
std::vector<CommonCode> group(group_raw.begin(), group_raw.end()); // convert as CommonCodes std::vector<CommonCode> group(group_raw.begin(), group_raw.end()); // convert as CommonCodes
EXPECT_EQ(seed, std::min_element(group.begin(), group.end())->unwrap()); // confirm min seed EXPECT_EQ(seed, std::min_element(group.begin(), group.end())->unwrap()); // confirm min seed
EXPECT_EQ(group.size(), Group::group_size(seed)); // verify group size
uint32_t type_id = TypeId(CommonCode(seed)).unwrap(); // current type id uint32_t type_id = TypeId(seed).unwrap(); // current type id
for (auto &&elem : group) { for (auto &&elem : group) {
EXPECT_EQ(TypeId(elem).unwrap(), type_id); // verify type id of group cases EXPECT_EQ(TypeId(elem).unwrap(), type_id); // verify type id of group cases
} }
@ -67,7 +75,7 @@ TEST(Group, group_cases) {
std::vector<std::future<std::vector<CommonCode>>> futures; std::vector<std::future<std::vector<CommonCode>>> futures;
for (auto &&seed : GROUP_SEEDS) { for (auto &&seed : GROUP_SEEDS) {
futures.emplace_back( futures.emplace_back(
pool.submit(test, CommonCode::unsafe_create(seed)) pool.submit(build, CommonCode::unsafe_create(seed))
); );
} }
@ -75,61 +83,100 @@ TEST(Group, group_cases) {
std::vector<CommonCode> all_cases; std::vector<CommonCode> all_cases;
all_cases.reserve(ALL_CASES_SIZE_SUM); all_cases.reserve(ALL_CASES_SIZE_SUM);
for (auto &&f : futures) { for (auto &&f : futures) {
auto ret = f.get(); auto cases = f.get();
all_cases.insert(all_cases.end(), ret.begin(), ret.end()); all_cases.insert(all_cases.end(), cases.begin(), cases.end()); // combine build result
} }
std::sort(all_cases.begin(), all_cases.end()); std::sort(all_cases.begin(), all_cases.end());
EXPECT_EQ(all_cases, AllCases::release()); // verify all released cases EXPECT_EQ(all_cases, AllCases::release()); // verify all released cases
} }
TEST(Group, build_group) { TEST(Group, group_seeds) {
std::vector<CommonCode> all_seeds;
all_seeds.reserve(ALL_GROUP_NUM);
for (uint32_t type_id = 0; type_id < TYPE_ID_LIMIT; ++type_id) {
auto seeds = Group::group_seeds(TypeId(type_id));
for (auto &&seed : seeds) {
EXPECT_EQ(TypeId(seed).unwrap(), type_id); // verify type id of seeds
}
all_seeds.insert(all_seeds.end(), seeds.begin(), seeds.end());
std::vector<CommonCode> sub_seeds;
sub_seeds.reserve(TYPE_ID_GROUP_NUM[type_id]);
for (uint32_t group_id = 0; group_id < TYPE_ID_GROUP_NUM[type_id]; ++group_id) {
sub_seeds.emplace_back(Group::group_seed(GroupId(type_id, group_id)));
}
std::sort(seeds.begin(), seeds.end());
std::sort(sub_seeds.begin(), sub_seeds.end()); // don't verify seeds order for now
EXPECT_EQ(seeds, sub_seeds); // verify group seeds
}
std::vector<CommonCode> group_seeds(GROUP_SEEDS, GROUP_SEEDS + ALL_GROUP_NUM);
EXPECT_EQ(all_seeds, group_seeds); // verify group seeds
auto test = [](CommonCode seed) {
EXPECT_EQ(Group::group_seed(seed), seed); // verify group seed fetch
EXPECT_EQ(Group::group_seed(seed.to_raw_code()), seed);
};
auto pool = TinyPool();
for (auto &&seed : GROUP_SEEDS) { // traverse all seeds
pool.submit(test, CommonCode::unsafe_create(seed));
}
pool.boot();
pool.join();
} }
TEST(Group, build_groups) { TEST(Group, build_groups) {
struct group_info_t { std::vector<Group::group_info_t> all_cases(SHORT_CODE_LIMIT);
uint16_t group_id;
uint32_t group_index;
};
ShortCode::speed_up(ShortCode::FAST);
std::vector<group_info_t> all_cases(SHORT_CODE_LIMIT);
std::vector<uint16_t> group_ids; auto test = [&all_cases](TypeId type_id) {
auto groups = Group::build_groups(type_id);
EXPECT_EQ(groups.size(), TYPE_ID_GROUP_NUM[type_id.unwrap()]); // verify groups num
for (uint16_t type_id = 0; type_id < klotski::TYPE_ID_LIMIT; ++type_id) {
std::vector<uint32_t> group_sizes; std::vector<uint32_t> group_sizes;
std::vector<CommonCode> group_seeds; std::map<uint32_t, std::vector<CommonCode>> group_seeds; // <group_size, group_seeds>
auto groups = Group::build_groups(TypeId(type_id));
group_sizes.reserve(groups.size()); for (uint32_t group_id = 0; group_id < groups.size(); ++group_id) {
group_seeds.reserve(groups.size()); auto group = Group::build_group(GroupId(type_id, group_id));
std::sort(group.begin(), group.end());
for (uint32_t id = 0; id < groups.size(); ++id) { std::sort(groups[group_id].begin(), groups[group_id].end());
group_sizes.emplace_back(groups[id].size()); // record size EXPECT_EQ(groups[group_id], group); // verify group data
std::sort(groups[id].begin(), groups[id].end()); // sort for group index EXPECT_EQ(group.size(), Group::group_size(GroupId(type_id, group_id))); // verify group size
for (uint32_t index = 0; index < groups[id].size(); ++index) { EXPECT_EQ(*group.begin(), Group::group_seed(GroupId(type_id, group_id))); // verify group seed
all_cases[groups[id][index].to_short_code().unwrap()] = {
.group_id = static_cast<uint16_t>(id), for (uint32_t index = 0; index < group.size(); ++index) {
all_cases[group[index].to_short_code().unwrap()] = { // storage group info
.type_id = 0,
.group_id = static_cast<uint16_t>(group_id),
.group_index = index, .group_index = index,
}; };
EXPECT_EQ(TypeId(groups[id][index]).unwrap(), type_id); // verify type id EXPECT_EQ(TypeId(group[index]), type_id); // verify released type id
} }
group_seeds.emplace_back(groups[id][0]); // record seed
}
// TODO: check group_seeds and group_sizes group_seeds[group.size()].emplace_back(*group.begin()); // storage group seeds
group_sizes.emplace_back(group.size()); // storage group size
}
// TODO: verify GROUP_OFFSET EXPECT_EQ(std::is_sorted(group_sizes.rbegin(), group_sizes.rend()), true); // verify group size order
for (auto &&tmp : group_seeds) {
EXPECT_EQ(std::is_sorted(tmp.second.begin(), tmp.second.end()), true); // verify group cases order
}
};
auto pool = TinyPool();
ShortCode::speed_up(ShortCode::FAST);
for (uint32_t type_id = 0; type_id < TYPE_ID_LIMIT; ++type_id) {
pool.submit(test, TypeId(type_id));
} }
pool.boot();
// TODO: verify GROUP_SEEDS / GROUP_SEEDS_INDEX / GROUP_SEEDS_INDEX_REV pool.join();
char buffer[9]; char buffer[9];
std::string group_info; std::string group_info_str;
for (auto &&tmp : all_cases) { for (auto &&tmp : all_cases) {
sprintf(buffer, "%d,%d\n", tmp.group_id, tmp.group_index); sprintf(buffer, "%d,%d\n", tmp.group_id, tmp.group_index);
group_info += buffer; group_info_str += buffer;
} }
auto group_info_md5 = md5(group_info.c_str(), group_info.size()); auto group_info_md5 = md5(group_info_str.c_str(), group_info_str.size());
EXPECT_STREQ(group_info_md5.c_str(), GROUP_INFO_MD5); // verify all group info EXPECT_STREQ(group_info_md5.c_str(), GROUP_INFO_MD5); // verify all group info
} }
// TODO: verify GROUP_SEEDS_INDEX_REV

Loading…
Cancel
Save