From 5fb02cfe58c57057f92e130f9fcef5d25cd9ce0c Mon Sep 17 00:00:00 2001 From: ruben Date: Tue, 12 May 2020 11:07:19 +0100 Subject: [PATCH] Added missing test file --- TODO.txt | 1 - .../detail/protocol/row_deserialization.cpp | 256 ++++++++++++++++++ 2 files changed, 256 insertions(+), 1 deletion(-) create mode 100644 test/unit/detail/protocol/row_deserialization.cpp diff --git a/TODO.txt b/TODO.txt index 6dd5e317..4459b42f 100644 --- a/TODO.txt +++ b/TODO.txt @@ -1,5 +1,4 @@ Sanitize - See if we have any trouble with user input in binary serialization: make assertions Test with an unknown protocol type Remove int1_signed, int2_signed... Remove int1, int2, int4, int8 diff --git a/test/unit/detail/protocol/row_deserialization.cpp b/test/unit/detail/protocol/row_deserialization.cpp new file mode 100644 index 00000000..60643cbc --- /dev/null +++ b/test/unit/detail/protocol/row_deserialization.cpp @@ -0,0 +1,256 @@ +// +// Copyright (c) 2019-2020 Ruben Perez Hidalgo (rubenperez038 at gmail dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +// Tests for both deserialize_binary_row() and deserialize_text_row() + +#include +#include "boost/mysql/detail/protocol/text_deserialization.hpp" +#include "boost/mysql/detail/protocol/binary_deserialization.hpp" +#include "boost/mysql/detail/network_algorithms/common.hpp" // for deserialize_row_fn +#include "test_common.hpp" + +using namespace boost::mysql::detail; +using namespace boost::mysql::test; +using namespace testing; +using boost::mysql::value; +using boost::mysql::collation; +using boost::mysql::error_code; +using boost::mysql::errc; +using boost::mysql::field_metadata; + +namespace +{ + +// Common +std::vector make_meta( + const std::vector& types +) +{ + std::vector res; + for (const auto type: types) + { + column_definition_packet coldef; + coldef.type = type; + res.emplace_back(coldef); + } + return res; +} + +// Success cases +struct row_testcase : named_param +{ + deserialize_row_fn deserializer; + std::string name; + std::vector from; + std::vector expected; + std::vector meta; + + row_testcase( + deserialize_row_fn deserializer, + std::string name, + std::vector&& from, + std::vector expected, + const std::vector& types + ): + deserializer(deserializer), + name(std::move(name)), + from(std::move(from)), + expected(std::move(expected)), + meta(make_meta(types)) + { + assert(this->expected.size() == this->meta.size()); + } +}; + +struct DeserializeRowTest : public TestWithParam +{ +}; + +TEST_P(DeserializeRowTest, CorrectFormat_SetsOutputValueReturnsTrue) +{ + const auto& buffer = GetParam().from; + deserialization_context ctx (buffer.data(), buffer.data() + buffer.size(), capabilities()); + + std::vector actual; + auto err = GetParam().deserializer(ctx, GetParam().meta, actual); + EXPECT_EQ(err, error_code()); + EXPECT_EQ(actual, GetParam().expected); +} + +// Error cases +struct row_err_testcase : named_param +{ + deserialize_row_fn deserializer; + std::string name; + std::vector from; + errc expected; + std::vector meta; + + row_err_testcase( + deserialize_row_fn deserializer, + std::string name, + std::vector&& from, + errc expected, + std::vector types + ): + deserializer(deserializer), + name(std::move(name)), + from(std::move(from)), + expected(expected), + meta(make_meta(types)) + { + } +}; + +struct DeserializeRowErrorTest : public TestWithParam +{ +}; + +TEST_P(DeserializeRowErrorTest, ErrorCondition_ReturnsErrorCode) +{ + const auto& buffer = GetParam().from; + deserialization_context ctx (buffer.data(), buffer.data() + buffer.size(), capabilities()); + + std::vector actual; + auto err = GetParam().deserializer(ctx, GetParam().meta, actual); + EXPECT_EQ(err, make_error_code(GetParam().expected)); +} + +// Helpers to make things less verbose +constexpr auto text = &deserialize_text_row; +constexpr auto bin = &deserialize_binary_row; + +// Instantiations for text protocol +INSTANTIATE_TEST_SUITE_P(Text, DeserializeRowTest, Values( + row_testcase( + text, + "one_value", + {0x01, 0x35}, + makevalues(std::int32_t(5)), + { protocol_field_type::tiny } + ), + row_testcase( + text, + "one_null", + {0xfb}, + makevalues(nullptr), + { protocol_field_type::tiny } + ), + row_testcase( + text, + "several_values", + {0x03, 0x76, 0x61, 0x6c, 0x02, 0x32, 0x31, 0x03, 0x30, 0x2e, 0x30}, + makevalues("val", std::int32_t(21), 0.0f), + { protocol_field_type::var_string, protocol_field_type::long_, protocol_field_type::float_ } + ), + row_testcase( + text, + "several_values_one_null", + {0x03, 0x76, 0x61, 0x6c, 0xfb, 0x03, 0x30, 0x2e, 0x30}, + makevalues("val", nullptr, 0.0f), + { protocol_field_type::var_string, protocol_field_type::long_, protocol_field_type::float_ } + ), + row_testcase( + text, + "several_nulls", + {0xfb, 0xfb, 0xfb}, + makevalues(nullptr, nullptr, nullptr), + { protocol_field_type::var_string, protocol_field_type::long_, protocol_field_type::datetime } + ) +), test_name_generator); + +INSTANTIATE_TEST_SUITE_P(Text, DeserializeRowErrorTest, testing::Values( + row_err_testcase(text, "no_space_string_single", {0x02, 0x00}, errc::incomplete_message, + {protocol_field_type::short_}), + row_err_testcase(text, "no_space_string_final", {0x01, 0x35, 0x02, 0x35}, errc::incomplete_message, + {protocol_field_type::tiny, protocol_field_type::short_}), + row_err_testcase(text, "no_space_null_single", {}, errc::incomplete_message, + {protocol_field_type::tiny}), + row_err_testcase(text, "no_space_null_final", {0xfb}, errc::incomplete_message, + {protocol_field_type::tiny, protocol_field_type::tiny}), + row_err_testcase(text, "extra_bytes", {0x01, 0x35, 0xfb, 0x00}, errc::extra_bytes, + {protocol_field_type::tiny, protocol_field_type::tiny}), + row_err_testcase(text, "contained_value_error_single", {0x01, 0x00}, errc::protocol_value_error, + {protocol_field_type::date}), + row_err_testcase(text, "contained_value_error_middle", {0xfb, 0x01, 0x00, 0xfb}, errc::protocol_value_error, + {protocol_field_type::date, protocol_field_type::date, protocol_field_type::date}) +), test_name_generator); + +// Instantiations for binary protocol +INSTANTIATE_TEST_SUITE_P(Binary, DeserializeRowTest, testing::Values( + row_testcase(bin, "one_value", {0x00, 0x00, 0x14}, + makevalues(std::int32_t(20)), + {protocol_field_type::tiny}), + row_testcase(bin, "one_null", {0x00, 0x04}, + makevalues(nullptr), + {protocol_field_type::tiny}), + row_testcase(bin, "two_values", {0x00, 0x00, 0x03, 0x6d, 0x69, 0x6e, 0x6d, 0x07}, + makevalues("min", std::int32_t(1901)), + {protocol_field_type::var_string, protocol_field_type::short_}), + row_testcase(bin, "one_value_one_null", {0x00, 0x08, 0x03, 0x6d, 0x61, 0x78}, + makevalues("max", nullptr), + {protocol_field_type::var_string, protocol_field_type::tiny}), + row_testcase(bin, "two_nulls", {0x00, 0x0c}, + makevalues(nullptr, nullptr), + {protocol_field_type::tiny, protocol_field_type::tiny}), + row_testcase(bin, "six_nulls", {0x00, 0xfc}, + std::vector(6, value(nullptr)), + std::vector(6, protocol_field_type::tiny)), + row_testcase(bin, "seven_nulls", {0x00, 0xfc, 0x01}, + std::vector(7, value(nullptr)), + std::vector(7, protocol_field_type::tiny)), + row_testcase(bin, "several_values", { + 0x00, 0x90, 0x00, 0xfd, 0x14, 0x00, 0xc3, 0xf5, 0x48, + 0x40, 0x02, 0x61, 0x62, 0x04, 0xe2, 0x07, 0x0a, + 0x05, 0x71, 0x99, 0x6d, 0xe2, 0x93, 0x4d, 0xf5, + 0x3d + }, makevalues( + std::int32_t(-3), + std::int32_t(20), + nullptr, + 3.14f, + "ab", + nullptr, + makedate(2018, 10, 5), + 3.10e-10 + ), { + protocol_field_type::tiny, + protocol_field_type::short_, + protocol_field_type::long_, + protocol_field_type::float_, + protocol_field_type::string, + protocol_field_type::long_, + protocol_field_type::date, + protocol_field_type::double_ + } + ) +), test_name_generator); + +INSTANTIATE_TEST_SUITE_P(Binary, DeserializeRowErrorTest, testing::Values( + row_err_testcase(bin, "no_space_null_bitmap_1", {0x00}, + errc::incomplete_message, + {protocol_field_type::tiny}), + row_err_testcase(bin, "no_space_null_bitmap_2", {0x00, 0xfc}, + errc::incomplete_message, + std::vector(7, protocol_field_type::tiny)), + row_err_testcase(bin, "no_space_value_single", {0x00, 0x00}, + errc::incomplete_message, + {protocol_field_type::tiny}), + row_err_testcase(bin, "no_space_value_last", {0x00, 0x00, 0x01}, + errc::incomplete_message, + std::vector(2, protocol_field_type::tiny)), + row_err_testcase(bin, "no_space_value_middle", {0x00, 0x00, 0x01}, + errc::incomplete_message, + std::vector(3, protocol_field_type::tiny)), + row_err_testcase(bin, "extra_bytes", {0x00, 0x00, 0x01, 0x02}, + errc::extra_bytes, + {protocol_field_type::tiny}) +), test_name_generator); + + +} // anon namespace +