1 /*
2 * Copyright (C) 2015 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include "variant_map.h"
18 #include "gtest/gtest.h"
19
20 #define EXPECT_NULL(expected) EXPECT_EQ(reinterpret_cast<const void*>(expected), \
21 static_cast<void*>(nullptr));
22
23 namespace art {
24
25 namespace {
26 template <typename TValue>
27 struct FruitMapKey : VariantMapKey<TValue> {
FruitMapKeyart::__anon42d105570111::FruitMapKey28 FruitMapKey() {}
29 };
30
31 struct FruitMap : VariantMap<FruitMap, FruitMapKey> {
32 // This 'using' line is necessary to inherit the variadic constructor.
33 using VariantMap<FruitMap, FruitMapKey>::VariantMap;
34
35 // Make the next '4' usages of Key slightly shorter to type.
36 template <typename TValue>
37 using Key = FruitMapKey<TValue>;
38
39 static const Key<int> Apple;
40 static const Key<double> Orange;
41 static const Key<std::string> Label;
42 };
43
44 const FruitMap::Key<int> FruitMap::Apple;
45 const FruitMap::Key<double> FruitMap::Orange;
46 const FruitMap::Key<std::string> FruitMap::Label;
47 } // namespace
48
TEST(VariantMaps,BasicReadWrite)49 TEST(VariantMaps, BasicReadWrite) {
50 FruitMap fm;
51
52 EXPECT_NULL(fm.Get(FruitMap::Apple));
53 EXPECT_FALSE(fm.Exists(FruitMap::Apple));
54 EXPECT_NULL(fm.Get(FruitMap::Orange));
55 EXPECT_FALSE(fm.Exists(FruitMap::Orange));
56
57 fm.Set(FruitMap::Apple, 1);
58 EXPECT_NULL(fm.Get(FruitMap::Orange));
59 EXPECT_EQ(1, *fm.Get(FruitMap::Apple));
60 EXPECT_TRUE(fm.Exists(FruitMap::Apple));
61
62 fm.Set(FruitMap::Apple, 5);
63 EXPECT_NULL(fm.Get(FruitMap::Orange));
64 EXPECT_EQ(5, *fm.Get(FruitMap::Apple));
65 EXPECT_TRUE(fm.Exists(FruitMap::Apple));
66
67 fm.Set(FruitMap::Orange, 555.0);
68 EXPECT_EQ(5, *fm.Get(FruitMap::Apple));
69 EXPECT_DOUBLE_EQ(555.0, *fm.Get(FruitMap::Orange));
70 EXPECT_EQ(size_t(2), fm.Size());
71
72 // Simple remove
73 fm.Remove(FruitMap::Apple);
74 EXPECT_FALSE(fm.Exists(FruitMap::Apple));
75
76 fm.Clear();
77 EXPECT_EQ(size_t(0), fm.Size());
78 EXPECT_FALSE(fm.Exists(FruitMap::Orange));
79 }
80
TEST(VariantMaps,SetPreviousValue)81 TEST(VariantMaps, SetPreviousValue) {
82 FruitMap fm;
83
84 // Indirect remove by setting yourself again
85 fm.Set(FruitMap::Label, std::string("hello_world"));
86 auto* ptr = fm.Get(FruitMap::Label);
87 ASSERT_TRUE(ptr != nullptr);
88 *ptr = "foobar";
89
90 // Set the value to the same exact pointer which we got out of the map.
91 // This should cleanly 'just work' and not try to delete the value too early.
92 fm.Set(FruitMap::Label, *ptr);
93
94 auto* new_ptr = fm.Get(FruitMap::Label);
95 ASSERT_TRUE(ptr != nullptr);
96 EXPECT_EQ(std::string("foobar"), *new_ptr);
97 }
98
TEST(VariantMaps,RuleOfFive)99 TEST(VariantMaps, RuleOfFive) {
100 // Test empty constructor
101 FruitMap fmEmpty;
102 EXPECT_EQ(size_t(0), fmEmpty.Size());
103
104 // Test empty constructor
105 FruitMap fmFilled;
106 fmFilled.Set(FruitMap::Apple, 1);
107 fmFilled.Set(FruitMap::Orange, 555.0);
108 EXPECT_EQ(size_t(2), fmFilled.Size());
109
110 // Test copy constructor (NOLINT as a reference is suggested, instead)
111 FruitMap fmEmptyCopy(fmEmpty); // NOLINT
112 EXPECT_EQ(size_t(0), fmEmptyCopy.Size());
113
114 // Test copy constructor
115 FruitMap fmFilledCopy(fmFilled);
116 EXPECT_EQ(size_t(2), fmFilledCopy.Size());
117 EXPECT_EQ(*fmFilled.Get(FruitMap::Apple), *fmFilledCopy.Get(FruitMap::Apple));
118 EXPECT_DOUBLE_EQ(*fmFilled.Get(FruitMap::Orange), *fmFilledCopy.Get(FruitMap::Orange));
119
120 // Test operator=
121 FruitMap fmFilledCopy2;
122 fmFilledCopy2 = fmFilled;
123 EXPECT_EQ(size_t(2), fmFilledCopy2.Size());
124 EXPECT_EQ(*fmFilled.Get(FruitMap::Apple), *fmFilledCopy2.Get(FruitMap::Apple));
125 EXPECT_DOUBLE_EQ(*fmFilled.Get(FruitMap::Orange), *fmFilledCopy2.Get(FruitMap::Orange));
126
127 // Test move constructor
128 FruitMap fmMoved(std::move(fmFilledCopy));
129 EXPECT_EQ(size_t(0), fmFilledCopy.Size());
130 EXPECT_EQ(size_t(2), fmMoved.Size());
131 EXPECT_EQ(*fmFilled.Get(FruitMap::Apple), *fmMoved.Get(FruitMap::Apple));
132 EXPECT_DOUBLE_EQ(*fmFilled.Get(FruitMap::Orange), *fmMoved.Get(FruitMap::Orange));
133
134 // Test operator= move
135 FruitMap fmMoved2;
136 fmMoved2.Set(FruitMap::Apple, 12345); // This value will be clobbered after the move
137
138 fmMoved2 = std::move(fmFilledCopy2);
139 EXPECT_EQ(size_t(0), fmFilledCopy2.Size());
140 EXPECT_EQ(size_t(2), fmMoved2.Size());
141 EXPECT_EQ(*fmFilled.Get(FruitMap::Apple), *fmMoved2.Get(FruitMap::Apple));
142 EXPECT_DOUBLE_EQ(*fmFilled.Get(FruitMap::Orange), *fmMoved2.Get(FruitMap::Orange));
143 }
144
TEST(VariantMaps,VariadicConstructors)145 TEST(VariantMaps, VariadicConstructors) {
146 // Variadic constructor, 1 kv/pair
147 FruitMap fmApple(FruitMap::Apple, 12345);
148 EXPECT_EQ(size_t(1), fmApple.Size());
149 EXPECT_EQ(12345, *fmApple.Get(FruitMap::Apple));
150
151 // Variadic constructor, 2 kv/pair
152 FruitMap fmAppleAndOrange(FruitMap::Apple, 12345,
153 FruitMap::Orange, 100.0);
154 EXPECT_EQ(size_t(2), fmAppleAndOrange.Size());
155 EXPECT_EQ(12345, *fmAppleAndOrange.Get(FruitMap::Apple));
156 EXPECT_DOUBLE_EQ(100.0, *fmAppleAndOrange.Get(FruitMap::Orange));
157 }
158
TEST(VariantMaps,ReleaseOrDefault)159 TEST(VariantMaps, ReleaseOrDefault) {
160 FruitMap fmAppleAndOrange(FruitMap::Apple, 12345,
161 FruitMap::Orange, 100.0);
162
163 int apple = fmAppleAndOrange.ReleaseOrDefault(FruitMap::Apple);
164 EXPECT_EQ(12345, apple);
165
166 // Releasing will also remove the Apple key.
167 EXPECT_EQ(size_t(1), fmAppleAndOrange.Size());
168
169 // Releasing again yields a default value.
170 int apple2 = fmAppleAndOrange.ReleaseOrDefault(FruitMap::Apple);
171 EXPECT_EQ(0, apple2);
172 }
173
TEST(VariantMaps,GetOrDefault)174 TEST(VariantMaps, GetOrDefault) {
175 FruitMap fm(FruitMap::Apple, 12345);
176
177 // Apple gives the expected value we set.
178 int apple = fm.GetOrDefault(FruitMap::Apple);
179 EXPECT_EQ(12345, apple);
180
181 // Map is still 1.
182 EXPECT_EQ(size_t(1), fm.Size());
183
184 // Orange gives back a default value, since it's not in the map.
185 double orange = fm.GetOrDefault(FruitMap::Orange);
186 EXPECT_DOUBLE_EQ(0.0, orange);
187 }
188
189 } // namespace art
190