1 // Copyright 2012 The Chromium Authors
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 <algorithm>
8
9 #include "base/strings/string_util.h"
10 #include "base/sys_byteorder.h"
11 #include "net/base/ip_address.h"
12 #include "net/base/sockaddr_storage.h"
13 #include "net/base/sys_addrinfo.h"
14 #include "testing/gmock/include/gmock/gmock.h"
15 #include "testing/gtest/include/gtest/gtest.h"
16
17 using ::testing::ElementsAre;
18 using ::testing::UnorderedElementsAre;
19
20 namespace net {
21 namespace {
22
23 const char kCanonicalHostname[] = "canonical.bar.com";
24
TEST(AddressListTest,Canonical)25 TEST(AddressListTest, Canonical) {
26 // Create an addrinfo with a canonical name.
27 struct sockaddr_in address;
28 // The contents of address do not matter for this test,
29 // so just zero-ing them out for consistency.
30 memset(&address, 0x0, sizeof(address));
31 // But we need to set the family.
32 address.sin_family = AF_INET;
33 struct addrinfo ai;
34 memset(&ai, 0x0, sizeof(ai));
35 ai.ai_family = AF_INET;
36 ai.ai_socktype = SOCK_STREAM;
37 ai.ai_addrlen = sizeof(address);
38 ai.ai_addr = reinterpret_cast<sockaddr*>(&address);
39 ai.ai_canonname = const_cast<char *>(kCanonicalHostname);
40
41 // Copy the addrinfo struct into an AddressList object and
42 // make sure it seems correct.
43 AddressList addrlist1 = AddressList::CreateFromAddrinfo(&ai);
44 EXPECT_THAT(addrlist1.dns_aliases(),
45 UnorderedElementsAre("canonical.bar.com"));
46
47 // Copy the AddressList to another one.
48 AddressList addrlist2 = addrlist1;
49 EXPECT_THAT(addrlist2.dns_aliases(),
50 UnorderedElementsAre("canonical.bar.com"));
51 }
52
TEST(AddressListTest,CreateFromAddrinfo)53 TEST(AddressListTest, CreateFromAddrinfo) {
54 // Create an 4-element addrinfo.
55 const unsigned kNumElements = 4;
56 SockaddrStorage storage[kNumElements];
57 struct addrinfo ai[kNumElements];
58 for (unsigned i = 0; i < kNumElements; ++i) {
59 struct sockaddr_in* addr =
60 reinterpret_cast<struct sockaddr_in*>(storage[i].addr);
61 storage[i].addr_len = sizeof(struct sockaddr_in);
62 // Populating the address with { i, i, i, i }.
63 memset(&addr->sin_addr, i, IPAddress::kIPv4AddressSize);
64 addr->sin_family = AF_INET;
65 // Set port to i << 2;
66 addr->sin_port = base::HostToNet16(static_cast<uint16_t>(i << 2));
67 memset(&ai[i], 0x0, sizeof(ai[i]));
68 ai[i].ai_family = addr->sin_family;
69 ai[i].ai_socktype = SOCK_STREAM;
70 ai[i].ai_addrlen = storage[i].addr_len;
71 ai[i].ai_addr = storage[i].addr;
72 if (i + 1 < kNumElements)
73 ai[i].ai_next = &ai[i + 1];
74 }
75
76 AddressList list = AddressList::CreateFromAddrinfo(&ai[0]);
77
78 ASSERT_EQ(kNumElements, list.size());
79 for (size_t i = 0; i < list.size(); ++i) {
80 EXPECT_EQ(ADDRESS_FAMILY_IPV4, list[i].GetFamily());
81 // Only check the first byte of the address.
82 EXPECT_EQ(i, list[i].address().bytes()[0]);
83 EXPECT_EQ(static_cast<int>(i << 2), list[i].port());
84 }
85
86 // Check if operator= works.
87 AddressList copy;
88 copy = list;
89 ASSERT_EQ(kNumElements, copy.size());
90
91 // Check if copy is independent.
92 copy[1] = IPEndPoint(copy[2].address(), 0xBEEF);
93 // Original should be unchanged.
94 EXPECT_EQ(1u, list[1].address().bytes()[0]);
95 EXPECT_EQ(1 << 2, list[1].port());
96 }
97
TEST(AddressListTest,CreateFromIPAddressList)98 TEST(AddressListTest, CreateFromIPAddressList) {
99 struct TestData {
100 std::string ip_address;
101 const char* in_addr;
102 int ai_family;
103 size_t ai_addrlen;
104 size_t in_addr_offset;
105 size_t in_addr_size;
106 } tests[] = {
107 { "127.0.0.1",
108 "\x7f\x00\x00\x01",
109 AF_INET,
110 sizeof(struct sockaddr_in),
111 offsetof(struct sockaddr_in, sin_addr),
112 sizeof(struct in_addr),
113 },
114 { "2001:db8:0::42",
115 "\x20\x01\x0d\xb8\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x42",
116 AF_INET6,
117 sizeof(struct sockaddr_in6),
118 offsetof(struct sockaddr_in6, sin6_addr),
119 sizeof(struct in6_addr),
120 },
121 { "192.168.1.1",
122 "\xc0\xa8\x01\x01",
123 AF_INET,
124 sizeof(struct sockaddr_in),
125 offsetof(struct sockaddr_in, sin_addr),
126 sizeof(struct in_addr),
127 },
128 };
129 const std::string kCanonicalName = "canonical.example.com";
130
131 // Construct a list of ip addresses.
132 IPAddressList ip_list;
133 for (const auto& test : tests) {
134 IPAddress ip_address;
135 ASSERT_TRUE(ip_address.AssignFromIPLiteral(test.ip_address));
136 ip_list.push_back(ip_address);
137 }
138
139 // Wrap the canonical name in an alias vector.
140 std::vector<std::string> aliases({kCanonicalName});
141
142 AddressList test_list =
143 AddressList::CreateFromIPAddressList(ip_list, std::move(aliases));
144 std::string canonical_name;
145 EXPECT_THAT(test_list.dns_aliases(), UnorderedElementsAre(kCanonicalName));
146 EXPECT_EQ(std::size(tests), test_list.size());
147 }
148
TEST(AddressListTest,GetCanonicalNameWhenUnset)149 TEST(AddressListTest, GetCanonicalNameWhenUnset) {
150 const IPAddress kAddress(1, 2, 3, 4);
151 const IPEndPoint kEndpoint(kAddress, 0);
152 AddressList addrlist(kEndpoint);
153
154 EXPECT_TRUE(addrlist.dns_aliases().empty());
155 }
156
TEST(AddressListTest,SetDefaultCanonicalNameThenSetDnsAliases)157 TEST(AddressListTest, SetDefaultCanonicalNameThenSetDnsAliases) {
158 const IPAddress kAddress(1, 2, 3, 4);
159 const IPEndPoint kEndpoint(kAddress, 0);
160 AddressList addrlist(kEndpoint);
161
162 addrlist.SetDefaultCanonicalName();
163
164 EXPECT_THAT(addrlist.dns_aliases(), UnorderedElementsAre("1.2.3.4"));
165
166 std::vector<std::string> aliases({"alias1", "alias2", "alias3"});
167 addrlist.SetDnsAliases(std::move(aliases));
168
169 // Setting the aliases after setting the default canonical name
170 // replaces the default canonical name.
171 EXPECT_THAT(addrlist.dns_aliases(),
172 UnorderedElementsAre("alias1", "alias2", "alias3"));
173 }
174
TEST(AddressListTest,SetDefaultCanonicalNameThenAppendDnsAliases)175 TEST(AddressListTest, SetDefaultCanonicalNameThenAppendDnsAliases) {
176 const IPAddress kAddress(1, 2, 3, 4);
177 const IPEndPoint kEndpoint(kAddress, 0);
178 AddressList addrlist(kEndpoint);
179
180 addrlist.SetDefaultCanonicalName();
181
182 EXPECT_THAT(addrlist.dns_aliases(), UnorderedElementsAre("1.2.3.4"));
183
184 std::vector<std::string> aliases({"alias1", "alias2", "alias3"});
185 addrlist.AppendDnsAliases(std::move(aliases));
186
187 // Appending the aliases after setting the default canonical name
188 // does not replace the default canonical name.
189 EXPECT_THAT(addrlist.dns_aliases(),
190 UnorderedElementsAre("1.2.3.4", "alias1", "alias2", "alias3"));
191 }
192
TEST(AddressListTest,DnsAliases)193 TEST(AddressListTest, DnsAliases) {
194 const IPAddress kAddress(1, 2, 3, 4);
195 const IPEndPoint kEndpoint(kAddress, 0);
196 std::vector<std::string> aliases({"alias1", "alias2", "alias3"});
197 AddressList addrlist(kEndpoint, std::move(aliases));
198
199 EXPECT_THAT(addrlist.dns_aliases(),
200 UnorderedElementsAre("alias1", "alias2", "alias3"));
201
202 std::vector<std::string> more_aliases({"alias4", "alias5", "alias6"});
203 addrlist.AppendDnsAliases(std::move(more_aliases));
204
205 EXPECT_THAT(addrlist.dns_aliases(),
206 UnorderedElementsAre("alias1", "alias2", "alias3", "alias4",
207 "alias5", "alias6"));
208
209 std::vector<std::string> new_aliases({"alias7", "alias8", "alias9"});
210 addrlist.SetDnsAliases(std::move(new_aliases));
211
212 EXPECT_THAT(addrlist.dns_aliases(),
213 UnorderedElementsAre("alias7", "alias8", "alias9"));
214 }
215
TEST(AddressListTest,DeduplicatesEmptyAddressList)216 TEST(AddressListTest, DeduplicatesEmptyAddressList) {
217 AddressList empty;
218 empty.Deduplicate();
219 EXPECT_EQ(empty.size(), 0u);
220 }
221
TEST(AddressListTest,DeduplicatesSingletonAddressList)222 TEST(AddressListTest, DeduplicatesSingletonAddressList) {
223 AddressList singleton;
224 singleton.push_back(IPEndPoint());
225 singleton.Deduplicate();
226 EXPECT_THAT(singleton.endpoints(), ElementsAre(IPEndPoint()));
227 }
228
TEST(AddressListTest,DeduplicatesLongerAddressList)229 TEST(AddressListTest, DeduplicatesLongerAddressList) {
230 AddressList several;
231 several.endpoints() = {IPEndPoint(IPAddress(0, 0, 0, 1), 0),
232 IPEndPoint(IPAddress(0, 0, 0, 2), 0),
233 IPEndPoint(IPAddress(0, 0, 0, 2), 0),
234 IPEndPoint(IPAddress(0, 0, 0, 3), 0),
235 IPEndPoint(IPAddress(0, 0, 0, 2), 0),
236 IPEndPoint(IPAddress(0, 0, 0, 1), 0),
237 IPEndPoint(IPAddress(0, 0, 0, 2), 0),
238 IPEndPoint(IPAddress(0, 0, 0, 3), 0),
239 IPEndPoint(IPAddress(0, 0, 0, 2), 0)};
240 several.Deduplicate();
241
242 // Deduplication should preserve the order of the first instances
243 // of the unique addresses.
244 EXPECT_THAT(several.endpoints(),
245 ElementsAre(IPEndPoint(IPAddress(0, 0, 0, 1), 0),
246 IPEndPoint(IPAddress(0, 0, 0, 2), 0),
247 IPEndPoint(IPAddress(0, 0, 0, 3), 0)));
248 }
249
250 // Test that, for every permutation of a list of endpoints, deduplication
251 // produces the same results as a naive reference implementation.
TEST(AddressListTest,DeduplicatePreservesOrder)252 TEST(AddressListTest, DeduplicatePreservesOrder) {
253 std::vector<IPEndPoint> permutation = {IPEndPoint(IPAddress(0, 0, 0, 1), 0),
254 IPEndPoint(IPAddress(0, 0, 0, 1), 0),
255 IPEndPoint(IPAddress(0, 0, 0, 2), 0),
256 IPEndPoint(IPAddress(0, 0, 0, 2), 0),
257 IPEndPoint(IPAddress(0, 0, 0, 3), 0)};
258 ASSERT_TRUE(std::is_sorted(permutation.begin(), permutation.end()));
259
260 do {
261 std::vector<IPEndPoint> expected;
262 std::set<IPEndPoint> set;
263 for (const IPEndPoint& endpoint : permutation) {
264 if (set.insert(endpoint).second)
265 expected.push_back(endpoint);
266 }
267 EXPECT_EQ(expected.size(), 3u);
268
269 AddressList address_list;
270 address_list.endpoints() = permutation;
271 address_list.Deduplicate();
272 EXPECT_EQ(address_list.endpoints(), expected);
273 } while (std::next_permutation(permutation.begin(), permutation.end()));
274 }
275
276 } // namespace
277 } // namespace net
278