X-Git-Url: http://plrg.eecs.uci.edu/git/?p=folly.git;a=blobdiff_plain;f=folly%2Ftest%2FMapUtilTest.cpp;h=7ef13f718fcf757e50fc2e7a202bcbb118cabc01;hp=f6d6902f7a6a1a160b3724f8f83fbfaddbae760d;hb=5a07e203d79324b68d69f294fa38e43b9671e9b1;hpb=f0901aec9160175eab49586f02539536a5d807fb diff --git a/folly/test/MapUtilTest.cpp b/folly/test/MapUtilTest.cpp index f6d6902f..7ef13f71 100644 --- a/folly/test/MapUtilTest.cpp +++ b/folly/test/MapUtilTest.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2015 Facebook, Inc. + * Copyright 2017 Facebook, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,8 +16,12 @@ #include +#include #include -#include +#include + +#include +#include using namespace folly; @@ -29,11 +33,26 @@ TEST(MapUtil, get_default) { EXPECT_EQ(0, get_default(m, 3)); } +TEST(MapUtil, get_default_function) { + std::map m; + m[1] = 2; + EXPECT_EQ(2, get_default(m, 1, [] { return 42; })); + EXPECT_EQ(42, get_default(m, 2, [] { return 42; })); + EXPECT_EQ(0, get_default(m, 3)); +} + TEST(MapUtil, get_or_throw) { std::map m; m[1] = 2; EXPECT_EQ(2, get_or_throw(m, 1)); EXPECT_THROW(get_or_throw(m, 2), std::out_of_range); + EXPECT_EQ(&m[1], &get_or_throw(m, 1)); + get_or_throw(m, 1) = 3; + EXPECT_EQ(3, get_or_throw(m, 1)); + const auto& cm = m; + EXPECT_EQ(&m[1], &get_or_throw(cm, 1)); + EXPECT_EQ(3, get_or_throw(cm, 1)); + EXPECT_THROW(get_or_throw(cm, 2), std::out_of_range); } TEST(MapUtil, get_or_throw_specified) { @@ -46,9 +65,9 @@ TEST(MapUtil, get_or_throw_specified) { TEST(MapUtil, get_optional) { std::map m; m[1] = 2; - EXPECT_TRUE(get_optional(m, 1)); + EXPECT_TRUE(get_optional(m, 1).hasValue()); EXPECT_EQ(2, get_optional(m, 1).value()); - EXPECT_FALSE(get_optional(m, 2)); + EXPECT_FALSE(get_optional(m, 2).hasValue()); } TEST(MapUtil, get_ref_default) { @@ -57,6 +76,21 @@ TEST(MapUtil, get_ref_default) { const int i = 42; EXPECT_EQ(2, get_ref_default(m, 1, i)); EXPECT_EQ(42, get_ref_default(m, 2, i)); + EXPECT_EQ(std::addressof(i), std::addressof(get_ref_default(m, 2, i))); +} + +TEST(MapUtil, get_ref_default_function) { + std::map m; + m[1] = 2; + const int i = 42; + EXPECT_EQ(2, get_ref_default(m, 1, [&i]() -> const int& { return i; })); + EXPECT_EQ(42, get_ref_default(m, 2, [&i]() -> const int& { return i; })); + EXPECT_EQ( + std::addressof(i), + std::addressof( + get_ref_default(m, 2, [&i]() -> const int& { return i; }))); + // statically disallowed: + // get_ref_default(m, 2, [] { return 7; }); } TEST(MapUtil, get_ptr) { @@ -67,3 +101,198 @@ TEST(MapUtil, get_ptr) { *get_ptr(m, 1) = 4; EXPECT_EQ(4, m.at(1)); } + +TEST(MapUtil, get_ptr_path_simple) { + using std::map; + map>>> m{{1, {{2, {{3, {{4, 5}}}}}}}}; + EXPECT_EQ(5, *get_ptr(m, 1, 2, 3, 4)); + EXPECT_TRUE(get_ptr(m, 1, 2, 3, 4)); + EXPECT_FALSE(get_ptr(m, 1, 2, 3, 0)); + EXPECT_TRUE(get_ptr(m, 1, 2, 3)); + EXPECT_FALSE(get_ptr(m, 1, 2, 0)); + EXPECT_TRUE(get_ptr(m, 1, 2)); + EXPECT_FALSE(get_ptr(m, 1, 0)); + EXPECT_TRUE(get_ptr(m, 1)); + EXPECT_FALSE(get_ptr(m, 0)); + const auto& cm = m; + ++*get_ptr(m, 1, 2, 3, 4); + EXPECT_EQ(6, *get_ptr(cm, 1, 2, 3, 4)); + EXPECT_TRUE(get_ptr(cm, 1, 2, 3, 4)); + EXPECT_FALSE(get_ptr(cm, 1, 2, 3, 0)); +} + +TEST(MapUtil, get_ptr_path_mixed) { + using std::map; + using std::unordered_map; + using std::string; + unordered_map>> m{{"a", {{1, {{"b", 7}}}}}}; + EXPECT_EQ(7, *get_ptr(m, "a", 1, "b")); + EXPECT_TRUE(get_ptr(m, "a", 1, "b")); + EXPECT_FALSE(get_ptr(m, "b", 1, "b")); + EXPECT_FALSE(get_ptr(m, "a", 2, "b")); + EXPECT_FALSE(get_ptr(m, "a", 1, "c")); + EXPECT_TRUE(get_ptr(m, "a", 1, "b")); + EXPECT_TRUE(get_ptr(m, "a", 1)); + EXPECT_TRUE(get_ptr(m, "a")); + const auto& cm = m; + ++*get_ptr(m, "a", 1, "b"); + EXPECT_EQ(8, *get_ptr(cm, "a", 1, "b")); + EXPECT_TRUE(get_ptr(cm, "a", 1, "b")); + EXPECT_FALSE(get_ptr(cm, "b", 1, "b")); +} + +namespace { +template +struct element_type { + using type = typename std::decay::type; +}; + +template +struct element_type { + using type = T; +}; + +template +using element_type_t = typename element_type::type; + +template +struct Compiles : std::false_type {}; + +template +struct Compiles< + T, + void_t>>(), + std::declval(), + std::declval()))>> : std::true_type {}; +} // namespace + +TEST(MapUtil, get_default_temporary) { + EXPECT_TRUE(Compiles::value); + EXPECT_TRUE(Compiles::value); + EXPECT_FALSE(Compiles::value); + EXPECT_FALSE(Compiles::value); + + EXPECT_TRUE(Compiles::value); + EXPECT_TRUE(Compiles::value); + EXPECT_FALSE(Compiles::value); +} + +TEST(MapUtil, get_default_path) { + using std::map; + map> m; + m[4][2] = 42; + EXPECT_EQ(42, get_default(m, 4, 2, 42)); + EXPECT_EQ(42, get_default(m, 1, 3, 42)); +} + +TEST(MapUtil, get_default_path_mixed) { + using std::map; + using std::unordered_map; + using std::string; + map> m; + int key1 = 42; + const string key2 = "hello"; + constexpr StringPiece value = "world"; + constexpr StringPiece dflt = "default"; + m[key1][key2] = value; + EXPECT_EQ(value, get_default(m, 42, key2, dflt)); + EXPECT_EQ(value, get_default(m, key1, "hello", dflt)); + EXPECT_EQ(dflt, get_default(m, 0, key2, dflt)); + EXPECT_EQ(dflt, get_default(m, key1, "bad", "default")); +} + +TEST(MapUtil, get_ref_default_path) { + using std::map; + map> m; + m[4][2] = 42; + const int dflt = 13; + EXPECT_EQ(42, get_ref_default(m, 4, 2, dflt)); + EXPECT_EQ(dflt, get_ref_default(m, 1, 3, dflt)); +} + +TEST(MapUtil, get_ref_default_path_mixed) { + using std::map; + using std::unordered_map; + using std::string; + map> m; + int key1 = 42; + const string key2 = "hello"; + constexpr StringPiece value = "world"; + constexpr StringPiece dflt = "default"; + m[key1][key2] = value; + EXPECT_EQ(value, get_ref_default(m, 42, key2, dflt)); + EXPECT_EQ(value, get_ref_default(m, key1, "hello", dflt)); + EXPECT_EQ(dflt, get_ref_default(m, 0, key2, dflt)); + EXPECT_EQ(dflt, get_ref_default(m, key1, "bad", dflt)); +} + +namespace { +template +struct GetRefDefaultPathCompiles : std::false_type {}; + +template +struct GetRefDefaultPathCompiles< + T, + void_t>>>(), + std::declval(), + std::declval(), + std::declval()))>> : std::true_type {}; +} // namespace + +TEST(MapUtil, get_ref_default_path_temporary) { + EXPECT_TRUE(GetRefDefaultPathCompiles::value); + EXPECT_TRUE(GetRefDefaultPathCompiles::value); + EXPECT_FALSE(GetRefDefaultPathCompiles::value); + EXPECT_FALSE(GetRefDefaultPathCompiles::value); +} + +namespace { + +class TestConstruction { + public: + TestConstruction() { + EXPECT_TRUE(false); + } + TestConstruction(TestConstruction&&) { + EXPECT_TRUE(false); + } + TestConstruction(const TestConstruction&) { + EXPECT_TRUE(false); + } + + explicit TestConstruction(std::string&& string) + : string_{std::move(string)} {} + explicit TestConstruction(int&& integer) : integer_{integer} {} + + TestConstruction& operator=(const TestConstruction&) = delete; + TestConstruction& operator=(TestConstruction&&) = delete; + + int integer_{}; + std::string string_{}; +}; + +} // namespace + +TEST(MapUtil, test_get_default_deferred_construction) { + auto map = std::unordered_map{}; + map.emplace( + std::piecewise_construct, + std::forward_as_tuple(1), + std::forward_as_tuple(1)); + + EXPECT_EQ(map.at(1).integer_, 1); + + { + auto val = get_default(map, 0, 1); + EXPECT_EQ(val.integer_, 1); + EXPECT_EQ(val.string_, ""); + } + + { + auto val = get_default(map, 0, "something"); + EXPECT_EQ(val.integer_, 0); + EXPECT_EQ(val.string_, "something"); + } +}