Loosen restriction to get folly::future::CoreTest pass on android
[folly.git] / folly / futures / test / WaitTest.cpp
1 /*
2  * Copyright 2015 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 <queue>
18
19 #include <gtest/gtest.h>
20
21 #include <folly/futures/Future.h>
22 #include <folly/io/async/EventBase.h>
23 #include <folly/Baton.h>
24
25 using namespace folly;
26 using std::vector;
27 using std::chrono::milliseconds;
28
29 TEST(Wait, waitImmediate) {
30   makeFuture().wait();
31   auto done = makeFuture(42).wait().value();
32   EXPECT_EQ(42, done);
33
34   vector<int> v{1,2,3};
35   auto done_v = makeFuture(v).wait().value();
36   EXPECT_EQ(v.size(), done_v.size());
37   EXPECT_EQ(v, done_v);
38
39   vector<Future<Unit>> v_f;
40   v_f.push_back(makeFuture());
41   v_f.push_back(makeFuture());
42   auto done_v_f = collectAll(v_f).wait().value();
43   EXPECT_EQ(2, done_v_f.size());
44
45   vector<Future<bool>> v_fb;
46   v_fb.push_back(makeFuture(true));
47   v_fb.push_back(makeFuture(false));
48   auto fut = collectAll(v_fb);
49   auto done_v_fb = std::move(fut.wait().value());
50   EXPECT_EQ(2, done_v_fb.size());
51 }
52
53 TEST(Wait, wait) {
54   Promise<int> p;
55   Future<int> f = p.getFuture();
56   std::atomic<bool> flag{false};
57   std::atomic<int> result{1};
58   std::atomic<std::thread::id> id;
59
60   std::thread t([&](Future<int>&& tf){
61       auto n = tf.then([&](Try<int> && t) {
62           id = std::this_thread::get_id();
63           return t.value();
64         });
65       flag = true;
66       result.store(n.wait().value());
67     },
68     std::move(f)
69     );
70   while(!flag){}
71   EXPECT_EQ(result.load(), 1);
72   p.setValue(42);
73   t.join();
74   // validate that the callback ended up executing in this thread, which
75   // is more to ensure that this test actually tests what it should
76   EXPECT_EQ(id, std::this_thread::get_id());
77   EXPECT_EQ(result.load(), 42);
78 }
79
80 struct MoveFlag {
81   MoveFlag() = default;
82   MoveFlag& operator=(const MoveFlag&) = delete;
83   MoveFlag(const MoveFlag&) = delete;
84   MoveFlag(MoveFlag&& other) noexcept {
85     other.moved = true;
86   }
87   bool moved{false};
88 };
89
90 TEST(Wait, waitReplacesSelf) {
91   // wait
92   {
93     // lvalue
94     auto f1 = makeFuture(MoveFlag());
95     f1.wait();
96     EXPECT_FALSE(f1.value().moved);
97
98     // rvalue
99     auto f2 = makeFuture(MoveFlag()).wait();
100     EXPECT_FALSE(f2.value().moved);
101   }
102
103   // wait(Duration)
104   {
105     // lvalue
106     auto f1 = makeFuture(MoveFlag());
107     f1.wait(milliseconds(1));
108     EXPECT_FALSE(f1.value().moved);
109
110     // rvalue
111     auto f2 = makeFuture(MoveFlag()).wait(milliseconds(1));
112     EXPECT_FALSE(f2.value().moved);
113   }
114
115   // waitVia
116   {
117     folly::EventBase eb;
118     // lvalue
119     auto f1 = makeFuture(MoveFlag());
120     f1.waitVia(&eb);
121     EXPECT_FALSE(f1.value().moved);
122
123     // rvalue
124     auto f2 = makeFuture(MoveFlag()).waitVia(&eb);
125     EXPECT_FALSE(f2.value().moved);
126   }
127 }
128
129 TEST(Wait, waitWithDuration) {
130  {
131   Promise<int> p;
132   Future<int> f = p.getFuture();
133   f.wait(milliseconds(1));
134   EXPECT_FALSE(f.isReady());
135   p.setValue(1);
136   EXPECT_TRUE(f.isReady());
137  }
138  {
139   Promise<int> p;
140   Future<int> f = p.getFuture();
141   p.setValue(1);
142   f.wait(milliseconds(1));
143   EXPECT_TRUE(f.isReady());
144  }
145  {
146   vector<Future<bool>> v_fb;
147   v_fb.push_back(makeFuture(true));
148   v_fb.push_back(makeFuture(false));
149   auto f = collectAll(v_fb);
150   f.wait(milliseconds(1));
151   EXPECT_TRUE(f.isReady());
152   EXPECT_EQ(2, f.value().size());
153  }
154  {
155   vector<Future<bool>> v_fb;
156   Promise<bool> p1;
157   Promise<bool> p2;
158   v_fb.push_back(p1.getFuture());
159   v_fb.push_back(p2.getFuture());
160   auto f = collectAll(v_fb);
161   f.wait(milliseconds(1));
162   EXPECT_FALSE(f.isReady());
163   p1.setValue(true);
164   EXPECT_FALSE(f.isReady());
165   p2.setValue(true);
166   EXPECT_TRUE(f.isReady());
167  }
168  {
169   auto f = makeFuture().wait(milliseconds(1));
170   EXPECT_TRUE(f.isReady());
171  }
172
173  {
174    Promise<Unit> p;
175    auto start = std::chrono::steady_clock::now();
176    auto f = p.getFuture().wait(milliseconds(100));
177    auto elapsed = std::chrono::steady_clock::now() - start;
178    EXPECT_GE(elapsed, milliseconds(100));
179    EXPECT_FALSE(f.isReady());
180    p.setValue();
181    EXPECT_TRUE(f.isReady());
182  }
183
184  {
185    // Try to trigger the race where the resultant Future is not yet complete
186    // even if we didn't hit the timeout, and make sure we deal with it properly
187    Promise<Unit> p;
188    folly::Baton<> b;
189    auto t = std::thread([&]{
190      b.post();
191      /* sleep override */ std::this_thread::sleep_for(milliseconds(100));
192      p.setValue();
193    });
194    b.wait();
195    auto f = p.getFuture().wait(std::chrono::seconds(3600));
196    EXPECT_TRUE(f.isReady());
197    t.join();
198  }
199 }
200
201 TEST(Wait, multipleWait) {
202   auto f = futures::sleep(milliseconds(100));
203   for (size_t i = 0; i < 5; ++i) {
204     EXPECT_FALSE(f.isReady());
205     f.wait(milliseconds(3));
206   }
207   EXPECT_FALSE(f.isReady());
208   f.wait();
209   EXPECT_TRUE(f.isReady());
210   f.wait();
211   EXPECT_TRUE(f.isReady());
212 }