Chromium Code Reviews| 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__) |