| Index: native_client_sdk/src/tests/nacl_io_socket_test/socket_test.cc
|
| diff --git a/native_client_sdk/src/tests/nacl_io_socket_test/socket_test.cc b/native_client_sdk/src/tests/nacl_io_socket_test/socket_test.cc
|
| index dfd682ae9b0129990219e13524763fb11b68b88c..c0c8c9c6603108c8686476f1a94d32b70a47b0aa 100644
|
| --- a/native_client_sdk/src/tests/nacl_io_socket_test/socket_test.cc
|
| +++ b/native_client_sdk/src/tests/nacl_io_socket_test/socket_test.cc
|
| @@ -44,6 +44,14 @@ void IP4ToSockAddr(uint32_t ip, uint16_t port, struct sockaddr_in* addr) {
|
| addr->sin_addr.s_addr = htonl(ip);
|
| }
|
|
|
| +void SetNonBlocking(int sock) {
|
| + int flags = fcntl(sock, F_GETFL);
|
| + ASSERT_NE(-1, flags);
|
| + flags |= O_NONBLOCK;
|
| + ASSERT_EQ(0, fcntl(sock, F_SETFL, flags));
|
| + ASSERT_EQ(flags, fcntl(sock, F_GETFL));
|
| +}
|
| +
|
| class SocketTest : public ::testing::Test {
|
| public:
|
| SocketTest() : sock1(-1), sock2(-1) {}
|
| @@ -291,6 +299,36 @@ TEST_F(SocketTestWithServer, TCPConnect) {
|
| EXPECT_EQ(0, memcmp(outbuf, inbuf, sizeof(outbuf)));
|
| }
|
|
|
| +TEST_F(SocketTestWithServer, TCPConnectNonBlock) {
|
| + char outbuf[256];
|
| + //char inbuf[512];
|
| +
|
| + memset(outbuf, 1, sizeof(outbuf));
|
| +
|
| + sockaddr_in addr;
|
| + socklen_t addrlen = sizeof(addr);
|
| +
|
| + IP4ToSockAddr(LOCAL_HOST, PORT1, &addr);
|
| +
|
| + SetNonBlocking(sock_);
|
| + ASSERT_EQ(-1, connect(sock_, (sockaddr*) &addr, addrlen));
|
| + ASSERT_EQ(EINPROGRESS, errno)
|
| + << "expected EINPROGRESS but got: " << strerror(errno) << "\n";
|
| + ASSERT_EQ(-1, connect(sock_, (sockaddr*) &addr, addrlen));
|
| + ASSERT_EQ(EALREADY, errno);
|
| +
|
| + // Wait for the socket connection to complete using poll()
|
| + struct pollfd pollfd = { sock_, POLLIN|POLLOUT, 0 };
|
| + ASSERT_EQ(1, poll(&pollfd, 1, -1));
|
| + ASSERT_EQ(POLLOUT, pollfd.revents);
|
| +
|
| + // Attempts to connect again should yield EISCONN
|
| + ASSERT_EQ(-1, connect(sock_, (sockaddr*) &addr, addrlen));
|
| + ASSERT_EQ(EISCONN, errno);
|
| +
|
| + // And SO_ERROR should be 0.
|
| +}
|
| +
|
| TEST_F(SocketTest, Getsockopt) {
|
| sock1 = socket(AF_INET, SOCK_STREAM, 0);
|
| EXPECT_GT(sock1, -1);
|
| @@ -334,7 +372,6 @@ TEST_F(SocketTestUDP, Listen) {
|
| }
|
|
|
| TEST_F(SocketTestTCP, Listen) {
|
| - // Accept should fail when socket not listening
|
| sockaddr_in addr;
|
| socklen_t addrlen = sizeof(addr);
|
|
|
| @@ -346,7 +383,7 @@ TEST_F(SocketTestTCP, Listen) {
|
| // Listen should fail on unbound socket
|
| ASSERT_EQ(-1, listen(server_sock, 10));
|
|
|
| - // bind and listen
|
| + // Bind and Listen
|
| ASSERT_EQ(0, Bind(server_sock, LOCAL_HOST, PORT1));
|
| ASSERT_EQ(0, listen(server_sock, 10))
|
| << "listen failed with: " << strerror(errno);
|
| @@ -377,6 +414,59 @@ TEST_F(SocketTestTCP, Listen) {
|
|
|
| char inbuf[512];
|
| ASSERT_EQ(5, recv(new_socket, inbuf, 5, 0));
|
| + ASSERT_EQ(0, close(new_socket));
|
| +}
|
| +
|
| +TEST_F(SocketTestTCP, ListenNonBlocking) {
|
| + int server_sock = sock1;
|
| +
|
| + // Set non-blocking
|
| + SetNonBlocking(server_sock);
|
| +
|
| + // bind and listen
|
| + ASSERT_EQ(0, Bind(server_sock, LOCAL_HOST, PORT1));
|
| + ASSERT_EQ(0, listen(server_sock, 10))
|
| + << "listen failed with: " << strerror(errno);
|
| +
|
| + // Accept should fail with EAGAIN since there is no incomming
|
| + // connection.
|
| + sockaddr_in addr;
|
| + socklen_t addrlen = sizeof(addr);
|
| + ASSERT_EQ(-1, accept(server_sock, (sockaddr*)&addr, &addrlen));
|
| + ASSERT_EQ(EAGAIN, errno);
|
| +
|
| + // If we poll the listening socket it should also return
|
| + // not readable to indicate that no connections are available
|
| + // to accept.
|
| + struct pollfd pollfd = { server_sock, POLLIN|POLLOUT, 0 };
|
| + ASSERT_EQ(0, poll(&pollfd, 1, 0));
|
| +
|
| + // Connect to listening socket
|
| + int client_sock = sock2;
|
| + IP4ToSockAddr(LOCAL_HOST, PORT1, &addr);
|
| + addrlen = sizeof(addr);
|
| + ASSERT_EQ(0, connect(client_sock, (sockaddr*)&addr, addrlen))
|
| + << "Failed with " << errno << ": " << strerror(errno) << "\n";
|
| +
|
| + // Not poll again but with an infintie timeout.
|
| + pollfd.fd = server_sock;
|
| + pollfd.events = POLLIN | POLLOUT;
|
| + ASSERT_EQ(1, poll(&pollfd, 1, -1));
|
| +
|
| + // Now non-blocking accept should return the new socket
|
| + int new_socket = accept(server_sock, (sockaddr*)&addr, &addrlen);
|
| + ASSERT_NE(-1, new_socket)
|
| + << "accept failed with: " << strerror(errno) << "\n";
|
| + ASSERT_EQ(0, close(new_socket));
|
| +
|
| + // Accept calls should once again fail with EAGAIN
|
| + ASSERT_EQ(-1, accept(server_sock, (sockaddr*)&addr, &addrlen));
|
| + ASSERT_EQ(EAGAIN, errno);
|
| +
|
| + // As should polling the listening socket
|
| + pollfd.fd = server_sock;
|
| + pollfd.events = POLLIN | POLLOUT;
|
| + ASSERT_EQ(0, poll(&pollfd, 1, 0));
|
| }
|
|
|
| #endif // PROVIDES_SOCKET_API
|
|
|