| Index: native_client_sdk/src/libraries/nacl_io_socket_test/socket_test.cc | 
| diff --git a/native_client_sdk/src/libraries/nacl_io_socket_test/socket_test.cc b/native_client_sdk/src/libraries/nacl_io_socket_test/socket_test.cc | 
| new file mode 100644 | 
| index 0000000000000000000000000000000000000000..1b425d5fc089930b7f02f2b23870e4ab8264bd61 | 
| --- /dev/null | 
| +++ b/native_client_sdk/src/libraries/nacl_io_socket_test/socket_test.cc | 
| @@ -0,0 +1,189 @@ | 
| +// Copyright 2013 The Chromium Authors. All rights reserved. | 
| +// Use of this source code is governed by a BSD-style license that can be | 
| +// found in the LICENSE file. | 
| + | 
| +#include <arpa/inet.h> | 
| +#include <errno.h> | 
| +#include <fcntl.h> | 
| +#include <netinet/in.h> | 
| +#include <pthread.h> | 
| +#include <sys/types.h> | 
| +#include <sys/socket.h> | 
| +#include <sys/stat.h> | 
| + | 
| +#include <map> | 
| +#include <string> | 
| + | 
| +#include "gmock/gmock.h" | 
| +#include "gtest/gtest.h" | 
| + | 
| +#include "nacl_io/kernel_intercept.h" | 
| +#include "nacl_io/kernel_proxy.h" | 
| +#include "nacl_io/ossocket.h" | 
| +#include "nacl_io/ostypes.h" | 
| + | 
| +#ifdef PROVIDES_SOCKET_API | 
| + | 
| +using namespace nacl_io; | 
| +using namespace sdk_util; | 
| + | 
| +// No error expected | 
| +#define ENONE 0 | 
| +#define LOCAL_HOST 0x7F000001 | 
| +#define PORT1 4006 | 
| +#define PORT2 4007 | 
| +#define ANY_PORT 0 | 
| + | 
| + | 
| +namespace { | 
| +class SocketTest : public ::testing::Test { | 
| + public: | 
| +  SocketTest() : sock1(0), sock2(0) {} | 
| + | 
| +  ~SocketTest() { | 
| +    EXPECT_EQ(0, close(sock1)); | 
| +    EXPECT_EQ(0, close(sock2)); | 
| +  } | 
| + | 
| +  void IP4ToSockAddr(uint32_t ip, uint16_t port, struct sockaddr_in* addr) { | 
| +    memset(addr, 0, sizeof(*addr)); | 
| + | 
| +    addr->sin_family = AF_INET; | 
| +    addr->sin_port = htons(port); | 
| +    addr->sin_addr.s_addr = htonl(ip); | 
| +  } | 
| + | 
| +  int Bind(int fd, uint32_t ip, uint16_t port) { | 
| +    sockaddr_in addr; | 
| +    socklen_t addrlen = sizeof(addr); | 
| + | 
| +    IP4ToSockAddr(ip, port, &addr); | 
| +    int err = bind(fd, (sockaddr*) &addr, addrlen); | 
| + | 
| +    if (err == -1) | 
| +      return errno; | 
| +    return 0; | 
| +  } | 
| + | 
| +  void SetupPorts() { | 
| +    EXPECT_EQ(Bind(sock1, LOCAL_HOST, 0), ENONE); | 
| +    EXPECT_EQ(Bind(sock2, LOCAL_HOST, 0), ENONE); | 
| +  } | 
| + | 
| + public: | 
| +  int sock1; | 
| +  int sock2; | 
| +}; | 
| + | 
| +class SocketTestUDP : public SocketTest { | 
| + public: | 
| +  SocketTestUDP() { | 
| +    sock1 = socket(AF_INET, SOCK_DGRAM, 0); | 
| +    sock2 = socket(AF_INET, SOCK_DGRAM, 0); | 
| + | 
| +    EXPECT_LT(-1, sock1); | 
| +    EXPECT_LT(-1, sock2); | 
| +  } | 
| +}; | 
| + | 
| +class SocketTestTCP : public SocketTest { | 
| + public: | 
| +  SocketTestTCP() { | 
| +    sock1 = socket(AF_INET, SOCK_STREAM, 0); | 
| +    sock2 = socket(AF_INET, SOCK_STREAM, 0); | 
| + | 
| +    EXPECT_LT(-1, sock1); | 
| +    EXPECT_LT(-1, sock2); | 
| +  } | 
| +}; | 
| + | 
| +}  // namespace | 
| + | 
| +TEST(SocketTestSimple, Socket) { | 
| +  EXPECT_EQ(-1, socket(AF_UNIX, SOCK_STREAM, 0)); | 
| +  EXPECT_EQ(errno, EAFNOSUPPORT); | 
| +  EXPECT_EQ(-1, socket(AF_INET, SOCK_RAW, 0)); | 
| +  EXPECT_EQ(errno, EPROTONOSUPPORT); | 
| + | 
| +  int sock1 = socket(AF_INET, SOCK_DGRAM, 0); | 
| +  EXPECT_NE(-1, sock1); | 
| + | 
| +  int sock2 = socket(AF_INET6, SOCK_DGRAM, 0); | 
| +  EXPECT_NE(-1, sock2); | 
| + | 
| +  int sock3 = socket(AF_INET, SOCK_STREAM, 0); | 
| +  EXPECT_NE(-1, sock3); | 
| + | 
| +  int sock4 = socket(AF_INET6, SOCK_STREAM, 0); | 
| +  EXPECT_NE(-1, sock4); | 
| + | 
| +  close(sock1); | 
| +  close(sock2); | 
| +  close(sock3); | 
| +  close(sock4); | 
| +} | 
| + | 
| +TEST_F(SocketTestUDP, Bind) { | 
| +  // Bind away. | 
| +  EXPECT_EQ(Bind(sock1, LOCAL_HOST, PORT1), ENONE); | 
| + | 
| +  // Invalid to rebind a socket. | 
| +  EXPECT_EQ(Bind(sock1, LOCAL_HOST, PORT1), EINVAL); | 
| + | 
| +  // Addr in use. | 
| +  EXPECT_EQ(Bind(sock2, LOCAL_HOST, PORT1), EADDRINUSE); | 
| + | 
| +  // Bind with a wildcard. | 
| +  EXPECT_EQ(Bind(sock2, LOCAL_HOST, ANY_PORT), ENONE); | 
| + | 
| +  // Invalid to rebind after wildcard | 
| +  EXPECT_EQ(Bind(sock2, LOCAL_HOST, PORT1), EINVAL); | 
| + | 
| +} | 
| + | 
| +TEST_F(SocketTestUDP, SendRcv) { | 
| +  char outbuf[256]; | 
| +  char inbuf[512]; | 
| + | 
| +  memset(outbuf, 1, sizeof(outbuf)); | 
| +  memset(inbuf, 0, sizeof(inbuf)); | 
| + | 
| +  EXPECT_EQ(Bind(sock1, LOCAL_HOST, PORT1), ENONE); | 
| +  EXPECT_EQ(Bind(sock2, LOCAL_HOST, PORT2), ENONE); | 
| + | 
| +  sockaddr_in addr; | 
| +  socklen_t addrlen = sizeof(addr); | 
| +  IP4ToSockAddr(LOCAL_HOST, PORT2, &addr); | 
| + | 
| +  int len1 = | 
| +     sendto(sock1, outbuf, sizeof(outbuf), 0, (sockaddr *) &addr, addrlen); | 
| +  EXPECT_EQ(sizeof(outbuf), len1); | 
| + | 
| +  // Ensure the buffers are different | 
| +  EXPECT_NE(0, memcmp(outbuf, inbuf, sizeof(outbuf))); | 
| +  memset(&addr, 0, sizeof(addr)); | 
| + | 
| +  // Try to receive the previously sent packet | 
| +  int len2 = | 
| +    recvfrom(sock2, inbuf, sizeof(inbuf), 0, (sockaddr *) &addr, &addrlen); | 
| +  EXPECT_EQ(sizeof(outbuf), len2); | 
| +  EXPECT_EQ(sizeof(sockaddr_in), addrlen); | 
| +  EXPECT_EQ(PORT1, htons(addr.sin_port)); | 
| + | 
| +  // Now they should be the same | 
| +  EXPECT_EQ(0, memcmp(outbuf, inbuf, sizeof(outbuf))); | 
| +} | 
| + | 
| +TEST_F(SocketTestTCP, Connect) { | 
| +  int sock = socket(AF_INET, SOCK_STREAM, 0); | 
| +  EXPECT_NE(-1, sock); | 
| + | 
| +  sockaddr_in addr; | 
| +  socklen_t addrlen = sizeof(addr); | 
| + | 
| +  IP4ToSockAddr(LOCAL_HOST, PORT1, &addr); | 
| +  int err = connect(sock, (sockaddr*) &addr, addrlen); | 
| +  EXPECT_EQ(ENONE, err) << "Failed with errno: " << errno << "\n"; | 
| +} | 
| + | 
| +#endif  // PROVIDES_SOCKETPAIR_API | 
|  |