diff --git a/libtransmission/variant.h b/libtransmission/variant.h index 34538912c..6f68ba849 100644 --- a/libtransmission/variant.h +++ b/libtransmission/variant.h @@ -219,13 +219,13 @@ public: [[nodiscard]] static auto make_raw(void const* value, size_t n_bytes) { - return tr_variant{ std::string{ static_cast(value), n_bytes } }; + return tr_variant{ std::string_view{ reinterpret_cast(value), n_bytes } }; } template [[nodiscard]] static auto make_raw(CharSpan const& value) { - static_assert(sizeof(CharSpan::value_type) == 1U); + static_assert(sizeof(typename CharSpan::value_type) == 1U); return make_raw(std::data(value), std::size(value)); } diff --git a/tests/libtransmission/dht-test.cc b/tests/libtransmission/dht-test.cc index 40123acd0..991124cb2 100644 --- a/tests/libtransmission/dht-test.cc +++ b/tests/libtransmission/dht-test.cc @@ -46,7 +46,7 @@ #include #include #include -#include // tr_variantDictAddRaw +#include #include "gtest/gtest.h" #include "test-fixtures.h" @@ -126,23 +126,22 @@ protected: { auto const dat_file = MockStateFile::filename(path); - auto dict = tr_variant{}; - tr_variantInitDict(&dict, 3U); - tr_variantDictAddRaw(&dict, TR_KEY_id, std::data(id_), std::size(id_)); - tr_variantDictAddInt(&dict, TR_KEY_id_timestamp, id_timestamp_); + auto map = tr_variant::Map{ 3U }; + map.try_emplace(TR_KEY_id, tr_variant::make_raw(id_)); + map.try_emplace(TR_KEY_id_timestamp, id_timestamp_); auto compact = std::vector{}; for (auto const& socket_address : ipv4_nodes_) { socket_address.to_compact(std::back_inserter(compact)); } - tr_variantDictAddRaw(&dict, TR_KEY_nodes, std::data(compact), std::size(compact)); + map.try_emplace(TR_KEY_nodes, tr_variant::make_raw(compact)); compact.clear(); for (auto const& socket_address : ipv6_nodes_) { socket_address.to_compact(std::back_inserter(compact)); } - tr_variantDictAddRaw(&dict, TR_KEY_nodes6, std::data(compact), std::size(compact)); - tr_variant_serde::benc().to_file(dict, dat_file); + map.try_emplace(TR_KEY_nodes6, tr_variant::make_raw(compact)); + tr_variant_serde::benc().to_file(tr_variant{ std::move(map) }, dat_file); } }; diff --git a/tests/libtransmission/json-test.cc b/tests/libtransmission/json-test.cc index f577c1e06..ef6445cab 100644 --- a/tests/libtransmission/json-test.cc +++ b/tests/libtransmission/json-test.cc @@ -51,7 +51,7 @@ private: TEST_P(JSONTest, testElements) { - auto const in = std::string{ + static auto constexpr In = std::string_view{ "{ \"string\": \"hello world\"," " \"escaped\": \"bell \\b formfeed \\f linefeed \\n carriage return \\r tab \\t\"," " \"int\": 5, " @@ -61,54 +61,60 @@ TEST_P(JSONTest, testElements) " \"null\": null }" }; - auto var = tr_variant_serde::json().inplace().parse(in).value_or(tr_variant{}); - EXPECT_TRUE(var.holds_alternative()); + auto const var = tr_variant_serde::json().inplace().parse(In).value_or(tr_variant{}); + auto const* const map = var.get_if(); + ASSERT_NE(map, nullptr); - auto sv = std::string_view{}; - auto key = tr_quark_new("string"sv); - EXPECT_TRUE(tr_variantDictFindStrView(&var, key, &sv)); - EXPECT_EQ("hello world"sv, sv); + auto sv = map->value_if(tr_quark_new("string"sv)); + ASSERT_TRUE(sv); + EXPECT_EQ("hello world"sv, *sv); - EXPECT_TRUE(tr_variantDictFindStrView(&var, tr_quark_new("escaped"sv), &sv)); - EXPECT_EQ("bell \b formfeed \f linefeed \n carriage return \r tab \t"sv, sv); + sv = map->value_if(tr_quark_new("escaped"sv)); + ASSERT_TRUE(sv); + EXPECT_EQ("bell \b formfeed \f linefeed \n carriage return \r tab \t"sv, *sv); - auto i = int64_t{}; - EXPECT_TRUE(tr_variantDictFindInt(&var, tr_quark_new("int"sv), &i)); - EXPECT_EQ(5, i); + auto i = map->value_if(tr_quark_new("int"sv)); + ASSERT_TRUE(i); + EXPECT_EQ(5, *i); - auto d = double{}; - EXPECT_TRUE(tr_variantDictFindReal(&var, tr_quark_new("float"sv), &d)); - EXPECT_EQ(65, int(d * 10)); + auto d = map->value_if(tr_quark_new("float"sv)); + ASSERT_TRUE(d); + EXPECT_EQ(65, int(*d * 10)); - auto f = bool{}; - EXPECT_TRUE(tr_variantDictFindBool(&var, tr_quark_new("true"sv), &f)); - EXPECT_TRUE(f); + auto b = map->value_if(tr_quark_new("true"sv)); + ASSERT_TRUE(b); + EXPECT_TRUE(*b); - EXPECT_TRUE(tr_variantDictFindBool(&var, tr_quark_new("false"sv), &f)); - EXPECT_FALSE(f); + b = map->value_if(tr_quark_new("false"sv)); + ASSERT_TRUE(b); + EXPECT_FALSE(*b); - EXPECT_TRUE(tr_variantDictFindStrView(&var, tr_quark_new("null"sv), &sv)); - EXPECT_EQ(""sv, sv); + sv = map->value_if(tr_quark_new("null"sv)); + ASSERT_TRUE(sv); + EXPECT_EQ(""sv, *sv); } TEST_P(JSONTest, testUtf8) { auto in = "{ \"key\": \"Letöltések\" }"sv; - auto sv = std::string_view{}; tr_quark const key = tr_quark_new("key"sv); auto serde = tr_variant_serde::json().inplace().compact(); auto var = serde.parse(in).value_or(tr_variant{}); - EXPECT_TRUE(var.holds_alternative()); - EXPECT_TRUE(tr_variantDictFindStrView(&var, key, &sv)); - EXPECT_EQ("Letöltések"sv, sv); + auto* map = var.get_if(); + ASSERT_NE(map, nullptr); + auto sv = map->value_if(key); + ASSERT_TRUE(sv); + EXPECT_EQ("Letöltések"sv, *sv); var.clear(); in = R"({ "key": "\u005C" })"sv; var = serde.parse(in).value_or(tr_variant{}); - EXPECT_TRUE(var.holds_alternative()); - EXPECT_TRUE(tr_variantDictFindStrView(&var, key, &sv)); - EXPECT_EQ("\\"sv, sv); + map = var.get_if(); + ASSERT_NE(map, nullptr); + sv = map->value_if(key); + ASSERT_TRUE(sv); + EXPECT_EQ("\\"sv, *sv); var.clear(); /** @@ -121,41 +127,51 @@ TEST_P(JSONTest, testUtf8) */ in = R"({ "key": "Let\u00f6lt\u00e9sek" })"sv; var = serde.parse(in).value_or(tr_variant{}); - EXPECT_TRUE(var.holds_alternative()); - EXPECT_TRUE(tr_variantDictFindStrView(&var, key, &sv)); - EXPECT_EQ("Letöltések"sv, sv); + map = var.get_if(); + ASSERT_NE(map, nullptr); + sv = map->value_if(key); + ASSERT_TRUE(sv); + EXPECT_EQ("Letöltések"sv, *sv); auto json = serde.to_string(var); var.clear(); EXPECT_FALSE(std::empty(json)); EXPECT_EQ(R"({"key":"Letöltések"})"sv, json); var = serde.parse(json).value_or(tr_variant{}); - EXPECT_TRUE(var.holds_alternative()); - EXPECT_TRUE(tr_variantDictFindStrView(&var, key, &sv)); - EXPECT_EQ("Letöltések"sv, sv); + map = var.get_if(); + ASSERT_NE(map, nullptr); + sv = map->value_if(key); + ASSERT_TRUE(sv); + EXPECT_EQ("Letöltések"sv, *sv); // Test string known to be prone to locale issues // https://github.com/transmission/transmission/issues/5967 var.clear(); - tr_variantInitDict(&var, 1U); - tr_variantDictAddStr(&var, key, "Дыскаграфія"sv); + var = tr_variant::make_map(1U); + map = var.get_if(); + map->try_emplace(key, "Дыскаграфія"sv); json = serde.to_string(var); EXPECT_EQ(R"({"key":"Дыскаграфія"})"sv, json); var = serde.parse(json).value_or(tr_variant{}); - EXPECT_TRUE(var.holds_alternative()); - EXPECT_TRUE(tr_variantDictFindStrView(&var, key, &sv)); - EXPECT_EQ("Дыскаграфія"sv, sv); + map = var.get_if(); + ASSERT_NE(map, nullptr); + sv = map->value_if(key); + ASSERT_TRUE(sv); + EXPECT_EQ("Дыскаграфія"sv, *sv); // Thinking emoji 🤔 var.clear(); - tr_variantInitDict(&var, 1U); - tr_variantDictAddStr(&var, key, "\xf0\x9f\xa4\x94"sv); + var = tr_variant::make_map(1U); + map = var.get_if(); + map->try_emplace(key, "\xf0\x9f\xa4\x94"sv); json = serde.to_string(var); EXPECT_EQ("{\"key\":\"\xf0\x9f\xa4\x94\"}"sv, json); var = serde.parse(json).value_or(tr_variant{}); - EXPECT_TRUE(var.holds_alternative()); - EXPECT_TRUE(tr_variantDictFindStrView(&var, key, &sv)); - EXPECT_EQ("\xf0\x9f\xa4\x94"sv, sv); + map = var.get_if(); + ASSERT_NE(map, nullptr); + sv = map->value_if(key); + ASSERT_TRUE(sv); + EXPECT_EQ("\xf0\x9f\xa4\x94"sv, *sv); } TEST_P(JSONTest, test1) @@ -176,32 +192,33 @@ TEST_P(JSONTest, test1) auto serde = tr_variant_serde::json(); auto var = serde.inplace().parse(Input).value_or(tr_variant{}); - EXPECT_TRUE(var.holds_alternative()); + auto* map = var.get_if(); + ASSERT_NE(map, nullptr); - auto sv = std::string_view{}; - auto i = int64_t{}; - auto* headers = tr_variantDictFind(&var, tr_quark_new("headers"sv)); - EXPECT_NE(nullptr, headers); - EXPECT_TRUE(headers->holds_alternative()); - EXPECT_TRUE(tr_variantDictFindStrView(headers, tr_quark_new("type"sv), &sv)); - EXPECT_EQ("request"sv, sv); - EXPECT_TRUE(tr_variantDictFindInt(headers, TR_KEY_tag, &i)); - EXPECT_EQ(666, i); - auto* body = tr_variantDictFind(&var, tr_quark_new("body"sv)); - EXPECT_NE(nullptr, body); - EXPECT_TRUE(tr_variantDictFindStrView(body, TR_KEY_name, &sv)); - EXPECT_EQ("torrent-info"sv, sv); - auto* args = tr_variantDictFind(body, tr_quark_new("arguments"sv)); - EXPECT_NE(nullptr, args); - EXPECT_TRUE(args->holds_alternative()); - auto* ids = tr_variantDictFind(args, TR_KEY_ids); - ASSERT_NE(nullptr, ids); - EXPECT_TRUE(ids->holds_alternative()); - EXPECT_EQ(2U, tr_variantListSize(ids)); - EXPECT_TRUE(tr_variantGetInt(tr_variantListChild(ids, 0), &i)); - EXPECT_EQ(7, i); - EXPECT_TRUE(tr_variantGetInt(tr_variantListChild(ids, 1), &i)); - EXPECT_EQ(10, i); + auto* headers = map->find_if(tr_quark_new("headers"sv)); + ASSERT_NE(headers, nullptr); + auto sv = headers->value_if(tr_quark_new("type"sv)); + ASSERT_TRUE(sv); + EXPECT_EQ("request"sv, *sv); + auto i = headers->value_if(TR_KEY_tag); + ASSERT_TRUE(i); + EXPECT_EQ(666, *i); + auto* body = map->find_if(tr_quark_new("body"sv)); + ASSERT_NE(body, nullptr); + sv = body->value_if(TR_KEY_name); + ASSERT_TRUE(sv); + EXPECT_EQ("torrent-info"sv, *sv); + auto* args = body->find_if(tr_quark_new("arguments"sv)); + ASSERT_NE(args, nullptr); + auto* ids = args->find_if(TR_KEY_ids); + ASSERT_NE(ids, nullptr); + EXPECT_EQ(2U, std::size(*ids)); + i = (*ids)[0].value_if(); + ASSERT_TRUE(i); + EXPECT_EQ(7, *i); + i = (*ids)[1].value_if(); + ASSERT_TRUE(i); + EXPECT_EQ(10, *i); } TEST_P(JSONTest, test2) @@ -221,11 +238,12 @@ TEST_P(JSONTest, test3) " \"leftUntilDone\": 2275655680 }"sv; auto var = tr_variant_serde::json().inplace().parse(Input).value_or(tr_variant{}); - EXPECT_TRUE(var.holds_alternative()); + auto* map = var.get_if(); + ASSERT_NE(map, nullptr); - auto sv = std::string_view{}; - EXPECT_TRUE(tr_variantDictFindStrView(&var, TR_KEY_errorString, &sv)); - EXPECT_EQ("torrent not registered with this tracker 6UHsVW'*C"sv, sv); + auto sv = map->value_if(TR_KEY_errorString); + ASSERT_TRUE(sv); + EXPECT_EQ("torrent not registered with this tracker 6UHsVW'*C"sv, *sv); } TEST_P(JSONTest, unescape) @@ -233,11 +251,12 @@ TEST_P(JSONTest, unescape) static auto constexpr Input = R"({ "string-1": "\/usr\/lib" })"sv; auto var = tr_variant_serde::json().inplace().parse(Input).value_or(tr_variant{}); - EXPECT_TRUE(var.holds_alternative()); + auto* map = var.get_if(); + ASSERT_NE(map, nullptr); - auto sv = std::string_view{}; - EXPECT_TRUE(tr_variantDictFindStrView(&var, tr_quark_new("string-1"sv), &sv)); - EXPECT_EQ("/usr/lib"sv, sv); + auto sv = map->value_if(tr_quark_new("string-1"sv)); + ASSERT_TRUE(sv); + EXPECT_EQ("/usr/lib"sv, *sv); } TEST_P(JSONTest, parseJsonFuzz) diff --git a/tests/libtransmission/makemeta-test.cc b/tests/libtransmission/makemeta-test.cc index c1757764a..2f7e73bc6 100644 --- a/tests/libtransmission/makemeta-test.cc +++ b/tests/libtransmission/makemeta-test.cc @@ -239,15 +239,16 @@ TEST_F(MakemetaTest, announceSingleTracker) // generate the torrent and parse it as a variant EXPECT_FALSE(builder.make_checksums().get().has_value()); auto top = tr_variant_serde::benc().parse(builder.benc()); - EXPECT_TRUE(top.has_value()); + ASSERT_TRUE(top); + auto* map = top->get_if(); // confirm there's an "announce" entry - auto single_announce = std::string_view{}; - EXPECT_TRUE(tr_variantDictFindStrView(&*top, TR_KEY_announce, &single_announce)); - EXPECT_EQ(SingleAnnounce, single_announce); + auto single_announce = map->value_if(TR_KEY_announce); + ASSERT_TRUE(single_announce); + EXPECT_EQ(SingleAnnounce, *single_announce); // confirm there's not an "announce-list" entry - EXPECT_EQ(nullptr, tr_variantDictFind(&*top, TR_KEY_announce_list)); + EXPECT_EQ(map->find(TR_KEY_announce_list), std::end(*map)); } TEST_F(MakemetaTest, announceMultiTracker) @@ -267,18 +268,18 @@ TEST_F(MakemetaTest, announceMultiTracker) // generate the torrent and parse it as a variant EXPECT_FALSE(builder.make_checksums().get().has_value()); auto top = tr_variant_serde::benc().parse(builder.benc()); - EXPECT_TRUE(top.has_value()); + ASSERT_TRUE(top); + auto* map = top->get_if(); // confirm there's an "announce" entry - auto single_announce = std::string_view{}; - EXPECT_TRUE(tr_variantDictFindStrView(&*top, TR_KEY_announce, &single_announce)); - EXPECT_EQ(builder.announce_list().at(0).announce.sv(), single_announce); + auto single_announce = map->value_if(TR_KEY_announce); + ASSERT_TRUE(single_announce); + EXPECT_EQ(builder.announce_list().at(0).announce.sv(), *single_announce); // confirm there's an "announce-list" entry - tr_variant* announce_list_variant = nullptr; - EXPECT_TRUE(tr_variantDictFindList(&*top, TR_KEY_announce_list, &announce_list_variant)); - EXPECT_NE(nullptr, announce_list_variant); - EXPECT_EQ(std::size(builder.announce_list()), tr_variantListSize(announce_list_variant)); + auto* announce_list_variant = map->find_if(TR_KEY_announce_list); + ASSERT_NE(announce_list_variant, nullptr); + EXPECT_EQ(std::size(builder.announce_list()), std::size(*announce_list_variant)); } TEST_F(MakemetaTest, privateAndSourceHasDifferentInfoHash) diff --git a/tests/libtransmission/move-test.cc b/tests/libtransmission/move-test.cc index f8625bc73..9ca690a70 100644 --- a/tests/libtransmission/move-test.cc +++ b/tests/libtransmission/move-test.cc @@ -37,11 +37,14 @@ class IncompleteDirTest protected: void SetUp() override { - auto const download_dir = GetParam().second; - tr_variantDictAddStr(settings(), TR_KEY_download_dir, download_dir); - auto const incomplete_dir = GetParam().first; - tr_variantDictAddStr(settings(), TR_KEY_incomplete_dir, incomplete_dir); - tr_variantDictAddBool(settings(), TR_KEY_incomplete_dir_enabled, true); + if (auto* map = settings()->get_if(); map != nullptr) + { + auto const download_dir = GetParam().second; + map->insert_or_assign(TR_KEY_download_dir, download_dir); + auto const incomplete_dir = GetParam().first; + map->insert_or_assign(TR_KEY_incomplete_dir, incomplete_dir); + map->insert_or_assign(TR_KEY_incomplete_dir_enabled, true); + } SessionTest::SetUp(); } diff --git a/tests/libtransmission/rpc-test.cc b/tests/libtransmission/rpc-test.cc index d18239b98..36dd849ce 100644 --- a/tests/libtransmission/rpc-test.cc +++ b/tests/libtransmission/rpc-test.cc @@ -32,38 +32,43 @@ using RpcTest = SessionTest; TEST_F(RpcTest, list) { - auto i = int64_t{}; - auto sv = std::string_view{}; - auto top = tr_rpc_parse_list_str("12"sv); - EXPECT_TRUE(top.holds_alternative()); - EXPECT_TRUE(tr_variantGetInt(&top, &i)); - EXPECT_EQ(12, i); + auto i = top.value_if(); + ASSERT_TRUE(i); + EXPECT_EQ(12, *i); top = tr_rpc_parse_list_str("6,7"sv); - EXPECT_TRUE(top.holds_alternative()); - EXPECT_EQ(2U, tr_variantListSize(&top)); - EXPECT_TRUE(tr_variantGetInt(tr_variantListChild(&top, 0), &i)); - EXPECT_EQ(6, i); - EXPECT_TRUE(tr_variantGetInt(tr_variantListChild(&top, 1), &i)); - EXPECT_EQ(7, i); + auto* v = top.get_if(); + ASSERT_NE(v, nullptr); + EXPECT_EQ(2U, std::size(*v)); + i = (*v)[0].value_if(); + ASSERT_TRUE(i); + EXPECT_EQ(6, *i); + i = (*v)[1].value_if(); + ASSERT_TRUE(i); + EXPECT_EQ(7, *i); top = tr_rpc_parse_list_str("asdf"sv); - EXPECT_TRUE(top.holds_alternative()); - EXPECT_TRUE(tr_variantGetStrView(&top, &sv)); - EXPECT_EQ("asdf"sv, sv); + auto sv = top.value_if(); + ASSERT_TRUE(sv); + EXPECT_EQ("asdf"sv, *sv); top = tr_rpc_parse_list_str("1,3-5"sv); - EXPECT_TRUE(top.holds_alternative()); - EXPECT_EQ(4U, tr_variantListSize(&top)); - EXPECT_TRUE(tr_variantGetInt(tr_variantListChild(&top, 0), &i)); - EXPECT_EQ(1, i); - EXPECT_TRUE(tr_variantGetInt(tr_variantListChild(&top, 1), &i)); - EXPECT_EQ(3, i); - EXPECT_TRUE(tr_variantGetInt(tr_variantListChild(&top, 2), &i)); - EXPECT_EQ(4, i); - EXPECT_TRUE(tr_variantGetInt(tr_variantListChild(&top, 3), &i)); - EXPECT_EQ(5, i); + v = top.get_if(); + ASSERT_NE(v, nullptr); + EXPECT_EQ(4U, std::size(*v)); + i = (*v)[0].value_if(); + ASSERT_TRUE(i); + EXPECT_EQ(1, *i); + i = (*v)[1].value_if(); + ASSERT_TRUE(i); + EXPECT_EQ(3, *i); + i = (*v)[2].value_if(); + ASSERT_TRUE(i); + EXPECT_EQ(4, *i); + i = (*v)[3].value_if(); + ASSERT_TRUE(i); + EXPECT_EQ(5, *i); } TEST_F(RpcTest, tagSync) @@ -154,18 +159,18 @@ TEST_F(RpcTest, sessionGet) auto* tor = zeroTorrentInit(ZeroTorrentState::NoFiles); EXPECT_NE(nullptr, tor); - auto request = tr_variant{}; - tr_variantInitDict(&request, 1); - tr_variantDictAddStrView(&request, TR_KEY_method, "session-get"); + auto request_map = tr_variant::Map{ 1U }; + request_map.try_emplace(TR_KEY_method, "session-get"sv); auto response = tr_variant{}; tr_rpc_request_exec( session_, - request, + std::move(request_map), [&response](tr_session* /*session*/, tr_variant&& resp) { response = std::move(resp); }); - EXPECT_TRUE(response.holds_alternative()); - tr_variant* args = nullptr; - EXPECT_TRUE(tr_variantDictFindDict(&response, TR_KEY_arguments, &args)); + auto* response_map = response.get_if(); + ASSERT_NE(response_map, nullptr); + auto* args_map = response_map->find_if(TR_KEY_arguments); + ASSERT_NE(args_map, nullptr); // what we expected static auto constexpr ExpectedKeys = std::array{ @@ -233,10 +238,7 @@ TEST_F(RpcTest, sessionGet) // what we got std::set actual_keys; - auto key = tr_quark{}; - tr_variant* val = nullptr; - auto n = size_t{}; - while ((tr_variantDictChild(args, n++, &key, &val))) + for (auto const& [key, val] : *args_map) { actual_keys.insert(key); } @@ -268,35 +270,36 @@ TEST_F(RpcTest, torrentGet) auto* tor = zeroTorrentInit(ZeroTorrentState::NoFiles); EXPECT_NE(nullptr, tor); - tr_variant request; - tr_variantInitDict(&request, 1); + auto request = tr_variant::Map{ 1U }; - tr_variantDictAddStrView(&request, TR_KEY_method, "torrent-get"); + request.try_emplace(TR_KEY_method, "torrent-get"); - tr_variant* args_in = tr_variantDictAddDict(&request, TR_KEY_arguments, 1); - tr_variant* fields = tr_variantDictAddList(args_in, TR_KEY_fields, 1); - tr_variantListAddStrView(fields, tr_quark_get_string_view(TR_KEY_id)); + auto args_in = tr_variant::Map{ 1U }; + auto fields = tr_variant::Vector{}; + fields.emplace_back(tr_quark_get_string_view(TR_KEY_id)); + args_in.try_emplace(TR_KEY_fields, std::move(fields)); + request.try_emplace(TR_KEY_arguments, std::move(args_in)); auto response = tr_variant{}; tr_rpc_request_exec( session_, - request, + std::move(request), [&response](tr_session* /*session*/, tr_variant&& resp) { response = std::move(resp); }); - EXPECT_TRUE(response.holds_alternative()); - tr_variant* args = nullptr; - EXPECT_TRUE(tr_variantDictFindDict(&response, TR_KEY_arguments, &args)); + auto* response_map = response.get_if(); + ASSERT_NE(response_map, nullptr); + auto* args_out = response_map->find_if(TR_KEY_arguments); + ASSERT_NE(args_out, nullptr); - tr_variant* torrents = nullptr; - EXPECT_TRUE(tr_variantDictFindList(args, TR_KEY_torrents, &torrents)); - EXPECT_EQ(1UL, tr_variantListSize(torrents)); + auto* torrents = args_out->find_if(TR_KEY_torrents); + ASSERT_NE(torrents, nullptr); + EXPECT_EQ(1UL, std::size(*torrents)); - tr_variant* first_torrent = tr_variantListChild(torrents, 0); - EXPECT_TRUE(first_torrent != nullptr); - EXPECT_TRUE(first_torrent->holds_alternative()); - int64_t first_torrent_id = 0; - EXPECT_TRUE(tr_variantDictFindInt(first_torrent, TR_KEY_id, &first_torrent_id)); - EXPECT_EQ(1, first_torrent_id); + auto* first_torrent = (*torrents)[0].get_if(); + ASSERT_NE(first_torrent, nullptr); + auto first_torrent_id = first_torrent->value_if(TR_KEY_id); + ASSERT_TRUE(first_torrent_id); + EXPECT_EQ(1, *first_torrent_id); // cleanup tr_torrentRemove(tor, false, nullptr, nullptr, nullptr, nullptr); diff --git a/tests/libtransmission/session-test.cc b/tests/libtransmission/session-test.cc index 4e947ab42..82f29bb61 100644 --- a/tests/libtransmission/session-test.cc +++ b/tests/libtransmission/session-test.cc @@ -283,14 +283,16 @@ TEST_F(SessionTest, sessionId) TEST_F(SessionTest, getDefaultSettingsIncludesSubmodules) { auto settings = tr_sessionGetDefaultSettings(); + auto* settings_map = settings.get_if(); + ASSERT_NE(settings_map, nullptr); // Choose a setting from each of [tr_session, tr_session_alt_speeds, tr_rpc_server] to test all of them. // These are all `false` by default for (auto const& key : { TR_KEY_peer_port_random_on_start, TR_KEY_alt_speed_time_enabled, TR_KEY_rpc_enabled }) { - auto flag = bool{}; - EXPECT_TRUE(tr_variantDictFindBool(&settings, key, &flag)); - EXPECT_FALSE(flag); + auto flag = settings_map->value_if(key); + ASSERT_TRUE(flag); + EXPECT_FALSE(*flag); } } @@ -304,10 +306,11 @@ TEST_F(SessionTest, honorsSettings) // Choose a setting from each of [tr_session, tr_session_alt_speeds, tr_rpc_server] to test all of them. // These are all `false` by default auto settings = tr_sessionGetDefaultSettings(); + auto* settings_map = settings.get_if(); + ASSERT_NE(settings_map, nullptr); for (auto const& key : { TR_KEY_peer_port_random_on_start, TR_KEY_alt_speed_time_enabled, TR_KEY_rpc_enabled }) { - tr_variantDictRemove(&settings, key); - tr_variantDictAddBool(&settings, key, true); + settings_map->insert_or_assign(key, true); } auto* session = tr_sessionInit(sandboxDir().data(), false, settings); @@ -332,11 +335,13 @@ TEST_F(SessionTest, savesSettings) // Choose a setting from each of [tr_session, tr_session_alt_speeds, tr_rpc_server] to test all of them. auto settings = tr_sessionGetSettings(session_); + auto* settings_map = settings.get_if(); + ASSERT_NE(settings_map, nullptr); for (auto const& key : { TR_KEY_peer_port_random_on_start, TR_KEY_alt_speed_time_enabled, TR_KEY_rpc_enabled }) { - auto flag = bool{}; - EXPECT_TRUE(tr_variantDictFindBool(&settings, key, &flag)); - EXPECT_TRUE(flag); + auto flag = settings_map->value_if(key); + ASSERT_TRUE(flag); + EXPECT_TRUE(*flag); } } diff --git a/tests/libtransmission/settings-test.cc b/tests/libtransmission/settings-test.cc index c736bc618..a23e27fdb 100644 --- a/tests/libtransmission/settings-test.cc +++ b/tests/libtransmission/settings-test.cc @@ -39,10 +39,9 @@ TEST_F(SettingsTest, canLoadBools) auto settings = tr_session::Settings{}; auto const expected_value = !settings.seed_queue_enabled; - auto var = tr_variant{}; - tr_variantInitDict(&var, 1); - tr_variantDictAddBool(&var, Key, expected_value); - settings.load(var); + auto map = tr_variant::Map{ 1U }; + map.try_emplace(Key, expected_value); + settings.load(tr_variant{ std::move(map) }); EXPECT_EQ(expected_value, settings.seed_queue_enabled); } @@ -56,9 +55,11 @@ TEST_F(SettingsTest, canSaveBools) settings.seed_queue_enabled = expected_value; auto var = settings.save(); - auto val = bool{}; - EXPECT_TRUE(tr_variantDictFindBool(&var, Key, &val)); - EXPECT_EQ(expected_value, val); + auto* const map = var.get_if(); + ASSERT_NE(map, nullptr); + auto const val = map->value_if(Key); + ASSERT_TRUE(val); + EXPECT_EQ(expected_value, *val); } TEST_F(SettingsTest, canLoadDoubles) @@ -68,10 +69,9 @@ TEST_F(SettingsTest, canLoadDoubles) auto settings = tr_session::Settings{}; auto const expected_value = settings.ratio_limit + 1.0; - auto var = tr_variant{}; - tr_variantInitDict(&var, 1); - tr_variantDictAddReal(&var, Key, expected_value); - settings.load(var); + auto map = tr_variant::Map{ 1U }; + map.try_emplace(Key, expected_value); + settings.load(tr_variant{ std::move(map) }); EXPECT_NEAR(expected_value, settings.ratio_limit, 0.001); } @@ -85,9 +85,11 @@ TEST_F(SettingsTest, canSaveDoubles) settings.seed_queue_enabled = expected_value; auto var = settings.save(); - auto val = bool{}; - EXPECT_TRUE(tr_variantDictFindBool(&var, Key, &val)); - EXPECT_EQ(expected_value, val); + auto* const map = var.get_if(); + ASSERT_NE(map, nullptr); + auto const val = map->value_if(Key); + ASSERT_TRUE(val); + EXPECT_EQ(expected_value, *val); } TEST_F(SettingsTest, canLoadEncryptionMode) @@ -98,17 +100,15 @@ TEST_F(SettingsTest, canLoadEncryptionMode) auto settings = std::make_unique(); ASSERT_NE(ExpectedValue, settings->encryption_mode); - auto var = tr_variant{}; - tr_variantInitDict(&var, 1); - tr_variantDictAddInt(&var, Key, ExpectedValue); - settings->load(var); + auto map = tr_variant::Map{ 1U }; + map.try_emplace(Key, ExpectedValue); + settings->load(tr_variant{ std::move(map) }); EXPECT_EQ(ExpectedValue, settings->encryption_mode); - var.clear(); settings = std::make_unique(); - tr_variantInitDict(&var, 1); - tr_variantDictAddStrView(&var, Key, "required"); - settings->load(var); + map = tr_variant::Map{ 1U }; + map.try_emplace(Key, "required"sv); + settings->load(tr_variant{ std::move(map) }); EXPECT_EQ(ExpectedValue, settings->encryption_mode); } @@ -122,9 +122,11 @@ TEST_F(SettingsTest, canSaveEncryptionMode) settings.encryption_mode = ExpectedValue; auto var = settings.save(); - auto val = int64_t{}; - EXPECT_TRUE(tr_variantDictFindInt(&var, Key, &val)); - EXPECT_EQ(ExpectedValue, val); + auto* const map = var.get_if(); + ASSERT_NE(map, nullptr); + auto const val = map->value_if(Key); + ASSERT_TRUE(val); + EXPECT_EQ(ExpectedValue, *val); } TEST_F(SettingsTest, canLoadLogLevel) @@ -136,17 +138,15 @@ TEST_F(SettingsTest, canLoadLogLevel) auto constexpr ExpectedValue = TR_LOG_DEBUG; ASSERT_NE(ExpectedValue, default_value); - auto var = tr_variant{}; - tr_variantInitDict(&var, 1); - tr_variantDictAddInt(&var, Key, ExpectedValue); - settings->load(var); + auto map = tr_variant::Map{ 1U }; + map.try_emplace(Key, ExpectedValue); + settings->load(tr_variant{ std::move(map) }); EXPECT_EQ(ExpectedValue, settings->log_level); - var.clear(); settings = std::make_unique(); - tr_variantInitDict(&var, 1); - tr_variantDictAddStrView(&var, Key, "debug"); - settings->load(var); + map = tr_variant::Map{ 1U }; + map.try_emplace(Key, "debug"sv); + settings->load(tr_variant{ std::move(map) }); EXPECT_EQ(ExpectedValue, settings->log_level); } @@ -161,9 +161,11 @@ TEST_F(SettingsTest, canSaveLogLevel) settings.log_level = ExpectedValue; auto var = settings.save(); - auto val = int64_t{}; - EXPECT_TRUE(tr_variantDictFindInt(&var, Key, &val)); - EXPECT_EQ(ExpectedValue, val); + auto* const map = var.get_if(); + ASSERT_NE(map, nullptr); + auto const val = map->value_if(Key); + ASSERT_TRUE(val); + EXPECT_EQ(ExpectedValue, *val); } TEST_F(SettingsTest, canLoadMode) @@ -175,17 +177,15 @@ TEST_F(SettingsTest, canLoadMode) auto constexpr ExpectedValue = tr_mode_t{ 0777 }; ASSERT_NE(ExpectedValue, default_value); - auto var = tr_variant{}; - tr_variantInitDict(&var, 1); - tr_variantDictAddInt(&var, Key, ExpectedValue); - settings->load(var); + auto map = tr_variant::Map{ 1U }; + map.try_emplace(Key, ExpectedValue); + settings->load(tr_variant{ std::move(map) }); EXPECT_EQ(ExpectedValue, settings->umask); - var.clear(); settings = std::make_unique(); - tr_variantInitDict(&var, 1); - tr_variantDictAddStrView(&var, Key, "0777"); - settings->load(var); + map = tr_variant::Map{ 1U }; + map.try_emplace(Key, "0777"sv); + settings->load(tr_variant{ std::move(map) }); EXPECT_EQ(ExpectedValue, settings->umask); } @@ -200,9 +200,11 @@ TEST_F(SettingsTest, canSaveMode) settings.umask = ExpectedValue; auto var = settings.save(); - auto val = std::string_view{}; - EXPECT_TRUE(tr_variantDictFindStrView(&var, Key, &val)); - EXPECT_EQ("0777", val); + auto* const map = var.get_if(); + ASSERT_NE(map, nullptr); + auto const val = map->value_if(Key); + ASSERT_TRUE(val); + EXPECT_EQ("0777"sv, *val); } TEST_F(SettingsTest, canLoadPort) @@ -214,10 +216,9 @@ TEST_F(SettingsTest, canLoadPort) auto constexpr ExpectedValue = tr_port::from_host(8080); ASSERT_NE(ExpectedValue, default_value); - auto var = tr_variant{}; - tr_variantInitDict(&var, 1); - tr_variantDictAddInt(&var, Key, ExpectedValue.host()); - settings.load(var); + auto map = tr_variant::Map{ 1U }; + map.try_emplace(Key, ExpectedValue.host()); + settings.load(tr_variant{ std::move(map) }); EXPECT_EQ(ExpectedValue, settings.peer_port); } @@ -232,9 +233,11 @@ TEST_F(SettingsTest, canSavePort) settings.peer_port = ExpectedValue; auto var = settings.save(); - auto val = int64_t{}; - EXPECT_TRUE(tr_variantDictFindInt(&var, Key, &val)); - EXPECT_EQ(ExpectedValue.host(), val); + auto* const map = var.get_if(); + ASSERT_NE(map, nullptr); + auto const val = map->value_if(Key); + ASSERT_TRUE(val); + EXPECT_EQ(ExpectedValue.host(), *val); } TEST_F(SettingsTest, canLoadPreallocation) @@ -246,17 +249,15 @@ TEST_F(SettingsTest, canLoadPreallocation) auto constexpr ExpectedValue = tr_open_files::Preallocation::Full; ASSERT_NE(ExpectedValue, default_value); - auto var = tr_variant{}; - tr_variantInitDict(&var, 1); - tr_variantDictAddInt(&var, Key, static_cast(ExpectedValue)); - settings->load(var); + auto map = tr_variant::Map{ 1U }; + map.try_emplace(Key, static_cast(ExpectedValue)); + settings->load(tr_variant{ std::move(map) }); EXPECT_EQ(ExpectedValue, settings->preallocation_mode); - var.clear(); settings = std::make_unique(); - tr_variantInitDict(&var, 1); - tr_variantDictAddStrView(&var, Key, "full"); - settings->load(var); + map = tr_variant::Map{ 1U }; + map.try_emplace(Key, "full"sv); + settings->load(tr_variant{ std::move(map) }); EXPECT_EQ(ExpectedValue, settings->preallocation_mode); } @@ -271,9 +272,11 @@ TEST_F(SettingsTest, canSavePreallocation) settings.preallocation_mode = ExpectedValue; auto var = settings.save(); - auto val = int64_t{}; - EXPECT_TRUE(tr_variantDictFindInt(&var, Key, &val)); - EXPECT_EQ(static_cast(ExpectedValue), val); + auto* const map = var.get_if(); + ASSERT_NE(map, nullptr); + auto const val = map->value_if(Key); + ASSERT_TRUE(val); + EXPECT_EQ(static_cast(ExpectedValue), *val); } TEST_F(SettingsTest, canLoadSizeT) @@ -283,10 +286,9 @@ TEST_F(SettingsTest, canLoadSizeT) auto settings = tr_session::Settings{}; auto const expected_value = settings.queue_stalled_minutes + 5U; - auto var = tr_variant{}; - tr_variantInitDict(&var, 1); - tr_variantDictAddInt(&var, Key, expected_value); - settings.load(var); + auto map = tr_variant::Map{ 1U }; + map.try_emplace(Key, expected_value); + settings.load(tr_variant{ std::move(map) }); EXPECT_EQ(expected_value, settings.queue_stalled_minutes); } @@ -299,9 +301,11 @@ TEST_F(SettingsTest, canSaveSizeT) settings.queue_stalled_minutes = expected_value; auto var = settings.save(); - auto val = int64_t{}; - EXPECT_TRUE(tr_variantDictFindInt(&var, Key, &val)); - EXPECT_EQ(expected_value, static_cast(val)); + auto* const map = var.get_if(); + ASSERT_NE(map, nullptr); + auto const val = map->value_if(Key); + ASSERT_TRUE(val); + EXPECT_EQ(expected_value, static_cast(*val)); } TEST_F(SettingsTest, canLoadString) @@ -312,10 +316,9 @@ TEST_F(SettingsTest, canLoadString) auto settings = tr_session::Settings{}; EXPECT_NE(ChangedValue, tr_session::Settings{}.bind_address_ipv4); - auto var = tr_variant{}; - tr_variantInitDict(&var, 1); - tr_variantDictAddStrView(&var, Key, ChangedValue); - settings.load(var); + auto map = tr_variant::Map{ 1U }; + map.try_emplace(Key, ChangedValue); + settings.load(tr_variant{ std::move(map) }); EXPECT_EQ(ChangedValue, settings.bind_address_ipv4); } @@ -329,9 +332,11 @@ TEST_F(SettingsTest, canSaveString) settings.bind_address_ipv4 = ChangedValue; auto var = settings.save(); - auto val = std::string_view{}; - EXPECT_TRUE(tr_variantDictFindStrView(&var, Key, &val)); - EXPECT_EQ(ChangedValue, val); + auto* const map = var.get_if(); + ASSERT_NE(map, nullptr); + auto const val = map->value_if(Key); + ASSERT_TRUE(val); + EXPECT_EQ(ChangedValue, *val); } TEST_F(SettingsTest, canLoadTos) @@ -343,17 +348,15 @@ TEST_F(SettingsTest, canLoadTos) auto const default_value = settings->peer_socket_tos; ASSERT_NE(ChangedValue, default_value); - auto var = tr_variant{}; - tr_variantInitDict(&var, 1); - tr_variantDictAddInt(&var, Key, 0x20); - settings->load(var); + auto map = tr_variant::Map{ 1U }; + map.try_emplace(Key, 0x20); + settings->load(tr_variant{ std::move(map) }); EXPECT_EQ(ChangedValue, settings->peer_socket_tos); - var.clear(); settings = std::make_unique(); - tr_variantInitDict(&var, 1); - tr_variantDictAddStrView(&var, Key, "cs1"); - settings->load(var); + map = tr_variant::Map{ 1U }; + map.try_emplace(Key, "cs1"sv); + settings->load(tr_variant{ std::move(map) }); EXPECT_EQ(ChangedValue, settings->peer_socket_tos); } @@ -367,9 +370,11 @@ TEST_F(SettingsTest, canSaveTos) settings.peer_socket_tos = tr_tos_t(0x20); auto var = settings.save(); - auto val = std::string_view{}; - EXPECT_TRUE(tr_variantDictFindStrView(&var, Key, &val)); - EXPECT_EQ(ChangedValue.toString(), val); + auto* const map = var.get_if(); + ASSERT_NE(map, nullptr); + auto const val = map->value_if(Key); + ASSERT_TRUE(val); + EXPECT_EQ(ChangedValue.toString(), *val); } TEST_F(SettingsTest, canLoadVerify) @@ -381,17 +386,15 @@ TEST_F(SettingsTest, canLoadVerify) auto const default_value = settings->torrent_added_verify_mode; ASSERT_NE(ChangedValue, default_value); - auto var = tr_variant{}; - tr_variantInitDict(&var, 1); - tr_variantDictAddStrView(&var, Key, "full"); - settings->load(var); + auto map = tr_variant::Map{ 1U }; + map.try_emplace(Key, "full"sv); + settings->load(tr_variant{ std::move(map) }); EXPECT_EQ(ChangedValue, settings->torrent_added_verify_mode); - var.clear(); settings = std::make_unique(); - tr_variantInitDict(&var, 1); - tr_variantDictAddInt(&var, Key, ChangedValue); - settings->load(var); + map = tr_variant::Map{ 1U }; + map.try_emplace(Key, ChangedValue); + settings->load(tr_variant{ std::move(map) }); EXPECT_EQ(ChangedValue, settings->torrent_added_verify_mode); } @@ -405,9 +408,11 @@ TEST_F(SettingsTest, canSaveVerify) settings.torrent_added_verify_mode = ChangedValue; auto var = settings.save(); - auto val = std::string_view{}; - EXPECT_TRUE(tr_variantDictFindStrView(&var, Key, &val)); - EXPECT_EQ("full", val); + auto* const map = var.get_if(); + ASSERT_NE(map, nullptr); + auto const val = map->value_if(Key); + ASSERT_TRUE(val); + EXPECT_EQ("full"sv, *val); } TEST_F(SettingsTest, canLoadPreferredTransport) @@ -419,17 +424,15 @@ TEST_F(SettingsTest, canLoadPreferredTransport) auto const default_value = settings->preferred_transport; ASSERT_NE(ExpectedValue, default_value); - auto var = tr_variant{}; - tr_variantInitDict(&var, 1); - tr_variantDictAddInt(&var, Key, ExpectedValue); - settings->load(var); + auto map = tr_variant::Map{ 1U }; + map.try_emplace(Key, ExpectedValue); + settings->load(tr_variant{ std::move(map) }); EXPECT_EQ(ExpectedValue, settings->preferred_transport); - var.clear(); settings = std::make_unique(); - tr_variantInitDict(&var, 1); - tr_variantDictAddStrView(&var, Key, "tcp"); - settings->load(var); + map = tr_variant::Map{ 1U }; + map.try_emplace(Key, "tcp"sv); + settings->load(tr_variant{ std::move(map) }); EXPECT_EQ(ExpectedValue, settings->preferred_transport); } @@ -442,13 +445,13 @@ TEST_F(SettingsTest, canSavePreferredTransport) auto const default_value = settings.preferred_transport; ASSERT_NE(ExpectedValue, default_value); - auto var = tr_variant{}; - tr_variantInitDict(&var, 100); settings.preferred_transport = ExpectedValue; - var = settings.save(); - auto val = std::string_view{}; - EXPECT_TRUE(tr_variantDictFindStrView(&var, Key, &val)); - EXPECT_EQ("tcp", val); + auto var = settings.save(); + auto* const map = var.get_if(); + ASSERT_NE(map, nullptr); + auto const val = map->value_if(Key); + ASSERT_TRUE(val); + EXPECT_EQ("tcp"sv, *val); } TEST_F(SettingsTest, canLoadSleepPerSecondsDuringVerify) @@ -460,17 +463,15 @@ TEST_F(SettingsTest, canLoadSleepPerSecondsDuringVerify) auto const default_value = settings->sleep_per_seconds_during_verify; ASSERT_NE(ExpectedValue, default_value); - auto var = tr_variant{}; - tr_variantInitDict(&var, 1); - tr_variantDictAddInt(&var, Key, ExpectedValue.count()); - settings->load(var); + auto map = tr_variant::Map{ 1U }; + map.try_emplace(Key, ExpectedValue.count()); + settings->load(tr_variant{ std::move(map) }); EXPECT_EQ(ExpectedValue, settings->sleep_per_seconds_during_verify); - var.clear(); settings = std::make_unique(); - tr_variantInitDict(&var, 1); - tr_variantDictAddInt(&var, Key, 90); - settings->load(var); + map = tr_variant::Map{ 1U }; + map.try_emplace(Key, 90); + settings->load(tr_variant{ std::move(map) }); EXPECT_EQ(ExpectedValue, settings->sleep_per_seconds_during_verify); } @@ -483,12 +484,11 @@ TEST_F(SettingsTest, canSaveSleepPerSecondsDuringVerify) auto const default_value = settings.sleep_per_seconds_during_verify; ASSERT_NE(ExpectedValue, default_value); - auto var = tr_variant{}; - tr_variantInitDict(&var, 100); settings.sleep_per_seconds_during_verify = ExpectedValue; - var = settings.save(); - - auto val_raw = int64_t{}; - EXPECT_TRUE(tr_variantDictFindInt(&var, Key, &val_raw)); - EXPECT_EQ(ExpectedValue, std::chrono::milliseconds{ val_raw }); + auto var = settings.save(); + auto* const map = var.get_if(); + ASSERT_NE(map, nullptr); + auto const val_raw = map->value_if(Key); + ASSERT_TRUE(val_raw); + EXPECT_EQ(ExpectedValue, std::chrono::milliseconds{ *val_raw }); } diff --git a/tests/libtransmission/test-fixtures.h b/tests/libtransmission/test-fixtures.h index d16143ab4..58d816775 100644 --- a/tests/libtransmission/test-fixtures.h +++ b/tests/libtransmission/test-fixtures.h @@ -479,9 +479,7 @@ protected: { if (!settings_) { - auto* settings = new tr_variant{}; - tr_variantInitDict(settings, 10); - settings_.reset(settings); + settings_ = std::make_shared(tr_variant::make_map(10U)); } return settings_.get(); diff --git a/tests/libtransmission/variant-test.cc b/tests/libtransmission/variant-test.cc index fb73bec20..ea478e73a 100644 --- a/tests/libtransmission/variant-test.cc +++ b/tests/libtransmission/variant-test.cc @@ -35,65 +35,69 @@ using VariantTest = ::testing::Test; TEST_F(VariantTest, getType) { - auto i = int64_t{}; - auto b = bool{}; - auto d = double{}; - auto sv = std::string_view{}; auto v = tr_variant{}; v = 30; - EXPECT_TRUE(tr_variantGetInt(&v, &i)); - EXPECT_EQ(30, i); - EXPECT_TRUE(tr_variantGetReal(&v, &d)); - EXPECT_EQ(30, int(d)); - EXPECT_FALSE(tr_variantGetBool(&v, &b)); - EXPECT_FALSE(tr_variantGetStrView(&v, &sv)); + auto i = v.value_if(); + ASSERT_TRUE(i); + EXPECT_EQ(30, *i); + auto d = v.value_if(); + ASSERT_TRUE(d); + EXPECT_EQ(30, static_cast(*d)); + EXPECT_FALSE(v.holds_alternative()); + EXPECT_FALSE(v.holds_alternative()); auto strkey = "foo"sv; v = tr_variant{ strkey }; - EXPECT_FALSE(tr_variantGetBool(&v, &b)); - EXPECT_TRUE(tr_variantGetStrView(&v, &sv)); - EXPECT_EQ(strkey, sv); - EXPECT_NE(std::data(strkey), std::data(sv)); + EXPECT_FALSE(v.holds_alternative()); + auto sv = v.value_if(); + ASSERT_TRUE(sv); + EXPECT_EQ(strkey, *sv); + EXPECT_NE(std::data(strkey), std::data(*sv)); + EXPECT_EQ(std::size(strkey), std::size(*sv)); strkey = "anything"sv; v = tr_variant::unmanaged_string(strkey); - EXPECT_TRUE(tr_variantGetStrView(&v, &sv)); - EXPECT_EQ(strkey, sv); - EXPECT_EQ(std::data(strkey), std::data(sv)); // literally the same memory - EXPECT_EQ(std::size(strkey), std::size(sv)); + sv = v.value_if(); + ASSERT_TRUE(sv); + EXPECT_EQ(strkey, *sv); + EXPECT_EQ(std::data(strkey), std::data(*sv)); // literally the same memory + EXPECT_EQ(std::size(strkey), std::size(*sv)); strkey = "true"sv; v = tr_variant{ strkey }; - EXPECT_TRUE(tr_variantGetBool(&v, &b)); - EXPECT_TRUE(b); - EXPECT_TRUE(tr_variantGetStrView(&v, &sv)); - EXPECT_EQ(strkey, sv); + auto b = v.value_if(); + ASSERT_TRUE(b); + EXPECT_TRUE(*b); + sv = v.value_if(); + ASSERT_TRUE(sv); + EXPECT_EQ(strkey, *sv); strkey = "false"sv; v = tr_variant{ strkey }; - EXPECT_TRUE(tr_variantGetBool(&v, &b)); - EXPECT_FALSE(b); - EXPECT_TRUE(tr_variantGetStrView(&v, &sv)); - EXPECT_EQ(strkey, sv); + b = v.value_if(); + ASSERT_TRUE(b); + EXPECT_FALSE(*b); + sv = v.value_if(); + ASSERT_TRUE(sv); + EXPECT_EQ(strkey, *sv); } TEST_F(VariantTest, parseInt) { - auto constexpr Benc = "i64e"sv; - auto constexpr ExpectVal = int64_t{ 64 }; + static auto constexpr Benc = "i64e"sv; + static auto constexpr ExpectVal = int64_t{ 64 }; auto benc = Benc; auto const value = transmission::benc::impl::ParseInt(&benc); - EXPECT_TRUE(value.has_value()); - assert(value.has_value()); + ASSERT_TRUE(value); EXPECT_EQ(ExpectVal, *value); EXPECT_EQ(std::data(Benc) + std::size(Benc), std::data(benc)); } TEST_F(VariantTest, parseIntWithMissingEnd) { - auto constexpr Benc = "i64"sv; + static auto constexpr Benc = "i64"sv; auto benc = Benc; EXPECT_FALSE(transmission::benc::impl::ParseInt(&benc)); @@ -102,7 +106,7 @@ TEST_F(VariantTest, parseIntWithMissingEnd) TEST_F(VariantTest, parseIntEmptyBuffer) { - auto constexpr Benc = ""sv; + static auto constexpr Benc = ""sv; auto benc = Benc; EXPECT_FALSE(transmission::benc::impl::ParseInt(&benc)); @@ -111,7 +115,7 @@ TEST_F(VariantTest, parseIntEmptyBuffer) TEST_F(VariantTest, parseIntWithBadDigits) { - auto constexpr Benc = "i6z4e"sv; + static auto constexpr Benc = "i6z4e"sv; auto benc = Benc; EXPECT_FALSE(transmission::benc::impl::ParseInt(&benc)); @@ -120,20 +124,19 @@ TEST_F(VariantTest, parseIntWithBadDigits) TEST_F(VariantTest, parseNegativeInt) { - auto constexpr Benc = "i-3e"sv; - auto constexpr Expected = int64_t{ -3 }; + static auto constexpr Benc = "i-3e"sv; + static auto constexpr Expected = int64_t{ -3 }; auto benc = Benc; auto const value = transmission::benc::impl::ParseInt(&benc); - EXPECT_TRUE(value.has_value()); - assert(value.has_value()); + ASSERT_TRUE(value); EXPECT_EQ(Expected, *value); EXPECT_EQ(std::data(Benc) + std::size(Benc), std::data(benc)); } TEST_F(VariantTest, parseNegativeWithLeadingZero) { - auto constexpr Benc = "i-03e"sv; + static auto constexpr Benc = "i-03e"sv; auto benc = Benc; EXPECT_FALSE(transmission::benc::impl::ParseInt(&benc)); @@ -142,20 +145,19 @@ TEST_F(VariantTest, parseNegativeWithLeadingZero) TEST_F(VariantTest, parseIntZero) { - auto constexpr Benc = "i0e"sv; - auto constexpr Expected = int64_t{ 0 }; + static auto constexpr Benc = "i0e"sv; + static auto constexpr Expected = int64_t{ 0 }; auto benc = Benc; auto const value = transmission::benc::impl::ParseInt(&benc); - EXPECT_TRUE(value.has_value()); - assert(value.has_value()); + ASSERT_TRUE(value); EXPECT_EQ(Expected, *value); EXPECT_EQ(std::data(Benc) + std::size(Benc), std::data(benc)); } TEST_F(VariantTest, parseIntWithLeadingZero) { - auto constexpr Benc = "i04e"sv; + static auto constexpr Benc = "i04e"sv; auto benc = Benc; EXPECT_FALSE(transmission::benc::impl::ParseInt(&benc)); @@ -176,8 +178,7 @@ TEST_F(VariantTest, str) // good string inout = benc = "4:boat"; value = ParseString(&inout); - EXPECT_TRUE(value.has_value()); - assert(value.has_value()); + ASSERT_TRUE(value); EXPECT_EQ("boat"sv, *value); EXPECT_EQ(std::data(benc) + std::size(benc), std::data(inout)); @@ -190,16 +191,14 @@ TEST_F(VariantTest, str) // empty string inout = benc = "0:"sv; value = ParseString(&inout); - EXPECT_TRUE(value.has_value()); - assert(value.has_value()); + ASSERT_TRUE(value); EXPECT_EQ(""sv, *value); EXPECT_EQ(std::data(benc) + std::size(benc), std::data(inout)); // short string inout = benc = "3:boat"; value = ParseString(&inout); - EXPECT_TRUE(value.has_value()); - assert(value.has_value()); + ASSERT_TRUE(value); EXPECT_EQ("boa"sv, *value); EXPECT_EQ(std::data(benc) + benc.find('t'), std::data(inout)); } @@ -211,23 +210,27 @@ TEST_F(VariantTest, parse) auto benc = "i64e"sv; auto var = serde.parse(benc).value_or(tr_variant{}); - auto i = int64_t{}; - EXPECT_TRUE(tr_variantGetInt(&var, &i)); - EXPECT_EQ(64, i); + auto i = var.value_if(); + ASSERT_TRUE(i); + EXPECT_EQ(64, *i); EXPECT_EQ(std::data(benc) + std::size(benc), serde.end()); var.clear(); benc = "li64ei32ei16ee"sv; var = serde.parse(benc).value_or(tr_variant{}); - EXPECT_TRUE(var.holds_alternative()); + auto* l = var.get_if(); + ASSERT_NE(l, nullptr); EXPECT_EQ(std::data(benc) + std::size(benc), serde.end()); - EXPECT_EQ(3, tr_variantListSize(&var)); - EXPECT_TRUE(tr_variantGetInt(tr_variantListChild(&var, 0), &i)); - EXPECT_EQ(64, i); - EXPECT_TRUE(tr_variantGetInt(tr_variantListChild(&var, 1), &i)); - EXPECT_EQ(32, i); - EXPECT_TRUE(tr_variantGetInt(tr_variantListChild(&var, 2), &i)); - EXPECT_EQ(16, i); + ASSERT_EQ(3, std::size(*l)); + i = (*l)[0].value_if(); + ASSERT_TRUE(i); + EXPECT_EQ(64, *i); + i = (*l)[1].value_if(); + ASSERT_TRUE(i); + EXPECT_EQ(32, *i); + i = (*l)[2].value_if(); + ASSERT_TRUE(i); + EXPECT_EQ(16, *i); EXPECT_EQ(benc, serde.to_string(var)); var.clear(); @@ -252,13 +255,7 @@ TEST_F(VariantTest, parse) TEST_F(VariantTest, bencParseAndReencode) { - struct LocalTest - { - std::string_view benc; - bool is_good; - }; - - auto constexpr Tests = std::array{ { + static auto constexpr Tests = std::array, 9>{ { { "llleee"sv, true }, { "d3:cow3:moo4:spam4:eggse"sv, true }, { "d4:spaml1:a1:bee"sv, true }, @@ -273,14 +270,14 @@ TEST_F(VariantTest, bencParseAndReencode) auto serde = tr_variant_serde::benc(); serde.inplace(); - for (auto const& test : Tests) + for (auto const& [benc, is_good] : Tests) { - auto var = serde.parse(test.benc); - EXPECT_EQ(test.is_good, var.has_value()); + auto var = serde.parse(benc); + EXPECT_EQ(is_good, var.has_value()); if (var) { - EXPECT_EQ(test.benc.data() + test.benc.size(), serde.end()); - EXPECT_EQ(test.benc, serde.to_string(*var)); + EXPECT_EQ(benc.data() + benc.size(), serde.end()); + EXPECT_EQ(benc, serde.to_string(*var)); } } } @@ -329,13 +326,7 @@ TEST_F(VariantTest, bencMalformedIncompleteString) TEST_F(VariantTest, bencToJson) { - struct LocalTest - { - std::string_view benc; - std::string_view expected; - }; - - auto constexpr Tests = std::array{ + static auto constexpr Tests = std::array, 5>{ { { "i6e"sv, "6"sv }, { "d5:helloi1e5:worldi2ee"sv, R"({"hello":1,"world":2})"sv }, { "d5:helloi1e5:worldi2e3:fooli1ei2ei3eee"sv, R"({"foo":[1,2,3],"hello":1,"world":2})"sv }, @@ -349,10 +340,10 @@ TEST_F(VariantTest, bencToJson) benc_serde.inplace(); json_serde.compact(); - for (auto const& test : Tests) + for (auto const& [benc, expected] : Tests) { - auto top = benc_serde.parse(test.benc).value_or(tr_variant{}); - EXPECT_EQ(test.expected, json_serde.to_string(top)); + auto top = benc_serde.parse(benc).value_or(tr_variant{}); + EXPECT_EQ(expected, json_serde.to_string(top)); } } @@ -368,51 +359,58 @@ TEST_F(VariantTest, merge) auto const s8 = tr_quark_new("s8"sv); /* initial dictionary (default values) */ - tr_variant dest; - tr_variantInitDict(&dest, 10); - tr_variantDictAddInt(&dest, i1, 1); - tr_variantDictAddInt(&dest, i2, 2); - tr_variantDictAddInt(&dest, i4, -35); /* remains untouched */ - tr_variantDictAddStrView(&dest, s5, "abc"); - tr_variantDictAddStrView(&dest, s6, "def"); - tr_variantDictAddStrView(&dest, s7, "127.0.0.1"); /* remains untouched */ + auto dest = tr_variant::make_map(6U); + auto* map = dest.get_if(); + map->try_emplace(i1, 1); + map->try_emplace(i2, 2); + map->try_emplace(i4, -35); /* remains untouched */ + map->try_emplace(s5, "abc"); + map->try_emplace(s6, "def"); + map->try_emplace(s7, "127.0.0.1"); /* remains untouched */ /* new dictionary, will overwrite items in dest */ - tr_variant src; - tr_variantInitDict(&src, 10); - tr_variantDictAddInt(&src, i1, 1); /* same value */ - tr_variantDictAddInt(&src, i2, 4); /* new value */ - tr_variantDictAddInt(&src, i3, 3); /* new key:value */ - tr_variantDictAddStrView(&src, s5, "abc"); /* same value */ - tr_variantDictAddStrView(&src, s6, "xyz"); /* new value */ - tr_variantDictAddStrView(&src, s8, "ghi"); /* new key:value */ + auto src = tr_variant::make_map(6U); + map = src.get_if(); + map->try_emplace(i1, 1); /* same value */ + map->try_emplace(i2, 4); /* new value */ + map->try_emplace(i3, 3); /* new key:value */ + map->try_emplace(s5, "abc"); /* same value */ + map->try_emplace(s6, "xyz"); /* new value */ + map->try_emplace(s8, "ghi"); /* new key:value */ - tr_variantMergeDicts(&dest, /*const*/ &src); + dest.merge(src); - auto i = int64_t{}; - EXPECT_TRUE(tr_variantDictFindInt(&dest, i1, &i)); - EXPECT_EQ(1, i); - EXPECT_TRUE(tr_variantDictFindInt(&dest, i2, &i)); - EXPECT_EQ(4, i); - EXPECT_TRUE(tr_variantDictFindInt(&dest, i3, &i)); - EXPECT_EQ(3, i); - EXPECT_TRUE(tr_variantDictFindInt(&dest, i4, &i)); - EXPECT_EQ(-35, i); - auto sv = std::string_view{}; - EXPECT_TRUE(tr_variantDictFindStrView(&dest, s5, &sv)); - EXPECT_EQ("abc"sv, sv); - EXPECT_TRUE(tr_variantDictFindStrView(&dest, s6, &sv)); - EXPECT_EQ("xyz"sv, sv); - EXPECT_TRUE(tr_variantDictFindStrView(&dest, s7, &sv)); - EXPECT_EQ("127.0.0.1"sv, sv); - EXPECT_TRUE(tr_variantDictFindStrView(&dest, s8, &sv)); - EXPECT_EQ("ghi"sv, sv); + map = dest.get_if(); + auto i = map->value_if(i1); + ASSERT_TRUE(i); + EXPECT_EQ(1, *i); + i = map->value_if(i2); + ASSERT_TRUE(i); + EXPECT_EQ(4, *i); + i = map->value_if(i3); + ASSERT_TRUE(i); + EXPECT_EQ(3, *i); + i = map->value_if(i4); + ASSERT_TRUE(i); + EXPECT_EQ(-35, *i); + auto sv = map->value_if(s5); + ASSERT_TRUE(sv); + EXPECT_EQ("abc"sv, *sv); + sv = map->value_if(s6); + ASSERT_TRUE(sv); + EXPECT_EQ("xyz"sv, *sv); + sv = map->value_if(s7); + ASSERT_TRUE(sv); + EXPECT_EQ("127.0.0.1"sv, *sv); + sv = map->value_if(s8); + ASSERT_TRUE(sv); + EXPECT_EQ("ghi"sv, *sv); } TEST_F(VariantTest, stackSmash) { // make a nested list of list of lists. - int constexpr Depth = STACK_SMASH_DEPTH; + static int constexpr Depth = STACK_SMASH_DEPTH; std::string const in = std::string(Depth, 'l') + std::string(Depth, 'e'); // confirm that it fails instead of crashing @@ -430,42 +428,48 @@ TEST_F(VariantTest, boolAndIntRecast) auto const key3 = tr_quark_new("key3"sv); auto const key4 = tr_quark_new("key4"sv); - auto top = tr_variant{}; - tr_variantInitDict(&top, 10); - tr_variantDictAddBool(&top, key1, false); - tr_variantDictAddBool(&top, key2, 0); // NOLINT modernize-use-bool-literals - tr_variantDictAddInt(&top, key3, true); // NOLINT readability-implicit-bool-conversion - tr_variantDictAddInt(&top, key4, 1); + auto top = tr_variant::make_map(4U); + auto* map = top.get_if(); + map->try_emplace(key1, false); + map->try_emplace(key2, 0); + map->try_emplace(key3, true); + map->try_emplace(key4, 1); // confirm we can read both bools and ints as bools - auto b = bool{}; - EXPECT_TRUE(tr_variantDictFindBool(&top, key1, &b)); - EXPECT_FALSE(b); - EXPECT_TRUE(tr_variantDictFindBool(&top, key2, &b)); - EXPECT_FALSE(b); - EXPECT_TRUE(tr_variantDictFindBool(&top, key3, &b)); - EXPECT_TRUE(b); - EXPECT_TRUE(tr_variantDictFindBool(&top, key4, &b)); - EXPECT_TRUE(b); + auto b = map->value_if(key1); + ASSERT_TRUE(b); + EXPECT_FALSE(*b); + b = map->value_if(key2); + ASSERT_TRUE(b); + EXPECT_FALSE(*b); + b = map->value_if(key3); + ASSERT_TRUE(b); + EXPECT_TRUE(*b); + b = map->value_if(key4); + ASSERT_TRUE(b); + EXPECT_TRUE(*b); // confirm we can read both bools and ints as ints - auto i = int64_t{}; - EXPECT_TRUE(tr_variantDictFindInt(&top, key1, &i)); - EXPECT_EQ(0, i); - EXPECT_TRUE(tr_variantDictFindInt(&top, key2, &i)); - EXPECT_EQ(0, i); - EXPECT_TRUE(tr_variantDictFindInt(&top, key3, &i)); - EXPECT_NE(0, i); - EXPECT_TRUE(tr_variantDictFindInt(&top, key4, &i)); - EXPECT_NE(0, i); + auto i = map->value_if(key1); + ASSERT_TRUE(i); + EXPECT_EQ(0, *i); + i = map->value_if(key2); + ASSERT_TRUE(i); + EXPECT_EQ(0, *i); + i = map->value_if(key3); + ASSERT_TRUE(i); + EXPECT_NE(0, *i); + i = map->value_if(key4); + ASSERT_TRUE(i); + EXPECT_NE(0, *i); } TEST_F(VariantTest, dictFindType) { - auto constexpr ExpectedStr = "this-is-a-string"sv; - auto constexpr ExpectedBool = true; - auto constexpr ExpectedInt = 1234; - auto constexpr ExpectedReal = 0.3; + static auto constexpr ExpectedStr = "this-is-a-string"sv; + static auto constexpr ExpectedBool = true; + static auto constexpr ExpectedInt = 1234; + static auto constexpr ExpectedReal = 0.3; auto const key_bool = tr_quark_new("this-is-a-bool"sv); auto const key_real = tr_quark_new("this-is-a-real"sv); @@ -474,50 +478,50 @@ TEST_F(VariantTest, dictFindType) auto const key_unknown = tr_quark_new("this-is-a-missing-entry"sv); // populate a dict - tr_variant top; - tr_variantInitDict(&top, 0); - tr_variantDictAddBool(&top, key_bool, ExpectedBool); - tr_variantDictAddInt(&top, key_int, ExpectedInt); - tr_variantDictAddReal(&top, key_real, ExpectedReal); - tr_variantDictAddStr(&top, key_str, ExpectedStr.data()); + auto top = tr_variant::make_map(4U); + auto* map = top.get_if(); + map->try_emplace(key_bool, ExpectedBool); + map->try_emplace(key_int, ExpectedInt); + map->try_emplace(key_real, ExpectedReal); + map->try_emplace(key_str, ExpectedStr); // look up the keys as strings - auto sv = std::string_view{}; - EXPECT_FALSE(tr_variantDictFindStrView(&top, key_bool, &sv)); - EXPECT_FALSE(tr_variantDictFindStrView(&top, key_real, &sv)); - EXPECT_FALSE(tr_variantDictFindStrView(&top, key_int, &sv)); - EXPECT_TRUE(tr_variantDictFindStrView(&top, key_str, &sv)); - EXPECT_EQ(ExpectedStr, sv); - EXPECT_TRUE(tr_variantDictFindStrView(&top, key_str, &sv)); - EXPECT_EQ(ExpectedStr, sv); - EXPECT_FALSE(tr_variantDictFindStrView(&top, key_unknown, &sv)); - EXPECT_FALSE(tr_variantDictFindStrView(&top, key_unknown, &sv)); + EXPECT_FALSE(map->value_if(key_bool)); + EXPECT_FALSE(map->value_if(key_real)); + EXPECT_FALSE(map->value_if(key_int)); + auto sv = map->value_if(key_str); + ASSERT_TRUE(sv); + EXPECT_EQ(ExpectedStr, *sv); + EXPECT_FALSE(map->value_if(key_unknown)); // look up the keys as bools - auto b = bool{}; - EXPECT_FALSE(tr_variantDictFindBool(&top, key_int, &b)); - EXPECT_FALSE(tr_variantDictFindBool(&top, key_real, &b)); - EXPECT_FALSE(tr_variantDictFindBool(&top, key_str, &b)); - EXPECT_TRUE(tr_variantDictFindBool(&top, key_bool, &b)); + EXPECT_FALSE(map->value_if(key_int)); + EXPECT_FALSE(map->value_if(key_real)); + EXPECT_FALSE(map->value_if(key_str)); + auto b = map->value_if(key_bool); + ASSERT_TRUE(b); EXPECT_EQ(ExpectedBool, b); + EXPECT_FALSE(map->value_if(key_unknown)); // look up the keys as doubles - auto d = double{}; - EXPECT_FALSE(tr_variantDictFindReal(&top, key_bool, &d)); - EXPECT_TRUE(tr_variantDictFindReal(&top, key_int, &d)); - EXPECT_EQ(ExpectedInt, std::lrint(d)); - EXPECT_FALSE(tr_variantDictFindReal(&top, key_str, &d)); - EXPECT_TRUE(tr_variantDictFindReal(&top, key_real, &d)); - EXPECT_EQ(std::lrint(ExpectedReal * 100), std::lrint(d * 100)); + EXPECT_FALSE(map->value_if(key_bool)); + auto d = map->value_if(key_int); + ASSERT_TRUE(d); + EXPECT_EQ(static_cast(ExpectedInt), *d); + EXPECT_FALSE(map->value_if(key_str)); + d = map->value_if(key_real); + ASSERT_TRUE(d); + EXPECT_EQ(ExpectedReal, *d); // look up the keys as ints - auto i = int64_t{}; - EXPECT_TRUE(tr_variantDictFindInt(&top, key_bool, &i)); - EXPECT_EQ(ExpectedBool ? 1 : 0, i); - EXPECT_FALSE(tr_variantDictFindInt(&top, key_real, &i)); - EXPECT_FALSE(tr_variantDictFindInt(&top, key_str, &i)); - EXPECT_TRUE(tr_variantDictFindInt(&top, key_int, &i)); - EXPECT_EQ(ExpectedInt, i); + auto i = map->value_if(key_bool); + ASSERT_TRUE(i); + EXPECT_EQ(ExpectedBool ? 1 : 0, *i); + EXPECT_FALSE(map->value_if(key_real)); + EXPECT_FALSE(map->value_if(key_str)); + i = map->value_if(key_int); + ASSERT_TRUE(i); + EXPECT_EQ(ExpectedInt, *i); } TEST_F(VariantTest, variantFromBufFuzz)