• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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(
256       std::chrono::milliseconds(500),
257       [&conn_watcher, &timed_out, &timed_out2]() {
258         timed_out = true;
259         conn_watcher.ConfigureTimeout(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