osrm-backend/third_party/vtzero/test/t/test_property_value.cpp

408 lines
12 KiB
C++

#include <test.hpp>
#include <vtzero/encoded_property_value.hpp>
#include <vtzero/property.hpp>
#include <vtzero/property_value.hpp>
#include <vtzero/types.hpp>
#ifdef VTZERO_TEST_WITH_VARIANT
# include <boost/variant.hpp>
using variant_type = boost::variant<std::string, float, double, int64_t, uint64_t, bool>;
struct variant_mapping : vtzero::property_value_mapping {
using float_type = int64_t;
using double_type = int64_t;
};
#endif
#include <string>
struct visitor_test_void {
int x = 0;
template <typename T>
void operator()(T /*value*/) {
x = 1;
}
void operator()(vtzero::data_view /*value*/) {
x = 2;
}
};
struct visitor_test_int {
template <typename T>
int operator()(T /*value*/) {
return 1;
}
int operator()(vtzero::data_view /*value*/) {
return 2;
}
};
struct visitor_test_to_string {
template <typename T>
std::string operator()(T value) {
return std::to_string(value);
}
std::string operator()(vtzero::data_view value) {
return std::string{value.data(), value.size()};
}
};
struct string_conv {
std::string s;
template <typename T>
explicit string_conv(T value) :
s(std::to_string(value)) {
}
explicit operator std::string() const {
return s;
}
};
struct string_mapping : vtzero::property_value_mapping {
using string_type = std::string;
using float_type = string_conv;
using double_type = string_conv;
using int_type = string_conv;
using uint_type = string_conv;
using bool_type = string_conv;
};
TEST_CASE("default constructed property_value") {
vtzero::property_value pv;
REQUIRE_FALSE(pv.valid());
REQUIRE(pv.data().data() == nullptr);
REQUIRE(pv == vtzero::property_value{});
REQUIRE_FALSE(pv != vtzero::property_value{});
}
TEST_CASE("empty property_value") {
char x = 0;
vtzero::data_view dv{&x, 0};
vtzero::property_value pv{dv};
REQUIRE(pv.valid());
REQUIRE_THROWS_AS(pv.type(), vtzero::format_exception);
}
TEST_CASE("string value") {
vtzero::encoded_property_value epv{"foo"};
vtzero::property_value pv{epv.data()};
REQUIRE(pv.string_value() == "foo");
visitor_test_void vt;
vtzero::apply_visitor(vt, pv);
REQUIRE(vt.x == 2);
const auto result = vtzero::apply_visitor(visitor_test_int{}, pv);
REQUIRE(result == 2);
const auto str = vtzero::apply_visitor(visitor_test_to_string{}, pv);
REQUIRE(str == "foo");
const std::string cs = vtzero::convert_property_value<std::string, string_mapping>(pv);
REQUIRE(cs == "foo");
#ifdef VTZERO_TEST_WITH_VARIANT
const auto vari = vtzero::convert_property_value<variant_type>(pv);
REQUIRE(boost::get<std::string>(vari) == "foo");
const auto conv = vtzero::convert_property_value<variant_type, variant_mapping>(pv);
REQUIRE(boost::get<std::string>(conv) == "foo");
#endif
}
TEST_CASE("float value") {
vtzero::encoded_property_value epv{1.2F};
vtzero::property_value pv{epv.data()};
REQUIRE(pv.float_value() == Approx(1.2));
visitor_test_void vt;
vtzero::apply_visitor(vt, pv);
REQUIRE(vt.x == 1);
const auto result = vtzero::apply_visitor(visitor_test_int{}, pv);
REQUIRE(result == 1);
const std::string cs = vtzero::convert_property_value<std::string, string_mapping>(pv);
REQUIRE(cs == "1.200000");
#ifdef VTZERO_TEST_WITH_VARIANT
const auto vari = vtzero::convert_property_value<variant_type>(pv);
REQUIRE(boost::get<float>(vari) == Approx(1.2));
const auto conv = vtzero::convert_property_value<variant_type, variant_mapping>(pv);
REQUIRE(boost::get<int64_t>(conv) == 1);
#endif
}
TEST_CASE("double value") {
vtzero::encoded_property_value epv{3.4};
vtzero::property_value pv{epv.data()};
REQUIRE(pv.double_value() == Approx(3.4));
const auto result = vtzero::apply_visitor(visitor_test_int{}, pv);
REQUIRE(result == 1);
const std::string cs = vtzero::convert_property_value<std::string, string_mapping>(pv);
REQUIRE(cs == "3.400000");
}
TEST_CASE("int value") {
vtzero::encoded_property_value epv{vtzero::int_value_type{42}};
vtzero::property_value pv{epv.data()};
REQUIRE(pv.int_value() == 42);
const auto str = vtzero::apply_visitor(visitor_test_to_string{}, pv);
REQUIRE(str == "42");
const std::string cs = vtzero::convert_property_value<std::string, string_mapping>(pv);
REQUIRE(cs == "42");
}
TEST_CASE("uint value") {
vtzero::encoded_property_value epv{vtzero::uint_value_type{99}};
vtzero::property_value pv{epv.data()};
REQUIRE(pv.uint_value() == 99);
const auto str = vtzero::apply_visitor(visitor_test_to_string{}, pv);
REQUIRE(str == "99");
const std::string cs = vtzero::convert_property_value<std::string, string_mapping>(pv);
REQUIRE(cs == "99");
}
TEST_CASE("sint value") {
vtzero::encoded_property_value epv{vtzero::sint_value_type{42}};
vtzero::property_value pv{epv.data()};
REQUIRE(pv.sint_value() == 42);
const auto str = vtzero::apply_visitor(visitor_test_to_string{}, pv);
REQUIRE(str == "42");
const std::string cs = vtzero::convert_property_value<std::string, string_mapping>(pv);
REQUIRE(cs == "42");
}
TEST_CASE("bool value") {
vtzero::encoded_property_value epv{true};
vtzero::property_value pv{epv.data()};
REQUIRE(pv.bool_value());
const auto str = vtzero::apply_visitor(visitor_test_to_string{}, pv);
REQUIRE(str == "1");
const std::string cs = vtzero::convert_property_value<std::string, string_mapping>(pv);
REQUIRE(cs == "1");
}
TEST_CASE("property and property_value equality comparisons") {
vtzero::encoded_property_value t{true};
vtzero::encoded_property_value f{false};
vtzero::encoded_property_value v1{vtzero::int_value_type{1}};
vtzero::encoded_property_value vs{"foo"};
REQUIRE(t == t);
REQUIRE_FALSE(t != t);
REQUIRE_FALSE(t == f);
REQUIRE_FALSE(t == v1);
REQUIRE_FALSE(t == vs);
using pv = vtzero::property_value;
REQUIRE(pv{t.data()} == pv{t.data()});
REQUIRE_FALSE(pv{t.data()} != pv{t.data()});
REQUIRE_FALSE(pv{t.data()} == pv{f.data()});
REQUIRE_FALSE(pv{t.data()} == pv{v1.data()});
REQUIRE_FALSE(pv{t.data()} == pv{vs.data()});
}
TEST_CASE("property and property_value ordering") {
using pv = vtzero::property_value;
vtzero::encoded_property_value t{true};
vtzero::encoded_property_value f{false};
REQUIRE_FALSE(t < f);
REQUIRE_FALSE(t <= f);
REQUIRE(t > f);
REQUIRE(t >= f);
REQUIRE_FALSE(pv{t.data()} < pv{f.data()});
REQUIRE_FALSE(pv{t.data()} <= pv{f.data()});
REQUIRE(pv{t.data()} > pv{f.data()});
REQUIRE(pv{t.data()} >= pv{f.data()});
vtzero::encoded_property_value v1{vtzero::int_value_type{22}};
vtzero::encoded_property_value v2{vtzero::int_value_type{17}};
REQUIRE_FALSE(v1 < v2);
REQUIRE_FALSE(v1 <= v2);
REQUIRE(v1 > v2);
REQUIRE(v1 >= v2);
REQUIRE_FALSE(pv{v1.data()} < pv{v2.data()});
REQUIRE_FALSE(pv{v1.data()} <= pv{v2.data()});
REQUIRE(pv{v1.data()} > pv{v2.data()});
REQUIRE(pv{v1.data()} >= pv{v2.data()});
vtzero::encoded_property_value vsf{"foo"};
vtzero::encoded_property_value vsb{"bar"};
vtzero::encoded_property_value vsx{"foobar"};
REQUIRE_FALSE(vsf < vsb);
REQUIRE_FALSE(vsf <= vsb);
REQUIRE(vsf > vsb);
REQUIRE(vsf >= vsb);
REQUIRE_FALSE(pv{vsf.data()} < pv{vsb.data()});
REQUIRE_FALSE(pv{vsf.data()} <= pv{vsb.data()});
REQUIRE(pv{vsf.data()} > pv{vsb.data()});
REQUIRE(pv{vsf.data()} >= pv{vsb.data()});
REQUIRE(vsf < vsx);
REQUIRE(vsf <= vsx);
REQUIRE_FALSE(vsf > vsx);
REQUIRE_FALSE(vsf >= vsx);
REQUIRE(pv{vsf.data()} < pv{vsx.data()});
REQUIRE(pv{vsf.data()} <= pv{vsx.data()});
REQUIRE_FALSE(pv{vsf.data()} > pv{vsx.data()});
REQUIRE_FALSE(pv{vsf.data()} >= pv{vsx.data()});
}
TEST_CASE("default constructed property") {
vtzero::property p;
REQUIRE_FALSE(p.valid());
REQUIRE_FALSE(p);
REQUIRE(p.key().data() == nullptr);
REQUIRE(p.value().data().data() == nullptr);
}
TEST_CASE("valid property") {
vtzero::data_view k{"key"};
vtzero::encoded_property_value epv{"value"};
vtzero::property_value pv{epv.data()};
vtzero::property p{k, pv};
REQUIRE(p.key() == "key");
REQUIRE(p.value().string_value() == "value");
}
TEST_CASE("create encoded property values from different string types") {
const std::string v{"value"};
vtzero::encoded_property_value epv1{vtzero::string_value_type{"value"}};
vtzero::encoded_property_value epv2{"value"};
vtzero::encoded_property_value epv3{v};
vtzero::encoded_property_value epv4{vtzero::data_view{v}};
vtzero::encoded_property_value epv5{"valuexxxxxxxxx", 5};
REQUIRE(epv1 == epv2);
REQUIRE(epv1 == epv3);
REQUIRE(epv1 == epv4);
REQUIRE(epv1 == epv5);
}
TEST_CASE("create encoded property values from different floating point types") {
vtzero::encoded_property_value f1{vtzero::float_value_type{3.2F}};
vtzero::encoded_property_value f2{3.2F};
vtzero::encoded_property_value d1{vtzero::double_value_type{3.2}};
vtzero::encoded_property_value d2{3.2};
REQUIRE(f1 == f2);
REQUIRE(d1 == d2);
vtzero::property_value pvf{f1.data()};
vtzero::property_value pvd{d1.data()};
REQUIRE(pvf.float_value() == Approx(pvd.double_value()));
}
TEST_CASE("create encoded property values from different integer types") {
vtzero::encoded_property_value i1{vtzero::int_value_type{7}};
vtzero::encoded_property_value i2{int64_t(7)};
vtzero::encoded_property_value i3{int32_t(7)};
vtzero::encoded_property_value i4{int16_t(7)};
vtzero::encoded_property_value u1{vtzero::uint_value_type{7}};
vtzero::encoded_property_value u2{uint64_t(7)};
vtzero::encoded_property_value u3{uint32_t(7)};
vtzero::encoded_property_value u4{uint16_t(7)};
vtzero::encoded_property_value s1{vtzero::sint_value_type{7}};
REQUIRE(i1 == i2);
REQUIRE(i1 == i3);
REQUIRE(i1 == i4);
REQUIRE(u1 == u2);
REQUIRE(u1 == u3);
REQUIRE(u1 == u4);
REQUIRE_FALSE(i1 == u1);
REQUIRE_FALSE(i1 == s1);
REQUIRE_FALSE(u1 == s1);
REQUIRE(i1.hash() == i2.hash());
REQUIRE(u1.hash() == u2.hash());
vtzero::property_value pvi{i1.data()};
vtzero::property_value pvu{u1.data()};
vtzero::property_value pvs{s1.data()};
REQUIRE(pvi.int_value() == static_cast<int64_t>(pvu.uint_value()));
REQUIRE(pvi.int_value() == pvs.sint_value());
}
TEST_CASE("create encoded property values from different bool types") {
vtzero::encoded_property_value b1{vtzero::bool_value_type{true}};
vtzero::encoded_property_value b2{true};
REQUIRE(b1 == b2);
REQUIRE(b1.hash() == b2.hash());
}
TEST_CASE("property equality comparison operator") {
std::string k = "key";
vtzero::encoded_property_value epv1{"value"};
vtzero::encoded_property_value epv2{"another value"};
vtzero::property_value pv1{epv1.data()};
vtzero::property_value pv2{epv2.data()};
vtzero::property p1{k, pv1};
vtzero::property p2{k, pv1};
vtzero::property p3{k, pv2};
REQUIRE(p1 == p2);
REQUIRE_FALSE(p1 == p3);
}
TEST_CASE("property inequality comparison operator") {
std::string k1 = "key";
std::string k2 = "another_key";
vtzero::encoded_property_value epv1{"value"};
vtzero::encoded_property_value epv2{"another value"};
vtzero::property_value pv1{epv1.data()};
vtzero::property_value pv2{epv2.data()};
vtzero::property p1{k1, pv1};
vtzero::property p2{k1, pv1};
vtzero::property p3{k1, pv2};
vtzero::property p4{k2, pv2};
REQUIRE_FALSE(p1 != p2);
REQUIRE(p1 != p3);
REQUIRE(p3 != p4);
}