• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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