• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2018 The Abseil Authors.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //      https://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #ifndef ABSL_CONTAINER_INTERNAL_UNORDERED_MAP_MODIFIERS_TEST_H_
16 #define ABSL_CONTAINER_INTERNAL_UNORDERED_MAP_MODIFIERS_TEST_H_
17 
18 #include <memory>
19 
20 #include "gmock/gmock.h"
21 #include "gtest/gtest.h"
22 #include "absl/container/internal/hash_generator_testing.h"
23 #include "absl/container/internal/hash_policy_testing.h"
24 
25 namespace absl {
26 ABSL_NAMESPACE_BEGIN
27 namespace container_internal {
28 
29 template <class UnordMap>
30 class ModifiersTest : public ::testing::Test {};
31 
32 TYPED_TEST_SUITE_P(ModifiersTest);
33 
TYPED_TEST_P(ModifiersTest,Clear)34 TYPED_TEST_P(ModifiersTest, Clear) {
35   using T = hash_internal::GeneratedType<TypeParam>;
36   std::vector<T> values;
37   std::generate_n(std::back_inserter(values), 10,
38                   hash_internal::Generator<T>());
39   TypeParam m(values.begin(), values.end());
40   ASSERT_THAT(items(m), ::testing::UnorderedElementsAreArray(values));
41   m.clear();
42   EXPECT_THAT(items(m), ::testing::UnorderedElementsAre());
43   EXPECT_TRUE(m.empty());
44 }
45 
TYPED_TEST_P(ModifiersTest,Insert)46 TYPED_TEST_P(ModifiersTest, Insert) {
47   using T = hash_internal::GeneratedType<TypeParam>;
48   using V = typename TypeParam::mapped_type;
49   T val = hash_internal::Generator<T>()();
50   TypeParam m;
51   auto p = m.insert(val);
52   EXPECT_TRUE(p.second);
53   EXPECT_EQ(val, *p.first);
54   T val2 = {val.first, hash_internal::Generator<V>()()};
55   p = m.insert(val2);
56   EXPECT_FALSE(p.second);
57   EXPECT_EQ(val, *p.first);
58 }
59 
TYPED_TEST_P(ModifiersTest,InsertHint)60 TYPED_TEST_P(ModifiersTest, InsertHint) {
61   using T = hash_internal::GeneratedType<TypeParam>;
62   using V = typename TypeParam::mapped_type;
63   T val = hash_internal::Generator<T>()();
64   TypeParam m;
65   auto it = m.insert(m.end(), val);
66   EXPECT_TRUE(it != m.end());
67   EXPECT_EQ(val, *it);
68   T val2 = {val.first, hash_internal::Generator<V>()()};
69   it = m.insert(it, val2);
70   EXPECT_TRUE(it != m.end());
71   EXPECT_EQ(val, *it);
72 }
73 
TYPED_TEST_P(ModifiersTest,InsertRange)74 TYPED_TEST_P(ModifiersTest, InsertRange) {
75   using T = hash_internal::GeneratedType<TypeParam>;
76   std::vector<T> values;
77   std::generate_n(std::back_inserter(values), 10,
78                   hash_internal::Generator<T>());
79   TypeParam m;
80   m.insert(values.begin(), values.end());
81   ASSERT_THAT(items(m), ::testing::UnorderedElementsAreArray(values));
82 }
83 
TYPED_TEST_P(ModifiersTest,InsertOrAssign)84 TYPED_TEST_P(ModifiersTest, InsertOrAssign) {
85 #ifdef UNORDERED_MAP_CXX17
86   using std::get;
87   using K = typename TypeParam::key_type;
88   using V = typename TypeParam::mapped_type;
89   K k = hash_internal::Generator<K>()();
90   V val = hash_internal::Generator<V>()();
91   TypeParam m;
92   auto p = m.insert_or_assign(k, val);
93   EXPECT_TRUE(p.second);
94   EXPECT_EQ(k, get<0>(*p.first));
95   EXPECT_EQ(val, get<1>(*p.first));
96   V val2 = hash_internal::Generator<V>()();
97   p = m.insert_or_assign(k, val2);
98   EXPECT_FALSE(p.second);
99   EXPECT_EQ(k, get<0>(*p.first));
100   EXPECT_EQ(val2, get<1>(*p.first));
101 #endif
102 }
103 
TYPED_TEST_P(ModifiersTest,InsertOrAssignHint)104 TYPED_TEST_P(ModifiersTest, InsertOrAssignHint) {
105 #ifdef UNORDERED_MAP_CXX17
106   using std::get;
107   using K = typename TypeParam::key_type;
108   using V = typename TypeParam::mapped_type;
109   K k = hash_internal::Generator<K>()();
110   V val = hash_internal::Generator<V>()();
111   TypeParam m;
112   auto it = m.insert_or_assign(m.end(), k, val);
113   EXPECT_TRUE(it != m.end());
114   EXPECT_EQ(k, get<0>(*it));
115   EXPECT_EQ(val, get<1>(*it));
116   V val2 = hash_internal::Generator<V>()();
117   it = m.insert_or_assign(it, k, val2);
118   EXPECT_EQ(k, get<0>(*it));
119   EXPECT_EQ(val2, get<1>(*it));
120 #endif
121 }
122 
TYPED_TEST_P(ModifiersTest,Emplace)123 TYPED_TEST_P(ModifiersTest, Emplace) {
124   using T = hash_internal::GeneratedType<TypeParam>;
125   using V = typename TypeParam::mapped_type;
126   T val = hash_internal::Generator<T>()();
127   TypeParam m;
128   // TODO(alkis): We need a way to run emplace in a more meaningful way. Perhaps
129   // with test traits/policy.
130   auto p = m.emplace(val);
131   EXPECT_TRUE(p.second);
132   EXPECT_EQ(val, *p.first);
133   T val2 = {val.first, hash_internal::Generator<V>()()};
134   p = m.emplace(val2);
135   EXPECT_FALSE(p.second);
136   EXPECT_EQ(val, *p.first);
137 }
138 
TYPED_TEST_P(ModifiersTest,EmplaceHint)139 TYPED_TEST_P(ModifiersTest, EmplaceHint) {
140   using T = hash_internal::GeneratedType<TypeParam>;
141   using V = typename TypeParam::mapped_type;
142   T val = hash_internal::Generator<T>()();
143   TypeParam m;
144   // TODO(alkis): We need a way to run emplace in a more meaningful way. Perhaps
145   // with test traits/policy.
146   auto it = m.emplace_hint(m.end(), val);
147   EXPECT_EQ(val, *it);
148   T val2 = {val.first, hash_internal::Generator<V>()()};
149   it = m.emplace_hint(it, val2);
150   EXPECT_EQ(val, *it);
151 }
152 
TYPED_TEST_P(ModifiersTest,TryEmplace)153 TYPED_TEST_P(ModifiersTest, TryEmplace) {
154 #ifdef UNORDERED_MAP_CXX17
155   using T = hash_internal::GeneratedType<TypeParam>;
156   using V = typename TypeParam::mapped_type;
157   T val = hash_internal::Generator<T>()();
158   TypeParam m;
159   // TODO(alkis): We need a way to run emplace in a more meaningful way. Perhaps
160   // with test traits/policy.
161   auto p = m.try_emplace(val.first, val.second);
162   EXPECT_TRUE(p.second);
163   EXPECT_EQ(val, *p.first);
164   T val2 = {val.first, hash_internal::Generator<V>()()};
165   p = m.try_emplace(val2.first, val2.second);
166   EXPECT_FALSE(p.second);
167   EXPECT_EQ(val, *p.first);
168 #endif
169 }
170 
TYPED_TEST_P(ModifiersTest,TryEmplaceHint)171 TYPED_TEST_P(ModifiersTest, TryEmplaceHint) {
172 #ifdef UNORDERED_MAP_CXX17
173   using T = hash_internal::GeneratedType<TypeParam>;
174   using V = typename TypeParam::mapped_type;
175   T val = hash_internal::Generator<T>()();
176   TypeParam m;
177   // TODO(alkis): We need a way to run emplace in a more meaningful way. Perhaps
178   // with test traits/policy.
179   auto it = m.try_emplace(m.end(), val.first, val.second);
180   EXPECT_EQ(val, *it);
181   T val2 = {val.first, hash_internal::Generator<V>()()};
182   it = m.try_emplace(it, val2.first, val2.second);
183   EXPECT_EQ(val, *it);
184 #endif
185 }
186 
187 template <class V>
188 using IfNotVoid = typename std::enable_if<!std::is_void<V>::value, V>::type;
189 
190 // In openmap we chose not to return the iterator from erase because that's
191 // more expensive. As such we adapt erase to return an iterator here.
192 struct EraseFirst {
193   template <class Map>
194   auto operator()(Map* m, int) const
195       -> IfNotVoid<decltype(m->erase(m->begin()))> {
196     return m->erase(m->begin());
197   }
198   template <class Map>
operatorEraseFirst199   typename Map::iterator operator()(Map* m, ...) const {
200     auto it = m->begin();
201     m->erase(it++);
202     return it;
203   }
204 };
205 
TYPED_TEST_P(ModifiersTest,Erase)206 TYPED_TEST_P(ModifiersTest, Erase) {
207   using T = hash_internal::GeneratedType<TypeParam>;
208   using std::get;
209   std::vector<T> values;
210   std::generate_n(std::back_inserter(values), 10,
211                   hash_internal::Generator<T>());
212   TypeParam m(values.begin(), values.end());
213   ASSERT_THAT(items(m), ::testing::UnorderedElementsAreArray(values));
214   auto& first = *m.begin();
215   std::vector<T> values2;
216   for (const auto& val : values)
217     if (get<0>(val) != get<0>(first)) values2.push_back(val);
218   auto it = EraseFirst()(&m, 0);
219   ASSERT_TRUE(it != m.end());
220   EXPECT_EQ(1, std::count(values2.begin(), values2.end(), *it));
221   EXPECT_THAT(items(m), ::testing::UnorderedElementsAreArray(values2.begin(),
222                                                              values2.end()));
223 }
224 
TYPED_TEST_P(ModifiersTest,EraseRange)225 TYPED_TEST_P(ModifiersTest, EraseRange) {
226   using T = hash_internal::GeneratedType<TypeParam>;
227   std::vector<T> values;
228   std::generate_n(std::back_inserter(values), 10,
229                   hash_internal::Generator<T>());
230   TypeParam m(values.begin(), values.end());
231   ASSERT_THAT(items(m), ::testing::UnorderedElementsAreArray(values));
232   auto it = m.erase(m.begin(), m.end());
233   EXPECT_THAT(items(m), ::testing::UnorderedElementsAre());
234   EXPECT_TRUE(it == m.end());
235 }
236 
TYPED_TEST_P(ModifiersTest,EraseKey)237 TYPED_TEST_P(ModifiersTest, EraseKey) {
238   using T = hash_internal::GeneratedType<TypeParam>;
239   std::vector<T> values;
240   std::generate_n(std::back_inserter(values), 10,
241                   hash_internal::Generator<T>());
242   TypeParam m(values.begin(), values.end());
243   ASSERT_THAT(items(m), ::testing::UnorderedElementsAreArray(values));
244   EXPECT_EQ(1, m.erase(values[0].first));
245   EXPECT_EQ(0, std::count(m.begin(), m.end(), values[0]));
246   EXPECT_THAT(items(m), ::testing::UnorderedElementsAreArray(values.begin() + 1,
247                                                              values.end()));
248 }
249 
TYPED_TEST_P(ModifiersTest,Swap)250 TYPED_TEST_P(ModifiersTest, Swap) {
251   using T = hash_internal::GeneratedType<TypeParam>;
252   std::vector<T> v1;
253   std::vector<T> v2;
254   std::generate_n(std::back_inserter(v1), 5, hash_internal::Generator<T>());
255   std::generate_n(std::back_inserter(v2), 5, hash_internal::Generator<T>());
256   TypeParam m1(v1.begin(), v1.end());
257   TypeParam m2(v2.begin(), v2.end());
258   EXPECT_THAT(items(m1), ::testing::UnorderedElementsAreArray(v1));
259   EXPECT_THAT(items(m2), ::testing::UnorderedElementsAreArray(v2));
260   m1.swap(m2);
261   EXPECT_THAT(items(m1), ::testing::UnorderedElementsAreArray(v2));
262   EXPECT_THAT(items(m2), ::testing::UnorderedElementsAreArray(v1));
263 }
264 
265 // TODO(alkis): Write tests for extract.
266 // TODO(alkis): Write tests for merge.
267 
268 REGISTER_TYPED_TEST_CASE_P(ModifiersTest, Clear, Insert, InsertHint,
269                            InsertRange, InsertOrAssign, InsertOrAssignHint,
270                            Emplace, EmplaceHint, TryEmplace, TryEmplaceHint,
271                            Erase, EraseRange, EraseKey, Swap);
272 
273 template <typename Type>
274 struct is_unique_ptr : std::false_type {};
275 
276 template <typename Type>
277 struct is_unique_ptr<std::unique_ptr<Type>> : std::true_type {};
278 
279 template <class UnordMap>
280 class UniquePtrModifiersTest : public ::testing::Test {
281  protected:
282   UniquePtrModifiersTest() {
283     static_assert(is_unique_ptr<typename UnordMap::mapped_type>::value,
284                   "UniquePtrModifiersTyest may only be called with a "
285                   "std::unique_ptr value type.");
286   }
287 };
288 
289 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(UniquePtrModifiersTest);
290 
291 TYPED_TEST_SUITE_P(UniquePtrModifiersTest);
292 
293 // Test that we do not move from rvalue arguments if an insertion does not
294 // happen.
295 TYPED_TEST_P(UniquePtrModifiersTest, TryEmplace) {
296 #ifdef UNORDERED_MAP_CXX17
297   using T = hash_internal::GeneratedType<TypeParam>;
298   using V = typename TypeParam::mapped_type;
299   T val = hash_internal::Generator<T>()();
300   TypeParam m;
301   auto p = m.try_emplace(val.first, std::move(val.second));
302   EXPECT_TRUE(p.second);
303   // A moved from std::unique_ptr is guaranteed to be nullptr.
304   EXPECT_EQ(val.second, nullptr);
305   T val2 = {val.first, hash_internal::Generator<V>()()};
306   p = m.try_emplace(val2.first, std::move(val2.second));
307   EXPECT_FALSE(p.second);
308   EXPECT_NE(val2.second, nullptr);
309 #endif
310 }
311 
312 REGISTER_TYPED_TEST_SUITE_P(UniquePtrModifiersTest, TryEmplace);
313 
314 }  // namespace container_internal
315 ABSL_NAMESPACE_END
316 }  // namespace absl
317 
318 #endif  // ABSL_CONTAINER_INTERNAL_UNORDERED_MAP_MODIFIERS_TEST_H_
319