Index: base/containers/flat_sorted_containers_unittest.cc |
diff --git a/base/containers/flat_sorted_containers_unittest.cc b/base/containers/flat_sorted_containers_unittest.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..acc56b7ef995a33f820799ed2df0c4075acd8f5b |
--- /dev/null |
+++ b/base/containers/flat_sorted_containers_unittest.cc |
@@ -0,0 +1,499 @@ |
+// Copyright (c) 2016 The Chromium Authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+ |
+#include <algorithm> |
+#include <iterator> |
+#include <string> |
+ |
+#include "base/containers/flat_map.h" |
+#include "base/containers/flat_set.h" |
+#include "build/build_config.h" |
+#include "testing/gtest/include/gtest/gtest.h" |
+ |
+namespace { |
+ |
+std::string Serialize(const std::string& that) { |
+ return that; |
+} |
+ |
+std::string Serialize(int that) { |
+ return std::to_string(that); |
+} |
+ |
+template <typename First, typename Second> |
+std::string Serialize(const std::pair<First, Second>& that) { |
+ return std::string("{") + Serialize(that.first) + ", " + |
+ Serialize(that.second) + std::string("}"); |
+} |
+ |
+template <typename Range> |
+std::string Serialize(const Range& range) { |
+ std::string res = "["; |
+ auto it = std::begin(range); |
+ res += Serialize(*it); |
+ for (++it; it != std::end(range); ++it) { |
+ res += ", " + Serialize(*it); |
+ } |
+ return res + ']'; |
+} |
+ |
+template <typename Lhs, typename Rhs> |
+std::string ExpectedActualMsg(const Lhs& expected, const Rhs& rhs) { |
+ return "\nExpected: " + Serialize(expected) + "\nDesired: " + Serialize(rhs); |
+} |
+ |
+struct AnyPairEquals { |
+ template <typename Lhs, typename Rhs> |
+ bool operator()(const Lhs& lhs, const Rhs& rhs) { |
+ return lhs == rhs; |
+ } |
+ template <typename L1, typename L2, typename R1, typename R2> |
+ bool operator()(const std::pair<L1, L2>& lhs, const std::pair<R1, R2>& rhs) { |
+ return lhs.first == rhs.first && lhs.second == rhs.second; |
+ } |
+}; |
+ |
+template <typename FlatMap, typename TestRange> |
+bool check_map(const FlatMap& fl_map, const TestRange& test) { |
+ auto test_beg = std::begin(test); |
+ auto test_end = std::end(test); |
+ if (static_cast<typename FlatMap::size_type>( |
+ std::distance(test_beg, test_end)) != fl_map.size()) |
+ return false; |
+ return std::equal(fl_map.begin(), fl_map.end(), test_beg, AnyPairEquals()); |
+} |
+ |
+} // namespace |
+ |
+// this makes the compiler to instantiate everything |
+template class base::flat_map<std::unique_ptr<int>, std::unique_ptr<int>>; |
+template class base::flat_set<std::unique_ptr<int>>; |
+ |
+using RegularFlatMap = base::flat_map<std::string, int>; |
+using RegularFlatSet = base::flat_set<std::string>; |
+ |
+std::vector<RegularFlatMap::value_type> RegularKeyValuePairs() { |
+ RegularFlatMap::value_type key_value_pairs[] = { |
+ {"b", 3}, |
+ {"b", 5}, |
+ {"a", 3}, |
+ {"fr", 3}, |
+ {"fa", 3}, |
+ {"d", 12}, |
+ {"a", 7}, |
+ {"long", 1233}, |
+ {"q", 0}, |
+ }; |
+ return std::vector<RegularFlatMap::value_type>(std::begin(key_value_pairs), |
+ std::end(key_value_pairs)); |
+} |
+ |
+std::vector<RegularFlatSet::value_type> RegularKeys() { |
+ auto key_value_pairs = RegularKeyValuePairs(); |
+ std::vector<RegularFlatSet::value_type> keys; |
+ keys.reserve(key_value_pairs.size()); |
+ for (const auto& kv_pair : key_value_pairs) |
+ keys.push_back(kv_pair.first); |
+ return keys; |
+} |
+ |
+template <typename FlatCont, typename StdCont, typename KeyValuePairs> |
+void insert_test(const KeyValuePairs& key_value_pairs) { |
+ { |
+ const char prefix[] = "<it, bool> insert (value) "; |
+ FlatCont fl_cont; |
+ StdCont test_cont; |
+ for (const auto& test_case : key_value_pairs) { |
+ std::pair<typename FlatCont::iterator, bool> fl_insert = |
+ fl_cont.insert(test_case); |
+ std::pair<typename StdCont::iterator, bool> test_insert = |
+ test_cont.insert(test_case); |
+ |
+ EXPECT_TRUE(check_map(fl_cont, test_cont)) |
+ << prefix << ExpectedActualMsg(test_cont, fl_cont); |
+ EXPECT_EQ(std::distance(fl_cont.begin(), fl_insert.first), |
+ std::distance(test_cont.begin(), test_insert.first)) |
+ << prefix; |
+ EXPECT_EQ(fl_insert.second, test_insert.second) << prefix; |
+ } |
+ } |
+ { |
+ const char prefix[] = "it insert (hint, value) "; |
+ FlatCont fl_cont; |
+ StdCont test_cont; |
+ auto fl_hint = fl_cont.begin(); |
+ auto test_hint = test_cont.begin(); |
+ for (const auto& test_case : key_value_pairs) { |
+ fl_hint = fl_cont.insert(fl_hint, test_case); |
+ test_hint = test_cont.insert(test_hint, test_case); |
+ |
+ EXPECT_TRUE(check_map(fl_cont, test_cont)) |
+ << prefix << ExpectedActualMsg(test_cont, fl_cont); |
+ EXPECT_EQ(std::distance(fl_cont.begin(), fl_hint), |
+ std::distance(test_cont.begin(), test_hint)) |
+ << prefix; |
+ } |
+ } |
+ { |
+ const char prefix[] = "void insert (first, last) "; |
+ FlatCont fl_cont; |
+ StdCont test_cont; |
+ fl_cont.insert(std::begin(key_value_pairs), std::end(key_value_pairs)); |
+ test_cont.insert(std::begin(key_value_pairs), std::end(key_value_pairs)); |
+ EXPECT_TRUE(check_map(fl_cont, test_cont)) |
+ << prefix << ExpectedActualMsg(test_cont, fl_cont); |
+ } |
+ |
+#ifndef OS_LINUX // on linux an older version of standard library is used. |
+ { |
+ const char prefix[] = "<it, bool> emplace(args...) "; |
+ FlatCont fl_cont; |
+ StdCont test_cont; |
+ for (const auto& test_case : key_value_pairs) { |
+ std::pair<typename FlatCont::iterator, bool> fl_emplace = |
+ fl_cont.emplace(test_case); |
+ std::pair<typename StdCont::iterator, bool> test_emplace = |
+ test_cont.emplace(test_case); |
+ |
+ EXPECT_TRUE(check_map(fl_cont, test_cont)) |
+ << prefix << ExpectedActualMsg(test_cont, fl_cont); |
+ EXPECT_EQ(std::distance(fl_cont.begin(), fl_emplace.first), |
+ std::distance(test_cont.begin(), test_emplace.first)) |
+ << prefix; |
+ EXPECT_EQ(fl_emplace.second, test_emplace.second) << prefix; |
+ } |
+ } |
+ |
+ { |
+ const char prefix[] = "it emplace_hint (hint, value) "; |
+ FlatCont fl_cont; |
+ StdCont test_cont; |
+ auto fl_hint = fl_cont.begin(); |
+ auto test_hint = test_cont.begin(); |
+ for (const auto& test_case : key_value_pairs) { |
+ fl_hint = fl_cont.emplace_hint(fl_hint, test_case); |
+ test_hint = test_cont.emplace_hint(test_hint, test_case); |
+ |
+ EXPECT_TRUE(check_map(fl_cont, test_cont)) |
+ << prefix << ExpectedActualMsg(test_cont, fl_cont); |
+ EXPECT_EQ(std::distance(fl_cont.begin(), fl_hint), |
+ std::distance(test_cont.begin(), test_hint)) |
+ << prefix; |
+ } |
+ } |
+#endif // OS_LINUX |
+} |
+ |
+TEST(FlatMapTest, Insertions) { |
+ using FlatMap = RegularFlatMap; |
+ using FlatSet = RegularFlatSet; |
+ using StdMap = RegularFlatMap::std_map; |
+ using StdSet = RegularFlatSet::std_set; |
+ |
+ auto key_value_pairs = RegularKeyValuePairs(); |
+ auto keys = RegularKeys(); |
+ |
+ { |
+ const char prefix[] = "operator[] "; |
+ FlatMap fl_map; |
+ StdMap test_map; |
+ for (const auto& test_case : key_value_pairs) { |
+ fl_map[test_case.first] = test_case.second; |
+ test_map[test_case.first] = test_case.second; |
+ EXPECT_TRUE(check_map(fl_map, test_map)) |
+ << prefix << ExpectedActualMsg(test_map, fl_map); |
+ } |
+ } |
+ |
+ insert_test<FlatMap, StdMap>(key_value_pairs); |
+ insert_test<FlatSet, StdSet>(keys); |
+} |
+ |
+template <typename FlatCont, typename StdCont, typename KeyValuePairs> |
+void regular_type_test(const KeyValuePairs& key_value_pairs) { |
+ { |
+ const char prefix[] = "default "; |
+ FlatCont fl_cont; |
+ StdCont test_cont; |
+ EXPECT_TRUE(check_map(fl_cont, test_cont)) |
+ << prefix << ExpectedActualMsg(test_cont, fl_cont); |
+ } |
+ { |
+ const char prefix[] = "from underlying type "; |
+ FlatCont fl_cont((typename FlatCont::underlying_type(key_value_pairs))); |
+ StdCont test_cont(key_value_pairs.begin(), key_value_pairs.end()); |
+ EXPECT_TRUE(check_map(fl_cont, test_cont)) |
+ << prefix << ExpectedActualMsg(test_cont, fl_cont); |
+ } |
+ { |
+ const char prefix[] = "from iterators "; |
+ FlatCont fl_cont(key_value_pairs.begin(), key_value_pairs.end()); |
+ StdCont test_cont(key_value_pairs.begin(), key_value_pairs.end()); |
+ EXPECT_TRUE(check_map(fl_cont, test_cont)) |
+ << prefix << ExpectedActualMsg(test_cont, fl_cont); |
+ } |
+ { |
+ const char prefix[] = "copy "; |
+ FlatCont fl_cont(key_value_pairs.begin(), key_value_pairs.end()); |
+ StdCont test_cont(key_value_pairs.begin(), key_value_pairs.end()); |
+ |
+ FlatCont fl_cont1 = fl_cont; |
+ StdCont test_cont1 = test_cont; |
+ EXPECT_TRUE(check_map(fl_cont, test_cont)) |
+ << prefix << ExpectedActualMsg(test_cont, fl_cont); |
+ } |
+ { |
+ const char prefix[] = "copy assign"; |
+ FlatCont fl_cont(key_value_pairs.begin(), key_value_pairs.end()); |
+ StdCont test_cont(key_value_pairs.begin(), key_value_pairs.end()); |
+ |
+ FlatCont fl_cont1; |
+ fl_cont1 = fl_cont; |
+ StdCont test_cont1; |
+ test_cont1 = test_cont; |
+ EXPECT_TRUE(check_map(fl_cont, test_cont)) |
+ << prefix << ExpectedActualMsg(test_cont, fl_cont); |
+ } |
+ { |
+ const char prefix[] = "move "; |
+ FlatCont fl_cont(key_value_pairs.begin(), key_value_pairs.end()); |
+ StdCont test_cont(key_value_pairs.begin(), key_value_pairs.end()); |
+ |
+ FlatCont fl_cont1 = std::move(fl_cont); |
+ StdCont test_cont1 = std::move(test_cont); |
+ EXPECT_TRUE(check_map(fl_cont, test_cont)) |
+ << prefix << ExpectedActualMsg(test_cont, fl_cont); |
+ } |
+ { |
+ const char prefix[] = "move assign"; |
+ FlatCont fl_cont(key_value_pairs.begin(), key_value_pairs.end()); |
+ StdCont test_cont(key_value_pairs.begin(), key_value_pairs.end()); |
+ |
+ FlatCont fl_cont1; |
+ fl_cont1 = std::move(fl_cont); |
+ StdCont test_cont1; |
+ test_cont1 = std::move(test_cont); |
+ EXPECT_TRUE(check_map(fl_cont, test_cont)) |
+ << prefix << ExpectedActualMsg(test_cont, fl_cont); |
+ } |
+ { |
+ const char prefix[] = "comparators "; |
+ FlatCont lhs(key_value_pairs.begin(), key_value_pairs.end()); |
+ FlatCont rhs(key_value_pairs.begin(), key_value_pairs.end()); |
+ EXPECT_EQ(lhs, rhs); |
+ lhs.erase(lhs.begin() + 5, lhs.end()); |
+ EXPECT_NE(lhs, rhs) << prefix << ExpectedActualMsg(lhs, rhs); |
+ EXPECT_TRUE(lhs < rhs) << prefix << ExpectedActualMsg(lhs, rhs); |
+ EXPECT_LE(lhs, rhs) << prefix << ExpectedActualMsg(lhs, rhs); |
+ |
+ EXPECT_GT(rhs, lhs) << prefix << ExpectedActualMsg(lhs, rhs); |
+ EXPECT_GE(rhs, lhs) << prefix << ExpectedActualMsg(lhs, rhs); |
+ } |
+} |
+ |
+TEST(FlatMapTest, RegularTypeAndConstructors) { |
+ using FlatMap = RegularFlatMap; |
+ using StdMap = RegularFlatMap::std_map; |
+ using FlatSet = RegularFlatSet; |
+ using StdSet = RegularFlatSet::std_set; |
+ |
+ auto key_value_pairs = RegularKeyValuePairs(); |
+ auto keys = RegularKeys(); |
+ |
+ regular_type_test<FlatMap, StdMap>(key_value_pairs); |
+ regular_type_test<FlatSet, StdSet>(keys); |
+ |
+ { |
+ const char prefix[] = "comparators "; |
+ FlatMap lhs(key_value_pairs.begin(), key_value_pairs.end()); |
+ FlatMap rhs(key_value_pairs.begin(), key_value_pairs.end()); |
+ EXPECT_EQ(lhs, rhs); |
+ lhs.erase(lhs.begin() + 5, lhs.end()); |
+ EXPECT_NE(lhs, rhs) << prefix << ExpectedActualMsg(lhs, rhs); |
+ EXPECT_TRUE(lhs < rhs) << prefix << ExpectedActualMsg(lhs, rhs); |
+ EXPECT_LE(lhs, rhs) << prefix << ExpectedActualMsg(lhs, rhs); |
+ |
+ EXPECT_GT(rhs, lhs) << prefix << ExpectedActualMsg(lhs, rhs); |
+ EXPECT_GE(rhs, lhs) << prefix << ExpectedActualMsg(lhs, rhs); |
+ } |
+ { |
+ const char prefix[] = "swap "; |
+ FlatMap lhs(key_value_pairs.begin(), key_value_pairs.end()); |
+ FlatMap rhs(key_value_pairs.begin(), key_value_pairs.end()); |
+ lhs.erase(lhs.begin() + 5, lhs.end()); |
+ |
+ FlatMap::underlying_type original_lhs(lhs.begin(), lhs.end()); |
+ FlatMap::underlying_type original_rhs(rhs.begin(), rhs.end()); |
+ |
+ swap(lhs, rhs); |
+ EXPECT_TRUE(check_map(lhs, original_rhs)) |
+ << prefix << ExpectedActualMsg(original_rhs, lhs); |
+ EXPECT_TRUE(check_map(rhs, original_lhs)) |
+ << prefix << ExpectedActualMsg(original_lhs, rhs); |
+ |
+ lhs.swap(rhs); |
+ EXPECT_TRUE(check_map(lhs, original_lhs)) |
+ << prefix << ExpectedActualMsg(original_lhs, lhs); |
+ EXPECT_TRUE(check_map(rhs, original_rhs)) |
+ << prefix << ExpectedActualMsg(original_rhs, rhs); |
+ } |
+} |
+ |
+TEST(FlatMapTest, Getters) { |
+ using FlatMap = RegularFlatMap; |
+ using StdMap = RegularFlatMap::std_map; |
+ |
+ auto key_value_pairs = RegularKeyValuePairs(); |
+ std::vector<FlatMap::key_type> keys; |
+ keys.reserve(key_value_pairs.size()); |
+ for (const auto& kv_pair : key_value_pairs) |
+ keys.push_back(kv_pair.first); |
+ |
+ { |
+ const char prefix[] = "at(key) "; |
+ FlatMap fl_map(key_value_pairs.begin(), key_value_pairs.end()); |
+ StdMap test_map(key_value_pairs.begin(), key_value_pairs.end()); |
+ const FlatMap& fl_const = fl_map; |
+ const StdMap& test_const = test_map; |
+ for (const auto& key : keys) { |
+ EXPECT_EQ(fl_map.at(key), test_map.at(key)) << prefix << key; |
+ EXPECT_EQ(fl_const.at(key), test_const.at(key)) << prefix << key; |
+ } |
+ } |
+ |
+ { |
+ const char prefix[] = "count(key) "; |
+ FlatMap fl_map(key_value_pairs.begin(), key_value_pairs.end()); |
+ StdMap test_map(key_value_pairs.begin(), key_value_pairs.end()); |
+ for (const auto& key : keys) { |
+ EXPECT_EQ(fl_map.count(key), test_map.count(key)) << prefix << key; |
+ } |
+ } |
+ |
+ // empty, size, max_size |
+ { |
+ FlatMap fl_map; |
+ EXPECT_TRUE(fl_map.empty()); |
+ EXPECT_EQ(fl_map.size(), FlatMap::size_type(0)); |
+ EXPECT_EQ(fl_map.max_size(), FlatMap::underlying_type().max_size()); |
+ } |
+ |
+ { |
+ const char prefix[] = "it find (key) "; |
+ FlatMap fl_map(key_value_pairs.begin(), key_value_pairs.end()); |
+ StdMap test_map(key_value_pairs.begin(), key_value_pairs.end()); |
+ const FlatMap& fl_const = fl_map; |
+ const StdMap& test_const = test_map; |
+ |
+ for (const auto& key : keys) { |
+ auto fl_found = fl_map.find(key); |
+ auto test_found = test_map.find(key); |
+ auto fl_const_found = fl_const.find(key); |
+ auto test_const_found = test_const.find(key); |
+ |
+ EXPECT_EQ(std::distance(fl_map.begin(), fl_found), |
+ std::distance(test_map.begin(), test_found)) |
+ << prefix; |
+ EXPECT_EQ(std::distance(fl_found, fl_map.end()), |
+ std::distance(test_found, test_map.end())) |
+ << prefix; |
+ EXPECT_EQ(std::distance(fl_const.begin(), fl_const_found), |
+ std::distance(test_const.begin(), test_const_found)) |
+ << prefix; |
+ EXPECT_EQ(std::distance(fl_const_found, fl_const.end()), |
+ std::distance(test_const_found, test_const.end())) |
+ << prefix; |
+ } |
+ } |
+ |
+ { |
+ const char prefix[] = "<it, it> equal_range (key) "; |
+ FlatMap fl_map(key_value_pairs.begin(), key_value_pairs.end()); |
+ StdMap test_map(key_value_pairs.begin(), key_value_pairs.end()); |
+ const FlatMap& fl_const = fl_map; |
+ const StdMap& test_const = test_map; |
+ |
+ for (const auto& key : keys) { |
+ auto fl_found = fl_map.equal_range(key); |
+ auto test_found = test_map.equal_range(key); |
+ auto fl_const_found = fl_const.equal_range(key); |
+ auto test_const_found = test_const.equal_range(key); |
+ |
+ EXPECT_EQ(std::distance(fl_map.begin(), fl_found.first), |
+ std::distance(test_map.begin(), test_found.first)) |
+ << prefix; |
+ EXPECT_EQ(std::distance(fl_found.first, fl_found.second), |
+ std::distance(test_found.first, test_found.second)) |
+ << prefix; |
+ EXPECT_EQ(std::distance(fl_found.second, fl_map.end()), |
+ std::distance(test_found.second, test_map.end())) |
+ << prefix; |
+ |
+ EXPECT_EQ(std::distance(fl_const.begin(), fl_const_found.first), |
+ std::distance(test_const.begin(), test_const_found.first)) |
+ << prefix; |
+ EXPECT_EQ(std::distance(fl_const_found.first, fl_const_found.second), |
+ std::distance(test_const_found.first, test_const_found.second)) |
+ << prefix; |
+ EXPECT_EQ(std::distance(fl_const_found.second, fl_const.end()), |
+ std::distance(test_const_found.second, test_const.end())) |
+ << prefix; |
+ } |
+ } |
+ |
+ { |
+ const char prefix[] = "it lower_bound (key) "; |
+ FlatMap fl_map(key_value_pairs.begin(), key_value_pairs.end()); |
+ StdMap test_map(key_value_pairs.begin(), key_value_pairs.end()); |
+ const FlatMap& fl_const = fl_map; |
+ const StdMap& test_const = test_map; |
+ |
+ for (const auto& key : keys) { |
+ auto fl_found = fl_map.lower_bound(key); |
+ auto test_found = test_map.lower_bound(key); |
+ auto fl_const_found = fl_const.lower_bound(key); |
+ auto test_const_found = test_const.lower_bound(key); |
+ |
+ EXPECT_EQ(std::distance(fl_map.begin(), fl_found), |
+ std::distance(test_map.begin(), test_found)) |
+ << prefix; |
+ EXPECT_EQ(std::distance(fl_found, fl_map.end()), |
+ std::distance(test_found, test_map.end())) |
+ << prefix; |
+ EXPECT_EQ(std::distance(fl_const.begin(), fl_const_found), |
+ std::distance(test_const.begin(), test_const_found)) |
+ << prefix; |
+ EXPECT_EQ(std::distance(fl_const_found, fl_const.end()), |
+ std::distance(test_const_found, test_const.end())) |
+ << prefix; |
+ } |
+ } |
+ { |
+ const char prefix[] = "it upper_bound (key) "; |
+ FlatMap fl_map(key_value_pairs.begin(), key_value_pairs.end()); |
+ StdMap test_map(key_value_pairs.begin(), key_value_pairs.end()); |
+ const FlatMap& fl_const = fl_map; |
+ const StdMap& test_const = test_map; |
+ |
+ for (const auto& key : keys) { |
+ auto fl_found = fl_map.upper_bound(key); |
+ auto test_found = test_map.upper_bound(key); |
+ auto fl_const_found = fl_const.upper_bound(key); |
+ auto test_const_found = test_const.upper_bound(key); |
+ |
+ EXPECT_EQ(std::distance(fl_map.begin(), fl_found), |
+ std::distance(test_map.begin(), test_found)) |
+ << prefix; |
+ EXPECT_EQ(std::distance(fl_found, fl_map.end()), |
+ std::distance(test_found, test_map.end())) |
+ << prefix; |
+ EXPECT_EQ(std::distance(fl_const.begin(), fl_const_found), |
+ std::distance(test_const.begin(), test_const_found)) |
+ << prefix; |
+ EXPECT_EQ(std::distance(fl_const_found, fl_const.end()), |
+ std::distance(test_const_found, test_const.end())) |
+ << prefix; |
+ } |
+ } |
+} |