| /* |
| * Copyright 2015 Facebook, Inc. |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| #include <gtest/gtest.h> |
| |
| #include <folly/futures/Future.h> |
| |
| #include <thread> |
| |
| using namespace folly; |
| |
| struct Widget { |
| int v_, copied_, moved_; |
| /* implicit */ Widget(int v) : v_(v), copied_(0), moved_(0) {} |
| Widget(const Widget& other) |
| : v_(other.v_), copied_(other.copied_ + 1), moved_(other.moved_) {} |
| Widget(Widget&& other) noexcept |
| : v_(other.v_), copied_(other.copied_), moved_(other.moved_ + 1) {} |
| Widget& operator=(const Widget& other) |
| { throw std::logic_error("unexpected copy assignment"); } |
| Widget& operator=(Widget&& other) |
| { throw std::logic_error("unexpected move assignment"); } |
| }; |
| |
| TEST(Then, tryConstructor) { |
| auto t = Try<Widget>(23); |
| EXPECT_EQ(t.value().v_, 23); |
| EXPECT_EQ(t.value().copied_, 0); |
| EXPECT_EQ(t.value().moved_, 1); |
| } |
| |
| TEST(Then, makeFuture) { |
| auto future = makeFuture<Widget>(23); |
| EXPECT_EQ(future.value().v_, 23); |
| EXPECT_EQ(future.value().copied_, 0); |
| EXPECT_EQ(future.value().moved_, 2); |
| } |
| |
| TEST(Then, tryConstRValueReference) { |
| auto future = makeFuture<Widget>(23).then( |
| [](const Try<Widget>&& t) { |
| EXPECT_EQ(t.value().copied_, 0); |
| EXPECT_EQ(t.value().moved_, 2); |
| return t.value().v_; |
| }); |
| EXPECT_EQ(future.value(), 23); |
| } |
| |
| TEST(Then, tryRValueReference) { |
| auto future = makeFuture<Widget>(23).then( |
| [](Try<Widget>&& t) { |
| EXPECT_EQ(t.value().copied_, 0); |
| EXPECT_EQ(t.value().moved_, 2); |
| return t.value().v_; |
| }); |
| EXPECT_EQ(future.value(), 23); |
| } |
| |
| TEST(Then, tryLValueReference) { |
| auto future = makeFuture<Widget>(23).then( |
| [](Try<Widget>& t) { |
| EXPECT_EQ(t.value().copied_, 0); |
| EXPECT_EQ(t.value().moved_, 2); |
| return t.value().v_; |
| }); |
| EXPECT_EQ(future.value(), 23); |
| } |
| |
| TEST(Then, tryConstLValueReference) { |
| auto future = makeFuture<Widget>(23).then( |
| [](const Try<Widget>& t) { |
| EXPECT_EQ(t.value().copied_, 0); |
| EXPECT_EQ(t.value().moved_, 2); |
| return t.value().v_; |
| }); |
| EXPECT_EQ(future.value(), 23); |
| } |
| |
| TEST(Then, tryValue) { |
| auto future = makeFuture<Widget>(23).then( |
| [](Try<Widget> t) { |
| EXPECT_EQ(t.value().copied_, 0); |
| EXPECT_EQ(t.value().moved_, 3); |
| return t.value().v_; |
| }); |
| EXPECT_EQ(future.value(), 23); |
| } |
| |
| TEST(Then, tryConstValue) { |
| auto future = makeFuture<Widget>(23).then( |
| [](const Try<Widget> t) { |
| EXPECT_EQ(t.value().copied_, 0); |
| EXPECT_EQ(t.value().moved_, 3); |
| return t.value().v_; |
| }); |
| EXPECT_EQ(future.value(), 23); |
| } |
| |
| TEST(Then, constRValueReference) { |
| auto future = makeFuture<Widget>(23).then( |
| [](const Widget&& w) { |
| EXPECT_EQ(w.copied_, 0); |
| EXPECT_EQ(w.moved_, 2); |
| return w.v_; |
| }); |
| EXPECT_EQ(future.value(), 23); |
| } |
| |
| TEST(Then, rValueReference) { |
| auto future = makeFuture<Widget>(23).then( |
| [](Widget&& w) { |
| EXPECT_EQ(w.copied_, 0); |
| EXPECT_EQ(w.moved_, 2); |
| return w.v_; |
| }); |
| EXPECT_EQ(future.value(), 23); |
| } |
| |
| TEST(Then, lValueReference) { |
| auto future = makeFuture<Widget>(23).then( |
| [](Widget& w) { |
| EXPECT_EQ(w.copied_, 0); |
| EXPECT_EQ(w.moved_, 2); |
| return w.v_; |
| }); |
| EXPECT_EQ(future.value(), 23); |
| } |
| |
| TEST(Then, constLValueReference) { |
| auto future = makeFuture<Widget>(23).then( |
| [](const Widget& w) { |
| EXPECT_EQ(w.copied_, 0); |
| EXPECT_EQ(w.moved_, 2); |
| return w.v_; |
| }); |
| EXPECT_EQ(future.value(), 23); |
| } |
| |
| TEST(Then, value) { |
| auto future = makeFuture<Widget>(23).then( |
| [](Widget w) { |
| EXPECT_EQ(w.copied_, 0); |
| EXPECT_EQ(w.moved_, 3); |
| return w.v_; |
| }); |
| EXPECT_EQ(future.value(), 23); |
| } |
| |
| TEST(Then, constValue) { |
| auto future = makeFuture<Widget>(23).then( |
| [](const Widget w) { |
| EXPECT_EQ(w.copied_, 0); |
| EXPECT_EQ(w.moved_, 3); |
| return w.v_; |
| }); |
| EXPECT_EQ(future.value(), 23); |
| } |
| |
| TEST(Then, voidThenShouldPropagateExceptions) { |
| EXPECT_FALSE(makeFuture(42).then().hasException()); |
| EXPECT_TRUE(makeFuture<int>(std::runtime_error("err")) |
| .then().hasException()); |
| } |