1 /*
2  * Copyright 2019 The Android Open Source Project
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 "os/reactor.h"
18 
19 #include <sys/eventfd.h>
20 
21 #include <chrono>
22 #include <future>
23 #include <thread>
24 
25 #include "common/bind.h"
26 #include "common/callback.h"
27 #include "gtest/gtest.h"
28 #include "os/log.h"
29 
30 namespace bluetooth {
31 namespace os {
32 namespace {
33 
34 constexpr int kReadReadyValue = 100;
35 
36 using common::Bind;
37 
38 std::promise<int>* g_promise;
39 
40 class ReactorTest : public ::testing::Test {
41  protected:
SetUp()42   void SetUp() override {
43     g_promise = new std::promise<int>;
44     reactor_ = new Reactor;
45   }
46 
TearDown()47   void TearDown() override {
48     delete g_promise;
49     g_promise = nullptr;
50     delete reactor_;
51     reactor_ = nullptr;
52   }
53 
54   Reactor* reactor_;
55 };
56 
57 class SampleReactable {
58  public:
SampleReactable()59   SampleReactable() : fd_(eventfd(0, EFD_NONBLOCK)) {
60     EXPECT_NE(fd_, -1);
61   }
62 
~SampleReactable()63   ~SampleReactable() {
64     close(fd_);
65   }
66 
OnReadReady()67   void OnReadReady() {}
68 
OnWriteReady()69   void OnWriteReady() {}
70 
71   int fd_;
72 };
73 
74 class FakeReactable {
75  public:
76   enum EventFdValue {
77     kSetPromise = 1,
78     kRegisterSampleReactable,
79     kUnregisterSampleReactable,
80     kSampleOutputValue,
81   };
FakeReactable()82   FakeReactable() : fd_(eventfd(0, 0)), reactor_(nullptr) {
83     EXPECT_NE(fd_, -1);
84   }
85 
FakeReactable(Reactor * reactor)86   FakeReactable(Reactor* reactor) : fd_(eventfd(0, 0)), reactor_(reactor) {
87     EXPECT_NE(fd_, -1);
88   }
89 
~FakeReactable()90   ~FakeReactable() {
91     close(fd_);
92   }
93 
OnReadReady()94   void OnReadReady() {
95     LOG_INFO();
96     uint64_t value = 0;
97     auto read_result = eventfd_read(fd_, &value);
98     LOG_INFO("value = %d", (int)value);
99     EXPECT_EQ(read_result, 0);
100     if (value == kSetPromise && g_promise != nullptr) {
101       g_promise->set_value(kReadReadyValue);
102     }
103     if (value == kRegisterSampleReactable) {
104       reactable_ = reactor_->Register(
105           sample_reactable_.fd_,
106           Bind(&FakeReactable::OnReadReady, common::Unretained(this)),
107           Bind(&FakeReactable::OnWriteReadyNoOp, common::Unretained(this)));
108       g_promise->set_value(kReadReadyValue);
109     }
110     if (value == kUnregisterSampleReactable) {
111       reactor_->Unregister(reactable_);
112       g_promise->set_value(kReadReadyValue);
113     }
114   }
115 
OnWriteReady()116   void OnWriteReady() {
117     auto write_result = eventfd_write(fd_, output_data_);
118     output_data_ = 0;
119     EXPECT_EQ(write_result, 0);
120   }
121 
OnWriteReadyNoOp()122   void OnWriteReadyNoOp() {}
123 
UnregisterInCallback()124   void UnregisterInCallback() {
125     uint64_t value = 0;
126     auto read_result = eventfd_read(fd_, &value);
127     EXPECT_EQ(read_result, 0);
128     g_promise->set_value(kReadReadyValue);
129     reactor_->Unregister(reactable_);
130   }
131 
132   SampleReactable sample_reactable_;
133   Reactor::Reactable* reactable_ = nullptr;
134   int fd_;
135 
136  private:
137   Reactor* reactor_;
138   uint64_t output_data_ = kSampleOutputValue;
139 };
140 
141 class FakeRunningReactable {
142  public:
FakeRunningReactable()143   FakeRunningReactable() : fd_(eventfd(0, 0)) {
144     EXPECT_NE(fd_, -1);
145   }
146 
~FakeRunningReactable()147   ~FakeRunningReactable() {
148     close(fd_);
149   }
150 
OnReadReady()151   void OnReadReady() {
152     uint64_t value = 0;
153     auto read_result = eventfd_read(fd_, &value);
154     ASSERT_EQ(read_result, 0);
155     started.set_value();
156     can_finish.get_future().wait();
157     finished.set_value();
158   }
159 
160   Reactor::Reactable* reactable_ = nullptr;
161   int fd_;
162 
163   std::promise<void> started;
164   std::promise<void> can_finish;
165   std::promise<void> finished;
166 };
167 
TEST_F(ReactorTest,start_and_stop)168 TEST_F(ReactorTest, start_and_stop) {
169   auto reactor_thread = std::thread(&Reactor::Run, reactor_);
170   reactor_->Stop();
171   reactor_thread.join();
172 }
173 
TEST_F(ReactorTest,stop_and_start)174 TEST_F(ReactorTest, stop_and_start) {
175   auto reactor_thread = std::thread(&Reactor::Stop, reactor_);
176   auto another_thread = std::thread(&Reactor::Run, reactor_);
177   reactor_thread.join();
178   another_thread.join();
179 }
180 
TEST_F(ReactorTest,stop_multi_times)181 TEST_F(ReactorTest, stop_multi_times) {
182   auto reactor_thread = std::thread(&Reactor::Run, reactor_);
183   for (int i = 0; i < 5; i++) {
184     reactor_->Stop();
185   }
186   reactor_thread.join();
187 }
188 
TEST_F(ReactorTest,cold_register_only)189 TEST_F(ReactorTest, cold_register_only) {
190   FakeReactable fake_reactable;
191   auto* reactable = reactor_->Register(
192       fake_reactable.fd_, Bind(&FakeReactable::OnReadReady, common::Unretained(&fake_reactable)), common::Closure());
193 
194   reactor_->Unregister(reactable);
195 }
196 
TEST_F(ReactorTest,cold_register)197 TEST_F(ReactorTest, cold_register) {
198   FakeReactable fake_reactable;
199   auto* reactable = reactor_->Register(
200       fake_reactable.fd_, Bind(&FakeReactable::OnReadReady, common::Unretained(&fake_reactable)), common::Closure());
201   auto reactor_thread = std::thread(&Reactor::Run, reactor_);
202   auto future = g_promise->get_future();
203 
204   auto write_result = eventfd_write(fake_reactable.fd_, FakeReactable::kSetPromise);
205   EXPECT_EQ(write_result, 0);
206   EXPECT_EQ(future.get(), kReadReadyValue);
207   reactor_->Stop();
208   reactor_thread.join();
209   reactor_->Unregister(reactable);
210 }
211 
TEST_F(ReactorTest,hot_register_from_different_thread)212 TEST_F(ReactorTest, hot_register_from_different_thread) {
213   auto reactor_thread = std::thread(&Reactor::Run, reactor_);
214   auto future = g_promise->get_future();
215 
216   FakeReactable fake_reactable;
217   auto* reactable = reactor_->Register(
218       fake_reactable.fd_, Bind(&FakeReactable::OnReadReady, common::Unretained(&fake_reactable)), common::Closure());
219   auto write_result = eventfd_write(fake_reactable.fd_, FakeReactable::kSetPromise);
220   EXPECT_EQ(write_result, 0);
221   EXPECT_EQ(future.get(), kReadReadyValue);
222   reactor_->Stop();
223   reactor_thread.join();
224 
225   reactor_->Unregister(reactable);
226 }
227 
TEST_F(ReactorTest,unregister_from_different_thread_while_task_is_executing_)228 TEST_F(ReactorTest, unregister_from_different_thread_while_task_is_executing_) {
229   FakeRunningReactable fake_reactable;
230   auto* reactable = reactor_->Register(
231       fake_reactable.fd_,
232       Bind(&FakeRunningReactable::OnReadReady, common::Unretained(&fake_reactable)),
233       common::Closure());
234   auto reactor_thread = std::thread(&Reactor::Run, reactor_);
235   auto write_result = eventfd_write(fake_reactable.fd_, 1);
236   ASSERT_EQ(write_result, 0);
237   fake_reactable.started.get_future().wait();
238   reactor_->Unregister(reactable);
239   fake_reactable.can_finish.set_value();
240   fake_reactable.finished.get_future().wait();
241 
242   reactor_->Stop();
243   reactor_thread.join();
244 }
245 
TEST_F(ReactorTest,unregister_from_different_thread_while_task_is_executing_wait_fails)246 TEST_F(ReactorTest, unregister_from_different_thread_while_task_is_executing_wait_fails) {
247   FakeRunningReactable fake_reactable;
248   auto* reactable = reactor_->Register(
249       fake_reactable.fd_,
250       common::Bind(&FakeRunningReactable::OnReadReady, common::Unretained(&fake_reactable)),
251       common::Closure());
252   auto reactor_thread = std::thread(&Reactor::Run, reactor_);
253   auto write_result = eventfd_write(fake_reactable.fd_, 1);
254   ASSERT_EQ(write_result, 0);
255   fake_reactable.started.get_future().wait();
256   reactor_->Unregister(reactable);
257   ASSERT_FALSE(reactor_->WaitForUnregisteredReactable(std::chrono::milliseconds(1)));
258   fake_reactable.can_finish.set_value();
259   fake_reactable.finished.get_future().wait();
260 
261   reactor_->Stop();
262   reactor_thread.join();
263 }
264 
TEST_F(ReactorTest,unregister_from_different_thread_while_task_is_executing_wait_succeeds)265 TEST_F(ReactorTest, unregister_from_different_thread_while_task_is_executing_wait_succeeds) {
266   FakeRunningReactable fake_reactable;
267   auto* reactable = reactor_->Register(
268       fake_reactable.fd_,
269       common::Bind(&FakeRunningReactable::OnReadReady, common::Unretained(&fake_reactable)),
270       common::Closure());
271   auto reactor_thread = std::thread(&Reactor::Run, reactor_);
272   auto write_result = eventfd_write(fake_reactable.fd_, 1);
273   ASSERT_EQ(write_result, 0);
274   fake_reactable.started.get_future().wait();
275   reactor_->Unregister(reactable);
276   fake_reactable.can_finish.set_value();
277   fake_reactable.finished.get_future().wait();
278   ASSERT_TRUE(reactor_->WaitForUnregisteredReactable(std::chrono::milliseconds(1)));
279 
280   reactor_->Stop();
281   reactor_thread.join();
282 }
283 
TEST_F(ReactorTest,hot_unregister_from_different_thread)284 TEST_F(ReactorTest, hot_unregister_from_different_thread) {
285   FakeReactable fake_reactable;
286   auto* reactable = reactor_->Register(
287       fake_reactable.fd_, Bind(&FakeReactable::OnReadReady, common::Unretained(&fake_reactable)), common::Closure());
288   auto reactor_thread = std::thread(&Reactor::Run, reactor_);
289   reactor_->Unregister(reactable);
290   auto future = g_promise->get_future();
291 
292   auto write_result = eventfd_write(fake_reactable.fd_, FakeReactable::kSetPromise);
293   EXPECT_EQ(write_result, 0);
294   future.wait_for(std::chrono::milliseconds(10));
295   g_promise->set_value(2);
296   EXPECT_EQ(future.get(), 2);
297   reactor_->Stop();
298   reactor_thread.join();
299 }
300 
TEST_F(ReactorTest,hot_register_from_same_thread)301 TEST_F(ReactorTest, hot_register_from_same_thread) {
302   auto reactor_thread = std::thread(&Reactor::Run, reactor_);
303   auto future = g_promise->get_future();
304 
305   FakeReactable fake_reactable(reactor_);
306   auto* reactable = reactor_->Register(
307       fake_reactable.fd_, Bind(&FakeReactable::OnReadReady, common::Unretained(&fake_reactable)), common::Closure());
308   auto write_result = eventfd_write(fake_reactable.fd_, FakeReactable::kRegisterSampleReactable);
309   EXPECT_EQ(write_result, 0);
310   EXPECT_EQ(future.get(), kReadReadyValue);
311   delete g_promise;
312   g_promise = new std::promise<int>;
313   future = g_promise->get_future();
314   write_result = eventfd_write(fake_reactable.fd_, FakeReactable::kUnregisterSampleReactable);
315   EXPECT_EQ(write_result, 0);
316   reactor_->Stop();
317   reactor_thread.join();
318 
319   reactor_->Unregister(reactable);
320 }
321 
TEST_F(ReactorTest,hot_unregister_from_same_thread)322 TEST_F(ReactorTest, hot_unregister_from_same_thread) {
323   auto reactor_thread = std::thread(&Reactor::Run, reactor_);
324   auto future = g_promise->get_future();
325 
326   FakeReactable fake_reactable(reactor_);
327   auto* reactable = reactor_->Register(
328       fake_reactable.fd_, Bind(&FakeReactable::OnReadReady, common::Unretained(&fake_reactable)), common::Closure());
329   auto write_result = eventfd_write(fake_reactable.fd_, FakeReactable::kRegisterSampleReactable);
330   EXPECT_EQ(write_result, 0);
331   EXPECT_EQ(future.get(), kReadReadyValue);
332   LOG_INFO();
333   delete g_promise;
334   g_promise = new std::promise<int>;
335   future = g_promise->get_future();
336   write_result = eventfd_write(fake_reactable.fd_, FakeReactable::kUnregisterSampleReactable);
337   EXPECT_EQ(write_result, 0);
338   EXPECT_EQ(future.get(), kReadReadyValue);
339   LOG_INFO();
340   reactor_->Stop();
341   reactor_thread.join();
342 
343   reactor_->Unregister(reactable);
344 }
345 
TEST_F(ReactorTest,hot_unregister_from_callback)346 TEST_F(ReactorTest, hot_unregister_from_callback) {
347   auto reactor_thread = std::thread(&Reactor::Run, reactor_);
348 
349   FakeReactable fake_reactable1(reactor_);
350   auto* reactable1 = reactor_->Register(
351       fake_reactable1.fd_, Bind(&FakeReactable::OnReadReady, common::Unretained(&fake_reactable1)), common::Closure());
352 
353   FakeReactable fake_reactable2(reactor_);
354   auto* reactable2 = reactor_->Register(
355       fake_reactable2.fd_,
356       Bind(&FakeReactable::UnregisterInCallback, common::Unretained(&fake_reactable2)),
357       common::Closure());
358   fake_reactable2.reactable_ = reactable2;
359   auto write_result = eventfd_write(fake_reactable2.fd_, 1);
360   EXPECT_EQ(write_result, 0);
361   reactor_->Stop();
362   reactor_thread.join();
363 
364   reactor_->Unregister(reactable1);
365 }
366 
TEST_F(ReactorTest,hot_unregister_during_unregister_from_callback)367 TEST_F(ReactorTest, hot_unregister_during_unregister_from_callback) {
368   auto reactor_thread = std::thread(&Reactor::Run, reactor_);
369   auto future = g_promise->get_future();
370 
371   FakeReactable fake_reactable1(reactor_);
372   auto* reactable1 = reactor_->Register(
373       fake_reactable1.fd_, Bind(&FakeReactable::OnReadReady, common::Unretained(&fake_reactable1)), common::Closure());
374 
375   FakeReactable fake_reactable2(reactor_);
376   auto* reactable2 = reactor_->Register(
377       fake_reactable2.fd_,
378       Bind(&FakeReactable::UnregisterInCallback, common::Unretained(&fake_reactable2)),
379       common::Closure());
380   fake_reactable2.reactable_ = reactable2;
381   auto write_result = eventfd_write(fake_reactable2.fd_, 1);
382   EXPECT_EQ(write_result, 0);
383   EXPECT_EQ(future.get(), kReadReadyValue);
384   reactor_->Unregister(reactable1);
385 
386   reactor_->Stop();
387   reactor_thread.join();
388 }
389 
TEST_F(ReactorTest,start_and_stop_multi_times)390 TEST_F(ReactorTest, start_and_stop_multi_times) {
391   auto reactor_thread = std::thread(&Reactor::Run, reactor_);
392   reactor_->Stop();
393   reactor_thread.join();
394   for (int i = 0; i < 5; i++) {
395     reactor_thread = std::thread(&Reactor::Run, reactor_);
396     reactor_->Stop();
397     reactor_thread.join();
398   }
399 }
400 
TEST_F(ReactorTest,on_write_ready)401 TEST_F(ReactorTest, on_write_ready) {
402   FakeReactable fake_reactable;
403   auto* reactable = reactor_->Register(
404       fake_reactable.fd_, common::Closure(), Bind(&FakeReactable::OnWriteReady, common::Unretained(&fake_reactable)));
405   auto reactor_thread = std::thread(&Reactor::Run, reactor_);
406   uint64_t value = 0;
407   auto read_result = eventfd_read(fake_reactable.fd_, &value);
408   EXPECT_EQ(read_result, 0);
409   EXPECT_EQ(value, FakeReactable::kSampleOutputValue);
410 
411   reactor_->Stop();
412   reactor_thread.join();
413 
414   reactor_->Unregister(reactable);
415 }
416 
TEST_F(ReactorTest,modify_registration)417 TEST_F(ReactorTest, modify_registration) {
418   FakeReactable fake_reactable;
419   auto* reactable = reactor_->Register(
420       fake_reactable.fd_, Bind(&FakeReactable::OnReadReady, common::Unretained(&fake_reactable)), common::Closure());
421   reactor_->ModifyRegistration(
422       reactable, common::Closure(), Bind(&FakeReactable::OnWriteReady, common::Unretained(&fake_reactable)));
423   auto reactor_thread = std::thread(&Reactor::Run, reactor_);
424   uint64_t value = 0;
425   auto read_result = eventfd_read(fake_reactable.fd_, &value);
426   EXPECT_EQ(read_result, 0);
427   EXPECT_EQ(value, FakeReactable::kSampleOutputValue);
428 
429   reactor_->Stop();
430   reactor_thread.join();
431 
432   reactor_->Unregister(reactable);
433 }
434 
435 }  // namespace
436 }  // namespace os
437 }  // namespace bluetooth
438