1 //
2 // Copyright 2017 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 #define LOG_TAG "async_fd_watcher_unittest"
18
19 #include "async_fd_watcher.h"
20 #include <gtest/gtest.h>
21 #include <cstdint>
22 #include <cstring>
23 #include <vector>
24
25 #include <log/log.h>
26 #include <netdb.h>
27 #include <netinet/in.h>
28 #include <sys/socket.h>
29 #include <sys/types.h>
30 #include <unistd.h>
31
32 namespace android {
33 namespace hardware {
34 namespace bluetooth {
35 namespace V1_0 {
36 namespace implementation {
37
38 using android::hardware::bluetooth::async::AsyncFdWatcher;
39
40 class AsyncFdWatcherSocketTest : public ::testing::Test {
41 public:
42 static const uint16_t kPort = 6111;
43 static const size_t kBufferSize = 16;
44
CheckBufferEquals()45 bool CheckBufferEquals() {
46 return strcmp(server_buffer_, client_buffer_) == 0;
47 }
48
49 protected:
StartServer()50 int StartServer() {
51 ALOGD("%s", __func__);
52 struct sockaddr_in serv_addr;
53 int fd = socket(AF_INET, SOCK_STREAM, 0);
54 EXPECT_FALSE(fd < 0);
55
56 memset(&serv_addr, 0, sizeof(serv_addr));
57 serv_addr.sin_family = AF_INET;
58 serv_addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
59 serv_addr.sin_port = htons(kPort);
60 int reuse_flag = 1;
61 EXPECT_FALSE(setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &reuse_flag,
62 sizeof(reuse_flag)) < 0);
63 EXPECT_FALSE(bind(fd, (sockaddr*)&serv_addr, sizeof(serv_addr)) < 0);
64
65 ALOGD("%s before listen", __func__);
66 listen(fd, 1);
67 return fd;
68 }
69
AcceptConnection(int fd)70 int AcceptConnection(int fd) {
71 ALOGD("%s", __func__);
72 struct sockaddr_in cli_addr;
73 memset(&cli_addr, 0, sizeof(cli_addr));
74 socklen_t clilen = sizeof(cli_addr);
75
76 int connection_fd = accept(fd, (struct sockaddr*)&cli_addr, &clilen);
77 EXPECT_FALSE(connection_fd < 0);
78
79 return connection_fd;
80 }
81
ReadIncomingMessage(int fd)82 void ReadIncomingMessage(int fd) {
83 ALOGD("%s", __func__);
84 int n = TEMP_FAILURE_RETRY(read(fd, server_buffer_, kBufferSize - 1));
85 EXPECT_FALSE(n < 0);
86
87 if (n == 0) { // got EOF
88 ALOGD("%s: EOF", __func__);
89 } else {
90 ALOGD("%s: Got something", __func__);
91 n = write(fd, "1", 1);
92 }
93 }
94
SetUp()95 void SetUp() override {
96 ALOGD("%s", __func__);
97 memset(server_buffer_, 0, kBufferSize);
98 memset(client_buffer_, 0, kBufferSize);
99 }
100
ConfigureServer()101 void ConfigureServer() {
102 socket_fd_ = StartServer();
103
104 conn_watcher_.WatchFdForNonBlockingReads(socket_fd_, [this](int fd) {
105 int connection_fd = AcceptConnection(fd);
106 ALOGD("%s: Conn_watcher fd = %d", __func__, fd);
107
108 conn_watcher_.ConfigureTimeout(std::chrono::seconds(0), []() {
109 bool connection_timeout_cleared = false;
110 ASSERT_TRUE(connection_timeout_cleared);
111 });
112
113 ALOGD("%s: 3", __func__);
114 async_fd_watcher_.WatchFdForNonBlockingReads(
115 connection_fd, [this](int fd) { ReadIncomingMessage(fd); });
116
117 // Time out if it takes longer than a second.
118 SetTimeout(std::chrono::seconds(1));
119 });
120 conn_watcher_.ConfigureTimeout(std::chrono::seconds(1), []() {
121 bool connection_timeout = true;
122 ASSERT_FALSE(connection_timeout);
123 });
124 }
125
CleanUpServer()126 void CleanUpServer() {
127 async_fd_watcher_.StopWatchingFileDescriptors();
128 conn_watcher_.StopWatchingFileDescriptors();
129 close(socket_fd_);
130 }
131
TearDown()132 void TearDown() override {
133 ALOGD("%s 3", __func__);
134 EXPECT_TRUE(CheckBufferEquals());
135 }
136
OnTimeout()137 void OnTimeout() {
138 ALOGD("%s", __func__);
139 timed_out_ = true;
140 }
141
ClearTimeout()142 void ClearTimeout() {
143 ALOGD("%s", __func__);
144 timed_out_ = false;
145 }
146
TimedOut()147 bool TimedOut() {
148 ALOGD("%s %d", __func__, timed_out_ ? 1 : 0);
149 return timed_out_;
150 }
151
SetTimeout(std::chrono::milliseconds timeout_ms)152 void SetTimeout(std::chrono::milliseconds timeout_ms) {
153 ALOGD("%s", __func__);
154 async_fd_watcher_.ConfigureTimeout(timeout_ms, [this]() { OnTimeout(); });
155 ClearTimeout();
156 }
157
ConnectClient()158 int ConnectClient() {
159 ALOGD("%s", __func__);
160 int socket_cli_fd = socket(AF_INET, SOCK_STREAM, 0);
161 EXPECT_FALSE(socket_cli_fd < 0);
162
163 struct sockaddr_in serv_addr;
164 memset((void*)&serv_addr, 0, sizeof(serv_addr));
165 serv_addr.sin_family = AF_INET;
166 serv_addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
167 serv_addr.sin_port = htons(kPort);
168
169 int result =
170 connect(socket_cli_fd, (struct sockaddr*)&serv_addr, sizeof(serv_addr));
171 EXPECT_FALSE(result < 0);
172
173 return socket_cli_fd;
174 }
175
WriteFromClient(int socket_cli_fd)176 void WriteFromClient(int socket_cli_fd) {
177 ALOGD("%s", __func__);
178 strcpy(client_buffer_, "1");
179 int n = write(socket_cli_fd, client_buffer_, strlen(client_buffer_));
180 EXPECT_TRUE(n > 0);
181 }
182
AwaitServerResponse(int socket_cli_fd)183 void AwaitServerResponse(int socket_cli_fd) {
184 ALOGD("%s", __func__);
185 int n = read(socket_cli_fd, client_buffer_, 1);
186 ALOGD("%s done", __func__);
187 EXPECT_TRUE(n > 0);
188 }
189
190 private:
191 AsyncFdWatcher async_fd_watcher_;
192 AsyncFdWatcher conn_watcher_;
193 int socket_fd_;
194 char server_buffer_[kBufferSize];
195 char client_buffer_[kBufferSize];
196 bool timed_out_;
197 };
198
199 // Use a single AsyncFdWatcher to signal a connection to the server socket.
TEST_F(AsyncFdWatcherSocketTest,Connect)200 TEST_F(AsyncFdWatcherSocketTest, Connect) {
201 int socket_fd = StartServer();
202
203 AsyncFdWatcher conn_watcher;
204 conn_watcher.WatchFdForNonBlockingReads(socket_fd, [this](int fd) {
205 int connection_fd = AcceptConnection(fd);
206 close(connection_fd);
207 });
208
209 // Fail if the client doesn't connect within 1 second.
210 conn_watcher.ConfigureTimeout(std::chrono::seconds(1), []() {
211 bool connection_timeout = true;
212 ASSERT_FALSE(connection_timeout);
213 });
214
215 ConnectClient();
216 conn_watcher.StopWatchingFileDescriptors();
217 close(socket_fd);
218 }
219
220 // Use a single AsyncFdWatcher to signal a connection to the server socket.
TEST_F(AsyncFdWatcherSocketTest,TimedOutConnect)221 TEST_F(AsyncFdWatcherSocketTest, TimedOutConnect) {
222 int socket_fd = StartServer();
223 bool timed_out = false;
224 bool* timeout_ptr = &timed_out;
225
226 AsyncFdWatcher conn_watcher;
227 conn_watcher.WatchFdForNonBlockingReads(socket_fd, [this](int fd) {
228 int connection_fd = AcceptConnection(fd);
229 close(connection_fd);
230 });
231
232 // Set the timeout flag after 100ms.
233 conn_watcher.ConfigureTimeout(std::chrono::milliseconds(100),
234 [timeout_ptr]() { *timeout_ptr = true; });
235 EXPECT_FALSE(timed_out);
236 sleep(1);
237 EXPECT_TRUE(timed_out);
238 conn_watcher.StopWatchingFileDescriptors();
239 close(socket_fd);
240 }
241
242 // Modify the timeout in a timeout callback.
TEST_F(AsyncFdWatcherSocketTest,TimedOutSchedulesTimeout)243 TEST_F(AsyncFdWatcherSocketTest, TimedOutSchedulesTimeout) {
244 int socket_fd = StartServer();
245 bool timed_out = false;
246 bool timed_out2 = false;
247
248 AsyncFdWatcher conn_watcher;
249 conn_watcher.WatchFdForNonBlockingReads(socket_fd, [this](int fd) {
250 int connection_fd = AcceptConnection(fd);
251 close(connection_fd);
252 });
253
254 // Set a timeout flag in each callback.
255 conn_watcher.ConfigureTimeout(std::chrono::milliseconds(500),
256 [&conn_watcher, &timed_out, &timed_out2]() {
257 timed_out = true;
258 conn_watcher.ConfigureTimeout(
259 std::chrono::seconds(1),
260 [&timed_out2]() { timed_out2 = true; });
261 });
262 EXPECT_FALSE(timed_out);
263 EXPECT_FALSE(timed_out2);
264 sleep(1);
265 EXPECT_TRUE(timed_out);
266 EXPECT_FALSE(timed_out2);
267 sleep(1);
268 EXPECT_TRUE(timed_out);
269 EXPECT_TRUE(timed_out2);
270 conn_watcher.StopWatchingFileDescriptors();
271 close(socket_fd);
272 }
273
274 // Use a single AsyncFdWatcher to watch two file descriptors.
TEST_F(AsyncFdWatcherSocketTest,WatchTwoFileDescriptors)275 TEST_F(AsyncFdWatcherSocketTest, WatchTwoFileDescriptors) {
276 int sockfd[2];
277 socketpair(AF_LOCAL, SOCK_STREAM, 0, sockfd);
278 bool cb1_called = false;
279 bool* cb1_called_ptr = &cb1_called;
280 bool cb2_called = false;
281 bool* cb2_called_ptr = &cb2_called;
282
283 AsyncFdWatcher watcher;
284 watcher.WatchFdForNonBlockingReads(sockfd[0], [cb1_called_ptr](int fd) {
285 char read_buf[1] = {0};
286 int n = TEMP_FAILURE_RETRY(read(fd, read_buf, sizeof(read_buf)));
287 ASSERT_TRUE(n == sizeof(read_buf));
288 ASSERT_TRUE(read_buf[0] == '1');
289 *cb1_called_ptr = true;
290 });
291
292 watcher.WatchFdForNonBlockingReads(sockfd[1], [cb2_called_ptr](int fd) {
293 char read_buf[1] = {0};
294 int n = TEMP_FAILURE_RETRY(read(fd, read_buf, sizeof(read_buf)));
295 ASSERT_TRUE(n == sizeof(read_buf));
296 ASSERT_TRUE(read_buf[0] == '2');
297 *cb2_called_ptr = true;
298 });
299
300 // Fail if the test doesn't pass within 3 seconds
301 watcher.ConfigureTimeout(std::chrono::seconds(3), []() {
302 bool connection_timeout = true;
303 ASSERT_FALSE(connection_timeout);
304 });
305
306 EXPECT_FALSE(cb1_called);
307 EXPECT_FALSE(cb2_called);
308
309 char one_buf[1] = {'1'};
310 TEMP_FAILURE_RETRY(write(sockfd[1], one_buf, sizeof(one_buf)));
311
312 sleep(1);
313
314 EXPECT_TRUE(cb1_called);
315 EXPECT_FALSE(cb2_called);
316
317 char two_buf[1] = {'2'};
318 TEMP_FAILURE_RETRY(write(sockfd[0], two_buf, sizeof(two_buf)));
319
320 sleep(1);
321
322 EXPECT_TRUE(cb1_called);
323 EXPECT_TRUE(cb2_called);
324
325 watcher.StopWatchingFileDescriptors();
326 }
327
328 // Use two AsyncFdWatchers to set up a server socket.
TEST_F(AsyncFdWatcherSocketTest,ClientServer)329 TEST_F(AsyncFdWatcherSocketTest, ClientServer) {
330 ConfigureServer();
331 int socket_cli_fd = ConnectClient();
332
333 WriteFromClient(socket_cli_fd);
334
335 AwaitServerResponse(socket_cli_fd);
336
337 close(socket_cli_fd);
338 CleanUpServer();
339 }
340
341 // Use two AsyncFdWatchers to set up a server socket, which times out.
TEST_F(AsyncFdWatcherSocketTest,TimeOutTest)342 TEST_F(AsyncFdWatcherSocketTest, TimeOutTest) {
343 ConfigureServer();
344 int socket_cli_fd = ConnectClient();
345
346 while (!TimedOut()) sleep(1);
347
348 close(socket_cli_fd);
349 CleanUpServer();
350 }
351
352 // Use two AsyncFdWatchers to set up a server socket, which times out.
TEST_F(AsyncFdWatcherSocketTest,RepeatedTimeOutTest)353 TEST_F(AsyncFdWatcherSocketTest, RepeatedTimeOutTest) {
354 ConfigureServer();
355 int socket_cli_fd = ConnectClient();
356 ClearTimeout();
357
358 // Time out when there are no writes.
359 EXPECT_FALSE(TimedOut());
360 sleep(2);
361 EXPECT_TRUE(TimedOut());
362 ClearTimeout();
363
364 // Don't time out when there is a write.
365 WriteFromClient(socket_cli_fd);
366 AwaitServerResponse(socket_cli_fd);
367 EXPECT_FALSE(TimedOut());
368 ClearTimeout();
369
370 // Time out when the write is late.
371 sleep(2);
372 WriteFromClient(socket_cli_fd);
373 AwaitServerResponse(socket_cli_fd);
374 EXPECT_TRUE(TimedOut());
375 ClearTimeout();
376
377 // Time out when there is a pause after a write.
378 WriteFromClient(socket_cli_fd);
379 sleep(2);
380 AwaitServerResponse(socket_cli_fd);
381 EXPECT_TRUE(TimedOut());
382 ClearTimeout();
383
384 close(socket_cli_fd);
385 CleanUpServer();
386 }
387
388 } // namespace implementation
389 } // namespace V1_0
390 } // namespace bluetooth
391 } // namespace hardware
392 } // namespace android
393