Modernize use of std::make_unique
[folly.git] / folly / test / OptionalTest.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/Optional.h>
18 #include <folly/Portability.h>
19 #include <folly/portability/GTest.h>
20
21 #include <algorithm>
22 #include <iomanip>
23 #include <memory>
24 #include <string>
25 #include <type_traits>
26 #include <unordered_map>
27 #include <vector>
28
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
128  private:
129   friend bool operator==(const MoveTester& o1, const MoveTester& o2);
130   std::string s_;
131 };
132
133 bool operator==(const MoveTester& o1, const MoveTester& o2) {
134   return o1.s_ == o2.s_;
135 }
136
137 TEST(Optional, value_or_rvalue_arg) {
138   Optional<MoveTester> opt;
139   MoveTester dflt = "hello";
140   EXPECT_EQ("hello", opt.value_or(dflt));
141   EXPECT_EQ("hello", dflt);
142   EXPECT_EQ("hello", opt.value_or(std::move(dflt)));
143   EXPECT_EQ("", dflt);
144   EXPECT_EQ("world", opt.value_or("world"));
145
146   dflt = "hello";
147   // Make sure that the const overload works on const objects
148   const auto& optc = opt;
149   EXPECT_EQ("hello", optc.value_or(dflt));
150   EXPECT_EQ("hello", dflt);
151   EXPECT_EQ("hello", optc.value_or(std::move(dflt)));
152   EXPECT_EQ("", dflt);
153   EXPECT_EQ("world", optc.value_or("world"));
154
155   dflt = "hello";
156   opt = "meow";
157   EXPECT_EQ("meow", opt.value_or(dflt));
158   EXPECT_EQ("hello", dflt);
159   EXPECT_EQ("meow", opt.value_or(std::move(dflt)));
160   EXPECT_EQ("hello", dflt);  // only moved if used
161 }
162
163 TEST(Optional, value_or_noncopyable) {
164   Optional<std::unique_ptr<int>> opt;
165   std::unique_ptr<int> dflt(new int(42));
166   EXPECT_EQ(42, *std::move(opt).value_or(std::move(dflt)));
167 }
168
169 struct ExpectingDeleter {
170   explicit ExpectingDeleter(int expected) : expected(expected) { }
171   int expected;
172   void operator()(const int* ptr) {
173     EXPECT_EQ(*ptr, expected);
174     delete ptr;
175   }
176 };
177
178 TEST(Optional, value_move) {
179   auto ptr = Optional<std::unique_ptr<int, ExpectingDeleter>>(
180       {new int(42), ExpectingDeleter{1337}}).value();
181   *ptr = 1337;
182 }
183
184 TEST(Optional, dereference_move) {
185   auto ptr = *Optional<std::unique_ptr<int, ExpectingDeleter>>(
186       {new int(42), ExpectingDeleter{1337}});
187   *ptr = 1337;
188 }
189
190 TEST(Optional, EmptyConstruct) {
191   Optional<int> opt;
192   EXPECT_FALSE(bool(opt));
193   Optional<int> test1(opt);
194   EXPECT_FALSE(bool(test1));
195   Optional<int> test2(std::move(opt));
196   EXPECT_FALSE(bool(test2));
197 }
198
199 TEST(Optional, InPlaceConstruct) {
200   using A = std::pair<int, double>;
201   Optional<A> opt(in_place, 5, 3.2);
202   EXPECT_TRUE(bool(opt));
203   EXPECT_EQ(5, opt->first);
204 }
205
206 TEST(Optional, InPlaceNestedConstruct) {
207   using A = std::pair<int, double>;
208   Optional<Optional<A>> opt(in_place, in_place, 5, 3.2);
209   EXPECT_TRUE(bool(opt));
210   EXPECT_TRUE(bool(*opt));
211   EXPECT_EQ(5, (*opt)->first);
212 }
213
214 TEST(Optional, Unique) {
215   Optional<unique_ptr<int>> opt;
216
217   opt.clear();
218   EXPECT_FALSE(bool(opt));
219   // empty->emplaced
220   opt.emplace(new int(5));
221   EXPECT_TRUE(bool(opt));
222   EXPECT_EQ(5, **opt);
223
224   opt.clear();
225   // empty->moved
226   opt = std::make_unique<int>(6);
227   EXPECT_EQ(6, **opt);
228   // full->moved
229   opt = std::make_unique<int>(7);
230   EXPECT_EQ(7, **opt);
231
232   // move it out by move construct
233   Optional<unique_ptr<int>> moved(std::move(opt));
234   EXPECT_TRUE(bool(moved));
235   EXPECT_FALSE(bool(opt));
236   EXPECT_EQ(7, **moved);
237
238   EXPECT_TRUE(bool(moved));
239   opt = std::move(moved); // move it back by move assign
240   EXPECT_FALSE(bool(moved));
241   EXPECT_TRUE(bool(opt));
242   EXPECT_EQ(7, **opt);
243 }
244
245 TEST(Optional, Shared) {
246   shared_ptr<int> ptr;
247   Optional<shared_ptr<int>> opt;
248   EXPECT_FALSE(bool(opt));
249   // empty->emplaced
250   opt.emplace(new int(5));
251   EXPECT_TRUE(bool(opt));
252   ptr = opt.value();
253   EXPECT_EQ(ptr.get(), opt->get());
254   EXPECT_EQ(2, ptr.use_count());
255   opt.clear();
256   EXPECT_EQ(1, ptr.use_count());
257   // full->copied
258   opt = ptr;
259   EXPECT_EQ(2, ptr.use_count());
260   EXPECT_EQ(ptr.get(), opt->get());
261   opt.clear();
262   EXPECT_EQ(1, ptr.use_count());
263   // full->moved
264   opt = std::move(ptr);
265   EXPECT_EQ(1, opt->use_count());
266   EXPECT_EQ(nullptr, ptr.get());
267   {
268     Optional<shared_ptr<int>> copied(opt);
269     EXPECT_EQ(2, opt->use_count());
270     Optional<shared_ptr<int>> moved(std::move(opt));
271     EXPECT_EQ(2, moved->use_count());
272     moved.emplace(new int(6));
273     EXPECT_EQ(1, moved->use_count());
274     copied = moved;
275     EXPECT_EQ(2, moved->use_count());
276   }
277 }
278
279 TEST(Optional, Order) {
280   std::vector<Optional<int>> vect{
281     { none },
282     { 3 },
283     { 1 },
284     { none },
285     { 2 },
286   };
287   std::vector<Optional<int>> expected {
288     { none },
289     { none },
290     { 1 },
291     { 2 },
292     { 3 },
293   };
294   std::sort(vect.begin(), vect.end());
295   EXPECT_EQ(vect, expected);
296 }
297
298 TEST(Optional, Swap) {
299   Optional<std::string> a;
300   Optional<std::string> b;
301
302   swap(a, b);
303   EXPECT_FALSE(a.hasValue());
304   EXPECT_FALSE(b.hasValue());
305
306   a = "hello";
307   EXPECT_TRUE(a.hasValue());
308   EXPECT_FALSE(b.hasValue());
309   EXPECT_EQ("hello", a.value());
310
311   swap(a, b);
312   EXPECT_FALSE(a.hasValue());
313   EXPECT_TRUE(b.hasValue());
314   EXPECT_EQ("hello", b.value());
315
316   a = "bye";
317   EXPECT_TRUE(a.hasValue());
318   EXPECT_EQ("bye", a.value());
319
320   swap(a, b);
321 }
322
323 TEST(Optional, Comparisons) {
324   Optional<int> o_;
325   Optional<int> o1(1);
326   Optional<int> o2(2);
327
328   EXPECT_TRUE(o_ <= (o_));
329   EXPECT_TRUE(o_ == (o_));
330   EXPECT_TRUE(o_ >= (o_));
331
332   EXPECT_TRUE(o1 < o2);
333   EXPECT_TRUE(o1 <= o2);
334   EXPECT_TRUE(o1 <= (o1));
335   EXPECT_TRUE(o1 == (o1));
336   EXPECT_TRUE(o1 != o2);
337   EXPECT_TRUE(o1 >= (o1));
338   EXPECT_TRUE(o2 >= o1);
339   EXPECT_TRUE(o2 > o1);
340
341   EXPECT_FALSE(o2 < o1);
342   EXPECT_FALSE(o2 <= o1);
343   EXPECT_FALSE(o2 <= o1);
344   EXPECT_FALSE(o2 == o1);
345   EXPECT_FALSE(o1 != (o1));
346   EXPECT_FALSE(o1 >= o2);
347   EXPECT_FALSE(o1 >= o2);
348   EXPECT_FALSE(o1 > o2);
349
350   /* folly::Optional explicitly doesn't support comparisons with contained value
351   EXPECT_TRUE(1 < o2);
352   EXPECT_TRUE(1 <= o2);
353   EXPECT_TRUE(1 <= o1);
354   EXPECT_TRUE(1 == o1);
355   EXPECT_TRUE(2 != o1);
356   EXPECT_TRUE(1 >= o1);
357   EXPECT_TRUE(2 >= o1);
358   EXPECT_TRUE(2 > o1);
359
360   EXPECT_FALSE(o2 < 1);
361   EXPECT_FALSE(o2 <= 1);
362   EXPECT_FALSE(o2 <= 1);
363   EXPECT_FALSE(o2 == 1);
364   EXPECT_FALSE(o2 != 2);
365   EXPECT_FALSE(o1 >= 2);
366   EXPECT_FALSE(o1 >= 2);
367   EXPECT_FALSE(o1 > 2);
368   */
369
370   // boost::optional does support comparison with contained value, which can
371   // lead to confusion when a bool is contained
372   boost::optional<int> boi(3);
373   EXPECT_TRUE(boi < 5);
374   EXPECT_TRUE(boi <= 4);
375   EXPECT_TRUE(boi == 3);
376   EXPECT_TRUE(boi != 2);
377   EXPECT_TRUE(boi >= 1);
378   EXPECT_TRUE(boi > 0);
379   EXPECT_TRUE(1 <  boi);
380   EXPECT_TRUE(2 <= boi);
381   EXPECT_TRUE(3 == boi);
382   EXPECT_TRUE(4 != boi);
383   EXPECT_TRUE(5 >= boi);
384   EXPECT_TRUE(6 >  boi);
385
386   boost::optional<bool> bob(false);
387   EXPECT_TRUE((bool)bob);
388   EXPECT_TRUE(bob == false); // well that was confusing
389   EXPECT_FALSE(bob != false);
390 }
391
392 TEST(Optional, HeterogeneousComparisons) {
393   using opt8 = Optional<uint8_t>;
394   using opt64 = Optional<uint64_t>;
395
396   EXPECT_TRUE(opt8(4) == uint64_t(4));
397   EXPECT_FALSE(opt8(8) == uint64_t(4));
398   EXPECT_FALSE(opt8() == uint64_t(4));
399
400   EXPECT_TRUE(uint64_t(4) == opt8(4));
401   EXPECT_FALSE(uint64_t(4) == opt8(8));
402   EXPECT_FALSE(uint64_t(4) == opt8());
403
404   EXPECT_FALSE(opt8(4) != uint64_t(4));
405   EXPECT_TRUE(opt8(8) != uint64_t(4));
406   EXPECT_TRUE(opt8() != uint64_t(4));
407
408   EXPECT_FALSE(uint64_t(4) != opt8(4));
409   EXPECT_TRUE(uint64_t(4) != opt8(8));
410   EXPECT_TRUE(uint64_t(4) != opt8());
411
412   EXPECT_TRUE(opt8() == opt64());
413   EXPECT_TRUE(opt8(4) == opt64(4));
414   EXPECT_FALSE(opt8(8) == opt64(4));
415   EXPECT_FALSE(opt8() == opt64(4));
416   EXPECT_FALSE(opt8(4) == opt64());
417
418   EXPECT_FALSE(opt8() != opt64());
419   EXPECT_FALSE(opt8(4) != opt64(4));
420   EXPECT_TRUE(opt8(8) != opt64(4));
421   EXPECT_TRUE(opt8() != opt64(4));
422   EXPECT_TRUE(opt8(4) != opt64());
423
424   EXPECT_TRUE(opt8() < opt64(4));
425   EXPECT_TRUE(opt8(4) < opt64(8));
426   EXPECT_FALSE(opt8() < opt64());
427   EXPECT_FALSE(opt8(4) < opt64(4));
428   EXPECT_FALSE(opt8(8) < opt64(4));
429   EXPECT_FALSE(opt8(4) < opt64());
430
431   EXPECT_FALSE(opt8() > opt64(4));
432   EXPECT_FALSE(opt8(4) > opt64(8));
433   EXPECT_FALSE(opt8() > opt64());
434   EXPECT_FALSE(opt8(4) > opt64(4));
435   EXPECT_TRUE(opt8(8) > opt64(4));
436   EXPECT_TRUE(opt8(4) > opt64());
437
438   EXPECT_TRUE(opt8() <= opt64(4));
439   EXPECT_TRUE(opt8(4) <= opt64(8));
440   EXPECT_TRUE(opt8() <= opt64());
441   EXPECT_TRUE(opt8(4) <= opt64(4));
442   EXPECT_FALSE(opt8(8) <= opt64(4));
443   EXPECT_FALSE(opt8(4) <= opt64());
444
445   EXPECT_FALSE(opt8() >= opt64(4));
446   EXPECT_FALSE(opt8(4) >= opt64(8));
447   EXPECT_TRUE(opt8() >= opt64());
448   EXPECT_TRUE(opt8(4) >= opt64(4));
449   EXPECT_TRUE(opt8(8) >= opt64(4));
450   EXPECT_TRUE(opt8(4) >= opt64());
451 }
452
453 TEST(Optional, NoneComparisons) {
454   using opt = Optional<int>;
455   EXPECT_TRUE(opt() == none);
456   EXPECT_TRUE(none == opt());
457   EXPECT_FALSE(opt(1) == none);
458   EXPECT_FALSE(none == opt(1));
459
460   EXPECT_FALSE(opt() != none);
461   EXPECT_FALSE(none != opt());
462   EXPECT_TRUE(opt(1) != none);
463   EXPECT_TRUE(none != opt(1));
464
465   EXPECT_FALSE(opt() < none);
466   EXPECT_FALSE(none < opt());
467   EXPECT_FALSE(opt(1) < none);
468   EXPECT_TRUE(none < opt(1));
469
470   EXPECT_FALSE(opt() > none);
471   EXPECT_FALSE(none > opt());
472   EXPECT_FALSE(none > opt(1));
473   EXPECT_TRUE(opt(1) > none);
474
475   EXPECT_TRUE(opt() <= none);
476   EXPECT_TRUE(none <= opt());
477   EXPECT_FALSE(opt(1) <= none);
478   EXPECT_TRUE(none <= opt(1));
479
480   EXPECT_TRUE(opt() >= none);
481   EXPECT_TRUE(none >= opt());
482   EXPECT_TRUE(opt(1) >= none);
483   EXPECT_FALSE(none >= opt(1));
484 }
485
486 TEST(Optional, Conversions) {
487   Optional<bool> mbool;
488   Optional<short> mshort;
489   Optional<char*> mstr;
490   Optional<int> mint;
491
492   //These don't compile
493   //bool b = mbool;
494   //short s = mshort;
495   //char* c = mstr;
496   //int x = mint;
497   //char* c(mstr);
498   //short s(mshort);
499   //int x(mint);
500
501   // intended explicit operator bool, for if (opt).
502   bool b(mbool);
503   EXPECT_FALSE(b);
504
505   // Truthy tests work and are not ambiguous
506   if (mbool && mshort && mstr && mint) { // only checks not-empty
507     if (*mbool && *mshort && *mstr && *mint) { // only checks value
508       ;
509     }
510   }
511
512   mbool = false;
513   EXPECT_TRUE(bool(mbool));
514   EXPECT_FALSE(*mbool);
515
516   mbool = true;
517   EXPECT_TRUE(bool(mbool));
518   EXPECT_TRUE(*mbool);
519
520   mbool = none;
521   EXPECT_FALSE(bool(mbool));
522
523   // No conversion allowed; does not compile
524   // EXPECT_TRUE(mbool == false);
525 }
526
527 TEST(Optional, Pointee) {
528   Optional<int> x;
529   EXPECT_FALSE(get_pointer(x));
530   x = 1;
531   EXPECT_TRUE(get_pointer(x));
532   *get_pointer(x) = 2;
533   EXPECT_TRUE(*x == 2);
534   x = none;
535   EXPECT_FALSE(get_pointer(x));
536 }
537
538 TEST(Optional, MakeOptional) {
539   // const L-value version
540   const std::string s("abc");
541   auto optStr = make_optional(s);
542   ASSERT_TRUE(optStr.hasValue());
543   EXPECT_EQ(*optStr, "abc");
544   *optStr = "cde";
545   EXPECT_EQ(s, "abc");
546   EXPECT_EQ(*optStr, "cde");
547
548   // L-value version
549   std::string s2("abc");
550   auto optStr2 = make_optional(s2);
551   ASSERT_TRUE(optStr2.hasValue());
552   EXPECT_EQ(*optStr2, "abc");
553   *optStr2 = "cde";
554   // it's vital to check that s2 wasn't clobbered
555   EXPECT_EQ(s2, "abc");
556
557   // L-value reference version
558   std::string& s3(s2);
559   auto optStr3 = make_optional(s3);
560   ASSERT_TRUE(optStr3.hasValue());
561   EXPECT_EQ(*optStr3, "abc");
562   *optStr3 = "cde";
563   EXPECT_EQ(s3, "abc");
564
565   // R-value ref version
566   unique_ptr<int> pInt(new int(3));
567   auto optIntPtr = make_optional(std::move(pInt));
568   EXPECT_TRUE(pInt.get() == nullptr);
569   ASSERT_TRUE(optIntPtr.hasValue());
570   EXPECT_EQ(**optIntPtr, 3);
571 }
572
573 #if __CLANG_PREREQ(3, 6)
574 # pragma clang diagnostic push
575 # pragma clang diagnostic ignored "-Wself-move"
576 #endif
577
578 TEST(Optional, SelfAssignment) {
579   Optional<int> a = 42;
580   a = a;
581   ASSERT_TRUE(a.hasValue() && a.value() == 42);
582
583   Optional<int> b = 23333333;
584   b = std::move(b);
585   ASSERT_TRUE(b.hasValue() && b.value() == 23333333);
586 }
587
588 #if __CLANG_PREREQ(3, 6)
589 # pragma clang diagnostic pop
590 #endif
591
592 class ContainsOptional {
593  public:
594   ContainsOptional() { }
595   explicit ContainsOptional(int x) : opt_(x) { }
596   bool hasValue() const { return opt_.hasValue(); }
597   int value() const { return opt_.value(); }
598
599   ContainsOptional(const ContainsOptional &other) = default;
600   ContainsOptional& operator=(const ContainsOptional &other) = default;
601   ContainsOptional(ContainsOptional &&other) = default;
602   ContainsOptional& operator=(ContainsOptional &&other) = default;
603
604  private:
605   Optional<int> opt_;
606 };
607
608 /**
609  * Test that a class containing an Optional can be copy and move assigned.
610  * This was broken under gcc 4.7 until assignment operators were explicitly
611  * defined.
612  */
613 TEST(Optional, AssignmentContained) {
614   {
615     ContainsOptional source(5), target;
616     target = source;
617     EXPECT_TRUE(target.hasValue());
618     EXPECT_EQ(5, target.value());
619   }
620
621   {
622     ContainsOptional source(5), target;
623     target = std::move(source);
624     EXPECT_TRUE(target.hasValue());
625     EXPECT_EQ(5, target.value());
626     EXPECT_FALSE(source.hasValue());
627   }
628
629   {
630     ContainsOptional opt_uninit, target(10);
631     target = opt_uninit;
632     EXPECT_FALSE(target.hasValue());
633   }
634 }
635
636 TEST(Optional, Exceptions) {
637   Optional<int> empty;
638   EXPECT_THROW(empty.value(), OptionalEmptyException);
639 }
640
641 TEST(Optional, NoThrowDefaultConstructible) {
642   EXPECT_TRUE(std::is_nothrow_default_constructible<Optional<bool>>::value);
643 }
644
645 struct NoDestructor {};
646
647 struct WithDestructor {
648   ~WithDestructor();
649 };
650
651 TEST(Optional, TriviallyDestructible) {
652   // These could all be static_asserts but EXPECT_* give much nicer output on
653   // failure.
654   EXPECT_TRUE(std::is_trivially_destructible<Optional<NoDestructor>>::value);
655   EXPECT_TRUE(std::is_trivially_destructible<Optional<int>>::value);
656   EXPECT_FALSE(std::is_trivially_destructible<Optional<WithDestructor>>::value);
657 }
658
659 TEST(Optional, Hash) {
660   // Test it's usable in std::unordered map (compile time check)
661   std::unordered_map<Optional<int>, Optional<int>> obj;
662   // Also check the std::hash template can be instantiated by the compiler
663   std::hash<Optional<int>>()(none);
664   std::hash<Optional<int>>()(3);
665 }
666 }