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-
2823using namespace system ;
2924
3025constexpr auto block1_hash = base16_hash(" 00000000839a8e6886ab5951d76f411475428afc90947ee320161bbf18eb6048" );
@@ -46,115 +41,158 @@ constexpr auto block6_data = base16_array("01000000fc33f596f822a0a1951ffdbf2a897
4641constexpr auto block7_data = base16_array(" 010000008d778fdc15a2d3fb76b7122a3b5582bea4f21f5a0c693537e7a03130000000003f674005103b42f984169c7d008370967e91920a6a5d64fd51282f75bc73a68af1c66649ffff001d39a59c860101000000010000000000000000000000000000000000000000000000000000000000000000ffffffff0704ffff001d012bffffffff0100f2052a01000000434104a59e64c774923d003fae7491b2a7f75d6b7aa3f35606a8ff1cf06cd3317d16a41aa16928b1df1f631f31f28c7da35d4edad3603adb2338c4d4dd268f31530555ac00000000" );
4742constexpr 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+
6254static const server::settings::embedded_pages admin{};
6355static 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
160198BOOST_AUTO_TEST_SUITE_END ()
0 commit comments