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