1// Copyright (c) 2012 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "net/base/address_list.h"
6
7#include "base/strings/string_util.h"
8#include "base/sys_byteorder.h"
9#include "net/base/net_util.h"
10#include "net/base/sys_addrinfo.h"
11#include "testing/gtest/include/gtest/gtest.h"
12
13namespace net {
14namespace {
15
16static const char* kCanonicalHostname = "canonical.bar.com";
17
18TEST(AddressListTest, Canonical) {
19  // Create an addrinfo with a canonical name.
20  struct sockaddr_in address;
21  // The contents of address do not matter for this test,
22  // so just zero-ing them out for consistency.
23  memset(&address, 0x0, sizeof(address));
24  // But we need to set the family.
25  address.sin_family = AF_INET;
26  struct addrinfo ai;
27  memset(&ai, 0x0, sizeof(ai));
28  ai.ai_family = AF_INET;
29  ai.ai_socktype = SOCK_STREAM;
30  ai.ai_addrlen = sizeof(address);
31  ai.ai_addr = reinterpret_cast<sockaddr*>(&address);
32  ai.ai_canonname = const_cast<char *>(kCanonicalHostname);
33
34  // Copy the addrinfo struct into an AddressList object and
35  // make sure it seems correct.
36  AddressList addrlist1 = AddressList::CreateFromAddrinfo(&ai);
37  EXPECT_EQ("canonical.bar.com", addrlist1.canonical_name());
38
39  // Copy the AddressList to another one.
40  AddressList addrlist2 = addrlist1;
41  EXPECT_EQ("canonical.bar.com", addrlist2.canonical_name());
42}
43
44TEST(AddressListTest, CreateFromAddrinfo) {
45  // Create an 4-element addrinfo.
46  const unsigned kNumElements = 4;
47  SockaddrStorage storage[kNumElements];
48  struct addrinfo ai[kNumElements];
49  for (unsigned i = 0; i < kNumElements; ++i) {
50    struct sockaddr_in* addr =
51        reinterpret_cast<struct sockaddr_in*>(storage[i].addr);
52    storage[i].addr_len = sizeof(struct sockaddr_in);
53    // Populating the address with { i, i, i, i }.
54    memset(&addr->sin_addr, i, kIPv4AddressSize);
55    addr->sin_family = AF_INET;
56    // Set port to i << 2;
57    addr->sin_port = base::HostToNet16(static_cast<uint16>(i << 2));
58    memset(&ai[i], 0x0, sizeof(ai[i]));
59    ai[i].ai_family = addr->sin_family;
60    ai[i].ai_socktype = SOCK_STREAM;
61    ai[i].ai_addrlen = storage[i].addr_len;
62    ai[i].ai_addr = storage[i].addr;
63    if (i + 1 < kNumElements)
64      ai[i].ai_next = &ai[i + 1];
65  }
66
67  AddressList list = AddressList::CreateFromAddrinfo(&ai[0]);
68
69  ASSERT_EQ(kNumElements, list.size());
70  for (size_t i = 0; i < list.size(); ++i) {
71    EXPECT_EQ(ADDRESS_FAMILY_IPV4, list[i].GetFamily());
72    // Only check the first byte of the address.
73    EXPECT_EQ(i, list[i].address()[0]);
74    EXPECT_EQ(static_cast<int>(i << 2), list[i].port());
75  }
76
77  // Check if operator= works.
78  AddressList copy;
79  copy = list;
80  ASSERT_EQ(kNumElements, copy.size());
81
82  // Check if copy is independent.
83  copy[1] = IPEndPoint(copy[2].address(), 0xBEEF);
84  // Original should be unchanged.
85  EXPECT_EQ(1u, list[1].address()[0]);
86  EXPECT_EQ(1 << 2, list[1].port());
87}
88
89TEST(AddressListTest, CreateFromIPAddressList) {
90  struct TestData {
91    std::string ip_address;
92    const char* in_addr;
93    int ai_family;
94    size_t ai_addrlen;
95    size_t in_addr_offset;
96    size_t in_addr_size;
97  } tests[] = {
98    { "127.0.0.1",
99      "\x7f\x00\x00\x01",
100      AF_INET,
101      sizeof(struct sockaddr_in),
102      offsetof(struct sockaddr_in, sin_addr),
103      sizeof(struct in_addr),
104    },
105    { "2001:db8:0::42",
106      "\x20\x01\x0d\xb8\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x42",
107      AF_INET6,
108      sizeof(struct sockaddr_in6),
109      offsetof(struct sockaddr_in6, sin6_addr),
110      sizeof(struct in6_addr),
111    },
112    { "192.168.1.1",
113      "\xc0\xa8\x01\x01",
114      AF_INET,
115      sizeof(struct sockaddr_in),
116      offsetof(struct sockaddr_in, sin_addr),
117      sizeof(struct in_addr),
118    },
119  };
120  const std::string kCanonicalName = "canonical.example.com";
121
122  // Construct a list of ip addresses.
123  IPAddressList ip_list;
124  for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
125    IPAddressNumber ip_number;
126    ASSERT_TRUE(ParseIPLiteralToNumber(tests[i].ip_address, &ip_number));
127    ip_list.push_back(ip_number);
128  }
129
130  AddressList test_list = AddressList::CreateFromIPAddressList(ip_list,
131                                                               kCanonicalName);
132  std::string canonical_name;
133  EXPECT_EQ(kCanonicalName, test_list.canonical_name());
134  EXPECT_EQ(ARRAYSIZE_UNSAFE(tests), test_list.size());
135}
136
137}  // namespace
138}  // namespace net
139