remove unnecessary & deprecated activate() call
[folly.git] / folly / futures / test / ExecutorTest.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 #include <folly/futures/InlineExecutor.h>
19 #include <folly/futures/ManualExecutor.h>
20 #include <folly/futures/QueuedImmediateExecutor.h>
21 #include <folly/futures/Future.h>
22 #include <folly/Baton.h>
23
24 using namespace folly;
25 using namespace std::chrono;
26 using namespace testing;
27
28 TEST(ManualExecutor, runIsStable) {
29   ManualExecutor x;
30   size_t count = 0;
31   auto f1 = [&]() { count++; };
32   auto f2 = [&]() { x.add(f1); x.add(f1); };
33   x.add(f2);
34   x.run();
35 }
36
37 TEST(ManualExecutor, scheduleDur) {
38   ManualExecutor x;
39   size_t count = 0;
40   milliseconds dur {10};
41   x.schedule([&]{ count++; }, dur);
42   EXPECT_EQ(count, 0);
43   x.run();
44   EXPECT_EQ(count, 0);
45   x.advance(dur/2);
46   EXPECT_EQ(count, 0);
47   x.advance(dur/2);
48   EXPECT_EQ(count, 1);
49 }
50
51 TEST(ManualExecutor, clockStartsAt0) {
52   ManualExecutor x;
53   EXPECT_EQ(x.now(), x.now().min());
54 }
55
56 TEST(ManualExecutor, scheduleAbs) {
57   ManualExecutor x;
58   size_t count = 0;
59   x.scheduleAt([&]{ count++; }, x.now() + milliseconds(10));
60   EXPECT_EQ(count, 0);
61   x.advance(milliseconds(10));
62   EXPECT_EQ(count, 1);
63 }
64
65 TEST(ManualExecutor, advanceTo) {
66   ManualExecutor x;
67   size_t count = 0;
68   x.scheduleAt([&]{ count++; }, steady_clock::now());
69   EXPECT_EQ(count, 0);
70   x.advanceTo(steady_clock::now());
71   EXPECT_EQ(count, 1);
72 }
73
74 TEST(ManualExecutor, advanceBack) {
75   ManualExecutor x;
76   size_t count = 0;
77   x.advance(microseconds(5));
78   x.schedule([&]{ count++; }, microseconds(6));
79   EXPECT_EQ(count, 0);
80   x.advanceTo(x.now() - microseconds(1));
81   EXPECT_EQ(count, 0);
82 }
83
84 TEST(ManualExecutor, advanceNeg) {
85   ManualExecutor x;
86   size_t count = 0;
87   x.advance(microseconds(5));
88   x.schedule([&]{ count++; }, microseconds(6));
89   EXPECT_EQ(count, 0);
90   x.advance(microseconds(-1));
91   EXPECT_EQ(count, 0);
92 }
93
94 TEST(ManualExecutor, waitForDoesNotDeadlock) {
95   ManualExecutor east, west;
96   folly::Baton<> baton;
97   auto f = makeFuture()
98     .via(&east)
99     .then([](Try<void>){ return makeFuture(); })
100     .via(&west);
101   std::thread t([&]{
102     baton.post();
103     west.waitFor(f);
104   });
105   baton.wait();
106   east.run();
107   t.join();
108 }
109
110 TEST(Executor, InlineExecutor) {
111   InlineExecutor x;
112   size_t counter = 0;
113   x.add([&]{
114     x.add([&]{
115       EXPECT_EQ(counter, 0);
116       counter++;
117     });
118     EXPECT_EQ(counter, 1);
119     counter++;
120   });
121   EXPECT_EQ(counter, 2);
122 }
123
124 TEST(Executor, QueuedImmediateExecutor) {
125   QueuedImmediateExecutor x;
126   size_t counter = 0;
127   x.add([&]{
128     x.add([&]{
129       EXPECT_EQ(1, counter);
130       counter++;
131     });
132     EXPECT_EQ(0, counter);
133     counter++;
134   });
135   EXPECT_EQ(2, counter);
136 }
137
138 TEST(Executor, Runnable) {
139   InlineExecutor x;
140   size_t counter = 0;
141   struct Runnable {
142     std::function<void()> fn;
143     void operator()() { fn(); }
144   };
145   Runnable f;
146   f.fn = [&]{ counter++; };
147   x.add(f);
148   EXPECT_EQ(counter, 1);
149 }
150
151 TEST(Executor, RunnablePtr) {
152   InlineExecutor x;
153   struct Runnable {
154     std::function<void()> fn;
155     void operator()() { fn(); }
156   };
157   size_t counter = 0;
158   auto fnp = std::make_shared<Runnable>();
159   fnp->fn = [&]{ counter++; };
160   x.addPtr(fnp);
161   EXPECT_EQ(counter, 1);
162 }
163
164 TEST(Executor, ThrowableThen) {
165   InlineExecutor x;
166   auto f = Future<void>().via(&x).then([](){
167     throw std::runtime_error("Faildog");
168   });
169   EXPECT_THROW(f.value(), std::exception);
170 }
171
172 class CrappyExecutor : public Executor {
173  public:
174   void add(Func f) override {
175     throw std::runtime_error("bad");
176   }
177 };
178
179 TEST(Executor, CrappyExecutor) {
180   CrappyExecutor x;
181   try {
182     auto f = Future<void>().via(&x).then([](){
183       return;
184     });
185     f.value();
186     EXPECT_TRUE(false);
187   } catch(...) {
188     // via() should throw
189     return;
190   }
191 }