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