1 // Copyright 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "base/stl_util.h"
9 #include <forward_list>
11 #include <initializer_list>
19 #include <type_traits>
20 #include <unordered_map>
21 #include <unordered_set>
24 #include "base/containers/cxx20_erase_vector.h"
25 #include "base/containers/queue.h"
26 #include "testing/gmock/include/gmock/gmock.h"
27 #include "testing/gtest/include/gtest/gtest.h"
28 #include "third_party/abseil-cpp/absl/types/optional.h"
32 using ::testing::IsNull;
33 using ::testing::Pair;
35 template <typename Container>
36 void RunConstCastIteratorTest() {
40 Container c = {1, 2, 3, 4, 5};
41 auto c_it = std::next(cbegin(c), 3);
42 auto it = base::ConstCastIterator(c, c_it);
43 static_assert(std::is_same<decltype(cbegin(std::declval<Container&>())),
44 decltype(c_it)>::value,
45 "c_it is not a constant iterator.");
46 static_assert(std::is_same<decltype(begin(std::declval<Container&>())),
48 "it is not a iterator.");
50 // Const casting the iterator should not modify the underlying container.
51 Container other = {1, 2, 3, 4, 5};
52 EXPECT_THAT(c, testing::ContainerEq(other));
60 TEST(STLUtilTest, ToUnderlying) {
66 enum class ScopedEnum : char {
71 static_assert(std::is_same<decltype(to_underlying(kOne)), int>::value, "");
72 static_assert(std::is_same<decltype(to_underlying(kTwo)), int>::value, "");
73 static_assert(to_underlying(kOne) == 1, "");
74 static_assert(to_underlying(kTwo) == 2, "");
77 std::is_same<decltype(to_underlying(ScopedEnum::kOne)), char>::value, "");
79 std::is_same<decltype(to_underlying(ScopedEnum::kTwo)), char>::value, "");
80 static_assert(to_underlying(ScopedEnum::kOne) == 1, "");
81 static_assert(to_underlying(ScopedEnum::kTwo) == 2, "");
84 TEST(STLUtilTest, GetUnderlyingContainer) {
86 std::queue<int> queue({1, 2, 3, 4, 5});
87 static_assert(std::is_same<decltype(GetUnderlyingContainer(queue)),
88 const std::deque<int>&>::value,
89 "GetUnderlyingContainer(queue) should be of type deque");
90 EXPECT_THAT(GetUnderlyingContainer(queue),
91 testing::ElementsAre(1, 2, 3, 4, 5));
95 std::queue<int> queue;
96 EXPECT_THAT(GetUnderlyingContainer(queue), testing::ElementsAre());
100 base::queue<int> queue({1, 2, 3, 4, 5});
102 std::is_same<decltype(GetUnderlyingContainer(queue)),
103 const base::circular_deque<int>&>::value,
104 "GetUnderlyingContainer(queue) should be of type circular_deque");
105 EXPECT_THAT(GetUnderlyingContainer(queue),
106 testing::ElementsAre(1, 2, 3, 4, 5));
110 std::vector<int> values = {1, 2, 3, 4, 5};
111 std::priority_queue<int> queue(values.begin(), values.end());
112 static_assert(std::is_same<decltype(GetUnderlyingContainer(queue)),
113 const std::vector<int>&>::value,
114 "GetUnderlyingContainer(queue) should be of type vector");
115 EXPECT_THAT(GetUnderlyingContainer(queue),
116 testing::UnorderedElementsAre(1, 2, 3, 4, 5));
120 std::stack<int> stack({1, 2, 3, 4, 5});
121 static_assert(std::is_same<decltype(GetUnderlyingContainer(stack)),
122 const std::deque<int>&>::value,
123 "GetUnderlyingContainer(stack) should be of type deque");
124 EXPECT_THAT(GetUnderlyingContainer(stack),
125 testing::ElementsAre(1, 2, 3, 4, 5));
129 TEST(STLUtilTest, ConstCastIterator) {
130 // Sequence Containers
131 RunConstCastIteratorTest<std::forward_list<int>>();
132 RunConstCastIteratorTest<std::list<int>>();
133 RunConstCastIteratorTest<std::deque<int>>();
134 RunConstCastIteratorTest<std::vector<int>>();
135 RunConstCastIteratorTest<std::array<int, 5>>();
136 RunConstCastIteratorTest<int[5]>();
138 // Associative Containers
139 RunConstCastIteratorTest<std::set<int>>();
140 RunConstCastIteratorTest<std::multiset<int>>();
142 // Unordered Associative Containers
143 RunConstCastIteratorTest<std::unordered_set<int>>();
144 RunConstCastIteratorTest<std::unordered_multiset<int>>();
147 TEST(STLUtilTest, STLSetDifference) {
162 std::set<int> difference;
163 difference.insert(1);
164 difference.insert(2);
165 EXPECT_EQ(difference, STLSetDifference<std::set<int> >(a1, a2));
169 std::set<int> difference;
170 difference.insert(5);
171 difference.insert(6);
172 difference.insert(7);
173 EXPECT_EQ(difference, STLSetDifference<std::set<int> >(a2, a1));
177 std::vector<int> difference;
178 difference.push_back(1);
179 difference.push_back(2);
180 EXPECT_EQ(difference, STLSetDifference<std::vector<int> >(a1, a2));
184 std::vector<int> difference;
185 difference.push_back(5);
186 difference.push_back(6);
187 difference.push_back(7);
188 EXPECT_EQ(difference, STLSetDifference<std::vector<int> >(a2, a1));
192 TEST(STLUtilTest, STLSetUnion) {
207 std::set<int> result;
215 EXPECT_EQ(result, STLSetUnion<std::set<int> >(a1, a2));
219 std::set<int> result;
227 EXPECT_EQ(result, STLSetUnion<std::set<int> >(a2, a1));
231 std::vector<int> result;
239 EXPECT_EQ(result, STLSetUnion<std::vector<int> >(a1, a2));
243 std::vector<int> result;
251 EXPECT_EQ(result, STLSetUnion<std::vector<int> >(a2, a1));
255 TEST(STLUtilTest, STLSetIntersection) {
270 std::set<int> result;
273 EXPECT_EQ(result, STLSetIntersection<std::set<int> >(a1, a2));
277 std::set<int> result;
280 EXPECT_EQ(result, STLSetIntersection<std::set<int> >(a2, a1));
284 std::vector<int> result;
287 EXPECT_EQ(result, STLSetIntersection<std::vector<int> >(a1, a2));
291 std::vector<int> result;
294 EXPECT_EQ(result, STLSetIntersection<std::vector<int> >(a2, a1));
298 TEST(Erase, IsNotIn) {
299 // Should keep both '2' but only one '4', like std::set_intersection.
300 std::vector<int> lhs = {0, 2, 2, 4, 4, 4, 6, 8, 10};
301 std::vector<int> rhs = {1, 2, 2, 4, 5, 6, 7};
302 std::vector<int> expected = {2, 2, 4, 6};
303 EXPECT_EQ(5u, EraseIf(lhs, IsNotIn<std::vector<int>>(rhs)));
304 EXPECT_EQ(expected, lhs);
307 TEST(STLUtilTest, InsertOrAssign) {
308 std::map<std::string, int> my_map;
309 auto result = InsertOrAssign(my_map, "Hello", 42);
310 EXPECT_THAT(*result.first, Pair("Hello", 42));
311 EXPECT_TRUE(result.second);
313 result = InsertOrAssign(my_map, "Hello", 43);
314 EXPECT_THAT(*result.first, Pair("Hello", 43));
315 EXPECT_FALSE(result.second);
318 TEST(STLUtilTest, InsertOrAssignHint) {
319 std::map<std::string, int> my_map;
320 auto result = InsertOrAssign(my_map, my_map.end(), "Hello", 42);
321 EXPECT_THAT(*result, Pair("Hello", 42));
323 result = InsertOrAssign(my_map, my_map.begin(), "Hello", 43);
324 EXPECT_THAT(*result, Pair("Hello", 43));
327 TEST(STLUtilTest, InsertOrAssignWrongHints) {
328 std::map<int, int> my_map;
329 // Since we insert keys in sorted order, my_map.begin() will be a wrong hint
330 // after the first iteration. Check that insertion happens anyway.
331 for (int i = 0; i < 10; ++i) {
333 auto result = InsertOrAssign(my_map, my_map.begin(), i, i);
334 EXPECT_THAT(*result, Pair(i, i));
337 // Overwrite the keys we just inserted. Since we no longer insert into the
338 // map, my_map.end() will be a wrong hint for all iterations but the last.
339 for (int i = 0; i < 10; ++i) {
340 SCOPED_TRACE(10 + i);
341 auto result = InsertOrAssign(my_map, my_map.end(), i, 10 + i);
342 EXPECT_THAT(*result, Pair(i, 10 + i));
346 TEST(STLUtilTest, TryEmplace) {
347 std::map<std::string, std::unique_ptr<int>> my_map;
348 auto result = TryEmplace(my_map, "Hello", nullptr);
349 EXPECT_THAT(*result.first, Pair("Hello", IsNull()));
350 EXPECT_TRUE(result.second);
352 auto new_value = std::make_unique<int>(42);
353 result = TryEmplace(my_map, "Hello", std::move(new_value));
354 EXPECT_THAT(*result.first, Pair("Hello", IsNull()));
355 EXPECT_FALSE(result.second);
356 // |new_value| should not be touched following a failed insertion.
357 ASSERT_NE(nullptr, new_value);
358 EXPECT_EQ(42, *new_value);
360 result = TryEmplace(my_map, "World", std::move(new_value));
361 EXPECT_EQ("World", result.first->first);
362 EXPECT_EQ(42, *result.first->second);
363 EXPECT_TRUE(result.second);
364 EXPECT_EQ(nullptr, new_value);
367 TEST(STLUtilTest, TryEmplaceHint) {
368 std::map<std::string, std::unique_ptr<int>> my_map;
369 auto result = TryEmplace(my_map, my_map.begin(), "Hello", nullptr);
370 EXPECT_THAT(*result, Pair("Hello", IsNull()));
372 auto new_value = std::make_unique<int>(42);
373 result = TryEmplace(my_map, result, "Hello", std::move(new_value));
374 EXPECT_THAT(*result, Pair("Hello", IsNull()));
375 // |new_value| should not be touched following a failed insertion.
376 ASSERT_NE(nullptr, new_value);
377 EXPECT_EQ(42, *new_value);
379 result = TryEmplace(my_map, result, "World", std::move(new_value));
380 EXPECT_EQ("World", result->first);
381 EXPECT_EQ(42, *result->second);
382 EXPECT_EQ(nullptr, new_value);
385 TEST(STLUtilTest, TryEmplaceWrongHints) {
386 std::map<int, int> my_map;
387 // Since we emplace keys in sorted order, my_map.begin() will be a wrong hint
388 // after the first iteration. Check that emplacement happens anyway.
389 for (int i = 0; i < 10; ++i) {
391 auto result = TryEmplace(my_map, my_map.begin(), i, i);
392 EXPECT_THAT(*result, Pair(i, i));
395 // Fail to overwrite the keys we just inserted. Since we no longer emplace
396 // into the map, my_map.end() will be a wrong hint for all tried emplacements
398 for (int i = 0; i < 10; ++i) {
399 SCOPED_TRACE(10 + i);
400 auto result = TryEmplace(my_map, my_map.end(), i, 10 + i);
401 EXPECT_THAT(*result, Pair(i, i));
405 TEST(STLUtilTest, OptionalOrNullptr) {
406 absl::optional<float> optional;
407 EXPECT_EQ(nullptr, base::OptionalOrNullptr(optional));
410 EXPECT_EQ(&optional.value(), base::OptionalOrNullptr(optional));
411 EXPECT_NE(nullptr, base::OptionalOrNullptr(optional));