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 45 bool CheckBufferEquals() { 46 return strcmp(server_buffer_, client_buffer_) == 0; 47 } 48 49 protected: 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 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 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 95 void SetUp() override { 96 ALOGD("%s", __func__); 97 memset(server_buffer_, 0, kBufferSize); 98 memset(client_buffer_, 0, kBufferSize); 99 } 100 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 126 void CleanUpServer() { 127 async_fd_watcher_.StopWatchingFileDescriptors(); 128 conn_watcher_.StopWatchingFileDescriptors(); 129 close(socket_fd_); 130 } 131 132 void TearDown() override { 133 ALOGD("%s 3", __func__); 134 EXPECT_TRUE(CheckBufferEquals()); 135 } 136 137 void OnTimeout() { 138 ALOGD("%s", __func__); 139 timed_out_ = true; 140 } 141 142 void ClearTimeout() { 143 ALOGD("%s", __func__); 144 timed_out_ = false; 145 } 146 147 bool TimedOut() { 148 ALOGD("%s %d", __func__, timed_out_ ? 1 : 0); 149 return timed_out_; 150 } 151 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 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 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 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. 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. 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. 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. 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. 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. 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. 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