1*6777b538SAndroid Build Coastguard Worker // Copyright 2017 The Chromium Authors
2*6777b538SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*6777b538SAndroid Build Coastguard Worker // found in the LICENSE file.
4*6777b538SAndroid Build Coastguard Worker
5*6777b538SAndroid Build Coastguard Worker #include "base/containers/flat_map.h"
6*6777b538SAndroid Build Coastguard Worker
7*6777b538SAndroid Build Coastguard Worker #include <string>
8*6777b538SAndroid Build Coastguard Worker #include <string_view>
9*6777b538SAndroid Build Coastguard Worker #include <type_traits>
10*6777b538SAndroid Build Coastguard Worker #include <utility>
11*6777b538SAndroid Build Coastguard Worker #include <vector>
12*6777b538SAndroid Build Coastguard Worker
13*6777b538SAndroid Build Coastguard Worker #include "base/ranges/algorithm.h"
14*6777b538SAndroid Build Coastguard Worker #include "base/test/move_only_int.h"
15*6777b538SAndroid Build Coastguard Worker #include "testing/gmock/include/gmock/gmock.h"
16*6777b538SAndroid Build Coastguard Worker #include "testing/gtest/include/gtest/gtest.h"
17*6777b538SAndroid Build Coastguard Worker
18*6777b538SAndroid Build Coastguard Worker // A flat_map is basically a interface to flat_tree. So several basic
19*6777b538SAndroid Build Coastguard Worker // operations are tested to make sure things are set up properly, but the bulk
20*6777b538SAndroid Build Coastguard Worker // of the tests are in flat_tree_unittests.cc.
21*6777b538SAndroid Build Coastguard Worker
22*6777b538SAndroid Build Coastguard Worker using ::testing::ElementsAre;
23*6777b538SAndroid Build Coastguard Worker
24*6777b538SAndroid Build Coastguard Worker namespace base {
25*6777b538SAndroid Build Coastguard Worker
26*6777b538SAndroid Build Coastguard Worker namespace {
27*6777b538SAndroid Build Coastguard Worker
28*6777b538SAndroid Build Coastguard Worker struct Unsortable {
29*6777b538SAndroid Build Coastguard Worker int value;
30*6777b538SAndroid Build Coastguard Worker };
31*6777b538SAndroid Build Coastguard Worker
operator ==(const Unsortable & lhs,const Unsortable & rhs)32*6777b538SAndroid Build Coastguard Worker bool operator==(const Unsortable& lhs, const Unsortable& rhs) {
33*6777b538SAndroid Build Coastguard Worker return lhs.value == rhs.value;
34*6777b538SAndroid Build Coastguard Worker }
35*6777b538SAndroid Build Coastguard Worker
36*6777b538SAndroid Build Coastguard Worker bool operator<(const Unsortable& lhs, const Unsortable& rhs) = delete;
37*6777b538SAndroid Build Coastguard Worker bool operator<=(const Unsortable& lhs, const Unsortable& rhs) = delete;
38*6777b538SAndroid Build Coastguard Worker bool operator>(const Unsortable& lhs, const Unsortable& rhs) = delete;
39*6777b538SAndroid Build Coastguard Worker bool operator>=(const Unsortable& lhs, const Unsortable& rhs) = delete;
40*6777b538SAndroid Build Coastguard Worker
41*6777b538SAndroid Build Coastguard Worker class ImplicitInt {
42*6777b538SAndroid Build Coastguard Worker public:
43*6777b538SAndroid Build Coastguard Worker // NOLINTNEXTLINE(google-explicit-constructor)
ImplicitInt(int data)44*6777b538SAndroid Build Coastguard Worker ImplicitInt(int data) : data_(data) {}
45*6777b538SAndroid Build Coastguard Worker
46*6777b538SAndroid Build Coastguard Worker private:
operator <(const ImplicitInt & lhs,const ImplicitInt & rhs)47*6777b538SAndroid Build Coastguard Worker friend bool operator<(const ImplicitInt& lhs, const ImplicitInt& rhs) {
48*6777b538SAndroid Build Coastguard Worker return lhs.data_ < rhs.data_;
49*6777b538SAndroid Build Coastguard Worker }
50*6777b538SAndroid Build Coastguard Worker
51*6777b538SAndroid Build Coastguard Worker int data_;
52*6777b538SAndroid Build Coastguard Worker };
53*6777b538SAndroid Build Coastguard Worker
54*6777b538SAndroid Build Coastguard Worker } // namespace
55*6777b538SAndroid Build Coastguard Worker
TEST(FlatMap,IncompleteType)56*6777b538SAndroid Build Coastguard Worker TEST(FlatMap, IncompleteType) {
57*6777b538SAndroid Build Coastguard Worker struct A {
58*6777b538SAndroid Build Coastguard Worker using Map = flat_map<A, A>;
59*6777b538SAndroid Build Coastguard Worker int data;
60*6777b538SAndroid Build Coastguard Worker Map set_with_incomplete_type;
61*6777b538SAndroid Build Coastguard Worker Map::iterator it;
62*6777b538SAndroid Build Coastguard Worker Map::const_iterator cit;
63*6777b538SAndroid Build Coastguard Worker
64*6777b538SAndroid Build Coastguard Worker // We do not declare operator< because clang complains that it's unused.
65*6777b538SAndroid Build Coastguard Worker };
66*6777b538SAndroid Build Coastguard Worker
67*6777b538SAndroid Build Coastguard Worker A a;
68*6777b538SAndroid Build Coastguard Worker }
69*6777b538SAndroid Build Coastguard Worker
TEST(FlatMap,RangeConstructor)70*6777b538SAndroid Build Coastguard Worker TEST(FlatMap, RangeConstructor) {
71*6777b538SAndroid Build Coastguard Worker flat_map<int, int>::value_type input_vals[] = {
72*6777b538SAndroid Build Coastguard Worker {1, 1}, {1, 2}, {1, 3}, {2, 1}, {2, 2}, {2, 3}, {3, 1}, {3, 2}, {3, 3}};
73*6777b538SAndroid Build Coastguard Worker
74*6777b538SAndroid Build Coastguard Worker flat_map<int, int> first(std::begin(input_vals), std::end(input_vals));
75*6777b538SAndroid Build Coastguard Worker EXPECT_THAT(first, ElementsAre(std::make_pair(1, 1), std::make_pair(2, 1),
76*6777b538SAndroid Build Coastguard Worker std::make_pair(3, 1)));
77*6777b538SAndroid Build Coastguard Worker }
78*6777b538SAndroid Build Coastguard Worker
TEST(FlatMap,MoveConstructor)79*6777b538SAndroid Build Coastguard Worker TEST(FlatMap, MoveConstructor) {
80*6777b538SAndroid Build Coastguard Worker using pair = std::pair<MoveOnlyInt, MoveOnlyInt>;
81*6777b538SAndroid Build Coastguard Worker
82*6777b538SAndroid Build Coastguard Worker flat_map<MoveOnlyInt, MoveOnlyInt> original;
83*6777b538SAndroid Build Coastguard Worker original.insert(pair(MoveOnlyInt(1), MoveOnlyInt(1)));
84*6777b538SAndroid Build Coastguard Worker original.insert(pair(MoveOnlyInt(2), MoveOnlyInt(2)));
85*6777b538SAndroid Build Coastguard Worker original.insert(pair(MoveOnlyInt(3), MoveOnlyInt(3)));
86*6777b538SAndroid Build Coastguard Worker original.insert(pair(MoveOnlyInt(4), MoveOnlyInt(4)));
87*6777b538SAndroid Build Coastguard Worker
88*6777b538SAndroid Build Coastguard Worker flat_map<MoveOnlyInt, MoveOnlyInt> moved(std::move(original));
89*6777b538SAndroid Build Coastguard Worker
90*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(1U, moved.count(MoveOnlyInt(1)));
91*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(1U, moved.count(MoveOnlyInt(2)));
92*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(1U, moved.count(MoveOnlyInt(3)));
93*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(1U, moved.count(MoveOnlyInt(4)));
94*6777b538SAndroid Build Coastguard Worker }
95*6777b538SAndroid Build Coastguard Worker
TEST(FlatMap,VectorConstructor)96*6777b538SAndroid Build Coastguard Worker TEST(FlatMap, VectorConstructor) {
97*6777b538SAndroid Build Coastguard Worker using IntPair = std::pair<int, int>;
98*6777b538SAndroid Build Coastguard Worker using IntMap = flat_map<int, int>;
99*6777b538SAndroid Build Coastguard Worker std::vector<IntPair> vect{{1, 1}, {1, 2}, {2, 1}};
100*6777b538SAndroid Build Coastguard Worker IntMap map(std::move(vect));
101*6777b538SAndroid Build Coastguard Worker EXPECT_THAT(map, ElementsAre(IntPair(1, 1), IntPair(2, 1)));
102*6777b538SAndroid Build Coastguard Worker }
103*6777b538SAndroid Build Coastguard Worker
TEST(FlatMap,InitializerListConstructor)104*6777b538SAndroid Build Coastguard Worker TEST(FlatMap, InitializerListConstructor) {
105*6777b538SAndroid Build Coastguard Worker flat_map<int, int> cont(
106*6777b538SAndroid Build Coastguard Worker {{1, 1}, {2, 2}, {3, 3}, {4, 4}, {5, 5}, {1, 2}, {10, 10}, {8, 8}});
107*6777b538SAndroid Build Coastguard Worker EXPECT_THAT(cont, ElementsAre(std::make_pair(1, 1), std::make_pair(2, 2),
108*6777b538SAndroid Build Coastguard Worker std::make_pair(3, 3), std::make_pair(4, 4),
109*6777b538SAndroid Build Coastguard Worker std::make_pair(5, 5), std::make_pair(8, 8),
110*6777b538SAndroid Build Coastguard Worker std::make_pair(10, 10)));
111*6777b538SAndroid Build Coastguard Worker }
112*6777b538SAndroid Build Coastguard Worker
TEST(FlatMap,SortedRangeConstructor)113*6777b538SAndroid Build Coastguard Worker TEST(FlatMap, SortedRangeConstructor) {
114*6777b538SAndroid Build Coastguard Worker using PairType = std::pair<int, Unsortable>;
115*6777b538SAndroid Build Coastguard Worker using MapType = flat_map<int, Unsortable>;
116*6777b538SAndroid Build Coastguard Worker MapType::value_type input_vals[] = {{1, {1}}, {2, {1}}, {3, {1}}};
117*6777b538SAndroid Build Coastguard Worker MapType map(sorted_unique, std::begin(input_vals), std::end(input_vals));
118*6777b538SAndroid Build Coastguard Worker EXPECT_THAT(
119*6777b538SAndroid Build Coastguard Worker map, ElementsAre(PairType(1, {1}), PairType(2, {1}), PairType(3, {1})));
120*6777b538SAndroid Build Coastguard Worker }
121*6777b538SAndroid Build Coastguard Worker
TEST(FlatMap,SortedCopyFromVectorConstructor)122*6777b538SAndroid Build Coastguard Worker TEST(FlatMap, SortedCopyFromVectorConstructor) {
123*6777b538SAndroid Build Coastguard Worker using PairType = std::pair<int, Unsortable>;
124*6777b538SAndroid Build Coastguard Worker using MapType = flat_map<int, Unsortable>;
125*6777b538SAndroid Build Coastguard Worker std::vector<PairType> vect{{1, {1}}, {2, {1}}};
126*6777b538SAndroid Build Coastguard Worker MapType map(sorted_unique, vect);
127*6777b538SAndroid Build Coastguard Worker EXPECT_THAT(map, ElementsAre(PairType(1, {1}), PairType(2, {1})));
128*6777b538SAndroid Build Coastguard Worker }
129*6777b538SAndroid Build Coastguard Worker
TEST(FlatMap,SortedMoveFromVectorConstructor)130*6777b538SAndroid Build Coastguard Worker TEST(FlatMap, SortedMoveFromVectorConstructor) {
131*6777b538SAndroid Build Coastguard Worker using PairType = std::pair<int, Unsortable>;
132*6777b538SAndroid Build Coastguard Worker using MapType = flat_map<int, Unsortable>;
133*6777b538SAndroid Build Coastguard Worker std::vector<PairType> vect{{1, {1}}, {2, {1}}};
134*6777b538SAndroid Build Coastguard Worker MapType map(sorted_unique, std::move(vect));
135*6777b538SAndroid Build Coastguard Worker EXPECT_THAT(map, ElementsAre(PairType(1, {1}), PairType(2, {1})));
136*6777b538SAndroid Build Coastguard Worker }
137*6777b538SAndroid Build Coastguard Worker
TEST(FlatMap,SortedInitializerListConstructor)138*6777b538SAndroid Build Coastguard Worker TEST(FlatMap, SortedInitializerListConstructor) {
139*6777b538SAndroid Build Coastguard Worker using PairType = std::pair<int, Unsortable>;
140*6777b538SAndroid Build Coastguard Worker flat_map<int, Unsortable> map(
141*6777b538SAndroid Build Coastguard Worker sorted_unique,
142*6777b538SAndroid Build Coastguard Worker {{1, {1}}, {2, {2}}, {3, {3}}, {4, {4}}, {5, {5}}, {8, {8}}, {10, {10}}});
143*6777b538SAndroid Build Coastguard Worker EXPECT_THAT(map,
144*6777b538SAndroid Build Coastguard Worker ElementsAre(PairType(1, {1}), PairType(2, {2}), PairType(3, {3}),
145*6777b538SAndroid Build Coastguard Worker PairType(4, {4}), PairType(5, {5}), PairType(8, {8}),
146*6777b538SAndroid Build Coastguard Worker PairType(10, {10})));
147*6777b538SAndroid Build Coastguard Worker }
148*6777b538SAndroid Build Coastguard Worker
TEST(FlatMap,InitializerListAssignment)149*6777b538SAndroid Build Coastguard Worker TEST(FlatMap, InitializerListAssignment) {
150*6777b538SAndroid Build Coastguard Worker flat_map<int, int> cont;
151*6777b538SAndroid Build Coastguard Worker cont = {{1, 1}, {2, 2}};
152*6777b538SAndroid Build Coastguard Worker EXPECT_THAT(cont, ElementsAre(std::make_pair(1, 1), std::make_pair(2, 2)));
153*6777b538SAndroid Build Coastguard Worker }
154*6777b538SAndroid Build Coastguard Worker
TEST(FlatMap,InsertFindSize)155*6777b538SAndroid Build Coastguard Worker TEST(FlatMap, InsertFindSize) {
156*6777b538SAndroid Build Coastguard Worker base::flat_map<int, int> s;
157*6777b538SAndroid Build Coastguard Worker s.insert(std::make_pair(1, 1));
158*6777b538SAndroid Build Coastguard Worker s.insert(std::make_pair(1, 1));
159*6777b538SAndroid Build Coastguard Worker s.insert(std::make_pair(2, 2));
160*6777b538SAndroid Build Coastguard Worker
161*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(2u, s.size());
162*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(std::make_pair(1, 1), *s.find(1));
163*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(std::make_pair(2, 2), *s.find(2));
164*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(s.end(), s.find(7));
165*6777b538SAndroid Build Coastguard Worker }
166*6777b538SAndroid Build Coastguard Worker
TEST(FlatMap,CopySwap)167*6777b538SAndroid Build Coastguard Worker TEST(FlatMap, CopySwap) {
168*6777b538SAndroid Build Coastguard Worker base::flat_map<int, int> original;
169*6777b538SAndroid Build Coastguard Worker original.insert({1, 1});
170*6777b538SAndroid Build Coastguard Worker original.insert({2, 2});
171*6777b538SAndroid Build Coastguard Worker EXPECT_THAT(original,
172*6777b538SAndroid Build Coastguard Worker ElementsAre(std::make_pair(1, 1), std::make_pair(2, 2)));
173*6777b538SAndroid Build Coastguard Worker
174*6777b538SAndroid Build Coastguard Worker base::flat_map<int, int> copy(original);
175*6777b538SAndroid Build Coastguard Worker EXPECT_THAT(copy, ElementsAre(std::make_pair(1, 1), std::make_pair(2, 2)));
176*6777b538SAndroid Build Coastguard Worker
177*6777b538SAndroid Build Coastguard Worker copy.erase(copy.begin());
178*6777b538SAndroid Build Coastguard Worker copy.insert({10, 10});
179*6777b538SAndroid Build Coastguard Worker EXPECT_THAT(copy, ElementsAre(std::make_pair(2, 2), std::make_pair(10, 10)));
180*6777b538SAndroid Build Coastguard Worker
181*6777b538SAndroid Build Coastguard Worker original.swap(copy);
182*6777b538SAndroid Build Coastguard Worker EXPECT_THAT(original,
183*6777b538SAndroid Build Coastguard Worker ElementsAre(std::make_pair(2, 2), std::make_pair(10, 10)));
184*6777b538SAndroid Build Coastguard Worker EXPECT_THAT(copy, ElementsAre(std::make_pair(1, 1), std::make_pair(2, 2)));
185*6777b538SAndroid Build Coastguard Worker }
186*6777b538SAndroid Build Coastguard Worker
187*6777b538SAndroid Build Coastguard Worker // operator[](const Key&)
TEST(FlatMap,SubscriptConstKey)188*6777b538SAndroid Build Coastguard Worker TEST(FlatMap, SubscriptConstKey) {
189*6777b538SAndroid Build Coastguard Worker base::flat_map<std::string, int> m;
190*6777b538SAndroid Build Coastguard Worker
191*6777b538SAndroid Build Coastguard Worker // Default construct elements that don't exist yet.
192*6777b538SAndroid Build Coastguard Worker int& s = m["a"];
193*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(0, s);
194*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(1u, m.size());
195*6777b538SAndroid Build Coastguard Worker
196*6777b538SAndroid Build Coastguard Worker // The returned mapped reference should refer into the map.
197*6777b538SAndroid Build Coastguard Worker s = 22;
198*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(22, m["a"]);
199*6777b538SAndroid Build Coastguard Worker
200*6777b538SAndroid Build Coastguard Worker // Overwrite existing elements.
201*6777b538SAndroid Build Coastguard Worker m["a"] = 44;
202*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(44, m["a"]);
203*6777b538SAndroid Build Coastguard Worker }
204*6777b538SAndroid Build Coastguard Worker
205*6777b538SAndroid Build Coastguard Worker // operator[](Key&&)
TEST(FlatMap,SubscriptMoveOnlyKey)206*6777b538SAndroid Build Coastguard Worker TEST(FlatMap, SubscriptMoveOnlyKey) {
207*6777b538SAndroid Build Coastguard Worker base::flat_map<MoveOnlyInt, int> m;
208*6777b538SAndroid Build Coastguard Worker
209*6777b538SAndroid Build Coastguard Worker // Default construct elements that don't exist yet.
210*6777b538SAndroid Build Coastguard Worker int& s = m[MoveOnlyInt(1)];
211*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(0, s);
212*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(1u, m.size());
213*6777b538SAndroid Build Coastguard Worker
214*6777b538SAndroid Build Coastguard Worker // The returned mapped reference should refer into the map.
215*6777b538SAndroid Build Coastguard Worker s = 22;
216*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(22, m[MoveOnlyInt(1)]);
217*6777b538SAndroid Build Coastguard Worker
218*6777b538SAndroid Build Coastguard Worker // Overwrite existing elements.
219*6777b538SAndroid Build Coastguard Worker m[MoveOnlyInt(1)] = 44;
220*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(44, m[MoveOnlyInt(1)]);
221*6777b538SAndroid Build Coastguard Worker }
222*6777b538SAndroid Build Coastguard Worker
223*6777b538SAndroid Build Coastguard Worker // Mapped& at(const Key&)
224*6777b538SAndroid Build Coastguard Worker // const Mapped& at(const Key&) const
TEST(FlatMap,AtFunction)225*6777b538SAndroid Build Coastguard Worker TEST(FlatMap, AtFunction) {
226*6777b538SAndroid Build Coastguard Worker base::flat_map<int, std::string> m = {{1, "a"}, {2, "b"}};
227*6777b538SAndroid Build Coastguard Worker
228*6777b538SAndroid Build Coastguard Worker // Basic Usage.
229*6777b538SAndroid Build Coastguard Worker EXPECT_EQ("a", m.at(1));
230*6777b538SAndroid Build Coastguard Worker EXPECT_EQ("b", m.at(2));
231*6777b538SAndroid Build Coastguard Worker
232*6777b538SAndroid Build Coastguard Worker // Const reference works.
233*6777b538SAndroid Build Coastguard Worker const std::string& const_ref = std::as_const(m).at(1);
234*6777b538SAndroid Build Coastguard Worker EXPECT_EQ("a", const_ref);
235*6777b538SAndroid Build Coastguard Worker
236*6777b538SAndroid Build Coastguard Worker // Reference works, can operate on the string.
237*6777b538SAndroid Build Coastguard Worker m.at(1)[0] = 'x';
238*6777b538SAndroid Build Coastguard Worker EXPECT_EQ("x", m.at(1));
239*6777b538SAndroid Build Coastguard Worker
240*6777b538SAndroid Build Coastguard Worker // Out-of-bounds will CHECK.
241*6777b538SAndroid Build Coastguard Worker EXPECT_DEATH_IF_SUPPORTED(m.at(-1), "");
242*6777b538SAndroid Build Coastguard Worker EXPECT_DEATH_IF_SUPPORTED({ m.at(-1)[0] = 'z'; }, "");
243*6777b538SAndroid Build Coastguard Worker
244*6777b538SAndroid Build Coastguard Worker // Heterogeneous look-up works.
245*6777b538SAndroid Build Coastguard Worker base::flat_map<std::string, int> m2 = {{"a", 1}, {"b", 2}};
246*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(1, m2.at(std::string_view("a")));
247*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(2, std::as_const(m2).at(std::string_view("b")));
248*6777b538SAndroid Build Coastguard Worker }
249*6777b538SAndroid Build Coastguard Worker
250*6777b538SAndroid Build Coastguard Worker // insert_or_assign(K&&, M&&)
TEST(FlatMap,InsertOrAssignMoveOnlyKey)251*6777b538SAndroid Build Coastguard Worker TEST(FlatMap, InsertOrAssignMoveOnlyKey) {
252*6777b538SAndroid Build Coastguard Worker base::flat_map<MoveOnlyInt, MoveOnlyInt> m;
253*6777b538SAndroid Build Coastguard Worker
254*6777b538SAndroid Build Coastguard Worker // Initial insertion should return an iterator to the element and set the
255*6777b538SAndroid Build Coastguard Worker // second pair member to |true|. The inserted key and value should be moved
256*6777b538SAndroid Build Coastguard Worker // from.
257*6777b538SAndroid Build Coastguard Worker MoveOnlyInt key(1);
258*6777b538SAndroid Build Coastguard Worker MoveOnlyInt val(22);
259*6777b538SAndroid Build Coastguard Worker auto result = m.insert_or_assign(std::move(key), std::move(val));
260*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(1, result.first->first.data());
261*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(22, result.first->second.data());
262*6777b538SAndroid Build Coastguard Worker EXPECT_TRUE(result.second);
263*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(1u, m.size());
264*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(0, key.data()); // moved from
265*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(0, val.data()); // moved from
266*6777b538SAndroid Build Coastguard Worker
267*6777b538SAndroid Build Coastguard Worker // Second call with same key should result in an assignment, overwriting the
268*6777b538SAndroid Build Coastguard Worker // old value. Assignment should be indicated by setting the second pair member
269*6777b538SAndroid Build Coastguard Worker // to |false|. Only the inserted value should be moved from, the key should be
270*6777b538SAndroid Build Coastguard Worker // left intact.
271*6777b538SAndroid Build Coastguard Worker key = MoveOnlyInt(1);
272*6777b538SAndroid Build Coastguard Worker val = MoveOnlyInt(44);
273*6777b538SAndroid Build Coastguard Worker result = m.insert_or_assign(std::move(key), std::move(val));
274*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(1, result.first->first.data());
275*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(44, result.first->second.data());
276*6777b538SAndroid Build Coastguard Worker EXPECT_FALSE(result.second);
277*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(1u, m.size());
278*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(1, key.data()); // not moved from
279*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(0, val.data()); // moved from
280*6777b538SAndroid Build Coastguard Worker
281*6777b538SAndroid Build Coastguard Worker // Check that random insertion results in sorted range.
282*6777b538SAndroid Build Coastguard Worker base::flat_map<MoveOnlyInt, int> map;
283*6777b538SAndroid Build Coastguard Worker for (int i : {3, 1, 5, 6, 8, 7, 0, 9, 4, 2}) {
284*6777b538SAndroid Build Coastguard Worker map.insert_or_assign(MoveOnlyInt(i), i);
285*6777b538SAndroid Build Coastguard Worker EXPECT_TRUE(ranges::is_sorted(map));
286*6777b538SAndroid Build Coastguard Worker }
287*6777b538SAndroid Build Coastguard Worker }
288*6777b538SAndroid Build Coastguard Worker
289*6777b538SAndroid Build Coastguard Worker // insert_or_assign(const_iterator hint, K&&, M&&)
TEST(FlatMap,InsertOrAssignMoveOnlyKeyWithHint)290*6777b538SAndroid Build Coastguard Worker TEST(FlatMap, InsertOrAssignMoveOnlyKeyWithHint) {
291*6777b538SAndroid Build Coastguard Worker base::flat_map<MoveOnlyInt, MoveOnlyInt> m;
292*6777b538SAndroid Build Coastguard Worker
293*6777b538SAndroid Build Coastguard Worker // Initial insertion should return an iterator to the element. The inserted
294*6777b538SAndroid Build Coastguard Worker // key and value should be moved from.
295*6777b538SAndroid Build Coastguard Worker MoveOnlyInt key(1);
296*6777b538SAndroid Build Coastguard Worker MoveOnlyInt val(22);
297*6777b538SAndroid Build Coastguard Worker auto result = m.insert_or_assign(m.end(), std::move(key), std::move(val));
298*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(1, result->first.data());
299*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(22, result->second.data());
300*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(1u, m.size());
301*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(0, key.data()); // moved from
302*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(0, val.data()); // moved from
303*6777b538SAndroid Build Coastguard Worker
304*6777b538SAndroid Build Coastguard Worker // Second call with same key should result in an assignment, overwriting the
305*6777b538SAndroid Build Coastguard Worker // old value. Only the inserted value should be moved from, the key should be
306*6777b538SAndroid Build Coastguard Worker // left intact.
307*6777b538SAndroid Build Coastguard Worker key = MoveOnlyInt(1);
308*6777b538SAndroid Build Coastguard Worker val = MoveOnlyInt(44);
309*6777b538SAndroid Build Coastguard Worker result = m.insert_or_assign(m.end(), std::move(key), std::move(val));
310*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(1, result->first.data());
311*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(44, result->second.data());
312*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(1u, m.size());
313*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(1, key.data()); // not moved from
314*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(0, val.data()); // moved from
315*6777b538SAndroid Build Coastguard Worker
316*6777b538SAndroid Build Coastguard Worker // Check that random insertion results in sorted range.
317*6777b538SAndroid Build Coastguard Worker base::flat_map<MoveOnlyInt, int> map;
318*6777b538SAndroid Build Coastguard Worker for (int i : {3, 1, 5, 6, 8, 7, 0, 9, 4, 2}) {
319*6777b538SAndroid Build Coastguard Worker map.insert_or_assign(map.end(), MoveOnlyInt(i), i);
320*6777b538SAndroid Build Coastguard Worker EXPECT_TRUE(ranges::is_sorted(map));
321*6777b538SAndroid Build Coastguard Worker }
322*6777b538SAndroid Build Coastguard Worker }
323*6777b538SAndroid Build Coastguard Worker
324*6777b538SAndroid Build Coastguard Worker // try_emplace(K&&, Args&&...)
TEST(FlatMap,TryEmplaceMoveOnlyKey)325*6777b538SAndroid Build Coastguard Worker TEST(FlatMap, TryEmplaceMoveOnlyKey) {
326*6777b538SAndroid Build Coastguard Worker base::flat_map<MoveOnlyInt, std::pair<MoveOnlyInt, MoveOnlyInt>> m;
327*6777b538SAndroid Build Coastguard Worker
328*6777b538SAndroid Build Coastguard Worker // Trying to emplace into an empty map should succeed. Insertion should return
329*6777b538SAndroid Build Coastguard Worker // an iterator to the element and set the second pair member to |true|. The
330*6777b538SAndroid Build Coastguard Worker // inserted key and value should be moved from.
331*6777b538SAndroid Build Coastguard Worker MoveOnlyInt key(1);
332*6777b538SAndroid Build Coastguard Worker MoveOnlyInt val1(22);
333*6777b538SAndroid Build Coastguard Worker MoveOnlyInt val2(44);
334*6777b538SAndroid Build Coastguard Worker // Test piecewise construction of mapped_type.
335*6777b538SAndroid Build Coastguard Worker auto result = m.try_emplace(std::move(key), std::move(val1), std::move(val2));
336*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(1, result.first->first.data());
337*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(22, result.first->second.first.data());
338*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(44, result.first->second.second.data());
339*6777b538SAndroid Build Coastguard Worker EXPECT_TRUE(result.second);
340*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(1u, m.size());
341*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(0, key.data()); // moved from
342*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(0, val1.data()); // moved from
343*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(0, val2.data()); // moved from
344*6777b538SAndroid Build Coastguard Worker
345*6777b538SAndroid Build Coastguard Worker // Second call with same key should result in a no-op, returning an iterator
346*6777b538SAndroid Build Coastguard Worker // to the existing element and returning false as the second pair member.
347*6777b538SAndroid Build Coastguard Worker // Key and values that were attempted to be inserted should be left intact.
348*6777b538SAndroid Build Coastguard Worker key = MoveOnlyInt(1);
349*6777b538SAndroid Build Coastguard Worker auto paired_val = std::make_pair(MoveOnlyInt(33), MoveOnlyInt(55));
350*6777b538SAndroid Build Coastguard Worker // Test construction of mapped_type from pair.
351*6777b538SAndroid Build Coastguard Worker result = m.try_emplace(std::move(key), std::move(paired_val));
352*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(1, result.first->first.data());
353*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(22, result.first->second.first.data());
354*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(44, result.first->second.second.data());
355*6777b538SAndroid Build Coastguard Worker EXPECT_FALSE(result.second);
356*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(1u, m.size());
357*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(1, key.data()); // not moved from
358*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(33, paired_val.first.data()); // not moved from
359*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(55, paired_val.second.data()); // not moved from
360*6777b538SAndroid Build Coastguard Worker
361*6777b538SAndroid Build Coastguard Worker // Check that random insertion results in sorted range.
362*6777b538SAndroid Build Coastguard Worker base::flat_map<MoveOnlyInt, int> map;
363*6777b538SAndroid Build Coastguard Worker for (int i : {3, 1, 5, 6, 8, 7, 0, 9, 4, 2}) {
364*6777b538SAndroid Build Coastguard Worker map.try_emplace(MoveOnlyInt(i), i);
365*6777b538SAndroid Build Coastguard Worker EXPECT_TRUE(ranges::is_sorted(map));
366*6777b538SAndroid Build Coastguard Worker }
367*6777b538SAndroid Build Coastguard Worker }
368*6777b538SAndroid Build Coastguard Worker
369*6777b538SAndroid Build Coastguard Worker // try_emplace(const_iterator hint, K&&, Args&&...)
TEST(FlatMap,TryEmplaceMoveOnlyKeyWithHint)370*6777b538SAndroid Build Coastguard Worker TEST(FlatMap, TryEmplaceMoveOnlyKeyWithHint) {
371*6777b538SAndroid Build Coastguard Worker base::flat_map<MoveOnlyInt, std::pair<MoveOnlyInt, MoveOnlyInt>> m;
372*6777b538SAndroid Build Coastguard Worker
373*6777b538SAndroid Build Coastguard Worker // Trying to emplace into an empty map should succeed. Insertion should return
374*6777b538SAndroid Build Coastguard Worker // an iterator to the element. The inserted key and value should be moved
375*6777b538SAndroid Build Coastguard Worker // from.
376*6777b538SAndroid Build Coastguard Worker MoveOnlyInt key(1);
377*6777b538SAndroid Build Coastguard Worker MoveOnlyInt val1(22);
378*6777b538SAndroid Build Coastguard Worker MoveOnlyInt val2(44);
379*6777b538SAndroid Build Coastguard Worker // Test piecewise construction of mapped_type.
380*6777b538SAndroid Build Coastguard Worker auto result =
381*6777b538SAndroid Build Coastguard Worker m.try_emplace(m.end(), std::move(key), std::move(val1), std::move(val2));
382*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(1, result->first.data());
383*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(22, result->second.first.data());
384*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(44, result->second.second.data());
385*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(1u, m.size());
386*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(0, key.data()); // moved from
387*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(0, val1.data()); // moved from
388*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(0, val2.data()); // moved from
389*6777b538SAndroid Build Coastguard Worker
390*6777b538SAndroid Build Coastguard Worker // Second call with same key should result in a no-op, returning an iterator
391*6777b538SAndroid Build Coastguard Worker // to the existing element. Key and values that were attempted to be inserted
392*6777b538SAndroid Build Coastguard Worker // should be left intact.
393*6777b538SAndroid Build Coastguard Worker key = MoveOnlyInt(1);
394*6777b538SAndroid Build Coastguard Worker val1 = MoveOnlyInt(33);
395*6777b538SAndroid Build Coastguard Worker val2 = MoveOnlyInt(55);
396*6777b538SAndroid Build Coastguard Worker auto paired_val = std::make_pair(MoveOnlyInt(33), MoveOnlyInt(55));
397*6777b538SAndroid Build Coastguard Worker // Test construction of mapped_type from pair.
398*6777b538SAndroid Build Coastguard Worker result = m.try_emplace(m.end(), std::move(key), std::move(paired_val));
399*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(1, result->first.data());
400*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(22, result->second.first.data());
401*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(44, result->second.second.data());
402*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(1u, m.size());
403*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(1, key.data()); // not moved from
404*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(33, paired_val.first.data()); // not moved from
405*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(55, paired_val.second.data()); // not moved from
406*6777b538SAndroid Build Coastguard Worker
407*6777b538SAndroid Build Coastguard Worker // Check that random insertion results in sorted range.
408*6777b538SAndroid Build Coastguard Worker base::flat_map<MoveOnlyInt, int> map;
409*6777b538SAndroid Build Coastguard Worker for (int i : {3, 1, 5, 6, 8, 7, 0, 9, 4, 2}) {
410*6777b538SAndroid Build Coastguard Worker map.try_emplace(map.end(), MoveOnlyInt(i), i);
411*6777b538SAndroid Build Coastguard Worker EXPECT_TRUE(ranges::is_sorted(map));
412*6777b538SAndroid Build Coastguard Worker }
413*6777b538SAndroid Build Coastguard Worker }
414*6777b538SAndroid Build Coastguard Worker
TEST(FlatMap,UsingTransparentCompare)415*6777b538SAndroid Build Coastguard Worker TEST(FlatMap, UsingTransparentCompare) {
416*6777b538SAndroid Build Coastguard Worker using ExplicitInt = base::MoveOnlyInt;
417*6777b538SAndroid Build Coastguard Worker base::flat_map<ExplicitInt, int> m;
418*6777b538SAndroid Build Coastguard Worker const auto& m1 = m;
419*6777b538SAndroid Build Coastguard Worker int x = 0;
420*6777b538SAndroid Build Coastguard Worker
421*6777b538SAndroid Build Coastguard Worker // Check if we can use lookup functions without converting to key_type.
422*6777b538SAndroid Build Coastguard Worker // Correctness is checked in flat_tree tests.
423*6777b538SAndroid Build Coastguard Worker m.count(x);
424*6777b538SAndroid Build Coastguard Worker m1.count(x);
425*6777b538SAndroid Build Coastguard Worker m.find(x);
426*6777b538SAndroid Build Coastguard Worker m1.find(x);
427*6777b538SAndroid Build Coastguard Worker m.contains(x);
428*6777b538SAndroid Build Coastguard Worker m1.contains(x);
429*6777b538SAndroid Build Coastguard Worker m.equal_range(x);
430*6777b538SAndroid Build Coastguard Worker m1.equal_range(x);
431*6777b538SAndroid Build Coastguard Worker m.lower_bound(x);
432*6777b538SAndroid Build Coastguard Worker m1.lower_bound(x);
433*6777b538SAndroid Build Coastguard Worker m.upper_bound(x);
434*6777b538SAndroid Build Coastguard Worker m1.upper_bound(x);
435*6777b538SAndroid Build Coastguard Worker m.erase(x);
436*6777b538SAndroid Build Coastguard Worker
437*6777b538SAndroid Build Coastguard Worker // Check if we broke overload resolution.
438*6777b538SAndroid Build Coastguard Worker m.emplace(ExplicitInt(0), 0);
439*6777b538SAndroid Build Coastguard Worker m.emplace(ExplicitInt(1), 0);
440*6777b538SAndroid Build Coastguard Worker m.erase(m.begin());
441*6777b538SAndroid Build Coastguard Worker m.erase(m.cbegin());
442*6777b538SAndroid Build Coastguard Worker }
443*6777b538SAndroid Build Coastguard Worker
TEST(FlatMap,UsingInitializerList)444*6777b538SAndroid Build Coastguard Worker TEST(FlatMap, UsingInitializerList) {
445*6777b538SAndroid Build Coastguard Worker base::flat_map<ImplicitInt, int> m;
446*6777b538SAndroid Build Coastguard Worker const auto& m1 = m;
447*6777b538SAndroid Build Coastguard Worker
448*6777b538SAndroid Build Coastguard Worker // Check if the calls can be resolved. Correctness is checked in flat_tree
449*6777b538SAndroid Build Coastguard Worker // tests.
450*6777b538SAndroid Build Coastguard Worker m.count({1});
451*6777b538SAndroid Build Coastguard Worker m1.count({2});
452*6777b538SAndroid Build Coastguard Worker m.find({3});
453*6777b538SAndroid Build Coastguard Worker m1.find({4});
454*6777b538SAndroid Build Coastguard Worker m.contains({5});
455*6777b538SAndroid Build Coastguard Worker m1.contains({6});
456*6777b538SAndroid Build Coastguard Worker m.equal_range({7});
457*6777b538SAndroid Build Coastguard Worker m1.equal_range({8});
458*6777b538SAndroid Build Coastguard Worker m.lower_bound({9});
459*6777b538SAndroid Build Coastguard Worker m1.lower_bound({10});
460*6777b538SAndroid Build Coastguard Worker m.upper_bound({11});
461*6777b538SAndroid Build Coastguard Worker m1.upper_bound({12});
462*6777b538SAndroid Build Coastguard Worker m.erase({13});
463*6777b538SAndroid Build Coastguard Worker }
464*6777b538SAndroid Build Coastguard Worker
TEST(FlatMap,DeductionGuides)465*6777b538SAndroid Build Coastguard Worker TEST(FlatMap, DeductionGuides) {
466*6777b538SAndroid Build Coastguard Worker {
467*6777b538SAndroid Build Coastguard Worker std::vector<std::pair<int, float>> v = {{1, 4.0}, {2, 3.0}};
468*6777b538SAndroid Build Coastguard Worker flat_map map{v};
469*6777b538SAndroid Build Coastguard Worker static_assert(std::is_same_v<decltype(map), flat_map<int, float>>);
470*6777b538SAndroid Build Coastguard Worker }
471*6777b538SAndroid Build Coastguard Worker
472*6777b538SAndroid Build Coastguard Worker {
473*6777b538SAndroid Build Coastguard Worker std::vector<std::pair<int, float>> v = {{1, 4.0}, {2, 3.0}};
474*6777b538SAndroid Build Coastguard Worker flat_map map(std::move(v));
475*6777b538SAndroid Build Coastguard Worker static_assert(std::is_same_v<decltype(map), flat_map<int, float>>);
476*6777b538SAndroid Build Coastguard Worker }
477*6777b538SAndroid Build Coastguard Worker }
478*6777b538SAndroid Build Coastguard Worker
479*6777b538SAndroid Build Coastguard Worker } // namespace base
480