1 // 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 
12 namespace openscreen {
13 
14 namespace {
15 
16 const FlatMap<int, absl::string_view> kSimpleFlatMap{{-1, "bar"},
17                                                      {123, "foo"},
18                                                      {10000, "baz"},
19                                                      {0, ""}};
20 
21 }  // namespace
22 
TEST(FlatMapTest,Find)23 TEST(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?
TEST(FlatMapTest,Access)35 TEST(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);
46   // The error message varies widely depending on how the test is run.
47   // NOTE: Google Test doesn't support death tests on some platforms, such
48   // as iOS.
49 #if defined(GTEST_HAS_DEATH_TEST)
50   EXPECT_DEATH(kSimpleFlatMap.at(31337), ".*");
51 #endif
52 }
53 
TEST(FlatMapTest,ErasureAndEmplacement)54 TEST(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.
64 #if defined(GTEST_HAS_DEATH_TEST)
65   EXPECT_DEATH(mutable_vector.erase_key(12345),
66                ".*failed to erase: element not found.*");
67 #endif
68 }
69 
TEST(FlatMapTest,Mutation)70 TEST(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 
TEST(FlatMapTest,GenerallyBehavesLikeAVector)78 TEST(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 
TEST(FlatMapTest,CanUseNonDefaultConstructibleThings)98 TEST(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
119