1 | /* |
2 | * Copyright 2011-present Facebook, Inc. |
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 <folly/DiscriminatedPtr.h> |
18 | |
19 | #include <folly/portability/GTest.h> |
20 | |
21 | using namespace folly; |
22 | |
23 | TEST(DiscriminatedPtr, Basic) { |
24 | struct Foo {}; |
25 | struct Bar {}; |
26 | typedef DiscriminatedPtr<void, int, Foo, Bar> Ptr; |
27 | |
28 | int a = 10; |
29 | Ptr p; |
30 | EXPECT_TRUE(p.empty()); |
31 | EXPECT_FALSE(p.hasType<void>()); |
32 | EXPECT_FALSE(p.hasType<int>()); |
33 | EXPECT_FALSE(p.hasType<Foo>()); |
34 | EXPECT_FALSE(p.hasType<Bar>()); |
35 | |
36 | p.set(&a); |
37 | EXPECT_FALSE(p.empty()); |
38 | EXPECT_FALSE(p.hasType<void>()); |
39 | EXPECT_TRUE(p.hasType<int>()); |
40 | EXPECT_FALSE(p.hasType<Foo>()); |
41 | EXPECT_FALSE(p.hasType<Bar>()); |
42 | |
43 | EXPECT_EQ(&a, p.get_nothrow<int>()); |
44 | EXPECT_EQ(&a, static_cast<const Ptr&>(p).get_nothrow<int>()); |
45 | EXPECT_EQ(&a, p.get<int>()); |
46 | EXPECT_EQ(&a, static_cast<const Ptr&>(p).get<int>()); |
47 | EXPECT_EQ(static_cast<void*>(nullptr), p.get_nothrow<void>()); |
48 | EXPECT_THROW({ p.get<void>(); }, std::invalid_argument); |
49 | |
50 | Foo foo; |
51 | p.set(&foo); |
52 | EXPECT_FALSE(p.empty()); |
53 | EXPECT_FALSE(p.hasType<void>()); |
54 | EXPECT_FALSE(p.hasType<int>()); |
55 | EXPECT_TRUE(p.hasType<Foo>()); |
56 | EXPECT_FALSE(p.hasType<Bar>()); |
57 | |
58 | EXPECT_EQ(static_cast<int*>(nullptr), p.get_nothrow<int>()); |
59 | |
60 | p.clear(); |
61 | EXPECT_TRUE(p.empty()); |
62 | EXPECT_FALSE(p.hasType<void>()); |
63 | EXPECT_FALSE(p.hasType<int>()); |
64 | EXPECT_FALSE(p.hasType<Foo>()); |
65 | EXPECT_FALSE(p.hasType<Bar>()); |
66 | } |
67 | |
68 | TEST(DiscriminatedPtr, Apply) { |
69 | struct Foo {}; |
70 | struct Visitor { |
71 | std::string operator()(int* /* ptr */) { |
72 | return "int" ; |
73 | } |
74 | std::string operator()(const int* /* ptr */) { |
75 | return "const int" ; |
76 | } |
77 | std::string operator()(Foo* /* ptr */) { |
78 | return "Foo" ; |
79 | } |
80 | std::string operator()(const Foo* /* ptr */) { |
81 | return "const Foo" ; |
82 | } |
83 | }; |
84 | |
85 | typedef DiscriminatedPtr<int, Foo> Ptr; |
86 | Ptr p; |
87 | |
88 | int a = 0; |
89 | p.set(&a); |
90 | EXPECT_EQ("int" , p.apply(Visitor())); |
91 | EXPECT_EQ("const int" , static_cast<const Ptr&>(p).apply(Visitor())); |
92 | |
93 | Foo foo; |
94 | p.set(&foo); |
95 | EXPECT_EQ("Foo" , p.apply(Visitor())); |
96 | EXPECT_EQ("const Foo" , static_cast<const Ptr&>(p).apply(Visitor())); |
97 | EXPECT_EQ("Foo" , apply_visitor(Visitor(), p)); |
98 | EXPECT_EQ("const Foo" , apply_visitor(Visitor(), static_cast<const Ptr&>(p))); |
99 | EXPECT_EQ("Foo" , apply_visitor(Visitor(), std::move(p))); |
100 | |
101 | p.clear(); |
102 | EXPECT_THROW({ p.apply(Visitor()); }, std::invalid_argument); |
103 | } |
104 | |
105 | TEST(DiscriminatedPtr, ApplyVoid) { |
106 | struct Foo {}; |
107 | struct Visitor { |
108 | void operator()(int* /* ptr */) { |
109 | result = "int" ; |
110 | } |
111 | void operator()(const int* /* ptr */) { |
112 | result = "const int" ; |
113 | } |
114 | void operator()(Foo* /* ptr */) { |
115 | result = "Foo" ; |
116 | } |
117 | void operator()(const Foo* /* ptr */) { |
118 | result = "const Foo" ; |
119 | } |
120 | |
121 | std::string result; |
122 | }; |
123 | |
124 | typedef DiscriminatedPtr<int, Foo> Ptr; |
125 | Ptr p; |
126 | Visitor v; |
127 | |
128 | int a = 0; |
129 | p.set(&a); |
130 | p.apply(v); |
131 | EXPECT_EQ("int" , v.result); |
132 | static_cast<const Ptr&>(p).apply(v); |
133 | EXPECT_EQ("const int" , v.result); |
134 | |
135 | Foo foo; |
136 | p.set(&foo); |
137 | p.apply(v); |
138 | EXPECT_EQ("Foo" , v.result); |
139 | static_cast<const Ptr&>(p).apply(v); |
140 | EXPECT_EQ("const Foo" , v.result); |
141 | |
142 | p.clear(); |
143 | EXPECT_THROW({ p.apply(v); }, std::invalid_argument); |
144 | } |
145 | |