#define BOOST_TEST_MODULE "test_find" #ifdef UNITTEST_FRAMEWORK_LIBRARY_EXIST #include #else #define BOOST_TEST_NO_LIB #include #endif #include #include #include #include #include #include #if __cplusplus >= 201703L #include #endif #include using test_value_types = std::tuple< toml::value, toml::basic_value, toml::basic_value, toml::basic_value >; BOOST_AUTO_TEST_CASE(test_find_throws) { // ----------------------------------------------------------------------- // const-reference version { // value is not a table const toml::value v(true); BOOST_CHECK_THROW(toml::find(v, "key"), toml::type_error); } { // the value corresponding to the key is not the expected type const toml::value v{{"key", 42}}; BOOST_CHECK_THROW(toml::find(v, "key"), toml::type_error); } { // the value corresponding to the key is not found const toml::value v{{"key", 42}}; BOOST_CHECK_THROW(toml::find(v, "different_key"), std::out_of_range); } { // the positive control. const toml::value v{{"key", 42}}; BOOST_TEST(42 == toml::find(v, "key")); } // ----------------------------------------------------------------------- // reference version { // value is not a table toml::value v(true); BOOST_CHECK_THROW(toml::find(v, "key"), toml::type_error); } { // the value corresponding to the key is not the expected type toml::value v{{"key", 42}}; BOOST_CHECK_THROW(toml::find(v, "key"), toml::type_error); } { // the value corresponding to the key is not found toml::value v{{"key", 42}}; BOOST_CHECK_THROW(toml::find(v, "different_key"), std::out_of_range); } { // the positive control. toml::value v{{"key", 42}}; BOOST_TEST(42 == toml::find(v, "key")); } // ----------------------------------------------------------------------- // move version { // value is not a table toml::value v(true); BOOST_CHECK_THROW(toml::find(std::move(v), "key"), toml::type_error); } { // the value corresponding to the key is not the expected type toml::value v{{"key", 42}}; BOOST_CHECK_THROW(toml::find(std::move(v), "key"), toml::type_error); } { // the value corresponding to the key is not found toml::value v{{"key", 42}}; BOOST_CHECK_THROW(toml::find(std::move(v), "different_key"), std::out_of_range); } { // the positive control. toml::value v{{"key", 42}}; BOOST_TEST(42 == toml::find(std::move(v), "key")); } } BOOST_AUTO_TEST_CASE(test_find_recursive) { // recursively search tables { toml::value v{ {"a", { {"b", { {"c", { {"d", 42} }} }} }} }; BOOST_TEST(42 == toml::find(v, "a", "b", "c", "d")); // reference that can be used to modify the content auto& num = toml::find(v, "a", "b", "c", "d"); num = 54; BOOST_TEST(54 == toml::find(v, "a", "b", "c", "d")); const std::string a("a"), b("b"), c("c"), d("d"); auto& num2 = toml::find(v, a, b, c, d); num2 = 42; BOOST_TEST(42 == toml::find(v, a, b, c, d)); auto num3 = toml::find(std::move(v), a, b, c, d); BOOST_TEST(42 == num3); } } BOOST_AUTO_TEST_CASE_TEMPLATE(test_find_exact, value_type, test_value_types) { { value_type v{{"key", true}}; BOOST_TEST(true == toml::find(v, "key")); toml::find(v, "key") = false; BOOST_TEST(false == toml::find(v, "key")); const auto moved = toml::find(std::move(v), "key"); BOOST_TEST(false == moved); } { value_type v{{"key", 42}}; BOOST_TEST(toml::integer(42) == toml::find(v, "key")); toml::find(v, "key") = 54; BOOST_TEST(toml::integer(54) == toml::find(v, "key")); const auto moved = toml::find(std::move(v), "key"); BOOST_TEST(toml::integer(54) == moved); } { value_type v{{"key", 3.14}}; BOOST_TEST(toml::floating(3.14) == toml::find(v, "key")); toml::find(v, "key") = 2.71; BOOST_TEST(toml::floating(2.71) == toml::find(v, "key")); const auto moved = toml::find(std::move(v), "key"); BOOST_TEST(toml::floating(2.71) == moved); } { value_type v{{"key", "foo"}}; BOOST_TEST(toml::string("foo", toml::string_t::basic) == toml::find(v, "key")); toml::find(v, "key").str += "bar"; BOOST_TEST(toml::string("foobar", toml::string_t::basic) == toml::find(v, "key")); const auto moved = toml::find(std::move(v), "key"); BOOST_TEST(toml::string("foobar", toml::string_t::basic) == moved); } { value_type v{{"key", value_type("foo", toml::string_t::literal)}}; BOOST_TEST(toml::string("foo", toml::string_t::literal) == toml::find(v, "key")); toml::find(v, "key").str += "bar"; BOOST_TEST(toml::string("foobar", toml::string_t::literal) == toml::find(v, "key")); const auto moved = toml::find(std::move(v), "key"); BOOST_TEST(toml::string("foobar", toml::string_t::literal) == moved); } { toml::local_date d(2018, toml::month_t::Apr, 22); value_type v{{"key", d}}; BOOST_CHECK(d == toml::find(v, "key")); toml::find(v, "key").year = 2017; d.year = 2017; BOOST_CHECK(d == toml::find(v, "key")); const auto moved = toml::find(std::move(v), "key"); BOOST_CHECK(d == moved); } { toml::local_time t(12, 30, 45); value_type v{{"key", t}}; BOOST_CHECK(t == toml::find(v, "key")); toml::find(v, "key").hour = 9; t.hour = 9; BOOST_CHECK(t == toml::find(v, "key")); const auto moved = toml::find(std::move(v), "key"); BOOST_CHECK(t == moved); } { toml::local_datetime dt(toml::local_date(2018, toml::month_t::Apr, 22), toml::local_time(12, 30, 45)); value_type v{{"key", dt}}; BOOST_CHECK(dt == toml::find(v, "key")); toml::find(v, "key").date.year = 2017; dt.date.year = 2017; BOOST_CHECK(dt == toml::find(v, "key")); const auto moved = toml::find(std::move(v), "key"); BOOST_CHECK(dt == moved); } { toml::offset_datetime 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{{"key", dt}}; BOOST_CHECK(dt == toml::find(v, "key")); toml::find(v, "key").date.year = 2017; dt.date.year = 2017; BOOST_CHECK(dt == toml::find(v, "key")); const auto moved = toml::find(std::move(v), "key"); BOOST_CHECK(dt == moved); } { typename value_type::array_type vec; vec.push_back(value_type(42)); vec.push_back(value_type(54)); value_type v{{"key", vec}}; const bool result1 = (vec == toml::find(v, "key")); BOOST_CHECK(result1); toml::find(v, "key").push_back(value_type(123)); vec.push_back(value_type(123)); const bool result2 = (vec == toml::find(v, "key")); BOOST_CHECK(result2); const auto moved = toml::find(std::move(v), "key"); const bool result3 = (vec == moved); BOOST_CHECK(result3); } { typename value_type::table_type tab; tab["key1"] = value_type(42); tab["key2"] = value_type(3.14); value_type v{{"key", tab}}; const bool result1 = (tab == toml::find(v, "key")); BOOST_CHECK(result1); toml::find(v, "key")["key3"] = value_type(123); tab["key3"] = value_type(123); const bool result2 = (tab == toml::find(v, "key")); BOOST_CHECK(result2); const auto moved = toml::find(std::move(v), "key"); const bool result3 = (tab == moved); BOOST_CHECK(result3); } { value_type v1(42); value_type v{{"key", v1}}; BOOST_CHECK(v1 == toml::find(v, "key")); value_type v2(54); toml::find(v, "key") = v2; BOOST_CHECK(v2 == toml::find(v, "key")); const auto moved = toml::find(std::move(v), "key"); BOOST_CHECK(v2 == moved); } } BOOST_AUTO_TEST_CASE_TEMPLATE(test_find_integer_type, value_type, test_value_types) { { value_type v{{"key", 42}}; BOOST_TEST(int(42) == toml::find(v, "key")); BOOST_TEST(short(42) == toml::find(v, "key")); BOOST_TEST(char(42) == toml::find(v, "key")); BOOST_TEST(unsigned(42) == toml::find(v, "key")); BOOST_TEST(long(42) == toml::find(v, "key")); BOOST_TEST(std::int64_t(42) == toml::find(v, "key")); BOOST_TEST(std::uint64_t(42) == toml::find(v, "key")); BOOST_TEST(std::int16_t(42) == toml::find(v, "key")); BOOST_TEST(std::uint16_t(42) == toml::find(v, "key")); BOOST_TEST(std::uint16_t(42) == toml::find(std::move(v), "key")); } } BOOST_AUTO_TEST_CASE_TEMPLATE(test_find_floating_type, value_type, test_value_types) { { value_type v{{"key", 3.14}}; BOOST_TEST(static_cast(3.14) == toml::find(v, "key")); BOOST_TEST(static_cast(3.14) == toml::find(v, "key")); BOOST_TEST(static_cast(3.14) == toml::find(v, "key")); BOOST_TEST(static_cast(3.14) == toml::find(std::move(v), "key")); } } BOOST_AUTO_TEST_CASE_TEMPLATE(test_find_string_type, value_type, test_value_types) { { value_type v{{"key", toml::string("foo", toml::string_t::basic)}}; BOOST_TEST("foo" == toml::find(v, "key")); toml::find(v, "key") += "bar"; BOOST_TEST("foobar" == toml::find(v, "key")); } { value_type v{{"key", toml::string("foo", toml::string_t::literal)}}; BOOST_TEST("foo" == toml::find(v, "key")); toml::find(v, "key") += "bar"; BOOST_TEST("foobar" == toml::find(v, "key")); } { value_type v{{"key", toml::string("foo", toml::string_t::literal)}}; const auto moved = toml::find(std::move(v), "key"); BOOST_TEST("foo" == moved); } #if __cplusplus >= 201703L { value_type v{{"key", toml::string("foo", toml::string_t::basic)}}; BOOST_TEST("foo" == toml::find(v, "key")); } { value_type v{{"key", toml::string("foo", toml::string_t::literal)}}; BOOST_TEST("foo" == toml::find(v, "key")); } #endif } BOOST_AUTO_TEST_CASE_TEMPLATE(test_find_toml_array, value_type, test_value_types) { value_type v{{"key", {42, 54, 69, 72}}}; const std::vector vec = toml::find>(v, "key"); const std::list lst = toml::find>(v, "key"); const std::deque deq = toml::find>(v, "key"); BOOST_TEST(42 == vec.at(0)); BOOST_TEST(54 == vec.at(1)); BOOST_TEST(69 == vec.at(2)); BOOST_TEST(72 == vec.at(3)); std::list::const_iterator iter = lst.begin(); BOOST_TEST(static_cast(42) == *(iter++)); BOOST_TEST(static_cast(54) == *(iter++)); BOOST_TEST(static_cast(69) == *(iter++)); BOOST_TEST(static_cast(72) == *(iter++)); BOOST_TEST(static_cast(42) == deq.at(0)); BOOST_TEST(static_cast(54) == deq.at(1)); BOOST_TEST(static_cast(69) == deq.at(2)); BOOST_TEST(static_cast(72) == deq.at(3)); std::array ary = toml::find>(v, "key"); BOOST_TEST(static_cast(42) == ary.at(0)); BOOST_TEST(static_cast(54) == ary.at(1)); BOOST_TEST(static_cast(69) == ary.at(2)); BOOST_TEST(static_cast(72) == ary.at(3)); std::tuple tpl = toml::find>(v, "key"); BOOST_TEST(static_cast(42) == std::get<0>(tpl)); BOOST_TEST(static_cast(54) == std::get<1>(tpl)); BOOST_TEST(static_cast(69) == std::get<2>(tpl)); BOOST_TEST(static_cast(72) == std::get<3>(tpl)); value_type p{{"key", {3.14, 2.71}}}; std::pair pr = toml::find >(p, "key"); BOOST_TEST(3.14 == pr.first); BOOST_TEST(2.71 == pr.second); } BOOST_AUTO_TEST_CASE_TEMPLATE(test_find_move_toml_array, value_type, test_value_types) { value_type v1{{"key", {42, 54, 69, 72}}}; value_type v2{{"key", {42, 54, 69, 72}}}; value_type v3{{"key", {42, 54, 69, 72}}}; value_type v4{{"key", {42, 54, 69, 72}}}; value_type v5{{"key", {42, 54, 69, 72}}}; const std::vector vec = toml::find>(std::move(v1), "key"); const std::list lst = toml::find>(std::move(v2), "key"); const std::deque deq = toml::find>(std::move(v3), "key"); BOOST_TEST(42 == vec.at(0)); BOOST_TEST(54 == vec.at(1)); BOOST_TEST(69 == vec.at(2)); BOOST_TEST(72 == vec.at(3)); std::list::const_iterator iter = lst.begin(); BOOST_TEST(static_cast(42) == *(iter++)); BOOST_TEST(static_cast(54) == *(iter++)); BOOST_TEST(static_cast(69) == *(iter++)); BOOST_TEST(static_cast(72) == *(iter++)); BOOST_TEST(static_cast(42) == deq.at(0)); BOOST_TEST(static_cast(54) == deq.at(1)); BOOST_TEST(static_cast(69) == deq.at(2)); BOOST_TEST(static_cast(72) == deq.at(3)); std::array ary = toml::find>(std::move(v4), "key"); BOOST_TEST(static_cast(42) == ary.at(0)); BOOST_TEST(static_cast(54) == ary.at(1)); BOOST_TEST(static_cast(69) == ary.at(2)); BOOST_TEST(static_cast(72) == ary.at(3)); std::tuple tpl = toml::find>(std::move(v5), "key"); BOOST_TEST(static_cast(42) == std::get<0>(tpl)); BOOST_TEST(static_cast(54) == std::get<1>(tpl)); BOOST_TEST(static_cast(69) == std::get<2>(tpl)); BOOST_TEST(static_cast(72) == std::get<3>(tpl)); value_type p{{"key", {3.14, 2.71}}}; std::pair pr = toml::find >(std::move(p), "key"); BOOST_TEST(3.14 == pr.first); BOOST_TEST(2.71 == pr.second); } BOOST_AUTO_TEST_CASE_TEMPLATE(test_find_toml_array_of_array, value_type, test_value_types) { value_type v1{42, 54, 69, 72}; value_type v2{"foo", "bar", "baz"}; value_type v{{"key", {v1, v2}}}; std::pair, std::vector> p = toml::find, std::vector>>(v, "key"); BOOST_TEST(p.first.at(0) == 42); BOOST_TEST(p.first.at(1) == 54); BOOST_TEST(p.first.at(2) == 69); BOOST_TEST(p.first.at(3) == 72); BOOST_TEST(p.second.at(0) == "foo"); BOOST_TEST(p.second.at(1) == "bar"); BOOST_TEST(p.second.at(2) == "baz"); std::tuple, std::vector> t = toml::find, std::vector>>(v, "key"); BOOST_TEST(std::get<0>(t).at(0) == 42); BOOST_TEST(std::get<0>(t).at(1) == 54); BOOST_TEST(std::get<0>(t).at(2) == 69); BOOST_TEST(std::get<0>(t).at(3) == 72); BOOST_TEST(std::get<1>(t).at(0) == "foo"); BOOST_TEST(std::get<1>(t).at(1) == "bar"); BOOST_TEST(std::get<1>(t).at(2) == "baz"); } BOOST_AUTO_TEST_CASE_TEMPLATE(test_find_move_toml_array_of_array, value_type, test_value_types) { value_type a1{42, 54, 69, 72}; value_type a2{"foo", "bar", "baz"}; value_type v1{{"key", {a1, a2}}}; value_type v2{{"key", {a1, a2}}}; std::pair, std::vector> p = toml::find, std::vector>>(std::move(v1), "key"); BOOST_TEST(p.first.at(0) == 42); BOOST_TEST(p.first.at(1) == 54); BOOST_TEST(p.first.at(2) == 69); BOOST_TEST(p.first.at(3) == 72); BOOST_TEST(p.second.at(0) == "foo"); BOOST_TEST(p.second.at(1) == "bar"); BOOST_TEST(p.second.at(2) == "baz"); std::tuple, std::vector> t = toml::find, std::vector>>(std::move(v2), "key"); BOOST_TEST(std::get<0>(t).at(0) == 42); BOOST_TEST(std::get<0>(t).at(1) == 54); BOOST_TEST(std::get<0>(t).at(2) == 69); BOOST_TEST(std::get<0>(t).at(3) == 72); BOOST_TEST(std::get<1>(t).at(0) == "foo"); BOOST_TEST(std::get<1>(t).at(1) == "bar"); BOOST_TEST(std::get<1>(t).at(2) == "baz"); } BOOST_AUTO_TEST_CASE_TEMPLATE(test_find_toml_table, value_type, test_value_types) { { value_type v1{{"key", { {"key1", 1}, {"key2", 2}, {"key3", 3}, {"key4", 4} }}}; const auto v = toml::find>(v1, "key"); BOOST_TEST(v.at("key1") == 1); BOOST_TEST(v.at("key2") == 2); BOOST_TEST(v.at("key3") == 3); BOOST_TEST(v.at("key4") == 4); } { value_type v1{{"key", { {"key1", 1}, {"key2", 2}, {"key3", 3}, {"key4", 4} }}}; const auto v = toml::find>(std::move(v1), "key"); BOOST_TEST(v.at("key1") == 1); BOOST_TEST(v.at("key2") == 2); BOOST_TEST(v.at("key3") == 3); BOOST_TEST(v.at("key4") == 4); } } BOOST_AUTO_TEST_CASE_TEMPLATE(test_find_toml_local_date, value_type, test_value_types) { { value_type v1{{"key", toml::local_date{2018, toml::month_t::Apr, 1}}}; const auto date = std::chrono::system_clock::to_time_t( toml::find(v1, "key")); 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); BOOST_TEST(c == date); } { value_type v1{{"key", toml::local_date{2018, toml::month_t::Apr, 1}}}; const auto date = std::chrono::system_clock::to_time_t( toml::find(std::move(v1), "key")); 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); BOOST_TEST(c == date); } } BOOST_AUTO_TEST_CASE_TEMPLATE(test_find_toml_local_time, value_type, test_value_types) { { value_type v1{{"key", toml::local_time{12, 30, 45}}}; const auto time = toml::find(v1, "key"); BOOST_CHECK(time == std::chrono::hours(12) + std::chrono::minutes(30) + std::chrono::seconds(45)); } { value_type v1{{"key", toml::local_time{12, 30, 45}}}; const auto time = toml::find(std::move(v1), "key"); BOOST_CHECK(time == std::chrono::hours(12) + std::chrono::minutes(30) + std::chrono::seconds(45)); } } BOOST_AUTO_TEST_CASE_TEMPLATE(test_find_toml_local_datetime, value_type, test_value_types) { { value_type v1{{"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::find(v1, "key")); 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); BOOST_TEST(c == date); } { value_type v1{{"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::find(std::move(v1), "key")); 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); BOOST_TEST(c == date); } } BOOST_AUTO_TEST_CASE_TEMPLATE(test_get_toml_offset_datetime, value_type, test_value_types) { { value_type v1{{"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::find(v1, "key"); const auto timet = std::chrono::system_clock::to_time_t(date); // get time_t as gmtime (2018-04-01T03:30:00Z) const auto tmp = std::gmtime(std::addressof(timet)); // XXX not threadsafe! BOOST_CHECK(tmp); const auto tm = *tmp; BOOST_TEST(tm.tm_year + 1900 == 2018); BOOST_TEST(tm.tm_mon + 1 == 4); BOOST_TEST(tm.tm_mday == 1); BOOST_TEST(tm.tm_hour == 3); BOOST_TEST(tm.tm_min == 30); BOOST_TEST(tm.tm_sec == 0); } { value_type v1{{"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::find(v1, "key"); const auto timet = std::chrono::system_clock::to_time_t(date); // get time_t as gmtime (2018-04-01T03:30:00Z) const auto tmp = std::gmtime(std::addressof(timet)); // XXX not threadsafe! BOOST_CHECK(tmp); const auto tm = *tmp; BOOST_TEST(tm.tm_year + 1900 == 2018); BOOST_TEST(tm.tm_mon + 1 == 4); BOOST_TEST(tm.tm_mday == 1); BOOST_TEST(tm.tm_hour == 20); BOOST_TEST(tm.tm_min == 30); BOOST_TEST(tm.tm_sec == 0); } { value_type v1{{"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::find(std::move(v1), "key"); const auto timet = std::chrono::system_clock::to_time_t(date); // get time_t as gmtime (2018-04-01T03:30:00Z) const auto tmp = std::gmtime(std::addressof(timet)); // XXX not threadsafe! BOOST_CHECK(tmp); const auto tm = *tmp; BOOST_TEST(tm.tm_year + 1900 == 2018); BOOST_TEST(tm.tm_mon + 1 == 4); BOOST_TEST(tm.tm_mday == 1); BOOST_TEST(tm.tm_hour == 20); BOOST_TEST(tm.tm_min == 30); BOOST_TEST(tm.tm_sec == 0); } }