folly::Future integration with Python
[folly.git] / folly / test / OptionalTest.cpp
1 /*
2  * Copyright 2016 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 #include <folly/Portability.h>
19
20 #include <memory>
21 #include <vector>
22 #include <algorithm>
23 #include <iomanip>
24 #include <string>
25 #include <type_traits>
26
27 #include <glog/logging.h>
28 #include <gtest/gtest.h>
29 #include <boost/optional.hpp>
30
31 using std::unique_ptr;
32 using std::shared_ptr;
33
34 namespace folly {
35
36 template<class V>
37 std::ostream& operator<<(std::ostream& os, const Optional<V>& v) {
38   if (v) {
39     os << "Optional(" << v.value() << ')';
40   } else {
41     os << "None";
42   }
43   return os;
44 }
45
46 struct NoDefault {
47   NoDefault(int, int) {}
48   char a, b, c;
49 };
50
51 static_assert(sizeof(Optional<char>) == 2, "");
52 static_assert(sizeof(Optional<int>) == 8, "");
53 static_assert(sizeof(Optional<NoDefault>) == 4, "");
54 static_assert(sizeof(Optional<char>) == sizeof(boost::optional<char>), "");
55 static_assert(sizeof(Optional<short>) == sizeof(boost::optional<short>), "");
56 static_assert(sizeof(Optional<int>) == sizeof(boost::optional<int>), "");
57 static_assert(sizeof(Optional<double>) == sizeof(boost::optional<double>), "");
58
59 TEST(Optional, NoDefault) {
60   Optional<NoDefault> x;
61   EXPECT_FALSE(x);
62   x.emplace(4, 5);
63   EXPECT_TRUE(bool(x));
64   x.clear();
65   EXPECT_FALSE(x);
66 }
67
68 TEST(Optional, String) {
69   Optional<std::string> maybeString;
70   EXPECT_FALSE(maybeString);
71   maybeString = "hello";
72   EXPECT_TRUE(bool(maybeString));
73 }
74
75 TEST(Optional, Const) {
76   { // default construct
77     Optional<const int> opt;
78     EXPECT_FALSE(bool(opt));
79     opt.emplace(4);
80     EXPECT_EQ(*opt, 4);
81     opt.emplace(5);
82     EXPECT_EQ(*opt, 5);
83     opt.clear();
84     EXPECT_FALSE(bool(opt));
85   }
86   { // copy-constructed
87     const int x = 6;
88     Optional<const int> opt(x);
89     EXPECT_EQ(*opt, 6);
90   }
91   { // move-constructed
92     const int x = 7;
93     Optional<const int> opt(std::move(x));
94     EXPECT_EQ(*opt, 7);
95   }
96   // no assignment allowed
97 }
98
99 TEST(Optional, Simple) {
100   Optional<int> opt;
101   EXPECT_FALSE(bool(opt));
102   EXPECT_EQ(42, opt.value_or(42));
103   opt = 4;
104   EXPECT_TRUE(bool(opt));
105   EXPECT_EQ(4, *opt);
106   EXPECT_EQ(4, opt.value_or(42));
107   opt = 5;
108   EXPECT_EQ(5, *opt);
109   opt.clear();
110   EXPECT_FALSE(bool(opt));
111 }
112
113 class MoveTester {
114 public:
115   /* implicit */ MoveTester(const char* s) : s_(s) {}
116   MoveTester(const MoveTester&) = default;
117   MoveTester(MoveTester&& other) noexcept {
118     s_ = std::move(other.s_);
119     other.s_ = "";
120   }
121   MoveTester& operator=(const MoveTester&) = default;
122   MoveTester& operator=(MoveTester&& other) noexcept {
123     s_ = std::move(other.s_);
124     other.s_ = "";
125     return *this;
126   }
127 private:
128   friend bool operator==(const MoveTester& o1, const MoveTester& o2);
129   std::string s_;
130 };
131
132 bool operator==(const MoveTester& o1, const MoveTester& o2) {
133   return o1.s_ == o2.s_;
134 }
135
136 TEST(Optional, value_or_rvalue_arg) {
137   Optional<MoveTester> opt;
138   MoveTester dflt = "hello";
139   EXPECT_EQ("hello", opt.value_or(dflt));
140   EXPECT_EQ("hello", dflt);
141   EXPECT_EQ("hello", opt.value_or(std::move(dflt)));
142   EXPECT_EQ("", dflt);
143   EXPECT_EQ("world", opt.value_or("world"));
144
145   dflt = "hello";
146   // Make sure that the const overload works on const objects
147   const auto& optc = opt;
148   EXPECT_EQ("hello", optc.value_or(dflt));
149   EXPECT_EQ("hello", dflt);
150   EXPECT_EQ("hello", optc.value_or(std::move(dflt)));
151   EXPECT_EQ("", dflt);
152   EXPECT_EQ("world", optc.value_or("world"));
153
154   dflt = "hello";
155   opt = "meow";
156   EXPECT_EQ("meow", opt.value_or(dflt));
157   EXPECT_EQ("hello", dflt);
158   EXPECT_EQ("meow", opt.value_or(std::move(dflt)));
159   EXPECT_EQ("hello", dflt);  // only moved if used
160 }
161
162 TEST(Optional, value_or_noncopyable) {
163   Optional<std::unique_ptr<int>> opt;
164   std::unique_ptr<int> dflt(new int(42));
165   EXPECT_EQ(42, *std::move(opt).value_or(std::move(dflt)));
166 }
167
168 struct ExpectingDeleter {
169   explicit ExpectingDeleter(int expected) : expected(expected) { }
170   int expected;
171   void operator()(const int* ptr) {
172     EXPECT_EQ(*ptr, expected);
173     delete ptr;
174   }
175 };
176
177 TEST(Optional, value_life_extention) {
178   // Extends the life of the value.
179   const auto& ptr = Optional<std::unique_ptr<int, ExpectingDeleter>>(
180       {new int(42), ExpectingDeleter{1337}}).value();
181   *ptr = 1337;
182 }
183
184 TEST(Optional, value_move) {
185   auto ptr = Optional<std::unique_ptr<int, ExpectingDeleter>>(
186       {new int(42), ExpectingDeleter{1337}}).value();
187   *ptr = 1337;
188 }
189
190 TEST(Optional, dereference_life_extention) {
191   // Extends the life of the value.
192   const auto& ptr = *Optional<std::unique_ptr<int, ExpectingDeleter>>(
193       {new int(42), ExpectingDeleter{1337}});
194   *ptr = 1337;
195 }
196
197 TEST(Optional, dereference_move) {
198   auto ptr = *Optional<std::unique_ptr<int, ExpectingDeleter>>(
199       {new int(42), ExpectingDeleter{1337}});
200   *ptr = 1337;
201 }
202
203 TEST(Optional, EmptyConstruct) {
204   Optional<int> opt;
205   EXPECT_FALSE(bool(opt));
206   Optional<int> test1(opt);
207   EXPECT_FALSE(bool(test1));
208   Optional<int> test2(std::move(opt));
209   EXPECT_FALSE(bool(test2));
210 }
211
212 TEST(Optional, Unique) {
213   Optional<unique_ptr<int>> opt;
214
215   opt.clear();
216   EXPECT_FALSE(bool(opt));
217   // empty->emplaced
218   opt.emplace(new int(5));
219   EXPECT_TRUE(bool(opt));
220   EXPECT_EQ(5, **opt);
221
222   opt.clear();
223   // empty->moved
224   opt = unique_ptr<int>(new int(6));
225   EXPECT_EQ(6, **opt);
226   // full->moved
227   opt = unique_ptr<int>(new int(7));
228   EXPECT_EQ(7, **opt);
229
230   // move it out by move construct
231   Optional<unique_ptr<int>> moved(std::move(opt));
232   EXPECT_TRUE(bool(moved));
233   EXPECT_FALSE(bool(opt));
234   EXPECT_EQ(7, **moved);
235
236   EXPECT_TRUE(bool(moved));
237   opt = std::move(moved); // move it back by move assign
238   EXPECT_FALSE(bool(moved));
239   EXPECT_TRUE(bool(opt));
240   EXPECT_EQ(7, **opt);
241 }
242
243 TEST(Optional, Shared) {
244   shared_ptr<int> ptr;
245   Optional<shared_ptr<int>> opt;
246   EXPECT_FALSE(bool(opt));
247   // empty->emplaced
248   opt.emplace(new int(5));
249   EXPECT_TRUE(bool(opt));
250   ptr = opt.value();
251   EXPECT_EQ(ptr.get(), opt->get());
252   EXPECT_EQ(2, ptr.use_count());
253   opt.clear();
254   EXPECT_EQ(1, ptr.use_count());
255   // full->copied
256   opt = ptr;
257   EXPECT_EQ(2, ptr.use_count());
258   EXPECT_EQ(ptr.get(), opt->get());
259   opt.clear();
260   EXPECT_EQ(1, ptr.use_count());
261   // full->moved
262   opt = std::move(ptr);
263   EXPECT_EQ(1, opt->use_count());
264   EXPECT_EQ(nullptr, ptr.get());
265   {
266     Optional<shared_ptr<int>> copied(opt);
267     EXPECT_EQ(2, opt->use_count());
268     Optional<shared_ptr<int>> moved(std::move(opt));
269     EXPECT_EQ(2, moved->use_count());
270     moved.emplace(new int(6));
271     EXPECT_EQ(1, moved->use_count());
272     copied = moved;
273     EXPECT_EQ(2, moved->use_count());
274   }
275 }
276
277 TEST(Optional, Order) {
278   std::vector<Optional<int>> vect{
279     { none },
280     { 3 },
281     { 1 },
282     { none },
283     { 2 },
284   };
285   std::vector<Optional<int>> expected {
286     { none },
287     { none },
288     { 1 },
289     { 2 },
290     { 3 },
291   };
292   std::sort(vect.begin(), vect.end());
293   EXPECT_EQ(vect, expected);
294 }
295
296 TEST(Optional, Swap) {
297   Optional<std::string> a;
298   Optional<std::string> b;
299
300   swap(a, b);
301   EXPECT_FALSE(a.hasValue());
302   EXPECT_FALSE(b.hasValue());
303
304   a = "hello";
305   EXPECT_TRUE(a.hasValue());
306   EXPECT_FALSE(b.hasValue());
307   EXPECT_EQ("hello", a.value());
308
309   swap(a, b);
310   EXPECT_FALSE(a.hasValue());
311   EXPECT_TRUE(b.hasValue());
312   EXPECT_EQ("hello", b.value());
313
314   a = "bye";
315   EXPECT_TRUE(a.hasValue());
316   EXPECT_EQ("bye", a.value());
317
318   swap(a, b);
319 }
320
321 TEST(Optional, Comparisons) {
322   Optional<int> o_;
323   Optional<int> o1(1);
324   Optional<int> o2(2);
325
326   EXPECT_TRUE(o_ <= (o_));
327   EXPECT_TRUE(o_ == (o_));
328   EXPECT_TRUE(o_ >= (o_));
329
330   EXPECT_TRUE(o1 < o2);
331   EXPECT_TRUE(o1 <= o2);
332   EXPECT_TRUE(o1 <= (o1));
333   EXPECT_TRUE(o1 == (o1));
334   EXPECT_TRUE(o1 != o2);
335   EXPECT_TRUE(o1 >= (o1));
336   EXPECT_TRUE(o2 >= o1);
337   EXPECT_TRUE(o2 > o1);
338
339   EXPECT_FALSE(o2 < o1);
340   EXPECT_FALSE(o2 <= o1);
341   EXPECT_FALSE(o2 <= o1);
342   EXPECT_FALSE(o2 == o1);
343   EXPECT_FALSE(o1 != (o1));
344   EXPECT_FALSE(o1 >= o2);
345   EXPECT_FALSE(o1 >= o2);
346   EXPECT_FALSE(o1 > o2);
347
348   /* folly::Optional explicitly doesn't support comparisons with contained value
349   EXPECT_TRUE(1 < o2);
350   EXPECT_TRUE(1 <= o2);
351   EXPECT_TRUE(1 <= o1);
352   EXPECT_TRUE(1 == o1);
353   EXPECT_TRUE(2 != o1);
354   EXPECT_TRUE(1 >= o1);
355   EXPECT_TRUE(2 >= o1);
356   EXPECT_TRUE(2 > o1);
357
358   EXPECT_FALSE(o2 < 1);
359   EXPECT_FALSE(o2 <= 1);
360   EXPECT_FALSE(o2 <= 1);
361   EXPECT_FALSE(o2 == 1);
362   EXPECT_FALSE(o2 != 2);
363   EXPECT_FALSE(o1 >= 2);
364   EXPECT_FALSE(o1 >= 2);
365   EXPECT_FALSE(o1 > 2);
366   */
367
368   // boost::optional does support comparison with contained value, which can
369   // lead to confusion when a bool is contained
370   boost::optional<int> boi(3);
371   EXPECT_TRUE(boi < 5);
372   EXPECT_TRUE(boi <= 4);
373   EXPECT_TRUE(boi == 3);
374   EXPECT_TRUE(boi != 2);
375   EXPECT_TRUE(boi >= 1);
376   EXPECT_TRUE(boi > 0);
377   EXPECT_TRUE(1 <  boi);
378   EXPECT_TRUE(2 <= boi);
379   EXPECT_TRUE(3 == boi);
380   EXPECT_TRUE(4 != boi);
381   EXPECT_TRUE(5 >= boi);
382   EXPECT_TRUE(6 >  boi);
383
384   boost::optional<bool> bob(false);
385   EXPECT_TRUE((bool)bob);
386   EXPECT_TRUE(bob == false); // well that was confusing
387   EXPECT_FALSE(bob != false);
388 }
389
390 TEST(Optional, Conversions) {
391   Optional<bool> mbool;
392   Optional<short> mshort;
393   Optional<char*> mstr;
394   Optional<int> mint;
395
396   //These don't compile
397   //bool b = mbool;
398   //short s = mshort;
399   //char* c = mstr;
400   //int x = mint;
401   //char* c(mstr);
402   //short s(mshort);
403   //int x(mint);
404
405   // intended explicit operator bool, for if (opt).
406   bool b(mbool);
407   EXPECT_FALSE(b);
408
409   // Truthy tests work and are not ambiguous
410   if (mbool && mshort && mstr && mint) { // only checks not-empty
411     if (*mbool && *mshort && *mstr && *mint) { // only checks value
412       ;
413     }
414   }
415
416   mbool = false;
417   EXPECT_TRUE(bool(mbool));
418   EXPECT_FALSE(*mbool);
419
420   mbool = true;
421   EXPECT_TRUE(bool(mbool));
422   EXPECT_TRUE(*mbool);
423
424   mbool = none;
425   EXPECT_FALSE(bool(mbool));
426
427   // No conversion allowed; does not compile
428   // EXPECT_TRUE(mbool == false);
429 }
430
431 TEST(Optional, Pointee) {
432   Optional<int> x;
433   EXPECT_FALSE(get_pointer(x));
434   x = 1;
435   EXPECT_TRUE(get_pointer(x));
436   *get_pointer(x) = 2;
437   EXPECT_TRUE(*x == 2);
438   x = none;
439   EXPECT_FALSE(get_pointer(x));
440 }
441
442 TEST(Optional, MakeOptional) {
443   // const L-value version
444   const std::string s("abc");
445   auto optStr = make_optional(s);
446   ASSERT_TRUE(optStr.hasValue());
447   EXPECT_EQ(*optStr, "abc");
448   *optStr = "cde";
449   EXPECT_EQ(s, "abc");
450   EXPECT_EQ(*optStr, "cde");
451
452   // L-value version
453   std::string s2("abc");
454   auto optStr2 = make_optional(s2);
455   ASSERT_TRUE(optStr2.hasValue());
456   EXPECT_EQ(*optStr2, "abc");
457   *optStr2 = "cde";
458   // it's vital to check that s2 wasn't clobbered
459   EXPECT_EQ(s2, "abc");
460
461   // L-value reference version
462   std::string& s3(s2);
463   auto optStr3 = make_optional(s3);
464   ASSERT_TRUE(optStr3.hasValue());
465   EXPECT_EQ(*optStr3, "abc");
466   *optStr3 = "cde";
467   EXPECT_EQ(s3, "abc");
468
469   // R-value ref version
470   unique_ptr<int> pInt(new int(3));
471   auto optIntPtr = make_optional(std::move(pInt));
472   EXPECT_TRUE(pInt.get() == nullptr);
473   ASSERT_TRUE(optIntPtr.hasValue());
474   EXPECT_EQ(**optIntPtr, 3);
475 }
476
477 #if __CLANG_PREREQ(3, 6)
478 # pragma clang diagnostic push
479 # pragma clang diagnostic ignored "-Wself-move"
480 #endif
481
482 TEST(Optional, SelfAssignment) {
483   Optional<int> a = 42;
484   a = a;
485   ASSERT_TRUE(a.hasValue() && a.value() == 42);
486
487   Optional<int> b = 23333333;
488   b = std::move(b);
489   ASSERT_TRUE(b.hasValue() && b.value() == 23333333);
490 }
491
492 #if __CLANG_PREREQ(3, 6)
493 # pragma clang diagnostic pop
494 #endif
495
496 class ContainsOptional {
497  public:
498   ContainsOptional() { }
499   explicit ContainsOptional(int x) : opt_(x) { }
500   bool hasValue() const { return opt_.hasValue(); }
501   int value() const { return opt_.value(); }
502
503   ContainsOptional(const ContainsOptional &other) = default;
504   ContainsOptional& operator=(const ContainsOptional &other) = default;
505   ContainsOptional(ContainsOptional &&other) = default;
506   ContainsOptional& operator=(ContainsOptional &&other) = default;
507
508  private:
509   Optional<int> opt_;
510 };
511
512 /**
513  * Test that a class containing an Optional can be copy and move assigned.
514  * This was broken under gcc 4.7 until assignment operators were explicitly
515  * defined.
516  */
517 TEST(Optional, AssignmentContained) {
518   {
519     ContainsOptional source(5), target;
520     target = source;
521     EXPECT_TRUE(target.hasValue());
522     EXPECT_EQ(5, target.value());
523   }
524
525   {
526     ContainsOptional source(5), target;
527     target = std::move(source);
528     EXPECT_TRUE(target.hasValue());
529     EXPECT_EQ(5, target.value());
530     EXPECT_FALSE(source.hasValue());
531   }
532
533   {
534     ContainsOptional opt_uninit, target(10);
535     target = opt_uninit;
536     EXPECT_FALSE(target.hasValue());
537   }
538 }
539
540 TEST(Optional, Exceptions) {
541   Optional<int> empty;
542   EXPECT_THROW(empty.value(), OptionalEmptyException);
543 }
544
545 TEST(Optional, NoThrowDefaultConstructible) {
546   EXPECT_TRUE(std::is_nothrow_default_constructible<Optional<bool>>::value);
547 }
548
549 struct NoDestructor {};
550
551 struct WithDestructor {
552   ~WithDestructor();
553 };
554
555 TEST(Optional, TriviallyDestructible) {
556   // These could all be static_asserts but EXPECT_* give much nicer output on
557   // failure.
558   EXPECT_TRUE(std::is_trivially_destructible<Optional<NoDestructor>>::value);
559   EXPECT_TRUE(std::is_trivially_destructible<Optional<int>>::value);
560   EXPECT_FALSE(std::is_trivially_destructible<Optional<WithDestructor>>::value);
561 }
562 }