• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (c) 2011 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/memory/scoped_ptr.h"
8 #include "base/string_util.h"
9 #include "net/base/host_resolver_proc.h"
10 #include "net/base/net_util.h"
11 #include "net/base/sys_addrinfo.h"
12 #if defined(OS_WIN)
13 #include "net/base/winsock_init.h"
14 #endif
15 #include "testing/gtest/include/gtest/gtest.h"
16 
17 namespace net {
18 namespace {
19 
20 // Use getaddrinfo() to allocate an addrinfo structure.
CreateAddressList(const std::string & hostname,int port,AddressList * addrlist)21 int CreateAddressList(const std::string& hostname, int port,
22                       AddressList* addrlist) {
23 #if defined(OS_WIN)
24   EnsureWinsockInit();
25 #endif
26   int rv = SystemHostResolverProc(hostname,
27                                   ADDRESS_FAMILY_UNSPECIFIED,
28                                   0,
29                                   addrlist, NULL);
30   if (rv == 0)
31     addrlist->SetPort(port);
32   return rv;
33 }
34 
CreateLongAddressList(AddressList * addrlist,int port)35 void CreateLongAddressList(AddressList* addrlist, int port) {
36   EXPECT_EQ(0, CreateAddressList("192.168.1.1", port, addrlist));
37   AddressList second_list;
38   EXPECT_EQ(0, CreateAddressList("192.168.1.2", port, &second_list));
39   addrlist->Append(second_list.head());
40 }
41 
TEST(AddressListTest,GetPort)42 TEST(AddressListTest, GetPort) {
43   AddressList addrlist;
44   EXPECT_EQ(0, CreateAddressList("192.168.1.1", 81, &addrlist));
45   EXPECT_EQ(81, addrlist.GetPort());
46 
47   addrlist.SetPort(83);
48   EXPECT_EQ(83, addrlist.GetPort());
49 }
50 
TEST(AddressListTest,Assignment)51 TEST(AddressListTest, Assignment) {
52   AddressList addrlist1;
53   EXPECT_EQ(0, CreateAddressList("192.168.1.1", 85, &addrlist1));
54   EXPECT_EQ(85, addrlist1.GetPort());
55 
56   // Should reference the same data as addrlist1 -- so when we change addrlist1
57   // both are changed.
58   AddressList addrlist2 = addrlist1;
59   EXPECT_EQ(85, addrlist2.GetPort());
60 
61   addrlist1.SetPort(80);
62   EXPECT_EQ(80, addrlist1.GetPort());
63   EXPECT_EQ(80, addrlist2.GetPort());
64 }
65 
TEST(AddressListTest,CopyRecursive)66 TEST(AddressListTest, CopyRecursive) {
67   AddressList addrlist1;
68   CreateLongAddressList(&addrlist1, 85);
69   EXPECT_EQ(85, addrlist1.GetPort());
70 
71   AddressList addrlist2;
72   addrlist2.Copy(addrlist1.head(), true);
73 
74   ASSERT_TRUE(addrlist2.head()->ai_next != NULL);
75 
76   // addrlist1 is the same as addrlist2 at this point.
77   EXPECT_EQ(85, addrlist1.GetPort());
78   EXPECT_EQ(85, addrlist2.GetPort());
79 
80   // Changes to addrlist1 are not reflected in addrlist2.
81   addrlist1.SetPort(70);
82   addrlist2.SetPort(90);
83 
84   EXPECT_EQ(70, addrlist1.GetPort());
85   EXPECT_EQ(90, addrlist2.GetPort());
86 }
87 
TEST(AddressListTest,CopyNonRecursive)88 TEST(AddressListTest, CopyNonRecursive) {
89   AddressList addrlist1;
90   CreateLongAddressList(&addrlist1, 85);
91   EXPECT_EQ(85, addrlist1.GetPort());
92 
93   AddressList addrlist2;
94   addrlist2.Copy(addrlist1.head(), false);
95 
96   ASSERT_TRUE(addrlist2.head()->ai_next == NULL);
97 
98   // addrlist1 is the same as addrlist2 at this point.
99   EXPECT_EQ(85, addrlist1.GetPort());
100   EXPECT_EQ(85, addrlist2.GetPort());
101 
102   // Changes to addrlist1 are not reflected in addrlist2.
103   addrlist1.SetPort(70);
104   addrlist2.SetPort(90);
105 
106   EXPECT_EQ(70, addrlist1.GetPort());
107   EXPECT_EQ(90, addrlist2.GetPort());
108 }
109 
TEST(AddressListTest,Append)110 TEST(AddressListTest, Append) {
111   AddressList addrlist1;
112   EXPECT_EQ(0, CreateAddressList("192.168.1.1", 11, &addrlist1));
113   EXPECT_EQ(11, addrlist1.GetPort());
114   AddressList addrlist2;
115   EXPECT_EQ(0, CreateAddressList("192.168.1.2", 12, &addrlist2));
116   EXPECT_EQ(12, addrlist2.GetPort());
117 
118   ASSERT_TRUE(addrlist1.head()->ai_next == NULL);
119   addrlist1.Append(addrlist2.head());
120   ASSERT_TRUE(addrlist1.head()->ai_next != NULL);
121 
122   AddressList addrlist3;
123   addrlist3.Copy(addrlist1.head()->ai_next, false);
124   EXPECT_EQ(12, addrlist3.GetPort());
125 }
126 
127 static const char* kCanonicalHostname = "canonical.bar.com";
128 
TEST(AddressListTest,Canonical)129 TEST(AddressListTest, Canonical) {
130   // Create an addrinfo with a canonical name.
131   sockaddr_in address;
132   // The contents of address do not matter for this test,
133   // so just zero-ing them out for consistency.
134   memset(&address, 0x0, sizeof(address));
135   struct addrinfo ai;
136   memset(&ai, 0x0, sizeof(ai));
137   ai.ai_family = AF_INET;
138   ai.ai_socktype = SOCK_STREAM;
139   ai.ai_addrlen = sizeof(address);
140   ai.ai_addr = reinterpret_cast<sockaddr*>(&address);
141   ai.ai_canonname = const_cast<char *>(kCanonicalHostname);
142 
143   // Copy the addrinfo struct into an AddressList object and
144   // make sure it seems correct.
145   AddressList addrlist1;
146   addrlist1.Copy(&ai, true);
147   const struct addrinfo* addrinfo1 = addrlist1.head();
148   EXPECT_TRUE(addrinfo1 != NULL);
149   EXPECT_TRUE(addrinfo1->ai_next == NULL);
150   std::string canon_name1;
151   EXPECT_TRUE(addrlist1.GetCanonicalName(&canon_name1));
152   EXPECT_EQ("canonical.bar.com", canon_name1);
153 
154   // Copy the AddressList to another one.
155   AddressList addrlist2;
156   addrlist2.Copy(addrinfo1, true);
157   const struct addrinfo* addrinfo2 = addrlist2.head();
158   EXPECT_TRUE(addrinfo2 != NULL);
159   EXPECT_TRUE(addrinfo2->ai_next == NULL);
160   EXPECT_TRUE(addrinfo2->ai_canonname != NULL);
161   EXPECT_NE(addrinfo1, addrinfo2);
162   EXPECT_NE(addrinfo1->ai_canonname, addrinfo2->ai_canonname);
163   std::string canon_name2;
164   EXPECT_TRUE(addrlist2.GetCanonicalName(&canon_name2));
165   EXPECT_EQ("canonical.bar.com", canon_name2);
166 
167   // Make sure that GetCanonicalName correctly returns false
168   // when ai_canonname is NULL.
169   ai.ai_canonname = NULL;
170   AddressList addrlist_no_canon;
171   addrlist_no_canon.Copy(&ai, true);
172   std::string canon_name3 = "blah";
173   EXPECT_FALSE(addrlist_no_canon.GetCanonicalName(&canon_name3));
174   EXPECT_EQ("blah", canon_name3);
175 }
176 
TEST(AddressListTest,IPLiteralConstructor)177 TEST(AddressListTest, IPLiteralConstructor) {
178   struct TestData {
179     std::string ip_address;
180     std::string canonical_ip_address;
181     bool is_ipv6;
182   } tests[] = {
183     { "127.0.00.1", "127.0.0.1", false },
184     { "192.168.1.1", "192.168.1.1", false },
185     { "::1", "::1", true },
186     { "2001:db8:0::42", "2001:db8::42", true },
187   };
188   for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); i++) {
189     AddressList expected_list;
190     int rv = CreateAddressList(tests[i].canonical_ip_address, 80,
191                                &expected_list);
192     if (tests[i].is_ipv6 && rv != 0) {
193       LOG(WARNING) << "Unable to resolve ip literal '" << tests[i].ip_address
194                    << "' test skipped.";
195       continue;
196     }
197     ASSERT_EQ(0, rv);
198     const struct addrinfo* good_ai = expected_list.head();
199 
200     IPAddressNumber ip_number;
201     ParseIPLiteralToNumber(tests[i].ip_address, &ip_number);
202     AddressList test_list(ip_number, 80, true);
203     const struct addrinfo* test_ai = test_list.head();
204 
205     EXPECT_EQ(good_ai->ai_family, test_ai->ai_family);
206     EXPECT_EQ(good_ai->ai_socktype, test_ai->ai_socktype);
207     EXPECT_EQ(good_ai->ai_addrlen, test_ai->ai_addrlen);
208     size_t sockaddr_size =
209         good_ai->ai_socktype == AF_INET ? sizeof(struct sockaddr_in) :
210         good_ai->ai_socktype == AF_INET6 ? sizeof(struct sockaddr_in6) : 0;
211     EXPECT_EQ(memcmp(good_ai->ai_addr, test_ai->ai_addr, sockaddr_size), 0);
212     EXPECT_EQ(good_ai->ai_next, test_ai->ai_next);
213     EXPECT_EQ(strcmp(tests[i].canonical_ip_address.c_str(),
214                      test_ai->ai_canonname), 0);
215   }
216 }
217 
TEST(AddressListTest,AddressFromAddrInfo)218 TEST(AddressListTest, AddressFromAddrInfo) {
219   struct TestData {
220     std::string ip_address;
221     std::string canonical_ip_address;
222     bool is_ipv6;
223   } tests[] = {
224     { "127.0.00.1", "127.0.0.1", false },
225     { "192.168.1.1", "192.168.1.1", false },
226     { "::1", "::1", true },
227     { "2001:db8:0::42", "2001:db8::42", true },
228   };
229   for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); i++) {
230     AddressList expected_list;
231     int rv = CreateAddressList(tests[i].canonical_ip_address, 80,
232                                &expected_list);
233     if (tests[i].is_ipv6 && rv != 0) {
234       LOG(WARNING) << "Unable to resolve ip literal '" << tests[i].ip_address
235                    << "' test skipped.";
236       continue;
237     }
238     ASSERT_EQ(0, rv);
239     const struct addrinfo* good_ai = expected_list.head();
240 
241     scoped_ptr<AddressList> test_list(
242         AddressList::CreateAddressListFromSockaddr(good_ai->ai_addr,
243                                                    good_ai->ai_addrlen,
244                                                    SOCK_STREAM,
245                                                    IPPROTO_TCP));
246     const struct addrinfo* test_ai = test_list->head();
247 
248     EXPECT_EQ(good_ai->ai_family, test_ai->ai_family);
249     EXPECT_EQ(good_ai->ai_addrlen, test_ai->ai_addrlen);
250     size_t sockaddr_size =
251         good_ai->ai_socktype == AF_INET ? sizeof(struct sockaddr_in) :
252         good_ai->ai_socktype == AF_INET6 ? sizeof(struct sockaddr_in6) : 0;
253     EXPECT_EQ(memcmp(good_ai->ai_addr, test_ai->ai_addr, sockaddr_size), 0);
254     EXPECT_EQ(good_ai->ai_next, test_ai->ai_next);
255   }
256 }
257 
258 }  // namespace
259 }  // namespace net
260