Fix copyright lines
[folly.git] / folly / futures / test / WhileDoTest.cpp
1 /*
2  * Copyright 2015-present 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 <folly/futures/Future.h>
22 #include <folly/futures/Promise.h>
23 #include <folly/portability/GTest.h>
24
25 using namespace folly;
26
27 inline void popAndFulfillPromise(
28     std::queue<std::shared_ptr<Promise<Unit>>>& ps,
29     std::mutex& ps_mutex) {
30   ps_mutex.lock();
31   auto p = ps.front();
32   ps.pop();
33   ps_mutex.unlock();
34   p->setValue();
35 }
36
37 inline std::function<Future<Unit>(void)> makeThunk(
38     std::queue<std::shared_ptr<Promise<Unit>>>& ps,
39     int& interrupt,
40     std::mutex& ps_mutex) {
41   return [&]() mutable {
42     auto p = std::make_shared<Promise<Unit>>();
43     p->setInterruptHandler(
44         [&](exception_wrapper const& /* e */) { ++interrupt; });
45     ps_mutex.lock();
46     ps.push(p);
47     ps_mutex.unlock();
48
49     return p->getFuture();
50   };
51 }
52
53 inline std::function<bool(void)> makePred(int& i) {
54   return [&]() {
55     bool res = i < 3;
56     ++i;
57     return res;
58   };
59 }
60
61 TEST(WhileDo, success) {
62   std::queue<std::shared_ptr<Promise<Unit>>> ps;
63   std::mutex ps_mutex;
64   int i = 0;
65   int interrupt = 0;
66   bool complete = false;
67   bool failure = false;
68
69   auto pred = makePred(i);
70   auto thunk = makeThunk(ps, interrupt, ps_mutex);
71   auto f = folly::whileDo(pred, 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(WhileDo, failure) {
90   std::queue<std::shared_ptr<Promise<Unit>>> ps;
91   std::mutex ps_mutex;
92   int i = 0;
93   int interrupt = 0;
94   bool complete = false;
95   bool failure = false;
96
97   auto pred = makePred(i);
98   auto thunk = makeThunk(ps, interrupt, ps_mutex);
99   auto f = folly::whileDo(pred, thunk)
100                .then([&]() mutable { complete = true; })
101                .onError([&](FutureException& /* e */) { failure = true; });
102
103   popAndFulfillPromise(ps, ps_mutex);
104   EXPECT_FALSE(complete);
105   EXPECT_FALSE(failure);
106
107   ps_mutex.lock();
108   auto p2 = ps.front();
109   ps.pop();
110   ps_mutex.unlock();
111   FutureException eggs("eggs");
112   p2->setException(eggs);
113
114   EXPECT_TRUE(f.isReady());
115   EXPECT_FALSE(complete);
116   EXPECT_TRUE(failure);
117 }
118
119 TEST(WhileDo, interrupt) {
120   std::queue<std::shared_ptr<Promise<Unit>>> ps;
121   std::mutex ps_mutex;
122   int interrupt = 0;
123   bool complete = false;
124   bool failure = false;
125
126   int i = 0;
127   auto pred = makePred(i);
128   auto thunk = makeThunk(ps, interrupt, ps_mutex);
129   auto f = folly::whileDo(pred, thunk)
130                .then([&]() mutable { complete = true; })
131                .onError([&](FutureException& /* e */) { failure = true; });
132
133   EXPECT_EQ(0, interrupt);
134
135   FutureException eggs("eggs");
136   f.raise(eggs);
137
138   for (int j = 1; j <= 3; ++j) {
139     EXPECT_EQ(1, interrupt);
140     popAndFulfillPromise(ps, ps_mutex);
141   }
142 }