2 * Copyright 2017 Facebook, Inc.
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 #include <folly/Expected.h>
18 #include <folly/portability/GTest.h>
24 #include <type_traits>
27 #include <glog/logging.h>
29 using std::unique_ptr;
30 using std::shared_ptr;
34 enum class E { E1, E2 };
36 std::ostream& operator<<(std::ostream& os, E e) {
47 template <class V, class E>
48 std::ostream& operator<<(std::ostream& os, const Expected<V, E>& e) {
50 os << "Expected(" << e.value() << ')';
52 os << "Unexpected(" << e.error() << ')';
58 NoDefault(int, int) {}
62 TEST(Expected, NoDefault) {
64 std::is_default_constructible<Expected<NoDefault, int>>::value, "");
65 Expected<NoDefault, int> x{in_place, 42, 42};
69 x = makeUnexpected(42);
70 EXPECT_FALSE(bool(x));
71 EXPECT_EQ(42, x.error());
74 TEST(Expected, String) {
75 Expected<std::string, int> maybeString;
76 EXPECT_FALSE(bool(maybeString));
77 EXPECT_EQ(0, maybeString.error());
78 maybeString = "hello";
79 EXPECT_TRUE(bool(maybeString));
80 EXPECT_EQ("hello", *maybeString);
83 TEST(Expected, Ambiguous) {
84 // Potentially ambiguous and confusing construction and assignment disallowed:
85 EXPECT_FALSE((std::is_constructible<Expected<int, int>, int>::value));
86 EXPECT_FALSE((std::is_assignable<Expected<int, int>&, int>::value));
89 TEST(Expected, Const) {
90 { // default construct
91 Expected<const int, int> ex;
92 EXPECT_FALSE(bool(ex));
93 EXPECT_EQ(0, ex.error());
98 ex = makeUnexpected(42);
99 EXPECT_FALSE(bool(ex));
100 EXPECT_EQ(42, ex.error());
102 { // copy-constructed
104 Expected<const int, int> ex{in_place, x};
105 Expected<const int, int> ex2 = ex;
108 { // move-constructed
110 Expected<const int, int> ex{in_place, std::move(x)};
111 Expected<const int, int> ex2 = std::move(ex);
114 // no assignment allowed
115 EXPECT_FALSE((std::is_copy_assignable<Expected<const int, int>>::value));
118 TEST(Expected, Simple) {
119 Expected<int, int> ex;
120 EXPECT_FALSE(bool(ex));
121 EXPECT_EQ(42, ex.value_or(42));
123 EXPECT_TRUE(bool(ex));
125 EXPECT_EQ(4, ex.value_or(42));
126 ex = makeUnexpected(-1);
127 EXPECT_FALSE(bool(ex));
128 EXPECT_EQ(-1, ex.error());
129 EXPECT_EQ(42, ex.value_or(42));
134 /* implicit */ MoveTester(const char* s) : s_(s) {}
135 MoveTester(const MoveTester&) = default;
136 MoveTester(MoveTester&& other) noexcept {
137 s_ = std::move(other.s_);
140 MoveTester& operator=(const MoveTester&) = default;
141 MoveTester& operator=(MoveTester&& other) noexcept {
142 s_ = std::move(other.s_);
148 friend bool operator==(const MoveTester& o1, const MoveTester& o2);
152 bool operator==(const MoveTester& o1, const MoveTester& o2) {
153 return o1.s_ == o2.s_;
156 TEST(Expected, value_or_rvalue_arg) {
157 Expected<MoveTester, int> ex = makeUnexpected(-1);
158 MoveTester dflt = "hello";
159 EXPECT_EQ("hello", ex.value_or(dflt));
160 EXPECT_EQ("hello", dflt);
161 EXPECT_EQ("hello", ex.value_or(std::move(dflt)));
163 EXPECT_EQ("world", ex.value_or("world"));
166 // Make sure that the const overload works on const objects
167 const auto& exc = ex;
168 EXPECT_EQ("hello", exc.value_or(dflt));
169 EXPECT_EQ("hello", dflt);
170 EXPECT_EQ("hello", exc.value_or(std::move(dflt)));
172 EXPECT_EQ("world", exc.value_or("world"));
176 EXPECT_EQ("meow", ex.value_or(dflt));
177 EXPECT_EQ("hello", dflt);
178 EXPECT_EQ("meow", ex.value_or(std::move(dflt)));
179 EXPECT_EQ("hello", dflt); // only moved if used
182 TEST(Expected, value_or_noncopyable) {
183 Expected<std::unique_ptr<int>, int> ex{unexpected, 42};
184 std::unique_ptr<int> dflt(new int(42));
185 EXPECT_EQ(42, *std::move(ex).value_or(std::move(dflt)));
188 struct ExpectingDeleter {
189 explicit ExpectingDeleter(int expected) : expected(expected) {}
191 void operator()(const int* ptr) {
192 EXPECT_EQ(*ptr, expected);
197 TEST(Expected, value_move) {
198 auto ptr = Expected<std::unique_ptr<int, ExpectingDeleter>, int>(
199 in_place, new int(42), ExpectingDeleter{1337})
204 TEST(Expected, dereference_move) {
205 auto ptr = *Expected<std::unique_ptr<int, ExpectingDeleter>, int>(
206 in_place, new int(42), ExpectingDeleter{1337});
210 TEST(Expected, EmptyConstruct) {
211 Expected<int, int> ex{unexpected, 42};
212 EXPECT_FALSE(bool(ex));
213 Expected<int, int> test1(ex);
214 EXPECT_FALSE(bool(test1));
215 Expected<int, int> test2(std::move(ex));
216 EXPECT_FALSE(bool(test2));
217 EXPECT_EQ(42, test2.error());
220 TEST(Expected, Unique) {
221 Expected<unique_ptr<int>, int> ex;
223 ex = makeUnexpected(-1);
224 EXPECT_FALSE(bool(ex));
226 ex.emplace(new int(5));
227 EXPECT_TRUE(bool(ex));
230 ex = makeUnexpected(-1);
232 ex = unique_ptr<int>(new int(6));
235 ex = unique_ptr<int>(new int(7));
238 // move it out by move construct
239 Expected<unique_ptr<int>, int> moved(std::move(ex));
240 EXPECT_TRUE(bool(moved));
241 EXPECT_TRUE(bool(ex));
242 EXPECT_EQ(nullptr, ex->get());
243 EXPECT_EQ(7, **moved);
245 EXPECT_TRUE(bool(moved));
246 ex = std::move(moved); // move it back by move assign
247 EXPECT_TRUE(bool(moved));
248 EXPECT_EQ(nullptr, moved->get());
249 EXPECT_TRUE(bool(ex));
253 TEST(Expected, Shared) {
255 Expected<shared_ptr<int>, int> ex{unexpected, -1};
256 EXPECT_FALSE(bool(ex));
258 ex.emplace(new int(5));
259 EXPECT_TRUE(bool(ex));
261 EXPECT_EQ(ptr.get(), ex->get());
262 EXPECT_EQ(2, ptr.use_count());
263 ex = makeUnexpected(-1);
264 EXPECT_EQ(1, ptr.use_count());
267 EXPECT_EQ(2, ptr.use_count());
268 EXPECT_EQ(ptr.get(), ex->get());
269 ex = makeUnexpected(-1);
270 EXPECT_EQ(1, ptr.use_count());
273 EXPECT_EQ(1, ex->use_count());
274 EXPECT_EQ(nullptr, ptr.get());
276 EXPECT_EQ(1, ex->use_count());
277 Expected<shared_ptr<int>, int> copied(ex);
278 EXPECT_EQ(2, ex->use_count());
279 Expected<shared_ptr<int>, int> moved(std::move(ex));
280 EXPECT_EQ(2, moved->use_count());
281 moved.emplace(new int(6));
282 EXPECT_EQ(1, moved->use_count());
284 EXPECT_EQ(2, moved->use_count());
288 TEST(Expected, Order) {
289 std::vector<Expected<int, E>> vect{
290 {unexpected, E::E1}, {3}, {1}, {unexpected, E::E1}, {2},
292 std::vector<Expected<int, E>> expected{
293 {unexpected, E::E1}, {unexpected, E::E1}, {1}, {2}, {3},
295 std::sort(vect.begin(), vect.end());
296 EXPECT_EQ(vect, expected);
299 TEST(Expected, Swap) {
300 Expected<std::string, E> a;
301 Expected<std::string, E> b;
304 EXPECT_FALSE(a.hasValue());
305 EXPECT_FALSE(b.hasValue());
308 EXPECT_TRUE(a.hasValue());
309 EXPECT_FALSE(b.hasValue());
310 EXPECT_EQ("hello", a.value());
313 EXPECT_FALSE(a.hasValue());
314 EXPECT_TRUE(b.hasValue());
315 EXPECT_EQ("hello", b.value());
318 EXPECT_TRUE(a.hasValue());
319 EXPECT_EQ("bye", a.value());
324 TEST(Expected, Comparisons) {
326 Expected<int, E> o1(1);
327 Expected<int, E> o2(2);
329 EXPECT_TRUE(o_ <= (o_));
330 EXPECT_TRUE(o_ == (o_));
331 EXPECT_TRUE(o_ >= (o_));
333 EXPECT_TRUE(o1 < o2);
334 EXPECT_TRUE(o1 <= o2);
335 EXPECT_TRUE(o1 <= (o1));
336 EXPECT_TRUE(o1 == (o1));
337 EXPECT_TRUE(o1 != o2);
338 EXPECT_TRUE(o1 >= (o1));
339 EXPECT_TRUE(o2 >= o1);
340 EXPECT_TRUE(o2 > o1);
342 EXPECT_FALSE(o2 < o1);
343 EXPECT_FALSE(o2 <= o1);
344 EXPECT_FALSE(o2 <= o1);
345 EXPECT_FALSE(o2 == o1);
346 EXPECT_FALSE(o1 != (o1));
347 EXPECT_FALSE(o1 >= o2);
348 EXPECT_FALSE(o1 >= o2);
349 EXPECT_FALSE(o1 > o2);
351 /* folly::Expected explicitly doesn't support comparisons with contained value
353 EXPECT_TRUE(1 <= o2);
354 EXPECT_TRUE(1 <= o1);
355 EXPECT_TRUE(1 == o1);
356 EXPECT_TRUE(2 != o1);
357 EXPECT_TRUE(1 >= o1);
358 EXPECT_TRUE(2 >= o1);
361 EXPECT_FALSE(o2 < 1);
362 EXPECT_FALSE(o2 <= 1);
363 EXPECT_FALSE(o2 <= 1);
364 EXPECT_FALSE(o2 == 1);
365 EXPECT_FALSE(o2 != 2);
366 EXPECT_FALSE(o1 >= 2);
367 EXPECT_FALSE(o1 >= 2);
368 EXPECT_FALSE(o1 > 2);
372 TEST(Expected, Conversions) {
373 Expected<bool, E> mbool;
374 Expected<short, E> mshort;
375 Expected<char*, E> mstr;
376 Expected<int, E> mint;
378 EXPECT_FALSE((std::is_convertible<Expected<bool, E>&, bool>::value));
379 EXPECT_FALSE((std::is_convertible<Expected<short, E>&, short>::value));
380 EXPECT_FALSE((std::is_convertible<Expected<char*, E>&, char*>::value));
381 EXPECT_FALSE((std::is_convertible<Expected<int, E>&, int>::value));
383 // intended explicit operator bool, for if (ex).
387 // Truthy tests work and are not ambiguous
388 if (mbool && mshort && mstr && mint) { // only checks not-empty
389 if (*mbool && *mshort && *mstr && *mint) { // only checks value
395 EXPECT_TRUE(bool(mbool));
396 EXPECT_FALSE(*mbool);
399 EXPECT_TRUE(bool(mbool));
402 mbool = {unexpected, E::E1};
403 EXPECT_FALSE(bool(mbool));
405 // No conversion allowed; does not compile
409 TEST(Expected, Pointee) {
411 EXPECT_FALSE(get_pointer(x));
413 EXPECT_TRUE(get_pointer(x));
415 EXPECT_TRUE(*x == 2);
416 x = {unexpected, E::E1};
417 EXPECT_FALSE(get_pointer(x));
420 TEST(Expected, MakeOptional) {
421 // const L-value version
422 const std::string s("abc");
423 auto exStr = makeExpected<E>(s);
424 ASSERT_TRUE(exStr.hasValue());
425 EXPECT_EQ(*exStr, "abc");
428 EXPECT_EQ(*exStr, "cde");
431 std::string s2("abc");
432 auto exStr2 = makeExpected<E>(s2);
433 ASSERT_TRUE(exStr2.hasValue());
434 EXPECT_EQ(*exStr2, "abc");
436 // it's vital to check that s2 wasn't clobbered
437 EXPECT_EQ(s2, "abc");
439 // L-value reference version
441 auto exStr3 = makeExpected<E>(s3);
442 ASSERT_TRUE(exStr3.hasValue());
443 EXPECT_EQ(*exStr3, "abc");
445 EXPECT_EQ(s3, "abc");
447 // R-value ref version
448 unique_ptr<int> pInt(new int(3));
449 auto exIntPtr = makeExpected<E>(std::move(pInt));
450 EXPECT_TRUE(pInt.get() == nullptr);
451 ASSERT_TRUE(exIntPtr.hasValue());
452 EXPECT_EQ(**exIntPtr, 3);
456 #pragma clang diagnostic push
457 #pragma clang diagnostic ignored "-Wself-move"
460 TEST(Expected, SelfAssignment) {
461 Expected<std::string, E> a = "42";
463 ASSERT_TRUE(a.hasValue() && a.value() == "42");
465 Expected<std::string, E> b = "23333333";
467 ASSERT_TRUE(b.hasValue() && b.value() == "23333333");
471 #pragma clang diagnostic pop
474 class ContainsExpected {
476 ContainsExpected() {}
477 explicit ContainsExpected(int x) : ex_(x) {}
478 bool hasValue() const {
479 return ex_.hasValue();
485 ContainsExpected(const ContainsExpected& other) = default;
486 ContainsExpected& operator=(const ContainsExpected& other) = default;
487 ContainsExpected(ContainsExpected&& other) = default;
488 ContainsExpected& operator=(ContainsExpected&& other) = default;
491 Expected<int, E> ex_;
495 * Test that a class containing an Expected can be copy and move assigned.
496 * This was broken under gcc 4.7 until assignment operators were explicitly
499 TEST(Expected, AssignmentContained) {
501 ContainsExpected source(5), target;
503 EXPECT_TRUE(target.hasValue());
504 EXPECT_EQ(5, target.value());
508 ContainsExpected source(5), target;
509 target = std::move(source);
510 EXPECT_TRUE(target.hasValue());
511 EXPECT_EQ(5, target.value());
512 EXPECT_TRUE(source.hasValue());
516 ContainsExpected ex_uninit, target(10);
518 EXPECT_FALSE(target.hasValue());
522 TEST(Expected, Exceptions) {
523 Expected<int, E> empty;
524 EXPECT_THROW(empty.value(), Unexpected<E>::BadExpectedAccess);
527 struct ThrowingBadness {
528 ThrowingBadness() noexcept(false);
529 ThrowingBadness(const ThrowingBadness&) noexcept(false);
530 ThrowingBadness(ThrowingBadness&&) noexcept(false);
531 ThrowingBadness& operator=(const ThrowingBadness&) noexcept(false);
532 ThrowingBadness& operator=(ThrowingBadness&&) noexcept(false);
535 TEST(Expected, NoThrowDefaultConstructible) {
537 (std::is_nothrow_default_constructible<Expected<bool, E>>::value));
539 (std::is_nothrow_default_constructible<Expected<std::string, E>>::value));
540 EXPECT_TRUE((std::is_nothrow_default_constructible<
541 Expected<ThrowingBadness, E>>::value));
542 EXPECT_FALSE((std::is_nothrow_default_constructible<
543 Expected<int, ThrowingBadness>>::value));
546 TEST(Expected, NoThrowMoveConstructible) {
547 EXPECT_TRUE((std::is_nothrow_move_constructible<Expected<bool, E>>::value));
548 EXPECT_TRUE((std::is_nothrow_move_constructible<
549 Expected<std::unique_ptr<int>, E>>::value));
551 std::is_nothrow_move_constructible<Expected<ThrowingBadness, E>>::value));
554 TEST(Expected, NoThrowMoveAssignable) {
555 EXPECT_TRUE((std::is_nothrow_move_assignable<Expected<bool, E>>::value));
556 EXPECT_TRUE((std::is_nothrow_move_assignable<
557 Expected<std::unique_ptr<int>, E>>::value));
559 (std::is_nothrow_move_assignable<Expected<ThrowingBadness, E>>::value));
562 struct NoSelfAssign {
563 NoSelfAssign() = default;
564 NoSelfAssign(NoSelfAssign&&) = default;
565 NoSelfAssign(const NoSelfAssign&) = default;
566 NoSelfAssign& operator=(NoSelfAssign&& that) {
567 EXPECT_NE(this, &that);
570 NoSelfAssign& operator=(const NoSelfAssign& that) {
571 EXPECT_NE(this, &that);
577 #pragma GCC diagnostic push
578 #pragma GCC diagnostic ignored "-Wpragmas"
579 #pragma GCC diagnostic ignored "-Wself-move"
582 TEST(Expected, NoSelfAssign) {
583 folly::Expected<NoSelfAssign, int> e {NoSelfAssign{}};
585 e = std::move(e); // @nolint
589 #pragma GCC diagnostic pop
592 struct NoDestructor {};
594 struct WithDestructor {
598 TEST(Expected, TriviallyDestructible) {
599 // These could all be static_asserts but EXPECT_* give much nicer output on
602 (std::is_trivially_destructible<Expected<NoDestructor, E>>::value));
603 EXPECT_TRUE((std::is_trivially_destructible<Expected<int, E>>::value));
605 (std::is_trivially_destructible<Expected<WithDestructor, E>>::value));
608 struct NoConstructor {};
610 struct WithConstructor {
614 TEST(Expected, TriviallyCopyable) {
615 // These could all be static_asserts but EXPECT_* give much nicer output on
617 EXPECT_TRUE((IsTriviallyCopyable<Expected<int, E>>::value));
618 EXPECT_TRUE((IsTriviallyCopyable<Expected<char*, E>>::value));
620 (IsTriviallyCopyable<Expected<NoDestructor, E>>::value));
622 (IsTriviallyCopyable<Expected<WithDestructor, E>>::value));
624 (IsTriviallyCopyable<Expected<NoConstructor, E>>::value));
626 (IsTriviallyCopyable<Expected<std::string, E>>::value));
628 (IsTriviallyCopyable<Expected<int, std::string>>::value));
629 // libstdc++ with GCC 4.x doesn't have std::is_trivially_copyable
630 #if (defined(__clang__) && !defined(_LIBCPP_VERSION)) || \
631 !(defined(__GNUC__) && !defined(__clang__) && __GNUC__ < 5)
633 (IsTriviallyCopyable<Expected<WithConstructor, E>>::value));
636 (IsTriviallyCopyable<Expected<Expected<int, E>, E>>::value));
639 TEST(Expected, Then) {
642 Expected<int, E> ex = Expected<std::unique_ptr<int>, E>{
643 in_place, new int(42)}.then([](std::unique_ptr<int> p) { return *p; });
644 EXPECT_TRUE(bool(ex));
650 Expected<int, E> ex =
651 Expected<std::unique_ptr<int>, E>{in_place, new int(42)}.then(
652 [](std::unique_ptr<int> p) { return makeExpected<E>(*p); });
653 EXPECT_TRUE(bool(ex));
659 Expected<Unit, E> ex = Expected<std::unique_ptr<int>, E>{
660 in_place, new int(42)}.then([](std::unique_ptr<int>) {});
661 EXPECT_TRUE(bool(ex));
664 // Non-flattening (different error codes)
666 Expected<Expected<int, int>, E> ex =
667 Expected<std::unique_ptr<int>, E>{in_place, new int(42)}.then(
668 [](std::unique_ptr<int> p) { return makeExpected<int>(*p); });
669 EXPECT_TRUE(bool(ex));
670 EXPECT_TRUE(bool(*ex));
676 Expected<int, E> ex = Expected<std::unique_ptr<int>, E>{
677 unexpected, E::E1}.then([](std::unique_ptr<int> p) -> int {
681 EXPECT_FALSE(bool(ex));
682 EXPECT_EQ(E::E1, ex.error());
687 Expected<std::string, E> ex =
688 Expected<std::unique_ptr<int>, E>{in_place, new int(42)}.then(
689 [](std::unique_ptr<int> p) { return makeExpected<E>(*p); },
690 [](int i) { return i == 42 ? "yes" : "no"; });
691 EXPECT_TRUE(bool(ex));
692 EXPECT_EQ("yes", *ex);
695 // Chaining with errors
697 Expected<std::string, E> ex =
698 Expected<std::unique_ptr<int>, E>{in_place, new int(42)}.then(
699 [](std::unique_ptr<int>) {
700 return Expected<int, E>(unexpected, E::E1);
702 [](int i) { return i == 42 ? "yes" : "no"; });
703 EXPECT_FALSE(bool(ex));
704 EXPECT_EQ(E::E1, ex.error());
708 TEST(Expected, ThenOrThrow) {
711 Expected<std::unique_ptr<int>, E>{in_place, new int(42)}.thenOrThrow(
712 [](std::unique_ptr<int> p) { return *p; });
718 (Expected<std::unique_ptr<int>, E>{unexpected, E::E1}.thenOrThrow(
719 [](std::unique_ptr<int> p) { return *p; })),
720 Unexpected<E>::BadExpectedAccess);
725 (Expected<std::unique_ptr<int>, E>{unexpected, E::E1}.thenOrThrow(
726 [](std::unique_ptr<int> p) { return *p; },
727 [](E) { return std::runtime_error(""); })),
733 (Expected<std::unique_ptr<int>, E>{unexpected, E::E1}.thenOrThrow(
734 [](std::unique_ptr<int> p) { return *p; },
735 [](E) { throw std::runtime_error(""); })),
741 (Expected<std::unique_ptr<int>, E>{unexpected, E::E1}.thenOrThrow(
742 [](std::unique_ptr<int> p) { return *p; }, [](E) {})),
743 Unexpected<E>::BadExpectedAccess);