1
0
Fork 0
mirror of https://github.com/KingDuckZ/incredis synced 2024-11-23 00:33:46 +00:00

Import catch and write a first integration test.

This commit is contained in:
King_DuckZ 2016-12-02 14:16:32 +00:00
parent 20edb06241
commit f74473bf07
8 changed files with 310 additions and 0 deletions

3
.gitmodules vendored
View file

@ -4,3 +4,6 @@
[submodule "lib/better-enums"]
path = lib/better-enums
url = https://github.com/aantron/better-enums.git
[submodule "lib/catch"]
path = lib/catch
url = https://github.com/philsquared/Catch.git

View file

@ -3,6 +3,7 @@ project(incredis CXX)
list (APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake/Modules)
include(shared_git_project)
include(CTest)
find_package(hiredis 0.11.0 REQUIRED)
find_package(CryptoPP 5.6)
@ -59,6 +60,7 @@ if (CryptoPP_FOUND)
else()
set (has_cryptopp_lib OFF)
endif()
set(INCREDIS_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}")
install(TARGETS ${PROJECT_NAME}
LIBRARY DESTINATION lib
@ -79,3 +81,7 @@ target_compile_features(${PROJECT_NAME}
PUBLIC cxx_noexcept
PUBLIC cxx_rvalue_references
)
if (BUILD_TESTING)
add_subdirectory(test/integration)
endif()

1
lib/catch Submodule

@ -0,0 +1 @@
Subproject commit 30cebd617788f6b399297725f97317f9bc462114

View file

@ -0,0 +1,52 @@
project(integration CXX)
find_package(Boost 1.53.0 REQUIRED COMPONENTS program_options)
set(INCREDIS_TEST_HOSTNAME "127.0.0.1" CACHE STRING "Hostname for the integration test to connect to")
set(INCREDIS_TEST_PORT "6379" CACHE STRING "Port on the host")
set(INCREDIS_TEST_SOCKET "" CACHE STRING "Socket name, leave empty to use hostname:port")
set(INCREDIS_TEST_DB "0" CACHE STRING "Number of the database to run the tests in - all data in it will be destroyed")
add_executable(${PROJECT_NAME}
main.cpp
redis_connection_fixture.cpp
test_insert_retrieve.cpp
)
target_include_directories(${PROJECT_NAME}
PRIVATE ${INCREDIS_SOURCE_DIR}/lib/catch/single_include
)
target_include_directories(${PROJECT_NAME} SYSTEM
PRIVATE ${Boost_INCLUDE_DIRS}
)
target_link_libraries(${PROJECT_NAME}
PRIVATE ${Boost_LIBRARIES}
PRIVATE incredis
)
if ("${INCREDIS_TEST_HOSTNAME}" STREQUAL "")
set(hostname_param "")
else()
set(hostname_param --hostname ${INCREDIS_TEST_HOSTNAME})
endif()
if ("${INCREDIS_TEST_PORT}" STREQUAL "")
set(port_param "")
else()
set(port_param --port ${INCREDIS_TEST_PORT})
endif()
if ("${INCREDIS_TEST_SOCKET}" STREQUAL "")
set(socket_param "")
else()
set(socket_param --socket ${INCREDIS_TEST_SOCKET})
endif()
if ("${INCREDIS_TEST_DB}" STREQUAL "")
set(db_param "")
else()
set(db_param --db ${INCREDIS_TEST_DB})
endif()
add_test(
NAME redis_integration
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
COMMAND ${PROJECT_NAME} ${hostname_param} ${port_param} ${socket_param} ${db_param}
)

95
test/integration/main.cpp Normal file
View file

@ -0,0 +1,95 @@
#define CATCH_CONFIG_RUNNER
#include "catch.hpp"
#include <boost/program_options.hpp>
#include <string>
#include <cstdint>
#include <algorithm>
#include <iterator>
#include <cassert>
#include <functional>
namespace po = boost::program_options;
namespace incredis {
namespace test {
std::string g_hostname = "127.0.0.1";
uint16_t g_port = 6379;
std::string g_socket = "";
uint32_t g_db = 0;
} //namespace test
} //namespace incredis
namespace {
const char* const unknown_options_key = "unknown_options";
void parse_commandline (int parArgc, const char* const* parArgv, po::variables_map& parVM) {
po::options_description connection_options("Redis connection options");
connection_options.add_options()
("hostname,h", po::value<std::string>(), "Server hostname")
("port,p", po::value<uint16_t>(), "Server port")
("socket,s", po::value<std::string>(), "Server socket (overrides hostname and port)")
("db,n", po::value<uint32_t>(), "Database number")
;
po::options_description positional_options("Catch test suite options");
positional_options.add_options()
(unknown_options_key, po::value<std::vector<std::string>>(), "List of options that will be passed to Catch")
;
po::options_description all("Available options");
all.add(connection_options).add(positional_options);
po::positional_options_description pd;
pd.add(unknown_options_key, -1);
po::store(po::command_line_parser(parArgc, parArgv).options(all).positional(pd).run(), parVM);
po::notify(parVM);
}
std::vector<const char*> stringlist_to_charlist (const std::vector<std::string>& parList) {
std::vector<const char*> retval;
retval.reserve(parList.size());
std::transform(parList.begin(), parList.end(), back_inserter(retval), std::bind(&std::string::c_str, std::placeholders::_1));
assert(parList.size() == retval.size());
return retval;
}
void set_global_connection_params (const po::variables_map& parVM) {
using namespace incredis::test;
if (parVM.count("hostname"))
g_hostname = parVM["hostname"].as<decltype(g_hostname)>();
if (parVM.count("port"))
g_port = parVM["port"].as<decltype(g_port)>();
if (parVM.count("socket"))
g_socket = parVM["socket"].as<decltype(g_socket)>();
if (parVM.count("db"))
g_db = parVM["db"].as<decltype(g_db)>();
}
} //unnamed namespace
int main (int parArgc, char* const parArgv[]) {
po::variables_map vm;
parse_commandline(parArgc, parArgv, vm);
const std::vector<std::string> unparsed_params_str(
vm.count(unknown_options_key) ?
vm[unknown_options_key].as<std::vector<std::string>>() :
std::vector<std::string>()
);
std::vector<const char*> unparsed_params =
stringlist_to_charlist(unparsed_params_str);
assert(parArgc);
unparsed_params.insert(unparsed_params.begin(), parArgv[0]);
//bleah
set_global_connection_params(vm);
Catch::Session session;
const int retcode = session.applyCommandLine(unparsed_params.size(), unparsed_params.data());
if (0 != retcode)
return retcode;
return session.run();
}

View file

@ -0,0 +1,44 @@
#include "redis_connection_fixture.hpp"
#include "catch.hpp"
#include "incredis/incredis.hpp"
#include <ciso646>
namespace incredis {
namespace test {
extern std::string g_hostname;
extern uint16_t g_port;
extern std::string g_socket;
extern uint32_t g_db;
RedisConnectionFixture::RedisConnectionFixture() :
m_hostname(g_hostname),
m_socket(g_socket),
m_db(g_db),
m_port(g_port)
{
if (use_socket_connection())
m_incredis.reset(new redis::IncRedis(std::string(m_socket)));
else
m_incredis.reset(new redis::IncRedis(std::string(m_hostname), m_port));
m_incredis->connect();
m_incredis->wait_for_connect();
REQUIRE_FALSE(not m_incredis->is_connected());
auto batch = m_incredis->make_batch();
batch.select(m_db);
batch.client_setname("IncredisIntegrationTest");
batch.script_flush();
REQUIRE_NOTHROW(batch.throw_if_failed());
}
RedisConnectionFixture::~RedisConnectionFixture() noexcept = default;
bool RedisConnectionFixture::use_socket_connection() const {
return not m_socket.empty();
}
redis::IncRedis& RedisConnectionFixture::incredis() {
return *m_incredis;
}
} //namespace test
} //namespace incredis

View file

@ -0,0 +1,28 @@
#include <cstdint>
#include <string>
#include <memory>
namespace redis {
class IncRedis;
} //namespace redis
namespace incredis {
namespace test {
class RedisConnectionFixture {
public:
RedisConnectionFixture();
~RedisConnectionFixture() noexcept;
redis::IncRedis& incredis();
private:
bool use_socket_connection() const;
std::unique_ptr<redis::IncRedis> m_incredis;
std::string m_hostname;
std::string m_socket;
uint32_t m_db;
uint16_t m_port;
};
} //namespace test
} //namespac incredis

View file

@ -0,0 +1,81 @@
#include "redis_connection_fixture.hpp"
#include "catch.hpp"
#include "incredis/incredis.hpp"
#include <unordered_map>
#include <string>
using incredis::test::RedisConnectionFixture;
TEST_CASE_METHOD(RedisConnectionFixture, "Batch insert elements in the db and expect to be able to read the same values back", "[set][get]") {
using redis::IncRedisBatch;
REQUIRE_FALSE(not incredis().flushdb());
REQUIRE(incredis().dbsize() == 0);
auto batch = incredis().make_batch();
const std::unordered_map<std::string, std::string> sample_values {
{"個人と対話", "プロセスやツール"},
{"動くソフトウェア", "包括的なドキュメント"},
{"顧客との協調", "契約交渉"},
{"変化への対応", "計画に従うこと"},
{"erase", "erases elements"},
{"swap", "swaps the contents"},
{"extract", "extracts nodes from the container"},
{"merge", "splices nodes from another container"}
};
for (auto& value : sample_values) {
batch.set(value.first, value.second, IncRedisBatch::ADD_NX);
}
REQUIRE_NOTHROW(batch.throw_if_failed());
REQUIRE(incredis().dbsize() == static_cast<redis::RedisInt>(sample_values.size()));
{
redis::RedisInt scanned_items = 0;
for (auto& key : incredis().scan()) {
REQUIRE(sample_values.count(key) == 1);
redis::IncRedis::opt_string value = incredis().get(key);
REQUIRE_FALSE(not value);
REQUIRE(*value == sample_values.at(key));
++scanned_items;
}
REQUIRE(static_cast<redis::RedisInt>(sample_values.size()) == scanned_items);
}
}
TEST_CASE_METHOD(RedisConnectionFixture, "Insert elements in the db and expect to be able to read the same values back", "[set][get]") {
using redis::IncRedisBatch;
REQUIRE_FALSE(not incredis().flushdb());
REQUIRE(incredis().dbsize() == 0);
incredis().set("個人と対話", "プロセスやツール");
incredis().set("動くソフトウェア", "包括的なドキュメント");
incredis().set("顧客との協調", "契約交渉");
incredis().set("変化への対応", "計画に従うこと");
incredis().set("erase", "erases elements");
incredis().set("swap", "swaps the contents");
incredis().set("extract", "extracts nodes from the container");
incredis().set("merge", "splices nodes from another container");
REQUIRE(incredis().dbsize() == 8);
REQUIRE_FALSE(not incredis().get("個人と対話"));
REQUIRE_FALSE(not incredis().get("動くソフトウェア"));
REQUIRE_FALSE(not incredis().get("顧客との協調"));
REQUIRE_FALSE(not incredis().get("変化への対応"));
REQUIRE_FALSE(not incredis().get("erase"));
REQUIRE_FALSE(not incredis().get("swap"));
REQUIRE_FALSE(not incredis().get("extract"));
REQUIRE_FALSE(not incredis().get("merge"));
REQUIRE(*incredis().get("個人と対話") == "プロセスやツール");
REQUIRE(*incredis().get("動くソフトウェア") == "包括的なドキュメント");
REQUIRE(*incredis().get("顧客との協調") == "契約交渉");
REQUIRE(*incredis().get("変化への対応") == "計画に従うこと");
REQUIRE(*incredis().get("erase") == "erases elements");
REQUIRE(*incredis().get("swap") == "swaps the contents");
REQUIRE(*incredis().get("extract") == "extracts nodes from the container");
REQUIRE(*incredis().get("merge") == "splices nodes from another container");
}