From 955c79e664df1129708180c0df9a9d7547c35c51 Mon Sep 17 00:00:00 2001 From: Thiago Silva <82097354+thsfs@users.noreply.github.com> Date: Tue, 7 Mar 2023 12:48:57 -0300 Subject: [PATCH] Migrate tests from the old message_parser to test the message_deserializer class (#4166) * Replace message_parser test for confirm_ack to test message_deserializer The old test checked the bytes generated the same confirm_ack object by ensuring its visitor was processed only once. Also verified the parse_status was success. In the new implementation the visitor isn't part of the deserializer. The outcome object is compared to the original, and the parse_status should be success. This is the sanity test, where the deserialization is expected to happen successfully. Also checks if the message pointer can be downcast to the proper type, that is the same of verifying its type is supported. * Move message_parser confirm_req tests to the message_deserializer format * Move message_parser publish test to the message_deserializer format * Move message_parser keepalive test to the message_deserializer format * Remove the dev_visitor class * Add message_deserialize tests for all the remaining message types * Add more comments to the message_deserializer_success_checker function * Update the file name to core_test/message_deserializer.cpp --- nano/core_test/CMakeLists.txt | 2 +- nano/core_test/message_deserializer.cpp | 223 ++++++++++++++++++++ nano/core_test/message_parser.cpp | 258 ------------------------ 3 files changed, 224 insertions(+), 259 deletions(-) create mode 100644 nano/core_test/message_deserializer.cpp delete mode 100644 nano/core_test/message_parser.cpp 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); -}