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 struct ConnectData {
     26   bool (*callback_fn)(int);
     27   const char* sock_path;
     28   ConnectData(bool (*callback_func)(int), const char* socket_path)
     29    : callback_fn(callback_func), sock_path(socket_path) {}
     30 };
     31 
     32 static void* ConnectFn(void* data) {
     33   ConnectData* pdata = reinterpret_cast<ConnectData*>(data);
     34   bool (*callback_fn)(int) = pdata->callback_fn;
     35   void* return_value = NULL;
     36 
     37   int fd = socket(PF_UNIX, SOCK_SEQPACKET | SOCK_CLOEXEC | SOCK_NONBLOCK, 0);
     38   if (fd < 0) {
     39     GTEST_LOG_(ERROR) << "socket call failed: " << strerror(errno);
     40     return reinterpret_cast<void*>(-1);
     41   }
     42 
     43   struct sockaddr_un addr;
     44   memset(&addr, 0, sizeof(addr));
     45   addr.sun_family = AF_UNIX;
     46   addr.sun_path[0] = '\0';
     47   strcpy(addr.sun_path + 1, pdata->sock_path);
     48 
     49   if (connect(fd, reinterpret_cast<struct sockaddr*>(&addr), sizeof(addr)) < 0) {
     50     GTEST_LOG_(ERROR) << "connect call failed: " << strerror(errno);
     51     return_value = reinterpret_cast<void*>(-1);
     52   }
     53   else if (callback_fn != NULL && !callback_fn(fd)) {
     54     return_value = reinterpret_cast<void*>(-1);
     55   }
     56 
     57   close(fd);
     58 
     59   return return_value;
     60 }
     61 
     62 static void RunTest(void (*test_fn)(struct sockaddr_un*, int),
     63                     bool (*callback_fn)(int fd), const char* sock_path) {
     64   int fd = socket(PF_UNIX, SOCK_SEQPACKET, 0);
     65   ASSERT_NE(fd, -1) << strerror(errno);
     66 
     67   struct sockaddr_un addr;
     68   memset(&addr, 0, sizeof(addr));
     69   addr.sun_family = AF_UNIX;
     70   addr.sun_path[0] = '\0';
     71   strcpy(addr.sun_path + 1, sock_path);
     72 
     73   ASSERT_NE(-1, bind(fd, reinterpret_cast<struct sockaddr*>(&addr), sizeof(addr))) << strerror(errno);
     74 
     75   ASSERT_NE(-1, listen(fd, 1)) << strerror(errno);
     76 
     77   ConnectData connect_data(callback_fn, sock_path);
     78 
     79   pthread_t thread;
     80   ASSERT_EQ(0, pthread_create(&thread, NULL, ConnectFn, &connect_data));
     81 
     82   fd_set read_set;
     83   FD_ZERO(&read_set);
     84   FD_SET(fd, &read_set);
     85   timeval tv;
     86   tv.tv_sec = 5;
     87   tv.tv_usec = 0;
     88   ASSERT_LT(0, select(fd+1, &read_set, NULL, NULL, &tv));
     89 
     90   test_fn(&addr, fd);
     91 
     92   void* ret_val;
     93   ASSERT_EQ(0, pthread_join(thread, &ret_val));
     94   ASSERT_EQ(NULL, ret_val);
     95 
     96   close(fd);
     97 }
     98 
     99 TEST(sys_socket, accept4_error) {
    100   ASSERT_EQ(-1, accept4(-1, NULL, NULL, 0));
    101   ASSERT_EQ(EBADF, errno);
    102 }
    103 
    104 static void TestAccept4(struct sockaddr_un* addr, int fd) {
    105   socklen_t len = sizeof(*addr);
    106   int fd_acc = accept4(fd, reinterpret_cast<struct sockaddr*>(addr), &len, SOCK_CLOEXEC);
    107   ASSERT_NE(fd_acc, -1) << strerror(errno);
    108 
    109   // Check that the flag was set properly.
    110   ASSERT_EQ(FD_CLOEXEC, fcntl(fd_acc, F_GETFD) & FD_CLOEXEC);
    111 
    112   close(fd_acc);
    113 }
    114 
    115 TEST(sys_socket, accept4_smoke) {
    116   RunTest(TestAccept4, NULL, "test_accept");
    117 }
    118 
    119 const char* g_RecvMsgs[] = {
    120   "RECVMMSG_ONE",
    121   "RECVMMSG_TWO",
    122   "RECVMMSG_THREE",
    123 };
    124 #define NUM_RECV_MSGS (sizeof(g_RecvMsgs)/sizeof(const char*))
    125 
    126 static bool SendMultiple(int fd) {
    127   for (size_t i = 0; i < NUM_RECV_MSGS; i++) {
    128     if (send(fd, g_RecvMsgs[i], strlen(g_RecvMsgs[i]) + 1, 0) < 0) {
    129       GTEST_LOG_(ERROR) << "send call failed: " << strerror(errno);
    130       return false;
    131     }
    132   }
    133 
    134   return true;
    135 }
    136 
    137 static void TestRecvMMsg(struct sockaddr_un *addr, int fd) {
    138   socklen_t len = sizeof(*addr);
    139   int fd_acc = accept(fd, reinterpret_cast<struct sockaddr*>(addr), &len);
    140   ASSERT_NE(fd_acc, -1) << strerror(errno);
    141 
    142   struct mmsghdr msgs[NUM_RECV_MSGS];
    143   memset(msgs, 0, sizeof(struct mmsghdr)*NUM_RECV_MSGS);
    144 
    145   struct iovec io[NUM_RECV_MSGS];
    146   char bufs[NUM_RECV_MSGS][100];
    147   for (size_t i = 0; i < NUM_RECV_MSGS; i++) {
    148     io[i].iov_base = reinterpret_cast<void*>(bufs[i]);
    149     io[i].iov_len = strlen(g_RecvMsgs[i]) + 1;
    150 
    151     msgs[i].msg_hdr.msg_iov = &io[i];
    152     msgs[i].msg_hdr.msg_iovlen = 1;
    153     msgs[i].msg_len = sizeof(struct msghdr);
    154   }
    155 
    156   struct timespec ts;
    157   memset(&ts, 0, sizeof(ts));
    158   ts.tv_sec = 5;
    159   ts.tv_nsec = 0;
    160   ASSERT_EQ(NUM_RECV_MSGS,
    161             static_cast<size_t>(recvmmsg(fd_acc, msgs, NUM_RECV_MSGS, 0, &ts)))
    162            << strerror(errno);
    163   for (size_t i = 0; i < NUM_RECV_MSGS; i++) {
    164     ASSERT_STREQ(g_RecvMsgs[i], bufs[i]);
    165   }
    166 
    167   close(fd_acc);
    168 }
    169 
    170 TEST(sys_socket, recvmmsg_smoke) {
    171   RunTest(TestRecvMMsg, SendMultiple, "test_revmmsg");
    172 }
    173 
    174 TEST(sys_socket, recvmmsg_error) {
    175   ASSERT_EQ(-1, recvmmsg(-1, NULL, 0, 0, NULL));
    176   ASSERT_EQ(EBADF, errno);
    177 }
    178 
    179 const char* g_SendMsgs[] = {
    180   "MSG_ONE",
    181   "MSG_TWO",
    182   "MSG_THREE"
    183 };
    184 #define NUM_SEND_MSGS (sizeof(g_SendMsgs)/sizeof(const char*))
    185 
    186 static bool SendMMsg(int fd) {
    187   struct mmsghdr msgs[NUM_SEND_MSGS];
    188   memset(msgs, 0, sizeof(struct mmsghdr)*NUM_SEND_MSGS);
    189   struct iovec io[NUM_SEND_MSGS];
    190   for (size_t i = 0; i < NUM_SEND_MSGS; i++) {
    191     io[i].iov_base = reinterpret_cast<void*>(const_cast<char*>(g_SendMsgs[i]));
    192     io[i].iov_len = strlen(g_SendMsgs[i]) + 1;
    193     msgs[i].msg_hdr.msg_iov = &io[i];
    194     msgs[i].msg_hdr.msg_iovlen = 1;
    195     msgs[i].msg_len = sizeof(struct msghdr);
    196   }
    197 
    198   if (sendmmsg(fd, msgs, NUM_SEND_MSGS, 0) < 0) {
    199     GTEST_LOG_(ERROR) << "sendmmsg call failed: " << strerror(errno);
    200     return false;
    201   }
    202   return true;
    203 }
    204 
    205 static void TestSendMMsg(struct sockaddr_un *addr, int fd) {
    206   socklen_t len = sizeof(*addr);
    207   int fd_acc = accept(fd, reinterpret_cast<struct sockaddr*>(addr), &len);
    208   ASSERT_NE(fd_acc, -1) << strerror(errno);
    209 
    210   fd_set read_set;
    211   FD_ZERO(&read_set);
    212   FD_SET(fd_acc, &read_set);
    213 
    214   for (size_t i = 0; i < NUM_SEND_MSGS; i++) {
    215     timeval tv;
    216     tv.tv_sec = 5;
    217     tv.tv_usec = 0;
    218     ASSERT_LT(0, select(fd_acc+1, &read_set, NULL, NULL, &tv));
    219     char buffer[100];
    220     ASSERT_EQ(strlen(g_SendMsgs[i]) + 1,
    221               static_cast<size_t>(recv(fd_acc, buffer, sizeof(buffer), 0)));
    222     ASSERT_STREQ(g_SendMsgs[i], buffer);
    223   }
    224 
    225   close(fd_acc);
    226 }
    227 
    228 TEST(sys_socket, sendmmsg_smoke) {
    229   RunTest(TestSendMMsg, SendMMsg, "test_sendmmsg");
    230 }
    231 
    232 TEST(sys_socket, sendmmsg_error) {
    233   ASSERT_EQ(-1, sendmmsg(-1, NULL, 0, 0));
    234   ASSERT_EQ(EBADF, errno);
    235 }
    236