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 |