2
0
mirror of https://github.com/boostorg/mysql.git synced 2026-02-15 01:02:17 +00:00

Added support for relational operators in value

Replaced std::nullptr_t for boost::variant2::monostate in values
Added support for relational operators in value
Automatic docs generation

closes #48
closes #46
This commit is contained in:
Ruben Perez
2021-03-06 16:35:15 +01:00
parent 087faf187a
commit ade68d172d
205 changed files with 636 additions and 305 deletions

View File

@@ -1,5 +1,5 @@
//
// Copyright (c) 2019-2020 Ruben Perez Hidalgo (rubenperez038 at gmail dot com)
// Copyright (c) 2019-2021 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)
@@ -7,9 +7,11 @@
#include "boost/mysql/value.hpp"
#include "test_common.hpp"
#include <boost/test/unit_test_suite.hpp>
#include <boost/type_index.hpp>
#include <boost/test/data/monomorphic/collection.hpp>
#include <boost/test/data/test_case.hpp>
#include <set>
#include <sstream>
#include <map>
#include <tuple>
@@ -18,6 +20,7 @@ BOOST_TEST_DONT_PRINT_LOG_VALUE(boost::mysql::value::variant_type)
BOOST_TEST_DONT_PRINT_LOG_VALUE(boost::mysql::date)
BOOST_TEST_DONT_PRINT_LOG_VALUE(boost::mysql::datetime)
BOOST_TEST_DONT_PRINT_LOG_VALUE(boost::mysql::time)
BOOST_TEST_DONT_PRINT_LOG_VALUE(boost::mysql::null_t)
using namespace boost::mysql::test;
using namespace boost::unit_test;
@@ -65,8 +68,9 @@ const T& const_int()
}
const value_constructor_sample all_value_constructor_samples [] {
value_constructor_sample("default_constructor", value(), vt(nullptr)),
value_constructor_sample("from_nullptr", value(nullptr), vt(nullptr)),
value_constructor_sample("default_constructor", value(), vt(boost::variant2::monostate())),
value_constructor_sample("from_null_t", value(boost::mysql::null_t()), vt(boost::variant2::monostate())),
value_constructor_sample("from_nullptr", value(nullptr), vt(boost::variant2::monostate())),
value_constructor_sample("from_u8", value(std::uint8_t(0xff)), vt(std::uint64_t(0xff))),
value_constructor_sample("from_u8_const_lvalue", value(const_int<std::uint8_t>()), vt(std::uint64_t(42))),
value_constructor_sample("from_u8_lvalue", value(non_const_int<std::uint8_t>()), vt(std::uint64_t(42))),
@@ -162,7 +166,7 @@ BOOST_AUTO_TEST_CASE(move_assignment)
// accessors: is, is_convertible_to, is_null, get, get_optional
using all_types = std::tuple<
std::nullptr_t,
boost::mysql::null_t,
std::uint64_t,
std::int64_t,
boost::string_view,
@@ -179,12 +183,14 @@ struct accessors_sample
value v;
type_index is_type; // the type for which is() should return true
std::map<type_index, vt> conversions;
bool is_null;
accessors_sample(const char* name, value v, type_index is, std::map<type_index, vt>&& convs) :
accessors_sample(const char* name, value v, type_index is, std::map<type_index, vt>&& convs, bool is_null = false) :
name(name),
v(v),
is_type(is),
conversions(std::move(convs))
conversions(std::move(convs)),
is_null(is_null)
{
}
};
@@ -203,14 +209,15 @@ std::map<type_index, vt> make_conversions(const Types&... types)
template <class T>
accessors_sample make_default_accessors_sample(
const char* name,
const T& v
const T& v,
bool is_null = false
)
{
return accessors_sample(name, value(v), type_id<T>(), make_conversions(v));
return accessors_sample(name, value(v), type_id<T>(), make_conversions(v), is_null);
}
const accessors_sample all_accessors_samples [] {
make_default_accessors_sample("null", nullptr),
make_default_accessors_sample("null", boost::mysql::null_t(), true),
accessors_sample("i64_positive", value(std::int64_t(42)), type_id<std::int64_t>(),
make_conversions(std::int64_t(42), std::uint64_t(42))),
accessors_sample("i64_negative", value(std::int64_t(-42)), type_id<std::int64_t>(),
@@ -246,8 +253,7 @@ void for_each_accessors_sample(Callable&& cb)
BOOST_DATA_TEST_CASE(is_null, data::make(all_accessors_samples))
{
bool expected = sample.is_type == type_id<std::nullptr_t>();
BOOST_TEST(sample.v.is_null() == expected);
BOOST_TEST(sample.v.is_null() == sample.is_null);
}
BOOST_AUTO_TEST_CASE_TEMPLATE(is, T, all_types)
@@ -336,7 +342,7 @@ struct value_equality_fixture
makedate(2019, 10, 1),
makedt(2019, 10, 1, 10),
maket(0, 0, -10),
nullptr
boost::mysql::null_t()
);
};
@@ -363,10 +369,10 @@ BOOST_FIXTURE_TEST_CASE(operators_eq_ne_same_type_different_value, value_equalit
makedate(2019, 9, 1),
makedt(2019, 9, 1, 10),
maket(0, 0, 10),
nullptr
boost::mysql::null_t()
);
// Note: nullptr_t (the last value) can't have other value than nullptr
// Note: null_t (the last value) can't have other value than null_t()
// so it is excluded from this test
for (std::size_t i = 0; i < values.size() - 1; ++i)
{
@@ -622,7 +628,7 @@ void add_time_samples(std::vector<stream_sample>& output)
std::vector<stream_sample> make_stream_samples()
{
std::vector<stream_sample> res {
{ "null", nullptr, "<NULL>" },
{ "null", boost::mysql::null_t(), "<NULL>" },
{ "i64_positive", std::int64_t(42), "42" },
{ "i64_negative", std::int64_t(-90), "-90" },
{ "i64_zero", std::int64_t(0), "0" },
@@ -645,4 +651,59 @@ BOOST_DATA_TEST_CASE(operator_stream, data::make(make_stream_samples()))
BOOST_TEST(ss.str() == sample.expected);
}
// Operators <, <=, >, >= (variant behavior)
BOOST_AUTO_TEST_CASE(operator_lt)
{
BOOST_TEST(value(100) < value(200)); // same type
BOOST_TEST(value(-2) < value("hola")); // different type
BOOST_TEST(!(value(200) < value(200))); // same type
BOOST_TEST(!(value("hola") < value(2))); // different type
}
BOOST_AUTO_TEST_CASE(operator_lte)
{
BOOST_TEST(value(200) <= value(200)); // same type
BOOST_TEST(value(-2) <= value("hola")); // different type
BOOST_TEST(!(value(300) <= value(200))); // same type
BOOST_TEST(!(value("hola") <= value(2))); // different type
}
BOOST_AUTO_TEST_CASE(operator_gt)
{
BOOST_TEST(value(200) > value(100)); // same type
BOOST_TEST(value("hola") > value(2)); // different type
BOOST_TEST(!(value(200) > value(200))); // same type
BOOST_TEST(!(value(-2) > value("hola"))); // different type
BOOST_TEST(value(std::uint64_t(10)) > value(std::int64_t(20))); // example
}
BOOST_AUTO_TEST_CASE(operator_gte)
{
BOOST_TEST(value(200) >= value(200)); // same type
BOOST_TEST(value("hola") >= value(-2)); // different type
BOOST_TEST(!(value(200) >= value(300))); // same type
BOOST_TEST(!(value(2) >= value("hola"))); // different type
}
// Can be placed in containers
BOOST_AUTO_TEST_CASE(can_be_placed_in_set)
{
std::set<value> s { value(200), value("hola"), value(200) };
BOOST_TEST(s.size() == 2);
s.emplace("test");
BOOST_TEST(s.size() == 3);
}
BOOST_AUTO_TEST_CASE(can_be_placed_in_map)
{
std::map<value, const char*> m;
m[value(200)] = "msg0";
m[value("key")] = "msg1";
BOOST_TEST(m.size() == 2);
BOOST_TEST(m.at(value("key")) == "msg1");
m[value("key")] = "msg2";
BOOST_TEST(m.size() == 2);
BOOST_TEST(m.at(value("key")) == "msg2");
}
BOOST_AUTO_TEST_SUITE_END() // test_value