1 // Copyright 2014 The Chromium OS 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 <algorithm>
6 #include <functional>
7 #include <string>
8 #include <utility>
9 #include <vector>
10
11 #include <brillo/any.h>
12 #include <gtest/gtest.h>
13
14 using brillo::Any;
15
TEST(Any,Empty)16 TEST(Any, Empty) {
17 Any val;
18 EXPECT_TRUE(val.IsEmpty());
19
20 Any val2 = val;
21 EXPECT_TRUE(val.IsEmpty());
22 EXPECT_TRUE(val2.IsEmpty());
23
24 Any val3 = std::move(val);
25 EXPECT_TRUE(val.IsEmpty());
26 EXPECT_TRUE(val3.IsEmpty());
27 }
28
TEST(Any,SimpleTypes)29 TEST(Any, SimpleTypes) {
30 Any val(20);
31 EXPECT_FALSE(val.IsEmpty());
32 EXPECT_TRUE(val.IsTypeCompatible<int>());
33 EXPECT_EQ(20, val.Get<int>());
34
35 Any val2(3.1415926);
36 EXPECT_FALSE(val2.IsEmpty());
37 EXPECT_TRUE(val2.IsTypeCompatible<double>());
38 EXPECT_FALSE(val2.IsTypeCompatible<int>());
39 EXPECT_DOUBLE_EQ(3.1415926, val2.Get<double>());
40
41 Any val3(std::string("blah"));
42 EXPECT_TRUE(val3.IsTypeCompatible<std::string>());
43 EXPECT_EQ("blah", val3.Get<std::string>());
44 }
45
TEST(Any,Clear)46 TEST(Any, Clear) {
47 Any val('x');
48 EXPECT_FALSE(val.IsEmpty());
49 EXPECT_EQ('x', val.Get<char>());
50
51 val.Clear();
52 EXPECT_TRUE(val.IsEmpty());
53 }
54
TEST(Any,Assignments)55 TEST(Any, Assignments) {
56 Any val(20);
57 EXPECT_EQ(20, val.Get<int>());
58
59 val = 3.1415926;
60 EXPECT_FALSE(val.IsEmpty());
61 EXPECT_TRUE(val.IsTypeCompatible<double>());
62 EXPECT_DOUBLE_EQ(3.1415926, val.Get<double>());
63
64 val = std::string("blah");
65 EXPECT_EQ("blah", val.Get<std::string>());
66
67 Any val2;
68 EXPECT_TRUE(val2.IsEmpty());
69 val2 = val;
70 EXPECT_FALSE(val.IsEmpty());
71 EXPECT_FALSE(val2.IsEmpty());
72 EXPECT_EQ("blah", val.Get<std::string>());
73 EXPECT_EQ("blah", val2.Get<std::string>());
74 val.Clear();
75 EXPECT_TRUE(val.IsEmpty());
76 EXPECT_EQ("blah", val2.Get<std::string>());
77 val2.Clear();
78 EXPECT_TRUE(val2.IsEmpty());
79
80 val = std::vector<int>{100, 20, 3};
81 auto v = val.Get<std::vector<int>>();
82 EXPECT_EQ(100, v[0]);
83 EXPECT_EQ(20, v[1]);
84 EXPECT_EQ(3, v[2]);
85
86 val2 = std::move(val);
87 EXPECT_TRUE(val.IsEmpty());
88 EXPECT_TRUE(val2.IsTypeCompatible<std::vector<int>>());
89 EXPECT_EQ(3, val2.Get<std::vector<int>>().size());
90
91 val = val2;
92 EXPECT_TRUE(val.IsTypeCompatible<std::vector<int>>());
93 EXPECT_TRUE(val2.IsTypeCompatible<std::vector<int>>());
94 EXPECT_EQ(3, val.Get<std::vector<int>>().size());
95 EXPECT_EQ(3, val2.Get<std::vector<int>>().size());
96 }
97
TEST(Any,Enums)98 TEST(Any, Enums) {
99 enum class Dummy { foo, bar, baz };
100 Any val(Dummy::bar);
101 EXPECT_FALSE(val.IsEmpty());
102 EXPECT_TRUE(val.IsConvertibleToInteger());
103 EXPECT_EQ(Dummy::bar, val.Get<Dummy>());
104 EXPECT_EQ(1, val.GetAsInteger());
105
106 val = Dummy::baz;
107 EXPECT_EQ(2, val.GetAsInteger());
108
109 val = Dummy::foo;
110 EXPECT_EQ(0, val.GetAsInteger());
111 }
112
TEST(Any,Integers)113 TEST(Any, Integers) {
114 Any val(14);
115 EXPECT_TRUE(val.IsConvertibleToInteger());
116 EXPECT_EQ(14, val.Get<int>());
117 EXPECT_EQ(14, val.GetAsInteger());
118
119 val = '\x40';
120 EXPECT_TRUE(val.IsConvertibleToInteger());
121 EXPECT_EQ(64, val.Get<char>());
122 EXPECT_EQ(64, val.GetAsInteger());
123
124 val = static_cast<uint16_t>(65535);
125 EXPECT_TRUE(val.IsConvertibleToInteger());
126 EXPECT_EQ(65535, val.Get<uint16_t>());
127 EXPECT_EQ(65535, val.GetAsInteger());
128
129 val = static_cast<uint64_t>(0xFFFFFFFFFFFFFFFFULL);
130 EXPECT_TRUE(val.IsConvertibleToInteger());
131 EXPECT_EQ(0xFFFFFFFFFFFFFFFFULL, val.Get<uint64_t>());
132 EXPECT_EQ(-1, val.GetAsInteger());
133
134 val = "abc";
135 EXPECT_FALSE(val.IsConvertibleToInteger());
136
137 int a = 5;
138 val = &a;
139 EXPECT_FALSE(val.IsConvertibleToInteger());
140 }
141
TEST(Any,Pointers)142 TEST(Any, Pointers) {
143 Any val("abc"); // const char*
144 EXPECT_FALSE(val.IsTypeCompatible<char*>());
145 EXPECT_TRUE(val.IsTypeCompatible<const char*>());
146 EXPECT_FALSE(val.IsTypeCompatible<volatile char*>());
147 EXPECT_TRUE(val.IsTypeCompatible<volatile const char*>());
148 EXPECT_STREQ("abc", val.Get<const char*>());
149
150 int a = 10;
151 val = &a;
152 EXPECT_TRUE(val.IsTypeCompatible<int*>());
153 EXPECT_TRUE(val.IsTypeCompatible<const int*>());
154 EXPECT_TRUE(val.IsTypeCompatible<volatile int*>());
155 EXPECT_TRUE(val.IsTypeCompatible<volatile const int*>());
156 EXPECT_EQ(10, *val.Get<const int*>());
157 *val.Get<int*>() = 3;
158 EXPECT_EQ(3, a);
159 }
160
TEST(Any,Arrays)161 TEST(Any, Arrays) {
162 // The following test are here to validate the array-to-pointer decay rules.
163 // Since Any does not store the contents of a C-style array, just a pointer
164 // to the data, putting array data into Any could be dangerous.
165 // Make sure the array's lifetime exceeds that of an Any containing the
166 // pointer to the array data.
167 // If you want to store the array with data, use corresponding value types
168 // such as std::vector or a struct containing C-style array as a member.
169
170 int int_array[] = {1, 2, 3}; // int*
171 Any val = int_array;
172 EXPECT_TRUE(val.IsTypeCompatible<int*>());
173 EXPECT_TRUE(val.IsTypeCompatible<const int*>());
174 EXPECT_TRUE(val.IsTypeCompatible<int[]>());
175 EXPECT_TRUE(val.IsTypeCompatible<const int[]>());
176 EXPECT_EQ(3, val.Get<int*>()[2]);
177
178 const int const_int_array[] = {10, 20, 30}; // const int*
179 val = const_int_array;
180 EXPECT_FALSE(val.IsTypeCompatible<int*>());
181 EXPECT_TRUE(val.IsTypeCompatible<const int*>());
182 EXPECT_FALSE(val.IsTypeCompatible<int[]>());
183 EXPECT_TRUE(val.IsTypeCompatible<const int[]>());
184 EXPECT_EQ(30, val.Get<const int*>()[2]);
185 }
186
TEST(Any,References)187 TEST(Any, References) {
188 // Passing references to object via Any might be error-prone or the
189 // semantics could be unfamiliar to other developers. In many cases,
190 // using pointers instead of references are more conventional and easier
191 // to understand. Even though the cases of passing references are quite
192 // explicit on both storing and retrieving ends, you might want to
193 // use pointers instead anyway.
194
195 int a = 5;
196 Any val(std::ref(a)); // int&
197 EXPECT_EQ(5, val.Get<std::reference_wrapper<int>>().get());
198 val.Get<std::reference_wrapper<int>>().get() = 7;
199 EXPECT_EQ(7, val.Get<std::reference_wrapper<int>>().get());
200 EXPECT_EQ(7, a);
201
202 Any val2(std::cref(a)); // const int&
203 EXPECT_EQ(7, val2.Get<std::reference_wrapper<const int>>().get());
204
205 a = 10;
206 EXPECT_EQ(10, val.Get<std::reference_wrapper<int>>().get());
207 EXPECT_EQ(10, val2.Get<std::reference_wrapper<const int>>().get());
208 }
209
TEST(Any,CustomTypes)210 TEST(Any, CustomTypes) {
211 struct Person {
212 std::string name;
213 int age;
214 };
215 Any val(Person{"Jack", 40});
216 Any val2 = val;
217 EXPECT_EQ("Jack", val.Get<Person>().name);
218 val.GetPtr<Person>()->name = "Joe";
219 val.GetPtr<Person>()->age /= 2;
220 EXPECT_EQ("Joe", val.Get<Person>().name);
221 EXPECT_EQ(20, val.Get<Person>().age);
222 EXPECT_EQ("Jack", val2.Get<Person>().name);
223 EXPECT_EQ(40, val2.Get<Person>().age);
224 }
225
TEST(Any,Swap)226 TEST(Any, Swap) {
227 Any val(12);
228 Any val2(2.7);
229 EXPECT_EQ(12, val.Get<int>());
230 EXPECT_EQ(2.7, val2.Get<double>());
231
232 val.Swap(val2);
233 EXPECT_EQ(2.7, val.Get<double>());
234 EXPECT_EQ(12, val2.Get<int>());
235
236 std::swap(val, val2);
237 EXPECT_EQ(12, val.Get<int>());
238 EXPECT_EQ(2.7, val2.Get<double>());
239 }
240
TEST(Any,TypeMismatch)241 TEST(Any, TypeMismatch) {
242 Any val(12);
243 EXPECT_DEATH(val.Get<double>(),
244 "Requesting value of type 'double' from variant containing "
245 "'int'");
246
247 val = std::string("123");
248 EXPECT_DEATH(val.GetAsInteger(),
249 "Unable to convert value of type 'std::.*' to integer");
250
251 Any empty;
252 EXPECT_DEATH(empty.GetAsInteger(), "Must not be called on an empty Any");
253 }
254
TEST(Any,TryGet)255 TEST(Any, TryGet) {
256 Any val(12);
257 Any empty;
258 EXPECT_EQ("dummy", val.TryGet<std::string>("dummy"));
259 EXPECT_EQ(12, val.TryGet<int>(17));
260 EXPECT_EQ(17, empty.TryGet<int>(17));
261 }
262
TEST(Any,Compare_Int)263 TEST(Any, Compare_Int) {
264 Any int1{12};
265 Any int2{12};
266 Any int3{20};
267 EXPECT_EQ(int1, int2);
268 EXPECT_NE(int2, int3);
269 }
270
TEST(Any,Compare_String)271 TEST(Any, Compare_String) {
272 Any str1{std::string{"foo"}};
273 Any str2{std::string{"foo"}};
274 Any str3{std::string{"bar"}};
275 EXPECT_EQ(str1, str2);
276 EXPECT_NE(str2, str3);
277 }
278
TEST(Any,Compare_Array)279 TEST(Any, Compare_Array) {
280 Any vec1{std::vector<int>{1, 2}};
281 Any vec2{std::vector<int>{1, 2}};
282 Any vec3{std::vector<int>{1, 2, 3}};
283 EXPECT_EQ(vec1, vec2);
284 EXPECT_NE(vec2, vec3);
285 }
286
TEST(Any,Compare_Empty)287 TEST(Any, Compare_Empty) {
288 Any empty1;
289 Any empty2;
290 Any int1{1};
291 EXPECT_EQ(empty1, empty2);
292 EXPECT_NE(int1, empty1);
293 EXPECT_NE(empty2, int1);
294 }
295
TEST(Any,Compare_NonComparable)296 TEST(Any, Compare_NonComparable) {
297 struct Person {
298 std::string name;
299 int age;
300 };
301 Any person1(Person{"Jack", 40});
302 Any person2 = person1;
303 Any person3(Person{"Jill", 20});
304 EXPECT_NE(person1, person2);
305 EXPECT_NE(person1, person3);
306 EXPECT_NE(person2, person3);
307 }
308
TEST(Any,GetUndecoratedTypeName)309 TEST(Any, GetUndecoratedTypeName) {
310 Any val;
311 EXPECT_TRUE(val.GetUndecoratedTypeName().empty());
312
313 val = 1;
314 EXPECT_EQ(brillo::GetUndecoratedTypeName<int>(),
315 val.GetUndecoratedTypeName());
316
317 val = 3.1415926;
318 EXPECT_EQ(brillo::GetUndecoratedTypeName<double>(),
319 val.GetUndecoratedTypeName());
320
321 val = std::string("blah");
322 EXPECT_EQ(brillo::GetUndecoratedTypeName<std::string>(),
323 val.GetUndecoratedTypeName());
324 }
325