MapUtilTest.cpp 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325
  1. /*
  2. * Copyright 2012-present Facebook, Inc.
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. #include <folly/MapUtil.h>
  17. #include <cstddef>
  18. #include <map>
  19. #include <unordered_map>
  20. #include <folly/Traits.h>
  21. #include <folly/portability/GTest.h>
  22. using namespace folly;
  23. TEST(MapUtil, get_default) {
  24. std::map<int, int> m;
  25. m[1] = 2;
  26. EXPECT_EQ(2, get_default(m, 1, 42));
  27. EXPECT_EQ(42, get_default(m, 2, 42));
  28. EXPECT_EQ(0, get_default(m, 3));
  29. }
  30. TEST(MapUtil, get_default_function) {
  31. std::map<int, int> m;
  32. m[1] = 2;
  33. EXPECT_EQ(2, get_default(m, 1, [] { return 42; }));
  34. EXPECT_EQ(42, get_default(m, 2, [] { return 42; }));
  35. EXPECT_EQ(0, get_default(m, 3));
  36. }
  37. TEST(MapUtil, get_or_throw) {
  38. std::map<int, int> m;
  39. m[1] = 2;
  40. EXPECT_EQ(2, get_or_throw(m, 1));
  41. EXPECT_THROW(get_or_throw(m, 2), std::out_of_range);
  42. EXPECT_EQ(&m[1], &get_or_throw(m, 1));
  43. get_or_throw(m, 1) = 3;
  44. EXPECT_EQ(3, get_or_throw(m, 1));
  45. const auto& cm = m;
  46. EXPECT_EQ(&m[1], &get_or_throw(cm, 1));
  47. EXPECT_EQ(3, get_or_throw(cm, 1));
  48. EXPECT_THROW(get_or_throw(cm, 2), std::out_of_range);
  49. }
  50. TEST(MapUtil, get_or_throw_specified) {
  51. std::map<int, int> m;
  52. m[1] = 2;
  53. EXPECT_EQ(2, get_or_throw<std::runtime_error>(m, 1));
  54. EXPECT_THROW(get_or_throw<std::runtime_error>(m, 2), std::runtime_error);
  55. }
  56. TEST(MapUtil, get_optional) {
  57. std::map<int, int> m;
  58. m[1] = 2;
  59. EXPECT_TRUE(get_optional(m, 1).hasValue());
  60. EXPECT_EQ(2, get_optional(m, 1).value());
  61. EXPECT_FALSE(get_optional(m, 2).hasValue());
  62. }
  63. TEST(MapUtil, get_optional_path_simple) {
  64. using std::map;
  65. map<int, map<int, map<int, map<int, int>>>> m{{1, {{2, {{3, {{4, 5}}}}}}}};
  66. EXPECT_EQ(folly::Optional<int>(5), get_optional(m, 1, 2, 3, 4));
  67. EXPECT_TRUE(get_optional(m, 1, 2, 3, 4));
  68. EXPECT_FALSE(get_optional(m, 1, 2, 3, 0));
  69. EXPECT_TRUE(get_optional(m, 1, 2, 3));
  70. EXPECT_FALSE(get_optional(m, 1, 2, 0));
  71. EXPECT_TRUE(get_optional(m, 1, 2));
  72. EXPECT_FALSE(get_optional(m, 1, 0));
  73. EXPECT_TRUE(get_optional(m, 1));
  74. EXPECT_FALSE(get_optional(m, 0));
  75. }
  76. TEST(MapUtil, get_optional_path_mixed) {
  77. using std::map;
  78. using std::string;
  79. using std::unordered_map;
  80. unordered_map<string, map<int, map<string, int>>> m{{"a", {{1, {{"b", 2}}}}}};
  81. EXPECT_EQ(folly::Optional<int>(2), get_optional(m, "a", 1, "b"));
  82. EXPECT_TRUE(get_optional(m, "a", 1, "b"));
  83. EXPECT_FALSE(get_optional(m, "b", 1, "b"));
  84. EXPECT_FALSE(get_optional(m, "a", 2, "b"));
  85. EXPECT_FALSE(get_optional(m, "a", 1, "c"));
  86. EXPECT_TRUE(get_optional(m, "a", 1));
  87. EXPECT_TRUE(get_optional(m, "a"));
  88. }
  89. TEST(MapUtil, get_ref_default) {
  90. std::map<int, int> m;
  91. m[1] = 2;
  92. const int i = 42;
  93. EXPECT_EQ(2, get_ref_default(m, 1, i));
  94. EXPECT_EQ(42, get_ref_default(m, 2, i));
  95. EXPECT_EQ(std::addressof(i), std::addressof(get_ref_default(m, 2, i)));
  96. }
  97. TEST(MapUtil, get_ref_default_function) {
  98. std::map<int, int> m;
  99. m[1] = 2;
  100. const int i = 42;
  101. EXPECT_EQ(2, get_ref_default(m, 1, [&i]() -> const int& { return i; }));
  102. EXPECT_EQ(42, get_ref_default(m, 2, [&i]() -> const int& { return i; }));
  103. EXPECT_EQ(
  104. std::addressof(i),
  105. std::addressof(
  106. get_ref_default(m, 2, [&i]() -> const int& { return i; })));
  107. // statically disallowed:
  108. // get_ref_default(m, 2, [] { return 7; });
  109. }
  110. TEST(MapUtil, get_ptr) {
  111. std::map<int, int> m;
  112. m[1] = 2;
  113. EXPECT_EQ(2, *get_ptr(m, 1));
  114. EXPECT_TRUE(get_ptr(m, 2) == nullptr);
  115. *get_ptr(m, 1) = 4;
  116. EXPECT_EQ(4, m.at(1));
  117. }
  118. TEST(MapUtil, get_ptr_path_simple) {
  119. using std::map;
  120. map<int, map<int, map<int, map<int, int>>>> m{{1, {{2, {{3, {{4, 5}}}}}}}};
  121. EXPECT_EQ(5, *get_ptr(m, 1, 2, 3, 4));
  122. EXPECT_TRUE(get_ptr(m, 1, 2, 3, 4));
  123. EXPECT_FALSE(get_ptr(m, 1, 2, 3, 0));
  124. EXPECT_TRUE(get_ptr(m, 1, 2, 3));
  125. EXPECT_FALSE(get_ptr(m, 1, 2, 0));
  126. EXPECT_TRUE(get_ptr(m, 1, 2));
  127. EXPECT_FALSE(get_ptr(m, 1, 0));
  128. EXPECT_TRUE(get_ptr(m, 1));
  129. EXPECT_FALSE(get_ptr(m, 0));
  130. const auto& cm = m;
  131. ++*get_ptr(m, 1, 2, 3, 4);
  132. EXPECT_EQ(6, *get_ptr(cm, 1, 2, 3, 4));
  133. EXPECT_TRUE(get_ptr(cm, 1, 2, 3, 4));
  134. EXPECT_FALSE(get_ptr(cm, 1, 2, 3, 0));
  135. }
  136. TEST(MapUtil, get_ptr_path_mixed) {
  137. using std::map;
  138. using std::string;
  139. using std::unordered_map;
  140. unordered_map<string, map<int, map<string, int>>> m{{"a", {{1, {{"b", 7}}}}}};
  141. EXPECT_EQ(7, *get_ptr(m, "a", 1, "b"));
  142. EXPECT_TRUE(get_ptr(m, "a", 1, "b"));
  143. EXPECT_FALSE(get_ptr(m, "b", 1, "b"));
  144. EXPECT_FALSE(get_ptr(m, "a", 2, "b"));
  145. EXPECT_FALSE(get_ptr(m, "a", 1, "c"));
  146. EXPECT_TRUE(get_ptr(m, "a", 1));
  147. EXPECT_TRUE(get_ptr(m, "a"));
  148. const auto& cm = m;
  149. ++*get_ptr(m, "a", 1, "b");
  150. EXPECT_EQ(8, *get_ptr(cm, "a", 1, "b"));
  151. EXPECT_TRUE(get_ptr(cm, "a", 1, "b"));
  152. EXPECT_FALSE(get_ptr(cm, "b", 1, "b"));
  153. }
  154. namespace {
  155. template <typename T>
  156. struct element_type {
  157. using type = typename std::decay<T>::type;
  158. };
  159. template <typename T>
  160. struct element_type<T()> {
  161. using type = T;
  162. };
  163. template <typename T>
  164. using element_type_t = typename element_type<T>::type;
  165. template <typename T, typename = void>
  166. struct Compiles : std::false_type {};
  167. template <typename T>
  168. struct Compiles<
  169. T,
  170. void_t<decltype(get_ref_default(
  171. std::declval<std::map<int, element_type_t<T>>>(),
  172. std::declval<int>(),
  173. std::declval<T>()))>> : std::true_type {};
  174. } // namespace
  175. TEST(MapUtil, get_default_temporary) {
  176. EXPECT_TRUE(Compiles<const int&>::value);
  177. EXPECT_TRUE(Compiles<int&>::value);
  178. EXPECT_FALSE(Compiles<const int&&>::value);
  179. EXPECT_FALSE(Compiles<int&&>::value);
  180. EXPECT_TRUE(Compiles<const int&()>::value);
  181. EXPECT_TRUE(Compiles<int&()>::value);
  182. EXPECT_FALSE(Compiles<int()>::value);
  183. }
  184. TEST(MapUtil, get_default_path) {
  185. using std::map;
  186. map<int, map<int, int>> m;
  187. m[4][2] = 42;
  188. EXPECT_EQ(42, get_default(m, 4, 2, 42));
  189. EXPECT_EQ(42, get_default(m, 1, 3, 42));
  190. }
  191. TEST(MapUtil, get_default_path_mixed) {
  192. using std::map;
  193. using std::string;
  194. using std::unordered_map;
  195. map<int, unordered_map<string, StringPiece>> m;
  196. int key1 = 42;
  197. const string key2 = "hello";
  198. constexpr StringPiece value = "world";
  199. constexpr StringPiece dflt = "default";
  200. m[key1][key2] = value;
  201. EXPECT_EQ(value, get_default(m, 42, key2, dflt));
  202. EXPECT_EQ(value, get_default(m, key1, "hello", dflt));
  203. EXPECT_EQ(dflt, get_default(m, 0, key2, dflt));
  204. EXPECT_EQ(dflt, get_default(m, key1, "bad", "default"));
  205. }
  206. TEST(MapUtil, get_ref_default_path) {
  207. using std::map;
  208. map<int, map<int, int>> m;
  209. m[4][2] = 42;
  210. const int dflt = 13;
  211. EXPECT_EQ(42, get_ref_default(m, 4, 2, dflt));
  212. EXPECT_EQ(dflt, get_ref_default(m, 1, 3, dflt));
  213. }
  214. TEST(MapUtil, get_ref_default_path_mixed) {
  215. using std::map;
  216. using std::string;
  217. using std::unordered_map;
  218. map<int, unordered_map<string, StringPiece>> m;
  219. int key1 = 42;
  220. const string key2 = "hello";
  221. constexpr StringPiece value = "world";
  222. constexpr StringPiece dflt = "default";
  223. m[key1][key2] = value;
  224. EXPECT_EQ(value, get_ref_default(m, 42, key2, dflt));
  225. EXPECT_EQ(value, get_ref_default(m, key1, "hello", dflt));
  226. EXPECT_EQ(dflt, get_ref_default(m, 0, key2, dflt));
  227. EXPECT_EQ(dflt, get_ref_default(m, key1, "bad", dflt));
  228. }
  229. namespace {
  230. template <typename T, typename = void>
  231. struct GetRefDefaultPathCompiles : std::false_type {};
  232. template <typename T>
  233. struct GetRefDefaultPathCompiles<
  234. T,
  235. void_t<decltype(get_ref_default(
  236. std::declval<std::map<int, std::map<int, element_type_t<T>>>>(),
  237. std::declval<int>(),
  238. std::declval<int>(),
  239. std::declval<T>()))>> : std::true_type {};
  240. } // namespace
  241. TEST(MapUtil, get_ref_default_path_temporary) {
  242. EXPECT_TRUE(GetRefDefaultPathCompiles<const int&>::value);
  243. EXPECT_TRUE(GetRefDefaultPathCompiles<int&>::value);
  244. EXPECT_FALSE(GetRefDefaultPathCompiles<const int&&>::value);
  245. EXPECT_FALSE(GetRefDefaultPathCompiles<int&&>::value);
  246. }
  247. namespace {
  248. class TestConstruction {
  249. public:
  250. TestConstruction() {
  251. EXPECT_TRUE(false);
  252. }
  253. TestConstruction(TestConstruction&&) {
  254. EXPECT_TRUE(false);
  255. }
  256. TestConstruction(const TestConstruction&) {
  257. EXPECT_TRUE(false);
  258. }
  259. explicit TestConstruction(std::string&& string)
  260. : string_{std::move(string)} {}
  261. explicit TestConstruction(int&& integer) : integer_{integer} {}
  262. TestConstruction& operator=(const TestConstruction&) = delete;
  263. TestConstruction& operator=(TestConstruction&&) = delete;
  264. int integer_{};
  265. std::string string_{};
  266. };
  267. } // namespace
  268. TEST(MapUtil, test_get_default_deferred_construction) {
  269. auto map = std::unordered_map<int, TestConstruction>{};
  270. map.emplace(
  271. std::piecewise_construct,
  272. std::forward_as_tuple(1),
  273. std::forward_as_tuple(1));
  274. EXPECT_EQ(map.at(1).integer_, 1);
  275. {
  276. auto val = get_default(map, 0, 1);
  277. EXPECT_EQ(val.integer_, 1);
  278. EXPECT_EQ(val.string_, "");
  279. }
  280. {
  281. auto val = get_default(map, 0, "something");
  282. EXPECT_EQ(val.integer_, 0);
  283. EXPECT_EQ(val.string_, "something");
  284. }
  285. }