Skip to content

Commit faf9392

Browse files
committed
Generalize electrum endpoint test using fixture.
1 parent bde05ec commit faf9392

1 file changed

Lines changed: 138 additions & 100 deletions

File tree

test/endpoints/electrum.cpp

Lines changed: 138 additions & 100 deletions
Original file line numberDiff line numberDiff line change
@@ -20,11 +20,6 @@
2020

2121
#include <future>
2222

23-
BOOST_FIXTURE_TEST_SUITE(electrum_tests, test::directory_setup_fixture)
24-
25-
// nop event handler.
26-
const auto events = [](auto, auto) {};
27-
2823
using namespace system;
2924

3025
constexpr auto block1_hash = base16_hash("00000000839a8e6886ab5951d76f411475428afc90947ee320161bbf18eb6048");
@@ -46,115 +41,158 @@ constexpr auto block6_data = base16_array("01000000fc33f596f822a0a1951ffdbf2a897
4641
constexpr auto block7_data = base16_array("010000008d778fdc15a2d3fb76b7122a3b5582bea4f21f5a0c693537e7a03130000000003f674005103b42f984169c7d008370967e91920a6a5d64fd51282f75bc73a68af1c66649ffff001d39a59c860101000000010000000000000000000000000000000000000000000000000000000000000000ffffffff0704ffff001d012bffffffff0100f2052a01000000434104a59e64c774923d003fae7491b2a7f75d6b7aa3f35606a8ff1cf06cd3317d16a41aa16928b1df1f631f31f28c7da35d4edad3603adb2338c4d4dd268f31530555ac00000000");
4742
constexpr auto block8_data = base16_array("010000004494c8cf4154bdcc0720cd4a59d9c9b285e4b146d45f061d2b6c967100000000e3855ed886605b6d4a99d5fa2ef2e9b0b164e63df3c4136bebf2d0dac0f1f7a667c86649ffff001d1c4b56660101000000010000000000000000000000000000000000000000000000000000000000000000ffffffff0704ffff001d012cffffffff0100f2052a01000000434104cc8d85f5e7933cb18f13b97d165e1189c1fb3e9c98b0dd5446b2a1989883ff9e740a8a75da99cc59a21016caf7a7afd3e4e9e7952983e18d1ff70529d62e0ba1ac00000000");
4843

49-
const auto genesis = system::settings{ chain::selection::mainnet }.genesis_block;
50-
const chain::block block1{ block1_data, true };
51-
const chain::block block2{ block2_data, true };
52-
const chain::block block3{ block3_data, true };
53-
const chain::block block4{ block4_data, true };
54-
const chain::block block5{ block5_data, true };
55-
const chain::block block6{ block6_data, true };
56-
const chain::block block7{ block7_data, true };
57-
const chain::block block8{ block8_data, true };
58-
59-
using context_t = database::context;
60-
using store_t = database::store<database::map>;
61-
using query_t = database::query<database::store<database::map>>;
44+
static const auto genesis = system::settings{ chain::selection::mainnet }.genesis_block;
45+
static const chain::block block1{ block1_data, true };
46+
static const chain::block block2{ block2_data, true };
47+
static const chain::block block3{ block3_data, true };
48+
static const chain::block block4{ block4_data, true };
49+
static const chain::block block5{ block5_data, true };
50+
static const chain::block block6{ block6_data, true };
51+
static const chain::block block7{ block7_data, true };
52+
static const chain::block block8{ block8_data, true };
53+
6254
static const server::settings::embedded_pages admin{};
6355
static const server::settings::embedded_pages native{};
6456

65-
bool setup_eight_block_store(query_t& query) NOEXCEPT
57+
struct electrum_setup_fixture
6658
{
67-
return query.initialize(genesis) &&
68-
query.set(block1, context_t{ 0, 1, 0 }, false, false) &&
69-
query.set(block2, context_t{ 0, 2, 0 }, false, false) &&
70-
query.set(block3, context_t{ 0, 3, 0 }, false, false) &&
71-
query.set(block4, context_t{ 0, 4, 0 }, false, false) &&
72-
query.set(block5, context_t{ 0, 5, 0 }, false, false) &&
73-
query.set(block6, context_t{ 0, 6, 0 }, false, false) &&
74-
query.set(block7, context_t{ 0, 7, 0 }, false, false) &&
75-
query.set(block8, context_t{ 0, 8, 0 }, false, false) &&
76-
query.push_confirmed(query.to_header(block1_hash), false) &&
77-
query.push_confirmed(query.to_header(block2_hash), false) &&
78-
query.push_confirmed(query.to_header(block3_hash), false) &&
79-
query.push_confirmed(query.to_header(block4_hash), false) &&
80-
query.push_confirmed(query.to_header(block5_hash), false) &&
81-
query.push_confirmed(query.to_header(block6_hash), false) &&
82-
query.push_confirmed(query.to_header(block7_hash), false) &&
83-
query.push_confirmed(query.to_header(block8_hash), false);
84-
}
59+
using context_t = database::context;
60+
using store_t = database::store<database::map>;
61+
using query_t = database::query<database::store<database::map>>;
62+
63+
DELETE_COPY_MOVE(electrum_setup_fixture);
64+
65+
electrum_setup_fixture() NOEXCEPT
66+
: config_{ chain::selection::mainnet, native, admin },
67+
store_
68+
{
69+
[&]() NOEXCEPT -> const database::settings&
70+
{
71+
config_.database.path = TEST_DIRECTORY;
72+
return config_.database;
73+
}()
74+
},
75+
query_{ store_ }, log_{},
76+
server_{ query_, config_, log_ }
77+
{
78+
BOOST_REQUIRE(test::clear(test::directory));
79+
80+
auto& database_settings = config_.database;
81+
auto& network_settings = config_.network;
82+
auto& node_settings = config_.node;
83+
auto& server_settings = config_.server;
84+
auto& electrum = server_settings.electrum;
85+
86+
// >>>>>>>>>>>>>>> REQUIRES LOCALHOST TCP PORT 65000. <<<<<<<<<<<<<<<
87+
electrum.binds = { { "127.0.0.1:65000" } };
88+
electrum.maximum_headers = 5;
89+
electrum.connections = 1;
90+
database_settings.interval_depth = 2;
91+
node_settings.delay_inbound = false;
92+
network_settings.inbound.connections = 0;
93+
network_settings.outbound.connections = 0;
94+
95+
// Create and populate the store.
96+
BOOST_REQUIRE(!store_.create([](auto, auto){}));
97+
BOOST_REQUIRE(setup_eight_block_store());
98+
99+
// Run the server.
100+
std::promise<code> running{};
101+
server_.run([&](const code& ec) NOEXCEPT
102+
{
103+
running.set_value(ec);
104+
});
105+
106+
// Block until server is running.
107+
BOOST_REQUIRE(!running.get_future().get());
108+
socket_.connect(electrum.binds.back().to_endpoint());
109+
}
110+
111+
~electrum_setup_fixture() NOEXCEPT
112+
{
113+
socket_.close();
114+
server_.close();
115+
BOOST_REQUIRE(!store_.close([](auto, auto){}));
116+
BOOST_REQUIRE(test::clear(test::directory));
117+
}
85118

86-
// TODO: move server setup to fixiture for all electrum tests.
87-
// TODO: make test utilities for server setup, start, request, response, close.
88-
BOOST_AUTO_TEST_CASE(endpoint_electrum_test)
89-
{
90-
const network::config::authority authority{ "127.0.0.1:65000" };
91-
const std::string request{ R"({"id":1,"method":"server.version","params":["test_client","1.4"]})" "\n" };
92-
93-
// Create base configuration.
94-
configuration configure(chain::selection::mainnet, native, admin);
95-
auto& database_settings = configure.database;
96-
auto& network_settings = configure.network;
97-
auto& server_settings = configure.server;
98-
auto& node_settings = configure.node;
99-
auto& electrum = server_settings.electrum;
100-
101-
// Create and populate the store.
102-
database_settings.path = TEST_DIRECTORY;
103-
database_settings.interval_depth = 2;
104-
store_t store{ database_settings };
105-
query_t query{ store };
106-
BOOST_REQUIRE(!store.create(events));
107-
BOOST_REQUIRE(setup_eight_block_store(query));
108-
109-
// Create the server with a reference to the store, config and log.
110-
network::logger log{};
111-
node_settings.delay_inbound = false;
112-
network_settings.inbound.connections = 0;
113-
network_settings.outbound.connections = 0;
114-
electrum.connections = 1;
115-
electrum.maximum_headers = 100;
116-
electrum.binds.push_back(authority);
117-
server::server_node server{ query, configure, log };
118-
119-
// Run the server, start is not required here (seeding, manual, and chasers).
120-
std::promise<code> running{};
121-
server.run([&](const code& ec) NOEXCEPT
119+
const configuration& config() const NOEXCEPT
120+
{
121+
return config_;
122+
}
123+
124+
auto get(const std::string& request) NOEXCEPT
122125
{
123-
running.set_value(ec);
124-
});
126+
socket_.send(boost::asio::buffer(request));
127+
boost::asio::streambuf stream{};
128+
read_until(socket_, stream, '\n');
125129

126-
// Blocks until server is running.
127-
BOOST_REQUIRE(!running.get_future().get());
130+
std::string response{};
131+
std::istream response_stream{ &stream };
132+
std::getline(response_stream, response);
128133

129-
// Connect, send request, and capture response.
134+
return boost::json::parse(response);
135+
}
136+
137+
private:
138+
bool setup_eight_block_store() NOEXCEPT
139+
{
140+
return query_.initialize(genesis) &&
141+
query_.set(block1, context_t{ 0, 1, 0 }, false, false) &&
142+
query_.set(block2, context_t{ 0, 2, 0 }, false, false) &&
143+
query_.set(block3, context_t{ 0, 3, 0 }, false, false) &&
144+
query_.set(block4, context_t{ 0, 4, 0 }, false, false) &&
145+
query_.set(block5, context_t{ 0, 5, 0 }, false, false) &&
146+
query_.set(block6, context_t{ 0, 6, 0 }, false, false) &&
147+
query_.set(block7, context_t{ 0, 7, 0 }, false, false) &&
148+
query_.set(block8, context_t{ 0, 8, 0 }, false, false) &&
149+
query_.push_confirmed(query_.to_header(block1_hash), false) &&
150+
query_.push_confirmed(query_.to_header(block2_hash), false) &&
151+
query_.push_confirmed(query_.to_header(block3_hash), false) &&
152+
query_.push_confirmed(query_.to_header(block4_hash), false) &&
153+
query_.push_confirmed(query_.to_header(block5_hash), false) &&
154+
query_.push_confirmed(query_.to_header(block6_hash), false) &&
155+
query_.push_confirmed(query_.to_header(block7_hash), false) &&
156+
query_.push_confirmed(query_.to_header(block8_hash), false);
157+
}
158+
159+
configuration config_;
160+
store_t store_;
161+
query_t query_;
162+
network::logger log_;
163+
server::server_node server_;
130164
boost::asio::io_context io{};
131-
boost::asio::ip::tcp::socket sock{ io };
132-
sock.connect(electrum.binds.back().to_endpoint());
133-
sock.send(boost::asio::buffer(request));
134-
boost::asio::streambuf stream{};
135-
read_until(sock, stream, '\n');
136-
sock.close();
137-
138-
// Parser and verify server response.
139-
std::string response{};
140-
std::istream response_stream{ &stream };
141-
std::getline(response_stream, response);
142-
143-
const auto parsed = boost::json::parse(response);
144-
BOOST_REQUIRE_EQUAL(parsed.at("id").as_int64(), 1);
145-
BOOST_REQUIRE(parsed.at("result").is_array());
146-
147-
const auto& result = parsed.at("result").as_array();
165+
boost::asio::ip::tcp::socket socket_{ io };
166+
};
167+
168+
BOOST_FIXTURE_TEST_SUITE(electrum_tests, electrum_setup_fixture)
169+
170+
BOOST_AUTO_TEST_CASE(electrum__server_version__default__1_4)
171+
{
172+
const auto response = get(R"({"id":42,"method":"server.version","params":["foobar"]})" "\n");
173+
BOOST_REQUIRE_EQUAL(response.at("id").as_int64(), 42);
174+
BOOST_REQUIRE(response.at("result").is_array());
175+
176+
const auto& result = response.at("result").as_array();
148177
BOOST_REQUIRE_EQUAL(result.size(), 2u);
149178
BOOST_REQUIRE(result.at(0).is_string());
150179
BOOST_REQUIRE(result.at(1).is_string());
151-
BOOST_TEST_MESSAGE("Version response: " + response);
180+
BOOST_REQUIRE_EQUAL(result.at(0).as_string(), config().network.user_agent);
181+
BOOST_REQUIRE_EQUAL(result.at(1).as_string(), "1.4");
182+
}
183+
184+
BOOST_AUTO_TEST_CASE(electrum__blockchain_block_header__genesis__expected)
185+
{
186+
get(R"({"id":"name","method":"server.version","params":["foobar","1.4"]})" "\n");
152187

153-
// Server close blocks until all threads joined.
154-
server.close();
188+
const auto response = get(R"({"id":43,"method":"blockchain.block.header","params":[0]})" "\n");
189+
BOOST_REQUIRE_EQUAL(response.at("id").as_int64(), 43);
190+
BOOST_REQUIRE(response.at("result").is_object());
155191

156-
// Store close is required as well.
157-
BOOST_REQUIRE(!store.close(events));
192+
const auto& result = response.at("result").as_object();
193+
BOOST_REQUIRE_EQUAL(result.size(), 1u);
194+
BOOST_REQUIRE(result.at("header").is_string());
195+
BOOST_REQUIRE_EQUAL(result.at("header").as_string(), encode_base16(genesis.header().to_data()));
158196
}
159197

160198
BOOST_AUTO_TEST_SUITE_END()

0 commit comments

Comments
 (0)