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