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/ManualExecutor.h>
21 #include <folly/wangle/InlineExecutor.h>
22 #include <folly/wangle/Later.h>
24 using namespace folly::wangle;
27 explicit ManualWaiter(std::shared_ptr<ManualExecutor> ex) : ex(ex) {}
34 std::shared_ptr<ManualExecutor> ex;
37 struct LaterFixture : public testing::Test {
39 westExecutor(new ManualExecutor),
40 eastExecutor(new ManualExecutor),
41 waiter(new ManualWaiter(westExecutor)),
45 ManualWaiter eastWaiter(eastExecutor);
47 eastWaiter.makeProgress();
53 eastExecutor->add([=]() { });
57 void addAsync(int a, int b, std::function<void(int&&)>&& cob) {
58 eastExecutor->add([=]() {
64 std::shared_ptr<ManualExecutor> westExecutor;
65 std::shared_ptr<ManualExecutor> eastExecutor;
66 std::shared_ptr<ManualWaiter> waiter;
67 InlineExecutor inlineExecutor;
72 TEST(Later, construct_and_launch) {
73 bool fulfilled = false;
74 auto later = Later<void>().then([&](Try<void>&& t) {
76 return makeFuture<int>(1);
79 // has not started yet.
80 EXPECT_FALSE(fulfilled);
82 EXPECT_EQ(later.launch().value(), 1);
83 EXPECT_TRUE(fulfilled);
86 TEST(Later, then_value) {
87 auto future = Later<int>(std::move(1))
88 .then([](Try<int>&& t) {
89 return t.value() == 1;
93 EXPECT_TRUE(future.value());
96 TEST(Later, then_future) {
97 auto future = Later<int>(1)
98 .then([](Try<int>&& t) {
99 return makeFuture(t.value() == 1);
102 EXPECT_TRUE(future.value());
105 TEST_F(LaterFixture, thread_hops) {
106 auto westThreadId = std::this_thread::get_id();
107 auto future = later.via(eastExecutor.get()).then([=](Try<void>&& t) {
108 EXPECT_NE(std::this_thread::get_id(), westThreadId);
109 return makeFuture<int>(1);
110 }).via(westExecutor.get()
111 ).then([=](Try<int>&& t) {
112 EXPECT_EQ(std::this_thread::get_id(), westThreadId);
115 while (!future.isReady()) {
116 waiter->makeProgress();
118 EXPECT_EQ(future.value(), 1);
121 TEST_F(LaterFixture, wrapping_preexisting_async_modules) {
122 auto westThreadId = std::this_thread::get_id();
123 std::function<void(std::function<void(int&&)>&&)> wrapper =
124 [=](std::function<void(int&&)>&& fn) {
125 addAsync(2, 2, std::move(fn));
127 auto future = Later<int>(std::move(wrapper))
128 .via(westExecutor.get())
129 .then([=](Try<int>&& t) {
130 EXPECT_EQ(std::this_thread::get_id(), westThreadId);
134 while (!future.isReady()) {
135 waiter->makeProgress();
137 EXPECT_EQ(future.value(), 4);
140 TEST_F(LaterFixture, chain_laters) {
141 auto westThreadId = std::this_thread::get_id();
142 auto future = later.via(eastExecutor.get()).then([=](Try<void>&& t) {
143 EXPECT_NE(std::this_thread::get_id(), westThreadId);
144 return makeFuture<int>(1);
145 }).then([=](Try<int>&& t) {
147 return Later<int>(std::move(val)).via(westExecutor.get())
148 .then([=](Try<int>&& t) mutable {
149 EXPECT_EQ(std::this_thread::get_id(), westThreadId);
152 }).then([=](Try<int>&& t) {
153 EXPECT_EQ(std::this_thread::get_id(), westThreadId);
157 while (!future.isReady()) {
158 waiter->makeProgress();
160 EXPECT_EQ(future.value(), 1);