mirror of
https://github.com/boostorg/mysql.git
synced 2026-02-14 12:52:17 +00:00
deserialize_text_field tests
This commit is contained in:
@@ -5,8 +5,8 @@
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
|
||||
#ifndef BOOST_MYSQL_DETAIL_PROTOCOL_BINARY_DESERIALIZATION_HPP
|
||||
#define BOOST_MYSQL_DETAIL_PROTOCOL_BINARY_DESERIALIZATION_HPP
|
||||
#ifndef BOOST_MYSQL_DETAIL_PROTOCOL_DESERIALIZE_BINARY_FIELD_HPP
|
||||
#define BOOST_MYSQL_DETAIL_PROTOCOL_DESERIALIZE_BINARY_FIELD_HPP
|
||||
|
||||
#include <boost/mysql/detail/protocol/serialization.hpp>
|
||||
#include <boost/mysql/error.hpp>
|
||||
@@ -26,17 +26,10 @@ inline errc deserialize_binary_field(
|
||||
field_view& output
|
||||
);
|
||||
|
||||
inline error_code deserialize_binary_row(
|
||||
deserialization_context& ctx,
|
||||
const std::vector<metadata>& meta,
|
||||
const std::uint8_t* buffer_first,
|
||||
std::vector<field_view>& output
|
||||
);
|
||||
|
||||
} // detail
|
||||
} // mysql
|
||||
} // boost
|
||||
|
||||
#include <boost/mysql/detail/protocol/impl/binary_deserialization.ipp>
|
||||
#include <boost/mysql/detail/protocol/impl/deserialize_binary_field.ipp>
|
||||
|
||||
#endif /* INCLUDE_BOOST_MYSQL_DETAIL_PROTOCOL_BINARY_DESERIALIZATION_HPP_ */
|
||||
@@ -8,11 +8,10 @@
|
||||
#ifndef BOOST_MYSQL_DETAIL_PROTOCOL_DESERIALIZE_ROW_HPP
|
||||
#define BOOST_MYSQL_DETAIL_PROTOCOL_DESERIALIZE_ROW_HPP
|
||||
|
||||
#include <boost/mysql/detail/protocol/resultset_encoding.hpp>
|
||||
#include <boost/asio/buffer.hpp>
|
||||
#include <boost/mysql/detail/protocol/capabilities.hpp>
|
||||
#include <boost/mysql/detail/protocol/serialization.hpp>
|
||||
#include <boost/mysql/detail/protocol/text_deserialization.hpp>
|
||||
#include <boost/mysql/detail/protocol/binary_deserialization.hpp>
|
||||
#include <boost/mysql/detail/protocol/serialization_context.hpp>
|
||||
#include <boost/mysql/resultset_base.hpp>
|
||||
#include <boost/mysql/error.hpp>
|
||||
#include <boost/mysql/field_view.hpp>
|
||||
@@ -23,6 +22,16 @@ namespace boost {
|
||||
namespace mysql {
|
||||
namespace detail {
|
||||
|
||||
// Exposed here for the sake of testing
|
||||
inline void deserialize_row(
|
||||
resultset_encoding encoding,
|
||||
deserialization_context& ctx,
|
||||
const std::vector<metadata>& meta,
|
||||
const std::uint8_t* buffer_first,
|
||||
std::vector<field_view>& output,
|
||||
error_code& err
|
||||
);
|
||||
|
||||
|
||||
inline bool deserialize_row(
|
||||
boost::asio::const_buffer read_message,
|
||||
@@ -32,45 +41,7 @@ inline bool deserialize_row(
|
||||
std::vector<field_view>& output,
|
||||
error_code& err,
|
||||
error_info& info
|
||||
)
|
||||
{
|
||||
assert(result.valid());
|
||||
|
||||
// Message type: row, error or eof?
|
||||
std::uint8_t msg_type = 0;
|
||||
deserialization_context ctx (read_message, current_capabilities);
|
||||
err = make_error_code(deserialize(ctx, msg_type));
|
||||
if (err)
|
||||
return false;
|
||||
if (msg_type == eof_packet_header)
|
||||
{
|
||||
// end of resultset => this is a ok_packet, not a row
|
||||
ok_packet ok_pack;
|
||||
err = deserialize_message(ctx, ok_pack);
|
||||
if (err)
|
||||
return false;
|
||||
result.complete(ok_pack);
|
||||
output.clear();
|
||||
return false;
|
||||
}
|
||||
else if (msg_type == error_packet_header)
|
||||
{
|
||||
// An error occurred during the generation of the rows
|
||||
err = process_error_packet(ctx, info);
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
// An actual row
|
||||
ctx.rewind(1); // keep the 'message type' byte, as it is part of the actual message
|
||||
err = result.encoding() == detail::resultset_encoding::text ?
|
||||
deserialize_text_row(ctx, result.meta(), buffer_first, output) :
|
||||
deserialize_binary_row(ctx, result.meta(), buffer_first, output);
|
||||
if (err)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
inline void offsets_to_string_views(
|
||||
std::vector<field_view>& fields,
|
||||
@@ -86,5 +57,7 @@ inline void offsets_to_string_views(
|
||||
} // mysql
|
||||
} // boost
|
||||
|
||||
#include <boost/mysql/detail/protocol/impl/deserialize_row.ipp>
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
@@ -5,8 +5,8 @@
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
|
||||
#ifndef BOOST_MYSQL_DETAIL_PROTOCOL_TEXT_DESERIALIZATION_HPP
|
||||
#define BOOST_MYSQL_DETAIL_PROTOCOL_TEXT_DESERIALIZATION_HPP
|
||||
#ifndef BOOST_MYSQL_DETAIL_PROTOCOL_DESERIALIZE_TEXT_FIELD_HPP
|
||||
#define BOOST_MYSQL_DETAIL_PROTOCOL_DESERIALIZE_TEXT_FIELD_HPP
|
||||
|
||||
#include <boost/mysql/detail/protocol/serialization.hpp>
|
||||
#include <boost/mysql/error.hpp>
|
||||
@@ -19,24 +19,17 @@ namespace boost {
|
||||
namespace mysql {
|
||||
namespace detail {
|
||||
|
||||
inline errc deserialize_text_value(
|
||||
inline errc deserialize_text_field(
|
||||
boost::string_view from,
|
||||
const metadata& meta,
|
||||
const std::uint8_t* buffer_first,
|
||||
field_view& output
|
||||
);
|
||||
|
||||
inline error_code deserialize_text_row(
|
||||
deserialization_context& ctx,
|
||||
const std::vector<metadata>& meta,
|
||||
const std::uint8_t* buffer_first,
|
||||
std::vector<field_view>& output
|
||||
);
|
||||
|
||||
} // detail
|
||||
} // mysql
|
||||
} // boost
|
||||
|
||||
#include <boost/mysql/detail/protocol/impl/text_deserialization.ipp>
|
||||
#include <boost/mysql/detail/protocol/impl/deserialize_text_field.ipp>
|
||||
|
||||
#endif
|
||||
@@ -5,15 +5,14 @@
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
|
||||
#ifndef BOOST_MYSQL_DETAIL_PROTOCOL_IMPL_BINARY_DESERIALIZATION_IPP
|
||||
#define BOOST_MYSQL_DETAIL_PROTOCOL_IMPL_BINARY_DESERIALIZATION_IPP
|
||||
#ifndef BOOST_MYSQL_DETAIL_PROTOCOL_IMPL_DESERIALIZE_BINARY_FIELD_IPP
|
||||
#define BOOST_MYSQL_DETAIL_PROTOCOL_IMPL_DESERIALIZE_BINARY_FIELD_IPP
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <boost/mysql/detail/auxiliar/string_view_offset.hpp>
|
||||
#include <boost/mysql/detail/protocol/binary_deserialization.hpp>
|
||||
#include <boost/mysql/detail/protocol/deserialize_binary_field.hpp>
|
||||
#include <boost/mysql/detail/protocol/serialization.hpp>
|
||||
#include <boost/mysql/detail/protocol/null_bitmap_traits.hpp>
|
||||
#include <boost/mysql/detail/protocol/constants.hpp>
|
||||
#include <boost/mysql/detail/protocol/date.hpp>
|
||||
#include <boost/mysql/detail/protocol/bit_deserialization.hpp>
|
||||
@@ -369,53 +368,4 @@ inline boost::mysql::errc boost::mysql::detail::deserialize_binary_field(
|
||||
}
|
||||
}
|
||||
|
||||
inline boost::mysql::error_code boost::mysql::detail::deserialize_binary_row(
|
||||
deserialization_context& ctx,
|
||||
const std::vector<metadata>& meta,
|
||||
const std::uint8_t* buffer_first,
|
||||
std::vector<field_view>& output
|
||||
)
|
||||
{
|
||||
std::size_t old_size = output.size();
|
||||
|
||||
// Skip packet header (it is not part of the message in the binary
|
||||
// protocol but it is in the text protocol, so we include it for homogeneity)
|
||||
// The caller will have checked we have this byte already for us
|
||||
assert(ctx.enough_size(1));
|
||||
ctx.advance(1);
|
||||
|
||||
// Number of fields
|
||||
auto num_fields = meta.size();
|
||||
output.resize(old_size + num_fields);
|
||||
|
||||
// Null bitmap
|
||||
null_bitmap_traits null_bitmap (binary_row_null_bitmap_offset, num_fields);
|
||||
const std::uint8_t* null_bitmap_begin = ctx.first();
|
||||
if (!ctx.enough_size(null_bitmap.byte_count()))
|
||||
return make_error_code(errc::incomplete_message);
|
||||
ctx.advance(null_bitmap.byte_count());
|
||||
|
||||
// Actual values
|
||||
for (std::vector<field_view>::size_type i = 0; i < output.size(); ++i)
|
||||
{
|
||||
if (null_bitmap.is_null(null_bitmap_begin, i))
|
||||
{
|
||||
output[old_size + i] = field_view(nullptr);
|
||||
}
|
||||
else
|
||||
{
|
||||
auto err = deserialize_binary_field(ctx, meta[i], buffer_first, output[old_size + i]);
|
||||
if (err != errc::ok)
|
||||
return make_error_code(err);
|
||||
}
|
||||
}
|
||||
|
||||
// Check for remaining bytes
|
||||
if (!ctx.empty())
|
||||
return make_error_code(errc::extra_bytes);
|
||||
|
||||
return error_code();
|
||||
}
|
||||
|
||||
|
||||
#endif /* INCLUDE_BOOST_MYSQL_DETAIL_PROTOCOL_IMPL_BINARY_DESERIALIZATION_IPP_ */
|
||||
177
include/boost/mysql/detail/protocol/impl/deserialize_row.ipp
Normal file
177
include/boost/mysql/detail/protocol/impl/deserialize_row.ipp
Normal file
@@ -0,0 +1,177 @@
|
||||
//
|
||||
// Copyright (c) 2019-2022 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)
|
||||
//
|
||||
|
||||
#ifndef BOOST_MYSQL_DETAIL_PROTOCOL_IMPL_DESERIALIZE_ROW_IPP
|
||||
#define BOOST_MYSQL_DETAIL_PROTOCOL_IMPL_DESERIALIZE_ROW_IPP
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <boost/mysql/detail/protocol/deserialize_row.hpp>
|
||||
#include <boost/mysql/detail/protocol/deserialize_text_field.hpp>
|
||||
#include <boost/mysql/detail/protocol/null_bitmap_traits.hpp>
|
||||
#include <boost/mysql/detail/protocol/deserialize_binary_field.hpp>
|
||||
#include <boost/mysql/detail/protocol/serialization.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace mysql {
|
||||
namespace detail {
|
||||
|
||||
inline bool is_next_field_null(
|
||||
const deserialization_context& ctx
|
||||
)
|
||||
{
|
||||
if (!ctx.enough_size(1))
|
||||
return false;
|
||||
return *ctx.first() == 0xfb;
|
||||
}
|
||||
|
||||
inline error_code deserialize_text_row(
|
||||
deserialization_context& ctx,
|
||||
const std::vector<metadata>& fields,
|
||||
const std::uint8_t* buffer_first,
|
||||
std::vector<field_view>& output
|
||||
)
|
||||
{
|
||||
std::size_t old_size = output.size();
|
||||
output.resize(old_size + fields.size());
|
||||
for (std::vector<field_view>::size_type i = 0; i < fields.size(); ++i)
|
||||
{
|
||||
if (is_next_field_null(ctx))
|
||||
{
|
||||
ctx.advance(1);
|
||||
output[old_size + i] = field_view(nullptr);
|
||||
}
|
||||
else
|
||||
{
|
||||
string_lenenc value_str;
|
||||
errc err = deserialize(ctx, value_str);
|
||||
if (err != errc::ok)
|
||||
return make_error_code(err);
|
||||
err = deserialize_text_field(value_str.value, fields[i], buffer_first, output[old_size + i]);
|
||||
if (err != errc::ok)
|
||||
return make_error_code(err);
|
||||
}
|
||||
}
|
||||
if (!ctx.empty())
|
||||
return make_error_code(errc::extra_bytes);
|
||||
return error_code();
|
||||
}
|
||||
|
||||
|
||||
inline error_code deserialize_binary_row(
|
||||
deserialization_context& ctx,
|
||||
const std::vector<metadata>& meta,
|
||||
const std::uint8_t* buffer_first,
|
||||
std::vector<field_view>& output
|
||||
)
|
||||
{
|
||||
std::size_t old_size = output.size();
|
||||
|
||||
// Skip packet header (it is not part of the message in the binary
|
||||
// protocol but it is in the text protocol, so we include it for homogeneity)
|
||||
// The caller will have checked we have this byte already for us
|
||||
assert(ctx.enough_size(1));
|
||||
ctx.advance(1);
|
||||
|
||||
// Number of fields
|
||||
auto num_fields = meta.size();
|
||||
output.resize(old_size + num_fields);
|
||||
|
||||
// Null bitmap
|
||||
null_bitmap_traits null_bitmap (binary_row_null_bitmap_offset, num_fields);
|
||||
const std::uint8_t* null_bitmap_begin = ctx.first();
|
||||
if (!ctx.enough_size(null_bitmap.byte_count()))
|
||||
return make_error_code(errc::incomplete_message);
|
||||
ctx.advance(null_bitmap.byte_count());
|
||||
|
||||
// Actual values
|
||||
for (std::vector<field_view>::size_type i = 0; i < output.size(); ++i)
|
||||
{
|
||||
if (null_bitmap.is_null(null_bitmap_begin, i))
|
||||
{
|
||||
output[old_size + i] = field_view(nullptr);
|
||||
}
|
||||
else
|
||||
{
|
||||
auto err = deserialize_binary_field(ctx, meta[i], buffer_first, output[old_size + i]);
|
||||
if (err != errc::ok)
|
||||
return make_error_code(err);
|
||||
}
|
||||
}
|
||||
|
||||
// Check for remaining bytes
|
||||
if (!ctx.empty())
|
||||
return make_error_code(errc::extra_bytes);
|
||||
|
||||
return error_code();
|
||||
}
|
||||
|
||||
} // detail
|
||||
} // mysql
|
||||
} // boost
|
||||
|
||||
void boost::mysql::detail::deserialize_row(
|
||||
resultset_encoding encoding,
|
||||
deserialization_context& ctx,
|
||||
const std::vector<metadata>& meta,
|
||||
const std::uint8_t* buffer_first,
|
||||
std::vector<field_view>& output,
|
||||
error_code& err
|
||||
)
|
||||
{
|
||||
err = encoding == detail::resultset_encoding::text ?
|
||||
deserialize_text_row(ctx, meta, buffer_first, output) :
|
||||
deserialize_binary_row(ctx, meta, buffer_first, output);
|
||||
}
|
||||
|
||||
bool boost::mysql::detail::deserialize_row(
|
||||
boost::asio::const_buffer read_message,
|
||||
capabilities current_capabilities,
|
||||
const std::uint8_t* buffer_first, // to store strings as offsets and allow buffer reallocation
|
||||
resultset_base& result,
|
||||
std::vector<field_view>& output,
|
||||
error_code& err,
|
||||
error_info& info
|
||||
)
|
||||
{
|
||||
assert(result.valid());
|
||||
|
||||
// Message type: row, error or eof?
|
||||
std::uint8_t msg_type = 0;
|
||||
deserialization_context ctx (read_message, current_capabilities);
|
||||
err = make_error_code(deserialize(ctx, msg_type));
|
||||
if (err)
|
||||
return false;
|
||||
if (msg_type == eof_packet_header)
|
||||
{
|
||||
// end of resultset => this is a ok_packet, not a row
|
||||
ok_packet ok_pack;
|
||||
err = deserialize_message(ctx, ok_pack);
|
||||
if (err)
|
||||
return false;
|
||||
result.complete(ok_pack);
|
||||
output.clear(); // TODO: this is wrong
|
||||
return false;
|
||||
}
|
||||
else if (msg_type == error_packet_header)
|
||||
{
|
||||
// An error occurred during the generation of the rows
|
||||
err = process_error_packet(ctx, info);
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
// An actual row
|
||||
ctx.rewind(1); // keep the 'message type' byte, as it is part of the actual message
|
||||
deserialize_row(result.encoding(), ctx, result.meta(), buffer_first, output, err);
|
||||
if (err)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -5,12 +5,12 @@
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
|
||||
#ifndef BOOST_MYSQL_DETAIL_PROTOCOL_IMPL_TEXT_DESERIALIZATION_IPP
|
||||
#define BOOST_MYSQL_DETAIL_PROTOCOL_IMPL_TEXT_DESERIALIZATION_IPP
|
||||
#ifndef BOOST_MYSQL_DETAIL_PROTOCOL_IMPL_DESERIALIZE_TEXT_FIELD_IPP
|
||||
#define BOOST_MYSQL_DETAIL_PROTOCOL_IMPL_DESERIALIZE_TEXT_FIELD_IPP
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <boost/mysql/detail/protocol/text_deserialization.hpp>
|
||||
#include <boost/mysql/detail/protocol/deserialize_text_field.hpp>
|
||||
#include <boost/mysql/detail/protocol/constants.hpp>
|
||||
#include <boost/mysql/detail/protocol/date.hpp>
|
||||
#include <boost/mysql/detail/protocol/bit_deserialization.hpp>
|
||||
@@ -296,20 +296,11 @@ inline errc deserialize_text_value_time(
|
||||
return errc::ok;
|
||||
}
|
||||
|
||||
inline bool is_next_field_null(
|
||||
const deserialization_context& ctx
|
||||
)
|
||||
{
|
||||
if (!ctx.enough_size(1))
|
||||
return false;
|
||||
return *ctx.first() == 0xfb;
|
||||
}
|
||||
|
||||
} // detail
|
||||
} // mysql
|
||||
} // boost
|
||||
|
||||
inline boost::mysql::errc boost::mysql::detail::deserialize_text_value(
|
||||
inline boost::mysql::errc boost::mysql::detail::deserialize_text_field(
|
||||
boost::string_view from,
|
||||
const metadata& meta,
|
||||
const std::uint8_t* buffer_first,
|
||||
@@ -358,38 +349,6 @@ inline boost::mysql::errc boost::mysql::detail::deserialize_text_value(
|
||||
}
|
||||
|
||||
|
||||
boost::mysql::error_code boost::mysql::detail::deserialize_text_row(
|
||||
deserialization_context& ctx,
|
||||
const std::vector<metadata>& fields,
|
||||
const std::uint8_t* buffer_first,
|
||||
std::vector<field_view>& output
|
||||
)
|
||||
{
|
||||
std::size_t old_size = output.size();
|
||||
output.resize(old_size + fields.size());
|
||||
for (std::vector<field_view>::size_type i = 0; i < fields.size(); ++i)
|
||||
{
|
||||
if (is_next_field_null(ctx))
|
||||
{
|
||||
ctx.advance(1);
|
||||
output[old_size + i] = field_view(nullptr);
|
||||
}
|
||||
else
|
||||
{
|
||||
string_lenenc value_str;
|
||||
errc err = deserialize(ctx, value_str);
|
||||
if (err != errc::ok)
|
||||
return make_error_code(err);
|
||||
err = deserialize_text_value(value_str.value, fields[i], buffer_first, output[old_size + i]);
|
||||
if (err != errc::ok)
|
||||
return make_error_code(err);
|
||||
}
|
||||
}
|
||||
if (!ctx.empty())
|
||||
return make_error_code(errc::extra_bytes);
|
||||
return error_code();
|
||||
}
|
||||
|
||||
#ifdef BOOST_MSVC
|
||||
#pragma warning( pop )
|
||||
#endif
|
||||
@@ -8,6 +8,7 @@
|
||||
#ifndef BOOST_MYSQL_FIELD_VIEW_HPP
|
||||
#define BOOST_MYSQL_FIELD_VIEW_HPP
|
||||
|
||||
#include <boost/config/detail/suffix.hpp>
|
||||
#include <boost/mysql/detail/auxiliar/string_view_offset.hpp>
|
||||
#include <boost/mysql/detail/auxiliar/field_impl.hpp>
|
||||
#include <boost/mysql/datetime_types.hpp>
|
||||
@@ -182,6 +183,10 @@ private:
|
||||
BOOST_CXX14_CONSTEXPR date get_date() const noexcept { return date(date::duration(date_));}
|
||||
BOOST_CXX14_CONSTEXPR datetime get_datetime() const noexcept { return datetime(datetime::duration(datetime_)); }
|
||||
BOOST_CXX14_CONSTEXPR time get_time() const noexcept { return time(time_); }
|
||||
BOOST_CXX14_CONSTEXPR detail::string_view_offset get_sv_offset() const noexcept
|
||||
{
|
||||
return detail::string_view_offset(sv_offset.offset, sv_offset.size);
|
||||
}
|
||||
};
|
||||
|
||||
internal_kind ikind_ { internal_kind::null };
|
||||
|
||||
@@ -214,7 +214,7 @@ BOOST_CXX14_CONSTEXPR inline boost::mysql::field_kind boost::mysql::field_view::
|
||||
case internal_kind::time: return field_kind::time;
|
||||
case internal_kind::field_ptr: return repr_.field_ptr->kind();
|
||||
// sv_offset values must be converted via offset_to_string_view before calling any other fn
|
||||
default: assert(false); return field_kind::null;
|
||||
default: return field_kind::null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -350,6 +350,13 @@ BOOST_CXX14_CONSTEXPR bool boost::mysql::field_view::operator==(
|
||||
const field_view& rhs
|
||||
) const noexcept
|
||||
{
|
||||
// Make operator== work for types not representable by field_kind
|
||||
if (ikind_ == internal_kind::sv_offset)
|
||||
{
|
||||
return rhs.ikind_ == internal_kind::sv_offset &&
|
||||
repr_.get_sv_offset() == rhs.repr_.get_sv_offset();
|
||||
}
|
||||
|
||||
auto k = kind(), rhs_k = rhs.kind();
|
||||
switch (k)
|
||||
{
|
||||
@@ -401,6 +408,10 @@ inline std::ostream& boost::mysql::operator<<(
|
||||
const field_view& value
|
||||
)
|
||||
{
|
||||
// Make operator<< work for detail::string_view_offset types
|
||||
if (value.ikind_ == field_view::internal_kind::sv_offset)
|
||||
return os << "<sv_offset>";
|
||||
|
||||
switch (value.kind())
|
||||
{
|
||||
case field_kind::null: return os << "<NULL>";
|
||||
|
||||
@@ -37,11 +37,11 @@ add_executable(
|
||||
unit/detail/auxiliar/static_string.cpp
|
||||
unit/detail/auxiliar/rows_iterator.cpp
|
||||
unit/detail/auxiliar/field_type_traits.cpp
|
||||
# unit/detail/protocol/capabilities.cpp
|
||||
unit/detail/protocol/capabilities.cpp
|
||||
# unit/detail/protocol/date.cpp
|
||||
# unit/detail/protocol/null_bitmap_traits.cpp
|
||||
# unit/detail/protocol/serialization_test.cpp
|
||||
# unit/detail/protocol/text_deserialization_value.cpp
|
||||
unit/detail/protocol/null_bitmap_traits.cpp
|
||||
unit/detail/protocol/serialization_test.cpp
|
||||
unit/detail/protocol/deserialize_text_field.cpp
|
||||
# unit/detail/protocol/text_deserialization_error.cpp
|
||||
# unit/detail/protocol/binary_deserialization_value.cpp
|
||||
# unit/detail/protocol/binary_deserialization_error.cpp
|
||||
|
||||
@@ -7,10 +7,14 @@
|
||||
|
||||
// Test deserialize_text_value(), just positive cases
|
||||
|
||||
#include <boost/mysql/detail/protocol/text_deserialization.hpp>
|
||||
#include <boost/mysql/detail/protocol/deserialize_text_field.hpp>
|
||||
#include <boost/mysql/detail/auxiliar/stringize.hpp>
|
||||
#include "boost/mysql/detail/auxiliar/string_view_offset.hpp"
|
||||
#include "boost/mysql/field_view.hpp"
|
||||
#include "test_common.hpp"
|
||||
#include <boost/test/data/monomorphic/collection.hpp>
|
||||
#include <boost/test/data/test_case.hpp>
|
||||
#include <boost/test/unit_test_suite.hpp>
|
||||
|
||||
using namespace boost::mysql::detail;
|
||||
using namespace boost::mysql::test;
|
||||
@@ -22,7 +26,12 @@ using boost::mysql::errc;
|
||||
namespace
|
||||
{
|
||||
|
||||
struct text_value_sample
|
||||
BOOST_AUTO_TEST_SUITE(test_deserialize_text_field)
|
||||
|
||||
// Success cases
|
||||
BOOST_AUTO_TEST_SUITE(success)
|
||||
|
||||
struct success_sample
|
||||
{
|
||||
std::string name;
|
||||
std::string from;
|
||||
@@ -32,7 +41,7 @@ struct text_value_sample
|
||||
std::uint16_t flags;
|
||||
|
||||
template <class T>
|
||||
text_value_sample(
|
||||
success_sample(
|
||||
std::string&& name,
|
||||
std::string&& from,
|
||||
T&& expected_value,
|
||||
@@ -50,7 +59,7 @@ struct text_value_sample
|
||||
}
|
||||
};
|
||||
|
||||
std::ostream& operator<<(std::ostream& os, const text_value_sample& input)
|
||||
std::ostream& operator<<(std::ostream& os, const success_sample& input)
|
||||
{
|
||||
return os << "(input=" << input.from
|
||||
<< ", type=" << to_string(input.type)
|
||||
@@ -58,7 +67,7 @@ std::ostream& operator<<(std::ostream& os, const text_value_sample& input)
|
||||
<< ")";
|
||||
}
|
||||
|
||||
void add_string_samples(std::vector<text_value_sample>& output)
|
||||
void add_string_samples(std::vector<success_sample>& output)
|
||||
{
|
||||
output.emplace_back("varchar_non_empty", "string", "string", protocol_field_type::var_string);
|
||||
output.emplace_back("varchar_empty", "", "", protocol_field_type::var_string);
|
||||
@@ -88,7 +97,7 @@ void add_int_samples_helper(
|
||||
std::string zerofill_s,
|
||||
std::uint64_t zerofill_b,
|
||||
protocol_field_type type,
|
||||
std::vector<text_value_sample>& output
|
||||
std::vector<success_sample>& output
|
||||
)
|
||||
{
|
||||
output.emplace_back("signed", "20", std::int64_t(20), type);
|
||||
@@ -103,7 +112,7 @@ void add_int_samples_helper(
|
||||
zerofill_b, type, column_flags::unsigned_ | column_flags::zerofill);
|
||||
}
|
||||
|
||||
void add_int_samples(std::vector<text_value_sample>& output)
|
||||
void add_int_samples(std::vector<success_sample>& output)
|
||||
{
|
||||
add_int_samples_helper(
|
||||
"127", 127,
|
||||
@@ -162,7 +171,7 @@ void add_int_samples(std::vector<text_value_sample>& output)
|
||||
}
|
||||
|
||||
// bit
|
||||
void add_bit_types(std::vector<text_value_sample>& output)
|
||||
void add_bit_types(std::vector<success_sample>& output)
|
||||
{
|
||||
output.emplace_back("bit_8", "\x12", std::uint64_t(0x12),
|
||||
protocol_field_type::bit, column_flags::unsigned_);
|
||||
@@ -185,7 +194,7 @@ void add_bit_types(std::vector<text_value_sample>& output)
|
||||
template <class T>
|
||||
void add_float_samples(
|
||||
protocol_field_type type,
|
||||
std::vector<text_value_sample>& output
|
||||
std::vector<success_sample>& output
|
||||
)
|
||||
{
|
||||
output.emplace_back("zero", "0", T(0.0), type);
|
||||
@@ -203,7 +212,7 @@ void add_float_samples(
|
||||
output.emplace_back("negative_exponent_negative_fractional", "-3.45e-20", T(-3.45e-20), type);
|
||||
}
|
||||
|
||||
void add_date_samples(std::vector<text_value_sample>& output)
|
||||
void add_date_samples(std::vector<success_sample>& output)
|
||||
{
|
||||
output.emplace_back("regular_date", "2019-02-28", makedate(2019, 2, 28), protocol_field_type::date);
|
||||
output.emplace_back("leap_year", "1788-02-29", makedate(1788, 2, 29), protocol_field_type::date);
|
||||
@@ -218,7 +227,7 @@ void add_date_samples(std::vector<text_value_sample>& output)
|
||||
|
||||
void add_datetime_samples(
|
||||
protocol_field_type type,
|
||||
std::vector<text_value_sample>& output
|
||||
std::vector<success_sample>& output
|
||||
)
|
||||
{
|
||||
output.emplace_back("0_decimals_date", "2010-02-15 00:00:00", makedt(2010, 2, 15), type);
|
||||
@@ -264,7 +273,8 @@ void add_datetime_samples(
|
||||
// not a real case, we cap decimals to 6
|
||||
output.emplace_back("7_decimals", "2010-02-15 02:05:30.002395", makedt(2010, 2, 15, 2, 5, 30, 2395), type, 0, 7);
|
||||
|
||||
// Generate all invalid date casuistic for all decimals
|
||||
// Generate all invalid date casuistic for all decimals.
|
||||
// These are accepted by MySQL depending on the configuration
|
||||
constexpr struct
|
||||
{
|
||||
const char* name;
|
||||
@@ -294,7 +304,7 @@ void add_datetime_samples(
|
||||
}
|
||||
}
|
||||
|
||||
void add_time_samples(std::vector<text_value_sample>& output)
|
||||
void add_time_samples(std::vector<success_sample>& output)
|
||||
{
|
||||
output.emplace_back("0_decimals_positive_h", "01:00:00", maket(1, 0, 0), protocol_field_type::time);
|
||||
output.emplace_back("0_decimals_positive_hm", "12:03:00", maket(12, 3, 0), protocol_field_type::time);
|
||||
@@ -365,9 +375,9 @@ void add_time_samples(std::vector<text_value_sample>& output)
|
||||
output.emplace_back("7_decimals", "14:51:23.501717", maket(14, 51, 23, 501717), protocol_field_type::time, 0, 7);
|
||||
}
|
||||
|
||||
std::vector<text_value_sample> make_all_samples()
|
||||
std::vector<success_sample> make_all_samples()
|
||||
{
|
||||
std::vector<text_value_sample> res;
|
||||
std::vector<success_sample> res;
|
||||
add_string_samples(res);
|
||||
add_int_samples(res);
|
||||
add_bit_types(res);
|
||||
@@ -380,17 +390,291 @@ std::vector<text_value_sample> make_all_samples()
|
||||
return res;
|
||||
}
|
||||
|
||||
BOOST_DATA_TEST_CASE(test_deserialize_text_value_ok, data::make(make_all_samples()))
|
||||
BOOST_DATA_TEST_CASE(ok, data::make(make_all_samples()))
|
||||
{
|
||||
column_definition_packet coldef {};
|
||||
coldef.type = sample.type;
|
||||
coldef.decimals = static_cast<std::uint8_t>(sample.decimals);
|
||||
coldef.flags = sample.flags;
|
||||
boost::mysql::metadata meta (coldef);
|
||||
boost::mysql::metadata meta (coldef, false);
|
||||
const std::uint8_t* buffer_first = reinterpret_cast<const std::uint8_t*>(sample.from.data());
|
||||
field_view actual_value;
|
||||
auto err = deserialize_text_value(sample.from, meta, actual_value);
|
||||
|
||||
auto err = deserialize_text_field(
|
||||
sample.from,
|
||||
meta,
|
||||
buffer_first,
|
||||
actual_value
|
||||
);
|
||||
BOOST_TEST(err == errc::ok);
|
||||
|
||||
// Strings are representd as string view offsets
|
||||
if (sample.expected.is_string())
|
||||
{
|
||||
field_view expected_offset (string_view_offset(0, sample.expected.get_string().size()));
|
||||
BOOST_TEST(actual_value == expected_offset);
|
||||
actual_value.offset_to_string_view(buffer_first);
|
||||
}
|
||||
|
||||
BOOST_TEST(actual_value == sample.expected);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_SUITE_END()
|
||||
|
||||
//
|
||||
// Error cases
|
||||
//
|
||||
|
||||
BOOST_AUTO_TEST_SUITE(errors)
|
||||
|
||||
struct error_sample
|
||||
{
|
||||
std::string name;
|
||||
boost::string_view from;
|
||||
protocol_field_type type;
|
||||
std::uint16_t flags;
|
||||
unsigned decimals;
|
||||
errc expected_err;
|
||||
|
||||
error_sample(std::string&& name, boost::string_view from, protocol_field_type type,
|
||||
std::uint16_t flags=0, unsigned decimals=0, errc expected_err=errc::protocol_value_error) :
|
||||
name(std::move(name)),
|
||||
from(from),
|
||||
type(type),
|
||||
flags(flags),
|
||||
decimals(decimals),
|
||||
expected_err(expected_err)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
std::ostream& operator<<(std::ostream& os, const error_sample& input)
|
||||
{
|
||||
return os << "(input=" << input.from
|
||||
<< ", type=" << to_string(input.type)
|
||||
<< ", name=" << input.name
|
||||
<< ")";
|
||||
}
|
||||
|
||||
void add_int_samples(
|
||||
protocol_field_type t,
|
||||
std::vector<error_sample>& output
|
||||
)
|
||||
{
|
||||
output.emplace_back("signed_blank", "", t);
|
||||
output.emplace_back("signed_non_number", "abtrf", t);
|
||||
output.emplace_back("signed_hex", "0x01", t);
|
||||
output.emplace_back("signed_fractional", "1.1", t);
|
||||
output.emplace_back("signed_exp", "2e10", t);
|
||||
output.emplace_back("signed_lt_min", "-9223372036854775809", t);
|
||||
output.emplace_back("signed_gt_max", "9223372036854775808", t);
|
||||
output.emplace_back("unsigned_blank", "", t, column_flags::unsigned_);
|
||||
output.emplace_back("unsigned_non_number", "abtrf", t, column_flags::unsigned_);
|
||||
output.emplace_back("unsigned_hex", "0x01", t, column_flags::unsigned_);
|
||||
output.emplace_back("unsigned_fractional", "1.1", t, column_flags::unsigned_);
|
||||
output.emplace_back("unsigned_exp", "2e10", t, column_flags::unsigned_);
|
||||
output.emplace_back("unsigned_lt_min", "-18446744073709551616", t, column_flags::unsigned_);
|
||||
output.emplace_back("unsigned_gt_max", "18446744073709551616", t, column_flags::unsigned_);
|
||||
}
|
||||
|
||||
void add_bit_samples(
|
||||
std::vector<error_sample>& output
|
||||
)
|
||||
{
|
||||
output.emplace_back("bit_string_view_too_short", "", protocol_field_type::bit, column_flags::unsigned_);
|
||||
output.emplace_back("bit_string_view_too_long", "123456789", protocol_field_type::bit, column_flags::unsigned_);
|
||||
}
|
||||
|
||||
void add_float_samples(
|
||||
protocol_field_type t,
|
||||
boost::string_view lt_min,
|
||||
boost::string_view gt_max,
|
||||
std::vector<error_sample>& output
|
||||
)
|
||||
{
|
||||
output.emplace_back("blank", "", t);
|
||||
output.emplace_back("non_number", "abtrf", t);
|
||||
output.emplace_back("lt_min", lt_min, t);
|
||||
output.emplace_back("gt_max", gt_max, t);
|
||||
output.emplace_back("inf", "inf", t); // inf values not allowed by SQL std
|
||||
output.emplace_back("minus_inf", "-inf", t);
|
||||
output.emplace_back("nan", "nan", t); // nan values not allowed by SQL std
|
||||
output.emplace_back("minus_nan", "-nan", t);
|
||||
}
|
||||
|
||||
void add_date_samples(std::vector<error_sample>& output)
|
||||
{
|
||||
output.emplace_back("empty", "", protocol_field_type::date);
|
||||
output.emplace_back("too_short", "2020-05-2", protocol_field_type::date);
|
||||
output.emplace_back("too_long", "02020-05-02", protocol_field_type::date);
|
||||
output.emplace_back("bad_delimiter", "2020:05:02", protocol_field_type::date);
|
||||
output.emplace_back("too_many_groups", "20-20-05-2", protocol_field_type::date);
|
||||
output.emplace_back("too_few_groups", "2020-00005", protocol_field_type::date);
|
||||
output.emplace_back("incomplete_year", "999-05-005", protocol_field_type::date);
|
||||
output.emplace_back("hex", "ffff-ff-ff", protocol_field_type::date);
|
||||
output.emplace_back("null_value", makesv("2020-05-\02"), protocol_field_type::date);
|
||||
output.emplace_back("long_year", "10000-05-2", protocol_field_type::date);
|
||||
output.emplace_back("long_month", "2010-005-2", protocol_field_type::date);
|
||||
output.emplace_back("long_day", "2010-5-002", protocol_field_type::date);
|
||||
output.emplace_back("negative_year", "-001-05-02", protocol_field_type::date);
|
||||
output.emplace_back("invalid_month", "2010-13-02", protocol_field_type::date);
|
||||
output.emplace_back("invalid_month_max","2010-99-02", protocol_field_type::date);
|
||||
output.emplace_back("negative_month", "2010--5-02", protocol_field_type::date);
|
||||
output.emplace_back("invalid_day", "2010-05-32", protocol_field_type::date);
|
||||
output.emplace_back("invalid_day_max", "2010-05-99", protocol_field_type::date);
|
||||
output.emplace_back("negative_day", "2010-05--2", protocol_field_type::date);
|
||||
}
|
||||
|
||||
void add_datetime_samples(
|
||||
protocol_field_type t,
|
||||
std::vector<error_sample>& output
|
||||
)
|
||||
{
|
||||
output.emplace_back("empty", "", t);
|
||||
output.emplace_back("too_short_0", "2020-05-02 23:01:0", t, 0, 0);
|
||||
output.emplace_back("too_short_1", "2020-05-02 23:01:0.1", t, 0, 1);
|
||||
output.emplace_back("too_short_2", "2020-05-02 23:01:00.1", t, 0, 2);
|
||||
output.emplace_back("too_short_3", "2020-05-02 23:01:00.11", t, 0, 3);
|
||||
output.emplace_back("too_short_4", "2020-05-02 23:01:00.111", t, 0, 4);
|
||||
output.emplace_back("too_short_5", "2020-05-02 23:01:00.1111", t, 0, 5);
|
||||
output.emplace_back("too_short_6", "2020-05-02 23:01:00.11111", t, 0, 6);
|
||||
output.emplace_back("too_long_0", "2020-05-02 23:01:00.8", t, 0, 0);
|
||||
output.emplace_back("too_long_1", "2020-05-02 23:01:00.98", t, 0, 1);
|
||||
output.emplace_back("too_long_2", "2020-05-02 23:01:00.998", t, 0, 2);
|
||||
output.emplace_back("too_long_3", "2020-05-02 23:01:00.9998", t, 0, 3);
|
||||
output.emplace_back("too_long_4", "2020-05-02 23:01:00.99998", t, 0, 4);
|
||||
output.emplace_back("too_long_5", "2020-05-02 23:01:00.999998", t, 0, 5);
|
||||
output.emplace_back("too_long_6", "2020-05-02 23:01:00.9999998", t, 0, 6);
|
||||
output.emplace_back("no_decimals_1", "2020-05-02 23:01:00 ", t, 0, 1);
|
||||
output.emplace_back("no_decimals_2", "2020-05-02 23:01:00 ", t, 0, 2);
|
||||
output.emplace_back("no_decimals_3", "2020-05-02 23:01:00 ", t, 0, 3);
|
||||
output.emplace_back("no_decimals_4", "2020-05-02 23:01:00 ", t, 0, 4);
|
||||
output.emplace_back("no_decimals_5", "2020-05-02 23:01:00 ", t, 0, 5);
|
||||
output.emplace_back("no_decimals_6", "2020-05-02 23:01:00 ", t, 0, 6);
|
||||
output.emplace_back("trailing_0", "2020-05-02 23:01:0p", t, 0, 0);
|
||||
output.emplace_back("trailing_1", "2020-05-02 23:01:00.p", t, 0, 1);
|
||||
output.emplace_back("trailing_2", "2020-05-02 23:01:00.1p", t, 0, 2);
|
||||
output.emplace_back("trailing_3", "2020-05-02 23:01:00.12p", t, 0, 3);
|
||||
output.emplace_back("trailing_4", "2020-05-02 23:01:00.123p", t, 0, 4);
|
||||
output.emplace_back("trailing_5", "2020-05-02 23:01:00.1234p", t, 0, 5);
|
||||
output.emplace_back("trailing_6", "2020-05-02 23:01:00.12345p", t, 0, 6);
|
||||
output.emplace_back("bad_delimiter", "2020-05-02 23-01-00", t);
|
||||
output.emplace_back("missing_1gp_0", "2020-05-02 23:01: ", t);
|
||||
output.emplace_back("missing_2gp_0", "2020-05-02 23: ", t);
|
||||
output.emplace_back("missing_3gp_0", "2020-05-02 ", t);
|
||||
output.emplace_back("missing_1gp_1", "2020-05-02 23:01:.9 ", t);
|
||||
output.emplace_back("missing_2gp_1", "2020-05-02 23:.9 ", t);
|
||||
output.emplace_back("missing_3gp_1", "2020-05-02.9 ", t);
|
||||
output.emplace_back("invalid_year", "10000-05-02 24:20:20.1", t, 0, 2);
|
||||
output.emplace_back("negative_year", "-100-05-02 24:20:20", t);
|
||||
output.emplace_back("invalid_month", "2020-13-02 24:20:20", t);
|
||||
output.emplace_back("negative_month", "2020--5-02 24:20:20", t);
|
||||
output.emplace_back("invalid_day", "2020-05-32 24:20:20", t);
|
||||
output.emplace_back("negative_day", "2020-05--2 24:20:20", t);
|
||||
output.emplace_back("invalid_hour", "2020-05-02 24:20:20", t);
|
||||
output.emplace_back("negative_hour", "2020-05-02 -2:20:20", t);
|
||||
output.emplace_back("invalid_min", "2020-05-02 22:60:20", t);
|
||||
output.emplace_back("negative_min", "2020-05-02 22:-1:20", t);
|
||||
output.emplace_back("invalid_sec", "2020-05-02 22:06:60", t);
|
||||
output.emplace_back("negative_sec", "2020-05-02 22:06:-1", t);
|
||||
output.emplace_back("negative_micro_2", "2020-05-02 22:06:01.-1", t, 0, 2);
|
||||
output.emplace_back("negative_micro_3", "2020-05-02 22:06:01.-12", t, 0, 3);
|
||||
output.emplace_back("negative_micro_4", "2020-05-02 22:06:01.-123", t, 0, 4);
|
||||
output.emplace_back("negative_micro_5", "2020-05-02 22:06:01.-1234", t, 0, 5);
|
||||
output.emplace_back("negative_micro_6", "2020-05-02 22:06:01.-12345", t, 0, 6);
|
||||
}
|
||||
|
||||
void add_time_samples(std::vector<error_sample>& output)
|
||||
{
|
||||
output.emplace_back("empty", "", protocol_field_type::time);
|
||||
output.emplace_back("not_numbers", "abjkjdb67", protocol_field_type::time);
|
||||
output.emplace_back("too_short_0", "1:20:20", protocol_field_type::time);
|
||||
output.emplace_back("too_short_1", "1:20:20.1", protocol_field_type::time, 0, 1);
|
||||
output.emplace_back("too_short_2", "01:20:20.1", protocol_field_type::time, 0, 2);
|
||||
output.emplace_back("too_short_3", "01:20:20.12", protocol_field_type::time, 0, 3);
|
||||
output.emplace_back("too_short_4", "01:20:20.123", protocol_field_type::time, 0, 4);
|
||||
output.emplace_back("too_short_5", "01:20:20.1234", protocol_field_type::time, 0, 5);
|
||||
output.emplace_back("too_short_6", "01:20:20.12345", protocol_field_type::time, 0, 6);
|
||||
output.emplace_back("too_long_0", "-9999:40:40", protocol_field_type::time, 0, 0);
|
||||
output.emplace_back("too_long_1", "-9999:40:40.1", protocol_field_type::time, 0, 1);
|
||||
output.emplace_back("too_long_2", "-9999:40:40.12", protocol_field_type::time, 0, 2);
|
||||
output.emplace_back("too_long_3", "-9999:40:40.123", protocol_field_type::time, 0, 3);
|
||||
output.emplace_back("too_long_4", "-9999:40:40.1234", protocol_field_type::time, 0, 4);
|
||||
output.emplace_back("too_long_5", "-9999:40:40.12345", protocol_field_type::time, 0, 5);
|
||||
output.emplace_back("too_long_6", "-9999:40:40.123456", protocol_field_type::time, 0, 6);
|
||||
output.emplace_back("extra_long", "-99999999:40:40.12345678", protocol_field_type::time, 0, 6);
|
||||
output.emplace_back("extra_long2", "99999999999:40:40", protocol_field_type::time, 0, 6);
|
||||
output.emplace_back("decimals_0", "01:20:20.1", protocol_field_type::time, 0, 0);
|
||||
output.emplace_back("no_decimals_1", "01:20:20 ", protocol_field_type::time, 0, 1);
|
||||
output.emplace_back("no_decimals_2", "01:20:20 ", protocol_field_type::time, 0, 2);
|
||||
output.emplace_back("no_decimals_3", "01:20:20 ", protocol_field_type::time, 0, 3);
|
||||
output.emplace_back("no_decimals_4", "01:20:20 ", protocol_field_type::time, 0, 4);
|
||||
output.emplace_back("no_decimals_5", "01:20:20 ", protocol_field_type::time, 0, 5);
|
||||
output.emplace_back("no_decimals_6", "01:20:20 ", protocol_field_type::time, 0, 6);
|
||||
output.emplace_back("bad_delimiter", "01-20-20", protocol_field_type::time);
|
||||
output.emplace_back("missing_1gp_0", "23:01: ", protocol_field_type::time);
|
||||
output.emplace_back("missing_2gp_0", "23: ", protocol_field_type::time);
|
||||
output.emplace_back("missing_1gp_1", "23:01:.9 ", protocol_field_type::time, 0, 1);
|
||||
output.emplace_back("missing_2gp_1", "23:.9 ", protocol_field_type::time, 0, 1);
|
||||
output.emplace_back("invalid_min", "22:60:20", protocol_field_type::time);
|
||||
output.emplace_back("negative_min", "22:-1:20", protocol_field_type::time);
|
||||
output.emplace_back("invalid_sec", "22:06:60", protocol_field_type::time);
|
||||
output.emplace_back("negative_sec", "22:06:-1", protocol_field_type::time);
|
||||
output.emplace_back("invalid_micro_1", "22:06:01.99", protocol_field_type::time, 0, 1);
|
||||
output.emplace_back("invalid_micro_2", "22:06:01.999", protocol_field_type::time, 0, 2);
|
||||
output.emplace_back("invalid_micro_3", "22:06:01.9999", protocol_field_type::time, 0, 3);
|
||||
output.emplace_back("invalid_micro_4", "22:06:01.99999", protocol_field_type::time, 0, 4);
|
||||
output.emplace_back("invalid_micro_5", "22:06:01.999999", protocol_field_type::time, 0, 5);
|
||||
output.emplace_back("invalid_micro_6", "22:06:01.9999999", protocol_field_type::time, 0, 6);
|
||||
output.emplace_back("negative_micro", "22:06:01.-1", protocol_field_type::time, 0, 2);
|
||||
output.emplace_back("lt_min", "-900:00:00.00", protocol_field_type::time, 0, 2);
|
||||
output.emplace_back("gt_max", "900:00:00.00", protocol_field_type::time, 0, 2);
|
||||
output.emplace_back("invalid_sign", "x670:00:00.00", protocol_field_type::time, 0, 2);
|
||||
output.emplace_back("null_char", makesv("20:00:\00.00"), protocol_field_type::time, 0, 2);
|
||||
output.emplace_back("trailing_0", "22:06:01k", protocol_field_type::time, 0, 0);
|
||||
output.emplace_back("trailing_1", "22:06:01.1k", protocol_field_type::time, 0, 1);
|
||||
output.emplace_back("trailing_2", "22:06:01.12k", protocol_field_type::time, 0, 2);
|
||||
output.emplace_back("trailing_3", "22:06:01.123k", protocol_field_type::time, 0, 3);
|
||||
output.emplace_back("trailing_4", "22:06:01.1234k", protocol_field_type::time, 0, 4);
|
||||
output.emplace_back("trailing_5", "22:06:01.12345k", protocol_field_type::time, 0, 5);
|
||||
output.emplace_back("trailing_6", "22:06:01.123456k", protocol_field_type::time, 0, 6);
|
||||
output.emplace_back("double_sign", "--22:06:01.123456", protocol_field_type::time, 0, 6);
|
||||
}
|
||||
|
||||
std::vector<error_sample> make_all_samples()
|
||||
{
|
||||
std::vector<error_sample> res;
|
||||
add_int_samples(protocol_field_type::tiny, res);
|
||||
add_int_samples(protocol_field_type::short_, res);
|
||||
add_int_samples(protocol_field_type::int24, res);
|
||||
add_int_samples(protocol_field_type::long_, res);
|
||||
add_int_samples(protocol_field_type::longlong, res);
|
||||
add_int_samples(protocol_field_type::year, res);
|
||||
add_bit_samples(res);
|
||||
add_float_samples(protocol_field_type::float_, "-2e90", "2e90", res);
|
||||
add_float_samples(protocol_field_type::double_, "-2e9999", "2e9999", res);
|
||||
add_date_samples(res);
|
||||
add_datetime_samples(protocol_field_type::datetime, res);
|
||||
add_datetime_samples(protocol_field_type::timestamp, res);
|
||||
add_time_samples(res);
|
||||
return res;
|
||||
}
|
||||
|
||||
BOOST_DATA_TEST_CASE(error, data::make(make_all_samples()))
|
||||
{
|
||||
column_definition_packet coldef {};
|
||||
coldef.type = sample.type;
|
||||
coldef.decimals = static_cast<std::uint8_t>(sample.decimals);
|
||||
coldef.flags = sample.flags;
|
||||
boost::mysql::metadata meta (coldef, false);
|
||||
auto buffer_first = reinterpret_cast<const std::uint8_t*>(sample.from.data());
|
||||
field_view actual_value;
|
||||
auto err = deserialize_text_field(sample.from, meta, buffer_first, actual_value);
|
||||
BOOST_TEST(err == sample.expected_err);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_SUITE_END()
|
||||
|
||||
BOOST_AUTO_TEST_SUITE_END()
|
||||
|
||||
} // anon namespace
|
||||
@@ -9,6 +9,7 @@
|
||||
#define BOOST_MYSQL_TEST_UNIT_DETAIL_PROTOCOL_SERIALIZATION_TEST_SAMPLES_PREPARED_STATEMENT_MESSAGES_HPP
|
||||
|
||||
#include <boost/mysql/detail/protocol/prepared_statement_messages.hpp>
|
||||
#include <boost/mysql/field_view.hpp>
|
||||
#include "../serialization_test.hpp"
|
||||
#include <forward_list>
|
||||
#include <array>
|
||||
@@ -79,7 +80,7 @@ serialization_sample make_stmt_execute_sample(
|
||||
const serialization_test_spec com_stmt_execute_packet_spec {
|
||||
serialization_test_type::serialization, {
|
||||
make_stmt_execute_sample(1, 0x80, 1, 1, // stmt ID, flags, itercount, new params
|
||||
make_values(std::uint64_t(0xabffffabacadae)), {
|
||||
make_field_views(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
|
||||
@@ -87,7 +88,7 @@ const serialization_test_spec com_stmt_execute_packet_spec {
|
||||
"uint64_t"
|
||||
),
|
||||
make_stmt_execute_sample(1, 0, 1, 1, // stmt ID, flags, itercount, new params
|
||||
make_values(std::int64_t(-0xabffffabacadae)), {
|
||||
make_field_views(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
|
||||
@@ -95,7 +96,7 @@ const serialization_test_spec com_stmt_execute_packet_spec {
|
||||
"int64_t"
|
||||
),
|
||||
make_stmt_execute_sample(1, 0, 1, 1, // stmt ID, flags, itercount, new params
|
||||
make_values(boost::string_view("test")), {
|
||||
make_field_views(boost::string_view("test")), {
|
||||
0x17, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00,
|
||||
0x00, 0x00, 0x00, 0x01, 0x0f, 0x00, 0x04, 0x74,
|
||||
0x65, 0x73, 0x74
|
||||
@@ -103,7 +104,7 @@ const serialization_test_spec com_stmt_execute_packet_spec {
|
||||
"string_view"
|
||||
),
|
||||
make_stmt_execute_sample(1, 0, 1, 1, // stmt ID, flags, itercount, new params
|
||||
make_values(3.14e20f), {
|
||||
make_field_views(3.14e20f), {
|
||||
0x17, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00,
|
||||
0x00, 0x00, 0x00, 0x01, 0x04, 0x00, 0x01, 0x2d,
|
||||
0x88, 0x61
|
||||
@@ -111,7 +112,7 @@ const serialization_test_spec com_stmt_execute_packet_spec {
|
||||
"float"
|
||||
),
|
||||
make_stmt_execute_sample(1, 0, 1, 1, // stmt ID, flags, itercount, new params
|
||||
make_values(2.1e214), {
|
||||
make_field_views(2.1e214), {
|
||||
0x17, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00,
|
||||
0x00, 0x00, 0x00, 0x01, 0x05, 0x00, 0x56, 0xc0,
|
||||
0xee, 0xa6, 0x95, 0x30, 0x6f, 0x6c
|
||||
@@ -119,7 +120,7 @@ const serialization_test_spec com_stmt_execute_packet_spec {
|
||||
"double"
|
||||
),
|
||||
make_stmt_execute_sample(1, 0, 1, 1, // stmt ID, flags, itercount, new params
|
||||
make_values(makedate(2010, 9, 3)), {
|
||||
make_field_views(makedate(2010, 9, 3)), {
|
||||
0x17, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00,
|
||||
0x00, 0x00, 0x00, 0x01, 0x0a, 0x00, 0x04, 0xda,
|
||||
0x07, 0x09, 0x03
|
||||
@@ -127,7 +128,7 @@ const serialization_test_spec com_stmt_execute_packet_spec {
|
||||
"date"
|
||||
),
|
||||
make_stmt_execute_sample(1, 0, 1, 1, // stmt ID, flags, itercount, new params
|
||||
make_values(makedt(2010, 9, 3, 10, 30, 59, 231800)), {
|
||||
make_field_views(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,
|
||||
@@ -136,7 +137,7 @@ const serialization_test_spec com_stmt_execute_packet_spec {
|
||||
"datetime"
|
||||
),
|
||||
make_stmt_execute_sample(1, 0, 1, 1, // stmt ID, flags, itercount, new params
|
||||
make_values(maket(230, 30, 59, 231800)), {
|
||||
make_field_views(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,
|
||||
@@ -145,14 +146,14 @@ const serialization_test_spec com_stmt_execute_packet_spec {
|
||||
"time"
|
||||
),
|
||||
make_stmt_execute_sample(1, 0, 1, 1, // stmt ID, flags, itercount, new params
|
||||
make_values(nullptr), {
|
||||
make_field_views(nullptr), {
|
||||
0x17, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00,
|
||||
0x00, 0x00, 0x01, 0x01, 0x06, 0x00
|
||||
},
|
||||
"null"
|
||||
),
|
||||
make_stmt_execute_sample(2, 0, 1, 1,
|
||||
make_values(
|
||||
make_field_views(
|
||||
std::uint64_t(0xabffffabacadae),
|
||||
std::int64_t(-0xabffffabacadae),
|
||||
boost::string_view("test"),
|
||||
@@ -178,7 +179,7 @@ const serialization_test_spec com_stmt_execute_packet_spec {
|
||||
"several_params"
|
||||
),
|
||||
make_stmt_execute_sample<1, std::forward_list<field_view>>(1, 0x80, 1, 1,
|
||||
make_values(std::uint64_t(0xabffff)), {
|
||||
make_field_views(std::uint64_t(0xabffff)), {
|
||||
0x17, 0x01, 0x00, 0x00, 0x00, 0x80, 0x01, 0x00,
|
||||
0x00, 0x00, 0x00, 0x01, 0x08, 0x80, 0xff, 0xff,
|
||||
0xab, 0x00, 0x00, 0x00, 0x00, 0x00
|
||||
|
||||
@@ -1,271 +0,0 @@
|
||||
//
|
||||
// Copyright (c) 2019-2022 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)
|
||||
//
|
||||
|
||||
// Test deserialize_text_value(), only error cases
|
||||
|
||||
#include <boost/mysql/detail/protocol/text_deserialization.hpp>
|
||||
#include "test_common.hpp"
|
||||
#include <boost/test/data/monomorphic/collection.hpp>
|
||||
#include <boost/test/data/test_case.hpp>
|
||||
|
||||
using namespace boost::mysql::detail;
|
||||
using namespace boost::mysql::test;
|
||||
using namespace boost::unit_test;
|
||||
using boost::mysql::field_view;
|
||||
using boost::mysql::error_code;
|
||||
using boost::mysql::errc;
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
struct text_value_err_sample
|
||||
{
|
||||
std::string name;
|
||||
boost::string_view from;
|
||||
protocol_field_type type;
|
||||
std::uint16_t flags;
|
||||
unsigned decimals;
|
||||
errc expected_err;
|
||||
|
||||
text_value_err_sample(std::string&& name, boost::string_view from, protocol_field_type type,
|
||||
std::uint16_t flags=0, unsigned decimals=0, errc expected_err=errc::protocol_value_error) :
|
||||
name(std::move(name)),
|
||||
from(from),
|
||||
type(type),
|
||||
flags(flags),
|
||||
decimals(decimals),
|
||||
expected_err(expected_err)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
std::ostream& operator<<(std::ostream& os, const text_value_err_sample& input)
|
||||
{
|
||||
return os << "(input=" << input.from
|
||||
<< ", type=" << to_string(input.type)
|
||||
<< ", name=" << input.name
|
||||
<< ")";
|
||||
}
|
||||
|
||||
void add_int_samples(
|
||||
protocol_field_type t,
|
||||
std::vector<text_value_err_sample>& output
|
||||
)
|
||||
{
|
||||
output.emplace_back("signed_blank", "", t);
|
||||
output.emplace_back("signed_non_number", "abtrf", t);
|
||||
output.emplace_back("signed_hex", "0x01", t);
|
||||
output.emplace_back("signed_fractional", "1.1", t);
|
||||
output.emplace_back("signed_exp", "2e10", t);
|
||||
output.emplace_back("signed_lt_min", "-9223372036854775809", t);
|
||||
output.emplace_back("signed_gt_max", "9223372036854775808", t);
|
||||
output.emplace_back("unsigned_blank", "", t, column_flags::unsigned_);
|
||||
output.emplace_back("unsigned_non_number", "abtrf", t, column_flags::unsigned_);
|
||||
output.emplace_back("unsigned_hex", "0x01", t, column_flags::unsigned_);
|
||||
output.emplace_back("unsigned_fractional", "1.1", t, column_flags::unsigned_);
|
||||
output.emplace_back("unsigned_exp", "2e10", t, column_flags::unsigned_);
|
||||
output.emplace_back("unsigned_lt_min", "-18446744073709551616", t, column_flags::unsigned_);
|
||||
output.emplace_back("unsigned_gt_max", "18446744073709551616", t, column_flags::unsigned_);
|
||||
}
|
||||
|
||||
void add_bit_samples(
|
||||
std::vector<text_value_err_sample>& output
|
||||
)
|
||||
{
|
||||
output.emplace_back("bit_string_view_too_short", "", protocol_field_type::bit, column_flags::unsigned_);
|
||||
output.emplace_back("bit_string_view_too_long", "123456789", protocol_field_type::bit, column_flags::unsigned_);
|
||||
}
|
||||
|
||||
void add_float_samples(
|
||||
protocol_field_type t,
|
||||
boost::string_view lt_min,
|
||||
boost::string_view gt_max,
|
||||
std::vector<text_value_err_sample>& output
|
||||
)
|
||||
{
|
||||
output.emplace_back("blank", "", t);
|
||||
output.emplace_back("non_number", "abtrf", t);
|
||||
output.emplace_back("lt_min", lt_min, t);
|
||||
output.emplace_back("gt_max", gt_max, t);
|
||||
output.emplace_back("inf", "inf", t); // inf values not allowed by SQL std
|
||||
output.emplace_back("minus_inf", "-inf", t);
|
||||
output.emplace_back("nan", "nan", t); // nan values not allowed by SQL std
|
||||
output.emplace_back("minus_nan", "-nan", t);
|
||||
}
|
||||
|
||||
void add_date_samples(std::vector<text_value_err_sample>& output)
|
||||
{
|
||||
output.emplace_back("empty", "", protocol_field_type::date);
|
||||
output.emplace_back("too_short", "2020-05-2", protocol_field_type::date);
|
||||
output.emplace_back("too_long", "02020-05-02", protocol_field_type::date);
|
||||
output.emplace_back("bad_delimiter", "2020:05:02", protocol_field_type::date);
|
||||
output.emplace_back("too_many_groups", "20-20-05-2", protocol_field_type::date);
|
||||
output.emplace_back("too_few_groups", "2020-00005", protocol_field_type::date);
|
||||
output.emplace_back("incomplete_year", "999-05-005", protocol_field_type::date);
|
||||
output.emplace_back("hex", "ffff-ff-ff", protocol_field_type::date);
|
||||
output.emplace_back("null_value", makesv("2020-05-\02"), protocol_field_type::date);
|
||||
output.emplace_back("long_year", "10000-05-2", protocol_field_type::date);
|
||||
output.emplace_back("long_month", "2010-005-2", protocol_field_type::date);
|
||||
output.emplace_back("long_day", "2010-5-002", protocol_field_type::date);
|
||||
output.emplace_back("negative_year", "-001-05-02", protocol_field_type::date);
|
||||
output.emplace_back("invalid_month", "2010-13-02", protocol_field_type::date);
|
||||
output.emplace_back("invalid_month_max","2010-99-02", protocol_field_type::date);
|
||||
output.emplace_back("negative_month", "2010--5-02", protocol_field_type::date);
|
||||
output.emplace_back("invalid_day", "2010-05-32", protocol_field_type::date);
|
||||
output.emplace_back("invalid_day_max", "2010-05-99", protocol_field_type::date);
|
||||
output.emplace_back("negative_day", "2010-05--2", protocol_field_type::date);
|
||||
}
|
||||
|
||||
void add_datetime_samples(
|
||||
protocol_field_type t,
|
||||
std::vector<text_value_err_sample>& output
|
||||
)
|
||||
{
|
||||
output.emplace_back("empty", "", t);
|
||||
output.emplace_back("too_short_0", "2020-05-02 23:01:0", t, 0, 0);
|
||||
output.emplace_back("too_short_1", "2020-05-02 23:01:0.1", t, 0, 1);
|
||||
output.emplace_back("too_short_2", "2020-05-02 23:01:00.1", t, 0, 2);
|
||||
output.emplace_back("too_short_3", "2020-05-02 23:01:00.11", t, 0, 3);
|
||||
output.emplace_back("too_short_4", "2020-05-02 23:01:00.111", t, 0, 4);
|
||||
output.emplace_back("too_short_5", "2020-05-02 23:01:00.1111", t, 0, 5);
|
||||
output.emplace_back("too_short_6", "2020-05-02 23:01:00.11111", t, 0, 6);
|
||||
output.emplace_back("too_long_0", "2020-05-02 23:01:00.8", t, 0, 0);
|
||||
output.emplace_back("too_long_1", "2020-05-02 23:01:00.98", t, 0, 1);
|
||||
output.emplace_back("too_long_2", "2020-05-02 23:01:00.998", t, 0, 2);
|
||||
output.emplace_back("too_long_3", "2020-05-02 23:01:00.9998", t, 0, 3);
|
||||
output.emplace_back("too_long_4", "2020-05-02 23:01:00.99998", t, 0, 4);
|
||||
output.emplace_back("too_long_5", "2020-05-02 23:01:00.999998", t, 0, 5);
|
||||
output.emplace_back("too_long_6", "2020-05-02 23:01:00.9999998", t, 0, 6);
|
||||
output.emplace_back("no_decimals_1", "2020-05-02 23:01:00 ", t, 0, 1);
|
||||
output.emplace_back("no_decimals_2", "2020-05-02 23:01:00 ", t, 0, 2);
|
||||
output.emplace_back("no_decimals_3", "2020-05-02 23:01:00 ", t, 0, 3);
|
||||
output.emplace_back("no_decimals_4", "2020-05-02 23:01:00 ", t, 0, 4);
|
||||
output.emplace_back("no_decimals_5", "2020-05-02 23:01:00 ", t, 0, 5);
|
||||
output.emplace_back("no_decimals_6", "2020-05-02 23:01:00 ", t, 0, 6);
|
||||
output.emplace_back("trailing_0", "2020-05-02 23:01:0p", t, 0, 0);
|
||||
output.emplace_back("trailing_1", "2020-05-02 23:01:00.p", t, 0, 1);
|
||||
output.emplace_back("trailing_2", "2020-05-02 23:01:00.1p", t, 0, 2);
|
||||
output.emplace_back("trailing_3", "2020-05-02 23:01:00.12p", t, 0, 3);
|
||||
output.emplace_back("trailing_4", "2020-05-02 23:01:00.123p", t, 0, 4);
|
||||
output.emplace_back("trailing_5", "2020-05-02 23:01:00.1234p", t, 0, 5);
|
||||
output.emplace_back("trailing_6", "2020-05-02 23:01:00.12345p", t, 0, 6);
|
||||
output.emplace_back("bad_delimiter", "2020-05-02 23-01-00", t);
|
||||
output.emplace_back("missing_1gp_0", "2020-05-02 23:01: ", t);
|
||||
output.emplace_back("missing_2gp_0", "2020-05-02 23: ", t);
|
||||
output.emplace_back("missing_3gp_0", "2020-05-02 ", t);
|
||||
output.emplace_back("missing_1gp_1", "2020-05-02 23:01:.9 ", t);
|
||||
output.emplace_back("missing_2gp_1", "2020-05-02 23:.9 ", t);
|
||||
output.emplace_back("missing_3gp_1", "2020-05-02.9 ", t);
|
||||
output.emplace_back("invalid_year", "10000-05-02 24:20:20.1", t, 0, 2);
|
||||
output.emplace_back("negative_year", "-100-05-02 24:20:20", t);
|
||||
output.emplace_back("invalid_month", "2020-13-02 24:20:20", t);
|
||||
output.emplace_back("negative_month", "2020--5-02 24:20:20", t);
|
||||
output.emplace_back("invalid_day", "2020-05-32 24:20:20", t);
|
||||
output.emplace_back("negative_day", "2020-05--2 24:20:20", t);
|
||||
output.emplace_back("invalid_hour", "2020-05-02 24:20:20", t);
|
||||
output.emplace_back("negative_hour", "2020-05-02 -2:20:20", t);
|
||||
output.emplace_back("invalid_min", "2020-05-02 22:60:20", t);
|
||||
output.emplace_back("negative_min", "2020-05-02 22:-1:20", t);
|
||||
output.emplace_back("invalid_sec", "2020-05-02 22:06:60", t);
|
||||
output.emplace_back("negative_sec", "2020-05-02 22:06:-1", t);
|
||||
output.emplace_back("negative_micro_2", "2020-05-02 22:06:01.-1", t, 0, 2);
|
||||
output.emplace_back("negative_micro_3", "2020-05-02 22:06:01.-12", t, 0, 3);
|
||||
output.emplace_back("negative_micro_4", "2020-05-02 22:06:01.-123", t, 0, 4);
|
||||
output.emplace_back("negative_micro_5", "2020-05-02 22:06:01.-1234", t, 0, 5);
|
||||
output.emplace_back("negative_micro_6", "2020-05-02 22:06:01.-12345", t, 0, 6);
|
||||
}
|
||||
|
||||
void add_time_samples(std::vector<text_value_err_sample>& output)
|
||||
{
|
||||
output.emplace_back("empty", "", protocol_field_type::time);
|
||||
output.emplace_back("not_numbers", "abjkjdb67", protocol_field_type::time);
|
||||
output.emplace_back("too_short_0", "1:20:20", protocol_field_type::time);
|
||||
output.emplace_back("too_short_1", "1:20:20.1", protocol_field_type::time, 0, 1);
|
||||
output.emplace_back("too_short_2", "01:20:20.1", protocol_field_type::time, 0, 2);
|
||||
output.emplace_back("too_short_3", "01:20:20.12", protocol_field_type::time, 0, 3);
|
||||
output.emplace_back("too_short_4", "01:20:20.123", protocol_field_type::time, 0, 4);
|
||||
output.emplace_back("too_short_5", "01:20:20.1234", protocol_field_type::time, 0, 5);
|
||||
output.emplace_back("too_short_6", "01:20:20.12345", protocol_field_type::time, 0, 6);
|
||||
output.emplace_back("too_long_0", "-9999:40:40", protocol_field_type::time, 0, 0);
|
||||
output.emplace_back("too_long_1", "-9999:40:40.1", protocol_field_type::time, 0, 1);
|
||||
output.emplace_back("too_long_2", "-9999:40:40.12", protocol_field_type::time, 0, 2);
|
||||
output.emplace_back("too_long_3", "-9999:40:40.123", protocol_field_type::time, 0, 3);
|
||||
output.emplace_back("too_long_4", "-9999:40:40.1234", protocol_field_type::time, 0, 4);
|
||||
output.emplace_back("too_long_5", "-9999:40:40.12345", protocol_field_type::time, 0, 5);
|
||||
output.emplace_back("too_long_6", "-9999:40:40.123456", protocol_field_type::time, 0, 6);
|
||||
output.emplace_back("extra_long", "-99999999:40:40.12345678", protocol_field_type::time, 0, 6);
|
||||
output.emplace_back("extra_long2", "99999999999:40:40", protocol_field_type::time, 0, 6);
|
||||
output.emplace_back("decimals_0", "01:20:20.1", protocol_field_type::time, 0, 0);
|
||||
output.emplace_back("no_decimals_1", "01:20:20 ", protocol_field_type::time, 0, 1);
|
||||
output.emplace_back("no_decimals_2", "01:20:20 ", protocol_field_type::time, 0, 2);
|
||||
output.emplace_back("no_decimals_3", "01:20:20 ", protocol_field_type::time, 0, 3);
|
||||
output.emplace_back("no_decimals_4", "01:20:20 ", protocol_field_type::time, 0, 4);
|
||||
output.emplace_back("no_decimals_5", "01:20:20 ", protocol_field_type::time, 0, 5);
|
||||
output.emplace_back("no_decimals_6", "01:20:20 ", protocol_field_type::time, 0, 6);
|
||||
output.emplace_back("bad_delimiter", "01-20-20", protocol_field_type::time);
|
||||
output.emplace_back("missing_1gp_0", "23:01: ", protocol_field_type::time);
|
||||
output.emplace_back("missing_2gp_0", "23: ", protocol_field_type::time);
|
||||
output.emplace_back("missing_1gp_1", "23:01:.9 ", protocol_field_type::time, 0, 1);
|
||||
output.emplace_back("missing_2gp_1", "23:.9 ", protocol_field_type::time, 0, 1);
|
||||
output.emplace_back("invalid_min", "22:60:20", protocol_field_type::time);
|
||||
output.emplace_back("negative_min", "22:-1:20", protocol_field_type::time);
|
||||
output.emplace_back("invalid_sec", "22:06:60", protocol_field_type::time);
|
||||
output.emplace_back("negative_sec", "22:06:-1", protocol_field_type::time);
|
||||
output.emplace_back("invalid_micro_1", "22:06:01.99", protocol_field_type::time, 0, 1);
|
||||
output.emplace_back("invalid_micro_2", "22:06:01.999", protocol_field_type::time, 0, 2);
|
||||
output.emplace_back("invalid_micro_3", "22:06:01.9999", protocol_field_type::time, 0, 3);
|
||||
output.emplace_back("invalid_micro_4", "22:06:01.99999", protocol_field_type::time, 0, 4);
|
||||
output.emplace_back("invalid_micro_5", "22:06:01.999999", protocol_field_type::time, 0, 5);
|
||||
output.emplace_back("invalid_micro_6", "22:06:01.9999999", protocol_field_type::time, 0, 6);
|
||||
output.emplace_back("negative_micro", "22:06:01.-1", protocol_field_type::time, 0, 2);
|
||||
output.emplace_back("lt_min", "-900:00:00.00", protocol_field_type::time, 0, 2);
|
||||
output.emplace_back("gt_max", "900:00:00.00", protocol_field_type::time, 0, 2);
|
||||
output.emplace_back("invalid_sign", "x670:00:00.00", protocol_field_type::time, 0, 2);
|
||||
output.emplace_back("null_char", makesv("20:00:\00.00"), protocol_field_type::time, 0, 2);
|
||||
output.emplace_back("trailing_0", "22:06:01k", protocol_field_type::time, 0, 0);
|
||||
output.emplace_back("trailing_1", "22:06:01.1k", protocol_field_type::time, 0, 1);
|
||||
output.emplace_back("trailing_2", "22:06:01.12k", protocol_field_type::time, 0, 2);
|
||||
output.emplace_back("trailing_3", "22:06:01.123k", protocol_field_type::time, 0, 3);
|
||||
output.emplace_back("trailing_4", "22:06:01.1234k", protocol_field_type::time, 0, 4);
|
||||
output.emplace_back("trailing_5", "22:06:01.12345k", protocol_field_type::time, 0, 5);
|
||||
output.emplace_back("trailing_6", "22:06:01.123456k", protocol_field_type::time, 0, 6);
|
||||
output.emplace_back("double_sign", "--22:06:01.123456", protocol_field_type::time, 0, 6);
|
||||
}
|
||||
|
||||
std::vector<text_value_err_sample> make_all_samples()
|
||||
{
|
||||
std::vector<text_value_err_sample> res;
|
||||
add_int_samples(protocol_field_type::tiny, res);
|
||||
add_int_samples(protocol_field_type::short_, res);
|
||||
add_int_samples(protocol_field_type::int24, res);
|
||||
add_int_samples(protocol_field_type::long_, res);
|
||||
add_int_samples(protocol_field_type::longlong, res);
|
||||
add_int_samples(protocol_field_type::year, res);
|
||||
add_bit_samples(res);
|
||||
add_float_samples(protocol_field_type::float_, "-2e90", "2e90", res);
|
||||
add_float_samples(protocol_field_type::double_, "-2e9999", "2e9999", res);
|
||||
add_date_samples(res);
|
||||
add_datetime_samples(protocol_field_type::datetime, res);
|
||||
add_datetime_samples(protocol_field_type::timestamp, res);
|
||||
add_time_samples(res);
|
||||
return res;
|
||||
}
|
||||
|
||||
BOOST_DATA_TEST_CASE(test_deserialize_text_value_error, data::make(make_all_samples()))
|
||||
{
|
||||
column_definition_packet coldef {};
|
||||
coldef.type = sample.type;
|
||||
coldef.decimals = static_cast<std::uint8_t>(sample.decimals);
|
||||
coldef.flags = sample.flags;
|
||||
boost::mysql::metadata meta (coldef);
|
||||
field_view actual_value;
|
||||
auto err = deserialize_text_value(sample.from, meta, actual_value);
|
||||
auto expected = sample.expected_err;
|
||||
BOOST_TEST(expected == err);
|
||||
}
|
||||
|
||||
} // anon namespace
|
||||
Reference in New Issue
Block a user