| // Copyright (c) 2012 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 "net/base/address_list.h" | 
 |  | 
 | #include "base/stl_util.h" | 
 | #include "base/strings/string_util.h" | 
 | #include "base/sys_byteorder.h" | 
 | #include "net/base/ip_address.h" | 
 | #include "net/base/sockaddr_storage.h" | 
 | #include "net/base/sys_addrinfo.h" | 
 | #include "starboard/memory.h" | 
 | #include "testing/gtest/include/gtest/gtest.h" | 
 |  | 
 | // Starboard does not define sockaddr or other types from <sys/socket.h>. | 
 | #if !defined(STARBOARD) | 
 |  | 
 | namespace net { | 
 | namespace { | 
 |  | 
 | const char kCanonicalHostname[] = "canonical.bar.com"; | 
 |  | 
 | TEST(AddressListTest, Canonical) { | 
 |   // Create an addrinfo with a canonical name. | 
 |   struct sockaddr_in address; | 
 |   // The contents of address do not matter for this test, | 
 |   // so just zero-ing them out for consistency. | 
 |   SbMemorySet(&address, 0x0, sizeof(address)); | 
 |   // But we need to set the family. | 
 |   address.sin_family = AF_INET; | 
 |   struct addrinfo ai; | 
 |   SbMemorySet(&ai, 0x0, sizeof(ai)); | 
 |   ai.ai_family = AF_INET; | 
 |   ai.ai_socktype = SOCK_STREAM; | 
 |   ai.ai_addrlen = sizeof(address); | 
 |   ai.ai_addr = reinterpret_cast<sockaddr*>(&address); | 
 |   ai.ai_canonname = const_cast<char *>(kCanonicalHostname); | 
 |  | 
 |   // Copy the addrinfo struct into an AddressList object and | 
 |   // make sure it seems correct. | 
 |   AddressList addrlist1 = AddressList::CreateFromAddrinfo(&ai); | 
 |   EXPECT_EQ("canonical.bar.com", addrlist1.canonical_name()); | 
 |  | 
 |   // Copy the AddressList to another one. | 
 |   AddressList addrlist2 = addrlist1; | 
 |   EXPECT_EQ("canonical.bar.com", addrlist2.canonical_name()); | 
 | } | 
 |  | 
 | TEST(AddressListTest, CreateFromAddrinfo) { | 
 |   // Create an 4-element addrinfo. | 
 |   const unsigned kNumElements = 4; | 
 |   SockaddrStorage storage[kNumElements]; | 
 |   struct addrinfo ai[kNumElements]; | 
 |   for (unsigned i = 0; i < kNumElements; ++i) { | 
 |     struct sockaddr_in* addr = | 
 |         reinterpret_cast<struct sockaddr_in*>(storage[i].addr); | 
 |     storage[i].addr_len = sizeof(struct sockaddr_in); | 
 |     // Populating the address with { i, i, i, i }. | 
 |     SbMemorySet(&addr->sin_addr, i, IPAddress::kIPv4AddressSize); | 
 |     addr->sin_family = AF_INET; | 
 |     // Set port to i << 2; | 
 |     addr->sin_port = base::HostToNet16(static_cast<uint16_t>(i << 2)); | 
 |     SbMemorySet(&ai[i], 0x0, sizeof(ai[i])); | 
 |     ai[i].ai_family = addr->sin_family; | 
 |     ai[i].ai_socktype = SOCK_STREAM; | 
 |     ai[i].ai_addrlen = storage[i].addr_len; | 
 |     ai[i].ai_addr = storage[i].addr; | 
 |     if (i + 1 < kNumElements) | 
 |       ai[i].ai_next = &ai[i + 1]; | 
 |   } | 
 |  | 
 |   AddressList list = AddressList::CreateFromAddrinfo(&ai[0]); | 
 |  | 
 |   ASSERT_EQ(kNumElements, list.size()); | 
 |   for (size_t i = 0; i < list.size(); ++i) { | 
 |     EXPECT_EQ(ADDRESS_FAMILY_IPV4, list[i].GetFamily()); | 
 |     // Only check the first byte of the address. | 
 |     EXPECT_EQ(i, list[i].address().bytes()[0]); | 
 |     EXPECT_EQ(static_cast<int>(i << 2), list[i].port()); | 
 |   } | 
 |  | 
 |   // Check if operator= works. | 
 |   AddressList copy; | 
 |   copy = list; | 
 |   ASSERT_EQ(kNumElements, copy.size()); | 
 |  | 
 |   // Check if copy is independent. | 
 |   copy[1] = IPEndPoint(copy[2].address(), 0xBEEF); | 
 |   // Original should be unchanged. | 
 |   EXPECT_EQ(1u, list[1].address().bytes()[0]); | 
 |   EXPECT_EQ(1 << 2, list[1].port()); | 
 | } | 
 |  | 
 | TEST(AddressListTest, CreateFromIPAddressList) { | 
 |   struct TestData { | 
 |     std::string ip_address; | 
 |     const char* in_addr; | 
 |     int ai_family; | 
 |     size_t ai_addrlen; | 
 |     size_t in_addr_offset; | 
 |     size_t in_addr_size; | 
 |   } tests[] = { | 
 |     { "127.0.0.1", | 
 |       "\x7f\x00\x00\x01", | 
 |       AF_INET, | 
 |       sizeof(struct sockaddr_in), | 
 |       offsetof(struct sockaddr_in, sin_addr), | 
 |       sizeof(struct in_addr), | 
 |     }, | 
 |     { "2001:db8:0::42", | 
 |       "\x20\x01\x0d\xb8\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x42", | 
 |       AF_INET6, | 
 |       sizeof(struct sockaddr_in6), | 
 |       offsetof(struct sockaddr_in6, sin6_addr), | 
 |       sizeof(struct in6_addr), | 
 |     }, | 
 |     { "192.168.1.1", | 
 |       "\xc0\xa8\x01\x01", | 
 |       AF_INET, | 
 |       sizeof(struct sockaddr_in), | 
 |       offsetof(struct sockaddr_in, sin_addr), | 
 |       sizeof(struct in_addr), | 
 |     }, | 
 |   }; | 
 |   const std::string kCanonicalName = "canonical.example.com"; | 
 |  | 
 |   // Construct a list of ip addresses. | 
 |   IPAddressList ip_list; | 
 |   for (const auto& test : tests) { | 
 |     IPAddress ip_address; | 
 |     ASSERT_TRUE(ip_address.AssignFromIPLiteral(test.ip_address)); | 
 |     ip_list.push_back(ip_address); | 
 |   } | 
 |  | 
 |   AddressList test_list = AddressList::CreateFromIPAddressList(ip_list, | 
 |                                                                kCanonicalName); | 
 |   std::string canonical_name; | 
 |   EXPECT_EQ(kCanonicalName, test_list.canonical_name()); | 
 |   EXPECT_EQ(base::size(tests), test_list.size()); | 
 | } | 
 |  | 
 | }  // namespace | 
 | }  // namespace net | 
 |  | 
 | #endif  // !defined(STARBOARD) |