monero/tests/unit_tests/zmq_rpc.cpp
Kevin Barbour 85db1734e7
Remove unused variables in monero codebase
There are quite a few variables in the code that are no longer
(or perhaps never were) in use. These were discovered by enabling
compiler warnings for unused variables and cleaning them up.

In most cases where the unused variables were the result
of a function call the call was left but the variable
assignment removed, unless it was obvious that it was
a simple getter with no side effects.
2021-02-09 08:05:05 +01:00

776 lines
25 KiB
C++

// Copyright (c) 2020, The Monero Project
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without modification, are
// permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this list of
// conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
// of conditions and the following disclaimer in the documentation and/or other
// materials provided with the distribution.
//
// 3. Neither the name of the copyright holder nor the names of its contributors may be
// used to endorse or promote products derived from this software without specific
// prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <boost/preprocessor/stringize.hpp>
#include <gtest/gtest.h>
#include <rapidjson/document.h>
#include "cryptonote_basic/account.h"
#include "cryptonote_basic/cryptonote_basic.h"
#include "cryptonote_basic/events.h"
#include "cryptonote_basic/cryptonote_format_utils.h"
#include "json_serialization.h"
#include "net/zmq.h"
#include "rpc/message.h"
#include "rpc/zmq_pub.h"
#include "rpc/zmq_server.h"
#include "serialization/json_object.h"
#define MASSERT(...) \
if (!(__VA_ARGS__)) \
return testing::AssertionFailure() << BOOST_PP_STRINGIZE(__VA_ARGS__)
TEST(ZmqFullMessage, InvalidRequest)
{
EXPECT_THROW(
(cryptonote::rpc::FullMessage{"{\"jsonrpc\":\"2.0\",\"id\":0,\"params\":[]}", true}),
cryptonote::json::MISSING_KEY
);
EXPECT_THROW(
(cryptonote::rpc::FullMessage{"{\"jsonrpc\":\"2.0\",\"id\":0,\"method\":3,\"params\":[]}", true}),
cryptonote::json::WRONG_TYPE
);
}
TEST(ZmqFullMessage, Request)
{
static constexpr const char request[] = "{\"jsonrpc\":\"2.0\",\"id\":0,\"method\":\"foo\",\"params\":[]}";
EXPECT_NO_THROW(
(cryptonote::rpc::FullMessage{request, true})
);
cryptonote::rpc::FullMessage parsed{request, true};
EXPECT_STREQ("foo", parsed.getRequestType().c_str());
}
namespace
{
using published_json = std::pair<std::string, rapidjson::Document>;
constexpr const char inproc_pub[] = "inproc://dummy_pub";
net::zmq::socket create_socket(void* ctx, const char* address)
{
net::zmq::socket sock{zmq_socket(ctx, ZMQ_PAIR)};
if (!sock)
MONERO_ZMQ_THROW("failed to create socket");
if (zmq_bind(sock.get(), address) != 0)
MONERO_ZMQ_THROW("socket bind failure");
return sock;
}
std::vector<std::string> get_messages(void* socket, int count = -1)
{
std::vector<std::string> out;
for ( ; count || count < 0; --count)
{
expect<std::string> next = net::zmq::receive(socket, (count < 0 ? ZMQ_DONTWAIT : 0));
if (next == net::zmq::make_error_code(EAGAIN))
return out;
out.push_back(std::move(*next));
}
return out;
}
std::vector<published_json> get_published(void* socket, int count = -1)
{
std::vector<published_json> out;
const auto messages = get_messages(socket, count);
out.reserve(messages.size());
for (const std::string& message : messages)
{
const char* split = std::strchr(message.c_str(), ':');
if (!split)
throw std::runtime_error{"Invalid ZMQ/Pub message"};
out.emplace_back();
out.back().first = {message.c_str(), split};
if (out.back().second.Parse(split + 1).HasParseError())
throw std::runtime_error{"Failed to parse ZMQ/Pub message"};
}
return out;
}
testing::AssertionResult compare_full_txpool(epee::span<const cryptonote::txpool_event> events, const published_json& pub)
{
MASSERT(pub.first == "json-full-txpool_add");
MASSERT(pub.second.IsArray());
MASSERT(pub.second.Size() <= events.size());
std::size_t i = 0;
for (const cryptonote::txpool_event& event : events)
{
MASSERT(i <= pub.second.Size());
if (!event.res)
continue;
cryptonote::transaction tx{};
cryptonote::json::fromJsonValue(pub.second[i], tx);
crypto::hash id{};
MASSERT(cryptonote::get_transaction_hash(event.tx, id));
MASSERT(cryptonote::get_transaction_hash(tx, id));
MASSERT(event.tx.hash == tx.hash);
++i;
}
return testing::AssertionSuccess();
}
testing::AssertionResult compare_minimal_txpool(epee::span<const cryptonote::txpool_event> events, const published_json& pub)
{
MASSERT(pub.first == "json-minimal-txpool_add");
MASSERT(pub.second.IsArray());
MASSERT(pub.second.Size() <= events.size());
std::size_t i = 0;
for (const cryptonote::txpool_event& event : events)
{
MASSERT(i <= pub.second.Size());
if (!event.res)
continue;
std::size_t actual_size = 0;
crypto::hash actual_id{};
MASSERT(pub.second[i].IsObject());
GET_FROM_JSON_OBJECT(pub.second[i], actual_id, id);
GET_FROM_JSON_OBJECT(pub.second[i], actual_size, blob_size);
std::size_t expected_size = 0;
crypto::hash expected_id{};
MASSERT(cryptonote::get_transaction_hash(event.tx, expected_id, expected_size));
MASSERT(expected_size == actual_size);
MASSERT(expected_id == actual_id);
++i;
}
return testing::AssertionSuccess();
}
testing::AssertionResult compare_full_block(const epee::span<const cryptonote::block> expected, const published_json& pub)
{
MASSERT(pub.first == "json-full-chain_main");
MASSERT(pub.second.IsArray());
std::vector<cryptonote::block> actual;
cryptonote::json::fromJsonValue(pub.second, actual);
MASSERT(expected.size() == actual.size());
for (std::size_t i = 0; i < expected.size(); ++i)
{
crypto::hash id;
MASSERT(cryptonote::get_block_hash(expected[i], id));
MASSERT(cryptonote::get_block_hash(actual[i], id));
MASSERT(expected[i].hash == actual[i].hash);
}
return testing::AssertionSuccess();
}
testing::AssertionResult compare_minimal_block(std::size_t height, const epee::span<const cryptonote::block> expected, const published_json& pub)
{
MASSERT(pub.first == "json-minimal-chain_main");
MASSERT(pub.second.IsObject());
MASSERT(!expected.empty());
std::size_t actual_height = 0;
crypto::hash actual_prev_id{};
std::vector<crypto::hash> actual_ids{};
GET_FROM_JSON_OBJECT(pub.second, actual_height, first_height);
GET_FROM_JSON_OBJECT(pub.second, actual_prev_id, first_prev_id);
GET_FROM_JSON_OBJECT(pub.second, actual_ids, ids);
MASSERT(height == actual_height);
MASSERT(expected[0].prev_id == actual_prev_id);
MASSERT(expected.size() == actual_ids.size());
for (std::size_t i = 0; i < expected.size(); ++i)
{
crypto::hash id;
MASSERT(cryptonote::get_block_hash(expected[i], id));
MASSERT(id == actual_ids[i]);
}
return testing::AssertionSuccess();
}
struct zmq_base : public testing::Test
{
cryptonote::account_base acct;
zmq_base()
: testing::Test(), acct()
{
acct.generate();
}
cryptonote::transaction make_miner_transaction()
{
return test::make_miner_transaction(acct.get_keys().m_account_address);
}
cryptonote::transaction make_transaction(const std::vector<cryptonote::account_public_address>& destinations)
{
return test::make_transaction(acct.get_keys(), {make_miner_transaction()}, destinations, true, true);
}
cryptonote::transaction make_transaction()
{
cryptonote::account_base temp_account;
temp_account.generate();
return make_transaction({temp_account.get_keys().m_account_address});
}
cryptonote::block make_block()
{
cryptonote::block block{};
block.major_version = 1;
block.minor_version = 3;
block.timestamp = 100;
block.prev_id = crypto::rand<crypto::hash>();
block.nonce = 100;
block.miner_tx = make_miner_transaction();
return block;
}
};
struct zmq_pub : public zmq_base
{
net::zmq::context ctx;
net::zmq::socket relay;
net::zmq::socket dummy_pub;
net::zmq::socket dummy_client;
std::shared_ptr<cryptonote::listener::zmq_pub> pub;
zmq_pub()
: zmq_base(),
ctx(zmq_init(1)),
relay(create_socket(ctx.get(), cryptonote::listener::zmq_pub::relay_endpoint())),
dummy_pub(create_socket(ctx.get(), inproc_pub)),
dummy_client(zmq_socket(ctx.get(), ZMQ_PAIR)),
pub(std::make_shared<cryptonote::listener::zmq_pub>(ctx.get()))
{
if (!dummy_client)
MONERO_ZMQ_THROW("failed to create socket");
if (zmq_connect(dummy_client.get(), inproc_pub) != 0)
MONERO_ZMQ_THROW("failed to connect to dummy pub");
}
virtual void TearDown() override final
{
EXPECT_EQ(0u, get_messages(relay.get()).size());
EXPECT_EQ(0u, get_messages(dummy_client.get()).size());
}
template<std::size_t N>
bool sub_request(const char (&topic)[N])
{
return pub->sub_request({topic, N - 1});
}
};
struct dummy_handler final : cryptonote::rpc::RpcHandler
{
dummy_handler()
: cryptonote::rpc::RpcHandler()
{}
virtual epee::byte_slice handle(std::string&& request) override final
{
throw std::logic_error{"not implemented"};
}
};
struct zmq_server : public zmq_base
{
dummy_handler handler;
cryptonote::rpc::ZmqServer server;
std::shared_ptr<cryptonote::listener::zmq_pub> pub;
net::zmq::socket sub;
zmq_server()
: zmq_base(),
handler(),
server(handler),
pub(),
sub()
{
void* ctx = server.init_rpc({}, {});
if (!ctx)
throw std::runtime_error{"init_rpc failure"};
const std::string endpoint = inproc_pub;
pub = server.init_pub({std::addressof(endpoint), 1});
if (!pub)
throw std::runtime_error{"failed to initiaze zmq/pub"};
sub.reset(zmq_socket(ctx, ZMQ_SUB));
if (!sub)
MONERO_ZMQ_THROW("failed to create socket");
if (zmq_connect(sub.get(), inproc_pub) != 0)
MONERO_ZMQ_THROW("failed to connect to dummy pub");
server.run();
}
virtual void TearDown() override final
{
EXPECT_EQ(0u, get_messages(sub.get()).size());
sub.reset();
pub.reset();
server.stop();
}
template<std::size_t N>
void subscribe(const char (&topic)[N])
{
if (zmq_setsockopt(sub.get(), ZMQ_SUBSCRIBE, topic, N - 1) != 0)
MONERO_ZMQ_THROW("failed to subscribe");
}
};
}
TEST_F(zmq_pub, InvalidContext)
{
EXPECT_THROW(cryptonote::listener::zmq_pub{nullptr}, std::logic_error);
}
TEST_F(zmq_pub, NoBlocking)
{
EXPECT_FALSE(pub->relay_to_pub(relay.get(), dummy_pub.get()));
}
TEST_F(zmq_pub, DefaultDrop)
{
EXPECT_EQ(0u, pub->send_txpool_add({{make_transaction(), {}, true}}));
const cryptonote::block bl = make_block();
EXPECT_EQ(0u,pub->send_chain_main(5, {std::addressof(bl), 1}));
EXPECT_NO_THROW(cryptonote::listener::zmq_pub::chain_main{pub}(5, {std::addressof(bl), 1}));
}
TEST_F(zmq_pub, JsonFullTxpool)
{
static constexpr const char topic[] = "\1json-full-txpool_add";
ASSERT_TRUE(sub_request(topic));
std::vector<cryptonote::txpool_event> events
{
{make_transaction(), {}, true}, {make_transaction(), {}, true}
};
EXPECT_NO_THROW(pub->send_txpool_add(events));
EXPECT_TRUE(pub->relay_to_pub(relay.get(), dummy_pub.get()));
auto pubs = get_published(dummy_client.get());
EXPECT_EQ(1u, pubs.size());
ASSERT_LE(1u, pubs.size());
EXPECT_TRUE(compare_full_txpool(epee::to_span(events), pubs.front()));
EXPECT_NO_THROW(cryptonote::listener::zmq_pub::txpool_add{pub}(events));
EXPECT_TRUE(pub->relay_to_pub(relay.get(), dummy_pub.get()));
pubs = get_published(dummy_client.get());
EXPECT_EQ(1u, pubs.size());
ASSERT_LE(1u, pubs.size());
EXPECT_TRUE(compare_full_txpool(epee::to_span(events), pubs.front()));
events.at(0).res = false;
EXPECT_EQ(1u, pub->send_txpool_add(events));
EXPECT_TRUE(pub->relay_to_pub(relay.get(), dummy_pub.get()));
pubs = get_published(dummy_client.get());
EXPECT_EQ(1u, pubs.size());
ASSERT_LE(1u, pubs.size());
EXPECT_TRUE(compare_full_txpool(epee::to_span(events), pubs.front()));
events.at(0).res = false;
EXPECT_NO_THROW(cryptonote::listener::zmq_pub::txpool_add{pub}(events));
EXPECT_TRUE(pub->relay_to_pub(relay.get(), dummy_pub.get()));
pubs = get_published(dummy_client.get());
EXPECT_EQ(1u, pubs.size());
ASSERT_LE(1u, pubs.size());
EXPECT_TRUE(compare_full_txpool(epee::to_span(events), pubs.front()));
}
TEST_F(zmq_pub, JsonMinimalTxpool)
{
static constexpr const char topic[] = "\1json-minimal-txpool_add";
ASSERT_TRUE(sub_request(topic));
std::vector<cryptonote::txpool_event> events
{
{make_transaction(), {}, true}, {make_transaction(), {}, true}
};
EXPECT_NO_THROW(pub->send_txpool_add(events));
EXPECT_TRUE(pub->relay_to_pub(relay.get(), dummy_pub.get()));
auto pubs = get_published(dummy_client.get());
EXPECT_EQ(1u, pubs.size());
ASSERT_LE(1u, pubs.size());
EXPECT_TRUE(compare_minimal_txpool(epee::to_span(events), pubs.front()));
EXPECT_NO_THROW(cryptonote::listener::zmq_pub::txpool_add{pub}(events));
EXPECT_TRUE(pub->relay_to_pub(relay.get(), dummy_pub.get()));
pubs = get_published(dummy_client.get());
EXPECT_EQ(1u, pubs.size());
ASSERT_LE(1u, pubs.size());
EXPECT_TRUE(compare_minimal_txpool(epee::to_span(events), pubs.front()));
events.at(0).res = false;
EXPECT_EQ(1u, pub->send_txpool_add(events));
EXPECT_TRUE(pub->relay_to_pub(relay.get(), dummy_pub.get()));
pubs = get_published(dummy_client.get());
EXPECT_EQ(1u, pubs.size());
ASSERT_LE(1u, pubs.size());
EXPECT_TRUE(compare_minimal_txpool(epee::to_span(events), pubs.front()));
events.at(0).res = false;
EXPECT_NO_THROW(cryptonote::listener::zmq_pub::txpool_add{pub}(events));
EXPECT_TRUE(pub->relay_to_pub(relay.get(), dummy_pub.get()));
pubs = get_published(dummy_client.get());
EXPECT_EQ(1u, pubs.size());
ASSERT_LE(1u, pubs.size());
EXPECT_TRUE(compare_minimal_txpool(epee::to_span(events), pubs.front()));
}
TEST_F(zmq_pub, JsonFullChain)
{
static constexpr const char topic[] = "\1json-full-chain_main";
ASSERT_TRUE(sub_request(topic));
const std::array<cryptonote::block, 2> blocks{{make_block(), make_block()}};
EXPECT_EQ(1u, pub->send_chain_main(100, epee::to_span(blocks)));
EXPECT_TRUE(pub->relay_to_pub(relay.get(), dummy_pub.get()));
auto pubs = get_published(dummy_client.get());
EXPECT_EQ(1u, pubs.size());
ASSERT_LE(1u, pubs.size());
EXPECT_TRUE(compare_full_block(epee::to_span(blocks), pubs.front()));
EXPECT_NO_THROW(cryptonote::listener::zmq_pub::chain_main{pub}(533, epee::to_span(blocks)));
EXPECT_TRUE(pub->relay_to_pub(relay.get(), dummy_pub.get()));
pubs = get_published(dummy_client.get());
EXPECT_EQ(1u, pubs.size());
ASSERT_LE(1u, pubs.size());
EXPECT_TRUE(compare_full_block(epee::to_span(blocks), pubs.front()));
}
TEST_F(zmq_pub, JsonMinimalChain)
{
static constexpr const char topic[] = "\1json-minimal-chain_main";
ASSERT_TRUE(sub_request(topic));
const std::array<cryptonote::block, 2> blocks{{make_block(), make_block()}};
EXPECT_EQ(1u, pub->send_chain_main(100, epee::to_span(blocks)));
EXPECT_TRUE(pub->relay_to_pub(relay.get(), dummy_pub.get()));
auto pubs = get_published(dummy_client.get());
EXPECT_EQ(1u, pubs.size());
ASSERT_LE(1u, pubs.size());
EXPECT_TRUE(compare_minimal_block(100, epee::to_span(blocks), pubs.front()));
EXPECT_NO_THROW(cryptonote::listener::zmq_pub::chain_main{pub}(533, epee::to_span(blocks)));
EXPECT_TRUE(pub->relay_to_pub(relay.get(), dummy_pub.get()));
pubs = get_published(dummy_client.get());
EXPECT_EQ(1u, pubs.size());
ASSERT_LE(1u, pubs.size());
EXPECT_TRUE(compare_minimal_block(533, epee::to_span(blocks), pubs.front()));
}
TEST_F(zmq_pub, JsonFullAll)
{
static constexpr const char topic[] = "\1json-full";
ASSERT_TRUE(sub_request(topic));
{
std::vector<cryptonote::txpool_event> events
{
{make_transaction(), {}, true}, {make_transaction(), {}, true}
};
EXPECT_EQ(1u, pub->send_txpool_add(events));
EXPECT_TRUE(pub->relay_to_pub(relay.get(), dummy_pub.get()));
auto pubs = get_published(dummy_client.get());
EXPECT_EQ(1u, pubs.size());
ASSERT_LE(1u, pubs.size());
EXPECT_TRUE(compare_full_txpool(epee::to_span(events), pubs.front()));
EXPECT_NO_THROW(cryptonote::listener::zmq_pub::txpool_add{pub}(events));
EXPECT_TRUE(pub->relay_to_pub(relay.get(), dummy_pub.get()));
pubs = get_published(dummy_client.get());
EXPECT_EQ(1u, pubs.size());
ASSERT_LE(1u, pubs.size());
EXPECT_TRUE(compare_full_txpool(epee::to_span(events), pubs.front()));
events.at(0).res = false;
EXPECT_NO_THROW(pub->send_txpool_add(events));
EXPECT_TRUE(pub->relay_to_pub(relay.get(), dummy_pub.get()));
pubs = get_published(dummy_client.get());
EXPECT_EQ(1u, pubs.size());
ASSERT_LE(1u, pubs.size());
EXPECT_TRUE(compare_full_txpool(epee::to_span(events), pubs.front()));
events.at(0).res = false;
EXPECT_NO_THROW(cryptonote::listener::zmq_pub::txpool_add{pub}(events));
EXPECT_TRUE(pub->relay_to_pub(relay.get(), dummy_pub.get()));
pubs = get_published(dummy_client.get());
EXPECT_EQ(1u, pubs.size());
ASSERT_LE(1u, pubs.size());
EXPECT_TRUE(compare_full_txpool(epee::to_span(events), pubs.front()));
}
{
const std::array<cryptonote::block, 2> blocks{{make_block(), make_block()}};
EXPECT_EQ(1u, pub->send_chain_main(100, epee::to_span(blocks)));
EXPECT_TRUE(pub->relay_to_pub(relay.get(), dummy_pub.get()));
auto pubs = get_published(dummy_client.get());
EXPECT_EQ(1u, pubs.size());
ASSERT_LE(1u, pubs.size());
EXPECT_TRUE(compare_full_block(epee::to_span(blocks), pubs.front()));
EXPECT_NO_THROW(cryptonote::listener::zmq_pub::chain_main{pub}(533, epee::to_span(blocks)));
EXPECT_TRUE(pub->relay_to_pub(relay.get(), dummy_pub.get()));
pubs = get_published(dummy_client.get());
EXPECT_EQ(1u, pubs.size());
ASSERT_LE(1u, pubs.size());
EXPECT_TRUE(compare_full_block(epee::to_span(blocks), pubs.front()));
}
}
TEST_F(zmq_pub, JsonMinimalAll)
{
static constexpr const char topic[] = "\1json-minimal";
ASSERT_TRUE(sub_request(topic));
{
std::vector<cryptonote::txpool_event> events
{
{make_transaction(), {}, true}, {make_transaction(), {}, true}
};
EXPECT_EQ(1u, pub->send_txpool_add(events));
EXPECT_TRUE(pub->relay_to_pub(relay.get(), dummy_pub.get()));
auto pubs = get_published(dummy_client.get());
EXPECT_EQ(1u, pubs.size());
ASSERT_LE(1u, pubs.size());
EXPECT_TRUE(compare_minimal_txpool(epee::to_span(events), pubs.front()));
EXPECT_NO_THROW(cryptonote::listener::zmq_pub::txpool_add{pub}(events));
EXPECT_TRUE(pub->relay_to_pub(relay.get(), dummy_pub.get()));
pubs = get_published(dummy_client.get());
EXPECT_EQ(1u, pubs.size());
ASSERT_LE(1u, pubs.size());
EXPECT_TRUE(compare_minimal_txpool(epee::to_span(events), pubs.front()));
events.at(0).res = false;
EXPECT_NO_THROW(pub->send_txpool_add(events));
EXPECT_TRUE(pub->relay_to_pub(relay.get(), dummy_pub.get()));
pubs = get_published(dummy_client.get());
EXPECT_EQ(1u, pubs.size());
ASSERT_LE(1u, pubs.size());
EXPECT_TRUE(compare_minimal_txpool(epee::to_span(events), pubs.front()));
events.at(0).res = false;
EXPECT_NO_THROW(cryptonote::listener::zmq_pub::txpool_add{pub}(events));
EXPECT_TRUE(pub->relay_to_pub(relay.get(), dummy_pub.get()));
pubs = get_published(dummy_client.get());
EXPECT_EQ(1u, pubs.size());
ASSERT_LE(1u, pubs.size());
EXPECT_TRUE(compare_minimal_txpool(epee::to_span(events), pubs.front()));
}
{
const std::array<cryptonote::block, 2> blocks{{make_block(), make_block()}};
EXPECT_EQ(1u, pub->send_chain_main(100, epee::to_span(blocks)));
EXPECT_TRUE(pub->relay_to_pub(relay.get(), dummy_pub.get()));
auto pubs = get_published(dummy_client.get());
EXPECT_EQ(1u, pubs.size());
ASSERT_LE(1u, pubs.size());
EXPECT_TRUE(compare_minimal_block(100, epee::to_span(blocks), pubs.front()));
EXPECT_NO_THROW(cryptonote::listener::zmq_pub::chain_main{pub}(533, epee::to_span(blocks)));
EXPECT_TRUE(pub->relay_to_pub(relay.get(), dummy_pub.get()));
pubs = get_published(dummy_client.get());
EXPECT_EQ(1u, pubs.size());
ASSERT_LE(1u, pubs.size());
EXPECT_TRUE(compare_minimal_block(533, epee::to_span(blocks), pubs.front()));
}
}
TEST_F(zmq_pub, JsonAll)
{
static constexpr const char topic[] = "\1json";
ASSERT_TRUE(sub_request(topic));
{
std::vector<cryptonote::txpool_event> events
{
{make_transaction(), {}, true}, {make_transaction(), {}, true}
};
EXPECT_EQ(1u, pub->send_txpool_add(events));
EXPECT_TRUE(pub->relay_to_pub(relay.get(), dummy_pub.get()));
auto pubs = get_published(dummy_client.get());
EXPECT_EQ(2u, pubs.size());
ASSERT_LE(2u, pubs.size());
EXPECT_TRUE(compare_full_txpool(epee::to_span(events), pubs.front()));
EXPECT_TRUE(compare_minimal_txpool(epee::to_span(events), pubs.back()));
EXPECT_NO_THROW(cryptonote::listener::zmq_pub::txpool_add{pub}(events));
EXPECT_TRUE(pub->relay_to_pub(relay.get(), dummy_pub.get()));
pubs = get_published(dummy_client.get());
EXPECT_EQ(2u, pubs.size());
ASSERT_LE(2u, pubs.size());
EXPECT_TRUE(compare_full_txpool(epee::to_span(events), pubs.front()));
EXPECT_TRUE(compare_minimal_txpool(epee::to_span(events), pubs.back()));
events.at(0).res = false;
EXPECT_EQ(1u, pub->send_txpool_add(events));
EXPECT_TRUE(pub->relay_to_pub(relay.get(), dummy_pub.get()));
pubs = get_published(dummy_client.get());
EXPECT_EQ(2u, pubs.size());
ASSERT_LE(2u, pubs.size());
EXPECT_TRUE(compare_full_txpool(epee::to_span(events), pubs.front()));
EXPECT_TRUE(compare_minimal_txpool(epee::to_span(events), pubs.back()));
events.at(0).res = false;
EXPECT_NO_THROW(cryptonote::listener::zmq_pub::txpool_add{pub}(events));
EXPECT_TRUE(pub->relay_to_pub(relay.get(), dummy_pub.get()));
pubs = get_published(dummy_client.get());
EXPECT_EQ(2u, pubs.size());
ASSERT_LE(2u, pubs.size());
EXPECT_TRUE(compare_full_txpool(epee::to_span(events), pubs.front()));
EXPECT_TRUE(compare_minimal_txpool(epee::to_span(events), pubs.back()));
}
{
const std::array<cryptonote::block, 1> blocks{{make_block()}};
EXPECT_EQ(2u, pub->send_chain_main(100, epee::to_span(blocks)));
EXPECT_TRUE(pub->relay_to_pub(relay.get(), dummy_pub.get()));
EXPECT_TRUE(pub->relay_to_pub(relay.get(), dummy_pub.get()));
auto pubs = get_published(dummy_client.get());
EXPECT_EQ(2u, pubs.size());
ASSERT_LE(2u, pubs.size());
EXPECT_TRUE(compare_full_block(epee::to_span(blocks), pubs.front()));
EXPECT_TRUE(compare_minimal_block(100, epee::to_span(blocks), pubs.back()));
EXPECT_NO_THROW(cryptonote::listener::zmq_pub::chain_main{pub}(533, epee::to_span(blocks)));
EXPECT_TRUE(pub->relay_to_pub(relay.get(), dummy_pub.get()));
EXPECT_TRUE(pub->relay_to_pub(relay.get(), dummy_pub.get()));
pubs = get_published(dummy_client.get());
EXPECT_EQ(2u, pubs.size());
ASSERT_LE(2u, pubs.size());
EXPECT_TRUE(compare_full_block(epee::to_span(blocks), pubs.front()));
EXPECT_TRUE(compare_minimal_block(533, epee::to_span(blocks), pubs.back()));
}
}
TEST_F(zmq_pub, JsonChainWeakPtrSkip)
{
static constexpr const char topic[] = "\1json";
ASSERT_TRUE(sub_request(topic));
const std::array<cryptonote::block, 1> blocks{{make_block()}};
pub.reset();
EXPECT_NO_THROW(cryptonote::listener::zmq_pub::chain_main{pub}(533, epee::to_span(blocks)));
}
TEST_F(zmq_pub, JsonTxpoolWeakPtrSkip)
{
static constexpr const char topic[] = "\1json";
ASSERT_TRUE(sub_request(topic));
std::vector<cryptonote::txpool_event> events
{
{make_transaction(), {}, true}, {make_transaction(), {}, true}
};
pub.reset();
EXPECT_NO_THROW(cryptonote::listener::zmq_pub::txpool_add{pub}(std::move(events)));
}
TEST_F(zmq_server, pub)
{
subscribe("json-minimal");
std::vector<cryptonote::txpool_event> events
{
{make_transaction(), {}, true}, {make_transaction(), {}, true}
};
const std::array<cryptonote::block, 1> blocks{{make_block()}};
ASSERT_EQ(1u, pub->send_txpool_add(events));
ASSERT_EQ(1u, pub->send_chain_main(200, epee::to_span(blocks)));
auto pubs = get_published(sub.get(), 2);
EXPECT_EQ(2u, pubs.size());
ASSERT_LE(2u, pubs.size());
EXPECT_TRUE(compare_minimal_txpool(epee::to_span(events), pubs.front()));
EXPECT_TRUE(compare_minimal_block(200, epee::to_span(blocks), pubs.back()));
}