-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
introduce limestone test-double for testing
- Loading branch information
1 parent
95a9fc4
commit 90de28e
Showing
4 changed files
with
263 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,85 @@ | ||
|
||
#include "concurrency_control/include/session.h" | ||
|
||
#include "gtest/gtest.h" | ||
#include "glog/logging.h" | ||
|
||
#include "test_tool.h" | ||
#include "doubles/limestone_double.h" | ||
|
||
namespace shirakami::testing { | ||
|
||
using namespace shirakami; | ||
|
||
class blob_mock_test : public ::testing::Test { | ||
public: | ||
static void call_once_f() { | ||
google::InitGoogleLogging("shirakami-test-test_double-blob_mock_test"); | ||
// FLAGS_stderrthreshold = 0; // output more than INFO | ||
} | ||
void SetUp() override { | ||
std::call_once(init_google_, call_once_f); | ||
init(); // NOLINT | ||
} | ||
|
||
void TearDown() override { | ||
fin(); | ||
test_double::log_channel_add_entry1::hook_func = nullptr; | ||
test_double::log_channel_add_entry2::hook_func = nullptr; | ||
test_double::datastore_switch_available_boundary_version::hook_func = nullptr; | ||
} | ||
|
||
private: | ||
static inline std::once_flag init_google_; | ||
}; | ||
|
||
TEST_F(blob_mock_test, insert_update_blob) { | ||
std::vector<std::pair<std::string, std::vector<limestone::api::blob_id_type>>> added; | ||
// prepare | ||
|
||
// test double | ||
test_double::log_channel_add_entry1::hook_func = [&added] ( | ||
[[maybe_unused]] test_double::log_channel_add_entry1::orig_type orig_func, | ||
[[maybe_unused]] limestone::api::log_channel* this_ptr, | ||
[[maybe_unused]] limestone::api::storage_id_type storage_id, | ||
[[maybe_unused]] std::string_view key, [[maybe_unused]] std::string_view value, | ||
[[maybe_unused]] limestone::api::write_version_type write_version) -> void { | ||
VLOG(40) << "add_entry 1 storage_id:" << storage_id << " key:" << key; | ||
added.emplace_back(key, std::vector<limestone::api::blob_id_type>{}); | ||
}; | ||
test_double::log_channel_add_entry2::hook_func = [&added] ( | ||
[[maybe_unused]] test_double::log_channel_add_entry2::orig_type orig_func, | ||
[[maybe_unused]] limestone::api::log_channel* this_ptr, | ||
[[maybe_unused]] limestone::api::storage_id_type storage_id, | ||
[[maybe_unused]] std::string_view key, [[maybe_unused]] std::string_view value, | ||
[[maybe_unused]] limestone::api::write_version_type write_version, | ||
[[maybe_unused]] const std::vector<limestone::api::blob_id_type>& large_objects) -> void { | ||
VLOG(40) << "add_entry 2 storage_id:" << storage_id << " key:" << key << shirakami_vecstring(large_objects); | ||
added.emplace_back(key, large_objects); | ||
}; | ||
|
||
Storage st{}; | ||
create_storage("", st); // N.B. create_storage may call add_entry | ||
Token s{}; | ||
ASSERT_OK(enter(s)); | ||
added.clear(); | ||
|
||
// test and verify | ||
ASSERT_EQ(added.size(), 0); | ||
ASSERT_OK(tx_begin({s, transaction_options::transaction_type::SHORT})); | ||
const blob_id_type b1[2] = {11, 22}; | ||
ASSERT_OK(insert(s, st, "k", "v", b1, 2)); | ||
const blob_id_type b2[3] = {99, 88, 77}; | ||
ASSERT_OK(update(s, st, "k", "v1", b2, 3)); | ||
ASSERT_OK(commit(s)); | ||
{ | ||
ASSERT_EQ(added.size(), 1); | ||
auto lobs = std::get<1>(added.at(0)); | ||
EXPECT_EQ(std::vector(std::begin(b2), std::end(b2)), lobs); | ||
} | ||
|
||
// cleanup | ||
ASSERT_OK(leave(s)); | ||
} | ||
|
||
} // namespace shirakami::testing |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,111 @@ | ||
#define _GNU_SOURCE 1 | ||
#include <dlfcn.h> | ||
|
||
#include "glog/logging.h" | ||
|
||
#include "limestone_double.h" | ||
|
||
#define EXTERN_C 1 | ||
|
||
namespace test_double::log_channel_add_entry1 { hook_type hook_func = nullptr; } | ||
namespace test_double::log_channel_add_entry2 { hook_type hook_func = nullptr; } | ||
namespace test_double::datastore_switch_available_boundary_version { hook_type hook_func = nullptr; } | ||
|
||
#if EXTERN_C == 0 | ||
|
||
namespace limestone::api { | ||
|
||
void log_channel::add_entry(storage_id_type storage_id, std::string_view key, std::string_view value, write_version_type write_version) { | ||
using namespace test_double::log_channel_add_entry1; | ||
static std::atomic<orig_type> orig_ptr{nullptr}; | ||
if (!orig_ptr) { | ||
orig_ptr = reinterpret_cast<orig_type>(dlsym(RTLD_NEXT, sym_name)); | ||
} | ||
LOG_IF(FATAL, !orig_ptr) << "dlsym " << sym_name << " failed"; | ||
if (hook_func) { | ||
return hook_func(orig_ptr.load(), this, storage_id, key, value, write_version); | ||
} else { | ||
return orig_ptr.load()(this, storage_id, key, value, write_version); | ||
} | ||
} | ||
|
||
void log_channel::add_entry(storage_id_type storage_id, std::string_view key, std::string_view value, write_version_type write_version, const std::vector<blob_id_type>& large_objects) { | ||
using namespace test_double::log_channel_add_entry2; | ||
static std::atomic<orig_type> orig_ptr{nullptr}; | ||
if (!orig_ptr) { | ||
orig_ptr = reinterpret_cast<orig_type>(dlsym(RTLD_NEXT, sym_name)); | ||
} | ||
LOG_IF(FATAL, !orig_ptr) << "dlsym " << sym_name << " failed"; | ||
if (hook_func) { | ||
return hook_func(orig_ptr.load(), this, storage_id, key, value, write_version, large_objects); | ||
} else { | ||
return orig_ptr.load()(this, storage_id, key, value, write_version, large_objects); | ||
} | ||
} | ||
|
||
void datastore::switch_available_boundary_version(write_version_type version) { | ||
using namespace test_double::datastore_switch_available_boundary_version; | ||
static std::atomic<orig_type> orig_ptr{nullptr}; | ||
if (!orig_ptr) { | ||
orig_ptr = reinterpret_cast<orig_type>(dlsym(RTLD_NEXT, sym_name)); | ||
} | ||
LOG_IF(FATAL, !orig_ptr) << "dlsym " << sym_name << " failed"; | ||
if (hook_func) { | ||
return hook_func(orig_ptr.load(), this, version); | ||
} else { | ||
return orig_ptr.load()(this, version); | ||
} | ||
} | ||
|
||
} | ||
|
||
#else | ||
|
||
extern "C" { | ||
|
||
void _ZN9limestone3api11log_channel9add_entryEmSt17basic_string_viewIcSt11char_traitsIcEES5_NS0_18write_version_typeE(limestone::api::log_channel* this_ptr, limestone::api::storage_id_type storage_id, std::string_view key, std::string_view value, limestone::api::write_version_type write_version) { | ||
using namespace test_double::log_channel_add_entry1; | ||
static std::atomic<orig_type> orig_ptr{nullptr}; | ||
if (!orig_ptr) { | ||
orig_ptr = reinterpret_cast<orig_type>(dlsym(RTLD_NEXT, sym_name)); | ||
} | ||
LOG_IF(FATAL, !orig_ptr) << "dlsym " << sym_name << " failed"; | ||
if (hook_func) { | ||
return hook_func(orig_ptr.load(), this_ptr, storage_id, key, value, write_version); | ||
} else { | ||
return orig_ptr.load()(this_ptr, storage_id, key, value, write_version); | ||
} | ||
} | ||
|
||
void _ZN9limestone3api11log_channel9add_entryEmSt17basic_string_viewIcSt11char_traitsIcEES5_NS0_18write_version_typeERKSt6vectorImSaImEE(limestone::api::log_channel* this_ptr, limestone::api::storage_id_type storage_id, std::string_view key, std::string_view value, limestone::api::write_version_type write_version, const std::vector<limestone::api::blob_id_type>& large_objects) { | ||
using namespace test_double::log_channel_add_entry2; | ||
static std::atomic<orig_type> orig_ptr{nullptr}; | ||
if (!orig_ptr) { | ||
orig_ptr = reinterpret_cast<orig_type>(dlsym(RTLD_NEXT, sym_name)); | ||
} | ||
LOG_IF(FATAL, !orig_ptr) << "dlsym " << sym_name << " failed"; | ||
if (hook_func) { | ||
return hook_func(orig_ptr.load(), this_ptr, storage_id, key, value, write_version, large_objects); | ||
} else { | ||
return orig_ptr.load()(this_ptr, storage_id, key, value, write_version, large_objects); | ||
} | ||
} | ||
|
||
void _ZN9limestone3api9datastore33switch_available_boundary_versionENS0_18write_version_typeE(limestone::api::datastore* this_ptr, limestone::api::write_version_type version) { | ||
using namespace test_double::datastore_switch_available_boundary_version; | ||
static std::atomic<orig_type> orig_ptr{nullptr}; | ||
if (!orig_ptr) { | ||
orig_ptr = reinterpret_cast<orig_type>(dlsym(RTLD_NEXT, sym_name)); | ||
} | ||
LOG_IF(FATAL, !orig_ptr) << "dlsym " << sym_name << " failed"; | ||
if (hook_func) { | ||
return hook_func(orig_ptr.load(), this_ptr, version); | ||
} else { | ||
return orig_ptr.load()(this_ptr, version); | ||
} | ||
} | ||
|
||
} | ||
#endif | ||
|
||
#undef EXTERN_C |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
#pragma once | ||
|
||
#include "limestone/api/write_version_type.h" | ||
#include "limestone/api/datastore.h" | ||
|
||
namespace test_double { | ||
|
||
// MEMBER_FUNC_DEF | ||
// nickname log_channel_add_entry1 | ||
// cppname void limestone::api::log_channel::add_entry(limestone::api::storage_id_type storage_id, std::string_view key, std::string_view value, limestone::api::write_version_type write_version) | ||
// cname _ZN9limestone3api11log_channel9add_entryEmSt17basic_string_viewIcSt11char_traitsIcEES5_NS0_18write_version_typeE | ||
namespace log_channel_add_entry1 { | ||
using orig_type = void(*)(limestone::api::log_channel*, limestone::api::storage_id_type storage_id, std::string_view key, std::string_view value, limestone::api::write_version_type write_version); | ||
using hook_type = std::function<void(orig_type orig_func, limestone::api::log_channel*, limestone::api::storage_id_type storage_id, std::string_view key, std::string_view value, limestone::api::write_version_type write_version)>; | ||
extern hook_type hook_func; | ||
constexpr const char sym_name[] = "_ZN9limestone3api11log_channel9add_entryEmSt17basic_string_viewIcSt11char_traitsIcEES5_NS0_18write_version_typeE"; | ||
} | ||
|
||
// MEMBER_FUNC_DEF | ||
// nickname log_channel_add_entry2 | ||
// cppname void limestone::api::log_channel::add_entry(limestone::api::storage_id_type storage_id, std::string_view key, std::string_view value, limestone::api::write_version_type write_version, const std::vector<limestone::api::blob_id_type>& large_objects) | ||
// cname _ZN9limestone3api11log_channel9add_entryEmSt17basic_string_viewIcSt11char_traitsIcEES5_NS0_18write_version_typeERKSt6vectorImSaImEE | ||
namespace log_channel_add_entry2 { | ||
using orig_type = void(*)(limestone::api::log_channel*, limestone::api::storage_id_type storage_id, std::string_view key, std::string_view value, limestone::api::write_version_type write_version, const std::vector<limestone::api::blob_id_type>& large_objects); | ||
using hook_type = std::function<void(orig_type orig_func, limestone::api::log_channel*, limestone::api::storage_id_type storage_id, std::string_view key, std::string_view value, limestone::api::write_version_type write_version, const std::vector<limestone::api::blob_id_type>& large_objects)>; | ||
extern hook_type hook_func; | ||
constexpr const char sym_name[] = "_ZN9limestone3api11log_channel9add_entryEmSt17basic_string_viewIcSt11char_traitsIcEES5_NS0_18write_version_typeERKSt6vectorImSaImEE"; | ||
} | ||
|
||
// MEMBER_FUNC_DEF | ||
// nickname datastore_switch_available_boundary_version | ||
// cppname void limestone::api::datastore::switch_available_boundary_version(limestone::api::write_version_type version) | ||
// cname _ZN9limestone3api9datastore33switch_available_boundary_versionENS0_18write_version_typeE | ||
namespace datastore_switch_available_boundary_version { | ||
using orig_type = void(*)(limestone::api::datastore*, limestone::api::write_version_type write_version); | ||
using hook_type = std::function<void(orig_type orig_func, limestone::api::datastore*, limestone::api::write_version_type write_version)>; | ||
extern hook_type hook_func; | ||
constexpr const char sym_name[] = "_ZN9limestone3api9datastore33switch_available_boundary_versionENS0_18write_version_typeE"; | ||
} | ||
|
||
} |