2017
[folly.git] / folly / test / DiscriminatedPtrTest.cpp
1 /*
2  * Copyright 2017 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 */) { return "int"; }
72     std::string operator()(const int* /* ptr */) { return "const int"; }
73     std::string operator()(Foo* /* ptr */) { return "Foo"; }
74     std::string operator()(const Foo* /* ptr */) { return "const Foo"; }
75   };
76
77   typedef DiscriminatedPtr<int, Foo> Ptr;
78   Ptr p;
79
80   int a = 0;
81   p.set(&a);
82   EXPECT_EQ("int", p.apply(Visitor()));
83   EXPECT_EQ("const int", static_cast<const Ptr&>(p).apply(Visitor()));
84
85   Foo foo;
86   p.set(&foo);
87   EXPECT_EQ("Foo", p.apply(Visitor()));
88   EXPECT_EQ("const Foo", static_cast<const Ptr&>(p).apply(Visitor()));
89
90   p.clear();
91   EXPECT_THROW({p.apply(Visitor());}, std::invalid_argument);
92 }
93
94 TEST(DiscriminatedPtr, ApplyVoid) {
95   struct Foo { };
96   struct Visitor {
97     void operator()(int* /* ptr */) { result = "int"; }
98     void operator()(const int* /* ptr */) { result = "const int"; }
99     void operator()(Foo* /* ptr */) { result = "Foo"; }
100     void operator()(const Foo* /* ptr */) { result = "const Foo"; }
101
102     std::string result;
103   };
104
105   typedef DiscriminatedPtr<int, Foo> Ptr;
106   Ptr p;
107   Visitor v;
108
109   int a = 0;
110   p.set(&a);
111   p.apply(v);
112   EXPECT_EQ("int", v.result);
113   static_cast<const Ptr&>(p).apply(v);
114   EXPECT_EQ("const int", v.result);
115
116   Foo foo;
117   p.set(&foo);
118   p.apply(v);
119   EXPECT_EQ("Foo", v.result);
120   static_cast<const Ptr&>(p).apply(v);
121   EXPECT_EQ("const Foo", v.result);
122
123   p.clear();
124   EXPECT_THROW({p.apply(v);}, std::invalid_argument);
125 }