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 #include <chrono>
21 #include <future>
22 #include <thread>
23
24 #include "gtest/gtest.h"
25
26 namespace bluetooth {
27 namespace os {
28 namespace {
29
30 constexpr int kReadReadyValue = 100;
31
32 std::promise<int>* g_promise;
33
34 class ReactorTest : public ::testing::Test {
35 protected:
SetUp()36 void SetUp() override {
37 g_promise = new std::promise<int>;
38 reactor_ = new Reactor;
39 }
40
TearDown()41 void TearDown() override {
42 delete g_promise;
43 g_promise = nullptr;
44 delete reactor_;
45 reactor_ = nullptr;
46 }
47
48 Reactor* reactor_;
49 };
50
51 class SampleReactable {
52 public:
SampleReactable()53 SampleReactable() : fd_(eventfd(0, EFD_NONBLOCK)) {
54 EXPECT_NE(fd_, 0);
55 }
56
~SampleReactable()57 ~SampleReactable() {
58 close(fd_);
59 }
60
OnReadReady()61 void OnReadReady() {}
62
OnWriteReady()63 void OnWriteReady() {}
64
65 int fd_;
66 };
67
68 class FakeReactable {
69 public:
70 enum EventFdValue {
71 kSetPromise = 1,
72 kRegisterSampleReactable,
73 kUnregisterSampleReactable,
74 kSampleOutputValue,
75 };
FakeReactable()76 FakeReactable() : fd_(eventfd(0, 0)), reactor_(nullptr) {
77 EXPECT_NE(fd_, 0);
78 }
79
FakeReactable(Reactor * reactor)80 FakeReactable(Reactor* reactor) : fd_(eventfd(0, 0)), reactor_(reactor) {
81 EXPECT_NE(fd_, 0);
82 }
83
~FakeReactable()84 ~FakeReactable() {
85 close(fd_);
86 }
87
OnReadReady()88 void OnReadReady() {
89 uint64_t value = 0;
90 auto read_result = eventfd_read(fd_, &value);
91 EXPECT_EQ(read_result, 0);
92 if (value == kSetPromise && g_promise != nullptr) {
93 g_promise->set_value(kReadReadyValue);
94 }
95 if (value == kRegisterSampleReactable) {
96 reactable_ = reactor_->Register(sample_reactable_.fd_, [this] { this->sample_reactable_.OnReadReady(); },
97 [this] { this->sample_reactable_.OnWriteReady(); });
98 g_promise->set_value(kReadReadyValue);
99 }
100 if (value == kUnregisterSampleReactable) {
101 reactor_->Unregister(reactable_);
102 g_promise->set_value(kReadReadyValue);
103 }
104 }
105
OnWriteReady()106 void OnWriteReady() {
107 auto write_result = eventfd_write(fd_, output_data_);
108 output_data_ = 0;
109 EXPECT_EQ(write_result, 0);
110 }
111
112 SampleReactable sample_reactable_;
113 Reactor::Reactable* reactable_ = nullptr;
114 int fd_;
115
116 private:
117 Reactor* reactor_;
118 uint64_t output_data_ = kSampleOutputValue;
119 };
120
TEST_F(ReactorTest,start_and_stop)121 TEST_F(ReactorTest, start_and_stop) {
122 auto reactor_thread = std::thread(&Reactor::Run, reactor_);
123 reactor_->Stop();
124 reactor_thread.join();
125 }
126
TEST_F(ReactorTest,stop_and_start)127 TEST_F(ReactorTest, stop_and_start) {
128 auto reactor_thread = std::thread(&Reactor::Stop, reactor_);
129 auto another_thread = std::thread(&Reactor::Run, reactor_);
130 reactor_thread.join();
131 another_thread.join();
132 }
133
TEST_F(ReactorTest,stop_multi_times)134 TEST_F(ReactorTest, stop_multi_times) {
135 auto reactor_thread = std::thread(&Reactor::Run, reactor_);
136 for (int i = 0; i < 5; i++) {
137 reactor_->Stop();
138 }
139 reactor_thread.join();
140 }
141
TEST_F(ReactorTest,cold_register_only)142 TEST_F(ReactorTest, cold_register_only) {
143 FakeReactable fake_reactable;
144 auto* reactable =
145 reactor_->Register(fake_reactable.fd_, std::bind(&FakeReactable::OnReadReady, &fake_reactable), nullptr);
146
147 reactor_->Unregister(reactable);
148 }
149
TEST_F(ReactorTest,cold_register)150 TEST_F(ReactorTest, cold_register) {
151 FakeReactable fake_reactable;
152 auto* reactable =
153 reactor_->Register(fake_reactable.fd_, std::bind(&FakeReactable::OnReadReady, &fake_reactable), nullptr);
154 auto reactor_thread = std::thread(&Reactor::Run, reactor_);
155 auto future = g_promise->get_future();
156
157 auto write_result = eventfd_write(fake_reactable.fd_, FakeReactable::kSetPromise);
158 EXPECT_EQ(write_result, 0);
159 EXPECT_EQ(future.get(), kReadReadyValue);
160 reactor_->Stop();
161 reactor_thread.join();
162 reactor_->Unregister(reactable);
163 }
164
TEST_F(ReactorTest,hot_register_from_different_thread)165 TEST_F(ReactorTest, hot_register_from_different_thread) {
166 auto reactor_thread = std::thread(&Reactor::Run, reactor_);
167 auto future = g_promise->get_future();
168
169 FakeReactable fake_reactable;
170 auto* reactable =
171 reactor_->Register(fake_reactable.fd_, std::bind(&FakeReactable::OnReadReady, &fake_reactable), nullptr);
172 auto write_result = eventfd_write(fake_reactable.fd_, FakeReactable::kSetPromise);
173 EXPECT_EQ(write_result, 0);
174 EXPECT_EQ(future.get(), kReadReadyValue);
175 reactor_->Stop();
176 reactor_thread.join();
177
178 reactor_->Unregister(reactable);
179 }
180
TEST_F(ReactorTest,hot_unregister_from_different_thread)181 TEST_F(ReactorTest, hot_unregister_from_different_thread) {
182 FakeReactable fake_reactable;
183 auto* reactable =
184 reactor_->Register(fake_reactable.fd_, std::bind(&FakeReactable::OnReadReady, &fake_reactable), nullptr);
185 auto reactor_thread = std::thread(&Reactor::Run, reactor_);
186 reactor_->Unregister(reactable);
187 auto future = g_promise->get_future();
188
189 auto write_result = eventfd_write(fake_reactable.fd_, FakeReactable::kSetPromise);
190 EXPECT_EQ(write_result, 0);
191 future.wait_for(std::chrono::milliseconds(10));
192 g_promise->set_value(2);
193 EXPECT_EQ(future.get(), 2);
194 reactor_->Stop();
195 reactor_thread.join();
196 }
197
TEST_F(ReactorTest,hot_register_from_same_thread)198 TEST_F(ReactorTest, hot_register_from_same_thread) {
199 auto reactor_thread = std::thread(&Reactor::Run, reactor_);
200 auto future = g_promise->get_future();
201
202 FakeReactable fake_reactable(reactor_);
203 auto* reactable =
204 reactor_->Register(fake_reactable.fd_, std::bind(&FakeReactable::OnReadReady, &fake_reactable), nullptr);
205 auto write_result = eventfd_write(fake_reactable.fd_, FakeReactable::kRegisterSampleReactable);
206 EXPECT_EQ(write_result, 0);
207 EXPECT_EQ(future.get(), kReadReadyValue);
208 reactor_->Stop();
209 reactor_thread.join();
210
211 reactor_->Unregister(reactable);
212 }
213
TEST_F(ReactorTest,hot_unregister_from_same_thread)214 TEST_F(ReactorTest, hot_unregister_from_same_thread) {
215 auto reactor_thread = std::thread(&Reactor::Run, reactor_);
216 auto future = g_promise->get_future();
217
218 FakeReactable fake_reactable(reactor_);
219 auto* reactable =
220 reactor_->Register(fake_reactable.fd_, std::bind(&FakeReactable::OnReadReady, &fake_reactable), nullptr);
221 auto write_result = eventfd_write(fake_reactable.fd_, FakeReactable::kRegisterSampleReactable);
222 EXPECT_EQ(write_result, 0);
223 EXPECT_EQ(future.get(), kReadReadyValue);
224 delete g_promise;
225 g_promise = new std::promise<int>;
226 future = g_promise->get_future();
227 write_result = eventfd_write(fake_reactable.fd_, FakeReactable::kUnregisterSampleReactable);
228 EXPECT_EQ(write_result, 0);
229 EXPECT_EQ(future.get(), kReadReadyValue);
230 reactor_->Stop();
231 reactor_thread.join();
232
233 reactor_->Unregister(reactable);
234 }
235
TEST_F(ReactorTest,start_and_stop_multi_times)236 TEST_F(ReactorTest, start_and_stop_multi_times) {
237 auto reactor_thread = std::thread(&Reactor::Run, reactor_);
238 reactor_->Stop();
239 reactor_thread.join();
240 for (int i = 0; i < 5; i++) {
241 reactor_thread = std::thread(&Reactor::Run, reactor_);
242 reactor_->Stop();
243 reactor_thread.join();
244 }
245 }
246
TEST_F(ReactorTest,on_write_ready)247 TEST_F(ReactorTest, on_write_ready) {
248 FakeReactable fake_reactable;
249 auto* reactable =
250 reactor_->Register(fake_reactable.fd_, nullptr, std::bind(&FakeReactable::OnWriteReady, &fake_reactable));
251 auto reactor_thread = std::thread(&Reactor::Run, reactor_);
252 uint64_t value = 0;
253 auto read_result = eventfd_read(fake_reactable.fd_, &value);
254 EXPECT_EQ(read_result, 0);
255 EXPECT_EQ(value, FakeReactable::kSampleOutputValue);
256
257 reactor_->Stop();
258 reactor_thread.join();
259
260 reactor_->Unregister(reactable);
261 }
262
TEST_F(ReactorTest,modify_registration)263 TEST_F(ReactorTest, modify_registration) {
264 FakeReactable fake_reactable;
265 auto* reactable =
266 reactor_->Register(fake_reactable.fd_, std::bind(&FakeReactable::OnReadReady, &fake_reactable), nullptr);
267 reactor_->ModifyRegistration(reactable, nullptr, std::bind(&FakeReactable::OnWriteReady, &fake_reactable));
268 auto reactor_thread = std::thread(&Reactor::Run, reactor_);
269 uint64_t value = 0;
270 auto read_result = eventfd_read(fake_reactable.fd_, &value);
271 EXPECT_EQ(read_result, 0);
272 EXPECT_EQ(value, FakeReactable::kSampleOutputValue);
273
274 reactor_->Stop();
275 reactor_thread.join();
276 }
277
278 } // namespace
279 } // namespace os
280 } // namespace bluetooth
281