(Wangle) Clean up tests
[folly.git] / folly / futures / test / CollectTest.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 <gtest/gtest.h>
18
19 #include <folly/futures/Future.h>
20 #include <folly/Random.h>
21 #include <folly/small_vector.h>
22
23 using namespace folly;
24
25 typedef FutureException eggs_t;
26 static eggs_t eggs("eggs");
27
28 auto rng = std::mt19937(folly::randomNumberSeed());
29
30 TEST(Collect, collectAll) {
31   // returns a vector variant
32   {
33     std::vector<Promise<int>> promises(10);
34     std::vector<Future<int>> futures;
35
36     for (auto& p : promises)
37       futures.push_back(p.getFuture());
38
39     auto allf = collectAll(futures);
40
41     std::shuffle(promises.begin(), promises.end(), rng);
42     for (auto& p : promises) {
43       EXPECT_FALSE(allf.isReady());
44       p.setValue(42);
45     }
46
47     EXPECT_TRUE(allf.isReady());
48     auto& results = allf.value();
49     for (auto& t : results) {
50       EXPECT_EQ(42, t.value());
51     }
52   }
53
54   // check error semantics
55   {
56     std::vector<Promise<int>> promises(4);
57     std::vector<Future<int>> futures;
58
59     for (auto& p : promises)
60       futures.push_back(p.getFuture());
61
62     auto allf = collectAll(futures);
63
64
65     promises[0].setValue(42);
66     promises[1].setException(eggs);
67
68     EXPECT_FALSE(allf.isReady());
69
70     promises[2].setValue(42);
71
72     EXPECT_FALSE(allf.isReady());
73
74     promises[3].setException(eggs);
75
76     EXPECT_TRUE(allf.isReady());
77     EXPECT_FALSE(allf.getTry().hasException());
78
79     auto& results = allf.value();
80     EXPECT_EQ(42, results[0].value());
81     EXPECT_TRUE(results[1].hasException());
82     EXPECT_EQ(42, results[2].value());
83     EXPECT_TRUE(results[3].hasException());
84   }
85
86   // check that futures are ready in then()
87   {
88     std::vector<Promise<void>> promises(10);
89     std::vector<Future<void>> futures;
90
91     for (auto& p : promises)
92       futures.push_back(p.getFuture());
93
94     auto allf = collectAll(futures)
95       .then([](Try<std::vector<Try<void>>>&& ts) {
96         for (auto& f : ts.value())
97           f.value();
98       });
99
100     std::shuffle(promises.begin(), promises.end(), rng);
101     for (auto& p : promises)
102       p.setValue();
103     EXPECT_TRUE(allf.isReady());
104   }
105 }
106
107 TEST(Collect, collect) {
108   // success case
109   {
110     std::vector<Promise<int>> promises(10);
111     std::vector<Future<int>> futures;
112
113     for (auto& p : promises)
114       futures.push_back(p.getFuture());
115
116     auto allf = collect(futures);
117
118     std::shuffle(promises.begin(), promises.end(), rng);
119     for (auto& p : promises) {
120       EXPECT_FALSE(allf.isReady());
121       p.setValue(42);
122     }
123
124     EXPECT_TRUE(allf.isReady());
125     for (auto i : allf.value()) {
126       EXPECT_EQ(42, i);
127     }
128   }
129
130   // failure case
131   {
132     std::vector<Promise<int>> promises(10);
133     std::vector<Future<int>> futures;
134
135     for (auto& p : promises)
136       futures.push_back(p.getFuture());
137
138     auto allf = collect(futures);
139
140     std::shuffle(promises.begin(), promises.end(), rng);
141     for (int i = 0; i < 10; i++) {
142       if (i < 5) {
143         // everthing goes well so far...
144         EXPECT_FALSE(allf.isReady());
145         promises[i].setValue(42);
146       } else if (i == 5) {
147         // short circuit with an exception
148         EXPECT_FALSE(allf.isReady());
149         promises[i].setException(eggs);
150         EXPECT_TRUE(allf.isReady());
151       } else if (i < 8) {
152         // don't blow up on further values
153         EXPECT_TRUE(allf.isReady());
154         promises[i].setValue(42);
155       } else {
156         // don't blow up on further exceptions
157         EXPECT_TRUE(allf.isReady());
158         promises[i].setException(eggs);
159       }
160     }
161
162     EXPECT_THROW(allf.value(), eggs_t);
163   }
164
165   // void futures success case
166   {
167     std::vector<Promise<void>> promises(10);
168     std::vector<Future<void>> futures;
169
170     for (auto& p : promises)
171       futures.push_back(p.getFuture());
172
173     auto allf = collect(futures);
174
175     std::shuffle(promises.begin(), promises.end(), rng);
176     for (auto& p : promises) {
177       EXPECT_FALSE(allf.isReady());
178       p.setValue();
179     }
180
181     EXPECT_TRUE(allf.isReady());
182   }
183
184   // void futures failure case
185   {
186     std::vector<Promise<void>> promises(10);
187     std::vector<Future<void>> futures;
188
189     for (auto& p : promises)
190       futures.push_back(p.getFuture());
191
192     auto allf = collect(futures);
193
194     std::shuffle(promises.begin(), promises.end(), rng);
195     for (int i = 0; i < 10; i++) {
196       if (i < 5) {
197         // everthing goes well so far...
198         EXPECT_FALSE(allf.isReady());
199         promises[i].setValue();
200       } else if (i == 5) {
201         // short circuit with an exception
202         EXPECT_FALSE(allf.isReady());
203         promises[i].setException(eggs);
204         EXPECT_TRUE(allf.isReady());
205       } else if (i < 8) {
206         // don't blow up on further values
207         EXPECT_TRUE(allf.isReady());
208         promises[i].setValue();
209       } else {
210         // don't blow up on further exceptions
211         EXPECT_TRUE(allf.isReady());
212         promises[i].setException(eggs);
213       }
214     }
215
216     EXPECT_THROW(allf.value(), eggs_t);
217   }
218
219   // move only compiles
220   {
221     std::vector<Promise<std::unique_ptr<int>>> promises(10);
222     std::vector<Future<std::unique_ptr<int>>> futures;
223
224     for (auto& p : promises)
225       futures.push_back(p.getFuture());
226
227     collect(futures);
228   }
229
230 }
231
232 struct NotDefaultConstructible {
233   NotDefaultConstructible() = delete;
234   explicit NotDefaultConstructible(int arg) : i(arg) {}
235   int i;
236 };
237
238 // We have a specialized implementation for non-default-constructible objects
239 // Ensure that it works and preserves order
240 TEST(Collect, collectNotDefaultConstructible) {
241   std::vector<Promise<NotDefaultConstructible>> promises(10);
242   std::vector<Future<NotDefaultConstructible>> futures;
243   std::vector<int> indices(10);
244   std::iota(indices.begin(), indices.end(), 0);
245   std::shuffle(indices.begin(), indices.end(), rng);
246
247   for (auto& p : promises)
248     futures.push_back(p.getFuture());
249
250   auto allf = collect(futures);
251
252   for (auto i : indices) {
253     EXPECT_FALSE(allf.isReady());
254     promises[i].setValue(NotDefaultConstructible(i));
255   }
256
257   EXPECT_TRUE(allf.isReady());
258   int i = 0;
259   for (auto val : allf.value()) {
260     EXPECT_EQ(i, val.i);
261     i++;
262   }
263 }
264
265 TEST(Collect, collectAny) {
266   {
267     std::vector<Promise<int>> promises(10);
268     std::vector<Future<int>> futures;
269
270     for (auto& p : promises)
271       futures.push_back(p.getFuture());
272
273     for (auto& f : futures) {
274       EXPECT_FALSE(f.isReady());
275     }
276
277     auto anyf = collectAny(futures);
278
279     /* futures were moved in, so these are invalid now */
280     EXPECT_FALSE(anyf.isReady());
281
282     promises[7].setValue(42);
283     EXPECT_TRUE(anyf.isReady());
284     auto& idx_fut = anyf.value();
285
286     auto i = idx_fut.first;
287     EXPECT_EQ(7, i);
288
289     auto& f = idx_fut.second;
290     EXPECT_EQ(42, f.value());
291   }
292
293   // error
294   {
295     std::vector<Promise<void>> promises(10);
296     std::vector<Future<void>> futures;
297
298     for (auto& p : promises)
299       futures.push_back(p.getFuture());
300
301     for (auto& f : futures) {
302       EXPECT_FALSE(f.isReady());
303     }
304
305     auto anyf = collectAny(futures);
306
307     EXPECT_FALSE(anyf.isReady());
308
309     promises[3].setException(eggs);
310     EXPECT_TRUE(anyf.isReady());
311     EXPECT_TRUE(anyf.value().second.hasException());
312   }
313
314   // then()
315   {
316     std::vector<Promise<int>> promises(10);
317     std::vector<Future<int>> futures;
318
319     for (auto& p : promises)
320       futures.push_back(p.getFuture());
321
322     auto anyf = collectAny(futures)
323       .then([](std::pair<size_t, Try<int>> p) {
324         EXPECT_EQ(42, p.second.value());
325       });
326
327     promises[3].setValue(42);
328     EXPECT_TRUE(anyf.isReady());
329   }
330 }
331
332
333 TEST(Collect, alreadyCompleted) {
334   {
335     std::vector<Future<void>> fs;
336     for (int i = 0; i < 10; i++)
337       fs.push_back(makeFuture());
338
339     collectAll(fs)
340       .then([&](std::vector<Try<void>> ts) {
341         EXPECT_EQ(fs.size(), ts.size());
342       });
343   }
344   {
345     std::vector<Future<int>> fs;
346     for (int i = 0; i < 10; i++)
347       fs.push_back(makeFuture(i));
348
349     collectAny(fs)
350       .then([&](std::pair<size_t, Try<int>> p) {
351         EXPECT_EQ(p.first, p.second.value());
352       });
353   }
354 }
355
356 TEST(Collect, collectN) {
357   std::vector<Promise<void>> promises(10);
358   std::vector<Future<void>> futures;
359
360   for (auto& p : promises)
361     futures.push_back(p.getFuture());
362
363   bool flag = false;
364   size_t n = 3;
365   collectN(futures, n)
366     .then([&](std::vector<std::pair<size_t, Try<void>>> v) {
367       flag = true;
368       EXPECT_EQ(n, v.size());
369       for (auto& tt : v)
370         EXPECT_TRUE(tt.second.hasValue());
371     });
372
373   promises[0].setValue();
374   EXPECT_FALSE(flag);
375   promises[1].setValue();
376   EXPECT_FALSE(flag);
377   promises[2].setValue();
378   EXPECT_TRUE(flag);
379 }
380
381 /// Ensure that we can compile collectAll/Any with folly::small_vector
382 TEST(Collect, smallVector) {
383   static_assert(!FOLLY_IS_TRIVIALLY_COPYABLE(Future<void>),
384                 "Futures should not be trivially copyable");
385   static_assert(!FOLLY_IS_TRIVIALLY_COPYABLE(Future<int>),
386                 "Futures should not be trivially copyable");
387
388   {
389     folly::small_vector<Future<void>> futures;
390
391     for (int i = 0; i < 10; i++)
392       futures.push_back(makeFuture());
393
394     auto anyf = collectAny(futures);
395   }
396   {
397     folly::small_vector<Future<void>> futures;
398
399     for (int i = 0; i < 10; i++)
400       futures.push_back(makeFuture());
401
402     auto allf = collectAll(futures);
403   }
404 }
405
406 TEST(Collect, collectAllVariadic) {
407   Promise<bool> pb;
408   Promise<int> pi;
409   Future<bool> fb = pb.getFuture();
410   Future<int> fi = pi.getFuture();
411   bool flag = false;
412   collectAll(std::move(fb), std::move(fi))
413     .then([&](std::tuple<Try<bool>, Try<int>> tup) {
414       flag = true;
415       EXPECT_TRUE(std::get<0>(tup).hasValue());
416       EXPECT_EQ(std::get<0>(tup).value(), true);
417       EXPECT_TRUE(std::get<1>(tup).hasValue());
418       EXPECT_EQ(std::get<1>(tup).value(), 42);
419     });
420   pb.setValue(true);
421   EXPECT_FALSE(flag);
422   pi.setValue(42);
423   EXPECT_TRUE(flag);
424 }
425
426 TEST(Collect, collectAllVariadicReferences) {
427   Promise<bool> pb;
428   Promise<int> pi;
429   Future<bool> fb = pb.getFuture();
430   Future<int> fi = pi.getFuture();
431   bool flag = false;
432   collectAll(fb, fi)
433     .then([&](std::tuple<Try<bool>, Try<int>> tup) {
434       flag = true;
435       EXPECT_TRUE(std::get<0>(tup).hasValue());
436       EXPECT_EQ(std::get<0>(tup).value(), true);
437       EXPECT_TRUE(std::get<1>(tup).hasValue());
438       EXPECT_EQ(std::get<1>(tup).value(), 42);
439     });
440   pb.setValue(true);
441   EXPECT_FALSE(flag);
442   pi.setValue(42);
443   EXPECT_TRUE(flag);
444 }
445
446 TEST(Collect, collectAllNone) {
447   std::vector<Future<int>> fs;
448   auto f = collectAll(fs);
449   EXPECT_TRUE(f.isReady());
450 }