polardbxengine/unittest/gunit/xplugin/xpl/row_builder_t.cc

727 lines
22 KiB
C++

/* Copyright (c) 2015, 2019, Oracle and/or its affiliates. All rights reserved.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License, version 2.0,
as published by the Free Software Foundation.
This program is also distributed with certain software (including
but not limited to OpenSSL) that is licensed under separate terms,
as designated in a particular file or component or in included license
documentation. The authors of MySQL hereby grant you an additional
permission to link the program and your derivative works with the
separately licensed software that they have included with MySQL.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License, version 2.0, for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
#include <gmock/gmock.h>
#include <gtest/gtest.h>
#include <stddef.h>
#include <stdio.h>
#include <limits>
#include <set>
#include <string>
#include "decimal.h"
#include "plugin/x/client/mysqlxclient/xdatetime.h"
#include "plugin/x/client/mysqlxclient/xdecimal.h"
#include "plugin/x/client/mysqlxclient/xrow.h"
#include "plugin/x/client/xrow_impl.h"
#include "plugin/x/ngs/include/ngs/protocol/page_pool.h"
#include "plugin/x/ngs/include/ngs/protocol/protocol_protobuf.h"
#include "plugin/x/protocol/encoders/encoding_xrow.h"
#include "unittest/gunit/xplugin/xpl/protobuf_message.h"
namespace protocol {
namespace test {
using ::xpl::test::message_with_header_from_buffer;
template <typename Expected_value_type, typename Method_type>
void assert_row_getter(const Expected_value_type &expected_value,
const Method_type &method, const std::string &buffer) {
Expected_value_type value;
const bool result = method(buffer, &value);
ASSERT_TRUE(result);
ASSERT_EQ(expected_value, value);
}
class Row_builder_testsuite : public testing::Test {
public:
std::string get_buffer_as_string() {
std::string result;
auto page = m_buffer.m_front;
while (page) {
result += std::string(reinterpret_cast<const char *>(page->m_begin_data),
page->get_used_bytes());
page = page->m_next_page;
}
return result;
}
ngs::Memory_block_pool m_memory_block_pool{{20, k_minimum_page_size}};
Encoding_pool m_pool{10, &m_memory_block_pool};
Encoding_buffer m_buffer{&m_pool};
XMessage_encoder m_encoder{&m_buffer};
XRow_encoder m_row{&m_encoder};
};
TEST_F(Row_builder_testsuite, row_start) {
m_row.begin_row();
m_row.field_null();
m_row.field_null();
ASSERT_EQ(2u, m_row.get_num_fields());
m_row.begin_row();
m_row.end_row();
ASSERT_EQ(0u, m_row.get_num_fields());
}
TEST_F(Row_builder_testsuite, row_msg_size) {
m_row.begin_row();
m_row.field_null();
m_row.end_row();
auto row_data = get_buffer_as_string();
// 1 byte for msg tag + 1 byte for field header + 1 byte
// for field value (NULL)
ASSERT_EQ(7, row_data.length());
ASSERT_EQ(3u, row_data[0]);
ASSERT_EQ(0u, row_data[1]);
ASSERT_EQ(0u, row_data[2]);
ASSERT_EQ(0u, row_data[3]);
m_row.begin_row();
m_row.field_null();
m_row.field_null();
m_row.end_row();
// offset of the size is 7 (3 bytes for prev msg + 4 for its size)
auto two_row_data = get_buffer_as_string();
// 1 byte for msg tag + 2*(1 byte for field header + 1 byte
// for field value (NULL))
ASSERT_EQ(16, two_row_data.length());
ASSERT_EQ(5u, two_row_data[7]);
ASSERT_EQ(0u, two_row_data[8]);
ASSERT_EQ(0u, two_row_data[9]);
ASSERT_EQ(0u, two_row_data[10]);
}
TEST_F(Row_builder_testsuite, row_abort) {
m_row.begin_row();
m_row.field_null();
m_row.field_null();
m_row.abort_row();
m_row.end_row();
auto row_data = get_buffer_as_string();
ASSERT_EQ(0u, row_data.length());
}
TEST_F(Row_builder_testsuite, fields_qty) {
m_row.begin_row();
ASSERT_EQ(0u, m_row.get_num_fields());
m_row.field_null();
m_row.field_null();
ASSERT_EQ(2u, m_row.get_num_fields());
m_row.field_unsigned_longlong(0);
m_row.field_float(0.0f);
m_row.field_float(0.0f);
ASSERT_EQ(5u, m_row.get_num_fields());
m_row.end_row();
}
TEST_F(Row_builder_testsuite, null_field) {
m_row.begin_row();
m_row.field_null();
m_row.end_row();
std::unique_ptr<Mysqlx::Resultset::Row> row(
message_with_header_from_buffer<Mysqlx::Resultset::Row>(
get_buffer_as_string()));
ASSERT_EQ(1, row->field_size());
ASSERT_EQ(0u, row->field(0).length());
}
TEST_F(Row_builder_testsuite, unsigned64_field) {
std::string *buffer;
int idx = 0;
m_row.begin_row();
m_row.field_unsigned_longlong(0);
m_row.field_unsigned_longlong(500);
m_row.field_unsigned_longlong(10000000);
m_row.field_unsigned_longlong(0x7fffffffffffffffLL);
m_row.field_unsigned_longlong(1);
m_row.field_unsigned_longlong(0xffffffffffffffffLL);
m_row.end_row();
std::unique_ptr<Mysqlx::Resultset::Row> row(
message_with_header_from_buffer<Mysqlx::Resultset::Row>(
get_buffer_as_string()));
buffer = row->mutable_field(idx++);
assert_row_getter<uint64_t>(static_cast<uint64_t>(0),
&xcl::row_decoder::buffer_to_u64, *buffer);
buffer = row->mutable_field(idx++);
assert_row_getter<uint64_t>(500, &xcl::row_decoder::buffer_to_u64, *buffer);
buffer = row->mutable_field(idx++);
assert_row_getter<uint64_t>(10000000, &xcl::row_decoder::buffer_to_u64,
*buffer);
buffer = row->mutable_field(idx++);
assert_row_getter<uint64_t>(0x7fffffffffffffffULL,
&xcl::row_decoder::buffer_to_u64, *buffer);
buffer = row->mutable_field(idx++);
assert_row_getter<uint64_t>(1, &xcl::row_decoder::buffer_to_u64, *buffer);
buffer = row->mutable_field(idx++);
assert_row_getter<uint64_t>(0xffffffffffffffffULL,
&xcl::row_decoder::buffer_to_u64, *buffer);
}
TEST_F(Row_builder_testsuite, signed64_field) {
std::string *buffer;
int idx = 0;
m_row.begin_row();
m_row.field_signed_longlong(0);
m_row.field_signed_longlong(-500);
m_row.field_signed_longlong(-10000000);
m_row.field_signed_longlong(0x7fffffffffffffffLL);
m_row.field_signed_longlong(-1);
m_row.end_row();
std::unique_ptr<Mysqlx::Resultset::Row> row(
message_with_header_from_buffer<Mysqlx::Resultset::Row>(
get_buffer_as_string()));
buffer = row->mutable_field(idx++);
assert_row_getter<int64_t>(0, &xcl::row_decoder::buffer_to_s64, *buffer);
buffer = row->mutable_field(idx++);
assert_row_getter<int64_t>(-500, &xcl::row_decoder::buffer_to_s64, *buffer);
buffer = row->mutable_field(idx++);
assert_row_getter<int64_t>(-10000000, &xcl::row_decoder::buffer_to_s64,
*buffer);
buffer = row->mutable_field(idx++);
assert_row_getter<int64_t>(0x7fffffffffffffffLL,
&xcl::row_decoder::buffer_to_s64, *buffer);
buffer = row->mutable_field(idx++);
assert_row_getter<int64_t>(-1, &xcl::row_decoder::buffer_to_s64, *buffer);
}
TEST_F(Row_builder_testsuite, float_field) {
std::string *buffer;
int idx = 0;
m_row.begin_row();
m_row.field_float(0.0f);
m_row.field_float(0.0001f);
m_row.field_float(-10000000.1f);
m_row.field_float(9999.91992f);
m_row.field_float(std::numeric_limits<float>::min());
m_row.field_float(std::numeric_limits<float>::max());
m_row.end_row();
std::unique_ptr<Mysqlx::Resultset::Row> row(
message_with_header_from_buffer<Mysqlx::Resultset::Row>(
get_buffer_as_string()));
buffer = row->mutable_field(idx++);
assert_row_getter<float>(0.0f, &xcl::row_decoder::buffer_to_float, *buffer);
buffer = row->mutable_field(idx++);
assert_row_getter<float>(0.0001f, &xcl::row_decoder::buffer_to_float,
*buffer);
buffer = row->mutable_field(idx++);
assert_row_getter<float>(-10000000.1f, &xcl::row_decoder::buffer_to_float,
*buffer);
buffer = row->mutable_field(idx++);
assert_row_getter<float>(9999.91992f, &xcl::row_decoder::buffer_to_float,
*buffer);
buffer = row->mutable_field(idx++);
assert_row_getter<float>(std::numeric_limits<float>::min(),
&xcl::row_decoder::buffer_to_float, *buffer);
buffer = row->mutable_field(idx++);
assert_row_getter<float>(std::numeric_limits<float>::max(),
&xcl::row_decoder::buffer_to_float, *buffer);
}
TEST_F(Row_builder_testsuite, double_field) {
std::string *buffer;
int idx = 0;
m_row.begin_row();
m_row.field_double(0.0);
m_row.field_double(0.0001);
m_row.field_double(-10000000.1);
m_row.field_double(9999.91992);
m_row.field_double(std::numeric_limits<double>::min());
m_row.field_double(std::numeric_limits<double>::max());
m_row.end_row();
std::unique_ptr<Mysqlx::Resultset::Row> row(
message_with_header_from_buffer<Mysqlx::Resultset::Row>(
get_buffer_as_string()));
buffer = row->mutable_field(idx++);
assert_row_getter<double>(0.0, &xcl::row_decoder::buffer_to_double, *buffer);
buffer = row->mutable_field(idx++);
assert_row_getter<double>(0.0001, &xcl::row_decoder::buffer_to_double,
*buffer);
buffer = row->mutable_field(idx++);
assert_row_getter<double>(-10000000.1, &xcl::row_decoder::buffer_to_double,
*buffer);
buffer = row->mutable_field(idx++);
assert_row_getter<double>(9999.91992, &xcl::row_decoder::buffer_to_double,
*buffer);
buffer = row->mutable_field(idx++);
assert_row_getter<double>(std::numeric_limits<double>::min(),
&xcl::row_decoder::buffer_to_double, *buffer);
buffer = row->mutable_field(idx++);
assert_row_getter<double>(std::numeric_limits<double>::max(),
&xcl::row_decoder::buffer_to_double, *buffer);
}
TEST_F(Row_builder_testsuite, string_field) {
std::string *buffer;
int idx = 0;
const char *pstr;
size_t len;
const char *const STR1 = "ABBABABBBAAA-09-0900--==0,\0\0\0\0\0";
m_row.begin_row();
m_row.field_string("", 0);
m_row.field_string(STR1, strlen(STR1));
m_row.end_row();
std::unique_ptr<Mysqlx::Resultset::Row> row(
message_with_header_from_buffer<Mysqlx::Resultset::Row>(
get_buffer_as_string()));
buffer = row->mutable_field(idx++);
ASSERT_TRUE(xcl::row_decoder::buffer_to_string(*buffer, &pstr, &len));
ASSERT_STREQ("", pstr);
ASSERT_EQ(len, 0u);
buffer = row->mutable_field(idx++);
ASSERT_TRUE(xcl::row_decoder::buffer_to_string(*buffer, &pstr, &len));
for (size_t i = 0; i < len; i++) {
ASSERT_EQ(STR1[i], pstr[i]);
}
ASSERT_EQ(len, strlen(STR1));
}
TEST_F(Row_builder_testsuite, date_field) {
std::string *buffer;
int idx = 0;
MYSQL_TIME time;
time.year = 2006;
time.month = 3;
time.day = 24;
m_row.begin_row();
m_row.field_date(&time);
m_row.end_row();
std::unique_ptr<Mysqlx::Resultset::Row> row(
message_with_header_from_buffer<Mysqlx::Resultset::Row>(
get_buffer_as_string()));
buffer = row->mutable_field(idx++);
xcl::DateTime xtime;
bool has_time = false;
ASSERT_TRUE(xcl::row_decoder::buffer_to_datetime(*buffer, &xtime, has_time));
ASSERT_EQ(time.year, xtime.year());
ASSERT_EQ(time.month, xtime.month());
ASSERT_EQ(time.day, xtime.day());
}
TEST_F(Row_builder_testsuite, time_field) {
std::string *buffer;
int idx = 0;
MYSQL_TIME time;
time.neg = false;
time.hour = 12;
time.minute = 0;
time.second = 0;
time.second_part = 999999;
MYSQL_TIME time2;
time2.neg = false;
time2.hour = 0;
time2.minute = 0;
time2.second = 0;
time2.second_part = 0;
MYSQL_TIME time3;
time3.neg = true;
time3.hour = 811;
time3.minute = 0;
time3.second = 0;
time3.second_part = 0;
m_row.begin_row();
m_row.field_time(&time);
m_row.field_time(&time2);
m_row.field_time(&time3);
m_row.end_row();
std::unique_ptr<Mysqlx::Resultset::Row> row{
message_with_header_from_buffer<Mysqlx::Resultset::Row>(
get_buffer_as_string())};
buffer = row->mutable_field(idx++);
xcl::Time xtime;
ASSERT_TRUE(xcl::row_decoder::buffer_to_time(*buffer, &xtime));
ASSERT_TRUE(false == xtime.is_negate());
ASSERT_EQ(time.hour, xtime.hour());
ASSERT_EQ(time.minute, xtime.minutes());
ASSERT_EQ(time.second, xtime.seconds());
ASSERT_EQ(time.second_part, xtime.useconds());
buffer = row->mutable_field(idx++);
ASSERT_TRUE(xcl::row_decoder::buffer_to_time(*buffer, &xtime));
ASSERT_TRUE(false == xtime.is_negate());
ASSERT_EQ(time2.hour, xtime.hour());
ASSERT_EQ(time2.minute, xtime.minutes());
ASSERT_EQ(time2.second, xtime.seconds());
ASSERT_EQ(time2.second_part, xtime.useconds());
buffer = row->mutable_field(idx++);
ASSERT_TRUE(xcl::row_decoder::buffer_to_time(*buffer, &xtime));
ASSERT_TRUE(true == xtime.is_negate());
ASSERT_EQ(time3.hour, xtime.hour());
ASSERT_EQ(time3.minute, xtime.minutes());
ASSERT_EQ(time3.second, xtime.seconds());
ASSERT_EQ(time3.second_part, xtime.useconds());
}
TEST_F(Row_builder_testsuite, datetime_field) {
std::string *buffer;
int idx = 0;
MYSQL_TIME time;
time.year = 2016;
time.month = 12;
time.day = 24;
time.hour = 13;
time.minute = 55;
time.second = 55;
time.second_part = 999999;
time.time_type = MYSQL_TIMESTAMP_DATETIME;
MYSQL_TIME time2;
time2.year = 2000;
time2.month = 1;
time2.day = 1;
time2.hour = 0;
time2.minute = 0;
time2.second = 0;
time2.second_part = 0;
time2.time_type = MYSQL_TIMESTAMP_DATETIME;
m_row.begin_row();
m_row.field_datetime(&time);
m_row.field_datetime(&time2);
m_row.end_row();
std::unique_ptr<Mysqlx::Resultset::Row> row{
message_with_header_from_buffer<Mysqlx::Resultset::Row>(
get_buffer_as_string())};
buffer = row->mutable_field(idx++);
xcl::DateTime xtime;
bool has_time = true;
ASSERT_TRUE(xcl::row_decoder::buffer_to_datetime(*buffer, &xtime, has_time));
ASSERT_EQ(time.year, xtime.year());
ASSERT_EQ(time.month, xtime.month());
ASSERT_EQ(time.day, xtime.day());
ASSERT_EQ(time.hour, xtime.hour());
ASSERT_EQ(time.minute, xtime.minutes());
ASSERT_EQ(time.second, xtime.seconds());
ASSERT_EQ(time.second_part, xtime.useconds());
buffer = row->mutable_field(idx++);
ASSERT_TRUE(xcl::row_decoder::buffer_to_datetime(*buffer, &xtime, has_time));
ASSERT_EQ(time2.year, xtime.year());
ASSERT_EQ(time2.month, xtime.month());
ASSERT_EQ(time2.day, xtime.day());
ASSERT_EQ(time2.hour, xtime.hour());
ASSERT_EQ(time2.minute, xtime.minutes());
ASSERT_EQ(time2.second, xtime.seconds());
ASSERT_EQ(time2.second_part, xtime.useconds());
}
TEST_F(Row_builder_testsuite, decimal_field) {
std::string *buffer;
int idx = 0;
xcl::Decimal xdecimal;
m_row.begin_row();
decimal_digit_t arr1[] = {1, 0};
decimal_t dec1 = {1, 1, 2, 1, arr1};
m_row.field_decimal(&dec1);
decimal_digit_t arr2[] = {1, 0};
decimal_t dec2 = {1, 1, 2, 0, arr2};
m_row.field_decimal(&dec2);
m_row.end_row();
std::unique_ptr<Mysqlx::Resultset::Row> row{
message_with_header_from_buffer<Mysqlx::Resultset::Row>(
get_buffer_as_string())};
buffer = row->mutable_field(idx++);
ASSERT_TRUE(xcl::row_decoder::buffer_to_decimal(*buffer, &xdecimal));
ASSERT_EQ("-1.0", xdecimal.to_string());
buffer = row->mutable_field(idx++);
ASSERT_TRUE(xcl::row_decoder::buffer_to_decimal(*buffer, &xdecimal));
ASSERT_EQ("1.0", xdecimal.to_string());
}
TEST_F(Row_builder_testsuite, set_field) {
std::string *buffer;
int idx = 0;
m_row.begin_row();
const char *const str_abcd = "A,B,C,D";
const char *const str_a = "A";
m_row.field_set(str_abcd, strlen(str_abcd));
m_row.field_set("", 0); // empty SET case
m_row.field_set(str_a, strlen(str_a));
m_row.end_row();
std::unique_ptr<Mysqlx::Resultset::Row> row(
message_with_header_from_buffer<Mysqlx::Resultset::Row>(
get_buffer_as_string()));
buffer = row->mutable_field(idx++);
std::set<std::string> elems;
std::string elems_string;
ASSERT_TRUE(xcl::row_decoder::buffer_to_string_set(*buffer, &elems_string));
ASSERT_STREQ("A,B,C,D", elems_string.c_str());
ASSERT_TRUE(xcl::row_decoder::buffer_to_set(*buffer, &elems));
ASSERT_EQ(1u, elems.count("A"));
ASSERT_EQ(1u, elems.count("B"));
ASSERT_EQ(1u, elems.count("C"));
ASSERT_EQ(1u, elems.count("D"));
ASSERT_EQ(4u, elems.size());
buffer = row->mutable_field(idx++);
xcl::row_decoder::buffer_to_set(*buffer, &elems);
ASSERT_EQ(true, elems.empty());
ASSERT_TRUE(xcl::row_decoder::buffer_to_string_set(*buffer, &elems_string));
ASSERT_STREQ("", elems_string.c_str());
buffer = row->mutable_field(idx++);
xcl::row_decoder::buffer_to_set(*buffer, &elems);
ASSERT_EQ(1u, elems.size());
ASSERT_EQ(1u, elems.count("A"));
ASSERT_TRUE(xcl::row_decoder::buffer_to_string_set(*buffer, &elems_string));
ASSERT_STREQ("A", elems_string.c_str());
}
TEST_F(Row_builder_testsuite, bit_field) {
std::string *buffer;
int idx = 0;
m_row.begin_row();
m_row.field_bit("\x00", 1);
m_row.field_bit("\x01", 1);
m_row.field_bit("\xff\x00", 2);
m_row.field_bit("\x00\x00\x00\x00\x00\x00\x00\x00", 8);
m_row.field_bit("\xff\xff\xff\xff\xff\xff\xff\xff", 8);
m_row.end_row();
std::unique_ptr<Mysqlx::Resultset::Row> row{
message_with_header_from_buffer<Mysqlx::Resultset::Row>(
get_buffer_as_string())};
buffer = row->mutable_field(idx++);
assert_row_getter<uint64_t>(0x0u, &xcl::row_decoder::buffer_to_u64, *buffer);
buffer = row->mutable_field(idx++);
assert_row_getter<uint64_t>(0x1u, &xcl::row_decoder::buffer_to_u64, *buffer);
buffer = row->mutable_field(idx++);
assert_row_getter<uint64_t>(0xff00u, &xcl::row_decoder::buffer_to_u64,
*buffer);
buffer = row->mutable_field(idx++);
assert_row_getter<uint64_t>(0x0000000000000000ULL,
&xcl::row_decoder::buffer_to_u64, *buffer);
buffer = row->mutable_field(idx++);
assert_row_getter<uint64_t>(0xffffffffffffffffULL,
&xcl::row_decoder::buffer_to_u64, *buffer);
}
TEST_F(Row_builder_testsuite, datetime_content_type_set) {
xcl::XRow_impl::Metadata metadata;
xcl::XRow_impl::Metadata::value_type metadata_row;
metadata_row.type = xcl::Column_type::DATETIME;
metadata_row.length = 19;
metadata_row.has_content_type = true;
metadata_row.content_type =
static_cast<uint32_t>(Mysqlx::Resultset::DATETIME);
metadata.push_back(metadata_row);
xcl::Context context;
::testing::StrictMock<xcl::XRow_impl> row_mock(&metadata, &context);
MYSQL_TIME time;
time.year = 2016;
time.month = 12;
time.day = 24;
time.hour = 13;
time.minute = 55;
time.second = 55;
time.second_part = 999999;
time.time_type = MYSQL_TIMESTAMP_DATETIME;
m_row.begin_row();
m_row.field_datetime(&time);
m_row.end_row();
std::unique_ptr<Mysqlx::Resultset::Row> row{
message_with_header_from_buffer<Mysqlx::Resultset::Row>(
get_buffer_as_string())};
row_mock.set_row(std::move(row));
xcl::DateTime result;
row_mock.get_datetime(0, &result);
EXPECT_TRUE(result.has_time());
EXPECT_EQ(result.year(), time.year);
EXPECT_EQ(result.month(), time.month);
EXPECT_EQ(result.day(), time.day);
EXPECT_EQ(result.hour(), time.hour);
EXPECT_EQ(result.minutes(), time.minute);
EXPECT_EQ(result.seconds(), time.second);
EXPECT_EQ(result.useconds(), time.second_part);
}
TEST_F(Row_builder_testsuite, datetime_content_type_not_set_and_has_time_part) {
xcl::XRow_impl::Metadata metadata;
xcl::XRow_impl::Metadata::value_type metadata_row;
metadata_row.type = xcl::Column_type::DATETIME;
metadata_row.length = 19;
metadata_row.has_content_type = false;
metadata.push_back(metadata_row);
xcl::Context context;
::testing::StrictMock<xcl::XRow_impl> row_mock(&metadata, &context);
MYSQL_TIME time;
time.year = 2016;
time.month = 12;
time.day = 24;
time.hour = 13;
time.minute = 55;
time.second = 55;
time.second_part = 0;
time.time_type = MYSQL_TIMESTAMP_DATETIME;
m_row.begin_row();
m_row.field_datetime(&time);
m_row.end_row();
std::unique_ptr<Mysqlx::Resultset::Row> row{
message_with_header_from_buffer<Mysqlx::Resultset::Row>(
get_buffer_as_string())};
row_mock.set_row(std::move(row));
xcl::DateTime result;
row_mock.get_datetime(0, &result);
EXPECT_EQ(row_mock.get_number_of_fields(), 1);
EXPECT_TRUE(result.has_time());
EXPECT_EQ(result.year(), time.year);
EXPECT_EQ(result.month(), time.month);
EXPECT_EQ(result.day(), time.day);
EXPECT_EQ(result.hour(), time.hour);
EXPECT_EQ(result.minutes(), time.minute);
EXPECT_EQ(result.seconds(), time.second);
EXPECT_EQ(result.useconds(), time.second_part);
}
TEST_F(Row_builder_testsuite,
datetime_content_type_not_set_and_not_contains_time_part) {
xcl::XRow_impl::Metadata metadata;
xcl::XRow_impl::Metadata::value_type metadata_row;
metadata_row.type = xcl::Column_type::DATETIME;
metadata_row.length = 10;
metadata_row.has_content_type = false;
metadata.push_back(metadata_row);
xcl::Context context;
::testing::StrictMock<xcl::XRow_impl> row_mock(&metadata, &context);
MYSQL_TIME time;
time.year = 2016;
time.month = 12;
time.day = 24;
time.hour = 0;
time.minute = 0;
time.second = 0;
time.second_part = 0;
time.time_type = MYSQL_TIMESTAMP_DATE;
m_row.begin_row();
m_row.field_datetime(&time);
m_row.end_row();
std::unique_ptr<Mysqlx::Resultset::Row> row{
message_with_header_from_buffer<Mysqlx::Resultset::Row>(
get_buffer_as_string())};
row_mock.set_row(std::move(row));
xcl::DateTime result;
row_mock.get_datetime(0, &result);
EXPECT_EQ(result.year(), time.year);
EXPECT_EQ(result.month(), time.month);
EXPECT_EQ(result.day(), time.day);
EXPECT_FALSE(result.has_time());
EXPECT_EQ(result.hour(), 0xFF);
EXPECT_EQ(result.minutes(), 0xFF);
EXPECT_EQ(result.seconds(), 0xFF);
EXPECT_EQ(result.useconds(), 0xFFFFFF);
}
} // namespace test
} // namespace protocol