2 * Copyright 2014 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 <gtest/gtest.h>
20 #include <folly/wangle/Future.h>
21 #include <folly/wangle/InlineExecutor.h>
22 #include <folly/wangle/ManualExecutor.h>
24 using namespace folly::wangle;
27 explicit ManualWaiter(std::shared_ptr<ManualExecutor> ex) : ex(ex) {}
34 std::shared_ptr<ManualExecutor> ex;
37 struct ViaFixture : public testing::Test {
39 future_(makeFuture().deactivate()),
40 westExecutor(new ManualExecutor),
41 eastExecutor(new ManualExecutor),
42 waiter(new ManualWaiter(westExecutor)),
46 ManualWaiter eastWaiter(eastExecutor);
48 eastWaiter.makeProgress();
54 eastExecutor->add([=]() { });
58 void addAsync(int a, int b, std::function<void(int&&)>&& cob) {
59 eastExecutor->add([=]() {
65 std::shared_ptr<ManualExecutor> westExecutor;
66 std::shared_ptr<ManualExecutor> eastExecutor;
67 std::shared_ptr<ManualWaiter> waiter;
68 InlineExecutor inlineExecutor;
73 TEST(Via, exception_on_launch) {
74 auto future = makeFuture<int>(std::runtime_error("E"));
75 EXPECT_THROW(future.value(), std::runtime_error);
78 TEST(Via, then_value) {
79 auto future = makeFuture(std::move(1))
80 .then([](Try<int>&& t) {
81 return t.value() == 1;
85 EXPECT_TRUE(future.value());
88 TEST(Via, then_future) {
89 auto future = makeFuture(1)
90 .then([](Try<int>&& t) {
91 return makeFuture(t.value() == 1);
94 EXPECT_TRUE(future.value());
97 static Future<std::string> doWorkStatic(Try<std::string>&& t) {
98 return makeFuture(t.value() + ";static");
101 TEST(Via, then_function) {
103 Future<std::string> doWork(Try<std::string>&& t) {
104 return makeFuture(t.value() + ";class");
106 static Future<std::string> doWorkStatic(Try<std::string>&& t) {
107 return makeFuture(t.value() + ";class-static");
111 auto f = makeFuture(std::string("start"))
113 .then(Worker::doWorkStatic)
114 .then(&w, &Worker::doWork)
117 EXPECT_EQ(f.value(), "start;static;class-static;class");
120 TEST_F(ViaFixture, thread_hops) {
121 auto westThreadId = std::this_thread::get_id();
122 auto f = future_.via(eastExecutor.get()).then([=](Try<void>&& t) {
123 EXPECT_NE(std::this_thread::get_id(), westThreadId);
124 return makeFuture<int>(1);
125 }).via(westExecutor.get()
126 ).then([=](Try<int>&& t) {
127 EXPECT_EQ(std::this_thread::get_id(), westThreadId);
130 while (!f.isReady()) {
131 waiter->makeProgress();
133 EXPECT_EQ(f.value(), 1);
136 TEST_F(ViaFixture, chain_vias) {
137 auto westThreadId = std::this_thread::get_id();
138 auto f = future_.via(eastExecutor.get()).then([=](Try<void>&& t) {
139 EXPECT_NE(std::this_thread::get_id(), westThreadId);
140 return makeFuture<int>(1);
141 }).then([=](Try<int>&& t) {
143 return makeFuture(std::move(val)).via(westExecutor.get())
144 .then([=](Try<int>&& t) mutable {
145 EXPECT_EQ(std::this_thread::get_id(), westThreadId);
148 }).then([=](Try<int>&& t) {
149 EXPECT_EQ(std::this_thread::get_id(), westThreadId);
153 while (!f.isReady()) {
154 waiter->makeProgress();
156 EXPECT_EQ(f.value(), 1);