Use the GTest portability headers
[folly.git] / folly / futures / test / WhileDoTest.cpp
1 /*
2  * Copyright 2016 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 <glog/logging.h>
22
23 #include <folly/futures/Future.h>
24 #include <folly/futures/Promise.h>
25 #include <folly/portability/GTest.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(
46         [&](exception_wrapper const& /* e */) { ++interrupt; });
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(WhileDo, success) {
64   std::queue<std::shared_ptr<Promise<Unit>>> ps;
65   std::mutex ps_mutex;
66   int i = 0;
67   int interrupt = 0;
68   bool complete = false;
69   bool failure = false;
70
71   auto pred = makePred(i);
72   auto thunk = makeThunk(ps, interrupt, ps_mutex);
73   auto f = folly::whileDo(pred, thunk)
74                .then([&]() mutable { complete = true; })
75                .onError([&](FutureException& /* e */) { failure = true; });
76
77   popAndFulfillPromise(ps, ps_mutex);
78   EXPECT_FALSE(complete);
79   EXPECT_FALSE(failure);
80
81   popAndFulfillPromise(ps, ps_mutex);
82   EXPECT_FALSE(complete);
83   EXPECT_FALSE(failure);
84
85   popAndFulfillPromise(ps, ps_mutex);
86   EXPECT_TRUE(f.isReady());
87   EXPECT_TRUE(complete);
88   EXPECT_FALSE(failure);
89 }
90
91 TEST(WhileDo, failure) {
92   std::queue<std::shared_ptr<Promise<Unit>>> ps;
93   std::mutex ps_mutex;
94   int i = 0;
95   int interrupt = 0;
96   bool complete = false;
97   bool failure = false;
98
99   auto pred = makePred(i);
100   auto thunk = makeThunk(ps, interrupt, ps_mutex);
101   auto f = folly::whileDo(pred, thunk)
102                .then([&]() mutable { complete = true; })
103                .onError([&](FutureException& /* e */) { failure = true; });
104
105   popAndFulfillPromise(ps, ps_mutex);
106   EXPECT_FALSE(complete);
107   EXPECT_FALSE(failure);
108
109   ps_mutex.lock();
110   auto p2 = ps.front();
111   ps.pop();
112   ps_mutex.unlock();
113   FutureException eggs("eggs");
114   p2->setException(eggs);
115
116   EXPECT_TRUE(f.isReady());
117   EXPECT_FALSE(complete);
118   EXPECT_TRUE(failure);
119 }
120
121 TEST(WhileDo, interrupt) {
122   std::queue<std::shared_ptr<Promise<Unit>>> ps;
123   std::mutex ps_mutex;
124   int i = 0;
125   int interrupt = 0;
126   bool complete = false;
127   bool failure = false;
128
129   auto pred = makePred(i);
130   auto thunk = makeThunk(ps, interrupt, ps_mutex);
131   auto f = folly::whileDo(pred, thunk)
132                .then([&]() mutable { complete = true; })
133                .onError([&](FutureException& /* e */) { failure = true; });
134
135   EXPECT_EQ(0, interrupt);
136
137   FutureException eggs("eggs");
138   f.raise(eggs);
139
140   for (int i = 1; i <= 3; ++i) {
141     EXPECT_EQ(1, interrupt);
142     popAndFulfillPromise(ps, ps_mutex);
143   }
144 }