Added futures helpers times, when, and whileDo
[folly.git] / folly / futures / test / TimesTest.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 <memory>
18 #include <mutex>
19
20 #include <gtest/gtest.h>
21 #include <glog/logging.h>
22
23 #include <folly/futures/Future.h>
24 #include <folly/futures/Promise.h>
25
26 using namespace folly;
27
28 inline void popAndFulfillPromise(
29     std::queue<std::shared_ptr<Promise<Unit>>>& ps,
30     std::mutex& ps_mutex) {
31   ps_mutex.lock();
32   auto p = ps.front();
33   ps.pop();
34   ps_mutex.unlock();
35   p->setValue();
36 }
37
38 inline std::function<Future<Unit>(void)> makeThunk(
39     std::queue<std::shared_ptr<Promise<Unit>>>& ps,
40     int& interrupt,
41     std::mutex& ps_mutex) {
42   return [&]() mutable {
43     auto p = std::make_shared<Promise<Unit>>();
44     p->setInterruptHandler([&](exception_wrapper const& e) {
45       ++interrupt;
46     });
47     ps_mutex.lock();
48     ps.push(p);
49     ps_mutex.unlock();
50
51     return p->getFuture();
52   };
53 }
54
55 inline std::function<bool(void)> makePred(int& i) {
56   return [&]() {
57     bool res = i < 3;
58     ++i;
59     return res;
60   };
61 }
62
63 TEST(Times, success) {
64   std::queue<std::shared_ptr<Promise<Unit>>> ps;
65   std::mutex ps_mutex;
66   int interrupt = 0;
67   bool complete = false;
68   bool failure = false;
69
70   auto thunk = makeThunk(ps, interrupt, ps_mutex);
71   auto f = folly::times(3, thunk)
72     .then([&]() mutable { complete = true; })
73     .onError([&] (FutureException& e) { failure = true; });
74
75   popAndFulfillPromise(ps, ps_mutex);
76   EXPECT_FALSE(complete);
77   EXPECT_FALSE(failure);
78
79   popAndFulfillPromise(ps, ps_mutex);
80   EXPECT_FALSE(complete);
81   EXPECT_FALSE(failure);
82
83   popAndFulfillPromise(ps, ps_mutex);
84   EXPECT_TRUE(f.isReady());
85   EXPECT_TRUE(complete);
86   EXPECT_FALSE(failure);
87 }
88
89 TEST(Times, failure) {
90   std::queue<std::shared_ptr<Promise<Unit>>> ps;
91   std::mutex ps_mutex;
92   int interrupt = 0;
93   bool complete = false;
94   bool failure = false;
95
96   auto thunk = makeThunk(ps, interrupt, ps_mutex);
97   auto f = folly::times(3, thunk)
98     .then([&]() mutable { complete = true; })
99     .onError([&] (FutureException& e) { failure = true; });
100
101   popAndFulfillPromise(ps, ps_mutex);
102   EXPECT_FALSE(complete);
103   EXPECT_FALSE(failure);
104
105   ps_mutex.lock();
106   auto p2 = ps.front();
107   ps.pop();
108   ps_mutex.unlock();
109   FutureException eggs("eggs");
110   p2->setException(eggs);
111
112   EXPECT_TRUE(f.isReady());
113   EXPECT_FALSE(complete);
114   EXPECT_TRUE(failure);
115 }
116
117 TEST(Times, interrupt) {
118   std::queue<std::shared_ptr<Promise<Unit>>> ps;
119   std::mutex ps_mutex;
120   int interrupt = 0;
121   bool complete = false;
122   bool failure = false;
123
124   auto thunk = makeThunk(ps, interrupt, ps_mutex);
125   auto f = folly::times(3, thunk)
126     .then([&]() mutable { complete = true; })
127     .onError([&] (FutureException& e) { failure = true; });
128
129   EXPECT_EQ(0, interrupt);
130
131   FutureException eggs("eggs");
132   f.raise(eggs);
133
134   for (int i = 1; i <= 3; ++i) {
135     EXPECT_EQ(1, interrupt);
136     popAndFulfillPromise(ps, ps_mutex);
137   }
138 }