Codemod: use #include angle brackets in folly and thrift
[folly.git] / folly / test / OptionalTest.cpp
1 /*
2  * Copyright 2014 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 std::unique_ptr;
30 using std::shared_ptr;
31
32 namespace folly {
33
34 template<class V>
35 std::ostream& operator<<(std::ostream& os, const Optional<V>& v) {
36   if (v) {
37     os << "Optional(" << v.value() << ')';
38   } else {
39     os << "None";
40   }
41   return os;
42 }
43
44 struct NoDefault {
45   NoDefault(int, int) {}
46   char a, b, c;
47 };
48
49 static_assert(sizeof(Optional<char>) == 2, "");
50 static_assert(sizeof(Optional<int>) == 8, "");
51 static_assert(sizeof(Optional<NoDefault>) == 4, "");
52 static_assert(sizeof(Optional<char>) == sizeof(boost::optional<char>), "");
53 static_assert(sizeof(Optional<short>) == sizeof(boost::optional<short>), "");
54 static_assert(sizeof(Optional<int>) == sizeof(boost::optional<int>), "");
55 static_assert(sizeof(Optional<double>) == sizeof(boost::optional<double>), "");
56
57 TEST(Optional, NoDefault) {
58   Optional<NoDefault> x;
59   EXPECT_FALSE(x);
60   x.emplace(4, 5);
61   EXPECT_TRUE(bool(x));
62   x.clear();
63   EXPECT_FALSE(x);
64 }
65
66 TEST(Optional, String) {
67   Optional<std::string> maybeString;
68   EXPECT_FALSE(maybeString);
69   maybeString = "hello";
70   EXPECT_TRUE(bool(maybeString));
71 }
72
73 TEST(Optional, Const) {
74   { // default construct
75     Optional<const int> opt;
76     EXPECT_FALSE(bool(opt));
77     opt.emplace(4);
78     EXPECT_EQ(*opt, 4);
79     opt.emplace(5);
80     EXPECT_EQ(*opt, 5);
81     opt.clear();
82     EXPECT_FALSE(bool(opt));
83   }
84   { // copy-constructed
85     const int x = 6;
86     Optional<const int> opt(x);
87     EXPECT_EQ(*opt, 6);
88   }
89   { // move-constructed
90     const int x = 7;
91     Optional<const int> opt(std::move(x));
92     EXPECT_EQ(*opt, 7);
93   }
94   // no assignment allowed
95 }
96
97 TEST(Optional, Simple) {
98   Optional<int> opt;
99   EXPECT_FALSE(bool(opt));
100   opt = 4;
101   EXPECT_TRUE(bool(opt));
102   EXPECT_EQ(4, *opt);
103   opt = 5;
104   EXPECT_EQ(5, *opt);
105   opt.clear();
106   EXPECT_FALSE(bool(opt));
107 }
108
109 TEST(Optional, EmptyConstruct) {
110   Optional<int> opt;
111   EXPECT_FALSE(bool(opt));
112   Optional<int> test1(opt);
113   EXPECT_FALSE(bool(test1));
114   Optional<int> test2(std::move(opt));
115   EXPECT_FALSE(bool(test2));
116 }
117
118 TEST(Optional, Unique) {
119   Optional<unique_ptr<int>> opt;
120
121   opt.clear();
122   EXPECT_FALSE(bool(opt));
123   // empty->emplaced
124   opt.emplace(new int(5));
125   EXPECT_TRUE(bool(opt));
126   EXPECT_EQ(5, **opt);
127
128   opt.clear();
129   // empty->moved
130   opt = unique_ptr<int>(new int(6));
131   EXPECT_EQ(6, **opt);
132   // full->moved
133   opt = unique_ptr<int>(new int(7));
134   EXPECT_EQ(7, **opt);
135
136   // move it out by move construct
137   Optional<unique_ptr<int>> moved(std::move(opt));
138   EXPECT_TRUE(bool(moved));
139   EXPECT_FALSE(bool(opt));
140   EXPECT_EQ(7, **moved);
141
142   EXPECT_TRUE(bool(moved));
143   opt = std::move(moved); // move it back by move assign
144   EXPECT_FALSE(bool(moved));
145   EXPECT_TRUE(bool(opt));
146   EXPECT_EQ(7, **opt);
147 }
148
149 TEST(Optional, Shared) {
150   shared_ptr<int> ptr;
151   Optional<shared_ptr<int>> opt;
152   EXPECT_FALSE(bool(opt));
153   // empty->emplaced
154   opt.emplace(new int(5));
155   EXPECT_TRUE(bool(opt));
156   ptr = opt.value();
157   EXPECT_EQ(ptr.get(), opt->get());
158   EXPECT_EQ(2, ptr.use_count());
159   opt.clear();
160   EXPECT_EQ(1, ptr.use_count());
161   // full->copied
162   opt = ptr;
163   EXPECT_EQ(2, ptr.use_count());
164   EXPECT_EQ(ptr.get(), opt->get());
165   opt.clear();
166   EXPECT_EQ(1, ptr.use_count());
167   // full->moved
168   opt = std::move(ptr);
169   EXPECT_EQ(1, opt->use_count());
170   EXPECT_EQ(nullptr, ptr.get());
171   {
172     Optional<shared_ptr<int>> copied(opt);
173     EXPECT_EQ(2, opt->use_count());
174     Optional<shared_ptr<int>> moved(std::move(opt));
175     EXPECT_EQ(2, moved->use_count());
176     moved.emplace(new int(6));
177     EXPECT_EQ(1, moved->use_count());
178     copied = moved;
179     EXPECT_EQ(2, moved->use_count());
180   }
181 }
182
183 TEST(Optional, Order) {
184   std::vector<Optional<int>> vect{
185     { none },
186     { 3 },
187     { 1 },
188     { none },
189     { 2 },
190   };
191   std::vector<Optional<int>> expected {
192     { none },
193     { none },
194     { 1 },
195     { 2 },
196     { 3 },
197   };
198   std::sort(vect.begin(), vect.end());
199   EXPECT_EQ(vect, expected);
200 }
201
202 TEST(Optional, Swap) {
203   Optional<std::string> a;
204   Optional<std::string> b;
205
206   swap(a, b);
207   EXPECT_FALSE(a.hasValue());
208   EXPECT_FALSE(b.hasValue());
209
210   a = "hello";
211   EXPECT_TRUE(a.hasValue());
212   EXPECT_FALSE(b.hasValue());
213   EXPECT_EQ("hello", a.value());
214
215   swap(a, b);
216   EXPECT_FALSE(a.hasValue());
217   EXPECT_TRUE(b.hasValue());
218   EXPECT_EQ("hello", b.value());
219
220   a = "bye";
221   EXPECT_TRUE(a.hasValue());
222   EXPECT_EQ("bye", a.value());
223
224   swap(a, b);
225 }
226
227 TEST(Optional, Comparisons) {
228   Optional<int> o_;
229   Optional<int> o1(1);
230   Optional<int> o2(2);
231
232   EXPECT_TRUE(o_ <= o_);
233   EXPECT_TRUE(o_ == o_);
234   EXPECT_TRUE(o_ >= o_);
235
236   EXPECT_TRUE(o1 < o2);
237   EXPECT_TRUE(o1 <= o2);
238   EXPECT_TRUE(o1 <= o1);
239   EXPECT_TRUE(o1 == o1);
240   EXPECT_TRUE(o1 != o2);
241   EXPECT_TRUE(o1 >= o1);
242   EXPECT_TRUE(o2 >= o1);
243   EXPECT_TRUE(o2 > o1);
244
245   EXPECT_FALSE(o2 < o1);
246   EXPECT_FALSE(o2 <= o1);
247   EXPECT_FALSE(o2 <= o1);
248   EXPECT_FALSE(o2 == o1);
249   EXPECT_FALSE(o1 != o1);
250   EXPECT_FALSE(o1 >= o2);
251   EXPECT_FALSE(o1 >= o2);
252   EXPECT_FALSE(o1 > o2);
253
254   /* folly::Optional explicitly doesn't support comparisons with contained value
255   EXPECT_TRUE(1 < o2);
256   EXPECT_TRUE(1 <= o2);
257   EXPECT_TRUE(1 <= o1);
258   EXPECT_TRUE(1 == o1);
259   EXPECT_TRUE(2 != o1);
260   EXPECT_TRUE(1 >= o1);
261   EXPECT_TRUE(2 >= o1);
262   EXPECT_TRUE(2 > o1);
263
264   EXPECT_FALSE(o2 < 1);
265   EXPECT_FALSE(o2 <= 1);
266   EXPECT_FALSE(o2 <= 1);
267   EXPECT_FALSE(o2 == 1);
268   EXPECT_FALSE(o2 != 2);
269   EXPECT_FALSE(o1 >= 2);
270   EXPECT_FALSE(o1 >= 2);
271   EXPECT_FALSE(o1 > 2);
272   */
273
274   // boost::optional does support comparison with contained value, which can
275   // lead to confusion when a bool is contained
276   boost::optional<int> boi(3);
277   EXPECT_TRUE(boi < 5);
278   EXPECT_TRUE(boi <= 4);
279   EXPECT_TRUE(boi == 3);
280   EXPECT_TRUE(boi != 2);
281   EXPECT_TRUE(boi >= 1);
282   EXPECT_TRUE(boi > 0);
283   EXPECT_TRUE(1 <  boi);
284   EXPECT_TRUE(2 <= boi);
285   EXPECT_TRUE(3 == boi);
286   EXPECT_TRUE(4 != boi);
287   EXPECT_TRUE(5 >= boi);
288   EXPECT_TRUE(6 >  boi);
289
290   boost::optional<bool> bob(false);
291   EXPECT_TRUE(bob);
292   EXPECT_TRUE(bob == false); // well that was confusing
293   EXPECT_FALSE(bob != false);
294 }
295
296 TEST(Optional, Conversions) {
297   Optional<bool> mbool;
298   Optional<short> mshort;
299   Optional<char*> mstr;
300   Optional<int> mint;
301
302   //These don't compile
303   //bool b = mbool;
304   //short s = mshort;
305   //char* c = mstr;
306   //int x = mint;
307   //char* c(mstr);
308   //short s(mshort);
309   //int x(mint);
310
311   // intended explicit operator bool, for if (opt).
312   bool b(mbool);
313
314   // Truthy tests work and are not ambiguous
315   if (mbool && mshort && mstr && mint) { // only checks not-empty
316     if (*mbool && *mshort && *mstr && *mint) { // only checks value
317       ;
318     }
319   }
320
321   mbool = false;
322   EXPECT_TRUE(bool(mbool));
323   EXPECT_FALSE(*mbool);
324
325   mbool = true;
326   EXPECT_TRUE(bool(mbool));
327   EXPECT_TRUE(*mbool);
328
329   mbool = none;
330   EXPECT_FALSE(bool(mbool));
331
332   // No conversion allowed; does not compile
333   // EXPECT_TRUE(mbool == false);
334 }
335
336 TEST(Optional, Pointee) {
337   Optional<int> x;
338   EXPECT_FALSE(get_pointer(x));
339   x = 1;
340   EXPECT_TRUE(get_pointer(x));
341   *get_pointer(x) = 2;
342   EXPECT_TRUE(*x == 2);
343   x = none;
344   EXPECT_FALSE(get_pointer(x));
345 }
346
347 TEST(Optional, MakeOptional) {
348   // const L-value version
349   const std::string s("abc");
350   auto optStr = make_optional(s);
351   ASSERT_TRUE(optStr.hasValue());
352   EXPECT_EQ(*optStr, "abc");
353   *optStr = "cde";
354   EXPECT_EQ(s, "abc");
355   EXPECT_EQ(*optStr, "cde");
356
357   // L-value version
358   std::string s2("abc");
359   auto optStr2 = make_optional(s2);
360   ASSERT_TRUE(optStr2.hasValue());
361   EXPECT_EQ(*optStr2, "abc");
362   *optStr2 = "cde";
363   // it's vital to check that s2 wasn't clobbered
364   EXPECT_EQ(s2, "abc");
365
366   // L-value reference version
367   std::string& s3(s2);
368   auto optStr3 = make_optional(s3);
369   ASSERT_TRUE(optStr3.hasValue());
370   EXPECT_EQ(*optStr3, "abc");
371   *optStr3 = "cde";
372   EXPECT_EQ(s3, "abc");
373
374   // R-value ref version
375   unique_ptr<int> pInt(new int(3));
376   auto optIntPtr = make_optional(std::move(pInt));
377   EXPECT_TRUE(pInt.get() == nullptr);
378   ASSERT_TRUE(optIntPtr.hasValue());
379   EXPECT_EQ(**optIntPtr, 3);
380 }
381
382 class ContainsOptional {
383  public:
384   ContainsOptional() { }
385   explicit ContainsOptional(int x) : opt_(x) { }
386   bool hasValue() const { return opt_.hasValue(); }
387   int value() const { return opt_.value(); }
388
389   ContainsOptional(const ContainsOptional &other) = default;
390   ContainsOptional& operator=(const ContainsOptional &other) = default;
391   ContainsOptional(ContainsOptional &&other) = default;
392   ContainsOptional& operator=(ContainsOptional &&other) = default;
393
394  private:
395   Optional<int> opt_;
396 };
397
398 /**
399  * Test that a class containing an Optional can be copy and move assigned.
400  * This was broken under gcc 4.7 until assignment operators were explicitly
401  * defined.
402  */
403 TEST(Optional, AssignmentContained) {
404   {
405     ContainsOptional source(5), target;
406     target = source;
407     EXPECT_TRUE(target.hasValue());
408     EXPECT_EQ(5, target.value());
409   }
410
411   {
412     ContainsOptional source(5), target;
413     target = std::move(source);
414     EXPECT_TRUE(target.hasValue());
415     EXPECT_EQ(5, target.value());
416     EXPECT_FALSE(source.hasValue());
417   }
418
419   {
420     ContainsOptional opt_uninit, target(10);
421     target = opt_uninit;
422     EXPECT_FALSE(target.hasValue());
423   }
424 }
425
426 }