1 /*
2 * Copyright (c) Facebook, Inc. and its affiliates.
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 <thrift/conformance/cpp2/AnyRef.h>
18
19 #include <folly/portability/GTest.h>
20
21 namespace apache::thrift::conformance {
22 namespace {
23
TEST(AnyRefTest,DocExample1)24 TEST(AnyRefTest, DocExample1) {
25 std::any a;
26 any_ref ra = a;
27 // ra can now be assigned any value
28 ra.assign_value(1); // a is now an int.
29 ra.assign_value(1.5); // a is now a double.
30
31 int i;
32 any_ref ri = i;
33 ri.assign_value(1); // i is now 1;
34 EXPECT_THROW(
35 ri.assign_value(1.5f),
36 std::bad_any_cast); // Thows a bad_any_cast exception
37 // because i is not a double.
38 }
39
TEST(AnyRefTest,DocExample2)40 TEST(AnyRefTest, DocExample2) {
41 auto foo = [](any_ref in) {
42 if (const auto* i = any_cast<const int>(&in)) {
43 return 1;
44 } else if (const auto* f = any_cast<const float>(&in)) {
45 return 2;
46 }
47 return 3;
48 };
49
50 EXPECT_EQ(foo(1), 1); // Captured as int&&.
51 const float f = 0.5f;
52 EXPECT_EQ(foo(f), 2); // Captured as const float&.
53 EXPECT_EQ(foo(1.5), 3);
54 }
55
TEST(AnyRefTest,DocExample3)56 TEST(AnyRefTest, DocExample3) {
57 auto foo2 = [](any_ref out) { // Previously was void foo(int& out).
58 out.assign_value(1);
59 };
60 int i;
61 std::any a;
62 double d;
63 foo2(i); // i is now 1.
64 EXPECT_EQ(i, 1);
65 foo2(a); // a now stores the integer 1.
66 EXPECT_EQ(std::any_cast<int>(a), 1);
67 EXPECT_THROW(foo2(d), std::bad_any_cast); // throws std::bad_any_cast.
68 }
69
TEST(AnyRefTest,DocExample4)70 TEST(AnyRefTest, DocExample4) {
71 std::any foo;
72 any_ref fooRef = foo;
73 EXPECT_TRUE(fooRef.has_reference()); // Is set to an empty std::any.
74 // The empty std::any advertises the any type.
75 EXPECT_EQ(fooRef.type(), typeid(std::any));
76
77 // The std::any value can be set through the any_ref.
78 fooRef.assign_value(1);
79 // Now it advertises the int type.
80 EXPECT_EQ(fooRef.type(), typeid(int));
81 // Which can be accessed directly through the any_ref.
82 fooRef.assign_value(2);
83 // The original value shows the change.
84 EXPECT_EQ(std::any_cast<int>(foo), 2);
85
86 // The std::any is still accessible.
87 fooRef.assign_value(2.0);
88 EXPECT_EQ(fooRef.type(), typeid(double));
89 }
90
TEST(AnyRefTest,DocExample5)91 TEST(AnyRefTest, DocExample5) {
92 any_ref ref;
93 int i = 0;
94 ref = {i};
95 ref.assign_value(1); // i now equals 1
96 EXPECT_EQ(i, 1);
97 double d = 0;
98 ref = {d};
99 ref.assign_value(1.0); // d now equals 1.0.
100 EXPECT_EQ(d, 1.0);
101 ref = {}; // ref doesn't refer to anything.
102 EXPECT_FALSE(ref.has_reference());
103 }
104
TEST(AnyRefTest,Empty)105 TEST(AnyRefTest, Empty) {
106 any_ref empty;
107 EXPECT_FALSE(empty.has_reference());
108 EXPECT_FALSE(empty.has_value());
109 EXPECT_FALSE(empty);
110 EXPECT_EQ(empty.type(), typeid(void));
111 EXPECT_FALSE(empty.is_const());
112 EXPECT_FALSE(empty.is_rvalue_reference());
113
114 EXPECT_THROW(any_cast<const int&>(empty), std::bad_any_cast);
115 EXPECT_THROW(any_cast_exact<const int&>(empty), std::bad_any_cast);
116 EXPECT_THROW(any_cast<void*>(empty), std::bad_any_cast);
117
118 // Uncomment to get epxected compiler error.
119 // EXPECT_EQ(ref, std::nullopt);
120 }
121
TEST(AnyRefTest,Const)122 TEST(AnyRefTest, Const) {
123 constexpr int i = 1;
124 any_ref ref = i;
125 EXPECT_TRUE(ref.has_reference());
126 EXPECT_TRUE(ref.has_value());
127 EXPECT_TRUE(ref);
128 EXPECT_EQ(ref.type(), typeid(int));
129 EXPECT_TRUE(ref.is_const());
130 EXPECT_FALSE(ref.is_rvalue_reference());
131
132 EXPECT_EQ(any_cast<const int>(ref), i);
133 EXPECT_EQ(any_cast<int>(ref), i);
134 EXPECT_THROW(any_cast<double>(ref), std::bad_any_cast);
135
136 EXPECT_EQ(&any_cast<const int&>(ref), &i);
137 EXPECT_EQ(&any_cast_exact<const int&>(ref), &i);
138
139 EXPECT_THROW(any_cast<const int&&>(ref), std::bad_any_cast);
140 EXPECT_THROW(any_cast_exact<const int&&>(ref), std::bad_any_cast);
141
142 EXPECT_THROW(any_cast<int&>(ref), std::bad_any_cast);
143 EXPECT_THROW(any_cast_exact<int&>(ref), std::bad_any_cast);
144
145 EXPECT_THROW(any_cast<const double&>(ref), std::bad_any_cast);
146 EXPECT_THROW(any_cast_exact<const double&>(ref), std::bad_any_cast);
147
148 ref = {std::move(i)};
149 EXPECT_TRUE(ref.has_reference());
150 EXPECT_TRUE(ref.has_value());
151 EXPECT_TRUE(ref);
152 EXPECT_EQ(ref.type(), typeid(int));
153 EXPECT_TRUE(ref.is_const());
154 EXPECT_TRUE(ref.is_rvalue_reference());
155
156 EXPECT_EQ(any_cast<const int>(ref), i);
157 EXPECT_EQ(any_cast<int>(ref), i);
158 EXPECT_THROW(any_cast<double>(ref), std::bad_any_cast);
159
160 EXPECT_EQ(&any_cast<const int&>(ref), &i);
161 EXPECT_THROW(&any_cast_exact<const int&>(ref), std::bad_any_cast);
162
163 EXPECT_EQ(any_cast<const int&&>(ref), i);
164 EXPECT_EQ(any_cast_exact<const int&&>(ref), i);
165
166 EXPECT_THROW(any_cast<int&>(ref), std::bad_any_cast);
167 EXPECT_THROW(any_cast_exact<int&>(ref), std::bad_any_cast);
168
169 EXPECT_THROW(any_cast<const double&>(ref), std::bad_any_cast);
170 EXPECT_THROW(any_cast_exact<const double&>(ref), std::bad_any_cast);
171 }
172
TEST(AnyRefTest,NonConst)173 TEST(AnyRefTest, NonConst) {
174 any_ref ref;
175 int i = 2;
176 ref = {i};
177 EXPECT_TRUE(ref.has_reference());
178 EXPECT_TRUE(ref.has_value());
179 EXPECT_TRUE(ref);
180 EXPECT_FALSE(ref.is_const());
181 EXPECT_FALSE(ref.is_rvalue_reference());
182
183 EXPECT_EQ(&any_cast<const int&>(ref), &i);
184 EXPECT_THROW(any_cast_exact<const int&>(ref), std::bad_any_cast);
185
186 EXPECT_EQ(&any_cast<int&>(ref), &i);
187 EXPECT_EQ(&any_cast_exact<int&>(ref), &i);
188
189 any_cast<int&>(ref) = 3;
190 EXPECT_EQ(i, 3);
191 any_cast_exact<int&>(ref) = 4;
192 EXPECT_EQ(i, 4);
193
194 ref = {std::move(i)};
195 EXPECT_TRUE(ref.has_reference());
196 EXPECT_TRUE(ref.has_value());
197 EXPECT_TRUE(ref);
198 EXPECT_FALSE(ref.is_const());
199 EXPECT_TRUE(ref.is_rvalue_reference());
200
201 EXPECT_EQ(any_cast<const int>(ref), i);
202 EXPECT_EQ(any_cast<int>(ref), i);
203 EXPECT_THROW(any_cast<double>(ref), std::bad_any_cast);
204
205 EXPECT_EQ(&any_cast<int&>(ref), &i);
206 EXPECT_THROW(any_cast_exact<int&>(ref), std::bad_any_cast);
207
208 EXPECT_EQ(any_cast<int&&>(ref), i);
209 EXPECT_EQ(any_cast_exact<int&&>(ref), i);
210
211 EXPECT_EQ(&any_cast<const int&>(ref), &i);
212 EXPECT_THROW(any_cast_exact<const int&>(ref), std::bad_any_cast);
213
214 EXPECT_EQ(any_cast<const int&&>(ref), i);
215 EXPECT_THROW(any_cast_exact<const int&&>(ref), std::bad_any_cast);
216
217 EXPECT_THROW(any_cast<double&&>(ref), std::bad_any_cast);
218 EXPECT_THROW(any_cast_exact<double&&>(ref), std::bad_any_cast);
219
220 EXPECT_THROW(any_cast<double&>(ref), std::bad_any_cast);
221 EXPECT_THROW(any_cast_exact<double&>(ref), std::bad_any_cast);
222
223 const float f = 1.5f;
224 ref = {f};
225 EXPECT_TRUE(ref.is_const());
226 EXPECT_THROW(any_cast<double>(ref), std::bad_any_cast);
227 EXPECT_EQ(any_cast<float>(ref), 1.5f);
228 EXPECT_EQ(any_cast_exact<const float&>(ref), 1.5f);
229 }
230
TEST(AnyRefTest,NullOpt)231 TEST(AnyRefTest, NullOpt) {
232 // Should not beable to create an any reference to nullopt.
233 // Uncomment to produce expected compiler error.
234 // any_ref empty(std::nullopt);
235 }
236
TEST(AnyRefTest,Volatile)237 TEST(AnyRefTest, Volatile) {
238 // Uncomment to get expected compile-time error.
239 // volatile int i;
240 // any_ref ref = i;
241 }
242
TEST(AnyRefTest,MoveOnly)243 TEST(AnyRefTest, MoveOnly) {
244 auto i = std::make_unique<int>(2);
245 any_ref ref = i;
246 EXPECT_TRUE(ref.has_reference());
247 EXPECT_TRUE(ref.has_value());
248 EXPECT_TRUE(ref);
249 EXPECT_FALSE(ref.is_const());
250 EXPECT_FALSE(ref.is_rvalue_reference());
251
252 EXPECT_EQ(&any_cast<std::unique_ptr<int>&>(ref), &i);
253 EXPECT_EQ(&any_cast_exact<std::unique_ptr<int>&>(ref), &i);
254
255 EXPECT_THROW(any_cast<std::unique_ptr<int>&&>(ref), std::bad_any_cast);
256 EXPECT_THROW(any_cast_exact<std::unique_ptr<int>&&>(ref), std::bad_any_cast);
257
258 // Uncomment to get expected compile-time error.
259 // any_cast<std::unique_ptr<int>>(ref);
260
261 ref = {std::move(i)};
262 EXPECT_NE(i, nullptr);
263 EXPECT_FALSE(ref.is_const());
264 EXPECT_TRUE(ref.is_rvalue_reference());
265
266 EXPECT_EQ(&any_cast<std::unique_ptr<int>&>(ref), &i);
267 EXPECT_THROW(any_cast_exact<std::unique_ptr<int>&>(ref), std::bad_any_cast);
268
269 EXPECT_EQ(any_cast<std::unique_ptr<int>&&>(ref).get(), i.get());
270 EXPECT_EQ(any_cast_exact<std::unique_ptr<int>&&>(ref).get(), i.get());
271 }
272
TEST(AnyRefTest,ImplicitCapture)273 TEST(AnyRefTest, ImplicitCapture) {
274 auto func = [](any_ref ref) -> int& { return any_cast<int&>(ref); };
275
276 EXPECT_THROW(func({}), std::bad_any_cast);
277 EXPECT_THROW(func({1.0}), std::bad_any_cast);
278 EXPECT_EQ(func(1), 1);
279 int i = 1;
280 EXPECT_EQ(&func(i), &i);
281 func(i) = 2;
282 EXPECT_EQ(i, 2);
283 func(std::move(i)) = 3;
284 EXPECT_EQ(i, 3);
285 any_ref ref = i;
286 EXPECT_EQ(&func(ref), &i);
287 }
288
TEST(AnyRefTest,Pointer)289 TEST(AnyRefTest, Pointer) {
290 int i = 2;
291 int* pi = &i;
292 any_ref ref = pi;
293
294 EXPECT_TRUE(ref.has_reference());
295 EXPECT_TRUE(ref.has_value());
296 EXPECT_TRUE(ref);
297 EXPECT_EQ(ref.type(), typeid(int*));
298 EXPECT_NE(ref.type(), typeid(int));
299 EXPECT_THROW(any_cast<const int&>(ref), std::bad_any_cast);
300 EXPECT_THROW(any_cast_exact<const int&>(ref), std::bad_any_cast);
301 EXPECT_THROW(any_cast<int>(ref), std::bad_any_cast);
302 EXPECT_EQ(any_cast<int*>(ref), &i);
303 EXPECT_EQ(&any_cast<int*&>(ref), &pi);
304 EXPECT_EQ(&any_cast_exact<int*&>(ref), &pi);
305
306 // Uncomment to get epxected compiler error.
307 // EXPECT_NE(ref, nullptr);
308 }
309
TEST(AnyRefTest,AnyTransparency_Empty)310 TEST(AnyRefTest, AnyTransparency_Empty) {
311 std::any a;
312 any_ref ref = a;
313 EXPECT_TRUE(ref.has_reference());
314 EXPECT_FALSE(ref.has_value());
315 EXPECT_FALSE(ref);
316 EXPECT_EQ(ref.type(), typeid(std::any));
317 EXPECT_FALSE(ref.is_const());
318 EXPECT_FALSE(ref.is_rvalue_reference());
319
320 EXPECT_EQ(&any_cast<std::any&>(ref), &a);
321 EXPECT_THROW(any_cast<int>(ref), std::bad_any_cast);
322 EXPECT_THROW(any_cast<double>(ref), std::bad_any_cast);
323
324 EXPECT_THROW(any_cast<int&>(ref), std::bad_any_cast);
325 EXPECT_THROW(any_cast_exact<int&>(ref), std::bad_any_cast);
326
327 EXPECT_FALSE(any_cast<std::any>(ref).has_value());
328
329 EXPECT_FALSE(any_cast<std::any&>(ref).has_value());
330 EXPECT_FALSE(any_cast_exact<std::any&>(ref).has_value());
331
332 EXPECT_FALSE(any_cast<const std::any&>(ref).has_value());
333 EXPECT_THROW(any_cast_exact<const std::any&>(ref), std::bad_any_cast);
334
335 // Can be assigned via the any_ref
336 any_cast<std::any&>(ref) = 1;
337 EXPECT_EQ(ref.type(), typeid(int));
338 EXPECT_FALSE(ref.is_const());
339 EXPECT_FALSE(ref.is_rvalue_reference());
340 EXPECT_EQ(std::any_cast<int&>(a), 1);
341 }
342
TEST(AnyRefTest,AnyTransparency_NonConst)343 TEST(AnyRefTest, AnyTransparency_NonConst) {
344 int i = 2;
345 std::any a = i;
346 any_ref ref = a;
347 EXPECT_TRUE(ref.has_reference());
348 EXPECT_TRUE(ref.has_value());
349 EXPECT_TRUE(ref);
350 EXPECT_EQ(ref.type(), typeid(int));
351 EXPECT_FALSE(ref.is_const());
352 EXPECT_FALSE(ref.is_rvalue_reference());
353
354 EXPECT_EQ(any_cast<int>(ref), 2);
355
356 EXPECT_EQ(&any_cast<std::any&>(ref), &a);
357 EXPECT_EQ(&any_cast_exact<std::any&>(ref), &a);
358
359 EXPECT_EQ(&any_cast<const std::any&>(ref), &a);
360 EXPECT_THROW(any_cast_exact<const std::any&>(ref), std::bad_any_cast);
361
362 EXPECT_THROW(any_cast<std::any&&>(ref), std::bad_any_cast);
363 EXPECT_THROW(any_cast_exact<std::any&&>(ref), std::bad_any_cast);
364
365 EXPECT_EQ(&any_cast<int&>(ref), &std::any_cast<int&>(a));
366 EXPECT_EQ(&any_cast_exact<int&>(ref), &std::any_cast<int&>(a));
367
368 EXPECT_EQ(&any_cast<const int&>(ref), &std::any_cast<const int&>(a));
369 EXPECT_THROW(any_cast_exact<const int&>(ref), std::bad_any_cast);
370
371 EXPECT_THROW(any_cast<int&&>(ref), std::bad_any_cast);
372 EXPECT_THROW(any_cast_exact<int&&>(ref), std::bad_any_cast);
373
374 EXPECT_NE(&any_cast<int&>(ref), &i);
375 EXPECT_NE(&any_cast_exact<int&>(ref), &i);
376
377 EXPECT_THROW(any_cast<double>(ref), std::bad_any_cast);
378 EXPECT_THROW(any_cast_exact<double&>(ref), std::bad_any_cast);
379
380 any_cast<int&>(ref) = 3;
381 EXPECT_EQ(i, 2);
382 EXPECT_EQ(any_cast<int&>(a), 3);
383 }
384
TEST(AnyRefTest,AnyTransparency_Const)385 TEST(AnyRefTest, AnyTransparency_Const) {
386 int i = 2;
387 std::any a = i;
388 const std::any& ca = a;
389 any_ref ref = ca;
390 EXPECT_TRUE(ref.has_reference());
391 EXPECT_TRUE(ref.has_value());
392 EXPECT_TRUE(ref);
393 EXPECT_EQ(ref.type(), typeid(int));
394 EXPECT_TRUE(ref.is_const());
395 EXPECT_FALSE(ref.is_rvalue_reference());
396
397 EXPECT_EQ(any_cast<int>(ref), 2);
398
399 EXPECT_THROW(any_cast<std::any&>(ref), std::bad_any_cast);
400 EXPECT_THROW(any_cast_exact<std::any&>(ref), std::bad_any_cast);
401
402 EXPECT_EQ(&any_cast<const std::any&>(ref), &a);
403 EXPECT_EQ(&any_cast_exact<const std::any&>(ref), &a);
404
405 EXPECT_THROW(any_cast<std::any&&>(ref), std::bad_any_cast);
406 EXPECT_THROW(any_cast_exact<std::any&&>(ref), std::bad_any_cast);
407
408 EXPECT_THROW(any_cast<int&>(ref), std::bad_any_cast);
409 EXPECT_THROW(any_cast_exact<int&>(ref), std::bad_any_cast);
410
411 EXPECT_EQ(&any_cast<const int&>(ref), &std::any_cast<const int&>(a));
412 EXPECT_EQ(&any_cast_exact<const int&>(ref), &std::any_cast<const int&>(a));
413
414 EXPECT_THROW(any_cast<const int&&>(ref), std::bad_any_cast);
415 EXPECT_THROW(any_cast_exact<const int&&>(ref), std::bad_any_cast);
416
417 EXPECT_NE(&any_cast<const int&>(ref), &i);
418 EXPECT_NE(&any_cast_exact<const int&>(ref), &i);
419
420 EXPECT_THROW(any_cast<double>(ref), std::bad_any_cast);
421 EXPECT_THROW(any_cast_exact<const double&>(ref), std::bad_any_cast);
422 }
423
424 } // namespace
425 } // namespace apache::thrift::conformance
426
427 namespace {
428
TEST(AnyRefTest,ADL)429 TEST(AnyRefTest, ADL) {
430 // Requires c++20 to work.
431 #if __cplusplus >= 202002L
432 std::any a = 1;
433 apache::thrift::conformance::any_ref ra = a;
434 EXPECT_EQ(any_cast<int>(a), 1);
435 EXPECT_EQ(any_cast<int>(ra), 1);
436 #endif
437 }
438
TEST(AnyRefTest,ADL_using)439 TEST(AnyRefTest, ADL_using) {
440 std::any a = 1;
441 apache::thrift::conformance::any_ref ra = a;
442 using apache::thrift::conformance::any_cast;
443 using std::any_cast;
444 EXPECT_EQ(any_cast<int>(a), 1);
445 EXPECT_EQ(any_cast<int>(ra), 1);
446 }
447
TEST(AnyRefTest,ADL_using_std)448 TEST(AnyRefTest, ADL_using_std) {
449 std::any a = 1;
450 apache::thrift::conformance::any_ref ra = a;
451 using std::any_cast;
452 EXPECT_EQ(any_cast<int>(a), 1);
453 EXPECT_EQ(any_cast<int>(ra), 1);
454 }
455
TEST(AnyRefTest,ADL_using_thrift)456 TEST(AnyRefTest, ADL_using_thrift) {
457 std::any a = 1;
458 apache::thrift::conformance::any_ref ra = a;
459 using apache::thrift::conformance::any_cast;
460 EXPECT_EQ(any_cast<int>(a), 1);
461 EXPECT_EQ(any_cast<int>(ra), 1);
462 }
463
464 } // namespace
465