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