Chromium Code Reviews| 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..fd032bbf27273c4dfbb2ebc328d4d65ac7bbe92e |
| --- /dev/null |
| +++ b/native_client_sdk/src/libraries/nacl_io_socket_test/socket_test.cc |
| @@ -0,0 +1,202 @@ |
| +// 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 |
| + |
| +uint16_t htons(uint16_t val) { |
|
binji
2013/08/09 19:28:06
why not use the functions provided by nacl_io?
noelallen1
2013/08/09 22:53:22
Has that landed? I'll merge it in if available.
Sam Clegg
2013/08/09 23:08:00
Yup, https://chromiumcodereview.appspot.com/226250
|
| + return (val >> 8) | (val << 8); |
| +} |
| + |
| +uint32_t htonl(uint32_t val) { |
| + return (val >> 24) | ((val >> 8) & 0xFF00) | |
| + ((val << 8) & 0xFF0000) | (val << 24); |
| +} |
| + |
| +namespace { |
| +class SocketTest : public ::testing::Test { |
| + public: |
| + ~SocketTest() { |
| + EXPECT_EQ(0, ki_close(sock1)); |
| + EXPECT_EQ(0, ki_close(sock2)); |
| + } |
| + |
| + void IP4ToSockAddr(struct sockaddr_in* addr, uint32_t ip, uint16_t port) { |
|
binji
2013/08/09 19:28:06
seems backward to have the out parameter first
noelallen1
2013/08/09 22:53:22
Done.
|
| + memset(addr, 0, sizeof(*addr)); |
| + |
| + addr->sin_family = AF_INET; |
| + uint16_t rport = htons(port); |
| + addr->sin_port = rport; |
|
binji
2013/08/09 19:28:06
why not just addr->sin_port = htons(port);
noelallen1
2013/08/09 22:53:22
Done.
|
| + uint32_t rip = htonl(ip); |
| + addr->sin_addr.s_addr = rip; |
| + } |
| + |
| + void Bind(int fd, uint32_t ip, uint16_t port, int expect) { |
|
binji
2013/08/09 19:28:06
expect_errno?
noelallen1
2013/08/09 22:53:22
Done.
|
| + sockaddr_in addr; |
| + socklen_t addrlen = sizeof(addr); |
| + |
| + IP4ToSockAddr(&addr, ip, port); |
| + int err = bind(fd, (sockaddr*) &addr, addrlen); |
|
binji
2013/08/09 19:28:06
ki_bind?
noelallen1
2013/08/09 22:53:22
Whoops, removing ki_ this should be the end-to-en
|
| + |
| + if (expect != 0) { |
|
binji
2013/08/09 19:28:06
ENONE
noelallen1
2013/08/09 22:53:22
Done.
|
| + EXPECT_EQ(-1, err); |
| + EXPECT_EQ(errno, expect); |
| + } else { |
| + EXPECT_EQ(0, err); |
| + } |
| + } |
| + |
| + void SetupPorts() { |
| + Bind(sock1, 0x7F000001, 0, ENONE); |
|
binji
2013/08/09 19:28:06
use const instead of magic number
noelallen1
2013/08/09 22:53:22
Done.
|
| + Bind(sock2, 0x7F000001, 0, ENONE); |
| + } |
| + |
| + public: |
| + int sock1; |
|
binji
2013/08/09 19:28:06
initialize member variables in constructor
noelallen1
2013/08/09 22:53:22
Done.
|
| + int sock2; |
| + uint16_t port1; |
| + uint16_t port2; |
| +}; |
| + |
| +class SocketTestUDP : public SocketTest { |
| + public: |
| + SocketTestUDP() { |
| + sock1 = ki_socket(AF_INET, SOCK_DGRAM, 0); |
| + sock2 = ki_socket(AF_INET, SOCK_DGRAM, 0); |
| + |
| + EXPECT_LT(-1, sock1); |
| + EXPECT_LT(-1, sock2); |
| + } |
| +}; |
| + |
| +class SocketTestTCP : public SocketTest { |
| + public: |
| + SocketTestTCP() { |
| + sock1 = ki_socket(AF_INET, SOCK_STREAM, 0); |
| + sock2 = ki_socket(AF_INET, SOCK_STREAM, 0); |
| + |
| + EXPECT_LT(-1, sock1); |
| + EXPECT_LT(-1, sock2); |
| + } |
| +}; |
| + |
| +} // namespace |
| + |
| + |
| +TEST(SocketTest, Socket) { |
| + EXPECT_LT(ki_socket(AF_UNIX, SOCK_STREAM, 0), 0); |
|
binji
2013/08/09 19:28:06
this looks a bit strange, maybe
EXPECT_EQ(-1, ki_
noelallen1
2013/08/09 22:53:22
Done.
|
| + EXPECT_EQ(errno, EAFNOSUPPORT); |
| + EXPECT_LT(ki_socket(AF_INET, SOCK_RAW, 0), 0); |
| + EXPECT_EQ(errno, EPROTONOSUPPORT); |
| + |
| + int sock1 = ki_socket(AF_INET, SOCK_DGRAM, 0); |
|
binji
2013/08/09 19:28:06
shadows this->sock1, which has dummy value, and is
noelallen1
2013/08/09 22:53:22
This is not a TEST_F.
binji
2013/08/09 23:08:27
You're right, whoops!
|
| + EXPECT_NE(-1, sock1); |
| + |
| + int sock2 = ki_socket(AF_INET6, SOCK_DGRAM, 0); |
| + EXPECT_NE(-1, sock2); |
| + |
| + int sock3 = ki_socket(AF_INET, SOCK_STREAM, 0); |
| + EXPECT_NE(-1, sock3); |
| + |
| + int sock4 = ki_socket(AF_INET6, SOCK_STREAM, 0); |
| + EXPECT_NE(-1, sock4); |
| + |
| + ki_close(sock1); |
| + ki_close(sock2); |
| + ki_close(sock3); |
| + ki_close(sock4); |
| +} |
| + |
| +TEST_F(SocketTestUDP, Bind) { |
| + // Bind away. |
| + Bind(sock1, 0x7F000001, 4006, ENONE); |
| + |
| + // Invalid to rebind a socket. |
| + Bind(sock1, 0x7F000001, 4006, EINVAL); |
| + |
| + // Addr in use. |
| + Bind(sock2, 0x7F000001, 4006, EADDRINUSE); |
| + |
| + // Bind with a wildcard. |
| + Bind(sock2, 0x7F000001, 0, ENONE); |
| + |
| + // Invalid to rebind after wildcard |
| + Bind(sock2, 0x7F000001, 4007, EINVAL); |
| + |
| +} |
| + |
| +TEST_F(SocketTestUDP, SendRcv) { |
| + char outbuf[256]; |
| + char inbuf[512]; |
|
binji
2013/08/09 19:28:06
why different sizes?
noelallen1
2013/08/09 22:53:22
To read > expected
|
| + |
| + memset(outbuf, 1, sizeof(outbuf)); |
| + memset(inbuf, 0, sizeof(inbuf)); |
| + |
| + Bind(sock1, 0x7F000001, 4006, ENONE); |
| + Bind(sock2, 0x7F000001, 4007, ENONE); |
| + |
| + sockaddr_in addr; |
| + socklen_t addrlen = sizeof(addr); |
| + IP4ToSockAddr(&addr, 0x7F000001, 4007); |
| + |
| + int len1 = |
| + sendto(sock1, outbuf, sizeof(outbuf), 0,(sockaddr *) &addr, addrlen); |
|
binji
2013/08/09 19:28:06
nit: space after comma, remove extra space after c
binji
2013/08/09 19:28:06
ki_sendto?
noelallen1
2013/08/09 22:53:22
Done.
noelallen1
2013/08/09 22:53:22
no ki_*, end to end.
binji
2013/08/09 23:08:27
OK, I see.
|
| + EXPECT_EQ(sizeof(outbuf), len1); |
| + |
| + // Ensure the buffers are different |
| + EXPECT_NE(0, memcmp(outbuf, inbuf, sizeof(outbuf))); |
| + |
| + // Try to receive the previously sent packet |
| + int len2 = |
| + ki_recvfrom(sock2, inbuf, sizeof(inbuf), 0, (sockaddr *) &addr, &addrlen); |
| + EXPECT_EQ(sizeof(outbuf), len2); |
| + EXPECT_EQ(sizeof(sockaddr_in), addrlen); |
|
binji
2013/08/09 19:28:06
check addr?
noelallen1
2013/08/09 22:53:22
Done.
|
| + |
| + // 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(&addr, 0x7F000001, 4006); |
| + int err = connect(sock, (sockaddr*) &addr, addrlen); |
| + EXPECT_EQ(0, err); |
| + |
| + if (err) { |
| + EXPECT_EQ(0, errno); |
|
binji
2013/08/09 19:28:06
check doesn't make sense -- if err is non-zero, we
noelallen1
2013/08/09 22:53:22
Done.
|
| + } |
| +} |
| + |
| + |
| +#endif // PROVIDES_SOCKETPAIR_API |