blob: 17b690e1ee7066ab65fb4b99a1c74483af753884 [file] [log] [blame]
Jordan Baylesfc4b6232020-11-24 17:10:33 -08001// Copyright 2020 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.
4
5#include "util/flat_map.h"
6
7#include <chrono>
8
9#include "absl/strings/string_view.h"
10#include "gtest/gtest.h"
11
12namespace openscreen {
13
14namespace {
15
16const FlatMap<int, absl::string_view> kSimpleFlatMap{{-1, "bar"},
17 {123, "foo"},
18 {10000, "baz"},
19 {0, ""}};
20
21} // namespace
22
23TEST(FlatMapTest, Find) {
24 EXPECT_EQ(kSimpleFlatMap.begin(), kSimpleFlatMap.find(-1));
25 EXPECT_EQ("bar", kSimpleFlatMap.find(-1)->second);
26 EXPECT_EQ("foo", kSimpleFlatMap.find(123)->second);
27 EXPECT_EQ("baz", kSimpleFlatMap.find(10000)->second);
28 EXPECT_EQ("", kSimpleFlatMap.find(0)->second);
29 EXPECT_EQ(kSimpleFlatMap.end(), kSimpleFlatMap.find(2));
30}
31
32// Since it is backed by a vector, we don't expose an operator[] due
33// to potential confusion. If the type of Key is int or std::size_t, do
34// you want the std::pair<Key, Value> or just the Value?
35TEST(FlatMapTest, Access) {
36 EXPECT_EQ("bar", kSimpleFlatMap[0].second);
37 EXPECT_EQ("foo", kSimpleFlatMap[1].second);
38 EXPECT_EQ("baz", kSimpleFlatMap[2].second);
39 EXPECT_EQ("", kSimpleFlatMap[3].second);
40
41 // NOTE: vector doesn't do any range checking for operator[], only at().
42 EXPECT_EQ("bar", kSimpleFlatMap.at(0).second);
43 EXPECT_EQ("foo", kSimpleFlatMap.at(1).second);
44 EXPECT_EQ("baz", kSimpleFlatMap.at(2).second);
45 EXPECT_EQ("", kSimpleFlatMap.at(3).second);
Jordan Baylesf5b12d62020-11-24 22:34:54 -080046 // The error message varies widely depending on how the test is run.
Jordan Bayles9be11f72020-11-24 23:34:53 -080047 // NOTE: Google Test doesn't support death tests on some platforms, such
48 // as iOS.
49#if defined(GTEST_HAS_DEATH_TEST)
Jordan Baylesf5b12d62020-11-24 22:34:54 -080050 EXPECT_DEATH(kSimpleFlatMap.at(31337), ".*");
Jordan Bayles9be11f72020-11-24 23:34:53 -080051#endif
Jordan Baylesfc4b6232020-11-24 17:10:33 -080052}
53
54TEST(FlatMapTest, ErasureAndEmplacement) {
55 auto mutable_vector = kSimpleFlatMap;
56 EXPECT_NE(mutable_vector.find(-1), mutable_vector.end());
57 mutable_vector.erase_key(-1);
58 EXPECT_EQ(mutable_vector.find(-1), mutable_vector.end());
59
60 mutable_vector.emplace_back(-1, "bar");
61 EXPECT_NE(mutable_vector.find(-1), mutable_vector.end());
62
63 // We absolutely should fail to erase something that's not there.
Jordan Bayles9be11f72020-11-24 23:34:53 -080064#if defined(GTEST_HAS_DEATH_TEST)
Jordan Baylesfc4b6232020-11-24 17:10:33 -080065 EXPECT_DEATH(mutable_vector.erase_key(12345),
66 ".*failed to erase: element not found.*");
Jordan Bayles9be11f72020-11-24 23:34:53 -080067#endif
Jordan Baylesfc4b6232020-11-24 17:10:33 -080068}
69
70TEST(FlatMapTest, Mutation) {
71 FlatMap<int, int> mutable_vector{{1, 2}};
72 EXPECT_EQ(2, mutable_vector[0].second);
73
74 mutable_vector[0].second = 3;
75 EXPECT_EQ(3, mutable_vector[0].second);
76}
77
78TEST(FlatMapTest, GenerallyBehavesLikeAVector) {
79 EXPECT_EQ(kSimpleFlatMap, kSimpleFlatMap);
80 EXPECT_TRUE(kSimpleFlatMap == kSimpleFlatMap);
81
82 for (auto& entry : kSimpleFlatMap) {
83 if (entry.first != 0) {
84 EXPECT_LT(0u, entry.second.size());
85 }
86 }
87
88 FlatMap<int, int> simple;
89 simple.emplace_back(1, 10);
90 EXPECT_EQ(simple, (FlatMap<int, int>{{1, 10}}));
91
92 auto it = simple.find(1);
93 ASSERT_NE(it, simple.end());
94 simple.erase(it);
95 EXPECT_EQ(simple.find(1), simple.end());
96}
97
98TEST(FlatMapTest, CanUseNonDefaultConstructibleThings) {
99 class NonDefaultConstructible {
100 public:
101 NonDefaultConstructible(int x, int y) : x_(x), y_(y) {}
102
103 int x() { return x_; }
104
105 int y() { return y_; }
106
107 private:
108 int x_;
109 int y_;
110 };
111
112 FlatMap<int, NonDefaultConstructible> flat_map;
113 flat_map.emplace_back(3, NonDefaultConstructible(2, 3));
114 auto it = flat_map.find(3);
115 ASSERT_TRUE(it != flat_map.end());
116 EXPECT_GT(it->second.y(), it->second.x());
117}
118} // namespace openscreen