diff --git a/nano/core_test/CMakeLists.txt b/nano/core_test/CMakeLists.txt index 79f3d758..dcd6734d 100644 --- a/nano/core_test/CMakeLists.txt +++ b/nano/core_test/CMakeLists.txt @@ -28,7 +28,7 @@ add_executable( locks.cpp logger.cpp message.cpp - message_parser.cpp + message_deserializer.cpp memory_pool.cpp network.cpp network_filter.cpp diff --git a/nano/core_test/message_deserializer.cpp b/nano/core_test/message_deserializer.cpp new file mode 100644 index 00000000..9363b405 --- /dev/null +++ b/nano/core_test/message_deserializer.cpp @@ -0,0 +1,223 @@ +#include +#include +#include + +#include + +#include + +#include +#include + +// Test the successful cases for message_deserializer, checking the supported message types and +// the integrity of the deserialized outcome. +template +auto message_deserializer_success_checker (message_type & message_original) -> void +{ + // Dependencies for the message deserializer. + nano::network_filter filter (1); + nano::block_uniquer block_uniquer; + nano::vote_uniquer vote_uniquer (block_uniquer); + + // Data used to simulate the incoming buffer to be deserialized, the offset tracks how much has been read from the input_source + // as the read function is called first to read the header, then called again to read the payload. + std::vector input_source; + auto offset = 0u; + + // Message Deserializer with the query function tweaked to read from the `input_source`. + auto const message_deserializer = std::make_shared (nano::dev::network_params.network, filter, block_uniquer, vote_uniquer, + [&input_source, &offset] (std::shared_ptr> const & data_a, size_t size_a, std::function callback_a) { + debug_assert (input_source.size () >= size_a); + data_a->resize (size_a); + auto const copy_start = input_source.begin () + offset; + std::copy (copy_start, copy_start + size_a, data_a->data ()); + offset += size_a; + callback_a (boost::system::errc::make_error_code (boost::system::errc::success), size_a); + }); + + // Generating the values for the `input_source`. + { + nano::vectorstream stream (input_source); + message_original.serialize (stream); + } + + // Deserializing and testing the success path. + message_deserializer->read ( + [&message_original] (boost::system::error_code ec_a, std::unique_ptr message_a) { + auto deserialized_message = dynamic_cast (message_a.get ()); + // Ensure the message type is supported. + ASSERT_NE (deserialized_message, nullptr); + auto deserialized_bytes = deserialized_message->to_bytes (); + auto original_bytes = message_original.to_bytes (); + // Ensure the integrity of the deserialized message. + ASSERT_EQ (*deserialized_bytes, *original_bytes); + }); + // This is a sanity test, to ensure the successful deserialization case passes. + ASSERT_EQ (message_deserializer->status, nano::transport::message_deserializer::parse_status::success); +} + +TEST (message_deserializer, exact_confirm_ack) +{ + nano::test::system system{ 1 }; + nano::block_builder builder; + auto block = builder + .send () + .previous (1) + .destination (1) + .balance (2) + .sign (nano::keypair ().prv, 4) + .work (*system.work.generate (nano::root (1))) + .build_shared (); + auto vote (std::make_shared (0, nano::keypair ().prv, 0, 0, std::vector{ block->hash () })); + nano::confirm_ack message{ nano::dev::network_params.network, vote }; + + message_deserializer_success_checker (message); +} + +TEST (message_deserializer, exact_confirm_req) +{ + nano::test::system system{ 1 }; + nano::block_builder builder; + auto block = builder + .send () + .previous (1) + .destination (1) + .balance (2) + .sign (nano::keypair ().prv, 4) + .work (*system.work.generate (nano::root (1))) + .build_shared (); + nano::confirm_req message{ nano::dev::network_params.network, block }; + + message_deserializer_success_checker (message); +} + +TEST (message_deserializer, exact_confirm_req_hash) +{ + nano::test::system system{ 1 }; + nano::block_builder builder; + auto block = builder + .send () + .previous (1) + .destination (1) + .balance (2) + .sign (nano::keypair ().prv, 4) + .work (*system.work.generate (nano::root (1))) + .build (); + // This test differs from the previous `exact_confirm_req` because this tests the confirm_req created from the block hash. + nano::confirm_req message{ nano::dev::network_params.network, block->hash (), block->root () }; + + message_deserializer_success_checker (message); +} + +TEST (message_deserializer, exact_publish) +{ + nano::test::system system{ 1 }; + nano::block_builder builder; + auto block = builder + .send () + .previous (1) + .destination (1) + .balance (2) + .sign (nano::keypair ().prv, 4) + .work (*system.work.generate (nano::root (1))) + .build_shared (); + nano::publish message{ nano::dev::network_params.network, block }; + + message_deserializer_success_checker (message); +} + +TEST (message_deserializer, exact_keepalive) +{ + nano::keepalive message{ nano::dev::network_params.network }; + + message_deserializer_success_checker (message); +} + +TEST (message_deserializer, exact_frontier_req) +{ + nano::frontier_req message{ nano::dev::network_params.network }; + message_deserializer_success_checker (message); +} + +TEST (message_deserializer, exact_telemetry_req) +{ + nano::telemetry_req message{ nano::dev::network_params.network }; + message_deserializer_success_checker (message); +} + +TEST (message_deserializer, exact_telemetry_ack) +{ + nano::telemetry_data data; + data.unknown_data.push_back (0xFF); + + nano::telemetry_ack message{ nano::dev::network_params.network, data }; + message_deserializer_success_checker (message); +} + +TEST (message_deserializer, exact_bulk_pull) +{ + nano::bulk_pull message{ nano::dev::network_params.network }; + message.header.flag_set (nano::message_header::bulk_pull_ascending_flag); + + message_deserializer_success_checker (message); +} + +TEST (message_deserializer, exact_bulk_pull_account) +{ + nano::bulk_pull_account message{ nano::dev::network_params.network }; + message.flags = nano::bulk_pull_account_flags::pending_address_only; + + message_deserializer_success_checker (message); +} + +TEST (message_deserializer, exact_bulk_push) +{ + nano::bulk_push message{ nano::dev::network_params.network }; + message_deserializer_success_checker (message); +} + +TEST (message_deserializer, exact_node_id_handshake) +{ + nano::node_id_handshake message{ nano::dev::network_params.network, boost::none, boost::none }; + message_deserializer_success_checker (message); +} + +TEST (message_deserializer, exact_asc_pull_req) +{ + nano::asc_pull_req message{ nano::dev::network_params.network }; + + // The asc_pull_req checks for the message fields and the payload to be filled. + message.id = 7; + message.type = nano::asc_pull_type::account_info; + + nano::asc_pull_req::account_info_payload message_payload; + message_payload.target = nano::test::random_account (); + message_payload.target_type = nano::asc_pull_req::hash_type::account; + + message.payload = message_payload; + message.update_header (); + + message_deserializer_success_checker (message); +} + +TEST (message_deserializer, exact_asc_pull_ack) +{ + nano::asc_pull_ack message{ nano::dev::network_params.network }; + + // The asc_pull_ack checks for the message fields and the payload to be filled. + message.id = 11; + message.type = nano::asc_pull_type::account_info; + + nano::asc_pull_ack::account_info_payload message_payload; + message_payload.account = nano::test::random_account (); + message_payload.account_open = nano::test::random_hash (); + message_payload.account_head = nano::test::random_hash (); + message_payload.account_block_count = 932932132; + message_payload.account_conf_frontier = nano::test::random_hash (); + message_payload.account_conf_height = 847312; + + message.payload = message_payload; + message.update_header (); + + message_deserializer_success_checker (message); +} diff --git a/nano/core_test/message_parser.cpp b/nano/core_test/message_parser.cpp deleted file mode 100644 index 532a036a..00000000 --- a/nano/core_test/message_parser.cpp +++ /dev/null @@ -1,258 +0,0 @@ -#include -#include - -#include - -namespace -{ -class dev_visitor : public nano::message_visitor -{ -public: - void keepalive (nano::keepalive const &) override - { - ++keepalive_count; - } - void publish (nano::publish const &) override - { - ++publish_count; - } - void confirm_req (nano::confirm_req const &) override - { - ++confirm_req_count; - } - void confirm_ack (nano::confirm_ack const &) override - { - ++confirm_ack_count; - } - void bulk_pull (nano::bulk_pull const &) override - { - ASSERT_FALSE (true); - } - void bulk_pull_account (nano::bulk_pull_account const &) override - { - ASSERT_FALSE (true); - } - void bulk_push (nano::bulk_push const &) override - { - ASSERT_FALSE (true); - } - void frontier_req (nano::frontier_req const &) override - { - ASSERT_FALSE (true); - } - void node_id_handshake (nano::node_id_handshake const &) override - { - ASSERT_FALSE (true); - } - void telemetry_req (nano::telemetry_req const &) override - { - ASSERT_FALSE (true); - } - void telemetry_ack (nano::telemetry_ack const &) override - { - ASSERT_FALSE (true); - } - - uint64_t keepalive_count{ 0 }; - uint64_t publish_count{ 0 }; - uint64_t confirm_req_count{ 0 }; - uint64_t confirm_ack_count{ 0 }; -}; -} - -TEST (message_parser, exact_confirm_ack_size) -{ - nano::test::system system (1); - dev_visitor visitor; - nano::network_filter filter (1); - nano::block_uniquer block_uniquer; - nano::vote_uniquer vote_uniquer (block_uniquer); - nano::message_parser parser (filter, block_uniquer, vote_uniquer, visitor, system.work, nano::dev::network_params.network); - nano::block_builder builder; - auto block = builder - .send () - .previous (1) - .destination (1) - .balance (2) - .sign (nano::keypair ().prv, 4) - .work (*system.work.generate (nano::root (1))) - .build_shared (); - auto vote (std::make_shared (0, nano::keypair ().prv, 0, 0, std::vector{ block->hash () })); - nano::confirm_ack message{ nano::dev::network_params.network, vote }; - std::vector bytes; - { - nano::vectorstream stream (bytes); - message.serialize (stream); - } - ASSERT_EQ (0, visitor.confirm_ack_count); - ASSERT_EQ (parser.status, nano::message_parser::parse_status::success); - auto error (false); - nano::bufferstream stream1 (bytes.data (), bytes.size ()); - nano::message_header header1 (error, stream1); - ASSERT_FALSE (error); - parser.deserialize_confirm_ack (stream1, header1); - ASSERT_EQ (1, visitor.confirm_ack_count); - ASSERT_EQ (parser.status, nano::message_parser::parse_status::success); - bytes.push_back (0); - nano::bufferstream stream2 (bytes.data (), bytes.size ()); - nano::message_header header2 (error, stream2); - ASSERT_FALSE (error); - parser.deserialize_confirm_ack (stream2, header2); - ASSERT_EQ (1, visitor.confirm_ack_count); - ASSERT_NE (parser.status, nano::message_parser::parse_status::success); -} - -TEST (message_parser, exact_confirm_req_size) -{ - nano::test::system system (1); - dev_visitor visitor; - nano::network_filter filter (1); - nano::block_uniquer block_uniquer; - nano::vote_uniquer vote_uniquer (block_uniquer); - nano::message_parser parser (filter, block_uniquer, vote_uniquer, visitor, system.work, nano::dev::network_params.network); - nano::block_builder builder; - auto block = builder - .send () - .previous (1) - .destination (1) - .balance (2) - .sign (nano::keypair ().prv, 4) - .work (*system.work.generate (nano::root (1))) - .build_shared (); - nano::confirm_req message{ nano::dev::network_params.network, block }; - std::vector bytes; - { - nano::vectorstream stream (bytes); - message.serialize (stream); - } - ASSERT_EQ (0, visitor.confirm_req_count); - ASSERT_EQ (parser.status, nano::message_parser::parse_status::success); - auto error (false); - nano::bufferstream stream1 (bytes.data (), bytes.size ()); - nano::message_header header1 (error, stream1); - ASSERT_FALSE (error); - parser.deserialize_confirm_req (stream1, header1); - ASSERT_EQ (1, visitor.confirm_req_count); - ASSERT_EQ (parser.status, nano::message_parser::parse_status::success); - bytes.push_back (0); - nano::bufferstream stream2 (bytes.data (), bytes.size ()); - nano::message_header header2 (error, stream2); - ASSERT_FALSE (error); - parser.deserialize_confirm_req (stream2, header2); - ASSERT_EQ (1, visitor.confirm_req_count); - ASSERT_NE (parser.status, nano::message_parser::parse_status::success); -} - -TEST (message_parser, exact_confirm_req_hash_size) -{ - nano::test::system system (1); - dev_visitor visitor; - nano::network_filter filter (1); - nano::block_uniquer block_uniquer; - nano::vote_uniquer vote_uniquer (block_uniquer); - nano::message_parser parser (filter, block_uniquer, vote_uniquer, visitor, system.work, nano::dev::network_params.network); - nano::block_builder builder; - auto block = builder - .send () - .previous (1) - .destination (1) - .balance (2) - .sign (nano::keypair ().prv, 4) - .work (*system.work.generate (nano::root (1))) - .build (); - nano::confirm_req message{ nano::dev::network_params.network, block->hash (), block->root () }; - std::vector bytes; - { - nano::vectorstream stream (bytes); - message.serialize (stream); - } - ASSERT_EQ (0, visitor.confirm_req_count); - ASSERT_EQ (parser.status, nano::message_parser::parse_status::success); - auto error (false); - nano::bufferstream stream1 (bytes.data (), bytes.size ()); - nano::message_header header1 (error, stream1); - ASSERT_FALSE (error); - parser.deserialize_confirm_req (stream1, header1); - ASSERT_EQ (1, visitor.confirm_req_count); - ASSERT_EQ (parser.status, nano::message_parser::parse_status::success); - bytes.push_back (0); - nano::bufferstream stream2 (bytes.data (), bytes.size ()); - nano::message_header header2 (error, stream2); - ASSERT_FALSE (error); - parser.deserialize_confirm_req (stream2, header2); - ASSERT_EQ (1, visitor.confirm_req_count); - ASSERT_NE (parser.status, nano::message_parser::parse_status::success); -} - -TEST (message_parser, exact_publish_size) -{ - nano::test::system system (1); - dev_visitor visitor; - nano::network_filter filter (1); - nano::block_uniquer block_uniquer; - nano::vote_uniquer vote_uniquer (block_uniquer); - nano::message_parser parser (filter, block_uniquer, vote_uniquer, visitor, system.work, nano::dev::network_params.network); - nano::block_builder builder; - auto block = builder - .send () - .previous (1) - .destination (1) - .balance (2) - .sign (nano::keypair ().prv, 4) - .work (*system.work.generate (nano::root (1))) - .build_shared (); - nano::publish message{ nano::dev::network_params.network, block }; - std::vector bytes; - { - nano::vectorstream stream (bytes); - message.serialize (stream); - } - ASSERT_EQ (0, visitor.publish_count); - ASSERT_EQ (parser.status, nano::message_parser::parse_status::success); - auto error (false); - nano::bufferstream stream1 (bytes.data (), bytes.size ()); - nano::message_header header1 (error, stream1); - ASSERT_FALSE (error); - parser.deserialize_publish (stream1, header1); - ASSERT_EQ (1, visitor.publish_count); - ASSERT_EQ (parser.status, nano::message_parser::parse_status::success); - bytes.push_back (0); - nano::bufferstream stream2 (bytes.data (), bytes.size ()); - nano::message_header header2 (error, stream2); - ASSERT_FALSE (error); - parser.deserialize_publish (stream2, header2); - ASSERT_EQ (1, visitor.publish_count); - ASSERT_NE (parser.status, nano::message_parser::parse_status::success); -} - -TEST (message_parser, exact_keepalive_size) -{ - nano::test::system system (1); - dev_visitor visitor; - nano::network_filter filter (1); - nano::block_uniquer block_uniquer; - nano::vote_uniquer vote_uniquer (block_uniquer); - nano::message_parser parser (filter, block_uniquer, vote_uniquer, visitor, system.work, nano::dev::network_params.network); - nano::keepalive message{ nano::dev::network_params.network }; - std::vector bytes; - { - nano::vectorstream stream (bytes); - message.serialize (stream); - } - ASSERT_EQ (0, visitor.keepalive_count); - ASSERT_EQ (parser.status, nano::message_parser::parse_status::success); - auto error (false); - nano::bufferstream stream1 (bytes.data (), bytes.size ()); - nano::message_header header1 (error, stream1); - ASSERT_FALSE (error); - parser.deserialize_keepalive (stream1, header1); - ASSERT_EQ (1, visitor.keepalive_count); - ASSERT_EQ (parser.status, nano::message_parser::parse_status::success); - bytes.push_back (0); - nano::bufferstream stream2 (bytes.data (), bytes.size ()); - nano::message_header header2 (error, stream2); - ASSERT_FALSE (error); - parser.deserialize_keepalive (stream2, header2); - ASSERT_EQ (1, visitor.keepalive_count); - ASSERT_NE (parser.status, nano::message_parser::parse_status::success); -}