diff --git a/include/mysql/impl/constants.hpp b/include/mysql/impl/constants.hpp index a1d90bef..5d3de381 100644 --- a/include/mysql/impl/constants.hpp +++ b/include/mysql/impl/constants.hpp @@ -87,14 +87,18 @@ constexpr std::uint16_t num = 32768; // Field is num (for clients) } // Prepared statements -constexpr std::uint8_t CURSOR_TYPE_NO_CURSOR = 0; -constexpr std::uint8_t CURSOR_TYPE_READ_ONLY = 1; -constexpr std::uint8_t CURSOR_TYPE_FOR_UPDATE = 2; -constexpr std::uint8_t CURSOR_TYPE_SCROLLABLE = 4; +namespace cursor_types +{ +constexpr std::uint8_t no_cursor = 0; +constexpr std::uint8_t read_only = 1; +constexpr std::uint8_t for_update = 2; +constexpr std::uint8_t scrollable = 4; +} + } } -#endif \ No newline at end of file +#endif diff --git a/include/mysql/impl/messages.ipp b/include/mysql/impl/messages.ipp index 40c9ef92..04405be6 100644 --- a/include/mysql/impl/messages.ipp +++ b/include/mysql/impl/messages.ipp @@ -23,13 +23,13 @@ inline protocol_field_type get_protocol_field_type( constexpr auto operator()(std::uint32_t) const noexcept { return protocol_field_type::long_; } constexpr auto operator()(std::int64_t) const noexcept { return protocol_field_type::longlong; } constexpr auto operator()(std::uint64_t) const noexcept { return protocol_field_type::longlong; } - constexpr auto operator()(std::string_view) const noexcept { return protocol_field_type::var_string; } + constexpr auto operator()(std::string_view) const noexcept { return protocol_field_type::varchar; } constexpr auto operator()(float) const noexcept { return protocol_field_type::float_; } constexpr auto operator()(double) const noexcept { return protocol_field_type::double_; } constexpr auto operator()(date) const noexcept { return protocol_field_type::date; } constexpr auto operator()(datetime) const noexcept { return protocol_field_type::datetime; } constexpr auto operator()(time) const noexcept { return protocol_field_type::time; } - constexpr auto operator()(year) const noexcept { return protocol_field_type::year; } + constexpr auto operator()(year) const noexcept { return protocol_field_type::short_; } constexpr auto operator()(std::nullptr_t) const noexcept { return protocol_field_type::null; } }; return std::visit(visitor(), input); @@ -45,7 +45,8 @@ inline bool is_unsigned( return std::visit([](auto v) { using type = decltype(v); return std::is_same_v || - std::is_same_v; + std::is_same_v || + std::is_same_v; }, input); } diff --git a/test/common/test_common.hpp b/test/common/test_common.hpp index 206698ab..d5a5106a 100644 --- a/test/common/test_common.hpp +++ b/test/common/test_common.hpp @@ -6,6 +6,7 @@ #include #include #include +#include namespace mysql { @@ -69,6 +70,12 @@ inline std::string_view makesv(const std::uint8_t (&value) [N]) return std::string_view(reinterpret_cast(value), N); } +inline std::string_view makesv(const std::uint8_t* value, std::size_t size) +{ + return std::string_view(reinterpret_cast(value), size); +} + + inline void validate_string_contains(std::string value, const std::vector& to_check) { std::transform(value.begin(), value.end(), value.begin(), &tolower); @@ -83,6 +90,31 @@ inline void validate_error_info(const mysql::error_info& value, const std::vecto validate_string_contains(value.message(), to_check); } +inline std::string buffer_diff(std::string_view s0, std::string_view s1) +{ + std::ostringstream ss; + ss << std::hex; + for (std::size_t i = 0; i < std::min(s0.size(), s1.size()); ++i) + { + unsigned b0 = reinterpret_cast(s0.data())[i]; + unsigned b1 = reinterpret_cast(s1.data())[i]; + if (b0 != b1) + { + ss << "i=" << i << ": " << b0 << " != " << b1 << "\n"; + } + } + if (s0.size() != s1.size()) + { + ss << "sizes: " << s0.size() << " != " << s1.size() << "\n"; + } + return ss.str(); +} + +inline void compare_buffers(std::string_view s0, std::string_view s1, const char* msg = "") +{ + EXPECT_EQ(s0, s1) << msg << ":\n" << buffer_diff(s0, s1); +} + } } diff --git a/test/unit/serialization.cpp b/test/unit/serialization.cpp index 52b2e562..5e7774ee 100644 --- a/test/unit/serialization.cpp +++ b/test/unit/serialization.cpp @@ -649,23 +649,128 @@ INSTANTIATE_TEST_SUITE_P(ComStmtExecute, SerializeTest, testing::Values( 0xab, 0x00 }, "uint32_t" + ), + make_stmt_execute_test(1, 0, 1, 1, // stmt ID, flags, itercount, new params + { std::int32_t(-0xabffff) }, { + 0x17, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, + 0x00, 0x00, 0x00, 0x01, 0x03, 0x00, 0x01, 0x00, + 0x54, 0xff + }, + "int32_t" + ), + make_stmt_execute_test(1, 0x80, 1, 1, // stmt ID, flags, itercount, new params + { std::uint64_t(0xabffffabacadae) }, { + 0x17, 0x01, 0x00, 0x00, 0x00, 0x80, 0x01, 0x00, + 0x00, 0x00, 0x00, 0x01, 0x08, 0x80, 0xae, 0xad, + 0xac, 0xab, 0xff, 0xff, 0xab, 0x00 + }, + "uint64_t" + ), + make_stmt_execute_test(1, 0, 1, 1, // stmt ID, flags, itercount, new params + { std::int64_t(-0xabffffabacadae) }, { + 0x17, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, + 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x52, 0x52, + 0x53, 0x54, 0x00, 0x00, 0x54, 0xff + }, + "int64_t" + ), + make_stmt_execute_test(1, 0, 1, 1, // stmt ID, flags, itercount, new params + { std::string_view("test") }, { + 0x17, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, + 0x00, 0x00, 0x00, 0x01, 0x0f, 0x00, 0x04, 0x74, + 0x65, 0x73, 0x74 + }, + "string_view" + ), + make_stmt_execute_test(1, 0, 1, 1, // stmt ID, flags, itercount, new params + { 3.14e20f }, { + 0x17, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, + 0x00, 0x00, 0x00, 0x01, 0x04, 0x00, 0x01, 0x2d, + 0x88, 0x61 + }, + "float" + ), + make_stmt_execute_test(1, 0, 1, 1, // stmt ID, flags, itercount, new params + { 2.1e214 }, { + 0x17, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, + 0x00, 0x00, 0x00, 0x01, 0x05, 0x00, 0x56, 0xc0, + 0xee, 0xa6, 0x95, 0x30, 0x6f, 0x6c + }, + "double" + ), + make_stmt_execute_test(1, 0, 1, 1, // stmt ID, flags, itercount, new params + { makedate(2010, 9, 3) }, { + 0x17, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, + 0x00, 0x00, 0x00, 0x01, 0x0a, 0x00, 0x04, 0xda, + 0x07, 0x09, 0x03 + }, + "date" + ), + make_stmt_execute_test(1, 0, 1, 1, // stmt ID, flags, itercount, new params + { makedt(2010, 9, 3, 10, 30, 59, 231800) }, { + 0x17, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, + 0x00, 0x00, 0x00, 0x01, 0x0c, 0x00, 0x0b, 0xda, + 0x07, 0x09, 0x03, 0x0a, 0x1e, 0x3b, 0x78, 0x89, + 0x03, 0x00 + }, + "datetime" + ), + make_stmt_execute_test(1, 0, 1, 1, // stmt ID, flags, itercount, new params + { maket(230, 30, 59, 231800) }, { + 0x17, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, + 0x00, 0x00, 0x00, 0x01, 0x0b, 0x00, 0x0c, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x0e, 0x1e, 0x3b, 0x78, + 0x89, 0x03, 0x00 + }, + "time" + ), + make_stmt_execute_test(1, 0, 1, 1, // stmt ID, flags, itercount, new params + { mysql::year(2010) }, { + 0x17, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, + 0x00, 0x00, 0x00, 0x01, 0x02, 0x80, 0xda, 0x07 + }, + "year" + ), + make_stmt_execute_test(1, 0, 1, 1, // stmt ID, flags, itercount, new params + { nullptr }, { + 0x17, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, + 0x00, 0x00, 0x01, 0x01, 0x06, 0x00 + }, + "null" + ), + make_stmt_execute_test(2, 0, 1, 1, makevalues( + std::uint32_t(0xabffff), + std::int32_t(-0xabffff), + std::uint64_t(0xabffffabacadae), + std::int64_t(-0xabffffabacadae), + std::string_view("test"), + nullptr, + 2.1e214, + mysql::year(2010), + makedate(2010, 9, 3), + makedt(2010, 9, 3, 10, 30, 59, 231800), + maket(230, 30, 59, 231800), + nullptr, + mysql::year(2010) + ), { + 0x17, 0x02, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, + 0x00, 0x00, 0x20, 0x08, 0x01, 0x03, 0x80, 0x03, + 0x00, 0x08, 0x80, 0x08, 0x00, 0x0f, 0x00, 0x06, + 0x00, 0x05, 0x00, 0x02, 0x80, 0x0a, 0x00, 0x0c, + 0x00, 0x0b, 0x00, 0x06, 0x00, 0x02, 0x80, 0xff, + 0xff, 0xab, 0x00, 0x01, 0x00, 0x54, 0xff, 0xae, + 0xad, 0xac, 0xab, 0xff, 0xff, 0xab, 0x00, 0x52, + 0x52, 0x53, 0x54, 0x00, 0x00, 0x54, 0xff, 0x04, + 0x74, 0x65, 0x73, 0x74, 0x56, 0xc0, 0xee, 0xa6, + 0x95, 0x30, 0x6f, 0x6c, 0xda, 0x07, 0x04, 0xda, + 0x07, 0x09, 0x03, 0x0b, 0xda, 0x07, 0x09, 0x03, + 0x0a, 0x1e, 0x3b, 0x78, 0x89, 0x03, 0x00, 0x0c, + 0x00, 0x09, 0x00, 0x00, 0x00, 0x0e, 0x1e, 0x3b, + 0x78, 0x89, 0x03, 0x00, 0xda, 0x07 + }, + "several_params" ) )); -/* - * std::int32_t, // signed TINYINT, SMALLINT, MEDIUMINT, INT - std::int64_t, // signed BIGINT - std::uint32_t, // unsigned TINYINT, SMALLINT, MEDIUMINT, INT - std::uint64_t, // unsigned BIGINT - std::string_view, // CHAR, VARCHAR, BINARY, VARBINARY, TEXT (all sizes), BLOB (all sizes), ENUM, SET, DECIMAL, BIT, GEOMTRY - float, // FLOAT - double, // DOUBLE - date, // DATE - datetime, // DATETIME, TIMESTAMP - time, // TIME - year, // YEAR - std::nullptr_t // Any of the above when the value is NULL - */ - } // anon namespace diff --git a/test/unit/serialization_test_common.hpp b/test/unit/serialization_test_common.hpp index fbc948e5..1a2c2e90 100644 --- a/test/unit/serialization_test_common.hpp +++ b/test/unit/serialization_test_common.hpp @@ -9,6 +9,7 @@ #include #include "mysql/impl/serialization.hpp" #include "mysql/value.hpp" +#include "test_common.hpp" namespace mysql { @@ -178,11 +179,6 @@ std::vector concat(std::vector&& lhs, const std::vector { - static std::string_view make_buffer_view(const uint8_t* buff, size_t sz) - { - return std::string_view(reinterpret_cast(buff), sz); - } - // get_size void get_size_test() { @@ -203,14 +199,14 @@ struct SerializationFixture : public testing::TestWithParam EXPECT_EQ(ctx.first(), buffer.data() + expected_size) << "Iterator not updated correctly"; // Buffer - std::string_view expected_populated = make_buffer_view(GetParam().expected_buffer.data(), expected_size); - std::string_view actual_populated = make_buffer_view(buffer.data(), expected_size); - EXPECT_EQ(expected_populated, actual_populated) << "Buffer contents incorrect"; + std::string_view expected_populated = test::makesv(GetParam().expected_buffer.data(), expected_size); + std::string_view actual_populated = test::makesv(buffer.data(), expected_size); + test::compare_buffers(expected_populated, actual_populated, "Buffer contents incorrect"); // Check for buffer overruns std::string expected_clean (8, 0x7a); - std::string_view actual_clean = make_buffer_view(buffer.data() + expected_size, 8); - EXPECT_EQ(expected_clean, actual_clean) << "Buffer overrun"; + std::string_view actual_clean = test::makesv(buffer.data() + expected_size, 8); + test::compare_buffers(expected_clean, actual_clean, "Buffer overrun"); } // deserialize