1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
8 #include <netinet/in.h>
10 #include <sys/types.h>
11 #include <sys/socket.h>
17 #include "echo_server.h"
18 #include "gmock/gmock.h"
19 #include "gtest/gtest.h"
20 #include "nacl_io/kernel_intercept.h"
21 #include "nacl_io/kernel_proxy.h"
22 #include "nacl_io/ossocket.h"
23 #include "nacl_io/ostypes.h"
24 #include "ppapi/cpp/message_loop.h"
25 #include "ppapi_simple/ps.h"
27 #ifdef PROVIDES_SOCKET_API
29 using namespace nacl_io;
30 using namespace sdk_util;
32 #define LOCAL_HOST 0x7F000001
39 void IP4ToSockAddr(uint32_t ip, uint16_t port, struct sockaddr_in* addr) {
40 memset(addr, 0, sizeof(*addr));
42 addr->sin_family = AF_INET;
43 addr->sin_port = htons(port);
44 addr->sin_addr.s_addr = htonl(ip);
47 void SetNonBlocking(int sock) {
48 int flags = fcntl(sock, F_GETFL);
51 ASSERT_EQ(0, fcntl(sock, F_SETFL, flags));
52 ASSERT_EQ(flags, fcntl(sock, F_GETFL));
55 class SocketTest : public ::testing::Test {
57 SocketTest() : sock1_(-1), sock2_(-1) {}
61 EXPECT_EQ(0, close(sock1_));
63 EXPECT_EQ(0, close(sock2_));
66 int Bind(int fd, uint32_t ip, uint16_t port) {
68 socklen_t addrlen = sizeof(addr);
70 IP4ToSockAddr(ip, port, &addr);
71 int err = bind(fd, (sockaddr*)&addr, addrlen);
83 class SocketTestUDP : public SocketTest {
88 sock1_ = socket(AF_INET, SOCK_DGRAM, 0);
89 sock2_ = socket(AF_INET, SOCK_DGRAM, 0);
91 EXPECT_GT(sock1_, -1);
92 EXPECT_GT(sock2_, -1);
96 class SocketTestTCP : public SocketTest {
101 sock1_ = socket(AF_INET, SOCK_STREAM, 0);
102 sock2_ = socket(AF_INET, SOCK_STREAM, 0);
104 EXPECT_GT(sock1_, -1);
105 EXPECT_GT(sock2_, -1);
109 class SocketTestWithServer : public ::testing::Test {
111 SocketTestWithServer() : instance_(PSGetInstanceId()) {
112 pthread_mutex_init(&ready_lock_, NULL);
113 pthread_cond_init(&ready_cond_, NULL);
116 void ServerThreadMain() {
117 loop_.AttachToCurrentThread();
118 pp::Instance instance(PSGetInstanceId());
119 EchoServer server(&instance, PORT1, ServerLog, &ready_cond_, &ready_lock_);
123 static void* ServerThreadMainStatic(void* arg) {
124 SocketTestWithServer* test = (SocketTestWithServer*)arg;
125 test->ServerThreadMain();
130 loop_ = pp::MessageLoop(&instance_);
131 pthread_mutex_lock(&ready_lock_);
133 // Start an echo server on a background thread.
134 pthread_create(&server_thread_, NULL, ServerThreadMainStatic, this);
136 // Wait for thread to signal that it is ready to accept connections.
137 pthread_cond_wait(&ready_cond_, &ready_lock_);
138 pthread_mutex_unlock(&ready_lock_);
140 sock_ = socket(AF_INET, SOCK_STREAM, 0);
141 EXPECT_GT(sock_, -1);
145 // Stop the echo server and the background thread it runs on
146 loop_.PostQuit(true);
147 pthread_join(server_thread_, NULL);
148 ASSERT_EQ(0, close(sock_));
151 static void ServerLog(const char* msg) {
152 // Uncomment to see logs of echo server on stdout
153 //printf("server: %s\n", msg);
158 pp::MessageLoop loop_;
159 pp::Instance instance_;
160 pthread_cond_t ready_cond_;
161 pthread_mutex_t ready_lock_;
162 pthread_t server_thread_;
167 TEST(SocketTestSimple, Socket) {
168 EXPECT_EQ(-1, socket(AF_UNIX, SOCK_STREAM, 0));
169 EXPECT_EQ(errno, EAFNOSUPPORT);
170 EXPECT_EQ(-1, socket(AF_INET, SOCK_RAW, 0));
171 EXPECT_EQ(errno, EPROTONOSUPPORT);
173 int sock1_ = socket(AF_INET, SOCK_DGRAM, 0);
174 EXPECT_NE(-1, sock1_);
176 int sock2_ = socket(AF_INET6, SOCK_DGRAM, 0);
177 EXPECT_NE(-1, sock2_);
179 int sock3 = socket(AF_INET, SOCK_STREAM, 0);
180 EXPECT_NE(-1, sock3);
182 int sock4 = socket(AF_INET6, SOCK_STREAM, 0);
183 EXPECT_NE(-1, sock4);
191 TEST_F(SocketTestUDP, Bind) {
193 EXPECT_EQ(0, Bind(sock1_, LOCAL_HOST, PORT1));
195 // Invalid to rebind a socket.
196 EXPECT_EQ(EINVAL, Bind(sock1_, LOCAL_HOST, PORT1));
199 EXPECT_EQ(EADDRINUSE, Bind(sock2_, LOCAL_HOST, PORT1));
201 // Bind with a wildcard.
202 EXPECT_EQ(0, Bind(sock2_, LOCAL_HOST, ANY_PORT));
204 // Invalid to rebind after wildcard
205 EXPECT_EQ(EINVAL, Bind(sock2_, LOCAL_HOST, PORT1));
208 TEST_F(SocketTestUDP, SendRcv) {
212 memset(outbuf, 1, sizeof(outbuf));
213 memset(inbuf, 0, sizeof(inbuf));
215 EXPECT_EQ(0, Bind(sock1_, LOCAL_HOST, PORT1));
216 EXPECT_EQ(0, Bind(sock2_, LOCAL_HOST, PORT2));
219 socklen_t addrlen = sizeof(addr);
220 IP4ToSockAddr(LOCAL_HOST, PORT2, &addr);
223 sendto(sock1_, outbuf, sizeof(outbuf), 0, (sockaddr*) &addr, addrlen);
224 EXPECT_EQ(sizeof(outbuf), len1);
226 // Ensure the buffers are different
227 EXPECT_NE(0, memcmp(outbuf, inbuf, sizeof(outbuf)));
228 memset(&addr, 0, sizeof(addr));
230 // Try to receive the previously sent packet
232 recvfrom(sock2_, inbuf, sizeof(inbuf), 0, (sockaddr*) &addr, &addrlen);
233 EXPECT_EQ(sizeof(outbuf), len2);
234 EXPECT_EQ(sizeof(sockaddr_in), addrlen);
235 EXPECT_EQ(PORT1, htons(addr.sin_port));
237 // Now they should be the same
238 EXPECT_EQ(0, memcmp(outbuf, inbuf, sizeof(outbuf)));
241 const size_t kQueueSize = 65536 * 8;
242 TEST_F(SocketTestUDP, FullFifo) {
243 char outbuf[16 * 1024];
245 ASSERT_EQ(0, Bind(sock1_, LOCAL_HOST, PORT1));
246 ASSERT_EQ(0, Bind(sock2_, LOCAL_HOST, PORT2));
249 socklen_t addrlen = sizeof(addr);
250 IP4ToSockAddr(LOCAL_HOST, PORT2, &addr);
253 while (total < kQueueSize * 8) {
254 int len = sendto(sock1_, outbuf, sizeof(outbuf), MSG_DONTWAIT,
255 (sockaddr*) &addr, addrlen);
259 EXPECT_EQ(EWOULDBLOCK, errno);
264 EXPECT_EQ(sizeof(outbuf), len);
268 EXPECT_GT(total, kQueueSize - 1);
269 EXPECT_LT(total, kQueueSize * 8);
272 TEST_F(SocketTestWithServer, TCPConnect) {
276 memset(outbuf, 1, sizeof(outbuf));
279 socklen_t addrlen = sizeof(addr);
281 IP4ToSockAddr(LOCAL_HOST, PORT1, &addr);
283 ASSERT_EQ(0, connect(sock_, (sockaddr*) &addr, addrlen))
284 << "Failed with " << errno << ": " << strerror(errno) << "\n";
286 // Send two different messages to the echo server and verify the
288 strcpy(outbuf, "hello");
289 memset(inbuf, 0, sizeof(inbuf));
290 ASSERT_EQ(sizeof(outbuf), write(sock_, outbuf, sizeof(outbuf)))
291 << "socket write failed with: " << strerror(errno);
292 ASSERT_EQ(sizeof(outbuf), read(sock_, inbuf, sizeof(inbuf)));
293 EXPECT_EQ(0, memcmp(outbuf, inbuf, sizeof(outbuf)));
295 strcpy(outbuf, "world");
296 memset(inbuf, 0, sizeof(inbuf));
297 ASSERT_EQ(sizeof(outbuf), write(sock_, outbuf, sizeof(outbuf)));
298 ASSERT_EQ(sizeof(outbuf), read(sock_, inbuf, sizeof(inbuf)));
299 EXPECT_EQ(0, memcmp(outbuf, inbuf, sizeof(outbuf)));
302 TEST_F(SocketTestWithServer, TCPConnectNonBlock) {
306 memset(outbuf, 1, sizeof(outbuf));
309 socklen_t addrlen = sizeof(addr);
311 IP4ToSockAddr(LOCAL_HOST, PORT1, &addr);
313 SetNonBlocking(sock_);
314 ASSERT_EQ(-1, connect(sock_, (sockaddr*) &addr, addrlen));
315 ASSERT_EQ(EINPROGRESS, errno)
316 << "expected EINPROGRESS but got: " << strerror(errno) << "\n";
317 ASSERT_EQ(-1, connect(sock_, (sockaddr*) &addr, addrlen));
318 ASSERT_EQ(EALREADY, errno);
320 // Wait for the socket connection to complete using poll()
321 struct pollfd pollfd = { sock_, POLLIN|POLLOUT, 0 };
322 ASSERT_EQ(1, poll(&pollfd, 1, -1));
323 ASSERT_EQ(POLLOUT, pollfd.revents);
325 // Attempts to connect again should yield EISCONN
326 ASSERT_EQ(-1, connect(sock_, (sockaddr*) &addr, addrlen));
327 ASSERT_EQ(EISCONN, errno);
329 // And SO_ERROR should be 0.
332 TEST_F(SocketTest, Getsockopt) {
333 sock1_ = socket(AF_INET, SOCK_STREAM, 0);
334 EXPECT_GT(sock1_, -1);
335 int socket_error = 99;
336 socklen_t len = sizeof(socket_error);
338 // Test for valid option (SO_ERROR) which should be 0 when a socket
340 ASSERT_EQ(0, getsockopt(sock1_, SOL_SOCKET, SO_ERROR, &socket_error, &len));
341 ASSERT_EQ(0, socket_error);
342 ASSERT_EQ(sizeof(socket_error), len);
344 // Test for an invalid option (-1)
345 ASSERT_EQ(-1, getsockopt(sock1_, SOL_SOCKET, -1, &socket_error, &len));
346 ASSERT_EQ(ENOPROTOOPT, errno);
349 TEST_F(SocketTest, Setsockopt) {
350 sock1_ = socket(AF_INET, SOCK_STREAM, 0);
351 EXPECT_GT(sock1_, -1);
353 // It should not be possible to set SO_ERROR using setsockopt.
354 int socket_error = 10;
355 socklen_t len = sizeof(socket_error);
356 ASSERT_EQ(-1, setsockopt(sock1_, SOL_SOCKET, SO_ERROR, &socket_error, len));
357 ASSERT_EQ(ENOPROTOOPT, errno);
361 TEST_F(SocketTest, Sockopt_KEEPALIVE) {
362 sock1_ = socket(AF_INET, SOCK_STREAM, 0);
363 ASSERT_GT(sock1_, -1);
364 sock2_ = socket(AF_INET, SOCK_DGRAM, 0);
365 ASSERT_GT(sock2_, -1);
368 socklen_t len = sizeof(value);
369 ASSERT_EQ(0, getsockopt(sock1_, SOL_SOCKET, SO_KEEPALIVE, &value, &len));
371 ASSERT_EQ(sizeof(int), len);
374 // Disabled until we support SO_LINGER (i.e. syncronouse close()/shutdown())
375 // TODO(sbc): re-enable once we fix http://crbug.com/312401
376 TEST_F(SocketTest, DISABLED_Sockopt_LINGER) {
377 sock1_ = socket(AF_INET, SOCK_STREAM, 0);
378 ASSERT_GT(sock1_, -1);
379 sock2_ = socket(AF_INET, SOCK_DGRAM, 0);
380 ASSERT_GT(sock2_, -1);
382 struct linger linger = { 7, 8 };
383 socklen_t len = sizeof(linger);
384 ASSERT_EQ(0, getsockopt(sock1_, SOL_SOCKET, SO_LINGER, &linger, &len));
385 ASSERT_EQ(0, linger.l_onoff);
386 ASSERT_EQ(0, linger.l_linger);
387 ASSERT_EQ(sizeof(struct linger), len);
388 ASSERT_EQ(0, getsockopt(sock2_, SOL_SOCKET, SO_LINGER, &linger, &len));
389 ASSERT_EQ(0, linger.l_onoff);
390 ASSERT_EQ(0, linger.l_linger);
391 ASSERT_EQ(sizeof(struct linger), len);
394 linger.l_linger = 77;
395 len = sizeof(linger);
396 ASSERT_EQ(0, setsockopt(sock1_, SOL_SOCKET, SO_LINGER, &linger, len));
398 linger.l_linger = 88;
399 ASSERT_EQ(0, setsockopt(sock2_, SOL_SOCKET, SO_LINGER, &linger, len));
401 len = sizeof(linger);
402 ASSERT_EQ(0, getsockopt(sock1_, SOL_SOCKET, SO_LINGER, &linger, &len));
403 ASSERT_EQ(1, linger.l_onoff);
404 ASSERT_EQ(77, linger.l_linger);
405 ASSERT_EQ(sizeof(struct linger), len);
406 ASSERT_EQ(0, getsockopt(sock2_, SOL_SOCKET, SO_LINGER, &linger, &len));
407 ASSERT_EQ(1, linger.l_onoff);
408 ASSERT_EQ(88, linger.l_linger);
409 ASSERT_EQ(sizeof(struct linger), len);
412 TEST_F(SocketTest, Sockopt_REUSEADDR) {
414 socklen_t len = sizeof(value);
415 sock1_ = socket(AF_INET, SOCK_STREAM, 0);
417 ASSERT_GT(sock1_, -1);
418 ASSERT_EQ(0, setsockopt(sock1_, SOL_SOCKET, SO_REUSEADDR, &value, len));
422 ASSERT_EQ(0, getsockopt(sock1_, SOL_SOCKET, SO_REUSEADDR, &value, &len));
424 ASSERT_EQ(sizeof(int), len);
427 // The size of the data to send is deliberately chosen to be
428 // larger than the TCP buffer in nacl_io.
429 // TODO(sbc): use ioctl to discover the actual buffer size at
431 #define LARGE_SEND_BYTES (800 * 1024)
432 TEST_F(SocketTestWithServer, LargeSend) {
433 char* outbuf = (char*)malloc(LARGE_SEND_BYTES);
434 char* inbuf = (char*)malloc(LARGE_SEND_BYTES);
436 int bytes_received = 0;
438 // Fill output buffer with ascending integers
439 int* outbuf_int = (int*)outbuf;
440 int* inbuf_int = (int*)inbuf;
441 for (int i = 0; i < LARGE_SEND_BYTES/sizeof(int); i++) {
446 socklen_t addrlen = sizeof(addr);
448 IP4ToSockAddr(LOCAL_HOST, PORT1, &addr);
449 ASSERT_EQ(0, connect(sock_, (sockaddr*) &addr, addrlen))
450 << "Failed with " << errno << ": " << strerror(errno) << "\n";
452 // Call send an recv until all bytes have been transfered.
453 while (bytes_received < LARGE_SEND_BYTES) {
454 if (bytes_sent < LARGE_SEND_BYTES) {
455 int sent = send(sock_, outbuf + bytes_sent,
456 LARGE_SEND_BYTES - bytes_sent, MSG_DONTWAIT);
458 ASSERT_EQ(EWOULDBLOCK, errno) << "send failed: " << strerror(errno);
463 int received = recv(sock_, inbuf + bytes_received,
464 LARGE_SEND_BYTES - bytes_received, MSG_DONTWAIT);
466 ASSERT_EQ(EWOULDBLOCK, errno) << "recv failed: " << strerror(errno);
468 bytes_received += received;
471 // Make sure there is nothing else to recv at this point
473 ASSERT_EQ(-1, recv(sock_, dummy, 10, MSG_DONTWAIT));
474 ASSERT_EQ(EWOULDBLOCK, errno);
477 for (int i = 0; i < LARGE_SEND_BYTES/4; i++) {
478 if (inbuf_int[i] != outbuf_int[i]) {
479 printf("%d: in=%d out=%d\n", i, inbuf_int[i], outbuf_int[i]);
485 for (int i = 0; i < LARGE_SEND_BYTES; i++) {
486 ASSERT_EQ(outbuf[i], inbuf[i]) << "cmp failed at " << i;
489 ASSERT_EQ(0, memcmp(inbuf, outbuf, LARGE_SEND_BYTES));
495 TEST_F(SocketTestUDP, Listen) {
496 EXPECT_EQ(-1, listen(sock1_, 10));
497 EXPECT_EQ(errno, ENOTSUP);
500 TEST_F(SocketTestTCP, Listen) {
502 socklen_t addrlen = sizeof(addr);
504 int server_sock = sock1_;
506 // Accept before listen should fail
507 ASSERT_EQ(-1, accept(server_sock, (sockaddr*)&addr, &addrlen));
509 // Listen should fail on unbound socket
510 ASSERT_EQ(-1, listen(server_sock, 10));
513 ASSERT_EQ(0, Bind(server_sock, LOCAL_HOST, PORT1));
514 ASSERT_EQ(0, listen(server_sock, 10))
515 << "listen failed with: " << strerror(errno);
517 // Connect to listening socket
518 int client_sock = sock2_;
519 IP4ToSockAddr(LOCAL_HOST, PORT1, &addr);
520 addrlen = sizeof(addr);
521 ASSERT_EQ(0, connect(client_sock, (sockaddr*)&addr, addrlen))
522 << "Failed with " << errno << ": " << strerror(errno) << "\n";
524 ASSERT_EQ(5, send(client_sock, "hello", 5, 0));
526 // Pass in addrlen that is larger than our actual address to make
527 // sure that it is correctly set back to sizeof(sockaddr_in)
528 addrlen = sizeof(addr) + 10;
529 int new_socket = accept(server_sock, (sockaddr*)&addr, &addrlen);
530 ASSERT_GT(new_socket, -1)
531 << "accept failed with " << errno << ": " << strerror(errno) << "\n";
533 // Verify addr and addrlen were set correctly
534 ASSERT_EQ(addrlen, sizeof(sockaddr_in));
535 sockaddr_in client_addr;
536 ASSERT_EQ(0, getsockname(client_sock, (sockaddr*)&client_addr, &addrlen));
537 ASSERT_EQ(client_addr.sin_family, addr.sin_family);
538 ASSERT_EQ(client_addr.sin_port, addr.sin_port);
539 ASSERT_EQ(client_addr.sin_addr.s_addr, addr.sin_addr.s_addr);
542 ASSERT_EQ(5, recv(new_socket, inbuf, 5, 0));
543 ASSERT_EQ(0, close(new_socket));
546 TEST_F(SocketTestTCP, ListenNonBlocking) {
547 int server_sock = sock1_;
550 SetNonBlocking(server_sock);
553 ASSERT_EQ(0, Bind(server_sock, LOCAL_HOST, PORT1));
554 ASSERT_EQ(0, listen(server_sock, 10))
555 << "listen failed with: " << strerror(errno);
557 // Accept should fail with EAGAIN since there is no incomming
560 socklen_t addrlen = sizeof(addr);
561 ASSERT_EQ(-1, accept(server_sock, (sockaddr*)&addr, &addrlen));
562 ASSERT_EQ(EAGAIN, errno);
564 // If we poll the listening socket it should also return
565 // not readable to indicate that no connections are available
567 struct pollfd pollfd = { server_sock, POLLIN|POLLOUT, 0 };
568 ASSERT_EQ(0, poll(&pollfd, 1, 0));
570 // Connect to listening socket
571 int client_sock = sock2_;
572 IP4ToSockAddr(LOCAL_HOST, PORT1, &addr);
573 addrlen = sizeof(addr);
574 ASSERT_EQ(0, connect(client_sock, (sockaddr*)&addr, addrlen))
575 << "Failed with " << errno << ": " << strerror(errno) << "\n";
577 // Not poll again but with an infintie timeout.
578 pollfd.fd = server_sock;
579 pollfd.events = POLLIN | POLLOUT;
580 ASSERT_EQ(1, poll(&pollfd, 1, -1));
582 // Now non-blocking accept should return the new socket
583 int new_socket = accept(server_sock, (sockaddr*)&addr, &addrlen);
584 ASSERT_NE(-1, new_socket)
585 << "accept failed with: " << strerror(errno) << "\n";
586 ASSERT_EQ(0, close(new_socket));
588 // Accept calls should once again fail with EAGAIN
589 ASSERT_EQ(-1, accept(server_sock, (sockaddr*)&addr, &addrlen));
590 ASSERT_EQ(EAGAIN, errno);
592 // As should polling the listening socket
593 pollfd.fd = server_sock;
594 pollfd.events = POLLIN | POLLOUT;
595 ASSERT_EQ(0, poll(&pollfd, 1, 0));
598 TEST_F(SocketTestTCP, SendRecvAfterRemoteShutdown) {
600 socklen_t addrlen = sizeof(addr);
602 int server_sock = sock1_;
603 int client_sock = sock2_;
606 ASSERT_EQ(0, Bind(server_sock, LOCAL_HOST, PORT1));
607 ASSERT_EQ(0, listen(server_sock, 10))
608 << "listen failed with: " << strerror(errno);
610 // connect to listening socket
611 IP4ToSockAddr(LOCAL_HOST, PORT1, &addr);
612 ASSERT_EQ(0, connect(client_sock, (sockaddr*)&addr, addrlen))
613 << "Failed with " << errno << ": " << strerror(errno) << "\n";
615 addrlen = sizeof(addr);
616 int new_sock = accept(server_sock, (sockaddr*)&addr, &addrlen);
617 ASSERT_NE(-1, new_sock);
619 const char* send_buf = "hello world";
620 ASSERT_EQ(strlen(send_buf), send(new_sock, send_buf, strlen(send_buf), 0));
622 // Recv first 10 bytes
624 ASSERT_EQ(10, recv(client_sock, buf, 10, 0));
626 // Close the new socket
627 ASSERT_EQ(0, close(new_sock));
630 int bytes_remaining = strlen(send_buf) - 10;
631 ASSERT_EQ(bytes_remaining, recv(client_sock, buf, 256, 0));
633 // Attempt to read/write after remote shutdown, with no bytes remainging
634 ASSERT_EQ(0, recv(client_sock, buf, 10, 0));
635 ASSERT_EQ(0, recv(client_sock, buf, 10, 0));
636 ASSERT_EQ(-1, send(client_sock, buf, 10, 0));
637 ASSERT_EQ(errno, EPIPE);
640 TEST_F(SocketTestTCP, SendRecvAfterLocalShutdown) {
642 socklen_t addrlen = sizeof(addr);
644 int server_sock = sock1_;
645 int client_sock = sock2_;
648 ASSERT_EQ(0, Bind(server_sock, LOCAL_HOST, PORT1));
649 ASSERT_EQ(0, listen(server_sock, 10))
650 << "listen failed with: " << strerror(errno);
652 // connect to listening socket
653 IP4ToSockAddr(LOCAL_HOST, PORT1, &addr);
654 ASSERT_EQ(0, connect(client_sock, (sockaddr*)&addr, addrlen))
655 << "Failed with " << errno << ": " << strerror(errno) << "\n";
657 addrlen = sizeof(addr);
658 int new_sock = accept(server_sock, (sockaddr*)&addr, &addrlen);
659 ASSERT_NE(-1, new_sock);
661 // Close the new socket
662 ASSERT_EQ(0, shutdown(client_sock, SHUT_RDWR));
664 // Attempt to read/write after shutdown
666 ASSERT_EQ(0, recv(client_sock, buffer, sizeof(buffer), 0));
667 ASSERT_EQ(-1, send(client_sock, buffer, sizeof(buffer), 0));
668 ASSERT_EQ(errno, EPIPE);
671 #define SEND_BYTES (1024)
672 TEST_F(SocketTestTCP, SendBufferedDataAfterShutdown) {
674 socklen_t addrlen = sizeof(addr);
676 int server_sock = sock1_;
677 int client_sock = sock2_;
680 ASSERT_EQ(0, Bind(server_sock, LOCAL_HOST, PORT1));
681 ASSERT_EQ(0, listen(server_sock, 10))
682 << "listen failed with: " << strerror(errno);
684 // connect to listening socket
685 IP4ToSockAddr(LOCAL_HOST, PORT1, &addr);
686 ASSERT_EQ(0, connect(client_sock, (sockaddr*)&addr, addrlen))
687 << "Failed with " << errno << ": " << strerror(errno) << "\n";
689 addrlen = sizeof(addr);
690 int new_sock = accept(server_sock, (sockaddr*)&addr, &addrlen);
691 ASSERT_NE(-1, new_sock);
693 // send a fairly large amount of data and immediately close
695 void* buffer = alloca(SEND_BYTES);
696 ASSERT_EQ(SEND_BYTES, send(client_sock, buffer, SEND_BYTES, 0));
697 ASSERT_EQ(0, close(client_sock));
699 // avoid double close of sock2_
702 // Attempt to recv() all the sent data. None should be lost.
703 int remainder = SEND_BYTES;
704 while (remainder > 0) {
705 int rtn = recv(new_sock, buffer, remainder, 0);
710 ASSERT_EQ(0, close(new_sock));
713 #endif // PROVIDES_SOCKET_API