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