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