Home | History | Annotate | Download | only in test
      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