/* * deserialization.cpp * * Created on: Jun 29, 2019 * Author: ruben */ #include "serialization_test_common.hpp" #include "mysql/impl/messages.hpp" #include "mysql/impl/binary_serialization.hpp" #include "test_common.hpp" using namespace testing; using namespace std; using namespace mysql::detail; using namespace mysql::test; using mysql::Error; using mysql::collation; using mysql::value; namespace { struct DeserializeErrorParams { shared_ptr value; vector buffer; string test_name; Error expected_error; template DeserializeErrorParams create(vector&& buffer, string&& test_name, Error err = Error::incomplete_message) { return DeserializeErrorParams { make_shared>(T{}), move(buffer), move(test_name), err }; } }; ostream& operator<<(ostream& os, const DeserializeErrorParams& params) { return os << params.value->get_type_name() << " - " << params.test_name; } // Special error conditions struct DeserializeErrorTest : testing::TestWithParam { }; TEST_P(DeserializeErrorTest, Deserialize_ErrorCondition_ReturnsErrorCode) { auto first = GetParam().buffer.data(); auto last = GetParam().buffer.data() + GetParam().buffer.size(); DeserializationContext ctx (first, last, capabilities(0)); auto value = GetParam().value->default_construct(); auto err = value->deserialize(ctx); EXPECT_EQ(err, GetParam().expected_error); } // Definitions for the parameterized tests string string_250 (250, 'a'); string string_251 (251, 'a'); string string_ffff (0xffff, 'a'); string string_10000 (0x10000, 'a'); enum class EnumInt1 : uint8_t { value0 = 0, value1 = 3, value2 = 0xff }; enum class EnumInt2 : uint16_t { value0 = 0, value1 = 3, value2 = 0xfeff }; enum class EnumInt4 : uint32_t { value0 = 0, value1 = 3, value2 = 0xfcfdfeff }; INSTANTIATE_TEST_SUITE_P(UnsignedFixedSizeInts, FullSerializationTest, ::testing::Values( SerializeParams(int1(0xff), {0xff}), SerializeParams(int2(0xfeff), {0xff, 0xfe}), SerializeParams(int3(0xfdfeff), {0xff, 0xfe, 0xfd}), SerializeParams(int4(0xfcfdfeff), {0xff, 0xfe, 0xfd, 0xfc}), SerializeParams(int6(0xfafbfcfdfeff), {0xff, 0xfe, 0xfd, 0xfc, 0xfb, 0xfa}), SerializeParams(int8(0xf8f9fafbfcfdfeff), {0xff, 0xfe, 0xfd, 0xfc, 0xfb, 0xfa, 0xf9, 0xf8}) )); INSTANTIATE_TEST_SUITE_P(SignedFixedSizeInts, FullSerializationTest, ::testing::Values( SerializeParams(int1_signed(-1), {0xff}, "Negative"), SerializeParams(int2_signed(-0x101), {0xff, 0xfe}, "Negative"), SerializeParams(int4_signed(-0x3020101), {0xff, 0xfe, 0xfd, 0xfc}, "Negative"), SerializeParams(int8_signed(-0x0706050403020101), {0xff, 0xfe, 0xfd, 0xfc, 0xfb, 0xfa, 0xf9, 0xf8}, "Negative"), SerializeParams(int1_signed(0x01), {0x01}, "Positive"), SerializeParams(int2_signed(0x0201), {0x01, 0x02}, "Positive"), SerializeParams(int4_signed(0x04030201), {0x01, 0x02, 0x03, 0x04}, "Positive"), SerializeParams(int8_signed(0x0807060504030201), {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08}, "Positive") )); INSTANTIATE_TEST_SUITE_P(LengthEncodedInt, FullSerializationTest, ::testing::Values( SerializeParams(int_lenenc(1), {0x01}, "1 byte (regular value)"), SerializeParams(int_lenenc(250), {0xfa}, "1 byte (max value)"), SerializeParams(int_lenenc(0xfeb7), {0xfc, 0xb7, 0xfe}, "2 bytes (regular value)"), SerializeParams(int_lenenc(0xffff), {0xfc, 0xff, 0xff}, "2 bytes (max value)"), SerializeParams(int_lenenc(0xa0feff), {0xfd, 0xff, 0xfe, 0xa0}, "3 bytes (regular value)"), SerializeParams(int_lenenc(0xffffff), {0xfd, 0xff, 0xff, 0xff}, "3 bytes (max value)"), SerializeParams(int_lenenc(0xf8f9fafbfcfdfeff), {0xfe, 0xff, 0xfe, 0xfd, 0xfc, 0xfb, 0xfa, 0xf9, 0xf8}, "8 bytes (regular value)"), SerializeParams(int_lenenc(0xffffffffffffffff), {0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}, "8 bytes (max value)") )); INSTANTIATE_TEST_SUITE_P(FixedSizeString, FullSerializationTest, ::testing::Values( SerializeParams(string_fixed<4>({'a', 'b', 'd', 'e'}), {0x61, 0x62, 0x64, 0x65}, "Regular characters"), SerializeParams(string_fixed<3>({'\0', '\1', 'a'}), {0x00, 0x01, 0x61}, "Null characters"), SerializeParams(string_fixed<3>({char(0xc3), char(0xb1), 'a'}), {0xc3, 0xb1, 0x61}, "UTF-8 characters"), SerializeParams(string_fixed<1>({'a'}), {0x61}, "Size 1 string") )); INSTANTIATE_TEST_SUITE_P(NullTerminatedString, FullSerializationTest, ::testing::Values( SerializeParams(string_null("abc"), {0x61, 0x62, 0x63, 0x00}, "Regular characters"), SerializeParams(string_null("\xc3\xb1"), {0xc3, 0xb1, 0x00}, "UTF-8 characters"), SerializeParams(string_null(""), {0x00}, "Empty string") )); INSTANTIATE_TEST_SUITE_P(LengthEncodedString, FullSerializationTest, ::testing::Values( SerializeParams(string_lenenc(""), {0x00}, "Empty string"), SerializeParams(string_lenenc("abc"), {0x03, 0x61, 0x62, 0x63}, "1 byte size, regular characters"), SerializeParams(string_lenenc(string_view("a\0b", 3)), {0x03, 0x61, 0x00, 0x62}, "1 byte size, null characters"), SerializeParams(string_lenenc(string_250), concat({250}, vector(250, 0x61)), "1 byte size, max"), SerializeParams(string_lenenc(string_251), concat({0xfc, 251, 0}, vector(251, 0x61)), "2 byte size, min"), SerializeParams(string_lenenc(string_ffff), concat({0xfc, 0xff, 0xff}, vector(0xffff, 0x61)), "2 byte size, max"), SerializeParams(string_lenenc(string_10000), concat({0xfd, 0x00, 0x00, 0x01}, vector(0x10000, 0x61)), "3 byte size, max") )); INSTANTIATE_TEST_SUITE_P(EofString, SerializeDeserializeTest, ::testing::Values( SerializeParams(string_eof("abc"), {0x61, 0x62, 0x63}, "Regular characters"), SerializeParams(string_eof(string_view("a\0b", 3)), {0x61, 0x00, 0x62}, "Null characters"), SerializeParams(string_eof(""), {}, "Empty string") )); INSTANTIATE_TEST_SUITE_P(Enums, FullSerializationTest, ::testing::Values( SerializeParams(EnumInt1::value1, {0x03}, "low value"), SerializeParams(EnumInt1::value2, {0xff}, "high value"), SerializeParams(EnumInt2::value1, {0x03, 0x00}, "low value"), SerializeParams(EnumInt2::value2, {0xff, 0xfe}, "high value"), SerializeParams(EnumInt4::value1, {0x03, 0x00, 0x00, 0x00}, "low value"), SerializeParams(EnumInt4::value2, {0xff, 0xfe, 0xfd, 0xfc}, "high value") )); // Other binary values INSTANTIATE_TEST_SUITE_P(Float, FullSerializationTest, ::testing::Values( SerializeParams(value_holder(-4.2f), {0x66, 0x66, 0x86, 0xc0}, "fractional_negative"), SerializeParams(value_holder( 4.2f), {0x66, 0x66, 0x86, 0x40}, "fractional_positive"), SerializeParams(value_holder(3.14e20f), {0x01, 0x2d, 0x88, 0x61}, "positive_exp_positive_fractional"), SerializeParams(value_holder(0.0f), {0x00, 0x00, 0x00, 0x00}, "zero") )); INSTANTIATE_TEST_SUITE_P(Double, FullSerializationTest, ::testing::Values( SerializeParams(value_holder(-4.2), {0xcd, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x10, 0xc0}, "fractional_negative"), SerializeParams(value_holder( 4.2), {0xcd, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x10, 0x40}, "fractional_positive"), SerializeParams(value_holder(3.14e200), {0xce, 0x46, 0x3c, 0x76, 0x9c, 0x68, 0x90, 0x69}, "positive_exp_positive_fractional"), SerializeParams(value_holder(0.0), {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, "zero") )); INSTANTIATE_TEST_SUITE_P(Date, FullSerializationTest, ::testing::Values( SerializeParams(makedate(2010, 3, 28), {0x04, 0xda, 0x07, 0x03, 0x1c}, "regular"), SerializeParams(makedate(1000, 1, 1), {0x04, 0xe8, 0x03, 0x01, 0x01}, "min"), SerializeParams(makedate(9999, 12, 31), {0x04, 0x0f, 0x27, 0x0c, 0x1f}, "max") )); INSTANTIATE_TEST_SUITE_P(Datetime, FullSerializationTest, ::testing::Values( SerializeParams(makedt(2010, 1, 1), {0x04, 0xda, 0x07, 0x01, 0x01}, "only_date"), SerializeParams(makedt(2010, 1, 1, 20, 0, 0, 0), {0x07, 0xda, 0x07, 0x01, 0x01, 0x14, 0x00, 0x00}, "date_h"), SerializeParams(makedt(2010, 1, 1, 0, 1, 0, 0), {0x07, 0xda, 0x07, 0x01, 0x01, 0x00, 0x01, 0x00}, "date_m"), SerializeParams(makedt(2010, 1, 1, 3, 2, 0, 0), {0x07, 0xda, 0x07, 0x01, 0x01, 0x03, 0x02, 0x00}, "date_hm"), SerializeParams(makedt(2010, 1, 1, 0, 0, 1, 0), {0x07, 0xda, 0x07, 0x01, 0x01, 0x00, 0x00, 0x01}, "date_s"), SerializeParams(makedt(2010, 1, 1, 0, 59, 1, 0), {0x07, 0xda, 0x07, 0x01, 0x01, 0x00, 0x3b, 0x01}, "date_ms"), SerializeParams(makedt(2010, 1, 1, 5, 0, 1, 0), {0x07, 0xda, 0x07, 0x01, 0x01, 0x05, 0x00, 0x01}, "date_hs"), SerializeParams(makedt(2010, 1, 1, 23, 1, 59, 0), {0x07, 0xda, 0x07, 0x01, 0x01, 0x17, 0x01, 0x3b}, "date_hms"), SerializeParams(makedt(2010, 1, 1, 0, 0, 0, 251000), {0x0b, 0xda, 0x07, 0x01, 0x01, 0x00, 0x00, 0x00, 0x78, 0xd4, 0x03, 0x00}, "date_u"), SerializeParams(makedt(2010, 1, 1, 23, 0, 0, 967510), {0x0b, 0xda, 0x07, 0x01, 0x01, 0x17, 0x00, 0x00, 0x56, 0xc3, 0x0e, 0x00}, "date_hu"), SerializeParams(makedt(2010, 1, 1, 0, 1, 0, 967510), {0x0b, 0xda, 0x07, 0x01, 0x01, 0x00, 0x01, 0x00, 0x56, 0xc3, 0x0e, 0x00}, "date_mu"), SerializeParams(makedt(2010, 1, 1, 23, 1, 0, 967510), {0x0b, 0xda, 0x07, 0x01, 0x01, 0x17, 0x01, 0x00, 0x56, 0xc3, 0x0e, 0x00}, "date_hmu"), SerializeParams(makedt(2010, 1, 1, 0, 0, 59, 967510), {0x0b, 0xda, 0x07, 0x01, 0x01, 0x00, 0x00, 0x3b, 0x56, 0xc3, 0x0e, 0x00}, "date_su"), SerializeParams(makedt(2010, 1, 1, 0, 1, 59, 967510), {0x0b, 0xda, 0x07, 0x01, 0x01, 0x00, 0x01, 0x3b, 0x56, 0xc3, 0x0e, 0x00}, "date_msu"), SerializeParams(makedt(2010, 1, 1, 23, 0, 59, 967510), {0x0b, 0xda, 0x07, 0x01, 0x01, 0x17, 0x00, 0x3b, 0x56, 0xc3, 0x0e, 0x00}, "date_hsu"), SerializeParams(makedt(2010, 1, 1, 23, 1, 59, 967510), {0x0b, 0xda, 0x07, 0x01, 0x01, 0x17, 0x01, 0x3b, 0x56, 0xc3, 0x0e, 0x00}, "date_hmsu") )); INSTANTIATE_TEST_SUITE_P(Time, FullSerializationTest, ::testing::Values( SerializeParams(maket(0, 0, 0), {0x00}, "zero"), SerializeParams(maket(48, 0, 0, 0), {0x08, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, "positive_d"), SerializeParams(maket(21, 0, 0, 0), {0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00}, "positive_h"), SerializeParams(maket(0, 40, 0), {0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0x00}, "positive_m"), SerializeParams(maket(0, 0, 21), {0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x15}, "positive_s"), SerializeParams(maket(0, 0, 0, 321000), {0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe8, 0xe5, 0x04, 0x00}, "positive_u"), SerializeParams(maket(838, 59, 58, 999000), {0x0c, 0x00, 0x22, 0x00, 0x00, 0x00, 0x16, 0x3b, 0x3a, 0x58, 0x3e, 0x0f, 0x00}, "positive_hmsu"), SerializeParams(-maket(48, 0, 0, 0), {0x08, 0x01, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, "negative_d"), SerializeParams(-maket(21, 0, 0, 0), {0x08, 0x01, 0x00, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00}, "negative_h"), SerializeParams(-maket(0, 40, 0), {0x08, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0x00}, "negative_m"), SerializeParams(-maket(0, 0, 21), {0x08, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x15}, "negative_s"), SerializeParams(-maket(0, 0, 0, 321000), {0x0c, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe8, 0xe5, 0x04, 0x00}, "negative_u"), SerializeParams(-maket(838, 59, 58, 999000), {0x0c, 0x01, 0x22, 0x00, 0x00, 0x00, 0x16, 0x3b, 0x3a, 0x58, 0x3e, 0x0f, 0x00}, "negative_hmsu") )); // Messages INSTANTIATE_TEST_SUITE_P(PacketHeader, FullSerializationTest, ::testing::Values( SerializeParams(packet_header{int3(3), int1(0)}, {0x03, 0x00, 0x00, 0x00}, "small packet, seqnum==0"), SerializeParams(packet_header{int3(9), int1(2)}, {0x09, 0x00, 0x00, 0x02}, "small packet, seqnum!=0"), SerializeParams(packet_header{int3(0xcacbcc), int1(0xfa)}, {0xcc, 0xcb, 0xca, 0xfa}, "big packet, seqnum!=0"), SerializeParams(packet_header{int3(0xffffff), int1(0xff)}, {0xff, 0xff, 0xff, 0xff}, "max packet, max seqnum") )); INSTANTIATE_TEST_SUITE_P(OkPacket, DeserializeTest, ::testing::Values( SerializeParams(ok_packet{ int_lenenc(4), // affected rows int_lenenc(0), // last insert ID int2(SERVER_STATUS_AUTOCOMMIT | SERVER_QUERY_NO_INDEX_USED), // server status int2(0), // warnings string_lenenc("Rows matched: 5 Changed: 4 Warnings: 0") }, { 0x04, 0x00, 0x22, 0x00, 0x00, 0x00, 0x28, 0x52, 0x6f, 0x77, 0x73, 0x20, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x65, 0x64, 0x3a, 0x20, 0x35, 0x20, 0x20, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x64, 0x3a, 0x20, 0x34, 0x20, 0x20, 0x57, 0x61, 0x72, 0x6e, 0x69, 0x6e, 0x67, 0x73, 0x3a, 0x20, 0x30 }, "successful UPDATE"), SerializeParams(ok_packet{ int_lenenc(1), // affected rows int_lenenc(6), // last insert ID int2(SERVER_STATUS_AUTOCOMMIT), // server status int2(0), // warnings string_lenenc("") // no message },{ 0x01, 0x06, 0x02, 0x00, 0x00, 0x00 }, "successful INSERT"), SerializeParams(ok_packet{ int_lenenc(0), // affected rows int_lenenc(0), // last insert ID int2(SERVER_STATUS_AUTOCOMMIT), // server status int2(0), // warnings string_lenenc("") // no message }, { 0x00, 0x00, 0x02, 0x00, 0x00, 0x00 }, "Successful login") )); INSTANTIATE_TEST_SUITE_P(ErrPacket, DeserializeTest, ::testing::Values( SerializeParams(err_packet{ int2(1049), // eror code string_fixed<1>({0x23}), // sql state marker string_fixed<5>({'4', '2', '0', '0', '0'}), // sql state string_eof("Unknown database 'a'") // err msg }, { 0x19, 0x04, 0x23, 0x34, 0x32, 0x30, 0x30, 0x30, 0x55, 0x6e, 0x6b, 0x6e, 0x6f, 0x77, 0x6e, 0x20, 0x64, 0x61, 0x74, 0x61, 0x62, 0x61, 0x73, 0x65, 0x20, 0x27, 0x61, 0x27 }, "Wrong USE database"), SerializeParams(err_packet{ int2(1146), // eror code string_fixed<1>({0x23}), // sql state marker string_fixed<5>({'4', '2', 'S', '0', '2'}), // sql state string_eof("Table 'awesome.unknown' doesn't exist") // err msg }, { 0x7a, 0x04, 0x23, 0x34, 0x32, 0x53, 0x30, 0x32, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x20, 0x27, 0x61, 0x77, 0x65, 0x73, 0x6f, 0x6d, 0x65, 0x2e, 0x75, 0x6e, 0x6b, 0x6e, 0x6f, 0x77, 0x6e, 0x27, 0x20, 0x64, 0x6f, 0x65, 0x73, 0x6e, 0x27, 0x74, 0x20, 0x65, 0x78, 0x69, 0x73, 0x74 }, "Unknown table"), SerializeParams(err_packet{ int2(1045), // error code string_fixed<1>({0x23}), // SQL state marker string_fixed<5>({'2', '8', '0', '0', '0'}), // SQL state string_eof("Access denied for user 'root'@'localhost' (using password: YES)") }, { 0x15, 0x04, 0x23, 0x32, 0x38, 0x30, 0x30, 0x30, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x20, 0x64, 0x65, 0x6e, 0x69, 0x65, 0x64, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x75, 0x73, 0x65, 0x72, 0x20, 0x27, 0x72, 0x6f, 0x6f, 0x74, 0x27, 0x40, 0x27, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x68, 0x6f, 0x73, 0x74, 0x27, 0x20, 0x28, 0x75, 0x73, 0x69, 0x6e, 0x67, 0x20, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x3a, 0x20, 0x59, 0x45, 0x53, 0x29 }, "Failed login") )); constexpr std::uint8_t handshake_auth_plugin_data [] = { 0x52, 0x1a, 0x50, 0x3a, 0x4b, 0x12, 0x70, 0x2f, 0x03, 0x5a, 0x74, 0x05, 0x28, 0x2b, 0x7f, 0x21, 0x43, 0x4a, 0x21, 0x62 }; constexpr std::uint32_t hanshake_caps = CLIENT_LONG_PASSWORD | CLIENT_FOUND_ROWS | CLIENT_LONG_FLAG | CLIENT_CONNECT_WITH_DB | CLIENT_NO_SCHEMA | CLIENT_COMPRESS | CLIENT_ODBC | CLIENT_LOCAL_FILES | CLIENT_IGNORE_SPACE | CLIENT_PROTOCOL_41 | CLIENT_INTERACTIVE | CLIENT_IGNORE_SIGPIPE | CLIENT_TRANSACTIONS | CLIENT_RESERVED | // old flag, but set in this frame CLIENT_RESERVED2 | // old flag, but set in this frame CLIENT_MULTI_STATEMENTS | CLIENT_MULTI_RESULTS | CLIENT_PS_MULTI_RESULTS | CLIENT_PLUGIN_AUTH | CLIENT_CONNECT_ATTRS | CLIENT_PLUGIN_AUTH_LENENC_CLIENT_DATA | CLIENT_CAN_HANDLE_EXPIRED_PASSWORDS | CLIENT_SESSION_TRACK | CLIENT_DEPRECATE_EOF | CLIENT_REMEMBER_OPTIONS; INSTANTIATE_TEST_SUITE_P(Handhsake, DeserializeSpaceTest, ::testing::Values( SerializeParams(handshake_packet{ string_null("5.7.27-0ubuntu0.19.04.1"), // server version int4(2), // connection ID string_lenenc(makesv(handshake_auth_plugin_data)), int4(hanshake_caps), int1(static_cast(collation::latin1_swedish_ci)), int2(SERVER_STATUS_AUTOCOMMIT), string_null("mysql_native_password"), {} // data buffer; internal, not used in the comparisons for correctness }, { 0x35, 0x2e, 0x37, 0x2e, 0x32, 0x37, 0x2d, 0x30, 0x75, 0x62, 0x75, 0x6e, 0x74, 0x75, 0x30, 0x2e, 0x31, 0x39, 0x2e, 0x30, 0x34, 0x2e, 0x31, 0x00, 0x02, 0x00, 0x00, 0x00, 0x52, 0x1a, 0x50, 0x3a, 0x4b, 0x12, 0x70, 0x2f, 0x00, 0xff, 0xf7, 0x08, 0x02, 0x00, 0xff, 0x81, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x5a, 0x74, 0x05, 0x28, 0x2b, 0x7f, 0x21, 0x43, 0x4a, 0x21, 0x62, 0x00, 0x6d, 0x79, 0x73, 0x71, 0x6c, 0x5f, 0x6e, 0x61, 0x74, 0x69, 0x76, 0x65, 0x5f, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x00 }) )); constexpr std::uint8_t handshake_response_auth_data [] = { 0xfe, 0xc6, 0x2c, 0x9f, 0xab, 0x43, 0x69, 0x46, 0xc5, 0x51, 0x35, 0xa5, 0xff, 0xdb, 0x3f, 0x48, 0xe6, 0xfc, 0x34, 0xc9 }; constexpr std::uint32_t handshake_response_caps = CLIENT_LONG_PASSWORD | CLIENT_LONG_FLAG | CLIENT_LOCAL_FILES | CLIENT_PROTOCOL_41 | CLIENT_INTERACTIVE | CLIENT_TRANSACTIONS | CLIENT_RESERVED2 | CLIENT_MULTI_STATEMENTS | CLIENT_MULTI_RESULTS | CLIENT_PS_MULTI_RESULTS | CLIENT_PLUGIN_AUTH | CLIENT_CONNECT_ATTRS | CLIENT_PLUGIN_AUTH_LENENC_CLIENT_DATA | CLIENT_CAN_HANDLE_EXPIRED_PASSWORDS | CLIENT_SESSION_TRACK | CLIENT_DEPRECATE_EOF; INSTANTIATE_TEST_SUITE_P(HandhsakeResponse, SerializeTest, ::testing::Values( SerializeParams(handshake_response_packet{ int4(handshake_response_caps), int4(16777216), // max packet size int1(static_cast(collation::utf8_general_ci)), string_null("root"), string_lenenc(makesv(handshake_response_auth_data)), string_null(""), // Irrelevant, not using connect with DB string_null("mysql_native_password") // auth plugin name }, { 0x85, 0xa6, 0xff, 0x01, 0x00, 0x00, 0x00, 0x01, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x72, 0x6f, 0x6f, 0x74, 0x00, 0x14, 0xfe, 0xc6, 0x2c, 0x9f, 0xab, 0x43, 0x69, 0x46, 0xc5, 0x51, 0x35, 0xa5, 0xff, 0xdb, 0x3f, 0x48, 0xe6, 0xfc, 0x34, 0xc9, 0x6d, 0x79, 0x73, 0x71, 0x6c, 0x5f, 0x6e, 0x61, 0x74, 0x69, 0x76, 0x65, 0x5f, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x00 }, "without database", handshake_response_caps), SerializeParams(handshake_response_packet{ int4(handshake_response_caps | CLIENT_CONNECT_WITH_DB), int4(16777216), // max packet size int1(static_cast(collation::utf8_general_ci)), string_null("root"), string_lenenc(makesv(handshake_response_auth_data)), string_null("database"), // database name string_null("mysql_native_password") // auth plugin name }, { 0x8d, 0xa6, 0xff, 0x01, 0x00, 0x00, 0x00, 0x01, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x72, 0x6f, 0x6f, 0x74, 0x00, 0x14, 0xfe, 0xc6, 0x2c, 0x9f, 0xab, 0x43, 0x69, 0x46, 0xc5, 0x51, 0x35, 0xa5, 0xff, 0xdb, 0x3f, 0x48, 0xe6, 0xfc, 0x34, 0xc9, 0x64, 0x61, 0x74, 0x61, 0x62, 0x61, 0x73, 0x65, 0x00, 0x6d, 0x79, 0x73, 0x71, 0x6c, 0x5f, 0x6e, 0x61, 0x74, 0x69, 0x76, 0x65, 0x5f, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x00 }, "with database", handshake_response_caps | CLIENT_CONNECT_WITH_DB) )); constexpr std::uint8_t auth_switch_request_auth_data [] = { 0x49, 0x49, 0x7e, 0x51, 0x5d, 0x1f, 0x19, 0x6a, 0x0f, 0x5a, 0x63, 0x15, 0x3e, 0x28, 0x31, 0x3e, 0x3c, 0x79, 0x09, 0x7c }; INSTANTIATE_TEST_SUITE_P(AuthSwitchRequest, DeserializeTest, testing::Values( SerializeParams(auth_switch_request_packet{ string_null("mysql_native_password"), string_eof(makesv(auth_switch_request_auth_data)) }, { 0x6d, 0x79, 0x73, 0x71, 0x6c, 0x5f, 0x6e, 0x61, 0x74, 0x69, 0x76, 0x65, 0x5f, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x00, 0x49, 0x49, 0x7e, 0x51, 0x5d, 0x1f, 0x19, 0x6a, 0x0f, 0x5a, 0x63, 0x15, 0x3e, 0x28, 0x31, 0x3e, 0x3c, 0x79, 0x09, 0x7c, 0x00 }) )); constexpr std::uint8_t auth_switch_response_auth_data [] = { 0xba, 0x55, 0x9c, 0xc5, 0x9c, 0xbf, 0xca, 0x06, 0x91, 0xff, 0xaa, 0x72, 0x59, 0xfc, 0x53, 0xdf, 0x88, 0x2d, 0xf9, 0xcf }; INSTANTIATE_TEST_SUITE_P(AuthSwitchResponse, SerializeTest, testing::Values( SerializeParams(auth_switch_response_packet{ string_eof(makesv(auth_switch_response_auth_data)) }, { 0xba, 0x55, 0x9c, 0xc5, 0x9c, 0xbf, 0xca, 0x06, 0x91, 0xff, 0xaa, 0x72, 0x59, 0xfc, 0x53, 0xdf, 0x88, 0x2d, 0xf9, 0xcf }) )); // Column definition INSTANTIATE_TEST_SUITE_P(ColumnDefinition, DeserializeSpaceTest, testing::Values( SerializeParams(column_definition_packet{ string_lenenc("def"), //catalog string_lenenc("awesome"), // schema (database) string_lenenc("test_table"), // table string_lenenc("test_table"), // physical table string_lenenc("id"), // field name string_lenenc("id"), // physical field name collation::binary, int4(11), // length protocol_field_type::long_, int2( column_flags::not_null | column_flags::pri_key | column_flags::auto_increment | column_flags::part_key ), int1(0) // decimals }, { 0x03, 0x64, 0x65, 0x66, 0x07, 0x61, 0x77, 0x65, 0x73, 0x6f, 0x6d, 0x65, 0x0a, 0x74, 0x65, 0x73, 0x74, 0x5f, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x0a, 0x74, 0x65, 0x73, 0x74, 0x5f, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x02, 0x69, 0x64, 0x02, 0x69, 0x64, 0x0c, 0x3f, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x03, 0x03, 0x42, 0x00, 0x00, 0x00 }, "Numeric, auto-increment primary key"), SerializeParams(column_definition_packet{ string_lenenc("def"), //catalog string_lenenc("awesome"), // schema (database) string_lenenc("child"), // table string_lenenc("child_table"), // physical table string_lenenc("field_alias"), // field name string_lenenc("field_varchar"), // physical field name collation::utf8_general_ci, int4(765), // length protocol_field_type::var_string, int2(), // no column flags int1(0) // decimals }, { 0x03, 0x64, 0x65, 0x66, 0x07, 0x61, 0x77, 0x65, 0x73, 0x6f, 0x6d, 0x65, 0x05, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x0b, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x5f, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x0b, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x5f, 0x61, 0x6c, 0x69, 0x61, 0x73, 0x0d, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x5f, 0x76, 0x61, 0x72, 0x63, 0x68, 0x61, 0x72, 0x0c, 0x21, 0x00, 0xfd, 0x02, 0x00, 0x00, 0xfd, 0x00, 0x00, 0x00, 0x00, 0x00 }, "Varchar field, aliased field and table names (query with a JOIN)"), SerializeParams(column_definition_packet{ string_lenenc("def"), //catalog string_lenenc("awesome"), // schema (database) string_lenenc("test_table"), // table string_lenenc("test_table"), // physical table string_lenenc("field_float"), // field name string_lenenc("field_float"), // physical field name collation::binary, // binary int4(12), // length protocol_field_type::float_, int2(), // no column flags int1(31) // decimals }, { 0x03, 0x64, 0x65, 0x66, 0x07, 0x61, 0x77, 0x65, 0x73, 0x6f, 0x6d, 0x65, 0x0a, 0x74, 0x65, 0x73, 0x74, 0x5f, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x0a, 0x74, 0x65, 0x73, 0x74, 0x5f, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x0b, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x0b, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x0c, 0x3f, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x1f, 0x00, 0x00 }, "Float field") )); INSTANTIATE_TEST_SUITE_P(ComQuery, SerializeTest, testing::Values( SerializeParams(com_query_packet{ string_eof("show databases") }, { 0x03, 0x73, 0x68, 0x6f, 0x77, 0x20, 0x64, 0x61, 0x74, 0x61, 0x62, 0x61, 0x73, 0x65, 0x73 }) )); INSTANTIATE_TEST_SUITE_P(ComStmtPrepare, SerializeTest, testing::Values( SerializeParams(com_stmt_prepare_packet{ string_eof("SELECT * from three_rows_table WHERE id = ?") }, { 0x16, 0x53, 0x45, 0x4c, 0x45, 0x43, 0x54, 0x20, 0x2a, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x74, 0x68, 0x72, 0x65, 0x65, 0x5f, 0x72, 0x6f, 0x77, 0x73, 0x5f, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x20, 0x57, 0x48, 0x45, 0x52, 0x45, 0x20, 0x69, 0x64, 0x20, 0x3d, 0x20, 0x3f }) )); INSTANTIATE_TEST_SUITE_P(ComStmtPrepareResponse, DeserializeSpaceTest, testing::Values( SerializeParams(com_stmt_prepare_ok_packet{ int4(1), // statement id int2(2), // number of fields int2(3), // number of params int2(0), // warnings }, { 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00 }) )); // Helper for composing ComStmtExecute tests SerializeParams make_stmt_execute_test( std::uint32_t stmt_id, std::uint8_t flags, std::uint32_t itercount, std::uint8_t new_params_flag, std::vector&& params, std::vector&& buffer, std::string&& test_name ) { auto params_shared = std::make_shared>(std::move(params)); return SerializeParams( com_stmt_execute_packet { int4(stmt_id), int1(flags), int4(itercount), int1(new_params_flag), params_shared->data(), params_shared->data() + params_shared->size() }, std::move(buffer), std::move(test_name), 0, // capabilities params_shared ); } INSTANTIATE_TEST_SUITE_P(ComStmtExecute, SerializeTest, testing::Values( make_stmt_execute_test(1, 0x80, 1, 1, // stmt ID, flags, itercount, new params { std::uint32_t(0xabffff) }, { 0x17, 0x01, 0x00, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x03, 0x80, 0xff, 0xff, 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 { 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, makedate(2010, 9, 3), makedt(2010, 9, 3, 10, 30, 59, 231800), maket(230, 30, 59, 231800), nullptr ), { 0x17, 0x02, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x20, 0x04, 0x01, 0x03, 0x80, 0x03, 0x00, 0x08, 0x80, 0x08, 0x00, 0x0f, 0x00, 0x06, 0x00, 0x05, 0x00, 0x0a, 0x00, 0x0c, 0x00, 0x0b, 0x00, 0x06, 0x00, 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, 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 }, "several_params" ) )); INSTANTIATE_TEST_SUITE_P(ComStmtClose, SerializeTest, testing::Values( SerializeParams(com_stmt_close_packet{int4(1)}, {0x19, 0x01, 0x00, 0x00, 0x00}) )); } // anon namespace