Optional
[folly.git] / folly / test / OptionalTest.cpp
1 /*
2  * Copyright 2012 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/Optional.h"
18
19 #include <memory>
20 #include <vector>
21 #include <algorithm>
22 #include <iomanip>
23 #include <string>
24
25 #include <glog/logging.h>
26 #include <gtest/gtest.h>
27 #include <boost/optional.hpp>
28
29 using namespace folly;
30 using std::unique_ptr;
31 using std::shared_ptr;
32
33 struct NoDefault {
34   NoDefault(int, int) {}
35   char a, b, c;
36 };
37
38 static_assert(sizeof(Optional<char>) == 2, "");
39 static_assert(sizeof(Optional<int>) == 8, "");
40 static_assert(sizeof(Optional<NoDefault>) == 4, "");
41 static_assert(sizeof(Optional<char>) == sizeof(boost::optional<char>), "");
42 static_assert(sizeof(Optional<short>) == sizeof(boost::optional<short>), "");
43 static_assert(sizeof(Optional<int>) == sizeof(boost::optional<int>), "");
44 static_assert(sizeof(Optional<double>) == sizeof(boost::optional<double>), "");
45
46 TEST(Optional, NoDefault) {
47   Optional<NoDefault> x;
48   EXPECT_FALSE(x);
49   x.emplace(4, 5);
50   EXPECT_TRUE(x);
51   x.clear();
52   EXPECT_FALSE(x);
53 }
54
55 TEST(Optional, String) {
56   Optional<std::string> maybeString;
57   EXPECT_FALSE(maybeString);
58   maybeString = "hello";
59   EXPECT_TRUE(maybeString);
60 }
61
62 TEST(Optional, Const) {
63   { // default construct
64     Optional<const int> opt;
65     EXPECT_FALSE(opt);
66     opt.emplace(4);
67     EXPECT_EQ(opt, 4);
68     opt.emplace(5);
69     EXPECT_EQ(opt, 5);
70     opt.clear();
71     EXPECT_FALSE(opt);
72   }
73   { // copy-constructed
74     const int x = 6;
75     Optional<const int> opt(x);
76     EXPECT_EQ(opt, 6);
77   }
78   { // move-constructed
79     const int x = 7;
80     Optional<const int> opt(std::move(x));
81     EXPECT_EQ(opt, 7);
82   }
83   // no assignment allowed
84 }
85
86 TEST(Optional, Simple) {
87   Optional<int> opt;
88   EXPECT_FALSE(opt);
89   opt = 4;
90   EXPECT_TRUE(opt);
91   EXPECT_EQ(4, *opt);
92   opt = 5;
93   EXPECT_EQ(5, *opt);
94   opt.clear();
95   EXPECT_FALSE(opt);
96 }
97
98 TEST(Optional, Unique) {
99   Optional<unique_ptr<int>> opt;
100
101   opt.clear();
102   EXPECT_FALSE(opt);
103   // empty->emplaced
104   opt.emplace(new int(5));
105   EXPECT_TRUE(opt);
106   EXPECT_EQ(5, **opt);
107
108   opt.clear();
109   // empty->moved
110   opt = unique_ptr<int>(new int(6));
111   EXPECT_EQ(6, **opt);
112   // full->moved
113   opt = unique_ptr<int>(new int(7));
114   EXPECT_EQ(7, **opt);
115
116   // move it out by move construct
117   Optional<unique_ptr<int>> moved(std::move(opt));
118   EXPECT_TRUE(moved);
119   EXPECT_FALSE(opt);
120   EXPECT_EQ(7, **moved);
121
122   EXPECT_TRUE(moved);
123   opt = std::move(moved); // move it back by move assign
124   EXPECT_FALSE(moved);
125   EXPECT_TRUE(opt);
126   EXPECT_EQ(7, **opt);
127 }
128
129 TEST(Optional, Shared) {
130   shared_ptr<int> ptr;
131   Optional<shared_ptr<int>> opt;
132   EXPECT_FALSE(opt);
133   // empty->emplaced
134   opt.emplace(new int(5));
135   EXPECT_TRUE(opt);
136   ptr = opt.value();
137   EXPECT_EQ(ptr.get(), opt->get());
138   EXPECT_EQ(2, ptr.use_count());
139   opt.clear();
140   EXPECT_EQ(1, ptr.use_count());
141   // full->copied
142   opt = ptr;
143   EXPECT_EQ(2, ptr.use_count());
144   EXPECT_EQ(ptr.get(), opt->get());
145   opt.clear();
146   EXPECT_EQ(1, ptr.use_count());
147   // full->moved
148   opt = std::move(ptr);
149   EXPECT_EQ(1, opt->use_count());
150   EXPECT_EQ(nullptr, ptr.get());
151   {
152     Optional<shared_ptr<int>> copied(opt);
153     EXPECT_EQ(2, opt->use_count());
154     Optional<shared_ptr<int>> moved(std::move(opt));
155     EXPECT_EQ(2, moved->use_count());
156     moved.emplace(new int(6));
157     EXPECT_EQ(1, moved->use_count());
158     copied = moved;
159     EXPECT_EQ(2, moved->use_count());
160   }
161 }
162
163 TEST(Optional, Order) {
164   std::vector<Optional<int>> vect{
165     { none },
166     { 3 },
167     { 1 },
168     { none },
169     { 2 },
170   };
171   std::vector<Optional<int>> expected {
172     { none },
173     { none },
174     { 1 },
175     { 2 },
176     { 3 },
177   };
178   std::sort(vect.begin(), vect.end());
179   EXPECT_TRUE(vect == expected);
180 }
181
182 TEST(Optional, Swap) {
183   Optional<std::string> a;
184   Optional<std::string> b;
185
186   swap(a, b);
187   EXPECT_FALSE(a.hasValue());
188   EXPECT_FALSE(b.hasValue());
189
190   a = "hello";
191   EXPECT_TRUE(a.hasValue());
192   EXPECT_FALSE(b.hasValue());
193   EXPECT_EQ("hello", a.value());
194
195   swap(a, b);
196   EXPECT_FALSE(a.hasValue());
197   EXPECT_TRUE(b.hasValue());
198   EXPECT_EQ("hello", b.value());
199
200   a = "bye";
201   EXPECT_TRUE(a.hasValue());
202   EXPECT_EQ("bye", a.value());
203
204   swap(a, b);
205 }
206
207 TEST(Optional, Comparisons) {
208   Optional<int> o_;
209   Optional<int> o1(1);
210   Optional<int> o2(2);
211
212   EXPECT_TRUE(o_ < 1);
213   EXPECT_TRUE(o_ <= 1);
214   EXPECT_TRUE(o_ <= o_);
215   EXPECT_TRUE(o_ == o_);
216   EXPECT_TRUE(o_ != 1);
217   EXPECT_TRUE(o_ >= o_);
218   EXPECT_TRUE(1 >= o_);
219   EXPECT_TRUE(1 > o_);
220
221   EXPECT_TRUE(o1 < o2);
222   EXPECT_TRUE(o1 <= o2);
223   EXPECT_TRUE(o1 <= o1);
224   EXPECT_TRUE(o1 == o1);
225   EXPECT_TRUE(o1 != o2);
226   EXPECT_TRUE(o1 >= o1);
227   EXPECT_TRUE(o2 >= o1);
228   EXPECT_TRUE(o2 > o1);
229
230   EXPECT_FALSE(o2 < o1);
231   EXPECT_FALSE(o2 <= o1);
232   EXPECT_FALSE(o2 <= o1);
233   EXPECT_FALSE(o2 == o1);
234   EXPECT_FALSE(o1 != o1);
235   EXPECT_FALSE(o1 >= o2);
236   EXPECT_FALSE(o1 >= o2);
237   EXPECT_FALSE(o1 > o2);
238
239   EXPECT_TRUE(1 < o2);
240   EXPECT_TRUE(1 <= o2);
241   EXPECT_TRUE(1 <= o1);
242   EXPECT_TRUE(1 == o1);
243   EXPECT_TRUE(2 != o1);
244   EXPECT_TRUE(1 >= o1);
245   EXPECT_TRUE(2 >= o1);
246   EXPECT_TRUE(2 > o1);
247
248   EXPECT_FALSE(o2 < 1);
249   EXPECT_FALSE(o2 <= 1);
250   EXPECT_FALSE(o2 <= 1);
251   EXPECT_FALSE(o2 == 1);
252   EXPECT_FALSE(o2 != 2);
253   EXPECT_FALSE(o1 >= 2);
254   EXPECT_FALSE(o1 >= 2);
255   EXPECT_FALSE(o1 > 2);
256 }
257
258 TEST(Optional, Pointee) {
259   Optional<int> x;
260   EXPECT_FALSE(get_pointer(x));
261   x = 1;
262   EXPECT_TRUE(get_pointer(x));
263   *get_pointer(x) = 2;
264   EXPECT_TRUE(x == 2);
265   x = none;
266   EXPECT_FALSE(get_pointer(x));
267 }