get_ptr(mapOfMaps, key, key...)
[folly.git] / folly / test / MapUtilTest.cpp
1 /*
2  * Copyright 2017 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
17 #include <folly/MapUtil.h>
18
19 #include <map>
20 #include <unordered_map>
21
22 #include <folly/portability/GTest.h>
23
24 using namespace folly;
25
26 TEST(MapUtil, get_default) {
27   std::map<int, int> m;
28   m[1] = 2;
29   EXPECT_EQ(2, get_default(m, 1, 42));
30   EXPECT_EQ(42, get_default(m, 2, 42));
31   EXPECT_EQ(0, get_default(m, 3));
32 }
33
34 TEST(MapUtil, get_default_function) {
35   std::map<int, int> m;
36   m[1] = 2;
37   EXPECT_EQ(2, get_default(m, 1, [] { return 42; }));
38   EXPECT_EQ(42, get_default(m, 2, [] { return 42; }));
39   EXPECT_EQ(0, get_default(m, 3));
40 }
41
42 TEST(MapUtil, get_or_throw) {
43   std::map<int, int> m;
44   m[1] = 2;
45   EXPECT_EQ(2, get_or_throw(m, 1));
46   EXPECT_THROW(get_or_throw(m, 2), std::out_of_range);
47   EXPECT_EQ(&m[1], &get_or_throw(m, 1));
48   get_or_throw(m, 1) = 3;
49   EXPECT_EQ(3, get_or_throw(m, 1));
50   const auto& cm = m;
51   EXPECT_EQ(&m[1], &get_or_throw(cm, 1));
52   EXPECT_EQ(3, get_or_throw(cm, 1));
53   EXPECT_THROW(get_or_throw(cm, 2), std::out_of_range);
54 }
55
56 TEST(MapUtil, get_or_throw_specified) {
57   std::map<int, int> m;
58   m[1] = 2;
59   EXPECT_EQ(2, get_or_throw<std::runtime_error>(m, 1));
60   EXPECT_THROW(get_or_throw<std::runtime_error>(m, 2), std::runtime_error);
61 }
62
63 TEST(MapUtil, get_optional) {
64   std::map<int, int> m;
65   m[1] = 2;
66   EXPECT_TRUE(get_optional(m, 1).hasValue());
67   EXPECT_EQ(2, get_optional(m, 1).value());
68   EXPECT_FALSE(get_optional(m, 2).hasValue());
69 }
70
71 TEST(MapUtil, get_ref_default) {
72   std::map<int, int> m;
73   m[1] = 2;
74   const int i = 42;
75   EXPECT_EQ(2, get_ref_default(m, 1, i));
76   EXPECT_EQ(42, get_ref_default(m, 2, i));
77   EXPECT_EQ(std::addressof(i), std::addressof(get_ref_default(m, 2, i)));
78 }
79
80 TEST(MapUtil, get_ref_default_function) {
81   std::map<int, int> m;
82   m[1] = 2;
83   const int i = 42;
84   EXPECT_EQ(2, get_ref_default(m, 1, [&i]() -> const int& { return i; }));
85   EXPECT_EQ(42, get_ref_default(m, 2, [&i]() -> const int& { return i; }));
86   EXPECT_EQ(
87       std::addressof(i),
88       std::addressof(
89           get_ref_default(m, 2, [&i]() -> const int& { return i; })));
90   // statically disallowed:
91   // get_ref_default(m, 2, [] { return 7; });
92 }
93
94 TEST(MapUtil, get_ptr) {
95   std::map<int, int> m;
96   m[1] = 2;
97   EXPECT_EQ(2, *get_ptr(m, 1));
98   EXPECT_TRUE(get_ptr(m, 2) == nullptr);
99   *get_ptr(m, 1) = 4;
100   EXPECT_EQ(4, m.at(1));
101 }
102
103 TEST(MapUtil, get_ptr_path_simple) {
104   using std::map;
105   map<int, map<int, map<int, map<int, int>>>> m{{1, {{2, {{3, {{4, 5}}}}}}}};
106   EXPECT_EQ(5, *get_ptr(m, 1, 2, 3, 4));
107   EXPECT_TRUE(get_ptr(m, 1, 2, 3, 4));
108   EXPECT_FALSE(get_ptr(m, 1, 2, 3, 0));
109   EXPECT_TRUE(get_ptr(m, 1, 2, 3));
110   EXPECT_FALSE(get_ptr(m, 1, 2, 0));
111   EXPECT_TRUE(get_ptr(m, 1, 2));
112   EXPECT_FALSE(get_ptr(m, 1, 0));
113   EXPECT_TRUE(get_ptr(m, 1));
114   EXPECT_FALSE(get_ptr(m, 0));
115   const auto& cm = m;
116   ++*get_ptr(m, 1, 2, 3, 4);
117   EXPECT_EQ(6, *get_ptr(cm, 1, 2, 3, 4));
118   EXPECT_TRUE(get_ptr(cm, 1, 2, 3, 4));
119   EXPECT_FALSE(get_ptr(cm, 1, 2, 3, 0));
120 }
121
122 TEST(MapUtil, get_ptr_path_mixed) {
123   using std::map;
124   using std::unordered_map;
125   using std::string;
126   unordered_map<string, map<int, map<string, int>>> m{{"a", {{1, {{"b", 7}}}}}};
127   EXPECT_EQ(7, *get_ptr(m, "a", 1, "b"));
128   EXPECT_TRUE(get_ptr(m, "a", 1, "b"));
129   EXPECT_FALSE(get_ptr(m, "b", 1, "b"));
130   EXPECT_FALSE(get_ptr(m, "a", 2, "b"));
131   EXPECT_FALSE(get_ptr(m, "a", 1, "c"));
132   EXPECT_TRUE(get_ptr(m, "a", 1, "b"));
133   EXPECT_TRUE(get_ptr(m, "a", 1));
134   EXPECT_TRUE(get_ptr(m, "a"));
135   const auto& cm = m;
136   ++*get_ptr(m, "a", 1, "b");
137   EXPECT_EQ(8, *get_ptr(cm, "a", 1, "b"));
138   EXPECT_TRUE(get_ptr(cm, "a", 1, "b"));
139   EXPECT_FALSE(get_ptr(cm, "b", 1, "b"));
140 }