From f1864148c4a091afd63be75bc1ff14ae93383523 Mon Sep 17 00:00:00 2001 From: Vasil Dimov Date: Fri, 6 Sep 2024 11:16:50 +0200 Subject: [PATCH] test: put the generic parts from StaticContentsSock into a separate class This allows reusing them in other mocked implementations. --- src/test/util/net.cpp | 91 ++++++++++++++++++++++++------------------- src/test/util/net.h | 40 ++++++++++++++----- 2 files changed, 83 insertions(+), 48 deletions(-) diff --git a/src/test/util/net.cpp b/src/test/util/net.cpp index 0861c2cc09b..77ce3b7585d 100644 --- a/src/test/util/net.cpp +++ b/src/test/util/net.cpp @@ -138,38 +138,31 @@ std::vector GetRandomNodeEvictionCandidates(int n_candida return candidates; } -StaticContentsSock::StaticContentsSock(const std::string& contents) - : Sock{INVALID_SOCKET}, m_contents{contents} +// Have different ZeroSock (or others that inherit from it) objects have different +// m_socket because EqualSharedPtrSock compares m_socket and we want to avoid two +// different objects comparing as equal. +static std::atomic g_mocked_sock_fd{0}; + +ZeroSock::ZeroSock() : Sock{g_mocked_sock_fd++} {} + +// Sock::~Sock() would try to close(2) m_socket if it is not INVALID_SOCKET, avoid that. +ZeroSock::~ZeroSock() { m_socket = INVALID_SOCKET; } + +ssize_t ZeroSock::Send(const void*, size_t len, int) const { return len; } + +ssize_t ZeroSock::Recv(void* buf, size_t len, int flags) const { + memset(buf, 0x0, len); + return len; } -StaticContentsSock::~StaticContentsSock() { m_socket = INVALID_SOCKET; } +int ZeroSock::Connect(const sockaddr*, socklen_t) const { return 0; } -StaticContentsSock& StaticContentsSock::operator=(Sock&& other) -{ - assert(false && "Move of Sock into MockSock not allowed."); - return *this; -} +int ZeroSock::Bind(const sockaddr*, socklen_t) const { return 0; } -ssize_t StaticContentsSock::Send(const void*, size_t len, int) const { return len; } +int ZeroSock::Listen(int) const { return 0; } -ssize_t StaticContentsSock::Recv(void* buf, size_t len, int flags) const -{ - const size_t consume_bytes{std::min(len, m_contents.size() - m_consumed)}; - std::memcpy(buf, m_contents.data() + m_consumed, consume_bytes); - if ((flags & MSG_PEEK) == 0) { - m_consumed += consume_bytes; - } - return consume_bytes; -} - -int StaticContentsSock::Connect(const sockaddr*, socklen_t) const { return 0; } - -int StaticContentsSock::Bind(const sockaddr*, socklen_t) const { return 0; } - -int StaticContentsSock::Listen(int) const { return 0; } - -std::unique_ptr StaticContentsSock::Accept(sockaddr* addr, socklen_t* addr_len) const +std::unique_ptr ZeroSock::Accept(sockaddr* addr, socklen_t* addr_len) const { if (addr != nullptr) { // Pretend all connections come from 5.5.5.5:6789 @@ -183,30 +176,28 @@ std::unique_ptr StaticContentsSock::Accept(sockaddr* addr, socklen_t* addr addr_in->sin_port = htons(6789); } } - return std::make_unique(""); -}; + return std::make_unique(); +} -int StaticContentsSock::GetSockOpt(int level, int opt_name, void* opt_val, socklen_t* opt_len) const +int ZeroSock::GetSockOpt(int level, int opt_name, void* opt_val, socklen_t* opt_len) const { std::memset(opt_val, 0x0, *opt_len); return 0; } -int StaticContentsSock::SetSockOpt(int, int, const void*, socklen_t) const { return 0; } +int ZeroSock::SetSockOpt(int, int, const void*, socklen_t) const { return 0; } -int StaticContentsSock::GetSockName(sockaddr* name, socklen_t* name_len) const +int ZeroSock::GetSockName(sockaddr* name, socklen_t* name_len) const { std::memset(name, 0x0, *name_len); return 0; } -bool StaticContentsSock::SetNonBlocking() const { return true; } +bool ZeroSock::SetNonBlocking() const { return true; } -bool StaticContentsSock::IsSelectable() const { return true; } +bool ZeroSock::IsSelectable() const { return true; } -bool StaticContentsSock::Wait(std::chrono::milliseconds timeout, - Event requested, - Event* occurred) const +bool ZeroSock::Wait(std::chrono::milliseconds timeout, Event requested, Event* occurred) const { if (occurred != nullptr) { *occurred = requested; @@ -214,7 +205,7 @@ bool StaticContentsSock::Wait(std::chrono::milliseconds timeout, return true; } -bool StaticContentsSock::WaitMany(std::chrono::milliseconds timeout, EventsPerSock& events_per_sock) const +bool ZeroSock::WaitMany(std::chrono::milliseconds timeout, EventsPerSock& events_per_sock) const { for (auto& [sock, events] : events_per_sock) { (void)sock; @@ -223,7 +214,29 @@ bool StaticContentsSock::WaitMany(std::chrono::milliseconds timeout, EventsPerSo return true; } -bool StaticContentsSock::IsConnected(std::string&) const +ZeroSock& ZeroSock::operator=(Sock&& other) { - return true; + assert(false && "Move of Sock into ZeroSock not allowed."); + return *this; +} + +StaticContentsSock::StaticContentsSock(const std::string& contents) + : m_contents{contents} +{ +} + +ssize_t StaticContentsSock::Recv(void* buf, size_t len, int flags) const +{ + const size_t consume_bytes{std::min(len, m_contents.size() - m_consumed)}; + std::memcpy(buf, m_contents.data() + m_consumed, consume_bytes); + if ((flags & MSG_PEEK) == 0) { + m_consumed += consume_bytes; + } + return consume_bytes; +} + +StaticContentsSock& StaticContentsSock::operator=(Sock&& other) +{ + assert(false && "Move of Sock into StaticContentsSock not allowed."); + return *this; } diff --git a/src/test/util/net.h b/src/test/util/net.h index 9397dbad3d7..20b70cc4544 100644 --- a/src/test/util/net.h +++ b/src/test/util/net.h @@ -134,18 +134,15 @@ constexpr auto ALL_NETWORKS = std::array{ }; /** - * A mocked Sock alternative that returns a statically contained data upon read and succeeds - * and ignores all writes. The data to be returned is given to the constructor and when it is - * exhausted an EOF is returned by further reads. + * A mocked Sock alternative that succeeds on all operations. + * Returns infinite amount of 0x0 bytes on reads. */ -class StaticContentsSock : public Sock +class ZeroSock : public Sock { public: - explicit StaticContentsSock(const std::string& contents); + ZeroSock(); - ~StaticContentsSock() override; - - StaticContentsSock& operator=(Sock&& other) override; + ~ZeroSock() override; ssize_t Send(const void*, size_t len, int) const override; @@ -175,9 +172,34 @@ public: bool WaitMany(std::chrono::milliseconds timeout, EventsPerSock& events_per_sock) const override; - bool IsConnected(std::string&) const override; +private: + ZeroSock& operator=(Sock&& other) override; +}; + +/** + * A mocked Sock alternative that returns a statically contained data upon read and succeeds + * and ignores all writes. The data to be returned is given to the constructor and when it is + * exhausted an EOF is returned by further reads. + */ +class StaticContentsSock : public ZeroSock +{ +public: + explicit StaticContentsSock(const std::string& contents); + + /** + * Return parts of the contents that was provided at construction until it is exhausted + * and then return 0 (EOF). + */ + ssize_t Recv(void* buf, size_t len, int flags) const override; + + bool IsConnected(std::string&) const override + { + return true; + } private: + StaticContentsSock& operator=(Sock&& other) override; + const std::string m_contents; mutable size_t m_consumed{0}; };