Home | History | Annotate | Download | only in tests
      1 /*
      2  * Copyright (C) 2014 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 <gtest/gtest.h>
     18 
     19 #include <errno.h>
     20 #include <sys/types.h>
     21 #include <sys/socket.h>
     22 #include <sys/un.h>
     23 #include <fcntl.h>
     24 
     25 #if defined(__BIONIC__)
     26   #define ACCEPT4_SUPPORTED 1
     27   #define RECVMMSG_SUPPORTED 1
     28   #define SENDMMSG_SUPPORTED 1
     29 #elif defined(__GLIBC_PREREQ)
     30   #if __GLIBC_PREREQ(2, 9)
     31     #define ACCEPT4_SUPPORTED 1
     32   #endif
     33   #if __GLIBC_PREREQ(2, 12)
     34     #define RECVMMSG_SUPPORTED 1
     35   #endif
     36   #if __GLIBC_PREREQ(2, 14)
     37     #define SENDMMSG_SUPPORTED 1
     38   #endif
     39 #endif
     40 
     41 #if defined(ACCEPT4_SUPPORTED) || defined(RECVMMSG_SUPPORTED) || defined(SENDMMSG_SUPPORTED)
     42 
     43 #define SOCK_PATH "test"
     44 
     45 static void* ConnectFn(void* data) {
     46   bool (*callback_fn)(int) = reinterpret_cast<bool (*)(int)>(data);
     47   void* return_value = NULL;
     48 
     49   int fd = socket(PF_UNIX, SOCK_SEQPACKET | SOCK_CLOEXEC | SOCK_NONBLOCK, 0);
     50   if (fd < 0) {
     51     GTEST_LOG_(ERROR) << "socket call failed: " << strerror(errno);
     52     return reinterpret_cast<void*>(-1);
     53   }
     54 
     55   struct sockaddr_un addr;
     56   memset(&addr, 0, sizeof(addr));
     57   addr.sun_family = AF_UNIX;
     58   addr.sun_path[0] = '\0';
     59   strcpy(addr.sun_path + 1, SOCK_PATH);
     60 
     61   if (connect(fd, reinterpret_cast<struct sockaddr*>(&addr), sizeof(addr)) < 0) {
     62     GTEST_LOG_(ERROR) << "connect call failed: " << strerror(errno);
     63     return_value = reinterpret_cast<void*>(-1);
     64   }
     65   else if (callback_fn != NULL && !callback_fn(fd)) {
     66     return_value = reinterpret_cast<void*>(-1);
     67   }
     68 
     69   close(fd);
     70 
     71   return return_value;
     72 }
     73 
     74 static void RunTest(void (*test_fn)(struct sockaddr_un*, int),
     75                     bool (*callback_fn)(int fd)) {
     76   int fd = socket(PF_UNIX, SOCK_SEQPACKET, 0);
     77   ASSERT_NE(fd, -1) << strerror(errno);
     78 
     79   struct sockaddr_un addr;
     80   memset(&addr, 0, sizeof(addr));
     81   addr.sun_family = AF_UNIX;
     82   addr.sun_path[0] = '\0';
     83   strcpy(addr.sun_path + 1, SOCK_PATH);
     84 
     85   ASSERT_NE(-1, bind(fd, reinterpret_cast<struct sockaddr*>(&addr), sizeof(addr))) << strerror(errno);
     86 
     87   ASSERT_NE(-1, listen(fd, 1)) << strerror(errno);
     88 
     89   pthread_t thread;
     90   ASSERT_EQ(0, pthread_create(&thread, NULL, ConnectFn, reinterpret_cast<void*>(callback_fn)));
     91 
     92   fd_set read_set;
     93   FD_ZERO(&read_set);
     94   FD_SET(fd, &read_set);
     95   timeval tv;
     96   tv.tv_sec = 5;
     97   tv.tv_usec = 0;
     98   ASSERT_LT(0, select(fd+1, &read_set, NULL, NULL, &tv));
     99 
    100   test_fn(&addr, fd);
    101 
    102   void* ret_val;
    103   ASSERT_EQ(0, pthread_join(thread, &ret_val));
    104   ASSERT_EQ(NULL, ret_val);
    105 
    106   close(fd);
    107 }
    108 #endif
    109 
    110 TEST(sys_socket, accept4_error) {
    111 #if defined(ACCEPT4_SUPPORTED)
    112   ASSERT_EQ(-1, accept4(-1, NULL, NULL, 0));
    113   ASSERT_EQ(EBADF, errno);
    114 #else
    115   GTEST_LOG_(INFO) << "This test does nothing.\n";
    116 #endif
    117 }
    118 
    119 #if defined(ACCEPT4_SUPPORTED)
    120 static void TestAccept4(struct sockaddr_un* addr, int fd) {
    121   socklen_t len = sizeof(*addr);
    122   int fd_acc = accept4(fd, reinterpret_cast<struct sockaddr*>(addr), &len, SOCK_CLOEXEC);
    123   ASSERT_NE(fd_acc, -1) << strerror(errno);
    124 
    125   // Check that the flag was set properly.
    126   ASSERT_EQ(FD_CLOEXEC, fcntl(fd_acc, F_GETFD) & FD_CLOEXEC);
    127 
    128   close(fd_acc);
    129 }
    130 #endif
    131 
    132 TEST(sys_socket, accept4_smoke) {
    133 #if defined(ACCEPT4_SUPPORTED)
    134   RunTest(TestAccept4, NULL);
    135 #else
    136   GTEST_LOG_(INFO) << "This test does nothing.\n";
    137 #endif
    138 }
    139 
    140 #if defined(RECVMMSG_SUPPORTED)
    141 const char* g_RecvMsgs[] = {
    142   "RECVMMSG_ONE",
    143   "RECVMMSG_TWO",
    144   "RECVMMSG_THREE",
    145 };
    146 #define NUM_RECV_MSGS (sizeof(g_RecvMsgs)/sizeof(const char*))
    147 
    148 static bool SendMultiple(int fd) {
    149   for (size_t i = 0; i < NUM_RECV_MSGS; i++) {
    150     if (send(fd, g_RecvMsgs[i], strlen(g_RecvMsgs[i]) + 1, 0) < 0) {
    151       GTEST_LOG_(ERROR) << "send call failed: " << strerror(errno);
    152       return false;
    153     }
    154   }
    155 
    156   return true;
    157 }
    158 
    159 static void TestRecvMMsg(struct sockaddr_un *addr, int fd) {
    160   socklen_t len = sizeof(*addr);
    161   int fd_acc = accept(fd, reinterpret_cast<struct sockaddr*>(addr), &len);
    162   ASSERT_NE(fd_acc, -1) << strerror(errno);
    163 
    164   struct mmsghdr msgs[NUM_RECV_MSGS];
    165   memset(msgs, 0, sizeof(struct mmsghdr)*NUM_RECV_MSGS);
    166 
    167   struct iovec io[NUM_RECV_MSGS];
    168   char bufs[NUM_RECV_MSGS][100];
    169   for (size_t i = 0; i < NUM_RECV_MSGS; i++) {
    170     io[i].iov_base = reinterpret_cast<void*>(bufs[i]);
    171     io[i].iov_len = strlen(g_RecvMsgs[i]) + 1;
    172 
    173     msgs[i].msg_hdr.msg_iov = &io[i];
    174     msgs[i].msg_hdr.msg_iovlen = 1;
    175     msgs[i].msg_len = sizeof(struct msghdr);
    176   }
    177 
    178   struct timespec ts;
    179   memset(&ts, 0, sizeof(ts));
    180   ts.tv_sec = 5;
    181   ts.tv_nsec = 0;
    182   ASSERT_EQ(NUM_RECV_MSGS,
    183             static_cast<size_t>(recvmmsg(fd_acc, msgs, NUM_RECV_MSGS, 0, &ts)))
    184            << strerror(errno);
    185   for (size_t i = 0; i < NUM_RECV_MSGS; i++) {
    186     ASSERT_STREQ(g_RecvMsgs[i], bufs[i]);
    187   }
    188 
    189   close(fd_acc);
    190 }
    191 #endif
    192 
    193 TEST(sys_socket, recvmmsg_smoke) {
    194 #if defined(RECVMMSG_SUPPORTED)
    195   RunTest(TestRecvMMsg, SendMultiple);
    196 #else
    197   GTEST_LOG_(INFO) << "This test does nothing.\n";
    198 #endif
    199 }
    200 
    201 TEST(sys_socket, recvmmsg_error) {
    202 #if defined(RECVMMSG_SUPPORTED)
    203   ASSERT_EQ(-1, recvmmsg(-1, NULL, 0, 0, NULL));
    204   ASSERT_EQ(EBADF, errno);
    205 #else
    206   GTEST_LOG_(INFO) << "This test does nothing.\n";
    207 #endif
    208 }
    209 
    210 #if defined(SENDMMSG_SUPPORTED)
    211 const char* g_SendMsgs[] = {
    212   "MSG_ONE",
    213   "MSG_TWO",
    214   "MSG_THREE"
    215 };
    216 #define NUM_SEND_MSGS (sizeof(g_SendMsgs)/sizeof(const char*))
    217 
    218 static bool SendMMsg(int fd) {
    219   struct mmsghdr msgs[NUM_SEND_MSGS];
    220   memset(msgs, 0, sizeof(struct mmsghdr)*NUM_SEND_MSGS);
    221   struct iovec io[NUM_SEND_MSGS];
    222   for (size_t i = 0; i < NUM_SEND_MSGS; i++) {
    223     io[i].iov_base = reinterpret_cast<void*>(const_cast<char*>(g_SendMsgs[i]));
    224     io[i].iov_len = strlen(g_SendMsgs[i]) + 1;
    225     msgs[i].msg_hdr.msg_iov = &io[i];
    226     msgs[i].msg_hdr.msg_iovlen = 1;
    227     msgs[i].msg_len = sizeof(struct msghdr);
    228   }
    229 
    230   if (sendmmsg(fd, msgs, NUM_SEND_MSGS, 0) < 0) {
    231     GTEST_LOG_(ERROR) << "sendmmsg call failed: " << strerror(errno);
    232     return false;
    233   }
    234   return true;
    235 }
    236 
    237 static void TestSendMMsg(struct sockaddr_un *addr, int fd) {
    238   socklen_t len = sizeof(*addr);
    239   int fd_acc = accept(fd, reinterpret_cast<struct sockaddr*>(addr), &len);
    240   ASSERT_NE(fd_acc, -1) << strerror(errno);
    241 
    242   fd_set read_set;
    243   FD_ZERO(&read_set);
    244   FD_SET(fd_acc, &read_set);
    245 
    246   for (size_t i = 0; i < NUM_SEND_MSGS; i++) {
    247     timeval tv;
    248     tv.tv_sec = 5;
    249     tv.tv_usec = 0;
    250     ASSERT_LT(0, select(fd_acc+1, &read_set, NULL, NULL, &tv));
    251     char buffer[100];
    252     ASSERT_EQ(strlen(g_SendMsgs[i]) + 1,
    253               static_cast<size_t>(recv(fd_acc, buffer, sizeof(buffer), 0)));
    254     ASSERT_STREQ(g_SendMsgs[i], buffer);
    255   }
    256 
    257   close(fd_acc);
    258 }
    259 #endif
    260 
    261 TEST(sys_socket, sendmmsg_smoke) {
    262 #if defined(SENDMMSG_SUPPORTED)
    263   RunTest(TestSendMMsg, SendMMsg);
    264 #else
    265   GTEST_LOG_(INFO) << "This test does nothing.\n";
    266 #endif
    267 }
    268 
    269 TEST(sys_socket, sendmmsg_error) {
    270 #if defined(SENDMMSG_SUPPORTED)
    271   ASSERT_EQ(-1, sendmmsg(-1, NULL, 0, 0));
    272   ASSERT_EQ(EBADF, errno);
    273 #else
    274   GTEST_LOG_(INFO) << "This test does nothing.\n";
    275 #endif
    276 }
    277