Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(570)

Unified Diff: base/containers/flat_sorted_containers_unittest.cc

Issue 2333253002: flat containers prototype (Closed)
Patch Set: Fixing performance bug in insert(It, It) Created 4 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
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;
+ }
+ }
+}

Powered by Google App Engine
This is Rietveld 408576698