Index: native_client_sdk/src/tests/nacl_io_test/host_resolver_test.cc |
diff --git a/native_client_sdk/src/tests/nacl_io_test/host_resolver_test.cc b/native_client_sdk/src/tests/nacl_io_test/host_resolver_test.cc |
index 9d79e1c5a55502f7f07786048b7231c5bfea9b1f..e0d0aa46c1d65559c6f6cd172e731912b810032f 100644 |
--- a/native_client_sdk/src/tests/nacl_io_test/host_resolver_test.cc |
+++ b/native_client_sdk/src/tests/nacl_io_test/host_resolver_test.cc |
@@ -18,13 +18,56 @@ namespace { |
class HostResolverTest : public ::testing::Test { |
public: |
- HostResolverTest() : pepper_(NULL) {} |
+ HostResolverTest() {} |
+ |
+ void SetUp() { |
+ ki_init(NULL); |
+ } |
+ |
+ void TearDown() { |
+ ki_uninit(); |
+ } |
+}; |
+ |
+#define FAKE_HOSTNAME "example.com" |
+#define FAKE_IP 0x01020304 |
+ |
+class FakeHostResolverTest : public ::testing::Test { |
+ public: |
+ FakeHostResolverTest() : pepper_(NULL), fake_resolver_(NULL) {} |
void SetUp() { |
pepper_ = new FakePepperInterface(); |
+ fake_resolver_ = |
+ (FakeHostResolverInterface*)pepper_->GetHostResolverInterface(); |
binji
2014/01/29 19:18:52
nit: use C++-style cast
Sam Clegg
2014/01/29 22:06:13
Done.
|
+ |
+ // Seed the fake resolver with some data |
+ fake_resolver_->fake_hostname = FAKE_HOSTNAME; |
+ AddFakeAddres(AF_INET); |
+ |
ki_init_interface(NULL, pepper_); |
} |
+ void AddFakeAddres(int family) { |
binji
2014/01/29 19:18:52
sp: AddFakeAddress
Sam Clegg
2014/01/29 22:06:13
Done.
|
+ if (family == AF_INET) { |
+ int address_count = fake_resolver_->fake_addresses_v4.size(); |
+ // Each new address we add is FAKE_IP incremented by 1 |
binji
2014/01/29 19:18:52
Maybe cleaner to just have a limited fixed list of
|
+ // each time to be unique. |
+ sockaddr_in fake_addr; |
+ fake_addr.sin_family = family; |
+ fake_addr.sin_addr.s_addr = htonl(FAKE_IP + address_count); |
+ fake_resolver_->fake_addresses_v4.push_back(fake_addr); |
+ } else if (family == AF_INET6) { |
+ sockaddr_in6 fake_addr; |
+ fake_addr.sin6_family = family; |
+ int address_count = fake_resolver_->fake_addresses_v6.size(); |
+ for (uint8_t i = 0; i < 16; i++) { |
+ fake_addr.sin6_addr.s6_addr[i] = i + address_count; |
+ } |
+ fake_resolver_->fake_addresses_v6.push_back(fake_addr); |
+ } |
+ } |
+ |
void TearDown() { |
ki_uninit(); |
pepper_ = NULL; |
@@ -32,13 +75,254 @@ class HostResolverTest : public ::testing::Test { |
protected: |
FakePepperInterface* pepper_; |
+ FakeHostResolverInterface* fake_resolver_; |
}; |
} // namespace |
+#define NULL_INFO ((struct addrinfo*)NULL) |
+#define NULL_ADDR ((struct sockaddr*)NULL) |
#define NULL_HOST (static_cast<hostent*>(NULL)) |
-TEST_F(HostResolverTest, GethostbynameNumeric) { |
+#if defined(__GLIBC__) && defined(__linux__) |
+//#define USE_SYSTEM_NS |
binji
2014/01/29 19:18:52
what is NS? NameService?
Sam Clegg
2014/01/29 22:06:13
Added comment
|
+#endif |
+ |
+#ifdef USE_SYSTEM_NS |
+#define ki_getaddrinfo getaddrinfo |
+#define ki_gethostbyname gethostbyname |
+#define ki_freeaddrinfo freeaddrinfo |
+#endif |
+ |
+TEST_F(HostResolverTest, Getaddrinfo_Numeric) { |
+ struct addrinfo* ai = NULL; |
+ struct sockaddr_in* in; |
+ struct addrinfo hints; |
+ |
+ // Numberic only |
+ memset(&hints, 0, sizeof(hints)); |
+ hints.ai_family = AF_INET; |
+ hints.ai_socktype = SOCK_STREAM; |
+ |
+ uint32_t expected_addr = htonl(0x01020304); |
+ ASSERT_EQ(0, ki_getaddrinfo("1.2.3.4", NULL, &hints, &ai)); |
+ ASSERT_NE(NULL_INFO, ai); |
+ ASSERT_NE(NULL_ADDR, ai->ai_addr); |
+ ASSERT_EQ(AF_INET, ai->ai_family); |
+ ASSERT_EQ(SOCK_STREAM, ai->ai_socktype); |
+ in = (struct sockaddr_in*)ai->ai_addr; |
+ ASSERT_EQ(expected_addr, in->sin_addr.s_addr); |
+ ASSERT_EQ(NULL_INFO, ai->ai_next); |
+ |
+ ki_freeaddrinfo(ai); |
+} |
+ |
+#ifndef USE_SYSTEM_NS |
+TEST_F(HostResolverTest, Getaddrinfo_MissingPPAPI) { |
+ // Verify that full lookups fail due to lack of PPAPI interfaces |
+ struct addrinfo* ai = NULL; |
+ ASSERT_EQ(EAI_SYSTEM, ki_getaddrinfo("google.com", NULL, NULL, &ai)); |
+} |
+#endif |
+ |
+TEST_F(HostResolverTest, Getaddrinfo_Passive) { |
+ struct addrinfo* ai = NULL; |
+ struct sockaddr_in* in; |
+ struct sockaddr_in6* in6; |
+ struct addrinfo hints; |
+ memset(&hints, 0, sizeof(hints)); |
+ |
+ uint32_t expected_port = htons(22); |
+ in_addr_t expected_addr = htonl(INADDR_ANY); |
+ in6_addr expected_addr6 = IN6ADDR_ANY_INIT; |
+ |
+ // AI_PASSIVE means that the returned address will be a wildcard |
+ // address suitable for binding and listening. This should not |
+ // hit PPAPI at all, so we don't need fakes. |
+ hints.ai_family = AF_INET; |
+ hints.ai_flags = AI_PASSIVE; |
+ hints.ai_socktype = SOCK_DGRAM; |
+ ASSERT_EQ(0, ki_getaddrinfo(NULL, "22", &hints, &ai)); |
+ ASSERT_NE(NULL_INFO, ai); |
+ ASSERT_NE(NULL_ADDR, ai->ai_addr); |
+ ASSERT_EQ(NULL_INFO, ai->ai_next); |
+ in = (struct sockaddr_in*)ai->ai_addr; |
+ ASSERT_EQ(expected_addr, in->sin_addr.s_addr); |
+ ASSERT_EQ(expected_port, in->sin_port); |
+ ASSERT_EQ(AF_INET, in->sin_family); |
binji
2014/01/29 19:18:52
free addrinfo here?
Sam Clegg
2014/01/29 22:06:13
Done.
|
+ |
+ // Same test with AF_INET6 |
+ hints.ai_family = AF_INET6; |
+ ASSERT_EQ(0, ki_getaddrinfo(NULL, "22", &hints, &ai)); |
+ ASSERT_NE(NULL_INFO, ai); |
+ ASSERT_NE(NULL_ADDR, ai->ai_addr); |
+ ASSERT_EQ(NULL_INFO, ai->ai_next); |
+ in6 = (struct sockaddr_in6*)ai->ai_addr; |
+ ASSERT_EQ(expected_port, in6->sin6_port); |
+ ASSERT_EQ(AF_INET6, in6->sin6_family); |
+ ASSERT_EQ(0, memcmp(in6->sin6_addr.s6_addr, |
+ &expected_addr6, |
+ sizeof(expected_addr6))); |
+ |
+ ki_freeaddrinfo(ai); |
+} |
+ |
+TEST_F(HostResolverTest, Getaddrinfo_Passive_Any) { |
+ // Similar to Getaddrinfo_Passive but don't set |
+ // ai_family in the hints, so we should get muplitple |
+ // results back for the different families. |
+ struct addrinfo* ai = NULL; |
+ struct sockaddr_in* in; |
+ struct sockaddr_in6* in6; |
+ struct addrinfo hints; |
+ memset(&hints, 0, sizeof(hints)); |
+ |
+ uint32_t expected_port = htons(22); |
+ in_addr_t expected_addr = htonl(INADDR_ANY); |
+ in6_addr expected_addr6 = IN6ADDR_ANY_INIT; |
+ |
+ hints.ai_flags = AI_PASSIVE; |
+ hints.ai_socktype = SOCK_DGRAM; |
+ ASSERT_EQ(0, ki_getaddrinfo(NULL, "22", &hints, &ai)); |
+ ASSERT_NE(NULL_INFO, ai); |
+ int count = 0; |
+ bool got_v4 = false; |
+ bool got_v6 = false; |
+ while (ai) { |
+ ASSERT_NE(NULL_ADDR, ai->ai_addr); |
+ switch (ai->ai_addr->sa_family) { |
+ case AF_INET: |
+ in = (struct sockaddr_in*)ai->ai_addr; |
+ ASSERT_EQ(expected_port, in->sin_port); |
+ ASSERT_EQ(AF_INET, in->sin_family); |
+ ASSERT_EQ(expected_addr, in->sin_addr.s_addr); |
+ got_v4 = true; |
+ break; |
+ case AF_INET6: |
+ in6 = (struct sockaddr_in6*)ai->ai_addr; |
+ ASSERT_EQ(expected_port, in6->sin6_port); |
+ ASSERT_EQ(AF_INET6, in6->sin6_family); |
+ ASSERT_EQ(0, memcmp(in6->sin6_addr.s6_addr, |
+ &expected_addr6, |
+ sizeof(expected_addr6))); |
+ got_v6 = true; |
+ break; |
+ default: |
+ ASSERT_TRUE(false) << "Unknown address type: " << ai->ai_addr; |
+ break; |
+ } |
+ ai = ai->ai_next; |
+ count++; |
+ } |
+ |
+ ASSERT_GT(count, 1); |
binji
2014/01/29 19:18:52
ASSERT_EQ(2, COUNT), Or could it be more than that
|
+ ASSERT_TRUE(got_v4); |
+ ASSERT_TRUE(got_v6); |
+} |
+ |
+#ifndef USE_SYSTEM_NS |
+ |
+TEST_F(FakeHostResolverTest, Getaddrinfo_Lookup) { |
+ struct addrinfo* ai = NULL; |
+ struct sockaddr_in* in; |
+ struct addrinfo hints; |
+ memset(&hints, 0, sizeof(hints)); |
+ |
+ in_addr_t expected_addr = htonl(FAKE_IP); |
+ |
+ // Lookup the fake hostname using getaddrinfo |
+ hints.ai_family = AF_INET; |
+ hints.ai_socktype = SOCK_STREAM; |
+ ASSERT_EQ(0, ki_getaddrinfo(FAKE_HOSTNAME, NULL, &hints, &ai)); |
+ ASSERT_NE(NULL_INFO, ai); |
+ ASSERT_NE(NULL_ADDR, ai->ai_addr); |
+ ASSERT_EQ(AF_INET, ai->ai_family); |
+ ASSERT_EQ(SOCK_STREAM, ai->ai_socktype); |
+ in = (struct sockaddr_in*)ai->ai_addr; |
+ ASSERT_EQ(expected_addr, in->sin_addr.s_addr); |
+ ASSERT_EQ(NULL_INFO, ai->ai_next); |
+ |
+ ki_freeaddrinfo(ai); |
+} |
+#endif |
+ |
+TEST_F(FakeHostResolverTest, Getaddrinfo_Multi) { |
binji
2014/01/29 19:18:52
doesn't this need to be ifndef'd too?
|
+ struct addrinfo* ai = NULL; |
+ struct addrinfo hints; |
+ memset(&hints, 0, sizeof(hints)); |
+ |
+ // Add three fake address on top of the initial one |
binji
2014/01/29 19:18:52
four
Sam Clegg
2014/01/29 22:06:13
Done.
|
+ // that the fixture creates. |
+ AddFakeAddres(AF_INET); |
+ AddFakeAddres(AF_INET); |
+ AddFakeAddres(AF_INET6); |
+ AddFakeAddres(AF_INET6); |
+ |
+ hints.ai_socktype = SOCK_STREAM; |
+ |
+ // First we test with AF_INET |
+ hints.ai_family = AF_INET; |
+ ASSERT_EQ(0, ki_getaddrinfo(FAKE_HOSTNAME, NULL, &hints, &ai)); |
binji
2014/01/29 19:18:52
ki_freeaddrinfo for each call to ki_getaddrinfo
Sam Clegg
2014/01/29 22:06:13
Done.
|
+ ASSERT_NE(NULL_INFO, ai); |
+ |
+ // We expect to be returned 3 AF_INET address with |
+ // address FAKE_IP, FAKE_IP+1 and FAKE_IP+2, since that |
+ // is that the fake was seeded with. |
+ uint32_t expected_addr = htonl(FAKE_IP); |
+ int count = 0; |
+ struct addrinfo* current = ai; |
+ while (current != NULL) { |
+ ASSERT_NE(NULL_ADDR, current->ai_addr); |
binji
2014/01/29 19:18:52
Move these tests into a function, to simplify? The
Sam Clegg
2014/01/29 22:06:13
Done.
|
+ ASSERT_EQ(AF_INET, current->ai_family); |
+ ASSERT_EQ(SOCK_STREAM, current->ai_socktype); |
+ sockaddr_in* in = (sockaddr_in*)current->ai_addr; |
+ ASSERT_EQ(expected_addr, in->sin_addr.s_addr); |
+ expected_addr += htonl(1); |
+ current = current->ai_next; |
+ count++; |
+ } |
+ ASSERT_EQ(3, count); |
+ |
+ // Same test but with AF_INET6 |
+ hints.ai_family = AF_INET6; |
+ ASSERT_EQ(0, ki_getaddrinfo(FAKE_HOSTNAME, NULL, &hints, &ai)); |
+ ASSERT_NE(NULL_INFO, ai); |
+ |
+ count = 0; |
+ current = ai; |
+ while (current != NULL) { |
+ ASSERT_NE(NULL_ADDR, current->ai_addr); |
+ ASSERT_EQ(AF_INET6, current->ai_family); |
+ ASSERT_EQ(SOCK_STREAM, current->ai_socktype); |
+ sockaddr_in6* in = (sockaddr_in6*)current->ai_addr; |
+ for (int i = 0; i < 16; i++) { |
+ ASSERT_EQ(i + count, in->sin6_addr.s6_addr[i]); |
+ } |
+ current = current->ai_next; |
+ count++; |
+ } |
+ ASSERT_EQ(2, count); |
+ |
+ // Same test but with AF_UNSPEC. Here we expect to get |
+ // 5 address back: 3 * v4 and 2 * v6. |
+ hints.ai_family = AF_UNSPEC; |
+ ASSERT_EQ(0, ki_getaddrinfo(FAKE_HOSTNAME, NULL, &hints, &ai)); |
+ ASSERT_NE(NULL_INFO, ai); |
+ |
+ count = 0; |
+ current = ai; |
+ while (current != NULL) { |
+ ASSERT_NE(NULL_ADDR, ai->ai_addr); |
+ ASSERT_EQ(SOCK_STREAM, ai->ai_socktype); |
+ current = current->ai_next; |
+ count++; |
+ } |
+ ASSERT_EQ(5, count); |
+ |
+ ki_freeaddrinfo(ai); |
+} |
+ |
+TEST_F(FakeHostResolverTest, Gethostbyname) { |
hostent* host = ki_gethostbyname(FAKE_HOSTNAME); |
// Verify the returned hostent structure |
@@ -53,3 +337,34 @@ TEST_F(HostResolverTest, GethostbynameNumeric) { |
in_addr_t exptected_addr = htonl(FAKE_IP); |
ASSERT_EQ(exptected_addr, *addr_list[0]); |
} |
+ |
+// Looking up purly numeric hostnames should work without PPAPI |
binji
2014/01/29 19:18:52
sp: purely
|
+// so we don't need the fakes for this test |
+TEST_F(HostResolverTest, Gethostbyname_Numeric) { |
+ struct hostent* host = ki_gethostbyname("8.8.8.8"); |
+ |
+ // Verify the returned hostent structure |
+ ASSERT_NE(NULL_HOST, host); |
+ ASSERT_EQ(AF_INET, host->h_addrtype); |
+ ASSERT_EQ(sizeof(in_addr_t), host->h_length); |
+ ASSERT_STREQ("8.8.8.8", host->h_name); |
+ |
+ in_addr_t** addr_list = reinterpret_cast<in_addr_t**>(host->h_addr_list); |
+ ASSERT_NE(reinterpret_cast<in_addr_t**>(NULL), addr_list); |
+ ASSERT_EQ(NULL, addr_list[1]); |
+ ASSERT_EQ(inet_addr("8.8.8.8"), *addr_list[0]); |
+} |
+ |
+// These utility functions are only used for newlib (glibc provides its own |
+// implementations of these functions). |
+#if !defined(__GLIBC__) |
+ |
+TEST(SocketUtilityFunctions, Hstrerror) { |
+ EXPECT_STREQ("Unknown error in gethostbyname: 2718.", hstrerror(2718)); |
+} |
+ |
+TEST(SocketUtilityFunctions, Gai_Strerror) { |
+ EXPECT_STREQ("Unknown error in getaddrinfo: 2719.", gai_strerror(2719)); |
+} |
+ |
+#endif // !defined(__GLIBC__) |