diff --git a/include/bitcoin/network/error.hpp b/include/bitcoin/network/error.hpp index f0a654dc6..6c3d9c736 100644 --- a/include/bitcoin/network/error.hpp +++ b/include/bitcoin/network/error.hpp @@ -312,6 +312,7 @@ enum error_t : uint8_t jsonrpc_v1_requires_params, jsonrpc_v1_requires_array_params, jsonrpc_v1_requires_id, + jsonrpc_params_not_collection, jsonrpc_reader_bad_buffer, jsonrpc_reader_stall, jsonrpc_reader_exception, diff --git a/include/bitcoin/network/impl/channels/channel_rpc.ipp b/include/bitcoin/network/impl/channels/channel_rpc.ipp index f15d97ad1..aef8c4eda 100644 --- a/include/bitcoin/network/impl/channels/channel_rpc.ipp +++ b/include/bitcoin/network/impl/channels/channel_rpc.ipp @@ -72,6 +72,9 @@ inline void CLASS::receive() NOEXCEPT const auto in = system::to_shared(); using namespace std::placeholders; + // Electrum, allow params singleton to be accepted as array. + in->strict = false; + // Post handle_read to strand upon stop, error, or buffer full. read(request_buffer(), *in, std::bind(&channel_rpc::handle_receive, diff --git a/include/bitcoin/network/messages/http_body.hpp b/include/bitcoin/network/messages/http_body.hpp index a3fc52230..a4833d963 100644 --- a/include/bitcoin/network/messages/http_body.hpp +++ b/include/bitcoin/network/messages/http_body.hpp @@ -235,7 +235,7 @@ struct BCT_API body }, value.value()); } - private: + protected: header& header_; value_type& value_; body_reader reader_; diff --git a/include/bitcoin/network/messages/rpc/body.hpp b/include/bitcoin/network/messages/rpc/body.hpp index 8f66643a4..09391ac4a 100644 --- a/include/bitcoin/network/messages/rpc/body.hpp +++ b/include/bitcoin/network/messages/rpc/body.hpp @@ -33,6 +33,7 @@ struct message_type : public json::json_value { Type message{}; + bool strict{ true }; }; /// Derived boost::beast::http body for JSON-RPC messages. diff --git a/include/bitcoin/network/messages/rpc/model.hpp b/include/bitcoin/network/messages/rpc/model.hpp index 90bb61f1b..0f5af49cb 100644 --- a/include/bitcoin/network/messages/rpc/model.hpp +++ b/include/bitcoin/network/messages/rpc/model.hpp @@ -161,6 +161,8 @@ using value_option = std::optional; using params_t = std::variant < + // non-standard rpc, required for Electrum compat. + value_t, array_t, object_t >; diff --git a/src/error.cpp b/src/error.cpp index 682cd7fa5..4493b0ea6 100644 --- a/src/error.cpp +++ b/src/error.cpp @@ -299,6 +299,7 @@ DEFINE_ERROR_T_MESSAGE_MAP(error) { jsonrpc_v1_requires_params, "jsonrpc v1 requires params" }, { jsonrpc_v1_requires_array_params, "jsonrpc v1 requires array params" }, { jsonrpc_v1_requires_id, "jsonrpc v1 requires id" }, + { jsonrpc_params_not_collection, "jsonrpc params not collection" }, { jsonrpc_reader_bad_buffer, "jsonrpc reader bad buffer" }, { jsonrpc_reader_stall, "jsonrpc reader stall" }, { jsonrpc_reader_exception, "jsonrpc reader exception" }, diff --git a/src/messages/rpc/body.cpp b/src/messages/rpc/body.cpp index 9656bffc2..a98ea7022 100644 --- a/src/messages/rpc/body.cpp +++ b/src/messages/rpc/body.cpp @@ -138,6 +138,22 @@ finish(boost_code& ec) NOEXCEPT value_.message.params.value())) ec = code{ error::jsonrpc_v1_requires_array_params }; } + else if (value_.message.params.has_value() && + std::holds_alternative(value_.message.params.value())) + { + if (!value_.strict) + { + // Convert non-standard rpc, required for Electrum compat. + value_.message.params.emplace(array_t + { + std::get(std::move(value_.message.params.value())) + }); + } + else + { + ec = code{ error::jsonrpc_params_not_collection }; + } + } } // rpc::body::reader (unused) diff --git a/src/messages/rpc/model.cpp b/src/messages/rpc/model.cpp index 13119df43..1584980ce 100644 --- a/src/messages/rpc/model.cpp +++ b/src/messages/rpc/model.cpp @@ -233,15 +233,7 @@ DEFINE_JSON_FROM_TAG(request_t) if (instance.params.has_value()) { - if (const auto& params = instance.params.value(); - std::holds_alternative(params)) - { - object["params"] = value_from(std::get(params)); - } - else - { - object["params"] = value_from(std::get(params)); - } + object["params"] = value_from(instance.params.value()); } value = object; @@ -290,6 +282,14 @@ DEFINE_JSON_TO_TAG(request_t) std::in_place_type, value_to(params) }; } + else + { + // Allow non-standard rpc, required for Electrum compat. + request.params = params_t + { + std::in_place_type, value_to(params) + }; + } } return request; diff --git a/test/error.cpp b/test/error.cpp index 96e2e9866..903e6a634 100644 --- a/test/error.cpp +++ b/test/error.cpp @@ -2140,6 +2140,15 @@ BOOST_AUTO_TEST_CASE(error_t__code__jsonrpc_v1_requires_id__true_expected_messag BOOST_REQUIRE_EQUAL(ec.message(), "jsonrpc v1 requires id"); } +BOOST_AUTO_TEST_CASE(error_t__code__jsonrpc_params_not_collection__true_expected_message) +{ + constexpr auto value = error::jsonrpc_params_not_collection; + const auto ec = code(value); + BOOST_REQUIRE(ec); + BOOST_REQUIRE(ec == value); + BOOST_REQUIRE_EQUAL(ec.message(), "jsonrpc params not collection"); +} + BOOST_AUTO_TEST_CASE(error_t__code__jsonrpc_reader_bad_buffer__true_expected_message) { constexpr auto value = error::jsonrpc_reader_bad_buffer; diff --git a/test/messages/http_body_reader.cpp b/test/messages/http_body_reader.cpp index eb5a0677c..6668a006f 100644 --- a/test/messages/http_body_reader.cpp +++ b/test/messages/http_body_reader.cpp @@ -18,7 +18,7 @@ */ #include "../test.hpp" -#if defined(HAVE_SLOW_TESTS) +////#if defined(HAVE_SLOW_TESTS) using namespace http; using namespace network::http; @@ -26,76 +26,116 @@ using namespace network::http; struct accessor : public body::reader { + // Forwarding constructor required because base is explicit and templated. + template + accessor(http::message_header& header, + body::value_type& value) NOEXCEPT + : base(header, value) + { + } + using base = body::reader; - using base::reader; - using base::to_reader; + using base::reader_; }; BOOST_AUTO_TEST_SUITE(http_body_reader_tests) -BOOST_AUTO_TEST_CASE(http_body_reader__to_reader__bogus__constructs_empty_reader) +BOOST_AUTO_TEST_CASE(http_body_reader__init__bogus__constructs_empty_reader) { - message_header header{}; + message_header header{}; header.set(http::field::content_type, "bogus"); body::value_type value{}; value = empty_body::value_type{}; - const auto variant = accessor::to_reader(header, value); - BOOST_REQUIRE(std::holds_alternative(variant)); + accessor reader(header, value); + length_type length{ max_size_t }; + boost_code ec{}; + reader.init(length, ec); + BOOST_REQUIRE(std::holds_alternative(reader.reader_)); +} + +BOOST_AUTO_TEST_CASE(http_body_reader__init__plain_json__constructs_json_reader) +{ + message_header header{}; + header.set(http::field::content_type, "application/json"); + body::value_type value{}; + value = json_body::value_type{}; + value.plain_json = true; + accessor reader(header, value); + length_type length{ max_size_t }; + boost_code ec{}; + reader.init(length, ec); + BOOST_REQUIRE(std::holds_alternative(reader.reader_)); } -BOOST_AUTO_TEST_CASE(http_body_reader__to_reader__json__constructs_json_reader) +BOOST_AUTO_TEST_CASE(http_body_reader__init__rpc_json__constructs_rpc_reader) { - message_header header{}; + message_header header{}; header.set(http::field::content_type, "application/json"); body::value_type value{}; value = json_body::value_type{}; - const auto variant = accessor::to_reader(header, value); - BOOST_REQUIRE(std::holds_alternative(variant)); + value.plain_json = false; + accessor reader(header, value); + length_type length{ max_size_t }; + boost_code ec{}; + reader.init(length, ec); + BOOST_REQUIRE(std::holds_alternative(reader.reader_)); } -BOOST_AUTO_TEST_CASE(http_body_reader__to_reader__application_octet_stream__constructs_data_reader) +BOOST_AUTO_TEST_CASE(http_body_reader__init__application_octet_stream__constructs_data_reader) { - message_header header{}; + message_header header{}; header.set(http::field::content_type, "application/octet-stream"); header.set(http::field::content_disposition, "bogus"); body::value_type value{}; value = chunk_body::value_type{}; - const auto variant = accessor::to_reader(header, value); - BOOST_REQUIRE(std::holds_alternative(variant)); + accessor reader(header, value); + length_type length{ max_size_t }; + boost_code ec{}; + reader.init(length, ec); + BOOST_REQUIRE(std::holds_alternative(reader.reader_)); } -BOOST_AUTO_TEST_CASE(http_body_reader__to_reader__application_octet_stream_with_attachment__constructs_file_reader) +BOOST_AUTO_TEST_CASE(http_body_reader__init__application_octet_stream_with_attachment__constructs_file_reader) { - message_header header{}; + message_header header{}; header.set(http::field::content_type, "application/octet-stream"); header.set(http::field::content_disposition, "filename=somenonsense.jpg"); body::value_type value{}; value = file_body::value_type{}; - const auto variant = accessor::to_reader(header, value); - BOOST_REQUIRE(std::holds_alternative(variant)); + accessor reader(header, value); + length_type length{ max_size_t }; + boost_code ec{}; + reader.init(length, ec); + BOOST_REQUIRE(std::holds_alternative(reader.reader_)); } -BOOST_AUTO_TEST_CASE(http_body_reader__to_reader__application_octet_stream_with_dirty_attachment__constructs_file_reader) +BOOST_AUTO_TEST_CASE(http_body_reader__init__application_octet_stream_with_dirty_attachment__constructs_file_reader) { - message_header header{}; + message_header header{}; header.set(http::field::content_type, "application/octet-stream"); header.set(http::field::content_disposition, "dirty 42; filename* = somenonsense.jpg; some other nonsense"); body::value_type value{}; value = file_body::value_type{}; - const auto variant = accessor::to_reader(header, value); - BOOST_REQUIRE(std::holds_alternative(variant)); + accessor reader(header, value); + length_type length{ max_size_t }; + boost_code ec{}; + reader.init(length, ec); + BOOST_REQUIRE(std::holds_alternative(reader.reader_)); } -BOOST_AUTO_TEST_CASE(http_body_reader__to_reader__text_plain__constructs_string_reader) +BOOST_AUTO_TEST_CASE(http_body_reader__init__text_plain__constructs_string_reader) { - message_header header{}; + message_header header{}; header.set(http::field::content_type, "text/plain"); body::value_type value{}; value = string_body::value_type{}; - const auto variant = accessor::to_reader(header, value); - BOOST_REQUIRE(std::holds_alternative(variant)); + accessor reader(header, value); + length_type length{ max_size_t }; + boost_code ec{}; + reader.init(length, ec); + BOOST_REQUIRE(std::holds_alternative(reader.reader_)); } BOOST_AUTO_TEST_SUITE_END() -#endif // HAVE_SLOW_TESTS +///#endif // HAVE_SLOW_TESTS diff --git a/test/messages/http_body_writer.cpp b/test/messages/http_body_writer.cpp index b3483e3e0..0e8f9b741 100644 --- a/test/messages/http_body_writer.cpp +++ b/test/messages/http_body_writer.cpp @@ -18,7 +18,7 @@ */ #include "../test.hpp" -#if defined(HAVE_SLOW_TESTS) +////#if defined(HAVE_SLOW_TESTS) using namespace http; using namespace network::http; @@ -118,5 +118,5 @@ BOOST_AUTO_TEST_CASE(http_body_writer__to_writer__file__constructs_file_writer) BOOST_AUTO_TEST_SUITE_END() -#endif // HAVE_SLOW_TESTS +////#endif // HAVE_SLOW_TESTS diff --git a/test/messages/json_body_reader.cpp b/test/messages/json_body_reader.cpp index 176c48b50..fa61bf726 100644 --- a/test/messages/json_body_reader.cpp +++ b/test/messages/json_body_reader.cpp @@ -18,7 +18,7 @@ */ #include "../test.hpp" -#if defined(HAVE_SLOW_TESTS) +////#if defined(HAVE_SLOW_TESTS) BOOST_AUTO_TEST_SUITE(json_body_reader_tests) @@ -28,16 +28,16 @@ using value = boost::json::value; BOOST_AUTO_TEST_CASE(json_body_reader__construct1__default__null_model) { - json::body::value_type body{}; - json::body::reader reader(body); + json::body<>::value_type body{}; + json::body<>::reader reader(body); BOOST_REQUIRE(boost::get(body.model).is_null()); } BOOST_AUTO_TEST_CASE(json_body_reader__construct2__default__null_model) { request_header header{}; - json::body::value_type body{}; - json::body::reader reader(header, body); + json::body<>::value_type body{}; + json::body<>::reader reader(header, body); BOOST_REQUIRE(boost::get(body.model).is_null()); } @@ -45,8 +45,8 @@ BOOST_AUTO_TEST_CASE(json_body_reader__init__simple_object__success) { const std::string_view text{ R"({"key":"value"})" }; const asio::const_buffer buffer{ text.data(), text.size() }; - json::body::value_type body{}; - json::body::reader reader(body); + json::body<>::value_type body{}; + json::body<>::reader reader(body); boost_code ec{}; reader.init(text.size(), ec); BOOST_REQUIRE(!ec); @@ -56,8 +56,8 @@ BOOST_AUTO_TEST_CASE(json_body_reader__put__simple_object__success_expected_cons { const std::string_view text{ R"({"key":"value"})" }; const asio::const_buffer buffer{ text.data(), text.size() }; - json::body::value_type body{}; - json::body::reader reader(body); + json::body<>::value_type body{}; + json::body<>::reader reader(body); boost_code ec{}; reader.init(text.size(), ec); BOOST_REQUIRE(!ec); @@ -71,8 +71,8 @@ BOOST_AUTO_TEST_CASE(json_body_reader__finish__simple_object__success_expected_m const std::string_view text{ R"({"key":"value"})" }; const asio::const_buffer buffer{ text.data(), text.size() }; - json::body::value_type body{}; - json::body::reader reader(body); + json::body<>::value_type body{}; + json::body<>::reader reader(body); boost_code ec{}; reader.init(text.size(), ec); BOOST_REQUIRE(!ec); @@ -91,8 +91,8 @@ BOOST_AUTO_TEST_CASE(json_body_reader__put__over_length__protocol_error) { const std::string_view text{ R"({"key":"value"})" }; const asio::const_buffer buffer{ text.data(), text.size() }; - json::body::value_type body{}; - json::body::reader reader(body); + json::body<>::value_type body{}; + json::body<>::reader reader(body); boost_code ec{}; reader.init(10, ec); BOOST_REQUIRE(!ec); @@ -102,4 +102,4 @@ BOOST_AUTO_TEST_CASE(json_body_reader__put__over_length__protocol_error) BOOST_AUTO_TEST_SUITE_END() -#endif // HAVE_SLOW_TESTS +////#endif // HAVE_SLOW_TESTS diff --git a/test/messages/json_body_writer.cpp b/test/messages/json_body_writer.cpp index fda9cbe86..95ce9dde1 100644 --- a/test/messages/json_body_writer.cpp +++ b/test/messages/json_body_writer.cpp @@ -18,7 +18,7 @@ */ #include "../test.hpp" -#if defined(HAVE_SLOW_TESTS) +////#if defined(HAVE_SLOW_TESTS) BOOST_AUTO_TEST_SUITE(json_body_writer_tests) @@ -40,23 +40,23 @@ bool operator!=(const asio::const_buffer& left, const asio::const_buffer& right) BOOST_AUTO_TEST_CASE(json_body_writer__constructor1__default__null_model) { - json::body::value_type body{}; - json::body::writer writer(body); + json::body<>::value_type body{}; + json::body<>::writer writer(body); BOOST_REQUIRE(boost::get(body.model).is_null()); } BOOST_AUTO_TEST_CASE(json_body_writer__constructor2__default__null_model) { response_header header{}; - json::body::value_type body{}; - json::body::writer writer(header, body); + json::body<>::value_type body{}; + json::body<>::writer writer(header, body); BOOST_REQUIRE(boost::get(body.model).is_null()); } BOOST_AUTO_TEST_CASE(json_body_writer__init__default__success) { - json::body::value_type body{}; - json::body::writer writer(body); + json::body<>::value_type body{}; + json::body<>::writer writer(body); boost_code ec{}; writer.init(ec); BOOST_REQUIRE(!ec); @@ -66,8 +66,8 @@ BOOST_AUTO_TEST_CASE(json_body_writer__get__null_model__success_expected_no_more { const std::string_view expected{ "null" }; const asio::const_buffer out{ expected.data(), expected.size() }; - json::body::value_type body{}; - json::body::writer writer(body); + json::body<>::value_type body{}; + json::body<>::writer writer(body); boost_code ec{}; writer.init(ec); BOOST_REQUIRE(!ec); @@ -83,9 +83,9 @@ BOOST_AUTO_TEST_CASE(json_body_writer__get__simple_object__success_expected_no_m { const std::string_view expected{ R"({"key":"value"})" }; const asio::const_buffer out{ expected.data(), expected.size() }; - json::body::value_type body{}; + json::body<>::value_type body{}; body.model = object{ { "key", "value" } }; - json::body::writer writer(body); + json::body<>::writer writer(body); boost_code ec{}; writer.init(ec); BOOST_REQUIRE(!ec); @@ -99,4 +99,4 @@ BOOST_AUTO_TEST_CASE(json_body_writer__get__simple_object__success_expected_no_m BOOST_AUTO_TEST_SUITE_END() -#endif // HAVE_SLOW_TESTS +////#endif // HAVE_SLOW_TESTS diff --git a/test/messages/rpc/body_reader.cpp b/test/messages/rpc/body_reader.cpp index c8ceb026c..c09ae872e 100644 --- a/test/messages/rpc/body_reader.cpp +++ b/test/messages/rpc/body_reader.cpp @@ -18,7 +18,7 @@ */ #include "../../test.hpp" -#if defined(HAVE_SLOW_TESTS) +////#if defined(HAVE_SLOW_TESTS) BOOST_AUTO_TEST_SUITE(rpc_body_reader_tests) @@ -28,33 +28,33 @@ using value = boost::json::value; BOOST_AUTO_TEST_CASE(rpc_body_reader__construct1__default__null_model_terminated) { - rpc::body::value_type body{}; - rpc::body::reader reader(body); + rpc::request_body::value_type body{}; + rpc::request_body::reader reader(body); BOOST_REQUIRE(body.model.is_null()); - BOOST_REQUIRE(body.request.jsonrpc == version::undefined); - BOOST_REQUIRE(!body.request.params.has_value()); - BOOST_REQUIRE(!body.request.id.has_value()); - BOOST_REQUIRE(body.request.method.empty()); + BOOST_REQUIRE(body.message.jsonrpc == version::undefined); + BOOST_REQUIRE(!body.message.params.has_value()); + BOOST_REQUIRE(!body.message.id.has_value()); + BOOST_REQUIRE(body.message.method.empty()); } BOOST_AUTO_TEST_CASE(rpc_body_reader__construct2__default__null_model_non_terminated) { request_header header{}; - rpc::body::value_type body{}; - rpc::body::reader reader(header, body); + rpc::request_body::value_type body{}; + rpc::request_body::reader reader(header, body); BOOST_REQUIRE(body.model.is_null()); - BOOST_REQUIRE(body.request.jsonrpc == version::undefined); - BOOST_REQUIRE(!body.request.params.has_value()); - BOOST_REQUIRE(!body.request.id.has_value()); - BOOST_REQUIRE(body.request.method.empty()); + BOOST_REQUIRE(body.message.jsonrpc == version::undefined); + BOOST_REQUIRE(!body.message.params.has_value()); + BOOST_REQUIRE(!body.message.id.has_value()); + BOOST_REQUIRE(body.message.method.empty()); } BOOST_AUTO_TEST_CASE(rpc_body_reader__init__simple_request__success) { const std::string_view text{ R"({"jsonrpc":"2.0","id":1,"method":"test"})" }; const asio::const_buffer buffer{ text.data(), text.size() }; - rpc::body::value_type body{}; - rpc::body::reader reader(body); + rpc::request_body::value_type body{}; + rpc::request_body::reader reader(body); boost_code ec{}; reader.init(text.size(), ec); BOOST_REQUIRE(!ec); @@ -64,9 +64,9 @@ BOOST_AUTO_TEST_CASE(rpc_body_reader__put__simple_request_non_terminated__succes { const std::string_view text{ R"({"jsonrpc":"2.0","id":1,"method":"test"})" }; const asio::const_buffer buffer{ text.data(), text.size() }; - rpc::body::value_type body{}; + rpc::request_body::value_type body{}; request_header header{}; - rpc::body::reader reader(header, body); + rpc::request_body::reader reader(header, body); boost_code ec{}; reader.init(text.size(), ec); BOOST_REQUIRE(!ec); @@ -79,8 +79,8 @@ BOOST_AUTO_TEST_CASE(rpc_body_reader__put__simple_request_terminated_with_newlin { const std::string_view text{ R"({"jsonrpc":"2.0","id":1,"method":"test"})""\n" }; const asio::const_buffer buffer{ text.data(), text.size() }; - rpc::body::value_type body{}; - rpc::body::reader reader(body); + rpc::request_body::value_type body{}; + rpc::request_body::reader reader(body); boost_code ec{}; reader.init(text.size(), ec); BOOST_REQUIRE(!ec); @@ -89,28 +89,28 @@ BOOST_AUTO_TEST_CASE(rpc_body_reader__put__simple_request_terminated_with_newlin BOOST_REQUIRE(!ec); } -BOOST_AUTO_TEST_CASE(rpc_body_reader__put__simple_request_terminated_without_newline__end_of_stream_expected_consumed_unterminated_set) +BOOST_AUTO_TEST_CASE(rpc_body_reader__put__simple_request_terminated_without_newline__consumed_not_done) { const std::string_view text{ R"({"jsonrpc":"2.0","id":1,"method":"test"})" }; const asio::const_buffer buffer{ text.data(), text.size() }; - rpc::body::value_type body{}; - rpc::body::reader reader(body); + rpc::request_body::value_type body{}; + rpc::request_body::reader reader(body); boost_code ec{}; reader.init(text.size(), ec); BOOST_REQUIRE(!ec); BOOST_REQUIRE_EQUAL(reader.put(buffer, ec), text.size()); - BOOST_REQUIRE(ec == error::http_error_t::end_of_stream); - BOOST_REQUIRE(!reader.is_done()); + BOOST_REQUIRE(!ec); + BOOST_REQUIRE(!reader.done()); } BOOST_AUTO_TEST_CASE(rpc_body_reader__finish__simple_request_non_terminated__success_expected_request_model_cleared) { const std::string_view text{ R"({"jsonrpc":"2.0","id":1,"method":"test"})" }; const asio::const_buffer buffer{ text.data(), text.size() }; - rpc::body::value_type body{}; + rpc::request_body::value_type body{}; request_header header{}; - rpc::body::reader reader(header, body); + rpc::request_body::reader reader(header, body); boost_code ec{}; reader.init(text.size(), ec); BOOST_REQUIRE(!ec); @@ -120,10 +120,10 @@ BOOST_AUTO_TEST_CASE(rpc_body_reader__finish__simple_request_non_terminated__suc reader.finish(ec); BOOST_REQUIRE(!ec); - BOOST_REQUIRE(body.request.jsonrpc == version::v2); - BOOST_REQUIRE(body.request.id.has_value()); - BOOST_REQUIRE_EQUAL(std::get(body.request.id.value()), 1); - BOOST_REQUIRE_EQUAL(body.request.method, "test"); + BOOST_REQUIRE(body.message.jsonrpc == version::v2); + BOOST_REQUIRE(body.message.id.has_value()); + BOOST_REQUIRE_EQUAL(std::get(body.message.id.value()), 1); + BOOST_REQUIRE_EQUAL(body.message.method, "test"); BOOST_REQUIRE(body.model.is_null()); } @@ -131,8 +131,8 @@ BOOST_AUTO_TEST_CASE(rpc_body_reader__finish__simple_request_terminated_with_new { const std::string_view text{ R"({"jsonrpc":"2.0","id":1,"method":"test"})""\n" }; const asio::const_buffer buffer{ text.data(), text.size() }; - rpc::body::value_type body{}; - rpc::body::reader reader(body); + rpc::request_body::value_type body{}; + rpc::request_body::reader reader(body); boost_code ec{}; reader.init(text.size(), ec); BOOST_REQUIRE(!ec); @@ -142,36 +142,37 @@ BOOST_AUTO_TEST_CASE(rpc_body_reader__finish__simple_request_terminated_with_new reader.finish(ec); BOOST_REQUIRE(!ec); - BOOST_REQUIRE(body.request.jsonrpc == version::v2); - BOOST_REQUIRE(body.request.id.has_value()); - BOOST_REQUIRE_EQUAL(std::get(body.request.id.value()), 1); - BOOST_REQUIRE_EQUAL(body.request.method, "test"); + BOOST_REQUIRE(body.message.jsonrpc == version::v2); + BOOST_REQUIRE(body.message.id.has_value()); + BOOST_REQUIRE_EQUAL(std::get(body.message.id.value()), 1); + BOOST_REQUIRE_EQUAL(body.message.method, "test"); BOOST_REQUIRE(body.model.is_null()); } -BOOST_AUTO_TEST_CASE(rpc_body_reader__finish__simple_request_terminated_without_newline__end_of_stream_error) +BOOST_AUTO_TEST_CASE(rpc_body_reader__finish__simple_request_terminated_without_newline__success_not_done) { const std::string_view text{ R"({"jsonrpc":"2.0","id":1,"method":"test"})" }; const asio::const_buffer buffer{ text.data(), text.size() }; - rpc::body::value_type body{}; - rpc::body::reader reader(body); + rpc::request_body::value_type body{}; + rpc::request_body::reader reader(body); boost_code ec{}; reader.init(text.size(), ec); BOOST_REQUIRE(!ec); reader.put(buffer, ec); - BOOST_REQUIRE(ec == error::http_error_t::end_of_stream); + BOOST_REQUIRE(!ec); reader.finish(ec); - BOOST_REQUIRE(ec == error::http_error_t::end_of_stream); + BOOST_REQUIRE(!ec); + BOOST_REQUIRE(!reader.done()); } BOOST_AUTO_TEST_CASE(rpc_body_reader__put__over_length__body_limit) { const std::string_view text{ R"({"jsonrpc":"2.0","id":1,"method":"test"})" }; const asio::const_buffer buffer{ text.data(), text.size() }; - rpc::body::value_type body{}; - rpc::body::reader reader(body); + rpc::request_body::value_type body{}; + rpc::request_body::reader reader(body); boost_code ec{}; reader.init(10, ec); BOOST_REQUIRE(!ec); @@ -181,4 +182,4 @@ BOOST_AUTO_TEST_CASE(rpc_body_reader__put__over_length__body_limit) BOOST_AUTO_TEST_SUITE_END() -#endif // HAVE_SLOW_TESTS +////#endif // HAVE_SLOW_TESTS diff --git a/test/messages/rpc/body_writer.cpp b/test/messages/rpc/body_writer.cpp index 1917d8581..2e6fbbd38 100644 --- a/test/messages/rpc/body_writer.cpp +++ b/test/messages/rpc/body_writer.cpp @@ -18,7 +18,7 @@ */ #include "../../test.hpp" -#if defined(HAVE_SLOW_TESTS) +////#if defined(HAVE_SLOW_TESTS) BOOST_AUTO_TEST_SUITE(rpc_body_writer_tests) @@ -34,41 +34,41 @@ bool operator==(const asio::const_buffer& left, const asio::const_buffer& right) BOOST_AUTO_TEST_CASE(rpc_body_writer__construct1__default__default_response_terminated) { - rpc::body::value_type body{}; - rpc::body::writer writer(body); - BOOST_REQUIRE(body.response.jsonrpc == version::undefined); - BOOST_REQUIRE(!body.response.id.has_value()); - BOOST_REQUIRE(!body.response.error.has_value()); - BOOST_REQUIRE(!body.response.result.has_value()); + rpc::response_body::value_type body{}; + rpc::response_body::writer writer(body); + BOOST_REQUIRE(body.message.jsonrpc == version::undefined); + BOOST_REQUIRE(!body.message.id.has_value()); + BOOST_REQUIRE(!body.message.error.has_value()); + BOOST_REQUIRE(!body.message.result.has_value()); } BOOST_AUTO_TEST_CASE(rpc_body_writer__construct2__default__default_response_non_terminated) { response_header header{}; - rpc::body::value_type body{}; - rpc::body::writer writer(header, body); - BOOST_REQUIRE(body.response.jsonrpc == version::undefined); - BOOST_REQUIRE(!body.response.id.has_value()); - BOOST_REQUIRE(!body.response.error.has_value()); - BOOST_REQUIRE(!body.response.result.has_value()); + rpc::response_body::value_type body{}; + rpc::response_body::writer writer(header, body); + BOOST_REQUIRE(body.message.jsonrpc == version::undefined); + BOOST_REQUIRE(!body.message.id.has_value()); + BOOST_REQUIRE(!body.message.error.has_value()); + BOOST_REQUIRE(!body.message.result.has_value()); } BOOST_AUTO_TEST_CASE(rpc_body_writer__init__default__success) { - rpc::body::value_type body{}; - rpc::body::writer writer(body); + rpc::response_body::value_type body{}; + rpc::response_body::writer writer(body); boost_code ec{}; writer.init(ec); BOOST_REQUIRE(!ec); } -BOOST_AUTO_TEST_CASE(rpc_body_writer__get__null_response_non_terminated__success_expected_no_more) +BOOST_AUTO_TEST_CASE(rpc_body_writer__get__null_response_non_terminated__success_expected_more) { - const std::string_view expected{ R"({"error":null})" }; + const std::string_view expected{ R"({"error":null,"result":null})" }; const asio::const_buffer out{ expected.data(), expected.size() }; - rpc::body::value_type body{}; + rpc::response_body::value_type body{}; response_header header{}; - rpc::body::writer writer(header, body); + rpc::response_body::writer writer(header, body); boost_code ec{}; writer.init(ec); BOOST_REQUIRE(!ec); @@ -77,17 +77,17 @@ BOOST_AUTO_TEST_CASE(rpc_body_writer__get__null_response_non_terminated__success BOOST_REQUIRE(!ec); BOOST_REQUIRE(buffer.has_value()); BOOST_REQUIRE(buffer.get().first == out); - BOOST_REQUIRE(!buffer.get().second); + BOOST_REQUIRE(buffer.get().second); } -BOOST_AUTO_TEST_CASE(rpc_body_writer__get__simple_response_non_terminated__success_expected_no_more) +BOOST_AUTO_TEST_CASE(rpc_body_writer__get__simple_response_non_terminated__success_expected_more) { const std::string_view expected{ R"({"jsonrpc":"2.0","id":1,"result":true})" }; const asio::const_buffer out{ expected.data(), expected.size() }; - rpc::body::value_type body{}; - body.response = response_t{ version::v2, identity_t{ 1 }, {}, value_t{ true } }; + rpc::response_body::value_type body{}; + body.message = response_t{ version::v2, identity_t{ 1 }, {}, value_t{ true } }; response_header header{}; - rpc::body::writer writer(header, body); + rpc::response_body::writer writer(header, body); boost_code ec{}; writer.init(ec); BOOST_REQUIRE(!ec); @@ -96,16 +96,16 @@ BOOST_AUTO_TEST_CASE(rpc_body_writer__get__simple_response_non_terminated__succe BOOST_REQUIRE(!ec); BOOST_REQUIRE(buffer.has_value()); BOOST_REQUIRE(buffer.get().first == out); - BOOST_REQUIRE(!buffer.get().second); + BOOST_REQUIRE(buffer.get().second); } BOOST_AUTO_TEST_CASE(rpc_body_writer__get__simple_response_terminated__success_expected_with_newline_no_more) { const std::string_view expected_json{ R"({"jsonrpc":"2.0","id":1,"result":true})" }; const std::string_view expected_newline{ "\n" }; - rpc::body::value_type body{}; - body.response = response_t{ version::v2, identity_t{ 1 }, {}, value_t{ true } }; - rpc::body::writer writer(body); + rpc::response_body::value_type body{}; + body.message = response_t{ version::v2, identity_t{ 1 }, {}, value_t{ true } }; + rpc::response_body::writer writer(body); boost_code ec{}; writer.init(ec); BOOST_REQUIRE(!ec); @@ -130,4 +130,4 @@ BOOST_AUTO_TEST_CASE(rpc_body_writer__get__simple_response_terminated__success_e BOOST_AUTO_TEST_SUITE_END() -#endif // HAVE_SLOW_TESTS +////#endif // HAVE_SLOW_TESTS