From 9e11872178041382422880fab176aaf3e0956656 Mon Sep 17 00:00:00 2001 From: Dnomd343 Date: Mon, 2 Oct 2023 14:28:33 +0800 Subject: [PATCH] test: add all cases ffi test --- src/core/ffi/all_cases.cc | 11 +- src/core_test/CMakeLists.txt | 13 ++- src/core_test/cases/all_cases.cc | 5 - src/core_test/ffi/all_cases.cc | 183 +++++++++++++++++++++++++++++++ third_party/third_party.cmake | 8 +- 5 files changed, 204 insertions(+), 16 deletions(-) create mode 100644 src/core_test/ffi/all_cases.cc diff --git a/src/core/ffi/all_cases.cc b/src/core/ffi/all_cases.cc index db44a53..d1de7e1 100644 --- a/src/core/ffi/all_cases.cc +++ b/src/core/ffi/all_cases.cc @@ -3,7 +3,6 @@ using klotski::cases::AllCases; using klotski::cases::BasicRanges; - using klotski::cases::ALL_CASES_NUM; void all_cases_prebuild() { @@ -11,9 +10,9 @@ void all_cases_prebuild() { } void all_cases_prebuild_async(executor_t executor, notifier_t callback) { - executor([](void *cb) { + executor([](void *fn) { all_cases_prebuild(); - ((notifier_t)cb)(); + ((notifier_t)fn)(); }, (void*)callback); } @@ -30,9 +29,9 @@ void all_cases_build() { } void all_cases_build_async(executor_t executor, notifier_t callback) { - executor([](void *cb) { + executor([](void *fn) { all_cases_build(); - ((notifier_t)cb)(); + ((notifier_t)fn)(); }, (void*)callback); } @@ -68,7 +67,7 @@ int all_cases_available() { } int all_cases_num(int head) { - if (head < 0 || head > 15) { + if (head < 0 || head >= (int)ALL_CASES_NUM.size()) { return -1; } return ALL_CASES_NUM[head]; diff --git a/src/core_test/CMakeLists.txt b/src/core_test/CMakeLists.txt index 8bfdefb..57cadbb 100644 --- a/src/core_test/CMakeLists.txt +++ b/src/core_test/CMakeLists.txt @@ -2,12 +2,13 @@ cmake_minimum_required(VERSION 3.0) set(CMAKE_CXX_STANDARD 20) -set(KLOTSKI_TEST_DEPS klotski-core gtest gtest_main xxHash::xxhash) +set(KLOTSKI_TEST_DEPS klotski-core gtest gtest_main md5sum xxHash::xxhash) ############################################################################################### include_directories(utils) +include_directories(${KLOTSKI_ROOT}/src/core/ffi) include_directories(${KLOTSKI_ROOT}/src/core/utils) include_directories(${KLOTSKI_ROOT}/src/core/all_cases) @@ -22,3 +23,13 @@ target_link_libraries(test_klotski_cases PRIVATE ${KLOTSKI_TEST_DEPS}) add_test(NAME klotski_cases COMMAND test_klotski_cases) ############################################################################################### + +set(KLOTSKI_TEST_FFI_SRC + ffi/all_cases.cc +) + +add_executable(test_klotski_ffi ${KLOTSKI_TEST_FFI_SRC}) +target_link_libraries(test_klotski_ffi PRIVATE ${KLOTSKI_TEST_DEPS}) +add_test(NAME klotski_ffi COMMAND test_klotski_ffi) + +############################################################################################### diff --git a/src/core_test/cases/all_cases.cc b/src/core_test/cases/all_cases.cc index d2925c4..439aa14 100644 --- a/src/core_test/cases/all_cases.cc +++ b/src/core_test/cases/all_cases.cc @@ -21,11 +21,6 @@ static const auto TEST_THREAD_NUM = 256; static const std::string ALL_CASES_XXHASH = "d589c8a45983ebb6"; static const std::string BASIC_RANGES_XXHASH = "5e7f633b7bd8af37"; -/// The efficiency of string hashing is not very high, but there is a memorable -/// story, and this scheme is still retained here. -//static const std::string ALL_CASES_MD5 = "3888e9fab8d3cbb50908b12b147cfb23"; -//static const std::string BASIC_RANGES_MD5 = "6f385dc171e201089ff96bb010b47212"; - /// Forcibly modify private variables to reset state. PRIVATE_ACCESS(AllCases, available_, bool) PRIVATE_ACCESS(BasicRanges, available_, bool) diff --git a/src/core_test/ffi/all_cases.cc b/src/core_test/ffi/all_cases.cc new file mode 100644 index 0000000..2f04926 --- /dev/null +++ b/src/core_test/ffi/all_cases.cc @@ -0,0 +1,183 @@ +#include +#include +#include + +#include "md5sum.h" +#include "exposer.h" +#include "klotski.h" +#include "all_cases.h" +#include "gtest/gtest.h" + +using md5::md5sum; + +using klotski::cases::AllCases; +using klotski::cases::BasicRanges; + +using klotski::cases::ALL_CASES_NUM; + +/// The efficiency of string hashing is not very high, but there is a memorable +/// story, and this scheme is still retained here. +static const std::string ALL_CASES_MD5 = "3888e9fab8d3cbb50908b12b147cfb23"; + +/// Forcibly modify private variables to reset state. +PRIVATE_ACCESS(AllCases, available_, bool) +PRIVATE_ACCESS(BasicRanges, available_, bool) + +/// Reset basic ranges build state, note it is thread-unsafe. +void basic_ranges_reset() { + access_BasicRanges_available_(BasicRanges::Instance()) = false; +} + +/// Reset all cases build state, note it is thread-unsafe. +void all_cases_reset() { + access_AllCases_available_(AllCases::Instance()) = false; +} + +TEST(FFI, all_cases_prebuild) { + basic_ranges_reset(); + EXPECT_FALSE(all_cases_prebuild_available()); + all_cases_prebuild(); + EXPECT_TRUE(all_cases_prebuild_available()); + all_cases_prebuild(); + EXPECT_TRUE(all_cases_prebuild_available()); +} + +TEST(FFI, all_cases_prebuild_async) { + basic_ranges_reset(); + static std::atomic_flag chan; + + chan.clear(); + all_cases_prebuild_async([](void (*fn)(void*), void *arg) { + std::thread worker(fn, arg); + worker.detach(); + }, []() { + chan.test_and_set(); + chan.notify_all(); + }); + EXPECT_FALSE(all_cases_prebuild_available()); + chan.wait(false); + EXPECT_TRUE(all_cases_prebuild_available()); + + chan.clear(); + all_cases_prebuild_async([](void (*fn)(void*), void *arg) { + std::thread worker(fn, arg); + worker.detach(); + }, []() { + chan.test_and_set(); + chan.notify_all(); + }); + EXPECT_TRUE(all_cases_prebuild_available()); + chan.wait(false); + EXPECT_TRUE(all_cases_prebuild_available()); +} + +TEST(FFI, all_cases_build) { + all_cases_reset(); + EXPECT_FALSE(all_cases_available()); + all_cases_build(); + EXPECT_TRUE(all_cases_available()); + all_cases_build(); + EXPECT_TRUE(all_cases_available()); +} + +TEST(FFI, all_cases_build_async) { + all_cases_reset(); + static std::atomic_flag chan; + + chan.clear(); + all_cases_build_async([](void (*fn)(void*), void *arg) { + std::thread worker(fn, arg); + worker.detach(); + }, []() { + chan.test_and_set(); + chan.notify_all(); + }); + EXPECT_FALSE(all_cases_available()); + chan.wait(false); + EXPECT_TRUE(all_cases_available()); + + chan.clear(); + all_cases_build_async([](void (*fn)(void*), void *arg) { + std::thread worker(fn, arg); + worker.detach(); + }, []() { + chan.test_and_set(); + chan.notify_all(); + }); + EXPECT_TRUE(all_cases_available()); + chan.wait(false); + EXPECT_TRUE(all_cases_available()); +} + +TEST(FFI, all_cases_build_parallel) { + all_cases_reset(); + EXPECT_FALSE(all_cases_available()); + all_cases_build_parallel([](void (*fn)(void*), void *arg) { + std::thread worker(fn, arg); + worker.detach(); + }); + EXPECT_TRUE(all_cases_available()); + all_cases_build_parallel([](void (*fn)(void*), void *arg) { + std::thread worker(fn, arg); + worker.detach(); + }); + EXPECT_TRUE(all_cases_available()); +} + +TEST(FFI, all_cases_build_parallel_async) { + all_cases_reset(); + static std::atomic_flag chan; + + chan.clear(); + all_cases_build_parallel_async([](void (*fn)(void*), void *arg) { + std::thread worker(fn, arg); + worker.detach(); + }, []() { + chan.test_and_set(); + chan.notify_all(); + }); + EXPECT_FALSE(all_cases_available()); + chan.wait(false); + EXPECT_TRUE(all_cases_available()); + + chan.clear(); + all_cases_build_parallel_async([](void (*fn)(void*), void *arg) { + std::thread worker(fn, arg); + worker.detach(); + }, []() { + chan.test_and_set(); + chan.notify_all(); + }); + EXPECT_TRUE(all_cases_available()); + chan.wait(false); + EXPECT_TRUE(all_cases_available()); +} + +TEST(FFI, all_cases_num) { + EXPECT_LT(all_cases_num(-2), 0); + EXPECT_LT(all_cases_num(-1), 0); + for (int i = 0; i < 15; ++i) { + EXPECT_EQ(all_cases_num(i), ALL_CASES_NUM[i]); + } + EXPECT_LT(all_cases_num(16), 0); + EXPECT_LT(all_cases_num(17), 0); +} + +TEST(FFI, all_cases_export) { + EXPECT_EQ(all_cases_export(-2), nullptr); + EXPECT_EQ(all_cases_export(-1), nullptr); + EXPECT_EQ(all_cases_export(16), nullptr); + EXPECT_EQ(all_cases_export(17), nullptr); + + std::string all_cases_str; + for (uint64_t head = 0; head < 15; ++head) { + auto num = all_cases_num((int)head); + auto *ranges = all_cases_export((int)head); + for (auto i = 0; i < num; ++i) { + char *tmp; + asprintf(&tmp, "%09llX\n", head << 32 | ranges[i]); + all_cases_str += tmp; + } + } + EXPECT_EQ(md5sum(all_cases_str), ALL_CASES_MD5); +} diff --git a/third_party/third_party.cmake b/third_party/third_party.cmake index bb4804c..e512f2d 100644 --- a/third_party/third_party.cmake +++ b/third_party/third_party.cmake @@ -4,10 +4,10 @@ set(ABSL_PROPAGATE_CXX_STD ON) include_directories(abseil-cpp) add_subdirectory(${KLOTSKI_THIRD_PARTY}/abseil-cpp EXCLUDE_FROM_ALL) -#if (KLOTSKI_UNIT_TEST) -# include_directories(${KLOTSKI_THIRD_PARTY}/md5sum) -# add_subdirectory(${KLOTSKI_THIRD_PARTY}/md5sum EXCLUDE_FROM_ALL) -#endif (KLOTSKI_UNIT_TEST) +if (KLOTSKI_UNIT_TEST) + include_directories(${KLOTSKI_THIRD_PARTY}/md5sum) + add_subdirectory(${KLOTSKI_THIRD_PARTY}/md5sum EXCLUDE_FROM_ALL) +endif (KLOTSKI_UNIT_TEST) if (KLOTSKI_UNIT_TEST) include_directories(${KLOTSKI_THIRD_PARTY}/googletest/googletest/include)