blob: eaf3ce133bf5098f554827aea74625e4c6f4220e [file] [log] [blame]
Alex Vakulenkob6513a12014-05-05 17:23:40 -07001// 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 <gtest/gtest.h>
11
12#include "buffet/any.h"
13
14using buffet::Any;
15
16TEST(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
25TEST(Any, SimpleTypes) {
26 Any val(20);
27 EXPECT_FALSE(val.IsEmpty());
28 EXPECT_TRUE(val.IsTypeCompatible<int>());
29 EXPECT_EQ(20, val.Get<int>());
30
31 Any val2(3.1415926);
32 EXPECT_FALSE(val2.IsEmpty());
33 EXPECT_TRUE(val2.IsTypeCompatible<double>());
34 EXPECT_FALSE(val2.IsTypeCompatible<int>());
35 EXPECT_DOUBLE_EQ(3.1415926, val2.Get<double>());
36
37 Any val3(std::string("blah"));
38 EXPECT_TRUE(val3.IsTypeCompatible<std::string>());
39 EXPECT_EQ("blah", val3.Get<std::string>());
40}
41
42TEST(Any, Clear) {
43 Any val('x');
44 EXPECT_FALSE(val.IsEmpty());
45 EXPECT_EQ('x', val.Get<char>());
46
47 val.Clear();
48 EXPECT_TRUE(val.IsEmpty());
49}
50
51TEST(Any, Assignments) {
52 Any val(20);
53 EXPECT_EQ(20, val.Get<int>());
54
55 val = 3.1415926;
56 EXPECT_FALSE(val.IsEmpty());
57 EXPECT_TRUE(val.IsTypeCompatible<double>());
58 EXPECT_DOUBLE_EQ(3.1415926, val.Get<double>());
59
60 val = std::string("blah");
61 EXPECT_EQ("blah", val.Get<std::string>());
62
63 Any val2;
64 EXPECT_TRUE(val2.IsEmpty());
65 val2 = val;
66 EXPECT_FALSE(val.IsEmpty());
67 EXPECT_FALSE(val2.IsEmpty());
68 EXPECT_EQ("blah", val.Get<std::string>());
69 EXPECT_EQ("blah", val2.Get<std::string>());
70 val.Clear();
71 EXPECT_TRUE(val.IsEmpty());
72 EXPECT_EQ("blah", val2.Get<std::string>());
73 val2.Clear();
74 EXPECT_TRUE(val2.IsEmpty());
75
Alex Vakulenkoa0424dd2014-06-13 16:10:17 -070076 val = std::vector<int>{100, 20, 3};
Alex Vakulenkob6513a12014-05-05 17:23:40 -070077 auto v = val.Get<std::vector<int>>();
78 EXPECT_EQ(100, v[0]);
79 EXPECT_EQ(20, v[1]);
80 EXPECT_EQ(3, v[2]);
81}
82
83TEST(Any, Enums) {
84 enum class Dummy { foo, bar, baz };
85 Any val(Dummy::bar);
86 EXPECT_FALSE(val.IsEmpty());
87 EXPECT_TRUE(val.IsConvertibleToInteger());
88 EXPECT_EQ(Dummy::bar, val.Get<Dummy>());
89 EXPECT_EQ(1, val.GetAsInteger());
90
91 val = Dummy::baz;
92 EXPECT_EQ(2, val.GetAsInteger());
93
94 val = Dummy::foo;
95 EXPECT_EQ(0, val.GetAsInteger());
96}
97
98TEST(Any, Integers) {
99 Any val(14);
100 EXPECT_TRUE(val.IsConvertibleToInteger());
101 EXPECT_EQ(14, val.Get<int>());
102 EXPECT_EQ(14, val.GetAsInteger());
103
104 val = '\x40';
105 EXPECT_TRUE(val.IsConvertibleToInteger());
106 EXPECT_EQ(64, val.Get<char>());
107 EXPECT_EQ(64, val.GetAsInteger());
108
109 val = static_cast<uint16_t>(65535);
110 EXPECT_TRUE(val.IsConvertibleToInteger());
111 EXPECT_EQ(65535, val.Get<uint16_t>());
112 EXPECT_EQ(65535, val.GetAsInteger());
113
114 val = static_cast<uint64_t>(0xFFFFFFFFFFFFFFFFULL);
115 EXPECT_TRUE(val.IsConvertibleToInteger());
116 EXPECT_EQ(0xFFFFFFFFFFFFFFFFULL, val.Get<uint64_t>());
117 EXPECT_EQ(-1, val.GetAsInteger());
118
119 val = "abc";
120 EXPECT_FALSE(val.IsConvertibleToInteger());
121
122 int a = 5;
123 val = &a;
124 EXPECT_FALSE(val.IsConvertibleToInteger());
125}
126
127TEST(Any, Pointers) {
128 Any val("abc"); // const char*
129 EXPECT_FALSE(val.IsTypeCompatible<char*>());
130 EXPECT_TRUE(val.IsTypeCompatible<const char*>());
131 EXPECT_FALSE(val.IsTypeCompatible<volatile char*>());
132 EXPECT_TRUE(val.IsTypeCompatible<volatile const char*>());
133 EXPECT_STREQ("abc", val.Get<const char*>());
134
135 int a = 10;
136 val = &a;
137 EXPECT_TRUE(val.IsTypeCompatible<int*>());
138 EXPECT_TRUE(val.IsTypeCompatible<const int*>());
139 EXPECT_TRUE(val.IsTypeCompatible<volatile int*>());
140 EXPECT_TRUE(val.IsTypeCompatible<volatile const int*>());
141 EXPECT_EQ(10, *val.Get<const int*>());
142 *val.Get<int*>() = 3;
143 EXPECT_EQ(3, a);
144}
145
146TEST(Any, Arrays) {
147 // The following test are here to validate the array-to-pointer decay rules.
148 // Since Any does not store the contents of a C-style array, just a pointer
149 // to the data, putting array data into Any could be dangerous.
150 // Make sure the array's lifetime exceeds that of an Any containing the
151 // pointer to the array data.
152 // If you want to store the array with data, use corresponding value types
153 // such as std::vector or a struct containing C-style array as a member.
154
155 int int_array[] = {1, 2, 3}; // int*
156 Any val = int_array;
157 EXPECT_TRUE(val.IsTypeCompatible<int*>());
158 EXPECT_TRUE(val.IsTypeCompatible<const int*>());
159 EXPECT_TRUE(val.IsTypeCompatible<int[]>());
160 EXPECT_TRUE(val.IsTypeCompatible<const int[]>());
161 EXPECT_EQ(3, val.Get<int*>()[2]);
162
163 const int const_int_array[] = {10, 20, 30}; // const int*
164 val = const_int_array;
165 EXPECT_FALSE(val.IsTypeCompatible<int*>());
166 EXPECT_TRUE(val.IsTypeCompatible<const int*>());
167 EXPECT_FALSE(val.IsTypeCompatible<int[]>());
168 EXPECT_TRUE(val.IsTypeCompatible<const int[]>());
169 EXPECT_EQ(30, val.Get<const int*>()[2]);
170}
171
172TEST(Any, References) {
173 // Passing references to object via Any might be error-prone or the
174 // semantics could be unfamiliar to other developers. In many cases,
175 // using pointers instead of references are more conventional and easier
176 // to understand. Even though the cases of passing references are quite
177 // explicit on both storing and retrieving ends, you might want to
178 // use pointers instead anyway.
179
180 int a = 5;
181 Any val(std::ref(a)); // int&
182 EXPECT_EQ(5, val.Get<std::reference_wrapper<int>>().get());
183 val.Get<std::reference_wrapper<int>>().get() = 7;
184 EXPECT_EQ(7, val.Get<std::reference_wrapper<int>>().get());
185 EXPECT_EQ(7, a);
186
187 Any val2(std::cref(a)); // const int&
188 EXPECT_EQ(7, val2.Get<std::reference_wrapper<const int>>().get());
189
190 a = 10;
191 EXPECT_EQ(10, val.Get<std::reference_wrapper<int>>().get());
192 EXPECT_EQ(10, val2.Get<std::reference_wrapper<const int>>().get());
193}
194
195TEST(Any, CustomTypes) {
196 struct Person {
197 std::string name;
198 int age;
199 };
Alex Vakulenkoa0424dd2014-06-13 16:10:17 -0700200 Any val(Person{"Jack", 40});
Alex Vakulenkob6513a12014-05-05 17:23:40 -0700201 Any val2 = val;
202 EXPECT_EQ("Jack", val.Get<Person>().name);
203 val.GetPtr<Person>()->name = "Joe";
204 val.GetPtr<Person>()->age /= 2;
205 EXPECT_EQ("Joe", val.Get<Person>().name);
206 EXPECT_EQ(20, val.Get<Person>().age);
207 EXPECT_EQ("Jack", val2.Get<Person>().name);
208 EXPECT_EQ(40, val2.Get<Person>().age);
209}
210
211TEST(Any, Swap) {
212 Any val(12);
213 Any val2(2.7);
214 EXPECT_EQ(12, val.Get<int>());
215 EXPECT_EQ(2.7, val2.Get<double>());
216
217 val.Swap(val2);
218 EXPECT_EQ(2.7, val.Get<double>());
219 EXPECT_EQ(12, val2.Get<int>());
220
221 std::swap(val, val2);
222 EXPECT_EQ(12, val.Get<int>());
223 EXPECT_EQ(2.7, val2.Get<double>());
224}
225
226TEST(Any, TypeMismatch) {
227 Any val(12);
228 EXPECT_DEATH(val.Get<double>(),
229 "Requesting value of type \\w+ from variant containing \\w+");
230
231 val = std::string("123");
232 EXPECT_DEATH(val.GetAsInteger(),
233 "Unable to convert value of type \\w+ to integer");
234
235 Any empty;
236 EXPECT_DEATH(empty.GetAsInteger(), "Must not be called on an empty Any");
237}
238
239TEST(Any, TryGet) {
240 Any val(12);
241 Any empty;
242 EXPECT_EQ("dummy", val.TryGet<std::string>("dummy"));
243 EXPECT_EQ(12, val.TryGet<int>(17));
244 EXPECT_EQ(17, empty.TryGet<int>(17));
245}