diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 3ca04aa..8fae99e 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -2,11 +2,13 @@ set(TOML11_TEST_NAMES test_comments test_datetime test_find + test_try_find test_find_or test_format_integer test_format_floating test_format_table test_get + test_try_get test_get_or test_location test_literal diff --git a/tests/test_try_find.cpp b/tests/test_try_find.cpp new file mode 100644 index 0000000..755e2fc --- /dev/null +++ b/tests/test_try_find.cpp @@ -0,0 +1,829 @@ +#define DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN +#include "doctest.h" + +#include "utility.hpp" + +#include +#include + +#include +#include +#include +#include +#include +#include + +#if defined(TOML11_HAS_STRING_VIEW) +#include +#endif + +namespace toml +{ +namespace detail +{ +std::tm localtime_s(const std::time_t* src); +std::tm gmtime_s(const std::time_t* src); +} // detail +} // toml + +TEST_CASE("testing toml::try_find with toml type") +{ + using value_type = toml::value; + using boolean_type = typename value_type::boolean_type ; + using integer_type = typename value_type::integer_type ; + using floating_type = typename value_type::floating_type ; + using string_type = typename value_type::string_type ; + using local_time_type = typename value_type::local_time_type ; + using local_date_type = typename value_type::local_date_type ; + using local_datetime_type = typename value_type::local_datetime_type ; + using offset_datetime_type = typename value_type::offset_datetime_type; + using array_type = typename value_type::array_type ; + using table_type = typename value_type::table_type ; + + { + value_type v(toml::table{{"a", true}}); + CHECK_EQ(true, toml::try_find(v, "a").unwrap()); + + toml::try_find(v, "a").unwrap() = false; + CHECK_EQ(false, toml::try_find(v, "a").unwrap()); + + boolean_type x = toml::try_find(std::move(v), "a").unwrap(); + CHECK_EQ(false, x); + } + { + value_type v(toml::table{{"a", 42}}); + CHECK_EQ(integer_type(42), toml::try_find(v, "a").unwrap()); + + toml::try_find(v, "a").unwrap() = 54; + CHECK_EQ(integer_type(54), toml::try_find(v, "a").unwrap()); + + integer_type x = toml::try_find(std::move(v), "a").unwrap(); + CHECK_EQ(integer_type(54), x); + } + { + value_type v(toml::table{{"a", 3.14}}); + CHECK_EQ(floating_type(3.14), toml::try_find(v, "a").unwrap()); + + toml::try_find(v, "a").unwrap() = 2.71; + CHECK_EQ(floating_type(2.71), toml::try_find(v, "a").unwrap()); + + floating_type x = toml::try_find(std::move(v), "a").unwrap(); + CHECK_EQ(floating_type(2.71), x); + } + { + value_type v(toml::table{{"a", "foo"}}); + CHECK_EQ("foo", toml::try_find(v, "a").unwrap()); + + toml::try_find(v, "a").unwrap() += "bar"; + CHECK_EQ("foobar", toml::try_find(v, "a").unwrap()); + + string_type x = toml::try_find(std::move(v), "a").unwrap(); + CHECK_EQ("foobar", x); + } + { + local_date_type d(2018, toml::month_t::Apr, 22); + value_type v(toml::table{{"a", d}}); + CHECK_EQ(d, toml::try_find(v, "a").unwrap()); + + toml::try_find(v, "a").unwrap().year = 2017; + d.year = 2017; + CHECK_EQ(d, toml::try_find(v, "a").unwrap()); + + local_date_type x = toml::try_find(std::move(v), "a").unwrap(); + CHECK_EQ(d, x); + } + { + local_time_type t(12, 30, 45); + value_type v(toml::table{{"a", t}}); + CHECK_EQ(t, toml::try_find(v, "a").unwrap()); + + toml::try_find(v, "a").unwrap().hour = 9; + t.hour = 9; + CHECK_EQ(t, toml::try_find(v, "a").unwrap()); + + local_time_type x = toml::try_find(std::move(v), "a").unwrap(); + CHECK_EQ(t, x); + } + { + local_datetime_type dt(toml::local_date(2018, toml::month_t::Apr, 22), + toml::local_time(12, 30, 45)); + value_type v(toml::table{{"a", dt}}); + CHECK_EQ(dt, toml::try_find(v, "a").unwrap()); + + toml::try_find(v, "a").unwrap().date.year = 2017; + dt.date.year = 2017; + CHECK_EQ(dt, toml::try_find(v, "a").unwrap()); + + toml::local_datetime x = toml::try_find(std::move(v), "a").unwrap(); + CHECK_EQ(dt, x); + } + { + offset_datetime_type dt(toml::local_datetime( + toml::local_date(2018, toml::month_t::Apr, 22), + toml::local_time(12, 30, 45)), toml::time_offset(9, 0)); + value_type v(toml::table{{"a", dt}}); + CHECK_EQ(dt, toml::try_find(v, "a").unwrap()); + + toml::try_find(v, "a").unwrap().date.year = 2017; + dt.date.year = 2017; + CHECK_EQ(dt, toml::try_find(v, "a").unwrap()); + + offset_datetime_type x = toml::try_find(std::move(v), "a").unwrap(); + CHECK_EQ(dt, x); + } + { + array_type vec; + vec.push_back(value_type(42)); + vec.push_back(value_type(54)); + value_type v(toml::table{{"a", vec}}); + CHECK_EQ(vec, toml::try_find(v, "a").unwrap()); + + toml::try_find(v, "a").unwrap().push_back(value_type(123)); + vec.push_back(value_type(123)); + CHECK_EQ(vec, toml::try_find(v, "a").unwrap()); + + array_type x = toml::try_find(std::move(v), "a").unwrap(); + CHECK_EQ(vec, x); + } + { + table_type tab; + tab["key1"] = value_type(42); + tab["key2"] = value_type(3.14); + value_type v(toml::table{{"a", tab}}); + CHECK_EQ(tab, toml::try_find(v, "a").unwrap()); + + toml::try_find(v, "a").unwrap()["key3"] = value_type(123); + tab["key3"] = value_type(123); + CHECK_EQ(tab, toml::try_find(v, "a").unwrap()); + + table_type x = toml::try_find(std::move(v), "a").unwrap(); + CHECK_EQ(tab, x); + } + { + value_type v1(toml::table{{"a", 42}}); + CHECK_EQ(toml::value(42), toml::try_find(v1, "a").unwrap()); + + value_type v2(54); + toml::try_find(v1, "a").unwrap() = v2; + CHECK_EQ(v2, toml::try_find(v1, "a").unwrap()); + + value_type x = toml::try_find(std::move(v1), "a").unwrap(); + CHECK_EQ(v2, x); + } +} + +TEST_CASE("testing try_find fails") +{ + using value_type = toml::value; + using boolean_type = typename value_type::boolean_type ; + using integer_type = typename value_type::integer_type ; + + // ----------------------------------------------------------------------- + // const-reference version + { + // value is not a table + const toml::value v(true); + CHECK_UNARY(toml::try_find(v, "key").is_err()); + } + { + // the value corresponding to the key is not the expected type + const toml::value v = toml::table{{"key", 42}}; + CHECK_UNARY(toml::try_find(v, "key").is_err()); + } + { + // the value corresponding to the key is not found + const toml::value v = toml::table{{"key", 42}}; + CHECK_UNARY(toml::try_find(v, "different_key").is_err()); + } + { + // the positive control. + const toml::value v = toml::table{{"key", 42}}; + CHECK_UNARY(toml::try_find(v, "key").is_ok()); + } + + // ----------------------------------------------------------------------- + // reference version + { + // value is not a table + toml::value v(true); + CHECK_UNARY(toml::try_find(v, "key").is_err()); + } + { + // the value corresponding to the key is not the expected type + toml::value v = toml::table{{"key", 42}}; + CHECK_UNARY(toml::try_find(v, "key").is_err()); + } + { + // the value corresponding to the key is not found + toml::value v = toml::table{{"key", 42}}; + CHECK_UNARY(toml::try_find(v, "different_key").is_err()); + } + { + // the positive control. + toml::value v = toml::table{{"key", 42}}; + CHECK_UNARY(toml::try_find(v, "key").is_ok()); + } + + // ----------------------------------------------------------------------- + // move version + + { + // value is not a table + toml::value v(true); + CHECK_UNARY(toml::try_find(std::move(v), "key").is_err()); + } + { + // the value corresponding to the key is not the expected type + toml::value v = toml::table{{"key", 42}}; + CHECK_UNARY(toml::try_find(std::move(v), "key").is_err()); + } + { + // the value corresponding to the key is not found + toml::value v = toml::table{{"key", 42}}; + CHECK_UNARY(toml::try_find(std::move(v), "different_key").is_err()); + } + { + // the positive control. + toml::value v = toml::table{{"key", 42}}; + CHECK_UNARY(toml::try_find(std::move(v), "key").is_ok()); + } +} + +TEST_CASE("testing toml::try_find(v, idx) throws") +{ + using value_type = toml::value; + using boolean_type = typename value_type::boolean_type ; + using integer_type = typename value_type::integer_type ; + + // ----------------------------------------------------------------------- + // const-reference version + { + // value is not an array + const toml::value v(true); + CHECK_UNARY(toml::try_find(v, 0).is_err()); + } + { + // the value corresponding to the key is not the expected type + const toml::value v = toml::array{1, 2, 3, 4, 5}; + CHECK_UNARY(toml::try_find(v, 0).is_err()); + } + { + // the value corresponding to the key is not found + const toml::value v = toml::array{1, 2, 3, 4, 5}; + CHECK_UNARY(toml::try_find(v, 6).is_err()); + } + { + // the positive control. + const toml::value v = toml::array{1, 2, 3, 4, 5}; + CHECK_UNARY(toml::try_find(v, 2).is_ok()); + } + + // ----------------------------------------------------------------------- + // non-const reference version + { + // value is not an array + toml::value v(true); + CHECK_UNARY(toml::try_find(v, 0).is_err()); + } + { + // the value corresponding to the key is not the expected type + toml::value v = toml::array{1, 2, 3, 4, 5}; + CHECK_UNARY(toml::try_find(v, 0).is_err()); + } + { + // the value corresponding to the key is not found + toml::value v = toml::array{1, 2, 3, 4, 5}; + CHECK_UNARY(toml::try_find(v, 6).is_err()); + } + { + // the positive control. + toml::value v = toml::array{1, 2, 3, 4, 5}; + CHECK_UNARY(toml::try_find(v, 2).is_ok()); + } + + // ----------------------------------------------------------------------- + // move version + { + // value is not an array + toml::value v(true); + CHECK_UNARY(toml::try_find(std::move(v), 0).is_err()); + } + { + // the value corresponding to the key is not the expected type + toml::value v = toml::array{1, 2, 3, 4, 5}; + CHECK_UNARY(toml::try_find(std::move(v), 0).is_err()); + } + { + // the value corresponding to the key is not found + toml::value v = toml::array{1, 2, 3, 4, 5}; + CHECK_UNARY(toml::try_find(std::move(v), 6).is_err()); + } + { + // the positive control. + toml::value v = toml::array{1, 2, 3, 4, 5}; + CHECK_UNARY(toml::try_find(std::move(v), 2).is_ok()); + } +} + +TEST_CASE("testing toml::try_find with recursive table/array") +{ + using value_type = toml::value; + using integer_type = typename value_type::integer_type ; + + // recursively search tables + { + toml::value v = toml::table{ + {"a", toml::table{ + {"b", toml::table{ + {"c", toml::table{ + {"d", 42} + }} + }} + }} + }; + CHECK_EQ(42, toml::try_find(v, "a", "b", "c", "d").unwrap()); + + // reference that can be used to modify the content + auto num = toml::try_find(v, "a", "b", "c", "d"); + CHECK_UNARY(num.is_ok()); + num.unwrap() = 54; + CHECK_EQ(54, toml::try_find(v, "a", "b", "c", "d").unwrap()); + + const std::string a("a"), b("b"), c("c"), d("d"); + auto num2 = toml::try_find(v, a, b, c, d); + CHECK_UNARY(num2.is_ok()); + num2.unwrap() = 42; + CHECK_EQ(42, toml::try_find(v, a, b, c, d).unwrap()); + + auto num3 = toml::try_find(v, a, "b", c, "d"); + CHECK_EQ(42, num3.unwrap()); + + auto num4 = toml::try_find(std::move(v), a, b, c, d); + CHECK_EQ(42, num4.unwrap()); + } + // recursively search arrays + { + toml::value v = toml::array{ + toml::array{"array", "of", "string"}, + toml::array{toml::array{1, 2, 3}, toml::array{3.14, 2.71}} + }; + CHECK_EQ("array" , toml::try_find(v, 0, 0).unwrap()); + CHECK_EQ("of" , toml::try_find(v, 0, 1).unwrap()); + CHECK_EQ("string", toml::try_find(v, 0, 2).unwrap()); + + CHECK_EQ(1, toml::try_find(v, 1, 0, 0).unwrap()); + CHECK_EQ(2, toml::try_find(v, 1, 0, 1).unwrap()); + CHECK_EQ(3, toml::try_find(v, 1, 0, 2).unwrap()); + + CHECK_EQ(3.14, toml::try_find(v, 1, 1, 0).unwrap()); + CHECK_EQ(2.71, toml::try_find(v, 1, 1, 1).unwrap()); + + // reference that can be used to modify the content + auto num = toml::try_find(v, 1, 0, 2); + num.unwrap() = 42; + CHECK_EQ( 1, toml::try_find(v, 1, 0, 0).unwrap()); + CHECK_EQ( 2, toml::try_find(v, 1, 0, 1).unwrap()); + CHECK_EQ(42, toml::try_find(v, 1, 0, 2).unwrap()); + + // move value + auto num2 = toml::try_find(std::move(v), 1, 0, 2); + CHECK_EQ(42, num2.unwrap()); + } + // recursively search mixtures + { + toml::value v = toml::table{{"array", toml::array{ + toml::array{1, 2, 3}, + toml::array{ + toml::table{{"foo", "bar"}, {"baz", "qux"}}, + toml::table{{"pi", 3.14}, {"e", 2.71}} + }} + }}; + + CHECK_EQ(1, toml::try_find(v, "array", 0, 0).unwrap()); + CHECK_EQ(2, toml::try_find(v, "array", 0, 1).unwrap()); + CHECK_EQ(3, toml::try_find(v, "array", 0, 2).unwrap()); + + CHECK_EQ("bar", toml::try_find(v, "array", 1, 0, "foo").unwrap()); + CHECK_EQ("qux", toml::try_find(v, "array", 1, 0, "baz").unwrap()); + + CHECK_EQ(3.14, toml::try_find(v, "array", 1, 1, "pi").unwrap()); + CHECK_EQ(2.71, toml::try_find(v, "array", 1, 1, "e" ).unwrap()); + + const std::string ar("array"); + const auto ar_c = "array"; + + const std::string pi("pi"); + const auto pi_c = "pi"; + + CHECK_EQ(3.14, toml::try_find(v, ar, 1, 1, "pi").unwrap()); + CHECK_EQ(3.14, toml::try_find(v, ar, 1, 1, pi) .unwrap()); + CHECK_EQ(3.14, toml::try_find(v, ar, 1, 1, pi_c).unwrap()); + + CHECK_EQ(3.14, toml::try_find(v, ar_c, 1, 1, "pi").unwrap()); + CHECK_EQ(3.14, toml::try_find(v, ar_c, 1, 1, pi) .unwrap()); + CHECK_EQ(3.14, toml::try_find(v, ar_c, 1, 1, pi_c).unwrap()); + + CHECK_EQ(3.14, toml::try_find(v, "array", 1, 1, pi) .unwrap()); + CHECK_EQ(3.14, toml::try_find(v, "array", 1, 1, pi_c).unwrap()); + } +} + +TEST_CASE("testing toml::try_find integer conversion") +{ + using value_type = toml::value; + + { + value_type v = toml::table{{"key", 42}}; + CHECK_EQ(int(42) , toml::try_find(v, "key").unwrap()); + CHECK_EQ(short(42) , toml::try_find(v, "key").unwrap()); + CHECK_EQ(char(42) , toml::try_find(v, "key").unwrap()); + CHECK_EQ(unsigned(42) , toml::try_find(v, "key").unwrap()); + CHECK_EQ(long(42) , toml::try_find(v, "key").unwrap()); + CHECK_EQ(std::int64_t(42) , toml::try_find(v, "key").unwrap()); + CHECK_EQ(std::uint64_t(42), toml::try_find(v, "key").unwrap()); + CHECK_EQ(std::int16_t(42) , toml::try_find(v, "key").unwrap()); + CHECK_EQ(std::uint16_t(42), toml::try_find(v, "key").unwrap()); + CHECK_EQ(std::uint16_t(42), toml::try_find(std::move(v), "key").unwrap()); + } +} + +TEST_CASE("testing toml::try_find floating conversion") +{ + using value_type = toml::value; + + { + value_type v = toml::table{{"key", 3.14}}; + const double ref(3.14); + CHECK_EQ(static_cast(ref), toml::try_find(v, "key").unwrap()); + CHECK_EQ( ref , toml::try_find(v, "key").unwrap()); + CHECK_EQ(static_cast(ref), toml::try_find(v, "key").unwrap()); + CHECK_EQ(static_cast(ref), toml::try_find(std::move(v), "key").unwrap()); + } +} + +TEST_CASE("testing toml::try_find string conversion") +{ + using value_type = toml::value; + + { + value_type v = toml::table{{"key", "foo"}}; + CHECK_EQ("foo", toml::try_find(v, "key").unwrap()); + toml::try_find(v, "key").unwrap() += "bar"; + CHECK_EQ("foobar", toml::try_find(v, "key").unwrap()); + } + +#if TOML11_CPLUSPLUS_STANDARD_VERSION >= 201703L + { + value_type v = toml::table{{"key", "foo"}}; + CHECK_EQ("foo", toml::try_find(v, "key").unwrap()); + } +#endif +} + +TEST_CASE("testing toml::try_find array conversion") +{ + using value_type = toml::value; + + value_type v = toml::table{{"key", toml::array{42, 54, 69, 72}}}; + + const std::vector vec = toml::try_find>(v, "key").unwrap(); + const std::list lst = toml::try_find>(v, "key").unwrap(); + const std::deque deq = toml::try_find>(v, "key").unwrap(); + + CHECK_EQ(42, vec.at(0)); + CHECK_EQ(54, vec.at(1)); + CHECK_EQ(69, vec.at(2)); + CHECK_EQ(72, vec.at(3)); + + std::list::const_iterator iter = lst.begin(); + CHECK_EQ(static_cast(42), *(iter++)); + CHECK_EQ(static_cast(54), *(iter++)); + CHECK_EQ(static_cast(69), *(iter++)); + CHECK_EQ(static_cast(72), *(iter++)); + + CHECK_EQ(static_cast(42), deq.at(0)); + CHECK_EQ(static_cast(54), deq.at(1)); + CHECK_EQ(static_cast(69), deq.at(2)); + CHECK_EQ(static_cast(72), deq.at(3)); + + std::array ary = toml::try_find>(v, "key").unwrap(); + CHECK_EQ(42, ary.at(0)); + CHECK_EQ(54, ary.at(1)); + CHECK_EQ(69, ary.at(2)); + CHECK_EQ(72, ary.at(3)); + + std::tuple tpl = + toml::try_find>(v, "key").unwrap(); + CHECK_EQ( 42 , std::get<0>(tpl)); + CHECK_EQ(static_cast(54), std::get<1>(tpl)); + CHECK_EQ(static_cast(69), std::get<2>(tpl)); + CHECK_EQ(static_cast(72), std::get<3>(tpl)); + + value_type p = toml::table{{"key", toml::array{3.14, 2.71}}}; + std::pair pr = toml::try_find >(p, "key").unwrap(); + CHECK_EQ(3.14, pr.first); + CHECK_EQ(2.71, pr.second); +} + +TEST_CASE("testing toml::try_find array move conversion") +{ + using value_type = toml::value; + + value_type v1 = toml::table{{"key", toml::array{42, 54, 69, 72}}}; + value_type v2 = toml::table{{"key", toml::array{42, 54, 69, 72}}}; + value_type v3 = toml::table{{"key", toml::array{42, 54, 69, 72}}}; + value_type v4 = toml::table{{"key", toml::array{42, 54, 69, 72}}}; + value_type v5 = toml::table{{"key", toml::array{42, 54, 69, 72}}}; + + const std::vector vec = toml::try_find>(std::move(v1), "key").unwrap(); + const std::list lst = toml::try_find>(std::move(v2), "key").unwrap(); + const std::deque deq = toml::try_find>(std::move(v3), "key").unwrap(); + + CHECK_EQ(42, vec.at(0)); + CHECK_EQ(54, vec.at(1)); + CHECK_EQ(69, vec.at(2)); + CHECK_EQ(72, vec.at(3)); + + std::list::const_iterator iter = lst.begin(); + CHECK_EQ(static_cast(42), *(iter++)); + CHECK_EQ(static_cast(54), *(iter++)); + CHECK_EQ(static_cast(69), *(iter++)); + CHECK_EQ(static_cast(72), *(iter++)); + + CHECK_EQ(static_cast(42), deq.at(0)); + CHECK_EQ(static_cast(54), deq.at(1)); + CHECK_EQ(static_cast(69), deq.at(2)); + CHECK_EQ(static_cast(72), deq.at(3)); + + std::array ary = toml::try_find>(std::move(v4), "key").unwrap(); + CHECK_EQ(42, ary.at(0)); + CHECK_EQ(54, ary.at(1)); + CHECK_EQ(69, ary.at(2)); + CHECK_EQ(72, ary.at(3)); + + std::tuple tpl = + toml::try_find>(std::move(v5), "key").unwrap(); + CHECK_EQ( 42 , std::get<0>(tpl)); + CHECK_EQ(static_cast(54), std::get<1>(tpl)); + CHECK_EQ(static_cast(69), std::get<2>(tpl)); + CHECK_EQ(static_cast(72), std::get<3>(tpl)); + + value_type p = toml::table{{"key", toml::array{3.14, 2.71}}}; + std::pair pr = toml::try_find >(std::move(p), "key").unwrap(); + CHECK_EQ(3.14, pr.first); + CHECK_EQ(2.71, pr.second); +} + +TEST_CASE("testing toml::try_find array of array conversion") +{ + using value_type = toml::value; + + value_type v1 = toml::array{42, 54, 69, 72}; + value_type v2 = toml::array{"foo", "bar", "baz"}; + value_type v = toml::table{{"key", toml::array{v1, v2}}}; + + std::pair, std::vector> p = + toml::try_find, std::vector>>(v, "key").unwrap(); + + CHECK_EQ(p.first.at(0), 42); + CHECK_EQ(p.first.at(1), 54); + CHECK_EQ(p.first.at(2), 69); + CHECK_EQ(p.first.at(3), 72); + + CHECK_EQ(p.second.at(0), "foo"); + CHECK_EQ(p.second.at(1), "bar"); + CHECK_EQ(p.second.at(2), "baz"); + + std::tuple, std::vector> t = + toml::try_find, std::vector>>(v, "key").unwrap(); + + CHECK_EQ(std::get<0>(t).at(0), 42); + CHECK_EQ(std::get<0>(t).at(1), 54); + CHECK_EQ(std::get<0>(t).at(2), 69); + CHECK_EQ(std::get<0>(t).at(3), 72); + + CHECK_EQ(std::get<1>(t).at(0), "foo"); + CHECK_EQ(std::get<1>(t).at(1), "bar"); + CHECK_EQ(std::get<1>(t).at(2), "baz"); +} + +TEST_CASE("testing toml::try_find array of array move conversion") +{ + using value_type = toml::value; + + value_type a1 = toml::array{42, 54, 69, 72}; + value_type a2 = toml::array{"foo", "bar", "baz"}; + value_type v1 = toml::table{{"key", toml::array{a1, a2}}}; + value_type v2 = toml::table{{"key", toml::array{a1, a2}}}; + + std::pair, std::vector> p = + toml::try_find, std::vector>>(std::move(v1), "key").unwrap(); + + CHECK_EQ(p.first.at(0), 42); + CHECK_EQ(p.first.at(1), 54); + CHECK_EQ(p.first.at(2), 69); + CHECK_EQ(p.first.at(3), 72); + + CHECK_EQ(p.second.at(0), "foo"); + CHECK_EQ(p.second.at(1), "bar"); + CHECK_EQ(p.second.at(2), "baz"); + + std::tuple, std::vector> t = + toml::try_find, std::vector>>(std::move(v2), "key").unwrap(); + + CHECK_EQ(std::get<0>(t).at(0), 42); + CHECK_EQ(std::get<0>(t).at(1), 54); + CHECK_EQ(std::get<0>(t).at(2), 69); + CHECK_EQ(std::get<0>(t).at(3), 72); + + CHECK_EQ(std::get<1>(t).at(0), "foo"); + CHECK_EQ(std::get<1>(t).at(1), "bar"); + CHECK_EQ(std::get<1>(t).at(2), "baz"); +} + +TEST_CASE("testing toml::try_find table conversion") +{ + using value_type = toml::value; + { + value_type v1 = toml::table{{"key", toml::table{ + {"key1", 1}, {"key2", 2}, {"key3", 3}, {"key4", 4} + }}}; + const auto v = toml::try_find>(v1, "key").unwrap(); + CHECK_EQ(v.at("key1"), 1); + CHECK_EQ(v.at("key2"), 2); + CHECK_EQ(v.at("key3"), 3); + CHECK_EQ(v.at("key4"), 4); + } + { + value_type v1 = toml::table{{"key", toml::table{ + {"key1", 1}, {"key2", 2}, {"key3", 3}, {"key4", 4} + }}}; + const auto v = toml::try_find>(std::move(v1), "key").unwrap(); + CHECK_EQ(v.at("key1"), 1); + CHECK_EQ(v.at("key2"), 2); + CHECK_EQ(v.at("key3"), 3); + CHECK_EQ(v.at("key4"), 4); + } +} + +TEST_CASE("testing toml::try_find local_date") +{ + using value_type = toml::value; + { + value_type v1 = toml::table{{"key", toml::local_date{2018, toml::month_t::Apr, 1}}}; + const auto date = std::chrono::system_clock::to_time_t( + toml::try_find(v1, "key").unwrap()); + + std::tm t; + t.tm_year = 2018 - 1900; + t.tm_mon = 4 - 1; + t.tm_mday = 1; + t.tm_hour = 0; + t.tm_min = 0; + t.tm_sec = 0; + t.tm_isdst = -1; + const auto c = std::mktime(&t); + CHECK_EQ(c, date); + } + { + value_type v1 = toml::table{{"key", toml::local_date{2018, toml::month_t::Apr, 1}}}; + const auto date = std::chrono::system_clock::to_time_t( + toml::try_find(std::move(v1), "key").unwrap()); + + std::tm t; + t.tm_year = 2018 - 1900; + t.tm_mon = 4 - 1; + t.tm_mday = 1; + t.tm_hour = 0; + t.tm_min = 0; + t.tm_sec = 0; + t.tm_isdst = -1; + const auto c = std::mktime(&t); + CHECK_EQ(c, date); + } +} + +TEST_CASE("testing toml::try_find local_time") +{ + using value_type = toml::value; + { + value_type v1 = toml::table{{"key", toml::local_time{12, 30, 45}}}; + const auto time = toml::try_find(v1, "key").unwrap(); + CHECK_EQ(time, std::chrono::hours(12) + + std::chrono::minutes(30) + std::chrono::seconds(45)); + } + { + value_type v1 = toml::table{{"key", toml::local_time{12, 30, 45}}}; + const auto time = toml::try_find(std::move(v1), "key").unwrap(); + CHECK_EQ(time, std::chrono::hours(12) + + std::chrono::minutes(30) + std::chrono::seconds(45)); + } +} + +TEST_CASE("testing toml::try_find local_datetime") +{ + using value_type = toml::value; + { + value_type v1 = toml::table{{"key", toml::local_datetime( + toml::local_date{2018, toml::month_t::Apr, 1}, + toml::local_time{12, 30, 45})}}; + + const auto date = std::chrono::system_clock::to_time_t( + toml::try_find(v1, "key").unwrap()); + std::tm t; + t.tm_year = 2018 - 1900; + t.tm_mon = 4 - 1; + t.tm_mday = 1; + t.tm_hour = 12; + t.tm_min = 30; + t.tm_sec = 45; + t.tm_isdst = -1; + const auto c = std::mktime(&t); + CHECK_EQ(c, date); + } + { + value_type v1 = toml::table{{"key", toml::local_datetime( + toml::local_date{2018, toml::month_t::Apr, 1}, + toml::local_time{12, 30, 45})}}; + + const auto date = std::chrono::system_clock::to_time_t( + toml::try_find(std::move(v1), "key").unwrap()); + std::tm t; + t.tm_year = 2018 - 1900; + t.tm_mon = 4 - 1; + t.tm_mday = 1; + t.tm_hour = 12; + t.tm_min = 30; + t.tm_sec = 45; + t.tm_isdst = -1; + const auto c = std::mktime(&t); + CHECK_EQ(c, date); + } +} + +TEST_CASE("testing toml::try_find offset_datetime") +{ + using value_type = toml::value; + { + value_type v1 = toml::table{{"key", toml::offset_datetime( + toml::local_date{2018, toml::month_t::Apr, 1}, + toml::local_time{12, 30, 0}, + toml::time_offset{9, 0})}}; + // 2018-04-01T12:30:00+09:00 + //, 2018-04-01T03:30:00Z + + const auto date = toml::try_find(v1, "key").unwrap(); + const auto timet = std::chrono::system_clock::to_time_t(date); + + // get time_t as gmtime (2018-04-01T03:30:00Z) + const auto tm = toml::detail::gmtime_s(std::addressof(timet)); + CHECK_EQ(tm.tm_year + 1900, 2018); + CHECK_EQ(tm.tm_mon + 1, 4); + CHECK_EQ(tm.tm_mday, 1); + CHECK_EQ(tm.tm_hour, 3); + CHECK_EQ(tm.tm_min, 30); + CHECK_EQ(tm.tm_sec, 0); + } + + { + value_type v1 = toml::table{{"key", toml::offset_datetime( + toml::local_date{2018, toml::month_t::Apr, 1}, + toml::local_time{12, 30, 0}, + toml::time_offset{-8, 0})}}; + // 2018-04-01T12:30:00-08:00 + //, 2018-04-01T20:30:00Z + + const auto date = toml::try_find(v1, "key").unwrap(); + const auto timet = std::chrono::system_clock::to_time_t(date); + + // get time_t as gmtime (2018-04-01T03:30:00Z) + const auto tm = toml::detail::gmtime_s(std::addressof(timet)); + CHECK_EQ(tm.tm_year + 1900, 2018); + CHECK_EQ(tm.tm_mon + 1, 4); + CHECK_EQ(tm.tm_mday, 1); + CHECK_EQ(tm.tm_hour, 20); + CHECK_EQ(tm.tm_min, 30); + CHECK_EQ(tm.tm_sec, 0); + } + + { + value_type v1 = toml::table{{"key", toml::offset_datetime( + toml::local_date{2018, toml::month_t::Apr, 1}, + toml::local_time{12, 30, 0}, + toml::time_offset{-8, 0})}}; + // 2018-04-01T12:30:00-08:00 + //, 2018-04-01T20:30:00Z + + const auto date = toml::try_find(std::move(v1), "key").unwrap(); + const auto timet = std::chrono::system_clock::to_time_t(date); + + // get time_t as gmtime (2018-04-01T03:30:00Z) + const auto tm = toml::detail::gmtime_s(std::addressof(timet)); + CHECK_EQ(tm.tm_year + 1900, 2018); + CHECK_EQ(tm.tm_mon + 1, 4); + CHECK_EQ(tm.tm_mday, 1); + CHECK_EQ(tm.tm_hour, 20); + CHECK_EQ(tm.tm_min, 30); + CHECK_EQ(tm.tm_sec, 0); + } +} diff --git a/tests/test_try_get.cpp b/tests/test_try_get.cpp new file mode 100644 index 0000000..fb43df6 --- /dev/null +++ b/tests/test_try_get.cpp @@ -0,0 +1,529 @@ +#define DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN +#include "doctest.h" + +#include "utility.hpp" + +#include +#include + +#include +#include +#include +#include +#include +#include + +#if TOML11_CPLUSPLUS_STANDARD_VERSION >= 201703L +#include +#endif + +namespace toml +{ +namespace detail +{ +std::tm localtime_s(const std::time_t* src); +std::tm gmtime_s(const std::time_t* src); +} // detail +} // toml + +TEST_CASE("testing toml::try_get with toml types") +{ + using value_type = toml::value; + using boolean_type = typename value_type::boolean_type ; + using integer_type = typename value_type::integer_type ; + using floating_type = typename value_type::floating_type ; + using string_type = typename value_type::string_type ; + using local_time_type = typename value_type::local_time_type ; + using local_date_type = typename value_type::local_date_type ; + using local_datetime_type = typename value_type::local_datetime_type ; + using offset_datetime_type = typename value_type::offset_datetime_type; + using array_type = typename value_type::array_type ; + using table_type = typename value_type::table_type ; + + { + value_type v(true); + CHECK_EQ(true, toml::try_get(v).unwrap()); + + toml::try_get(v).unwrap() = false; + CHECK_EQ(false, toml::try_get(v).unwrap()); + + boolean_type x = toml::try_get(std::move(v)).unwrap(); + CHECK_EQ(false, x); + } + { + value_type v(42); + CHECK_EQ(integer_type(42), toml::try_get(v).unwrap()); + + toml::try_get(v).unwrap() = 54; + CHECK_EQ(integer_type(54), toml::try_get(v).unwrap()); + + integer_type x = toml::try_get(std::move(v)).unwrap(); + CHECK_EQ(integer_type(54), x); + } + { + value_type v(3.14); + CHECK_EQ(floating_type(3.14), toml::try_get(v).unwrap()); + + toml::try_get(v).unwrap() = 2.71; + CHECK_EQ(floating_type(2.71), toml::try_get(v).unwrap()); + + floating_type x = toml::try_get(std::move(v)).unwrap(); + CHECK_EQ(floating_type(2.71), x); + } + { + value_type v("foo"); + CHECK_EQ("foo", toml::try_get(v).unwrap()); + + toml::try_get(v).unwrap() += "bar"; + CHECK_EQ("foobar", toml::try_get(v).unwrap()); + + string_type x = toml::try_get(std::move(v)).unwrap(); + CHECK_EQ("foobar", x); + } + { + local_date_type d(2018, toml::month_t::Apr, 22); + value_type v(d); + CHECK_EQ(d, toml::try_get(v).unwrap()); + + toml::try_get(v).unwrap().year = 2017; + d.year = 2017; + CHECK_EQ(d, toml::try_get(v).unwrap()); + + local_date_type x = toml::try_get(std::move(v)).unwrap(); + CHECK_EQ(d, x); + } + { + local_time_type t(12, 30, 45); + value_type v(t); + CHECK_EQ(t, toml::try_get(v).unwrap()); + + toml::try_get(v).unwrap().hour = 9; + t.hour = 9; + CHECK_EQ(t, toml::try_get(v).unwrap()); + + local_time_type x = toml::try_get(std::move(v)).unwrap(); + CHECK_EQ(t, x); + } + { + local_datetime_type dt(toml::local_date(2018, toml::month_t::Apr, 22), + toml::local_time(12, 30, 45)); + value_type v(dt); + CHECK_EQ(dt, toml::try_get(v).unwrap()); + + toml::try_get(v).unwrap().date.year = 2017; + dt.date.year = 2017; + CHECK_EQ(dt, toml::try_get(v).unwrap()); + + toml::local_datetime x = toml::try_get(std::move(v)).unwrap(); + CHECK_EQ(dt, x); + } + { + offset_datetime_type dt(toml::local_datetime( + toml::local_date(2018, toml::month_t::Apr, 22), + toml::local_time(12, 30, 45)), toml::time_offset(9, 0)); + value_type v(dt); + CHECK_EQ(dt, toml::try_get(v).unwrap()); + + toml::try_get(v).unwrap().date.year = 2017; + dt.date.year = 2017; + CHECK_EQ(dt, toml::try_get(v).unwrap()); + + offset_datetime_type x = toml::try_get(std::move(v)).unwrap(); + CHECK_EQ(dt, x); + } + { + array_type vec; + vec.push_back(value_type(42)); + vec.push_back(value_type(54)); + value_type v(vec); + CHECK_EQ(vec, toml::try_get(v).unwrap()); + + toml::try_get(v).unwrap().push_back(value_type(123)); + vec.push_back(value_type(123)); + CHECK_EQ(vec, toml::try_get(v).unwrap()); + + array_type x = toml::try_get(std::move(v)).unwrap(); + CHECK_EQ(vec, x); + } + { + table_type tab; + tab["key1"] = value_type(42); + tab["key2"] = value_type(3.14); + value_type v(tab); + CHECK_EQ(tab, toml::try_get(v).unwrap()); + + toml::try_get(v).unwrap()["key3"] = value_type(123); + tab["key3"] = value_type(123); + CHECK_EQ(tab, toml::try_get(v).unwrap()); + + table_type x = toml::try_get(std::move(v)).unwrap(); + CHECK_EQ(tab, x); + } + { + value_type v1(42); + CHECK_EQ(v1, toml::try_get(v1).unwrap()); + + value_type v2(54); + toml::try_get(v1).unwrap() = v2; + CHECK_EQ(v2, toml::try_get(v1).unwrap()); + + value_type x = toml::try_get(std::move(v1)).unwrap(); + CHECK_EQ(v2, x); + } +} + +TEST_CASE("testing toml::try_get") +{ + using value_type = toml::value; + { + value_type v(42); + + CHECK_EQ(int(42), toml::try_get(v).unwrap()); + CHECK_EQ(short(42), toml::try_get(v).unwrap()); + CHECK_EQ(char(42), toml::try_get(v).unwrap()); + CHECK_EQ(unsigned(42), toml::try_get(v).unwrap()); + CHECK_EQ(long(42), toml::try_get(v).unwrap()); + CHECK_EQ(std::int64_t(42), toml::try_get(v).unwrap()); + CHECK_EQ(std::uint64_t(42), toml::try_get(v).unwrap()); + CHECK_EQ(std::int16_t(42), toml::try_get(v).unwrap()); + CHECK_EQ(std::uint16_t(42), toml::try_get(v).unwrap()); + + CHECK_EQ(int(42), toml::try_get(as_const(v)).unwrap()); + CHECK_EQ(short(42), toml::try_get(as_const(v)).unwrap()); + CHECK_EQ(char(42), toml::try_get(as_const(v)).unwrap()); + CHECK_EQ(unsigned(42), toml::try_get(as_const(v)).unwrap()); + CHECK_EQ(long(42), toml::try_get(as_const(v)).unwrap()); + CHECK_EQ(std::int64_t(42), toml::try_get(as_const(v)).unwrap()); + CHECK_EQ(std::uint64_t(42), toml::try_get(as_const(v)).unwrap()); + CHECK_EQ(std::int16_t(42), toml::try_get(as_const(v)).unwrap()); + CHECK_EQ(std::uint16_t(42), toml::try_get(as_const(v)).unwrap()); + + value_type v1(v); + value_type v2(v); + value_type v3(v); + value_type v4(v); + value_type v5(v); + value_type v6(v); + value_type v7(v); + value_type v8(v); + value_type v9(v); + + CHECK_EQ(int(42), toml::try_get(v1).unwrap()); + CHECK_EQ(short(42), toml::try_get(v2).unwrap()); + CHECK_EQ(char(42), toml::try_get(v3).unwrap()); + CHECK_EQ(unsigned(42), toml::try_get(v4).unwrap()); + CHECK_EQ(long(42), toml::try_get(v5).unwrap()); + CHECK_EQ(std::int64_t(42), toml::try_get(v6).unwrap()); + CHECK_EQ(std::uint64_t(42), toml::try_get(v7).unwrap()); + CHECK_EQ(std::int16_t(42), toml::try_get(v8).unwrap()); + CHECK_EQ(std::uint16_t(42), toml::try_get(v9).unwrap()); + } +} + +TEST_CASE("testing toml::try_get") +{ + using value_type = toml::value; + { + const double ref(3.14); + + value_type v(ref); + CHECK_EQ(static_cast(ref), toml::try_get(v).unwrap()); + CHECK_EQ( ref , toml::try_get(v).unwrap()); + CHECK_EQ(static_cast(ref), toml::try_get(v).unwrap()); + + value_type v1(ref); + value_type v2(ref); + value_type v3(ref); + CHECK_EQ(static_cast(ref), toml::try_get(std::move(v1)).unwrap()); + CHECK_EQ( ref , toml::try_get(std::move(v2)).unwrap()); + CHECK_EQ(static_cast(ref), toml::try_get(std::move(v3)).unwrap()); + } +} + +#if TOML11_CPLUSPLUS_STANDARD_VERSION >= 201703L +TEST_CASE("testing toml::try_get") +{ + using value_type = toml::value; + { + value_type v("foo"); + CHECK_EQ("foo", toml::try_get(v).unwrap()); + } +} +#endif + +TEST_CASE("testing toml::try_get") +{ + using value_type = toml::value; + { + const value_type v(toml::array{42, 54, 69, 72}); + + const std::vector vec = toml::try_get>(v).unwrap(); + const std::list lst = toml::try_get>(v).unwrap(); + const std::deque deq = toml::try_get>(v).unwrap(); + + CHECK_EQ(42, vec.at(0)); + CHECK_EQ(54, vec.at(1)); + CHECK_EQ(69, vec.at(2)); + CHECK_EQ(72, vec.at(3)); + + std::list::const_iterator iter = lst.begin(); + CHECK_EQ(static_cast(42), *(iter++)); + CHECK_EQ(static_cast(54), *(iter++)); + CHECK_EQ(static_cast(69), *(iter++)); + CHECK_EQ(static_cast(72), *(iter++)); + + CHECK_EQ(static_cast(42), deq.at(0)); + CHECK_EQ(static_cast(54), deq.at(1)); + CHECK_EQ(static_cast(69), deq.at(2)); + CHECK_EQ(static_cast(72), deq.at(3)); + + std::array ary = toml::try_get>(v).unwrap(); + CHECK_EQ(42, ary.at(0)); + CHECK_EQ(54, ary.at(1)); + CHECK_EQ(69, ary.at(2)); + CHECK_EQ(72, ary.at(3)); + + std::tuple tpl = + toml::try_get>(v).unwrap(); + CHECK_EQ( 42 , std::get<0>(tpl)); + CHECK_EQ(static_cast(54), std::get<1>(tpl)); + CHECK_EQ(static_cast(69), std::get<2>(tpl)); + CHECK_EQ(static_cast(72), std::get<3>(tpl)); + + const value_type p(toml::array{3.14, 2.71}); + std::pair pr = toml::try_get >(p).unwrap(); + CHECK_EQ(3.14, pr.first); + CHECK_EQ(2.71, pr.second); + } + + { + value_type v(toml::array{42, 54, 69, 72}); + const std::vector vec = toml::try_get>(std::move(v)).unwrap(); + CHECK_EQ(42, vec.at(0)); + CHECK_EQ(54, vec.at(1)); + CHECK_EQ(69, vec.at(2)); + CHECK_EQ(72, vec.at(3)); + } + { + value_type v(toml::array{42, 54, 69, 72}); + const std::deque deq = toml::try_get>(std::move(v)).unwrap(); + CHECK_EQ(42, deq.at(0)); + CHECK_EQ(54, deq.at(1)); + CHECK_EQ(69, deq.at(2)); + CHECK_EQ(72, deq.at(3)); + } + { + value_type v(toml::array{42, 54, 69, 72}); + const std::list lst = toml::try_get>(std::move(v)).unwrap(); + std::list::const_iterator iter = lst.begin(); + CHECK_EQ(42, *(iter++)); + CHECK_EQ(54, *(iter++)); + CHECK_EQ(69, *(iter++)); + CHECK_EQ(72, *(iter++)); + } + { + value_type v(toml::array{42, 54, 69, 72}); + std::array ary = toml::try_get>(std::move(v)).unwrap(); + CHECK_EQ(42, ary.at(0)); + CHECK_EQ(54, ary.at(1)); + CHECK_EQ(69, ary.at(2)); + CHECK_EQ(72, ary.at(3)); + } + { + value_type v(toml::array{42, 54, 69, 72}); + std::tuple tpl = + toml::try_get>(std::move(v)).unwrap(); + CHECK_EQ( 42 , std::get<0>(tpl)); + CHECK_EQ(static_cast(54), std::get<1>(tpl)); + CHECK_EQ(static_cast(69), std::get<2>(tpl)); + CHECK_EQ(static_cast(72), std::get<3>(tpl)); + } +} + +TEST_CASE("testing toml::try_get") +{ + using value_type = toml::value; + { + const value_type v1(toml::array{42, 54, 69, 72}); + const value_type v2(toml::array{"foo", "bar", "baz"}); + const value_type v (toml::array{v1, v2}); + + std::pair, std::vector> p = + toml::try_get, std::vector>>(v).unwrap(); + + CHECK_EQ(p.first.size(), 4u); + CHECK_EQ(p.first.at(0), 42); + CHECK_EQ(p.first.at(1), 54); + CHECK_EQ(p.first.at(2), 69); + CHECK_EQ(p.first.at(3), 72); + + CHECK_EQ(p.second.size(), 3u); + CHECK_EQ(p.second.at(0), "foo"); + CHECK_EQ(p.second.at(1), "bar"); + CHECK_EQ(p.second.at(2), "baz"); + + std::tuple, std::vector> t = + toml::try_get, std::vector>>(v).unwrap(); + + CHECK_EQ(std::get<0>(t).at(0), 42); + CHECK_EQ(std::get<0>(t).at(1), 54); + CHECK_EQ(std::get<0>(t).at(2), 69); + CHECK_EQ(std::get<0>(t).at(3), 72); + + CHECK_EQ(std::get<1>(t).at(0), "foo"); + CHECK_EQ(std::get<1>(t).at(1), "bar"); + CHECK_EQ(std::get<1>(t).at(2), "baz"); + } + { + const value_type v1(toml::array{42, 54, 69, 72}); + const value_type v2(toml::array{"foo", "bar", "baz"}); + value_type v (toml::array{v1, v2}); + + std::pair, std::vector> p = + toml::try_get, std::vector>>(std::move(v)).unwrap(); + + CHECK_EQ(p.first.size(), 4u); + CHECK_EQ(p.first.at(0), 42); + CHECK_EQ(p.first.at(1), 54); + CHECK_EQ(p.first.at(2), 69); + CHECK_EQ(p.first.at(3), 72); + + CHECK_EQ(p.second.size(), 3u); + CHECK_EQ(p.second.at(0), "foo"); + CHECK_EQ(p.second.at(1), "bar"); + CHECK_EQ(p.second.at(2), "baz"); + } +} + +TEST_CASE("testing toml::try_get") +{ + using value_type = toml::value; + { + const value_type v1(toml::table{ + {"key1", 1}, + {"key2", 2}, + {"key3", 3}, + {"key4", 4} + }); + + const auto v = toml::try_get>(v1).unwrap(); + CHECK_EQ(v.at("key1"), 1); + CHECK_EQ(v.at("key2"), 2); + CHECK_EQ(v.at("key3"), 3); + CHECK_EQ(v.at("key4"), 4); + } + { + value_type v1(toml::table{ + {"key1", 1}, + {"key2", 2}, + {"key3", 3}, + {"key4", 4} + }); + const auto v = toml::try_get>(std::move(v1)).unwrap(); + CHECK_EQ(v.at("key1"), 1); + CHECK_EQ(v.at("key2"), 2); + CHECK_EQ(v.at("key3"), 3); + CHECK_EQ(v.at("key4"), 4); + } +} + +TEST_CASE("testing toml::try_get(local_date)") +{ + using value_type = toml::value; + + value_type v1(toml::local_date{2018, toml::month_t::Apr, 1}); + const auto date = std::chrono::system_clock::to_time_t( + toml::try_get(v1).unwrap()); + + std::tm t; + t.tm_year = 2018 - 1900; + t.tm_mon = 4 - 1; + t.tm_mday = 1; + t.tm_hour = 0; + t.tm_min = 0; + t.tm_sec = 0; + t.tm_isdst = -1; + const auto c = std::mktime(&t); + CHECK_EQ(c, date); +} + +TEST_CASE("testing toml::try_get") +{ + using value_type = toml::value; + + value_type v1(toml::local_time{12, 30, 45}); + const auto time = toml::try_get(v1).unwrap(); + const bool result = time == std::chrono::hours(12) + + std::chrono::minutes(30) + + std::chrono::seconds(45); + CHECK_UNARY(result); +} + +TEST_CASE("testing toml::try_get(local_datetime)") +{ + using value_type = toml::value; + + value_type v1(toml::local_datetime( + toml::local_date{2018, toml::month_t::Apr, 1}, + toml::local_time{12, 30, 45})); + + const auto date = std::chrono::system_clock::to_time_t( + toml::try_get(v1).unwrap()); + + std::tm t; + t.tm_year = 2018 - 1900; + t.tm_mon = 4 - 1; + t.tm_mday = 1; + t.tm_hour = 12; + t.tm_min = 30; + t.tm_sec = 45; + t.tm_isdst = -1; + const auto c = std::mktime(&t); + CHECK_EQ(c, date); +} + +TEST_CASE("testing toml::try_get(offset_datetime)") +{ + using value_type = toml::value; + { + value_type v1(toml::offset_datetime( + toml::local_date{2018, toml::month_t::Apr, 1}, + toml::local_time{12, 30, 0}, + toml::time_offset{9, 0})); + // 2018-04-01T12:30:00+09:00 + // == 2018-04-01T03:30:00Z + + const auto date = toml::try_get(v1).unwrap(); + const auto timet = std::chrono::system_clock::to_time_t(date); + + // get time_t as gmtime (2018-04-01T03:30:00Z) + const auto tm = toml::detail::gmtime_s(std::addressof(timet)); + CHECK_EQ(tm.tm_year + 1900, 2018); + CHECK_EQ(tm.tm_mon + 1, 4); + CHECK_EQ(tm.tm_mday, 1); + CHECK_EQ(tm.tm_hour, 3); + CHECK_EQ(tm.tm_min, 30); + CHECK_EQ(tm.tm_sec, 0); + } + + { + value_type v1(toml::offset_datetime( + toml::local_date{2018, toml::month_t::Apr, 1}, + toml::local_time{12, 30, 0}, + toml::time_offset{-8, 0})); + // 2018-04-01T12:30:00-08:00 + //, 2018-04-01T20:30:00Z + + const auto date = toml::try_get(v1).unwrap(); + const auto timet = std::chrono::system_clock::to_time_t(date); + + // get time_t as gmtime (2018-04-01T03:30:00Z) + const auto tm = toml::detail::gmtime_s(std::addressof(timet)); + CHECK_EQ(tm.tm_year + 1900, 2018); + CHECK_EQ(tm.tm_mon + 1, 4); + CHECK_EQ(tm.tm_mday, 1); + CHECK_EQ(tm.tm_hour, 20); + CHECK_EQ(tm.tm_min, 30); + CHECK_EQ(tm.tm_sec, 0); + } +}