From 7d0862629ca769ee944aa0c100699bea7f4ffdef Mon Sep 17 00:00:00 2001 From: Alexey Ozeritskiy Date: Thu, 23 Nov 2023 17:26:21 +0300 Subject: [PATCH] Add tests --- CMakeLists.txt | 2 +- src/messages.h | 112 +++++++++++++++++++++++++++++++++++++++++++-- test/test_raft.cpp | 21 ++++++++- 3 files changed, 130 insertions(+), 5 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 55eab35..1269a05 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -18,7 +18,7 @@ add_library(miniraft add_executable(test_raft test/test_raft.cpp) -target_include_directories(test_raft PRIVATE ${CMOCKA_INCLUDE_DIRS}) +target_include_directories(test_raft PRIVATE ${CMOCKA_INCLUDE_DIRS} ${CMAKE_SOURCE_DIR}/src) target_link_directories(test_raft PRIVATE ${CMOCKA_LIBRARY_DIRS}) target_link_libraries(test_raft miniraft ${CMOCKA_LIBRARIES}) diff --git a/src/messages.h b/src/messages.h index 31fdf43..f0b2fb3 100644 --- a/src/messages.h +++ b/src/messages.h @@ -1,7 +1,113 @@ #pragma once +#include +#include -struct TLogEntry { - int Term = 1; - int Size = 0; +#include +#include + +enum class EMessageType : uint32_t { + NONE = 0, + LOG_ENTRY = 1, + REQUEST_VOTE_REQUEST = 2, +}; + +struct TMessage { + static constexpr EMessageType MessageType = EMessageType::NONE; + uint32_t Type; + uint32_t Len; + char Value[0]; +}; + +struct TLogEntry: public TMessage { + static constexpr EMessageType MessageType = EMessageType::LOG_ENTRY; + uint64_t Term = 1; char Data[0]; }; + +struct RequestVoteRequest: public TMessage { + static constexpr EMessageType MessageType = EMessageType::REQUEST_VOTE_REQUEST; + uint64_t Term; + uint64_t LastLogIndex; + uint64_t LastLogTerm; + uint32_t Src; + uint32_t Dst; + uint32_t CandidateId; +}; + +template +requires std::derived_from +struct TMessageHolder { + T* Mes; + std::shared_ptr RawData; + + template + requires std::derived_from + TMessageHolder(U* u, const std::shared_ptr& rawData) + : Mes(u) + , RawData(rawData) + { } + + template + requires std::derived_from + TMessageHolder(const TMessageHolder& other) + : Mes(other.Mes) + , RawData(other.RawData) + { } + + T* operator->() { + return Mes; + } + + template + requires std::derived_from + TMessageHolder Cast() { + return TMessageHolder(static_cast(Mes), RawData); + } + + template + requires std::derived_from + auto Maybe() { + struct Maybe { + U* Mes; + std::shared_ptr RawData; + + operator bool() const { + return Mes != nullptr; + } + + TMessageHolder Cast() { + if (Mes) { + return TMessageHolder(Mes, RawData); + } + throw std::bad_cast(); + } + }; + + U* dst = Mes->Type == static_cast(U::MessageType) + ? static_cast(dst) + : nullptr; + + return Maybe { + .Mes = dst, + .RawData = RawData + }; + } +}; + +template +requires std::derived_from +T* NewMessage(uint32_t type, uint32_t len) { + char* data = new char[len]; + T* mes = reinterpret_cast(data); + mes->Type = type; + mes->Len = len; + return mes; +} + +template +requires std::derived_from +TMessageHolder NewHoldedMessage(uint32_t type, uint32_t len) +{ + T* mes = NewMessage(type, len); + return TMessageHolder(mes, std::shared_ptr(reinterpret_cast(mes))); +} diff --git a/test/test_raft.cpp b/test/test_raft.cpp index 3784405..d60d47b 100644 --- a/test/test_raft.cpp +++ b/test/test_raft.cpp @@ -1,3 +1,5 @@ +#include + #include #include #include @@ -9,9 +11,26 @@ void test_empty(void** state) { } +void test_message_create(void** state) { + auto mes = NewHoldedMessage(0, 4); + assert_true(mes->Len == 4); + assert_true(mes->Type == 0); +} + +void test_message_cast(void** state) { + TMessageHolder mes = NewHoldedMessage(static_cast(TLogEntry::MessageType), 4); + auto casted = mes.Cast(); + assert_true(mes.RawData == casted.RawData); + + auto casted2 = mes.Maybe(); + assert_false(casted2); +} + int main() { const struct CMUnitTest tests[] = { cmocka_unit_test(test_empty), + cmocka_unit_test(test_message_create), + cmocka_unit_test(test_message_cast), }; - return 0; + return cmocka_run_group_tests(tests, NULL, NULL); }